diff --git a/src/outputs.h b/src/outputs.h index eeda8357..578bad60 100644 --- a/src/outputs.h +++ b/src/outputs.h @@ -134,6 +134,7 @@ struct output_device // Quality of audio output struct media_quality quality; + int format; // Address char *v4_address; diff --git a/src/player.c b/src/player.c index f485b8c3..0a08d48f 100644 --- a/src/player.c +++ b/src/player.c @@ -151,6 +151,9 @@ struct speaker_attr_param bool prevent_playback; bool busy; + struct media_quality quality; + int format; + const char *pin; }; @@ -2883,6 +2886,48 @@ speaker_start_all(void *arg, int *retval) return COMMAND_END; } +// This is borderline misuse of the outputs_device interface, but the purpose is +// to register streaming session info with outputs/streaming.c via the player +// thread. It must be the player thread because session setup requires that +// outputs_quality_subscribe() is called, and by design it isn't thread safe. +static enum command_state +streaming_register(void *arg, int *retval) +{ + struct speaker_attr_param *param = arg; + struct output_device device = + { + .type = OUTPUT_TYPE_STREAMING, + .type_name = "streaming", + .name = "streaming", + .quality = param->quality, + .format = param->format, + }; + + *retval = outputs_device_start(&device, NULL, false); + if (*retval < 0) + return COMMAND_END; + + *retval = device.id; // Actually the fd that the called needs + return COMMAND_END; +} + +static enum command_state +streaming_deregister(void *arg, int *retval) +{ + struct speaker_attr_param *param = arg; + struct output_device device = + { + .type = OUTPUT_TYPE_STREAMING, + .type_name = "streaming", + .name = "streaming", + .id = param->spk_id, + .session = "dummy", // to pass check in outputs_device_stop() + }; + + *retval = outputs_device_stop(&device, NULL); + return COMMAND_END; +} + static enum command_state volume_set(void *arg, int *retval) { @@ -3138,7 +3183,7 @@ player_get_status(struct player_status *status) } -/* --------------------------- Thread: httpd (DACP) ------------------------- */ +/* ------------------------------ Thread: httpd ----------------------------- */ /* * Stores the now playing media item dbmfi-id in the given id pointer. @@ -3424,6 +3469,33 @@ player_speaker_authorize(uint64_t id, const char *pin) return ret; } +int +player_streaming_register(int format, struct media_quality quality) +{ + struct speaker_attr_param param; + int ret; + + param.format = format; + param.quality = quality; + + ret = commands_exec_sync(cmdbase, streaming_register, NULL, ¶m); + + return ret; +} + +int +player_streaming_deregister(int id) +{ + struct speaker_attr_param param; + int ret; + + param.spk_id = id; + + ret = commands_exec_sync(cmdbase, streaming_deregister, NULL, ¶m); + + return ret; +} + int player_volume_set(int vol) { diff --git a/src/player.h b/src/player.h index 974794f4..3246023c 100644 --- a/src/player.h +++ b/src/player.h @@ -6,6 +6,7 @@ #include #include "db.h" +#include "misc.h" // for struct media_quality // Maximum number of previously played songs that are remembered #define MAX_HISTORY_COUNT 20 @@ -117,6 +118,12 @@ player_speaker_resurrect(void *arg); int player_speaker_authorize(uint64_t id, const char *pin); +int +player_streaming_register(int format, struct media_quality quality); + +int +player_streaming_deregister(int id); + int player_playback_start(void);