Compare commits

...

6 Commits

Author SHA1 Message Date
Christopher Arndt 2d8533d122 feat: wrap transport API and add transport query example
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2023-05-22 19:58:43 +02:00
Christopher Arndt ada9b13857 fix: use fixed-size integer types for custom types
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2023-05-22 19:58:43 +02:00
Christopher Arndt e06f62da8c docs: for deprecated functions/types show original C decl in comment
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2023-05-22 19:58:43 +02:00
Christopher Arndt 309e45e22a refactor: various formatting tweaks
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2023-05-22 19:58:43 +02:00
Christopher Arndt 08c05c71d4 refactor: remove superfluous semicolons from end of comments
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2023-05-22 19:58:43 +02:00
Christopher Arndt 5c4af1a90a feat: wrap MIDI API and add example MIDI client
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2023-05-22 19:58:43 +02:00
4 changed files with 416 additions and 113 deletions

View File

@ -7,10 +7,10 @@ A [Nim] wrapper for the [JACK] [C API]
This software is in *alpha status* and has no official release yet.
The basic JACK APIs (client lifecycle, ports, callbacks) have been wrapped and
are functional (see [examples]), but MIDI, transport and meta-data APIs still
need wrapping. Also, symbol names may still be changed and things moved around
before the first public release.
The basic JACK APIs (client lifecycle, ports, callbacks, MIDI, transport) have
been wrapped and are functional (see [examples]), but latency, threading and
meta-data APIs still need wrapping. Also, symbol names may still be changed
and things moved around before the first public release.
Also, I plan to add a higher-level abstraction on top of the direct mapping
from Nim procs and types to C functions and types, probably in the form of

View File

@ -0,0 +1,89 @@
import std/[logging, os, strutils]
import signal
import jacket
var jclient: ClientP
var event: MidiEvent
var midiPort: PortP
var status: cint
var exitSignalled: bool = false
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
proc cleanup() =
debug "Cleaning up..."
if jclient != nil:
discard jclient.deactivate()
discard jclient.clientClose()
jclient = nil
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 printMidiEvent(event: var MidiEvent) =
if 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:
printMidiEvent(event)
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)
# 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(50)
cleanup()
when isMainModule:
main()

View File

@ -0,0 +1,54 @@
import std/[logging, strformat]
import jacket
var
jclient: ClientP
status: cint
pos: Position
transportState: TransportState
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_info", NullOption.ord, status.addr)
debug "JACK server status: " & $status
if jclient == nil:
error getJackStatusErrorString(status)
quit 1
transportState = transportQuery(jclient, pos.addr)
echo fmt"usecs: {pos.usecs}"
echo fmt"frameRate: {pos.frameRate}"
echo fmt"frame: {pos.frame}"
echo fmt"valid: {pos.valid.ord}"
if bool(pos.valid.ord and PositionBBT.ord):
echo fmt"bar: {pos.bar}"
echo fmt"beat: {pos.beat}"
echo fmt"tick: {pos.tick}"
echo fmt"barStartTick: {pos.barStartTick}"
echo fmt"beatsPerBar: {pos.beatsPerBar}"
echo fmt"beatType: {pos.beatType}"
echo fmt"beatsPerMinute: {pos.beatsPerMinute}"
case transportState
of TransportStopped:
echo "JACK transport stopped, starting it now."
transportStart(jclient)
of TransportRolling:
echo "JACK transport rolling, stopping it now."
transportStop(jclient)
of TransportStarting:
echo "JACK transport starting, nothing to do."
else:
echo "Unknown JACK transport state."
discard jclient.clientClose

View File

@ -24,14 +24,15 @@ const
JACK_DEFAULT_AUDIO_TYPE* = "32 bit float mono audio"
JACK_DEFAULT_MIDI_TYPE* = "8 bit raw midi"
# ----------------------------- Custom Types ------------------------------
type
Time* = culonglong
NFrames* = culong
Uuid* = culonglong
PortId* = culong
PortTypeId* = culong
Time* = uint64
NFrames* = uint32
Uuid* = uint64
PortId* = uint32
PortTypeId* = uint32
DefaultAudioSample* = cfloat
type
@ -40,6 +41,14 @@ type
Port = distinct object
PortP* = ptr Port
type
MidiData* = uint8
MidiEvent* = object
time*: NFrames
size*: csize_t
buffer*: ptr UncheckedArray[MidiData]
MidiEventP* = ptr MidiEvent
type
JackOptions* {.size: sizeof(cint) pure.} = enum
NullOption = 0x00,
@ -69,10 +78,10 @@ type
type
JackPortFlags* {.size: sizeof(culong) pure.} = enum
PortIsInput = 0x1,
PortIsOutput = 0x2,
PortIsPhysical = 0x4,
PortCanMonitor = 0x8,
PortIsInput = 0x01,
PortIsOutput = 0x02,
PortIsPhysical = 0x04,
PortCanMonitor = 0x08,
PortIsTerminal = 0x10
type
@ -80,7 +89,86 @@ type
CaptureLatency,
PlaybackLatency
# Transport
type
PositionBits* {.size: sizeof(cint).} = enum
PositionBBT = 0x10,
PositionTimecode = 0x20,
BBTFrameOffset = 0x40,
AudioVideoRatio = 0x80,
VideoFrameOffset = 0x100,
TickDouble = 0x200
TransportState* {.size: sizeof(cint).} = enum
TransportStopped = 0,
TransportRolling = 1,
TransportLooping = 2,
TransportStarting = 3,
TransportNetStarting = 4
type
Position* = object
unique1*: uint64
usecs*: Time
frameRate*: NFrames
frame*: NFrames
valid*: PositionBits
bar*: int32
beat*: int32
tick*: int32
barStartTick*: cdouble
beatsPerBar*: cfloat
beatType*: cfloat
ticksPerBeat*: cdouble
beatsPerMinute*: cdouble
frameTime*: cdouble
nextTime*: cdouble
bbtOffset*: NFrames
audioFramesPerVideoFrame*: cfloat
videoOffset*: NFrames
tickDouble*: cdouble
padding*: array[5, int32]
unique2*: uint64
PositionP* = ptr Position
#[ DEPRECATED
typedef enum {
JackTransportState = 0x1,
JackTransportPosition = 0x2,
JackTransportLoop = 0x4,
JackTransportSMPTE = 0x8,
JackTransportBBT = 0x10
} jack_transport_bits_t;
typedef struct {
jack_nframes_t frame_rate;
jack_time_t usecs;
jack_transport_bits_t valid;
jack_transport_state_t transport_state;
jack_nframes_t frame;
jack_nframes_t loop_start;
jack_nframes_t loop_end;
long smpte_offset
float smpte_frame_rate;
int bar;
int beat;
int tick;
double bar_start_tick;
float beats_per_bar;
float beat_type;
double ticks_per_beat;
double beats_per_minute;
} jack_transport_info_t;
]#
const
JACK_POSITION_MASK* = (PositionBBT.ord or PositionTimecode.ord)
EXTENDED_TIME_INFO* = true
JACK_TICK_DOUBLE* = true
# Callback function types
type
JackProcessCallback* = proc (nframes: NFrames; arg: pointer): cint {.cdecl.}
JackThreadCallback* = proc (arg: pointer): pointer {.cdecl.}
@ -100,19 +188,23 @@ type
JackInfoCallback* = proc (msg: cstring) {.cdecl.}
JackErrorCallback* = proc (msg: cstring) {.cdecl.}
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.}
# ----------------------------- Version info ------------------------------
# void jack_get_version(int *major_ptr, int *minor_ptr, int *micro_ptr, int *proto_ptr) ;
# void jack_get_version(int *major_ptr, int *minor_ptr, int *micro_ptr, int *proto_ptr)
proc getVersion*(major: ptr cint; minor: ptr cint; micro: ptr cint; proto: ptr cint) {.importc: "jack_get_version".}
# const char * jack_get_version_string(void) ;
# const char * jack_get_version_string(void)
proc getVersionString*(): cstring {.importc: "jack_get_version_string".}
# --------------------------- Memory management ---------------------------
# void jack_free(void* ptr) ;
# void jack_free(void* ptr)
proc free*(`ptr`: pointer) {.importc: "jack_free".}
@ -120,29 +212,28 @@ proc free*(`ptr`: pointer) {.importc: "jack_free".}
# jack_client_t * jack_client_open (char *client_name,
# jack_options_t options,
# jack_status_t *status, ...) ;
# jack_status_t *status, ...)
proc clientOpen*(clientName: cstring; options: cint; status: ptr cint): ClientP {.
varargs, importc: "jack_client_open".}
# DEPRECATED
# proc clientNew*(clientName: cstring): ClientP {.importc: "jack_client_new".}
#[ DEPRECATED
jack_client_t * jack_client_new (const char *client_name)
]#
# int jack_client_close (jack_client_t *client) ;
# int jack_client_close (jack_client_t *client)
proc clientClose*(client: ClientP): cint {.importc: "jack_client_close"}
# int jack_client_name_size (void) ;
# int jack_client_name_size (void)
proc clientNameSize*(): cint {.importc: "jack_client_name_size"}
# char * jack_get_client_name (jack_client_t *client) ;
# char * jack_get_client_name (jack_client_t *client)
proc getClientName*(client: ClientP): cstring {.importc: "jack_get_client_name".}
# char *jack_get_uuid_for_client_name (jack_client_t *client,
# const char *client_name) ;
# char *jack_get_uuid_for_client_name (jack_client_t *client, const char *client_name)
proc getUuidForClientName*(client: ClientP; clientName: cstring): cstring {.
importc: "jack_get_uuid_for_client_name".}
# char *jack_get_client_name_by_uuid (jack_client_t *client,
# const char *client_uuid ) ;
# char *jack_get_client_name_by_uuid (jack_client_t *client, const char *client_uuid)
proc getClientNameByUuid*(client: ClientP; clientUuid: cstring): cstring {.
importc: "jack_get_client_name_by_uuid".}
@ -153,31 +244,30 @@ proc internalClientNew*(clientName: cstring; loadName: cstring; loadInit: cstrin
proc internalClientClose*(clientName: cstring) {.importc: "jack_internal_client_close".}
]#
# int jack_activate (jack_client_t *client) ;
# int jack_activate (jack_client_t *client)
proc activate*(client: ClientP): cint {.importc: "jack_activate".}
# int jack_deactivate (jack_client_t *client) ;
# int jack_deactivate (jack_client_t *client)
proc deactivate*(client: ClientP): cint {.importc: "jack_deactivate".}
# int jack_get_client_pid (const char *name) ;
# int jack_get_client_pid (const char *name)
proc getClientPid*(name: cstring): cint {.importc: "jack_get_client_pid".}
# FIXME: not implemented yet
# jack_native_thread_t jack_client_thread_id (jack_client_t *client) ;
# proc clientThreadId*(client: ClientP): NativeThread {.
# importc: "jack_client_thread_id".}
# jack_native_thread_t jack_client_thread_id (jack_client_t *client)
# proc clientThreadId*(client: ClientP): NativeThread {.importc: "jack_client_thread_id".}
# int jack_is_realtime (jack_client_t *client) ;
# int jack_is_realtime (jack_client_t *client)
proc isRealtime*(client: ClientP): cint {.importc: "jack_is_realtime".}
# DEPRECATED
# proc threadWait*(client: ClientP; status: cint): NFrames {.
# importc: "jack_thread_wait".}
#[ DEPRECATED
jack_nframes_t jack_thread_wait (jack_client_t *client, int status)
]#
# jack_nframes_t jack_cycle_wait (jack_client_t* client) ;
# jack_nframes_t jack_cycle_wait (jack_client_t* client)
proc cycleWait*(client: ClientP): NFrames {.importc: "jack_cycle_wait".}
# void jack_cycle_signal (jack_client_t* client, int status) ;
# void jack_cycle_signal (jack_client_t* client, int status)
proc cycleSignal*(client: ClientP; status: cint) {.importc: "jack_cycle_signal".}
@ -233,23 +323,23 @@ proc setLatencyCallback*(client: ClientP; latencyCallback: JackLatencyCallback;
# -------------------------- Server Client Control ------------------------
# int jack_set_freewheel(jack_client_t* client, int onoff) ;
# int jack_set_freewheel(jack_client_t* client, int onoff)
proc setFreewheel*(client: ClientP; onoff: cint): cint {.importc: "jack_set_freewheel".}
# int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) ;
# int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes)
proc setBufferSize*(client: ClientP; nframes: NFrames): cint {.importc: "jack_set_buffer_size".}
#jack_nframes_t jack_get_sample_rate (jack_client_t *) ;
#jack_nframes_t jack_get_sample_rate (jack_client_t *)
proc getSampleRate*(client: ClientP): NFrames {.importc: "jack_get_sample_rate".}
# jack_nframes_t jack_get_buffer_size (jack_client_t *) ;
# jack_nframes_t jack_get_buffer_size (jack_client_t *)
proc getBufferSize*(client: ClientP): NFrames {.importc: "jack_get_buffer_size".}
# DEPRECATED
# proc engineTakeoverTimebase*(a1: ClientP): cint {.
# importc: "jack_engine_takeover_timebase".}
#[ DEPRECATED
int jack_engine_takeover_timebase (jack_client_t *)
]#
# float jack_cpu_load (jack_client_t *client) ;
# float jack_cpu_load (jack_client_t *client)
proc cpuLoad*(client: ClientP): cfloat {.importc: "jack_cpu_load".}
@ -259,133 +349,176 @@ proc cpuLoad*(client: ClientP): cfloat {.importc: "jack_cpu_load".}
# const char *port_name,
# const char *port_type,
# unsigned long flags,
# unsigned long buffer_size) ;
# unsigned long buffer_size)
proc portRegister*(client: ClientP; portName: cstring; portType: cstring;
flags: culong; bufferSize: culong): PortP {.importc: "jack_port_register".}
# int jack_port_unregister (jack_client_t *client, jack_port_t *port) ;
# int jack_port_unregister (jack_client_t *client, jack_port_t *port)
proc portUnregister*(client: ClientP; port: PortP): cint {.importc: "jack_port_unregister".}
# void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t) ;
# void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t)
proc portGetBuffer*(port: PortP; nframes: NFrames): pointer {.importc: "jack_port_get_buffer".}
# jack_uuid_t jack_port_uuid (const jack_port_t *port) ;
# jack_uuid_t jack_port_uuid (const jack_port_t *port)
proc portUuid*(port: PortP): Uuid {.importc: "jack_port_uuid".}
# const char * jack_port_name (const jack_port_t *port) ;
# const char * jack_port_name (const jack_port_t *port)
proc portName*(port: PortP): cstring {.importc: "jack_port_name".}
# const char * jack_port_short_name (const jack_port_t *port) ;
# const char * jack_port_short_name (const jack_port_t *port)
proc portShortName*(port: PortP): cstring {.importc: "jack_port_short_name".}
# int jack_port_flags (const jack_port_t *port) ;
# int jack_port_flags (const jack_port_t *port)
proc portFlags*(port: PortP): cint {.importc: "jack_port_flags".}
# const char * jack_port_type (const jack_port_t *port) ;
# const char * jack_port_type (const jack_port_t *port)
proc portType*(port: PortP): cstring {.importc: "jack_port_type".}
# jack_port_type_id_t jack_port_type_id (const jack_port_t *port) ;
# jack_port_type_id_t jack_port_type_id (const jack_port_t *port)
proc portTypeId*(port: PortP): PortTypeId {.importc: "jack_port_type_id".}
# int jack_port_is_mine (const jack_client_t *client, const jack_port_t *port) ;
# int jack_port_is_mine (const jack_client_t *client, const jack_port_t *port)
proc portIsMine*(client: ClientP; port: PortP): cint {.
importc: "jack_port_is_mine".}
# int jack_port_connected (const jack_port_t *port) ;
# int jack_port_connected (const jack_port_t *port)
proc portConnected*(port: PortP): cint {.importc: "jack_port_connected".}
# int jack_port_connected_to (const jack_port_t *port,
# const char *port_name) ;
# const char *port_name)
proc portConnectedTo*(port: PortP; portName: cstring): cint {.importc: "jack_port_connected_to".}
# const char ** jack_port_get_connections (const jack_port_t *port) ;
# const char ** jack_port_get_connections (const jack_port_t *port)
#
# CAVEAT: The caller is responsible for calling jack_free() on any non-NULL
# returned value.
# CAVEAT: The caller is responsible for calling jack_free() on any non-NULL returned value.
proc portGetConnections*(port: PortP): cstringArray {.importc: "jack_port_get_connections".}
# const char ** jack_port_get_all_connections (const jack_client_t *client,
# const jack_port_t *port) ;
# const jack_port_t *port)
#
# CAVEAT: The caller is responsible for calling jack_free() on any non-NULL
# returned value.
# CAVEAT: The caller is responsible for calling jack_free() on any non-NULL returned value.
proc portGetAllConnections*(client: ClientP; port: PortP): cstringArray {.
importc: "jack_port_get_all_connections".}
#[ DEPRECATED
proc portTie*(src: PortP; dst: PortP): cint {.importc: "jack_port_tie".}
int jack_port_tie (jack_port_t *src, jack_port_t *dst)
proc portUntie*(port: PortP): cint {.importc: "jack_port_untie".}
int jack_port_untie (jack_port_t *port)
proc portSetName*(port: PortP; portName: cstring): cint {.importc: "jack_port_set_name".}
int jack_port_set_name (jack_port_t *port, const char *port_name)
]#
# int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port_name) ;
# int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port_name)
proc portRename*(client: ClientP; port: PortP; portName: cstring): cint {.importc: "jack_port_rename".}
# int jack_port_set_alias (jack_port_t *port, const char *alias) ;
# int jack_port_set_alias (jack_port_t *port, const char *alias)
proc portSetAlias*(port: PortP; alias: cstring): cint {.importc: "jack_port_set_alias".}
# int jack_port_unset_alias (jack_port_t *port, const char *alias) ;
# int jack_port_unset_alias (jack_port_t *port, const char *alias)
proc portUnsetAlias*(port: PortP; alias: cstring): cint {.importc: "jack_port_unset_alias".}
# int jack_port_get_aliases (const jack_port_t *port, char* const aliases[2]) ;
# int jack_port_get_aliases (const jack_port_t *port, char* const aliases[2])
proc portGetAliases*(port: PortP; aliases: array[2, cstring]): cint {.importc: "jack_port_get_aliases".}
#int jack_port_request_monitor (jack_port_t *port, int onoff) ;
#int jack_port_request_monitor (jack_port_t *port, int onoff)
proc portRequestMonitor*(port: PortP; onoff: cint): cint {.importc: "jack_port_request_monitor".}
# int jack_port_request_monitor_by_name (jack_client_t *client,
# const char *port_name, int onoff) ;
# const char *port_name, int onoff)
proc portRequestMonitorByName*(client: ClientP; portName: cstring; onoff: cint): cint {.
importc: "jack_port_request_monitor_by_name".}
# int jack_port_ensure_monitor (jack_port_t *port, int onoff) ;
# int jack_port_ensure_monitor (jack_port_t *port, int onoff)
proc portEnsureMonitor*(port: PortP; onoff: cint): cint {.
importc: "jack_port_ensure_monitor".}
# int jack_port_monitoring_input (jack_port_t *port) ;
# int jack_port_monitoring_input (jack_port_t *port)
proc portMonitoringInput*(port: PortP): cint {.importc: "jack_port_monitoring_input".}
# ------------------------------ Port Lookup ------------------------------
# const char ** jack_get_ports (jack_client_t *client,
# const char *port_name_pattern,
# const char *type_name_pattern,
# unsigned long flags)
#
# CAVEAT: The caller is responsible for calling jack_free() on any non-NULL returned value.
proc getPorts*(client: ClientP; portNamePattern: cstring;
typeNamePattern: cstring; flags: culong): cstringArray {.importc: "jack_get_ports".}
# jack_port_t * jack_port_by_name (jack_client_t *client, const char *port_name)
proc portByName*(client: ClientP; portName: cstring): PortP {.importc: "jack_port_by_name".}
# jack_port_t * jack_port_by_id (jack_client_t *client, jack_port_id_t port_id)
proc portById*(client: ClientP; portId: PortId): PortP {.importc: "jack_port_by_id".}
# ------------------------------ Connections ------------------------------
# int jack_connect (jack_client_t *client,
# const char *source_port,
# const char *destination_port) ;
# const char *destination_port)
proc connect*(client: ClientP; srcPort: cstring; destPort: cstring): cint {.importc: "jack_connect".}
# int jack_disconnect (jack_client_t *client,
# const char *source_port,
# const char *destination_port) ;
# const char *destination_port)
proc disconnect*(client: ClientP; srcPort: cstring; destPort: cstring): cint {.importc: "jack_disconnect".}
# int jack_port_disconnect (jack_client_t *client, jack_port_t *port) ;
# int jack_port_disconnect (jack_client_t *client, jack_port_t *port)
proc portDisconnect*(client: ClientP; port: PortP): cint {.importc: "jack_port_disconnect".}
# int jack_port_name_size(void) ;
# int jack_port_name_size(void)
proc portNameSize*(): cint {.importc: "jack_port_name_size".}
# int jack_port_type_size(void) ;
# int jack_port_type_size(void)
proc portTypeSize*(): cint {.importc: "jack_port_type_size".}
# size_t jack_port_type_get_buffer_size (jack_client_t *client, const char *port_type) ;
# size_t jack_port_type_get_buffer_size (jack_client_t *client, const char *port_type)
proc portTypeGetBufferSize*(client: ClientP; portType: cstring): csize_t {.
importc: "jack_port_type_get_buffer_size".}
# --------------------------------- MIDI ----------------------------------
# jack_nframes_t jack_midi_get_event_count (void *port_buffer)
proc midiGetEventCount*(portBuffer: pointer): NFrames {.importc: "jack_midi_get_event_count".}
# int jack_midi_event_get (jack_midi_event_t *event, void *port_buffer, uint32_t event_index)
proc midiEventGet*(event: MidiEventP, portBuffer: pointer, eventIndex: uint32): cint {.
importc: "jack_midi_event_get".}
# void jack_midi_clear_buffer (void *port_buffer)
proc midiClearBuffer*(portBuffer: pointer) {.importc: "jack_midi_clear_buffer".}
# size_t jack_midi_max_event_size (void *port_buffer)
proc midiMaxEventSize*(portBuffer: pointer): csize_t {.importc: "jack_midi_max_event_size".}
# jack_midi_data_t * jack_midi_event_reserve (void *port_buffer, jack_nframes_t time, size_t data_size)
proc midiEventReserve*(portBuffer: pointer, time: NFrames, dataSize: csize_t): ptr MidiData {.
importc: "jack_midi_event_reserve".}
# int jack_midi_event_write (void *port_buffer, jack_nframes_t time, const jack_midi_data_t *data, size_t data_size)
proc midiEventWrite*(portBuffer: pointer, time: NFrames, data: ptr MidiData, dataSize: csize_t): int {.
importc: "jack_midi_event_write".}
# uint32_t jack_midi_get_lost_event_count (void *port_buffer)
proc midiGetLostEventCount*(portBuffer: pointer): uint32 {.importc: "jack_midi_get_lost_event_count".}
# -------------------------------- Latency --------------------------------
#[ FIXME: not implemented yet
# void jack_port_set_latency (jack_port_t *port, jack_nframes_t) ;
# void jack_port_set_latency (jack_port_t *port, jack_nframes_t)
proc portSetLatency*(port: PortP; a2: NFrames) {.importc: "jack_port_set_latency".}
#[ FIXME: not implemented yet
# void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) ;
# void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
proc portGetLatencyRange*(port: PortP; mode: LatencyCallbackMode;
range: ptr LatencyRange) {.importc: "jack_port_get_latency_range".}
proc portSetLatencyRange*(port: PortP; mode: LatencyCallbackMode;
range: ptr LatencyRange) {.importc: "jack_port_set_latency_range".}
]#
proc recomputeTotalLatencies*(client: ClientP): cint {.importc: "jack_recompute_total_latencies".}
@ -396,53 +529,80 @@ proc portGetTotalLatency*(client: ClientP; port: PortP): NFrames {.importc: "jac
proc recomputeTotalLatency*(a1: ClientP; port: PortP): cint {.importc: "jack_recompute_total_latency".}
]#
# ------------------------------ Port Lookup ------------------------------
# const char ** jack_get_ports (jack_client_t *client,
# const char *port_name_pattern,
# const char *type_name_pattern,
# unsigned long flags) ;
#
# CAVEAT: The caller is responsible for calling jack_free() on any non-NULL
# returned value.
proc getPorts*(client: ClientP; portNamePattern: cstring;
typeNamePattern: cstring; flags: culong): cstringArray {.importc: "jack_get_ports".}
# jack_port_t * jack_port_by_name (jack_client_t *client, const char *port_name) ;
proc portByName*(client: ClientP; portName: cstring): PortP {.importc: "jack_port_by_name".}
# jack_port_t * jack_port_by_id (jack_client_t *client, jack_port_id_t port_id) ;
proc portById*(client: ClientP; portId: PortId): PortP {.importc: "jack_port_by_id".}
# ----------------------------- Time handling -----------------------------
# jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *) ;
# jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *)
proc framesSinceCycleStart*(client: ClientP): NFrames {.importc: "jack_frames_since_cycle_start".}
# jack_nframes_t jack_frame_time (const jack_client_t *) ;
# jack_nframes_t jack_frame_time (const jack_client_t *)
proc frameTime*(client: ClientP): NFrames {.importc: "jack_frame_time".}
# jack_nframes_t jack_last_frame_time (const jack_client_t *client) ;
# jack_nframes_t jack_last_frame_time (const jack_client_t *client)
proc lastFrameTime*(client: ClientP): NFrames {.importc: "jack_last_frame_time".}
# int jack_get_cycle_times(const jack_client_t *client,
# jack_nframes_t *current_frames,
# jack_time_t *current_usecs,
# jack_time_t *next_usecs,
# float *period_usecs) ;
# float *period_usecs)
proc getCycleTimes*(client: ClientP; currentFrames: ptr NFrames;
currentUsecs: ptr Time; nextUsecs: ptr Time;
periodUsecs: ptr cfloat): cint {.importc: "jack_get_cycle_times".}
# jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t) ;
# jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t)
proc framesToTime*(client: ClientP; nframes: NFrames): Time {.importc: "jack_frames_to_time".}
# jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t) ;
# jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t)
proc timeToFrames*(client: ClientP; time: Time): NFrames {.importc: "jack_time_to_frames".}
# jack_time_t jack_get_time(void) ;
# jack_time_t jack_get_time(void)
proc getTime*(): Time {.importc: "jack_get_time".}
# ------------------------------- Transport -------------------------------
# int jack_release_timebase (jack_client_t *client)
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: JackSyncCallback; arg: pointer): cint {.
importc: "jack_set_sync_callback".}
# int jack_set_sync_timeout (jack_client_t *client, jack_time_t timeout)
proc setSyncTimeout*(client: ClientP; timeout: Time): cint {.importc: "jack_set_sync_timeout".}
# int jack_set_timebase_callback (jack_client_t *client,
# int conditional,
# JackTimebaseCallback timebase_callback,
# void *arg)
proc setTimebaseCallback*(client: ClientP; conditional: cint; timebaseCallback: JackTimebaseCallback;
arg: pointer): cint {.
importc: "jack_set_timebase_callback".}
# int jack_transport_locate (jack_client_t *client, jack_nframes_t frame)
proc transportLocate*(client: ClientP; frame: NFrames): cint {.importc: "jack_transport_locate".}
# jack_transport_state_t jack_transport_query (const jack_client_t *client, jack_position_t *pos)
proc transportQuery*(client: ClientP; pos: PositionP): TransportState {.importc: "jack_transport_query".}
# jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client)
proc getCurrentTransportFrame*(client: ClientP): NFrames {.importc: "jack_get_current_transport_frame".}
# int jack_transport_reposition (jack_client_t *client, const jack_position_t *pos)
proc transportReposition*(client: ClientP; pos: PositionP): cint {.importc: "jack_transport_reposition".}
# void jack_transport_start (jack_client_t *client)
proc transportStart*(client: ClientP) {.importc: "jack_transport_start".}
# void jack_transport_stop (jack_client_t *client)
proc transportStop*(client: ClientP) {.importc: "jack_transport_stop".}
#[ DEPRECATED
void jack_get_transport_info (jack_client_t *client, jack_transport_info_t *tinfo)
void jack_set_transport_info (jack_client_t *client, jack_transport_info_t *tinfo)
]#
# ---------------------------- Error handling -----------------------------
proc setErrorFunction*(errorCallback: JackErrorCallback) {.importc: "jack_set_error_function".}