1 /*****************************************************************************
2 * media_player.c: Libvlc API Media Instance management functions
3 *****************************************************************************
4 * Copyright (C) 2005-2009 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
30 #include <vlc/libvlc.h>
31 #include <vlc/libvlc_media.h>
32 #include <vlc/libvlc_events.h>
34 #include <vlc_demux.h>
35 #include <vlc_input.h>
40 #include "libvlc_internal.h"
41 #include "media_internal.h" // libvlc_media_set_state()
42 #include "media_player_internal.h"
45 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
46 vlc_value_t oldval, vlc_value_t newval,
49 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
50 vlc_value_t oldval, vlc_value_t newval,
53 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
54 vlc_value_t oldval, vlc_value_t newval,
58 snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd,
59 vlc_value_t oldval, vlc_value_t newval, void *p_data );
63 mouse_moved( vlc_object_t *p_this, char const *psz_cmd,
64 vlc_value_t oldval, vlc_value_t newval, void *p_data );
66 mouse_button( vlc_object_t *p_this, char const *psz_cmd,
67 vlc_value_t oldval, vlc_value_t newval, void *p_data );
69 mouse_clicked( vlc_object_t *p_this, char const *psz_cmd,
70 vlc_value_t oldval, vlc_value_t newval, void *p_data );
72 mouse_object( vlc_object_t *p_this, char const *psz_cmd,
73 vlc_value_t oldval, vlc_value_t newval, void *p_data );
76 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
82 #define register_event(a, b) __register_event(a, libvlc_MediaPlayer ## b)
83 static inline void __register_event(libvlc_media_player_t *mp, libvlc_event_type_t type)
85 libvlc_event_manager_register_event_type(mp->p_event_manager, type);
88 static inline void lock(libvlc_media_player_t *mp)
90 vlc_mutex_lock(&mp->object_lock);
93 static inline void unlock(libvlc_media_player_t *mp)
95 vlc_mutex_unlock(&mp->object_lock);
99 * Release the associated input thread.
101 * Object lock is NOT held.
103 static void release_input_thread( libvlc_media_player_t *p_mi, bool b_input_abort )
107 input_thread_t *p_input_thread = p_mi->p_input_thread;
108 if( !p_input_thread )
111 var_DelCallback( p_input_thread, "can-seek",
112 input_seekable_changed, p_mi );
113 var_DelCallback( p_input_thread, "can-pause",
114 input_pausable_changed, p_mi );
115 var_DelCallback( p_input_thread, "intf-event",
116 input_event_changed, p_mi );
118 /* We owned this one */
119 input_Stop( p_input_thread, b_input_abort );
121 vlc_thread_join( p_input_thread );
123 assert( p_mi->p_input_resource == NULL );
124 assert( p_input_thread->b_dead );
125 /* Store the input resource for future use. */
126 p_mi->p_input_resource = input_DetachResource( p_input_thread );
128 vlc_object_release( p_input_thread );
130 p_mi->p_input_thread = NULL;
134 * Retrieve the input thread. Be sure to release the object
135 * once you are done with it. (libvlc Internal)
137 * Function will lock the object.
139 input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi )
141 input_thread_t *p_input_thread;
146 p_input_thread = p_mi->p_input_thread;
148 vlc_object_hold( p_input_thread );
150 libvlc_printerr( "No active input" );
153 return p_input_thread;
157 * Get vout thread from current input
159 * Object lock is NOT held.
161 static vout_thread_t *get_vout_thread( libvlc_media_player_t *p_mi )
163 vout_thread_t *p_vout_thread;
165 p_vout_thread = input_GetVout( p_mi->p_input_thread );
168 var_AddCallback( p_vout_thread, "mouse-button-down", mouse_button, p_mi );
169 var_AddCallback( p_vout_thread, "mouse-moved", mouse_moved, p_mi );
170 var_AddCallback( p_vout_thread, "mouse-clicked", mouse_clicked, p_mi );
171 var_AddCallback( p_vout_thread, "mouse-object", mouse_object, p_mi );
174 return p_vout_thread;
178 * Release the associated vout thread.
180 * Object lock is NOT held.
182 static void release_vout_thread( libvlc_media_player_t *p_mi )
184 vout_thread_t *p_vout_thread;
186 if( !p_mi || !p_mi->p_vout_thread )
189 p_vout_thread = p_mi->p_vout_thread;
191 var_DelCallback( p_vout_thread, "mouse-button-down", mouse_button, p_mi );
192 var_DelCallback( p_vout_thread, "mouse-moved", mouse_moved, p_mi );
193 var_DelCallback( p_vout_thread, "mouse-clicked", mouse_clicked, p_mi );
194 var_DelCallback( p_vout_thread, "mouse-object", mouse_object, p_mi );
196 vlc_object_release( p_vout_thread );
197 p_mi->p_vout_thread = NULL;
201 * Set the internal state of the media_player. (media player Internal)
203 * Function will lock the media_player.
205 static void set_state( libvlc_media_player_t *p_mi, libvlc_state_t state,
212 libvlc_media_t *media = p_mi->p_md;
214 libvlc_media_retain(media);
221 // Also set the state of the corresponding media
222 // This is strictly for convenience.
223 libvlc_media_set_state(media, state);
225 libvlc_media_release(media);
230 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
231 vlc_value_t oldval, vlc_value_t newval,
237 libvlc_media_player_t * p_mi = p_userdata;
238 libvlc_event_t event;
240 event.type = libvlc_MediaPlayerSeekableChanged;
241 event.u.media_player_seekable_changed.new_seekable = newval.b_bool;
243 libvlc_event_send( p_mi->p_event_manager, &event );
248 input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
249 vlc_value_t oldval, vlc_value_t newval,
255 libvlc_media_player_t * p_mi = p_userdata;
256 libvlc_event_t event;
258 event.type = libvlc_MediaPlayerPausableChanged;
259 event.u.media_player_pausable_changed.new_pausable = newval.b_bool;
261 libvlc_event_send( p_mi->p_event_manager, &event );
266 input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
267 vlc_value_t oldval, vlc_value_t newval,
271 input_thread_t * p_input = (input_thread_t *)p_this;
272 libvlc_media_player_t * p_mi = p_userdata;
273 libvlc_event_t event;
275 assert( !strcmp( psz_cmd, "intf-event" ) );
277 if( newval.i_int == INPUT_EVENT_STATE )
279 libvlc_state_t libvlc_state;
281 switch ( var_GetInteger( p_input, "state" ) )
284 libvlc_state = libvlc_NothingSpecial;
285 event.type = libvlc_MediaPlayerNothingSpecial;
288 libvlc_state = libvlc_Opening;
289 event.type = libvlc_MediaPlayerOpening;
292 libvlc_state = libvlc_Playing;
293 event.type = libvlc_MediaPlayerPlaying;
296 libvlc_state = libvlc_Paused;
297 event.type = libvlc_MediaPlayerPaused;
300 libvlc_state = libvlc_Ended;
301 event.type = libvlc_MediaPlayerEndReached;
304 libvlc_state = libvlc_Error;
305 event.type = libvlc_MediaPlayerEncounteredError;
312 set_state( p_mi, libvlc_state, false );
313 libvlc_event_send( p_mi->p_event_manager, &event );
315 else if( newval.i_int == INPUT_EVENT_ABORT )
317 libvlc_state_t libvlc_state = libvlc_Stopped;
318 event.type = libvlc_MediaPlayerStopped;
320 set_state( p_mi, libvlc_state, false );
321 libvlc_event_send( p_mi->p_event_manager, &event );
323 else if( newval.i_int == INPUT_EVENT_POSITION )
325 if( var_GetInteger( p_input, "state" ) != PLAYING_S )
326 return VLC_SUCCESS; /* Don't send the position while stopped */
329 event.type = libvlc_MediaPlayerPositionChanged;
330 event.u.media_player_position_changed.new_position =
331 var_GetFloat( p_input, "position" );
332 libvlc_event_send( p_mi->p_event_manager, &event );
335 event.type = libvlc_MediaPlayerTimeChanged;
336 event.u.media_player_time_changed.new_time =
337 from_mtime(var_GetTime( p_input, "time" ));
338 libvlc_event_send( p_mi->p_event_manager, &event );
340 else if( newval.i_int == INPUT_EVENT_LENGTH )
342 event.type = libvlc_MediaPlayerLengthChanged;
343 event.u.media_player_length_changed.new_length =
344 from_mtime(var_GetTime( p_input, "length" ));
345 libvlc_event_send( p_mi->p_event_manager, &event );
347 else if( newval.i_int == INPUT_EVENT_VOUT )
350 /* release old vout */
351 if( p_mi->p_vout_thread )
352 release_vout_thread( p_mi );
353 /* remember new vout */
354 p_mi->p_vout_thread = get_vout_thread( p_mi );
362 /**************************************************************************
363 * Snapshot Taken Event.
365 * FIXME: This snapshot API interface makes no sense in media_player.
366 *************************************************************************/
367 static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd,
368 vlc_value_t oldval, vlc_value_t newval, void *p_data )
370 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);
372 libvlc_media_player_t *mp = p_data;
373 libvlc_event_t event;
374 event.type = libvlc_MediaPlayerSnapshotTaken;
375 event.u.media_player_snapshot_taken.psz_filename = newval.psz_string;
376 libvlc_event_send(mp->p_event_manager, &event);
381 /**************************************************************************
383 *************************************************************************/
386 mouse_moved( vlc_object_t *p_this, char const *psz_cmd,
387 vlc_value_t oldval, vlc_value_t newval, void *p_data )
389 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);
391 libvlc_media_player_t *mp = p_data;
392 libvlc_event_t event;
393 event.type = libvlc_MediaPlayerMouseMoved;
394 event.u.media_player_mouse_moved.x = newval.coords.x;
395 event.u.media_player_mouse_moved.y = newval.coords.y;
396 libvlc_event_send(mp->p_event_manager, &event);
402 mouse_button( vlc_object_t *p_this, char const *psz_cmd,
403 vlc_value_t oldval, vlc_value_t newval, void *p_data )
405 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);
407 libvlc_media_player_t *mp = p_data;
408 libvlc_event_t event;
409 int pressed = newval.i_int;
411 event.type = libvlc_MediaPlayerMouseButton;
412 event.u.media_player_mouse_button.mb_left = (pressed & (1<<MOUSE_BUTTON_LEFT));
413 event.u.media_player_mouse_button.mb_center = (pressed & (1<<MOUSE_BUTTON_CENTER));
414 event.u.media_player_mouse_button.mb_right = (pressed & (1<<MOUSE_BUTTON_RIGHT));
415 event.u.media_player_mouse_button.mb_wheel_up = (pressed & (1<<MOUSE_BUTTON_WHEEL_UP));
416 event.u.media_player_mouse_button.mb_wheel_down = (pressed & (1<<MOUSE_BUTTON_WHEEL_DOWN));
417 libvlc_event_send(mp->p_event_manager, &event);
423 mouse_clicked( vlc_object_t *p_this, char const *psz_cmd,
424 vlc_value_t oldval, vlc_value_t newval, void *p_data )
426 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);
428 libvlc_media_player_t *mp = p_data;
429 libvlc_event_t event;
430 event.type = libvlc_MediaPlayerMouseClick;
431 event.u.media_player_mouse_clicked.clicked = newval.b_bool ? 1 : 0;
432 libvlc_event_send(mp->p_event_manager, &event);
438 mouse_object( vlc_object_t *p_this, char const *psz_cmd,
439 vlc_value_t oldval, vlc_value_t newval, void *p_data )
441 VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_this);
443 libvlc_media_player_t *mp = p_data;
444 libvlc_event_t event;
445 event.type = libvlc_MediaPlayerMouseObject;
446 event.u.media_player_mouse_object.moved = (newval.b_bool ? 1 : 0);
447 libvlc_event_send(mp->p_event_manager, &event);
452 static input_thread_t *find_input (vlc_object_t *obj)
454 libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
455 input_thread_t *p_input;
458 p_input = mp->p_input_thread;
460 vlc_object_hold (p_input);
466 static void libvlc_media_player_destroy( libvlc_media_player_t * );
469 /**************************************************************************
470 * Create a Media Instance object.
473 * - All items created by _new start with a refcount set to 1.
474 * - Accessor _release decrease the refcount by 1, if after that
475 * operation the refcount is 0, the object is destroyed.
476 * - Accessor _retain increase the refcount by 1 (XXX: to implement)
478 * Object locking strategy:
479 * - No lock held while in constructor.
480 * - When accessing any member variable this lock is held. (XXX who locks?)
481 * - When attempting to destroy the object the lock is also held.
482 **************************************************************************/
483 libvlc_media_player_t *
484 libvlc_media_player_new( libvlc_instance_t *instance )
486 libvlc_media_player_t * mp;
490 mp = vlc_object_create (instance->p_libvlc_int, sizeof(*mp));
491 if (unlikely(mp == NULL))
493 libvlc_printerr("Not enough memory");
496 vlc_object_attach (mp, mp->p_libvlc);
499 var_Create (mp, "rate", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT);
502 var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
504 var_Create (mp, "drawable-hwnd", VLC_VAR_ADDRESS);
507 var_Create (mp, "drawable-agl", VLC_VAR_INTEGER);
508 var_Create (mp, "drawable-nsobject", VLC_VAR_ADDRESS);
511 var_Create (mp, "keyboard-events", VLC_VAR_BOOL);
512 var_SetBool (mp, "keyboard-events", true);
513 var_Create (mp, "mouse-events", VLC_VAR_BOOL);
514 var_SetBool (mp, "mouse-events", true);
516 var_Create (mp, "fullscreen", VLC_VAR_BOOL);
517 var_Create (mp, "autoscale", VLC_VAR_BOOL);
518 var_SetBool (mp, "autoscale", true);
519 var_Create (mp, "scale", VLC_VAR_FLOAT);
520 var_SetFloat (mp, "scale", 1.);
521 var_Create (mp, "aspect-ratio", VLC_VAR_STRING);
522 var_Create (mp, "crop", VLC_VAR_STRING);
523 var_Create (mp, "deinterlace", VLC_VAR_INTEGER);
524 var_Create (mp, "deinterlace-mode", VLC_VAR_STRING);
526 var_Create (mp, "vbi-page", VLC_VAR_INTEGER);
528 var_Create (mp, "marq-marquee", VLC_VAR_STRING);
529 var_Create (mp, "marq-color", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
530 var_Create (mp, "marq-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
531 var_Create (mp, "marq-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
532 var_Create (mp, "marq-refresh", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
533 var_Create (mp, "marq-size", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
534 var_Create (mp, "marq-timeout", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
535 var_Create (mp, "marq-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
536 var_Create (mp, "marq-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
538 var_Create (mp, "logo-file", VLC_VAR_STRING);
539 var_Create (mp, "logo-x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
540 var_Create (mp, "logo-y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
541 var_Create (mp, "logo-delay", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
542 var_Create (mp, "logo-repeat", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
543 var_Create (mp, "logo-opacity", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
544 var_Create (mp, "logo-position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
547 var_Create (mp, "aout", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
548 var_Create (mp, "volume-muted", VLC_VAR_BOOL);
549 var_Create (mp, "saved-volume", VLC_VAR_INTEGER);
550 var_Create (mp, "volume-change", VLC_VAR_VOID);
551 var_Create (mp, "find-input-callback", VLC_VAR_ADDRESS);
552 var_SetAddress (mp, "find-input-callback", find_input);
555 mp->state = libvlc_NothingSpecial;
556 mp->p_libvlc_instance = instance;
557 mp->p_input_thread = NULL;
558 mp->p_input_resource = NULL;
559 mp->p_vout_thread = NULL;
561 mp->p_event_manager = libvlc_event_manager_new(mp, instance);
562 if (unlikely(mp->p_event_manager == NULL))
564 vlc_object_release(mp);
567 vlc_mutex_init(&mp->object_lock);
569 register_event(mp, NothingSpecial);
570 register_event(mp, Opening);
571 register_event(mp, Buffering);
572 register_event(mp, Playing);
573 register_event(mp, Paused);
574 register_event(mp, Stopped);
575 register_event(mp, Forward);
576 register_event(mp, Backward);
577 register_event(mp, EndReached);
578 register_event(mp, EncounteredError);
579 register_event(mp, SeekableChanged);
581 register_event(mp, PositionChanged);
582 register_event(mp, TimeChanged);
583 register_event(mp, LengthChanged);
584 register_event(mp, TitleChanged);
585 register_event(mp, PausableChanged);
587 /* Snapshot initialization */
588 register_event(mp, SnapshotTaken);
590 register_event(mp, MediaChanged);
593 register_event(mp, MouseMoved);
594 register_event(mp, MouseButton);
595 register_event(mp, MouseClick);
596 register_event(mp, MouseObject);
598 /* Attach a var callback to the global object to provide the glue between
599 * vout_thread that generates the event and media_player that re-emits it
600 * with its own event manager
602 * FIXME: It's unclear why we want to put this in public API, and why we
603 * want to expose it in such a limiting and ugly way.
605 var_AddCallback(mp->p_libvlc, "snapshot-file", snapshot_was_taken, mp);
607 libvlc_retain(instance);
611 /**************************************************************************
612 * Create a Media Instance object with a media descriptor.
613 **************************************************************************/
614 libvlc_media_player_t *
615 libvlc_media_player_new_from_media( libvlc_media_t * p_md )
617 libvlc_media_player_t * p_mi;
619 p_mi = libvlc_media_player_new( p_md->p_libvlc_instance );
623 libvlc_media_retain( p_md );
629 /**************************************************************************
630 * Destroy a Media Instance object (libvlc internal)
632 * Warning: No lock held here, but hey, this is internal. Caller must lock.
633 **************************************************************************/
634 static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
638 /* Detach Callback from the main libvlc object */
639 var_DelCallback( p_mi->p_libvlc,
640 "snapshot-file", snapshot_was_taken, p_mi );
642 /* If the input thread hasn't been already deleted it means
643 * that the owners didn't stop the thread before releasing it. */
644 assert(!p_mi->p_input_thread);
646 /* Fallback for those who don't use NDEBUG */
647 if( p_mi->p_vout_thread )
648 release_vout_thread( p_mi );
650 if(p_mi->p_input_thread )
651 release_input_thread(p_mi, true);
653 if( p_mi->p_input_resource )
655 input_resource_Delete( p_mi->p_input_resource );
656 p_mi->p_input_resource = NULL;
659 libvlc_event_manager_release( p_mi->p_event_manager );
660 libvlc_media_release( p_mi->p_md );
661 vlc_mutex_destroy( &p_mi->object_lock );
663 libvlc_instance_t *instance = p_mi->p_libvlc_instance;
664 vlc_object_release( p_mi );
665 libvlc_release(instance);
668 /**************************************************************************
669 * Release a Media Instance object.
671 * Function does the locking.
672 **************************************************************************/
673 void libvlc_media_player_release( libvlc_media_player_t *p_mi )
679 destroy = !--p_mi->i_refcount;
683 libvlc_media_player_destroy( p_mi );
686 /**************************************************************************
687 * Retain a Media Instance object.
689 * Caller must hold the lock.
690 **************************************************************************/
691 void libvlc_media_player_retain( libvlc_media_player_t *p_mi )
700 /**************************************************************************
701 * Set the Media descriptor associated with the instance.
703 * Enter without lock -- function will lock the object.
704 **************************************************************************/
705 void libvlc_media_player_set_media(
706 libvlc_media_player_t *p_mi,
707 libvlc_media_t *p_md )
711 /* FIXME I am not sure if it is a user request or on die(eof/error)
713 release_input_thread( p_mi,
714 p_mi->p_input_thread &&
715 !p_mi->p_input_thread->b_eof &&
716 !p_mi->p_input_thread->b_error );
718 set_state( p_mi, libvlc_NothingSpecial, true );
720 libvlc_media_release( p_mi->p_md );
726 return; /* It is ok to pass a NULL md */
729 libvlc_media_retain( p_md );
732 /* The policy here is to ignore that we were created using a different
733 * libvlc_instance, because we don't really care */
734 p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
738 /* Send an event for the newly available media */
739 libvlc_event_t event;
740 event.type = libvlc_MediaPlayerMediaChanged;
741 event.u.media_player_media_changed.new_media = p_md;
742 libvlc_event_send( p_mi->p_event_manager, &event );
746 /**************************************************************************
747 * Get the Media descriptor associated with the instance.
748 **************************************************************************/
750 libvlc_media_player_get_media( libvlc_media_player_t *p_mi )
757 libvlc_media_retain( p_mi->p_md );
762 /**************************************************************************
763 * Get the event Manager.
764 **************************************************************************/
765 libvlc_event_manager_t *
766 libvlc_media_player_event_manager( libvlc_media_player_t *p_mi )
768 return p_mi->p_event_manager;
771 /**************************************************************************
772 * Tell media player to start playing.
773 **************************************************************************/
774 int libvlc_media_player_play( libvlc_media_player_t *p_mi )
776 input_thread_t * p_input_thread;
778 if( (p_input_thread = libvlc_get_input_thread( p_mi )) )
780 /* A thread already exists, send it a play message */
781 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
782 vlc_object_release( p_input_thread );
786 /* Ignore previous exception */
792 libvlc_printerr( "No associated media descriptor" );
796 p_mi->p_input_thread = input_Create( p_mi,
797 p_mi->p_md->p_input_item, NULL,
798 p_mi->p_input_resource );
799 if( !p_mi->p_input_thread )
802 libvlc_printerr( "Not enough memory" );
806 p_mi->p_input_resource = NULL;
807 p_input_thread = p_mi->p_input_thread;
809 var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
810 var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
811 var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
813 if( input_Start( p_input_thread ) )
815 vlc_object_release( p_input_thread );
816 p_mi->p_input_thread = NULL;
823 /**************************************************************************
825 **************************************************************************/
826 void libvlc_media_player_pause( libvlc_media_player_t *p_mi )
828 input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi );
829 if( !p_input_thread )
832 libvlc_state_t state = libvlc_media_player_get_state( p_mi );
833 if( state == libvlc_Playing || state == libvlc_Buffering )
835 if( libvlc_media_player_can_pause( p_mi ) )
836 input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S );
838 libvlc_media_player_stop( p_mi );
841 input_Control( p_input_thread, INPUT_SET_STATE, PLAYING_S );
843 vlc_object_release( p_input_thread );
846 /**************************************************************************
847 * Tells whether the media player is currently playing.
849 * Enter with lock held.
850 **************************************************************************/
851 int libvlc_media_player_is_playing( libvlc_media_player_t *p_mi )
853 libvlc_state_t state = libvlc_media_player_get_state( p_mi );
854 return (libvlc_Playing == state) || (libvlc_Buffering == state);
857 /**************************************************************************
859 **************************************************************************/
860 void libvlc_media_player_stop( libvlc_media_player_t *p_mi )
862 libvlc_state_t state = libvlc_media_player_get_state( p_mi );
865 release_input_thread( p_mi, true ); /* This will stop the input thread */
868 /* Force to go to stopped state, in case we were in Ended, or Error
870 if( state != libvlc_Stopped )
872 set_state( p_mi, libvlc_Stopped, false );
874 /* Construct and send the event */
875 libvlc_event_t event;
876 event.type = libvlc_MediaPlayerStopped;
877 libvlc_event_send( p_mi->p_event_manager, &event );
881 /**************************************************************************
883 **************************************************************************/
884 void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
887 assert (p_mi != NULL);
889 var_SetAddress (p_mi, "drawable-nsobject", drawable);
891 (void) p_mi; (void)drawable;
895 /**************************************************************************
897 **************************************************************************/
898 void * libvlc_media_player_get_nsobject( libvlc_media_player_t *p_mi )
900 assert (p_mi != NULL);
902 return var_GetAddress (p_mi, "drawable-nsobject");
908 /**************************************************************************
910 **************************************************************************/
911 void libvlc_media_player_set_agl( libvlc_media_player_t *p_mi,
915 var_SetInteger (p_mi, "drawable-agl", drawable);
917 (void) p_mi; (void)drawable;
921 /**************************************************************************
923 **************************************************************************/
924 uint32_t libvlc_media_player_get_agl( libvlc_media_player_t *p_mi )
926 assert (p_mi != NULL);
928 return var_GetInteger (p_mi, "drawable-agl");
934 /**************************************************************************
936 **************************************************************************/
937 void libvlc_media_player_set_xwindow( libvlc_media_player_t *p_mi,
940 assert (p_mi != NULL);
941 var_SetInteger (p_mi, "drawable-xid", drawable);
944 /**************************************************************************
946 **************************************************************************/
947 uint32_t libvlc_media_player_get_xwindow( libvlc_media_player_t *p_mi )
949 return var_GetInteger (p_mi, "drawable-xid");
952 /**************************************************************************
954 **************************************************************************/
955 void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
958 assert (p_mi != NULL);
960 var_SetAddress (p_mi, "drawable-hwnd", drawable);
962 (void) p_mi; (void) drawable;
966 /**************************************************************************
968 **************************************************************************/
969 void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi )
971 assert (p_mi != NULL);
973 return var_GetAddress (p_mi, "drawable-hwnd");
979 /**************************************************************************
980 * Getters for stream information
981 **************************************************************************/
982 libvlc_time_t libvlc_media_player_get_length(
983 libvlc_media_player_t *p_mi )
985 input_thread_t *p_input_thread;
986 libvlc_time_t i_time;
988 p_input_thread = libvlc_get_input_thread ( p_mi );
989 if( !p_input_thread )
992 i_time = from_mtime(var_GetTime( p_input_thread, "length" ));
993 vlc_object_release( p_input_thread );
998 libvlc_time_t libvlc_media_player_get_time( libvlc_media_player_t *p_mi )
1000 input_thread_t *p_input_thread;
1001 libvlc_time_t i_time;
1003 p_input_thread = libvlc_get_input_thread ( p_mi );
1004 if( !p_input_thread )
1007 i_time = from_mtime(var_GetTime( p_input_thread , "time" ));
1008 vlc_object_release( p_input_thread );
1012 void libvlc_media_player_set_time( libvlc_media_player_t *p_mi,
1013 libvlc_time_t i_time )
1015 input_thread_t *p_input_thread;
1017 p_input_thread = libvlc_get_input_thread ( p_mi );
1018 if( !p_input_thread )
1021 var_SetTime( p_input_thread, "time", to_mtime(i_time) );
1022 vlc_object_release( p_input_thread );
1025 void libvlc_media_player_set_position( libvlc_media_player_t *p_mi,
1028 input_thread_t *p_input_thread;
1030 p_input_thread = libvlc_get_input_thread ( p_mi );
1031 if( !p_input_thread )
1034 var_SetFloat( p_input_thread, "position", position );
1035 vlc_object_release( p_input_thread );
1038 float libvlc_media_player_get_position( libvlc_media_player_t *p_mi )
1040 input_thread_t *p_input_thread;
1043 p_input_thread = libvlc_get_input_thread ( p_mi );
1044 if( !p_input_thread )
1047 f_position = var_GetFloat( p_input_thread, "position" );
1048 vlc_object_release( p_input_thread );
1053 void libvlc_media_player_set_chapter( libvlc_media_player_t *p_mi,
1056 input_thread_t *p_input_thread;
1058 p_input_thread = libvlc_get_input_thread ( p_mi );
1059 if( !p_input_thread )
1062 var_SetInteger( p_input_thread, "chapter", chapter );
1063 vlc_object_release( p_input_thread );
1066 int libvlc_media_player_get_chapter( libvlc_media_player_t *p_mi )
1068 input_thread_t *p_input_thread;
1071 p_input_thread = libvlc_get_input_thread ( p_mi );
1072 if( !p_input_thread )
1075 i_chapter = var_GetInteger( p_input_thread, "chapter" );
1076 vlc_object_release( p_input_thread );
1081 int libvlc_media_player_get_chapter_count( libvlc_media_player_t *p_mi )
1083 input_thread_t *p_input_thread;
1086 p_input_thread = libvlc_get_input_thread ( p_mi );
1087 if( !p_input_thread )
1090 var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
1091 vlc_object_release( p_input_thread );
1096 int libvlc_media_player_get_chapter_count_for_title(
1097 libvlc_media_player_t *p_mi,
1100 input_thread_t *p_input_thread;
1103 p_input_thread = libvlc_get_input_thread ( p_mi );
1104 if( !p_input_thread )
1108 if( asprintf( &psz_name, "title %2i", i_title ) == -1 )
1110 vlc_object_release( p_input_thread );
1113 var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL );
1114 vlc_object_release( p_input_thread );
1120 void libvlc_media_player_set_title( libvlc_media_player_t *p_mi,
1123 input_thread_t *p_input_thread;
1125 p_input_thread = libvlc_get_input_thread ( p_mi );
1126 if( !p_input_thread )
1129 var_SetInteger( p_input_thread, "title", i_title );
1130 vlc_object_release( p_input_thread );
1133 libvlc_event_t event;
1134 event.type = libvlc_MediaPlayerTitleChanged;
1135 event.u.media_player_title_changed.new_title = i_title;
1136 libvlc_event_send( p_mi->p_event_manager, &event );
1139 int libvlc_media_player_get_title( libvlc_media_player_t *p_mi )
1141 input_thread_t *p_input_thread;
1144 p_input_thread = libvlc_get_input_thread ( p_mi );
1145 if( !p_input_thread )
1148 i_title = var_GetInteger( p_input_thread, "title" );
1149 vlc_object_release( p_input_thread );
1154 int libvlc_media_player_get_title_count( libvlc_media_player_t *p_mi )
1156 input_thread_t *p_input_thread;
1159 p_input_thread = libvlc_get_input_thread ( p_mi );
1160 if( !p_input_thread )
1163 var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
1164 vlc_object_release( p_input_thread );
1169 void libvlc_media_player_next_chapter( libvlc_media_player_t *p_mi )
1171 input_thread_t *p_input_thread;
1173 p_input_thread = libvlc_get_input_thread ( p_mi );
1174 if( !p_input_thread )
1177 int i_type = var_Type( p_input_thread, "next-chapter" );
1178 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1179 "next-chapter":"next-title", true );
1181 vlc_object_release( p_input_thread );
1184 void libvlc_media_player_previous_chapter( libvlc_media_player_t *p_mi )
1186 input_thread_t *p_input_thread;
1188 p_input_thread = libvlc_get_input_thread ( p_mi );
1189 if( !p_input_thread )
1192 int i_type = var_Type( p_input_thread, "next-chapter" );
1193 var_SetBool( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ?
1194 "prev-chapter":"prev-title", true );
1196 vlc_object_release( p_input_thread );
1199 float libvlc_media_player_get_fps( libvlc_media_player_t *p_mi )
1201 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
1204 if( p_input_thread )
1206 if( input_Control( p_input_thread, INPUT_GET_VIDEO_FPS, &f_fps ) )
1208 vlc_object_release( p_input_thread );
1213 int libvlc_media_player_will_play( libvlc_media_player_t *p_mi )
1216 input_thread_t *p_input_thread =
1217 libvlc_get_input_thread ( p_mi );
1218 if ( !p_input_thread )
1221 b_will_play = !p_input_thread->b_die && !p_input_thread->b_dead;
1222 vlc_object_release( p_input_thread );
1227 int libvlc_media_player_set_rate( libvlc_media_player_t *p_mi, float rate )
1231 libvlc_printerr ("Playing backward not supported");
1235 var_SetFloat (p_mi, "rate", rate);
1237 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
1238 if( !p_input_thread )
1240 var_SetFloat( p_input_thread, "rate", rate );
1241 vlc_object_release( p_input_thread );
1245 float libvlc_media_player_get_rate( libvlc_media_player_t *p_mi )
1247 return var_GetFloat (p_mi, "rate");
1250 libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi )
1253 libvlc_state_t state = p_mi->state;
1258 int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi )
1260 input_thread_t *p_input_thread;
1263 p_input_thread = libvlc_get_input_thread ( p_mi );
1264 if ( !p_input_thread )
1266 b_seekable = var_GetBool( p_input_thread, "can-seek" );
1267 vlc_object_release( p_input_thread );
1272 /* internal function, used by audio, video */
1273 libvlc_track_description_t *
1274 libvlc_get_track_description( libvlc_media_player_t *p_mi,
1275 const char *psz_variable )
1277 input_thread_t *p_input = libvlc_get_input_thread( p_mi );
1278 libvlc_track_description_t *p_track_description = NULL,
1279 *p_actual, *p_previous;
1284 vlc_value_t val_list, text_list;
1285 var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list);
1288 if( val_list.p_list->i_count <= 0 )
1291 p_track_description = ( libvlc_track_description_t * )
1292 malloc( sizeof( libvlc_track_description_t ) );
1293 if ( !p_track_description )
1295 libvlc_printerr( "Not enough memory" );
1298 p_actual = p_track_description;
1300 for( int i = 0; i < val_list.p_list->i_count; i++ )
1304 p_actual = ( libvlc_track_description_t * )
1305 malloc( sizeof( libvlc_track_description_t ) );
1308 libvlc_track_description_release( p_track_description );
1309 libvlc_printerr( "Not enough memory" );
1313 p_actual->i_id = val_list.p_list->p_values[i].i_int;
1314 p_actual->psz_name = strdup( text_list.p_list->p_values[i].psz_string );
1315 p_actual->p_next = NULL;
1317 p_previous->p_next = p_actual;
1318 p_previous = p_actual;
1323 var_FreeList( &val_list, &text_list );
1324 vlc_object_release( p_input );
1326 return p_track_description;
1329 void libvlc_track_description_release( libvlc_track_description_t *p_td )
1331 libvlc_track_description_t *p_actual, *p_before;
1336 free( p_actual->psz_name );
1337 p_before = p_actual;
1338 p_actual = p_before->p_next;
1343 int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi )
1345 input_thread_t *p_input_thread;
1348 p_input_thread = libvlc_get_input_thread ( p_mi );
1349 if ( !p_input_thread )
1351 b_can_pause = var_GetBool( p_input_thread, "can-pause" );
1352 vlc_object_release( p_input_thread );
1357 void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi )
1359 input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
1360 if( p_input_thread != NULL )
1362 var_TriggerCallback( p_input_thread, "frame-next" );
1363 vlc_object_release( p_input_thread );