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); | 
