10e90099 |
(defpackage :objc.notification
(:use :cl )
(:export
#:main-loop-ticker
#:dnc
#:observe-notifications
|
1c7b674a |
#:*mailbox*
#:setup-notifications))
|
10e90099 |
(in-package :objc.notification)
(serapeum:eval-always
(named-readtables:in-readtable :objc-readtable))
(defun main-loop-ticker ()
(let ((main-run-loop [#@NSRunLoop @(mainRunLoop)]))
(loop do
(sleep 0.1)
(trivial-main-thread:with-body-in-main-thread (:blocking t)
(objc-runtime::tick-ns-runloop main-run-loop
0.1)))))
(defun dnc ()
[#@NSDistributedNotificationCenter
@(defaultCenter)])
(defvar *mailbox*)
(cffi:defcallback handle-notification :void
((_ :pointer) (__ :pointer) (notification :pointer))
(declare (ignore _ __))
(sb-concurrency:send-message
*mailbox*
(objc-runtime.data-extractors:extract-from-objc
[notification @(userInfo)])))
(defvar *notification-handler*)
|
1c7b674a |
(defun setup-notifications ()
|
10e90099 |
(if (boundp '*notification-handler*)
*notification-handler*
(let ((delegate-class
(objc-runtime::objc-allocate-class-pair
#@NSObject
(format nil "FWNotificationHandler~a"
(gensym))
0)))
(objc-runtime::class-add-method
delegate-class
@(handle-notification:)
(cffi:callback handle-notification)
"v@:@")
(setf *mailbox*
(sb-concurrency:make-mailbox)
*notification-handler*
[[delegate-class @(alloc)] @(init)]))))
(define-condition notifications-not-initialized (error)
())
(defun observe-notifications (dnc notification-name)
(tagbody start
(restart-case
(if (boundp '*notification-handler*)
[dnc @(addObserver:selector:name:object:)
:pointer *notification-handler*
:pointer @(handle-notification:)
:pointer (objc-runtime::make-nsstring
notification-name)
:pointer (cffi:null-pointer)]
(error 'notifications-not-initialized))
(setup-and-retry ()
|
1c7b674a |
(setup-notifications)
|
10e90099 |
(go start)))))
|