implemented automatic checks for config updates
Stefan Schuermans

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