diff --git a/examples/jacket_midi_print_ringbuffer.nim b/examples/jacket_midi_print_ringbuffer.nim new file mode 100644 index 0000000..f0e7342 --- /dev/null +++ b/examples/jacket_midi_print_ringbuffer.nim @@ -0,0 +1,156 @@ +# This requires either nim 1.9+ or --threads:on: + +import std/[locks, logging, os, strformat] +import signal +import jacket + +var + jclient: ClientP + event: MidiEvent + midiPort: PortP + rb: RingbufferP + midiEventPrinter: Thread[void] + status: cint + exitSignalled: bool = false + exitLoop: bool = false + overruns: uint = 0 + dataReady: Cond + dataReadyLock: Lock + +let rbSize = 128 + +var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug) +addHandler(log) + + +proc cleanup() = + debug "Cleaning up..." + + if jclient != nil: + debug "Deactivating JACK client..." + discard jclient.deactivate() + + if midiEventPrinter.running: + debug "Stopping MIDI event printer thread..." + exitLoop = true + if dataReadyLock.tryAcquire(): + dataReady.signal() + dataReadyLock.release() + + debug "Joining MIDI event printer thread..." + midiEventPrinter.joinThread() + debug "Joined." + + if jclient != nil: + debug "Closing JACK client..." + discard jclient.clientClose() + jclient = nil + + debug fmt"Buffer overruns: {overruns}" + debug "Bye." + +proc errorCb(msg: cstring) {.cdecl.} = + # Suppress verbose JACK error messages when server is not available by + # default. Pass ``lvlAll`` when creating the logger to enable them. + debug "JACK error: " & $msg + +proc signalCb(sig: cint) {.noconv.} = + info "Received signal: " & $sig + exitSignalled = true + +proc shutdownCb(arg: pointer = nil) {.cdecl.} = + info "JACK server has shut down." + exitSignalled = true + +proc midiEventPrinterProc() {.thread.} = + var recvBuf: array[4, uint8] + + dataReadyLock.acquire() + + while not exitLoop: + while not exitLoop and ringbufferReadSpace(rb) >= 4: + var read = cast[int](ringbufferRead(rb, cast[cstring](recvBuf.addr), 4)) + + if recvBuf[0] <= 3: + for i in 0..