implement scrobbling. fixes #3

This commit is contained in:
Thomas Amland 2020-11-14 13:04:58 +01:00
parent 4211966433
commit a896d01769
3 changed files with 25 additions and 5 deletions

View File

@ -27,7 +27,7 @@ const authService = new AuthService()
const api = new API(authService) const api = new API(authService)
const router = setupRouter(authService) const router = setupRouter(authService)
const store = setupStore(authService, api) const store = setupStore(authService, api)
setupAudio(store) setupAudio(store, api)
Vue.prototype.$auth = authService Vue.prototype.$auth = authService
Vue.prototype.$api = api Vue.prototype.$api = api

View File

@ -1,5 +1,6 @@
import { Store, Module } from 'vuex' import { Store, Module } from 'vuex'
import { shuffle, trackListEquals } from '@/shared/utils' import { shuffle, trackListEquals } from '@/shared/utils'
import { API } from '@/shared/api'
const audio = new Audio() const audio = new Audio()
const storedQueue = JSON.parse(localStorage.getItem('queue') || '[]') const storedQueue = JSON.parse(localStorage.getItem('queue') || '[]')
@ -12,6 +13,7 @@ const mediaSession: MediaSession | undefined = navigator.mediaSession
interface State { interface State {
queue: any[]; queue: any[];
queueIndex: number; queueIndex: number;
scrobbled: boolean;
isPlaying: boolean; isPlaying: boolean;
duration: number; // duration of current track in seconds duration: number; // duration of current track in seconds
currentTime: number; // position of current track in seconds currentTime: number; // position of current track in seconds
@ -24,6 +26,7 @@ export const playerModule: Module<State, any> = {
state: { state: {
queue: storedQueue, queue: storedQueue,
queueIndex: storedQueueIndex, queueIndex: storedQueueIndex,
scrobbled: false,
isPlaying: false, isPlaying: false,
duration: 0, duration: 0,
currentTime: 0, currentTime: 0,
@ -65,6 +68,7 @@ export const playerModule: Module<State, any> = {
index = index < state.queue.length ? index : 0 index = index < state.queue.length ? index : 0
state.queueIndex = index state.queueIndex = index
localStorage.setItem('queueIndex', index) localStorage.setItem('queueIndex', index)
state.scrobbled = false
const track = state.queue[index] const track = state.queue[index]
audio.src = track.url audio.src = track.url
if (mediaSession) { if (mediaSession) {
@ -94,6 +98,9 @@ export const playerModule: Module<State, any> = {
setDuration(state, value: any) { setDuration(state, value: any) {
state.duration = value state.duration = value
}, },
setScrobbled(state) {
state.scrobbled = true
},
}, },
actions: { actions: {
@ -194,20 +201,29 @@ export const playerModule: Module<State, any> = {
}, },
} }
export function setupAudio(store: Store<any>) { export function setupAudio(store: Store<any>, api: API) {
audio.ontimeupdate = () => { audio.ontimeupdate = () => {
store.commit('player/setCurrentTime', audio.currentTime) store.commit('player/setCurrentTime', audio.currentTime)
// Scrobble
if (store.state.player.scrobbled === false &&
audio.duration > 30 &&
audio.currentTime / audio.duration > 0.7) {
const id = store.getters['player/trackId']
store.commit('player/setScrobbled')
api.scrobble(id)
}
} }
audio.ondurationchange = () => { audio.ondurationchange = () => {
store.commit('player/setDuration', audio.duration) store.commit('player/setDuration', audio.duration)
} }
audio.onended = () => {
store.dispatch('player/next')
}
audio.onerror = () => { audio.onerror = () => {
store.commit('player/setPaused') store.commit('player/setPaused')
store.commit('setError', audio.error) store.commit('setError', audio.error)
} }
audio.onended = () => {
store.dispatch('player/next')
}
if (mediaSession) { if (mediaSession) {
mediaSession.setActionHandler('play', () => { mediaSession.setActionHandler('play', () => {

View File

@ -312,6 +312,10 @@ export class API {
return this.get('rest/startScan') return this.get('rest/startScan')
} }
async scrobble(id: string): Promise<void> {
return this.get('rest/scrobble', { id })
}
private normalizeRadioStation(item: any): Track & RadioStation { private normalizeRadioStation(item: any): Track & RadioStation {
return { return {
id: `radio-${item.id}`, id: `radio-${item.id}`,