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__
37 #include <vlc_common.h>
38 #include <vlc_plugin.h>
41 #include <vlc_playlist.h>
42 #include "vlc_filter.h"
45 #include "AtmoDynData.h"
46 #include "AtmoLiveView.h"
47 #include "AtmoTools.h"
48 #include "AtmoExternalCaptureInput.h"
49 #include "AtmoConfig.h"
50 #include "AtmoConnection.h"
51 #include "AtmoSerialConnection.h"
54 /*****************************************************************************
56 *****************************************************************************/
57 /* directly to vlc related functions required that the module is accepted */
58 static int CreateFilter ( vlc_object_t * );
59 static void DestroyFilter ( vlc_object_t * );
60 static picture_t * Filter( filter_t *, picture_t *);
62 /* callback for global variable state pause / continue / stop events */
63 static void AddStateVariableCallback( filter_t *);
64 static void DelStateVariableCallback( filter_t *);
65 static int StateCallback(vlc_object_t *, char const *,
66 vlc_value_t, vlc_value_t, void *);
68 /* callback for variable crop-update */
69 static void AddCropVariableCallback( filter_t *);
70 static void DelCropVariableCallback( filter_t *);
71 static int CropCallback(vlc_object_t *, char const *,
72 vlc_value_t, vlc_value_t, void *);
74 /* callback for atmo settings variables whose change
75 should be immediately realized and applied to output
77 static void DelAtmoSettingsVariablesCallbacks(filter_t *);
78 static void AddAtmoSettingsVariablesCallbacks(filter_t *);
79 static int AtmoSettingsCallback(vlc_object_t *, char const *,
80 vlc_value_t, vlc_value_t, void *);
83 #if defined(__ATMO_DEBUG__)
84 static void atmo_parse_crop(char *psz_cropconfig,
85 video_format_t fmt_in,
86 video_format_t fmt_render,
88 int &i_visible_height,
94 /* function to shutdown the fade thread which is started on pause*/
95 static void CheckAndStopFadeThread(filter_t *);
97 /* extracts a small RGB (BGR) Image from an YUV image */
98 static void ExtractMiniImage_YUV(filter_sys_t *, picture_t *, uint8_t *);
100 #if defined(__ATMO_DEBUG__)
101 void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename);
104 /*****************************************************************************
105 * External Prototypes for the AtmoCtrlLib.DLL
106 *****************************************************************************/
108 * if effectmode = emLivePicture then the source could be GDI (Screencapture)
109 * or External - this means another application delivers Pixeldata to AtmoWin
110 * Clientsoftware through AtmoCtrlLib.DLL and the COM Api
113 #define lvsExternal 1
117 strings for settings menus and hints
119 #define MODULE_DESCRIPTION N_ ( \
120 "This module allows to control an so called AtmoLight device which "\
121 "is connected to your computer.\n"\
122 "AtmoLight is the homebrew version of that what Philips calls AmbiLight.\n"\
123 "If you need further informations feel free to visit us at\n\n"\
124 "http://www.vdr-wiki.de/wiki/index.php/Atmo-plugin\n"\
125 "http://www.vdr-wiki.de/wiki/index.php/AtmoWin\n\n"\
126 "there you will find detailed descriptions how to build it for your self and "\
127 "where you can get the required parts and so on.\n There you can also see "\
128 "pictures and some movies showing such a device in live action...")
132 #if defined( __ATMO_DEBUG__ )
133 # define SAVEFRAMES_TEXT N_("Save Debug Frames")
134 # define SAVEFRAMES_LONGTEXT N_("Writes every 128th miniframe to a folder.")
135 # define FRAMEPATH_TEXT N_("Debug Frame Folder")
136 # define FRAMEPATH_LONGTEXT N_("defines the path where the debugframes " \
140 #define WIDTH_TEXT N_("Extracted Image Width")
141 #define WIDTH_LONGTEXT N_("defines the width of the mini image for " \
142 "further processing (64 is default)")
144 #define HEIGHT_TEXT N_("Extracted Image Height")
145 #define HEIGHT_LONGTEXT N_("defines the height of the mini image for " \
146 "further processing (48 is default)")
148 #define PCOLOR_TEXT N_("use Pause Color")
149 #define PCOLOR_LONGTEXT N_("use the color defined below if the user " \
150 "paused the video.(have light to get another beer?)")
151 #define PCOLOR_RED_TEXT N_("Pause-Red")
152 #define PCOLOR_RED_LONGTEXT N_("the red component of pause color")
153 #define PCOLOR_GREEN_TEXT N_("Pause-Green")
154 #define PCOLOR_GREEN_LONGTEXT N_("the green component of pause color")
155 #define PCOLOR_BLUE_TEXT N_("Pause-Blue")
156 #define PCOLOR_BLUE_LONGTEXT N_("the blue component of pause color")
157 #define FADESTEPS_TEXT N_("Pause-Fadesteps")
158 #define FADESTEPS_LONGTEXT N_("Number of steps to change current color " \
159 "to pause color (each step takes 40ms)")
161 #define ECOLOR_RED_TEXT N_("End-Red")
162 #define ECOLOR_RED_LONGTEXT N_("the red component of the shutdown color")
163 #define ECOLOR_GREEN_TEXT N_("End-Green")
164 #define ECOLOR_GREEN_LONGTEXT N_("the green component of the shutdown color")
165 #define ECOLOR_BLUE_TEXT N_("End-Blue")
166 #define ECOLOR_BLUE_LONGTEXT N_("the blue component of the shutdown color")
167 #define EFADESTEPS_TEXT N_("End-Fadesteps")
168 #define EFADESTEPS_LONGTEXT N_("Number of steps to change current color to " \
169 "end color for dimming up the light in cinema " \
170 "style... (each step takes 40ms)")
172 #define USEWHITEADJ_TEXT N_("Use Software White adjust")
173 #define USEWHITEADJ_LONGTEXT N_("Should the buildin driver do a white " \
174 "adjust or you LED stripes? recommend.")
175 #define WHITE_RED_TEXT N_("White Red")
176 #define WHITE_RED_LONGTEXT N_("Red value of a pure white on your "\
178 #define WHITE_GREEN_TEXT N_("White Green")
179 #define WHITE_GREEN_LONGTEXT N_("Green value of a pure white on your "\
181 #define WHITE_BLUE_TEXT N_("White Blue")
182 #define WHITE_BLUE_LONGTEXT N_("Blue value of a pure white on your "\
185 #define SERIALDEV_TEXT N_("Serial Port/Device")
186 #define SERIALDEV_LONGTEXT N_("Name of the serial port where the AtmoLight "\
187 "controller is attached to\n on Windows usually "\
188 "something like COM1 or COM2 on Linux /dev/ttyS01 f.e.")
190 #define EDGE_TEXT N_("Edge Weightning")
191 #define EDGE_LONGTEXT N_("increasing this value will result in color "\
192 "more depending on the border of the frame")
193 #define BRIGHTNESS_TEXT N_("Brightness")
194 #define BRIGHTNESS_LONGTEXT N_("overall Brightness of you LED stripes")
195 #define DARKNESS_TEXT N_("Darkness Limit")
196 #define DARKNESS_LONGTEXT N_("pixels with a saturation lower than this will "\
197 "be ignored should be greater than one for "\
198 "letterboxed videos")
199 #define HUEWINSIZE_TEXT N_("Hue windowing")
200 #define HUEWINSIZE_LONGTEXT N_("used for statistics")
201 #define SATWINSIZE_TEXT N_("Sat windowing")
202 #define SATWINSIZE_LONGTEXT N_("used for statistics")
204 #define MEANLENGTH_TEXT N_("Filter length (ms)")
205 #define MEANLENGTH_LONGTEXT N_("Time it takes until a color is complete "\
206 "changed, removes flickering")
207 #define MEANTHRESHOLD_TEXT N_("Filter threshold")
208 #define MEANTHRESHOLD_LONGTEXT N_("How much a color must changed, for an "\
209 "imediate color change")
210 #define MEANPERCENTNEW_TEXT N_("Filter Smoothness %")
211 #define MEANPERCENTNEW_LONGTEXT N_("Filter Smoothness")
213 #define FILTERMODE_TEXT N_("Filtermode")
214 #define FILTERMODE_LONGTEXT N_("kind of filtering which should be use to "\
215 "calcuate the color output")
216 static int pi_filtermode_values[] = {
221 static const char *ppsz_filtermode_descriptions[] = {
227 #define FRAMEDELAY_TEXT N_("Framedelay")
228 #define FRAMEDELAY_LONGTEXT N_("helps to get video out and light effects "\
229 "insync values around 20ms should do the trick")
232 #define CHANNEL_0_ASSIGN_TEXT N_("Channel summary")
233 #define CHANNEL_1_ASSIGN_TEXT N_("Channel left")
234 #define CHANNEL_2_ASSIGN_TEXT N_("Channel right")
235 #define CHANNEL_3_ASSIGN_TEXT N_("Channel top")
236 #define CHANNEL_4_ASSIGN_TEXT N_("Channel bottom")
238 #define CHANNELASSIGN_LONGTEXT N_("maps the hardware channel X to logical "\
239 "channel Y to fix wrong wiring:-)")
240 static int pi_channel_assignment_values[] = {
248 static const char *ppsz_channel_assignment_descriptions[] = {
257 #define ZONE_0_GRADIENT_TEXT N_("summary gradient")
258 #define ZONE_1_GRADIENT_TEXT N_("left gradient")
259 #define ZONE_2_GRADIENT_TEXT N_("right gradient")
260 #define ZONE_3_GRADIENT_TEXT N_("top gradient")
261 #define ZONE_4_GRADIENT_TEXT N_("bottom gradient")
262 #define ZONE_X_GRADIENT_LONG_TEXT N_("defines a small bitmap with 64x48 "\
263 "pixels, containing a grayscale gradient")
266 # define ATMOWINEXE_TEXT N_("Filename of AtmoWinA.exe")
267 # define ATMOWINEXE_LONGTEXT N_("if you wan't that the AtmoLight control "\
268 "software is launched by\nVLC enter the "\
269 "complete Filename of AtmoWinA.exe here")
270 # define USEBUILDIN_TEXT N_("Use buildin AtmoLight")
271 # define USEBUILDIN_LONGTEXT N_("VideoLan will directly use your AtmoLight "\
272 "hardware without running the external "\
273 "AtmoWinA.exe Userspace driver.")
276 #define CFG_PREFIX "atmo-"
278 /*****************************************************************************
280 *****************************************************************************/
282 set_description( N_("AtmoLight Filter") );
283 set_help( MODULE_DESCRIPTION );
284 set_shortname( N_( "AtmoLight" ));
285 set_capability( "video filter2", 0 );
287 set_category( CAT_VIDEO );
288 set_subcategory( SUBCAT_VIDEO_VFILTER );
291 set_section( N_("Choose between the buildin AtmoLight "\
292 "driver or the external" ), 0 );
295 only on win32 exists the option to use the buildin driver or
296 the more flexible external driver application
298 add_bool(CFG_PREFIX "usebuildin", true, NULL,
299 USEBUILDIN_TEXT, USEBUILDIN_LONGTEXT, false);
300 add_string(CFG_PREFIX "serialdev", "COM1", NULL,
301 SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false );
304 on win32 the executeable external driver application
305 for automatic start if needed
307 add_file(CFG_PREFIX "atmowinexe", NULL, NULL,
308 ATMOWINEXE_TEXT, ATMOWINEXE_LONGTEXT, false );
310 set_section( N_("Enter connection of your AtmoLight hardware" ), 0 );
311 add_string(CFG_PREFIX "serialdev", "/dev/ttyS01", NULL,
312 SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false );
316 color which is showed if you want durring pausing
317 your movie ... used for both buildin / external
319 set_section( N_("Illuminate the room with this color on pause" ), 0 );
320 add_bool(CFG_PREFIX "usepausecolor", false, NULL,
321 PCOLOR_TEXT, PCOLOR_LONGTEXT, false);
322 add_integer_with_range(CFG_PREFIX "pcolor-red", 0, 0, 255, NULL,
323 PCOLOR_RED_TEXT, PCOLOR_RED_LONGTEXT, false);
324 add_integer_with_range(CFG_PREFIX "pcolor-green", 0, 0, 255, NULL,
325 PCOLOR_GREEN_TEXT, PCOLOR_GREEN_LONGTEXT, false);
326 add_integer_with_range(CFG_PREFIX "pcolor-blue", 192, 0, 255, NULL,
327 PCOLOR_BLUE_TEXT, PCOLOR_BLUE_LONGTEXT, false);
328 add_integer_with_range(CFG_PREFIX "fadesteps", 50, 1, 250, NULL,
329 FADESTEPS_TEXT, FADESTEPS_LONGTEXT, false);
332 color which is showed if you finished watching your movie ...
333 used for both buildin / external
335 set_section( N_("Illuminate the room with this color on shutdown" ), 0 );
336 add_integer_with_range(CFG_PREFIX "ecolor-red", 192, 0, 255, NULL,
337 ECOLOR_RED_TEXT, ECOLOR_RED_LONGTEXT, false);
338 add_integer_with_range(CFG_PREFIX "ecolor-green", 192, 0, 255, NULL,
339 ECOLOR_GREEN_TEXT, ECOLOR_GREEN_LONGTEXT, false);
340 add_integer_with_range(CFG_PREFIX "ecolor-blue", 192, 0, 255, NULL,
341 ECOLOR_BLUE_TEXT, ECOLOR_BLUE_LONGTEXT, false);
342 add_integer_with_range(CFG_PREFIX "efadesteps", 50, 1, 250, NULL,
343 EFADESTEPS_TEXT, EFADESTEPS_LONGTEXT, false);
346 settings only for the buildin driver (if external driver app is used
347 these parameters are ignored.)
349 definition of parameters for the buildin filter ...
351 set_section( N_("Settings only for buildin Live Video Processor" ), 0 );
353 add_integer_with_range(CFG_PREFIX "EdgeWeightning", 8, 1, 30, NULL,
354 EDGE_TEXT, EDGE_LONGTEXT, false);
356 add_integer_with_range(CFG_PREFIX "Brightness", 100, 50, 300, NULL,
357 BRIGHTNESS_TEXT, BRIGHTNESS_LONGTEXT, false);
359 add_integer_with_range(CFG_PREFIX "DarknessLimit", 5, 0, 10, NULL,
360 DARKNESS_TEXT, DARKNESS_LONGTEXT, false);
362 add_integer_with_range(CFG_PREFIX "HueWinSize", 3, 0, 5, NULL,
363 HUEWINSIZE_TEXT, HUEWINSIZE_LONGTEXT, false);
365 add_integer_with_range(CFG_PREFIX "SatWinSize", 3, 0, 5, NULL,
366 SATWINSIZE_TEXT, SATWINSIZE_LONGTEXT, false);
368 add_integer(CFG_PREFIX "filtermode", (int)afmCombined, NULL,
369 FILTERMODE_TEXT, FILTERMODE_LONGTEXT, false );
371 change_integer_list(pi_filtermode_values, ppsz_filtermode_descriptions, 0 );
373 add_integer_with_range(CFG_PREFIX "MeanLength", 300, 300, 5000, NULL,
374 MEANLENGTH_TEXT, MEANLENGTH_LONGTEXT, false);
376 add_integer_with_range(CFG_PREFIX "MeanThreshold", 40, 1, 100, NULL,
377 MEANTHRESHOLD_TEXT, MEANTHRESHOLD_LONGTEXT, false);
379 add_integer_with_range(CFG_PREFIX "PercentNew", 50, 1, 100, NULL,
380 MEANPERCENTNEW_TEXT, MEANPERCENTNEW_LONGTEXT, false);
382 add_integer_with_range(CFG_PREFIX "FrameDelay", 18, 0, 35, NULL,
383 FRAMEDELAY_TEXT, FRAMEDELAY_LONGTEXT, false);
386 output channel reordering
388 set_section( N_("Change channel assignment (fixes wrong wiring)" ), 0 );
389 add_integer( CFG_PREFIX "channel_0", 0, NULL,
390 CHANNEL_0_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
391 change_integer_list( pi_channel_assignment_values,
392 ppsz_channel_assignment_descriptions, 0 );
394 add_integer( CFG_PREFIX "channel_1", 1, NULL,
395 CHANNEL_1_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
396 change_integer_list( pi_channel_assignment_values,
397 ppsz_channel_assignment_descriptions, 0 );
399 add_integer( CFG_PREFIX "channel_2", 2, NULL,
400 CHANNEL_2_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
401 change_integer_list( pi_channel_assignment_values,
402 ppsz_channel_assignment_descriptions, 0 );
404 add_integer( CFG_PREFIX "channel_3", 3, NULL,
405 CHANNEL_3_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
406 change_integer_list( pi_channel_assignment_values,
407 ppsz_channel_assignment_descriptions, 0 );
409 add_integer( CFG_PREFIX "channel_4", 4, NULL,
410 CHANNEL_4_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false );
411 change_integer_list( pi_channel_assignment_values,
412 ppsz_channel_assignment_descriptions, 0 );
415 LED color white calibration
417 set_section( N_("Adjust the white light to your LED stripes" ), 0 );
418 add_bool(CFG_PREFIX "whiteadj", true, NULL,
419 USEWHITEADJ_TEXT, USEWHITEADJ_LONGTEXT, false);
420 add_integer_with_range(CFG_PREFIX "white-red", 255, 0, 255, NULL,
421 WHITE_RED_TEXT, WHITE_RED_LONGTEXT, false);
423 add_integer_with_range(CFG_PREFIX "white-green", 255, 0, 255, NULL,
424 WHITE_GREEN_TEXT, WHITE_GREEN_LONGTEXT, false);
426 add_integer_with_range(CFG_PREFIX "white-blue", 255, 0, 255, NULL,
427 WHITE_BLUE_TEXT, WHITE_BLUE_LONGTEXT, false);
428 /* end of definition of parameter for the buildin filter ... part 1 */
432 only for buildin (external has own definition) per default the calucation
433 used linear gradients for assigning a priority to the pixel - depending
434 how near they are to the border ...for changing this you can create 64x48
435 Pixel BMP files - which contain your own grayscale... (you can produce funny
436 effects with this...) the images MUST not compressed, should have 24-bit per
437 pixel, or a simple 256 color grayscale palette
439 set_section( N_("Change gradients" ), 0 );
440 add_file(CFG_PREFIX "gradient_zone_0", NULL, NULL,
441 ZONE_0_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
442 add_file(CFG_PREFIX "gradient_zone_1", NULL, NULL,
443 ZONE_1_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
444 add_file(CFG_PREFIX "gradient_zone_2", NULL, NULL,
445 ZONE_2_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
446 add_file(CFG_PREFIX "gradient_zone_3", NULL, NULL,
447 ZONE_3_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
448 add_file(CFG_PREFIX "gradient_zone_4", NULL, NULL,
449 ZONE_4_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true );
452 #if defined(__ATMO_DEBUG__)
453 add_bool(CFG_PREFIX "saveframes", false, NULL,
454 SAVEFRAMES_TEXT, SAVEFRAMES_LONGTEXT, false);
455 add_string(CFG_PREFIX "framepath", "", NULL,
456 FRAMEPATH_TEXT, FRAMEPATH_LONGTEXT, false );
459 may be later if computers gets more power ;-) than now we increase
460 the samplesize from which we do the stats for output color calculation
462 add_integer_with_range(CFG_PREFIX "width", 64, 64, 512, NULL,
463 WIDTH_TEXT, WIDTH_LONGTEXT, true);
464 add_integer_with_range(CFG_PREFIX "height", 48, 48, 384, NULL,
465 HEIGHT_TEXT, HEIGHT_LONGTEXT, true);
467 add_shortcut( "atmo" );
468 set_callbacks( CreateFilter, DestroyFilter );
472 static const char *const ppsz_filter_options[] = {
519 #if defined(__ATMO_DEBUG__)
534 /*****************************************************************************
535 * fadethread_t: Color Fading Thread
536 *****************************************************************************
537 * changes slowly the color of the output if videostream gets paused...
538 *****************************************************************************
544 /* tell the thread which color should be the target of fading */
548 /* how many steps should happen until this */
553 static void FadeToColorThread(fadethread_t *p_fadethread);
556 /*****************************************************************************
557 * filter_sys_t: AtmoLight filter method descriptor
558 *****************************************************************************
559 * It describes the AtmoLight specific properties of an video filter.
560 *****************************************************************************/
564 special for the access of the p_fadethread member all other members
565 need no special protection so far!
567 vlc_mutex_t filter_lock;
570 int32_t i_AtmoOldEffect;
573 int32_t i_atmo_width;
574 int32_t i_atmo_height;
576 #if defined(__ATMO_DEBUG__)
579 char sz_framepath[MAX_PATH];
582 /* light color durring movie pause ... */
583 bool b_usepausecolor;
584 uint8_t ui_pausecolor_red;
585 uint8_t ui_pausecolor_green;
586 uint8_t ui_pausecolor_blue;
589 /* light color on movie finish ... */
590 uint8_t ui_endcolor_red;
591 uint8_t ui_endcolor_green;
592 uint8_t ui_endcolor_blue;
595 fadethread_t *p_fadethread;
597 /* Variables for buildin driver only... */
599 /* is only present and initialized if the internal driver is used*/
600 CAtmoConfig *p_atmo_config;
601 /* storage for temporal settings "volatile" */
602 CAtmoDynData *p_atmo_dyndata;
603 /* initialized for buildin driver with AtmoCreateTransferBuffers */
604 BITMAPINFOHEADER mini_image_format;
605 /* is only use buildin driver! */
606 uint8_t *p_atmo_transfer_buffer;
607 /* end buildin driver */
610 contains the real output size of the video calculated on
611 change event of the variable "crop" from vout
613 int32_t i_crop_x_offset;
614 int32_t i_crop_y_offset;
615 int32_t i_crop_width;
616 int32_t i_crop_height;
618 void (*pf_extract_mini_image) (filter_sys_t *p_sys,
620 uint8_t *p_transfer_dest);
623 /* External Library as wrapper arround COM Stuff */
624 HINSTANCE h_AtmoCtrl;
625 int32_t (*pf_ctrl_atmo_initialize) (void);
626 void (*pf_ctrl_atmo_finalize) (int32_t what);
627 int32_t (*pf_ctrl_atmo_switch_effect) (int32_t);
628 int32_t (*pf_ctrl_atmo_set_live_source) (int32_t);
629 void (*pf_ctrl_atmo_create_transfer_buffers) (int32_t, int32_t,
631 uint8_t* (*pf_ctrl_atmo_lock_transfer_buffer) (void);
632 void (*pf_ctrl_atmo_send_pixel_data) (void);
637 initialize previously configured Atmo Light environment
638 - if internal is enabled try to access the device on the serial port
639 - if not internal is enabled and we are on win32 try to initialize
640 the previously loaded DLL ...
642 Return Values may be: -1 (failed for some reason - filter will be disabled)
645 static int32_t AtmoInitialize(filter_t *p_filter, bool b_for_thread)
647 filter_sys_t *p_sys = p_filter->p_sys;
648 if(p_sys->p_atmo_config)
650 if(b_for_thread == false)
653 /* setup Output Threads ... */
654 msg_Dbg( p_filter, "open serial connection %s",
655 p_sys->p_atmo_config->getSerialDevice());
657 if(CAtmoTools::RecreateConnection(p_sys->p_atmo_dyndata) == ATMO_TRUE)
659 msg_Dbg( p_filter, "start live view thread ...");
660 CAtmoTools::SwitchEffect(p_sys->p_atmo_dyndata, emLivePicture);
661 msg_Dbg( p_filter, "live view thread launched...");
665 msg_Err( p_filter,"failed to open serial device? some other software/driver may use it?");
669 } else if(p_sys->pf_ctrl_atmo_initialize)
671 /* on win32 with active ctrl dll */
672 return p_sys->pf_ctrl_atmo_initialize();
679 prepare the shutdown of the effect threads,
680 for build in filter - close the serialport after finishing the threads...
681 cleanup possible loaded DLL...
683 static void AtmoFinalize(filter_t *p_filter, int32_t what)
685 filter_sys_t *p_sys = p_filter->p_sys;
686 if(p_sys->p_atmo_config)
690 CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
693 p_atmo_dyndata->LockCriticalSection();
695 CThread *p_effect_thread = p_atmo_dyndata->getEffectThread();
696 p_atmo_dyndata->setEffectThread(NULL);
697 if(p_effect_thread != NULL)
700 forced the thread to die...
701 and wait for termination of the thread
703 p_effect_thread->Terminate();
704 delete p_effect_thread;
705 msg_Dbg( p_filter, "effect thread died peacefully");
709 close serial port if it is open (all OS specific is inside
710 CAtmoSerialConnection implemented / defined)
712 CAtmoConnection *p_atmo_connection =
713 p_atmo_dyndata->getAtmoConnection();
714 p_atmo_dyndata->setAtmoConnection(NULL);
715 if(p_atmo_connection) {
716 p_atmo_connection->CloseConnection();
717 delete p_atmo_connection;
719 p_atmo_dyndata->UnLockCriticalSection();
723 } else if(p_sys->pf_ctrl_atmo_finalize)
725 /* on win32 with active ctrl dll */
726 p_sys->pf_ctrl_atmo_finalize(what);
732 switch the current light effect - does only something on win32, with the
733 external libraries - if the buildin effects are used nothing happens
735 static int32_t AtmoSwitchEffect(filter_t *p_filter, int32_t newMode)
737 filter_sys_t *p_sys = p_filter->p_sys;
738 if(p_sys->p_atmo_config)
743 doesnt know different modes for effects so this
744 function call would just do nothing special
749 } else if(p_sys->pf_ctrl_atmo_switch_effect)
751 /* on win32 with active ctrl dll */
752 return p_sys->pf_ctrl_atmo_switch_effect(newMode);
759 set the current live picture source, does only something on win32,
760 with the external libraries - if the buildin effects are used nothing
763 static int32_t AtmoSetLiveSource(filter_t *p_filter, int32_t newSource)
765 filter_sys_t *p_sys = p_filter->p_sys;
766 if(p_sys->p_atmo_config)
771 doesnt know different sources so this
772 function call would just do nothing special
776 } else if(p_sys->pf_ctrl_atmo_set_live_source)
778 /* on win32 with active ctrl dll */
779 return p_sys->pf_ctrl_atmo_set_live_source(newSource);
786 setup the pixel transferbuffers which is used to transfer pixeldata from
787 the filter to the effect thread, and possible accross the process
788 boundaries on win32, with the external DLL
790 static void AtmoCreateTransferBuffers(filter_t *p_filter,
792 int32_t bytePerPixel,
796 filter_sys_t *p_sys = p_filter->p_sys;
797 if(p_sys->p_atmo_config)
800 we need a buffer where the image is stored (only for transfer
801 to the processing thread)
803 if(p_sys->p_atmo_transfer_buffer)
804 free(p_sys->p_atmo_transfer_buffer);
806 p_sys->p_atmo_transfer_buffer = (uint8_t *)malloc(bytePerPixel *
809 memset(&p_sys->mini_image_format,0,sizeof(BITMAPINFOHEADER));
811 p_sys->mini_image_format.biSize = sizeof(BITMAPINFOHEADER);
812 p_sys->mini_image_format.biWidth = width;
813 p_sys->mini_image_format.biHeight = height;
814 p_sys->mini_image_format.biBitCount = bytePerPixel*8;
815 p_sys->mini_image_format.biCompression = FourCC;
818 } else if(p_sys->pf_ctrl_atmo_create_transfer_buffers)
820 /* on win32 with active ctrl dll */
821 p_sys->pf_ctrl_atmo_create_transfer_buffers(FourCC,
830 acquire the transfer buffer pointer the buildin version only
831 returns the pointer to the allocated buffer ... the
832 external version on win32 has to do some COM stuff to lock the
833 Variant Byte array which is behind the buffer
835 static uint8_t* AtmoLockTransferBuffer(filter_t *p_filter)
837 filter_sys_t *p_sys = p_filter->p_sys;
838 if(p_sys->p_atmo_config)
840 return p_sys->p_atmo_transfer_buffer;
842 } else if(p_sys->pf_ctrl_atmo_lock_transfer_buffer)
844 /* on win32 with active ctrl dll */
845 return p_sys->pf_ctrl_atmo_lock_transfer_buffer();
852 send the content of current pixel buffer got with AtmoLockTransferBuffer
853 to the processing threads
854 - build in version - will forward the data to AtmoExternalCaptureInput Thread
855 - win32 external - will do the same, but across the process boundaries via
856 COM to the AtmoWinA.exe Process
858 static void AtmoSendPixelData(filter_t *p_filter)
860 filter_sys_t *p_sys = p_filter->p_sys;
861 if(p_sys->p_atmo_config && p_sys->p_atmo_transfer_buffer)
863 CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
867 the cast will go Ok because we are inside videolan there is only
868 this kind of effect thread implemented!
871 CAtmoLiveView *p_atmo_live_view_thread =
872 (CAtmoLiveView *)p_atmo_dyndata->getEffectThread();
873 if(p_atmo_live_view_thread)
876 the same as above inside videolan only this single kind of
877 input exists so we can cast without further tests!
879 CAtmoExternalCaptureInput *p_atmo_external_capture_input_thread =
880 (CAtmoExternalCaptureInput *)p_atmo_live_view_thread->getAtmoInput();
881 if(p_atmo_external_capture_input_thread)
884 this call will do a 1:1 copy of this buffer, and wakeup
885 the thread from normal sleeping
887 p_atmo_external_capture_input_thread->
888 DeliverNewSourceDataPaket(&p_sys->mini_image_format,
889 p_sys->p_atmo_transfer_buffer);
894 } else if(p_sys->pf_ctrl_atmo_send_pixel_data)
896 /* on win32 with active ctrl dll */
897 p_sys->pf_ctrl_atmo_send_pixel_data();
903 Shutdown AtmoLight finally - is call from DestroyFilter
904 does the cleanup restores the effectmode on the external Software
905 (only win32) and possible setup the final light ...
907 static void Atmo_Shutdown(filter_t *p_filter)
909 filter_sys_t *p_sys = p_filter->p_sys;
911 if(p_sys->b_enabled == true)
914 if there is a still running show pause color thread kill him!
916 CheckAndStopFadeThread(p_filter);
918 if(p_sys->p_atmo_config || (p_sys->i_AtmoOldEffect == emStaticColor))
921 fade to end color (in case of external AtmoWin Software
922 assume that the static color will equal to this
923 one to get a soft change and no flash!
925 p_sys->b_pause_live = true;
927 // perpare spawn fadeing thread
928 vlc_mutex_lock( &p_sys->filter_lock );
930 p_sys->p_fadethread = (fadethread_t *)vlc_object_create( p_filter,
931 sizeof(fadethread_t) );
933 p_sys->p_fadethread->p_filter = p_filter;
934 p_sys->p_fadethread->ui_red = p_sys->ui_endcolor_red;
935 p_sys->p_fadethread->ui_green = p_sys->ui_endcolor_green;
936 p_sys->p_fadethread->ui_blue = p_sys->ui_endcolor_blue;
937 p_sys->p_fadethread->i_steps = p_sys->i_endfadesteps;
939 if( vlc_thread_create( p_sys->p_fadethread,
942 VLC_THREAD_PRIORITY_LOW,
945 msg_Err( p_filter, "cannot create FadeToColorThread" );
946 vlc_object_release( p_sys->p_fadethread );
947 p_sys->p_fadethread = NULL;
948 vlc_mutex_unlock( &p_sys->filter_lock );
952 vlc_mutex_unlock( &p_sys->filter_lock );
954 /* wait for the thread... */
955 vlc_thread_join(p_sys->p_fadethread);
957 vlc_object_release(p_sys->p_fadethread);
959 p_sys->p_fadethread = NULL;
963 if(p_sys->i_AtmoOldEffect != emLivePicture)
964 AtmoSwitchEffect(p_filter, p_sys->i_AtmoOldEffect);
966 AtmoSetLiveSource(p_filter, lvsGDI);
968 AtmoFinalize(p_filter, 1);
970 /* disable filter method .. */
971 p_sys->b_enabled = false;
976 initialize the filter_sys_t structure with the data from the settings
977 variables - if the external filter on win32 is enabled try loading the DLL,
978 if this fails fallback to the buildin software
980 static void Atmo_SetupParameters(filter_t *p_filter)
982 bool b_use_buildin_driver = true;
984 filter_sys_t *p_sys = p_filter->p_sys;
987 /* default filter disabled until DLL loaded and Init Success!*/
988 p_sys->b_enabled = false;
990 /* setup default mini image size (may be later a user option) */
991 p_sys->i_atmo_width = 64;
992 p_sys->i_atmo_height = 48;
995 vlc_mutex_init( &p_sys->filter_lock );
1000 only on WIN32 the user has the choice between
1001 internal driver and external
1003 b_use_buildin_driver = var_CreateGetBoolCommand( p_filter,
1004 CFG_PREFIX "usebuildin" );
1006 if(b_use_buildin_driver == false) {
1008 /* Load the Com Wrapper Library (source available) */
1009 p_sys->h_AtmoCtrl = LoadLibraryA("AtmoCtrlLib.dll");
1010 if(p_sys->h_AtmoCtrl != NULL)
1012 msg_Dbg( p_filter, "LoadLibrary('AtmoCtrlLib.dll'); Success");
1014 /* importing all required functions I hope*/
1015 p_sys->pf_ctrl_atmo_initialize =
1016 (int32_t (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoInitialize");
1017 if(!p_sys->pf_ctrl_atmo_initialize)
1018 msg_Err( p_filter, "export AtmoInitialize missing.");
1020 p_sys->pf_ctrl_atmo_finalize =
1021 (void (*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoFinalize");
1022 if(!p_sys->pf_ctrl_atmo_finalize)
1023 msg_Err( p_filter, "export AtmoFinalize missing.");
1025 p_sys->pf_ctrl_atmo_switch_effect =
1026 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSwitchEffect");
1027 if(!p_sys->pf_ctrl_atmo_switch_effect)
1028 msg_Err( p_filter, "export AtmoSwitchEffect missing.");
1030 p_sys->pf_ctrl_atmo_set_live_source =
1031 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSetLiveSource");
1032 if(!p_sys->pf_ctrl_atmo_set_live_source)
1033 msg_Err( p_filter, "export AtmoSetLiveSource missing.");
1035 p_sys->pf_ctrl_atmo_create_transfer_buffers =
1036 (void (*)(int32_t, int32_t, int32_t , int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoCreateTransferBuffers");
1037 if(!p_sys->pf_ctrl_atmo_create_transfer_buffers)
1038 msg_Err( p_filter, "export AtmoCreateTransferBuffers missing.");
1040 p_sys->pf_ctrl_atmo_lock_transfer_buffer=
1041 (uint8_t*(*) (void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoLockTransferBuffer");
1042 if(!p_sys->pf_ctrl_atmo_lock_transfer_buffer)
1043 msg_Err( p_filter, "export AtmoLockTransferBuffer missing.");
1045 p_sys->pf_ctrl_atmo_send_pixel_data =
1046 (void (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSendPixelData");
1047 if(!p_sys->pf_ctrl_atmo_send_pixel_data)
1048 msg_Err( p_filter, "export AtmoSendPixelData missing.");
1050 /* the DLL is missing try internal filter ...*/
1051 msg_Warn( p_filter, "AtmoCtrlLib.dll missing fallback to internal driver");
1052 b_use_buildin_driver = true;
1058 if(b_use_buildin_driver == true) {
1059 msg_Dbg( p_filter, "use buildin driver");
1061 now we have to read a lof of options from the config dialog
1062 most important the serial device if not set ... we can skip
1063 the rest and disable the filter...
1065 char *psz_serialdev = var_CreateGetStringCommand( p_filter,
1066 CFG_PREFIX "serialdev" );
1067 if(psz_serialdev && (strlen(psz_serialdev)>0)) {
1068 msg_Dbg( p_filter, "use buildin driver on port %s",psz_serialdev);
1070 p_sys->p_atmo_config = new CAtmoConfig();
1072 p_sys->p_atmo_config->setSerialDevice(psz_serialdev);
1074 p_sys->p_atmo_config->setLiveViewFilterMode(
1075 (AtmoFilterMode)var_CreateGetIntegerCommand( p_filter,
1076 CFG_PREFIX "filtermode")
1079 p_sys->p_atmo_config->setLiveViewFilter_PercentNew(
1080 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "PercentNew")
1082 p_sys->p_atmo_config->setLiveViewFilter_MeanLength(
1083 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanLength")
1085 p_sys->p_atmo_config->setLiveViewFilter_MeanThreshold(
1086 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanThreshold")
1089 p_sys->p_atmo_config->setLiveView_EdgeWeighting(
1090 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "EdgeWeightning")
1092 p_sys->p_atmo_config->setLiveView_BrightCorrect(
1093 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "Brightness")
1095 p_sys->p_atmo_config->setLiveView_DarknessLimit(
1096 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "DarknessLimit")
1098 p_sys->p_atmo_config->setLiveView_HueWinSize(
1099 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "HueWinSize")
1101 p_sys->p_atmo_config->setLiveView_SatWinSize(
1102 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "SatWinSize")
1105 /* currently not required inside vlc */
1106 p_sys->p_atmo_config->setLiveView_WidescreenMode( 0 );
1108 p_sys->p_atmo_config->setLiveView_FrameDelay(
1109 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "FrameDelay")
1113 p_sys->p_atmo_config->setUseSoftwareWhiteAdj(
1114 var_CreateGetBoolCommand( p_filter, CFG_PREFIX "whiteadj")
1116 p_sys->p_atmo_config->setWhiteAdjustment_Red(
1117 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-red")
1119 p_sys->p_atmo_config->setWhiteAdjustment_Green(
1120 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-green")
1122 p_sys->p_atmo_config->setWhiteAdjustment_Blue(
1123 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-blue")
1126 tChannelAssignment *p_channel_assignment =
1127 p_sys->p_atmo_config->getChannelAssignment(0);
1129 p_channel_assignment->mappings[0] = var_CreateGetIntegerCommand(
1130 p_filter, CFG_PREFIX "channel_0");
1132 p_channel_assignment->mappings[1] = var_CreateGetIntegerCommand(
1133 p_filter, CFG_PREFIX "channel_1");
1135 p_channel_assignment->mappings[2] = var_CreateGetIntegerCommand(
1136 p_filter, CFG_PREFIX "channel_2");
1138 p_channel_assignment->mappings[3] = var_CreateGetIntegerCommand(
1139 p_filter, CFG_PREFIX "channel_3");
1141 p_channel_assignment->mappings[4] = var_CreateGetIntegerCommand(
1142 p_filter, CFG_PREFIX "channel_4");
1144 for(int i=0;i<ATMO_NUM_CHANNELS;i++)
1145 msg_Dbg( p_filter, "map software channel %d to hardware channel %d",
1146 p_channel_assignment->mappings[i],
1151 char psz_gradient_var_name[30];
1152 char *psz_gradient_file;
1153 for(int i=0;i<ATMO_NUM_CHANNELS;i++)
1155 sprintf(psz_gradient_var_name, CFG_PREFIX "gradient_zone_%d", i);
1156 psz_gradient_file = var_CreateGetStringCommand(
1158 psz_gradient_var_name
1160 if(psz_gradient_file && strlen(psz_gradient_file)>0)
1162 msg_Dbg( p_filter, "loading gradientfile %s for "\
1163 "zone %d", psz_gradient_file, i);
1165 int i_res = p_sys->p_atmo_config->getZoneDefinition(i)->
1166 LoadGradientFromBitmap(psz_gradient_file);
1168 if(i_res != ATMO_LOAD_GRADIENT_OK)
1170 msg_Err( p_filter,"failed to load gradient '%s' with "\
1171 "error %d",psz_gradient_file,i_res);
1174 delete psz_gradient_file;
1177 p_sys->p_atmo_dyndata = new CAtmoDynData((vlc_object_t *)p_filter,
1178 p_sys->p_atmo_config
1181 msg_Dbg( p_filter, "buildin driver initialized");
1183 free(psz_serialdev);
1185 msg_Err(p_filter,"no serial devicename set");
1189 switch( p_filter->fmt_in.video.i_chroma )
1191 case VLC_FOURCC('I','4','2','0'):
1192 case VLC_FOURCC('I','Y','U','V'):
1193 case VLC_FOURCC('Y','V','1','2'):
1194 case VLC_FOURCC('Y','V','1','6'):
1195 case VLC_FOURCC('Y','V','U','9'):
1196 // simple enough? Dionoea?
1197 p_sys->pf_extract_mini_image = ExtractMiniImage_YUV;
1200 msg_Dbg( p_filter, "InitFilter-unsupported chroma: %4.4s",
1201 (char *)&p_filter->fmt_in.video.i_chroma);
1202 p_sys->pf_extract_mini_image = NULL;
1205 p_sys->i_crop_x_offset = 0;
1206 p_sys->i_crop_y_offset = 0;
1207 p_sys->i_crop_width = p_filter->fmt_in.video.i_visible_width;
1208 p_sys->i_crop_height = p_filter->fmt_in.video.i_visible_height;
1210 msg_Dbg( p_filter, "set default crop %d,%d %dx%d",p_sys->i_crop_x_offset,
1211 p_sys->i_crop_y_offset,
1212 p_sys->i_crop_width,
1213 p_sys->i_crop_height );
1216 #if defined(__ATMO_DEBUG__)
1217 /* save debug images to a folder as Bitmap files ? */
1218 p_sys->b_saveframes = var_CreateGetBoolCommand( p_filter,
1219 CFG_PREFIX "saveframes"
1221 msg_Dbg(p_filter,"saveframes = %d", (int)p_sys->b_saveframes);
1224 read debug image folder from config
1226 psz_path = var_CreateGetStringCommand( p_filter, CFG_PREFIX "framepath" );
1227 if(psz_path != NULL)
1229 strcpy(p_sys->sz_framepath, psz_path);
1230 #if defined( WIN32 )
1231 size_t i_strlen = strlen(p_sys->sz_framepath);
1232 if((i_strlen>0) && (p_sys->sz_framepath[i_strlen-1] != '\\'))
1234 p_sys->sz_framepath[i_strlen] = '\\';
1235 p_sys->sz_framepath[i_strlen+1] = 0;
1240 msg_Dbg(p_filter,"saveframesfolder %s",p_sys->sz_framepath);
1244 size of extracted image by default 64x48 (other imagesizes are
1245 currently ignored by AtmoWin)
1247 p_sys->i_atmo_width = var_CreateGetIntegerCommand( p_filter,
1248 CFG_PREFIX "width");
1249 p_sys->i_atmo_height = var_CreateGetIntegerCommand( p_filter,
1250 CFG_PREFIX "height");
1251 msg_Dbg(p_filter,"mini image size %d * %d pixels", p_sys->i_atmo_width,
1252 p_sys->i_atmo_height);
1255 because atmowin could also be used for lighten up the room - I think if you
1256 pause the video it would be useful to get a little bit more light into to
1257 your living room? - instead switching on a lamp?
1259 p_sys->b_usepausecolor = var_CreateGetBoolCommand( p_filter,
1260 CFG_PREFIX "usepausecolor" );
1261 p_sys->ui_pausecolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1262 CFG_PREFIX "pcolor-red");
1263 p_sys->ui_pausecolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1264 CFG_PREFIX "pcolor-green");
1265 p_sys->ui_pausecolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1266 CFG_PREFIX "pcolor-blue");
1267 p_sys->i_fadesteps = var_CreateGetIntegerCommand( p_filter,
1268 CFG_PREFIX "fadesteps");
1269 if(p_sys->i_fadesteps < 1)
1270 p_sys->i_fadesteps = 1;
1271 msg_Dbg(p_filter,"use pause color %d, RGB: %d, %d, %d, Fadesteps: %d",
1272 (int)p_sys->b_usepausecolor,
1273 p_sys->ui_pausecolor_red,
1274 p_sys->ui_pausecolor_green,
1275 p_sys->ui_pausecolor_blue,
1276 p_sys->i_fadesteps);
1279 this color is use on shutdown of the filter - the define the
1280 final light after playback... may be used to dim up the light -
1281 how it happens in the cinema...
1283 p_sys->ui_endcolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1284 CFG_PREFIX "ecolor-red");
1285 p_sys->ui_endcolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1286 CFG_PREFIX "ecolor-green");
1287 p_sys->ui_endcolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1288 CFG_PREFIX "ecolor-blue");
1289 p_sys->i_endfadesteps = var_CreateGetIntegerCommand( p_filter,
1290 CFG_PREFIX "efadesteps");
1291 if(p_sys->i_endfadesteps < 1)
1292 p_sys->i_endfadesteps = 1;
1293 msg_Dbg(p_filter,"use ende color RGB: %d, %d, %d, Fadesteps: %d",
1294 p_sys->ui_endcolor_red,
1295 p_sys->ui_endcolor_green,
1296 p_sys->ui_endcolor_blue,
1297 p_sys->i_endfadesteps);
1299 /* if the external DLL was loaded successfully call AtmoInitialize -
1300 (must be done for each thread where you wan't to use AtmoLight!
1302 int i = AtmoInitialize(p_filter, false);
1303 #if defined( WIN32 )
1304 if((i != 1) && !b_use_buildin_driver)
1306 /* COM Server for AtmoLight not running ?
1307 if the exe path is configured try to start the "userspace" driver
1309 psz_path = var_CreateGetStringCommand( p_filter,
1310 CFG_PREFIX "atmowinexe" );
1311 if(psz_path != NULL)
1313 STARTUPINFO startupinfo;
1314 PROCESS_INFORMATION pinfo;
1315 memset(&startupinfo, 0, sizeof(STARTUPINFO));
1316 startupinfo.cb = sizeof(STARTUPINFO);
1317 if(CreateProcess(psz_path, NULL, NULL, NULL,
1318 FALSE, 0, NULL, NULL, &startupinfo, &pinfo) == TRUE)
1320 msg_Dbg(p_filter,"launched AtmoWin from %s",psz_path);
1321 WaitForInputIdle(pinfo.hProcess, 5000);
1323 retry to initialize the library COM ... functionality
1324 after the server was launched
1326 i = AtmoInitialize(p_filter, false);
1328 msg_Err(p_filter,"failed to launch AtmoWin from %s", psz_path);
1335 if(i == 1) /* Init Atmolight success... */
1337 msg_Dbg( p_filter, "AtmoInitialize Ok!");
1339 /* Setup Transferbuffers for 64 x 48 , RGB with 32bit Per Pixel */
1340 AtmoCreateTransferBuffers(p_filter, BI_RGB, 4,
1341 p_sys->i_atmo_width,
1342 p_sys->i_atmo_height
1345 /* say the userspace driver that a live mode should be activated
1346 the functions returns the old mode for later restore!
1348 p_sys->i_AtmoOldEffect = AtmoSwitchEffect(p_filter, emLivePicture);
1351 live view can have two differnt source the AtmoWinA
1352 internal GDI Screencapture and the external one - which we
1355 AtmoSetLiveSource(p_filter, lvsExternal);
1357 /* enable other parts only if everything is fine */
1358 p_sys->b_enabled = true;
1364 /*****************************************************************************
1365 * CreateFilter: allocates AtmoLight video thread output method
1366 *****************************************************************************
1367 * This function allocates and initializes a AtmoLight vout method.
1368 *****************************************************************************/
1369 static int CreateFilter( vlc_object_t *p_this )
1371 filter_t *p_filter = (filter_t *)p_this;
1372 filter_sys_t *p_sys;
1374 /* Allocate structure */
1375 p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) );
1376 p_filter->p_sys = p_sys;
1377 if( p_filter->p_sys == NULL )
1379 msg_Err( p_filter, "out of memory for p_sys structure" );
1382 /* set all entries to zero */
1383 memset(p_sys, 0, sizeof( filter_sys_t ));
1385 /* further Setup Function pointers for videolan for calling my filter */
1386 p_filter->pf_video_filter = Filter;
1388 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
1391 AddStateVariableCallback(p_filter);
1393 AddCropVariableCallback(p_filter);
1395 AddAtmoSettingsVariablesCallbacks(p_filter);
1397 Atmo_SetupParameters(p_filter);
1405 /*****************************************************************************
1406 * DestroyFilter: destroy AtmoLight video thread output method
1407 *****************************************************************************
1408 * Terminate an output method created by CreateFilter
1409 *****************************************************************************/
1411 static void DestroyFilter( vlc_object_t *p_this )
1413 filter_t *p_filter = (filter_t *)p_this;
1414 filter_sys_t *p_sys = p_filter->p_sys;
1416 DelStateVariableCallback(p_filter);
1417 DelCropVariableCallback(p_filter);
1418 DelAtmoSettingsVariablesCallbacks(p_filter);
1420 Atmo_Shutdown(p_filter);
1422 #if defined( WIN32 )
1423 if(p_sys->h_AtmoCtrl != NULL)
1425 FreeLibrary(p_sys->h_AtmoCtrl);
1429 delete p_sys->p_atmo_dyndata;
1430 delete p_sys->p_atmo_config;
1432 vlc_mutex_destroy( &p_sys->filter_lock );
1439 function stolen from some other videolan source filter ;-)
1440 for the moment RGB is OK... but better would be a direct transformation
1443 static inline void yuv_to_rgb( uint8_t *r, uint8_t *g, uint8_t *b,
1444 uint8_t y1, uint8_t u1, uint8_t v1 )
1446 /* macros used for YUV pixel conversions */
1447 # define SCALEBITS 10
1448 # define ONE_HALF (1 << (SCALEBITS - 1))
1449 # define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
1450 # define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
1452 int y, cb, cr, r_add, g_add, b_add;
1456 r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;
1457 g_add = - FIX(0.34414*255.0/224.0) * cb
1458 - FIX(0.71414*255.0/224.0) * cr + ONE_HALF;
1459 b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;
1460 y = (y1 - 16) * FIX(255.0/219.0);
1461 *r = CLAMP((y + r_add) >> SCALEBITS);
1462 *g = CLAMP((y + g_add) >> SCALEBITS);
1463 *b = CLAMP((y + b_add) >> SCALEBITS);
1465 /******************************************************************************
1466 * ExtractMiniImage_YUV: extract a small image from the picture as 24-bit RGB
1467 *******************************************************************************
1468 * p_sys is a pointer to
1469 * p_inpic is the source frame
1470 * p_transfer_dest is the target buffer for the picture must be big enough!
1471 * (in win32 enviroment this buffer comes from the external DLL where it is
1472 * create as "variant array" and returned through the AtmoLockTransferbuffer
1474 static void ExtractMiniImage_YUV(filter_sys_t *p_sys,
1476 uint8_t *p_transfer_dest)
1483 uint8_t *p_rgb_dst_line_red;
1484 uint8_t *p_rgb_dst_line_green;
1485 uint8_t *p_rgb_dst_line_blue;
1490 /* calcute Pointers for Storage of B G R (A) */
1491 p_rgb_dst_line_blue = p_transfer_dest;
1492 p_rgb_dst_line_green = p_transfer_dest + 1;
1493 p_rgb_dst_line_red = p_transfer_dest + 2 ;
1495 int i_row_count = p_sys->i_atmo_height + 1;
1496 int i_col_count = p_sys->i_atmo_width + 1;
1497 int i_y_row,i_u_row,i_v_row,i_pixel_row;
1501 /* these two ugly loops extract the small image - goes it faster? how?
1502 the loops are so designed that there is a small border around the extracted
1503 image so we wont get column and row - zero from the frame, and not the most
1504 right and bottom pixels --- which may be clipped on computers useing TV out
1507 TODO: try to find out if the output is clipped through VLC - and try here
1508 to ingore the clipped away area for a better result!
1510 TODO: performance improvement in InitFilter percalculated the offsets of
1511 the lines inside the planes so I can save (i_row_count * 3) 2xMUL and
1512 one time DIV the same could be done for the inner loop I think...
1514 for(i_row = 1; i_row < i_row_count; i_row++)
1516 // calcute the current Lines in the source planes for this outputrow
1517 /* Adresscalcuation pointer to plane Length of one pixelrow in bytes
1518 calculate row now number
1521 p_inpic->format? transform Pixel row into row of plane...
1522 how? simple? fast? good?
1525 /* compute the source pixel row and respect the active cropping */
1526 i_pixel_row = (i_row * p_sys->i_crop_height) / i_row_count
1527 + p_sys->i_crop_y_offset;
1530 trans for these Pixel row into the row of each plane ..
1531 because planesize can differ from image size
1533 i_y_row = (i_pixel_row * p_inpic->p[Y_PLANE].i_visible_lines) /
1534 p_inpic->format.i_visible_height;
1536 i_u_row = (i_pixel_row * p_inpic->p[U_PLANE].i_visible_lines) /
1537 p_inpic->format.i_visible_height;
1539 i_v_row = (i_pixel_row * p_inpic->p[V_PLANE].i_visible_lines) /
1540 p_inpic->format.i_visible_height;
1542 /* calculate the pointers to the pixeldata for this row
1545 p_src_y = p_inpic->p[Y_PLANE].p_pixels +
1546 p_inpic->p[Y_PLANE].i_pitch * i_y_row;
1547 p_src_u = p_inpic->p[U_PLANE].p_pixels +
1548 p_inpic->p[U_PLANE].i_pitch * i_u_row;
1549 p_src_v = p_inpic->p[V_PLANE].p_pixels +
1550 p_inpic->p[V_PLANE].i_pitch * i_v_row;
1552 for(i_col = 1; i_col < i_col_count; i_col++)
1554 i_pixel_col = (i_col * p_sys->i_crop_width) / i_col_count +
1555 p_sys->i_crop_x_offset;
1557 trans for these Pixel row into the row of each plane ..
1558 because planesize can differ from image size
1560 i_xpos_y = (i_pixel_col * p_inpic->p[Y_PLANE].i_visible_pitch) /
1561 p_inpic->format.i_visible_width;
1562 i_xpos_u = (i_pixel_col * p_inpic->p[U_PLANE].i_visible_pitch) /
1563 p_inpic->format.i_visible_width;
1564 i_xpos_v = (i_pixel_col * p_inpic->p[V_PLANE].i_visible_pitch) /
1565 p_inpic->format.i_visible_width;
1567 yuv_to_rgb(p_rgb_dst_line_red,
1568 p_rgb_dst_line_green,
1569 p_rgb_dst_line_blue,
1575 /* +4 because output image should be RGB32 with dword alignment! */
1576 p_rgb_dst_line_red += 4;
1577 p_rgb_dst_line_green += 4;
1578 p_rgb_dst_line_blue += 4;
1584 /******************************************************************************
1585 * SaveBitmap: Saves the content of a transferbuffer as Bitmap to disk
1586 *******************************************************************************
1587 * just for debugging
1588 * p_sys -> configuration if Atmo from there the function will get height and
1590 * p_pixels -> should be the dword aligned BGR(A) image data
1591 * psz_filename -> filename where to store
1593 #if defined(__ATMO_DEBUG__)
1594 void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename)
1596 /* for debug out only used*/
1597 BITMAPINFO bmp_info;
1598 BITMAPFILEHEADER bmp_fileheader;
1601 memset(&bmp_info, 0, sizeof(BITMAPINFO));
1602 bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1603 bmp_info.bmiHeader.biSizeImage = p_sys->i_atmo_height *
1604 p_sys->i_atmo_width * 4;
1605 bmp_info.bmiHeader.biCompression = BI_RGB;
1606 bmp_info.bmiHeader.biWidth = p_sys->i_atmo_width;
1607 bmp_info.bmiHeader.biHeight = -p_sys->i_atmo_height;
1608 bmp_info.bmiHeader.biBitCount = 32;
1609 bmp_info.bmiHeader.biPlanes = 1;
1611 bmp_fileheader.bfReserved1 = 0;
1612 bmp_fileheader.bfReserved2 = 0;
1613 bmp_fileheader.bfSize = sizeof(BITMAPFILEHEADER) +
1614 sizeof(BITMAPINFOHEADER) +
1615 bmp_info.bmiHeader.biSizeImage;
1616 bmp_fileheader.bfType = VLC_TWOCC('M','B');
1617 bmp_fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) +
1618 sizeof(BITMAPINFOHEADER);
1620 fp_bitmap = fopen(psz_filename,"wb");
1621 if( fp_bitmap != NULL)
1623 fwrite(&bmp_fileheader, sizeof(BITMAPFILEHEADER), 1, fp_bitmap);
1624 fwrite(&bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp_bitmap);
1625 fwrite(p_pixels, bmp_info.bmiHeader.biSizeImage, 1, fp_bitmap);
1632 /****************************************************************************
1633 * CreateMiniImage: extracts a 64x48 pixel image from the frame
1634 * (there is a small border arround thats why the loops starts with one
1635 * instead zero) without any interpolation
1636 *****************************************************************************/
1637 static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic)
1639 filter_sys_t *p_sys = p_filter->p_sys;
1641 pointer to RGB Buffer created in external libary as safe array which
1642 is locked inside AtmoLockTransferBuffer
1644 uint8_t *p_transfer = NULL;
1645 #if defined( __ATMO_DEBUG__ )
1646 /* for debug out only used*/
1647 char sz_filename[MAX_PATH];
1651 Lock the before created VarArray (AtmoCreateTransferBuffers)
1652 inside my wrapper library and give me a pointer to the buffer!
1653 below linux a global buffer may be used and protected with a mutex?
1655 p_transfer = AtmoLockTransferBuffer(p_filter);
1656 if(p_transfer == NULL)
1658 msg_Err( p_filter, "AtmoLight no transferbuffer available. "\
1659 "AtmoLight will be disabled!");
1660 p_sys->b_enabled = false;
1665 do the call via pointer to function instead of having a
1668 p_sys->pf_extract_mini_image(p_sys, p_inpic, p_transfer);
1671 #if defined( __ATMO_DEBUG__ )
1673 if debugging enabled save every 128th image to disk
1675 if((p_sys->b_saveframes == true) && (p_sys->sz_framepath[0] != 0 ))
1678 if((p_sys->i_framecounter & 127) == 0)
1680 sprintf(sz_filename,"%satmo_dbg_%06d.bmp",p_sys->sz_framepath,
1681 p_sys->i_framecounter);
1682 msg_Dbg(p_filter, "SaveFrame %s",sz_filename);
1684 SaveBitmap(p_sys, p_transfer, sz_filename);
1686 p_sys->i_framecounter++;
1690 /* show the colors on the wall */
1691 AtmoSendPixelData(p_filter);
1697 /*****************************************************************************
1698 * Filter: calls the extract method and forwards the incomming picture 1:1
1699 *****************************************************************************
1701 *****************************************************************************/
1703 static picture_t * Filter( filter_t *p_filter, picture_t *p_pic )
1705 filter_sys_t *p_sys = p_filter->p_sys;
1706 if( !p_pic ) return NULL;
1708 if((p_sys->b_enabled == true) &&
1709 (p_sys->pf_extract_mini_image != NULL) &&
1710 (p_sys->b_pause_live == false))
1712 CreateMiniImage(p_filter, p_pic);
1719 /*****************************************************************************
1720 * FadeToColorThread: Threadmethod which changes slowly the color
1721 * to a target color defined in p_fadethread struct
1722 * use for: Fade to Pause Color, and Fade to End Color
1723 *****************************************************************************/
1724 static void FadeToColorThread(fadethread_t *p_fadethread)
1726 filter_sys_t *p_sys = (filter_sys_t *)p_fadethread->p_filter->p_sys;
1727 int i_steps_done = 0;
1737 vlc_thread_ready( p_fadethread );
1739 uint8_t *p_source = NULL;
1741 /* initialize AtmoWin for this thread! */
1742 AtmoInitialize(p_fadethread->p_filter , true);
1744 uint8_t *p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
1745 if(p_transfer != NULL) {
1746 /* safe colors as "32bit" Integers to avoid overflows*/
1747 i_pause_red = p_fadethread->ui_red;
1748 i_pause_blue = p_fadethread->ui_blue;
1749 i_pause_green = p_fadethread->ui_green;
1752 allocate a temporary buffer for the last send
1753 image size less then 15kb
1755 int i_size = 4 * p_sys->i_atmo_width * p_sys->i_atmo_height;
1756 p_source = (uint8_t *)malloc( i_size );
1757 if(p_source != NULL)
1760 get a copy of the last transfered image as orign for the
1763 memcpy(p_source, p_transfer, i_size);
1764 /* send the same pixel data again... to unlock the buffer! */
1765 AtmoSendPixelData( p_fadethread->p_filter );
1767 while( (!p_fadethread->b_die) &&
1768 (i_steps_done < p_fadethread->i_steps))
1770 p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
1771 if(!p_transfer) break; /* should not happen if it worked
1772 one time in the code above! */
1775 move all pixels in the mini image (64x48) one step closer to
1776 the desired color these loop takes the most time of this
1777 thread improvements wellcome!
1780 (i_index < i_size) && (!p_fadethread->b_die);
1783 i_src_blue = p_source[i_index+0];
1784 i_src_green = p_source[i_index+1];
1785 i_src_red = p_source[i_index+2];
1786 p_transfer[i_index+0] = (uint8_t) (((
1787 (i_pause_blue - i_src_blue)
1788 * i_steps_done)/p_fadethread->i_steps)
1791 p_transfer[i_index+1] = (uint8_t) (((
1792 (i_pause_green - i_src_green)
1793 * i_steps_done)/p_fadethread->i_steps)
1796 p_transfer[i_index+2] = (uint8_t) (((
1797 (i_pause_red - i_src_red)
1798 * i_steps_done)/p_fadethread->i_steps)
1802 /* send image to lightcontroller */
1803 AtmoSendPixelData( p_fadethread->p_filter );
1804 /* is there something like and interruptable sleep inside
1805 the VLC libaries? inside native win32 I would use an Event
1806 (CreateEvent) and here an WaitForSingleObject?
1808 if(p_fadethread->b_die) break;
1810 if(p_fadethread->b_die) break;
1812 if(p_fadethread->b_die) break;
1814 if(p_fadethread->b_die) break;
1819 /* in failure of malloc also unlock buffer */
1820 AtmoSendPixelData(p_fadethread->p_filter);
1823 /* call indirect to OleUnitialize() for this thread */
1824 AtmoFinalize(p_fadethread->p_filter, 0);
1827 /*****************************************************************************
1828 * CheckAndStopFadeThread: if there is a fadethread structure left, or running.
1829 ******************************************************************************
1830 * this function will stop the thread ... and waits for its termination
1831 * before removeing the objects from vout_sys_t ...
1832 ******************************************************************************/
1833 static void CheckAndStopFadeThread(filter_t *p_filter)
1835 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1836 vlc_mutex_lock( &p_sys->filter_lock );
1837 if(p_sys->p_fadethread != NULL)
1839 msg_Dbg(p_filter, "kill still running fadeing thread...");
1841 p_sys->p_fadethread->b_die = true;
1843 vlc_thread_join(p_sys->p_fadethread);
1845 vlc_object_release(p_sys->p_fadethread);
1846 p_sys->p_fadethread = NULL;
1848 vlc_mutex_unlock( &p_sys->filter_lock );
1851 /*****************************************************************************
1852 * StateCallback: Callback for the inputs variable "State" to get notified
1853 * about Pause and Continue Playback events.
1854 *****************************************************************************/
1855 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
1856 vlc_value_t oldval, vlc_value_t newval,
1859 filter_t *p_filter = (filter_t *)p_data;
1860 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1862 if((p_sys->b_usepausecolor == true) && (p_sys->b_enabled == true))
1864 msg_Dbg(p_filter, "state change from: %d to %d", oldval.i_int,
1867 if((newval.i_int == PAUSE_S) && (oldval.i_int == PLAYING_S))
1869 /* tell the other thread to stop sending images to light
1871 p_sys->b_pause_live = true;
1873 // ggf. alten Thread abräumen should not happen....
1874 CheckAndStopFadeThread(p_filter);
1876 // perpare spawn fadeing thread
1877 vlc_mutex_lock( &p_sys->filter_lock );
1879 launch only a new thread if there is none active!
1880 or waiting for cleanup
1882 if(p_sys->p_fadethread == NULL)
1884 p_sys->p_fadethread = (fadethread_t *)vlc_object_create(
1886 sizeof(fadethread_t) );
1888 p_sys->p_fadethread->p_filter = p_filter;
1889 p_sys->p_fadethread->ui_red = p_sys->ui_pausecolor_red;
1890 p_sys->p_fadethread->ui_green = p_sys->ui_pausecolor_green;
1891 p_sys->p_fadethread->ui_blue = p_sys->ui_pausecolor_blue;
1892 p_sys->p_fadethread->i_steps = p_sys->i_fadesteps;
1894 if( vlc_thread_create( p_sys->p_fadethread,
1895 "AtmoLight fadeing",
1897 VLC_THREAD_PRIORITY_LOW,
1900 msg_Err( p_filter, "cannot create FadeToColorThread" );
1901 vlc_object_release( p_sys->p_fadethread );
1902 p_sys->p_fadethread = NULL;
1905 vlc_mutex_unlock( &p_sys->filter_lock );
1908 if((newval.i_int == PLAYING_S) && (oldval.i_int == PAUSE_S))
1910 /* playback continues check thread state */
1911 CheckAndStopFadeThread(p_filter);
1912 /* reactivate the Render function... to do its normal work */
1913 p_sys->b_pause_live = false;
1920 /*****************************************************************************
1921 * AddPlaylistInputThreadStateCallback: Setup call back on "State" Variable
1922 *****************************************************************************
1923 * Add Callback function to the "state" variable of the input thread..
1924 * first find the PlayList and get the input thread from there to attach
1925 * my callback? is vlc_object_find the right way for this??
1926 *****************************************************************************/
1927 static void AddStateVariableCallback(filter_t *p_filter)
1929 playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_filter,
1930 VLC_OBJECT_PLAYLIST,
1934 input_thread_t *p_input = p_playlist->p_input;
1937 var_AddCallback( p_input, "state", StateCallback, p_filter );
1939 vlc_object_release( p_playlist );
1943 /*****************************************************************************
1944 * DelPlaylistInputThreadStateCallback: Remove call back on "State" Variable
1945 *****************************************************************************
1946 * Delete the callback function to the "state" variable of the input thread...
1947 * first find the PlayList and get the input thread from there to attach
1948 * my callback? is vlc_object_find the right way for this??
1949 *****************************************************************************/
1950 static void DelStateVariableCallback( filter_t *p_filter )
1952 playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_filter,
1953 VLC_OBJECT_PLAYLIST,
1957 input_thread_t *p_input = p_playlist->p_input;
1960 var_DelCallback( p_input, "state", StateCallback, p_filter );
1962 vlc_object_release( p_playlist );
1967 static int CropCallback(vlc_object_t *p_this, char const *psz_cmd,
1968 vlc_value_t oldval, vlc_value_t newval,
1971 vout_thread_t *p_vout = (vout_thread_t *)p_this;
1972 filter_t *p_filter = (filter_t *)p_data;
1973 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1976 //if the handler is attache to crop variable directly!
1977 int i_visible_width, i_visible_height, i_x_offset, i_y_offset;
1978 atmo_parse_crop(newval.psz_string, p_vout->fmt_render,
1980 i_visible_width, i_visible_height,
1981 i_x_offset, i_y_offset);
1982 p_sys->i_crop_x_offset = i_x_offset;
1983 p_sys->i_crop_y_offset = i_y_offset;
1984 p_sys->i_crop_width = i_visible_width;
1985 p_sys->i_crop_height = i_visible_height;
1988 p_sys->i_crop_x_offset = p_vout->fmt_in.i_x_offset;
1989 p_sys->i_crop_y_offset = p_vout->fmt_in.i_y_offset;
1990 p_sys->i_crop_width = p_vout->fmt_in.i_visible_width;
1991 p_sys->i_crop_height = p_vout->fmt_in.i_visible_height;
1993 msg_Dbg(p_filter, "cropping picture %ix%i to %i,%i,%ix%i",
1994 p_vout->fmt_in.i_width,
1995 p_vout->fmt_in.i_height,
1996 p_sys->i_crop_x_offset,
1997 p_sys->i_crop_y_offset,
1998 p_sys->i_crop_width,
1999 p_sys->i_crop_height
2006 static void AddCropVariableCallback( filter_t *p_filter)
2008 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2013 var_AddCallback( p_vout, "crop-update", CropCallback, p_filter );
2014 vlc_object_release( p_vout );
2018 static void DelCropVariableCallback( filter_t *p_filter)
2020 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2025 var_DelCallback( p_vout, "crop-update", CropCallback, p_filter );
2026 vlc_object_release( p_vout );
2031 /****************************************************************************
2032 * StateCallback: Callback for the inputs variable "State" to get notified
2033 * about Pause and Continue Playback events.
2034 *****************************************************************************/
2035 static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
2036 vlc_value_t oldval, vlc_value_t newval,
2039 filter_t *p_filter = (filter_t *)p_data;
2040 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
2042 CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
2046 msg_Dbg(p_filter, "apply AtmoSettingsCallback %s (int: %d -> %d)",
2052 if( !strcmp( psz_var, CFG_PREFIX "filtermode" ))
2053 p_atmo_config->setLiveViewFilterMode( (AtmoFilterMode)newval.i_int);
2055 else if( !strcmp( psz_var, CFG_PREFIX "PercentNew" ))
2056 p_atmo_config->setLiveViewFilter_PercentNew( newval.i_int );
2058 else if( !strcmp( psz_var, CFG_PREFIX "MeanLength" ))
2059 p_atmo_config->setLiveViewFilter_MeanLength( newval.i_int );
2061 else if( !strcmp( psz_var, CFG_PREFIX "MeanThreshold" ))
2062 p_atmo_config->setLiveViewFilter_MeanThreshold( newval.i_int );
2064 else if( !strcmp( psz_var, CFG_PREFIX "EdgeWeightning" ))
2065 p_atmo_config->setLiveView_EdgeWeighting( newval.i_int );
2067 else if( !strcmp( psz_var, CFG_PREFIX "Brightness" ))
2068 p_atmo_config->setLiveView_BrightCorrect( newval.i_int );
2070 else if( !strcmp( psz_var, CFG_PREFIX "DarknessLimit" ))
2071 p_atmo_config->setLiveView_DarknessLimit( newval.i_int );
2073 else if( !strcmp( psz_var, CFG_PREFIX "HueWinSize" ))
2074 p_atmo_config->setLiveView_HueWinSize( newval.i_int );
2076 else if( !strcmp( psz_var, CFG_PREFIX "SatWinSize" ))
2077 p_atmo_config->setLiveView_SatWinSize( newval.i_int );
2079 else if( !strcmp( psz_var, CFG_PREFIX "FrameDelay" ))
2080 p_atmo_config->setLiveView_FrameDelay( newval.i_int );
2082 else if( !strcmp( psz_var, CFG_PREFIX "whiteadj" ))
2083 p_atmo_config->setUseSoftwareWhiteAdj( newval.b_bool );
2085 else if( !strcmp( psz_var, CFG_PREFIX "white-red" ))
2086 p_atmo_config->setWhiteAdjustment_Red( newval.i_int );
2088 else if( !strcmp( psz_var, CFG_PREFIX "white-green" ))
2089 p_atmo_config->setWhiteAdjustment_Green( newval.i_int );
2091 else if( !strcmp( psz_var, CFG_PREFIX "white-blue" ))
2092 p_atmo_config->setWhiteAdjustment_Blue( newval.i_int );
2098 static void AddAtmoSettingsVariablesCallbacks(filter_t *p_filter)
2100 var_AddCallback( p_filter, CFG_PREFIX "filtermode",
2101 AtmoSettingsCallback, p_filter );
2102 var_AddCallback( p_filter, CFG_PREFIX "PercentNew",
2103 AtmoSettingsCallback, p_filter );
2106 var_AddCallback( p_filter, CFG_PREFIX "MeanLength",
2107 AtmoSettingsCallback, p_filter );
2108 var_AddCallback( p_filter, CFG_PREFIX "MeanThreshold",
2109 AtmoSettingsCallback, p_filter );
2111 var_AddCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2112 AtmoSettingsCallback, p_filter );
2113 var_AddCallback( p_filter, CFG_PREFIX "Brightness",
2114 AtmoSettingsCallback, p_filter );
2115 var_AddCallback( p_filter, CFG_PREFIX "DarknessLimit",
2116 AtmoSettingsCallback, p_filter );
2118 var_AddCallback( p_filter, CFG_PREFIX "HueWinSize",
2119 AtmoSettingsCallback, p_filter );
2120 var_AddCallback( p_filter, CFG_PREFIX "SatWinSize",
2121 AtmoSettingsCallback, p_filter );
2122 var_AddCallback( p_filter, CFG_PREFIX "FrameDelay",
2123 AtmoSettingsCallback, p_filter );
2126 var_AddCallback( p_filter, CFG_PREFIX "whiteadj",
2127 AtmoSettingsCallback, p_filter );
2128 var_AddCallback( p_filter, CFG_PREFIX "white-red",
2129 AtmoSettingsCallback, p_filter );
2130 var_AddCallback( p_filter, CFG_PREFIX "white-green",
2131 AtmoSettingsCallback, p_filter );
2132 var_AddCallback( p_filter, CFG_PREFIX "white-blue",
2133 AtmoSettingsCallback, p_filter );
2136 static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
2139 var_DelCallback( p_filter, CFG_PREFIX "filtermode",
2140 AtmoSettingsCallback, p_filter );
2142 var_DelCallback( p_filter, CFG_PREFIX "PercentNew",
2143 AtmoSettingsCallback, p_filter );
2144 var_DelCallback( p_filter, CFG_PREFIX "MeanLength",
2145 AtmoSettingsCallback, p_filter );
2146 var_DelCallback( p_filter, CFG_PREFIX "MeanThreshold",
2147 AtmoSettingsCallback, p_filter );
2149 var_DelCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2150 AtmoSettingsCallback, p_filter );
2151 var_DelCallback( p_filter, CFG_PREFIX "Brightness",
2152 AtmoSettingsCallback, p_filter );
2153 var_DelCallback( p_filter, CFG_PREFIX "DarknessLimit",
2154 AtmoSettingsCallback, p_filter );
2156 var_DelCallback( p_filter, CFG_PREFIX "HueWinSize",
2157 AtmoSettingsCallback, p_filter );
2158 var_DelCallback( p_filter, CFG_PREFIX "SatWinSize",
2159 AtmoSettingsCallback, p_filter );
2160 var_DelCallback( p_filter, CFG_PREFIX "FrameDelay",
2161 AtmoSettingsCallback, p_filter );
2164 var_DelCallback( p_filter, CFG_PREFIX "whiteadj",
2165 AtmoSettingsCallback, p_filter );
2166 var_DelCallback( p_filter, CFG_PREFIX "white-red",
2167 AtmoSettingsCallback, p_filter );
2168 var_DelCallback( p_filter, CFG_PREFIX "white-green",
2169 AtmoSettingsCallback, p_filter );
2170 var_DelCallback( p_filter, CFG_PREFIX "white-blue",
2171 AtmoSettingsCallback, p_filter );
2176 #if defined(__ATMO_DEBUG__)
2177 static void atmo_parse_crop(char *psz_cropconfig,
2178 video_format_t fmt_in,
2179 video_format_t fmt_render,
2180 int &i_visible_width, int &i_visible_height,
2181 int &i_x_offset, int &i_y_offset )
2183 int64_t i_aspect_num, i_aspect_den;
2184 unsigned int i_width, i_height;
2186 i_visible_width = fmt_in.i_visible_width;
2187 i_visible_height = fmt_in.i_visible_height;
2188 i_x_offset = fmt_in.i_x_offset;
2189 i_y_offset = fmt_in.i_y_offset;
2191 char *psz_end = NULL, *psz_parser = strchr( psz_cropconfig, ':' );
2194 /* We're using the 3:4 syntax */
2195 i_aspect_num = strtol( psz_cropconfig, &psz_end, 10 );
2196 if( psz_end == psz_cropconfig || !i_aspect_num ) return;
2198 i_aspect_den = strtol( ++psz_parser, &psz_end, 10 );
2199 if( psz_end == psz_parser || !i_aspect_den ) return;
2201 i_width = fmt_in.i_sar_den * fmt_render.i_visible_height *
2202 i_aspect_num / i_aspect_den / fmt_in.i_sar_num;
2204 i_height = fmt_render.i_visible_width*fmt_in.i_sar_num *
2205 i_aspect_den / i_aspect_num / fmt_in.i_sar_den;
2207 if( i_width < fmt_render.i_visible_width )
2209 i_x_offset = fmt_render.i_x_offset +
2210 (fmt_render.i_visible_width - i_width) / 2;
2211 i_visible_width = i_width;
2215 i_y_offset = fmt_render.i_y_offset +
2216 (fmt_render.i_visible_height - i_height) / 2;
2217 i_visible_height = i_height;
2222 psz_parser = strchr( psz_cropconfig, 'x' );
2225 /* Maybe we're using the <width>x<height>+<left>+<top> syntax */
2226 unsigned int i_crop_width, i_crop_height, i_crop_top, i_crop_left;
2228 i_crop_width = strtol( psz_cropconfig, &psz_end, 10 );
2229 if( psz_end != psz_parser ) return;
2231 psz_parser = strchr( ++psz_end, '+' );
2232 i_crop_height = strtol( psz_end, &psz_end, 10 );
2233 if( psz_end != psz_parser ) return;
2235 psz_parser = strchr( ++psz_end, '+' );
2236 i_crop_left = strtol( psz_end, &psz_end, 10 );
2237 if( psz_end != psz_parser ) return;
2240 i_crop_top = strtol( psz_end, &psz_end, 10 );
2241 if( *psz_end != '\0' ) return;
2243 i_width = i_crop_width;
2244 i_visible_width = i_width;
2246 i_height = i_crop_height;
2247 i_visible_height = i_height;
2249 i_x_offset = i_crop_left;
2250 i_y_offset = i_crop_top;
2254 /* Maybe we're using the <left>+<top>+<right>+<bottom> syntax */
2255 unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right;
2257 psz_parser = strchr( psz_cropconfig, '+' );
2258 i_crop_left = strtol( psz_cropconfig, &psz_end, 10 );
2259 if( psz_end != psz_parser ) return;
2261 psz_parser = strchr( ++psz_end, '+' );
2262 i_crop_top = strtol( psz_end, &psz_end, 10 );
2263 if( psz_end != psz_parser ) return;
2265 psz_parser = strchr( ++psz_end, '+' );
2266 i_crop_right = strtol( psz_end, &psz_end, 10 );
2267 if( psz_end != psz_parser ) return;
2270 i_crop_bottom = strtol( psz_end, &psz_end, 10 );
2271 if( *psz_end != '\0' ) return;
2273 i_width = fmt_render.i_visible_width - i_crop_left - i_crop_right;
2274 i_visible_width = i_width;
2276 i_height = fmt_render.i_visible_height - i_crop_top - i_crop_bottom;
2277 i_visible_height = i_height;
2279 i_x_offset = i_crop_left;
2280 i_y_offset = i_crop_top;