From 41b9bf9869de2bd12460f03a4ee0d2fb77488301 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 29 May 2008 15:19:07 +0000 Subject: preliminary gtk binding git-svn-id: file:///home/lennart/svn/public/libcanberra/trunk@36 01b60673-d06a-42c0-afdd-89cb8e0f78ac --- configure.ac | 1 + src/canberra-gtk.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/canberra-gtk.h | 4 ++ src/canberra.h | 4 ++ src/common.c | 30 ++++++---- src/common.h | 3 + src/test-canberra.c | 6 +- todo | 1 + 8 files changed, 185 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index de665de..bac0244 100644 --- a/configure.ac +++ b/configure.ac @@ -272,6 +272,7 @@ AC_SUBST(HAVE_PULSE) AM_CONDITIONAL([HAVE_PULSE], [test "x$HAVE_PULSE" = x1]) PKG_CHECK_MODULES(VORBIS, [ vorbisfile ]) +PKG_CHECK_MODULES(GTK, [ gtk+-2.0 ]) ################################### # Output # diff --git a/src/canberra-gtk.c b/src/canberra-gtk.c index cb38bba..81eb2e0 100644 --- a/src/canberra-gtk.c +++ b/src/canberra-gtk.c @@ -24,20 +24,45 @@ #include #endif -static GtkWidget* get_toplevel(GtkWidget *w) { - while (w) { - if (GTK_WIDGET_TOPLEVEL(w)) - return w; +ca_context *ca_gtk_context_get(void) { + static GStaticPrivate context_private = G_STATIC_PRIVATE_INIT; + ca_context *c = NULL; + int ret; + const char *name; - w = gtk_widget_get_parent(w); - } + if ((c = g_static_private_get(&context_private))) + return c; + + ca_assert_se(ca_context_create(&c) == CA_SUCCESS); + + if ((name = g_get_application_name())) + ca_assert_se(ca_context_change_props(c, CA_PROP_APPLICATION_NAME, name, NULL) == 0); + + g_static_private_set(&context_private, c, (GDestroyNotify) ca_context_destroy); + + return c; + +fail: - return NULL; + if (c) + g_asset_se(ca_context_destroy(c) == 0); +} + +static GtkWindow* get_toplevel(GtkWidget *w) { + if (!(w = gtk_wídget_get_toplevel(w))) + return NULL; + + if (!GTK_IS_WINDOW(w)) + return NULL; + + return GTK_WINDOW(w); }; int ca_gtk_proplist_set_for_window(ca_proplist *p, GtkWidget *w) { int ret; - const char *t; + const char *t, role; + GdkWindow *dw; + GdkScreen *screen; ca_return_val_if_fail(p, CA_ERROR_INVALID); ca_return_val_if_fail(w, CA_ERROR_INVALID); @@ -49,19 +74,133 @@ int ca_gtk_proplist_set_for_window(ca_proplist *p, GtkWidget *w) { if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_NAME, t)) < 0) return ret; + if ((role = gtk_window_get_role(w))) { + if (role && t) { + char *id = ca_sprintf_malloc("%s#%s", t, role); + + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ID, id)) < 0) { + ca_free(t); + return ret; + } + + ca_free(t); + } + } else if (t) + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ID, t)) < 0) + return ret; + if ((t = gtk_window_get_icon_name(w))) - if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_NAME, t)) < 0) + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_ICON_NAME, t)) < 0) + return ret; + + if ((dw = GTK_WIDGET(w)->window)) + if ((ret = ca_proplist_setf(p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long) GDK_WINDOW_XID(dw))) < 0) + return ret; + + if ((screen = gtk_widget_get_screen(w))) { + + if ((t = gtk_display_get_name(gdk_screen_get_display(screen)))) + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_X11_DISPLAY, t)) < 0) + return ret; + + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_X11_SCREEN, "%i", gdk_screen_get_number(screen))) < 0) + return ret; + + if (dw) + if ((ret = ca_proplist_sets(p, CA_PROP_WINDOW_X11_MONITOR, "%i", gdk_screen_get_monitor_at_window(screen, dw))) < 0) + return ret; + } + + return CA_SUCCESS; +} + +int ca_gtk_proplist_set_for_event(ca_proplist *p, GdkEvent *e) { + gdouble x, y; + GdkWindow *gw; + GtkWindow *w = NULL; + + ca_return_val_if_fail(p, CA_ERROR_INVALID); + ca_return_val_if_fail(e, CA_ERROR_INVALID); + + if (gw = gdk_event_get_window(e)) + if ((w = gtk_lookup_window(gw))) + if ((ret = ca_gtk_proplist_set_for_window(p, w)) < 0) + return ret; + + if (gdk_event_get_root_coords(e, &x, &y)) { + if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_X, "%0.0f", x)) < 0) return ret; + if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_Y, "%0.0f", y)) < 0) + return ret; + } + + if (e->event_type == GDK_BUTTON_PRESS || + e->event_type == GDK_2BUTTON_PRESS || + e->event_type == GDK_3BUTTON_PRESS || + e->event_type == GDK_BUTTON_RELEASE) { + if ((ret = ca_proplist_setf(p, CA_PROP_EVENT_MOUSE_BUTTON, "%u", e->button.button)) < 0) + return ret; + } + return CA_SUCCESS; } +int ca_gtk_play_for_window(GtkWidget *w, uint32_t id, ...) { + va_list ap; + int ret; + ca_proplist *p; + + ca_return_val_if_fail(w, CA_ERROR_INVALID); + + if ((ret = ca_proplist_create(&p)) < 0) + return ret; + + if ((ret = ca_gtk_proplist_set_for_window(p, w)) < 0) + goto fail; + va_start(ap, id); + ret = ca_proplist_merge_ap(p, ap); + va_end(ap); + if (ret < 0) + goto fail; -const char *ca_gtk_window_display(GtkWidget *w) { + ret = ca_context_play_full(ca_gtk_context_get(), id, p, NULL, NULL); + +fail: + + ca_assert_se(ca_proplist_destroy(p) == 0); + + return ret; } -const char *ca_gtk_window_xid(GtkWidget *w) { +int ca_gtk_play_for_event(GdkEvent *e, uint32_t id, ...) { + va_list ap; + int ret; + ca_proplist *p; + + ca_return_val_if_fail(w, CA_ERROR_INVALID); + + if ((ret = ca_proplist_create(&p)) < 0) + return ret; + + if ((ret = ca_gtk_proplist_set_for_event(p, e)) < 0) + goto fail; + + va_start(ap, id); + ret = ca_proplist_merge_ap(p, ap); + va_end(ap); + + if (ret < 0) + goto fail; + + ret = ca_context_play_full(ca_gtk_context_get(), id, p, NULL, NULL); + +fail: + + ca_assert_se(ca_proplist_destroy(p) == 0); + + return ret; } diff --git a/src/canberra-gtk.h b/src/canberra-gtk.h index b5941eb..412cdb2 100644 --- a/src/canberra-gtk.h +++ b/src/canberra-gtk.h @@ -29,6 +29,10 @@ ca_context *ca_gtk_context_get(void); int ca_gtk_play_for_window(GtkWidget *w, uint32_t id, ...) CA_GCC_SENTINEL; +int ca_gtk_play_for_event(GdkEvent *e, uint32_t id, ...) CA_GCC_SENTINEL; + int ca_gtk_proplist_set_for_window(ca_proplist *p, GtkWidget *w); +int ca_gtk_proplist_set_for_event(ca_proplist *p, GdkEvent *e); + #endif diff --git a/src/canberra.h b/src/canberra.h index 493cc99..7e7209c 100644 --- a/src/canberra.h +++ b/src/canberra.h @@ -95,12 +95,16 @@ #define CA_PROP_EVENT_DESCRIPTION "event.description" #define CA_PROP_EVENT_MOUSE_X "event.mouse.x" #define CA_PROP_EVENT_MOUSE_Y "event.mouse.y" +#define CA_PROP_EVENT_MOUSE_HPOS "event.mouse.hpos" +#define CA_PROP_EVENT_MOUSE_VPOS "event.mouse.vpos" #define CA_PROP_EVENT_MOUSE_BUTTON "event.mouse.button" #define CA_PROP_WINDOW_NAME "window.name" #define CA_PROP_WINDOW_ID "window.id" #define CA_PROP_WINDOW_ICON "window.icon" #define CA_PROP_WINDOW_ICON_NAME "window.icon_name" #define CA_PROP_WINDOW_X11_DISPLAY "window.x11.display" +#define CA_PROP_WINDOW_X11_SCREEN "window.x11.screen" +#define CA_PROP_WINDOW_X11_MONITOR "window.x11.monitor" #define CA_PROP_WINDOW_X11_XID "window.x11.xid" #define CA_PROP_APPLICATION_NAME "application.name" #define CA_PROP_APPLICATION_ID "application.id" diff --git a/src/common.c b/src/common.c index db59e27..3207e79 100644 --- a/src/common.c +++ b/src/common.c @@ -158,14 +158,10 @@ int ca_context_open(ca_context *c) { return ret; } -static int ca_proplist_from_ap(ca_proplist **_p, va_list ap) { +int ca_proplist_merge_ap(ca_proplist *p, va_list ap) { int ret; - ca_proplist *p; - - ca_assert(_p); - if ((ret = ca_proplist_create(&p)) < 0) - return ret; + ca_return_val_if_fail(p, CA_ERROR_INVALID); for (;;) { const char *key, *value; @@ -173,15 +169,27 @@ static int ca_proplist_from_ap(ca_proplist **_p, va_list ap) { if (!(key = va_arg(ap, const char*))) break; - if (!(value = va_arg(ap, const char*))) { - ret = CA_ERROR_INVALID; - goto fail; - } + if (!(value = va_arg(ap, const char*))) + return CA_ERROR_INVALID; if ((ret = ca_proplist_sets(p, key, value)) < 0) - goto fail; + return ret; } + return CA_SUCCESS; + +int ca_proplist_from_ap(ca_proplist **_p, va_list ap) { + int ret; + ca_proplist *p; + + ca_return_val_if_fail(_p, CA_ERROR_INVALID); + + if ((ret = ca_proplist_create(&p)) < 0) + return ret; + + if ((ret = ca_proplist_merge_ap(p, ap)) < 0) + goto fail; + *_p = p; return CA_SUCCESS; diff --git a/src/common.h b/src/common.h index 13139b3..ebf1aeb 100644 --- a/src/common.h +++ b/src/common.h @@ -45,6 +45,9 @@ typedef enum ca_cache_control { CA_CACHE_CONTROL_VOLATILE } ca_cache_control_t; +int ca_proplist_merge_ap(ca_proplist *p, va_list ap); +int ca_proplist_from_ap(ca_proplist **_p, va_list ap); + int ca_parse_cache_control(ca_cache_control_t *control, const char *c); #endif diff --git a/src/test-canberra.c b/src/test-canberra.c index 6dd1d5b..266e441 100644 --- a/src/test-canberra.c +++ b/src/test-canberra.c @@ -52,7 +52,7 @@ int main(int argc, char *argv[]) { ret = ca_context_change_props(c, CA_PROP_APPLICATION_NAME, "An example", CA_PROP_APPLICATION_ID, "org.freedesktop.libcanberra.Test", - CA_PROP_WINDOW_X11_DISPLAY, getenv("DISPLAY"), + CA_PROP_WINDOW_X11_SCREEN, getenv("DISPLAY"), NULL); fprintf(stderr, "change_props: %s\n", ca_strerror(ret)); @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) { /* Now trigger a sound event, the quick version */ ret = ca_context_play(c, 0, - CA_PROP_EVENT_ID, "desktop-logout", + CA_PROP_EVENT_ID, "desktop-login", CA_PROP_MEDIA_FILENAME, "/usr/share/sounds/bar.wav", CA_PROP_MEDIA_NAME, "User has logged off from session", CA_PROP_MEDIA_LANGUAGE, "en_EN", @@ -83,7 +83,7 @@ int main(int argc, char *argv[]) { usleep(500000); /* Stop one sound */ - ret = ca_context_cancel(c, 0); +/* ret = ca_context_cancel(c, 0); */ fprintf(stderr, "cancel: %s\n", ca_strerror(ret)); fprintf(stderr, "Sleep 2s ...\n"); diff --git a/todo b/todo index 57b59e0..ca19eb1 100644 --- a/todo +++ b/todo @@ -3,3 +3,4 @@ * alsa backend * dso backend * lookup cache +* ca_context_left_to_play() -- cgit