static gboolean session_new_bus (const char *address) { DBusError error; dbus_error_init (&error); if (session_bus != NULL) { N_DEBUG (LOG_CAT "received session bus address '%s'", address); dbus_connection_unref (session_bus); session_bus = NULL; } else N_DEBUG (LOG_CAT "received new session bus address '%s'", address); if ((session_bus = dbus_connection_open (address, &error)) == NULL || !dbus_bus_register (session_bus, &error)) { if (dbus_error_is_set(&error)) { N_WARNING (LOG_CAT "failed to connect to session bus %s (%s)", address, error.message); dbus_error_free (&error); } else N_WARNING (LOG_CAT "failed to connect to session bus %s", address); return FALSE; } session_reconnect (); return TRUE; }
static void setup_system_sound_levels (NValue *value) { gchar **split = NULL; gchar **iter = NULL; guint i = 0; if (!value) { N_WARNING (LOG_CAT "no system-sound-levels key defined " "in profile.ini!"); return; } if (n_value_type (value) != N_VALUE_TYPE_STRING) { N_WARNING (LOG_CAT "invalid value type for system sound levels!"); return; } split = g_strsplit (n_value_get_string (value), ";", -1); for (iter = split; *iter; ++iter) ++num_system_sound_levels; system_sound_levels = (int*) g_malloc0 (sizeof (int) * num_system_sound_levels); for (iter = split, i = 0; *iter; ++iter, ++i) { system_sound_levels[i] = atoi (*iter); system_sound_levels[i] = CLAMP_VALUE (system_sound_levels[i], 0, 100); } g_strfreev (split); }
static int mce_sink_initialize (NSinkInterface *iface) { (void) iface; DBusError error; dbus_error_init (&error); bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error); if (bus == NULL) { N_WARNING ("%s >> failed to get system bus: %s", __FUNCTION__, error.message); dbus_error_free (&error); return FALSE; } char *rule = "type='signal',interface='" MCE_SIGNAL_IF "'"; dbus_bus_add_match(bus, rule, &error); if (dbus_error_is_set(&error)) { N_WARNING ("%s >> failed to add D-BUS match rule, cause: %s", __FUNCTION__, error.message); dbus_error_free (&error); return FALSE; } dbus_connection_add_filter(bus, mce_signal_filter, NULL, NULL); return TRUE; }
static gboolean connect_peer_to_peer() { DBusError error; dbus_error_init (&error); volume_bus = dbus_connection_open (volume_pulse_address, &error); if (dbus_error_is_set (&error)) { N_WARNING (LOG_CAT "failed to open connection to pulseaudio: %s", error.message); dbus_error_free (&error); return FALSE; } dbus_connection_setup_with_g_main (volume_bus, NULL); if (!dbus_connection_add_filter (volume_bus, filter_cb, NULL, NULL)) { N_WARNING (LOG_CAT "failed to add filter"); return FALSE; } process_queued_ops(); return TRUE; }
static NProplist* n_core_load_params (NCore *core, const char *plugin_name) { g_assert (core != NULL); g_assert (plugin_name != NULL); NProplist *proplist = NULL; GKeyFile *keyfile = NULL; gchar *filename = NULL; gchar *full_path = NULL; gchar **keys = NULL; gchar **iter = NULL; GError *error = NULL; gchar *value = NULL; filename = g_strdup_printf ("%s.ini", plugin_name); full_path = g_build_filename (core->conf_path, PLUGIN_CONF_PATH, filename, NULL); keyfile = g_key_file_new (); if (!g_key_file_load_from_file (keyfile, full_path, G_KEY_FILE_NONE, &error)) { if (error->code & G_KEY_FILE_ERROR_NOT_FOUND) { N_WARNING (LOG_CAT "problem with configuration file '%s': %s", filename, error->message); } goto done; } keys = g_key_file_get_keys (keyfile, plugin_name, NULL, NULL); if (!keys) { N_WARNING (LOG_CAT "no group '%s' within configuration file '%s'", plugin_name, filename); goto done; } proplist = n_proplist_new (); for (iter = keys; *iter; ++iter) { if ((value = g_key_file_get_string (keyfile, plugin_name, *iter, NULL)) == NULL) continue; N_DEBUG (LOG_CAT "+ plugin parameter: %s = %s", *iter, value); n_proplist_set_string (proplist, *iter, value); g_free (value); } g_strfreev (keys); done: if (error) g_error_free (error); if (keyfile) g_key_file_free (keyfile); g_free (full_path); g_free (filename); return proplist; }
/* Read and create proplist from a custom file */ static NProplist* ffm_read_props(const char *file_name) { NProplist *proplist = NULL; GKeyFile *keyfile = NULL; gchar **keys = NULL; gchar **iter = NULL; GError *error = NULL; gchar *value = NULL; if (!file_name) { N_DEBUG (LOG_CAT "NULL file_name parameter, cannot read props"); return NULL; } keyfile = g_key_file_new (); N_DEBUG (LOG_CAT "Loading properties from file \"%s\"", file_name); if (!g_key_file_load_from_file (keyfile, file_name, G_KEY_FILE_NONE, &error)) { N_WARNING (LOG_CAT "problem with configuration file" " '%s': %s", file_name, error->message); goto done; } keys = g_key_file_get_keys (keyfile, FFM_PLUGIN_NAME, NULL, NULL); if (!keys) { N_WARNING (LOG_CAT "no group '%s' within configuration file " "'%s'", FFM_PLUGIN_NAME, file_name); goto done; } proplist = n_proplist_new (); for (iter = keys; *iter; ++iter) { if ((value = g_key_file_get_string (keyfile, FFM_PLUGIN_NAME, *iter, NULL)) == NULL) continue; N_DEBUG (LOG_CAT "+ plugin parameter: %s = %s", *iter, value); n_proplist_set_string (proplist, *iter, value); g_free (value); } g_strfreev (keys); done: if (error) g_error_free (error); if (keyfile) g_key_file_free (keyfile); return proplist; }
static gchar* load_session_bus_address (const char *filename) { FILE *fp = NULL; size_t file_size = 0; size_t bytes_read = 0; char *buf = NULL; gchar *address = NULL; if (!filename) return NULL; if ((fp = fopen (filename, "r")) == NULL) { N_DEBUG (LOG_CAT "no address file %s", filename); return NULL; } fseek (fp, 0L, SEEK_END); file_size = ftell (fp); fseek (fp, 0L, SEEK_SET); if (file_size > 0) { if ((buf = (char*) g_try_malloc0 (sizeof (char) * file_size)) == NULL) { N_WARNING (LOG_CAT "failed to allocate memory to read session bus " "address file."); fclose (fp); return NULL; } bytes_read = fread (buf, sizeof (char), file_size, fp); if (bytes_read != file_size) { N_WARNING (LOG_CAT "failed to read the session bus address file."); g_free (buf); fclose (fp); return NULL; } if ((address = parse_address (buf)) != NULL) { N_DEBUG (LOG_CAT "parsed DBus session bus address: %s", address); } else { N_WARNING (LOG_CAT "failed to parse DBus session bus address."); } g_free (buf); } fclose (fp); return address; }
static DBusHandlerResult mce_signal_filter (DBusConnection *connection, DBusMessage *msg, void *user_data) { (void) connection; (void) user_data; if (dbus_message_is_signal(msg, MCE_SIGNAL_IF, MCE_LED_PATTERN_DEACTIVATED_SIG)) { DBusError error; dbus_error_init(&error); gchar *pattern = NULL; if (!dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &pattern, DBUS_TYPE_INVALID)) { N_WARNING ("%s >> failed to read MCE signal arguments, cause: %s", __FUNCTION__, error.message); dbus_error_free(&error); } else { GList *event; N_DEBUG ("%s >> mce finished playing %s", __FUNCTION__, pattern); for (event = active_events; event != NULL; event = g_list_next(event)) { MceData *data = (MceData *) event->data; if (g_strcmp0(pattern, data->pattern) == 0) { n_sink_interface_complete(data->iface, data->request); N_DEBUG ("%s >> led pattern %s complete", __FUNCTION__, data->pattern); active_events = g_list_remove_all(active_events, data); break; } } } } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
static void n_core_parse_events_from_file (NCore *core, const char *filename) { g_assert (core != NULL); g_assert (filename != NULL); GKeyFile *keyfile = NULL; GError *error = NULL; gchar **group_list = NULL; gchar **group = NULL; NEvent *event = NULL; keyfile = g_key_file_new (); if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &error)) { N_WARNING (LOG_CAT "failed to load event file: %s", error->message); g_error_free (error); g_key_file_free (keyfile); return; } /* each unique group is considered as an event, even if split within separate files. */ N_DEBUG (LOG_CAT "processing event file '%s'", filename); group_list = g_key_file_get_groups (keyfile, NULL); for (group = group_list; *group; ++group) { event = n_event_new_from_group (core, keyfile, *group); if (event) n_core_add_event (core, event); } g_strfreev (group_list); g_key_file_free (keyfile); }
static void n_core_parse_keytypes (NCore *core, GKeyFile *keyfile) { g_assert (core != NULL); g_assert (keyfile != NULL); gchar **conf_keys = NULL; gchar **key = NULL; gchar *value = NULL; int key_type = 0; /* load all the event configuration key entries. */ conf_keys = g_key_file_get_keys (keyfile, "keytypes", NULL, NULL); if (!conf_keys) return; for (key = conf_keys; *key; ++key) { value = g_key_file_get_string (keyfile, "keytypes", *key, NULL); if (!value) { N_WARNING (LOG_CAT "no datatype defined for key '%s'", *key); continue; } if (strncmp (value, "INTEGER", 7) == 0) key_type = N_VALUE_TYPE_INT; else if (strncmp (value, "STRING", 6) == 0) key_type = N_VALUE_TYPE_STRING; else if (strncmp (value, "BOOLEAN", 7) == 0) key_type = N_VALUE_TYPE_BOOL; if (!key_type) { N_WARNING (LOG_CAT "unrecognized datatype '%s' for key '%s'", value, *key); g_free (value); continue; } N_DEBUG (LOG_CAT "new key type '%s' = %s", *key, value); g_hash_table_replace (core->key_types, g_strdup (*key), (gpointer) key_type); g_free (value); } g_strfreev (conf_keys); }
static gboolean add_entry (const char *role, guint volume) { DBusMessage *msg = NULL; DBusMessage *reply = NULL; const char *empty = ""; gboolean success = FALSE; dbus_bool_t muted = FALSE; dbus_bool_t apply = TRUE; dbus_uint32_t vol = 0; DBusMessageIter iter; DBusError error; if (!volume_bus || !role) return FALSE; /* convert the volume from 0-100 to PA_VOLUME_NORM range */ vol = TO_PA_VOL(volume); dbus_error_init (&error); msg = dbus_message_new_method_call (0, STREAM_RESTORE_PATH, STREAM_RESTORE_IF, ADD_ENTRY_METHOD); if (msg == NULL) goto done; dbus_message_iter_init_append (msg, &iter); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &role); dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &empty); append_volume (&iter, vol); dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &muted); dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &apply); reply = dbus_connection_send_with_reply_and_block (volume_bus, msg, -1, &error); if (!reply) { if (dbus_error_is_set (&error)) { N_WARNING (LOG_CAT "failed to update volume role '%s': %s", role, error.message); } goto done; } N_DEBUG (LOG_CAT "volume for role '%s' set to %d", role, vol); success = TRUE; done: dbus_error_free (&error); if (reply) dbus_message_unref (reply); if (msg) dbus_message_unref (msg); return success; }
static void get_address_reply_cb(DBusPendingCall *pending, void *data) { DBusMessageIter iter; DBusMessageIter sub; int current_type; char *address = NULL; DBusMessage *msg = NULL; (void) data; msg = dbus_pending_call_steal_reply(pending); if (!msg) { N_WARNING(LOG_CAT "Could not get reply from pending call."); goto retry; } dbus_message_iter_init(msg, &iter); // Reply string is inside DBUS_TYPE_VARIANT while ((current_type = dbus_message_iter_get_arg_type(&iter)) != DBUS_TYPE_INVALID) { if (current_type == DBUS_TYPE_VARIANT) { dbus_message_iter_recurse(&iter, &sub); while ((current_type = dbus_message_iter_get_arg_type(&sub)) != DBUS_TYPE_INVALID) { if (current_type == DBUS_TYPE_STRING) dbus_message_iter_get_basic(&sub, &address); dbus_message_iter_next(&sub); } } dbus_message_iter_next(&iter); } if (address) { N_DEBUG (LOG_CAT "Got PulseAudio DBus address: %s", address); volume_pulse_address = g_strdup(address); // Unref sesssion bus connection, it is not needed anymore. // Real communication is done with peer-to-peer connection. dbus_connection_unref(volume_session_bus); volume_session_bus = NULL; } // Always retry connection, if address was determined, it is used // to get peer-to-peer connection, if address wasn't determined, // we'll need to reconnect and retry anyway. retry: if (msg) dbus_message_unref(msg); if (pending) dbus_pending_call_unref(pending); retry_connect(); }
static gboolean call_dbus_method (DBusConnection *bus, DBusMessage *msg) { if (!dbus_connection_send (bus, msg, 0)) { N_WARNING ("Failed to send DBus message %s to interface %s", dbus_message_get_member (msg), dbus_message_get_interface (msg)); return FALSE; } return TRUE; }
static gchar* get_object_path (const char *stream_name) { DBusMessage *msg = NULL; DBusMessage *reply = NULL; const gchar *obj_path= NULL; gchar *ret = NULL; DBusError error; g_assert (volume_bus); g_assert (stream_name); dbus_error_init (&error); msg = dbus_message_new_method_call (NULL, STREAM_RESTORE_PATH, STREAM_RESTORE_IF, "GetEntryByName"); if (msg == NULL) goto done; dbus_message_append_args (msg, DBUS_TYPE_STRING, &stream_name, DBUS_TYPE_INVALID); reply = dbus_connection_send_with_reply_and_block (volume_bus, msg, -1, &error); if (!reply) { if (dbus_error_is_set (&error)) { N_DEBUG (LOG_CAT "couldn't get object path for %s: %s", stream_name, error.message); } goto done; } if (!dbus_message_get_args (reply, NULL, DBUS_TYPE_OBJECT_PATH, &obj_path, DBUS_TYPE_INVALID)) { N_WARNING (LOG_CAT "failed to get object path"); goto done; } ret = g_strdup (obj_path); done: dbus_error_free (&error); if (reply) dbus_message_unref (reply); if (msg) dbus_message_unref (msg); return ret; }
static int n_core_parse_configuration (NCore *core) { g_assert (core != NULL); g_assert (core->conf_path != NULL); GKeyFile *keyfile = NULL; GError *error = NULL; gchar *filename = NULL; gchar **plugins = NULL; filename = g_build_filename (core->conf_path, DEFAULT_CONF_FILENAME, NULL); keyfile = g_key_file_new (); if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &error)) { N_WARNING (LOG_CAT "failed to load configuration file file: %s", error->message); g_error_free (error); g_key_file_free (keyfile); g_free (filename); return FALSE; } N_DEBUG (LOG_CAT "parsing configuration file '%s'", filename); /* parse the required plugins. */ if ((plugins = g_key_file_get_string_list (keyfile, "general", "plugins", NULL, NULL)) != NULL) { parse_plugins (plugins, &core->required_plugins); g_strfreev (plugins); } /* parse the optional plugins. */ if ((plugins = g_key_file_get_string_list (keyfile, "general", "plugins-optional", NULL, NULL)) != NULL) { parse_plugins (plugins, &core->optional_plugins); g_strfreev (plugins); } /* load all the event configuration key entries. */ n_core_parse_keytypes (core, keyfile); /* load the sink order. the first sink has the highest priority. */ n_core_parse_sink_order (core, keyfile); g_key_file_free (keyfile); g_free (filename); return TRUE; }
/* * Create a Hash table of effects from a string of semicolon separated keys. * Values of keys will be initialized to -1. */ static GHashTable *ffm_new_effect_list(const char *effect_data) { GHashTable *list = NULL; gchar **effect_names; int i = 0; struct ffm_effect_data *data; if (!effect_data) { N_WARNING (LOG_CAT "NULL effect_data pointer"); return NULL; } N_DEBUG (LOG_CAT "creating effect list for %s", effect_data); effect_names = g_strsplit((const gchar*) effect_data, ";", 0); if (!effect_names[0]) { N_WARNING (LOG_CAT "Empty effect_data string"); goto ffm_effect_list_done; } list = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); for (i = 0; effect_names[i] != NULL; i++) { /* Add effect key to effect list with initial data */ data = g_new(struct ffm_effect_data, 1); data->id = -1; data->repeat = 1; g_hash_table_insert(list, strdup(effect_names[i]), data); } ffm_effect_list_done: g_strfreev(effect_names); return list; }
int NativeProxyObject::fireEvent(const char* name, const TiObject* event) const { EventPairSmartPtr ep = events_.value(name); if (ep.get() != NULL && ep->container()) { if (event != NULL) { ep->container()->fireEvent(event); } else { ep->container()->fireEvent(); } return NATIVE_ERROR_OK; } N_WARNING(Native::Msg::Unsupported_event_name_ << name); return NATIVE_ERROR_NOTSUPPORTED; }
static int canberra_connect () { int error; if (c_context) return TRUE; ca_context_create (&c_context); error = ca_context_open (c_context); if (error) { N_WARNING (LOG_CAT "can't connect to canberra! %s", ca_strerror (error)); ca_context_destroy (c_context); c_context = 0; return FALSE; } return TRUE; }
static int tonegen_sink_initialize (NSinkInterface *iface) { (void) iface; DBusError error; dbus_error_init (&error); system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error); if (!system_bus) { N_WARNING (LOG_CAT "failed to get system bus: %s", error.message); dbus_error_free (&error); return FALSE; } dbus_connection_setup_with_g_main (system_bus, NULL); return TRUE; }
static ProfileEntry* parse_profile_entry (const char *value) { g_assert (value != NULL); ProfileEntry *entry = NULL; gchar **tokens = NULL; gchar **source_tokens = NULL; /* split the profile key and target key */ tokens = g_strsplit (value, "=>", 2); if (tokens[1] == NULL) { N_WARNING (LOG_CAT "profile store key missing for '%s'", value); g_strfreev (tokens); return NULL; } g_strstrip (tokens[0]); g_strstrip (tokens[1]); /* figure out the source profile for the key */ source_tokens = g_strsplit (tokens[0], "@", 2); g_strstrip (source_tokens[0]); if (source_tokens[1]) g_strstrip (source_tokens[1]); /* new entry */ entry = g_new0 (ProfileEntry, 1); entry->key = g_strdup (source_tokens[0]); entry->profile = g_strdup (source_tokens[1]); entry->target = g_strdup (tokens[1]); g_strfreev (source_tokens); g_strfreev (tokens); return entry; }
static void n_core_parse_sink_order (NCore *core, GKeyFile *keyfile) { g_assert (core != NULL); g_assert (keyfile != NULL); gchar **sink_list = NULL; gchar **item = NULL; gsize num_items = 0; sink_list = g_key_file_get_string_list (keyfile, "general", "sink-order", &num_items, NULL); if (!sink_list) { N_WARNING (LOG_CAT "no sink-order, re-synchronization may be undefined."); return; } for (item = sink_list; *item; ++item) core->sink_order = g_list_append (core->sink_order, g_strdup (*item)); g_strfreev (sink_list); }
static DBusHandlerResult filter_cb (DBusConnection *connection, DBusMessage *msg, void *data) { (void) connection; (void) data; const char *obj_path; char *stream_name; GList *list, *i; SubscribeItem *item; int volume = 0; if (dbus_message_has_interface (msg, DBUS_INTERFACE_LOCAL) && dbus_message_has_path (msg, DBUS_PATH_LOCAL) && dbus_message_has_member (msg, DISCONNECTED_SIG)) { N_DEBUG (LOG_CAT "pulseaudio disconnected, reconnecting in %d seconds", RETRY_TIMEOUT); disconnect_from_pulseaudio (); // After disconnecting re-query stream restore object names. if (subscribe_map && object_map) { list = g_hash_table_get_values (subscribe_map); for (i = g_list_first (list); i; i = g_list_next (i)) { SubscribeItem *item = (SubscribeItem*) i->data; if (item->object_path) { g_free (item->object_path); item->object_path = NULL; } } g_list_free (list); queue_subscribe = TRUE; } // If PulseAudio is restarting path to runtime files may change so we'll // have to request DBus address again. if (volume_pulse_address) { g_free(volume_pulse_address); volume_pulse_address = NULL; } retry_connect(); } else if (subscribe_callback && dbus_message_has_interface (msg, STREAM_RESTORE_IF) && dbus_message_has_path (msg, STREAM_RESTORE_PATH) && dbus_message_has_member (msg, NEW_ENTRY_MEMBER)) { if (!dbus_message_get_args (msg, NULL, DBUS_TYPE_OBJECT_PATH, &obj_path, DBUS_TYPE_INVALID)) { N_WARNING (LOG_CAT "failed to get arguments for new entry"); goto end; } // If the entry is in subscribe_map but not in object_map, look up the entry // and add to object_map if (!object_map_complete && !g_hash_table_lookup (object_map, obj_path)) { if ((stream_name = get_object_name (obj_path))) { if ((item = g_hash_table_lookup (subscribe_map, stream_name))) { item->object_path = g_strdup (obj_path); N_DEBUG (LOG_CAT "stream restore entry for %s appeared (%s)", item->stream_name, item->object_path); update_object_map_listen (); } g_free (stream_name); } } } else if (subscribe_callback && dbus_message_has_interface (msg, STREAM_RESTORE_IF) && dbus_message_has_path (msg, STREAM_RESTORE_PATH) && dbus_message_has_member (msg, ENTRY_REMOVED_MEMBER)) { if (!dbus_message_get_args (msg, NULL, DBUS_TYPE_OBJECT_PATH, &obj_path, DBUS_TYPE_INVALID)) { N_WARNING (LOG_CAT "failed to get arguments for removed entry"); goto end; } if ((item = g_hash_table_lookup (object_map, obj_path))) { g_hash_table_remove (object_map, item->object_path); g_free (item->object_path); item->object_path = NULL; update_object_map_listen (); N_DEBUG (LOG_CAT "removed entry %s from object map (%s)", item->stream_name, obj_path); } } else if (subscribe_callback && dbus_message_has_interface (msg, STREAM_ENTRY_IF) && dbus_message_has_member (msg, VOLUME_UPDATED_MEMBER)) { if (!(obj_path = dbus_message_get_path (msg))) goto end; if ((item = g_hash_table_lookup (object_map, obj_path))) { N_DEBUG (LOG_CAT "volume updated for stream %s (%s)", item->stream_name, item->object_path); if (get_volume (msg, &volume)) { subscribe_callback (item->stream_name, FROM_PA_VOL(volume), item->data, subscribe_userdata); } } } end: return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
static gchar* get_object_name (const char *obj_path) { DBusMessage *msg = NULL; DBusMessage *reply = NULL; const gchar *stream_name = NULL; gchar *ret = NULL; const gchar *iface = STREAM_ENTRY_IF; const gchar *addr = "Name"; DBusError error; DBusMessageIter iter; DBusMessageIter sub; int current_type; g_assert (volume_bus); g_assert (obj_path); dbus_error_init (&error); msg = dbus_message_new_method_call(STREAM_ENTRY_IF, obj_path, DBUS_PROPERTIES_IF, "Get"); if (msg == NULL) goto done; if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &iface, DBUS_TYPE_STRING, &addr, DBUS_TYPE_INVALID)) goto done; reply = dbus_connection_send_with_reply_and_block (volume_bus, msg, -1, &error); if (!reply) { if (dbus_error_is_set (&error)) { N_WARNING (LOG_CAT "couldn't get object name for %s: %s", obj_path, error.message); } goto done; } dbus_message_iter_init(reply, &iter); // Reply string is inside DBUS_TYPE_VARIANT while ((current_type = dbus_message_iter_get_arg_type(&iter)) != DBUS_TYPE_INVALID) { if (current_type == DBUS_TYPE_VARIANT) { dbus_message_iter_recurse(&iter, &sub); while ((current_type = dbus_message_iter_get_arg_type(&sub)) != DBUS_TYPE_INVALID) { if (current_type == DBUS_TYPE_STRING) dbus_message_iter_get_basic(&sub, &stream_name); dbus_message_iter_next(&sub); } } dbus_message_iter_next(&iter); } if (!stream_name) { N_WARNING (LOG_CAT "failed to get stream name"); goto done; } ret = g_strdup (stream_name); done: dbus_error_free (&error); if (reply) dbus_message_unref (reply); if (msg) dbus_message_unref (msg); return ret; }
static gboolean connect_get_address() { DBusError error; DBusMessage *msg = NULL; DBusPendingCall *pending = NULL; const char *iface = PULSE_LOOKUP_IF; const char *addr = PULSE_LOOKUP_ADDRESS; dbus_error_init (&error); if (volume_session_bus && !dbus_connection_get_is_connected(volume_session_bus)) { dbus_connection_unref(volume_session_bus); volume_session_bus = NULL; } if (!volume_session_bus) volume_session_bus = dbus_bus_get(DBUS_BUS_SESSION, &error); if (dbus_error_is_set(&error)) { N_WARNING(LOG_CAT "failed to open connection to session bus: %s", error.message); dbus_error_free (&error); goto fail; } dbus_connection_setup_with_g_main(volume_session_bus, NULL); if (!(msg = dbus_message_new_method_call(PULSE_LOOKUP_DEST, PULSE_LOOKUP_PATH, DBUS_PROPERTIES_IF, "Get"))) goto fail; if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &iface, DBUS_TYPE_STRING, &addr, DBUS_TYPE_INVALID)) goto fail; if (!dbus_connection_send_with_reply(volume_session_bus, msg, &pending, DBUS_TIMEOUT_USE_DEFAULT)) goto fail; if (!pending) goto fail; if (!dbus_pending_call_set_notify(pending, get_address_reply_cb, NULL, NULL)) goto fail; dbus_message_unref(msg); return TRUE; fail: if (pending) { dbus_pending_call_cancel(pending); dbus_pending_call_unref(pending); } if (msg) dbus_message_unref(msg); return FALSE; }
static int canberra_sink_play (NSinkInterface *iface, NRequest *request) { CanberraData *data = (CanberraData*) n_request_get_data (request, CANBERRA_KEY); (void) iface; N_DEBUG (LOG_CAT "sink play"); g_assert (data != NULL); if (!data->sound_enabled) goto complete; if (canberra_connect () == FALSE) return FALSE; static GHashTable *cached_samples = NULL; if (!cached_samples) { cached_samples = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); } NProplist *props = props = (NProplist*) n_request_get_properties (request); ca_proplist *ca_props = 0; int error; ca_proplist_create (&ca_props); /* TODO: don't hardcode */ ca_proplist_sets (ca_props, CA_PROP_CANBERRA_XDG_THEME_NAME, "jolla-ambient"); ca_proplist_sets (ca_props, CA_PROP_EVENT_ID, data->filename); /* convert all properties within the request that begin with "sound.stream." prefix. */ n_proplist_foreach (props, proplist_to_structure_cb, ca_props); if (g_hash_table_lookup_extended (cached_samples, data->filename, NULL, NULL) == FALSE) { N_DEBUG (LOG_CAT "caching sample %s", data->filename); error = ca_context_cache_full (c_context, ca_props); if (error) { N_WARNING (LOG_CAT "canberra couldn't cache sample %s", data->filename); return FALSE; } g_hash_table_add (cached_samples, strdup(data->filename)); } else { N_DEBUG (LOG_CAT "sample %s is cached", data->filename); } error = ca_context_play_full (c_context, 0, ca_props, NULL, NULL); ca_proplist_destroy (ca_props); if (error) { N_WARNING (LOG_CAT "sink play had a warning: %s", ca_strerror (error)); if (error == CA_ERROR_NOTAVAILABLE || error == CA_ERROR_DISCONNECTED || error == CA_ERROR_STATE || error == CA_ERROR_DESTROYED) { ca_context_destroy (c_context); c_context = 0; } return FALSE; } complete: /* We do not know how long our samples play, but let's guess we * are done in 200ms. */ data->complete_cb_id = g_timeout_add (200, canberra_complete_cb, data); return TRUE; }