add_integer: remove callback parameter
[vlc/asuraparaju-public.git] / modules / video_filter / atmo / atmo.cpp
blob1f2d6e481635de20a9de859cbc1146de316448cb
1 /*****************************************************************************
2 * atmo.cpp : "Atmo Light" video filter
3 *****************************************************************************
4 * Copyright (C) 2000-2006 the VideoLAN team
5 * $Id$
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 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27 #define __STDC_FORMAT_MACROS 1
28 #include <stdlib.h> /* malloc(), free() */
29 #include <string.h>
30 #include <math.h> /* sin(), cos() */
31 #include <assert.h>
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
37 // #define __ATMO_DEBUG__
39 // [:Zs]+$
40 #include <vlc_common.h>
41 #include <vlc_plugin.h>
42 #include <vlc_vout.h>
44 #include <vlc_playlist.h>
45 #include <vlc_filter.h>
47 #include "AtmoDefs.h"
48 #include "AtmoDynData.h"
49 #include "AtmoLiveView.h"
50 #include "AtmoTools.h"
51 #include "AtmoExternalCaptureInput.h"
52 #include "AtmoConfig.h"
53 #include "AtmoConnection.h"
54 #include "AtmoClassicConnection.h"
57 /*****************************************************************************
58 * Local prototypes
59 *****************************************************************************/
60 /* directly to vlc related functions required that the module is accepted */
61 static int CreateFilter ( vlc_object_t * );
62 static void DestroyFilter ( vlc_object_t * );
63 static picture_t * Filter( filter_t *, picture_t *);
65 /* callback for global variable state pause / continue / stop events */
66 static void AddStateVariableCallback( filter_t *);
67 static void DelStateVariableCallback( filter_t *);
68 static int StateCallback(vlc_object_t *, char const *,
69 vlc_value_t, vlc_value_t, void *);
71 /* callback for atmo settings variables whose change
72 should be immediately realized and applied to output
74 static void DelAtmoSettingsVariablesCallbacks(filter_t *);
75 static void AddAtmoSettingsVariablesCallbacks(filter_t *);
76 static int AtmoSettingsCallback(vlc_object_t *, char const *,
77 vlc_value_t, vlc_value_t, void *);
80 #if defined(__ATMO_DEBUG__)
81 static void atmo_parse_crop(char *psz_cropconfig,
82 video_format_t fmt_in,
83 video_format_t fmt_render,
84 int &i_visible_width,
85 int &i_visible_height,
86 int &i_x_offset,
87 int &i_y_offset );
88 #endif
91 /* function to shutdown the fade thread which is started on pause*/
92 static void CheckAndStopFadeThread(filter_t *);
94 /* extracts a small RGB (BGR) Image from an YUV image */
95 static void ExtractMiniImage_YUV(filter_sys_t *, picture_t *, uint8_t *);
97 #if defined(__ATMO_DEBUG__)
98 void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename);
99 #endif
101 /*****************************************************************************
102 * External Prototypes for the AtmoCtrlLib.DLL
103 *****************************************************************************/
105 * if effectmode = emLivePicture then the source could be GDI (Screencapture)
106 * or External - this means another application delivers Pixeldata to AtmoWin
107 * Clientsoftware through AtmoCtrlLib.DLL and the COM Api
109 #define lvsGDI 0
110 #define lvsExternal 1
112 #define CLASSIC_ATMO_NUM_ZONES 5
116 strings for settings menus and hints
118 #define MODULE_DESCRIPTION N_ ( \
119 "This module allows to control an so called AtmoLight device "\
120 "connected to your computer.\n"\
121 "AtmoLight is the homegrown version of what Philips calls AmbiLight.\n"\
122 "If you need further information feel free to visit us at\n\n"\
123 "http://www.vdr-wiki.de/wiki/index.php/Atmo-plugin\n"\
124 "http://www.vdr-wiki.de/wiki/index.php/AtmoWin\n\n"\
125 "You can find there detailed descriptions on how to build it for yourself "\
126 "and where to get the required parts.\n" \
127 "You can also have a look at pictures and some movies showing such a device " \
128 "in live action.")
130 #define DRIVER_TEXT N_("Device type")
131 #define DRIVER_LONGTEXT N_("Choose your preferred hardware from " \
132 "the list, or choose AtmoWin Software " \
133 "to delegate processing to the external " \
134 "process - with more options")
136 static const int pi_device_type_values[] = {
137 #if defined( WIN32 )
138 0, /* use AtmoWinA.exe userspace driver */
139 #endif
140 1, /* AtmoLight classic */
141 2, /* Quattro AtmoLight */
142 3, /* DMX Device */
143 4, /* MoMoLight device */
144 5 /* fnordlicht */
146 static const char *const ppsz_device_type_descriptions[] = {
147 #if defined( WIN32 )
148 N_("AtmoWin Software"),
149 #endif
150 N_("Classic AtmoLight"),
151 N_("Quattro AtmoLight"),
152 N_("DMX"),
153 N_("MoMoLight"),
154 N_("fnordlicht")
157 #define DMX_CHANNELS_TEXT N_("Count of AtmoLight channels")
158 #define DMX_CHANNELS_LONGTEXT N_("How many AtmoLight channels, should be " \
159 "emulated with that DMX device")
160 #define DMX_CHBASE_TEXT N_("DMX address for each channel")
161 #define DMX_CHBASE_LONGTEXT N_("Define here the DMX base address for each " \
162 "channel use , or ; to separate the values")
164 #define MOMO_CHANNELS_TEXT N_("Count of channels")
165 #define MOMO_CHANNELS_LONGTEXT N_("Depending on your MoMoLight hardware " \
166 "choose 3 or 4 channels")
168 #define FNORDLICHT_AMOUNT_TEXT N_("Count of fnordlicht's")
169 #define FNORDLICHT_AMOUNT_LONGTEXT N_("Depending on the amount your " \
170 "fnordlicht hardware " \
171 "choose 1 to 4 channels")
173 #if defined( WIN32 )
174 # define DEFAULT_DEVICE 0
175 #else
176 # define DEFAULT_DEVICE 1
177 #endif
179 #if defined( __ATMO_DEBUG__ )
180 # define SAVEFRAMES_TEXT N_("Save Debug Frames")
181 # define SAVEFRAMES_LONGTEXT N_("Write every 128th miniframe to a folder.")
182 # define FRAMEPATH_TEXT N_("Debug Frame Folder")
183 # define FRAMEPATH_LONGTEXT N_("The path where the debugframes " \
184 "should be saved")
185 #endif
187 #define WIDTH_TEXT N_("Extracted Image Width")
188 #define WIDTH_LONGTEXT N_("The width of the mini image for " \
189 "further processing (64 is default)")
191 #define HEIGHT_TEXT N_("Extracted Image Height")
192 #define HEIGHT_LONGTEXT N_("The height of the mini image for " \
193 "further processing (48 is default)")
195 #define SHOW_DOTS_TEXT N_("Mark analyzed pixels")
196 #define SHOW_DOTS_LONGTEXT N_("makes the sample grid visible on screen as "\
197 "white pixels")
199 #define PCOLOR_TEXT N_("Color when paused")
200 #define PCOLOR_LONGTEXT N_("Set the color to show if the user " \
201 "pauses the video. (Have light to get " \
202 "another beer?)")
203 #define PCOLOR_RED_TEXT N_("Pause-Red")
204 #define PCOLOR_RED_LONGTEXT N_("Red component of the pause color")
205 #define PCOLOR_GREEN_TEXT N_("Pause-Green")
206 #define PCOLOR_GREEN_LONGTEXT N_("Green component of the pause color")
207 #define PCOLOR_BLUE_TEXT N_("Pause-Blue")
208 #define PCOLOR_BLUE_LONGTEXT N_("Blue component of the pause color")
209 #define FADESTEPS_TEXT N_("Pause-Fadesteps")
210 #define FADESTEPS_LONGTEXT N_("Number of steps to change current color " \
211 "to pause color (each step takes 40ms)")
213 #define ECOLOR_RED_TEXT N_("End-Red")
214 #define ECOLOR_RED_LONGTEXT N_("Red component of the shutdown color")
215 #define ECOLOR_GREEN_TEXT N_("End-Green")
216 #define ECOLOR_GREEN_LONGTEXT N_("Green component of the shutdown color")
217 #define ECOLOR_BLUE_TEXT N_("End-Blue")
218 #define ECOLOR_BLUE_LONGTEXT N_("Blue component of the shutdown color")
219 #define EFADESTEPS_TEXT N_("End-Fadesteps")
220 #define EFADESTEPS_LONGTEXT N_("Number of steps to change current color to " \
221 "end color for dimming up the light in cinema " \
222 "style... (each step takes 40ms)")
224 #define ZONE_TOP_TEXT N_("Number of zones on top")
225 #define ZONE_TOP_LONGTEXT N_("Number of zones on the top of the screen")
226 #define ZONE_BOTTOM_TEXT N_("Number of zones on bottom")
227 #define ZONE_BOTTOM_LONGTEXT N_("Number of zones on the bottom of the screen")
228 #define ZONE_LR_TEXT N_("Zones on left / right side")
229 #define ZONE_LR_LONGTEXT N_("left and right side having allways the " \
230 "same number of zones")
231 #define ZONE_SUMMARY_TEXT N_("Calculate a average zone")
232 #define ZONE_SUMMARY_LONGTEXT N_("it contains the average of all pixels " \
233 "in the sample image (only useful for " \
234 "single channel AtmoLight)")
237 #define USEWHITEADJ_TEXT N_("Use Software White adjust")
238 #define USEWHITEADJ_LONGTEXT N_("Should the buildin driver do a white " \
239 "adjust or your LED stripes? recommend.")
240 #define WHITE_RED_TEXT N_("White Red")
241 #define WHITE_RED_LONGTEXT N_("Red value of a pure white on your "\
242 "LED stripes.")
243 #define WHITE_GREEN_TEXT N_("White Green")
244 #define WHITE_GREEN_LONGTEXT N_("Green value of a pure white on your "\
245 "LED stripes.")
246 #define WHITE_BLUE_TEXT N_("White Blue")
247 #define WHITE_BLUE_LONGTEXT N_("Blue value of a pure white on your "\
248 "LED stripes.")
250 #define SERIALDEV_TEXT N_("Serial Port/Device")
251 #define SERIALDEV_LONGTEXT N_("Name of the serial port where the AtmoLight "\
252 "controller is attached to.\n" \
253 "On Windows usually something like COM1 or " \
254 "COM2. On Linux /dev/ttyS01 f.e.")
256 #define EDGE_TEXT N_("Edge Weightning")
257 #define EDGE_LONGTEXT N_("Increasing this value will result in color "\
258 "more depending on the border of the frame.")
259 #define BRIGHTNESS_TEXT N_("Brightness")
260 #define BRIGHTNESS_LONGTEXT N_("Overall brightness of your LED stripes")
261 #define DARKNESS_TEXT N_("Darkness Limit")
262 #define DARKNESS_LONGTEXT N_("Pixels with a saturation lower than this will "\
263 "be ignored. Should be greater than one for "\
264 "letterboxed videos.")
265 #define HUEWINSIZE_TEXT N_("Hue windowing")
266 #define HUEWINSIZE_LONGTEXT N_("Used for statistics.")
267 #define SATWINSIZE_TEXT N_("Sat windowing")
268 #define SATWINSIZE_LONGTEXT N_("Used for statistics.")
270 #define MEANLENGTH_TEXT N_("Filter length (ms)")
271 #define MEANLENGTH_LONGTEXT N_("Time it takes until a color is completely "\
272 "changed. This prevents flickering.")
273 #define MEANTHRESHOLD_TEXT N_("Filter threshold")
274 #define MEANTHRESHOLD_LONGTEXT N_("How much a color has to be changed for an "\
275 "immediate color change.")
276 #define MEANPERCENTNEW_TEXT N_("Filter Smoothness (in %)")
277 #define MEANPERCENTNEW_LONGTEXT N_("Filter Smoothness")
279 #define FILTERMODE_TEXT N_("Output Color filter mode")
280 #define FILTERMODE_LONGTEXT N_("defines the how the output color should " \
281 "be calculated based on previous color")
283 static const int pi_filtermode_values[] = {
284 (int)afmNoFilter,
285 (int)afmCombined,
286 (int)afmPercent
288 static const char *const ppsz_filtermode_descriptions[] = {
289 N_("No Filtering"),
290 N_("Combined"),
291 N_("Percent")
294 #define FRAMEDELAY_TEXT N_("Frame delay (ms)")
295 #define FRAMEDELAY_LONGTEXT N_("Helps to get the video output and the light "\
296 "effects in sync. Values around 20ms should " \
297 "do the trick.")
300 #define CHANNEL_0_ASSIGN_TEXT N_("Channel 0: summary")
301 #define CHANNEL_1_ASSIGN_TEXT N_("Channel 1: left")
302 #define CHANNEL_2_ASSIGN_TEXT N_("Channel 2: right")
303 #define CHANNEL_3_ASSIGN_TEXT N_("Channel 3: top")
304 #define CHANNEL_4_ASSIGN_TEXT N_("Channel 4: bottom")
306 #define CHANNELASSIGN_LONGTEXT N_("Maps the hardware channel X to logical "\
307 "zone Y to fix wrong wiring :-)")
308 static const int pi_zone_assignment_values[] = {
316 static const char *const ppsz_zone_assignment_descriptions[] = {
317 N_("disabled"),
318 N_("Zone 4:summary"),
319 N_("Zone 3:left"),
320 N_("Zone 1:right"),
321 N_("Zone 0:top"),
322 N_("Zone 2:bottom")
324 #define CHANNELS_ASSIGN_TEXT N_("Channel / Zone Assignment")
325 #define CHANNELS_ASSIGN_LONGTEXT N_("for devices with more than five " \
326 "channels / zones write down here for each channel " \
327 "the zone number to show and separate the values with " \
328 ", or ; and use -1 to not use some channels. For the " \
329 "classic AtmoLight the sequence 4,3,1,0,2 would set the " \
330 "default channel/zone mapping. " \
331 "Having only two zones on top, and one zone on left and " \
332 "right and no summary zone the mapping for classic " \
333 "AtmoLight would be -1,3,2,1,0")
335 #define ZONE_0_GRADIENT_TEXT N_("Zone 0: Top gradient")
336 #define ZONE_1_GRADIENT_TEXT N_("Zone 1: Right gradient")
337 #define ZONE_2_GRADIENT_TEXT N_("Zone 2: Bottom gradient")
338 #define ZONE_3_GRADIENT_TEXT N_("Zone 3: Left gradient")
339 #define ZONE_4_GRADIENT_TEXT N_("Zone 4: Summary gradient")
340 #define ZONE_X_GRADIENT_LONG_TEXT N_("Defines a small bitmap with 64x48 "\
341 "pixels, containing a grayscale gradient")
343 #define GRADIENT_PATH_TEXT N_("Gradient bitmap searchpath")
344 #define GRADIENT_PATH_LONGTEXT N_("Now preferred option to assign gradient "\
345 "bitmaps, put them as zone_0.bmp, zone_1.bmp etc. into one folder and "\
346 "set the foldername here")
348 #if defined( WIN32 )
349 # define ATMOWINEXE_TEXT N_("Filename of AtmoWin*.exe")
350 # define ATMOWINEXE_LONGTEXT N_("if you want the AtmoLight control "\
351 "software to be launched by VLC, enter the "\
352 "complete path of AtmoWinA.exe here.")
353 #endif
355 #define CFG_PREFIX "atmo-"
357 /*****************************************************************************
358 * Module descriptor
359 *****************************************************************************/
360 vlc_module_begin ()
361 set_description( N_("AtmoLight Filter") )
362 set_help( MODULE_DESCRIPTION )
363 set_shortname( N_( "AtmoLight" ))
364 set_category( CAT_VIDEO )
365 set_subcategory( SUBCAT_VIDEO_VFILTER )
367 set_capability( "video filter2", 0 )
370 set_section( N_("Choose Devicetype and Connection" ), 0 )
372 add_integer( CFG_PREFIX "device", DEFAULT_DEVICE,
373 DRIVER_TEXT, DRIVER_LONGTEXT, false )
374 change_integer_list( pi_device_type_values,
375 ppsz_device_type_descriptions )
377 #if defined(WIN32)
378 add_string(CFG_PREFIX "serialdev", "COM1",
379 SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false )
381 on win32 the executeable external driver application
382 for automatic start if needed
384 add_loadfile(CFG_PREFIX "atmowinexe", NULL,
385 ATMOWINEXE_TEXT, ATMOWINEXE_LONGTEXT, false )
386 #else
387 add_string(CFG_PREFIX "serialdev", "/dev/ttyUSB0",
388 SERIALDEV_TEXT, SERIALDEV_LONGTEXT, false )
389 #endif
392 color which is showed if you want durring pausing
393 your movie ... used for both buildin / external
395 set_section( N_("Illuminate the room with this color on pause" ), 0 )
396 add_bool(CFG_PREFIX "usepausecolor", false, NULL,
397 PCOLOR_TEXT, PCOLOR_LONGTEXT, false)
398 add_integer_with_range(CFG_PREFIX "pcolor-red", 0, 0, 255, NULL,
399 PCOLOR_RED_TEXT, PCOLOR_RED_LONGTEXT, false)
400 add_integer_with_range(CFG_PREFIX "pcolor-green", 0, 0, 255, NULL,
401 PCOLOR_GREEN_TEXT, PCOLOR_GREEN_LONGTEXT, false)
402 add_integer_with_range(CFG_PREFIX "pcolor-blue", 192, 0, 255, NULL,
403 PCOLOR_BLUE_TEXT, PCOLOR_BLUE_LONGTEXT, false)
404 add_integer_with_range(CFG_PREFIX "fadesteps", 50, 1, 250, NULL,
405 FADESTEPS_TEXT, FADESTEPS_LONGTEXT, false)
408 color which is showed if you finished watching your movie ...
409 used for both buildin / external
411 set_section( N_("Illuminate the room with this color on shutdown" ), 0 )
412 add_integer_with_range(CFG_PREFIX "ecolor-red", 192, 0, 255, NULL,
413 ECOLOR_RED_TEXT, ECOLOR_RED_LONGTEXT, false)
414 add_integer_with_range(CFG_PREFIX "ecolor-green", 192, 0, 255, NULL,
415 ECOLOR_GREEN_TEXT, ECOLOR_GREEN_LONGTEXT, false)
416 add_integer_with_range(CFG_PREFIX "ecolor-blue", 192, 0, 255, NULL,
417 ECOLOR_BLUE_TEXT, ECOLOR_BLUE_LONGTEXT, false)
418 add_integer_with_range(CFG_PREFIX "efadesteps", 50, 1, 250, NULL,
419 EFADESTEPS_TEXT, EFADESTEPS_LONGTEXT, false)
422 set_section( N_("DMX options" ), 0 )
423 add_integer_with_range(CFG_PREFIX "dmx-channels", 5, 1, 64, NULL,
424 DMX_CHANNELS_TEXT, DMX_CHANNELS_LONGTEXT, false)
425 add_string(CFG_PREFIX "dmx-chbase", "0,3,6,9,12",
426 DMX_CHBASE_TEXT, DMX_CHBASE_LONGTEXT, false )
428 set_section( N_("MoMoLight options" ), 0 )
429 add_integer_with_range(CFG_PREFIX "momo-channels", 3, 3, 4, NULL,
430 MOMO_CHANNELS_TEXT, MOMO_CHANNELS_LONGTEXT, false)
432 /* 2,2,4 means 2 is the default value, 1 minimum amount,
433 4 maximum amount
435 set_section( N_("fnordlicht options" ), 0 )
436 add_integer_with_range(CFG_PREFIX "fnordlicht-amount", 2, 1, 4, NULL,
437 FNORDLICHT_AMOUNT_TEXT,
438 FNORDLICHT_AMOUNT_LONGTEXT, false)
442 instead of redefining the original AtmoLight zones with gradient
443 bitmaps, we can now define the layout of the zones useing these
444 parameters - the function with the gradient bitmaps would still
445 work (but for most cases its no longer required)
447 short description whats this means - f.e. the classic atmo would
448 have this layout
449 zones-top = 1 - zone 0
450 zones-lr = 1 - zone 1 und zone 3
451 zones-bottom = 1 - zone 2
452 zone-summary = true - zone 4
454 ,------------,
456 Z3| Z4 | Z1
457 |____________|
460 the zone numbers will be counted clockwise starting at top / left
461 if you want to split the light at the top, without having a bottom zone
462 (which is my private config)
464 zones-top = 2 - zone 0, zone 1
465 zones-lr = 1 - zone 2 und zone 3
466 zones-bottom = 0
467 zone-summary = false
469 Z0 Z1
470 ,------------,
472 Z3| | Z2
473 |____________|
477 set_section( N_("Zone Layout for the build-in Atmo" ), 0 )
478 add_integer_with_range(CFG_PREFIX "zones-top", 1, 0, 16, NULL,
479 ZONE_TOP_TEXT, ZONE_TOP_LONGTEXT, false)
480 add_integer_with_range(CFG_PREFIX "zones-bottom", 1, 0, 16, NULL,
481 ZONE_BOTTOM_TEXT, ZONE_BOTTOM_LONGTEXT, false)
482 add_integer_with_range(CFG_PREFIX "zones-lr", 1, 0, 16, NULL,
483 ZONE_LR_TEXT, ZONE_LR_LONGTEXT, false)
484 add_bool(CFG_PREFIX "zone-summary", false, NULL,
485 ZONE_SUMMARY_TEXT, ZONE_SUMMARY_LONGTEXT, false)
488 settings only for the buildin driver (if external driver app is used
489 these parameters are ignored.)
491 definition of parameters for the buildin filter ...
493 set_section( N_("Settings for the built-in Live Video Processor only" ), 0 )
495 add_integer_with_range(CFG_PREFIX "edgeweightning", 3, 1, 30, NULL,
496 EDGE_TEXT, EDGE_LONGTEXT, false)
498 add_integer_with_range(CFG_PREFIX "brightness", 100, 50, 300, NULL,
499 BRIGHTNESS_TEXT, BRIGHTNESS_LONGTEXT, false)
501 add_integer_with_range(CFG_PREFIX "darknesslimit", 3, 0, 10, NULL,
502 DARKNESS_TEXT, DARKNESS_LONGTEXT, false)
504 add_integer_with_range(CFG_PREFIX "huewinsize", 3, 0, 5, NULL,
505 HUEWINSIZE_TEXT, HUEWINSIZE_LONGTEXT, false)
507 add_integer_with_range(CFG_PREFIX "satwinsize", 3, 0, 5, NULL,
508 SATWINSIZE_TEXT, SATWINSIZE_LONGTEXT, false)
510 add_integer(CFG_PREFIX "filtermode", (int)afmCombined,
511 FILTERMODE_TEXT, FILTERMODE_LONGTEXT, false )
513 change_integer_list(pi_filtermode_values, ppsz_filtermode_descriptions )
515 add_integer_with_range(CFG_PREFIX "meanlength", 300, 300, 5000, NULL,
516 MEANLENGTH_TEXT, MEANLENGTH_LONGTEXT, false)
518 add_integer_with_range(CFG_PREFIX "meanthreshold", 40, 1, 100, NULL,
519 MEANTHRESHOLD_TEXT, MEANTHRESHOLD_LONGTEXT, false)
521 add_integer_with_range(CFG_PREFIX "percentnew", 50, 1, 100, NULL,
522 MEANPERCENTNEW_TEXT, MEANPERCENTNEW_LONGTEXT, false)
524 add_integer_with_range(CFG_PREFIX "framedelay", 18, 0, 200, NULL,
525 FRAMEDELAY_TEXT, FRAMEDELAY_LONGTEXT, false)
528 output channel reordering
530 set_section( N_("Change channel assignment (fixes wrong wiring)" ), 0 )
531 add_integer( CFG_PREFIX "channel_0", 4,
532 CHANNEL_0_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
533 change_integer_list( pi_zone_assignment_values,
534 ppsz_zone_assignment_descriptions )
536 add_integer( CFG_PREFIX "channel_1", 3,
537 CHANNEL_1_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
538 change_integer_list( pi_zone_assignment_values,
539 ppsz_zone_assignment_descriptions )
541 add_integer( CFG_PREFIX "channel_2", 1,
542 CHANNEL_2_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
543 change_integer_list( pi_zone_assignment_values,
544 ppsz_zone_assignment_descriptions )
546 add_integer( CFG_PREFIX "channel_3", 0,
547 CHANNEL_3_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
548 change_integer_list( pi_zone_assignment_values,
549 ppsz_zone_assignment_descriptions )
551 add_integer( CFG_PREFIX "channel_4", 2,
552 CHANNEL_4_ASSIGN_TEXT, CHANNELASSIGN_LONGTEXT, false )
553 change_integer_list( pi_zone_assignment_values,
554 ppsz_zone_assignment_descriptions )
556 add_string(CFG_PREFIX "channels", "",
557 CHANNELS_ASSIGN_TEXT, CHANNELS_ASSIGN_LONGTEXT, false )
561 LED color white calibration
563 set_section( N_("Adjust the white light to your LED stripes" ), 0 )
564 add_bool(CFG_PREFIX "whiteadj", true, NULL,
565 USEWHITEADJ_TEXT, USEWHITEADJ_LONGTEXT, false)
566 add_integer_with_range(CFG_PREFIX "white-red", 255, 0, 255, NULL,
567 WHITE_RED_TEXT, WHITE_RED_LONGTEXT, false)
569 add_integer_with_range(CFG_PREFIX "white-green", 255, 0, 255, NULL,
570 WHITE_GREEN_TEXT, WHITE_GREEN_LONGTEXT, false)
572 add_integer_with_range(CFG_PREFIX "white-blue", 255, 0, 255, NULL,
573 WHITE_BLUE_TEXT, WHITE_BLUE_LONGTEXT, false)
574 /* end of definition of parameter for the buildin filter ... part 1 */
578 only for buildin (external has own definition) per default the calucation
579 used linear gradients for assigning a priority to the pixel - depending
580 how near they are to the border ...for changing this you can create 64x48
581 Pixel BMP files - which contain your own grayscale... (you can produce funny
582 effects with this...) the images MUST not compressed, should have 24-bit per
583 pixel, or a simple 256 color grayscale palette
585 set_section( N_("Change gradients" ), 0 )
586 add_loadfile(CFG_PREFIX "gradient_zone_0", NULL,
587 ZONE_0_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
588 add_loadfile(CFG_PREFIX "gradient_zone_1", NULL,
589 ZONE_1_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
590 add_loadfile(CFG_PREFIX "gradient_zone_2", NULL,
591 ZONE_2_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
592 add_loadfile(CFG_PREFIX "gradient_zone_3", NULL,
593 ZONE_3_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
594 add_loadfile(CFG_PREFIX "gradient_zone_4", NULL,
595 ZONE_4_GRADIENT_TEXT, ZONE_X_GRADIENT_LONG_TEXT, true )
596 add_directory(CFG_PREFIX "gradient_path", NULL,
597 GRADIENT_PATH_TEXT, GRADIENT_PATH_LONGTEXT, false )
599 #if defined(__ATMO_DEBUG__)
600 add_bool(CFG_PREFIX "saveframes", false, NULL,
601 SAVEFRAMES_TEXT, SAVEFRAMES_LONGTEXT, false)
602 add_string(CFG_PREFIX "framepath", "",
603 FRAMEPATH_TEXT, FRAMEPATH_LONGTEXT, false )
604 #endif
606 may be later if computers gets more power ;-) than now we increase
607 the samplesize from which we do the stats for output color calculation
609 add_integer_with_range(CFG_PREFIX "width", 64, 64, 512, NULL,
610 WIDTH_TEXT, WIDTH_LONGTEXT, true)
611 add_integer_with_range(CFG_PREFIX "height", 48, 48, 384, NULL,
612 HEIGHT_TEXT, HEIGHT_LONGTEXT, true)
613 add_bool(CFG_PREFIX "showdots", false, NULL,
614 SHOW_DOTS_TEXT, SHOW_DOTS_LONGTEXT, false)
615 add_shortcut( "atmo" )
616 set_callbacks( CreateFilter, DestroyFilter )
617 vlc_module_end ()
620 static const char *const ppsz_filter_options[] = {
621 "device",
623 "serialdev",
626 "edgeweightning",
627 "brightness",
628 "darknesslimit",
629 "huewinsize",
630 "satwinsize",
632 "filtermode",
634 "meanlength",
635 "meanthreshold",
636 "percentnew",
637 "framedelay",
639 "zones-top",
640 "zones-bottom",
641 "zones-lr",
642 "zone-summary",
644 "channel_0",
645 "channel_1",
646 "channel_2",
647 "channel_3",
648 "channel_4",
649 "channels",
651 "whiteadj",
652 "white-red",
653 "white-green",
654 "white-blue",
656 "usepausecolor",
657 "pcolor-red",
658 "pcolor-green",
659 "pcolor-blue",
660 "fadesteps",
662 "ecolor-red",
663 "ecolor-green",
664 "ecolor-blue",
665 "efadesteps",
667 "dmx-channels",
668 "dmx-chbase",
669 "momo-channels",
670 "fnordlicht-amount",
672 #if defined(WIN32 )
673 "atmowinexe",
674 #endif
675 #if defined(__ATMO_DEBUG__)
676 "saveframes" ,
677 "framepath",
678 #endif
679 "width",
680 "height",
681 "showdots",
682 "gradient_zone_0",
683 "gradient_zone_1",
684 "gradient_zone_2",
685 "gradient_zone_3",
686 "gradient_zone_4",
687 "gradient_path",
688 NULL
692 /*****************************************************************************
693 * fadethread_t: Color Fading Thread
694 *****************************************************************************
695 * changes slowly the color of the output if videostream gets paused...
696 *****************************************************************************
698 typedef struct
700 VLC_COMMON_MEMBERS
701 filter_t *p_filter;
702 /* tell the thread which color should be the target of fading */
703 uint8_t ui_red;
704 uint8_t ui_green;
705 uint8_t ui_blue;
706 /* how many steps should happen until this */
707 int i_steps;
709 } fadethread_t;
711 static void *FadeToColorThread(vlc_object_t *);
714 /*****************************************************************************
715 * filter_sys_t: AtmoLight filter method descriptor
716 *****************************************************************************
717 * It describes the AtmoLight specific properties of an video filter.
718 *****************************************************************************/
719 struct filter_sys_t
722 special for the access of the p_fadethread member all other members
723 need no special protection so far!
725 vlc_mutex_t filter_lock;
727 bool b_enabled;
728 int32_t i_AtmoOldEffect;
729 bool b_pause_live;
730 bool b_show_dots;
731 int32_t i_device_type;
733 int32_t i_atmo_width;
734 int32_t i_atmo_height;
735 /* used to disable fadeout if less than 50 frames are processed
736 used to avoid long time waiting when switch quickly between
737 deinterlaceing modes, where the output filter chains is rebuild
738 on each switch
740 int32_t i_frames_processed;
742 #if defined(__ATMO_DEBUG__)
743 bool b_saveframes;
744 uint32_t ui_frame_counter;
745 char sz_framepath[MAX_PATH];
746 #endif
748 /* light color durring movie pause ... */
749 bool b_usepausecolor;
750 uint8_t ui_pausecolor_red;
751 uint8_t ui_pausecolor_green;
752 uint8_t ui_pausecolor_blue;
753 int i_fadesteps;
755 /* light color on movie finish ... */
756 uint8_t ui_endcolor_red;
757 uint8_t ui_endcolor_green;
758 uint8_t ui_endcolor_blue;
759 int i_endfadesteps;
761 fadethread_t *p_fadethread;
763 /* Variables for buildin driver only... */
765 /* is only present and initialized if the internal driver is used*/
766 CAtmoConfig *p_atmo_config;
767 /* storage for temporal settings "volatile" */
768 CAtmoDynData *p_atmo_dyndata;
769 /* initialized for buildin driver with AtmoCreateTransferBuffers */
770 BITMAPINFOHEADER mini_image_format;
771 /* is only use buildin driver! */
772 uint8_t *p_atmo_transfer_buffer;
773 /* end buildin driver */
776 contains the real output size of the video calculated on
777 change event of the variable "crop" from vout
779 int32_t i_crop_x_offset;
780 int32_t i_crop_y_offset;
781 int32_t i_crop_width;
782 int32_t i_crop_height;
784 void (*pf_extract_mini_image) (filter_sys_t *p_sys,
785 picture_t *p_inpic,
786 uint8_t *p_transfer_dest);
788 #if defined( WIN32 )
789 /* External Library as wrapper arround COM Stuff */
790 HINSTANCE h_AtmoCtrl;
791 int32_t (*pf_ctrl_atmo_initialize) (void);
792 void (*pf_ctrl_atmo_finalize) (int32_t what);
793 int32_t (*pf_ctrl_atmo_switch_effect) (int32_t);
794 int32_t (*pf_ctrl_atmo_set_live_source) (int32_t);
795 void (*pf_ctrl_atmo_create_transfer_buffers) (int32_t, int32_t,
796 int32_t , int32_t);
797 uint8_t* (*pf_ctrl_atmo_lock_transfer_buffer) (void);
798 void (*pf_ctrl_atmo_send_pixel_data) (void);
799 void (*pf_ctrl_atmo_get_image_size)(int32_t *,int32_t *);
800 #endif
804 initialize previously configured Atmo Light environment
805 - if internal is enabled try to access the device on the serial port
806 - if not internal is enabled and we are on win32 try to initialize
807 the previously loaded DLL ...
809 Return Values may be: -1 (failed for some reason - filter will be disabled)
810 1 Ok. lets rock
812 static int32_t AtmoInitialize(filter_t *p_filter, bool b_for_thread)
814 filter_sys_t *p_sys = p_filter->p_sys;
815 if(p_sys->p_atmo_config)
817 if(b_for_thread == false)
819 /* open com port */
820 /* setup Output Threads ... */
821 msg_Dbg( p_filter, "open atmo device...");
822 if(CAtmoTools::RecreateConnection(p_sys->p_atmo_dyndata)
823 == ATMO_TRUE)
825 return 1;
826 } else {
827 msg_Err( p_filter,"failed to open atmo device, "\
828 "some other software/driver may use it?");
831 #if defined(WIN32)
832 } else if(p_sys->pf_ctrl_atmo_initialize)
834 /* on win32 with active ctrl dll */
835 return p_sys->pf_ctrl_atmo_initialize();
836 #endif
838 return -1;
842 prepare the shutdown of the effect threads,
843 for build in filter - close the serialport after finishing the threads...
844 cleanup possible loaded DLL...
846 static void AtmoFinalize(filter_t *p_filter, int32_t what)
848 filter_sys_t *p_sys = p_filter->p_sys;
849 if(p_sys->p_atmo_config)
851 if(what == 1)
853 CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
854 if(p_atmo_dyndata)
856 p_atmo_dyndata->LockCriticalSection();
858 CAtmoInput *p_input = p_atmo_dyndata->getLiveInput();
859 p_atmo_dyndata->setLiveInput( NULL );
860 if(p_input != NULL)
862 p_input->Terminate();
863 delete p_input;
864 msg_Dbg( p_filter, "input thread died peacefully");
867 CThread *p_effect_thread = p_atmo_dyndata->getEffectThread();
868 p_atmo_dyndata->setEffectThread(NULL);
869 if(p_effect_thread != NULL)
872 forced the thread to die...
873 and wait for termination of the thread
875 p_effect_thread->Terminate();
876 delete p_effect_thread;
877 msg_Dbg( p_filter, "effect thread died peacefully");
880 CAtmoPacketQueue *p_queue =
881 p_atmo_dyndata->getLivePacketQueue();
882 p_atmo_dyndata->setLivePacketQueue( NULL );
883 if(p_queue != NULL)
885 delete p_queue;
886 msg_Dbg( p_filter, "packetqueue removed");
890 close serial port if it is open (all OS specific is inside
891 CAtmoSerialConnection implemented / defined)
893 CAtmoConnection *p_atmo_connection =
894 p_atmo_dyndata->getAtmoConnection();
895 p_atmo_dyndata->setAtmoConnection(NULL);
896 if(p_atmo_connection) {
897 p_atmo_connection->CloseConnection();
898 delete p_atmo_connection;
900 p_atmo_dyndata->UnLockCriticalSection();
903 #if defined(WIN32)
904 } else if(p_sys->pf_ctrl_atmo_finalize)
906 /* on win32 with active ctrl dll */
907 p_sys->pf_ctrl_atmo_finalize(what);
908 #endif
913 switch the current light effect to LiveView
915 static int32_t AtmoSwitchEffect(filter_t *p_filter, int32_t newMode)
917 filter_sys_t *p_sys = p_filter->p_sys;
919 msg_Dbg( p_filter, "AtmoSwitchEffect %d", newMode );
921 if(p_sys->p_atmo_config)
923 return CAtmoTools::SwitchEffect(p_sys->p_atmo_dyndata, emLivePicture);
924 #if defined(WIN32)
925 } else if(p_sys->pf_ctrl_atmo_switch_effect)
927 /* on win32 with active ctrl dll */
928 return p_sys->pf_ctrl_atmo_switch_effect( newMode );
929 #endif
931 return emDisabled;
935 set the current live picture source, does only something on win32,
936 with the external libraries - if the buildin effects are used nothing
937 happens...
939 static int32_t AtmoSetLiveSource(filter_t *p_filter, int32_t newSource)
941 filter_sys_t *p_sys = p_filter->p_sys;
943 msg_Dbg( p_filter, "AtmoSetLiveSource %d", newSource );
945 if(p_sys->p_atmo_config)
948 buildin driver
950 doesnt know different sources so this
951 function call would just do nothing special
952 in this case
954 #if defined(WIN32)
955 } else if(p_sys->pf_ctrl_atmo_set_live_source)
957 /* on win32 with active ctrl dll */
958 return p_sys->pf_ctrl_atmo_set_live_source(newSource);
959 #endif
961 return lvsGDI;
965 setup the pixel transferbuffers which is used to transfer pixeldata from
966 the filter to the effect thread, and possible accross the process
967 boundaries on win32, with the external DLL
969 static void AtmoCreateTransferBuffers(filter_t *p_filter,
970 int32_t FourCC,
971 int32_t bytePerPixel,
972 int32_t width,
973 int32_t height)
975 filter_sys_t *p_sys = p_filter->p_sys;
976 if(p_sys->p_atmo_config)
979 we need a buffer where the image is stored (only for transfer
980 to the processing thread)
982 free( p_sys->p_atmo_transfer_buffer );
984 p_sys->p_atmo_transfer_buffer = (uint8_t *)malloc(bytePerPixel *
985 width * height);
987 memset(&p_sys->mini_image_format,0,sizeof(BITMAPINFOHEADER));
989 p_sys->mini_image_format.biSize = sizeof(BITMAPINFOHEADER);
990 p_sys->mini_image_format.biWidth = width;
991 p_sys->mini_image_format.biHeight = height;
992 p_sys->mini_image_format.biBitCount = bytePerPixel*8;
993 p_sys->mini_image_format.biCompression = FourCC;
995 #if defined(WIN32)
996 } else if(p_sys->pf_ctrl_atmo_create_transfer_buffers)
998 /* on win32 with active ctrl dll */
999 p_sys->pf_ctrl_atmo_create_transfer_buffers(FourCC,
1000 bytePerPixel,
1001 width,
1002 height);
1003 #endif
1008 acquire the transfer buffer pointer the buildin version only
1009 returns the pointer to the allocated buffer ... the
1010 external version on win32 has to do some COM stuff to lock the
1011 Variant Byte array which is behind the buffer
1013 static uint8_t* AtmoLockTransferBuffer(filter_t *p_filter)
1015 filter_sys_t *p_sys = p_filter->p_sys;
1016 if(p_sys->p_atmo_config)
1018 return p_sys->p_atmo_transfer_buffer;
1019 #if defined(WIN32)
1020 } else if(p_sys->pf_ctrl_atmo_lock_transfer_buffer)
1022 /* on win32 with active ctrl dll */
1023 return p_sys->pf_ctrl_atmo_lock_transfer_buffer();
1024 #endif
1026 return NULL;
1030 send the content of current pixel buffer got with AtmoLockTransferBuffer
1031 to the processing threads
1032 - build in version - will forward the data to AtmoExternalCaptureInput Thread
1033 - win32 external - will do the same, but across the process boundaries via
1034 COM to the AtmoWinA.exe Process
1036 static void AtmoSendPixelData(filter_t *p_filter)
1038 filter_sys_t *p_sys = p_filter->p_sys;
1039 if(p_sys->p_atmo_config && p_sys->p_atmo_transfer_buffer)
1041 CAtmoDynData *p_atmo_dyndata = p_sys->p_atmo_dyndata;
1042 if(p_atmo_dyndata &&
1043 (p_atmo_dyndata->getLivePictureSource() == lpsExtern))
1046 the cast will go Ok because we are inside videolan there is only
1047 this kind of effect thread implemented!
1049 CAtmoExternalCaptureInput *p_atmo_external_capture_input_thread =
1050 (CAtmoExternalCaptureInput *)p_atmo_dyndata->getLiveInput();
1052 if(p_atmo_external_capture_input_thread)
1055 the same as above inside videolan only this single kind of
1056 input exists so we can cast without further tests!
1058 this call will do a 1:1 copy of this buffer, and wakeup
1059 the thread from normal sleeping
1061 p_atmo_external_capture_input_thread->
1062 DeliverNewSourceDataPaket(&p_sys->mini_image_format,
1063 p_sys->p_atmo_transfer_buffer);
1066 #if defined(WIN32)
1067 } else if(p_sys->pf_ctrl_atmo_send_pixel_data)
1069 /* on win32 with active ctrl dll */
1070 p_sys->pf_ctrl_atmo_send_pixel_data();
1071 #endif
1072 } else
1074 msg_Warn( p_filter, "AtmoSendPixelData no method");
1079 Shutdown AtmoLight finally - is call from DestroyFilter
1080 does the cleanup restores the effectmode on the external Software
1081 (only win32) and possible setup the final light ...
1083 static void Atmo_Shutdown(filter_t *p_filter)
1085 filter_sys_t *p_sys = p_filter->p_sys;
1087 if(p_sys->b_enabled == true)
1089 msg_Dbg( p_filter, "shut down atmo!");
1091 if there is a still running show pause color thread kill him!
1093 CheckAndStopFadeThread(p_filter);
1095 // perpare spawn fadeing thread
1096 vlc_mutex_lock( &p_sys->filter_lock );
1099 fade to end color (in case of external AtmoWin Software
1100 assume that the static color will equal to this
1101 one to get a soft change and no flash!
1103 p_sys->b_pause_live = true;
1106 p_sys->p_fadethread = (fadethread_t *)vlc_object_create( p_filter,
1107 sizeof(fadethread_t) );
1109 p_sys->p_fadethread->p_filter = p_filter;
1110 p_sys->p_fadethread->ui_red = p_sys->ui_endcolor_red;
1111 p_sys->p_fadethread->ui_green = p_sys->ui_endcolor_green;
1112 p_sys->p_fadethread->ui_blue = p_sys->ui_endcolor_blue;
1113 if(p_sys->i_frames_processed < 50)
1114 p_sys->p_fadethread->i_steps = 1;
1115 else
1116 p_sys->p_fadethread->i_steps = p_sys->i_endfadesteps;
1118 if( vlc_thread_create( p_sys->p_fadethread,
1119 "AtmoLight fadeing",
1120 FadeToColorThread,
1121 VLC_THREAD_PRIORITY_LOW ) )
1123 msg_Err( p_filter, "cannot create FadeToColorThread" );
1124 vlc_object_release( p_sys->p_fadethread );
1125 p_sys->p_fadethread = NULL;
1126 vlc_mutex_unlock( &p_sys->filter_lock );
1128 } else {
1130 vlc_mutex_unlock( &p_sys->filter_lock );
1132 /* wait for the thread... */
1133 vlc_thread_join(p_sys->p_fadethread);
1135 vlc_object_release(p_sys->p_fadethread);
1137 p_sys->p_fadethread = NULL;
1141 the following happens only useing the
1142 external AtmoWin Device Software
1144 if( !p_sys->p_atmo_config )
1146 if(p_sys->i_AtmoOldEffect != emLivePicture)
1147 AtmoSwitchEffect( p_filter, p_sys->i_AtmoOldEffect);
1148 else
1149 AtmoSetLiveSource( p_filter, lvsGDI );
1152 /* close device connection etc. */
1153 AtmoFinalize(p_filter, 1);
1155 /* disable filter method .. */
1156 p_sys->b_enabled = false;
1161 depending on mode setup imagesize to 64x48(classic), or defined
1162 resolution of external atmowin.exe on windows
1164 static void Atmo_SetupImageSize(filter_t *p_filter)
1166 filter_sys_t *p_sys = p_filter->p_sys;
1168 size of extracted image by default 64x48 (other imagesizes are
1169 currently ignored by AtmoWin)
1171 p_sys->i_atmo_width = var_CreateGetIntegerCommand( p_filter,
1172 CFG_PREFIX "width");
1173 p_sys->i_atmo_height = var_CreateGetIntegerCommand( p_filter,
1174 CFG_PREFIX "height");
1176 if(p_sys->p_atmo_config)
1178 #if defined(WIN32)
1179 } else if(p_sys->pf_ctrl_atmo_get_image_size)
1181 /* on win32 with active ctrl dll */
1182 p_sys->pf_ctrl_atmo_get_image_size( &p_sys->i_atmo_width,
1183 &p_sys->i_atmo_height );
1184 #endif
1187 msg_Dbg(p_filter,"sample image size %d * %d pixels", p_sys->i_atmo_width,
1188 p_sys->i_atmo_height);
1192 initialize the zone and channel mapping for the buildin atmolight adapter
1194 static void Atmo_SetupBuildZones(filter_t *p_filter)
1196 filter_sys_t *p_sys = p_filter->p_sys;
1198 p_sys->p_atmo_dyndata->LockCriticalSection();
1200 CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
1203 CAtmoChannelAssignment *p_channel_assignment =
1204 p_atmo_config->getChannelAssignment(0);
1206 // channel 0 - zone 4
1207 p_channel_assignment->setZoneIndex( 0, var_CreateGetIntegerCommand(
1208 p_filter, CFG_PREFIX "channel_0")
1211 // channel 1 - zone 3
1212 p_channel_assignment->setZoneIndex( 1, var_CreateGetIntegerCommand(
1213 p_filter, CFG_PREFIX "channel_1")
1216 // channel 2 - zone 1
1217 p_channel_assignment->setZoneIndex( 2, var_CreateGetIntegerCommand(
1218 p_filter, CFG_PREFIX "channel_2")
1221 // channel 3 - zone 0
1222 p_channel_assignment->setZoneIndex( 3, var_CreateGetIntegerCommand(
1223 p_filter, CFG_PREFIX "channel_3")
1226 // channel 4 - zone 2
1227 p_channel_assignment->setZoneIndex( 4, var_CreateGetIntegerCommand(
1228 p_filter, CFG_PREFIX "channel_4")
1231 char *psz_channels = var_CreateGetStringCommand(
1232 p_filter,
1233 CFG_PREFIX "channels"
1235 if( psz_channels && strlen(psz_channels) > 0 )
1237 msg_Dbg( p_filter, "deal with new zone mapping %s", psz_channels );
1238 int channel = 0;
1239 char *psz_temp = psz_channels;
1240 char *psz_start = psz_temp;
1241 while( *psz_temp )
1243 if(*psz_temp == ',' || *psz_temp == ';')
1245 *psz_temp = 0;
1246 if(*psz_start)
1248 int zone = atoi( psz_start );
1249 if( zone < -1 ||
1250 zone >= p_channel_assignment->getSize()) {
1251 msg_Warn( p_filter, "Zone %d out of range -1..%d",
1252 zone, p_channel_assignment->getSize()-1 );
1253 } else {
1254 p_channel_assignment->setZoneIndex( channel, zone );
1255 channel++;
1258 psz_start = psz_temp;
1259 psz_start++;
1262 psz_temp++;
1266 process the rest of the string
1268 if( *psz_start && !*psz_temp )
1270 int zone = atoi( psz_start );
1271 if( zone < -1 ||
1272 zone >= p_channel_assignment->getSize()) {
1273 msg_Warn( p_filter, "Zone %d out of range -1..%d",
1274 zone, p_channel_assignment->getSize()-1 );
1275 } else {
1276 p_channel_assignment->setZoneIndex( channel, zone );
1280 free( psz_channels );
1282 for(int i=0;i< p_channel_assignment->getSize() ;i++)
1283 msg_Info( p_filter, "map zone %d to hardware channel %d",
1284 p_channel_assignment->getZoneIndex( i ),
1287 p_sys->p_atmo_dyndata->getAtmoConnection()
1288 ->SetChannelAssignment( p_channel_assignment );
1295 calculate the default gradients for each zone!
1296 depending on the zone layout set before, this now
1297 supports also multiple gradients on each side
1298 (older versions could do this only with external
1299 gradient bitmaps)
1301 p_sys->p_atmo_dyndata->CalculateDefaultZones();
1305 first try to load the old style defined gradient bitmaps
1306 this could only be done for the first five zones
1307 - should be deprecated -
1309 CAtmoZoneDefinition *p_zone;
1310 char psz_gradient_var_name[30];
1311 char *psz_gradient_file;
1312 for(int i=0;i<CLASSIC_ATMO_NUM_ZONES;i++)
1314 sprintf(psz_gradient_var_name, CFG_PREFIX "gradient_zone_%d", i);
1315 psz_gradient_file = var_CreateGetStringCommand(
1316 p_filter,
1317 psz_gradient_var_name
1319 if(psz_gradient_file && strlen(psz_gradient_file)>0)
1321 msg_Dbg( p_filter, "loading gradientfile %s for "\
1322 "zone %d", psz_gradient_file, i);
1324 p_zone = p_atmo_config->getZoneDefinition(i);
1325 if( p_zone )
1327 int i_res = p_zone->LoadGradientFromBitmap(psz_gradient_file);
1329 if(i_res != ATMO_LOAD_GRADIENT_OK)
1331 msg_Err( p_filter,"failed to load gradient '%s' with "\
1332 "error %d",psz_gradient_file,i_res);
1336 free( psz_gradient_file );
1341 the new approach try to load a gradient bitmap for each zone
1342 from a previously defined folder containing
1343 zone_0.bmp
1344 zone_1.bmp
1345 zone_2.bmp etc.
1347 char *psz_gradient_path = var_CreateGetStringCommand(
1348 p_filter,
1349 CFG_PREFIX "gradient_path"
1351 if( psz_gradient_path && strlen(psz_gradient_path) > 0 )
1353 char *psz_file_name = (char *)malloc( strlen(psz_gradient_path) + 16 );
1354 assert( psz_file_name );
1356 for(int i=0; i < p_atmo_config->getZoneCount(); i++ )
1358 p_zone = p_atmo_config->getZoneDefinition(i);
1360 if( p_zone )
1362 sprintf(psz_file_name, "%s%szone_%d.bmp",
1363 psz_gradient_path, DIR_SEP, i );
1365 int i_res = p_zone->LoadGradientFromBitmap( psz_file_name );
1367 if( i_res == ATMO_LOAD_GRADIENT_OK )
1369 msg_Dbg( p_filter, "loaded gradientfile %s for "\
1370 "zone %d", psz_file_name, i);
1373 if( (i_res != ATMO_LOAD_GRADIENT_OK) &&
1374 (i_res != ATMO_LOAD_GRADIENT_FILENOTFOND) )
1376 msg_Err( p_filter,"failed to load gradient '%s' with "\
1377 "error %d",psz_file_name,i_res);
1382 free( psz_file_name );
1384 free( psz_gradient_path );
1387 p_sys->p_atmo_dyndata->UnLockCriticalSection();
1391 static void Atmo_SetupConfig(filter_t *p_filter, CAtmoConfig *p_atmo_config)
1394 figuring out the device ports (com-ports, ttys)
1396 char *psz_serialdev = var_CreateGetStringCommand( p_filter,
1397 CFG_PREFIX "serialdev" );
1398 char *psz_temp = psz_serialdev;
1400 if( psz_temp && strlen(psz_temp) > 0 )
1402 char *psz_token;
1403 int i_port = 0;
1404 int i;
1405 int j;
1407 msg_Dbg( p_filter, "use port(s) %s",psz_serialdev);
1410 psz_serialdev - may contain up to 4 COM ports for the quattro device
1411 the quattro device is just hack of useing 4 classic devices as one
1412 logical device - thanks that usb-com-ports exists :)
1413 as Seperator I defined , or ; with the hope that these
1414 characters are never part of a device name
1416 while( (psz_token = strsep(&psz_temp, ",;")) != NULL && i_port < 4 )
1419 psz_token may contain spaces we have to trim away
1421 i = 0;
1422 j = 0;
1424 find first none space in string
1426 while( psz_token[i] == 32 ) i++;
1428 contains string only spaces or is empty? skip it
1430 if( !psz_token[i] )
1431 continue;
1434 trim
1436 while( psz_token[i] && psz_token[i] != 32 )
1437 psz_token[ j++ ] = psz_token[ i++ ];
1438 psz_token[j++] = 0;
1440 msg_Dbg( p_filter, "Serial Device [%d]: %s", i_port, psz_token );
1442 p_atmo_config->setSerialDevice( i_port, psz_token );
1444 i_port++;
1447 else
1449 msg_Err(p_filter,"no serial devicename(s) set");
1451 free( psz_serialdev );
1454 configuration of light source layout arround the display
1456 p_atmo_config->setZonesTopCount(
1457 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "zones-top")
1459 p_atmo_config->setZonesBottomCount(
1460 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "zones-bottom")
1462 p_atmo_config->setZonesLRCount(
1463 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "zones-lr")
1465 p_atmo_config->setZoneSummary(
1466 var_CreateGetBoolCommand( p_filter, CFG_PREFIX "zone-summary")
1470 p_atmo_config->setLiveViewFilterMode(
1471 (AtmoFilterMode)var_CreateGetIntegerCommand( p_filter,
1472 CFG_PREFIX "filtermode")
1475 p_atmo_config->setLiveViewFilter_PercentNew(
1476 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "percentnew")
1478 p_atmo_config->setLiveViewFilter_MeanLength(
1479 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "meanlength")
1481 p_atmo_config->setLiveViewFilter_MeanThreshold(
1482 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "meanthreshold")
1485 p_atmo_config->setLiveView_EdgeWeighting(
1486 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "edgeweightning")
1488 p_atmo_config->setLiveView_BrightCorrect(
1489 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "brightness")
1491 p_atmo_config->setLiveView_DarknessLimit(
1492 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "darknesslimit")
1494 p_atmo_config->setLiveView_HueWinSize(
1495 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "huewinsize")
1497 p_atmo_config->setLiveView_SatWinSize(
1498 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "satwinsize")
1501 /* currently not required inside vlc */
1502 p_atmo_config->setLiveView_WidescreenMode( 0 );
1504 p_atmo_config->setLiveView_FrameDelay(
1505 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "framedelay")
1509 p_atmo_config->setUseSoftwareWhiteAdj(
1510 var_CreateGetBoolCommand( p_filter, CFG_PREFIX "whiteadj")
1512 p_atmo_config->setWhiteAdjustment_Red(
1513 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-red")
1515 p_atmo_config->setWhiteAdjustment_Green(
1516 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-green")
1518 p_atmo_config->setWhiteAdjustment_Blue(
1519 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "white-blue")
1523 settings for DMX device only
1525 p_atmo_config->setDMX_RGB_Channels(
1526 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "dmx-channels")
1529 char *psz_chbase = var_CreateGetStringCommand( p_filter,
1530 CFG_PREFIX "dmx-chbase" );
1531 if( psz_chbase && strlen(psz_chbase) > 0 )
1532 p_atmo_config->setDMX_BaseChannels( psz_chbase );
1534 free( psz_chbase );
1537 momolight options
1539 p_atmo_config->setMoMo_Channels(
1540 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "momo-channels")
1544 fnordlicht options
1546 p_atmo_config->setFnordlicht_Amount(
1547 var_CreateGetIntegerCommand( p_filter, CFG_PREFIX "fnordlicht-amount")
1554 initialize the filter_sys_t structure with the data from the settings
1555 variables - if the external filter on win32 is enabled try loading the DLL,
1556 if this fails fallback to the buildin software
1558 static void Atmo_SetupParameters(filter_t *p_filter)
1560 char *psz_path;
1561 filter_sys_t *p_sys = p_filter->p_sys;
1564 /* default filter disabled until DLL loaded and Init Success!*/
1565 p_sys->b_enabled = false;
1567 /* setup default mini image size (may be later a user option) */
1568 p_sys->i_atmo_width = 64;
1569 p_sys->i_atmo_height = 48;
1571 p_sys->i_device_type = var_CreateGetIntegerCommand( p_filter,
1572 CFG_PREFIX "device");
1575 i_device_type
1576 0 => use AtmoWin Software (only win32)
1577 1 => use AtmoClassicConnection (direct)
1578 2 => use AtmoMultiConnection (direct up to four serial ports required)
1579 3 => use AtmoDmxConnection (simple serial DMX Device up to 255 channels)
1583 #if defined(WIN32)
1585 only on WIN32 the user has the choice between
1586 internal driver and external
1589 if(p_sys->i_device_type == 0) {
1591 /* Load the Com Wrapper Library (source available) */
1592 p_sys->h_AtmoCtrl = LoadLibraryA("AtmoCtrlLib.dll");
1593 if(p_sys->h_AtmoCtrl == NULL)
1596 be clever if the location of atmowina.exe is set
1597 try to load the dll from the same folder :-)
1599 char *psz_path = var_CreateGetStringCommand( p_filter,
1600 CFG_PREFIX "atmowinexe" );
1601 if( psz_path && strlen(psz_path) > 0 )
1603 char *psz_bs = strrchr( psz_path , '\\');
1604 if( psz_bs )
1606 *psz_bs = 0;
1608 now format a new dll filename with complete path
1610 char *psz_dllname = NULL;
1611 asprintf( &psz_dllname, "%s\\AtmoCtrlLib.dll", psz_path );
1612 if( psz_dllname )
1614 msg_Dbg( p_filter, "Try Loading '%s'", psz_dllname );
1615 p_sys->h_AtmoCtrl = LoadLibraryA( psz_dllname );
1617 free( psz_dllname );
1620 free( psz_path );
1624 if(p_sys->h_AtmoCtrl != NULL)
1626 msg_Dbg( p_filter, "Load Library ok!");
1628 /* importing all required functions I hope*/
1629 p_sys->pf_ctrl_atmo_initialize =
1630 (int32_t (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,
1631 "AtmoInitialize");
1632 if(!p_sys->pf_ctrl_atmo_initialize)
1633 msg_Err( p_filter, "export AtmoInitialize missing.");
1635 p_sys->pf_ctrl_atmo_finalize =
1636 (void (*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,
1637 "AtmoFinalize");
1638 if(!p_sys->pf_ctrl_atmo_finalize)
1639 msg_Err( p_filter, "export AtmoFinalize missing.");
1641 p_sys->pf_ctrl_atmo_switch_effect =
1642 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,
1643 "AtmoSwitchEffect");
1644 if(!p_sys->pf_ctrl_atmo_switch_effect)
1645 msg_Err( p_filter, "export AtmoSwitchEffect missing.");
1647 p_sys->pf_ctrl_atmo_set_live_source =
1648 (int32_t(*)(int32_t))GetProcAddress(p_sys->h_AtmoCtrl,
1649 "AtmoSetLiveSource");
1650 if(!p_sys->pf_ctrl_atmo_set_live_source)
1651 msg_Err( p_filter, "export AtmoSetLiveSource missing.");
1653 p_sys->pf_ctrl_atmo_create_transfer_buffers =
1654 (void (*)(int32_t, int32_t, int32_t , int32_t))
1655 GetProcAddress(p_sys->h_AtmoCtrl,"AtmoCreateTransferBuffers");
1656 if(!p_sys->pf_ctrl_atmo_create_transfer_buffers)
1657 msg_Err( p_filter, "export AtmoCreateTransferBuffers missing.");
1659 p_sys->pf_ctrl_atmo_lock_transfer_buffer=
1660 (uint8_t*(*) (void))GetProcAddress(p_sys->h_AtmoCtrl,
1661 "AtmoLockTransferBuffer");
1662 if(!p_sys->pf_ctrl_atmo_lock_transfer_buffer)
1663 msg_Err( p_filter, "export AtmoLockTransferBuffer missing.");
1665 p_sys->pf_ctrl_atmo_send_pixel_data =
1666 (void (*)(void))GetProcAddress(p_sys->h_AtmoCtrl,
1667 "AtmoSendPixelData");
1668 if(!p_sys->pf_ctrl_atmo_send_pixel_data)
1669 msg_Err( p_filter, "export AtmoSendPixelData missing.");
1671 p_sys->pf_ctrl_atmo_get_image_size =
1672 (void (*)(int32_t*,int32_t*))GetProcAddress(p_sys->h_AtmoCtrl,
1673 "AtmoWinGetImageSize");
1674 if(!p_sys->pf_ctrl_atmo_get_image_size)
1675 msg_Err( p_filter, "export AtmoWinGetImageSize missing.");
1677 } else {
1678 /* the DLL is missing try internal filter ...*/
1679 msg_Warn( p_filter,
1680 "AtmoCtrlLib.dll missing fallback to internal atmo classic driver");
1681 p_sys->i_device_type = 1;
1684 #endif
1686 if(p_sys->i_device_type >= 1) {
1687 msg_Dbg( p_filter, "try use buildin driver %d ", p_sys->i_device_type);
1689 now we have to read a lof of options from the config dialog
1690 most important the serial device if not set ... we can skip
1691 the rest and disable the filter...
1694 p_sys->p_atmo_config = new CAtmoConfig();
1696 p_sys->p_atmo_dyndata = new CAtmoDynData(
1697 (vlc_object_t *)p_filter,
1698 p_sys->p_atmo_config
1701 Atmo_SetupConfig( p_filter, p_sys->p_atmo_config );
1702 switch(p_sys->i_device_type)
1704 case 1:
1705 p_sys->p_atmo_config->setConnectionType( actClassicAtmo );
1706 break;
1708 case 2:
1709 p_sys->p_atmo_config->setConnectionType( actMultiAtmo );
1710 break;
1712 case 3:
1713 p_sys->p_atmo_config->setConnectionType( actDMX );
1714 break;
1716 case 4:
1717 p_sys->p_atmo_config->setConnectionType( actMoMoLight );
1718 break;
1720 case 5:
1721 p_sys->p_atmo_config->setConnectionType( actFnordlicht );
1722 break;
1724 default:
1725 msg_Warn( p_filter, "invalid device type %d found",
1726 p_sys->i_device_type );
1729 msg_Dbg( p_filter, "buildin driver config set");
1733 switch( p_filter->fmt_in.video.i_chroma )
1735 case VLC_CODEC_I420:
1736 case VLC_CODEC_YV12:
1737 p_sys->pf_extract_mini_image = ExtractMiniImage_YUV;
1738 break;
1739 default:
1740 msg_Warn( p_filter, "InitFilter-unsupported chroma: %4.4s",
1741 (char *)&p_filter->fmt_in.video.i_chroma);
1742 p_sys->pf_extract_mini_image = NULL;
1746 for debugging purpose show the samplinggrid on each frame as
1747 white dots
1749 p_sys->b_show_dots = var_CreateGetBoolCommand( p_filter,
1750 CFG_PREFIX "showdots"
1753 #if defined(__ATMO_DEBUG__)
1754 /* save debug images to a folder as Bitmap files ? */
1755 p_sys->b_saveframes = var_CreateGetBoolCommand( p_filter,
1756 CFG_PREFIX "saveframes"
1758 msg_Dbg(p_filter,"saveframes = %d", (int)p_sys->b_saveframes);
1761 read debug image folder from config
1763 psz_path = var_CreateGetStringCommand( p_filter, CFG_PREFIX "framepath" );
1764 if(psz_path != NULL)
1766 strcpy(p_sys->sz_framepath, psz_path);
1767 #if defined( WIN32 )
1768 size_t i_strlen = strlen(p_sys->sz_framepath);
1769 if((i_strlen>0) && (p_sys->sz_framepath[i_strlen-1] != '\\'))
1771 p_sys->sz_framepath[i_strlen] = '\\';
1772 p_sys->sz_framepath[i_strlen+1] = 0;
1774 #endif
1775 free(psz_path);
1777 msg_Dbg(p_filter,"saveframesfolder %s",p_sys->sz_framepath);
1778 #endif
1782 because atmowin could also be used for lighten up the room - I think if you
1783 pause the video it would be useful to get a little bit more light into to
1784 your living room? - instead switching on a lamp?
1786 p_sys->b_usepausecolor = var_CreateGetBoolCommand( p_filter,
1787 CFG_PREFIX "usepausecolor" );
1788 p_sys->ui_pausecolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1789 CFG_PREFIX "pcolor-red");
1790 p_sys->ui_pausecolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1791 CFG_PREFIX "pcolor-green");
1792 p_sys->ui_pausecolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1793 CFG_PREFIX "pcolor-blue");
1794 p_sys->i_fadesteps = var_CreateGetIntegerCommand( p_filter,
1795 CFG_PREFIX "fadesteps");
1796 if(p_sys->i_fadesteps < 1)
1797 p_sys->i_fadesteps = 1;
1798 msg_Dbg(p_filter,"use pause color %d, RGB: %d, %d, %d, Fadesteps: %d",
1799 (int)p_sys->b_usepausecolor,
1800 p_sys->ui_pausecolor_red,
1801 p_sys->ui_pausecolor_green,
1802 p_sys->ui_pausecolor_blue,
1803 p_sys->i_fadesteps);
1806 this color is use on shutdown of the filter - the define the
1807 final light after playback... may be used to dim up the light -
1808 how it happens in the cinema...
1810 p_sys->ui_endcolor_red = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1811 CFG_PREFIX "ecolor-red");
1812 p_sys->ui_endcolor_green = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1813 CFG_PREFIX "ecolor-green");
1814 p_sys->ui_endcolor_blue = (uint8_t)var_CreateGetIntegerCommand( p_filter,
1815 CFG_PREFIX "ecolor-blue");
1816 p_sys->i_endfadesteps = var_CreateGetIntegerCommand( p_filter,
1817 CFG_PREFIX "efadesteps");
1818 if(p_sys->i_endfadesteps < 1)
1819 p_sys->i_endfadesteps = 1;
1820 msg_Dbg(p_filter,"use ende color RGB: %d, %d, %d, Fadesteps: %d",
1821 p_sys->ui_endcolor_red,
1822 p_sys->ui_endcolor_green,
1823 p_sys->ui_endcolor_blue,
1824 p_sys->i_endfadesteps);
1829 if the external DLL was loaded successfully call AtmoInitialize -
1830 (must be done for each thread where you want to use AtmoLight!)
1832 int i = AtmoInitialize(p_filter, false);
1834 #if defined( WIN32 )
1835 if((i != 1) && (p_sys->i_device_type == 0))
1838 COM Server for AtmoLight not running ?
1839 if the exe path is configured try to start the "userspace" driver
1841 psz_path = var_CreateGetStringCommand( p_filter,
1842 CFG_PREFIX "atmowinexe" );
1843 if(psz_path != NULL)
1845 STARTUPINFO startupinfo;
1846 PROCESS_INFORMATION pinfo;
1847 memset(&startupinfo, 0, sizeof(STARTUPINFO));
1848 startupinfo.cb = sizeof(STARTUPINFO);
1849 if(CreateProcess(psz_path, NULL, NULL, NULL,
1850 FALSE, 0, NULL, NULL, &startupinfo, &pinfo) == TRUE)
1852 msg_Dbg(p_filter,"launched AtmoWin from %s",psz_path);
1853 WaitForInputIdle(pinfo.hProcess, 5000);
1855 retry to initialize the library COM ... functionality
1856 after the server was launched
1858 i = AtmoInitialize(p_filter, false);
1859 } else {
1860 msg_Err(p_filter,"failed to launch AtmoWin from %s", psz_path);
1862 free(psz_path);
1865 #endif
1867 if(i == 1) /* Init Atmolight success... */
1869 msg_Dbg( p_filter, "AtmoInitialize Ok!");
1871 configure
1872 p_sys->i_atmo_width and p_sys->i_atmo_height
1873 if the external AtmoWinA.exe is used, it may require
1874 a other sample image size than 64 x 48
1875 (this overrides the settings of the filter)
1877 Atmo_SetupImageSize( p_filter );
1880 if( p_sys->i_device_type >= 1 )
1883 AtmoConnection class initialized now we can initialize
1884 the default zone and channel mappings
1886 Atmo_SetupBuildZones( p_filter );
1889 /* Setup Transferbuffers for 64 x 48 , RGB with 32bit Per Pixel */
1890 AtmoCreateTransferBuffers(p_filter, BI_RGB, 4,
1891 p_sys->i_atmo_width,
1892 p_sys->i_atmo_height
1895 /* say the userspace driver that a live mode should be activated
1896 the functions returns the old mode for later restore!
1897 - the buildin driver launches the live view thread in that case
1899 p_sys->i_AtmoOldEffect = AtmoSwitchEffect(p_filter, emLivePicture);
1902 live view can have two differnt source the AtmoWinA
1903 internal GDI Screencapture and the external one - which we
1904 need here...
1906 AtmoSetLiveSource(p_filter, lvsExternal);
1908 /* enable other parts only if everything is fine */
1909 p_sys->b_enabled = true;
1911 msg_Dbg( p_filter, "Atmo Filter Enabled Ok!");
1917 /*****************************************************************************
1918 * CreateFilter: allocates AtmoLight video thread output method
1919 *****************************************************************************
1920 * This function allocates and initializes a AtmoLight vout method.
1921 *****************************************************************************/
1922 static int CreateFilter( vlc_object_t *p_this )
1924 filter_t *p_filter = (filter_t *)p_this;
1925 filter_sys_t *p_sys;
1927 /* Allocate structure */
1928 p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) );
1929 p_filter->p_sys = p_sys;
1930 if( p_filter->p_sys == NULL )
1931 return VLC_ENOMEM;
1932 /* set all entries to zero */
1933 memset(p_sys, 0, sizeof( filter_sys_t ));
1934 vlc_mutex_init( &p_sys->filter_lock );
1936 msg_Dbg( p_filter, "Create Atmo Filter");
1938 /* further Setup Function pointers for videolan for calling my filter */
1939 p_filter->pf_video_filter = Filter;
1941 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
1942 p_filter->p_cfg );
1944 AddStateVariableCallback(p_filter);
1946 AddAtmoSettingsVariablesCallbacks(p_filter);
1948 Atmo_SetupParameters(p_filter);
1951 return VLC_SUCCESS;
1956 /*****************************************************************************
1957 * DestroyFilter: destroy AtmoLight video thread output method
1958 *****************************************************************************
1959 * Terminate an output method created by CreateFilter
1960 *****************************************************************************/
1962 static void DestroyFilter( vlc_object_t *p_this )
1964 filter_t *p_filter = (filter_t *)p_this;
1965 filter_sys_t *p_sys = p_filter->p_sys;
1967 msg_Dbg( p_filter, "Destroy Atmo Filter");
1969 DelStateVariableCallback(p_filter);
1971 DelAtmoSettingsVariablesCallbacks(p_filter);
1973 Atmo_Shutdown(p_filter);
1975 #if defined( WIN32 )
1976 if(p_sys->h_AtmoCtrl != NULL)
1978 FreeLibrary(p_sys->h_AtmoCtrl);
1980 #endif
1982 delete p_sys->p_atmo_dyndata;
1983 delete p_sys->p_atmo_config;
1985 vlc_mutex_destroy( &p_sys->filter_lock );
1987 free( p_sys );
1992 function stolen from some other videolan source filter ;-)
1993 for the moment RGB is OK... but better would be a direct transformation
1994 from YUV --> HSV
1996 static inline void yuv_to_rgb( uint8_t *r, uint8_t *g, uint8_t *b,
1997 uint8_t y1, uint8_t u1, uint8_t v1 )
1999 /* macros used for YUV pixel conversions */
2000 # define SCALEBITS 10
2001 # define ONE_HALF (1 << (SCALEBITS - 1))
2002 # define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
2003 # define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
2005 int y, cb, cr, r_add, g_add, b_add;
2007 cb = u1 - 128;
2008 cr = v1 - 128;
2009 r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;
2010 g_add = - FIX(0.34414*255.0/224.0) * cb
2011 - FIX(0.71414*255.0/224.0) * cr + ONE_HALF;
2012 b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;
2013 y = (y1 - 16) * FIX(255.0/219.0);
2014 *r = CLAMP((y + r_add) >> SCALEBITS);
2015 *g = CLAMP((y + g_add) >> SCALEBITS);
2016 *b = CLAMP((y + b_add) >> SCALEBITS);
2018 /******************************************************************************
2019 * ExtractMiniImage_YUV: extract a small image from the picture as 24-bit RGB
2020 *******************************************************************************
2021 * p_sys is a pointer to
2022 * p_inpic is the source frame
2023 * p_transfer_dest is the target buffer for the picture must be big enough!
2024 * (in win32 enviroment this buffer comes from the external DLL where it is
2025 * create as "variant array" and returned through the AtmoLockTransferbuffer
2027 static void ExtractMiniImage_YUV(filter_sys_t *p_sys,
2028 picture_t *p_inpic,
2029 uint8_t *p_transfer_dest)
2031 int i_col;
2032 int i_row;
2033 uint8_t *p_src_y;
2034 uint8_t *p_src_u;
2035 uint8_t *p_src_v;
2036 uint8_t *p_rgb_dst_line_red;
2037 uint8_t *p_rgb_dst_line_green;
2038 uint8_t *p_rgb_dst_line_blue;
2039 int i_xpos_y;
2040 int i_xpos_u;
2041 int i_xpos_v;
2043 /* calcute Pointers for Storage of B G R (A) */
2044 p_rgb_dst_line_blue = p_transfer_dest;
2045 p_rgb_dst_line_green = p_transfer_dest + 1;
2046 p_rgb_dst_line_red = p_transfer_dest + 2 ;
2048 int i_row_count = p_sys->i_atmo_height + 1;
2049 int i_col_count = p_sys->i_atmo_width + 1;
2050 int i_y_row,i_u_row,i_v_row,i_pixel_row;
2051 int i_pixel_col;
2054 /* these two ugly loops extract the small image - goes it faster? how?
2055 the loops are so designed that there is a small border around the extracted
2056 image so we wont get column and row - zero from the frame, and not the most
2057 right and bottom pixels --- which may be clipped on computers useing TV out
2058 - through overscan!
2060 TODO: try to find out if the output is clipped through VLC - and try here
2061 to ingore the clipped away area for a better result!
2063 TODO: performance improvement in InitFilter percalculated the offsets of
2064 the lines inside the planes so I can save (i_row_count * 3) 2xMUL and
2065 one time DIV the same could be done for the inner loop I think...
2067 for(i_row = 1; i_row < i_row_count; i_row++)
2069 // calcute the current Lines in the source planes for this outputrow
2070 /* Adresscalcuation pointer to plane Length of one pixelrow in bytes
2071 calculate row now number
2074 p_inpic->format? transform Pixel row into row of plane...
2075 how? simple? fast? good?
2078 /* compute the source pixel row and respect the active cropping */
2079 i_pixel_row = (i_row * p_sys->i_crop_height) / i_row_count
2080 + p_sys->i_crop_y_offset;
2083 trans for these Pixel row into the row of each plane ..
2084 because planesize can differ from image size
2086 i_y_row = (i_pixel_row * p_inpic->p[Y_PLANE].i_visible_lines) /
2087 p_inpic->format.i_visible_height;
2089 i_u_row = (i_pixel_row * p_inpic->p[U_PLANE].i_visible_lines) /
2090 p_inpic->format.i_visible_height;
2092 i_v_row = (i_pixel_row * p_inpic->p[V_PLANE].i_visible_lines) /
2093 p_inpic->format.i_visible_height;
2095 /* calculate the pointers to the pixeldata for this row
2096 in each plane
2098 p_src_y = p_inpic->p[Y_PLANE].p_pixels +
2099 p_inpic->p[Y_PLANE].i_pitch * i_y_row;
2100 p_src_u = p_inpic->p[U_PLANE].p_pixels +
2101 p_inpic->p[U_PLANE].i_pitch * i_u_row;
2102 p_src_v = p_inpic->p[V_PLANE].p_pixels +
2103 p_inpic->p[V_PLANE].i_pitch * i_v_row;
2105 for(i_col = 1; i_col < i_col_count; i_col++)
2107 i_pixel_col = (i_col * p_sys->i_crop_width) / i_col_count +
2108 p_sys->i_crop_x_offset;
2110 trans for these Pixel row into the row of each plane ..
2111 because planesize can differ from image size
2113 i_xpos_y = (i_pixel_col * p_inpic->p[Y_PLANE].i_visible_pitch) /
2114 p_inpic->format.i_visible_width;
2115 i_xpos_u = (i_pixel_col * p_inpic->p[U_PLANE].i_visible_pitch) /
2116 p_inpic->format.i_visible_width;
2117 i_xpos_v = (i_pixel_col * p_inpic->p[V_PLANE].i_visible_pitch) /
2118 p_inpic->format.i_visible_width;
2120 yuv_to_rgb(p_rgb_dst_line_red,
2121 p_rgb_dst_line_green,
2122 p_rgb_dst_line_blue,
2124 p_src_y[i_xpos_y],
2125 p_src_u[i_xpos_u],
2126 p_src_v[i_xpos_v]);
2128 /* +4 because output image should be RGB32 with dword alignment! */
2129 p_rgb_dst_line_red += 4;
2130 p_rgb_dst_line_green += 4;
2131 p_rgb_dst_line_blue += 4;
2135 if(p_sys->b_show_dots)
2137 for(i_row = 1; i_row < i_row_count; i_row++)
2139 i_pixel_row = (i_row * p_sys->i_crop_height) / i_row_count
2140 + p_sys->i_crop_y_offset;
2142 i_y_row = (i_pixel_row * p_inpic->p[Y_PLANE].i_visible_lines) /
2143 p_inpic->format.i_visible_height;
2145 p_src_y = p_inpic->p[Y_PLANE].p_pixels +
2146 p_inpic->p[Y_PLANE].i_pitch * i_y_row;
2148 for(i_col = 1; i_col < i_col_count; i_col++)
2150 i_pixel_col = (i_col * p_sys->i_crop_width) / i_col_count +
2151 p_sys->i_crop_x_offset;
2152 i_xpos_y = (i_pixel_col * p_inpic->p[Y_PLANE].i_visible_pitch) /
2153 p_inpic->format.i_visible_width;
2155 p_src_y[i_xpos_y] = 255;
2163 /******************************************************************************
2164 * SaveBitmap: Saves the content of a transferbuffer as Bitmap to disk
2165 *******************************************************************************
2166 * just for debugging
2167 * p_sys -> configuration if Atmo from there the function will get height and
2168 * width
2169 * p_pixels -> should be the dword aligned BGR(A) image data
2170 * psz_filename -> filename where to store
2172 #if defined(__ATMO_DEBUG__)
2173 void SaveBitmap(filter_sys_t *p_sys, uint8_t *p_pixels, char *psz_filename)
2175 /* for debug out only used*/
2176 BITMAPINFO bmp_info;
2177 BITMAPFILEHEADER bmp_fileheader;
2178 FILE *fp_bitmap;
2180 memset(&bmp_info, 0, sizeof(BITMAPINFO));
2181 bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2182 bmp_info.bmiHeader.biSizeImage = p_sys->i_atmo_height *
2183 p_sys->i_atmo_width * 4;
2184 bmp_info.bmiHeader.biCompression = BI_RGB;
2185 bmp_info.bmiHeader.biWidth = p_sys->i_atmo_width;
2186 bmp_info.bmiHeader.biHeight = -p_sys->i_atmo_height;
2187 bmp_info.bmiHeader.biBitCount = 32;
2188 bmp_info.bmiHeader.biPlanes = 1;
2190 bmp_fileheader.bfReserved1 = 0;
2191 bmp_fileheader.bfReserved2 = 0;
2192 bmp_fileheader.bfSize = sizeof(BITMAPFILEHEADER) +
2193 sizeof(BITMAPINFOHEADER) +
2194 bmp_info.bmiHeader.biSizeImage;
2195 bmp_fileheader.bfType = VLC_TWOCC('B','M');
2196 bmp_fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) +
2197 sizeof(BITMAPINFOHEADER);
2199 fp_bitmap = fopen(psz_filename,"wb");
2200 if( fp_bitmap != NULL)
2202 fwrite(&bmp_fileheader, sizeof(BITMAPFILEHEADER), 1, fp_bitmap);
2203 fwrite(&bmp_info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp_bitmap);
2204 fwrite(p_pixels, bmp_info.bmiHeader.biSizeImage, 1, fp_bitmap);
2205 fclose(fp_bitmap);
2208 #endif
2211 /****************************************************************************
2212 * CreateMiniImage: extracts a 64x48 pixel image from the frame
2213 * (there is a small border arround thats why the loops starts with one
2214 * instead zero) without any interpolation
2215 *****************************************************************************/
2216 static void CreateMiniImage( filter_t *p_filter, picture_t *p_inpic)
2218 filter_sys_t *p_sys = p_filter->p_sys;
2220 pointer to RGB Buffer created in external libary as safe array which
2221 is locked inside AtmoLockTransferBuffer
2223 uint8_t *p_transfer;
2224 #if defined( __ATMO_DEBUG__ )
2225 /* for debug out only used*/
2226 char sz_filename[MAX_PATH];
2227 #endif
2230 Lock the before created VarArray (AtmoCreateTransferBuffers)
2231 inside my wrapper library and give me a pointer to the buffer!
2232 below linux a global buffer may be used and protected with a mutex?
2234 p_transfer = AtmoLockTransferBuffer(p_filter);
2235 if(p_transfer == NULL)
2237 msg_Err( p_filter, "AtmoLight no transferbuffer available. "\
2238 "AtmoLight will be disabled!");
2239 p_sys->b_enabled = false;
2240 return;
2244 do the call via pointer to function instead of having a
2245 case structure here
2247 p_sys->pf_extract_mini_image(p_sys, p_inpic, p_transfer);
2250 #if defined( __ATMO_DEBUG__ )
2252 if debugging enabled save every 128th image to disk
2254 if((p_sys->b_saveframes == true) && (p_sys->sz_framepath[0] != 0 ))
2257 if((p_sys->ui_frame_counter & 127) == 0)
2259 sprintf(sz_filename,"%satmo_dbg_%06u.bmp",p_sys->sz_framepath,
2260 p_sys->ui_frame_counter);
2261 msg_Dbg(p_filter, "SaveFrame %s",sz_filename);
2263 SaveBitmap(p_sys, p_transfer, sz_filename);
2267 msg_Dbg( p_filter, "AtmoFrame %u Time: %d ms", p_sys->ui_frame_counter,
2268 mdate() / 1000);
2269 p_sys->ui_frame_counter++;
2270 #endif
2272 p_sys->i_frames_processed++;
2275 /* show the colors on the wall */
2276 AtmoSendPixelData( p_filter );
2282 /*****************************************************************************
2283 * Filter: calls the extract method and forwards the incomming picture 1:1
2284 *****************************************************************************
2286 *****************************************************************************/
2288 static picture_t * Filter( filter_t *p_filter, picture_t *p_pic )
2290 filter_sys_t *p_sys = p_filter->p_sys;
2291 if( !p_pic ) return NULL;
2293 vlc_mutex_lock( &p_sys->filter_lock );
2295 if((p_sys->b_enabled == true) &&
2296 (p_sys->pf_extract_mini_image != NULL) &&
2297 (p_sys->b_pause_live == false))
2299 p_sys->i_crop_x_offset = p_filter->fmt_in.video.i_x_offset;
2300 p_sys->i_crop_y_offset = p_filter->fmt_in.video.i_y_offset;
2301 p_sys->i_crop_width = p_filter->fmt_in.video.i_visible_width;
2302 p_sys->i_crop_height = p_filter->fmt_in.video.i_visible_height;
2304 CreateMiniImage(p_filter, p_pic);
2307 vlc_mutex_unlock( &p_sys->filter_lock );
2311 return p_pic;
2315 /*****************************************************************************
2316 * FadeToColorThread: Threadmethod which changes slowly the color
2317 * to a target color defined in p_fadethread struct
2318 * use for: Fade to Pause Color, and Fade to End Color
2319 *****************************************************************************/
2320 static void *FadeToColorThread(vlc_object_t *obj)
2322 fadethread_t *p_fadethread = (fadethread_t *)obj;
2323 filter_sys_t *p_sys = (filter_sys_t *)p_fadethread->p_filter->p_sys;
2324 int i_steps_done = 0;
2325 int i_index;
2326 int i_pause_red;
2327 int i_pause_green;
2328 int i_pause_blue;
2330 int i_src_red;
2331 int i_src_green;
2332 int i_src_blue;
2334 uint8_t *p_source = NULL;
2336 int canc = vlc_savecancel ();
2337 /* initialize AtmoWin for this thread! */
2338 AtmoInitialize(p_fadethread->p_filter , true);
2340 uint8_t *p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
2341 if(p_transfer != NULL) {
2342 /* safe colors as "32bit" Integers to avoid overflows*/
2343 i_pause_red = p_fadethread->ui_red;
2344 i_pause_blue = p_fadethread->ui_blue;
2345 i_pause_green = p_fadethread->ui_green;
2348 allocate a temporary buffer for the last send
2349 image size less then 15kb
2351 int i_size = 4 * p_sys->i_atmo_width * p_sys->i_atmo_height;
2352 p_source = (uint8_t *)malloc( i_size );
2353 if(p_source != NULL)
2356 get a copy of the last transfered image as orign for the
2357 fading steps...
2359 memcpy(p_source, p_transfer, i_size);
2360 /* send the same pixel data again... to unlock the buffer! */
2361 AtmoSendPixelData( p_fadethread->p_filter );
2363 while( (vlc_object_alive (p_fadethread)) &&
2364 (i_steps_done < p_fadethread->i_steps))
2366 p_transfer = AtmoLockTransferBuffer( p_fadethread->p_filter );
2367 if(!p_transfer) break; /* should not happen if it worked
2368 one time in the code above! */
2369 i_steps_done++;
2371 move all pixels in the mini image (64x48) one step closer to
2372 the desired color these loop takes the most time of this
2373 thread improvements wellcome!
2375 for(i_index = 0;
2376 (i_index < i_size) && (vlc_object_alive (p_fadethread));
2377 i_index+=4)
2379 i_src_blue = p_source[i_index+0];
2380 i_src_green = p_source[i_index+1];
2381 i_src_red = p_source[i_index+2];
2382 p_transfer[i_index+0] = (uint8_t) (((
2383 (i_pause_blue - i_src_blue)
2384 * i_steps_done)/p_fadethread->i_steps)
2385 + i_src_blue);
2387 p_transfer[i_index+1] = (uint8_t) (((
2388 (i_pause_green - i_src_green)
2389 * i_steps_done)/p_fadethread->i_steps)
2390 + i_src_green);
2392 p_transfer[i_index+2] = (uint8_t) (((
2393 (i_pause_red - i_src_red)
2394 * i_steps_done)/p_fadethread->i_steps)
2395 + i_src_red);
2398 /* send image to lightcontroller */
2399 AtmoSendPixelData( p_fadethread->p_filter );
2400 /* is there something like and interruptable sleep inside
2401 the VLC libaries? inside native win32 I would use an Event
2402 (CreateEvent) and here an WaitForSingleObject?
2404 msleep(40000);
2406 free(p_source);
2407 } else {
2408 /* in failure of malloc also unlock buffer */
2409 AtmoSendPixelData(p_fadethread->p_filter);
2412 /* call indirect to OleUnitialize() for this thread */
2413 AtmoFinalize(p_fadethread->p_filter, 0);
2414 vlc_restorecancel (canc);
2415 return NULL;
2418 /*****************************************************************************
2419 * CheckAndStopFadeThread: if there is a fadethread structure left, or running.
2420 ******************************************************************************
2421 * this function will stop the thread ... and waits for its termination
2422 * before removeing the objects from vout_sys_t ...
2423 ******************************************************************************/
2424 static void CheckAndStopFadeThread(filter_t *p_filter)
2426 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
2427 vlc_mutex_lock( &p_sys->filter_lock );
2428 if(p_sys->p_fadethread != NULL)
2430 msg_Dbg(p_filter, "kill still running fadeing thread...");
2432 p_sys->p_fadethread->b_die = true;
2434 vlc_thread_join(p_sys->p_fadethread);
2436 vlc_object_release(p_sys->p_fadethread);
2437 p_sys->p_fadethread = NULL;
2439 vlc_mutex_unlock( &p_sys->filter_lock );
2442 /*****************************************************************************
2443 * StateCallback: Callback for the inputs variable "State" to get notified
2444 * about Pause and Continue Playback events.
2445 *****************************************************************************/
2446 static int StateCallback( vlc_object_t *p_this, char const *psz_cmd,
2447 vlc_value_t oldval, vlc_value_t newval,
2448 void *p_data )
2450 filter_t *p_filter = (filter_t *)p_data;
2451 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
2453 if((p_sys->b_usepausecolor == true) && (p_sys->b_enabled == true))
2455 msg_Dbg(p_filter, "state change from: %"PRId64" to %"PRId64, oldval.i_int,
2456 newval.i_int);
2458 if((newval.i_int == PAUSE_S) && (oldval.i_int == PLAYING_S))
2460 /* tell the other thread to stop sending images to light
2461 controller */
2462 p_sys->b_pause_live = true;
2464 // clean up old thread - should not happen....
2465 CheckAndStopFadeThread( p_filter );
2467 // perpare spawn fadeing thread
2468 vlc_mutex_lock( &p_sys->filter_lock );
2470 launch only a new thread if there is none active!
2471 or waiting for cleanup
2473 if(p_sys->p_fadethread == NULL)
2475 p_sys->p_fadethread = (fadethread_t *)vlc_object_create(
2476 p_filter,
2477 sizeof(fadethread_t) );
2479 p_sys->p_fadethread->p_filter = p_filter;
2480 p_sys->p_fadethread->ui_red = p_sys->ui_pausecolor_red;
2481 p_sys->p_fadethread->ui_green = p_sys->ui_pausecolor_green;
2482 p_sys->p_fadethread->ui_blue = p_sys->ui_pausecolor_blue;
2483 p_sys->p_fadethread->i_steps = p_sys->i_fadesteps;
2485 if( vlc_thread_create( p_sys->p_fadethread,
2486 "AtmoLight fadeing",
2487 FadeToColorThread,
2488 VLC_THREAD_PRIORITY_LOW ) )
2490 msg_Err( p_filter, "cannot create FadeToColorThread" );
2491 vlc_object_release( p_sys->p_fadethread );
2492 p_sys->p_fadethread = NULL;
2495 vlc_mutex_unlock( &p_sys->filter_lock );
2498 if((newval.i_int == PLAYING_S) && (oldval.i_int == PAUSE_S))
2500 /* playback continues check thread state */
2501 CheckAndStopFadeThread( p_filter );
2502 /* reactivate the Render function... to do its normal work */
2503 p_sys->b_pause_live = false;
2507 return VLC_SUCCESS;
2510 /*****************************************************************************
2511 * AddPlaylistInputThreadStateCallback: Setup call back on "State" Variable
2512 *****************************************************************************
2513 * Add Callback function to the "state" variable of the input thread..
2514 * first find the PlayList and get the input thread from there to attach
2515 * my callback?
2516 *****************************************************************************/
2517 static void AddStateVariableCallback(filter_t *p_filter)
2519 input_thread_t *p_input = playlist_CurrentInput( pl_Get( p_filter ) );
2520 if(p_input)
2522 var_AddCallback( p_input, "state", StateCallback, p_filter );
2523 vlc_object_release( p_input );
2527 /*****************************************************************************
2528 * DelPlaylistInputThreadStateCallback: Remove call back on "State" Variable
2529 *****************************************************************************
2530 * Delete the callback function to the "state" variable of the input thread...
2531 * first find the PlayList and get the input thread from there to attach
2532 * my callback? is vlc_object_find the right way for this??
2533 *****************************************************************************/
2534 static void DelStateVariableCallback( filter_t *p_filter )
2536 input_thread_t *p_input = playlist_CurrentInput( pl_Get ( p_filter ) );
2537 if(p_input)
2539 var_DelCallback( p_input, "state", StateCallback, p_filter );
2540 vlc_object_release( p_input );
2544 /****************************************************************************
2545 * StateCallback: Callback for the inputs variable "State" to get notified
2546 * about Pause and Continue Playback events.
2547 *****************************************************************************/
2548 static int AtmoSettingsCallback( vlc_object_t *p_this, char const *psz_var,
2549 vlc_value_t oldval, vlc_value_t newval,
2550 void *p_data )
2552 filter_t *p_filter = (filter_t *)p_data;
2553 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
2555 vlc_mutex_lock( &p_sys->filter_lock );
2557 if( !strcmp( psz_var, CFG_PREFIX "showdots" ))
2559 p_sys->b_show_dots = newval.b_bool;
2562 CAtmoConfig *p_atmo_config = p_sys->p_atmo_config;
2563 if(p_atmo_config)
2566 msg_Dbg(p_filter, "apply AtmoSettingsCallback %s (int: %"PRId64" -> %"PRId64")",
2567 psz_var,
2568 oldval.i_int,
2569 newval.i_int
2572 if( !strcmp( psz_var, CFG_PREFIX "filtermode" ))
2573 p_atmo_config->setLiveViewFilterMode( (AtmoFilterMode)newval.i_int);
2575 else if( !strcmp( psz_var, CFG_PREFIX "percentnew" ))
2576 p_atmo_config->setLiveViewFilter_PercentNew( newval.i_int );
2578 else if( !strcmp( psz_var, CFG_PREFIX "meanlength" ))
2579 p_atmo_config->setLiveViewFilter_MeanLength( newval.i_int );
2581 else if( !strcmp( psz_var, CFG_PREFIX "meanthreshold" ))
2582 p_atmo_config->setLiveViewFilter_MeanThreshold( newval.i_int );
2584 else if( !strcmp( psz_var, CFG_PREFIX "edgeweightning" ))
2585 p_atmo_config->setLiveView_EdgeWeighting( newval.i_int );
2587 else if( !strcmp( psz_var, CFG_PREFIX "brightness" ))
2588 p_atmo_config->setLiveView_BrightCorrect( newval.i_int );
2590 else if( !strcmp( psz_var, CFG_PREFIX "darknesslimit" ))
2591 p_atmo_config->setLiveView_DarknessLimit( newval.i_int );
2593 else if( !strcmp( psz_var, CFG_PREFIX "huewinsize" ))
2594 p_atmo_config->setLiveView_HueWinSize( newval.i_int );
2596 else if( !strcmp( psz_var, CFG_PREFIX "satwinsize" ))
2597 p_atmo_config->setLiveView_SatWinSize( newval.i_int );
2599 else if( !strcmp( psz_var, CFG_PREFIX "framedelay" ))
2600 p_atmo_config->setLiveView_FrameDelay( newval.i_int );
2602 else if( !strcmp( psz_var, CFG_PREFIX "whiteadj" ))
2603 p_atmo_config->setUseSoftwareWhiteAdj( newval.b_bool );
2605 else if( !strcmp( psz_var, CFG_PREFIX "white-red" ))
2606 p_atmo_config->setWhiteAdjustment_Red( newval.i_int );
2608 else if( !strcmp( psz_var, CFG_PREFIX "white-green" ))
2609 p_atmo_config->setWhiteAdjustment_Green( newval.i_int );
2611 else if( !strcmp( psz_var, CFG_PREFIX "white-blue" ))
2612 p_atmo_config->setWhiteAdjustment_Blue( newval.i_int );
2616 vlc_mutex_unlock( &p_sys->filter_lock );
2618 return VLC_SUCCESS;
2621 static void AddAtmoSettingsVariablesCallbacks(filter_t *p_filter)
2623 var_AddCallback( p_filter, CFG_PREFIX "filtermode",
2624 AtmoSettingsCallback, p_filter );
2625 var_AddCallback( p_filter, CFG_PREFIX "percentnew",
2626 AtmoSettingsCallback, p_filter );
2629 var_AddCallback( p_filter, CFG_PREFIX "meanlength",
2630 AtmoSettingsCallback, p_filter );
2631 var_AddCallback( p_filter, CFG_PREFIX "meanthreshold",
2632 AtmoSettingsCallback, p_filter );
2634 var_AddCallback( p_filter, CFG_PREFIX "edgeweightning",
2635 AtmoSettingsCallback, p_filter );
2636 var_AddCallback( p_filter, CFG_PREFIX "brightness",
2637 AtmoSettingsCallback, p_filter );
2638 var_AddCallback( p_filter, CFG_PREFIX "darknesslimit",
2639 AtmoSettingsCallback, p_filter );
2641 var_AddCallback( p_filter, CFG_PREFIX "huewinsize",
2642 AtmoSettingsCallback, p_filter );
2643 var_AddCallback( p_filter, CFG_PREFIX "satwinsize",
2644 AtmoSettingsCallback, p_filter );
2645 var_AddCallback( p_filter, CFG_PREFIX "framedelay",
2646 AtmoSettingsCallback, p_filter );
2649 var_AddCallback( p_filter, CFG_PREFIX "whiteadj",
2650 AtmoSettingsCallback, p_filter );
2651 var_AddCallback( p_filter, CFG_PREFIX "white-red",
2652 AtmoSettingsCallback, p_filter );
2653 var_AddCallback( p_filter, CFG_PREFIX "white-green",
2654 AtmoSettingsCallback, p_filter );
2655 var_AddCallback( p_filter, CFG_PREFIX "white-blue",
2656 AtmoSettingsCallback, p_filter );
2658 var_AddCallback( p_filter, CFG_PREFIX "showdots",
2659 AtmoSettingsCallback, p_filter );
2663 static void DelAtmoSettingsVariablesCallbacks( filter_t *p_filter )
2666 var_DelCallback( p_filter, CFG_PREFIX "filtermode",
2667 AtmoSettingsCallback, p_filter );
2669 var_DelCallback( p_filter, CFG_PREFIX "percentnew",
2670 AtmoSettingsCallback, p_filter );
2671 var_DelCallback( p_filter, CFG_PREFIX "meanlength",
2672 AtmoSettingsCallback, p_filter );
2673 var_DelCallback( p_filter, CFG_PREFIX "meanthreshold",
2674 AtmoSettingsCallback, p_filter );
2676 var_DelCallback( p_filter, CFG_PREFIX "edgeweightning",
2677 AtmoSettingsCallback, p_filter );
2678 var_DelCallback( p_filter, CFG_PREFIX "brightness",
2679 AtmoSettingsCallback, p_filter );
2680 var_DelCallback( p_filter, CFG_PREFIX "darknesslimit",
2681 AtmoSettingsCallback, p_filter );
2683 var_DelCallback( p_filter, CFG_PREFIX "huewinsize",
2684 AtmoSettingsCallback, p_filter );
2685 var_DelCallback( p_filter, CFG_PREFIX "satwinsize",
2686 AtmoSettingsCallback, p_filter );
2687 var_DelCallback( p_filter, CFG_PREFIX "framedelay",
2688 AtmoSettingsCallback, p_filter );
2691 var_DelCallback( p_filter, CFG_PREFIX "whiteadj",
2692 AtmoSettingsCallback, p_filter );
2693 var_DelCallback( p_filter, CFG_PREFIX "white-red",
2694 AtmoSettingsCallback, p_filter );
2695 var_DelCallback( p_filter, CFG_PREFIX "white-green",
2696 AtmoSettingsCallback, p_filter );
2697 var_DelCallback( p_filter, CFG_PREFIX "white-blue",
2698 AtmoSettingsCallback, p_filter );
2700 var_DelCallback( p_filter, CFG_PREFIX "showdots",
2701 AtmoSettingsCallback, p_filter );
2706 #if defined(__ATMO_DEBUG__)
2707 static void atmo_parse_crop(char *psz_cropconfig,
2708 video_format_t fmt_in,
2709 video_format_t fmt_render,
2710 int &i_visible_width, int &i_visible_height,
2711 int &i_x_offset, int &i_y_offset )
2713 int64_t i_aspect_num, i_aspect_den;
2714 unsigned int i_width, i_height;
2716 i_visible_width = fmt_in.i_visible_width;
2717 i_visible_height = fmt_in.i_visible_height;
2718 i_x_offset = fmt_in.i_x_offset;
2719 i_y_offset = fmt_in.i_y_offset;
2721 char *psz_end = NULL, *psz_parser = strchr( psz_cropconfig, ':' );
2722 if( psz_parser )
2724 /* We're using the 3:4 syntax */
2725 i_aspect_num = strtol( psz_cropconfig, &psz_end, 10 );
2726 if( psz_end == psz_cropconfig || !i_aspect_num ) return;
2728 i_aspect_den = strtol( ++psz_parser, &psz_end, 10 );
2729 if( psz_end == psz_parser || !i_aspect_den ) return;
2731 i_width = fmt_in.i_sar_den * fmt_render.i_visible_height *
2732 i_aspect_num / i_aspect_den / fmt_in.i_sar_num;
2734 i_height = fmt_render.i_visible_width*fmt_in.i_sar_num *
2735 i_aspect_den / i_aspect_num / fmt_in.i_sar_den;
2737 if( i_width < fmt_render.i_visible_width )
2739 i_x_offset = fmt_render.i_x_offset +
2740 (fmt_render.i_visible_width - i_width) / 2;
2741 i_visible_width = i_width;
2743 else
2745 i_y_offset = fmt_render.i_y_offset +
2746 (fmt_render.i_visible_height - i_height) / 2;
2747 i_visible_height = i_height;
2750 else
2752 psz_parser = strchr( psz_cropconfig, 'x' );
2753 if( psz_parser )
2755 /* Maybe we're using the <width>x<height>+<left>+<top> syntax */
2756 unsigned int i_crop_width, i_crop_height, i_crop_top, i_crop_left;
2758 i_crop_width = strtol( psz_cropconfig, &psz_end, 10 );
2759 if( psz_end != psz_parser ) return;
2761 psz_parser = strchr( ++psz_end, '+' );
2762 i_crop_height = strtol( psz_end, &psz_end, 10 );
2763 if( psz_end != psz_parser ) return;
2765 psz_parser = strchr( ++psz_end, '+' );
2766 i_crop_left = strtol( psz_end, &psz_end, 10 );
2767 if( psz_end != psz_parser ) return;
2769 psz_end++;
2770 i_crop_top = strtol( psz_end, &psz_end, 10 );
2771 if( *psz_end != '\0' ) return;
2773 i_width = i_crop_width;
2774 i_visible_width = i_width;
2776 i_height = i_crop_height;
2777 i_visible_height = i_height;
2779 i_x_offset = i_crop_left;
2780 i_y_offset = i_crop_top;
2782 else
2784 /* Maybe we're using the <left>+<top>+<right>+<bottom> syntax */
2785 unsigned int i_crop_top, i_crop_left, i_crop_bottom, i_crop_right;
2787 psz_parser = strchr( psz_cropconfig, '+' );
2788 i_crop_left = strtol( psz_cropconfig, &psz_end, 10 );
2789 if( psz_end != psz_parser ) return;
2791 psz_parser = strchr( ++psz_end, '+' );
2792 i_crop_top = strtol( psz_end, &psz_end, 10 );
2793 if( psz_end != psz_parser ) return;
2795 psz_parser = strchr( ++psz_end, '+' );
2796 i_crop_right = strtol( psz_end, &psz_end, 10 );
2797 if( psz_end != psz_parser ) return;
2799 psz_end++;
2800 i_crop_bottom = strtol( psz_end, &psz_end, 10 );
2801 if( *psz_end != '\0' ) return;
2803 i_width = fmt_render.i_visible_width -
2804 i_crop_left -
2805 i_crop_right;
2806 i_visible_width = i_width;
2808 i_height = fmt_render.i_visible_height -
2809 i_crop_top -
2810 i_crop_bottom;
2811 i_visible_height = i_height;
2813 i_x_offset = i_crop_left;
2814 i_y_offset = i_crop_top;
2818 #endif