diff options
| -rw-r--r-- | src/pulsecore/sink-input.c | 32 | ||||
| -rw-r--r-- | src/pulsecore/sink.c | 34 | ||||
| -rw-r--r-- | src/pulsecore/source-output.c | 31 | ||||
| -rw-r--r-- | src/pulsecore/source.c | 25 | 
4 files changed, 87 insertions, 35 deletions
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index c06da13f..57c6c601 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -264,10 +264,18 @@ static int sink_input_set_state(pa_sink_input *i, pa_sink_input_state_t state) {  }  void pa_sink_input_unlink(pa_sink_input *i) { +    pa_bool_t linked;      pa_assert(i); -    pa_assert(PA_SINK_INPUT_LINKED(i->state)); -    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i); +    /* See pa_sink_unlink() for a couple of comments how this function +     * works */ + +    pa_sink_input_ref(i); + +    linked = PA_SINK_INPUT_LINKED(i->state); + +    if (linked) +        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], i);      if (i->sync_prev)          i->sync_prev->sync_next = i->sync_next; @@ -276,14 +284,16 @@ void pa_sink_input_unlink(pa_sink_input *i) {      i->sync_prev = i->sync_next = NULL; -    pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL);      pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL); -    pa_idxset_remove_by_data(i->sink->inputs, i, NULL); - -    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index); +    if (pa_idxset_remove_by_data(i->sink->inputs, i, NULL)) +        pa_sink_input_unref(i); -    sink_input_set_state(i, PA_SINK_INPUT_UNLINKED); -    pa_sink_update_status(i->sink); +    if (linked) { +        pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL); +        sink_input_set_state(i, PA_SINK_INPUT_UNLINKED); +        pa_sink_update_status(i->sink); +    } else +        i->state = PA_SINK_INPUT_UNLINKED;      i->peek = NULL;      i->drop = NULL; @@ -293,7 +303,11 @@ void pa_sink_input_unlink(pa_sink_input *i) {      i->detach = NULL;      i->suspend = NULL; -    pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i); +    if (linked) { +        pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_REMOVE, i->index); +        pa_hook_fire(&i->sink->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], i); +    } +      i->sink = NULL;      pa_sink_input_unref(i);  } diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 409d0260..b814f837 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -200,14 +200,26 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {  }  void pa_sink_unlink(pa_sink* s) { +    pa_bool_t linked;      pa_sink_input *i, *j = NULL;      pa_assert(s); -    pa_assert(PA_SINK_LINKED(s->state)); -    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s); +    /* Please note that pa_sink_unlink() does more than simply +     * reversing pa_sink_put(). It also undoes the registrations +     * already done in pa_sink_new()! */ + +    /* All operations here shall be idempotent, i.e. pa_sink_unlink() +     * may be called multiple times on the same sink without bad +     * effects. */ + +    linked = PA_SINK_LINKED(s->state); -    pa_namereg_unregister(s->core, s->name); +    if (linked) +        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s); + +    if (s->state != PA_SINK_UNLINKED) +        pa_namereg_unregister(s->core, s->name);      pa_idxset_remove_by_data(s->core->sinks, s, NULL);      while ((i = pa_idxset_first(s->inputs, NULL))) { @@ -216,10 +228,10 @@ void pa_sink_unlink(pa_sink* s) {          j = i;      } -    sink_set_state(s, PA_SINK_UNLINKED); - -    if (s->monitor_source) -        pa_source_unlink(s->monitor_source); +    if (linked) +        sink_set_state(s, PA_SINK_UNLINKED); +    else +        s->state = PA_SINK_UNLINKED;      s->get_latency = NULL;      s->get_volume = NULL; @@ -228,9 +240,13 @@ void pa_sink_unlink(pa_sink* s) {      s->get_mute = NULL;      s->set_state = NULL; -    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); +    if (s->monitor_source) +        pa_source_unlink(s->monitor_source); -    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s); +    if (linked) { +        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); +        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], s); +    }  }  static void sink_free(pa_object *o) { diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 34eef8ba..1991613e 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -194,20 +194,29 @@ static int source_output_set_state(pa_source_output *o, pa_source_output_state_t  }  void pa_source_output_unlink(pa_source_output*o) { +    pa_bool_t linked;      pa_assert(o); -    pa_assert(PA_SOURCE_OUTPUT_LINKED(o->state)); -    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o); +    /* See pa_sink_unlink() for a couple of comments how this function +     * works */ -    pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL); +    pa_source_output_ref(o); -    pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); -    pa_idxset_remove_by_data(o->source->outputs, o, NULL); +    linked = PA_SOURCE_OUTPUT_LINKED(o->state); -    pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); +    if (linked) +        pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], o); -    source_output_set_state(o, PA_SOURCE_OUTPUT_UNLINKED); -    pa_source_update_status(o->source); +    pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL); +    if (pa_idxset_remove_by_data(o->source->outputs, o, NULL)) +        pa_source_output_unref(o); + +    if (linked) { +        pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_REMOVE_OUTPUT, o, 0, NULL); +        source_output_set_state(o, PA_SOURCE_OUTPUT_UNLINKED); +        pa_source_update_status(o->source); +    } else +        o->state = PA_SOURCE_OUTPUT_UNLINKED;      o->push = NULL;      o->kill = NULL; @@ -216,7 +225,10 @@ void pa_source_output_unlink(pa_source_output*o) {      o->detach = NULL;      o->suspend = NULL; -    pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], o); +    if (linked) { +        pa_subscription_post(o->source->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_REMOVE, o->index); +        pa_hook_fire(&o->source->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], o); +    }      o->source = NULL;      pa_source_output_unref(o); @@ -451,7 +463,6 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int              return 0;          } -      }      return -1; diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 8f9cbc4a..9745a13e 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -175,14 +175,21 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {  }  void pa_source_unlink(pa_source *s) { +    pa_bool_t linked;      pa_source_output *o, *j = NULL;      pa_assert(s); -    pa_assert(PA_SOURCE_LINKED(s->state)); -    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s); +    /* See pa_sink_unlink() for a couple of comments how this function +     * works. */ + +    linked = PA_SOURCE_LINKED(s->state); + +    if (linked) +        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s); -    pa_namereg_unregister(s->core, s->name); +    if (s->state != PA_SOURCE_UNLINKED) +        pa_namereg_unregister(s->core, s->name);      pa_idxset_remove_by_data(s->core->sources, s, NULL);      while ((o = pa_idxset_first(s->outputs, NULL))) { @@ -191,7 +198,10 @@ void pa_source_unlink(pa_source *s) {          j = o;      } -    source_set_state(s, PA_SOURCE_UNLINKED); +    if (linked) +        source_set_state(s, PA_SOURCE_UNLINKED); +    else +        s->state = PA_SOURCE_UNLINKED;      s->get_latency = NULL;      s->get_volume = NULL; @@ -200,9 +210,10 @@ void pa_source_unlink(pa_source *s) {      s->get_mute = NULL;      s->set_state = NULL; -    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); - -    pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s); +    if (linked) { +        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); +        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s); +    }  }  static void source_free(pa_object *o) {  | 
