diff --git a/client/src/lib/Apps/MusicBrowser/Song.svelte b/client/src/lib/Apps/MusicBrowser/Song.svelte
index 00cee78..7b101e0 100644
--- a/client/src/lib/Apps/MusicBrowser/Song.svelte
+++ b/client/src/lib/Apps/MusicBrowser/Song.svelte
@@ -7,8 +7,7 @@
let { title, artist, coverImg } = song
const handlePlay = () => {
- musicStore.setCurrent(slug)
- !$musicStore.playing && musicStore.toggle()
+ musicStore.play(slug)
}
const handleQueueNext = () => {
@@ -33,7 +32,6 @@
diff --git a/client/src/lib/Dashboard/Dashboard.svelte b/client/src/lib/Dashboard/Dashboard.svelte
index dc825d1..0fa97d8 100644
--- a/client/src/lib/Dashboard/Dashboard.svelte
+++ b/client/src/lib/Dashboard/Dashboard.svelte
@@ -3,10 +3,10 @@
import Speedometer from './Speedometer.svelte'
import SpeedLimit from './SpeedLimit.svelte'
import MediaDisplay from './MediaPlayer/MediaDisplay.svelte'
- import Player from './MediaPlayer/Player.svelte'
+ // import Player from './MediaPlayer/Player.svelte'
-
+
diff --git a/client/src/lib/Dashboard/MediaPlayer/Controls.svelte b/client/src/lib/Dashboard/MediaPlayer/Controls.svelte
index 92e72d5..8593140 100644
--- a/client/src/lib/Dashboard/MediaPlayer/Controls.svelte
+++ b/client/src/lib/Dashboard/MediaPlayer/Controls.svelte
@@ -1,9 +1,16 @@
diff --git a/client/src/lib/Dashboard/MediaPlayer/MediaDisplay.svelte b/client/src/lib/Dashboard/MediaPlayer/MediaDisplay.svelte
index 47e50f7..c72cd66 100644
--- a/client/src/lib/Dashboard/MediaPlayer/MediaDisplay.svelte
+++ b/client/src/lib/Dashboard/MediaPlayer/MediaDisplay.svelte
@@ -2,6 +2,9 @@
import Controls from './Controls.svelte'
import { musicStore } from '../../stores/musicStore'
import { songList } from './songList'
+ import { fly } from 'svelte/transition'
+ import { quintInOut } from 'svelte/easing'
+ import { onMount } from 'svelte'
$: currentSong = $musicStore.queue[$musicStore.currentIndex]
$: songData = songList[currentSong]
@@ -17,10 +20,19 @@
const toggle = () => {
musicStore.toggle()
}
+
+ onMount(() => {
+ document.addEventListener('ended', () => {
+ musicStore.skip()
+ })
+ })
{#if songData}
-
+
- import { AudioManager } from './audioManager'
- import { musicStore } from '../../stores/musicStore'
- import { songList } from './songList'
-
- const audioManager = new AudioManager()
- $: currentSong = songList[$musicStore.queue[$musicStore.currentIndex]]
-
- let src: string = ''
- $: {
- if (currentSong) src = currentSong.src
- console.log(currentSong)
- }
-
- $: {
- if (src !== '' && $musicStore.playing) {
- audioManager.playAudio(src)
- console.log(src)
- } else if (!$musicStore.playing) {
- console.log('stopping')
- audioManager.stopAudio()
- }
- console.log($musicStore.queue)
- console.log($musicStore.currentIndex)
- }
-
diff --git a/client/src/lib/Dashboard/MediaPlayer/audioManager.ts b/client/src/lib/Dashboard/MediaPlayer/audioManager.ts
deleted file mode 100644
index c5522e1..0000000
--- a/client/src/lib/Dashboard/MediaPlayer/audioManager.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-export class AudioManager {
- private audioContext: AudioContext | null = null
- private currentSource: AudioBufferSourceNode | null = null
- private currentToken: number = 0 // Unique token for each play request
- private isPlaying: boolean = false // Track whether audio is playing
-
- constructor() {
- this.initAudioContext()
- }
-
- private async initAudioContext() {
- if (!this.audioContext) {
- this.audioContext = new AudioContext()
- }
- }
-
- public async playAudio(url: string): Promise
{
- const playToken = ++this.currentToken // Update the token for this request
- await this.initAudioContext()
-
- if (this.audioContext) {
- this.stopAudio() // Stop any currently playing audio
-
- 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
- }
-
- 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
- }
- }
- }
-
- public stopAudio() {
- if (this.currentSource) {
- this.currentSource.stop()
- this.currentSource = null
- this.isPlaying = false // Update the playing status
- }
- }
-
- // Method to check if audio is currently playing
- public isAudioPlaying(): boolean {
- return this.isPlaying
- }
-}
-
-// Usage example
-const audioManager = new AudioManager()
-console.log(audioManager.isAudioPlaying()) // False, initially
-
-// 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
- })
-
-// 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/stores/audioManager.ts b/client/src/lib/stores/audioManager.ts
new file mode 100644
index 0000000..ce826c0
--- /dev/null
+++ b/client/src/lib/stores/audioManager.ts
@@ -0,0 +1,51 @@
+export class AudioPlayer {
+ private audio: HTMLAudioElement
+ private currentUrl: string | null = null
+ private isPlaying: boolean = false
+ public length: number = 0
+
+ constructor() {
+ this.audio = new Audio()
+ this.audio.addEventListener('ended', () => {
+ this.isPlaying = false
+ const ended = new CustomEvent('ended', {
+ detail: this.currentUrl,
+ bubbles: true,
+ })
+ document.dispatchEvent(ended)
+ })
+
+ this.audio.onloadedmetadata = () => {
+ this.length = this.audio.duration
+ }
+ }
+
+ // Getter for playing state
+ get playing(): boolean {
+ return this.isPlaying
+ }
+
+ // Method to play audio from a URL
+ play(url: string): void {
+ this.audio.src = url
+ this.currentUrl = url
+ this.audio.play().catch(e => console.error('Error playing audio:', e))
+ this.isPlaying = true
+ }
+
+ // Method to pause audio playback
+ pause(): void {
+ if (this.isPlaying) {
+ this.audio.pause()
+ this.isPlaying = false
+ }
+ }
+
+ // Method to unpause (resume) audio playback
+ unpause(): void {
+ if (!this.isPlaying && this.currentUrl) {
+ this.audio.play().catch(e => console.error('Error playing audio:', e))
+ this.isPlaying = true
+ }
+ }
+}
diff --git a/client/src/lib/stores/musicStore.ts b/client/src/lib/stores/musicStore.ts
index f990414..1f5a2bb 100644
--- a/client/src/lib/stores/musicStore.ts
+++ b/client/src/lib/stores/musicStore.ts
@@ -1,8 +1,11 @@
import { writable } from 'svelte/store'
+import { songList } from '../Dashboard/MediaPlayer/songList'
+import { AudioPlayer } from './audioManager'
interface MusicQueue {
queue: string[]
currentIndex: number
+ player: AudioPlayer
playing: boolean
}
@@ -10,11 +13,27 @@ function createMusicStore() {
const { subscribe, set, update } = writable({
queue: [],
currentIndex: 0,
+ player: new AudioPlayer(),
playing: false,
})
return {
subscribe,
+ play: (songSlug: string) =>
+ update(store => {
+ if (store.queue.length >= 1) {
+ store.queue.splice(store.currentIndex + 1, 0, songSlug)
+ store.currentIndex++
+ store.player.play(songList[songSlug].src)
+ } else {
+ store.queue[0] = songSlug
+ store.currentIndex = 0
+ store.player.play(songList[songSlug].src)
+ }
+ store.playing = true
+
+ return store
+ }),
push: (songSlug: string) =>
update(store => {
store.queue.push(songSlug)
@@ -22,43 +41,54 @@ function createMusicStore() {
}),
skip: () =>
update(store => {
- let next = store.queue[store.currentIndex + 1]
-
- if (next !== undefined) {
+ if (store.currentIndex < store.queue.length - 1) {
+ let next = store.queue[store.currentIndex + 1]
store.currentIndex++
+ store.playing = true
+ store.player.play(songList[next].src)
}
return store
}),
- setCurrent: (songSlug: string) =>
- update(store => {
- store.currentIndex = store.queue.length
- store.queue.push(songSlug)
- return store
- }),
queueNext: (songSlug: string) =>
update(store => {
store.queue.splice(store.currentIndex + 1, 0, songSlug)
return store
}),
- pause: update(store => {
- store.playing = false
- return store
- }),
- play: update(store => {
- store.playing = true
- return store
- }),
toggle: () =>
update(store => {
- store.playing = !store.playing
+ if (store.player.playing) {
+ store.playing = false
+ store.player.pause()
+ } else {
+ store.playing = true
+ store.player.unpause()
+ }
return store
}),
+ pause: update(store => {
+ store.player.pause()
+
+ return store
+ }),
+ unpause: update(store => {
+ store.player.unpause()
+
+ return store
+ }),
rewind: () =>
update(store => {
store.currentIndex--
+ store.player.play(songList[store.queue[store.currentIndex]].src)
+ store.playing = true
return store
}),
- reset: () => set({ queue: [], currentIndex: 0, playing: false }),
+ reset: () =>
+ set({
+ queue: [],
+ currentIndex: 0,
+ player: new AudioPlayer(),
+ playing: false,
+ }),
}
}