From ef15b583df8200e1efcd07c1418598d47da4bab2 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Thu, 9 Jun 2022 23:49:49 -0500 Subject: [PATCH] Initial freedesktop_notifier utility --- .gitignore | 1 + README.md | 4 ++ notifications.prs | 3 ++ src/freedesktop_notifier.nim | 20 +++++++++ src/notifications.nim | 18 ++++++++ src/private/libnotify.nim | 87 ++++++++++++++++++++++++++++++++++++ syndicate_utils.nimble | 4 +- 7 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 notifications.prs create mode 100644 src/freedesktop_notifier.nim create mode 100644 src/notifications.nim create mode 100644 src/private/libnotify.nim diff --git a/.gitignore b/.gitignore index 04c28eb..f25d384 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ http_translator json_translator msg json_socket_translator +freedesktop_notifier diff --git a/README.md b/README.md index 2f409ca..c08b432 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Syndicate utils +## freedesktop_notifier + +Does that desktop notification thing. See [notifications.prs](./notifications.prs) for the message schema. + ## http_translator Dispatches HTTP requests to registered handlers. diff --git a/notifications.prs b/notifications.prs new file mode 100644 index 0000000..1b27ebd --- /dev/null +++ b/notifications.prs @@ -0,0 +1,3 @@ +version 1 . +Urgency = =Low / =Normal / =Critical . +Notify = . diff --git a/src/freedesktop_notifier.nim b/src/freedesktop_notifier.nim new file mode 100644 index 0000000..6e22f08 --- /dev/null +++ b/src/freedesktop_notifier.nim @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: ☭ 2022 Emery Hemingway +# SPDX-License-Identifier: Unlicense + +import std/[asyncdispatch, strutils] +import syndicate +import ./private/libnotify +import ./notifications + +bootDataspace("main") do (ds: Ref; turn: var Turn): + connectStdio(ds, turn) + let nc = newNotifyClient("syndicate") + onMessage(turn, ds, ?Notify) do (s: string, b: string, t: int, u: Urgency): + nc.send_new_notification( + summary = s, + body = b, + icon_fname = "", + timeout = t, + urgency = NotificationUrgency u) + +runForever() diff --git a/src/notifications.nim b/src/notifications.nim new file mode 100644 index 0000000..05f4593 --- /dev/null +++ b/src/notifications.nim @@ -0,0 +1,18 @@ + +import + std/typetraits, preserves + +type + Notify* {.preservesRecord: "notify".} = object + `summary`*: string + `body`*: string + `timeout`*: int + `urgency`*: Urgency + + `Urgency`* {.preservesOr, pure.} = enum + `Low`, `Normal`, `Critical` +proc `$`*(x: Notify): string = + `$`(toPreserve(x)) + +proc encode*(x: Notify): seq[byte] = + encode(toPreserve(x)) diff --git a/src/private/libnotify.nim b/src/private/libnotify.nim new file mode 100644 index 0000000..c6ab0f2 --- /dev/null +++ b/src/private/libnotify.nim @@ -0,0 +1,87 @@ +## +## A minimalistic wrapper for libnotify +## https://github.com/FedericoCeratto/nim-libnotify +## +## Wraps libnotify.so.4 https://developer.gnome.org/libnotify/ +## +## Released under LGPLv3, see LICENSE file +## 2015 - Federico Ceratto +## + +{.deadCodeElim: on.} + +import glib2 + +const libnotify_fn* = "libnotify.so.4" + +type Notify = pointer + +type NotificationUrgency* = enum + Low, Normal, Critical + +proc notify_init*(name: cstring): bool + {.importc: "notify_init", dynlib: libnotify_fn.} + +proc notify_uninit*(): void {.importc: "notify_uninit", + dynlib: libnotify_fn.} + +proc notify_is_initted(): bool + {.importc: "notify_is_initted", dynlib: libnotify_fn.} + +proc notify_get_app_name(): cstring + {.importc: "notify_get_app_name", dynlib: libnotify_fn.} + +proc notify_set_app_name(name: cstring): void + {.importc: "notify_set_app_name", dynlib: libnotify_fn.} + +proc notify_notification_new(a, b, c: cstring): Notify + {.importc: "notify_notification_new", dynlib: libnotify_fn.} + +proc notify_notification_show(notification: Notify, gerror: cint): gboolean + {.importc: "notify_notification_show", dynlib: libnotify_fn.} + +proc notify_notification_set_timeout(notification: Notify, timeout: cint): void + {.importc: "notify_notification_set_timeout", dynlib: libnotify_fn.} + +proc notify_notification_set_urgency(notification: Notify, urgency: NotificationUrgency): void + {.importc: "notify_notification_set_urgency", dynlib: libnotify_fn.} + + + +type NotifyClient* = ref object of RootObj + + +proc newNotifyClient*(app_name: string): NotifyClient = + ## Initialize notification client + if notify_is_initted() == false: + doAssert notify_init(app_name) + doAssert notify_is_initted() + new(NotifyClient) + +proc get_app_name*(self: NotifyClient): string = + ## Get application name + return $notify_get_app_name() + +proc set_app_name*(self: NotifyClient, app_name: string) = + ## Set application name + notify_set_app_name(app_name.cstring) + +proc send_new_notification*(self: NotifyClient, summary, body, icon_fname: string, timeout=0, + urgency=NotificationUrgency.Normal) = + ## Show a notification. Optionally specify a timeout in milliseconds and an + ## urgency as a NotificationUrgency.Low / Normal / Critical + let n = notify_notification_new(summary.cstring, body.cstring, icon_fname.cstring) + + notify_notification_set_urgency(n, urgency) + + if timeout != 0: + notify_notification_set_timeout(n, timeout.cint) + + let error: cint = 0 + doAssert notify_notification_show(n, error) + if error != 0: + raise newException(Exception, "Unhandled exception") + +proc uninit*(self: NotifyClient) = + ## Uninitialize the library + notify_uninit() diff --git a/syndicate_utils.nimble b/syndicate_utils.nimble index a0ee0b7..2257bc4 100644 --- a/syndicate_utils.nimble +++ b/syndicate_utils.nimble @@ -5,9 +5,9 @@ author = "Emery Hemingway" description = "Utilites for Syndicated Actors and Synit" license = "unlicense" srcDir = "src" -bin = @["http_translator", "json_socket_translator", "json_translator", "msg"] +bin = @["http_translator", "json_socket_translator", "json_translator", "msg", "freedesktop_notifier"] # Dependencies -requires "nim >= 1.6.6", "syndicate >= 0.3.1" +requires "nim >= 1.6.6", "syndicate >= 0.3.1", "gtk2 >= 1.3"