From cee0bf05f5dd326bad11f3cddf59ee533924932e Mon Sep 17 00:00:00 2001 From: Nuwan Date: Tue, 13 Jan 2026 20:19:19 +0530 Subject: [PATCH] docs(1): create phase plan Phase 1: Backing Track Playback Monitoring - 1 plan created - 3 total tasks defined - Ready for execution --- .../01-01-PLAN.md | 215 ++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 .planning/phases/01-backing-track-playback-monitoring/01-01-PLAN.md diff --git a/.planning/phases/01-backing-track-playback-monitoring/01-01-PLAN.md b/.planning/phases/01-backing-track-playback-monitoring/01-01-PLAN.md new file mode 100644 index 000000000..755c95860 --- /dev/null +++ b/.planning/phases/01-backing-track-playback-monitoring/01-01-PLAN.md @@ -0,0 +1,215 @@ +--- +phase: 01-backing-track-playback-monitoring +type: execute +--- + + +Implement real-time playback monitoring for the backing track player by adding 500ms polling of the native client and displaying current position and duration in M:SS format. + +Purpose: Complete the player's time display functionality, matching the legacy web implementation's polling pattern while using modern React hooks. This establishes the monitoring foundation that Phase 2 (seek controls) will build upon. + +Output: Backing track player with live-updating time displays showing current position and total duration while track plays. + + + +@./.claude/get-shit-done/workflows/execute-phase.md +@./.claude/get-shit-down/templates/summary.md + + + +@.planning/PROJECT.md +@.planning/ROADMAP.md +@.planning/STATE.md +@.planning/phases/01-backing-track-playback-monitoring/1-CONTEXT.md +@jam-ui/src/components/client/JKSessionBackingTrackPlayer.js + +**Codebase conventions:** +- React functional components with hooks (React 16.13.1) +- camelCase for functions and variables +- Single quotes for strings (Prettier enforced) +- 2-space indentation + +**Legacy implementation reference:** +- web/app/assets/javascripts/playbackControls.js: 500ms polling via setTimeout (lines 301-337) +- web/app/assets/javascripts/utils.js: prettyPrintSeconds() time formatting (lines 885-906) +- jamClient methods: SessionCurrrentPlayPosMs(), SessionGetTracksPlayDurationMs(), isSessionTrackPlaying() + +**Current state:** +- JKSessionBackingTrackPlayer.js has currentTime and duration state hardcoded to "0:00" (lines 20-21) +- Play/pause/stop controls work via jamClient (lines 34-58) +- UI structure already in place with time displays (lines 207, 217 for popup; lines 302, 312 for modal) + +**Vision from CONTEXT.md:** +- Functional parity with legacy web (500ms polling, accurate time display) +- UI layout: Current time (M:SS) on left of slider, duration (M:SS) on right +- No padding on single-digit minutes (1:02 not 01:02) + + + + + + Task 1: Add formatTime utility function + jam-ui/src/components/client/JKSessionBackingTrackPlayer.js + Add a formatTime utility function to convert milliseconds to M:SS format (matching legacy web prettyPrintSeconds behavior). Place it inside the component before the useEffect hooks. + +Implementation: +- Accept milliseconds as parameter +- Convert to seconds (Math.floor(ms / 1000)) +- Calculate minutes: Math.floor(seconds / 60) +- Calculate remaining seconds: seconds % 60 +- Pad seconds with "0" if less than 10 (e.g., "1:05" not "1:5") +- NO padding on minutes (single digit is fine: "1:02" not "01:02") +- Return formatted string: `${minutes}:${seconds.toString().padStart(2, '0')}` + +Example outputs: +- formatTime(62000) → "1:02" +- formatTime(313000) → "5:13" +- formatTime(3605000) → "60:05" + +Do NOT implement hours formatting (tracks are < 60 minutes). + Add console.log tests: +- formatTime(62000) should output "1:02" +- formatTime(313000) should output "5:13" +- formatTime(0) should output "0:00" + formatTime function exists, converts milliseconds to M:SS format with proper padding (seconds only) + + + + Task 2: Add playback monitoring with 500ms polling + jam-ui/src/components/client/JKSessionBackingTrackPlayer.js + Add useEffect hook for playback monitoring with 500ms polling interval matching legacy web implementation (web/app/assets/javascripts/playbackControls.js lines 301-337). + +Implementation: +- Add useEffect that runs when isPlaying changes +- When isPlaying is true, start polling: + - Use setInterval (not setTimeout recursion) with 500ms interval + - In interval callback: + 1. Check if jamClient exists (guard against undefined) + 2. Call jamClient.SessionCurrrentPlayPosMs() → current position in ms + 3. Call jamClient.SessionGetTracksPlayDurationMs() → total duration in ms + 4. Call jamClient.isSessionTrackPlaying() → boolean for playing state + 5. Update setCurrentTime(formatTime(positionMs)) + 6. Update setDuration(formatTime(durationMs)) + 7. Sync setIsPlaying(isPlaying) if state changed +- When isPlaying is false, clear the interval +- Return cleanup function that clears interval + +Error handling: +- Wrap jamClient calls in try/catch +- On error, log to console but don't crash +- Continue polling even if one poll fails + +Dependencies: [isPlaying, jamClient, backingTrack] + +IMPORTANT: Use setInterval (not setTimeout recursion) for consistent 500ms timing. Store intervalId in a variable to clear on cleanup. + Check console logs show: +1. When play clicked: Polling starts, position/duration update every 500ms +2. When pause clicked: Polling stops, interval cleared +3. When stop clicked: Polling stops, position resets to 0:00 +4. No errors logged during playback + Playback monitoring polls jamClient every 500ms when playing, updates currentTime and duration state with formatted values, cleans up interval on pause/stop + + + + Task 3: Initialize duration on track load + jam-ui/src/components/client/JKSessionBackingTrackPlayer.js + Modify the existing useEffect (lines 25-32) that runs when track opens to fetch and set initial duration immediately, not waiting for playback to start. + +Current code: +```javascript +useEffect(() => { + if (isOpen && backingTrack) { + setIsPlaying(false); + setCurrentTime('0:00'); + setDuration('0:00'); + } +}, [isOpen, backingTrack]); +``` + +Change to: +```javascript +useEffect(() => { + if (isOpen && backingTrack && jamClient) { + setIsPlaying(false); + setCurrentTime('0:00'); + + // Fetch and set duration immediately when track loads + try { + const durationMs = jamClient.SessionGetTracksPlayDurationMs(); + setDuration(formatTime(durationMs)); + } catch (error) { + console.error('Error fetching track duration:', error); + setDuration('0:00'); + } + } +}, [isOpen, backingTrack, jamClient]); +``` + +This ensures the duration appears immediately when the player opens, matching the UI in the reference screenshot where "5:13" is visible before playback starts. + Open backing track player without playing: +- Duration displays actual track length (e.g., "5:13") immediately +- Current time shows "0:00" +- No errors in console + Duration fetched and displayed when track loads (before play starts), matching legacy web behavior + + + + + +Before declaring phase complete: +- [ ] Open backing track player, verify duration shows immediately (e.g., "5:13") +- [ ] Click play, verify current time updates every ~500ms (1:00 → 1:01 → 1:02) +- [ ] Verify time format matches reference: M:SS (no leading zero on minutes) +- [ ] Click pause, verify polling stops (time freezes) +- [ ] Click play again, verify polling resumes from paused position +- [ ] Click stop, verify time resets to "0:00" +- [ ] Check browser console for errors (should be none) +- [ ] Verify both modal and popup versions work identically + + + + +- formatTime utility converts milliseconds to M:SS format correctly +- Playback monitoring polls jamClient every 500ms when playing +- Current time display updates smoothly during playback +- Duration displays immediately when track loads +- Polling stops cleanly when paused/stopped +- No console errors during playback +- Functional parity with legacy web monitoring behavior + + + +After completion, create `.planning/phases/01-backing-track-playback-monitoring/01-01-SUMMARY.md`: + +# Phase 1 Plan 1: Backing Track Playback Monitoring Summary + +**Real-time backing track playback monitoring with 500ms polling and M:SS time display** + +## Accomplishments + +- Added formatTime utility for milliseconds → M:SS conversion +- Implemented 500ms polling with setInterval matching legacy web pattern +- Wired up currentTime and duration displays to live jamClient data +- Duration fetches immediately on track load (before play) + +## Files Created/Modified + +- `jam-ui/src/components/client/JKSessionBackingTrackPlayer.js` - Added formatTime, polling useEffect, duration initialization + +## Decisions Made + +- Used setInterval (not setTimeout recursion) for consistent 500ms timing +- Polling runs only when isPlaying=true to avoid unnecessary jamClient calls +- Error handling: log errors but continue polling (don't crash on transient failures) + +## Issues Encountered + +(None expected - straightforward polling implementation) + +## Next Phase Readiness + +Phase 2 (Backing Track Seek Controls) can now proceed. The monitoring useEffect will need slight modification to support seeking: +- When user drags slider, pause polling briefly +- After seek, resume polling from new position +- This is handled in Phase 2, not here +