Commit 046570ac authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

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.
parent cb06fa8d
...@@ -155,6 +155,7 @@ struct audio_output ...@@ -155,6 +155,7 @@ struct audio_output
struct { struct {
void (*volume_report)(audio_output_t *, float); void (*volume_report)(audio_output_t *, float);
void (*mute_report)(audio_output_t *, bool); void (*mute_report)(audio_output_t *, bool);
void (*policy_report)(audio_output_t *, bool);
int (*gain_request)(audio_output_t *, float); int (*gain_request)(audio_output_t *, float);
} event; } event;
}; };
...@@ -233,6 +234,11 @@ static inline void aout_MuteReport(audio_output_t *aout, bool mute) ...@@ -233,6 +234,11 @@ static inline void aout_MuteReport(audio_output_t *aout, bool mute)
aout->event.mute_report(aout, 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) static inline int aout_GainRequest(audio_output_t *aout, float gain)
{ {
return aout->event.gain_request(aout, gain); return aout->event.gain_request(aout, gain);
......
...@@ -468,6 +468,7 @@ libvlc_media_player_new( libvlc_instance_t *instance ) ...@@ -468,6 +468,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
var_Create (mp, "volume", VLC_VAR_FLOAT); var_Create (mp, "volume", VLC_VAR_FLOAT);
var_Create (mp, "find-input-callback", VLC_VAR_ADDRESS); var_Create (mp, "find-input-callback", VLC_VAR_ADDRESS);
var_SetAddress (mp, "find-input-callback", find_input); 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-data", VLC_VAR_ADDRESS);
var_Create (mp, "amem-setup", VLC_VAR_ADDRESS); var_Create (mp, "amem-setup", VLC_VAR_ADDRESS);
var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS); var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS);
......
...@@ -56,6 +56,11 @@ static void aout_OutputMuteReport (audio_output_t *aout, bool mute) ...@@ -56,6 +56,11 @@ static void aout_OutputMuteReport (audio_output_t *aout, bool mute)
var_SetBool (aout, "mute", 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) static int aout_OutputGainRequest (audio_output_t *aout, float gain)
{ {
aout_owner_t *owner = aout_owner (aout); aout_owner_t *owner = aout_owner (aout);
...@@ -82,6 +87,7 @@ int aout_OutputNew( audio_output_t *p_aout, ...@@ -82,6 +87,7 @@ int aout_OutputNew( audio_output_t *p_aout,
p_aout->event.volume_report = aout_OutputVolumeReport; p_aout->event.volume_report = aout_OutputVolumeReport;
p_aout->event.mute_report = aout_OutputMuteReport; p_aout->event.mute_report = aout_OutputMuteReport;
p_aout->event.policy_report = aout_OutputPolicyReport;
p_aout->event.gain_request = aout_OutputGainRequest; p_aout->event.gain_request = aout_OutputGainRequest;
/* Find the best output plug-in. */ /* Find the best output plug-in. */
......
...@@ -1184,6 +1184,11 @@ static const char *const ppsz_albumart_descriptions[] = ...@@ -1184,6 +1184,11 @@ static const char *const ppsz_albumart_descriptions[] =
#define AUTOSTART_LONGTEXT N_( "Automatically start playing the playlist " \ #define AUTOSTART_LONGTEXT N_( "Automatically start playing the playlist " \
"content once it's loaded." ) "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_TEXT N_("Use media library")
#define ML_LONGTEXT N_( \ #define ML_LONGTEXT N_( \
"The media library is automatically saved and reloaded each time you " \ "The media library is automatically saved and reloaded each time you " \
...@@ -2048,6 +2053,7 @@ vlc_module_begin () ...@@ -2048,6 +2053,7 @@ vlc_module_begin ()
change_safe() change_safe()
add_bool( "playlist-autostart", true, add_bool( "playlist-autostart", true,
AUTOSTART_TEXT, AUTOSTART_LONGTEXT, false ) 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 ) add_bool( "media-library", 0, ML_TEXT, ML_LONGTEXT, false )
#if defined( MEDIA_LIBRARY ) #if defined( MEDIA_LIBRARY )
add_bool( "load-media-library-on-startup", 1, LOAD_ML_TEXT, add_bool( "load-media-library-on-startup", 1, LOAD_ML_TEXT,
......
...@@ -68,6 +68,38 @@ static int RandomCallback( vlc_object_t *p_this, char const *psz_cmd, ...@@ -68,6 +68,38 @@ static int RandomCallback( vlc_object_t *p_this, char const *psz_cmd,
return VLC_SUCCESS; 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, static int RateCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p ) vlc_value_t oldval, vlc_value_t newval, void *p )
{ {
...@@ -416,6 +448,8 @@ static void VariablesInit( playlist_t *p_playlist ) ...@@ -416,6 +448,8 @@ static void VariablesInit( playlist_t *p_playlist )
var_AddCallback( p_playlist, "random", RandomCallback, NULL ); var_AddCallback( p_playlist, "random", RandomCallback, NULL );
var_Create( p_playlist, "repeat", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); 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, "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_Create( p_playlist, "rate", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
var_AddCallback( p_playlist, "rate", RateCallback, NULL ); var_AddCallback( p_playlist, "rate", RateCallback, NULL );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment