Blame src/canberra-gtk-play.c

Packit 3ae693
/*-*- Mode: C; c-basic-offset: 8 -*-*/
Packit 3ae693
Packit 3ae693
/***
Packit 3ae693
  This file is part of libcanberra.
Packit 3ae693
Packit 3ae693
  Copyright 2008 Lennart Poettering
Packit 3ae693
Packit 3ae693
  libcanberra is free software; you can redistribute it and/or modify
Packit 3ae693
  it under the terms of the GNU Lesser General Public License as
Packit 3ae693
  published by the Free Software Foundation, either version 2.1 of the
Packit 3ae693
  License, or (at your option) any later version.
Packit 3ae693
Packit 3ae693
  libcanberra is distributed in the hope that it will be useful, but
Packit 3ae693
  WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 3ae693
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Packit 3ae693
  Lesser General Public License for more details.
Packit 3ae693
Packit 3ae693
  You should have received a copy of the GNU Lesser General Public
Packit 3ae693
  License along with libcanberra. If not, see
Packit 3ae693
  <http://www.gnu.org/licenses/>.
Packit 3ae693
***/
Packit 3ae693
Packit 3ae693
#ifdef HAVE_CONFIG_H
Packit 3ae693
#include <config.h>
Packit 3ae693
#endif
Packit 3ae693
Packit 3ae693
#include <string.h>
Packit 3ae693
#include <locale.h>
Packit 3ae693
Packit 3ae693
#include <gtk/gtk.h>
Packit 3ae693
#include <canberra-gtk.h>
Packit 3ae693
Packit 3ae693
static int ret = 0;
Packit 3ae693
static ca_proplist *proplist = NULL;
Packit 3ae693
static int n_loops = 1;
Packit 3ae693
Packit 3ae693
static void callback(ca_context *c, uint32_t id, int error, void *userdata);
Packit 3ae693
Packit 3ae693
static gboolean idle_quit(gpointer userdata) {
Packit 3ae693
        gtk_main_quit();
Packit 3ae693
        return FALSE;
Packit 3ae693
}
Packit 3ae693
Packit 3ae693
static gboolean idle_play(gpointer userdata) {
Packit 3ae693
        int r;
Packit 3ae693
Packit 3ae693
        g_assert(n_loops > 1);
Packit 3ae693
Packit 3ae693
        n_loops--;
Packit 3ae693
Packit 3ae693
        r = ca_context_play_full(ca_gtk_context_get(), 1, proplist, callback, NULL);
Packit 3ae693
Packit 3ae693
        if (r < 0) {
Packit 3ae693
                g_printerr("Failed to play sound: %s\n", ca_strerror(r));
Packit 3ae693
                ret = 1;
Packit 3ae693
                gtk_main_quit();
Packit 3ae693
        }
Packit 3ae693
Packit 3ae693
        return FALSE;
Packit 3ae693
}
Packit 3ae693
Packit 3ae693
static void callback(ca_context *c, uint32_t id, int error, void *userdata) {
Packit 3ae693
Packit 3ae693
        if (error < 0) {
Packit 3ae693
                g_printerr("Failed to play sound (callback): %s\n", ca_strerror(error));
Packit 3ae693
                ret = 1;
Packit 3ae693
Packit 3ae693
        } else if (n_loops > 1) {
Packit 3ae693
                /* So, why don't we call ca_context_play_full() here directly?
Packit 3ae693
                   -- Because the context this callback is called from is
Packit 3ae693
                   explicitly documented as undefined and no libcanberra function
Packit 3ae693
                   may be called from it. */
Packit 3ae693
Packit 3ae693
                g_idle_add(idle_play, NULL);
Packit 3ae693
                return;
Packit 3ae693
        }
Packit 3ae693
Packit 3ae693
        /* So, why don't we call gtk_main_quit() here directly? -- Because
Packit 3ae693
         * otherwise we might end up with a small race condition: this
Packit 3ae693
         * callback might get called before the main loop actually started
Packit 3ae693
         * running */
Packit 3ae693
        g_idle_add(idle_quit, NULL);
Packit 3ae693
}
Packit 3ae693
Packit 3ae693
static GQuark error_domain(void) {
Packit 3ae693
        return g_quark_from_static_string("canberra-error-quark");
Packit 3ae693
}
Packit 3ae693
Packit 3ae693
static gboolean property_callback(
Packit 3ae693
                const gchar *option_name,
Packit 3ae693
                const gchar *value,
Packit 3ae693
                gpointer data,
Packit 3ae693
                GError **error) {
Packit 3ae693
Packit 3ae693
        const char *equal;
Packit 3ae693
        char *t;
Packit 3ae693
Packit 3ae693
        if (!(equal = strchr(value, '='))) {
Packit 3ae693
                g_set_error(error, error_domain(), 0, "Property lacks '='.");
Packit 3ae693
                return FALSE;
Packit 3ae693
        }
Packit 3ae693
Packit 3ae693
        t = g_strndup(value, equal - value);
Packit 3ae693
Packit 3ae693
        if (ca_proplist_sets(proplist, t, equal + 1) < 0) {
Packit 3ae693
                g_set_error(error, error_domain(), 0, "Invalid property.");
Packit 3ae693
                g_free(t);
Packit 3ae693
                return FALSE;
Packit 3ae693
        }
Packit 3ae693
Packit 3ae693
        g_free(t);
Packit 3ae693
        return TRUE;
Packit 3ae693
}
Packit 3ae693
Packit 3ae693
int main (int argc, char *argv[]) {
Packit 3ae693
        GOptionContext *oc;
Packit 3ae693
        static gchar *event_id = NULL, *filename = NULL, *event_description = NULL, *cache_control = NULL, *volume = NULL;
Packit 3ae693
        int r;
Packit 3ae693
        static gboolean version = FALSE;
Packit 3ae693
        GError *error = NULL;
Packit 3ae693
Packit 3ae693
        static const GOptionEntry options[] = {
Packit 3ae693
                { "version",       'v', 0, G_OPTION_ARG_NONE,     &version,                  "Display version number and quit", NULL },
Packit 3ae693
                { "id",            'i', 0, G_OPTION_ARG_STRING,   &event_id,                 "Event sound identifier",  "STRING" },
Packit 3ae693
                { "file",          'f', 0, G_OPTION_ARG_STRING,   &filename,                 "Play file",  "PATH" },
Packit 3ae693
                { "description",   'd', 0, G_OPTION_ARG_STRING,   &event_description,        "Event sound description", "STRING" },
Packit 3ae693
                { "cache-control", 'c', 0, G_OPTION_ARG_STRING,   &cache_control,            "Cache control (permanent, volatile, never)", "STRING" },
Packit 3ae693
                { "loop",          'l', 0, G_OPTION_ARG_INT,      &n_loops,                  "Loop how many times (detault: 1)", "INTEGER" },
Packit 3ae693
                { "volume",        'V', 0, G_OPTION_ARG_STRING,   &volume,                   "A floating point dB value for the sample volume (ex: 0.0)", "STRING" },
Packit 3ae693
                { "property",      0,   0, G_OPTION_ARG_CALLBACK, (void*) property_callback, "An arbitrary property", "STRING" },
Packit 3ae693
                { NULL, 0, 0, 0, NULL, NULL, NULL }
Packit 3ae693
        };
Packit 3ae693
Packit 3ae693
        setlocale(LC_ALL, "");
Packit 3ae693
Packit 3ae693
        g_type_init();
Packit 3ae693
Packit 3ae693
        ca_proplist_create(&proplist);
Packit 3ae693
Packit 3ae693
        oc = g_option_context_new("- canberra-gtk-play");
Packit 3ae693
        g_option_context_add_main_entries(oc, options, NULL);
Packit 3ae693
        g_option_context_add_group(oc, gtk_get_option_group(TRUE));
Packit 3ae693
        g_option_context_set_help_enabled(oc, TRUE);
Packit 3ae693
Packit 3ae693
        if (!(g_option_context_parse(oc, &argc, &argv, &error))) {
Packit 3ae693
                g_print("Option parsing failed: %s\n", error->message);
Packit 3ae693
                return 1;
Packit 3ae693
        }
Packit 3ae693
        g_option_context_free(oc);
Packit 3ae693
Packit 3ae693
        if (version) {
Packit 3ae693
                g_print("canberra-gtk-play from %s\n", PACKAGE_STRING);
Packit 3ae693
                return 0;
Packit 3ae693
        }
Packit 3ae693
Packit 3ae693
        if (!event_id && !filename) {
Packit 3ae693
                g_printerr("No event id or file specified.\n");
Packit 3ae693
                return 1;
Packit 3ae693
        }
Packit 3ae693
Packit 3ae693
        ca_context_change_props(ca_gtk_context_get(),
Packit 3ae693
                                CA_PROP_APPLICATION_NAME, "canberra-gtk-play",
Packit 3ae693
                                CA_PROP_APPLICATION_VERSION, PACKAGE_VERSION,
Packit 3ae693
                                CA_PROP_APPLICATION_ID, "org.freedesktop.libcanberra.gtk-play",
Packit 3ae693
                                NULL);
Packit 3ae693
Packit 3ae693
        if (event_id)
Packit 3ae693
                ca_proplist_sets(proplist, CA_PROP_EVENT_ID, event_id);
Packit 3ae693
Packit 3ae693
        if (filename)
Packit 3ae693
                ca_proplist_sets(proplist, CA_PROP_MEDIA_FILENAME, filename);
Packit 3ae693
Packit 3ae693
        if (cache_control)
Packit 3ae693
                ca_proplist_sets(proplist, CA_PROP_CANBERRA_CACHE_CONTROL, cache_control);
Packit 3ae693
Packit 3ae693
        if (event_description)
Packit 3ae693
                ca_proplist_sets(proplist, CA_PROP_EVENT_DESCRIPTION, event_description);
Packit 3ae693
Packit 3ae693
        if (volume)
Packit 3ae693
                ca_proplist_sets(proplist, CA_PROP_CANBERRA_VOLUME, volume);
Packit 3ae693
Packit 3ae693
        r = ca_context_play_full(ca_gtk_context_get(), 1, proplist, callback, NULL);
Packit 3ae693
Packit 3ae693
        if (r < 0) {
Packit 3ae693
                g_printerr("Failed to play sound: %s\n", ca_strerror(r));
Packit 3ae693
                ret = 1;
Packit 3ae693
                goto finish;
Packit 3ae693
        }
Packit 3ae693
Packit 3ae693
        gtk_main();
Packit 3ae693
Packit 3ae693
finish:
Packit 3ae693
Packit 3ae693
        ca_proplist_destroy(proplist);
Packit 3ae693
Packit 3ae693
        return ret;
Packit 3ae693
}