Files
MusicPlayer/web/src/ts/player/index.ts
T
janishutz 8a3dd7a583 feat: loading local songs, basic association
association used to load existing playlists with local files
2026-09-02 14:23:16 +02:00

176 lines
3.5 KiB
TypeScript

import {
addSongList,
clearQueue,
removeSong,
shuffleList
} from './playlists/add';
import {
currentSource,
isPlaying,
queue,
queueIdx,
rawQueue,
repeat,
shuffle,
sources
} from './state';
import {
duration,
playbackPercentage,
startTracking,
stopTracking
} from './status-tracking';
import type {
RepeatMode
} from '../dtype/player';
import type {
Song
} from '../dtype/playlist';
import {
load
} from './playlists/loader';
import {
playIndex
} from './playlists';
const next = () => {
playIndex( ( queueIdx.value + 1 ) % queue.value.length );
};
const prev = () => {
// TODO: Back to beginning if more than some seconds have passed?
playIndex( ( queueIdx.value - 1 + queue.value.length ) % queue.value.length );
};
const play = () => {
if ( currentSource.value === '' ) return;
isPlaying.value = true;
sources[currentSource.value]?.play();
startTracking();
};
const pause = () => {
if ( currentSource.value === '' ) return;
isPlaying.value = false;
sources[currentSource.value]?.pause();
stopTracking();
};
/**
* Seek to a specific point in the song
* @param pos - Percentage of song, value in [0, 1]
*/
const seekTo = ( pos: number ) => {
if ( currentSource.value === '' ) return;
sources[currentSource.value]?.seekTo( pos );
};
const skip10 = () => {
if ( currentSource.value === '' ) return;
const source = sources[currentSource.value];
const duration = source?.getDuration() ?? -1;
seekTo( ( ( ( source?.getPlaybackPos() ?? 0 ) * duration ) + 10 ) / duration );
};
const back10 = () => {
if ( currentSource.value === '' ) return;
const source = sources[currentSource.value];
const duration = source?.getDuration() ?? -1;
seekTo( ( ( ( source?.getPlaybackPos() ?? 0 ) * duration ) - 10 ) / duration );
};
/**
* Turn on or off shuffle
* @param enabled - Whether to enable or disable shuffle
*/
const setShuffle = ( enabled: boolean ) => {
shuffle.value = enabled;
if ( enabled ) {
shuffleList();
queueIdx.value = 0;
} else {
const curr = queue.value[queueIdx.value];
queue.value = [];
for ( let i = 0; i < rawQueue.value.length; i++ ) {
if ( rawQueue.value[i] === curr )
queueIdx.value = i;
queue.value.push( rawQueue.value[i]! );
}
}
};
/**
* Change the repeat mode
* @param mode - The repeat mode to switch into
*/
const setRepeat = ( mode: RepeatMode ) => {
repeat.value = mode;
};
const getSources = (): string[] => {
return Object.keys( sources );
};
const addToSongList = ( songs: Song[] ) => {
addSongList( songs );
if ( currentSource.value === '' ) {
playIndex( 0 );
}
};
/**
* Add songs to the playlist from given source
* @param source - The ID of the source to add from
*/
const addSongFromSource = async ( source: string ): Promise<boolean> => {
if ( sources[source]!.authorized.value ) {
sources[source]!.addSongsFromThisSource( addToSongList );
} else {
sources[source]!.login!();
return false;
}
return true;
};
export default {
play,
pause,
seekTo,
skip10,
back10,
setShuffle,
setRepeat,
playIndex,
getSources,
addSongFromSource,
next,
prev,
clearQueue,
removeSong,
queue,
queueIdx,
duration,
playbackPercentage,
repeat,
shuffle,
isPlaying,
'loadPlaylist': load
};