ebdd6df1316363bd17306b916b64afbda1268068
[vlc.git] / src / control / video.c
1 /*****************************************************************************
2  * video.c: libvlc new API video functions
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  *
6  * $Id: core.c 14187 2006-02-07 16:37:40Z courmisch $
7  *
8  * Authors: Cl´┐Żent 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
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 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 General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28 #include <vlc/libvlc.h>
29 #include <vlc_input.h>
30 #include <vlc_vout.h>
31
32 #include "libvlc_internal.h"
33
34 /*
35  * Remember to release the returned vout_thread_t since it is locked at
36  * the end of this function.
37  */
38 static vout_thread_t *GetVout( libvlc_media_instance_t *p_mi,
39                                libvlc_exception_t *p_exception )
40 {
41     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi, p_exception );
42     vout_thread_t *p_vout = NULL;
43
44     if( p_input_thread )
45     {
46         p_vout = vlc_object_find( p_input_thread, VLC_OBJECT_VOUT, FIND_ANYWHERE );
47         if( !p_vout )
48         {
49             libvlc_exception_raise( p_exception, "No active video output" );
50         }
51         vlc_object_release( p_input_thread );
52     }
53     return p_vout;
54 }
55
56 /**********************************************************************
57  * Exported functions
58  **********************************************************************/
59
60 void libvlc_set_fullscreen( libvlc_media_instance_t *p_mi, int b_fullscreen,
61                             libvlc_exception_t *p_e )
62 {
63     /* We only work on the first vout */
64     vout_thread_t *p_vout1 = GetVout( p_mi, p_e );
65     vlc_value_t val; int i_ret;
66
67     /* GetVout will raise the exception for us */
68     if( !p_vout1 )
69     {
70         return;
71     }
72
73     if( b_fullscreen ) val.b_bool = VLC_TRUE;
74     else               val.b_bool = VLC_FALSE;
75
76     i_ret = var_Set( p_vout1, "fullscreen", val );
77     if( i_ret )
78         libvlc_exception_raise( p_e,
79                         "Unexpected error while setting fullscreen value" );
80
81     vlc_object_release( p_vout1 );
82 }
83
84 int libvlc_get_fullscreen( libvlc_media_instance_t *p_mi,
85                             libvlc_exception_t *p_e )
86 {
87     /* We only work on the first vout */
88     vout_thread_t *p_vout1 = GetVout( p_mi, p_e );
89     vlc_value_t val; int i_ret;
90
91     /* GetVout will raise the exception for us */
92     if( !p_vout1 )
93         return 0;
94
95     i_ret = var_Get( p_vout1, "fullscreen", &val );
96     if( i_ret )
97         libvlc_exception_raise( p_e,
98                         "Unexpected error while looking up fullscreen value" );
99
100     return val.b_bool == VLC_TRUE ? 1 : 0;
101 }
102
103 void libvlc_toggle_fullscreen( libvlc_media_instance_t *p_mi,
104                                libvlc_exception_t *p_e )
105 {
106     /* We only work on the first vout */
107     vout_thread_t *p_vout1 = GetVout( p_mi, p_e );
108     vlc_value_t val; int i_ret;
109
110     /* GetVout will raise the exception for us */
111     if( !p_vout1 )
112         return;
113
114     i_ret = var_Get( p_vout1, "fullscreen", &val );
115     if( i_ret )
116         libvlc_exception_raise( p_e,
117                         "Unexpected error while looking up fullscreen value" );
118
119     val.b_bool = !val.b_bool;
120     i_ret = var_Set( p_vout1, "fullscreen", val );
121     if( i_ret )
122         libvlc_exception_raise( p_e,
123                         "Unexpected error while setting fullscreen value" );
124
125     vlc_object_release( p_vout1 );
126 }
127
128 void
129 libvlc_video_take_snapshot( libvlc_media_instance_t *p_mi, char *psz_filepath,
130         unsigned int i_width, unsigned int i_height, libvlc_exception_t *p_e )
131 {
132     vout_thread_t *p_vout = GetVout( p_mi, p_e );
133     input_thread_t *p_input_thread;
134
135     /* GetVout will raise the exception for us */
136     if( !p_vout )
137     {
138         return;
139     }
140
141     if( !psz_filepath )
142     {
143         libvlc_exception_raise( p_e, "filepath is null" );
144         return;
145     }
146
147     var_SetInteger( p_vout, "snapshot-width", i_width );
148     var_SetInteger( p_vout, "snapshot-height", i_height );
149
150     p_input_thread = (input_thread_t*)vlc_object_get(
151                                  p_mi->p_libvlc_instance->p_libvlc_int,
152                                  p_mi->i_input_id );
153     if( !p_input_thread )
154     {
155         libvlc_exception_raise( p_e, "Input does not exist" );
156         return;
157     }
158
159     var_SetString( p_vout, "snapshot-path", psz_filepath );
160     var_SetString( p_vout, "snapshot-format", "png" );
161
162     vout_Control( p_vout, VOUT_SNAPSHOT );
163     vlc_object_release( p_vout );
164     vlc_object_release( p_input_thread );
165 }
166
167 int libvlc_video_get_height( libvlc_media_instance_t *p_mi,
168                              libvlc_exception_t *p_e )
169 {
170     vout_thread_t *p_vout1 = GetVout( p_mi, p_e );
171     if( !p_vout1 )
172         return 0;
173
174     vlc_object_release( p_vout1 );
175
176     return p_vout1->i_window_height;
177 }
178
179 int libvlc_video_get_width( libvlc_media_instance_t *p_mi,
180                             libvlc_exception_t *p_e )
181 {
182     vout_thread_t *p_vout1 = GetVout( p_mi, p_e );
183     if( !p_vout1 )
184         return 0;
185
186     vlc_object_release( p_vout1 );
187
188     return p_vout1->i_window_width;
189 }
190
191 vlc_bool_t libvlc_media_instance_has_vout( libvlc_media_instance_t *p_mi,
192                                   libvlc_exception_t *p_e )
193 {
194     input_thread_t *p_input_thread = libvlc_get_input_thread(p_mi, p_e);
195     vlc_bool_t has_vout = VLC_FALSE;
196
197     if( p_input_thread )
198     {
199         vout_thread_t *p_vout;
200
201         p_vout = vlc_object_find( p_input_thread, VLC_OBJECT_VOUT, FIND_CHILD );
202         if( p_vout )
203         {
204             has_vout = VLC_TRUE;
205             vlc_object_release( p_vout );
206         }
207         vlc_object_release( p_input_thread );
208     }
209     return has_vout;
210 }
211
212 int libvlc_video_reparent( libvlc_media_instance_t *p_mi, libvlc_drawable_t d,
213                            libvlc_exception_t *p_e )
214 {
215     vout_thread_t *p_vout = GetVout( p_mi, p_e );
216
217     if( p_vout )
218     {
219         vout_Control( p_vout , VOUT_REPARENT, d);
220         vlc_object_release( p_vout );
221     }
222     return 0;
223 }
224
225 void libvlc_video_resize( libvlc_media_instance_t *p_mi, int width, int height, libvlc_exception_t *p_e )
226 {
227     vout_thread_t *p_vout = GetVout( p_mi, p_e );
228     if( p_vout )
229     {
230         vout_Control( p_vout, VOUT_SET_SIZE, width, height );
231         vlc_object_release( p_vout );
232     }
233 }
234
235 void libvlc_video_redraw_rectangle( libvlc_media_instance_t *p_mi,
236                            const libvlc_rectangle_t *area,
237                            libvlc_exception_t *p_e )
238 {
239     if( (NULL != area)
240      && ((area->bottom - area->top) > 0)
241      && ((area->right - area->left) > 0) )
242     {
243         vout_thread_t *p_vout = GetVout( p_mi, p_e );
244         if( p_vout )
245         {
246             /* tell running vout to redraw area */
247             vout_Control( p_vout , VOUT_REDRAW_RECT,
248                                area->top, area->left, area->bottom, area->right );
249             vlc_object_release( p_vout );
250         }
251     }
252 }
253
254 /* global video settings */
255
256 void libvlc_video_set_parent( libvlc_instance_t *p_instance, libvlc_drawable_t d,
257                               libvlc_exception_t *p_e )
258 {
259     /* set as default for future vout instances */
260     var_SetInteger(p_instance->p_libvlc_int, "drawable", (int)d);
261
262     if( libvlc_playlist_isplaying(p_instance, p_e) )
263     {
264         libvlc_media_instance_t *p_mi = libvlc_playlist_get_media_instance(p_instance, p_e);
265         if( p_mi )
266         {
267             vout_thread_t *p_vout = GetVout( p_mi, p_e );
268             if( p_vout )
269             {
270                 /* tell running vout to re-parent */
271                 vout_Control( p_vout , VOUT_REPARENT, d);
272                 vlc_object_release( p_vout );
273             }
274             libvlc_media_instance_release(p_mi);
275         }
276     }
277 }
278
279 libvlc_drawable_t libvlc_video_get_parent( libvlc_instance_t *p_instance, libvlc_exception_t *p_e )
280 {
281     libvlc_drawable_t result;
282  
283     result = var_GetInteger( p_instance->p_libvlc_int, "drawable" );
284  
285     return result;
286 }
287
288
289 void libvlc_video_set_size( libvlc_instance_t *p_instance, int width, int height,
290                            libvlc_exception_t *p_e )
291 {
292     /* set as default for future vout instances */
293     config_PutInt(p_instance->p_libvlc_int, "width", width);
294     config_PutInt(p_instance->p_libvlc_int, "height", height);
295
296     if( libvlc_playlist_isplaying(p_instance, p_e) )
297     {
298         libvlc_media_instance_t *p_mi = libvlc_playlist_get_media_instance(p_instance, p_e);
299         if( p_mi )
300         {
301             vout_thread_t *p_vout = GetVout( p_mi, p_e );
302             if( p_vout )
303             {
304                 /* tell running vout to re-size */
305                 vout_Control( p_vout , VOUT_SET_SIZE, width, height);
306                 vlc_object_release( p_vout );
307             }
308             libvlc_media_instance_release(p_mi);
309         }
310     }
311 }
312
313 void libvlc_video_set_viewport( libvlc_instance_t *p_instance,
314                             const libvlc_rectangle_t *view, const libvlc_rectangle_t *clip,
315                            libvlc_exception_t *p_e )
316 {
317     if( NULL == view )
318     {
319         libvlc_exception_raise( p_e, "viewport is NULL" );
320     }
321
322     /* if clip is NULL, then use view rectangle as clip */
323     if( NULL == clip )
324         clip = view;
325
326     /* set as default for future vout instances */
327     var_SetInteger( p_instance->p_libvlc_int, "drawable-view-top", view->top );
328     var_SetInteger( p_instance->p_libvlc_int, "drawable-view-left", view->left );
329     var_SetInteger( p_instance->p_libvlc_int, "drawable-view-bottom", view->bottom );
330     var_SetInteger( p_instance->p_libvlc_int, "drawable-view-right", view->right );
331     var_SetInteger( p_instance->p_libvlc_int, "drawable-clip-top", clip->top );
332     var_SetInteger( p_instance->p_libvlc_int, "drawable-clip-left", clip->left );
333     var_SetInteger( p_instance->p_libvlc_int, "drawable-clip-bottom", clip->bottom );
334     var_SetInteger( p_instance->p_libvlc_int, "drawable-clip-right", clip->right );
335
336     if( libvlc_playlist_isplaying(p_instance, p_e) )
337     {
338         libvlc_media_instance_t *p_mi = libvlc_playlist_get_media_instance(p_instance, p_e);
339         if( p_mi )
340         {
341             vout_thread_t *p_vout = GetVout( p_mi, p_e );
342             if( p_vout )
343             {
344                 /* change viewport for running vout */
345                 vout_Control( p_vout , VOUT_SET_VIEWPORT,
346                                    view->top, view->left, view->bottom, view->right,
347                                    clip->top, clip->left, clip->bottom, clip->right );
348                 vlc_object_release( p_vout );
349             }
350             libvlc_media_instance_release(p_mi);
351         }
352     }
353 }
354
355 char *libvlc_video_get_aspect_ratio( libvlc_media_instance_t *p_mi,
356                                      libvlc_exception_t *p_e )
357 {
358     char *psz_aspect = 0;
359     vout_thread_t *p_vout = GetVout( p_mi, p_e );
360
361     if( !p_vout )
362         return 0;
363
364     psz_aspect = var_GetNonEmptyString( p_vout, "aspect-ratio" );
365     vlc_object_release( p_vout );
366     return psz_aspect ? psz_aspect : strdup("");
367 }
368
369 void libvlc_video_set_aspect_ratio( libvlc_media_instance_t *p_mi,
370                                     char *psz_aspect, libvlc_exception_t *p_e )
371 {
372     vout_thread_t *p_vout = GetVout( p_mi, p_e );
373     int i_ret = -1;
374
375     if( !p_vout )
376         return;
377
378     i_ret = var_SetString( p_vout, "aspect-ratio", psz_aspect );
379     if( i_ret )
380         libvlc_exception_raise( p_e,
381                         "Unexpected error while setting aspect-ratio value" );
382
383     vlc_object_release( p_vout );
384 }
385
386 int libvlc_video_get_spu( libvlc_media_instance_t *p_mi,
387                           libvlc_exception_t *p_e )
388 {
389     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi, p_e );
390     vlc_value_t val_list;
391     vlc_value_t val;
392     int i_spu = -1;
393     int i_ret = -1;
394     int i;
395
396     if( !p_input_thread )
397         return -1;
398
399     i_ret = var_Get( p_input_thread, "spu-es", &val );
400     if( i_ret < 0 )
401     {
402         libvlc_exception_raise( p_e, "Getting subtitle information failed" );
403         vlc_object_release( p_input_thread );
404         return i_ret;
405     }
406
407     var_Change( p_input_thread, "spu-es", VLC_VAR_GETCHOICES, &val_list, NULL );
408     for( i = 0; i < val_list.p_list->i_count; i++ )
409     {
410         vlc_value_t spu_val = val_list.p_list->p_values[i];
411         if( val.i_int == spu_val.i_int )
412         {
413             i_spu = i;
414             break;
415         }
416     }
417     vlc_object_release( p_input_thread );
418     return i_spu;
419 }
420
421 void libvlc_video_set_spu( libvlc_media_instance_t *p_mi, int i_spu,
422                            libvlc_exception_t *p_e )
423 {
424     input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi, p_e );
425     vlc_value_t val_list;
426     int i_ret = -1;
427     int i;
428
429     if( !p_input_thread )
430         return;
431
432     var_Change( p_input_thread, "spu-es", VLC_VAR_GETCHOICES, &val_list, NULL );
433     for( i = 0; i < val_list.p_list->i_count; i++ )
434     {
435         vlc_value_t val = val_list.p_list->p_values[i];
436         if( i_spu == i )
437         {
438             vlc_value_t new_val;
439
440             new_val.i_int = val.i_int;
441             i_ret = var_Set( p_input_thread, "spu-es", new_val );
442             if( i_ret < 0 )
443             {
444                 libvlc_exception_raise( p_e, "Setting subtitle value failed" );
445             }
446             vlc_object_release( p_input_thread );
447             return;
448         }
449     }
450     libvlc_exception_raise( p_e, "Subtitle value out of range" );
451     vlc_object_release( p_input_thread );
452 }
453
454 char *libvlc_video_get_crop_geometry( libvlc_media_instance_t *p_mi,
455                                    libvlc_exception_t *p_e )
456 {
457     char *psz_geometry = 0;
458     vout_thread_t *p_vout = GetVout( p_mi, p_e );
459
460     if( !p_vout )
461         return 0;
462
463     psz_geometry = var_GetNonEmptyString( p_vout, "crop" );
464     vlc_object_release( p_vout );
465     return psz_geometry ? psz_geometry : strdup("");
466 }
467
468 void libvlc_video_set_crop_geometry( libvlc_media_instance_t *p_mi,
469                                     char *psz_geometry, libvlc_exception_t *p_e )
470 {
471     vout_thread_t *p_vout = GetVout( p_mi, p_e );
472     int i_ret = -1;
473
474     if( !p_vout )
475         return;
476
477     i_ret = var_SetString( p_vout, "crop", psz_geometry );
478     if( i_ret )
479         libvlc_exception_raise( p_e,
480                         "Unexpected error while setting crop geometry" );
481
482     vlc_object_release( p_vout );
483 }
484
485 int libvlc_video_get_teletext( libvlc_media_instance_t *p_mi,
486                                libvlc_exception_t *p_e )
487 {
488     vout_thread_t *p_vout = GetVout( p_mi, p_e );
489     vlc_object_t *p_vbi;
490     int i_ret = -1;
491
492     if( !p_vout )
493         return i_ret;
494
495     p_vbi = (vlc_object_t *) vlc_object_find_name( p_vout, "zvbi",
496                                                    FIND_ANYWHERE );
497     if( p_vbi )
498     {
499         i_ret = var_GetInteger( p_vout, "vbi-page" );
500         vlc_object_release( p_vbi );
501     }
502
503     vlc_object_release( p_vout );
504     return i_ret;
505 }
506
507 void libvlc_video_set_teletext( libvlc_media_instance_t *p_mi, int i_page,
508                                 libvlc_exception_t *p_e )
509 {
510     vout_thread_t *p_vout = GetVout( p_mi, p_e );
511     vlc_object_t *p_vbi;
512     int i_ret = -1;
513
514     if( !p_vout )
515         return;
516
517     p_vbi = (vlc_object_t *) vlc_object_find_name( p_vout, "zvbi",
518                                                    FIND_ANYWHERE );
519     if( p_vbi )
520     {
521         i_ret = var_SetInteger( p_vbi, "vbi-page", i_page );
522         vlc_object_release( p_vbi );
523     }
524     if( i_ret )
525         libvlc_exception_raise( p_e,
526                         "Unexpected error while setting teletext page" );
527     vlc_object_release( p_vout );
528 }
529
530 int libvlc_video_destroy( libvlc_media_instance_t *p_mi,
531                           libvlc_exception_t *p_e )
532 {
533     vout_thread_t *p_vout = GetVout( p_mi, p_e );
534     vlc_object_detach( p_vout );
535     vlc_object_release( p_vout );
536     vout_Destroy( p_vout );
537
538     return 0;
539 }