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