mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
pulse-server: add a monitor for the sink
This commit is contained in:
parent
348110e58c
commit
58db8ca435
1 changed files with 91 additions and 9 deletions
|
|
@ -97,6 +97,7 @@ struct device {
|
||||||
struct cvolume volume;
|
struct cvolume volume;
|
||||||
struct channel_map map;
|
struct channel_map map;
|
||||||
bool muted;
|
bool muted;
|
||||||
|
struct device *monitor;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct buffer_attr {
|
struct buffer_attr {
|
||||||
|
|
@ -169,6 +170,7 @@ struct impl {
|
||||||
struct spa_list servers;
|
struct spa_list servers;
|
||||||
|
|
||||||
struct device default_sink;
|
struct device default_sink;
|
||||||
|
struct device default_monitor;
|
||||||
struct device default_source;
|
struct device default_source;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1894,12 +1896,40 @@ static int do_stat(struct client *client, uint32_t command, uint32_t tag, struct
|
||||||
return send_message(client, reply);
|
return send_message(client, reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct device *find_device_by_name(struct impl *impl, const char *name)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
if (strcmp(name, impl->default_source.name) == 0)
|
||||||
|
dev = &impl->default_source;
|
||||||
|
else if (strcmp(name, impl->default_sink.name) == 0)
|
||||||
|
dev = &impl->default_sink;
|
||||||
|
else if (strcmp(name, impl->default_monitor.name) == 0)
|
||||||
|
dev = &impl->default_monitor;
|
||||||
|
else
|
||||||
|
dev = NULL;
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct device *find_device_by_index(struct impl *impl, uint32_t index)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
if (impl->default_source.index == index)
|
||||||
|
dev = &impl->default_source;
|
||||||
|
else if (impl->default_sink.index == index)
|
||||||
|
dev = &impl->default_sink;
|
||||||
|
else if (impl->default_monitor.index == index)
|
||||||
|
dev = &impl->default_monitor;
|
||||||
|
else
|
||||||
|
dev = NULL;
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_lookup(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
static int do_lookup(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
||||||
{
|
{
|
||||||
struct impl *impl = client->impl;
|
struct impl *impl = client->impl;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
struct message *reply;
|
struct message *reply;
|
||||||
uint32_t idx = 0;
|
struct device *dev;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if ((res = message_get(m,
|
if ((res = message_get(m,
|
||||||
|
|
@ -1911,9 +1941,12 @@ static int do_lookup(struct client *client, uint32_t command, uint32_t tag, stru
|
||||||
|
|
||||||
pw_log_info(NAME" %p: LOOKUP %s", impl, name);
|
pw_log_info(NAME" %p: LOOKUP %s", impl, name);
|
||||||
|
|
||||||
|
if ((dev = find_device_by_name(impl, name)) == NULL)
|
||||||
|
return reply_error(client, -1, ERR_NOENTITY);
|
||||||
|
|
||||||
reply = reply_new(client, tag);
|
reply = reply_new(client, tag);
|
||||||
message_put(reply,
|
message_put(reply,
|
||||||
TAG_U32, idx,
|
TAG_U32, dev->index,
|
||||||
TAG_INVALID);
|
TAG_INVALID);
|
||||||
|
|
||||||
return send_message(client, reply);
|
return send_message(client, reply);
|
||||||
|
|
@ -1960,6 +1993,8 @@ static void fill_client_info(struct client *client, struct message *m)
|
||||||
|
|
||||||
static void fill_sink_info(struct client *client, struct message *m, struct device *sink)
|
static void fill_sink_info(struct client *client, struct message *m, struct device *sink)
|
||||||
{
|
{
|
||||||
|
struct device *monitor = sink->monitor;
|
||||||
|
|
||||||
message_put(m,
|
message_put(m,
|
||||||
TAG_U32, sink->index, /* sink index */
|
TAG_U32, sink->index, /* sink index */
|
||||||
TAG_STRING, sink->name,
|
TAG_STRING, sink->name,
|
||||||
|
|
@ -1969,8 +2004,8 @@ static void fill_sink_info(struct client *client, struct message *m, struct devi
|
||||||
TAG_U32, SPA_ID_INVALID, /* module index */
|
TAG_U32, SPA_ID_INVALID, /* module index */
|
||||||
TAG_CVOLUME, &sink->volume,
|
TAG_CVOLUME, &sink->volume,
|
||||||
TAG_BOOLEAN, sink->muted,
|
TAG_BOOLEAN, sink->muted,
|
||||||
TAG_U32, SPA_ID_INVALID, /* monitor source */
|
TAG_U32, monitor ? monitor->index : SPA_ID_INVALID, /* monitor source */
|
||||||
TAG_STRING, NULL, /* monitor source name */
|
TAG_STRING, monitor ? monitor->name : 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 */
|
||||||
|
|
@ -2011,6 +2046,8 @@ static void fill_sink_info(struct client *client, struct message *m, struct devi
|
||||||
|
|
||||||
static void fill_source_info(struct client *client, struct message *m, struct device *source)
|
static void fill_source_info(struct client *client, struct message *m, struct device *source)
|
||||||
{
|
{
|
||||||
|
struct device *monitor = source->monitor;
|
||||||
|
|
||||||
message_put(m,
|
message_put(m,
|
||||||
TAG_U32, source->index, /* source index */
|
TAG_U32, source->index, /* source index */
|
||||||
TAG_STRING, source->name,
|
TAG_STRING, source->name,
|
||||||
|
|
@ -2020,8 +2057,8 @@ static void fill_source_info(struct client *client, struct message *m, struct de
|
||||||
TAG_U32, SPA_ID_INVALID, /* module index */
|
TAG_U32, SPA_ID_INVALID, /* module index */
|
||||||
TAG_CVOLUME, &source->volume,
|
TAG_CVOLUME, &source->volume,
|
||||||
TAG_BOOLEAN, source->muted,
|
TAG_BOOLEAN, source->muted,
|
||||||
TAG_U32, SPA_ID_INVALID, /* monitor source */
|
TAG_U32, monitor ? monitor->index : SPA_ID_INVALID, /* monitor source */
|
||||||
TAG_STRING, NULL, /* monitor source name */
|
TAG_STRING, monitor ? monitor->name : 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 */
|
||||||
|
|
@ -2066,6 +2103,7 @@ static int do_get_info(struct client *client, uint32_t command, uint32_t tag, st
|
||||||
struct message *reply;
|
struct message *reply;
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
|
struct device *dev;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if ((res = message_get(m,
|
if ((res = message_get(m,
|
||||||
|
|
@ -2085,6 +2123,9 @@ static int do_get_info(struct client *client, uint32_t command, uint32_t tag, st
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (idx == SPA_ID_INVALID && name == NULL)
|
||||||
|
return reply_error(client, -1, ERR_INVALID);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
@ -2098,10 +2139,27 @@ static int do_get_info(struct client *client, uint32_t command, uint32_t tag, st
|
||||||
case COMMAND_GET_SAMPLE_INFO:
|
case COMMAND_GET_SAMPLE_INFO:
|
||||||
return reply_error(client, -1, ERR_NOENTITY);
|
return reply_error(client, -1, ERR_NOENTITY);
|
||||||
case COMMAND_GET_SINK_INFO:
|
case COMMAND_GET_SINK_INFO:
|
||||||
fill_sink_info(client, reply, &impl->default_sink);
|
if (idx != SPA_ID_INVALID)
|
||||||
|
dev = find_device_by_index(impl, idx);
|
||||||
|
else
|
||||||
|
dev = find_device_by_name(impl, name);
|
||||||
|
if (dev == NULL)
|
||||||
|
return reply_error(client, -1, ERR_NOENTITY);
|
||||||
|
if (dev->direction != PW_DIRECTION_INPUT)
|
||||||
|
return reply_error(client, -1, ERR_INVALID);
|
||||||
|
|
||||||
|
fill_sink_info(client, reply, dev);
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_SOURCE_INFO:
|
case COMMAND_GET_SOURCE_INFO:
|
||||||
fill_source_info(client, reply, &impl->default_source);
|
if (idx != SPA_ID_INVALID)
|
||||||
|
dev = find_device_by_index(impl, idx);
|
||||||
|
else
|
||||||
|
dev = find_device_by_name(impl, name);
|
||||||
|
if (dev == NULL)
|
||||||
|
return reply_error(client, -1, ERR_NOENTITY);
|
||||||
|
if (dev->direction != PW_DIRECTION_OUTPUT)
|
||||||
|
return reply_error(client, -1, ERR_INVALID);
|
||||||
|
fill_source_info(client, reply, dev);
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_SINK_INPUT_INFO:
|
case COMMAND_GET_SINK_INPUT_INFO:
|
||||||
case COMMAND_GET_SOURCE_OUTPUT_INFO:
|
case COMMAND_GET_SOURCE_OUTPUT_INFO:
|
||||||
|
|
@ -2134,6 +2192,7 @@ static int do_get_info_list(struct client *client, uint32_t command, uint32_t ta
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_SOURCE_INFO_LIST:
|
case COMMAND_GET_SOURCE_INFO_LIST:
|
||||||
fill_source_info(client, reply, &impl->default_source);
|
fill_source_info(client, reply, &impl->default_source);
|
||||||
|
fill_source_info(client, reply, &impl->default_monitor);
|
||||||
break;
|
break;
|
||||||
case COMMAND_GET_SINK_INPUT_INFO_LIST:
|
case COMMAND_GET_SINK_INPUT_INFO_LIST:
|
||||||
case COMMAND_GET_SOURCE_OUTPUT_INFO_LIST:
|
case COMMAND_GET_SOURCE_OUTPUT_INFO_LIST:
|
||||||
|
|
@ -2931,9 +2990,32 @@ struct pw_protocol_pulse *pw_protocol_pulse_new(struct pw_context *context,
|
||||||
.map[0] = 1,
|
.map[0] = 1,
|
||||||
.map[1] = 2, },
|
.map[1] = 2, },
|
||||||
.muted = false,
|
.muted = false,
|
||||||
|
.monitor = &impl->default_monitor,
|
||||||
|
};
|
||||||
|
impl->default_monitor = (struct device) {
|
||||||
|
.index = 2,
|
||||||
|
.name = "output.pipewire.monitor",
|
||||||
|
.direction = PW_DIRECTION_OUTPUT,
|
||||||
|
.props = pw_properties_new(
|
||||||
|
"device.description", "Monitor of PipeWire Sink",
|
||||||
|
NULL),
|
||||||
|
.ss = (struct sample_spec) {
|
||||||
|
.format = SAMPLE_FLOAT32LE,
|
||||||
|
.rate = 44100,
|
||||||
|
.channels = 2, },
|
||||||
|
.volume = (struct cvolume) {
|
||||||
|
.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) {
|
impl->default_source = (struct device) {
|
||||||
.index = 2,
|
.index = 3,
|
||||||
.name = "output.pipewire",
|
.name = "output.pipewire",
|
||||||
.direction = PW_DIRECTION_OUTPUT,
|
.direction = PW_DIRECTION_OUTPUT,
|
||||||
.props = pw_properties_new(
|
.props = pw_properties_new(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue