176 lines
5.5 KiB
Common Lisp
176 lines
5.5 KiB
Common Lisp
(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)
|