|
|
|
@ -69,15 +69,15 @@ new Vue({ |
|
|
|
|
|
|
|
downloads: {}, |
|
|
|
|
|
|
|
cancelSource: axios.CancelToken.source(), |
|
|
|
|
|
|
|
//Player
|
|
|
|
track: null, |
|
|
|
audio: null, |
|
|
|
playback: null, |
|
|
|
volume: 0.00, |
|
|
|
//0 = Stopped, 1 = Paused, 2 = Playing, 3 = Loading
|
|
|
|
state: 0, |
|
|
|
loaders: 0, |
|
|
|
loading: false, |
|
|
|
playbackInfo: {}, |
|
|
|
position: 0, |
|
|
|
positionVal: 0, |
|
|
|
muted: false, |
|
|
|
//Gapless playback meta
|
|
|
|
gapless: { |
|
|
|
@ -88,7 +88,7 @@ new Vue({ |
|
|
|
}, |
|
|
|
|
|
|
|
//0 - normal, 1 - repeat list, 2 - repeat track
|
|
|
|
repeat: 0, |
|
|
|
repeatMode: 0, |
|
|
|
shuffled: false, |
|
|
|
|
|
|
|
//Library cache
|
|
|
|
@ -122,64 +122,110 @@ new Vue({ |
|
|
|
methods: { |
|
|
|
// PLAYBACK METHODS
|
|
|
|
isPlaying() { |
|
|
|
return this.state == 2; |
|
|
|
return this.playback && this.playback.state >= 1; |
|
|
|
}, |
|
|
|
|
|
|
|
play() { |
|
|
|
if (!this.audio || this.state != 1) return; |
|
|
|
this.audio.play(); |
|
|
|
this.state = 2; |
|
|
|
//Repeat button click
|
|
|
|
async repeatClick() { |
|
|
|
if (this.repeatMode == 2) { |
|
|
|
if (this.playback) this.playback.audio.loop = false; |
|
|
|
this.repeatMode = 0; |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
return; |
|
|
|
} |
|
|
|
this.repeatMode += 1; |
|
|
|
if (this.repeatMode == 2) { |
|
|
|
if (this.playback) this.playback.audio.loop = true; |
|
|
|
} |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
}, |
|
|
|
|
|
|
|
async play(playback) { |
|
|
|
playback = playback || this.playback; |
|
|
|
if (!playback || playback.state != 0) return; |
|
|
|
playback.state = 1; |
|
|
|
if(playback.audio) { |
|
|
|
if (playback.position) { |
|
|
|
playback.audio.currentTime = playback.position / 1000; |
|
|
|
playback.position = null; |
|
|
|
} |
|
|
|
await playback.audio.play(); |
|
|
|
if (playback.state == 0) playback.audio.pause(); |
|
|
|
else playback.state = 2; |
|
|
|
} |
|
|
|
}, |
|
|
|
pause() { |
|
|
|
if (!this.audio || this.state != 2) return; |
|
|
|
this.audio.pause(); |
|
|
|
this.state = 1; |
|
|
|
|
|
|
|
pause(playback) { |
|
|
|
playback = playback || this.playback; |
|
|
|
if (!playback || playback.state == 0) return; |
|
|
|
if (playback.state == 2) playback.audio.pause(); |
|
|
|
playback.state = 0; |
|
|
|
}, |
|
|
|
toggle() { |
|
|
|
if (this.isPlaying()) return this.pause(); |
|
|
|
this.play(); |
|
|
|
}, |
|
|
|
seek(t) { |
|
|
|
if (!this.audio || isNaN(t) || !t) return; |
|
|
|
if (isNaN(t) || (!t && t !== 0) || !this.playback) return; |
|
|
|
if (!this.playback.audio) { |
|
|
|
this.playback.position = t; |
|
|
|
return; |
|
|
|
} |
|
|
|
//ms -> s
|
|
|
|
this.audio.currentTime = (t / 1000); |
|
|
|
this.position = t; |
|
|
|
|
|
|
|
this.playback.audio.currentTime = t / 1000; |
|
|
|
this.positionVal = t; |
|
|
|
this.updateState(); |
|
|
|
}, |
|
|
|
|
|
|
|
position() { |
|
|
|
if (!this.playback) return 0; |
|
|
|
if (!this.playback.audio) return this.playback.position; |
|
|
|
return this.playback.audio.currentTime * 1000; |
|
|
|
}, |
|
|
|
|
|
|
|
//Current track duration
|
|
|
|
duration() { |
|
|
|
//Prevent 0 division
|
|
|
|
if (!this.audio) return 1; |
|
|
|
return this.audio.duration * 1000; |
|
|
|
if (!this.playback || !this.playback.audio || !this.playback.audio.duration) |
|
|
|
return (this.track ? this.track.duration : 0) || 1; |
|
|
|
return this.playback.audio.duration * 1000; |
|
|
|
}, |
|
|
|
|
|
|
|
//Replace queue, has to make clone of data to not keep references
|
|
|
|
replaceQueue(newQueue) { |
|
|
|
async replaceQueue(newQueue) { |
|
|
|
this.queue.data = Object.assign([], newQueue); |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
}, |
|
|
|
|
|
|
|
//Add track to queue at index
|
|
|
|
addTrackIndex(track, index) { |
|
|
|
async addTrackIndex(track, index) { |
|
|
|
this.queue.data.splice(index, 0, track); |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
}, |
|
|
|
|
|
|
|
//Play at index in queue
|
|
|
|
async playIndex(index) { |
|
|
|
if (index >= this.queue.data.length || index < 0) return; |
|
|
|
this.queue.index = index; |
|
|
|
await this.playTrack(this.queue.data[this.queue.index]); |
|
|
|
this.play(); |
|
|
|
this.savePlaybackInfo(); |
|
|
|
await this.playTrack(this.queue.data[this.queue.index], true); |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
}, |
|
|
|
//Skip n tracks, can be negative
|
|
|
|
async skip(n) { |
|
|
|
let newIndex = this.queue.index + n; |
|
|
|
// Loop entire list
|
|
|
|
if (this.repeatMode == 1) { |
|
|
|
newIndex %= this.queue.data.length; |
|
|
|
while (newIndex < 0) newIndex += this.queue.data.length; |
|
|
|
} |
|
|
|
//Out of bounds
|
|
|
|
if (newIndex < 0 || newIndex >= this.queue.data.length) return; |
|
|
|
await this.playIndex(newIndex); |
|
|
|
if (newIndex >= this.queue.data.length) return; |
|
|
|
// Just seek to track start if attempting to skip -1 on the first track
|
|
|
|
if (newIndex < 0) await this.seek(0); |
|
|
|
else await this.playIndex(newIndex); |
|
|
|
}, |
|
|
|
shuffle() { |
|
|
|
|
|
|
|
async shuffle() { |
|
|
|
if (!this.shuffled) { |
|
|
|
//Save positions
|
|
|
|
for (let i=0; i<this.queue.data.length; i++) |
|
|
|
@ -193,44 +239,66 @@ new Vue({ |
|
|
|
//Update index
|
|
|
|
this.queue.index = this.queue.data.findIndex(t => t.id == this.track.id); |
|
|
|
this.shuffled = true; |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
return; |
|
|
|
} |
|
|
|
//Restore unshuffled queue
|
|
|
|
if (this.shuffled) { |
|
|
|
} else { |
|
|
|
//Restore unshuffled queue
|
|
|
|
this.queue.data.sort((a, b) => (a._position || 10000) - (b._position || 10000)); |
|
|
|
this.queue.index = this.queue.data.findIndex(t => t.id == this.track.id); |
|
|
|
this.shuffled = false; |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
return; |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
//Skip wrapper
|
|
|
|
skipNext() { |
|
|
|
this.skip(1); |
|
|
|
this.savePlaybackInfo(); |
|
|
|
async skipNext() { |
|
|
|
await this.skip(1); |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
}, |
|
|
|
async skipPrev() { |
|
|
|
if (this.position() >= 10000) await this.seek(0); |
|
|
|
else await this.skip(-1); |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
}, |
|
|
|
|
|
|
|
toggleMute() { |
|
|
|
if (this.audio) this.audio.muted = !this.audio.muted; |
|
|
|
if (this.playback && this.playback.audio) this.playback.audio.muted = !this.playback.audio.muted; |
|
|
|
this.muted = !this.muted; |
|
|
|
}, |
|
|
|
|
|
|
|
async playTrack(track) { |
|
|
|
async playTrack(track, autoplay) { |
|
|
|
if (!track || !track.streamUrl) return; |
|
|
|
if (this.loading) { |
|
|
|
this.cancelSource.cancel(); |
|
|
|
this.cancelSource = axios.CancelToken.source(); |
|
|
|
} |
|
|
|
this.resetGapless(); |
|
|
|
|
|
|
|
this.track = track; |
|
|
|
this.loaders++; |
|
|
|
this.state = 3; |
|
|
|
this.loading = true; |
|
|
|
//Stop audio
|
|
|
|
let autoplay = (this.state == 2); |
|
|
|
if (this.audio) this.audio.pause(); |
|
|
|
if (this.audio) this.audio.currentTime = 0; |
|
|
|
if (this.playback && this.playback.audio) { |
|
|
|
this.pause(); |
|
|
|
this.playback.audio.removeEventListener('timeupdate', this.onTimeUpdate); |
|
|
|
this.playback.audio.removeEventListener('ended', this.onEnded); |
|
|
|
} |
|
|
|
this.playback = { |
|
|
|
audio: null, |
|
|
|
state: autoplay ? 1 : 0, |
|
|
|
}; |
|
|
|
this.track = track; |
|
|
|
this.positionVal = 0; |
|
|
|
|
|
|
|
//Load track meta
|
|
|
|
let playbackInfo = await this.loadPlaybackInfo(track.streamUrl, track.duration); |
|
|
|
if (!playbackInfo) { |
|
|
|
this.loaders--; |
|
|
|
this.skipNext(); |
|
|
|
let playbackInfo; |
|
|
|
try { |
|
|
|
playbackInfo = await this.loadPlaybackInfo(track.streamUrl, track.duration, this.cancelSource.token); |
|
|
|
if (!playbackInfo) { |
|
|
|
this.loading = false; |
|
|
|
this.skipNext(); |
|
|
|
return; |
|
|
|
} |
|
|
|
} catch (err) { // canceled
|
|
|
|
return; |
|
|
|
} |
|
|
|
this.playbackInfo = playbackInfo; |
|
|
|
@ -242,108 +310,105 @@ new Vue({ |
|
|
|
else |
|
|
|
url = this.playbackInfo.direct; |
|
|
|
//Cancel loading
|
|
|
|
this.loaders--; |
|
|
|
if (this.loaders > 0) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
this.loading = false; |
|
|
|
//Audio
|
|
|
|
this.audio = new Audio(url); |
|
|
|
autoplay = this.playback.state >= 1; |
|
|
|
let position = this.playback.position; |
|
|
|
this.playback = { |
|
|
|
state: 0, |
|
|
|
audio: new Audio(url), |
|
|
|
position, |
|
|
|
}; |
|
|
|
this.configureAudio(); |
|
|
|
this.state = 1; |
|
|
|
if (autoplay) this.play(); |
|
|
|
//MediaSession
|
|
|
|
this.updateMediaSession(); |
|
|
|
|
|
|
|
if (autoplay) |
|
|
|
await this.play(); |
|
|
|
//Loads more tracks if end of list
|
|
|
|
this.loadSTL(); |
|
|
|
}, |
|
|
|
//Configure html audio element
|
|
|
|
configureAudio() { |
|
|
|
this.playback.audio.loop = this.repeatMode == 2; |
|
|
|
this.playback.audio.muted = this.muted; |
|
|
|
this.playback.audio.volume = this.volume * this.volume; |
|
|
|
|
|
|
|
//Listen position updates
|
|
|
|
this.audio.addEventListener('timeupdate', async () => { |
|
|
|
this.position = this.audio.currentTime * 1000; |
|
|
|
this.playback.audio.addEventListener('timeupdate', this.onTimeUpdate); |
|
|
|
this.playback.audio.addEventListener('ended', this.onEnded); |
|
|
|
}, |
|
|
|
async onTimeUpdate() { |
|
|
|
this.positionVal = this.position(); |
|
|
|
//Gapless playback
|
|
|
|
if (this.position() >= (this.duration() - (this.settings.crossfadeDuration + 10000)) && this.isPlaying()) { |
|
|
|
this.loadGapless(); |
|
|
|
} |
|
|
|
|
|
|
|
//Gapless playback
|
|
|
|
if (this.position >= (this.duration() - (this.settings.crossfadeDuration + 7500)) && this.state == 2) { |
|
|
|
if (this.repeat != 2) |
|
|
|
this.loadGapless(); |
|
|
|
//Crossfade
|
|
|
|
if (this.settings.crossfadeDuration > 0 && this.position() >= (this.duration() - this.settings.crossfadeDuration) && this.isPlaying() && this.gapless.audio && !this.gapless.crossfade && this.gapless.track) { |
|
|
|
this.gapless.crossfade = true; |
|
|
|
let oldPlayback = this.playback; |
|
|
|
if (!oldPlayback) return; |
|
|
|
let currentVolume = oldPlayback.audio.volume; |
|
|
|
let playback = { |
|
|
|
audio: this.gapless.audio, |
|
|
|
state: 0, // start as paused
|
|
|
|
}; |
|
|
|
this.playback = playback; |
|
|
|
await this.play(playback); |
|
|
|
|
|
|
|
//Update meta
|
|
|
|
this.playbackInfo = this.gapless.info; |
|
|
|
this.track = this.gapless.track; |
|
|
|
this.queue.index = this.gapless.index; |
|
|
|
|
|
|
|
this.configureAudio(); |
|
|
|
this.updateMediaSession(); |
|
|
|
|
|
|
|
playback.audio.volume = 0.0; |
|
|
|
let volumeStep = currentVolume / (this.settings.crossfadeDuration / 50); |
|
|
|
for (let i = 0; i < this.settings.crossfadeDuration / 50; i++) { |
|
|
|
oldPlayback.audio.volume = Math.max(oldPlayback.audio.volume - volumeStep, 0); |
|
|
|
if (playback.audio.volume + volumeStep >= Math.min(1.0, currentVolume)) |
|
|
|
break; |
|
|
|
playback.audio.volume += volumeStep; |
|
|
|
await new Promise(res => setTimeout(() => res(), 50)); |
|
|
|
} |
|
|
|
//Restore original volume
|
|
|
|
playback.audio.volume = currentVolume; |
|
|
|
await this.pause(oldPlayback); |
|
|
|
|
|
|
|
//Crossfade
|
|
|
|
if (this.settings.crossfadeDuration > 0 && this.position >= (this.duration() - this.settings.crossfadeDuration) && this.state == 2 && this.gapless.audio && !this.gapless.crossfade && this.gapless.track) { |
|
|
|
this.gapless.crossfade = true; |
|
|
|
let currentVolume = this.audio.volume; |
|
|
|
let oldAudio = this.audio; |
|
|
|
this.audio = this.gapless.audio; |
|
|
|
this.audio.play(); |
|
|
|
|
|
|
|
//Update meta
|
|
|
|
this.playbackInfo = this.gapless.info; |
|
|
|
this.track = this.gapless.track; |
|
|
|
this.queue.index = this.gapless.index; |
|
|
|
|
|
|
|
this.configureAudio(); |
|
|
|
this.updateMediaSession(); |
|
|
|
|
|
|
|
this.audio.volume = 0.0; |
|
|
|
let volumeStep = currentVolume / (this.settings.crossfadeDuration / 50); |
|
|
|
for (let i=0; i<(this.settings.crossfadeDuration / 50); i++) { |
|
|
|
if ((oldAudio.volume - volumeStep) > 0) |
|
|
|
oldAudio.volume -= volumeStep; |
|
|
|
if ((this.audio.volume + volumeStep) >= 1.0 || (this.audio.volume + volumeStep) >= currentVolume) |
|
|
|
break; |
|
|
|
this.audio.volume += volumeStep; |
|
|
|
await new Promise((res) => setTimeout(() => res(), 50)); |
|
|
|
} |
|
|
|
//Restore original volume
|
|
|
|
this.audio.voume = currentVolume; |
|
|
|
|
|
|
|
oldAudio.pause(); |
|
|
|
|
|
|
|
if (this.playback === playback) { |
|
|
|
this.resetGapless(); |
|
|
|
this.updateState(); |
|
|
|
|
|
|
|
//Save
|
|
|
|
await this.savePlaybackInfo(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//Scrobble/LogListen
|
|
|
|
if (this.position >= this.duration() * 0.75) { |
|
|
|
this.logListen(); |
|
|
|
} |
|
|
|
}); |
|
|
|
this.audio.muted = this.muted; |
|
|
|
//Set volume
|
|
|
|
this.audio.volume = this.volume * this.volume; |
|
|
|
|
|
|
|
this.audio.addEventListener('ended', async () => { |
|
|
|
if (this.gapless.crossfade) return; |
|
|
|
|
|
|
|
//Repeat track
|
|
|
|
if (this.repeat == 2) { |
|
|
|
this.seek(0); |
|
|
|
this.audio.play(); |
|
|
|
this.updateState(); |
|
|
|
return; |
|
|
|
} |
|
|
|
//Scrobble/LogListen
|
|
|
|
if (this.position() >= this.duration() * 0.75) { |
|
|
|
this.logListen(); |
|
|
|
} |
|
|
|
}, |
|
|
|
async onEnded() { |
|
|
|
if (this.gapless.crossfade) return; |
|
|
|
|
|
|
|
//Repeat list
|
|
|
|
if (this.repeat == 1 && this.queue.index == this.queue.data.length - 1) { |
|
|
|
this.skip(-(this.queue.data.length - 1)); |
|
|
|
return; |
|
|
|
} |
|
|
|
//Repeat track
|
|
|
|
if (this.repeatMode == 2) { |
|
|
|
this.updateState(); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
//End of queue
|
|
|
|
if (this.queue.index+1 == this.queue.data.length) { |
|
|
|
this.state = 1; |
|
|
|
return; |
|
|
|
} |
|
|
|
//End of queue
|
|
|
|
if (this.repeatMode == 0 && this.queue.index + 1 == this.queue.data.length) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
//Skip to next track
|
|
|
|
this.skip(1); |
|
|
|
this.savePlaybackInfo(); |
|
|
|
}); |
|
|
|
//Skip to next track
|
|
|
|
this.skip(1); |
|
|
|
this.savePlaybackInfo(); |
|
|
|
}, |
|
|
|
//Update media session with current track metadata
|
|
|
|
updateMediaSession() { |
|
|
|
@ -360,24 +425,27 @@ new Vue({ |
|
|
|
] |
|
|
|
}); |
|
|
|
//Controls
|
|
|
|
navigator.mediaSession.setActionHandler('play', this.play); |
|
|
|
navigator.mediaSession.setActionHandler('pause', this.pause); |
|
|
|
navigator.mediaSession.setActionHandler('nexttrack', this.skipNext); |
|
|
|
navigator.mediaSession.setActionHandler('previoustrack', () => this.skip(-1)); |
|
|
|
navigator.mediaSession.setActionHandler('play', async () => await this.play()); |
|
|
|
navigator.mediaSession.setActionHandler('pause', () => this.pause()); |
|
|
|
navigator.mediaSession.setActionHandler('nexttrack', () => this.skipNext()); |
|
|
|
navigator.mediaSession.setActionHandler('previoustrack', () => this.skipPrev()); |
|
|
|
}, |
|
|
|
//Get Deezer CDN image url
|
|
|
|
getImageUrl(img, size = 256) { |
|
|
|
return `https://e-cdns-images.dzcdn.net/images/${img.type}/${img.hash}/${size}x${size}-000000-80-0-0.jpg` |
|
|
|
}, |
|
|
|
|
|
|
|
async loadPlaybackInfo(streamUrl, duration) { |
|
|
|
async loadPlaybackInfo(streamUrl, duration, cancelToken) { |
|
|
|
//Get playback info
|
|
|
|
let quality = this.settings.streamQuality; |
|
|
|
let infoUrl = `/streaminfo/${streamUrl}?q=${quality}`; |
|
|
|
let res; |
|
|
|
try { |
|
|
|
res = await this.$axios.get(infoUrl); |
|
|
|
} catch (_) { |
|
|
|
res = await this.$axios.get(infoUrl, cancelToken ? { cancelToken } : { }); |
|
|
|
} catch (err) { |
|
|
|
if (axios.isCancel(err)) { |
|
|
|
throw err; |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
@ -399,19 +467,19 @@ new Vue({ |
|
|
|
|
|
|
|
//Reset gapless playback meta
|
|
|
|
resetGapless() { |
|
|
|
this.gapless = {crossfade: false,promise: null,audio: null,info: null,track: null,index:null}; |
|
|
|
this.gapless = { crossfade: false, promise: null, audio: null, info: null, track: null, index: null }; |
|
|
|
}, |
|
|
|
//Load next track for gapless
|
|
|
|
async loadGapless() { |
|
|
|
if (this.loaders != 0 || this.gapless.promise || this.gapless.audio || this.gapless.crossfade) return; |
|
|
|
if (this.repeatMode == 2 || this.loading || this.gapless.promise || this.gapless.audio || this.gapless.crossfade) return; |
|
|
|
|
|
|
|
//Repeat list
|
|
|
|
if (this.repeat == 1 && this.queue.index == this.queue.data.length - 1) { |
|
|
|
if (this.repeatMode == 1 && this.queue.index == this.queue.data.length - 1) { |
|
|
|
this.gapless.track = this.queue.data[0]; |
|
|
|
this.gapless.index = 0; |
|
|
|
} else { |
|
|
|
//Last song
|
|
|
|
if (this.queue.index+1 >= this.queue.data.length) return; |
|
|
|
if (this.queue.index + 1 >= this.queue.data.length) return; |
|
|
|
//Next song
|
|
|
|
this.gapless.track = this.queue.data[this.queue.index + 1]; |
|
|
|
this.gapless.index = this.queue.index + 1; |
|
|
|
@ -446,7 +514,7 @@ new Vue({ |
|
|
|
if (data.data) { |
|
|
|
this.queue.data = this.queue.data.concat(data.data); |
|
|
|
} |
|
|
|
this.savePlaybackInfo(); |
|
|
|
await this.savePlaybackInfo(); |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
@ -464,9 +532,9 @@ new Vue({ |
|
|
|
async savePlaybackInfo() { |
|
|
|
let data = { |
|
|
|
queue: this.queue, |
|
|
|
position: this.position, |
|
|
|
position: this.position(), |
|
|
|
track: this.track, |
|
|
|
repeat: this.repeat, |
|
|
|
repeatMode: this.repeatMode, |
|
|
|
shuffled: this.shuffled |
|
|
|
} |
|
|
|
await this.$axios.post('/playback', data); |
|
|
|
@ -503,22 +571,22 @@ new Vue({ |
|
|
|
//Send state update to integrations
|
|
|
|
async updateState() { |
|
|
|
//Wait for duration
|
|
|
|
if (this.state == 2 && (this.duration() == null || isNaN(this.duration()))) { |
|
|
|
if (this.isPlaying() && (this.duration() == null || isNaN(this.duration()))) { |
|
|
|
setTimeout(() => { |
|
|
|
this.updateState(); |
|
|
|
}, 500); |
|
|
|
return; |
|
|
|
} |
|
|
|
this.$io.emit('stateChange', { |
|
|
|
position: this.position, |
|
|
|
position: this.position(), |
|
|
|
duration: this.duration(), |
|
|
|
state: this.state, |
|
|
|
playing: this.isPlaying(), |
|
|
|
track: this.track |
|
|
|
}); |
|
|
|
|
|
|
|
//Update in electron
|
|
|
|
if (this.settings.electron) { |
|
|
|
ipcRenderer.send('playing', this.state == 2); |
|
|
|
ipcRenderer.send('playing', this.isPlaying()); |
|
|
|
} |
|
|
|
}, |
|
|
|
updateLanguage(l) { |
|
|
|
@ -574,10 +642,10 @@ new Vue({ |
|
|
|
if (pd.data != {}) { |
|
|
|
if (pd.data.queue) this.queue = pd.data.queue; |
|
|
|
if (pd.data.track) this.track = pd.data.track; |
|
|
|
if (pd.data.repeat) this.repeat = pd.data.repeat; |
|
|
|
if (pd.data.repeatMode) this.repeatMode = pd.data.repeatMode; |
|
|
|
if (pd.data.shuffled) this.shuffled = pd.data.shuffled; |
|
|
|
this.playTrack(this.track).then(() => { |
|
|
|
this.seek(pd.data.position); |
|
|
|
this.playTrack(this.track).then(async () => { |
|
|
|
await this.seek(pd.data.position); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
@ -607,10 +675,10 @@ new Vue({ |
|
|
|
this.toggle(); |
|
|
|
}); |
|
|
|
ipcRenderer.on('skipNext', () => { |
|
|
|
this.skip(1); |
|
|
|
this.skipNext(); |
|
|
|
}); |
|
|
|
ipcRenderer.on('skipPrev', () => { |
|
|
|
this.skip(-1); |
|
|
|
this.skipPrev(); |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
@ -694,13 +762,13 @@ new Vue({ |
|
|
|
//K toggle playback
|
|
|
|
if (e.code == "KeyK" || e.code == "Space") this.$root.toggle(); |
|
|
|
//L +10s (from YT)
|
|
|
|
if (e.code == "KeyL") this.$root.seek((this.position + 10000)); |
|
|
|
if (e.code == "KeyL") this.$root.seek(this.position() + 10000); |
|
|
|
//J -10s (from YT)
|
|
|
|
if (e.code == "KeyJ") this.$root.seek((this.position - 10000)); |
|
|
|
if (e.code == "KeyJ") this.$root.seek(this.position() - 10000); |
|
|
|
//-> +5s (from YT)
|
|
|
|
if (e.code == "ArrowRight") this.$root.seek((this.position + 5000)); |
|
|
|
if (e.code == "ArrowRight") this.$root.seek(this.position() + 5000); |
|
|
|
//<- -5s (from YT)
|
|
|
|
if (e.code == "ArrowLeft") this.$root.seek((this.position - 5000)); |
|
|
|
if (e.code == "ArrowLeft") this.$root.seek(this.position() - 5000); |
|
|
|
// ^ v - Volume
|
|
|
|
if (e.code == 'ArrowUp') { |
|
|
|
if ((this.volume + 0.05) > 1) { |
|
|
|
@ -727,8 +795,8 @@ new Vue({ |
|
|
|
}, |
|
|
|
//Update volume with curve
|
|
|
|
volume() { |
|
|
|
if (this.audio) |
|
|
|
this.audio.volume = this.volume * this.volume; |
|
|
|
if (this.playback && this.playback.audio) |
|
|
|
this.playback.audio.volume = this.volume * this.volume; |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
|