mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
pulse-server: implement temporary data attached to manager objects
Add functions for setting timer-based lifetimes for object data. Having the timers in the object data themselves simplifies life cycle management, as client/manager disconnects are handled without further work.
This commit is contained in:
parent
36ad886388
commit
83be5d866f
2 changed files with 74 additions and 6 deletions
|
|
@ -41,12 +41,15 @@
|
|||
#define manager_emit_removed(m,o) spa_hook_list_call(&m->hooks, struct pw_manager_events, removed, 0, o)
|
||||
#define manager_emit_metadata(m,o,s,k,t,v) spa_hook_list_call(&m->hooks, struct pw_manager_events, metadata,0,o,s,k,t,v)
|
||||
#define manager_emit_disconnect(m) spa_hook_list_call(&m->hooks, struct pw_manager_events, disconnect, 0)
|
||||
#define manager_emit_object_data_timeout(m,o,k) spa_hook_list_call(&m->hooks, struct pw_manager_events, object_data_timeout,0,o,k)
|
||||
|
||||
struct object;
|
||||
|
||||
struct manager {
|
||||
struct pw_manager this;
|
||||
|
||||
struct pw_loop *loop;
|
||||
|
||||
struct spa_hook core_listener;
|
||||
struct spa_hook registry_listener;
|
||||
int sync_seq;
|
||||
|
|
@ -64,8 +67,10 @@ struct object_info {
|
|||
|
||||
struct object_data {
|
||||
struct spa_list link;
|
||||
struct object *object;
|
||||
const char *key;
|
||||
size_t size;
|
||||
struct spa_source *timer;
|
||||
};
|
||||
|
||||
struct object {
|
||||
|
|
@ -188,6 +193,16 @@ static void object_update_params(struct object *o)
|
|||
}
|
||||
}
|
||||
|
||||
static void object_data_free(struct object_data *d)
|
||||
{
|
||||
spa_list_remove(&d->link);
|
||||
if (d->timer) {
|
||||
pw_loop_destroy_source(d->object->manager->loop, d->timer);
|
||||
d->timer = NULL;
|
||||
}
|
||||
free(d);
|
||||
}
|
||||
|
||||
static void object_destroy(struct object *o)
|
||||
{
|
||||
struct manager *m = o->manager;
|
||||
|
|
@ -201,10 +216,8 @@ static void object_destroy(struct object *o)
|
|||
free(o->this.message_object_path);
|
||||
clear_params(&o->this.param_list, SPA_ID_INVALID);
|
||||
clear_params(&o->pending_list, SPA_ID_INVALID);
|
||||
spa_list_consume(d, &o->data_list, link) {
|
||||
spa_list_remove(&d->link);
|
||||
free(d);
|
||||
}
|
||||
spa_list_consume(d, &o->data_list, link)
|
||||
object_data_free(d);
|
||||
free(o);
|
||||
}
|
||||
|
||||
|
|
@ -716,6 +729,7 @@ static const struct pw_core_events core_events = {
|
|||
struct pw_manager *pw_manager_new(struct pw_core *core)
|
||||
{
|
||||
struct manager *m;
|
||||
struct pw_context *context;
|
||||
|
||||
m = calloc(1, sizeof(*m));
|
||||
if (m == NULL)
|
||||
|
|
@ -729,6 +743,9 @@ struct pw_manager *pw_manager_new(struct pw_core *core)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
context = pw_core_get_context(core);
|
||||
m->loop = pw_context_get_main_loop(context);
|
||||
|
||||
spa_hook_list_init(&m->hooks);
|
||||
|
||||
spa_list_init(&m->this.object_list);
|
||||
|
|
@ -847,11 +864,14 @@ void *pw_manager_object_add_data(struct pw_manager_object *obj, const char *key,
|
|||
if (d != NULL) {
|
||||
if (d->size == size)
|
||||
goto done;
|
||||
spa_list_remove(&d->link);
|
||||
free(d);
|
||||
object_data_free(d);
|
||||
}
|
||||
|
||||
d = calloc(1, sizeof(struct object_data) + size);
|
||||
if (d == NULL)
|
||||
return NULL;
|
||||
|
||||
d->object = o;
|
||||
d->key = key;
|
||||
d->size = size;
|
||||
|
||||
|
|
@ -861,6 +881,49 @@ done:
|
|||
return SPA_PTROFF(d, sizeof(struct object_data), void);
|
||||
}
|
||||
|
||||
static void object_data_timeout(void *data, uint64_t count)
|
||||
{
|
||||
struct object_data *d = data;
|
||||
struct object *o = d->object;
|
||||
struct manager *m = o->manager;
|
||||
|
||||
pw_log_debug("manager:%p object id:%d data '%s' lifetime ends",
|
||||
m, o->this.id, d->key);
|
||||
|
||||
if (d->timer) {
|
||||
pw_loop_destroy_source(m->loop, d->timer);
|
||||
d->timer = NULL;
|
||||
}
|
||||
|
||||
manager_emit_object_data_timeout(m, &o->this, d->key);
|
||||
}
|
||||
|
||||
void *pw_manager_object_add_temporary_data(struct pw_manager_object *obj, const char *key,
|
||||
size_t size, uint64_t lifetime_nsec)
|
||||
{
|
||||
struct object *o = SPA_CONTAINER_OF(obj, struct object, this);
|
||||
struct object_data *d;
|
||||
void *data;
|
||||
struct timespec timeout = {0}, interval = {0};
|
||||
|
||||
data = pw_manager_object_add_data(obj, key, size);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
d = SPA_PTROFF(data, -sizeof(struct object_data), void);
|
||||
|
||||
if (d->timer == NULL)
|
||||
d->timer = pw_loop_add_timer(o->manager->loop, object_data_timeout, d);
|
||||
if (d->timer == NULL)
|
||||
return NULL;
|
||||
|
||||
timeout.tv_sec = lifetime_nsec / SPA_NSEC_PER_SEC;
|
||||
timeout.tv_nsec = lifetime_nsec % SPA_NSEC_PER_SEC;
|
||||
pw_loop_update_timer(o->manager->loop, d->timer, &timeout, &interval, false);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void *pw_manager_object_get_data(struct pw_manager_object *obj, const char *id)
|
||||
{
|
||||
struct object *o = SPA_CONTAINER_OF(obj, struct object, this);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ struct pw_manager_events {
|
|||
const char *type, const char *value);
|
||||
|
||||
void (*disconnect) (void *data);
|
||||
|
||||
void (*object_data_timeout) (void *data, struct pw_manager_object *object,
|
||||
const char *key);
|
||||
};
|
||||
|
||||
struct pw_manager {
|
||||
|
|
@ -115,6 +118,8 @@ int pw_manager_for_each_object(struct pw_manager *manager,
|
|||
|
||||
void *pw_manager_object_add_data(struct pw_manager_object *o, const char *key, size_t size);
|
||||
void *pw_manager_object_get_data(struct pw_manager_object *obj, const char *key);
|
||||
void *pw_manager_object_add_temporary_data(struct pw_manager_object *o, const char *key,
|
||||
size_t size, uint64_t lifetime_nsec);
|
||||
|
||||
bool pw_manager_object_is_client(struct pw_manager_object *o);
|
||||
bool pw_manager_object_is_module(struct pw_manager_object *o);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue