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 if(p_sys->p_atmo_transfer_buffer)
809 free(p_sys->p_atmo_transfer_buffer);
811 p_sys->p_atmo_transfer_buffer = (uint8_t *)malloc(bytePerPixel *
814 memset(&p_sys->mini_image_format,0,sizeof(BITMAPINFOHEADER));
816 p_sys->mini_image_format.biSize = sizeof(BITMAPINFOHEADER);
817 p_sys->mini_image_format.biWidth = width;
818 p_sys->mini_image_format.biHeight = height;
819 p_sys->mini_image_format.biBitCount = bytePerPixel*8;
820 p_sys->mini_image_format.biCompression = FourCC;
823 } else if(p_sys->pf_ctrl_atmo_create_transfer_buffers)
825 /* on win32 with active ctrl dll */
826 p_sys->pf_ctrl_atmo_create_transfer_buffers(FourCC,
835 acquire the transfer buffer pointer the buildin version only
836 returns the pointer to the allocated buffer ... the
837 external version on win32 has to do some COM stuff to lock the
838 Variant Byte array which is behind the buffer
840 static uint8_t* AtmoLockTransferBuffer(filter_t *p_filter)
842 filter_sys_t *p_sys = p_filter->p_sys;
843 if(p_sys->p_atmo_config)
845 return p_sys->p_atmo_transfer_buffer;
847 } else if(p_sys->pf_ctrl_atmo_lock_transfer_buffer)
849 /* on win32 with active ctrl dll */
850 return p_sys->pf_ctrl_atmo_lock_transfer_buffer();
857 send the content of current pixel buffer got with AtmoLockTransferBuffer
858 to the processing threads
859 - build in version - will forward the data to AtmoExternalCaptureInput Thread
860 - win32 external - will do the same, but across the process boundaries via
861 COM to the AtmoWinA.exe Process
863 static void AtmoSendPixelData(filter_t *p_filter)
865 filter_sys_t *p_sys = p_filter->p_sys;
866 if(p_sys->p_atmo_config && p_sys->p_atmo_transfer_buffer)
868 CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
872 the cast will go Ok because we are inside videolan there is only
873 this kind of effect thread implemented!
876 CAtmoLiveView *p_atmo_live_view_thread =
877 (CAtmoLiveView *)p_atmo_dyndata->getEffectThread();
878 if(p_atmo_live_view_thread)
881 the same as above inside videolan only this single kind of
882 input exists so we can cast without further tests!
884 CAtmoExternalCaptureInput *p_atmo_external_capture_input_thread =
885 (CAtmoExternalCaptureInput *)p_atmo_live_view_thread->getAtmoInput();
886 if(p_atmo_external_capture_input_thread)
889 this call will do a 1:1 copy of this buffer, and wakeup
890 the thread from normal sleeping
892 p_atmo_external_capture_input_thread->
893 DeliverNewSourceDataPaket(&p_sys->mini_image_format,
894 p_sys->p_atmo_transfer_buffer);
899 } else if(p_sys->pf_ctrl_atmo_send_pixel_data)
901 /* on win32 with active ctrl dll */
902 p_sys->pf_ctrl_atmo_send_pixel_data();
908 Shutdown AtmoLight finally - is call from DestroyFilter
909 does the cleanup restores the effectmode on the external Software
910 (only win32) and possible setup the final light ...
912 static void Atmo_Shutdown(filter_t *p_filter)
914 filter_sys_t *p_sys = p_filter->p_sys;
916 if(p_sys->b_enabled == true)
919 if there is a still running show pause color thread kill him!
921 CheckAndStopFadeThread(p_filter);
923 if(p_sys->p_atmo_config || (p_sys->i_AtmoOldEffect == emStaticColor))
926 fade to end color (in case of external AtmoWin Software
927 assume that the static color will equal to this
928 one to get a soft change and no flash!
930 p_sys->b_pause_live = true;
932 // perpare spawn fadeing thread
933 vlc_mutex_lock( &p_sys->filter_lock );
935 p_sys->p_fadethread = (fadethread_t *)vlc_object_create( p_filter,
936 sizeof(fadethread_t) );
938 p_sys->p_fadethread->p_filter = p_filter;
939 p_sys->p_fadethread->ui_red = p_sys->ui_endcolor_red;
940 p_sys->p_fadethread->ui_green = p_sys->ui_endcolor_green;
941 p_sys->p_fadethread->ui_blue = p_sys->ui_endcolor_blue;
942 p_sys->p_fadethread->i_steps = p_sys->i_endfadesteps;
944 if( vlc_thread_create( p_sys->p_fadethread,
947 VLC_THREAD_PRIORITY_LOW ) )
949 msg_Err( p_filter, "cannot create FadeToColorThread" );
950 vlc_object_release( p_sys->p_fadethread );
951 p_sys->p_fadethread = NULL;
952 vlc_mutex_unlock( &p_sys->filter_lock );
956 vlc_mutex_unlock( &p_sys->filter_lock );
958 /* wait for the thread... */
959 vlc_thread_join(p_sys->p_fadethread);
961 vlc_object_release(p_sys->p_fadethread);
963 p_sys->p_fadethread = NULL;
967 if(p_sys->i_AtmoOldEffect != emLivePicture)
968 AtmoSwitchEffect(p_filter, p_sys->i_AtmoOldEffect);
970 AtmoSetLiveSource(p_filter, lvsGDI);
972 AtmoFinalize(p_filter, 1);
974 /* disable filter method .. */
975 p_sys->b_enabled = false;
980 initialize the filter_sys_t structure with the data from the settings
981 variables - if the external filter on win32 is enabled try loading the DLL,
982 if this fails fallback to the buildin software
984 static void Atmo_SetupParameters(filter_t *p_filter)
986 bool b_use_buildin_driver = true;
988 filter_sys_t *p_sys = p_filter->p_sys;
991 /* default filter disabled until DLL loaded and Init Success!*/
992 p_sys->b_enabled = false;
994 /* setup default mini image size (may be later a user option) */
995 p_sys->i_atmo_width = 64;
996 p_sys->i_atmo_height = 48;
999 vlc_mutex_init( &p_sys->filter_lock );
1004 only on WIN32 the user has the choice between
1005 internal driver and external
1007 b_use_buildin_driver = var_CreateGetBoolCommand( p_filter,
1008 CFG_PREFIX "usebuildin" );
1010 if(b_use_buildin_driver == false) {
1012 /* Load the Com Wrapper Library (source available) */
1013 p_sys->h_AtmoCtrl = LoadLibraryA("AtmoCtrlLib.dll");
1014 if(p_sys->h_AtmoCtrl != NULL)
1016 msg_Dbg( p_filter, "LoadLibrary('AtmoCtrlLib.dll'); Success");
1018 /* importing all required functions I hope*/
1019 p_sys->pf_ctrl_atmo_initialize =
1020 (int32_t (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoInitialize");
1021 if(!p_sys->pf_ctrl_atmo_initialize)
1022 msg_Err( p_filter, "export AtmoInitialize missing.");
1024 p_sys->pf_ctrl_atmo_finalize =
1025 (void (*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoFinalize");
1026 if(!p_sys->pf_ctrl_atmo_finalize)
1027 msg_Err( p_filter, "export AtmoFinalize missing.");
1029 p_sys->pf_ctrl_atmo_switch_effect =
1030 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSwitchEffect");
1031 if(!p_sys->pf_ctrl_atmo_switch_effect)
1032 msg_Err( p_filter, "export AtmoSwitchEffect missing.");
1034 p_sys->pf_ctrl_atmo_set_live_source =
1035 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSetLiveSource");
1036 if(!p_sys->pf_ctrl_atmo_set_live_source)
1037 msg_Err( p_filter, "export AtmoSetLiveSource missing.");
1039 p_sys->pf_ctrl_atmo_create_transfer_buffers =
1040 (void (*)(int32_t, int32_t, int32_t , int32_t))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoCreateTransferBuffers");
1041 if(!p_sys->pf_ctrl_atmo_create_transfer_buffers)
1042 msg_Err( p_filter, "export AtmoCreateTransferBuffers missing.");
1044 p_sys->pf_ctrl_atmo_lock_transfer_buffer=
1045 (uint8_t*(*) (void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoLockTransferBuffer");
1046 if(!p_sys->pf_ctrl_atmo_lock_transfer_buffer)
1047 msg_Err( p_filter, "export AtmoLockTransferBuffer missing.");
1049 p_sys->pf_ctrl_atmo_send_pixel_data =
1050 (void (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,"AtmoSendPixelData");
1051 if(!p_sys->pf_ctrl_atmo_send_pixel_data)
1052 msg_Err( p_filter, "export AtmoSendPixelData missing.");
1054 /* the DLL is missing try internal filter ...*/
1055 msg_Warn( p_filter, "AtmoCtrlLib.dll missing fallback to internal driver");
1056 b_use_buildin_driver = true;
1062 if(b_use_buildin_driver == true) {
1063 msg_Dbg( p_filter, "use buildin driver");
1065 now we have to read a lof of options from the config dialog
1066 most important the serial device if not set ... we can skip
1067 the rest and disable the filter...
1069 char *psz_serialdev = var_CreateGetStringCommand( p_filter,
1070 CFG_PREFIX "serialdev" );
1071 if(psz_serialdev && (strlen(psz_serialdev)>0)) {
1072 msg_Dbg( p_filter, "use buildin driver on port %s",psz_serialdev);
1074 p_sys->p_atmo_config = new CAtmoConfig();
1076 p_sys->p_atmo_config->setSerialDevice(psz_serialdev);
1078 p_sys->p_atmo_config->setLiveViewFilterMode(
1079 (AtmoFilterMode)var_CreateGetIntegerCommand( p_filter,
1080 CFG_PREFIX "filtermode")
1083 p_sys->p_atmo_config->setLiveViewFilter_PercentNew(
1084 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "PercentNew")
1086 p_sys->p_atmo_config->setLiveViewFilter_MeanLength(
1087 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanLength")
1089 p_sys->p_atmo_config->setLiveViewFilter_MeanThreshold(
1090 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "MeanThreshold")
1093 p_sys->p_atmo_config->setLiveView_EdgeWeighting(
1094 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "EdgeWeightning")
1096 p_sys->p_atmo_config->setLiveView_BrightCorrect(
1097 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "Brightness")
1099 p_sys->p_atmo_config->setLiveView_DarknessLimit(
1100 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "DarknessLimit")
1102 p_sys->p_atmo_config->setLiveView_HueWinSize(
1103 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "HueWinSize")
1105 p_sys->p_atmo_config->setLiveView_SatWinSize(
1106 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "SatWinSize")
1109 /* currently not required inside vlc */
1110 p_sys->p_atmo_config->setLiveView_WidescreenMode( 0 );
1112 p_sys->p_atmo_config->setLiveView_FrameDelay(
1113 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "FrameDelay")
1117 p_sys->p_atmo_config->setUseSoftwareWhiteAdj(
1118 var_CreateGetBoolCommand( p_filter, CFG_PREFIX "whiteadj")
1120 p_sys->p_atmo_config->setWhiteAdjustment_Red(
1121 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-red")
1123 p_sys->p_atmo_config->setWhiteAdjustment_Green(
1124 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-green")
1126 p_sys->p_atmo_config->setWhiteAdjustment_Blue(
1127 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-blue")
1130 tChannelAssignment *p_channel_assignment =
1131 p_sys->p_atmo_config->getChannelAssignment(0);
1133 p_channel_assignment->mappings[0] = var_CreateGetIntegerCommand(
1134 p_filter, CFG_PREFIX "channel_0");
1136 p_channel_assignment->mappings[1] = var_CreateGetIntegerCommand(
1137 p_filter, CFG_PREFIX "channel_1");
1139 p_channel_assignment->mappings[2] = var_CreateGetIntegerCommand(
1140 p_filter, CFG_PREFIX "channel_2");
1142 p_channel_assignment->mappings[3] = var_CreateGetIntegerCommand(
1143 p_filter, CFG_PREFIX "channel_3");
1145 p_channel_assignment->mappings[4] = var_CreateGetIntegerCommand(
1146 p_filter, CFG_PREFIX "channel_4");
1148 for(int i=0;i<ATMO_NUM_CHANNELS;i++)
1149 msg_Dbg( p_filter, "map software channel %d to hardware channel %d",
1150 p_channel_assignment->mappings[i],
1155 char psz_gradient_var_name[30];
1156 char *psz_gradient_file;
1157 for(int i=0;i<ATMO_NUM_CHANNELS;i++)
1159 sprintf(psz_gradient_var_name, CFG_PREFIX "gradient_zone_%d", i);
1160 psz_gradient_file = var_CreateGetStringCommand(
1162 psz_gradient_var_name
1164 if(psz_gradient_file && strlen(psz_gradient_file)>0)
1166 msg_Dbg( p_filter, "loading gradientfile %s for "\
1167 "zone %d", psz_gradient_file, i);
1169 int i_res = p_sys->p_atmo_config->getZoneDefinition(i)->
1170 LoadGradientFromBitmap(psz_gradient_file);
1172 if(i_res != ATMO_LOAD_GRADIENT_OK)
1174 msg_Err( p_filter,"failed to load gradient '%s' with "\
1175 "error %d",psz_gradient_file,i_res);
1178 free( psz_gradient_file );
1181 p_sys->p_atmo_dyndata = new CAtmoDynData((vlc_object_t *)p_filter,
1182 p_sys->p_atmo_config
1185 msg_Dbg( p_filter, "buildin driver initialized");
1187 free(psz_serialdev);
1189 msg_Err(p_filter,"no serial devicename set");
1193 switch( p_filter->fmt_in.video.i_chroma )
1195 case VLC_FOURCC('I','4','2','0'):
1196 case VLC_FOURCC('I','Y','U','V'):
1197 case VLC_FOURCC('Y','V','1','2'):
1198 case VLC_FOURCC('Y','V','1','6'):
1199 case VLC_FOURCC('Y','V','U','9'):
1200 // simple enough? Dionoea?
1201 p_sys->pf_extract_mini_image = ExtractMiniImage_YUV;
1204 msg_Dbg( p_filter, "InitFilter-unsupported chroma: %4.4s",
1205 (char *)&p_filter->fmt_in.video.i_chroma);
1206 p_sys->pf_extract_mini_image = NULL;
1209 p_sys->i_crop_x_offset = 0;
1210 p_sys->i_crop_y_offset = 0;
1211 p_sys->i_crop_width = p_filter->fmt_in.video.i_visible_width;
1212 p_sys->i_crop_height = p_filter->fmt_in.video.i_visible_height;
1214 msg_Dbg( p_filter, "set default crop %d,%d %dx%d",p_sys->i_crop_x_offset,
1215 p_sys->i_crop_y_offset,
1216 p_sys->i_crop_width,
1217 p_sys->i_crop_height );
1220 #if defined(__ATMO_DEBUG__)
1221 /* save debug images to a folder as Bitmap files ? */
1222 p_sys->b_saveframes = var_CreateGetBoolCommand( p_filter,
1223 CFG_PREFIX "saveframes"
1225 msg_Dbg(p_filter,"saveframes = %d", (int)p_sys->b_saveframes);
1228 read debug image folder from config
1230 psz_path = var_CreateGetStringCommand( p_filter, CFG_PREFIX "framepath" );
1231 if(psz_path != NULL)
1233 strcpy(p_sys->sz_framepath, psz_path);
1234 #if defined( WIN32 )
1235 size_t i_strlen = strlen(p_sys->sz_framepath);
1236 if((i_strlen>0) && (p_sys->sz_framepath[i_strlen-1] != '\\'))
1238 p_sys->sz_framepath[i_strlen] = '\\';
1239 p_sys->sz_framepath[i_strlen+1] = 0;
1244 msg_Dbg(p_filter,"saveframesfolder %s",p_sys->sz_framepath);
1248 size of extracted image by default 64x48 (other imagesizes are
1249 currently ignored by AtmoWin)
1251 p_sys->i_atmo_width = var_CreateGetIntegerCommand( p_filter,
1252 CFG_PREFIX "width");
1253 p_sys->i_atmo_height = var_CreateGetIntegerCommand( p_filter,
1254 CFG_PREFIX "height");
1255 msg_Dbg(p_filter,"mini image size %d * %d pixels", p_sys->i_atmo_width,
1256 p_sys->i_atmo_height);
1259 because atmowin could also be used for lighten up the room - I think if you
1260 pause the video it would be useful to get a little bit more light into to
1261 your living room? - instead switching on a lamp?
1263 p_sys->b_usepausecolor = var_CreateGetBoolCommand( p_filter,
1264 CFG_PREFIX "usepausecolor" );
1265 p_sys->ui_pausecolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1266 CFG_PREFIX "pcolor-red");
1267 p_sys->ui_pausecolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1268 CFG_PREFIX "pcolor-green");
1269 p_sys->ui_pausecolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1270 CFG_PREFIX "pcolor-blue");
1271 p_sys->i_fadesteps = var_CreateGetIntegerCommand( p_filter,
1272 CFG_PREFIX "fadesteps");
1273 if(p_sys->i_fadesteps < 1)
1274 p_sys->i_fadesteps = 1;
1275 msg_Dbg(p_filter,"use pause color %d, RGB: %d, %d, %d, Fadesteps: %d",
1276 (int)p_sys->b_usepausecolor,
1277 p_sys->ui_pausecolor_red,
1278 p_sys->ui_pausecolor_green,
1279 p_sys->ui_pausecolor_blue,
1280 p_sys->i_fadesteps);
1283 this color is use on shutdown of the filter - the define the
1284 final light after playback... may be used to dim up the light -
1285 how it happens in the cinema...
1287 p_sys->ui_endcolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1288 CFG_PREFIX "ecolor-red");
1289 p_sys->ui_endcolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1290 CFG_PREFIX "ecolor-green");
1291 p_sys->ui_endcolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1292 CFG_PREFIX "ecolor-blue");
1293 p_sys->i_endfadesteps = var_CreateGetIntegerCommand( p_filter,
1294 CFG_PREFIX "efadesteps");
1295 if(p_sys->i_endfadesteps < 1)
1296 p_sys->i_endfadesteps = 1;
1297 msg_Dbg(p_filter,"use ende color RGB: %d, %d, %d, Fadesteps: %d",
1298 p_sys->ui_endcolor_red,
1299 p_sys->ui_endcolor_green,
1300 p_sys->ui_endcolor_blue,
1301 p_sys->i_endfadesteps);
1303 /* if the external DLL was loaded successfully call AtmoInitialize -
1304 (must be done for each thread where you wan't to use AtmoLight!
1306 int i = AtmoInitialize(p_filter, false);
1307 #if defined( WIN32 )
1308 if((i != 1) && !b_use_buildin_driver)
1310 /* COM Server for AtmoLight not running ?
1311 if the exe path is configured try to start the "userspace" driver
1313 psz_path = var_CreateGetStringCommand( p_filter,
1314 CFG_PREFIX "atmowinexe" );
1315 if(psz_path != NULL)
1317 STARTUPINFO startupinfo;
1318 PROCESS_INFORMATION pinfo;
1319 memset(&startupinfo, 0, sizeof(STARTUPINFO));
1320 startupinfo.cb = sizeof(STARTUPINFO);
1321 if(CreateProcess(psz_path, NULL, NULL, NULL,
1322 FALSE, 0, NULL, NULL, &startupinfo, &pinfo) == TRUE)
1324 msg_Dbg(p_filter,"launched AtmoWin from %s",psz_path);
1325 WaitForInputIdle(pinfo.hProcess, 5000);
1327 retry to initialize the library COM ... functionality
1328 after the server was launched
1330 i = AtmoInitialize(p_filter, false);
1332 msg_Err(p_filter,"failed to launch AtmoWin from %s", psz_path);
1339 if(i == 1) /* Init Atmolight success... */
1341 msg_Dbg( p_filter, "AtmoInitialize Ok!");
1343 /* Setup Transferbuffers for 64 x 48 , RGB with 32bit Per Pixel */
1344 AtmoCreateTransferBuffers(p_filter, BI_RGB, 4,
1345 p_sys->i_atmo_width,
1346 p_sys->i_atmo_height
1349 /* say the userspace driver that a live mode should be activated
1350 the functions returns the old mode for later restore!
1352 p_sys->i_AtmoOldEffect = AtmoSwitchEffect(p_filter, emLivePicture);
1355 live view can have two differnt source the AtmoWinA
1356 internal GDI Screencapture and the external one - which we
1359 AtmoSetLiveSource(p_filter, lvsExternal);
1361 /* enable other parts only if everything is fine */
1362 p_sys->b_enabled = true;
1368 /*****************************************************************************
1369 * CreateFilter: allocates AtmoLight video thread output method
1370 *****************************************************************************
1371 * This function allocates and initializes a AtmoLight vout method.
1372 *****************************************************************************/
1373 static int CreateFilter( vlc_object_t *p_this )
1375 filter_t *p_filter = (filter_t *)p_this;
1376 filter_sys_t *p_sys;
1378 /* Allocate structure */
1379 p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) );
1380 p_filter->p_sys = p_sys;
1381 if( p_filter->p_sys == NULL )
1383 /* set all entries to zero */
1384 memset(p_sys, 0, sizeof( filter_sys_t ));
1386 /* further Setup Function pointers for videolan for calling my filter */
1387 p_filter->pf_video_filter = Filter;
1389 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
1392 AddStateVariableCallback(p_filter);
1394 AddCropVariableCallback(p_filter);
1396 AddAtmoSettingsVariablesCallbacks(p_filter);
1398 Atmo_SetupParameters(p_filter);
1406 /*****************************************************************************
1407 * DestroyFilter: destroy AtmoLight video thread output method
1408 *****************************************************************************
1409 * Terminate an output method created by CreateFilter
1410 *****************************************************************************/
1412 static void DestroyFilter( vlc_object_t *p_this )
1414 filter_t *p_filter = (filter_t *)p_this;
1415 filter_sys_t *p_sys = p_filter->p_sys;
1417 DelStateVariableCallback(p_filter);
1418 DelCropVariableCallback(p_filter);
1419 DelAtmoSettingsVariablesCallbacks(p_filter);
1421 Atmo_Shutdown(p_filter);
1423 #if defined( WIN32 )
1424 if(p_sys->h_AtmoCtrl != NULL)
1426 FreeLibrary(p_sys->h_AtmoCtrl);
1430 delete p_sys->p_atmo_dyndata;
1431 delete p_sys->p_atmo_config;
1433 vlc_mutex_destroy( &p_sys->filter_lock );
1440 function stolen from some other videolan source filter ;-)
1441 for the moment RGB is OK... but better would be a direct transformation
1444 static inline void yuv_to_rgb( uint8_t *r, uint8_t *g, uint8_t *b,
1445 uint8_t y1, uint8_t u1, uint8_t v1 )
1447 /* macros used for YUV pixel conversions */
1448 # define SCALEBITS 10
1449 # define ONE_HALF (1 << (SCALEBITS - 1))
1450 # define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
1451 # define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
1453 int y, cb, cr, r_add, g_add, b_add;
1457 r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;
1458 g_add = - FIX(0.34414*255.0/224.0) * cb
1459 - FIX(0.71414*255.0/224.0) * cr + ONE_HALF;
1460 b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;
1461 y = (y1 - 16) * FIX(255.0/219.0);
1462 *r = CLAMP((y + r_add) >> SCALEBITS);
1463 *g = CLAMP((y + g_add) >> SCALEBITS);
1464 *b = CLAMP((y + b_add) >> SCALEBITS);
1466 /******************************************************************************
1467 * ExtractMiniImage_YUV: extract a small image from the picture as 24-bit RGB
1468 *******************************************************************************
1469 * p_sys is a pointer to
1470 * p_inpic is the source frame
1471 * p_transfer_dest is the target buffer for the picture must be big enough!
1472 * (in win32 enviroment this buffer comes from the external DLL where it is
1473 * create as "variant array" and returned through the AtmoLockTransferbuffer
1475 static void ExtractMiniImage_YUV(filter_sys_t *p_sys,
1477 uint8_t *p_transfer_dest)
1484 uint8_t *p_rgb_dst_line_red;
1485 uint8_t *p_rgb_dst_line_green;
1486 uint8_t *p_rgb_dst_line_blue;
1491 /* calcute Pointers for Storage of B G R (A) */
1492 p_rgb_dst_line_blue = p_transfer_dest;
1493 p_rgb_dst_line_green = p_transfer_dest + 1;
1494 p_rgb_dst_line_red = p_transfer_dest + 2 ;
1496 int i_row_count = p_sys->i_atmo_height + 1;
1497 int i_col_count = p_sys->i_atmo_width + 1;
1498 int i_y_row,i_u_row,i_v_row,i_pixel_row;
1502 /* these two ugly loops extract the small image - goes it faster? how?
1503 the loops are so designed that there is a small border around the extracted
1504 image so we wont get column and row - zero from the frame, and not the most
1505 right and bottom pixels --- which may be clipped on computers useing TV out
1508 TODO: try to find out if the output is clipped through VLC - and try here
1509 to ingore the clipped away area for a better result!
1511 TODO: performance improvement in InitFilter percalculated the offsets of
1512 the lines inside the planes so I can save (i_row_count * 3) 2xMUL and
1513 one time DIV the same could be done for the inner loop I think...
1515 for(i_row = 1; i_row < i_row_count; i_row++)
1517 // calcute the current Lines in the source planes for this outputrow
1518 /* Adresscalcuation pointer to plane Length of one pixelrow in bytes
1519 calculate row now number
1522 p_inpic->format? transform Pixel row into row of plane...
1523 how? simple? fast? good?
1526 /* compute the source pixel row and respect the active cropping */
1527 i_pixel_row = (i_row * p_sys->i_crop_height) / i_row_count
1528 + p_sys->i_crop_y_offset;
1531 trans for these Pixel row into the row of each plane ..
1532 because planesize can differ from image size
1534 i_y_row = (i_pixel_row * p_inpic->p[Y_PLANE].i_visible_lines) /
1535 p_inpic->format.i_visible_height;
1537 i_u_row = (i_pixel_row * p_inpic->p[U_PLANE].i_visible_lines) /
1538 p_inpic->format.i_visible_height;
1540 i_v_row = (i_pixel_row * p_inpic->p[V_PLANE].i_visible_lines) /
1541 p_inpic->format.i_visible_height;
1543 /* calculate the pointers to the pixeldata for this row
1546 p_src_y = p_inpic->p[Y_PLANE].p_pixels +
1547 p_inpic->p[Y_PLANE].i_pitch * i_y_row;
1548 p_src_u = p_inpic->p[U_PLANE].p_pixels +
1549 p_inpic->p[U_PLANE].i_pitch * i_u_row;
1550 p_src_v = p_inpic->p[V_PLANE].p_pixels +
1551 p_inpic->p[V_PLANE].i_pitch * i_v_row;
1553 for(i_col = 1; i_col < i_col_count; i_col++)
1555 i_pixel_col = (i_col * p_sys->i_crop_width) / i_col_count +
1556 p_sys->i_crop_x_offset;
1558 trans for these Pixel row into the row of each plane ..
1559 because planesize can differ from image size
1561 i_xpos_y = (i_pixel_col * p_inpic->p[Y_PLANE].i_visible_pitch) /
1562 p_inpic->format.i_visible_width;
1563 i_xpos_u = (i_pixel_col * p_inpic->p[U_PLANE].i_visible_pitch) /
1564 p_inpic->format.i_visible_width;
1565 i_xpos_v = (i_pixel_col * p_inpic->p[V_PLANE].i_visible_pitch) /
1566 p_inpic->format.i_visible_width;
1568 yuv_to_rgb(p_rgb_dst_line_red,
1569 p_rgb_dst_line_green,
1570 p_rgb_dst_line_blue,
1576 /* +4 because output image should be RGB32 with dword alignment! */
1577 p_rgb_dst_line_red += 4;
1578 p_rgb_dst_line_green += 4;
1579 p_rgb_dst_line_blue += 4;
1585 /******************************************************************************
1586 * SaveBitmap: Saves the content of a transferbuffer as Bitmap to disk
1587 *******************************************************************************
1588 * just for debugging
1589 * p_sys -> configuration if Atmo from there the function will get height and
1591 * p_pixels -> should be the dword aligned BGR(A) image data
1592 * psz_filename -> filename where to store
1594 #if defined(__ATMO_DEBUG__)
1595 void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename)
1597 /* for debug out only used*/
1598 BITMAPINFO bmp_info;
1599 BITMAPFILEHEADER bmp_fileheader;
1602 memset(&bmp_info, 0, sizeof(BITMAPINFO));
1603 bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1604 bmp_info.bmiHeader.biSizeImage = p_sys->i_atmo_height *
1605 p_sys->i_atmo_width * 4;
1606 bmp_info.bmiHeader.biCompression = BI_RGB;
1607 bmp_info.bmiHeader.biWidth = p_sys->i_atmo_width;
1608 bmp_info.bmiHeader.biHeight = -p_sys->i_atmo_height;
1609 bmp_info.bmiHeader.biBitCount = 32;
1610 bmp_info.bmiHeader.biPlanes = 1;
1612 bmp_fileheader.bfReserved1 = 0;
1613 bmp_fileheader.bfReserved2 = 0;
1614 bmp_fileheader.bfSize = sizeof(BITMAPFILEHEADER) +
1615 sizeof(BITMAPINFOHEADER) +
1616 bmp_info.bmiHeader.biSizeImage;
1617 bmp_fileheader.bfType = VLC_TWOCC('M','B');
1618 bmp_fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) +
1619 sizeof(BITMAPINFOHEADER);
1621 fp_bitmap = fopen(psz_filename,"wb");
1622 if( fp_bitmap != NULL)
1624 fwrite(&bmp_fileheader, sizeof(BITMAPFILEHEADER), 1, fp_bitmap);
1625 fwrite(&bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp_bitmap);
1626 fwrite(p_pixels, bmp_info.bmiHeader.biSizeImage, 1, fp_bitmap);
1633 /****************************************************************************
1634 * CreateMiniImage: extracts a 64x48 pixel image from the frame
1635 * (there is a small border arround thats why the loops starts with one
1636 * instead zero) without any interpolation
1637 *****************************************************************************/
1638 static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic)
1640 filter_sys_t *p_sys = p_filter->p_sys;
1642 pointer to RGB Buffer created in external libary as safe array which
1643 is locked inside AtmoLockTransferBuffer
1645 uint8_t *p_transfer = NULL;
1646 #if defined( __ATMO_DEBUG__ )
1647 /* for debug out only used*/
1648 char sz_filename[MAX_PATH];
1652 Lock the before created VarArray (AtmoCreateTransferBuffers)
1653 inside my wrapper library and give me a pointer to the buffer!
1654 below linux a global buffer may be used and protected with a mutex?
1656 p_transfer = AtmoLockTransferBuffer(p_filter);
1657 if(p_transfer == NULL)
1659 msg_Err( p_filter, "AtmoLight no transferbuffer available. "\
1660 "AtmoLight will be disabled!");
1661 p_sys->b_enabled = false;
1666 do the call via pointer to function instead of having a
1669 p_sys->pf_extract_mini_image(p_sys, p_inpic, p_transfer);
1672 #if defined( __ATMO_DEBUG__ )
1674 if debugging enabled save every 128th image to disk
1676 if((p_sys->b_saveframes == true) && (p_sys->sz_framepath[0] != 0 ))
1679 if((p_sys->i_framecounter & 127) == 0)
1681 sprintf(sz_filename,"%satmo_dbg_%06d.bmp",p_sys->sz_framepath,
1682 p_sys->i_framecounter);
1683 msg_Dbg(p_filter, "SaveFrame %s",sz_filename);
1685 SaveBitmap(p_sys, p_transfer, sz_filename);
1687 p_sys->i_framecounter++;
1691 /* show the colors on the wall */
1692 AtmoSendPixelData(p_filter);
1698 /*****************************************************************************
1699 * Filter: calls the extract method and forwards the incomming picture 1:1
1700 *****************************************************************************
1702 *****************************************************************************/
1704 static picture_t * Filter( filter_t *p_filter, picture_t *p_pic )
1706 filter_sys_t *p_sys = p_filter->p_sys;
1707 if( !p_pic ) return NULL;
1709 if((p_sys->b_enabled == true) &&
1710 (p_sys->pf_extract_mini_image != NULL) &&
1711 (p_sys->b_pause_live == false))
1713 CreateMiniImage(p_filter, p_pic);
1720 /*****************************************************************************
1721 * FadeToColorThread: Threadmethod which changes slowly the color
1722 * to a target color defined in p_fadethread struct
1723 * use for: Fade to Pause Color, and Fade to End Color
1724 *****************************************************************************/
1725 static void *FadeToColorThread(vlc_object_t *obj)
1727 fadethread_t *p_fadethread = (fadethread_t *)obj;
1728 filter_sys_t *p_sys = (filter_sys_t *)p_fadethread->p_filter->p_sys;
1729 int i_steps_done = 0;
1739 uint8_t *p_source = NULL;
1741 int canc = vlc_savecancel ();
1742 /* initialize AtmoWin for this thread! */
1743 AtmoInitialize(p_fadethread->p_filter , true);
1745 uint8_t *p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
1746 if(p_transfer != NULL) {
1747 /* safe colors as "32bit" Integers to avoid overflows*/
1748 i_pause_red = p_fadethread->ui_red;
1749 i_pause_blue = p_fadethread->ui_blue;
1750 i_pause_green = p_fadethread->ui_green;
1753 allocate a temporary buffer for the last send
1754 image size less then 15kb
1756 int i_size = 4 * p_sys->i_atmo_width * p_sys->i_atmo_height;
1757 p_source = (uint8_t *)malloc( i_size );
1758 if(p_source != NULL)
1761 get a copy of the last transfered image as orign for the
1764 memcpy(p_source, p_transfer, i_size);
1765 /* send the same pixel data again... to unlock the buffer! */
1766 AtmoSendPixelData( p_fadethread->p_filter );
1768 while( (vlc_object_alive (p_fadethread)) &&
1769 (i_steps_done < p_fadethread->i_steps))
1771 p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
1772 if(!p_transfer) break; /* should not happen if it worked
1773 one time in the code above! */
1776 move all pixels in the mini image (64x48) one step closer to
1777 the desired color these loop takes the most time of this
1778 thread improvements wellcome!
1781 (i_index < i_size) && (vlc_object_alive (p_fadethread));
1784 i_src_blue = p_source[i_index+0];
1785 i_src_green = p_source[i_index+1];
1786 i_src_red = p_source[i_index+2];
1787 p_transfer[i_index+0] = (uint8_t) (((
1788 (i_pause_blue - i_src_blue)
1789 * i_steps_done)/p_fadethread->i_steps)
1792 p_transfer[i_index+1] = (uint8_t) (((
1793 (i_pause_green - i_src_green)
1794 * i_steps_done)/p_fadethread->i_steps)
1797 p_transfer[i_index+2] = (uint8_t) (((
1798 (i_pause_red - i_src_red)
1799 * i_steps_done)/p_fadethread->i_steps)
1803 /* send image to lightcontroller */
1804 AtmoSendPixelData( p_fadethread->p_filter );
1805 /* is there something like and interruptable sleep inside
1806 the VLC libaries? inside native win32 I would use an Event
1807 (CreateEvent) and here an WaitForSingleObject?
1809 if(!vlc_object_alive (p_fadethread)) break;
1811 if(!vlc_object_alive (p_fadethread)) break;
1813 if(!vlc_object_alive (p_fadethread)) break;
1815 if(!vlc_object_alive (p_fadethread)) break;
1820 /* in failure of malloc also unlock buffer */
1821 AtmoSendPixelData(p_fadethread->p_filter);
1824 /* call indirect to OleUnitialize() for this thread */
1825 AtmoFinalize(p_fadethread->p_filter, 0);
1826 vlc_restorecancel (canc);
1830 /*****************************************************************************
1831 * CheckAndStopFadeThread: if there is a fadethread structure left, or running.
1832 ******************************************************************************
1833 * this function will stop the thread ... and waits for its termination
1834 * before removeing the objects from vout_sys_t ...
1835 ******************************************************************************/
1836 static void CheckAndStopFadeThread(filter_t *p_filter)
1838 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1839 vlc_mutex_lock( &p_sys->filter_lock );
1840 if(p_sys->p_fadethread != NULL)
1842 msg_Dbg(p_filter, "kill still running fadeing thread...");
1844 p_sys->p_fadethread->b_die = true;
1846 vlc_thread_join(p_sys->p_fadethread);
1848 vlc_object_release(p_sys->p_fadethread);
1849 p_sys->p_fadethread = NULL;
1851 vlc_mutex_unlock( &p_sys->filter_lock );
1854 /*****************************************************************************
1855 * StateCallback: Callback for the inputs variable "State" to get notified
1856 * about Pause and Continue Playback events.
1857 *****************************************************************************/
1858 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
1859 vlc_value_t oldval, vlc_value_t newval,
1862 filter_t *p_filter = (filter_t *)p_data;
1863 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1865 if((p_sys->b_usepausecolor == true) && (p_sys->b_enabled == true))
1867 msg_Dbg(p_filter, "state change from: %d to %d", oldval.i_int,
1870 if((newval.i_int == PAUSE_S) && (oldval.i_int == PLAYING_S))
1872 /* tell the other thread to stop sending images to light
1874 p_sys->b_pause_live = true;
1876 // ggf. alten Thread abräumen should not happen....
1877 CheckAndStopFadeThread(p_filter);
1879 // perpare spawn fadeing thread
1880 vlc_mutex_lock( &p_sys->filter_lock );
1882 launch only a new thread if there is none active!
1883 or waiting for cleanup
1885 if(p_sys->p_fadethread == NULL)
1887 p_sys->p_fadethread = (fadethread_t *)vlc_object_create(
1889 sizeof(fadethread_t) );
1891 p_sys->p_fadethread->p_filter = p_filter;
1892 p_sys->p_fadethread->ui_red = p_sys->ui_pausecolor_red;
1893 p_sys->p_fadethread->ui_green = p_sys->ui_pausecolor_green;
1894 p_sys->p_fadethread->ui_blue = p_sys->ui_pausecolor_blue;
1895 p_sys->p_fadethread->i_steps = p_sys->i_fadesteps;
1897 if( vlc_thread_create( p_sys->p_fadethread,
1898 "AtmoLight fadeing",
1900 VLC_THREAD_PRIORITY_LOW ) )
1902 msg_Err( p_filter, "cannot create FadeToColorThread" );
1903 vlc_object_release( p_sys->p_fadethread );
1904 p_sys->p_fadethread = NULL;
1907 vlc_mutex_unlock( &p_sys->filter_lock );
1910 if((newval.i_int == PLAYING_S) && (oldval.i_int == PAUSE_S))
1912 /* playback continues check thread state */
1913 CheckAndStopFadeThread(p_filter);
1914 /* reactivate the Render function... to do its normal work */
1915 p_sys->b_pause_live = false;
1922 /*****************************************************************************
1923 * AddPlaylistInputThreadStateCallback: Setup call back on "State" Variable
1924 *****************************************************************************
1925 * Add Callback function to the "state" variable of the input thread..
1926 * first find the PlayList and get the input thread from there to attach
1927 * my callback? is vlc_object_find the right way for this??
1928 *****************************************************************************/
1929 static void AddStateVariableCallback(filter_t *p_filter)
1931 playlist_t *p_playlist = pl_Hold( p_filter );
1932 input_thread_t *p_input = playlist_CurrentInput( p_playlist );
1935 var_AddCallback( p_input, "state", StateCallback, p_filter );
1936 vlc_object_release( p_input );
1938 pl_Release( p_filter );
1941 /*****************************************************************************
1942 * DelPlaylistInputThreadStateCallback: Remove call back on "State" Variable
1943 *****************************************************************************
1944 * Delete the callback function to the "state" variable of the input thread...
1945 * first find the PlayList and get the input thread from there to attach
1946 * my callback? is vlc_object_find the right way for this??
1947 *****************************************************************************/
1948 static void DelStateVariableCallback( filter_t *p_filter )
1950 playlist_t *p_playlist = pl_Hold( p_filter );
1951 input_thread_t *p_input = playlist_CurrentInput( p_playlist );
1954 var_DelCallback( p_input, "state", StateCallback, p_filter );
1955 vlc_object_release( p_input );
1957 pl_Release( p_filter );
1961 static int CropCallback(vlc_object_t *p_this, char const *psz_cmd,
1962 vlc_value_t oldval, vlc_value_t newval,
1965 vout_thread_t *p_vout = (vout_thread_t *)p_this;
1966 filter_t *p_filter = (filter_t *)p_data;
1967 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
1970 //if the handler is attache to crop variable directly!
1971 int i_visible_width, i_visible_height, i_x_offset, i_y_offset;
1972 atmo_parse_crop(newval.psz_string, p_vout->fmt_render,
1974 i_visible_width, i_visible_height,
1975 i_x_offset, i_y_offset);
1976 p_sys->i_crop_x_offset = i_x_offset;
1977 p_sys->i_crop_y_offset = i_y_offset;
1978 p_sys->i_crop_width = i_visible_width;
1979 p_sys->i_crop_height = i_visible_height;
1982 p_sys->i_crop_x_offset = p_vout->fmt_in.i_x_offset;
1983 p_sys->i_crop_y_offset = p_vout->fmt_in.i_y_offset;
1984 p_sys->i_crop_width = p_vout->fmt_in.i_visible_width;
1985 p_sys->i_crop_height = p_vout->fmt_in.i_visible_height;
1987 msg_Dbg(p_filter, "cropping picture %ix%i to %i,%i,%ix%i",
1988 p_vout->fmt_in.i_width,
1989 p_vout->fmt_in.i_height,
1990 p_sys->i_crop_x_offset,
1991 p_sys->i_crop_y_offset,
1992 p_sys->i_crop_width,
1993 p_sys->i_crop_height
2000 static void AddCropVariableCallback( filter_t *p_filter)
2002 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2007 var_AddCallback( p_vout, "crop-update", CropCallback, p_filter );
2008 vlc_object_release( p_vout );
2012 static void DelCropVariableCallback( filter_t *p_filter)
2014 vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find( p_filter,
2019 var_DelCallback( p_vout, "crop-update", CropCallback, p_filter );
2020 vlc_object_release( p_vout );
2025 /****************************************************************************
2026 * StateCallback: Callback for the inputs variable "State" to get notified
2027 * about Pause and Continue Playback events.
2028 *****************************************************************************/
2029 static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
2030 vlc_value_t oldval, vlc_value_t newval,
2033 filter_t *p_filter = (filter_t *)p_data;
2034 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
2036 CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
2040 msg_Dbg(p_filter, "apply AtmoSettingsCallback %s (int: %d -> %d)",
2046 if( !strcmp( psz_var, CFG_PREFIX "filtermode" ))
2047 p_atmo_config->setLiveViewFilterMode( (AtmoFilterMode)newval.i_int);
2049 else if( !strcmp( psz_var, CFG_PREFIX "PercentNew" ))
2050 p_atmo_config->setLiveViewFilter_PercentNew( newval.i_int );
2052 else if( !strcmp( psz_var, CFG_PREFIX "MeanLength" ))
2053 p_atmo_config->setLiveViewFilter_MeanLength( newval.i_int );
2055 else if( !strcmp( psz_var, CFG_PREFIX "MeanThreshold" ))
2056 p_atmo_config->setLiveViewFilter_MeanThreshold( newval.i_int );
2058 else if( !strcmp( psz_var, CFG_PREFIX "EdgeWeightning" ))
2059 p_atmo_config->setLiveView_EdgeWeighting( newval.i_int );
2061 else if( !strcmp( psz_var, CFG_PREFIX "Brightness" ))
2062 p_atmo_config->setLiveView_BrightCorrect( newval.i_int );
2064 else if( !strcmp( psz_var, CFG_PREFIX "DarknessLimit" ))
2065 p_atmo_config->setLiveView_DarknessLimit( newval.i_int );
2067 else if( !strcmp( psz_var, CFG_PREFIX "HueWinSize" ))
2068 p_atmo_config->setLiveView_HueWinSize( newval.i_int );
2070 else if( !strcmp( psz_var, CFG_PREFIX "SatWinSize" ))
2071 p_atmo_config->setLiveView_SatWinSize( newval.i_int );
2073 else if( !strcmp( psz_var, CFG_PREFIX "FrameDelay" ))
2074 p_atmo_config->setLiveView_FrameDelay( newval.i_int );
2076 else if( !strcmp( psz_var, CFG_PREFIX "whiteadj" ))
2077 p_atmo_config->setUseSoftwareWhiteAdj( newval.b_bool );
2079 else if( !strcmp( psz_var, CFG_PREFIX "white-red" ))
2080 p_atmo_config->setWhiteAdjustment_Red( newval.i_int );
2082 else if( !strcmp( psz_var, CFG_PREFIX "white-green" ))
2083 p_atmo_config->setWhiteAdjustment_Green( newval.i_int );
2085 else if( !strcmp( psz_var, CFG_PREFIX "white-blue" ))
2086 p_atmo_config->setWhiteAdjustment_Blue( newval.i_int );
2092 static void AddAtmoSettingsVariablesCallbacks(filter_t *p_filter)
2094 var_AddCallback( p_filter, CFG_PREFIX "filtermode",
2095 AtmoSettingsCallback, p_filter );
2096 var_AddCallback( p_filter, CFG_PREFIX "PercentNew",
2097 AtmoSettingsCallback, p_filter );
2100 var_AddCallback( p_filter, CFG_PREFIX "MeanLength",
2101 AtmoSettingsCallback, p_filter );
2102 var_AddCallback( p_filter, CFG_PREFIX "MeanThreshold",
2103 AtmoSettingsCallback, p_filter );
2105 var_AddCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2106 AtmoSettingsCallback, p_filter );
2107 var_AddCallback( p_filter, CFG_PREFIX "Brightness",
2108 AtmoSettingsCallback, p_filter );
2109 var_AddCallback( p_filter, CFG_PREFIX "DarknessLimit",
2110 AtmoSettingsCallback, p_filter );
2112 var_AddCallback( p_filter, CFG_PREFIX "HueWinSize",
2113 AtmoSettingsCallback, p_filter );
2114 var_AddCallback( p_filter, CFG_PREFIX "SatWinSize",
2115 AtmoSettingsCallback, p_filter );
2116 var_AddCallback( p_filter, CFG_PREFIX "FrameDelay",
2117 AtmoSettingsCallback, p_filter );
2120 var_AddCallback( p_filter, CFG_PREFIX "whiteadj",
2121 AtmoSettingsCallback, p_filter );
2122 var_AddCallback( p_filter, CFG_PREFIX "white-red",
2123 AtmoSettingsCallback, p_filter );
2124 var_AddCallback( p_filter, CFG_PREFIX "white-green",
2125 AtmoSettingsCallback, p_filter );
2126 var_AddCallback( p_filter, CFG_PREFIX "white-blue",
2127 AtmoSettingsCallback, p_filter );
2130 static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
2133 var_DelCallback( p_filter, CFG_PREFIX "filtermode",
2134 AtmoSettingsCallback, p_filter );
2136 var_DelCallback( p_filter, CFG_PREFIX "PercentNew",
2137 AtmoSettingsCallback, p_filter );
2138 var_DelCallback( p_filter, CFG_PREFIX "MeanLength",
2139 AtmoSettingsCallback, p_filter );
2140 var_DelCallback( p_filter, CFG_PREFIX "MeanThreshold",
2141 AtmoSettingsCallback, p_filter );
2143 var_DelCallback( p_filter, CFG_PREFIX "EdgeWeightning",
2144 AtmoSettingsCallback, p_filter );
2145 var_DelCallback( p_filter, CFG_PREFIX "Brightness",
2146 AtmoSettingsCallback, p_filter );
2147 var_DelCallback( p_filter, CFG_PREFIX "DarknessLimit",
2148 AtmoSettingsCallback, p_filter );
2150 var_DelCallback( p_filter, CFG_PREFIX "HueWinSize",
2151 AtmoSettingsCallback, p_filter );
2152 var_DelCallback( p_filter, CFG_PREFIX "SatWinSize",
2153 AtmoSettingsCallback, p_filter );
2154 var_DelCallback( p_filter, CFG_PREFIX "FrameDelay",
2155 AtmoSettingsCallback, p_filter );
2158 var_DelCallback( p_filter, CFG_PREFIX "whiteadj",
2159 AtmoSettingsCallback, p_filter );
2160 var_DelCallback( p_filter, CFG_PREFIX "white-red",
2161 AtmoSettingsCallback, p_filter );
2162 var_DelCallback( p_filter, CFG_PREFIX "white-green",
2163 AtmoSettingsCallback, p_filter );
2164 var_DelCallback( p_filter, CFG_PREFIX "white-blue",
2165 AtmoSettingsCallback, p_filter );
2170 #if defined(__ATMO_DEBUG__)
2171 static void atmo_parse_crop(char *psz_cropconfig,
2172 video_format_t fmt_in,
2173 video_format_t fmt_render,
2174 int &i_visible_width, int &i_visible_height,
2175 int &i_x_offset, int &i_y_offset )
2177 int64_t i_aspect_num, i_aspect_den;
2178 unsigned int i_width, i_height;
2180 i_visible_width = fmt_in.i_visible_width;
2181 i_visible_height = fmt_in.i_visible_height;
2182 i_x_offset = fmt_in.i_x_offset;
2183 i_y_offset = fmt_in.i_y_offset;
2185 char *psz_end = NULL, *psz_parser = strchr( psz_cropconfig, ':' );
2188 /* We're using the 3:4 syntax */
2189 i_aspect_num = strtol( psz_cropconfig, &psz_end, 10 );
2190 if( psz_end == psz_cropconfig || !i_aspect_num ) return;
2192 i_aspect_den = strtol( ++psz_parser, &psz_end, 10 );
2193 if( psz_end == psz_parser || !i_aspect_den ) return;
2195 i_width = fmt_in.i_sar_den * fmt_render.i_visible_height *
2196 i_aspect_num / i_aspect_den / fmt_in.i_sar_num;
2198 i_height = fmt_render.i_visible_width*fmt_in.i_sar_num *
2199 i_aspect_den / i_aspect_num / fmt_in.i_sar_den;
2201 if( i_width < fmt_render.i_visible_width )
2203 i_x_offset = fmt_render.i_x_offset +
2204 (fmt_render.i_visible_width - i_width) / 2;
2205 i_visible_width = i_width;
2209 i_y_offset = fmt_render.i_y_offset +
2210 (fmt_render.i_visible_height - i_height) / 2;
2211 i_visible_height = i_height;
2216 psz_parser = strchr( psz_cropconfig, 'x' );
2219 /* Maybe we're using the <width>x<height>+<left>+<top> syntax */
2220 unsigned int i_crop_width, i_crop_height, i_crop_top, i_crop_left;
2222 i_crop_width = strtol( psz_cropconfig, &psz_end, 10 );
2223 if( psz_end != psz_parser ) return;
2225 psz_parser = strchr( ++psz_end, '+' );
2226 i_crop_height = strtol( psz_end, &psz_end, 10 );
2227 if( psz_end != psz_parser ) return;
2229 psz_parser = strchr( ++psz_end, '+' );
2230 i_crop_left = strtol( psz_end, &psz_end, 10 );
2231 if( psz_end != psz_parser ) return;
2234 i_crop_top = strtol( psz_end, &psz_end, 10 );
2235 if( *psz_end != '\0' ) return;
2237 i_width = i_crop_width;
2238 i_visible_width = i_width;
2240 i_height = i_crop_height;
2241 i_visible_height = i_height;
2243 i_x_offset = i_crop_left;
2244 i_y_offset = i_crop_top;
2248 /* Maybe we're using the <left>+<top>+<right>+<bottom> syntax */
2249 unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right;
2251 psz_parser = strchr( psz_cropconfig, '+' );
2252 i_crop_left = strtol( psz_cropconfig, &psz_end, 10 );
2253 if( psz_end != psz_parser ) return;
2255 psz_parser = strchr( ++psz_end, '+' );
2256 i_crop_top = strtol( psz_end, &psz_end, 10 );
2257 if( psz_end != psz_parser ) return;
2259 psz_parser = strchr( ++psz_end, '+' );
2260 i_crop_right = strtol( psz_end, &psz_end, 10 );
2261 if( psz_end != psz_parser ) return;
2264 i_crop_bottom = strtol( psz_end, &psz_end, 10 );
2265 if( *psz_end != '\0' ) return;
2267 i_width = fmt_render.i_visible_width - i_crop_left - i_crop_right;
2268 i_visible_width = i_width;
2270 i_height = fmt_render.i_visible_height - i_crop_top - i_crop_bottom;
2271 i_visible_height = i_height;
2273 i_x_offset = i_crop_left;
2274 i_y_offset = i_crop_top;