esp32-audio-player 0.1.0
Audio player engine for ESP32
Loading...
Searching...
No Matches
a2dp_sink.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
15//
16// Shutting down: a2dp_xq_deinit() before audio_player_stop(), so no headphone button reaches a
17// player that no longer exists.
23#pragma once
24
25#include "a2dp_xq.h"
26#include "audio_player/player.h"
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32static inline int ap_a2dp_negotiate(audio_sink_t *s, const audio_format_t *src, audio_format_t *out) {
33 (void)s;
34 if (!src || !out || !src->sample_rate || !src->channels) return CORE_EINVAL;
35 if (src->dop) return CORE_EUNSUPPORTED;
36 out->sample_rate = A2DP_XQ_SAMPLE_RATE;
37 out->channels = 2;
38 out->bits = 16;
39 out->dop = false;
40 return CORE_OK;
41}
42
43static inline int ap_a2dp_open(audio_sink_t *s, const audio_format_t *fmt) {
44 (void)s;
45 if (!fmt) return CORE_EINVAL;
46 if (fmt->sample_rate != A2DP_XQ_SAMPLE_RATE || fmt->channels != 2 || fmt->dop) return CORE_EUNSUPPORTED;
47 return a2dp_xq_start() == ESP_OK ? CORE_OK : CORE_EIO;
48}
49
50static inline int32_t ap_a2dp_write(audio_sink_t *s, const int32_t *pcm, uint32_t frames, uint32_t timeout_ms) {
51 (void)s;
52 int32_t n = a2dp_xq_write_q31(pcm, frames, timeout_ms);
53 if (n < 0) return CORE_EINVAL;
54 return n;
55}
56
57static inline void ap_a2dp_pause(audio_sink_t *s, bool paused) {
58 (void)s;
59 a2dp_xq_pause(paused);
60}
61
62static inline void ap_a2dp_flush(audio_sink_t *s) {
63 (void)s;
64 a2dp_xq_flush();
65}
66
67static inline int ap_a2dp_set_volume_db(audio_sink_t *s, float db) {
68 (void)s;
69 a2dp_xq_set_volume_db(db);
70 return CORE_OK;
71}
72
73static inline uint32_t ap_a2dp_buffered_frames(audio_sink_t *s) {
74 (void)s;
75 return a2dp_xq_buffered_frames();
76}
77
78static inline void ap_a2dp_describe(audio_sink_t *s, char *out, size_t out_size) {
79 (void)s;
80 if (!out || !out_size) return;
81 a2dp_xq_describe(out, out_size);
82 if (!out[0]) core_strlcpy(out, "Bluetooth", out_size);
83}
84
85static inline void ap_a2dp_close(audio_sink_t *s) {
86 (void)s;
87 a2dp_xq_stop();
88}
89
91static inline audio_sink_t *audio_player_a2dp_sink(void) {
92 static audio_sink_t sink;
93 sink.name = "bluetooth";
95 sink.ctx = NULL;
96 sink.negotiate = ap_a2dp_negotiate;
97 sink.open = ap_a2dp_open;
98 sink.write = ap_a2dp_write;
99 sink.pause = ap_a2dp_pause;
100 sink.flush = ap_a2dp_flush;
101 sink.set_volume_db = ap_a2dp_set_volume_db;
102 sink.buffered_frames = ap_a2dp_buffered_frames;
103 sink.describe = ap_a2dp_describe;
104 sink.close = ap_a2dp_close;
105 return &sink;
106}
107
110static inline void audio_player_a2dp_remote(a2dp_xq_remote_t cmd, int value, void *user) {
111 player_t *p = (player_t *)user;
112 if (!p) return;
113 switch (cmd) {
114 case A2DP_XQ_REMOTE_PLAY_PAUSE: player_cmd_toggle_pause(p); break;
115 case A2DP_XQ_REMOTE_PLAY: player_cmd_resume(p); break;
116 case A2DP_XQ_REMOTE_PAUSE: player_cmd_pause(p); break;
117 case A2DP_XQ_REMOTE_STOP: player_cmd_pause(p); break;
118 case A2DP_XQ_REMOTE_NEXT: player_cmd_next(p); break;
119 case A2DP_XQ_REMOTE_PREV: player_cmd_prev(p); break;
120 case A2DP_XQ_REMOTE_VOL_UP: player_cmd_volume_step(p, 1); break;
121 case A2DP_XQ_REMOTE_VOL_DOWN: player_cmd_volume_step(p, -1); break;
122 case A2DP_XQ_REMOTE_VOLUME_ABS: player_cmd_set_volume_db(p, a2dp_xq_volume_to_db(value)); break;
123 case A2DP_XQ_REMOTE_LINK_DOWN: player_cmd_pause(p); break;
124 }
125}
126
127#ifdef __cplusplus
128}
129#endif
static int ap_a2dp_negotiate(audio_sink_t *s, const audio_format_t *src, audio_format_t *out)
The player resamples everything to 44.1 kHz for this sink and keeps its DSP output at 32 bits; the si...
Definition a2dp_sink.h:32
static void audio_player_a2dp_remote(a2dp_xq_remote_t cmd, int value, void *user)
a2dp_xq_config_t.remote_cb with remote_user = the player: the headphone buttons control the player,...
Definition a2dp_sink.h:110
static void ap_a2dp_describe(audio_sink_t *s, char *out, size_t out_size)
Definition a2dp_sink.h:78
static void ap_a2dp_pause(audio_sink_t *s, bool paused)
Definition a2dp_sink.h:57
static int32_t ap_a2dp_write(audio_sink_t *s, const int32_t *pcm, uint32_t frames, uint32_t timeout_ms)
Definition a2dp_sink.h:50
static int ap_a2dp_set_volume_db(audio_sink_t *s, float db)
Definition a2dp_sink.h:67
static audio_sink_t * audio_player_a2dp_sink(void)
The sink. Call after a2dp_xq_init(); it stays valid until a2dp_xq_deinit().
Definition a2dp_sink.h:91
static void ap_a2dp_close(audio_sink_t *s)
Definition a2dp_sink.h:85
static uint32_t ap_a2dp_buffered_frames(audio_sink_t *s)
Definition a2dp_sink.h:73
static void ap_a2dp_flush(audio_sink_t *s)
Definition a2dp_sink.h:62
static int ap_a2dp_open(audio_sink_t *s, const audio_format_t *fmt)
Definition a2dp_sink.h:43
size_t core_strlcpy(char *dst, const char *src, size_t size)
Small string helpers (UTF-8 safe where noted).
@ CORE_EUNSUPPORTED
format or feature not supported
Definition base.h:25
@ CORE_EIO
Definition base.h:24
@ CORE_EINVAL
Definition base.h:23
@ CORE_OK
Definition base.h:19
Playback engine: queue, gapless transitions, DSP, output negotiation, resume.
void player_cmd_resume(player_t *p)
from STOPPED with a non-empty queue: starts the current item
void player_cmd_volume_step(player_t *p, int steps)
void player_cmd_pause(player_t *p)
void player_cmd_next(player_t *p)
void player_cmd_prev(player_t *p)
restart the track if more than 3 s played
void player_cmd_toggle_pause(player_t *p)
struct player player_t
Definition player.h:111
void player_cmd_set_volume_db(player_t *p, float db)
@ SINK_CAP_HW_VOLUME
set_volume_db works; DSP software volume stays off
Definition sink.h:18
@ SINK_CAP_DITHERS
the sink reduces Q31 to its bit depth with its own TPDF dither
Definition sink.h:24
Definition audio.h:23
bool dop
true: frames are DoP-encoded DSD, bypass all processing
Definition audio.h:27
uint8_t channels
1 or 2 (mono is upmixed by the player before the sink)
Definition audio.h:25
uint32_t sample_rate
Hz, e.g. 44100.
Definition audio.h:24
uint8_t bits
significant bits of the source: 16, 24 or 32
Definition audio.h:26