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 "\
121 "connected to your computer.\n"\
122 "AtmoLight is the homegrown version of what Philips calls AmbiLight.\n"\
123 "If you need further information 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 "You can find there detailed descriptions on how to build it for yourself "\
127 "and where to get the required parts.\n" \
128 "You can also have a look at pictures and some movies showing such a device " \
133 #if defined( __ATMO_DEBUG__ )
134 # define SAVEFRAMES_TEXT N_("Save Debug Frames")
135 # define SAVEFRAMES_LONGTEXT N_("Write every 128th miniframe to a folder.")
136 # define FRAMEPATH_TEXT N_("Debug Frame Folder")
137 # define FRAMEPATH_LONGTEXT N_("The path where the debugframes " \
141 #define WIDTH_TEXT N_("Extracted Image Width")
142 #define WIDTH_LONGTEXT N_("The width of the mini image for " \
143 "further processing (64 is default)")
145 #define HEIGHT_TEXT N_("Extracted Image Height")
146 #define HEIGHT_LONGTEXT N_("The height of the mini image for " \
147 "further processing (48 is default)")
149 #define PCOLOR_TEXT N_("Color when paused")
150 #define PCOLOR_LONGTEXT N_("Set the color to show if the user " \
151 "pauses the video. (Have light to get " \
153 #define PCOLOR_RED_TEXT N_("Pause-Red")
154 #define PCOLOR_RED_LONGTEXT N_("Red component of the pause color")
155 #define PCOLOR_GREEN_TEXT N_("Pause-Green")
156 #define PCOLOR_GREEN_LONGTEXT N_("Green component of the pause color")
157 #define PCOLOR_BLUE_TEXT N_("Pause-Blue")
158 #define PCOLOR_BLUE_LONGTEXT N_("Blue component of the pause color")
159 #define FADESTEPS_TEXT N_("Pause-Fadesteps")
160 #define FADESTEPS_LONGTEXT N_("Number of steps to change current color " \
161 "to pause color (each step takes 40ms)")
163 #define ECOLOR_RED_TEXT N_("End-Red")
164 #define ECOLOR_RED_LONGTEXT N_("Red component of the shutdown color")
165 #define ECOLOR_GREEN_TEXT N_("End-Green")
166 #define ECOLOR_GREEN_LONGTEXT N_("Green component of the shutdown color")
167 #define ECOLOR_BLUE_TEXT N_("End-Blue")
168 #define ECOLOR_BLUE_LONGTEXT N_("Blue component of the shutdown color")
169 #define EFADESTEPS_TEXT N_("End-Fadesteps")
170 #define EFADESTEPS_LONGTEXT N_("Number of steps to change current color to " \
171 "end color for dimming up the light in cinema " \
172 "style... (each step takes 40ms)")
174 #define USEWHITEADJ_TEXT N_("Use Software White adjust")
175 #define USEWHITEADJ_LONGTEXT N_("Should the buildin driver do a white " \
176 "adjust or your LED stripes? recommend.")
177 #define WHITE_RED_TEXT N_("White Red")
178 #define WHITE_RED_LONGTEXT N_("Red value of a pure white on your "\
180 #define WHITE_GREEN_TEXT N_("White Green")
181 #define WHITE_GREEN_LONGTEXT N_("Green value of a pure white on your "\
183 #define WHITE_BLUE_TEXT N_("White Blue")
184 #define WHITE_BLUE_LONGTEXT N_("Blue value of a pure white on your "\
187 #define SERIALDEV_TEXT N_("Serial Port/Device")
188 #define SERIALDEV_LONGTEXT N_("Name of the serial port where the AtmoLight "\
189 "controller is attached to.\n" \
190 "On Windows usually something like COM1 or " \
191 "COM2. On Linux /dev/ttyS01 f.e.")
193 #define EDGE_TEXT N_("Edge Weightning")
194 #define EDGE_LONGTEXT N_("Increasing this value will result in color "\
195 "more depending on the border of the frame.")
196 #define BRIGHTNESS_TEXT N_("Brightness")
197 #define BRIGHTNESS_LONGTEXT N_("Overall brightness of your LED stripes")
198 #define DARKNESS_TEXT N_("Darkness Limit")
199 #define DARKNESS_LONGTEXT N_("Pixels with a saturation lower than this will "\
200 "be ignored. Should be greater than one for "\
201 "letterboxed videos.")
202 #define HUEWINSIZE_TEXT N_("Hue windowing")
203 #define HUEWINSIZE_LONGTEXT N_("Used for statistics.")
204 #define SATWINSIZE_TEXT N_("Sat windowing")
205 #define SATWINSIZE_LONGTEXT N_("Used for statistics.")
207 #define MEANLENGTH_TEXT N_("Filter length (ms)")
208 #define MEANLENGTH_LONGTEXT N_("Time it takes until a color is completely "\
209 "changed. This prevents flickering.")
210 #define MEANTHRESHOLD_TEXT N_("Filter threshold")
211 #define MEANTHRESHOLD_LONGTEXT N_("How much a color has to be changed for an "\
212 "immediate color change.")
213 #define MEANPERCENTNEW_TEXT N_("Filter Smoothness (in %)")
214 #define MEANPERCENTNEW_LONGTEXT N_("Filter Smoothness")
216 /* FIXME: WTF?!! feepk, July 6 '08 */
217 #define FILTERMODE_TEXT N_("Filter mode")
218 #define FILTERMODE_LONGTEXT N_("kind of filtering which should be use to "\
219 "calcuate the color output")
220 static const int pi_filtermode_values[] = {
225 static const char *const ppsz_filtermode_descriptions[] = {
231 #define FRAMEDELAY_TEXT N_("Frame delay")
232 #define FRAMEDELAY_LONGTEXT N_("Helps to get the video output and the light "\
233 "effects in sync. Values around 20ms should " \
237 #define CHANNEL_0_ASSIGN_TEXT N_("Channel summary")
238 #define CHANNEL_1_ASSIGN_TEXT N_("Channel left")
239 #define CHANNEL_2_ASSIGN_TEXT N_("Channel right")
240 #define CHANNEL_3_ASSIGN_TEXT N_("Channel top")
241 #define CHANNEL_4_ASSIGN_TEXT N_("Channel bottom")
243 #define CHANNELASSIGN_LONGTEXT N_("Maps the hardware channel X to logical "\
244 "channel Y to fix wrong wiring :-)")
245 static const int pi_channel_assignment_values[] = {
253 static const char *const ppsz_channel_assignment_descriptions[] = {
262 #define ZONE_0_GRADIENT_TEXT N_("Summary gradient")
263 #define ZONE_1_GRADIENT_TEXT N_("Left gradient")
264 #define ZONE_2_GRADIENT_TEXT N_("Right gradient")
265 #define ZONE_3_GRADIENT_TEXT N_("Top gradient")
266 #define ZONE_4_GRADIENT_TEXT N_("Bottom gradient")
267 #define ZONE_X_GRADIENT_LONG_TEXT N_("Defines a small bitmap with 64x48 "\
268 "pixels, containing a grayscale gradient")
271 # define ATMOWINEXE_TEXT N_("Filename of AtmoWinA.exe")
272 # define ATMOWINEXE_LONGTEXT N_("if you want the AtmoLight control "\
273 "software to be launched by VLC, enter the "\
274 "complete path of AtmoWinA.exe here.")
275 # define USEBUILDIN_TEXT N_("Use built-in AtmoLight")
276 # define USEBUILDIN_LONGTEXT N_("VLC will directly use your AtmoLight "\
277 "hardware without running the external "\
278 "AtmoWinA.exe Userspace driver.")
281 #define CFG_PREFIX "atmo-"
283 /*****************************************************************************
285 *****************************************************************************/
287 set_description( N_("AtmoLight Filter") )
288 set_help( MODULE_DESCRIPTION )
289 set_shortname( N_( "AtmoLight" ))
290 set_capability( "video filter2", 0 )
292 set_category( CAT_VIDEO )
293 set_subcategory( SUBCAT_VIDEO_VFILTER )
296 set_section( N_("Choose between the built-in AtmoLight "\
297 "driver or the external" ), 0 )
300 only on win32 exists the option to use the buildin driver or
301 the more flexible external driver application
303 add_bool(CFG_PREFIX "usebuildin", true, NULL,
304 USEBUILDIN_TEXT, USEBUILDIN_LONGTEXT, false)
305 add_string(CFG_PREFIX "serialdev", "COM1", NULL,
306 SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false )
309 on win32 the executeable external driver application
310 for automatic start if needed
312 add_file(CFG_PREFIX "atmowinexe", NULL, NULL,
313 ATMOWINEXE_TEXT, ATMOWINEXE_LONGTEXT, false )
315 set_section( N_("Enter the connection of your AtmoLight hardware" ), 0 )
316 add_string(CFG_PREFIX "serialdev", "/dev/ttyS01", NULL,
317 SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false )
321 color which is showed if you want durring pausing
322 your movie ... used for both buildin / external
324 set_section( N_("Illuminate the room with this color on pause" ), 0 )
325 add_bool(CFG_PREFIX "usepausecolor", false, NULL,
326 PCOLOR_TEXT, PCOLOR_LONGTEXT, false)
327 add_integer_with_range(CFG_PREFIX "pcolor-red", 0, 0, 255, NULL,
328 PCOLOR_RED_TEXT, PCOLOR_RED_LONGTEXT, false)
329 add_integer_with_range(CFG_PREFIX "pcolor-green", 0, 0, 255, NULL,
330 PCOLOR_GREEN_TEXT, PCOLOR_GREEN_LONGTEXT, false)
331 add_integer_with_range(CFG_PREFIX "pcolor-blue", 192, 0, 255, NULL,
332 PCOLOR_BLUE_TEXT, PCOLOR_BLUE_LONGTEXT, false)
333 add_integer_with_range(CFG_PREFIX "fadesteps", 50, 1, 250, NULL,
334 FADESTEPS_TEXT, FADESTEPS_LONGTEXT, false)
337 color which is showed if you finished watching your movie ...
338 used for both buildin / external
340 set_section( N_("Illuminate the room with this color on shutdown" ), 0 )
341 add_integer_with_range(CFG_PREFIX "ecolor-red", 192, 0, 255, NULL,
342 ECOLOR_RED_TEXT, ECOLOR_RED_LONGTEXT, false)
343 add_integer_with_range(CFG_PREFIX "ecolor-green", 192, 0, 255, NULL,
344 ECOLOR_GREEN_TEXT, ECOLOR_GREEN_LONGTEXT, false)
345 add_integer_with_range(CFG_PREFIX "ecolor-blue", 192, 0, 255, NULL,
346 ECOLOR_BLUE_TEXT, ECOLOR_BLUE_LONGTEXT, false)
347 add_integer_with_range(CFG_PREFIX "efadesteps", 50, 1, 250, NULL,
348 EFADESTEPS_TEXT, EFADESTEPS_LONGTEXT, false)
351 settings only for the buildin driver (if external driver app is used
352 these parameters are ignored.)
354 definition of parameters for the buildin filter ...
356 set_section( N_("Settings for the built-in Live Video Processor only" ), 0 )
358 add_integer_with_range(CFG_PREFIX "EdgeWeightning", 8, 1, 30, NULL,
359 EDGE_TEXT, EDGE_LONGTEXT, false)
361 add_integer_with_range(CFG_PREFIX "Brightness", 100, 50, 300, NULL,
362 BRIGHTNESS_TEXT, BRIGHTNESS_LONGTEXT, false)
364 add_integer_with_range(CFG_PREFIX "DarknessLimit", 5, 0, 10, NULL,
365 DARKNESS_TEXT, DARKNESS_LONGTEXT, false)
367 add_integer_with_range(CFG_PREFIX "HueWinSize", 3, 0, 5, NULL,
368 HUEWINSIZE_TEXT, HUEWINSIZE_LONGTEXT, false)
370 add_integer_with_range(CFG_PREFIX "SatWinSize", 3, 0, 5, NULL,
371 SATWINSIZE_TEXT, SATWINSIZE_LONGTEXT, false)
373 add_integer(CFG_PREFIX "filtermode", (int)afmCombined, NULL,
374 FILTERMODE_TEXT, FILTERMODE_LONGTEXT, false )
376 change_integer_list(pi_filtermode_values, ppsz_filtermode_descriptions, NULL )
378 add_integer_with_range(CFG_PREFIX "MeanLength", 300, 300, 5000, NULL,
379 MEANLENGTH_TEXT, MEANLENGTH_LONGTEXT, false)
381 add_integer_with_range(CFG_PREFIX "MeanThreshold", 40, 1, 100, NULL,
382 MEANTHRESHOLD_TEXT, MEANTHRESHOLD_LONGTEXT, false)
384 add_integer_with_range(CFG_PREFIX "PercentNew", 50, 1, 100, NULL,
385 MEANPERCENTNEW_TEXT, MEANPERCENTNEW_LONGTEXT, false)
387 add_integer_with_range(CFG_PREFIX "FrameDelay", 18, 0, 35, NULL,
388 FRAMEDELAY_TEXT, FRAMEDELAY_LONGTEXT, false)
391 output channel reordering
393 set_section( N_("Change channel assignment (fixes wrong wiring)" ), 0 )
394 add_integer( CFG_PREFIX "channel_0", 0, NULL,
395 CHANNEL_0_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_1", 1, NULL,
400 CHANNEL_1_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_2", 2, NULL,
405 CHANNEL_2_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_3", 3, NULL,
410 CHANNEL_3_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
411 change_integer_list( pi_channel_assignment_values,
412 ppsz_channel_assignment_descriptions, 0 )
414 add_integer( CFG_PREFIX "channel_4", 4, NULL,
415 CHANNEL_4_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
416 change_integer_list( pi_channel_assignment_values,
417 ppsz_channel_assignment_descriptions, 0 )
420 LED color white calibration
422 set_section( N_("Adjust the white light to your LED stripes" ), 0 )
423 add_bool(CFG_PREFIX "whiteadj", true, NULL,
424 USEWHITEADJ_TEXT, USEWHITEADJ_LONGTEXT, false)
425 add_integer_with_range(CFG_PREFIX "white-red", 255, 0, 255, NULL,
426 WHITE_RED_TEXT, WHITE_RED_LONGTEXT, false)
428 add_integer_with_range(CFG_PREFIX "white-green", 255, 0, 255, NULL,
429 WHITE_GREEN_TEXT, WHITE_GREEN_LONGTEXT, false)
431 add_integer_with_range(CFG_PREFIX "white-blue", 255, 0, 255, NULL,
432 WHITE_BLUE_TEXT, WHITE_BLUE_LONGTEXT, false)
433 /* end of definition of parameter for the buildin filter ... part 1 */
437 only for buildin (external has own definition) per default the calucation
438 used linear gradients for assigning a priority to the pixel - depending
439 how near they are to the border ...for changing this you can create 64x48
440 Pixel BMP files - which contain your own grayscale... (you can produce funny
441 effects with this...) the images MUST not compressed, should have 24-bit per
442 pixel, or a simple 256 color grayscale palette
444 set_section( N_("Change gradients" ), 0 )
445 add_file(CFG_PREFIX "gradient_zone_0", NULL, NULL,
446 ZONE_0_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
447 add_file(CFG_PREFIX "gradient_zone_1", NULL, NULL,
448 ZONE_1_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
449 add_file(CFG_PREFIX "gradient_zone_2", NULL, NULL,
450 ZONE_2_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
451 add_file(CFG_PREFIX "gradient_zone_3", NULL, NULL,
452 ZONE_3_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
453 add_file(CFG_PREFIX "gradient_zone_4", NULL, NULL,
454 ZONE_4_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
457 #if defined(__ATMO_DEBUG__)
458 add_bool(CFG_PREFIX "saveframes", false, NULL,
459 SAVEFRAMES_TEXT, SAVEFRAMES_LONGTEXT, false)
460 add_string(CFG_PREFIX "framepath", "", NULL,
461 FRAMEPATH_TEXT, FRAMEPATH_LONGTEXT, false )
464 may be later if computers gets more power ;-) than now we increase
465 the samplesize from which we do the stats for output color calculation
467 add_integer_with_range(CFG_PREFIX "width", 64, 64, 512, NULL,
468 WIDTH_TEXT, WIDTH_LONGTEXT, true)
469 add_integer_with_range(CFG_PREFIX "height", 48, 48, 384, NULL,
470 HEIGHT_TEXT, HEIGHT_LONGTEXT, true)
472 add_shortcut( "atmo" )
473 set_callbacks( CreateFilter, DestroyFilter )
477 static const char *const ppsz_filter_options[] = {
524 #if defined(__ATMO_DEBUG__)
539 /*****************************************************************************
540 * fadethread_t: Color Fading Thread
541 *****************************************************************************
542 * changes slowly the color of the output if videostream gets paused...
543 *****************************************************************************
549 /* tell the thread which color should be the target of fading */
553 /* how many steps should happen until this */
558 static void *FadeToColorThread(vlc_object_t *);
561 /*****************************************************************************
562 * filter_sys_t: AtmoLight filter method descriptor
563 *****************************************************************************
564 * It describes the AtmoLight specific properties of an video filter.
565 *****************************************************************************/
569 special for the access of the p_fadethread member all other members
570 need no special protection so far!
572 vlc_mutex_t filter_lock;
575 int32_t i_AtmoOldEffect;
578 int32_t i_atmo_width;
579 int32_t i_atmo_height;
581 #if defined(__ATMO_DEBUG__)
584 char sz_framepath[MAX_PATH];
587 /* light color durring movie pause ... */
588 bool b_usepausecolor;
589 uint8_t ui_pausecolor_red;
590 uint8_t ui_pausecolor_green;
591 uint8_t ui_pausecolor_blue;
594 /* light color on movie finish ... */
595 uint8_t ui_endcolor_red;
596 uint8_t ui_endcolor_green;
597 uint8_t ui_endcolor_blue;
600 fadethread_t *p_fadethread;
602 /* Variables for buildin driver only... */
604 /* is only present and initialized if the internal driver is used*/
605 CAtmoConfig *p_atmo_config;
606 /* storage for temporal settings "volatile" */
607 CAtmoDynData *p_atmo_dyndata;
608 /* initialized for buildin driver with AtmoCreateTransferBuffers */
609 BITMAPINFOHEADER mini_image_format;
610 /* is only use buildin driver! */
611 uint8_t *p_atmo_transfer_buffer;
612 /* end buildin driver */
615 contains the real output size of the video calculated on
616 change event of the variable "crop" from vout
618 int32_t i_crop_x_offset;
619 int32_t i_crop_y_offset;
620 int32_t i_crop_width;
621 int32_t i_crop_height;
623 void (*pf_extract_mini_image) (filter_sys_t *p_sys,
625 uint8_t *p_transfer_dest);
628 /* External Library as wrapper arround COM Stuff */
629 HINSTANCE h_AtmoCtrl;
630 int32_t (*pf_ctrl_atmo_initialize) (void);
631 void (*pf_ctrl_atmo_finalize) (int32_t what);
632 int32_t (*pf_ctrl_atmo_switch_effect) (int32_t);
633 int32_t (*pf_ctrl_atmo_set_live_source) (int32_t);
634 void (*pf_ctrl_atmo_create_transfer_buffers) (int32_t, int32_t,
636 uint8_t* (*pf_ctrl_atmo_lock_transfer_buffer) (void);
637 void (*pf_ctrl_atmo_send_pixel_data) (void);
642 initialize previously configured Atmo Light environment
643 - if internal is enabled try to access the device on the serial port
644 - if not internal is enabled and we are on win32 try to initialize
645 the previously loaded DLL ...
647 Return Values may be: -1 (failed for some reason - filter will be disabled)
650 static int32_t AtmoInitialize(filter_t *p_filter, bool b_for_thread)
652 filter_sys_t *p_sys = p_filter->p_sys;
653 if(p_sys->p_atmo_config)
655 if(b_for_thread == false)
658 /* setup Output Threads ... */
659 msg_Dbg( p_filter, "open serial connection %s",
660 p_sys->p_atmo_config->getSerialDevice());
662 if(CAtmoTools::RecreateConnection(p_sys->p_atmo_dyndata) == ATMO_TRUE)
664 msg_Dbg( p_filter, "start live view thread ...");
665 CAtmoTools::SwitchEffect(p_sys->p_atmo_dyndata, emLivePicture);
666 msg_Dbg( p_filter, "live view thread launched...");
670 msg_Err( p_filter,"failed to open serial device? some other software/driver may use it?");
674 } else if(p_sys->pf_ctrl_atmo_initialize)
676 /* on win32 with active ctrl dll */
677 return p_sys->pf_ctrl_atmo_initialize();
684 prepare the shutdown of the effect threads,
685 for build in filter - close the serialport after finishing the threads...
686 cleanup possible loaded DLL...
688 static void AtmoFinalize(filter_t *p_filter, int32_t what)
690 filter_sys_t *p_sys = p_filter->p_sys;
691 if(p_sys->p_atmo_config)
695 CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
698 p_atmo_dyndata->LockCriticalSection();
700 CThread *p_effect_thread = p_atmo_dyndata->getEffectThread();
701 p_atmo_dyndata->setEffectThread(NULL);
702 if(p_effect_thread != NULL)
705 forced the thread to die...
706 and wait for termination of the thread
708 p_effect_thread->Terminate();
709 delete p_effect_thread;
710 msg_Dbg( p_filter, "effect thread died peacefully");
714 close serial port if it is open (all OS specific is inside
715 CAtmoSerialConnection implemented / defined)
717 CAtmoConnection *p_atmo_connection =
718 p_atmo_dyndata->getAtmoConnection();
719 p_atmo_dyndata->setAtmoConnection(NULL);
720 if(p_atmo_connection) {
721 p_atmo_connection->CloseConnection();
722 delete p_atmo_connection;
724 p_atmo_dyndata->UnLockCriticalSection();
728 } else if(p_sys->pf_ctrl_atmo_finalize)
730 /* on win32 with active ctrl dll */
731 p_sys->pf_ctrl_atmo_finalize(what);
737 switch the current light effect - does only something on win32, with the
738 external libraries - if the buildin effects are used nothing happens
740 static int32_t AtmoSwitchEffect(filter_t *p_filter, int32_t newMode)
742 filter_sys_t *p_sys = p_filter->p_sys;
743 if(p_sys->p_atmo_config)
748 doesnt know different modes for effects so this
749 function call would just do nothing special
754 } else if(p_sys->pf_ctrl_atmo_switch_effect)
756 /* on win32 with active ctrl dll */
757 return p_sys->pf_ctrl_atmo_switch_effect(newMode);
764 set the current live picture source, does only something on win32,
765 with the external libraries - if the buildin effects are used nothing
768 static int32_t AtmoSetLiveSource(filter_t *p_filter, int32_t newSource)
770 filter_sys_t *p_sys = p_filter->p_sys;
771 if(p_sys->p_atmo_config)
776 doesnt know different sources so this
777 function call would just do nothing special
781 } else if(p_sys->pf_ctrl_atmo_set_live_source)
783 /* on win32 with active ctrl dll */
784 return p_sys->pf_ctrl_atmo_set_live_source(newSource);
791 setup the pixel transferbuffers which is used to transfer pixeldata from
792 the filter to the effect thread, and possible accross the process
793 boundaries on win32, with the external DLL
795 static void AtmoCreateTransferBuffers(filter_t *p_filter,
797 int32_t bytePerPixel,
801 filter_sys_t *p_sys = p_filter->p_sys;
802 if(p_sys->p_atmo_config)
805 we need a buffer where the image is stored (only for transfer
806 to the processing thread)
808 free( p_sys->p_atmo_transfer_buffer );
810 p_sys->p_atmo_transfer_buffer = (uint8_t *)malloc(bytePerPixel *
813 memset(&p_sys->mini_image_format,0,sizeof(BITMAPINFOHEADER));
815 p_sys->mini_image_format.biSize = sizeof(BITMAPINFOHEADER);
816 p_sys->mini_image_format.biWidth = width;
817 p_sys->mini_image_format.biHeight = height;
818 p_sys->mini_image_format.biBitCount = bytePerPixel*8;
819 p_sys->mini_image_format.biCompression = FourCC;
822 } else if(p_sys->pf_ctrl_atmo_create_transfer_buffers)
824 /* on win32 with active ctrl dll */
825 p_sys->pf_ctrl_atmo_create_transfer_buffers(FourCC,
834 acquire the transfer buffer pointer the buildin version only
835 returns the pointer to the allocated buffer ... the
836 external version on win32 has to do some COM stuff to lock the
837 Variant Byte array which is behind the buffer
839 static uint8_t* AtmoLockTransferBuffer(filter_t *p_filter)
841 filter_sys_t *p_sys = p_filter->p_sys;
842 if(p_sys->p_atmo_config)
844 return p_sys->p_atmo_transfer_buffer;
846 } else if(p_sys->pf_ctrl_atmo_lock_transfer_buffer)
848 /* on win32 with active ctrl dll */
849 return p_sys->pf_ctrl_atmo_lock_transfer_buffer();
856 send the content of current pixel buffer got with AtmoLockTransferBuffer
857 to the processing threads
858 - build in version - will forward the data to AtmoExternalCaptureInput Thread
859 - win32 external - will do the same, but across the process boundaries via
860 COM to the AtmoWinA.exe Process
862 static void AtmoSendPixelData(filter_t *p_filter)
864 filter_sys_t *p_sys = p_filter->p_sys;
865 if(p_sys->p_atmo_config && p_sys->p_atmo_transfer_buffer)
867 CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
871 the cast will go Ok because we are inside videolan there is only
872 this kind of effect thread implemented!
875 CAtmoLiveView *p_atmo_live_view_thread =
876 (CAtmoLiveView *)p_atmo_dyndata->getEffectThread();
877 if(p_atmo_live_view_thread)
880 the same as above inside videolan only this single kind of
881 input exists so we can cast without further tests!
883 CAtmoExternalCaptureInput *p_atmo_external_capture_input_thread =
884 (CAtmoExternalCaptureInput *)p_atmo_live_view_thread->getAtmoInput();
885 if(p_atmo_external_capture_input_thread)
888 this call will do a 1:1 copy of this buffer, and wakeup
889 the thread from normal sleeping
891 p_atmo_external_capture_input_thread->
892 DeliverNewSourceDataPaket(&p_sys->mini_image_format,
893 p_sys->p_atmo_transfer_buffer);
898 } else if(p_sys->pf_ctrl_atmo_send_pixel_data)
900 /* on win32 with active ctrl dll */
901 p_sys->pf_ctrl_atmo_send_pixel_data();
907 Shutdown AtmoLight finally - is call from DestroyFilter
908 does the cleanup restores the effectmode on the external Software
909 (only win32) and possible setup the final light ...
911 static void Atmo_Shutdown(filter_t *p_filter)
913 filter_sys_t *p_sys = p_filter->p_sys;
915 if(p_sys->b_enabled == true)
918 if there is a still running show pause color thread kill him!
920 CheckAndStopFadeThread(p_filter);
922 if(p_sys->p_atmo_config || (p_sys->i_AtmoOldEffect == emStaticColor))
925 fade to end color (in case of external AtmoWin Software
926 assume that the static color will equal to this
927 one to get a soft change and no flash!
929 p_sys->b_pause_live = true;
931 // perpare spawn fadeing thread
932 vlc_mutex_lock( &p_sys->filter_lock );
934 p_sys->p_fadethread = (fadethread_t *)vlc_object_create( p_filter,
935 sizeof(fadethread_t) );
937 p_sys->p_fadethread->p_filter = p_filter;
938 p_sys->p_fadethread->ui_red = p_sys->ui_endcolor_red;
939 p_sys->p_fadethread->ui_green = p_sys->ui_endcolor_green;
940 p_sys->p_fadethread->ui_blue = p_sys->ui_endcolor_blue;
941 p_sys->p_fadethread->i_steps = p_sys->i_endfadesteps;
943 if( vlc_thread_create( p_sys->p_fadethread,
946 VLC_THREAD_PRIORITY_LOW ) )
948 msg_Err( p_filter, "cannot create FadeToColorThread" );
949 vlc_object_release( p_sys->p_fadethread );
950 p_sys->p_fadethread = NULL;
951 vlc_mutex_unlock( &p_sys->filter_lock );
955 vlc_mutex_unlock( &p_sys->filter_lock );
957 /* wait for the thread... */
958 vlc_thread_join(p_sys->p_fadethread);
960 vlc_object_release(p_sys->p_fadethread);
962 p_sys->p_fadethread = NULL;
966 if(p_sys->i_AtmoOldEffect != emLivePicture)
967 AtmoSwitchEffect(p_filter, p_sys->i_AtmoOldEffect);
969 AtmoSetLiveSource(p_filter, lvsGDI);
971 AtmoFinalize(p_filter, 1);
973 /* disable filter method .. */
974 p_sys->b_enabled = false;
979 initialize the filter_sys_t structure with the data from the settings
980 variables - if the external filter on win32 is enabled try loading the DLL,
981 if this fails fallback to the buildin software
983 static void Atmo_SetupParameters(filter_t *p_filter)
985 bool b_use_buildin_driver = true;
987 filter_sys_t *p_sys = p_filter->p_sys;
990 /* default filter disabled until DLL loaded and Init Success!*/
991 p_sys->b_enabled = false;
993 /* setup default mini image size (may be later a user option) */
994 p_sys->i_atmo_width = 64;
995 p_sys->i_atmo_height = 48;
998 vlc_mutex_init( &p_sys->filter_lock );
1003 only on WIN32 the user has the choice between
1004 internal driver and external
1006 b_use_buildin_driver = var_CreateGetBoolCommand( p_filter,
1007 CFG_PREFIX "usebuildin" );
1009 if(b_use_buildin_driver == false) {
1011 /* Load the Com Wrapper Library (source available) */
1012 p_sys->h_AtmoCtrl = LoadLibraryA("AtmoCtrlLib.dll");
1013 if(p_sys->h_AtmoCtrl != NULL)
1015 msg_Dbg( p_filter, "LoadLibrary('AtmoCtrlLib.dll'); Success");
1017 /* importing all required functions I hope*/
1018 p_sys->pf_ctrl_atmo_initialize =
1019 (int32_t (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoInitialize");
1020 if(!p_sys->pf_ctrl_atmo_initialize)
1021 msg_Err( p_filter, "export AtmoInitialize missing.");
1023 p_sys->pf_ctrl_atmo_finalize =
1024 (void (*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoFinalize");
1025 if(!p_sys->pf_ctrl_atmo_finalize)
1026 msg_Err( p_filter, "export AtmoFinalize missing.");
1028 p_sys->pf_ctrl_atmo_switch_effect =
1029 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSwitchEffect");
1030 if(!p_sys->pf_ctrl_atmo_switch_effect)
1031 msg_Err( p_filter, "export AtmoSwitchEffect missing.");
1033 p_sys->pf_ctrl_atmo_set_live_source =
1034 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSetLiveSource");
1035 if(!p_sys->pf_ctrl_atmo_set_live_source)
1036 msg_Err( p_filter, "export AtmoSetLiveSource missing.");
1038 p_sys->pf_ctrl_atmo_create_transfer_buffers =
1039 (void (*)(int32_t, int32_t, int32_t , int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoCreateTransferBuffers");
1040 if(!p_sys->pf_ctrl_atmo_create_transfer_buffers)
1041 msg_Err( p_filter, "export AtmoCreateTransferBuffers missing.");
1043 p_sys->pf_ctrl_atmo_lock_transfer_buffer=
1044 (uint8_t*(*) (void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoLockTransferBuffer");
1045 if(!p_sys->pf_ctrl_atmo_lock_transfer_buffer)
1046 msg_Err( p_filter, "export AtmoLockTransferBuffer missing.");
1048 p_sys->pf_ctrl_atmo_send_pixel_data =
1049 (void (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSendPixelData");
1050 if(!p_sys->pf_ctrl_atmo_send_pixel_data)
1051 msg_Err( p_filter, "export AtmoSendPixelData missing.");
1053 /* the DLL is missing try internal filter ...*/
1054 msg_Warn( p_filter, "AtmoCtrlLib.dll missing fallback to internal driver");
1055 b_use_buildin_driver = true;
1061 if(b_use_buildin_driver == true) {
1062 msg_Dbg( p_filter, "use buildin driver");
1064 now we have to read a lof of options from the config dialog
1065 most important the serial device if not set ... we can skip
1066 the rest and disable the filter...
1068 char *psz_serialdev = var_CreateGetStringCommand( p_filter,
1069 CFG_PREFIX "serialdev" );
1070 if(psz_serialdev && (strlen(psz_serialdev)>0)) {
1071 msg_Dbg( p_filter, "use buildin driver on port %s",psz_serialdev);
1073 p_sys->p_atmo_config = new CAtmoConfig();
1075 p_sys->p_atmo_config->setSerialDevice(psz_serialdev);
1077 p_sys->p_atmo_config->setLiveViewFilterMode(
1078 (AtmoFilterMode)var_CreateGetIntegerCommand( p_filter,
1079 CFG_PREFIX "filtermode")
1082 p_sys->p_atmo_config->setLiveViewFilter_PercentNew(
1083 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "PercentNew")
1085 p_sys->p_atmo_config->setLiveViewFilter_MeanLength(
1086 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanLength")
1088 p_sys->p_atmo_config->setLiveViewFilter_MeanThreshold(
1089 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanThreshold")
1092 p_sys->p_atmo_config->setLiveView_EdgeWeighting(
1093 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "EdgeWeightning")
1095 p_sys->p_atmo_config->setLiveView_BrightCorrect(
1096 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "Brightness")
1098 p_sys->p_atmo_config->setLiveView_DarknessLimit(
1099 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "DarknessLimit")
1101 p_sys->p_atmo_config->setLiveView_HueWinSize(
1102 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "HueWinSize")
1104 p_sys->p_atmo_config->setLiveView_SatWinSize(
1105 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "SatWinSize")
1108 /* currently not required inside vlc */
1109 p_sys->p_atmo_config->setLiveView_WidescreenMode( 0 );
1111 p_sys->p_atmo_config->setLiveView_FrameDelay(
1112 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "FrameDelay")
1116 p_sys->p_atmo_config->setUseSoftwareWhiteAdj(
1117 var_CreateGetBoolCommand( p_filter, CFG_PREFIX "whiteadj")
1119 p_sys->p_atmo_config->setWhiteAdjustment_Red(
1120 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-red")
1122 p_sys->p_atmo_config->setWhiteAdjustment_Green(
1123 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-green")
1125 p_sys->p_atmo_config->setWhiteAdjustment_Blue(
1126 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-blue")
1129 tChannelAssignment *p_channel_assignment =
1130 p_sys->p_atmo_config->getChannelAssignment(0);
1132 p_channel_assignment->mappings[0] = var_CreateGetIntegerCommand(
1133 p_filter, CFG_PREFIX "channel_0");
1135 p_channel_assignment->mappings[1] = var_CreateGetIntegerCommand(
1136 p_filter, CFG_PREFIX "channel_1");
1138 p_channel_assignment->mappings[2] = var_CreateGetIntegerCommand(
1139 p_filter, CFG_PREFIX "channel_2");
1141 p_channel_assignment->mappings[3] = var_CreateGetIntegerCommand(
1142 p_filter, CFG_PREFIX "channel_3");
1144 p_channel_assignment->mappings[4] = var_CreateGetIntegerCommand(
1145 p_filter, CFG_PREFIX "channel_4");
1147 for(int i=0;i<ATMO_NUM_CHANNELS;i++)
1148 msg_Dbg( p_filter, "map software channel %d to hardware channel %d",
1149 p_channel_assignment->mappings[i],
1154 char psz_gradient_var_name[30];
1155 char *psz_gradient_file;
1156 for(int i=0;i<ATMO_NUM_CHANNELS;i++)
1158 sprintf(psz_gradient_var_name, CFG_PREFIX "gradient_zone_%d", i);
1159 psz_gradient_file = var_CreateGetStringCommand(
1161 psz_gradient_var_name
1163 if(psz_gradient_file && strlen(psz_gradient_file)>0)
1165 msg_Dbg( p_filter, "loading gradientfile %s for "\
1166 "zone %d", psz_gradient_file, i);
1168 int i_res = p_sys->p_atmo_config->getZoneDefinition(i)->
1169 LoadGradientFromBitmap(psz_gradient_file);
1171 if(i_res != ATMO_LOAD_GRADIENT_OK)
1173 msg_Err( p_filter,"failed to load gradient '%s' with "\
1174 "error %d",psz_gradient_file,i_res);
1177 free( psz_gradient_file );
1180 p_sys->p_atmo_dyndata = new CAtmoDynData((vlc_object_t *)p_filter,
1181 p_sys->p_atmo_config
1184 msg_Dbg( p_filter, "buildin driver initialized");
1186 free(psz_serialdev);
1188 msg_Err(p_filter,"no serial devicename set");
1192 switch( p_filter->fmt_in.video.i_chroma )
1194 case VLC_CODEC_I420:
1195 case VLC_CODEC_YV12:
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(vlc_object_t *obj)
1723 fadethread_t *p_fadethread = (fadethread_t *)obj;
1724 filter_sys_t *p_sys = (filter_sys_t *)p_fadethread->p_filter->p_sys;
1725 int i_steps_done = 0;
1735 uint8_t *p_source = NULL;
1737 int canc = vlc_savecancel ();
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);
1822 vlc_restorecancel (canc);
1826 /*****************************************************************************
1827 * CheckAndStopFadeThread: if there is a fadethread structure left, or running.
1828 ******************************************************************************
1829 * this function will stop the thread ... and waits for its termination
1830 * before removeing the objects from vout_sys_t ...
1831 ******************************************************************************/
1832 static void CheckAndStopFadeThread(filter_t *p_filter)
1834 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1835 vlc_mutex_lock( &p_sys->filter_lock );
1836 if(p_sys->p_fadethread != NULL)
1838 msg_Dbg(p_filter, "kill still running fadeing thread...");
1840 p_sys->p_fadethread->b_die = true;
1842 vlc_thread_join(p_sys->p_fadethread);
1844 vlc_object_release(p_sys->p_fadethread);
1845 p_sys->p_fadethread = NULL;
1847 vlc_mutex_unlock( &p_sys->filter_lock );
1850 /*****************************************************************************
1851 * StateCallback: Callback for the inputs variable "State" to get notified
1852 * about Pause and Continue Playback events.
1853 *****************************************************************************/
1854 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
1855 vlc_value_t oldval, vlc_value_t newval,
1858 filter_t *p_filter = (filter_t *)p_data;
1859 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1861 if((p_sys->b_usepausecolor == true) && (p_sys->b_enabled == true))
1863 msg_Dbg(p_filter, "state change from: %d to %d", oldval.i_int,
1866 if((newval.i_int == PAUSE_S) && (oldval.i_int == PLAYING_S))
1868 /* tell the other thread to stop sending images to light
1870 p_sys->b_pause_live = true;
1872 // ggf. alten Thread abräumen should not happen....
1873 CheckAndStopFadeThread(p_filter);
1875 // perpare spawn fadeing thread
1876 vlc_mutex_lock( &p_sys->filter_lock );
1878 launch only a new thread if there is none active!
1879 or waiting for cleanup
1881 if(p_sys->p_fadethread == NULL)
1883 p_sys->p_fadethread = (fadethread_t *)vlc_object_create(
1885 sizeof(fadethread_t) );
1887 p_sys->p_fadethread->p_filter = p_filter;
1888 p_sys->p_fadethread->ui_red = p_sys->ui_pausecolor_red;
1889 p_sys->p_fadethread->ui_green = p_sys->ui_pausecolor_green;
1890 p_sys->p_fadethread->ui_blue = p_sys->ui_pausecolor_blue;
1891 p_sys->p_fadethread->i_steps = p_sys->i_fadesteps;
1893 if( vlc_thread_create( p_sys->p_fadethread,
1894 "AtmoLight fadeing",
1896 VLC_THREAD_PRIORITY_LOW ) )
1898 msg_Err( p_filter, "cannot create FadeToColorThread" );
1899 vlc_object_release( p_sys->p_fadethread );
1900 p_sys->p_fadethread = NULL;
1903 vlc_mutex_unlock( &p_sys->filter_lock );
1906 if((newval.i_int == PLAYING_S) && (oldval.i_int == PAUSE_S))
1908 /* playback continues check thread state */
1909 CheckAndStopFadeThread(p_filter);
1910 /* reactivate the Render function... to do its normal work */
1911 p_sys->b_pause_live = false;
1918 /*****************************************************************************
1919 * AddPlaylistInputThreadStateCallback: Setup call back on "State" Variable
1920 *****************************************************************************
1921 * Add Callback function to the "state" variable of the input thread..
1922 * first find the PlayList and get the input thread from there to attach
1923 * my callback? is vlc_object_find the right way for this??
1924 *****************************************************************************/
1925 static void AddStateVariableCallback(filter_t *p_filter)
1927 playlist_t *p_playlist = pl_Hold( p_filter );
1928 input_thread_t *p_input = playlist_CurrentInput( p_playlist );
1931 var_AddCallback( p_input, "state", StateCallback, p_filter );
1932 vlc_object_release( p_input );
1934 pl_Release( p_filter );
1937 /*****************************************************************************
1938 * DelPlaylistInputThreadStateCallback: Remove call back on "State" Variable
1939 *****************************************************************************
1940 * Delete the callback function to the "state" variable of the input thread...
1941 * first find the PlayList and get the input thread from there to attach
1942 * my callback? is vlc_object_find the right way for this??
1943 *****************************************************************************/
1944 static void DelStateVariableCallback( filter_t *p_filter )
1946 playlist_t *p_playlist = pl_Hold( p_filter );
1947 input_thread_t *p_input = playlist_CurrentInput( p_playlist );
1950 var_DelCallback( p_input, "state", StateCallback, p_filter );
1951 vlc_object_release( p_input );
1953 pl_Release( p_filter );
1957 static int CropCallback(vlc_object_t *p_this, char const *psz_cmd,
1958 vlc_value_t oldval, vlc_value_t newval,
1961 vout_thread_t *p_vout = (vout_thread_t *)p_this;
1962 filter_t *p_filter = (filter_t *)p_data;
1963 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1966 //if the handler is attache to crop variable directly!
1967 int i_visible_width, i_visible_height, i_x_offset, i_y_offset;
1968 atmo_parse_crop(newval.psz_string, p_vout->fmt_render,
1970 i_visible_width, i_visible_height,
1971 i_x_offset, i_y_offset);
1972 p_sys->i_crop_x_offset = i_x_offset;
1973 p_sys->i_crop_y_offset = i_y_offset;
1974 p_sys->i_crop_width = i_visible_width;
1975 p_sys->i_crop_height = i_visible_height;
1978 p_sys->i_crop_x_offset = p_vout->fmt_in.i_x_offset;
1979 p_sys->i_crop_y_offset = p_vout->fmt_in.i_y_offset;
1980 p_sys->i_crop_width = p_vout->fmt_in.i_visible_width;
1981 p_sys->i_crop_height = p_vout->fmt_in.i_visible_height;
1983 msg_Dbg(p_filter, "cropping picture %ix%i to %i,%i,%ix%i",
1984 p_vout->fmt_in.i_width,
1985 p_vout->fmt_in.i_height,
1986 p_sys->i_crop_x_offset,
1987 p_sys->i_crop_y_offset,
1988 p_sys->i_crop_width,
1989 p_sys->i_crop_height
1996 static void AddCropVariableCallback( filter_t *p_filter)
1998 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2003 var_AddCallback( p_vout, "crop-update", CropCallback, p_filter );
2004 vlc_object_release( p_vout );
2008 static void DelCropVariableCallback( filter_t *p_filter)
2010 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2015 var_DelCallback( p_vout, "crop-update", CropCallback, p_filter );
2016 vlc_object_release( p_vout );
2021 /****************************************************************************
2022 * StateCallback: Callback for the inputs variable "State" to get notified
2023 * about Pause and Continue Playback events.
2024 *****************************************************************************/
2025 static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
2026 vlc_value_t oldval, vlc_value_t newval,
2029 filter_t *p_filter = (filter_t *)p_data;
2030 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
2032 CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
2036 msg_Dbg(p_filter, "apply AtmoSettingsCallback %s (int: %d -> %d)",
2042 if( !strcmp( psz_var, CFG_PREFIX "filtermode" ))
2043 p_atmo_config->setLiveViewFilterMode( (AtmoFilterMode)newval.i_int);
2045 else if( !strcmp( psz_var, CFG_PREFIX "PercentNew" ))
2046 p_atmo_config->setLiveViewFilter_PercentNew( newval.i_int );
2048 else if( !strcmp( psz_var, CFG_PREFIX "MeanLength" ))
2049 p_atmo_config->setLiveViewFilter_MeanLength( newval.i_int );
2051 else if( !strcmp( psz_var, CFG_PREFIX "MeanThreshold" ))
2052 p_atmo_config->setLiveViewFilter_MeanThreshold( newval.i_int );
2054 else if( !strcmp( psz_var, CFG_PREFIX "EdgeWeightning" ))
2055 p_atmo_config->setLiveView_EdgeWeighting( newval.i_int );
2057 else if( !strcmp( psz_var, CFG_PREFIX "Brightness" ))
2058 p_atmo_config->setLiveView_BrightCorrect( newval.i_int );
2060 else if( !strcmp( psz_var, CFG_PREFIX "DarknessLimit" ))
2061 p_atmo_config->setLiveView_DarknessLimit( newval.i_int );
2063 else if( !strcmp( psz_var, CFG_PREFIX "HueWinSize" ))
2064 p_atmo_config->setLiveView_HueWinSize( newval.i_int );
2066 else if( !strcmp( psz_var, CFG_PREFIX "SatWinSize" ))
2067 p_atmo_config->setLiveView_SatWinSize( newval.i_int );
2069 else if( !strcmp( psz_var, CFG_PREFIX "FrameDelay" ))
2070 p_atmo_config->setLiveView_FrameDelay( newval.i_int );
2072 else if( !strcmp( psz_var, CFG_PREFIX "whiteadj" ))
2073 p_atmo_config->setUseSoftwareWhiteAdj( newval.b_bool );
2075 else if( !strcmp( psz_var, CFG_PREFIX "white-red" ))
2076 p_atmo_config->setWhiteAdjustment_Red( newval.i_int );
2078 else if( !strcmp( psz_var, CFG_PREFIX "white-green" ))
2079 p_atmo_config->setWhiteAdjustment_Green( newval.i_int );
2081 else if( !strcmp( psz_var, CFG_PREFIX "white-blue" ))
2082 p_atmo_config->setWhiteAdjustment_Blue( newval.i_int );
2088 static void AddAtmoSettingsVariablesCallbacks(filter_t *p_filter)
2090 var_AddCallback( p_filter, CFG_PREFIX "filtermode",
2091 AtmoSettingsCallback, p_filter );
2092 var_AddCallback( p_filter, CFG_PREFIX "PercentNew",
2093 AtmoSettingsCallback, p_filter );
2096 var_AddCallback( p_filter, CFG_PREFIX "MeanLength",
2097 AtmoSettingsCallback, p_filter );
2098 var_AddCallback( p_filter, CFG_PREFIX "MeanThreshold",
2099 AtmoSettingsCallback, p_filter );
2101 var_AddCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2102 AtmoSettingsCallback, p_filter );
2103 var_AddCallback( p_filter, CFG_PREFIX "Brightness",
2104 AtmoSettingsCallback, p_filter );
2105 var_AddCallback( p_filter, CFG_PREFIX "DarknessLimit",
2106 AtmoSettingsCallback, p_filter );
2108 var_AddCallback( p_filter, CFG_PREFIX "HueWinSize",
2109 AtmoSettingsCallback, p_filter );
2110 var_AddCallback( p_filter, CFG_PREFIX "SatWinSize",
2111 AtmoSettingsCallback, p_filter );
2112 var_AddCallback( p_filter, CFG_PREFIX "FrameDelay",
2113 AtmoSettingsCallback, p_filter );
2116 var_AddCallback( p_filter, CFG_PREFIX "whiteadj",
2117 AtmoSettingsCallback, p_filter );
2118 var_AddCallback( p_filter, CFG_PREFIX "white-red",
2119 AtmoSettingsCallback, p_filter );
2120 var_AddCallback( p_filter, CFG_PREFIX "white-green",
2121 AtmoSettingsCallback, p_filter );
2122 var_AddCallback( p_filter, CFG_PREFIX "white-blue",
2123 AtmoSettingsCallback, p_filter );
2126 static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
2129 var_DelCallback( p_filter, CFG_PREFIX "filtermode",
2130 AtmoSettingsCallback, p_filter );
2132 var_DelCallback( p_filter, CFG_PREFIX "PercentNew",
2133 AtmoSettingsCallback, p_filter );
2134 var_DelCallback( p_filter, CFG_PREFIX "MeanLength",
2135 AtmoSettingsCallback, p_filter );
2136 var_DelCallback( p_filter, CFG_PREFIX "MeanThreshold",
2137 AtmoSettingsCallback, p_filter );
2139 var_DelCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2140 AtmoSettingsCallback, p_filter );
2141 var_DelCallback( p_filter, CFG_PREFIX "Brightness",
2142 AtmoSettingsCallback, p_filter );
2143 var_DelCallback( p_filter, CFG_PREFIX "DarknessLimit",
2144 AtmoSettingsCallback, p_filter );
2146 var_DelCallback( p_filter, CFG_PREFIX "HueWinSize",
2147 AtmoSettingsCallback, p_filter );
2148 var_DelCallback( p_filter, CFG_PREFIX "SatWinSize",
2149 AtmoSettingsCallback, p_filter );
2150 var_DelCallback( p_filter, CFG_PREFIX "FrameDelay",
2151 AtmoSettingsCallback, p_filter );
2154 var_DelCallback( p_filter, CFG_PREFIX "whiteadj",
2155 AtmoSettingsCallback, p_filter );
2156 var_DelCallback( p_filter, CFG_PREFIX "white-red",
2157 AtmoSettingsCallback, p_filter );
2158 var_DelCallback( p_filter, CFG_PREFIX "white-green",
2159 AtmoSettingsCallback, p_filter );
2160 var_DelCallback( p_filter, CFG_PREFIX "white-blue",
2161 AtmoSettingsCallback, p_filter );
2166 #if defined(__ATMO_DEBUG__)
2167 static void atmo_parse_crop(char *psz_cropconfig,
2168 video_format_t fmt_in,
2169 video_format_t fmt_render,
2170 int &i_visible_width, int &i_visible_height,
2171 int &i_x_offset, int &i_y_offset )
2173 int64_t i_aspect_num, i_aspect_den;
2174 unsigned int i_width, i_height;
2176 i_visible_width = fmt_in.i_visible_width;
2177 i_visible_height = fmt_in.i_visible_height;
2178 i_x_offset = fmt_in.i_x_offset;
2179 i_y_offset = fmt_in.i_y_offset;
2181 char *psz_end = NULL, *psz_parser = strchr( psz_cropconfig, ':' );
2184 /* We're using the 3:4 syntax */
2185 i_aspect_num = strtol( psz_cropconfig, &psz_end, 10 );
2186 if( psz_end == psz_cropconfig || !i_aspect_num ) return;
2188 i_aspect_den = strtol( ++psz_parser, &psz_end, 10 );
2189 if( psz_end == psz_parser || !i_aspect_den ) return;
2191 i_width = fmt_in.i_sar_den * fmt_render.i_visible_height *
2192 i_aspect_num / i_aspect_den / fmt_in.i_sar_num;
2194 i_height = fmt_render.i_visible_width*fmt_in.i_sar_num *
2195 i_aspect_den / i_aspect_num / fmt_in.i_sar_den;
2197 if( i_width < fmt_render.i_visible_width )
2199 i_x_offset = fmt_render.i_x_offset +
2200 (fmt_render.i_visible_width - i_width) / 2;
2201 i_visible_width = i_width;
2205 i_y_offset = fmt_render.i_y_offset +
2206 (fmt_render.i_visible_height - i_height) / 2;
2207 i_visible_height = i_height;
2212 psz_parser = strchr( psz_cropconfig, 'x' );
2215 /* Maybe we're using the <width>x<height>+<left>+<top> syntax */
2216 unsigned int i_crop_width, i_crop_height, i_crop_top, i_crop_left;
2218 i_crop_width = strtol( psz_cropconfig, &psz_end, 10 );
2219 if( psz_end != psz_parser ) return;
2221 psz_parser = strchr( ++psz_end, '+' );
2222 i_crop_height = strtol( psz_end, &psz_end, 10 );
2223 if( psz_end != psz_parser ) return;
2225 psz_parser = strchr( ++psz_end, '+' );
2226 i_crop_left = strtol( psz_end, &psz_end, 10 );
2227 if( psz_end != psz_parser ) return;
2230 i_crop_top = strtol( psz_end, &psz_end, 10 );
2231 if( *psz_end != '\0' ) return;
2233 i_width = i_crop_width;
2234 i_visible_width = i_width;
2236 i_height = i_crop_height;
2237 i_visible_height = i_height;
2239 i_x_offset = i_crop_left;
2240 i_y_offset = i_crop_top;
2244 /* Maybe we're using the <left>+<top>+<right>+<bottom> syntax */
2245 unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right;
2247 psz_parser = strchr( psz_cropconfig, '+' );
2248 i_crop_left = strtol( psz_cropconfig, &psz_end, 10 );
2249 if( psz_end != psz_parser ) return;
2251 psz_parser = strchr( ++psz_end, '+' );
2252 i_crop_top = strtol( psz_end, &psz_end, 10 );
2253 if( psz_end != psz_parser ) return;
2255 psz_parser = strchr( ++psz_end, '+' );
2256 i_crop_right = strtol( psz_end, &psz_end, 10 );
2257 if( psz_end != psz_parser ) return;
2260 i_crop_bottom = strtol( psz_end, &psz_end, 10 );
2261 if( *psz_end != '\0' ) return;
2263 i_width = fmt_render.i_visible_width - i_crop_left - i_crop_right;
2264 i_visible_width = i_width;
2266 i_height = fmt_render.i_visible_height - i_crop_top - i_crop_bottom;
2267 i_visible_height = i_height;
2269 i_x_offset = i_crop_left;
2270 i_y_offset = i_crop_top;