libvlc: add renderer_discoverer external API
[vlc.git] / lib / video.c
1 /*****************************************************************************
2  * video.c: libvlc new API video functions
3  *****************************************************************************
4  * Copyright (C) 2005-2010 VLC authors and VideoLAN
5  *
6  * $Id$
7  *
8  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
9  *          Filippo Carone <littlejohn@videolan.org>
10  *          Jean-Paul Saman <jpsaman _at_ m2x _dot_ nl>
11  *          Damien Fouilleul <damienf a_t videolan dot org>
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU Lesser General Public License as published by
15  * the Free Software Foundation; either version 2.1 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU Lesser General Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc/libvlc.h>
33 #include <vlc/libvlc_media.h>
34 #include <vlc/libvlc_media_player.h>
35
36 #include <vlc_common.h>
37 #include <vlc_input.h>
38 #include <vlc_vout.h>
39
40 #include "media_player_internal.h"
41 #include <math.h>
42 #include <assert.h>
43
44 /*
45  * Remember to release the returned vout_thread_t.
46  */
47 static vout_thread_t **GetVouts( libvlc_media_player_t *p_mi, size_t *n )
48 {
49     input_thread_t *p_input = libvlc_get_input_thread( p_mi );
50     if( !p_input )
51     {
52         *n = 0;
53         return NULL;
54     }
55
56     vout_thread_t **pp_vouts;
57     if (input_Control( p_input, INPUT_GET_VOUTS, &pp_vouts, n))
58     {
59         *n = 0;
60         pp_vouts = NULL;
61     }
62     vlc_object_release (p_input);
63     return pp_vouts;
64 }
65
66 static vout_thread_t *GetVout (libvlc_media_player_t *mp, size_t num)
67 {
68     vout_thread_t *p_vout = NULL;
69     size_t n;
70     vout_thread_t **pp_vouts = GetVouts (mp, &n);
71     if (pp_vouts == NULL)
72         goto err;
73
74     if (num < n)
75         p_vout = pp_vouts[num];
76
77     for (size_t i = 0; i < n; i++)
78         if (i != num)
79             vlc_object_release (pp_vouts[i]);
80     free (pp_vouts);
81
82     if (p_vout == NULL)
83 err:
84         libvlc_printerr ("Video output not active");
85     return p_vout;
86 }
87
88 /**********************************************************************
89  * Exported functions
90  **********************************************************************/
91
92 void libvlc_set_fullscreen( libvlc_media_player_t *p_mi, int b_fullscreen )
93 {
94     /* This will work even if the video is not currently active */
95     var_SetBool (p_mi, "fullscreen", !!b_fullscreen);
96
97     /* Apply to current video outputs (if any) */
98     size_t n;
99     vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
100     for (size_t i = 0; i < n; i++)
101     {
102         var_SetBool (pp_vouts[i], "fullscreen", b_fullscreen);
103         vlc_object_release (pp_vouts[i]);
104     }
105     free (pp_vouts);
106 }
107
108 int libvlc_get_fullscreen( libvlc_media_player_t *p_mi )
109 {
110     return var_GetBool (p_mi, "fullscreen");
111 }
112
113 void libvlc_toggle_fullscreen( libvlc_media_player_t *p_mi )
114 {
115     bool b_fullscreen = var_ToggleBool (p_mi, "fullscreen");
116
117     /* Apply to current video outputs (if any) */
118     size_t n;
119     vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
120     for (size_t i = 0; i < n; i++)
121     {
122         vout_thread_t *p_vout = pp_vouts[i];
123
124         var_SetBool (p_vout, "fullscreen", b_fullscreen);
125         vlc_object_release (p_vout);
126     }
127     free (pp_vouts);
128 }
129
130 void libvlc_video_set_key_input( libvlc_media_player_t *p_mi, unsigned on )
131 {
132     var_SetBool (p_mi, "keyboard-events", !!on);
133 }
134
135 void libvlc_video_set_mouse_input( libvlc_media_player_t *p_mi, unsigned on )
136 {
137     var_SetBool (p_mi, "mouse-events", !!on);
138 }
139
140 int
141 libvlc_video_take_snapshot( libvlc_media_player_t *p_mi, unsigned num,
142                             const char *psz_filepath,
143                             unsigned int i_width, unsigned int i_height )
144 {
145     assert( psz_filepath );
146
147     vout_thread_t *p_vout = GetVout (p_mi, num);
148     if (p_vout == NULL)
149         return -1;
150
151     /* FIXME: This is not atomic. All parameters should be passed at once
152      * (obviously _not_ with var_*()). Also, the libvlc object should not be
153      * used for the callbacks: that breaks badly if there are concurrent
154      * media players in the instance. */
155     var_Create( p_vout, "snapshot-width", VLC_VAR_INTEGER );
156     var_SetInteger( p_vout, "snapshot-width", i_width);
157     var_Create( p_vout, "snapshot-height", VLC_VAR_INTEGER );
158     var_SetInteger( p_vout, "snapshot-height", i_height );
159     var_Create( p_vout, "snapshot-path", VLC_VAR_STRING );
160     var_SetString( p_vout, "snapshot-path", psz_filepath );
161     var_Create( p_vout, "snapshot-format", VLC_VAR_STRING );
162     var_SetString( p_vout, "snapshot-format", "png" );
163     var_TriggerCallback( p_vout, "video-snapshot" );
164     vlc_object_release( p_vout );
165     return 0;
166 }
167
168 int libvlc_video_get_size( libvlc_media_player_t *p_mi, unsigned num,
169                            unsigned *restrict px, unsigned *restrict py )
170 {
171     libvlc_media_track_info_t *info;
172     int ret = -1;
173     if (!p_mi->p_md)
174         return ret;
175     int infos = libvlc_media_get_tracks_info(p_mi->p_md, &info);
176     if (infos <= 0)
177         return ret;
178
179     for (int i = 0; i < infos; i++)
180         if (info[i].i_type == libvlc_track_video && num-- == 0) {
181             *px = info[i].u.video.i_width;
182             *py = info[i].u.video.i_height;
183             ret = 0;
184             break;
185         }
186
187     free(info);
188     return ret;
189 }
190
191 int libvlc_video_get_height( libvlc_media_player_t *p_mi )
192 {
193     unsigned width, height;
194
195     if (libvlc_video_get_size (p_mi, 0, &width, &height))
196         return 0;
197     return height;
198 }
199
200 int libvlc_video_get_width( libvlc_media_player_t *p_mi )
201 {
202     unsigned width, height;
203
204     if (libvlc_video_get_size (p_mi, 0, &width, &height))
205         return 0;
206     return width;
207 }
208
209 int libvlc_video_get_cursor( libvlc_media_player_t *mp, unsigned num,
210                              int *restrict px, int *restrict py )
211 {
212     vout_thread_t *p_vout = GetVout (mp, num);
213     if (p_vout == NULL)
214         return -1;
215
216     var_GetCoords (p_vout, "mouse-moved", px, py);
217     vlc_object_release (p_vout);
218     return 0;
219 }
220
221 unsigned libvlc_media_player_has_vout( libvlc_media_player_t *p_mi )
222 {
223     size_t n;
224     vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
225     for (size_t i = 0; i < n; i++)
226         vlc_object_release (pp_vouts[i]);
227     free (pp_vouts);
228     return n;
229 }
230
231 float libvlc_video_get_scale( libvlc_media_player_t *mp )
232 {
233     float f_scale = var_GetFloat (mp, "zoom");
234     if (var_GetBool (mp, "autoscale"))
235         f_scale = 0.f;
236     return f_scale;
237 }
238
239 void libvlc_video_set_scale( libvlc_media_player_t *p_mp, float f_scale )
240 {
241     if (isfinite(f_scale) && f_scale != 0.f)
242         var_SetFloat (p_mp, "zoom", f_scale);
243     var_SetBool (p_mp, "autoscale", f_scale == 0.f);
244
245     /* Apply to current video outputs (if any) */
246     size_t n;
247     vout_thread_t **pp_vouts = GetVouts (p_mp, &n);
248     for (size_t i = 0; i < n; i++)
249     {
250         vout_thread_t *p_vout = pp_vouts[i];
251
252         if (isfinite(f_scale) && f_scale != 0.f)
253             var_SetFloat (p_vout, "zoom", f_scale);
254         var_SetBool (p_vout, "autoscale", f_scale == 0.f);
255         vlc_object_release (p_vout);
256     }
257     free (pp_vouts);
258 }
259
260 char *libvlc_video_get_aspect_ratio( libvlc_media_player_t *p_mi )
261 {
262     return var_GetNonEmptyString (p_mi, "aspect-ratio");
263 }
264
265 void libvlc_video_set_aspect_ratio( libvlc_media_player_t *p_mi,
266                                     const char *psz_aspect )
267 {
268     if (psz_aspect == NULL)
269         psz_aspect = "";
270     var_SetString (p_mi, "aspect-ratio", psz_aspect);
271
272     size_t n;
273     vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
274     for (size_t i = 0; i < n; i++)
275     {
276         vout_thread_t *p_vout = pp_vouts[i];
277
278         var_SetString (p_vout, "aspect-ratio", psz_aspect);
279         vlc_object_release (p_vout);
280     }
281     free (pp_vouts);
282 }
283
284 int libvlc_video_get_spu( libvlc_media_player_t *p_mi )
285 {
286     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
287
288     if( !p_input_thread )
289     {
290         libvlc_printerr( "No active input" );
291         return -1;
292     }
293
294     int i_spu = var_GetInteger( p_input_thread, "spu-es" );
295     vlc_object_release( p_input_thread );
296     return i_spu;
297 }
298
299 int libvlc_video_get_spu_count( libvlc_media_player_t *p_mi )
300 {
301     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
302     int i_spu_count;
303
304     if( !p_input_thread )
305         return 0;
306
307     i_spu_count = var_CountChoices( p_input_thread, "spu-es" );
308     vlc_object_release( p_input_thread );
309     return i_spu_count;
310 }
311
312 libvlc_track_description_t *
313         libvlc_video_get_spu_description( libvlc_media_player_t *p_mi )
314 {
315     return libvlc_get_track_description( p_mi, "spu-es" );
316 }
317
318 int libvlc_video_set_spu( libvlc_media_player_t *p_mi, int i_spu )
319 {
320     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
321     vlc_value_t list;
322     int i_ret = -1;
323
324     if( !p_input_thread )
325         return -1;
326
327     var_Change (p_input_thread, "spu-es", VLC_VAR_GETCHOICES, &list, NULL);
328     for (int i = 0; i < list.p_list->i_count; i++)
329     {
330         if( i_spu == list.p_list->p_values[i].i_int )
331         {
332             if( var_SetInteger( p_input_thread, "spu-es", i_spu ) < 0 )
333                 break;
334             i_ret = 0;
335             goto end;
336         }
337     }
338     libvlc_printerr( "Track identifier not found" );
339 end:
340     vlc_object_release (p_input_thread);
341     var_FreeList (&list, NULL);
342     return i_ret;
343 }
344
345 int libvlc_video_set_subtitle_file( libvlc_media_player_t *p_mi,
346                                     const char *psz_subtitle )
347 {
348     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
349     bool b_ret = false;
350
351     if( p_input_thread )
352     {
353         if( !input_AddSubtitle( p_input_thread, psz_subtitle, true ) )
354             b_ret = true;
355         vlc_object_release( p_input_thread );
356     }
357     return b_ret;
358 }
359
360 int64_t libvlc_video_get_spu_delay( libvlc_media_player_t *p_mi )
361 {
362     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
363     int64_t val = 0;
364
365     if( p_input_thread )
366     {
367         val = var_GetInteger( p_input_thread, "spu-delay" );
368         vlc_object_release( p_input_thread );
369     }
370     else
371     {
372         libvlc_printerr( "No active input" );
373     }
374
375     return val;
376 }
377
378 int libvlc_video_set_spu_delay( libvlc_media_player_t *p_mi,
379                                 int64_t i_delay )
380 {
381     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
382     int ret = -1;
383
384     if( p_input_thread )
385     {
386         var_SetInteger( p_input_thread, "spu-delay", i_delay );
387         vlc_object_release( p_input_thread );
388         ret = 0;
389     }
390     else
391     {
392         libvlc_printerr( "No active input" );
393     }
394
395     return ret;
396 }
397
398 libvlc_track_description_t *
399         libvlc_video_get_title_description( libvlc_media_player_t *p_mi )
400 {
401     return libvlc_get_track_description( p_mi, "title" );
402 }
403
404 libvlc_track_description_t *
405         libvlc_video_get_chapter_description( libvlc_media_player_t *p_mi,
406                                               int i_title )
407 {
408     char psz_title[sizeof ("title ") + 3 * sizeof (int)];
409     sprintf( psz_title,  "title %2u", i_title );
410     return libvlc_get_track_description( p_mi, psz_title );
411 }
412
413 char *libvlc_video_get_crop_geometry (libvlc_media_player_t *p_mi)
414 {
415     return var_GetNonEmptyString (p_mi, "crop");
416 }
417
418 void libvlc_video_set_crop_geometry( libvlc_media_player_t *p_mi,
419                                      const char *psz_geometry )
420 {
421     if (psz_geometry == NULL)
422         psz_geometry = "";
423
424     var_SetString (p_mi, "crop", psz_geometry);
425
426     size_t n;
427     vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
428
429     for (size_t i = 0; i < n; i++)
430     {
431         vout_thread_t *p_vout = pp_vouts[i];
432         vlc_value_t val;
433
434         /* Make sure the geometry is in the choice list */
435         /* Earlier choices are removed to not grow a long list over time. */
436         /* FIXME: not atomic - lock? */
437         val.psz_string = (char *)psz_geometry;
438         var_Change (p_vout, "crop", VLC_VAR_CLEARCHOICES, NULL, NULL);
439         var_Change (p_vout, "crop", VLC_VAR_ADDCHOICE, &val, &val);
440         var_SetString (p_vout, "crop", psz_geometry);
441         vlc_object_release (p_vout);
442     }
443     free (pp_vouts);
444 }
445
446 int libvlc_video_get_teletext( libvlc_media_player_t *p_mi )
447 {
448     return var_GetInteger (p_mi, "vbi-page");
449 }
450
451 void libvlc_video_set_teletext( libvlc_media_player_t *p_mi, int i_page )
452 {
453     input_thread_t *p_input_thread;
454     vlc_object_t *p_zvbi = NULL;
455     int telx;
456
457     var_SetInteger (p_mi, "vbi-page", i_page);
458
459     p_input_thread = libvlc_get_input_thread( p_mi );
460     if( !p_input_thread ) return;
461
462     if( var_CountChoices( p_input_thread, "teletext-es" ) <= 0 )
463     {
464         vlc_object_release( p_input_thread );
465         return;
466     }
467
468     telx = var_GetInteger( p_input_thread, "teletext-es" );
469     if( input_GetEsObjects( p_input_thread, telx, &p_zvbi, NULL, NULL )
470         == VLC_SUCCESS )
471     {
472         var_SetInteger( p_zvbi, "vbi-page", i_page );
473         vlc_object_release( p_zvbi );
474     }
475     vlc_object_release( p_input_thread );
476 }
477
478 void libvlc_toggle_teletext( libvlc_media_player_t *p_mi )
479 {
480     input_thread_t *p_input_thread;
481
482     p_input_thread = libvlc_get_input_thread(p_mi);
483     if( !p_input_thread ) return;
484
485     if( var_CountChoices( p_input_thread, "teletext-es" ) <= 0 )
486     {
487         vlc_object_release( p_input_thread );
488         return;
489     }
490     const bool b_selected = var_GetInteger( p_input_thread, "teletext-es" ) >= 0;
491     if( b_selected )
492     {
493         var_SetInteger( p_input_thread, "spu-es", -1 );
494     }
495     else
496     {
497         vlc_value_t list;
498         if( !var_Change( p_input_thread, "teletext-es", VLC_VAR_GETCHOICES, &list, NULL ) )
499         {
500             if( list.p_list->i_count > 0 )
501                 var_SetInteger( p_input_thread, "spu-es", list.p_list->p_values[0].i_int );
502
503             var_FreeList( &list, NULL );
504         }
505     }
506     vlc_object_release( p_input_thread );
507 }
508
509 int libvlc_video_get_track_count( libvlc_media_player_t *p_mi )
510 {
511     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
512     int i_track_count;
513
514     if( !p_input_thread )
515         return -1;
516
517     i_track_count = var_CountChoices( p_input_thread, "video-es" );
518
519     vlc_object_release( p_input_thread );
520     return i_track_count;
521 }
522
523 libvlc_track_description_t *
524         libvlc_video_get_track_description( libvlc_media_player_t *p_mi )
525 {
526     return libvlc_get_track_description( p_mi, "video-es" );
527 }
528
529 int libvlc_video_get_track( libvlc_media_player_t *p_mi )
530 {
531     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
532
533     if( !p_input_thread )
534         return -1;
535
536     int id = var_GetInteger( p_input_thread, "video-es" );
537     vlc_object_release( p_input_thread );
538     return id;
539 }
540
541 int libvlc_video_set_track( libvlc_media_player_t *p_mi, int i_track )
542 {
543     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi );
544     vlc_value_t val_list;
545     int i_ret = -1;
546
547     if( !p_input_thread )
548         return -1;
549
550     var_Change( p_input_thread, "video-es", VLC_VAR_GETCHOICES, &val_list, NULL );
551     for( int i = 0; i < val_list.p_list->i_count; i++ )
552     {
553         if( i_track == val_list.p_list->p_values[i].i_int )
554         {
555             if( var_SetBool( p_input_thread, "video", true ) < 0)
556                 break;
557             if( var_SetInteger( p_input_thread, "video-es", i_track ) < 0 )
558                 break;
559             i_ret = 0;
560             goto end;
561         }
562     }
563     libvlc_printerr( "Track identifier not found" );
564 end:
565     var_FreeList( &val_list, NULL );
566     vlc_object_release( p_input_thread );
567     return i_ret;
568 }
569
570 /******************************************************************************
571  * libvlc_video_set_deinterlace : enable deinterlace
572  *****************************************************************************/
573 void libvlc_video_set_deinterlace( libvlc_media_player_t *p_mi,
574                                    const char *psz_mode )
575 {
576     if (psz_mode == NULL)
577         psz_mode = "";
578     if (*psz_mode
579      && strcmp (psz_mode, "blend")    && strcmp (psz_mode, "bob")
580      && strcmp (psz_mode, "discard")  && strcmp (psz_mode, "linear")
581      && strcmp (psz_mode, "mean")     && strcmp (psz_mode, "x")
582      && strcmp (psz_mode, "yadif")    && strcmp (psz_mode, "yadif2x")
583      && strcmp (psz_mode, "phosphor") && strcmp (psz_mode, "ivtc"))
584         return;
585
586     if (*psz_mode)
587     {
588         var_SetString (p_mi, "deinterlace-mode", psz_mode);
589         var_SetInteger (p_mi, "deinterlace", 1);
590     }
591     else
592         var_SetInteger (p_mi, "deinterlace", 0);
593
594     size_t n;
595     vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
596     for (size_t i = 0; i < n; i++)
597     {
598         vout_thread_t *p_vout = pp_vouts[i];
599
600         if (*psz_mode)
601         {
602             var_SetString (p_vout, "deinterlace-mode", psz_mode);
603             var_SetInteger (p_vout, "deinterlace", 1);
604         }
605         else
606             var_SetInteger (p_vout, "deinterlace", 0);
607         vlc_object_release (p_vout);
608     }
609     free (pp_vouts);
610 }
611
612 /* ************** */
613 /* module helpers */
614 /* ************** */
615
616 static bool find_sub_source_by_name( libvlc_media_player_t *p_mi, const char *restrict name )
617 {
618     vout_thread_t *vout = GetVout( p_mi, 0 );
619     if (!vout)
620         return false;
621
622     char *psz_sources = var_GetString( vout, "sub-source" );
623     if( !psz_sources )
624     {
625         libvlc_printerr( "%s not enabled", name );
626         vlc_object_release( vout );
627         return false;
628     }
629
630     /* Find 'name'  */
631     char *p = strstr( psz_sources, name );
632     free( psz_sources );
633     vlc_object_release( vout );
634     return (p != NULL);
635 }
636
637 typedef const struct {
638     const char name[20];
639     unsigned type;
640 } opt_t;
641
642 static void
643 set_int( libvlc_media_player_t *p_mi, const char *restrict name,
644          const opt_t *restrict opt, int value )
645 {
646     if( !opt ) return;
647
648     switch( opt->type )
649     {
650         case 0: /* the enabler */
651         {
652             vout_thread_t *vout = GetVout( p_mi, 0 );
653             if (vout != NULL)
654             {   /* Fill sub-source */
655                 vout_EnableFilter( vout, opt->name, value, false );
656                 var_TriggerCallback( vout, "sub-source" );
657                 vlc_object_release( vout );
658             }
659             break;
660         }
661         case VLC_VAR_INTEGER:
662             var_SetInteger( p_mi, opt->name, value );
663             break;
664         case VLC_VAR_FLOAT:
665             var_SetFloat( p_mi, opt->name, value );
666             break;
667         default:
668             libvlc_printerr( "Invalid argument to %s in %s", name, "set int" );
669             return;
670     }
671 }
672
673 static int
674 get_int( libvlc_media_player_t *p_mi, const char *restrict name,
675          const opt_t *restrict opt )
676 {
677     if( !opt ) return 0;
678
679     switch( opt->type )
680     {
681         case 0: /* the enabler */
682         {
683             bool b_enabled = find_sub_source_by_name( p_mi, name );
684             return b_enabled ? 1 : 0;
685         }
686     case VLC_VAR_INTEGER:
687         return var_GetInteger(p_mi, opt->name);
688     case VLC_VAR_FLOAT:
689         return lroundf(var_GetFloat(p_mi, opt->name));
690     default:
691         libvlc_printerr( "Invalid argument to %s in %s", name, "get int" );
692         return 0;
693     }
694 }
695
696 static void
697 set_float( libvlc_media_player_t *p_mi, const char *restrict name,
698             const opt_t *restrict opt, float value )
699 {
700     if( !opt ) return;
701
702     if( opt->type != VLC_VAR_FLOAT )
703     {
704         libvlc_printerr( "Invalid argument to %s in %s", name, "set float" );
705         return;
706     }
707
708     var_SetFloat( p_mi, opt->name, value );
709 }
710
711 static float
712 get_float( libvlc_media_player_t *p_mi, const char *restrict name,
713             const opt_t *restrict opt )
714 {
715     if( !opt ) return 0.0;
716
717     if( opt->type != VLC_VAR_FLOAT )
718     {
719         libvlc_printerr( "Invalid argument to %s in %s", name, "get float" );
720         return 0.0;
721     }
722
723     return var_GetFloat( p_mi, opt->name );
724 }
725
726 static void
727 set_string( libvlc_media_player_t *p_mi, const char *restrict name,
728             const opt_t *restrict opt, const char *restrict psz_value )
729 {
730     if( !opt ) return;
731
732     if( opt->type != VLC_VAR_STRING )
733     {
734         libvlc_printerr( "Invalid argument to %s in %s", name, "set string" );
735         return;
736     }
737
738     var_SetString( p_mi, opt->name, psz_value );
739 }
740
741 static char *
742 get_string( libvlc_media_player_t *p_mi, const char *restrict name,
743             const opt_t *restrict opt )
744 {
745     if( !opt ) return NULL;
746
747     if( opt->type != VLC_VAR_STRING )
748     {
749         libvlc_printerr( "Invalid argument to %s in %s", name, "get string" );
750         return NULL;
751     }
752
753     return var_GetString( p_mi, opt->name );
754 }
755
756 static const opt_t *
757 marq_option_bynumber(unsigned option)
758 {
759     static const opt_t optlist[] =
760     {
761         { "marq",          0 },
762         { "marq-marquee",  VLC_VAR_STRING },
763         { "marq-color",    VLC_VAR_INTEGER },
764         { "marq-opacity",  VLC_VAR_INTEGER },
765         { "marq-position", VLC_VAR_INTEGER },
766         { "marq-refresh",  VLC_VAR_INTEGER },
767         { "marq-size",     VLC_VAR_INTEGER },
768         { "marq-timeout",  VLC_VAR_INTEGER },
769         { "marq-x",        VLC_VAR_INTEGER },
770         { "marq-y",        VLC_VAR_INTEGER },
771     };
772     enum { num_opts = sizeof(optlist) / sizeof(*optlist) };
773
774     const opt_t *r = option < num_opts ? optlist+option : NULL;
775     if( !r )
776         libvlc_printerr( "Unknown marquee option" );
777     return r;
778 }
779
780 /*****************************************************************************
781  * libvlc_video_get_marquee_int : get a marq option value
782  *****************************************************************************/
783 int libvlc_video_get_marquee_int( libvlc_media_player_t *p_mi,
784                                   unsigned option )
785 {
786     return get_int( p_mi, "marq", marq_option_bynumber(option) );
787 }
788
789 /*****************************************************************************
790  * libvlc_video_get_marquee_string : get a marq option value
791  *****************************************************************************/
792 char * libvlc_video_get_marquee_string( libvlc_media_player_t *p_mi,
793                                         unsigned option )
794 {
795     return get_string( p_mi, "marq", marq_option_bynumber(option) );
796 }
797
798 /*****************************************************************************
799  * libvlc_video_set_marquee_int: enable, disable or set an int option
800  *****************************************************************************/
801 void libvlc_video_set_marquee_int( libvlc_media_player_t *p_mi,
802                          unsigned option, int value )
803 {
804     set_int( p_mi, "marq", marq_option_bynumber(option), value );
805 }
806
807 /*****************************************************************************
808  * libvlc_video_set_marquee_string: set a string option
809  *****************************************************************************/
810 void libvlc_video_set_marquee_string( libvlc_media_player_t *p_mi,
811                 unsigned option, const char * value )
812 {
813     set_string( p_mi, "marq", marq_option_bynumber(option), value );
814 }
815
816
817 /* logo module support */
818
819 static const opt_t *
820 logo_option_bynumber( unsigned option )
821 {
822     static const opt_t vlogo_optlist[] =
823     /* depends on libvlc_video_logo_option_t */
824     {
825         { "logo",          0 },
826         { "logo-file",     VLC_VAR_STRING },
827         { "logo-x",        VLC_VAR_INTEGER },
828         { "logo-y",        VLC_VAR_INTEGER },
829         { "logo-delay",    VLC_VAR_INTEGER },
830         { "logo-repeat",   VLC_VAR_INTEGER },
831         { "logo-opacity",  VLC_VAR_INTEGER },
832         { "logo-position", VLC_VAR_INTEGER },
833     };
834     enum { num_vlogo_opts = sizeof(vlogo_optlist) / sizeof(*vlogo_optlist) };
835
836     const opt_t *r = option < num_vlogo_opts ? vlogo_optlist+option : NULL;
837     if( !r )
838         libvlc_printerr( "Unknown logo option" );
839     return r;
840 }
841
842 void libvlc_video_set_logo_string( libvlc_media_player_t *p_mi,
843                                    unsigned option, const char *psz_value )
844 {
845     set_string( p_mi,"logo",logo_option_bynumber(option), psz_value );
846 }
847
848
849 void libvlc_video_set_logo_int( libvlc_media_player_t *p_mi,
850                                 unsigned option, int value )
851 {
852     set_int( p_mi, "logo", logo_option_bynumber(option), value );
853 }
854
855
856 int libvlc_video_get_logo_int( libvlc_media_player_t *p_mi,
857                                unsigned option )
858 {
859     return get_int( p_mi, "logo", logo_option_bynumber(option) );
860 }
861
862
863 /* adjust module support */
864
865
866 static const opt_t *
867 adjust_option_bynumber( unsigned option )
868 {
869     static const opt_t optlist[] =
870     {
871         { "adjust",     0 },
872         { "contrast",   VLC_VAR_FLOAT },
873         { "brightness", VLC_VAR_FLOAT },
874         { "hue",        VLC_VAR_FLOAT },
875         { "saturation", VLC_VAR_FLOAT },
876         { "gamma",      VLC_VAR_FLOAT },
877     };
878     enum { num_opts = sizeof(optlist) / sizeof(*optlist) };
879
880     const opt_t *r = option < num_opts ? optlist+option : NULL;
881     if( !r )
882         libvlc_printerr( "Unknown adjust option" );
883     return r;
884 }
885
886
887 void libvlc_video_set_adjust_int( libvlc_media_player_t *p_mi,
888                                   unsigned option, int value )
889 {
890     set_int( p_mi, "adjust", adjust_option_bynumber(option), value );
891 }
892
893
894 int libvlc_video_get_adjust_int( libvlc_media_player_t *p_mi,
895                                  unsigned option )
896 {
897     return get_int( p_mi, "adjust", adjust_option_bynumber(option) );
898 }
899
900
901 void libvlc_video_set_adjust_float( libvlc_media_player_t *p_mi,
902                                     unsigned option, float value )
903 {
904     set_float( p_mi, "adjust", adjust_option_bynumber(option), value );
905 }
906
907
908 float libvlc_video_get_adjust_float( libvlc_media_player_t *p_mi,
909                                      unsigned option )
910 {
911     return get_float( p_mi, "adjust", adjust_option_bynumber(option) );
912 }