media-session: improve cleanup

This commit is contained in:
Wim Taymans 2019-12-18 12:15:03 +01:00
parent 2a4c57798d
commit 147f488514
11 changed files with 301 additions and 162 deletions

View file

@ -404,7 +404,7 @@ static void proxy_destroy(void *data)
pw_properties_free(endpoint->props); pw_properties_free(endpoint->props);
spa_list_remove(&endpoint->link); spa_list_remove(&endpoint->link);
spa_hook_remove(&endpoint->proxy_listener); spa_hook_remove(&endpoint->proxy_listener);
spa_hook_remove(&endpoint->listener); spa_hook_remove(&endpoint->client_endpoint_listener);
} }
static void proxy_bound(void *data, uint32_t id) static void proxy_bound(void *data, uint32_t id)
@ -693,10 +693,11 @@ handle_device(struct impl *impl, struct sm_object *obj)
return 0; return 0;
} }
static void destroy_device(struct device *device) static void destroy_device(struct impl *impl, struct device *device)
{ {
deactivate_device(device); deactivate_device(device);
spa_hook_remove(&device->listener); spa_hook_remove(&device->listener);
sm_object_remove_data((struct sm_object*)device->device, SESSION_KEY);
} }
static void session_create(void *data, struct sm_object *object) static void session_create(void *data, struct sm_object *object)
@ -721,12 +722,14 @@ static void session_create(void *data, struct sm_object *object)
static void session_remove(void *data, struct sm_object *object) static void session_remove(void *data, struct sm_object *object)
{ {
struct impl *impl = data;
switch (object->type) { switch (object->type) {
case PW_TYPE_INTERFACE_Device: case PW_TYPE_INTERFACE_Device:
{ {
struct device *device; struct device *device;
if ((device = sm_object_get_data(object, SESSION_KEY)) != NULL) if ((device = sm_object_get_data(object, SESSION_KEY)) != NULL)
destroy_device(device); destroy_device(impl, device);
break; break;
} }
default: default:
@ -734,28 +737,29 @@ static void session_remove(void *data, struct sm_object *object)
} }
} }
static void session_destroy(void *data)
{
struct impl *impl = data;
spa_hook_remove(&impl->listener);
free(impl);
}
static const struct sm_media_session_events session_events = { static const struct sm_media_session_events session_events = {
SM_VERSION_MEDIA_SESSION_EVENTS, SM_VERSION_MEDIA_SESSION_EVENTS,
.create = session_create, .create = session_create,
.remove = session_remove, .remove = session_remove,
.destroy = session_destroy,
}; };
void *sm_alsa_endpoint_start(struct sm_media_session *session) int sm_alsa_endpoint_start(struct sm_media_session *session)
{ {
struct impl *impl; struct impl *impl;
impl = calloc(1, sizeof(struct impl)); impl = calloc(1, sizeof(struct impl));
if (impl == NULL) if (impl == NULL)
return NULL; return -errno;
impl->session = session; impl->session = session;
sm_media_session_add_listener(session, &impl->listener, &session_events, impl); sm_media_session_add_listener(session, &impl->listener, &session_events, impl);
return impl;
}
int sm_alsa_endpoint_stop(void *data)
{
return 0; return 0;
} }

View file

@ -39,26 +39,44 @@
struct impl { struct impl {
struct sm_media_session *session; struct sm_media_session *session;
struct spa_hook listener;
struct pw_properties *props; struct pw_properties *props;
struct pw_proxy *proxy; struct pw_proxy *proxy;
}; };
void * sm_alsa_midi_start(struct sm_media_session *session) static void session_destroy(void *data)
{
struct impl *impl = data;
spa_hook_remove(&impl->listener);
pw_proxy_destroy(impl->proxy);
pw_properties_free(impl->props);
free(impl);
}
static const struct sm_media_session_events session_events = {
SM_VERSION_MEDIA_SESSION_EVENTS,
.destroy = session_destroy,
};
int sm_alsa_midi_start(struct sm_media_session *session)
{ {
struct impl *impl; struct impl *impl;
int res;
impl = calloc(1, sizeof(struct impl)); impl = calloc(1, sizeof(struct impl));
if (impl == NULL) if (impl == NULL)
return NULL; return -errno;
impl->session = session; impl->session = session;
impl->props = pw_properties_new( impl->props = pw_properties_new(
SPA_KEY_FACTORY_NAME, SPA_NAME_API_ALSA_SEQ_BRIDGE, SPA_KEY_FACTORY_NAME, SPA_NAME_API_ALSA_SEQ_BRIDGE,
SPA_KEY_NODE_NAME, "Midi-Bridge", SPA_KEY_NODE_NAME, "Midi-Bridge",
NULL); NULL);
if (impl->props == NULL) if (impl->props == NULL) {
res = -errno;
goto cleanup; goto cleanup;
}
impl->proxy = sm_media_session_create_object(session, impl->proxy = sm_media_session_create_object(session,
"spa-node-factory", "spa-node-factory",
@ -67,23 +85,17 @@ void * sm_alsa_midi_start(struct sm_media_session *session)
&impl->props->dict, &impl->props->dict,
0); 0);
if (impl->proxy == NULL) if (impl->proxy == NULL) {
res = -errno;
goto cleanup_props; goto cleanup_props;
}
sm_media_session_add_listener(session, &impl->listener, &session_events, impl);
return impl; return 0;
cleanup_props: cleanup_props:
pw_properties_free(impl->props); pw_properties_free(impl->props);
cleanup: cleanup:
free(impl); free(impl);
return NULL; return res;
}
int sm_alsa_midi_stop(void *data)
{
struct impl *impl = data;
pw_proxy_destroy(impl->proxy);
pw_properties_free(impl->props);
free(impl);
return 0;
} }

View file

@ -96,6 +96,7 @@ struct device {
struct impl { struct impl {
struct sm_media_session *session; struct sm_media_session *session;
struct spa_hook session_listener;
DBusConnection *conn; DBusConnection *conn;
@ -255,6 +256,7 @@ static void alsa_remove_node(struct device *device, struct node *node)
pw_log_debug("remove node %u", node->id); pw_log_debug("remove node %u", node->id);
spa_list_remove(&node->link); spa_list_remove(&node->link);
sm_object_destroy(&node->snode->obj); sm_object_destroy(&node->snode->obj);
pw_properties_free(node->props);
free(node); free(node);
} }
@ -484,8 +486,16 @@ static void sync_complete_done(void *data, int seq)
add_jack_timeout(impl); add_jack_timeout(impl);
} }
static void sync_destroy(void *data)
{
struct device *device = data;
if (device->seq != 0)
sync_complete_done(data, device->seq);
}
static const struct pw_proxy_events sync_complete_release = { static const struct pw_proxy_events sync_complete_release = {
PW_VERSION_PROXY_EVENTS, PW_VERSION_PROXY_EVENTS,
.destroy = sync_destroy,
.done = sync_complete_done .done = sync_complete_done
}; };
@ -656,6 +666,7 @@ static void alsa_remove_device(struct impl *impl, struct device *device)
sm_object_destroy(&device->sdevice->obj); sm_object_destroy(&device->sdevice->obj);
spa_hook_remove(&device->listener); spa_hook_remove(&device->listener);
pw_unload_spa_handle(device->handle); pw_unload_spa_handle(device->handle);
pw_properties_free(device->props);
free(device); free(device);
} }
@ -710,7 +721,22 @@ static int alsa_start_jack_device(struct impl *impl)
return res; return res;
} }
void *sm_alsa_monitor_start(struct sm_media_session *session) static void session_destroy(void *data)
{
struct impl *impl = data;
spa_hook_remove(&impl->session_listener);
spa_hook_remove(&impl->listener);
pw_proxy_destroy(impl->jack_device);
pw_unload_spa_handle(impl->handle);
free(impl);
}
static const struct sm_media_session_events session_events = {
SM_VERSION_MEDIA_SESSION_EVENTS,
.destroy = session_destroy,
};
int sm_alsa_monitor_start(struct sm_media_session *session)
{ {
struct pw_context *context = session->context; struct pw_context *context = session->context;
struct impl *impl; struct impl *impl;
@ -719,7 +745,7 @@ void *sm_alsa_monitor_start(struct sm_media_session *session)
impl = calloc(1, sizeof(struct impl)); impl = calloc(1, sizeof(struct impl));
if (impl == NULL) if (impl == NULL)
return NULL; return -errno;
impl->session = session; impl->session = session;
@ -747,20 +773,13 @@ void *sm_alsa_monitor_start(struct sm_media_session *session)
if ((res = alsa_start_jack_device(impl)) < 0) if ((res = alsa_start_jack_device(impl)) < 0)
goto out_unload; goto out_unload;
return impl; sm_media_session_add_listener(session, &impl->session_listener, &session_events, impl);
return 0;
out_unload: out_unload:
pw_unload_spa_handle(impl->handle); pw_unload_spa_handle(impl->handle);
out_free: out_free:
free(impl); free(impl);
errno = -res; return res;
return NULL;
}
int sm_alsa_monitor_stop(void *data)
{
struct impl *impl = data;
pw_unload_spa_handle(impl->handle);
free(impl);
return 0;
} }

View file

@ -33,6 +33,7 @@
#include <spa/monitor/device.h> #include <spa/monitor/device.h>
#include <spa/node/node.h> #include <spa/node/node.h>
#include <spa/utils/hook.h> #include <spa/utils/hook.h>
#include <spa/utils/result.h>
#include <spa/utils/names.h> #include <spa/utils/names.h>
#include <spa/param/audio/format-utils.h> #include <spa/param/audio/format-utils.h>
#include <spa/param/props.h> #include <spa/param/props.h>
@ -72,6 +73,7 @@ struct bluez5_object {
struct impl { struct impl {
struct sm_media_session *session; struct sm_media_session *session;
struct spa_hook session_listener;
struct spa_handle *handle; struct spa_handle *handle;
@ -294,6 +296,7 @@ static struct bluez5_object *bluez5_create_object(struct impl *impl, uint32_t id
return obj; return obj;
clean_object: clean_object:
pw_properties_free(obj->props);
free(obj); free(obj);
unload_handle: unload_handle:
pw_unload_spa_handle(handle); pw_unload_spa_handle(handle);
@ -315,6 +318,7 @@ static void bluez5_remove_object(struct impl *impl, struct bluez5_object *obj)
pw_proxy_destroy(obj->proxy); pw_proxy_destroy(obj->proxy);
pw_unload_spa_handle(obj->handle); pw_unload_spa_handle(obj->handle);
pw_properties_free(obj->props);
free(obj); free(obj);
} }
@ -344,7 +348,21 @@ static const struct spa_device_events bluez5_enum_callbacks =
.object_info = bluez5_enum_object_info, .object_info = bluez5_enum_object_info,
}; };
void *sm_bluez5_monitor_start(struct sm_media_session *session) static void session_destroy(void *data)
{
struct impl *impl = data;
spa_hook_remove(&impl->session_listener);
spa_hook_remove(&impl->listener);
pw_unload_spa_handle(impl->handle);
free(impl);
}
static const struct sm_media_session_events session_events = {
SM_VERSION_MEDIA_SESSION_EVENTS,
.destroy = session_destroy,
};
int sm_bluez5_monitor_start(struct sm_media_session *session)
{ {
struct spa_handle *handle; struct spa_handle *handle;
struct pw_context *context = session->context; struct pw_context *context = session->context;
@ -355,11 +373,12 @@ void *sm_bluez5_monitor_start(struct sm_media_session *session)
handle = pw_context_load_spa_handle(context, SPA_NAME_API_BLUEZ5_ENUM_DBUS, NULL); handle = pw_context_load_spa_handle(context, SPA_NAME_API_BLUEZ5_ENUM_DBUS, NULL);
if (handle == NULL) { if (handle == NULL) {
res = -errno; res = -errno;
pw_log_error("can't load %s: %m", SPA_NAME_API_BLUEZ5_ENUM_DBUS);
goto out; goto out;
} }
if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Device, &iface)) < 0) { if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Device, &iface)) < 0) {
pw_log_error("can't get Device interface: %d", res); pw_log_error("can't get Device interface: %s", spa_strerror(res));
goto out_unload; goto out_unload;
} }
@ -377,19 +396,13 @@ void *sm_bluez5_monitor_start(struct sm_media_session *session)
spa_device_add_listener(impl->monitor, &impl->listener, spa_device_add_listener(impl->monitor, &impl->listener,
&bluez5_enum_callbacks, impl); &bluez5_enum_callbacks, impl);
return impl; sm_media_session_add_listener(session, &impl->session_listener,
&session_events, impl);
out_unload:
pw_unload_spa_handle(handle);
out:
errno = -res;
return NULL;
}
int sm_bluez5_monitor_stop(void *data)
{
struct impl *impl = data;
pw_unload_spa_handle(impl->handle);
free(impl);
return 0; return 0;
out_unload:
pw_unload_spa_handle(handle);
out:
return res;
} }

View file

@ -53,20 +53,21 @@
#define sm_object_emit_update(s) sm_object_emit(s, update, 0) #define sm_object_emit_update(s) sm_object_emit(s, update, 0)
#define sm_object_emit_destroy(s) sm_object_emit(s, destroy, 0) #define sm_object_emit_destroy(s) sm_object_emit(s, destroy, 0)
#define sm_media_session_emit(s,m,v,...) spa_hook_list_call(&s->hooks, struct sm_media_session_events, m, v, ##__VA_ARGS__) #define sm_media_session_emit(s,m,v,...) spa_hook_list_call(&(s)->hooks, struct sm_media_session_events, m, v, ##__VA_ARGS__)
#define sm_media_session_emit_create(s,obj) sm_media_session_emit(s, create, 0, obj) #define sm_media_session_emit_create(s,obj) sm_media_session_emit(s, create, 0, obj)
#define sm_media_session_emit_remove(s,obj) sm_media_session_emit(s, remove, 0, obj) #define sm_media_session_emit_remove(s,obj) sm_media_session_emit(s, remove, 0, obj)
#define sm_media_session_emit_rescan(s,seq) sm_media_session_emit(s, rescan, 0, seq) #define sm_media_session_emit_rescan(s,seq) sm_media_session_emit(s, rescan, 0, seq)
#define sm_media_session_emit_destroy(s) sm_media_session_emit(s, destroy, 0)
void * sm_stream_endpoint_start(struct sm_media_session *sess); int sm_stream_endpoint_start(struct sm_media_session *sess);
void * sm_metadata_start(struct sm_media_session *sess); int sm_metadata_start(struct sm_media_session *sess);
void * sm_alsa_midi_start(struct sm_media_session *sess); int sm_alsa_midi_start(struct sm_media_session *sess);
void * sm_v4l2_monitor_start(struct sm_media_session *sess); int sm_v4l2_monitor_start(struct sm_media_session *sess);
void * sm_v4l2_endpoint_start(struct sm_media_session *sess); int sm_v4l2_endpoint_start(struct sm_media_session *sess);
void * sm_bluez5_monitor_start(struct sm_media_session *sess); int sm_bluez5_monitor_start(struct sm_media_session *sess);
void * sm_alsa_monitor_start(struct sm_media_session *sess); int sm_alsa_monitor_start(struct sm_media_session *sess);
void * sm_alsa_endpoint_start(struct sm_media_session *sess); int sm_alsa_endpoint_start(struct sm_media_session *sess);
int sm_policy_ep_start(struct sm_media_session *sess); int sm_policy_ep_start(struct sm_media_session *sess);
/** user data to add to an object */ /** user data to add to an object */
@ -154,19 +155,25 @@ struct object_info {
void (*destroy) (void *object); void (*destroy) (void *object);
}; };
static void add_object(struct impl *impl, struct sm_object *obj) static void add_object(struct impl *impl, struct sm_object *obj, uint32_t id)
{ {
size_t size = pw_map_get_size(&impl->globals); size_t size = pw_map_get_size(&impl->globals);
obj->id = id;
pw_log_debug("add %u %p", obj->id, obj);
while (obj->id > size) while (obj->id > size)
pw_map_insert_at(&impl->globals, size++, NULL); pw_map_insert_at(&impl->globals, size++, NULL);
pw_map_insert_at(&impl->globals, obj->id, obj); pw_map_insert_at(&impl->globals, obj->id, obj);
spa_list_append(&impl->global_list, &obj->link); spa_list_append(&impl->global_list, &obj->link);
sm_media_session_emit_create(impl, obj);
} }
static void remove_object(struct impl *impl, struct sm_object *obj) static void remove_object(struct impl *impl, struct sm_object *obj)
{ {
pw_log_debug("remove %u %p", obj->id, obj);
pw_map_insert_at(&impl->globals, obj->id, NULL); pw_map_insert_at(&impl->globals, obj->id, NULL);
spa_list_remove(&obj->link); spa_list_remove(&obj->link);
sm_media_session_emit_remove(impl, obj);
obj->id = SPA_ID_INVALID;
} }
static void *find_object(struct impl *impl, uint32_t id) static void *find_object(struct impl *impl, uint32_t id)
@ -637,15 +644,18 @@ static void session_destroy(void *object)
{ {
struct sm_session *sess = object; struct sm_session *sess = object;
struct sm_endpoint *endpoint; struct sm_endpoint *endpoint;
struct pw_session_info *i = sess->info;
if (sess->info) {
free(sess->info);
}
spa_list_consume(endpoint, &sess->endpoint_list, link) { spa_list_consume(endpoint, &sess->endpoint_list, link) {
endpoint->session = NULL; endpoint->session = NULL;
spa_list_remove(&endpoint->link); spa_list_remove(&endpoint->link);
} }
if (i) {
if (i->props)
pw_properties_free ((struct pw_properties *)i->props);
free(i);
}
} }
static const struct object_info session_info = { static const struct object_info session_info = {
@ -725,12 +735,7 @@ static void endpoint_destroy(void *object)
{ {
struct sm_endpoint *endpoint = object; struct sm_endpoint *endpoint = object;
struct sm_endpoint_stream *stream; struct sm_endpoint_stream *stream;
struct pw_endpoint_info *i = endpoint->info;
if (endpoint->info) {
free(endpoint->info->name);
free(endpoint->info->media_class);
free(endpoint->info);
}
spa_list_consume(stream, &endpoint->stream_list, link) { spa_list_consume(stream, &endpoint->stream_list, link) {
stream->endpoint = NULL; stream->endpoint = NULL;
@ -740,6 +745,13 @@ static void endpoint_destroy(void *object)
endpoint->session = NULL; endpoint->session = NULL;
spa_list_remove(&endpoint->link); spa_list_remove(&endpoint->link);
} }
if (i) {
if (i->props)
pw_properties_free ((struct pw_properties *)i->props);
free(i->name);
free(i->media_class);
free(i);
}
} }
static const struct object_info endpoint_info = { static const struct object_info endpoint_info = {
@ -892,15 +904,27 @@ destroy_proxy(void *data)
{ {
struct sm_object *obj = data; struct sm_object *obj = data;
struct impl *impl = SPA_CONTAINER_OF(obj->session, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(obj->session, struct impl, this);
struct data *d;
sm_media_session_emit_remove(impl, obj); pw_log_debug("object %p: proxy:%p id:%d", obj, obj->proxy, obj->id);
remove_object(impl, obj); spa_hook_remove(&obj->proxy_listener);
if (SPA_FLAG_IS_SET(obj->mask, SM_OBJECT_CHANGE_MASK_LISTENER))
spa_hook_remove(&obj->object_listener);
if (obj->id != SPA_ID_INVALID)
remove_object(impl, obj);
sm_object_emit_destroy(obj); sm_object_emit_destroy(obj);
if (obj->destroy) if (obj->destroy)
obj->destroy(obj); obj->destroy(obj);
pw_properties_free(obj->props);
spa_list_consume(d, &obj->data, link) {
spa_list_remove(&d->link);
free(d);
}
} }
static void done_proxy(void *data, int seq) static void done_proxy(void *data, int seq)
@ -923,14 +947,10 @@ static void bound_proxy(void *data, uint32_t id)
struct sm_object *obj = data; struct sm_object *obj = data;
struct impl *impl = SPA_CONTAINER_OF(obj->session, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(obj->session, struct impl, this);
pw_log_debug("bound %p proxy %p id:%d", obj, obj->proxy, id); pw_log_debug("bound %p proxy %p id:%d->%d", obj, obj->proxy, obj->id, id);
if (obj->id == SPA_ID_INVALID) { if (obj->id == SPA_ID_INVALID)
obj->id = id; add_object(impl, obj, id);
pw_log_debug("bound %p proxy %p id:%d", obj, obj->proxy, id);
add_object(impl, obj);
sm_media_session_emit_create(impl, obj);
}
} }
static const struct pw_proxy_events proxy_events = { static const struct pw_proxy_events proxy_events = {
@ -1011,10 +1031,9 @@ static struct sm_object *init_object(struct impl *impl, const struct object_info
if (info->init) if (info->init)
info->init(obj); info->init(obj);
if (id != SPA_ID_INVALID) { if (id != SPA_ID_INVALID)
add_object(impl, obj); add_object(impl, obj, id);
sm_media_session_emit_create(impl, obj);
}
return obj; return obj;
} }
@ -1082,6 +1101,7 @@ update_object(struct impl *impl, const struct object_info *info,
pw_log_debug(NAME" %p: update type:%d -> type:%d", impl, obj->type, type); pw_log_debug(NAME" %p: update type:%d -> type:%d", impl, obj->type, type);
obj->handle = obj->proxy; obj->handle = obj->proxy;
spa_hook_remove(&obj->proxy_listener); spa_hook_remove(&obj->proxy_listener);
pw_proxy_add_listener(obj->handle, &obj->handle_listener, &proxy_events, obj);
if (SPA_FLAG_IS_SET(obj->mask, SM_OBJECT_CHANGE_MASK_LISTENER)) if (SPA_FLAG_IS_SET(obj->mask, SM_OBJECT_CHANGE_MASK_LISTENER))
spa_hook_remove(&obj->object_listener); spa_hook_remove(&obj->object_listener);
@ -1636,18 +1656,20 @@ static int start_policy(struct impl *impl)
} }
pw_core_add_listener(impl->policy_core, pw_core_add_listener(impl->policy_core,
&impl->policy_listener, &impl->policy_listener,
&core_events, impl); &core_events, impl);
pw_proxy_add_listener((struct pw_proxy*)impl->policy_core, pw_proxy_add_listener((struct pw_proxy*)impl->policy_core,
&impl->proxy_policy_listener, &impl->proxy_policy_listener,
&proxy_core_events, impl); &proxy_core_events, impl);
impl->registry = pw_core_get_registry(impl->policy_core,
PW_VERSION_REGISTRY, 0);
pw_registry_add_listener(impl->registry,
&impl->registry_listener,
&registry_events, impl);
return sm_policy_ep_start(&impl->this); impl->registry = pw_core_get_registry(impl->policy_core,
PW_VERSION_REGISTRY, 0);
pw_registry_add_listener(impl->registry,
&impl->registry_listener,
&registry_events, impl);
sm_policy_ep_start(&impl->this);
return 0;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -1655,6 +1677,7 @@ int main(int argc, char *argv[])
struct impl impl = { 0, }; struct impl impl = { 0, };
const struct spa_support *support; const struct spa_support *support;
uint32_t n_support; uint32_t n_support;
int res = 0;
pw_init(&argc, &argv); pw_init(&argc, &argv);
@ -1685,15 +1708,20 @@ int main(int argc, char *argv[])
else else
pw_log_debug("got dbus connection %p", impl.this.dbus_connection); pw_log_debug("got dbus connection %p", impl.this.dbus_connection);
if (start_session(&impl) < 0) if ((res = start_session(&impl)) < 0)
return -1; goto exit;
if (start_policy(&impl) < 0) if ((res = start_policy(&impl)) < 0)
return -1; goto exit;
pw_main_loop_run(impl.loop); pw_main_loop_run(impl.loop);
exit:
sm_media_session_emit_destroy(&impl);
pw_context_destroy(impl.this.context); pw_context_destroy(impl.this.context);
pw_main_loop_destroy(impl.loop); pw_main_loop_destroy(impl.loop);
return 0; pw_map_clear(&impl.endpoint_links);
pw_map_clear(&impl.globals);
return res;
} }

View file

@ -67,6 +67,7 @@ struct sm_object {
int pending; int pending;
struct pw_proxy *handle; struct pw_proxy *handle;
struct spa_hook handle_listener;
struct spa_hook_list hooks; struct spa_hook_list hooks;
struct spa_list data; struct spa_list data;
@ -200,6 +201,7 @@ struct sm_media_session_events {
void (*remove) (void *data, struct sm_object *object); void (*remove) (void *data, struct sm_object *object);
void (*rescan) (void *data, int seq); void (*rescan) (void *data, int seq);
void (*destroy) (void *data);
}; };
struct sm_media_session { struct sm_media_session {

View file

@ -65,6 +65,8 @@ struct metadata {
struct spa_interface iface; struct spa_interface iface;
struct sm_media_session *session; struct sm_media_session *session;
struct spa_hook session_listener;
struct spa_hook_list hooks; struct spa_hook_list hooks;
struct pw_properties *properties; struct pw_properties *properties;
@ -180,11 +182,33 @@ struct pw_metadata_methods impl_metadata = {
.clear = impl_clear, .clear = impl_clear,
}; };
void *sm_metadata_start(struct sm_media_session *sess) static void session_destroy(void *data)
{
struct metadata *this = data;
spa_hook_remove(&this->session_listener);
pw_proxy_destroy(this->proxy);
clear_items(this);
pw_array_clear(&this->metadata);
pw_properties_free(this->properties);
free(this);
}
static const struct sm_media_session_events session_events = {
SM_VERSION_MEDIA_SESSION_EVENTS,
.destroy = session_destroy,
};
int sm_metadata_start(struct sm_media_session *sess)
{ {
struct metadata *md; struct metadata *md;
int res;
md = calloc(1, sizeof(*md)); md = calloc(1, sizeof(*md));
if (md == NULL)
return -errno;
md->session = sess; md->session = sess;
md->properties = pw_properties_new(NULL, NULL); md->properties = pw_properties_new(NULL, NULL);
pw_array_init(&md->metadata, 4096); pw_array_init(&md->metadata, 4096);
@ -200,18 +224,18 @@ void *sm_metadata_start(struct sm_media_session *sess)
NULL, NULL,
md, md,
0); 0);
return md; if (md->proxy == NULL) {
} res = -errno;
goto error_free;
}
int sm_metadata_stop(void *data) sm_media_session_add_listener(sess, &md->session_listener,
{ &session_events, md);
struct metadata *this = data;
pw_proxy_destroy(this->proxy);
clear_items(this);
pw_array_clear(&this->metadata);
pw_properties_free(this->properties);
free(this);
return 0; return 0;
error_free:
pw_array_clear(&md->metadata);
pw_properties_free(md->properties);
free(md);
return res;
} }

View file

@ -179,6 +179,13 @@ handle_endpoint(struct impl *impl, struct sm_object *object)
return 1; return 1;
} }
static void destroy_endpoint(struct impl *impl, struct endpoint *ep)
{
spa_list_remove(&ep->link);
free(ep->media);
sm_object_remove_data((struct sm_object*)ep->obj, SESSION_KEY);
}
static int static int
handle_stream(struct impl *impl, struct sm_object *object) handle_stream(struct impl *impl, struct sm_object *object)
{ {
@ -202,6 +209,11 @@ handle_stream(struct impl *impl, struct sm_object *object)
return 0; return 0;
} }
static void destroy_stream(struct impl *impl, struct stream *s)
{
sm_object_remove_data((struct sm_object*)s->obj, SESSION_KEY);
}
static void session_create(void *data, struct sm_object *object) static void session_create(void *data, struct sm_object *object)
{ {
struct impl *impl = data; struct impl *impl = data;
@ -236,10 +248,15 @@ static void session_remove(void *data, struct sm_object *object)
case PW_TYPE_INTERFACE_Endpoint: case PW_TYPE_INTERFACE_Endpoint:
{ {
struct endpoint *ep; struct endpoint *ep;
if ((ep = sm_object_get_data(object, SESSION_KEY)) != NULL) { if ((ep = sm_object_get_data(object, SESSION_KEY)) != NULL)
spa_list_remove(&ep->link); destroy_endpoint(impl, ep);
free(ep->media); break;
} }
case PW_TYPE_INTERFACE_EndpointStream:
{
struct stream *s;
if ((s = sm_object_get_data(object, SESSION_KEY)) != NULL)
destroy_stream(impl, s);
break; break;
} }
default: default:
@ -490,20 +507,28 @@ static void session_rescan(void *data, int seq)
rescan_endpoint(impl, ep); rescan_endpoint(impl, ep);
} }
static void session_destroy(void *data)
{
struct impl *impl = data;
spa_hook_remove(&impl->listener);
free(impl);
}
static const struct sm_media_session_events session_events = { static const struct sm_media_session_events session_events = {
SM_VERSION_MEDIA_SESSION_EVENTS, SM_VERSION_MEDIA_SESSION_EVENTS,
.create = session_create, .create = session_create,
.remove = session_remove, .remove = session_remove,
.rescan = session_rescan, .rescan = session_rescan,
.destroy = session_destroy,
}; };
void *sm_policy_ep_start(struct sm_media_session *session) int sm_policy_ep_start(struct sm_media_session *session)
{ {
struct impl *impl; struct impl *impl;
impl = calloc(1, sizeof(struct impl)); impl = calloc(1, sizeof(struct impl));
if (impl == NULL) if (impl == NULL)
return NULL; return -errno;
impl->session = session; impl->session = session;
impl->context = session->context; impl->context = session->context;
@ -512,12 +537,5 @@ void *sm_policy_ep_start(struct sm_media_session *session)
sm_media_session_add_listener(impl->session, &impl->listener, &session_events, impl); sm_media_session_add_listener(impl->session, &impl->listener, &session_events, impl);
return impl;
}
int sm_policy_ep_stop(void *data)
{
struct impl *impl = data;
free(impl);
return 0; return 0;
} }

View file

@ -543,12 +543,13 @@ handle_node(struct impl *impl, struct sm_object *obj)
return 1; return 1;
} }
static void destroy_node(struct node *node) static void destroy_node(struct impl *impl, struct node *node)
{ {
if (node->endpoint) if (node->endpoint)
destroy_endpoint(node->endpoint); destroy_endpoint(node->endpoint);
free(node->media); free(node->media);
spa_hook_remove(&node->listener); spa_hook_remove(&node->listener);
sm_object_remove_data((struct sm_object*)node->obj, SESSION_KEY);
} }
static void session_create(void *data, struct sm_object *object) static void session_create(void *data, struct sm_object *object)
@ -573,12 +574,14 @@ static void session_create(void *data, struct sm_object *object)
static void session_remove(void *data, struct sm_object *object) static void session_remove(void *data, struct sm_object *object)
{ {
struct impl *impl = data;
switch (object->type) { switch (object->type) {
case PW_TYPE_INTERFACE_Node: case PW_TYPE_INTERFACE_Node:
{ {
struct node *node; struct node *node;
if ((node = sm_object_get_data(object, SESSION_KEY)) != NULL) if ((node = sm_object_get_data(object, SESSION_KEY)) != NULL)
destroy_node(node); destroy_node(impl, node);
break; break;
} }
default: default:
@ -586,29 +589,30 @@ static void session_remove(void *data, struct sm_object *object)
} }
} }
static void session_destroy(void *data)
{
struct impl *impl = data;
spa_hook_remove(&impl->listener);
free(impl);
}
static const struct sm_media_session_events session_events = { static const struct sm_media_session_events session_events = {
SM_VERSION_MEDIA_SESSION_EVENTS, SM_VERSION_MEDIA_SESSION_EVENTS,
.create = session_create, .create = session_create,
.remove = session_remove, .remove = session_remove,
.destroy = session_destroy,
}; };
void * sm_stream_endpoint_start(struct sm_media_session *session) int sm_stream_endpoint_start(struct sm_media_session *session)
{ {
struct impl *impl; struct impl *impl;
impl = calloc(1, sizeof(struct impl)); impl = calloc(1, sizeof(struct impl));
if (impl == NULL) if (impl == NULL)
return NULL; return -errno;
impl->session = session; impl->session = session;
sm_media_session_add_listener(session, &impl->listener, &session_events, impl); sm_media_session_add_listener(session, &impl->listener, &session_events, impl);
return impl;
}
int sm_stream_endpoint_stop(void *data)
{
struct impl *impl = data;
spa_hook_remove(&impl->listener);
return 0; return 0;
} }

View file

@ -354,7 +354,7 @@ static void proxy_destroy(void *data)
pw_properties_free(endpoint->props); pw_properties_free(endpoint->props);
spa_list_remove(&endpoint->link); spa_list_remove(&endpoint->link);
spa_hook_remove(&endpoint->proxy_listener); spa_hook_remove(&endpoint->proxy_listener);
spa_hook_remove(&endpoint->listener); spa_hook_remove(&endpoint->client_endpoint_listener);
} }
static void proxy_bound(void *data, uint32_t id) static void proxy_bound(void *data, uint32_t id)
@ -575,10 +575,11 @@ handle_device(struct impl *impl, struct sm_object *obj)
return 0; return 0;
} }
static void destroy_device(struct device *device) static void destroy_device(struct impl *impl, struct device *device)
{ {
deactivate_device(device); deactivate_device(device);
spa_hook_remove(&device->listener); spa_hook_remove(&device->listener);
sm_object_remove_data((struct sm_object*)device->device, SESSION_KEY);
} }
static void session_create(void *data, struct sm_object *object) static void session_create(void *data, struct sm_object *object)
@ -603,12 +604,14 @@ static void session_create(void *data, struct sm_object *object)
static void session_remove(void *data, struct sm_object *object) static void session_remove(void *data, struct sm_object *object)
{ {
struct impl *impl = data;
switch (object->type) { switch (object->type) {
case PW_TYPE_INTERFACE_Device: case PW_TYPE_INTERFACE_Device:
{ {
struct device *device; struct device *device;
if ((device = sm_object_get_data(object, SESSION_KEY)) != NULL) if ((device = sm_object_get_data(object, SESSION_KEY)) != NULL)
destroy_device(device); destroy_device(impl, device);
break; break;
} }
default: default:
@ -616,28 +619,30 @@ static void session_remove(void *data, struct sm_object *object)
} }
} }
static void session_destroy(void *data)
{
struct impl *impl = data;
spa_hook_remove(&impl->listener);
free(impl);
}
static const struct sm_media_session_events session_events = { static const struct sm_media_session_events session_events = {
SM_VERSION_MEDIA_SESSION_EVENTS, SM_VERSION_MEDIA_SESSION_EVENTS,
.create = session_create, .create = session_create,
.remove = session_remove, .remove = session_remove,
.destroy = session_destroy,
}; };
void *sm_v4l2_endpoint_start(struct sm_media_session *session) int sm_v4l2_endpoint_start(struct sm_media_session *session)
{ {
struct impl *impl; struct impl *impl;
impl = calloc(1, sizeof(struct impl)); impl = calloc(1, sizeof(struct impl));
if (impl == NULL) if (impl == NULL)
return NULL; return -errno;
impl->session = session; impl->session = session;
sm_media_session_add_listener(session, &impl->listener, &session_events, impl); sm_media_session_add_listener(session, &impl->listener, &session_events, impl);
return impl;
}
int sm_v4l2_endpoint_stop(void *data)
{
return 0; return 0;
} }

View file

@ -80,6 +80,7 @@ struct device {
struct impl { struct impl {
struct sm_media_session *session; struct sm_media_session *session;
struct spa_hook session_listener;
struct spa_handle *handle; struct spa_handle *handle;
struct spa_device *monitor; struct spa_device *monitor;
@ -181,6 +182,7 @@ static void v4l2_remove_node(struct device *dev, struct node *node)
pw_log_debug("remove node %u", node->id); pw_log_debug("remove node %u", node->id);
spa_list_remove(&node->link); spa_list_remove(&node->link);
pw_proxy_destroy(node->proxy); pw_proxy_destroy(node->proxy);
pw_properties_free(node->props);
free(node); free(node);
} }
@ -405,6 +407,7 @@ static void v4l2_remove_device(struct impl *impl, struct device *dev)
sm_object_destroy(&dev->sdevice->obj); sm_object_destroy(&dev->sdevice->obj);
spa_hook_remove(&dev->listener); spa_hook_remove(&dev->listener);
pw_unload_spa_handle(dev->handle); pw_unload_spa_handle(dev->handle);
pw_properties_free(dev->props);
free(dev); free(dev);
} }
@ -434,7 +437,21 @@ static const struct spa_device_events v4l2_udev_callbacks =
.object_info = v4l2_udev_object_info, .object_info = v4l2_udev_object_info,
}; };
void * sm_v4l2_monitor_start(struct sm_media_session *sess) static void session_destroy(void *data)
{
struct impl *impl = data;
spa_hook_remove(&impl->session_listener);
spa_hook_remove(&impl->listener);
pw_unload_spa_handle(impl->handle);
free(impl);
}
static const struct sm_media_session_events session_events = {
SM_VERSION_MEDIA_SESSION_EVENTS,
.destroy = session_destroy,
};
int sm_v4l2_monitor_start(struct sm_media_session *sess)
{ {
struct pw_context *context = sess->context; struct pw_context *context = sess->context;
struct impl *impl; struct impl *impl;
@ -443,7 +460,7 @@ void * sm_v4l2_monitor_start(struct sm_media_session *sess)
impl = calloc(1, sizeof(struct impl)); impl = calloc(1, sizeof(struct impl));
if (impl == NULL) if (impl == NULL)
return NULL; return -errno;
impl->session = sess; impl->session = sess;
@ -464,20 +481,13 @@ void * sm_v4l2_monitor_start(struct sm_media_session *sess)
spa_device_add_listener(impl->monitor, &impl->listener, spa_device_add_listener(impl->monitor, &impl->listener,
&v4l2_udev_callbacks, impl); &v4l2_udev_callbacks, impl);
return impl; sm_media_session_add_listener(sess, &impl->session_listener, &session_events, impl);
return 0;
out_unload: out_unload:
pw_unload_spa_handle(impl->handle); pw_unload_spa_handle(impl->handle);
out_free: out_free:
free(impl); free(impl);
errno = -res; return res;
return NULL;
}
int sm_v4l2_monitor_stop(void *data)
{
struct impl *impl = data;
pw_unload_spa_handle(impl->handle);
free(impl);
return 0;
} }