Compare commits
No commits in common. "c1d00decc95ce6f8d442da6d3b4c188dc39e3327" and "2d8533d122ad83e28416b8964d1e0469f9c642c1" have entirely different histories.
c1d00decc9
...
2d8533d122
|
@ -1,46 +0,0 @@
|
|||
import std/[logging, strformat]
|
||||
import jacket
|
||||
|
||||
var
|
||||
jclient: ClientP
|
||||
status: cint
|
||||
descs: ptr UncheckedArray[Description]
|
||||
|
||||
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
|
||||
|
||||
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
|
||||
|
||||
addHandler(log)
|
||||
setErrorFunction(errorCb)
|
||||
jclient = clientOpen("jacket_property", NullOption.ord, status.addr)
|
||||
debug "JACK server status: " & $status
|
||||
|
||||
if jclient == nil:
|
||||
error getJackStatusErrorString(status)
|
||||
quit 1
|
||||
|
||||
let numDescs = getAllProperties(descs)
|
||||
|
||||
if numDescs != -1:
|
||||
var desc: Description
|
||||
|
||||
for i in 0..<numDescs:
|
||||
desc = descs[i]
|
||||
echo fmt"Subject: {desc.subject}"
|
||||
|
||||
if desc.property_cnt > 0:
|
||||
for p in 0..<desc.property_cnt:
|
||||
var prop = desc.properties[p]
|
||||
echo fmt"* {prop.key}: {prop.data} (type: {prop.type})"
|
||||
|
||||
echo ""
|
||||
freeDescription(desc.addr, 0)
|
||||
|
||||
free(descs)
|
||||
else:
|
||||
error "Could not get properties!"
|
||||
|
||||
discard jclient.clientClose
|
|
@ -1,125 +0,0 @@
|
|||
import std/[logging, os, strutils]
|
||||
import signal
|
||||
import jacket
|
||||
|
||||
var
|
||||
jclient: ClientP
|
||||
event: MidiEvent
|
||||
midiPort: PortP
|
||||
midiEventChan: Channel[MidiEvent]
|
||||
midiEventPrinter: Thread[void]
|
||||
status: cint
|
||||
exitSignalled: bool = false
|
||||
|
||||
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
|
||||
|
||||
|
||||
proc cleanup() =
|
||||
debug "Cleaning up..."
|
||||
|
||||
if jclient != nil:
|
||||
debug "Deactivating JACK client..."
|
||||
discard jclient.deactivate()
|
||||
|
||||
if midiEventPrinter.running:
|
||||
debug "Stopping MIDI event printer thread..."
|
||||
# Receiving an invalid event causes receiving thread to wake up and
|
||||
# break its endless loop
|
||||
event.size = 0
|
||||
midiEventChan.send(event)
|
||||
|
||||
midiEventPrinter.joinThread()
|
||||
|
||||
debug "Closing MIDI event channel..."
|
||||
midiEventChan.close()
|
||||
|
||||
if jclient != nil:
|
||||
debug "Closing JACK client..."
|
||||
discard jclient.clientClose()
|
||||
jclient = nil
|
||||
|
||||
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() =
|
||||
var event: MidiEvent
|
||||
|
||||
while true:
|
||||
event = midiEventChan.recv()
|
||||
|
||||
if event.size == 0:
|
||||
break
|
||||
elif event.size <= 3:
|
||||
for i in 0..<event.size:
|
||||
stdout.write(event.buffer[i].toHex)
|
||||
stdout.write("h ")
|
||||
|
||||
stdout.write("\n")
|
||||
stdout.flushFile()
|
||||
|
||||
proc processCb*(nFrames: NFrames, arg: pointer): cint {.cdecl.} =
|
||||
let inbuf = portGetBuffer(midiPort, nFrames)
|
||||
let count = midiGetEventCount(inbuf)
|
||||
|
||||
for i in 0..<count:
|
||||
if midiEventGet(event.addr, inbuf, i.uint32) == 0:
|
||||
if not midiEventChan.trySend(event):
|
||||
warn "MIDI event channel overflow!"
|
||||
|
||||
proc main() =
|
||||
addHandler(log)
|
||||
|
||||
# Create JACK client
|
||||
setErrorFunction(errorCb)
|
||||
jclient = clientOpen("jacket_midi_print", NoStartServer.ord or UseExactName.ord, status.addr)
|
||||
debug "JACK server status: " & $status
|
||||
|
||||
if jclient == nil:
|
||||
error getJackStatusErrorString(status)
|
||||
quit QuitFailure
|
||||
|
||||
# Set up signal handlers to clean up on exit
|
||||
when defined(windows):
|
||||
setSignalProc(signalCb, SIGABRT, SIGINT, SIGTERM)
|
||||
else:
|
||||
setSignalProc(signalCb, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGTERM)
|
||||
|
||||
# Set up a thread, which receives MIDI events from process callback via a
|
||||
# Channel and prints them without danger of blocking the process callback
|
||||
midiEventChan.open()
|
||||
createThread(midiEventPrinter, midiEventPrinterProc)
|
||||
|
||||
# Register JACK callbacks
|
||||
if jclient.setProcessCallback(processCb, nil) != 0:
|
||||
error "Could not set JACK process callback function."
|
||||
cleanup()
|
||||
quit QuitFailure
|
||||
|
||||
jclient.onShutdown(shutdownCb, nil)
|
||||
|
||||
# Create output port
|
||||
midiPort = jclient.portRegister("midi_in", JACK_DEFAULT_MIDI_TYPE, PortIsInput.ord, 0)
|
||||
|
||||
# Activate JACK client ...
|
||||
if jclient.activate() == 0:
|
||||
# ... and keep running until a signal is received
|
||||
while not exitSignalled:
|
||||
sleep(200)
|
||||
|
||||
cleanup()
|
||||
|
||||
|
||||
when isMainModule:
|
||||
main()
|
135
src/jacket.nim
135
src/jacket.nim
|
@ -77,7 +77,7 @@ type
|
|||
ClientZombie = 0x1000
|
||||
|
||||
type
|
||||
PortFlags* {.size: sizeof(culong) pure.} = enum
|
||||
JackPortFlags* {.size: sizeof(culong) pure.} = enum
|
||||
PortIsInput = 0x01,
|
||||
PortIsOutput = 0x02,
|
||||
PortIsPhysical = 0x04,
|
||||
|
@ -85,7 +85,7 @@ type
|
|||
PortIsTerminal = 0x10
|
||||
|
||||
type
|
||||
LatencyCallbackMode* {.size: sizeof(cint) pure.} = enum
|
||||
JackLatencyCallbackMode* {.size: sizeof(cint) pure.} = enum
|
||||
CaptureLatency,
|
||||
PlaybackLatency
|
||||
|
||||
|
@ -167,54 +167,31 @@ const
|
|||
EXTENDED_TIME_INFO* = true
|
||||
JACK_TICK_DOUBLE* = true
|
||||
|
||||
# Metadata
|
||||
|
||||
type
|
||||
Property* = object
|
||||
key*: cstring
|
||||
data*: cstring
|
||||
`type`*: cstring
|
||||
|
||||
PropertyChange* {.size: sizeof(cint).} = enum
|
||||
PropertyCreated,
|
||||
PropertyChanged,
|
||||
PropertyDeleted
|
||||
|
||||
Description* = object
|
||||
subject*: Uuid
|
||||
property_cnt*: uint32
|
||||
properties*: ptr UncheckedArray[Property]
|
||||
property_size*: uint32
|
||||
|
||||
DescriptionP* = ptr Description
|
||||
|
||||
# Callback function types
|
||||
|
||||
type
|
||||
ProcessCallback* = proc (nframes: NFrames; arg: pointer): cint {.cdecl.}
|
||||
ThreadCallback* = proc (arg: pointer): pointer {.cdecl.}
|
||||
ThreadInitCallback* = proc (arg: pointer) {.cdecl.}
|
||||
GraphOrderCallback* = proc (arg: pointer): cint {.cdecl.}
|
||||
XRunCallback* = proc (arg: pointer): cint {.cdecl.}
|
||||
BufferSizeCallback* = proc (nframes: NFrames; arg: pointer): cint {.cdecl.}
|
||||
SampleRateCallback* = proc (nframes: NFrames; arg: pointer): cint {.cdecl.}
|
||||
PortRegistrationCallback* = proc (port: PortId; flag: cint; arg: pointer) {.cdecl.}
|
||||
ClientRegistrationCallback* = proc (name: cstring; flag: cint; arg: pointer) {.cdecl.}
|
||||
PortConnectCallback* = proc (portA: PortId; portB: PortId; connect: cint; arg: pointer) {.cdecl.}
|
||||
PortRenameCallback* = proc (port: PortId; oldName: cstring; newName: cstring; arg: pointer) {.cdecl.}
|
||||
FreewheelCallback* = proc (starting: cint; arg: pointer) {.cdecl.}
|
||||
ShutdownCallback* = proc (arg: pointer) {.cdecl.}
|
||||
InfoShutdownCallback* = proc (code: JackStatus; reason: cstring; arg: pointer) {.cdecl.}
|
||||
LatencyCallback* = proc (mode: LatencyCallbackMode; arg: pointer) {.cdecl.}
|
||||
InfoCallback* = proc (msg: cstring) {.cdecl.}
|
||||
ErrorCallback* = proc (msg: cstring) {.cdecl.}
|
||||
JackProcessCallback* = proc (nframes: NFrames; arg: pointer): cint {.cdecl.}
|
||||
JackThreadCallback* = proc (arg: pointer): pointer {.cdecl.}
|
||||
JackThreadInitCallback* = proc (arg: pointer) {.cdecl.}
|
||||
JackGraphOrderCallback* = proc (arg: pointer): cint {.cdecl.}
|
||||
JackXRunCallback* = proc (arg: pointer): cint {.cdecl.}
|
||||
JackBufferSizeCallback* = proc (nframes: NFrames; arg: pointer): cint {.cdecl.}
|
||||
JackSampleRateCallback* = proc (nframes: NFrames; arg: pointer): cint {.cdecl.}
|
||||
JackPortRegistrationCallback* = proc (port: PortId; flag: cint; arg: pointer) {.cdecl.}
|
||||
JackClientRegistrationCallback* = proc (name: cstring; flag: cint; arg: pointer) {.cdecl.}
|
||||
JackPortConnectCallback* = proc (portA: PortId; portB: PortId; connect: cint; arg: pointer) {.cdecl.}
|
||||
JackPortRenameCallback* = proc (port: PortId; oldName: cstring; newName: cstring; arg: pointer) {.cdecl.}
|
||||
JackFreewheelCallback* = proc (starting: cint; arg: pointer) {.cdecl.}
|
||||
JackShutdownCallback* = proc (arg: pointer) {.cdecl.}
|
||||
JackInfoShutdownCallback* = proc (code: JackStatus; reason: cstring; arg: pointer) {.cdecl.}
|
||||
JackLatencyCallback* = proc (mode: JackLatencyCallbackMode; arg: pointer) {.cdecl.}
|
||||
JackInfoCallback* = proc (msg: cstring) {.cdecl.}
|
||||
JackErrorCallback* = proc (msg: cstring) {.cdecl.}
|
||||
|
||||
SyncCallback* = proc (state: TransportState; pos: ptr Position; arg: pointer): cint {.cdecl.}
|
||||
TimebaseCallback* = proc (state: TransportState; nframes: NFrames; pos: ptr Position; newPos: cint;
|
||||
JackSyncCallback* = proc (state: TransportState; pos: ptr Position; arg: pointer): cint {.cdecl.}
|
||||
JackTimebaseCallback* = proc (state: TransportState; nframes: NFrames; pos: ptr Position; newPos: cint;
|
||||
arg: pointer) {.cdecl.}
|
||||
|
||||
PropertyChangeCallback* = proc (subject: Uuid, key: cstring, change: PropertyChange, arg: pointer) {.cdecl.}
|
||||
|
||||
|
||||
# ----------------------------- Version info ------------------------------
|
||||
|
||||
|
@ -296,51 +273,51 @@ proc cycleSignal*(client: ClientP; status: cint) {.importc: "jack_cycle_signal".
|
|||
|
||||
# ------------------------------- Callbacks -------------------------------
|
||||
|
||||
proc setProcessThread*(client: ClientP; threadCallback: ThreadCallback; arg: pointer): cint {.
|
||||
proc setProcessThread*(client: ClientP; threadCallback: JackThreadCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_process_thread".}
|
||||
|
||||
proc setThreadInitCallback*(client: ClientP; threadInitCallback: ThreadInitCallback; arg: pointer): cint {.
|
||||
proc setThreadInitCallback*(client: ClientP; threadInitCallback: JackThreadInitCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_thread_init_callback".}
|
||||
|
||||
proc onShutdown*(client: ClientP; shutdownCallback: ShutdownCallback; arg: pointer) {.
|
||||
proc onShutdown*(client: ClientP; shutdownCallback: JackShutdownCallback; arg: pointer) {.
|
||||
importc: "jack_on_shutdown".}
|
||||
|
||||
proc onInfoShutdown*(client: ClientP; shutdownCallback: InfoShutdownCallback; arg: pointer) {.
|
||||
proc onInfoShutdown*(client: ClientP; shutdownCallback: JackInfoShutdownCallback; arg: pointer) {.
|
||||
importc: "jack_on_info_shutdown".}
|
||||
|
||||
proc setProcessCallback*(client: ClientP; processCallback: ProcessCallback; arg: pointer): cint {.
|
||||
proc setProcessCallback*(client: ClientP; processCallback: JackProcessCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_process_callback".}
|
||||
|
||||
proc setFreewheelCallback*(client: ClientP; freewheelCallback: FreewheelCallback; arg: pointer): cint {.
|
||||
proc setFreewheelCallback*(client: ClientP; freewheelCallback: JackFreewheelCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_freewheel_callback".}
|
||||
|
||||
proc setBufferSizeCallback*(client: ClientP; bufsizeCallback: BufferSizeCallback; arg: pointer): cint {.
|
||||
proc setBufferSizeCallback*(client: ClientP; bufsizeCallback: JackBufferSizeCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_buffer_size_callback".}
|
||||
|
||||
proc setSampleRateCallback*(client: ClientP; srateCallback: SampleRateCallback; arg: pointer): cint {.
|
||||
proc setSampleRateCallback*(client: ClientP; srateCallback: JackSampleRateCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_sample_rate_callback".}
|
||||
|
||||
proc setClientRegistrationCallback*(client: ClientP; registrationCallback: ClientRegistrationCallback;
|
||||
proc setClientRegistrationCallback*(client: ClientP; registrationCallback: JackClientRegistrationCallback;
|
||||
arg: pointer): cint {.
|
||||
importc: "jack_set_client_registration_callback".}
|
||||
|
||||
proc setPortRegistrationCallback*(client: ClientP; registrationCallback: PortRegistrationCallback;
|
||||
proc setPortRegistrationCallback*(client: ClientP; registrationCallback: JackPortRegistrationCallback;
|
||||
arg: pointer): cint {.
|
||||
importc: "jack_set_port_registration_callback".}
|
||||
|
||||
proc setPortConnectCallback*(client: ClientP; connectCallback: PortConnectCallback; arg: pointer): cint {.
|
||||
proc setPortConnectCallback*(client: ClientP; connectCallback: JackPortConnectCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_port_connect_callback".}
|
||||
|
||||
proc setPortRenameCallback*(client: ClientP; renameCallback: PortRenameCallback; arg: pointer): cint {.
|
||||
proc setPortRenameCallback*(client: ClientP; renameCallback: JackPortRenameCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_port_rename_callback".}
|
||||
|
||||
proc setGraphOrderCallback*(client: ClientP; graphCallback: GraphOrderCallback; a3: pointer): cint {.
|
||||
proc setGraphOrderCallback*(client: ClientP; graphCallback: JackGraphOrderCallback; a3: pointer): cint {.
|
||||
importc: "jack_set_graph_order_callback".}
|
||||
|
||||
proc setXrunCallback*(client: ClientP; xrunCallback: XRunCallback; arg: pointer): cint {.
|
||||
proc setXrunCallback*(client: ClientP; xrunCallback: JackXRunCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_xrun_callback".}
|
||||
|
||||
proc setLatencyCallback*(client: ClientP; latencyCallback: LatencyCallback; arg: pointer): cint {.
|
||||
proc setLatencyCallback*(client: ClientP; latencyCallback: JackLatencyCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_latency_callback".}
|
||||
|
||||
|
||||
|
@ -589,7 +566,7 @@ proc getTime*(): Time {.importc: "jack_get_time".}
|
|||
proc releaseTimebase*(client: ClientP): cint {.importc: "jack_release_timebase".}
|
||||
|
||||
# int jack_set_sync_callback (jack_client_t *client, JackSyncCallback sync_callback, void *arg)
|
||||
proc setSyncCallback*(client: ClientP; syncCallback: SyncCallback; arg: pointer): cint {.
|
||||
proc setSyncCallback*(client: ClientP; syncCallback: JackSyncCallback; arg: pointer): cint {.
|
||||
importc: "jack_set_sync_callback".}
|
||||
|
||||
# int jack_set_sync_timeout (jack_client_t *client, jack_time_t timeout)
|
||||
|
@ -599,7 +576,7 @@ proc setSyncTimeout*(client: ClientP; timeout: Time): cint {.importc: "jack_set_
|
|||
# int conditional,
|
||||
# JackTimebaseCallback timebase_callback,
|
||||
# void *arg)
|
||||
proc setTimebaseCallback*(client: ClientP; conditional: cint; timebaseCallback: TimebaseCallback;
|
||||
proc setTimebaseCallback*(client: ClientP; conditional: cint; timebaseCallback: JackTimebaseCallback;
|
||||
arg: pointer): cint {.
|
||||
importc: "jack_set_timebase_callback".}
|
||||
|
||||
|
@ -626,46 +603,14 @@ void jack_get_transport_info (jack_client_t *client, jack_transport_info_t *tinf
|
|||
void jack_set_transport_info (jack_client_t *client, jack_transport_info_t *tinfo)
|
||||
]#
|
||||
|
||||
# ------------------------------- Metadata --------------------------------
|
||||
|
||||
# int jack_set_property (jack_client_t*, jack_uuid_t subject, const char* key, const char* value, const char* type)
|
||||
proc setProperty*(client: ClientP, subject: Uuid, key, value, `type`: cstring): cint {.importc: "jack_set_property".}
|
||||
|
||||
# int jack_get_property (jack_uuid_t subject, const char* key, char** value, char** type)
|
||||
proc getProperty*(subject: Uuid, key: cstring, value, `type`: ptr cstring): cint {.importc: "jack_get_property".}
|
||||
|
||||
# void jack_free_description (jack_description_t* desc, int free_description_itself)
|
||||
proc freeDescription*(desc: DescriptionP, freeDescriptionItself: cint) {.importc: "jack_free_description".}
|
||||
|
||||
# int jack_get_properties (jack_uuid_t subject, jack_description_t* desc)
|
||||
proc getProperties*(subject: Uuid, desc: DescriptionP): cint {.importc: "jack_get_properties".}
|
||||
|
||||
# int jack_get_all_properties (jack_description_t** descs)
|
||||
proc getAllProperties*(descs: var ptr UncheckedArray[Description]): cint {.importc: "jack_get_all_properties".}
|
||||
|
||||
# int jack_remove_property (jack_client_t* client, jack_uuid_t subject, const char* key)
|
||||
proc removeProperty*(client: ClientP, subject: Uuid): cint {.importc: "jack_remove_property".}
|
||||
|
||||
# int jack_remove_properties (jack_client_t* client, jack_uuid_t subject)
|
||||
proc removeProperties*(client: ClientP, subject: Uuid): cint {.importc: "jack_remove_properties".}
|
||||
|
||||
# int jack_remove_all_properties (jack_client_t* client)
|
||||
proc removeAllProperties*(client: ClientP): cint {.importc: "jack_remove_all_properties".}
|
||||
|
||||
# int jack_set_property_change_callback (jack_client_t* client, JackPropertyChangeCallback callback, void* arg)
|
||||
proc setPropertyChangeCallback*(client: ClientP, callback: PropertyChangeCallback, arg: pointer): cint {.
|
||||
importc: "jack_set_property_change_callback".}
|
||||
|
||||
|
||||
# ---------------------------- Error handling -----------------------------
|
||||
|
||||
proc setErrorFunction*(errorCallback: ErrorCallback) {.importc: "jack_set_error_function".}
|
||||
proc setErrorFunction*(errorCallback: JackErrorCallback) {.importc: "jack_set_error_function".}
|
||||
|
||||
proc setInfoFunction*(infoCallback: InfoCallback) {.importc: "jack_set_info_function".}
|
||||
proc setInfoFunction*(infoCallback: JackInfoCallback) {.importc: "jack_set_info_function".}
|
||||
|
||||
{.pop.}
|
||||
|
||||
|
||||
# --------------------------- Helper functions ----------------------------
|
||||
|
||||
proc getJackStatusErrorString*(status: cint): string =
|
||||
|
|
Loading…
Reference in New Issue