diff --git a/audio/a2dp.c b/audio/a2dp.c
index 1208ad1..d51276d 100644
--- a/audio/a2dp.c
+++ b/audio/a2dp.c
g_free(cb);
}
-static gboolean finalize_config(struct a2dp_setup *s)
+static void finalize_setup_errno(struct a2dp_setup *s, int err,
+ GSourceFunc cb1, ...)
{
+ GSourceFunc finalize;
+ va_list args;
+ struct avdtp_error avdtp_err;
+
+ if (err < 0) {
+ avdtp_error_init(&avdtp_err, AVDTP_ERRNO, -err);
+ s->err = &avdtp_err;
+ }
+
+ va_start(args, cb1);
+ finalize = cb1;
+ setup_ref(s);
+ while (finalize != NULL) {
+ finalize(s);
+ finalize = va_arg(args, GSourceFunc);
+ }
+ setup_unref(s);
+ va_end(args);
+}
+
+static gboolean finalize_config(gpointer data)
+{
+ struct a2dp_setup *s = data;
GSList *l;
struct avdtp_stream *stream = s->err ? NULL : s->stream;
return FALSE;
}
-static gboolean finalize_config_errno(struct a2dp_setup *s, int err)
-{
- struct avdtp_error avdtp_err;
-
- avdtp_error_init(&avdtp_err, AVDTP_ERRNO, -err);
- s->err = err ? &avdtp_err : NULL;
-
- return finalize_config(s);
-}
-
-static gboolean finalize_resume(struct a2dp_setup *s)
+static gboolean finalize_resume(gpointer data)
{
+ struct a2dp_setup *s = data;
GSList *l;
for (l = s->cb; l != NULL; ) {
return FALSE;
}
-static gboolean finalize_resume_errno(struct a2dp_setup *s, int err)
-{
- struct avdtp_error avdtp_err;
-
- avdtp_error_init(&avdtp_err, AVDTP_ERRNO, -err);
- s->err = err ? &avdtp_err : NULL;
-
- return finalize_resume(s);
-}
-
-static gboolean finalize_suspend(struct a2dp_setup *s)
+static gboolean finalize_suspend(gpointer data)
{
+ struct a2dp_setup *s = data;
GSList *l;
for (l = s->cb; l != NULL; ) {
return FALSE;
}
-static gboolean finalize_suspend_errno(struct a2dp_setup *s, int err)
-{
- struct avdtp_error avdtp_err;
-
- avdtp_error_init(&avdtp_err, AVDTP_ERRNO, -err);
- s->err = err ? &avdtp_err : NULL;
-
- return finalize_suspend(s);
-}
-
-static gboolean finalize_select(struct a2dp_setup *s)
+static void finalize_select(struct a2dp_setup *s)
{
GSList *l;
cb->select_cb(s->session, s->sep, s->caps, cb->user_data);
setup_cb_free(cb);
}
-
- return FALSE;
}
static struct a2dp_setup *find_setup_by_session(struct avdtp *session)
if (ret == NULL) {
setup->stream = NULL;
- finalize_config_errno(setup, -EPERM);
+ finalize_setup_errno(setup, -EPERM, finalize_config);
return;
}
error("Error on avdtp_open %s (%d)", strerror(-err), -err);
setup->stream = NULL;
- finalize_config_errno(setup, err);
+ finalize_setup_errno(setup, err, finalize_config);
}
static void setconf_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
return;
setup->stream = NULL;
- finalize_config_errno(setup, -EPERM);
+ finalize_setup_errno(setup, -EPERM, finalize_config);
return;
}
if (ret < 0) {
error("Error on avdtp_open %s (%d)", strerror(-ret), -ret);
setup->stream = NULL;
- finalize_config_errno(setup, ret);
+ finalize_setup_errno(setup, ret, finalize_config);
}
}
perr = avdtp_start(session, a2dp_sep->stream);
if (perr < 0) {
error("Error on avdtp_start %s (%d)", strerror(-perr), -perr);
- finalize_resume_errno(setup, perr);
+ finalize_setup_errno(setup, -EIO, finalize_suspend);
}
}
if (!setup)
return TRUE;
- finalize_suspend_errno(setup, -ECONNRESET);
- finalize_resume_errno(setup, -ECONNRESET);
+ finalize_setup_errno(setup, -ECONNRESET, finalize_suspend,
+ finalize_resume);
return TRUE;
}
return FALSE;
failed:
- finalize_config_errno(setup, posix_err);
+ finalize_setup_errno(setup, posix_err, finalize_config);
return FALSE;
}
case AVDTP_STATE_STREAMING:
if (avdtp_stream_has_capabilities(setup->stream, caps)) {
DBG("Configuration match: resuming");
- g_idle_add((GSourceFunc) finalize_config, setup);
+ g_idle_add(finalize_config, setup);
} else if (!setup->reconfigure) {
setup->reconfigure = TRUE;
if (avdtp_close(session, sep->stream, FALSE) < 0) {
if (sep->suspending)
setup->start = TRUE;
else
- g_idle_add((GSourceFunc) finalize_resume, setup);
+ g_idle_add(finalize_resume, setup);
break;
default:
error("SEP in bad state for resume");
goto failed;
break;
case AVDTP_STATE_OPEN:
- g_idle_add((GSourceFunc) finalize_suspend, setup);
+ g_idle_add(finalize_suspend, setup);
break;
case AVDTP_STATE_STREAMING:
if (avdtp_suspend(session, sep->stream) < 0) {