diff --git a/README.org b/README.org index 7316fc3..e52f96e 100644 --- a/README.org +++ b/README.org @@ -1,3 +1,4 @@ -#+TITLE: cl-gio +#+TITLE: cl-glib -This library serves as a dependency of [[https://github.com/bohonghuang/cl-gtk4][cl-gtk4]] to create ~Application~, requiring ~glib~ and Object Introspection installed in your system. +This library serves as a dependency of [[https://github.com/bohonghuang/cl-gtk4][cl-gtk4]] to create ~Application~ and provide multi-threading support, +requiring ~glib~ and Object Introspection installed in your system. diff --git a/cl-glib.asd b/cl-glib.asd new file mode 100644 index 0000000..a4a37d4 --- /dev/null +++ b/cl-glib.asd @@ -0,0 +1,20 @@ +(defsystem cl-glib + :version "1.0.0" + :author "Bohong Huang <1281299809@qq.com>" + :maintainer "Bohong Huang <1281299809@qq.com>" + :license "lgpl3" + :description "GLib binding for Common Lisp." + :homepage "https://github.com/BohongHuang/cl-glib" + :bug-tracker "https://github.com/BohongHuang/cl-glib/issues" + :source-control (:git "https://github.com/BohongHuang/cl-glib.git") + :serial t + :components ((:file "glib")) + :depends-on (#:cl-gobject-introspection-wrapper #:bordeaux-threads)) + +(uiop:register-image-restore-hook + (lambda () + (let* ((namespace "GLib") + (package (find-package (string-upcase namespace)))) + (when package + (setf (symbol-value (find-symbol "*NS*" package)) + (uiop:symbol-call :gir :require-namespace namespace)))))) diff --git a/cl-gio.asd b/cl-glib.gio.asd similarity index 93% rename from cl-gio.asd rename to cl-glib.gio.asd index ac6a187..f195ade 100644 --- a/cl-gio.asd +++ b/cl-glib.gio.asd @@ -1,4 +1,4 @@ -(defsystem cl-gio +(defsystem cl-glib.gio :version "1.0.0" :author "Bohong Huang <1281299809@qq.com>" :maintainer "Bohong Huang <1281299809@qq.com>" @@ -8,7 +8,7 @@ :bug-tracker "https://github.com/BohongHuang/cl-glib/issues" :source-control (:git "https://github.com/BohongHuang/cl-glib.git") :serial t - :components ((:file "package")) + :components ((:file "gio")) :depends-on (#:cl-gobject-introspection-wrapper)) (uiop:register-image-restore-hook diff --git a/cl-glib.gobject.asd b/cl-glib.gobject.asd new file mode 100644 index 0000000..f14abd6 --- /dev/null +++ b/cl-glib.gobject.asd @@ -0,0 +1,20 @@ +(defsystem cl-glib.gobject + :version "1.0.0" + :author "Bohong Huang <1281299809@qq.com>" + :maintainer "Bohong Huang <1281299809@qq.com>" + :license "lgpl3" + :description "GObject binding for Common Lisp." + :homepage "https://github.com/BohongHuang/cl-gobject" + :bug-tracker "https://github.com/BohongHuang/cl-gobject/issues" + :source-control (:git "https://github.com/BohongHuang/cl-gobject.git") + :serial t + :components ((:file "gobject")) + :depends-on (#:cl-gobject-introspection-wrapper)) + +(uiop:register-image-restore-hook + (lambda () + (let* ((namespace "GObject") + (package (find-package (string-upcase namespace)))) + (when package + (setf (symbol-value (find-symbol "*NS*" package)) + (uiop:symbol-call :gir :require-namespace namespace)))))) diff --git a/package.lisp b/gio.lisp similarity index 98% rename from package.lisp rename to gio.lisp index 67a8a80..1c2947f 100644 --- a/package.lisp +++ b/gio.lisp @@ -1,4 +1,4 @@ -;;;; package.lisp +;;;; gio.lisp ;;;; Copyright (C) 2022 Bohong Huang ;;;; diff --git a/glib.lisp b/glib.lisp new file mode 100644 index 0000000..863bb07 --- /dev/null +++ b/glib.lisp @@ -0,0 +1,100 @@ +;;;; glib.lisp + +;;;; Copyright (C) 2022 Bohong Huang +;;;; +;;;; This program is free software: you can redistribute it and/or modify +;;;; it under the terms of the GNU Lesser General Public License as published by +;;;; the Free Software Foundation, either version 3 of the License, or +;;;; (at your option) any later version. +;;;; +;;;; This program is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU Lesser General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU Lesser General Public License +;;;; along with this program. If not, see . + +(cl:defpackage glib + (:use) + (:export #:*ns*)) + +(cl:in-package #:glib) + +(cl:eval-when (:execute :compile-toplevel :load-toplevel) + (cl:setf gir-wrapper:*quoted-name-alist* '(("CSET_a_2_z" . +cset-a-z-lower-case+) + ("CSET_A_2_Z" . +cset-a-z-upper-case+) + ("t" . time) + ("timeout_add") + ("timeout_add_seconds") + ("idle_add")))) + +(gir-wrapper:define-gir-namespace "GLib") + +(cl:defvar *objects* (cl:make-hash-table)) + +(cl:defvar *objects-lock* (bt:make-lock)) + +(cffi:defcallback funcall-object-callback :bool ((user-data :pointer)) + (cl:funcall (cl:gethash (cffi:pointer-address user-data) *objects*))) + +(cffi:defcallback free-object-callback :void ((user-data :pointer)) + (bt:with-lock-held (*objects-lock*) + (cl:remhash (cffi:pointer-address user-data) *objects*))) + +(cl:defconstant +1+maxsizet+ (cl:expt 2 (cl:- (cl:* 8 (cffi:foreign-type-size :pointer)) #+sbcl 2))) + +(cl:deftype unsigned-word () + `(cl:integer 0 ,(cl:1- +1+maxsizet+))) + +(cl:defun put-object (object) + (bt:with-lock-held (*objects-lock*) + (cl:loop + :with object-id :of-type unsigned-word := 0 + :do (cl:setf object-id (cl:random +1+maxsizet+)) + :while (cl:gethash object-id *objects*) + :finally + (cl:setf (cl:gethash object-id *objects*) object) + (cl:return object-id)))) + +(cl:defun timeout-add (interval function cl:&optional (priority +priority-default+)) + (gir:invoke (*ns* 'timeout-add) + priority + interval + (cffi:callback funcall-object-callback) + (cffi:make-pointer (put-object function)) + (cffi:callback free-object-callback))) + +(cl:export 'timeout-add) + +(cl:defun timeout-add-seconds (interval function cl:&optional (priority +priority-default+)) + (gir:invoke (*ns* 'timeout-add-seconds) + priority + interval + (cffi:callback funcall-object-callback) + (cffi:make-pointer (put-object function)) + (cffi:callback free-object-callback))) + +(cl:export 'timeout-add-seconds) + +(cl:defun idle-add (function cl:&optional (priority +priority-default+)) + (gir:invoke (*ns* 'idle-add) + priority + (cffi:callback funcall-object-callback) + (cffi:make-pointer (put-object function)) + (cffi:callback free-object-callback))) + +(cl:export 'idle-add) + +(cl:defun funcall (function cl:&rest arguments) + (idle-add (cl:lambda () (cl:apply function arguments) cl:nil))) + +(cl:export 'funcall) + +(cl:defmacro with-main-event-loop (cl:&body body) + `(funcall (cl:lambda () ,@body))) + +(cl:export 'with-main-event-loop) + +(cl:eval-when (:execute :compile-toplevel :load-toplevel) + (cl:setf gir-wrapper:*quoted-name-alist* cl:nil)) diff --git a/gobject.lisp b/gobject.lisp new file mode 100644 index 0000000..87c82fc --- /dev/null +++ b/gobject.lisp @@ -0,0 +1,24 @@ +;;;; gobject.lisp + +;;;; Copyright (C) 2022 Bohong Huang +;;;; +;;;; This program is free software: you can redistribute it and/or modify +;;;; it under the terms of the GNU Lesser General Public License as published by +;;;; the Free Software Foundation, either version 3 of the License, or +;;;; (at your option) any later version. +;;;; +;;;; This program is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU Lesser General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU Lesser General Public License +;;;; along with this program. If not, see . + +(cl:defpackage gobject + (:nicknames #:gobj) + (:export #:*ns*)) + +(cl:in-package #:gobj) + +(gir-wrapper:define-gir-namespace "GObject")