Add track info support for BT audio sink (#2190)
This commit is contained in:
parent
bf385490d3
commit
6d6433f256
3 changed files with 56 additions and 0 deletions
|
|
@ -43,6 +43,8 @@ void setup() {
|
|||
a2dp.begin();
|
||||
}
|
||||
|
||||
char *nowPlaying = nullptr;
|
||||
|
||||
void loop() {
|
||||
if (BOOTSEL) {
|
||||
if (status == A2DPSink::PAUSED) {
|
||||
|
|
@ -54,4 +56,9 @@ void loop() {
|
|||
}
|
||||
while (BOOTSEL);
|
||||
}
|
||||
if (!nowPlaying || strcmp(nowPlaying, a2dp.trackTitle())) {
|
||||
free(nowPlaying);
|
||||
nowPlaying = strdup(a2dp.trackTitle());
|
||||
Serial.printf("NOW PLAYING: %s\n", nowPlaying);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -559,6 +559,14 @@ void A2DPSink::avrcp_controller_packet_handler(uint8_t packet_type, uint16_t cha
|
|||
break;
|
||||
|
||||
case AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED:
|
||||
_title[0] = 0;
|
||||
_artist[0] = 0;
|
||||
_album[0] = 0;
|
||||
_genre[0] = 0;
|
||||
avrcp_controller_get_now_playing_info(avrcp_connection->avrcp_cid);
|
||||
if (_trackChangedCB) {
|
||||
_trackChangedCB(_trackChangedData);
|
||||
}
|
||||
DEBUGV("AVRCP Controller: Track changed\n");
|
||||
break;
|
||||
|
||||
|
|
@ -585,6 +593,8 @@ void A2DPSink::avrcp_controller_packet_handler(uint8_t packet_type, uint16_t cha
|
|||
case AVRCP_SUBEVENT_NOW_PLAYING_TITLE_INFO:
|
||||
if (avrcp_subevent_now_playing_title_info_get_value_len(packet) > 0) {
|
||||
memcpy(avrcp_subevent_value, avrcp_subevent_now_playing_title_info_get_value(packet), avrcp_subevent_now_playing_title_info_get_value_len(packet));
|
||||
strncpy(_title, (char *)avrcp_subevent_value, sizeof(_title));
|
||||
_title[sizeof(_title) - 1] = 0;
|
||||
DEBUGV("AVRCP Controller: Title %s\n", avrcp_subevent_value);
|
||||
}
|
||||
break;
|
||||
|
|
@ -592,6 +602,8 @@ void A2DPSink::avrcp_controller_packet_handler(uint8_t packet_type, uint16_t cha
|
|||
case AVRCP_SUBEVENT_NOW_PLAYING_ARTIST_INFO:
|
||||
if (avrcp_subevent_now_playing_artist_info_get_value_len(packet) > 0) {
|
||||
memcpy(avrcp_subevent_value, avrcp_subevent_now_playing_artist_info_get_value(packet), avrcp_subevent_now_playing_artist_info_get_value_len(packet));
|
||||
strncpy(_artist, (char *)avrcp_subevent_value, sizeof(_artist));
|
||||
_artist[sizeof(_artist) - 1] = 0;
|
||||
DEBUGV("AVRCP Controller: Artist %s\n", avrcp_subevent_value);
|
||||
}
|
||||
break;
|
||||
|
|
@ -599,6 +611,8 @@ void A2DPSink::avrcp_controller_packet_handler(uint8_t packet_type, uint16_t cha
|
|||
case AVRCP_SUBEVENT_NOW_PLAYING_ALBUM_INFO:
|
||||
if (avrcp_subevent_now_playing_album_info_get_value_len(packet) > 0) {
|
||||
memcpy(avrcp_subevent_value, avrcp_subevent_now_playing_album_info_get_value(packet), avrcp_subevent_now_playing_album_info_get_value_len(packet));
|
||||
strncpy(_album, (char *)avrcp_subevent_value, sizeof(_album));
|
||||
_album[sizeof(_album) - 1] = 0;
|
||||
DEBUGV("AVRCP Controller: Album %s\n", avrcp_subevent_value);
|
||||
}
|
||||
break;
|
||||
|
|
@ -606,6 +620,8 @@ void A2DPSink::avrcp_controller_packet_handler(uint8_t packet_type, uint16_t cha
|
|||
case AVRCP_SUBEVENT_NOW_PLAYING_GENRE_INFO:
|
||||
if (avrcp_subevent_now_playing_genre_info_get_value_len(packet) > 0) {
|
||||
memcpy(avrcp_subevent_value, avrcp_subevent_now_playing_genre_info_get_value(packet), avrcp_subevent_now_playing_genre_info_get_value_len(packet));
|
||||
strncpy(_genre, (char *)avrcp_subevent_value, sizeof(_genre));
|
||||
_genre[sizeof(_genre) - 1] = 0;
|
||||
DEBUGV("AVRCP Controller: Genre %s\n", avrcp_subevent_value);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@
|
|||
class A2DPSink : public Stream {
|
||||
public:
|
||||
A2DPSink() {
|
||||
_title[0] = 0;
|
||||
_artist[0] = 0;
|
||||
_album[0] = 0;
|
||||
_genre[0] = 0;
|
||||
}
|
||||
virtual int available() override {
|
||||
return 0; // Unreadable, this is output only
|
||||
|
|
@ -96,6 +100,11 @@ public:
|
|||
_connectData = cbData;
|
||||
}
|
||||
|
||||
void onTrackChanged(void (*cb)(void *), void *cbData = nullptr) {
|
||||
_trackChangedCB = cb;
|
||||
_trackChangedData = cbData;
|
||||
}
|
||||
|
||||
typedef enum { STOPPED, PLAYING, PAUSED } PlaybackStatus;
|
||||
void onPlaybackStatus(void (*cb)(void *, PlaybackStatus), void *cbData = nullptr) {
|
||||
_playbackStatusCB = cb;
|
||||
|
|
@ -190,6 +199,22 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const char *trackTitle() {
|
||||
return _title;
|
||||
}
|
||||
|
||||
const char *trackArtist() {
|
||||
return _artist;
|
||||
}
|
||||
|
||||
const char *trackAlbum() {
|
||||
return _album;
|
||||
}
|
||||
|
||||
const char *trackGenre() {
|
||||
return _genre;
|
||||
}
|
||||
|
||||
private:
|
||||
void handle_pcm_data(int16_t * data, int num_audio_frames, int num_channels, int sample_rate, void * context);
|
||||
|
||||
|
|
@ -224,6 +249,9 @@ private:
|
|||
void *_connectData;
|
||||
void (*_playbackStatusCB)(void *, PlaybackStatus) = nullptr;
|
||||
void *_playbackStatusData;
|
||||
void (*_trackChangedCB)(void *) = nullptr;
|
||||
void *_trackChangedData;
|
||||
|
||||
char *_name = nullptr;
|
||||
uint8_t _sourceAddress[6];
|
||||
|
||||
|
|
@ -301,4 +329,9 @@ private:
|
|||
a2dp_sink_avrcp_connection_t a2dp_sink_avrcp_connection;
|
||||
|
||||
int16_t output_buffer[(128 + 16) * NUM_CHANNELS]; // 16 * 8 * 2
|
||||
|
||||
char _title[64];
|
||||
char _artist[64];
|
||||
char _album[64];
|
||||
char _genre[32];
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue