@@ -264,7 +264,7 @@ enum OptionsType { | |||||
/*! | /*! | ||||
* JACK auto-connect to hardware ports. | * JACK auto-connect to hardware ports. | ||||
*/ | */ | ||||
OPTION_JACK_AUTOCONENCT = 9, | |||||
OPTION_JACK_AUTOCONNECT = 9, | |||||
/*! | /*! | ||||
* JACK Transport master. | * JACK Transport master. | ||||
@@ -1564,7 +1564,7 @@ void CarlaEngine::setOption(const OptionsType option, const int value, const cha | |||||
fOptions.oscUiTimeout = static_cast<uint>(value); | fOptions.oscUiTimeout = static_cast<uint>(value); | ||||
break; | break; | ||||
case OPTION_JACK_AUTOCONENCT: | |||||
case OPTION_JACK_AUTOCONNECT: | |||||
CARLA_ENGINE_SET_OPTION_RUNNING_CHECK | CARLA_ENGINE_SET_OPTION_RUNNING_CHECK | ||||
fOptions.jackAutoConnect = (value != 0); | fOptions.jackAutoConnect = (value != 0); | ||||
break; | break; | ||||
@@ -95,8 +95,8 @@ INCLUDEPATH = . .. plugin \ | |||||
../../utils | ../../utils | ||||
# RtAudio/RtMidi | # RtAudio/RtMidi | ||||
INCLUDEPATH += rtaudio-4.0.11 rtmidi-2.0.1 | |||||
SOURCES += rtaudio-4.0.11/RtAudio.cpp | |||||
INCLUDEPATH += rtaudio-4.0.12 rtmidi-2.0.1 | |||||
SOURCES += rtaudio-4.0.12/RtAudio.cpp | |||||
SOURCES += rtmidi-2.0.1/RtMidi.cpp | SOURCES += rtmidi-2.0.1/RtMidi.cpp | ||||
# Plugin | # Plugin | ||||
@@ -33,6 +33,21 @@ CARLA_BACKEND_START_NAMESPACE | |||||
// ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
static const char** gRetNames = nullptr; | |||||
static std::vector<RtAudio::Api> gRtAudioApis; | |||||
static void initRtApis() | |||||
{ | |||||
static bool initiated = false; | |||||
if (! initiated) | |||||
{ | |||||
initiated = true; | |||||
RtAudio::getCompiledApi(gRtAudioApis); | |||||
} | |||||
} | |||||
RtMidi::Api getMatchedAudioMidiAPi(const RtAudio::Api rtApi) | RtMidi::Api getMatchedAudioMidiAPi(const RtAudio::Api rtApi) | ||||
{ | { | ||||
switch (rtApi) | switch (rtApi) | ||||
@@ -106,6 +121,12 @@ public: | |||||
fUsedPortNames.clear(); | fUsedPortNames.clear(); | ||||
fUsedConnections.clear(); | fUsedConnections.clear(); | ||||
if (gRetNames != nullptr) | |||||
{ | |||||
delete[] gRetNames; | |||||
gRetNames = nullptr; | |||||
} | |||||
} | } | ||||
// ------------------------------------- | // ------------------------------------- | ||||
@@ -933,20 +954,6 @@ private: | |||||
// ----------------------------------------- | // ----------------------------------------- | ||||
static std::vector<RtAudio::Api> sRtAudioApis; | |||||
static void initRtApis() | |||||
{ | |||||
static bool initiated = false; | |||||
if (! initiated) | |||||
{ | |||||
initiated = true; | |||||
RtAudio::getCompiledApi(sRtAudioApis); | |||||
} | |||||
} | |||||
CarlaEngine* CarlaEngine::newRtAudio(RtAudioApi api) | CarlaEngine* CarlaEngine::newRtAudio(RtAudioApi api) | ||||
{ | { | ||||
RtAudio::Api rtApi(RtAudio::UNSPECIFIED); | RtAudio::Api rtApi(RtAudio::UNSPECIFIED); | ||||
@@ -986,16 +993,16 @@ size_t CarlaEngine::getRtAudioApiCount() | |||||
{ | { | ||||
initRtApis(); | initRtApis(); | ||||
return sRtAudioApis.size(); | |||||
return gRtAudioApis.size(); | |||||
} | } | ||||
const char* CarlaEngine::getRtAudioApiName(const unsigned int index) | const char* CarlaEngine::getRtAudioApiName(const unsigned int index) | ||||
{ | { | ||||
initRtApis(); | initRtApis(); | ||||
if (index < sRtAudioApis.size()) | |||||
if (index < gRtAudioApis.size()) | |||||
{ | { | ||||
const RtAudio::Api& api(sRtAudioApis[index]); | |||||
const RtAudio::Api& api(gRtAudioApis[index]); | |||||
switch (api) | switch (api) | ||||
{ | { | ||||
@@ -1035,11 +1042,47 @@ const char** CarlaEngine::getRtAudioApiDeviceNames(const unsigned int index) | |||||
{ | { | ||||
initRtApis(); | initRtApis(); | ||||
if (index < sRtAudioApis.size()) | |||||
if (index < gRtAudioApis.size()) | |||||
{ | { | ||||
const RtAudio::Api& api(sRtAudioApis[index]); | |||||
const RtAudio::Api& api(gRtAudioApis[index]); | |||||
RtAudio rtAudio(api); | RtAudio rtAudio(api); | ||||
if (gRetNames != nullptr) | |||||
{ | |||||
int i=0; | |||||
while (gRetNames[i] != nullptr) | |||||
delete[] gRetNames[i++]; | |||||
delete[] gRetNames; | |||||
gRetNames = nullptr; | |||||
} | |||||
const unsigned int devCount(rtAudio.getDeviceCount()); | |||||
if (devCount > 0) | |||||
{ | |||||
NonRtList<const char*> devNames; | |||||
for (unsigned int i=0; i < devCount; ++i) | |||||
{ | |||||
RtAudio::DeviceInfo devInfo(rtAudio.getDeviceInfo(i)); | |||||
if (devInfo.probed && devInfo.outputChannels > 0 /*&& (devInfo.nativeFormats & RTAUDIO_FLOAT32) != 0*/) | |||||
devNames.append(carla_strdup(devInfo.name.c_str())); | |||||
} | |||||
const unsigned int realDevCount(devNames.count()); | |||||
gRetNames = new const char*[realDevCount+1]; | |||||
for (unsigned int i=0; i < realDevCount; ++i) | |||||
gRetNames[i] = devNames.getAt(i); | |||||
gRetNames[realDevCount] = nullptr; | |||||
devNames.clear(); | |||||
return gRetNames; | |||||
} | |||||
} | } | ||||
return nullptr; | return nullptr; | ||||
@@ -529,7 +529,7 @@ bool carla_engine_init(const char* driverName, const char* clientName) | |||||
# endif | # endif | ||||
standalone.engine->setOption(CarlaBackend::OPTION_MAX_PARAMETERS, static_cast<int>(standalone.options.maxParameters), nullptr); | standalone.engine->setOption(CarlaBackend::OPTION_MAX_PARAMETERS, static_cast<int>(standalone.options.maxParameters), nullptr); | ||||
standalone.engine->setOption(CarlaBackend::OPTION_OSC_UI_TIMEOUT, static_cast<int>(standalone.options.oscUiTimeout), nullptr); | standalone.engine->setOption(CarlaBackend::OPTION_OSC_UI_TIMEOUT, static_cast<int>(standalone.options.oscUiTimeout), nullptr); | ||||
standalone.engine->setOption(CarlaBackend::OPTION_JACK_AUTOCONENCT, standalone.options.jackAutoConnect ? 1 : 0, nullptr); | |||||
standalone.engine->setOption(CarlaBackend::OPTION_JACK_AUTOCONNECT, standalone.options.jackAutoConnect ? 1 : 0, nullptr); | |||||
standalone.engine->setOption(CarlaBackend::OPTION_JACK_TIMEMASTER, standalone.options.jackTimeMaster ? 1 : 0, nullptr); | standalone.engine->setOption(CarlaBackend::OPTION_JACK_TIMEMASTER, standalone.options.jackTimeMaster ? 1 : 0, nullptr); | ||||
# ifdef WANT_RTAUDIO | # ifdef WANT_RTAUDIO | ||||
standalone.engine->setOption(CarlaBackend::OPTION_RTAUDIO_BUFFER_SIZE, static_cast<int>(standalone.options.rtaudioBufferSize), nullptr); | standalone.engine->setOption(CarlaBackend::OPTION_RTAUDIO_BUFFER_SIZE, static_cast<int>(standalone.options.rtaudioBufferSize), nullptr); | ||||
@@ -701,7 +701,7 @@ void carla_set_engine_option(CarlaOptionsType option, int value, const char* val | |||||
standalone.options.oscUiTimeout = static_cast<unsigned int>(value); | standalone.options.oscUiTimeout = static_cast<unsigned int>(value); | ||||
break; | break; | ||||
case CarlaBackend::OPTION_JACK_AUTOCONENCT: | |||||
case CarlaBackend::OPTION_JACK_AUTOCONNECT: | |||||
standalone.options.jackAutoConnect = (value != 0); | standalone.options.jackAutoConnect = (value != 0); | ||||
break; | break; | ||||
@@ -972,18 +972,17 @@ class CarlaMainW(QMainWindow): | |||||
else: | else: | ||||
defaultMode = PROCESS_MODE_CONTINUOUS_RACK | defaultMode = PROCESS_MODE_CONTINUOUS_RACK | ||||
Carla.processMode = settings.value("Engine/ProcessMode", defaultMode, type=int) | |||||
Carla.maxParameters = settings.value("Engine/MaxParameters", MAX_DEFAULT_PARAMETERS, type=int) | |||||
audioDriver = settings.value("Engine/AudioDriver", CARLA_DEFAULT_AUDIO_DRIVER, type=str) | |||||
transportMode = settings.value("Engine/TransportMode", TRANSPORT_MODE_JACK, type=int) | |||||
forceStereo = settings.value("Engine/ForceStereo", False, type=bool) | |||||
preferPluginBridges = settings.value("Engine/PreferPluginBridges", False, type=bool) | |||||
preferUiBridges = settings.value("Engine/PreferUiBridges", True, type=bool) | |||||
useDssiVstChunks = settings.value("Engine/UseDssiVstChunks", False, type=bool) | |||||
transportMode = settings.value("Engine/TransportMode", TRANSPORT_MODE_JACK, type=int) | |||||
forceStereo = settings.value("Engine/ForceStereo", False, type=bool) | |||||
preferPluginBridges = settings.value("Engine/PreferPluginBridges", False, type=bool) | |||||
preferUiBridges = settings.value("Engine/PreferUiBridges", True, type=bool) | |||||
useDssiVstChunks = settings.value("Engine/UseDssiVstChunks", False, type=bool) | |||||
oscUiTimeout = settings.value("Engine/OscUiTimeout", 40, type=int) | |||||
oscUiTimeout = settings.value("Engine/OscUiTimeout", 40, type=int) | |||||
preferredBufferSize = settings.value("Engine/PreferredBufferSize", 512, type=int) | |||||
preferredSampleRate = settings.value("Engine/PreferredSampleRate", 44100, type=int) | |||||
Carla.processMode = settings.value("Engine/ProcessMode", defaultMode, type=int) | |||||
Carla.maxParameters = settings.value("Engine/MaxParameters", MAX_DEFAULT_PARAMETERS, type=int) | |||||
if Carla.processMode == PROCESS_MODE_CONTINUOUS_RACK: | if Carla.processMode == PROCESS_MODE_CONTINUOUS_RACK: | ||||
forceStereo = True | forceStereo = True | ||||
@@ -998,14 +997,26 @@ class CarlaMainW(QMainWindow): | |||||
Carla.host.set_engine_option(OPTION_PREFER_UI_BRIDGES, preferUiBridges, "") | Carla.host.set_engine_option(OPTION_PREFER_UI_BRIDGES, preferUiBridges, "") | ||||
Carla.host.set_engine_option(OPTION_USE_DSSI_VST_CHUNKS, useDssiVstChunks, "") | Carla.host.set_engine_option(OPTION_USE_DSSI_VST_CHUNKS, useDssiVstChunks, "") | ||||
Carla.host.set_engine_option(OPTION_OSC_UI_TIMEOUT, oscUiTimeout, "") | Carla.host.set_engine_option(OPTION_OSC_UI_TIMEOUT, oscUiTimeout, "") | ||||
Carla.host.set_engine_option(OPTION_PREFERRED_BUFFER_SIZE, preferredBufferSize, "") | |||||
Carla.host.set_engine_option(OPTION_PREFERRED_SAMPLE_RATE, preferredSampleRate, "") | |||||
if audioDriver == "JACK": | |||||
jackAutoConnect = settings.value("Engine/JackAutoConnect", False, type=bool) | |||||
jackTimeMaster = settings.value("Engine/JackTimeMaster", False, type=bool) | |||||
Carla.host.set_engine_option(OPTION_JACK_AUTOCONNECT, jackAutoConnect, "") | |||||
Carla.host.set_engine_option(OPTION_JACK_TIMEMASTER, jackTimeMaster, "") | |||||
else: | |||||
rtaudioBufferSize = settings.value("Engine/RtAudioBufferSize", 512, type=int) | |||||
rtaudioSampleRate = settings.value("Engine/RtAudioSampleRate", 44100, type=int) | |||||
rtaudioDevice = settings.value("Engine/RtAudioDevice", "", type=str) | |||||
Carla.host.set_engine_option(OPTION_RTAUDIO_BUFFER_SIZE, rtaudioBufferSize, "") | |||||
Carla.host.set_engine_option(OPTION_RTAUDIO_SAMPLE_RATE, rtaudioSampleRate, "") | |||||
Carla.host.set_engine_option(OPTION_RTAUDIO_SAMPLE_RATE, 0, rtaudioDevice) | |||||
# --------------------------------------------- | # --------------------------------------------- | ||||
# Start | # Start | ||||
audioDriver = settings.value("Engine/AudioDriver", CARLA_DEFAULT_AUDIO_DRIVER, type=str) | |||||
if not Carla.host.engine_init(audioDriver, self.fClientName): | if not Carla.host.engine_init(audioDriver, self.fClientName): | ||||
if self.fFirstEngineInit: | if self.fFirstEngineInit: | ||||
self.fFirstEngineInit = False | self.fFirstEngineInit = False | ||||
@@ -57,6 +57,27 @@ else: | |||||
MACOS = False | MACOS = False | ||||
WINDOWS = False | WINDOWS = False | ||||
# ------------------------------------------------------------------------------------------------------------ | |||||
# Convert a ctypes char** into a python string list | |||||
def charStringList(charPtr): | |||||
i = 0 | |||||
retList = [] | |||||
if not charPtr: | |||||
return retList | |||||
while True: | |||||
char_p = charPtr[i] | |||||
if not char_p: | |||||
break | |||||
retList.append(char_p.decode("utf-8", errors="ignore")) | |||||
i += 1 | |||||
return retList | |||||
# ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
# Convert a ctypes struct into a python dict | # Convert a ctypes struct into a python dict | ||||
@@ -175,7 +196,7 @@ OPTION_PREFER_UI_BRIDGES = 5 | |||||
OPTION_USE_DSSI_VST_CHUNKS = 6 | OPTION_USE_DSSI_VST_CHUNKS = 6 | ||||
OPTION_MAX_PARAMETERS = 7 | OPTION_MAX_PARAMETERS = 7 | ||||
OPTION_OSC_UI_TIMEOUT = 8 | OPTION_OSC_UI_TIMEOUT = 8 | ||||
OPTION_JACK_AUTOCONENCT = 9 | |||||
OPTION_JACK_AUTOCONNECT = 9 | |||||
OPTION_JACK_TIMEMASTER = 10 | OPTION_JACK_TIMEMASTER = 10 | ||||
OPTION_RTAUDIO_BUFFER_SIZE = 11 | OPTION_RTAUDIO_BUFFER_SIZE = 11 | ||||
OPTION_RTAUDIO_SAMPLE_RATE = 12 | OPTION_RTAUDIO_SAMPLE_RATE = 12 | ||||
@@ -635,8 +656,7 @@ class Host(object): | |||||
return self.lib.carla_get_engine_driver_name(index) | return self.lib.carla_get_engine_driver_name(index) | ||||
def get_engine_driver_device_names(self, index): | def get_engine_driver_device_names(self, index): | ||||
# FIXME | |||||
return self.lib.carla_get_engine_driver_device_names(index) | |||||
return charStringList(self.lib.carla_get_engine_driver_device_names(index)) | |||||
def get_internal_plugin_count(self): | def get_internal_plugin_count(self): | ||||
return self.lib.carla_get_internal_plugin_count() | return self.lib.carla_get_internal_plugin_count() | ||||
@@ -220,8 +220,8 @@ const char* OptionsType2Str(const OptionsType& type) | |||||
return "OPTION_MAX_PARAMETERS"; | return "OPTION_MAX_PARAMETERS"; | ||||
case OPTION_OSC_UI_TIMEOUT: | case OPTION_OSC_UI_TIMEOUT: | ||||
return "OPTION_OSC_UI_TIMEOUT"; | return "OPTION_OSC_UI_TIMEOUT"; | ||||
case OPTION_JACK_AUTOCONENCT: | |||||
return "OPTION_JACK_AUTOCONENCT"; | |||||
case OPTION_JACK_AUTOCONNECT: | |||||
return "OPTION_JACK_AUTOCONNECT"; | |||||
case OPTION_JACK_TIMEMASTER: | case OPTION_JACK_TIMEMASTER: | ||||
return "OPTION_JACK_TIMEMASTER"; | return "OPTION_JACK_TIMEMASTER"; | ||||
#ifdef WANT_RTAUDIO | #ifdef WANT_RTAUDIO | ||||