#!/bin/sh set -eu DBUS_NAME="org.freedesktop.Notifications" DBUS_PATH="/org/freedesktop/Notifications" DBUS_IFAC_DUNST="org.dunstproject.cmd0" DBUS_IFAC_PROP="org.freedesktop.DBus.Properties" DBUS_IFAC_FDN="org.freedesktop.Notifications" die(){ printf "%s\n" "${1}" >&2; exit 1; } show_help() { cat <<-EOH Usage: dunstctl [parameters]" Commands: action Perform the default action, or open the context menu of the notification at the given position close Close the last notification close-all Close the all notifications context Open context menu count [displayed|history|waiting] Show the number of notifications history-pop Pop one notification from history is-paused Check if dunst is running or paused set-paused [true|false|toggle] Set the pause status debug Print debugging information help Show this help EOH } dbus_send_checked() { dbus-send "$@" \ || die "Failed to communicate with dunst, is it running? Or maybe the version is outdated. You can try 'dunstctl debug' as a next debugging step." } method_call() { dbus_send_checked --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "$@" } property_get() { dbus_send_checked --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_PROP}.Get" "string:${DBUS_IFAC_DUNST}" "string:${1}" } property_set() { dbus_send_checked --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_PROP}.Set" "string:${DBUS_IFAC_DUNST}" "string:${1}" "${2}" } command -v dbus-send >/dev/null 2>/dev/null || \ die "Command dbus-send not found" case "${1:-}" in "action") method_call "${DBUS_IFAC_DUNST}.NotificationAction" "int32:${2:-0}" >/dev/null ;; "close") method_call "${DBUS_IFAC_DUNST}.NotificationCloseLast" >/dev/null ;; "close-all") method_call "${DBUS_IFAC_DUNST}.NotificationCloseAll" >/dev/null ;; "context") method_call "${DBUS_IFAC_DUNST}.ContextMenuCall" >/dev/null ;; "count") [ $# -eq 1 ] || [ "${2}" = "displayed" ] || [ "${2}" = "history" ] || [ "${2}" = "waiting" ] \ || die "Please give either 'displayed', 'history', 'waiting' or none as count parameter." if [ $# -eq 1 ]; then property_get waitingLength | ( read -r _ _ waiting; printf " Waiting: %s\n" "${waiting}" ) property_get displayedLength | ( read -r _ _ displayed; printf " Currently displayed: %s\n" "${displayed}" ) property_get historyLength | ( read -r _ _ history; printf " History: %s\n" "${history}") else property_get ${2}Length | ( read -r _ _ notifications; printf "%s\n" "${notifications}"; ) fi ;; "history-pop") method_call "${DBUS_IFAC_DUNST}.NotificationShow" >/dev/null ;; "is-paused") property_get paused | ( read -r _ _ paused; printf "%s\n" "${paused}"; ) ;; "set-paused") [ "${2:-}" ] \ || die "No status parameter specified. Please give either 'true', 'false' or 'toggle' as paused parameter." [ "${2}" = "true" ] || [ "${2}" = "false" ] || [ "${2}" = "toggle" ] \ || die "Please give either 'true', 'false' or 'toggle' as paused parameter." if [ "${2}" = "toggle" ]; then paused=$(property_get paused | ( read -r _ _ paused; printf "%s\n" "${paused}"; )) if [ "${paused}" = "true" ]; then property_set paused variant:boolean:false else property_set paused variant:boolean:true fi else property_set paused variant:boolean:"$2" fi ;; "help"|"--help"|"-h") show_help ;; "debug") dbus-send --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_FDN}.GetServerInformation" >/dev/null 2>/dev/null \ || die "Dunst is not running." dbus-send --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_FDN}.GetServerInformation" \ | ( read -r name _ version _ [ "${name}" = "dunst" ] printf "dunst version: %s\n" "${version}" ) \ || die "Another notification manager is running. It's not dunst" dbus-send --print-reply=literal --dest="${DBUS_NAME}" "${DBUS_PATH}" "${DBUS_IFAC_DUNST}.Ping" >/dev/null 2>/dev/null \ || die "Dunst controlling interface not available. Is the version too old?" ;; "") die "dunstctl: No command specified. Please consult the usage." ;; *) die "dunstctl: unrecognized command '${1:-}'. Please consult the usage." ;; esac