Stefan Schuermans commited on 2011-12-10 22:52:36
Showing 5 changed files, with 284 additions and 110 deletions.
... | ... |
@@ -0,0 +1,84 @@ |
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 |
+#ifndef LISTTRACKER_H |
|
7 |
+#define LISTTRACKER_H |
|
8 |
+ |
|
9 |
+#include <list> |
|
10 |
+#include <string> |
|
11 |
+ |
|
12 |
+#include "Directory.h" |
|
13 |
+#include "File.h" |
|
14 |
+ |
|
15 |
+namespace Blinker { |
|
16 |
+ |
|
17 |
+/** |
|
18 |
+ * @brief tracker of a list kept in a directory |
|
19 |
+ * @param[in] PARENT type of parent object |
|
20 |
+ * @param[in] TYPE type of objects to allocate for list entries |
|
21 |
+ * @param[in] FIDI if to track files or subdirs in directory |
|
22 |
+ (File or Directory) |
|
23 |
+ */ |
|
24 |
+template<typename PARENT, typename TYPE, typename FIDI> |
|
25 |
+class ListTracker |
|
26 |
+{ |
|
27 |
+public: |
|
28 |
+ /// list entry |
|
29 |
+ struct Entry { |
|
30 |
+ std::string m_name; ///< name of list entry |
|
31 |
+ TYPE *m_pObj; ///< object |
|
32 |
+ }; |
|
33 |
+ |
|
34 |
+ /// list |
|
35 |
+ typedef std::list<Entry> List; |
|
36 |
+ |
|
37 |
+ /// list iterator |
|
38 |
+ typedef typename List::const_reverse_iterator ListIt; |
|
39 |
+ |
|
40 |
+public: |
|
41 |
+ /** |
|
42 |
+ * @brief constructor |
|
43 |
+ * @param[in] parent parent object |
|
44 |
+ * @param[in] dir directory containing list and begin tracked |
|
45 |
+ */ |
|
46 |
+ ListTracker(PARENT &parent, const Directory &dir); |
|
47 |
+ |
|
48 |
+ /// destructor |
|
49 |
+ virtual ~ListTracker(); |
|
50 |
+ |
|
51 |
+private: |
|
52 |
+ /// copy constructor disabled |
|
53 |
+ ListTracker(const ListTracker &that); |
|
54 |
+ |
|
55 |
+ /// assignment operator disabled |
|
56 |
+ const ListTracker & operator=(const ListTracker &that); |
|
57 |
+ |
|
58 |
+public: |
|
59 |
+ /// initialize list by reading directory |
|
60 |
+ void init(); |
|
61 |
+ |
|
62 |
+ /// clear list |
|
63 |
+ void clear(); |
|
64 |
+ |
|
65 |
+ /// check for update of configuration |
|
66 |
+ void updateConfig(); |
|
67 |
+ |
|
68 |
+protected: |
|
69 |
+ /// light update of list, i.e. check all entries in current list |
|
70 |
+ void updateListLight(); |
|
71 |
+ |
|
72 |
+ /// full update of list, i.e. scan files/subdirs in list directory |
|
73 |
+ void updateListFull(); |
|
74 |
+ |
|
75 |
+public: |
|
76 |
+ PARENT &m_parent; ///< parent object |
|
77 |
+ Directory m_dir; ///< directory containing list and being tracked |
|
78 |
+ List m_list; ///< list begin tracked |
|
79 |
+}; // class ListTracker |
|
80 |
+ |
|
81 |
+} // namespace Blinker |
|
82 |
+ |
|
83 |
+#endif // #ifndef LISTTRACKER_H |
|
84 |
+ |
... | ... |
@@ -0,0 +1,177 @@ |
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 |
+#ifndef LISTTRACKER_IMPL_H |
|
7 |
+#define LISTTRACKER_IMPL_H |
|
8 |
+ |
|
9 |
+#include <list> |
|
10 |
+#include <string> |
|
11 |
+ |
|
12 |
+#include "Directory.h" |
|
13 |
+#include "File.h" |
|
14 |
+#include "ListTracker.h" |
|
15 |
+ |
|
16 |
+namespace Blinker { |
|
17 |
+ |
|
18 |
+/* ################### |
|
19 |
+ # ListTrackerFiDi # |
|
20 |
+ ################### */ |
|
21 |
+ |
|
22 |
+ |
|
23 |
+/// internal helper class to achive different behavior for FIDI parameter |
|
24 |
+template <typename FIDI> |
|
25 |
+class ListTrackerFiDi |
|
26 |
+{ |
|
27 |
+public: |
|
28 |
+ static inline Directory::Type type(); |
|
29 |
+ static inline FIDI get(const Directory &dir, const std::string name); |
|
30 |
+}; |
|
31 |
+ |
|
32 |
+template<> |
|
33 |
+inline Directory::Type ListTrackerFiDi<File>::type() |
|
34 |
+{ |
|
35 |
+ return Directory::TypeFile; |
|
36 |
+} |
|
37 |
+ |
|
38 |
+template<> |
|
39 |
+inline File ListTrackerFiDi<File>:: |
|
40 |
+ get(const Directory &dir, const std::string name) |
|
41 |
+{ |
|
42 |
+ return dir.getFile(name); |
|
43 |
+} |
|
44 |
+ |
|
45 |
+template<> |
|
46 |
+inline Directory::Type ListTrackerFiDi<Directory>::type() |
|
47 |
+{ |
|
48 |
+ return Directory::TypeSubdir; |
|
49 |
+} |
|
50 |
+ |
|
51 |
+template<> |
|
52 |
+inline Directory ListTrackerFiDi<Directory>:: |
|
53 |
+ get(const Directory &dir, const std::string name) |
|
54 |
+{ |
|
55 |
+ return dir.getSubdir(name); |
|
56 |
+} |
|
57 |
+ |
|
58 |
+/* ############### |
|
59 |
+ # ListTracker # |
|
60 |
+ ############### */ |
|
61 |
+ |
|
62 |
+/** |
|
63 |
+ * @brief constructor |
|
64 |
+ * @param[in] dir directory containing list and begin tracked |
|
65 |
+ * @param[in] parent parent object |
|
66 |
+ */ |
|
67 |
+template<typename PARENT, typename TYPE, typename FIDI> |
|
68 |
+ListTracker<PARENT, TYPE, FIDI>::ListTracker(PARENT &parent, |
|
69 |
+ const Directory &dir): |
|
70 |
+ m_parent(parent), |
|
71 |
+ m_dir(dir) |
|
72 |
+{ |
|
73 |
+} |
|
74 |
+ |
|
75 |
+/// destructor |
|
76 |
+template<typename PARENT, typename TYPE, typename FIDI> |
|
77 |
+ListTracker<PARENT, TYPE, FIDI>::~ListTracker() |
|
78 |
+{ |
|
79 |
+ /* free leftover list entries: |
|
80 |
+ Depending on the interaction bet ween the list entry object and |
|
81 |
+ the parent, it might be too late to free them, as the parent might |
|
82 |
+ already be partly deconstructed and thus might be in an inconsistent |
|
83 |
+ state. It's recommended to call clear manually before, so that the |
|
84 |
+ following call becomes a no-operation. */ |
|
85 |
+ clear(); |
|
86 |
+} |
|
87 |
+ |
|
88 |
+/// initialize list by reading directory |
|
89 |
+template<typename PARENT, typename TYPE, typename FIDI> |
|
90 |
+void ListTracker<PARENT, TYPE, FIDI>::init() |
|
91 |
+{ |
|
92 |
+ updateListFull(); |
|
93 |
+} |
|
94 |
+ |
|
95 |
+/// clear list |
|
96 |
+template<typename PARENT, typename TYPE, typename FIDI> |
|
97 |
+void ListTracker<PARENT, TYPE, FIDI>::clear() |
|
98 |
+{ |
|
99 |
+ while (!m_list.empty()) { |
|
100 |
+ delete m_list.back().m_pObj; |
|
101 |
+ m_list.pop_back(); |
|
102 |
+ } |
|
103 |
+} |
|
104 |
+ |
|
105 |
+/// check for update of configuration |
|
106 |
+template<typename PARENT, typename TYPE, typename FIDI> |
|
107 |
+void ListTracker<PARENT, TYPE, FIDI>::updateConfig() |
|
108 |
+{ |
|
109 |
+ // directory modified -> full, otherwise -> light |
|
110 |
+ if (m_dir.checkModified()) |
|
111 |
+ updateListFull(); |
|
112 |
+ else |
|
113 |
+ updateListLight(); |
|
114 |
+} |
|
115 |
+ |
|
116 |
+/// light update of list, i.e. check all entries in current list |
|
117 |
+template<typename PARENT, typename TYPE, typename FIDI> |
|
118 |
+void ListTracker<PARENT, TYPE, FIDI>::updateListLight() |
|
119 |
+{ |
|
120 |
+ typename List::iterator it; |
|
121 |
+ for (it = m_list.begin(); it != m_list.end(); ++it) |
|
122 |
+ it->m_pObj->updateConfig(); |
|
123 |
+} |
|
124 |
+ |
|
125 |
+/// full update of list, i.e. scan files/subdirs in list directory |
|
126 |
+template<typename PARENT, typename TYPE, typename FIDI> |
|
127 |
+void ListTracker<PARENT, TYPE, FIDI>::updateListFull() |
|
128 |
+{ |
|
129 |
+ // get list of files/subdirs in directory |
|
130 |
+ typedef std::list<std::string> FileList; |
|
131 |
+ FileList curFiles; |
|
132 |
+ m_dir.getEntries(ListTrackerFiDi<FIDI>::type(), curFiles); |
|
133 |
+ |
|
134 |
+ // walk through current list and file/subdir list simultaneously |
|
135 |
+ FileList::const_iterator itFile = curFiles.begin(); |
|
136 |
+ typename List::iterator it = m_list.begin(); |
|
137 |
+ while (itFile != curFiles.end() || it != m_list.end()) { |
|
138 |
+ |
|
139 |
+ // new entry inserted |
|
140 |
+ if (it == m_list.end() || |
|
141 |
+ (itFile != curFiles.end() && *itFile < it->m_name)) { |
|
142 |
+ // create object |
|
143 |
+ Entry entry; |
|
144 |
+ entry.m_name = *itFile; |
|
145 |
+ entry.m_pObj = new TYPE(m_parent, *itFile, |
|
146 |
+ ListTrackerFiDi<FIDI>::get(m_dir, *itFile)); |
|
147 |
+ if (entry.m_pObj) |
|
148 |
+ // insert list entry |
|
149 |
+ m_list.insert(it, entry); |
|
150 |
+ // advance to next file/subdir |
|
151 |
+ ++itFile; |
|
152 |
+ } |
|
153 |
+ |
|
154 |
+ // entry removed |
|
155 |
+ else if (itFile == curFiles.end() || *itFile > it->m_name) { |
|
156 |
+ // remove entry |
|
157 |
+ delete it->m_pObj; |
|
158 |
+ it = m_list.erase(it); |
|
159 |
+ // do not advance to next file/subdir |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ // entry stayed in list |
|
163 |
+ else { |
|
164 |
+ // check for update |
|
165 |
+ it->m_pObj->updateConfig(); |
|
166 |
+ // advance to next file/subdir and next entry |
|
167 |
+ ++itFile; |
|
168 |
+ ++it; |
|
169 |
+ } |
|
170 |
+ |
|
171 |
+ } // while itFile it |
|
172 |
+} |
|
173 |
+ |
|
174 |
+} // namespace Blinker |
|
175 |
+ |
|
176 |
+#endif // #ifndef LISTTRACKER_IMPL_H |
|
177 |
+ |
... | ... |
@@ -11,6 +11,8 @@ |
11 | 11 |
#include "CallMgr.h" |
12 | 12 |
#include "Directory.h" |
13 | 13 |
#include "File.h" |
14 |
+#include "ListTracker.h" |
|
15 |
+#include "ListTracker_impl.h" |
|
14 | 16 |
#include "Module.h" |
15 | 17 |
#include "Priority.h" |
16 | 18 |
#include "PriorityInput.h" |
... | ... |
@@ -29,94 +31,28 @@ namespace Blinker { |
29 | 31 |
Priority::Priority(CallMgr &callMgr, StreamMgr &streamMgr, |
30 | 32 |
const Directory &dirBase): |
31 | 33 |
Module(callMgr, streamMgr, dirBase), |
32 |
- m_dirInputs(dirBase.getSubdir("inputs")), |
|
33 | 34 |
m_fileOutStream(dirBase.getFile("outstream"), streamMgr), |
34 |
- m_itCurIn(m_inList.rend()) |
|
35 |
+ m_inListTracker(*this, dirBase.getSubdir("inputs")), |
|
36 |
+ m_itCurIn(m_inListTracker.m_list.rend()) |
|
35 | 37 |
{ |
36 |
- // set up |
|
37 |
- updateInListFull(); |
|
38 | 38 |
} |
39 | 39 |
|
40 | 40 |
/// virtual destructor |
41 | 41 |
Priority::~Priority() |
42 | 42 |
{ |
43 |
- // clean up |
|
44 |
- while (!m_inList.empty()) { |
|
45 |
- delete m_inList.back().m_pInput; |
|
46 |
- m_inList.pop_back(); |
|
47 |
- } |
|
48 | 43 |
} |
49 | 44 |
|
50 | 45 |
/// check for update of configuration |
51 | 46 |
void Priority::updateConfig() |
52 | 47 |
{ |
53 |
- // input list update (directory modified -> full, otherwise -> light) |
|
54 |
- if (m_dirInputs.checkModified()) |
|
55 |
- updateInListFull(); |
|
56 |
- else |
|
57 |
- updateInListLight(); |
|
48 |
+ // input list update |
|
49 |
+ m_inListTracker.updateConfig(); |
|
58 | 50 |
|
59 | 51 |
// output stream name file was modified -> re-get output stream |
60 | 52 |
if (m_fileOutStream.checkModified()) |
61 | 53 |
m_fileOutStream.update(); |
62 | 54 |
} |
63 | 55 |
|
64 |
-/// light update of input list, i.e. check all entries in current input list |
|
65 |
-void Priority::updateInListLight() |
|
66 |
-{ |
|
67 |
- // walk through all inputs in input list and check for modification |
|
68 |
- InList::iterator itIn; |
|
69 |
- for (itIn = m_inList.begin(); itIn != m_inList.end(); ++itIn) |
|
70 |
- itIn->m_pInput->updateConfig(); |
|
71 |
-} |
|
72 |
- |
|
73 |
-/// full update of input list, i.e. scan subdirs in input list directory |
|
74 |
-void Priority::updateInListFull() |
|
75 |
-{ |
|
76 |
- // get list of subdirs in input directory |
|
77 |
- typedef std::list<std::string> Subdirlist; |
|
78 |
- Subdirlist curSubdirs; |
|
79 |
- m_dirInputs.getEntries(Directory::TypeSubdir, curSubdirs); |
|
80 |
- |
|
81 |
- // walk through current input list and subdir list simultaneously |
|
82 |
- Subdirlist::const_iterator itSubdir = curSubdirs.begin(); |
|
83 |
- InList::iterator itIn = m_inList.begin(); |
|
84 |
- while (itSubdir != curSubdirs.end() || itIn != m_inList.end()) { |
|
85 |
- |
|
86 |
- // new input inserted |
|
87 |
- if (itIn == m_inList.end() || |
|
88 |
- (itSubdir != curSubdirs.end() && *itSubdir < itIn->m_name)) { |
|
89 |
- // create input object |
|
90 |
- InEntry inEntry(*itSubdir); |
|
91 |
- inEntry.m_pInput = new Input(*this, *itSubdir, |
|
92 |
- m_dirInputs.getSubdir(*itSubdir)); |
|
93 |
- if (inEntry.m_pInput) |
|
94 |
- // insert input list entry |
|
95 |
- m_inList.insert(itIn, inEntry); |
|
96 |
- // advance to next subdir |
|
97 |
- ++itSubdir; |
|
98 |
- } |
|
99 |
- |
|
100 |
- // input removed |
|
101 |
- else if (itSubdir == curSubdirs.end() || *itSubdir > itIn->m_name) { |
|
102 |
- // remove input |
|
103 |
- delete itIn->m_pInput; |
|
104 |
- itIn = m_inList.erase(itIn); |
|
105 |
- // do not advance to next subdir |
|
106 |
- } |
|
107 |
- |
|
108 |
- // input stayed in input list |
|
109 |
- else { |
|
110 |
- // check for update |
|
111 |
- itIn->m_pInput->updateConfig(); |
|
112 |
- // advance to next file and next entry |
|
113 |
- ++itSubdir; |
|
114 |
- ++itIn; |
|
115 |
- } |
|
116 |
- |
|
117 |
- } // while itSubdir itIn |
|
118 |
-} |
|
119 |
- |
|
120 | 56 |
/** |
121 | 57 |
* @brief select specific input (called by inputs) |
122 | 58 |
* @param[in] input input to select |
... | ... |
@@ -124,8 +60,9 @@ void Priority::updateInListFull() |
124 | 60 |
void Priority::select(const Input *pInput) |
125 | 61 |
{ |
126 | 62 |
// search inputs for passed input |
127 |
- m_itCurIn = m_inList.rbegin(); |
|
128 |
- while (m_itCurIn != m_inList.rend() && m_itCurIn->m_pInput != pInput) |
|
63 |
+ m_itCurIn = m_inListTracker.m_list.rbegin(); |
|
64 |
+ while (m_itCurIn != m_inListTracker.m_list.rend() && |
|
65 |
+ m_itCurIn->m_pObj != pInput) |
|
129 | 66 |
++m_itCurIn; |
130 | 67 |
|
131 | 68 |
// send current frame |
... | ... |
@@ -138,9 +75,9 @@ void Priority::selectLower() |
138 | 75 |
stBlinkenFrame *pFrame; |
139 | 76 |
|
140 | 77 |
// search inputs with lower priority until a frame is found |
141 |
- while (m_itCurIn != m_inList.rend()) { |
|
78 |
+ while (m_itCurIn != m_inListTracker.m_list.rend()) { |
|
142 | 79 |
// check for frame |
143 |
- if ((pFrame = m_itCurIn->m_pInput->getCurFrame())) { |
|
80 |
+ if ((pFrame = m_itCurIn->m_pObj->getCurFrame())) { |
|
144 | 81 |
// frame found -> keep this input as current, send frame |
145 | 82 |
m_fileOutStream.setFrame(pFrame); |
146 | 83 |
return; |
... | ... |
@@ -159,24 +96,13 @@ void Priority::curFrame() |
159 | 96 |
stBlinkenFrame *pFrame; |
160 | 97 |
|
161 | 98 |
// current input available and frame it it available -> send frame |
162 |
- if (m_itCurIn != m_inList.rend() && |
|
163 |
- (pFrame = m_itCurIn->m_pInput->getCurFrame())) |
|
99 |
+ if (m_itCurIn != m_inListTracker.m_list.rend() && |
|
100 |
+ (pFrame = m_itCurIn->m_pObj->getCurFrame())) |
|
164 | 101 |
m_fileOutStream.setFrame(pFrame); |
165 | 102 |
// no frame available -> send this information |
166 | 103 |
else |
167 | 104 |
m_fileOutStream.setFrame(NULL); |
168 | 105 |
} |
169 | 106 |
|
170 |
-/* ##################### |
|
171 |
- # Priority::InEntry # |
|
172 |
- ##################### */ |
|
173 |
- |
|
174 |
-/// constructor |
|
175 |
-Priority::InEntry::InEntry(const std::string &name): |
|
176 |
- m_name(name), |
|
177 |
- m_pInput(NULL) |
|
178 |
-{ |
|
179 |
-} |
|
180 |
- |
|
181 | 107 |
} // namespace Blinker |
182 | 108 |
|
... | ... |
@@ -14,6 +14,7 @@ |
14 | 14 |
#include "CallMgr.h" |
15 | 15 |
#include "Directory.h" |
16 | 16 |
#include "File.h" |
17 |
+#include "ListTracker.h" |
|
17 | 18 |
#include "Module.h" |
18 | 19 |
#include "OutStreamFile.h" |
19 | 20 |
#include "StreamMgr.h" |
... | ... |
@@ -27,18 +28,11 @@ protected: |
27 | 28 |
/// input to priority based selector |
28 | 29 |
class Input; |
29 | 30 |
|
30 |
- /// input list entry |
|
31 |
- struct InEntry { |
|
32 |
- std::string m_name; ///< name of input list entry |
|
33 |
- Input *m_pInput; ///< input object |
|
34 |
- InEntry(const std::string &name); ///< constructor |
|
35 |
- }; |
|
36 |
- |
|
37 |
- /// input list |
|
38 |
- typedef std::list<InEntry> InList; |
|
31 |
+ /// input list tracker |
|
32 |
+ typedef ListTracker<Priority, Input, Directory> InListTracker; |
|
39 | 33 |
|
40 | 34 |
/// input list iterator |
41 |
- typedef InList::const_reverse_iterator InListIt; |
|
35 |
+ typedef InListTracker::ListIt InListIt; |
|
42 | 36 |
|
43 | 37 |
public: |
44 | 38 |
/** |
... | ... |
@@ -64,12 +58,6 @@ public: |
64 | 58 |
virtual void updateConfig(); |
65 | 59 |
|
66 | 60 |
protected: |
67 |
- /// light update of input list, i.e. check all entries in current input list |
|
68 |
- void updateInListLight(); |
|
69 |
- |
|
70 |
- /// full update of input list, i.e. scan subdirs in input list directory |
|
71 |
- void updateInListFull(); |
|
72 |
- |
|
73 | 61 |
/** |
74 | 62 |
* @brief select specific input (called by inputs) |
75 | 63 |
* @param[in] input input to select |
... | ... |
@@ -83,9 +71,8 @@ protected: |
83 | 71 |
void curFrame(); |
84 | 72 |
|
85 | 73 |
protected: |
86 |
- Directory m_dirInputs; ///< input stream directory |
|
87 | 74 |
OutStreamFile m_fileOutStream; ///< output stream name file |
88 |
- InList m_inList; ///< current input list |
|
75 |
+ InListTracker m_inListTracker; ///< input list tracker |
|
89 | 76 |
InListIt m_itCurIn; ///< current input |
90 | 77 |
}; // class Priority |
91 | 78 |
|
... | ... |
@@ -84,13 +84,13 @@ void Priority::Input::frame(stBlinkenFrame *pFrame) |
84 | 84 |
if (pFrame) { |
85 | 85 |
|
86 | 86 |
// if we are current input |
87 |
- if (m_priority.m_itCurIn != m_priority.m_inList.rend() && |
|
88 |
- m_priority.m_itCurIn->m_pInput == this) |
|
87 |
+ if (m_priority.m_itCurIn != m_priority.m_inListTracker.m_list.rend() && |
|
88 |
+ m_priority.m_itCurIn->m_pObj == this) |
|
89 | 89 |
// pass on frame |
90 | 90 |
m_priority.m_fileOutStream.setFrame(pFrame); |
91 | 91 |
|
92 | 92 |
// we have a higher priority than current input |
93 |
- if (m_priority.m_itCurIn == m_priority.m_inList.rend() || |
|
93 |
+ if (m_priority.m_itCurIn == m_priority.m_inListTracker.m_list.rend() || |
|
94 | 94 |
m_priority.m_itCurIn->m_name < m_name) |
95 | 95 |
// tell priority based selector to select us as input |
96 | 96 |
m_priority.select(this); |
... | ... |
@@ -100,8 +100,8 @@ void Priority::Input::frame(stBlinkenFrame *pFrame) |
100 | 100 |
else { |
101 | 101 |
|
102 | 102 |
// if we are current input |
103 |
- if (m_priority.m_itCurIn != m_priority.m_inList.rend() && |
|
104 |
- m_priority.m_itCurIn->m_pInput == this) |
|
103 |
+ if (m_priority.m_itCurIn != m_priority.m_inListTracker.m_list.rend() && |
|
104 |
+ m_priority.m_itCurIn->m_pObj == this) |
|
105 | 105 |
// tell priority based selector to select lower priority input |
106 | 106 |
m_priority.selectLower(); |
107 | 107 |
|
108 | 108 |