2010-11-11 09:40:24

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH 1/2] Remove a2dp setup callbacks after they return

From: Luiz Augusto von Dentz <[email protected]>

Since the callback won't be ever called again it make no sense to keep
them, also this cause a2dp_cancel to assume there are still some pending
callbacks to be processed and do not abort when it should.
---
audio/a2dp.c | 55 +++++++++++++++++++++++++++++++++++--------------------
1 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/audio/a2dp.c b/audio/a2dp.c
index 3aaf022..a55020d 100644
--- a/audio/a2dp.c
+++ b/audio/a2dp.c
@@ -160,15 +160,18 @@ static gboolean finalize_config(struct a2dp_setup *s)
struct avdtp_stream *stream = s->err ? NULL : s->stream;

setup_ref(s);
- for (l = s->cb; l != NULL; l = l->next) {
+ for (l = s->cb; l != NULL; ){
struct a2dp_setup_cb *cb = l->data;

+ l = l->next;
+
if (!cb->config_cb)
continue;

cb->config_cb(s->session, s->sep, stream, s->err,
cb->user_data);
- cb->config_cb = NULL;
+ s->cb = g_slist_remove(s->cb, cb);
+ g_free(cb);
setup_unref(s);
}

@@ -193,14 +196,18 @@ static gboolean finalize_resume(struct a2dp_setup *s)

setup_ref(s);

- for (l = s->cb; l != NULL; l = l->next) {
+ for (l = s->cb; l != NULL; ) {
struct a2dp_setup_cb *cb = l->data;

- if (cb && cb->resume_cb) {
- cb->resume_cb(s->session, s->err, cb->user_data);
- cb->resume_cb = NULL;
- setup_unref(s);
- }
+ l = l->next;
+
+ if (!cb->resume_cb)
+ continue;
+
+ cb->resume_cb(s->session, s->err, cb->user_data);
+ s->cb = g_slist_remove(s->cb, cb);
+ g_free(cb);
+ setup_unref(s);
}

setup_unref(s);
@@ -213,14 +220,18 @@ static gboolean finalize_suspend(struct a2dp_setup *s)
GSList *l;

setup_ref(s);
- for (l = s->cb; l != NULL; l = l->next) {
+ for (l = s->cb; l != NULL; ) {
struct a2dp_setup_cb *cb = l->data;

- if (cb->suspend_cb) {
- cb->suspend_cb(s->session, s->err, cb->user_data);
- cb->suspend_cb = NULL;
- setup_unref(s);
- }
+ l = l->next;
+
+ if (!cb->suspend_cb)
+ continue;
+
+ cb->suspend_cb(s->session, s->err, cb->user_data);
+ s->cb = g_slist_remove(s->cb, cb);
+ g_free(cb);
+ setup_unref(s);
}

setup_unref(s);
@@ -242,14 +253,18 @@ static gboolean finalize_select(struct a2dp_setup *s, GSList *caps)
GSList *l;

setup_ref(s);
- for (l = s->cb; l != NULL; l = l->next) {
+ for (l = s->cb; l != NULL; ) {
struct a2dp_setup_cb *cb = l->data;

- if (cb->select_cb) {
- cb->select_cb(s->session, s->sep, caps, cb->user_data);
- cb->select_cb = NULL;
- setup_unref(s);
- }
+ l = l->next;
+
+ if (!cb->select_cb)
+ continue;
+
+ cb->select_cb(s->session, s->sep, caps, cb->user_data);
+ s->cb = g_slist_remove(s->cb, cb);
+ g_free(cb);
+ setup_unref(s);
}

setup_unref(s);
--
1.7.1



2010-11-11 10:36:45

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 1/2] Remove a2dp setup callbacks after they return

Hi Luiz,

On Thu, Nov 11, 2010, Luiz Augusto von Dentz wrote:
> From: Luiz Augusto von Dentz <[email protected]>
>
> Since the callback won't be ever called again it make no sense to keep
> them, also this cause a2dp_cancel to assume there are still some pending
> callbacks to be processed and do not abort when it should.
> ---
> audio/a2dp.c | 55 +++++++++++++++++++++++++++++++++++--------------------
> 1 files changed, 35 insertions(+), 20 deletions(-)

Both patches have been pushed upstream. Thanks.

Johan

2010-11-11 09:40:25

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: [PATCH 2/2] Fix not aborting sink stream configuration on disconnect

From: Luiz Augusto von Dentz <[email protected]>

If stream configuration is not complete it should be aborted so we can
proceed with disconnection process.
---
audio/sink.c | 28 +++++++++++++++++++++++++++-
1 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/audio/sink.c b/audio/sink.c
index a9f6307..cb3ca74 100644
--- a/audio/sink.c
+++ b/audio/sink.c
@@ -351,6 +351,12 @@ static void discovery_complete(struct avdtp *session, GSList *seps, struct avdtp
struct pending_request *pending;
int id;

+ if (!sink->connect) {
+ avdtp_unref(sink->session);
+ sink->session = NULL;
+ return;
+ }
+
pending = sink->connect;

if (err) {
@@ -669,11 +675,31 @@ gboolean sink_new_stream(struct audio_device *dev, struct avdtp *session,

gboolean sink_shutdown(struct sink *sink)
{
- if (!sink->stream)
+ if (!sink->session)
return FALSE;

avdtp_set_device_disconnect(sink->session, TRUE);

+ /* cancel pending connect */
+ if (sink->connect) {
+ struct pending_request *pending = sink->connect;
+
+ if (pending->msg)
+ error_failed(pending->conn, pending->msg,
+ "Stream setup failed");
+ pending_request_free(sink->dev, pending);
+ sink->connect = NULL;
+
+ return TRUE;
+ }
+
+ /* disconnect already ongoing */
+ if (sink->disconnect)
+ return TRUE;
+
+ if (!sink->stream)
+ return FALSE;
+
if (avdtp_close(sink->session, sink->stream, FALSE) < 0)
return FALSE;

--
1.7.1