package com.ydl.media.audio
import android.content.Context
import android.content.IntentFilter
import android.media.AudioManager
import android.os.Handler
import android.os.Looper
import com.tencent.bugly.Bugly.applicationContext
import com.ydl.media.audio.enums.PlayModeEnum
import com.ydl.media.audio.manager.AudioFocusManager
import com.ydl.media.audio.manager.MediaSessionManager
import com.ydl.media.audio.manager.NotifyManager
import com.ydl.media.audio.model.Music
import com.ydl.media.audio.receiver.NoisyAudioStreamReceiver
import com.ydl.media.audio.utils.PlayProgressUtil
import com.ydl.ydlcommon.utils.LogUtil
import com.yidianling.common.tools.ToastUtil
import tv.danmaku.ijk.media.player.IMediaPlayer
import tv.danmaku.ijk.media.player.IjkMediaPlayer
import java.io.IOException
import java.util.*
import kotlin.collections.ArrayList
/**
* Created by haorui on 2019-10-27 .
* Des:
*/
class AudioPlayer private constructor() {
private var context: Context? = null
private var audioFocusManager: AudioFocusManager? = null
var mediaPlayer: IMediaPlayer? = null
private var handler: Handler? = null
private var noisyReceiver: NoisyAudioStreamReceiver? = null
private var noisyFilter: IntentFilter? = null
private var musicList: MutableList<Music> = ArrayList()
private val listeners = ArrayList<OnPlayerEventListener>()
private var state = STATE_IDLE
private val mPublishRunnable = object : Runnable {
override fun run() {
if (isPlaying) {
val current = (mediaPlayer!!.currentPosition * 1.0).toFloat()
val du = mediaPlayer!!.duration.toFloat()
var percent = (current * 100 / du).toInt()
//保存进度
if (autoSaveProgress) {
PlayProgressUtil.saveProgress(
context,
playMusic!!.path,
(if (percent == 99 || percent == 100) 0 else current.toInt())
)
}
for (listener in listeners) {
listener.onPublish(percent, current.toLong())
}
}
handler!!.postDelayed(this, TIME_UPDATE)
}
}
val audioSessionId: Int
get() = if (mediaPlayer != null)mediaPlayer!!.audioSessionId else 0
val audioPosition: Long
get() = if (isPlaying || isPausing) {
mediaPlayer!!.currentPosition.toLong()
} else {
0
}
val playMusic: Music?
get() = if (musicList.isEmpty()) {
null
} else musicList[playPosition]
val isPlaying: Boolean
get() = state == STATE_PLAYING
val isPausing: Boolean
get() = state == STATE_PAUSE
val isPreparing: Boolean
get() = state == STATE_PREPARING
val isIdle: Boolean
get() = state == STATE_IDLE
var playPosition: Int = 0
get() {
if (field < 0 || field >= musicList.size) {
field = 0
}
return field
}
/**
* 设置播放模式
* 默认为列表循环
*/
var playMode = PlayModeEnum.LIST_LOOP
/**
* 是否自动保存播放进度
*/
var autoSaveProgress = false
/**
* 是否显示通知栏
*/
var isShowNotify = false
private object SingletonHolder {
val instance = AudioPlayer()
}
/**
* 初始化播放器
*/
fun init(context: Context) {
this.context = context.applicationContext
audioFocusManager = AudioFocusManager(context)
mediaPlayer = IjkMediaPlayer()
try {
(mediaPlayer as IjkMediaPlayer).setOption(
IjkMediaPlayer.OPT_CATEGORY_FORMAT,
"dns_cache_clear",
1
)
} catch (e: Exception) {
LogUtil.e(e.message)
}
mediaPlayer!!.setOnPreparedListener { mp ->
if (isPreparing) {
if (autoSaveProgress) {
//自动播放
var time = PlayProgressUtil.getProgress(context, playMusic!!.path)
if (time > 0) {
startPlayer()
seekTo(position = time.toLong())
} else {
startPlayer()
}
} else {
startPlayer()
}
}
for (listener in listeners) {
listener.onPrepared(mediaPlayer!!.duration)
}
}
mediaPlayer!!.setOnBufferingUpdateListener { mp, percent ->
for (listener in listeners) {
listener.onBufferingUpdate(percent)
}
}
mediaPlayer!!.setOnCompletionListener {
if (autoSaveProgress) {
PlayProgressUtil.saveProgress(applicationContext, playMusic!!.path, 0)
}
for (listener in listeners) {
listener.onComplete()
}
if (playMode == PlayModeEnum.SINGLE) {
stopPlayer()
playMode = PlayModeEnum.LIST_LOOP
return@setOnCompletionListener
}
next()
}
handler = Handler(Looper.getMainLooper())
noisyReceiver = NoisyAudioStreamReceiver()
noisyFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
}
/**
* 添加播放监听
*/
fun addOnPlayEventListener(listener: OnPlayerEventListener) {
if (!listeners.contains(listener)) {
listeners.add(listener)
}
}
/**
* 移除播放监听
*/
fun removeOnPlayEventListener(listener: OnPlayerEventListener) {
listeners.remove(listener)
}
/**
* 添加播放列表
*/
fun addPlayList(music: ArrayList<Music>) {
if (music.isEmpty()) {
return
}
musicList.clear()
musicList.addAll(music)
playMode = PlayModeEnum.LIST_LOOP
autoSaveProgress = false
}
/**
* 单曲模式播放音乐
*/
fun singlePlay(music: Music, isAutoSaveProgress: Boolean = false) {
musicList.clear()
musicList.add(music)
playMode = PlayModeEnum.SINGLE
autoSaveProgress = isAutoSaveProgress
play(0)
}
/**
* 单曲循环模式播放音乐
*/
fun singleCirclePlay(music: Music) {
musicList.clear()
musicList.add(music)
playMode = PlayModeEnum.SINGLE_LOOP
autoSaveProgress = false
play(0)
}
/**
* 添加后自动播放
*/
fun addAndPlay(music: Music) {
var position = musicList.indexOf(music)
if (position < 0) {
musicList.add(music)
position = musicList.size - 1
}
play(position)
}
/**
* 播放第一首
*/
fun play() {
play(0)
}
/**
* 加载指定索引的音乐
*/
fun play(position: Int) {
var position = position
if (musicList.isEmpty()) {
return
}
if (position < 0) {
position = musicList.size - 1
} else if (position >= musicList.size) {
position = 0
}
playPosition = position
val music = playMusic
try {
mediaPlayer!!.reset()
mediaPlayer!!.dataSource = music!!.path
mediaPlayer!!.prepareAsync()
state = STATE_PREPARING
for (listener in listeners) {
listener.onChange(music)
}
if (isShowNotify) {
NotifyManager.get().showPlay(music)
MediaSessionManager.get().updateMetaData(music)
MediaSessionManager.get().updatePlaybackState()
}
} catch (e: IOException) {
e.printStackTrace()
ToastUtil.toastShort("当前歌曲无法播放")
}
}
/**
* 从列表里移除播放音乐
*/
fun delete(position: Int) {
val music = musicList!!.removeAt(position)
if (playPosition > position) {
playPosition -= 1
} else if (playPosition == position) {
if (isPlaying || isPreparing) {
playPosition -= 1
next()
} else {
stopPlayer()
for (listener in listeners) {
listener.onChange(playMusic!!)
}
}
}
}
/**
* 暂停或者播放音乐
*/
fun playPause() {
if (isPreparing) {
stopPlayer()
} else if (isPlaying) {
pausePlayer()
} else if (isPausing) {
startPlayer()
} else {
play(playPosition)
}
}
/**
*开始播放
*/
fun startPlayer() {
if (!isPreparing && !isPausing) {
return
}
if (audioFocusManager!!.requestAudioFocus()) {
mediaPlayer!!.start()
state = STATE_PLAYING
handler!!.post(mPublishRunnable)
if (isShowNotify) {
NotifyManager.get().showPlay(playMusic)
MediaSessionManager.get().updatePlaybackState()
}
context!!.registerReceiver(noisyReceiver, noisyFilter)
for (listener in listeners) {
listener.onPlayerStart()
}
}
}
/**
* 暂停播放器
*/
@JvmOverloads
fun pausePlayer(abandonAudioFocus: Boolean = true) {
if (!isPlaying) {
return
}
mediaPlayer!!.pause()
state = STATE_PAUSE
handler!!.removeCallbacks(mPublishRunnable)
if (isShowNotify) {
NotifyManager.get().showPause(playMusic)
MediaSessionManager.get().updatePlaybackState()
}
context!!.unregisterReceiver(noisyReceiver)
if (abandonAudioFocus) {
audioFocusManager!!.abandonAudioFocus()
}
for (listener in listeners) {
listener.onPlayerPause()
}
}
/**
* 停止播放器
*/
fun stopPlayer() {
if (isIdle) {
return
}
pausePlayer()
musicList.clear()
mediaPlayer!!.reset()
state = STATE_IDLE
}
/**
* 下一首
*/
operator fun next() {
if (musicList.isEmpty()) {
return
}
var playPosition = when (playMode) {
PlayModeEnum.SHUFFLE -> Random().nextInt(musicList.size)
PlayModeEnum.SINGLE_LOOP -> playPosition
PlayModeEnum.LIST_LOOP -> playPosition + 1
else -> playPosition + 1
}
play(playPosition);
}
/**
* 上一首
*/
fun prev() {
if (musicList.isEmpty()) {
return
}
when (playMode) {
PlayModeEnum.SHUFFLE -> play(Random().nextInt(musicList.size))
PlayModeEnum.SINGLE_LOOP -> play(playPosition)
PlayModeEnum.LIST_LOOP -> play(playPosition - 1)
else -> play(playPosition - 1)
}
}
/**
* 跳转到指定的时间位置
* @param percent 百分比
* @param position 时间点
*/
fun seekTo(percent: Int = -1, position: Long = -1) {
if (isPlaying || isPausing) {
var currentPosition = 0L
var currentPercent = 0
if (position != (-1).toLong()) {
val current = (currentPosition * 1.0).toFloat()
val du = mediaPlayer!!.duration.toFloat()
currentPercent = (current * 100 / du).toInt()
currentPosition = position
} else {
currentPosition = percent * mediaPlayer!!.duration / 100
}
mediaPlayer!!.seekTo(currentPosition)
MediaSessionManager.get().updatePlaybackState()
if (autoSaveProgress) {
PlayProgressUtil.saveProgress(
context,
musicList[playPosition].coverPath,
currentPosition.toInt()
)
}
for (listener in listeners) {
listener.onPublish(currentPercent, currentPosition)
}
}
}
/**
* 获取播放列表
*/
fun getMusicList(): List<Music>? {
return musicList
}
/**
* 获取音乐时长
*/
fun getDuration(): Long {
return mediaPlayer?.duration ?: 0
}
companion object {
private val STATE_IDLE = 0
private val STATE_PREPARING = 1
private val STATE_PLAYING = 2
private val STATE_PAUSE = 3
private val TIME_UPDATE = 300L
fun get(): AudioPlayer {
return SingletonHolder.instance
}
}
}