summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFederico Mena-Quintero <federico@ximian.com>2009-04-19 03:24:53 +0200
committerLennart Poettering <lennart@poettering.net>2009-04-19 03:24:53 +0200
commit9b75398f448af1a15a8e2859d0d115875e3b6fef (patch)
treee66c80637874e4d1eeadbb83e3d5adfae16e9be7
parentad95e65e46aba26adb125433cf9a10fe5d0275a5 (diff)
pulse: don't hang when operation gets canceled
Handle properly when a sample play operation gets canceled. http://bugs.freedesktop.org/show_bug.cgi?id=21263
-rw-r--r--src/canberra.h3
-rw-r--r--src/common.c3
-rw-r--r--src/pulse.c25
3 files changed, 27 insertions, 4 deletions
diff --git a/src/canberra.h b/src/canberra.h
index 9664ef2..b4ceb27 100644
--- a/src/canberra.h
+++ b/src/canberra.h
@@ -415,7 +415,8 @@ enum {
CA_ERROR_INTERNAL = -15,
CA_ERROR_DISABLED = -16,
CA_ERROR_FORKED = -17,
- _CA_ERROR_MAX = -18
+ CA_ERROR_DISCONNECTED = -18,
+ _CA_ERROR_MAX = -19
};
/**
diff --git a/src/common.c b/src/common.c
index ac8b982..e2548ec 100644
--- a/src/common.c
+++ b/src/common.c
@@ -663,7 +663,8 @@ const char *ca_strerror(int code) {
[-CA_ERROR_IO] = "IO error",
[-CA_ERROR_INTERNAL] = "Internal error",
[-CA_ERROR_DISABLED] = "Sound disabled",
- [-CA_ERROR_FORKED] = "Process forked"
+ [-CA_ERROR_FORKED] = "Process forked",
+ [-CA_ERROR_DISCONNECTED] = "Disconnected"
};
ca_return_val_if_fail(code <= 0, NULL);
diff --git a/src/pulse.c b/src/pulse.c
index 3cd4b2a..c959719 100644
--- a/src/pulse.c
+++ b/src/pulse.c
@@ -770,6 +770,8 @@ int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_cal
/* Ok, this sample has an event id, let's try to play it from the cache */
for (;;) {
+ ca_bool_t canceled;
+
pa_threaded_mainloop_lock(p->mainloop);
/* Let's try to play the sample */
@@ -779,16 +781,35 @@ int driver_play(ca_context *c, uint32_t id, ca_proplist *proplist, ca_finish_cal
goto finish;
}
- while (pa_operation_get_state(o) != PA_OPERATION_DONE)
+ for (;;) {
+ pa_operation_state_t state = pa_operation_get_state(o);
+
+ if (state == PA_OPERATION_DONE) {
+ canceled = FALSE;
+ break;
+ } else if (state == PA_OPERATION_CANCELED) {
+ canceled = TRUE;
+ break;
+ }
+
pa_threaded_mainloop_wait(p->mainloop);
+ }
pa_operation_unref(o);
pa_threaded_mainloop_unlock(p->mainloop);
+ /* The operation might have been canceled due to connection termination */
+ if (canceled) {
+ ret = CA_ERROR_DISCONNECTED;
+ goto finish;
+ }
+
/* Did we manage to play the sample or did some other error occur? */
- if (out->error != CA_ERROR_NOTFOUND)
+ if (out->error != CA_ERROR_NOTFOUND) {
+ ret = out->error;
goto finish;
+ }
/* Hmm, we need to play it directly */
if (cache_control != CA_CACHE_CONTROL_PERMANENT)