]> git.sesse.net Git - vlc/blob - modules/video_filter/atmo/AtmoMultiConnection.cpp
Use var_InheritString for --decklink-video-connection.
[vlc] / modules / video_filter / atmo / AtmoMultiConnection.cpp
1 /*
2  * AtmoMultiConnection.cpp: Class for communication with up to 4 - 4 channel classic atmolight controllers
3  * so you can built a cheap solution for having up to 16 channels
4  *
5  * See the README.txt file for copyright information and how to reach the author(s).
6  *
7  * $Id$
8  */
9
10 #include "AtmoDefs.h"
11 #include "AtmoMultiConnection.h"
12
13 #if !defined(_ATMO_VLC_PLUGIN_)
14 #include "AtmoMultiConfigDialog.h"
15 #endif
16
17 #include <stdio.h>
18 #include <fcntl.h>
19
20 #if !defined(WIN32)
21 #include <termios.h>
22 #include <unistd.h>
23 #endif
24
25
26
27 CAtmoMultiConnection::CAtmoMultiConnection(CAtmoConfig *cfg) : CAtmoConnection(cfg)
28 {
29    m_hComports[0] = INVALID_HANDLE_VALUE;
30    m_hComports[1] = INVALID_HANDLE_VALUE;
31    m_hComports[2] = INVALID_HANDLE_VALUE;
32    m_hComports[3] = INVALID_HANDLE_VALUE;
33    memset(&m_output, 0, sizeof(m_output));
34 }
35
36 CAtmoMultiConnection::~CAtmoMultiConnection(void)
37 {
38 }
39
40 HANDLE CAtmoMultiConnection::OpenDevice(char *devName)
41 {
42      HANDLE hComport;
43
44 #if !defined(_ATMO_VLC_PLUGIN_)
45      m_dwLastWin32Error = 0;
46 #endif
47
48 #if defined(WIN32)
49      hComport = CreateFile(devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
50      if(hComport == INVALID_HANDLE_VALUE) {
51 #if !defined(_ATMO_VLC_PLUGIN_)
52             m_dwLastWin32Error = GetLastError();
53 #endif
54             return INVALID_HANDLE_VALUE;
55      }
56      /* change serial settings (Speed, stopbits etc.) */
57      DCB dcb; // für comport-parameter
58      dcb.DCBlength = sizeof(DCB);
59      GetCommState (hComport, &dcb); // ger current serialport settings
60      dcb.BaudRate  = 38400;        // set speed
61      dcb.ByteSize  = 8;            // set databits
62      dcb.Parity    = NOPARITY;     // set parity
63      dcb.StopBits  = ONESTOPBIT;   // set one stop bit
64      SetCommState (hComport, &dcb);    // apply settings
65
66 #else
67
68      int bconst = B38400;
69      hComport = open(devName,O_RDWR |O_NOCTTY);
70      if(hComport < 0) {
71             return INVALID_HANDLE_VALUE;;
72      }
73      struct termios tio;
74      memset(&tio,0,sizeof(tio));
75      tio.c_cflag = (CS8 | CREAD | HUPCL | CLOCAL);
76      tio.c_iflag = (INPCK | BRKINT);
77      cfsetispeed(&tio, bconst);
78      cfsetospeed(&tio, bconst);
79      if(!tcsetattr(hComport, TCSANOW, &tio)) {
80          tcflush(hComport, TCIOFLUSH);
81      } else {
82          // can't change parms
83         close(hComport);
84         return INVALID_HANDLE_VALUE;
85      }
86 #endif
87
88      return hComport;
89 }
90
91 ATMO_BOOL CAtmoMultiConnection::OpenConnection()
92 {
93     int z = 0;
94 #if defined(_ATMO_VLC_PLUGIN_)
95
96     for(int c = 0; c < 4; c++ ) {
97         char *devName = m_pAtmoConfig->getSerialDevice( c );
98         if( devName && strlen(devName) > 0 )
99         {
100             m_hComports[z] = OpenDevice( devName );
101             if(m_hComports[z] == INVALID_HANDLE_VALUE) {
102                 while(z) {
103                       z--;
104 #if defined(WIN32)
105                       CloseHandle( m_hComports[z] );
106 #else
107                       close( m_hComports[z] );
108 #endif
109                       m_hComports[z] = INVALID_HANDLE_VALUE;
110                 }
111                 return ATMO_FALSE;
112             }
113             z++;
114         }
115     }
116
117
118 #else
119
120     char devName[16];
121
122     for(int c = 0; c < 4; c++ ) {
123         int comportnr = m_pAtmoConfig->getComport(c);
124         if(comportnr > 0)
125         {
126             sprintf(devName,"com%d",comportnr);
127             m_hComports[z] = OpenDevice(devName);
128             if(m_hComports[z] == INVALID_HANDLE_VALUE) {
129                 while(z) {
130                       z--;
131                       CloseHandle( m_hComports[z] );
132                       m_hComports[z] = INVALID_HANDLE_VALUE;
133                 }
134                 return ATMO_FALSE;
135             }
136             z++;
137         }
138     }
139 #endif
140     return ATMO_TRUE;
141 }
142
143 void CAtmoMultiConnection::CloseConnection() {
144     for(int i = 0; i < 4; i++ ) {
145         if(m_hComports[i] != INVALID_HANDLE_VALUE) {
146 #if defined(WIN32)
147            CloseHandle( m_hComports[i] );
148 #else
149            close( m_hComports[i] );
150 #endif
151                m_hComports[i] = INVALID_HANDLE_VALUE;
152         }
153     }
154 }
155
156 ATMO_BOOL CAtmoMultiConnection::isOpen(void) {
157      int z = 0;
158      for(int i = 0; i < 4; i++ )
159          if(m_hComports[i] != INVALID_HANDLE_VALUE) z++;
160
161          return (z > 0);
162 }
163
164 int CAtmoMultiConnection::getNumChannels()
165 {
166     int z = 0;
167 #if defined(_ATMO_VLC_PLUGIN_)
168     char *psz_dev;
169     for(int i=0;i<4;i++) {
170         psz_dev = m_pAtmoConfig->getSerialDevice( i );
171         if( psz_dev && strlen( psz_dev ) > 0 )
172             z+=4;
173     }
174 #else
175     for(int i=0;i<4;i++)
176         if(m_pAtmoConfig->getComport(i)>0)
177            z+=4;
178 #endif
179     return z;
180 }
181
182 ATMO_BOOL CAtmoMultiConnection::CreateDefaultMapping(CAtmoChannelAssignment *ca)
183 {
184   if(!ca) return ATMO_FALSE;
185   int z = getNumChannels();
186   ca->setSize( z );
187   // 1 : 1 mapping vorschlagen...
188   for(int i = 0; i < z ; i++ ) {
189       ca->setZoneIndex( i, i );
190   }
191   return ATMO_TRUE;
192 }
193
194
195 ATMO_BOOL CAtmoMultiConnection::internal_HardwareWhiteAdjust(HANDLE hComport,
196                                                      int global_gamma,
197                                                      int global_contrast,
198                                                      int contrast_red,
199                                                      int contrast_green,
200                                                      int contrast_blue,
201                                                      int gamma_red,
202                                                      int gamma_green,
203                                                      int gamma_blue,
204                                                      ATMO_BOOL storeToEeprom) {
205   if(hComport == INVALID_HANDLE_VALUE)
206      return ATMO_FALSE;
207
208      DWORD iBytesWritten;
209 /*
210 [0] = 255
211 [1] = 00
212 [2] = 00
213 [3] = 101
214
215 [4]  brightness  0..255 ?
216
217 [5]  Contrast Red     11 .. 100
218 [6]  Contrast  Green  11 .. 100
219 [7]  Contrast  Blue   11 .. 100
220
221 [8]   Gamma Red    11 .. 35
222 [9]   Gamma Red    11 .. 35
223 [10]  Gamma Red    11 .. 35
224
225 [11]  Globale Contrast  11 .. 100
226
227 [12]  Store Data: 199 (else 0)
228
229 */
230      unsigned char sendBuffer[16];
231      sendBuffer[0] = 0xFF;
232      sendBuffer[1] = 0x00;
233      sendBuffer[2] = 0x00;
234      sendBuffer[3] = 101;
235
236      sendBuffer[4] = (global_gamma & 255);
237
238      sendBuffer[5] = (contrast_red & 255);
239      sendBuffer[6] = (contrast_green & 255);
240      sendBuffer[7] = (contrast_blue & 255);
241
242      sendBuffer[8]  = (gamma_red & 255);
243      sendBuffer[9]  = (gamma_green & 255);
244      sendBuffer[10] = (gamma_blue & 255);
245
246      sendBuffer[11] = (global_contrast & 255);
247
248      if(storeToEeprom == ATMO_TRUE)
249         sendBuffer[12] = 199; // store to eeprom!
250      else
251         sendBuffer[12] = 0;
252
253 #if defined(WIN32)
254      WriteFile(hComport, sendBuffer, 13, &iBytesWritten, NULL); // send to COM-Port
255 #else
256      iBytesWritten = write(hComport, sendBuffer, 13);
257      tcdrain(hComport);
258 #endif
259
260      return (iBytesWritten == 13) ? ATMO_TRUE : ATMO_FALSE;
261 }
262
263
264 ATMO_BOOL CAtmoMultiConnection::HardwareWhiteAdjust( int global_gamma,
265                                                      int global_contrast,
266                                                      int contrast_red,
267                                                      int contrast_green,
268                                                      int contrast_blue,
269                                                      int gamma_red,
270                                                      int gamma_green,
271                                                      int gamma_blue,
272                                                      ATMO_BOOL storeToEeprom)
273 {
274     for(int z = 0 ; z < 4; z++ ) {
275         if(m_hComports[z]!= INVALID_HANDLE_VALUE)
276            if(internal_HardwareWhiteAdjust(m_hComports[z], global_gamma, global_contrast,
277                                            contrast_red, contrast_green, contrast_blue,
278                                            gamma_red, gamma_green, gamma_blue,
279                                            storeToEeprom) == ATMO_FALSE)
280                                                 return ATMO_FALSE;
281     }
282     return ATMO_TRUE;
283 }
284
285 ATMO_BOOL CAtmoMultiConnection::internal_SendData(HANDLE hComport, unsigned char *colorData)
286 {
287  if(m_hComports[0] == INVALID_HANDLE_VALUE)
288     return ATMO_FALSE;
289
290   unsigned char buffer[19];
291   DWORD iBytesWritten;
292
293   buffer[0] = 0xFF;  // Start Byte
294   buffer[1] = 0x00;  // Start channel 0
295   buffer[2] = 0x00;  // Start channel 0
296   buffer[3] = 15; //
297   buffer[4] = 0; // Summe Red
298   buffer[5] = 0; // Summe Green
299   buffer[6] = 0; // Summe Blue
300   memcpy(&buffer[7], colorData, 4 * 3);
301
302 #if defined(WIN32)
303    WriteFile(hComport, buffer, 19, &iBytesWritten, NULL); // send to COM-Port
304 #else
305    iBytesWritten = write(hComport, buffer, 19);
306    tcdrain(hComport);
307 #endif
308
309  return (iBytesWritten == 19) ? ATMO_TRUE : ATMO_FALSE;
310 }
311
312 ATMO_BOOL CAtmoMultiConnection::SendData(pColorPacket data)
313 {
314    if(m_hComports[0] == INVALID_HANDLE_VALUE)
315           return ATMO_FALSE;
316
317    int numChannels = this->getNumChannels();
318
319    int idx;
320    int iBuffer = 0;
321    ATMO_BOOL result = ATMO_TRUE;
322
323    Lock();
324
325    for(int i = 0; i < numChannels ; i++) {
326        if(m_ChannelAssignment && (i < m_NumAssignedChannels))
327           idx = m_ChannelAssignment[i];
328        else
329           idx = -1;
330        if((idx>=0) && (idx<data->numColors)) {
331           m_output[iBuffer] = data->zone[idx].r;
332           m_output[iBuffer+1] = data->zone[idx].g;
333           m_output[iBuffer+2] = data->zone[idx].b;
334        }
335        iBuffer+=3;
336    }
337    for(int i = 0;i < 4; i++)
338        if(m_hComports[i] != INVALID_HANDLE_VALUE)
339           result = result & internal_SendData(m_hComports[i], &m_output[i*4*3]);
340
341    Unlock();
342
343    return result;
344 }
345
346 ATMO_BOOL CAtmoMultiConnection::setChannelColor(int channel, tRGBColor color)
347 {
348    if(m_hComports[0] == INVALID_HANDLE_VALUE)
349           return ATMO_FALSE;
350    if((channel < 0) || (channel >= getNumChannels()))
351       return ATMO_FALSE;
352
353    ATMO_BOOL result = ATMO_TRUE;
354
355    Lock();
356    channel*=3;
357    m_output[channel++] = color.r;
358    m_output[channel++] = color.g;
359    m_output[channel]   = color.b;
360    for(int i = 0; i < 4; i++)
361        if(m_hComports[i] != INVALID_HANDLE_VALUE)
362           result = result & internal_SendData(m_hComports[i], &m_output[i*4*3]);
363    Unlock();
364
365    return result;
366 }
367
368 ATMO_BOOL CAtmoMultiConnection::setChannelValues(int numValues,unsigned char *channel_values)
369 {
370   if(m_hComports[0] == INVALID_HANDLE_VALUE)
371      return ATMO_FALSE;
372
373   if((numValues & 1) || !channel_values)
374      return ATMO_FALSE; // numValues must be even!
375
376   ATMO_BOOL result = ATMO_TRUE;
377
378
379   Lock();
380   int Index = 0;
381   for (int i = 0; i < numValues; i+=2) {
382        Index = (int)channel_values[i];
383        if(Index < sizeof(m_output))
384           m_output[Index] = channel_values[i + 1];
385   }
386   for(int i = 0; i < 4; i++)
387       if(m_hComports[i] != INVALID_HANDLE_VALUE)
388          result = result & internal_SendData(m_hComports[i], &m_output[i*4*3]);
389
390   Unlock();
391   return result;
392 }
393
394 #if !defined(_ATMO_VLC_PLUGIN_)
395
396 char *CAtmoMultiConnection::getChannelName(int ch)
397 {
398   int devnum = ch / 4;
399   int kanal  = ch % 4;
400   char buf[60];
401   switch(kanal) {
402          case 0: {
403                    sprintf(buf,"Atmo[%d.%d] Links (%d)", devnum, kanal, ch);
404                    break;
405                  }
406          case 1: {
407                    sprintf(buf,"Atmo[%d.%d] Rechts (%d)", devnum, kanal, ch);
408                    break;
409                  }
410          case 2: {
411                    sprintf(buf,"Atmo[%d.%d] Oben (%d)", devnum, kanal, ch);
412                    break;
413                  }
414          case 3: {
415                    sprintf(buf,"Atmo[%d.%d] Unten (%d)", devnum, kanal, ch);
416                    break;
417                  }
418   }
419   return strdup(buf);
420 }
421
422 ATMO_BOOL CAtmoMultiConnection::ShowConfigDialog(HINSTANCE hInst, HWND parent, CAtmoConfig *cfg)
423 {
424     CAtmoMultiConfigDialog *dlg = new CAtmoMultiConfigDialog(hInst, parent, cfg);
425
426     INT_PTR result = dlg->ShowModal();
427
428     delete dlg;
429
430     if(result == IDOK)
431       return ATMO_TRUE;
432     else
433       return ATMO_FALSE;
434 }
435
436 #endif
437