]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/source.c
sink, source: Allow calling set_mute() during initialization
[pulseaudio] / src / pulsecore / source.c
index 853bb6c4deda55ed793c559776ba6280a633d5bf..bf7e9776d48bdf39441ab0d156a502ff99fac6c6 100644 (file)
@@ -218,10 +218,16 @@ pa_source* pa_source_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, false);
     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_source_new_data_set_port(data, p->name);
+    }
+
     if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {
         pa_xfree(s);
         pa_namereg_unregister(core, name);
@@ -288,24 +294,10 @@ pa_source* pa_source_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 (p->available == PA_AVAILABLE_NO)
-                continue;
-
-            if (!s->active_port || p->priority > s->active_port->priority)
-                s->active_port = p;
-        }
-
-        if (!s->active_port) {
-            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;
@@ -1437,20 +1429,13 @@ static void update_real_volume(pa_source *s, const pa_cvolume *new_volume, pa_ch
     PA_IDXSET_FOREACH(o, s->outputs, idx) {
         if (o->destination_source && (o->destination_source->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)) {
             if (pa_source_flat_volume_enabled(s)) {
-                pa_cvolume old_volume = o->volume;
+                pa_cvolume new_output_volume;
 
                 /* Follow the root source's real volume. */
-                o->volume = *new_volume;
-                pa_cvolume_remap(&o->volume, channel_map, &o->channel_map);
+                new_output_volume = *new_volume;
+                pa_cvolume_remap(&new_output_volume, channel_map, &o->channel_map);
+                pa_source_output_set_volume_direct(o, &new_output_volume);
                 compute_reference_ratio(o);
-
-                /* The volume changed, let's tell people so */
-                if (!pa_cvolume_equal(&old_volume, &o->volume)) {
-                    if (o->volume_changed)
-                        o->volume_changed(o);
-
-                    pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
-                }
             }
 
             update_real_volume(o->destination_source, new_volume, channel_map);
@@ -1505,7 +1490,7 @@ static void propagate_reference_volume(pa_source *s) {
      * source output volumes accordingly */
 
     PA_IDXSET_FOREACH(o, s->outputs, idx) {
-        pa_cvolume old_volume;
+        pa_cvolume new_volume;
 
         if (o->destination_source && (o->destination_source->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)) {
             propagate_reference_volume(o->destination_source);
@@ -1516,24 +1501,14 @@ static void propagate_reference_volume(pa_source *s) {
             continue;
         }
 
-        old_volume = o->volume;
-
         /* This basically calculates:
          *
          * o->volume := o->reference_volume * o->reference_ratio  */
 
-        o->volume = s->reference_volume;
-        pa_cvolume_remap(&o->volume, &s->channel_map, &o->channel_map);
-        pa_sw_cvolume_multiply(&o->volume, &o->volume, &o->reference_ratio);
-
-        /* The volume changed, let's tell people so */
-        if (!pa_cvolume_equal(&old_volume, &o->volume)) {
-
-            if (o->volume_changed)
-                o->volume_changed(o);
-
-            pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
-        }
+        new_volume = s->reference_volume;
+        pa_cvolume_remap(&new_volume, &s->channel_map, &o->channel_map);
+        pa_sw_cvolume_multiply(&new_volume, &new_volume, &o->reference_ratio);
+        pa_source_output_set_volume_direct(o, &new_volume);
     }
 }
 
@@ -1556,13 +1531,11 @@ static bool update_reference_volume(pa_source *s, const pa_cvolume *v, const pa_
     pa_cvolume_remap(&volume, channel_map, &s->channel_map);
 
     reference_volume_changed = !pa_cvolume_equal(&volume, &s->reference_volume);
-    s->reference_volume = volume;
+    pa_source_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_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-    else if (!(s->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER))
+    if (!reference_volume_changed && !(s->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER))
         /* If the root source's volume doesn't change, then there can't be any
          * changes in the other source in the source tree either.
          *
@@ -1728,9 +1701,8 @@ static void propagate_real_volume(pa_source *s, const pa_cvolume *old_real_volum
     }
 
     if (pa_source_flat_volume_enabled(s)) {
-
         PA_IDXSET_FOREACH(o, s->outputs, idx) {
-            pa_cvolume old_volume = o->volume;
+            pa_cvolume new_volume;
 
             /* 2. Since the source's reference and real volumes are equal
              * now our ratios should be too. */
@@ -1744,18 +1716,10 @@ static void propagate_real_volume(pa_source *s, const pa_cvolume *old_real_volum
              * o->volume = s->reference_volume * o->reference_ratio
              *
              * This is identical to propagate_reference_volume() */
-            o->volume = s->reference_volume;
-            pa_cvolume_remap(&o->volume, &s->channel_map, &o->channel_map);
-            pa_sw_cvolume_multiply(&o->volume, &o->volume, &o->reference_ratio);
-
-            /* Notify if something changed */
-            if (!pa_cvolume_equal(&old_volume, &o->volume)) {
-
-                if (o->volume_changed)
-                    o->volume_changed(o);
-
-                pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index);
-            }
+            new_volume = s->reference_volume;
+            pa_cvolume_remap(&new_volume, &s->channel_map, &o->channel_map);
+            pa_sw_cvolume_multiply(&new_volume, &new_volume, &o->reference_ratio);
+            pa_source_output_set_volume_direct(o, &new_volume);
 
             if (o->destination_source && (o->destination_source->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER))
                 propagate_real_volume(o->destination_source, old_real_volume);
@@ -1825,19 +1789,26 @@ void pa_source_set_mute(pa_source *s, bool mute, bool save) {
 
     pa_source_assert_ref(s);
     pa_assert_ctl_context();
-    pa_assert(PA_SOURCE_IS_LINKED(s->state));
 
     old_muted = s->muted;
+
+    if (mute == old_muted) {
+        s->save_muted |= save;
+        return;
+    }
+
     s->muted = mute;
-    s->save_muted = (old_muted == s->muted && s->save_muted) || save;
+    s->save_muted = save;
 
     if (!(s->flags & PA_SOURCE_DEFERRED_VOLUME) && s->set_mute)
         s->set_mute(s);
 
-    pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
+    if (!PA_SOURCE_IS_LINKED(s->state))
+        return;
 
-    if (old_muted != s->muted)
-        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    pa_log_debug("The mute of source %s changed from %s to %s.", s->name, pa_yes_no(old_muted), pa_yes_no(mute));
+    pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
+    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
 }
 
 /* Called from main thread */
@@ -2078,9 +2049,7 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
                 o->thread_info.direct_on_input = NULL;
             }
 
-            if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
-                pa_source_output_unref(o);
-
+            pa_hashmap_remove_and_free(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index));
             pa_source_invalidate_requested_latency(s, true);
 
             /* In flat volume mode we need to update the volume as
@@ -2878,3 +2847,27 @@ done:
 
     return out_formats;
 }
+
+/* Called from the main thread. */
+void pa_source_set_reference_volume_direct(pa_source *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 source %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_SOURCE_DECIBEL_VOLUME),
+                 pa_cvolume_snprint_verbose(new_volume_str, sizeof(new_volume_str), volume, &s->channel_map,
+                                            s->flags & PA_SOURCE_DECIBEL_VOLUME));
+
+    pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+}