summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
Diffstat (limited to 'audio')
-rw-r--r--audio/avdtp.c16
-rw-r--r--audio/sink.c79
-rw-r--r--audio/sink.h1
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);