As I can never resist digging in to the “too deep”, I came up with a simple function to schedule a callback via GCD…
[code]Sub setDispatch(nanosecondsFromNow as uint64,context as ptr, callback as ptr)
declare Function dispatch_time lib “/usr/lib/libSystem.B.dylib” (when as uint64,delta as uint64) as uint64
declare Function dispatch_get_global_queue lib “/usr/lib/libSystem.B.dylib” (ID as int32,flags as integer) as ptr
declare sub dispatch_after_f lib “/usr/lib/libSystem.B.dylib” (when as uint64,queue as ptr,context as ptr,work as ptr)
dim dispatch as ptr=dispatch_get_global_queue(2,0)
dim when as uint64=dispatch_time(0,nanosecondsFromNow)
dispatch_after_f(when,dispatch,context,callback)
End Sub
[/code]
The callback is a shared or global that has one parameter, context as ptr. You can pass a memoryblock, just be sure the memoryblock doesn’t go out of scope before the callback fires or you’ll get garbage.
Also be sure to add #Pragma StackOverflowChecking false
to the callback or it will crash (not the case using the main queue).
Call it like:
setDispatch(1000000,context,AddressOf doDispatch)
Using a global queue with highest priority gets accuracy of less than a millisecond here vs 2-3 with the main queue.
In your usage I would store a base time value and add the offsets to schedule the callbacks. The memoryblocks would contain the midi data that needs to be sent at that point in time. This way you can queue up the data and not need to do any calculations in the sending code, just send whats in the context memoryblock and maybe set display values to be used by an update timer.