mirror of
https://github.com/janishutz/MusicPlayer.git
synced 2026-09-10 14:25:24 +02:00
feat: basic player component
This commit is contained in:
@@ -1,20 +1,26 @@
|
||||
import {
|
||||
addSongList,
|
||||
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 {
|
||||
addSongList
|
||||
} from './playlists/add';
|
||||
import {
|
||||
playIndex
|
||||
} from './playlists';
|
||||
@@ -31,6 +37,8 @@ const prev = () => {
|
||||
const play = () => {
|
||||
if ( currentSource.value === '' ) return;
|
||||
|
||||
isPlaying.value = true;
|
||||
|
||||
sources[currentSource.value]?.play();
|
||||
startTracking();
|
||||
};
|
||||
@@ -38,6 +46,8 @@ const play = () => {
|
||||
const pause = () => {
|
||||
if ( currentSource.value === '' ) return;
|
||||
|
||||
isPlaying.value = false;
|
||||
|
||||
sources[currentSource.value]?.pause();
|
||||
stopTracking();
|
||||
};
|
||||
@@ -70,11 +80,34 @@ const back10 = () => {
|
||||
seekTo( ( ( ( source?.getPlaybackPos() ?? 0 ) * duration ) - 10 ) / duration );
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn on or off shuffle
|
||||
* @param enabled - Whether to enable or disable shuffle
|
||||
*/
|
||||
const setShuffle = ( enabled: boolean ) => {
|
||||
// TODO: Shuffle the order
|
||||
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;
|
||||
};
|
||||
@@ -99,5 +132,12 @@ export default {
|
||||
getSources,
|
||||
addSongFromSource,
|
||||
next,
|
||||
prev
|
||||
prev,
|
||||
queue,
|
||||
queueIdx,
|
||||
duration,
|
||||
playbackPercentage,
|
||||
repeat,
|
||||
shuffle,
|
||||
isPlaying
|
||||
};
|
||||
|
||||
@@ -1,14 +1,107 @@
|
||||
import {
|
||||
queue,
|
||||
queueIdx,
|
||||
rawQueue,
|
||||
shuffle
|
||||
} from '../state';
|
||||
import type {
|
||||
Song
|
||||
} from '@/ts/dtype/playlist';
|
||||
import {
|
||||
queue
|
||||
} from '../state';
|
||||
|
||||
export const addSongList = ( songs: Song[] ) => {
|
||||
for ( const song of songs ) {
|
||||
queue.value.push( song );
|
||||
export const addSongList = ( songs: Song[], first: boolean = false ) => {
|
||||
if ( first ) {
|
||||
// FIXME: Needs to insert at current index in queue, but where for rawQueue?
|
||||
// Probably at end if shuffled, else insert into queue, then copy
|
||||
rawQueue.value = songs.concat( rawQueue.value );
|
||||
queue.value = songs.concat( queue.value );
|
||||
} else {
|
||||
rawQueue.value = rawQueue.value.concat( songs );
|
||||
queue.value = queue.value.concat( songs );
|
||||
}
|
||||
};
|
||||
|
||||
export const shuffleList = () => {};
|
||||
export const clearQueue = () => {
|
||||
queue.value = [];
|
||||
rawQueue.value = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a song from the given queue index
|
||||
* @param idx - The index to remove at
|
||||
* @returns True if successful, False if not
|
||||
*/
|
||||
export const removeSong = ( idx: number ) => {
|
||||
if ( idx <= queueIdx.value ) return false;
|
||||
|
||||
const removed = queue.value.splice( idx, 1 )[0];
|
||||
|
||||
// TODO: Check that this works
|
||||
for ( let i = 0; i < rawQueue.value.length; i++ ) {
|
||||
if ( rawQueue.value[ i ] === removed ) {
|
||||
rawQueue.value.splice( i, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Move a song in the queue
|
||||
* @param idx - The index to move
|
||||
* @param newIdx - The index to move it to
|
||||
* @returns True if successful, false if constraints were violated
|
||||
*/
|
||||
export const moveSong = ( idx: number, newIdx: number ) => {
|
||||
if ( idx === newIdx ) return true;
|
||||
|
||||
if ( idx <= queueIdx.value || newIdx <= queueIdx.value || idx > queue.value.length || newIdx > queue.value.length )
|
||||
return false;
|
||||
|
||||
// Affects only the queue if shuffled, else copy the queue into rawQueue
|
||||
const movedEl = queue.value[ idx ]!;
|
||||
|
||||
if ( idx < newIdx )
|
||||
for ( let i = idx + 1; i < Math.min( queue.value.length, newIdx + 1 ); i++ ) {
|
||||
queue.value[ i - 1 ] = queue.value[ i ]!;
|
||||
}
|
||||
else if ( idx > newIdx )
|
||||
for ( let i = idx + 1; i > Math.max( 0, newIdx + 1 ); i-- ) {
|
||||
queue.value[ i ] = queue.value[ i - 1 ]!;
|
||||
}
|
||||
|
||||
queue.value[ newIdx ] = movedEl;
|
||||
|
||||
if ( !shuffle.value ) {
|
||||
// If we don't shuffle, the rawQueue should also be updated
|
||||
rawQueue.value = [];
|
||||
|
||||
for ( const song of queue.value ) {
|
||||
rawQueue.value.push( song );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/** Shuffle the song list */
|
||||
export const shuffleList = () => {
|
||||
const shuffled = rawQueue.value
|
||||
.map( ( val, idx ) => {
|
||||
return {
|
||||
val,
|
||||
idx,
|
||||
'sort': Math.random()
|
||||
};
|
||||
} ).sort( ( a, b ) => a.sort - b.sort );
|
||||
const q: Song[] = [];
|
||||
|
||||
// Make current song the first in the list
|
||||
q.push( rawQueue.value[queueIdx.value]! );
|
||||
|
||||
for ( const el of shuffled ) {
|
||||
if ( el.idx !== queueIdx.value )
|
||||
q.push( el.val );
|
||||
}
|
||||
|
||||
queue.value = q;
|
||||
};
|
||||
|
||||
@@ -18,6 +18,8 @@ export const sources: {
|
||||
|
||||
export const currentSource = ref( '' );
|
||||
|
||||
export const rawQueue: Ref<Playlist> = ref( [] );
|
||||
|
||||
export const queueIdx = ref( 0 );
|
||||
|
||||
export const queue: Ref<Playlist> = ref( [] );
|
||||
@@ -27,7 +29,3 @@ export const isPlaying = ref( false );
|
||||
export const shuffle = ref( false );
|
||||
|
||||
export const repeat: Ref<RepeatMode> = ref( 'off' );
|
||||
|
||||
export const playbackPercentage = ref( 0 );
|
||||
|
||||
export const duration = ref( 0 );
|
||||
|
||||
@@ -1,4 +1,49 @@
|
||||
// Tracking of time and player status
|
||||
export const startTracking = () => {};
|
||||
import {
|
||||
currentSource,
|
||||
queueIdx,
|
||||
repeat,
|
||||
sources
|
||||
} from './state';
|
||||
import {
|
||||
playIndex
|
||||
} from './playlists';
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
|
||||
export const stopTracking = () => {};
|
||||
// Tracking of time and player status
|
||||
let interval = -1;
|
||||
|
||||
export const playbackPercentage = ref( 0 );
|
||||
|
||||
export const duration = ref( 0 );
|
||||
|
||||
export const startTracking = () => {
|
||||
if ( interval === -1 ) {
|
||||
interval = setInterval( tracker, 250 );
|
||||
}
|
||||
|
||||
duration.value = sources[currentSource.value]?.getDuration() ?? -1;
|
||||
};
|
||||
|
||||
const tracker = () => {
|
||||
playbackPercentage.value = sources[currentSource.value]?.getPlaybackPos() ?? -1;
|
||||
|
||||
if ( playbackPercentage.value > duration.value ) {
|
||||
if ( repeat.value === 'one' ) {
|
||||
sources[currentSource.value]?.seekTo( 0 );
|
||||
} else {
|
||||
stopTracking();
|
||||
playIndex( queueIdx.value + 1 );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const stopTracking = () => {
|
||||
try {
|
||||
clearInterval( interval );
|
||||
interval = -1;
|
||||
} catch {
|
||||
// empty
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user