예제 #1
0
파일: session.c 프로젝트: plundstr/ngfd
static gboolean
poll_session_bus_address_file (gpointer userdata)
{
    (void) userdata;

    gchar *address = NULL;

    if (g_file_test (SESSION_BUS_ADDRESS_FILENAME, G_FILE_TEST_EXISTS)) {
        N_DEBUG (LOG_CAT "session bus address file exists.");

        if ((address = load_session_bus_address (SESSION_BUS_ADDRESS_FILENAME)) != NULL) {
            stop_file_polling  ();
            session_new_bus    (address);
            g_free             (address);
            setup_file_watcher ();
            return FALSE;
        }
    }

    return TRUE;
}
예제 #2
0
파일: context.c 프로젝트: matthewvogt/ngfd
int
n_context_subscribe_value_change (NContext *context, const char *key,
                                  NContextValueChangeFunc callback,
                                  void *userdata)
{
    NContextSubscriber *subscriber = NULL;

    if (!context || !callback)
        return FALSE;

    subscriber = g_slice_new0 (NContextSubscriber);
    subscriber->key      = g_strdup (key);
    subscriber->callback = callback;
    subscriber->userdata = userdata;

    context->subscribers = g_list_append (context->subscribers, subscriber);

    N_DEBUG (LOG_CAT "subscriber added for key '%s'", key ? key : "<all keys>");

    return TRUE;
}
예제 #3
0
파일: core.c 프로젝트: plundstr/ngfd
static NPlugin*
n_core_load_plugin (NCore *core, const char *plugin_name)
{
    g_assert (core != NULL);
    g_assert (plugin_name != NULL);

    NPlugin *plugin    = NULL;
    gchar   *filename  = NULL;
    gchar   *full_path = NULL;

    filename  = g_strdup_printf ("libngfd_%s.so", plugin_name);
    full_path = g_build_filename (core->plugin_path, filename, NULL);

    if (!(plugin = n_plugin_load (full_path)))
        goto done;

    plugin->core   = core;
    plugin->params = n_core_load_params (core, plugin_name);

    if (!plugin->load (plugin))
        goto done;

    N_DEBUG (LOG_CAT "loaded plugin '%s'", plugin_name);

    g_free (full_path);
    g_free (filename);

    return plugin;

done:
    N_ERROR (LOG_CAT "unable to load plugin '%s'", plugin_name);

    if (plugin)
        n_plugin_unload (plugin);

    g_free (full_path);
    g_free (filename);

    return NULL;
}
예제 #4
0
파일: plugin.c 프로젝트: jusa/ngfd
static int
canberra_sink_prepare (NSinkInterface *iface, NRequest *request)
{
    N_DEBUG (LOG_CAT "sink prepare");

    CanberraData *data = g_slice_new0 (CanberraData);
    NProplist *props = props = (NProplist*) n_request_get_properties (request);

    data->request    = request;
    data->iface      = iface;
    data->filename = n_proplist_get_string (props, SOUND_FILENAME_KEY);
    data->sound_enabled = TRUE;
    data->complete_cb_id = 0;

    n_request_store_data (request, CANBERRA_KEY, data);
    n_sink_interface_synchronize (iface, request);

    if (n_proplist_has_key (props, SOUND_VOLUME_KEY))
        data->sound_enabled = n_proplist_get_int (props, SOUND_VOLUME_KEY) > 0;

    return TRUE;
}
예제 #5
0
static void
process_queued_ops ()
{
    QueueItem *queued_volume = NULL;

    while ((queued_volume = g_queue_pop_head (volume_queue)) != NULL) {
        N_DEBUG (LOG_CAT "processing queued volume for role '%s', volume %d ",
            queued_volume->role, queued_volume->volume);
        add_entry (queued_volume->role, queued_volume->volume);

        g_free (queued_volume->role);
        g_slice_free (QueueItem, queued_volume);
    }

    // listen for objects here
    if (queue_subscribe) {
        listen_for_signal (NEW_ENTRY_SIGNAL, NULL);
        listen_for_signal (ENTRY_REMOVED_SIGNAL, NULL);
        update_object_map_listen ();
        queue_subscribe = FALSE;
    }
}
예제 #6
0
파일: core.c 프로젝트: plundstr/ngfd
void
n_core_register_input (NCore *core, const NInputInterfaceDecl *iface)
{
    NInputInterface *input = NULL;

    g_assert (core != NULL);
    g_assert (iface->name != NULL);

    input = g_new0 (NInputInterface, 1);
    input->name  = iface->name;
    input->core  = core;
    input->funcs = *iface;

    core->num_inputs++;
    core->inputs = (NInputInterface**) g_realloc (core->inputs,
        sizeof (NInputInterface*) * (core->num_inputs + 1));

    core->inputs[core->num_inputs-1] = input;
    core->inputs[core->num_inputs]   = NULL;

    N_DEBUG (LOG_CAT "input interface '%s' registered", input->name);
}
예제 #7
0
파일: core.c 프로젝트: plundstr/ngfd
void
n_core_register_sink (NCore *core, const NSinkInterfaceDecl *iface)
{
    g_assert (core != NULL);
    g_assert (iface->name != NULL);
    g_assert (iface->play != NULL);
    g_assert (iface->stop != NULL);

    NSinkInterface *sink = NULL;
    sink = g_new0 (NSinkInterface, 1);
    sink->name  = iface->name;
    sink->core  = core;
    sink->funcs = *iface;

    core->num_sinks++;
    core->sinks = (NSinkInterface**) g_realloc (core->sinks,
        sizeof (NSinkInterface*) * (core->num_sinks + 1));

    core->sinks[core->num_sinks-1] = sink;
    core->sinks[core->num_sinks]   = NULL;

    N_DEBUG (LOG_CAT "sink interface '%s' registered", sink->name);
}
예제 #8
0
파일: plugin.c 프로젝트: kjokinie/ngfd
/*
 * 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;
}
예제 #9
0
파일: plugin.c 프로젝트: jusa/ngfd
static void
canberra_sink_shutdown (NSinkInterface *iface)
{
    (void) iface;
    N_DEBUG (LOG_CAT "sink shutdown");
}
예제 #10
0
파일: plugin.c 프로젝트: jusa/ngfd
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;
}
예제 #11
0
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;
}