mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
media-session: rework device reservation
Monitor the device reservation objects and mark the device available. Don't select nodes from devices that are not available. Acquire the device reservation when a device starts. Release the device reservation when we suspend the device again.
This commit is contained in:
parent
11086f23ea
commit
d3634aca7e
6 changed files with 188 additions and 59 deletions
|
|
@ -67,6 +67,7 @@ struct node {
|
|||
struct spa_node *node;
|
||||
|
||||
struct sm_node *snode;
|
||||
unsigned int acquired:1;
|
||||
};
|
||||
|
||||
struct device {
|
||||
|
|
@ -81,6 +82,7 @@ struct device {
|
|||
int priority;
|
||||
|
||||
int profile;
|
||||
int pending_profile;
|
||||
|
||||
struct pw_properties *props;
|
||||
|
||||
|
|
@ -91,6 +93,8 @@ struct device {
|
|||
struct sm_device *sdevice;
|
||||
struct spa_hook listener;
|
||||
|
||||
uint32_t n_acquired;
|
||||
|
||||
unsigned int first:1;
|
||||
unsigned int appeared:1;
|
||||
struct spa_list node_list;
|
||||
|
|
@ -138,6 +142,46 @@ static void alsa_update_node(struct device *device, struct node *node,
|
|||
pw_properties_update(node->props, info->props);
|
||||
}
|
||||
|
||||
static int node_acquire(void *data)
|
||||
{
|
||||
struct node *node = data;
|
||||
struct device *device = node->device;
|
||||
|
||||
pw_log_debug("acquire %u", node->id);
|
||||
|
||||
if (node->acquired)
|
||||
return 0;
|
||||
|
||||
node->acquired = true;
|
||||
|
||||
if (device && device->n_acquired++ == 0)
|
||||
rd_device_acquire(device->reserve);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int node_release(void *data)
|
||||
{
|
||||
struct node *node = data;
|
||||
struct device *device = node->device;
|
||||
|
||||
pw_log_debug("release %u", node->id);
|
||||
|
||||
if (!node->acquired)
|
||||
return 0;
|
||||
|
||||
node->acquired = false;
|
||||
|
||||
if (device && --device->n_acquired == 0)
|
||||
rd_device_release(device->reserve);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sm_object_methods node_methods = {
|
||||
SM_VERSION_OBJECT_METHODS,
|
||||
.acquire = node_acquire,
|
||||
.release = node_release,
|
||||
};
|
||||
|
||||
static struct node *alsa_create_node(struct device *device, uint32_t id,
|
||||
const struct spa_device_object_info *info)
|
||||
{
|
||||
|
|
@ -242,6 +286,8 @@ static struct node *alsa_create_node(struct device *device, uint32_t id,
|
|||
goto clean_node;
|
||||
}
|
||||
|
||||
node->snode->obj.methods = SPA_CALLBACKS_INIT(&node_methods, node);
|
||||
|
||||
spa_list_append(&device->node_list, &node->link);
|
||||
|
||||
return node;
|
||||
|
|
@ -398,6 +444,23 @@ static int update_device_props(struct device *device)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void set_profile(struct device *device, int index)
|
||||
{
|
||||
char buf[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
|
||||
|
||||
pw_log_debug("%p: set profile %d id:%d", device, index, device->device_id);
|
||||
|
||||
if (device->device_id != 0) {
|
||||
device->profile = index;
|
||||
spa_device_set_param(device->device,
|
||||
SPA_PARAM_Profile, 0,
|
||||
spa_pod_builder_add_object(&b,
|
||||
SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
|
||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(index)));
|
||||
}
|
||||
}
|
||||
|
||||
static void set_jack_profile(struct impl *impl, int index)
|
||||
{
|
||||
char buf[1024];
|
||||
|
|
@ -413,23 +476,6 @@ static void set_jack_profile(struct impl *impl, int index)
|
|||
SPA_PARAM_PROFILE_index, SPA_POD_Int(index)));
|
||||
}
|
||||
|
||||
static void set_profile(struct device *device, int index)
|
||||
{
|
||||
char buf[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
|
||||
|
||||
pw_log_debug("%p: set profile %d id:%d", device, index, device->device_id);
|
||||
|
||||
device->profile = index;
|
||||
if (device->device_id != 0) {
|
||||
spa_device_set_param(device->device,
|
||||
SPA_PARAM_Profile, 0,
|
||||
spa_pod_builder_add_object(&b,
|
||||
SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
|
||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(index)));
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_jack_timeout(struct impl *impl)
|
||||
{
|
||||
struct pw_loop *main_loop = impl->session->loop;
|
||||
|
|
@ -463,19 +509,18 @@ static void add_jack_timeout(struct impl *impl)
|
|||
static void reserve_acquired(void *data, struct rd_device *d)
|
||||
{
|
||||
struct device *device = data;
|
||||
struct impl *impl = device->impl;
|
||||
|
||||
pw_log_debug("%p: reserve acquired", device);
|
||||
pw_log_debug("%p: reserve acquired %d", device, device->n_acquired);
|
||||
|
||||
remove_jack_timeout(impl);
|
||||
set_jack_profile(impl, 0);
|
||||
set_profile(device, 1);
|
||||
device->sdevice->locked = false;
|
||||
|
||||
if (device->n_acquired == 0)
|
||||
rd_device_release(device->reserve);
|
||||
}
|
||||
|
||||
static void sync_complete_done(void *data, int seq)
|
||||
{
|
||||
struct device *device = data;
|
||||
struct impl *impl = device->impl;
|
||||
|
||||
pw_log_debug("%d %d", device->seq, seq);
|
||||
if (seq != device->seq)
|
||||
|
|
@ -486,8 +531,6 @@ static void sync_complete_done(void *data, int seq)
|
|||
|
||||
if (device->reserve)
|
||||
rd_device_complete_release(device->reserve, true);
|
||||
|
||||
add_jack_timeout(impl);
|
||||
}
|
||||
|
||||
static void sync_destroy(void *data)
|
||||
|
|
@ -506,11 +549,9 @@ static const struct pw_proxy_events sync_complete_release = {
|
|||
static void reserve_release(void *data, struct rd_device *d, int forced)
|
||||
{
|
||||
struct device *device = data;
|
||||
struct impl *impl = device->impl;
|
||||
|
||||
pw_log_debug("%p: reserve release", device);
|
||||
|
||||
remove_jack_timeout(impl);
|
||||
set_profile(device, 0);
|
||||
|
||||
if (device->seq == 0)
|
||||
|
|
@ -520,9 +561,41 @@ static void reserve_release(void *data, struct rd_device *d, int forced)
|
|||
device->seq = pw_proxy_sync(device->sdevice->obj.proxy, 0);
|
||||
}
|
||||
|
||||
static void reserve_busy(void *data, struct rd_device *d, const char *name, int32_t prio)
|
||||
{
|
||||
struct device *device = data;
|
||||
struct impl *impl = device->impl;
|
||||
|
||||
pw_log_debug("%p: reserve busy %s", device, name);
|
||||
device->sdevice->locked = true;
|
||||
|
||||
if (strcmp(name, "jack") == 0) {
|
||||
add_jack_timeout(impl);
|
||||
} else {
|
||||
remove_jack_timeout(impl);
|
||||
}
|
||||
}
|
||||
|
||||
static void reserve_available(void *data, struct rd_device *d, const char *name)
|
||||
{
|
||||
struct device *device = data;
|
||||
struct impl *impl = device->impl;
|
||||
|
||||
pw_log_debug("%p: reserve available %s", device, name);
|
||||
device->sdevice->locked = false;
|
||||
|
||||
remove_jack_timeout(impl);
|
||||
if (strcmp(name, "jack") == 0) {
|
||||
set_jack_profile(impl, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const struct rd_device_callbacks reserve_callbacks = {
|
||||
.acquired = reserve_acquired,
|
||||
.release = reserve_release,
|
||||
.busy = reserve_busy,
|
||||
.available = reserve_available,
|
||||
};
|
||||
|
||||
static void device_destroy(void *data)
|
||||
|
|
@ -542,18 +615,17 @@ static void device_update(void *data)
|
|||
|
||||
pw_log_debug("device %p appeared %d %d", device, device->appeared, device->profile);
|
||||
|
||||
if (device->appeared)
|
||||
return;
|
||||
if (!device->appeared) {
|
||||
device->device_id = device->sdevice->obj.id;
|
||||
device->appeared = true;
|
||||
|
||||
device->device_id = device->sdevice->obj.id;
|
||||
device->appeared = true;
|
||||
|
||||
spa_device_add_listener(device->device,
|
||||
&device->device_listener,
|
||||
&alsa_device_events, device);
|
||||
|
||||
set_profile(device, device->profile);
|
||||
sm_object_sync_update(&device->sdevice->obj);
|
||||
spa_device_add_listener(device->device,
|
||||
&device->device_listener,
|
||||
&alsa_device_events, device);
|
||||
sm_object_sync_update(&device->sdevice->obj);
|
||||
}
|
||||
if (device->pending_profile != device->profile && !device->sdevice->locked)
|
||||
set_profile(device, device->pending_profile);
|
||||
}
|
||||
|
||||
static const struct sm_object_events device_events = {
|
||||
|
|
@ -634,14 +706,12 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id,
|
|||
} else {
|
||||
rd_device_set_application_device_name(device->reserve,
|
||||
spa_dict_lookup(info->props, SPA_KEY_API_ALSA_PATH));
|
||||
|
||||
rd_device_acquire(device->reserve);
|
||||
}
|
||||
device->priority -= atol(card) * 64;
|
||||
}
|
||||
|
||||
/* no device reservation, activate device right now */
|
||||
if (device->reserve == NULL)
|
||||
set_profile(device, 1);
|
||||
|
||||
device->pending_profile = 1;
|
||||
device->first = true;
|
||||
spa_list_init(&device->node_list);
|
||||
spa_list_append(&impl->device_list, &device->link);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue