Stefan Schuermans commited on 2011-10-24 22:41:59
Showing 5 changed files, with 238 additions and 64 deletions.
... | ... |
@@ -12,12 +12,13 @@ |
12 | 12 |
#include "Directory.h" |
13 | 13 |
#include "Module.h" |
14 | 14 |
#include "StreamMgr.h" |
15 |
+#include "TimeCallee.h" |
|
15 | 16 |
|
16 | 17 |
namespace Blinker { |
17 | 18 |
|
18 | 19 |
/// manager for modules of one type |
19 | 20 |
template<typename MODULE> |
20 |
-class ModuleMgr |
|
21 |
+class ModuleMgr: public TimeCallee |
|
21 | 22 |
{ |
22 | 23 |
protected: |
23 | 24 |
/// module list entry |
... | ... |
@@ -52,12 +53,18 @@ private: |
52 | 53 |
const ModuleMgr & operator=(const ModuleMgr &that); |
53 | 54 |
|
54 | 55 |
public: |
56 |
+ /// callback when requsted time reached |
|
57 |
+ virtual void timeCall(); |
|
58 |
+ |
|
59 |
+protected: |
|
55 | 60 |
/// check for update of configuration |
56 | 61 |
void updateConfig(); |
57 | 62 |
|
58 |
-protected: |
|
59 |
- /// update module list |
|
60 |
- void updateModuleList(); |
|
63 |
+ /// light update of module list, i.e. call all modules in current list |
|
64 |
+ void updateModuleListLight(); |
|
65 |
+ |
|
66 |
+ /// full update of module list, i.e. scan all subdirs in base directory |
|
67 |
+ void updateModuleListFull(); |
|
61 | 68 |
|
62 | 69 |
protected: |
63 | 70 |
CallMgr &m_callMgr; ///< callback manager |
... | ... |
@@ -83,7 +90,10 @@ ModuleMgr<MODULE>::ModuleMgr(CallMgr &callMgr, StreamMgr &streamMgr, |
83 | 90 |
m_streamMgr(streamMgr), |
84 | 91 |
m_dirBase(dirBase) |
85 | 92 |
{ |
86 |
- updateModuleList(); |
|
93 |
+ updateModuleListFull(); |
|
94 |
+ |
|
95 |
+ // request call in 1s |
|
96 |
+ m_callMgr.requestTimeCall(this, Time::now() + Time(1)); |
|
87 | 97 |
} |
88 | 98 |
|
89 | 99 |
/// destructor |
... | ... |
@@ -97,18 +107,44 @@ ModuleMgr<MODULE>::~ModuleMgr() |
97 | 107 |
} |
98 | 108 |
} |
99 | 109 |
|
110 |
+/// callback when requsted time reached |
|
111 |
+template<typename MODULE> |
|
112 |
+void ModuleMgr<MODULE>::timeCall() |
|
113 |
+{ |
|
114 |
+ updateConfig(); |
|
115 |
+ |
|
116 |
+ // request next call in 1s |
|
117 |
+ m_callMgr.requestTimeCall(this, Time::now() + Time(1)); |
|
118 |
+} |
|
119 |
+ |
|
100 | 120 |
/// check for update of configuration |
101 | 121 |
template<typename MODULE> |
102 | 122 |
void ModuleMgr<MODULE>::updateConfig() |
103 | 123 |
{ |
104 |
- // base directory was modified -> update module list |
|
124 |
+ // module list update (base directory modified -> full, otherwise -> light) |
|
105 | 125 |
if (m_dirBase.checkModified()) |
106 |
- updateModuleList(); |
|
126 |
+ updateModuleListFull(); |
|
127 |
+ else |
|
128 |
+ updateModuleListLight(); |
|
129 |
+} |
|
130 |
+ |
|
131 |
+/// light update of module list, i.e. call all modules in current list |
|
132 |
+template<typename MODULE> |
|
133 |
+void ModuleMgr<MODULE>::updateModuleListLight() |
|
134 |
+{ |
|
135 |
+ typename ModuleList::iterator itEntry; |
|
136 |
+ for (itEntry = m_moduleList.begin(); itEntry != m_moduleList.end(); |
|
137 |
+ ++itEntry) { |
|
138 |
+ |
|
139 |
+ // call module to check for changes |
|
140 |
+ itEntry->m_pModule->updateConfig(); |
|
141 |
+ |
|
142 |
+ } // for itEntry |
|
107 | 143 |
} |
108 | 144 |
|
109 |
-/// update module list |
|
145 |
+/// full update of module list, i.e. scan all subdirs in base directory |
|
110 | 146 |
template<typename MODULE> |
111 |
-void ModuleMgr<MODULE>::updateModuleList() |
|
147 |
+void ModuleMgr<MODULE>::updateModuleListFull() |
|
112 | 148 |
{ |
113 | 149 |
// get list of subdirectories in base directory |
114 | 150 |
typedef std::list<std::string> Subdirlist; |
... | ... |
@@ -121,7 +157,8 @@ void ModuleMgr<MODULE>::updateModuleList() |
121 | 157 |
while (itSubdir != curSubdirs.end() || itEntry != m_moduleList.end()) { |
122 | 158 |
|
123 | 159 |
// new module inserted |
124 |
- if (itEntry == m_moduleList.end() || *itSubdir < itEntry->m_name) { |
|
160 |
+ if (itEntry == m_moduleList.end() || |
|
161 |
+ (itSubdir != curSubdirs.end() && *itSubdir < itEntry->m_name)) { |
|
125 | 162 |
// create module |
126 | 163 |
Entry entry(*itSubdir); |
127 | 164 |
entry.createModule(*this); |
... | ... |
@@ -33,15 +33,15 @@ Player::Player(CallMgr &callMgr, StreamMgr &streamMgr, |
33 | 33 |
m_fileOutStream(dirBase.getFile("outstream")), |
34 | 34 |
m_dirPlaylist(dirBase.getSubdir("playlist")), |
35 | 35 |
m_pOutStream(NULL), |
36 |
+ m_curValid(false), |
|
36 | 37 |
m_curEntry(m_playlist.begin()), |
37 | 38 |
m_curFrame(0) |
38 | 39 |
{ |
39 | 40 |
// get output stream |
40 |
- m_fileOutStream.getStr(m_nameOutStream); |
|
41 |
- m_pOutStream = &m_streamMgr.refStream(m_nameOutStream); |
|
41 |
+ getOutStream(); |
|
42 | 42 |
|
43 | 43 |
// load playlist |
44 |
- updatePlaylist(); |
|
44 |
+ updatePlaylistFull(); |
|
45 | 45 |
} |
46 | 46 |
|
47 | 47 |
/// virtual destructor |
... | ... |
@@ -53,26 +53,88 @@ Player::~Player() |
53 | 53 |
m_playlist.pop_back(); |
54 | 54 |
} |
55 | 55 |
|
56 |
- // unreference stream |
|
57 |
- m_pOutStream = NULL; |
|
58 |
- m_streamMgr.unrefStream(m_nameOutStream); |
|
56 |
+ // release output stream |
|
57 |
+ releaseOutStream(); |
|
59 | 58 |
} |
60 | 59 |
|
61 | 60 |
/// check for update of configuration |
62 | 61 |
void Player::updateConfig() |
63 | 62 |
{ |
64 |
- // TODO |
|
63 |
+ // output stream name file was modified -> re-get output stream |
|
64 |
+ if (m_fileOutStream.checkModified()) { |
|
65 |
+ releaseOutStream(); |
|
66 |
+ getOutStream(); |
|
67 |
+ } |
|
68 |
+ |
|
69 |
+ // playlist update (directory modified -> full, otherwise -> light) |
|
70 |
+ if (m_dirPlaylist.checkModified()) |
|
71 |
+ updatePlaylistFull(); |
|
72 |
+ else |
|
73 |
+ updatePlaylistLight(); |
|
65 | 74 |
} |
66 | 75 |
|
67 | 76 |
/// callback when requsted time reached |
68 | 77 |
void Player::timeCall() |
69 | 78 |
{ |
70 |
- // show next frame |
|
71 |
- showFrame(); |
|
79 |
+ // leave if time is not yet ready to next frame |
|
80 |
+ if (Time::now() < m_nextTime) { |
|
81 |
+ // request call at time for next frame |
|
82 |
+ m_callMgr.requestTimeCall(this, m_nextTime); |
|
83 |
+ return; |
|
72 | 84 |
} |
73 | 85 |
|
74 |
-/// update playlist |
|
75 |
-void Player::updatePlaylist() |
|
86 |
+ // go to next frame |
|
87 |
+ ++m_curFrame; |
|
88 |
+ |
|
89 |
+ // process new current frame |
|
90 |
+ procFrame(); |
|
91 |
+} |
|
92 |
+ |
|
93 |
+/// light update of playlist, i.e. stat all files in current playlist |
|
94 |
+void Player::updatePlaylistLight() |
|
95 |
+{ |
|
96 |
+ // walk through all files in playlist and check for modification |
|
97 |
+ Playlist::iterator itEntry = m_playlist.begin(); |
|
98 |
+ bool bCurChg = false; |
|
99 |
+ while (itEntry != m_playlist.end()) { |
|
100 |
+ |
|
101 |
+ // movie changed |
|
102 |
+ if (itEntry->m_file.checkModified()) { |
|
103 |
+ // check if changed movie is current movie |
|
104 |
+ if (itEntry == m_curEntry) { |
|
105 |
+ // advance current movie to next movie |
|
106 |
+ ++m_curEntry; |
|
107 |
+ bCurChg = true; |
|
108 |
+ } |
|
109 |
+ // remove entry |
|
110 |
+ itEntry->freeMovie(); |
|
111 |
+ itEntry = m_playlist.erase(itEntry); |
|
112 |
+ // re-load entry |
|
113 |
+ itEntry->freeMovie(); |
|
114 |
+ if (!itEntry->loadMovie()) { |
|
115 |
+ // loading movie failed -> remove entry |
|
116 |
+ itEntry = m_playlist.erase(itEntry); |
|
117 |
+ // do not advance to next file |
|
118 |
+ continue; |
|
119 |
+ } |
|
120 |
+ } |
|
121 |
+ |
|
122 |
+ // advance to next file |
|
123 |
+ ++itEntry; |
|
124 |
+ |
|
125 |
+ } // while itEntry |
|
126 |
+ |
|
127 |
+ // current movie entry changed |
|
128 |
+ if (bCurChg) { |
|
129 |
+ // go to begin of new current movie and start playing now |
|
130 |
+ m_curFrame = 0; |
|
131 |
+ m_nextTime = Time::now(); |
|
132 |
+ procFrame(); |
|
133 |
+ } |
|
134 |
+} |
|
135 |
+ |
|
136 |
+/// full update of playlist, i.e. scan files in playlist directory |
|
137 |
+void Player::updatePlaylistFull() |
|
76 | 138 |
{ |
77 | 139 |
// get list of files in playlist directory |
78 | 140 |
typedef std::list<std::string> Filelist; |
... | ... |
@@ -87,7 +149,8 @@ void Player::updatePlaylist() |
87 | 149 |
while (itFile != curFiles.end() || itEntry != m_playlist.end()) { |
88 | 150 |
|
89 | 151 |
// new movie inserted |
90 |
- if (itEntry == m_playlist.end() || *itFile < itEntry->m_name) { |
|
152 |
+ if (itEntry == m_playlist.end() || |
|
153 |
+ (itFile != curFiles.end() && *itFile < itEntry->m_name)) { |
|
91 | 154 |
// load movie |
92 | 155 |
Entry entry(*itFile, m_dirPlaylist.getFile(*itFile)); |
93 | 156 |
if (entry.loadMovie()) |
... | ... |
@@ -124,24 +187,44 @@ void Player::updatePlaylist() |
124 | 187 |
|
125 | 188 |
// current movie entry changed - or - playlist was empty and is not now |
126 | 189 |
if (bCurChg || (bWasEmpty && !m_playlist.empty())) { |
127 |
- // go to begin of movie and start playing now |
|
190 |
+ // go to begin of new current movie and start playing now |
|
128 | 191 |
m_curFrame = 0; |
129 |
- m_showTime = Time::now(); |
|
130 |
- showFrame(); |
|
192 |
+ m_nextTime = Time::now(); |
|
193 |
+ procFrame(); |
|
131 | 194 |
} |
132 | 195 |
} |
133 | 196 |
|
134 |
-/// show current frame |
|
135 |
-void Player::showFrame() |
|
197 |
+/// get output stream |
|
198 |
+void Player::getOutStream() |
|
136 | 199 |
{ |
137 |
- // leave if time is not yet ready to show frame |
|
138 |
- if (Time::now() < m_showTime) { |
|
139 |
- m_callMgr.requestTimeCall(this, m_showTime); // request call at show time |
|
140 |
- return; |
|
200 |
+ // get name of output stream |
|
201 |
+ m_fileOutStream.getStr(m_nameOutStream); |
|
202 |
+ |
|
203 |
+ // get output stream |
|
204 |
+ m_pOutStream = &m_streamMgr.refStream(m_nameOutStream); |
|
205 |
+ |
|
206 |
+ // send current frame to stream |
|
207 |
+ sendFrame(); |
|
208 |
+} |
|
209 |
+ |
|
210 |
+/// release output stream |
|
211 |
+void Player::releaseOutStream() |
|
212 |
+{ |
|
213 |
+ // send no frame information |
|
214 |
+ if (m_pOutStream) |
|
215 |
+ m_pOutStream->setNoFrame(); |
|
216 |
+ |
|
217 |
+ // unreference output stream |
|
218 |
+ m_pOutStream = NULL; |
|
219 |
+ m_streamMgr.unrefStream(m_nameOutStream); |
|
141 | 220 |
} |
142 | 221 |
|
222 |
+/// process current frame |
|
223 |
+void Player::procFrame() |
|
224 |
+{ |
|
143 | 225 |
// movie finished -> next movie |
144 | 226 |
// use while loops to handle empty movies / empty playlist |
227 |
+ m_curValid = true; |
|
145 | 228 |
bool wrapped = false; |
146 | 229 |
while (true) { |
147 | 230 |
// playlist finished -> re-start from beginning |
... | ... |
@@ -150,13 +233,13 @@ void Player::showFrame() |
150 | 233 |
m_curFrame = 0; |
151 | 234 |
// detect empty playlist or playlist with only empty movies |
152 | 235 |
if (wrapped) { |
153 |
- // empty playlist or playlist with only empty movies -> no frame |
|
154 |
- if (m_pOutStream) |
|
155 |
- m_pOutStream->setNoFrame(); |
|
156 |
- return; |
|
236 |
+ m_curValid = false; |
|
237 |
+ break; |
|
157 | 238 |
} |
158 | 239 |
wrapped = true; |
159 | 240 |
} |
241 |
+ if (!m_curValid) |
|
242 |
+ break; |
|
160 | 243 |
// movie not yet finished -> done |
161 | 244 |
if (m_curFrame < BlinkenMovieGetFrameCnt(m_curEntry->m_pMovie)) |
162 | 245 |
break; |
... | ... |
@@ -165,20 +248,36 @@ void Player::showFrame() |
165 | 248 |
m_curFrame = 0; |
166 | 249 |
} |
167 | 250 |
|
168 |
- // show frame |
|
251 |
+ // send new frame to stream |
|
252 |
+ sendFrame(); |
|
253 |
+ |
|
254 |
+ // if a frame is there |
|
255 |
+ if (m_curValid) { |
|
256 |
+ // calculate time for next frame |
|
169 | 257 |
stBlinkenFrame *pFrame = |
170 | 258 |
BlinkenMovieGetFrame(m_curEntry->m_pMovie, m_curFrame); |
171 |
- if (m_pOutStream) |
|
172 |
- m_pOutStream->setFrame(pFrame); |
|
173 |
- |
|
174 |
- // calculate show time for next frame |
|
175 | 259 |
Time duration; |
176 | 260 |
duration.fromMs(BlinkenFrameGetDuration(pFrame)); |
177 |
- m_showTime += duration; |
|
178 |
- m_callMgr.requestTimeCall(this, m_showTime); // request call at show time |
|
261 |
+ m_nextTime += duration; |
|
262 |
+ // request call at time for next frame |
|
263 |
+ m_callMgr.requestTimeCall(this, m_nextTime); |
|
264 |
+ } |
|
265 |
+} |
|
179 | 266 |
|
180 |
- // go to next frame |
|
181 |
- ++m_curFrame; |
|
267 |
+/// send current frame to output stream |
|
268 |
+void Player::sendFrame() |
|
269 |
+{ |
|
270 |
+ if (m_pOutStream) { |
|
271 |
+ // frame avalable -> send it |
|
272 |
+ if (m_curValid) { |
|
273 |
+ stBlinkenFrame *pFrame = |
|
274 |
+ BlinkenMovieGetFrame(m_curEntry->m_pMovie, m_curFrame); |
|
275 |
+ m_pOutStream->setFrame(pFrame); |
|
276 |
+ } |
|
277 |
+ // no frame available -> send this information |
|
278 |
+ else |
|
279 |
+ m_pOutStream->setNoFrame(); |
|
280 |
+ } |
|
182 | 281 |
} |
183 | 282 |
|
184 | 283 |
/* ################# |
... | ... |
@@ -66,11 +66,23 @@ public: |
66 | 66 |
virtual void timeCall(); |
67 | 67 |
|
68 | 68 |
protected: |
69 |
- /// update playlist |
|
70 |
- void updatePlaylist(); |
|
69 |
+ /// light update of playlist, i.e. stat all files in current playlist |
|
70 |
+ void updatePlaylistLight(); |
|
71 | 71 |
|
72 |
- /// show current frame |
|
73 |
- void showFrame(); |
|
72 |
+ /// full update of playlist, i.e. scan files in playlist directory |
|
73 |
+ void updatePlaylistFull(); |
|
74 |
+ |
|
75 |
+ /// get output stream |
|
76 |
+ void getOutStream(); |
|
77 |
+ |
|
78 |
+ /// release output stream |
|
79 |
+ void releaseOutStream(); |
|
80 |
+ |
|
81 |
+ /// process current frame |
|
82 |
+ void procFrame(); |
|
83 |
+ |
|
84 |
+ /// send current frame to output stream |
|
85 |
+ void sendFrame(); |
|
74 | 86 |
|
75 | 87 |
protected: |
76 | 88 |
SettingFile m_fileOutStream; ///< output stream name file |
... | ... |
@@ -78,9 +90,10 @@ protected: |
78 | 90 |
std::string m_nameOutStream; ///< name of output stream |
79 | 91 |
Stream *m_pOutStream; ///< output stream |
80 | 92 |
Playlist m_playlist; ///< current playlist |
93 |
+ bool m_curValid; ///< if there is a current frame |
|
81 | 94 |
Playlist::const_iterator m_curEntry; ///< current playlist entry |
82 | 95 |
int m_curFrame; ///< current frame in movie |
83 |
- Time m_showTime; ///< when to show frame |
|
96 |
+ Time m_nextTime; ///< when to show next frame |
|
84 | 97 |
}; // class Player |
85 | 98 |
|
86 | 99 |
} // namespace Blinker |
... | ... |
@@ -32,31 +32,25 @@ Printer::Printer(CallMgr &callMgr, StreamMgr &streamMgr, |
32 | 32 |
m_fileInStream(dirBase.getFile("instream")), |
33 | 33 |
m_pInStream(NULL) |
34 | 34 |
{ |
35 |
- // get input stream |
|
36 |
- m_fileInStream.getStr(m_nameInStream); |
|
37 |
- m_pInStream = &m_streamMgr.refStream(m_nameInStream); |
|
38 |
- |
|
39 |
- // attach to input stream |
|
40 |
- if (m_pInStream) |
|
41 |
- m_pInStream->attach(this); |
|
35 |
+ // get input stream and attach to it |
|
36 |
+ getInStream(); |
|
42 | 37 |
} |
43 | 38 |
|
44 | 39 |
/// virtual destructor |
45 | 40 |
Printer::~Printer() |
46 | 41 |
{ |
47 |
- // detach from input stream |
|
48 |
- if (m_pInStream) |
|
49 |
- m_pInStream->detach(this); |
|
50 |
- |
|
51 |
- // unreference stream |
|
52 |
- m_pInStream = NULL; |
|
53 |
- m_streamMgr.unrefStream(m_nameInStream); |
|
42 |
+ // detach from input stream and release it |
|
43 |
+ releaseInStream(); |
|
54 | 44 |
} |
55 | 45 |
|
56 | 46 |
/// check for update of configuration |
57 | 47 |
void Printer::updateConfig() |
58 | 48 |
{ |
59 |
- // TODO |
|
49 |
+ // input stream name file was modified -> re-get input stream |
|
50 |
+ if (m_fileInStream.checkModified()) { |
|
51 |
+ releaseInStream(); |
|
52 |
+ getInStream(); |
|
53 |
+ } |
|
60 | 54 |
} |
61 | 55 |
|
62 | 56 |
/** |
... | ... |
@@ -76,5 +70,29 @@ void Printer::setNoFrame() |
76 | 70 |
std::cout << "no frame" << std::endl; |
77 | 71 |
} |
78 | 72 |
|
73 |
+/// get input stream and attach to it |
|
74 |
+void Printer::getInStream() |
|
75 |
+{ |
|
76 |
+ // get input stream |
|
77 |
+ m_fileInStream.getStr(m_nameInStream); |
|
78 |
+ m_pInStream = &m_streamMgr.refStream(m_nameInStream); |
|
79 |
+ |
|
80 |
+ // attach to input stream |
|
81 |
+ if (m_pInStream) |
|
82 |
+ m_pInStream->attach(this); |
|
83 |
+} |
|
84 |
+ |
|
85 |
+/// detach from input stream and release it |
|
86 |
+void Printer::releaseInStream() |
|
87 |
+{ |
|
88 |
+ // detach from input stream |
|
89 |
+ if (m_pInStream) |
|
90 |
+ m_pInStream->detach(this); |
|
91 |
+ |
|
92 |
+ // unreference stream |
|
93 |
+ m_pInStream = NULL; |
|
94 |
+ m_streamMgr.unrefStream(m_nameInStream); |
|
95 |
+} |
|
96 |
+ |
|
79 | 97 |
} // namespace Blinker |
80 | 98 |
|
... | ... |
@@ -55,6 +55,13 @@ public: |
55 | 55 |
/// set current frame to none |
56 | 56 |
virtual void setNoFrame(); |
57 | 57 |
|
58 |
+protected: |
|
59 |
+ /// get input stream and attach to it |
|
60 |
+ void getInStream(); |
|
61 |
+ |
|
62 |
+ /// detach from input stream and release it |
|
63 |
+ void releaseInStream(); |
|
64 |
+ |
|
58 | 65 |
protected: |
59 | 66 |
SettingFile m_fileInStream; ///< input stream name file |
60 | 67 |
std::string m_nameInStream; ///< name of input stream |
61 | 68 |