mirror of
https://github.com/janishutz/MusicPlayer.git
synced 2026-09-10 14:25:24 +02:00
feat: improve sync
This commit is contained in:
Vendored
+5
@@ -4,4 +4,9 @@ import type {
|
||||
|
||||
declare global {
|
||||
var MusicKit: MusicKitObject;
|
||||
interface GlobalEventHandlersEventMap {
|
||||
'musicplayer:playpause': CustomEvent<void>;
|
||||
'musicplayer:playindex': CustomEvent<void>;
|
||||
'musicplayer:seek': CustomEvent<void>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import {
|
||||
queueIdx
|
||||
} from '../player/state';
|
||||
import {
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
ref,
|
||||
watch
|
||||
} from 'vue';
|
||||
@@ -116,7 +118,8 @@ const sendStateData = () => {
|
||||
request.post( `/room/${ room.value }/update/state`, JSON.stringify( {
|
||||
'playing': isPlaying.value,
|
||||
'index': queueIdx.value,
|
||||
'start': new Date().getTime() - ( playbackPercentage.value * ( queue.value[ queueIdx.value ]?.duration ?? 0 ) ) - 100
|
||||
'start': new Date().getTime() - 100,
|
||||
'offset': playbackPercentage.value * ( queue.value[ queueIdx.value ]?.duration ?? 0 )
|
||||
} ) );
|
||||
|
||||
setTimeout( () => {
|
||||
@@ -128,10 +131,25 @@ const sendStateData = () => {
|
||||
const useRoomWatchers = () => {
|
||||
watch( queue, sendPlaylistData );
|
||||
|
||||
watch( [
|
||||
isPlaying,
|
||||
queueIdx
|
||||
], sendStateData );
|
||||
onMounted( () => {
|
||||
document.addEventListener( 'musicplayer:playindex', sendStateData );
|
||||
document.addEventListener( 'musicplayer:seek', sendStateData );
|
||||
document.addEventListener( 'musicplayer:playpause', sendStateData );
|
||||
} );
|
||||
|
||||
onUnmounted( () => {
|
||||
try {
|
||||
document.addEventListener( 'musicplayer:play', sendStateData );
|
||||
} catch { /* empty */ }
|
||||
|
||||
try {
|
||||
document.addEventListener( 'musicplayer:seek', sendStateData );
|
||||
} catch { /* empty */ }
|
||||
|
||||
try {
|
||||
document.addEventListener( 'musicplayer:playpause', sendStateData );
|
||||
} catch { /* empty */ }
|
||||
} );
|
||||
|
||||
if ( room.value ) connect();
|
||||
};
|
||||
|
||||
@@ -29,7 +29,6 @@ import type {
|
||||
import {
|
||||
load
|
||||
} from './playlists/loader';
|
||||
import messages from '../messages';
|
||||
import {
|
||||
playIndex
|
||||
} from './playlists';
|
||||
@@ -52,6 +51,7 @@ const play = () => {
|
||||
|
||||
sources[currentSource.value]?.play();
|
||||
startTracking();
|
||||
document.dispatchEvent( new CustomEvent( 'musicplayer:playpause' ) );
|
||||
};
|
||||
|
||||
const pause = () => {
|
||||
@@ -61,6 +61,7 @@ const pause = () => {
|
||||
|
||||
sources[currentSource.value]?.pause();
|
||||
stopTracking();
|
||||
document.dispatchEvent( new CustomEvent( 'musicplayer:playpause' ) );
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -71,6 +72,7 @@ const seekTo = ( pos: number ) => {
|
||||
if ( currentSource.value === '' ) return;
|
||||
|
||||
sources[currentSource.value]?.seekTo( pos );
|
||||
document.dispatchEvent( new CustomEvent( 'musicplayer:seek' ) );
|
||||
};
|
||||
|
||||
const skip10 = () => {
|
||||
@@ -153,8 +155,6 @@ const addSongFromSource = async ( source: string, cb?: ( songs: Song[] ) => void
|
||||
return true;
|
||||
};
|
||||
|
||||
messages.useRoomWatchers();
|
||||
|
||||
export default {
|
||||
play,
|
||||
pause,
|
||||
|
||||
@@ -16,8 +16,8 @@ import type {
|
||||
Song
|
||||
} from '@/ts/dtype/playlist';
|
||||
import {
|
||||
playlistIdx
|
||||
} from '@/ts/userPlaylists/state';
|
||||
setPlaylistIdx
|
||||
} from '@/ts/userPlaylists';
|
||||
|
||||
export const addSongList = ( songs: Song[] ) => {
|
||||
rawQueue.value = rawQueue.value.concat( songs );
|
||||
@@ -25,7 +25,7 @@ export const addSongList = ( songs: Song[] ) => {
|
||||
};
|
||||
|
||||
export const clearQueue = () => {
|
||||
playlistIdx.value = -1;
|
||||
setPlaylistIdx( 0 );
|
||||
queue.value = [];
|
||||
rawQueue.value = [];
|
||||
sources[currentSource.value]?.stop();
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
* Play a song at the given index of the queue. Wraps to 0 and end if index below 0 or above end
|
||||
* @param idx - The index in the queue to play at
|
||||
*/
|
||||
export const playIndex = async ( idx: number ) => {
|
||||
export const playIndex = ( idx: number ) => {
|
||||
if ( idx >= queue.value.length ) {
|
||||
idx = repeat.value === 'all' ? 0 : -1;
|
||||
} else if ( idx < 0 ) {
|
||||
@@ -42,4 +42,7 @@ export const playIndex = async ( idx: number ) => {
|
||||
startTracking();
|
||||
|
||||
isPlaying.value = true;
|
||||
setTimeout( () => {
|
||||
document.dispatchEvent( new CustomEvent( 'musicplayer:playindex', {} ) );
|
||||
}, 500 );
|
||||
};
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
currentQueue,
|
||||
currentQueueIdx,
|
||||
isPlaying,
|
||||
playbackOffset,
|
||||
playbackTime,
|
||||
startTime
|
||||
} from './state';
|
||||
import type {
|
||||
@@ -40,6 +42,8 @@ const connect = (): Promise<void> => {
|
||||
currentQueueIdx.value = data.state.index;
|
||||
isPlaying.value = data.state.playing;
|
||||
startTime.value = data.state.start;
|
||||
playbackTime.value = data.state.offset;
|
||||
playbackOffset.value = data.state.offset;
|
||||
|
||||
resolve();
|
||||
};
|
||||
|
||||
@@ -2,6 +2,8 @@ import {
|
||||
currentQueue,
|
||||
currentQueueIdx,
|
||||
isPlaying,
|
||||
playbackOffset,
|
||||
playbackTime,
|
||||
startTime
|
||||
} from './state';
|
||||
import type {
|
||||
@@ -17,6 +19,7 @@ export interface StateUpdate {
|
||||
'playing': boolean;
|
||||
'index': number;
|
||||
'start': number;
|
||||
'offset': number;
|
||||
}
|
||||
|
||||
export const messageHandler = ( msg: string ) => {
|
||||
@@ -36,6 +39,8 @@ export const messageHandler = ( msg: string ) => {
|
||||
currentQueueIdx.value = state.index;
|
||||
isPlaying.value = state.playing;
|
||||
startTime.value = state.start;
|
||||
playbackTime.value = state.offset;
|
||||
playbackOffset.value = state.offset;
|
||||
} else {
|
||||
console.log( '[SSE] Received unknown data', data.type );
|
||||
}
|
||||
|
||||
@@ -13,3 +13,9 @@ export const isPlaying = ref( false );
|
||||
export const currentQueueIdx = ref( -1 );
|
||||
|
||||
export const startTime = ref( new Date().getTime() );
|
||||
|
||||
export const showArtworks = ref( false );
|
||||
|
||||
export const playbackTime = ref( 0 );
|
||||
|
||||
export const playbackOffset = ref( 0 );
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import {
|
||||
editingPlaylists,
|
||||
playlistIdx,
|
||||
playlists
|
||||
} from './state';
|
||||
import player from '../player';
|
||||
|
||||
|
||||
export const addPlaylist = ( name: string ) => {
|
||||
playlists.value.push( {
|
||||
@@ -17,3 +20,13 @@ export const removePlaylist = ( idx: number ) => {
|
||||
editingPlaylists.value.splice( idx, 1 );
|
||||
}
|
||||
};
|
||||
|
||||
export const selectPlaylist = ( idx: number ) => {
|
||||
playlistIdx.value = idx;
|
||||
player.clearQueue();
|
||||
player.loadPlaylist( playlists.value[ idx ]!.songs );
|
||||
};
|
||||
|
||||
export const setPlaylistIdx = ( idx: number ) => {
|
||||
playlistIdx.value = idx;
|
||||
};
|
||||
|
||||
@@ -16,15 +16,17 @@ import {
|
||||
useNotification
|
||||
} from '@kyvg/vue3-notification';
|
||||
|
||||
export const savePlaylist = async () => {
|
||||
export const savePlaylist = () => {
|
||||
rawQueue.value = queue.value;
|
||||
shuffle.value = false;
|
||||
|
||||
if ( playlistIdx.value ) {
|
||||
if ( playlistIdx.value < 0 ) {
|
||||
let name: null | string = '';
|
||||
|
||||
while ( !name || name.length === 0 ) {
|
||||
name = prompt( 'You are trying to save a playlist that has not previously been created. Please enter a name for it' );
|
||||
|
||||
if ( !name ) return;
|
||||
}
|
||||
|
||||
addPlaylist( name );
|
||||
|
||||
Reference in New Issue
Block a user