]> git.sesse.net Git - vlc/blob - src/video_output/vout_intf.c
sftp: change item b_net
[vlc] / src / video_output / vout_intf.c
1 /*****************************************************************************
2  * vout_intf.c : video output interface
3  *****************************************************************************
4  * Copyright (C) 2000-2007 VLC authors and VideoLAN
5  *
6  * Authors: Gildas Bazin <gbazin@videolan.org>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32
33 #include <stdio.h>
34 #include <stdlib.h>                                                /* free() */
35 #include <assert.h>
36
37 #include <vlc_block.h>
38 #include <vlc_modules.h>
39
40 #include <vlc_vout.h>
41 #include <vlc_vout_osd.h>
42 #include <vlc_strings.h>
43 #include <vlc_charset.h>
44 #include "vout_internal.h"
45
46 /*****************************************************************************
47  * Local prototypes
48  *****************************************************************************/
49 /* Object variables callbacks */
50 static int CropCallback( vlc_object_t *, char const *,
51                          vlc_value_t, vlc_value_t, void * );
52 static int CropBorderCallback( vlc_object_t *, char const *,
53                                vlc_value_t, vlc_value_t, void * );
54 static int AspectCallback( vlc_object_t *, char const *,
55                            vlc_value_t, vlc_value_t, void * );
56 static int AutoScaleCallback( vlc_object_t *, char const *,
57                               vlc_value_t, vlc_value_t, void * );
58 static int ZoomCallback( vlc_object_t *, char const *,
59                          vlc_value_t, vlc_value_t, void * );
60 static int AboveCallback( vlc_object_t *, char const *,
61                           vlc_value_t, vlc_value_t, void * );
62 static int WallPaperCallback( vlc_object_t *, char const *,
63                               vlc_value_t, vlc_value_t, void * );
64 static int FullscreenCallback( vlc_object_t *, char const *,
65                                vlc_value_t, vlc_value_t, void * );
66 static int SnapshotCallback( vlc_object_t *, char const *,
67                              vlc_value_t, vlc_value_t, void * );
68 static int VideoFilterCallback( vlc_object_t *, char const *,
69                                 vlc_value_t, vlc_value_t, void * );
70 static int SubSourceCallback( vlc_object_t *, char const *,
71                               vlc_value_t, vlc_value_t, void * );
72 static int SubFilterCallback( vlc_object_t *, char const *,
73                               vlc_value_t, vlc_value_t, void * );
74 static int SubMarginCallback( vlc_object_t *, char const *,
75                               vlc_value_t, vlc_value_t, void * );
76
77 /*****************************************************************************
78  * vout_IntfInit: called during the vout creation to initialise misc things.
79  *****************************************************************************/
80 static const struct
81 {
82     double f_value;
83     char psz_label[13];
84 } p_zoom_values[] = {
85     { 0.25, N_("1:4 Quarter") },
86     { 0.5, N_("1:2 Half") },
87     { 1, N_("1:1 Original") },
88     { 2, N_("2:1 Double") },
89 };
90
91 static const struct
92 {
93     char psz_value[8];
94     char psz_label[8];
95 } p_crop_values[] = {
96     { "", N_("Default") },
97     { "16:10", "16:10" },
98     { "16:9", "16:9" },
99     { "4:3", "4:3" },
100     { "185:100", "1.85:1" },
101     { "221:100", "2.21:1" },
102     { "235:100", "2.35:1" },
103     { "239:100", "2.39:1" },
104     { "5:3", "5:3" },
105     { "5:4", "5:4" },
106     { "1:1", "1:1" },
107 };
108
109 static const struct
110 {
111     char psz_value[8];
112     char psz_label[8];
113 } p_aspect_ratio_values[] = {
114     { "", N_("Default") },
115     { "16:9", "16:9" },
116     { "4:3", "4:3" },
117     { "1:1", "1:1" },
118     { "16:10", "16:10" },
119     { "221:100", "2.21:1" },
120     { "235:100", "2.35:1" },
121     { "239:100", "2.39:1" },
122     { "5:4", "5:4" },
123 };
124
125 static void AddCustomRatios( vout_thread_t *p_vout, const char *psz_var,
126                              char *psz_list )
127 {
128     assert( psz_list );
129
130     char *psz_cur = psz_list;
131     char *psz_next;
132     while( psz_cur && *psz_cur )
133     {
134         vlc_value_t val, text;
135         psz_next = strchr( psz_cur, ',' );
136         if( psz_next )
137         {
138             *psz_next = '\0';
139             psz_next++;
140         }
141         val.psz_string = psz_cur;
142         text.psz_string = psz_cur;
143         var_Change( p_vout, psz_var, VLC_VAR_ADDCHOICE, &val, &text);
144         psz_cur = psz_next;
145     }
146 }
147
148 void vout_IntfInit( vout_thread_t *p_vout )
149 {
150     vlc_value_t val, text;
151     char *psz_buf;
152
153     /* Create a few object variables we'll need later on */
154     var_Create( p_vout, "snapshot-num", VLC_VAR_INTEGER );
155     var_SetInteger( p_vout, "snapshot-num", 1 );
156
157     var_Create( p_vout, "width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
158     var_Create( p_vout, "height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
159     var_Create( p_vout, "align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
160
161     var_Create( p_vout, "mouse-hide-timeout",
162                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
163
164     /* Add variables to manage scaling video */
165     var_Create( p_vout, "autoscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
166                 | VLC_VAR_ISCOMMAND );
167     text.psz_string = _("Autoscale video");
168     var_Change( p_vout, "autoscale", VLC_VAR_SETTEXT, &text, NULL );
169     var_AddCallback( p_vout, "autoscale", AutoScaleCallback, NULL );
170
171     var_Create( p_vout, "zoom", VLC_VAR_FLOAT | VLC_VAR_ISCOMMAND |
172                 VLC_VAR_DOINHERIT );
173
174     text.psz_string = _("Zoom");
175     var_Change( p_vout, "zoom", VLC_VAR_SETTEXT, &text, NULL );
176
177     for( size_t i = 0; i < ARRAY_SIZE(p_zoom_values); i++ )
178     {
179         val.f_float = p_zoom_values[i].f_value;
180         text.psz_string = vlc_gettext( p_zoom_values[i].psz_label );
181         var_Change( p_vout, "zoom", VLC_VAR_ADDCHOICE, &val, &text );
182     }
183
184     var_AddCallback( p_vout, "zoom", ZoomCallback, NULL );
185
186     /* Crop offset vars */
187     var_Create( p_vout, "crop-left", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
188     var_Create( p_vout, "crop-top", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
189     var_Create( p_vout, "crop-right", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
190     var_Create( p_vout, "crop-bottom", VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND );
191
192     var_AddCallback( p_vout, "crop-left", CropBorderCallback, NULL );
193     var_AddCallback( p_vout, "crop-top", CropBorderCallback, NULL );
194     var_AddCallback( p_vout, "crop-right", CropBorderCallback, NULL );
195     var_AddCallback( p_vout, "crop-bottom", CropBorderCallback, NULL );
196
197     /* Crop object var */
198     var_Create( p_vout, "crop", VLC_VAR_STRING | VLC_VAR_ISCOMMAND |
199                 VLC_VAR_DOINHERIT );
200
201     text.psz_string = _("Crop");
202     var_Change( p_vout, "crop", VLC_VAR_SETTEXT, &text, NULL );
203
204     for( size_t i = 0; i < ARRAY_SIZE(p_crop_values); i++ )
205     {
206         val.psz_string = (char*)p_crop_values[i].psz_value;
207         text.psz_string = _( p_crop_values[i].psz_label );
208         var_Change( p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &text );
209     }
210
211     /* Add custom crop ratios */
212     psz_buf = var_CreateGetNonEmptyString( p_vout, "custom-crop-ratios" );
213     if( psz_buf )
214     {
215         AddCustomRatios( p_vout, "crop", psz_buf );
216         free( psz_buf );
217     }
218
219     var_AddCallback( p_vout, "crop", CropCallback, NULL );
220
221     /* Monitor pixel aspect-ratio */
222     var_Create( p_vout, "monitor-par", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
223
224     /* Aspect-ratio object var */
225     var_Create( p_vout, "aspect-ratio", VLC_VAR_STRING | VLC_VAR_ISCOMMAND |
226                 VLC_VAR_DOINHERIT );
227
228     text.psz_string = _("Aspect ratio");
229     var_Change( p_vout, "aspect-ratio", VLC_VAR_SETTEXT, &text, NULL );
230
231     for( size_t i = 0; i < ARRAY_SIZE(p_aspect_ratio_values); i++ )
232     {
233         val.psz_string = (char*)p_aspect_ratio_values[i].psz_value;
234         text.psz_string = _( p_aspect_ratio_values[i].psz_label );
235         var_Change( p_vout, "aspect-ratio", VLC_VAR_ADDCHOICE, &val, &text );
236     }
237
238     /* Add custom aspect ratios */
239     psz_buf = var_CreateGetNonEmptyString( p_vout, "custom-aspect-ratios" );
240     if( psz_buf )
241     {
242         AddCustomRatios( p_vout, "aspect-ratio", psz_buf );
243         free( psz_buf );
244     }
245
246     var_AddCallback( p_vout, "aspect-ratio", AspectCallback, NULL );
247
248     /* Add a variable to indicate if the window should be on top of others */
249     var_Create( p_vout, "video-on-top", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
250                 | VLC_VAR_ISCOMMAND );
251     text.psz_string = _("Always on top");
252     var_Change( p_vout, "video-on-top", VLC_VAR_SETTEXT, &text, NULL );
253     var_AddCallback( p_vout, "video-on-top", AboveCallback, NULL );
254
255     /* Add a variable to indicate if the window should be below all others */
256     var_Create( p_vout, "video-wallpaper", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
257     var_AddCallback( p_vout, "video-wallpaper", WallPaperCallback,
258                      (void *)(uintptr_t)VOUT_WINDOW_STATE_BELOW );
259
260     /* Add a variable to indicate whether we want window decoration or not */
261     var_Create( p_vout, "video-deco", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
262
263     /* Add a fullscreen variable */
264     var_Create( p_vout, "fullscreen",
265                 VLC_VAR_BOOL | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
266     text.psz_string = _("Fullscreen");
267     var_Change( p_vout, "fullscreen", VLC_VAR_SETTEXT, &text, NULL );
268     var_AddCallback( p_vout, "fullscreen", FullscreenCallback, NULL );
269
270     /* Add a snapshot variable */
271     var_Create( p_vout, "video-snapshot", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
272     text.psz_string = _("Snapshot");
273     var_Change( p_vout, "video-snapshot", VLC_VAR_SETTEXT, &text, NULL );
274     var_AddCallback( p_vout, "video-snapshot", SnapshotCallback, NULL );
275
276     /* Add a video-filter variable */
277     var_Create( p_vout, "video-filter",
278                 VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
279     var_AddCallback( p_vout, "video-filter", VideoFilterCallback, NULL );
280
281     /* Add a sub-source variable */
282     var_Create( p_vout, "sub-source",
283                 VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
284     var_AddCallback( p_vout, "sub-source", SubSourceCallback, NULL );
285
286     /* Add a sub-filter variable */
287     var_Create( p_vout, "sub-filter",
288                 VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
289     var_AddCallback( p_vout, "sub-filter", SubFilterCallback, NULL );
290
291     /* Add sub-margin variable */
292     var_Create( p_vout, "sub-margin",
293                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
294     var_AddCallback( p_vout, "sub-margin", SubMarginCallback, NULL );
295
296     /* Mouse coordinates */
297     var_Create( p_vout, "mouse-button-down", VLC_VAR_INTEGER );
298     var_Create( p_vout, "mouse-moved", VLC_VAR_COORDS );
299     var_Create( p_vout, "mouse-clicked", VLC_VAR_COORDS );
300     var_Create( p_vout, "mouse-object", VLC_VAR_BOOL );
301
302     vout_IntfReinit( p_vout );
303 }
304
305 void vout_IntfReinit( vout_thread_t *p_vout )
306 {
307     var_TriggerCallback( p_vout, "zoom" );
308     var_TriggerCallback( p_vout, "crop" );
309     var_TriggerCallback( p_vout, "aspect-ratio" );
310
311     var_TriggerCallback( p_vout, "video-on-top" );
312     var_TriggerCallback( p_vout, "video-wallpaper" );
313
314     var_TriggerCallback( p_vout, "video-filter" );
315     var_TriggerCallback( p_vout, "sub-source" );
316     var_TriggerCallback( p_vout, "sub-filter" );
317     var_TriggerCallback( p_vout, "sub-margin" );
318 }
319
320 /*****************************************************************************
321  * vout_Snapshot: generates a snapshot.
322  *****************************************************************************/
323 /**
324  * This function will inject a subpicture into the vout with the provided
325  * picture
326  */
327 static int VoutSnapshotPip( vout_thread_t *p_vout, picture_t *p_pic )
328 {
329     subpicture_t *p_subpic = subpicture_NewFromPicture( VLC_OBJECT(p_vout),
330                                                         p_pic, VLC_CODEC_YUVA );
331     if( !p_subpic )
332         return VLC_EGENERIC;
333
334     /* FIXME SPU_DEFAULT_CHANNEL is not good (used by the text) but
335      * hardcoded 0 doesn't seem right */
336     p_subpic->i_channel = 0;
337     p_subpic->i_start = mdate();
338     p_subpic->i_stop  = p_subpic->i_start + 4000000;
339     p_subpic->b_ephemer = true;
340     p_subpic->b_fade = true;
341
342     /* Reduce the picture to 1/4^2 of the screen */
343     p_subpic->i_original_picture_width  *= 4;
344     p_subpic->i_original_picture_height *= 4;
345
346     vout_PutSubpicture( p_vout, p_subpic );
347     return VLC_SUCCESS;
348 }
349
350 /**
351  * This function will display the name and a PIP of the provided snapshot
352  */
353 static void VoutOsdSnapshot( vout_thread_t *p_vout, picture_t *p_pic, const char *psz_filename )
354 {
355     msg_Dbg( p_vout, "snapshot taken (%s)", psz_filename );
356     vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", psz_filename );
357
358     if( var_InheritBool( p_vout, "snapshot-preview" ) )
359     {
360         if( VoutSnapshotPip( p_vout, p_pic ) )
361             msg_Warn( p_vout, "Failed to display snapshot" );
362     }
363 }
364
365 /**
366  * This function will handle a snapshot request
367  */
368 static void VoutSaveSnapshot( vout_thread_t *p_vout )
369 {
370     char *psz_path = var_InheritString( p_vout, "snapshot-path" );
371     char *psz_format = var_InheritString( p_vout, "snapshot-format" );
372     char *psz_prefix = var_InheritString( p_vout, "snapshot-prefix" );
373
374     /* */
375     picture_t *p_picture;
376     block_t *p_image;
377     video_format_t fmt;
378
379     /* 500ms timeout
380      * XXX it will cause trouble with low fps video (< 2fps) */
381     if( vout_GetSnapshot( p_vout, &p_image, &p_picture, &fmt, psz_format, 500*1000 ) )
382     {
383         p_picture = NULL;
384         p_image = NULL;
385         goto exit;
386     }
387
388     if( !psz_path )
389     {
390         psz_path = vout_snapshot_GetDirectory();
391         if( !psz_path )
392         {
393             msg_Err( p_vout, "no path specified for snapshots" );
394             goto exit;
395         }
396     }
397
398     vout_snapshot_save_cfg_t cfg;
399     memset( &cfg, 0, sizeof(cfg) );
400     cfg.is_sequential = var_InheritBool( p_vout, "snapshot-sequential" );
401     cfg.sequence = var_GetInteger( p_vout, "snapshot-num" );
402     cfg.path = psz_path;
403     cfg.format = psz_format;
404     cfg.prefix_fmt = psz_prefix;
405
406     char *psz_filename;
407     int  i_sequence;
408     if (vout_snapshot_SaveImage( &psz_filename, &i_sequence,
409                                  p_image, p_vout, &cfg ) )
410         goto exit;
411     if( cfg.is_sequential )
412         var_SetInteger( p_vout, "snapshot-num", i_sequence + 1 );
413
414     VoutOsdSnapshot( p_vout, p_picture, psz_filename );
415
416     /* signal creation of a new snapshot file */
417     var_SetString( p_vout->p_libvlc, "snapshot-file", psz_filename );
418
419     free( psz_filename );
420
421 exit:
422     if( p_image )
423         block_Release( p_image );
424     if( p_picture )
425         picture_Release( p_picture );
426     free( psz_prefix );
427     free( psz_format );
428     free( psz_path );
429 }
430
431 /*****************************************************************************
432  * Handle filters
433  *****************************************************************************/
434
435 void vout_EnableFilter( vout_thread_t *p_vout, const char *psz_name,
436                         bool b_add, bool b_setconfig )
437 {
438     char *psz_parser;
439     char *psz_string;
440     const char *psz_filter_type;
441
442     module_t *p_obj = module_find( psz_name );
443     if( !p_obj )
444     {
445         msg_Err( p_vout, "Unable to find filter module \"%s\".", psz_name );
446         return;
447     }
448
449     if( module_provides( p_obj, "video filter2" ) )
450     {
451         psz_filter_type = "video-filter";
452     }
453     else if( module_provides( p_obj, "sub source" ) )
454     {
455         psz_filter_type = "sub-source";
456     }
457     else if( module_provides( p_obj, "sub filter" ) )
458     {
459         psz_filter_type = "sub-filter";
460     }
461     else
462     {
463         msg_Err( p_vout, "Unknown video filter type." );
464         return;
465     }
466
467     psz_string = var_GetString( p_vout, psz_filter_type );
468
469     /* Todo : Use some generic chain manipulation functions */
470     if( !psz_string ) psz_string = strdup("");
471
472     psz_parser = strstr( psz_string, psz_name );
473     if( b_add )
474     {
475         if( !psz_parser )
476         {
477             psz_parser = psz_string;
478             if( asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
479                           psz_string, psz_name ) == -1 )
480             {
481                 free( psz_parser );
482                 return;
483             }
484             free( psz_parser );
485         }
486         else
487         {
488             free( psz_string );
489             return;
490         }
491     }
492     else
493     {
494         if( psz_parser )
495         {
496             memmove( psz_parser, psz_parser + strlen(psz_name) +
497                             (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ),
498                             strlen(psz_parser + strlen(psz_name)) + 1 );
499
500             /* Remove trailing : : */
501             if( *(psz_string+strlen(psz_string ) -1 ) == ':' )
502             {
503                 *(psz_string+strlen(psz_string ) -1 ) = '\0';
504             }
505          }
506          else
507          {
508              free( psz_string );
509              return;
510          }
511     }
512
513     if( b_setconfig )
514     {
515         config_PutPsz( p_vout, psz_filter_type, psz_string );
516     }
517
518     var_SetString( p_vout, psz_filter_type, psz_string );
519
520     free( psz_string );
521 }
522
523 /*****************************************************************************
524  * Object variables callbacks
525  *****************************************************************************/
526 static int CropCallback( vlc_object_t *object, char const *cmd,
527                          vlc_value_t oldval, vlc_value_t newval, void *data )
528 {
529     vout_thread_t *vout = (vout_thread_t *)object;
530     VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
531     unsigned num, den;
532     unsigned y, x;
533     unsigned width, height;
534     unsigned left, top, right, bottom;
535
536     if (sscanf(newval.psz_string, "%u:%u", &num, &den) == 2) {
537         vout_ControlChangeCropRatio(vout, num, den);
538     } else if (sscanf(newval.psz_string, "%ux%u+%u+%u",
539                       &width, &height, &x, &y) == 4) {
540         vout_ControlChangeCropWindow(vout, x, y, width, height);
541     } else if (sscanf(newval.psz_string, "%u+%u+%u+%u",
542                     &left, &top, &right, &bottom) == 4) {
543         vout_ControlChangeCropBorder(vout, left, top, right, bottom);
544     } else if (*newval.psz_string == '\0') {
545         vout_ControlChangeCropRatio(vout, 0, 0);
546     } else {
547         msg_Err(object, "Unknown crop format (%s)", newval.psz_string);
548     }
549     return VLC_SUCCESS;
550 }
551
552 static int CropBorderCallback(vlc_object_t *object, char const *cmd,
553                               vlc_value_t oldval, vlc_value_t newval, void *data)
554 {
555     char buf[4 * 21];
556
557     snprintf(buf, sizeof (buf), "%"PRIu64"+%"PRIu64"+%"PRIu64"+%"PRIu64,
558              var_GetInteger(object, "crop-left"),
559              var_GetInteger(object, "crop-top"),
560              var_GetInteger(object, "crop-right"),
561              var_GetInteger(object, "crop-bottom"));
562     var_SetString(object, "crop", buf);
563
564     VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data); VLC_UNUSED(newval);
565     return VLC_SUCCESS;
566 }
567
568 static int AspectCallback( vlc_object_t *object, char const *cmd,
569                          vlc_value_t oldval, vlc_value_t newval, void *data )
570 {
571     vout_thread_t *vout = (vout_thread_t *)object;
572     VLC_UNUSED(cmd); VLC_UNUSED(oldval); VLC_UNUSED(data);
573     unsigned num, den;
574
575     if (sscanf(newval.psz_string, "%u:%u", &num, &den) == 2 &&
576         (num > 0) == (den > 0))
577         vout_ControlChangeSampleAspectRatio(vout, num, den);
578     else if (*newval.psz_string == '\0')
579         vout_ControlChangeSampleAspectRatio(vout, 0, 0);
580     return VLC_SUCCESS;
581 }
582
583 static int AutoScaleCallback( vlc_object_t *obj, char const *name,
584                               vlc_value_t prev, vlc_value_t cur, void *data )
585 {
586     vout_thread_t *p_vout = (vout_thread_t *)obj;
587
588     (void) name; (void) prev; (void) data;
589     vout_ControlChangeDisplayFilled( p_vout, cur.b_bool );
590     return VLC_SUCCESS;
591 }
592
593 static int ZoomCallback( vlc_object_t *obj, char const *name,
594                          vlc_value_t prev, vlc_value_t cur, void *data )
595 {
596     vout_thread_t *p_vout = (vout_thread_t *)obj;
597
598     (void) name; (void) prev; (void) data;
599     vout_ControlChangeZoom( p_vout, 1000 * cur.f_float, 1000 );
600     return VLC_SUCCESS;
601 }
602
603 static int AboveCallback( vlc_object_t *obj, char const *name,
604                           vlc_value_t prev, vlc_value_t cur, void *data )
605 {
606     vout_ControlChangeWindowState( (vout_thread_t *)obj,
607         cur.b_bool ? VOUT_WINDOW_STATE_ABOVE : VOUT_WINDOW_STATE_NORMAL );
608     (void) name; (void) prev; (void) data;
609     return VLC_SUCCESS;
610 }
611
612 static int WallPaperCallback( vlc_object_t *obj, char const *name,
613                               vlc_value_t prev, vlc_value_t cur, void *data )
614 {
615     vout_thread_t *vout = (vout_thread_t *)obj;
616
617     if( cur.b_bool )
618     {
619         vout_ControlChangeWindowState( vout, VOUT_WINDOW_STATE_BELOW );
620         vout_ControlChangeFullscreen( vout, true );
621     }
622     else
623     {
624         var_TriggerCallback( obj, "fullscreen" );
625         var_TriggerCallback( obj, "video-on-top" );
626     }
627     (void) name; (void) prev; (void) data;
628     return VLC_SUCCESS;
629 }
630
631 static int FullscreenCallback( vlc_object_t *p_this, char const *psz_cmd,
632                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
633 {
634     vout_thread_t *p_vout = (vout_thread_t *)p_this;
635     (void)psz_cmd; (void)p_data;
636
637     if( oldval.b_bool != newval.b_bool )
638         vout_ControlChangeFullscreen( p_vout, newval.b_bool );
639     return VLC_SUCCESS;
640 }
641
642 static int SnapshotCallback( vlc_object_t *p_this, char const *psz_cmd,
643                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
644 {
645     vout_thread_t *p_vout = (vout_thread_t *)p_this;
646     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
647     VLC_UNUSED(newval); VLC_UNUSED(p_data);
648
649     VoutSaveSnapshot( p_vout );
650     return VLC_SUCCESS;
651 }
652
653 static int VideoFilterCallback( vlc_object_t *p_this, char const *psz_cmd,
654                                 vlc_value_t oldval, vlc_value_t newval, void *p_data)
655 {
656     vout_thread_t *p_vout = (vout_thread_t *)p_this;
657     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
658
659     vout_ControlChangeFilters( p_vout, newval.psz_string );
660     return VLC_SUCCESS;
661 }
662
663 static int SubSourceCallback( vlc_object_t *p_this, char const *psz_cmd,
664                               vlc_value_t oldval, vlc_value_t newval, void *p_data)
665 {
666     vout_thread_t *p_vout = (vout_thread_t *)p_this;
667     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
668
669     vout_ControlChangeSubSources( p_vout, newval.psz_string );
670     return VLC_SUCCESS;
671 }
672
673 static int SubFilterCallback( vlc_object_t *p_this, char const *psz_cmd,
674                               vlc_value_t oldval, vlc_value_t newval, void *p_data)
675 {
676     vout_thread_t *p_vout = (vout_thread_t *)p_this;
677     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
678
679     vout_ControlChangeSubFilters( p_vout, newval.psz_string );
680     return VLC_SUCCESS;
681 }
682
683 static int SubMarginCallback( vlc_object_t *p_this, char const *psz_cmd,
684                               vlc_value_t oldval, vlc_value_t newval, void *p_data)
685 {
686     vout_thread_t *p_vout = (vout_thread_t *)p_this;
687     VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
688
689     vout_ControlChangeSubMargin( p_vout, newval.i_int );
690     return VLC_SUCCESS;
691 }
692