1 /*****************************************************************************
2 * media_player.c: Libvlc API Media Instance management functions
3 *****************************************************************************
4 * Copyright (C) 2005-2009 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 *****************************************************************************/
30 #include <vlc/libvlc.h>
31 #include <vlc/libvlc_media.h>
32 #include <vlc/libvlc_events.h>
34 #include <vlc_demux.h>
35 #include <vlc_input.h>
40 #include "libvlc_internal.h"
41 #include "media_internal.h" // libvlc_media_set_state()
42 #include "media_player_internal.h"
45 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
46 vlc_value_t oldval, vlc_value_t newval,
49 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
50 vlc_value_t oldval, vlc_value_t newval,
53 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
54 vlc_value_t oldval, vlc_value_t newval,
58 snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd,
59 vlc_value_t oldval, vlc_value_t newval, void *p_data );
61 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
67 #define register_event(a, b) __register_event(a, libvlc_MediaPlayer ## b)
68 static inline void __register_event(libvlc_media_player_t *mp, libvlc_event_type_t type)
70 libvlc_event_manager_register_event_type(mp->p_event_manager, type);
73 static inline void lock(libvlc_media_player_t *mp)
75 vlc_mutex_lock(&mp->object_lock);
78 static inline void unlock(libvlc_media_player_t *mp)
80 vlc_mutex_unlock(&mp->object_lock);
84 * Release the associated input thread.
86 * Object lock is NOT held.
88 static void release_input_thread( libvlc_media_player_t *p_mi, bool b_input_abort )
90 input_thread_t * p_input_thread;
92 if( !p_mi || !p_mi->p_input_thread )
95 p_input_thread = p_mi->p_input_thread;
97 var_DelCallback( p_input_thread, "can-seek",
98 input_seekable_changed, p_mi );
99 var_DelCallback( p_input_thread, "can-pause",
100 input_pausable_changed, p_mi );
101 var_DelCallback( p_input_thread, "intf-event",
102 input_event_changed, p_mi );
104 /* We owned this one */
105 input_Stop( p_input_thread, b_input_abort );
107 vlc_thread_join( p_input_thread );
109 assert( p_mi->p_input_resource == NULL );
110 assert( p_input_thread->b_dead );
111 /* Store the input resource for future use. */
112 p_mi->p_input_resource = input_DetachResource( p_input_thread );
114 var_Destroy( p_input_thread, "drawable-hwnd" );
115 var_Destroy( p_input_thread, "drawable-xid" );
116 var_Destroy( p_input_thread, "drawable-agl" );
118 vlc_object_release( p_input_thread );
120 p_mi->p_input_thread = NULL;
124 * Retrieve the input thread. Be sure to release the object
125 * once you are done with it. (libvlc Internal)
127 * Function will lock the object.
129 input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi,
130 libvlc_exception_t *p_e )
132 input_thread_t *p_input_thread;
134 if( !p_mi ) RAISENULL( "Media Instance is NULL" );
138 if( !p_mi->p_input_thread )
141 RAISENULL( "Input is NULL" );
144 p_input_thread = p_mi->p_input_thread;
145 vlc_object_hold( p_input_thread );
149 return p_input_thread;
153 * Set the internal state of the media_player. (media player Internal)
155 * Function will lock the media_player.
157 static void set_state( libvlc_media_player_t *p_mi, libvlc_state_t state,
163 libvlc_media_t *media = p_mi->p_md;
165 libvlc_media_retain(media);
171 // Also set the state of the corresponding media
172 // This is strictly for convenience.
173 libvlc_media_set_state(media, state);
175 libvlc_media_release(media);
180 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
181 vlc_value_t oldval, vlc_value_t newval,
187 libvlc_media_player_t * p_mi = p_userdata;
188 libvlc_event_t event;
190 event.type = libvlc_MediaPlayerSeekableChanged;
191 event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
193 libvlc_event_send( p_mi->p_event_manager, &event );
198 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
199 vlc_value_t oldval, vlc_value_t newval,
205 libvlc_media_player_t * p_mi = p_userdata;
206 libvlc_event_t event;
208 event.type = libvlc_MediaPlayerPausableChanged;
209 event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
211 libvlc_event_send( p_mi->p_event_manager, &event );
216 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
217 vlc_value_t oldval, vlc_value_t newval,
221 input_thread_t * p_input = (input_thread_t *)p_this;
222 libvlc_media_player_t * p_mi = p_userdata;
223 libvlc_event_t event;
225 assert( !strcmp( psz_cmd, "intf-event" ) );
227 if( newval.i_int == INPUT_EVENT_STATE )
229 libvlc_state_t libvlc_state;
231 switch ( var_GetInteger( p_input, "state" ) )
234 libvlc_state = libvlc_NothingSpecial;
235 event.type = libvlc_MediaPlayerNothingSpecial;
238 libvlc_state = libvlc_Opening;
239 event.type = libvlc_MediaPlayerOpening;
242 libvlc_state = libvlc_Playing;
243 event.type = libvlc_MediaPlayerPlaying;
246 libvlc_state = libvlc_Paused;
247 event.type = libvlc_MediaPlayerPaused;
250 libvlc_state = libvlc_Ended;
251 event.type = libvlc_MediaPlayerEndReached;
254 libvlc_state = libvlc_Error;
255 event.type = libvlc_MediaPlayerEncounteredError;
262 set_state( p_mi, libvlc_state, false );
263 libvlc_event_send( p_mi->p_event_manager, &event );
265 else if( newval.i_int == INPUT_EVENT_ABORT )
267 libvlc_state_t libvlc_state = libvlc_Stopped;
268 event.type = libvlc_MediaPlayerStopped;
270 set_state( p_mi, libvlc_state, false );
271 libvlc_event_send( p_mi->p_event_manager, &event );
273 else if( newval.i_int == INPUT_EVENT_POSITION )
275 if( var_GetInteger( p_input, "state" ) != PLAYING_S )
276 return VLC_SUCCESS; /* Don't send the position while stopped */
279 event.type = libvlc_MediaPlayerPositionChanged;
280 event.u.media_player_position_changed.new_position =
281 var_GetFloat( p_input, "position" );
282 libvlc_event_send( p_mi->p_event_manager, &event );
285 event.type = libvlc_MediaPlayerTimeChanged;
286 event.u.media_player_time_changed.new_time =
287 from_mtime(var_GetTime( p_input, "time" ));
288 libvlc_event_send( p_mi->p_event_manager, &event );
290 else if( newval.i_int == INPUT_EVENT_LENGTH )
292 event.type = libvlc_MediaPlayerLengthChanged;
293 event.u.media_player_length_changed.new_length =
294 from_mtime(var_GetTime( p_input, "length" ));
295 libvlc_event_send( p_mi->p_event_manager, &event );
302 /**************************************************************************
303 * Snapshot Taken Event.
305 * FIXME: This snapshot API interface makes no sense in media_player.
306 *************************************************************************/
307 static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd,
308 vlc_value_t oldval, vlc_value_t newval, void *p_data )
310 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);
312 libvlc_media_player_t *mp = p_data;
313 libvlc_event_t event;
314 event.type = libvlc_MediaPlayerSnapshotTaken;
315 event.u.media_player_snapshot_taken.psz_filename = newval.psz_string;
316 libvlc_event_send(mp->p_event_manager, &event);
322 static void libvlc_media_player_destroy( libvlc_media_player_t * );
325 /**************************************************************************
326 * Create a Media Instance object.
329 * - All items created by _new start with a refcount set to 1.
330 * - Accessor _release decrease the refcount by 1, if after that
331 * operation the refcount is 0, the object is destroyed.
332 * - Accessor _retain increase the refcount by 1 (XXX: to implement)
334 * Object locking strategy:
335 * - No lock held while in constructor.
336 * - When accessing any member variable this lock is held. (XXX who locks?)
337 * - When attempting to destroy the object the lock is also held.
338 **************************************************************************/
339 libvlc_media_player_t *
340 libvlc_media_player_new( libvlc_instance_t *instance, libvlc_exception_t *e )
342 libvlc_media_player_t * mp;
346 mp = malloc(sizeof(libvlc_media_player_t));
349 libvlc_exception_raise(e);
350 libvlc_printerr("Not enough memory");
354 mp->drawable.agl = 0;
355 mp->drawable.xid = 0;
356 mp->drawable.hwnd = NULL;
357 mp->drawable.nsobject = NULL;
358 mp->keyboard_events = mp->mouse_events = 1;
359 mp->state = libvlc_NothingSpecial;
360 mp->p_libvlc_instance = instance;
361 mp->p_input_thread = NULL;
362 mp->p_input_resource = NULL;
364 mp->p_event_manager = libvlc_event_manager_new(mp, instance);
365 if (unlikely(mp->p_event_manager == NULL))
370 vlc_mutex_init(&mp->object_lock);
372 register_event(mp, NothingSpecial);
373 register_event(mp, Opening);
374 register_event(mp, Buffering);
375 register_event(mp, Playing);
376 register_event(mp, Paused);
377 register_event(mp, Stopped);
378 register_event(mp, Forward);
379 register_event(mp, Backward);
380 register_event(mp, EndReached);
381 register_event(mp, EncounteredError);
382 register_event(mp, SeekableChanged);
384 register_event(mp, PositionChanged);
385 register_event(mp, TimeChanged);
386 register_event(mp, LengthChanged);
387 register_event(mp, TitleChanged);
388 register_event(mp, PausableChanged);
390 /* Snapshot initialization */
391 register_event(mp, SnapshotTaken);
393 register_event(mp, MediaChanged);
395 /* Attach a var callback to the global object to provide the glue between
396 * vout_thread that generates the event and media_player that re-emits it
397 * with its own event manager
399 * FIXME: It's unclear why we want to put this in public API, and why we
400 * want to expose it in such a limiting and ugly way.
402 var_AddCallback(instance->p_libvlc_int, "snapshot-file", snapshot_was_taken, mp);
407 /**************************************************************************
408 * Create a Media Instance object with a media descriptor.
409 **************************************************************************/
410 libvlc_media_player_t *
411 libvlc_media_player_new_from_media(
412 libvlc_media_t * p_md,
413 libvlc_exception_t *p_e )
415 libvlc_media_player_t * p_mi;
417 p_mi = libvlc_media_player_new( p_md->p_libvlc_instance, p_e );
421 libvlc_media_retain( p_md );
427 /**************************************************************************
428 * Destroy a Media Instance object (libvlc internal)
430 * Warning: No lock held here, but hey, this is internal. Caller must lock.
431 **************************************************************************/
432 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
436 /* Detach Callback from the main libvlc object */
437 var_DelCallback( p_mi->p_libvlc_instance->p_libvlc_int,
438 "snapshot-file", snapshot_was_taken, p_mi );
440 /* If the input thread hasn't been already deleted it means
441 * that the owners didn't stop the thread before releasing it. */
442 assert(!p_mi->p_input_thread);
444 /* Fallback for those who don't use NDEBUG */
445 if (p_mi->p_input_thread)
446 release_input_thread(p_mi, true);
448 if( p_mi->p_input_resource )
450 input_resource_Delete( p_mi->p_input_resource );
451 p_mi->p_input_resource = NULL;
454 libvlc_event_manager_release( p_mi->p_event_manager );
455 libvlc_media_release( p_mi->p_md );
456 vlc_mutex_destroy( &p_mi->object_lock );
460 /**************************************************************************
461 * Release a Media Instance object.
463 * Function does the locking.
464 **************************************************************************/
465 void libvlc_media_player_release( libvlc_media_player_t *p_mi )
471 destroy = !--p_mi->i_refcount;
475 libvlc_media_player_destroy( p_mi );
478 /**************************************************************************
479 * Retain a Media Instance object.
481 * Caller must hold the lock.
482 **************************************************************************/
483 void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
492 /**************************************************************************
493 * Set the Media descriptor associated with the instance.
495 * Enter without lock -- function will lock the object.
496 **************************************************************************/
497 void libvlc_media_player_set_media(
498 libvlc_media_player_t *p_mi,
499 libvlc_media_t *p_md )
503 /* FIXME I am not sure if it is a user request or on die(eof/error)
505 release_input_thread( p_mi,
506 p_mi->p_input_thread &&
507 !p_mi->p_input_thread->b_eof &&
508 !p_mi->p_input_thread->b_error );
510 set_state( p_mi, libvlc_NothingSpecial, true );
512 libvlc_media_release( p_mi->p_md );
518 return; /* It is ok to pass a NULL md */
521 libvlc_media_retain( p_md );
524 /* The policy here is to ignore that we were created using a different
525 * libvlc_instance, because we don't really care */
526 p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
530 /* Send an event for the newly available media */
531 libvlc_event_t event;
532 event.type = libvlc_MediaPlayerMediaChanged;
533 event.u.media_player_media_changed.new_media = p_md;
534 libvlc_event_send( p_mi->p_event_manager, &event );
538 /**************************************************************************
539 * Get the Media descriptor associated with the instance.
540 **************************************************************************/
542 libvlc_media_player_get_media( libvlc_media_player_t *p_mi )
549 libvlc_media_retain( p_mi->p_md );
554 /**************************************************************************
555 * Get the event Manager.
556 **************************************************************************/
557 libvlc_event_manager_t *
558 libvlc_media_player_event_manager( libvlc_media_player_t *p_mi )
560 return p_mi->p_event_manager;
563 /**************************************************************************
564 * Tell media player to start playing.
565 **************************************************************************/
566 void libvlc_media_player_play( libvlc_media_player_t *p_mi,
567 libvlc_exception_t *p_e )
569 input_thread_t * p_input_thread;
571 if( (p_input_thread = libvlc_get_input_thread( p_mi, p_e )) )
573 /* A thread already exists, send it a play message */
574 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
575 vlc_object_release( p_input_thread );
579 /* Ignore previous exception */
580 libvlc_exception_clear( p_e );
587 libvlc_exception_raise( p_e );
588 libvlc_printerr( "No associated media descriptor" );
592 p_mi->p_input_thread = input_Create( p_mi->p_libvlc_instance->p_libvlc_int,
593 p_mi->p_md->p_input_item, NULL, p_mi->p_input_resource );
595 if( !p_mi->p_input_thread )
601 p_mi->p_input_resource = NULL;
602 p_input_thread = p_mi->p_input_thread;
604 var_Create( p_input_thread, "drawable-agl", VLC_VAR_INTEGER );
605 if( p_mi->drawable.agl )
606 var_SetInteger( p_input_thread, "drawable-agl", p_mi->drawable.agl );
608 var_Create( p_input_thread, "drawable-xid", VLC_VAR_INTEGER );
609 if( p_mi->drawable.xid )
610 var_SetInteger( p_input_thread, "drawable-xid", p_mi->drawable.xid );
612 var_Create( p_input_thread, "drawable-hwnd", VLC_VAR_ADDRESS );
613 if( p_mi->drawable.hwnd != NULL )
614 var_SetAddress( p_input_thread, "drawable-hwnd", p_mi->drawable.hwnd );
616 var_Create( p_input_thread, "drawable-nsobject", VLC_VAR_ADDRESS );
617 if( p_mi->drawable.nsobject != NULL )
618 var_SetAddress( p_input_thread, "drawable-nsobject", p_mi->drawable.nsobject );
620 var_Create( p_input_thread, "keyboard-events", VLC_VAR_BOOL );
621 var_SetBool( p_input_thread, "keyboard-events", p_mi->keyboard_events );
622 var_Create( p_input_thread, "mouse-events", VLC_VAR_BOOL );
623 var_SetBool( p_input_thread, "mouse-events", p_mi->mouse_events );
625 var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
626 var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
627 var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
629 if( input_Start( p_input_thread ) )
631 vlc_object_release( p_input_thread );
632 p_mi->p_input_thread = NULL;
638 /**************************************************************************
640 **************************************************************************/
641 void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
642 libvlc_exception_t *p_e )
644 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
645 if( !p_input_thread )
648 libvlc_state_t state = libvlc_media_player_get_state( p_mi );
649 if( state == libvlc_Playing || state == libvlc_Buffering )
651 if( libvlc_media_player_can_pause( p_mi, p_e ) )
652 input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
654 libvlc_media_player_stop( p_mi );
657 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
659 vlc_object_release( p_input_thread );
662 /**************************************************************************
663 * Tells whether the media player is currently playing.
665 * Enter with lock held.
666 **************************************************************************/
667 int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi )
669 libvlc_state_t state = libvlc_media_player_get_state( p_mi );
670 return (libvlc_Playing == state) || (libvlc_Buffering == state);
673 /**************************************************************************
675 **************************************************************************/
676 void libvlc_media_player_stop( libvlc_media_player_t *p_mi )
678 libvlc_state_t state = libvlc_media_player_get_state( p_mi );
681 release_input_thread( p_mi, true ); /* This will stop the input thread */
684 /* Force to go to stopped state, in case we were in Ended, or Error
686 if( state != libvlc_Stopped )
688 set_state( p_mi, libvlc_Stopped, false );
690 /* Construct and send the event */
691 libvlc_event_t event;
692 event.type = libvlc_MediaPlayerStopped;
693 libvlc_event_send( p_mi->p_event_manager, &event );
697 /**************************************************************************
699 **************************************************************************/
700 void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
703 p_mi->drawable.nsobject = drawable;
706 /**************************************************************************
708 **************************************************************************/
709 void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
711 return p_mi->drawable.nsobject;
714 /**************************************************************************
716 **************************************************************************/
717 void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
720 p_mi->drawable.agl = drawable;
723 /**************************************************************************
725 **************************************************************************/
726 uint32_t libvlc_media_player_get_agl( libvlc_media_player_t *p_mi )
728 return p_mi->drawable.agl;
731 /**************************************************************************
733 **************************************************************************/
734 void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
737 p_mi->drawable.xid = drawable;
740 /**************************************************************************
742 **************************************************************************/
743 uint32_t libvlc_media_player_get_xwindow( libvlc_media_player_t *p_mi )
745 return p_mi->drawable.xid;
748 /**************************************************************************
750 **************************************************************************/
751 void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
754 p_mi->drawable.hwnd = drawable;
757 /**************************************************************************
759 **************************************************************************/
760 void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi )
762 return p_mi->drawable.hwnd;
765 /**************************************************************************
766 * Getters for stream information
767 **************************************************************************/
768 libvlc_time_t libvlc_media_player_get_length(
769 libvlc_media_player_t *p_mi,
770 libvlc_exception_t *p_e )
772 input_thread_t *p_input_thread;
773 libvlc_time_t i_time;
775 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
776 if( !p_input_thread )
779 i_time = from_mtime(var_GetTime( p_input_thread, "length" ));
780 vlc_object_release( p_input_thread );
785 libvlc_time_t libvlc_media_player_get_time(
786 libvlc_media_player_t *p_mi,
787 libvlc_exception_t *p_e )
789 input_thread_t *p_input_thread;
790 libvlc_time_t i_time;
792 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
793 if( !p_input_thread )
796 i_time = from_mtime(var_GetTime( p_input_thread , "time" ));
797 vlc_object_release( p_input_thread );
801 void libvlc_media_player_set_time(
802 libvlc_media_player_t *p_mi,
803 libvlc_time_t i_time,
804 libvlc_exception_t *p_e )
806 input_thread_t *p_input_thread;
808 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
809 if( !p_input_thread )
812 var_SetTime( p_input_thread, "time", to_mtime(i_time) );
813 vlc_object_release( p_input_thread );
816 void libvlc_media_player_set_position(
817 libvlc_media_player_t *p_mi,
819 libvlc_exception_t *p_e )
821 input_thread_t *p_input_thread;
823 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
824 if( !p_input_thread )
827 var_SetFloat( p_input_thread, "position", position );
828 vlc_object_release( p_input_thread );
831 float libvlc_media_player_get_position(
832 libvlc_media_player_t *p_mi,
833 libvlc_exception_t *p_e )
835 input_thread_t *p_input_thread;
838 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
839 if( !p_input_thread )
842 f_position = var_GetFloat( p_input_thread, "position" );
843 vlc_object_release( p_input_thread );
848 void libvlc_media_player_set_chapter(
849 libvlc_media_player_t *p_mi,
851 libvlc_exception_t *p_e )
853 input_thread_t *p_input_thread;
855 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
856 if( !p_input_thread )
859 var_SetInteger( p_input_thread, "chapter", chapter );
860 vlc_object_release( p_input_thread );
863 int libvlc_media_player_get_chapter(
864 libvlc_media_player_t *p_mi,
865 libvlc_exception_t *p_e )
867 input_thread_t *p_input_thread;
870 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
871 if( !p_input_thread )
874 i_chapter = var_GetInteger( p_input_thread, "chapter" );
875 vlc_object_release( p_input_thread );
880 int libvlc_media_player_get_chapter_count(
881 libvlc_media_player_t *p_mi,
882 libvlc_exception_t *p_e )
884 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_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
892 vlc_object_release( p_input_thread );
897 int libvlc_media_player_get_chapter_count_for_title(
898 libvlc_media_player_t *p_mi,
900 libvlc_exception_t *p_e )
902 input_thread_t *p_input_thread;
905 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
906 if( !p_input_thread )
910 if( asprintf( &psz_name, "title %2i", i_title ) == -1 )
912 vlc_object_release( p_input_thread );
915 var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL );
916 vlc_object_release( p_input_thread );
922 void libvlc_media_player_set_title(
923 libvlc_media_player_t *p_mi,
925 libvlc_exception_t *p_e )
927 input_thread_t *p_input_thread;
929 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
930 if( !p_input_thread )
933 var_SetInteger( p_input_thread, "title", i_title );
934 vlc_object_release( p_input_thread );
937 libvlc_event_t event;
938 event.type = libvlc_MediaPlayerTitleChanged;
939 event.u.media_player_title_changed.new_title = i_title;
940 libvlc_event_send( p_mi->p_event_manager, &event );
943 int libvlc_media_player_get_title(
944 libvlc_media_player_t *p_mi,
945 libvlc_exception_t *p_e )
947 input_thread_t *p_input_thread;
950 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
951 if( !p_input_thread )
954 i_title = var_GetInteger( p_input_thread, "title" );
955 vlc_object_release( p_input_thread );
960 int libvlc_media_player_get_title_count(
961 libvlc_media_player_t *p_mi,
962 libvlc_exception_t *p_e )
964 input_thread_t *p_input_thread;
967 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
968 if( !p_input_thread )
971 var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
972 vlc_object_release( p_input_thread );
977 void libvlc_media_player_next_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" );
988 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
989 "next-chapter":"next-title", true );
991 vlc_object_release( p_input_thread );
994 void libvlc_media_player_previous_chapter(
995 libvlc_media_player_t *p_mi,
996 libvlc_exception_t *p_e )
998 input_thread_t *p_input_thread;
1000 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
1001 if( !p_input_thread )
1004 int i_type = var_Type( p_input_thread, "next-chapter" );
1005 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1006 "prev-chapter":"prev-title", true );
1008 vlc_object_release( p_input_thread );
1011 float libvlc_media_player_get_fps(
1012 libvlc_media_player_t *p_mi,
1013 libvlc_exception_t *p_e)
1015 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1018 if( p_input_thread )
1020 if( input_Control( p_input_thread, INPUT_GET_VIDEO_FPS, &f_fps ) )
1022 vlc_object_release( p_input_thread );
1027 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi,
1028 libvlc_exception_t *p_e)
1031 input_thread_t *p_input_thread =
1032 libvlc_get_input_thread ( p_mi, p_e);
1033 if ( !p_input_thread )
1036 b_will_play = !p_input_thread->b_die && !p_input_thread->b_dead;
1037 vlc_object_release( p_input_thread );
1042 void libvlc_media_player_set_rate(
1043 libvlc_media_player_t *p_mi,
1045 libvlc_exception_t *p_e )
1047 input_thread_t *p_input_thread;
1050 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1051 if( !p_input_thread )
1054 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1055 if( (rate < 0.0) && !b_can_rewind )
1057 vlc_object_release( p_input_thread );
1058 libvlc_exception_raise( p_e );
1059 libvlc_printerr( "Invalid playback rate" );
1063 var_SetFloat( p_input_thread, "rate", rate );
1064 vlc_object_release( p_input_thread );
1067 float libvlc_media_player_get_rate(
1068 libvlc_media_player_t *p_mi,
1069 libvlc_exception_t *p_e )
1071 input_thread_t *p_input_thread;
1075 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1076 if( !p_input_thread )
1077 return 0.0; /* rate < 0 indicates rewind */
1079 f_rate = var_GetFloat( p_input_thread, "rate" );
1080 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1081 /* FIXME: why are negative values forbidden ?? (rewinding) */
1082 if( f_rate < 0 && !b_can_rewind )
1084 vlc_object_release( p_input_thread );
1087 vlc_object_release( p_input_thread );
1092 libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi )
1095 libvlc_state_t state = p_mi->state;
1100 int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi,
1101 libvlc_exception_t *p_e )
1103 input_thread_t *p_input_thread;
1106 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1107 if ( !p_input_thread )
1109 /* We do return the right value, no need to throw an exception */
1110 clear_if_needed(p_e);
1113 b_seekable = var_GetBool( p_input_thread, "can-seek" );
1114 vlc_object_release( p_input_thread );
1119 /* internal function, used by audio, video */
1120 libvlc_track_description_t *
1121 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1122 const char *psz_variable,
1123 libvlc_exception_t *p_e )
1125 input_thread_t *p_input = libvlc_get_input_thread( p_mi, p_e );
1126 libvlc_track_description_t *p_track_description = NULL,
1127 *p_actual, *p_previous;
1132 vlc_value_t val_list, text_list;
1133 var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list);
1136 if( val_list.p_list->i_count <= 0 )
1139 p_track_description = ( libvlc_track_description_t * )
1140 malloc( sizeof( libvlc_track_description_t ) );
1141 if ( !p_track_description )
1143 libvlc_exception_raise( p_e );
1144 libvlc_printerr( "Not enough memory" );
1147 p_actual = p_track_description;
1149 for( int i = 0; i < val_list.p_list->i_count; i++ )
1153 p_actual = ( libvlc_track_description_t * )
1154 malloc( sizeof( libvlc_track_description_t ) );
1157 libvlc_track_description_release( p_track_description );
1158 libvlc_exception_raise( p_e );
1159 libvlc_printerr( "Not enough memory" );
1163 p_actual->i_id = val_list.p_list->p_values[i].i_int;
1164 p_actual->psz_name = strdup( text_list.p_list->p_values[i].psz_string );
1165 p_actual->p_next = NULL;
1167 p_previous->p_next = p_actual;
1168 p_previous = p_actual;
1173 var_FreeList( &val_list, &text_list );
1174 vlc_object_release( p_input );
1176 return p_track_description;
1179 void libvlc_track_description_release( libvlc_track_description_t *p_td )
1181 libvlc_track_description_t *p_actual, *p_before;
1186 free( p_actual->psz_name );
1187 p_before = p_actual;
1188 p_actual = p_before->p_next;
1193 int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi,
1194 libvlc_exception_t *p_e )
1196 input_thread_t *p_input_thread;
1199 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1200 if ( !p_input_thread )
1202 /* We do return the right value, no need to throw an exception */
1203 clear_if_needed(p_e);
1206 b_can_pause = var_GetBool( p_input_thread, "can-pause" );
1207 vlc_object_release( p_input_thread );
1212 void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi, libvlc_exception_t *p_e )
1214 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1215 if( p_input_thread != NULL )
1217 var_TriggerCallback( p_input_thread, "frame-next" );
1218 vlc_object_release( p_input_thread );
1222 libvlc_exception_raise( p_e );
1223 libvlc_printerr( "No active input" );