616b8e2a049b7e7823602ee6710fac75edc2df58
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

1) /* Blinker
2)    Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org>
3)    Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4)    a blinkenarea.org project */
5) 
6) #include <list>
7) #include <string>
8) 
9) #include <BlinkenLib/BlinkenFrame.h>
10) #include <BlinkenLib/BlinkenMovie.h>
11) 
12) #include "Directory.h"
13) #include "File.h"
14) #include "InStreamFile.h"
15) #include "ListTracker.h"
16) #include "ListTracker_impl.h"
17) #include "Loveletter.h"
18) #include "LoveletterMovie.h"
19) #include "Mgrs.h"
20) #include "Module.h"
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

21) #include "NameFile.h"
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

22) #include "OutStreamFile.h"
23) #include "StreamRecv.h"
24) #include "Time.h"
25) #include "TimeCallee.h"
26) 
27) namespace Blinker {
28) 
29) /**
30)  * @brief constructor
31)  * @param[in] name module name
32)  * @param[in] mgrs managers
33)  * @param[in] dirBase base directory
34)  */
35) Loveletter::Loveletter(const std::string &name, Mgrs &mgrs,
36)                const Directory &dirBase):
37)   Module(name, mgrs, dirBase),
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

38)   m_fileSound(dirBase.getFile("sound")),
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

39)   m_fileOutStream(dirBase.getFile("outstream"), mgrs.m_streamMgr),
40)   m_fileHaltStream(dirBase.getFile("haltstream"), mgrs.m_streamMgr),
41)   m_movieTracker(*this, dirBase.getSubdir("movies")),
42)   m_curValid(false),
43)   m_pCurMovie(NULL),
44)   m_curFrame(0),
45)   m_curChange(false),
46)   m_halted(false),
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

47)   m_pOpConn(NULL),
48)   m_sendPlay(false)
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

49) {
50)   // load movies
51)   m_fileHaltStream.setStreamRecv(this);
52)   m_movieTracker.init();
53)   checkCurChanged();
54) 
55)   // open operator connection interface
56)   m_mgrs.m_opMgr.open(m_name, this);
57) }
58) 
59) /// virtual destructor
60) Loveletter::~Loveletter()
61) {
62)   // close operator connection interface
63)   m_mgrs.m_opMgr.close(m_name);
64)   closeOpConn();
65) 
66)   // cancel time callback request
67)   m_mgrs.m_callMgr.cancelTimeCall(this);
68) 
69)   // free all movies
70)   m_movieTracker.clear();
71)   m_fileHaltStream.setStreamRecv(NULL);
72) }
73) 
74) /// check for update of configuration
75) void Loveletter::updateConfig()
76) {
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

77)   // sound name file was modified -> re-read sound name
78)   if (m_fileSound.checkModified())
79)     m_fileSound.update();
80) 
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

81)   // output stream name file was modified -> re-get output stream
82)   if (m_fileOutStream.checkModified()) {
83)     m_fileOutStream.update();
84)     sendFrame();
85)   }
86) 
87)   // halt stream name file was modified -> re-get halt stream
88)   if (m_fileHaltStream.checkModified())
89)     m_fileHaltStream.update();
90) 
91)   // movie update
92)   m_movieTracker.updateConfig();
93)   checkCurChanged();
94) }
95) 
96) /**
97)  * @brief set current frame
98)  * @param[in] stream stream name
99)  * @param[in] pFrame current frame (NULL for none)
100)  */
101) void Loveletter::setFrame(const std::string &stream, stBlinkenFrame *pFrame)
102) {
103)   // this is coming from the halt stream, which will halt playing
104)   // whenever a frame is available on this halt stream
105) 
106)   // halt stream came to life -> halt playing
107)   if (pFrame && !m_halted) {
108)     m_halted = true;
109)     if (m_curValid) {
110)       // store remaining frame time
111)       m_remainTime = m_nextTime - Time::now();
112)       if (m_remainTime < Time::zero)
113)         m_remainTime = Time::zero;
114)     }
115)     // cancel time call
116)     m_mgrs.m_callMgr.cancelTimeCall(this);
117)   }
118) 
119)   // halt stream ended -> continue playing
120)   else if (!pFrame && m_halted) {
121)     m_halted = false;
122)     if (m_curValid) {
123)       // determine time for next frame
124)       m_nextTime = Time::now() + m_remainTime;
125)       // schedule time call
126)       m_mgrs.m_callMgr.requestTimeCall(this, m_nextTime);
127)     }
128)   }
129) 
130)   (void)stream; // unused
131) }
132) 
133) /// callback when requested time reached
134) void Loveletter::timeCall()
135) {
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

136)   // send sound play request on operator connection
137)   if (m_sendPlay) {
138)     m_sendPlay = false;
139)     if (m_pOpConn && m_fileSound.m_valid)
140)       m_pOpConn->sendPlay(m_fileSound.m_obj.m_str);
141)   }
142) 
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

143)   // leave if halted
144)   if (m_halted)
145)     return;
146) 
147)   // leave if time is not yet ready to next frame
148)   if (Time::now() < m_nextTime) {
149)     // request call at time for next frame
150)     m_mgrs.m_callMgr.requestTimeCall(this, m_nextTime);
151)     return;
152)   }
153) 
154)   // go to next frame
155)   ++m_curFrame;
156) 
157)   // process new current frame
158)   procFrame();
159) }
160) 
161) /**
162)  * @brief check if accepting new operator connction is possible
163)  * @param[in] name operator interface name
164)  * @return if accepting new connection is possible
165)  */
166) bool Loveletter::acceptNewOpConn(const std::string &name)
167) {
168)   // accept new connection if none active
169)   return !m_pOpConn;
170)   (void)name; // unused
171) }
172) 
173) /**
174)  * @brief new operator connection
175)  * @param[in] name operator interface name
176)  * @param[in] pConn operator connection object
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

177)  *
178)  * The new connection may not yet be used for sending inside this callback.
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

179)  */
180) void Loveletter::newOpConn(const std::string &name, OpConn *pConn)
181) {
182)   closeOpConn(); // close old connection (to be on the safe side)
183)   m_pOpConn = pConn; // remember new connection
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

184)   m_sendPlay = true; // schedule sending play request
185)   m_mgrs.m_callMgr.requestTimeCall(this, Time::now());
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

186)   (void)name; // unused
187) }
188) 
189) /**
190)  * @brief key command received on operator connection
191)  * @param[in] pConn operator connection object
192)  * @param[in] key key that was pressed
193)  */
194) void Loveletter::opConnRecvKey(OpConn *pConn, char key)
195) {
196)   switch (key) {
197)     // begin new movie number
198)     case '*':
199)       m_movieNumber.clear();
200)       break;
Stefan Schuermans begin with new number after...

Stefan Schuermans authored 12 years ago

201)     // add digit to movie number
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

202)     case '0':
203)     case '1':
204)     case '2':
205)     case '3':
206)     case '4':
207)     case '5':
208)     case '6':
209)     case '7':
210)     case '8':
211)     case '9':
212)       m_movieNumber += key;
213)       break;
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

214)     // exit / play movie
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

215)     case '#':
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

216)       if (m_movieNumber.empty())
217)         closeOpConn();
218)       else
219)         startPlaying();
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

220)       break;
221)   }
222)   (void)pConn; // unused
223) }
224) 
225) /**
226)  * @brief play command received on operator connection
227)  * @param[in] pConn operator connection object
228)  * @param[in] sound name of sound to play
229)  */
230) void Loveletter::opConnRecvPlay(OpConn *pConn, const std::string &sound)
231) {
232)   // this events does not make sense in this direction, ignore it
233)   (void)pConn; // unused
234)   (void)sound; // unused
235) }
236) 
237) /**
238)  * @brief operator connection is closed
239)  * @param[in] pConn operator connection object
Stefan Schuermans clarified operator connecti...

Stefan Schuermans authored 12 years ago

240)  *
241)  * The connection may not be used for sending any more in this callback.
Stefan Schuermans implemented loveletter module

Stefan Schuermans authored 12 years ago

242)  */
243) void Loveletter::opConnClose(OpConn *pConn)
244) {
245)   m_pOpConn = NULL;
246)   stopPlaying();
247)   (void)pConn; // unused
248) }
249) 
250) /// check if current movie changed and react
251) void Loveletter::checkCurChanged()
252) {
253)   // current movie changed
254)   if (m_curChange) {
255)     m_curChange = false;
256) 
257)     // go to begin of new current movie and start playing now
258)     m_curFrame = 0;
259)     m_remainTime = Time::zero;
260)     m_nextTime = Time::now();
261)     procFrame();
262) 
263)   } // if (m_curChange)
264) }
265) 
266) /// process current frame
267) void Loveletter::procFrame()
268) {
269)   // a movie is selected and this is loaded
270)   if (m_pCurMovie && m_pCurMovie->m_pMovie) {
271)     int frameCnt = BlinkenMovieGetFrameCnt(m_pCurMovie->m_pMovie);
272)     // movie not empty
273)     if (frameCnt > 0) {
274)       // movie finsihed -> restart
275)       if (m_curFrame >= frameCnt)
276)         m_curFrame = 0;
277)       // valid
278)       m_curValid = true;
279)     }
280)     // movie empty -> not valid
281)     else
282)       m_curValid = false;
283)   }
284)   // no movie selected or selected one not loaded -> not valid
285)   else
286)     m_curValid = false;
287) 
288)   // send new frame to stream
289)   sendFrame();
290) 
291)   // if a frame is there
292)   if (m_curValid) {
293)     // get frame time and calculate absolute time for next frame
294)     stBlinkenFrame *pFrame =
295)       BlinkenMovieGetFrame(m_pCurMovie->m_pMovie, m_curFrame);
296)     m_remainTime.fromMs(BlinkenFrameGetDuration(pFrame));
297)     m_nextTime += m_remainTime;
298)     // request call at time for next frame
299)     if (!m_halted)
300)       m_mgrs.m_callMgr.requestTimeCall(this, m_nextTime);
301)   }
302) }
303) 
304) /// send current frame to output stream
305) void Loveletter::sendFrame()
306) {
307)   // frame available -> send it
308)   if (m_curValid) {
309)     stBlinkenFrame *pFrame =
310)       BlinkenMovieGetFrame(m_pCurMovie->m_pMovie, m_curFrame);
311)     m_fileOutStream.setFrame(pFrame);
312)   }
313)   // no frame available -> send this information
314)   else
315)     m_fileOutStream.setFrame(NULL);
316) }
317) 
318) /// close current operator connection
319) void Loveletter::closeOpConn()
320) {
321)   if (m_pOpConn) {
322)     m_pOpConn->close();
323)     m_pOpConn = NULL;
324)   }
325) 
326)   stopPlaying();
327) };
328) 
329) /// start playing movie (indictaed by m_movieNumber)
330) void Loveletter::startPlaying()
331) {
332)   // find movie and make it current
333)   MovieMap::const_iterator itMovie = m_movieMap.find(m_movieNumber);
334)   if (itMovie == m_movieMap.end())
335)     m_pCurMovie = NULL; // not found -> no movie
336)   else
337)     m_pCurMovie = itMovie->second;
338) 
339)   // start playing movie
340)   m_curChange = true;
341)   checkCurChanged();
Stefan Schuermans begin with new number after...

Stefan Schuermans authored 12 years ago

342) 
343)   // begin new movie number
344)   m_movieNumber.clear();