From d52ebeac200cfcf97be651a1e03e644469e24dab Mon Sep 17 00:00:00 2001 From: vicrodh <103399283+vicrodh@users.noreply.github.com> Date: Wed, 28 Jan 2026 11:41:37 -0600 Subject: [PATCH] fix(cast): stop local playback before establishing cast connection When user connects to a Chromecast/DLNA device while local playback is active, the local stream was conflicting with the cast stream. Now connectToDevice(): 1. Captures current track info and position 2. Stops local playback completely 3. Establishes the cast connection 4. Automatically resumes the track on the cast device 5. Seeks to the saved position (if > 5 seconds) This provides seamless handoff from local to cast playback. --- src/lib/stores/castStore.ts | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/lib/stores/castStore.ts b/src/lib/stores/castStore.ts index 448663dc8..e3335ab45 100644 --- a/src/lib/stores/castStore.ts +++ b/src/lib/stores/castStore.ts @@ -6,6 +6,13 @@ */ import { invoke } from '@tauri-apps/api/core'; +import { + getCurrentTrack, + getIsPlaying, + getCurrentTime, + setIsPlaying, + type PlayingTrack +} from './playerStore'; export type CastProtocol = 'chromecast' | 'dlna' | 'airplay'; @@ -104,9 +111,36 @@ export function getConnectedProtocol(): CastProtocol | null { /** * Connect to a cast device + * + * IMPORTANT: If local playback is active, we capture the current track/position, + * stop local playback, establish the cast connection, then resume on the cast device. */ export async function connectToDevice(device: CastDevice, protocol: CastProtocol): Promise { + // Capture current playback state BEFORE stopping + const wasPlaying = getIsPlaying(); + const currentTrack = getCurrentTrack(); + const currentPosition = getCurrentTime(); + + console.log('[CastStore] Connecting to device, current state:', { + wasPlaying, + trackId: currentTrack?.id, + position: currentPosition + }); + + // Stop local playback BEFORE connecting to avoid stream conflicts + if (wasPlaying || currentTrack) { + console.log('[CastStore] Stopping local playback before cast connection...'); + try { + await invoke('stop_playback'); + setIsPlaying(false); + } catch (err) { + // Ignore errors - player might not be playing + console.log('[CastStore] stop_playback returned:', err); + } + } + try { + // Now establish the cast connection switch (protocol) { case 'chromecast': await invoke('cast_connect', { deviceId: device.id }); @@ -128,6 +162,36 @@ export async function connectToDevice(device: CastDevice, protocol: CastProtocol currentTrackId: null }; notifyListeners(); + + // If there was a track playing, resume it on the cast device + if (wasPlaying && currentTrack && !currentTrack.isLocal) { + console.log('[CastStore] Resuming track on cast device:', currentTrack.title); + try { + await castTrack(currentTrack.id, { + title: currentTrack.title, + artist: currentTrack.artist, + album: currentTrack.album, + artworkUrl: currentTrack.artwork, + durationSecs: currentTrack.duration + }); + + // Try to seek to the saved position (if significant) + if (currentPosition > 5) { + console.log('[CastStore] Seeking to saved position:', currentPosition); + // Small delay to let the stream start + setTimeout(async () => { + try { + await castSeek(currentPosition); + } catch (seekErr) { + console.log('[CastStore] Could not restore position:', seekErr); + } + }, 2000); + } + } catch (castErr) { + console.error('[CastStore] Failed to resume track on cast device:', castErr); + // Don't throw - connection succeeded, just playback resume failed + } + } } catch (err) { console.error('[CastStore] Failed to connect:', err); throw err;