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 void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
640 libvlc_exception_t *p_e )
642 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
644 if( state == libvlc_Playing || state == libvlc_Paused )
646 /* Send a stop notification event only of we are in playing or paused states */
647 libvlc_media_set_state( p_mi->p_md, libvlc_Ended, p_e );
649 /* Construct and send the event */
650 libvlc_event_t event;
651 event.type = libvlc_MediaPlayerStopped;
652 libvlc_event_send( p_mi->p_event_manager, &event );
655 if( p_mi->b_own_its_input_thread )
657 vlc_mutex_lock( &p_mi->object_lock );
658 release_input_thread( p_mi ); /* This will stop the input thread */
659 vlc_mutex_unlock( &p_mi->object_lock );
663 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
665 if( !p_input_thread )
668 input_StopThread( p_input_thread );
669 vlc_object_release( p_input_thread );
673 /**************************************************************************
675 **************************************************************************/
676 void libvlc_media_player_set_drawable( libvlc_media_player_t *p_mi,
677 libvlc_drawable_t drawable,
678 libvlc_exception_t *p_e )
680 input_thread_t *p_input_thread;
681 vout_thread_t *p_vout = NULL;
683 p_mi->drawable = drawable;
685 /* Allow on the fly drawable changing. This is tricky has this may
686 * not be supported by every vout. We though can't disable it
687 * because of some creepy drawable type that are not flexible enough
688 * (Win32 HWND for instance) */
689 p_input_thread = libvlc_get_input_thread( p_mi, p_e );
690 if( !p_input_thread ) {
691 /* No input, nothing more to do, we are fine */
692 libvlc_exception_clear( p_e );
696 p_vout = vlc_object_find( p_input_thread, VLC_OBJECT_VOUT, FIND_CHILD );
699 vout_Control( p_vout , VOUT_REPARENT, drawable);
700 vlc_object_release( p_vout );
702 vlc_object_release( p_input_thread );
705 /**************************************************************************
707 **************************************************************************/
709 libvlc_media_player_get_drawable ( libvlc_media_player_t *p_mi, libvlc_exception_t *p_e )
712 return p_mi->drawable;
715 /**************************************************************************
716 * Getters for stream information
717 **************************************************************************/
718 libvlc_time_t libvlc_media_player_get_length(
719 libvlc_media_player_t *p_mi,
720 libvlc_exception_t *p_e )
722 input_thread_t *p_input_thread;
725 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
726 if( !p_input_thread )
729 var_Get( p_input_thread, "length", &val );
730 vlc_object_release( p_input_thread );
732 return (val.i_time+500LL)/1000LL;
735 libvlc_time_t libvlc_media_player_get_time(
736 libvlc_media_player_t *p_mi,
737 libvlc_exception_t *p_e )
739 input_thread_t *p_input_thread;
742 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
743 if( !p_input_thread )
746 var_Get( p_input_thread , "time", &val );
747 vlc_object_release( p_input_thread );
748 return (val.i_time+500LL)/1000LL;
751 void libvlc_media_player_set_time(
752 libvlc_media_player_t *p_mi,
754 libvlc_exception_t *p_e )
756 input_thread_t *p_input_thread;
759 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
760 if( !p_input_thread )
763 value.i_time = time*1000LL;
764 var_Set( p_input_thread, "time", value );
765 vlc_object_release( p_input_thread );
768 void libvlc_media_player_set_position(
769 libvlc_media_player_t *p_mi,
771 libvlc_exception_t *p_e )
773 input_thread_t *p_input_thread;
775 val.f_float = position;
777 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
778 if( !p_input_thread )
781 var_Set( p_input_thread, "position", val );
782 vlc_object_release( p_input_thread );
785 float libvlc_media_player_get_position(
786 libvlc_media_player_t *p_mi,
787 libvlc_exception_t *p_e )
789 input_thread_t *p_input_thread;
792 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
793 if( !p_input_thread )
796 var_Get( p_input_thread, "position", &val );
797 vlc_object_release( p_input_thread );
802 void libvlc_media_player_set_chapter(
803 libvlc_media_player_t *p_mi,
805 libvlc_exception_t *p_e )
807 input_thread_t *p_input_thread;
811 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
812 if( !p_input_thread )
815 var_Set( p_input_thread, "chapter", val );
816 vlc_object_release( p_input_thread );
819 int libvlc_media_player_get_chapter(
820 libvlc_media_player_t *p_mi,
821 libvlc_exception_t *p_e )
823 input_thread_t *p_input_thread;
826 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
827 if( !p_input_thread )
830 var_Get( p_input_thread, "chapter", &val );
831 vlc_object_release( p_input_thread );
836 int libvlc_media_player_get_chapter_count(
837 libvlc_media_player_t *p_mi,
838 libvlc_exception_t *p_e )
840 input_thread_t *p_input_thread;
843 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
844 if( !p_input_thread )
847 var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
848 vlc_object_release( p_input_thread );
853 int libvlc_media_player_get_chapter_count_for_title(
854 libvlc_media_player_t *p_mi,
856 libvlc_exception_t *p_e )
858 input_thread_t *p_input_thread;
861 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
862 if( !p_input_thread )
866 if( asprintf( &psz_name, "title %2i", i_title ) == -1 )
868 vlc_object_release( p_input_thread );
871 var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL );
872 vlc_object_release( p_input_thread );
878 void libvlc_media_player_set_title(
879 libvlc_media_player_t *p_mi,
881 libvlc_exception_t *p_e )
883 input_thread_t *p_input_thread;
887 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
888 if( !p_input_thread )
891 var_Set( p_input_thread, "title", val );
892 vlc_object_release( p_input_thread );
895 libvlc_event_t event;
896 event.type = libvlc_MediaPlayerTitleChanged;
897 event.u.media_player_title_changed.new_title = i_title;
898 libvlc_event_send( p_mi->p_event_manager, &event );
901 int libvlc_media_player_get_title(
902 libvlc_media_player_t *p_mi,
903 libvlc_exception_t *p_e )
905 input_thread_t *p_input_thread;
908 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
909 if( !p_input_thread )
912 var_Get( p_input_thread, "title", &val );
913 vlc_object_release( p_input_thread );
918 int libvlc_media_player_get_title_count(
919 libvlc_media_player_t *p_mi,
920 libvlc_exception_t *p_e )
922 input_thread_t *p_input_thread;
925 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
926 if( !p_input_thread )
929 var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
930 vlc_object_release( p_input_thread );
935 void libvlc_media_player_next_chapter(
936 libvlc_media_player_t *p_mi,
937 libvlc_exception_t *p_e )
939 input_thread_t *p_input_thread;
941 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
942 if( !p_input_thread )
945 int i_type = var_Type( p_input_thread, "next-chapter" );
948 var_Set( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
949 "next-chapter":"next-title", val );
951 vlc_object_release( p_input_thread );
954 void libvlc_media_player_previous_chapter(
955 libvlc_media_player_t *p_mi,
956 libvlc_exception_t *p_e )
958 input_thread_t *p_input_thread;
960 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
961 if( !p_input_thread )
964 int i_type = var_Type( p_input_thread, "next-chapter" );
967 var_Set( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
968 "prev-chapter":"prev-title", val );
970 vlc_object_release( p_input_thread );
973 float libvlc_media_player_get_fps(
974 libvlc_media_player_t *p_mi,
975 libvlc_exception_t *p_e)
977 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
982 if( input_Control( p_input_thread, INPUT_GET_VIDEO_FPS, &f_fps ) )
984 vlc_object_release( p_input_thread );
989 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi,
990 libvlc_exception_t *p_e)
992 input_thread_t *p_input_thread =
993 libvlc_get_input_thread ( p_mi, p_e);
994 if ( !p_input_thread )
997 if ( !p_input_thread->b_die && !p_input_thread->b_dead )
999 vlc_object_release( p_input_thread );
1002 vlc_object_release( p_input_thread );
1006 void libvlc_media_player_set_rate(
1007 libvlc_media_player_t *p_mi,
1009 libvlc_exception_t *p_e )
1011 input_thread_t *p_input_thread;
1016 RAISEVOID( "Rate value is invalid" );
1018 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
1019 if( !p_input_thread )
1022 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1023 if( (rate < 0) && !b_can_rewind )
1025 vlc_object_release( p_input_thread );
1026 libvlc_exception_raise( p_e, "Rate value is invalid" );
1030 val.i_int = 1000.0f/rate;
1031 var_Set( p_input_thread, "rate", val );
1032 vlc_object_release( p_input_thread );
1035 float libvlc_media_player_get_rate(
1036 libvlc_media_player_t *p_mi,
1037 libvlc_exception_t *p_e )
1039 input_thread_t *p_input_thread;
1043 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1044 if( !p_input_thread )
1045 return 0.0; /* rate < 0 indicates rewind */
1047 var_Get( p_input_thread, "rate", &val );
1048 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1049 if( (val.i_int < 0) && !b_can_rewind )
1051 libvlc_exception_raise( p_e, "invalid rate" );
1054 vlc_object_release( p_input_thread );
1056 return (float)1000.0f/val.i_int;
1059 libvlc_state_t libvlc_media_player_get_state(
1060 libvlc_media_player_t *p_mi,
1061 libvlc_exception_t *p_e )
1063 input_thread_t *p_input_thread;
1066 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1067 if ( !p_input_thread )
1069 /* We do return the right value, no need to throw an exception */
1070 if( libvlc_exception_raised( p_e ) )
1071 libvlc_exception_clear( p_e );
1072 return libvlc_Ended;
1075 var_Get( p_input_thread, "state", &val );
1076 vlc_object_release( p_input_thread );
1078 return vlc_to_libvlc_state(val.i_int);
1081 int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi,
1082 libvlc_exception_t *p_e )
1084 input_thread_t *p_input_thread;
1087 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1088 if ( !p_input_thread )
1090 /* We do return the right value, no need to throw an exception */
1091 if( libvlc_exception_raised( p_e ) )
1092 libvlc_exception_clear( p_e );
1095 var_Get( p_input_thread, "can-seek", &val );
1096 vlc_object_release( p_input_thread );
1101 /* internal function, used by audio, video */
1102 libvlc_track_description_t *
1103 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1104 const char *psz_variable,
1105 libvlc_exception_t *p_e )
1107 input_thread_t *p_input = libvlc_get_input_thread( p_mi, p_e );
1112 vlc_value_t val_list, text_list;
1113 var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list);
1115 if( val_list.p_list->i_count <= 0 ) /* no tracks */
1118 libvlc_track_description_t *p_track_description, *p_actual, *p_previous;
1119 p_track_description = ( libvlc_track_description_t * )
1120 malloc( sizeof( libvlc_track_description_t ) );
1121 if ( !p_track_description )
1123 var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
1124 vlc_object_release( p_input );
1125 libvlc_exception_raise( p_e, "no enough memory" );
1128 p_actual = p_track_description;
1130 for( int i = 0; i < val_list.p_list->i_count; i++ )
1134 p_actual = ( libvlc_track_description_t * )
1135 malloc( sizeof( libvlc_track_description_t ) );
1138 libvlc_track_description_release( p_track_description );
1139 var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
1140 vlc_object_release( p_input );
1141 libvlc_exception_raise( p_e, "no enough memory" );
1145 p_actual->i_id = val_list.p_list->p_values[i].i_int;
1146 p_actual->psz_name = strdup( text_list.p_list->p_values[i].psz_string );
1147 p_actual->p_next = NULL;
1149 p_previous->p_next = p_actual;
1150 p_previous = p_actual;
1153 var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
1154 vlc_object_release( p_input );
1156 return p_track_description;
1159 void libvlc_track_description_release( libvlc_track_description_t *p_track_description )
1161 libvlc_track_description_t *p_actual, *p_before;
1162 p_actual = p_track_description;
1166 free( p_actual->psz_name );
1167 p_before = p_actual;
1168 p_actual = p_before->p_next;
1173 int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi,
1174 libvlc_exception_t *p_e )
1176 input_thread_t *p_input_thread;
1179 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1180 if ( !p_input_thread )
1182 /* We do return the right value, no need to throw an exception */
1183 if( libvlc_exception_raised( p_e ) )
1184 libvlc_exception_clear( p_e );
1187 var_Get( p_input_thread, "can-pause", &val );
1188 vlc_object_release( p_input_thread );