From c0c35a50025df54cee95ddb00b325438b1f47e5e Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Mon, 13 May 2019 14:01:55 +0200 Subject: [PATCH] libvlc: player: use vlc_player Implement the old libvlc player API using the new vlc_player. Signed-off-by: Jean-Baptiste Kempf --- lib/audio.c | 95 ++- lib/media_player.c | 1622 +++++++++++++++++++------------------------ lib/media_player_internal.h | 21 +- lib/video.c | 266 +++---- 4 files changed, 839 insertions(+), 1165 deletions(-) diff --git a/lib/audio.c b/lib/audio.c index 751584d0f1..f5e4493138 100644 --- a/lib/audio.c +++ b/lib/audio.c @@ -50,7 +50,7 @@ static audio_output_t *GetAOut( libvlc_media_player_t *mp ) { assert( mp != NULL ); - audio_output_t *p_aout = input_resource_HoldAout( mp->input.p_resource ); + audio_output_t *p_aout = vlc_player_aout_Hold(mp->player); if( p_aout == NULL ) libvlc_printerr( "No active audio output" ); return p_aout; @@ -131,14 +131,6 @@ int libvlc_audio_output_set( libvlc_media_player_t *mp, const char *psz_name ) var_SetString( mp, "aout", value ); free( value ); - /* Forget the existing audio output */ - input_resource_ResetAout(mp->input.p_resource); - - /* Create a new audio output */ - audio_output_t *aout = input_resource_GetAout(mp->input.p_resource); - if( aout != NULL ) - input_resource_PutAout(mp->input.p_resource, aout); - return 0; } @@ -340,16 +332,13 @@ int libvlc_audio_set_volume( libvlc_media_player_t *mp, int volume ) *****************************************************************************/ int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - int i_track_count; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( !p_input_thread ) - return -1; + int ret = vlc_player_GetTrackCount(p_mi->player, AUDIO_ES); - i_track_count = var_CountChoices( p_input_thread, "audio-es" ); - - input_Release(p_input_thread); - return i_track_count; + vlc_player_Unlock(player); + return ret; } /***************************************************************************** @@ -358,7 +347,7 @@ int libvlc_audio_get_track_count( libvlc_media_player_t *p_mi ) libvlc_track_description_t * libvlc_audio_get_track_description( libvlc_media_player_t *p_mi ) { - return libvlc_get_track_description( p_mi, "audio-es" ); + return libvlc_get_track_description( p_mi, AUDIO_ES ); } /***************************************************************************** @@ -366,12 +355,14 @@ libvlc_track_description_t * *****************************************************************************/ int libvlc_audio_get_track( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - int id = var_GetInteger( p_input_thread, "audio-es" ); - input_Release(p_input_thread); + const struct vlc_player_track *track = + vlc_player_GetSelectedTrack(player, AUDIO_ES); + int id = track ? vlc_es_id_GetInputId(track->es_id) : -1; + + vlc_player_Unlock(player); return id; } @@ -380,30 +371,27 @@ int libvlc_audio_get_track( libvlc_media_player_t *p_mi ) *****************************************************************************/ int libvlc_audio_set_track( libvlc_media_player_t *p_mi, int i_track ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - vlc_value_t *val_list; - size_t count; int i_ret = -1; - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - var_Change( p_input_thread, "audio-es", VLC_VAR_GETCHOICES, - &count, &val_list, (char ***)NULL ); + size_t count = vlc_player_GetAudioTrackCount(player); for( size_t i = 0; i < count; i++ ) { - if( i_track == val_list[i].i_int ) + const struct vlc_player_track *track = + vlc_player_GetAudioTrackAt(player, i); + if (i_track == vlc_es_id_GetInputId(track->es_id)) { - if( var_SetInteger( p_input_thread, "audio-es", i_track ) < 0 ) - break; + /* found */ + vlc_player_SelectTrack(player, track->es_id); i_ret = 0; goto end; } } libvlc_printerr( "Track identifier not found" ); end: - free( val_list ); - input_Release(p_input_thread); + vlc_player_Unlock(player); return i_ret; } @@ -446,14 +434,14 @@ int libvlc_audio_set_channel( libvlc_media_player_t *mp, int channel ) *****************************************************************************/ int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi ); - int64_t val = 0; - if( p_input_thread != NULL ) - { - val = US_FROM_VLC_TICK( var_GetInteger( p_input_thread, "audio-delay" ) ); - input_Release(p_input_thread); - } - return val; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + vlc_tick_t delay = vlc_player_GetAudioDelay(player); + + vlc_player_Unlock(player); + + return US_FROM_VLC_TICK(delay); } /***************************************************************************** @@ -461,18 +449,15 @@ int64_t libvlc_audio_get_delay( libvlc_media_player_t *p_mi ) *****************************************************************************/ int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_delay ) { - input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi ); - int ret = 0; - if( p_input_thread != NULL ) - { - var_SetInteger( p_input_thread, "audio-delay", VLC_TICK_FROM_US( i_delay ) ); - input_Release(p_input_thread); - } - else - { - ret = -1; - } - return ret; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + vlc_player_SetAudioDelay(player, VLC_TICK_FROM_US(i_delay), + VLC_PLAYER_WHENCE_ABSOLUTE); + + vlc_player_Unlock(player); + /* may not fail anymore, keep int not to break the API */ + return 0; } /***************************************************************************** diff --git a/lib/media_player.c b/lib/media_player.c index ca65556cc3..057add2afe 100644 --- a/lib/media_player.c +++ b/lib/media_player.c @@ -47,470 +47,451 @@ #define ES_INIT (-2) /* -1 is reserved for ES deselect */ static int -input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd, - vlc_value_t oldval, vlc_value_t newval, - void * p_userdata ); -static int -input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd, - vlc_value_t oldval, vlc_value_t newval, - void * p_userdata ); -static int -input_scrambled_changed( vlc_object_t * p_this, char const * psz_cmd, - vlc_value_t oldval, vlc_value_t newval, - void * p_userdata ); -static int -input_event_changed( vlc_object_t * p_this, char const * psz_cmd, - vlc_value_t oldval, vlc_value_t newval, - void * p_userdata ); - -static int -input_es_changed( vlc_object_t * p_this, char const * psz_cmd, - int action, vlc_value_t *p_val, - void *p_userdata); +snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd, + vlc_value_t oldval, vlc_value_t newval, void *p_data ); -static int -corks_changed(vlc_object_t *obj, const char *name, vlc_value_t old, - vlc_value_t cur, void *opaque); +static void media_attach_preparsed_event(libvlc_media_t *); +static void media_detach_preparsed_event(libvlc_media_t *); -static int -mute_changed(vlc_object_t *obj, const char *name, vlc_value_t old, - vlc_value_t cur, void *opaque); +static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi ); -static int -volume_changed(vlc_object_t *obj, const char *name, vlc_value_t old, - vlc_value_t cur, void *opaque); +// player callbacks static void -add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi ); +on_current_media_changed(vlc_player_t *player, input_item_t *new_media, + void *data) +{ + (void) player; -static void -del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi ); + libvlc_media_player_t *mp = data; -static int -snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd, - vlc_value_t oldval, vlc_value_t newval, void *p_data ); + libvlc_media_t *md = mp->p_md; -static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi ); + input_item_t *media = md ? md->p_input_item : NULL; + if (new_media == media) + /* no changes */ + return; -/* - * Shortcuts - */ + if (md) + media_detach_preparsed_event(md); -/* - * The input lock protects the input and input resource pointer. - * It MUST NOT be used from callbacks. - * - * The object lock protects the reset, namely the media and the player state. - * It can, and usually needs to be taken from callbacks. - * The object lock can be acquired under the input lock... and consequently - * the opposite order is STRICTLY PROHIBITED. - */ -static inline void lock(libvlc_media_player_t *mp) -{ - vlc_mutex_lock(&mp->object_lock); + if (new_media) + { + mp->p_md = libvlc_media_new_from_input_item(mp->p_libvlc_instance, + new_media); + if (!mp->p_md) + /* error already printed by the function call */ + return; + + media_attach_preparsed_event(mp->p_md); + } + else + mp->p_md = NULL; + + libvlc_media_release(md); + + libvlc_event_t event; + event.type = libvlc_MediaPlayerMediaChanged; + event.u.media_player_media_changed.new_media = mp->p_md; + libvlc_event_send(&mp->event_manager, &event); } -static inline void unlock(libvlc_media_player_t *mp) +static void +on_state_changed(vlc_player_t *player, enum vlc_player_state new_state, + void *data) { - vlc_mutex_unlock(&mp->object_lock); + (void) player; + + libvlc_media_player_t *mp = data; + + libvlc_event_t event; + switch (new_state) { + case VLC_PLAYER_STATE_STOPPED: + event.type = libvlc_MediaPlayerStopped; + break; + case VLC_PLAYER_STATE_STOPPING: + event.type = libvlc_MediaPlayerEndReached; + break; + case VLC_PLAYER_STATE_STARTED: + event.type = libvlc_MediaPlayerOpening; + break; + case VLC_PLAYER_STATE_PLAYING: + event.type = libvlc_MediaPlayerPlaying; + break; + case VLC_PLAYER_STATE_PAUSED: + event.type = libvlc_MediaPlayerPaused; + break; + default: + vlc_assert_unreachable(); + } + + libvlc_event_send(&mp->event_manager, &event); } -static inline void lock_input(libvlc_media_player_t *mp) +static void +on_error_changed(vlc_player_t *player, enum vlc_player_error error, void *data) { - vlc_mutex_lock(&mp->input.lock); + (void) player; + + libvlc_media_player_t *mp = data; + + libvlc_event_t event; + switch (error) { + case VLC_PLAYER_ERROR_NONE: + event.type = libvlc_MediaPlayerNothingSpecial; + break; + case VLC_PLAYER_ERROR_GENERIC: + event.type = libvlc_MediaPlayerEncounteredError; + break; + default: + vlc_assert_unreachable(); + } + + libvlc_event_send(&mp->event_manager, &event); } -static inline void unlock_input(libvlc_media_player_t *mp) +static void +on_buffering_changed(vlc_player_t *player, float new_buffering, void *data) { - vlc_mutex_unlock(&mp->input.lock); + (void) player; + + libvlc_media_player_t *mp = data; + + libvlc_event_t event; + event.type = libvlc_MediaPlayerBuffering; + event.u.media_player_buffering.new_cache = 100 * new_buffering; + + libvlc_event_send(&mp->event_manager, &event); } -static void input_item_preparsed_changed( const vlc_event_t *p_event, - void * user_data ) +static void +on_capabilities_changed(vlc_player_t *player, int old_caps, int new_caps, void *data) { - libvlc_media_t *p_md = user_data; - if( p_event->u.input_item_preparsed_changed.new_status & ITEM_PREPARSED ) + (void) player; + + libvlc_media_player_t *mp = data; + + libvlc_event_t event; + + bool old_seekable = old_caps & VLC_INPUT_CAPABILITIES_SEEKABLE; + bool new_seekable = new_caps & VLC_INPUT_CAPABILITIES_SEEKABLE; + if (new_seekable != old_seekable) { - /* Send the event */ - libvlc_event_t event; - event.type = libvlc_MediaParsedChanged; - event.u.media_parsed_changed.new_status = libvlc_media_parsed_status_done; - libvlc_event_send( &p_md->event_manager, &event ); + event.type = libvlc_MediaPlayerSeekableChanged; + event.u.media_player_seekable_changed.new_seekable = new_seekable; + libvlc_event_send(&mp->event_manager, &event); } -} -static void media_attach_preparsed_event( libvlc_media_t *p_md ) -{ - vlc_event_attach( &p_md->p_input_item->event_manager, - vlc_InputItemPreparsedChanged, - input_item_preparsed_changed, p_md ); + bool old_pauseable = old_caps & VLC_INPUT_CAPABILITIES_PAUSEABLE; + bool new_pauseable = new_caps & VLC_INPUT_CAPABILITIES_PAUSEABLE; + if (new_pauseable != old_pauseable) + { + event.type = libvlc_MediaPlayerPausableChanged; + event.u.media_player_pausable_changed.new_pausable = new_pauseable; + libvlc_event_send(&mp->event_manager, &event); + } } -static void media_detach_preparsed_event( libvlc_media_t *p_md ) +static void +on_position_changed(vlc_player_t *player, vlc_tick_t new_time, float new_pos, + void *data) { - vlc_event_detach( &p_md->p_input_item->event_manager, - vlc_InputItemPreparsedChanged, - input_item_preparsed_changed, - p_md ); + (void) player; + + libvlc_media_player_t *mp = data; + + libvlc_event_t event; + + event.type = libvlc_MediaPlayerPositionChanged; + event.u.media_player_position_changed.new_position = new_pos; + libvlc_event_send(&mp->event_manager, &event); + + event.type = libvlc_MediaPlayerTimeChanged; + event.u.media_player_time_changed.new_time = MS_FROM_VLC_TICK(new_time); + libvlc_event_send(&mp->event_manager, &event); } -/* - * Release the associated input thread. - * - * Object lock is NOT held. - * Input lock is held or instance is being destroyed. - */ -static void release_input_thread( libvlc_media_player_t *p_mi ) +static void +on_length_changed(vlc_player_t *player, vlc_tick_t new_length, void *data) { - assert( p_mi ); + (void) player; - input_thread_t *p_input_thread = p_mi->input.p_thread; - if( !p_input_thread ) - return; - p_mi->input.p_thread = NULL; + libvlc_media_player_t *mp = data; - media_detach_preparsed_event( p_mi->p_md ); + libvlc_event_t event; - var_DelCallback( p_input_thread, "can-seek", - input_seekable_changed, p_mi ); - var_DelCallback( p_input_thread, "can-pause", - input_pausable_changed, p_mi ); - var_DelCallback( p_input_thread, "program-scrambled", - input_scrambled_changed, p_mi ); - var_DelCallback( p_input_thread, "intf-event", - input_event_changed, p_mi ); - del_es_callbacks( p_input_thread, p_mi ); + event.type = libvlc_MediaPlayerLengthChanged; + event.u.media_player_length_changed.new_length = + MS_FROM_VLC_TICK(new_length); - /* We owned this one */ - input_Stop( p_input_thread ); - input_Close( p_input_thread ); + libvlc_event_send(&mp->event_manager, &event); } -/* - * Retrieve the input thread. Be sure to release the object - * once you are done with it. (libvlc Internal) - */ -input_thread_t *libvlc_get_input_thread( libvlc_media_player_t *p_mi ) +static int +track_type_from_cat(enum es_format_category_e cat) { - input_thread_t *p_input_thread; + switch (cat) + { + case VIDEO_ES: + return libvlc_track_video; + case AUDIO_ES: + return libvlc_track_audio; + case SPU_ES: + return libvlc_track_text; + default: + return libvlc_track_unknown; + } +} - assert( p_mi ); +static void +on_track_list_changed(vlc_player_t *player, enum vlc_player_list_action action, + const struct vlc_player_track *track, void *data) +{ + (void) player; + + libvlc_media_player_t *mp = data; - lock_input(p_mi); - p_input_thread = p_mi->input.p_thread; - if( p_input_thread ) - input_Hold(p_input_thread); + libvlc_event_t event; + if (action == VLC_PLAYER_LIST_ADDED) + event.type = libvlc_MediaPlayerESAdded; + else if (action == VLC_PLAYER_LIST_REMOVED) + event.type = libvlc_MediaPlayerESDeleted; else - libvlc_printerr( "No active input" ); - unlock_input(p_mi); + /* no event to forward */ + return; - return p_input_thread; + event.u.media_player_es_changed.i_type = + track_type_from_cat(track->fmt.i_cat); + event.u.media_player_es_changed.i_id = vlc_es_id_GetInputId(track->es_id); + + libvlc_event_send(&mp->event_manager, &event); } -/* - * Set the internal state of the media_player. (media player Internal) - * - * Function will lock the media_player. - */ -static void set_state( libvlc_media_player_t *p_mi, libvlc_state_t state, - bool b_locked ) +static void +on_track_selection_changed(vlc_player_t *player, vlc_es_id_t *unselected_id, + vlc_es_id_t *selected_id, void *data) { - if(!b_locked) - lock(p_mi); - p_mi->state = state; + (void) player; + (void) unselected_id; - libvlc_media_t *media = p_mi->p_md; - if (media) - libvlc_media_retain(media); + libvlc_media_player_t *mp = data; - if(!b_locked) - unlock(p_mi); + libvlc_event_t event; + event.type = libvlc_MediaPlayerESSelected; - if (media) + if (selected_id) { - // Also set the state of the corresponding media - // This is strictly for convenience. - libvlc_media_set_state(media, state); - - libvlc_media_release(media); + enum es_format_category_e cat = vlc_es_id_GetCat(selected_id); + event.u.media_player_es_changed.i_type = track_type_from_cat(cat); + event.u.media_player_es_changed.i_id = + vlc_es_id_GetInputId(selected_id); + libvlc_event_send(&mp->event_manager, &event); } } -static int -input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd, - vlc_value_t oldval, vlc_value_t newval, - void * p_userdata ) -{ - VLC_UNUSED(oldval); - VLC_UNUSED(p_this); - VLC_UNUSED(psz_cmd); - libvlc_media_player_t * p_mi = p_userdata; - libvlc_event_t event; +static void +on_program_list_changed(vlc_player_t *player, + enum vlc_player_list_action action, + const struct vlc_player_program *prgm, void* data) +{ + (void) action; + (void) prgm; - event.type = libvlc_MediaPlayerSeekableChanged; - event.u.media_player_seekable_changed.new_seekable = newval.b_bool; + libvlc_media_player_t *mp = data; - libvlc_event_send( &p_mi->event_manager, &event ); - return VLC_SUCCESS; -} + const struct vlc_player_program *selected = + vlc_player_GetSelectedProgram(player); + if (!selected) + return; -static int -input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd, - vlc_value_t oldval, vlc_value_t newval, - void * p_userdata ) -{ - VLC_UNUSED(oldval); - VLC_UNUSED(p_this); - VLC_UNUSED(psz_cmd); - libvlc_media_player_t * p_mi = p_userdata; libvlc_event_t event; + event.type = libvlc_MediaPlayerScrambledChanged; + event.u.media_player_scrambled_changed.new_scrambled = selected->scrambled; - event.type = libvlc_MediaPlayerPausableChanged; - event.u.media_player_pausable_changed.new_pausable = newval.b_bool; - - libvlc_event_send( &p_mi->event_manager, &event ); - return VLC_SUCCESS; + libvlc_event_send(&mp->event_manager, &event); } -static int -input_scrambled_changed( vlc_object_t * p_this, char const * psz_cmd, - vlc_value_t oldval, vlc_value_t newval, - void * p_userdata ) -{ - VLC_UNUSED(oldval); - VLC_UNUSED(p_this); - VLC_UNUSED(psz_cmd); - libvlc_media_player_t * p_mi = p_userdata; - libvlc_event_t event; +static void +on_program_selection_changed(vlc_player_t *player, int unselected_id, + int selected_id, void *data) +{ + (void) unselected_id; + libvlc_media_player_t *mp = data; + + if (selected_id == -1) + return; + + const struct vlc_player_program *program = + vlc_player_GetSelectedProgram(player); + assert(program); + + libvlc_event_t event; event.type = libvlc_MediaPlayerScrambledChanged; - event.u.media_player_scrambled_changed.new_scrambled = newval.b_bool; + event.u.media_player_scrambled_changed.new_scrambled = program->scrambled; - libvlc_event_send( &p_mi->event_manager, &event ); - return VLC_SUCCESS; + libvlc_event_send(&mp->event_manager, &event); } -static int -input_event_changed( vlc_object_t * p_this, char const * psz_cmd, - vlc_value_t oldval, vlc_value_t newval, - void * p_userdata ) +static void +on_title_selection_changed(vlc_player_t *player, + const struct vlc_player_title *new_title, + size_t new_idx, void *data) { - VLC_UNUSED(oldval); VLC_UNUSED(psz_cmd); - input_thread_t * p_input = (input_thread_t *)p_this; - libvlc_media_player_t * p_mi = p_userdata; + (void) player; + (void) new_title; + + libvlc_media_player_t *mp = data; + libvlc_event_t event; + event.type = libvlc_MediaPlayerTitleChanged; + event.u.media_player_title_changed.new_title = new_idx; - assert( !strcmp( psz_cmd, "intf-event" ) ); + libvlc_event_send(&mp->event_manager, &event); +} - if( newval.i_int == INPUT_EVENT_STATE ) - { - libvlc_state_t libvlc_state; +static void +on_chapter_selection_changed(vlc_player_t *player, + const struct vlc_player_title *title, + size_t title_idx, + const struct vlc_player_chapter *new_chapter, + size_t new_chapter_idx, + void *data) +{ + (void) player; + (void) title; + (void) title_idx; + (void) new_chapter; - switch ( var_GetInteger( p_input, "state" ) ) - { - case INIT_S: - libvlc_state = libvlc_NothingSpecial; - event.type = libvlc_MediaPlayerNothingSpecial; - break; - case OPENING_S: - libvlc_state = libvlc_Opening; - event.type = libvlc_MediaPlayerOpening; - break; - case PLAYING_S: - libvlc_state = libvlc_Playing; - event.type = libvlc_MediaPlayerPlaying; - break; - case PAUSE_S: - libvlc_state = libvlc_Paused; - event.type = libvlc_MediaPlayerPaused; - break; - case END_S: - libvlc_state = libvlc_Ended; - event.type = libvlc_MediaPlayerEndReached; - break; - case ERROR_S: - libvlc_state = libvlc_Error; - event.type = libvlc_MediaPlayerEncounteredError; - break; - - default: - return VLC_SUCCESS; - } + libvlc_media_player_t *mp = data; - set_state( p_mi, libvlc_state, false ); - libvlc_event_send( &p_mi->event_manager, &event ); - } - else if( newval.i_int == INPUT_EVENT_DEAD ) - { - libvlc_state_t libvlc_state = libvlc_Ended; - event.type = libvlc_MediaPlayerEndReached; + libvlc_event_t event; + event.type = libvlc_MediaPlayerChapterChanged; + event.u.media_player_chapter_changed.new_chapter = new_chapter_idx; - set_state( p_mi, libvlc_state, false ); - libvlc_event_send( &p_mi->event_manager, &event ); - } - else if( newval.i_int == INPUT_EVENT_POSITION ) - { - if( var_GetInteger( p_input, "state" ) != PLAYING_S ) - return VLC_SUCCESS; /* Don't send the position while stopped */ - - /* */ - event.type = libvlc_MediaPlayerPositionChanged; - event.u.media_player_position_changed.new_position = - var_GetFloat( p_input, "position" ); - libvlc_event_send( &p_mi->event_manager, &event ); - - /* */ - event.type = libvlc_MediaPlayerTimeChanged; - event.u.media_player_time_changed.new_time = - from_mtime(var_GetInteger( p_input, "time" )); - libvlc_event_send( &p_mi->event_manager, &event ); - } - else if( newval.i_int == INPUT_EVENT_LENGTH ) - { - event.type = libvlc_MediaPlayerLengthChanged; - event.u.media_player_length_changed.new_length = - from_mtime(var_GetInteger( p_input, "length" )); - libvlc_event_send( &p_mi->event_manager, &event ); - } - else if( newval.i_int == INPUT_EVENT_CACHE ) - { - event.type = libvlc_MediaPlayerBuffering; - event.u.media_player_buffering.new_cache = (100 * - var_GetFloat( p_input, "cache" )); - libvlc_event_send( &p_mi->event_manager, &event ); - } - else if( newval.i_int == INPUT_EVENT_VOUT ) - { - vout_thread_t **pp_vout; - size_t i_vout; - if( input_Control( p_input, INPUT_GET_VOUTS, &pp_vout, &i_vout ) ) - { - i_vout = 0; - } - else - { - for( size_t i = 0; i < i_vout; i++ ) - vout_Release(pp_vout[i]); - free( pp_vout ); - } + libvlc_event_send(&mp->event_manager, &event); +} - event.type = libvlc_MediaPlayerVout; - event.u.media_player_vout.new_count = i_vout; - libvlc_event_send( &p_mi->event_manager, &event ); - } - else if ( newval.i_int == INPUT_EVENT_TITLE ) - { - event.type = libvlc_MediaPlayerTitleChanged; - event.u.media_player_title_changed.new_title = var_GetInteger( p_input, "title" ); - libvlc_event_send( &p_mi->event_manager, &event ); - } - else if ( newval.i_int == INPUT_EVENT_CHAPTER ) - { - event.type = libvlc_MediaPlayerChapterChanged; - event.u.media_player_chapter_changed.new_chapter = var_GetInteger( p_input, "chapter" ); - libvlc_event_send( &p_mi->event_manager, &event ); - } - else if ( newval.i_int == INPUT_EVENT_ES ) - { - /* Send ESSelected events from this callback ("intf-event") and not - * from "audio-es", "video-es", "spu-es" callbacks. Indeed, these - * callbacks are not triggered when the input_thread changes an ES - * while this callback is. */ - struct { - const char *psz_name; - const libvlc_track_type_t type; - int new_es; - } es_list[] = { - { "audio-es", libvlc_track_audio, ES_INIT }, - { "video-es", libvlc_track_video, ES_INIT }, - { "spu-es", libvlc_track_text, ES_INIT }, - }; - /* Check if an ES selection changed */ - lock( p_mi ); - for( size_t i = 0; i < ARRAY_SIZE( es_list ); ++i ) - { - int current_es = var_GetInteger( p_input, es_list[i].psz_name ); - if( current_es != p_mi->selected_es[i] ) - es_list[i].new_es = p_mi->selected_es[i] = current_es; - } - unlock( p_mi ); +static void +on_media_subitems_changed(vlc_player_t *player, input_item_t *media, + input_item_node_t *new_subitems, void *data) +{ + (void) player; - /* Send the ESSelected event for each ES that were newly selected */ - for( size_t i = 0; i < ARRAY_SIZE( es_list ); ++i ) - { - if( es_list[i].new_es != ES_INIT ) - { - event.type = libvlc_MediaPlayerESSelected; - event.u.media_player_es_changed.i_type = es_list[i].type; - event.u.media_player_es_changed.i_id = es_list[i].new_es; - libvlc_event_send( &p_mi->event_manager, &event ); - } - } - } + libvlc_media_player_t *mp = data; - return VLC_SUCCESS; + input_item_t *current = mp->p_md ? mp->p_md->p_input_item : NULL; + if (media == current) + libvlc_media_add_subtree(mp->p_md, new_subitems); } -static int track_type_from_name(const char *psz_name) +static void +on_cork_changed(vlc_player_t *player, unsigned cork_count, void *data) { - if( !strcmp( psz_name, "video-es" ) ) - return libvlc_track_video; - else if( !strcmp( psz_name, "audio-es" ) ) - return libvlc_track_audio; - else if( !strcmp( psz_name, "spu-es" ) ) - return libvlc_track_text; - else - return libvlc_track_unknown; + (void) player; + + libvlc_media_player_t *mp = data; + + libvlc_event_t event; + event.type = cork_count ? libvlc_MediaPlayerCorked + : libvlc_MediaPlayerUncorked; + + libvlc_event_send(&mp->event_manager, &event); } -static int input_es_changed( vlc_object_t *p_this, - char const *psz_cmd, - int action, - vlc_value_t *p_val, - void *p_userdata ) +static void +on_vout_changed(vlc_player_t *player, enum vlc_player_vout_action action, + vout_thread_t *vout, void *data) { - VLC_UNUSED(p_this); - libvlc_media_player_t *mp = p_userdata; + (void) action; + (void) vout; + + libvlc_media_player_t *mp = data; + + size_t count; + vout_thread_t **vouts = vlc_player_vout_HoldAll(player, &count); + if (!vouts) + return; + for (size_t i = 0; i < count; ++i) + vout_Release(vouts[i]); + free(vouts); + libvlc_event_t event; + event.type = libvlc_MediaPlayerVout; + event.u.media_player_vout.new_count = count; - /* Ignore the "Disable" element */ - if (p_val && p_val->i_int < 0) - return VLC_EGENERIC; + libvlc_event_send(&mp->event_manager, &event); +} - switch (action) - { - case VLC_VAR_ADDCHOICE: - event.type = libvlc_MediaPlayerESAdded; - break; - case VLC_VAR_DELCHOICE: - case VLC_VAR_CLEARCHOICES: - event.type = libvlc_MediaPlayerESDeleted; - break; - default: - return VLC_EGENERIC; - } +// player aout callbacks - event.u.media_player_es_changed.i_type = track_type_from_name(psz_cmd); +static void +on_volume_changed(vlc_player_t *player, float new_volume, void *data) +{ + (void) player; - int i_id; - if (action != VLC_VAR_CLEARCHOICES) - { - if (!p_val) - return VLC_EGENERIC; - i_id = p_val->i_int; - } - else - { - /* -1 means all ES tracks of this type were deleted. */ - i_id = -1; - } - event.u.media_player_es_changed.i_id = i_id; + libvlc_media_player_t *mp = data; + + libvlc_event_t event; + event.type = libvlc_MediaPlayerAudioVolume; + event.u.media_player_audio_volume.volume = new_volume; libvlc_event_send(&mp->event_manager, &event); +} - return VLC_SUCCESS; +static void +on_mute_changed(vlc_player_t *player, bool new_muted, void *data) +{ + (void) player; + + libvlc_media_player_t *mp = data; + + libvlc_event_t event; + event.type = new_muted ? libvlc_MediaPlayerMuted + : libvlc_MediaPlayerUnmuted; + + libvlc_event_send(&mp->event_manager, &event); +} + +static void +on_audio_device_changed(vlc_player_t *player, const char *device, void *data) +{ + (void) player; + + libvlc_media_player_t *mp = data; + + libvlc_event_t event; + event.type = libvlc_MediaPlayerAudioDevice; + event.u.media_player_audio_device.device = device; + + libvlc_event_send(&mp->event_manager, &event); } +static const struct vlc_player_cbs vlc_player_cbs = { + .on_current_media_changed = on_current_media_changed, + .on_state_changed = on_state_changed, + .on_error_changed = on_error_changed, + .on_buffering_changed = on_buffering_changed, + .on_capabilities_changed = on_capabilities_changed, + .on_position_changed = on_position_changed, + .on_length_changed = on_length_changed, + .on_track_list_changed = on_track_list_changed, + .on_track_selection_changed = on_track_selection_changed, + .on_program_list_changed = on_program_list_changed, + .on_program_selection_changed = on_program_selection_changed, + .on_title_selection_changed = on_title_selection_changed, + .on_chapter_selection_changed = on_chapter_selection_changed, + .on_media_subitems_changed = on_media_subitems_changed, + .on_cork_changed = on_cork_changed, + .on_vout_changed = on_vout_changed, +}; + +static const struct vlc_player_aout_cbs vlc_player_aout_cbs = { + .on_volume_changed = on_volume_changed, + .on_mute_changed = on_mute_changed, + .on_device_changed = on_audio_device_changed, +}; + /************************************************************************** * Snapshot Taken Event. * @@ -530,64 +511,33 @@ static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd, return VLC_SUCCESS; } -static int corks_changed(vlc_object_t *obj, const char *name, vlc_value_t old, - vlc_value_t cur, void *opaque) +static void input_item_preparsed_changed( const vlc_event_t *p_event, + void * user_data ) { - libvlc_media_player_t *mp = (libvlc_media_player_t *)obj; - - if (!old.i_int != !cur.i_int) + libvlc_media_t *p_md = user_data; + if( p_event->u.input_item_preparsed_changed.new_status & ITEM_PREPARSED ) { + /* Send the event */ libvlc_event_t event; - - event.type = cur.i_int ? libvlc_MediaPlayerCorked - : libvlc_MediaPlayerUncorked; - libvlc_event_send(&mp->event_manager, &event); + event.type = libvlc_MediaParsedChanged; + event.u.media_parsed_changed.new_status = libvlc_media_parsed_status_done; + libvlc_event_send( &p_md->event_manager, &event ); } - VLC_UNUSED(name); VLC_UNUSED(opaque); - return VLC_SUCCESS; -} - -static int audio_device_changed(vlc_object_t *obj, const char *name, - vlc_value_t old, vlc_value_t cur, void *opaque) -{ - libvlc_media_player_t *mp = (libvlc_media_player_t *)obj; - libvlc_event_t event; - - event.type = libvlc_MediaPlayerAudioDevice; - event.u.media_player_audio_device.device = cur.psz_string; - libvlc_event_send(&mp->event_manager, &event); - VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque); - return VLC_SUCCESS; } -static int mute_changed(vlc_object_t *obj, const char *name, vlc_value_t old, - vlc_value_t cur, void *opaque) +static void media_attach_preparsed_event( libvlc_media_t *p_md ) { - libvlc_media_player_t *mp = (libvlc_media_player_t *)obj; - - if (old.b_bool != cur.b_bool) - { - libvlc_event_t event; - - event.type = cur.b_bool ? libvlc_MediaPlayerMuted - : libvlc_MediaPlayerUnmuted; - libvlc_event_send(&mp->event_manager, &event); - } - VLC_UNUSED(name); VLC_UNUSED(opaque); - return VLC_SUCCESS; + vlc_event_attach( &p_md->p_input_item->event_manager, + vlc_InputItemPreparsedChanged, + input_item_preparsed_changed, p_md ); } -static int volume_changed(vlc_object_t *obj, const char *name, vlc_value_t old, - vlc_value_t cur, void *opaque) +static void media_detach_preparsed_event( libvlc_media_t *p_md ) { - libvlc_media_player_t *mp = (libvlc_media_player_t *)obj; - libvlc_event_t event; - - event.type = libvlc_MediaPlayerAudioVolume; - event.u.media_player_audio_volume.volume = cur.f_float; - libvlc_event_send(&mp->event_manager, &event); - VLC_UNUSED(name); VLC_UNUSED(old); VLC_UNUSED(opaque); - return VLC_SUCCESS; + vlc_event_detach( &p_md->p_input_item->event_manager, + vlc_InputItemPreparsedChanged, + input_item_preparsed_changed, + p_md ); } /************************************************************************** @@ -745,33 +695,28 @@ libvlc_media_player_new( libvlc_instance_t *instance ) } mp->p_md = NULL; - mp->state = libvlc_NothingSpecial; mp->p_libvlc_instance = instance; - mp->input.p_thread = NULL; - mp->input.p_renderer = NULL; - mp->input.p_resource = input_resource_New(VLC_OBJECT(mp)); - if (unlikely(mp->input.p_resource == NULL)) - { - vlc_object_delete(mp); - return NULL; - } - audio_output_t *aout = input_resource_GetAout(mp->input.p_resource); - if( aout != NULL ) - input_resource_PutAout(mp->input.p_resource, aout); + /* use a reentrant lock to allow calling libvlc functions from callbacks */ + mp->player = vlc_player_New(VLC_OBJECT(mp), VLC_PLAYER_LOCK_REENTRANT, + NULL, NULL); + if (unlikely(!mp->player)) + goto error1; + + vlc_player_Lock(mp->player); + + mp->listener = vlc_player_AddListener(mp->player, &vlc_player_cbs, mp); + if (unlikely(!mp->listener)) + goto error2; + + mp->aout_listener = + vlc_player_aout_AddListener(mp->player, &vlc_player_aout_cbs, mp); + if (unlikely(!mp->aout_listener)) + goto error3; - vlc_viewpoint_init(&mp->viewpoint); + vlc_player_Unlock(mp->player); - var_Create (mp, "viewpoint", VLC_VAR_ADDRESS); - var_SetAddress( mp, "viewpoint", &mp->viewpoint ); - vlc_mutex_init (&mp->input.lock); mp->i_refcount = 1; libvlc_event_manager_init(&mp->event_manager, mp); - vlc_mutex_init(&mp->object_lock); - - var_AddCallback(mp, "corks", corks_changed, NULL); - var_AddCallback(mp, "audio-device", audio_device_changed, NULL); - var_AddCallback(mp, "mute", mute_changed, NULL); - var_AddCallback(mp, "volume", volume_changed, NULL); /* Snapshot initialization */ /* Attach a var callback to the global object to provide the glue between @@ -786,6 +731,15 @@ libvlc_media_player_new( libvlc_instance_t *instance ) libvlc_retain(instance); return mp; + +error3: + vlc_player_RemoveListener(mp->player, mp->listener); +error2: + vlc_player_Unlock(mp->player); + vlc_player_Delete(mp->player); +error1: + vlc_object_delete(mp); + return NULL; } /************************************************************************** @@ -802,6 +756,19 @@ libvlc_media_player_new_from_media( libvlc_media_t * p_md ) libvlc_media_retain( p_md ); p_mi->p_md = p_md; + media_attach_preparsed_event(p_md); + + vlc_player_Lock(p_mi->player); + int ret = vlc_player_SetCurrentMedia(p_mi->player, p_md->p_input_item); + vlc_player_Unlock(p_mi->player); + + if (ret != VLC_SUCCESS) + { + media_detach_preparsed_event(p_md); + libvlc_media_release(p_md); + p_mi->p_md = NULL; + return NULL; + } return p_mi; } @@ -819,25 +786,15 @@ static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi ) var_DelCallback( vlc_object_instance(p_mi), "snapshot-file", snapshot_was_taken, p_mi ); - /* Detach callback from the media player / input manager object */ - var_DelCallback( p_mi, "volume", volume_changed, NULL ); - var_DelCallback( p_mi, "mute", mute_changed, NULL ); - var_DelCallback( p_mi, "audio-device", audio_device_changed, NULL ); - var_DelCallback( p_mi, "corks", corks_changed, NULL ); - - /* No need for lock_input() because no other threads knows us anymore */ - if( p_mi->input.p_thread ) - release_input_thread(p_mi); - input_resource_Terminate( p_mi->input.p_resource ); - input_resource_Release( p_mi->input.p_resource ); - if( p_mi->input.p_renderer ) - vlc_renderer_item_release( p_mi->input.p_renderer ); + vlc_player_Lock(p_mi->player); + vlc_player_aout_RemoveListener(p_mi->player, p_mi->aout_listener); + vlc_player_RemoveListener(p_mi->player, p_mi->listener); + vlc_player_Unlock(p_mi->player); - vlc_mutex_destroy( &p_mi->input.lock ); + vlc_player_Delete(p_mi->player); libvlc_event_manager_destroy(&p_mi->event_manager); libvlc_media_release( p_mi->p_md ); - vlc_mutex_destroy( &p_mi->object_lock ); vlc_http_cookie_jar_t *cookies = var_GetAddress( p_mi, "http-cookies" ); if ( cookies ) @@ -861,9 +818,9 @@ void libvlc_media_player_release( libvlc_media_player_t *p_mi ) bool destroy; assert( p_mi ); - lock(p_mi); + vlc_player_Lock(p_mi->player); destroy = !--p_mi->i_refcount; - unlock(p_mi); + vlc_player_Unlock(p_mi->player); if( destroy ) libvlc_media_player_destroy( p_mi ); @@ -878,9 +835,9 @@ void libvlc_media_player_retain( libvlc_media_player_t *p_mi ) { assert( p_mi ); - lock(p_mi); + vlc_player_Lock(p_mi->player); p_mi->i_refcount++; - unlock(p_mi); + vlc_player_Unlock(p_mi->player); } /************************************************************************** @@ -892,38 +849,27 @@ void libvlc_media_player_set_media( libvlc_media_player_t *p_mi, libvlc_media_t *p_md ) { - lock_input(p_mi); + vlc_player_Lock(p_mi->player); - release_input_thread( p_mi ); - - lock( p_mi ); - set_state( p_mi, libvlc_NothingSpecial, true ); - unlock_input( p_mi ); + if (p_mi->p_md) + media_detach_preparsed_event(p_mi->p_md); libvlc_media_release( p_mi->p_md ); - if( !p_md ) + if( p_md ) { - p_mi->p_md = NULL; - unlock(p_mi); - return; /* It is ok to pass a NULL md */ + libvlc_media_retain( p_md ); + media_attach_preparsed_event(p_md); } - - libvlc_media_retain( p_md ); p_mi->p_md = p_md; + vlc_player_SetCurrentMedia(p_mi->player, p_md->p_input_item); + /* The policy here is to ignore that we were created using a different * libvlc_instance, because we don't really care */ p_mi->p_libvlc_instance = p_md->p_libvlc_instance; - unlock(p_mi); - - /* Send an event for the newly available media */ - libvlc_event_t event; - event.type = libvlc_MediaPlayerMediaChanged; - event.u.media_player_media_changed.new_media = p_md; - libvlc_event_send( &p_mi->event_manager, &event ); - + vlc_player_Unlock(p_mi->player); } /************************************************************************** @@ -934,11 +880,11 @@ libvlc_media_player_get_media( libvlc_media_player_t *p_mi ) { libvlc_media_t *p_m; - lock( p_mi ); + vlc_player_Lock(p_mi->player); p_m = p_mi->p_md; if( p_m ) libvlc_media_retain( p_m ); - unlock( p_mi ); + vlc_player_Unlock(p_mi->player); return p_m; } @@ -952,122 +898,43 @@ libvlc_media_player_event_manager( libvlc_media_player_t *p_mi ) return &p_mi->event_manager; } -static void add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi ) -{ - var_AddListCallback( p_input_thread, "video-es", input_es_changed, p_mi ); - var_AddListCallback( p_input_thread, "audio-es", input_es_changed, p_mi ); - var_AddListCallback( p_input_thread, "spu-es", input_es_changed, p_mi ); -} - -static void del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi ) -{ - var_DelListCallback( p_input_thread, "video-es", input_es_changed, p_mi ); - var_DelListCallback( p_input_thread, "audio-es", input_es_changed, p_mi ); - var_DelListCallback( p_input_thread, "spu-es", input_es_changed, p_mi ); -} - -static void on_input_event(input_thread_t *input, - const struct vlc_input_event *event, void *userdata) -{ - if (event->type == INPUT_EVENT_SUBITEMS) - { - libvlc_media_player_t *media_player = userdata; - libvlc_media_t *media = media_player->p_md; - libvlc_media_add_subtree(media, event->subitems); - } - - input_LegacyEvents(input, event, userdata); -} - /************************************************************************** * Tell media player to start playing. **************************************************************************/ int libvlc_media_player_play( libvlc_media_player_t *p_mi ) { - lock_input( p_mi ); + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - input_thread_t *p_input_thread = p_mi->input.p_thread; - if( p_input_thread ) + int ret = vlc_player_Start(player); + if (ret == VLC_SUCCESS) { - /* A thread already exists, send it a play message */ - var_SetInteger( p_input_thread, "state", PLAYING_S ); - unlock_input( p_mi ); - return 0; + if (vlc_player_IsPaused(player)) + vlc_player_Resume(player); } - /* Ignore previous exception */ - lock(p_mi); - - if( !p_mi->p_md ) - { - unlock(p_mi); - unlock_input( p_mi ); - libvlc_printerr( "No associated media descriptor" ); - return -1; - } - - for( size_t i = 0; i < ARRAY_SIZE( p_mi->selected_es ); ++i ) - p_mi->selected_es[i] = ES_INIT; - - media_attach_preparsed_event( p_mi->p_md ); - - p_input_thread = input_Create( p_mi, on_input_event, p_mi, - p_mi->p_md->p_input_item, - p_mi->input.p_resource, - p_mi->input.p_renderer ); - unlock(p_mi); - if( !p_input_thread ) - { - unlock_input(p_mi); - media_detach_preparsed_event( p_mi->p_md ); - libvlc_printerr( "Not enough memory" ); - return -1; - } - - input_LegacyVarInit( p_input_thread ); - var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi ); - var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi ); - var_AddCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi ); - var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi ); - add_es_callbacks( p_input_thread, p_mi ); - - if( input_Start( p_input_thread ) ) - { - unlock_input(p_mi); - del_es_callbacks( p_input_thread, p_mi ); - var_DelCallback( p_input_thread, "intf-event", input_event_changed, p_mi ); - var_DelCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi ); - var_DelCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi ); - var_DelCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi ); - input_Close( p_input_thread ); - media_detach_preparsed_event( p_mi->p_md ); - libvlc_printerr( "Input initialization failure" ); - return -1; - } - p_mi->input.p_thread = p_input_thread; - unlock_input(p_mi); - return 0; + vlc_player_Unlock(player); + return ret; } void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused ) { - input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi ); - if( !p_input_thread ) - return; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( paused ) + if (paused) { - if( libvlc_media_player_can_pause( p_mi ) ) - var_SetInteger( p_input_thread, "state", PAUSE_S ); + if (vlc_player_CanPause(player)) + vlc_player_Pause(player); else - input_Stop( p_input_thread ); + vlc_player_Stop(player); } else { - var_SetInteger( p_input_thread, "state", PLAYING_S ); + vlc_player_Resume(player); } - input_Release(p_input_thread); + vlc_player_Unlock(player); } /************************************************************************** @@ -1075,7 +942,12 @@ void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused ) **************************************************************************/ void libvlc_media_player_pause( libvlc_media_player_t *p_mi ) { - libvlc_media_player_set_pause( p_mi, libvlc_media_player_is_playing( p_mi ) ); + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + vlc_player_TogglePause(player); + + vlc_player_Unlock(player); } /************************************************************************** @@ -1083,8 +955,13 @@ void libvlc_media_player_pause( libvlc_media_player_t *p_mi ) **************************************************************************/ bool libvlc_media_player_is_playing(libvlc_media_player_t *p_mi) { - libvlc_state_t state = libvlc_media_player_get_state( p_mi ); - return libvlc_Playing == state; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + bool ret = vlc_player_IsStarted(player) && !vlc_player_IsPaused(player); + + vlc_player_Unlock(player); + return ret; } /************************************************************************** @@ -1092,41 +969,24 @@ bool libvlc_media_player_is_playing(libvlc_media_player_t *p_mi) **************************************************************************/ void libvlc_media_player_stop( libvlc_media_player_t *p_mi ) { - lock_input(p_mi); - release_input_thread( p_mi ); /* This will stop the input thread */ + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - /* Force to go to stopped state, in case we were in Ended, or Error - * state. */ - if( p_mi->state != libvlc_Stopped ) - { - set_state( p_mi, libvlc_Stopped, false ); - - /* Construct and send the event */ - libvlc_event_t event; - event.type = libvlc_MediaPlayerStopped; - libvlc_event_send( &p_mi->event_manager, &event ); - } + vlc_player_Stop(player); - input_resource_Terminate( p_mi->input.p_resource ); - unlock_input(p_mi); + vlc_player_Unlock(player); } int libvlc_media_player_set_renderer( libvlc_media_player_t *p_mi, libvlc_renderer_item_t *p_litem ) { - vlc_renderer_item_t *p_item = - p_litem ? libvlc_renderer_item_to_vlc( p_litem ) : NULL; - - lock_input( p_mi ); - input_thread_t *p_input_thread = p_mi->input.p_thread; - if( p_input_thread ) - input_Control( p_input_thread, INPUT_SET_RENDERER, p_item ); + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( p_mi->input.p_renderer ) - vlc_renderer_item_release( p_mi->input.p_renderer ); - p_mi->input.p_renderer = p_item ? vlc_renderer_item_hold( p_item ) : NULL; - unlock_input( p_mi ); + vlc_renderer_item_t *renderer = libvlc_renderer_item_to_vlc(p_litem); + vlc_player_SetRenderer(player, renderer); + vlc_player_Unlock(player); return 0; } @@ -1364,16 +1224,12 @@ void libvlc_audio_set_callbacks( libvlc_media_player_t *mp, var_SetAddress( mp, "amem-drain", drain_cb ); var_SetAddress( mp, "amem-data", opaque ); var_SetString( mp, "aout", "amem,none" ); - - input_resource_ResetAout(mp->input.p_resource); } void libvlc_audio_set_volume_callback( libvlc_media_player_t *mp, libvlc_audio_set_volume_cb cb ) { var_SetAddress( mp, "amem-set-volume", cb ); - - input_resource_ResetAout(mp->input.p_resource); } void libvlc_audio_set_format_callbacks( libvlc_media_player_t *mp, @@ -1382,8 +1238,6 @@ void libvlc_audio_set_format_callbacks( libvlc_media_player_t *mp, { var_SetAddress( mp, "amem-setup", setup ); var_SetAddress( mp, "amem-cleanup", cleanup ); - - input_resource_ResetAout(mp->input.p_resource); } void libvlc_audio_set_format( libvlc_media_player_t *mp, const char *format, @@ -1392,8 +1246,6 @@ void libvlc_audio_set_format( libvlc_media_player_t *mp, const char *format, var_SetString( mp, "amem-format", format ); var_SetInteger( mp, "amem-rate", rate ); var_SetInteger( mp, "amem-channels", channels ); - - input_resource_ResetAout(mp->input.p_resource); } @@ -1403,185 +1255,169 @@ void libvlc_audio_set_format( libvlc_media_player_t *mp, const char *format, libvlc_time_t libvlc_media_player_get_length( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread; - libvlc_time_t i_time; - - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - i_time = from_mtime(var_GetInteger( p_input_thread, "length" )); - input_Release(p_input_thread); + vlc_tick_t length = vlc_player_GetLength(player); + libvlc_time_t i_time = from_mtime(length); + vlc_player_Unlock(player); return i_time; } libvlc_time_t libvlc_media_player_get_time( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread; - libvlc_time_t i_time; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1; + vlc_tick_t tick = vlc_player_GetTime(player); + libvlc_time_t i_time = from_mtime(tick); - i_time = from_mtime(var_GetInteger( p_input_thread , "time" )); - input_Release(p_input_thread); + vlc_player_Unlock(player); return i_time; } int libvlc_media_player_set_time( libvlc_media_player_t *p_mi, libvlc_time_t i_time, bool b_fast ) { - input_thread_t *p_input_thread; + vlc_tick_t tick = to_mtime(i_time); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + enum vlc_player_seek_speed speed = b_fast ? VLC_PLAYER_SEEK_FAST + : VLC_PLAYER_SEEK_PRECISE; + vlc_player_SeekByTime(player, tick, speed, VLC_PLAYER_WHENCE_ABSOLUTE); - input_SetTime( p_input_thread, to_mtime(i_time), b_fast ); - input_Release(p_input_thread); + vlc_player_Unlock(player); + + /* may not fail anymore, keep int not to break the API */ return 0; } int libvlc_media_player_set_position( libvlc_media_player_t *p_mi, float position, bool b_fast ) { - input_thread_t *p_input_thread; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1; + enum vlc_player_seek_speed speed = b_fast ? VLC_PLAYER_SEEK_FAST + : VLC_PLAYER_SEEK_PRECISE; + vlc_player_SeekByPos(player, position, speed, VLC_PLAYER_WHENCE_ABSOLUTE); + + vlc_player_Unlock(player); - input_SetPosition( p_input_thread, position, b_fast ); - input_Release(p_input_thread); + /* may not fail anymore, keep int not to break the API */ return 0; } float libvlc_media_player_get_position( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread; - float f_position; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1.0; - - f_position = var_GetFloat( p_input_thread, "position" ); - input_Release(p_input_thread); + float f_position = vlc_player_GetPosition(player); + vlc_player_Unlock(player); return f_position; } void libvlc_media_player_set_chapter( libvlc_media_player_t *p_mi, int chapter ) { - input_thread_t *p_input_thread; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return; + vlc_player_SelectChapterIdx(player, chapter); - var_SetInteger( p_input_thread, "chapter", chapter ); - input_Release(p_input_thread); + vlc_player_Unlock(player); } int libvlc_media_player_get_chapter( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread; - int i_chapter; - - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - i_chapter = var_GetInteger( p_input_thread, "chapter" ); - input_Release(p_input_thread); + ssize_t i_chapter = vlc_player_GetSelectedChapterIdx(player); + vlc_player_Unlock(player); return i_chapter; } int libvlc_media_player_get_chapter_count( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread; - size_t val; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1; - - int i_ret = var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val ); - input_Release(p_input_thread); + const struct vlc_player_title *title = vlc_player_GetSelectedTitle(player); + int ret = title ? (int) title->chapter_count : -1; - return i_ret == VLC_SUCCESS ? (ssize_t)val : -1; + vlc_player_Unlock(player); + return ret; } int libvlc_media_player_get_chapter_count_for_title( libvlc_media_player_t *p_mi, int i_title ) { - size_t val; + assert(i_title >= 0); + size_t idx = i_title; + int ret = -1; - input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + vlc_player_title_list *titles = vlc_player_GetTitleList(player); + if (!titles) + goto end; + + size_t titles_count = vlc_player_title_list_GetCount(titles); + if (idx < titles_count) + goto end; - char psz_name[sizeof ("title ") + 3 * sizeof (int)]; - sprintf( psz_name, "title %2u", i_title ); + const struct vlc_player_title *title = + vlc_player_title_list_GetAt(titles, idx); + assert(title); - int i_ret = var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val ); - input_Release(p_input_thread); + ret = title->chapter_count; - return i_ret == VLC_SUCCESS ? (ssize_t)val : -1; +end: + vlc_player_Unlock(player); + return ret; } void libvlc_media_player_set_title( libvlc_media_player_t *p_mi, int i_title ) { - input_thread_t *p_input_thread; - - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - var_SetInteger( p_input_thread, "title", i_title ); - input_Release(p_input_thread); + vlc_player_SelectTitleIdx(player, i_title); - //send event - libvlc_event_t event; - event.type = libvlc_MediaPlayerTitleChanged; - event.u.media_player_title_changed.new_title = i_title; - libvlc_event_send( &p_mi->event_manager, &event ); + vlc_player_Unlock(player); } int libvlc_media_player_get_title( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread; - int i_title; - - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - i_title = var_GetInteger( p_input_thread, "title" ); - input_Release(p_input_thread); + ssize_t i_title = vlc_player_GetSelectedTitleIdx(player); + vlc_player_Unlock(player); return i_title; } int libvlc_media_player_get_title_count( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread; - size_t val; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return -1; - - int i_ret = var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val ); - input_Release(p_input_thread); + vlc_player_title_list *titles = vlc_player_GetTitleList(player); + int ret = titles ? (int) vlc_player_title_list_GetCount(titles) : -1; - return i_ret == VLC_SUCCESS ? (ssize_t)val : -1; + vlc_player_Unlock(player); + return ret; } int libvlc_media_player_get_full_title_descriptions( libvlc_media_player_t *p_mi, @@ -1589,49 +1425,46 @@ int libvlc_media_player_get_full_title_descriptions( libvlc_media_player_t *p_mi { assert( p_mi ); - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); + int ret = -1; - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - input_title_t **p_input_title; - int count; + vlc_player_title_list *titles = vlc_player_GetTitleList(player); + if (!titles) + goto end; - /* fetch data */ - int ret = input_Control( p_input_thread, INPUT_GET_FULL_TITLE_INFO, - &p_input_title, &count ); - input_Release(p_input_thread); - if( ret != VLC_SUCCESS ) - return -1; + size_t count = vlc_player_title_list_GetCount(titles); - libvlc_title_description_t **titles = vlc_alloc( count, sizeof (*titles) ); - if( count > 0 && unlikely(titles == NULL) ) - return -1; + libvlc_title_description_t **descs = vlc_alloc(count, sizeof(*descs)); + if (count > 0 && !descs) + goto end; - /* fill array */ - for( int i = 0; i < count; i++) + for (size_t i = 0; i < count; i++) { - libvlc_title_description_t *title = malloc( sizeof (*title) ); - if( unlikely(title == NULL) ) + const struct vlc_player_title *title = + vlc_player_title_list_GetAt(titles, i); + libvlc_title_description_t *desc = malloc(sizeof(*desc)); + if (!desc) { - libvlc_title_descriptions_release( titles, i ); - return -1; + libvlc_title_descriptions_release(descs, i); + goto end; } - titles[i] = title; + + descs[i] = desc; /* we want to return milliseconds to match the rest of the API */ - title->i_duration = MS_FROM_VLC_TICK(p_input_title[i]->i_length); - title->i_flags = p_input_title[i]->i_flags; - if( p_input_title[i]->psz_name ) - title->psz_name = strdup( p_input_title[i]->psz_name ); - else - title->psz_name = NULL; - vlc_input_title_Delete( p_input_title[i] ); + desc->i_duration = MS_FROM_VLC_TICK(title->length); + desc->i_flags = title->flags; + desc->psz_name = title->name ? strdup(title->name) : NULL; } - free( p_input_title ); - *pp_titles = titles; - return count; + ret = count; + *pp_titles = descs; + +end: + vlc_player_Unlock(player); + return ret; } void libvlc_title_descriptions_release( libvlc_title_description_t **p_titles, @@ -1654,82 +1487,56 @@ int libvlc_media_player_get_full_chapter_descriptions( libvlc_media_player_t *p_ { assert( p_mi ); - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); + int ret = -1; - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - seekpoint_t **p_seekpoint = NULL; - input_title_t **pp_title, *p_title = NULL; - int i_title_count = 0, ci_chapter_count = 0; - int ret = input_Control( p_input_thread, INPUT_GET_FULL_TITLE_INFO, &pp_title, - &i_title_count ); - input_Release(p_input_thread); + vlc_player_title_list *titles = vlc_player_GetTitleList(player); + if (!titles) + goto end; - if( ret != VLC_SUCCESS || i_chapters_of_title >= i_title_count ) - goto error; + size_t titles_count = vlc_player_title_list_GetCount(titles); + if (i_chapters_of_title < (int) titles_count) + goto end; - p_title = pp_title[i_chapters_of_title]; - int64_t i_title_duration = MS_FROM_VLC_TICK(p_title->i_length); - p_seekpoint = p_title->seekpoint; - ci_chapter_count = p_title->i_seekpoint; + const struct vlc_player_title *title = + vlc_player_title_list_GetAt(titles, i_chapters_of_title); + assert(title); - if( ci_chapter_count == 0 || p_seekpoint == NULL) - goto error; + size_t i_chapter_count = title->chapter_count; - *pp_chapters = calloc( ci_chapter_count, sizeof(**pp_chapters) ); - if( !*pp_chapters ) - { - goto error; - } + libvlc_chapter_description_t **descs = + vlc_alloc(i_chapter_count, sizeof(*descs)); + if (i_chapter_count > 0 && !descs) + goto end; - /* fill array */ - for( int i = 0; i < ci_chapter_count; ++i ) + for (size_t i = 0; i < i_chapter_count; i++) { - libvlc_chapter_description_t *p_chapter = malloc( sizeof(*p_chapter) ); - if( unlikely(p_chapter == NULL) ) + const struct vlc_player_chapter *chapter = &title->chapters[i]; + libvlc_chapter_description_t *desc = malloc(sizeof(*desc)); + if (!desc) { - goto error; + libvlc_chapter_descriptions_release(descs, i); + goto end; } - (*pp_chapters)[i] = p_chapter; - - p_chapter->i_time_offset = MS_FROM_VLC_TICK( p_seekpoint[i]->i_time_offset ); - if( i < ci_chapter_count - 1 ) - { - p_chapter->i_duration = MS_FROM_VLC_TICK( p_seekpoint[i + 1]->i_time_offset ) - - p_chapter->i_time_offset; - } - else - { - if ( i_title_duration ) - p_chapter->i_duration = i_title_duration - p_chapter->i_time_offset; - else - p_chapter->i_duration = 0; - } + descs[i] = desc; - if( p_seekpoint[i]->psz_name ) - { - p_chapter->psz_name = strdup( p_seekpoint[i]->psz_name ); - } - else - { - p_chapter->psz_name = NULL; - } - vlc_seekpoint_Delete( p_seekpoint[i] ); - p_seekpoint[i] = NULL; + vlc_tick_t chapter_end = i < i_chapter_count - 1 + ? title->chapters[i + 1].time + : title->length; + desc->i_time_offset = MS_FROM_VLC_TICK(chapter->time); + desc->psz_name = chapter->name ? strdup(chapter->name) : NULL; + desc->i_duration = MS_FROM_VLC_TICK(chapter_end) - desc->i_time_offset; } - free( p_seekpoint ); - return ci_chapter_count; + ret = i_chapter_count; + *pp_chapters = descs; -error: - if( *pp_chapters ) - libvlc_chapter_descriptions_release( *pp_chapters, ci_chapter_count ); - for( int i = 0; i < i_title_count; i++ ) - vlc_input_title_Delete( pp_title[i] ); - free( pp_title ) ; - return -1; +end: + vlc_player_Unlock(player); + return ret; } void libvlc_chapter_descriptions_release( libvlc_chapter_description_t **p_chapters, @@ -1748,113 +1555,116 @@ void libvlc_chapter_descriptions_release( libvlc_chapter_description_t **p_chapt void libvlc_media_player_next_chapter( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return; - - int i_type = var_Type( p_input_thread, "next-chapter" ); - var_TriggerCallback( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ? - "next-chapter":"next-title" ); + vlc_player_SelectNextChapter(player); - input_Release(p_input_thread); + vlc_player_Unlock(player); } void libvlc_media_player_previous_chapter( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread; - - p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - int i_type = var_Type( p_input_thread, "next-chapter" ); - var_TriggerCallback( p_input_thread, (i_type & VLC_VAR_TYPE) != 0 ? - "prev-chapter":"prev-title" ); + vlc_player_SelectPrevChapter(player); - input_Release(p_input_thread); + vlc_player_Unlock(player); } int libvlc_media_player_set_rate( libvlc_media_player_t *p_mi, float rate ) { - var_SetFloat (p_mi, "rate", rate); + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi ); - if( !p_input_thread ) - return 0; - var_SetFloat( p_input_thread, "rate", rate ); - input_Release(p_input_thread); + vlc_player_ChangeRate(player, rate); + + vlc_player_Unlock(player); return 0; } float libvlc_media_player_get_rate( libvlc_media_player_t *p_mi ) { - return var_GetFloat (p_mi, "rate"); + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + float rate = vlc_player_GetRate(player); + + vlc_player_Unlock(player); + return rate; } libvlc_state_t libvlc_media_player_get_state( libvlc_media_player_t *p_mi ) { - lock(p_mi); - libvlc_state_t state = p_mi->state; - unlock(p_mi); - return state; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + enum vlc_player_error error = vlc_player_GetError(player); + enum vlc_player_state state = vlc_player_GetState(player); + + vlc_player_Unlock(player); + + if (error != VLC_PLAYER_ERROR_NONE) + return libvlc_Error; + switch (state) { + case VLC_PLAYER_STATE_STOPPED: + return libvlc_Stopped; + case VLC_PLAYER_STATE_STOPPING: + return libvlc_Ended; + case VLC_PLAYER_STATE_STARTED: + return libvlc_Opening; + case VLC_PLAYER_STATE_PLAYING: + return libvlc_Playing; + case VLC_PLAYER_STATE_PAUSED: + return libvlc_Paused; + default: + vlc_assert_unreachable(); + } } bool libvlc_media_player_is_seekable(libvlc_media_player_t *p_mi) { - input_thread_t *p_input_thread; - bool b_seekable; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if ( !p_input_thread ) - return false; - b_seekable = var_GetBool( p_input_thread, "can-seek" ); - input_Release(p_input_thread); + bool b_seekable = vlc_player_CanSeek(player); + vlc_player_Unlock(player); return b_seekable; } void libvlc_media_player_navigate( libvlc_media_player_t* p_mi, unsigned navigate ) { - static const int map[] = + static const enum vlc_player_nav map[] = { - INPUT_NAV_ACTIVATE, INPUT_NAV_UP, INPUT_NAV_DOWN, - INPUT_NAV_LEFT, INPUT_NAV_RIGHT, INPUT_NAV_POPUP, + VLC_PLAYER_NAV_ACTIVATE, VLC_PLAYER_NAV_UP, VLC_PLAYER_NAV_DOWN, + VLC_PLAYER_NAV_LEFT, VLC_PLAYER_NAV_RIGHT, VLC_PLAYER_NAV_POPUP, }; if( navigate >= sizeof(map) / sizeof(map[0]) ) return; - input_thread_t *p_input = libvlc_get_input_thread ( p_mi ); - if ( p_input == NULL ) - return; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + vlc_player_Navigate(player, map[navigate]); - input_Control( p_input, map[navigate], NULL ); - input_Release(p_input); + vlc_player_Unlock(player); } /* internal function, used by audio, video */ libvlc_track_description_t * libvlc_get_track_description( libvlc_media_player_t *p_mi, - const char *psz_variable ) + enum es_format_category_e cat ) { - input_thread_t *p_input = libvlc_get_input_thread( p_mi ); - libvlc_track_description_t *ret, **pp = &ret; - - if( !p_input ) - return NULL; - - vlc_value_t *val_list; - char **text_list; - size_t count; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - int i_ret = var_Change( p_input, psz_variable, VLC_VAR_GETCHOICES, - &count, &val_list, &text_list ); - if( i_ret != VLC_SUCCESS ) - return NULL; + libvlc_track_description_t *ret, **pp = &ret; + size_t count = vlc_player_GetTrackCount(player, cat); for (size_t i = 0; i < count; i++) { libvlc_track_description_t *tr = malloc(sizeof (*tr)); @@ -1864,17 +1674,23 @@ libvlc_track_description_t * continue; } + const struct vlc_player_track *track = + vlc_player_GetTrackAt(player, cat, i); + *pp = tr; - tr->i_id = val_list[i].i_int; - tr->psz_name = text_list[i]; + tr->i_id = vlc_es_id_GetInputId(track->es_id); + tr->psz_name = strdup(track->name); + if (unlikely(!tr->psz_name)) + { + free(tr); + continue; + } pp = &tr->p_next; } *pp = NULL; - free(val_list); - free(text_list); - input_Release(p_input); + vlc_player_Unlock(player); return ret; } @@ -1894,40 +1710,42 @@ void libvlc_track_description_list_release( libvlc_track_description_t *p_td ) bool libvlc_media_player_can_pause(libvlc_media_player_t *p_mi) { - input_thread_t *p_input_thread; - bool b_can_pause; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - p_input_thread = libvlc_get_input_thread ( p_mi ); - if ( !p_input_thread ) - return false; - b_can_pause = var_GetBool( p_input_thread, "can-pause" ); - input_Release(p_input_thread); + bool b_can_pause = vlc_player_CanPause(player); + vlc_player_Unlock(player); return b_can_pause; } bool libvlc_media_player_program_scrambled(libvlc_media_player_t *p_mi) { - input_thread_t *p_input_thread; - bool b_program_scrambled; + bool b_program_scrambled = false; - p_input_thread = libvlc_get_input_thread ( p_mi ); - if ( !p_input_thread ) - return false; - b_program_scrambled = var_GetBool( p_input_thread, "program-scrambled" ); - input_Release(p_input_thread); + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + const struct vlc_player_program *program = + vlc_player_GetSelectedProgram(player); + if (!program) + goto end; + b_program_scrambled = program->scrambled; + + vlc_player_Unlock(player); +end: return b_program_scrambled; } void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi ); - if( p_input_thread != NULL ) - { - var_TriggerCallback( p_input_thread, "frame-next" ); - input_Release(p_input_thread); - } + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); + + vlc_player_NextVideoFrame(player); + + vlc_player_Unlock(player); } /** @@ -1966,26 +1784,18 @@ int libvlc_media_player_add_slave( libvlc_media_player_t *p_mi, libvlc_media_slave_type_t i_type, const char *psz_uri, bool b_select ) { - input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi ); + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( p_input_thread == NULL ) - { - libvlc_media_t *p_media = libvlc_media_player_get_media( p_mi ); - if( p_media == NULL ) - return -1; + enum es_format_category_e cat = i_type == libvlc_media_slave_type_subtitle + ? SPU_ES + : AUDIO_ES; - int i_ret = libvlc_media_slaves_add( p_media, i_type, 4, psz_uri ); - libvlc_media_release( p_media ); - return i_ret; - } - else - { - int i_ret = input_AddSlave( p_input_thread, (enum slave_type) i_type, - psz_uri, b_select, false, false ); - input_Release(p_input_thread); + int ret = vlc_player_AddAssociatedMedia(player, cat, psz_uri, b_select, + false, false); - return i_ret == VLC_SUCCESS ? 0 : -1; - } + vlc_player_Unlock(player); + return ret; } /** @@ -2018,7 +1828,7 @@ int libvlc_media_player_set_equalizer( libvlc_media_player_t *p_mi, libvlc_equal } var_SetString( p_mi, "audio-filter", p_equalizer ? "equalizer" : "" ); - audio_output_t *p_aout = input_resource_HoldAout( p_mi->input.p_resource ); + audio_output_t *p_aout = vlc_player_aout_Hold( p_mi->player ); if( p_aout != NULL ) { if( p_equalizer != NULL ) diff --git a/lib/media_player_internal.h b/lib/media_player_internal.h index bc1faf44ba..c2d5348e22 100644 --- a/lib/media_player_internal.h +++ b/lib/media_player_internal.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "../modules/audio_filter/equalizer_presets.h" @@ -40,31 +41,19 @@ struct libvlc_media_player_t struct vlc_object_t obj; int i_refcount; - vlc_mutex_t object_lock; - struct - { - input_thread_t *p_thread; - input_resource_t *p_resource; - vlc_renderer_item_t *p_renderer; - vlc_mutex_t lock; - } input; + vlc_player_t *player; + vlc_player_listener_id *listener; + vlc_player_aout_listener_id *aout_listener; struct libvlc_instance_t * p_libvlc_instance; /* Parent instance */ libvlc_media_t * p_md; /* current media descriptor */ libvlc_event_manager_t event_manager; - libvlc_state_t state; - vlc_viewpoint_t viewpoint; - int selected_es[3]; }; -/* Media player - audio, video */ -input_thread_t *libvlc_get_input_thread(libvlc_media_player_t * ); - - libvlc_track_description_t * libvlc_get_track_description( libvlc_media_player_t *p_mi, - const char *psz_variable ); + enum es_format_category_e cat ); /** * Internal equalizer structure. diff --git a/lib/video.c b/lib/video.c index cb7838a28a..a318df0098 100644 --- a/lib/video.c +++ b/lib/video.c @@ -50,21 +50,8 @@ */ static vout_thread_t **GetVouts( libvlc_media_player_t *p_mi, size_t *n ) { - input_thread_t *p_input = libvlc_get_input_thread( p_mi ); - if( !p_input ) - { - *n = 0; - return NULL; - } - - vout_thread_t **pp_vouts; - if (input_Control( p_input, INPUT_GET_VOUTS, &pp_vouts, n)) - { - *n = 0; - pp_vouts = NULL; - } - input_Release(p_input); - return pp_vouts; + vlc_player_t *player = p_mi->player; + return vlc_player_vout_HoldAll(player, n); } static vout_thread_t *GetVout (libvlc_media_player_t *mp, size_t num) @@ -286,134 +273,94 @@ int libvlc_video_update_viewpoint( libvlc_media_player_t *p_mi, .fov = p_viewpoint->f_field_of_view, }; - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - if( p_input_thread != NULL ) - { - if( input_UpdateViewpoint( p_input_thread, &update, - b_absolute ) != VLC_SUCCESS ) - { - input_Release(p_input_thread); - return -1; - } - input_Release(p_input_thread); - return 0; - } - - /* Save the viewpoint in case the input is not created yet */ - if( !b_absolute ) - { - p_mi->viewpoint.yaw += update.yaw; - p_mi->viewpoint.pitch += update.pitch; - p_mi->viewpoint.roll += update.roll; - p_mi->viewpoint.fov += update.fov; - } - else - p_mi->viewpoint = update; - - vlc_viewpoint_clip( &p_mi->viewpoint ); + enum vlc_player_whence whence = b_absolute ? VLC_PLAYER_WHENCE_ABSOLUTE + : VLC_PLAYER_WHENCE_RELATIVE; + vlc_player_UpdateViewpoint(p_mi->player, &update, whence); + /* may not fail anymore, keep int not to break the API */ return 0; } int libvlc_video_get_spu( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( !p_input_thread ) - { - libvlc_printerr( "No active input" ); - return -1; - } + const struct vlc_player_track *track = + vlc_player_GetSelectedTrack(player, SPU_ES); + int i_spu = track ? vlc_es_id_GetInputId(track->es_id) : -1; - int i_spu = var_GetInteger( p_input_thread, "spu-es" ); - input_Release(p_input_thread); + vlc_player_Unlock(player); return i_spu; } int libvlc_video_get_spu_count( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - int i_spu_count; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( !p_input_thread ) - return 0; + int ret = vlc_player_GetTrackCount(p_mi->player, SPU_ES); - i_spu_count = var_CountChoices( p_input_thread, "spu-es" ); - input_Release(p_input_thread); - return i_spu_count; + vlc_player_Unlock(player); + return ret; } libvlc_track_description_t * libvlc_video_get_spu_description( libvlc_media_player_t *p_mi ) { - return libvlc_get_track_description( p_mi, "spu-es" ); + return libvlc_get_track_description( p_mi, SPU_ES ); } int libvlc_video_set_spu( libvlc_media_player_t *p_mi, int i_spu ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - vlc_value_t *list; - size_t count; int i_ret = -1; - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - var_Change(p_input_thread, "spu-es", VLC_VAR_GETCHOICES, - &count, &list, (char ***)NULL); + size_t count = vlc_player_GetSubtitleTrackCount(player); for (size_t i = 0; i < count; i++) { - if( i_spu == list[i].i_int ) + const struct vlc_player_track *track = + vlc_player_GetSubtitleTrackAt(player, i); + if (i_spu == vlc_es_id_GetInputId(track->es_id)) { - if( var_SetInteger( p_input_thread, "spu-es", i_spu ) < 0 ) - break; + /* found */ + vlc_player_SelectTrack(player, track->es_id); i_ret = 0; goto end; } } libvlc_printerr( "Track identifier not found" ); end: - input_Release(p_input_thread); - free(list); + vlc_player_Unlock(player); return i_ret; } int64_t libvlc_video_get_spu_delay( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - int64_t val = 0; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( p_input_thread ) - { - val = US_FROM_VLC_TICK( var_GetInteger( p_input_thread, "spu-delay" ) ); - input_Release(p_input_thread); - } - else - { - libvlc_printerr( "No active input" ); - } + vlc_tick_t delay = vlc_player_GetSubtitleDelay(player); - return val; + vlc_player_Unlock(player); + + return US_FROM_VLC_TICK(delay); } int libvlc_video_set_spu_delay( libvlc_media_player_t *p_mi, int64_t i_delay ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - int ret = -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( p_input_thread ) - { - var_SetInteger( p_input_thread, "spu-delay", VLC_TICK_FROM_US( i_delay ) ); - input_Release(p_input_thread); - ret = 0; - } - else - { - libvlc_printerr( "No active input" ); - } + vlc_player_SetSubtitleDelay(player, VLC_TICK_FROM_US(i_delay), + VLC_PLAYER_WHENCE_ABSOLUTE); - return ret; + vlc_player_Unlock(player); + /* may not fail anymore, keep int not to break the API */ + return 0; } char *libvlc_video_get_crop_geometry (libvlc_media_player_t *p_mi) @@ -447,50 +394,30 @@ int libvlc_video_get_teletext( libvlc_media_player_t *p_mi ) return var_GetInteger (p_mi, "vbi-page"); } -static void teletext_enable( input_thread_t *p_input_thread, bool b_enable ) -{ - if( b_enable ) - { - vlc_value_t *list; - size_t count; - - if( !var_Change( p_input_thread, "teletext-es", VLC_VAR_GETCHOICES, - &count, &list, (char ***)NULL ) ) - { - if( count > 0 ) - var_SetInteger( p_input_thread, "spu-es", list[0].i_int ); - - free(list); - } - } - else - var_SetInteger( p_input_thread, "spu-es", -1 ); -} - void libvlc_video_set_teletext( libvlc_media_player_t *p_mi, int i_page ) { - input_thread_t *p_input_thread; - vlc_object_t *p_zvbi = NULL; - int telx; - bool b_key = false; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( i_page >= 0 && i_page < 1000 ) - var_SetInteger( p_mi, "vbi-page", i_page ); - else if( i_page >= 1000 ) + if (i_page == 0) + vlc_player_SetTeletextEnabled(player, false); + else if (i_page > 0) { - switch (i_page) + if (i_page >= 1000) { - case libvlc_teletext_key_red: - case libvlc_teletext_key_green: - case libvlc_teletext_key_yellow: - case libvlc_teletext_key_blue: - case libvlc_teletext_key_index: - b_key = true; - break; - default: + bool is_key = i_page == libvlc_teletext_key_red + || i_page == libvlc_teletext_key_green + || i_page == libvlc_teletext_key_yellow + || i_page == libvlc_teletext_key_blue + || i_page == libvlc_teletext_key_index; + if (!is_key) + { libvlc_printerr("Invalid key action"); return; + } } + vlc_player_SetTeletextEnabled(player, true); + vlc_player_SelectTeletextPage(player, i_page); } else { @@ -498,99 +425,62 @@ void libvlc_video_set_teletext( libvlc_media_player_t *p_mi, int i_page ) return; } - p_input_thread = libvlc_get_input_thread( p_mi ); - if( !p_input_thread ) return; - - if( var_CountChoices( p_input_thread, "teletext-es" ) <= 0 ) - { - input_Release(p_input_thread); - return; - } - - if( i_page == 0 ) - { - teletext_enable( p_input_thread, false ); - } - else - { - telx = var_GetInteger( p_input_thread, "teletext-es" ); - if( telx >= 0 ) - { - if( input_GetEsObjects( p_input_thread, telx, &p_zvbi ) - == VLC_SUCCESS ) - { - var_SetInteger( p_zvbi, "vbi-page", i_page ); - } - } - else if (!b_key) - { - /* the "vbi-page" will be selected on es creation */ - teletext_enable( p_input_thread, true ); - } - else - libvlc_printerr("Key action sent while the teletext is disabled"); - } - input_Release(p_input_thread); + vlc_player_Unlock(player); } int libvlc_video_get_track_count( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - int i_track_count; - - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - i_track_count = var_CountChoices( p_input_thread, "video-es" ); + int ret = vlc_player_GetTrackCount(p_mi->player, VIDEO_ES); - input_Release(p_input_thread); - return i_track_count; + vlc_player_Unlock(player); + return ret; } libvlc_track_description_t * libvlc_video_get_track_description( libvlc_media_player_t *p_mi ) { - return libvlc_get_track_description( p_mi, "video-es" ); + return libvlc_get_track_description( p_mi, VIDEO_ES ); } int libvlc_video_get_track( libvlc_media_player_t *p_mi ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - if( !p_input_thread ) - return -1; + const struct vlc_player_track * track = + vlc_player_GetSelectedTrack(player, VIDEO_ES); + int id = track ? vlc_es_id_GetInputId(track->es_id) : -1; - int id = var_GetInteger( p_input_thread, "video-es" ); - input_Release(p_input_thread); + vlc_player_Unlock(player); return id; } int libvlc_video_set_track( libvlc_media_player_t *p_mi, int i_track ) { - input_thread_t *p_input_thread = libvlc_get_input_thread( p_mi ); - vlc_value_t *val_list; - size_t count; int i_ret = -1; - if( !p_input_thread ) - return -1; + vlc_player_t *player = p_mi->player; + vlc_player_Lock(player); - var_Change( p_input_thread, "video-es", VLC_VAR_GETCHOICES, - &count, &val_list, (char ***)NULL ); + size_t count = vlc_player_GetVideoTrackCount(player); for( size_t i = 0; i < count; i++ ) { - if( i_track == val_list[i].i_int ) + const struct vlc_player_track *track = + vlc_player_GetVideoTrackAt(player, i); + if (i_track == vlc_es_id_GetInputId(track->es_id)) { - if( var_SetInteger( p_input_thread, "video-es", i_track ) < 0 ) - break; + /* found */ + vlc_player_SelectTrack(player, track->es_id); i_ret = 0; goto end; } } libvlc_printerr( "Track identifier not found" ); end: - free(val_list); - input_Release(p_input_thread); + vlc_player_Unlock(player); return i_ret; } -- 2.11.4.GIT