]> git.sesse.net Git - vlc/blob - modules/video_filter/atmo/AtmoTools.cpp
Revert "atmo: add support for new device fnordlicht"
[vlc] / modules / video_filter / atmo / AtmoTools.cpp
1 /*
2  * AtmoTools.cpp: Collection of tool and helperfunction
3  *
4  * See the README.txt file for copyright information and how to reach the author(s).
5  *
6  * $Id$
7  */
8
9 #include "AtmoTools.h"
10 #include "AtmoDynData.h"
11 #include "AtmoLiveView.h"
12 #include "AtmoClassicConnection.h"
13 #include "AtmoDmxSerialConnection.h"
14 #include "AtmoMultiConnection.h"
15 #include "MoMoConnection.h"
16 #include "AtmoExternalCaptureInput.h"
17 #include <math.h>
18
19 #if !defined(_ATMO_VLC_PLUGIN_)
20 #   include "AtmoColorChanger.h"
21 #   include "AtmoLeftRightColorChanger.h"
22
23 #   include "AtmoDummyConnection.h"
24 #   include "AtmoNulConnection.h"
25 #   include "MondolightConnection.h"
26
27 #   include "AtmoGdiDisplayCaptureInput.h"
28 #endif
29
30
31 CAtmoTools::CAtmoTools(void)
32 {
33 }
34
35 CAtmoTools::~CAtmoTools(void)
36 {
37 }
38
39 void CAtmoTools::ShowShutdownColor(CAtmoDynData *pDynData)
40 {
41     pDynData->LockCriticalSection();
42
43
44     CAtmoConnection *atmoConnection = pDynData->getAtmoConnection();
45     CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
46     if((atmoConnection != NULL) && (atmoConfig!=NULL) && atmoConfig->isSetShutdownColor()) {
47        int i;
48        pColorPacket packet;
49        AllocColorPacket(packet, atmoConfig->getZoneCount());
50
51        // set a special color? on shutdown of the software? mostly may use black or so ...
52        // if this function ist disabled ... atmo will continuing to show the last color...
53        for(i = 0; i < packet->numColors; i++) {
54            packet->zone[i].r = atmoConfig->getShutdownColor_Red();
55            packet->zone[i].g = atmoConfig->getShutdownColor_Green();
56            packet->zone[i].b = atmoConfig->getShutdownColor_Blue();
57        }
58
59        packet = CAtmoTools::ApplyGamma(atmoConfig, packet);
60
61        if(atmoConfig->isUseSoftwareWhiteAdj())
62           packet = CAtmoTools::WhiteCalibration(atmoConfig, packet);
63
64        atmoConnection->SendData(packet);
65
66        delete (char *)packet;
67
68         }
69
70     pDynData->UnLockCriticalSection();
71 }
72
73 EffectMode CAtmoTools::SwitchEffect(CAtmoDynData *pDynData, EffectMode newEffectMode)
74 {
75     // may need a critical section??
76     if(pDynData == NULL) {
77        return emUndefined;
78     }
79     pDynData->LockCriticalSection();
80
81     CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
82     if(atmoConfig == NULL) {
83        pDynData->UnLockCriticalSection();
84        return emUndefined;
85     }
86     CAtmoConnection *atmoConnection = pDynData->getAtmoConnection();
87
88     EffectMode oldEffectMode = atmoConfig->getEffectMode();
89     CThread *currentEffect = pDynData->getEffectThread();
90     CAtmoInput *currentInput = pDynData->getLiveInput();
91     CAtmoPacketQueue *currentPacketQueue = pDynData->getLivePacketQueue();
92
93
94     if(oldEffectMode == emLivePicture) {
95         /* in case of disabling the live mode
96            first we have to stop the input
97            then the effect thread!
98         */
99         if(currentInput != NULL) {
100            pDynData->setLiveInput( NULL );
101            currentInput->Close();
102            delete currentInput;
103            currentInput = NULL;
104         }
105     }
106
107     // stop and delete/cleanup current Effect Thread...
108     pDynData->setEffectThread( NULL );
109     if(currentEffect != NULL) {
110        currentEffect->Terminate();
111        delete currentEffect;
112        currentEffect = NULL;
113     }
114
115     if(oldEffectMode == emLivePicture) {
116        /*
117          and last we kill the PacketQueue used for communication between the threads
118        */
119        pDynData->setLivePacketQueue( NULL );
120        delete currentPacketQueue;
121        currentPacketQueue = NULL;
122     }
123
124     if((atmoConnection!=NULL) && (atmoConnection->isOpen()==ATMO_TRUE)) {
125         // neuen EffectThread nur mit aktiver Connection starten...
126
127         switch(newEffectMode) {
128             case emDisabled:
129                 break;
130
131             case emStaticColor: {
132                  // get values from config - and put them to all channels?
133                  pColorPacket packet;
134                  AllocColorPacket(packet, atmoConfig->getZoneCount());
135                  for(int i=0; i < packet->numColors; i++){
136                      packet->zone[i].r = atmoConfig->getStaticColor_Red();
137                      packet->zone[i].g = atmoConfig->getStaticColor_Green();
138                      packet->zone[i].b = atmoConfig->getStaticColor_Blue();
139                  }
140
141                  packet = CAtmoTools::ApplyGamma( atmoConfig, packet );
142
143                  if(atmoConfig->isUseSoftwareWhiteAdj())
144                     packet = CAtmoTools::WhiteCalibration(atmoConfig, packet);
145
146                  atmoConnection->SendData( packet );
147
148                  delete (char *)packet;
149
150                  break;
151              }
152
153             case emLivePicture: {
154                 currentEffect = new CAtmoLiveView(pDynData);
155
156 #if !defined(_ATMO_VLC_PLUGIN_)
157                 CAtmoPacketQueueStatus *packetMon = NULL;
158                 if(atmoConfig->getShow_statistics()) {
159                    packetMon = new CAtmoPacketQueueStatus(pDynData->getHinstance(), (HWND)NULL);
160                    packetMon->createWindow();
161                    packetMon->showWindow(SW_SHOW);
162                 }
163                 currentPacketQueue = new CAtmoPacketQueue(packetMon);
164                 pDynData->setLivePictureSource(lpsScreenCapture);
165                 currentInput = new CAtmoGdiDisplayCaptureInput( pDynData );
166 #else
167                 currentPacketQueue = new CAtmoPacketQueue();
168                 pDynData->setLivePictureSource(lpsExtern);
169                 currentInput = new CAtmoExternalCaptureInput( pDynData );
170 #endif
171                 break;
172             }
173
174 #if !defined(_ATMO_VLC_PLUGIN_)
175             case emColorChange:
176                 currentEffect = new CAtmoColorChanger(atmoConnection, atmoConfig);
177                 break;
178
179             case emLrColorChange:
180                 currentEffect = new CAtmoLeftRightColorChanger(atmoConnection, atmoConfig);
181                 break;
182 #endif
183         }
184
185     }
186
187     atmoConfig->setEffectMode( newEffectMode );
188
189     pDynData->setLivePacketQueue( currentPacketQueue );
190     pDynData->setEffectThread( currentEffect );
191     pDynData->setLiveInput( currentInput );
192
193     if(currentEffect != NULL)
194        currentEffect->Run();
195     if(currentInput != NULL)
196        currentInput->Open();
197
198     pDynData->UnLockCriticalSection();
199     return oldEffectMode;
200 }
201
202 LivePictureSource CAtmoTools::SwitchLiveSource(CAtmoDynData *pDynData, LivePictureSource newLiveSource)
203 {
204     LivePictureSource oldSource;
205     pDynData->LockCriticalSection();
206
207     oldSource = pDynData->getLivePictureSource();
208     pDynData->setLivePictureSource( newLiveSource );
209
210     if ((pDynData->getAtmoConfig()->getEffectMode() == emLivePicture) &&
211         (pDynData->getEffectThread() != NULL) &&
212         (pDynData->getLivePacketQueue() != NULL))
213     {
214         CAtmoInput *input = pDynData->getLiveInput();
215         pDynData->setLiveInput( NULL );
216         if(input != NULL) {
217             input->Close();
218             delete input;
219             input = NULL;
220         }
221
222         switch(pDynData->getLivePictureSource()) {
223 #if !defined(_ATMO_VLC_PLUGIN_)
224                case lpsScreenCapture:
225                     input = new CAtmoGdiDisplayCaptureInput( pDynData );
226                break;
227 #endif
228                case lpsExtern:
229                     input = new CAtmoExternalCaptureInput( pDynData );
230                break;
231         }
232
233         pDynData->setLiveInput( input );
234         if(input != NULL)
235            input->Open();
236     }
237
238     pDynData->UnLockCriticalSection();
239     return oldSource;
240 }
241
242 ATMO_BOOL CAtmoTools::RecreateConnection(CAtmoDynData *pDynData)
243 {
244     pDynData->LockCriticalSection();
245
246     CAtmoConnection *current = pDynData->getAtmoConnection();
247     CAtmoConfig *atmoConfig = pDynData->getAtmoConfig();
248     AtmoConnectionType act = atmoConfig->getConnectionType();
249     pDynData->setAtmoConnection(NULL);
250     if(current != NULL) {
251        current->CloseConnection();
252        delete current;
253     }
254
255     switch(act) {
256            case actClassicAtmo: {
257                CAtmoClassicConnection *tempConnection = new CAtmoClassicConnection( atmoConfig );
258                if(tempConnection->OpenConnection() == ATMO_FALSE) {
259 #if !defined(_ATMO_VLC_PLUGIN_)
260                   if(atmoConfig->getIgnoreConnectionErrorOnStartup() == ATMO_FALSE)
261                   {
262                         char errorMsgBuf[200];
263                         sprintf(errorMsgBuf,"Failed to open serial port com%d with errorcode: %d (0x%x)",
264                                     pDynData->getAtmoConfig()->getComport(),
265                                     tempConnection->getLastError(),
266                                     tempConnection->getLastError()
267                                 );
268                         MessageBox(0,errorMsgBuf,"Error",MB_ICONERROR | MB_OK);
269                   }
270 #endif
271                   pDynData->setAtmoConnection(tempConnection);
272
273                   pDynData->UnLockCriticalSection();
274                   return ATMO_FALSE;
275                }
276                pDynData->setAtmoConnection(tempConnection);
277                pDynData->ReloadZoneDefinitionBitmaps();
278
279                tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
280
281                CAtmoTools::SetChannelAssignment(pDynData,
282                                                 atmoConfig->getCurrentChannelAssignment());
283
284                pDynData->UnLockCriticalSection();
285                return ATMO_TRUE;
286            }
287
288 #if !defined(_ATMO_VLC_PLUGIN_)
289            case actDummy:
290            {
291                // actDummy8,actDummy12,actDummy16
292                CAtmoDummyConnection *tempConnection = new CAtmoDummyConnection(pDynData->getHinstance(),
293                                                                                atmoConfig);
294                if(tempConnection->OpenConnection() == ATMO_FALSE) {
295                   pDynData->setAtmoConnection(tempConnection);
296                   pDynData->UnLockCriticalSection();
297                   return ATMO_FALSE;
298                }
299                pDynData->setAtmoConnection(tempConnection);
300                pDynData->ReloadZoneDefinitionBitmaps();
301
302                tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
303
304                CAtmoTools::SetChannelAssignment(pDynData, pDynData->getAtmoConfig()->getCurrentChannelAssignment());
305
306                pDynData->UnLockCriticalSection();
307                return ATMO_TRUE;
308            }
309 #endif
310
311            case actDMX: {
312                // create here your DMX connections... instead of the dummy....
313                CAtmoDmxSerialConnection *tempConnection = new CAtmoDmxSerialConnection( atmoConfig );
314                if(tempConnection->OpenConnection() == ATMO_FALSE) {
315                   pDynData->setAtmoConnection(tempConnection);
316
317                   pDynData->UnLockCriticalSection();
318                   return ATMO_FALSE;
319                }
320                pDynData->setAtmoConnection(tempConnection);
321                pDynData->ReloadZoneDefinitionBitmaps();
322
323                tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
324
325                CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment());
326
327                pDynData->UnLockCriticalSection();
328                return ATMO_TRUE;
329            }
330
331 #if !defined(_ATMO_VLC_PLUGIN_)
332            case actNUL: {
333                CAtmoNulConnection *tempConnection = new CAtmoNulConnection( atmoConfig );
334                if(tempConnection->OpenConnection() == ATMO_FALSE) {
335                   pDynData->setAtmoConnection(tempConnection);
336                   pDynData->UnLockCriticalSection();
337                   return ATMO_FALSE;
338                }
339                pDynData->setAtmoConnection(tempConnection);
340                pDynData->ReloadZoneDefinitionBitmaps();
341
342                tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
343
344                CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment());
345
346                pDynData->UnLockCriticalSection();
347                return ATMO_TRUE;
348            }
349 #endif
350
351            case actMultiAtmo: {
352                CAtmoMultiConnection *tempConnection = new CAtmoMultiConnection( atmoConfig );
353                if(tempConnection->OpenConnection() == ATMO_FALSE) {
354                   pDynData->setAtmoConnection(tempConnection);
355                   pDynData->UnLockCriticalSection();
356                   return ATMO_FALSE;
357                }
358                pDynData->setAtmoConnection(tempConnection);
359                pDynData->ReloadZoneDefinitionBitmaps();
360
361                tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
362
363                CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment());
364
365                pDynData->UnLockCriticalSection();
366                return ATMO_TRUE;
367            }
368
369 #if !defined(_ATMO_VLC_PLUGIN_)
370            case actMondolight: {
371                CMondolightConnection *tempConnection = new CMondolightConnection( atmoConfig );
372                if(tempConnection->OpenConnection() == ATMO_FALSE) {
373                   pDynData->setAtmoConnection(tempConnection);
374                   pDynData->UnLockCriticalSection();
375                   return ATMO_FALSE;
376                }
377                pDynData->setAtmoConnection(tempConnection);
378                pDynData->ReloadZoneDefinitionBitmaps();
379
380                tempConnection->CreateDefaultMapping(atmoConfig->getChannelAssignment(0));
381
382                CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment());
383
384                pDynData->UnLockCriticalSection();
385                return ATMO_TRUE;
386            }
387 #endif
388            case actMoMoLight: {
389                CMoMoConnection *tempConnection = new CMoMoConnection( atmoConfig );
390                if(tempConnection->OpenConnection() == ATMO_FALSE) {
391                   pDynData->setAtmoConnection(tempConnection);
392                   pDynData->UnLockCriticalSection();
393                   return ATMO_FALSE;
394                }
395                pDynData->setAtmoConnection(tempConnection);
396                pDynData->ReloadZoneDefinitionBitmaps();
397
398                tempConnection->CreateDefaultMapping( atmoConfig->getChannelAssignment(0) );
399
400                CAtmoTools::SetChannelAssignment(pDynData, atmoConfig->getCurrentChannelAssignment() );
401
402                pDynData->UnLockCriticalSection();
403                return ATMO_TRUE;
404            }
405
406            default: {
407                pDynData->UnLockCriticalSection();
408                return ATMO_FALSE;
409            }
410     }
411 }
412
413 pColorPacket CAtmoTools::WhiteCalibration(CAtmoConfig *pAtmoConfig, pColorPacket ColorPacket)
414 {
415     int w_adj_red   = pAtmoConfig->getWhiteAdjustment_Red();
416     int w_adj_green = pAtmoConfig->getWhiteAdjustment_Green();
417     int w_adj_blue  = pAtmoConfig->getWhiteAdjustment_Blue();
418
419     for (int i = 0; i < ColorPacket->numColors; i++)  {
420         ColorPacket->zone[i].r = (unsigned char)(((int)w_adj_red   * (int)ColorPacket->zone[i].r) / 255);
421         ColorPacket->zone[i].g = (unsigned char)(((int)w_adj_green * (int)ColorPacket->zone[i].g) / 255);
422         ColorPacket->zone[i].b = (unsigned char)(((int)w_adj_blue  * (int)ColorPacket->zone[i].b) / 255);
423     }
424     return ColorPacket;
425 }
426
427 pColorPacket CAtmoTools::ApplyGamma(CAtmoConfig *pAtmoConfig, pColorPacket ColorPacket)
428 {
429   double v;
430   switch(pAtmoConfig->getSoftware_gamma_mode()) {
431     case agcNone: break;
432     case agcPerColor: {
433         double GammaRed   = 10.0 / ((double)pAtmoConfig->getSoftware_gamma_red());
434         double GammaGreen = 10.0 / ((double)pAtmoConfig->getSoftware_gamma_green());
435         double GammaBlue  = 10.0 / ((double)pAtmoConfig->getSoftware_gamma_blue());
436         for (int i = 0; i < ColorPacket->numColors; i++)
437         {
438           v = ColorPacket->zone[i].r;
439           v = (pow( v / 255.0f, GammaRed ) * 255.0f);
440           ColorPacket->zone[i].r = ATMO_MIN((int)v, 255);
441
442           v = ColorPacket->zone[i].g;
443           v = (pow( v / 255.0f, GammaGreen ) * 255.0f);
444           ColorPacket->zone[i].g = ATMO_MIN((int)v, 255);
445
446           v = ColorPacket->zone[i].b;
447           v = (pow( v / 255.0f, GammaBlue ) * 255.0f);
448           ColorPacket->zone[i].b = ATMO_MIN((int)v, 255);
449         }
450         break;
451     }
452     case agcGlobal:   {
453         double Gamma   = 10.0 / ((double)pAtmoConfig->getSoftware_gamma_global());
454         for (int i = 0; i < ColorPacket->numColors; i++)
455         {
456           v = ColorPacket->zone[i].r;
457           v = (pow( v / 255.0f, Gamma ) * 255.0f);
458           ColorPacket->zone[i].r = ATMO_MIN((int)v, 255);
459
460           v = ColorPacket->zone[i].g;
461           v = (pow( v / 255.0f, Gamma ) * 255.0f);
462           ColorPacket->zone[i].g = ATMO_MIN((int)v, 255);
463
464           v = ColorPacket->zone[i].b;
465           v = (pow( v / 255.0f, Gamma ) * 255.0f);
466           ColorPacket->zone[i].b = ATMO_MIN((int)v, 255);
467         }
468         break;
469     }
470   }
471   return ColorPacket;
472 }
473
474 int CAtmoTools::SetChannelAssignment(CAtmoDynData *pDynData, int index)
475 {
476     CAtmoConfig *pAtmoConfig = pDynData->getAtmoConfig();
477     CAtmoConnection *pAtmoConnection = pDynData->getAtmoConnection();
478     int oldIndex = pAtmoConfig->getCurrentChannelAssignment();
479
480     CAtmoChannelAssignment *ca = pAtmoConfig->getChannelAssignment(index);
481     if((ca!=NULL) && (pAtmoConnection!=NULL)) {
482         pAtmoConnection->SetChannelAssignment(ca);
483         pAtmoConfig->setCurrentChannelAssignment(index);
484     }
485     return oldIndex;
486 }
487
488
489 #if !defined(_ATMO_VLC_PLUGIN_)
490
491 void CAtmoTools::SaveBitmap(HDC hdc,HBITMAP hBmp,char *fileName) {
492      BITMAPINFO bmpInfo;
493      BITMAPFILEHEADER  bmpFileHeader;
494      ZeroMemory(&bmpInfo, sizeof(BITMAPINFO));
495      bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
496
497      GetDIBits(hdc,hBmp,0,0,NULL,&bmpInfo,DIB_RGB_COLORS);
498      if(bmpInfo.bmiHeader.biSizeImage<=0)
499         bmpInfo.bmiHeader.biSizeImage=bmpInfo.bmiHeader.biWidth * abs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8;
500      void *pBuf = malloc(bmpInfo.bmiHeader.biSizeImage);
501      bmpInfo.bmiHeader.biCompression=BI_RGB;
502
503      GetDIBits(hdc,hBmp,0,bmpInfo.bmiHeader.biHeight,pBuf, &bmpInfo, DIB_RGB_COLORS);
504
505
506      bmpFileHeader.bfReserved1=0;
507      bmpFileHeader.bfReserved2=0;
508      bmpFileHeader.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage;
509      bmpFileHeader.bfType = MakeIntelWord('M','B');
510      bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
511
512
513      FILE *fp = NULL;
514      fp = fopen(fileName,"wb");
515      fwrite(&bmpFileHeader,sizeof(BITMAPFILEHEADER),1,fp);
516      fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
517      fwrite(pBuf,bmpInfo.bmiHeader.biSizeImage,1,fp);
518      fclose(fp);
519 }
520
521
522
523 #endif
524