From edb41bef60f68a74f26d156daaa880cb8f485525 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Mon, 10 Mar 2025 15:46:59 +0100 Subject: [PATCH] Re-factor notifier. * Add an internal `_notifier_uninit()` function. * Instead of `#ifdef` inside `notify()`, provide different target-specific static implementations. This also introduces `log_error_once()`. Signed-off-by: Steffen Jaeckel --- src/log.h | 15 +++ src/ui/notifier.c | 237 ++++++++++++++++++++++++++-------------------- 2 files changed, 148 insertions(+), 104 deletions(-) diff --git a/src/log.h b/src/log.h index 14394a24..d40d1889 100644 --- a/src/log.h +++ b/src/log.h @@ -38,6 +38,10 @@ #include +#define PROF_TMPVAR__(n, l) n##l +#define PROF_TMPVAR_(n, l) PROF_TMPVAR__(n, l) +#define PROF_TMPVAR(n) PROF_TMPVAR_(PROF_##n##_, __LINE__) + // log levels typedef enum { PROF_LEVEL_DEBUG, @@ -58,6 +62,17 @@ void log_msg(log_level_t level, const char* const area, const char* const msg); int log_level_from_string(char* log_level, log_level_t* level); const char* log_string_from_level(log_level_t level); +#define _log_Xtype_once(type, ...) \ + do { \ + static gboolean PROF_TMPVAR(once) = FALSE; \ + if (!PROF_TMPVAR(once)) { \ + log_##type(__VA_ARGS__); \ + PROF_TMPVAR(once) = TRUE; \ + } \ + } while (0) + +#define log_error_once(...) _log_Xtype_once(error, __VA_ARGS__) + void log_stderr_init(log_level_t level); void log_stderr_handler(void); diff --git a/src/ui/notifier.c b/src/ui/notifier.c index 344748c3..32c97590 100644 --- a/src/ui/notifier.c +++ b/src/ui/notifier.c @@ -56,8 +56,139 @@ #include "xmpp/muc.h" static GTimer* remind_timer; + #ifdef HAVE_LIBNOTIFY static NotifyNotification* notification; + +static void +_notifier_uninit(void) +{ + if (notify_is_initted()) { + g_object_unref(G_OBJECT(notification)); + notification = NULL; + notify_uninit(); + } +} +#else +static void +_notifier_uninit(void) +{ +} +#endif + +#ifdef HAVE_LIBNOTIFY +static void +_notify(const char* const message, int timeout, const char* const category) +{ + log_debug("Attempting notification: %s", message); + if (notify_is_initted()) { + log_debug("Reinitialising libnotify"); + notify_uninit(); + } else { + log_debug("Initialising libnotify"); + } + notify_init("Profanity"); + + if (notify_is_initted()) { + if (notification) + g_object_unref(G_OBJECT(notification)); + notification = notify_notification_new("Profanity", message, NULL); + notify_notification_set_timeout(notification, timeout); + notify_notification_set_category(notification, category); + notify_notification_set_urgency(notification, NOTIFY_URGENCY_NORMAL); + + GError* error = NULL; + gboolean notify_success = notify_notification_show(notification, &error); + + if (!notify_success) { + log_error("Error sending desktop notification:"); + log_error(" -> Message : %s", message); + log_error(" -> Error : %s", error->message); + g_error_free(error); + } else { + log_debug("Notification sent."); + } + } else { + log_error("Libnotify not initialised."); + } +} +#elif defined(PLATFORM_CYGWIN) +static void +_notify(const char* const message, int timeout, const char* const category) +{ + NOTIFYICONDATA nid; + memset(&nid, 0, sizeof(nid)); + nid.cbSize = sizeof(NOTIFYICONDATA); + // nid.hWnd = hWnd; + nid.uID = 100; + nid.uVersion = NOTIFYICON_VERSION; + // nid.uCallbackMessage = WM_MYMESSAGE; + nid.hIcon = LoadIcon(NULL, IDI_APPLICATION); + strcpy(nid.szTip, "Tray Icon"); + nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; + Shell_NotifyIcon(NIM_ADD, &nid); + + // For a Ballon Tip + nid.uFlags = NIF_INFO; + strcpy(nid.szInfoTitle, "Profanity"); // Title + strncpy(nid.szInfo, message, sizeof(nid.szInfo) - 1); // Copy Tip + nid.uTimeout = timeout; // 3 Seconds + nid.dwInfoFlags = NIIF_INFO; + + Shell_NotifyIcon(NIM_MODIFY, &nid); +} +#elif defined(HAVE_OSXNOTIFY) +static void +_notify(const char* const message, int timeout, const char* const category) +{ + GString* notify_command = g_string_new("terminal-notifier -title \"Profanity\" -message '"); + + auto_char char* escaped_single = str_replace(message, "'", "'\\''"); + + if (escaped_single[0] == '<') { + g_string_append(notify_command, "\\<"); + g_string_append(notify_command, &escaped_single[1]); + } else if (escaped_single[0] == '[') { + g_string_append(notify_command, "\\["); + g_string_append(notify_command, &escaped_single[1]); + } else if (escaped_single[0] == '(') { + g_string_append(notify_command, "\\("); + g_string_append(notify_command, &escaped_single[1]); + } else if (escaped_single[0] == '{') { + g_string_append(notify_command, "\\{"); + g_string_append(notify_command, &escaped_single[1]); + } else { + g_string_append(notify_command, escaped_single); + } + + g_string_append(notify_command, "'"); + + char* term_name = getenv("TERM_PROGRAM"); + char* app_id = NULL; + if (g_strcmp0(term_name, "Apple_Terminal") == 0) { + app_id = "com.apple.Terminal"; + } else if (g_strcmp0(term_name, "iTerm.app") == 0) { + app_id = "com.googlecode.iterm2"; + } + + if (app_id) { + g_string_append(notify_command, " -sender "); + g_string_append(notify_command, app_id); + } + + int res = system(notify_command->str); + if (res == -1) { + log_error("Could not send desktop notification."); + } + + g_string_free(notify_command, TRUE); +} +#else +static void +_notify(const char* const message, int timeout, const char* const category) +{ + log_error_once("Notification backend missing"); +} #endif void @@ -69,13 +200,7 @@ notifier_initialise(void) void notifier_uninit(void) { -#ifdef HAVE_LIBNOTIFY - g_object_unref(G_OBJECT(notification)); - notification = NULL; - if (notify_is_initted()) { - notify_uninit(); - } -#endif + _notifier_uninit(); g_timer_destroy(remind_timer); } @@ -202,102 +327,6 @@ notify_remind(void) void notify(const char* const message, int timeout, const char* const category) { -#ifdef HAVE_LIBNOTIFY log_debug("Attempting notification: %s", message); - if (notify_is_initted()) { - log_debug("Reinitialising libnotify"); - notify_uninit(); - } else { - log_debug("Initialising libnotify"); - } - notify_init("Profanity"); - - if (notify_is_initted()) { - if (notification) - g_object_unref(G_OBJECT(notification)); - notification = notify_notification_new("Profanity", message, NULL); - notify_notification_set_timeout(notification, timeout); - notify_notification_set_category(notification, category); - notify_notification_set_urgency(notification, NOTIFY_URGENCY_NORMAL); - - GError* error = NULL; - gboolean notify_success = notify_notification_show(notification, &error); - - if (!notify_success) { - log_error("Error sending desktop notification:"); - log_error(" -> Message : %s", message); - log_error(" -> Error : %s", error->message); - g_error_free(error); - } else { - log_debug("Notification sent."); - } - } else { - log_error("Libnotify not initialised."); - } -#endif -#ifdef PLATFORM_CYGWIN - NOTIFYICONDATA nid; - memset(&nid, 0, sizeof(nid)); - nid.cbSize = sizeof(NOTIFYICONDATA); - // nid.hWnd = hWnd; - nid.uID = 100; - nid.uVersion = NOTIFYICON_VERSION; - // nid.uCallbackMessage = WM_MYMESSAGE; - nid.hIcon = LoadIcon(NULL, IDI_APPLICATION); - strcpy(nid.szTip, "Tray Icon"); - nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; - Shell_NotifyIcon(NIM_ADD, &nid); - - // For a Ballon Tip - nid.uFlags = NIF_INFO; - strcpy(nid.szInfoTitle, "Profanity"); // Title - strncpy(nid.szInfo, message, sizeof(nid.szInfo) - 1); // Copy Tip - nid.uTimeout = timeout; // 3 Seconds - nid.dwInfoFlags = NIIF_INFO; - - Shell_NotifyIcon(NIM_MODIFY, &nid); -#endif -#ifdef HAVE_OSXNOTIFY - GString* notify_command = g_string_new("terminal-notifier -title \"Profanity\" -message '"); - - auto_char char* escaped_single = str_replace(message, "'", "'\\''"); - - if (escaped_single[0] == '<') { - g_string_append(notify_command, "\\<"); - g_string_append(notify_command, &escaped_single[1]); - } else if (escaped_single[0] == '[') { - g_string_append(notify_command, "\\["); - g_string_append(notify_command, &escaped_single[1]); - } else if (escaped_single[0] == '(') { - g_string_append(notify_command, "\\("); - g_string_append(notify_command, &escaped_single[1]); - } else if (escaped_single[0] == '{') { - g_string_append(notify_command, "\\{"); - g_string_append(notify_command, &escaped_single[1]); - } else { - g_string_append(notify_command, escaped_single); - } - - g_string_append(notify_command, "'"); - - char* term_name = getenv("TERM_PROGRAM"); - char* app_id = NULL; - if (g_strcmp0(term_name, "Apple_Terminal") == 0) { - app_id = "com.apple.Terminal"; - } else if (g_strcmp0(term_name, "iTerm.app") == 0) { - app_id = "com.googlecode.iterm2"; - } - - if (app_id) { - g_string_append(notify_command, " -sender "); - g_string_append(notify_command, app_id); - } - - int res = system(notify_command->str); - if (res == -1) { - log_error("Could not send desktop notification."); - } - - g_string_free(notify_command, TRUE); -#endif + _notify(message, timeout, category); }