Swift Package for BrlAPI, with some helpers.
The package exposes a single Braille library that depends on the BrlAPI binary XCFramework target. Translation from text to braille dot patterns happens server-side in the BRLTTY daemon — this package sends text via brlapi__writeWText and lets the daemon apply its configured text/contraction tables.
swift package build-brlapi -- --xcframework
swift build
swift testbuild-brlapi is a command plugin that initialises the BRLTTY git submodule and runs Scripts/build-brltty-macos.sh. Pass -- --no-clean to skip the configure step on subsequent builds:
swift package build-brlapi -- --no-cleanPass -- --arch=arm64 or -- --arch=x86_64 to build for a specific architecture:
swift package build-brlapi -- --arch=arm64To build the xcframework directly from the plugin (equivalent to running the script manually):
swift package build-brlapi -- --xcframework --universal
swift package build-brlapi -- --xcframework --universal --no-cleanPackage.swift ships with a URL-based binaryTarget, so a fresh clone resolves BrlAPI.xcframework from a published GitHub release without running the plugin. The plugin is only needed when working on BRLTTY itself or cutting a new release.
Run this on Apple Silicon — Rosetta 2 (installed by default) lets configure test binaries for x86_64 execute during the cross-compile:
./Scripts/create-brlapi-xcframework.sh --universalOr via the plugin:
swift package build-brlapi -- --xcframework --universalThis compiles BRLTTY for arm64 and x86_64, lipos the dylibs into a fat binary, and produces:
BrlAPI.xcframework— the binary target consumed by SPMBrlAPI.xcframework.zip— the release asset- The SPM checksum printed to stdout — note it
Pass --no-clean to reuse existing BRLTTY build outputs:
./Scripts/create-brlapi-xcframework.sh --universal --no-clean# Confirm both architectures are present
lipo -info BrlAPI.xcframework/macos-arm64_x86_64/BrlAPI.framework/BrlAPI(If the file isn't there, you may have forgotten --universal, which changes the path.)
swift build
swift testThe framework binaries must be signed with a Developer ID certificate before release.
codesign --force --sign "Developer ID Application: Your Name (TEAMID)" \
--timestamp \
BrlAPI.xcframework/macos-arm64_x86_64/BrlAPI.framework/Versions/A/BrlAPI
codesign --force --sign "Developer ID Application: Your Name (TEAMID)" \
--timestamp \
BrlAPI.xcframework/macos-arm64_x86_64/BrlAPI.framework
codesign --force --sign "Developer ID Application: Your Name (TEAMID)" \
--timestamp \
BrlAPI.xcframeworkVerify the binary has a valid Developer ID signature:
codesign -dv BrlAPI.xcframework/macos-arm64_x86_64/BrlAPI.framework/Versions/A/BrlAPI
# TeamIdentifier should match your team ID; no "adhoc" in the flagsThen notarize:
ditto -c -k --keepParent BrlAPI.xcframework BrlAPI.xcframework.zip
xcrun notarytool submit BrlAPI.xcframework.zip \
--apple-id "your@email.com" \
--team-id "TEAMID" \
--waitThe checksum will change after signing — recompute it:
swift package compute-checksum BrlAPI.xcframework.zipReplace the URL/checksum on the BrlAPI binaryTarget:
.binaryTarget(
name: "BrlAPI",
url: "https://github.com/rustle/Braille/releases/download/<tag>/BrlAPI.xcframework.zip",
checksum: "<checksum from step 3>"
),Commit this change.
git tag <tag>
git push origin main --tags
gh release create <tag> BrlAPI.xcframework.zip --title "<tag>"Package.swift at a release tag uses the URL binary target, so there is no local build path in the shipped manifest. Consumers who want to work on the Braille package itself reference it via a local override in their consuming project:
// In SpeakUp or ScreenReader Package.swift
.package(path: "../Braille")This bypasses the binary target entirely and uses the source package directly.
Run the daemon without -q and with --log-level=debug to see each BrlAPI write it receives:
sudo .build/brltty/Programs/brltty -b no -x no -n -A auth=none --log-level=debugapitest is a BrlAPI client that connects to the running daemon and sends test patterns — the same path your code uses. With the daemon running:
.build/brltty/Programs/apitestbrltest exercises braille drivers directly (bypasses BrlAPI). Useful for confirming a driver works independently of the daemon:
.build/brltty/Programs/brltest -b noBoth apitest and brltest are built by ./Scripts/build-brltty-macos.sh.
BrlAPIDisplay connects to a running BRLTTY daemon over a Unix socket. The daemon must be running before connect() is called; if it isn't, the call throws BrlAPIError.connectionFailed.
Run BRLTTY with the null drivers so the socket is available without hardware:
sudo .build/brltty/Programs/brltty -b no -x no -n -q -A auth=none-b no— null Braille driver (simulates a display)-x no— null screen driver-n— don't daemonize (stays in foreground)-q— quiet-A auth=none— disable key-file authentication (the app runs as a non-root user and cannot read root's auth key)
The simulated display accepts write calls silently, so the full send path can be exercised.
sudo .build/brltty/Programs/brlttyBRLTTY auto-detects most USB and Bluetooth displays. Pass -b <driver> to force a specific driver if needed.
- BRLTTY needs
root(or USB/Accessibility permissions) to open the display device. - The socket is created at
/var/run/BrlAPI.socket(root) or~/.BrlAPI.socket(user). - If
/etc/brltty.confis absent, pass all options on the command line as shown above.
BrlAPIDisplay.write(text:) calls brlapi__writeWText, which sends raw text to the daemon. The daemon translates the text to dot patterns using its currently loaded text and contraction tables (the BRLTTY .ttb / .ctb formats).
Pick a table on the daemon command line:
sudo .build/brltty/Programs/brltty -T en-nabcc -b no -x no -n -A auth=noneOr set text-table / contraction-table in /etc/brltty.conf. The bundled tables live under BRLTTY/Tables/Text/ and BRLTTY/Tables/Contraction/.
Selecting the table is a daemon-level concern; the client has no API to override it.
Braille is released under an Apache license. See the LICENSE file for more information.