Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 修复在长时间暂停后无法播放的问题 #1627

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 95 additions & 41 deletions src/utils/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ import { decode as base642Buffer } from '@/utils/base64';

const PLAY_PAUSE_FADE_DURATION = 200;

/**
* @readonly
* @enum {string}
*/
const UNPLAYABLE_CONDITION = {
PLAY_NEXT_TRACK: 'playNextTrack',
PLAY_PREV_TRACK: 'playPrevTrack',
};

const electron =
process.env.IS_ELECTRON === true ? window.require('electron') : null;
const ipcRenderer =
Expand Down Expand Up @@ -164,6 +173,9 @@ export default class {
get currentTrack() {
return this._currentTrack;
}
get currentTrackID() {
return this._currentTrack?.id ?? 0;
}
get playlistSource() {
return this._playlistSource;
}
Expand Down Expand Up @@ -199,7 +211,7 @@ export default class {

if (this._enabled) {
// 恢复当前播放歌曲
this._replaceCurrentTrack(this._currentTrack.id, false).then(() => {
this._replaceCurrentTrack(this.currentTrackID, false).then(() => {
this._howler?.seek(localStorage.getItem('playerCurrentTrackTime') ?? 0);
}); // update audio source and init howler
this._initMediaSession();
Expand Down Expand Up @@ -278,7 +290,7 @@ export default class {
// 返回 [trackID, index]
return [this.list[next], next];
}
async _shuffleTheList(firstTrackID = this._currentTrack.id) {
async _shuffleTheList(firstTrackID = this.currentTrackID) {
let list = this._list.filter(tid => tid !== firstTrackID);
if (firstTrackID === 'first') list = this._list;
this._shuffledList = shuffle(list);
Expand Down Expand Up @@ -321,6 +333,25 @@ export default class {
this._nextTrackCallback();
},
});
this._howler.on('loaderror', (_, errCode) => {
// https://developer.mozilla.org/en-US/docs/Web/API/MediaError/code
// code 3: MEDIA_ERR_DECODE
if (errCode === 3) {
this._playNextTrack(this._isPersonalFM);
} else {
const t = this.progress;
this._replaceCurrentTrackAudio(this.currentTrack, false, false).then(
replaced => {
// 如果 replaced 为 false,代表当前的 track 已经不是这里想要替换的track
// 此时则不修改当前的歌曲进度
if (replaced) {
this._howler?.seek(t);
this.play();
}
}
);
}
});
if (autoplay) {
this.play();
if (this._currentTrack.name) {
Expand Down Expand Up @@ -452,33 +483,61 @@ export default class {
_replaceCurrentTrack(
id,
autoplay = true,
ifUnplayableThen = 'playNextTrack'
ifUnplayableThen = UNPLAYABLE_CONDITION.PLAY_NEXT_TRACK
) {
if (autoplay && this._currentTrack.name) {
this._scrobble(this.currentTrack, this._howler?.seek());
}
return getTrackDetail(id).then(data => {
let track = data.songs[0];
const track = data.songs[0];
this._currentTrack = track;
this._updateMediaSessionMetaData(track);
return this._getAudioSource(track).then(source => {
if (source) {
return this._replaceCurrentTrackAudio(
track,
autoplay,
true,
ifUnplayableThen
);
});
}
/**
* @returns 是否成功加载音频,并使用加载完成的音频替换了howler实例
*/
_replaceCurrentTrackAudio(
track,
autoplay,
isCacheNextTrack,
ifUnplayableThen = UNPLAYABLE_CONDITION.PLAY_NEXT_TRACK
) {
return this._getAudioSource(track).then(source => {
if (source) {
let replaced = false;
memorydream marked this conversation as resolved.
Show resolved Hide resolved
if (track.id === this.currentTrackID) {
this._playAudioSource(source, autoplay);
replaced = true;
}
if (isCacheNextTrack) {
this._cacheNextTrack();
return source;
} else {
store.dispatch('showToast', `无法播放 ${track.name}`);
if (ifUnplayableThen === 'playNextTrack') {
if (this.isPersonalFM) {
this.playNextFMTrack();
} else {
this.playNextTrack();
}
} else {
}
return replaced;
} else {
store.dispatch('showToast', `无法播放 ${track.name}`);
switch (ifUnplayableThen) {
case UNPLAYABLE_CONDITION.PLAY_NEXT_TRACK:
this._playNextTrack(this.isPersonalFM);
break;
case UNPLAYABLE_CONDITION.PLAY_PREV_TRACK:
this.playPrevTrack();
}
break;
default:
store.dispatch(
'showToast',
`undefined Unplayable condition: ${ifUnplayableThen}`
);
break;
}
});
return false;
}
});
}
_cacheNextTrack() {
Expand Down Expand Up @@ -511,11 +570,7 @@ export default class {
this.playPrevTrack();
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
if (this.isPersonalFM) {
this.playNextFMTrack();
} else {
this.playNextTrack();
}
this._playNextTrack(this.isPersonalFM);
});
navigator.mediaSession.setActionHandler('stop', () => {
this.pause();
Expand Down Expand Up @@ -579,11 +634,9 @@ export default class {
_nextTrackCallback() {
this._scrobble(this._currentTrack, 0, true);
if (!this.isPersonalFM && this.repeatMode === 'one') {
this._replaceCurrentTrack(this._currentTrack.id);
} else if (this.isPersonalFM) {
this.playNextFMTrack();
this._replaceCurrentTrack(this.currentTrackID);
} else {
this.playNextTrack();
this._playNextTrack(this.isPersonalFM);
}
}
_loadPersonalFMNextTrack() {
Expand Down Expand Up @@ -628,11 +681,14 @@ export default class {
}
ipcRenderer?.send('pauseDiscordPresence', track);
}

currentTrackID() {
const { list, current } = this._getListAndCurrent();
return list[current];
_playNextTrack(isPersonal) {
if (isPersonal) {
this.playNextFMTrack();
} else {
this.playNextTrack();
}
}

appendTrack(trackID) {
this.list.append(trackID);
}
Expand Down Expand Up @@ -697,7 +753,11 @@ export default class {
const [trackID, index] = this._getPrevTrack();
if (trackID === undefined) return false;
this.current = index;
this._replaceCurrentTrack(trackID, true, 'playPrevTrack');
this._replaceCurrentTrack(
trackID,
true,
UNPLAYABLE_CONDITION.PLAY_PREV_TRACK
);
return true;
}
saveSelfToLocalStorage() {
Expand Down Expand Up @@ -838,20 +898,14 @@ export default class {
addTrackToPlayNext(trackID, playNow = false) {
this._playNextList.push(trackID);
if (playNow) {
if (this.isPersonalFM) {
this.playNextFMTrack();
} else {
this.playNextTrack();
}
this.playNextTrack();
}
}
playPersonalFM() {
this._isPersonalFM = true;
if (!this._enabled) this._enabled = true;
if (this._currentTrack.id !== this._personalFMTrack.id) {
this._replaceCurrentTrack(this._personalFMTrack.id).then(() =>
this.playOrPause()
);
if (this.currentTrackID !== this._personalFMTrack.id) {
this._replaceCurrentTrack(this._personalFMTrack.id, true);
} else {
this.playOrPause();
}
Expand Down