summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc-André Lureau <marc-andre.lureau@nokia.com>2009-04-08 19:02:39 +0300
committerMarc-André Lureau <marc-andre.lureau@nokia.com>2009-04-18 00:08:15 +0300
commitc7083f59e01b383ed9fe5e0b3e4cce1e7c665e68 (patch)
tree8c2e662b0e5f7046420b0f93a7137bd6f2414adc
parentc7c181b62ecb994bc9e58044c119ea278bfb2bcd (diff)
pulse: use nofail
-rw-r--r--src/pulse.c113
1 files changed, 81 insertions, 32 deletions
diff --git a/src/pulse.c b/src/pulse.c
index ed371de..c3e919d 100644
--- a/src/pulse.c
+++ b/src/pulse.c
@@ -76,6 +76,9 @@ struct private {
#define PRIVATE(c) ((struct private *) ((c)->private))
+static void context_state_cb(pa_context *pc, void *userdata);
+static void context_subscribe_cb(pa_context *pc, pa_subscription_event_type_t t, uint32_t idx, void *userdata);
+
static void outstanding_free(struct outstanding *o) {
ca_assert(o);
@@ -192,6 +195,43 @@ static int translate_error(int error) {
return table[error];
}
+static int context_connect(ca_context *c) {
+ pa_proplist *l;
+ struct private *p;
+ int ret;
+
+ ca_return_val_if_fail(c, CA_ERROR_INVALID);
+ ca_return_val_if_fail(p = c->private, CA_ERROR_STATE);
+ ca_return_val_if_fail(p->mainloop, CA_ERROR_STATE);
+ ca_return_val_if_fail(!p->context, CA_ERROR_STATE);
+
+ if ((ret = convert_proplist(&l, c->props)) < 0) {
+ driver_destroy(c);
+ return ret;
+ }
+
+ strip_prefix(l, "canberra.");
+
+ if (!(p->context = pa_context_new_with_proplist(pa_threaded_mainloop_get_api(p->mainloop), "libcanberra", l))) {
+ pa_proplist_free(l);
+ driver_destroy(c);
+ return CA_ERROR_OOM;
+ }
+
+ pa_proplist_free(l);
+
+ pa_context_set_state_callback(p->context, context_state_cb, c);
+ pa_context_set_subscribe_callback(p->context, context_subscribe_cb, c);
+
+ if (pa_context_connect(p->context, NULL, PA_CONTEXT_NOFAIL, NULL) < 0) {
+ ret = translate_error(pa_context_errno(p->context));
+ driver_destroy(c);
+ return ret;
+ }
+
+ return CA_SUCCESS;
+}
+
static void context_state_cb(pa_context *pc, void *userdata) {
ca_context *c = userdata;
pa_context_state_t state;
@@ -229,6 +269,17 @@ static void context_state_cb(pa_context *pc, void *userdata) {
}
ca_mutex_unlock(p->outstanding_mutex);
+
+ if (p->context) {
+ pa_context_disconnect(p->context);
+ pa_context_unref(p->context);
+ p->subscribed = FALSE;
+ p->context = NULL;
+ }
+
+ /* FIXME: recycle previous pa_context_proplist and restore state as much as possible? */
+ if (context_connect(c) != CA_SUCCESS)
+ return;
}
pa_threaded_mainloop_signal(p->mainloop, FALSE);
@@ -277,7 +328,6 @@ static void context_subscribe_cb(pa_context *pc, pa_subscription_event_type_t t,
}
int driver_open(ca_context *c) {
- pa_proplist *l;
struct private *p;
int ret;
@@ -299,29 +349,8 @@ int driver_open(ca_context *c) {
return CA_ERROR_OOM;
}
- if ((ret = convert_proplist(&l, c->props)) < 0) {
- driver_destroy(c);
- return ret;
- }
-
- strip_prefix(l, "canberra.");
-
- if (!(p->context = pa_context_new_with_proplist(pa_threaded_mainloop_get_api(p->mainloop), "libcanberra", l))) {
- pa_proplist_free(l);
- driver_destroy(c);
- return CA_ERROR_OOM;
- }
-
- pa_proplist_free(l);
-
- pa_context_set_state_callback(p->context, context_state_cb, c);
- pa_context_set_subscribe_callback(p->context, context_subscribe_cb, c);
-
- if (pa_context_connect(p->context, NULL, 0, NULL) < 0) {
- ret = translate_error(pa_context_errno(p->context));
- driver_destroy(c);
+ if ((ret = context_connect(c)) != CA_SUCCESS)
return ret;
- }
pa_threaded_mainloop_lock(p->mainloop);
@@ -421,15 +450,19 @@ int driver_change_props(ca_context *c, ca_proplist *changed, ca_proplist *merged
p = PRIVATE(c);
ca_return_val_if_fail(p->mainloop, CA_ERROR_STATE);
- ca_return_val_if_fail(p->context, CA_ERROR_STATE);
+
+ pa_threaded_mainloop_lock(p->mainloop);
+
+ if (!p->context) {
+ pa_threaded_mainloop_unlock(p->mainloop);
+ return CA_ERROR_STATE; /* can be silently ignored */
+ }
if ((ret = convert_proplist(&l, changed)) < 0)
return ret;
strip_prefix(l, "canberra.");
- pa_threaded_mainloop_lock(p->mainloop);
-
/* We start these asynchronously and don't care about the return
* value */
@@ -455,13 +488,17 @@ static int subscribe(ca_context *c) {
p = PRIVATE(c);
ca_return_val_if_fail(p->mainloop, CA_ERROR_STATE);
- ca_return_val_if_fail(p->context, CA_ERROR_STATE);
if (p->subscribed)
return CA_SUCCESS;
pa_threaded_mainloop_lock(p->mainloop);
+ if (!p->context) {
+ pa_threaded_mainloop_unlock(p->mainloop);
+ return CA_ERROR_STATE;
+ }
+
/* We start these asynchronously and don't care about the return
* value */
@@ -677,7 +714,6 @@ int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_cal
p = PRIVATE(c);
ca_return_val_if_fail(p->mainloop, CA_ERROR_STATE);
- ca_return_val_if_fail(p->context, CA_ERROR_STATE);
if (!(out = ca_new0(struct outstanding, 1))) {
ret = CA_ERROR_OOM;
@@ -820,8 +856,11 @@ int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_cal
break;
/* Check for failure */
- if (state == PA_STREAM_FAILED) {
- ret = translate_error(pa_context_errno(p->context));
+ if (state == PA_STREAM_FAILED) { /* it means it was disconnected */
+ if (pa_context_errno(p->context) == PA_OK) /* and context reconnected immediately */
+ ret = CA_ERROR_STATE;
+ else
+ ret = translate_error(pa_context_errno(p->context));
pa_threaded_mainloop_unlock(p->mainloop);
goto finish;
}
@@ -877,10 +916,14 @@ int driver_cancel(ca_context *c, uint32_t id) {
p = PRIVATE(c);
ca_return_val_if_fail(p->mainloop, CA_ERROR_STATE);
- ca_return_val_if_fail(p->context, CA_ERROR_STATE);
pa_threaded_mainloop_lock(p->mainloop);
+ if (!p->context) {
+ pa_threaded_mainloop_unlock(p->mainloop);
+ return CA_ERROR_STATE;
+ }
+
ca_mutex_lock(p->outstanding_mutex);
/* We start these asynchronously and don't care about the return
@@ -939,7 +982,6 @@ int driver_cache(ca_context *c, ca_proplist *proplist) {
p = PRIVATE(c);
ca_return_val_if_fail(p->mainloop, CA_ERROR_STATE);
- ca_return_val_if_fail(p->context, CA_ERROR_STATE);
if (!(out = ca_new0(struct outstanding, 1))) {
ret = CA_ERROR_OOM;
@@ -995,8 +1037,15 @@ int driver_cache(ca_context *c, ca_proplist *proplist) {
pa_threaded_mainloop_lock(p->mainloop);
+ if (!p->context) {
+ pa_threaded_mainloop_unlock(p->mainloop);
+ ret = CA_ERROR_STATE;
+ goto finish;
+ }
+
if (!(out->stream = pa_stream_new_with_proplist(p->context, name, &ss, NULL, l))) {
ret = translate_error(pa_context_errno(p->context));
+
pa_threaded_mainloop_unlock(p->mainloop);
goto finish;
}