summaryrefslogtreecommitdiffstats
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/coreaudio/module-coreaudio-device.c2
-rw-r--r--src/modules/dbus/iface-stream.c121
-rw-r--r--src/modules/echo-cancel/module-echo-cancel.c6
-rw-r--r--src/modules/module-equalizer-sink.c4
-rw-r--r--src/modules/module-ladspa-sink.c3
-rw-r--r--src/modules/module-remap-sink.c3
-rw-r--r--src/modules/module-solaris.c2
-rw-r--r--src/modules/module-stream-restore.c14
-rw-r--r--src/modules/module-virtual-sink.c3
-rw-r--r--src/modules/module-virtual-source.c3
10 files changed, 110 insertions, 51 deletions
diff --git a/src/modules/coreaudio/module-coreaudio-device.c b/src/modules/coreaudio/module-coreaudio-device.c
index 5e6d49c2..cc4600b5 100644
--- a/src/modules/coreaudio/module-coreaudio-device.c
+++ b/src/modules/coreaudio/module-coreaudio-device.c
@@ -747,7 +747,7 @@ int pa__init(pa_module *m) {
ca_device_create_streams(m, TRUE);
/* create the message thread */
- if (!(u->thread = pa_thread_new(thread_func, u))) {
+ if (!(u->thread = pa_thread_new("coreaudio", thread_func, u))) {
pa_log("Failed to create thread.");
goto fail;
}
diff --git a/src/modules/dbus/iface-stream.c b/src/modules/dbus/iface-stream.c
index 681790b7..a9eb373f 100644
--- a/src/modules/dbus/iface-stream.c
+++ b/src/modules/dbus/iface-stream.c
@@ -56,6 +56,9 @@ struct pa_dbusiface_stream {
dbus_bool_t mute;
pa_proplist *proplist;
+ pa_bool_t has_volume;
+ pa_bool_t read_only_volume;
+
pa_dbus_protocol *dbus_protocol;
pa_subscription *subscription;
pa_hook_slot *send_event_slot;
@@ -189,6 +192,14 @@ static void handle_get_index(DBusConnection *conn, DBusMessage *msg, void *userd
pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &idx);
}
+/* The returned string has to be freed with pa_xfree() by the caller. */
+static char *stream_to_string(pa_dbusiface_stream *s) {
+ if (s->type == STREAM_TYPE_PLAYBACK)
+ return pa_sprintf_malloc("Playback stream %u", (unsigned) s->sink_input->index);
+ else
+ return pa_sprintf_malloc("Record stream %u", (unsigned) s->source_output->index);
+}
+
static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *userdata) {
pa_dbusiface_stream *s = userdata;
const char *driver = NULL;
@@ -200,12 +211,11 @@ static void handle_get_driver(DBusConnection *conn, DBusMessage *msg, void *user
driver = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->driver : s->source_output->driver;
if (!driver) {
- if (s->type == STREAM_TYPE_PLAYBACK)
- pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
- "Playback stream %u doesn't have a driver.", s->sink_input->index);
- else
- pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
- "Record stream %u doesn't have a driver.", s->source_output->index);
+ char *str = stream_to_string(s);
+
+ pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have a driver.", str);
+ pa_xfree(str);
+
return;
}
@@ -224,12 +234,11 @@ static void handle_get_owner_module(DBusConnection *conn, DBusMessage *msg, void
owner_module = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->module : s->source_output->module;
if (!owner_module) {
- if (s->type == STREAM_TYPE_PLAYBACK)
- pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
- "Playback stream %u doesn't have an owner module.", s->sink_input->index);
- else
- pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
- "Record stream %u doesn't have an owner module.", s->source_output->index);
+ char *str = stream_to_string(s);
+
+ pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have an owner module.", str);
+ pa_xfree(str);
+
return;
}
@@ -250,12 +259,11 @@ static void handle_get_client(DBusConnection *conn, DBusMessage *msg, void *user
client = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->client : s->source_output->client;
if (!client) {
- if (s->type == STREAM_TYPE_PLAYBACK)
- pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
- "Playback stream %u isn't associated to any client.", s->sink_input->index);
- else
- pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY,
- "Record stream %u isn't associated to any client.", s->source_output->index);
+ char *str = stream_to_string(s);
+
+ pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s isn't associated to any client.", str);
+ pa_xfree(str);
+
return;
}
@@ -332,8 +340,12 @@ static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *user
pa_assert(msg);
pa_assert(s);
- if (s->type == STREAM_TYPE_RECORD) {
- pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have volume.");
+ if (!s->has_volume) {
+ char *str = stream_to_string(s);
+
+ pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have volume.", str);
+ pa_xfree(str);
+
return;
}
@@ -357,8 +369,15 @@ static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessag
pa_assert(iter);
pa_assert(s);
- if (s->type == STREAM_TYPE_RECORD) {
- pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "Record streams don't have volume.");
+ if (!s->has_volume || s->read_only_volume) {
+ char *str = stream_to_string(s);
+
+ if (!s->has_volume)
+ pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have volume.", str);
+ else if (s->read_only_volume)
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "%s has read-only volume.", str);
+ pa_xfree(str);
+
return;
}
@@ -509,6 +528,11 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat
pa_assert(msg);
pa_assert(s);
+ if (s->has_volume) {
+ for (i = 0; i < s->volume.channels; ++i)
+ volume[i] = s->volume.values[i];
+ }
+
if (s->type == STREAM_TYPE_PLAYBACK) {
idx = s->sink_input->index;
driver = s->sink_input->driver;
@@ -517,8 +541,6 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat
device = pa_dbusiface_core_get_sink_path(s->core, s->sink);
sample_format = s->sink_input->sample_spec.format;
channel_map = &s->sink_input->channel_map;
- for (i = 0; i < s->volume.channels; ++i)
- volume[i] = s->volume.values[i];
buffer_latency = pa_sink_input_get_latency(s->sink_input, &device_latency);
resample_method = pa_resample_method_to_string(s->sink_input->actual_resample_method);
} else {
@@ -555,11 +577,12 @@ static void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *userdat
if (client)
pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CLIENT].property_name, DBUS_TYPE_OBJECT_PATH, &client_path);
+ pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_DEVICE].property_name, DBUS_TYPE_OBJECT_PATH, &device);
pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_FORMAT].property_name, DBUS_TYPE_UINT32, &sample_format);
pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_SAMPLE_RATE].property_name, DBUS_TYPE_UINT32, &s->sample_rate);
pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_CHANNELS].property_name, DBUS_TYPE_UINT32, channels, channel_map->channels);
- if (s->type == STREAM_TYPE_PLAYBACK) {
+ if (s->has_volume) {
pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_VOLUME].property_name, DBUS_TYPE_UINT32, volume, s->volume.channels);
pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_MUTE].property_name, DBUS_TYPE_BOOLEAN, &s->mute);
}
@@ -707,30 +730,33 @@ static void subscription_cb(pa_core *c, pa_subscription_event_type_t t, uint32_t
}
if (s->type == STREAM_TYPE_PLAYBACK) {
- pa_cvolume new_volume;
pa_bool_t new_mute = FALSE;
- pa_sink_input_get_volume(s->sink_input, &new_volume, TRUE);
+ if (s->has_volume) {
+ pa_cvolume new_volume;
- if (!pa_cvolume_equal(&s->volume, &new_volume)) {
- dbus_uint32_t volume[PA_CHANNELS_MAX];
- dbus_uint32_t *volume_ptr = volume;
+ pa_sink_input_get_volume(s->sink_input, &new_volume, TRUE);
- s->volume = new_volume;
+ if (!pa_cvolume_equal(&s->volume, &new_volume)) {
+ dbus_uint32_t volume[PA_CHANNELS_MAX];
+ dbus_uint32_t *volume_ptr = volume;
- for (i = 0; i < s->volume.channels; ++i)
- volume[i] = s->volume.values[i];
+ s->volume = new_volume;
- pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
- PA_DBUSIFACE_STREAM_INTERFACE,
- signals[SIGNAL_VOLUME_UPDATED].name));
- pa_assert_se(dbus_message_append_args(signal_msg,
- DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels,
- DBUS_TYPE_INVALID));
+ for (i = 0; i < s->volume.channels; ++i)
+ volume[i] = s->volume.values[i];
- pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
- dbus_message_unref(signal_msg);
- signal_msg = NULL;
+ pa_assert_se(signal_msg = dbus_message_new_signal(s->path,
+ PA_DBUSIFACE_STREAM_INTERFACE,
+ signals[SIGNAL_VOLUME_UPDATED].name));
+ pa_assert_se(dbus_message_append_args(signal_msg,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &volume_ptr, s->volume.channels,
+ DBUS_TYPE_INVALID));
+
+ pa_dbus_protocol_send_signal(s->dbus_protocol, signal_msg);
+ dbus_message_unref(signal_msg);
+ signal_msg = NULL;
+ }
}
new_mute = pa_sink_input_get_mute(s->sink_input);
@@ -822,7 +848,14 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, p
s->path = pa_sprintf_malloc("%s/%s%u", PA_DBUS_CORE_OBJECT_PATH, PLAYBACK_OBJECT_NAME, sink_input->index);
s->sink = pa_sink_ref(sink_input->sink);
s->sample_rate = sink_input->sample_spec.rate;
- pa_sink_input_get_volume(sink_input, &s->volume, TRUE);
+ s->has_volume = pa_sink_input_is_volume_readable(sink_input);
+ s->read_only_volume = s->has_volume ? !pa_sink_input_is_volume_writable(sink_input) : FALSE;
+
+ if (s->has_volume)
+ pa_sink_input_get_volume(sink_input, &s->volume, TRUE);
+ else
+ pa_cvolume_init(&s->volume);
+
s->mute = pa_sink_input_get_mute(sink_input);
s->proplist = pa_proplist_copy(sink_input->proplist);
s->dbus_protocol = pa_dbus_protocol_get(sink_input->core);
@@ -853,6 +886,8 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_
pa_cvolume_init(&s->volume);
s->mute = FALSE;
s->proplist = pa_proplist_copy(source_output->proplist);
+ s->has_volume = FALSE;
+ s->read_only_volume = FALSE;
s->dbus_protocol = pa_dbus_protocol_get(source_output->core);
s->subscription = pa_subscription_new(source_output->core, PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscription_cb, s);
s->send_event_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT],
diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index 611ebb71..0108c31b 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -1502,6 +1502,7 @@ int pa__init(pa_module*m) {
source_output_data.driver = __FILE__;
source_output_data.module = m;
source_output_data.source = source_master;
+ source_output_data.destination_source = u->source;
/* FIXME
source_output_data.flags = PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; */
@@ -1531,11 +1532,14 @@ int pa__init(pa_module*m) {
u->source_output->moving = source_output_moving_cb;
u->source_output->userdata = u;
+ u->source->output_from_master = u->source_output;
+
/* Create sink input */
pa_sink_input_new_data_init(&sink_input_data);
sink_input_data.driver = __FILE__;
sink_input_data.module = m;
sink_input_data.sink = sink_master;
+ sink_input_data.origin_sink = u->sink;
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Echo-Cancel Sink Stream");
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
pa_sink_input_new_data_set_sample_spec(&sink_input_data, &sink_ss);
@@ -1566,6 +1570,8 @@ int pa__init(pa_module*m) {
u->sink_input->mute_changed = sink_input_mute_changed_cb;
u->sink_input->userdata = u;
+ u->sink->input_to_master = u->sink_input;
+
pa_sink_input_get_silence(u->sink_input, &silence);
u->source_memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0,
diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c
index bc349ce0..a28405b6 100644
--- a/src/modules/module-equalizer-sink.c
+++ b/src/modules/module-equalizer-sink.c
@@ -1200,6 +1200,7 @@ int pa__init(pa_module*m) {
sink_input_data.driver = __FILE__;
sink_input_data.module = m;
sink_input_data.sink = master;
+ sink_input_data.origin_sink = u->sink;
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Equalized Stream");
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
@@ -1225,9 +1226,10 @@ int pa__init(pa_module*m) {
u->sink_input->moving = sink_input_moving_cb;
u->sink_input->volume_changed = sink_input_volume_changed_cb;
u->sink_input->mute_changed = sink_input_mute_changed_cb;
-
u->sink_input->userdata = u;
+ u->sink->input_to_master = u->sink_input;
+
dbus_init(u);
/* default filter to these */
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 88df67ec..cdccf1a3 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -832,6 +832,7 @@ int pa__init(pa_module*m) {
sink_input_data.driver = __FILE__;
sink_input_data.module = m;
sink_input_data.sink = master;
+ sink_input_data.origin_sink = u->sink;
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "LADSPA Stream");
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
@@ -859,6 +860,8 @@ int pa__init(pa_module*m) {
u->sink_input->mute_changed = sink_input_mute_changed_cb;
u->sink_input->userdata = u;
+ u->sink->input_to_master = u->sink_input;
+
pa_sink_put(u->sink);
pa_sink_input_put(u->sink_input);
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 43748bd0..7f64f306 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -420,6 +420,7 @@ int pa__init(pa_module*m) {
sink_input_data.driver = __FILE__;
sink_input_data.module = m;
sink_input_data.sink = master;
+ sink_input_data.origin_sink = u->sink;
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Remapped Stream");
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
@@ -446,6 +447,8 @@ int pa__init(pa_module*m) {
u->sink_input->moving = sink_input_moving_cb;
u->sink_input->userdata = u;
+ u->sink->input_to_master = u->sink_input;
+
pa_sink_put(u->sink);
pa_sink_input_put(u->sink_input);
diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c
index 396094ce..5c1a86c2 100644
--- a/src/modules/module-solaris.c
+++ b/src/modules/module-solaris.c
@@ -1015,7 +1015,7 @@ int pa__init(pa_module *m) {
else
pa_log_warn("Could not register SIGPOLL handler");
- if (!(u->thread = pa_thread_new(thread_func, u))) {
+ if (!(u->thread = pa_thread_new("solaris", thread_func, u))) {
pa_log("Failed to create thread.");
goto fail;
}
diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index f8fecd89..f4e4a55c 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1168,6 +1168,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
}
if (sink_input->save_volume) {
+ pa_assert(pa_sink_input_is_volume_writable(sink_input));
+
entry.channel_map = sink_input->channel_map;
pa_sink_input_get_volume(sink_input, &entry.volume, FALSE);
entry.volume_valid = TRUE;
@@ -1327,8 +1329,11 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu
if ((e = read_entry(u, name))) {
if (u->restore_volume && e->volume_valid) {
-
- if (!new_data->volume_is_set) {
+ if (!pa_sink_input_new_data_is_volume_writable(new_data))
+ pa_log_debug("Not restoring volume for sink input %s, because its volume can't be changed.", name);
+ else if (new_data->volume_is_set)
+ pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
+ else {
pa_cvolume v;
pa_log_info("Restoring volume for sink input %s.", name);
@@ -1339,8 +1344,7 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu
new_data->volume_is_absolute = FALSE;
new_data->save_volume = TRUE;
- } else
- pa_log_debug("Not restoring volume for sink input %s, because already set.", name);
+ }
}
if (u->restore_muted && e->muted_valid) {
@@ -1615,7 +1619,7 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) {
}
pa_xfree(n);
- if (u->restore_volume && e->volume_valid) {
+ if (u->restore_volume && e->volume_valid && pa_sink_input_is_volume_writable(si)) {
pa_cvolume v;
v = e->volume;
diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-sink.c
index fac204d4..40bab5aa 100644
--- a/src/modules/module-virtual-sink.c
+++ b/src/modules/module-virtual-sink.c
@@ -556,6 +556,7 @@ int pa__init(pa_module*m) {
sink_input_data.driver = __FILE__;
sink_input_data.module = m;
sink_input_data.sink = master;
+ sink_input_data.origin_sink = u->sink;
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Virtual Sink Stream");
pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
@@ -583,6 +584,8 @@ int pa__init(pa_module*m) {
u->sink_input->mute_changed = sink_input_mute_changed_cb;
u->sink_input->userdata = u;
+ u->sink->input_to_master = u->sink_input;
+
/* (9) IF YOU REQUIRE A FIXED BLOCK SIZE MAKE SURE TO PASS A
* SILENCE MEMBLOCK AS LAST PARAMETER
* HERE. pa_sink_input_get_silence() IS USEFUL HERE. */
diff --git a/src/modules/module-virtual-source.c b/src/modules/module-virtual-source.c
index fdf89b02..a2b073fa 100644
--- a/src/modules/module-virtual-source.c
+++ b/src/modules/module-virtual-source.c
@@ -629,6 +629,7 @@ int pa__init(pa_module*m) {
source_output_data.driver = __FILE__;
source_output_data.module = m;
source_output_data.source = master;
+ source_output_data.destination_source = u->source;
/* FIXME
source_output_data.flags = PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; */
@@ -654,6 +655,8 @@ int pa__init(pa_module*m) {
u->source_output->moving = source_output_moving_cb;
u->source_output->userdata = u;
+ u->source->output_from_master = u->source_output;
+
pa_source_put(u->source);
pa_source_output_put(u->source_output);