From cef451ebac42f21a85bcc65d8b122c72f94e918c Mon Sep 17 00:00:00 2001 From: Charles Lehner Date: Sun, 20 Sep 2015 01:08:39 -0400 Subject: Use libnotify for notifications in glib < 2.40 (#65) --- mk/modules.mk | 4 ++++ modules/gtk/gtk_mod.c | 58 ++++++++++++++++++++++++++++++++++++++++++++------- modules/gtk/module.mk | 9 ++++++-- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/mk/modules.mk b/mk/modules.mk index 085a8c5..ac16662 100644 --- a/mk/modules.mk +++ b/mk/modules.mk @@ -225,6 +225,10 @@ ifeq ($(OS),freebsd) MODULES += dtmfio endif +ifneq ($(USE_GTK),) +USE_LIBNOTIFY := $(shell pkg-config 'libnotify glib-2.0 < 2.40' && echo "yes") +endif + endif # ------------------------------------------------------------------------- # diff --git a/modules/gtk/gtk_mod.c b/modules/gtk/gtk_mod.c index 427912c..2a99a28 100644 --- a/modules/gtk/gtk_mod.c +++ b/modules/gtk/gtk_mod.c @@ -12,6 +12,14 @@ #include #include "gtk_mod.h" +#ifdef USE_LIBNOTIFY +#include +#endif + +#if GLIB_CHECK_VERSION(2,40,0) || defined(USE_LIBNOTIFY) +#define USE_NOTIFICATIONS 1 +#endif + /* About */ #define COPYRIGHT " Copyright (C) 2010 - 2015 Alfred E. Heggestad et al." #define COMMENTS "A modular SIP User-Agent with audio and video support" @@ -265,18 +273,21 @@ static void accounts_menu_set_status(struct gtk_mod *mod, } +#ifdef USE_NOTIFICATIONS static void notify_incoming_call(struct gtk_mod *mod, struct call *call) { - GNotification *notification; - GVariant *target; + static const char *title = "Incoming call"; + const char *msg = call_peeruri(call); + +#if GLIB_CHECK_VERSION(2,40,0) char id[64]; + GVariant *target; + GNotification *notification = g_notification_new(title); re_snprintf(id, sizeof id, "incoming-call-%p", call); id[sizeof id - 1] = '\0'; - notification = g_notification_new("Incoming call"); - #if GLIB_CHECK_VERSION(2,42,0) g_notification_set_priority(notification, G_NOTIFICATION_PRIORITY_URGENT); @@ -285,14 +296,25 @@ static void notify_incoming_call(struct gtk_mod *mod, #endif target = g_variant_new_int64(GPOINTER_TO_INT(call)); - g_notification_set_body(notification, call_peeruri(call)); + g_notification_set_body(notification, msg); g_notification_add_button_with_target_value(notification, "Answer", "app.answer", target); g_notification_add_button_with_target_value(notification, "Reject", "app.reject", target); g_application_send_notification(mod->app, id, notification); + +#elif defined(USE_LIBNOTIFY) + if (!notify_is_initted()) + return; + NotifyNotification* notification = notify_notification_new(title, + msg, "midori"); + notify_notification_set_urgency(notification, NOTIFY_URGENCY_CRITICAL); + notify_notification_show(notification, NULL); + +#endif g_object_unref(notification); } +#endif static void denotify_incoming_call(struct gtk_mod *mod, @@ -392,9 +414,11 @@ static void ua_event_handler(struct ua *ua, accounts_menu_set_status(mod, ua, ev); break; +#ifdef USE_NOTIFICATIONS case UA_EVENT_CALL_INCOMING: notify_incoming_call(mod, call); break; +#endif case UA_EVENT_CALL_CLOSED: win = get_call_window(mod, call); @@ -435,15 +459,16 @@ static void ua_event_handler(struct ua *ua, gdk_threads_leave(); } +#ifdef USE_NOTIFICATIONS static void message_handler(const struct pl *peer, const struct pl *ctype, struct mbuf *body, void *arg) { struct gtk_mod *mod = arg; - GNotification *notification; char title[128]; char msg[512]; (void)ctype; + /* Display notification of chat */ re_snprintf(title, sizeof title, "Chat from %r", peer); @@ -452,11 +477,24 @@ static void message_handler(const struct pl *peer, const struct pl *ctype, re_snprintf(msg, sizeof msg, "%b", mbuf_buf(body), mbuf_get_left(body)); - notification = g_notification_new(title); +#if GLIB_CHECK_VERSION(2,40,0) + GNotification *notification = g_notification_new(title); g_notification_set_body(notification, msg); g_application_send_notification(mod->app, NULL, notification); + +#elif defined(USE_LIBNOTIFY) + (void)mod; + + if (!notify_is_initted()) + return; + NotifyNotification* notification = notify_notification_new(title, msg, + "baresip"); + notify_notification_show(notification, NULL); + +#endif g_object_unref(notification); } +#endif static void popup_menu(struct gtk_mod *mod, GtkMenuPositionFunc position, @@ -611,6 +649,10 @@ static void *gtk_thread(void *arg) err = NULL; } +#ifdef USE_LIBNOTIFY + notify_init("baresip"); +#endif + mod->status_icon = gtk_status_icon_new_from_icon_name("call-start"); gtk_status_icon_set_tooltip_text (mod->status_icon, "baresip"); @@ -859,9 +901,11 @@ static int module_init(void) return err; aufilt_register(&vumeter); +#ifdef USE_NOTIFICATIONS err = message_init(message_handler, &mod_obj); if (err) return err; +#endif err = cmd_register(cmdv, ARRAY_SIZE(cmdv)); diff --git a/modules/gtk/module.mk b/modules/gtk/module.mk index aae0145..2ed3709 100644 --- a/modules/gtk/module.mk +++ b/modules/gtk/module.mk @@ -8,8 +8,13 @@ MOD := gtk $(MOD)_SRCS += gtk_mod.c call_window.c dial_dialog.c transfer_dialog.c \ uri_entry.c -$(MOD)_LFLAGS += `pkg-config --libs gtk+-2.0 ` -$(MOD)_CFLAGS += `pkg-config --cflags gtk+-2.0 ` +$(MOD)_LFLAGS += `pkg-config --libs gtk+-2.0 $($(MOD)_EXTRA)` +$(MOD)_CFLAGS += `pkg-config --cflags gtk+-2.0 $($(MOD)_EXTRA)` $(MOD)_CFLAGS += -Wno-strict-prototypes +ifneq ($(USE_LIBNOTIFY),) +$(MOD)_EXTRA = libnotify +$(MOD)_CFLAGS += -DUSE_LIBNOTIFY=1 +endif + include mk/mod.mk -- cgit v1.2.3 From af7051ee3e5d06fec09e3aea2968241a8c7dd2e1 Mon Sep 17 00:00:00 2001 From: Charles Lehner Date: Sun, 20 Sep 2015 02:13:12 -0400 Subject: Add submenu per incoming call Allows answering calls without GNotification/Libnotify --- modules/gtk/gtk_mod.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/modules/gtk/gtk_mod.c b/modules/gtk/gtk_mod.c index 2a99a28..11d1fae 100644 --- a/modules/gtk/gtk_mod.c +++ b/modules/gtk/gtk_mod.c @@ -50,6 +50,7 @@ struct gtk_mod { GSList *accounts_menu_group; struct dial_dialog *dial_dialog; GSList *call_windows; + GSList *incoming_call_menus; }; struct gtk_mod mod_obj; @@ -65,6 +66,7 @@ enum gtk_mod_events { static void answer_activated(GSimpleAction *, GVariant *, gpointer); static void reject_activated(GSimpleAction *, GVariant *, gpointer); +static void denotify_incoming_call(struct gtk_mod *, struct call *); static GActionEntry app_entries[] = { {"answer", answer_activated, "x", NULL, NULL, {0} }, @@ -174,6 +176,24 @@ static void menu_on_presence_set(GtkMenuItem *item, struct gtk_mod *mod) } +static void menu_on_incoming_call_answer(GtkMenuItem *menuItem, + struct gtk_mod *mod) +{ + struct call *call = g_object_get_data(G_OBJECT(menuItem), "call"); + denotify_incoming_call(mod, call); + mqueue_push(mod->mq, MQ_ANSWER, call); +} + + +static void menu_on_incoming_call_reject(GtkMenuItem *menuItem, + struct gtk_mod *mod) +{ + struct call *call = g_object_get_data(G_OBJECT(menuItem), "call"); + denotify_incoming_call(mod, call); + mqueue_push(mod->mq, MQ_HANGUP, call); +} + + static GtkMenuItem *accounts_menu_add_item(struct gtk_mod *mod, struct ua *ua) { @@ -273,12 +293,13 @@ static void accounts_menu_set_status(struct gtk_mod *mod, } -#ifdef USE_NOTIFICATIONS static void notify_incoming_call(struct gtk_mod *mod, struct call *call) { static const char *title = "Incoming call"; const char *msg = call_peeruri(call); + GtkWidget *call_menu; + GtkWidget *menu_item; #if GLIB_CHECK_VERSION(2,40,0) char id[64]; @@ -302,29 +323,69 @@ static void notify_incoming_call(struct gtk_mod *mod, g_notification_add_button_with_target_value(notification, "Reject", "app.reject", target); g_application_send_notification(mod->app, id, notification); + g_object_unref(notification); #elif defined(USE_LIBNOTIFY) + /* If glib does not have GNotification, use libnotify instead. */ if (!notify_is_initted()) return; NotifyNotification* notification = notify_notification_new(title, - msg, "midori"); + msg, "baresip"); notify_notification_set_urgency(notification, NOTIFY_URGENCY_CRITICAL); notify_notification_show(notification, NULL); - -#endif g_object_unref(notification); -} + #endif + /* Add incoming call to the app menu */ + call_menu = gtk_menu_new(); + menu_item = gtk_menu_item_new_with_mnemonic("_Incoming call"); + g_object_set_data(G_OBJECT(menu_item), "call", call); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), + call_menu); + gtk_menu_shell_prepend(GTK_MENU_SHELL(mod->app_menu), menu_item); + mod->incoming_call_menus = g_slist_append(mod->incoming_call_menus, + menu_item); + + menu_item = gtk_menu_item_new_with_label(call_peeruri(call)); + gtk_widget_set_sensitive(menu_item, FALSE); + gtk_menu_shell_append(GTK_MENU_SHELL(call_menu), menu_item); + + menu_item = gtk_menu_item_new_with_mnemonic("_Accept"); + g_object_set_data(G_OBJECT(menu_item), "call", call); + g_signal_connect(G_OBJECT(menu_item), "activate", + G_CALLBACK(menu_on_incoming_call_answer), mod); + gtk_menu_shell_append(GTK_MENU_SHELL(call_menu), menu_item); + + menu_item = gtk_menu_item_new_with_mnemonic("_Reject"); + g_object_set_data(G_OBJECT(menu_item), "call", call); + g_signal_connect(G_OBJECT(menu_item), "activate", + G_CALLBACK(menu_on_incoming_call_reject), mod); + gtk_menu_shell_append(GTK_MENU_SHELL(call_menu), menu_item); +} static void denotify_incoming_call(struct gtk_mod *mod, struct call *call) { +#if GLIB_CHECK_VERSION(2,40,0) char id[64]; re_snprintf(id, sizeof id, "incoming-call-%p", call); id[sizeof id - 1] = '\0'; g_application_withdraw_notification(mod->app, id); +#endif + + /* Remove call submenu */ + GSList *item, *next; + for (item = mod->incoming_call_menus; item; item = next) { + next = item->next; + GtkWidget *menu_item = item->data; + if (call == g_object_get_data(G_OBJECT(menu_item), "call")) { + gtk_widget_destroy(menu_item); + mod->incoming_call_menus = + g_slist_delete_link(mod->incoming_call_menus, item); + } + } } @@ -481,6 +542,7 @@ static void message_handler(const struct pl *peer, const struct pl *ctype, GNotification *notification = g_notification_new(title); g_notification_set_body(notification, msg); g_application_send_notification(mod->app, NULL, notification); + g_object_unref(notification); #elif defined(USE_LIBNOTIFY) (void)mod; @@ -490,9 +552,8 @@ static void message_handler(const struct pl *peer, const struct pl *ctype, NotifyNotification* notification = notify_notification_new(title, msg, "baresip"); notify_notification_show(notification, NULL); - -#endif g_object_unref(notification); +#endif } #endif @@ -664,6 +725,7 @@ static void *gtk_thread(void *arg) mod->contacts_inited = false; mod->dial_dialog = NULL; mod->call_windows = NULL; + mod->incoming_call_menus = NULL; /* App menu */ mod->app_menu = gtk_menu_new(); -- cgit v1.2.3 From f6580a4c7a0c01153df720bfd3ad5396ffb646ba Mon Sep 17 00:00:00 2001 From: Charles Lehner Date: Sun, 20 Sep 2015 03:04:01 -0400 Subject: gtk: clean up more things on module unload --- modules/gtk/gtk_mod.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/gtk/gtk_mod.c b/modules/gtk/gtk_mod.c index 11d1fae..ee9e1a2 100644 --- a/modules/gtk/gtk_mod.c +++ b/modules/gtk/gtk_mod.c @@ -987,6 +987,15 @@ static int module_close(void) aufilt_unregister(&vumeter); message_close(); +#ifdef USE_LIBNOTIFY + if (notify_is_initted()) + notify_uninit(); +#endif + + g_slist_free(mod_obj.accounts_menu_group); + g_slist_free(mod_obj.call_windows); + g_slist_free(mod_obj.incoming_call_menus); + return 0; } -- cgit v1.2.3