first version, plays videos to stdout
Stefan Schuermans

Stefan Schuermans commited on 2011-10-23 11:37:40
Showing 24 changed files, with 1441 additions and 0 deletions.

... ...
@@ -0,0 +1 @@
1
+example.cfg
... ...
@@ -0,0 +1,2 @@
1
+Blinker
2
+deps
... ...
@@ -0,0 +1,39 @@
1
+SRCS=$(wildcard noarch/*.cpp) $(wildcard linux/*.cpp)
2
+TARGET=Blinker
3
+
4
+CPP=g++
5
+INCLUDE=-Inoarch -Ilinux
6
+CFLAGS=-Wall -Wextra -g2
7
+LDFLAGS=
8
+LIBS=-lBlinkenLib
9
+
10
+SRCS_BASE=$(patsubst %.cpp,%,$(SRCS))
11
+DEPS=$(addsuffix .d,$(SRCS_BASE))
12
+OBJS=$(addsuffix .o,$(SRCS_BASE))
13
+
14
+.PHONY: all clean
15
+.SUFFIXES:
16
+.SECONDARY:
17
+
18
+all: deps $(TARGET)
19
+
20
+ifneq ($(MAKECMDGOALS),clean)
21
+  include deps
22
+endif
23
+
24
+deps: $(DEPS)
25
+	cat /dev/null $+ >$@
26
+
27
+%.d: %.cpp Makefile
28
+	$(CPP) $(INCLUDE) $(CFLAGS) -M -o $@ $<
29
+	sed -i 1s!^!$(dir $<)! $@
30
+
31
+%.o: %.cpp Makefile
32
+	$(CPP) $(INCLUDE) $(CFLAGS) -c -o $@ $<
33
+
34
+$(TARGET): $(OBJS)
35
+	$(CPP) $(LDFLAGS) -o $@ $+ $(LIBS)
36
+
37
+clean:
38
+	rm -f deps $(DEPS) $(OBJS) $(TARGET)
39
+
... ...
@@ -0,0 +1,2 @@
1
+*.d
2
+*.o
... ...
@@ -0,0 +1,89 @@
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 <dirent.h>
7
+#include <string>
8
+#include <string.h>
9
+#include <sys/stat.h>
10
+#include <sys/types.h>
11
+#include <unistd.h>
12
+
13
+#include "Directory.h"
14
+#include "File.h"
15
+
16
+namespace Blinker {
17
+
18
+/**
19
+ * @brief constructor from path
20
+ * @param[in] path path to directory
21
+ */
22
+Directory::Directory(const std::string &path):
23
+  File(path)
24
+{
25
+  if (m_path.empty() || m_path.at(m_path.length() - 1) != '/')
26
+    m_path += '/';
27
+}
28
+
29
+/**
30
+ * @brief get list of entries in directory
31
+ * @param[in] type type of directory entries to return
32
+ * @param[out] entries list of directory entries
33
+ */
34
+void Directory::getEntries(Type type, std::list<std::string> &entries) const
35
+{
36
+  entries.clear();
37
+
38
+  if (m_path.empty())
39
+    return;
40
+  DIR *dir = opendir(m_path.c_str());
41
+  if (!dir)
42
+    return;
43
+
44
+  struct dirent *dirent;
45
+  while ((dirent = readdir(dir))) {
46
+    if (strcmp(dirent->d_name, ".") && strcmp(dirent->d_name, "..") ) {
47
+
48
+      struct stat s;
49
+      if (stat((m_path + dirent->d_name).c_str(), &s))
50
+        continue; // cannot stat -> silently ignore
51
+
52
+      bool ok = false;
53
+      switch (type) {
54
+        case TypeSubdir: ok = S_ISDIR(s.st_mode); break;
55
+        case TypeFile:   ok = S_ISREG(s.st_mode); break;
56
+      }
57
+      if (ok)
58
+        entries.push_back(dirent->d_name);
59
+
60
+    } // if ! "." && ! ".."
61
+  } // while dirent
62
+
63
+  closedir(dir);
64
+
65
+  entries.sort();
66
+}
67
+
68
+/**
69
+ * @brief get subdirectory
70
+ * @param[in] name of subdirectory
71
+ * @return subdirectory object
72
+ */
73
+Directory Directory::getSubdir(const std::string &name) const
74
+{
75
+  return Directory(m_path + name);
76
+}
77
+
78
+/**
79
+ * @brief get file in directory
80
+ * @param[in] name of file
81
+ * @return file object
82
+ */
83
+File Directory::getFile(const std::string &name) const
84
+{
85
+  return File(m_path + name);
86
+}
87
+
88
+} // namespace Blinker
89
+
... ...
@@ -0,0 +1,59 @@
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 DIRECTORY_H
7
+#define DIRECTORY_H
8
+
9
+#include <list>
10
+#include <string>
11
+
12
+#include "File.h"
13
+
14
+namespace Blinker {
15
+
16
+/// information about a directory
17
+class Directory: public File
18
+{
19
+public:
20
+  /// type of directory entries
21
+  enum Type {
22
+    TypeSubdir, ///< subdirectory
23
+    TypeFile    ///< file
24
+  };
25
+
26
+public:
27
+  /**
28
+   * @brief constructor from path
29
+   * @param[in] path path to directory
30
+   */
31
+  Directory(const std::string &path);
32
+
33
+public:
34
+  /**
35
+   * @brief get list of entries in directory
36
+   * @param[in] type type of directory entries to return
37
+   * @param[out] entries list of directory entries
38
+   */
39
+  void getEntries(Type type, std::list<std::string> &entries) const;
40
+
41
+  /**
42
+   * @brief get subdirectory
43
+   * @param[in] name of subdirectory
44
+   * @return subdirectory object
45
+   */
46
+  Directory getSubdir(const std::string &name) const;
47
+
48
+  /**
49
+   * @brief get file in directory
50
+   * @param[in] name of file
51
+   * @return file object
52
+   */
53
+  File getFile(const std::string &name) const;
54
+}; // class Directory
55
+
56
+} // namespace Blinker
57
+
58
+#endif // #ifndef DIRECTORY_H
59
+
... ...
@@ -0,0 +1,61 @@
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 <string>
7
+#include <sys/stat.h>
8
+#include <sys/types.h>
9
+#include <unistd.h>
10
+
11
+#include "File.h"
12
+#include "Time.h"
13
+
14
+namespace Blinker {
15
+
16
+/**
17
+ * @brief constructor from path
18
+ * @param[in] path path to file
19
+ */
20
+File::File(const std::string &path):
21
+  m_path(path),
22
+  m_lastCheck() // initialize last check to "now"
23
+{
24
+}
25
+
26
+/**
27
+ * @brief get path to file
28
+ * @return path to file
29
+ */
30
+const std::string & File::getPath()
31
+{
32
+  return m_path;
33
+}
34
+
35
+/**
36
+ * @brief check if file has been modified
37
+ * @return if file has been modified since last check
38
+ */
39
+bool File::checkModified()
40
+{
41
+  /* get current time before getting modification time
42
+     for not missing any modification */
43
+  Time now;
44
+
45
+  // get modification time
46
+  struct stat s;
47
+  if (stat(m_path.c_str(), &s))
48
+    return false; // cannot stat -> silently ignore
49
+  Time modified(s.st_mtime);
50
+
51
+  // has file been modified since last check
52
+  bool mod = modified > m_lastCheck;
53
+
54
+  // remember "now" as last check time
55
+  m_lastCheck = now;
56
+
57
+  return mod;
58
+}
59
+
60
+} // namespace Blinker
61
+
... ...
@@ -0,0 +1,46 @@
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 FILE_H
7
+#define FILE_H
8
+
9
+#include <string>
10
+
11
+#include "Time.h"
12
+
13
+namespace Blinker {
14
+
15
+/// information about a file
16
+class File
17
+{
18
+public:
19
+  /**
20
+   * @brief constructor from path
21
+   * @param[in] path path to file
22
+   */
23
+  File(const std::string &path);
24
+
25
+public:
26
+  /**
27
+   * @brief get path to file
28
+   * @return path to file
29
+   */
30
+  const std::string & getPath();
31
+
32
+  /**
33
+   * @brief check if file has been modified
34
+   * @return if file has been modified since last check
35
+   */
36
+  bool checkModified();
37
+
38
+protected:
39
+  std::string m_path; ///< path to file
40
+  Time m_lastCheck; ///< last time modification time was checked
41
+}; // class File
42
+
43
+} // namespace Blinker
44
+
45
+#endif // #ifndef FILE_H
46
+
... ...
@@ -0,0 +1,203 @@
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 <errno.h>
7
+#include <stdint.h>
8
+#include <sys/time.h>
9
+#include <time.h>
10
+
11
+#include "Time.h"
12
+
13
+namespace Blinker {
14
+
15
+const Time Time::zero(0); ///< zero time
16
+
17
+/**
18
+ * @brief get current time
19
+ * @return current time
20
+ */
21
+Time Time::now()
22
+{
23
+  Time now;
24
+
25
+  struct timeval tv;
26
+  gettimeofday(&tv, NULL);
27
+  now.m_sec = tv.tv_sec;
28
+  now.m_ns = tv.tv_usec * 1000;
29
+
30
+  return now;
31
+}
32
+
33
+/// constructor
34
+Time::Time():
35
+  m_sec(0),
36
+  m_ns(0)
37
+{
38
+}
39
+
40
+/**
41
+ * @brief constructor from seconds
42
+ * @param[in] t time in seconds
43
+ */
44
+Time::Time(time_t t):
45
+  m_sec(t),
46
+  m_ns(0)
47
+{
48
+}
49
+
50
+/// comparison
51
+//@{
52
+
53
+int Time::compare(const Time &that) const
54
+{
55
+  if (m_sec < that.m_sec)
56
+    return -1;
57
+  if (m_sec > that.m_sec)
58
+    return 1;
59
+  if (m_ns < that.m_ns)
60
+    return -1;
61
+  if (m_ns > that.m_ns)
62
+    return 1;
63
+  return 0;
64
+}
65
+
66
+bool Time::operator==(const Time &that) const
67
+{
68
+  return compare(that) == 0;
69
+}
70
+
71
+bool Time::operator!=(const Time &that) const
72
+{
73
+  return compare(that) != 0;
74
+}
75
+
76
+bool Time::operator<(const Time &that) const
77
+{
78
+  return compare(that) < 0;
79
+}
80
+
81
+bool Time::operator>(const Time &that) const
82
+{
83
+  return compare(that) > 0;
84
+}
85
+
86
+bool Time::operator<=(const Time &that) const
87
+{
88
+  return compare(that) <= 0;
89
+}
90
+
91
+bool Time::operator>=(const Time &that) const
92
+{
93
+  return compare(that) >= 0;
94
+}
95
+
96
+//@}
97
+
98
+/// arithmetic
99
+//@{
100
+
101
+const Time & Time::operator+=(const Time &that)
102
+{
103
+  m_sec += that.m_sec;
104
+  m_ns += that.m_ns;
105
+  fix();
106
+  return *this;
107
+}
108
+
109
+const Time & Time::operator-=(const Time &that)
110
+{
111
+  m_sec -= that.m_sec;
112
+  m_ns -= that.m_ns;
113
+  fix();
114
+  return *this;
115
+}
116
+
117
+Time Time::operator+(const Time &that) const
118
+{
119
+  Time result(*this);
120
+  result += that;
121
+  return result;
122
+}
123
+
124
+Time Time::operator-(const Time &that) const
125
+{
126
+  Time result(*this);
127
+  result -= that;
128
+  return result;
129
+}
130
+
131
+//@}
132
+
133
+/**
134
+ * @brief convert from milliseconds
135
+ * @param[in] ms milliseconds
136
+ */
137
+void Time::fromMs(int ms)
138
+{
139
+  if (ms >= 0) {
140
+    m_sec = ms / 1000;
141
+    m_ns = (ms % 1000) * 1000000;
142
+  } else {
143
+    m_sec = -(-ms / 1000);
144
+    m_ns = -(-ms % 1000) * 1000000;
145
+  }
146
+}
147
+
148
+/**
149
+ * @brief convert to seconds
150
+ * @return seconds
151
+ */
152
+time_t Time::toSec() const
153
+{
154
+  if (m_ns >= 500000000)
155
+    return m_sec + 1;
156
+  else if (m_ns <= 500000000)
157
+    return m_sec - 1;
158
+  else
159
+    return m_sec;
160
+}
161
+
162
+/// fix internal time representation after calculation
163
+void Time::fix()
164
+{
165
+  if (m_ns >= 1000000000) {
166
+    m_sec += m_ns / 1000000000;
167
+    m_ns = m_ns % 1000000000;
168
+  } else if (m_ns <= -1000000000) {
169
+    m_sec -= -m_ns / 1000000000;
170
+    m_ns = -(-m_ns % 1000000000);
171
+  }
172
+  if (m_sec > 0 && m_ns < 0) {
173
+    m_sec -= 1;
174
+    m_ns += 1000000000;
175
+  } else if (m_sec < 0 && m_ns > 0) {
176
+    m_sec += 1;
177
+    m_ns -= 1000000000;
178
+  }
179
+}
180
+
181
+/// sleep for duration
182
+void Time::sleepFor() const
183
+{
184
+  // do not sleep for negative time
185
+  if (*this < zero)
186
+    return;
187
+
188
+  // sleep
189
+  struct timespec req, rem;
190
+  req.tv_sec  = m_sec;
191
+  req.tv_nsec = m_ns;
192
+  while (nanosleep(&req, &rem) && errno == EINTR)
193
+    req = rem;
194
+}
195
+
196
+/// sleep until time
197
+void Time::sleepUntil() const
198
+{
199
+  (*this - now()).sleepFor();
200
+}
201
+
202
+} // namespace Blinker
203
+
... ...
@@ -0,0 +1,88 @@
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 TIME_H
7
+#define TIME_H
8
+
9
+#include <stdint.h>
10
+#include <time.h>
11
+
12
+namespace Blinker {
13
+
14
+/// time, either point in time or duration
15
+class Time
16
+{
17
+public:
18
+  static const Time zero; ///< zero time
19
+
20
+public:
21
+  /**
22
+   * @brief get current time
23
+   * @return current time
24
+   */
25
+  static Time now();
26
+
27
+public:
28
+  /// constructor
29
+  Time();
30
+
31
+  /**
32
+   * @brief constructor from seconds
33
+   * @param[in] t time in seconds
34
+   */
35
+  Time(time_t t);
36
+
37
+public:
38
+  /// comparison
39
+  //@{
40
+  int compare(const Time &that) const;
41
+  bool operator==(const Time &that) const;
42
+  bool operator!=(const Time &that) const;
43
+  bool operator<(const Time &that) const;
44
+  bool operator>(const Time &that) const;
45
+  bool operator<=(const Time &that) const;
46
+  bool operator>=(const Time &that) const;
47
+  //@}
48
+
49
+  /// arithmetic
50
+  //@{
51
+  const Time & operator+=(const Time &that);
52
+  const Time & operator-=(const Time &that);
53
+  Time operator+(const Time &that) const;
54
+  Time operator-(const Time &that) const;
55
+  //@}
56
+
57
+  /**
58
+   * @brief convert from milliseconds
59
+   * @param[in] ms milliseconds
60
+   */
61
+  void fromMs(int ms);
62
+
63
+  /**
64
+   * @brief convert to seconds
65
+   * @return seconds
66
+   */
67
+  time_t toSec() const;
68
+
69
+public:
70
+  /// sleep for duration
71
+  void sleepFor() const;
72
+
73
+  /// sleep until time
74
+  void sleepUntil() const;
75
+
76
+protected:
77
+  /// fix internal time representation after calculation
78
+  void fix();
79
+
80
+protected:
81
+  int64_t m_sec; ///< seconds
82
+  int64_t m_ns;  ///< nanoseconds
83
+}; // class Time
84
+
85
+} // namespace Blinker
86
+
87
+#endif // #ifndef TIME_H
88
+
... ...
@@ -0,0 +1,2 @@
1
+*.d
2
+*.o
... ...
@@ -0,0 +1,83 @@
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 <map>
7
+#include <set>
8
+
9
+#include "CallMgr.h"
10
+#include "Time.h"
11
+#include "TimeCallee.h"
12
+
13
+namespace Blinker {
14
+
15
+/// constructor
16
+CallMgr::CallMgr()
17
+{
18
+}
19
+
20
+/// destructor
21
+CallMgr::~CallMgr()
22
+{
23
+}
24
+
25
+/**
26
+ * @brief cancel callback at certain time
27
+ * @param[in] callee whom not to call
28
+ */
29
+void CallMgr::cancelTimeCall(TimeCallee *callee)
30
+{
31
+  // find time a call is registered at
32
+  TimeCalleeMap::iterator itCallee;
33
+  itCallee = m_timeCallees.find(callee);
34
+  if (itCallee == m_timeCallees.end())
35
+    return; // no call registered
36
+  const Time &time = itCallee->second;
37
+
38
+  // remove registered call
39
+  m_times[time].erase(callee);
40
+  m_timeCallees.erase(itCallee);
41
+}
42
+
43
+/**
44
+ * @brief request callback at certain time
45
+ * @param[in] callee whom to call
46
+ * @param[in] time when to call
47
+ *
48
+ * this cancels a previous time call request from callee
49
+ */
50
+void CallMgr::requestTimeCall(TimeCallee *callee, const Time &time)
51
+{
52
+  // cancel previous call
53
+  cancelTimeCall(callee);
54
+
55
+  // register call at new time
56
+  m_times[time].insert(callee);
57
+  m_timeCallees[callee] = time;
58
+}
59
+
60
+/// run call manager
61
+void CallMgr::run()
62
+{
63
+  while (!m_times.empty()) {
64
+
65
+    // wait until next time is reached
66
+    m_times.begin()->first.sleepUntil();
67
+
68
+    // get callees and remove entry from time map
69
+    TimeCallees timeCallees = m_times.begin()->second;
70
+    m_times.erase(m_times.begin());
71
+
72
+    // call callees
73
+    TimeCallees::const_iterator itTC;
74
+    for (itTC = timeCallees.begin(); itTC != timeCallees.end(); ++itTC) {
75
+      m_timeCallees.erase(*itTC); // first remove request from callee map
76
+      (*itTC)->timeCall(); // then call callee
77
+    }
78
+
79
+  } // while m_times
80
+}
81
+
82
+} // namespace Blinker
83
+
... ...
@@ -0,0 +1,71 @@
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 CALLMGR_H
7
+#define CALLMGR_H
8
+
9
+#include <map>
10
+#include <set>
11
+
12
+#include "Time.h"
13
+#include "TimeCallee.h"
14
+
15
+namespace Blinker {
16
+
17
+/// callback manager, calls back at certain time or events
18
+class CallMgr
19
+{
20
+protected:
21
+  /// set of time callees to call at a certain time
22
+  typedef std::set<TimeCallee *> TimeCallees;
23
+  /// what set of time callees to call at a certain time
24
+  typedef std::map<Time, TimeCallees> TimeMap;
25
+  /// when to call a time callee
26
+  typedef std::map<TimeCallee *, Time> TimeCalleeMap;
27
+
28
+public:
29
+  /// constructor
30
+  CallMgr();
31
+
32
+  /// destructor
33
+  ~CallMgr();
34
+
35
+private:
36
+  /// copy constructor disabled
37
+  CallMgr(const CallMgr & that);
38
+
39
+  /// assignment operator disabled
40
+  const CallMgr& operator=(const CallMgr &that);
41
+
42
+public:
43
+  /**
44
+   * @brief cancel callback at certain time
45
+   * @param[in] callee whom not to call
46
+   */
47
+  void cancelTimeCall(TimeCallee *callee);
48
+
49
+  /**
50
+   * @brief request callback at certain time
51
+   * @param[in] callee whom to call
52
+   * @param[in] time when to call
53
+   *
54
+   * this cancels a previous time call request from callee
55
+   */
56
+  void requestTimeCall(TimeCallee *callee, const Time &time);
57
+
58
+  /// run call manager
59
+  void run();
60
+
61
+protected:
62
+  /// what time callees to call at a certain time
63
+  TimeMap m_times;
64
+  /// when to call time callees
65
+  TimeCalleeMap m_timeCallees;
66
+}; // class CallMgr
67
+
68
+} // namespace Blinker
69
+
70
+#endif // #ifndef CALLMGR_H
71
+
... ...
@@ -0,0 +1,207 @@
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 "CallMgr.h"
13
+#include "Directory.h"
14
+#include "File.h"
15
+#include "Player.h"
16
+#include "StreamMgr.h"
17
+#include "Time.h"
18
+#include "TimeCallee.h"
19
+
20
+namespace Blinker {
21
+
22
+/**
23
+ * @brief constructor
24
+ * @param[in] callMgr callback manager
25
+ * @param[in] streamMgr stream manager
26
+ * @param[in] dirBase base directory
27
+ */
28
+Player::Player(CallMgr &callMgr, StreamMgr &streamMgr,
29
+               const Directory &dirBase):
30
+  m_callMgr(callMgr),
31
+  m_streamMgr(streamMgr),
32
+  m_dirBase(dirBase),
33
+  m_dirPlaylist(dirBase.getSubdir("playlist")),
34
+  m_streamName("TEST"), // TODO
35
+  m_pStream(NULL),
36
+  m_curEntry(m_playlist.begin()),
37
+  m_curFrame(0)
38
+{
39
+  // get output stream
40
+  m_pStream = &m_streamMgr.refStream(m_streamName);
41
+
42
+  // load playlist
43
+  updatePlaylist();
44
+}
45
+
46
+/// virtual destructor
47
+Player::~Player()
48
+{
49
+  // free all movies
50
+  while (!m_playlist.empty()) {
51
+    m_playlist.back().freeMovie();
52
+    m_playlist.pop_back();
53
+  }
54
+
55
+  // unreference stream
56
+  m_pStream = NULL;
57
+  m_streamMgr.unrefStream(m_streamName);
58
+}
59
+
60
+/// callback when requsted time reached
61
+void Player::timeCall()
62
+{
63
+  // show next frame
64
+  showFrame();
65
+}
66
+
67
+/// update playlist
68
+void Player::updatePlaylist()
69
+{
70
+  // get list of files in playlist directory
71
+  typedef std::list<std::string> Filelist;
72
+  Filelist curFiles;
73
+  m_dirPlaylist.getEntries(Directory::TypeFile, curFiles);
74
+
75
+  // walk through current playlist and file list simultaneously
76
+  bool                     bWasEmpty = m_playlist.empty();
77
+  Filelist::const_iterator itFile    = curFiles.begin();
78
+  Playlist::iterator       itEntry   = m_playlist.begin();
79
+  bool                     bCurChg   = false;
80
+  while (itFile != curFiles.end() || itEntry != m_playlist.end()) {
81
+
82
+    // new movie inserted
83
+    if (itEntry == m_playlist.end() || *itFile < itEntry->m_name) {
84
+      // load movie
85
+      Entry entry(*itFile, m_dirPlaylist.getFile(*itFile));
86
+      if (entry.loadMovie())
87
+        // insert playlist entry
88
+        m_playlist.insert(itEntry, entry);
89
+      // advance to next file
90
+      ++itFile;
91
+    }
92
+
93
+    // movie removed
94
+    // movie changed (=> remove and re-insert in next iteration)
95
+    else if (itFile == curFiles.end() || *itFile > itEntry->m_name ||
96
+             itEntry->m_file.checkModified()) {
97
+      // check if movie to remov movie is current movie
98
+      if (itEntry == m_curEntry) {
99
+        // advance current movie to next movie
100
+        ++m_curEntry;
101
+        bCurChg = true;
102
+      }
103
+      // remove entry
104
+      itEntry->freeMovie();
105
+      itEntry = m_playlist.erase(itEntry);
106
+      // do not advance to next file
107
+    }
108
+
109
+    // movie stayed in playlist and did not change
110
+    else {
111
+      // advance to next file and next entry
112
+      ++itFile;
113
+      ++itEntry;
114
+    }
115
+
116
+  } // while itFile itPlaylist
117
+
118
+  // current movie entry changed - or - playlist was empty and is not now
119
+  if (bCurChg || (bWasEmpty && !m_playlist.empty())) {
120
+    // go to begin of movie and start playing now
121
+    m_curFrame = 0;
122
+    m_showTime = Time::now();
123
+    showFrame();
124
+  }
125
+}
126
+
127
+/// show current frame
128
+void Player::showFrame()
129
+{
130
+  // leave if time is not yet ready to show frame
131
+  if (Time::now() < m_showTime) {
132
+    m_callMgr.requestTimeCall(this, m_showTime); // request call at show time
133
+    return;
134
+  }
135
+
136
+  // movie finished -> next movie
137
+  //   use while loops to handle empty movies / empty playlist
138
+  bool wrapped = false;
139
+  while (true) {
140
+    // playlist finished -> re-start from beginning
141
+    while (m_curEntry == m_playlist.end()) {
142
+      m_curEntry = m_playlist.begin();
143
+      m_curFrame = 0;
144
+      // detect empty playlist or playlist with only empty movies
145
+      if (wrapped) {
146
+        // empty playlist or playlist with only empty movies -> no frame
147
+        if (m_pStream)
148
+          m_pStream->setNoFrame();
149
+        return;
150
+      }
151
+      wrapped = true;
152
+    }
153
+    // movie not yet finished -> done
154
+    if (m_curFrame < BlinkenMovieGetFrameCnt(m_curEntry->m_pMovie))
155
+      break;
156
+    // movie finished -> next movie
157
+    ++m_curEntry;
158
+    m_curFrame = 0;
159
+  }
160
+
161
+  // show frame
162
+  stBlinkenFrame *pFrame =
163
+      BlinkenMovieGetFrame(m_curEntry->m_pMovie, m_curFrame);
164
+  if (m_pStream)
165
+    m_pStream->setFrame(pFrame);
166
+
167
+  // calculate show time for next frame
168
+  Time duration;
169
+  duration.fromMs(BlinkenFrameGetDuration(pFrame));
170
+  m_showTime += duration;
171
+  m_callMgr.requestTimeCall(this, m_showTime); // request call at show time
172
+
173
+  // go to next frame
174
+  ++m_curFrame;
175
+}
176
+
177
+/* #################
178
+   # Player::Entry #
179
+   ################# */
180
+
181
+/// constructor
182
+Player::Entry::Entry(const std::string &name, const File &file):
183
+  m_name(name),
184
+  m_file(file),
185
+  m_pMovie(NULL)
186
+{
187
+}
188
+
189
+/// load movie from current file
190
+bool Player::Entry::loadMovie()
191
+{
192
+  freeMovie();
193
+  m_pMovie = BlinkenMovieLoad(m_file.getPath().c_str());
194
+  return m_pMovie;
195
+}
196
+
197
+/// free current movie
198
+void Player::Entry::freeMovie()
199
+{
200
+  if (m_pMovie) {
201
+    BlinkenMovieFree(m_pMovie);
202
+    m_pMovie = NULL;
203
+  }
204
+}
205
+
206
+} // namespace Blinker
207
+
... ...
@@ -0,0 +1,86 @@
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 PLAYER_H
7
+#define PLAYER_H
8
+
9
+#include <list>
10
+#include <string>
11
+
12
+#include <BlinkenLib/BlinkenMovie.h>
13
+
14
+#include "CallMgr.h"
15
+#include "Directory.h"
16
+#include "File.h"
17
+#include "StreamMgr.h"
18
+#include "Time.h"
19
+#include "TimeCallee.h"
20
+
21
+namespace Blinker {
22
+
23
+/// a movie player
24
+class Player: public TimeCallee
25
+{
26
+protected:
27
+  /// playlist entry
28
+  struct Entry {
29
+    std::string     m_name;    ///< name of playlist entry
30
+    File            m_file;    ///< file object (to check for updates)
31
+    stBlinkenMovie *m_pMovie;  ///< movie object
32
+    Entry(const std::string &name, const File &file); ///< constructor
33
+    bool loadMovie(); ///< load movie from current file
34
+    void freeMovie(); ///< free current movie
35
+  };
36
+
37
+  /// playlist
38
+  typedef std::list<Entry> Playlist;
39
+
40
+public:
41
+  /**
42
+   * @brief constructor
43
+   * @param[in] callMgr callback manager
44
+   * @param[in] streamMgr stream manager
45
+   * @param[in] dirBase base directory
46
+   */
47
+  Player(CallMgr &callMgr, StreamMgr &streamMgr, const Directory &dirBase);
48
+
49
+  /// virtual destructor
50
+  virtual ~Player();
51
+
52
+private:
53
+  /// copy constructor disabled
54
+  Player(const Player & that);
55
+
56
+  /// assignment operator disabled
57
+  const Player& operator=(const Player &that);
58
+
59
+public:
60
+  /// callback when requsted time reached
61
+  virtual void timeCall();
62
+
63
+protected:
64
+  /// update playlist
65
+  void updatePlaylist();
66
+
67
+  /// show current frame
68
+  void showFrame();
69
+
70
+protected:
71
+  CallMgr                  &m_callMgr;    ///< callback manager
72
+  StreamMgr                &m_streamMgr;  ///< stream manager
73
+  Directory                m_dirBase;     ///< base directory
74
+  Directory                m_dirPlaylist; ///< playlist directory
75
+  std::string              m_streamName;  ///< name of output stream
76
+  Stream                   *m_pStream;    ///< output stream
77
+  Playlist                 m_playlist;    ///< current playlist
78
+  Playlist::const_iterator m_curEntry;    ///< current playlist entry
79
+  int                      m_curFrame;    ///< current frame in movie
80
+  Time                     m_showTime;    ///< when to show frame
81
+}; // class Player
82
+
83
+} // namespace Blinker
84
+
85
+#endif // #ifndef PLAYER_H
86
+
... ...
@@ -0,0 +1,75 @@
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 <iostream> // DEBUG
7
+#include <set>
8
+#include <stdlib.h> // DEBUG
9
+
10
+#include <BlinkenLib/BlinkenFrame.h>
11
+
12
+#include "Stream.h"
13
+#include "StreamRecv.h"
14
+
15
+namespace Blinker {
16
+
17
+/// constructor
18
+Stream::Stream()
19
+{
20
+}
21
+
22
+/// virtual destructor
23
+Stream::~Stream()
24
+{
25
+}
26
+
27
+/**
28
+ * @brief attach a stream receiver
29
+ * @param[in] recv stream receiver to attach
30
+ */
31
+void Stream::attach(StreamRecv *recv)
32
+{
33
+  m_recvs.insert(recv);
34
+}
35
+
36
+/**
37
+ * @brief detach a stream receiver
38
+ * @param[in] recv stream receiver to detach
39
+ */
40
+void Stream::detach(StreamRecv *recv)
41
+{
42
+  m_recvs.erase(recv);
43
+}
44
+
45
+/**
46
+ * @brief set current frame
47
+ * @param[in] pFrame current frame
48
+ */
49
+void Stream::setFrame(stBlinkenFrame *pFrame)
50
+{
51
+  // DEBUG
52
+  char *str = BlinkenFrameToString(pFrame);
53
+  std::cout << str;
54
+  free(str);
55
+
56
+  // pass frame to all receivers
57
+  Recvs::iterator it;
58
+  for (it = m_recvs.begin(); it != m_recvs.end(); ++it)
59
+    (*it)->setFrame(pFrame);
60
+}
61
+
62
+/// set current frame to none
63
+void Stream::setNoFrame()
64
+{
65
+  // DEBUG
66
+  std::cout << "no frame" << std::endl;
67
+
68
+  // pass "no frame" to all receivers
69
+  Recvs::iterator it;
70
+  for (it = m_recvs.begin(); it != m_recvs.end(); ++it)
71
+    (*it)->setNoFrame();
72
+}
73
+
74
+} // namespace Blinker
75
+
... ...
@@ -0,0 +1,61 @@
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 STREAM_H
7
+#define STREAM_H
8
+
9
+#include <set>
10
+
11
+#include <BlinkenLib/BlinkenFrame.h>
12
+
13
+#include "StreamRecv.h"
14
+
15
+namespace Blinker {
16
+
17
+/// a video stream
18
+class Stream: public StreamRecv
19
+{
20
+protected:
21
+  /// set of receivers of this stream
22
+  typedef std::set<StreamRecv *> Recvs;
23
+
24
+public:
25
+  /// constructor
26
+  Stream();
27
+
28
+  /// virtual destructor
29
+  virtual ~Stream();
30
+
31
+public:
32
+  /**
33
+   * @brief attach a stream receiver
34
+   * @param[in] recv stream receiver to attach
35
+   */
36
+  void attach(StreamRecv *recv);
37
+
38
+  /**
39
+   * @brief detach a stream receiver
40
+   * @param[in] recv stream receiver to detach
41
+   */
42
+  void detach(StreamRecv *recv);
43
+
44
+  /**
45
+   * @brief set current frame
46
+   * @param[in] pFrame current frame
47
+   */
48
+  virtual void setFrame(stBlinkenFrame *pFrame);
49
+
50
+  /// set current frame to none
51
+  virtual void setNoFrame();
52
+
53
+protected:
54
+  /// receivers of this stream
55
+  Recvs m_recvs;
56
+}; // class Stream
57
+
58
+} // namespace Blinker
59
+
60
+#endif // #ifndef STREAM_H
61
+
... ...
@@ -0,0 +1,67 @@
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 <map>
7
+#include <set>
8
+#include <string>
9
+
10
+#include "Stream.h"
11
+#include "StreamMgr.h"
12
+
13
+namespace Blinker {
14
+
15
+/// constructor
16
+StreamMgr::StreamMgr()
17
+{
18
+}
19
+
20
+/// destructor
21
+StreamMgr::~StreamMgr()
22
+{
23
+}
24
+
25
+/**
26
+ * @brief reference stream
27
+ * @param[in] name stream name
28
+ * @return stream
29
+ *
30
+ * if the stream does not exists, it is created
31
+ */
32
+Stream & StreamMgr::refStream(const std::string &name)
33
+{
34
+  Entry &entry = m_streams[name];
35
+  entry.m_refCnt++;
36
+  return entry.m_stream;
37
+}
38
+
39
+/**
40
+ * @brief unreference stream
41
+ * @param[in] name stream name
42
+ *
43
+ * if the last reference is removed, the stream is deleted
44
+ */
45
+void StreamMgr::unrefStream(const std::string &name)
46
+{
47
+  StreamMap::iterator itStream = m_streams.find(name);
48
+  if (itStream != m_streams.end()) {
49
+    if (itStream->second.m_refCnt > 0)
50
+      itStream->second.m_refCnt--;
51
+    if (itStream->second.m_refCnt == 0)
52
+      m_streams.erase(itStream);
53
+  }
54
+}
55
+
56
+/* ####################
57
+   # StreamMgr::Entry #
58
+   #################### */
59
+
60
+/// constructor
61
+StreamMgr::Entry::Entry():
62
+  m_refCnt(0)
63
+{
64
+}
65
+
66
+} // namespace Blinker
67
+
... ...
@@ -0,0 +1,71 @@
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 STREAMMGR_H
7
+#define STREAMMGR_H
8
+
9
+#include <map>
10
+#include <set>
11
+#include <string>
12
+
13
+#include "Stream.h"
14
+
15
+namespace Blinker {
16
+
17
+/// stream manager
18
+class StreamMgr
19
+{
20
+protected:
21
+  /// stream map entry
22
+  struct Entry {
23
+    Stream       m_stream; ///< the stream
24
+    unsigned int m_refCnt; ///< reference count
25
+    Entry(); ///< constructor
26
+  };
27
+
28
+  /// map of streams
29
+  typedef std::map<std::string, Entry> StreamMap;
30
+
31
+public:
32
+  /// constructor
33
+  StreamMgr();
34
+
35
+  /// destructor
36
+  ~StreamMgr();
37
+
38
+private:
39
+  /// copy constructor disabled
40
+  StreamMgr(const StreamMgr & that);
41
+
42
+  /// assignment operator disabled
43
+  const StreamMgr& operator=(const StreamMgr &that);
44
+
45
+public:
46
+  /**
47
+   * @brief reference stream
48
+   * @param[in] name stream name
49
+   * @return stream
50
+   *
51
+   * if the stream does not exists, it is created
52
+   */
53
+  Stream & refStream(const std::string &name);
54
+
55
+  /**
56
+   * @brief unreference stream
57
+   * @param[in] name stream name
58
+   *
59
+   * if the last reference is removed, the stream is deleted
60
+   */
61
+  void unrefStream(const std::string &name);
62
+
63
+protected:
64
+  /// map of streams
65
+  StreamMap m_streams;
66
+}; // class StreamMgr
67
+
68
+} // namespace Blinker
69
+
70
+#endif // #ifndef STREAMMGR_H
71
+
... ...
@@ -0,0 +1,23 @@
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 <BlinkenLib/BlinkenFrame.h>
7
+
8
+#include "StreamRecv.h"
9
+
10
+namespace Blinker {
11
+
12
+/// constructor
13
+StreamRecv::StreamRecv()
14
+{
15
+}
16
+
17
+/// virtual destructor
18
+StreamRecv::~StreamRecv()
19
+{
20
+}
21
+
22
+} // namespace Blinker
23
+
... ...
@@ -0,0 +1,37 @@
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 STREAMRECV_H
7
+#define STREAMRECV_H
8
+
9
+#include <BlinkenLib/BlinkenFrame.h>
10
+
11
+namespace Blinker {
12
+
13
+/// video stream receiver interface
14
+class StreamRecv
15
+{
16
+public:
17
+  /// constructor
18
+  StreamRecv();
19
+
20
+  /// virtual destructor
21
+  virtual ~StreamRecv();
22
+
23
+public:
24
+  /**
25
+   * @brief set current frame
26
+   * @param[in] pFrame current frame
27
+   */
28
+  virtual void setFrame(stBlinkenFrame *pFrame) = 0;
29
+
30
+  /// set current frame to none
31
+  virtual void setNoFrame() = 0;
32
+}; // class StreamRecv
33
+
34
+} // namespace Blinker
35
+
36
+#endif // #ifndef STREAMRECV_H
37
+
... ...
@@ -0,0 +1,20 @@
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 "TimeCallee.h"
7
+
8
+namespace Blinker {
9
+
10
+/// constructor
11
+TimeCallee::TimeCallee()
12
+{
13
+}
14
+
15
+/// destructor
16
+TimeCallee::~TimeCallee(){
17
+}
18
+
19
+} // namespace Blinker
20
+
... ...
@@ -0,0 +1,29 @@
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 TIMECALLEE_H
7
+#define TIMECALLEE_H
8
+
9
+namespace Blinker {
10
+
11
+/// time callee interface (i.e. called at a certain time)
12
+class TimeCallee
13
+{
14
+public:
15
+  /// constructor
16
+  TimeCallee();
17
+
18
+  /// destructor
19
+  virtual ~TimeCallee();
20
+
21
+public:
22
+  /// callback when requsted time reached
23
+  virtual void timeCall() = 0;
24
+}; // class TimeCallee
25
+
26
+} // namespace Blinker
27
+
28
+#endif // #ifndef TIMECALLEE_H
29
+
... ...
@@ -0,0 +1,19 @@
1
+#include "CallMgr.h"
2
+#include "Directory.h"
3
+#include "Player.h"
4
+#include "StreamMgr.h"
5
+
6
+using namespace Blinker;
7
+
8
+int main()
9
+{
10
+  CallMgr callMgr;
11
+  StreamMgr streamMgr;
12
+
13
+  Player player(callMgr, streamMgr, Directory("../example.cfg/players/hdl"));
14
+
15
+  callMgr.run();
16
+
17
+  return 0;
18
+}
19
+
0 20