docs(04-01): create jamClient JamTrack API reference
- Documented all 15+ JamTrack-specific jamClient methods with signatures - Covered playback, track data, download/sync, and JMEP methods - Added comparison table: JamTrack vs Backing Track methods - Included usage examples for load flow, download/sync, monitoring - Noted critical implementation details (fqId format, async patterns, string returns)
This commit is contained in:
parent
b7208d945c
commit
d3ff1f1477
|
|
@ -0,0 +1,569 @@
|
||||||
|
# JamTrack jamClient API Reference
|
||||||
|
|
||||||
|
Complete reference for jamClient JamTrack-related methods discovered in `web/app/assets/javascripts/bridge_api.es6` and usage patterns from legacy code.
|
||||||
|
|
||||||
|
**Source:** Lines 1035-1093 in bridge_api.es6
|
||||||
|
|
||||||
|
## 1. Playback Methods
|
||||||
|
|
||||||
|
### JamTrackPlay(fqId)
|
||||||
|
|
||||||
|
**Purpose:** Load JamTrack into session (despite name, this is "load", not "play")
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackPlay(fqId)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `fqId` (string): Fully-qualified ID format: `{jamTrackId}-{sampleRate}`
|
||||||
|
- Example: `'12345-48'` or `'12345-44'`
|
||||||
|
- Sample rate: '44' for 44.1kHz, '48' for 48kHz
|
||||||
|
- Must match client's audio sample rate (from `GetSampleRate()`)
|
||||||
|
|
||||||
|
**Returns:** Boolean
|
||||||
|
- `true`: JamTrack loaded successfully
|
||||||
|
- `false`: Failed to load (show error to user)
|
||||||
|
|
||||||
|
**Usage pattern** (session.js:2760):
|
||||||
|
```javascript
|
||||||
|
var sampleRate = context.jamClient.GetSampleRate(); // 44 or 48
|
||||||
|
var sampleRateForFilename = sampleRate == 48 ? '48' : '44';
|
||||||
|
var fqId = jamTrack.id + '-' + sampleRateForFilename;
|
||||||
|
|
||||||
|
var result = context.jamClient.JamTrackPlay(fqId);
|
||||||
|
if (!result) {
|
||||||
|
app.notify({
|
||||||
|
title: "JamTrack Can Not Open",
|
||||||
|
text: "Unable to open your JamTrack. Please contact support@jamkazam.com"
|
||||||
|
}, null, true);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Must be called AFTER JamTrack is synchronized (on disk with keys)
|
||||||
|
- Loads all stem tracks into session mixer
|
||||||
|
- Call `JamTrackLoadJmep(fqId, jmepData)` BEFORE this if tempo/pitch modifications needed
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### JamTrackStopPlay()
|
||||||
|
|
||||||
|
**Purpose:** Stop JamTrack playback and unload from session
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackStopPlay()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Void
|
||||||
|
|
||||||
|
**Usage pattern** (session.js:2743):
|
||||||
|
```javascript
|
||||||
|
// Always stop before loading new JamTrack
|
||||||
|
context.jamClient.JamTrackStopPlay();
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Cleans up current JamTrack resources
|
||||||
|
- Should be called before loading a new JamTrack
|
||||||
|
- Safe to call even if no JamTrack is loaded
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### JamTrackIsPlaying()
|
||||||
|
|
||||||
|
**Purpose:** Query whether a JamTrack is currently playing
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackIsPlaying()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Boolean
|
||||||
|
- `true`: JamTrack is actively playing
|
||||||
|
- `false`: No JamTrack playing or paused
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Use for playback state checks in UI
|
||||||
|
- Similar to `isSessionTrackPlaying()` for Backing Tracks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### JamTrackIsPlayable()
|
||||||
|
|
||||||
|
**Purpose:** Check if JamTrack can be played (loaded and ready)
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackIsPlayable()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Boolean
|
||||||
|
- `true`: JamTrack is loaded and can be played
|
||||||
|
- `false`: No JamTrack loaded or not ready
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Use to enable/disable play button
|
||||||
|
- Checks if JamTrack was successfully loaded via `JamTrackPlay()`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Track Data Methods
|
||||||
|
|
||||||
|
### JamTrackGetTracks()
|
||||||
|
|
||||||
|
**Purpose:** Get list of stem tracks in currently loaded JamTrack
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackGetTracks()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Array of track objects (format TBD - not shown in legacy code)
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Called after JamTrack is loaded
|
||||||
|
- Returns individual stems (drums, bass, guitar, vocals, etc.)
|
||||||
|
- Used to populate stem mixer UI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### JamTrackGetTrackDetail(fqId)
|
||||||
|
|
||||||
|
**Purpose:** Get synchronization state and version for a JamTrack
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackGetTrackDetail(fqId)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `fqId` (string): Fully-qualified ID `{jamTrackId}-{sampleRate}`
|
||||||
|
|
||||||
|
**Returns:** Object
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
key_state: string, // Encryption key status
|
||||||
|
version: number // JamTrack version number
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Usage pattern** (download_jamtrack.js.coffee state machine):
|
||||||
|
- Queries client to determine current sync state
|
||||||
|
- Used by state machine to decide next action (packaging, downloading, keying, synchronized)
|
||||||
|
- `key_state` values determine if encryption keys are available
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Called repeatedly during download/sync process
|
||||||
|
- Return value drives state machine transitions
|
||||||
|
- Critical for determining when JamTrack is ready to play
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### JamTrackGetImage()
|
||||||
|
|
||||||
|
**Purpose:** Get album art image for currently loaded JamTrack
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackGetImage()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Image data (format TBD - possibly base64 or file path)
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Display album art in player UI
|
||||||
|
- Similar functionality to potential Backing Track cover art
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### GetJamTrackTimeline()
|
||||||
|
|
||||||
|
**Purpose:** Get timeline/waveform data for visualization
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.GetJamTrackTimeline()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Timeline data structure (format TBD)
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Used for waveform visualization in UI
|
||||||
|
- May include beat markers, section markers
|
||||||
|
- Advanced feature for timeline scrubbing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Download/Sync Methods
|
||||||
|
|
||||||
|
### JamTrackDownload(jamTrackId, mixdownId, userId, progressCallback, successCallback, failCallback)
|
||||||
|
|
||||||
|
**Purpose:** Download JamTrack package from server to local disk
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackDownload(
|
||||||
|
jamTrackId, // JamTrack ID (integer)
|
||||||
|
mixdownId, // Selected mixdown package ID (integer)
|
||||||
|
userId, // Current user ID (integer)
|
||||||
|
progressCallback, // Function name (string) for progress updates
|
||||||
|
successCallback, // Function name (string) for completion
|
||||||
|
failCallback // Function name (string) for errors
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- All parameters required
|
||||||
|
- Callbacks are **function names as strings**, not function references
|
||||||
|
- Callbacks are called by native client with download progress data
|
||||||
|
|
||||||
|
**Returns:** Void (callbacks handle results)
|
||||||
|
|
||||||
|
**Usage pattern** (download_jamtrack.js.coffee downloading state):
|
||||||
|
```coffeescript
|
||||||
|
context.jamClient.JamTrackDownload(
|
||||||
|
@jamTrack.id,
|
||||||
|
@jamTrack.selectedMixdown.id,
|
||||||
|
@app.currentUser.id,
|
||||||
|
'onDownloadProgress', # String, not function ref
|
||||||
|
'onDownloadSuccess',
|
||||||
|
'onDownloadFail'
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Callback signatures:**
|
||||||
|
- `progressCallback(percentComplete, bytesDownloaded, totalBytes)`
|
||||||
|
- `successCallback()`
|
||||||
|
- `failCallback(errorMessage)`
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Called when state machine reaches `downloading` state
|
||||||
|
- Must be preceded by mixdown packaging on server
|
||||||
|
- After success, call `JamTrackKeysRequest()` to fetch encryption keys
|
||||||
|
- Callbacks must be global functions accessible to native client
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### JamTrackKeysRequest()
|
||||||
|
|
||||||
|
**Purpose:** Request encryption keys for downloaded JamTrack
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackKeysRequest()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Void (asynchronous operation)
|
||||||
|
|
||||||
|
**Usage pattern** (download_jamtrack.js.coffee keying state):
|
||||||
|
- Called after successful download
|
||||||
|
- Native client fetches keys from server
|
||||||
|
- Poll `JamTrackGetTrackDetail()` to check when keys are available
|
||||||
|
- State machine has 10-second timeout for keying operation
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Required for encrypted JamTrack playback
|
||||||
|
- Separate step from download
|
||||||
|
- Can fail with timeout if server doesn't respond
|
||||||
|
- After success, JamTrack is "synchronized" and ready to play
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### InvalidateJamTrack(fqId)
|
||||||
|
|
||||||
|
**Purpose:** Clear cached JamTrack version, force re-download
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.InvalidateJamTrack(fqId)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `fqId` (string): Fully-qualified ID `{jamTrackId}-{sampleRate}`
|
||||||
|
|
||||||
|
**Returns:** Void
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Used when new JamTrack version is available
|
||||||
|
- Forces download of updated package
|
||||||
|
- Clears local cache and encryption keys
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. JMEP (Jam Enhancement Package) Methods
|
||||||
|
|
||||||
|
### JamTrackLoadJmep(fqId, jmepData)
|
||||||
|
|
||||||
|
**Purpose:** Load tempo/pitch modifications for JamTrack playback
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.JamTrackLoadJmep(fqId, jmepData)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `fqId` (string): Fully-qualified ID `{jamTrackId}-{sampleRate}`
|
||||||
|
- `jmepData` (object): JMEP data structure with tempo/pitch settings
|
||||||
|
|
||||||
|
**Returns:** Void
|
||||||
|
|
||||||
|
**Usage pattern** (session.js:2749-2757):
|
||||||
|
```javascript
|
||||||
|
if(jamTrack.jmep) {
|
||||||
|
logger.debug("setting jmep data");
|
||||||
|
context.jamClient.JamTrackLoadJmep(fqId, jamTrack.jmep);
|
||||||
|
} else {
|
||||||
|
logger.debug("no jmep data for jamtrack");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load JamTrack AFTER setting JMEP
|
||||||
|
context.jamClient.JamTrackPlay(fqId);
|
||||||
|
```
|
||||||
|
|
||||||
|
**JMEP data structure:**
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
tempo: number, // Tempo modification (BPM or percentage)
|
||||||
|
pitch: number, // Pitch shift (semitones)
|
||||||
|
// Additional fields TBD
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- **Must be called BEFORE `JamTrackPlay()`**
|
||||||
|
- Optional feature - check `if(jamTrack.jmep)` before calling
|
||||||
|
- Allows practicing at different tempos without re-encoding
|
||||||
|
- Pitch shift for transposition to different keys
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Playback Control Methods
|
||||||
|
|
||||||
|
### SessionJamTrackSeekMs()
|
||||||
|
|
||||||
|
**Purpose:** Seek to specific position in JamTrack playback
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.SessionJamTrackSeekMs(positionMs)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `positionMs` (number): Position in milliseconds
|
||||||
|
|
||||||
|
**Returns:** Void (or boolean - TBD)
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Similar to `SessionTrackSeekMs()` for Backing Tracks
|
||||||
|
- Use for seek bar / scrubbing functionality
|
||||||
|
- Requires JamTrack to be loaded and playing/paused
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SessionCurrrentJamTrackPlayPosMs()
|
||||||
|
|
||||||
|
**Purpose:** Get current playback position in milliseconds
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.SessionCurrrentJamTrackPlayPosMs()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Number (milliseconds)
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- Poll at 500ms intervals for playback monitoring
|
||||||
|
- Similar to `SessionCurrentPlayPosMs()` for Backing Tracks
|
||||||
|
- Use for time display and seek bar position
|
||||||
|
- Returns string - use `parseInt()` before math operations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### SessionGetJamTracksPlayDurationMs()
|
||||||
|
|
||||||
|
**Purpose:** Get total duration of loaded JamTrack in milliseconds
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.SessionGetJamTracksPlayDurationMs()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Number (milliseconds)
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- **Note plural "JamTracks"** in method name (differs from singular in other methods)
|
||||||
|
- Call after JamTrack is loaded to get duration
|
||||||
|
- Use for time display and seek bar maximum
|
||||||
|
- Returns string - use `parseInt()` before math operations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Query Methods
|
||||||
|
|
||||||
|
### GetSampleRate()
|
||||||
|
|
||||||
|
**Purpose:** Get audio interface sample rate (44.1 or 48 kHz)
|
||||||
|
|
||||||
|
**Signature:**
|
||||||
|
```javascript
|
||||||
|
context.jamClient.GetSampleRate()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameters:** None
|
||||||
|
|
||||||
|
**Returns:** Number
|
||||||
|
- `44` for 44.1 kHz
|
||||||
|
- `48` for 48 kHz
|
||||||
|
|
||||||
|
**Usage pattern** (session.js:2745):
|
||||||
|
```javascript
|
||||||
|
var sampleRate = context.jamClient.GetSampleRate();
|
||||||
|
var sampleRateForFilename = sampleRate == 48 ? '48' : '44';
|
||||||
|
var fqId = jamTrack.id + '-' + sampleRateForFilename;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
- **Critical for fqId construction**
|
||||||
|
- Sample rate determined by user's audio interface configuration
|
||||||
|
- JamTrack packages are encoded at specific sample rates
|
||||||
|
- Must match package sample rate for playback
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Comparison: JamTrack vs Backing Track Methods
|
||||||
|
|
||||||
|
| Operation | JamTrack Method | Backing Track Method | Notes |
|
||||||
|
|-----------|-----------------|----------------------|-------|
|
||||||
|
| **Select file** | jQuery dialog | `ShowSelectBackingTrackDialog()` | JamTrack: purchased list; Backing Track: native file picker |
|
||||||
|
| **Open/Load** | `JamTrackPlay(fqId)` | `SessionOpenBackingTrackFile(path)` | JamTrack: ID-based; Backing Track: file path |
|
||||||
|
| **Stop** | `JamTrackStopPlay()` | `SessionCloseBackingTrack(path)` | JamTrack: no params; Backing Track: needs path |
|
||||||
|
| **Check playing** | `JamTrackIsPlaying()` | `isSessionTrackPlaying()` | Same concept |
|
||||||
|
| **Get position** | `SessionCurrrentJamTrackPlayPosMs()` | `SessionCurrentPlayPosMs()` | Same concept |
|
||||||
|
| **Get duration** | `SessionGetJamTracksPlayDurationMs()` | `SessionGetTracksPlayDurationMs()` | Both plural "Tracks" |
|
||||||
|
| **Seek** | `SessionJamTrackSeekMs(ms)` | `SessionTrackSeekMs(ms)` | Same concept |
|
||||||
|
|
||||||
|
**Shared methods** (used by both):
|
||||||
|
- `SessionStartPlay()` - Start playback
|
||||||
|
- `SessionStopPlay()` - Stop playback
|
||||||
|
- `SessionPausePlay()` - Pause playback
|
||||||
|
- `GetSampleRate()` - Audio interface sample rate
|
||||||
|
|
||||||
|
**Key differences:**
|
||||||
|
1. **Identification:** JamTrack uses fqId (`id-sampleRate`), Backing Track uses file path
|
||||||
|
2. **Selection UI:** JamTrack has server-side catalog, Backing Track is local files
|
||||||
|
3. **Synchronization:** JamTrack requires download/keys, Backing Track is immediate
|
||||||
|
4. **Stems:** JamTrack has multiple stem tracks, Backing Track is single file
|
||||||
|
5. **JMEP:** JamTrack supports tempo/pitch modification, Backing Track does not
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Example 1: Complete JamTrack Load Flow
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 1. Get sample rate
|
||||||
|
const sampleRate = jamClient.GetSampleRate(); // 44 or 48
|
||||||
|
const sampleRateStr = sampleRate == 48 ? '48' : '44';
|
||||||
|
const fqId = `${jamTrack.id}-${sampleRateStr}`;
|
||||||
|
|
||||||
|
// 2. Stop any existing playback
|
||||||
|
jamClient.JamTrackStopPlay();
|
||||||
|
|
||||||
|
// 3. Load JMEP if present (tempo/pitch modifications)
|
||||||
|
if (jamTrack.jmep) {
|
||||||
|
jamClient.JamTrackLoadJmep(fqId, jamTrack.jmep);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Load JamTrack
|
||||||
|
const result = jamClient.JamTrackPlay(fqId);
|
||||||
|
if (!result) {
|
||||||
|
console.error('Failed to load JamTrack');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Start playback
|
||||||
|
jamClient.SessionStartPlay();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: Download and Sync
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 1. Start download
|
||||||
|
jamClient.JamTrackDownload(
|
||||||
|
jamTrackId,
|
||||||
|
mixdownId,
|
||||||
|
userId,
|
||||||
|
'onProgress', // Callback names as strings
|
||||||
|
'onSuccess',
|
||||||
|
'onFail'
|
||||||
|
);
|
||||||
|
|
||||||
|
// 2. On download success, request encryption keys
|
||||||
|
function onSuccess() {
|
||||||
|
jamClient.JamTrackKeysRequest();
|
||||||
|
|
||||||
|
// Poll for key availability
|
||||||
|
const checkKeys = setInterval(() => {
|
||||||
|
const detail = jamClient.JamTrackGetTrackDetail(fqId);
|
||||||
|
if (detail.key_state === 'AVAILABLE') {
|
||||||
|
clearInterval(checkKeys);
|
||||||
|
// Now can call JamTrackPlay(fqId)
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: Playback Monitoring
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Poll every 500ms for position updates
|
||||||
|
const pollInterval = setInterval(async () => {
|
||||||
|
if (!jamClient.JamTrackIsPlaying()) {
|
||||||
|
clearInterval(pollInterval);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const position = parseInt(jamClient.SessionCurrrentJamTrackPlayPosMs());
|
||||||
|
const duration = parseInt(jamClient.SessionGetJamTracksPlayDurationMs());
|
||||||
|
|
||||||
|
updateUI(position, duration);
|
||||||
|
}, 500);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critical Notes for React Implementation
|
||||||
|
|
||||||
|
1. **fqId format is mandatory:** Always `{jamTrackId}-{sampleRate}`
|
||||||
|
2. **Sample rate matters:** Must match package sample rate (44 or 48)
|
||||||
|
3. **Load order:** JMEP → JamTrackPlay → SessionStartPlay
|
||||||
|
4. **String returns:** All position/duration methods return strings, use `parseInt()`
|
||||||
|
5. **Async operations:** Download and key fetching are asynchronous with callbacks
|
||||||
|
6. **Callback names:** Pass callback names as strings, not function references
|
||||||
|
7. **Global scope:** Callback functions must be accessible globally to native client
|
||||||
|
8. **Shared playback controls:** Use Session* methods (Start/Stop/Pause) like Backing Track
|
||||||
|
|
||||||
|
## Method Availability
|
||||||
|
|
||||||
|
All methods assume native client is available (`gon.isNativeClient === true`). In browser mode, show appropriate fallback UI directing users to download the native client.
|
||||||
Loading…
Reference in New Issue