lx-music-desktop/src/renderer/store/modules/player.js

364 lines
11 KiB
JavaScript

import path from 'path'
import music from '../../utils/music'
import { getRandom, checkPath, assertApiSupport } from '../../utils'
// state
const state = {
listInfo: {
list: [],
id: null,
},
playIndex: -1,
changePlay: false,
isShowPlayerDetail: false,
playedList: [],
playMusicInfo: null,
tempPlayList: [],
}
let urlRequest
let picRequest
let lrcRequest
const filterList = async({ playedList, listInfo, savePath, commit }) => {
// if (this.list.listName === null) return
let list
let canPlayList = []
const filteredPlayedList = playedList.filter(({ listId, isTempPlay }) => listInfo.id === listId && !isTempPlay).map(({ musicInfo }) => musicInfo)
if (listInfo.id == 'download') {
list = []
for (const item of listInfo.list) {
const filePath = path.join(savePath, item.fileName)
if (!await checkPath(filePath) || !item.isComplate || /\.ape$/.test(filePath)) continue
canPlayList.push(item)
// 排除已播放音乐
let index = filteredPlayedList.indexOf(item)
if (index > -1) {
filteredPlayedList.splice(index, 1)
continue
}
list.push(item)
}
} else {
list = listInfo.list.filter(s => {
if (!assertApiSupport(s.source)) return false
canPlayList.push(s)
let index = filteredPlayedList.indexOf(s)
if (index > -1) {
filteredPlayedList.splice(index, 1)
return false
}
return true
})
}
if (!list.length && playedList.length) {
commit('clearPlayedList')
return canPlayList
}
return list
}
// getters
const getters = {
list: state => state.listInfo.list,
changePlay: satte => satte.changePlay,
playInfo(state) {
if (state.playMusicInfo == null) return { listId: null, playIndex: -1, playListId: null, listPlayIndex: -1, isPlayList: false, musicInfo: null }
const playListId = state.listInfo.id
let listId = state.playMusicInfo.listId
const isTempPlay = !!state.playMusicInfo.isTempPlay
const isPlayList = listId === playListId
let playIndex = -1
let listPlayIndex = state.playIndex
if (listId != '__temp__') {
if (isPlayList) {
playIndex = state.listInfo.list.indexOf(state.playMusicInfo.musicInfo)
if (!isTempPlay) listPlayIndex = playIndex
} else {
let list = window.allList[listId]
if (list) playIndex = list.list.indexOf(state.playMusicInfo.musicInfo)
}
}
// console.log({
// listId,
// playIndex,
// playListId,
// listPlayIndex,
// isPlayList,
// isTempPlay,
// musicInfo: state.playMusicInfo.musicInfo,
// })
return {
listId,
playIndex,
playListId,
listPlayIndex,
isPlayList,
isTempPlay,
musicInfo: state.playMusicInfo.musicInfo,
}
},
isShowPlayerDetail: state => state.isShowPlayerDetail,
playMusicInfo: state => state.playMusicInfo,
playedList: state => state.playedList,
tempPlayList: state => state.tempPlayList,
}
// actions
const actions = {
getUrl({ commit, state }, { musicInfo, originMusic, type, isRefresh }) {
if (!musicInfo._types[type]) {
// 兼容旧版酷我源搜索列表过滤128k音质的bug
if (!(musicInfo.source == 'kw' && type == '128k')) return Promise.reject(new Error('该歌曲没有可播放的音频'))
// return Promise.reject(new Error('该歌曲没有可播放的音频'))
}
if (urlRequest && urlRequest.cancelHttp) urlRequest.cancelHttp()
if (musicInfo.typeUrl[type] && !isRefresh) return Promise.resolve(musicInfo.typeUrl[type])
urlRequest = music[musicInfo.source].getMusicUrl(musicInfo, type)
return urlRequest.promise.then(({ url }) => {
if (originMusic) commit('setUrl', { musicInfo: originMusic, url, type })
commit('setUrl', { musicInfo, url, type })
urlRequest = null
return url
}).catch(err => {
urlRequest = null
return Promise.reject(err)
})
},
getPic({ commit, state }, musicInfo) {
if (picRequest && picRequest.cancelHttp) picRequest.cancelHttp()
picRequest = music[musicInfo.source].getPic(musicInfo)
return picRequest.promise.then(url => {
picRequest = null
commit('getPic', { musicInfo, url })
}).catch(err => {
picRequest = null
return Promise.reject(err)
})
},
getLrc({ commit, state }, musicInfo) {
if (lrcRequest && lrcRequest.cancelHttp) lrcRequest.cancelHttp()
if (musicInfo.lrc && musicInfo.tlrc != null) {
if (musicInfo.lrc.startsWith('\ufeff[id:$00000000]')) {
let str = musicInfo.lrc.replace('\ufeff[id:$00000000]\n', '')
commit('setLrc', { musicInfo, lyric: str, tlyric: musicInfo.tlrc })
}
return Promise.resolve()
}
lrcRequest = music[musicInfo.source].getLyric(musicInfo)
return lrcRequest.promise.then(({ lyric, tlyric }) => {
lrcRequest = null
commit('setLrc', { musicInfo, lyric, tlyric })
}).catch(err => {
lrcRequest = null
return Promise.reject(err)
})
},
async playPrev({ state, rootState, commit, getters }) {
const currentListId = state.listInfo.id
const currentList = state.listInfo.list
if (state.playedList.length) {
// 从已播放列表移除播放列表已删除的歌曲
let index
for (index = state.playedList.indexOf(state.playMusicInfo) - 1; index > -1; index--) {
const playMusicInfo = state.playedList[index]
if (playMusicInfo.listId == currentListId && !currentList.includes(playMusicInfo.musicInfo)) {
commit('removePlayedList', index)
continue
}
break
}
if (index > -1) {
commit('setPlayMusicInfo', state.playedList[index])
return
}
}
let filteredList = await filterList({
listInfo: state.listInfo,
playedList: state.playedList,
savePath: rootState.setting.download.savePath,
commit,
})
if (!filteredList.length) return commit('setPlayMusicInfo', null)
const playInfo = getters.playInfo
let currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex])
if (currentIndex == -1) currentIndex = 0
let nextIndex = currentIndex
if (!playInfo.isTempPlay) {
switch (rootState.setting.player.togglePlayMethod) {
case 'random':
nextIndex = getRandom(0, filteredList.length)
break
case 'listLoop':
case 'list':
nextIndex = currentIndex === 0 ? filteredList.length - 1 : currentIndex - 1
break
case 'singleLoop':
break
default:
nextIndex = -1
return
}
if (nextIndex < 0) return
}
commit('setPlayMusicInfo', {
musicInfo: filteredList[nextIndex],
listId: currentListId,
})
},
async playNext({ state, rootState, commit, getters }) {
if (state.tempPlayList.length) {
const playMusicInfo = state.tempPlayList[0]
commit('removeTempPlayList', 0)
commit('setPlayMusicInfo', playMusicInfo)
return
}
const currentListId = state.listInfo.id
const currentList = state.listInfo.list
if (state.playedList.length) {
// 从已播放列表移除播放列表已删除的歌曲
let index
for (index = state.playedList.indexOf(state.playMusicInfo) + 1; index < state.playedList.length; index++) {
const playMusicInfo = state.playedList[index]
if (playMusicInfo.listId == currentListId && !currentList.includes(playMusicInfo.musicInfo)) {
commit('removePlayedList', index)
continue
}
break
}
if (index < state.playedList.length) {
commit('setPlayMusicInfo', state.playedList[index])
return
}
}
let filteredList = await filterList({
listInfo: state.listInfo,
playedList: state.playedList,
savePath: rootState.setting.download.savePath,
commit,
})
if (!filteredList.length) return commit('setPlayMusicInfo', null)
const playInfo = getters.playInfo
const currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex])
let nextIndex = currentIndex
switch (rootState.setting.player.togglePlayMethod) {
case 'listLoop':
nextIndex = currentIndex === filteredList.length - 1 ? 0 : currentIndex + 1
break
case 'random':
nextIndex = getRandom(0, filteredList.length)
break
case 'list':
nextIndex = currentIndex === filteredList.length - 1 ? -1 : currentIndex + 1
break
case 'singleLoop':
break
default:
nextIndex = -1
return
}
if (nextIndex < 0) return
commit('setPlayMusicInfo', {
musicInfo: filteredList[nextIndex],
listId: currentListId,
})
},
}
// mitations
const mutations = {
setUrl(state, datas) {
datas.musicInfo.typeUrl = Object.assign({}, datas.musicInfo.typeUrl, { [datas.type]: datas.url })
},
getPic(state, datas) {
datas.musicInfo.img = datas.url
},
setLrc(state, datas) {
datas.musicInfo.lrc = datas.lyric
datas.musicInfo.tlrc = datas.tlyric
},
setList(state, { list, index }) {
state.playMusicInfo = {
musicInfo: list.list[index],
listId: list.id,
}
state.listInfo = list
state.playIndex = index
state.changePlay = true
// console.log(state.playMusicInfo)
if (state.playedList.length) this.commit('player/clearPlayedList')
if (state.tempPlayList.length) this.commit('player/clearTempPlayeList')
},
setPlayIndex(state, index) {
state.playIndex = index
},
setChangePlay(state) {
state.changePlay = true
},
resetChangePlay(state) {
state.changePlay = false
},
setPlayedList(state, item) {
// console.log(item)
if (state.playedList.includes(item)) return
state.playedList.push(item)
},
removePlayedList(state, index) {
state.playedList.splice(index, 1)
},
clearPlayedList(state) {
state.playedList.splice(0, state.playedList.length)
},
visiblePlayerDetail(state, visible) {
state.isShowPlayerDetail = visible
},
setTempPlayList(state, list) {
state.tempPlayList.push(...list.map(({ musicInfo, listId }) => ({ musicInfo, listId, isTempPlay: true })))
if (!state.playMusicInfo) this.commit('player/playNext')
},
removeTempPlayList(state, index) {
state.tempPlayList.splice(index, 1)
},
clearTempPlayeList(state) {
state.tempPlayList.splice(0, state.tempPlayList.length)
},
setPlayMusicInfo(state, playMusicInfo) {
let playIndex = state.playIndex
if (playMusicInfo == null) {
playIndex = -1
} else {
let listId = playMusicInfo.listId
if (listId != '__temp__' && listId === state.listInfo.id) playIndex = state.listInfo.list.indexOf(state.playMusicInfo.musicInfo)
}
state.playMusicInfo = playMusicInfo
state.playIndex = playIndex
state.changePlay = true
},
}
export default {
namespaced: true,
state,
getters,
actions,
mutations,
}