]> git.sesse.net Git - vlc/blob - modules/video_filter/atmo/FnordlichtConnection.cpp
Use var_InheritString for --decklink-video-connection.
[vlc] / modules / video_filter / atmo / FnordlichtConnection.cpp
1 /*
2  * FnordlichtConnection.h: class to access a FnordlichtLight Hardware
3  * - the description could be found
4  * here: http://github.com/fd0/fnordlicht/raw/master/doc/PROTOCOL
5  *
6  * (C) Kai Lauterbach (klaute at gmail.com)
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  *
22  * $Id$
23  */
24
25
26 #include "AtmoDefs.h"
27 #include "FnordlichtConnection.h"
28
29 #if !defined(_ATMO_VLC_PLUGIN_)
30 # include "FnordlichtConfigDialog.h"
31 #endif
32
33 #include <stdio.h>
34 #include <fcntl.h>
35
36 #if !defined(WIN32)
37 #include <termios.h>
38 #include <unistd.h>
39 #endif
40
41 CFnordlichtConnection::CFnordlichtConnection(CAtmoConfig *cfg)
42     : CAtmoConnection(cfg)
43 {
44     m_hComport = INVALID_HANDLE_VALUE;
45 }
46
47 CFnordlichtConnection::~CFnordlichtConnection()
48 {
49 }
50
51 ATMO_BOOL CFnordlichtConnection::OpenConnection()
52 {
53 #if defined(_ATMO_VLC_PLUGIN_)
54     char *serdevice = m_pAtmoConfig->getSerialDevice();
55     if ( !serdevice )
56         return ATMO_FALSE;
57 #else
58     int portNummer = m_pAtmoConfig->getComport();
59     m_dwLastWin32Error = 0;
60     if ( portNummer < 1 )
61         return ATMO_FALSE; // make no real sense;-)
62 #endif
63
64     CloseConnection();
65
66 #if !defined(_ATMO_VLC_PLUGIN_)
67     char serdevice[16];  // com4294967295
68     sprintf(serdevice,"com%d",portNummer);
69 #endif
70
71 #if defined(WIN32)
72
73     m_hComport = CreateFile(serdevice,
74                     GENERIC_WRITE, 0, NULL,
75                     OPEN_EXISTING, 0, NULL);
76     if ( m_hComport == INVALID_HANDLE_VALUE )
77     {
78         // we have a problem here can't open com port...
79         // somebody else may use it?
80         // m_dwLastWin32Error = GetLastError();
81         return ATMO_FALSE;
82     }
83     /* change serial settings (Speed, stopbits etc.) */
84     DCB dcb; // für comport-parameter
85     dcb.DCBlength = sizeof(DCB);
86     GetCommState(m_hComport, &dcb); // ger current serialport settings
87     dcb.BaudRate = 19200;       // set speed
88     dcb.ByteSize = 8;          // set databits
89     dcb.Parity   = NOPARITY;    // set parity
90     dcb.StopBits = ONESTOPBIT;   // set one stop bit
91     SetCommState(m_hComport, &dcb);    // apply settings
92
93 #else
94
95     int bconst = B19200;
96     m_hComport = open(serdevice,O_RDWR |O_NOCTTY);
97     if ( m_hComport < 0 )
98         return ATMO_FALSE;
99
100     struct termios tio;
101     memset(&tio,0,sizeof(tio));
102     tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
103     tio.c_iflag = (INPCK | BRKINT);
104     cfsetispeed(&tio, bconst);
105     cfsetospeed(&tio, bconst);
106     if( ! tcsetattr(m_hComport, TCSANOW, &tio) )
107         tcflush(m_hComport, TCIOFLUSH);
108     else {
109         // can't change parms
110         close(m_hComport);
111         m_hComport = -1;
112         return false;
113     }
114
115 #endif
116
117     // sync fnordlicht
118     if ( sync() )
119         // stop fading on all devices
120         if ( stop(255) )
121             return true; // fnordlicht initialized...
122
123     return false; // something is going wrong...
124 }
125
126 void CFnordlichtConnection::CloseConnection()
127 {
128     if ( m_hComport != INVALID_HANDLE_VALUE )
129     {
130         reset(255);
131
132 #if defined(WIN32)
133         CloseHandle(m_hComport);
134 #else
135         close(m_hComport);
136 #endif
137         m_hComport = INVALID_HANDLE_VALUE;
138     }
139 }
140
141 ATMO_BOOL CFnordlichtConnection::isOpen(void)
142 {
143     return (m_hComport != INVALID_HANDLE_VALUE);
144 }
145
146 ATMO_BOOL CFnordlichtConnection::HardwareWhiteAdjust(int global_gamma,
147                                            int global_contrast,
148                                            int contrast_red,
149                                            int contrast_green,
150                                            int contrast_blue,
151                                            int gamma_red,
152                                            int gamma_green,
153                                            int gamma_blue,
154                                            ATMO_BOOL storeToEeprom)
155 {
156     return ATMO_FALSE; //no hardware adjust required
157 }
158
159 /*
160     def fade_rgb(addr, r, g, b, step, delay)
161        $dev.write addr.chr
162        $dev.write "\x01"
163        $dev.write step.chr
164        $dev.write delay.chr
165        $dev.write r.chr
166        $dev.write g.chr
167        $dev.write b.chr
168        $dev.write "\x00\x00\x00\x00\x00"
169        $dev.write "\x00\x00\x00"
170        $dev.flush
171     end
172 */
173 ATMO_BOOL CFnordlichtConnection::SendData(pColorPacket data)
174 {
175     if ( m_hComport == INVALID_HANDLE_VALUE )
176         return ATMO_FALSE;
177
178     int amount = getAmountFnordlichter();
179     unsigned char buffer[15];
180     memset(&buffer, 0, sizeof(buffer) ); // zero buffer
181     int iBytesWritten;
182
183     Lock();
184
185     buffer[1] = 0x01; // fade to rgb color
186     buffer[2] = 0x80; // in two steps
187     buffer[3] = 0x01; // 1ms pause between steps
188
189     // send all packages to all fnordlicht's
190     for( unsigned char i=0; i < amount; i++ )
191     {
192         int idx;
193         if ( m_ChannelAssignment && i < m_NumAssignedChannels )
194             idx = m_ChannelAssignment[i];
195         else
196             idx = -1; // no channel assigned to fnordlicht[i]
197
198         if( idx >= 0 && idx <= data->numColors )
199         {
200             // fnordlicht address equals to a MoMo Channel
201             buffer[0] = i; // fnordlicht address (0..254, 255 = broadcast)
202             buffer[4] = data->zone[idx].r;
203             buffer[5] = data->zone[idx].g;
204             buffer[6] = data->zone[idx].b;
205         }
206
207 #if defined(WIN32)
208         // send to COM-Port
209         WriteFile( m_hComport, buffer, sizeof(buffer),
210                     (DWORD*)&iBytesWritten, NULL );
211 #else
212         iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
213         tcflush(m_hComport, TCIOFLUSH);
214         tcdrain(m_hComport); // flush buffer
215 #endif
216
217         if (iBytesWritten != sizeof(buffer))
218         {
219             Unlock();
220             return ATMO_FALSE; // shouldn't be...
221         }
222
223     }
224
225     Unlock();
226
227     return ATMO_TRUE;
228 }
229
230
231 ATMO_BOOL CFnordlichtConnection::CreateDefaultMapping(CAtmoChannelAssignment *ca)
232 {
233     if ( !ca )
234         return ATMO_FALSE;
235     ca->setSize( getAmountFnordlichter() );  // oder 4 ? depending on config!
236     ca->setZoneIndex(0, 0); // Zone 5
237     ca->setZoneIndex(1, 1);
238     ca->setZoneIndex(2, 2);
239     ca->setZoneIndex(3, 3);
240     return ATMO_TRUE;
241 }
242
243 int CFnordlichtConnection::getAmountFnordlichter()
244 {
245    return m_pAtmoConfig->getFnordlicht_Amount();
246 }
247
248 /*
249     def sync(addr = 0)
250        1.upto(15) do
251           $dev.write "\e"
252        end
253        $dev.write addr.chr
254        $dev.flush
255     end
256 */
257 ATMO_BOOL CFnordlichtConnection::sync(void)
258 {
259     if ( m_hComport == INVALID_HANDLE_VALUE )
260         return ATMO_FALSE;
261
262     unsigned char buffer[16];
263
264     int iBytesWritten;
265
266     Lock();
267
268     // fill buffer with 15 escape character
269     memset(&buffer, 0x1b, sizeof(buffer)-1);
270
271     buffer[sizeof(buffer)-1] = 0x00; // append one zero byte
272
273 #if defined(WIN32)
274         // send to COM-Port
275         WriteFile( m_hComport, buffer, sizeof(buffer),
276                     (DWORD*)&iBytesWritten, NULL );
277 #else
278         iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
279         tcflush(m_hComport, TCIOFLUSH);
280         tcdrain(m_hComport); // flush buffer
281 #endif
282
283     Unlock();
284
285     return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
286
287 }
288
289 /*
290     def stop(addr, fading = 1)
291        $dev.write addr.chr
292        $dev.write "\x08"
293        $dev.write fading.chr
294        $dev.write "\x00\x00\x00\x00"
295        $dev.write "\x00\x00\x00\x00\x00"
296        $dev.write "\x00\x00\x00"
297        $dev.flush
298     end
299 */
300 ATMO_BOOL CFnordlichtConnection::stop(unsigned char addr)
301 {
302     if(m_hComport == INVALID_HANDLE_VALUE)
303         return ATMO_FALSE;
304
305     unsigned char buffer[15];
306     memset(&buffer, 0, sizeof(buffer)); // zero buffer
307     int iBytesWritten;
308
309     Lock();
310
311     buffer[0] = addr; // fnordlicht address (255 = broadcast)
312     buffer[1] = 0x08; // stop command
313     buffer[2] = 1;    // fading
314
315 #if defined(WIN32)
316         // send to COM-Port
317         WriteFile( m_hComport, buffer, sizeof(buffer),
318                     (DWORD*)&iBytesWritten, NULL );
319 #else
320         iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
321         tcflush(m_hComport, TCIOFLUSH);
322         tcdrain(m_hComport); // flush buffer
323 #endif
324
325     Unlock();
326
327     return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
328 }
329
330 /*
331 */
332 ATMO_BOOL CFnordlichtConnection::reset(unsigned char addr)
333 {
334     if(m_hComport == INVALID_HANDLE_VALUE)
335         return ATMO_FALSE;
336
337     stop(255);
338
339     if ( sync() && start_bootloader(addr) )
340     {
341 #if defined(_ATMO_VLC_PLUGIN_)
342         do_sleep(200000); // wait 200ms
343 #else
344         do_sleep(200); // wait 200ms
345 #endif
346         if ( sync() && boot_enter_application(addr) )
347                 return ATMO_TRUE;
348     }
349
350     return ATMO_FALSE;
351 }
352
353 /*
354     def start_bootloader(addr)
355         $dev.write(addr.chr)
356         $dev.write("\x80")
357         $dev.write("\x6b\x56\x27\xfc")
358         $dev.write("\x00\x00\x00\x00\x00\x00\x00\x00\x00")
359         $dev.flush
360     end
361 */
362 ATMO_BOOL CFnordlichtConnection::start_bootloader(unsigned char addr)
363 {
364     if(m_hComport == INVALID_HANDLE_VALUE)
365         return ATMO_FALSE;
366
367     unsigned char buffer[15];
368     memset(&buffer, 0, sizeof(buffer)); // zero buffer
369     int iBytesWritten;
370
371     Lock();
372
373     buffer[0] = addr; // fnordlicht address (255 = broadcast)
374     buffer[1] = 0x80; // start_bootloader
375     buffer[2] = 0x6b;
376     buffer[3] = 0x56;
377     buffer[4] = 0x27;
378     buffer[5] = 0xfc;
379
380 #if defined(WIN32)
381         // send to COM-Port
382         WriteFile( m_hComport, buffer, sizeof(buffer),
383                     (DWORD*)&iBytesWritten, NULL );
384 #else
385         iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
386         tcflush(m_hComport, TCIOFLUSH);
387         tcdrain(m_hComport); // flush buffer
388 #endif
389
390     Unlock();
391
392     return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
393 }
394
395 /*
396     def boot_enter_application(addr)
397         $dev.write(addr.chr)
398         $dev.write("\x87")
399         $dev.write("\x00"*13)
400         $dev.flush
401     end
402 */
403 ATMO_BOOL CFnordlichtConnection::boot_enter_application(unsigned char addr)
404 {
405     if(m_hComport == INVALID_HANDLE_VALUE)
406         return ATMO_FALSE;
407
408     unsigned char buffer[15];
409     memset(&buffer, 0, sizeof(buffer)); // zero buffer
410     int iBytesWritten;
411
412     Lock();
413
414     buffer[0] = addr; // fnordlicht address (255 = broadcast)
415     buffer[1] = 0x87; // boot_ender_application command
416
417 #if defined(WIN32)
418         // send to COM-Port
419         WriteFile( m_hComport, buffer, sizeof(buffer),
420                     (DWORD*)&iBytesWritten, NULL );
421 #else
422         iBytesWritten = write(m_hComport, buffer, sizeof(buffer));
423         tcflush(m_hComport, TCIOFLUSH);
424         tcdrain(m_hComport); // flush buffer
425 #endif
426
427     Unlock();
428
429     return (iBytesWritten == sizeof(buffer)) ? ATMO_TRUE : ATMO_FALSE;
430 }
431
432 #if !defined(_ATMO_VLC_PLUGIN_)
433
434 char *CFnordlichtConnection::getChannelName(int ch)
435 {
436     char buf[60];
437     if( ch < 0 ) return NULL;
438     if( ch >= getAmountFnordlichter() ) return NULL;
439
440     sprintf(buf,"Number [%d]",ch);
441     return strdup(buf);
442     // sorry asprintf is not defined on Visual Studio :)
443     // return (asprintf(&ret, "Number [%d]", ch) != -1) ? ret : NULL;
444
445 }
446
447 ATMO_BOOL CFnordlichtConnection::ShowConfigDialog(HINSTANCE hInst, HWND parent,
448                                                     CAtmoConfig *cfg)
449 {
450     CFnordlichtConfigDialog *dlg = new CFnordlichtConfigDialog(hInst,
451                                                                 parent,
452                                                                 cfg);
453
454     INT_PTR result = dlg->ShowModal();
455
456     delete dlg;
457
458     if(result == IDOK)
459         return ATMO_TRUE;
460     else
461         return ATMO_FALSE;
462 }
463
464 #endif