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 *****************************************************************************/
26 #include <vlc/libvlc.h>
27 #include <vlc/libvlc_media.h>
28 #include <vlc/libvlc_events.h>
30 #include <vlc_demux.h>
31 #include <vlc_input.h>
36 #include "libvlc_internal.h"
37 #include "media_internal.h" // libvlc_media_set_state()
38 #include "media_player_internal.h"
41 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
42 vlc_value_t oldval, vlc_value_t newval,
45 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
46 vlc_value_t oldval, vlc_value_t newval,
49 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
50 vlc_value_t oldval, vlc_value_t newval,
53 static int SnapshotTakenCallback( vlc_object_t *p_this, char const *psz_cmd,
54 vlc_value_t oldval, vlc_value_t newval, void *p_data );
56 static const libvlc_state_t vlc_to_libvlc_state_array[] =
58 [INIT_S] = libvlc_NothingSpecial,
59 [OPENING_S] = libvlc_Opening,
60 [PLAYING_S] = libvlc_Playing,
61 [PAUSE_S] = libvlc_Paused,
62 [END_S] = libvlc_Ended,
63 [ERROR_S] = libvlc_Error,
66 static inline libvlc_state_t vlc_to_libvlc_state( int vlc_state )
68 if( vlc_state < 0 || vlc_state > 6 )
71 return vlc_to_libvlc_state_array[vlc_state];
75 * Release the associated input thread.
77 * Object lock is NOT held.
79 static void release_input_thread( libvlc_media_player_t *p_mi, bool b_input_abort )
81 input_thread_t * p_input_thread;
83 if( !p_mi || !p_mi->p_input_thread )
86 p_input_thread = p_mi->p_input_thread;
88 var_DelCallback( p_input_thread, "can-seek",
89 input_seekable_changed, p_mi );
90 var_DelCallback( p_input_thread, "can-pause",
91 input_pausable_changed, p_mi );
92 var_DelCallback( p_input_thread, "intf-event",
93 input_event_changed, p_mi );
95 /* We owned this one */
96 input_Stop( p_input_thread, b_input_abort );
97 vlc_thread_join( p_input_thread );
99 var_Destroy( p_input_thread, "drawable-hwnd" );
100 var_Destroy( p_input_thread, "drawable-xid" );
101 var_Destroy( p_input_thread, "drawable-agl" );
103 vlc_object_release( p_input_thread );
105 p_mi->p_input_thread = NULL;
109 * Retrieve the input thread. Be sure to release the object
110 * once you are done with it. (libvlc Internal)
112 * Function will lock the object.
114 input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi,
115 libvlc_exception_t *p_e )
117 input_thread_t *p_input_thread;
119 if( !p_mi ) RAISENULL( "Media Instance is NULL" );
121 vlc_mutex_lock( &p_mi->object_lock );
123 if( !p_mi->p_input_thread )
125 vlc_mutex_unlock( &p_mi->object_lock );
126 RAISENULL( "Input is NULL" );
129 p_input_thread = p_mi->p_input_thread;
130 vlc_object_hold( p_input_thread );
132 vlc_mutex_unlock( &p_mi->object_lock );
134 return p_input_thread;
138 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
139 vlc_value_t oldval, vlc_value_t newval,
145 libvlc_media_player_t * p_mi = p_userdata;
146 libvlc_event_t event;
148 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
149 event.type = libvlc_MediaPlayerSeekableChanged;
150 event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
152 libvlc_event_send( p_mi->p_event_manager, &event );
157 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
158 vlc_value_t oldval, vlc_value_t newval,
164 libvlc_media_player_t * p_mi = p_userdata;
165 libvlc_event_t event;
167 libvlc_media_set_state( p_mi->p_md, libvlc_NothingSpecial, NULL);
168 event.type = libvlc_MediaPlayerPausableChanged;
169 event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
171 libvlc_event_send( p_mi->p_event_manager, &event );
176 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
177 vlc_value_t oldval, vlc_value_t newval,
181 input_thread_t * p_input = (input_thread_t *)p_this;
182 libvlc_media_player_t * p_mi = p_userdata;
183 libvlc_event_t event;
185 assert( !strcmp( psz_cmd, "intf-event" ) );
187 if( newval.i_int == INPUT_EVENT_STATE )
189 libvlc_state_t libvlc_state;
191 switch ( var_GetInteger( p_input, "state" ) )
194 libvlc_state = libvlc_NothingSpecial;
195 event.type = libvlc_MediaPlayerNothingSpecial;
198 libvlc_state = libvlc_Opening;
199 event.type = libvlc_MediaPlayerOpening;
202 libvlc_state = libvlc_Playing;
203 event.type = libvlc_MediaPlayerPlaying;
206 libvlc_state = libvlc_Paused;
207 event.type = libvlc_MediaPlayerPaused;
210 libvlc_state = libvlc_Ended;
211 event.type = libvlc_MediaPlayerEndReached;
214 libvlc_state = libvlc_Error;
215 event.type = libvlc_MediaPlayerEncounteredError;
222 libvlc_media_set_state( p_mi->p_md, libvlc_state, NULL );
223 libvlc_event_send( p_mi->p_event_manager, &event );
225 else if( newval.i_int == INPUT_EVENT_POSITION )
227 if( var_GetInteger( p_input, "state" ) != PLAYING_S )
228 return VLC_SUCCESS; /* Don't send the position while stopped */
231 event.type = libvlc_MediaPlayerPositionChanged;
232 event.u.media_player_position_changed.new_position =
233 var_GetFloat( p_input, "position" );
234 libvlc_event_send( p_mi->p_event_manager, &event );
237 event.type = libvlc_MediaPlayerTimeChanged;
238 event.u.media_player_time_changed.new_time =
239 var_GetTime( p_input, "time" );
240 libvlc_event_send( p_mi->p_event_manager, &event );
242 else if( newval.i_int == INPUT_EVENT_LENGTH )
244 event.type = libvlc_MediaPlayerLengthChanged;
245 event.u.media_player_length_changed.new_length =
246 var_GetTime( p_input, "length" );
247 libvlc_event_send( p_mi->p_event_manager, &event );
254 static void libvlc_media_player_destroy( libvlc_media_player_t * );
256 /**************************************************************************
257 * Create a Media Instance object.
260 * - All items created by _new start with a refcount set to 1.
261 * - Accessor _release decrease the refcount by 1, if after that
262 * operation the refcount is 0, the object is destroyed.
263 * - Accessor _retain increase the refcount by 1 (XXX: to implement)
265 * Object locking strategy:
266 * - No lock held while in constructor.
267 * - When accessing any member variable this lock is held. (XXX who locks?)
268 * - When attempting to destroy the object the lock is also held.
269 **************************************************************************/
270 libvlc_media_player_t *
271 libvlc_media_player_new( libvlc_instance_t * p_libvlc_instance,
272 libvlc_exception_t * p_e )
274 libvlc_media_player_t * p_mi;
276 if( !p_libvlc_instance )
278 libvlc_exception_raise( p_e, "invalid libvlc instance" );
282 p_mi = malloc( sizeof(libvlc_media_player_t) );
285 libvlc_exception_raise( p_e, "Not enough memory" );
289 p_mi->drawable.agl = 0;
290 p_mi->drawable.xid = 0;
291 p_mi->drawable.hwnd = NULL;
292 p_mi->drawable.nsobject = NULL;
293 p_mi->p_libvlc_instance = p_libvlc_instance;
294 p_mi->p_input_thread = NULL;
295 p_mi->i_refcount = 1;
296 vlc_mutex_init( &p_mi->object_lock );
297 p_mi->p_event_manager = libvlc_event_manager_new( p_mi,
298 p_libvlc_instance, p_e );
299 if( libvlc_exception_raised( p_e ) )
301 vlc_mutex_destroy( &p_mi->object_lock );
306 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
307 libvlc_MediaPlayerNothingSpecial, p_e );
308 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
309 libvlc_MediaPlayerOpening, p_e );
310 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
311 libvlc_MediaPlayerBuffering, p_e );
312 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
313 libvlc_MediaPlayerPlaying, p_e );
314 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
315 libvlc_MediaPlayerPaused, p_e );
316 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
317 libvlc_MediaPlayerStopped, p_e );
318 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
319 libvlc_MediaPlayerForward, p_e );
320 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
321 libvlc_MediaPlayerBackward, p_e );
322 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
323 libvlc_MediaPlayerEndReached, p_e );
324 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
325 libvlc_MediaPlayerEncounteredError, p_e );
327 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
328 libvlc_MediaPlayerPositionChanged, p_e );
329 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
330 libvlc_MediaPlayerTimeChanged, p_e );
331 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
332 libvlc_MediaPlayerLengthChanged, p_e );
333 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
334 libvlc_MediaPlayerTitleChanged, p_e );
335 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
336 libvlc_MediaPlayerSeekableChanged, p_e );
337 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
338 libvlc_MediaPlayerPausableChanged, p_e );
340 /* Snapshot initialization */
341 libvlc_event_manager_register_event_type( p_mi->p_event_manager,
342 libvlc_MediaPlayerSnapshotTaken, p_e );
344 /* Attach a var callback to the global object to provide the glue between
345 vout_thread that generates the event and media_player that re-emits it
346 with its own event manager
348 var_Create( p_libvlc_instance->p_libvlc_int, "vout-snapshottaken",
349 VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
350 var_AddCallback( p_libvlc_instance->p_libvlc_int, "vout-snapshottaken",
351 SnapshotTakenCallback, p_mi );
356 /**************************************************************************
357 * Create a Media Instance object with a media descriptor.
358 **************************************************************************/
359 libvlc_media_player_t *
360 libvlc_media_player_new_from_media(
361 libvlc_media_t * p_md,
362 libvlc_exception_t *p_e )
364 libvlc_media_player_t * p_mi;
366 p_mi = libvlc_media_player_new( p_md->p_libvlc_instance, p_e );
370 libvlc_media_retain( p_md );
376 /**************************************************************************
377 * Destroy a Media Instance object (libvlc internal)
379 * Warning: No lock held here, but hey, this is internal. Caller must lock.
380 **************************************************************************/
381 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
383 input_thread_t *p_input_thread;
384 libvlc_exception_t p_e;
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 libvlc_exception_init( &p_e );
393 p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
395 if( libvlc_exception_raised( &p_e ) )
396 /* no need to worry about no input thread */
397 libvlc_exception_clear( &p_e );
399 release_input_thread( p_mi, true );
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 )
498 libvlc_media_retain( p_mi->p_md );
502 /**************************************************************************
503 * Get the event Manager.
504 **************************************************************************/
505 libvlc_event_manager_t *
506 libvlc_media_player_event_manager(
507 libvlc_media_player_t *p_mi,
508 libvlc_exception_t *p_e )
512 return p_mi->p_event_manager;
515 /**************************************************************************
516 * Trigger a snapshot Taken Event.
517 *************************************************************************/
518 static int SnapshotTakenCallback( vlc_object_t *p_this, char const *psz_cmd,
519 vlc_value_t oldval, vlc_value_t newval, void *p_data )
521 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
524 libvlc_media_player_t* p_mi = (libvlc_media_player_t*) p_data ;
525 libvlc_event_t event ;
526 event.type = libvlc_MediaPlayerSnapshotTaken ;
527 event.u.media_player_snapshot_taken.psz_filename = newval.psz_string ;
528 /* Snapshot psz data is a vlc_variable owned by libvlc object .
529 Its memmory management is taken care by the obj*/
530 msg_Dbg( p_this, "about to emit libvlc_snapshot_taken.make psz_str=0x%p"
531 " (%s)", event.u.media_player_snapshot_taken.psz_filename,
532 event.u.media_player_snapshot_taken.psz_filename );
533 libvlc_event_send( p_mi->p_event_manager, &event );
538 /**************************************************************************
539 * Tell media player to start playing.
540 **************************************************************************/
541 void libvlc_media_player_play( libvlc_media_player_t *p_mi,
542 libvlc_exception_t *p_e )
544 input_thread_t * p_input_thread;
546 if( (p_input_thread = libvlc_get_input_thread( p_mi, p_e )) )
548 /* A thread already exists, send it a play message */
549 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
550 vlc_object_release( p_input_thread );
554 /* Ignore previous exception */
555 libvlc_exception_clear( p_e );
557 vlc_mutex_lock( &p_mi->object_lock );
561 libvlc_exception_raise( p_e, "no associated media descriptor" );
562 vlc_mutex_unlock( &p_mi->object_lock );
566 p_mi->p_input_thread = input_Create( p_mi->p_libvlc_instance->p_libvlc_int,
567 p_mi->p_md->p_input_item, NULL, NULL );
569 if( !p_mi->p_input_thread )
571 vlc_mutex_unlock( &p_mi->object_lock );
575 p_input_thread = p_mi->p_input_thread;
577 var_Create( p_input_thread, "drawable-agl", VLC_VAR_INTEGER );
578 if( p_mi->drawable.agl )
579 var_SetInteger( p_input_thread, "drawable-agl", p_mi->drawable.agl );
581 var_Create( p_input_thread, "drawable-xid", VLC_VAR_INTEGER );
582 if( p_mi->drawable.xid )
583 var_SetInteger( p_input_thread, "drawable-xid", p_mi->drawable.xid );
585 var_Create( p_input_thread, "drawable-hwnd", VLC_VAR_ADDRESS );
586 if( p_mi->drawable.hwnd != NULL )
588 vlc_value_t val = { .p_address = p_mi->drawable.hwnd };
589 var_Set( p_input_thread, "drawable-hwnd", val );
592 var_Create( p_input_thread, "drawable-nsobject", VLC_VAR_ADDRESS );
593 if( p_mi->drawable.nsobject != NULL )
595 vlc_value_t val = { .p_address = p_mi->drawable.nsobject };
596 var_Set( p_input_thread, "drawable-nsobject", val );
599 var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
600 var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
601 var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
603 if( input_Start( p_input_thread ) )
605 vlc_object_release( p_input_thread );
606 p_mi->p_input_thread = NULL;
609 vlc_mutex_unlock( &p_mi->object_lock );
612 /**************************************************************************
614 **************************************************************************/
615 void libvlc_media_player_pause( libvlc_media_player_t *p_mi,
616 libvlc_exception_t *p_e )
618 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
619 if( !p_input_thread )
622 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
623 if( state == libvlc_Playing || state == libvlc_Buffering )
625 if( libvlc_media_player_can_pause( p_mi, p_e ) )
626 input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
628 libvlc_media_player_stop( p_mi, p_e );
631 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
633 vlc_object_release( p_input_thread );
636 /**************************************************************************
637 * Tells whether the media player is currently playing.
639 * Enter with lock held.
640 **************************************************************************/
641 int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi,
642 libvlc_exception_t *p_e )
644 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
645 return (libvlc_Playing == state) || (libvlc_Buffering == state);
648 /**************************************************************************
650 **************************************************************************/
651 void libvlc_media_player_stop( libvlc_media_player_t *p_mi,
652 libvlc_exception_t *p_e )
654 libvlc_state_t state = libvlc_media_player_get_state( p_mi, p_e );
656 if( state == libvlc_Playing ||
657 state == libvlc_Paused ||
658 state == libvlc_Buffering )
660 /* Send a stop notification event only if we are in playing,
661 * buffering or paused states */
662 libvlc_media_set_state( p_mi->p_md, libvlc_Ended, p_e );
664 /* Construct and send the event */
665 libvlc_event_t event;
666 event.type = libvlc_MediaPlayerStopped;
667 libvlc_event_send( p_mi->p_event_manager, &event );
670 vlc_mutex_lock( &p_mi->object_lock );
671 release_input_thread( p_mi, true ); /* This will stop the input thread */
672 vlc_mutex_unlock( &p_mi->object_lock );
675 /**************************************************************************
677 **************************************************************************/
678 void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
680 libvlc_exception_t *p_e )
683 p_mi->drawable.nsobject = drawable;
686 /**************************************************************************
688 **************************************************************************/
689 void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
691 return p_mi->drawable.nsobject;
694 /**************************************************************************
696 **************************************************************************/
697 void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
699 libvlc_exception_t *p_e )
702 p_mi->drawable.agl = drawable;
705 /**************************************************************************
707 **************************************************************************/
708 uint32_t libvlc_media_player_get_agl( libvlc_media_player_t *p_mi )
710 return p_mi->drawable.agl;
713 /**************************************************************************
715 **************************************************************************/
716 void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
718 libvlc_exception_t *p_e )
721 p_mi->drawable.xid = drawable;
724 /**************************************************************************
726 **************************************************************************/
727 uint32_t libvlc_media_player_get_xwindow( libvlc_media_player_t *p_mi )
729 return p_mi->drawable.xid;
732 /**************************************************************************
734 **************************************************************************/
735 void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
737 libvlc_exception_t *p_e )
740 p_mi->drawable.hwnd = drawable;
743 /**************************************************************************
745 **************************************************************************/
746 void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi )
748 return p_mi->drawable.hwnd;
751 /**************************************************************************
753 **************************************************************************/
754 void libvlc_media_player_set_drawable( libvlc_media_player_t *p_mi,
755 libvlc_drawable_t drawable,
756 libvlc_exception_t *p_e )
759 if (sizeof (HWND) <= sizeof (libvlc_drawable_t))
760 p_mi->drawable.hwnd = (HWND)drawable;
762 libvlc_exception_raise(p_e, "Operation not supported");
763 #elif defined(__APPLE__)
764 p_mi->drawable.agl = drawable;
767 p_mi->drawable.xid = drawable;
772 /**************************************************************************
774 **************************************************************************/
776 libvlc_media_player_get_drawable ( libvlc_media_player_t *p_mi,
777 libvlc_exception_t *p_e )
782 if (sizeof (HWND) <= sizeof (libvlc_drawable_t))
783 return (libvlc_drawable_t)p_mi->drawable.hwnd;
786 #elif defined(__APPLE__)
787 return p_mi->drawable.agl;
789 return p_mi->drawable.xid;
793 /**************************************************************************
794 * Getters for stream information
795 **************************************************************************/
796 libvlc_time_t libvlc_media_player_get_length(
797 libvlc_media_player_t *p_mi,
798 libvlc_exception_t *p_e )
800 input_thread_t *p_input_thread;
803 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
804 if( !p_input_thread )
807 var_Get( p_input_thread, "length", &val );
808 vlc_object_release( p_input_thread );
810 return (val.i_time+500LL)/1000LL;
813 libvlc_time_t libvlc_media_player_get_time(
814 libvlc_media_player_t *p_mi,
815 libvlc_exception_t *p_e )
817 input_thread_t *p_input_thread;
820 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
821 if( !p_input_thread )
824 var_Get( p_input_thread , "time", &val );
825 vlc_object_release( p_input_thread );
826 return (val.i_time+500LL)/1000LL;
829 void libvlc_media_player_set_time(
830 libvlc_media_player_t *p_mi,
832 libvlc_exception_t *p_e )
834 input_thread_t *p_input_thread;
836 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
837 if( !p_input_thread )
840 var_SetTime( p_input_thread, "time", time*1000LL );
841 vlc_object_release( p_input_thread );
844 void libvlc_media_player_set_position(
845 libvlc_media_player_t *p_mi,
847 libvlc_exception_t *p_e )
849 input_thread_t *p_input_thread;
851 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
852 if( !p_input_thread )
855 var_SetFloat( p_input_thread, "position", position );
856 vlc_object_release( p_input_thread );
859 float libvlc_media_player_get_position(
860 libvlc_media_player_t *p_mi,
861 libvlc_exception_t *p_e )
863 input_thread_t *p_input_thread;
866 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
867 if( !p_input_thread )
870 var_Get( p_input_thread, "position", &val );
871 vlc_object_release( p_input_thread );
876 void libvlc_media_player_set_chapter(
877 libvlc_media_player_t *p_mi,
879 libvlc_exception_t *p_e )
881 input_thread_t *p_input_thread;
883 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
884 if( !p_input_thread )
887 var_SetInteger( p_input_thread, "chapter", chapter );
888 vlc_object_release( p_input_thread );
891 int libvlc_media_player_get_chapter(
892 libvlc_media_player_t *p_mi,
893 libvlc_exception_t *p_e )
895 input_thread_t *p_input_thread;
898 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
899 if( !p_input_thread )
902 var_Get( p_input_thread, "chapter", &val );
903 vlc_object_release( p_input_thread );
908 int libvlc_media_player_get_chapter_count(
909 libvlc_media_player_t *p_mi,
910 libvlc_exception_t *p_e )
912 input_thread_t *p_input_thread;
915 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
916 if( !p_input_thread )
919 var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
920 vlc_object_release( p_input_thread );
925 int libvlc_media_player_get_chapter_count_for_title(
926 libvlc_media_player_t *p_mi,
928 libvlc_exception_t *p_e )
930 input_thread_t *p_input_thread;
933 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
934 if( !p_input_thread )
938 if( asprintf( &psz_name, "title %2i", i_title ) == -1 )
940 vlc_object_release( p_input_thread );
943 var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL );
944 vlc_object_release( p_input_thread );
950 void libvlc_media_player_set_title(
951 libvlc_media_player_t *p_mi,
953 libvlc_exception_t *p_e )
955 input_thread_t *p_input_thread;
957 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
958 if( !p_input_thread )
961 var_SetInteger( p_input_thread, "title", i_title );
962 vlc_object_release( p_input_thread );
965 libvlc_event_t event;
966 event.type = libvlc_MediaPlayerTitleChanged;
967 event.u.media_player_title_changed.new_title = i_title;
968 libvlc_event_send( p_mi->p_event_manager, &event );
971 int libvlc_media_player_get_title(
972 libvlc_media_player_t *p_mi,
973 libvlc_exception_t *p_e )
975 input_thread_t *p_input_thread;
978 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
979 if( !p_input_thread )
982 var_Get( p_input_thread, "title", &val );
983 vlc_object_release( p_input_thread );
988 int libvlc_media_player_get_title_count(
989 libvlc_media_player_t *p_mi,
990 libvlc_exception_t *p_e )
992 input_thread_t *p_input_thread;
995 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
996 if( !p_input_thread )
999 var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
1000 vlc_object_release( p_input_thread );
1005 void libvlc_media_player_next_chapter(
1006 libvlc_media_player_t *p_mi,
1007 libvlc_exception_t *p_e )
1009 input_thread_t *p_input_thread;
1011 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
1012 if( !p_input_thread )
1015 int i_type = var_Type( p_input_thread, "next-chapter" );
1016 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1017 "next-chapter":"next-title", true );
1019 vlc_object_release( p_input_thread );
1022 void libvlc_media_player_previous_chapter(
1023 libvlc_media_player_t *p_mi,
1024 libvlc_exception_t *p_e )
1026 input_thread_t *p_input_thread;
1028 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
1029 if( !p_input_thread )
1032 int i_type = var_Type( p_input_thread, "next-chapter" );
1033 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1034 "prev-chapter":"prev-title", true );
1036 vlc_object_release( p_input_thread );
1039 float libvlc_media_player_get_fps(
1040 libvlc_media_player_t *p_mi,
1041 libvlc_exception_t *p_e)
1043 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1046 if( p_input_thread )
1048 if( input_Control( p_input_thread, INPUT_GET_VIDEO_FPS, &f_fps ) )
1050 vlc_object_release( p_input_thread );
1055 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi,
1056 libvlc_exception_t *p_e)
1058 input_thread_t *p_input_thread =
1059 libvlc_get_input_thread ( p_mi, p_e);
1060 if ( !p_input_thread )
1063 if ( !p_input_thread->b_die && !p_input_thread->b_dead )
1065 vlc_object_release( p_input_thread );
1068 vlc_object_release( p_input_thread );
1072 void libvlc_media_player_set_rate(
1073 libvlc_media_player_t *p_mi,
1075 libvlc_exception_t *p_e )
1077 input_thread_t *p_input_thread;
1080 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1081 if( !p_input_thread )
1084 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1085 if( (rate < 0.0) && !b_can_rewind )
1087 vlc_object_release( p_input_thread );
1088 libvlc_exception_raise( p_e, "Rate value is invalid" );
1092 var_SetInteger( p_input_thread, "rate", 1000.0f/rate );
1093 vlc_object_release( p_input_thread );
1096 float libvlc_media_player_get_rate(
1097 libvlc_media_player_t *p_mi,
1098 libvlc_exception_t *p_e )
1100 input_thread_t *p_input_thread;
1104 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1105 if( !p_input_thread )
1106 return 0.0; /* rate < 0 indicates rewind */
1108 var_Get( p_input_thread, "rate", &val );
1109 b_can_rewind = var_GetBool( p_input_thread, "can-rewind" );
1110 if( (val.i_int < 0) && !b_can_rewind )
1112 libvlc_exception_raise( p_e, "invalid rate" );
1115 vlc_object_release( p_input_thread );
1117 return (float)1000.0f/val.i_int;
1120 libvlc_state_t libvlc_media_player_get_state(
1121 libvlc_media_player_t *p_mi,
1122 libvlc_exception_t *p_e )
1124 input_thread_t *p_input_thread;
1125 libvlc_state_t state = libvlc_Ended;
1128 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1129 if( !p_input_thread )
1131 /* We do return the right value, no need to throw an exception */
1132 if( libvlc_exception_raised( p_e ) )
1133 libvlc_exception_clear( p_e );
1137 var_Get( p_input_thread, "state", &val );
1138 state = vlc_to_libvlc_state(val.i_int);
1140 if( state == libvlc_Playing )
1143 caching = var_GetFloat( p_input_thread, "cache" );
1144 if( caching > 0.0 && caching < 1.0 )
1145 state = libvlc_Buffering;
1147 vlc_object_release( p_input_thread );
1151 int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi,
1152 libvlc_exception_t *p_e )
1154 input_thread_t *p_input_thread;
1157 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1158 if ( !p_input_thread )
1160 /* We do return the right value, no need to throw an exception */
1161 if( libvlc_exception_raised( p_e ) )
1162 libvlc_exception_clear( p_e );
1165 var_Get( p_input_thread, "can-seek", &val );
1166 vlc_object_release( p_input_thread );
1171 /* internal function, used by audio, video */
1172 libvlc_track_description_t *
1173 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1174 const char *psz_variable,
1175 libvlc_exception_t *p_e )
1177 input_thread_t *p_input = libvlc_get_input_thread( p_mi, p_e );
1178 libvlc_track_description_t *p_track_description = NULL,
1179 *p_actual, *p_previous;
1184 vlc_value_t val_list, text_list;
1185 var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list);
1188 if( val_list.p_list->i_count <= 0 )
1191 p_track_description = ( libvlc_track_description_t * )
1192 malloc( sizeof( libvlc_track_description_t ) );
1193 if ( !p_track_description )
1195 libvlc_exception_raise( p_e, "no enough memory" );
1198 p_actual = p_track_description;
1200 for( int i = 0; i < val_list.p_list->i_count; i++ )
1204 p_actual = ( libvlc_track_description_t * )
1205 malloc( sizeof( libvlc_track_description_t ) );
1208 libvlc_track_description_release( p_track_description );
1209 libvlc_exception_raise( p_e, "no enough memory" );
1213 p_actual->i_id = val_list.p_list->p_values[i].i_int;
1214 p_actual->psz_name = strdup( text_list.p_list->p_values[i].psz_string );
1215 p_actual->p_next = NULL;
1217 p_previous->p_next = p_actual;
1218 p_previous = p_actual;
1223 var_FreeList( &val_list, &text_list );
1224 vlc_object_release( p_input );
1226 return p_track_description;
1229 void libvlc_track_description_release( libvlc_track_description_t *p_td )
1231 libvlc_track_description_t *p_actual, *p_before;
1236 free( p_actual->psz_name );
1237 p_before = p_actual;
1238 p_actual = p_before->p_next;
1243 int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi,
1244 libvlc_exception_t *p_e )
1246 input_thread_t *p_input_thread;
1249 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
1250 if ( !p_input_thread )
1252 /* We do return the right value, no need to throw an exception */
1253 if( libvlc_exception_raised( p_e ) )
1254 libvlc_exception_clear( p_e );
1257 var_Get( p_input_thread, "can-pause", &val );
1258 vlc_object_release( p_input_thread );