]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/sink.c
sink, source: Assign to reference_volume from only one place
[pulseaudio] / src / pulsecore / sink.c
index de8c82ea63e20a501682e407dc50b6244ab1681b..c1cd2db4f54ef0a49b2c526cea61de18a9658ab5 100644 (file)
@@ -82,7 +82,7 @@ pa_sink_new_data* pa_sink_new_data_init(pa_sink_new_data *data) {
 
     pa_zero(*data);
     data->proplist = pa_proplist_new();
-    data->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+    data->ports = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) pa_device_port_unref);
 
     return data;
 }
@@ -142,7 +142,7 @@ void pa_sink_new_data_done(pa_sink_new_data *data) {
     pa_proplist_free(data->proplist);
 
     if (data->ports)
-        pa_hashmap_free(data->ports, (pa_free_cb_t) pa_device_port_unref);
+        pa_hashmap_free(data->ports);
 
     pa_xfree(data->name);
     pa_xfree(data->active_port);
@@ -231,10 +231,16 @@ pa_sink* pa_sink_new(
     if (data->card)
         pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
 
-    pa_device_init_description(data->proplist);
+    pa_device_init_description(data->proplist, data->card);
     pa_device_init_icon(data->proplist, true);
     pa_device_init_intended_roles(data->proplist);
 
+    if (!data->active_port) {
+        pa_device_port *p = pa_device_port_find_best(data->ports);
+        if (p)
+            pa_sink_new_data_set_port(data, p->name);
+    }
+
     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_FIXATE], data) < 0) {
         pa_xfree(s);
         pa_namereg_unregister(core, name);
@@ -300,14 +306,10 @@ pa_sink* pa_sink_new(
         if ((s->active_port = pa_hashmap_get(s->ports, data->active_port)))
             s->save_port = data->save_port;
 
-    if (!s->active_port) {
-        void *state;
-        pa_device_port *p;
-
-        PA_HASHMAP_FOREACH(p, s->ports, state)
-            if (!s->active_port || p->priority > s->active_port->priority)
-                s->active_port = p;
-    }
+    /* Hopefully the active port has already been assigned in the previous call
+       to pa_device_port_find_best, but better safe than sorry */
+    if (!s->active_port)
+        s->active_port = pa_device_port_find_best(s->ports);
 
     if (s->active_port)
         s->latency_offset = s->active_port->latency_offset;
@@ -325,7 +327,8 @@ pa_sink* pa_sink_new(
             0);
 
     s->thread_info.rtpoll = NULL;
-    s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+    s->thread_info.inputs = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
+                                                (pa_free_cb_t) pa_sink_input_unref);
     s->thread_info.soft_volume =  s->soft_volume;
     s->thread_info.soft_muted = s->muted;
     s->thread_info.state = s->state;
@@ -730,7 +733,7 @@ static void sink_free(pa_object *o) {
     }
 
     pa_idxset_free(s->inputs, NULL);
-    pa_hashmap_free(s->thread_info.inputs, (pa_free_cb_t) pa_sink_input_unref);
+    pa_hashmap_free(s->thread_info.inputs);
 
     if (s->silence.memblock)
         pa_memblock_unref(s->silence.memblock);
@@ -742,7 +745,7 @@ static void sink_free(pa_object *o) {
         pa_proplist_free(s->proplist);
 
     if (s->ports)
-        pa_hashmap_free(s->ports, (pa_free_cb_t) pa_device_port_unref);
+        pa_hashmap_free(s->ports);
 
     pa_xfree(s);
 }
@@ -1410,8 +1413,7 @@ int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
         }
     }
 
-    if (PA_UNLIKELY (desired_rate < 8000 ||
-                     desired_rate > PA_RATE_MAX))
+    if (PA_UNLIKELY(!pa_sample_rate_valid(desired_rate)))
         return -1;
 
     if (!passthrough) {
@@ -1952,13 +1954,11 @@ static bool update_reference_volume(pa_sink *s, const pa_cvolume *v, const pa_ch
     pa_cvolume_remap(&volume, channel_map, &s->channel_map);
 
     reference_volume_changed = !pa_cvolume_equal(&volume, &s->reference_volume);
-    s->reference_volume = volume;
+    pa_sink_set_reference_volume_direct(s, &volume);
 
     s->save_volume = (!reference_volume_changed && s->save_volume) || save;
 
-    if (reference_volume_changed)
-        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-    else if (!(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
+    if (!reference_volume_changed && !(s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER))
         /* If the root sink's volume doesn't change, then there can't be any
          * changes in the other sinks in the sink tree either.
          *
@@ -2047,7 +2047,7 @@ void pa_sink_set_volume(
 
         /* Let's 'push' the reference volume if necessary */
         pa_cvolume_merge(&new_reference_volume, &s->reference_volume, &root_sink->real_volume);
-        /* If the sink and it's root don't have the same number of channels, we need to remap */
+        /* If the sink and its root don't have the same number of channels, we need to remap */
         if (s != root_sink && !pa_channel_map_equal(&s->channel_map, &root_sink->channel_map))
             pa_cvolume_remap(&new_reference_volume, &s->channel_map, &root_sink->channel_map);
         update_reference_volume(root_sink, &new_reference_volume, &root_sink->channel_map, save);
@@ -2545,9 +2545,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
                 i->thread_info.sync_next = NULL;
             }
 
-            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
-                pa_sink_input_unref(i);
-
+            pa_hashmap_remove_and_free(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
             pa_sink_invalidate_requested_latency(s, true);
             pa_sink_request_rewind(s, (size_t) -1);
 
@@ -2628,8 +2626,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             i->thread_info.attached = false;
 
             /* Let's remove the sink input ...*/
-            if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index)))
-                pa_sink_input_unref(i);
+            pa_hashmap_remove_and_free(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index));
 
             pa_sink_invalidate_requested_latency(s, true);
 
@@ -2795,18 +2792,6 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             return 0;
         }
 
-        case PA_SINK_MESSAGE_DETACH:
-
-            /* Detach all streams */
-            pa_sink_detach_within_thread(s);
-            return 0;
-
-        case PA_SINK_MESSAGE_ATTACH:
-
-            /* Reattach all streams */
-            pa_sink_attach_within_thread(s);
-            return 0;
-
         case PA_SINK_MESSAGE_GET_REQUESTED_LATENCY: {
 
             pa_usec_t *usec = userdata;
@@ -2921,24 +2906,6 @@ int pa_sink_suspend_all(pa_core *c, bool suspend, pa_suspend_cause_t cause) {
     return ret;
 }
 
-/* Called from main thread */
-void pa_sink_detach(pa_sink *s) {
-    pa_sink_assert_ref(s);
-    pa_assert_ctl_context();
-    pa_assert(PA_SINK_IS_LINKED(s->state));
-
-    pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_DETACH, NULL, 0, NULL) == 0);
-}
-
-/* Called from main thread */
-void pa_sink_attach(pa_sink *s) {
-    pa_sink_assert_ref(s);
-    pa_assert_ctl_context();
-    pa_assert(PA_SINK_IS_LINKED(s->state));
-
-    pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
-}
-
 /* Called from IO thread */
 void pa_sink_detach_within_thread(pa_sink *s) {
     pa_sink_input *i;
@@ -3462,16 +3429,21 @@ bool pa_device_init_icon(pa_proplist *p, bool is_sink) {
     return true;
 }
 
-bool pa_device_init_description(pa_proplist *p) {
+bool pa_device_init_description(pa_proplist *p, pa_card *card) {
     const char *s, *d = NULL, *k;
     pa_assert(p);
 
     if (pa_proplist_contains(p, PA_PROP_DEVICE_DESCRIPTION))
         return true;
 
-    if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
-        if (pa_streq(s, "internal"))
-            d = _("Built-in Audio");
+    if (card)
+        if ((s = pa_proplist_gets(card->proplist, PA_PROP_DEVICE_DESCRIPTION)))
+            d = s;
+
+    if (!d)
+        if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_FORM_FACTOR)))
+            if (pa_streq(s, "internal"))
+                d = _("Built-in Audio");
 
     if (!d)
         if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS)))
@@ -3824,3 +3796,27 @@ done:
 
     return out_formats;
 }
+
+/* Called from the main thread. */
+void pa_sink_set_reference_volume_direct(pa_sink *s, const pa_cvolume *volume) {
+    pa_cvolume old_volume;
+    char old_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
+    char new_volume_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
+
+    pa_assert(s);
+    pa_assert(volume);
+
+    old_volume = s->reference_volume;
+
+    if (pa_cvolume_equal(volume, &old_volume))
+        return;
+
+    s->reference_volume = *volume;
+    pa_log_debug("The reference volume of sink %s changed from %s to %s.", s->name,
+                 pa_cvolume_snprint_verbose(old_volume_str, sizeof(old_volume_str), &old_volume, &s->channel_map,
+                                            s->flags & PA_SINK_DECIBEL_VOLUME),
+                 pa_cvolume_snprint_verbose(new_volume_str, sizeof(new_volume_str), volume, &s->channel_map,
+                                            s->flags & PA_SINK_DECIBEL_VOLUME));
+
+    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+}