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