more notes and some opengl light in the tunnel

This commit is contained in:
efim 2024-12-23 09:26:47 +01:00
parent a7c31193bc
commit 8f0d4b30bb
5 changed files with 154 additions and 215 deletions

View File

@ -1,174 +0,0 @@
;(load (sb-ext:posix-getenv "ASDF"))
(asdf:load-system 'dbus)
(defpackage
#:screencasting
(:use #:cl)
(:export call-with-all-predefined))
(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.Request")
;; some iolib tutorial https://pages.cs.wisc.edu/~psilord/blog/data/iolib-tutorial/tutorial.html
;; i hoped it would help me understand the 'publish-events'
;; 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?
(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)))
;; 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?
;; alright, let's have function startup new bus connection for each call
;; but then try to do these multiple calls
(defun call-screencast-method (method-name params)
(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)
(format t "before sending notification")
(send-notification bus "yayaya from the first response")
(format t "ending signal handler")
(force-output))
(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 +request-interface+)
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
(desktop +screen-cast-interface+ method-name ; "CreateSession"
params
;; '(("handle_token" ((:string) "yayay"))
;; ("session_handle_token" ((:string) "hohoyyy")))
))
(dbus:publish-objects bus '(request-object) )))
(end-of-file ()
:disconnected-by-bus)))
'(call-screencast-method "CreateSession"
'(("handle_token" ((:string) "yayay"))
("session_handle_token" ((:string) "hohoyyy"))))
;; let's define ALL beforehand?
(defun call-with-all-predefined ()
(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-create-session-name "createSessionReq")
(resp-path (concatenate 'string "/org/freedesktop/portal/desktop/request/"
requester-name
"/"
request-create-session-name))
(request-select-sources "selectSourcesReq")
(select-sources-resp-path (concatenate 'string "/org/freedesktop/portal/desktop/request/"
requester-name
"/"
request-select-sources))
(request-start "startReq")
(start-resp-path (concatenate 'string "/org/freedesktop/portal/desktop/request/"
requester-name
"/"
request-start))
(session-handle-hardcoded "yayay")
(session-handle-path (concatenate 'string "/org/freedesktop/portal/desktop/session/"
requester-name
"/"
session-handle-hardcoded)))
(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 "About sto send SelectSources with path ~S~%" session-handle-path)
(force-output)
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
(desktop +screen-cast-interface+ "SelectSources"
session-handle-path ; hardcoded session-handle
`(("handle_token" ((:string) ,request-select-sources)))))
(format t "Still first callback, after calling SelectSources~%")
(force-output))
(dbus:define-dbus-object select-sources-request-obj
(:path select-sources-resp-path))
(dbus:define-dbus-signal-handler (select-sources-request-obj response) ((id :uint32) (results (:ARRAY (:DICT-ENTRY :STRING :VARIANT))))
(:interface +request-interface+)
(format t ">> Got inside of SelectSources callback ~A ~A~%" id results)
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
(desktop +screen-cast-interface+ "Start"
session-handle-path
"parent-window"
`(("handle_token" ((:string) , request-start)))))
(format t ">> Still inside SelectSources callback, after calling Start~%")
(force-output))
(dbus:define-dbus-object start-request-obj
(:path start-resp-path))
(dbus:define-dbus-signal-handler (start-request-obj response) ((id :uint32) (results (:ARRAY (:DICT-ENTRY :STRING :VARIANT))))
(:interface +request-interface+)
(format t ">> Got inside of Start callback ~A ~A~%" id results))
(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 +request-interface+)
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
(desktop +screen-cast-interface+ "CreateSession"
`(("handle_token" ((:string) ,request-create-session-name))
("session_handle_token" ((:string) ,session-handle-hardcoded)))))
(dbus:publish-objects bus)))
(end-of-file ()
:disconnected-by-bus)))
;; ok
;; >> Got inside of Start callback 0 ((streams
;; ((43
;; ((position (0 0)) (size (1920 1080)))))))
;; interesting. now what do do with the streams?
;; An array of PipeWire streams. Each stream consists of a PipeWire node ID (the first element in the tuple, and a Vardict of properties.
;; ok, now i need to figure out how
;; yeah, nix shell nixpkgs#qpwgraph
;; with this tool i see new 'out' node, maybe i can even already connect to it with
;; some program?
;; yes. enefedov@LLF33A87M:~/Documents/personal/learning-screen-share$ gst-launch-1.0 pipewiresrc path=43 ! videoconvert ! autovideosink
;; cool.
;; now i want to have a window with this video stream created by my program
;; this is new level of "i have no idea where to go"
;; https://github.com/death/dbus/issues/31
;; asked my question about multiple async dbus requests

View File

@ -145,6 +145,7 @@
(format T "Bus connection name ~A~%" (dbus:bus-name bus))
(dbus:add-match bus :type :signal
:interface +request-interface+)
(format T "About to send first message to dbus : Create Seccion~%")
(dbus:with-introspected-object (desktop bus "/org/freedesktop/portal/desktop" "org.freedesktop.portal.Desktop")
(desktop +screen-cast-interface+ "CreateSession"
`(("handle_token" ((:string) ,request-create-session-name))

View File

@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1719597372,
"narHash": "sha256-SpZKwy6sjgH00xiYmfjVAX+JaNkPQ2Q/BrEhNtWJvH4=",
"lastModified": 1734802620,
"narHash": "sha256-rUg5S3bKZu1rNPY5/EqQNXN9DNpXIZXc/AnbcK/h/sU=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "dd66e39ec4c7252fab7e6f8fd57b5ab2a3c7d63c",
"rev": "8ddbc4432614ed034cb69f02eedd723250d9513e",
"type": "github"
},
"original": {

View File

@ -4,43 +4,37 @@
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'
ps.cl-cffi-gtk
ps.sdl2
ps.cl-opengl
ps.cl-gobject-introspection
]);
in
{
devShells.default = pkgs.mkShell {
SDL_VIDEODRIVER="wayland";
WAYLAND_DISPLAY="wayland-1";
EGL_PLATFORM="wayland";
buildInputs = [
pkgs.gst_all_1.gstreamer
pkgs.gst_all_1.gst-plugins-base
pkgs.gst_all_1.gst-plugins-good
pkgs.pipewire
sbcl'
];
};
}
);
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'
ps.cl-cffi-gtk
ps.sdl2
ps.cl-opengl
ps.cl-gobject-introspection
]);
# Create a wrapper that uses system's Wayland
in {
devShells.default = pkgs.mkShell {
buildInputs = [
sbcl'
pkgs.nixfmt
];
};
});
# see https://serokell.io/blog/practical-nix-flakes
}

118
notes.org
View File

@ -677,4 +677,122 @@ but maybe i want something else?
let's read docs on appsrc
https://github.com/go-gst/go-gst/tree/v1.1.0/examples/appsrc
* [2024-12-08 Sun]
** well, i guess i will maybe return to this?
https://www.youtube.com/watch?v=Jn_09BeUEI0
here is gltransformation
this looks like what i'd really want, no?
** and this is documentation
https://gstreamer.freedesktop.org/documentation/opengl/index.html?gi-language=c
https://gstreamer.freedesktop.org/documentation/opengl/gltransformation.html?gi-language=c#gltransformation
why doesn't it work?
* [2024-12-21 Sat]
** wait. it works now? how and why
maybe because it's installed via apt?
yes. if i try to use
gst-launch-1.0 gltestsrc ! gltransformation scale-y=0.5 scale-x=0.5 ! glimagesink
in the nix shell i get
#+begin_src
Setting pipeline to PAUSED ...
Caught SIGSEGV
Spinning. Please run 'gdb gst-launch-1.0 242683' to continue debugging, Ctrl-C to quit, or Ctrl-\ to dump core.
#+end_src
** for now found article about other ways to transform
https://lubosz.wordpress.com/2014/06/16/transforming-video-on-the-gpu/
but that this opengl way is much faster
comparing with this:
https://gstreamer.freedesktop.org/documentation/videoconvertscale/videoscale.html?gi-language=c
gst-launch-1.0 -v videotestsrc ! videoscale ! autovideosink
gst-launch-1.0 -v videotestsrc ! videoscale ! video/x-raw,width=1000 ! autovideosink
** the ordinary error is
gst-launch-1.0 gltestsrc ! gltransformation rotation-z=45 ! glimagesink
Setting pipeline to PAUSED ...
Caught SIGSEGV
Spinning. Please run 'gdb gst-launch-1.0 7843' to continue debugging, Ctrl-C to quit, or Ctrl-\ to dump core.
** huh. trying previous nixpkgs releases
and in 23.05 the error is different
efim-nefedov@LLF33A87M:~/Documents/personal/scratch-screen-share$ gst-launch-1.0 gltestsrc ! gltransformation rotation-z=45 ! glimagesink
Setting pipeline to PAUSED ...
ERROR: from element /GstPipeline:pipeline0/GstGLImageSinkBin:glimagesinkbin0/GstGLImageSink:sink: Could not find any FBConfig's to use (check attributes?)
Additional debug info:
../ext/gl/gstglimagesink.c(1131): _ensure_gl_setup (): /GstPipeline:pipeline0/GstGLImageSinkBin:glimagesinkbin0/GstGLImageSink:sink
ERROR: pipeline doesn't want to preroll.
Failed to set pipeline to PAUSED.
Setting pipeline to NULL ...
Freeing pipeline ...
** ok, looking at the error the problem is in creating connection
WARN gldisplayegl gstgldisplay_egl.c:408:gst_gl_display_egl_from_gl_display:<gldisplayegl1> failed to get EGLDisplay from native display
but beats me if i know what needs to be done
claude.ai recommends adding LD_LIBRARY_PATH to gstreamer
so trying
#+begin_src nix
gstWrapper = pkgs.writeScriptBin "gst-launch-wrapped" ''
#!${pkgs.bash}/bin/bash
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH
exec ${pkgs.gst_all_1.gstreamer}/bin/gst-launch-1.0 "$@"
'';
#+end_src
but that fails
$ gst-launch-wrapped gltestsrc ! gltransformation rotation-z=45 ! glimagesink
/nix/store/p6k7xp1lsfmbdd731mlglrdj2d66mr82-bash-5.2p37/bin/bash: error while loading shared libraries: __vdso_gettimeofday: invalid mode for dlopen(): Invalid argument
* [2024-12-22 Sun]
** ok, let's try what
let's try default video out after i turn on the screen sharing from cl part
with code cleaned up i can start the share, that's nice
gst-launch-1.0 pipewiresrc path=90 ! videoconvert ! autovideosink
let's also try to add opengl processing
gst-launch-1.0 pipewiresrc path=90 ! videoconvert ! gltransformation rotation-z=45 ! glimagesink
so, this kind of works
gst-launch-1.0 pipewiresrc path=90 ! videoconvert ! capsfilter caps="video/x-raw,format=RGBA" ! glupload ! gltransformation rotation-z=45 ! glimagesink
even if the thing is small
** trying to figure out why gl things open a small window
*** one that works
GST_DEBUG=4,caps:5 gst-launch-1.0 pipewiresrc path=90 ! videoconvert ! autovideosink
has
deterministic way of creating a stream-id
0:00:00.032812186 44186 0x74b020000b70 INFO GST_EVENT gstevent.c:918:gst_event_new_caps: creating caps event video/x-raw, format=(string)BGRA, width=(int)1920, height=(int)1080, framerate=(fraction)0/1, max-framerate=(fraction)60/1
0:00:00.033493070 44186 0x74b020000b70 INFO GST_EVENT gstevent.c:918:gst_event_new_caps: creating caps event video/x-raw, width=(int)1920, height=(int)1080, framerate=(fraction)0/1, max-framerate=(fraction)60/1, format=(string)YV12
*** and comparing with
GST_DEBUG=4,caps:5 gst-launch-1.0 pipewiresrc path=90 ! videoconvert ! capsfilter caps="video/x-raw,format=RGBA" ! glupload ! gltransformation rotation-z=45 ! glimagesink
(by recommendation of claude)
0:00:00.152714238 44533 0x784a70000b70 INFO GST_EVENT gstevent.c:918:gst_event_new_caps: creating caps event video/x-raw(memory:GLMemory), width=(int)1920, height=(int)1080, framerate=(fraction)0/1, max-framerate=(fraction)60/1, format=(string)RGBA, texture-target=(string)2D
0:00:00.152789062 44533 0x784a70000b70 INFO basetransform gstbasetransform.c:1326:gst_base_transform_setcaps:<glcolorbalance0> reuse caps
0:00:00.152821256 44533 0x784a70000b70 INFO GST_EVENT gstevent.c:918:gst_event_new_caps: creating caps event video/x-raw(memory:GLMemory), width=(int)1920, height=(int)1080, framerate=(fraction)0/1, max-framerate=(fraction)60/1, format=(string)RGBA, texture-target=(string)2D
well, i guess i can just open the window full size
*** ok! looks like it does stream full resolution.
now. i'd want to open the displaying pipeline programmatically
and then maybe try to dynamically change params
i guess even without a window embedding, just starting a window is good enough
but also, hm.
do i need any ui for the video window? i really don't think so.
maybe let's figure out the missing cursor
gst-launch-1.0 pipewiresrc path=90 ! videoconvert ! capsfilter caps="video/x-raw,format=RGBA" ! glupload ! gltransformation rotation-x=-15 ortho=True ! glimagesink
gst-launch-1.0 gltestsrc ! gltransformation rotation-x=-45 ortho=True ! glimagesink
** am i not getting into Create Session? after the Start?
https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.ScreenCast.html
(also note that here are cursor options)
** ok, let's try writing this in java then