mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
pulse-server: add sink/source sink_input/source_output introspect
This commit is contained in:
parent
02d04c63ea
commit
fdf3485902
3 changed files with 333 additions and 228 deletions
|
|
@ -173,11 +173,39 @@ struct object_info device_info = {
|
||||||
.destroy = device_destroy,
|
.destroy = device_destroy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* node */
|
||||||
|
static void node_event_info(void *object, const struct pw_node_info *info)
|
||||||
|
{
|
||||||
|
struct object *o = object;
|
||||||
|
pw_log_debug("object %p: id:%d change-mask:%"PRIu64, o, o->this.id, info->change_mask);
|
||||||
|
info = o->this.info = pw_node_info_update(o->this.info, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pw_node_events node_events = {
|
||||||
|
PW_VERSION_NODE_EVENTS,
|
||||||
|
.info = node_event_info,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void node_destroy(void *data)
|
||||||
|
{
|
||||||
|
struct object *o = data;
|
||||||
|
if (o->this.info)
|
||||||
|
pw_node_info_free(o->this.info);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct object_info node_info = {
|
||||||
|
.type = PW_TYPE_INTERFACE_Node,
|
||||||
|
.version = PW_VERSION_NODE,
|
||||||
|
.events = &node_events,
|
||||||
|
.destroy = node_destroy,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct object_info *objects[] =
|
static const struct object_info *objects[] =
|
||||||
{
|
{
|
||||||
&module_info,
|
&module_info,
|
||||||
&client_info,
|
&client_info,
|
||||||
&device_info,
|
&device_info,
|
||||||
|
&node_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct object_info *find_info(const char *type, uint32_t version)
|
static const struct object_info *find_info(const char *type, uint32_t version)
|
||||||
|
|
@ -348,7 +376,7 @@ void pw_manager_add_listener(struct pw_manager *manager,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pw_manager_object *pw_manager_find_object(struct pw_manager *manager,
|
struct pw_manager_object *pw_manager_find_object(struct pw_manager *manager,
|
||||||
const char *type, uint32_t id)
|
uint32_t id)
|
||||||
{
|
{
|
||||||
struct manager *this = (struct manager*)manager;
|
struct manager *this = (struct manager*)manager;
|
||||||
struct object *o;
|
struct object *o;
|
||||||
|
|
@ -356,8 +384,6 @@ struct pw_manager_object *pw_manager_find_object(struct pw_manager *manager,
|
||||||
o = find_object(this, id);
|
o = find_object(this, id);
|
||||||
if (o == NULL)
|
if (o == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (type != NULL && strcmp(type, o->this.type) != 0)
|
|
||||||
return NULL;
|
|
||||||
return (struct pw_manager_object*)o;
|
return (struct pw_manager_object*)o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ void pw_manager_add_listener(struct pw_manager *manager,
|
||||||
void pw_manager_destroy(struct pw_manager *manager);
|
void pw_manager_destroy(struct pw_manager *manager);
|
||||||
|
|
||||||
struct pw_manager_object *pw_manager_find_object(struct pw_manager *manager,
|
struct pw_manager_object *pw_manager_find_object(struct pw_manager *manager,
|
||||||
const char *type, uint32_t id);
|
uint32_t id);
|
||||||
int pw_manager_for_each_object(struct pw_manager *manager,
|
int pw_manager_for_each_object(struct pw_manager *manager,
|
||||||
int (*callback) (void *data, struct pw_manager_object *object),
|
int (*callback) (void *data, struct pw_manager_object *object),
|
||||||
void *data);
|
void *data);
|
||||||
|
|
|
||||||
|
|
@ -103,20 +103,6 @@ struct client {
|
||||||
unsigned int disconnecting:1;
|
unsigned int disconnecting:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct device {
|
|
||||||
#define DEVICE_FLAG_MONITOR (1<<0)
|
|
||||||
uint32_t flags;
|
|
||||||
uint32_t index;
|
|
||||||
char *name;
|
|
||||||
enum pw_direction direction;
|
|
||||||
struct pw_properties *props;
|
|
||||||
struct sample_spec ss;
|
|
||||||
struct volume volume;
|
|
||||||
struct channel_map map;
|
|
||||||
bool muted;
|
|
||||||
struct device *monitor;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct buffer_attr {
|
struct buffer_attr {
|
||||||
uint32_t maxlength;
|
uint32_t maxlength;
|
||||||
uint32_t tlength;
|
uint32_t tlength;
|
||||||
|
|
@ -156,8 +142,6 @@ struct stream {
|
||||||
struct volume volume;
|
struct volume volume;
|
||||||
bool muted;
|
bool muted;
|
||||||
|
|
||||||
struct device *dev;
|
|
||||||
|
|
||||||
uint32_t drain_tag;
|
uint32_t drain_tag;
|
||||||
unsigned int corked:1;
|
unsigned int corked:1;
|
||||||
unsigned int volume_set:1;
|
unsigned int volume_set:1;
|
||||||
|
|
@ -190,10 +174,6 @@ struct impl {
|
||||||
|
|
||||||
struct spa_source *source;
|
struct spa_source *source;
|
||||||
struct spa_list servers;
|
struct spa_list servers;
|
||||||
|
|
||||||
struct device default_sink;
|
|
||||||
struct device default_monitor;
|
|
||||||
struct device default_source;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct command {
|
struct command {
|
||||||
|
|
@ -772,8 +752,8 @@ static int reply_create_playback_stream(struct stream *stream)
|
||||||
|
|
||||||
reply = reply_new(client, stream->create_tag);
|
reply = reply_new(client, stream->create_tag);
|
||||||
message_put(reply,
|
message_put(reply,
|
||||||
TAG_U32, stream->channel, /* stream index/channel */
|
TAG_U32, stream->channel, /* stream index/channel */
|
||||||
TAG_U32, stream->channel, /* sink_input/stream index */
|
TAG_U32, pw_stream_get_node_id(stream->stream), /* sink_input/stream index */
|
||||||
TAG_U32, size, /* missing/requested bytes */
|
TAG_U32, size, /* missing/requested bytes */
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
|
|
||||||
|
|
@ -791,8 +771,8 @@ static int reply_create_playback_stream(struct stream *stream)
|
||||||
message_put(reply,
|
message_put(reply,
|
||||||
TAG_SAMPLE_SPEC, &stream->ss,
|
TAG_SAMPLE_SPEC, &stream->ss,
|
||||||
TAG_CHANNEL_MAP, &stream->map,
|
TAG_CHANNEL_MAP, &stream->map,
|
||||||
TAG_U32, stream->dev->index, /* sink index */
|
TAG_U32, 0, /* sink index */
|
||||||
TAG_STRING, stream->dev->name, /* sink name */
|
TAG_STRING, "sink", /* sink name */
|
||||||
TAG_BOOLEAN, false, /* sink suspended state */
|
TAG_BOOLEAN, false, /* sink suspended state */
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
}
|
}
|
||||||
|
|
@ -861,7 +841,7 @@ static int reply_create_record_stream(struct stream *stream)
|
||||||
reply = reply_new(client, stream->create_tag);
|
reply = reply_new(client, stream->create_tag);
|
||||||
message_put(reply,
|
message_put(reply,
|
||||||
TAG_U32, stream->channel, /* stream index/channel */
|
TAG_U32, stream->channel, /* stream index/channel */
|
||||||
TAG_U32, stream->channel, /* source_output/stream index */
|
TAG_U32, pw_stream_get_node_id(stream->stream), /* source_output/stream index */
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
|
|
||||||
if (client->version >= 9) {
|
if (client->version >= 9) {
|
||||||
|
|
@ -874,8 +854,8 @@ static int reply_create_record_stream(struct stream *stream)
|
||||||
message_put(reply,
|
message_put(reply,
|
||||||
TAG_SAMPLE_SPEC, &stream->ss,
|
TAG_SAMPLE_SPEC, &stream->ss,
|
||||||
TAG_CHANNEL_MAP, &stream->map,
|
TAG_CHANNEL_MAP, &stream->map,
|
||||||
TAG_U32, stream->dev->index, /* source index */
|
TAG_U32, SPA_ID_INVALID, /* source index */
|
||||||
TAG_STRING, stream->dev->name, /* source name */
|
TAG_STRING, NULL, /* source name */
|
||||||
TAG_BOOLEAN, false, /* source suspended state */
|
TAG_BOOLEAN, false, /* source suspended state */
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
}
|
}
|
||||||
|
|
@ -1166,6 +1146,12 @@ static const struct pw_stream_events stream_events =
|
||||||
.drained = stream_drained,
|
.drained = stream_drained,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct pw_manager_object *find_node_by_name(struct impl *impl, const char *name)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static struct device *find_device_by_name(struct impl *impl, const char *name)
|
static struct device *find_device_by_name(struct impl *impl, const char *name)
|
||||||
{
|
{
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
@ -1209,6 +1195,7 @@ static struct device *find_device(struct impl *impl, uint32_t idx, const char *n
|
||||||
dev = find_device_by_name(impl, name);
|
dev = find_device_by_name(impl, name);
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void fix_stream_properties(struct stream *stream, struct pw_properties *props)
|
static void fix_stream_properties(struct stream *stream, struct pw_properties *props)
|
||||||
{
|
{
|
||||||
|
|
@ -1275,7 +1262,6 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
const struct spa_pod *params[32];
|
const struct spa_pod *params[32];
|
||||||
uint8_t buffer[4096];
|
uint8_t buffer[4096];
|
||||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||||
struct device *dev = NULL;
|
|
||||||
|
|
||||||
props = pw_properties_new(NULL, NULL);
|
props = pw_properties_new(NULL, NULL);
|
||||||
if (props == NULL) {
|
if (props == NULL) {
|
||||||
|
|
@ -1314,14 +1300,6 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
if (sink_index != SPA_ID_INVALID && sink_name != NULL) {
|
if (sink_index != SPA_ID_INVALID && sink_name != NULL) {
|
||||||
res = -EINVAL;
|
res = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
} else if ((sink_index != SPA_ID_INVALID || sink_name != NULL)) {
|
|
||||||
dev = find_device(impl, sink_index, sink_name);
|
|
||||||
if (dev == NULL) {
|
|
||||||
res = -ENOENT;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dev = &impl->default_sink;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->version >= 12) {
|
if (client->version >= 12) {
|
||||||
|
|
@ -1434,13 +1412,19 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
stream->muted = muted;
|
stream->muted = muted;
|
||||||
stream->muted_set = muted_set;
|
stream->muted_set = muted_set;
|
||||||
stream->attr = attr;
|
stream->attr = attr;
|
||||||
stream->dev = dev;
|
|
||||||
stream->is_underrun = true;
|
stream->is_underrun = true;
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (no_move)
|
if (no_move)
|
||||||
flags |= PW_STREAM_FLAG_DONT_RECONNECT;
|
flags |= PW_STREAM_FLAG_DONT_RECONNECT;
|
||||||
|
|
||||||
|
if (sink_name != NULL)
|
||||||
|
pw_properties_set(props,
|
||||||
|
PW_KEY_NODE_TARGET, sink_name);
|
||||||
|
else if (sink_index != SPA_ID_INVALID)
|
||||||
|
pw_properties_setf(props,
|
||||||
|
PW_KEY_NODE_TARGET, "%u", sink_index);
|
||||||
|
|
||||||
fix_stream_properties(stream, props),
|
fix_stream_properties(stream, props),
|
||||||
stream->stream = pw_stream_new(client->core, name, props);
|
stream->stream = pw_stream_new(client->core, name, props);
|
||||||
props = NULL;
|
props = NULL;
|
||||||
|
|
@ -1508,7 +1492,6 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
const struct spa_pod *params[32];
|
const struct spa_pod *params[32];
|
||||||
uint8_t buffer[4096];
|
uint8_t buffer[4096];
|
||||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
|
||||||
struct device *dev = NULL;
|
|
||||||
|
|
||||||
props = pw_properties_new(NULL, NULL);
|
props = pw_properties_new(NULL, NULL);
|
||||||
if (props == NULL) {
|
if (props == NULL) {
|
||||||
|
|
@ -1543,19 +1526,7 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
if (source_index != SPA_ID_INVALID && source_name != NULL) {
|
if (source_index != SPA_ID_INVALID && source_name != NULL) {
|
||||||
res = -EINVAL;
|
res = -EINVAL;
|
||||||
goto error;
|
goto error;
|
||||||
} else if ((source_index != SPA_ID_INVALID || source_name != NULL)) {
|
|
||||||
dev = find_device(impl, source_index, source_name);
|
|
||||||
if (dev == NULL) {
|
|
||||||
res = -ENOENT;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dev = &impl->default_source;
|
|
||||||
}
|
}
|
||||||
if (dev->direction == PW_DIRECTION_INPUT)
|
|
||||||
dev = dev->monitor;
|
|
||||||
if (SPA_FLAG_IS_SET(dev->flags, DEVICE_FLAG_MONITOR))
|
|
||||||
pw_properties_set(props, PW_KEY_STREAM_CAPTURE_SINK, "true");
|
|
||||||
|
|
||||||
if (client->version >= 12) {
|
if (client->version >= 12) {
|
||||||
if ((res = message_get(m,
|
if ((res = message_get(m,
|
||||||
|
|
@ -1662,7 +1633,6 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
stream->muted = muted;
|
stream->muted = muted;
|
||||||
stream->muted_set = muted_set;
|
stream->muted_set = muted_set;
|
||||||
stream->attr = attr;
|
stream->attr = attr;
|
||||||
stream->dev = dev;
|
|
||||||
|
|
||||||
if (peak_detect)
|
if (peak_detect)
|
||||||
pw_properties_set(props, PW_KEY_STREAM_MONITOR, "true");
|
pw_properties_set(props, PW_KEY_STREAM_MONITOR, "true");
|
||||||
|
|
@ -1670,6 +1640,13 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
if (no_move)
|
if (no_move)
|
||||||
flags |= PW_STREAM_FLAG_DONT_RECONNECT;
|
flags |= PW_STREAM_FLAG_DONT_RECONNECT;
|
||||||
|
|
||||||
|
if (source_name != NULL)
|
||||||
|
pw_properties_set(props,
|
||||||
|
PW_KEY_NODE_TARGET, source_name);
|
||||||
|
else if (source_index != SPA_ID_INVALID)
|
||||||
|
pw_properties_setf(props,
|
||||||
|
PW_KEY_NODE_TARGET, "%u", source_index);
|
||||||
|
|
||||||
fix_stream_properties(stream, props),
|
fix_stream_properties(stream, props),
|
||||||
stream->stream = pw_stream_new(client->core, name, props);
|
stream->stream = pw_stream_new(client->core, name, props);
|
||||||
props = NULL;
|
props = NULL;
|
||||||
|
|
@ -2110,8 +2087,8 @@ static int do_get_server_info(struct client *client, uint32_t command, uint32_t
|
||||||
TAG_STRING, pw_get_user_name(),
|
TAG_STRING, pw_get_user_name(),
|
||||||
TAG_STRING, pw_get_host_name(),
|
TAG_STRING, pw_get_host_name(),
|
||||||
TAG_SAMPLE_SPEC, &ss,
|
TAG_SAMPLE_SPEC, &ss,
|
||||||
TAG_STRING, impl->default_sink.name,
|
TAG_STRING, NULL, /* default sink name */
|
||||||
TAG_STRING, impl->default_source.name,
|
TAG_STRING, NULL /* default source name */,
|
||||||
TAG_U32, 0,
|
TAG_U32, 0,
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
|
|
||||||
|
|
@ -2147,7 +2124,7 @@ static int do_lookup(struct client *client, uint32_t command, uint32_t tag, stru
|
||||||
struct impl *impl = client->impl;
|
struct impl *impl = client->impl;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
struct message *reply;
|
struct message *reply;
|
||||||
struct device *dev;
|
struct pw_manager_object *o;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if ((res = message_get(m,
|
if ((res = message_get(m,
|
||||||
|
|
@ -2158,13 +2135,12 @@ static int do_lookup(struct client *client, uint32_t command, uint32_t tag, stru
|
||||||
goto error_invalid;
|
goto error_invalid;
|
||||||
|
|
||||||
pw_log_info(NAME" %p: LOOKUP %s", impl, name);
|
pw_log_info(NAME" %p: LOOKUP %s", impl, name);
|
||||||
|
if ((o = find_node_by_name(impl, name)) == NULL)
|
||||||
if ((dev = find_device_by_name(impl, name)) == NULL)
|
|
||||||
goto error_noentity;
|
goto error_noentity;
|
||||||
|
|
||||||
reply = reply_new(client, tag);
|
reply = reply_new(client, tag);
|
||||||
message_put(reply,
|
message_put(reply,
|
||||||
TAG_U32, dev->index,
|
TAG_U32, SPA_ID_INVALID,
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
|
|
||||||
return send_message(client, reply);
|
return send_message(client, reply);
|
||||||
|
|
@ -2203,11 +2179,15 @@ static int do_drain_stream(struct client *client, uint32_t command, uint32_t tag
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fill_client_info(struct client *client, struct message *m,
|
static int fill_client_info(struct client *client, struct message *m,
|
||||||
struct pw_manager_object *o)
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct pw_client_info *info = o->info;
|
struct pw_client_info *info = o->info;
|
||||||
|
|
||||||
|
if (o == NULL ||
|
||||||
|
strcmp(o->type, PW_TYPE_INTERFACE_Client) != 0)
|
||||||
|
return ERR_NOENTITY;
|
||||||
|
|
||||||
message_put(m,
|
message_put(m,
|
||||||
TAG_U32, o->id, /* client index */
|
TAG_U32, o->id, /* client index */
|
||||||
TAG_STRING, pw_properties_get(o->props, PW_KEY_APP_NAME),
|
TAG_STRING, pw_properties_get(o->props, PW_KEY_APP_NAME),
|
||||||
|
|
@ -2219,13 +2199,18 @@ static void fill_client_info(struct client *client, struct message *m,
|
||||||
TAG_PROPLIST, info ? info->props : NULL,
|
TAG_PROPLIST, info ? info->props : NULL,
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fill_module_info(struct client *client, struct message *m,
|
static int fill_module_info(struct client *client, struct message *m,
|
||||||
struct pw_manager_object *o)
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct pw_module_info *info = o->info;
|
struct pw_module_info *info = o->info;
|
||||||
|
|
||||||
|
if (o == NULL ||
|
||||||
|
strcmp(o->type, PW_TYPE_INTERFACE_Module) != 0)
|
||||||
|
return ERR_NOENTITY;
|
||||||
|
|
||||||
message_put(m,
|
message_put(m,
|
||||||
TAG_U32, o->id, /* module index */
|
TAG_U32, o->id, /* module index */
|
||||||
TAG_STRING, info ? info->name : NULL,
|
TAG_STRING, info ? info->name : NULL,
|
||||||
|
|
@ -2243,19 +2228,22 @@ static void fill_module_info(struct client *client, struct message *m,
|
||||||
TAG_PROPLIST, info ? info->props : NULL,
|
TAG_PROPLIST, info ? info->props : NULL,
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fill_card_info(struct client *client, struct message *m,
|
static int fill_card_info(struct client *client, struct message *m,
|
||||||
struct pw_manager_object *o)
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct pw_device_info *info = o->info;
|
struct pw_device_info *info = o->info;
|
||||||
const char *str;
|
const char *str;
|
||||||
uint32_t module_id = SPA_ID_INVALID;
|
uint32_t module_id = SPA_ID_INVALID;
|
||||||
|
|
||||||
if (o->props == NULL || info == NULL || info->props == NULL ||
|
if (o == NULL ||
|
||||||
|
strcmp(o->type, PW_TYPE_INTERFACE_Device) != 0 ||
|
||||||
|
o->props == NULL || info == NULL || info->props == NULL ||
|
||||||
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) == NULL ||
|
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) == NULL ||
|
||||||
strcmp(str, "Audio/Device") != 0)
|
strcmp(str, "Audio/Device") != 0)
|
||||||
return;
|
return ERR_NOENTITY;
|
||||||
|
|
||||||
if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL)
|
if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL)
|
||||||
module_id = (uint32_t)atoi(str);
|
module_id = (uint32_t)atoi(str);
|
||||||
|
|
@ -2289,7 +2277,7 @@ static void fill_card_info(struct client *client, struct message *m,
|
||||||
TAG_PROPLIST, info->props,
|
TAG_PROPLIST, info->props,
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
if (client->version < 26)
|
if (client->version < 26)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
message_put(m,
|
message_put(m,
|
||||||
TAG_U32, 0, /* n_ports */
|
TAG_U32, 0, /* n_ports */
|
||||||
|
|
@ -2323,31 +2311,57 @@ static void fill_card_info(struct client *client, struct message *m,
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fill_sink_info(struct client *client, struct message *m, struct device *sink)
|
static int fill_sink_info(struct client *client, struct message *m,
|
||||||
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct device *monitor = sink->monitor;
|
struct pw_node_info *info = o->info;
|
||||||
|
const char *str;
|
||||||
|
struct sample_spec ss;
|
||||||
|
struct volume volume;
|
||||||
|
struct channel_map map;
|
||||||
|
|
||||||
|
if (o == NULL ||
|
||||||
|
strcmp(o->type, PW_TYPE_INTERFACE_Node) != 0 ||
|
||||||
|
o->props == NULL || info == NULL || info->props == NULL ||
|
||||||
|
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) == NULL ||
|
||||||
|
strcmp(str, "Audio/Sink") != 0)
|
||||||
|
return ERR_NOENTITY;
|
||||||
|
|
||||||
|
ss = (struct sample_spec) {
|
||||||
|
.format = SAMPLE_FLOAT32LE,
|
||||||
|
.rate = 44100,
|
||||||
|
.channels = 2, };
|
||||||
|
volume = (struct volume) {
|
||||||
|
.channels = 2,
|
||||||
|
.values[0] = 1.0f,
|
||||||
|
.values[1] = 1.0f, };
|
||||||
|
map = (struct channel_map) {
|
||||||
|
.channels = 2,
|
||||||
|
.map[0] = 1,
|
||||||
|
.map[1] = 2, };
|
||||||
|
|
||||||
message_put(m,
|
message_put(m,
|
||||||
TAG_U32, sink->index, /* sink index */
|
TAG_U32, o->id, /* sink index */
|
||||||
TAG_STRING, sink->name,
|
TAG_STRING, spa_dict_lookup(info->props, PW_KEY_NODE_NAME),
|
||||||
TAG_STRING, pw_properties_get(sink->props, PW_KEY_DEVICE_DESCRIPTION),
|
TAG_STRING, spa_dict_lookup(info->props, PW_KEY_NODE_DESCRIPTION),
|
||||||
TAG_SAMPLE_SPEC, &sink->ss,
|
TAG_SAMPLE_SPEC, &ss,
|
||||||
TAG_CHANNEL_MAP, &sink->map,
|
TAG_CHANNEL_MAP, &map,
|
||||||
TAG_U32, SPA_ID_INVALID, /* module index */
|
TAG_U32, SPA_ID_INVALID, /* module index */
|
||||||
TAG_CVOLUME, &sink->volume,
|
TAG_CVOLUME, &volume,
|
||||||
TAG_BOOLEAN, sink->muted,
|
TAG_BOOLEAN, false,
|
||||||
TAG_U32, monitor ? monitor->index : SPA_ID_INVALID, /* monitor source */
|
TAG_U32, SPA_ID_INVALID, /* monitor source */
|
||||||
TAG_STRING, monitor ? monitor->name : NULL, /* monitor source name */
|
TAG_STRING, NULL, /* monitor source name */
|
||||||
TAG_USEC, 0LL, /* latency */
|
TAG_USEC, 0LL, /* latency */
|
||||||
TAG_STRING, "PipeWire", /* driver */
|
TAG_STRING, "PipeWire", /* driver */
|
||||||
TAG_U32, 0, /* flags */
|
TAG_U32, 0, /* flags */
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
|
|
||||||
if (client->version >= 13) {
|
if (client->version >= 13) {
|
||||||
message_put(m,
|
message_put(m,
|
||||||
TAG_PROPLIST, sink->props ? &sink->props->dict : NULL,
|
TAG_PROPLIST, info->props,
|
||||||
TAG_USEC, 0LL, /* requested latency */
|
TAG_USEC, 0LL, /* requested latency */
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
}
|
}
|
||||||
|
|
@ -2376,23 +2390,54 @@ static void fill_sink_info(struct client *client, struct message *m, struct devi
|
||||||
TAG_FORMAT_INFO, &info,
|
TAG_FORMAT_INFO, &info,
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fill_source_info(struct client *client, struct message *m, struct device *source)
|
static int fill_source_info(struct client *client, struct message *m,
|
||||||
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct device *monitor = source->monitor;
|
struct pw_node_info *info = o->info;
|
||||||
|
const char *str;
|
||||||
|
struct sample_spec ss;
|
||||||
|
struct volume volume;
|
||||||
|
struct channel_map map;
|
||||||
|
bool is_monitor;
|
||||||
|
|
||||||
|
if (o == NULL ||
|
||||||
|
strcmp(o->type, PW_TYPE_INTERFACE_Node) != 0 ||
|
||||||
|
o->props == NULL || info == NULL || info->props == NULL ||
|
||||||
|
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) == NULL)
|
||||||
|
return ERR_NOENTITY;
|
||||||
|
|
||||||
|
is_monitor = strcmp(str, "Audio/Sink") == 0;
|
||||||
|
if (strcmp(str, "Audio/Source") != 0 &&
|
||||||
|
!is_monitor)
|
||||||
|
return ERR_NOENTITY;
|
||||||
|
|
||||||
|
ss = (struct sample_spec) {
|
||||||
|
.format = SAMPLE_FLOAT32LE,
|
||||||
|
.rate = 44100,
|
||||||
|
.channels = 2, };
|
||||||
|
volume = (struct volume) {
|
||||||
|
.channels = 2,
|
||||||
|
.values[0] = 1.0f,
|
||||||
|
.values[1] = 1.0f, };
|
||||||
|
map = (struct channel_map) {
|
||||||
|
.channels = 2,
|
||||||
|
.map[0] = 1,
|
||||||
|
.map[1] = 2, };
|
||||||
|
|
||||||
message_put(m,
|
message_put(m,
|
||||||
TAG_U32, source->index, /* source index */
|
TAG_U32, is_monitor ? o->id | 0x10000 : o->id, /* source index */
|
||||||
TAG_STRING, source->name,
|
TAG_STRING, spa_dict_lookup(info->props, PW_KEY_NODE_NAME),
|
||||||
TAG_STRING, pw_properties_get(source->props, PW_KEY_DEVICE_DESCRIPTION),
|
TAG_STRING, spa_dict_lookup(info->props, PW_KEY_NODE_DESCRIPTION),
|
||||||
TAG_SAMPLE_SPEC, &source->ss,
|
TAG_SAMPLE_SPEC, &ss,
|
||||||
TAG_CHANNEL_MAP, &source->map,
|
TAG_CHANNEL_MAP, &map,
|
||||||
TAG_U32, SPA_ID_INVALID, /* module index */
|
TAG_U32, SPA_ID_INVALID, /* module index */
|
||||||
TAG_CVOLUME, &source->volume,
|
TAG_CVOLUME, &volume,
|
||||||
TAG_BOOLEAN, source->muted,
|
TAG_BOOLEAN, false,
|
||||||
TAG_U32, monitor ? monitor->index : SPA_ID_INVALID, /* monitor source */
|
TAG_U32, SPA_ID_INVALID, /* monitor source */
|
||||||
TAG_STRING, monitor ? monitor->name : NULL, /* monitor source name */
|
TAG_STRING, NULL, /* monitor source name */
|
||||||
TAG_USEC, 0LL, /* latency */
|
TAG_USEC, 0LL, /* latency */
|
||||||
TAG_STRING, "PipeWire", /* driver */
|
TAG_STRING, "PipeWire", /* driver */
|
||||||
TAG_U32, 0, /* flags */
|
TAG_U32, 0, /* flags */
|
||||||
|
|
@ -2400,7 +2445,7 @@ static void fill_source_info(struct client *client, struct message *m, struct de
|
||||||
|
|
||||||
if (client->version >= 13) {
|
if (client->version >= 13) {
|
||||||
message_put(m,
|
message_put(m,
|
||||||
TAG_PROPLIST, source->props ? &source->props->dict : NULL,
|
TAG_PROPLIST, info->props,
|
||||||
TAG_USEC, 0LL, /* requested latency */
|
TAG_USEC, 0LL, /* requested latency */
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
}
|
}
|
||||||
|
|
@ -2429,6 +2474,143 @@ static void fill_source_info(struct client *client, struct message *m, struct de
|
||||||
TAG_FORMAT_INFO, &info,
|
TAG_FORMAT_INFO, &info,
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fill_sink_input_info(struct client *client, struct message *m,
|
||||||
|
struct pw_manager_object *o)
|
||||||
|
{
|
||||||
|
struct pw_node_info *info = o->info;
|
||||||
|
const char *str;
|
||||||
|
struct sample_spec ss;
|
||||||
|
struct volume volume;
|
||||||
|
struct channel_map map;
|
||||||
|
|
||||||
|
if (o == NULL ||
|
||||||
|
strcmp(o->type, PW_TYPE_INTERFACE_Node) != 0 ||
|
||||||
|
o->props == NULL || info == NULL || info->props == NULL ||
|
||||||
|
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) == NULL ||
|
||||||
|
strcmp(str, "Stream/Output/Audio") != 0)
|
||||||
|
return ERR_NOENTITY;
|
||||||
|
|
||||||
|
ss = (struct sample_spec) {
|
||||||
|
.format = SAMPLE_FLOAT32LE,
|
||||||
|
.rate = 44100,
|
||||||
|
.channels = 2, };
|
||||||
|
volume = (struct volume) {
|
||||||
|
.channels = 2,
|
||||||
|
.values[0] = 1.0f,
|
||||||
|
.values[1] = 1.0f, };
|
||||||
|
map = (struct channel_map) {
|
||||||
|
.channels = 2,
|
||||||
|
.map[0] = 1,
|
||||||
|
.map[1] = 2, };
|
||||||
|
|
||||||
|
message_put(m,
|
||||||
|
TAG_U32, o->id, /* sink_input index */
|
||||||
|
TAG_STRING, spa_dict_lookup(info->props, PW_KEY_MEDIA_NAME),
|
||||||
|
TAG_U32, SPA_ID_INVALID, /* module index */
|
||||||
|
TAG_U32, SPA_ID_INVALID, /* client index */
|
||||||
|
TAG_U32, SPA_ID_INVALID, /* sink index */
|
||||||
|
TAG_SAMPLE_SPEC, &ss,
|
||||||
|
TAG_CHANNEL_MAP, &map,
|
||||||
|
TAG_CVOLUME, &volume,
|
||||||
|
TAG_USEC, 0LL, /* latency */
|
||||||
|
TAG_USEC, 0LL, /* sink latency */
|
||||||
|
TAG_STRING, "PipeWire", /* resample method */
|
||||||
|
TAG_STRING, "PipeWire", /* driver */
|
||||||
|
TAG_INVALID);
|
||||||
|
if (client->version >= 11)
|
||||||
|
message_put(m,
|
||||||
|
TAG_BOOLEAN, false, /* muted */
|
||||||
|
TAG_INVALID);
|
||||||
|
if (client->version >= 13)
|
||||||
|
message_put(m,
|
||||||
|
TAG_PROPLIST, info->props,
|
||||||
|
TAG_INVALID);
|
||||||
|
if (client->version >= 19)
|
||||||
|
message_put(m,
|
||||||
|
TAG_BOOLEAN, false, /* corked */
|
||||||
|
TAG_INVALID);
|
||||||
|
if (client->version >= 20)
|
||||||
|
message_put(m,
|
||||||
|
TAG_BOOLEAN, true, /* has_volume */
|
||||||
|
TAG_BOOLEAN, true, /* volume writable */
|
||||||
|
TAG_INVALID);
|
||||||
|
if (client->version >= 21) {
|
||||||
|
struct format_info fi;
|
||||||
|
spa_zero(fi);
|
||||||
|
fi.encoding = ENCODING_PCM;
|
||||||
|
message_put(m,
|
||||||
|
TAG_FORMAT_INFO, &fi,
|
||||||
|
TAG_INVALID);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fill_source_output_info(struct client *client, struct message *m,
|
||||||
|
struct pw_manager_object *o)
|
||||||
|
{
|
||||||
|
struct pw_node_info *info = o->info;
|
||||||
|
const char *str;
|
||||||
|
struct sample_spec ss;
|
||||||
|
struct volume volume;
|
||||||
|
struct channel_map map;
|
||||||
|
|
||||||
|
if (o == NULL ||
|
||||||
|
strcmp(o->type, PW_TYPE_INTERFACE_Node) != 0 ||
|
||||||
|
o->props == NULL || info == NULL || info->props == NULL ||
|
||||||
|
(str = pw_properties_get(o->props, PW_KEY_MEDIA_CLASS)) == NULL ||
|
||||||
|
strcmp(str, "Stream/Input/Audio") != 0)
|
||||||
|
return ERR_NOENTITY;
|
||||||
|
|
||||||
|
ss = (struct sample_spec) {
|
||||||
|
.format = SAMPLE_FLOAT32LE,
|
||||||
|
.rate = 44100,
|
||||||
|
.channels = 2, };
|
||||||
|
volume = (struct volume) {
|
||||||
|
.channels = 2,
|
||||||
|
.values[0] = 1.0f,
|
||||||
|
.values[1] = 1.0f, };
|
||||||
|
map = (struct channel_map) {
|
||||||
|
.channels = 2,
|
||||||
|
.map[0] = 1,
|
||||||
|
.map[1] = 2, };
|
||||||
|
|
||||||
|
message_put(m,
|
||||||
|
TAG_U32, o->id, /* source_output index */
|
||||||
|
TAG_STRING, spa_dict_lookup(info->props, PW_KEY_MEDIA_NAME),
|
||||||
|
TAG_U32, SPA_ID_INVALID, /* module index */
|
||||||
|
TAG_U32, SPA_ID_INVALID, /* client index */
|
||||||
|
TAG_U32, SPA_ID_INVALID, /* source index */
|
||||||
|
TAG_SAMPLE_SPEC, &ss,
|
||||||
|
TAG_CHANNEL_MAP, &map,
|
||||||
|
TAG_USEC, 0LL, /* latency */
|
||||||
|
TAG_USEC, 0LL, /* source latency */
|
||||||
|
TAG_STRING, "PipeWire", /* resample method */
|
||||||
|
TAG_STRING, "PipeWire", /* driver */
|
||||||
|
TAG_INVALID);
|
||||||
|
if (client->version >= 13)
|
||||||
|
message_put(m,
|
||||||
|
TAG_PROPLIST, info->props,
|
||||||
|
TAG_INVALID);
|
||||||
|
if (client->version >= 19)
|
||||||
|
message_put(m,
|
||||||
|
TAG_BOOLEAN, false, /* corked */
|
||||||
|
TAG_INVALID);
|
||||||
|
if (client->version >= 22) {
|
||||||
|
struct format_info fi;
|
||||||
|
spa_zero(fi);
|
||||||
|
fi.encoding = ENCODING_PCM;
|
||||||
|
message_put(m,
|
||||||
|
TAG_CVOLUME, &volume,
|
||||||
|
TAG_BOOLEAN, false, /* muted */
|
||||||
|
TAG_BOOLEAN, true, /* has_volume */
|
||||||
|
TAG_BOOLEAN, true, /* volume writable */
|
||||||
|
TAG_FORMAT_INFO, &fi,
|
||||||
|
TAG_INVALID);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_get_info(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
static int do_get_info(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
||||||
|
|
@ -2437,7 +2619,6 @@ static int do_get_info(struct client *client, uint32_t command, uint32_t tag, st
|
||||||
struct message *reply = NULL;
|
struct message *reply = NULL;
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
struct device *dev;
|
|
||||||
int res, err;
|
int res, err;
|
||||||
struct pw_manager_object *o;
|
struct pw_manager_object *o;
|
||||||
|
|
||||||
|
|
@ -2465,60 +2646,50 @@ static int do_get_info(struct client *client, uint32_t command, uint32_t tag, st
|
||||||
pw_log_info(NAME" %p: %s idx:%u name:%s", impl,
|
pw_log_info(NAME" %p: %s idx:%u name:%s", impl,
|
||||||
commands[command].name, idx, name);
|
commands[command].name, idx, name);
|
||||||
|
|
||||||
|
o = pw_manager_find_object(client->manager, idx);
|
||||||
|
|
||||||
reply = reply_new(client, tag);
|
reply = reply_new(client, tag);
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case COMMAND_GET_CLIENT_INFO:
|
case COMMAND_GET_CLIENT_INFO:
|
||||||
o = pw_manager_find_object(client->manager, PW_TYPE_INTERFACE_Client, idx);
|
err = fill_client_info(client, reply, o);
|
||||||
if (o == NULL)
|
|
||||||
goto error_noentity;
|
|
||||||
fill_client_info(client, reply, o);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_GET_MODULE_INFO:
|
case COMMAND_GET_MODULE_INFO:
|
||||||
o = pw_manager_find_object(client->manager, PW_TYPE_INTERFACE_Module, idx);
|
err = fill_module_info(client, reply, o);
|
||||||
if (o == NULL)
|
|
||||||
goto error_noentity;
|
|
||||||
fill_module_info(client, reply, o);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_GET_CARD_INFO:
|
case COMMAND_GET_CARD_INFO:
|
||||||
|
err = fill_card_info(client, reply, o);
|
||||||
|
break;
|
||||||
|
|
||||||
case COMMAND_GET_SAMPLE_INFO:
|
case COMMAND_GET_SAMPLE_INFO:
|
||||||
goto error_noentity;
|
err = ERR_NOENTITY;
|
||||||
|
break;
|
||||||
|
|
||||||
case COMMAND_GET_SINK_INFO:
|
case COMMAND_GET_SINK_INFO:
|
||||||
dev = find_device(impl, idx, name);
|
err = fill_sink_info(client, reply, o);
|
||||||
if (dev == NULL)
|
|
||||||
goto error_noentity;
|
|
||||||
if (dev->direction != PW_DIRECTION_INPUT)
|
|
||||||
goto error_invalid;
|
|
||||||
fill_sink_info(client, reply, dev);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COMMAND_GET_SOURCE_INFO:
|
case COMMAND_GET_SOURCE_INFO:
|
||||||
|
err = fill_source_info(client, reply, o);
|
||||||
dev = find_device(impl, idx, name);
|
|
||||||
if (dev == NULL)
|
|
||||||
goto error_noentity;
|
|
||||||
if (dev->direction != PW_DIRECTION_OUTPUT)
|
|
||||||
goto error_invalid;
|
|
||||||
|
|
||||||
fill_source_info(client, reply, dev);
|
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_SINK_INPUT_INFO:
|
case COMMAND_GET_SINK_INPUT_INFO:
|
||||||
|
err = fill_sink_input_info(client, reply, o);
|
||||||
|
break;
|
||||||
case COMMAND_GET_SOURCE_OUTPUT_INFO:
|
case COMMAND_GET_SOURCE_OUTPUT_INFO:
|
||||||
/* fixme add ourselves */
|
err = fill_source_output_info(client, reply, o);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
if (err != 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
return send_message(client, reply);
|
return send_message(client, reply);
|
||||||
|
|
||||||
error_protocol:
|
error_protocol:
|
||||||
err = ERR_PROTOCOL;
|
err = ERR_PROTOCOL;
|
||||||
goto error;
|
goto error;
|
||||||
error_noentity:
|
|
||||||
err = ERR_NOENTITY;
|
|
||||||
goto error;
|
|
||||||
error_invalid:
|
error_invalid:
|
||||||
err = ERR_INVALID;
|
err = ERR_INVALID;
|
||||||
goto error;
|
goto error;
|
||||||
|
|
@ -2531,38 +2702,13 @@ error:
|
||||||
struct info_list_data {
|
struct info_list_data {
|
||||||
struct client *client;
|
struct client *client;
|
||||||
struct message *reply;
|
struct message *reply;
|
||||||
|
int (*fill_func) (struct client *client, struct message *m, struct pw_manager_object *o);
|
||||||
};
|
};
|
||||||
|
|
||||||
static int do_list_clients(void *data, struct pw_manager_object *object)
|
static int do_list_info(void *data, struct pw_manager_object *object)
|
||||||
{
|
{
|
||||||
struct info_list_data *info = data;
|
struct info_list_data *info = data;
|
||||||
|
info->fill_func(info->client, info->reply, object);
|
||||||
if (strcmp(object->type, PW_TYPE_INTERFACE_Client) != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fill_client_info(info->client, info->reply, object);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_list_modules(void *data, struct pw_manager_object *object)
|
|
||||||
{
|
|
||||||
struct info_list_data *info = data;
|
|
||||||
|
|
||||||
if (strcmp(object->type, PW_TYPE_INTERFACE_Module) != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fill_module_info(info->client, info->reply, object);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_list_cards(void *data, struct pw_manager_object *object)
|
|
||||||
{
|
|
||||||
struct info_list_data *info = data;
|
|
||||||
|
|
||||||
if (strcmp(object->type, PW_TYPE_INTERFACE_Device) != 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fill_card_info(info->client, info->reply, object);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2570,7 +2716,6 @@ static int do_get_info_list(struct client *client, uint32_t command, uint32_t ta
|
||||||
{
|
{
|
||||||
struct impl *impl = client->impl;
|
struct impl *impl = client->impl;
|
||||||
struct info_list_data info;
|
struct info_list_data info;
|
||||||
int (*list_func) (void *data, struct pw_manager_object *object) = NULL;
|
|
||||||
|
|
||||||
pw_log_info(NAME" %p: %s", impl, commands[command].name);
|
pw_log_info(NAME" %p: %s", impl, commands[command].name);
|
||||||
|
|
||||||
|
|
@ -2579,32 +2724,33 @@ static int do_get_info_list(struct client *client, uint32_t command, uint32_t ta
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case COMMAND_GET_CLIENT_INFO_LIST:
|
case COMMAND_GET_CLIENT_INFO_LIST:
|
||||||
list_func = do_list_clients;
|
info.fill_func = fill_client_info;
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_MODULE_INFO_LIST:
|
case COMMAND_GET_MODULE_INFO_LIST:
|
||||||
list_func = do_list_modules;
|
info.fill_func = fill_module_info;
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_CARD_INFO_LIST:
|
case COMMAND_GET_CARD_INFO_LIST:
|
||||||
list_func = do_list_cards;
|
info.fill_func = fill_card_info;
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_SAMPLE_INFO_LIST:
|
case COMMAND_GET_SAMPLE_INFO_LIST:
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_SINK_INFO_LIST:
|
case COMMAND_GET_SINK_INFO_LIST:
|
||||||
fill_sink_info(client, info.reply, &impl->default_sink);
|
info.fill_func = fill_sink_info;
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_SOURCE_INFO_LIST:
|
case COMMAND_GET_SOURCE_INFO_LIST:
|
||||||
fill_source_info(client, info.reply, &impl->default_source);
|
info.fill_func = fill_source_info;
|
||||||
fill_source_info(client, info.reply, &impl->default_monitor);
|
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_SINK_INPUT_INFO_LIST:
|
case COMMAND_GET_SINK_INPUT_INFO_LIST:
|
||||||
|
info.fill_func = fill_sink_input_info;
|
||||||
|
break;
|
||||||
case COMMAND_GET_SOURCE_OUTPUT_INFO_LIST:
|
case COMMAND_GET_SOURCE_OUTPUT_INFO_LIST:
|
||||||
/* fixme add ourselves */
|
info.fill_func = fill_source_output_info;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
if (list_func)
|
if (info.fill_func)
|
||||||
pw_manager_for_each_object(client->manager, list_func, &info);
|
pw_manager_for_each_object(client->manager, do_list_info, &info);
|
||||||
|
|
||||||
return send_message(client, info.reply);
|
return send_message(client, info.reply);
|
||||||
}
|
}
|
||||||
|
|
@ -3413,73 +3559,6 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
|
||||||
pw_context_add_listener(context, &impl->context_listener,
|
pw_context_add_listener(context, &impl->context_listener,
|
||||||
&context_events, impl);
|
&context_events, impl);
|
||||||
|
|
||||||
impl->default_sink = (struct device) {
|
|
||||||
.index = 1,
|
|
||||||
.name = "input.pipewire",
|
|
||||||
.direction = PW_DIRECTION_INPUT,
|
|
||||||
.props = pw_properties_new(
|
|
||||||
PW_KEY_DEVICE_DESCRIPTION, "PipeWire Sink",
|
|
||||||
NULL),
|
|
||||||
.ss = (struct sample_spec) {
|
|
||||||
.format = SAMPLE_FLOAT32LE,
|
|
||||||
.rate = 44100,
|
|
||||||
.channels = 2, },
|
|
||||||
.volume = (struct volume) {
|
|
||||||
.channels = 2,
|
|
||||||
.values[0] = 1.0f,
|
|
||||||
.values[1] = 1.0f, },
|
|
||||||
.map = (struct channel_map) {
|
|
||||||
.channels = 2,
|
|
||||||
.map[0] = 1,
|
|
||||||
.map[1] = 2, },
|
|
||||||
.muted = false,
|
|
||||||
.monitor = &impl->default_monitor,
|
|
||||||
};
|
|
||||||
impl->default_monitor = (struct device) {
|
|
||||||
.flags = DEVICE_FLAG_MONITOR,
|
|
||||||
.index = 2,
|
|
||||||
.name = "output.pipewire.monitor",
|
|
||||||
.direction = PW_DIRECTION_OUTPUT,
|
|
||||||
.props = pw_properties_new(
|
|
||||||
PW_KEY_DEVICE_DESCRIPTION, "Monitor of PipeWire Sink",
|
|
||||||
NULL),
|
|
||||||
.ss = (struct sample_spec) {
|
|
||||||
.format = SAMPLE_FLOAT32LE,
|
|
||||||
.rate = 44100,
|
|
||||||
.channels = 2, },
|
|
||||||
.volume = (struct volume) {
|
|
||||||
.channels = 2,
|
|
||||||
.values[0] = 1.0f,
|
|
||||||
.values[1] = 1.0f, },
|
|
||||||
.map = (struct channel_map) {
|
|
||||||
.channels = 2,
|
|
||||||
.map[0] = 1,
|
|
||||||
.map[1] = 2, },
|
|
||||||
.muted = false,
|
|
||||||
.monitor = &impl->default_sink,
|
|
||||||
};
|
|
||||||
impl->default_source = (struct device) {
|
|
||||||
.index = 3,
|
|
||||||
.name = "output.pipewire",
|
|
||||||
.direction = PW_DIRECTION_OUTPUT,
|
|
||||||
.props = pw_properties_new(
|
|
||||||
PW_KEY_DEVICE_DESCRIPTION, "PipeWire Source",
|
|
||||||
NULL),
|
|
||||||
.ss = (struct sample_spec) {
|
|
||||||
.format = SAMPLE_FLOAT32LE,
|
|
||||||
.rate = 44100,
|
|
||||||
.channels = 2, },
|
|
||||||
.volume = (struct volume) {
|
|
||||||
.channels = 2,
|
|
||||||
.values[0] = 1.0f,
|
|
||||||
.values[1] = 1.0f, },
|
|
||||||
.map = (struct channel_map) {
|
|
||||||
.channels = 2,
|
|
||||||
.map[0] = 1,
|
|
||||||
.map[1] = 2, },
|
|
||||||
.muted = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
str = NULL;
|
str = NULL;
|
||||||
if (props != NULL)
|
if (props != NULL)
|
||||||
str = pw_properties_get(props, "server.address");
|
str = pw_properties_get(props, "server.address");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue