{{{ (in-package "CCL") (eval-when (:load-toplevel :execute) (open-shared-library "/System/Library/Frameworks/DiskArbitration.framework/DiskArbitration")) (eval-when (:compile-toplevel :load-toplevel :execute) (use-interface-dir :cocoa) (load "ccl:cocoa-ide;lib;cf-utils")) (defcallback disk-appeared (:address disk-ref :address context :void) (declare (ignore context)) (let* ((dict (external-call "DADiskCopyDescription" :address disk-ref #>CFDictionaryRef))) (with-cfstring (key "DAVolumeName") (let ((name (#_CFDictionaryGetValue dict key))) (format t "~&disk ~s appeared~%" (if (%null-ptr-p name) "(null)" (%get-cfstring name))))) (#_CFRelease dict))) (defcallback disk-disappeared (:address disk-ref :address context :void) (declare (ignore context)) (let* ((dict (external-call "DADiskCopyDescription" :address disk-ref #>CFDictionaryRef))) (with-cfstring (key "DAVolumeName") (let ((name (#_CFDictionaryGetValue dict key))) (format t "~&disk ~s disappeared~%" (if (%null-ptr-p name) "(null)" (%get-cfstring name))))) (#_CFRelease dict))) (defun disk-watcher () (let ((session (external-call "DASessionCreate" :address +null-ptr+ :address))) (external-call "DARegisterDiskAppearedCallback" :address session :address +null-ptr+ :address disk-appeared :address +null-ptr+) (external-call "DARegisterDiskDisappearedCallback" :address session :address +null-ptr+ :address disk-disappeared :address +null-ptr+) (external-call "DASessionScheduleWithRunLoop" :address session :address (#_CFRunLoopGetCurrent) :address #&kCFRunLoopDefaultMode) ;; this blocks (#_CFRunLoopRun) (#_CFRelease session))) (defparameter *disk-watcher-run-loop* nil) (defun run-disk-watcher () (process-run-function "disk watcher" #'(lambda () (setq *disk-watcher-run-loop* (#_CFRunLoopGetCurrent)) (disk-watcher) (setq *disk-watcher-run-loop* nil)))) (defun stop-disk-watcher () (#_CFRunLoopStop *disk-watcher-run-loop*)) }}}