Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

supernova: enable building JACK API on macOS #4291

Merged
merged 3 commits into from
May 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 49 additions & 0 deletions README_MACOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,55 @@ This should be fixed at some point (its a build tool configuration issue). Until

They do however work on Linux and Windows.

Building with native JACK backend
------------------------------

If you want to use `scsynth` or `supernova` on macOS with JACK, but _without_ the JackRouter driver, you can build them with the native JACK backend. **In that case you will not be able to boot `scsynth`/`supernova` without booting JACK first.** JackRouter allows any macOS application to stream audio to/from JACK, but at the time of writing this (early 2019) it is outdated and the development has stalled.

First you need to install JACK, either through `homebrew`:

```
brew install jack qjackctl
```

or by installing the `JackOSX` package. Please note, JACK from `homebrew` is `jack1` and does _not_ include JackRouter. `JackOSX` is `jack2` and it does include JackRouter. `jack1` and `jack2` implement the same API, but you should have only one of them installed at a time.

In order to build with JACK, you need to add the `-DAUDIOAPI=jack` flag to cmake.

After running cmake configuration proceed with the build process as usual.

### Running SuperCollider with JACK

When `jack` is installed via `homebrew`, you need to add jack's path to the `$PATH` environment variable in `sclang`:
mossheim marked this conversation as resolved.
Show resolved Hide resolved

```supercollider
"PATH".setenv("echo $PATH".unixCmdGetStdOut ++ ":/usr/local/bin");
```
Please note, this is not needed when using the JackOSX package.

Optionally, you can have `scsynth`/`supernova` automatically connect to system inputs/outputs by setting appropriate environment variables (refer to the Linux section of the "Audio device selection" reference in SuperCollider help):

```supercollider
// connect all input channels with system
"SC_JACK_DEFAULT_INPUTS".setenv("system");
// connect all output channels with system
"SC_JACK_DEFAULT_OUTPUTS".setenv("system");
```

Now you can start JACK, either using `JackPilot` app (from JackOSX package), `qjackctl` (from `homebrew`) or from command line:


```
jackd -d coreaudio
# or
jackd -d coreaudio -r48000 -p512 # specifying sample rate and buffer size
```

Then start `scsynth`/`supernova` as usual.

### Caveats

JACK installed with `homebrew` can only use a single device for both input and output. In order to use it with the internal soundcard on macOS, one needs to create an aggregate device that includes both input and output. JACK from `JackOSX` does not have this limitation.

sclang and scynth executables
-----------------------------
Expand Down
2 changes: 1 addition & 1 deletion server/scsynth/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ elseif(AUDIOAPI STREQUAL portaudio AND ((NOT WIN32) OR MSYS)) # MSYS like Apple
message(FATAL_ERROR "Portaudio selected as audio API, but development files not found")
endif()
endif()
message(STATUS "Audio API: ${AUDIOAPI}")
message(STATUS "scsynth audio API: ${AUDIOAPI}")

set(scsynth_sources
SC_BufGen.cpp
Expand Down
53 changes: 36 additions & 17 deletions server/supernova/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,29 +124,48 @@ else()
endif()
endif()

if(APPLE OR MSYS)
find_package(Portaudio)
if(NOT PORTAUDIO_FOUND)
message(FATAL_ERROR "Portaudio missing")
endif()
target_compile_definitions(libsupernova PUBLIC PORTAUDIO_BACKEND ${PORTAUDIO_DEFINITIONS})
target_include_directories(libsupernova PUBLIC ${PORTAUDIO_INCLUDE_DIRS})
target_link_libraries(libsupernova ${PORTAUDIO_LIBRARIES})
elseif (WIN32)
target_compile_definitions(libsupernova PUBLIC PORTAUDIO_BACKEND -DPORTAUDIO_BACKEND)
target_include_directories(libsupernova PUBLIC ${PORTAUDIO_INCLUDE_DIRS})
if(MSYS)
target_link_libraries(libsupernova ${PORTAUDIO_LIBRARIES})
if(AUDIOAPI STREQUAL "default")
if(APPLE)
set(AUDIOAPI portaudio)
elseif(WIN32)
set(AUDIOAPI portaudio)
else()
target_link_libraries(libsupernova portaudio)
endif()
else()
set(AUDIOAPI jack)
endif(APPLE)
endif()

if(NOT AUDIOAPI MATCHES "^(jack|coreaudio|portaudio)$")
message(FATAL_ERROR "Unrecognized audio API: ${AUDIOAPI}")
endif()

if(AUDIOAPI STREQUAL "coreaudio")
set(AUDIOAPI portaudio)
message(FATAL_ERROR "supernova: coreaudio API not implemented yet, use 'default' or 'portaudio' instead")
endif()
dyfer marked this conversation as resolved.
Show resolved Hide resolved

if(AUDIOAPI STREQUAL jack)
find_package(Jack REQUIRED)
elseif(AUDIOAPI STREQUAL portaudio AND ((NOT WIN32) OR MSYS)) # MSYS like Apple
find_package(Portaudio REQUIRED)
endif()
message(STATUS "supernova audio API: ${AUDIOAPI}")

if(AUDIOAPI STREQUAL jack)
find_library(JACK NAMES jack)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this necessary with find_package above? seems like the same work done twice in different ways. also dubious of just failing silently if jack isn't found here

if (JACK)
if(JACK)
target_compile_definitions(libsupernova PUBLIC JACK_BACKEND)
target_link_libraries(libsupernova ${JACK})
target_include_directories(libsupernova PUBLIC ${JACK_INCLUDE_DIRS})
endif()
elseif(AUDIOAPI STREQUAL portaudio)
target_include_directories(libsupernova PUBLIC ${PORTAUDIO_INCLUDE_DIRS})
if(WIN32)
target_compile_definitions(libsupernova PUBLIC PORTAUDIO_BACKEND -DPORTAUDIO_BACKEND)
mossheim marked this conversation as resolved.
Show resolved Hide resolved
target_link_libraries(libsupernova portaudio)
else()
target_compile_definitions(libsupernova PUBLIC PORTAUDIO_BACKEND ${PORTAUDIO_DEFINITIONS})
target_link_libraries(libsupernova ${PORTAUDIO_LIBRARIES})
endif()
endif()

find_package(Sndfile)
Expand Down