From: RĂ©mi Denis-Courmont Date: Wed, 8 Aug 2012 15:48:35 +0000 (+0300) Subject: playlist: add simple corking infrastructure for audio policy X-Git-Tag: 2.1.0-git~3517 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=046570ac9a35bc0e6e49c59a6bbb5ab86c634ee5;p=vlc playlist: add simple corking infrastructure for audio policy Depending on the system, this can be called ducking, focus, policy... But it basically boils down to pausing playback automatically when a higher priority audio stream starts, typically a voice call. Resuming playback automatically when communications are over would be possible as well. But that seems unfriendly to me, so I skipped it. --- diff --git a/include/vlc_aout.h b/include/vlc_aout.h index 4c7a44da9b..47630274b6 100644 --- a/include/vlc_aout.h +++ b/include/vlc_aout.h @@ -155,6 +155,7 @@ struct audio_output struct { void (*volume_report)(audio_output_t *, float); void (*mute_report)(audio_output_t *, bool); + void (*policy_report)(audio_output_t *, bool); int (*gain_request)(audio_output_t *, float); } event; }; @@ -233,6 +234,11 @@ static inline void aout_MuteReport(audio_output_t *aout, bool mute) aout->event.mute_report(aout, mute); } +static inline void aout_PolicyReport(audio_output_t *aout, bool cork) +{ + aout->event.policy_report(aout, cork); +} + static inline int aout_GainRequest(audio_output_t *aout, float gain) { return aout->event.gain_request(aout, gain); diff --git a/lib/media_player.c b/lib/media_player.c index f30f18404f..a41b8c7cc7 100644 --- a/lib/media_player.c +++ b/lib/media_player.c @@ -468,6 +468,7 @@ libvlc_media_player_new( libvlc_instance_t *instance ) var_Create (mp, "volume", VLC_VAR_FLOAT); var_Create (mp, "find-input-callback", VLC_VAR_ADDRESS); var_SetAddress (mp, "find-input-callback", find_input); + var_Create (mp, "corks", VLC_VAR_INTEGER); var_Create (mp, "amem-data", VLC_VAR_ADDRESS); var_Create (mp, "amem-setup", VLC_VAR_ADDRESS); var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS); diff --git a/src/audio_output/output.c b/src/audio_output/output.c index 4e81e160e6..a43473a307 100644 --- a/src/audio_output/output.c +++ b/src/audio_output/output.c @@ -56,6 +56,11 @@ static void aout_OutputMuteReport (audio_output_t *aout, bool mute) var_SetBool (aout, "mute", mute); } +static void aout_OutputPolicyReport (audio_output_t *aout, bool cork) +{ + (cork ? var_IncInteger : var_DecInteger) (aout->p_parent, "corks"); +} + static int aout_OutputGainRequest (audio_output_t *aout, float gain) { aout_owner_t *owner = aout_owner (aout); @@ -82,6 +87,7 @@ int aout_OutputNew( audio_output_t *p_aout, p_aout->event.volume_report = aout_OutputVolumeReport; p_aout->event.mute_report = aout_OutputMuteReport; + p_aout->event.policy_report = aout_OutputPolicyReport; p_aout->event.gain_request = aout_OutputGainRequest; /* Find the best output plug-in. */ diff --git a/src/libvlc-module.c b/src/libvlc-module.c index 7b6e2f92cd..f1ef74ce45 100644 --- a/src/libvlc-module.c +++ b/src/libvlc-module.c @@ -1184,6 +1184,11 @@ static const char *const ppsz_albumart_descriptions[] = #define AUTOSTART_LONGTEXT N_( "Automatically start playing the playlist " \ "content once it's loaded." ) +#define CORK_TEXT N_("Pause on audio communication") +#define CORK_LONGTEXT N_( \ + "If pending audio communication is detected, playback will be paused " \ + "automatically." ) + #define ML_TEXT N_("Use media library") #define ML_LONGTEXT N_( \ "The media library is automatically saved and reloaded each time you " \ @@ -2048,6 +2053,7 @@ vlc_module_begin () change_safe() add_bool( "playlist-autostart", true, AUTOSTART_TEXT, AUTOSTART_LONGTEXT, false ) + add_bool( "playlist-cork", true, CORK_TEXT, CORK_LONGTEXT, false ) add_bool( "media-library", 0, ML_TEXT, ML_LONGTEXT, false ) #if defined( MEDIA_LIBRARY ) add_bool( "load-media-library-on-startup", 1, LOAD_ML_TEXT, diff --git a/src/playlist/engine.c b/src/playlist/engine.c index 66a73aeab0..1aa8e80ed8 100644 --- a/src/playlist/engine.c +++ b/src/playlist/engine.c @@ -68,6 +68,38 @@ static int RandomCallback( vlc_object_t *p_this, char const *psz_cmd, return VLC_SUCCESS; } +/** + * When there are one or more pending corks, playback should be paused. + * This is used for audio policy. + * \warning Always add and remove a cork with var_IncInteger() and var_DecInteger(). + * var_Get() and var_Set() are prone to race conditions. + */ +static int CorksCallback( vlc_object_t *obj, char const *var, + vlc_value_t old, vlc_value_t cur, void *dummy ) +{ + playlist_t *pl = (playlist_t *)obj; + + msg_Dbg( obj, "corks count: %"PRId64" -> %"PRId64, old.i_int, cur.i_int ); + if( !old.i_int == !cur.i_int ) + return VLC_SUCCESS; /* nothing to do */ + + if( cur.i_int ) + { + if( var_InheritBool( obj, "playlist-cork" ) ) + { + msg_Dbg( obj, "corked" ); + playlist_Pause( pl ); + } + else + msg_Dbg( obj, "not corked" ); + } + else + msg_Dbg( obj, "uncorked" ); + + (void) var; (void) dummy; + return VLC_SUCCESS; +} + static int RateCallback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p ) { @@ -416,6 +448,8 @@ static void VariablesInit( playlist_t *p_playlist ) var_AddCallback( p_playlist, "random", RandomCallback, NULL ); var_Create( p_playlist, "repeat", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Create( p_playlist, "loop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); + var_Create( p_playlist, "corks", VLC_VAR_INTEGER ); + var_AddCallback( p_playlist, "corks", CorksCallback, NULL ); var_Create( p_playlist, "rate", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT ); var_AddCallback( p_playlist, "rate", RateCallback, NULL );