import TrackPlayer, { isPlaying } from 'react-native-track-player'; import type { Track } from '@/types/audio'; import { setupPlayer } from './trackPlayer'; import { SAMPLE_TRACKS, toRntpTrack } from './sampleTracks'; /** * Transport actions screens call. Thin wrappers over RNTP so the UI never * imports the engine directly — at M3/M4 this is where a custom Media3 module * would slot in behind the same function signatures. */ /** * Set up the player. Setup is deferred to here (a user-initiated play) rather * than app launch: RNTP starts a foreground MediaSession service on setup, and * Android only permits starting a foreground service while the app is in the * foreground. */ async function ensurePlayerReady(): Promise { await setupPlayer(); } /** Replace the queue with the given tracks and start playing at startIndex. */ export async function playTracks(tracks: Track[], startIndex = 0): Promise { if (tracks.length === 0) return; await ensurePlayerReady(); await TrackPlayer.setQueue(tracks.map(toRntpTrack)); if (startIndex > 0) { await TrackPlayer.skip(startIndex); } await TrackPlayer.play(); } /** Fisher–Yates shuffle a copy of the tracks and play from the top. */ export async function shuffleTracks(tracks: Track[]): Promise { const shuffled = [...tracks]; for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; } await playTracks(shuffled); } /** M0 demo entry point: load the streamed sample queue if nothing is queued. */ export async function playSample(): Promise { await ensurePlayerReady(); const queue = await TrackPlayer.getQueue(); if (queue.length === 0) { await TrackPlayer.add(SAMPLE_TRACKS.map(toRntpTrack)); } await TrackPlayer.play(); } export const play = (): Promise => TrackPlayer.play(); export const pause = (): Promise => TrackPlayer.pause(); export const seekTo = (seconds: number): Promise => TrackPlayer.seekTo(seconds); export async function togglePlay(): Promise { const { playing } = await isPlaying(); if (playing) { await TrackPlayer.pause(); } else { await ensurePlayerReady(); await TrackPlayer.play(); } } export async function skipToNext(): Promise { try { await TrackPlayer.skipToNext(); } catch { // no next track — ignore } } export async function skipToPrevious(): Promise { try { await TrackPlayer.skipToPrevious(); } catch { // no previous track — ignore } }