- Add new API `pa_operation_set_cancel_callback` for users to set cancelation callbacks. --- src/pulse/context.c | 9 +++++++-- src/pulse/internal.h | 3 +++ src/pulse/operation.c | 25 ++++++++++++++++++++++++- src/pulse/operation.h | 7 +++++++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index 4618635..1ce2738 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -199,8 +199,13 @@ static void context_unlink(pa_context *c) { s = n; } - while (c->operations) - pa_operation_cancel(c->operations); + while (c->operations) { + pa_operation *o = c->operations; + if (o->cancel_callback) + o->cancel_callback(o, o->cancel_userdata); + + pa_operation_cancel(o); + } if (c->pdispatch) { pa_pdispatch_unref(c->pdispatch); diff --git a/src/pulse/internal.h b/src/pulse/internal.h index c5bdcb1..c647c96 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -234,6 +234,8 @@ struct pa_operation { pa_operation_state_t state; void *userdata; pa_operation_cb_t callback; + void *cancel_userdata; + pa_operation_cancel_cb_t cancel_callback; void *private; /* some operations might need this */ }; @@ -249,6 +251,7 @@ void pa_command_stream_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, p void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); void pa_command_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +pa_operation *pa_operation_new_with_cancel_callback(pa_context *c, pa_stream *s, pa_operation_cb_t callback, void *userdata, pa_operation_cancel_cb_t cancel_callback, void *cancel_userdata); pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t callback, void *userdata); void pa_operation_done(pa_operation *o); diff --git a/src/pulse/operation.c b/src/pulse/operation.c index fe160a3..85867f5 100644 --- a/src/pulse/operation.c +++ b/src/pulse/operation.c @@ -26,13 +26,14 @@ #include <pulse/xmalloc.h> #include <pulsecore/macro.h> #include <pulsecore/flist.h> +#include <pulse/fork-detect.h> #include "internal.h" #include "operation.h" PA_STATIC_FLIST_DECLARE(operations, 0, pa_xfree); -pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata) { +pa_operation *pa_operation_new_with_cancel_callback(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata, pa_operation_cancel_cb_t cancel_cb, void *cancel_userdata) { pa_operation *o; pa_assert(c); @@ -47,6 +48,8 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb o->state = PA_OPERATION_RUNNING; o->callback = cb; o->userdata = userdata; + o->cancel_callback = cancel_cb; + o->cancel_userdata = cancel_userdata; /* Refcounting is strictly one-way: from the "bigger" to the "smaller" object. */ PA_LLIST_PREPEND(pa_operation, c->operations, o); @@ -55,6 +58,10 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb return o; } +pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata) { + return pa_operation_new_with_cancel_callback(c, s, cb, userdata, NULL, NULL); +} + pa_operation *pa_operation_ref(pa_operation *o) { pa_assert(o); pa_assert(PA_REFCNT_VALUE(o) >= 1); @@ -91,6 +98,8 @@ static void operation_unlink(pa_operation *o) { o->stream = NULL; o->callback = NULL; o->userdata = NULL; + o->cancel_callback = NULL; + o->cancel_userdata = NULL; } static void operation_set_state(pa_operation *o, pa_operation_state_t st) { @@ -130,3 +139,17 @@ pa_operation_state_t pa_operation_get_state(pa_operation *o) { return o->state; } + +void pa_operation_set_cancel_callback(pa_operation *o, pa_operation_cancel_cb_t cb, void *userdata) { + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + + if (pa_detect_fork()) + return; + + if (o->state == PA_OPERATION_DONE || o->state == PA_OPERATION_CANCELED) + return; + + o->cancel_callback = cb; + o->cancel_userdata = userdata; +} diff --git a/src/pulse/operation.h b/src/pulse/operation.h index b6b5691..a5f97fa 100644 --- a/src/pulse/operation.h +++ b/src/pulse/operation.h @@ -34,6 +34,9 @@ PA_C_DECL_BEGIN /** An asynchronous operation object */ typedef struct pa_operation pa_operation; +/** A generic callback for operation cancelation */ +typedef void (*pa_operation_cancel_cb_t) (pa_operation *o, void *userdata); + /** Increase the reference count by one */ pa_operation *pa_operation_ref(pa_operation *o); @@ -50,6 +53,10 @@ void pa_operation_cancel(pa_operation *o); /** Return the current status of the operation */ pa_operation_state_t pa_operation_get_state(pa_operation *o); +/** Set the callback function that is called when the operation + * is canceled due to disconnection. \since 3.0 */ +void pa_operation_set_cancel_callback(pa_operation *o, pa_operation_cancel_cb_t cb, void *userdata); + PA_C_DECL_END #endif -- 1.7.9.5