Compare commits

..

12 Commits

Author SHA1 Message Date
ca918769ec
[ci] feat: add GitHub actions workflows for building/testing/docs (#2)
* disable windows runner for now (chocolatey jack package is broken)
* install jack and pcre from homebrew for macOS workflow
* install libjack-jackd2-dev libpcre3-dev for linux workflow
* add additional libjack location candidate for macOS / homebrew
* make library name patterns const strings

Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2025-01-23 03:10:43 +01:00
f05bbbd294 fix: examples require threading package
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2025-01-23 02:58:11 +01:00
2c99d183ba fix: define SIGTERM on windows, since it is not exported by system/ansi_c there
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2025-01-22 23:13:01 +01:00
3b40310afd docs: minor readme tweaks and fixes
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2025-01-20 02:23:45 +01:00
3915638e73
feat: stream-line API and fix minor wrapping errors (#1)
* Rename types:
   * `ptr` types have no suffix (e.g. `ClientP` -> `Client`)
   * normal object types hyve a `T` suffix, if needed (e.g. `Port` -> `PortT`)
   * Constants also use CamelCase (UPPER_CASE can still be used).
* Make functions returning an error discardable
* Add missing return types for some functions.

Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2025-01-20 02:16:38 +01:00
1fa9a68ee6 refactor: use 'byte' instead of 'uint8' in ringbuffer example
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2025-01-20 00:10:31 +01:00
ad7014da09 Use proper exit status enum value 2024-05-21 18:15:51 +02:00
1444154ca4 fix: set import search path for examples, so that they don't use the installed version
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2024-05-15 00:02:37 +02:00
70c7782f5b feat: add passthru client example
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2024-05-15 00:01:39 +02:00
03d7471656 fix: remove superfluous import and global var
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2024-05-15 00:01:00 +02:00
9645542176 feat: implement converters for enums
Allows to pass enum values directly for cint/culong params

Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2024-05-14 23:47:13 +02:00
0bfb23b6ff docs: wording change in readme
Signed-off-by: Christopher Arndt <chris@chrisarndt.de>
2023-11-23 17:40:38 +01:00
19 changed files with 495 additions and 295 deletions

58
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,58 @@
name: Run tests and build examples
on: [push, pull_request]
env:
nim_version: "2.2.0"
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
#os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Check out sources
uses: actions/checkout@v4
- name: Nim Runtime Cache
id: cache-nim
uses: actions/cache@v4
with:
path: ".nim_runtime"
key: ${{ runner.os }}-nim-${{ env.nim_version }}
- name: Install Nim
id: install-nim
if: ${{ hashFiles('.nim_runtime/bin/nim*') == '' }}
uses: jiro4989/setup-nim-action@v2
with:
nim-version: ${{ env.nim_version }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Set PATH for Unix
if: ${{ runner.os != 'Windows' && steps.install-nim.outcome == 'skipped' }}
shell: bash
run: |
echo "$(pwd)/.nim_runtime/bin" >> "$GITHUB_PATH"
echo "$HOME/.nimble/bin" >> "$GITHUB_PATH"
- name: Set PATH for Windows
if: ${{ runner.os == 'Windows' && steps.install-nim.outcome == 'skipped' }}
shell: pwsh
run: |
echo "$(Get-Location)\.nim_runtime\bin" >> $Env:GITHUB_PATH
mkdir -Force ~\.nimble\bin
(Resolve-Path ~\.nimble\bin).Path >> $Env:GITHUB_PATH
- name: Install dependency packages (jack)
uses: ConorMacBride/install-package@v1
with:
brew: jack pcre
apt: libjack-jackd2-dev libpcre3-dev
choco: jack
- name: Update PATH (Windows)
if: runner.os == 'Windows'
run: Add-Content $env:GITHUB_PATH "C:\Program Files\jack\bin"
- name: Run tests
run: nimble test -y
- name: Build examples (debug)
run: nimble examples_debug
- name: Build examples (release)
run: nimble examples

26
.github/workflows/docs.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: Build and publish API docs
on:
push:
branches:
- master
env:
nim-version: "stable"
nim-src: src/jacket.nim
deploy-dir: .gh-pages
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jiro4989/setup-nim-action@v2
with:
nim-version: ${{ env.nim-version }}
- run: nimble install -y
- run: nimble doc --index:on --project --git.url:https://github.com/${{ github.repository }} --git.commit:master --out:${{ env.deploy-dir }} ${{ env.nim-src }}
- name: "Copy to index.html"
run: cp ${{ env.deploy-dir }}/jacket.html ${{ env.deploy-dir }}/index.html
- name: Deploy documents
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ${{ env.deploy-dir }}

View File

@ -1,17 +1,19 @@
# jacket # jacket
A [Nim] wrapper for the [JACK] client side [C API] aka *libjack*. A [Nim] wrapper for the JACK Audio Connection Kit ([JACK]) client side [C API]
aka **libjack**.
## Project status ## Project status
This software is in *beta status*. This software is in *beta status*.
The majority of JACK client APIs have been wrapped and are functional (see The majority of JACK client API functions have been wrapped and are functional
[examples]), but some APIs (e.g. threading) still need wrapping. Others, like (see [examples]), but some API parts (e.g. threading) still need wrapping.
the server control or the deprecated session API, will probably not be covered Others, like the server control or the deprecated session API, will probably
by these bindings. While this project is in beta stage, symbol names may still not be covered by these bindings. While this project is in beta stage, symbol
be changed and things moved around before the first public release. names may still be changed and things moved around before the first stable
release.
## Installation ## Installation
@ -19,7 +21,7 @@ be changed and things moved around before the first public release.
* Clone this repository. * Clone this repository.
* Change into the `jacket` directory. * Change into the `jacket` directory.
* Run [`nimble install`] (or `nimble develop`). * Run [`nimble install`] (or `nimble develop`).
* Run the [examples] with `nim compile --run examples/<example>.nim`. * Build the [examples] with `nimble examples`.
(Some examples need `--threads:on` with Nim < 2.0). (Some examples need `--threads:on` with Nim < 2.0).
@ -27,10 +29,9 @@ be changed and things moved around before the first public release.
## Usage ## Usage
Here is a very minimal JACK client application, which just passes audio through Here is a very minimal JACK client application, which just passes audio through
from its single input port to its output port. from its single input port to its output port. Any error checking and handling
has been omitted for brevity's sake. See the files in the [examples] directory
Any error checking and handling has been omitted for brevity's sake. See the for more robust example code.
files in the [examples] directory for more robust example code.
```nim ```nim
import std/os import std/os
@ -38,11 +39,11 @@ import system/ansi_c
import jacket import jacket
var var
jackClient: ClientP
status: cint status: cint
exitSignalled: bool = false exitSignalled = false
inpPort, outPort: PortP inpPort, outPort: Port
type JackBufferP = ptr UncheckedArray[DefaultAudioSample]
type SampleBuffer = ptr UncheckedArray[DefaultAudioSample]
proc signalCb(sig: cint) {.noconv.} = proc signalCb(sig: cint) {.noconv.} =
exitSignalled = true exitSignalled = true
@ -51,41 +52,41 @@ proc shutdownCb(arg: pointer = nil) {.cdecl.} =
exitSignalled = true exitSignalled = true
proc processCb(nFrames: NFrames, arg: pointer): cint {.cdecl.} = proc processCb(nFrames: NFrames, arg: pointer): cint {.cdecl.} =
var inpbuf = cast[JackBufferP](portGetBuffer(inpPort, nFrames)) let inpbuf = cast[SampleBuffer](portGetBuffer(inpPort, nFrames))
var outbuf = cast[JackBufferP](portGetBuffer(outPort, nFrames)) let outbuf = cast[SampleBuffer](portGetBuffer(outPort, nFrames))
# copy samples from input to output buffer # copy samples from input to output buffer
for i in 0 ..< nFrames: for i in 0 ..< nFrames:
outbuf[i] = inpbuf[i] outbuf[i] = inpbuf[i]
# Create JACK Client ptr # Create JACK Client ptr
jackClient = clientOpen("passthru", NullOption.ord, status.addr) var jackClient = clientOpen("passthru", NullOption, status.addr)
# Register audio input and output ports # Register audio input and output ports
inpPort = jackClient.portRegister("in_1", JACK_DEFAULT_AUDIO_TYPE, PortIsInput.ord, 0) inpPort = jackClient.portRegister("in_1", JackDefaultAudioType, PortIsInput, 0)
outPort = jackClient.portRegister("out_1", JACK_DEFAULT_AUDIO_TYPE, PortIsOutput.ord, 0) outPort = jackClient.portRegister("out_1", JackDefaultAudioType, PortIsOutput, 0)
# Set JACK callbacks # Set JACK callbacks
jackClient.onShutdown(shutdownCb) jackClient.onShutdown(shutdownCb)
discard jackClient.setProcessCallback(processCb, nil) jackClient.setProcessCallback(processCb, nil)
# Handle POSIX signals # Handle POSIX signals
c_signal(SIGINT, signalCb) c_signal(SIGINT, signalCb)
c_signal(SIGTERM, signalCb) c_signal(SIGTERM, signalCb)
# Activate JACK client ... # Activate JACK client ...
discard jackClient.activate() jackClient.activate()
while not exitSignalled: while not exitSignalled:
sleep(50) sleep(50)
discard jackClient.clientClose() jackClient.clientClose()
``` ```
## License ## License
This software is released under the *MIT License*. See the file This software is released under the **MIT License**. See the file
[LICENSE.md](./LICENSE.md) for more information. [LICENSE.md](./LICENSE.md) for more information.
Please note that the JACK client library (libjack), which this project wraps, Please note that the JACK client library (libjack), which this project wraps,
is licensed under the [LGPL-2.1]. This wrapper does not statically or is licensed under the [LGPL-2.1]. This wrapper does not statically or
dynamically link to libjack, but only loads it via the dynamic linker at dynamically link to libjack at build time, but only loads it via [dynlib] at
run-time. run-time.
Software using this wrapper is, in the opinion of its author, not considered a Software using this wrapper is, in the opinion of its author, not considered a
@ -96,11 +97,12 @@ professional legal counsel when in doubt.
## Author ## Author
*jacket* is written by [Christopher Arndt]. **jacket** is written by [Christopher Arndt].
[C API]: https://jackaudio.org/api/ [C API]: https://jackaudio.org/api/
[Christopher Arndt]: mailto:info@chrisarndt.de [Christopher Arndt]: mailto:info@chrisarndt.de
[dynlib]: https://nim-lang.org/docs/manual.html#foreign-function-interface-dynlib-pragma-for-import
[examples]: ./examples [examples]: ./examples
[JACK]: https://jackaudio.org/ [JACK]: https://jackaudio.org/
[LGPL-2.1]: https://spdx.org/licenses/LGPL-2.1-or-later.html [LGPL-2.1]: https://spdx.org/licenses/LGPL-2.1-or-later.html

View File

@ -5,13 +5,13 @@ var status: cint
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug) var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
proc errorCb(msg: cstring) {.cdecl.} = proc errorCb(msg: cstring) {.cdecl.} =
# Suppress verbose JACK error messages when server is not available by # Suppress verbose JACK error messages when server is not available by
# default. Pass ``lvlAll`` when creating the logger to enable them. # default. Pass ``lvlAll`` when creating the logger to enable them.
debug "JACK error: " & $msg debug "JACK error: " & $msg
addHandler(log) addHandler(log)
setErrorFunction(errorCb) setErrorFunction(errorCb)
var jclient = clientOpen("jacket_info", NullOption.ord, status.addr) var jclient = clientOpen("jacket_info", NullOption, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -26,4 +26,4 @@ echo("DSP load: ", jclient.cpuLoad, "%")
echo("Server time: ", getTime()) echo("Server time: ", getTime())
echo("Client name: ", jclient.getClientName) echo("Client name: ", jclient.getClientName)
discard jclient.clientClose jclient.clientClose()

View File

@ -3,18 +3,18 @@ import jacket
var var
status: cint status: cint
descs: ptr UncheckedArray[Description] descs: ptr UncheckedArray[DescriptionT]
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug) var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
proc errorCb(msg: cstring) {.cdecl.} = proc errorCb(msg: cstring) {.cdecl.} =
# Suppress verbose JACK error messages when server is not available by # Suppress verbose JACK error messages when server is not available by
# default. Pass ``lvlAll`` when creating the logger to enable them. # default. Pass ``lvlAll`` when creating the logger to enable them.
debug "JACK error: " & $msg debug "JACK error: " & $msg
addHandler(log) addHandler(log)
setErrorFunction(errorCb) setErrorFunction(errorCb)
let jclient = clientOpen("jacket_property", NullOption.ord, status.addr) let jclient = clientOpen("jacket_property", NullOption, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -40,4 +40,4 @@ if numDescs != -1:
else: else:
error "Could not get properties!" error "Could not get properties!"
discard jclient.clientClose jclient.clientClose()

View File

@ -2,9 +2,9 @@ import std/[logging, os, strutils]
import signal import signal
import jacket import jacket
var jclient: ClientP var jclient: Client
var event: MidiEvent var event: MidiEventT
var midiPort: PortP var midiPort: Port
var status: cint var status: cint
var exitSignalled: bool = false var exitSignalled: bool = false
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug) var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
@ -13,8 +13,8 @@ var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
proc cleanup() = proc cleanup() =
debug "Cleaning up..." debug "Cleaning up..."
if jclient != nil: if jclient != nil:
discard jclient.deactivate() jclient.deactivate()
discard jclient.clientClose() jclient.clientClose()
jclient = nil jclient = nil
proc errorCb(msg: cstring) {.cdecl.} = proc errorCb(msg: cstring) {.cdecl.} =
@ -30,7 +30,7 @@ proc shutdownCb(arg: pointer = nil) {.cdecl.} =
warn "JACK server has shut down." warn "JACK server has shut down."
exitSignalled = true exitSignalled = true
proc printMidiEvent(event: var MidiEvent) = proc printMidiEvent(event: var MidiEventT) =
if event.size <= 3: if event.size <= 3:
for i in 0..<event.size: for i in 0..<event.size:
stdout.write(event.buffer[i].toHex) stdout.write(event.buffer[i].toHex)
@ -52,7 +52,7 @@ proc main() =
# Create JACK client # Create JACK client
setErrorFunction(errorCb) setErrorFunction(errorCb)
jclient = clientOpen("jacket_midi_print", NoStartServer.ord or UseExactName.ord, status.addr) jclient = clientOpen("jacket_midi_print", NoStartServer or UseExactName, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -74,7 +74,7 @@ proc main() =
jclient.onShutdown(shutdownCb) jclient.onShutdown(shutdownCb)
# Create output port # Create output port
midiPort = jclient.portRegister("midi_in", JACK_DEFAULT_MIDI_TYPE, PortIsInput.ord, 0) midiPort = jclient.portRegister("midi_in", JackDefaultMidiType, PortIsInput, 0)
# Activate JACK client ... # Activate JACK client ...
if jclient.activate() == 0: if jclient.activate() == 0:

View File

@ -5,10 +5,10 @@ import signal
import jacket import jacket
var var
jclient: ClientP jclient: Client
event: MidiEvent event: MidiEventT
midiPort: PortP midiPort: Port
rb: RingbufferP rb: Ringbuffer
midiEventPrinter: Thread[void] midiEventPrinter: Thread[void]
status: cint status: cint
exitSignalled: bool = false exitSignalled: bool = false
@ -27,7 +27,7 @@ proc cleanup() =
if jclient != nil: if jclient != nil:
debug "Deactivating JACK client..." debug "Deactivating JACK client..."
discard jclient.deactivate() jclient.deactivate()
if midiEventPrinter.running: if midiEventPrinter.running:
debug "Stopping MIDI event printer thread..." debug "Stopping MIDI event printer thread..."
@ -42,7 +42,7 @@ proc cleanup() =
if jclient != nil: if jclient != nil:
debug "Closing JACK client..." debug "Closing JACK client..."
discard jclient.clientClose() jclient.clientClose()
jclient = nil jclient = nil
debug fmt"Buffer overruns: {overruns}" debug fmt"Buffer overruns: {overruns}"
@ -68,7 +68,7 @@ proc midiEventPrinterProc() {.thread.} =
while true: while true:
while not exitLoop and ringbufferReadSpace(rb) >= 4: while not exitLoop and ringbufferReadSpace(rb) >= 4:
var read = cast[int](ringbufferRead(rb, cast[cstring](recvBuf.addr), 4)) discard ringbufferRead(rb, cast[cstring](recvBuf.addr), 4)
if recvBuf[0] <= 3: if recvBuf[0] <= 3:
for i in 0..<recvBuf[0].int: for i in 0..<recvBuf[0].int:
@ -110,7 +110,7 @@ proc processCb*(nFrames: NFrames, arg: pointer): cint {.cdecl.} =
proc main() = proc main() =
# Create JACK client # Create JACK client
setErrorFunction(errorCb) setErrorFunction(errorCb)
jclient = clientOpen("jacket_midi_print", NoStartServer.ord or UseExactName.ord, status.addr) jclient = clientOpen("jacket_midi_print", NoStartServer or UseExactName, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -138,7 +138,7 @@ proc main() =
jclient.onShutdown(shutdownCb) jclient.onShutdown(shutdownCb)
# Create output port # Create output port
midiPort = jclient.portRegister("midi_in", JACK_DEFAULT_MIDI_TYPE, PortIsInput.ord, 0) midiPort = jclient.portRegister("midi_in", JackDefaultMidiType, PortIsInput, 0)
# Activate JACK client ... # Activate JACK client ...
if jclient.activate() == 0: if jclient.activate() == 0:

View File

@ -3,10 +3,9 @@ import signal
import jacket import jacket
var var
jclient: ClientP jclient: Client
event: MidiEvent midiPort: Port
midiPort: PortP midiEventChan: Channel[MidiEventT]
midiEventChan: Channel[MidiEvent]
midiEventPrinter: Thread[void] midiEventPrinter: Thread[void]
status: cint status: cint
exitSignalled: bool = false exitSignalled: bool = false
@ -19,13 +18,13 @@ proc cleanup() =
if jclient != nil: if jclient != nil:
debug "Deactivating JACK client..." debug "Deactivating JACK client..."
discard jclient.deactivate() jclient.deactivate()
if midiEventPrinter.running: if midiEventPrinter.running:
debug "Stopping MIDI event printer thread..." debug "Stopping MIDI event printer thread..."
# Receiving an invalid event causes receiving thread to wake up and # Receiving an invalid event causes receiving thread to wake up and
# break its endless loop # break its endless loop
event.size = 0 let event = MidiEventT(size: 0)
midiEventChan.send(event) midiEventChan.send(event)
midiEventPrinter.joinThread() midiEventPrinter.joinThread()
@ -35,7 +34,7 @@ proc cleanup() =
if jclient != nil: if jclient != nil:
debug "Closing JACK client..." debug "Closing JACK client..."
discard jclient.clientClose() jclient.clientClose()
jclient = nil jclient = nil
debug "Bye." debug "Bye."
@ -54,10 +53,8 @@ proc shutdownCb(arg: pointer = nil) {.cdecl.} =
exitSignalled = true exitSignalled = true
proc midiEventPrinterProc() = proc midiEventPrinterProc() =
var event: MidiEvent
while true: while true:
event = midiEventChan.recv() let event = midiEventChan.recv()
if event.size == 0: if event.size == 0:
break break
@ -70,6 +67,7 @@ proc midiEventPrinterProc() =
stdout.flushFile() stdout.flushFile()
proc processCb*(nFrames: NFrames, arg: pointer): cint {.cdecl.} = proc processCb*(nFrames: NFrames, arg: pointer): cint {.cdecl.} =
var event: MidiEventT
let inbuf = portGetBuffer(midiPort, nFrames) let inbuf = portGetBuffer(midiPort, nFrames)
let count = midiGetEventCount(inbuf) let count = midiGetEventCount(inbuf)
@ -83,7 +81,7 @@ proc main() =
# Create JACK client # Create JACK client
setErrorFunction(errorCb) setErrorFunction(errorCb)
jclient = clientOpen("jacket_midi_print", NoStartServer.ord or UseExactName.ord, status.addr) jclient = clientOpen("jacket_midi_print", NoStartServer or UseExactName, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -110,7 +108,7 @@ proc main() =
jclient.onShutdown(shutdownCb) jclient.onShutdown(shutdownCb)
# Create output port # Create output port
midiPort = jclient.portRegister("midi_in", JACK_DEFAULT_MIDI_TYPE, PortIsInput.ord, 0) midiPort = jclient.portRegister("midi_in", JackDefaultMidiType, PortIsInput, 0)
# Activate JACK client ... # Activate JACK client ...
if jclient.activate() == 0: if jclient.activate() == 0:

View File

@ -4,16 +4,15 @@
# nimble install threading # nimble install threading
# #
import std/[isolation, logging, os, strformat] import std/[logging, os, strformat]
import threading/channels import threading/channels
import signal import signal
import jacket import jacket
var var
jclient: ClientP jclient: Client
event: MidiEvent midiPort: Port
midiPort: PortP midiEventChan: Chan[MidiEventT]
midiEventChan: Chan[MidiEvent]
midiEventPrinter: Thread[void] midiEventPrinter: Thread[void]
status: cint status: cint
exitSignalled: bool = false exitSignalled: bool = false
@ -26,20 +25,20 @@ proc cleanup() =
if jclient != nil: if jclient != nil:
debug "Deactivating JACK client..." debug "Deactivating JACK client..."
discard jclient.deactivate() jclient.deactivate()
if midiEventPrinter.running: if midiEventPrinter.running:
debug "Stopping MIDI event printer thread..." debug "Stopping MIDI event printer thread..."
# Receiving an invalid event causes receiving thread to wake up and # Receiving an invalid event causes receiving thread to wake up and
# break its endless loop # break its endless loop
event.size = 0 let event = MidiEventT(size: 0)
midiEventChan.send(event) discard midiEventChan.trySend(event)
midiEventPrinter.joinThread() midiEventPrinter.joinThread()
if jclient != nil: if jclient != nil:
debug "Closing JACK client..." debug "Closing JACK client..."
discard jclient.clientClose() jclient.clientClose()
jclient = nil jclient = nil
debug "Bye." debug "Bye."
@ -58,7 +57,7 @@ proc shutdownCb(arg: pointer = nil) {.cdecl.} =
exitSignalled = true exitSignalled = true
proc midiEventPrinterProc() = proc midiEventPrinterProc() =
var event: MidiEvent var event: MidiEventT
while true: while true:
midiEventChan.recv(event) midiEventChan.recv(event)
@ -73,22 +72,21 @@ proc midiEventPrinterProc() =
stdout.flushFile() stdout.flushFile()
proc processCb*(nFrames: NFrames, arg: pointer): cint {.cdecl.} = proc processCb*(nFrames: NFrames, arg: pointer): cint {.cdecl.} =
var event: MidiEventT
let inbuf = portGetBuffer(midiPort, nFrames) let inbuf = portGetBuffer(midiPort, nFrames)
let count = midiGetEventCount(inbuf) let count = midiGetEventCount(inbuf)
for i in 0..<count: for i in 0..<count:
if midiEventGet(event.addr, inbuf, i.uint32) == 0: if midiEventGet(event.addr, inbuf, i.uint32) == 0:
midiEventChan.send(event) if not midiEventChan.trySend(event):
# trySend does not work: https://github.com/nim-lang/threading/issues/30 warn "MIDI event channel overflow!"
#if not midiEventChan.trySend(event):
# warn "MIDI event channel overflow!"
proc main() = proc main() =
addHandler(log) addHandler(log)
# Create JACK client # Create JACK client
setErrorFunction(errorCb) setErrorFunction(errorCb)
jclient = clientOpen("jacket_midi_print", NoStartServer.ord or UseExactName.ord, status.addr) jclient = clientOpen("jacket_midi_print", NoStartServer or UseExactName, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -103,7 +101,7 @@ proc main() =
# Set up a thread, which receives MIDI events from process callback via a # Set up a thread, which receives MIDI events from process callback via a
# Channel and prints them without danger of blocking the process callback # Channel and prints them without danger of blocking the process callback
midiEventChan = newChan[MidiEvent]() midiEventChan = newChan[MidiEventT]()
createThread(midiEventPrinter, midiEventPrinterProc) createThread(midiEventPrinter, midiEventPrinterProc)
# Register JACK callbacks # Register JACK callbacks
@ -115,7 +113,7 @@ proc main() =
jclient.onShutdown(shutdownCb) jclient.onShutdown(shutdownCb)
# Create output port # Create output port
midiPort = jclient.portRegister("midi_in", JACK_DEFAULT_MIDI_TYPE, PortIsInput.ord, 0) midiPort = jclient.portRegister("midi_in", JACK_DEFAULT_MIDI_TYPE, PortIsInput, 0)
# Activate JACK client ... # Activate JACK client ...
if jclient.activate() == 0: if jclient.activate() == 0:

View File

@ -0,0 +1,82 @@
## Simple JACK client, which just passes audio through
## from its single (mono) input to its single (mono) output.
import std/[logging, os]
import signal
import jacket
var
jclient: Client
status: cint
exitSignalled: bool = false
inpPort, outPort: Port
log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
type JackBufferP = ptr UncheckedArray[DefaultAudioSample]
proc errorCb(msg: cstring) {.cdecl.} =
# Suppress verbose JACK error messages when server is not available by
# default. Compile in non-release mode or pass ``lvlDebug`` or lower
# when creating the logger above to enable them.
debug "JACK error: " & $msg
proc cleanup(sig: cint = 0) =
debug "Cleaning up..."
if jclient != nil:
jclient.deactivate()
jclient.clientClose()
jclient = nil
proc signalCb(sig: cint) {.noconv.} =
debug "Received signal: " & $sig
exitSignalled = true
proc shutdownCb(arg: pointer = nil) {.cdecl.} =
warn "JACK server has shut down."
exitSignalled = true
proc processCb(nFrames: NFrames, arg: pointer): cint {.cdecl.} =
var inpbuf = cast[JackBufferP](portGetBuffer(inpPort, nFrames))
var outbuf = cast[JackBufferP](portGetBuffer(outPort, nFrames))
# copy samples from input to output buffer
for i in 0 ..< nFrames:
outbuf[i] = inpbuf[i]
addHandler(log)
# Create JACK Client ptr
setErrorFunction(errorCb)
jclient = clientOpen("passthru", NullOption, status.addr)
debug "JACK server status: " & $status
if jclient == nil:
error getJackStatusErrorString(status)
quit QuitFailure
# Register audio input and output ports
inpPort = jclient.portRegister("in_1", JackDefaultAudioType, PortIsInput, 0)
outPort = jclient.portRegister("out_1", JackDefaultAudioType, PortIsOutput, 0)
# Register JACK callbacks
jclient.onShutdown(shutdownCb)
if jclient.setProcessCallback(processCb, nil) != 0:
error "Could not set JACK process callback function."
cleanup()
quit QuitFailure
# Handle signals
when defined(windows):
setSignalProc(signalCb, SIGABRT, SIGINT, SIGTERM)
else:
setSignalProc(signalCb, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGTERM)
# Activate JACK client ...
if jclient.activate() == 0:
# ... and keep running until a signal is received
while not exitSignalled:
sleep(50)
# Deactivate client and close server connection
cleanup()

View File

@ -2,7 +2,7 @@ import std/[logging, os]
import jacket import jacket
import signal import signal
var jclient: ClientP var jclient: Client
var status: cint var status: cint
var exitSignalled: bool = false var exitSignalled: bool = false
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug) var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
@ -10,8 +10,8 @@ var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
proc cleanup(sig: cint = 0) = proc cleanup(sig: cint = 0) =
debug "Cleaning up..." debug "Cleaning up..."
if jclient != nil: if jclient != nil:
discard jclient.deactivate() jclient.deactivate()
discard jclient.clientClose() jclient.clientClose()
jclient = nil jclient = nil
proc errorCb(msg: cstring) {.cdecl.} = proc errorCb(msg: cstring) {.cdecl.} =
@ -30,7 +30,7 @@ proc shutdownCb(arg: pointer = nil) {.cdecl.} =
proc portConnected(portA: PortId; portB: PortId; connect: cint; arg: pointer) {.cdecl.} = proc portConnected(portA: PortId; portB: PortId; connect: cint; arg: pointer) {.cdecl.} =
let portAPtr = jclient.portById(portA) let portAPtr = jclient.portById(portA)
let portBPtr = jclient.portById(portB) let portBPtr = jclient.portById(portB)
if portAPtr != nil: if portAPtr != nil:
echo("Port A: ", portName(portAPtr)) echo("Port A: ", portName(portAPtr))
else: else:
@ -40,12 +40,12 @@ proc portConnected(portA: PortId; portB: PortId; connect: cint; arg: pointer) {.
echo("Port B: ", portName(portBPtr)) echo("Port B: ", portName(portBPtr))
else: else:
echo "Port B: <unknown>" echo "Port B: <unknown>"
echo("Action: ", if connect > 0: "connect" else: "disconnect") echo("Action: ", if connect > 0: "connect" else: "disconnect")
addHandler(log) addHandler(log)
setErrorFunction(errorCb) setErrorFunction(errorCb)
jclient = clientOpen("jacket_port_connect_cb", NoStartServer.ord, status.addr) jclient = clientOpen("jacket_port_connect_cb", NoStartServer, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -57,8 +57,8 @@ when defined(windows):
else: else:
setSignalProc(signalCb, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGTERM) setSignalProc(signalCb, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGTERM)
discard jclient.portRegister("in_1", JACK_DEFAULT_AUDIO_TYPE, PortIsInput.ord, 0) discard jclient.portRegister("in_1", JackDefaultAudioType, PortIsInput, 0)
discard jclient.portRegister("out_1", JACK_DEFAULT_AUDIO_TYPE, PortIsOutput.ord, 0) discard jclient.portRegister("out_1", JackDefaultAudioType, PortIsOutput, 0)
if jclient.setPortConnectCallback(portConnected) != 0: if jclient.setPortConnectCallback(portConnected) != 0:
error "Error: could not set JACK port connection callback." error "Error: could not set JACK port connection callback."

View File

@ -2,7 +2,7 @@ import std/[logging, os]
import signal import signal
import jacket import jacket
var jclient: ClientP var jclient: Client
var status: cint var status: cint
var exitSignalled: bool = false var exitSignalled: bool = false
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug) var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
@ -10,7 +10,7 @@ var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
proc cleanup(sig: cint = 0) = proc cleanup(sig: cint = 0) =
debug "Cleaning up..." debug "Cleaning up..."
if jclient != nil: if jclient != nil:
discard jclient.clientClose() jclient.clientClose()
jclient = nil jclient = nil
proc errorCb(msg: cstring) {.cdecl.} = proc errorCb(msg: cstring) {.cdecl.} =
@ -28,7 +28,7 @@ proc shutdownCb(arg: pointer = nil) {.cdecl.} =
addHandler(log) addHandler(log)
setErrorFunction(errorCb) setErrorFunction(errorCb)
jclient = clientOpen("jacket_port_register", NoStartServer.ord or UseExactName.ord, status.addr) jclient = clientOpen("jacket_port_register", NoStartServer or UseExactName, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -40,8 +40,8 @@ when defined(windows):
else: else:
setSignalProc(signalCb, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGTERM) setSignalProc(signalCb, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGTERM)
discard jclient.portRegister("in_1", JACK_DEFAULT_AUDIO_TYPE, PortIsInput.ord, 0) discard jclient.portRegister("in_1", JackDefaultAudioType, PortIsInput, 0)
discard jclient.portRegister("out_1", JACK_DEFAULT_AUDIO_TYPE, PortIsOutput.ord, 0) discard jclient.portRegister("out_1", JackDefaultAudioType, PortIsOutput, 0)
jclient.onShutdown(shutdownCb) jclient.onShutdown(shutdownCb)

View File

@ -9,35 +9,35 @@ proc main() =
let size = 32 let size = 32
var read, written: int var read, written: int
var data = [0x64.uint8, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66] var data = [0x64.byte, 0x65, 0x61, 0x64, 0x62, 0x65, 0x65, 0x66]
var recvBuf: array[8, uint8] var recvBuf: array[8, byte]
let rb = ringbufferCreate(size.csize_t) let rb = ringbufferCreate(size.csize_t)
debug fmt"Created ringbuffer of {size} bytes size." debug fmt"Created ringbuffer of {size} bytes size."
doAssert ringbufferReadSpace(rb) == 0 doAssert ringbufferReadSpace(rb) == 0
written = cast[int](ringbufferWrite(rb, cast[cstring](data.addr), 4)) written = ringbufferWrite(rb, cast[cstring](data.addr), 4).int
doAssert written == 4 doAssert written == 4
debug fmt"Written {written} bytes to ringbuffer." debug fmt"Written {written} bytes to ringbuffer."
doAssert ringbufferReadSpace(rb) == 4 doAssert ringbufferReadSpace(rb) == 4
written = cast[int](ringbufferWrite(rb, cast[cstring](data[4].addr), 4)) written = ringbufferWrite(rb, cast[cstring](data[4].addr), 4).int
doAssert written == 4 doAssert written == 4
debug fmt"Written {written} bytes to ringbuffer." debug fmt"Written {written} bytes to ringbuffer."
doAssert ringbufferReadSpace(rb) == 8 doAssert ringbufferReadSpace(rb) == 8
read = cast[int](ringbufferRead(rb, cast[cstring](recvBuf.addr), 4)) read = ringbufferRead(rb, cast[cstring](recvBuf.addr), 4).int
doAssert read == 4 doAssert read == 4
debug fmt"Read {read} bytes from ringbuffer into receive buffer: {recvBuf}" debug fmt"Read {read} bytes from ringbuffer. Receive buffer: {recvBuf}"
doAssert ringbufferReadSpace(rb) == 4 doAssert ringbufferReadSpace(rb) == 4
read = cast[int](ringbufferRead(rb, cast[cstring](recvBuf[4].addr), 4)) read = ringbufferRead(rb, cast[cstring](recvBuf[4].addr), 4).int
doAssert read == 4 doAssert read == 4
debug fmt"Read {read} bytes from ringbuffer into receive buffer: {recvBuf}" debug fmt"Read {read} bytes from ringbuffer. Receive buffer: {recvBuf}"
doAssert ringbufferReadSpace(rb) == 0 doAssert ringbufferReadSpace(rb) == 0

View File

@ -2,8 +2,8 @@ import std/[logging, math, os]
import signal import signal
import jacket import jacket
var jclient: ClientP var jclient: Client
var outPort: PortP var outPort: Port
var status: cint var status: cint
var exitSignalled: bool = false var exitSignalled: bool = false
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug) var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
@ -26,7 +26,7 @@ type
proc initSineOsc(sr: float, freq: float): SineOsc = proc initSineOsc(sr: float, freq: float): SineOsc =
let phsInc = twoPi / tableSize let phsInc = twoPi / tableSize
var phase = 0.0 var phase = 0.0
for i in 0 ..< tableSize: for i in 0 ..< tableSize:
result.waveform[i] = sin(phase) result.waveform[i] = sin(phase)
phase += phsInc phase += phsInc
@ -37,15 +37,15 @@ proc initSineOsc(sr: float, freq: float): SineOsc =
proc tick(osc: SineOscP): float = proc tick(osc: SineOscP): float =
result = osc.waveform[int(osc.phase)] result = osc.waveform[int(osc.phase)]
osc.phase += osc.idxInc; osc.phase += osc.idxInc;
if osc.phase >= tableSize: if osc.phase >= tableSize:
osc.phase -= tableSize osc.phase -= tableSize
proc cleanup() = proc cleanup() =
debug "Cleaning up..." debug "Cleaning up..."
if jclient != nil: if jclient != nil:
discard jclient.deactivate() jclient.deactivate()
discard jclient.clientClose() jclient.clientClose()
jclient = nil jclient = nil
proc errorCb(msg: cstring) {.cdecl.} = proc errorCb(msg: cstring) {.cdecl.} =
@ -61,7 +61,7 @@ proc shutdownCb(arg: pointer = nil) {.cdecl.} =
warn "JACK server has shut down." warn "JACK server has shut down."
exitSignalled = true exitSignalled = true
proc processCb(nFrames: NFrames, arg: pointer): cint {.cdecl.} = proc processCb(nFrames: NFrames, arg: pointer): cint {.cdecl.} =
var outbuf = cast[JackBufferP](portGetBuffer(outPort, nFrames)) var outbuf = cast[JackBufferP](portGetBuffer(outPort, nFrames))
let osc = cast[SineOscP](arg) let osc = cast[SineOscP](arg)
@ -74,7 +74,7 @@ addHandler(log)
# Create JACK client # Create JACK client
setErrorFunction(errorCb) setErrorFunction(errorCb)
jclient = clientOpen("jacket_sine", NoStartServer.ord or UseExactName.ord, status.addr) jclient = clientOpen("jacket_sine", NoStartServer or UseExactName, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -101,7 +101,7 @@ if jclient.setProcessCallback(processCb, osc.addr) != 0:
jclient.onShutdown(shutdownCb) jclient.onShutdown(shutdownCb)
# Create output port # Create output port
outPort = jclient.portRegister("out_1", JACK_DEFAULT_AUDIO_TYPE, PortIsOutput.ord, 0) outPort = jclient.portRegister("out_1", JackDefaultAudioType, PortIsOutput, 0)
# Activate JACK client ... # Activate JACK client ...
if jclient.activate() == 0: if jclient.activate() == 0:

View File

@ -2,21 +2,21 @@ import std/[logging, strformat]
import jacket import jacket
var var
jclient: ClientP jclient: Client
status: cint status: cint
pos: Position pos: PositionT
transportState: TransportState transportState: TransportState
var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug) var log = newConsoleLogger(when defined(release): lvlInfo else: lvlDebug)
proc errorCb(msg: cstring) {.cdecl.} = proc errorCb(msg: cstring) {.cdecl.} =
# Suppress verbose JACK error messages when server is not available by # Suppress verbose JACK error messages when server is not available by
# default. Pass ``lvlAll`` when creating the logger to enable them. # default. Pass ``lvlAll`` when creating the logger to enable them.
debug "JACK error: " & $msg debug "JACK error: " & $msg
addHandler(log) addHandler(log)
setErrorFunction(errorCb) setErrorFunction(errorCb)
jclient = clientOpen("jacket_info", NullOption.ord, status.addr) jclient = clientOpen("jacket_info", NullOption, status.addr)
debug "JACK server status: " & $status debug "JACK server status: " & $status
if jclient == nil: if jclient == nil:
@ -51,4 +51,4 @@ of TransportStarting:
else: else:
echo "Unknown JACK transport state." echo "Unknown JACK transport state."
discard jclient.clientClose jclient.clientClose()

1
examples/nim.cfg Normal file
View File

@ -0,0 +1 @@
--path:"../src/"

View File

@ -1,13 +1,15 @@
import system/ansi_c import system/ansi_c
export SIG_DFL, SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM export SIG_DFL, SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV
when not defined(windows): when not defined(windows):
export SIGPIPE export SIGPIPE, SIGTERM
var var
SIG_IGN* {.importc: "SIG_IGN", header: "<signal.h>".}: cint SIG_IGN* {.importc: "SIG_IGN", header: "<signal.h>".}: cint
SIGHUP* {.importc: "SIGHUP", header: "<signal.h>".}: cint SIGHUP* {.importc: "SIGHUP", header: "<signal.h>".}: cint
SIGQUIT* {.importc: "SIGQUIT", header: "<signal.h>".}: cint SIGQUIT* {.importc: "SIGQUIT", header: "<signal.h>".}: cint
else:
const SIGTERM* = cint(15)
type CSighandlerT = proc (a: cint) {.noconv.} type CSighandlerT = proc (a: cint) {.noconv.}

View File

@ -1,8 +1,8 @@
# Package # Package
version = "0.1.0" version = "0.2.0"
author = "Christopher Arndt" author = "Christopher Arndt"
description = "A Nim wrapper for the JACK client-side C API aka libjack" description = "A Nim wrapper for the JACK Audio Connection Kit client-side C API aka libjack"
license = "MIT" license = "MIT"
srcDir = "src" srcDir = "src"
@ -10,3 +10,31 @@ srcDir = "src"
# Dependencies # Dependencies
requires "nim >= 1.6.0" requires "nim >= 1.6.0"
taskrequires "examples", "threading"
taskrequires "examples_debug", "threading"
let examples = @[
"info",
"list_all_properties",
"midi_print",
"midi_print_ringbuffer",
"midi_print_thread",
"midi_print_threading",
"passthru",
"port_connect_cb",
"port_register",
"ringbuffer",
"sine",
"transport_query",
]
task examples, "Build examples (release)":
for example in examples:
echo "Building example 'jacket_" & example & "'..."
selfExec("compile -d:release -d:strip examples/jacket_" & example & ".nim")
task examples_debug, "Build examples (debug)":
for example in examples:
echo "Building example 'jacket_" & example & "' (debug)..."
selfExec("compile examples/jacket_" & example & ".nim")

View File

@ -1,29 +1,26 @@
# jacket.nim # jacket.nim
# Possible names/install locations of libjack, according to: # Possible names/install locations of libjack, according to:
# https://github.com/x42/weakjack/blob/master/weak_libjack.c#L108 # https://github.com/x42/weakjack/blob/master/weak_libjack.c#L108
proc getJackLibName: string = when defined(windows):
when system.hostOS == "windows": when sizeof(int) == 4:
when sizeof(int) == 4: const soname = "(|lib)jack.dll"
result = "libjack.dll"
else:
result = "libjack64.dll"
elif system.hostOS == "macosx":
result = "(|/usr/local/lib/|/opt/homebrew/lib/|/opt/local/lib/)libjack.dylib"
else: else:
result = "libjack.so.0" const soname = "(|lib)jack64.dll"
elif defined(macosx):
const soname = "(|/usr/local/lib/|/opt/homebrew/lib/|/opt/homebrew/opt/jack/lib/|/opt/local/lib/)libjack.dylib"
else:
const soname = "libjack.so.0"
{.push dynlib: getJackLibName().} {.push dynlib: soname.}
# ------------------------------ Constants -------------------------------- # ------------------------------ Constants --------------------------------
const const
JACK_MAX_FRAMES* = (4294967295'i64) JackMaxFrames* = (4294967295'i64)
JACK_LOAD_INIT_LIMIT* = 1024 JackLoadInitLimit* = 1024
JACK_DEFAULT_AUDIO_TYPE* = "32 bit float mono audio" JackDefaultAudioType* = "32 bit float mono audio"
JACK_DEFAULT_MIDI_TYPE* = "8 bit raw midi" JackDefaultMidiType* = "8 bit raw midi"
# ----------------------------- Custom Types ------------------------------ # ----------------------------- Custom Types ------------------------------
@ -37,18 +34,18 @@ type
DefaultAudioSample* = cfloat DefaultAudioSample* = cfloat
type type
Client = distinct object ClientT = distinct object
ClientP* = ptr Client Client* = ptr ClientT
Port = distinct object PortT = distinct object
PortP* = ptr Port Port* = ptr PortT
type type
MidiData* = uint8 MidiData* = uint8
MidiEvent* = object MidiEventT* = object
time*: NFrames time*: NFrames
size*: csize_t size*: csize_t
buffer*: ptr UncheckedArray[MidiData] buffer*: ptr UncheckedArray[MidiData]
MidiEventP* = ptr MidiEvent MidiEvent* = ptr MidiEventT
type type
JackOptions* {.size: sizeof(cint) pure.} = enum JackOptions* {.size: sizeof(cint) pure.} = enum
@ -113,7 +110,7 @@ type
TransportNetStarting = 4 TransportNetStarting = 4
type type
Position* = object PositionT* = object
unique1*: uint64 unique1*: uint64
usecs*: Time usecs*: Time
frameRate*: NFrames frameRate*: NFrames
@ -135,7 +132,7 @@ type
tickDouble*: cdouble tickDouble*: cdouble
padding*: array[5, int32] padding*: array[5, int32]
unique2*: uint64 unique2*: uint64
PositionP* = ptr Position Position* = ptr PositionT
#[ DEPRECATED #[ DEPRECATED
typedef enum { typedef enum {
@ -168,20 +165,20 @@ typedef struct {
]# ]#
const const
JACK_POSITION_MASK* = (PositionBBT.ord or PositionTimecode.ord) JackPositionMask* = (PositionBBT.ord or PositionTimecode.ord)
EXTENDED_TIME_INFO* = true ExtendedTimeInfo* = true
JACK_TICK_DOUBLE* = true JackTickDouble* = true
# Ringbuffer # Ringbuffer
type type
RingbufferData* = object RingbufferDataT* = object
buf*: ptr char buf*: ptr char
len*: csize_t len*: csize_t
RingbufferDataP* = ptr RingbufferData RingbufferData* = ptr RingbufferDataT
Ringbuffer = distinct object RingbufferT = distinct object
RingbufferP* = ptr Ringbuffer Ringbuffer* = ptr RingbufferT
# Metadata # Metadata
@ -196,13 +193,13 @@ type
PropertyChanged, PropertyChanged,
PropertyDeleted PropertyDeleted
Description* = object DescriptionT* = object
subject*: Uuid subject*: Uuid
property_cnt*: uint32 property_cnt*: uint32
properties*: ptr UncheckedArray[Property] properties*: ptr UncheckedArray[Property]
property_size*: uint32 property_size*: uint32
DescriptionP* = ptr Description Description* = ptr DescriptionT
# Callback function types # Callback function types
@ -232,6 +229,12 @@ type
PropertyChangeCallback* = proc (subject: Uuid, key: cstring, change: PropertyChange, arg: pointer) {.cdecl.} PropertyChangeCallback* = proc (subject: Uuid, key: cstring, change: PropertyChange, arg: pointer) {.cdecl.}
# ------------------------- Converters for Enums --------------------------
converter jackIntEnumToCInt*[T: JackOptions | JackStatus | LatencyCallbackMode |
PositionBits | TransportState | PropertyChange](x: T): cint = x.ord.cint
converter portFlagsToCULong*(x: PortFlags): culong = x.ord.culong
# ----------------------------- Version info ------------------------------ # ----------------------------- 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)
@ -252,47 +255,47 @@ proc free*(`ptr`: pointer) {.importc: "jack_free".}
# jack_client_t * jack_client_open (char *client_name, # jack_client_t * jack_client_open (char *client_name,
# jack_options_t options, # jack_options_t options,
# jack_status_t *status, ...) # jack_status_t *status, ...)
proc clientOpen*(clientName: cstring; options: cint; status: ptr cint): ClientP {. proc clientOpen*(clientName: cstring; options: cint; status: ptr cint): Client {.
varargs, importc: "jack_client_open".} varargs, importc: "jack_client_open".}
# 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"} proc clientClose*(client: Client): cint {.importc: "jack_client_close", discardable.}
# int jack_client_name_size (void) # int jack_client_name_size (void)
proc clientNameSize*(): cint {.importc: "jack_client_name_size"} 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".} proc getClientName*(client: Client): 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 {. proc getUuidForClientName*(client: Client; clientName: cstring): cstring {.
importc: "jack_get_uuid_for_client_name".} 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 {. proc getClientNameByUuid*(client: Client; clientUuid: cstring): cstring {.
importc: "jack_get_client_name_by_uuid".} importc: "jack_get_client_name_by_uuid".}
# int jack_activate (jack_client_t *client) # int jack_activate (jack_client_t *client)
proc activate*(client: ClientP): cint {.importc: "jack_activate".} proc activate*(client: Client): cint {.importc: "jack_activate", discardable.}
# int jack_deactivate (jack_client_t *client) # int jack_deactivate (jack_client_t *client)
proc deactivate*(client: ClientP): cint {.importc: "jack_deactivate".} proc deactivate*(client: Client): cint {.importc: "jack_deactivate", discardable.}
# 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".} proc getClientPid*(name: cstring): cint {.importc: "jack_get_client_pid".}
# FIXME: not implemented yet # FIXME: not implemented yet
# jack_native_thread_t jack_client_thread_id (jack_client_t *client) # jack_native_thread_t jack_client_thread_id (jack_client_t *client)
# proc clientThreadId*(client: ClientP): NativeThread {.importc: "jack_client_thread_id".} # proc clientThreadId*(client: Client): 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".} proc isRealtime*(client: Client): cint {.importc: "jack_is_realtime".}
# 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".} proc cycleWait*(client: Client): 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".} proc cycleSignal*(client: Client; status: cint) {.importc: "jack_cycle_signal".}
#[ DEPRECATED #[ DEPRECATED
jack_client_t *jack_client_new (const char *client_name) jack_client_t *jack_client_new (const char *client_name)
@ -302,23 +305,23 @@ jack_nframes_t jack_thread_wait (jack_client_t *client, int status)
# --------------------------- Internal Clients ---------------------------- # --------------------------- Internal Clients ----------------------------
# char *jack_get_internal_client_name (jack_client_t *client, jack_intclient_t intclient); # char *jack_get_internal_client_name (jack_client_t *client, jack_intclient_t intclient);
proc getInternalClientName*(client: ClientP; intclient: IntClient): cstring {. proc getInternalClientName*(client: Client; intclient: IntClient): cstring {.
importc: "jack_get_internal_client_name".} importc: "jack_get_internal_client_name".}
# jack_intclient_t jack_internal_client_handle (jack_client_t *client, const char *client_name, # jack_intclient_t jack_internal_client_handle (jack_client_t *client, const char *client_name,
# jack_status_t *status) # jack_status_t *status)
proc internalClientHandle*(client: ClientP; clientName: cstring; status: ptr cint): IntClient {. proc internalClientHandle*(client: Client; clientName: cstring; status: ptr cint): IntClient {.
importc: "jack_internal_client_handle".} importc: "jack_internal_client_handle".}
# jack_intclient_t jack_internal_client_load (jack_client_t *client, const char *client_name, # jack_intclient_t jack_internal_client_load (jack_client_t *client, const char *client_name,
# jack_options_t options, jack_status_t *status, ...) # jack_options_t options, jack_status_t *status, ...)
proc internalClientLoad*(client: ClientP; clientName: cstring; options: cint; status: ptr cint): IntClient {. proc internalClientLoad*(client: Client; clientName: cstring; options: cint; status: ptr cint): IntClient {.
varargs, importc: "jack_internal_client_load".} varargs, importc: "jack_internal_client_load".}
# jack_status_t jack_internal_client_unload (jack_client_t *client, jack_intclient_t intclient) # jack_status_t jack_internal_client_unload (jack_client_t *client, jack_intclient_t intclient)
proc internalClientUnload*(client: ClientP; intclient: IntClient): cint {. proc internalClientUnload*(client: Client; intclient: IntClient): cint {.
importc: "jack_internal_client_unload".} importc: "jack_internal_client_unload", discardable.}
#[ DEPRECATED #[ DEPRECATED
int jack_internal_client_new (const char * client_name, const char *load_name, const char *load_init) int jack_internal_client_new (const char * client_name, const char *load_name, const char *load_init)
@ -328,70 +331,70 @@ void jack_internal_client_close (const char *client_name)
# ------------------------------- Callbacks ------------------------------- # ------------------------------- Callbacks -------------------------------
proc setProcessThread*(client: ClientP; threadCallback: ThreadCallback; arg: pointer = nil): cint {. proc onShutdown*(client: Client; shutdownCallback: ShutdownCallback; arg: pointer = nil) {.
importc: "jack_set_process_thread".}
proc setThreadInitCallback*(client: ClientP; threadInitCallback: ThreadInitCallback; arg: pointer = nil): cint {.
importc: "jack_set_thread_init_callback".}
proc onShutdown*(client: ClientP; shutdownCallback: ShutdownCallback; arg: pointer = nil) {.
importc: "jack_on_shutdown".} importc: "jack_on_shutdown".}
proc onInfoShutdown*(client: ClientP; shutdownCallback: InfoShutdownCallback; arg: pointer = nil) {. proc onInfoShutdown*(client: Client; shutdownCallback: InfoShutdownCallback; arg: pointer = nil) {.
importc: "jack_on_info_shutdown".} importc: "jack_on_info_shutdown".}
proc setProcessCallback*(client: ClientP; processCallback: ProcessCallback; arg: pointer = nil): cint {. proc setProcessThread*(client: Client; threadCallback: ThreadCallback; arg: pointer = nil): cint {.
importc: "jack_set_process_callback".} importc: "jack_set_process_thread", discardable.}
proc setFreewheelCallback*(client: ClientP; freewheelCallback: FreewheelCallback; arg: pointer = nil): cint {. proc setThreadInitCallback*(client: Client; threadInitCallback: ThreadInitCallback; arg: pointer = nil): cint {.
importc: "jack_set_freewheel_callback".} importc: "jack_set_thread_init_callback", discardable.}
proc setBufferSizeCallback*(client: ClientP; bufsizeCallback: BufferSizeCallback; arg: pointer = nil): cint {. proc setProcessCallback*(client: Client; processCallback: ProcessCallback; arg: pointer = nil): cint {.
importc: "jack_set_buffer_size_callback".} importc: "jack_set_process_callback", discardable.}
proc setSampleRateCallback*(client: ClientP; srateCallback: SampleRateCallback; arg: pointer = nil): cint {. proc setFreewheelCallback*(client: Client; freewheelCallback: FreewheelCallback; arg: pointer = nil): cint {.
importc: "jack_set_sample_rate_callback".} importc: "jack_set_freewheel_callback", discardable.}
proc setClientRegistrationCallback*(client: ClientP; registrationCallback: ClientRegistrationCallback; proc setBufferSizeCallback*(client: Client; bufsizeCallback: BufferSizeCallback; arg: pointer = nil): cint {.
importc: "jack_set_buffer_size_callback", discardable.}
proc setSampleRateCallback*(client: Client; srateCallback: SampleRateCallback; arg: pointer = nil): cint {.
importc: "jack_set_sample_rate_callback", discardable.}
proc setClientRegistrationCallback*(client: Client; registrationCallback: ClientRegistrationCallback;
arg: pointer = nil): cint {. arg: pointer = nil): cint {.
importc: "jack_set_client_registration_callback".} importc: "jack_set_client_registration_callback", discardable.}
proc setPortRegistrationCallback*(client: ClientP; registrationCallback: PortRegistrationCallback; proc setPortRegistrationCallback*(client: Client; registrationCallback: PortRegistrationCallback;
arg: pointer = nil): cint {. arg: pointer = nil): cint {.
importc: "jack_set_port_registration_callback".} importc: "jack_set_port_registration_callback", discardable.}
proc setPortConnectCallback*(client: ClientP; connectCallback: PortConnectCallback; arg: pointer = nil): cint {. proc setPortConnectCallback*(client: Client; connectCallback: PortConnectCallback; arg: pointer = nil): cint {.
importc: "jack_set_port_connect_callback".} importc: "jack_set_port_connect_callback", discardable.}
proc setPortRenameCallback*(client: ClientP; renameCallback: PortRenameCallback; arg: pointer = nil): cint {. proc setPortRenameCallback*(client: Client; renameCallback: PortRenameCallback; arg: pointer = nil): cint {.
importc: "jack_set_port_rename_callback".} importc: "jack_set_port_rename_callback", discardable.}
proc setGraphOrderCallback*(client: ClientP; graphCallback: GraphOrderCallback; a3: pointer): cint {. proc setGraphOrderCallback*(client: Client; graphCallback: GraphOrderCallback; arg: pointer = nil): cint {.
importc: "jack_set_graph_order_callback".} importc: "jack_set_graph_order_callback", discardable.}
proc setXrunCallback*(client: ClientP; xrunCallback: XRunCallback; arg: pointer = nil): cint {. proc setXrunCallback*(client: Client; xrunCallback: XRunCallback; arg: pointer = nil): cint {.
importc: "jack_set_xrun_callback".} importc: "jack_set_xrun_callback", discardable.}
proc setLatencyCallback*(client: ClientP; latencyCallback: LatencyCallback; arg: pointer = nil): cint {. proc setLatencyCallback*(client: Client; latencyCallback: LatencyCallback; arg: pointer = nil): cint {.
importc: "jack_set_latency_callback".} importc: "jack_set_latency_callback", discardable.}
# -------------------------- Server Client Control ------------------------ # -------------------------- 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".} proc setFreewheel*(client: Client; onoff: cint): cint {.importc: "jack_set_freewheel", discardable.}
# 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".} proc setBufferSize*(client: Client; nframes: NFrames): cint {.importc: "jack_set_buffer_size", discardable.}
#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".} proc getSampleRate*(client: Client): 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".} proc getBufferSize*(client: Client): NFrames {.importc: "jack_get_buffer_size".}
# 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".} proc cpuLoad*(client: Client): cfloat {.importc: "jack_cpu_load".}
#[ DEPRECATED #[ DEPRECATED
int jack_engine_takeover_timebase (jack_client_t *) int jack_engine_takeover_timebase (jack_client_t *)
@ -405,82 +408,82 @@ int jack_engine_takeover_timebase (jack_client_t *)
# const char *port_type, # const char *port_type,
# unsigned long flags, # unsigned long flags,
# unsigned long buffer_size) # unsigned long buffer_size)
proc portRegister*(client: ClientP; portName: cstring; portType: cstring; proc portRegister*(client: Client; portName: cstring; portType: cstring;
flags: culong; bufferSize: culong): PortP {.importc: "jack_port_register".} flags: culong; bufferSize: culong): Port {.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".} proc portUnregister*(client: Client; port: Port): cint {.importc: "jack_port_unregister", discardable.}
# 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".} proc portGetBuffer*(port: Port; 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".} proc portUuid*(port: Port): 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".} proc portName*(port: Port): 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".} proc portShortName*(port: Port): 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".} proc portFlags*(port: Port): 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".} proc portType*(port: Port): 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".} proc portTypeId*(port: Port): 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 {. proc portIsMine*(client: Client; port: Port): cint {.
importc: "jack_port_is_mine".} 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".} proc portConnected*(port: Port): cint {.importc: "jack_port_connected".}
# int jack_port_connected_to (const jack_port_t *port, # 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".} proc portConnectedTo*(port: Port; 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".} proc portGetConnections*(port: Port): cstringArray {.importc: "jack_port_get_connections".}
# const char ** jack_port_get_all_connections (const jack_client_t *client, # 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 {. proc portGetAllConnections*(client: Client; port: Port): cstringArray {.
importc: "jack_port_get_all_connections".} importc: "jack_port_get_all_connections".}
# 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".} proc portRename*(client: Client; port: Port; portName: cstring): cint {.importc: "jack_port_rename", discardable.}
# 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".} proc portSetAlias*(port: Port; alias: cstring): cint {.importc: "jack_port_set_alias", discardable.}
# 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".} proc portUnsetAlias*(port: Port; alias: cstring): cint {.importc: "jack_port_unset_alias", discardable.}
# 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".} proc portGetAliases*(port: Port; 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".} proc portRequestMonitor*(port: Port; onoff: cint): cint {.importc: "jack_port_request_monitor", discardable.}
# int jack_port_request_monitor_by_name (jack_client_t *client, # 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 {. proc portRequestMonitorByName*(client: Client; portName: cstring; onoff: cint): cint {.
importc: "jack_port_request_monitor_by_name".} importc: "jack_port_request_monitor_by_name", discardable.}
# 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 {. proc portEnsureMonitor*(port: Port; onoff: cint): cint {.
importc: "jack_port_ensure_monitor".} importc: "jack_port_ensure_monitor", discardable.}
# 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".} proc portMonitoringInput*(port: Port): cint {.importc: "jack_port_monitoring_input".}
#[ DEPRECATED #[ DEPRECATED
int jack_port_tie (jack_port_t *src, jack_port_t *dst) int jack_port_tie (jack_port_t *src, jack_port_t *dst)
@ -497,14 +500,14 @@ int jack_port_set_name (jack_port_t *port, const char *port_name)
# unsigned long flags) # unsigned long flags)
# #
# 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 getPorts*(client: ClientP; portNamePattern: cstring; proc getPorts*(client: Client; portNamePattern: cstring;
typeNamePattern: cstring; flags: culong): cstringArray {.importc: "jack_get_ports".} typeNamePattern: cstring; flags: culong): cstringArray {.importc: "jack_get_ports".}
# jack_port_t * jack_port_by_name (jack_client_t *client, const char *port_name) # 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".} proc portByName*(client: Client; portName: cstring): Port {.importc: "jack_port_by_name".}
# jack_port_t * jack_port_by_id (jack_client_t *client, jack_port_id_t port_id) # 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".} proc portById*(client: Client; portId: PortId): Port {.importc: "jack_port_by_id".}
# ------------------------------ Connections ------------------------------ # ------------------------------ Connections ------------------------------
@ -512,15 +515,15 @@ proc portById*(client: ClientP; portId: PortId): PortP {.importc: "jack_port_by_
# int jack_connect (jack_client_t *client, # int jack_connect (jack_client_t *client,
# const char *source_port, # const char *source_port,
# const char *destination_port) # const char *destination_port)
proc connect*(client: ClientP; srcPort: cstring; destPort: cstring): cint {.importc: "jack_connect".} proc connect*(client: Client; srcPort: cstring; destPort: cstring): cint {.importc: "jack_connect", discardable.}
# int jack_disconnect (jack_client_t *client, # int jack_disconnect (jack_client_t *client,
# const char *source_port, # const char *source_port,
# const char *destination_port) # const char *destination_port)
proc disconnect*(client: ClientP; srcPort: cstring; destPort: cstring): cint {.importc: "jack_disconnect".} proc disconnect*(client: Client; srcPort: cstring; destPort: cstring): cint {.importc: "jack_disconnect", discardable.}
# 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".} proc portDisconnect*(client: Client; port: Port): cint {.importc: "jack_port_disconnect", discardable.}
# int jack_port_name_size(void) # int jack_port_name_size(void)
proc portNameSize*(): cint {.importc: "jack_port_name_size".} proc portNameSize*(): cint {.importc: "jack_port_name_size".}
@ -529,7 +532,7 @@ proc portNameSize*(): cint {.importc: "jack_port_name_size".}
proc portTypeSize*(): cint {.importc: "jack_port_type_size".} 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 {. proc portTypeGetBufferSize*(client: Client; portType: cstring): csize_t {.
importc: "jack_port_type_get_buffer_size".} importc: "jack_port_type_get_buffer_size".}
@ -539,7 +542,7 @@ proc portTypeGetBufferSize*(client: ClientP; portType: cstring): csize_t {.
proc midiGetEventCount*(portBuffer: pointer): NFrames {.importc: "jack_midi_get_event_count".} 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) # 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 {. proc midiEventGet*(event: MidiEvent, portBuffer: pointer, eventIndex: uint32): cint {.
importc: "jack_midi_event_get".} importc: "jack_midi_event_get".}
# void jack_midi_clear_buffer (void *port_buffer) # void jack_midi_clear_buffer (void *port_buffer)
@ -553,8 +556,8 @@ proc midiEventReserve*(portBuffer: pointer, time: NFrames, dataSize: csize_t): p
importc: "jack_midi_event_reserve".} 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) # 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 {. proc midiEventWrite*(portBuffer: pointer, time: NFrames, data: ptr MidiData, dataSize: csize_t): cint {.
importc: "jack_midi_event_write".} importc: "jack_midi_event_write", discardable.}
# uint32_t jack_midi_get_lost_event_count (void *port_buffer) # uint32_t jack_midi_get_lost_event_count (void *port_buffer)
proc midiGetLostEventCount*(portBuffer: pointer): uint32 {.importc: "jack_midi_get_lost_event_count".} proc midiGetLostEventCount*(portBuffer: pointer): uint32 {.importc: "jack_midi_get_lost_event_count".}
@ -563,15 +566,15 @@ proc midiGetLostEventCount*(portBuffer: pointer): uint32 {.importc: "jack_midi_g
# -------------------------------- Latency -------------------------------- # -------------------------------- Latency --------------------------------
# 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) {. proc portGetLatencyRange*(port: Port; mode: LatencyCallbackMode; range: ptr LatencyRange) {.
importc: "jack_port_get_latency_range".} importc: "jack_port_get_latency_range".}
# void jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) # void jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
proc portSetLatencyRange*(port: PortP; mode: LatencyCallbackMode; range: ptr LatencyRange) {. proc portSetLatencyRange*(port: Port; mode: LatencyCallbackMode; range: ptr LatencyRange) {.
importc: "jack_port_set_latency_range".} importc: "jack_port_set_latency_range".}
# int jack_recompute_total_latencies (jack_client_t *) # int jack_recompute_total_latencies (jack_client_t *)
proc recomputeTotalLatencies*(client: ClientP): cint {.importc: "jack_recompute_total_latencies".} proc recomputeTotalLatencies*(client: Client): cint {.importc: "jack_recompute_total_latencies", discardable.}
#[ DEPRECATED #[ DEPRECATED
jack_nframes_t jack_port_get_latency (jack_port_t *port) jack_nframes_t jack_port_get_latency (jack_port_t *port)
@ -584,28 +587,28 @@ int jack_recompute_total_latency (jack_client_t *, jack_port_t *port)
# ----------------------------- Time handling ----------------------------- # ----------------------------- 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".} proc framesSinceCycleStart*(client: Client): 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".} proc frameTime*(client: Client): 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".} proc lastFrameTime*(client: Client): NFrames {.importc: "jack_last_frame_time".}
# int jack_get_cycle_times(const jack_client_t *client, # int jack_get_cycle_times(const jack_client_t *client,
# jack_nframes_t *current_frames, # jack_nframes_t *current_frames,
# jack_time_t *current_usecs, # jack_time_t *current_usecs,
# jack_time_t *next_usecs, # jack_time_t *next_usecs,
# float *period_usecs) # float *period_usecs)
proc getCycleTimes*(client: ClientP; currentFrames: ptr NFrames; proc getCycleTimes*(client: Client; currentFrames: ptr NFrames;
currentUsecs: ptr Time; nextUsecs: ptr Time; currentUsecs: ptr Time; nextUsecs: ptr Time;
periodUsecs: ptr cfloat): cint {.importc: "jack_get_cycle_times".} 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".} proc framesToTime*(client: Client; 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".} proc timeToFrames*(client: Client; 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".} proc getTime*(): Time {.importc: "jack_get_time".}
@ -614,40 +617,40 @@ proc getTime*(): Time {.importc: "jack_get_time".}
# ------------------------------- Transport ------------------------------- # ------------------------------- Transport -------------------------------
# int jack_release_timebase (jack_client_t *client) # int jack_release_timebase (jack_client_t *client)
proc releaseTimebase*(client: ClientP): cint {.importc: "jack_release_timebase".} proc releaseTimebase*(client: Client): cint {.importc: "jack_release_timebase", discardable.}
# int jack_set_sync_callback (jack_client_t *client, JackSyncCallback sync_callback, void *arg) # int jack_set_sync_callback (jack_client_t *client, JackSyncCallback sync_callback, void *arg)
proc setSyncCallback*(client: ClientP; syncCallback: SyncCallback; arg: pointer = nil): cint {. proc setSyncCallback*(client: Client; syncCallback: SyncCallback; arg: pointer = nil): cint {.
importc: "jack_set_sync_callback".} importc: "jack_set_sync_callback", discardable.}
# int jack_set_sync_timeout (jack_client_t *client, jack_time_t timeout) # 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".} proc setSyncTimeout*(client: Client; timeout: Time): cint {.importc: "jack_set_sync_timeout", discardable.}
# int jack_set_timebase_callback (jack_client_t *client, # int jack_set_timebase_callback (jack_client_t *client,
# int conditional, # int conditional,
# JackTimebaseCallback timebase_callback, # JackTimebaseCallback timebase_callback,
# void *arg) # void *arg)
proc setTimebaseCallback*(client: ClientP; conditional: cint; timebaseCallback: TimebaseCallback; proc setTimebaseCallback*(client: Client; conditional: cint; timebaseCallback: TimebaseCallback;
arg: pointer = nil): cint {. arg: pointer = nil): cint {.
importc: "jack_set_timebase_callback".} importc: "jack_set_timebase_callback", discardable.}
# int jack_transport_locate (jack_client_t *client, jack_nframes_t frame) # int jack_transport_locate (jack_client_t *client, jack_nframes_t frame)
proc transportLocate*(client: ClientP; frame: NFrames): cint {.importc: "jack_transport_locate".} proc transportLocate*(client: Client; frame: NFrames): cint {.importc: "jack_transport_locate", discardable.}
# jack_transport_state_t jack_transport_query (const jack_client_t *client, jack_position_t *pos) # 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".} proc transportQuery*(client: Client; pos: Position): TransportState {.importc: "jack_transport_query".}
# jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client) # jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client)
proc getCurrentTransportFrame*(client: ClientP): NFrames {.importc: "jack_get_current_transport_frame".} proc getCurrentTransportFrame*(client: Client): NFrames {.importc: "jack_get_current_transport_frame".}
# int jack_transport_reposition (jack_client_t *client, const jack_position_t *pos) # int jack_transport_reposition (jack_client_t *client, const jack_position_t *pos)
proc transportReposition*(client: ClientP; pos: PositionP): cint {.importc: "jack_transport_reposition".} proc transportReposition*(client: Client; pos: Position): cint {.importc: "jack_transport_reposition".}
# void jack_transport_start (jack_client_t *client) # void jack_transport_start (jack_client_t *client)
proc transportStart*(client: ClientP) {.importc: "jack_transport_start".} proc transportStart*(client: Client) {.importc: "jack_transport_start".}
# void jack_transport_stop (jack_client_t *client) # void jack_transport_stop (jack_client_t *client)
proc transportStop*(client: ClientP) {.importc: "jack_transport_stop".} proc transportStop*(client: Client) {.importc: "jack_transport_stop".}
#[ DEPRECATED #[ DEPRECATED
void jack_get_transport_info (jack_client_t *client, jack_transport_info_t *tinfo) void jack_get_transport_info (jack_client_t *client, jack_transport_info_t *tinfo)
@ -657,79 +660,81 @@ void jack_set_transport_info (jack_client_t *client, jack_transport_info_t *tinf
# ----------------------------- Ringbuffers ------------------------------- # ----------------------------- Ringbuffers -------------------------------
# jack_ringbuffer_t *jack_ringbuffer_create (size_t sz) # jack_ringbuffer_t *jack_ringbuffer_create (size_t sz)
proc ringbufferCreate*(sz: csize_t): RingbufferP {.importc: "jack_ringbuffer_create".} proc ringbufferCreate*(sz: csize_t): Ringbuffer {.importc: "jack_ringbuffer_create".}
# void jack_ringbuffer_free (jack_ringbuffer_t *rb) # void jack_ringbuffer_free (jack_ringbuffer_t *rb)
proc ringbufferFree*(rb: RingbufferP) {.importc: "jack_ringbuffer_free".} proc ringbufferFree*(rb: Ringbuffer) {.importc: "jack_ringbuffer_free".}
# void jack_ringbuffer_get_read_vector (const jack_ringbuffer_t *rb, jack_ringbuffer_data_t *vec) # void jack_ringbuffer_get_read_vector (const jack_ringbuffer_t *rb, jack_ringbuffer_data_t *vec)
proc ringbufferGetReadVector*(rb: RingbufferP, vec: var RingbufferDataP) {.importc: "jack_ringbuffer_get_read_vector".} proc ringbufferGetReadVector*(rb: Ringbuffer, vec: var RingbufferData) {.importc: "jack_ringbuffer_get_read_vector".}
# void jack_ringbuffer_get_write_vector (const jack_ringbuffer_t *rb, jack_ringbuffer_data_t *vec) # void jack_ringbuffer_get_write_vector (const jack_ringbuffer_t *rb, jack_ringbuffer_data_t *vec)
proc ringbufferGetWriteVector*(rb: RingbufferP, vec: var RingbufferDataP) {.importc: "jack_ringbuffer_get_write_vector".} proc ringbufferGetWriteVector*(rb: Ringbuffer, vec: var RingbufferData) {.importc: "jack_ringbuffer_get_write_vector".}
# size_t jack_ringbuffer_read (jack_ringbuffer_t *rb, char *dest, size_t cnt) # size_t jack_ringbuffer_read (jack_ringbuffer_t *rb, char *dest, size_t cnt)
proc ringbufferRead*(rb: RingbufferP, dest: cstring, cnt: csize_t): csize_t {.importc: "jack_ringbuffer_read".} proc ringbufferRead*(rb: Ringbuffer, dest: cstring, cnt: csize_t): csize_t {.importc: "jack_ringbuffer_read".}
# size_t jack_ringbuffer_peek (jack_ringbuffer_t *rb, char *dest, size_t cnt) # size_t jack_ringbuffer_peek (jack_ringbuffer_t *rb, char *dest, size_t cnt)
proc ringbufferPeek*(rb: RingbufferP, dest: cstring, cnt: csize_t): csize_t {.importc: "jack_ringbuffer_peek".} proc ringbufferPeek*(rb: Ringbuffer, dest: cstring, cnt: csize_t): csize_t {.importc: "jack_ringbuffer_peek".}
# void jack_ringbuffer_read_advance (jack_ringbuffer_t *rb, size_t cnt) # void jack_ringbuffer_read_advance (jack_ringbuffer_t *rb, size_t cnt)
proc ringbufferReadAdvance*(rb: RingbufferP, cnt: csize_t) {.importc: "jack_ringbuffer_read_advance".} proc ringbufferReadAdvance*(rb: Ringbuffer, cnt: csize_t) {.importc: "jack_ringbuffer_read_advance".}
# size_t jack_ringbuffer_read_space (const jack_ringbuffer_t *rb) # size_t jack_ringbuffer_read_space (const jack_ringbuffer_t *rb)
proc ringbufferReadSpace*(rb: RingbufferP): csize_t {.importc: "jack_ringbuffer_read_space".} proc ringbufferReadSpace*(rb: Ringbuffer): csize_t {.importc: "jack_ringbuffer_read_space".}
# int jack_ringbuffer_mlock (jack_ringbuffer_t *rb) # int jack_ringbuffer_mlock (jack_ringbuffer_t *rb)
proc ringbufferMlock*(rb: RingbufferP): int {.importc: "jack_ringbuffer_mlock".} proc ringbufferMlock*(rb: Ringbuffer): cint {.importc: "jack_ringbuffer_mlock", discardable.}
# void jack_ringbuffer_reset (jack_ringbuffer_t *rb) # void jack_ringbuffer_reset (jack_ringbuffer_t *rb)
proc ringbufferReset*(rb: RingbufferP) {.importc: "jack_ringbuffer_reset".} proc ringbufferReset*(rb: Ringbuffer) {.importc: "jack_ringbuffer_reset".}
# size_t jack_ringbuffer_write (jack_ringbuffer_t *rb, const char *src, size_t cnt) # size_t jack_ringbuffer_write (jack_ringbuffer_t *rb, const char *src, size_t cnt)
proc ringbufferWrite*(rb: RingbufferP, src: cstring, cnt: csize_t): csize_t {.importc: "jack_ringbuffer_write".} proc ringbufferWrite*(rb: Ringbuffer, src: cstring, cnt: csize_t): csize_t {.importc: "jack_ringbuffer_write".}
# void jack_ringbuffer_write_advance (jack_ringbuffer_t *rb, size_t cnt) # void jack_ringbuffer_write_advance (jack_ringbuffer_t *rb, size_t cnt)
proc ringbufferWriteAdvance*(rb: RingbufferP, cnt: csize_t) {.importc: "jack_ringbuffer_write_advance".} proc ringbufferWriteAdvance*(rb: Ringbuffer, cnt: csize_t) {.importc: "jack_ringbuffer_write_advance".}
# size_t jack_ringbuffer_write_space (const jack_ringbuffer_t *rb) # size_t jack_ringbuffer_write_space (const jack_ringbuffer_t *rb)
proc ringbufferWriteSpace*(rb: RingbufferP): csize_t {.importc: "jack_ringbuffer_write_space".} proc ringbufferWriteSpace*(rb: Ringbuffer): csize_t {.importc: "jack_ringbuffer_write_space".}
# ------------------------------- Metadata -------------------------------- # ------------------------------- Metadata --------------------------------
# int jack_set_property (jack_client_t*, jack_uuid_t subject, const char* key, const char* value, const char* type) # 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".} proc setProperty*(client: Client, subject: Uuid, key, value, `type`: cstring): cint {.importc: "jack_set_property", discardable.}
# int jack_get_property (jack_uuid_t subject, const char* key, char** value, char** type) # 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".} proc getProperty*(subject: Uuid, key: cstring, value, `type`: ptr cstring): cint {.importc: "jack_get_property", discardable.}
# void jack_free_description (jack_description_t* desc, int free_description_itself) # void jack_free_description (jack_description_t* desc, int free_description_itself)
proc freeDescription*(desc: DescriptionP, freeDescriptionItself: cint) {.importc: "jack_free_description".} proc freeDescription*(desc: Description, freeDescriptionItself: cint) {.importc: "jack_free_description".}
# int jack_get_properties (jack_uuid_t subject, jack_description_t* desc) # int jack_get_properties (jack_uuid_t subject, jack_description_t* desc)
proc getProperties*(subject: Uuid, desc: DescriptionP): cint {.importc: "jack_get_properties".} proc getProperties*(subject: Uuid, desc: Description): cint {.importc: "jack_get_properties", discardable.}
# int jack_get_all_properties (jack_description_t** descs) # int jack_get_all_properties (jack_description_t** descs)
proc getAllProperties*(descs: var ptr UncheckedArray[Description]): cint {.importc: "jack_get_all_properties".} proc getAllProperties*(descs: var ptr UncheckedArray[DescriptionT]): cint {.importc: "jack_get_all_properties", discardable.}
# int jack_remove_property (jack_client_t* client, jack_uuid_t subject, const char* key) # 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".} proc removeProperty*(client: Client, subject: Uuid): cint {.importc: "jack_remove_property", discardable.}
# int jack_remove_properties (jack_client_t* client, jack_uuid_t subject) # int jack_remove_properties (jack_client_t* client, jack_uuid_t subject)
proc removeProperties*(client: ClientP, subject: Uuid): cint {.importc: "jack_remove_properties".} proc removeProperties*(client: Client, subject: Uuid): cint {.importc: "jack_remove_properties", discardable.}
# int jack_remove_all_properties (jack_client_t* client) # int jack_remove_all_properties (jack_client_t* client)
proc removeAllProperties*(client: ClientP): cint {.importc: "jack_remove_all_properties".} proc removeAllProperties*(client: Client): cint {.importc: "jack_remove_all_properties", discardable.}
# int jack_set_property_change_callback (jack_client_t* client, JackPropertyChangeCallback callback, void* arg) # int jack_set_property_change_callback (jack_client_t* client, JackPropertyChangeCallback callback, void* arg)
proc setPropertyChangeCallback*(client: ClientP, callback: PropertyChangeCallback, arg: pointer = nil): cint {. proc setPropertyChangeCallback*(client: Client, callback: PropertyChangeCallback, arg: pointer = nil): cint {.
importc: "jack_set_property_change_callback".} importc: "jack_set_property_change_callback", discardable.}
# ---------------------------- Error handling ----------------------------- # ---------------------------- Error handling -----------------------------
# void jack_set_error_function (void(*)(const char *) func)
proc setErrorFunction*(errorCallback: ErrorCallback) {.importc: "jack_set_error_function".} proc setErrorFunction*(errorCallback: ErrorCallback) {.importc: "jack_set_error_function".}
# void jack_set_info_function (void(*)(const char *) func)
proc setInfoFunction*(infoCallback: InfoCallback) {.importc: "jack_set_info_function".} proc setInfoFunction*(infoCallback: InfoCallback) {.importc: "jack_set_info_function".}
{.pop.} {.pop.}
@ -739,33 +744,33 @@ proc setInfoFunction*(infoCallback: InfoCallback) {.importc: "jack_set_info_func
proc getJackStatusErrorString*(status: cint): string = proc getJackStatusErrorString*(status: cint): string =
# Get JACK error status as string. # Get JACK error status as string.
if status == Success.ord: if status == Success:
return "" return ""
if status == Failure.ord: if status == Failure:
# Only include this generic message if no other error status is set # Only include this generic message if no other error status is set
result = "Overall operation failed" result = "Overall operation failed"
if (status and InvalidOption.ord) > 0: if (status and InvalidOption) > 0:
result.add("\nThe operation contained an invalid and unsupported option") result.add("\nThe operation contained an invalid and unsupported option")
if (status and NameNotUnique.ord) > 0: if (status and NameNotUnique) > 0:
result.add("\nThe desired client name was not unique") result.add("\nThe desired client name was not unique")
if (status and ServerStarted.ord) > 0: if (status and ServerStarted) > 0:
result.add("\nThe JACK server was started as a result of this operation") result.add("\nThe JACK server was started as a result of this operation")
if (status and ServerFailed.ord) > 0: if (status and ServerFailed) > 0:
result.add("\nUnable to connect to the JACK server") result.add("\nUnable to connect to the JACK server")
if (status and ServerError.ord) > 0: if (status and ServerError) > 0:
result.add("\nCommunication error with the JACK server") result.add("\nCommunication error with the JACK server")
if (status and NoSuchClient.ord) > 0: if (status and NoSuchClient) > 0:
result.add("\nRequested client does not exist") result.add("\nRequested client does not exist")
if (status and LoadFailure.ord) > 0: if (status and LoadFailure) > 0:
result.add("\nUnable to load internal client") result.add("\nUnable to load internal client")
if (status and InitFailure.ord) > 0: if (status and InitFailure) > 0:
result.add("\nUnable to initialize client") result.add("\nUnable to initialize client")
if (status and ShmFailure.ord) > 0: if (status and ShmFailure) > 0:
result.add("\nUnable to access shared memory") result.add("\nUnable to access shared memory")
if (status and VersionError.ord) > 0: if (status and VersionError) > 0:
result.add("\nClient's protocol version does not match") result.add("\nClient's protocol version does not match")
if (status and BackendError.ord) > 0: if (status and BackendError) > 0:
result.add("\nBackend Error") result.add("\nBackend Error")
if (status and ClientZombie.ord) > 0: if (status and ClientZombie) > 0:
result.add("\nClient is being shutdown against its will") result.add("\nClient is being shutdown against its will")