11 #:*glib-interface-age*
21 #:+g-priority-default+
22 #:+g-priority-high-idle+
23 #:+g-priority-default-idle+
31 #:with-catching-to-g-error
33 #:g-error-condition-domain
34 #:g-error-condition-code
35 #:g-error-condition-message)
37 "Cl-gtk2-glib is wrapper for @a[http://library.gnome.org/devel/glib/]{GLib}."))
41 (eval-when (:compile-toplevel :load-toplevel :execute)
42 (defvar *initializers-table* (make-hash-table :test 'equalp))
43 (defvar *initializers* nil)
44 (defun register-initializer (key fn)
45 (unless (gethash key *initializers-table*)
46 (setf (gethash key *initializers-table*) t
47 *initializers* (nconc *initializers* (list fn)))))
48 (defvar *finalizers-table* (make-hash-table :test 'equalp))
49 (defvar *finalizers* nil)
50 (defun register-finalizer (key fn)
51 (unless (gethash key *finalizers-table*)
52 (setf (gethash key *finalizers-table*) t
53 *finalizers* (nconc *finalizers* (list fn))))))
55 (defun run-initializers ()
56 (iter (for fn in *initializers*)
59 (defun run-finalizers ()
60 (iter (for fn in *finalizers*)
64 (pushnew 'run-initializers sb-ext:*init-hooks*)
66 (pushnew 'run-initializers ccl:*restore-lisp-functions*)
69 (pushnew 'run-finalizers sb-ext:*save-hooks*)
71 (pushnew 'run-finalizers ccl:*save-exit-functions*)
73 (defmacro at-init ((&rest keys) &body body)
75 @arg[keys]{list of expression}
77 Runs the code normally but also schedules the code to be run at image load time.
78 It is used to reinitialize the libraries when the dumped image is loaded. (Works only on SBCL for now).
80 At-init form may be called multiple times. The same code from should not be run multiple times at initialization time (in best case, this will only slow down initialization, in worst case, the code may crash). To ensure this, every @code{at-init} expression is added to hash-table with the @code{body} and @code{keys} as a composite key. This ensures that the same code is only executed once (once on the same set of parameters).
84 \(defmethod initialize-instance :after ((class gobject-class) &key &allow-other-keys)
85 (register-object-type (gobject-class-g-type-name class) (class-name class))
86 (at-init (class) (initialize-gobject-class-g-type class)))
89 In this example, for every @code{class}, @code{(initialize-gobject-class-g-type class)} will be called only once.
91 `(progn (register-initializer (list ,@keys ',body) (lambda () ,@body))
94 (defmacro at-finalize ((&rest keys) &body body)
95 `(register-finalizer (list ,@keys ',body) (lambda () ,@body)))
98 (eval-when (:compile-toplevel :load-toplevel :execute)
99 (define-foreign-library glib
100 (:unix (:or "libglib-2.0.so.0" "libglib-2.0.so"))
101 (:windows "libglib-2.0-0.dll")
102 (t (:default "libglib-2.0"))))
103 (eval-when (:compile-toplevel :load-toplevel :execute)
104 (define-foreign-library gthread
105 (:unix (:or "libgthread-2.0.so.0" "libgthread-2.0.so"))
106 (:windows "libgthread-2.0-0.dll")
107 (t "libgthread-2.0")))
109 (use-foreign-library glib)
110 (use-foreign-library gthread))
117 ;; Fundamentals - Basic types
121 ;; TODO: not sure about these: for amd64 they are ok
122 (eval-when (:compile-toplevel :load-toplevel :execute)
124 ((cffi-features:cffi-feature-p :x86-64) (defctype gsize :uint64))
125 ((cffi-features:cffi-feature-p :x86) (defctype gsize :ulong))
126 (t (error "Can not define 'gsize', unknown CPU architecture (known are x86 and x86-64)"))))
128 (defctype gssize :long)
130 (defctype goffset :uint64)
134 ;; Fundamentals - Version information
137 (defcvar (*glib-major-version* "glib_major_version" :read-only t :library glib) :uint)
138 (defcvar (*glib-minor-version* "glib_minor_version" :read-only t :library glib) :uint)
139 (defcvar (*glib-micro-version* "glib_micro_version" :read-only t :library glib) :uint)
140 (defcvar (*glib-binary-age* "glib_binary_age" :read-only t :library glib) :uint)
141 (defcvar (*glib-interface-age* "glib_interface_age" :read-only t :library glib) :uint)
145 ;; Limits of Basic Types, Standard Macros, Type Conversion Macros, Byte Order Macros,
146 ;; Numerical Definitions, Miscellaneous Macros, Atomic operations
149 ;; Core Application Support - The Main Event Loop
151 (defcstruct g-main-loop)
152 (defcstruct g-main-context)
153 (defcstruct g-source)
154 (defcstruct g-source-funcs
159 (closure-callback :pointer)
160 (closure-marshal :pointer))
161 (defcstruct g-source-callback-funcs
168 (defcstruct g-poll-fd
169 (fd :int) ;; TODO: #if defined (G_OS_WIN32) && GLIB_SIZEOF_VOID_P == 8
173 (defcstruct g-time-val
175 (microseconds :long))
177 (defcstruct g-thread)
179 (defcfun (g-main-loop-new "g_main_loop_new" :library glib) (:pointer g-main-loop)
180 (context (:pointer g-main-context))
181 (is-running :boolean))
183 (defcfun (g-main-loop-ref "g_main_loop_ref" :library glib) (:pointer g-main-loop)
184 (loop (:pointer g-main-loop)))
186 (defcfun (g-main-loop-unref "g_main_loop_unref" :library glib) (:pointer g-main-loop)
187 (loop (:pointer g-main-loop)))
189 (defcfun (g-main-loop-run "g_main_loop_run" :library glib) :void
190 (loop (:pointer g-main-loop)))
192 (defcfun (g-main-loop-quit "g_main_loop_quit" :library glib) :void
193 (loop (:pointer g-main-loop)))
195 (defcfun (g-main-loop-is-running "g_main_loop_is_running" :library glib) :boolean
196 (loop (:pointer g-main-loop)))
198 (defcfun (g-main-loop-get-context "g_main_loop_get_context" :library glib) (:pointer g-main-context)
199 (loop (:pointer g-main-loop)))
201 (defconstant +g-priority-high+ -100 "Use this for high priority event sources. It is not used within GLib or GTK+.")
202 (defconstant +g-priority-default+ 0 "Use this for default priority event sources. In GLib this priority is used when adding timeout functions with g_timeout_add(). In GDK this priority is used for events from the X server.")
203 (defconstant +g-priority-high-idle+ 100 "Use this for high priority idle functions. GTK+ uses @variable{+g-priority-high-idle+} + 10 for resizing operations, and @variable{+g-priority-high-idle+} + 20 for redrawing operations. (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)")
204 (defconstant +g-priority-default-idle+ 200 "Use this for default priority idle functions. In GLib this priority is used when adding idle functions with g_idle_add().")
205 (defconstant +g-priority-low+ 300 "Use this for very low priority background tasks. It is not used within GLib or GTK+.")
207 (defcfun (g-main-context-new "g_main_context_new" :library glib) (:pointer g-main-context))
209 (defcfun (g-main-context-ref "g_main_context_ref" :library glib) (:pointer g-main-context)
210 (context (:pointer g-main-context)))
212 (defcfun (g-main-context-unref "g_main_context_unref" :library glib) (:pointer g-main-context)
213 (context (:pointer g-main-context)))
215 (defcfun (g-main-context-default "g_main_context_default" :library glib) (:pointer g-main-context))
217 (defcfun (g-main-context-iteration "g_main_context_iteration" :library glib) :boolean
218 (context (:pointer g-main-context))
219 (may-block :boolean))
221 (defcfun (g-main-context-pending "g_main_context_pending" :library glib) :boolean
222 (context (:pointer g-main-context)))
224 (defcfun (g-main-context-find-source-by-id "g_main_context_find_source_by_id" :library glib) (:pointer g-source)
225 (context (:pointer g-main-context))
228 (defcfun (g-main-context-find-source-by-user-data "g_main_context_find_source_by_user_data" :library glib) (:pointer g-source)
229 (context (:pointer g-main-context))
230 (user-data :pointer))
232 (defcfun (g-main-context-find-source-by-funcs-user-data "g_main_context_find_source_by_funcs_user_data" :library glib) (:pointer g-source)
233 (context (:pointer g-main-context))
234 (funcs (:pointer g-source-funcs))
235 (user-data :pointer))
237 (defcfun (g-main-context-wakeup "g_main_context_wakeup" :library glib) :void
238 (context (:pointer g-main-context)))
240 (defcfun (g-main-context-acquire "g_main_context_acquire" :library glib) :boolean
241 (context (:pointer g-main-context)))
243 (defcfun (g-main-context-release "g_main_context_release" :library glib) :void
244 (context (:pointer g-main-context)))
246 (defcfun (g-main-context-is-owner "g_main_context_is_owner" :library glib) :boolean
247 (context (:pointer g-main-context)))
249 (defcfun (g-main-context-wait "g_main_context_wait" :library glib) :boolean
250 (context (:pointer g-main-context))
251 (cond (:pointer g-cond))
252 (mutex (:pointer g-mutex)))
254 (defcfun (g_main_context_prepare "g_main_context_prepare" :library glib) :boolean
255 (context (:pointer g-main-context))
256 (priority-ret (:pointer :int)))
258 (defcfun (g_main_context_query "g_main_context_query" :library glib) :int
259 (context (:pointer g-main-context))
261 (timeout-ret (:pointer :int))
262 (fds-ret (:pointer g-poll-fd))
265 (defcfun (g-main-context-check "g_main_context_check" :library glib) :int
266 (context (:pointer g-main-context))
268 (fds (:pointer g-poll-fd))
271 (defcfun (g-main-context-dispatch "g_main_context_dispatch" :library glib) :void
272 (context (:pointer g-main-context)))
274 (defcfun (g-main-context-set-poll-func "g_main_context_set_poll_func" :library glib) :void
275 (context (:pointer g-main-context))
278 (defcfun (g-main-context-get-poll-func "g_main_context_get_poll_func" :library glib) :pointer
279 (context (:pointer g-main-context)))
281 (defcfun (g-main-context-add-poll "g_main_context_add_poll" :library glib) :void
282 (context (:pointer g-main-context))
283 (fd (:pointer g-poll-fd))
286 (defcfun (g-main-context-remove-poll "g_main_context_remove_poll" :library glib) :void
287 (context (:pointer g-main-context))
288 (fd (:pointer g-poll-fd)))
290 (defcfun (g-main-depth "g_main_depth" :library glib) :int)
292 (defcfun (g-main-current-source "g_main_current_source" :library glib) (:pointer g-source))
294 (defcfun (g-timeout-source-new "g_timeout_source_new" :library glib) (:pointer g-source)
295 (interval-milliseconds :int))
297 (defcfun (g-timeout-source-new-seconds "g_timeout_source_new_seconds" :library glib) (:pointer g-source)
298 (interval-seconds :int))
300 (defcfun (g-timeout-add "g_timeout_add" :library glib) :uint
301 (interval-milliseconds :uint)
305 (defcfun (g-timeout-add-full "g_timeout_add_full" :library glib) :uint
307 (interval-milliseconds :uint)
310 (destroy-notify :pointer))
312 (defcfun (g-timeout-add-seconds "g_timeout_add_seconds" :library glib) :uint
313 (interval-seconds :uint)
317 (defcfun (g-timeout-add-seconds-full "g_timeout_add_seconds_full" :library glib) :uint
319 (interval-seconds :uint)
322 (destroy-notify :pointer))
324 (defcfun (g-idle-source-new "g_idle_source_new" :library glib) (:pointer g-source))
326 (defcfun (g-idle-add "g_idle_add" :library glib) :uint
330 (defcfun (g-idle-add-full "g_idle_add_full" :library glib) :uint
331 "A low-level function for adding callbacks to be called from main loop. Wrapper around g_idle_add_full.
332 Adds a function to be called whenever there are no higher priority events pending. If the function returns FALSE it is automatically removed from the list of event sources and will not be called again.
333 @arg[priority]{an integer specifying the priority. See @variable{+g-priority-default+}, @variable{+g-priority-default-idle+}, @variable{+g-priority-high+}, @variable{+g-priority-high-idle+}, @variable{+g-priority-low+}.}
334 @arg[function]{pointer to callback that will be called. Callback should accept a single pointer argument and return a boolean FALSE if it should be removed}
335 @arg[data]{pointer that will be passed to callback function}
336 @arg[notify]{function that will be called when callback is no more needed. It will receive the @code{data} argument}"
342 (defcfun (g-idle-remove-by-data "g_idle_remove_by_data" :library glib) :boolean
345 ;(defctype g-pid :int) ;;TODO: might work on amd64 linux, but on others
347 ;; Omitted GPid, g_child_add_watch, g_child_add_watch_full
349 (defcfun (g-source-new "g_source_new" :library glib) (:pointer g-source)
350 (source-funcs (:pointer g-source-funcs))
353 (defcfun (g-source-ref "g_source_ref" :library glib) (:pointer g-source)
354 (source (:pointer g-source)))
356 (defcfun (g-source-unref "g_source_unref" :library glib) :void
357 (source (:pointer g-source)))
359 (defcfun (g-source-set-funcs "g_source_set_funcs" :library glib) :void
360 (source (:pointer g-source))
361 (funcs (:pointer g-source-funcs)))
363 (defcfun (g-source-attach "g_source_attach" :library glib) :uint
364 (source (:pointer g-source))
365 (context (:pointer g-main-context)))
367 (defcfun (g-source-destroy "g_source_destroy" :library glib) :void
368 (source (:pointer g-source)))
370 (defcfun (g-source-is-destroyed "g_source_is_destroyed" :library glib) :boolean
371 (source (:pointer g-source)))
373 (defcfun (g-source-set-priority "g_source_set_priority" :library glib) :void
374 (source (:pointer g-source))
377 (defcfun (g-source-get-priority "g_source_get_priority" :library glib) :int
378 (source (:pointer g-source)))
380 (defcfun (g-source-set-can-recurse "g_source_set_can_recurse" :library glib) :void
381 (source (:pointer g-source))
382 (can-recurse :boolean))
384 (defcfun (g-source-get-can-recurse "g_source_get_can_recurse" :library glib) :boolean
385 (source (:pointer g-source)))
387 (defcfun (g-source-get-id "g_source_get_id" :library glib) :uint
388 (source (:pointer g-source)))
390 (defcfun (g-source-get-context "g_source_get_context" :library glib) (:pointer g-main-context)
391 (source (:pointer g-source)))
393 (defcfun (g-source-set-callback "g_source_set_callback" :library glib) :void
394 (source (:pointer g-source))
399 (defcfun (g-source-add-poll "g_source_add_poll" :library glib) :void
400 (source (:pointer g-source))
401 (fd (:pointer g-poll-fd)))
403 (defcfun (g-source-remove-poll "g_source_remove_poll" :library glib) :void
404 (source (:pointer g-source))
405 (fd (:pointer g-poll-fd)))
407 (defcfun (g-source-get-current-time "g_source_get_current_time" :library glib) :void
408 (source (:pointer g-source))
409 (timeval-ret (:pointer g-time-val)))
411 (defcfun (g-source-remove "g_source_remove" :library glib) :boolean
414 (defcfun (g-source-remove-by-funcs-user-data "g_source_remove_by_funcs_user_data" :library glib) :boolean
415 (funcs (:pointer g-source-funcs))
418 (defcfun (g-source-remove-by-user-data "g_source_remove_by_user_data" :library glib) :boolean
422 ;; Core Application Support - Threads
425 (defcenum g-thread-error
426 :g-thread-error-again)
428 ;omitted: struct GThreadFunctions
430 (defcfun (g-thread-init "g_thread_init") :void
433 (defcfun g-thread-get-initialized :boolean)
436 (unless (g-thread-get-initialized)
437 (g-thread-init (null-pointer))))
439 (defcenum g-thread-priority
440 :g-thread-priority-low
441 :g-thread-priority-normal
442 :g-thread-priority-hight
443 :g-thread-priority-urgent)
445 ;omitted: g_thread_create, g_thread_create_full, g_thread_yield, g_thread_exit, g_thread_foreach
447 (defcfun (g-thread-self "g_thread_self" :library glib) (:pointer g-thread))
449 (defcfun (g-thread-join "g_thread_join" :library glib) :pointer
450 (thread (:pointer g-thread)))
452 (defcfun (g-thread-priority "g_thread_set_priority" :library glib) :void
453 (thread (:pointer g-thread))
454 (priority g-thread-priority))
456 ;;;; TODO: Commented g_mutex_*, g_cond* because they are not functions, but called through dispatch table
458 ;; (defcfun (g-mutex-new "g_mutex_new" :library glib) (:pointer g-mutex))
460 ;; (defcfun (g-mutex-lock "g_mutex_lock" :library glib) :void
461 ;; (mutex (:pointer g-mutex)))
463 ;; (defcfun (g-mutex-try-lock "g_mutex_trylock" :library glib) :boolean
464 ;; (mutex (:pointer g-mutex)))
466 ;; (defcfun (g-mutex-free "g_mutex_free" :library glib) :void
467 ;; (mutex (:pointer g-mutex)))
469 ;omitted: GStaticMutex, GStaticRWLock stuff
471 ;; (defcfun (g-cond-new "g_cond_new" :library glib) (:pointer g-cond))
473 ;; (defcfun (g-cond-signal "g_cond_signal" :library glib) :void
474 ;; (cond (:pointer g-cond)))
476 ;; (defcfun (g-cond-broadcast "g_cond_broadcast" :library glib) :void
477 ;; (cond (:pointer g-cond)))
479 ;; (defcfun (g-cond-wait "g_cond_wait" :library glib) :void
480 ;; (cond (:pointer g-cond))
481 ;; (mutex (:pointer g-mutex)))
483 ;; (defcfun (g-cond-timed-wait "g_cond_timed_wait" :library glib) :boolean
484 ;; (cond (:pointer g-cond))
485 ;; (mutex (:pointer g-mutex))
486 ;; (abs-time (:pointer g-time-val)))
488 ;; (defcfun (g-cond-free "g_cond_free" :library glib) :void
489 ;; (cond (:pointer g-cond)))
491 ;omitted: GPrivate, GOnce stuff
493 ;omitted: Thread pools, Asynchronous queues, Dynamic Loading of Modules,
494 ; Memory Allocation, IO Channels, Error Reporting, Message Output and Debugging Functions, Message Logging
496 (defcfun g-free :void
497 "@arg[ptr]{pointer previously obtained with @fun{g-malloc} or with g_malloc C function}
498 Frees the pointer by calling g_free on it."
501 (defcfun (g-malloc "g_malloc0") :pointer
502 "@arg[n-bytes]{an integer}
503 @return{pointer to beginning of allocated memory}
504 Allocates the specified number of bytes in memory. Calls g_malloc.
508 (defcfun g-strdup :pointer
509 "@arg[str]{a @class{string}}
510 @return{foreign pointer to new string}
511 Allocates a new string that is equal to @code{str}. Use @fun{g-free} to free it."
512 (str (:string :free-to-foreign t)))
514 ;omitted all GLib Utilites
515 ;TODO: omitted Date and Time Functions