[vlc-devel] [PATCH] Audiotrack: Hardware volume management

Geoffrey Métais geoffrey.metais at gmail.com
Mon Nov 26 15:36:08 CET 2018


This allows proper ducking during notifications on Android
---
 modules/audio_output/audiotrack.c | 99 +++++++++++++++++++++++++++++--
 1 file changed, 94 insertions(+), 5 deletions(-)

diff --git a/modules/audio_output/audiotrack.c b/modules/audio_output/audiotrack.c
index 238826bb95..04a7305887 100644
--- a/modules/audio_output/audiotrack.c
+++ b/modules/audio_output/audiotrack.c
@@ -80,13 +80,12 @@ static const struct {
 };
 
 struct aout_sys_t {
-    /* sw gain */
-    float soft_gain;
-    bool soft_mute;
 
     enum at_dev at_dev;
 
     jobject p_audiotrack; /* AudioTrack ref */
+    float volume;
+    bool mute;
 
     audio_sample_format_t fmt; /* fmt setup by Start */
 
@@ -218,6 +217,9 @@ static struct
         jmethodID getTimestamp;
         jmethodID getMinBufferSize;
         jmethodID getNativeOutputSampleRate;
+        jmethodID getMaxVolume;
+        jmethodID setVolume;
+        jmethodID setStereoVolume;
         jint STATE_INITIALIZED;
         jint MODE_STREAM;
         jint ERROR;
@@ -358,6 +360,13 @@ InitJNIFields( audio_output_t *p_aout, JNIEnv* env )
     GET_ID( GetStaticMethodID, AudioTrack.getNativeOutputSampleRate,
             "getNativeOutputSampleRate",  "(I)I", true );
 #endif
+    GET_ID( GetStaticMethodID, AudioTrack.getMaxVolume,
+            "getMaxVolume",  "()F", true );
+    GET_ID( GetMethodID, AudioTrack.setVolume,
+            "setVolume",  "(F)I", true );
+    if( !jfields.AudioTrack.setVolume )
+        GET_ID( GetMethodID, AudioTrack.setStereoVolume,
+                "setStereoVolume",  "(FF)I", true );
     GET_CONST_INT( AudioTrack.STATE_INITIALIZED, "STATE_INITIALIZED", true );
     GET_CONST_INT( AudioTrack.MODE_STREAM, "MODE_STREAM", true );
     GET_CONST_INT( AudioTrack.ERROR, "ERROR", true );
@@ -495,6 +504,7 @@ check_exception( JNIEnv *env, audio_output_t *p_aout,
 #define JNI_AT_CALL_BOOL( method, ... ) JNI_CALL_BOOL( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
 #define JNI_AT_CALL_VOID( method, ... ) JNI_CALL_VOID( p_sys->p_audiotrack, jfields.AudioTrack.method, ##__VA_ARGS__ )
 #define JNI_AT_CALL_STATIC_INT( method, ... ) JNI_CALL( CallStaticIntMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
+#define JNI_AT_CALL_STATIC_FLOAT( method, ... ) JNI_CALL( CallStaticFloatMethod, jfields.AudioTrack.clazz, jfields.AudioTrack.method, ##__VA_ARGS__ )
 
 #define JNI_AUDIOTIMESTAMP_GET_LONG( field ) JNI_CALL( GetLongField, p_sys->timestamp.p_obj, jfields.AudioTimestamp.field )
 
@@ -1332,8 +1342,11 @@ Start( audio_output_t *p_aout, audio_sample_format_t *restrict p_fmt )
     CHECK_AT_EXCEPTION( "play" );
 
     *p_fmt = p_sys->fmt;
-    aout_SoftVolumeStart( p_aout );
 
+    if (p_sys->mute)
+        p_aout->mute_set(p_aout, true);
+    else
+        p_aout->volume_set(p_aout, p_sys->volume)
     aout_FormatPrint( p_aout, "VLC will output:", &p_sys->fmt );
 
     return VLC_SUCCESS;
@@ -1898,6 +1911,78 @@ bailout:
     vlc_mutex_unlock( &p_sys->lock );
 }
 
+static int
+VolumeSet( audio_output_t *p_aout, float volume )
+{
+    aout_sys_t *p_sys = p_aout->sys;
+    JNIEnv *env;
+    float gain = 1.0f;
+    if (volume > 1.f)
+    {
+        p_sys->volume = 1.f;
+        gain = volume;
+    }
+    else
+        p_sys->volume = volume;
+
+    if( p_sys->b_error || !( env = GET_ENV() ) )
+        return VLC_EGENERIC;
+    if (p_sys->p_audiotrack != NULL)
+    {
+        if( jfields.AudioTrack.setVolume )
+        {
+            JNI_AT_CALL_INT( setVolume, volume );
+            CHECK_AT_EXCEPTION( "setVolume" );
+        } else
+        {
+            JNI_AT_CALL_INT( setStereoVolume, volume, volume );
+            CHECK_AT_EXCEPTION( "setStereoVolume" );
+        }
+    }
+    aout_VolumeReport(p_aout, volume);
+    aout_GainRequest(aout, gain * gain * gain);
+    return 0;
+}
+
+static int
+MuteSet( audio_output_t *p_aout, bool mute )
+{
+    aout_sys_t *p_sys = p_aout->sys;
+    JNIEnv *env;
+    p_sys->mute = mute;
+
+    if( p_sys->b_error || !( env = GET_ENV() ) )
+        return VLC_EGENERIC;
+    if (p_sys->p_audiotrack != NULL)
+    {
+        if( jfields.AudioTrack.setVolume )
+        {
+            JNI_AT_CALL_INT( setVolume, mute ? 0.0f : p_sys->volume );
+            CHECK_AT_EXCEPTION( "setVolume" );
+        } else
+        {
+            JNI_AT_CALL_INT( setStereoVolume, mute ? 0.0f : p_sys->volume, mute ? 0.0f : p_sys->volume );
+            CHECK_AT_EXCEPTION( "setStereoVolume" );
+        }
+    }
+    aout_MuteReport(aout, mute);
+    return 0;
+}
+
+static float
+getMaxVolume( audio_output_t *p_aout)
+{
+    aout_sys_t *p_sys = p_aout->sys;
+    JNIEnv *env;
+
+    if( p_sys->b_error || !( env = GET_ENV() ) )
+        return VLC_EGENERIC;
+
+    float ret = JNI_AT_CALL_STATIC_FLOAT( getMaxVolume );
+    CHECK_AT_EXCEPTION( "getMaxVolume" );
+    return ret;
+}
+
 static int DeviceSelect(audio_output_t *p_aout, const char *p_id)
 {
     aout_sys_t *p_sys = p_aout->sys;
@@ -1981,7 +2066,11 @@ Open( vlc_object_t *obj )
     for( unsigned int i = 0; at_devs[i].id; ++i )
         aout_HotplugReport(p_aout, at_devs[i].id, at_devs[i].name);
 
-    aout_SoftVolumeInit( p_aout );
+    msg_Dbg( p_aout, "max_volume: %f", getMaxVolume(p_aout));
+    p_aout->volume_set = VolumeSet;
+    p_aout->mute_set = MuteSet;
+    p_sys->volume = 1.0f;
+    p_sys->mute = false;
 
     return VLC_SUCCESS;
 }
-- 
2.17.1



More information about the vlc-devel mailing list