]> code.delx.au - pulseaudio/blobdiff - src/modules/dbus/iface-device.c
hashmap: Add the ability to free keys
[pulseaudio] / src / modules / dbus / iface-device.c
index 3a747a4472e2ea3e9309b2d9f543d4940dfa666d..34b370b557c9b0fa573bb583b2f9157317a8591e 100644 (file)
@@ -76,11 +76,6 @@ static void handle_source_get_monitor_of_sink(DBusConnection *conn, DBusMessage
 
 static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *userdata);
 
-enum device_type {
-    DEVICE_TYPE_SINK,
-    DEVICE_TYPE_SOURCE
-};
-
 struct pa_dbusiface_device {
     pa_dbusiface_core *core;
 
@@ -88,7 +83,7 @@ struct pa_dbusiface_device {
         pa_sink *sink;
         pa_source *source;
     };
-    enum device_type type;
+    pa_device_type_t type;
     char *path;
     pa_cvolume volume;
     dbus_bool_t mute;
@@ -266,7 +261,7 @@ static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userd
     pa_assert(msg);
     pa_assert(d);
 
-    idx = (d->type == DEVICE_TYPE_SINK) ? d->sink->index : d->source->index;
+    idx = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->index : d->source->index;
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx);
 }
@@ -279,7 +274,7 @@ static void handle_get_name(DBusConnection *conn, DBusMessage *msg, void *userda
     pa_assert(msg);
     pa_assert(d);
 
-    name = (d->type == DEVICE_TYPE_SINK) ? d->sink->name : d->source->name;
+    name = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->name : d->source->name;
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &name);
 }
@@ -292,7 +287,7 @@ static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *user
     pa_assert(msg);
     pa_assert(d);
 
-    driver = (d->type == DEVICE_TYPE_SINK) ? d->sink->driver : d->source->driver;
+    driver = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->driver : d->source->driver;
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_STRING, &driver);
 }
@@ -306,10 +301,10 @@ static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void
     pa_assert(msg);
     pa_assert(d);
 
-    owner_module = (d->type == DEVICE_TYPE_SINK) ? d->sink->module : d->source->module;
+    owner_module = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->module : d->source->module;
 
     if (!owner_module) {
-        if (d->type == DEVICE_TYPE_SINK)
+        if (d->type == PA_DEVICE_TYPE_SINK)
             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
                                "Sink %s doesn't have an owner module.", d->sink->name);
         else
@@ -332,10 +327,10 @@ static void handle_get_card(DBusConnection *conn, DBusMessage *msg, void *userda
     pa_assert(msg);
     pa_assert(d);
 
-    card = (d->type == DEVICE_TYPE_SINK) ? d->sink->card : d->source->card;
+    card = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->card : d->source->card;
 
     if (!card) {
-        if (d->type == DEVICE_TYPE_SINK)
+        if (d->type == PA_DEVICE_TYPE_SINK)
             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
                                "Sink %s doesn't belong to any card.", d->sink->name);
         else
@@ -357,7 +352,7 @@ static void handle_get_sample_format(DBusConnection *conn, DBusMessage *msg, voi
     pa_assert(msg);
     pa_assert(d);
 
-    sample_format = (d->type == DEVICE_TYPE_SINK) ? d->sink->sample_spec.format : d->source->sample_spec.format;
+    sample_format = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->sample_spec.format : d->source->sample_spec.format;
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_format);
 }
@@ -370,7 +365,7 @@ static void handle_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void
     pa_assert(msg);
     pa_assert(d);
 
-    sample_rate = (d->type == DEVICE_TYPE_SINK) ? d->sink->sample_spec.rate : d->source->sample_spec.rate;
+    sample_rate = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->sample_spec.rate : d->source->sample_spec.rate;
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &sample_rate);
 }
@@ -385,7 +380,7 @@ static void handle_get_channels(DBusConnection *conn, DBusMessage *msg, void *us
     pa_assert(msg);
     pa_assert(d);
 
-    channel_map = (d->type == DEVICE_TYPE_SINK) ? &d->sink->channel_map : &d->source->channel_map;
+    channel_map = (d->type == PA_DEVICE_TYPE_SINK) ? &d->sink->channel_map : &d->source->channel_map;
 
     for (i = 0; i < channel_map->channels; ++i)
         channels[i] = channel_map->map[i];
@@ -422,33 +417,32 @@ static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessag
     pa_assert(iter);
     pa_assert(d);
 
-    pa_cvolume_init(&new_vol);
-
-    device_channels = (d->type == DEVICE_TYPE_SINK) ? d->sink->channel_map.channels : d->source->channel_map.channels;
-
-    new_vol.channels = device_channels;
+    device_channels = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->channel_map.channels : d->source->channel_map.channels;
 
     dbus_message_iter_recurse(iter, &array_iter);
     dbus_message_iter_get_fixed_array(&array_iter, &volume, &n_volume_entries);
 
-    if (n_volume_entries != device_channels) {
+    if (n_volume_entries != device_channels && n_volume_entries != 1) {
         pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS,
                            "Expected %u volume entries, got %i.", device_channels, n_volume_entries);
         return;
     }
 
+    pa_cvolume_init(&new_vol);
+    new_vol.channels = n_volume_entries;
+
     for (i = 0; i < n_volume_entries; ++i) {
-        if (volume[i] > PA_VOLUME_MAX) {
+        if (!PA_VOLUME_IS_VALID(volume[i])) {
             pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "Too large volume value: %u", volume[i]);
             return;
         }
         new_vol.values[i] = volume[i];
     }
 
-    if (d->type == DEVICE_TYPE_SINK)
-        pa_sink_set_volume(d->sink, &new_vol, TRUE, TRUE);
+    if (d->type == PA_DEVICE_TYPE_SINK)
+        pa_sink_set_volume(d->sink, &new_vol, true, true);
     else
-        pa_source_set_volume(d->source, &new_vol, TRUE);
+        pa_source_set_volume(d->source, &new_vol, true, true);
 
     pa_dbus_send_empty_reply(conn, msg);
 }
@@ -461,7 +455,7 @@ static void handle_get_has_flat_volume(DBusConnection *conn, DBusMessage *msg, v
     pa_assert(msg);
     pa_assert(d);
 
-    has_flat_volume = (d->type == DEVICE_TYPE_SINK) ? (d->sink->flags & PA_SINK_FLAT_VOLUME) : FALSE;
+    has_flat_volume = (d->type == PA_DEVICE_TYPE_SINK) ? !!(d->sink->flags & PA_SINK_FLAT_VOLUME) : FALSE;
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_flat_volume);
 }
@@ -474,9 +468,9 @@ static void handle_get_has_convertible_to_decibel_volume(DBusConnection *conn, D
     pa_assert(msg);
     pa_assert(d);
 
-    has_convertible_to_decibel_volume = (d->type == DEVICE_TYPE_SINK)
-                                        ? (d->sink->flags & PA_SINK_DECIBEL_VOLUME)
-                                        : (d->source->flags & PA_SOURCE_DECIBEL_VOLUME);
+    has_convertible_to_decibel_volume = (d->type == PA_DEVICE_TYPE_SINK)
+                                        ? !!(d->sink->flags & PA_SINK_DECIBEL_VOLUME)
+                                        : !!(d->source->flags & PA_SOURCE_DECIBEL_VOLUME);
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_convertible_to_decibel_volume);
 }
@@ -489,7 +483,7 @@ static void handle_get_base_volume(DBusConnection *conn, DBusMessage *msg, void
     pa_assert(msg);
     pa_assert(d);
 
-    base_volume = (d->type == DEVICE_TYPE_SINK) ? d->sink->base_volume : d->source->base_volume;
+    base_volume = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->base_volume : d->source->base_volume;
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &base_volume);
 }
@@ -502,7 +496,7 @@ static void handle_get_volume_steps(DBusConnection *conn, DBusMessage *msg, void
     pa_assert(msg);
     pa_assert(d);
 
-    volume_steps = (d->type == DEVICE_TYPE_SINK) ? d->sink->n_volume_steps : d->source->n_volume_steps;
+    volume_steps = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->n_volume_steps : d->source->n_volume_steps;
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &volume_steps);
 }
@@ -528,10 +522,10 @@ static void handle_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMessageI
 
     dbus_message_iter_get_basic(iter, &mute);
 
-    if (d->type == DEVICE_TYPE_SINK)
-        pa_sink_set_mute(d->sink, mute, TRUE);
+    if (d->type == PA_DEVICE_TYPE_SINK)
+        pa_sink_set_mute(d->sink, mute, true);
     else
-        pa_source_set_mute(d->source, mute, TRUE);
+        pa_source_set_mute(d->source, mute, true);
 
     pa_dbus_send_empty_reply(conn, msg);
 }
@@ -544,9 +538,9 @@ static void handle_get_has_hardware_volume(DBusConnection *conn, DBusMessage *ms
     pa_assert(msg);
     pa_assert(d);
 
-    has_hardware_volume = (d->type == DEVICE_TYPE_SINK)
-                          ? (d->sink->flags & PA_SINK_HW_VOLUME_CTRL)
-                          : (d->source->flags & PA_SOURCE_HW_VOLUME_CTRL);
+    has_hardware_volume = (d->type == PA_DEVICE_TYPE_SINK)
+                          ? !!(d->sink->flags & PA_SINK_HW_VOLUME_CTRL)
+                          : !!(d->source->flags & PA_SOURCE_HW_VOLUME_CTRL);
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_hardware_volume);
 }
@@ -559,9 +553,9 @@ static void handle_get_has_hardware_mute(DBusConnection *conn, DBusMessage *msg,
     pa_assert(msg);
     pa_assert(d);
 
-    has_hardware_mute = (d->type == DEVICE_TYPE_SINK)
-                        ? (d->sink->flags & PA_SINK_HW_MUTE_CTRL)
-                        : (d->source->flags & PA_SOURCE_HW_MUTE_CTRL);
+    has_hardware_mute = (d->type == PA_DEVICE_TYPE_SINK)
+                        ? !!(d->sink->flags & PA_SINK_HW_MUTE_CTRL)
+                        : !!(d->source->flags & PA_SOURCE_HW_MUTE_CTRL);
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_hardware_mute);
 }
@@ -574,7 +568,7 @@ static void handle_get_configured_latency(DBusConnection *conn, DBusMessage *msg
     pa_assert(msg);
     pa_assert(d);
 
-    configured_latency = (d->type == DEVICE_TYPE_SINK)
+    configured_latency = (d->type == PA_DEVICE_TYPE_SINK)
                          ? pa_sink_get_requested_latency(d->sink)
                          : pa_source_get_requested_latency(d->source);
 
@@ -589,9 +583,9 @@ static void handle_get_has_dynamic_latency(DBusConnection *conn, DBusMessage *ms
     pa_assert(msg);
     pa_assert(d);
 
-    has_dynamic_latency = (d->type == DEVICE_TYPE_SINK)
-                          ? (d->sink->flags & PA_SINK_DYNAMIC_LATENCY)
-                          : (d->source->flags & PA_SOURCE_DYNAMIC_LATENCY);
+    has_dynamic_latency = (d->type == PA_DEVICE_TYPE_SINK)
+                          ? !!(d->sink->flags & PA_SINK_DYNAMIC_LATENCY)
+                          : !!(d->source->flags & PA_SOURCE_DYNAMIC_LATENCY);
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &has_dynamic_latency);
 }
@@ -604,15 +598,19 @@ static void handle_get_latency(DBusConnection *conn, DBusMessage *msg, void *use
     pa_assert(msg);
     pa_assert(d);
 
-    if (d->type == DEVICE_TYPE_SINK && !(d->sink->flags & PA_SINK_LATENCY))
+    if (d->type == PA_DEVICE_TYPE_SINK && !(d->sink->flags & PA_SINK_LATENCY)) {
         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
                            "Sink %s doesn't support latency querying.", d->sink->name);
-    else if (d->type == DEVICE_TYPE_SOURCE && !(d->source->flags & PA_SOURCE_LATENCY))
+        return;
+    }
+
+    if (d->type == PA_DEVICE_TYPE_SOURCE && !(d->source->flags & PA_SOURCE_LATENCY)) {
         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
                            "Source %s doesn't support latency querying.", d->source->name);
-    return;
+        return;
+    }
 
-    latency = (d->type == DEVICE_TYPE_SINK) ? pa_sink_get_latency(d->sink) : pa_source_get_latency(d->source);
+    latency = (d->type == PA_DEVICE_TYPE_SINK) ? pa_sink_get_latency(d->sink) : pa_source_get_latency(d->source);
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT64, &latency);
 }
@@ -625,9 +623,9 @@ static void handle_get_is_hardware_device(DBusConnection *conn, DBusMessage *msg
     pa_assert(msg);
     pa_assert(d);
 
-    is_hardware_device = (d->type == DEVICE_TYPE_SINK)
-                         ? (d->sink->flags & PA_SINK_HARDWARE)
-                         : (d->source->flags & PA_SOURCE_HARDWARE);
+    is_hardware_device = (d->type == PA_DEVICE_TYPE_SINK)
+                         ? !!(d->sink->flags & PA_SINK_HARDWARE)
+                         : !!(d->source->flags & PA_SOURCE_HARDWARE);
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_hardware_device);
 }
@@ -640,9 +638,9 @@ static void handle_get_is_network_device(DBusConnection *conn, DBusMessage *msg,
     pa_assert(msg);
     pa_assert(d);
 
-    is_network_device = (d->type == DEVICE_TYPE_SINK)
-                        ? (d->sink->flags & PA_SINK_NETWORK)
-                        : (d->source->flags & PA_SOURCE_NETWORK);
+    is_network_device = (d->type == PA_DEVICE_TYPE_SINK)
+                        ? !!(d->sink->flags & PA_SINK_NETWORK)
+                        : !!(d->source->flags & PA_SOURCE_NETWORK);
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_BOOLEAN, &is_network_device);
 }
@@ -655,7 +653,7 @@ static void handle_get_state(DBusConnection *conn, DBusMessage *msg, void *userd
     pa_assert(msg);
     pa_assert(d);
 
-    state = (d->type == DEVICE_TYPE_SINK) ? d->sink_state : d->source_state;
+    state = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink_state : d->source_state;
 
     pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &state);
 }
@@ -710,7 +708,7 @@ static void handle_get_active_port(DBusConnection *conn, DBusMessage *msg, void
     if (!d->active_port) {
         pa_assert(pa_hashmap_isempty(d->ports));
 
-        if (d->type == DEVICE_TYPE_SINK)
+        if (d->type == PA_DEVICE_TYPE_SINK)
             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
                                "The sink %s has no ports, and therefore there's no active port either.", d->sink->name);
         else
@@ -738,7 +736,7 @@ static void handle_set_active_port(DBusConnection *conn, DBusMessage *msg, DBusM
     if (!d->active_port) {
         pa_assert(pa_hashmap_isempty(d->ports));
 
-        if (d->type == DEVICE_TYPE_SINK)
+        if (d->type == PA_DEVICE_TYPE_SINK)
             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
                                "The sink %s has no ports, and therefore there's no active port either.", d->sink->name);
         else
@@ -754,14 +752,14 @@ static void handle_set_active_port(DBusConnection *conn, DBusMessage *msg, DBusM
         return;
     }
 
-    if (d->type == DEVICE_TYPE_SINK) {
-        if ((r = pa_sink_set_port(d->sink, pa_dbusiface_device_port_get_name(new_active), TRUE)) < 0) {
+    if (d->type == PA_DEVICE_TYPE_SINK) {
+        if ((r = pa_sink_set_port(d->sink, pa_dbusiface_device_port_get_name(new_active), true)) < 0) {
             pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
                                "Internal error in PulseAudio: pa_sink_set_port() failed with error code %i.", r);
             return;
         }
     } else {
-        if ((r = pa_source_set_port(d->source, pa_dbusiface_device_port_get_name(new_active), TRUE)) < 0) {
+        if ((r = pa_source_set_port(d->source, pa_dbusiface_device_port_get_name(new_active), true)) < 0) {
             pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED,
                                "Internal error in PulseAudio: pa_source_set_port() failed with error code %i.", r);
             return;
@@ -819,7 +817,7 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat
     pa_assert(msg);
     pa_assert(d);
 
-    if (d->type == DEVICE_TYPE_SINK) {
+    if (d->type == PA_DEVICE_TYPE_SINK) {
         idx = d->sink->index;
         name = d->sink->name;
         driver = d->sink->driver;
@@ -828,17 +826,17 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat
         sample_format = d->sink->sample_spec.format;
         sample_rate = d->sink->sample_spec.rate;
         channel_map = &d->sink->channel_map;
-        has_flat_volume = d->sink->flags & PA_SINK_FLAT_VOLUME;
-        has_convertible_to_decibel_volume = d->sink->flags & PA_SINK_DECIBEL_VOLUME;
+        has_flat_volume = !!(d->sink->flags & PA_SINK_FLAT_VOLUME);
+        has_convertible_to_decibel_volume = !!(d->sink->flags & PA_SINK_DECIBEL_VOLUME);
         base_volume = d->sink->base_volume;
         volume_steps = d->sink->n_volume_steps;
-        has_hardware_volume = d->sink->flags & PA_SINK_HW_VOLUME_CTRL;
-        has_hardware_mute = d->sink->flags & PA_SINK_HW_MUTE_CTRL;
+        has_hardware_volume = !!(d->sink->flags & PA_SINK_HW_VOLUME_CTRL);
+        has_hardware_mute = !!(d->sink->flags & PA_SINK_HW_MUTE_CTRL);
         configured_latency = pa_sink_get_requested_latency(d->sink);
-        has_dynamic_latency = d->sink->flags & PA_SINK_DYNAMIC_LATENCY;
+        has_dynamic_latency = !!(d->sink->flags & PA_SINK_DYNAMIC_LATENCY);
         latency = pa_sink_get_latency(d->sink);
-        is_hardware_device = d->sink->flags & PA_SINK_HARDWARE;
-        is_network_device = d->sink->flags & PA_SINK_NETWORK;
+        is_hardware_device = !!(d->sink->flags & PA_SINK_HARDWARE);
+        is_network_device = !!(d->sink->flags & PA_SINK_NETWORK);
         state = pa_sink_get_state(d->sink);
     } else {
         idx = d->source->index;
@@ -850,16 +848,16 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat
         sample_rate = d->source->sample_spec.rate;
         channel_map = &d->source->channel_map;
         has_flat_volume = FALSE;
-        has_convertible_to_decibel_volume = d->source->flags & PA_SOURCE_DECIBEL_VOLUME;
+        has_convertible_to_decibel_volume = !!(d->source->flags & PA_SOURCE_DECIBEL_VOLUME);
         base_volume = d->source->base_volume;
         volume_steps = d->source->n_volume_steps;
-        has_hardware_volume = d->source->flags & PA_SOURCE_HW_VOLUME_CTRL;
-        has_hardware_mute = d->source->flags & PA_SOURCE_HW_MUTE_CTRL;
+        has_hardware_volume = !!(d->source->flags & PA_SOURCE_HW_VOLUME_CTRL);
+        has_hardware_mute = !!(d->source->flags & PA_SOURCE_HW_MUTE_CTRL);
         configured_latency = pa_source_get_requested_latency(d->source);
-        has_dynamic_latency = d->source->flags & PA_SOURCE_DYNAMIC_LATENCY;
+        has_dynamic_latency = !!(d->source->flags & PA_SOURCE_DYNAMIC_LATENCY);
         latency = pa_source_get_latency(d->source);
-        is_hardware_device = d->source->flags & PA_SOURCE_HARDWARE;
-        is_network_device = d->source->flags & PA_SOURCE_NETWORK;
+        is_hardware_device = !!(d->source->flags & PA_SOURCE_HARDWARE);
+        is_network_device = !!(d->source->flags & PA_SOURCE_NETWORK);
         state = pa_source_get_state(d->source);
     }
     if (owner_module)
@@ -925,19 +923,30 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat
 static void handle_suspend(DBusConnection *conn, DBusMessage *msg, void *userdata) {
     pa_dbusiface_device *d = userdata;
     dbus_bool_t suspend = FALSE;
+    pa_client *client;
 
     pa_assert(conn);
     pa_assert(msg);
     pa_assert(d);
 
     pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_BOOLEAN, &suspend, DBUS_TYPE_INVALID));
+    pa_assert_se(client = pa_dbus_protocol_get_client(d->dbus_protocol, conn));
 
-    if ((d->type == DEVICE_TYPE_SINK) && (pa_sink_suspend(d->sink, suspend, PA_SUSPEND_USER) < 0)) {
-        pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_sink_suspend() failed.");
-        return;
-    } else if ((d->type == DEVICE_TYPE_SOURCE) && (pa_source_suspend(d->source, suspend, PA_SUSPEND_USER) < 0)) {
-        pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_source_suspend() failed.");
-        return;
+    if (d->type == PA_DEVICE_TYPE_SINK) {
+        pa_log_debug("%s sink %s requested by client %" PRIu32 ".", suspend ? "Suspending" : "Resuming", d->sink->name, client->index);
+
+        if (pa_sink_suspend(d->sink, suspend, PA_SUSPEND_USER) < 0) {
+            pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_sink_suspend() failed.");
+            return;
+        }
+
+    } else {
+        pa_log_debug("%s source %s requested by client %" PRIu32 ".", suspend ? "Suspending" : "Resuming", d->source->name, client->index);
+
+        if (pa_source_suspend(d->source, suspend, PA_SUSPEND_USER) < 0) {
+            pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "Internal error in PulseAudio: pa_source_suspend() failed.");
+            return;
+        }
     }
 
     pa_dbus_send_empty_reply(conn, msg);
@@ -956,7 +965,7 @@ static void handle_get_port_by_name(DBusConnection *conn, DBusMessage *msg, void
     pa_assert_se(dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &port_name, DBUS_TYPE_INVALID));
 
     if (!(port = pa_hashmap_get(d->ports, port_name))) {
-        if (d->type == DEVICE_TYPE_SINK)
+        if (d->type == PA_DEVICE_TYPE_SINK)
             pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NOT_FOUND,
                                "%s: No such port on sink %s.", port_name, d->sink->name);
         else
@@ -977,7 +986,7 @@ static void handle_sink_get_monitor_source(DBusConnection *conn, DBusMessage *ms
     pa_assert(conn);
     pa_assert(msg);
     pa_assert(d);
-    pa_assert(d->type == DEVICE_TYPE_SINK);
+    pa_assert(d->type == PA_DEVICE_TYPE_SINK);
 
     monitor_source = pa_dbusiface_core_get_source_path(d->core, d->sink->monitor_source);
 
@@ -994,7 +1003,7 @@ static void handle_sink_get_all(DBusConnection *conn, DBusMessage *msg, void *us
     pa_assert(conn);
     pa_assert(msg);
     pa_assert(d);
-    pa_assert(d->type == DEVICE_TYPE_SINK);
+    pa_assert(d->type == PA_DEVICE_TYPE_SINK);
 
     monitor_source = pa_dbusiface_core_get_source_path(d->core, d->sink->monitor_source);
 
@@ -1019,7 +1028,7 @@ static void handle_source_get_monitor_of_sink(DBusConnection *conn, DBusMessage
     pa_assert(conn);
     pa_assert(msg);
     pa_assert(d);
-    pa_assert(d->type == DEVICE_TYPE_SOURCE);
+    pa_assert(d->type == PA_DEVICE_TYPE_SOURCE);
 
     if (!d->source->monitor_of) {
         pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Source %s is not a monitor source.", d->source->name);
@@ -1041,7 +1050,7 @@ static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *
     pa_assert(conn);
     pa_assert(msg);
     pa_assert(d);
-    pa_assert(d->type == DEVICE_TYPE_SOURCE);
+    pa_assert(d->type == PA_DEVICE_TYPE_SOURCE);
 
     if (d->source->monitor_of)
         monitor_of_sink = pa_dbusiface_core_get_sink_path(d->core, d->source->monitor_of);
@@ -1063,9 +1072,9 @@ static void handle_source_get_all(DBusConnection *conn, DBusMessage *msg, void *
 
 static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
     pa_dbusiface_device *d = userdata;
-    DBusMessage *signal = NULL;
+    DBusMessage *signal_msg = NULL;
     const pa_cvolume *new_volume = NULL;
-    pa_bool_t new_mute = FALSE;
+    bool new_mute = false;
     pa_sink_state_t new_sink_state = 0;
     pa_source_state_t new_source_state = 0;
     pa_device_port *new_active_port = NULL;
@@ -1075,20 +1084,20 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
     pa_assert(c);
     pa_assert(d);
 
-    if ((d->type == DEVICE_TYPE_SINK && idx != d->sink->index) || (d->type == DEVICE_TYPE_SOURCE && idx != d->source->index))
+    if ((d->type == PA_DEVICE_TYPE_SINK && idx != d->sink->index) || (d->type == PA_DEVICE_TYPE_SOURCE && idx != d->source->index))
         return;
 
     if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
         return;
 
-    pa_assert(((d->type == DEVICE_TYPE_SINK)
+    pa_assert(((d->type == PA_DEVICE_TYPE_SINK)
                 && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK))
-              || ((d->type == DEVICE_TYPE_SOURCE)
+              || ((d->type == PA_DEVICE_TYPE_SOURCE)
                    && ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE)));
 
-    new_volume = (d->type == DEVICE_TYPE_SINK)
-                 ? pa_sink_get_volume(d->sink, FALSE)
-                 : pa_source_get_volume(d->source, FALSE);
+    new_volume = (d->type == PA_DEVICE_TYPE_SINK)
+                 ? pa_sink_get_volume(d->sink, false)
+                 : pa_source_get_volume(d->source, false);
 
     if (!pa_cvolume_equal(&d->volume, new_volume)) {
         dbus_uint32_t volume[PA_CHANNELS_MAX];
@@ -1099,60 +1108,60 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
         for (i = 0; i < d->volume.channels; ++i)
             volume[i] = d->volume.values[i];
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_VOLUME_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal,
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                          PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                          signals[SIGNAL_VOLUME_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg,
                                               DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, d->volume.channels,
                                               DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
-    new_mute = (d->type == DEVICE_TYPE_SINK) ? pa_sink_get_mute(d->sink, FALSE) : pa_source_get_mute(d->source, FALSE);
+    new_mute = (d->type == PA_DEVICE_TYPE_SINK) ? pa_sink_get_mute(d->sink, false) : pa_source_get_mute(d->source, false);
 
     if (d->mute != new_mute) {
         d->mute = new_mute;
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_MUTE_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID));
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                          PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                          signals[SIGNAL_MUTE_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_BOOLEAN, &d->mute, DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
-    if (d->type == DEVICE_TYPE_SINK)
+    if (d->type == PA_DEVICE_TYPE_SINK)
         new_sink_state = pa_sink_get_state(d->sink);
     else
         new_source_state = pa_source_get_state(d->source);
 
-    if ((d->type == DEVICE_TYPE_SINK && d->sink_state != new_sink_state)
-        || (d->type == DEVICE_TYPE_SOURCE && d->source_state != new_source_state)) {
+    if ((d->type == PA_DEVICE_TYPE_SINK && d->sink_state != new_sink_state)
+        || (d->type == PA_DEVICE_TYPE_SOURCE && d->source_state != new_source_state)) {
         dbus_uint32_t state = 0;
 
-        if (d->type == DEVICE_TYPE_SINK)
+        if (d->type == PA_DEVICE_TYPE_SINK)
             d->sink_state = new_sink_state;
         else
             d->source_state = new_source_state;
 
-        state = (d->type == DEVICE_TYPE_SINK) ? d->sink_state : d->source_state;
+        state = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink_state : d->source_state;
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_STATE_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID));
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                          PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                          signals[SIGNAL_STATE_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
-    new_active_port = (d->type == DEVICE_TYPE_SINK) ? d->sink->active_port : d->source->active_port;
+    new_active_port = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->active_port : d->source->active_port;
 
     if (d->active_port != new_active_port) {
         const char *object_path = NULL;
@@ -1160,37 +1169,39 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
         d->active_port = new_active_port;
         object_path = pa_dbusiface_device_port_get_path(pa_hashmap_get(d->ports, d->active_port->name));
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_ACTIVE_PORT_UPDATED].name));
-        pa_assert_se(dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                          PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                          signals[SIGNAL_ACTIVE_PORT_UPDATED].name));
+        pa_assert_se(dbus_message_append_args(signal_msg, DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_INVALID));
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 
-    new_proplist = (d->type == DEVICE_TYPE_SINK) ? d->sink->proplist : d->source->proplist;
+    new_proplist = (d->type == PA_DEVICE_TYPE_SINK) ? d->sink->proplist : d->source->proplist;
 
     if (!pa_proplist_equal(d->proplist, new_proplist)) {
         DBusMessageIter msg_iter;
 
         pa_proplist_update(d->proplist, PA_UPDATE_SET, new_proplist);
 
-        pa_assert_se(signal = dbus_message_new_signal(d->path,
-                                                      PA_DBUSIFACE_DEVICE_INTERFACE,
-                                                      signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
-        dbus_message_iter_init_append(signal, &msg_iter);
+        pa_assert_se(signal_msg = dbus_message_new_signal(d->path,
+                                                          PA_DBUSIFACE_DEVICE_INTERFACE,
+                                                          signals[SIGNAL_PROPERTY_LIST_UPDATED].name));
+        dbus_message_iter_init_append(signal_msg, &msg_iter);
         pa_dbus_append_proplist(&msg_iter, d->proplist);
 
-        pa_dbus_protocol_send_signal(d->dbus_protocol, signal);
-        dbus_message_unref(signal);
-        signal = NULL;
+        pa_dbus_protocol_send_signal(d->dbus_protocol, signal_msg);
+        dbus_message_unref(signal_msg);
+        signal_msg = NULL;
     }
 }
 
 pa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_sink *sink) {
     pa_dbusiface_device *d = NULL;
+    pa_device_port *port;
+    void *state;
 
     pa_assert(core);
     pa_assert(sink);
@@ -1198,27 +1209,21 @@ pa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_si
     d = pa_xnew0(pa_dbusiface_device, 1);
     d->core = core;
     d->sink = pa_sink_ref(sink);
-    d->type = DEVICE_TYPE_SINK;
+    d->type = PA_DEVICE_TYPE_SINK;
     d->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, SINK_OBJECT_NAME, sink->index);
-    d->volume = *pa_sink_get_volume(sink, FALSE);
-    d->mute = pa_sink_get_mute(sink, FALSE);
+    d->volume = *pa_sink_get_volume(sink, false);
+    d->mute = pa_sink_get_mute(sink, false);
     d->sink_state = pa_sink_get_state(sink);
-    d->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
+    d->ports = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) pa_dbusiface_device_port_free);
     d->next_port_index = 0;
-    d->active_port = NULL;
+    d->active_port = sink->active_port;
     d->proplist = pa_proplist_copy(sink->proplist);
     d->dbus_protocol = pa_dbus_protocol_get(sink->core);
     d->subscription = pa_subscription_new(sink->core, PA_SUBSCRIPTION_MASK_SINK, subscription_cb, d);
 
-    if (sink->ports) {
-        pa_device_port *port;
-        void *state = NULL;
-
-        PA_HASHMAP_FOREACH(port, sink->ports, state) {
-            pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, sink->core, port, d->next_port_index++);
-            pa_hashmap_put(d->ports, pa_dbusiface_device_port_get_name(p), p);
-        }
-        pa_assert_se(d->active_port = sink->active_port);
+    PA_HASHMAP_FOREACH(port, sink->ports, state) {
+        pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, sink->core, port, d->next_port_index++);
+        pa_hashmap_put(d->ports, (char *) pa_dbusiface_device_port_get_name(p), p);
     }
 
     pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0);
@@ -1229,6 +1234,8 @@ pa_dbusiface_device *pa_dbusiface_device_new_sink(pa_dbusiface_core *core, pa_si
 
 pa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_source *source) {
     pa_dbusiface_device *d = NULL;
+    pa_device_port *port;
+    void *state;
 
     pa_assert(core);
     pa_assert(source);
@@ -1236,27 +1243,21 @@ pa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_
     d = pa_xnew0(pa_dbusiface_device, 1);
     d->core = core;
     d->source = pa_source_ref(source);
-    d->type = DEVICE_TYPE_SOURCE;
+    d->type = PA_DEVICE_TYPE_SOURCE;
     d->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, SOURCE_OBJECT_NAME, source->index);
-    d->volume = *pa_source_get_volume(source, FALSE);
-    d->mute = pa_source_get_mute(source, FALSE);
+    d->volume = *pa_source_get_volume(source, false);
+    d->mute = pa_source_get_mute(source, false);
     d->source_state = pa_source_get_state(source);
     d->ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
     d->next_port_index = 0;
-    d->active_port = NULL;
+    d->active_port = source->active_port;
     d->proplist = pa_proplist_copy(source->proplist);
     d->dbus_protocol = pa_dbus_protocol_get(source->core);
     d->subscription = pa_subscription_new(source->core, PA_SUBSCRIPTION_MASK_SOURCE, subscription_cb, d);
 
-    if (source->ports) {
-        pa_device_port *port;
-        void *state = NULL;
-
-        PA_HASHMAP_FOREACH(port, source->ports, state) {
-            pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, source->core, port, d->next_port_index++);
-            pa_hashmap_put(d->ports, pa_dbusiface_device_port_get_name(p), p);
-        }
-        pa_assert_se(d->active_port = source->active_port);
+    PA_HASHMAP_FOREACH(port, source->ports, state) {
+        pa_dbusiface_device_port *p = pa_dbusiface_device_port_new(d, source->core, port, d->next_port_index++);
+        pa_hashmap_put(d->ports, (char *) pa_dbusiface_device_port_get_name(p), p);
     }
 
     pa_assert_se(pa_dbus_protocol_add_interface(d->dbus_protocol, d->path, &device_interface_info, d) >= 0);
@@ -1265,20 +1266,12 @@ pa_dbusiface_device *pa_dbusiface_device_new_source(pa_dbusiface_core *core, pa_
     return d;
 }
 
-static void port_free_cb(void *p, void *userdata) {
-    pa_dbusiface_device_port *port = p;
-
-    pa_assert(port);
-
-    pa_dbusiface_device_port_free(port);
-}
-
 void pa_dbusiface_device_free(pa_dbusiface_device *d) {
     pa_assert(d);
 
     pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, device_interface_info.name) >= 0);
 
-    if (d->type == DEVICE_TYPE_SINK) {
+    if (d->type == PA_DEVICE_TYPE_SINK) {
         pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, sink_interface_info.name) >= 0);
         pa_sink_unref(d->sink);
 
@@ -1286,7 +1279,7 @@ void pa_dbusiface_device_free(pa_dbusiface_device *d) {
         pa_assert_se(pa_dbus_protocol_remove_interface(d->dbus_protocol, d->path, source_interface_info.name) >= 0);
         pa_source_unref(d->source);
     }
-    pa_hashmap_free(d->ports, port_free_cb, NULL);
+    pa_hashmap_free(d->ports);
     pa_proplist_free(d->proplist);
     pa_dbus_protocol_unref(d->dbus_protocol);
     pa_subscription_free(d->subscription);
@@ -1303,14 +1296,14 @@ const char *pa_dbusiface_device_get_path(pa_dbusiface_device *d) {
 
 pa_sink *pa_dbusiface_device_get_sink(pa_dbusiface_device *d) {
     pa_assert(d);
-    pa_assert(d->type == DEVICE_TYPE_SINK);
+    pa_assert(d->type == PA_DEVICE_TYPE_SINK);
 
     return d->sink;
 }
 
 pa_source *pa_dbusiface_device_get_source(pa_dbusiface_device *d) {
     pa_assert(d);
-    pa_assert(d->type == DEVICE_TYPE_SOURCE);
+    pa_assert(d->type == PA_DEVICE_TYPE_SOURCE);
 
     return d->source;
 }