diff options
-rw-r--r-- | audio/avdtp.c | 16 | ||||
-rw-r--r-- | audio/sink.c | 79 | ||||
-rw-r--r-- | audio/sink.h | 1 |
3 files changed, 70 insertions, 26 deletions
diff --git a/audio/avdtp.c b/audio/avdtp.c index d1cb5ef3..a45b7d28 100644 --- a/audio/avdtp.c +++ b/audio/avdtp.c @@ -391,6 +391,9 @@ struct avdtp { guint dc_timer; + /* Attempt stream setup instead of disconnecting */ + gboolean stream_setup; + DBusPendingCall *pending_auth; }; @@ -597,12 +600,21 @@ static gboolean stream_open_timeout(gpointer user_data) static gboolean disconnect_timeout(gpointer user_data) { struct avdtp *session = user_data; + struct audio_device *dev; + gboolean stream_setup; assert(session->ref == 1); session->dc_timer = 0; + stream_setup = session->stream_setup; + session->stream_setup = FALSE; - connection_lost(session, -ETIMEDOUT); + dev = manager_get_device(&session->server->src, &session->dst); + + if (dev && dev->sink && stream_setup) + sink_setup_stream(dev->sink, session); + else + connection_lost(session, -ETIMEDOUT); return FALSE; } @@ -611,6 +623,7 @@ static void remove_disconnect_timer(struct avdtp *session) { g_source_remove(session->dc_timer); session->dc_timer = 0; + session->stream_setup = FALSE; } static void set_disconnect_timer(struct avdtp *session) @@ -2963,6 +2976,7 @@ static void auth_cb(DBusError *derr, void *user_data) /* Here we set the disconnect timer so we don't stay in IDLE state * indefinitely but set auto_dc to FALSE so that when a stream is * finally opened it doesn't get closed due to a timeout */ + session->stream_setup = TRUE; set_disconnect_timer(session); avdtp_set_auto_disconnect(session, FALSE); diff --git a/audio/sink.c b/audio/sink.c index 347e3f69..44faacf0 100644 --- a/audio/sink.c +++ b/audio/sink.c @@ -164,13 +164,16 @@ static gboolean stream_setup_retry(gpointer user_data) struct pending_request *pending = sink->connect; if (sink->state >= AVDTP_STATE_OPEN) { - DBusMessage *reply; debug("Stream successfully created, after XCASE connect:connect"); - reply = dbus_message_new_method_return(pending->msg); - g_dbus_send_message(pending->conn, reply); + if (pending->msg) { + DBusMessage *reply; + reply = dbus_message_new_method_return(pending->msg); + g_dbus_send_message(pending->conn, reply); + } } else { debug("Stream setup failed, after XCASE connect:connect"); - error_failed(pending->conn, pending->msg, "Stream setup failed"); + if (pending->msg) + error_failed(pending->conn, pending->msg, "Stream setup failed"); } sink->connect = NULL; @@ -189,26 +192,33 @@ static void stream_setup_complete(struct avdtp *session, struct a2dp_sep *sep, pending = sink->connect; if (stream) { - DBusMessage *reply; + debug("Stream successfully created"); + + if (pending->msg) { + DBusMessage *reply; + reply = dbus_message_new_method_return(pending->msg); + g_dbus_send_message(pending->conn, reply); + } + sink->connect = NULL; - reply = dbus_message_new_method_return(pending->msg); - g_dbus_send_message(pending->conn, reply); pending_request_free(pending); - debug("Stream successfully created"); + + return; + } + + avdtp_unref(sink->session); + sink->session = NULL; + if (avdtp_error_type(err) == AVDTP_ERROR_ERRNO + && avdtp_error_posix_errno(err) != EHOSTDOWN) { + debug("connect:connect XCASE detected"); + g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER, + stream_setup_retry, sink); } else { - avdtp_unref(sink->session); - sink->session = NULL; - if (avdtp_error_type(err) == AVDTP_ERROR_ERRNO - && avdtp_error_posix_errno(err) != EHOSTDOWN) { - debug("connect:connect XCASE detected"); - g_timeout_add_seconds(STREAM_SETUP_RETRY_TIMER, - stream_setup_retry, sink); - } else { - sink->connect = NULL; + if (pending->msg) error_failed(pending->conn, pending->msg, "Stream setup failed"); - pending_request_free(pending); - debug("Stream setup failed : %s", avdtp_strerror(err)); - } + sink->connect = NULL; + pending_request_free(pending); + debug("Stream setup failed : %s", avdtp_strerror(err)); } } @@ -395,13 +405,30 @@ static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp return; failed: - error_failed(pending->conn, pending->msg, "Stream setup failed"); + if (pending->msg) + error_failed(pending->conn, pending->msg, "Stream setup failed"); pending_request_free(pending); sink->connect = NULL; avdtp_unref(sink->session); sink->session = NULL; } +gboolean sink_setup_stream(struct sink *sink, struct avdtp *session) +{ + if (sink->connect || sink->disconnect) + return FALSE; + + if (session && !sink->session) + sink->session = avdtp_ref(session); + + if (avdtp_discover(sink->session, discovery_complete, sink) < 0) + return FALSE; + + sink->connect = g_new0(struct pending_request, 1); + + return TRUE; +} + static DBusMessage *sink_connect(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -427,12 +454,14 @@ static DBusMessage *sink_connect(DBusConnection *conn, avdtp_set_auto_disconnect(sink->session, FALSE); - pending = g_new0(struct pending_request, 1); + if (!sink_setup_stream(sink, NULL)) + return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", + "Failed to create a stream"); + + pending = sink->connect; + pending->conn = dbus_connection_ref(conn); pending->msg = dbus_message_ref(msg); - sink->connect = pending; - - avdtp_discover(sink->session, discovery_complete, sink); debug("stream creation in progress"); diff --git a/audio/sink.h b/audio/sink.h index a665e560..8bd6bef1 100644 --- a/audio/sink.h +++ b/audio/sink.h @@ -30,3 +30,4 @@ gboolean sink_is_active(struct audio_device *dev); avdtp_state_t sink_get_state(struct audio_device *dev); gboolean sink_new_stream(struct audio_device *dev, struct avdtp *session, struct avdtp_stream *stream); +gboolean sink_setup_stream(struct sink *sink, struct avdtp *session); |