let's do ugly versioning in my playground
This commit is contained in:
commit
70de7c4491
|
@ -0,0 +1,2 @@
|
||||||
|
/*~
|
||||||
|
/.direnv/
|
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1710146030,
|
||||||
|
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1719597372,
|
||||||
|
"narHash": "sha256-SpZKwy6sjgH00xiYmfjVAX+JaNkPQ2Q/BrEhNtWJvH4=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "dd66e39ec4c7252fab7e6f8fd57b5ab2a3c7d63c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
description = "common lisp dbus playground";
|
||||||
|
inputs.nixpkgs.url = "github:nixos/nixpkgs";
|
||||||
|
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils }:
|
||||||
|
flake-utils.lib.eachDefaultSystem
|
||||||
|
(system:
|
||||||
|
let
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
# https://nixos.org/manual/nixpkgs/stable/#lisp-overriding-package-attributes
|
||||||
|
# getting version with automatic introspection mixin
|
||||||
|
dbus' = pkgs.sbcl.pkgs.dbus.overrideLispAttrs (oldAttrs: rec {
|
||||||
|
version = "1.4";
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "death";
|
||||||
|
repo = "dbus";
|
||||||
|
rev = "master";
|
||||||
|
hash = "sha256-xbg3tPYfRNGJo+9F/58w2bDeZqV33Z871+ClSg4ACPk=";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
sbcl' = pkgs.sbcl.withPackages (ps: [ ps.alexandria dbus' ]);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
buildInputs = [
|
||||||
|
sbcl'
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
# see https://serokell.io/blog/practical-nix-flakes
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
;;;; +----------------------------------------------------------------+
|
||||||
|
;;;; | DBUS |
|
||||||
|
;;;; +----------------------------------------------------------------+
|
||||||
|
(load (sb-ext:posix-getenv "ASDF"))
|
||||||
|
(asdf:load-system 'dbus)
|
||||||
|
(defpackage #:listening-response
|
||||||
|
(:use #:cl #:dbus)
|
||||||
|
(:export #:publish-example))
|
||||||
|
|
||||||
|
(in-package #:listening-response)
|
||||||
|
|
||||||
|
(define-dbus-object root
|
||||||
|
(:path "/"))
|
||||||
|
|
||||||
|
(define-dbus-signal-handler (root response) ()
|
||||||
|
(:interface "org.freedesktop.portal.Request")
|
||||||
|
(format t "Got signal with arg ~S~%" "yup")
|
||||||
|
(force-output))
|
||||||
|
|
||||||
|
(defun listen-for-responses ()
|
||||||
|
(handler-case
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(format t "Bus connection name: ~A~%" (bus-name bus))
|
||||||
|
(dbus:add-match bus :type :signal :interface "org.freedesktop.portal.Request")
|
||||||
|
(publish-objects bus))
|
||||||
|
(end-of-file ()
|
||||||
|
:disconnected-by-bus))) ; org.freedesktop.portal.Request
|
||||||
|
;; yep, works with
|
||||||
|
;; dbus-send --session --type=signal / org.freedesktop.portal.Request.Response
|
||||||
|
;; again, will need to register object on the expected response path
|
|
@ -0,0 +1,119 @@
|
||||||
|
(load (sb-ext:posix-getenv "ASDF"))
|
||||||
|
(asdf:load-system 'dbus)
|
||||||
|
|
||||||
|
(defpackage #:screencasting (:use #:cl))
|
||||||
|
(in-package #:screencasting)
|
||||||
|
|
||||||
|
;; https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.ScreenCast.html
|
||||||
|
(defconstant +screen-cast-interface+ "org.freedesktop.portal.ScreenCast")
|
||||||
|
(defconstant +request-interface+ "org.freedesktop.portal.ScreenCast")
|
||||||
|
|
||||||
|
;; i'm not sure how to do interactive calls,
|
||||||
|
;; since maybe i need to "publish objects"
|
||||||
|
;; and that means the callbacks are set in stone?
|
||||||
|
;; i guess i could try to do a Notification call in the callback on screenshot request?
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(with-introspected-object (notification bus "/org/freedesktop/Notifications" "org.freedesktop.Notifications")
|
||||||
|
(notification "org.freedesktop.Notifications" "Notify"
|
||||||
|
"Test" 0 "" "Test" "This is a test; I repeat, this is a test." '() '() -1)
|
||||||
|
))
|
||||||
|
|
||||||
|
(defun send-notification (bus message)
|
||||||
|
(dbus:with-introspected-object (notification bus "/org/freedesktop/Notifications" "org.freedesktop.Notifications")
|
||||||
|
(notification "org.freedesktop.Notifications" "Notify"
|
||||||
|
"Test" 0 "" "Test" (or message "This is a test; I repeat, this is a test.") '() '() -1)))
|
||||||
|
|
||||||
|
;; i guess i could pass both bus and
|
||||||
|
|
||||||
|
(defun call-screencast ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (dbus:session-server-addresses))
|
||||||
|
(let*
|
||||||
|
((requester-name (cl-ppcre:regex-replace "\\." (dbus:bus-name bus) "_" :start 1))
|
||||||
|
(request-name "yayay")
|
||||||
|
(resp-path (concatenate 'string "/org/freedesktop/portal/desktop/request/"
|
||||||
|
requester-name
|
||||||
|
"/"
|
||||||
|
request-name)))
|
||||||
|
(dbus:define-dbus-object request-object
|
||||||
|
(:path resp-path))
|
||||||
|
|
||||||
|
(dbus:define-dbus-signal-handler (request-object response) ((id :uint32) (results (:ARRAY (:DICT-ENTRY :STRING :VARIANT))))
|
||||||
|
(:interface +request-interface+)
|
||||||
|
(format t "Got response ~S with results ~S~%" id results)
|
||||||
|
(send-notification bus "yayaya from the first response"))
|
||||||
|
|
||||||
|
(format T "Will try to listen on ~A~%" resp-path)
|
||||||
|
(format T "Bus connection name ~A~%" (dbus:bus-name bus))
|
||||||
|
(dbus:add-match bus :type :signal
|
||||||
|
:interface "org.freedesktop.portal.Request")
|
||||||
|
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
|
||||||
|
(desktop +screen-cast-interface+ "CreateSession"
|
||||||
|
'(("handle_token" ((:string) "yayay"))
|
||||||
|
("session_handle_token" ((:string) "hohoyyy")))))
|
||||||
|
(dbus:publish-objects bus)))
|
||||||
|
(end-of-file ()
|
||||||
|
:disconnected-by-bus)))
|
||||||
|
|
||||||
|
;; let's then try to move macroses that define 'request' to outside?
|
||||||
|
;; they would take bus, create expected request-response listener
|
||||||
|
|
||||||
|
(alexandria:with-gensyms (lala)
|
||||||
|
(format nil "i-got-gensym-~S" lala))
|
||||||
|
|
||||||
|
;; well this notification library has interactive "register callback"
|
||||||
|
;; for multiple callbacks on Notification signals
|
||||||
|
;; https://github.com/Lautaro-Garcia/cl-notify/blob/main/src/signals.lisp
|
||||||
|
;; basicly loop starts and one signal-handler that calls all currently registered
|
||||||
|
;; i guess for my case i'll want separate with-open-bus?
|
||||||
|
;; how would i then exit the publish-objects loop?
|
||||||
|
;; am i really expected to exit it?
|
||||||
|
;; alright, let's try to start publish objects and after that registering stuff
|
||||||
|
;; to do the call?
|
||||||
|
(defun do-request (bus)
|
||||||
|
(let*
|
||||||
|
((requester-name (cl-ppcre:regex-replace "\\." (dbus:bus-name bus) "_" :start 1))
|
||||||
|
(request-name "yayay")
|
||||||
|
(resp-path (concatenate 'string "/org/freedesktop/portal/desktop/request/"
|
||||||
|
requester-name
|
||||||
|
"/"
|
||||||
|
request-name)))
|
||||||
|
(dbus:define-dbus-object request-object
|
||||||
|
(:path resp-path))
|
||||||
|
(dbus:define-dbus-signal-handler (request-object response) ((id :uint32) (results (:ARRAY (:DICT-ENTRY :STRING :VARIANT))))
|
||||||
|
(:interface "org.freedesktop.portal.Request")
|
||||||
|
(format t "Got response ~A with results ~A~%" id results)
|
||||||
|
(send-notification bus "yayaya from the first response"))
|
||||||
|
(format T "Will try to make a call for ~A~%" resp-path)
|
||||||
|
(format T "Bus connection name ~A~%" (dbus:bus-name bus))
|
||||||
|
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
|
||||||
|
(desktop "org.freedesktop.portal.Screenshot" "Screenshot"
|
||||||
|
""
|
||||||
|
'(("handle_token" ((:string) "yayay")))))
|
||||||
|
(dbus:add-match bus :type :signal
|
||||||
|
:interface "org.freedesktop.portal.Request")
|
||||||
|
(dbus:publish-objects bus)))
|
||||||
|
|
||||||
|
(defvar *running-bus*)
|
||||||
|
(do-request *running-bus*)
|
||||||
|
|
||||||
|
(defun run-bus ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (dbus:session-server-addresses))
|
||||||
|
(format T "Bus connection name ~A~%" (dbus:bus-name bus))
|
||||||
|
(setq *running-bus* bus)
|
||||||
|
(dbus:publish-objects bus))
|
||||||
|
(end-of-file ()
|
||||||
|
:disconnected-by-bus)))
|
||||||
|
|
||||||
|
;; well, i suppose i would need to open multiple connections?
|
||||||
|
;; let's do something like this https://github.com/Lautaro-Garcia/cl-notify/blob/main/src/dbus-protocol.lisp#L27
|
||||||
|
;; (defmacro with-dbus-method-inovaction ((result-var method &rest args) &body body)
|
||||||
|
;; (alexandria:with-gensyms (bus notifications-object)
|
||||||
|
;; `(dbus:with-open-bus (,bus (dbus:session-server-addresses))
|
||||||
|
;; (dbus:with-introspected-object (,notifications-object ,bus "/org/freedesktop/Notifications" "org.freedesktop.Notifications")
|
||||||
|
;; (let ((,result-var (,notifications-object "org.freedesktop.Notifications" ,method ,@args)))
|
||||||
|
;; ,@body)))))
|
||||||
|
|
||||||
|
;; but. this supposes result-var being a resulting value
|
||||||
|
;; and i'd want to what? pass in a callback to register?
|
|
@ -0,0 +1,377 @@
|
||||||
|
(load (sb-ext:posix-getenv "ASDF"))
|
||||||
|
(asdf:load-system 'dbus)
|
||||||
|
|
||||||
|
(defpackage #:screenshotting (:use #:cl))
|
||||||
|
(in-package #:screenshotting)
|
||||||
|
|
||||||
|
;; let's try to initiate and get screenshot somehow
|
||||||
|
;; #<DBUS/INTROSPECT::INTERFACE "org.freedesktop.portal.Screenshot">
|
||||||
|
|
||||||
|
(iolib/multiplex:with-event-base (event-base)
|
||||||
|
(dbus:with-open-connection (connection event-base (dbus:session-server-addresses))
|
||||||
|
(dbus:authenticate (dbus:supported-authentication-mechanisms connection) connection)
|
||||||
|
(dbus:hello connection)
|
||||||
|
(let ((obj (dbus:make-object-from-introspection connection "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")))
|
||||||
|
(dbus:list-interface-methods (dbus:object-interface "org.freedesktop.portal.Screenshot" obj)))))
|
||||||
|
|
||||||
|
(defun start ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (dbus:session-server-addresses))
|
||||||
|
(format T "Bus connection name ~A~%" (dbus:bus-name bus)))
|
||||||
|
(end-of-file ()
|
||||||
|
:disconnected-by-bus)))
|
||||||
|
|
||||||
|
;; https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Screenshot.html
|
||||||
|
;; Since version 0.9 of xdg-desktop-portal, the handle will be of the form
|
||||||
|
;;/org/freedesktop/portal/desktop/request/SENDER/TOKEN
|
||||||
|
;; so for me it would be (dbus:bus-name bus) and "param-i-ve-passed"
|
||||||
|
|
||||||
|
;; a question aboud argument with vararg array
|
||||||
|
;; https://github.com/death/dbus/issues/20
|
||||||
|
|
||||||
|
(defun call-screenshot ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (dbus:session-server-addresses))
|
||||||
|
(format T "Bus connection name ~A~%" (dbus:bus-name bus))
|
||||||
|
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
|
||||||
|
(desktop "org.freedesktop.portal.Screenshot" "Screenshot"
|
||||||
|
""
|
||||||
|
'(("handle_token" ((:string) "yayay")))))
|
||||||
|
(dbus:add-match bus :type :signal
|
||||||
|
:interface "org.freedesktop.portal.Request"
|
||||||
|
:destination (dbus:bus-name bus))
|
||||||
|
(DBUS:publish-objects bus))))
|
||||||
|
|
||||||
|
;; checking params for signal with
|
||||||
|
;; (dbus:sigexp "ua{sv}")
|
||||||
|
;; as string from here https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Request.html#request
|
||||||
|
|
||||||
|
;; wowy, i get the link with my handle
|
||||||
|
;; "/org/freedesktop/portal/desktop/request/1_87/yayay"
|
||||||
|
;; and now the result should be signalled on the Reply object at that path
|
||||||
|
|
||||||
|
;; lot's of stuff in dbus-monitor:
|
||||||
|
;; method call time=1719909623.911588 sender=:1.89 -> destination=org.freedesktop.portal.Desktop serial=3 path=/org/freedesktop/portal/desktop; interface=org.freedesktop.portal.Screenshot; member=Screenshot
|
||||||
|
;; string ""
|
||||||
|
;; array [
|
||||||
|
;; dict entry(
|
||||||
|
;; string "handle_token"
|
||||||
|
;; variant string "yayay"
|
||||||
|
;; )
|
||||||
|
;; ]
|
||||||
|
;; method call time=1719909623.911612 sender=:1.23 -> destination=org.freedesktop.DBus serial=212 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=GetConnectionUnixProcessID
|
||||||
|
;; string ":1.89"
|
||||||
|
;; method return time=1719909623.911618 sender=org.freedesktop.DBus -> destination=:1.23 serial=152 reply_serial=212
|
||||||
|
;; uint32 93638
|
||||||
|
;; method call time=1719909623.911624 sender=:1.23 -> destination=org.freedesktop.DBus serial=213 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
|
||||||
|
;; string "type='signal',sender='org.freedesktop.impl.portal.desktop.gnome',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='/org/freedesktop/portal/desktop/request/1_89/yayay',arg0='org.freedesktop.impl.portal.Request'"
|
||||||
|
;; method return time=1719909623.911631 sender=org.freedesktop.DBus -> destination=:1.23 serial=153 reply_serial=213
|
||||||
|
;; method call time=1719909623.911635 sender=:1.23 -> destination=org.freedesktop.DBus serial=214 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
|
||||||
|
;; string "type='signal',sender='org.freedesktop.impl.portal.desktop.gnome',interface='org.freedesktop.impl.portal.Request',path='/org/freedesktop/portal/desktop/request/1_89/yayay'"
|
||||||
|
;; method return time=1719909623.911641 sender=org.freedesktop.DBus -> destination=:1.23 serial=154 reply_serial=214
|
||||||
|
;; method call time=1719909623.911644 sender=:1.23 -> destination=org.freedesktop.DBus serial=215 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=StartServiceByName
|
||||||
|
;; string "org.freedesktop.impl.portal.desktop.gnome"
|
||||||
|
;; uint32 0
|
||||||
|
;; method return time=1719909623.911651 sender=org.freedesktop.DBus -> destination=:1.23 serial=155 reply_serial=215
|
||||||
|
;; uint32 2
|
||||||
|
;; method call time=1719909623.911657 sender=:1.23 -> destination=org.freedesktop.DBus serial=216 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=GetNameOwner
|
||||||
|
;; string "org.freedesktop.impl.portal.desktop.gnome"
|
||||||
|
;; method return time=1719909623.911662 sender=org.freedesktop.DBus -> destination=:1.23 serial=156 reply_serial=216
|
||||||
|
;; string ":1.28"
|
||||||
|
;; method call time=1719909623.911668 sender=:1.23 -> destination=:1.28 serial=217 path=/org/freedesktop/portal/desktop/request/1_89/yayay; interface=org.freedesktop.DBus.Properties; member=GetAll
|
||||||
|
;; string "org.freedesktop.impl.portal.Request"
|
||||||
|
;; error time=1719909623.911674 sender=:1.28 -> destination=:1.23 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=217
|
||||||
|
;; string "Object does not exist at path “/org/freedesktop/portal/desktop/request/1_89/yayay”"
|
||||||
|
;; method call time=1719909623.911680 sender=:1.23 -> destination=:1.28 serial=218 path=/org/freedesktop/portal/desktop; interface=org.freedesktop.impl.portal.Screenshot; member=Screenshot
|
||||||
|
;; object path "/org/freedesktop/portal/desktop/request/1_89/yayay"
|
||||||
|
;; string ""
|
||||||
|
;; string ""
|
||||||
|
;; array [
|
||||||
|
;; ]
|
||||||
|
;; method return time=1719909623.911693 sender=:1.23 -> destination=:1.89 serial=219 reply_serial=3
|
||||||
|
;; object path "/org/freedesktop/portal/desktop/request/1_89/yayay"
|
||||||
|
;; signal time=1719909623.911699 sender=org.freedesktop.DBus -> destination=:1.89 serial=5 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameLost
|
||||||
|
;; string ":1.89"
|
||||||
|
;; signal time=1719909623.911705 sender=org.freedesktop.DBus -> destination=(null destination) serial=123 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
|
||||||
|
;; string ":1.89"
|
||||||
|
;; string ":1.89"
|
||||||
|
;; string ""
|
||||||
|
;; method call time=1719909623.911714 sender=:1.23 -> destination=:1.28 serial=220 path=/org/freedesktop/portal/desktop/request/1_89/yayay; interface=org.freedesktop.impl.portal.Request; member=Close
|
||||||
|
;; error time=1719909623.911717 sender=:1.28 -> destination=:1.23 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=220
|
||||||
|
;; string "Object does not exist at path “/org/freedesktop/portal/desktop/request/1_89/yayay”"
|
||||||
|
|
||||||
|
;; does this mean that I should be the one creating the response object?
|
||||||
|
|
||||||
|
;; well, now maybe i will be able to figure out more in the flameshot repo
|
||||||
|
;; https://github.com/flameshot-org/flameshot/blob/c1dac52231024174faa68a29577129ebca125dff/src/utils/screengrabber.cpp#L59
|
||||||
|
|
||||||
|
;; or, well, the Claude writes that maybe connection is closed prematurely because nobody is listening?
|
||||||
|
|
||||||
|
(cl-ppcre:regex-replace "\\." ":1.241" "_" :start 1)
|
||||||
|
|
||||||
|
(defun call-screenshot ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (dbus:session-server-addresses))
|
||||||
|
(let*
|
||||||
|
((requester-name (cl-ppcre:regex-replace "\\." (dbus:bus-name bus) "_" :start 1))
|
||||||
|
(request-name "yayay")
|
||||||
|
(resp-path (concatenate 'string "/org/freedesktop/portal/desktop/request/"
|
||||||
|
requester-name
|
||||||
|
"/"
|
||||||
|
request-name)))
|
||||||
|
(dbus:define-dbus-object request-object
|
||||||
|
(:path resp-path))
|
||||||
|
(dbus:define-dbus-signal-handler (request-object response) ((id :uint32) (results (:ARRAY (:DICT-ENTRY :STRING :VARIANT))))
|
||||||
|
(:interface "org.freedesktop.portal.Request")
|
||||||
|
(format t "Got response ~A with results ~A~%" id results))
|
||||||
|
(format T "Will try to listen on ~A~%" resp-path)
|
||||||
|
(format T "Bus connection name ~A~%" (dbus:bus-name bus))
|
||||||
|
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
|
||||||
|
(desktop "org.freedesktop.portal.Screenshot" "Screenshot"
|
||||||
|
""
|
||||||
|
'(("handle_token" ((:string) "yayay")))))
|
||||||
|
(dbus:add-match bus :type :signal
|
||||||
|
:interface "org.freedesktop.portal.Request")
|
||||||
|
(dbus:publish-objects bus)))))
|
||||||
|
;; with new code inserted about listening on request.response
|
||||||
|
|
||||||
|
;; method call time=1720082195.600449 sender=:1.207 -> destination=org.freedesktop.portal.Desktop serial=3 path=/org/freedesktop/portal/desktop; interface=org.freedesktop.portal.Screenshot; member=Screenshot
|
||||||
|
;; string ""
|
||||||
|
;; array [
|
||||||
|
;; dict entry(
|
||||||
|
;; string "handle_token"
|
||||||
|
;; variant string "yayay"
|
||||||
|
;; )
|
||||||
|
;; ]
|
||||||
|
;; method call time=1720082195.600630 sender=:1.23 -> destination=org.freedesktop.DBus serial=1869 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=GetConnectionUnixProcessID
|
||||||
|
;; string ":1.207"
|
||||||
|
;; method return time=1720082195.600635 sender=org.freedesktop.DBus -> destination=:1.23 serial=212 reply_serial=1869
|
||||||
|
;; uint32 93638
|
||||||
|
;; method call time=1720082195.600871 sender=:1.23 -> destination=org.freedesktop.DBus serial=1870 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
|
||||||
|
;; string "type='signal',sender='org.freedesktop.impl.portal.desktop.gnome',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='/org/freedesktop/portal/desktop/request/1_207/yayay',arg0='org.freedesktop.impl.portal.Request'"
|
||||||
|
;; method return time=1720082195.600875 sender=org.freedesktop.DBus -> destination=:1.23 serial=213 reply_serial=1870
|
||||||
|
;; method call time=1720082195.600883 sender=:1.23 -> destination=org.freedesktop.DBus serial=1871 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
|
||||||
|
;; string "type='signal',sender='org.freedesktop.impl.portal.desktop.gnome',interface='org.freedesktop.impl.portal.Request',path='/org/freedesktop/portal/desktop/request/1_207/yayay'"
|
||||||
|
;; method return time=1720082195.600887 sender=org.freedesktop.DBus -> destination=:1.23 serial=214 reply_serial=1871
|
||||||
|
;; method call time=1720082195.600902 sender=:1.23 -> destination=org.freedesktop.DBus serial=1872 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=StartServiceByName
|
||||||
|
;; string "org.freedesktop.impl.portal.desktop.gnome"
|
||||||
|
;; uint32 0
|
||||||
|
;; method return time=1720082195.600907 sender=org.freedesktop.DBus -> destination=:1.23 serial=215 reply_serial=1872
|
||||||
|
;; uint32 2
|
||||||
|
;; method call time=1720082195.600959 sender=:1.23 -> destination=org.freedesktop.DBus serial=1873 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=GetNameOwner
|
||||||
|
;; string "org.freedesktop.impl.portal.desktop.gnome"
|
||||||
|
;; method return time=1720082195.600963 sender=org.freedesktop.DBus -> destination=:1.23 serial=216 reply_serial=1873
|
||||||
|
;; string ":1.28"
|
||||||
|
;; method call time=1720082195.601013 sender=:1.23 -> destination=:1.28 serial=1874 path=/org/freedesktop/portal/desktop/request/1_207/yayay; interface=org.freedesktop.DBus.Properties; member=GetAll
|
||||||
|
;; string "org.freedesktop.impl.portal.Request"
|
||||||
|
;; error time=1720082195.601138 sender=:1.28 -> destination=:1.23 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=1874
|
||||||
|
;; string "Object does not exist at path “/org/freedesktop/portal/desktop/request/1_207/yayay”"
|
||||||
|
;; method call time=1720082195.601215 sender=:1.23 -> destination=:1.28 serial=1875 path=/org/freedesktop/portal/desktop; interface=org.freedesktop.impl.portal.Screenshot; member=Screenshot
|
||||||
|
;; object path "/org/freedesktop/portal/desktop/request/1_207/yayay"
|
||||||
|
;; string ""
|
||||||
|
;; string ""
|
||||||
|
;; array [
|
||||||
|
;; ]
|
||||||
|
;; method return time=1720082195.601235 sender=:1.23 -> destination=:1.207 serial=1876 reply_serial=3
|
||||||
|
;; object path "/org/freedesktop/portal/desktop/request/1_207/yayay"
|
||||||
|
;; method call time=1720082195.601435 sender=:1.207 -> destination=org.freedesktop.DBus serial=4 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
|
||||||
|
;; string "type=signal,interface=org.freedesktop.portal.Request,destination=:1.207"
|
||||||
|
;; method return time=1720082195.604833 sender=org.freedesktop.DBus -> destination=:1.207 serial=3 reply_serial=4
|
||||||
|
;; signal time=1720082198.479133 sender=:1.192 -> destination=(null destination) serial=221 path=/org/gnome/Terminal/window/2; interface=org.gtk.Actions; member=Changed
|
||||||
|
;; array [
|
||||||
|
;; ]
|
||||||
|
;; array [
|
||||||
|
;; dict entry(
|
||||||
|
;; string "copy"
|
||||||
|
;; boolean true
|
||||||
|
;; )
|
||||||
|
;; ]
|
||||||
|
;; array [
|
||||||
|
;; ]
|
||||||
|
;; array [
|
||||||
|
;; ]
|
||||||
|
|
||||||
|
;; trying suggestion on not creating an object ourselves?
|
||||||
|
(defun call-screenshot-register-request ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (dbus:session-server-addresses))
|
||||||
|
(let*
|
||||||
|
((bus-name (dbus:bus-name bus))
|
||||||
|
(request-name "yayay"))
|
||||||
|
(dbus:define-dbus-object root-object
|
||||||
|
(:path "/"))
|
||||||
|
(dbus:define-dbus-signal-handler
|
||||||
|
(root-object response)
|
||||||
|
((id :uint32) (results (:ARRAY (:DICT-ENTRY :STRING :VARIANT))))
|
||||||
|
(:interface "org.freedesktop.portal.Request")
|
||||||
|
(format t "Got response ~A with results ~A~%" id results))
|
||||||
|
(format T "Bus connection name ~A~%" (dbus:bus-name bus))
|
||||||
|
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
|
||||||
|
(desktop "org.freedesktop.portal.Screenshot" "Screenshot"
|
||||||
|
""
|
||||||
|
'(("handle_token" ((:string) "yayay")))))
|
||||||
|
(dbus:add-match bus :type :signal
|
||||||
|
:interface "org.freedesktop.portal.Request")
|
||||||
|
(dbus:publish-objects bus)))))
|
||||||
|
|
||||||
|
;; method call time=1720270194.734644 sender=:1.95 -> destination=org.freedesktop.portal.Desktop serial=3 path=/org/freedesktop/portal/desktop; interface=org.freedesktop.portal.Screenshot; member=Screenshot
|
||||||
|
;; string ""
|
||||||
|
;; array [
|
||||||
|
;; dict entry(
|
||||||
|
;; string "handle_token"
|
||||||
|
;; variant string "yayay"
|
||||||
|
;; )
|
||||||
|
;; ]
|
||||||
|
;; method call time=1720270194.734664 sender=:1.25 -> destination=org.freedesktop.DBus serial=239 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=GetConnectionUnixProcessID
|
||||||
|
;; string ":1.95"
|
||||||
|
;; method return time=1720270194.734669 sender=org.freedesktop.DBus -> destination=:1.25 serial=169 reply_serial=239
|
||||||
|
;; uint32 94649
|
||||||
|
;; method call time=1720270194.734674 sender=:1.25 -> destination=org.freedesktop.DBus serial=240 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
|
||||||
|
;; string "type='signal',sender='org.freedesktop.impl.portal.desktop.gnome',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='/org/freedesktop/portal/desktop/request/1_95/yayay',arg0='org.freedesktop.impl.portal.Request'"
|
||||||
|
;; method return time=1720270194.734679 sender=org.freedesktop.DBus -> destination=:1.25 serial=170 reply_serial=240
|
||||||
|
;; method call time=1720270194.734682 sender=:1.25 -> destination=org.freedesktop.DBus serial=241 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
|
||||||
|
;; string "type='signal',sender='org.freedesktop.impl.portal.desktop.gnome',interface='org.freedesktop.impl.portal.Request',path='/org/freedesktop/portal/desktop/request/1_95/yayay'"
|
||||||
|
;; method return time=1720270194.734688 sender=org.freedesktop.DBus -> destination=:1.25 serial=171 reply_serial=241
|
||||||
|
;; method call time=1720270194.734691 sender=:1.25 -> destination=org.freedesktop.DBus serial=242 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=StartServiceByName
|
||||||
|
;; string "org.freedesktop.impl.portal.desktop.gnome"
|
||||||
|
;; uint32 0
|
||||||
|
;; method return time=1720270194.734698 sender=org.freedesktop.DBus -> destination=:1.25 serial=172 reply_serial=242
|
||||||
|
;; uint32 2
|
||||||
|
;; method call time=1720270194.734702 sender=:1.25 -> destination=org.freedesktop.DBus serial=243 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=GetNameOwner
|
||||||
|
;; string "org.freedesktop.impl.portal.desktop.gnome"
|
||||||
|
;; method return time=1720270194.734707 sender=org.freedesktop.DBus -> destination=:1.25 serial=173 reply_serial=243
|
||||||
|
;; string ":1.30"
|
||||||
|
;; method call time=1720270194.734712 sender=:1.25 -> destination=:1.30 serial=244 path=/org/freedesktop/portal/desktop/request/1_95/yayay; interface=org.freedesktop.DBus.Properties; member=GetAll
|
||||||
|
;; string "org.freedesktop.impl.portal.Request"
|
||||||
|
;; error time=1720270194.734718 sender=:1.30 -> destination=:1.25 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=244
|
||||||
|
;; string "Object does not exist at path “/org/freedesktop/portal/desktop/request/1_95/yayay”"
|
||||||
|
;; method call time=1720270194.734723 sender=:1.25 -> destination=:1.30 serial=245 path=/org/freedesktop/portal/desktop; interface=org.freedesktop.impl.portal.Screenshot; member=Screenshot
|
||||||
|
;; object path "/org/freedesktop/portal/desktop/request/1_95/yayay"
|
||||||
|
;; string ""
|
||||||
|
;; string ""
|
||||||
|
;; array [
|
||||||
|
;; ]
|
||||||
|
;; method return time=1720270194.734736 sender=:1.25 -> destination=:1.95 serial=246 reply_serial=3
|
||||||
|
;; object path "/org/freedesktop/portal/desktop/request/1_95/yayay"
|
||||||
|
;; method call time=1720270194.734741 sender=:1.95 -> destination=org.freedesktop.DBus serial=4 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=AddMatch
|
||||||
|
;; string "type=signal,interface=org.freedesktop.portal.Request"
|
||||||
|
;; method return time=1720270194.754781 sender=org.freedesktop.DBus -> destination=:1.95 serial=3 reply_serial=4
|
||||||
|
|
||||||
|
;; well, it seems that still same Object does not exist
|
||||||
|
;; so. oh. it's 1_95, so what.
|
||||||
|
;; i'm not subscribing to same thing, right?
|
||||||
|
;; let's try to chagne in place
|
||||||
|
;; um. what. what if i manually send to Request sinal?
|
||||||
|
|
||||||
|
|
||||||
|
;; and these changes they are messy, would be better to use commits
|
||||||
|
|
||||||
|
(defun call-screenshot ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (dbus:session-server-addresses))
|
||||||
|
(let*
|
||||||
|
((requester-name (cl-ppcre:regex-replace "\\." (dbus:bus-name bus) "_" :start 1))
|
||||||
|
(request-name "yayay")
|
||||||
|
(resp-path (concatenate 'string "/org/freedesktop/portal/desktop/request/"
|
||||||
|
requester-name
|
||||||
|
"/"
|
||||||
|
request-name)))
|
||||||
|
(dbus:define-dbus-object request-object
|
||||||
|
(:path resp-path))
|
||||||
|
(dbus:define-dbus-signal-handler (request-object response) ((id :uint32) (results (:ARRAY (:DICT-ENTRY :STRING :VARIANT))))
|
||||||
|
(:interface "org.freedesktop.portal.Request")
|
||||||
|
(format t "Got response ~A with results ~A~%" id results))
|
||||||
|
(format T "Will try to listen on ~A~%" resp-path)
|
||||||
|
(format T "Bus connection name ~A~%" (dbus:bus-name bus))
|
||||||
|
;; (dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
|
||||||
|
;; (desktop "org.freedesktop.portal.Screenshot" "Screenshot"
|
||||||
|
;; ""
|
||||||
|
;; '(("handle_token" ((:string) "yayay")))))
|
||||||
|
(dbus:add-match bus :type :signal
|
||||||
|
:interface "org.freedesktop.portal.Request")
|
||||||
|
(dbus:publish-objects bus)))))
|
||||||
|
|
||||||
|
;; ok, dbus-send can't add a{sv} because dict:string:variant is not allowed
|
||||||
|
;; variant is a container and nesting is not supported by the tool
|
||||||
|
;; let's try again on the real method call?
|
||||||
|
(defun call-screenshot ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (dbus:session-server-addresses))
|
||||||
|
(let*
|
||||||
|
((requester-name (cl-ppcre:regex-replace "\\." (dbus:bus-name bus) "_" :start 1))
|
||||||
|
(request-name "yayay")
|
||||||
|
(resp-path (concatenate 'string "/org/freedesktop/portal/desktop/request/"
|
||||||
|
requester-name
|
||||||
|
"/"
|
||||||
|
request-name)))
|
||||||
|
(dbus:define-dbus-object request-object
|
||||||
|
(:path resp-path))
|
||||||
|
(dbus:define-dbus-signal-handler (request-object response) ((id :uint32) (results (:ARRAY (:DICT-ENTRY :STRING :VARIANT))))
|
||||||
|
(:interface "org.freedesktop.portal.Request")
|
||||||
|
(format t "Got response ~A with results ~A~%" id results))
|
||||||
|
(format T "Will try to listen on ~A~%" resp-path)
|
||||||
|
(format T "Bus connection name ~A~%" (dbus:bus-name bus))
|
||||||
|
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
|
||||||
|
(desktop "org.freedesktop.portal.Screenshot" "Screenshot"
|
||||||
|
""
|
||||||
|
'(("handle_token" ((:string) "yayay")))))
|
||||||
|
(dbus:add-match bus :type :signal
|
||||||
|
:interface "org.freedesktop.portal.Request")
|
||||||
|
(dbus:publish-objects bus)))))
|
||||||
|
|
||||||
|
|
||||||
|
;;; uhm, let's try another method that should more certainly work
|
||||||
|
;; gdbus call --session --dest org.freedesktop.portal.Desktop --object-path /org/freedesktop/portal/desktop --method org.freedesktop.portal.FileChooser.OpenFile "" "Choose a file" '{}'
|
||||||
|
|
||||||
|
;; and when trying with a screenshot
|
||||||
|
;; $ gdbus call --session --dest org.freedesktop.portal.Desktop --object-path /org/freedesktop/portal/desktop --method org.freedesktop.portal.Screenshot.Screenshot "" '{}'
|
||||||
|
;; this returns the path
|
||||||
|
|
||||||
|
;; wow
|
||||||
|
;; this has info
|
||||||
|
;; systemctl --user status xdg-desktop-portal-gnome.service
|
||||||
|
;; Jul 06 15:14:28 LLF33A87M xdg-desktop-portal-gnome[3770]: Failed to get screenshot: Cannot invoke method; proxy is for the well-known name org.gnome.Shell.Screenshot without an owner, and proxy was constructed with the G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START flag
|
||||||
|
|
||||||
|
|
||||||
|
;; and. if i want to be able to get screenshots i'll need another backend
|
||||||
|
;; https://wiki.archlinux.org/title/XDG_Desktop_Portal
|
||||||
|
;; so. not on xmonad or pure X11
|
||||||
|
;; i could try wayland and another tiling manager, you know
|
||||||
|
;; but i guess first restart into gnome session and try to call gdbus from there
|
||||||
|
;; List of backends and interfaces
|
||||||
|
|
||||||
|
;; The following table lists all backends available and their support for certain common interfaces.
|
||||||
|
;; Backend File chooser Screenshot and screen cast
|
||||||
|
;; xdg-desktop-portal-dde Yes Yes, on Deepin Desktop Environment
|
||||||
|
;; xdg-desktop-portal-gtk Yes No
|
||||||
|
;; xdg-desktop-portal-gnome Yes Yes, on GNOME
|
||||||
|
;; xdg-desktop-portal-kde Yes Yes, on KDE
|
||||||
|
;; xdg-desktop-portal-hyprland1 No Yes, on wlroots
|
||||||
|
;; xdg-desktop-portal-lxqt Yes No
|
||||||
|
;; xdg-desktop-portal-wlr No Yes, on wlroots
|
||||||
|
;; xdg-desktop-portal-xapp No Yes, on Cinnamon
|
||||||
|
;; xdg-desktop-portal-liri-gitAUR Yes Yes, on Liri
|
||||||
|
;; xdg-desktop-portal-shanaAUR Yes2 No
|
||||||
|
;; xdg-desktop-portal-tdAUR Yes No
|
||||||
|
;; xdg-desktop-portal-termfilechooser-gitAUR Yes3 No
|
||||||
|
|
||||||
|
;; yep, looks like this does work on gnome, so, yeah.
|
||||||
|
;; well, let's try another window manager? one on wlroots maybe just hyprland
|
||||||
|
;; or qtile which should also use wlroots, but do i need this hackability?
|
||||||
|
;; i don't think i'm using it for much, so hyprland?
|
||||||
|
;; because i don't even really want to use python for hacking
|
||||||
|
|
||||||
|
;; or, alternatively i guess i could try to install on Ubuntu
|
||||||
|
;; yeah, seems huh. will probably not launch through just home-manager?
|
||||||
|
;; or maybe it exactly will, just pull it's own wayland and stuff
|
||||||
|
;; https://github.com/nix-community/home-manager/issues/1167 maybe things won't work
|
||||||
|
|
||||||
|
;; i tried to install sway just on ubuntu
|
||||||
|
;; and thing works somewhat, but screenshots are blocked
|
||||||
|
;; not sure what to do about that.
|
||||||
|
;; i could continue working on gnome for now
|
||||||
|
|
||||||
|
;; OH, whoah. this faq https://github.com/emersion/xdg-desktop-portal-wlr
|
||||||
|
;; has link to python3 snippet
|
||||||
|
;; https://gitlab.gnome.org/-/snippets/19
|
||||||
|
;; and that starts the screen cast!
|
|
@ -0,0 +1,31 @@
|
||||||
|
(defpackage #:notification-example
|
||||||
|
(:use #:cl #:dbus)
|
||||||
|
(:export #:listen-for-notifications))
|
||||||
|
(in-package #:notification-example)
|
||||||
|
(define-dbus-object root-object
|
||||||
|
(:path "/"))
|
||||||
|
|
||||||
|
(define-dbus-signal-handler (root-object on-notification-closed) ((id :uint32) (reason :uint32))
|
||||||
|
(:interface "org.freedesktop.Notifications")
|
||||||
|
(:name "NotificationClosed")
|
||||||
|
(format t "Notification ~A closed for reason ~A~%" id reason))
|
||||||
|
|
||||||
|
(define-dbus-signal-handler (root-object on-action-invoked) ((id :uint32) (action-key :string))
|
||||||
|
(:interface "org.freedesktop.Notifications")
|
||||||
|
(:name "ActionInvoked")
|
||||||
|
(format t "Action ~A invoked on notification ~A~%" action-key id))
|
||||||
|
|
||||||
|
(defun listen-for-notifications ()
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(format t "Bus connection name: ~A~%" (bus-name bus))
|
||||||
|
(add-match bus :type :signal
|
||||||
|
:interface "org.freedesktop.Notifications"
|
||||||
|
:member "NotificationClosed")
|
||||||
|
(add-match bus :type :signal
|
||||||
|
:interface "org.freedesktop.Notifications"
|
||||||
|
:member "ActionInvoked")
|
||||||
|
(publish-objects bus)
|
||||||
|
(format t "Listening for notification signals...~%")
|
||||||
|
(loop (sleep 1)
|
||||||
|
(format t ".")
|
||||||
|
(force-output))))
|
|
@ -0,0 +1,33 @@
|
||||||
|
* [2024-06-28 Fri]
|
||||||
|
** well, i'm setting up sbcl and sly?
|
||||||
|
because i imagine using Common Lisp for my attempt at building screen
|
||||||
|
sharing for the XR glasses
|
||||||
|
|
||||||
|
for the cool runtime access, right?
|
||||||
|
** well, just flake shell and (use-package sly) is enough
|
||||||
|
for .lisp files to get stuff
|
||||||
|
|
||||||
|
yes, i'm still using C-M-f and stuff to move around sexps but things are fine
|
||||||
|
|
||||||
|
so, what's next?
|
||||||
|
well, this is nice high level description
|
||||||
|
dbus
|
||||||
|
https://www.freedesktop.org/wiki/Software/dbus/
|
||||||
|
|
||||||
|
and here's something to start usage
|
||||||
|
https://blog.macrolet.net/posts/DBus-and-PolicyKit-from-Common-Lisp.html
|
||||||
|
from https://github.com/death/dbus
|
||||||
|
|
||||||
|
and even lots of examples, but i think i will need a big book on Common Lisp to learn new things?
|
||||||
|
* [2024-06-29 Sat]
|
||||||
|
** going through the dbus guide, sounds neat
|
||||||
|
https://develop.kde.org/docs/features/d-bus/introduction_to_dbus/
|
||||||
|
|
||||||
|
that qdbus and qdbus-viewer are in
|
||||||
|
#+begin_src bash
|
||||||
|
$ nix shell nixpkgs#kdePackages.qttools
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** now let's read about calling methods
|
||||||
|
|
||||||
|
* the receiving of the signals
|
|
@ -0,0 +1,50 @@
|
||||||
|
;;;; +----------------------------------------------------------------+
|
||||||
|
;;;; | DBUS |
|
||||||
|
;;;; +----------------------------------------------------------------+
|
||||||
|
(load (sb-ext:posix-getenv "ASDF"))
|
||||||
|
(asdf:load-system 'dbus)
|
||||||
|
(defpackage #:publish-example
|
||||||
|
(:use #:cl #:dbus)
|
||||||
|
(:export #:publish-example))
|
||||||
|
|
||||||
|
(in-package #:publish-example)
|
||||||
|
|
||||||
|
(define-dbus-object root
|
||||||
|
(:path "/"))
|
||||||
|
|
||||||
|
(define-dbus-object my-service
|
||||||
|
(:path "/org/adeht/MyService")
|
||||||
|
(:parent root))
|
||||||
|
|
||||||
|
(define-dbus-method (my-service my-method) ((s1 :string) (s2 :string)) (:string)
|
||||||
|
(:interface "org.adeht.MyService")
|
||||||
|
(format t "will process call for ~S and ~S~%" s1 s2)
|
||||||
|
(force-output)
|
||||||
|
(concatenate 'string "updated" s1 s2))
|
||||||
|
|
||||||
|
(define-dbus-signal-handler (my-service on-signal) ()
|
||||||
|
(:interface "org.adeht.MyService")
|
||||||
|
(format t "Got signal with arg ~S~%" "hoh")
|
||||||
|
(force-output))
|
||||||
|
|
||||||
|
(define-dbus-signal-handler (root on-signal) ((s :string))
|
||||||
|
(:interface "org.adeht.MyService")
|
||||||
|
(format t "Got signal on root with arg ~S~%" s)
|
||||||
|
(force-output))
|
||||||
|
|
||||||
|
(defun publish-example ()
|
||||||
|
(handler-case
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(format t "Bus connection name: ~A~%" (bus-name bus))
|
||||||
|
(dbus:add-match bus :type :signal :interface "org.adeht.MyService")
|
||||||
|
(publish-objects bus))
|
||||||
|
(end-of-file ()
|
||||||
|
:disconnected-by-bus)))
|
||||||
|
|
||||||
|
;; was missing the 'add-match
|
||||||
|
;; and now let's try to catch the NotificationClosed tihngy
|
||||||
|
;; enefedov@LLF33A87M:~$ dbus-send --session --type=signal /org/adeht/MyService org.adeht.MyService.OnSignal string:"Hello yayyaline"
|
||||||
|
|
||||||
|
;; and when i do signal-handler on 'root
|
||||||
|
;; $ dbus-send --session --type=signal /org/adeht/MyService org.adeht.MyService.OnSignal ;; this is how to send it
|
||||||
|
;; so! i need to create it on the object path, ok
|
|
@ -0,0 +1,377 @@
|
||||||
|
;; for the sly to use dynamibly decided sbcl impl, to pick up wrappers
|
||||||
|
;; with packages?
|
||||||
|
;; (setq inferior-lisp-program "/bin/env sbcl")
|
||||||
|
|
||||||
|
;; so. what? load dbus library and try out examples?
|
||||||
|
;; maybe i want to try some of the simpler function calls
|
||||||
|
;; and then get to screen sharing dialog, and print some info on frames?
|
||||||
|
|
||||||
|
;; https://nixos.org/manual/nixpkgs/stable/#lisp-building-wrappers
|
||||||
|
(load (sb-ext:posix-getenv "ASDF"))
|
||||||
|
(asdf:load-system 'alexandria)
|
||||||
|
(asdf:load-system 'dbus)
|
||||||
|
|
||||||
|
;; https://blog.macrolet.net/posts/DBus-and-PolicyKit-from-Common-Lisp.html
|
||||||
|
(defpackage #:example
|
||||||
|
(:use #:cl #:dbus))
|
||||||
|
|
||||||
|
(in-package #:example)
|
||||||
|
|
||||||
|
(with-open-bus (bus (system-server-addresses))
|
||||||
|
(with-introspected-object (authority bus
|
||||||
|
"/org/freedesktop/PolicyKit1/Authority"
|
||||||
|
"org.freedesktop.PolicyKit1")
|
||||||
|
(let* ((subject `("system-bus-name" (("name" ((:string) ,(bus-name bus))))))
|
||||||
|
(action-id "org.freedesktop.policykit.exec")
|
||||||
|
(details ())
|
||||||
|
(flags 1)
|
||||||
|
(cancellation-id "")
|
||||||
|
(result
|
||||||
|
(authority "org.freedesktop.PolicyKit1.Authority" "CheckAuthorization"
|
||||||
|
subject action-id details flags cancellation-id)))
|
||||||
|
(format T "~A~%" result))))
|
||||||
|
|
||||||
|
(dbus/server-addresses:system-server-addresses)
|
||||||
|
(system-server-addresses)
|
||||||
|
|
||||||
|
;; C-c is sly-prefix-map
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(with-introspected-object (notification bus "/org/freedesktop/Notifications" "org.freedesktop.Notifications")
|
||||||
|
(notification "org.freedesktop.Notifications" "Notify"
|
||||||
|
"Test" 0 "" "Test" "This is a test; I repeat, this is a test." '() '() -1)
|
||||||
|
))
|
||||||
|
|
||||||
|
;; ok, but how do i introspect which parameters i need to pass to the call?
|
||||||
|
;; i could use
|
||||||
|
;;$ qdbus org.freedesktop.Notifications /org/freedesktop/Notifications
|
||||||
|
;; from kdePackages.qttools
|
||||||
|
;; but i'd prefer from cl
|
||||||
|
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(list-names bus))
|
||||||
|
|
||||||
|
(with-open-connection (bus (make-instance 'iomux:event-base) (session-server-addresses))
|
||||||
|
(let ((obj (make-object-from-introspection bus "/org/freedesktop/Notifications" "org.freedesktop.Notifications")))
|
||||||
|
(format T "hello")
|
||||||
|
(format T "~A" obj)))
|
||||||
|
|
||||||
|
;; sly-macroexpand-1
|
||||||
|
;; (let ((bus
|
||||||
|
;; (open-connection (make-instance 'iolib/multiplex:event-base)
|
||||||
|
;; (session-server-addresses) :if-failed :error)))
|
||||||
|
;; (unwind-protect
|
||||||
|
;; (progn
|
||||||
|
;; (make-object-from-introspection bus "/org/freedesktop/Notifications"
|
||||||
|
;; "org.freedesktop.Notifications"))
|
||||||
|
;; (when bus (close-connection bus))))
|
||||||
|
|
||||||
|
;; oh, ok. make-object-from-introspection can be subsctituted with convenience
|
||||||
|
;; ' with-introspected-object' and that's already in examples
|
||||||
|
;; so convenience does hide the multiplexers and connecitons
|
||||||
|
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(list-names bus ))
|
||||||
|
|
||||||
|
;; "org.freedesktop.Notifications"
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(get-managed-objects bus "org.freedesktop.Notifications" ))
|
||||||
|
|
||||||
|
;; wait, what if i just use 'object in the forms passed to 'with-introspected-object'?
|
||||||
|
;; and gensyms pick it up? :shrug:
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(get-managed-objects bus "org.freedesktop.Notifications" "/org/freedesktop/Notifications" ))
|
||||||
|
;; nope
|
||||||
|
|
||||||
|
;; ok, found another example maybe
|
||||||
|
;; https://github.com/lucashpandolfo/udisks
|
||||||
|
;; well, maybe it should work?
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(get-managed-objects bus "org.gtk.vfs.AfcVolumeMonitor" "/org/gtk/Private/RemoteVolumeMonitor" ))
|
||||||
|
|
||||||
|
;; ok, maybe these servcies don't have managed objects?
|
||||||
|
;; otherwise they would have ObjectManager interface or something
|
||||||
|
;; so let's try to figure out which interface I need to add for
|
||||||
|
;; get-all-properties to work
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(get-all-properties bus "org.freedesktop.Notifications"
|
||||||
|
"/org/freedesktop/Notifications"
|
||||||
|
"org.freedesktop.Notifications"))
|
||||||
|
|
||||||
|
;; nil, but maybe because it has methods, not properties?
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(get-all-properties bus "org.freedesktop.portal.Desktop" "/org/freedesktop/portal/desktop" "org.freedesktop.portal.ScreenCast"))
|
||||||
|
|
||||||
|
;; (("AvailableSourceTypes" 0) ("AvailableCursorModes" 0) ("version" 4))
|
||||||
|
;; ok, so this is getting properties. cool
|
||||||
|
;; next - figuring out how to check method signatures?
|
||||||
|
;; should be possible no?
|
||||||
|
|
||||||
|
;; oh, maybe i should use 'make-object-from-introspection directly
|
||||||
|
;; but where do i get "connection?"
|
||||||
|
|
||||||
|
(format T "well")
|
||||||
|
|
||||||
|
(iolib/multiplex:with-event-base (event-base)
|
||||||
|
(format T "yoyo")
|
||||||
|
(with-open-connection (connection event-base (session-server-addresses))
|
||||||
|
(format T "in connection ~A" connection)
|
||||||
|
(let ((introspection (dbus/introspect:fetch-introspection-document connection "/org/freedesktop/Notifications" "org.freedesktop.Notifications")))
|
||||||
|
(format T "Introspection: ~A" introspection))
|
||||||
|
|
||||||
|
(let ((obj (make-object-from-introspection connection "/org/freedesktop/Notifications" "org.freedesktop.Notifications")))
|
||||||
|
(format T "hello")
|
||||||
|
(format T "~A" obj))))
|
||||||
|
|
||||||
|
(with-open-bus (my-bus (session-server-addresses))
|
||||||
|
(handler-case
|
||||||
|
(let ((props (dbus:get-all-properties my-bus "org.freedesktop.Notifications" "/org/freedesktop/Notifications" "org.freedesktop.Notifications")))
|
||||||
|
(format T "Notification properties: ~A~%" props))
|
||||||
|
(error (e)
|
||||||
|
(format T "Error getting properties: ~pA~%" e))))
|
||||||
|
|
||||||
|
;; well, strange
|
||||||
|
|
||||||
|
;; https://old.reddit.com/r/lisp/comments/179zl1/has_anyone_else_used_the_dbus_package_much/
|
||||||
|
(progn
|
||||||
|
(setf upower_conn
|
||||||
|
(open-connection
|
||||||
|
(make-instance 'iolib.multiplex:event-base) (system-server-addresses)))
|
||||||
|
(authenticate (supported-authentication-mechanisms upower_conn) upower_conn)
|
||||||
|
(hello upower_conn)
|
||||||
|
(invoke-method upower_conn "Introspect"
|
||||||
|
:path "/org/freedesktop/UPower"
|
||||||
|
:destination "org.freedesktop.UPower"
|
||||||
|
:interface "org.freedesktop.DBus.Introspectable"))
|
||||||
|
|
||||||
|
|
||||||
|
(progn
|
||||||
|
(setf upower_conn
|
||||||
|
(open-connection
|
||||||
|
(make-instance 'iolib.multiplex:event-base) (system-server-addresses)))
|
||||||
|
(authenticate (supported-authentication-mechanisms upower_conn) upower_conn)
|
||||||
|
(hello upower_conn)
|
||||||
|
(setf bat0_obj
|
||||||
|
(make-object-from-introspection
|
||||||
|
upower_conn
|
||||||
|
"/org/freedesktop/UPower/devices/battery_BAT0"
|
||||||
|
"org.freedesktop.UPower"))
|
||||||
|
(object-invoke bat0_obj "org.freedesktop.DBus.Properties" "GetAll" "org.freedesktop.UPower.Device"))
|
||||||
|
|
||||||
|
;; ok, so this works.
|
||||||
|
;; from 11 years ago, cool
|
||||||
|
;; creating object from introspection
|
||||||
|
;; doing invoke, but similar to with-object
|
||||||
|
|
||||||
|
;; let's try get object for Notification
|
||||||
|
;; and then try to print object and stuff
|
||||||
|
|
||||||
|
(iolib/multiplex:with-event-base (event-base)
|
||||||
|
(with-open-connection (connection event-base (session-server-addresses))
|
||||||
|
(authenticate (supported-authentication-mechanisms connection) connection)
|
||||||
|
(hello connection)
|
||||||
|
(let ((obj (make-object-from-introspection connection "/org/freedesktop/Notifications" "org.freedesktop.Notifications")))
|
||||||
|
(print-object obj nil)
|
||||||
|
(list-object-interfaces obj))))
|
||||||
|
|
||||||
|
;; ok, so this works?
|
||||||
|
;; i needed both authenticate and hello, cool
|
||||||
|
;; thank you https://old.reddit.com/r/lisp/comments/179zl1/has_anyone_else_used_the_dbus_package_much/
|
||||||
|
|
||||||
|
;; (#<DBUS/INTROSPECT::INTERFACE "org.freedesktop.Notifications">
|
||||||
|
;; #<DBUS/INTROSPECT::INTERFACE "org.dunstproject.cmd0">
|
||||||
|
;; #<DBUS/INTROSPECT::INTERFACE "org.freedesktop.DBus.Peer">
|
||||||
|
;; #<DBUS/INTROSPECT::INTERFACE "org.freedesktop.DBus.Introspectable">
|
||||||
|
;; #<DBUS/INTROSPECT::INTERFACE "org.freedesktop.DBus.Properties">)
|
||||||
|
|
||||||
|
;; wowy, yeay!
|
||||||
|
;; i guess maybe now let's try to list interface on Desktop, which will have ScreenCast
|
||||||
|
|
||||||
|
|
||||||
|
(iolib/multiplex:with-event-base (event-base)
|
||||||
|
(with-open-connection (connection event-base (session-server-addresses))
|
||||||
|
(authenticate (supported-authentication-mechanisms connection) connection)
|
||||||
|
(hello connection)
|
||||||
|
(let ((obj (make-object-from-introspection connection "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")))
|
||||||
|
(print-object obj nil)
|
||||||
|
(list-object-interfaces obj))))
|
||||||
|
|
||||||
|
;; nice!
|
||||||
|
|
||||||
|
;; so, what to try next though?
|
||||||
|
;; i wanted a way to check the funciton signatures
|
||||||
|
;; maybe for this one?
|
||||||
|
;; #<DBUS/INTROSPECT::INTERFACE "org.freedesktop.portal.Screenshot">
|
||||||
|
;; how do i get methods of an interface?
|
||||||
|
;; oh, so 'list-object-interfaces only returns values from hashmap that obj
|
||||||
|
;; already contains
|
||||||
|
(iolib/multiplex:with-event-base (event-base)
|
||||||
|
(with-open-connection (connection event-base (session-server-addresses))
|
||||||
|
(authenticate (supported-authentication-mechanisms connection) connection)
|
||||||
|
(hello connection)
|
||||||
|
(let ((obj (make-object-from-introspection connection "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")))
|
||||||
|
(list-interface-methods (object-interface "org.freedesktop.portal.Screenshot" obj)))))
|
||||||
|
|
||||||
|
;; (#<DBUS/INTROSPECT::METHOD "PickColor" sa{sv}>
|
||||||
|
;; #<DBUS/INTROSPECT::METHOD "Screenshot" sa{sv}>)
|
||||||
|
;; ok, here are sa{sv} types of parameters, maybe this is it
|
||||||
|
;; i suppose next is figuring out how to call
|
||||||
|
|
||||||
|
;; let's read more general stuff about dbus then?
|
||||||
|
;; https://develop.kde.org/docs/features/d-bus/accessing_dbus_interfaces/
|
||||||
|
;; i think this is in C with qt library, but ok
|
||||||
|
|
||||||
|
;; here's about Variants https://doc.qt.io/qt-5/qvariant.html
|
||||||
|
;; what's that?
|
||||||
|
|
||||||
|
;; ok, now examples should be more understandable
|
||||||
|
;; https://github.com/death/dbus/blob/8bba6a0942232e9d7fa915b33bbe32dfedc5abb9/examples/notify.lisp
|
||||||
|
;; https://github.com/death/dbus/blob/8bba6a0942232e9d7fa915b33bbe32dfedc5abb9/examples/publish.lisp
|
||||||
|
|
||||||
|
;; maybe. let's try to call something with screenshots, let's go
|
||||||
|
|
||||||
|
;; https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Screenshot.html
|
||||||
|
(iolib/multiplex:with-event-base (event-base)
|
||||||
|
(with-open-connection (connection event-base (session-server-addresses))
|
||||||
|
(authenticate (supported-authentication-mechanisms connection) connection)
|
||||||
|
(hello connection)
|
||||||
|
(let ((obj (make-object-from-introspection connection "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")))
|
||||||
|
(list-interface-methods (object-interface "org.freedesktop.portal.Screenshot" obj)))))
|
||||||
|
|
||||||
|
;; for the sa{sv} looking into documentation
|
||||||
|
;; https://dbus.freedesktop.org/doc/dbus-specification.html#type-system
|
||||||
|
;; so for screenshot it's string, then array of dict entry string->variant
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
|
||||||
|
(desktop "org.freedesktop.portal.Screenshot" "Screenshot" "" '())))
|
||||||
|
|
||||||
|
;; dbus-send --session --dest=org.freedesktop.portal.Screenshot --type=method_call --print-reply /org/freedesktop/portal/desktop org.freedesktop.portal.Screenshot
|
||||||
|
|
||||||
|
;; well, calling Screenshot from the qdbusviewer doesn't work
|
||||||
|
;; maybe it can work from code,
|
||||||
|
;; not quite found an easy answer, but here's code for flameshot
|
||||||
|
;; https://github.com/flameshot-org/flameshot/blob/c1dac52231024174faa68a29577129ebca125dff/src/utils/screengrabber.cpp#L59
|
||||||
|
|
||||||
|
(iolib/multiplex:with-event-base (event-base)
|
||||||
|
(with-open-connection (connection event-base (session-server-addresses))
|
||||||
|
(authenticate (supported-authentication-mechanisms connection) connection)
|
||||||
|
(hello connection)
|
||||||
|
(let ((obj (make-object-from-introspection connection "/org/adeht/MyService" "org.adeht.MyService")))
|
||||||
|
(list-interface-methods (object-interface "org.adeht.MyService" obj))
|
||||||
|
))) ; missing Introspecable on the service defined through death/dbus
|
||||||
|
;; that's because 8 months ago introspection publishing was changed to be done by default
|
||||||
|
;; and my version is older, i could try to set up separate action from removed example?
|
||||||
|
;; but better to try to update
|
||||||
|
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(with-introspected-object (desktop bus "/org/adeht/MyService" "org.adeht.MyService")
|
||||||
|
(desktop "org.adeht.MyService" "my-method" "hello")))
|
||||||
|
|
||||||
|
;; trying from another discussion
|
||||||
|
;; still trying to receive a signal
|
||||||
|
(define-dbus-object root
|
||||||
|
(:path "/"))
|
||||||
|
|
||||||
|
(dbus:define-dbus-object my-notifications-service
|
||||||
|
(:path "/org/freedesktop/Notifications")
|
||||||
|
(:parent root))
|
||||||
|
|
||||||
|
;; (dbus:define-dbus-signal-handler (my-notifications-service notification-closed) ()
|
||||||
|
;; (:interface "org.freedesktop.Notifications")
|
||||||
|
;; (format t "Got notification closed without parameters" )
|
||||||
|
;; (force-output))
|
||||||
|
|
||||||
|
(dbus:define-dbus-signal-handler (my-notifications-service notification-closed) ((id :uint32) (reason :uint32))
|
||||||
|
(:interface "org.freedesktop.Notifications")
|
||||||
|
(format t "Got notification closed with parameters ~A ~A" id reason)
|
||||||
|
(force-output))
|
||||||
|
|
||||||
|
(define-dbus-signal-handler (my-notifications-service on-non-notification-end-signal) ((s :string))
|
||||||
|
(:interface "org.adeht.MyService")
|
||||||
|
(format t "Got signal with arg ~S~%" s)
|
||||||
|
(force-output))
|
||||||
|
|
||||||
|
(defun example-listen-to-notification ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (session-server-addresses))
|
||||||
|
; (dbus:add-match bus :type :signal :interface "org.freedesktop.Notifications" :member "NotificationClosed")
|
||||||
|
; (dbus:add-match bus :type :signal :interface "org.adeht.MyService")
|
||||||
|
(dbus:add-match bus :type :signal :path "/org/freedesktop/Notifications")
|
||||||
|
(format t "Bus connection name: ~A~%" (dbus:bus-name bus))
|
||||||
|
(dbus:publish-objects bus))
|
||||||
|
(end-of-file ()
|
||||||
|
:disconnected-by-bus)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;; signal time=1719758221.505386 sender=:1.64 -> destination=:1.162 serial=83 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications; member=NotificationClosed
|
||||||
|
;; uint32 15
|
||||||
|
;; uint32 2
|
||||||
|
(with-open-bus (bus (session-server-addresses))
|
||||||
|
(with-introspected-object (notification bus "/org/freedesktop/Notifications" "org.freedesktop.Notifications")
|
||||||
|
(notification "org.freedesktop.Notifications" "Notify"
|
||||||
|
"Test" 0 "" "Test" "This is a test; I repeat, this is a test." '() '() -1)
|
||||||
|
))
|
||||||
|
|
||||||
|
;; yes, i re-declared signal handler without parameters and now it catches
|
||||||
|
;; the
|
||||||
|
;; goood!
|
||||||
|
|
||||||
|
;; but it doesn't catch when i actually close the notification
|
||||||
|
;; maybe because of parameters?
|
||||||
|
;; oh, maybe uint32 are not the ones i had before in the signature
|
||||||
|
|
||||||
|
;; this works for my extra interface handler:
|
||||||
|
;; $ dbus-send --session --type=signal /org/freedesktop/Notifications org.adeht.MyService.OnNonNotificationEndSignal string:"Hello yayyaline"
|
||||||
|
|
||||||
|
;; huh. so manual with uint32 works
|
||||||
|
;; dbus-send --session --type=signal /org/freedesktop/Notifications org.freedesktop.Notifications.NotificationClosed uint32:4 uint32:8
|
||||||
|
|
||||||
|
;; and if i only define without params, then manual without params works
|
||||||
|
;; dbus-send --session --type=signal /org/freedesktop/Notifications org.freedesktop.Notifications.NotificationClosed
|
||||||
|
|
||||||
|
;; but the one from actually closed notification doesn't work?
|
||||||
|
;; in dbus-monitor one from actually closing:
|
||||||
|
;; signal time=1719765073.249989 sender=:1.45 -> destination=:1.112 serial=51 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications; member=NotificationClosed
|
||||||
|
;; uint32 11
|
||||||
|
;; uint32 2
|
||||||
|
|
||||||
|
;; and from manual invocation:
|
||||||
|
;; signal time=1719765156.257421 sender=:1.115 -> destination=(null destination) serial=2 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications; member=NotificationClosed
|
||||||
|
;; uint32 2222
|
||||||
|
;; uint32 11111
|
||||||
|
|
||||||
|
;; is there any visible difference?
|
||||||
|
;; aaand, yeah, i get with manual and dont get with actual
|
||||||
|
|
||||||
|
;; aaand, yes.
|
||||||
|
;; when signal has "destination" set - it's not broadcasted,
|
||||||
|
;; so, not everyone gets it. when i do actual closing of notification
|
||||||
|
;; the resulting NotificationClosed is likely sent to caller
|
||||||
|
;; and my code doesn't receive it, coool
|
||||||
|
;; $ dbus-send --session --type=signal --dest=:1.108 /org/freedesktop/Notifications org.freedesktop.Notifications.NotificationClosed uint32:777 uint32:333
|
||||||
|
;; this works - when i match with a name from "Bus connection name"
|
||||||
|
|
||||||
|
;; yay. i suppose
|
||||||
|
;; now what would be an example of broadcasted signal that i could listen to
|
||||||
|
;; in my example
|
||||||
|
|
||||||
|
;; let's do safeeyes icon change:
|
||||||
|
;; signal time=1719766048.367111 sender=:1.34 -> destination=(null destination) serial=101 path=/org/ayatana/NotificationItem/safeeyes_2; interface=org.kde.StatusNotifierItem; member=NewIcon
|
||||||
|
|
||||||
|
(dbus:define-dbus-object my-safeeyes-listener
|
||||||
|
(:path "/org/ayatana/NotificationItem/safeeyes_2"))
|
||||||
|
|
||||||
|
(dbus:define-dbus-signal-handler (my-safeeyes-listener new-icon) ()
|
||||||
|
(:interface "org.kde.StatusNotifierItem")
|
||||||
|
(format t "Got notification on the safeeyes icon change~%" )
|
||||||
|
(force-output))
|
||||||
|
|
||||||
|
(defun example-listen-to-safeeys ()
|
||||||
|
(handler-case
|
||||||
|
(dbus:with-open-bus (bus (session-server-addresses))
|
||||||
|
(dbus:add-match bus :type :signal :interface "org.kde.StatusNotifierItem")
|
||||||
|
(format t "Bus connection name: ~A~%" (dbus:bus-name bus))
|
||||||
|
(dbus:publish-objects bus))
|
||||||
|
(end-of-file ()
|
||||||
|
:disconnected-by-bus)))
|
Loading…
Reference in New Issue