static void source_free(struct audio_device *dev) { struct source *source = dev->source; if (source->cb_id) avdtp_stream_remove_cb(source->session, source->stream, source->cb_id); if (source->session) avdtp_unref(source->session); if (source->connect_id > 0) { audio_source_connected(dev->btd_dev, -ECANCELED); a2dp_cancel(dev, source->connect_id); source->connect_id = 0; } if (source->disconnect_id > 0) { audio_source_disconnected(dev->btd_dev, -ECANCELED); a2dp_cancel(dev, source->disconnect_id); source->disconnect_id = 0; } if (source->retry_id) g_source_remove(source->retry_id); avdtp_remove_state_cb(source->avdtp_callback_id); g_free(source); dev->source = NULL; }
static void source_free(struct btd_service *service) { struct source *source = btd_service_get_user_data(service); if (source->cb_id) avdtp_stream_remove_cb(source->session, source->stream, source->cb_id); if (source->session) avdtp_unref(source->session); if (source->connect_id > 0) { btd_service_connecting_complete(source->service, -ECANCELED); a2dp_cancel(source->connect_id); source->connect_id = 0; } if (source->disconnect_id > 0) { btd_service_disconnecting_complete(source->service, -ECANCELED); a2dp_cancel(source->disconnect_id); source->disconnect_id = 0; } avdtp_remove_state_cb(source->avdtp_callback_id); btd_service_unref(source->service); g_free(source); }
static void sink_free(struct audio_device *dev) { struct sink *sink = dev->sink; if (sink->cb_id) avdtp_stream_remove_cb(sink->session, sink->stream, sink->cb_id); if (sink->session) avdtp_unref(sink->session); if (sink->connect_id > 0) { btd_service_connecting_complete(sink->service, -ECANCELED); a2dp_cancel(dev, sink->connect_id); sink->connect_id = 0; } if (sink->disconnect_id > 0) { btd_service_disconnecting_complete(sink->service, -ECANCELED); a2dp_cancel(dev, sink->disconnect_id); sink->disconnect_id = 0; } if (sink->retry_id) g_source_remove(sink->retry_id); avdtp_remove_state_cb(sink->avdtp_callback_id); btd_service_unref(sink->service); g_free(sink); dev->sink = NULL; }
int source_disconnect(struct btd_service *service) { struct source *source = btd_service_get_user_data(service); if (!source->session) return -ENOTCONN; /* cancel pending connect */ if (source->connect_id > 0) { a2dp_cancel(source->connect_id); source->connect_id = 0; btd_service_connecting_complete(source->service, -ECANCELED); avdtp_unref(source->session); source->session = NULL; return 0; } /* disconnect already ongoing */ if (source->disconnect_id > 0) return -EBUSY; if (!source->stream) return -ENOTCONN; return avdtp_close(source->session, source->stream, FALSE); }
int source_disconnect(struct audio_device *dev, gboolean shutdown) { struct source *source = dev->source; if (!source->session) return -ENOTCONN; if (shutdown) avdtp_set_device_disconnect(source->session, TRUE); /* cancel pending connect */ if (source->connect_id > 0) { a2dp_cancel(dev, source->connect_id); source->connect_id = 0; audio_source_connected(dev->btd_dev, -ECANCELED); avdtp_unref(source->session); source->session = NULL; return 0; } /* disconnect already ongoing */ if (source->disconnect_id > 0) return -EBUSY; if (!source->stream) return -ENOTCONN; return avdtp_close(source->session, source->stream, FALSE); }
int sink_disconnect(struct audio_device *dev, gboolean shutdown) { struct sink *sink = dev->sink; if (!sink->session) return -ENOTCONN; if (shutdown) avdtp_set_device_disconnect(sink->session, TRUE); /* cancel pending connect */ if (sink->connect_id > 0) { a2dp_cancel(dev, sink->connect_id); sink->connect_id = 0; btd_service_connecting_complete(sink->service, -ECANCELED); avdtp_unref(sink->session); sink->session = NULL; return 0; } /* disconnect already ongoing */ if (sink->disconnect_id > 0) return -EBUSY; if (!sink->stream) return -ENOTCONN; return avdtp_close(sink->session, sink->stream, FALSE); }
static void pending_request_free(struct audio_device *dev, struct pending_request *pending) { if (pending->conn) dbus_connection_unref(pending->conn); if (pending->msg) dbus_message_unref(pending->msg); if (pending->id) a2dp_cancel(dev, pending->id); g_free(pending); }
static void stream_state_changed(struct avdtp_stream *stream, avdtp_state_t old_state, avdtp_state_t new_state, struct avdtp_error *err, void *user_data) { struct btd_service *service = user_data; struct source *source = btd_service_get_user_data(service); if (err) return; switch (new_state) { case AVDTP_STATE_IDLE: btd_service_disconnecting_complete(source->service, 0); if (source->disconnect_id > 0) { a2dp_cancel(source->disconnect_id); source->disconnect_id = 0; } if (source->session) { avdtp_unref(source->session); source->session = NULL; } source->stream = NULL; source->cb_id = 0; break; case AVDTP_STATE_OPEN: btd_service_connecting_complete(source->service, 0); source_set_state(source, SOURCE_STATE_CONNECTED); break; case AVDTP_STATE_STREAMING: source_set_state(source, SOURCE_STATE_PLAYING); break; case AVDTP_STATE_CONFIGURED: case AVDTP_STATE_CLOSING: case AVDTP_STATE_ABORTING: default: break; } source->stream_state = new_state; }
static void stream_state_changed(struct avdtp_stream *stream, avdtp_state_t old_state, avdtp_state_t new_state, struct avdtp_error *err, void *user_data) { struct audio_device *dev = user_data; struct sink *sink = dev->sink; if (err) return; switch (new_state) { case AVDTP_STATE_IDLE: btd_service_disconnecting_complete(sink->service, 0); if (sink->disconnect_id > 0) { a2dp_cancel(dev, sink->disconnect_id); sink->disconnect_id = 0; } if (sink->session) { avdtp_unref(sink->session); sink->session = NULL; } sink->stream = NULL; sink->cb_id = 0; break; case AVDTP_STATE_OPEN: sink_set_state(dev, SINK_STATE_CONNECTED); break; case AVDTP_STATE_STREAMING: sink_set_state(dev, SINK_STATE_PLAYING); break; case AVDTP_STATE_CONFIGURED: case AVDTP_STATE_CLOSING: case AVDTP_STATE_ABORTING: default: break; } sink->stream_state = new_state; }
static gboolean stream_setup_retry(gpointer user_data) { struct source *source = user_data; int err; source->retry_id = 0; if (source->stream_state >= AVDTP_STATE_OPEN) { DBG("Stream successfully created, after XCASE connect:connect"); err = 0; } else { DBG("Stream setup failed, after XCASE connect:connect"); err = -EIO; } audio_source_connected(source->dev->btd_dev, err); if (source->connect_id > 0) { a2dp_cancel(source->dev, source->connect_id); source->connect_id = 0; } return FALSE; }
static gboolean stream_setup_retry(gpointer user_data) { struct sink *sink = user_data; int err; sink->retry_id = 0; if (sink->stream_state >= AVDTP_STATE_OPEN) { DBG("Stream successfully created, after XCASE connect:connect"); err = 0; } else { DBG("Stream setup failed, after XCASE connect:connect"); err = -EIO; } btd_service_connecting_complete(sink->service, err); if (sink->connect_id > 0) { a2dp_cancel(sink->dev, sink->connect_id); sink->connect_id = 0; } return FALSE; }
static void cancel_a2dp(struct media_transport *transport, guint id) { a2dp_cancel(transport->device, id); }