mirror of
https://github.com/janishutz/MusicPlayer.git
synced 2026-09-10 14:25:24 +02:00
feat: basic player commands
This commit is contained in:
Vendored
+1
@@ -0,0 +1 @@
|
||||
export type RepeatMode = 'off' | 'one' | 'all';
|
||||
@@ -0,0 +1,103 @@
|
||||
import {
|
||||
currentSource,
|
||||
queueIdx,
|
||||
repeat,
|
||||
shuffle,
|
||||
sources
|
||||
} from './state';
|
||||
import {
|
||||
startTracking,
|
||||
stopTracking
|
||||
} from './status-tracking';
|
||||
import type {
|
||||
RepeatMode
|
||||
} from '../dtype/player';
|
||||
import {
|
||||
addSongList
|
||||
} from './playlists/add';
|
||||
import {
|
||||
playIndex
|
||||
} from './playlists';
|
||||
|
||||
const next = () => {
|
||||
playIndex( queueIdx.value + 1 );
|
||||
};
|
||||
|
||||
const prev = () => {
|
||||
// TODO: Back to beginning if more than some seconds have passed?
|
||||
playIndex( queueIdx.value - 1 );
|
||||
};
|
||||
|
||||
const play = () => {
|
||||
if ( currentSource.value === '' ) return;
|
||||
|
||||
sources[currentSource.value]?.play();
|
||||
startTracking();
|
||||
};
|
||||
|
||||
const pause = () => {
|
||||
if ( currentSource.value === '' ) return;
|
||||
|
||||
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 );
|
||||
};
|
||||
|
||||
const setShuffle = ( enabled: boolean ) => {
|
||||
// TODO: Shuffle the order
|
||||
shuffle.value = enabled;
|
||||
};
|
||||
|
||||
const setRepeat = ( mode: RepeatMode ) => {
|
||||
repeat.value = mode;
|
||||
};
|
||||
|
||||
const getSources = (): string[] => {
|
||||
return Object.keys( sources );
|
||||
};
|
||||
|
||||
const addSongFromSource = async ( source: string ) => {
|
||||
addSongList( await sources[source]!.addSongsFromThisSource() );
|
||||
};
|
||||
|
||||
export default {
|
||||
play,
|
||||
pause,
|
||||
seekTo,
|
||||
skip10,
|
||||
back10,
|
||||
setShuffle,
|
||||
setRepeat,
|
||||
playIndex,
|
||||
getSources,
|
||||
addSongFromSource,
|
||||
next,
|
||||
prev
|
||||
};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
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 shuffleList = () => {};
|
||||
@@ -0,0 +1,36 @@
|
||||
import {
|
||||
currentSource,
|
||||
queue,
|
||||
queueIdx,
|
||||
repeat,
|
||||
sources
|
||||
} from '../state';
|
||||
import {
|
||||
startTracking,
|
||||
stopTracking
|
||||
} from '../status-tracking';
|
||||
|
||||
/**
|
||||
* 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 ) => {
|
||||
if ( idx >= queue.value.length ) {
|
||||
idx = repeat.value === 'all' ? 0 : -1;
|
||||
} else if ( idx < 0 ) {
|
||||
idx = repeat.value === 'all' ? queue.value.length - 1 : -1;
|
||||
}
|
||||
|
||||
if ( idx < 0 ) return false;
|
||||
|
||||
sources[currentSource.value]?.stop();
|
||||
stopTracking();
|
||||
|
||||
const nextSong = queue.value[ idx ]!;
|
||||
|
||||
queueIdx.value = idx;
|
||||
currentSource.value = nextSong.source;
|
||||
sources[currentSource.value]?.playSong( nextSong.identifier );
|
||||
|
||||
startTracking();
|
||||
};
|
||||
@@ -1 +1,2 @@
|
||||
// TODO: If local files contained, prompt user to select files, then associate based on file names
|
||||
export const load = () => {};
|
||||
+1
-1
@@ -22,7 +22,7 @@ export interface PlayerSourcePlugin {
|
||||
'login'?: () => Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Play a song by its ID
|
||||
* Play a song by its ID. Should start playing it immediately
|
||||
*/
|
||||
'playSong': ( id: string ) => Promise<void>;
|
||||
|
||||
|
||||
@@ -2,9 +2,21 @@ import {
|
||||
type Ref,
|
||||
ref
|
||||
} from 'vue';
|
||||
import type {
|
||||
PlayerSourcePlugin
|
||||
} from './plugins/interface';
|
||||
import type {
|
||||
Playlist
|
||||
} from '../dtype/playlist';
|
||||
import type {
|
||||
RepeatMode
|
||||
} from '../dtype/player';
|
||||
|
||||
export const sources: {
|
||||
[key: string]: PlayerSourcePlugin
|
||||
} = {};
|
||||
|
||||
export const currentSource = ref( '' );
|
||||
|
||||
export const queueIdx = ref( 0 );
|
||||
|
||||
@@ -14,7 +26,7 @@ export const isPlaying = ref( false );
|
||||
|
||||
export const shuffle = ref( false );
|
||||
|
||||
export const repeat: Ref<'off' | 'one' | 'all'> = ref( 'off' );
|
||||
export const repeat: Ref<RepeatMode> = ref( 'off' );
|
||||
|
||||
export const playbackPercentage = ref( 0 );
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// Tracking of time and player status
|
||||
export const startTracking = () => {};
|
||||
|
||||
export const stopTracking = () => {};
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
# Frontend
|
||||
- [ ] Status tracking (position, etc)
|
||||
- [ ] Change metadata association for automated association
|
||||
- [ ] Move songs with D&D, or index assignment?
|
||||
- [ ] Explain additional info
|
||||
- [ ] Tour
|
||||
- [ ] Get player working
|
||||
- [ ] Save playlists locally or on backend
|
||||
- [ ] SSE connection
|
||||
- [ ] Anti-Tamper
|
||||
- [ ] Remote showcase views
|
||||
- [ ] Login
|
||||
- [ ] About page
|
||||
- [ ] Apple-Music signin
|
||||
- [ ] Loading existing playlists with local music and association of that
|
||||
|
||||
# Backend
|
||||
- [ ] Implement all endpoints
|
||||
- [ ] Integrate with store and auth sdks
|
||||
- [ ] Create FOSS solution for above (single user)
|
||||
- [ ] Setup guide
|
||||
- [ ] Docker containers
|
||||
- [ ] CI
|
||||
Reference in New Issue
Block a user