mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
pulse-server: pass FILE to message handlers
Use `open_memstream()` to create a FILE stream and pass that to message handlers to store their response. This allows the `open_memstream()` calls and related error handling to be removed from the message handlers.
This commit is contained in:
parent
649b33c73f
commit
4e69507b18
3 changed files with 55 additions and 57 deletions
|
|
@ -9,6 +9,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <spa/utils/defs.h>
|
#include <spa/utils/defs.h>
|
||||||
#include <spa/pod/pod.h>
|
#include <spa/pod/pod.h>
|
||||||
|
|
||||||
|
|
@ -69,7 +71,7 @@ struct pw_manager_object {
|
||||||
struct pw_proxy *proxy;
|
struct pw_proxy *proxy;
|
||||||
char *message_object_path;
|
char *message_object_path;
|
||||||
int (*message_handler)(struct pw_manager *m, struct pw_manager_object *o,
|
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;
|
void *info;
|
||||||
struct spa_param_info *params;
|
struct spa_param_info *params;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
/* SPDX-License-Identifier: MIT */
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
|
||||||
|
|
@ -20,7 +21,7 @@
|
||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "message-handler.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];
|
struct transport_codec_info codecs[64];
|
||||||
uint32_t n_codecs, active;
|
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,
|
pw_device_set_param((struct pw_device *)o->proxy,
|
||||||
SPA_PARAM_Props, 0, param);
|
SPA_PARAM_Props, 0, param);
|
||||||
return 0;
|
|
||||||
} else if (spa_streq(message, "list-codecs")) {
|
} else if (spa_streq(message, "list-codecs")) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
FILE *r;
|
|
||||||
size_t size;
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
r = open_memstream(response, &size);
|
fputc('[', response);
|
||||||
if (r == NULL)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
fputc('[', r);
|
|
||||||
for (i = 0; i < n_codecs; ++i) {
|
for (i = 0; i < n_codecs; ++i) {
|
||||||
const char *desc = codecs[i].description;
|
const char *desc = codecs[i].description;
|
||||||
fprintf(r, "%s{\"name\":\"%d\",\"description\":\"%s\"}",
|
fprintf(response, "%s{\"name\":\"%d\",\"description\":\"%s\"}",
|
||||||
first ? "" : ",",
|
first ? "" : ",",
|
||||||
(int)codecs[i].id, desc ? desc : "Unknown");
|
(int)codecs[i].id, desc ? desc : "Unknown");
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
fputc(']', r);
|
fputc(']', response);
|
||||||
|
|
||||||
return fclose(r) ? -errno : 0;
|
|
||||||
} else if (spa_streq(message, "get-codec")) {
|
} else if (spa_streq(message, "get-codec")) {
|
||||||
if (active == SPA_ID_INVALID)
|
if (active == SPA_ID_INVALID)
|
||||||
*response = strdup("null");
|
fputs("null", response);
|
||||||
else
|
else
|
||||||
*response = spa_aprintf("\"%d\"", (int)codecs[active].id);
|
fprintf(response, "\"%d\"", (int) codecs[active].id);
|
||||||
return *response ? 0 : -ENOMEM;
|
} 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);
|
pw_log_debug(": core %p object message:'%s' params:'%s'", o, message, params);
|
||||||
|
|
||||||
if (spa_streq(message, "list-handlers")) {
|
if (spa_streq(message, "list-handlers")) {
|
||||||
FILE *r;
|
|
||||||
size_t size;
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
r = open_memstream(response, &size);
|
fputc('[', response);
|
||||||
if (r == NULL)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
fputc('[', r);
|
|
||||||
spa_list_for_each(o, &m->object_list, link) {
|
spa_list_for_each(o, &m->object_list, link) {
|
||||||
if (o->message_object_path) {
|
if (o->message_object_path) {
|
||||||
fprintf(r, "%s{\"name\":\"%s\",\"description\":\"%s\"}",
|
fprintf(response, "%s{\"name\":\"%s\",\"description\":\"%s\"}",
|
||||||
first ? "" : ",",
|
first ? "" : ",",
|
||||||
o->message_object_path, o->type);
|
o->message_object_path, o->type);
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fputc(']', r);
|
fputc(']', response);
|
||||||
return fclose(r) ? -errno : 0;
|
} else {
|
||||||
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOSYS;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_object_message_handlers(struct pw_manager_object *o)
|
void register_object_message_handlers(struct pw_manager_object *o)
|
||||||
|
|
|
||||||
|
|
@ -5099,12 +5099,12 @@ static int do_send_object_message(struct client *client, uint32_t command, uint3
|
||||||
{
|
{
|
||||||
struct impl *impl = client->impl;
|
struct impl *impl = client->impl;
|
||||||
struct pw_manager *manager = client->manager;
|
struct pw_manager *manager = client->manager;
|
||||||
const char *object_path = NULL;
|
const char *object_path = NULL, *message = NULL, *params = NULL;
|
||||||
const char *message = NULL;
|
|
||||||
const char *params = NULL;
|
|
||||||
struct message *reply;
|
|
||||||
struct pw_manager_object *o;
|
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,
|
if (message_get(m,
|
||||||
TAG_STRING, &object_path,
|
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)
|
if (object_path == NULL || message == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
len = strlen(object_path);
|
path_len = strlen(object_path);
|
||||||
if (len > 0 && object_path[len - 1] == '/')
|
if (path_len > 0 && object_path[path_len - 1] == '/')
|
||||||
--len;
|
--path_len;
|
||||||
|
spa_autofree char *path = strndup(object_path, path_len);
|
||||||
spa_autofree char *path = strndup(object_path, len);
|
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
spa_autofree char *response = NULL;
|
|
||||||
int res = -ENOENT;
|
|
||||||
|
|
||||||
spa_list_for_each(o, &manager->object_list, link) {
|
spa_list_for_each(o, &manager->object_list, link) {
|
||||||
if (spa_streq(o->message_object_path, path)) {
|
if (spa_streq(o->message_object_path, path))
|
||||||
if (o->message_handler)
|
|
||||||
res = o->message_handler(manager, o, message, params, &response);
|
|
||||||
else
|
|
||||||
res = -ENOSYS;
|
|
||||||
break;
|
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 : "<null>");
|
||||||
|
|
||||||
|
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)
|
free(response_str);
|
||||||
return res;
|
|
||||||
|
|
||||||
pw_log_debug("%p: object message response:'%s'", impl, response ? response : "<null>");
|
return res;
|
||||||
|
|
||||||
reply = reply_new(client, tag);
|
|
||||||
message_put(reply, TAG_STRING, response, TAG_INVALID);
|
|
||||||
|
|
||||||
return client_queue_message(client, reply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_error_access(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
static int do_error_access(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue