diff --git a/cleaned-up/#start-share.lisp# b/cleaned-up/#start-share.lisp# deleted file mode 100644 index 4245ab9..0000000 --- a/cleaned-up/#start-share.lisp# +++ /dev/null @@ -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 - diff --git a/cleaned-up/start-share.lisp b/cleaned-up/start-share.lisp index 4245ab9..f690639 100644 --- a/cleaned-up/start-share.lisp +++ b/cleaned-up/start-share.lisp @@ -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)) diff --git a/flake.lock b/flake.lock index 721892c..0221733 100644 --- a/flake.lock +++ b/flake.lock @@ -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": { diff --git a/flake.nix b/flake.nix index 5635b09..610ada4 100644 --- a/flake.nix +++ b/flake.nix @@ -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 } diff --git a/notes.org b/notes.org index 1c16eee..d1d690b 100644 --- a/notes.org +++ b/notes.org @@ -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: 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: 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