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 const libvlc_state_t vlc_to_libvlc_state_array[] =
62 [INIT_S] = libvlc_NothingSpecial,
63 [OPENING_S] = libvlc_Opening,
64 [PLAYING_S] = libvlc_Playing,
65 [PAUSE_S] = libvlc_Paused,
66 [END_S] = libvlc_Ended,
67 [ERROR_S] = libvlc_Error,
70 static inline libvlc_state_t vlc_to_libvlc_state( int vlc_state )
72 if( vlc_state < 0 || vlc_state > 6 )
75 return vlc_to_libvlc_state_array[vlc_state];
79 * Release the associated input thread.
81 * Object lock is NOT held.
83 static void release_input_thread( libvlc_media_player_t *p_mi, bool b_input_abort )
85 input_thread_t * p_input_thread;
87 if( !p_mi || !p_mi->p_input_thread )
90 p_input_thread = p_mi->p_input_thread;
92 var_DelCallback( p_input_thread, "can-seek",
93 input_seekable_changed, p_mi );
94 var_DelCallback( p_input_thread, "can-pause",
95 input_pausable_changed, p_mi );
96 var_DelCallback( p_input_thread, "intf-event",
97 input_event_changed, p_mi );
99 /* We owned this one */
100 input_Stop( p_input_thread, b_input_abort );
101 vlc_thread_join( p_input_thread );
103 var_Destroy( p_input_thread, "drawable-hwnd" );
104 var_Destroy( p_input_thread, "drawable-xid" );
105 var_Destroy( p_input_thread, "drawable-agl" );
107 vlc_object_release( p_input_thread );
109 p_mi->p_input_thread = NULL;
113 * Retrieve the input thread. Be sure to release the object
114 * once you are done with it. (libvlc Internal)
116 * Function will lock the object.
118 input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi,
119 libvlc_exception_t *p_e )
121 input_thread_t *p_input_thread;
123 if( !p_mi ) RAISENULL( "Media Instance is NULL" );
125 vlc_mutex_lock( &p_mi->object_lock );
127 if( !p_mi->p_input_thread )
129 vlc_mutex_unlock( &p_mi->object_lock );
130 RAISENULL( "Input is NULL" );
133 p_input_thread = p_mi->p_input_thread;
134 vlc_object_hold( p_input_thread );
136 vlc_mutex_unlock( &p_mi->object_lock );
138 return p_input_thread;
142 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
143 vlc_value_t oldval, vlc_value_t newval,
149 libvlc_media_player_t * p_mi = p_userdata;
150 libvlc_event_t event;
152 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
153 event.type = libvlc_MediaPlayerSeekableChanged;
154 event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
156 libvlc_event_send( p_mi->p_event_manager, &event );
161 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
162 vlc_value_t oldval, vlc_value_t newval,
168 libvlc_media_player_t * p_mi = p_userdata;
169 libvlc_event_t event;
171 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
172 event.type = libvlc_MediaPlayerPausableChanged;
173 event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
175 libvlc_event_send( p_mi->p_event_manager, &event );
180 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
181 vlc_value_t oldval, vlc_value_t newval,
185 input_thread_t * p_input = (input_thread_t *)p_this;
186 libvlc_media_player_t * p_mi = p_userdata;
187 libvlc_event_t event;
189 assert( !strcmp( psz_cmd, "intf-event" ) );
191 if( newval.i_int == INPUT_EVENT_STATE )
193 libvlc_state_t libvlc_state;
195 switch ( var_GetInteger( p_input, "state" ) )
198 libvlc_state = libvlc_NothingSpecial;
199 event.type = libvlc_MediaPlayerNothingSpecial;
202 libvlc_state = libvlc_Opening;
203 event.type = libvlc_MediaPlayerOpening;
206 libvlc_state = libvlc_Playing;
207 event.type = libvlc_MediaPlayerPlaying;
210 libvlc_state = libvlc_Paused;
211 event.type = libvlc_MediaPlayerPaused;
214 libvlc_state = libvlc_Ended;
215 event.type = libvlc_MediaPlayerEndReached;
218 libvlc_state = libvlc_Error;
219 event.type = libvlc_MediaPlayerEncounteredError;
226 libvlc_media_set_state( p_mi->p_md, libvlc_state, NULL );
227 libvlc_event_send( p_mi->p_event_manager, &event );
229 else if( newval.i_int == INPUT_EVENT_POSITION )
231 if( var_GetInteger( p_input, "state" ) != PLAYING_S )
232 return VLC_SUCCESS; /* Don't send the position while stopped */
235 event.type = libvlc_MediaPlayerPositionChanged;
236 event.u.media_player_position_changed.new_position =
237 var_GetFloat( p_input, "position" );
238 libvlc_event_send( p_mi->p_event_manager, &event );
241 event.type = libvlc_MediaPlayerTimeChanged;
242 event.u.media_player_time_changed.new_time =
243 var_GetTime( p_input, "time" );
244 libvlc_event_send( p_mi->p_event_manager, &event );
246 else if( newval.i_int == INPUT_EVENT_LENGTH )
248 event.type = libvlc_MediaPlayerLengthChanged;
249 event.u.media_player_length_changed.new_length =
250 var_GetTime( p_input, "length" );
251 libvlc_event_send( p_mi->p_event_manager, &event );
258 static void libvlc_media_player_destroy( libvlc_media_player_t * );
260 /**************************************************************************
261 * Create a Media Instance object.
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)
269 * Object locking strategy:
270 * - No lock held while in constructor.
271 * - When accessing any member variable this lock is held. (XXX who locks?)
272 * - When attempting to destroy the object the lock is also held.
273 **************************************************************************/
274 libvlc_media_player_t *
275 libvlc_media_player_new( libvlc_instance_t * p_libvlc_instance,
276 libvlc_exception_t * p_e )
278 libvlc_media_player_t * p_mi;
280 if( !p_libvlc_instance )
282 libvlc_exception_raise( p_e, "invalid libvlc instance" );
286 p_mi = malloc( sizeof(libvlc_media_player_t) );
289 libvlc_exception_raise( p_e, "not enough memory" );
293 p_mi->drawable.agl = 0;
294 p_mi->drawable.xid = 0;
295 p_mi->drawable.hwnd = NULL;
296 p_mi->drawable.nsobject = NULL;
297 p_mi->p_libvlc_instance = p_libvlc_instance;
298 p_mi->p_input_thread = NULL;
299 p_mi->i_refcount = 1;
300 vlc_mutex_init( &p_mi->object_lock );
301 p_mi->p_event_manager = libvlc_event_manager_new( p_mi,
302 p_libvlc_instance, p_e );
303 if( libvlc_exception_raised( p_e ) )
305 vlc_mutex_destroy( &p_mi->object_lock );
310 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
311 libvlc_MediaPlayerNothingSpecial, p_e );
312 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
313 libvlc_MediaPlayerOpening, p_e );
314 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
315 libvlc_MediaPlayerBuffering, p_e );
316 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
317 libvlc_MediaPlayerPlaying, p_e );
318 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
319 libvlc_MediaPlayerPaused, p_e );
320 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
321 libvlc_MediaPlayerStopped, p_e );
322 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
323 libvlc_MediaPlayerForward, p_e );
324 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
325 libvlc_MediaPlayerBackward, p_e );
326 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
327 libvlc_MediaPlayerEndReached, p_e );
328 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
329 libvlc_MediaPlayerEncounteredError, p_e );
331 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
332 libvlc_MediaPlayerPositionChanged, p_e );
333 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
334 libvlc_MediaPlayerTimeChanged, p_e );
335 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
336 libvlc_MediaPlayerLengthChanged, p_e );
337 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
338 libvlc_MediaPlayerTitleChanged, p_e );
339 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
340 libvlc_MediaPlayerSeekableChanged, p_e );
341 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
342 libvlc_MediaPlayerPausableChanged, p_e );
344 /* Snapshot initialization */
345 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
346 libvlc_MediaPlayerSnapshotTaken, p_e );
348 /* Attach a var callback to the global object to provide the glue between
349 vout_thread that generates the event and media_player that re-emits it
350 with its own event manager
352 var_Create( p_libvlc_instance->p_libvlc_int, "vout-snapshottaken",
353 VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
354 var_AddCallback( p_libvlc_instance->p_libvlc_int, "vout-snapshottaken",
355 SnapshotTakenCallback, p_mi );
360 /**************************************************************************
361 * Create a Media Instance object with a media descriptor.
362 **************************************************************************/
363 libvlc_media_player_t *
364 libvlc_media_player_new_from_media(
365 libvlc_media_t * p_md,
366 libvlc_exception_t *p_e )
368 libvlc_media_player_t * p_mi;
370 p_mi = libvlc_media_player_new( p_md->p_libvlc_instance, p_e );
374 libvlc_media_retain( p_md );
380 /**************************************************************************
381 * Destroy a Media Instance object (libvlc internal)
383 * Warning: No lock held here, but hey, this is internal. Caller must lock.
384 **************************************************************************/
385 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
387 input_thread_t *p_input_thread;
388 libvlc_exception_t p_e;
392 /* Detach Callback from the main libvlc object */
393 var_DelCallback( p_mi->p_libvlc_instance->p_libvlc_int,
394 "vout-snapshottaken", SnapshotTakenCallback, p_mi );
396 libvlc_exception_init( &p_e );
397 p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
399 if( libvlc_exception_raised( &p_e ) )
400 /* no need to worry about no input thread */
401 libvlc_exception_clear( &p_e );
403 release_input_thread( p_mi, true );
405 libvlc_event_manager_release( p_mi->p_event_manager );
406 libvlc_media_release( p_mi->p_md );
407 vlc_mutex_destroy( &p_mi->object_lock );
411 /**************************************************************************
412 * Release a Media Instance object.
414 * Function does the locking.
415 **************************************************************************/
416 void libvlc_media_player_release( libvlc_media_player_t *p_mi )
421 vlc_mutex_lock( &p_mi->object_lock );
422 destroy = !--p_mi->i_refcount;
423 vlc_mutex_unlock( &p_mi->object_lock );
426 libvlc_media_player_destroy( p_mi );
429 /**************************************************************************
430 * Retain a Media Instance object.
432 * Caller must hold the lock.
433 **************************************************************************/
434 void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
438 vlc_mutex_lock( &p_mi->object_lock );
440 vlc_mutex_unlock( &p_mi->object_lock );
443 /**************************************************************************
444 * Set the Media descriptor associated with the instance.
446 * Enter without lock -- function will lock the object.
447 **************************************************************************/
448 void libvlc_media_player_set_media(
449 libvlc_media_player_t *p_mi,
450 libvlc_media_t *p_md,
451 libvlc_exception_t *p_e )
458 vlc_mutex_lock( &p_mi->object_lock );
460 /* FIXME I am not sure if it is a user request or on die(eof/error)
462 release_input_thread( p_mi,
463 p_mi->p_input_thread &&
464 !p_mi->p_input_thread->b_eof &&
465 !p_mi->p_input_thread->b_error );
468 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, p_e );
470 libvlc_media_release( p_mi->p_md );
475 vlc_mutex_unlock( &p_mi->object_lock );
476 return; /* It is ok to pass a NULL md */
479 libvlc_media_retain( p_md );
482 /* The policy here is to ignore that we were created using a different
483 * libvlc_instance, because we don't really care */
484 p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
486 vlc_mutex_unlock( &p_mi->object_lock );
489 /**************************************************************************
490 * Get the Media descriptor associated with the instance.
491 **************************************************************************/
493 libvlc_media_player_get_media(
494 libvlc_media_player_t *p_mi,
495 libvlc_exception_t *p_e )
500 vlc_mutex_lock( &p_mi->object_lock );
503 libvlc_media_retain( p_mi->p_md );
504 vlc_mutex_unlock( &p_mi->object_lock );
508 /**************************************************************************
509 * Get the event Manager.
510 **************************************************************************/
511 libvlc_event_manager_t *
512 libvlc_media_player_event_manager(
513 libvlc_media_player_t *p_mi,
514 libvlc_exception_t *p_e )
518 return p_mi->p_event_manager;
521 /**************************************************************************
522 * Trigger a snapshot Taken Event.
523 *************************************************************************/
524 static int SnapshotTakenCallback( vlc_object_t *p_this, char const *psz_cmd,
525 vlc_value_t oldval, vlc_value_t newval, void *p_data )
527 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
530 libvlc_media_player_t* p_mi = (libvlc_media_player_t*) p_data ;
531 libvlc_event_t event ;
532 event.type = libvlc_MediaPlayerSnapshotTaken ;
533 event.u.media_player_snapshot_taken.psz_filename = newval.psz_string ;
534 /* Snapshot psz data is a vlc_variable owned by libvlc object .
535 Its memmory management is taken care by the obj*/
536 msg_Dbg( p_this, "about to emit libvlc_snapshot_taken.make psz_str=0x%p"
537 " (%s)", event.u.media_player_snapshot_taken.psz_filename,
538 event.u.media_player_snapshot_taken.psz_filename );
539 libvlc_event_send( p_mi->p_event_manager, &event );
544 /**************************************************************************
545 * Tell media player to start playing.
546 **************************************************************************/
547 void libvlc_media_player_play( libvlc_media_player_t *p_mi,
548 libvlc_exception_t *p_e )
550 input_thread_t * p_input_thread;
552 if( (p_input_thread = libvlc_get_input_thread( p_mi, p_e )) )
554 /* A thread already exists, send it a play message */
555 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
556 vlc_object_release( p_input_thread );
560 /* Ignore previous exception */
561 libvlc_exception_clear( p_e );
563 vlc_mutex_lock( &p_mi->object_lock );
567 libvlc_exception_raise( p_e, "no associated media descriptor" );
568 vlc_mutex_unlock( &p_mi->object_lock );
572 p_mi->p_input_thread = input_Create( p_mi->p_libvlc_instance->p_libvlc_int,
573 p_mi->p_md->p_input_item, NULL, NULL );
575 if( !p_mi->p_input_thread )
577 vlc_mutex_unlock( &p_mi->object_lock );
581 p_input_thread = p_mi->p_input_thread;
583 var_Create( p_input_thread, "drawable-agl", VLC_VAR_INTEGER );
584 if( p_mi->drawable.agl )
585 var_SetInteger( p_input_thread, "drawable-agl", p_mi->drawable.agl );
587 var_Create( p_input_thread, "drawable-xid", VLC_VAR_INTEGER );
588 if( p_mi->drawable.xid )
589 var_SetInteger( p_input_thread, "drawable-xid", p_mi->drawable.xid );
591 var_Create( p_input_thread, "drawable-hwnd", VLC_VAR_ADDRESS );
592 if( p_mi->drawable.hwnd != NULL )
594 vlc_value_t val = { .p_address = p_mi->drawable.hwnd };
595 var_Set( p_input_thread, "drawable-hwnd", val );
598 var_Create( p_input_thread, "drawable-nsobject", VLC_VAR_ADDRESS );
599 if( p_mi->drawable.nsobject != NULL )
601 vlc_value_t val = { .p_address = p_mi->drawable.nsobject };
602 var_Set( p_input_thread, "drawable-nsobject", val );
605 var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
606 var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
607 var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
609 if( input_Start( p_input_thread ) )
611 vlc_object_release( p_input_thread );
612 p_mi->p_input_thread = NULL;
615 vlc_mutex_unlock( &p_mi->object_lock );
618 /**************************************************************************
620 **************************************************************************/
621 void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
622 libvlc_exception_t *p_e )
624 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
625 if( !p_input_thread )
628 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
629 if( state == libvlc_Playing || state == libvlc_Buffering )
631 if( libvlc_media_player_can_pause( p_mi, p_e ) )
632 input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
634 libvlc_media_player_stop( p_mi, p_e );
637 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
639 vlc_object_release( p_input_thread );
642 /**************************************************************************
643 * Tells whether the media player is currently playing.
645 * Enter with lock held.
646 **************************************************************************/
647 int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi,
648 libvlc_exception_t *p_e )
650 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
651 return (libvlc_Playing == state) || (libvlc_Buffering == state);
654 /**************************************************************************
656 **************************************************************************/
657 void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
658 libvlc_exception_t *p_e )
660 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
662 if( state == libvlc_Playing ||
663 state == libvlc_Paused ||
664 state == libvlc_Buffering )
666 /* Send a stop notification event only if we are in playing,
667 * buffering or paused states */
668 libvlc_media_set_state( p_mi->p_md, libvlc_Ended, p_e );
670 /* Construct and send the event */
671 libvlc_event_t event;
672 event.type = libvlc_MediaPlayerStopped;
673 libvlc_event_send( p_mi->p_event_manager, &event );
676 vlc_mutex_lock( &p_mi->object_lock );
677 release_input_thread( p_mi, true ); /* This will stop the input thread */
678 vlc_mutex_unlock( &p_mi->object_lock );
681 /**************************************************************************
683 **************************************************************************/
684 void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
686 libvlc_exception_t *p_e )
689 p_mi->drawable.nsobject = drawable;
692 /**************************************************************************
694 **************************************************************************/
695 void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
697 return p_mi->drawable.nsobject;
700 /**************************************************************************
702 **************************************************************************/
703 void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
705 libvlc_exception_t *p_e )
708 p_mi->drawable.agl = drawable;
711 /**************************************************************************
713 **************************************************************************/
714 uint32_t libvlc_media_player_get_agl( libvlc_media_player_t *p_mi )
716 return p_mi->drawable.agl;
719 /**************************************************************************
721 **************************************************************************/
722 void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
724 libvlc_exception_t *p_e )
727 p_mi->drawable.xid = drawable;
730 /**************************************************************************
732 **************************************************************************/
733 uint32_t libvlc_media_player_get_xwindow( libvlc_media_player_t *p_mi )
735 return p_mi->drawable.xid;
738 /**************************************************************************
740 **************************************************************************/
741 void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
743 libvlc_exception_t *p_e )
746 p_mi->drawable.hwnd = drawable;
749 /**************************************************************************
751 **************************************************************************/
752 void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi )
754 return p_mi->drawable.hwnd;
757 /**************************************************************************
759 **************************************************************************/
760 void libvlc_media_player_set_drawable( libvlc_media_player_t *p_mi,
761 libvlc_drawable_t drawable,
762 libvlc_exception_t *p_e )
765 if (sizeof (HWND) <= sizeof (libvlc_drawable_t))
766 p_mi->drawable.hwnd = (HWND)drawable;
768 libvlc_exception_raise(p_e, "Operation not supported");
769 #elif defined(__APPLE__)
770 p_mi->drawable.agl = drawable;
773 p_mi->drawable.xid = drawable;
778 /**************************************************************************
780 **************************************************************************/
782 libvlc_media_player_get_drawable ( libvlc_media_player_t *p_mi,
783 libvlc_exception_t *p_e )
788 if (sizeof (HWND) <= sizeof (libvlc_drawable_t))
789 return (libvlc_drawable_t)p_mi->drawable.hwnd;
792 #elif defined(__APPLE__)
793 return p_mi->drawable.agl;
795 return p_mi->drawable.xid;
799 /**************************************************************************
800 * Getters for stream information
801 **************************************************************************/
802 libvlc_time_t libvlc_media_player_get_length(
803 libvlc_media_player_t *p_mi,
804 libvlc_exception_t *p_e )
806 input_thread_t *p_input_thread;
809 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
810 if( !p_input_thread )
813 var_Get( p_input_thread, "length", &val );
814 vlc_object_release( p_input_thread );
816 return (val.i_time+500LL)/1000LL;
819 libvlc_time_t libvlc_media_player_get_time(
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 , "time", &val );
831 vlc_object_release( p_input_thread );
832 return (val.i_time+500LL)/1000LL;
835 void libvlc_media_player_set_time(
836 libvlc_media_player_t *p_mi,
838 libvlc_exception_t *p_e )
840 input_thread_t *p_input_thread;
842 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
843 if( !p_input_thread )
846 var_SetTime( p_input_thread, "time", time*1000LL );
847 vlc_object_release( p_input_thread );
850 void libvlc_media_player_set_position(
851 libvlc_media_player_t *p_mi,
853 libvlc_exception_t *p_e )
855 input_thread_t *p_input_thread;
857 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
858 if( !p_input_thread )
861 var_SetFloat( p_input_thread, "position", position );
862 vlc_object_release( p_input_thread );
865 float libvlc_media_player_get_position(
866 libvlc_media_player_t *p_mi,
867 libvlc_exception_t *p_e )
869 input_thread_t *p_input_thread;
872 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
873 if( !p_input_thread )
876 var_Get( p_input_thread, "position", &val );
877 vlc_object_release( p_input_thread );
882 void libvlc_media_player_set_chapter(
883 libvlc_media_player_t *p_mi,
885 libvlc_exception_t *p_e )
887 input_thread_t *p_input_thread;
889 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
890 if( !p_input_thread )
893 var_SetInteger( p_input_thread, "chapter", chapter );
894 vlc_object_release( p_input_thread );
897 int libvlc_media_player_get_chapter(
898 libvlc_media_player_t *p_mi,
899 libvlc_exception_t *p_e )
901 input_thread_t *p_input_thread;
904 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
905 if( !p_input_thread )
908 var_Get( p_input_thread, "chapter", &val );
909 vlc_object_release( p_input_thread );
914 int libvlc_media_player_get_chapter_count(
915 libvlc_media_player_t *p_mi,
916 libvlc_exception_t *p_e )
918 input_thread_t *p_input_thread;
921 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
922 if( !p_input_thread )
925 var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
926 vlc_object_release( p_input_thread );
931 int libvlc_media_player_get_chapter_count_for_title(
932 libvlc_media_player_t *p_mi,
934 libvlc_exception_t *p_e )
936 input_thread_t *p_input_thread;
939 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
940 if( !p_input_thread )
944 if( asprintf( &psz_name, "title %2i", i_title ) == -1 )
946 vlc_object_release( p_input_thread );
949 var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL );
950 vlc_object_release( p_input_thread );
956 void libvlc_media_player_set_title(
957 libvlc_media_player_t *p_mi,
959 libvlc_exception_t *p_e )
961 input_thread_t *p_input_thread;
963 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
964 if( !p_input_thread )
967 var_SetInteger( p_input_thread, "title", i_title );
968 vlc_object_release( p_input_thread );
971 libvlc_event_t event;
972 event.type = libvlc_MediaPlayerTitleChanged;
973 event.u.media_player_title_changed.new_title = i_title;
974 libvlc_event_send( p_mi->p_event_manager, &event );
977 int libvlc_media_player_get_title(
978 libvlc_media_player_t *p_mi,
979 libvlc_exception_t *p_e )
981 input_thread_t *p_input_thread;
984 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
985 if( !p_input_thread )
988 var_Get( p_input_thread, "title", &val );
989 vlc_object_release( p_input_thread );
994 int libvlc_media_player_get_title_count(
995 libvlc_media_player_t *p_mi,
996 libvlc_exception_t *p_e )
998 input_thread_t *p_input_thread;
1001 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1002 if( !p_input_thread )
1005 var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
1006 vlc_object_release( p_input_thread );
1011 void libvlc_media_player_next_chapter(
1012 libvlc_media_player_t *p_mi,
1013 libvlc_exception_t *p_e )
1015 input_thread_t *p_input_thread;
1017 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
1018 if( !p_input_thread )
1021 int i_type = var_Type( p_input_thread, "next-chapter" );
1022 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1023 "next-chapter":"next-title", true );
1025 vlc_object_release( p_input_thread );
1028 void libvlc_media_player_previous_chapter(
1029 libvlc_media_player_t *p_mi,
1030 libvlc_exception_t *p_e )
1032 input_thread_t *p_input_thread;
1034 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
1035 if( !p_input_thread )
1038 int i_type = var_Type( p_input_thread, "next-chapter" );
1039 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1040 "prev-chapter":"prev-title", true );
1042 vlc_object_release( p_input_thread );
1045 float libvlc_media_player_get_fps(
1046 libvlc_media_player_t *p_mi,
1047 libvlc_exception_t *p_e)
1049 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1052 if( p_input_thread )
1054 if( input_Control( p_input_thread, INPUT_GET_VIDEO_FPS, &f_fps ) )
1056 vlc_object_release( p_input_thread );
1061 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi,
1062 libvlc_exception_t *p_e)
1064 input_thread_t *p_input_thread =
1065 libvlc_get_input_thread ( p_mi, p_e);
1066 if ( !p_input_thread )
1069 if ( !p_input_thread->b_die && !p_input_thread->b_dead )
1071 vlc_object_release( p_input_thread );
1074 vlc_object_release( p_input_thread );
1078 void libvlc_media_player_set_rate(
1079 libvlc_media_player_t *p_mi,
1081 libvlc_exception_t *p_e )
1083 input_thread_t *p_input_thread;
1086 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1087 if( !p_input_thread )
1090 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1091 if( (rate < 0.0) && !b_can_rewind )
1093 vlc_object_release( p_input_thread );
1094 libvlc_exception_raise( p_e, "Rate value is invalid" );
1098 var_SetInteger( p_input_thread, "rate", 1000.0f/rate );
1099 vlc_object_release( p_input_thread );
1102 float libvlc_media_player_get_rate(
1103 libvlc_media_player_t *p_mi,
1104 libvlc_exception_t *p_e )
1106 input_thread_t *p_input_thread;
1110 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1111 if( !p_input_thread )
1112 return 0.0; /* rate < 0 indicates rewind */
1114 var_Get( p_input_thread, "rate", &val );
1115 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1116 if( (val.i_int < 0) && !b_can_rewind )
1118 libvlc_exception_raise( p_e, "invalid rate" );
1121 vlc_object_release( p_input_thread );
1123 return (float)1000.0f/val.i_int;
1126 libvlc_state_t libvlc_media_player_get_state(
1127 libvlc_media_player_t *p_mi,
1128 libvlc_exception_t *p_e )
1130 input_thread_t *p_input_thread;
1131 libvlc_state_t state = libvlc_Ended;
1134 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1135 if( !p_input_thread )
1137 /* We do return the right value, no need to throw an exception */
1138 if( libvlc_exception_raised( p_e ) )
1139 libvlc_exception_clear( p_e );
1143 var_Get( p_input_thread, "state", &val );
1144 state = vlc_to_libvlc_state(val.i_int);
1146 if( state == libvlc_Playing )
1149 caching = var_GetFloat( p_input_thread, "cache" );
1150 if( caching > 0.0 && caching < 1.0 )
1151 state = libvlc_Buffering;
1153 vlc_object_release( p_input_thread );
1157 int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi,
1158 libvlc_exception_t *p_e )
1160 input_thread_t *p_input_thread;
1163 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1164 if ( !p_input_thread )
1166 /* We do return the right value, no need to throw an exception */
1167 if( libvlc_exception_raised( p_e ) )
1168 libvlc_exception_clear( p_e );
1171 var_Get( p_input_thread, "can-seek", &val );
1172 vlc_object_release( p_input_thread );
1177 /* internal function, used by audio, video */
1178 libvlc_track_description_t *
1179 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1180 const char *psz_variable,
1181 libvlc_exception_t *p_e )
1183 input_thread_t *p_input = libvlc_get_input_thread( p_mi, p_e );
1184 libvlc_track_description_t *p_track_description = NULL,
1185 *p_actual, *p_previous;
1190 vlc_value_t val_list, text_list;
1191 var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list);
1194 if( val_list.p_list->i_count <= 0 )
1197 p_track_description = ( libvlc_track_description_t * )
1198 malloc( sizeof( libvlc_track_description_t ) );
1199 if ( !p_track_description )
1201 libvlc_exception_raise( p_e, "not enough memory" );
1204 p_actual = p_track_description;
1206 for( int i = 0; i < val_list.p_list->i_count; i++ )
1210 p_actual = ( libvlc_track_description_t * )
1211 malloc( sizeof( libvlc_track_description_t ) );
1214 libvlc_track_description_release( p_track_description );
1215 libvlc_exception_raise( p_e, "not enough memory" );
1219 p_actual->i_id = val_list.p_list->p_values[i].i_int;
1220 p_actual->psz_name = strdup( text_list.p_list->p_values[i].psz_string );
1221 p_actual->p_next = NULL;
1223 p_previous->p_next = p_actual;
1224 p_previous = p_actual;
1229 var_FreeList( &val_list, &text_list );
1230 vlc_object_release( p_input );
1232 return p_track_description;
1235 void libvlc_track_description_release( libvlc_track_description_t *p_td )
1237 libvlc_track_description_t *p_actual, *p_before;
1242 free( p_actual->psz_name );
1243 p_before = p_actual;
1244 p_actual = p_before->p_next;
1249 int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi,
1250 libvlc_exception_t *p_e )
1252 input_thread_t *p_input_thread;
1255 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1256 if ( !p_input_thread )
1258 /* We do return the right value, no need to throw an exception */
1259 if( libvlc_exception_raised( p_e ) )
1260 libvlc_exception_clear( p_e );
1263 var_Get( p_input_thread, "can-pause", &val );
1264 vlc_object_release( p_input_thread );