Hi Tanu Kaskinen, I rewrote the patch by following your feedback. I kept "pa_operation_new_with_state_callback" (" pa_operation_new_with_cancel_callback" previously) refactoring as the same for a while because the argument favonia provided. If you insist that we should remove pa_operation_new_with_state_callback, I will send another patch with that removed. Thanks diff --git a/src/map-file b/src/map-file index a20314c..91d61c2 100644 --- a/src/map-file +++ b/src/map-file @@ -220,6 +220,7 @@ pa_msleep; pa_operation_cancel; pa_operation_get_state; pa_operation_ref; +pa_operation_set_state_callback; pa_operation_unref; pa_parse_sample_format; pa_path_get_filename; diff --git a/src/pulse/internal.h b/src/pulse/internal.h index c5bdcb1..aee4398 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 *state_userdata; + pa_operation_notify_cb_t state_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_state_callback(pa_context *c, pa_stream *s, pa_operation_cb_t callback, void *userdata, pa_operation_notify_cb_t state_callback, void *state_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..891269e 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_state_callback(pa_context *c, pa_stream *s, pa_operation_cb_t cb, void *userdata, pa_operation_notify_cb_t state_cb, void *state_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->state_callback = state_cb; + o->state_userdata = state_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_state_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->state_callback = NULL; + o->state_userdata = NULL; } static void operation_set_state(pa_operation *o, pa_operation_state_t st) { @@ -104,6 +113,9 @@ static void operation_set_state(pa_operation *o, pa_operation_state_t st) { o->state = st; + if (o->state_callback) + o->state_callback(o, o->state_userdata); + if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) operation_unlink(o); @@ -130,3 +142,17 @@ pa_operation_state_t pa_operation_get_state(pa_operation *o) { return o->state; } + +void pa_operation_set_state_callback(pa_operation *o, pa_operation_notify_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->state_callback = cb; + o->state_userdata = userdata; +} diff --git a/src/pulse/operation.h b/src/pulse/operation.h index b6b5691..20c3636 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_notify_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_state_callback(pa_operation *o, pa_operation_notify_cb_t cb, void *userdata); + PA_C_DECL_END #endif On Sat, Jan 5, 2013 at 12:25 AM, Favonia <favonia at gmail.com> wrote: > On Fri, Jan 4, 2013 at 7:50 AM, Tanu Kaskinen <tanuk at iki.fi> wrote: > > Ok, would you be willing to write an updated patch? > I'm CC'ing one of my teammates who might be able to do it now. > > > Some feedback about the first version: > > > > * It would be better to call the callback from operation_set_state > > rather than from context_unlink(). > That's probably true. We'll look at it. Thanks. > > > * pa_operation_new_with_cancel_callback() seems unnecessary. There's no > > need to initialize the callback to anything else than NULL when creating > > a new operation object. > This is indeed unnecessary under the current practice. As far as I > remember, all current APIs which return a new pa_operation object only > provide a way to subscribe to the result of successful execution. > Perhaps I was hoping that, in some future version we can also set up > the new callback when created. We can certainly comment out this > function for now. However, in the long run, refactoring with this > function will help, I think. > > > * Every new function in the public API need to be added to > > src/map-file, otherwise applications won't be able to use the function > > (linking will fail). > I see. Sorry for the mistake. > > Favonia > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/pulseaudio-discuss/attachments/20130105/f777b45c/attachment-0001.html>