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