1 /*****************************************************************************
2 * media_player.c: Libvlc API Media Instance management functions
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
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.
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.
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 *****************************************************************************/
24 #include "libvlc_internal.h"
26 #include <vlc/libvlc.h>
27 #include <vlc_demux.h>
28 #include <vlc_input.h>
34 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
35 vlc_value_t oldval, vlc_value_t newval,
38 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
39 vlc_value_t oldval, vlc_value_t newval,
42 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
43 vlc_value_t oldval, vlc_value_t newval,
46 static int SnapshotTakenCallback( vlc_object_t *p_this, char const *psz_cmd,
47 vlc_value_t oldval, vlc_value_t newval, void *p_data );
49 static const libvlc_state_t vlc_to_libvlc_state_array[] =
51 [INIT_S] = libvlc_NothingSpecial,
52 [OPENING_S] = libvlc_Opening,
53 [PLAYING_S] = libvlc_Playing,
54 [PAUSE_S] = libvlc_Paused,
55 [END_S] = libvlc_Ended,
56 [ERROR_S] = libvlc_Error,
59 static inline libvlc_state_t vlc_to_libvlc_state( int vlc_state )
61 if( vlc_state < 0 || vlc_state > 6 )
64 return vlc_to_libvlc_state_array[vlc_state];
68 * Release the associated input thread
70 * Object lock is NOT held.
72 static void release_input_thread( libvlc_media_player_t *p_mi )
74 input_thread_t * p_input_thread;
76 if( !p_mi || !p_mi->p_input_thread )
79 p_input_thread = p_mi->p_input_thread;
81 /* No one is tracking this input_thread appart us. Destroy it */
82 if( p_mi->b_own_its_input_thread )
84 var_DelCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
85 var_DelCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
86 var_DelCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
88 /* We owned this one */
89 input_StopThread( p_input_thread );
90 vlc_thread_join( p_input_thread );
92 var_Destroy( p_input_thread, "drawable" );
95 vlc_object_release( p_input_thread );
97 p_mi->p_input_thread = NULL;
101 * Retrieve the input thread. Be sure to release the object
102 * once you are done with it. (libvlc Internal)
104 * Object lock is held.
106 input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi,
107 libvlc_exception_t *p_e )
109 input_thread_t *p_input_thread;
111 if( !p_mi ) RAISENULL( "Media Instance is NULL" );
113 vlc_mutex_lock( &p_mi->object_lock );
115 if( !p_mi->p_input_thread )
117 vlc_mutex_unlock( &p_mi->object_lock );
118 RAISENULL( "Input is NULL" );
121 p_input_thread = p_mi->p_input_thread;
122 vlc_object_hold( p_input_thread );
124 vlc_mutex_unlock( &p_mi->object_lock );
126 return p_input_thread;
130 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
131 vlc_value_t oldval, vlc_value_t newval,
137 libvlc_media_player_t * p_mi = p_userdata;
138 libvlc_event_t event;
140 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
141 event.type = libvlc_MediaPlayerSeekableChanged;
142 event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
144 libvlc_event_send( p_mi->p_event_manager, &event );
149 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
150 vlc_value_t oldval, vlc_value_t newval,
156 libvlc_media_player_t * p_mi = p_userdata;
157 libvlc_event_t event;
159 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
160 event.type = libvlc_MediaPlayerPausableChanged;
161 event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
163 libvlc_event_send( p_mi->p_event_manager, &event );
168 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
169 vlc_value_t oldval, vlc_value_t newval,
173 input_thread_t * p_input = (input_thread_t *)p_this;
174 libvlc_media_player_t * p_mi = p_userdata;
175 libvlc_event_t event;
177 assert( !strcmp( psz_cmd, "intf-event" ) );
179 if( newval.i_int == INPUT_EVENT_STATE )
181 libvlc_state_t libvlc_state;
183 switch ( var_GetInteger( p_input, "state" ) )
186 libvlc_state = libvlc_NothingSpecial;
187 event.type = libvlc_MediaPlayerNothingSpecial;
190 libvlc_state = libvlc_Opening;
191 event.type = libvlc_MediaPlayerOpening;
194 libvlc_state = libvlc_Playing;
195 event.type = libvlc_MediaPlayerPlaying;
198 libvlc_state = libvlc_Paused;
199 event.type = libvlc_MediaPlayerPaused;
202 libvlc_state = libvlc_Ended;
203 event.type = libvlc_MediaPlayerEndReached;
206 libvlc_state = libvlc_Error;
207 event.type = libvlc_MediaPlayerEncounteredError;
214 libvlc_media_set_state( p_mi->p_md, libvlc_state, NULL);
215 libvlc_event_send( p_mi->p_event_manager, &event );
217 else if( newval.i_int == INPUT_EVENT_TIMES )
219 if( var_GetInteger( p_input, "state" ) != PLAYING_S )
220 return VLC_SUCCESS; /* Don't send the position while stopped */
223 event.type = libvlc_MediaPlayerPositionChanged;
224 event.u.media_player_position_changed.new_position = var_GetFloat( p_input, "position" );;
225 libvlc_event_send( p_mi->p_event_manager, &event );
228 event.type = libvlc_MediaPlayerTimeChanged;
229 event.u.media_player_time_changed.new_time = var_GetTime( p_input, "time" );
230 libvlc_event_send( p_mi->p_event_manager, &event );
238 /**************************************************************************
239 * Create a Media Instance object
240 **************************************************************************/
241 libvlc_media_player_t *
242 libvlc_media_player_new( libvlc_instance_t * p_libvlc_instance,
243 libvlc_exception_t * p_e )
245 libvlc_media_player_t * p_mi;
247 if( !p_libvlc_instance )
249 libvlc_exception_raise( p_e, "invalid libvlc instance" );
253 p_mi = malloc( sizeof(libvlc_media_player_t) );
256 libvlc_exception_raise( p_e, "Not enough memory" );
261 p_mi->p_libvlc_instance = p_libvlc_instance;
262 p_mi->p_input_thread = NULL;
263 /* refcount strategy:
264 * - All items created by _new start with a refcount set to 1
265 * - Accessor _release decrease the refcount by 1, if after that
266 * operation the refcount is 0, the object is destroyed.
267 * - Accessor _retain increase the refcount by 1 (XXX: to implement) */
268 p_mi->i_refcount = 1;
269 p_mi->b_own_its_input_thread = true;
270 /* object_lock strategy:
271 * - No lock held in constructor
272 * - Lock when accessing all variable this lock is held
273 * - Lock when attempting to destroy the object the lock is also held */
274 vlc_mutex_init( &p_mi->object_lock );
275 p_mi->p_event_manager = libvlc_event_manager_new( p_mi,
276 p_libvlc_instance, p_e );
277 if( libvlc_exception_raised( p_e ) )
283 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
284 libvlc_MediaPlayerNothingSpecial, p_e );
285 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
286 libvlc_MediaPlayerOpening, p_e );
287 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
288 libvlc_MediaPlayerBuffering, p_e );
289 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
290 libvlc_MediaPlayerPlaying, p_e );
291 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
292 libvlc_MediaPlayerPaused, p_e );
293 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
294 libvlc_MediaPlayerStopped, p_e );
295 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
296 libvlc_MediaPlayerForward, p_e );
297 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
298 libvlc_MediaPlayerBackward, p_e );
299 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
300 libvlc_MediaPlayerEndReached, p_e );
301 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
302 libvlc_MediaPlayerEncounteredError, p_e );
304 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
305 libvlc_MediaPlayerPositionChanged, p_e );
306 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
307 libvlc_MediaPlayerTimeChanged, p_e );
308 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
309 libvlc_MediaPlayerTitleChanged, p_e );
310 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
311 libvlc_MediaPlayerSeekableChanged, p_e );
312 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
313 libvlc_MediaPlayerPausableChanged, p_e );
315 /* Snapshot initialization */
316 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
317 libvlc_MediaPlayerSnapshotTaken, p_e );
318 /* Attach a var callback to the global object to provide the glue between
319 vout_thread that generates the event and media_player that re-emits it
320 with its own event manager
322 var_Create( p_libvlc_instance->p_libvlc_int, "vout-snapshottaken", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
323 var_AddCallback( p_libvlc_instance->p_libvlc_int, "vout-snapshottaken", SnapshotTakenCallback, p_mi );
328 /**************************************************************************
329 * Create a Media Instance object with a media descriptor
330 **************************************************************************/
331 libvlc_media_player_t *
332 libvlc_media_player_new_from_media(
333 libvlc_media_t * p_md,
334 libvlc_exception_t *p_e )
336 libvlc_media_player_t * p_mi;
337 p_mi = libvlc_media_player_new( p_md->p_libvlc_instance, p_e );
342 libvlc_media_retain( p_md );
348 /**************************************************************************
349 * Create a new media instance object from an input_thread (Libvlc Internal)
350 **************************************************************************/
351 libvlc_media_player_t * libvlc_media_player_new_from_input_thread(
352 struct libvlc_instance_t *p_libvlc_instance,
353 input_thread_t *p_input,
354 libvlc_exception_t *p_e )
356 libvlc_media_player_t * p_mi;
360 libvlc_exception_raise( p_e, "invalid input thread" );
364 p_mi = libvlc_media_player_new( p_libvlc_instance, p_e );
369 p_mi->p_md = libvlc_media_new_from_input_item(
371 input_GetItem( p_input ), p_e );
375 libvlc_media_player_destroy( p_mi );
379 /* will be released in media_player_release() */
380 vlc_object_hold( p_input );
382 p_mi->p_input_thread = p_input;
383 p_mi->b_own_its_input_thread = false;
388 /**************************************************************************
389 * Destroy a Media Instance object (libvlc internal)
391 * Warning: No lock held here, but hey, this is internal.
392 **************************************************************************/
393 void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
395 input_thread_t *p_input_thread;
396 libvlc_exception_t p_e;
398 libvlc_exception_init( &p_e );
403 /* Detach Callback from the main libvlc object */
404 var_DelCallback( p_mi->p_libvlc_instance->p_libvlc_int, "vout-snapshottaken", SnapshotTakenCallback, p_mi );
406 p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
408 if( libvlc_exception_raised( &p_e ) )
410 libvlc_event_manager_release( p_mi->p_event_manager );
411 libvlc_exception_clear( &p_e );
413 return; /* no need to worry about no input thread */
415 vlc_mutex_destroy( &p_mi->object_lock );
417 vlc_object_release( p_input_thread );
419 libvlc_media_release( p_mi->p_md );
424 /**************************************************************************
425 * Release a Media Instance object
426 **************************************************************************/
427 void libvlc_media_player_release( libvlc_media_player_t *p_mi )
432 vlc_mutex_lock( &p_mi->object_lock );
436 if( p_mi->i_refcount > 0 )
438 vlc_mutex_unlock( &p_mi->object_lock );
441 vlc_mutex_unlock( &p_mi->object_lock );
442 vlc_mutex_destroy( &p_mi->object_lock );
444 release_input_thread( p_mi );
446 libvlc_event_manager_release( p_mi->p_event_manager );
448 libvlc_media_release( p_mi->p_md );
453 /**************************************************************************
454 * Retain a Media Instance object
455 **************************************************************************/
456 void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
464 /**************************************************************************
465 * Set the Media descriptor associated with the instance
466 **************************************************************************/
467 void libvlc_media_player_set_media(
468 libvlc_media_player_t *p_mi,
469 libvlc_media_t *p_md,
470 libvlc_exception_t *p_e )
477 vlc_mutex_lock( &p_mi->object_lock );
479 release_input_thread( p_mi );
482 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, p_e );
484 libvlc_media_release( p_mi->p_md );
489 vlc_mutex_unlock( &p_mi->object_lock );
490 return; /* It is ok to pass a NULL md */
493 libvlc_media_retain( p_md );
496 /* The policy here is to ignore that we were created using a different
497 * libvlc_instance, because we don't really care */
498 p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
500 vlc_mutex_unlock( &p_mi->object_lock );
503 /**************************************************************************
504 * Get the Media descriptor associated with the instance
505 **************************************************************************/
507 libvlc_media_player_get_media(
508 libvlc_media_player_t *p_mi,
509 libvlc_exception_t *p_e )
516 libvlc_media_retain( p_mi->p_md );
520 /**************************************************************************
521 * Get the event Manager
522 **************************************************************************/
523 libvlc_event_manager_t *
524 libvlc_media_player_event_manager(
525 libvlc_media_player_t *p_mi,
526 libvlc_exception_t *p_e )
530 return p_mi->p_event_manager;
533 /**************************************************************************
534 * Trigger a snapshot Taken Event
535 *************************************************************************/
536 static int SnapshotTakenCallback( vlc_object_t *p_this, char const *psz_cmd,
537 vlc_value_t oldval, vlc_value_t newval, void *p_data )
539 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
542 libvlc_media_player_t* p_mi = (libvlc_media_player_t*) p_data ;
543 libvlc_event_t event ;
544 event.type = libvlc_MediaPlayerSnapshotTaken ;
545 event.u.media_player_snapshot_taken.psz_filename = newval.psz_string ;
546 /* Snapshot psz data is a vlc_variable owned by libvlc object .
547 Its memmory management is taken care by the obj*/
548 msg_Dbg( p_this, "about to emit libvlc_snapshot_taken.make psz_str=0x%x (%s)",
549 event.u.media_player_snapshot_taken.psz_filename ,event.u.media_player_snapshot_taken.psz_filename );
550 libvlc_event_send( p_mi->p_event_manager, &event );
555 /**************************************************************************
557 **************************************************************************/
558 void libvlc_media_player_play( libvlc_media_player_t *p_mi,
559 libvlc_exception_t *p_e )
561 input_thread_t * p_input_thread;
563 if( (p_input_thread = libvlc_get_input_thread( p_mi, p_e )) )
565 /* A thread already exists, send it a play message */
566 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
567 vlc_object_release( p_input_thread );
571 /* Ignore previous exception */
572 libvlc_exception_clear( p_e );
574 vlc_mutex_lock( &p_mi->object_lock );
578 libvlc_exception_raise( p_e, "no associated media descriptor" );
579 vlc_mutex_unlock( &p_mi->object_lock );
583 p_mi->p_input_thread = input_CreateThread( p_mi->p_libvlc_instance->p_libvlc_int,
584 p_mi->p_md->p_input_item );
587 if( !p_mi->p_input_thread )
589 vlc_mutex_unlock( &p_mi->object_lock );
593 p_input_thread = p_mi->p_input_thread;
598 val.i_int = p_mi->drawable;
599 var_Create( p_input_thread, "drawable", VLC_VAR_DOINHERIT );
600 var_Set( p_input_thread, "drawable", val );
603 var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
604 var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
605 var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
607 vlc_mutex_unlock( &p_mi->object_lock );
610 /**************************************************************************
612 **************************************************************************/
613 void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
614 libvlc_exception_t *p_e )
616 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
618 if( !p_input_thread )
621 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
623 if( state == libvlc_Playing )
625 if( libvlc_media_player_can_pause( p_mi, p_e ) )
626 input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
628 libvlc_media_player_stop( p_mi, p_e );
631 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
633 vlc_object_release( p_input_thread );
636 /**************************************************************************
638 **************************************************************************/
639 int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi,
640 libvlc_exception_t *p_e )
642 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
644 if( !p_input_thread )
647 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
649 vlc_object_release( p_input_thread );
651 if( state == libvlc_Playing )
659 /**************************************************************************
661 **************************************************************************/
662 void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
663 libvlc_exception_t *p_e )
665 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
667 if( state == libvlc_Playing || state == libvlc_Paused )
669 /* Send a stop notification event only of we are in playing or paused states */
670 libvlc_media_set_state( p_mi->p_md, libvlc_Ended, p_e );
672 /* Construct and send the event */
673 libvlc_event_t event;
674 event.type = libvlc_MediaPlayerStopped;
675 libvlc_event_send( p_mi->p_event_manager, &event );
678 if( p_mi->b_own_its_input_thread )
680 vlc_mutex_lock( &p_mi->object_lock );
681 release_input_thread( p_mi ); /* This will stop the input thread */
682 vlc_mutex_unlock( &p_mi->object_lock );
686 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
688 if( !p_input_thread )
691 input_StopThread( p_input_thread );
692 vlc_object_release( p_input_thread );
696 /**************************************************************************
698 **************************************************************************/
699 void libvlc_media_player_set_drawable( libvlc_media_player_t *p_mi,
700 libvlc_drawable_t drawable,
701 libvlc_exception_t *p_e )
703 input_thread_t *p_input_thread;
704 vout_thread_t *p_vout = NULL;
706 p_mi->drawable = drawable;
708 /* Allow on the fly drawable changing. This is tricky has this may
709 * not be supported by every vout. We though can't disable it
710 * because of some creepy drawable type that are not flexible enough
711 * (Win32 HWND for instance) */
712 p_input_thread = libvlc_get_input_thread( p_mi, p_e );
713 if( !p_input_thread ) {
714 /* No input, nothing more to do, we are fine */
715 libvlc_exception_clear( p_e );
719 p_vout = vlc_object_find( p_input_thread, VLC_OBJECT_VOUT, FIND_CHILD );
722 vout_Control( p_vout , VOUT_REPARENT, drawable);
723 vlc_object_release( p_vout );
725 vlc_object_release( p_input_thread );
728 /**************************************************************************
730 **************************************************************************/
732 libvlc_media_player_get_drawable ( libvlc_media_player_t *p_mi, libvlc_exception_t *p_e )
735 return p_mi->drawable;
738 /**************************************************************************
739 * Getters for stream information
740 **************************************************************************/
741 libvlc_time_t libvlc_media_player_get_length(
742 libvlc_media_player_t *p_mi,
743 libvlc_exception_t *p_e )
745 input_thread_t *p_input_thread;
748 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
749 if( !p_input_thread )
752 var_Get( p_input_thread, "length", &val );
753 vlc_object_release( p_input_thread );
755 return (val.i_time+500LL)/1000LL;
758 libvlc_time_t libvlc_media_player_get_time(
759 libvlc_media_player_t *p_mi,
760 libvlc_exception_t *p_e )
762 input_thread_t *p_input_thread;
765 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
766 if( !p_input_thread )
769 var_Get( p_input_thread , "time", &val );
770 vlc_object_release( p_input_thread );
771 return (val.i_time+500LL)/1000LL;
774 void libvlc_media_player_set_time(
775 libvlc_media_player_t *p_mi,
777 libvlc_exception_t *p_e )
779 input_thread_t *p_input_thread;
782 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
783 if( !p_input_thread )
786 value.i_time = time*1000LL;
787 var_Set( p_input_thread, "time", value );
788 vlc_object_release( p_input_thread );
791 void libvlc_media_player_set_position(
792 libvlc_media_player_t *p_mi,
794 libvlc_exception_t *p_e )
796 input_thread_t *p_input_thread;
798 val.f_float = position;
800 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
801 if( !p_input_thread )
804 var_Set( p_input_thread, "position", val );
805 vlc_object_release( p_input_thread );
808 float libvlc_media_player_get_position(
809 libvlc_media_player_t *p_mi,
810 libvlc_exception_t *p_e )
812 input_thread_t *p_input_thread;
815 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
816 if( !p_input_thread )
819 var_Get( p_input_thread, "position", &val );
820 vlc_object_release( p_input_thread );
825 void libvlc_media_player_set_chapter(
826 libvlc_media_player_t *p_mi,
828 libvlc_exception_t *p_e )
830 input_thread_t *p_input_thread;
834 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
835 if( !p_input_thread )
838 var_Set( p_input_thread, "chapter", val );
839 vlc_object_release( p_input_thread );
842 int libvlc_media_player_get_chapter(
843 libvlc_media_player_t *p_mi,
844 libvlc_exception_t *p_e )
846 input_thread_t *p_input_thread;
849 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
850 if( !p_input_thread )
853 var_Get( p_input_thread, "chapter", &val );
854 vlc_object_release( p_input_thread );
859 int libvlc_media_player_get_chapter_count(
860 libvlc_media_player_t *p_mi,
861 libvlc_exception_t *p_e )
863 input_thread_t *p_input_thread;
866 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
867 if( !p_input_thread )
870 var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
871 vlc_object_release( p_input_thread );
876 int libvlc_media_player_get_chapter_count_for_title(
877 libvlc_media_player_t *p_mi,
879 libvlc_exception_t *p_e )
881 input_thread_t *p_input_thread;
884 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
885 if( !p_input_thread )
889 if( asprintf( &psz_name, "title %2i", i_title ) == -1 )
891 vlc_object_release( p_input_thread );
894 var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL );
895 vlc_object_release( p_input_thread );
901 void libvlc_media_player_set_title(
902 libvlc_media_player_t *p_mi,
904 libvlc_exception_t *p_e )
906 input_thread_t *p_input_thread;
910 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
911 if( !p_input_thread )
914 var_Set( p_input_thread, "title", val );
915 vlc_object_release( p_input_thread );
918 libvlc_event_t event;
919 event.type = libvlc_MediaPlayerTitleChanged;
920 event.u.media_player_title_changed.new_title = i_title;
921 libvlc_event_send( p_mi->p_event_manager, &event );
924 int libvlc_media_player_get_title(
925 libvlc_media_player_t *p_mi,
926 libvlc_exception_t *p_e )
928 input_thread_t *p_input_thread;
931 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
932 if( !p_input_thread )
935 var_Get( p_input_thread, "title", &val );
936 vlc_object_release( p_input_thread );
941 int libvlc_media_player_get_title_count(
942 libvlc_media_player_t *p_mi,
943 libvlc_exception_t *p_e )
945 input_thread_t *p_input_thread;
948 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
949 if( !p_input_thread )
952 var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
953 vlc_object_release( p_input_thread );
958 void libvlc_media_player_next_chapter(
959 libvlc_media_player_t *p_mi,
960 libvlc_exception_t *p_e )
962 input_thread_t *p_input_thread;
964 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
965 if( !p_input_thread )
968 int i_type = var_Type( p_input_thread, "next-chapter" );
971 var_Set( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
972 "next-chapter":"next-title", val );
974 vlc_object_release( p_input_thread );
977 void libvlc_media_player_previous_chapter(
978 libvlc_media_player_t *p_mi,
979 libvlc_exception_t *p_e )
981 input_thread_t *p_input_thread;
983 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
984 if( !p_input_thread )
987 int i_type = var_Type( p_input_thread, "next-chapter" );
990 var_Set( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
991 "prev-chapter":"prev-title", val );
993 vlc_object_release( p_input_thread );
996 float libvlc_media_player_get_fps(
997 libvlc_media_player_t *p_mi,
998 libvlc_exception_t *p_e)
1000 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1003 if( p_input_thread )
1005 if( input_Control( p_input_thread, INPUT_GET_VIDEO_FPS, &f_fps ) )
1007 vlc_object_release( p_input_thread );
1012 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi,
1013 libvlc_exception_t *p_e)
1015 input_thread_t *p_input_thread =
1016 libvlc_get_input_thread ( p_mi, p_e);
1017 if ( !p_input_thread )
1020 if ( !p_input_thread->b_die && !p_input_thread->b_dead )
1022 vlc_object_release( p_input_thread );
1025 vlc_object_release( p_input_thread );
1029 void libvlc_media_player_set_rate(
1030 libvlc_media_player_t *p_mi,
1032 libvlc_exception_t *p_e )
1034 input_thread_t *p_input_thread;
1039 RAISEVOID( "Rate value is invalid" );
1041 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
1042 if( !p_input_thread )
1045 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1046 if( (rate < 0) && !b_can_rewind )
1048 vlc_object_release( p_input_thread );
1049 libvlc_exception_raise( p_e, "Rate value is invalid" );
1053 val.i_int = 1000.0f/rate;
1054 var_Set( p_input_thread, "rate", val );
1055 vlc_object_release( p_input_thread );
1058 float libvlc_media_player_get_rate(
1059 libvlc_media_player_t *p_mi,
1060 libvlc_exception_t *p_e )
1062 input_thread_t *p_input_thread;
1066 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1067 if( !p_input_thread )
1068 return 0.0; /* rate < 0 indicates rewind */
1070 var_Get( p_input_thread, "rate", &val );
1071 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1072 if( (val.i_int < 0) && !b_can_rewind )
1074 libvlc_exception_raise( p_e, "invalid rate" );
1077 vlc_object_release( p_input_thread );
1079 return (float)1000.0f/val.i_int;
1082 libvlc_state_t libvlc_media_player_get_state(
1083 libvlc_media_player_t *p_mi,
1084 libvlc_exception_t *p_e )
1086 input_thread_t *p_input_thread;
1089 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1090 if ( !p_input_thread )
1092 /* We do return the right value, no need to throw an exception */
1093 if( libvlc_exception_raised( p_e ) )
1094 libvlc_exception_clear( p_e );
1095 return libvlc_Ended;
1098 var_Get( p_input_thread, "state", &val );
1099 vlc_object_release( p_input_thread );
1101 return vlc_to_libvlc_state(val.i_int);
1104 int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi,
1105 libvlc_exception_t *p_e )
1107 input_thread_t *p_input_thread;
1110 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1111 if ( !p_input_thread )
1113 /* We do return the right value, no need to throw an exception */
1114 if( libvlc_exception_raised( p_e ) )
1115 libvlc_exception_clear( p_e );
1118 var_Get( p_input_thread, "can-seek", &val );
1119 vlc_object_release( p_input_thread );
1124 /* internal function, used by audio, video */
1125 libvlc_track_description_t *
1126 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1127 const char *psz_variable,
1128 libvlc_exception_t *p_e )
1130 input_thread_t *p_input = libvlc_get_input_thread( p_mi, p_e );
1135 vlc_value_t val_list, text_list;
1136 var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list);
1138 if( val_list.p_list->i_count <= 0 ) /* no tracks */
1141 libvlc_track_description_t *p_track_description, *p_actual, *p_previous;
1142 p_track_description = ( libvlc_track_description_t * )
1143 malloc( sizeof( libvlc_track_description_t ) );
1144 if ( !p_track_description )
1146 var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
1147 vlc_object_release( p_input );
1148 libvlc_exception_raise( p_e, "no enough memory" );
1151 p_actual = p_track_description;
1153 for( int i = 0; i < val_list.p_list->i_count; i++ )
1157 p_actual = ( libvlc_track_description_t * )
1158 malloc( sizeof( libvlc_track_description_t ) );
1161 libvlc_track_description_release( p_track_description );
1162 var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
1163 vlc_object_release( p_input );
1164 libvlc_exception_raise( p_e, "no enough memory" );
1168 p_actual->i_id = val_list.p_list->p_values[i].i_int;
1169 p_actual->psz_name = strdup( text_list.p_list->p_values[i].psz_string );
1170 p_actual->p_next = NULL;
1172 p_previous->p_next = p_actual;
1173 p_previous = p_actual;
1176 var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
1177 vlc_object_release( p_input );
1179 return p_track_description;
1182 void libvlc_track_description_release( libvlc_track_description_t *p_track_description )
1184 libvlc_track_description_t *p_actual, *p_before;
1185 p_actual = p_track_description;
1189 free( p_actual->psz_name );
1190 p_before = p_actual;
1191 p_actual = p_before->p_next;
1196 int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi,
1197 libvlc_exception_t *p_e )
1199 input_thread_t *p_input_thread;
1202 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1203 if ( !p_input_thread )
1205 /* We do return the right value, no need to throw an exception */
1206 if( libvlc_exception_raised( p_e ) )
1207 libvlc_exception_clear( p_e );
1210 var_Get( p_input_thread, "can-pause", &val );
1211 vlc_object_release( p_input_thread );