fix(02-01): handle seek to end edge case in backing track player

UAT-004: When seeking to end while paused, then clicking play, the
player would break (slider jumps to 0, no audio, play button stops working).

Root cause: jamClient enters end-of-track state when position >= duration.
Calling SessionStartPlay() without resetting causes undefined behavior.

Solution:
- Detect when position is at/near end (within 100ms)
- Call SessionStopPlay() to reset jamClient state
- Seek to position 0
- Then start playback normally

Also added diagnostic logging to handlePlay, handleSeek, and polling
to help debug playback state transitions.
This commit is contained in:
Nuwan 2026-01-14 11:29:37 +05:30
parent 2c5ba2f4bc
commit ba93f1a270
1 changed files with 36 additions and 0 deletions

View File

@ -85,6 +85,12 @@ const JKSessionBackingTrackPlayer = ({
const validPosition = parseInt(positionMs, 10) || 0;
const validDuration = parseInt(durationInMs, 10) || 0;
// Check if track reached the end
if (validPosition >= validDuration && validDuration > 0) {
console.log('JKSessionBackingTrackPlayer: Track reached end, stopping playback');
setIsPlaying(false);
}
setCurrentPositionMs(validPosition);
setCurrentTime(formatTime(validPosition));
setDurationMs(validDuration);
@ -92,6 +98,7 @@ const JKSessionBackingTrackPlayer = ({
// Sync playing state if changed
if (trackIsPlaying !== isPlaying) {
console.log('JKSessionBackingTrackPlayer: Playing state changed from', isPlaying, 'to', trackIsPlaying);
setIsPlaying(trackIsPlaying);
}
} catch (error) {
@ -110,14 +117,34 @@ const JKSessionBackingTrackPlayer = ({
const handlePlay = async () => {
try {
console.log('JKSessionBackingTrackPlayer handlePlay:', {
isPlaying,
currentPositionMs,
durationMs
});
if (isPlaying) {
// Pause
await jamClient.SessionPausePlay();
setIsPlaying(false);
console.log('JKSessionBackingTrackPlayer: Paused');
} else {
// Check if we're at or very near the end (within 100ms)
if (currentPositionMs >= durationMs - 100 && durationMs > 0) {
console.log('JKSessionBackingTrackPlayer: At end of track, resetting to start before play');
// Stop first to reset state
await jamClient.SessionStopPlay();
// Seek to start
await jamClient.SessionTrackSeekMs(0);
// Update UI state
setCurrentPositionMs(0);
setCurrentTime('0:00');
}
// Play (1 = normal playback mode)
await jamClient.SessionStartPlay(1);
setIsPlaying(true);
console.log('JKSessionBackingTrackPlayer: Playing');
}
} catch (error) {
console.error('Error toggling playback:', error);
@ -175,12 +202,21 @@ const JKSessionBackingTrackPlayer = ({
const seekPositionMs = parseInt(e.target.value);
try {
console.log('JKSessionBackingTrackPlayer handleSeek:', {
seekPositionMs,
durationMs,
isPlaying,
currentPositionMs
});
// Update local state immediately for responsive UI
setCurrentPositionMs(seekPositionMs);
setCurrentTime(formatTime(seekPositionMs));
// Seek the native client to the new position
await jamClient.SessionTrackSeekMs(seekPositionMs);
console.log('JKSessionBackingTrackPlayer: Seek completed');
} catch (error) {
console.error('Error seeking:', error);
}