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,
57 static int SnapshotTakenCallback( vlc_object_t *p_this, char const *psz_cmd,
58 vlc_value_t oldval, vlc_value_t newval, void *p_data );
60 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
63 * Release the associated input thread.
65 * Object lock is NOT held.
67 static void release_input_thread( libvlc_media_player_t *p_mi, bool b_input_abort )
69 input_thread_t * p_input_thread;
71 if( !p_mi || !p_mi->p_input_thread )
74 p_input_thread = p_mi->p_input_thread;
76 var_DelCallback( p_input_thread, "can-seek",
77 input_seekable_changed, p_mi );
78 var_DelCallback( p_input_thread, "can-pause",
79 input_pausable_changed, p_mi );
80 var_DelCallback( p_input_thread, "intf-event",
81 input_event_changed, p_mi );
83 /* We owned this one */
84 input_Stop( p_input_thread, b_input_abort );
86 vlc_thread_join( p_input_thread );
88 assert( p_mi->p_input_resource == NULL );
89 assert( p_input_thread->b_dead );
90 /* Store the input resource for future use. */
91 p_mi->p_input_resource = input_DetachResource( p_input_thread );
93 var_Destroy( p_input_thread, "drawable-hwnd" );
94 var_Destroy( p_input_thread, "drawable-xid" );
95 var_Destroy( p_input_thread, "drawable-agl" );
97 vlc_object_release( p_input_thread );
99 p_mi->p_input_thread = NULL;
103 * Retrieve the input thread. Be sure to release the object
104 * once you are done with it. (libvlc Internal)
106 * Function will lock the object.
108 input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi,
109 libvlc_exception_t *p_e )
111 input_thread_t *p_input_thread;
113 if( !p_mi ) RAISENULL( "Media Instance is NULL" );
115 vlc_mutex_lock( &p_mi->object_lock );
117 if( !p_mi->p_input_thread )
119 vlc_mutex_unlock( &p_mi->object_lock );
120 RAISENULL( "Input is NULL" );
123 p_input_thread = p_mi->p_input_thread;
124 vlc_object_hold( p_input_thread );
126 vlc_mutex_unlock( &p_mi->object_lock );
128 return p_input_thread;
132 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
133 vlc_value_t oldval, vlc_value_t newval,
139 libvlc_media_player_t * p_mi = p_userdata;
140 libvlc_event_t event;
142 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
143 event.type = libvlc_MediaPlayerSeekableChanged;
144 event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
146 libvlc_event_send( p_mi->p_event_manager, &event );
151 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
152 vlc_value_t oldval, vlc_value_t newval,
158 libvlc_media_player_t * p_mi = p_userdata;
159 libvlc_event_t event;
161 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
162 event.type = libvlc_MediaPlayerPausableChanged;
163 event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
165 libvlc_event_send( p_mi->p_event_manager, &event );
170 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
171 vlc_value_t oldval, vlc_value_t newval,
175 input_thread_t * p_input = (input_thread_t *)p_this;
176 libvlc_media_player_t * p_mi = p_userdata;
177 libvlc_event_t event;
179 assert( !strcmp( psz_cmd, "intf-event" ) );
181 if( newval.i_int == INPUT_EVENT_STATE )
183 libvlc_state_t libvlc_state;
185 switch ( var_GetInteger( p_input, "state" ) )
188 libvlc_state = libvlc_NothingSpecial;
189 event.type = libvlc_MediaPlayerNothingSpecial;
192 libvlc_state = libvlc_Opening;
193 event.type = libvlc_MediaPlayerOpening;
196 libvlc_state = libvlc_Playing;
197 event.type = libvlc_MediaPlayerPlaying;
200 libvlc_state = libvlc_Paused;
201 event.type = libvlc_MediaPlayerPaused;
204 libvlc_state = libvlc_Ended;
205 event.type = libvlc_MediaPlayerEndReached;
208 libvlc_state = libvlc_Error;
209 event.type = libvlc_MediaPlayerEncounteredError;
216 libvlc_media_set_state( p_mi->p_md, libvlc_state, NULL );
217 libvlc_event_send( p_mi->p_event_manager, &event );
219 else if( newval.i_int == INPUT_EVENT_ABORT )
221 libvlc_state_t libvlc_state = libvlc_Stopped;
222 event.type = libvlc_MediaPlayerStopped;
224 libvlc_media_set_state( p_mi->p_md, libvlc_state, NULL );
225 libvlc_event_send( p_mi->p_event_manager, &event );
227 else if( newval.i_int == INPUT_EVENT_POSITION )
229 if( var_GetInteger( p_input, "state" ) != PLAYING_S )
230 return VLC_SUCCESS; /* Don't send the position while stopped */
233 event.type = libvlc_MediaPlayerPositionChanged;
234 event.u.media_player_position_changed.new_position =
235 var_GetFloat( p_input, "position" );
236 libvlc_event_send( p_mi->p_event_manager, &event );
239 event.type = libvlc_MediaPlayerTimeChanged;
240 event.u.media_player_time_changed.new_time =
241 var_GetTime( p_input, "time" );
242 libvlc_event_send( p_mi->p_event_manager, &event );
244 else if( newval.i_int == INPUT_EVENT_LENGTH )
246 event.type = libvlc_MediaPlayerLengthChanged;
247 event.u.media_player_length_changed.new_length =
248 var_GetTime( p_input, "length" );
249 libvlc_event_send( p_mi->p_event_manager, &event );
256 static void libvlc_media_player_destroy( libvlc_media_player_t * );
258 /**************************************************************************
259 * Create a Media Instance object.
262 * - All items created by _new start with a refcount set to 1.
263 * - Accessor _release decrease the refcount by 1, if after that
264 * operation the refcount is 0, the object is destroyed.
265 * - Accessor _retain increase the refcount by 1 (XXX: to implement)
267 * Object locking strategy:
268 * - No lock held while in constructor.
269 * - When accessing any member variable this lock is held. (XXX who locks?)
270 * - When attempting to destroy the object the lock is also held.
271 **************************************************************************/
272 libvlc_media_player_t *
273 libvlc_media_player_new( libvlc_instance_t * p_libvlc_instance,
274 libvlc_exception_t * p_e )
276 libvlc_media_player_t * p_mi;
278 if( !p_libvlc_instance )
280 libvlc_exception_raise( p_e, "invalid libvlc instance" );
284 p_mi = malloc( sizeof(libvlc_media_player_t) );
287 libvlc_exception_raise( p_e, "not enough memory" );
291 p_mi->drawable.agl = 0;
292 p_mi->drawable.xid = 0;
293 p_mi->drawable.hwnd = NULL;
294 p_mi->drawable.nsobject = NULL;
295 p_mi->p_libvlc_instance = p_libvlc_instance;
296 p_mi->p_input_thread = NULL;
297 p_mi->p_input_resource = NULL;
298 p_mi->i_refcount = 1;
299 vlc_mutex_init( &p_mi->object_lock );
300 p_mi->p_event_manager = libvlc_event_manager_new( p_mi,
301 p_libvlc_instance, p_e );
302 if( libvlc_exception_raised( p_e ) )
304 vlc_mutex_destroy( &p_mi->object_lock );
309 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
310 libvlc_MediaPlayerNothingSpecial, p_e );
311 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
312 libvlc_MediaPlayerOpening, p_e );
313 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
314 libvlc_MediaPlayerBuffering, p_e );
315 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
316 libvlc_MediaPlayerPlaying, p_e );
317 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
318 libvlc_MediaPlayerPaused, p_e );
319 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
320 libvlc_MediaPlayerStopped, p_e );
321 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
322 libvlc_MediaPlayerForward, p_e );
323 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
324 libvlc_MediaPlayerBackward, p_e );
325 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
326 libvlc_MediaPlayerEndReached, p_e );
327 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
328 libvlc_MediaPlayerEncounteredError, p_e );
330 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
331 libvlc_MediaPlayerPositionChanged, p_e );
332 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
333 libvlc_MediaPlayerTimeChanged, p_e );
334 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
335 libvlc_MediaPlayerLengthChanged, p_e );
336 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
337 libvlc_MediaPlayerTitleChanged, p_e );
338 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
339 libvlc_MediaPlayerSeekableChanged, p_e );
340 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
341 libvlc_MediaPlayerPausableChanged, p_e );
343 /* Snapshot initialization */
344 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
345 libvlc_MediaPlayerSnapshotTaken, p_e );
347 /* Attach a var callback to the global object to provide the glue between
348 vout_thread that generates the event and media_player that re-emits it
349 with its own event manager
351 var_Create( p_libvlc_instance->p_libvlc_int, "vout-snapshottaken",
352 VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
353 var_AddCallback( p_libvlc_instance->p_libvlc_int, "vout-snapshottaken",
354 SnapshotTakenCallback, p_mi );
359 /**************************************************************************
360 * Create a Media Instance object with a media descriptor.
361 **************************************************************************/
362 libvlc_media_player_t *
363 libvlc_media_player_new_from_media(
364 libvlc_media_t * p_md,
365 libvlc_exception_t *p_e )
367 libvlc_media_player_t * p_mi;
369 p_mi = libvlc_media_player_new( p_md->p_libvlc_instance, p_e );
373 libvlc_media_retain( p_md );
379 /**************************************************************************
380 * Destroy a Media Instance object (libvlc internal)
382 * Warning: No lock held here, but hey, this is internal. Caller must lock.
383 **************************************************************************/
384 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
388 /* Detach Callback from the main libvlc object */
389 var_DelCallback( p_mi->p_libvlc_instance->p_libvlc_int,
390 "vout-snapshottaken", SnapshotTakenCallback, p_mi );
392 /* Release the input thread */
393 release_input_thread( p_mi, true );
395 if( p_mi->p_input_resource )
397 input_resource_Delete( p_mi->p_input_resource );
398 p_mi->p_input_resource = NULL;
401 libvlc_event_manager_release( p_mi->p_event_manager );
402 libvlc_media_release( p_mi->p_md );
403 vlc_mutex_destroy( &p_mi->object_lock );
407 /**************************************************************************
408 * Release a Media Instance object.
410 * Function does the locking.
411 **************************************************************************/
412 void libvlc_media_player_release( libvlc_media_player_t *p_mi )
417 vlc_mutex_lock( &p_mi->object_lock );
418 destroy = !--p_mi->i_refcount;
419 vlc_mutex_unlock( &p_mi->object_lock );
422 libvlc_media_player_destroy( p_mi );
425 /**************************************************************************
426 * Retain a Media Instance object.
428 * Caller must hold the lock.
429 **************************************************************************/
430 void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
434 vlc_mutex_lock( &p_mi->object_lock );
436 vlc_mutex_unlock( &p_mi->object_lock );
439 /**************************************************************************
440 * Set the Media descriptor associated with the instance.
442 * Enter without lock -- function will lock the object.
443 **************************************************************************/
444 void libvlc_media_player_set_media(
445 libvlc_media_player_t *p_mi,
446 libvlc_media_t *p_md,
447 libvlc_exception_t *p_e )
454 vlc_mutex_lock( &p_mi->object_lock );
456 /* FIXME I am not sure if it is a user request or on die(eof/error)
458 release_input_thread( p_mi,
459 p_mi->p_input_thread &&
460 !p_mi->p_input_thread->b_eof &&
461 !p_mi->p_input_thread->b_error );
464 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, p_e );
466 libvlc_media_release( p_mi->p_md );
471 vlc_mutex_unlock( &p_mi->object_lock );
472 return; /* It is ok to pass a NULL md */
475 libvlc_media_retain( p_md );
478 /* The policy here is to ignore that we were created using a different
479 * libvlc_instance, because we don't really care */
480 p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
482 vlc_mutex_unlock( &p_mi->object_lock );
485 /**************************************************************************
486 * Get the Media descriptor associated with the instance.
487 **************************************************************************/
489 libvlc_media_player_get_media(
490 libvlc_media_player_t *p_mi,
491 libvlc_exception_t *p_e )
496 vlc_mutex_lock( &p_mi->object_lock );
499 libvlc_media_retain( p_mi->p_md );
500 vlc_mutex_unlock( &p_mi->object_lock );
504 /**************************************************************************
505 * Get the event Manager.
506 **************************************************************************/
507 libvlc_event_manager_t *
508 libvlc_media_player_event_manager(
509 libvlc_media_player_t *p_mi,
510 libvlc_exception_t *p_e )
514 return p_mi->p_event_manager;
517 /**************************************************************************
518 * Trigger a snapshot Taken Event.
519 *************************************************************************/
520 static int SnapshotTakenCallback( vlc_object_t *p_this, char const *psz_cmd,
521 vlc_value_t oldval, vlc_value_t newval, void *p_data )
523 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
526 libvlc_media_player_t* p_mi = (libvlc_media_player_t*) p_data ;
527 libvlc_event_t event ;
528 event.type = libvlc_MediaPlayerSnapshotTaken ;
529 event.u.media_player_snapshot_taken.psz_filename = newval.psz_string ;
530 /* Snapshot psz data is a vlc_variable owned by libvlc object .
531 Its memmory management is taken care by the obj*/
532 msg_Dbg( p_this, "about to emit libvlc_snapshot_taken.make psz_str=0x%p"
533 " (%s)", event.u.media_player_snapshot_taken.psz_filename,
534 event.u.media_player_snapshot_taken.psz_filename );
535 libvlc_event_send( p_mi->p_event_manager, &event );
540 /**************************************************************************
541 * Tell media player to start playing.
542 **************************************************************************/
543 void libvlc_media_player_play( libvlc_media_player_t *p_mi,
544 libvlc_exception_t *p_e )
546 input_thread_t * p_input_thread;
548 if( (p_input_thread = libvlc_get_input_thread( p_mi, p_e )) )
550 /* A thread already exists, send it a play message */
551 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
552 vlc_object_release( p_input_thread );
556 /* Ignore previous exception */
557 libvlc_exception_clear( p_e );
559 vlc_mutex_lock( &p_mi->object_lock );
563 libvlc_exception_raise( p_e, "no associated media descriptor" );
564 vlc_mutex_unlock( &p_mi->object_lock );
568 p_mi->p_input_thread = input_Create( p_mi->p_libvlc_instance->p_libvlc_int,
569 p_mi->p_md->p_input_item, NULL, p_mi->p_input_resource );
571 if( !p_mi->p_input_thread )
573 vlc_mutex_unlock( &p_mi->object_lock );
577 p_mi->p_input_resource = NULL;
578 p_input_thread = p_mi->p_input_thread;
580 var_Create( p_input_thread, "drawable-agl", VLC_VAR_INTEGER );
581 if( p_mi->drawable.agl )
582 var_SetInteger( p_input_thread, "drawable-agl", p_mi->drawable.agl );
584 var_Create( p_input_thread, "drawable-xid", VLC_VAR_INTEGER );
585 if( p_mi->drawable.xid )
586 var_SetInteger( p_input_thread, "drawable-xid", p_mi->drawable.xid );
588 var_Create( p_input_thread, "drawable-hwnd", VLC_VAR_ADDRESS );
589 if( p_mi->drawable.hwnd != NULL )
590 var_SetAddress( p_input_thread, "drawable-hwnd", p_mi->drawable.hwnd );
592 var_Create( p_input_thread, "drawable-nsobject", VLC_VAR_ADDRESS );
593 if( p_mi->drawable.nsobject != NULL )
594 var_SetAddress( p_input_thread, "drawable-nsobject", p_mi->drawable.nsobject );
596 var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
597 var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
598 var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
600 if( input_Start( p_input_thread ) )
602 vlc_object_release( p_input_thread );
603 p_mi->p_input_thread = NULL;
606 vlc_mutex_unlock( &p_mi->object_lock );
609 /**************************************************************************
611 **************************************************************************/
612 void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
613 libvlc_exception_t *p_e )
615 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
616 if( !p_input_thread )
619 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
620 if( state == libvlc_Playing || state == libvlc_Buffering )
622 if( libvlc_media_player_can_pause( p_mi, p_e ) )
623 input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
625 libvlc_media_player_stop( p_mi, p_e );
628 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
630 vlc_object_release( p_input_thread );
633 /**************************************************************************
634 * Tells whether the media player is currently playing.
636 * Enter with lock held.
637 **************************************************************************/
638 int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi,
639 libvlc_exception_t *p_e )
641 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
642 return (libvlc_Playing == state) || (libvlc_Buffering == state);
645 /**************************************************************************
647 **************************************************************************/
648 void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
649 libvlc_exception_t *p_e )
651 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
653 if( state == libvlc_Playing ||
654 state == libvlc_Paused ||
655 state == libvlc_Buffering )
657 /* Send a stop notification event only if we are in playing,
658 * buffering or paused states */
659 libvlc_media_set_state( p_mi->p_md, libvlc_Stopped, p_e );
661 /* Construct and send the event */
662 libvlc_event_t event;
663 event.type = libvlc_MediaPlayerStopped;
664 libvlc_event_send( p_mi->p_event_manager, &event );
667 vlc_mutex_lock( &p_mi->object_lock );
668 release_input_thread( p_mi, true ); /* This will stop the input thread */
669 vlc_mutex_unlock( &p_mi->object_lock );
672 /**************************************************************************
674 **************************************************************************/
675 void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
677 libvlc_exception_t *p_e )
680 p_mi->drawable.nsobject = drawable;
683 /**************************************************************************
685 **************************************************************************/
686 void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
688 return p_mi->drawable.nsobject;
691 /**************************************************************************
693 **************************************************************************/
694 void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
696 libvlc_exception_t *p_e )
699 p_mi->drawable.agl = drawable;
702 /**************************************************************************
704 **************************************************************************/
705 uint32_t libvlc_media_player_get_agl( libvlc_media_player_t *p_mi )
707 return p_mi->drawable.agl;
710 /**************************************************************************
712 **************************************************************************/
713 void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
715 libvlc_exception_t *p_e )
718 p_mi->drawable.xid = drawable;
721 /**************************************************************************
723 **************************************************************************/
724 uint32_t libvlc_media_player_get_xwindow( libvlc_media_player_t *p_mi )
726 return p_mi->drawable.xid;
729 /**************************************************************************
731 **************************************************************************/
732 void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
734 libvlc_exception_t *p_e )
737 p_mi->drawable.hwnd = drawable;
740 /**************************************************************************
742 **************************************************************************/
743 void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi )
745 return p_mi->drawable.hwnd;
748 /**************************************************************************
750 **************************************************************************/
751 void libvlc_media_player_set_drawable( libvlc_media_player_t *p_mi,
752 libvlc_drawable_t drawable,
753 libvlc_exception_t *p_e )
756 if (sizeof (HWND) <= sizeof (libvlc_drawable_t))
757 p_mi->drawable.hwnd = (HWND)drawable;
759 libvlc_exception_raise(p_e, "Operation not supported");
760 #elif defined(__APPLE__)
761 p_mi->drawable.agl = drawable;
764 p_mi->drawable.xid = drawable;
769 /**************************************************************************
771 **************************************************************************/
773 libvlc_media_player_get_drawable ( libvlc_media_player_t *p_mi,
774 libvlc_exception_t *p_e )
779 if (sizeof (HWND) <= sizeof (libvlc_drawable_t))
780 return (libvlc_drawable_t)p_mi->drawable.hwnd;
783 #elif defined(__APPLE__)
784 return p_mi->drawable.agl;
786 return p_mi->drawable.xid;
790 /**************************************************************************
791 * Getters for stream information
792 **************************************************************************/
793 libvlc_time_t libvlc_media_player_get_length(
794 libvlc_media_player_t *p_mi,
795 libvlc_exception_t *p_e )
797 input_thread_t *p_input_thread;
798 libvlc_time_t i_time;
800 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
801 if( !p_input_thread )
804 i_time = var_GetTime( p_input_thread, "length" );
805 vlc_object_release( p_input_thread );
807 return (i_time+500LL)/1000LL;
810 libvlc_time_t libvlc_media_player_get_time(
811 libvlc_media_player_t *p_mi,
812 libvlc_exception_t *p_e )
814 input_thread_t *p_input_thread;
815 libvlc_time_t i_time;
817 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
818 if( !p_input_thread )
821 i_time = var_GetTime( p_input_thread , "time" );
822 vlc_object_release( p_input_thread );
823 return (i_time+500LL)/1000LL;
826 void libvlc_media_player_set_time(
827 libvlc_media_player_t *p_mi,
828 libvlc_time_t i_time,
829 libvlc_exception_t *p_e )
831 input_thread_t *p_input_thread;
833 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
834 if( !p_input_thread )
837 var_SetTime( p_input_thread, "time", i_time*1000LL );
838 vlc_object_release( p_input_thread );
841 void libvlc_media_player_set_position(
842 libvlc_media_player_t *p_mi,
844 libvlc_exception_t *p_e )
846 input_thread_t *p_input_thread;
848 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
849 if( !p_input_thread )
852 var_SetFloat( p_input_thread, "position", position );
853 vlc_object_release( p_input_thread );
856 float libvlc_media_player_get_position(
857 libvlc_media_player_t *p_mi,
858 libvlc_exception_t *p_e )
860 input_thread_t *p_input_thread;
863 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
864 if( !p_input_thread )
867 f_position = var_GetFloat( p_input_thread, "position" );
868 vlc_object_release( p_input_thread );
873 void libvlc_media_player_set_chapter(
874 libvlc_media_player_t *p_mi,
876 libvlc_exception_t *p_e )
878 input_thread_t *p_input_thread;
880 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
881 if( !p_input_thread )
884 var_SetInteger( p_input_thread, "chapter", chapter );
885 vlc_object_release( p_input_thread );
888 int libvlc_media_player_get_chapter(
889 libvlc_media_player_t *p_mi,
890 libvlc_exception_t *p_e )
892 input_thread_t *p_input_thread;
895 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
896 if( !p_input_thread )
899 i_chapter = var_GetInteger( p_input_thread, "chapter" );
900 vlc_object_release( p_input_thread );
905 int libvlc_media_player_get_chapter_count(
906 libvlc_media_player_t *p_mi,
907 libvlc_exception_t *p_e )
909 input_thread_t *p_input_thread;
912 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
913 if( !p_input_thread )
916 var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
917 vlc_object_release( p_input_thread );
922 int libvlc_media_player_get_chapter_count_for_title(
923 libvlc_media_player_t *p_mi,
925 libvlc_exception_t *p_e )
927 input_thread_t *p_input_thread;
930 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
931 if( !p_input_thread )
935 if( asprintf( &psz_name, "title %2i", i_title ) == -1 )
937 vlc_object_release( p_input_thread );
940 var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL );
941 vlc_object_release( p_input_thread );
947 void libvlc_media_player_set_title(
948 libvlc_media_player_t *p_mi,
950 libvlc_exception_t *p_e )
952 input_thread_t *p_input_thread;
954 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
955 if( !p_input_thread )
958 var_SetInteger( p_input_thread, "title", i_title );
959 vlc_object_release( p_input_thread );
962 libvlc_event_t event;
963 event.type = libvlc_MediaPlayerTitleChanged;
964 event.u.media_player_title_changed.new_title = i_title;
965 libvlc_event_send( p_mi->p_event_manager, &event );
968 int libvlc_media_player_get_title(
969 libvlc_media_player_t *p_mi,
970 libvlc_exception_t *p_e )
972 input_thread_t *p_input_thread;
975 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
976 if( !p_input_thread )
979 i_title = var_GetInteger( p_input_thread, "title" );
980 vlc_object_release( p_input_thread );
985 int libvlc_media_player_get_title_count(
986 libvlc_media_player_t *p_mi,
987 libvlc_exception_t *p_e )
989 input_thread_t *p_input_thread;
992 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
993 if( !p_input_thread )
996 var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
997 vlc_object_release( p_input_thread );
1002 void libvlc_media_player_next_chapter(
1003 libvlc_media_player_t *p_mi,
1004 libvlc_exception_t *p_e )
1006 input_thread_t *p_input_thread;
1008 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
1009 if( !p_input_thread )
1012 int i_type = var_Type( p_input_thread, "next-chapter" );
1013 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1014 "next-chapter":"next-title", true );
1016 vlc_object_release( p_input_thread );
1019 void libvlc_media_player_previous_chapter(
1020 libvlc_media_player_t *p_mi,
1021 libvlc_exception_t *p_e )
1023 input_thread_t *p_input_thread;
1025 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
1026 if( !p_input_thread )
1029 int i_type = var_Type( p_input_thread, "next-chapter" );
1030 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1031 "prev-chapter":"prev-title", true );
1033 vlc_object_release( p_input_thread );
1036 float libvlc_media_player_get_fps(
1037 libvlc_media_player_t *p_mi,
1038 libvlc_exception_t *p_e)
1040 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1043 if( p_input_thread )
1045 if( input_Control( p_input_thread, INPUT_GET_VIDEO_FPS, &f_fps ) )
1047 vlc_object_release( p_input_thread );
1052 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi,
1053 libvlc_exception_t *p_e)
1055 input_thread_t *p_input_thread =
1056 libvlc_get_input_thread ( p_mi, p_e);
1057 if ( !p_input_thread )
1060 if ( !p_input_thread->b_die && !p_input_thread->b_dead )
1062 vlc_object_release( p_input_thread );
1065 vlc_object_release( p_input_thread );
1069 void libvlc_media_player_set_rate(
1070 libvlc_media_player_t *p_mi,
1072 libvlc_exception_t *p_e )
1074 input_thread_t *p_input_thread;
1077 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1078 if( !p_input_thread )
1081 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1082 if( (rate < 0.0) && !b_can_rewind )
1084 vlc_object_release( p_input_thread );
1085 libvlc_exception_raise( p_e, "Rate value is invalid" );
1089 var_SetInteger( p_input_thread, "rate", 1000.0f/rate );
1090 vlc_object_release( p_input_thread );
1093 float libvlc_media_player_get_rate(
1094 libvlc_media_player_t *p_mi,
1095 libvlc_exception_t *p_e )
1097 input_thread_t *p_input_thread;
1101 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1102 if( !p_input_thread )
1103 return 0.0; /* rate < 0 indicates rewind */
1105 i_rate = var_GetInteger( p_input_thread, "rate" );
1106 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1107 if( i_rate < 0 && !b_can_rewind )
1109 vlc_object_release( p_input_thread );
1110 libvlc_exception_raise( p_e, "invalid rate" );
1113 vlc_object_release( p_input_thread );
1115 return (float)1000.0f/i_rate;
1118 libvlc_state_t libvlc_media_player_get_state(
1119 libvlc_media_player_t *p_mi,
1120 libvlc_exception_t *p_e )
1122 input_thread_t *p_input_thread;
1123 libvlc_state_t state = libvlc_Ended;
1125 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1126 if( !p_input_thread )
1128 /* We do return the right value, no need to throw an exception */
1129 if( libvlc_exception_raised( p_e ) )
1130 libvlc_exception_clear( p_e );
1134 state = libvlc_media_get_state( p_mi->p_md, NULL );
1135 if( state == libvlc_Playing )
1138 caching = var_GetFloat( p_input_thread, "cache" );
1139 if( caching > 0.0 && caching < 1.0 )
1140 state = libvlc_Buffering;
1142 vlc_object_release( p_input_thread );
1146 int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi,
1147 libvlc_exception_t *p_e )
1149 input_thread_t *p_input_thread;
1152 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1153 if ( !p_input_thread )
1155 /* We do return the right value, no need to throw an exception */
1156 if( libvlc_exception_raised( p_e ) )
1157 libvlc_exception_clear( p_e );
1160 b_seekable = var_GetBool( p_input_thread, "can-seek" );
1161 vlc_object_release( p_input_thread );
1166 /* internal function, used by audio, video */
1167 libvlc_track_description_t *
1168 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1169 const char *psz_variable,
1170 libvlc_exception_t *p_e )
1172 input_thread_t *p_input = libvlc_get_input_thread( p_mi, p_e );
1173 libvlc_track_description_t *p_track_description = NULL,
1174 *p_actual, *p_previous;
1179 vlc_value_t val_list, text_list;
1180 var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list);
1183 if( val_list.p_list->i_count <= 0 )
1186 p_track_description = ( libvlc_track_description_t * )
1187 malloc( sizeof( libvlc_track_description_t ) );
1188 if ( !p_track_description )
1190 libvlc_exception_raise( p_e, "not enough memory" );
1193 p_actual = p_track_description;
1195 for( int i = 0; i < val_list.p_list->i_count; i++ )
1199 p_actual = ( libvlc_track_description_t * )
1200 malloc( sizeof( libvlc_track_description_t ) );
1203 libvlc_track_description_release( p_track_description );
1204 libvlc_exception_raise( p_e, "not enough memory" );
1208 p_actual->i_id = val_list.p_list->p_values[i].i_int;
1209 p_actual->psz_name = strdup( text_list.p_list->p_values[i].psz_string );
1210 p_actual->p_next = NULL;
1212 p_previous->p_next = p_actual;
1213 p_previous = p_actual;
1218 var_FreeList( &val_list, &text_list );
1219 vlc_object_release( p_input );
1221 return p_track_description;
1224 void libvlc_track_description_release( libvlc_track_description_t *p_td )
1226 libvlc_track_description_t *p_actual, *p_before;
1231 free( p_actual->psz_name );
1232 p_before = p_actual;
1233 p_actual = p_before->p_next;
1238 int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi,
1239 libvlc_exception_t *p_e )
1241 input_thread_t *p_input_thread;
1244 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1245 if ( !p_input_thread )
1247 /* We do return the right value, no need to throw an exception */
1248 if( libvlc_exception_raised( p_e ) )
1249 libvlc_exception_clear( p_e );
1252 b_can_pause = var_GetBool( p_input_thread, "can-pause" );
1253 vlc_object_release( p_input_thread );
1258 void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi, libvlc_exception_t *p_e )
1260 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1261 if( p_input_thread != NULL )
1263 var_TriggerCallback( p_input_thread, "frame-next" );
1264 vlc_object_release( p_input_thread );
1267 libvlc_exception_raise( p_e, "Input thread is NULL" );