added flexipix output support added auto-configuration stuff to makefile
Stefan Schuermans

Stefan Schuermans commited on 2011-12-14 22:02:48
Showing 11 changed files, with 385 additions and 7 deletions.

... ...
@@ -0,0 +1,33 @@
1
+<html>
2
+  <head>
3
+    <title>Blinker - FlexiPix</title>
4
+  </head>
5
+  <body>
6
+    <h1>Blinker - FlexiPix</h1>
7
+    <p>
8
+      The <a href="http://www.fleixpix.de">FlexiPix</a> module is used
9
+      to output a stream to a FlexiPix display.
10
+      It is only functional if Blinker has been compiled against
11
+      <a href="http://git.blinkenarea.org/?p=libflexipix">libflexipix</a>.
12
+    </p>
13
+    <h2>Configuration</h2>
14
+    <p>
15
+      The configuration of the FlexiPix module with name <code>NAME</code>
16
+      is located in the <code>flexipixes/NAME</code> subdirectory.
17
+    </p>
18
+    <h3>Input Stream</h3>
19
+    <p>
20
+      The file <code>instream</code> contains the name of the stream to
21
+      read.
22
+      The frames received from this stream are send to the FlexiPix display.
23
+    </p>
24
+    <h3>FlexiPix Configuration File</h3>
25
+    <p>
26
+      The file <code>flexipix.flp</code> is the FlexiPix configuration
27
+      file used to access the FlexiPix display.
28
+      It is a standard FlexiPix configuration file as it is expected
29
+      by libflexipix.
30
+    </p>
31
+  </body>
32
+</html>
33
+
... ...
@@ -85,6 +85,7 @@
85 85
       The following module types are available for instantiation:
86 86
       <ul>
87 87
         <li><a href="canvas.html">Canvas</a></li>
88
+        <li><a href="flexipix.html">FlexiPix</a></li>
88 89
         <li><a href="output.html">Output</a></li>
89 90
         <li><a href="player.html">Player</a></li>
90 91
         <li><a href="printer.html">Printer</a></li>
... ...
@@ -0,0 +1,32 @@
1
+# FlexiPix configuration file
2
+
3
+# the address to bind the local socket to
4
+#  - the FlexiPix network 10.70.80.0/16 must be reachable from this address
5
+bindAddr = 0.0.0.0:0
6
+
7
+# the size of the display
8
+#  - <width>,<height> in pixels
9
+size = 18,8
10
+
11
+# this line adds a new distributor
12
+#  - the general format is: distributor <distributor number> = <number of outputs>,<number of pixel per output>
13
+distributor 0 = 6,64
14
+
15
+# those lines introduce a mapping between the channel values in the video and the values transmitted to the display
16
+#  - mapping is done per distributor and applies to all pixels connected to it
17
+#  - the general format is: mapping <distributor number> (red|green|blue) = <base> <factor> <gamma>
18
+#  - the mapping formula is: <display value> := <base> + <factor> * <original value> ^ (1 / <gamma>)
19
+mapping 0 red = 0.0 1.0 1.0
20
+mapping 0 green = 0.0 1.0 1.0
21
+mapping 0 blue = 0.0 1.0 1.0
22
+
23
+# these lines specify the logical positions of the pixels at an output in movie coordinates
24
+#  - the general format is: output <distributor number>,<output number> = <pixel x>,<pixel y> ...
25
+#  - the order of the pixels is the order they are connected in the chain
26
+output 0,0 = 1,0 1,1 1,2 1,3 1,4 1,5 1,6 1,7 0,7 0,6 0,5 0,4 0,3 0,2 0,1 0,0
27
+output 0,1 =
28
+output 0,2 = 2,0 2,1 2,2 2,3 2,4 2,5 2,6 2,7 3,7 3,6 3,5 3,4 3,3 3,2 3,1 3,0 4,0 4,1 4,2 4,3 4,4 4,5 4,6 4,7 5,7 5,6 5,5 5,4 5,3 5,2 5,1 5,0 6,0 6,1 6,2 6,3 6,4 6,5 6,6 6,7 7,7 7,6 7,5 7,4 7,3 7,2 7,1 7,0 8,0 8,1 8,2 8,3 8,4 8,5 8,6 8,7 9,7 9,6 9,5 9,4 9,3 9,2 9,1 9,0
29
+output 0,3 =
30
+output 0,4 = 10,0 10,1 10,2 10,3 10,4 10,5 10,6 10,7 11,7 11,6 11,5 11,4 11,3 11,2 11,1 11,0 12,0 12,1 12,2 12,3 12,4 12,5 12,6 12,7 13,7 13,6 13,5 13,4 13,3 13,2 13,1 13,0 14,0 14,1 14,2 14,3 14,4 14,5 14,6 14,7 15,7 15,6 15,5 15,4 15,3 15,2 15,1 15,0 16,0 16,1 16,2 16,3 16,4 16,5 16,6 16,7 17,7 17,6 17,5 17,4 17,3 17,2 17,1 17,0
31
+output 0,5 =
32
+
... ...
@@ -1,2 +1,3 @@
1 1
 Blinker
2
+config.mk
2 3
 deps
... ...
@@ -1,35 +1,49 @@
1
+CFGS=$(wildcard config/*.cfg.sh)
1 2
 SRCS=$(wildcard noarch/*.cpp) $(wildcard linux/*.cpp)
2 3
 TARGET=Blinker
3 4
 
4 5
 CPP=g++
6
+CONFIG=
7
+DEFINE=-DBLINKER_CONFIG="\"$(CONFIG)\""
5 8
 INCLUDE=-Inoarch -Ilinux
6 9
 CFLAGS=-Wall -Wextra -g2
7 10
 LDFLAGS=
8 11
 LIBS=-lBlinkenLib
9 12
 
13
+CFGS_BASE=$(patsubst %.cfg.sh,%,$(CFGS))
14
+CFGS_MK=$(addsuffix .cfg.mk,$(CFGS_BASE))
10 15
 SRCS_BASE=$(patsubst %.cpp,%,$(SRCS))
11 16
 DEPS=$(addsuffix .d,$(SRCS_BASE))
12 17
 OBJS=$(addsuffix .o,$(SRCS_BASE))
13 18
 
14
-.PHONY: all clean
19
+.PHONY: all clean distclean
15 20
 .SUFFIXES:
16 21
 .SECONDARY:
17 22
 
18
-all: deps $(TARGET)
23
+all: $(TARGET)
19 24
 
20 25
 ifneq ($(MAKECMDGOALS),clean)
26
+  ifneq ($(MAKECMDGOALS),distclean)
27
+    include config.mk
21 28
     include deps
22 29
   endif
30
+endif
31
+
32
+config.mk: $(CFGS_MK)
33
+	cat /dev/null $^ >$@
34
+
35
+%.cfg.mk: %.cfg.sh
36
+	sh $< >$@
23 37
 
24 38
 deps: $(DEPS)
25
-	cat /dev/null $+ >$@
39
+	cat /dev/null $^ >$@
26 40
 
27
-%.d: %.cpp Makefile
28
-	$(CPP) $(INCLUDE) $(CFLAGS) -M -o $@ $<
41
+%.d: %.cpp Makefile config.mk
42
+	$(CPP) $(DEFINE) $(INCLUDE) $(CFLAGS) -M -o $@ $<
29 43
 	sed -i 1s!^!$(dir $<)! $@
30 44
 
31 45
 %.o: %.cpp Makefile
32
-	$(CPP) $(INCLUDE) $(CFLAGS) -c -o $@ $<
46
+	$(CPP) $(DEFINE) $(INCLUDE) $(CFLAGS) -c -o $@ $<
33 47
 
34 48
 $(TARGET): $(OBJS)
35 49
 	$(CPP) $(LDFLAGS) -o $@ $+ $(LIBS)
... ...
@@ -37,3 +51,6 @@ $(TARGET): $(OBJS)
37 51
 clean:
38 52
 	rm -f deps $(DEPS) $(OBJS) $(TARGET)
39 53
 
54
+distclean: clean
55
+	rm -f config.mk $(CFGS_MK)
56
+
... ...
@@ -0,0 +1 @@
1
+*.cfg.mk
... ...
@@ -0,0 +1,6 @@
1
+if echo '#include <flexipix/flexipix.h>' | g++ - -E &>/dev/null
2
+then
3
+  echo CONFIG+=FLP
4
+  echo DEFINE+=-DBLINKER_CFG_FLEXIPIX
5
+  echo LIBS+=-lflexipix
6
+fi
... ...
@@ -0,0 +1,193 @@
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>
7
+#include <stdlib.h>
8
+#include <string>
9
+#include <string.h>
10
+
11
+#include <BlinkenLib/BlinkenFrame.h>
12
+#include <BlinkenLib/BlinkenProto.h>
13
+
14
+#ifdef BLINKER_CFG_FLEXIPIX
15
+extern "C" {
16
+#include <flexipix/flexipix.h>
17
+} // extern "C"
18
+#endif // #ifdef BLINKER_CFG_FLEIXPIX
19
+
20
+#include "CallMgr.h"
21
+#include "Directory.h"
22
+#include "File.h"
23
+#include "FlexiPix.h"
24
+#include "InStreamFile.h"
25
+#include "Module.h"
26
+#include "Size.h"
27
+#include "StreamMgr.h"
28
+#include "StreamRecv.h"
29
+#include "Time.h"
30
+#include "TimeCallee.h"
31
+
32
+namespace Blinker {
33
+
34
+/**
35
+ * @brief constructor
36
+ * @param[in] callMgr callback manager
37
+ * @param[in] streamMgr stream manager
38
+ * @param[in] dirBase base directory
39
+ */
40
+FlexiPix::FlexiPix(CallMgr &callMgr, StreamMgr &streamMgr,
41
+                 const Directory &dirBase):
42
+  Module(callMgr, streamMgr, dirBase),
43
+  m_fileInStream(dirBase.getFile("instream"), streamMgr),
44
+  m_fileConfig(dirBase.getFile("flexipix.flp")),
45
+  m_pDisplay(NULL)
46
+{
47
+  // set up
48
+  m_fileInStream.setStreamRecv(this);
49
+  createDisplay();
50
+}
51
+
52
+/// virtual destructor
53
+FlexiPix::~FlexiPix()
54
+{
55
+  // clean up
56
+  destroyDisplay();
57
+  m_fileInStream.setStreamRecv(NULL);
58
+  m_callMgr.cancelTimeCall(this);
59
+}
60
+
61
+/// check for update of configuration
62
+void FlexiPix::updateConfig()
63
+{
64
+  // input stream name file was modified -> re-get input stream
65
+  if (m_fileInStream.checkModified())
66
+    m_fileInStream.update();
67
+
68
+  // FlexiPix config file was modified -> re-create display
69
+  if (m_fileConfig.checkModified())
70
+    createDisplay();
71
+}
72
+
73
+/**
74
+ * @brief set current frame
75
+ * @param[in] stream stream name
76
+ * @param[in] pFrame current frame (NULL for none)
77
+ */
78
+void FlexiPix::setFrame(const std::string &stream, stBlinkenFrame *pFrame)
79
+{
80
+  displayFrame(pFrame);
81
+  (void)stream; // unused
82
+}
83
+
84
+/// callback when requested time reached
85
+void FlexiPix::timeCall()
86
+{
87
+  // refresh frame
88
+  sendFrame();
89
+}
90
+
91
+/// (re-)create FlexiPix display
92
+void FlexiPix::createDisplay()
93
+{
94
+#ifdef BLINKER_CFG_FLEXIPIX
95
+  destroyDisplay();
96
+
97
+  // create a display
98
+  m_pDisplay = flp_display_create(m_fileConfig.getPath().c_str(), NULL, NULL);
99
+  if (!m_pDisplay)
100
+    return;
101
+
102
+  // get size of display
103
+  flp_display_get_size(m_pDisplay, &m_size.m_width, &m_size.m_height);
104
+
105
+  // output current frame
106
+  displayFrame(m_fileInStream.getCurFrame());
107
+#endif // #ifdef BLINKER_CFG_FLEXIPIX
108
+}
109
+
110
+/// destroy FlexiPix display
111
+void FlexiPix::destroyDisplay()
112
+{
113
+#ifdef BLINKER_CFG_FLEXIPIX
114
+  if (m_pDisplay) {
115
+    flp_display_free(m_pDisplay);
116
+    m_pDisplay = NULL;
117
+  }
118
+#endif // #ifdef BLINKER_CFG_FLEXIPIX
119
+}
120
+
121
+/**
122
+ * @brief display frame on FlexiPix
123
+ * @param[in] pFrame frame to display (or NULL)
124
+ */
125
+void FlexiPix::displayFrame(stBlinkenFrame *pFrame)
126
+{
127
+#ifdef BLINKER_CFG_FLEXIPIX
128
+  char data[65536];
129
+  bool haveData = false;
130
+  stBlinkenFrame *pClonedFrame;
131
+
132
+  // leave if no display
133
+  if (!m_pDisplay)
134
+    return;
135
+
136
+  // convert frame to needed size and then to MCUF data as FlexiPix library
137
+  // can read data section of MCUF packet
138
+
139
+  // frame available
140
+  if (pFrame) {
141
+    // format matches (size matches and 24bit RGB as required by FlexiPix)
142
+    if (BlinkenFrameGetWidth(pFrame) == (int)m_size.m_width &&
143
+        BlinkenFrameGetHeight(pFrame) == (int)m_size.m_height &&
144
+        BlinkenFrameGetChannels(pFrame) == 3 &&
145
+        BlinkenFrameGetMaxval(pFrame) == 255) {
146
+      // convert to MCUF packet
147
+      haveData = BlinkenFrameToNetwork(pFrame, BlinkenProtoMcuf,
148
+                                       data, sizeof(data)) >= 0;
149
+    }
150
+    // format does not match
151
+    else {
152
+      // convert format: clone and resize
153
+      pClonedFrame = BlinkenFrameClone(pFrame);
154
+      if (pClonedFrame) {
155
+        BlinkenFrameResize(pClonedFrame, m_size.m_height,
156
+                           m_size.m_width, 3, 255);
157
+        // convert to MCUF packet
158
+        haveData = BlinkenFrameToNetwork(pFrame, BlinkenProtoMcuf,
159
+                                         data, sizeof(data)) >= 0;
160
+        // free clones frame
161
+        BlinkenFrameFree(pClonedFrame);
162
+      }
163
+    }
164
+  }
165
+
166
+  // data available -> to FlexiPix display
167
+  if (haveData)
168
+    flp_display_data(m_pDisplay, (flp_u8_t*)(data + 12), 3, m_size.m_width * 3,
169
+                     0, 0, m_size.m_width, m_size.m_height);
170
+  // no data available -> clear FlexiPix display
171
+  else
172
+    flp_display_data_clear(m_pDisplay);
173
+
174
+  // send configured frame
175
+  sendFrame();
176
+#else // #ifdef BLINKER_CFG_FLEXIPIX
177
+  (void)pFrame;
178
+#endif // #ifdef BLINKER_CFG_FLEXIPIX else
179
+}
180
+
181
+/// (re-)send frame to FlexiPix
182
+void FlexiPix::sendFrame()
183
+{
184
+#ifdef BLINKER_CFG_FLEXIPIX
185
+  if (m_pDisplay) {
186
+    flp_display_send(m_pDisplay);
187
+    m_callMgr.requestTimeCall(this, Time::now() + Time(1)); // for refresh
188
+  }
189
+#endif // #ifdef BLINKER_CFG_FLEXIPIX
190
+}
191
+
192
+} // namespace Blinker
193
+
... ...
@@ -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 BLINKER_FLEXIPIX_H
7
+#define BLINKER_FLEXIPIX_H
8
+
9
+#include <string>
10
+
11
+#include <BlinkenLib/BlinkenFrame.h>
12
+
13
+#include "CallMgr.h"
14
+#include "Directory.h"
15
+#include "File.h"
16
+#include "InStreamFile.h"
17
+#include "Module.h"
18
+#include "Size.h"
19
+#include "StreamMgr.h"
20
+#include "StreamRecv.h"
21
+#include "Time.h"
22
+#include "TimeCallee.h"
23
+
24
+namespace Blinker {
25
+
26
+/// FlexiPix output module
27
+class FlexiPix: public Module, public StreamRecv, public TimeCallee
28
+{
29
+public:
30
+  /**
31
+   * @brief constructor
32
+   * @param[in] callMgr callback manager
33
+   * @param[in] streamMgr stream manager
34
+   * @param[in] dirBase base directory
35
+   */
36
+  FlexiPix(CallMgr &callMgr, StreamMgr &streamMgr, const Directory &dirBase);
37
+
38
+  /// virtual destructor
39
+  virtual ~FlexiPix();
40
+
41
+private:
42
+  /// copy constructor disabled
43
+  FlexiPix(const FlexiPix &that);
44
+
45
+  /// assignment operator disabled
46
+  const FlexiPix & operator=(const FlexiPix &that);
47
+
48
+public:
49
+  /// check for update of configuration
50
+  virtual void updateConfig();
51
+
52
+  /**
53
+   * @brief set current frame
54
+   * @param[in] stream stream name
55
+   * @param[in] pFrame current frame (NULL for none)
56
+   */
57
+  virtual void setFrame(const std::string &stream, stBlinkenFrame *pFrame);
58
+
59
+  /// callback when requested time reached
60
+  virtual void timeCall();
61
+
62
+protected:
63
+  /// (re-)create FlexiPix display
64
+  void createDisplay();
65
+
66
+  /// destroy FlexiPix display
67
+  void destroyDisplay();
68
+
69
+  /**
70
+   * @brief display frame on FlexiPix
71
+   * @param[in] pFrame frame to display (or NULL)
72
+   */
73
+  void displayFrame(stBlinkenFrame *pFrame);
74
+
75
+  /// (re-)send frame to FlexiPix
76
+  void sendFrame();
77
+
78
+protected:
79
+  InStreamFile         m_fileInStream; ///< input stream name file
80
+  File                 m_fileConfig;   ///< FlexiPix config file
81
+  struct flp_display_s *m_pDisplay;    ///< FlexiPix display
82
+  Size                 m_size;         ///< size of FlexiPix display
83
+}; // class FlexiPix
84
+
85
+} // namespace Blinker
86
+
87
+#endif // #ifndef BLINKER_FLEXIPIX_H
88
+
... ...
@@ -9,6 +9,7 @@
9 9
 #include "CallMgr.h"
10 10
 #include "Canvas.h"
11 11
 #include "Directory.h"
12
+#include "FlexiPix.h"
12 13
 #include "ModuleMgr.h"
13 14
 #include "ModuleMgr_impl.h"
14 15
 #include "Output.h"
... ...
@@ -31,6 +32,8 @@ void run(const std::string &dirConfig)
31 32
 
32 33
   ModuleMgr<Canvas> canvasMgr(callMgr, streamMgr,
33 34
                               dirCfg.getSubdir("canvases"));
35
+  ModuleMgr<FlexiPix> flexipixMgr(callMgr, streamMgr,
36
+                                  dirCfg.getSubdir("flexipixes"));
34 37
   ModuleMgr<Output> outputMgr(callMgr, streamMgr,
35 38
                               dirCfg.getSubdir("outputs"));
36 39
   ModuleMgr<Player> playerMgr(callMgr, streamMgr,
... ...
@@ -54,7 +57,9 @@ int main(int argc, const char *argv[])
54 57
   const char * dirConfig;
55 58
 
56 59
   if (argc < 2) {
57
-    std::cerr << "usage: " << argv[0] << " config-directory" << std::endl;
60
+    std::cerr << "Blinker" << std::endl
61
+              << "configuration:"BLINKER_CONFIG << std::endl
62
+              << "usage: " << argv[0] << " config-directory" << std::endl;
58 63
     return 2;
59 64
   }
60 65
   dirConfig = argv[1];
61 66