mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	Merge remote branch 'tanuk2/fixes'
This commit is contained in:
		
						commit
						1415a295c2
					
				
					 7 changed files with 118 additions and 82 deletions
				
			
		| 
						 | 
				
			
			@ -1037,7 +1037,7 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) {
 | 
			
		|||
 | 
			
		||||
        e->switch_use = PA_ALSA_SWITCH_IGNORE;
 | 
			
		||||
        e->volume_use = PA_ALSA_VOLUME_IGNORE;
 | 
			
		||||
        e->enumeration_use = PA_ALSA_VOLUME_IGNORE;
 | 
			
		||||
        e->enumeration_use = PA_ALSA_ENUMERATION_IGNORE;
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2683,7 +2683,7 @@ static int mapping_parse_description(
 | 
			
		|||
    pa_assert(ps);
 | 
			
		||||
 | 
			
		||||
    if ((m = mapping_get(ps, section))) {
 | 
			
		||||
        pa_xstrdup(m->description);
 | 
			
		||||
        pa_xfree(m->description);
 | 
			
		||||
        m->description = pa_xstrdup(rvalue);
 | 
			
		||||
    } else if ((p = profile_get(ps, section))) {
 | 
			
		||||
        pa_xfree(p->description);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1252,10 +1252,7 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
 | 
			
		|||
        s->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
 | 
			
		||||
        s->n_volume_steps = PA_VOLUME_NORM+1;
 | 
			
		||||
 | 
			
		||||
        if (u->mixer_path->max_dB > 0.0)
 | 
			
		||||
        pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(s->base_volume));
 | 
			
		||||
        else
 | 
			
		||||
            pa_log_info("No particular base volume set, fixing to 0 dB");
 | 
			
		||||
    } else {
 | 
			
		||||
        s->base_volume = PA_VOLUME_NORM;
 | 
			
		||||
        s->n_volume_steps = u->mixer_path->max_volume - u->mixer_path->min_volume + 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1186,10 +1186,7 @@ static int source_set_port_cb(pa_source *s, pa_device_port *p) {
 | 
			
		|||
        s->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
 | 
			
		||||
        s->n_volume_steps = PA_VOLUME_NORM+1;
 | 
			
		||||
 | 
			
		||||
        if (u->mixer_path->max_dB > 0.0)
 | 
			
		||||
        pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(s->base_volume));
 | 
			
		||||
        else
 | 
			
		||||
            pa_log_info("No particular base volume set, fixing to 0 dB");
 | 
			
		||||
    } else {
 | 
			
		||||
        s->base_volume = PA_VOLUME_NORM;
 | 
			
		||||
        s->n_volume_steps = u->mixer_path->max_volume - u->mixer_path->min_volume + 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,13 +48,12 @@
 | 
			
		|||
PA_MODULE_DESCRIPTION("D-Bus interface");
 | 
			
		||||
PA_MODULE_USAGE(
 | 
			
		||||
        "access=local|remote|local,remote "
 | 
			
		||||
        "tcp_port=<port number>");
 | 
			
		||||
        "tcp_port=<port number> "
 | 
			
		||||
        "tcp_listen=<hostname>");
 | 
			
		||||
PA_MODULE_LOAD_ONCE(TRUE);
 | 
			
		||||
PA_MODULE_AUTHOR("Tanu Kaskinen");
 | 
			
		||||
PA_MODULE_VERSION(PACKAGE_VERSION);
 | 
			
		||||
 | 
			
		||||
#define CLEANUP_INTERVAL 10 /* seconds */
 | 
			
		||||
 | 
			
		||||
enum server_type {
 | 
			
		||||
    SERVER_TYPE_LOCAL,
 | 
			
		||||
    SERVER_TYPE_TCP
 | 
			
		||||
| 
						 | 
				
			
			@ -68,13 +67,14 @@ struct userdata {
 | 
			
		|||
    pa_bool_t local_access;
 | 
			
		||||
    pa_bool_t remote_access;
 | 
			
		||||
    uint32_t tcp_port;
 | 
			
		||||
    char *tcp_listen;
 | 
			
		||||
 | 
			
		||||
    struct server *local_server;
 | 
			
		||||
    struct server *tcp_server;
 | 
			
		||||
 | 
			
		||||
    pa_idxset *connections;
 | 
			
		||||
 | 
			
		||||
    pa_time_event *cleanup_event;
 | 
			
		||||
    pa_defer_event *cleanup_event;
 | 
			
		||||
 | 
			
		||||
    pa_dbus_protocol *dbus_protocol;
 | 
			
		||||
    pa_dbusiface_core *core_iface;
 | 
			
		||||
| 
						 | 
				
			
			@ -95,6 +95,7 @@ struct connection {
 | 
			
		|||
static const char* const valid_modargs[] = {
 | 
			
		||||
    "access",
 | 
			
		||||
    "tcp_port",
 | 
			
		||||
    "tcp_listen",
 | 
			
		||||
    NULL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -154,6 +155,23 @@ static dbus_bool_t user_check_cb(DBusConnection *connection, unsigned long uid,
 | 
			
		|||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DBusHandlerResult disconnection_filter_cb(DBusConnection *connection, DBusMessage *message, void *user_data) {
 | 
			
		||||
    struct connection *c = user_data;
 | 
			
		||||
 | 
			
		||||
    pa_assert(connection);
 | 
			
		||||
    pa_assert(message);
 | 
			
		||||
    pa_assert(c);
 | 
			
		||||
 | 
			
		||||
    if (dbus_message_is_signal(message, "org.freedesktop.DBus.Local", "Disconnected")) {
 | 
			
		||||
        /* The connection died. Now we want to free the connection object, but
 | 
			
		||||
         * let's wait until this message is fully processed, in case someone
 | 
			
		||||
         * else is interested in this signal too. */
 | 
			
		||||
        c->server->userdata->module->core->mainloop->defer_enable(c->server->userdata->cleanup_event, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Called by D-Bus when a new client connection is received. */
 | 
			
		||||
static void connection_new_cb(DBusServer *dbus_server, DBusConnection *new_connection, void *data) {
 | 
			
		||||
    struct server *s = data;
 | 
			
		||||
| 
						 | 
				
			
			@ -192,6 +210,8 @@ static void connection_new_cb(DBusServer *dbus_server, DBusConnection *new_conne
 | 
			
		|||
    c->client->send_event = client_send_event_cb;
 | 
			
		||||
    c->client->userdata = c;
 | 
			
		||||
 | 
			
		||||
    pa_assert_se(dbus_connection_add_filter(new_connection, disconnection_filter_cb, c, NULL));
 | 
			
		||||
 | 
			
		||||
    pa_idxset_put(s->userdata->connections, c, NULL);
 | 
			
		||||
 | 
			
		||||
    pa_assert_se(pa_dbus_protocol_register_connection(s->userdata->dbus_protocol, new_connection, c->client) >= 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -401,6 +421,7 @@ static struct server *start_server(struct userdata *u, const char *address, enum
 | 
			
		|||
 | 
			
		||||
    s = pa_xnew0(struct server, 1);
 | 
			
		||||
    s->userdata = u;
 | 
			
		||||
    s->type = type;
 | 
			
		||||
    s->dbus_server = dbus_server_listen(address, &error);
 | 
			
		||||
 | 
			
		||||
    if (dbus_error_is_set(&error)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -452,7 +473,7 @@ static struct server *start_tcp_server(struct userdata *u) {
 | 
			
		|||
 | 
			
		||||
    pa_assert(u);
 | 
			
		||||
 | 
			
		||||
    address = pa_sprintf_malloc("tcp:host=127.0.0.1,port=%u", u->tcp_port);
 | 
			
		||||
    address = pa_sprintf_malloc("tcp:host=%s,port=%u", u->tcp_listen, u->tcp_port);
 | 
			
		||||
 | 
			
		||||
    s = start_server(u, address, SERVER_TYPE_TCP); /* May return NULL */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -486,33 +507,23 @@ static int get_access_arg(pa_modargs *ma, pa_bool_t *local_access, pa_bool_t *re
 | 
			
		|||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Frees dead client connections. Called every CLEANUP_INTERVAL seconds. */
 | 
			
		||||
static void cleanup_cb(pa_mainloop_api *a, pa_time_event *e, const struct timeval *tv, void *userdata) {
 | 
			
		||||
/* Frees dead client connections. */
 | 
			
		||||
static void cleanup_cb(pa_mainloop_api *a, pa_defer_event *e, void *userdata) {
 | 
			
		||||
    struct userdata *u = userdata;
 | 
			
		||||
    struct connection *conn = NULL;
 | 
			
		||||
    uint32_t idx;
 | 
			
		||||
    struct timeval cleanup_timeval;
 | 
			
		||||
    unsigned free_count = 0;
 | 
			
		||||
 | 
			
		||||
    for (conn = pa_idxset_first(u->connections, &idx); conn; conn = pa_idxset_next(u->connections, &idx)) {
 | 
			
		||||
        if (!dbus_connection_get_is_connected(pa_dbus_wrap_connection_get(conn->wrap_conn))) {
 | 
			
		||||
    PA_IDXSET_FOREACH(conn, u->connections, idx) {
 | 
			
		||||
        if (!dbus_connection_get_is_connected(pa_dbus_wrap_connection_get(conn->wrap_conn)))
 | 
			
		||||
            connection_free(conn);
 | 
			
		||||
            ++free_count;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (free_count > 0)
 | 
			
		||||
        pa_log_debug("Freed %u dead D-Bus client connections.", free_count);
 | 
			
		||||
 | 
			
		||||
    pa_gettimeofday(&cleanup_timeval);
 | 
			
		||||
    cleanup_timeval.tv_sec += CLEANUP_INTERVAL;
 | 
			
		||||
    u->module->core->mainloop->time_restart(e, &cleanup_timeval);
 | 
			
		||||
    u->module->core->mainloop->defer_enable(e, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pa__init(pa_module *m) {
 | 
			
		||||
    struct userdata *u = NULL;
 | 
			
		||||
    pa_modargs *ma = NULL;
 | 
			
		||||
    struct timeval cleanup_timeval;
 | 
			
		||||
 | 
			
		||||
    pa_assert(m);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -537,6 +548,8 @@ int pa__init(pa_module *m) {
 | 
			
		|||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    u->tcp_listen = pa_xstrdup(pa_modargs_get_value(ma, "tcp_listen", "0.0.0.0"));
 | 
			
		||||
 | 
			
		||||
    if (u->local_access && !(u->local_server = start_local_server(u))) {
 | 
			
		||||
        pa_log("Starting the local D-Bus server failed.");
 | 
			
		||||
        goto fail;
 | 
			
		||||
| 
						 | 
				
			
			@ -549,9 +562,8 @@ int pa__init(pa_module *m) {
 | 
			
		|||
 | 
			
		||||
    u->connections = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
 | 
			
		||||
 | 
			
		||||
    pa_gettimeofday(&cleanup_timeval);
 | 
			
		||||
    cleanup_timeval.tv_sec += CLEANUP_INTERVAL;
 | 
			
		||||
    u->cleanup_event = m->core->mainloop->time_new(m->core->mainloop, &cleanup_timeval, cleanup_cb, u);
 | 
			
		||||
    u->cleanup_event = m->core->mainloop->defer_new(m->core->mainloop, cleanup_cb, u);
 | 
			
		||||
    m->core->mainloop->defer_enable(u->cleanup_event, 0);
 | 
			
		||||
 | 
			
		||||
    u->dbus_protocol = pa_dbus_protocol_get(m->core);
 | 
			
		||||
    u->core_iface = pa_dbusiface_core_new(m->core);
 | 
			
		||||
| 
						 | 
				
			
			@ -588,7 +600,7 @@ void pa__done(pa_module *m) {
 | 
			
		|||
        pa_dbusiface_core_free(u->core_iface);
 | 
			
		||||
 | 
			
		||||
    if (u->cleanup_event)
 | 
			
		||||
        m->core->mainloop->time_free(u->cleanup_event);
 | 
			
		||||
        m->core->mainloop->defer_free(u->cleanup_event);
 | 
			
		||||
 | 
			
		||||
    if (u->connections)
 | 
			
		||||
        pa_idxset_free(u->connections, connection_free_cb, NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -602,6 +614,7 @@ void pa__done(pa_module *m) {
 | 
			
		|||
    if (u->dbus_protocol)
 | 
			
		||||
        pa_dbus_protocol_unref(u->dbus_protocol);
 | 
			
		||||
 | 
			
		||||
    pa_xfree(u->tcp_listen);
 | 
			
		||||
    pa_xfree(u);
 | 
			
		||||
    m->userdata = NULL;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -310,7 +310,7 @@ static struct dbus_entry *dbus_entry_new(struct userdata *u, const char *entry_n
 | 
			
		|||
    de->index = u->next_index++;
 | 
			
		||||
    de->object_path = pa_sprintf_malloc("%s/%s%u", OBJECT_PATH, ENTRY_OBJECT_NAME, de->index);
 | 
			
		||||
 | 
			
		||||
    pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, u) >= 0);
 | 
			
		||||
    pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, de->object_path, &entry_interface_info, de) >= 0);
 | 
			
		||||
 | 
			
		||||
    return de;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -765,6 +765,7 @@ static void handle_entry_set_device(DBusConnection *conn, DBusMessage *msg, DBus
 | 
			
		|||
        value.size = sizeof(struct entry);
 | 
			
		||||
        pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
 | 
			
		||||
 | 
			
		||||
        apply_entry(de->userdata, de->entry_name, e);
 | 
			
		||||
        send_device_updated_signal(de, e);
 | 
			
		||||
        trigger_save(de->userdata);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -829,6 +830,7 @@ static void handle_entry_set_volume(DBusConnection *conn, DBusMessage *msg, DBus
 | 
			
		|||
        value.size = sizeof(struct entry);
 | 
			
		||||
        pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
 | 
			
		||||
 | 
			
		||||
        apply_entry(de->userdata, de->entry_name, e);
 | 
			
		||||
        send_volume_updated_signal(de, e);
 | 
			
		||||
        trigger_save(de->userdata);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -886,6 +888,7 @@ static void handle_entry_set_mute(DBusConnection *conn, DBusMessage *msg, DBusMe
 | 
			
		|||
        value.size = sizeof(struct entry);
 | 
			
		||||
        pa_assert_se(pa_database_set(de->userdata->database, &key, &value, TRUE) == 0);
 | 
			
		||||
 | 
			
		||||
        apply_entry(de->userdata, de->entry_name, e);
 | 
			
		||||
        send_mute_updated_signal(de, e);
 | 
			
		||||
        trigger_save(de->userdata);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1766,7 +1766,7 @@ int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bo
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, pa_bool_t *fail) {
 | 
			
		||||
    char line[1024];
 | 
			
		||||
    char line[2048];
 | 
			
		||||
    int ifstate = IFSTATE_NONE;
 | 
			
		||||
    int ret = -1;
 | 
			
		||||
    pa_bool_t _fail = TRUE;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,12 +63,18 @@ struct connection_entry {
 | 
			
		|||
     * are accepted. Only used when listening_for_all_signals == TRUE. */
 | 
			
		||||
    pa_idxset *all_signals_objects;
 | 
			
		||||
 | 
			
		||||
    /* Signal name -> idxset. The idxsets contain object paths. If an idxset is
 | 
			
		||||
     * empty, then that signal is accepted from all objects. Only used when
 | 
			
		||||
     * listening_for_all_signals == FALSE. */
 | 
			
		||||
    /* Signal name -> signal paths entry. The entries contain object paths. If
 | 
			
		||||
     * a path set is empty, then that signal is accepted from all objects. This
 | 
			
		||||
     * variable is only used when listening_for_all_signals == FALSE. */
 | 
			
		||||
    pa_hashmap *listening_signals;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Only used in connection entries' listening_signals hashmap. */
 | 
			
		||||
struct signal_paths_entry {
 | 
			
		||||
    char *signal;
 | 
			
		||||
    pa_idxset *paths;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct interface_entry {
 | 
			
		||||
    char *name;
 | 
			
		||||
    pa_hashmap *method_handlers;
 | 
			
		||||
| 
						 | 
				
			
			@ -406,7 +412,7 @@ static enum find_result_t find_handler_from_properties_call(struct call_info *ca
 | 
			
		|||
                return NO_SUCH_PROPERTY_INTERFACE;
 | 
			
		||||
            else if ((call_info->property_handler =
 | 
			
		||||
                        pa_hashmap_get(call_info->iface_entry->property_handlers, call_info->property)))
 | 
			
		||||
                return FOUND_GET_PROPERTY;
 | 
			
		||||
                return call_info->property_handler->get_cb ? FOUND_GET_PROPERTY : PROPERTY_ACCESS_DENIED;
 | 
			
		||||
            else
 | 
			
		||||
                return NO_SUCH_PROPERTY;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -440,7 +446,7 @@ static enum find_result_t find_handler_from_properties_call(struct call_info *ca
 | 
			
		|||
                call_info->expected_property_sig = call_info->property_handler->type;
 | 
			
		||||
 | 
			
		||||
                if (pa_streq(call_info->property_sig, call_info->expected_property_sig))
 | 
			
		||||
                    return FOUND_SET_PROPERTY;
 | 
			
		||||
                    return call_info->property_handler->set_cb ? FOUND_SET_PROPERTY : PROPERTY_ACCESS_DENIED;
 | 
			
		||||
                else
 | 
			
		||||
                    return INVALID_PROPERTY_SIG;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -919,22 +925,35 @@ static void unregister_all_objects(pa_dbus_protocol *p, DBusConnection *conn) {
 | 
			
		|||
        pa_assert_se(dbus_connection_unregister_object_path(conn, obj_entry->path));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void free_listened_object_name_cb(void *p, void *userdata) {
 | 
			
		||||
    pa_assert(p);
 | 
			
		||||
static struct signal_paths_entry *signal_paths_entry_new(const char *signal_name) {
 | 
			
		||||
    struct signal_paths_entry *e = NULL;
 | 
			
		||||
 | 
			
		||||
    pa_xfree(p);
 | 
			
		||||
    pa_assert(signal_name);
 | 
			
		||||
 | 
			
		||||
    e = pa_xnew0(struct signal_paths_entry, 1);
 | 
			
		||||
    e->signal = pa_xstrdup(signal_name);
 | 
			
		||||
    e->paths = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
 | 
			
		||||
 | 
			
		||||
    return e;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void free_listening_signals_idxset_cb(void *p, void *userdata) {
 | 
			
		||||
    pa_idxset *set = p;
 | 
			
		||||
static void signal_paths_entry_free(struct signal_paths_entry *e) {
 | 
			
		||||
    char *path = NULL;
 | 
			
		||||
 | 
			
		||||
    pa_assert(set);
 | 
			
		||||
    pa_assert(e);
 | 
			
		||||
 | 
			
		||||
    pa_idxset_free(set, free_listened_object_name_cb, NULL);
 | 
			
		||||
    pa_xfree(e->signal);
 | 
			
		||||
 | 
			
		||||
    while ((path = pa_idxset_steal_first(e->paths, NULL)))
 | 
			
		||||
        pa_xfree(path);
 | 
			
		||||
 | 
			
		||||
    pa_xfree(e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pa_dbus_protocol_unregister_connection(pa_dbus_protocol *p, DBusConnection *conn) {
 | 
			
		||||
    struct connection_entry *conn_entry;
 | 
			
		||||
    struct connection_entry *conn_entry = NULL;
 | 
			
		||||
    struct signal_paths_entry *signal_paths_entry = NULL;
 | 
			
		||||
    char *object_path = NULL;
 | 
			
		||||
 | 
			
		||||
    pa_assert(p);
 | 
			
		||||
    pa_assert(conn);
 | 
			
		||||
| 
						 | 
				
			
			@ -945,8 +964,13 @@ int pa_dbus_protocol_unregister_connection(pa_dbus_protocol *p, DBusConnection *
 | 
			
		|||
    unregister_all_objects(p, conn);
 | 
			
		||||
 | 
			
		||||
    dbus_connection_unref(conn_entry->connection);
 | 
			
		||||
    pa_idxset_free(conn_entry->all_signals_objects, free_listened_object_name_cb, NULL);
 | 
			
		||||
    pa_hashmap_free(conn_entry->listening_signals, free_listening_signals_idxset_cb, NULL);
 | 
			
		||||
 | 
			
		||||
    while ((object_path = pa_idxset_steal_first(conn_entry->all_signals_objects, NULL)))
 | 
			
		||||
        pa_xfree(object_path);
 | 
			
		||||
 | 
			
		||||
    while ((signal_paths_entry = pa_hashmap_steal_first(conn_entry->listening_signals)))
 | 
			
		||||
        signal_paths_entry_free(signal_paths_entry);
 | 
			
		||||
 | 
			
		||||
    pa_xfree(conn_entry);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -970,10 +994,10 @@ void pa_dbus_protocol_add_signal_listener(
 | 
			
		|||
        const char *signal_name,
 | 
			
		||||
        char **objects,
 | 
			
		||||
        unsigned n_objects) {
 | 
			
		||||
    struct connection_entry *conn_entry;
 | 
			
		||||
    pa_idxset *object_set;
 | 
			
		||||
    char *object_path;
 | 
			
		||||
    unsigned i;
 | 
			
		||||
    struct connection_entry *conn_entry = NULL;
 | 
			
		||||
    struct signal_paths_entry *signal_paths_entry = NULL;
 | 
			
		||||
    char *object_path = NULL;
 | 
			
		||||
    unsigned i = 0;
 | 
			
		||||
 | 
			
		||||
    pa_assert(p);
 | 
			
		||||
    pa_assert(conn);
 | 
			
		||||
| 
						 | 
				
			
			@ -983,30 +1007,31 @@ void pa_dbus_protocol_add_signal_listener(
 | 
			
		|||
 | 
			
		||||
    /* all_signals_objects will either be emptied or replaced with new objects,
 | 
			
		||||
     * so we empty it here unconditionally. If listening_for_all_signals is
 | 
			
		||||
     * currently FALSE, the idxset is empty already. */
 | 
			
		||||
     * currently FALSE, the idxset is empty already so this does nothing. */
 | 
			
		||||
    while ((object_path = pa_idxset_steal_first(conn_entry->all_signals_objects, NULL)))
 | 
			
		||||
        pa_xfree(object_path);
 | 
			
		||||
 | 
			
		||||
    if (signal_name) {
 | 
			
		||||
        conn_entry->listening_for_all_signals = FALSE;
 | 
			
		||||
 | 
			
		||||
        /* Replace the old object list with a new one. */
 | 
			
		||||
        if ((object_set = pa_hashmap_remove(conn_entry->listening_signals, signal_name)))
 | 
			
		||||
            pa_idxset_free(object_set, free_listened_object_name_cb, NULL);
 | 
			
		||||
        object_set = pa_idxset_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
 | 
			
		||||
        /* Replace the old signal paths entry for this signal with a new
 | 
			
		||||
         * one. */
 | 
			
		||||
        if ((signal_paths_entry = pa_hashmap_remove(conn_entry->listening_signals, signal_name)))
 | 
			
		||||
            signal_paths_entry_free(signal_paths_entry);
 | 
			
		||||
        signal_paths_entry = signal_paths_entry_new(signal_name);
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < n_objects; ++i)
 | 
			
		||||
            pa_idxset_put(object_set, pa_xstrdup(objects[i]), NULL);
 | 
			
		||||
            pa_idxset_put(signal_paths_entry->paths, pa_xstrdup(objects[i]), NULL);
 | 
			
		||||
 | 
			
		||||
        pa_hashmap_put(conn_entry->listening_signals, signal_name, object_set);
 | 
			
		||||
        pa_hashmap_put(conn_entry->listening_signals, signal_paths_entry->signal, signal_paths_entry);
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        conn_entry->listening_for_all_signals = TRUE;
 | 
			
		||||
 | 
			
		||||
        /* We're not interested in individual signals anymore, so let's empty
 | 
			
		||||
         * listening_signals. */
 | 
			
		||||
        while ((object_set = pa_hashmap_steal_first(conn_entry->listening_signals)))
 | 
			
		||||
            pa_idxset_free(object_set, free_listened_object_name_cb, NULL);
 | 
			
		||||
        while ((signal_paths_entry = pa_hashmap_steal_first(conn_entry->listening_signals)))
 | 
			
		||||
            signal_paths_entry_free(signal_paths_entry);
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < n_objects; ++i)
 | 
			
		||||
            pa_idxset_put(conn_entry->all_signals_objects, pa_xstrdup(objects[i]), NULL);
 | 
			
		||||
| 
						 | 
				
			
			@ -1014,8 +1039,8 @@ void pa_dbus_protocol_add_signal_listener(
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection *conn, const char *signal_name) {
 | 
			
		||||
    struct connection_entry *conn_entry;
 | 
			
		||||
    pa_idxset *object_set;
 | 
			
		||||
    struct connection_entry *conn_entry = NULL;
 | 
			
		||||
    struct signal_paths_entry *signal_paths_entry = NULL;
 | 
			
		||||
 | 
			
		||||
    pa_assert(p);
 | 
			
		||||
    pa_assert(conn);
 | 
			
		||||
| 
						 | 
				
			
			@ -1023,8 +1048,8 @@ void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection
 | 
			
		|||
    pa_assert_se((conn_entry = pa_hashmap_get(p->connections, conn)));
 | 
			
		||||
 | 
			
		||||
    if (signal_name) {
 | 
			
		||||
        if ((object_set = pa_hashmap_get(conn_entry->listening_signals, signal_name)))
 | 
			
		||||
            pa_idxset_free(object_set, free_listened_object_name_cb, NULL);
 | 
			
		||||
        if ((signal_paths_entry = pa_hashmap_get(conn_entry->listening_signals, signal_name)))
 | 
			
		||||
            signal_paths_entry_free(signal_paths_entry);
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        char *object_path;
 | 
			
		||||
| 
						 | 
				
			
			@ -1034,37 +1059,38 @@ void pa_dbus_protocol_remove_signal_listener(pa_dbus_protocol *p, DBusConnection
 | 
			
		|||
        while ((object_path = pa_idxset_steal_first(conn_entry->all_signals_objects, NULL)))
 | 
			
		||||
            pa_xfree(object_path);
 | 
			
		||||
 | 
			
		||||
        while ((object_set = pa_hashmap_steal_first(conn_entry->listening_signals)))
 | 
			
		||||
            pa_idxset_free(object_set, free_listened_object_name_cb, NULL);
 | 
			
		||||
        while ((signal_paths_entry = pa_hashmap_steal_first(conn_entry->listening_signals)))
 | 
			
		||||
            signal_paths_entry_free(signal_paths_entry);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal_name) {
 | 
			
		||||
void pa_dbus_protocol_send_signal(pa_dbus_protocol *p, DBusMessage *signal_msg) {
 | 
			
		||||
    struct connection_entry *conn_entry;
 | 
			
		||||
    struct signal_paths_entry *signal_paths_entry;
 | 
			
		||||
    void *state = NULL;
 | 
			
		||||
    pa_idxset *object_set;
 | 
			
		||||
    DBusMessage *signal_copy;
 | 
			
		||||
    char *signal_string;
 | 
			
		||||
 | 
			
		||||
    pa_assert(p);
 | 
			
		||||
    pa_assert(signal_name);
 | 
			
		||||
    pa_assert(dbus_message_get_type(signal_name) == DBUS_MESSAGE_TYPE_SIGNAL);
 | 
			
		||||
    pa_assert_se(dbus_message_get_interface(signal_name));
 | 
			
		||||
    pa_assert_se(dbus_message_get_member(signal_name));
 | 
			
		||||
    pa_assert(signal_msg);
 | 
			
		||||
    pa_assert(dbus_message_get_type(signal_msg) == DBUS_MESSAGE_TYPE_SIGNAL);
 | 
			
		||||
    pa_assert(dbus_message_get_path(signal_msg));
 | 
			
		||||
    pa_assert(dbus_message_get_interface(signal_msg));
 | 
			
		||||
    pa_assert(dbus_message_get_member(signal_msg));
 | 
			
		||||
 | 
			
		||||
    signal_string = pa_sprintf_malloc("%s.%s", dbus_message_get_interface(signal_name), dbus_message_get_member(signal_name));
 | 
			
		||||
    signal_string = pa_sprintf_malloc("%s.%s", dbus_message_get_interface(signal_msg), dbus_message_get_member(signal_msg));
 | 
			
		||||
 | 
			
		||||
    PA_HASHMAP_FOREACH(conn_entry, p->connections, state) {
 | 
			
		||||
        if ((conn_entry->listening_for_all_signals /* Case 1: listening for all signals */
 | 
			
		||||
             && (pa_idxset_get_by_data(conn_entry->all_signals_objects, dbus_message_get_path(signal_name), NULL)
 | 
			
		||||
             && (pa_idxset_get_by_data(conn_entry->all_signals_objects, dbus_message_get_path(signal_msg), NULL)
 | 
			
		||||
                 || pa_idxset_isempty(conn_entry->all_signals_objects)))
 | 
			
		||||
 | 
			
		||||
            || (!conn_entry->listening_for_all_signals /* Case 2: not listening for all signals */
 | 
			
		||||
                && (object_set = pa_hashmap_get(conn_entry->listening_signals, signal_string))
 | 
			
		||||
                && (pa_idxset_get_by_data(object_set, dbus_message_get_path(signal_name), NULL)
 | 
			
		||||
                    || pa_idxset_isempty(object_set)))) {
 | 
			
		||||
                && (signal_paths_entry = pa_hashmap_get(conn_entry->listening_signals, signal_string))
 | 
			
		||||
                && (pa_idxset_get_by_data(signal_paths_entry->paths, dbus_message_get_path(signal_msg), NULL)
 | 
			
		||||
                    || pa_idxset_isempty(signal_paths_entry->paths)))) {
 | 
			
		||||
 | 
			
		||||
            pa_assert_se(signal_copy = dbus_message_copy(signal_name));
 | 
			
		||||
            pa_assert_se(signal_copy = dbus_message_copy(signal_msg));
 | 
			
		||||
            pa_assert_se(dbus_connection_send(conn_entry->connection, signal_copy, NULL));
 | 
			
		||||
            dbus_message_unref(signal_copy);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue