From: Tanu Kaskinen Date: Sun, 16 Aug 2009 18:25:48 +0000 (+0300) Subject: Merge branch 'master' of git://0pointer.de/pulseaudio into dbus-work X-Git-Tag: v0.98-dev~354^2~31 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bcaba0b1b43d6a1b32aadfa98860f40b2c93e136;p=platform%2Fupstream%2Fpulseaudio.git Merge branch 'master' of git://0pointer.de/pulseaudio into dbus-work Conflicts: src/Makefile.am src/daemon/daemon-conf.c src/daemon/daemon.conf.in src/modules/module-stream-restore.c src/pulse/client-conf.c src/pulsecore/namereg.c --- bcaba0b1b43d6a1b32aadfa98860f40b2c93e136 diff --cc po/es.po index 8af1c7384,b36d69394..6995716ef --- a/po/es.po +++ b/po/es.po @@@ -2600,9 -2408,8 +2408,7 @@@ msgstr "Servidor de Sonido PulseAudio #~ "Tipo: %s\n" #~ "Módulo: %s\n" #~ "Argumento: %s\n" - #~ msgid "sink" #~ msgstr "destino" - #~ msgid "source" #~ msgstr "fuente" - diff --cc po/pt_BR.po index fd4f53919,20365eeba..323e5b944 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@@ -2497,6 -2370,6 +2370,5 @@@ msgstr "Servidor de som PulseAudio #~ msgstr "" #~ "', ou eleve o RLIMIT_NICE/RLIMIT_RTPRIO dos limites do recurso para este " #~ "usuário." - #~ msgid "socketpair(): %s" #~ msgstr "socketpair(): %s" - diff --cc src/daemon/daemon-conf.c index ace460edc,9a87b5552..31f290094 --- a/src/daemon/daemon-conf.c +++ b/src/daemon/daemon-conf.c @@@ -476,14 -441,15 +476,18 @@@ int pa_daemon_conf_load(pa_daemon_conf { "high-priority", pa_config_parse_bool, &c->high_priority, NULL }, { "realtime-scheduling", pa_config_parse_bool, &c->realtime_scheduling, NULL }, { "disallow-module-loading", pa_config_parse_bool, &c->disallow_module_loading, NULL }, + { "allow-module-loading", pa_config_parse_not_bool, &c->disallow_module_loading, NULL }, { "disallow-exit", pa_config_parse_bool, &c->disallow_exit, NULL }, + { "allow-exit", pa_config_parse_not_bool, &c->disallow_exit, NULL }, { "use-pid-file", pa_config_parse_bool, &c->use_pid_file, NULL }, { "system-instance", pa_config_parse_bool, &c->system_instance, NULL }, +#ifdef HAVE_DBUS + { "local-server-type", parse_server_type, c, NULL }, +#endif { "no-cpu-limit", pa_config_parse_bool, &c->no_cpu_limit, NULL }, + { "cpu-limit", pa_config_parse_not_bool, &c->no_cpu_limit, NULL }, { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL }, + { "enable-shm", pa_config_parse_not_bool, &c->disable_shm, NULL }, { "flat-volumes", pa_config_parse_bool, &c->flat_volumes, NULL }, { "lock-memory", pa_config_parse_bool, &c->lock_memory, NULL }, { "exit-idle-time", pa_config_parse_int, &c->exit_idle_time, NULL }, @@@ -669,15 -629,12 +675,15 @@@ char *pa_daemon_conf_dump(pa_daemon_con pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level); pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling)); pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority); - pa_strbuf_printf(s, "disallow-module-loading = %s\n", pa_yes_no(c->disallow_module_loading)); - pa_strbuf_printf(s, "disallow-exit = %s\n", pa_yes_no(c->disallow_exit)); + pa_strbuf_printf(s, "allow-module-loading = %s\n", pa_yes_no(!c->disallow_module_loading)); + pa_strbuf_printf(s, "allow-exit = %s\n", pa_yes_no(!c->disallow_exit)); pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file)); pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance)); +#ifdef HAVE_DBUS + pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]); +#endif - pa_strbuf_printf(s, "no-cpu-limit = %s\n", pa_yes_no(c->no_cpu_limit)); - pa_strbuf_printf(s, "disable-shm = %s\n", pa_yes_no(c->disable_shm)); + pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit)); + pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm)); pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes)); pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory)); pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time); diff --cc src/daemon/daemon.conf.in index 9bea6148c,d8b58d8a0..a11fd06c5 --- a/src/daemon/daemon.conf.in +++ b/src/daemon/daemon.conf.in @@@ -21,15 -21,14 +21,15 @@@ ; daemonize = no ; fail = yes - ; disallow-module-loading = no - ; disallow-exit = no + ; allow-module-loading = yes + ; allow-exit = yes ; use-pid-file = yes ; system-instance = no +; local-server-type = user - ; disable-shm = no + ; enable-shm = yes ; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB ; lock-memory = no - ; no-cpu-limit = no + ; cpu-limit = yes ; high-priority = yes ; nice-level = -11 diff --cc src/modules/module-stream-restore.c index e90630310,e560bd280..076b39189 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@@ -106,15 -100,9 +106,15 @@@ struct userdata pa_native_protocol *protocol; pa_idxset *subscribed; + +#ifdef HAVE_DBUS + pa_dbus_protocol *dbus_protocol; + pa_hashmap *dbus_entries; + uint32_t next_index; /* For generating object paths for entries. */ +#endif }; - #define ENTRY_VERSION 2 + #define ENTRY_VERSION 3 struct entry { uint8_t version; @@@ -1216,7 -324,10 +1231,11 @@@ static void subscribe_callback(pa_core pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device)); entry.device_valid = TRUE; + device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device)); + if (sink_input->sink->card) { + pa_strlcpy(entry.card, sink_input->sink->card->name, sizeof(entry.card)); + entry.card_valid = TRUE; + } } } else { @@@ -1239,7 -348,10 +1258,12 @@@ pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device)); entry.device_valid = source_output->save_source; + device_updated = !created_new_entry && (!old->device_valid || !pa_streq(entry.device, old->device)); ++ + if (source_output->source->card) { + pa_strlcpy(entry.card, source_output->source->card->name, sizeof(entry.card)); + entry.card_valid = TRUE; + } } } diff --cc src/pulse/client-conf.c index 8eab1094d,4aa4ba1fc..62c06f6aa --- a/src/pulse/client-conf.c +++ b/src/pulse/client-conf.c @@@ -94,17 -92,17 +94,18 @@@ int pa_client_conf_load(pa_client_conf /* Prepare the configuration parse table */ pa_config_item table[] = { - { "daemon-binary", pa_config_parse_string, &c->daemon_binary, NULL }, - { "extra-arguments", pa_config_parse_string, &c->extra_arguments, NULL }, - { "default-sink", pa_config_parse_string, &c->default_sink, NULL }, - { "default-source", pa_config_parse_string, &c->default_source, NULL }, - { "default-server", pa_config_parse_string, &c->default_server, NULL }, - { "default-dbus-server", pa_config_parse_string, &c->default_dbus_server, NULL }, - { "autospawn", pa_config_parse_bool, &c->autospawn, NULL }, - { "cookie-file", pa_config_parse_string, &c->cookie_file, NULL }, - { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL }, - { "shm-size-bytes", pa_config_parse_size, &c->shm_size, NULL }, - { NULL, NULL, NULL, NULL }, + { "daemon-binary", pa_config_parse_string, &c->daemon_binary, NULL }, + { "extra-arguments", pa_config_parse_string, &c->extra_arguments, NULL }, + { "default-sink", pa_config_parse_string, &c->default_sink, NULL }, + { "default-source", pa_config_parse_string, &c->default_source, NULL }, + { "default-server", pa_config_parse_string, &c->default_server, NULL }, ++ { "default-dbus-server", pa_config_parse_string, &c->default_dbus_server, NULL }, + { "autospawn", pa_config_parse_bool, &c->autospawn, NULL }, + { "cookie-file", pa_config_parse_string, &c->cookie_file, NULL }, + { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL }, + { "enable-shm", pa_config_parse_not_bool, &c->disable_shm, NULL }, + { "shm-size-bytes", pa_config_parse_size, &c->shm_size, NULL }, + { NULL, NULL, NULL, NULL }, }; if (filename) { diff --cc src/pulsecore/dbus-util.c index 903acadb7,4e6148f07..b45e6a6c6 --- a/src/pulsecore/dbus-util.c +++ b/src/pulsecore/dbus-util.c @@@ -445,475 -422,3 +445,475 @@@ void pa_dbus_free_pending_list(pa_dbus_ pa_dbus_pending_free(i); } } + +void pa_dbus_send_error(DBusConnection *c, DBusMessage *in_reply_to, const char *name, const char *format, ...) { + va_list ap; + char *message; + DBusMessage *reply = NULL; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(name); + pa_assert(format); + + va_start(ap, format); + message = pa_vsprintf_malloc(format, ap); + va_end(ap); + pa_assert_se((reply = dbus_message_new_error(in_reply_to, name, message))); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + + dbus_message_unref(reply); + + pa_xfree(message); +} + +void pa_dbus_send_empty_reply(DBusConnection *c, DBusMessage *in_reply_to) { + DBusMessage *reply = NULL; + + pa_assert(c); + pa_assert(in_reply_to); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +void pa_dbus_send_basic_value_reply(DBusConnection *c, DBusMessage *in_reply_to, int type, void *data) { + DBusMessage *reply = NULL; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + pa_assert_se(dbus_message_append_args(reply, type, data, DBUS_TYPE_INVALID)); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +static const char *signature_from_basic_type(int type) { + switch (type) { + case DBUS_TYPE_BOOLEAN: return DBUS_TYPE_BOOLEAN_AS_STRING; + case DBUS_TYPE_BYTE: return DBUS_TYPE_BYTE_AS_STRING; + case DBUS_TYPE_INT16: return DBUS_TYPE_INT16_AS_STRING; + case DBUS_TYPE_UINT16: return DBUS_TYPE_UINT16_AS_STRING; + case DBUS_TYPE_INT32: return DBUS_TYPE_INT32_AS_STRING; + case DBUS_TYPE_UINT32: return DBUS_TYPE_UINT32_AS_STRING; + case DBUS_TYPE_INT64: return DBUS_TYPE_INT64_AS_STRING; + case DBUS_TYPE_UINT64: return DBUS_TYPE_UINT64_AS_STRING; + case DBUS_TYPE_DOUBLE: return DBUS_TYPE_DOUBLE_AS_STRING; + case DBUS_TYPE_STRING: return DBUS_TYPE_STRING_AS_STRING; + case DBUS_TYPE_OBJECT_PATH: return DBUS_TYPE_OBJECT_PATH_AS_STRING; + case DBUS_TYPE_SIGNATURE: return DBUS_TYPE_SIGNATURE_AS_STRING; + default: pa_assert_not_reached(); + } +} + +void pa_dbus_send_basic_variant_reply(DBusConnection *c, DBusMessage *in_reply_to, int type, void *data) { + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + DBusMessageIter variant_iter; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + dbus_message_iter_init_append(reply, &msg_iter); + pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_VARIANT, signature_from_basic_type(type), &variant_iter)); + pa_assert_se(dbus_message_iter_append_basic(&variant_iter, type, data)); + pa_assert_se(dbus_message_iter_close_container(&msg_iter, &variant_iter)); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +/* Note: returns sizeof(char*) for strings, object paths and signatures. */ +static unsigned basic_type_size(int type) { + switch (type) { + case DBUS_TYPE_BOOLEAN: return sizeof(dbus_bool_t); + case DBUS_TYPE_BYTE: return 1; + case DBUS_TYPE_INT16: return sizeof(dbus_int16_t); + case DBUS_TYPE_UINT16: return sizeof(dbus_uint16_t); + case DBUS_TYPE_INT32: return sizeof(dbus_int32_t); + case DBUS_TYPE_UINT32: return sizeof(dbus_uint32_t); + case DBUS_TYPE_INT64: return sizeof(dbus_int64_t); + case DBUS_TYPE_UINT64: return sizeof(dbus_uint64_t); + case DBUS_TYPE_DOUBLE: return sizeof(double); + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + case DBUS_TYPE_SIGNATURE: return sizeof(char*); + default: pa_assert_not_reached(); + } +} + +void pa_dbus_send_basic_array_variant_reply(DBusConnection *c, DBusMessage *in_reply_to, int item_type, void *array, unsigned n) { + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(dbus_type_is_basic(item_type)); + pa_assert(array || n == 0); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + dbus_message_iter_init_append(reply, &msg_iter); + pa_dbus_append_basic_array_variant(&msg_iter, item_type, array, n); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +void pa_dbus_send_proplist_variant_reply(DBusConnection *c, DBusMessage *in_reply_to, pa_proplist *proplist) { + DBusMessage *reply = NULL; + DBusMessageIter msg_iter; + + pa_assert(c); + pa_assert(in_reply_to); + pa_assert(proplist); + + pa_assert_se((reply = dbus_message_new_method_return(in_reply_to))); + dbus_message_iter_init_append(reply, &msg_iter); + pa_dbus_append_proplist_variant(&msg_iter, proplist); + pa_assert_se(dbus_connection_send(c, reply, NULL)); + dbus_message_unref(reply); +} + +void pa_dbus_append_basic_array(DBusMessageIter *iter, int item_type, const void *array, unsigned n) { + DBusMessageIter array_iter; + unsigned i; + unsigned item_size; + + pa_assert(iter); + pa_assert(dbus_type_is_basic(item_type)); + pa_assert(array || n == 0); + + item_size = basic_type_size(item_type); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, signature_from_basic_type(item_type), &array_iter)); + + for (i = 0; i < n; ++i) + pa_assert_se(dbus_message_iter_append_basic(&array_iter, item_type, &((uint8_t*) array)[i * item_size])); + + pa_assert_se(dbus_message_iter_close_container(iter, &array_iter)); +}; + +void pa_dbus_append_basic_variant(DBusMessageIter *iter, int type, void *data) { + DBusMessageIter variant_iter; + + pa_assert(iter); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, signature_from_basic_type(type), &variant_iter)); + pa_assert_se(dbus_message_iter_append_basic(&variant_iter, type, data)); + pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); +} + +void pa_dbus_append_basic_array_variant(DBusMessageIter *iter, int item_type, const void *array, unsigned n) { + DBusMessageIter variant_iter; + char *array_signature; + + pa_assert(iter); + pa_assert(dbus_type_is_basic(item_type)); + pa_assert(array || n == 0); + + array_signature = pa_sprintf_malloc("a%c", *signature_from_basic_type(item_type)); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, array_signature, &variant_iter)); + pa_dbus_append_basic_array(&variant_iter, item_type, array, n); + pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); + + pa_xfree(array_signature); +} + +void pa_dbus_append_basic_variant_dict_entry(DBusMessageIter *dict_iter, const char *key, int type, void *data) { + DBusMessageIter dict_entry_iter; + + pa_assert(dict_iter); + pa_assert(key); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + pa_assert_se(dbus_message_iter_open_container(dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); + pa_dbus_append_basic_variant(&dict_entry_iter, type, data); + pa_assert_se(dbus_message_iter_close_container(dict_iter, &dict_entry_iter)); +} + +void pa_dbus_append_basic_array_variant_dict_entry(DBusMessageIter *dict_iter, const char *key, int item_type, const void *array, unsigned n) { + DBusMessageIter dict_entry_iter; + + pa_assert(dict_iter); + pa_assert(key); + pa_assert(dbus_type_is_basic(item_type)); + pa_assert(array || n == 0); + + pa_assert_se(dbus_message_iter_open_container(dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); + pa_dbus_append_basic_array_variant(&dict_entry_iter, item_type, array, n); + pa_assert_se(dbus_message_iter_close_container(dict_iter, &dict_entry_iter)); +} + +void pa_dbus_append_proplist(DBusMessageIter *iter, pa_proplist *proplist) { + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + DBusMessageIter array_iter; + void *state = NULL; + const char *key; + + pa_assert(iter); + pa_assert(proplist); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{say}", &dict_iter)); + - while ((key = pa_proplist_iterate(proplist, state))) { ++ while ((key = pa_proplist_iterate(proplist, &state))) { + const void *value = NULL; + size_t nbytes; + + pa_assert_se(pa_proplist_get(proplist, key, &value, &nbytes) >= 0); + + pa_assert_se(dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); + + pa_assert_se(dbus_message_iter_open_container(&dict_entry_iter, DBUS_TYPE_ARRAY, "y", &array_iter)); + pa_assert_se(dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE, &value, nbytes)); + pa_assert_se(dbus_message_iter_close_container(&dict_entry_iter, &array_iter)); + + pa_assert_se(dbus_message_iter_close_container(&dict_iter, &dict_entry_iter)); + } + + pa_assert_se(dbus_message_iter_close_container(iter, &dict_iter)); +} + +void pa_dbus_append_proplist_variant(DBusMessageIter *iter, pa_proplist *proplist) { + DBusMessageIter variant_iter; + + pa_assert(iter); + pa_assert(proplist); + + pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, "a{say}", &variant_iter)); + pa_dbus_append_proplist(&variant_iter, proplist); + pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); +} + +void pa_dbus_append_proplist_variant_dict_entry(DBusMessageIter *dict_iter, const char *key, pa_proplist *proplist) { + DBusMessageIter dict_entry_iter; + + pa_assert(dict_iter); + pa_assert(key); + pa_assert(proplist); + + pa_assert_se(dbus_message_iter_open_container(dict_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry_iter)); + pa_assert_se(dbus_message_iter_append_basic(&dict_entry_iter, DBUS_TYPE_STRING, &key)); + pa_dbus_append_proplist_variant(&dict_entry_iter, proplist); + pa_assert_se(dbus_message_iter_close_container(dict_iter, &dict_entry_iter)); +} + +int pa_dbus_get_basic_set_property_arg(DBusConnection *c, DBusMessage *msg, int type, void *data) { + DBusMessageIter msg_iter; + DBusMessageIter variant_iter; + + pa_assert(c); + pa_assert(msg); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + /* Skip the interface and property name arguments. */ + if (!dbus_message_iter_init(msg, &msg_iter) || !dbus_message_iter_next(&msg_iter) || !dbus_message_iter_next(&msg_iter)) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments."); + return -1; + } + + if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_VARIANT) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Message argument isn't a variant."); + return -1; + } + + dbus_message_iter_recurse(&msg_iter, &variant_iter); + + if (pa_dbus_get_basic_arg(c, msg, &variant_iter, type, data) < 0) + return -1; + + return 0; +} + +int pa_dbus_get_fixed_array_set_property_arg(DBusConnection *c, DBusMessage *msg, int item_type, void *data, unsigned *n) { + DBusMessageIter msg_iter; + DBusMessageIter variant_iter; + + pa_assert(c); + pa_assert(msg); + pa_assert(dbus_type_is_fixed(item_type)); + pa_assert(data); + pa_assert(n); + + /* Skip the interface and property name arguments. */ + if (!dbus_message_iter_init(msg, &msg_iter) || !dbus_message_iter_next(&msg_iter) || !dbus_message_iter_next(&msg_iter)) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments."); + return -1; + } + + if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_VARIANT) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Message argument isn't a variant."); + return -1; + } + + dbus_message_iter_recurse(&msg_iter, &variant_iter); + + if (pa_dbus_get_fixed_array_arg(c, msg, &variant_iter, item_type, data, n) < 0) + return -1; + + return 0; +} + +int pa_dbus_get_basic_arg(DBusConnection *c, DBusMessage *msg, DBusMessageIter *iter, int type, void *data) { + int arg_type; + + pa_assert(c); + pa_assert(msg); + pa_assert(iter); + pa_assert(dbus_type_is_basic(type)); + pa_assert(data); + + arg_type = dbus_message_iter_get_arg_type(iter); + if (arg_type != type) { + if (arg_type == DBUS_TYPE_INVALID) + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments. D-Bus type '%c' expected.", (char) type); + else + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Wrong argument type: '%c'. Expected type '%c'.", (char) arg_type, (char) type); + return -1; + } + + dbus_message_iter_get_basic(iter, data); + + dbus_message_iter_next(iter); + + return 0; +} + +int pa_dbus_get_fixed_array_arg(DBusConnection *c, DBusMessage *msg, DBusMessageIter *iter, int item_type, void *array, unsigned *n) { + DBusMessageIter array_iter; + int signed_n; + int arg_type; + int element_type; + + pa_assert(c); + pa_assert(msg); + pa_assert(iter); + pa_assert(dbus_type_is_fixed(item_type)); + pa_assert(array); + pa_assert(n); + + arg_type = dbus_message_iter_get_arg_type(iter); + if (arg_type != DBUS_TYPE_ARRAY) { + if (arg_type == DBUS_TYPE_INVALID) + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments. An array of type '%c' was expected.", (char) item_type); + else + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Wrong argument type: '%c'. An array of type '%c' was expected.", (char) arg_type, (char) item_type); + return -1; + } + + element_type = dbus_message_iter_get_element_type(iter); + if (element_type != item_type) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Wrong array element type: '%c'. Element type '%c' was expected.", (char) element_type, (char) item_type); + return -1; + } + + dbus_message_iter_recurse(iter, &array_iter); + + dbus_message_iter_get_fixed_array(&array_iter, array, &signed_n); + + dbus_message_iter_next(iter); + + pa_assert(signed_n >= 0); + + *n = signed_n; + + return 0; +} + +pa_proplist *pa_dbus_get_proplist_arg(DBusConnection *c, DBusMessage *msg, DBusMessageIter *iter) { + DBusMessageIter dict_iter; + DBusMessageIter dict_entry_iter; + int arg_type; + pa_proplist *proplist = NULL; + const char *key; + const uint8_t *value; + int value_length; + + pa_assert(c); + pa_assert(msg); + pa_assert(iter); + + arg_type = dbus_message_iter_get_arg_type(iter); + if (arg_type != DBUS_TYPE_ARRAY) { + if (arg_type == DBUS_TYPE_INVALID) + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Too few arguments. An array was expected."); + else + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Wrong argument type: '%c'. An array was expected.", (char) arg_type); + return NULL; + } + + arg_type = dbus_message_iter_get_element_type(iter); + if (arg_type != DBUS_TYPE_DICT_ENTRY) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Wrong array element type: '%c'. A dictionary entry was expected.", (char) arg_type); + return NULL; + } + + proplist = pa_proplist_new(); + + dbus_message_iter_recurse(iter, &dict_iter); + + while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) { + dbus_message_iter_recurse(&dict_iter, &dict_entry_iter); + + arg_type = dbus_message_iter_get_arg_type(&dict_entry_iter); + if (arg_type != DBUS_TYPE_STRING) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Wrong dict key type: '%c'. A string was expected.", (char) arg_type); + goto fail; + } + + dbus_message_iter_get_basic(&dict_entry_iter, &key); + dbus_message_iter_next(&dict_entry_iter); + + if (strlen(key) <= 0 || !pa_ascii_valid(key)) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Invalid property list key."); + goto fail; + } + + arg_type = dbus_message_iter_get_arg_type(&dict_entry_iter); + if (arg_type != DBUS_TYPE_ARRAY) { + if (arg_type == DBUS_TYPE_INVALID) + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Dict value missing."); + else + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Wrong dict value type: '%c'. An array was expected.", (char) arg_type); + goto fail; + } + + arg_type = dbus_message_iter_get_element_type(&dict_entry_iter); + if (arg_type != DBUS_TYPE_BYTE) { + pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Wrong dict value item type: '%c'. A byte was expected.", (char) arg_type); + goto fail; + } + + dbus_message_iter_get_fixed_array(&dict_entry_iter, &value, &value_length); + + pa_assert(value_length >= 0); + + pa_assert_se(pa_proplist_set(proplist, key, value, value_length) >= 0); + + dbus_message_iter_next(&dict_iter); + } + + dbus_message_iter_next(iter); + + return proplist; + +fail: + if (proplist) + pa_proplist_free(proplist); + + return NULL; +} diff --cc src/pulsecore/namereg.c index 046c87b20,e26923d41..d7d83c5e8 --- a/src/pulsecore/namereg.c +++ b/src/pulsecore/namereg.c @@@ -166,31 -160,10 +166,38 @@@ void pa_namereg_unregister(pa_core *c, pa_assert_se(e = pa_hashmap_remove(c->namereg, name)); - if (c->default_sink == e->data) - pa_namereg_set_default_sink(c, NULL); - else if (c->default_source == e->data) - pa_namereg_set_default_source(c, NULL); + if (c->default_sink == e->data) { - pa_sink *new_default = pa_idxset_first(c->sinks, &idx); ++ pa_sink *new_default = NULL; + - if (new_default == e->data) - new_default = pa_idxset_next(c->sinks, &idx); ++ /* FIXME: the selection here should be based priority values on ++ * the sinks */ ++ ++ PA_IDXSET_FOREACH(new_default, c->sinks, idx) { ++ if (new_default != e->data && PA_SINK_IS_LINKED(pa_sink_get_state(new_default))) ++ break; ++ } + + pa_namereg_set_default_sink(c, new_default); + + } else if (c->default_source == e->data) { - pa_source *new_default; ++ pa_source *new_default = NULL; + - for (new_default = pa_idxset_first(c->sources, &idx); new_default; new_default = pa_idxset_next(c->sources, &idx)) { - if (new_default != e->data && !new_default->monitor_of) ++ /* First, try to find one that isn't a monitor */ ++ PA_IDXSET_FOREACH(new_default, c->sources, idx) { ++ if (new_default != e->data && !new_default->monitor_of && PA_SOURCE_IS_LINKED(pa_source_get_state(new_default))) + break; + } + + if (!new_default) { - new_default = pa_idxset_first(c->sources, &idx); - - if (new_default == e->data) - new_default = pa_idxset_next(c->sources, &idx); ++ /* Then, fallback to a monitor */ ++ PA_IDXSET_FOREACH(new_default, c->sources, idx) { ++ if (new_default != e->data && PA_SOURCE_IS_LINKED(pa_source_get_state(new_default))) ++ break; ++ } + } + + pa_namereg_set_default_source(c, new_default); + } pa_xfree(e->name); pa_xfree(e); @@@ -268,16 -248,43 +281,49 @@@ pa_source* pa_namereg_set_default_sourc return s; } +/* XXX: After removing old functionality, has this function become useless? */ pa_sink *pa_namereg_get_default_sink(pa_core *c) { + pa_sink *s; + uint32_t idx; + pa_assert(c); - return c->default_sink; - if (c->default_sink && PA_SINK_IS_LINKED(pa_sink_get_state(c->default_sink))) ++ if (!c->default_sink || PA_SINK_IS_LINKED(pa_sink_get_state(c->default_sink))) + return c->default_sink; + ++ /* The old default sink has become unlinked, set a new one. */ ++ + /* FIXME: the selection here should be based priority values on + * the sinks */ + + PA_IDXSET_FOREACH(s, c->sinks, idx) + if (PA_SINK_IS_LINKED(pa_sink_get_state(s))) + return pa_namereg_set_default_sink(c, s); + - return NULL; ++ return pa_namereg_set_default_sink(c, NULL); } +/* XXX: After removing old functionality, has this function become useless? */ pa_source *pa_namereg_get_default_source(pa_core *c) { + pa_source *s; + uint32_t idx; + pa_assert(c); - return c->default_source; - if (c->default_source && PA_SOURCE_IS_LINKED(pa_source_get_state(c->default_source))) ++ if (!c->default_source || PA_SOURCE_IS_LINKED(pa_source_get_state(c->default_source))) + return c->default_source; + ++ /* The old default source has become unlinked, set a new one. */ ++ + /* First, try to find one that isn't a monitor */ + PA_IDXSET_FOREACH(s, c->sources, idx) + if (!s->monitor_of && PA_SOURCE_IS_LINKED(pa_source_get_state(s))) + return pa_namereg_set_default_source(c, s); + + /* Then, fallback to a monitor */ + PA_IDXSET_FOREACH(s, c->sources, idx) + if (PA_SOURCE_IS_LINKED(pa_source_get_state(s))) + return pa_namereg_set_default_source(c, s); + - return NULL; ++ return pa_namereg_set_default_source(c, NULL); }