aboutsummaryrefslogtreecommitdiff
path: root/audio/sink.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2009-02-02 19:26:23 -0800
committerJohan Hedberg <johan.hedberg@nokia.com>2009-02-02 19:32:14 -0800
commit38ca09be34dbb514fa1194b9a164d1b63a74069b (patch)
tree8a5e533c31a9e1d286801adafd09aefb3cf6a6c1 /audio/sink.c
parent8b3e4cf9d9eaba3cfc5ec5361d136ebb84ab749f (diff)
downloadbluez-38ca09be34dbb514fa1194b9a164d1b63a74069b.tar.gz
Set up a stream for incoming connections if the sink doesn't do it
Some headsets when acting as initiators of an AVDTP connection create the AVDTP signaling channel but don't do anything else over it (i.e. they expect us to set up a stream when needed). This patch makes bluetoothd do the same as AudioSink.Connect() if no AVDTP commands have been received from the sink within one second after it has created the AVDTP signaling channel to us. Setting up a stream is also important because the AudioSink Connected property is bound to the existence of a configured stream (which makes sense since an AVDTP connection as such tells us nothing about what sinks and sources there are or even if audio or video will be used).
Diffstat (limited to 'audio/sink.c')
-rw-r--r--audio/sink.c79
1 files changed, 54 insertions, 25 deletions
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");