3f3d19a37ac43672ee18bb73ed6c7a9f1d775bd8
[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, "scale");
234     if (var_GetBool (mp, "autoscale"))
235         f_scale = 0.;
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, "scale", 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, "scale", 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_GetTime( 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_SetTime( 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[12];
409     sprintf( psz_title,  "title %2i", 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_GETLIST, &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_SetInteger( p_input_thread, "video-es", i_track ) < 0 )
556                 break;
557             i_ret = 0;
558             goto end;
559         }
560     }
561     libvlc_printerr( "Track identifier not found" );
562 end:
563     var_FreeList( &val_list, NULL );
564     vlc_object_release( p_input_thread );
565     return i_ret;
566 }
567
568 /******************************************************************************
569  * libvlc_video_set_deinterlace : enable deinterlace
570  *****************************************************************************/
571 void libvlc_video_set_deinterlace( libvlc_media_player_t *p_mi,
572                                    const char *psz_mode )
573 {
574     if (psz_mode == NULL)
575         psz_mode = "";
576     if (*psz_mode
577      && strcmp (psz_mode, "blend")    && strcmp (psz_mode, "bob")
578      && strcmp (psz_mode, "discard")  && strcmp (psz_mode, "linear")
579      && strcmp (psz_mode, "mean")     && strcmp (psz_mode, "x")
580      && strcmp (psz_mode, "yadif")    && strcmp (psz_mode, "yadif2x")
581      && strcmp (psz_mode, "phosphor") && strcmp (psz_mode, "ivtc"))
582         return;
583
584     if (*psz_mode)
585     {
586         var_SetString (p_mi, "deinterlace-mode", psz_mode);
587         var_SetInteger (p_mi, "deinterlace", 1);
588     }
589     else
590         var_SetInteger (p_mi, "deinterlace", 0);
591
592     size_t n;
593     vout_thread_t **pp_vouts = GetVouts (p_mi, &n);
594     for (size_t i = 0; i < n; i++)
595     {
596         vout_thread_t *p_vout = pp_vouts[i];
597
598         if (*psz_mode)
599         {
600             var_SetString (p_vout, "deinterlace-mode", psz_mode);
601             var_SetInteger (p_vout, "deinterlace", 1);
602         }
603         else
604             var_SetInteger (p_vout, "deinterlace", 0);
605         vlc_object_release (p_vout);
606     }
607     free (pp_vouts);
608 }
609
610 /* ************** */
611 /* module helpers */
612 /* ************** */
613
614 static bool find_sub_source_by_name( libvlc_media_player_t *p_mi, const char *restrict name )
615 {
616     vout_thread_t *vout = GetVout( p_mi, 0 );
617     if (!vout)
618         return false;
619
620     char *psz_sources = var_GetString( vout, "sub-source" );
621     if( !psz_sources )
622     {
623         libvlc_printerr( "%s not enabled", name );
624         vlc_object_release( vout );
625         return false;
626     }
627
628     /* Find 'name'  */
629     char *p = strstr( psz_sources, name );
630     free( psz_sources );
631     vlc_object_release( vout );
632     return (p != NULL);
633 }
634
635 typedef const struct {
636     const char name[20];
637     unsigned type;
638 } opt_t;
639
640 static void
641 set_int( libvlc_media_player_t *p_mi, const char *restrict name,
642          const opt_t *restrict opt, int value )
643 {
644     if( !opt ) return;
645
646     switch( opt->type )
647     {
648         case 0: /* the enabler */
649         {
650             vout_thread_t *vout = GetVout( p_mi, 0 );
651             if (vout != NULL)
652             {   /* Fill sub-source */
653                 vout_EnableFilter( vout, opt->name, value, false );
654                 var_TriggerCallback( vout, "sub-source" );
655                 vlc_object_release( vout );
656             }
657             break;
658         }
659         case VLC_VAR_INTEGER:
660             var_SetInteger( p_mi, opt->name, value );
661             break;
662         case VLC_VAR_FLOAT:
663             var_SetFloat( p_mi, opt->name, value );
664             break;
665         default:
666             libvlc_printerr( "Invalid argument to %s in %s", name, "set int" );
667             return;
668     }
669 }
670
671 static int
672 get_int( libvlc_media_player_t *p_mi, const char *restrict name,
673          const opt_t *restrict opt )
674 {
675     if( !opt ) return 0;
676
677     switch( opt->type )
678     {
679         case 0: /* the enabler */
680         {
681             bool b_enabled = find_sub_source_by_name( p_mi, name );
682             return b_enabled ? 1 : 0;
683         }
684     case VLC_VAR_INTEGER:
685         return var_GetInteger(p_mi, opt->name);
686     case VLC_VAR_FLOAT:
687         return lroundf(var_GetFloat(p_mi, opt->name));
688     default:
689         libvlc_printerr( "Invalid argument to %s in %s", name, "get int" );
690         return 0;
691     }
692 }
693
694 static void
695 set_float( libvlc_media_player_t *p_mi, const char *restrict name,
696             const opt_t *restrict opt, float value )
697 {
698     if( !opt ) return;
699
700     if( opt->type != VLC_VAR_FLOAT )
701     {
702         libvlc_printerr( "Invalid argument to %s in %s", name, "set float" );
703         return;
704     }
705
706     var_SetFloat( p_mi, opt->name, value );
707 }
708
709 static float
710 get_float( libvlc_media_player_t *p_mi, const char *restrict name,
711             const opt_t *restrict opt )
712 {
713     if( !opt ) return 0.0;
714
715     if( opt->type != VLC_VAR_FLOAT )
716     {
717         libvlc_printerr( "Invalid argument to %s in %s", name, "get float" );
718         return 0.0;
719     }
720
721     return var_GetFloat( p_mi, opt->name );
722 }
723
724 static void
725 set_string( libvlc_media_player_t *p_mi, const char *restrict name,
726             const opt_t *restrict opt, const char *restrict psz_value )
727 {
728     if( !opt ) return;
729
730     if( opt->type != VLC_VAR_STRING )
731     {
732         libvlc_printerr( "Invalid argument to %s in %s", name, "set string" );
733         return;
734     }
735
736     var_SetString( p_mi, opt->name, psz_value );
737 }
738
739 static char *
740 get_string( libvlc_media_player_t *p_mi, const char *restrict name,
741             const opt_t *restrict opt )
742 {
743     if( !opt ) return NULL;
744
745     if( opt->type != VLC_VAR_STRING )
746     {
747         libvlc_printerr( "Invalid argument to %s in %s", name, "get string" );
748         return NULL;
749     }
750
751     return var_GetString( p_mi, opt->name );
752 }
753
754 static const opt_t *
755 marq_option_bynumber(unsigned option)
756 {
757     static const opt_t optlist[] =
758     {
759         { "marq",          0 },
760         { "marq-marquee",  VLC_VAR_STRING },
761         { "marq-color",    VLC_VAR_INTEGER },
762         { "marq-opacity",  VLC_VAR_INTEGER },
763         { "marq-position", VLC_VAR_INTEGER },
764         { "marq-refresh",  VLC_VAR_INTEGER },
765         { "marq-size",     VLC_VAR_INTEGER },
766         { "marq-timeout",  VLC_VAR_INTEGER },
767         { "marq-x",        VLC_VAR_INTEGER },
768         { "marq-y",        VLC_VAR_INTEGER },
769     };
770     enum { num_opts = sizeof(optlist) / sizeof(*optlist) };
771
772     const opt_t *r = option < num_opts ? optlist+option : NULL;
773     if( !r )
774         libvlc_printerr( "Unknown marquee option" );
775     return r;
776 }
777
778 /*****************************************************************************
779  * libvlc_video_get_marquee_int : get a marq option value
780  *****************************************************************************/
781 int libvlc_video_get_marquee_int( libvlc_media_player_t *p_mi,
782                                   unsigned option )
783 {
784     return get_int( p_mi, "marq", marq_option_bynumber(option) );
785 }
786
787 /*****************************************************************************
788  * libvlc_video_get_marquee_string : get a marq option value
789  *****************************************************************************/
790 char * libvlc_video_get_marquee_string( libvlc_media_player_t *p_mi,
791                                         unsigned option )
792 {
793     return get_string( p_mi, "marq", marq_option_bynumber(option) );
794 }
795
796 /*****************************************************************************
797  * libvlc_video_set_marquee_int: enable, disable or set an int option
798  *****************************************************************************/
799 void libvlc_video_set_marquee_int( libvlc_media_player_t *p_mi,
800                          unsigned option, int value )
801 {
802     set_int( p_mi, "marq", marq_option_bynumber(option), value );
803 }
804
805 /*****************************************************************************
806  * libvlc_video_set_marquee_string: set a string option
807  *****************************************************************************/
808 void libvlc_video_set_marquee_string( libvlc_media_player_t *p_mi,
809                 unsigned option, const char * value )
810 {
811     set_string( p_mi, "marq", marq_option_bynumber(option), value );
812 }
813
814
815 /* logo module support */
816
817 static const opt_t *
818 logo_option_bynumber( unsigned option )
819 {
820     static const opt_t vlogo_optlist[] =
821     /* depends on libvlc_video_logo_option_t */
822     {
823         { "logo",          0 },
824         { "logo-file",     VLC_VAR_STRING },
825         { "logo-x",        VLC_VAR_INTEGER },
826         { "logo-y",        VLC_VAR_INTEGER },
827         { "logo-delay",    VLC_VAR_INTEGER },
828         { "logo-repeat",   VLC_VAR_INTEGER },
829         { "logo-opacity",  VLC_VAR_INTEGER },
830         { "logo-position", VLC_VAR_INTEGER },
831     };
832     enum { num_vlogo_opts = sizeof(vlogo_optlist) / sizeof(*vlogo_optlist) };
833
834     const opt_t *r = option < num_vlogo_opts ? vlogo_optlist+option : NULL;
835     if( !r )
836         libvlc_printerr( "Unknown logo option" );
837     return r;
838 }
839
840 void libvlc_video_set_logo_string( libvlc_media_player_t *p_mi,
841                                    unsigned option, const char *psz_value )
842 {
843     set_string( p_mi,"logo",logo_option_bynumber(option), psz_value );
844 }
845
846
847 void libvlc_video_set_logo_int( libvlc_media_player_t *p_mi,
848                                 unsigned option, int value )
849 {
850     set_int( p_mi, "logo", logo_option_bynumber(option), value );
851 }
852
853
854 int libvlc_video_get_logo_int( libvlc_media_player_t *p_mi,
855                                unsigned option )
856 {
857     return get_int( p_mi, "logo", logo_option_bynumber(option) );
858 }
859
860
861 /* adjust module support */
862
863
864 static const opt_t *
865 adjust_option_bynumber( unsigned option )
866 {
867     static const opt_t optlist[] =
868     {
869         { "adjust",     0 },
870         { "contrast",   VLC_VAR_FLOAT },
871         { "brightness", VLC_VAR_FLOAT },
872         { "hue",        VLC_VAR_INTEGER },
873         { "saturation", VLC_VAR_FLOAT },
874         { "gamma",      VLC_VAR_FLOAT },
875     };
876     enum { num_opts = sizeof(optlist) / sizeof(*optlist) };
877
878     const opt_t *r = option < num_opts ? optlist+option : NULL;
879     if( !r )
880         libvlc_printerr( "Unknown adjust option" );
881     return r;
882 }
883
884
885 void libvlc_video_set_adjust_int( libvlc_media_player_t *p_mi,
886                                   unsigned option, int value )
887 {
888     set_int( p_mi, "adjust", adjust_option_bynumber(option), value );
889 }
890
891
892 int libvlc_video_get_adjust_int( libvlc_media_player_t *p_mi,
893                                  unsigned option )
894 {
895     return get_int( p_mi, "adjust", adjust_option_bynumber(option) );
896 }
897
898
899 void libvlc_video_set_adjust_float( libvlc_media_player_t *p_mi,
900                                     unsigned option, float value )
901 {
902     set_float( p_mi, "adjust", adjust_option_bynumber(option), value );
903 }
904
905
906 float libvlc_video_get_adjust_float( libvlc_media_player_t *p_mi,
907                                      unsigned option )
908 {
909     return get_float( p_mi, "adjust", adjust_option_bynumber(option) );
910 }