Modifier des notifications
avec libnotify

La librairie libnotify permet d’envoyer des notifications à un daemon régulièrement utilisé sous Linux. Nous allons ici voir comment mettre à jour des notifications qui sont déjà affichées.

Avec notify-send ?

Cette librairie apporte la commande notify-send, qui affiche une notification directement sur le bureau :

notify-send "Titre" "Description"

Mais qu’en est-il si l’on souhaite mettre à jour ou modifier une notification déjà affichée ? Si on lance cette commande plusieurs fois, les notifications s’empilent plutôt que de mettre à jour celle qui les précède immédiatement.

Le manuel (man notify-send) nous montre que les options sont peu nombreuses, et rien ne semble répondre à cette question:

-?, --help
-u, --urgency=LEVEL
-t, --expire-time=TIME
-i, --icon=ICON[,ICON...]
-c, --category=TYPE[,TYPE...]
-h, --hint=TYPE:NAME:VALUE

Il va donc falloir faire sans cette commande et aller un peu aux sources.

Avec gdbus

notify-send se contente d’envoyer des informations de façon simplifiée, mais nous pouvons utiliser un outil de plus bas niveau : gdbus.

La commande suivante va nous donner le même résultat que précédemment :

gdbus call \
    --session \
    --dest org.freedesktop.Notifications \
    --object-path /org/freedesktop/Notifications \
    --method org.freedesktop.Notifications.Notify \
    "identifier" \
    "1" \
    "" \
    "Notification title" \
    "Notification description" \
    "[]" \
    "{}" \
    "2000"

Le deuxième paramètre (ici 1) sera l’identifiant de la notification que l’on souhaite remplacer, nous y reviendrons dans quelques instants. Le suivant nous permet de définir une icône. "[]" permet de spécifier des actions, "{}" des indices, and finalement le dernier argument 2000 permet d’indiquer la durée d’affichage de la notification (en millisecondes).

Une fois que cette commande est exécutée, le terminal retourne une réponse qui ressemble à :

(uint32 13,)

Ce nombre, ici 13 est celui qui nous permettra d’identifier la notification que nous allons remplacer.

Cela signifie que la commande suivante ne va pas créer une nouvelle notification, mais remplacer la précédente :

gdbus call \
    --session \
    --dest org.freedesktop.Notifications \
    --object-path /org/freedesktop/Notifications \
    --method org.freedesktop.Notifications.Notify \
    "identifier" \
    "13" \
    "" \
    "My updated title" \
    "My updated description" \
    "[]" \
    "{}" \
    "2000"

Récupérer l’id de la notification

Pour automatiser les choses, il nous faut maintenant récupérer cet identifiant automatiquement, puis le réinjecter dans notre fonction.

Pour le récupérer, on filtre la fonction précédente avec :

| sed 's/[^ ]* //; s/,.//'

On pourrait stocker ce nombre dans un fichier temporaire, par exemple > /tmp/.notif. Cependant, pour éviter d’utiliser le disque dur ou le SSD, nous pouvons directement stocker un fichier dans la RAM :

> ${XDG_RUNTIME_DIR}/.notif

Ce nombre peut-être initié au démarrage avec :

echo '1' > ${XDG_RUNTIME_DIR}/.notif

On peut alors le récupérer avec :

notif=`cat ${XDG_RUNTIME_DIR}/.notif`

Résultat

Nous obtenons donc le code suivant, qui exécuté plusieurs fois, met à jour la notification :

notif=`cat ${XDG_RUNTIME_DIR}/.notif`
gdbus call \
    --session \
    --dest org.freedesktop.Notifications \
    --object-path /org/freedesktop/Notifications \
    --method org.freedesktop.Notifications.Notify \
    "identifier" \
    "`echo $notif`" \
    "" \
    "My updated title" \
    "My updated description" \
    "[]" \
    "{}" \
    "2000" \
| sed 's/[^ ]* //; s/,.//' > ${XDG_RUNTIME_DIR}/.notif