diff --git a/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js b/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js index 9ca7015ee..fb44e9232 100644 --- a/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js +++ b/jam-ui/src/components/client/JKSessionBackingTrackPlayer.js @@ -172,7 +172,14 @@ const JKSessionBackingTrackPlayer = ({ // Check if track reached the end if (validPosition >= validDuration && validDuration > 0) { + // Stop playback and reset to beginning for clean state + await jamClient.SessionStopPlay(); setIsPlaying(false); + setCurrentPositionMs(0); + setCurrentTime('0:00'); + // Exit early - don't update position to end + consecutivePollingErrorsRef.current = 0; + return; } // Only update state if values actually changed (lazy updates) @@ -374,18 +381,19 @@ const JKSessionBackingTrackPlayer = ({ // Set loop state using SessionSetBackingTrackFileLoop // This requires the file path and loop boolean - if (!backingTrack || !backingTrack.path) { + const trackPath = getBackingTrackPath(backingTrack); + if (!trackPath) { handleError('playback', 'No backing track available for loop change', null); setIsLooping(previousLoop); // Revert checkbox return; } - await jamClient.SessionSetBackingTrackFileLoop(backingTrack.path, shouldLoop); + await jamClient.SessionSetBackingTrackFileLoop(trackPath, shouldLoop); } catch (error) { handleError('playback', 'Failed to toggle loop', error); setIsLooping(previousLoop); // Revert checkbox on error } - }, [isLooping, jamClient, backingTrack, handleError]); + }, [isLooping, jamClient, backingTrack, handleError, getBackingTrackPath]); /* * UAT-003 Fix: Seek while paused limitation workaround @@ -460,18 +468,30 @@ const JKSessionBackingTrackPlayer = ({ } }, [handleStop, closeMedia, isPopup, onClose]); + // Helper to get backing track path (handles both string and object formats) + const getBackingTrackPath = useCallback((backingTrack) => { + if (!backingTrack) return null; + // If backingTrack is a string, it's the path itself (popup mode) + if (typeof backingTrack === 'string') return backingTrack; + // If it's an object, extract the path property (modal mode) + return backingTrack.path || null; + }, []); + const getFileName = useCallback((backingTrack) => { if (!backingTrack) return 'Unknown File'; - // Extract filename from path or use provided name - if (backingTrack.path) { - return backingTrack.path.split('/').pop().split('\\').pop(); + // Get the path first + const path = getBackingTrackPath(backingTrack); + if (path) { + return path.split('/').pop().split('\\').pop(); } - if (backingTrack.name) { + + // Fallback to name if it's an object + if (typeof backingTrack === 'object' && backingTrack.name) { return backingTrack.name; } return 'Audio File'; - }, []); + }, [getBackingTrackPath]);