From f2659d995b40f3c71769c6759019747cab86e45f Mon Sep 17 00:00:00 2001 From: chme Date: Wed, 7 Feb 2018 21:04:47 +0100 Subject: [PATCH 1/6] [player] Refactor speaker_set/speaker_deactivate --- src/player.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/player.c b/src/player.c index d9c3fb0e..2979a183 100644 --- a/src/player.c +++ b/src/player.c @@ -2473,10 +2473,15 @@ speaker_deactivate(struct output_device *device) { DPRINTF(E_DBG, L_PLAYER, "Deactivating %s device '%s'\n", device->type_name, device->name); + if (device->selected) + speaker_deselect_output(device); + + if (!device->session) + return 0; + outputs_status_cb(device->session, device_shutdown_cb); outputs_device_stop(device->session); - - return 0; + return 1; } static enum command_state @@ -2546,22 +2551,9 @@ speaker_set(void *arg, int *retval) { DPRINTF(E_DBG, L_PLAYER, "The %s device '%s' is NOT selected\n", device->type_name, device->name); - if (device->selected) - speaker_deselect_output(device); - - if (device->session) - { - ret = speaker_deactivate(device); - if (ret < 0) - { - DPRINTF(E_LOG, L_PLAYER, "Could not deactivate %s device '%s'\n", device->type_name, device->name); - - if (cmdarg->speaker_set_param.intval != -2) - cmdarg->speaker_set_param.intval = -1; - } - else - (*retval)++; - } + ret = speaker_deactivate(device); + if (ret > 0) + (*retval)++; } } From d36e6ac5abc6b0e12696532397e5e8c7a7affcb7 Mon Sep 17 00:00:00 2001 From: chme Date: Wed, 7 Feb 2018 21:17:54 +0100 Subject: [PATCH 2/6] [player] Refactor speaker_set/speaker_activate --- src/player.c | 59 ++++++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/src/player.c b/src/player.c index 2979a183..b908760a 100644 --- a/src/player.c +++ b/src/player.c @@ -2436,12 +2436,21 @@ speaker_activate(struct output_device *device) { int ret; - if (!device) + if (device->has_password && !device->password) { - DPRINTF(E_LOG, L_PLAYER, "Bug! speaker_activate called with device\n"); - return -1; + DPRINTF(E_INFO, L_PLAYER, "The %s device '%s' is password-protected, but we don't have it\n", device->type_name, device->name); + + return -2; } + DPRINTF(E_DBG, L_PLAYER, "The %s device '%s' is selected\n", device->type_name, device->name); + + if (!device->selected) + speaker_select_output(device); + + if (device->session) + return 0; + if (player_state == PLAY_PLAYING) { DPRINTF(E_DBG, L_PLAYER, "Activating %s device '%s'\n", device->type_name, device->name); @@ -2450,7 +2459,7 @@ speaker_activate(struct output_device *device) if (ret < 0) { DPRINTF(E_LOG, L_PLAYER, "Could not start %s device '%s'\n", device->type_name, device->name); - return -1; + goto error; } } else @@ -2461,11 +2470,16 @@ speaker_activate(struct output_device *device) if (ret < 0) { DPRINTF(E_LOG, L_PLAYER, "Could not probe %s device '%s'\n", device->type_name, device->name); - return -1; + goto error; } } return 0; + + error: + DPRINTF(E_LOG, L_PLAYER, "Could not activate %s device '%s'\n", device->type_name, device->name); + speaker_deselect_output(device); + return -1; } static int @@ -2518,40 +2532,17 @@ speaker_set(void *arg, int *retval) if (i <= nspk) { - if (device->has_password && !device->password) - { - DPRINTF(E_INFO, L_PLAYER, "The %s device '%s' is password-protected, but we don't have it\n", device->type_name, device->name); + ret = speaker_activate(device); - cmdarg->speaker_set_param.intval = -2; - continue; - } - - DPRINTF(E_DBG, L_PLAYER, "The %s device '%s' is selected\n", device->type_name, device->name); - - if (!device->selected) - speaker_select_output(device); - - if (!device->session) - { - ret = speaker_activate(device); - if (ret < 0) - { - DPRINTF(E_LOG, L_PLAYER, "Could not activate %s device '%s'\n", device->type_name, device->name); - - speaker_deselect_output(device); - - if (cmdarg->speaker_set_param.intval != -2) - cmdarg->speaker_set_param.intval = -1; - } - else - (*retval)++; - } + if (ret > 0) + (*retval)++; + else if (ret < 0 && cmdarg->speaker_set_param.intval != -2) + cmdarg->speaker_set_param.intval = ret; } else { - DPRINTF(E_DBG, L_PLAYER, "The %s device '%s' is NOT selected\n", device->type_name, device->name); - ret = speaker_deactivate(device); + if (ret > 0) (*retval)++; } From 94fd370df28d4e4bf9a764984660929225fb0248 Mon Sep 17 00:00:00 2001 From: chme Date: Wed, 7 Feb 2018 21:30:38 +0100 Subject: [PATCH 3/6] [player] Simplify parameter passing to player commands --- src/player.c | 115 +++++++++++++++++++-------------------------------- 1 file changed, 42 insertions(+), 73 deletions(-) diff --git a/src/player.c b/src/player.c index b908760a..8f0f60b2 100644 --- a/src/player.c +++ b/src/player.c @@ -155,16 +155,7 @@ struct speaker_auth_param union player_arg { - struct volume_param vol_param; - void *noarg; - struct spk_enum *spk_enum; struct output_device *device; - struct player_status *status; - struct player_source *ps; - struct metadata_param metadata_param; - uint32_t *id_ptr; - struct speaker_set_param speaker_set_param; - enum repeat_mode mode; struct speaker_auth_param auth; uint32_t id; int intval; @@ -1375,13 +1366,12 @@ device_auth_kickoff(void *arg, int *retval) static enum command_state device_metadata_send(void *arg, int *retval) { - union player_arg *cmdarg; + struct metadata_param *metadata_param = arg; struct input_metadata *imd; struct output_metadata *omd; - cmdarg = arg; - imd = cmdarg->metadata_param.input; - omd = cmdarg->metadata_param.output; + imd = metadata_param->input; + omd = metadata_param->output; outputs_metadata_send(omd, imd->rtptime, imd->offset, imd->startup); @@ -1777,15 +1767,12 @@ playback_suspend(void) static enum command_state get_status(void *arg, int *retval) { - union player_arg *cmdarg = arg; + struct player_status *status = arg; struct timespec ts; struct player_source *ps; - struct player_status *status; uint64_t pos; int ret; - status = cmdarg->status; - memset(status, 0, sizeof(struct player_status)); status->shuffle = shuffle; @@ -1865,12 +1852,9 @@ get_status(void *arg, int *retval) static enum command_state now_playing(void *arg, int *retval) { - union player_arg *cmdarg = arg; - uint32_t *id; + uint32_t *id = arg; struct player_source *ps_playing; - id = cmdarg->id_ptr; - ps_playing = source_now_playing(); if (ps_playing) @@ -2398,13 +2382,10 @@ player_speaker_status_trigger(void) static enum command_state speaker_enumerate(void *arg, int *retval) { - union player_arg *cmdarg = arg; + struct spk_enum *spk_enum = arg; struct output_device *device; - struct spk_enum *spk_enum; struct spk_flags flags; - spk_enum = cmdarg->spk_enum; - #ifdef DEBUG_RELVOL DPRINTF(E_DBG, L_PLAYER, "*** master: %d\n", master_volume); #endif @@ -2501,7 +2482,7 @@ speaker_deactivate(struct output_device *device) static enum command_state speaker_set(void *arg, int *retval) { - union player_arg *cmdarg = arg; + struct speaker_set_param *speaker_set_param = arg; struct output_device *device; uint64_t *ids; int nspk; @@ -2509,7 +2490,7 @@ speaker_set(void *arg, int *retval) int ret; *retval = 0; - ids = cmdarg->speaker_set_param.device_ids; + ids = speaker_set_param->device_ids; if (ids) nspk = ids[0]; @@ -2536,8 +2517,8 @@ speaker_set(void *arg, int *retval) if (ret > 0) (*retval)++; - else if (ret < 0 && cmdarg->speaker_set_param.intval != -2) - cmdarg->speaker_set_param.intval = ret; + else if (ret < 0 && speaker_set_param->intval != -2) + speaker_set_param->intval = ret; } else { @@ -2551,7 +2532,7 @@ speaker_set(void *arg, int *retval) if (*retval > 0) return COMMAND_PENDING; // async - *retval = cmdarg->speaker_set_param.intval; + *retval = speaker_set_param->intval; return COMMAND_END; } @@ -2596,14 +2577,14 @@ volume_set(void *arg, int *retval) static enum command_state volume_setrel_speaker(void *arg, int *retval) { - union player_arg *cmdarg = arg; + struct volume_param *vol_param = arg; struct output_device *device; uint64_t id; int relvol; *retval = 0; - id = cmdarg->vol_param.spk_id; - relvol = cmdarg->vol_param.volume; + id = vol_param->spk_id; + relvol = vol_param->volume; for (device = dev_list; device; device = device->next) { @@ -2640,14 +2621,14 @@ volume_setrel_speaker(void *arg, int *retval) static enum command_state volume_setabs_speaker(void *arg, int *retval) { - union player_arg *cmdarg = arg; + struct volume_param *vol_param = arg; struct output_device *device; uint64_t id; int volume; *retval = 0; - id = cmdarg->vol_param.spk_id; - volume = cmdarg->vol_param.volume; + id = vol_param->spk_id; + volume = vol_param->volume; master_volume = volume; @@ -2690,24 +2671,24 @@ volume_setabs_speaker(void *arg, int *retval) static enum command_state repeat_set(void *arg, int *retval) { - union player_arg *cmdarg = arg; + enum repeat_mode *mode = arg; - if (cmdarg->mode == repeat) + if (*mode == repeat) { *retval = 0; return COMMAND_END; } - switch (cmdarg->mode) + switch (*mode) { case REPEAT_OFF: case REPEAT_SONG: case REPEAT_ALL: - repeat = cmdarg->mode; + repeat = *mode; break; default: - DPRINTF(E_LOG, L_PLAYER, "Invalid repeat mode: %d\n", cmdarg->mode); + DPRINTF(E_LOG, L_PLAYER, "Invalid repeat mode: %d\n", *mode); *retval = -1; return COMMAND_END; } @@ -2837,12 +2818,9 @@ player_get_current_pos(uint64_t *pos, struct timespec *ts, int commit) int player_get_status(struct player_status *status) { - union player_arg cmdarg; int ret; - cmdarg.status = status; - - ret = commands_exec_sync(cmdbase, get_status, NULL, &cmdarg); + ret = commands_exec_sync(cmdbase, get_status, NULL, status); return ret; } @@ -2858,12 +2836,9 @@ player_get_status(struct player_status *status) int player_now_playing(uint32_t *id) { - union player_arg cmdarg; int ret; - cmdarg.id_ptr = id; - - ret = commands_exec_sync(cmdbase, now_playing, NULL, &cmdarg); + ret = commands_exec_sync(cmdbase, now_playing, NULL, id); return ret; } @@ -2968,27 +2943,24 @@ player_playback_prev(void) void player_speaker_enumerate(spk_enum_cb cb, void *arg) { - union player_arg cmdarg; struct spk_enum spk_enum; spk_enum.cb = cb; spk_enum.arg = arg; - cmdarg.spk_enum = &spk_enum; - - commands_exec_sync(cmdbase, speaker_enumerate, NULL, &cmdarg); + commands_exec_sync(cmdbase, speaker_enumerate, NULL, &spk_enum); } int player_speaker_set(uint64_t *ids) { - union player_arg cmdarg; + struct speaker_set_param speaker_set_param; int ret; - cmdarg.speaker_set_param.device_ids = ids; - cmdarg.speaker_set_param.intval = 0; + speaker_set_param.device_ids = ids; + speaker_set_param.intval = 0; - ret = commands_exec_sync(cmdbase, speaker_set, NULL, &cmdarg); + ret = commands_exec_sync(cmdbase, speaker_set, NULL, &speaker_set_param); listener_notify(LISTENER_SPEAKER); @@ -3016,7 +2988,7 @@ player_volume_set(int vol) int player_volume_setrel_speaker(uint64_t id, int relvol) { - union player_arg cmdarg; + struct volume_param vol_param; int ret; if (relvol < 0 || relvol > 100) @@ -3025,17 +2997,17 @@ player_volume_setrel_speaker(uint64_t id, int relvol) return -1; } - cmdarg.vol_param.spk_id = id; - cmdarg.vol_param.volume = relvol; + vol_param.spk_id = id; + vol_param.volume = relvol; - ret = commands_exec_sync(cmdbase, volume_setrel_speaker, NULL, &cmdarg); + ret = commands_exec_sync(cmdbase, volume_setrel_speaker, NULL, &vol_param); return ret; } int player_volume_setabs_speaker(uint64_t id, int vol) { - union player_arg cmdarg; + struct volume_param vol_param; int ret; if (vol < 0 || vol > 100) @@ -3044,22 +3016,19 @@ player_volume_setabs_speaker(uint64_t id, int vol) return -1; } - cmdarg.vol_param.spk_id = id; - cmdarg.vol_param.volume = vol; + vol_param.spk_id = id; + vol_param.volume = vol; - ret = commands_exec_sync(cmdbase, volume_setabs_speaker, NULL, &cmdarg); + ret = commands_exec_sync(cmdbase, volume_setabs_speaker, NULL, &vol_param); return ret; } int player_repeat_set(enum repeat_mode mode) { - union player_arg cmdarg; int ret; - cmdarg.mode = mode; - - ret = commands_exec_sync(cmdbase, repeat_set, NULL, &cmdarg); + ret = commands_exec_sync(cmdbase, repeat_set, NULL, &mode); return ret; } @@ -3183,12 +3152,12 @@ player_raop_verification_kickoff(char **arglist) void player_metadata_send(void *imd, void *omd) { - union player_arg cmdarg; + struct metadata_param metadata_param; - cmdarg.metadata_param.input = imd; - cmdarg.metadata_param.output = omd; + metadata_param.input = imd; + metadata_param.output = omd; - commands_exec_sync(cmdbase, device_metadata_send, NULL, &cmdarg); + commands_exec_sync(cmdbase, device_metadata_send, NULL, &metadata_param); } From 93879c6f90dbdc07cb3e8ab10d87cce3e03adc9f Mon Sep 17 00:00:00 2001 From: chme Date: Wed, 7 Feb 2018 22:18:09 +0100 Subject: [PATCH 4/6] [player] Refactor speaker enumerate callback --- src/httpd_dacp.c | 30 +++++++++++++++--------------- src/httpd_jsonapi.c | 18 +++++++++--------- src/mpd.c | 25 +++++++++++++------------ src/player.c | 26 ++++++++++++-------------- src/player.h | 21 ++++++++++++++------- 5 files changed, 63 insertions(+), 57 deletions(-) diff --git a/src/httpd_dacp.c b/src/httpd_dacp.c index 9cec68b8..8680f32d 100644 --- a/src/httpd_dacp.c +++ b/src/httpd_dacp.c @@ -510,34 +510,34 @@ playqueuecontents_add_queue_item(struct evbuffer *songlist, struct db_queue_item } static void -speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, void *arg) +speaker_enum_cb(struct spk_info *spk, void *arg) { struct evbuffer *evbuf; int len; evbuf = (struct evbuffer *)arg; - len = 8 + strlen(name) + 28; - if (flags.selected) + len = 8 + strlen(spk->name) + 28; + if (spk->selected) len += 9; - if (flags.has_password) + if (spk->has_password) len += 9; - if (flags.has_video) + if (spk->has_video) len += 9; CHECK_ERR(L_DACP, evbuffer_expand(evbuf, 71 + len)); - dmap_add_container(evbuf, "mdcl", len); /* 8 + len */ - if (flags.selected) - dmap_add_char(evbuf, "caia", 1); /* 9 */ - if (flags.has_password) - dmap_add_char(evbuf, "cahp", 1); /* 9 */ - if (flags.has_video) - dmap_add_char(evbuf, "caiv", 1); /* 9 */ - dmap_add_string(evbuf, "minm", name); /* 8 + len */ - dmap_add_long(evbuf, "msma", id); /* 16 */ + dmap_add_container(evbuf, "mdcl", len); /* 8 + len */ + if (spk->selected) + dmap_add_char(evbuf, "caia", 1); /* 9 */ + if (spk->has_password) + dmap_add_char(evbuf, "cahp", 1); /* 9 */ + if (spk->has_video) + dmap_add_char(evbuf, "caiv", 1); /* 9 */ + dmap_add_string(evbuf, "minm", spk->name); /* 8 + len */ + dmap_add_long(evbuf, "msma", spk->id); /* 16 */ - dmap_add_int(evbuf, "cmvo", relvol); /* 12 */ + dmap_add_int(evbuf, "cmvo", spk->relvol); /* 12 */ } static int diff --git a/src/httpd_jsonapi.c b/src/httpd_jsonapi.c index b39ae298..f98830b7 100644 --- a/src/httpd_jsonapi.c +++ b/src/httpd_jsonapi.c @@ -495,7 +495,7 @@ jsonapi_reply_lastfm_logout(struct httpd_request *hreq) } static void -speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, void *arg) +speaker_enum_cb(struct spk_info *spk, void *arg) { json_object *outputs; json_object *output; @@ -504,15 +504,15 @@ speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relv outputs = arg; output = json_object_new_object(); - snprintf(output_id, sizeof(output_id), "%" PRIu64, id); + snprintf(output_id, sizeof(output_id), "%" PRIu64, spk->id); json_object_object_add(output, "id", json_object_new_string(output_id)); - json_object_object_add(output, "name", json_object_new_string(name)); - json_object_object_add(output, "type", json_object_new_string(output_type)); - json_object_object_add(output, "selected", json_object_new_boolean(flags.selected)); - json_object_object_add(output, "has_password", json_object_new_boolean(flags.has_password)); - json_object_object_add(output, "requires_auth", json_object_new_boolean(flags.requires_auth)); - json_object_object_add(output, "needs_auth_key", json_object_new_boolean(flags.needs_auth_key)); - json_object_object_add(output, "volume", json_object_new_int(absvol)); + json_object_object_add(output, "name", json_object_new_string(spk->name)); + json_object_object_add(output, "type", json_object_new_string(spk->output_type)); + json_object_object_add(output, "selected", json_object_new_boolean(spk->selected)); + json_object_object_add(output, "has_password", json_object_new_boolean(spk->has_password)); + json_object_object_add(output, "requires_auth", json_object_new_boolean(spk->requires_auth)); + json_object_object_add(output, "needs_auth_key", json_object_new_boolean(spk->needs_auth_key)); + json_object_object_add(output, "volume", json_object_new_int(spk->absvol)); json_object_array_add(outputs, output); } diff --git a/src/mpd.c b/src/mpd.c index bf46df55..4754a57a 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -3571,10 +3571,11 @@ mpd_command_password(struct evbuffer *evbuf, int argc, char **argv, char **errms /* * Callback function for the 'player_speaker_enumerate' function. - * Adds a new struct output to the given struct outputs in *arg for the given speaker (id, name, etc.). + * Expect a struct output_get_param as argument and allocates a struct output if + * the shortid of output_get_param matches the given speaker/output spk. */ static void -outputs_enum_cb(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, void *arg) +outputs_enum_cb(struct spk_info *spk, void *arg) { struct outputs *outputs; struct output *output; @@ -3583,15 +3584,15 @@ outputs_enum_cb(uint64_t id, const char *name, const char *output_type, int relv output = (struct output*)malloc(sizeof(struct output)); - output->id = id; - output->shortid = (unsigned short) id; - output->name = strdup(name); - output->selected = flags.selected; + output->id = spk->id; + output->shortid = (unsigned short) spk->id; + output->name = strdup(spk->name); + output->selected = spk->selected; output->next = outputs->outputs; outputs->outputs = output; outputs->count++; - if (flags.selected) + if (spk->selected) outputs->active++; DPRINTF(E_DBG, L_MPD, "Output enum: shortid %d, id %" PRIu64 ", name '%s', selected %d\n", @@ -3869,7 +3870,7 @@ mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **e * outputvolume: 50 */ static void -speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, void *arg) +speaker_enum_cb(struct spk_info *spk, void *arg) { struct evbuffer *evbuf; @@ -3880,10 +3881,10 @@ speaker_enum_cb(uint64_t id, const char *name, const char *output_type, int relv "outputname: %s\n" "outputenabled: %d\n" "outputvolume: %d\n", - (unsigned short) id, - name, - flags.selected, - absvol); + (unsigned short) spk->id, + spk->name, + spk->selected, + spk->absvol); } /* diff --git a/src/player.c b/src/player.c index 8f0f60b2..efb1b158 100644 --- a/src/player.c +++ b/src/player.c @@ -2384,27 +2384,25 @@ speaker_enumerate(void *arg, int *retval) { struct spk_enum *spk_enum = arg; struct output_device *device; - struct spk_flags flags; - -#ifdef DEBUG_RELVOL - DPRINTF(E_DBG, L_PLAYER, "*** master: %d\n", master_volume); -#endif + struct spk_info spk; for (device = dev_list; device; device = device->next) { if (device->advertised || device->selected) { - flags.selected = device->selected; - flags.has_password = device->has_password; - flags.has_video = device->has_video; - flags.requires_auth = device->requires_auth; - flags.needs_auth_key = (device->requires_auth && device->auth_key == NULL); + spk.id = device->id; + spk.name = device->name; + spk.output_type = device->type_name; + spk.relvol = device->relvol; + spk.absvol = device->volume; - spk_enum->cb(device->id, device->name, device->type_name, device->relvol, device->volume, flags, spk_enum->arg); + spk.selected = device->selected; + spk.has_password = device->has_password; + spk.has_video = device->has_video; + spk.requires_auth = device->requires_auth; + spk.needs_auth_key = (device->requires_auth && device->auth_key == NULL); -#ifdef DEBUG_RELVOL - DPRINTF(E_DBG, L_PLAYER, "*** %s: abs %d rel %d\n", device->name, device->volume, device->relvol); -#endif + spk_enum->cb(&spk, spk_enum->arg); } } diff --git a/src/player.h b/src/player.h index 26fe51d1..7f52d2c6 100644 --- a/src/player.h +++ b/src/player.h @@ -2,6 +2,7 @@ #ifndef __PLAYER_H__ #define __PLAYER_H__ +#include #include #include "db.h" @@ -28,13 +29,19 @@ enum repeat_mode { REPEAT_ALL = 2, }; -struct spk_flags { - unsigned selected:1; - unsigned has_password:1; - unsigned requires_auth:1; - unsigned needs_auth_key:1; +struct spk_info { + uint64_t id; + const char *name; + const char *output_type; + int relvol; + int absvol; - unsigned has_video:1; + bool selected; + bool has_password; + bool requires_auth; + bool needs_auth_key; + + bool has_video; }; struct player_status { @@ -57,7 +64,7 @@ struct player_status { uint32_t len_ms; }; -typedef void (*spk_enum_cb)(uint64_t id, const char *name, const char *output_type, int relvol, int absvol, struct spk_flags flags, void *arg); +typedef void (*spk_enum_cb)(struct spk_info *spk, void *arg); struct player_history { From decf9f1329ffbe61bf21849452909f96a2521c08 Mon Sep 17 00:00:00 2001 From: chme Date: Wed, 7 Feb 2018 23:05:23 +0100 Subject: [PATCH 5/6] [player] Add commands to enable/disable output --- src/player.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/player.h | 6 ++++ 2 files changed, 84 insertions(+) diff --git a/src/player.c b/src/player.c index efb1b158..7acfab21 100644 --- a/src/player.c +++ b/src/player.c @@ -2534,6 +2534,60 @@ speaker_set(void *arg, int *retval) return COMMAND_END; } +static enum command_state +speaker_enable(void *arg, int *retval) +{ + uint64_t *id = arg; + struct output_device *device; + + *retval = 0; + + DPRINTF(E_DBG, L_PLAYER, "Speaker enable: %" PRIu64 "\n", *id); + + *retval = 0; + + for (device = dev_list; device; device = device->next) + { + if (*id == device->id) + { + *retval = speaker_activate(device); + break; + } + } + + if (*retval > 0) + return COMMAND_PENDING; // async + + return COMMAND_END; +} + +static enum command_state +speaker_disable(void *arg, int *retval) +{ + uint64_t *id = arg; + struct output_device *device; + + *retval = 0; + + DPRINTF(E_DBG, L_PLAYER, "Speaker disable: %" PRIu64 "\n", *id); + + *retval = 0; + + for (device = dev_list; device; device = device->next) + { + if (*id == device->id) + { + *retval = speaker_deactivate(device); + break; + } + } + + if (*retval > 0) + return COMMAND_PENDING; // async + + return COMMAND_END; +} + static enum command_state volume_set(void *arg, int *retval) { @@ -2965,6 +3019,30 @@ player_speaker_set(uint64_t *ids) return ret; } +int +player_speaker_enable(uint64_t id) +{ + int ret; + + ret = commands_exec_sync(cmdbase, speaker_enable, NULL, &id); + + listener_notify(LISTENER_SPEAKER); + + return ret; +} + +int +player_speaker_disable(uint64_t id) +{ + int ret; + + ret = commands_exec_sync(cmdbase, speaker_disable, NULL, &id); + + listener_notify(LISTENER_SPEAKER); + + return ret; +} + int player_volume_set(int vol) { diff --git a/src/player.h b/src/player.h index 7f52d2c6..ad58cefa 100644 --- a/src/player.h +++ b/src/player.h @@ -95,6 +95,12 @@ player_speaker_enumerate(spk_enum_cb cb, void *arg); int player_speaker_set(uint64_t *ids); +int +player_speaker_enable(uint64_t id); + +int +player_speaker_disable(uint64_t id); + void player_speaker_status_trigger(void); From 43887d160fcdc58c8185bc7401a5f2c700a1ecf1 Mon Sep 17 00:00:00 2001 From: chme Date: Wed, 7 Feb 2018 23:06:41 +0100 Subject: [PATCH 6/6] [mpd] Refactor commands to enable/disable/toggle/volume for outputs --- src/mpd.c | 323 +++++++++++++----------------------------------------- 1 file changed, 74 insertions(+), 249 deletions(-) diff --git a/src/mpd.c b/src/mpd.c index 4754a57a..4ed69eb1 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -212,31 +212,21 @@ struct output char *name; unsigned selected; - - struct output *next; }; -struct outputs +struct output_get_param { - unsigned int count; - unsigned int active; - struct output *outputs; + unsigned short shortid; + struct output *output; }; static void -free_outputs(struct output *outputs) +free_output(struct output *output) { - struct output *temp; - struct output *next; - - temp = outputs; - next = outputs ? outputs->next : NULL; - while (temp) + if (output) { - free(temp->name); - free(temp); - temp = next; - next = next ? next->next : NULL; + free(output->name); + free(output); } } @@ -3575,28 +3565,23 @@ mpd_command_password(struct evbuffer *evbuf, int argc, char **argv, char **errms * the shortid of output_get_param matches the given speaker/output spk. */ static void -outputs_enum_cb(struct spk_info *spk, void *arg) +output_get_cb(struct spk_info *spk, void *arg) { - struct outputs *outputs; - struct output *output; + struct output_get_param *param = arg; - outputs = (struct outputs *)arg; + if (!param->output + && param->shortid == (unsigned short) spk->id) + { + param->output = calloc(1, sizeof(struct output)); - output = (struct output*)malloc(sizeof(struct output)); + param->output->id = spk->id; + param->output->shortid = (unsigned short) spk->id; + param->output->name = strdup(spk->name); + param->output->selected = spk->selected; - output->id = spk->id; - output->shortid = (unsigned short) spk->id; - output->name = strdup(spk->name); - output->selected = spk->selected; - - output->next = outputs->outputs; - outputs->outputs = output; - outputs->count++; - if (spk->selected) - outputs->active++; - - DPRINTF(E_DBG, L_MPD, "Output enum: shortid %d, id %" PRIu64 ", name '%s', selected %d\n", - output->shortid, output->id, output->name, output->selected); + DPRINTF(E_DBG, L_MPD, "Output found: shortid %d, id %" PRIu64 ", name '%s', selected %d\n", + param->output->shortid, param->output->id, param->output->name, param->output->selected); + } } /* @@ -3606,20 +3591,10 @@ outputs_enum_cb(struct spk_info *spk, void *arg) static int mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx) { - struct outputs outputs; - struct output *output; + struct output_get_param param; uint32_t num; - uint64_t *ids; - int nspk; - int i; int ret; - if (argc < 2) - { - *errmsg = safe_asprintf("Missing argument for command 'disableoutput'"); - return ACK_ERROR_ARG; - } - ret = safe_atou32(argv[1], &num); if (ret < 0) { @@ -3627,57 +3602,21 @@ mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char ** return ACK_ERROR_ARG; } - outputs.count = 0; - outputs.active = 0; - outputs.outputs = NULL; + memset(¶m, 0, sizeof(struct output_get_param)); + param.shortid = num; - player_speaker_enumerate(outputs_enum_cb, &outputs); + player_speaker_enumerate(output_get_cb, ¶m); - nspk = outputs.active; - output = outputs.outputs; - while (output) + if (param.output && param.output->selected) { - if (output->shortid == num && output->selected) + ret = player_speaker_disable(param.output->id); + free_output(param.output); + + if (ret < 0) { - nspk--; - break; + *errmsg = safe_asprintf("Speakers deactivation failed: %d", num); + return ACK_ERROR_UNKNOWN; } - output = output->next; - } - - if (nspk == outputs.active) - { - DPRINTF(E_LOG, L_MPD, "No speaker to deactivate\n"); - free_outputs(outputs.outputs); - return 0; - } - - ids = (uint64_t *)malloc((nspk + 1) * sizeof(uint64_t)); - - ids[0] = nspk; - - i = 1; - output = outputs.outputs; - while (output) - { - if (output->shortid != num && output->selected) - { - ids[i] = output->id; - i++; - } - - output = output->next; - } - - ret = player_speaker_set(ids); - - free(ids); - free_outputs(outputs.outputs); - - if (ret < 0) - { - *errmsg = safe_asprintf("Speakers deactivation failed: %d", num); - return ACK_ERROR_UNKNOWN; } return 0; @@ -3690,20 +3629,10 @@ mpd_command_disableoutput(struct evbuffer *evbuf, int argc, char **argv, char ** static int mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx) { - struct outputs outputs; - struct output *output; + struct output_get_param param; uint32_t num; - uint64_t *ids; - int nspk; - int i; int ret; - if (argc < 2) - { - *errmsg = safe_asprintf("Missing argument for command 'enableoutput'"); - return ACK_ERROR_ARG; - } - ret = safe_atou32(argv[1], &num); if (ret < 0) { @@ -3711,58 +3640,21 @@ mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **e return ACK_ERROR_ARG; } - outputs.count = 0; - outputs.active = 0; - outputs.outputs = NULL; + memset(¶m, 0, sizeof(struct output_get_param)); + param.shortid = num; - player_speaker_enumerate(outputs_enum_cb, &outputs); + player_speaker_enumerate(output_get_cb, ¶m); - nspk = outputs.active; - output = outputs.outputs; - while (output) + if (param.output && !param.output->selected) { - if (output->shortid == num && !output->selected) + ret = player_speaker_enable(param.output->id); + free_output(param.output); + + if (ret < 0) { - nspk++; - break; + *errmsg = safe_asprintf("Speakers deactivation failed: %d", num); + return ACK_ERROR_UNKNOWN; } - output = output->next; - } - - if (nspk == outputs.active) - { - DPRINTF(E_LOG, L_MPD, "No speaker to activate\n"); - free_outputs(outputs.outputs); - return 0; - } - - ids = (uint64_t *)malloc((nspk + 1) * sizeof(uint64_t)); - - ids[0] = nspk; - - i = 1; - output = outputs.outputs; - while (output) - { - if (output->shortid == num || output->selected) - { - ids[i] = output->id; - i++; - } - - output = output->next; - } - - ret = player_speaker_set(ids); - - if (ids) - free(ids); - free_outputs(outputs.outputs); - - if (ret < 0) - { - *errmsg = safe_asprintf("Speakers activation failed: %d", num); - return ACK_ERROR_UNKNOWN; } return 0; @@ -3775,20 +3667,10 @@ mpd_command_enableoutput(struct evbuffer *evbuf, int argc, char **argv, char **e static int mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx) { - struct outputs outputs; - struct output *output; + struct output_get_param param; uint32_t num; - uint64_t *ids; - int nspk; - int i; int ret; - if (argc < 2) - { - *errmsg = safe_asprintf("Missing argument for command 'toggleoutput'"); - return ACK_ERROR_ARG; - } - ret = safe_atou32(argv[1], &num); if (ret < 0) { @@ -3796,64 +3678,25 @@ mpd_command_toggleoutput(struct evbuffer *evbuf, int argc, char **argv, char **e return ACK_ERROR_ARG; } - outputs.count = 0; - outputs.active = 0; - outputs.outputs = NULL; + memset(¶m, 0, sizeof(struct output_get_param)); + param.shortid = num; - player_speaker_enumerate(outputs_enum_cb, &outputs); + player_speaker_enumerate(output_get_cb, ¶m); - nspk = outputs.active; - output = outputs.outputs; - while (output) + if (param.output) { - if (output->shortid == num && !output->selected) + if (param.output->selected) + ret = player_speaker_disable(param.output->id); + else + ret = player_speaker_enable(param.output->id); + + free_output(param.output); + + if (ret < 0) { - nspk++; - break; + *errmsg = safe_asprintf("Toggle speaker failed: %d", num); + return ACK_ERROR_UNKNOWN; } - else if (output->shortid == num && output->selected) - { - nspk--; - break; - } - output = output->next; - } - - if (nspk == outputs.active) - { - DPRINTF(E_LOG, L_MPD, "No speaker to de/activate\n"); - free_outputs(outputs.outputs); - return 0; - } - - ids = (uint64_t *)malloc((nspk + 1) * sizeof(uint64_t)); - - ids[0] = nspk; - - i = 1; - output = outputs.outputs; - while (output) - { - if ((output->shortid == num && !output->selected) - || (output->shortid != num && output->selected)) - { - ids[i] = output->id; - i++; - } - - output = output->next; - } - - ret = player_speaker_set(ids); - - if (ids) - free(ids); - free_outputs(outputs.outputs); - - if (ret < 0) - { - *errmsg = safe_asprintf("Speakers de/activation failed: %d", num); - return ACK_ERROR_UNKNOWN; } return 0; @@ -3888,7 +3731,7 @@ speaker_enum_cb(struct spk_info *spk, void *arg) } /* - * Command handler function for 'outputs' + * Command handler function for 'output' * Returns a lists with the avaiable speakers. */ static int @@ -3902,43 +3745,31 @@ mpd_command_outputs(struct evbuffer *evbuf, int argc, char **argv, char **errmsg static int outputvolume_set(uint32_t shortid, int volume, char **errmsg) { - struct outputs outputs; - struct output *output; + struct output_get_param param; int ret; - outputs.count = 0; - outputs.active = 0; - outputs.outputs = NULL; + memset(¶m, 0, sizeof(struct output_get_param)); + param.shortid = shortid; - player_speaker_enumerate(outputs_enum_cb, &outputs); + player_speaker_enumerate(output_get_cb, ¶m); - output = outputs.outputs; - while (output) + if (param.output) { - if (output->shortid == shortid) + ret = player_volume_setabs_speaker(param.output->id, volume); + free_output(param.output); + + if (ret < 0) { - break; + *errmsg = safe_asprintf("Setting volume to %d for speaker with short-id %d failed", volume, shortid); + return ACK_ERROR_UNKNOWN; } - output = output->next; } - - if (!output) + else { - free_outputs(outputs.outputs); *errmsg = safe_asprintf("No speaker found for short id: %d", shortid); return ACK_ERROR_UNKNOWN; } - ret = player_volume_setabs_speaker(output->id, volume); - - free_outputs(outputs.outputs); - - if (ret < 0) - { - *errmsg = safe_asprintf("Setting volume to %d for speaker with short-id %d failed", volume, shortid); - return ACK_ERROR_UNKNOWN; - } - return 0; } @@ -3949,12 +3780,6 @@ mpd_command_outputvolume(struct evbuffer *evbuf, int argc, char **argv, char **e int volume; int ret; - if (argc < 3) - { - *errmsg = safe_asprintf("Missing argument for command 'outputvolume'"); - return ACK_ERROR_ARG; - } - ret = safe_atou32(argv[1], &shortid); if (ret < 0) { @@ -4335,9 +4160,9 @@ static struct mpd_command mpd_handlers[] = { "ping", mpd_command_ignore, -1 }, // Audio output devices - { "disableoutput", mpd_command_disableoutput, -1 }, - { "enableoutput", mpd_command_enableoutput, -1 }, - { "toggleoutput", mpd_command_toggleoutput, -1 }, + { "disableoutput", mpd_command_disableoutput, 2 }, + { "enableoutput", mpd_command_enableoutput, 2 }, + { "toggleoutput", mpd_command_toggleoutput, 2 }, { "outputs", mpd_command_outputs, -1 }, // Reflection @@ -4356,7 +4181,7 @@ static struct mpd_command mpd_handlers[] = { "sendmessage", mpd_command_sendmessage, -1 }, // Forked-daapd commands (not supported by mpd) - { "outputvolume", mpd_command_outputvolume, -1 }, + { "outputvolume", mpd_command_outputvolume, 3 }, // NULL command to terminate loop { NULL, NULL, -1 }