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 /* set all entries to zero */
1380 memset(p_sys, 0, sizeof( filter_sys_t ));
1382 /* further Setup Function pointers for videolan for calling my filter */
1383 p_filter->pf_video_filter = Filter;
1385 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
1388 AddStateVariableCallback(p_filter);
1390 AddCropVariableCallback(p_filter);
1392 AddAtmoSettingsVariablesCallbacks(p_filter);
1394 Atmo_SetupParameters(p_filter);
1402 /*****************************************************************************
1403 * DestroyFilter: destroy AtmoLight video thread output method
1404 *****************************************************************************
1405 * Terminate an output method created by CreateFilter
1406 *****************************************************************************/
1408 static void DestroyFilter( vlc_object_t *p_this )
1410 filter_t *p_filter = (filter_t *)p_this;
1411 filter_sys_t *p_sys = p_filter->p_sys;
1413 DelStateVariableCallback(p_filter);
1414 DelCropVariableCallback(p_filter);
1415 DelAtmoSettingsVariablesCallbacks(p_filter);
1417 Atmo_Shutdown(p_filter);
1419 #if defined( WIN32 )
1420 if(p_sys->h_AtmoCtrl != NULL)
1422 FreeLibrary(p_sys->h_AtmoCtrl);
1426 delete p_sys->p_atmo_dyndata;
1427 delete p_sys->p_atmo_config;
1429 vlc_mutex_destroy( &p_sys->filter_lock );
1436 function stolen from some other videolan source filter ;-)
1437 for the moment RGB is OK... but better would be a direct transformation
1440 static inline void yuv_to_rgb( uint8_t *r, uint8_t *g, uint8_t *b,
1441 uint8_t y1, uint8_t u1, uint8_t v1 )
1443 /* macros used for YUV pixel conversions */
1444 # define SCALEBITS 10
1445 # define ONE_HALF (1 << (SCALEBITS - 1))
1446 # define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
1447 # define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
1449 int y, cb, cr, r_add, g_add, b_add;
1453 r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;
1454 g_add = - FIX(0.34414*255.0/224.0) * cb
1455 - FIX(0.71414*255.0/224.0) * cr + ONE_HALF;
1456 b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;
1457 y = (y1 - 16) * FIX(255.0/219.0);
1458 *r = CLAMP((y + r_add) >> SCALEBITS);
1459 *g = CLAMP((y + g_add) >> SCALEBITS);
1460 *b = CLAMP((y + b_add) >> SCALEBITS);
1462 /******************************************************************************
1463 * ExtractMiniImage_YUV: extract a small image from the picture as 24-bit RGB
1464 *******************************************************************************
1465 * p_sys is a pointer to
1466 * p_inpic is the source frame
1467 * p_transfer_dest is the target buffer for the picture must be big enough!
1468 * (in win32 enviroment this buffer comes from the external DLL where it is
1469 * create as "variant array" and returned through the AtmoLockTransferbuffer
1471 static void ExtractMiniImage_YUV(filter_sys_t *p_sys,
1473 uint8_t *p_transfer_dest)
1480 uint8_t *p_rgb_dst_line_red;
1481 uint8_t *p_rgb_dst_line_green;
1482 uint8_t *p_rgb_dst_line_blue;
1487 /* calcute Pointers for Storage of B G R (A) */
1488 p_rgb_dst_line_blue = p_transfer_dest;
1489 p_rgb_dst_line_green = p_transfer_dest + 1;
1490 p_rgb_dst_line_red = p_transfer_dest + 2 ;
1492 int i_row_count = p_sys->i_atmo_height + 1;
1493 int i_col_count = p_sys->i_atmo_width + 1;
1494 int i_y_row,i_u_row,i_v_row,i_pixel_row;
1498 /* these two ugly loops extract the small image - goes it faster? how?
1499 the loops are so designed that there is a small border around the extracted
1500 image so we wont get column and row - zero from the frame, and not the most
1501 right and bottom pixels --- which may be clipped on computers useing TV out
1504 TODO: try to find out if the output is clipped through VLC - and try here
1505 to ingore the clipped away area for a better result!
1507 TODO: performance improvement in InitFilter percalculated the offsets of
1508 the lines inside the planes so I can save (i_row_count * 3) 2xMUL and
1509 one time DIV the same could be done for the inner loop I think...
1511 for(i_row = 1; i_row < i_row_count; i_row++)
1513 // calcute the current Lines in the source planes for this outputrow
1514 /* Adresscalcuation pointer to plane Length of one pixelrow in bytes
1515 calculate row now number
1518 p_inpic->format? transform Pixel row into row of plane...
1519 how? simple? fast? good?
1522 /* compute the source pixel row and respect the active cropping */
1523 i_pixel_row = (i_row * p_sys->i_crop_height) / i_row_count
1524 + p_sys->i_crop_y_offset;
1527 trans for these Pixel row into the row of each plane ..
1528 because planesize can differ from image size
1530 i_y_row = (i_pixel_row * p_inpic->p[Y_PLANE].i_visible_lines) /
1531 p_inpic->format.i_visible_height;
1533 i_u_row = (i_pixel_row * p_inpic->p[U_PLANE].i_visible_lines) /
1534 p_inpic->format.i_visible_height;
1536 i_v_row = (i_pixel_row * p_inpic->p[V_PLANE].i_visible_lines) /
1537 p_inpic->format.i_visible_height;
1539 /* calculate the pointers to the pixeldata for this row
1542 p_src_y = p_inpic->p[Y_PLANE].p_pixels +
1543 p_inpic->p[Y_PLANE].i_pitch * i_y_row;
1544 p_src_u = p_inpic->p[U_PLANE].p_pixels +
1545 p_inpic->p[U_PLANE].i_pitch * i_u_row;
1546 p_src_v = p_inpic->p[V_PLANE].p_pixels +
1547 p_inpic->p[V_PLANE].i_pitch * i_v_row;
1549 for(i_col = 1; i_col < i_col_count; i_col++)
1551 i_pixel_col = (i_col * p_sys->i_crop_width) / i_col_count +
1552 p_sys->i_crop_x_offset;
1554 trans for these Pixel row into the row of each plane ..
1555 because planesize can differ from image size
1557 i_xpos_y = (i_pixel_col * p_inpic->p[Y_PLANE].i_visible_pitch) /
1558 p_inpic->format.i_visible_width;
1559 i_xpos_u = (i_pixel_col * p_inpic->p[U_PLANE].i_visible_pitch) /
1560 p_inpic->format.i_visible_width;
1561 i_xpos_v = (i_pixel_col * p_inpic->p[V_PLANE].i_visible_pitch) /
1562 p_inpic->format.i_visible_width;
1564 yuv_to_rgb(p_rgb_dst_line_red,
1565 p_rgb_dst_line_green,
1566 p_rgb_dst_line_blue,
1572 /* +4 because output image should be RGB32 with dword alignment! */
1573 p_rgb_dst_line_red += 4;
1574 p_rgb_dst_line_green += 4;
1575 p_rgb_dst_line_blue += 4;
1581 /******************************************************************************
1582 * SaveBitmap: Saves the content of a transferbuffer as Bitmap to disk
1583 *******************************************************************************
1584 * just for debugging
1585 * p_sys -> configuration if Atmo from there the function will get height and
1587 * p_pixels -> should be the dword aligned BGR(A) image data
1588 * psz_filename -> filename where to store
1590 #if defined(__ATMO_DEBUG__)
1591 void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename)
1593 /* for debug out only used*/
1594 BITMAPINFO bmp_info;
1595 BITMAPFILEHEADER bmp_fileheader;
1598 memset(&bmp_info, 0, sizeof(BITMAPINFO));
1599 bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1600 bmp_info.bmiHeader.biSizeImage = p_sys->i_atmo_height *
1601 p_sys->i_atmo_width * 4;
1602 bmp_info.bmiHeader.biCompression = BI_RGB;
1603 bmp_info.bmiHeader.biWidth = p_sys->i_atmo_width;
1604 bmp_info.bmiHeader.biHeight = -p_sys->i_atmo_height;
1605 bmp_info.bmiHeader.biBitCount = 32;
1606 bmp_info.bmiHeader.biPlanes = 1;
1608 bmp_fileheader.bfReserved1 = 0;
1609 bmp_fileheader.bfReserved2 = 0;
1610 bmp_fileheader.bfSize = sizeof(BITMAPFILEHEADER) +
1611 sizeof(BITMAPINFOHEADER) +
1612 bmp_info.bmiHeader.biSizeImage;
1613 bmp_fileheader.bfType = VLC_TWOCC('M','B');
1614 bmp_fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) +
1615 sizeof(BITMAPINFOHEADER);
1617 fp_bitmap = fopen(psz_filename,"wb");
1618 if( fp_bitmap != NULL)
1620 fwrite(&bmp_fileheader, sizeof(BITMAPFILEHEADER), 1, fp_bitmap);
1621 fwrite(&bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp_bitmap);
1622 fwrite(p_pixels, bmp_info.bmiHeader.biSizeImage, 1, fp_bitmap);
1629 /****************************************************************************
1630 * CreateMiniImage: extracts a 64x48 pixel image from the frame
1631 * (there is a small border arround thats why the loops starts with one
1632 * instead zero) without any interpolation
1633 *****************************************************************************/
1634 static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic)
1636 filter_sys_t *p_sys = p_filter->p_sys;
1638 pointer to RGB Buffer created in external libary as safe array which
1639 is locked inside AtmoLockTransferBuffer
1641 uint8_t *p_transfer = NULL;
1642 #if defined( __ATMO_DEBUG__ )
1643 /* for debug out only used*/
1644 char sz_filename[MAX_PATH];
1648 Lock the before created VarArray (AtmoCreateTransferBuffers)
1649 inside my wrapper library and give me a pointer to the buffer!
1650 below linux a global buffer may be used and protected with a mutex?
1652 p_transfer = AtmoLockTransferBuffer(p_filter);
1653 if(p_transfer == NULL)
1655 msg_Err( p_filter, "AtmoLight no transferbuffer available. "\
1656 "AtmoLight will be disabled!");
1657 p_sys->b_enabled = false;
1662 do the call via pointer to function instead of having a
1665 p_sys->pf_extract_mini_image(p_sys, p_inpic, p_transfer);
1668 #if defined( __ATMO_DEBUG__ )
1670 if debugging enabled save every 128th image to disk
1672 if((p_sys->b_saveframes == true) && (p_sys->sz_framepath[0] != 0 ))
1675 if((p_sys->i_framecounter & 127) == 0)
1677 sprintf(sz_filename,"%satmo_dbg_%06d.bmp",p_sys->sz_framepath,
1678 p_sys->i_framecounter);
1679 msg_Dbg(p_filter, "SaveFrame %s",sz_filename);
1681 SaveBitmap(p_sys, p_transfer, sz_filename);
1683 p_sys->i_framecounter++;
1687 /* show the colors on the wall */
1688 AtmoSendPixelData(p_filter);
1694 /*****************************************************************************
1695 * Filter: calls the extract method and forwards the incomming picture 1:1
1696 *****************************************************************************
1698 *****************************************************************************/
1700 static picture_t * Filter( filter_t *p_filter, picture_t *p_pic )
1702 filter_sys_t *p_sys = p_filter->p_sys;
1703 if( !p_pic ) return NULL;
1705 if((p_sys->b_enabled == true) &&
1706 (p_sys->pf_extract_mini_image != NULL) &&
1707 (p_sys->b_pause_live == false))
1709 CreateMiniImage(p_filter, p_pic);
1716 /*****************************************************************************
1717 * FadeToColorThread: Threadmethod which changes slowly the color
1718 * to a target color defined in p_fadethread struct
1719 * use for: Fade to Pause Color, and Fade to End Color
1720 *****************************************************************************/
1721 static void FadeToColorThread(fadethread_t *p_fadethread)
1723 filter_sys_t *p_sys = (filter_sys_t *)p_fadethread->p_filter->p_sys;
1724 int i_steps_done = 0;
1734 vlc_thread_ready( p_fadethread );
1736 uint8_t *p_source = NULL;
1738 /* initialize AtmoWin for this thread! */
1739 AtmoInitialize(p_fadethread->p_filter , true);
1741 uint8_t *p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
1742 if(p_transfer != NULL) {
1743 /* safe colors as "32bit" Integers to avoid overflows*/
1744 i_pause_red = p_fadethread->ui_red;
1745 i_pause_blue = p_fadethread->ui_blue;
1746 i_pause_green = p_fadethread->ui_green;
1749 allocate a temporary buffer for the last send
1750 image size less then 15kb
1752 int i_size = 4 * p_sys->i_atmo_width * p_sys->i_atmo_height;
1753 p_source = (uint8_t *)malloc( i_size );
1754 if(p_source != NULL)
1757 get a copy of the last transfered image as orign for the
1760 memcpy(p_source, p_transfer, i_size);
1761 /* send the same pixel data again... to unlock the buffer! */
1762 AtmoSendPixelData( p_fadethread->p_filter );
1764 while( (vlc_object_alive (p_fadethread)) &&
1765 (i_steps_done < p_fadethread->i_steps))
1767 p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
1768 if(!p_transfer) break; /* should not happen if it worked
1769 one time in the code above! */
1772 move all pixels in the mini image (64x48) one step closer to
1773 the desired color these loop takes the most time of this
1774 thread improvements wellcome!
1777 (i_index < i_size) && (vlc_object_alive (p_fadethread));
1780 i_src_blue = p_source[i_index+0];
1781 i_src_green = p_source[i_index+1];
1782 i_src_red = p_source[i_index+2];
1783 p_transfer[i_index+0] = (uint8_t) (((
1784 (i_pause_blue - i_src_blue)
1785 * i_steps_done)/p_fadethread->i_steps)
1788 p_transfer[i_index+1] = (uint8_t) (((
1789 (i_pause_green - i_src_green)
1790 * i_steps_done)/p_fadethread->i_steps)
1793 p_transfer[i_index+2] = (uint8_t) (((
1794 (i_pause_red - i_src_red)
1795 * i_steps_done)/p_fadethread->i_steps)
1799 /* send image to lightcontroller */
1800 AtmoSendPixelData( p_fadethread->p_filter );
1801 /* is there something like and interruptable sleep inside
1802 the VLC libaries? inside native win32 I would use an Event
1803 (CreateEvent) and here an WaitForSingleObject?
1805 if(!vlc_object_alive (p_fadethread)) break;
1807 if(!vlc_object_alive (p_fadethread)) break;
1809 if(!vlc_object_alive (p_fadethread)) break;
1811 if(!vlc_object_alive (p_fadethread)) break;
1816 /* in failure of malloc also unlock buffer */
1817 AtmoSendPixelData(p_fadethread->p_filter);
1820 /* call indirect to OleUnitialize() for this thread */
1821 AtmoFinalize(p_fadethread->p_filter, 0);
1824 /*****************************************************************************
1825 * CheckAndStopFadeThread: if there is a fadethread structure left, or running.
1826 ******************************************************************************
1827 * this function will stop the thread ... and waits for its termination
1828 * before removeing the objects from vout_sys_t ...
1829 ******************************************************************************/
1830 static void CheckAndStopFadeThread(filter_t *p_filter)
1832 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1833 vlc_mutex_lock( &p_sys->filter_lock );
1834 if(p_sys->p_fadethread != NULL)
1836 msg_Dbg(p_filter, "kill still running fadeing thread...");
1838 p_sys->p_fadethread->b_die = true;
1840 vlc_thread_join(p_sys->p_fadethread);
1842 vlc_object_release(p_sys->p_fadethread);
1843 p_sys->p_fadethread = NULL;
1845 vlc_mutex_unlock( &p_sys->filter_lock );
1848 /*****************************************************************************
1849 * StateCallback: Callback for the inputs variable "State" to get notified
1850 * about Pause and Continue Playback events.
1851 *****************************************************************************/
1852 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
1853 vlc_value_t oldval, vlc_value_t newval,
1856 filter_t *p_filter = (filter_t *)p_data;
1857 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1859 if((p_sys->b_usepausecolor == true) && (p_sys->b_enabled == true))
1861 msg_Dbg(p_filter, "state change from: %d to %d", oldval.i_int,
1864 if((newval.i_int == PAUSE_S) && (oldval.i_int == PLAYING_S))
1866 /* tell the other thread to stop sending images to light
1868 p_sys->b_pause_live = true;
1870 // ggf. alten Thread abräumen should not happen....
1871 CheckAndStopFadeThread(p_filter);
1873 // perpare spawn fadeing thread
1874 vlc_mutex_lock( &p_sys->filter_lock );
1876 launch only a new thread if there is none active!
1877 or waiting for cleanup
1879 if(p_sys->p_fadethread == NULL)
1881 p_sys->p_fadethread = (fadethread_t *)vlc_object_create(
1883 sizeof(fadethread_t) );
1885 p_sys->p_fadethread->p_filter = p_filter;
1886 p_sys->p_fadethread->ui_red = p_sys->ui_pausecolor_red;
1887 p_sys->p_fadethread->ui_green = p_sys->ui_pausecolor_green;
1888 p_sys->p_fadethread->ui_blue = p_sys->ui_pausecolor_blue;
1889 p_sys->p_fadethread->i_steps = p_sys->i_fadesteps;
1891 if( vlc_thread_create( p_sys->p_fadethread,
1892 "AtmoLight fadeing",
1894 VLC_THREAD_PRIORITY_LOW,
1897 msg_Err( p_filter, "cannot create FadeToColorThread" );
1898 vlc_object_release( p_sys->p_fadethread );
1899 p_sys->p_fadethread = NULL;
1902 vlc_mutex_unlock( &p_sys->filter_lock );
1905 if((newval.i_int == PLAYING_S) && (oldval.i_int == PAUSE_S))
1907 /* playback continues check thread state */
1908 CheckAndStopFadeThread(p_filter);
1909 /* reactivate the Render function... to do its normal work */
1910 p_sys->b_pause_live = false;
1917 /*****************************************************************************
1918 * AddPlaylistInputThreadStateCallback: Setup call back on "State" Variable
1919 *****************************************************************************
1920 * Add Callback function to the "state" variable of the input thread..
1921 * first find the PlayList and get the input thread from there to attach
1922 * my callback? is vlc_object_find the right way for this??
1923 *****************************************************************************/
1924 static void AddStateVariableCallback(filter_t *p_filter)
1926 playlist_t *p_playlist = pl_Yield( p_filter );
1927 input_thread_t *p_input = p_playlist->p_input;
1930 var_AddCallback( p_input, "state", StateCallback, p_filter );
1932 vlc_object_release( p_playlist );
1935 /*****************************************************************************
1936 * DelPlaylistInputThreadStateCallback: Remove call back on "State" Variable
1937 *****************************************************************************
1938 * Delete the callback function to the "state" variable of the input thread...
1939 * first find the PlayList and get the input thread from there to attach
1940 * my callback? is vlc_object_find the right way for this??
1941 *****************************************************************************/
1942 static void DelStateVariableCallback( filter_t *p_filter )
1944 playlist_t *p_playlist = pl_Yield( p_filter );
1945 input_thread_t *p_input = p_playlist->p_input;
1948 var_DelCallback( p_input, "state", StateCallback, p_filter );
1950 vlc_object_release( p_playlist );
1954 static int CropCallback(vlc_object_t *p_this, char const *psz_cmd,
1955 vlc_value_t oldval, vlc_value_t newval,
1958 vout_thread_t *p_vout = (vout_thread_t *)p_this;
1959 filter_t *p_filter = (filter_t *)p_data;
1960 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1963 //if the handler is attache to crop variable directly!
1964 int i_visible_width, i_visible_height, i_x_offset, i_y_offset;
1965 atmo_parse_crop(newval.psz_string, p_vout->fmt_render,
1967 i_visible_width, i_visible_height,
1968 i_x_offset, i_y_offset);
1969 p_sys->i_crop_x_offset = i_x_offset;
1970 p_sys->i_crop_y_offset = i_y_offset;
1971 p_sys->i_crop_width = i_visible_width;
1972 p_sys->i_crop_height = i_visible_height;
1975 p_sys->i_crop_x_offset = p_vout->fmt_in.i_x_offset;
1976 p_sys->i_crop_y_offset = p_vout->fmt_in.i_y_offset;
1977 p_sys->i_crop_width = p_vout->fmt_in.i_visible_width;
1978 p_sys->i_crop_height = p_vout->fmt_in.i_visible_height;
1980 msg_Dbg(p_filter, "cropping picture %ix%i to %i,%i,%ix%i",
1981 p_vout->fmt_in.i_width,
1982 p_vout->fmt_in.i_height,
1983 p_sys->i_crop_x_offset,
1984 p_sys->i_crop_y_offset,
1985 p_sys->i_crop_width,
1986 p_sys->i_crop_height
1993 static void AddCropVariableCallback( filter_t *p_filter)
1995 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2000 var_AddCallback( p_vout, "crop-update", CropCallback, p_filter );
2001 vlc_object_release( p_vout );
2005 static void DelCropVariableCallback( filter_t *p_filter)
2007 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2012 var_DelCallback( p_vout, "crop-update", CropCallback, p_filter );
2013 vlc_object_release( p_vout );
2018 /****************************************************************************
2019 * StateCallback: Callback for the inputs variable "State" to get notified
2020 * about Pause and Continue Playback events.
2021 *****************************************************************************/
2022 static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
2023 vlc_value_t oldval, vlc_value_t newval,
2026 filter_t *p_filter = (filter_t *)p_data;
2027 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
2029 CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
2033 msg_Dbg(p_filter, "apply AtmoSettingsCallback %s (int: %d -> %d)",
2039 if( !strcmp( psz_var, CFG_PREFIX "filtermode" ))
2040 p_atmo_config->setLiveViewFilterMode( (AtmoFilterMode)newval.i_int);
2042 else if( !strcmp( psz_var, CFG_PREFIX "PercentNew" ))
2043 p_atmo_config->setLiveViewFilter_PercentNew( newval.i_int );
2045 else if( !strcmp( psz_var, CFG_PREFIX "MeanLength" ))
2046 p_atmo_config->setLiveViewFilter_MeanLength( newval.i_int );
2048 else if( !strcmp( psz_var, CFG_PREFIX "MeanThreshold" ))
2049 p_atmo_config->setLiveViewFilter_MeanThreshold( newval.i_int );
2051 else if( !strcmp( psz_var, CFG_PREFIX "EdgeWeightning" ))
2052 p_atmo_config->setLiveView_EdgeWeighting( newval.i_int );
2054 else if( !strcmp( psz_var, CFG_PREFIX "Brightness" ))
2055 p_atmo_config->setLiveView_BrightCorrect( newval.i_int );
2057 else if( !strcmp( psz_var, CFG_PREFIX "DarknessLimit" ))
2058 p_atmo_config->setLiveView_DarknessLimit( newval.i_int );
2060 else if( !strcmp( psz_var, CFG_PREFIX "HueWinSize" ))
2061 p_atmo_config->setLiveView_HueWinSize( newval.i_int );
2063 else if( !strcmp( psz_var, CFG_PREFIX "SatWinSize" ))
2064 p_atmo_config->setLiveView_SatWinSize( newval.i_int );
2066 else if( !strcmp( psz_var, CFG_PREFIX "FrameDelay" ))
2067 p_atmo_config->setLiveView_FrameDelay( newval.i_int );
2069 else if( !strcmp( psz_var, CFG_PREFIX "whiteadj" ))
2070 p_atmo_config->setUseSoftwareWhiteAdj( newval.b_bool );
2072 else if( !strcmp( psz_var, CFG_PREFIX "white-red" ))
2073 p_atmo_config->setWhiteAdjustment_Red( newval.i_int );
2075 else if( !strcmp( psz_var, CFG_PREFIX "white-green" ))
2076 p_atmo_config->setWhiteAdjustment_Green( newval.i_int );
2078 else if( !strcmp( psz_var, CFG_PREFIX "white-blue" ))
2079 p_atmo_config->setWhiteAdjustment_Blue( newval.i_int );
2085 static void AddAtmoSettingsVariablesCallbacks(filter_t *p_filter)
2087 var_AddCallback( p_filter, CFG_PREFIX "filtermode",
2088 AtmoSettingsCallback, p_filter );
2089 var_AddCallback( p_filter, CFG_PREFIX "PercentNew",
2090 AtmoSettingsCallback, p_filter );
2093 var_AddCallback( p_filter, CFG_PREFIX "MeanLength",
2094 AtmoSettingsCallback, p_filter );
2095 var_AddCallback( p_filter, CFG_PREFIX "MeanThreshold",
2096 AtmoSettingsCallback, p_filter );
2098 var_AddCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2099 AtmoSettingsCallback, p_filter );
2100 var_AddCallback( p_filter, CFG_PREFIX "Brightness",
2101 AtmoSettingsCallback, p_filter );
2102 var_AddCallback( p_filter, CFG_PREFIX "DarknessLimit",
2103 AtmoSettingsCallback, p_filter );
2105 var_AddCallback( p_filter, CFG_PREFIX "HueWinSize",
2106 AtmoSettingsCallback, p_filter );
2107 var_AddCallback( p_filter, CFG_PREFIX "SatWinSize",
2108 AtmoSettingsCallback, p_filter );
2109 var_AddCallback( p_filter, CFG_PREFIX "FrameDelay",
2110 AtmoSettingsCallback, p_filter );
2113 var_AddCallback( p_filter, CFG_PREFIX "whiteadj",
2114 AtmoSettingsCallback, p_filter );
2115 var_AddCallback( p_filter, CFG_PREFIX "white-red",
2116 AtmoSettingsCallback, p_filter );
2117 var_AddCallback( p_filter, CFG_PREFIX "white-green",
2118 AtmoSettingsCallback, p_filter );
2119 var_AddCallback( p_filter, CFG_PREFIX "white-blue",
2120 AtmoSettingsCallback, p_filter );
2123 static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
2126 var_DelCallback( p_filter, CFG_PREFIX "filtermode",
2127 AtmoSettingsCallback, p_filter );
2129 var_DelCallback( p_filter, CFG_PREFIX "PercentNew",
2130 AtmoSettingsCallback, p_filter );
2131 var_DelCallback( p_filter, CFG_PREFIX "MeanLength",
2132 AtmoSettingsCallback, p_filter );
2133 var_DelCallback( p_filter, CFG_PREFIX "MeanThreshold",
2134 AtmoSettingsCallback, p_filter );
2136 var_DelCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2137 AtmoSettingsCallback, p_filter );
2138 var_DelCallback( p_filter, CFG_PREFIX "Brightness",
2139 AtmoSettingsCallback, p_filter );
2140 var_DelCallback( p_filter, CFG_PREFIX "DarknessLimit",
2141 AtmoSettingsCallback, p_filter );
2143 var_DelCallback( p_filter, CFG_PREFIX "HueWinSize",
2144 AtmoSettingsCallback, p_filter );
2145 var_DelCallback( p_filter, CFG_PREFIX "SatWinSize",
2146 AtmoSettingsCallback, p_filter );
2147 var_DelCallback( p_filter, CFG_PREFIX "FrameDelay",
2148 AtmoSettingsCallback, p_filter );
2151 var_DelCallback( p_filter, CFG_PREFIX "whiteadj",
2152 AtmoSettingsCallback, p_filter );
2153 var_DelCallback( p_filter, CFG_PREFIX "white-red",
2154 AtmoSettingsCallback, p_filter );
2155 var_DelCallback( p_filter, CFG_PREFIX "white-green",
2156 AtmoSettingsCallback, p_filter );
2157 var_DelCallback( p_filter, CFG_PREFIX "white-blue",
2158 AtmoSettingsCallback, p_filter );
2163 #if defined(__ATMO_DEBUG__)
2164 static void atmo_parse_crop(char *psz_cropconfig,
2165 video_format_t fmt_in,
2166 video_format_t fmt_render,
2167 int &i_visible_width, int &i_visible_height,
2168 int &i_x_offset, int &i_y_offset )
2170 int64_t i_aspect_num, i_aspect_den;
2171 unsigned int i_width, i_height;
2173 i_visible_width = fmt_in.i_visible_width;
2174 i_visible_height = fmt_in.i_visible_height;
2175 i_x_offset = fmt_in.i_x_offset;
2176 i_y_offset = fmt_in.i_y_offset;
2178 char *psz_end = NULL, *psz_parser = strchr( psz_cropconfig, ':' );
2181 /* We're using the 3:4 syntax */
2182 i_aspect_num = strtol( psz_cropconfig, &psz_end, 10 );
2183 if( psz_end == psz_cropconfig || !i_aspect_num ) return;
2185 i_aspect_den = strtol( ++psz_parser, &psz_end, 10 );
2186 if( psz_end == psz_parser || !i_aspect_den ) return;
2188 i_width = fmt_in.i_sar_den * fmt_render.i_visible_height *
2189 i_aspect_num / i_aspect_den / fmt_in.i_sar_num;
2191 i_height = fmt_render.i_visible_width*fmt_in.i_sar_num *
2192 i_aspect_den / i_aspect_num / fmt_in.i_sar_den;
2194 if( i_width < fmt_render.i_visible_width )
2196 i_x_offset = fmt_render.i_x_offset +
2197 (fmt_render.i_visible_width - i_width) / 2;
2198 i_visible_width = i_width;
2202 i_y_offset = fmt_render.i_y_offset +
2203 (fmt_render.i_visible_height - i_height) / 2;
2204 i_visible_height = i_height;
2209 psz_parser = strchr( psz_cropconfig, 'x' );
2212 /* Maybe we're using the <width>x<height>+<left>+<top> syntax */
2213 unsigned int i_crop_width, i_crop_height, i_crop_top, i_crop_left;
2215 i_crop_width = strtol( psz_cropconfig, &psz_end, 10 );
2216 if( psz_end != psz_parser ) return;
2218 psz_parser = strchr( ++psz_end, '+' );
2219 i_crop_height = strtol( psz_end, &psz_end, 10 );
2220 if( psz_end != psz_parser ) return;
2222 psz_parser = strchr( ++psz_end, '+' );
2223 i_crop_left = strtol( psz_end, &psz_end, 10 );
2224 if( psz_end != psz_parser ) return;
2227 i_crop_top = strtol( psz_end, &psz_end, 10 );
2228 if( *psz_end != '\0' ) return;
2230 i_width = i_crop_width;
2231 i_visible_width = i_width;
2233 i_height = i_crop_height;
2234 i_visible_height = i_height;
2236 i_x_offset = i_crop_left;
2237 i_y_offset = i_crop_top;
2241 /* Maybe we're using the <left>+<top>+<right>+<bottom> syntax */
2242 unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right;
2244 psz_parser = strchr( psz_cropconfig, '+' );
2245 i_crop_left = strtol( psz_cropconfig, &psz_end, 10 );
2246 if( psz_end != psz_parser ) return;
2248 psz_parser = strchr( ++psz_end, '+' );
2249 i_crop_top = strtol( psz_end, &psz_end, 10 );
2250 if( psz_end != psz_parser ) return;
2252 psz_parser = strchr( ++psz_end, '+' );
2253 i_crop_right = strtol( psz_end, &psz_end, 10 );
2254 if( psz_end != psz_parser ) return;
2257 i_crop_bottom = strtol( psz_end, &psz_end, 10 );
2258 if( *psz_end != '\0' ) return;
2260 i_width = fmt_render.i_visible_width - i_crop_left - i_crop_right;
2261 i_visible_width = i_width;
2263 i_height = fmt_render.i_visible_height - i_crop_top - i_crop_bottom;
2264 i_visible_height = i_height;
2266 i_x_offset = i_crop_left;
2267 i_y_offset = i_crop_top;