mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
pulse-server: implement subscribe in device-restore
Add a client that subscribes to the list of subscribers and make the client watch for EnumFormat changes. When a subscribed client sees an EnumFormat change for a sink, emit EVENT to the client. This will send the EVENT to pavucontrol when the supported IEC958 formats change so that it can update the gui.
This commit is contained in:
parent
979eb0278f
commit
bffcb2e6f1
1 changed files with 149 additions and 9 deletions
|
|
@ -19,6 +19,15 @@
|
|||
|
||||
#define EXT_DEVICE_RESTORE_VERSION 1
|
||||
|
||||
enum {
|
||||
SUBCOMMAND_TEST,
|
||||
SUBCOMMAND_SUBSCRIBE,
|
||||
SUBCOMMAND_EVENT,
|
||||
SUBCOMMAND_READ_FORMATS_ALL,
|
||||
SUBCOMMAND_READ_FORMATS,
|
||||
SUBCOMMAND_SAVE_FORMATS
|
||||
};
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -38,11 +47,13 @@
|
|||
|
||||
#include "../client.h"
|
||||
#include "../collect.h"
|
||||
#include "../commands.h"
|
||||
#include "../defs.h"
|
||||
#include "../extension.h"
|
||||
#include "../format.h"
|
||||
#include "../manager.h"
|
||||
#include "../message.h"
|
||||
#include "../operation.h"
|
||||
#include "../reply.h"
|
||||
#include "../volume.h"
|
||||
|
||||
|
|
@ -59,6 +70,8 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
|
|||
|
||||
struct module_device_restore_data {
|
||||
struct module *module;
|
||||
|
||||
struct spa_list subscribed;
|
||||
};
|
||||
|
||||
static const struct spa_dict_item module_device_restore_info[] = {
|
||||
|
|
@ -83,11 +96,127 @@ static int do_extension_device_restore_test(struct module *module, struct client
|
|||
return client_queue_message(client, reply);
|
||||
}
|
||||
|
||||
static int do_extension_device_restore_subscribe(struct module *module, struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
||||
struct subscribe {
|
||||
struct spa_list link;
|
||||
struct module_device_restore_data *data;
|
||||
|
||||
struct client *client;
|
||||
struct spa_hook listener;
|
||||
|
||||
struct spa_hook manager_listener;
|
||||
};
|
||||
|
||||
static void remove_subscribe(struct subscribe *s)
|
||||
{
|
||||
return reply_simple_ack(client, tag);
|
||||
spa_list_remove(&s->link);
|
||||
spa_hook_remove(&s->listener);
|
||||
spa_hook_remove(&s->manager_listener);
|
||||
free(s);
|
||||
}
|
||||
|
||||
static void emit_event(struct subscribe *s, uint32_t type, uint32_t idx)
|
||||
{
|
||||
struct client *client = s->client;
|
||||
struct message *msg = message_alloc(client->impl, -1, 0);
|
||||
|
||||
pw_log_info("[%s] EVENT index:%u name:%s %d/%d", client->name,
|
||||
s->data->module->index, s->data->module->info->name, type, idx);
|
||||
|
||||
message_put(msg,
|
||||
TAG_U32, COMMAND_EXTENSION,
|
||||
TAG_U32, 0,
|
||||
TAG_U32, s->data->module->index,
|
||||
TAG_STRING, s->data->module->info->name,
|
||||
TAG_U32, SUBCOMMAND_EVENT,
|
||||
TAG_U32, type,
|
||||
TAG_U32, idx,
|
||||
TAG_INVALID);
|
||||
|
||||
client_queue_message(client, msg);
|
||||
}
|
||||
|
||||
static void module_client_disconnect(void *data)
|
||||
{
|
||||
struct subscribe *s = data;
|
||||
remove_subscribe(s);
|
||||
}
|
||||
|
||||
static const struct client_events module_client_events = {
|
||||
VERSION_CLIENT_EVENTS,
|
||||
.disconnect = module_client_disconnect,
|
||||
};
|
||||
|
||||
static void manager_updated(void *data, struct pw_manager_object *object)
|
||||
{
|
||||
struct subscribe *s = data;
|
||||
uint32_t i;
|
||||
|
||||
if (!pw_manager_object_is_sink(object))
|
||||
return;
|
||||
|
||||
for (i = 0; i < object->n_params; i++) {
|
||||
if (object->params[i].id == SPA_PARAM_EnumFormat &&
|
||||
object->params[i].user != 0)
|
||||
emit_event(s, DEVICE_TYPE_SINK, object->index);
|
||||
}
|
||||
}
|
||||
|
||||
struct pw_manager_events manager_events = {
|
||||
PW_VERSION_MANAGER_EVENTS,
|
||||
.added = manager_updated,
|
||||
.updated = manager_updated,
|
||||
};
|
||||
|
||||
static struct subscribe *add_subscribe(struct module_device_restore_data *data, struct client *c)
|
||||
{
|
||||
struct subscribe *s;
|
||||
s = calloc(1, sizeof(*s));
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
s->data = data;
|
||||
s->client = c;
|
||||
client_add_listener(c, &s->listener, &module_client_events, s);
|
||||
spa_list_append(&data->subscribed, &s->link);
|
||||
|
||||
pw_manager_add_listener(c->manager, &s->manager_listener,
|
||||
&manager_events, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
static struct subscribe *find_subscribe(struct module_device_restore_data *data, struct client *c)
|
||||
{
|
||||
struct subscribe *s;
|
||||
spa_list_for_each(s, &data->subscribed, link) {
|
||||
if (s->client == c)
|
||||
return s;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int do_extension_device_restore_subscribe(struct module *module, struct client *client, uint32_t command, uint32_t tag, struct message *m)
|
||||
{
|
||||
struct module_device_restore_data * const d = module->user_data;
|
||||
int res;
|
||||
bool enabled;
|
||||
struct subscribe *s;
|
||||
|
||||
if ((res = message_get(m,
|
||||
TAG_BOOLEAN, &enabled,
|
||||
TAG_INVALID)) < 0)
|
||||
return -EPROTO;
|
||||
|
||||
s = find_subscribe(d, client);
|
||||
if (enabled) {
|
||||
if (s == NULL)
|
||||
s = add_subscribe(d, client);
|
||||
if (s == NULL)
|
||||
return -errno;
|
||||
} else {
|
||||
if (s != NULL)
|
||||
remove_subscribe(s);
|
||||
}
|
||||
return reply_simple_ack(client, tag);
|
||||
}
|
||||
|
||||
struct format_data {
|
||||
struct client *client;
|
||||
|
|
@ -248,7 +377,6 @@ static int set_node_codecs(struct pw_manager_object *o, uint32_t n_codecs, uint3
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int do_extension_device_restore_save_formats(struct module *module, struct client *client,
|
||||
uint32_t command, uint32_t tag, struct message *m)
|
||||
{
|
||||
|
|
@ -318,12 +446,12 @@ static int do_extension_device_restore_save_formats(struct module *module, struc
|
|||
}
|
||||
|
||||
static const struct extension module_device_restore_extension[] = {
|
||||
{ "TEST", 0, do_extension_device_restore_test, },
|
||||
{ "SUBSCRIBE", 1, do_extension_device_restore_subscribe, },
|
||||
{ "EVENT", 2, },
|
||||
{ "READ_FORMATS_ALL", 3, do_extension_device_restore_read_formats_all, },
|
||||
{ "READ_FORMATS", 4, do_extension_device_restore_read_formats, },
|
||||
{ "SAVE_FORMATS", 5, do_extension_device_restore_save_formats, },
|
||||
{ "TEST", SUBCOMMAND_TEST, do_extension_device_restore_test, },
|
||||
{ "SUBSCRIBE", SUBCOMMAND_SUBSCRIBE, do_extension_device_restore_subscribe, },
|
||||
{ "EVENT", SUBCOMMAND_EVENT, },
|
||||
{ "READ_FORMATS_ALL", SUBCOMMAND_READ_FORMATS_ALL, do_extension_device_restore_read_formats_all, },
|
||||
{ "READ_FORMATS", SUBCOMMAND_READ_FORMATS, do_extension_device_restore_read_formats, },
|
||||
{ "SAVE_FORMATS", SUBCOMMAND_SAVE_FORMATS, do_extension_device_restore_save_formats, },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
|
@ -339,6 +467,17 @@ static int module_device_restore_prepare(struct module * const module)
|
|||
|
||||
static int module_device_restore_load(struct module *module)
|
||||
{
|
||||
struct module_device_restore_data * const data = module->user_data;
|
||||
spa_list_init(&data->subscribed);
|
||||
return 0;
|
||||
}
|
||||
static int module_device_restore_unload(struct module *module)
|
||||
{
|
||||
struct module_device_restore_data * const data = module->user_data;
|
||||
struct subscribe *s;
|
||||
|
||||
spa_list_consume(s, &data->subscribed, link)
|
||||
remove_subscribe(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -347,6 +486,7 @@ DEFINE_MODULE_INFO(module_device_restore) = {
|
|||
.load_once = true,
|
||||
.prepare = module_device_restore_prepare,
|
||||
.load = module_device_restore_load,
|
||||
.unload = module_device_restore_unload,
|
||||
.extension = module_device_restore_extension,
|
||||
.properties = &SPA_DICT_INIT_ARRAY(module_device_restore_info),
|
||||
.data_size = sizeof(struct module_device_restore_data),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue