-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9f484cb
commit c29b3be
Showing
1 changed file
with
90 additions
and
126 deletions.
There are no files selected for viewing
216 changes: 90 additions & 126 deletions
216
app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,161 +1,125 @@ | ||
package org.schabi.newpipe.player.helper; | ||
|
||
import android.animation.Animator; | ||
import android.animation.AnimatorListenerAdapter; | ||
import android.animation.ValueAnimator; | ||
import android.content.Context; | ||
import android.content.Intent; | ||
import android.media.AudioManager; | ||
import android.media.audiofx.AudioEffect; | ||
import android.util.Log; | ||
|
||
import androidx.annotation.NonNull; | ||
import androidx.core.content.ContextCompat; | ||
import androidx.media.AudioFocusRequestCompat; | ||
import androidx.media.AudioManagerCompat; | ||
|
||
import com.google.android.exoplayer2.SimpleExoPlayer; | ||
import com.google.android.exoplayer2.analytics.AnalyticsListener; | ||
|
||
public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AnalyticsListener { | ||
|
||
private static final String TAG = "AudioFocusReactor"; | ||
|
||
private static final int DUCK_DURATION = 1500; | ||
private static final float DUCK_AUDIO_TO = .2f; | ||
|
||
private static final int FOCUS_GAIN_TYPE = AudioManagerCompat.AUDIOFOCUS_GAIN; | ||
private static final int STREAM_TYPE = AudioManager.STREAM_MUSIC; | ||
|
||
private final SimpleExoPlayer player; | ||
private final Context context; | ||
private final AudioManager audioManager; | ||
|
||
private final AudioFocusRequestCompat request; | ||
|
||
public AudioReactor(@NonNull final Context context, | ||
@NonNull final SimpleExoPlayer player) { | ||
this.player = player; | ||
this.context = context; | ||
this.audioManager = ContextCompat.getSystemService(context, AudioManager.class); | ||
player.addAnalyticsListener(this); | ||
|
||
request = new AudioFocusRequestCompat.Builder(FOCUS_GAIN_TYPE) | ||
//.setAcceptsDelayedFocusGain(true) | ||
.setWillPauseWhenDucked(true) | ||
.setOnAudioFocusChangeListener(this) | ||
.build(); | ||
package org.schabi.newpipe.player.helper | ||
|
||
import android.animation.ValueAnimator | ||
import android.content.Context | ||
import android.content.Intent | ||
import android.media.AudioManager | ||
import android.media.AudioManager.OnAudioFocusChangeListener | ||
import android.media.audiofx.AudioEffect | ||
import android.util.Log | ||
import androidx.core.animation.addListener | ||
import androidx.core.content.getSystemService | ||
import androidx.media.AudioFocusRequestCompat | ||
import androidx.media.AudioManagerCompat | ||
import com.google.android.exoplayer2.SimpleExoPlayer | ||
import com.google.android.exoplayer2.analytics.AnalyticsListener | ||
import com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime | ||
|
||
class AudioReactor( | ||
private val context: Context, | ||
private val player: SimpleExoPlayer | ||
) : OnAudioFocusChangeListener, AnalyticsListener { | ||
private val audioManager = context.getSystemService<AudioManager>()!! | ||
private val request = AudioFocusRequestCompat.Builder(FOCUS_GAIN_TYPE) | ||
//.setAcceptsDelayedFocusGain(true) | ||
.setWillPauseWhenDucked(true) | ||
.setOnAudioFocusChangeListener(this) | ||
.build() | ||
|
||
init { | ||
player.addAnalyticsListener(this) | ||
} | ||
|
||
public void dispose() { | ||
abandonAudioFocus(); | ||
player.removeAnalyticsListener(this); | ||
fun dispose() { | ||
abandonAudioFocus() | ||
player.removeAnalyticsListener(this) | ||
} | ||
|
||
/*////////////////////////////////////////////////////////////////////////// | ||
// Audio Manager | ||
//////////////////////////////////////////////////////////////////////////*/ | ||
public void requestAudioFocus() { | ||
AudioManagerCompat.requestAudioFocus(audioManager, request); | ||
////////////////////////////////////////////////////////////////////////// */ | ||
fun requestAudioFocus() { | ||
AudioManagerCompat.requestAudioFocus(audioManager, request) | ||
} | ||
|
||
public void abandonAudioFocus() { | ||
AudioManagerCompat.abandonAudioFocusRequest(audioManager, request); | ||
fun abandonAudioFocus() { | ||
AudioManagerCompat.abandonAudioFocusRequest(audioManager, request) | ||
} | ||
|
||
public int getVolume() { | ||
return audioManager.getStreamVolume(STREAM_TYPE); | ||
} | ||
public void setVolume(final int volume) { | ||
audioManager.setStreamVolume(STREAM_TYPE, volume, 0); | ||
} | ||
var volume: Int | ||
get() = audioManager.getStreamVolume(STREAM_TYPE) | ||
set(volume) { | ||
audioManager.setStreamVolume(STREAM_TYPE, volume, 0) | ||
} | ||
|
||
public int getMaxVolume() { | ||
return AudioManagerCompat.getStreamMaxVolume(audioManager, STREAM_TYPE); | ||
} | ||
val maxVolume: Int | ||
get() = AudioManagerCompat.getStreamMaxVolume(audioManager, STREAM_TYPE) | ||
|
||
/*////////////////////////////////////////////////////////////////////////// | ||
// AudioFocus | ||
//////////////////////////////////////////////////////////////////////////*/ | ||
@Override | ||
public void onAudioFocusChange(final int focusChange) { | ||
Log.d(TAG, "onAudioFocusChange() called with: focusChange = [" + focusChange + "]"); | ||
switch (focusChange) { | ||
case AudioManager.AUDIOFOCUS_GAIN: | ||
onAudioFocusGain(); | ||
break; | ||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: | ||
onAudioFocusLossCanDuck(); | ||
break; | ||
case AudioManager.AUDIOFOCUS_LOSS: | ||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: | ||
onAudioFocusLoss(); | ||
break; | ||
////////////////////////////////////////////////////////////////////////// */ | ||
override fun onAudioFocusChange(focusChange: Int) { | ||
Log.d(TAG, "onAudioFocusChange() called with: focusChange = [$focusChange]") | ||
when (focusChange) { | ||
AudioManager.AUDIOFOCUS_GAIN -> onAudioFocusGain() | ||
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> onAudioFocusLossCanDuck() | ||
AudioManager.AUDIOFOCUS_LOSS, AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> onAudioFocusLoss() | ||
} | ||
} | ||
|
||
private void onAudioFocusGain() { | ||
Log.d(TAG, "onAudioFocusGain() called"); | ||
player.setVolume(DUCK_AUDIO_TO); | ||
animateAudio(DUCK_AUDIO_TO, 1.0f); | ||
private fun onAudioFocusGain() { | ||
Log.d(TAG, "onAudioFocusGain() called") | ||
player.volume = DUCK_AUDIO_TO | ||
animateAudio(DUCK_AUDIO_TO, 1.0f) | ||
if (PlayerHelper.isResumeAfterAudioFocusGain(context)) { | ||
player.play(); | ||
player.play() | ||
} | ||
} | ||
|
||
private void onAudioFocusLoss() { | ||
Log.d(TAG, "onAudioFocusLoss() called"); | ||
player.pause(); | ||
private fun onAudioFocusLoss() { | ||
Log.d(TAG, "onAudioFocusLoss() called") | ||
player.pause() | ||
} | ||
|
||
private void onAudioFocusLossCanDuck() { | ||
Log.d(TAG, "onAudioFocusLossCanDuck() called"); | ||
private fun onAudioFocusLossCanDuck() { | ||
Log.d(TAG, "onAudioFocusLossCanDuck() called") | ||
// Set the volume to 1/10 on ducking | ||
player.setVolume(DUCK_AUDIO_TO); | ||
player.volume = DUCK_AUDIO_TO | ||
} | ||
|
||
private void animateAudio(final float from, final float to) { | ||
final ValueAnimator valueAnimator = new ValueAnimator(); | ||
valueAnimator.setFloatValues(from, to); | ||
valueAnimator.setDuration(AudioReactor.DUCK_DURATION); | ||
valueAnimator.addListener(new AnimatorListenerAdapter() { | ||
@Override | ||
public void onAnimationStart(final Animator animation) { | ||
player.setVolume(from); | ||
} | ||
@Override | ||
public void onAnimationCancel(final Animator animation) { | ||
player.setVolume(to); | ||
} | ||
@Override | ||
public void onAnimationEnd(final Animator animation) { | ||
player.setVolume(to); | ||
} | ||
}); | ||
valueAnimator.addUpdateListener(animation -> | ||
player.setVolume(((float) animation.getAnimatedValue()))); | ||
valueAnimator.start(); | ||
private fun animateAudio(from: Float, to: Float) { | ||
val valueAnimator = ValueAnimator() | ||
valueAnimator.setFloatValues(from, to) | ||
valueAnimator.duration = DUCK_DURATION.toLong() | ||
valueAnimator.addListener( | ||
onStart = { player.volume = from }, | ||
onCancel = { player.volume = to }, | ||
onEnd = { player.volume = to } | ||
) | ||
valueAnimator.addUpdateListener { animation: ValueAnimator -> | ||
player.volume = animation.animatedValue as Float | ||
} | ||
valueAnimator.start() | ||
} | ||
|
||
/*////////////////////////////////////////////////////////////////////////// | ||
// Audio Processing | ||
//////////////////////////////////////////////////////////////////////////*/ | ||
@Override | ||
public void onAudioSessionId(final EventTime eventTime, final int audioSessionId) { | ||
////////////////////////////////////////////////////////////////////////// */ | ||
override fun onAudioSessionId(eventTime: EventTime, audioSessionId: Int) { | ||
if (!PlayerHelper.isUsingDSP()) { | ||
return; | ||
return | ||
} | ||
val intent = Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) | ||
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, audioSessionId) | ||
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.packageName) | ||
context.sendBroadcast(intent) | ||
} | ||
|
||
final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION); | ||
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, audioSessionId); | ||
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName()); | ||
context.sendBroadcast(intent); | ||
companion object { | ||
private const val TAG = "AudioFocusReactor" | ||
private const val DUCK_DURATION = 1500 | ||
private const val DUCK_AUDIO_TO = .2f | ||
private const val FOCUS_GAIN_TYPE = AudioManagerCompat.AUDIOFOCUS_GAIN | ||
private const val STREAM_TYPE = AudioManager.STREAM_MUSIC | ||
} | ||
} |