]> git.sesse.net Git - vlc/blob - src/control/media_player.c
update module LIST file.
[vlc] / src / control / media_player.c
1 /*****************************************************************************
2  * media_player.c: Libvlc API Media Instance management functions
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "libvlc_internal.h"
25
26 #include <vlc/libvlc.h>
27 #include <vlc_demux.h>
28 #include <vlc_input.h>
29 #include "libvlc.h"
30
31 static int
32 input_state_changed( vlc_object_t * p_this, char const * psz_cmd,
33                      vlc_value_t oldval, vlc_value_t newval,
34                      void * p_userdata );
35 static int
36 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
37                         vlc_value_t oldval, vlc_value_t newval,
38                         void * p_userdata );
39 static int
40 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
41                         vlc_value_t oldval, vlc_value_t newval,
42                         void * p_userdata );
43 static int
44 input_position_changed( vlc_object_t * p_this, char const * psz_cmd,
45                      vlc_value_t oldval, vlc_value_t newval,
46                      void * p_userdata );
47 static int
48 input_time_changed( vlc_object_t * p_this, char const * psz_cmd,
49                      vlc_value_t oldval, vlc_value_t newval,
50                      void * p_userdata );
51
52 static const libvlc_state_t vlc_to_libvlc_state_array[] =
53 {
54     [INIT_S]        = libvlc_Opening,
55     [OPENING_S]     = libvlc_Opening,
56     [BUFFERING_S]   = libvlc_Buffering,    
57     [PLAYING_S]     = libvlc_Playing,    
58     [PAUSE_S]       = libvlc_Paused,    
59     [END_S]         = libvlc_Ended,    
60     [ERROR_S]       = libvlc_Error,    
61 };
62 static inline libvlc_state_t vlc_to_libvlc_state( int vlc_state )
63 {
64     if( vlc_state < 0 || vlc_state > 6 )
65         return libvlc_Stopped;
66
67     return vlc_to_libvlc_state_array[vlc_state];
68 }
69
70 /*
71  * Release the associated input thread
72  *
73  * Object lock is NOT held.
74  */
75 static void release_input_thread( libvlc_media_player_t *p_mi )
76 {
77     input_thread_t * p_input_thread;
78
79     if( !p_mi || !p_mi->p_input_thread )
80         return;
81
82     p_input_thread = p_mi->p_input_thread;
83
84     /* No one is tracking this input_thread appart us. Destroy it */
85     if( p_mi->b_own_its_input_thread )
86     {
87         var_DelCallback( p_input_thread, "state", input_state_changed, p_mi );
88         var_DelCallback( p_input_thread, "seekable", input_seekable_changed, p_mi );
89         var_DelCallback( p_input_thread, "pausable", input_pausable_changed, p_mi );
90         var_DelCallback( p_input_thread, "intf-change", input_position_changed, p_mi );
91         var_DelCallback( p_input_thread, "intf-change", input_time_changed, p_mi );
92
93         /* We owned this one */
94         input_StopThread( p_input_thread );
95
96         var_Destroy( p_input_thread, "drawable" );
97     }
98
99     vlc_object_release( p_input_thread );
100
101     p_mi->p_input_thread = NULL;
102 }
103
104 /*
105  * Retrieve the input thread. Be sure to release the object
106  * once you are done with it. (libvlc Internal)
107  *
108  * Object lock is held.
109  */
110 input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi,
111                                          libvlc_exception_t *p_e )
112 {
113     input_thread_t *p_input_thread;
114
115     if( !p_mi ) RAISENULL( "Media Instance is NULL" );
116     
117     vlc_mutex_lock( &p_mi->object_lock );
118
119     if( !p_mi->p_input_thread )
120     {
121         vlc_mutex_unlock( &p_mi->object_lock );
122         RAISENULL( "Input is NULL" );
123     }
124
125     p_input_thread = p_mi->p_input_thread;
126     vlc_object_yield( p_input_thread );
127
128     vlc_mutex_unlock( &p_mi->object_lock );
129
130     return p_input_thread;
131 }
132
133 /*
134  * input_state_changed (Private) (input var "state" Callback)
135  */
136 static int
137 input_state_changed( vlc_object_t * p_this, char const * psz_cmd,
138                      vlc_value_t oldval, vlc_value_t newval,
139                      void * p_userdata )
140 {
141     VLC_UNUSED(oldval);
142     VLC_UNUSED(p_this);
143     VLC_UNUSED(psz_cmd);
144     libvlc_media_player_t * p_mi = p_userdata;
145     libvlc_event_t event;
146     libvlc_event_type_t type = newval.i_int;
147
148     switch ( type )
149     {
150         case END_S:
151             libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
152             event.type = libvlc_MediaPlayerEndReached;
153             break;
154         case PAUSE_S:
155             libvlc_media_set_state( p_mi->p_md, libvlc_Playing, NULL);
156             event.type = libvlc_MediaPlayerPaused;
157             break;
158         case PLAYING_S:
159             libvlc_media_set_state( p_mi->p_md, libvlc_Playing, NULL);
160             event.type = libvlc_MediaPlayerPlayed;
161             break;
162         case ERROR_S:
163             libvlc_media_set_state( p_mi->p_md, libvlc_Error, NULL);
164             event.type = libvlc_MediaPlayerEncounteredError;
165             break;
166         default:
167             return VLC_SUCCESS;
168     }
169
170     libvlc_event_send( p_mi->p_event_manager, &event );
171     return VLC_SUCCESS;
172 }
173
174 static int
175 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
176                         vlc_value_t oldval, vlc_value_t newval,
177                         void * p_userdata )
178 {
179     VLC_UNUSED(oldval);
180     VLC_UNUSED(p_this);
181     VLC_UNUSED(psz_cmd);
182     libvlc_media_player_t * p_mi = p_userdata;
183     libvlc_event_t event;
184
185     libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
186     event.type = libvlc_MediaPlayerSeekableChanged;
187     event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
188
189     libvlc_event_send( p_mi->p_event_manager, &event );
190     return VLC_SUCCESS;
191 }
192
193 static int
194 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
195                         vlc_value_t oldval, vlc_value_t newval,
196                         void * p_userdata )
197 {
198     VLC_UNUSED(oldval);
199     VLC_UNUSED(p_this);
200     VLC_UNUSED(psz_cmd);
201     libvlc_media_player_t * p_mi = p_userdata;
202     libvlc_event_t event;
203
204     libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
205     event.type = libvlc_MediaPlayerPausableChanged;
206     event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
207
208     libvlc_event_send( p_mi->p_event_manager, &event );
209     return VLC_SUCCESS;
210 }
211
212 /*
213  * input_position_changed (Private) (input var "intf-change" Callback)
214  */
215 static int
216 input_position_changed( vlc_object_t * p_this, char const * psz_cmd,
217                      vlc_value_t oldval, vlc_value_t newval,
218                      void * p_userdata )
219 {
220     VLC_UNUSED(oldval);
221     libvlc_media_player_t * p_mi = p_userdata;
222     vlc_value_t val;
223
224     if (!strncmp(psz_cmd, "intf", 4 /* "-change" no need to go further */))
225     {
226         input_thread_t * p_input = (input_thread_t *)p_this;
227
228         var_Get( p_input, "state", &val );
229         if( val.i_int != PLAYING_S )
230             return VLC_SUCCESS; /* Don't send the position while stopped */
231
232         var_Get( p_input, "position", &val );
233     }
234     else
235         val.i_time = newval.i_time;
236
237     libvlc_event_t event;
238     event.type = libvlc_MediaPlayerPositionChanged;
239     event.u.media_player_position_changed.new_position = val.f_float;
240
241     libvlc_event_send( p_mi->p_event_manager, &event );
242     return VLC_SUCCESS;
243 }
244
245 /*
246  * input_time_changed (Private) (input var "intf-change" Callback)
247  */
248 static int
249 input_time_changed( vlc_object_t * p_this, char const * psz_cmd,
250                      vlc_value_t oldval, vlc_value_t newval,
251                      void * p_userdata )
252 {
253     VLC_UNUSED(oldval);
254     libvlc_media_player_t * p_mi = p_userdata;
255     vlc_value_t val;
256
257     if (!strncmp(psz_cmd, "intf", 4 /* "-change" no need to go further */))
258     {
259         input_thread_t * p_input = (input_thread_t *)p_this;
260     
261         var_Get( p_input, "state", &val );
262         if( val.i_int != PLAYING_S )
263             return VLC_SUCCESS; /* Don't send the position while stopped */
264
265         var_Get( p_input, "time", &val );
266     }
267     else
268         val.i_time = newval.i_time;
269
270     libvlc_event_t event;
271     event.type = libvlc_MediaPlayerTimeChanged;
272     event.u.media_player_time_changed.new_time = val.i_time;
273     libvlc_event_send( p_mi->p_event_manager, &event );
274     return VLC_SUCCESS;
275 }
276
277 /**************************************************************************
278  * Create a Media Instance object
279  **************************************************************************/
280 libvlc_media_player_t *
281 libvlc_media_player_new( libvlc_instance_t * p_libvlc_instance,
282                            libvlc_exception_t * p_e )
283 {
284     libvlc_media_player_t * p_mi;
285
286     if( !p_libvlc_instance )
287     {
288         libvlc_exception_raise( p_e, "invalid libvlc instance" );
289         return NULL;
290     }
291
292     p_mi = malloc( sizeof(libvlc_media_player_t) );
293     p_mi->p_md = NULL;
294     p_mi->drawable = 0;
295     p_mi->p_libvlc_instance = p_libvlc_instance;
296     p_mi->p_input_thread = NULL;
297     /* refcount strategy:
298      * - All items created by _new start with a refcount set to 1
299      * - Accessor _release decrease the refcount by 1, if after that
300      *   operation the refcount is 0, the object is destroyed.
301      * - Accessor _retain increase the refcount by 1 (XXX: to implement) */
302     p_mi->i_refcount = 1;
303     p_mi->b_own_its_input_thread = VLC_TRUE;
304     /* object_lock strategy:
305      * - No lock held in constructor
306      * - Lock when accessing all variable this lock is held
307      * - Lock when attempting to destroy the object the lock is also held */
308     vlc_mutex_init( p_mi->p_libvlc_instance->p_libvlc_int,
309                     &p_mi->object_lock );
310     p_mi->p_event_manager = libvlc_event_manager_new( p_mi,
311             p_libvlc_instance, p_e );
312     if( libvlc_exception_raised( p_e ) )
313     {
314         free( p_mi );
315         return NULL;
316     }
317
318     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
319             libvlc_MediaPlayerEndReached, p_e );
320     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
321             libvlc_MediaPlayerStopped, p_e );
322     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
323             libvlc_MediaPlayerEncounteredError, p_e );
324     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
325             libvlc_MediaPlayerPaused, p_e );
326     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
327             libvlc_MediaPlayerPlayed, p_e );
328     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
329             libvlc_MediaPlayerPositionChanged, p_e );
330     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
331             libvlc_MediaPlayerTimeChanged, p_e );
332     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
333             libvlc_MediaPlayerSeekableChanged, p_e );
334     libvlc_event_manager_register_event_type( p_mi->p_event_manager,
335             libvlc_MediaPlayerPausableChanged, p_e );
336
337     return p_mi;
338 }
339
340 /**************************************************************************
341  * Create a Media Instance object with a media descriptor
342  **************************************************************************/
343 libvlc_media_player_t *
344 libvlc_media_player_new_from_media(
345                                     libvlc_media_t * p_md,
346                                     libvlc_exception_t *p_e )
347 {
348     libvlc_media_player_t * p_mi;
349     p_mi = libvlc_media_player_new( p_md->p_libvlc_instance, p_e );
350
351     if( !p_mi )
352         return NULL;
353
354     libvlc_media_retain( p_md );
355     p_mi->p_md = p_md;
356
357     return p_mi;
358 }
359
360 /**************************************************************************
361  * Create a new media instance object from an input_thread (Libvlc Internal)
362  **************************************************************************/
363 libvlc_media_player_t * libvlc_media_player_new_from_input_thread(
364                                    struct libvlc_instance_t *p_libvlc_instance,
365                                    input_thread_t *p_input,
366                                    libvlc_exception_t *p_e )
367 {
368     libvlc_media_player_t * p_mi;
369
370     if( !p_input )
371     {
372         libvlc_exception_raise( p_e, "invalid input thread" );
373         return NULL;
374     }
375
376     p_mi = libvlc_media_player_new( p_libvlc_instance, p_e );
377
378     if( !p_mi )
379         return NULL;
380
381     p_mi->p_md = libvlc_media_new_from_input_item(
382                     p_libvlc_instance,
383                     input_GetItem( p_input ), p_e );
384
385     if( !p_mi->p_md )
386     {
387         libvlc_media_player_destroy( p_mi );
388         return NULL;
389     }
390
391     /* will be released in media_player_release() */
392     vlc_object_yield( p_input );
393
394     p_mi->p_input_thread = p_input;
395     p_mi->b_own_its_input_thread = VLC_FALSE;
396
397     return p_mi;
398 }
399
400 /**************************************************************************
401  * Destroy a Media Instance object (libvlc internal)
402  *
403  * Warning: No lock held here, but hey, this is internal.
404  **************************************************************************/
405 void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
406 {
407     input_thread_t *p_input_thread;
408     libvlc_exception_t p_e;
409
410     libvlc_exception_init( &p_e );
411
412     if( !p_mi )
413         return;
414
415     p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
416
417     if( libvlc_exception_raised( &p_e ) )
418     {
419         libvlc_event_manager_release( p_mi->p_event_manager );
420         libvlc_exception_clear( &p_e );
421         free( p_mi );
422         return; /* no need to worry about no input thread */
423     }
424     vlc_mutex_destroy( &p_mi->object_lock );
425
426     vlc_object_release( p_input_thread );
427
428     libvlc_media_release( p_mi->p_md );
429
430     free( p_mi );
431 }
432
433 /**************************************************************************
434  * Release a Media Instance object
435  **************************************************************************/
436 void libvlc_media_player_release( libvlc_media_player_t *p_mi )
437 {
438     if( !p_mi )
439         return;
440
441     vlc_mutex_lock( &p_mi->object_lock );
442  
443     p_mi->i_refcount--;
444
445     if( p_mi->i_refcount > 0 )
446     {
447         vlc_mutex_unlock( &p_mi->object_lock );
448         return;
449     }
450     vlc_mutex_unlock( &p_mi->object_lock );
451     vlc_mutex_destroy( &p_mi->object_lock );
452
453     release_input_thread( p_mi );
454
455     libvlc_event_manager_release( p_mi->p_event_manager );
456  
457     libvlc_media_release( p_mi->p_md );
458
459     free( p_mi );
460 }
461
462 /**************************************************************************
463  * Retain a Media Instance object
464  **************************************************************************/
465 void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
466 {
467     if( !p_mi )
468         return;
469
470     p_mi->i_refcount++;
471 }
472
473 /**************************************************************************
474  * Set the Media descriptor associated with the instance
475  **************************************************************************/
476 void libvlc_media_player_set_media(
477                             libvlc_media_player_t *p_mi,
478                             libvlc_media_t *p_md,
479                             libvlc_exception_t *p_e )
480 {
481     (void)p_e;
482
483     if( !p_mi )
484         return;
485
486     vlc_mutex_lock( &p_mi->object_lock );
487
488     release_input_thread( p_mi );
489
490     if( p_mi->p_md )
491         libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL );
492
493     libvlc_media_release( p_mi->p_md );
494
495     if( !p_md )
496     {
497         p_mi->p_md = NULL;
498         vlc_mutex_unlock( &p_mi->object_lock );
499         return; /* It is ok to pass a NULL md */
500     }
501
502     libvlc_media_retain( p_md );
503     p_mi->p_md = p_md;
504  
505     /* The policy here is to ignore that we were created using a different
506      * libvlc_instance, because we don't really care */
507     p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
508
509     vlc_mutex_unlock( &p_mi->object_lock );
510 }
511
512 /**************************************************************************
513  * Get the Media descriptor associated with the instance
514  **************************************************************************/
515 libvlc_media_t *
516 libvlc_media_player_get_media(
517                             libvlc_media_player_t *p_mi,
518                             libvlc_exception_t *p_e )
519 {
520     (void)p_e;
521
522     if( !p_mi->p_md )
523         return NULL;
524
525     libvlc_media_retain( p_mi->p_md );
526     return p_mi->p_md;
527 }
528
529 /**************************************************************************
530  * Get the event Manager
531  **************************************************************************/
532 libvlc_event_manager_t *
533 libvlc_media_player_event_manager(
534                             libvlc_media_player_t *p_mi,
535                             libvlc_exception_t *p_e )
536 {
537     (void)p_e;
538
539     return p_mi->p_event_manager;
540 }
541
542 /**************************************************************************
543  * Play
544  **************************************************************************/
545 void libvlc_media_player_play( libvlc_media_player_t *p_mi,
546                                  libvlc_exception_t *p_e )
547 {
548     input_thread_t * p_input_thread;
549
550     if( (p_input_thread = libvlc_get_input_thread( p_mi, p_e )) )
551     {
552         /* A thread already exists, send it a play message */
553         input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
554         vlc_object_release( p_input_thread );
555         return;
556     }
557
558     /* Ignore previous exception */
559     libvlc_exception_clear( p_e );
560
561     vlc_mutex_lock( &p_mi->object_lock );
562  
563     if( !p_mi->p_md )
564     {
565         libvlc_exception_raise( p_e, "no associated media descriptor" );
566         vlc_mutex_unlock( &p_mi->object_lock );
567         return;
568     }
569
570     p_mi->p_input_thread = input_CreateThread( p_mi->p_libvlc_instance->p_libvlc_int,
571                       p_mi->p_md->p_input_item );
572
573
574     if( !p_mi->p_input_thread )
575     {
576         vlc_mutex_unlock( &p_mi->object_lock );
577         return;
578     }
579
580     p_input_thread = p_mi->p_input_thread;
581
582     if( p_mi->drawable )
583     {
584         vlc_value_t val;
585         val.i_int = p_mi->drawable;
586         var_Create( p_input_thread, "drawable", VLC_VAR_DOINHERIT );
587         var_Set( p_input_thread, "drawable", val );
588     }
589     var_AddCallback( p_input_thread, "state", input_state_changed, p_mi );
590     var_AddCallback( p_input_thread, "seekable", input_seekable_changed, p_mi );
591     var_AddCallback( p_input_thread, "pausable", input_pausable_changed, p_mi );
592     var_AddCallback( p_input_thread, "intf-change", input_position_changed, p_mi );
593     var_AddCallback( p_input_thread, "intf-change", input_time_changed, p_mi );
594
595     vlc_mutex_unlock( &p_mi->object_lock );
596 }
597
598 /**************************************************************************
599  * Pause
600  **************************************************************************/
601 void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
602                                   libvlc_exception_t *p_e )
603 {
604     input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
605
606     if( !p_input_thread )
607         return;
608
609     int state = var_GetInteger( p_input_thread, "state" );
610
611     if( state == PLAYING_S )
612     {
613         if( libvlc_media_player_can_pause( p_mi, p_e ) )
614             input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
615         else
616             libvlc_media_player_stop( p_mi, p_e );
617     }
618     else
619         input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
620
621     vlc_object_release( p_input_thread );
622 }
623
624 /**************************************************************************
625  * Stop
626  **************************************************************************/
627 void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
628                                  libvlc_exception_t *p_e )
629 {
630     if( p_mi->b_own_its_input_thread )
631     {
632         vlc_mutex_lock( &p_mi->object_lock );
633         release_input_thread( p_mi ); /* This will stop the input thread */
634         vlc_mutex_unlock( &p_mi->object_lock );
635     }
636     else
637     {
638         input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
639
640         if( !p_input_thread )
641             return;
642
643         input_StopThread( p_input_thread );
644         vlc_object_release( p_input_thread );
645     }
646
647     /* Send a stop notification event */
648     libvlc_event_t event;
649     libvlc_media_set_state( p_mi->p_md, libvlc_Stopped, NULL);
650     event.type = libvlc_MediaPlayerStopped;
651     libvlc_event_send( p_mi->p_event_manager, &event );
652 }
653
654 /**************************************************************************
655  * Set Drawable
656  **************************************************************************/
657 void libvlc_media_player_set_drawable( libvlc_media_player_t *p_mi,
658                                          libvlc_drawable_t drawable,
659                                          libvlc_exception_t *p_e )
660 {
661     (void)p_e;
662     p_mi->drawable = drawable;
663 }
664
665 /**************************************************************************
666  * Get Drawable
667  **************************************************************************/
668 libvlc_drawable_t
669 libvlc_media_player_get_drawable ( libvlc_media_player_t *p_mi, libvlc_exception_t *p_e )
670 {
671     (void)p_e;
672     return p_mi->drawable;
673 }
674
675 /**************************************************************************
676  * Getters for stream information
677  **************************************************************************/
678 libvlc_time_t libvlc_media_player_get_length(
679                              libvlc_media_player_t *p_mi,
680                              libvlc_exception_t *p_e )
681 {
682     input_thread_t *p_input_thread;
683     vlc_value_t val;
684
685     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
686     if( !p_input_thread )
687         return -1;
688
689     var_Get( p_input_thread, "length", &val );
690     vlc_object_release( p_input_thread );
691
692     return (val.i_time+500LL)/1000LL;
693 }
694
695 libvlc_time_t libvlc_media_player_get_time(
696                                    libvlc_media_player_t *p_mi,
697                                    libvlc_exception_t *p_e )
698 {
699     input_thread_t *p_input_thread;
700     vlc_value_t val;
701
702     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
703     if( !p_input_thread )
704         return -1;
705
706     var_Get( p_input_thread , "time", &val );
707     vlc_object_release( p_input_thread );
708     return (val.i_time+500LL)/1000LL;
709 }
710
711 void libvlc_media_player_set_time(
712                                  libvlc_media_player_t *p_mi,
713                                  libvlc_time_t time,
714                                  libvlc_exception_t *p_e )
715 {
716     input_thread_t *p_input_thread;
717     vlc_value_t value;
718
719     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
720     if( !p_input_thread )
721         return;
722
723     value.i_time = time*1000LL;
724     var_Set( p_input_thread, "time", value );
725     vlc_object_release( p_input_thread );
726 }
727
728 void libvlc_media_player_set_position(
729                                 libvlc_media_player_t *p_mi,
730                                 float position,
731                                 libvlc_exception_t *p_e )
732 {
733     input_thread_t *p_input_thread;
734     vlc_value_t val;
735     val.f_float = position;
736
737     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
738     if( !p_input_thread )
739         return;
740
741     var_Set( p_input_thread, "position", val );
742     vlc_object_release( p_input_thread );
743 }
744
745 float libvlc_media_player_get_position(
746                                  libvlc_media_player_t *p_mi,
747                                  libvlc_exception_t *p_e )
748 {
749     input_thread_t *p_input_thread;
750     vlc_value_t val;
751
752     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
753     if( !p_input_thread )
754         return -1.0;
755
756     var_Get( p_input_thread, "position", &val );
757     vlc_object_release( p_input_thread );
758
759     return val.f_float;
760 }
761
762 void libvlc_media_player_set_chapter(
763                                  libvlc_media_player_t *p_mi,
764                                  int chapter,
765                                  libvlc_exception_t *p_e )
766 {
767     input_thread_t *p_input_thread;
768     vlc_value_t val;
769     val.i_int = chapter;
770
771     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
772     if( !p_input_thread )
773         return;
774
775     var_Set( p_input_thread, "chapter", val );
776     vlc_object_release( p_input_thread );
777 }
778
779 int libvlc_media_player_get_chapter(
780                                  libvlc_media_player_t *p_mi,
781                                  libvlc_exception_t *p_e )
782 {
783     input_thread_t *p_input_thread;
784     vlc_value_t val;
785
786     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
787     if( !p_input_thread )
788         return -1.0;
789
790     var_Get( p_input_thread, "chapter", &val );
791     vlc_object_release( p_input_thread );
792
793     return val.i_int;
794 }
795
796 int libvlc_media_player_get_chapter_count(
797                                  libvlc_media_player_t *p_mi,
798                                  libvlc_exception_t *p_e )
799 {
800     input_thread_t *p_input_thread;
801     vlc_value_t val;
802
803     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
804     if( !p_input_thread )
805         return -1.0;
806
807     var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
808     vlc_object_release( p_input_thread );
809
810     return val.i_int;
811 }
812
813 float libvlc_media_player_get_fps(
814                                  libvlc_media_player_t *p_mi,
815                                  libvlc_exception_t *p_e)
816 {
817     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
818     double f_fps = 0.0;
819
820     if( p_input_thread )
821     {
822         if( input_Control( p_input_thread, INPUT_GET_VIDEO_FPS, &f_fps ) )
823             f_fps = 0.0;
824         vlc_object_release( p_input_thread );
825     }
826     return f_fps;
827 }
828
829 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi,
830                                      libvlc_exception_t *p_e)
831 {
832     input_thread_t *p_input_thread =
833                             libvlc_get_input_thread ( p_mi, p_e);
834     if ( !p_input_thread )
835         return VLC_FALSE;
836
837     if ( !p_input_thread->b_die && !p_input_thread->b_dead )
838     {
839         vlc_object_release( p_input_thread );
840         return VLC_TRUE;
841     }
842     vlc_object_release( p_input_thread );
843     return VLC_FALSE;
844 }
845
846 void libvlc_media_player_set_rate(
847                                  libvlc_media_player_t *p_mi,
848                                  float rate,
849                                  libvlc_exception_t *p_e )
850 {
851     input_thread_t *p_input_thread;
852     vlc_value_t val;
853
854     if( rate <= 0 )
855         RAISEVOID( "Rate value is invalid" );
856
857     val.i_int = 1000.0f/rate;
858
859     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
860     if ( !p_input_thread )
861         return;
862
863     var_Set( p_input_thread, "rate", val );
864     vlc_object_release( p_input_thread );
865 }
866
867 float libvlc_media_player_get_rate(
868                                  libvlc_media_player_t *p_mi,
869                                  libvlc_exception_t *p_e )
870 {
871     input_thread_t *p_input_thread;
872     vlc_value_t val;
873
874     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
875     if ( !p_input_thread )
876         return -1.0;
877
878     var_Get( p_input_thread, "rate", &val );
879     vlc_object_release( p_input_thread );
880
881     return (float)1000.0f/val.i_int;
882 }
883
884 libvlc_state_t libvlc_media_player_get_state(
885                                  libvlc_media_player_t *p_mi,
886                                  libvlc_exception_t *p_e )
887 {
888     input_thread_t *p_input_thread;
889     vlc_value_t val;
890
891     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
892     if ( !p_input_thread )
893     {
894         /* We do return the right value, no need to throw an exception */
895         if( libvlc_exception_raised( p_e ) )
896             libvlc_exception_clear( p_e );
897         return libvlc_Stopped;
898     }
899
900     var_Get( p_input_thread, "state", &val );
901     vlc_object_release( p_input_thread );
902
903     return vlc_to_libvlc_state(val.i_int);
904 }
905
906 int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi,
907                                        libvlc_exception_t *p_e )
908 {
909     input_thread_t *p_input_thread;
910     vlc_value_t val;
911
912     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
913     if ( !p_input_thread )
914     {
915         /* We do return the right value, no need to throw an exception */
916         if( libvlc_exception_raised( p_e ) )
917             libvlc_exception_clear( p_e );
918         return VLC_FALSE;
919     }
920     var_Get( p_input_thread, "seekable", &val );
921     vlc_object_release( p_input_thread );
922
923     return val.b_bool;
924 }
925
926 int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi,
927                                      libvlc_exception_t *p_e )
928 {
929     input_thread_t *p_input_thread;
930     vlc_value_t val;
931
932     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
933     if ( !p_input_thread )
934     {
935         /* We do return the right value, no need to throw an exception */
936         if( libvlc_exception_raised( p_e ) )
937             libvlc_exception_clear( p_e );
938         return VLC_FALSE;
939     }
940     var_Get( p_input_thread, "can-pause", &val );
941     vlc_object_release( p_input_thread );
942
943     return val.b_bool;
944 }