]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/sink.c
Use pa_hashmap_remove_and_free() where appropriate
[pulseaudio] / src / pulsecore / sink.c
index cd08b9901edca235c2ed550c1de962cd8f36bd15..e308b3e7d011a5db093269127b7e749382a33b49 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);
 }
@@ -1377,8 +1380,8 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
 }
 
 /* Called from main thread */
-bool pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
-    bool ret = false;
+int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
+    int ret = -1;
     uint32_t desired_rate = rate;
     uint32_t default_rate = s->default_sample_rate;
     uint32_t alternate_rate = s->alternate_sample_rate;
@@ -1386,37 +1389,38 @@ bool pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
     pa_sink_input *i;
     bool use_alternate = false;
 
+    if (rate == s->sample_spec.rate)
+        return 0;
+
     if (!s->update_rate)
-        return false;
+        return -1;
 
     if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough)) {
         pa_log_debug("Default and alternate sample rates are the same.");
-        return false;
+        return -1;
     }
 
     if (PA_SINK_IS_RUNNING(s->state)) {
         pa_log_info("Cannot update rate, SINK_IS_RUNNING, will keep using %u Hz",
                     s->sample_spec.rate);
-        return false;
+        return -1;
     }
 
     if (s->monitor_source) {
         if (PA_SOURCE_IS_RUNNING(s->monitor_source->state) == true) {
             pa_log_info("Cannot update rate, monitor source is RUNNING");
-            return false;
+            return -1;
         }
     }
 
-    if (PA_UNLIKELY (desired_rate < 8000 ||
-                     desired_rate > PA_RATE_MAX))
-        return false;
+    if (PA_UNLIKELY(!pa_sample_rate_valid(desired_rate)))
+        return -1;
 
     if (!passthrough) {
-        pa_assert(default_rate % 4000 || default_rate % 11025);
-        pa_assert(alternate_rate % 4000 || alternate_rate % 11025);
+        pa_assert((default_rate % 4000 == 0) || (default_rate % 11025 == 0));
+        pa_assert((alternate_rate % 4000 == 0) || (alternate_rate % 11025 == 0));
 
-        if (default_rate % 4000) {
-            /* default is a 11025 multiple */
+        if (default_rate % 11025 == 0) {
             if ((alternate_rate % 4000 == 0) && (desired_rate % 4000 == 0))
                 use_alternate=true;
         } else {
@@ -1434,15 +1438,15 @@ bool pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
     }
 
     if (desired_rate == s->sample_spec.rate)
-        return false;
+        return -1;
 
     if (!passthrough && pa_sink_used_by(s) > 0)
-        return false;
+        return -1;
 
     pa_log_debug("Suspending sink %s due to changing the sample rate.", s->name);
     pa_sink_suspend(s, true, PA_SUSPEND_INTERNAL);
 
-    if (s->update_rate(s, desired_rate) == true) {
+    if (s->update_rate(s, desired_rate) >= 0) {
         /* update monitor source as well */
         if (s->monitor_source && !passthrough)
             pa_source_update_rate(s->monitor_source, desired_rate, false);
@@ -1453,7 +1457,7 @@ bool pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
                 pa_sink_input_update_rate(i);
         }
 
-        ret = true;
+        ret = 0;
     }
 
     pa_sink_suspend(s, false, PA_SUSPEND_INTERNAL);
@@ -2045,7 +2049,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);
@@ -2543,9 +2547,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);
 
@@ -2626,8 +2628,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);
 
@@ -2793,18 +2794,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;
@@ -2919,24 +2908,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;
@@ -3460,16 +3431,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)))