lx-music-desktop/src/renderer/core/useApp/usePlayer/usePlayer.js

399 lines
13 KiB
JavaScript

import { onBeforeUnmount, useI18n, watch, useCommit, useAction } from '@renderer/utils/vueTools'
import { setTitle, checkPath } from '@renderer/utils'
import { langS2T, wait, waitCancel } from '@renderer/utils/tools'
import {
setStop as setPlayerStop,
setPause as setPlayerPause,
setPlay as setPlayerPlay,
setResource,
isEmpty as isPlayerEmpty,
setLoopPlay,
} from '@renderer/plugins/player'
import { player as eventKeyPlayerNames } from '@common/hotKey'
import { player as eventPlayerNames } from '@renderer/event/names'
import useMediaSessionInfo from './useMediaSessionInfo'
import usePlayProgress from './usePlayProgress'
import usePlayEvent from './usePlayEvent'
import { requestMsg } from '@renderer/utils/message'
import {
isPlay,
setPlay,
setAllStatus,
musicInfo,
setMusicInfo,
musicInfoItem,
playMusicInfo,
setPlayList,
setPlayMusicInfo,
playedList,
} from '@renderer/core/share/player'
import { downloadList } from '@renderer/core/share/download'
import { qualityList } from '@renderer/core/share'
import { getList } from '@renderer/core/share/utils'
import path from 'path'
import useLyric from './useLyric'
import useVolume from './useVolume'
import useWatchList from './useWatchList'
const getPlayType = (highQuality, songInfo) => {
let type = '128k'
let list = qualityList.value[songInfo.source]
if (highQuality && songInfo._types['320k'] && list && list.includes('320k')) type = '320k'
return type
}
const useDelayNextTimeout = ({ playNext, timeout }) => {
let delayNextTimeout
const clearDelayNextTimeout = () => {
// console.log(this.delayNextTimeout)
if (delayNextTimeout) {
waitCancel(delayNextTimeout)
delayNextTimeout = null
}
}
const addDelayNextTimeout = () => {
clearDelayNextTimeout()
delayNextTimeout = Math.random()
wait(timeout, delayNextTimeout).then(() => {
delayNextTimeout = null
playNext()
}).catch(_ => _)
}
return {
clearDelayNextTimeout,
addDelayNextTimeout,
}
}
export default ({ setting }) => {
const { t } = useI18n()
const playNext = useAction('player', 'playNext')
const playPrev = useAction('player', 'playPrev')
const getUrl = useAction('player', 'getUrl')
const getPic = useAction('player', 'getPic')
const getLrc = useAction('player', 'getLrc')
const clearPlayedList = useCommit('player', 'clearPlayedList')
const setPlayedList = useCommit('player', 'setPlayedList')
const { addDelayNextTimeout, clearDelayNextTimeout } = useDelayNextTimeout({ playNext, timeout: 5000 })
const { addDelayNextTimeout: addLoadTimeout, clearDelayNextTimeout: clearLoadTimeout } = useDelayNextTimeout({ playNext, timeout: 123000 })
let isGettingUrl = false
const setUrl = (targetSong, isRefresh, isRetryed = false) => {
let type = getPlayType(setting.value.player.highQuality, targetSong)
// this.musicInfo.url = await getMusicUrl(targetSong, type)
setAllStatus(t('player__geting_url'))
if (setting.value.player.autoSkipOnError) addLoadTimeout()
isGettingUrl = true
return getUrl({
musicInfo: targetSong,
type,
isRefresh,
onToggleSource() {
if (targetSong !== musicInfoItem.value || isPlay.value || type != getPlayType(setting.value.player.highQuality, musicInfoItem.value)) return
setAllStatus('Try toggle source...')
},
}).then(url => {
if (global.isPlayedStop) return
if (targetSong !== musicInfoItem.value || isPlay.value || type != getPlayType(setting.value.player.highQuality, musicInfoItem.value)) return
setMusicInfo({ url })
setResource(url)
}).catch(err => {
// console.log('err', err.message)
if (global.isPlayedStop) return
if (targetSong !== musicInfoItem.value || isPlay.value) return
if (err.message == requestMsg.cancelRequest) return
if (!isRetryed) return setUrl(targetSong, isRefresh, true)
setAllStatus(err.message)
if (setting.value.player.autoSkipOnError) addDelayNextTimeout()
return Promise.reject(err)
}).finally(() => {
clearLoadTimeout()
if (targetSong === musicInfoItem.value) isGettingUrl = false
})
}
const setImg = ({ listId, musicInfo: targetSong }) => {
if (targetSong.img) {
setMusicInfo({ img: targetSong.img })
} else {
getPic({ musicInfo: targetSong, listId }).then(() => {
if (targetSong.songmid !== musicInfo.songmid) return
setMusicInfo({ img: targetSong.img })
window.eventHub.emit(eventPlayerNames.updatePic, musicInfo)
})
}
}
const setLrc = (targetSong) => {
getLrc(targetSong).then(({ lyric, tlyric, lxlyric }) => {
if (targetSong.songmid !== musicInfo.songmid) return
return (
setting.value.player.isS2t
? Promise.all([
lyric ? langS2T(lyric) : Promise.resolve(''),
tlyric ? langS2T(tlyric) : Promise.resolve(''),
lxlyric ? langS2T(lxlyric) : Promise.resolve(''),
])
: Promise.resolve([lyric, tlyric, lxlyric])
).then(([lyric, tlyric, lxlyric]) => {
setMusicInfo({
lrc: lyric,
tlrc: tlyric,
lxlrc: lxlyric,
})
})
}).catch((err) => {
console.log(err)
if (targetSong.songmid !== musicInfo.songmid) return
setAllStatus(t('lyric__load_error'))
}).finally(() => {
if (targetSong.songmid !== musicInfo.songmid) return
window.eventHub.emit(eventPlayerNames.updateLyric, musicInfo)
})
}
usePlayProgress({ setting, playNext })
useMediaSessionInfo({ playPrev, playNext })
usePlayEvent({
setting,
playNext,
setAllStatus,
setUrl,
})
useLyric({
setting,
})
useVolume({ setting })
useWatchList({ playNext })
// 恢复上次播放的状态
const handleRestorePlay = async(restorePlayInfo) => {
if (!restorePlayInfo.listId) return
const list = getList(restorePlayInfo.listId)
setPlayList(restorePlayInfo.listId)
setPlayMusicInfo(restorePlayInfo.listId, list[restorePlayInfo.index])
window.eventHub.emit(eventPlayerNames.setPlayInfo, {
musicInfo: musicInfoItem.value,
progress: {
time: setting.value.player.isSavePlayTime ? (restorePlayInfo.time || 0) : 0,
maxTime: restorePlayInfo.maxTime || 0,
},
})
setImg({ musicInfo: musicInfoItem.value, listId: playMusicInfo.listId })
setLrc(musicInfoItem.value)
if (setting.value.player.togglePlayMethod == 'random') setPlayedList({ ...playMusicInfo })
}
const setPlayStatus = () => {
setPlay(true)
}
const setPauseStatus = () => {
setPlay(false)
if (global.isPlayedStop) handlePause()
}
const setStopStatus = () => {
setPlay(false)
setTitle()
setAllStatus('')
setMusicInfo({
songmid: null,
img: null,
lrc: null,
tlrc: null,
lxlrc: null,
url: null,
name: '',
singer: '',
album: '',
})
}
// 播放音乐
const playMusic = async() => {
// console.log('playMusic')
setStopStatus()
if (window.restorePlayInfo) {
handleRestorePlay(window.restorePlayInfo)
window.restorePlayInfo = null
return
}
if (playMusicInfo.musicInfo) {
setPlayerStop()
window.eventHub.emit(eventPlayerNames.pause)
setStopStatus()
} else {
window.eventHub.emit(eventPlayerNames.setStop)
}
clearDelayNextTimeout()
let targetSong = playMusicInfo.musicInfo
if (setting.value.player.togglePlayMethod == 'random' && !playMusicInfo.isTempPlay) setPlayedList({ ...playMusicInfo })
if (targetSong.key) { // 如果是已下载的歌曲
const filePath = path.join(setting.value.download.savePath, targetSong.metadata.fileName)
// console.log(filePath)
if (!await checkPath(filePath) || !targetSong.isComplate || /\.ape$/.test(filePath)) {
return getList(playMusicInfo.listId).length == 1 ? null : playNext()
}
window.eventHub.emit(eventPlayerNames.setPlayInfo, {
musicInfo: musicInfoItem.value,
progress: {
time: 0,
maxTime: 0,
},
})
setResource(filePath)
// console.log(filePath)
} else {
// if (!this.assertApiSupport(targetSong.source)) return this.playNext()
window.eventHub.emit(eventPlayerNames.setPlayInfo, {
musicInfo: musicInfoItem.value,
progress: {
time: 0,
maxTime: 0,
},
})
setUrl(musicInfoItem.value)
}
setImg({ musicInfo: musicInfoItem.value, listId: playMusicInfo.listId })
setLrc(musicInfoItem.value)
}
const handleSetPlayInfo = ({ musicInfo }) => {
setMusicInfo({
songmid: musicInfo.songmid,
singer: musicInfo.singer,
name: musicInfo.name,
album: musicInfo.albumName,
})
setTitle(`${musicInfo.name} - ${musicInfo.singer}`)
}
const handelStop = () => {
setPlayerStop()
setPlayMusicInfo(playMusicInfo.listId, null)
window.eventHub.emit(eventPlayerNames.stop)
}
const handleEnded = () => {
setAllStatus(t('player__end'))
if (global.isPlayedStop) return
playNext()
}
const handlePause = () => {
setPlayerPause()
}
const handlePlay = async() => {
if (playMusicInfo.musicInfo == null) return
if (isPlayerEmpty()) {
if (playMusicInfo.listId == 'download') {
const musicInfo = playMusicInfo.musicInfo
const filePath = path.join(setting.value.download.savePath, musicInfo.metadata.fileName)
if (!await checkPath(filePath) || !musicInfo.isComplate || /\.ape$/.test(filePath)) {
if (downloadList.length == 1) {
window.eventHub.emit(eventPlayerNames.setStop)
} else {
playNext()
}
return
}
if (!isGettingUrl) setResource(filePath)
} else {
// if (!this.assertApiSupport(this.targetSong.source)) return this.playNext()
if (!isGettingUrl) setUrl(musicInfoItem.value)
}
return
}
setPlayerPlay()
}
// 播放、暂停播放切换
const handleTogglePlay = () => {
if (global.isPlayedStop) global.isPlayedStop = false
if (isPlay.value) {
handlePause()
} else {
handlePlay()
}
}
const handlePlayedStop = () => {
clearDelayNextTimeout()
clearLoadTimeout()
}
watch(() => setting.value.player.togglePlayMethod, newValue => {
setLoopPlay(newValue === 'singleLoop')
if (playedList.length) clearPlayedList()
if (newValue == 'random' && playMusicInfo.musicInfo && !playMusicInfo.isTempPlay) setPlayedList({ ...playMusicInfo })
})
setLoopPlay(setting.value.player.togglePlayMethod === 'singleLoop')
window.eventHub.on(eventKeyPlayerNames.next.action, playNext)
window.eventHub.on(eventKeyPlayerNames.prev.action, playPrev)
window.eventHub.on(eventKeyPlayerNames.toggle_play.action, handleTogglePlay)
window.eventHub.on(eventPlayerNames.play, setPlayStatus)
window.eventHub.on(eventPlayerNames.pause, setPauseStatus)
window.eventHub.on(eventPlayerNames.error, setPauseStatus)
window.eventHub.on(eventPlayerNames.stop, setStopStatus)
window.eventHub.on(eventPlayerNames.playMusic, playMusic)
window.eventHub.on(eventPlayerNames.setPlay, handlePlay)
window.eventHub.on(eventPlayerNames.setPause, handlePause)
window.eventHub.on(eventPlayerNames.setStop, handelStop)
window.eventHub.on(eventPlayerNames.setTogglePlay, handleTogglePlay)
window.eventHub.on(eventPlayerNames.setPlayPrev, playPrev)
window.eventHub.on(eventPlayerNames.setPlayNext, playNext)
window.eventHub.on(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
window.eventHub.on(eventPlayerNames.player_ended, handleEnded)
window.eventHub.on(eventPlayerNames.playedStop, handlePlayedStop)
onBeforeUnmount(() => {
window.eventHub.off(eventKeyPlayerNames.next.action, playNext)
window.eventHub.off(eventKeyPlayerNames.prev.action, playPrev)
window.eventHub.off(eventKeyPlayerNames.toggle_play.action, handleTogglePlay)
window.eventHub.off(eventPlayerNames.play, setPlayStatus)
window.eventHub.off(eventPlayerNames.pause, setPauseStatus)
window.eventHub.off(eventPlayerNames.error, setPauseStatus)
window.eventHub.off(eventPlayerNames.stop, setStopStatus)
window.eventHub.off(eventPlayerNames.playMusic, playMusic)
window.eventHub.off(eventPlayerNames.setTogglePlay, handleTogglePlay)
window.eventHub.off(eventPlayerNames.setPlay, handlePlay)
window.eventHub.off(eventPlayerNames.setPause, handlePause)
window.eventHub.off(eventPlayerNames.setStop, handelStop)
window.eventHub.off(eventPlayerNames.setPlayPrev, playPrev)
window.eventHub.off(eventPlayerNames.setPlayNext, playNext)
window.eventHub.off(eventPlayerNames.setPlayInfo, handleSetPlayInfo)
window.eventHub.off(eventPlayerNames.player_ended, handleEnded)
window.eventHub.off(eventPlayerNames.playedStop, handlePlayedStop)
})
}