package com.netease.nim.uikit.common.media.audioplayer;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.text.TextUtils;
import com.netease.nim.uikit.R;
import com.netease.nim.uikit.common.util.log.LogUtil;
import com.netease.nimlib.sdk.media.player.AudioPlayer;
import com.netease.nimlib.sdk.media.player.OnPlayListener;
abstract public class BaseAudioControl<T> {
interface AudioControllerState {
int stop = 0;
int ready = 1;
int playing = 2;
}
private int state;
protected boolean isEarPhoneModeEnable = true; // 是否是听筒模式
public interface AudioControlListener {
//AudioControl准备就绪,已经postDelayed playRunnable,不等同于AudioPlayer已经开始播放
public void onAudioControllerReady(Playable playable);
/**
* 结束播放
*/
public void onEndPlay(Playable playable);
/**
* 显示播放过程中的进度条
* @param curPosition 当前进度,如果传-1则自动获取进度
*/
public void updatePlayingProgress(Playable playable, long curPosition);
}
protected AudioControlListener audioControlListener;
protected Context mContext;
protected AudioPlayer currentAudioPlayer;
protected Playable currentPlayable;
protected boolean needSeek = false;
protected long seekPosition;
private MediaPlayer mSuffixPlayer = null;
private boolean mSuffix = false;
protected Handler mHandler = new Handler();
private BasePlayerListener basePlayerListener = null;
protected void setOnPlayListener(Playable playingPlayable, AudioControlListener audioControlListener) {
this.audioControlListener = audioControlListener;
basePlayerListener = new BasePlayerListener(currentAudioPlayer, playingPlayable);
currentAudioPlayer.setOnPlayListener(basePlayerListener);
basePlayerListener.setAudioControlListener(audioControlListener);
}
public void setEarPhoneModeEnable(boolean isEarPhoneModeEnable) {
this.isEarPhoneModeEnable = isEarPhoneModeEnable;
if (isEarPhoneModeEnable) {
updateAudioStreamType(AudioManager.STREAM_VOICE_CALL);
} else {
updateAudioStreamType(AudioManager.STREAM_MUSIC);
}
}
@SuppressWarnings("unchecked")
public void changeAudioControlListener(AudioControlListener audioControlListener) {
this.audioControlListener = audioControlListener;
if (isPlayingAudio()) {
OnPlayListener onPlayListener = currentAudioPlayer.getOnPlayListener();
if (onPlayListener != null) {
((BasePlayerListener) onPlayListener).setAudioControlListener(audioControlListener);
}
}
}
public AudioControlListener getAudioControlListener() {
return audioControlListener;
}
public BaseAudioControl(Context context, boolean suffix) {
this.mContext = context;
this.mSuffix = suffix;
}
protected void playSuffix() {
if(mSuffix) {
mSuffixPlayer = MediaPlayer.create(mContext, R.raw.audio_end_tip);
mSuffixPlayer.setLooping(false);
mSuffixPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mSuffixPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mSuffixPlayer.release();
mSuffixPlayer = null;
}
});
mSuffixPlayer.start();
}
}
protected boolean startAudio(
Playable playable,
AudioControlListener audioControlListener,
int audioStreamType,
boolean resetOrigAudioStreamType,
long delayMillis)
{
String filePath = playable.getPath();
if(TextUtils.isEmpty(filePath)) {
return false;
}
//正在播放,停止播放
if(isPlayingAudio()) {
stopAudio();
//如果相等,就是同一个对象了
if(currentPlayable.isAudioEqual(playable)) {
return false;
}
}
state = AudioControllerState.stop;
currentPlayable = playable;
currentAudioPlayer = new AudioPlayer(mContext);
currentAudioPlayer.setDataSource(filePath);
setOnPlayListener(currentPlayable, audioControlListener);
if (resetOrigAudioStreamType) {
this.origAudioStreamType = audioStreamType;
}
this.currentAudioStreamType = audioStreamType;
mHandler.postDelayed(playRunnable, delayMillis);
state = AudioControllerState.ready;
if (audioControlListener != null) {
audioControlListener.onAudioControllerReady(currentPlayable);
}
return true;
}
Runnable playRunnable = new Runnable() {
@Override
public void run() {
if (currentAudioPlayer == null) {
LogUtil.audio("playRunnable run when currentAudioPlayer == null");
return;
}
currentAudioPlayer.start(currentAudioStreamType);
}
};
private int origAudioStreamType;
private int currentAudioStreamType;
public int getCurrentAudioStreamType() {
return currentAudioStreamType;
}
protected int getUserSettingAudioStreamType() {
// 听筒模式/扬声器模式
if (isEarPhoneModeEnable) {
return AudioManager.STREAM_VOICE_CALL;
} else {
return AudioManager.STREAM_MUSIC;
}
}
protected void resetAudioController(Playable playable) {
currentAudioPlayer.setOnPlayListener(null);
currentAudioPlayer = null;
state = AudioControllerState.stop;
}
//playing or ready
public boolean isPlayingAudio() {
if(currentAudioPlayer != null) {
return state == AudioControllerState.playing
|| state == AudioControllerState.ready;
} else {
return false;
}
}
//stop or cancel
public void stopAudio() {
if (state == AudioControllerState.playing) {
//playing->stop
currentAudioPlayer.stop();
} else if (state == AudioControllerState.ready) {
//ready->cancel
mHandler.removeCallbacks(playRunnable);
resetAudioController(currentPlayable);
if (audioControlListener != null) {
audioControlListener.onEndPlay(currentPlayable);
}
}
}
public boolean updateAudioStreamType(int audioStreamType) {
if(!isPlayingAudio()) {
return false;
}
if (audioStreamType == getCurrentAudioStreamType()) {
return false;
}
changeAudioStreamType(audioStreamType);
return true;
}
public boolean restoreAudioStreamType() {
if(!isPlayingAudio()) {
return false;
}
if (origAudioStreamType == getCurrentAudioStreamType()) {
return false;
}
changeAudioStreamType(origAudioStreamType);
return true;
}
private void changeAudioStreamType(int audioStreamType) {
if (currentAudioPlayer.isPlaying()) {
seekPosition = currentAudioPlayer.getCurrentPosition();
needSeek = true;
currentAudioStreamType = audioStreamType;
currentAudioPlayer.start(audioStreamType);
} else {
currentAudioStreamType = origAudioStreamType;
}
}
public class BasePlayerListener implements OnPlayListener {
protected AudioPlayer listenerPlayingAudioPlayer;
protected Playable listenerPlayingPlayable;
protected AudioControlListener audioControlListener;
public BasePlayerListener(AudioPlayer playingAudioPlayer, Playable playingPlayable) {
listenerPlayingAudioPlayer = playingAudioPlayer;
listenerPlayingPlayable = playingPlayable;
}
public void setAudioControlListener(AudioControlListener audioControlListener) {
this.audioControlListener = audioControlListener;
}
protected boolean checkAudioPlayerValid() {
if (currentAudioPlayer != listenerPlayingAudioPlayer) {
return false;
}
return true;
}
@Override
public void onPrepared() {
if (!checkAudioPlayerValid()) {
return;
}
state = AudioControllerState.playing;
if (needSeek) {
needSeek = false;
listenerPlayingAudioPlayer.seekTo((int) seekPosition);
}
}
@Override
public void onPlaying(long curPosition) {
if (!checkAudioPlayerValid()) {
return;
}
if (audioControlListener != null) {
audioControlListener.updatePlayingProgress(listenerPlayingPlayable, curPosition);
}
}
@Override
public void onInterrupt() {
if (!checkAudioPlayerValid()) {
return;
}
resetAudioController(listenerPlayingPlayable);
if (audioControlListener != null) {
audioControlListener.onEndPlay(currentPlayable);
}
}
@Override
public void onError(String error) {
if (!checkAudioPlayerValid()) {
return;
}
resetAudioController(listenerPlayingPlayable);
if (audioControlListener != null) {
audioControlListener.onEndPlay(currentPlayable);
}
}
@Override
public void onCompletion() {
if (!checkAudioPlayerValid()) {
return;
}
resetAudioController(listenerPlayingPlayable);
if (audioControlListener != null) {
audioControlListener.onEndPlay(currentPlayable);
}
playSuffix();
}
};
public void startPlayAudio(
T t,
AudioControlListener audioControlListener) {
startPlayAudio(t, audioControlListener, getUserSettingAudioStreamType());
}
public void startPlayAudio(
T t,
AudioControlListener audioControlListener,
int audioStreamType) {
startPlayAudioDelay(0, t, audioControlListener, audioStreamType);
}
public void startPlayAudioDelay(long delayMillis, T t, AudioControlListener audioControlListener) {
startPlayAudioDelay(delayMillis, t, audioControlListener, getUserSettingAudioStreamType());
}
public abstract void startPlayAudioDelay(long delayMillis, T t, AudioControlListener audioControlListener, int audioStreamType);
public abstract T getPlayingAudio();
}