diff --git a/src/modules/module-protocol-pulse/manager.h b/src/modules/module-protocol-pulse/manager.h index 52dab04e4..3dd04d8a4 100644 --- a/src/modules/module-protocol-pulse/manager.h +++ b/src/modules/module-protocol-pulse/manager.h @@ -9,6 +9,8 @@ extern "C" { #endif +#include + #include #include @@ -69,7 +71,7 @@ struct pw_manager_object { struct pw_proxy *proxy; char *message_object_path; int (*message_handler)(struct pw_manager *m, struct pw_manager_object *o, - const char *message, const char *params, char **response); + const char *message, const char *params, FILE *response); void *info; struct spa_param_info *params; diff --git a/src/modules/module-protocol-pulse/message-handler.c b/src/modules/module-protocol-pulse/message-handler.c index 79ab584c0..1e5af9761 100644 --- a/src/modules/module-protocol-pulse/message-handler.c +++ b/src/modules/module-protocol-pulse/message-handler.c @@ -3,6 +3,7 @@ /* SPDX-License-Identifier: MIT */ #include +#include #include @@ -20,7 +21,7 @@ #include "manager.h" #include "message-handler.h" -static int bluez_card_object_message_handler(struct pw_manager *m, struct pw_manager_object *o, const char *message, const char *params, char **response) +static int bluez_card_object_message_handler(struct pw_manager *m, struct pw_manager_object *o, const char *message, const char *params, FILE *response) { struct transport_codec_info codecs[64]; uint32_t n_codecs, active; @@ -60,66 +61,53 @@ static int bluez_card_object_message_handler(struct pw_manager *m, struct pw_man pw_device_set_param((struct pw_device *)o->proxy, SPA_PARAM_Props, 0, param); - return 0; } else if (spa_streq(message, "list-codecs")) { uint32_t i; - FILE *r; - size_t size; bool first = true; - r = open_memstream(response, &size); - if (r == NULL) - return -errno; - - fputc('[', r); + fputc('[', response); for (i = 0; i < n_codecs; ++i) { const char *desc = codecs[i].description; - fprintf(r, "%s{\"name\":\"%d\",\"description\":\"%s\"}", + fprintf(response, "%s{\"name\":\"%d\",\"description\":\"%s\"}", first ? "" : ",", (int)codecs[i].id, desc ? desc : "Unknown"); first = false; } - fputc(']', r); - - return fclose(r) ? -errno : 0; + fputc(']', response); } else if (spa_streq(message, "get-codec")) { if (active == SPA_ID_INVALID) - *response = strdup("null"); + fputs("null", response); else - *response = spa_aprintf("\"%d\"", (int)codecs[active].id); - return *response ? 0 : -ENOMEM; + fprintf(response, "\"%d\"", (int) codecs[active].id); + } else { + return -ENOSYS; } - return -ENOSYS; + return 0; } -static int core_object_message_handler(struct pw_manager *m, struct pw_manager_object *o, const char *message, const char *params, char **response) +static int core_object_message_handler(struct pw_manager *m, struct pw_manager_object *o, const char *message, const char *params, FILE *response) { pw_log_debug(": core %p object message:'%s' params:'%s'", o, message, params); if (spa_streq(message, "list-handlers")) { - FILE *r; - size_t size; bool first = true; - r = open_memstream(response, &size); - if (r == NULL) - return -errno; - - fputc('[', r); + fputc('[', response); spa_list_for_each(o, &m->object_list, link) { if (o->message_object_path) { - fprintf(r, "%s{\"name\":\"%s\",\"description\":\"%s\"}", + fprintf(response, "%s{\"name\":\"%s\",\"description\":\"%s\"}", first ? "" : ",", o->message_object_path, o->type); first = false; } } - fputc(']', r); - return fclose(r) ? -errno : 0; + fputc(']', response); + } else { + return -ENOSYS; } - return -ENOSYS; + return 0; } void register_object_message_handlers(struct pw_manager_object *o) diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c index dce96afab..791c4580b 100644 --- a/src/modules/module-protocol-pulse/pulse-server.c +++ b/src/modules/module-protocol-pulse/pulse-server.c @@ -5099,12 +5099,12 @@ static int do_send_object_message(struct client *client, uint32_t command, uint3 { struct impl *impl = client->impl; struct pw_manager *manager = client->manager; - const char *object_path = NULL; - const char *message = NULL; - const char *params = NULL; - struct message *reply; + const char *object_path = NULL, *message = NULL, *params = NULL; struct pw_manager_object *o; - int len = 0; + char *response_str = NULL; + size_t path_len = 0, response_len = 0; + FILE *response; + int res = -ENOENT; if (message_get(m, TAG_STRING, &object_path, @@ -5120,36 +5120,44 @@ static int do_send_object_message(struct client *client, uint32_t command, uint3 if (object_path == NULL || message == NULL) return -EINVAL; - len = strlen(object_path); - if (len > 0 && object_path[len - 1] == '/') - --len; - - spa_autofree char *path = strndup(object_path, len); + path_len = strlen(object_path); + if (path_len > 0 && object_path[path_len - 1] == '/') + --path_len; + spa_autofree char *path = strndup(object_path, path_len); if (path == NULL) return -ENOMEM; - spa_autofree char *response = NULL; - int res = -ENOENT; - spa_list_for_each(o, &manager->object_list, link) { - if (spa_streq(o->message_object_path, path)) { - if (o->message_handler) - res = o->message_handler(manager, o, message, params, &response); - else - res = -ENOSYS; + if (spa_streq(o->message_object_path, path)) break; - } + } + if (spa_list_is_end(o, &manager->object_list, link)) + return -ENOENT; + + if (o->message_handler == NULL) + return -ENOSYS; + + response = open_memstream(&response_str, &response_len); + if (response == NULL) + return -errno; + + res = o->message_handler(manager, o, message, params, response); + + if (fclose(response)) + return -errno; + + pw_log_debug("%p: object message response: (%d) '%s'", impl, res, response_str ? response_str : ""); + + if (res >= 0) { + struct message *reply = reply_new(client, tag); + + message_put(reply, TAG_STRING, response_str, TAG_INVALID); + res = client_queue_message(client, reply); } - if (res < 0) - return res; + free(response_str); - pw_log_debug("%p: object message response:'%s'", impl, response ? response : ""); - - reply = reply_new(client, tag); - message_put(reply, TAG_STRING, response, TAG_INVALID); - - return client_queue_message(client, reply); + return res; } static int do_error_access(struct client *client, uint32_t command, uint32_t tag, struct message *m)