Files
aes67-ESP32-P4/components/spotify/include/spotify.h
T
bsncubed b8702e6faa Spotify: tell cspot when a new track becomes audible
The Mac dropped the device soon after the first track change: we never
called SpircHandler::notifyAudioReachedPlayback(), so cspot's queue did
not advance and the state sent to Spotify stalled.
- The data callback records a boundary (output write position, track
  id) when the track id changes; the session loop (<= 200 ms) calls
  notifyAudioReachedPlayback(id) once playback (ring read position)
  passes it, and notifyAudioEnded() after DEPLETED once the buffer is
  empty. PLAYBACK_START clears boundaries (next data is a new one),
  seek/flush drop pending ones.
- audio_ring exposes its write/read frame counters (wrap-safe compare).
- Verified: 10 min on the Mac without a disconnect, every track change
  notified ("track audible, Spotify notified"), app shows the playing
  track (switches up to ~3-5 s early), 0 underruns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 20:47:28 +10:00

49 lines
2.0 KiB
C

// Spotify Connect (cspot). Project code; GPL-3.0 through cspot.
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
SPOTIFY_EV_PLAY, // playback (re)started or resumed
SPOTIFY_EV_PAUSE,
SPOTIFY_EV_FLUSH, // skip, seek, new track: drop buffered audio
SPOTIFY_EV_VOLUME, // value: 0..65535
} spotify_event_t;
// PCM from Spotify: 44.1 kHz stereo s16 interleaved. Return the frames taken (may block).
typedef size_t (*spotify_pcm_cb_t)(const int16_t *pcm, size_t frames);
typedef void (*spotify_event_cb_t)(spotify_event_t ev, int value);
// Output positions in frames (monotonic, wrap at 2^32): written into the output buffer so far, and
// played out so far. Used to tell Spotify when a new track actually becomes audible.
typedef uint32_t (*spotify_pos_cb_t)(void);
// Registers the zeroconf endpoints (/spotify_info), starts the session task and applies the config.
esp_err_t spotify_init(spotify_pcm_cb_t pcm, spotify_event_cb_t event, spotify_pos_cb_t written,
spotify_pos_cb_t played);
// Re-read the "source" config: enabled (advertised, sessions accepted) when mode is spotify/auto and
// the client credentials are set; otherwise not advertised and a running session is ended.
// A new device name ends the session and re-advertises.
void spotify_apply(void);
// Pause/resume the running session (the Spotify app follows). No-op without a session.
void spotify_pause(bool pause);
// Suspend: end any running session (waits until its tasks are gone, max ~3 s) and refuse new ones.
// Resume: back to what the config says. Used around firmware uploads.
void spotify_suspend(bool suspend);
// The player's volume (0..100 %): reported to the Spotify app when a session starts (else the app
// shows 0 while we play at the player's level), and pushed to a running session.
void spotify_set_volume(int pct);
// Current state for status.spotify_state.
const char *spotify_state(void);
#ifdef __cplusplus
}
#endif