mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
pulse-server: keep track of sink/monitor changes
For sink nodes, keep a separate device_info around for the sink and the monitor source part of the node. Only emit changes for the sink and monitor source part when it changed. See #3388
This commit is contained in:
parent
07c574160c
commit
c9b7367f8f
6 changed files with 152 additions and 103 deletions
|
|
@ -6,6 +6,9 @@
|
||||||
#include <spa/pod/builder.h>
|
#include <spa/pod/builder.h>
|
||||||
#include <spa/pod/parser.h>
|
#include <spa/pod/parser.h>
|
||||||
#include <spa/utils/string.h>
|
#include <spa/utils/string.h>
|
||||||
|
|
||||||
|
#include <spa/param/audio/format-utils.h>
|
||||||
|
|
||||||
#include <pipewire/pipewire.h>
|
#include <pipewire/pipewire.h>
|
||||||
|
|
||||||
#include "collect.h"
|
#include "collect.h"
|
||||||
|
|
@ -226,7 +229,7 @@ uint32_t find_profile_index(struct pw_manager_object *card, const char *name)
|
||||||
return SPA_ID_INVALID;
|
return SPA_ID_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_device_info(struct pw_manager_object *device, struct pw_manager_object *card,
|
static void collect_device_info(struct pw_manager_object *device, struct pw_manager_object *card,
|
||||||
struct device_info *dev_info, bool monitor, struct defs *defs)
|
struct device_info *dev_info, bool monitor, struct defs *defs)
|
||||||
{
|
{
|
||||||
struct pw_manager_param *p;
|
struct pw_manager_param *p;
|
||||||
|
|
@ -287,6 +290,57 @@ void collect_device_info(struct pw_manager_object *device, struct pw_manager_obj
|
||||||
dev_info->volume_info.volume.channels = dev_info->map.channels;
|
dev_info->volume_info.volume.channels = dev_info->map.channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_device_info(struct pw_manager *manager, struct pw_manager_object *o,
|
||||||
|
enum pw_direction direction, bool monitor, struct defs *defs)
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
const char *key = monitor ? "device.info.monitor" : "device.info";
|
||||||
|
struct pw_manager_object *card = NULL;
|
||||||
|
struct pw_node_info *info = o->info;
|
||||||
|
struct device_info *dev_info, di;
|
||||||
|
|
||||||
|
if (info == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
di = DEVICE_INFO_INIT(direction);
|
||||||
|
if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_ID)) != NULL)
|
||||||
|
di.card_id = (uint32_t)atoi(str);
|
||||||
|
if ((str = spa_dict_lookup(info->props, "card.profile.device")) != NULL)
|
||||||
|
di.device = (uint32_t)atoi(str);
|
||||||
|
if (di.card_id != SPA_ID_INVALID) {
|
||||||
|
struct selector sel = { .id = di.card_id, .type = pw_manager_object_is_card, };
|
||||||
|
card = select_object(manager, &sel);
|
||||||
|
}
|
||||||
|
collect_device_info(o, card, &di, monitor, defs);
|
||||||
|
|
||||||
|
dev_info = pw_manager_object_get_data(o, key);
|
||||||
|
if (dev_info) {
|
||||||
|
if (memcmp(dev_info, &di, sizeof(di)) != 0) {
|
||||||
|
if (monitor || direction == PW_DIRECTION_INPUT)
|
||||||
|
o->change_mask |= PW_MANAGER_OBJECT_FLAG_SOURCE;
|
||||||
|
else
|
||||||
|
o->change_mask |= PW_MANAGER_OBJECT_FLAG_SINK;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
o->change_mask = ~0;
|
||||||
|
dev_info = pw_manager_object_add_data(o, key, sizeof(*dev_info));
|
||||||
|
}
|
||||||
|
if (dev_info != NULL)
|
||||||
|
*dev_info = di;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_device_info(struct pw_manager_object *o, struct device_info *info,
|
||||||
|
enum pw_direction direction, bool monitor)
|
||||||
|
{
|
||||||
|
const char *key = monitor ? "device.info.monitor" : "device.info";
|
||||||
|
struct device_info *di;
|
||||||
|
di = pw_manager_object_get_data(o, key);
|
||||||
|
if (di != NULL)
|
||||||
|
*info = *di;
|
||||||
|
else
|
||||||
|
*info = DEVICE_INFO_INIT(direction);
|
||||||
|
}
|
||||||
|
|
||||||
static bool array_contains(uint32_t *vals, uint32_t n_vals, uint32_t val)
|
static bool array_contains(uint32_t *vals, uint32_t n_vals, uint32_t val)
|
||||||
{
|
{
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
|
|
@ -527,3 +581,21 @@ uint32_t collect_transport_codec_info(struct pw_manager_object *card,
|
||||||
|
|
||||||
return n_codecs;
|
return n_codecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void update_object_info(struct pw_manager *manager, struct pw_manager_object *o,
|
||||||
|
struct defs *defs)
|
||||||
|
{
|
||||||
|
if (pw_manager_object_is_sink(o)) {
|
||||||
|
update_device_info(manager, o, PW_DIRECTION_OUTPUT, false, defs);
|
||||||
|
update_device_info(manager, o, PW_DIRECTION_OUTPUT, true, defs);
|
||||||
|
}
|
||||||
|
if (pw_manager_object_is_source(o)) {
|
||||||
|
update_device_info(manager, o, PW_DIRECTION_INPUT, false, defs);
|
||||||
|
}
|
||||||
|
if (pw_manager_object_is_source_output(o)) {
|
||||||
|
update_device_info(manager, o, PW_DIRECTION_INPUT, false, defs);
|
||||||
|
}
|
||||||
|
if (pw_manager_object_is_sink_input(o)) {
|
||||||
|
update_device_info(manager, o, PW_DIRECTION_OUTPUT, false, defs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ struct selector {
|
||||||
struct pw_manager_object *select_object(struct pw_manager *m, struct selector *s);
|
struct pw_manager_object *select_object(struct pw_manager *m, struct selector *s);
|
||||||
uint32_t id_to_index(struct pw_manager *m, uint32_t id);
|
uint32_t id_to_index(struct pw_manager *m, uint32_t id);
|
||||||
void select_best(struct selector *s, struct pw_manager_object *o);
|
void select_best(struct selector *s, struct pw_manager_object *o);
|
||||||
|
void update_object_info(struct pw_manager *manager, struct pw_manager_object *o,
|
||||||
|
struct defs *defs);
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
|
|
||||||
|
|
@ -47,9 +49,11 @@ struct device_info {
|
||||||
unsigned int have_volume:1;
|
unsigned int have_volume:1;
|
||||||
unsigned int have_iec958codecs:1;
|
unsigned int have_iec958codecs:1;
|
||||||
|
|
||||||
|
uint32_t card_id;
|
||||||
uint32_t device;
|
uint32_t device;
|
||||||
uint32_t active_port;
|
uint32_t active_port;
|
||||||
const char *active_port_name;
|
const char *active_port_name;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEVICE_INFO_INIT(_dir) \
|
#define DEVICE_INFO_INIT(_dir) \
|
||||||
|
|
@ -58,12 +62,13 @@ struct device_info {
|
||||||
.ss = SAMPLE_SPEC_INIT, \
|
.ss = SAMPLE_SPEC_INIT, \
|
||||||
.map = CHANNEL_MAP_INIT, \
|
.map = CHANNEL_MAP_INIT, \
|
||||||
.volume_info = VOLUME_INFO_INIT, \
|
.volume_info = VOLUME_INFO_INIT, \
|
||||||
|
.card_id = SPA_ID_INVALID, \
|
||||||
.device = SPA_ID_INVALID, \
|
.device = SPA_ID_INVALID, \
|
||||||
.active_port = SPA_ID_INVALID, \
|
.active_port = SPA_ID_INVALID, \
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_device_info(struct pw_manager_object *device, struct pw_manager_object *card,
|
void get_device_info(struct pw_manager_object *device, struct device_info *info,
|
||||||
struct device_info *dev_info, bool monitor, struct defs *defs);
|
enum pw_direction direction, bool monitor);
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -220,17 +220,15 @@ static int set_node_codecs(struct pw_manager_object *o, uint32_t n_codecs, uint3
|
||||||
static int do_extension_device_restore_save_formats(struct client *client,
|
static int do_extension_device_restore_save_formats(struct client *client,
|
||||||
uint32_t command, uint32_t tag, struct message *m)
|
uint32_t command, uint32_t tag, struct message *m)
|
||||||
{
|
{
|
||||||
struct impl *impl = client->impl;
|
|
||||||
struct pw_manager *manager = client->manager;
|
struct pw_manager *manager = client->manager;
|
||||||
struct selector sel;
|
struct selector sel;
|
||||||
struct pw_manager_object *o, *card = NULL;
|
struct pw_manager_object *o, *card = NULL;
|
||||||
struct pw_node_info *info;
|
struct pw_node_info *info;
|
||||||
int res;
|
int res;
|
||||||
uint32_t type, sink_index, card_id = SPA_ID_INVALID;
|
uint32_t type, sink_index;
|
||||||
uint8_t i, n_formats;
|
uint8_t i, n_formats;
|
||||||
uint32_t n_codecs = 0, codec, iec958codecs[32];
|
uint32_t n_codecs = 0, codec, iec958codecs[32];
|
||||||
struct device_info dev_info;
|
struct device_info dev_info;
|
||||||
const char *str;
|
|
||||||
|
|
||||||
if ((res = message_get(m,
|
if ((res = message_get(m,
|
||||||
TAG_U32, &type,
|
TAG_U32, &type,
|
||||||
|
|
@ -269,18 +267,12 @@ static int do_extension_device_restore_save_formats(struct client *client,
|
||||||
if (o == NULL || (info = o->info) == NULL || info->props == NULL)
|
if (o == NULL || (info = o->info) == NULL || info->props == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
dev_info = DEVICE_INFO_INIT(SPA_DIRECTION_INPUT);
|
get_device_info(o, &dev_info, SPA_DIRECTION_INPUT, false);
|
||||||
|
|
||||||
if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_ID)) != NULL)
|
if (dev_info.card_id != SPA_ID_INVALID) {
|
||||||
card_id = (uint32_t)atoi(str);
|
struct selector sel = { .id = dev_info.card_id, .type = pw_manager_object_is_card, };
|
||||||
if ((str = spa_dict_lookup(info->props, "card.profile.device")) != NULL)
|
|
||||||
dev_info.device = (uint32_t)atoi(str);
|
|
||||||
if (card_id != SPA_ID_INVALID) {
|
|
||||||
struct selector sel = { .id = card_id, .type = pw_manager_object_is_card, };
|
|
||||||
card = select_object(manager, &sel);
|
card = select_object(manager, &sel);
|
||||||
}
|
}
|
||||||
collect_device_info(o, card, &dev_info, false, &impl->defs);
|
|
||||||
|
|
||||||
if (card != NULL && dev_info.active_port != SPA_ID_INVALID) {
|
if (card != NULL && dev_info.active_port != SPA_ID_INVALID) {
|
||||||
res = set_card_codecs(card, dev_info.active_port,
|
res = set_card_codecs(card, dev_info.active_port,
|
||||||
dev_info.device, n_codecs, iec958codecs);
|
dev_info.device, n_codecs, iec958codecs);
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ struct pw_manager_object {
|
||||||
struct spa_param_info *params;
|
struct spa_param_info *params;
|
||||||
uint32_t n_params;
|
uint32_t n_params;
|
||||||
|
|
||||||
|
#define PW_MANAGER_OBJECT_FLAG_SOURCE (1<<0)
|
||||||
|
#define PW_MANAGER_OBJECT_FLAG_SINK (1<<1)
|
||||||
uint64_t change_mask; /* object specific params change mask */
|
uint64_t change_mask; /* object specific params change mask */
|
||||||
struct spa_list param_list;
|
struct spa_list param_list;
|
||||||
unsigned int creating:1;
|
unsigned int creating:1;
|
||||||
|
|
|
||||||
|
|
@ -180,17 +180,14 @@ static char* channel_map_snprint(char *s, size_t l, const struct channel_map *ma
|
||||||
static void fill_service_data(struct module_zeroconf_publish_data *d, struct service *s,
|
static void fill_service_data(struct module_zeroconf_publish_data *d, struct service *s,
|
||||||
struct pw_manager_object *o)
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct impl *impl = d->module->impl;
|
|
||||||
bool is_sink = pw_manager_object_is_sink(o);
|
bool is_sink = pw_manager_object_is_sink(o);
|
||||||
bool is_source = pw_manager_object_is_source(o);
|
bool is_source = pw_manager_object_is_source(o);
|
||||||
struct pw_node_info *info = o->info;
|
struct pw_node_info *info = o->info;
|
||||||
const char *name, *desc, *str;
|
const char *name, *desc;
|
||||||
uint32_t card_id = SPA_ID_INVALID;
|
|
||||||
struct pw_manager *manager = d->manager;
|
struct pw_manager *manager = d->manager;
|
||||||
struct pw_manager_object *card = NULL;
|
struct pw_manager_object *card = NULL;
|
||||||
struct card_info card_info = CARD_INFO_INIT;
|
struct card_info card_info = CARD_INFO_INIT;
|
||||||
struct device_info dev_info = is_sink ?
|
struct device_info dev_info;
|
||||||
DEVICE_INFO_INIT(PW_DIRECTION_OUTPUT) : DEVICE_INFO_INIT(PW_DIRECTION_INPUT);
|
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
|
|
||||||
if (info == NULL || info->props == NULL)
|
if (info == NULL || info->props == NULL)
|
||||||
|
|
@ -202,19 +199,15 @@ static void fill_service_data(struct module_zeroconf_publish_data *d, struct ser
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
name = "unknown";
|
name = "unknown";
|
||||||
|
|
||||||
if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_ID)) != NULL)
|
get_device_info(o, &dev_info, is_sink ? PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT, false);
|
||||||
card_id = (uint32_t)atoi(str);
|
|
||||||
if ((str = spa_dict_lookup(info->props, "card.profile.device")) != NULL)
|
if (dev_info.card_id != SPA_ID_INVALID) {
|
||||||
dev_info.device = (uint32_t)atoi(str);
|
struct selector sel = { .id = dev_info.card_id, .type = pw_manager_object_is_card, };
|
||||||
if (card_id != SPA_ID_INVALID) {
|
|
||||||
struct selector sel = { .id = card_id, .type = pw_manager_object_is_card, };
|
|
||||||
card = select_object(manager, &sel);
|
card = select_object(manager, &sel);
|
||||||
}
|
}
|
||||||
if (card)
|
if (card)
|
||||||
collect_card_info(card, &card_info);
|
collect_card_info(card, &card_info);
|
||||||
|
|
||||||
collect_device_info(o, card, &dev_info, false, &impl->defs);
|
|
||||||
|
|
||||||
if (!pw_manager_object_is_virtual(o)) {
|
if (!pw_manager_object_is_virtual(o)) {
|
||||||
if (is_sink)
|
if (is_sink)
|
||||||
flags |= SINK_HARDWARE;
|
flags |= SINK_HARDWARE;
|
||||||
|
|
|
||||||
|
|
@ -208,13 +208,15 @@ static int send_object_event(struct client *client, struct pw_manager_object *o,
|
||||||
{
|
{
|
||||||
uint32_t event = 0, mask = 0, res_index = o->index;
|
uint32_t event = 0, mask = 0, res_index = o->index;
|
||||||
|
|
||||||
if (pw_manager_object_is_sink(o)) {
|
pw_log_debug("index:%d id:%d %08lx type:%u", o->index, o->id, o->change_mask, type);
|
||||||
|
|
||||||
|
if (pw_manager_object_is_sink(o) && o->change_mask & PW_MANAGER_OBJECT_FLAG_SINK) {
|
||||||
client_queue_subscribe_event(client,
|
client_queue_subscribe_event(client,
|
||||||
SUBSCRIPTION_MASK_SINK,
|
SUBSCRIPTION_MASK_SINK,
|
||||||
SUBSCRIPTION_EVENT_SINK | type,
|
SUBSCRIPTION_EVENT_SINK | type,
|
||||||
res_index);
|
res_index);
|
||||||
}
|
}
|
||||||
if (pw_manager_object_is_source_or_monitor(o)) {
|
if (pw_manager_object_is_source_or_monitor(o) && o->change_mask & PW_MANAGER_OBJECT_FLAG_SOURCE) {
|
||||||
mask = SUBSCRIPTION_MASK_SOURCE;
|
mask = SUBSCRIPTION_MASK_SOURCE;
|
||||||
event = SUBSCRIPTION_EVENT_SOURCE;
|
event = SUBSCRIPTION_EVENT_SOURCE;
|
||||||
}
|
}
|
||||||
|
|
@ -808,6 +810,7 @@ static void manager_added(void *data, struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct client *client = data;
|
struct client *client = data;
|
||||||
struct pw_manager *manager = client->manager;
|
struct pw_manager *manager = client->manager;
|
||||||
|
struct impl *impl = client->impl;
|
||||||
const char *str;
|
const char *str;
|
||||||
|
|
||||||
register_object_message_handlers(o);
|
register_object_message_handlers(o);
|
||||||
|
|
@ -869,8 +872,12 @@ static void manager_added(void *data, struct pw_manager_object *o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_object_info(manager, o, &impl->defs);
|
||||||
|
|
||||||
send_object_event(client, o, SUBSCRIPTION_EVENT_NEW);
|
send_object_event(client, o, SUBSCRIPTION_EVENT_NEW);
|
||||||
|
|
||||||
|
o->change_mask = 0;
|
||||||
|
|
||||||
/* Adding sinks etc. may also change defaults */
|
/* Adding sinks etc. may also change defaults */
|
||||||
send_default_change_subscribe_event(client, pw_manager_object_is_sink(o), pw_manager_object_is_source_or_monitor(o));
|
send_default_change_subscribe_event(client, pw_manager_object_is_sink(o), pw_manager_object_is_source_or_monitor(o));
|
||||||
}
|
}
|
||||||
|
|
@ -878,9 +885,15 @@ static void manager_added(void *data, struct pw_manager_object *o)
|
||||||
static void manager_updated(void *data, struct pw_manager_object *o)
|
static void manager_updated(void *data, struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct client *client = data;
|
struct client *client = data;
|
||||||
|
struct pw_manager *manager = client->manager;
|
||||||
|
struct impl *impl = client->impl;
|
||||||
|
|
||||||
|
update_object_info(manager, o, &impl->defs);
|
||||||
|
|
||||||
send_object_event(client, o, SUBSCRIPTION_EVENT_CHANGE);
|
send_object_event(client, o, SUBSCRIPTION_EVENT_CHANGE);
|
||||||
|
|
||||||
|
o->change_mask = 0;
|
||||||
|
|
||||||
set_temporary_move_target(client, o, SPA_ID_INVALID);
|
set_temporary_move_target(client, o, SPA_ID_INVALID);
|
||||||
|
|
||||||
send_latency_offset_subscribe_event(client, o);
|
send_latency_offset_subscribe_event(client, o);
|
||||||
|
|
@ -1646,8 +1659,8 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
|
||||||
spa_zero(fix_ss);
|
spa_zero(fix_ss);
|
||||||
spa_zero(fix_map);
|
spa_zero(fix_map);
|
||||||
if ((fix_format || fix_rate || fix_channels) && o != NULL) {
|
if ((fix_format || fix_rate || fix_channels) && o != NULL) {
|
||||||
struct device_info dev_info = DEVICE_INFO_INIT(PW_DIRECTION_OUTPUT);
|
struct device_info dev_info;
|
||||||
collect_device_info(o, NULL, &dev_info, is_monitor, &impl->defs);
|
get_device_info(o, &dev_info, PW_DIRECTION_OUTPUT, is_monitor);
|
||||||
fix_ss.format = fix_format ? dev_info.ss.format : 0;
|
fix_ss.format = fix_format ? dev_info.ss.format : 0;
|
||||||
fix_ss.rate = fix_rate ? dev_info.ss.rate : 0;
|
fix_ss.rate = fix_rate ? dev_info.ss.rate : 0;
|
||||||
fix_ss.channels = fix_channels ? dev_info.ss.channels : 0;
|
fix_ss.channels = fix_channels ? dev_info.ss.channels : 0;
|
||||||
|
|
@ -1936,8 +1949,8 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
|
||||||
spa_zero(fix_ss);
|
spa_zero(fix_ss);
|
||||||
spa_zero(fix_map);
|
spa_zero(fix_map);
|
||||||
if ((fix_format || fix_rate || fix_channels) && o != NULL) {
|
if ((fix_format || fix_rate || fix_channels) && o != NULL) {
|
||||||
struct device_info dev_info = DEVICE_INFO_INIT(PW_DIRECTION_INPUT);
|
struct device_info dev_info;
|
||||||
collect_device_info(o, NULL, &dev_info, is_monitor, &impl->defs);
|
get_device_info(o, &dev_info, PW_DIRECTION_INPUT, is_monitor);
|
||||||
fix_ss.format = fix_format ? dev_info.ss.format : 0;
|
fix_ss.format = fix_format ? dev_info.ss.format : 0;
|
||||||
fix_ss.rate = fix_rate ? dev_info.ss.rate : 0;
|
fix_ss.rate = fix_rate ? dev_info.ss.rate : 0;
|
||||||
fix_ss.channels = fix_channels ? dev_info.ss.channels : 0;
|
fix_ss.channels = fix_channels ? dev_info.ss.channels : 0;
|
||||||
|
|
@ -2890,11 +2903,10 @@ done:
|
||||||
|
|
||||||
static int do_set_volume(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
static int do_set_volume(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_manager *manager = client->manager;
|
||||||
struct pw_node_info *info;
|
struct pw_node_info *info;
|
||||||
uint32_t index, card_id = SPA_ID_INVALID;
|
uint32_t index;
|
||||||
const char *name, *str;
|
const char *name;
|
||||||
struct volume volume;
|
struct volume volume;
|
||||||
struct pw_manager_object *o, *card = NULL;
|
struct pw_manager_object *o, *card = NULL;
|
||||||
int res;
|
int res;
|
||||||
|
|
@ -2930,22 +2942,16 @@ static int do_set_volume(struct client *client, uint32_t command, uint32_t tag,
|
||||||
if (o == NULL || (info = o->info) == NULL || info->props == NULL)
|
if (o == NULL || (info = o->info) == NULL || info->props == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
dev_info = DEVICE_INFO_INIT(direction);
|
get_device_info(o, &dev_info, direction, is_monitor);
|
||||||
|
|
||||||
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)
|
|
||||||
dev_info.device = (uint32_t)atoi(str);
|
|
||||||
if (card_id != SPA_ID_INVALID) {
|
|
||||||
struct selector sel = { .id = card_id, .type = pw_manager_object_is_card, };
|
|
||||||
card = select_object(manager, &sel);
|
|
||||||
}
|
|
||||||
collect_device_info(o, card, &dev_info, is_monitor, &impl->defs);
|
|
||||||
|
|
||||||
if (dev_info.have_volume &&
|
if (dev_info.have_volume &&
|
||||||
volume_compare(&dev_info.volume_info.volume, &volume) == 0)
|
volume_compare(&dev_info.volume_info.volume, &volume) == 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
if (dev_info.card_id != SPA_ID_INVALID) {
|
||||||
|
struct selector sel = { .id = dev_info.card_id, .type = pw_manager_object_is_card, };
|
||||||
|
card = select_object(manager, &sel);
|
||||||
|
}
|
||||||
if (card != NULL && !is_monitor && dev_info.active_port != SPA_ID_INVALID)
|
if (card != NULL && !is_monitor && dev_info.active_port != SPA_ID_INVALID)
|
||||||
res = set_card_volume_mute_delay(card, dev_info.active_port,
|
res = set_card_volume_mute_delay(card, dev_info.active_port,
|
||||||
dev_info.device, &volume, NULL, NULL);
|
dev_info.device, &volume, NULL, NULL);
|
||||||
|
|
@ -2961,11 +2967,10 @@ done:
|
||||||
|
|
||||||
static int do_set_mute(struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
static int do_set_mute(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_manager *manager = client->manager;
|
||||||
struct pw_node_info *info;
|
struct pw_node_info *info;
|
||||||
uint32_t index, card_id = SPA_ID_INVALID;
|
uint32_t index;
|
||||||
const char *name, *str;
|
const char *name;
|
||||||
bool mute;
|
bool mute;
|
||||||
struct pw_manager_object *o, *card = NULL;
|
struct pw_manager_object *o, *card = NULL;
|
||||||
int res;
|
int res;
|
||||||
|
|
@ -2996,22 +3001,17 @@ static int do_set_mute(struct client *client, uint32_t command, uint32_t tag, st
|
||||||
if (o == NULL || (info = o->info) == NULL || info->props == NULL)
|
if (o == NULL || (info = o->info) == NULL || info->props == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
dev_info = DEVICE_INFO_INIT(direction);
|
get_device_info(o, &dev_info, direction, is_monitor);
|
||||||
|
|
||||||
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)
|
|
||||||
dev_info.device = (uint32_t)atoi(str);
|
|
||||||
if (card_id != SPA_ID_INVALID) {
|
|
||||||
struct selector sel = { .id = card_id, .type = pw_manager_object_is_card, };
|
|
||||||
card = select_object(manager, &sel);
|
|
||||||
}
|
|
||||||
collect_device_info(o, card, &dev_info, is_monitor, &impl->defs);
|
|
||||||
|
|
||||||
if (dev_info.have_volume &&
|
if (dev_info.have_volume &&
|
||||||
dev_info.volume_info.mute == mute)
|
dev_info.volume_info.mute == mute)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
if (dev_info.card_id != SPA_ID_INVALID) {
|
||||||
|
struct selector sel = { .id = dev_info.card_id, .type = pw_manager_object_is_card, };
|
||||||
|
card = select_object(manager, &sel);
|
||||||
|
}
|
||||||
|
|
||||||
if (card != NULL && !is_monitor && dev_info.active_port != SPA_ID_INVALID)
|
if (card != NULL && !is_monitor && dev_info.active_port != SPA_ID_INVALID)
|
||||||
res = set_card_volume_mute_delay(card, dev_info.active_port,
|
res = set_card_volume_mute_delay(card, dev_info.active_port,
|
||||||
dev_info.device, NULL, &mute, NULL);
|
dev_info.device, NULL, &mute, NULL);
|
||||||
|
|
@ -3666,24 +3666,22 @@ static int fill_sink_info_proplist(struct message *m, const struct spa_dict *sin
|
||||||
static bool validate_device_info(struct device_info *dev_info)
|
static bool validate_device_info(struct device_info *dev_info)
|
||||||
{
|
{
|
||||||
return sample_spec_valid(&dev_info->ss) &&
|
return sample_spec_valid(&dev_info->ss) &&
|
||||||
channel_map_valid(&dev_info->map) &&
|
channel_map_valid(&dev_info->map) &&
|
||||||
volume_valid(&dev_info->volume_info.volume);
|
volume_valid(&dev_info->volume_info.volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fill_sink_info(struct client *client, struct message *m,
|
static int fill_sink_info(struct client *client, struct message *m,
|
||||||
struct pw_manager_object *o)
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct impl *impl = client->impl;
|
|
||||||
struct pw_node_info *info = o->info;
|
struct pw_node_info *info = o->info;
|
||||||
struct pw_manager *manager = client->manager;
|
struct pw_manager *manager = client->manager;
|
||||||
const char *name, *desc, *str;
|
const char *name, *desc, *str;
|
||||||
char *monitor_name = NULL;
|
char *monitor_name = NULL;
|
||||||
uint32_t module_id = SPA_ID_INVALID;
|
uint32_t module_id = SPA_ID_INVALID;
|
||||||
uint32_t card_id = SPA_ID_INVALID;
|
|
||||||
struct pw_manager_object *card = NULL;
|
struct pw_manager_object *card = NULL;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
struct card_info card_info = CARD_INFO_INIT;
|
struct card_info card_info = CARD_INFO_INIT;
|
||||||
struct device_info dev_info = DEVICE_INFO_INIT(PW_DIRECTION_OUTPUT);
|
struct device_info dev_info;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
if (!pw_manager_object_is_sink(o) || info == NULL || info->props == NULL)
|
if (!pw_manager_object_is_sink(o) || info == NULL || info->props == NULL)
|
||||||
|
|
@ -3707,19 +3705,8 @@ static int fill_sink_info(struct client *client, struct message *m,
|
||||||
if (module_id == SPA_ID_INVALID &&
|
if (module_id == SPA_ID_INVALID &&
|
||||||
(str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL)
|
(str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL)
|
||||||
module_id = (uint32_t)atoi(str);
|
module_id = (uint32_t)atoi(str);
|
||||||
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)
|
|
||||||
dev_info.device = (uint32_t)atoi(str);
|
|
||||||
if (card_id != SPA_ID_INVALID) {
|
|
||||||
struct selector sel = { .id = card_id, .type = pw_manager_object_is_card, };
|
|
||||||
card = select_object(manager, &sel);
|
|
||||||
}
|
|
||||||
if (card)
|
|
||||||
collect_card_info(card, &card_info);
|
|
||||||
|
|
||||||
collect_device_info(o, card, &dev_info, false, &impl->defs);
|
|
||||||
|
|
||||||
|
get_device_info(o, &dev_info, PW_DIRECTION_OUTPUT, false);
|
||||||
if (!validate_device_info(&dev_info)) {
|
if (!validate_device_info(&dev_info)) {
|
||||||
pw_log_warn("%d: sink not ready: sample:%d map:%d volume:%d",
|
pw_log_warn("%d: sink not ready: sample:%d map:%d volume:%d",
|
||||||
o->id, sample_spec_valid(&dev_info.ss),
|
o->id, sample_spec_valid(&dev_info.ss),
|
||||||
|
|
@ -3728,6 +3715,14 @@ static int fill_sink_info(struct client *client, struct message *m,
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (dev_info.card_id != SPA_ID_INVALID) {
|
||||||
|
struct selector sel = { .id = dev_info.card_id, .type = pw_manager_object_is_card, };
|
||||||
|
card = select_object(manager, &sel);
|
||||||
|
}
|
||||||
|
if (card)
|
||||||
|
collect_card_info(card, &card_info);
|
||||||
|
|
||||||
flags = SINK_LATENCY | SINK_DYNAMIC_LATENCY | SINK_DECIBEL_VOLUME;
|
flags = SINK_LATENCY | SINK_DYNAMIC_LATENCY | SINK_DECIBEL_VOLUME;
|
||||||
if (!pw_manager_object_is_virtual(o))
|
if (!pw_manager_object_is_virtual(o))
|
||||||
flags |= SINK_HARDWARE;
|
flags |= SINK_HARDWARE;
|
||||||
|
|
@ -3880,7 +3875,6 @@ static int fill_source_info_proplist(struct message *m, const struct spa_dict *s
|
||||||
static int fill_source_info(struct client *client, struct message *m,
|
static int fill_source_info(struct client *client, struct message *m,
|
||||||
struct pw_manager_object *o)
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct impl *impl = client->impl;
|
|
||||||
struct pw_node_info *info = o->info;
|
struct pw_node_info *info = o->info;
|
||||||
struct pw_manager *manager = client->manager;
|
struct pw_manager *manager = client->manager;
|
||||||
bool is_monitor;
|
bool is_monitor;
|
||||||
|
|
@ -3888,11 +3882,10 @@ static int fill_source_info(struct client *client, struct message *m,
|
||||||
char *monitor_name = NULL;
|
char *monitor_name = NULL;
|
||||||
char *monitor_desc = NULL;
|
char *monitor_desc = NULL;
|
||||||
uint32_t module_id = SPA_ID_INVALID;
|
uint32_t module_id = SPA_ID_INVALID;
|
||||||
uint32_t card_id = SPA_ID_INVALID;
|
|
||||||
struct pw_manager_object *card = NULL;
|
struct pw_manager_object *card = NULL;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
struct card_info card_info = CARD_INFO_INIT;
|
struct card_info card_info = CARD_INFO_INIT;
|
||||||
struct device_info dev_info = DEVICE_INFO_INIT(PW_DIRECTION_INPUT);
|
struct device_info dev_info;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
is_monitor = pw_manager_object_is_monitor(o);
|
is_monitor = pw_manager_object_is_monitor(o);
|
||||||
|
|
@ -3918,20 +3911,8 @@ static int fill_source_info(struct client *client, struct message *m,
|
||||||
if (module_id == SPA_ID_INVALID &&
|
if (module_id == SPA_ID_INVALID &&
|
||||||
(str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL)
|
(str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL)
|
||||||
module_id = (uint32_t)atoi(str);
|
module_id = (uint32_t)atoi(str);
|
||||||
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)
|
|
||||||
dev_info.device = (uint32_t)atoi(str);
|
|
||||||
|
|
||||||
if (card_id != SPA_ID_INVALID) {
|
|
||||||
struct selector sel = { .id = card_id, .type = pw_manager_object_is_card, };
|
|
||||||
card = select_object(manager, &sel);
|
|
||||||
}
|
|
||||||
if (card)
|
|
||||||
collect_card_info(card, &card_info);
|
|
||||||
|
|
||||||
collect_device_info(o, card, &dev_info, is_monitor, &impl->defs);
|
|
||||||
|
|
||||||
|
get_device_info(o, &dev_info, PW_DIRECTION_INPUT, is_monitor);
|
||||||
if (!validate_device_info(&dev_info)) {
|
if (!validate_device_info(&dev_info)) {
|
||||||
pw_log_warn("%d: source not ready: sample:%d map:%d volume:%d",
|
pw_log_warn("%d: source not ready: sample:%d map:%d volume:%d",
|
||||||
o->id, sample_spec_valid(&dev_info.ss),
|
o->id, sample_spec_valid(&dev_info.ss),
|
||||||
|
|
@ -3941,6 +3922,14 @@ static int fill_source_info(struct client *client, struct message *m,
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = SOURCE_LATENCY | SOURCE_DYNAMIC_LATENCY | SOURCE_DECIBEL_VOLUME;
|
flags = SOURCE_LATENCY | SOURCE_DYNAMIC_LATENCY | SOURCE_DECIBEL_VOLUME;
|
||||||
|
|
||||||
|
if (dev_info.card_id != SPA_ID_INVALID) {
|
||||||
|
struct selector sel = { .id = dev_info.card_id, .type = pw_manager_object_is_card, };
|
||||||
|
card = select_object(manager, &sel);
|
||||||
|
}
|
||||||
|
if (card)
|
||||||
|
collect_card_info(card, &card_info);
|
||||||
|
|
||||||
if (!pw_manager_object_is_virtual(o))
|
if (!pw_manager_object_is_virtual(o))
|
||||||
flags |= SOURCE_HARDWARE;
|
flags |= SOURCE_HARDWARE;
|
||||||
if (pw_manager_object_is_network(o))
|
if (pw_manager_object_is_network(o))
|
||||||
|
|
@ -4050,13 +4039,12 @@ static const char *get_media_name(struct pw_node_info *info)
|
||||||
static int fill_sink_input_info(struct client *client, struct message *m,
|
static int fill_sink_input_info(struct client *client, struct message *m,
|
||||||
struct pw_manager_object *o)
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct impl *impl = client->impl;
|
|
||||||
struct pw_node_info *info = o->info;
|
struct pw_node_info *info = o->info;
|
||||||
struct pw_manager *manager = client->manager;
|
struct pw_manager *manager = client->manager;
|
||||||
const char *str;
|
const char *str;
|
||||||
uint32_t module_id = SPA_ID_INVALID, client_id = SPA_ID_INVALID;
|
uint32_t module_id = SPA_ID_INVALID, client_id = SPA_ID_INVALID;
|
||||||
uint32_t peer_index;
|
uint32_t peer_index;
|
||||||
struct device_info dev_info = DEVICE_INFO_INIT(PW_DIRECTION_OUTPUT);
|
struct device_info dev_info;
|
||||||
|
|
||||||
if (!pw_manager_object_is_sink_input(o) || info == NULL || info->props == NULL)
|
if (!pw_manager_object_is_sink_input(o) || info == NULL || info->props == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
@ -4071,8 +4059,7 @@ static int fill_sink_input_info(struct client *client, struct message *m,
|
||||||
(str = spa_dict_lookup(info->props, PW_KEY_CLIENT_ID)) != NULL)
|
(str = spa_dict_lookup(info->props, PW_KEY_CLIENT_ID)) != NULL)
|
||||||
client_id = (uint32_t)atoi(str);
|
client_id = (uint32_t)atoi(str);
|
||||||
|
|
||||||
collect_device_info(o, NULL, &dev_info, false, &impl->defs);
|
get_device_info(o, &dev_info, PW_DIRECTION_OUTPUT, false);
|
||||||
|
|
||||||
if (!validate_device_info(&dev_info))
|
if (!validate_device_info(&dev_info))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
|
|
@ -4131,13 +4118,12 @@ static int fill_sink_input_info(struct client *client, struct message *m,
|
||||||
static int fill_source_output_info(struct client *client, struct message *m,
|
static int fill_source_output_info(struct client *client, struct message *m,
|
||||||
struct pw_manager_object *o)
|
struct pw_manager_object *o)
|
||||||
{
|
{
|
||||||
struct impl *impl = client->impl;
|
|
||||||
struct pw_node_info *info = o->info;
|
struct pw_node_info *info = o->info;
|
||||||
struct pw_manager *manager = client->manager;
|
struct pw_manager *manager = client->manager;
|
||||||
const char *str;
|
const char *str;
|
||||||
uint32_t module_id = SPA_ID_INVALID, client_id = SPA_ID_INVALID;
|
uint32_t module_id = SPA_ID_INVALID, client_id = SPA_ID_INVALID;
|
||||||
uint32_t peer_index;
|
uint32_t peer_index;
|
||||||
struct device_info dev_info = DEVICE_INFO_INIT(PW_DIRECTION_INPUT);
|
struct device_info dev_info;
|
||||||
|
|
||||||
if (!pw_manager_object_is_source_output(o) || info == NULL || info->props == NULL)
|
if (!pw_manager_object_is_source_output(o) || info == NULL || info->props == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
@ -4152,8 +4138,7 @@ static int fill_source_output_info(struct client *client, struct message *m,
|
||||||
(str = spa_dict_lookup(info->props, PW_KEY_CLIENT_ID)) != NULL)
|
(str = spa_dict_lookup(info->props, PW_KEY_CLIENT_ID)) != NULL)
|
||||||
client_id = (uint32_t)atoi(str);
|
client_id = (uint32_t)atoi(str);
|
||||||
|
|
||||||
collect_device_info(o, NULL, &dev_info, false, &impl->defs);
|
get_device_info(o, &dev_info, PW_DIRECTION_INPUT, false);
|
||||||
|
|
||||||
if (!validate_device_info(&dev_info))
|
if (!validate_device_info(&dev_info))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue