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 <s@jaeckel.eu>
This commit is contained in:
Steffen Jaeckel
2025-03-10 15:46:59 +01:00
parent 00d50d457c
commit edb41bef60
2 changed files with 148 additions and 104 deletions

View File

@@ -38,6 +38,10 @@
#include <glib.h>
#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);

View File

@@ -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);
}