mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-09 21:17:18 +03:00
Merge branch 'master' into httpd
Conflicts: components/wifi-manager/http_server.c components/wifi-manager/wifi_manager.c main/config.c main/config.h
This commit is contained in:
@@ -43,7 +43,8 @@
|
||||
#include "dmap_parser.h"
|
||||
#include "log_util.h"
|
||||
|
||||
#define RTSP_STACK_SIZE (8*1024)
|
||||
#define RTSP_STACK_SIZE (8*1024)
|
||||
#define SEARCH_STACK_SIZE (2*1048)
|
||||
|
||||
typedef struct raop_ctx_s {
|
||||
#ifdef WIN32
|
||||
@@ -60,7 +61,7 @@ typedef struct raop_ctx_s {
|
||||
#else
|
||||
TaskHandle_t thread, search_thread, joiner;
|
||||
StaticTask_t *xTaskBuffer;
|
||||
StackType_t *xStack;
|
||||
StackType_t xStack[RTSP_STACK_SIZE] __attribute__ ((aligned (4)));
|
||||
#endif
|
||||
unsigned char mac[6];
|
||||
int latency;
|
||||
@@ -71,14 +72,19 @@ typedef struct raop_ctx_s {
|
||||
struct rtp_s *rtp;
|
||||
raop_cmd_cb_t cmd_cb;
|
||||
raop_data_cb_t data_cb;
|
||||
/*
|
||||
struct {
|
||||
char DACPid[32], id[32];
|
||||
struct in_addr host;
|
||||
u16_t port;
|
||||
#ifdef WIN32
|
||||
struct mDNShandle_s *handle;
|
||||
#else
|
||||
bool running;
|
||||
TaskHandle_t thread, joiner;
|
||||
StaticTask_t *xTaskBuffer;
|
||||
StackType_t xStack[SEARCH_STACK_SIZE] __attribute__ ((aligned (4)));;
|
||||
#endif
|
||||
} active_remote;
|
||||
*/
|
||||
void *owner;
|
||||
} raop_ctx_t;
|
||||
|
||||
@@ -98,7 +104,7 @@ static void* search_remote(void *args);
|
||||
extern char private_key[];
|
||||
|
||||
enum { RSA_MODE_KEY, RSA_MODE_AUTH };
|
||||
|
||||
|
||||
static void on_dmap_string(void *ctx, const char *code, const char *name, const char *buf, size_t len);
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
@@ -186,26 +192,23 @@ struct raop_ctx_s *raop_create(struct in_addr host, char *name,
|
||||
id[63] = '\0';
|
||||
ctx->svc = mdnsd_register_svc(ctx->svr, id, "_raop._tcp.local", ctx->port, NULL, (const char**) txt);
|
||||
pthread_create(&ctx->thread, NULL, &rtsp_thread, ctx);
|
||||
pthread_create(&ctx->thread, NULL, &rtsp_thread, ctx);
|
||||
|
||||
#else
|
||||
LOG_INFO("starting mDNS with %s", id);
|
||||
ESP_ERROR_CHECK( mdns_service_add(id, "_raop", "_tcp", ctx->port, txt, sizeof(txt) / sizeof(mdns_txt_item_t)) );
|
||||
|
||||
ctx->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
ctx->xStack = (StackType_t*) malloc(RTSP_STACK_SIZE);
|
||||
ctx->thread = xTaskCreateStatic( (TaskFunction_t) rtsp_thread, "RTSP_thread", RTSP_STACK_SIZE, ctx, ESP_TASK_PRIO_MIN + 1, ctx->xStack, ctx->xTaskBuffer);
|
||||
#endif
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void raop_delete(struct raop_ctx_s *ctx) {
|
||||
int sock;
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void raop_delete(struct raop_ctx_s *ctx) {
|
||||
#ifdef WIN32
|
||||
int sock;
|
||||
struct sockaddr addr;
|
||||
socklen_t nlen = sizeof(struct sockaddr);
|
||||
#endif
|
||||
|
||||
@@ -214,66 +217,99 @@ void raop_delete(struct raop_ctx_s *ctx) {
|
||||
#ifdef WIN32
|
||||
ctx->running = false;
|
||||
|
||||
|
||||
// wake-up thread by connecting socket, needed for freeBSD
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
getsockname(ctx->sock, (struct sockaddr *) &addr, &nlen);
|
||||
connect(sock, (struct sockaddr*) &addr, sizeof(addr));
|
||||
closesocket(sock);
|
||||
|
||||
#ifdef WIN32
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
getsockname(ctx->sock, (struct sockaddr *) &addr, &nlen);
|
||||
connect(sock, (struct sockaddr*) &addr, sizeof(addr));
|
||||
vTaskDelete(ctx->thread);
|
||||
closesocket(sock);
|
||||
heap_caps_free(ctx->xTaskBuffer);
|
||||
#endif
|
||||
|
||||
|
||||
pthread_join(ctx->thread, NULL);
|
||||
#ifdef WIN32
|
||||
|
||||
rtp_end(ctx->rtp);
|
||||
|
||||
shutdown(ctx->sock, SD_BOTH);
|
||||
closesocket(ctx->sock);
|
||||
|
||||
|
||||
// terminate search, but do not reclaim memory of pthread if never launched
|
||||
if (ctx->active_remote.handle) {
|
||||
close_mDNS(ctx->active_remote.handle);
|
||||
pthread_join(ctx->search_thread, NULL);
|
||||
}
|
||||
|
||||
// stop broadcasting devices
|
||||
mdns_service_remove(ctx->svr, ctx->svc);
|
||||
mdnsd_stop(ctx->svr);
|
||||
#else
|
||||
// first stop the search task if any
|
||||
if (ctx->active_remote.running) {
|
||||
ctx->active_remote.joiner = xTaskGetCurrentTaskHandle();
|
||||
ctx->active_remote.running = false;
|
||||
|
||||
vTaskResume(ctx->active_remote.thread);
|
||||
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||||
vTaskDelete(ctx->active_remote.thread);
|
||||
|
||||
heap_caps_free(ctx->active_remote.xTaskBuffer);
|
||||
}
|
||||
|
||||
// then the RTSP task
|
||||
ctx->joiner = xTaskGetCurrentTaskHandle();
|
||||
ctx->running = false;
|
||||
|
||||
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||||
vTaskDelete(ctx->thread);
|
||||
heap_caps_free(ctx->xTaskBuffer);
|
||||
|
||||
rtp_end(ctx->rtp);
|
||||
|
||||
shutdown(ctx->sock, SHUT_RDWR);
|
||||
closesocket(ctx->sock);
|
||||
|
||||
pthread_join(ctx->search_thread, NULL);
|
||||
}
|
||||
*/
|
||||
|
||||
NFREE(ctx->rtsp.aeskey);
|
||||
NFREE(ctx->rtsp.aesiv);
|
||||
NFREE(ctx->rtsp.fmtp);
|
||||
|
||||
mdns_service_remove("_raop", "_tcp");
|
||||
#endif
|
||||
|
||||
NFREE(ctx->rtsp.aeskey);
|
||||
#else
|
||||
NFREE(ctx->rtsp.aesiv);
|
||||
#endif
|
||||
|
||||
NFREE(ctx->rtsp.fmtp);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void raop_cmd(struct raop_ctx_s *ctx, raop_event_t event, void *param) {
|
||||
struct sockaddr_in addr;
|
||||
int sock;
|
||||
char *command = NULL;
|
||||
|
||||
// first notify the remote controller (if any)
|
||||
switch(event) {
|
||||
case RAOP_REW:
|
||||
command = strdup("beginrew");
|
||||
break;
|
||||
case RAOP_FWD:
|
||||
command = strdup("beginff");
|
||||
break;
|
||||
case RAOP_PREV:
|
||||
command = strdup("previtem");
|
||||
break;
|
||||
case RAOP_NEXT:
|
||||
command = strdup("nextitem");
|
||||
break;
|
||||
case RAOP_TOGGLE:
|
||||
command = strdup("playpause");
|
||||
break;
|
||||
case RAOP_PAUSE:
|
||||
command = strdup("pause");
|
||||
break;
|
||||
case RAOP_PLAY:
|
||||
command = strdup("play");
|
||||
break;
|
||||
case RAOP_RESUME:
|
||||
command = strdup("playresume");
|
||||
break;
|
||||
case RAOP_STOP:
|
||||
command = strdup("stop");
|
||||
break;
|
||||
case RAOP_VOLUME_UP:
|
||||
command = strdup("volumeup");
|
||||
break;
|
||||
@@ -286,9 +322,9 @@ void raop_cmd(struct raop_ctx_s *ctx, raop_event_t event, void *param) {
|
||||
asprintf(&command,"setproperty?dmcp.device-volume=%0.4lf", Volume);
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// no command to send to remote or no remote found yet
|
||||
if (!command || !ctx->active_remote.port) {
|
||||
@@ -317,11 +353,7 @@ void raop_cmd(struct raop_ctx_s *ctx, raop_event_t event, void *param) {
|
||||
if (len > 0) resp[len-1] = '\0';
|
||||
LOG_INFO("[%p]: sending airplay remote\n%s<== received ==>\n%s", ctx, buf, resp);
|
||||
|
||||
len = recv(sock, resp, 512, 0);
|
||||
NFREE(method);
|
||||
LOG_INFO("[%p]: sending airplay remote\n%s<== received ==>\n%s", ctx, buf, resp);
|
||||
|
||||
NFREE(method);
|
||||
NFREE(buf);
|
||||
kd_free(headers);
|
||||
}
|
||||
@@ -366,7 +398,7 @@ static void *rtsp_thread(void *arg) {
|
||||
closesocket(sock);
|
||||
LOG_INFO("RTSP close %u", sock);
|
||||
sock = -1;
|
||||
if (n < 0 || !res) {
|
||||
}
|
||||
}
|
||||
|
||||
if (sock != -1) closesocket(sock);
|
||||
@@ -429,12 +461,27 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
|
||||
kd_add(resp, "Public", "ANNOUNCE, SETUP, RECORD, PAUSE, FLUSH, TEARDOWN, OPTIONS, GET_PARAMETER, SET_PARAMETER");
|
||||
|
||||
} else if (!strcmp(method, "ANNOUNCE")) {
|
||||
|
||||
char *padded, *p;
|
||||
|
||||
|
||||
NFREE(ctx->rtsp.aeskey);
|
||||
NFREE(ctx->rtsp.aesiv);
|
||||
NFREE(ctx->rtsp.fmtp);
|
||||
|
||||
// LMS might has taken over the player, leaving us with a running RTP session (should not happen)
|
||||
if (ctx->rtp) {
|
||||
LOG_WARN("[%p]: closing unfinished RTP session", ctx);
|
||||
rtp_end(ctx->rtp);
|
||||
}
|
||||
|
||||
// same, should not happen unless we have missed a teardown ...
|
||||
if (ctx->active_remote.running) {
|
||||
ctx->active_remote.joiner = xTaskGetCurrentTaskHandle();
|
||||
ctx->active_remote.running = false;
|
||||
|
||||
vTaskResume(ctx->active_remote.thread);
|
||||
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||||
vTaskDelete(ctx->active_remote.thread);
|
||||
|
||||
heap_caps_free(ctx->active_remote.xTaskBuffer);
|
||||
memset(&ctx->active_remote, 0, sizeof(ctx->active_remote));
|
||||
|
||||
@@ -467,13 +514,17 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
|
||||
}
|
||||
|
||||
if ((p = strcasestr(body, "fmtp")) != NULL) {
|
||||
NFREE(padded);
|
||||
p = strextract(p, ":", "\r\n");
|
||||
ctx->rtsp.fmtp = strdup(p);
|
||||
NFREE(p);
|
||||
}
|
||||
|
||||
// on announce, search remote
|
||||
NFREE(p);
|
||||
if ((buf = kd_lookup(headers, "DACP-ID")) != NULL) strcpy(ctx->active_remote.DACPid, buf);
|
||||
if ((buf = kd_lookup(headers, "Active-Remote")) != NULL) strcpy(ctx->active_remote.id, buf);
|
||||
|
||||
#ifdef WIN32
|
||||
ctx->active_remote.handle = init_mDNS(false, ctx->host);
|
||||
pthread_create(&ctx->search_thread, NULL, &search_remote, ctx);
|
||||
#else
|
||||
ctx->active_remote.running = true;
|
||||
@@ -481,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
|
||||
|
||||
ctx->active_remote.handle = init_mDNS(false, ctx->host);
|
||||
} else if (!strcmp(method, "SETUP") && ((buf = kd_lookup(headers, "Transport")) != NULL)) {
|
||||
char *p;
|
||||
rtp_resp_t rtp = { 0 };
|
||||
short unsigned tport = 0, cport = 0;
|
||||
@@ -520,7 +571,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
|
||||
kd_add(resp, "Audio-Latency", latency);
|
||||
}
|
||||
|
||||
snprintf(latency, 6, "%u", ctx->latency);
|
||||
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);
|
||||
|
||||
@@ -533,7 +584,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
|
||||
unsigned rtptime = 0;
|
||||
char *p;
|
||||
|
||||
unsigned short seqno = 0;
|
||||
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);
|
||||
|
||||
@@ -541,20 +592,32 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
|
||||
if (ctx->rtp && rtp_flush(ctx->rtp, seqno, rtptime))
|
||||
success = ctx->cmd_cb(RAOP_FLUSH, NULL);
|
||||
|
||||
// only send FLUSH if useful (discards frames above buffer head and top)
|
||||
} else if (!strcmp(method, "TEARDOWN")) {
|
||||
|
||||
rtp_end(ctx->rtp);
|
||||
|
||||
} else if (!strcmp(method, "TEARDOWN")) {
|
||||
|
||||
ctx->rtp = NULL;
|
||||
|
||||
// need to make sure no search is on-going and reclaim pthread memory
|
||||
#ifdef WIN32
|
||||
if (ctx->active_remote.handle) close_mDNS(ctx->active_remote.handle);
|
||||
pthread_join(ctx->search_thread, NULL);
|
||||
#else
|
||||
ctx->active_remote.joiner = xTaskGetCurrentTaskHandle();
|
||||
ctx->active_remote.running = false;
|
||||
|
||||
// task might not need to be resumed anyway
|
||||
vTaskResume(ctx->active_remote.thread);
|
||||
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||||
vTaskDelete(ctx->active_remote.thread);
|
||||
|
||||
heap_caps_free(ctx->active_remote.xTaskBuffer);
|
||||
|
||||
LOG_INFO("[%p]: mDNS search task terminated", ctx);
|
||||
#endif
|
||||
// need to make sure no search is on-going and reclaim pthread memory
|
||||
|
||||
memset(&ctx->active_remote, 0, sizeof(ctx->active_remote));
|
||||
pthread_join(ctx->search_thread, NULL);
|
||||
NFREE(ctx->rtsp.aeskey);
|
||||
NFREE(ctx->rtsp.aesiv);
|
||||
NFREE(ctx->rtsp.fmtp);
|
||||
|
||||
@@ -563,7 +626,7 @@ 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) {
|
||||
float volume;
|
||||
|
||||
sscanf(p, "%*[^:]:%f", &volume);
|
||||
@@ -585,7 +648,6 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
|
||||
LOG_INFO("[%p]: received metadata\n\tartist: %s\n\talbum: %s\n\ttitle: %s",
|
||||
ctx, metadata.artist, metadata.album, metadata.title);
|
||||
free_metadata(&metadata);
|
||||
if (!dmap_parse(&settings, body, len)) {
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -605,7 +667,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
|
||||
NFREE(body);
|
||||
NFREE(buf);
|
||||
kd_free(resp);
|
||||
|
||||
kd_free(headers);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -625,11 +687,9 @@ bool search_remote_cb(mDNSservice_t *slist, void *cookie, bool *stop) {
|
||||
inet_ntoa(ctx->active_remote.host), ctx->active_remote.port);
|
||||
*stop = true;
|
||||
break;
|
||||
LOG_INFO("[%p]: found ActiveRemote for %s at %s:%u", ctx, ctx->active_remote.DACPid,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// let caller clear list
|
||||
return false;
|
||||
}
|
||||
@@ -637,7 +697,57 @@ static void* search_remote(void *args) {
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void* search_remote(void *args) {
|
||||
|
||||
raop_ctx_t *ctx = (raop_ctx_t*) args;
|
||||
|
||||
query_mDNS(ctx->active_remote.handle, "_dacp._tcp.local", 0, 0, &search_remote_cb, (void*) ctx);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void* search_remote(void *args) {
|
||||
raop_ctx_t *ctx = (raop_ctx_t*) args;
|
||||
bool found = false;
|
||||
|
||||
LOG_INFO("starting remote search");
|
||||
|
||||
while (ctx->active_remote.running && !found) {
|
||||
mdns_result_t *results = NULL;
|
||||
mdns_result_t *r;
|
||||
mdns_ip_addr_t *a;
|
||||
|
||||
if (mdns_query_ptr("_dacp", "_tcp", 3000, 32, &results)) {
|
||||
LOG_ERROR("mDNS active remote query Failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (r = results; r && !strcasestr(r->instance_name, ctx->active_remote.DACPid); r = r->next);
|
||||
if (r) {
|
||||
for (a = r->addr; a && a->addr.type != IPADDR_TYPE_V4; a = a->next);
|
||||
if (a) {
|
||||
found = true;
|
||||
ctx->active_remote.host.s_addr = a->addr.u_addr.ip4.addr;
|
||||
ctx->active_remote.port = r->port;
|
||||
LOG_INFO("found remote %s %s:%hu", r->instance_name, inet_ntoa(ctx->active_remote.host), ctx->active_remote.port);
|
||||
}
|
||||
}
|
||||
|
||||
mdns_query_results_free(results);
|
||||
}
|
||||
|
||||
/*
|
||||
for some reason which is beyond me, if that tasks gives the semaphore
|
||||
before the RTSP tasks waits for it, then freeRTOS crashes in queue
|
||||
management caused by LWIP stack once the RTSP socket is closed. I have
|
||||
no clue why, but so we'll suspend the tasks as soon as we're done with
|
||||
search and wait for the resume then give the semaphore
|
||||
*/
|
||||
// PS: I know this is not fully race-condition free
|
||||
if (ctx->active_remote.running) vTaskSuspend(NULL);
|
||||
xTaskNotifyGive(ctx->active_remote.joiner);
|
||||
|
||||
// now our context will be deleted
|
||||
vTaskSuspend(NULL);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "platform.h"
|
||||
#include "raop_sink.h"
|
||||
|
||||
struct raop_ctx_s* raop_create(struct in_addr host, char *name, unsigned char mac[6], int latency,
|
||||
struct raop_ctx_s* raop_create(struct in_addr host, char *name, unsigned char mac[6], int latency,
|
||||
raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb);
|
||||
void raop_delete(struct raop_ctx_s *ctx);
|
||||
void raop_cmd(struct raop_ctx_s *ctx, raop_event_t event, void *param);
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "esp_pthread.h"
|
||||
#include "esp_system.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "nvs_utilities.h"
|
||||
#include "config.h"
|
||||
#include "raop.h"
|
||||
#include "audio_controls.h"
|
||||
|
||||
#include "log_util.h"
|
||||
|
||||
@@ -22,14 +23,68 @@
|
||||
#define CONFIG_AIRPLAY_NAME "ESP32-AirPlay"
|
||||
#endif
|
||||
|
||||
static const char * TAG = "platform";
|
||||
|
||||
log_level raop_loglevel = lINFO;
|
||||
log_level util_loglevel;
|
||||
|
||||
static log_level *loglevel = &raop_loglevel;
|
||||
static struct raop_ctx_s *raop;
|
||||
|
||||
static void raop_volume_up(void) {
|
||||
raop_cmd(raop, RAOP_VOLUME_UP, NULL);
|
||||
LOG_INFO("AirPlay volume up");
|
||||
}
|
||||
|
||||
static void raop_volume_down(void) {
|
||||
raop_cmd(raop, RAOP_VOLUME_DOWN, NULL);
|
||||
LOG_INFO("AirPlay volume down");
|
||||
}
|
||||
|
||||
static void raop_toggle(void) {
|
||||
raop_cmd(raop, RAOP_TOGGLE, NULL);
|
||||
LOG_INFO("AirPlay play/pause");
|
||||
}
|
||||
|
||||
static void raop_pause(void) {
|
||||
raop_cmd(raop, RAOP_PAUSE, NULL);
|
||||
LOG_INFO("AirPlay pause");
|
||||
}
|
||||
|
||||
static void raop_play(void) {
|
||||
raop_cmd(raop, RAOP_PLAY, NULL);
|
||||
LOG_INFO("AirPlay play");
|
||||
}
|
||||
|
||||
static void raop_stop(void) {
|
||||
raop_cmd(raop, RAOP_STOP, NULL);
|
||||
LOG_INFO("AirPlay stop");
|
||||
}
|
||||
|
||||
static void raop_prev(void) {
|
||||
raop_cmd(raop, RAOP_PREV, NULL);
|
||||
LOG_INFO("AirPlay previous");
|
||||
}
|
||||
|
||||
static void raop_next(void) {
|
||||
raop_cmd(raop, RAOP_NEXT, NULL);
|
||||
LOG_INFO("AirPlay next");
|
||||
}
|
||||
|
||||
const static actrls_t controls = {
|
||||
raop_volume_up, raop_volume_down, // volume up, volume down
|
||||
raop_toggle, raop_play, // toggle, play
|
||||
raop_pause, raop_stop, // pause, stop
|
||||
NULL, NULL, // rew, fwd
|
||||
raop_prev, raop_next, // prev, next
|
||||
};
|
||||
|
||||
/****************************************************************************************
|
||||
* Airplay taking/giving audio system's control
|
||||
*/
|
||||
void raop_master(bool on) {
|
||||
if (on) actrls_set(controls, NULL);
|
||||
else actrls_unset();
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Airplay sink de-initialization
|
||||
*/
|
||||
@@ -56,14 +111,14 @@ void raop_sink_init(raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) {
|
||||
ESP_ERROR_CHECK( mdns_init() );
|
||||
ESP_ERROR_CHECK( mdns_hostname_set(hostname) );
|
||||
|
||||
char * sink_name_buffer= (char *)config_alloc_get(NVS_TYPE_STR, "airplay_name");
|
||||
char * sink_name_buffer= (char *)config_alloc_get(NVS_TYPE_STR,"airplay_name");
|
||||
if(sink_name_buffer != NULL){
|
||||
memset(sink_name, 0x00, sizeof(sink_name));
|
||||
strncpy(sink_name,sink_name_buffer,sizeof(sink_name)-1 );
|
||||
free(sink_name_buffer);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "mdns hostname set to: [%s] with servicename %s", hostname, sink_name);
|
||||
LOG_INFO( "mdns hostname set to: [%s] with servicename %s", hostname, sink_name);
|
||||
|
||||
// create RAOP instance, latency is set by controller
|
||||
uint8_t mac[6];
|
||||
@@ -72,8 +127,10 @@ void raop_sink_init(raop_cmd_cb_t cmd_cb, raop_data_cb_t data_cb) {
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Airplay local command (stop, start, volume ...)
|
||||
* Airplay forced disconnection
|
||||
*/
|
||||
void raop_sink_cmd(raop_event_t event, void *param) {
|
||||
raop_cmd(raop, event, param);
|
||||
void raop_disconnect(void) {
|
||||
LOG_INFO("forced disconnection");
|
||||
raop_cmd(raop, RAOP_STOP, NULL);
|
||||
actrls_unset();
|
||||
}
|
||||
|
||||
@@ -13,27 +13,31 @@
|
||||
|
||||
#define RAOP_SAMPLE_RATE 44100
|
||||
|
||||
typedef enum { RAOP_SETUP, RAOP_STREAM, RAOP_PLAY, RAOP_FLUSH, RAOP_PAUSE, RAOP_STOP, RAOP_VOLUME, RAOP_TIMING } raop_event_t ;
|
||||
typedef enum { RAOP_SETUP, RAOP_STREAM, RAOP_PLAY, RAOP_FLUSH, 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 void (*raop_cmd_cb_t)(raop_event_t event, void *param);
|
||||
typedef bool (*raop_cmd_cb_t)(raop_event_t event, void *param);
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief deinit sink mode (need to be provided)
|
||||
*/
|
||||
|
||||
void raop_sink_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief init sink mode (need to be provided)
|
||||
* @brief do what's necessary when becoming in charge
|
||||
*/
|
||||
void raop_master(bool on);
|
||||
|
||||
void raop_sink_cmd(raop_event_t event, void *param);
|
||||
/**
|
||||
* @brief force disconnection
|
||||
*/
|
||||
void raop_disconnect(void);
|
||||
|
||||
#endif /* RAOP_SINK_H*/
|
||||
@@ -139,7 +139,7 @@ typedef struct rtp_s {
|
||||
#ifdef WIN32
|
||||
pthread_t thread;
|
||||
#else
|
||||
TaskHandle_t thread, joiner;
|
||||
TaskHandle_t thread, joiner;
|
||||
StaticTask_t *xTaskBuffer;
|
||||
StackType_t xStack[RTP_STACK_SIZE] __attribute__ ((aligned (4)));
|
||||
#endif
|
||||
@@ -275,11 +275,11 @@ rtp_resp_t rtp_init(struct in_addr host, int latency, char *aeskey, char *aesiv,
|
||||
#ifdef WIN32
|
||||
pthread_create(&ctx->thread, NULL, rtp_thread_func, (void *) ctx);
|
||||
#else
|
||||
// xTaskCreate((TaskFunction_t) rtp_thread_func, "RTP_thread", RTP_TASK_SIZE, ctx, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1 , &ctx->thread);
|
||||
// xTaskCreate((TaskFunction_t) rtp_thread_func, "RTP_thread", RTP_TASK_SIZE, ctx, CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1 , &ctx->thread);
|
||||
ctx->xTaskBuffer = (StaticTask_t*) heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
ctx->thread = xTaskCreateStatic( (TaskFunction_t) rtp_thread_func, "RTP_thread", RTP_STACK_SIZE, ctx,
|
||||
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT + 1, ctx->xStack, ctx->xTaskBuffer );
|
||||
#endif
|
||||
} else {
|
||||
LOG_ERROR("[%p]: cannot start RTP", ctx);
|
||||
rtp_end(ctx);
|
||||
@@ -304,9 +304,8 @@ void rtp_end(rtp_t *ctx)
|
||||
#endif
|
||||
ctx->running = false;
|
||||
#ifdef WIN32
|
||||
pthread_join(ctx->thread, NULL);
|
||||
pthread_join(ctx->thread, NULL);
|
||||
#else
|
||||
xTaskNotifyWait(0, 0, NULL, portMAX_DELAY);
|
||||
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||||
vTaskDelete(ctx->thread);
|
||||
heap_caps_free(ctx->xTaskBuffer);
|
||||
@@ -715,7 +714,7 @@ static void *rtp_thread_func(void *arg) {
|
||||
}
|
||||
|
||||
free(packet);
|
||||
LOG_INFO("[%p]: terminating", ctx);
|
||||
LOG_INFO("[%p]: terminating", ctx);
|
||||
|
||||
#ifndef WIN32
|
||||
xTaskNotifyGive(ctx->joiner);
|
||||
|
||||
Reference in New Issue
Block a user