X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=lib%2Fmedia_player.c;h=c2bb7c22f862084bc9730d1f606b541f96ac4f8b;hb=6e3efa23762b387a463ac64091b34d3c90964c7f;hp=14d5bcea4c932697860e7a5a18de5ea13bad9898;hpb=2f6eb75c0d317e521e201e3a61a0b0642ee9e552;p=vlc diff --git a/lib/media_player.c b/lib/media_player.c index 14d5bcea4c..c2bb7c22f8 100644 --- a/lib/media_player.c +++ b/lib/media_player.c @@ -1,23 +1,23 @@ /***************************************************************************** * media_player.c: Libvlc API Media Instance management functions ***************************************************************************** - * Copyright (C) 2005-2011 the VideoLAN team + * Copyright (C) 2005-2011 VLC authors and VideoLAN * * Authors: Clément Stenac * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #ifdef HAVE_CONFIG_H @@ -33,28 +33,13 @@ #include #include #include +#include #include #include "libvlc_internal.h" #include "media_internal.h" // libvlc_media_set_state() #include "media_player_internal.h" -/* - * mapping of libvlc_navigate_mode_t to vlc_action_t - */ -static const vlc_action_t libvlc_navigate_to_action[] = -{ - ACTIONID_NAV_ACTIVATE, - ACTIONID_NAV_UP, - ACTIONID_NAV_DOWN, - ACTIONID_NAV_LEFT, - ACTIONID_NAV_RIGHT -}; - -static const uint32_t libvlc_navigate_to_action_size = \ - sizeof( libvlc_navigate_to_action ) / sizeof( libvlc_navigate_to_action[0] ); - - static int input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, @@ -64,10 +49,30 @@ 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); + +static int +input_es_selected( vlc_object_t * p_this, char const * psz_cmd, + vlc_value_t oldval, vlc_value_t newval, + void * p_userdata ); + +static void +add_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi ); + +static void +del_es_callbacks( input_thread_t *p_input_thread, libvlc_media_player_t *p_mi ); + 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 ); @@ -132,8 +137,11 @@ static void release_input_thread( libvlc_media_player_t *p_mi, bool b_input_abor 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 ); /* We owned this one */ input_Stop( p_input_thread, b_input_abort ); @@ -226,6 +234,24 @@ input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd, return VLC_SUCCESS; } +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; + + event.type = libvlc_MediaPlayerScrambledChanged; + event.u.media_player_scrambled_changed.new_scrambled = newval.b_bool; + + libvlc_event_send( p_mi->p_event_manager, &event ); + return VLC_SUCCESS; +} + static int input_event_changed( vlc_object_t * p_this, char const * psz_cmd, vlc_value_t oldval, vlc_value_t newval, @@ -338,6 +364,85 @@ input_event_changed( vlc_object_t * p_this, char const * psz_cmd, return VLC_SUCCESS; } +static int track_type_from_name(const char *psz_name) +{ + 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; +} + +static int input_es_changed( vlc_object_t *p_this, + char const *psz_cmd, + int action, + vlc_value_t *p_val, + void *p_userdata ) +{ + VLC_UNUSED(p_this); + libvlc_media_player_t *mp = p_userdata; + libvlc_event_t event; + + /* Ignore the "Disable" element */ + if (p_val && p_val->i_int < 0) + return VLC_EGENERIC; + + 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; + } + + event.u.media_player_es_changed.i_type = track_type_from_name(psz_cmd); + + 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_event_send(mp->p_event_manager, &event); + + return VLC_SUCCESS; +} + +static int +input_es_selected( vlc_object_t * p_this, char const * psz_cmd, + vlc_value_t oldval, vlc_value_t newval, + void * p_userdata ) +{ + VLC_UNUSED(p_this); + VLC_UNUSED(oldval); + libvlc_media_player_t *mp = p_userdata; + libvlc_event_t event; + + event.type = libvlc_MediaPlayerESSelected; + event.u.media_player_es_changed.i_type = track_type_from_name(psz_cmd); + event.u.media_player_es_changed.i_id = newval.i_int; + + libvlc_event_send(mp->p_event_manager, &event); + + return VLC_SUCCESS; +} + /************************************************************************** * Snapshot Taken Event. * @@ -357,13 +462,6 @@ static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd, return VLC_SUCCESS; } -static input_thread_t *find_input (vlc_object_t *obj) -{ - libvlc_media_player_t *mp = (libvlc_media_player_t *)obj; - - return libvlc_get_input_thread (mp); -} - /* */ static void libvlc_media_player_destroy( libvlc_media_player_t * ); @@ -413,7 +511,7 @@ libvlc_media_player_new( libvlc_instance_t *instance ) var_Create (mp, "vmem-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); var_Create (mp, "vmem-pitch", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); var_Create (mp, "drawable-xid", VLC_VAR_INTEGER); -#if defined (WIN32) || defined (__OS2__) +#if defined (_WIN32) || defined (__OS2__) var_Create (mp, "drawable-hwnd", VLC_VAR_INTEGER); #endif #ifdef __APPLE__ @@ -465,9 +563,9 @@ libvlc_media_player_new( libvlc_instance_t *instance ) /* Audio */ var_Create (mp, "aout", VLC_VAR_STRING | VLC_VAR_DOINHERIT); var_Create (mp, "mute", VLC_VAR_BOOL); - var_Create (mp, "volume", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); - var_Create (mp, "find-input-callback", VLC_VAR_ADDRESS); - var_SetAddress (mp, "find-input-callback", find_input); + var_Create (mp, "volume", VLC_VAR_FLOAT); + var_Create (mp, "corks", VLC_VAR_INTEGER); + var_Create (mp, "audio-filter", VLC_VAR_STRING); var_Create (mp, "amem-data", VLC_VAR_ADDRESS); var_Create (mp, "amem-setup", VLC_VAR_ADDRESS); var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS); @@ -481,16 +579,36 @@ libvlc_media_player_new( libvlc_instance_t *instance ) var_Create (mp, "amem-rate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); var_Create (mp, "amem-channels", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); + /* Video Title */ + var_Create (mp, "video-title-show", VLC_VAR_BOOL); + var_Create (mp, "video-title-position", VLC_VAR_INTEGER); + var_Create (mp, "video-title-timeout", VLC_VAR_INTEGER); + + /* Equalizer */ + var_Create (mp, "equalizer-preamp", VLC_VAR_FLOAT); + var_Create (mp, "equalizer-vlcfreqs", VLC_VAR_BOOL); + var_Create (mp, "equalizer-bands", VLC_VAR_STRING); + mp->p_md = NULL; mp->state = libvlc_NothingSpecial; mp->p_libvlc_instance = instance; mp->input.p_thread = NULL; - mp->input.p_resource = NULL; + mp->input.p_resource = input_resource_New(VLC_OBJECT(mp)); + if (unlikely(mp->input.p_resource == NULL)) + { + vlc_object_release(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); + vlc_mutex_init (&mp->input.lock); mp->i_refcount = 1; mp->p_event_manager = libvlc_event_manager_new(mp, instance); if (unlikely(mp->p_event_manager == NULL)) { + input_resource_Release(mp->input.p_resource); vlc_object_release(mp); return NULL; } @@ -515,6 +633,10 @@ libvlc_media_player_new( libvlc_instance_t *instance ) register_event(mp, PausableChanged); register_event(mp, Vout); + register_event(mp, ScrambledChanged); + register_event(mp, ESAdded); + register_event(mp, ESDeleted); + register_event(mp, ESSelected); /* Snapshot initialization */ register_event(mp, SnapshotTaken); @@ -568,12 +690,8 @@ static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi ) /* No need for lock_input() because no other threads knows us anymore */ if( p_mi->input.p_thread ) release_input_thread(p_mi, true); - if( p_mi->input.p_resource ) - { - input_resource_Terminate( p_mi->input.p_resource ); - input_resource_Release( p_mi->input.p_resource ); - p_mi->input.p_resource = NULL; - } + input_resource_Terminate( p_mi->input.p_resource ); + input_resource_Release( p_mi->input.p_resource ); vlc_mutex_destroy( &p_mi->input.lock ); libvlc_event_manager_release( p_mi->p_event_manager ); @@ -673,12 +791,13 @@ libvlc_media_player_get_media( libvlc_media_player_t *p_mi ) { libvlc_media_t *p_m; - lock(p_mi); + lock( p_mi ); p_m = p_mi->p_md; if( p_m ) - libvlc_media_retain( p_mi->p_md ); - unlock(p_mi); - return p_mi->p_md; + libvlc_media_retain( p_m ); + unlock( p_mi ); + + return p_m; } /************************************************************************** @@ -690,6 +809,26 @@ libvlc_media_player_event_manager( libvlc_media_player_t *p_mi ) return p_mi->p_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 ); + var_AddCallback( p_input_thread, "video-es", input_es_selected, p_mi ); + var_AddCallback( p_input_thread, "audio-es", input_es_selected, p_mi ); + var_AddCallback( p_input_thread, "spu-es", input_es_selected, 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 ); + var_DelCallback( p_input_thread, "video-es", input_es_selected, p_mi ); + var_DelCallback( p_input_thread, "audio-es", input_es_selected, p_mi ); + var_DelCallback( p_input_thread, "spu-es", input_es_selected, p_mi ); +} + /************************************************************************** * Tell media player to start playing. **************************************************************************/ @@ -717,8 +856,6 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi ) return -1; } - if( !p_mi->input.p_resource ) - p_mi->input.p_resource = input_resource_New( VLC_OBJECT( p_mi ) ); p_input_thread = input_Create( p_mi, p_mi->p_md->p_input_item, NULL, p_mi->input.p_resource ); unlock(p_mi); @@ -731,13 +868,17 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi ) 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 ); vlc_object_release( p_input_thread ); libvlc_printerr( "Input initialization failure" ); @@ -762,7 +903,7 @@ void libvlc_media_player_set_pause( libvlc_media_player_t *p_mi, int paused ) if( libvlc_media_player_can_pause( p_mi ) ) input_Control( p_input_thread, INPUT_SET_STATE, PAUSE_S ); else - libvlc_media_player_stop( p_mi ); + input_Stop( p_input_thread, true ); } } else @@ -818,8 +959,7 @@ void libvlc_media_player_stop( libvlc_media_player_t *p_mi ) libvlc_event_send( p_mi->p_event_manager, &event ); } - if( p_mi->input.p_resource != NULL ) - input_resource_Terminate( p_mi->input.p_resource ); + input_resource_Terminate( p_mi->input.p_resource ); unlock_input(p_mi); } @@ -935,7 +1075,7 @@ void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi, void *drawable ) { assert (p_mi != NULL); -#if defined (WIN32) || defined (__OS2__) +#if defined (_WIN32) || defined (__OS2__) var_SetString (p_mi, "window", (drawable != NULL) ? "embed-hwnd,any" : ""); var_SetInteger (p_mi, "drawable-hwnd", (uintptr_t)drawable); @@ -950,7 +1090,7 @@ void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi, void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi ) { assert (p_mi != NULL); -#if defined (WIN32) || defined (__OS2__) +#if defined (_WIN32) || defined (__OS2__) return (void *)(uintptr_t)var_GetInteger (p_mi, "drawable-hwnd"); #else return NULL; @@ -972,12 +1112,16 @@ 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, @@ -986,6 +1130,8 @@ 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, @@ -994,6 +1140,8 @@ 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); } @@ -1108,10 +1256,10 @@ int libvlc_media_player_get_chapter_count( libvlc_media_player_t *p_mi ) if( !p_input_thread ) return -1; - var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL ); + int i_ret = var_Change( p_input_thread, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL ); vlc_object_release( p_input_thread ); - return val.i_int; + return i_ret == VLC_SUCCESS ? val.i_int : -1; } int libvlc_media_player_get_chapter_count_for_title( @@ -1131,11 +1279,11 @@ int libvlc_media_player_get_chapter_count_for_title( vlc_object_release( p_input_thread ); return -1; } - var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL ); + int i_ret = var_Change( p_input_thread, psz_name, VLC_VAR_CHOICESCOUNT, &val, NULL ); vlc_object_release( p_input_thread ); free( psz_name ); - return val.i_int; + return i_ret == VLC_SUCCESS ? val.i_int : -1; } void libvlc_media_player_set_title( libvlc_media_player_t *p_mi, @@ -1181,10 +1329,10 @@ int libvlc_media_player_get_title_count( libvlc_media_player_t *p_mi ) if( !p_input_thread ) return -1; - var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL ); + int i_ret = var_Change( p_input_thread, "title", VLC_VAR_CHOICESCOUNT, &val, NULL ); vlc_object_release( p_input_thread ); - return val.i_int; + return i_ret == VLC_SUCCESS ? val.i_int : -1; } void libvlc_media_player_next_chapter( libvlc_media_player_t *p_mi ) @@ -1239,7 +1387,7 @@ int libvlc_media_player_will_play( libvlc_media_player_t *p_mi ) if ( !p_input_thread ) return false; - b_will_play = !p_input_thread->b_die && !p_input_thread->b_dead; + b_will_play = !p_input_thread->b_dead; vlc_object_release( p_input_thread ); return b_will_play; @@ -1247,12 +1395,6 @@ int libvlc_media_player_will_play( libvlc_media_player_t *p_mi ) int libvlc_media_player_set_rate( libvlc_media_player_t *p_mi, float rate ) { - if (rate < 0.) - { - libvlc_printerr ("Playing backward not supported"); - return -1; - } - var_SetFloat (p_mi, "rate", rate); input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi ); @@ -1293,19 +1435,21 @@ int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi ) void libvlc_media_player_navigate( libvlc_media_player_t* p_mi, unsigned navigate ) { - input_thread_t *p_input_thread; + static const vlc_action_t map[] = + { + INPUT_NAV_ACTIVATE, INPUT_NAV_UP, INPUT_NAV_DOWN, + INPUT_NAV_LEFT, INPUT_NAV_RIGHT, + }; - if ( navigate > libvlc_navigate_to_action_size) + if( navigate >= sizeof(map) / sizeof(map[0]) ) return; - p_input_thread = libvlc_get_input_thread ( p_mi ); - if ( !p_input_thread ) + input_thread_t *p_input = libvlc_get_input_thread ( p_mi ); + if ( p_input == NULL ) return; - var_SetInteger( p_mi->p_libvlc_instance->p_libvlc_int, - "key-action", libvlc_navigate_to_action[navigate] ); - - vlc_object_release( p_input_thread ); + input_Control( p_input, map[navigate], NULL ); + vlc_object_release( p_input ); } /* internal function, used by audio, video */ @@ -1321,7 +1465,9 @@ libvlc_track_description_t * return NULL; vlc_value_t val_list, text_list; - var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list); + int i_ret = var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list ); + if( i_ret != VLC_SUCCESS ) + return NULL; /* no tracks */ if( val_list.p_list->i_count <= 0 ) @@ -1399,6 +1545,20 @@ int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi ) return b_can_pause; } +int libvlc_media_player_program_scrambled( libvlc_media_player_t *p_mi ) +{ + input_thread_t *p_input_thread; + bool b_program_scrambled; + + 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" ); + vlc_object_release( p_input_thread ); + + 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 ); @@ -1408,3 +1568,81 @@ void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi ) vlc_object_release( p_input_thread ); } } + +/** + * Private lookup table to get subpicture alignment flag values corresponding + * to a libvlc_position_t enumerated value. + */ +static const unsigned char position_subpicture_alignment[] = { + [libvlc_position_center] = 0, + [libvlc_position_left] = SUBPICTURE_ALIGN_LEFT, + [libvlc_position_right] = SUBPICTURE_ALIGN_RIGHT, + [libvlc_position_top] = SUBPICTURE_ALIGN_TOP, + [libvlc_position_top_left] = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT, + [libvlc_position_top_right] = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_RIGHT, + [libvlc_position_bottom] = SUBPICTURE_ALIGN_BOTTOM, + [libvlc_position_bottom_left] = SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_LEFT, + [libvlc_position_bottom_right] = SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_RIGHT +}; + +void libvlc_media_player_set_video_title_display( libvlc_media_player_t *p_mi, libvlc_position_t position, unsigned timeout ) +{ + assert( position >= libvlc_position_disable && position <= libvlc_position_bottom_right ); + + if ( position != libvlc_position_disable ) + { + var_SetBool( p_mi, "video-title-show", true ); + var_SetInteger( p_mi, "video-title-position", position_subpicture_alignment[position] ); + var_SetInteger( p_mi, "video-title-timeout", timeout ); + } + else + { + var_SetBool( p_mi, "video-title-show", false ); + } +} + +/** + * Maximum size of a formatted equalizer amplification band frequency value. + * + * The allowed value range is supposed to be constrained from -20.0 to 20.0. + * + * The format string " %.07f" with a minimum value of "-20" gives a maximum + * string length of e.g. " -19.1234567", i.e. 12 bytes (not including the null + * terminator). + */ +#define EQZ_BAND_VALUE_SIZE 12 + +int libvlc_media_player_set_equalizer( libvlc_media_player_t *p_mi, libvlc_equalizer_t *p_equalizer ) +{ + char bands[EQZ_BANDS_MAX * EQZ_BAND_VALUE_SIZE + 1]; + + if( p_equalizer != NULL ) + { + for( unsigned i = 0, c = 0; i < EQZ_BANDS_MAX; i++ ) + { + c += snprintf( bands + c, sizeof(bands) - c, " %.07f", + p_equalizer->f_amp[i] ); + if( unlikely(c >= sizeof(bands)) ) + return -1; + } + + var_SetFloat( p_mi, "equalizer-preamp", p_equalizer->f_preamp ); + var_SetString( p_mi, "equalizer-bands", bands ); + } + var_SetString( p_mi, "audio-filter", p_equalizer ? "equalizer" : "" ); + + audio_output_t *p_aout = input_resource_HoldAout( p_mi->input.p_resource ); + if( p_aout != NULL ) + { + if( p_equalizer != NULL ) + { + var_SetFloat( p_aout, "equalizer-preamp", p_equalizer->f_preamp ); + var_SetString( p_aout, "equalizer-bands", bands ); + } + + var_SetString( p_aout, "audio-filter", p_equalizer ? "equalizer" : "" ); + vlc_object_release( p_aout ); + } + + return 0; +}