mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
pulse-server: implement set_sink/source_port
This commit is contained in:
parent
22dcd87de9
commit
686128a5dd
2 changed files with 117 additions and 3 deletions
|
|
@ -489,6 +489,32 @@ static uint32_t collect_port_info(struct pw_manager_object *card, struct card_in
|
|||
return n;
|
||||
}
|
||||
|
||||
static uint32_t find_port_id(struct pw_manager_object *card, uint32_t direction, const char *port_name)
|
||||
{
|
||||
struct pw_manager_param *p;
|
||||
|
||||
spa_list_for_each(p, &card->param_list, link) {
|
||||
uint32_t id, dir;
|
||||
const char *name;
|
||||
|
||||
if (p->id != SPA_PARAM_EnumRoute)
|
||||
continue;
|
||||
|
||||
if (spa_pod_parse_object(p->param,
|
||||
SPA_TYPE_OBJECT_ParamRoute, NULL,
|
||||
SPA_PARAM_ROUTE_index, SPA_POD_Int(&id),
|
||||
SPA_PARAM_ROUTE_direction, SPA_POD_Id(&dir),
|
||||
SPA_PARAM_ROUTE_name, SPA_POD_Id(&name)) < 0)
|
||||
continue;
|
||||
if (dir != direction)
|
||||
continue;
|
||||
if (strcmp(name, port_name) == 0)
|
||||
return id;
|
||||
|
||||
}
|
||||
return SPA_ID_INVALID;
|
||||
}
|
||||
|
||||
static struct spa_dict *collect_props(struct spa_pod *info, struct spa_dict *dict)
|
||||
{
|
||||
struct spa_pod_parser prs;
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ static int reply_error(struct client *client, uint32_t tag, uint32_t error)
|
|||
{
|
||||
struct message *reply;
|
||||
|
||||
pw_log_debug(NAME" %p: ERROR tag:%u error:%u", client, tag, error);
|
||||
pw_log_warn(NAME" %p: ERROR tag:%u error:%u", client, tag, error);
|
||||
|
||||
reply = message_alloc(client, -1, 0);
|
||||
message_put(reply,
|
||||
|
|
@ -2123,6 +2123,25 @@ static int set_card_mute(struct pw_manager_object *o, uint32_t id,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int set_card_port(struct pw_manager_object *o, uint32_t id,
|
||||
uint32_t device_id)
|
||||
{
|
||||
char buf[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
|
||||
|
||||
if (!SPA_FLAG_IS_SET(o->permissions, PW_PERM_W | PW_PERM_X))
|
||||
return ERR_ACCESS;
|
||||
|
||||
pw_device_set_param((struct pw_device*)o->proxy,
|
||||
SPA_PARAM_Route, 0,
|
||||
spa_pod_builder_add_object(&b,
|
||||
SPA_TYPE_OBJECT_ParamRoute, SPA_PARAM_Route,
|
||||
SPA_PARAM_ROUTE_index, SPA_POD_Int(id),
|
||||
SPA_PARAM_ROUTE_device, SPA_POD_Int(device_id)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_set_stream_volume(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
||||
{
|
||||
struct impl *impl = client->impl;
|
||||
|
|
@ -2433,6 +2452,75 @@ error:
|
|||
return reply_error(client, tag, res);
|
||||
}
|
||||
|
||||
static int do_set_port(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
||||
{
|
||||
struct impl *impl = client->impl;
|
||||
struct pw_manager *manager = client->manager;
|
||||
struct pw_node_info *info;
|
||||
uint32_t id, card_id = SPA_ID_INVALID, device_id = SPA_ID_INVALID;
|
||||
uint32_t port_id = SPA_ID_INVALID;
|
||||
const char *name, *str, *port_name;
|
||||
struct pw_manager_object *o, *card = NULL;
|
||||
int res;
|
||||
enum pw_direction direction;
|
||||
|
||||
if ((res = message_get(m,
|
||||
TAG_U32, &id,
|
||||
TAG_STRING, &name,
|
||||
TAG_STRING, &port_name,
|
||||
TAG_INVALID)) < 0)
|
||||
goto error_protocol;
|
||||
|
||||
pw_log_info(NAME" %p: %s index:%u name:%s port:%s", impl,
|
||||
commands[command].name, id, name, port_name);
|
||||
|
||||
if ((id == SPA_ID_INVALID && name == NULL) ||
|
||||
(id != SPA_ID_INVALID && name != NULL))
|
||||
goto error_invalid;
|
||||
|
||||
if (command == COMMAND_SET_SINK_PORT)
|
||||
direction = PW_DIRECTION_OUTPUT;
|
||||
else
|
||||
direction = PW_DIRECTION_INPUT;
|
||||
|
||||
o = find_device(client, id, name, direction == PW_DIRECTION_OUTPUT);
|
||||
if (o == NULL || o->info == NULL)
|
||||
goto error_noentity;
|
||||
info = o->info;
|
||||
if (info == NULL)
|
||||
goto error_noentity;
|
||||
|
||||
if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_ID)) != NULL)
|
||||
card_id = (uint32_t)atoi(str);
|
||||
if ((str = spa_dict_lookup(info->props, "card.profile.device")) != NULL)
|
||||
device_id = (uint32_t)atoi(str);
|
||||
if (card_id != SPA_ID_INVALID) {
|
||||
struct selector sel = { .id = card_id, .type = is_card, };
|
||||
card = select_object(manager, &sel);
|
||||
}
|
||||
if (card == NULL || device_id == SPA_ID_INVALID)
|
||||
goto error_noentity;
|
||||
|
||||
port_id = find_port_id(card, direction, port_name);
|
||||
|
||||
if ((res = set_card_port(card, device_id, port_id)) != 0)
|
||||
goto error;
|
||||
|
||||
return reply_simple_ack(client, tag);
|
||||
|
||||
error_invalid:
|
||||
res = ERR_INVALID;
|
||||
goto error;
|
||||
error_noentity:
|
||||
res = ERR_NOENTITY;
|
||||
goto error;
|
||||
error_protocol:
|
||||
res = ERR_PROTOCOL;
|
||||
goto error;
|
||||
error:
|
||||
return reply_error(client, tag, res);
|
||||
}
|
||||
|
||||
static int do_set_stream_name(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
||||
{
|
||||
struct impl *impl = client->impl;
|
||||
|
|
@ -3722,8 +3810,8 @@ static const struct command commands[COMMAND_MAX] =
|
|||
[COMMAND_RECORD_BUFFER_ATTR_CHANGED] = { "RECORD_BUFFER_ATTR_CHANGED", },
|
||||
|
||||
/* Supported since protocol v16 (0.9.16) */
|
||||
[COMMAND_SET_SINK_PORT] = { "SET_SINK_PORT", do_error_not_implemented, },
|
||||
[COMMAND_SET_SOURCE_PORT] = { "SET_SOURCE_PORT", do_error_not_implemented, },
|
||||
[COMMAND_SET_SINK_PORT] = { "SET_SINK_PORT", do_set_port, },
|
||||
[COMMAND_SET_SOURCE_PORT] = { "SET_SOURCE_PORT", do_set_port, },
|
||||
|
||||
/* Supported since protocol v22 (1.0) */
|
||||
[COMMAND_SET_SOURCE_OUTPUT_VOLUME] = { "SET_SOURCE_OUTPUT_VOLUME", do_set_stream_volume, },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue