diff --git a/spa/plugins/bluez5/backend-native.c b/spa/plugins/bluez5/backend-native.c index b60b7213e..1e6b6ecc7 100644 --- a/spa/plugins/bluez5/backend-native.c +++ b/spa/plugins/bluez5/backend-native.c @@ -88,6 +88,7 @@ struct rfcomm { struct spa_source source; struct impl *backend; struct spa_bt_device *device; + struct spa_hook device_listener; struct spa_bt_transport *transport; struct spa_hook transport_listener; enum spa_bt_profile profile; @@ -174,8 +175,18 @@ static void rfcomm_free(struct rfcomm *rfcomm) spa_hook_remove(&rfcomm->transport_listener); spa_bt_transport_free(rfcomm->transport); } - if (rfcomm->device) + if (rfcomm->device) { spa_bt_device_report_battery_level(rfcomm->device, SPA_BT_NO_BATTERY); + spa_hook_remove(&rfcomm->device_listener); + rfcomm->device = NULL; + } + if (rfcomm->source.fd >= 0) { + if (rfcomm->source.loop) + spa_loop_remove_source(rfcomm->source.loop, &rfcomm->source); + shutdown(rfcomm->source.fd, SHUT_RDWR); + close (rfcomm->source.fd); + rfcomm->source.fd = -1; + } free(rfcomm); } @@ -664,8 +675,6 @@ static void rfcomm_event(struct spa_source *source) if (source->rmask & (SPA_IO_HUP | SPA_IO_ERR)) { spa_log_info(backend->log, NAME": lost RFCOMM connection."); - if (source->loop) - spa_loop_remove_source(source->loop, source); rfcomm_free(rfcomm); return; } @@ -1157,6 +1166,17 @@ static int backend_native_ensure_codec(void *data, struct spa_bt_device *device, #endif } +static void device_destroy(void *data) +{ + struct rfcomm *rfcomm = data; + rfcomm_free(rfcomm); +} + +static const struct spa_bt_device_events device_events = { + SPA_VERSION_BT_DEVICE_EVENTS, + .destroy = device_destroy, +}; + static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessage *m, void *userdata) { struct impl *backend = userdata; @@ -1221,6 +1241,10 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag rfcomm->source.mask = SPA_IO_IN; rfcomm->source.rmask = 0; + spa_bt_device_add_listener(d, &rfcomm->device_listener, &device_events, rfcomm); + spa_loop_add_source(backend->main_loop, &rfcomm->source); + spa_list_append(&backend->rfcomm_list, &rfcomm->link); + if (d->settings && (str = spa_dict_lookup(d->settings, "bluez5.msbc-support"))) rfcomm->msbc_support_enabled_in_config = strcmp(str, "true") == 0 || atoi(str) == 1; else @@ -1270,9 +1294,6 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag goto fail_need_memory; dbus_message_unref(r); - spa_loop_add_source(backend->main_loop, &rfcomm->source); - spa_list_append(&backend->rfcomm_list, &rfcomm->link); - return DBUS_HANDLER_RESULT_HANDLED; fail_need_memory: @@ -1326,11 +1347,6 @@ static DBusHandlerResult profile_request_disconnection(DBusConnection *conn, DBu spa_list_for_each_safe(rfcomm, rfcomm_tmp, &backend->rfcomm_list, link) { if (rfcomm->device == d && rfcomm->profile == profile) { - if (rfcomm->source.loop) - spa_loop_remove_source(rfcomm->source.loop, &rfcomm->source); - shutdown(rfcomm->source.fd, SHUT_RDWR); - close (rfcomm->source.fd); - rfcomm->source.fd = -1; rfcomm_free(rfcomm); } } diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c index c9bc6c980..0253b9d4e 100644 --- a/spa/plugins/bluez5/bluez5-dbus.c +++ b/spa/plugins/bluez5/bluez5-dbus.c @@ -675,6 +675,8 @@ static void device_free(struct spa_bt_device *device) spa_log_debug(monitor->log, "%p", device); + spa_bt_device_emit_destroy(device); + battery_remove(device); device_stop_timer(device); diff --git a/spa/plugins/bluez5/defs.h b/spa/plugins/bluez5/defs.h index 2b45e1828..2fa056b13 100644 --- a/spa/plugins/bluez5/defs.h +++ b/spa/plugins/bluez5/defs.h @@ -386,6 +386,9 @@ struct spa_bt_device_events { /** Profile configuration changed */ void (*profiles_changed) (void *data, uint32_t prev_profiles, uint32_t prev_connected); + + /** Device freed */ + void (*destroy) (void *data); }; struct spa_bt_device { @@ -446,6 +449,7 @@ int spa_bt_device_report_battery_level(struct spa_bt_device *device, uint8_t per #define spa_bt_device_emit_connected(d,...) spa_bt_device_emit(d, connected, 0, __VA_ARGS__) #define spa_bt_device_emit_codec_switched(d,...) spa_bt_device_emit(d, codec_switched, 0, __VA_ARGS__) #define spa_bt_device_emit_profiles_changed(d,...) spa_bt_device_emit(d, profiles_changed, 0, __VA_ARGS__) +#define spa_bt_device_emit_destroy(d) spa_bt_device_emit(d, destroy, 0) #define spa_bt_device_add_listener(d,listener,events,data) \ spa_hook_list_append(&(d)->listener_list, listener, events, data)