diff --git a/src/examples/media-session/alsa-endpoint.c b/src/examples/media-session/alsa-endpoint.c index b46bd6b31..582edff4a 100644 --- a/src/examples/media-session/alsa-endpoint.c +++ b/src/examples/media-session/alsa-endpoint.c @@ -404,7 +404,7 @@ static void proxy_destroy(void *data) pw_properties_free(endpoint->props); spa_list_remove(&endpoint->link); 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) @@ -693,10 +693,11 @@ handle_device(struct impl *impl, struct sm_object *obj) return 0; } -static void destroy_device(struct device *device) +static void destroy_device(struct impl *impl, struct device *device) { deactivate_device(device); 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) @@ -721,12 +722,14 @@ static void session_create(void *data, struct sm_object *object) static void session_remove(void *data, struct sm_object *object) { + struct impl *impl = data; + switch (object->type) { case PW_TYPE_INTERFACE_Device: { struct device *device; if ((device = sm_object_get_data(object, SESSION_KEY)) != NULL) - destroy_device(device); + destroy_device(impl, device); break; } 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 = { SM_VERSION_MEDIA_SESSION_EVENTS, .create = session_create, .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; impl = calloc(1, sizeof(struct impl)); if (impl == NULL) - return NULL; + return -errno; impl->session = session; sm_media_session_add_listener(session, &impl->listener, &session_events, impl); - - return impl; -} - -int sm_alsa_endpoint_stop(void *data) -{ return 0; } diff --git a/src/examples/media-session/alsa-midi.c b/src/examples/media-session/alsa-midi.c index 502428651..9a9ad330c 100644 --- a/src/examples/media-session/alsa-midi.c +++ b/src/examples/media-session/alsa-midi.c @@ -39,26 +39,44 @@ struct impl { struct sm_media_session *session; + struct spa_hook listener; struct pw_properties *props; 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; + int res; impl = calloc(1, sizeof(struct impl)); if (impl == NULL) - return NULL; + return -errno; impl->session = session; impl->props = pw_properties_new( SPA_KEY_FACTORY_NAME, SPA_NAME_API_ALSA_SEQ_BRIDGE, SPA_KEY_NODE_NAME, "Midi-Bridge", NULL); - if (impl->props == NULL) + if (impl->props == NULL) { + res = -errno; goto cleanup; + } impl->proxy = sm_media_session_create_object(session, "spa-node-factory", @@ -67,23 +85,17 @@ void * sm_alsa_midi_start(struct sm_media_session *session) &impl->props->dict, 0); - if (impl->proxy == NULL) + if (impl->proxy == NULL) { + res = -errno; goto cleanup_props; + } + sm_media_session_add_listener(session, &impl->listener, &session_events, impl); - return impl; + return 0; cleanup_props: pw_properties_free(impl->props); cleanup: free(impl); - return NULL; -} - -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; + return res; } diff --git a/src/examples/media-session/alsa-monitor.c b/src/examples/media-session/alsa-monitor.c index 78c2e8eeb..19b527623 100644 --- a/src/examples/media-session/alsa-monitor.c +++ b/src/examples/media-session/alsa-monitor.c @@ -96,6 +96,7 @@ struct device { struct impl { struct sm_media_session *session; + struct spa_hook session_listener; 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); spa_list_remove(&node->link); sm_object_destroy(&node->snode->obj); + pw_properties_free(node->props); free(node); } @@ -484,8 +486,16 @@ static void sync_complete_done(void *data, int seq) 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 = { PW_VERSION_PROXY_EVENTS, + .destroy = sync_destroy, .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); spa_hook_remove(&device->listener); pw_unload_spa_handle(device->handle); + pw_properties_free(device->props); free(device); } @@ -710,7 +721,22 @@ static int alsa_start_jack_device(struct impl *impl) 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 impl *impl; @@ -719,7 +745,7 @@ void *sm_alsa_monitor_start(struct sm_media_session *session) impl = calloc(1, sizeof(struct impl)); if (impl == NULL) - return NULL; + return -errno; 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) goto out_unload; - return impl; + sm_media_session_add_listener(session, &impl->session_listener, &session_events, impl); + + return 0; out_unload: pw_unload_spa_handle(impl->handle); out_free: free(impl); - errno = -res; - return NULL; -} - -int sm_alsa_monitor_stop(void *data) -{ - struct impl *impl = data; - pw_unload_spa_handle(impl->handle); - free(impl); - return 0; + return res; } diff --git a/src/examples/media-session/bluez-monitor.c b/src/examples/media-session/bluez-monitor.c index cb35a4e66..28941aad6 100644 --- a/src/examples/media-session/bluez-monitor.c +++ b/src/examples/media-session/bluez-monitor.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ struct bluez5_object { struct impl { struct sm_media_session *session; + struct spa_hook session_listener; struct spa_handle *handle; @@ -294,6 +296,7 @@ static struct bluez5_object *bluez5_create_object(struct impl *impl, uint32_t id return obj; clean_object: + pw_properties_free(obj->props); free(obj); unload_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_unload_spa_handle(obj->handle); + pw_properties_free(obj->props); free(obj); } @@ -344,7 +348,21 @@ static const struct spa_device_events bluez5_enum_callbacks = .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 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); if (handle == NULL) { res = -errno; + pw_log_error("can't load %s: %m", SPA_NAME_API_BLUEZ5_ENUM_DBUS); goto out; } 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; } @@ -377,19 +396,13 @@ void *sm_bluez5_monitor_start(struct sm_media_session *session) spa_device_add_listener(impl->monitor, &impl->listener, &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; + +out_unload: + pw_unload_spa_handle(handle); +out: + return res; } diff --git a/src/examples/media-session/media-session.c b/src/examples/media-session/media-session.c index a74963f02..5dce8535b 100644 --- a/src/examples/media-session/media-session.c +++ b/src/examples/media-session/media-session.c @@ -53,20 +53,21 @@ #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_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_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_destroy(s) sm_media_session_emit(s, destroy, 0) -void * sm_stream_endpoint_start(struct sm_media_session *sess); -void * sm_metadata_start(struct sm_media_session *sess); -void * sm_alsa_midi_start(struct sm_media_session *sess); -void * sm_v4l2_monitor_start(struct sm_media_session *sess); -void * sm_v4l2_endpoint_start(struct sm_media_session *sess); -void * sm_bluez5_monitor_start(struct sm_media_session *sess); -void * sm_alsa_monitor_start(struct sm_media_session *sess); -void * sm_alsa_endpoint_start(struct sm_media_session *sess); +int sm_stream_endpoint_start(struct sm_media_session *sess); +int sm_metadata_start(struct sm_media_session *sess); +int sm_alsa_midi_start(struct sm_media_session *sess); +int sm_v4l2_monitor_start(struct sm_media_session *sess); +int sm_v4l2_endpoint_start(struct sm_media_session *sess); +int sm_bluez5_monitor_start(struct sm_media_session *sess); +int sm_alsa_monitor_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); /** user data to add to an object */ @@ -154,19 +155,25 @@ struct object_info { 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); + obj->id = id; + pw_log_debug("add %u %p", obj->id, obj); while (obj->id > size) pw_map_insert_at(&impl->globals, size++, NULL); pw_map_insert_at(&impl->globals, obj->id, obj); 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) { + pw_log_debug("remove %u %p", obj->id, obj); pw_map_insert_at(&impl->globals, obj->id, NULL); 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) @@ -637,15 +644,18 @@ static void session_destroy(void *object) { struct sm_session *sess = object; struct sm_endpoint *endpoint; - - if (sess->info) { - free(sess->info); - } + struct pw_session_info *i = sess->info; spa_list_consume(endpoint, &sess->endpoint_list, link) { endpoint->session = NULL; 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 = { @@ -725,12 +735,7 @@ static void endpoint_destroy(void *object) { struct sm_endpoint *endpoint = object; struct sm_endpoint_stream *stream; - - if (endpoint->info) { - free(endpoint->info->name); - free(endpoint->info->media_class); - free(endpoint->info); - } + struct pw_endpoint_info *i = endpoint->info; spa_list_consume(stream, &endpoint->stream_list, link) { stream->endpoint = NULL; @@ -740,6 +745,13 @@ static void endpoint_destroy(void *object) endpoint->session = NULL; 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 = { @@ -892,15 +904,27 @@ destroy_proxy(void *data) { struct sm_object *obj = data; 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); if (obj->destroy) 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) @@ -923,14 +947,10 @@ static void bound_proxy(void *data, uint32_t id) struct sm_object *obj = data; 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) { - obj->id = 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); - } + if (obj->id == SPA_ID_INVALID) + add_object(impl, obj, id); } 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) info->init(obj); - if (id != SPA_ID_INVALID) { - add_object(impl, obj); - sm_media_session_emit_create(impl, obj); - } + if (id != SPA_ID_INVALID) + add_object(impl, obj, id); + 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); obj->handle = obj->proxy; 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)) spa_hook_remove(&obj->object_listener); @@ -1636,18 +1656,20 @@ static int start_policy(struct impl *impl) } pw_core_add_listener(impl->policy_core, - &impl->policy_listener, - &core_events, impl); + &impl->policy_listener, + &core_events, impl); pw_proxy_add_listener((struct pw_proxy*)impl->policy_core, - &impl->proxy_policy_listener, - &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, - ®istry_events, impl); + &impl->proxy_policy_listener, + &proxy_core_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, + ®istry_events, impl); + + sm_policy_ep_start(&impl->this); + return 0; } int main(int argc, char *argv[]) @@ -1655,6 +1677,7 @@ int main(int argc, char *argv[]) struct impl impl = { 0, }; const struct spa_support *support; uint32_t n_support; + int res = 0; pw_init(&argc, &argv); @@ -1685,15 +1708,20 @@ int main(int argc, char *argv[]) else pw_log_debug("got dbus connection %p", impl.this.dbus_connection); - if (start_session(&impl) < 0) - return -1; - if (start_policy(&impl) < 0) - return -1; + if ((res = start_session(&impl)) < 0) + goto exit; + if ((res = start_policy(&impl)) < 0) + goto exit; pw_main_loop_run(impl.loop); +exit: + sm_media_session_emit_destroy(&impl); pw_context_destroy(impl.this.context); pw_main_loop_destroy(impl.loop); - return 0; + pw_map_clear(&impl.endpoint_links); + pw_map_clear(&impl.globals); + + return res; } diff --git a/src/examples/media-session/media-session.h b/src/examples/media-session/media-session.h index 59b34896e..d116958ea 100644 --- a/src/examples/media-session/media-session.h +++ b/src/examples/media-session/media-session.h @@ -67,6 +67,7 @@ struct sm_object { int pending; struct pw_proxy *handle; + struct spa_hook handle_listener; struct spa_hook_list hooks; struct spa_list data; @@ -200,6 +201,7 @@ struct sm_media_session_events { void (*remove) (void *data, struct sm_object *object); void (*rescan) (void *data, int seq); + void (*destroy) (void *data); }; struct sm_media_session { diff --git a/src/examples/media-session/metadata.c b/src/examples/media-session/metadata.c index edfbb2cc8..b25a90870 100644 --- a/src/examples/media-session/metadata.c +++ b/src/examples/media-session/metadata.c @@ -65,6 +65,8 @@ struct metadata { struct spa_interface iface; struct sm_media_session *session; + struct spa_hook session_listener; + struct spa_hook_list hooks; struct pw_properties *properties; @@ -180,11 +182,33 @@ struct pw_metadata_methods impl_metadata = { .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; + int res; md = calloc(1, sizeof(*md)); + if (md == NULL) + return -errno; + md->session = sess; md->properties = pw_properties_new(NULL, NULL); pw_array_init(&md->metadata, 4096); @@ -200,18 +224,18 @@ void *sm_metadata_start(struct sm_media_session *sess) NULL, md, 0); - return md; -} + if (md->proxy == NULL) { + res = -errno; + goto error_free; + } -int sm_metadata_stop(void *data) -{ - struct metadata *this = data; - - pw_proxy_destroy(this->proxy); - - clear_items(this); - pw_array_clear(&this->metadata); - pw_properties_free(this->properties); - free(this); + sm_media_session_add_listener(sess, &md->session_listener, + &session_events, md); return 0; + +error_free: + pw_array_clear(&md->metadata); + pw_properties_free(md->properties); + free(md); + return res; } diff --git a/src/examples/media-session/policy-ep.c b/src/examples/media-session/policy-ep.c index 52b41c207..9f4a01f29 100644 --- a/src/examples/media-session/policy-ep.c +++ b/src/examples/media-session/policy-ep.c @@ -179,6 +179,13 @@ handle_endpoint(struct impl *impl, struct sm_object *object) 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 handle_stream(struct impl *impl, struct sm_object *object) { @@ -202,6 +209,11 @@ handle_stream(struct impl *impl, struct sm_object *object) 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) { struct impl *impl = data; @@ -236,10 +248,15 @@ static void session_remove(void *data, struct sm_object *object) case PW_TYPE_INTERFACE_Endpoint: { struct endpoint *ep; - if ((ep = sm_object_get_data(object, SESSION_KEY)) != NULL) { - spa_list_remove(&ep->link); - free(ep->media); - } + if ((ep = sm_object_get_data(object, SESSION_KEY)) != NULL) + destroy_endpoint(impl, ep); + break; + } + case PW_TYPE_INTERFACE_EndpointStream: + { + struct stream *s; + if ((s = sm_object_get_data(object, SESSION_KEY)) != NULL) + destroy_stream(impl, s); break; } default: @@ -490,20 +507,28 @@ static void session_rescan(void *data, int seq) 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 = { SM_VERSION_MEDIA_SESSION_EVENTS, .create = session_create, .remove = session_remove, .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; impl = calloc(1, sizeof(struct impl)); if (impl == NULL) - return NULL; + return -errno; impl->session = session; 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); - return impl; -} - -int sm_policy_ep_stop(void *data) -{ - struct impl *impl = data; - free(impl); return 0; } diff --git a/src/examples/media-session/stream-endpoint.c b/src/examples/media-session/stream-endpoint.c index 44bc563c5..e35665364 100644 --- a/src/examples/media-session/stream-endpoint.c +++ b/src/examples/media-session/stream-endpoint.c @@ -543,12 +543,13 @@ handle_node(struct impl *impl, struct sm_object *obj) return 1; } -static void destroy_node(struct node *node) +static void destroy_node(struct impl *impl, struct node *node) { if (node->endpoint) destroy_endpoint(node->endpoint); free(node->media); 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) @@ -573,12 +574,14 @@ static void session_create(void *data, struct sm_object *object) static void session_remove(void *data, struct sm_object *object) { + struct impl *impl = data; + switch (object->type) { case PW_TYPE_INTERFACE_Node: { struct node *node; if ((node = sm_object_get_data(object, SESSION_KEY)) != NULL) - destroy_node(node); + destroy_node(impl, node); break; } 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 = { SM_VERSION_MEDIA_SESSION_EVENTS, .create = session_create, .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; impl = calloc(1, sizeof(struct impl)); if (impl == NULL) - return NULL; + return -errno; impl->session = session; 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; } diff --git a/src/examples/media-session/v4l2-endpoint.c b/src/examples/media-session/v4l2-endpoint.c index cd62efba9..96fa58dd6 100644 --- a/src/examples/media-session/v4l2-endpoint.c +++ b/src/examples/media-session/v4l2-endpoint.c @@ -354,7 +354,7 @@ static void proxy_destroy(void *data) pw_properties_free(endpoint->props); spa_list_remove(&endpoint->link); 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) @@ -575,10 +575,11 @@ handle_device(struct impl *impl, struct sm_object *obj) return 0; } -static void destroy_device(struct device *device) +static void destroy_device(struct impl *impl, struct device *device) { deactivate_device(device); 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) @@ -603,12 +604,14 @@ static void session_create(void *data, struct sm_object *object) static void session_remove(void *data, struct sm_object *object) { + struct impl *impl = data; + switch (object->type) { case PW_TYPE_INTERFACE_Device: { struct device *device; if ((device = sm_object_get_data(object, SESSION_KEY)) != NULL) - destroy_device(device); + destroy_device(impl, device); break; } 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 = { SM_VERSION_MEDIA_SESSION_EVENTS, .create = session_create, .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; impl = calloc(1, sizeof(struct impl)); if (impl == NULL) - return NULL; + return -errno; impl->session = session; sm_media_session_add_listener(session, &impl->listener, &session_events, impl); - return impl; -} - -int sm_v4l2_endpoint_stop(void *data) -{ return 0; } diff --git a/src/examples/media-session/v4l2-monitor.c b/src/examples/media-session/v4l2-monitor.c index 6b6c43d4f..a7b8d6939 100644 --- a/src/examples/media-session/v4l2-monitor.c +++ b/src/examples/media-session/v4l2-monitor.c @@ -80,6 +80,7 @@ struct device { struct impl { struct sm_media_session *session; + struct spa_hook session_listener; struct spa_handle *handle; 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); spa_list_remove(&node->link); pw_proxy_destroy(node->proxy); + pw_properties_free(node->props); free(node); } @@ -405,6 +407,7 @@ static void v4l2_remove_device(struct impl *impl, struct device *dev) sm_object_destroy(&dev->sdevice->obj); spa_hook_remove(&dev->listener); pw_unload_spa_handle(dev->handle); + pw_properties_free(dev->props); free(dev); } @@ -434,7 +437,21 @@ static const struct spa_device_events v4l2_udev_callbacks = .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 impl *impl; @@ -443,7 +460,7 @@ void * sm_v4l2_monitor_start(struct sm_media_session *sess) impl = calloc(1, sizeof(struct impl)); if (impl == NULL) - return NULL; + return -errno; 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, &v4l2_udev_callbacks, impl); - return impl; + sm_media_session_add_listener(sess, &impl->session_listener, &session_events, impl); + + return 0; out_unload: pw_unload_spa_handle(impl->handle); out_free: free(impl); - errno = -res; - return NULL; -} - -int sm_v4l2_monitor_stop(void *data) -{ - struct impl *impl = data; - pw_unload_spa_handle(impl->handle); - free(impl); - return 0; + return res; }