Display for AirPlay / Bluetooth (still WIP)

This commit is contained in:
philippe44
2020-01-26 01:31:43 -08:00
parent dc392b342f
commit 1fd31471a2
18 changed files with 704 additions and 53 deletions

View File

@@ -532,7 +532,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
ctx->active_remote.thread = xTaskCreateStatic( (TaskFunction_t) search_remote, "search_remote", SEARCH_STACK_SIZE, ctx, ESP_TASK_PRIO_MIN + 1, ctx->active_remote.xStack, ctx->active_remote.xTaskBuffer);
#endif
} else if (!strcmp(method, "SETUP") && ((buf = kd_lookup(headers, "Transport")) != NULL)) {
} else if (!strcmp(method, "SETUP") && ((buf = kd_lookup(headers, "Transport")) != NULL)) {
char *p;
rtp_resp_t rtp = { 0 };
short unsigned tport = 0, cport = 0;
@@ -571,7 +571,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
kd_add(resp, "Audio-Latency", latency);
}
buf = kd_lookup(headers, "RTP-Info");
buf = kd_lookup(headers, "RTP-Info");
if (buf && (p = strcasestr(buf, "seq")) != NULL) sscanf(p, "%*[^=]=%hu", &seqno);
if (buf && (p = strcasestr(buf, "rtptime")) != NULL) sscanf(p, "%*[^=]=%u", &rtptime);
@@ -584,7 +584,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
unsigned rtptime = 0;
char *p;
buf = kd_lookup(headers, "RTP-Info");
buf = kd_lookup(headers, "RTP-Info");
if ((p = strcasestr(buf, "seq")) != NULL) sscanf(p, "%*[^=]=%hu", &seqno);
if ((p = strcasestr(buf, "rtptime")) != NULL) sscanf(p, "%*[^=]=%u", &rtptime);
@@ -615,7 +615,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
LOG_INFO("[%p]: mDNS search task terminated", ctx);
#endif
memset(&ctx->active_remote, 0, sizeof(ctx->active_remote));
NFREE(ctx->rtsp.aeskey);
NFREE(ctx->rtsp.aesiv);
@@ -626,9 +626,17 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
} else if (!strcmp(method, "SET_PARAMETER")) {
char *p;
if (body && (p = strcasestr(body, "volume")) != NULL) {
if (body && (p = strcasestr(body, "volume")) != NULL) {
float volume;
sscanf(p, "%*[^:]:%f", &volume);
LOG_INFO("[%p]: SET PARAMETER volume %f", ctx, volume);
volume = (volume == -144.0) ? 0 : (1 + volume / 30);
success = ctx->cmd_cb(RAOP_VOLUME, volume);
} else if (body && (p = strcasestr(body, "progress")) != NULL) {
u32_t start, current, stop = 0;
sscanf(p, "%*[^:]:%u/%u/%u", &start, &current, &stop);
current = (current - start) / 44100;
if (stop) stop = (stop - start) / 44100;
LOG_INFO("[%p]: SET PARAMETER progress %u/%u %s", ctx, current, stop, p);
@@ -636,15 +644,16 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
}
if (body && ((p = kd_lookup(headers, "Content-Type")) != NULL) && !strcasecmp(p, "application/x-dmap-tagged")) {
struct metadata_s metadata;
dmap_settings settings = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, on_dmap_string, NULL,
NULL
};
LOG_INFO("[%p]: received metadata");
settings.ctx = &metadata;
memset(&metadata, 0, sizeof(struct metadata_s));
if (!dmap_parse(&settings, body, len)) {
if (!dmap_parse(&settings, body, len)) {
LOG_INFO("[%p]: received metadata\n\tartist: %s\n\talbum: %s\n\ttitle: %s",
ctx, metadata.artist, metadata.album, metadata.title);
success = ctx->cmd_cb(RAOP_METADATA, metadata.artist, metadata.album, metadata.title);

View File

@@ -14,9 +14,10 @@
#include "config.h"
#include "raop.h"
#include "audio_controls.h"
#include "display.h"
#include "accessors.h"
#include "log_util.h"
#include "trace.h"
#ifndef CONFIG_AIRPLAY_NAME
@@ -28,6 +29,7 @@ log_level util_loglevel;
static log_level *loglevel = &raop_loglevel;
static struct raop_ctx_s *raop;
raop_cmd_vcb_t cmd_handler_chain;
static void raop_volume_up(void) {
raop_cmd(raop, RAOP_VOLUME_UP, NULL);
@@ -77,6 +79,51 @@ const static actrls_t controls = {
raop_prev, raop_next, // prev, next
};
/****************************************************************************************
* Command handler
*/
bool cmd_handler(raop_event_t event, ...) {
bool res = true;
va_list args;
va_start(args, event);
switch(event) {
case RAOP_SETUP:
displayer_control(DISPLAYER_ACTIVATE);
res = cmd_handler_chain(event, args);
break;
case RAOP_STOP:
displayer_control(DISPLAYER_SUSPEND);
res = cmd_handler_chain(event, args);
break;
case RAOP_METADATA: {
int speed;
char *artist = va_arg(args, char*), *album = va_arg(args, char*), *title = va_arg(args, char*);
char *string = config_metadata_format(artist, album, title, &speed, 256);
displayer_scroll(string, speed);
free(string);
break;
}
case RAOP_PROGRESS: {
u32_t elapsed = va_arg(args, u32_t);
u32_t duration = va_arg(args, u32_t);
char msg[32];
if (elapsed > 3600) snprintf(msg, 32, "AIRPLAY %2u:%02u:%02u", elapsed / 3600, elapsed / 60, elapsed % 60);
else snprintf(msg, 32, "AIRPLAY %2u:%02u", elapsed / 60, elapsed % 60);
display->line(1, DISPLAY_LEFT, 0, DISPLAY_CLEAR | DISPLAY_UPDATE, msg);
break;
}
default:
res = cmd_handler_chain(event, args);
}
va_end(args);
return res;
}
/****************************************************************************************
* Airplay taking/giving audio system's control
*/
@@ -96,7 +143,7 @@ void raop_sink_deinit(void) {
/****************************************************************************************
* Airplay sink initialization
*/
void raop_sink_init(raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) {
void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) {
const char *hostname;
char sink_name[64-6] = CONFIG_AIRPLAY_NAME;
tcpip_adapter_ip_info_t ipInfo;
@@ -123,7 +170,8 @@ void raop_sink_init(raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) {
// create RAOP instance, latency is set by controller
uint8_t mac[6];
esp_read_mac(mac, ESP_MAC_WIFI_STA);
raop = raop_create(host, sink_name, mac, 0, cmd_cb, data_cb);
cmd_handler_chain = cmd_cb;
raop = raop_create(host, sink_name, mac, 0, cmd_handler, data_cb);
}
/****************************************************************************************
@@ -131,6 +179,7 @@ void raop_sink_init(raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) {
*/
void raop_disconnect(void) {
LOG_INFO("forced disconnection");
displayer_control(DISPLAYER_SHUTDOWN);
raop_cmd(raop, RAOP_STOP, NULL);
actrls_unset();
}

View File

@@ -10,20 +10,22 @@
#define RAOP_SINK_H
#include <stdint.h>
#include <stdarg.h>
#define RAOP_SAMPLE_RATE 44100
typedef enum { RAOP_SETUP, RAOP_STREAM, RAOP_PLAY, RAOP_FLUSH, RAOP_PAUSE, RAOP_STOP,
typedef enum { RAOP_SETUP, RAOP_STREAM, RAOP_PLAY, RAOP_FLUSH, RAOP_METADATA, RAOP_PROGRESS, RAOP_PAUSE, RAOP_STOP,
RAOP_VOLUME, RAOP_TIMING, RAOP_PREV, RAOP_NEXT, RAOP_REW, RAOP_FWD,
RAOP_VOLUME_UP, RAOP_VOLUME_DOWN, RAOP_RESUME, RAOP_TOGGLE } raop_event_t ;
typedef bool (*raop_cmd_cb_t)(raop_event_t event, void *param);
typedef bool (*raop_cmd_cb_t)(raop_event_t event, ...);
typedef bool (*raop_cmd_vcb_t)(raop_event_t event, va_list args);
typedef void (*raop_data_cb_t)(const u8_t *data, size_t len, u32_t playtime);
/**
* @brief init sink mode (need to be provided)
*/
void raop_sink_init(raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb);
void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb);
/**
* @brief deinit sink mode (need to be provided)

View File

@@ -429,7 +429,7 @@ static void buffer_put_packet(rtp_t *ctx, seq_t seqno, unsigned rtptime, bool fi
ctx->ab_read = seqno;
ctx->flush_seqno = -1;
ctx->playing = true;
ctx->resent_req = ctx->resent_rec = ctx->silent_frames = ctx->discarded = 0;
ctx->resent_req = ctx->resent_rec = ctx->silent_frames = ctx->discarded = 0;
playtime = ctx->synchro.time + (((s32_t)(rtptime - ctx->synchro.rtp)) * 1000) / RAOP_SAMPLE_RATE;
ctx->cmd_cb(RAOP_PLAY, playtime);
} else {
@@ -671,7 +671,7 @@ static void *rtp_thread_func(void *arg) {
if (!count--) {
rtp_request_timing(ctx);
count = 3;
count = 3;
}
if ((ctx->synchro.status & RTP_SYNC) && (ctx->synchro.status & NTP_SYNC)) ctx->cmd_cb(RAOP_TIMING);

View File

@@ -47,11 +47,8 @@ typedef struct metadata_s {
u8_t channels;
} metadata_t;
/*
void free_metadata(struct metadata_s *metadata);
void dup_metadata(struct metadata_s *dst, struct metadata_s *src);
*/
u32_t gettime_ms(void);