diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ce956ec --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +app/static/songs/** filter=lfs diff=lfs merge=lfs -text diff --git a/app/static/songs/danger-zone/audio.mp3 b/app/static/songs/danger-zone/audio.mp3 index 25e367e..50069ff 100644 Binary files a/app/static/songs/danger-zone/audio.mp3 and b/app/static/songs/danger-zone/audio.mp3 differ diff --git a/app/static/songs/danger-zone/cover.png b/app/static/songs/danger-zone/cover.png index c4968ef..4e4139c 100644 Binary files a/app/static/songs/danger-zone/cover.png and b/app/static/songs/danger-zone/cover.png differ diff --git a/app/static/songs/deja-vu/audio.m4a b/app/static/songs/deja-vu/audio.m4a new file mode 100644 index 0000000..43eff68 --- /dev/null +++ b/app/static/songs/deja-vu/audio.m4a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ffed6b030e6efac7b842aa1d04fe142ae67cc42676ef0863fd98c986e45167c +size 4272439 diff --git a/app/static/songs/deja-vu/cover.jpg b/app/static/songs/deja-vu/cover.jpg new file mode 100644 index 0000000..f64a267 --- /dev/null +++ b/app/static/songs/deja-vu/cover.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:577320e227fedd883db36d7e1fd0399b4f7bae898a9c927de4b347c59f54917f +size 36462 diff --git a/app/static/songs/xenogenesis/audio.m4a b/app/static/songs/xenogenesis/audio.m4a new file mode 100644 index 0000000..481189a --- /dev/null +++ b/app/static/songs/xenogenesis/audio.m4a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed6986a60bd281410b2e47a21928280ef1b4ef8ea0015f046886e0c1ca38f1f8 +size 3780869 diff --git a/app/static/songs/xenogenesis/cover.jpg b/app/static/songs/xenogenesis/cover.jpg new file mode 100644 index 0000000..b1705b3 --- /dev/null +++ b/app/static/songs/xenogenesis/cover.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60bb7c64e60ec007b423dcd427cb7c7cb8a5e075b504e3168b5a63a0d4b6cc7e +size 79875 diff --git a/client/src/lib/Apps/MusicBrowser/Song.svelte b/client/src/lib/Apps/MusicBrowser/Song.svelte index 5972a1a..00cee78 100644 --- a/client/src/lib/Apps/MusicBrowser/Song.svelte +++ b/client/src/lib/Apps/MusicBrowser/Song.svelte @@ -8,6 +8,7 @@ const handlePlay = () => { musicStore.setCurrent(slug) + !$musicStore.playing && musicStore.toggle() } const handleQueueNext = () => { @@ -17,6 +18,8 @@ const handleQueueLast = () => { musicStore.push(slug) } + + $: nowPlaying = slug === $musicStore.queue[$musicStore.currentIndex]
{artist}

-
- +
{/if} diff --git a/client/src/lib/Dashboard/MediaPlayer/audioManager.ts b/client/src/lib/Dashboard/MediaPlayer/audioManager.ts index 63bc198..c5522e1 100644 --- a/client/src/lib/Dashboard/MediaPlayer/audioManager.ts +++ b/client/src/lib/Dashboard/MediaPlayer/audioManager.ts @@ -1,11 +1,8 @@ export class AudioManager { private audioContext: AudioContext | null = null private currentSource: AudioBufferSourceNode | null = null - private currentBuffer: AudioBuffer | null = null // Stores the current audio buffer - private startTime: number = 0 // When the current playback started - private pauseTime: number = 0 // Track where we paused private currentToken: number = 0 // Unique token for each play request - private isPaused: boolean = false + private isPlaying: boolean = false // Track whether audio is playing constructor() { this.initAudioContext() @@ -18,13 +15,6 @@ export class AudioManager { } public async playAudio(url: string): Promise { - if (this.isPaused && this.currentBuffer) { - // If paused, resume instead of reloading - this.resume() - return - } - - this.pauseTime = 0 // Reset pause time for a new track const playToken = ++this.currentToken // Update the token for this request await this.initAudioContext() @@ -34,69 +24,65 @@ export class AudioManager { try { const response = await fetch(url) const arrayBuffer = await response.arrayBuffer() + // Before decoding, check if the token has changed + if (this.currentToken !== playToken) { + return // Abort this operation if a new play request has been made + } + const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer) + + const source = this.audioContext.createBufferSource() + source.buffer = audioBuffer + source.connect(this.audioContext.destination) + + // Again check the token before starting playback if (this.currentToken !== playToken) { return // Abort if a newer request has been made } - const audioBuffer = await this.audioContext.decodeAudioData(arrayBuffer) - this.currentBuffer = audioBuffer // Save the buffer for potential pausing/resuming - this.startPlayback(audioBuffer, 0) // Start playback from the beginning + source.start(0) + this.currentSource = source + this.isPlaying = true // Update the playing status + + // Set the playing status to false when the audio ends + source.onended = () => { + if (this.currentToken === playToken) { + // Check to avoid race conditions + this.isPlaying = false + } + } } catch (error) { console.error('Error playing audio:', error) + this.isPlaying = false // Ensure status is accurate in case of error } } } - private startPlayback(buffer: AudioBuffer, offset: number) { - const source = this.audioContext!.createBufferSource() - source.buffer = buffer - source.connect(this.audioContext!.destination) - source.start(0, offset) - this.startTime = this.audioContext!.currentTime - offset - this.currentSource = source - this.isPaused = false - - source.onended = () => { - if (!this.isPaused) { - this.currentBuffer = null // Clear the buffer if playback finishes normally - } - } - } - - public pause() { - if (!this.isPaused && this.currentSource && this.audioContext) { - this.pauseTime = this.audioContext.currentTime - this.startTime - this.currentSource.stop() - this.isPaused = true - } - } - - public resume() { - if (this.isPaused && this.currentBuffer) { - this.startPlayback(this.currentBuffer, this.pauseTime) - } - } - public stopAudio() { if (this.currentSource) { this.currentSource.stop() this.currentSource = null - this.currentBuffer = null // Clear the current buffer - this.isPaused = false - this.pauseTime = 0 + this.isPlaying = false // Update the playing status } } + + // Method to check if audio is currently playing + public isAudioPlaying(): boolean { + return this.isPlaying + } } -// Usage example: +// Usage example const audioManager = new AudioManager() -const audioUrl = 'https://example.com/path/to/your/audio/file.mp3' +console.log(audioManager.isAudioPlaying()) // False, initially -// To play the audio -audioManager.playAudio(audioUrl) +// To play audio +audioManager + .playAudio('https://example.com/path/to/your/audio/file.mp3') + .then(() => { + console.log(audioManager.isAudioPlaying()) // Should log true when audio starts playing + }) -// To pause the audio -audioManager.pause() - -// To resume the audio -audioManager.resume() +// Later, you can check if audio is still playing +setTimeout(() => { + console.log(audioManager.isAudioPlaying()) // The result depends on the audio length and timing +}, 1000) diff --git a/client/src/lib/Dashboard/MediaPlayer/songList.ts b/client/src/lib/Dashboard/MediaPlayer/songList.ts index d0a0dd6..8d2f288 100644 --- a/client/src/lib/Dashboard/MediaPlayer/songList.ts +++ b/client/src/lib/Dashboard/MediaPlayer/songList.ts @@ -5,10 +5,16 @@ export const songList: { [key: string]: SongData } = { src: '/static/songs/danger-zone/audio.mp3', coverImg: '/static/songs/danger-zone/cover.png', }, - 'monko-zone': { - title: 'Danger Zone', - artist: 'Kenny Loggins', - src: '/static/songs/danger-zone/audio.mp3', - coverImg: '/static/songs/danger-zone/cover.png', + 'deja-vu': { + title: 'Deja Vu', + artist: 'Initial D', + src: '/static/songs/deja-vu/audio.m4a', + coverImg: '/static/songs/deja-vu/cover.jpg', + }, + 'Xenogenesis': { + title: 'Xenogenesis', + artist: 'TheFatRat', + src: '/static/songs/xenogenesis/audio.m4a', + coverImg: '/static/songs/xenogenesis/cover.jpg', }, } diff --git a/client/src/lib/stores/musicStore.ts b/client/src/lib/stores/musicStore.ts index b608c65..f990414 100644 --- a/client/src/lib/stores/musicStore.ts +++ b/client/src/lib/stores/musicStore.ts @@ -53,6 +53,11 @@ function createMusicStore() { store.playing = !store.playing return store }), + rewind: () => + update(store => { + store.currentIndex-- + return store + }), reset: () => set({ queue: [], currentIndex: 0, playing: false }), } }