(load (sb-ext:posix-getenv "ASDF")) (asdf:load-system 'cl-cffi-gtk) (defpackage :video-processor (:use :cl)) (in-package :video-processor) (defun create-main-window () (let ((window (gtk:gtk-window-new :toplevel))) (setf (gtk:gtk-window-title window) "Video Processor") (setf (gtk:gtk-window-default-size window) '(800 600)) (g:g-signal-connect window "destroy" (lambda (widget) (declare (ignore widget)) (gtk:leave-gtk-main))) window)) (defun create-drawing-area () (let ((area (gtk:gtk-drawing-area-new))) (g:g-signal-connect area "draw" #'draw-callback) area)) (defun draw-callback (widget cr) (declare (ignore widget)) ;; Clear the surface with a light gray color (let ((cr (gobject:pointer cr))) (cairo:cairo-set-source-rgb cr 0.9 0.9 0.9) (cairo:cairo-paint cr) ;; Draw a blue rectangle (cairo:cairo-set-source-rgb cr 0.0 0.0 1.0) (cairo:cairo-rectangle cr 50 50 200 100) (cairo:cairo-fill cr) ;; Draw some text (cairo:cairo-set-source-rgb cr 0.0 0.0 0.0) (cairo:cairo-select-font-face cr "Sans" :normal :normal) (cairo:cairo-set-font-size cr 40.0) (cairo:cairo-move-to cr 100 300) (cairo:cairo-show-text cr "Waiting for video..."))) (defun main () (gtk:within-main-loop (let* ((window (create-main-window)) (area (create-drawing-area))) (gtk:gtk-container-add window area) (gtk:gtk-widget-show-all window)))) (defun start-video-processing () ;; Initialize Pipewire connection here ;; Start a thread to continuously read frames and trigger redraws ) ;(main) ;(start-video-processing) ;; ok, i can create a window ;; copying stuff with hopes that it will help to get frames from pipewire (cffi:define-foreign-library libpipewire (:unix (:or "/lib/x86_64-linux-gnu/libpipewire-0.3.so.0" "libpipewire-0.3.so.0" "libpipewire-0.3.so")) (t (:default "libpipewire-0.3"))) (cffi:use-foreign-library libpipewire) ;; Define constants (defconstant +pw-stream-flag-autoconnect+ 2) (defun setup-pipewire () (pw-init (cffi:null-pointer) (cffi:null-pointer)) (let* ((loop (pw-loop-new)) (context (pw-context-new loop (cffi:null-pointer) 0)) (core (pw-context-connect context (cffi:null-pointer) 0)) (stream (pw-stream-new core "my-stream" (cffi:null-pointer)))) ;; Set up stream parameters (let ((params (pw-stream-get-properties stream))) (pw-properties-set params "media.type" "Audio") (pw-properties-set params "media.category" "Capture") (pw-properties-set params "media.role" "Music")) ;; Connect the stream (let ((stream-flags +pw-stream-flag-autoconnect+) (target 0)) ; Changed to 0 instead of null-pointer for target-id (pw-stream-connect stream "output" target stream-flags (cffi:null-pointer) 0)) ;; Return the created objects (values loop context core stream))) (defun setup-pipewire () (pw-init (cffi:null-pointer) (cffi:null-pointer)) (let* ((loop (pw-loop-new))) (unless loop (error "Failed to create Pipewire loop")) (let ((context (pw-context-new loop (cffi:null-pointer) 0))) (unless context (error "Failed to create Pipewire context")) (let ((core (pw-context-connect context (cffi:null-pointer) 0))) (unless core (error "Failed to connect Pipewire context")) (let ((stream (pw-stream-new core "my-stream" (cffi:null-pointer)))) (unless stream (error "Failed to create Pipewire stream")) ;; Set up stream parameters (let ((params (pw-stream-get-properties stream))) (unless params (error "Failed to get stream properties")) (unless (= 0 (pw-properties-set params "media.type" "Audio")) (error "Failed to set media.type")) (unless (= 0 (pw-properties-set params "media.category" "Capture")) (error "Failed to set media.category")) (unless (= 0 (pw-properties-set params "media.role" "Music")) (error "Failed to set media.role")) ;; Connect the stream (let ((stream-flags +pw-stream-flag-autoconnect+) (target 0)) (unless (>= (pw-stream-connect stream "output" target stream-flags (cffi:null-pointer) 0) 0) (error "Failed to connect stream")) ;; Return the created objects (values loop context core stream)))))))) ;; Define necessary CFFI bindings (cffi:defcfun ("pw_init" pw-init) :void (argc :pointer) (argv :pointer)) (cffi:defcfun ("pw_loop_new" pw-loop-new) :pointer) (cffi:defcfun ("pw_context_new" pw-context-new) :pointer (loop :pointer) (properties :pointer) (user-data-size :int)) (cffi:defcfun ("pw_context_connect" pw-context-connect) :pointer (context :pointer) (properties :pointer) (user-data-size :int)) (cffi:defcfun ("pw_stream_new" pw-stream-new) :pointer (core :pointer) (name :string) (properties :pointer)) (cffi:defcfun ("pw_stream_get_properties" pw-stream-get-properties) :pointer (stream :pointer)) (cffi:defcfun ("pw_properties_set" pw-properties-set) :int (properties :pointer) (key :string) (value :string)) (cffi:defcfun ("pw_stream_connect" pw-stream-connect) :int (stream :pointer) (direction :string) (target-id :int32) (flags :int) (params :pointer) (n-params :uint32)) (setup-pipewire)