1 /*****************************************************************************
2 * atmo.cpp : "Atmo Light" video filter
3 *****************************************************************************
4 * Copyright (C) 2000-2006 the VideoLAN team
7 * Authors: André Weber (WeberAndre@gmx.de)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
29 #include <math.h> /* sin(), cos() */
35 // #define __ATMO_DEBUG__
40 #include <vlc_playlist.h>
41 #include "vlc_filter.h"
44 #include "AtmoDynData.h"
45 #include "AtmoLiveView.h"
46 #include "AtmoTools.h"
47 #include "AtmoExternalCaptureInput.h"
48 #include "AtmoConfig.h"
49 #include "AtmoConnection.h"
50 #include "AtmoSerialConnection.h"
53 /*****************************************************************************
55 *****************************************************************************/
56 /* directly to vlc related functions required that the module is accepted */
57 static int CreateFilter ( vlc_object_t * );
58 static void DestroyFilter ( vlc_object_t * );
59 static picture_t * Filter( filter_t *, picture_t *);
61 /* callback for global variable state pause / continue / stop events */
62 static void AddStateVariableCallback( filter_t *);
63 static void DelStateVariableCallback( filter_t *);
64 static int StateCallback(vlc_object_t *, char const *,
65 vlc_value_t, vlc_value_t, void *);
67 /* callback for variable crop-update */
68 static void AddCropVariableCallback( filter_t *);
69 static void DelCropVariableCallback( filter_t *);
70 static int CropCallback(vlc_object_t *, char const *,
71 vlc_value_t, vlc_value_t, void *);
73 /* callback for atmo settings variables whose change
74 should be immediately realized and applied to output
76 static void DelAtmoSettingsVariablesCallbacks(filter_t *);
77 static void AddAtmoSettingsVariablesCallbacks(filter_t *);
78 static int AtmoSettingsCallback(vlc_object_t *, char const *,
79 vlc_value_t, vlc_value_t, void *);
82 #if defined(__ATMO_DEBUG__)
83 static void atmo_parse_crop(char *psz_cropconfig,
84 video_format_t fmt_in,
85 video_format_t fmt_render,
87 int &i_visible_height,
93 /* function to shutdown the fade thread which is started on pause*/
94 static void CheckAndStopFadeThread(filter_t *);
96 /* extracts a small RGB (BGR) Image from an YUV image */
97 static void ExtractMiniImage_YUV(filter_sys_t *, picture_t *, uint8_t *);
99 #if defined(__ATMO_DEBUG__)
100 void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename);
103 /*****************************************************************************
104 * External Prototypes for the AtmoCtrlLib.DLL
105 *****************************************************************************/
107 * if effectmode = emLivePicture then the source could be GDI (Screencapture)
108 * or External - this means another application delivers Pixeldata to AtmoWin
109 * Clientsoftware through AtmoCtrlLib.DLL and the COM Api
112 #define lvsExternal 1
116 strings for settings menus and hints
118 #define MODULE_DESCRIPTION N_ ( \
119 "This module allows to control an so called AtmoLight device which "\
120 "is connected to your computer.\n"\
121 "AtmoLight is the homebrew version of that what Philips calls AmbiLight.\n"\
122 "If you need further informations feel free to visit us at\n\n"\
123 "http://www.vdr-wiki.de/wiki/index.php/Atmo-plugin\n"\
124 "http://www.vdr-wiki.de/wiki/index.php/AtmoWin\n\n"\
125 "there you will find detailed descriptions how to build it for your self and "\
126 "where you can get the required parts and so on.\n There you can also see "\
127 "pictures and some movies showing such a device in live action...")
131 #if defined( __ATMO_DEBUG__ )
132 # define SAVEFRAMES_TEXT N_("Save Debug Frames")
133 # define SAVEFRAMES_LONGTEXT N_("Writes every 128th miniframe to a folder.")
134 # define FRAMEPATH_TEXT N_("Debug Frame Folder")
135 # define FRAMEPATH_LONGTEXT N_("defines the path where the debugframes " \
139 #define WIDTH_TEXT N_("Extracted Image Width")
140 #define WIDTH_LONGTEXT N_("defines the width of the mini image for " \
141 "further processing (64 is default)")
143 #define HEIGHT_TEXT N_("Extracted Image Height")
144 #define HEIGHT_LONGTEXT N_("defines the height of the mini image for " \
145 "further processing (48 is default)")
147 #define PCOLOR_TEXT N_("use Pause Color")
148 #define PCOLOR_LONGTEXT N_("use the color defined below if the user " \
149 "paused the video.(have light to get another beer?)")
150 #define PCOLOR_RED_TEXT N_("Pause-Red")
151 #define PCOLOR_RED_LONGTEXT N_("the red component of pause color")
152 #define PCOLOR_GREEN_TEXT N_("Pause-Green")
153 #define PCOLOR_GREEN_LONGTEXT N_("the green component of pause color")
154 #define PCOLOR_BLUE_TEXT N_("Pause-Blue")
155 #define PCOLOR_BLUE_LONGTEXT N_("the blue component of pause color")
156 #define FADESTEPS_TEXT N_("Pause-Fadesteps")
157 #define FADESTEPS_LONGTEXT N_("Number of steps to change current color " \
158 "to pause color (each step takes 40ms)")
160 #define ECOLOR_RED_TEXT N_("End-Red")
161 #define ECOLOR_RED_LONGTEXT N_("the red component of the shutdown color")
162 #define ECOLOR_GREEN_TEXT N_("End-Green")
163 #define ECOLOR_GREEN_LONGTEXT N_("the green component of the shutdown color")
164 #define ECOLOR_BLUE_TEXT N_("End-Blue")
165 #define ECOLOR_BLUE_LONGTEXT N_("the blue component of the shutdown color")
166 #define EFADESTEPS_TEXT N_("End-Fadesteps")
167 #define EFADESTEPS_LONGTEXT N_("Number of steps to change current color to " \
168 "end color for dimming up the light in cinema " \
169 "style... (each step takes 40ms)")
171 #define USEWHITEADJ_TEXT N_("Use Software White adjust")
172 #define USEWHITEADJ_LONGTEXT N_("Should the buildin driver do a white " \
173 "adjust or you LED stripes? recommend.")
174 #define WHITE_RED_TEXT N_("White Red")
175 #define WHITE_RED_LONGTEXT N_("Red value of a pure white on your "\
177 #define WHITE_GREEN_TEXT N_("White Green")
178 #define WHITE_GREEN_LONGTEXT N_("Green value of a pure white on your "\
180 #define WHITE_BLUE_TEXT N_("White Blue")
181 #define WHITE_BLUE_LONGTEXT N_("Blue value of a pure white on your "\
184 #define SERIALDEV_TEXT N_("Serial Port/Device")
185 #define SERIALDEV_LONGTEXT N_("Name of the serial port where the AtmoLight "\
186 "controller is attached to\n on Windows usually "\
187 "something like COM1 or COM2 on Linux /dev/ttyS01 f.e.")
189 #define EDGE_TEXT N_("Edge Weightning")
190 #define EDGE_LONGTEXT N_("increasing this value will result in color "\
191 "more depending on the border of the frame")
192 #define BRIGHTNESS_TEXT N_("Brightness")
193 #define BRIGHTNESS_LONGTEXT N_("overall Brightness of you LED stripes")
194 #define DARKNESS_TEXT N_("Darkness Limit")
195 #define DARKNESS_LONGTEXT N_("pixels with a saturation lower than this will "\
196 "be ignored should be greater than one for "\
197 "letterboxed videos")
198 #define HUEWINSIZE_TEXT N_("Hue windowing")
199 #define HUEWINSIZE_LONGTEXT N_("used for statistics")
200 #define SATWINSIZE_TEXT N_("Sat windowing")
201 #define SATWINSIZE_LONGTEXT N_("used for statistics")
203 #define MEANLENGTH_TEXT N_("Filter length (ms)")
204 #define MEANLENGTH_LONGTEXT N_("Time it takes until a color is complete "\
205 "changed, removes flickering")
206 #define MEANTHRESHOLD_TEXT N_("Filter threshold")
207 #define MEANTHRESHOLD_LONGTEXT N_("How much a color must changed, for an "\
208 "imediate color change")
209 #define MEANPERCENTNEW_TEXT N_("Filter Smoothness %")
210 #define MEANPERCENTNEW_LONGTEXT N_("Filter Smoothness")
212 #define FILTERMODE_TEXT N_("Filtermode")
213 #define FILTERMODE_LONGTEXT N_("kind of filtering which should be use to "\
214 "calcuate the color output")
215 static int pi_filtermode_values[] = {
220 static const char *ppsz_filtermode_descriptions[] = {
226 #define FRAMEDELAY_TEXT N_("Framedelay")
227 #define FRAMEDELAY_LONGTEXT N_("helps to get video out and light effects "\
228 "insync values around 20ms should do the trick")
231 #define CHANNEL_0_ASSIGN_TEXT N_("Channel summary")
232 #define CHANNEL_1_ASSIGN_TEXT N_("Channel left")
233 #define CHANNEL_2_ASSIGN_TEXT N_("Channel right")
234 #define CHANNEL_3_ASSIGN_TEXT N_("Channel top")
235 #define CHANNEL_4_ASSIGN_TEXT N_("Channel bottom")
237 #define CHANNELASSIGN_LONGTEXT N_("maps the hardware channel X to logical "\
238 "channel Y to fix wrong wiring:-)")
239 static int pi_channel_assignment_values[] = {
247 static const char *ppsz_channel_assignment_descriptions[] = {
256 #define ZONE_0_GRADIENT_TEXT N_("summary gradient")
257 #define ZONE_1_GRADIENT_TEXT N_("left gradient")
258 #define ZONE_2_GRADIENT_TEXT N_("right gradient")
259 #define ZONE_3_GRADIENT_TEXT N_("top gradient")
260 #define ZONE_4_GRADIENT_TEXT N_("bottom gradient")
261 #define ZONE_X_GRADIENT_LONG_TEXT N_("defines a small bitmap with 64x48 "\
262 "pixels, containing a grayscale gradient")
265 # define ATMOWINEXE_TEXT N_("Filename of AtmoWinA.exe")
266 # define ATMOWINEXE_LONGTEXT N_("if you wan't that the AtmoLight control "\
267 "software is launched by\nVLC enter the "\
268 "complete Filename of AtmoWinA.exe here")
269 # define USEBUILDIN_TEXT N_("Use buildin AtmoLight")
270 # define USEBUILDIN_LONGTEXT N_("VideoLan will directly use your AtmoLight "\
271 "hardware without running the external "\
272 "AtmoWinA.exe Userspace driver.")
275 #define CFG_PREFIX "atmo-"
277 /*****************************************************************************
279 *****************************************************************************/
281 set_description( _("AtmoLight Filter") );
282 set_help( MODULE_DESCRIPTION );
283 set_shortname( _( "AtmoLight" ));
284 set_capability( "video filter2", 0 );
286 set_category( CAT_VIDEO );
287 set_subcategory( SUBCAT_VIDEO_VFILTER );
290 set_section( N_("Choose between the buildin AtmoLight "\
291 "driver or the external" ), 0 );
294 only on win32 exists the option to use the buildin driver or
295 the more flexible external driver application
297 add_bool(CFG_PREFIX "usebuildin", true, NULL,
298 USEBUILDIN_TEXT, USEBUILDIN_LONGTEXT, false);
299 add_string(CFG_PREFIX "serialdev", "COM1", NULL,
300 SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false );
303 on win32 the executeable external driver application
304 for automatic start if needed
306 add_file(CFG_PREFIX "atmowinexe", NULL, NULL,
307 ATMOWINEXE_TEXT, ATMOWINEXE_LONGTEXT, false );
309 set_section( N_("Enter connection of your AtmoLight hardware" ), 0 );
310 add_string(CFG_PREFIX "serialdev", "/dev/ttyS01", NULL,
311 SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false );
315 color which is showed if you want durring pausing
316 your movie ... used for both buildin / external
318 set_section( N_("Illuminate the room with this color on pause" ), 0 );
319 add_bool(CFG_PREFIX "usepausecolor", false, NULL,
320 PCOLOR_TEXT, PCOLOR_LONGTEXT, false);
321 add_integer_with_range(CFG_PREFIX "pcolor-red", 0, 0, 255, NULL,
322 PCOLOR_RED_TEXT, PCOLOR_RED_LONGTEXT, false);
323 add_integer_with_range(CFG_PREFIX "pcolor-green", 0, 0, 255, NULL,
324 PCOLOR_GREEN_TEXT, PCOLOR_GREEN_LONGTEXT, false);
325 add_integer_with_range(CFG_PREFIX "pcolor-blue", 192, 0, 255, NULL,
326 PCOLOR_BLUE_TEXT, PCOLOR_BLUE_LONGTEXT, false);
327 add_integer_with_range(CFG_PREFIX "fadesteps", 50, 1, 250, NULL,
328 FADESTEPS_TEXT, FADESTEPS_LONGTEXT, false);
331 color which is showed if you finished watching your movie ...
332 used for both buildin / external
334 set_section( N_("Illuminate the room with this color on shutdown" ), 0 );
335 add_integer_with_range(CFG_PREFIX "ecolor-red", 192, 0, 255, NULL,
336 ECOLOR_RED_TEXT, ECOLOR_RED_LONGTEXT, false);
337 add_integer_with_range(CFG_PREFIX "ecolor-green", 192, 0, 255, NULL,
338 ECOLOR_GREEN_TEXT, ECOLOR_GREEN_LONGTEXT, false);
339 add_integer_with_range(CFG_PREFIX "ecolor-blue", 192, 0, 255, NULL,
340 ECOLOR_BLUE_TEXT, ECOLOR_BLUE_LONGTEXT, false);
341 add_integer_with_range(CFG_PREFIX "efadesteps", 50, 1, 250, NULL,
342 EFADESTEPS_TEXT, EFADESTEPS_LONGTEXT, false);
345 settings only for the buildin driver (if external driver app is used
346 these parameters are ignored.)
348 definition of parameters for the buildin filter ...
350 set_section( N_("Settings only for buildin Live Video Processor" ), 0 );
352 add_integer_with_range(CFG_PREFIX "EdgeWeightning", 8, 1, 30, NULL,
353 EDGE_TEXT, EDGE_LONGTEXT, false);
355 add_integer_with_range(CFG_PREFIX "Brightness", 100, 50, 300, NULL,
356 BRIGHTNESS_TEXT, BRIGHTNESS_LONGTEXT, false);
358 add_integer_with_range(CFG_PREFIX "DarknessLimit", 5, 0, 10, NULL,
359 DARKNESS_TEXT, DARKNESS_LONGTEXT, false);
361 add_integer_with_range(CFG_PREFIX "HueWinSize", 3, 0, 5, NULL,
362 HUEWINSIZE_TEXT, HUEWINSIZE_LONGTEXT, false);
364 add_integer_with_range(CFG_PREFIX "SatWinSize", 3, 0, 5, NULL,
365 SATWINSIZE_TEXT, SATWINSIZE_LONGTEXT, false);
367 add_integer(CFG_PREFIX "filtermode", (int)afmCombined, NULL,
368 FILTERMODE_TEXT, FILTERMODE_LONGTEXT, false );
370 change_integer_list(pi_filtermode_values, ppsz_filtermode_descriptions, 0 );
372 add_integer_with_range(CFG_PREFIX "MeanLength", 300, 300, 5000, NULL,
373 MEANLENGTH_TEXT, MEANLENGTH_LONGTEXT, false);
375 add_integer_with_range(CFG_PREFIX "MeanThreshold", 40, 1, 100, NULL,
376 MEANTHRESHOLD_TEXT, MEANTHRESHOLD_LONGTEXT, false);
378 add_integer_with_range(CFG_PREFIX "PercentNew", 50, 1, 100, NULL,
379 MEANPERCENTNEW_TEXT, MEANPERCENTNEW_LONGTEXT, false);
381 add_integer_with_range(CFG_PREFIX "FrameDelay", 18, 0, 35, NULL,
382 FRAMEDELAY_TEXT, FRAMEDELAY_LONGTEXT, false);
385 output channel reordering
387 set_section( N_("Change channel assignment (fixes wrong wiring)" ), 0 );
388 add_integer( CFG_PREFIX "channel_0", 0, NULL,
389 CHANNEL_0_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
390 change_integer_list( pi_channel_assignment_values,
391 ppsz_channel_assignment_descriptions, 0 );
393 add_integer( CFG_PREFIX "channel_1", 1, NULL,
394 CHANNEL_1_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
395 change_integer_list( pi_channel_assignment_values,
396 ppsz_channel_assignment_descriptions, 0 );
398 add_integer( CFG_PREFIX "channel_2", 2, NULL,
399 CHANNEL_2_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
400 change_integer_list( pi_channel_assignment_values,
401 ppsz_channel_assignment_descriptions, 0 );
403 add_integer( CFG_PREFIX "channel_3", 3, NULL,
404 CHANNEL_3_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
405 change_integer_list( pi_channel_assignment_values,
406 ppsz_channel_assignment_descriptions, 0 );
408 add_integer( CFG_PREFIX "channel_4", 4, NULL,
409 CHANNEL_4_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
410 change_integer_list( pi_channel_assignment_values,
411 ppsz_channel_assignment_descriptions, 0 );
414 LED color white calibration
416 set_section( N_("Adjust the white light to your LED stripes" ), 0 );
417 add_bool(CFG_PREFIX "whiteadj", true, NULL,
418 USEWHITEADJ_TEXT, USEWHITEADJ_LONGTEXT, false);
419 add_integer_with_range(CFG_PREFIX "white-red", 255, 0, 255, NULL,
420 WHITE_RED_TEXT, WHITE_RED_LONGTEXT, false);
422 add_integer_with_range(CFG_PREFIX "white-green", 255, 0, 255, NULL,
423 WHITE_GREEN_TEXT, WHITE_GREEN_LONGTEXT, false);
425 add_integer_with_range(CFG_PREFIX "white-blue", 255, 0, 255, NULL,
426 WHITE_BLUE_TEXT, WHITE_BLUE_LONGTEXT, false);
427 /* end of definition of parameter for the buildin filter ... part 1 */
431 only for buildin (external has own definition) per default the calucation
432 used linear gradients for assigning a priority to the pixel - depending
433 how near they are to the border ...for changing this you can create 64x48
434 Pixel BMP files - which contain your own grayscale... (you can produce funny
435 effects with this...) the images MUST not compressed, should have 24-bit per
436 pixel, or a simple 256 color grayscale palette
438 set_section( N_("Change gradients" ), 0 );
439 add_file(CFG_PREFIX "gradient_zone_0", NULL, NULL,
440 ZONE_0_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
441 add_file(CFG_PREFIX "gradient_zone_1", NULL, NULL,
442 ZONE_1_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
443 add_file(CFG_PREFIX "gradient_zone_2", NULL, NULL,
444 ZONE_2_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
445 add_file(CFG_PREFIX "gradient_zone_3", NULL, NULL,
446 ZONE_3_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
447 add_file(CFG_PREFIX "gradient_zone_4", NULL, NULL,
448 ZONE_4_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
451 #if defined(__ATMO_DEBUG__)
452 add_bool(CFG_PREFIX "saveframes", false, NULL,
453 SAVEFRAMES_TEXT, SAVEFRAMES_LONGTEXT, false);
454 add_string(CFG_PREFIX "framepath", "", NULL,
455 FRAMEPATH_TEXT, FRAMEPATH_LONGTEXT, false );
458 may be later if computers gets more power ;-) than now we increase
459 the samplesize from which we do the stats for output color calculation
461 add_integer_with_range(CFG_PREFIX "width", 64, 64, 512, NULL,
462 WIDTH_TEXT, WIDTH_LONGTEXT, true);
463 add_integer_with_range(CFG_PREFIX "height", 48, 48, 384, NULL,
464 HEIGHT_TEXT, HEIGHT_LONGTEXT, true);
466 add_shortcut( "atmo" );
467 set_callbacks( CreateFilter, DestroyFilter );
471 static const char *ppsz_filter_options[] = {
518 #if defined(__ATMO_DEBUG__)
533 /*****************************************************************************
534 * fadethread_t: Color Fading Thread
535 *****************************************************************************
536 * changes slowly the color of the output if videostream gets paused...
537 *****************************************************************************
543 /* tell the thread which color should be the target of fading */
547 /* how many steps should happen until this */
552 static void FadeToColorThread(fadethread_t *p_fadethread);
555 /*****************************************************************************
556 * filter_sys_t: AtmoLight filter method descriptor
557 *****************************************************************************
558 * It describes the AtmoLight specific properties of an video filter.
559 *****************************************************************************/
563 special for the access of the p_fadethread member all other members
564 need no special protection so far!
566 vlc_mutex_t filter_lock;
569 int32_t i_AtmoOldEffect;
572 int32_t i_atmo_width;
573 int32_t i_atmo_height;
575 #if defined(__ATMO_DEBUG__)
578 char sz_framepath[MAX_PATH];
581 /* light color durring movie pause ... */
582 bool b_usepausecolor;
583 uint8_t ui_pausecolor_red;
584 uint8_t ui_pausecolor_green;
585 uint8_t ui_pausecolor_blue;
588 /* light color on movie finish ... */
589 uint8_t ui_endcolor_red;
590 uint8_t ui_endcolor_green;
591 uint8_t ui_endcolor_blue;
594 fadethread_t *p_fadethread;
596 /* Variables for buildin driver only... */
598 /* is only present and initialized if the internal driver is used*/
599 CAtmoConfig *p_atmo_config;
600 /* storage for temporal settings "volatile" */
601 CAtmoDynData *p_atmo_dyndata;
602 /* initialized for buildin driver with AtmoCreateTransferBuffers */
603 BITMAPINFOHEADER mini_image_format;
604 /* is only use buildin driver! */
605 uint8_t *p_atmo_transfer_buffer;
606 /* end buildin driver */
609 contains the real output size of the video calculated on
610 change event of the variable "crop" from vout
612 int32_t i_crop_x_offset;
613 int32_t i_crop_y_offset;
614 int32_t i_crop_width;
615 int32_t i_crop_height;
617 void (*pf_extract_mini_image) (filter_sys_t *p_sys,
619 uint8_t *p_transfer_dest);
622 /* External Library as wrapper arround COM Stuff */
623 HINSTANCE h_AtmoCtrl;
624 int32_t (*pf_ctrl_atmo_initialize) (void);
625 void (*pf_ctrl_atmo_finalize) (int32_t what);
626 int32_t (*pf_ctrl_atmo_switch_effect) (int32_t);
627 int32_t (*pf_ctrl_atmo_set_live_source) (int32_t);
628 void (*pf_ctrl_atmo_create_transfer_buffers) (int32_t, int32_t,
630 uint8_t* (*pf_ctrl_atmo_lock_transfer_buffer) (void);
631 void (*pf_ctrl_atmo_send_pixel_data) (void);
636 initialize previously configured Atmo Light environment
637 - if internal is enabled try to access the device on the serial port
638 - if not internal is enabled and we are on win32 try to initialize
639 the previously loaded DLL ...
641 Return Values may be: -1 (failed for some reason - filter will be disabled)
644 static int32_t AtmoInitialize(filter_t *p_filter, bool b_for_thread)
646 filter_sys_t *p_sys = p_filter->p_sys;
647 if(p_sys->p_atmo_config)
649 if(b_for_thread == false)
652 /* setup Output Threads ... */
653 msg_Dbg( p_filter, "open serial connection %s",
654 p_sys->p_atmo_config->getSerialDevice());
656 if(CAtmoTools::RecreateConnection(p_sys->p_atmo_dyndata) == ATMO_TRUE)
658 msg_Dbg( p_filter, "start live view thread ...");
659 CAtmoTools::SwitchEffect(p_sys->p_atmo_dyndata, emLivePicture);
660 msg_Dbg( p_filter, "live view thread launched...");
664 msg_Err( p_filter,"failed to open serial device? some other software/driver may use it?");
668 } else if(p_sys->pf_ctrl_atmo_initialize)
670 /* on win32 with active ctrl dll */
671 return p_sys->pf_ctrl_atmo_initialize();
678 prepare the shutdown of the effect threads,
679 for build in filter - close the serialport after finishing the threads...
680 cleanup possible loaded DLL...
682 static void AtmoFinalize(filter_t *p_filter, int32_t what)
684 filter_sys_t *p_sys = p_filter->p_sys;
685 if(p_sys->p_atmo_config)
689 CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
692 p_atmo_dyndata->LockCriticalSection();
694 CThread *p_effect_thread = p_atmo_dyndata->getEffectThread();
695 p_atmo_dyndata->setEffectThread(NULL);
696 if(p_effect_thread != NULL)
699 forced the thread to die...
700 and wait for termination of the thread
702 p_effect_thread->Terminate();
703 delete p_effect_thread;
704 msg_Dbg( p_filter, "effect thread died peacefully");
708 close serial port if it is open (all OS specific is inside
709 CAtmoSerialConnection implemented / defined)
711 CAtmoConnection *p_atmo_connection =
712 p_atmo_dyndata->getAtmoConnection();
713 p_atmo_dyndata->setAtmoConnection(NULL);
714 if(p_atmo_connection) {
715 p_atmo_connection->CloseConnection();
716 delete p_atmo_connection;
718 p_atmo_dyndata->UnLockCriticalSection();
722 } else if(p_sys->pf_ctrl_atmo_finalize)
724 /* on win32 with active ctrl dll */
725 p_sys->pf_ctrl_atmo_finalize(what);
731 switch the current light effect - does only something on win32, with the
732 external libraries - if the buildin effects are used nothing happens
734 static int32_t AtmoSwitchEffect(filter_t *p_filter, int32_t newMode)
736 filter_sys_t *p_sys = p_filter->p_sys;
737 if(p_sys->p_atmo_config)
742 doesnt know different modes for effects so this
743 function call would just do nothing special
748 } else if(p_sys->pf_ctrl_atmo_switch_effect)
750 /* on win32 with active ctrl dll */
751 return p_sys->pf_ctrl_atmo_switch_effect(newMode);
758 set the current live picture source, does only something on win32,
759 with the external libraries - if the buildin effects are used nothing
762 static int32_t AtmoSetLiveSource(filter_t *p_filter, int32_t newSource)
764 filter_sys_t *p_sys = p_filter->p_sys;
765 if(p_sys->p_atmo_config)
770 doesnt know different sources so this
771 function call would just do nothing special
775 } else if(p_sys->pf_ctrl_atmo_set_live_source)
777 /* on win32 with active ctrl dll */
778 return p_sys->pf_ctrl_atmo_set_live_source(newSource);
785 setup the pixel transferbuffers which is used to transfer pixeldata from
786 the filter to the effect thread, and possible accross the process
787 boundaries on win32, with the external DLL
789 static void AtmoCreateTransferBuffers(filter_t *p_filter,
791 int32_t bytePerPixel,
795 filter_sys_t *p_sys = p_filter->p_sys;
796 if(p_sys->p_atmo_config)
799 we need a buffer where the image is stored (only for transfer
800 to the processing thread)
802 if(p_sys->p_atmo_transfer_buffer)
803 free(p_sys->p_atmo_transfer_buffer);
805 p_sys->p_atmo_transfer_buffer = (uint8_t *)malloc(bytePerPixel *
808 memset(&p_sys->mini_image_format,0,sizeof(BITMAPINFOHEADER));
810 p_sys->mini_image_format.biSize = sizeof(BITMAPINFOHEADER);
811 p_sys->mini_image_format.biWidth = width;
812 p_sys->mini_image_format.biHeight = height;
813 p_sys->mini_image_format.biBitCount = bytePerPixel*8;
814 p_sys->mini_image_format.biCompression = FourCC;
817 } else if(p_sys->pf_ctrl_atmo_create_transfer_buffers)
819 /* on win32 with active ctrl dll */
820 p_sys->pf_ctrl_atmo_create_transfer_buffers(FourCC,
829 acquire the transfer buffer pointer the buildin version only
830 returns the pointer to the allocated buffer ... the
831 external version on win32 has to do some COM stuff to lock the
832 Variant Byte array which is behind the buffer
834 static uint8_t* AtmoLockTransferBuffer(filter_t *p_filter)
836 filter_sys_t *p_sys = p_filter->p_sys;
837 if(p_sys->p_atmo_config)
839 return p_sys->p_atmo_transfer_buffer;
841 } else if(p_sys->pf_ctrl_atmo_lock_transfer_buffer)
843 /* on win32 with active ctrl dll */
844 return p_sys->pf_ctrl_atmo_lock_transfer_buffer();
851 send the content of current pixel buffer got with AtmoLockTransferBuffer
852 to the processing threads
853 - build in version - will forward the data to AtmoExternalCaptureInput Thread
854 - win32 external - will do the same, but across the process boundaries via
855 COM to the AtmoWinA.exe Process
857 static void AtmoSendPixelData(filter_t *p_filter)
859 filter_sys_t *p_sys = p_filter->p_sys;
860 if(p_sys->p_atmo_config && p_sys->p_atmo_transfer_buffer)
862 CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
866 the cast will go Ok because we are inside videolan there is only
867 this kind of effect thread implemented!
870 CAtmoLiveView *p_atmo_live_view_thread =
871 (CAtmoLiveView *)p_atmo_dyndata->getEffectThread();
872 if(p_atmo_live_view_thread)
875 the same as above inside videolan only this single kind of
876 input exists so we can cast without further tests!
878 CAtmoExternalCaptureInput *p_atmo_external_capture_input_thread =
879 (CAtmoExternalCaptureInput *)p_atmo_live_view_thread->getAtmoInput();
880 if(p_atmo_external_capture_input_thread)
883 this call will do a 1:1 copy of this buffer, and wakeup
884 the thread from normal sleeping
886 p_atmo_external_capture_input_thread->
887 DeliverNewSourceDataPaket(&p_sys->mini_image_format,
888 p_sys->p_atmo_transfer_buffer);
893 } else if(p_sys->pf_ctrl_atmo_send_pixel_data)
895 /* on win32 with active ctrl dll */
896 p_sys->pf_ctrl_atmo_send_pixel_data();
902 Shutdown AtmoLight finally - is call from DestroyFilter
903 does the cleanup restores the effectmode on the external Software
904 (only win32) and possible setup the final light ...
906 static void Atmo_Shutdown(filter_t *p_filter)
908 filter_sys_t *p_sys = p_filter->p_sys;
910 if(p_sys->b_enabled == true)
913 if there is a still running show pause color thread kill him!
915 CheckAndStopFadeThread(p_filter);
917 if(p_sys->p_atmo_config || (p_sys->i_AtmoOldEffect == emStaticColor))
920 fade to end color (in case of external AtmoWin Software
921 assume that the static color will equal to this
922 one to get a soft change and no flash!
924 p_sys->b_pause_live = true;
926 // perpare spawn fadeing thread
927 vlc_mutex_lock( &p_sys->filter_lock );
929 p_sys->p_fadethread = (fadethread_t *)vlc_object_create( p_filter,
930 sizeof(fadethread_t) );
932 p_sys->p_fadethread->p_filter = p_filter;
933 p_sys->p_fadethread->ui_red = p_sys->ui_endcolor_red;
934 p_sys->p_fadethread->ui_green = p_sys->ui_endcolor_green;
935 p_sys->p_fadethread->ui_blue = p_sys->ui_endcolor_blue;
936 p_sys->p_fadethread->i_steps = p_sys->i_endfadesteps;
938 if( vlc_thread_create( p_sys->p_fadethread,
941 VLC_THREAD_PRIORITY_LOW,
944 msg_Err( p_filter, "cannot create FadeToColorThread" );
945 vlc_object_release( p_sys->p_fadethread );
946 p_sys->p_fadethread = NULL;
947 vlc_mutex_unlock( &p_sys->filter_lock );
951 vlc_mutex_unlock( &p_sys->filter_lock );
953 /* wait for the thread... */
954 vlc_thread_join(p_sys->p_fadethread);
956 vlc_object_release(p_sys->p_fadethread);
958 p_sys->p_fadethread = NULL;
962 if(p_sys->i_AtmoOldEffect != emLivePicture)
963 AtmoSwitchEffect(p_filter, p_sys->i_AtmoOldEffect);
965 AtmoSetLiveSource(p_filter, lvsGDI);
967 AtmoFinalize(p_filter, 1);
969 /* disable filter method .. */
970 p_sys->b_enabled = false;
975 initialize the filter_sys_t structure with the data from the settings
976 variables - if the external filter on win32 is enabled try loading the DLL,
977 if this fails fallback to the buildin software
979 static void Atmo_SetupParameters(filter_t *p_filter)
981 bool b_use_buildin_driver = true;
983 filter_sys_t *p_sys = p_filter->p_sys;
986 /* default filter disabled until DLL loaded and Init Success!*/
987 p_sys->b_enabled = false;
989 /* setup default mini image size (may be later a user option) */
990 p_sys->i_atmo_width = 64;
991 p_sys->i_atmo_height = 48;
994 vlc_mutex_init( p_filter, &p_sys->filter_lock );
999 only on WIN32 the user has the choice between
1000 internal driver and external
1002 b_use_buildin_driver = var_CreateGetBoolCommand( p_filter,
1003 CFG_PREFIX "usebuildin" );
1005 if(b_use_buildin_driver == false) {
1007 /* Load the Com Wrapper Library (source available) */
1008 p_sys->h_AtmoCtrl = LoadLibraryA("AtmoCtrlLib.dll");
1009 if(p_sys->h_AtmoCtrl != NULL)
1011 msg_Dbg( p_filter, "LoadLibrary('AtmoCtrlLib.dll'); Success");
1013 /* importing all required functions I hope*/
1014 p_sys->pf_ctrl_atmo_initialize =
1015 (int32_t (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoInitialize");
1016 if(!p_sys->pf_ctrl_atmo_initialize)
1017 msg_Err( p_filter, "export AtmoInitialize missing.");
1019 p_sys->pf_ctrl_atmo_finalize =
1020 (void (*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoFinalize");
1021 if(!p_sys->pf_ctrl_atmo_finalize)
1022 msg_Err( p_filter, "export AtmoFinalize missing.");
1024 p_sys->pf_ctrl_atmo_switch_effect =
1025 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSwitchEffect");
1026 if(!p_sys->pf_ctrl_atmo_switch_effect)
1027 msg_Err( p_filter, "export AtmoSwitchEffect missing.");
1029 p_sys->pf_ctrl_atmo_set_live_source =
1030 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSetLiveSource");
1031 if(!p_sys->pf_ctrl_atmo_set_live_source)
1032 msg_Err( p_filter, "export AtmoSetLiveSource missing.");
1034 p_sys->pf_ctrl_atmo_create_transfer_buffers =
1035 (void (*)(int32_t, int32_t, int32_t , int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoCreateTransferBuffers");
1036 if(!p_sys->pf_ctrl_atmo_create_transfer_buffers)
1037 msg_Err( p_filter, "export AtmoCreateTransferBuffers missing.");
1039 p_sys->pf_ctrl_atmo_lock_transfer_buffer=
1040 (uint8_t*(*) (void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoLockTransferBuffer");
1041 if(!p_sys->pf_ctrl_atmo_lock_transfer_buffer)
1042 msg_Err( p_filter, "export AtmoLockTransferBuffer missing.");
1044 p_sys->pf_ctrl_atmo_send_pixel_data =
1045 (void (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSendPixelData");
1046 if(!p_sys->pf_ctrl_atmo_send_pixel_data)
1047 msg_Err( p_filter, "export AtmoSendPixelData missing.");
1049 /* the DLL is missing try internal filter ...*/
1050 msg_Warn( p_filter, "AtmoCtrlLib.dll missing fallback to internal driver");
1051 b_use_buildin_driver = true;
1057 if(b_use_buildin_driver == true) {
1058 msg_Dbg( p_filter, "use buildin driver");
1060 now we have to read a lof of options from the config dialog
1061 most important the serial device if not set ... we can skip
1062 the rest and disable the filter...
1064 char *psz_serialdev = var_CreateGetStringCommand( p_filter,
1065 CFG_PREFIX "serialdev" );
1066 if(psz_serialdev && (strlen(psz_serialdev)>0)) {
1067 msg_Dbg( p_filter, "use buildin driver on port %s",psz_serialdev);
1069 p_sys->p_atmo_config = new CAtmoConfig();
1071 p_sys->p_atmo_config->setSerialDevice(psz_serialdev);
1073 p_sys->p_atmo_config->setLiveViewFilterMode(
1074 (AtmoFilterMode)var_CreateGetIntegerCommand( p_filter,
1075 CFG_PREFIX "filtermode")
1078 p_sys->p_atmo_config->setLiveViewFilter_PercentNew(
1079 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "PercentNew")
1081 p_sys->p_atmo_config->setLiveViewFilter_MeanLength(
1082 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanLength")
1084 p_sys->p_atmo_config->setLiveViewFilter_MeanThreshold(
1085 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanThreshold")
1088 p_sys->p_atmo_config->setLiveView_EdgeWeighting(
1089 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "EdgeWeightning")
1091 p_sys->p_atmo_config->setLiveView_BrightCorrect(
1092 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "Brightness")
1094 p_sys->p_atmo_config->setLiveView_DarknessLimit(
1095 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "DarknessLimit")
1097 p_sys->p_atmo_config->setLiveView_HueWinSize(
1098 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "HueWinSize")
1100 p_sys->p_atmo_config->setLiveView_SatWinSize(
1101 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "SatWinSize")
1104 /* currently not required inside vlc */
1105 p_sys->p_atmo_config->setLiveView_WidescreenMode( 0 );
1107 p_sys->p_atmo_config->setLiveView_FrameDelay(
1108 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "FrameDelay")
1112 p_sys->p_atmo_config->setUseSoftwareWhiteAdj(
1113 var_CreateGetBoolCommand( p_filter, CFG_PREFIX "whiteadj")
1115 p_sys->p_atmo_config->setWhiteAdjustment_Red(
1116 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-red")
1118 p_sys->p_atmo_config->setWhiteAdjustment_Green(
1119 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-green")
1121 p_sys->p_atmo_config->setWhiteAdjustment_Blue(
1122 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-blue")
1125 tChannelAssignment *p_channel_assignment =
1126 p_sys->p_atmo_config->getChannelAssignment(0);
1128 p_channel_assignment->mappings[0] = var_CreateGetIntegerCommand(
1129 p_filter, CFG_PREFIX "channel_0");
1131 p_channel_assignment->mappings[1] = var_CreateGetIntegerCommand(
1132 p_filter, CFG_PREFIX "channel_1");
1134 p_channel_assignment->mappings[2] = var_CreateGetIntegerCommand(
1135 p_filter, CFG_PREFIX "channel_2");
1137 p_channel_assignment->mappings[3] = var_CreateGetIntegerCommand(
1138 p_filter, CFG_PREFIX "channel_3");
1140 p_channel_assignment->mappings[4] = var_CreateGetIntegerCommand(
1141 p_filter, CFG_PREFIX "channel_4");
1143 for(int i=0;i<ATMO_NUM_CHANNELS;i++)
1144 msg_Dbg( p_filter, "map software channel %d to hardware channel %d",
1145 p_channel_assignment->mappings[i],
1150 char psz_gradient_var_name[30];
1151 char *psz_gradient_file;
1152 for(int i=0;i<ATMO_NUM_CHANNELS;i++)
1154 sprintf(psz_gradient_var_name, CFG_PREFIX "gradient_zone_%d", i);
1155 psz_gradient_file = var_CreateGetStringCommand(
1157 psz_gradient_var_name
1159 if(psz_gradient_file && strlen(psz_gradient_file)>0)
1161 msg_Dbg( p_filter, "loading gradientfile %s for "\
1162 "zone %d", psz_gradient_file, i);
1164 int i_res = p_sys->p_atmo_config->getZoneDefinition(i)->
1165 LoadGradientFromBitmap(psz_gradient_file);
1167 if(i_res != ATMO_LOAD_GRADIENT_OK)
1169 msg_Err( p_filter,"failed to load gradient '%s' with "\
1170 "error %d",psz_gradient_file,i_res);
1173 delete psz_gradient_file;
1176 p_sys->p_atmo_dyndata = new CAtmoDynData((vlc_object_t *)p_filter,
1177 p_sys->p_atmo_config
1180 msg_Dbg( p_filter, "buildin driver initialized");
1182 free(psz_serialdev);
1184 msg_Err(p_filter,"no serial devicename set");
1188 switch( p_filter->fmt_in.video.i_chroma )
1190 case VLC_FOURCC('I','4','2','0'):
1191 case VLC_FOURCC('I','Y','U','V'):
1192 case VLC_FOURCC('Y','V','1','2'):
1193 case VLC_FOURCC('Y','V','1','6'):
1194 case VLC_FOURCC('Y','V','U','9'):
1195 // simple enough? Dionoea?
1196 p_sys->pf_extract_mini_image = ExtractMiniImage_YUV;
1199 msg_Dbg( p_filter, "InitFilter-unsupported chroma: %4.4s",
1200 (char *)&p_filter->fmt_in.video.i_chroma);
1201 p_sys->pf_extract_mini_image = NULL;
1204 p_sys->i_crop_x_offset = 0;
1205 p_sys->i_crop_y_offset = 0;
1206 p_sys->i_crop_width = p_filter->fmt_in.video.i_visible_width;
1207 p_sys->i_crop_height = p_filter->fmt_in.video.i_visible_height;
1209 msg_Dbg( p_filter, "set default crop %d,%d %dx%d",p_sys->i_crop_x_offset,
1210 p_sys->i_crop_y_offset,
1211 p_sys->i_crop_width,
1212 p_sys->i_crop_height );
1215 #if defined(__ATMO_DEBUG__)
1216 /* save debug images to a folder as Bitmap files ? */
1217 p_sys->b_saveframes = var_CreateGetBoolCommand( p_filter,
1218 CFG_PREFIX "saveframes"
1220 msg_Dbg(p_filter,"saveframes = %d", (int)p_sys->b_saveframes);
1223 read debug image folder from config
1225 psz_path = var_CreateGetStringCommand( p_filter, CFG_PREFIX "framepath" );
1226 if(psz_path != NULL)
1228 strcpy(p_sys->sz_framepath, psz_path);
1229 #if defined( WIN32 )
1230 size_t i_strlen = strlen(p_sys->sz_framepath);
1231 if((i_strlen>0) && (p_sys->sz_framepath[i_strlen-1] != '\\'))
1233 p_sys->sz_framepath[i_strlen] = '\\';
1234 p_sys->sz_framepath[i_strlen+1] = 0;
1239 msg_Dbg(p_filter,"saveframesfolder %s",p_sys->sz_framepath);
1243 size of extracted image by default 64x48 (other imagesizes are
1244 currently ignored by AtmoWin)
1246 p_sys->i_atmo_width = var_CreateGetIntegerCommand( p_filter,
1247 CFG_PREFIX "width");
1248 p_sys->i_atmo_height = var_CreateGetIntegerCommand( p_filter,
1249 CFG_PREFIX "height");
1250 msg_Dbg(p_filter,"mini image size %d * %d pixels", p_sys->i_atmo_width,
1251 p_sys->i_atmo_height);
1254 because atmowin could also be used for lighten up the room - I think if you
1255 pause the video it would be useful to get a little bit more light into to
1256 your living room? - instead switching on a lamp?
1258 p_sys->b_usepausecolor = var_CreateGetBoolCommand( p_filter,
1259 CFG_PREFIX "usepausecolor" );
1260 p_sys->ui_pausecolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1261 CFG_PREFIX "pcolor-red");
1262 p_sys->ui_pausecolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1263 CFG_PREFIX "pcolor-green");
1264 p_sys->ui_pausecolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1265 CFG_PREFIX "pcolor-blue");
1266 p_sys->i_fadesteps = var_CreateGetIntegerCommand( p_filter,
1267 CFG_PREFIX "fadesteps");
1268 if(p_sys->i_fadesteps < 1)
1269 p_sys->i_fadesteps = 1;
1270 msg_Dbg(p_filter,"use pause color %d, RGB: %d, %d, %d, Fadesteps: %d",
1271 (int)p_sys->b_usepausecolor,
1272 p_sys->ui_pausecolor_red,
1273 p_sys->ui_pausecolor_green,
1274 p_sys->ui_pausecolor_blue,
1275 p_sys->i_fadesteps);
1278 this color is use on shutdown of the filter - the define the
1279 final light after playback... may be used to dim up the light -
1280 how it happens in the cinema...
1282 p_sys->ui_endcolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1283 CFG_PREFIX "ecolor-red");
1284 p_sys->ui_endcolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1285 CFG_PREFIX "ecolor-green");
1286 p_sys->ui_endcolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1287 CFG_PREFIX "ecolor-blue");
1288 p_sys->i_endfadesteps = var_CreateGetIntegerCommand( p_filter,
1289 CFG_PREFIX "efadesteps");
1290 if(p_sys->i_endfadesteps < 1)
1291 p_sys->i_endfadesteps = 1;
1292 msg_Dbg(p_filter,"use ende color RGB: %d, %d, %d, Fadesteps: %d",
1293 p_sys->ui_endcolor_red,
1294 p_sys->ui_endcolor_green,
1295 p_sys->ui_endcolor_blue,
1296 p_sys->i_endfadesteps);
1298 /* if the external DLL was loaded successfully call AtmoInitialize -
1299 (must be done for each thread where you wan't to use AtmoLight!
1301 int i = AtmoInitialize(p_filter, false);
1302 #if defined( WIN32 )
1303 if((i != 1) && !b_use_buildin_driver)
1305 /* COM Server for AtmoLight not running ?
1306 if the exe path is configured try to start the "userspace" driver
1308 psz_path = var_CreateGetStringCommand( p_filter,
1309 CFG_PREFIX "atmowinexe" );
1310 if(psz_path != NULL)
1312 STARTUPINFO startupinfo;
1313 PROCESS_INFORMATION pinfo;
1314 memset(&startupinfo, 0, sizeof(STARTUPINFO));
1315 startupinfo.cb = sizeof(STARTUPINFO);
1316 if(CreateProcess(psz_path, NULL, NULL, NULL,
1317 FALSE, 0, NULL, NULL, &startupinfo, &pinfo) == TRUE)
1319 msg_Dbg(p_filter,"launched AtmoWin from %s",psz_path);
1320 WaitForInputIdle(pinfo.hProcess, 5000);
1322 retry to initialize the library COM ... functionality
1323 after the server was launched
1325 i = AtmoInitialize(p_filter, false);
1327 msg_Err(p_filter,"failed to launch AtmoWin from %s", psz_path);
1334 if(i == 1) /* Init Atmolight success... */
1336 msg_Dbg( p_filter, "AtmoInitialize Ok!");
1338 /* Setup Transferbuffers for 64 x 48 , RGB with 32bit Per Pixel */
1339 AtmoCreateTransferBuffers(p_filter, BI_RGB, 4,
1340 p_sys->i_atmo_width,
1341 p_sys->i_atmo_height
1344 /* say the userspace driver that a live mode should be activated
1345 the functions returns the old mode for later restore!
1347 p_sys->i_AtmoOldEffect = AtmoSwitchEffect(p_filter, emLivePicture);
1350 live view can have two differnt source the AtmoWinA
1351 internal GDI Screencapture and the external one - which we
1354 AtmoSetLiveSource(p_filter, lvsExternal);
1356 /* enable other parts only if everything is fine */
1357 p_sys->b_enabled = true;
1363 /*****************************************************************************
1364 * CreateFilter: allocates AtmoLight video thread output method
1365 *****************************************************************************
1366 * This function allocates and initializes a AtmoLight vout method.
1367 *****************************************************************************/
1368 static int CreateFilter( vlc_object_t *p_this )
1370 filter_t *p_filter = (filter_t *)p_this;
1371 filter_sys_t *p_sys;
1373 /* Allocate structure */
1374 p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) );
1375 p_filter->p_sys = p_sys;
1376 if( p_filter->p_sys == NULL )
1378 msg_Err( p_filter, "out of memory for p_sys structure" );
1381 /* set all entries to zero */
1382 memset(p_sys, 0, sizeof( filter_sys_t ));
1384 /* further Setup Function pointers for videolan for calling my filter */
1385 p_filter->pf_video_filter = Filter;
1387 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
1390 AddStateVariableCallback(p_filter);
1392 AddCropVariableCallback(p_filter);
1394 AddAtmoSettingsVariablesCallbacks(p_filter);
1396 Atmo_SetupParameters(p_filter);
1404 /*****************************************************************************
1405 * DestroyFilter: destroy AtmoLight video thread output method
1406 *****************************************************************************
1407 * Terminate an output method created by CreateFilter
1408 *****************************************************************************/
1410 static void DestroyFilter( vlc_object_t *p_this )
1412 filter_t *p_filter = (filter_t *)p_this;
1413 filter_sys_t *p_sys = p_filter->p_sys;
1415 DelStateVariableCallback(p_filter);
1416 DelCropVariableCallback(p_filter);
1417 DelAtmoSettingsVariablesCallbacks(p_filter);
1419 Atmo_Shutdown(p_filter);
1421 #if defined( WIN32 )
1422 if(p_sys->h_AtmoCtrl != NULL)
1424 FreeLibrary(p_sys->h_AtmoCtrl);
1428 delete p_sys->p_atmo_dyndata;
1429 delete p_sys->p_atmo_config;
1431 vlc_mutex_destroy( &p_sys->filter_lock );
1438 function stolen from some other videolan source filter ;-)
1439 for the moment RGB is OK... but better would be a direct transformation
1442 static inline void yuv_to_rgb( uint8_t *r, uint8_t *g, uint8_t *b,
1443 uint8_t y1, uint8_t u1, uint8_t v1 )
1445 /* macros used for YUV pixel conversions */
1446 # define SCALEBITS 10
1447 # define ONE_HALF (1 << (SCALEBITS - 1))
1448 # define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
1449 # define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
1451 int y, cb, cr, r_add, g_add, b_add;
1455 r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;
1456 g_add = - FIX(0.34414*255.0/224.0) * cb
1457 - FIX(0.71414*255.0/224.0) * cr + ONE_HALF;
1458 b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;
1459 y = (y1 - 16) * FIX(255.0/219.0);
1460 *r = CLAMP((y + r_add) >> SCALEBITS);
1461 *g = CLAMP((y + g_add) >> SCALEBITS);
1462 *b = CLAMP((y + b_add) >> SCALEBITS);
1464 /******************************************************************************
1465 * ExtractMiniImage_YUV: extract a small image from the picture as 24-bit RGB
1466 *******************************************************************************
1467 * p_sys is a pointer to
1468 * p_inpic is the source frame
1469 * p_transfer_dest is the target buffer for the picture must be big enough!
1470 * (in win32 enviroment this buffer comes from the external DLL where it is
1471 * create as "variant array" and returned through the AtmoLockTransferbuffer
1473 static void ExtractMiniImage_YUV(filter_sys_t *p_sys,
1475 uint8_t *p_transfer_dest)
1482 uint8_t *p_rgb_dst_line_red;
1483 uint8_t *p_rgb_dst_line_green;
1484 uint8_t *p_rgb_dst_line_blue;
1489 /* calcute Pointers for Storage of B G R (A) */
1490 p_rgb_dst_line_blue = p_transfer_dest;
1491 p_rgb_dst_line_green = p_transfer_dest + 1;
1492 p_rgb_dst_line_red = p_transfer_dest + 2 ;
1494 int i_row_count = p_sys->i_atmo_height + 1;
1495 int i_col_count = p_sys->i_atmo_width + 1;
1496 int i_y_row,i_u_row,i_v_row,i_pixel_row;
1500 /* these two ugly loops extract the small image - goes it faster? how?
1501 the loops are so designed that there is a small border around the extracted
1502 image so we wont get column and row - zero from the frame, and not the most
1503 right and bottom pixels --- which may be clipped on computers useing TV out
1506 TODO: try to find out if the output is clipped through VLC - and try here
1507 to ingore the clipped away area for a better result!
1509 TODO: performance improvement in InitFilter percalculated the offsets of
1510 the lines inside the planes so I can save (i_row_count * 3) 2xMUL and
1511 one time DIV the same could be done for the inner loop I think...
1513 for(i_row = 1; i_row < i_row_count; i_row++)
1515 // calcute the current Lines in the source planes for this outputrow
1516 /* Adresscalcuation pointer to plane Length of one pixelrow in bytes
1517 calculate row now number
1520 p_inpic->format? transform Pixel row into row of plane...
1521 how? simple? fast? good?
1524 /* compute the source pixel row and respect the active cropping */
1525 i_pixel_row = (i_row * p_sys->i_crop_height) / i_row_count
1526 + p_sys->i_crop_y_offset;
1529 trans for these Pixel row into the row of each plane ..
1530 because planesize can differ from image size
1532 i_y_row = (i_pixel_row * p_inpic->p[Y_PLANE].i_visible_lines) /
1533 p_inpic->format.i_visible_height;
1535 i_u_row = (i_pixel_row * p_inpic->p[U_PLANE].i_visible_lines) /
1536 p_inpic->format.i_visible_height;
1538 i_v_row = (i_pixel_row * p_inpic->p[V_PLANE].i_visible_lines) /
1539 p_inpic->format.i_visible_height;
1541 /* calculate the pointers to the pixeldata for this row
1544 p_src_y = p_inpic->p[Y_PLANE].p_pixels +
1545 p_inpic->p[Y_PLANE].i_pitch * i_y_row;
1546 p_src_u = p_inpic->p[U_PLANE].p_pixels +
1547 p_inpic->p[U_PLANE].i_pitch * i_u_row;
1548 p_src_v = p_inpic->p[V_PLANE].p_pixels +
1549 p_inpic->p[V_PLANE].i_pitch * i_v_row;
1551 for(i_col = 1; i_col < i_col_count; i_col++)
1553 i_pixel_col = (i_col * p_sys->i_crop_width) / i_col_count +
1554 p_sys->i_crop_x_offset;
1556 trans for these Pixel row into the row of each plane ..
1557 because planesize can differ from image size
1559 i_xpos_y = (i_pixel_col * p_inpic->p[Y_PLANE].i_visible_pitch) /
1560 p_inpic->format.i_visible_width;
1561 i_xpos_u = (i_pixel_col * p_inpic->p[U_PLANE].i_visible_pitch) /
1562 p_inpic->format.i_visible_width;
1563 i_xpos_v = (i_pixel_col * p_inpic->p[V_PLANE].i_visible_pitch) /
1564 p_inpic->format.i_visible_width;
1566 yuv_to_rgb(p_rgb_dst_line_red,
1567 p_rgb_dst_line_green,
1568 p_rgb_dst_line_blue,
1574 /* +4 because output image should be RGB32 with dword alignment! */
1575 p_rgb_dst_line_red += 4;
1576 p_rgb_dst_line_green += 4;
1577 p_rgb_dst_line_blue += 4;
1583 /******************************************************************************
1584 * SaveBitmap: Saves the content of a transferbuffer as Bitmap to disk
1585 *******************************************************************************
1586 * just for debugging
1587 * p_sys -> configuration if Atmo from there the function will get height and
1589 * p_pixels -> should be the dword aligned BGR(A) image data
1590 * psz_filename -> filename where to store
1592 #if defined(__ATMO_DEBUG__)
1593 void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename)
1595 /* for debug out only used*/
1596 BITMAPINFO bmp_info;
1597 BITMAPFILEHEADER bmp_fileheader;
1600 memset(&bmp_info, 0, sizeof(BITMAPINFO));
1601 bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1602 bmp_info.bmiHeader.biSizeImage = p_sys->i_atmo_height *
1603 p_sys->i_atmo_width * 4;
1604 bmp_info.bmiHeader.biCompression = BI_RGB;
1605 bmp_info.bmiHeader.biWidth = p_sys->i_atmo_width;
1606 bmp_info.bmiHeader.biHeight = -p_sys->i_atmo_height;
1607 bmp_info.bmiHeader.biBitCount = 32;
1608 bmp_info.bmiHeader.biPlanes = 1;
1610 bmp_fileheader.bfReserved1 = 0;
1611 bmp_fileheader.bfReserved2 = 0;
1612 bmp_fileheader.bfSize = sizeof(BITMAPFILEHEADER) +
1613 sizeof(BITMAPINFOHEADER) +
1614 bmp_info.bmiHeader.biSizeImage;
1615 bmp_fileheader.bfType = VLC_TWOCC('M','B');
1616 bmp_fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) +
1617 sizeof(BITMAPINFOHEADER);
1619 fp_bitmap = fopen(psz_filename,"wb");
1620 if( fp_bitmap != NULL)
1622 fwrite(&bmp_fileheader, sizeof(BITMAPFILEHEADER), 1, fp_bitmap);
1623 fwrite(&bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp_bitmap);
1624 fwrite(p_pixels, bmp_info.bmiHeader.biSizeImage, 1, fp_bitmap);
1631 /****************************************************************************
1632 * CreateMiniImage: extracts a 64x48 pixel image from the frame
1633 * (there is a small border arround thats why the loops starts with one
1634 * instead zero) without any interpolation
1635 *****************************************************************************/
1636 static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic)
1638 filter_sys_t *p_sys = p_filter->p_sys;
1640 pointer to RGB Buffer created in external libary as safe array which
1641 is locked inside AtmoLockTransferBuffer
1643 uint8_t *p_transfer = NULL;
1644 #if defined( __ATMO_DEBUG__ )
1645 /* for debug out only used*/
1646 char sz_filename[MAX_PATH];
1650 Lock the before created VarArray (AtmoCreateTransferBuffers)
1651 inside my wrapper library and give me a pointer to the buffer!
1652 below linux a global buffer may be used and protected with a mutex?
1654 p_transfer = AtmoLockTransferBuffer(p_filter);
1655 if(p_transfer == NULL)
1657 msg_Err( p_filter, "AtmoLight no transferbuffer available. "\
1658 "AtmoLight will be disabled!");
1659 p_sys->b_enabled = false;
1664 do the call via pointer to function instead of having a
1667 p_sys->pf_extract_mini_image(p_sys, p_inpic, p_transfer);
1670 #if defined( __ATMO_DEBUG__ )
1672 if debugging enabled save every 128th image to disk
1674 if((p_sys->b_saveframes == true) && (p_sys->sz_framepath[0] != 0 ))
1677 if((p_sys->i_framecounter & 127) == 0)
1679 sprintf(sz_filename,"%satmo_dbg_%06d.bmp",p_sys->sz_framepath,
1680 p_sys->i_framecounter);
1681 msg_Dbg(p_filter, "SaveFrame %s",sz_filename);
1683 SaveBitmap(p_sys, p_transfer, sz_filename);
1685 p_sys->i_framecounter++;
1689 /* show the colors on the wall */
1690 AtmoSendPixelData(p_filter);
1696 /*****************************************************************************
1697 * Filter: calls the extract method and forwards the incomming picture 1:1
1698 *****************************************************************************
1700 *****************************************************************************/
1702 static picture_t * Filter( filter_t *p_filter, picture_t *p_pic )
1704 filter_sys_t *p_sys = p_filter->p_sys;
1705 if( !p_pic ) return NULL;
1707 if((p_sys->b_enabled == true) &&
1708 (p_sys->pf_extract_mini_image != NULL) &&
1709 (p_sys->b_pause_live == false))
1711 CreateMiniImage(p_filter, p_pic);
1718 /*****************************************************************************
1719 * FadeToColorThread: Threadmethod which changes slowly the color
1720 * to a target color defined in p_fadethread struct
1721 * use for: Fade to Pause Color, and Fade to End Color
1722 *****************************************************************************/
1723 static void FadeToColorThread(fadethread_t *p_fadethread)
1725 filter_sys_t *p_sys = (filter_sys_t *)p_fadethread->p_filter->p_sys;
1726 int i_steps_done = 0;
1736 vlc_thread_ready( p_fadethread );
1738 uint8_t *p_source = NULL;
1740 /* initialize AtmoWin for this thread! */
1741 AtmoInitialize(p_fadethread->p_filter , true);
1743 uint8_t *p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
1744 if(p_transfer != NULL) {
1745 /* safe colors as "32bit" Integers to avoid overflows*/
1746 i_pause_red = p_fadethread->ui_red;
1747 i_pause_blue = p_fadethread->ui_blue;
1748 i_pause_green = p_fadethread->ui_green;
1751 allocate a temporary buffer for the last send
1752 image size less then 15kb
1754 int i_size = 4 * p_sys->i_atmo_width * p_sys->i_atmo_height;
1755 p_source = (uint8_t *)malloc( i_size );
1756 if(p_source != NULL)
1759 get a copy of the last transfered image as orign for the
1762 memcpy(p_source, p_transfer, i_size);
1763 /* send the same pixel data again... to unlock the buffer! */
1764 AtmoSendPixelData( p_fadethread->p_filter );
1766 while( (!p_fadethread->b_die) &&
1767 (i_steps_done < p_fadethread->i_steps))
1769 p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
1770 if(!p_transfer) break; /* should not happen if it worked
1771 one time in the code above! */
1774 move all pixels in the mini image (64x48) one step closer to
1775 the desired color these loop takes the most time of this
1776 thread improvements wellcome!
1779 (i_index < i_size) && (!p_fadethread->b_die);
1782 i_src_blue = p_source[i_index+0];
1783 i_src_green = p_source[i_index+1];
1784 i_src_red = p_source[i_index+2];
1785 p_transfer[i_index+0] = (uint8_t) (((
1786 (i_pause_blue - i_src_blue)
1787 * i_steps_done)/p_fadethread->i_steps)
1790 p_transfer[i_index+1] = (uint8_t) (((
1791 (i_pause_green - i_src_green)
1792 * i_steps_done)/p_fadethread->i_steps)
1795 p_transfer[i_index+2] = (uint8_t) (((
1796 (i_pause_red - i_src_red)
1797 * i_steps_done)/p_fadethread->i_steps)
1801 /* send image to lightcontroller */
1802 AtmoSendPixelData( p_fadethread->p_filter );
1803 /* is there something like and interruptable sleep inside
1804 the VLC libaries? inside native win32 I would use an Event
1805 (CreateEvent) and here an WaitForSingleObject?
1807 if(p_fadethread->b_die) break;
1809 if(p_fadethread->b_die) break;
1811 if(p_fadethread->b_die) break;
1813 if(p_fadethread->b_die) break;
1818 /* in failure of malloc also unlock buffer */
1819 AtmoSendPixelData(p_fadethread->p_filter);
1822 /* call indirect to OleUnitialize() for this thread */
1823 AtmoFinalize(p_fadethread->p_filter, 0);
1826 /*****************************************************************************
1827 * CheckAndStopFadeThread: if there is a fadethread structure left, or running.
1828 ******************************************************************************
1829 * this function will stop the thread ... and waits for its termination
1830 * before removeing the objects from vout_sys_t ...
1831 ******************************************************************************/
1832 static void CheckAndStopFadeThread(filter_t *p_filter)
1834 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1835 vlc_mutex_lock( &p_sys->filter_lock );
1836 if(p_sys->p_fadethread != NULL)
1838 msg_Dbg(p_filter, "kill still running fadeing thread...");
1840 p_sys->p_fadethread->b_die = true;
1842 vlc_thread_join(p_sys->p_fadethread);
1844 vlc_object_release(p_sys->p_fadethread);
1845 p_sys->p_fadethread = NULL;
1847 vlc_mutex_unlock( &p_sys->filter_lock );
1850 /*****************************************************************************
1851 * StateCallback: Callback for the inputs variable "State" to get notified
1852 * about Pause and Continue Playback events.
1853 *****************************************************************************/
1854 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
1855 vlc_value_t oldval, vlc_value_t newval,
1858 filter_t *p_filter = (filter_t *)p_data;
1859 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1861 if((p_sys->b_usepausecolor == true) && (p_sys->b_enabled == true))
1863 msg_Dbg(p_filter, "state change from: %d to %d", oldval.i_int,
1866 if((newval.i_int == PAUSE_S) && (oldval.i_int == PLAYING_S))
1868 /* tell the other thread to stop sending images to light
1870 p_sys->b_pause_live = true;
1872 // ggf. alten Thread abräumen should not happen....
1873 CheckAndStopFadeThread(p_filter);
1875 // perpare spawn fadeing thread
1876 vlc_mutex_lock( &p_sys->filter_lock );
1878 launch only a new thread if there is none active!
1879 or waiting for cleanup
1881 if(p_sys->p_fadethread == NULL)
1883 p_sys->p_fadethread = (fadethread_t *)vlc_object_create(
1885 sizeof(fadethread_t) );
1887 p_sys->p_fadethread->p_filter = p_filter;
1888 p_sys->p_fadethread->ui_red = p_sys->ui_pausecolor_red;
1889 p_sys->p_fadethread->ui_green = p_sys->ui_pausecolor_green;
1890 p_sys->p_fadethread->ui_blue = p_sys->ui_pausecolor_blue;
1891 p_sys->p_fadethread->i_steps = p_sys->i_fadesteps;
1893 if( vlc_thread_create( p_sys->p_fadethread,
1894 "AtmoLight fadeing",
1896 VLC_THREAD_PRIORITY_LOW,
1899 msg_Err( p_filter, "cannot create FadeToColorThread" );
1900 vlc_object_release( p_sys->p_fadethread );
1901 p_sys->p_fadethread = NULL;
1904 vlc_mutex_unlock( &p_sys->filter_lock );
1907 if((newval.i_int == PLAYING_S) && (oldval.i_int == PAUSE_S))
1909 /* playback continues check thread state */
1910 CheckAndStopFadeThread(p_filter);
1911 /* reactivate the Render function... to do its normal work */
1912 p_sys->b_pause_live = false;
1919 /*****************************************************************************
1920 * AddPlaylistInputThreadStateCallback: Setup call back on "State" Variable
1921 *****************************************************************************
1922 * Add Callback function to the "state" variable of the input thread..
1923 * first find the PlayList and get the input thread from there to attach
1924 * my callback? is vlc_object_find the right way for this??
1925 *****************************************************************************/
1926 static void AddStateVariableCallback(filter_t *p_filter)
1928 playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_filter,
1929 VLC_OBJECT_PLAYLIST,
1933 input_thread_t *p_input = p_playlist->p_input;
1936 var_AddCallback( p_input, "state", StateCallback, p_filter );
1938 vlc_object_release( p_playlist );
1942 /*****************************************************************************
1943 * DelPlaylistInputThreadStateCallback: Remove call back on "State" Variable
1944 *****************************************************************************
1945 * Delete the callback function to the "state" variable of the input thread...
1946 * first find the PlayList and get the input thread from there to attach
1947 * my callback? is vlc_object_find the right way for this??
1948 *****************************************************************************/
1949 static void DelStateVariableCallback( filter_t *p_filter )
1951 playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_filter,
1952 VLC_OBJECT_PLAYLIST,
1956 input_thread_t *p_input = p_playlist->p_input;
1959 var_DelCallback( p_input, "state", StateCallback, p_filter );
1961 vlc_object_release( p_playlist );
1966 static int CropCallback(vlc_object_t *p_this, char const *psz_cmd,
1967 vlc_value_t oldval, vlc_value_t newval,
1970 vout_thread_t *p_vout = (vout_thread_t *)p_this;
1971 filter_t *p_filter = (filter_t *)p_data;
1972 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1975 //if the handler is attache to crop variable directly!
1976 int i_visible_width, i_visible_height, i_x_offset, i_y_offset;
1977 atmo_parse_crop(newval.psz_string, p_vout->fmt_render,
1979 i_visible_width, i_visible_height,
1980 i_x_offset, i_y_offset);
1981 p_sys->i_crop_x_offset = i_x_offset;
1982 p_sys->i_crop_y_offset = i_y_offset;
1983 p_sys->i_crop_width = i_visible_width;
1984 p_sys->i_crop_height = i_visible_height;
1987 p_sys->i_crop_x_offset = p_vout->fmt_in.i_x_offset;
1988 p_sys->i_crop_y_offset = p_vout->fmt_in.i_y_offset;
1989 p_sys->i_crop_width = p_vout->fmt_in.i_visible_width;
1990 p_sys->i_crop_height = p_vout->fmt_in.i_visible_height;
1992 msg_Dbg(p_filter, "cropping picture %ix%i to %i,%i,%ix%i",
1993 p_vout->fmt_in.i_width,
1994 p_vout->fmt_in.i_height,
1995 p_sys->i_crop_x_offset,
1996 p_sys->i_crop_y_offset,
1997 p_sys->i_crop_width,
1998 p_sys->i_crop_height
2005 static void AddCropVariableCallback( filter_t *p_filter)
2007 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2012 var_AddCallback( p_vout, "crop-update", CropCallback, p_filter );
2013 vlc_object_release( p_vout );
2017 static void DelCropVariableCallback( filter_t *p_filter)
2019 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2024 var_DelCallback( p_vout, "crop-update", CropCallback, p_filter );
2025 vlc_object_release( p_vout );
2030 /****************************************************************************
2031 * StateCallback: Callback for the inputs variable "State" to get notified
2032 * about Pause and Continue Playback events.
2033 *****************************************************************************/
2034 static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
2035 vlc_value_t oldval, vlc_value_t newval,
2038 filter_t *p_filter = (filter_t *)p_data;
2039 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
2041 CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
2045 msg_Dbg(p_filter, "apply AtmoSettingsCallback %s (int: %d -> %d)",
2051 if( !strcmp( psz_var, CFG_PREFIX "filtermode" ))
2052 p_atmo_config->setLiveViewFilterMode( (AtmoFilterMode)newval.i_int);
2054 else if( !strcmp( psz_var, CFG_PREFIX "PercentNew" ))
2055 p_atmo_config->setLiveViewFilter_PercentNew( newval.i_int );
2057 else if( !strcmp( psz_var, CFG_PREFIX "MeanLength" ))
2058 p_atmo_config->setLiveViewFilter_MeanLength( newval.i_int );
2060 else if( !strcmp( psz_var, CFG_PREFIX "MeanThreshold" ))
2061 p_atmo_config->setLiveViewFilter_MeanThreshold( newval.i_int );
2063 else if( !strcmp( psz_var, CFG_PREFIX "EdgeWeightning" ))
2064 p_atmo_config->setLiveView_EdgeWeighting( newval.i_int );
2066 else if( !strcmp( psz_var, CFG_PREFIX "Brightness" ))
2067 p_atmo_config->setLiveView_BrightCorrect( newval.i_int );
2069 else if( !strcmp( psz_var, CFG_PREFIX "DarknessLimit" ))
2070 p_atmo_config->setLiveView_DarknessLimit( newval.i_int );
2072 else if( !strcmp( psz_var, CFG_PREFIX "HueWinSize" ))
2073 p_atmo_config->setLiveView_HueWinSize( newval.i_int );
2075 else if( !strcmp( psz_var, CFG_PREFIX "SatWinSize" ))
2076 p_atmo_config->setLiveView_SatWinSize( newval.i_int );
2078 else if( !strcmp( psz_var, CFG_PREFIX "FrameDelay" ))
2079 p_atmo_config->setLiveView_FrameDelay( newval.i_int );
2081 else if( !strcmp( psz_var, CFG_PREFIX "whiteadj" ))
2082 p_atmo_config->setUseSoftwareWhiteAdj( newval.b_bool );
2084 else if( !strcmp( psz_var, CFG_PREFIX "white-red" ))
2085 p_atmo_config->setWhiteAdjustment_Red( newval.i_int );
2087 else if( !strcmp( psz_var, CFG_PREFIX "white-green" ))
2088 p_atmo_config->setWhiteAdjustment_Green( newval.i_int );
2090 else if( !strcmp( psz_var, CFG_PREFIX "white-blue" ))
2091 p_atmo_config->setWhiteAdjustment_Blue( newval.i_int );
2097 static void AddAtmoSettingsVariablesCallbacks(filter_t *p_filter)
2099 var_AddCallback( p_filter, CFG_PREFIX "filtermode",
2100 AtmoSettingsCallback, p_filter );
2101 var_AddCallback( p_filter, CFG_PREFIX "PercentNew",
2102 AtmoSettingsCallback, p_filter );
2105 var_AddCallback( p_filter, CFG_PREFIX "MeanLength",
2106 AtmoSettingsCallback, p_filter );
2107 var_AddCallback( p_filter, CFG_PREFIX "MeanThreshold",
2108 AtmoSettingsCallback, p_filter );
2110 var_AddCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2111 AtmoSettingsCallback, p_filter );
2112 var_AddCallback( p_filter, CFG_PREFIX "Brightness",
2113 AtmoSettingsCallback, p_filter );
2114 var_AddCallback( p_filter, CFG_PREFIX "DarknessLimit",
2115 AtmoSettingsCallback, p_filter );
2117 var_AddCallback( p_filter, CFG_PREFIX "HueWinSize",
2118 AtmoSettingsCallback, p_filter );
2119 var_AddCallback( p_filter, CFG_PREFIX "SatWinSize",
2120 AtmoSettingsCallback, p_filter );
2121 var_AddCallback( p_filter, CFG_PREFIX "FrameDelay",
2122 AtmoSettingsCallback, p_filter );
2125 var_AddCallback( p_filter, CFG_PREFIX "whiteadj",
2126 AtmoSettingsCallback, p_filter );
2127 var_AddCallback( p_filter, CFG_PREFIX "white-red",
2128 AtmoSettingsCallback, p_filter );
2129 var_AddCallback( p_filter, CFG_PREFIX "white-green",
2130 AtmoSettingsCallback, p_filter );
2131 var_AddCallback( p_filter, CFG_PREFIX "white-blue",
2132 AtmoSettingsCallback, p_filter );
2135 static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
2138 var_DelCallback( p_filter, CFG_PREFIX "filtermode",
2139 AtmoSettingsCallback, p_filter );
2141 var_DelCallback( p_filter, CFG_PREFIX "PercentNew",
2142 AtmoSettingsCallback, p_filter );
2143 var_DelCallback( p_filter, CFG_PREFIX "MeanLength",
2144 AtmoSettingsCallback, p_filter );
2145 var_DelCallback( p_filter, CFG_PREFIX "MeanThreshold",
2146 AtmoSettingsCallback, p_filter );
2148 var_DelCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2149 AtmoSettingsCallback, p_filter );
2150 var_DelCallback( p_filter, CFG_PREFIX "Brightness",
2151 AtmoSettingsCallback, p_filter );
2152 var_DelCallback( p_filter, CFG_PREFIX "DarknessLimit",
2153 AtmoSettingsCallback, p_filter );
2155 var_DelCallback( p_filter, CFG_PREFIX "HueWinSize",
2156 AtmoSettingsCallback, p_filter );
2157 var_DelCallback( p_filter, CFG_PREFIX "SatWinSize",
2158 AtmoSettingsCallback, p_filter );
2159 var_DelCallback( p_filter, CFG_PREFIX "FrameDelay",
2160 AtmoSettingsCallback, p_filter );
2163 var_DelCallback( p_filter, CFG_PREFIX "whiteadj",
2164 AtmoSettingsCallback, p_filter );
2165 var_DelCallback( p_filter, CFG_PREFIX "white-red",
2166 AtmoSettingsCallback, p_filter );
2167 var_DelCallback( p_filter, CFG_PREFIX "white-green",
2168 AtmoSettingsCallback, p_filter );
2169 var_DelCallback( p_filter, CFG_PREFIX "white-blue",
2170 AtmoSettingsCallback, p_filter );
2175 #if defined(__ATMO_DEBUG__)
2176 static void atmo_parse_crop(char *psz_cropconfig,
2177 video_format_t fmt_in,
2178 video_format_t fmt_render,
2179 int &i_visible_width, int &i_visible_height,
2180 int &i_x_offset, int &i_y_offset )
2182 int64_t i_aspect_num, i_aspect_den;
2183 unsigned int i_width, i_height;
2185 i_visible_width = fmt_in.i_visible_width;
2186 i_visible_height = fmt_in.i_visible_height;
2187 i_x_offset = fmt_in.i_x_offset;
2188 i_y_offset = fmt_in.i_y_offset;
2190 char *psz_end = NULL, *psz_parser = strchr( psz_cropconfig, ':' );
2193 /* We're using the 3:4 syntax */
2194 i_aspect_num = strtol( psz_cropconfig, &psz_end, 10 );
2195 if( psz_end == psz_cropconfig || !i_aspect_num ) return;
2197 i_aspect_den = strtol( ++psz_parser, &psz_end, 10 );
2198 if( psz_end == psz_parser || !i_aspect_den ) return;
2200 i_width = fmt_in.i_sar_den * fmt_render.i_visible_height *
2201 i_aspect_num / i_aspect_den / fmt_in.i_sar_num;
2203 i_height = fmt_render.i_visible_width*fmt_in.i_sar_num *
2204 i_aspect_den / i_aspect_num / fmt_in.i_sar_den;
2206 if( i_width < fmt_render.i_visible_width )
2208 i_x_offset = fmt_render.i_x_offset +
2209 (fmt_render.i_visible_width - i_width) / 2;
2210 i_visible_width = i_width;
2214 i_y_offset = fmt_render.i_y_offset +
2215 (fmt_render.i_visible_height - i_height) / 2;
2216 i_visible_height = i_height;
2221 psz_parser = strchr( psz_cropconfig, 'x' );
2224 /* Maybe we're using the <width>x<height>+<left>+<top> syntax */
2225 unsigned int i_crop_width, i_crop_height, i_crop_top, i_crop_left;
2227 i_crop_width = strtol( psz_cropconfig, &psz_end, 10 );
2228 if( psz_end != psz_parser ) return;
2230 psz_parser = strchr( ++psz_end, '+' );
2231 i_crop_height = strtol( psz_end, &psz_end, 10 );
2232 if( psz_end != psz_parser ) return;
2234 psz_parser = strchr( ++psz_end, '+' );
2235 i_crop_left = strtol( psz_end, &psz_end, 10 );
2236 if( psz_end != psz_parser ) return;
2239 i_crop_top = strtol( psz_end, &psz_end, 10 );
2240 if( *psz_end != '\0' ) return;
2242 i_width = i_crop_width;
2243 i_visible_width = i_width;
2245 i_height = i_crop_height;
2246 i_visible_height = i_height;
2248 i_x_offset = i_crop_left;
2249 i_y_offset = i_crop_top;
2253 /* Maybe we're using the <left>+<top>+<right>+<bottom> syntax */
2254 unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right;
2256 psz_parser = strchr( psz_cropconfig, '+' );
2257 i_crop_left = strtol( psz_cropconfig, &psz_end, 10 );
2258 if( psz_end != psz_parser ) return;
2260 psz_parser = strchr( ++psz_end, '+' );
2261 i_crop_top = strtol( psz_end, &psz_end, 10 );
2262 if( psz_end != psz_parser ) return;
2264 psz_parser = strchr( ++psz_end, '+' );
2265 i_crop_right = strtol( psz_end, &psz_end, 10 );
2266 if( psz_end != psz_parser ) return;
2269 i_crop_bottom = strtol( psz_end, &psz_end, 10 );
2270 if( *psz_end != '\0' ) return;
2272 i_width = fmt_render.i_visible_width - i_crop_left - i_crop_right;
2273 i_visible_width = i_width;
2275 i_height = fmt_render.i_visible_height - i_crop_top - i_crop_bottom;
2276 i_visible_height = i_height;
2278 i_x_offset = i_crop_left;
2279 i_y_offset = i_crop_top;