1 /*
2 * Carla Standalone
3 * Copyright (C) 2011-2021 Filipe Coelho <falktx@falktx.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
16 */
17
18 // TODO:
19 // Check carla_stderr2("Engine is not running"); <= prepend func name and args
20
21 #include "CarlaHostImpl.hpp"
22 #include "CarlaMIDI.h"
23
24 #include "CarlaEngineInit.hpp"
25 #include "CarlaPlugin.hpp"
26
27 #include "CarlaBackendUtils.hpp"
28 #include "CarlaBase64Utils.hpp"
29 #include "ThreadSafeFFTW.hpp"
30 #ifndef BUILD_BRIDGE
31 # include "CarlaLogThread.hpp"
32 #endif
33
34 #include "water/files/File.h"
35
36 #define CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(cond, msg, ret) \
37 if (! (cond)) { \
38 carla_stderr2("%s: " msg, __FUNCTION__); \
39 if (handle->isStandalone) \
40 ((CarlaHostStandalone*)handle)->lastError = msg; \
41 return ret; \
42 }
43
44 // --------------------------------------------------------------------------------------------------------------------
45
46 #ifdef USING_JUCE
47 static void carla_standalone_juce_init(void);
48 static void carla_standalone_juce_idle(void);
49 static void carla_standalone_juce_cleanup(void);
50 # define carla_juce_init carla_standalone_juce_init
51 # define carla_juce_idle carla_standalone_juce_idle
52 # define carla_juce_cleanup carla_standalone_juce_cleanup
53 # include "utils/JUCE.cpp"
54 # undef carla_juce_init
55 # undef carla_juce_idle
56 # undef carla_juce_cleanup
57 #endif
58
59 // -------------------------------------------------------------------------------------------------------------------
60 // Always return a valid string ptr for standalone functions
61
62 static const char* const gNullCharPtr = "";
63
checkStringPtr(const char * & charPtr)64 static void checkStringPtr(const char*& charPtr) noexcept
65 {
66 if (charPtr == nullptr)
67 charPtr = gNullCharPtr;
68 }
69
70 // -------------------------------------------------------------------------------------------------------------------
71 // Constructors
72
_CarlaPluginInfo()73 _CarlaPluginInfo::_CarlaPluginInfo() noexcept
74 : type(CB::PLUGIN_NONE),
75 category(CB::PLUGIN_CATEGORY_NONE),
76 hints(0x0),
77 optionsAvailable(0x0),
78 optionsEnabled(0x0),
79 filename(gNullCharPtr),
80 name(gNullCharPtr),
81 label(gNullCharPtr),
82 maker(gNullCharPtr),
83 copyright(gNullCharPtr),
84 iconName(gNullCharPtr),
85 uniqueId(0) {}
86
~_CarlaPluginInfo()87 _CarlaPluginInfo::~_CarlaPluginInfo() noexcept
88 {
89 if (label != gNullCharPtr)
90 delete[] label;
91 if (maker != gNullCharPtr)
92 delete[] maker;
93 if (copyright != gNullCharPtr)
94 delete[] copyright;
95 }
96
_CarlaParameterInfo()97 _CarlaParameterInfo::_CarlaParameterInfo() noexcept
98 : name(gNullCharPtr),
99 symbol(gNullCharPtr),
100 unit(gNullCharPtr),
101 comment(gNullCharPtr),
102 groupName(gNullCharPtr),
103 scalePointCount(0) {}
104
~_CarlaParameterInfo()105 _CarlaParameterInfo::~_CarlaParameterInfo() noexcept
106 {
107 if (name != gNullCharPtr)
108 delete[] name;
109 if (symbol != gNullCharPtr)
110 delete[] symbol;
111 if (unit != gNullCharPtr)
112 delete[] unit;
113 if (comment != gNullCharPtr)
114 delete[] comment;
115 if (groupName != gNullCharPtr)
116 delete[] groupName;
117 }
118
_CarlaScalePointInfo()119 _CarlaScalePointInfo::_CarlaScalePointInfo() noexcept
120 : value(0.0f),
121 label(gNullCharPtr) {}
122
~_CarlaScalePointInfo()123 _CarlaScalePointInfo::~_CarlaScalePointInfo() noexcept
124 {
125 if (label != gNullCharPtr)
126 delete[] label;
127 }
128
_CarlaTransportInfo()129 _CarlaTransportInfo::_CarlaTransportInfo() noexcept
130 : playing(false),
131 frame(0),
132 bar(0),
133 beat(0),
134 tick(0),
135 bpm(0.0) {}
136
clear()137 void _CarlaTransportInfo::clear() noexcept
138 {
139 playing = false;
140 frame = 0;
141 bar = 0;
142 beat = 0;
143 tick = 0;
144 bpm = 0.0;
145 }
146
147 // --------------------------------------------------------------------------------------------------------------------
148
149 using CarlaBackend::CarlaPluginPtr;
150
151 // --------------------------------------------------------------------------------------------------------------------
152
carla_get_engine_driver_count()153 uint carla_get_engine_driver_count()
154 {
155 carla_debug("carla_get_engine_driver_count()");
156
157 return CarlaEngine::getDriverCount();
158 }
159
carla_get_engine_driver_name(uint index)160 const char* carla_get_engine_driver_name(uint index)
161 {
162 carla_debug("carla_get_engine_driver_name(%i)", index);
163
164 return CarlaEngine::getDriverName(index);
165 }
166
carla_get_engine_driver_device_names(uint index)167 const char* const* carla_get_engine_driver_device_names(uint index)
168 {
169 carla_debug("carla_get_engine_driver_device_names(%i)", index);
170
171 return CarlaEngine::getDriverDeviceNames(index);
172 }
173
carla_get_engine_driver_device_info(uint index,const char * name)174 const EngineDriverDeviceInfo* carla_get_engine_driver_device_info(uint index, const char* name)
175 {
176 CARLA_SAFE_ASSERT_RETURN(name != nullptr, nullptr);
177
178 static EngineDriverDeviceInfo retDevInfo;
179 static const uint32_t nullBufferSizes[] = { 0 };
180 static const double nullSampleRates[] = { 0.0 };
181
182 carla_debug("carla_get_engine_driver_device_info(%i, \"%s\")", index, name);
183
184 if (const EngineDriverDeviceInfo* const devInfo = CarlaEngine::getDriverDeviceInfo(index, name))
185 {
186 retDevInfo.hints = devInfo->hints;
187 retDevInfo.bufferSizes = (devInfo->bufferSizes != nullptr) ? devInfo->bufferSizes : nullBufferSizes;
188 retDevInfo.sampleRates = (devInfo->sampleRates != nullptr) ? devInfo->sampleRates : nullSampleRates;
189 }
190 else
191 {
192 retDevInfo.hints = 0x0;
193 retDevInfo.bufferSizes = nullBufferSizes;
194 retDevInfo.sampleRates = nullSampleRates;
195 }
196
197 return &retDevInfo;
198 }
199
carla_show_engine_driver_device_control_panel(uint index,const char * name)200 bool carla_show_engine_driver_device_control_panel(uint index, const char* name)
201 {
202 return CarlaEngine::showDriverDeviceControlPanel(index, name);
203 }
204
205 // --------------------------------------------------------------------------------------------------------------------
206
carla_standalone_host_init(void)207 CarlaHostHandle carla_standalone_host_init(void)
208 {
209 #ifdef CARLA_OS_UNIX
210 static const ThreadSafeFFTW sThreadSafeFFTW;
211 #endif
212
213 static CarlaHostStandalone gStandalone;
214
215 return &gStandalone;
216 }
217
carla_get_engine_from_handle(CarlaHostHandle handle)218 CarlaEngine* carla_get_engine_from_handle(CarlaHostHandle handle)
219 {
220 carla_debug("carla_get_engine(%p)", handle);
221
222 return handle->engine;
223 }
224
225 // --------------------------------------------------------------------------------------------------------------------
226
carla_engine_init_common(const CarlaHostStandalone & standalone,CarlaEngine * const engine)227 static void carla_engine_init_common(const CarlaHostStandalone& standalone, CarlaEngine* const engine)
228 {
229 engine->setCallback(standalone.engineCallback, standalone.engineCallbackPtr);
230 engine->setFileCallback(standalone.fileCallback, standalone.fileCallbackPtr);
231
232 using water::File;
233 const File waterBinaryDir(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory());
234
235 #ifdef BUILD_BRIDGE
236 /*
237 if (const char* const forceStereo = std::getenv("ENGINE_OPTION_FORCE_STEREO"))
238 engine->setOption(CB::ENGINE_OPTION_FORCE_STEREO, (std::strcmp(forceStereo, "true") == 0) ? 1 : 0, nullptr);
239
240 if (const char* const preferPluginBridges = std::getenv("ENGINE_OPTION_PREFER_PLUGIN_BRIDGES"))
241 engine->setOption(CB::ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, (std::strcmp(preferPluginBridges, "true") == 0) ? 1 : 0, nullptr);
242
243 if (const char* const preferUiBridges = std::getenv("ENGINE_OPTION_PREFER_UI_BRIDGES"))
244 engine->setOption(CB::ENGINE_OPTION_PREFER_UI_BRIDGES, (std::strcmp(preferUiBridges, "true") == 0) ? 1 : 0, nullptr);
245 */
246
247 if (const char* const uisAlwaysOnTop = std::getenv("ENGINE_OPTION_UIS_ALWAYS_ON_TOP"))
248 engine->setOption(CB::ENGINE_OPTION_UIS_ALWAYS_ON_TOP, (std::strcmp(uisAlwaysOnTop, "true") == 0) ? 1 : 0, nullptr);
249
250 if (const char* const maxParameters = std::getenv("ENGINE_OPTION_MAX_PARAMETERS"))
251 engine->setOption(CB::ENGINE_OPTION_MAX_PARAMETERS, std::atoi(maxParameters), nullptr);
252
253 if (const char* const resetXruns = std::getenv("ENGINE_OPTION_RESET_XRUNS"))
254 engine->setOption(CB::ENGINE_OPTION_RESET_XRUNS, (std::strcmp(resetXruns, "true") == 0) ? 1 : 0, nullptr);
255
256 if (const char* const uiBridgesTimeout = std::getenv("ENGINE_OPTION_UI_BRIDGES_TIMEOUT"))
257 engine->setOption(CB::ENGINE_OPTION_UI_BRIDGES_TIMEOUT, std::atoi(uiBridgesTimeout), nullptr);
258
259 if (const char* const pathAudio = std::getenv("ENGINE_OPTION_FILE_PATH_AUDIO"))
260 engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_AUDIO, pathAudio);
261
262 if (const char* const pathMIDI = std::getenv("ENGINE_OPTION_FILE_PATH_MIDI"))
263 engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_MIDI, pathMIDI);
264
265 if (const char* const pathLADSPA = std::getenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA"))
266 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LADSPA, pathLADSPA);
267
268 if (const char* const pathDSSI = std::getenv("ENGINE_OPTION_PLUGIN_PATH_DSSI"))
269 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_DSSI, pathDSSI);
270
271 if (const char* const pathLV2 = std::getenv("ENGINE_OPTION_PLUGIN_PATH_LV2"))
272 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LV2, pathLV2);
273
274 if (const char* const pathVST2 = std::getenv("ENGINE_OPTION_PLUGIN_PATH_VST2"))
275 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_VST2, pathVST2);
276
277 if (const char* const pathVST3 = std::getenv("ENGINE_OPTION_PLUGIN_PATH_VST3"))
278 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_VST3, pathVST3);
279
280 if (const char* const pathSF2 = std::getenv("ENGINE_OPTION_PLUGIN_PATH_SF2"))
281 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_SF2, pathSF2);
282
283 if (const char* const pathSFZ = std::getenv("ENGINE_OPTION_PLUGIN_PATH_SFZ"))
284 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_SFZ, pathSFZ);
285
286 if (const char* const binaryDir = std::getenv("ENGINE_OPTION_PATH_BINARIES"))
287 engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, binaryDir);
288 else
289 engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, waterBinaryDir.getFullPathName().toRawUTF8());
290
291 if (const char* const resourceDir = std::getenv("ENGINE_OPTION_PATH_RESOURCES"))
292 engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, resourceDir);
293 else
294 engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, waterBinaryDir.getChildFile("resources").getFullPathName().toRawUTF8());
295
296 if (const char* const preventBadBehaviour = std::getenv("ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR"))
297 engine->setOption(CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, (std::strcmp(preventBadBehaviour, "true") == 0) ? 1 : 0, nullptr);
298
299 if (const char* const frontendWinId = std::getenv("ENGINE_OPTION_FRONTEND_WIN_ID"))
300 engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, frontendWinId);
301 #else
302 engine->setOption(CB::ENGINE_OPTION_FORCE_STEREO, standalone.engineOptions.forceStereo ? 1 : 0, nullptr);
303 engine->setOption(CB::ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, standalone.engineOptions.preferPluginBridges ? 1 : 0, nullptr);
304 engine->setOption(CB::ENGINE_OPTION_PREFER_UI_BRIDGES, standalone.engineOptions.preferUiBridges ? 1 : 0, nullptr);
305 engine->setOption(CB::ENGINE_OPTION_UIS_ALWAYS_ON_TOP, standalone.engineOptions.uisAlwaysOnTop ? 1 : 0, nullptr);
306 engine->setOption(CB::ENGINE_OPTION_MAX_PARAMETERS, static_cast<int>(standalone.engineOptions.maxParameters), nullptr);
307 engine->setOption(CB::ENGINE_OPTION_RESET_XRUNS, standalone.engineOptions.resetXruns ? 1 : 0, nullptr);
308 engine->setOption(CB::ENGINE_OPTION_UI_BRIDGES_TIMEOUT, static_cast<int>(standalone.engineOptions.uiBridgesTimeout), nullptr);
309 engine->setOption(CB::ENGINE_OPTION_AUDIO_BUFFER_SIZE, static_cast<int>(standalone.engineOptions.audioBufferSize), nullptr);
310 engine->setOption(CB::ENGINE_OPTION_AUDIO_SAMPLE_RATE, static_cast<int>(standalone.engineOptions.audioSampleRate), nullptr);
311 engine->setOption(CB::ENGINE_OPTION_AUDIO_TRIPLE_BUFFER, standalone.engineOptions.audioTripleBuffer ? 1 : 0, nullptr);
312
313 if (standalone.engineOptions.audioDriver != nullptr)
314 engine->setOption(CB::ENGINE_OPTION_AUDIO_DRIVER, 0, standalone.engineOptions.audioDriver);
315
316 if (standalone.engineOptions.audioDevice != nullptr)
317 engine->setOption(CB::ENGINE_OPTION_AUDIO_DEVICE, 0, standalone.engineOptions.audioDevice);
318
319 engine->setOption(CB::ENGINE_OPTION_OSC_ENABLED, standalone.engineOptions.oscEnabled, nullptr);
320 engine->setOption(CB::ENGINE_OPTION_OSC_PORT_TCP, standalone.engineOptions.oscPortTCP, nullptr);
321 engine->setOption(CB::ENGINE_OPTION_OSC_PORT_UDP, standalone.engineOptions.oscPortUDP, nullptr);
322
323 if (standalone.engineOptions.pathAudio != nullptr)
324 engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_AUDIO, standalone.engineOptions.pathAudio);
325
326 if (standalone.engineOptions.pathMIDI != nullptr)
327 engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_MIDI, standalone.engineOptions.pathMIDI);
328
329 if (standalone.engineOptions.pathLADSPA != nullptr)
330 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LADSPA, standalone.engineOptions.pathLADSPA);
331
332 if (standalone.engineOptions.pathDSSI != nullptr)
333 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_DSSI, standalone.engineOptions.pathDSSI);
334
335 if (standalone.engineOptions.pathLV2 != nullptr)
336 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LV2, standalone.engineOptions.pathLV2);
337
338 if (standalone.engineOptions.pathVST2 != nullptr)
339 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_VST2, standalone.engineOptions.pathVST2);
340
341 if (standalone.engineOptions.pathVST3 != nullptr)
342 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_VST3, standalone.engineOptions.pathVST3);
343
344 if (standalone.engineOptions.pathSF2 != nullptr)
345 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_SF2, standalone.engineOptions.pathSF2);
346
347 if (standalone.engineOptions.pathSFZ != nullptr)
348 engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_SFZ, standalone.engineOptions.pathSFZ);
349
350 if (standalone.engineOptions.binaryDir != nullptr && standalone.engineOptions.binaryDir[0] != '\0')
351 engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, standalone.engineOptions.binaryDir);
352 else
353 engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, waterBinaryDir.getFullPathName().toRawUTF8());
354
355 if (standalone.engineOptions.resourceDir != nullptr && standalone.engineOptions.resourceDir[0] != '\0')
356 engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, standalone.engineOptions.resourceDir);
357
358 engine->setOption(CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, standalone.engineOptions.preventBadBehaviour ? 1 : 0, nullptr);
359
360 engine->setOption(CB::ENGINE_OPTION_FRONTEND_BACKGROUND_COLOR, static_cast<int>(standalone.engineOptions.bgColor), nullptr);
361 engine->setOption(CB::ENGINE_OPTION_FRONTEND_FOREGROUND_COLOR, static_cast<int>(standalone.engineOptions.fgColor), nullptr);
362 engine->setOption(CB::ENGINE_OPTION_FRONTEND_UI_SCALE, static_cast<int>(standalone.engineOptions.uiScale * 1000.0f), nullptr);
363
364 if (standalone.engineOptions.frontendWinId != 0)
365 {
366 char strBuf[STR_MAX+1];
367 strBuf[STR_MAX] = '\0';
368 std::snprintf(strBuf, STR_MAX, P_UINTPTR, standalone.engineOptions.frontendWinId);
369 engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, strBuf);
370 }
371 else
372 {
373 engine->setOption(CB::ENGINE_OPTION_FRONTEND_WIN_ID, 0, "0");
374 }
375
376 # ifndef CARLA_OS_WIN
377 if (standalone.engineOptions.wine.executable != nullptr && standalone.engineOptions.wine.executable[0] != '\0')
378 engine->setOption(CB::ENGINE_OPTION_WINE_EXECUTABLE, 0, standalone.engineOptions.wine.executable);
379
380 engine->setOption(CB::ENGINE_OPTION_WINE_AUTO_PREFIX, standalone.engineOptions.wine.autoPrefix ? 1 : 0, nullptr);
381
382 if (standalone.engineOptions.wine.fallbackPrefix != nullptr && standalone.engineOptions.wine.fallbackPrefix[0] != '\0')
383 engine->setOption(CB::ENGINE_OPTION_WINE_FALLBACK_PREFIX, 0, standalone.engineOptions.wine.fallbackPrefix);
384
385 engine->setOption(CB::ENGINE_OPTION_WINE_RT_PRIO_ENABLED, standalone.engineOptions.wine.rtPrio ? 1 : 0, nullptr);
386 engine->setOption(CB::ENGINE_OPTION_WINE_BASE_RT_PRIO, standalone.engineOptions.wine.baseRtPrio, nullptr);
387 engine->setOption(CB::ENGINE_OPTION_WINE_SERVER_RT_PRIO, standalone.engineOptions.wine.serverRtPrio, nullptr);
388 # endif
389
390 engine->setOption(CB::ENGINE_OPTION_CLIENT_NAME_PREFIX, 0, standalone.engineOptions.clientNamePrefix);
391
392 engine->setOption(CB::ENGINE_OPTION_PLUGINS_ARE_STANDALONE, standalone.engineOptions.pluginsAreStandalone, nullptr);
393 #endif // BUILD_BRIDGE
394 }
395
carla_engine_init(CarlaHostHandle handle,const char * driverName,const char * clientName)396 bool carla_engine_init(CarlaHostHandle handle, const char* driverName, const char* clientName)
397 {
398 CARLA_SAFE_ASSERT_RETURN(driverName != nullptr && driverName[0] != '\0', false);
399 CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false);
400 carla_debug("carla_engine_init(%p, \"%s\", \"%s\")", handle, driverName, clientName);
401
402 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->isStandalone, "Must be a standalone host handle", false);
403 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine == nullptr, "Engine is already initialized", false);
404
405 #ifdef CARLA_OS_WIN
406 carla_setenv("WINEASIO_CLIENT_NAME", clientName);
407 #endif
408
409 #ifdef USING_JUCE
410 carla_standalone_juce_init();
411 #endif
412
413 CarlaHostStandalone& shandle((CarlaHostStandalone&)*handle);
414
415 CarlaEngine* const engine = CarlaEngine::newDriverByName(driverName);
416 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(engine != nullptr, "The selected audio driver is not available", false);
417
418 shandle.engine = engine;
419
420 #ifdef BUILD_BRIDGE
421 if (std::getenv("CARLA_BRIDGE_DUMMY") != nullptr)
422 {
423 // engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, CB::ENGINE_PROCESS_MODE_PATCHBAY, nullptr);
424 engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, CB::ENGINE_PROCESS_MODE_CONTINUOUS_RACK, nullptr);
425 engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, CB::ENGINE_TRANSPORT_MODE_INTERNAL, nullptr);
426
427 engine->setOption(CB::ENGINE_OPTION_AUDIO_BUFFER_SIZE, 4096, nullptr);
428 engine->setOption(CB::ENGINE_OPTION_AUDIO_SAMPLE_RATE, 48000, nullptr);
429 }
430 else
431 {
432 engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, CB::ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, nullptr);
433 engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, CB::ENGINE_TRANSPORT_MODE_JACK, nullptr);
434 }
435 engine->setOption(CB::ENGINE_OPTION_FORCE_STEREO, false, nullptr);
436 engine->setOption(CB::ENGINE_OPTION_PREFER_PLUGIN_BRIDGES, false, nullptr);
437 engine->setOption(CB::ENGINE_OPTION_PREFER_UI_BRIDGES, false, nullptr);
438 #else
439 engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, static_cast<int>(shandle.engineOptions.processMode), nullptr);
440 engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, static_cast<int>(shandle.engineOptions.transportMode), shandle.engineOptions.transportExtra);
441 #endif
442
443 carla_engine_init_common(shandle, engine);
444
445 if (engine->init(clientName))
446 {
447 #ifndef BUILD_BRIDGE
448 if (shandle.logThreadEnabled && std::getenv("CARLA_LOGS_DISABLED") == nullptr)
449 shandle.logThread.init();
450 #endif
451 shandle.lastError = "No error";
452 return true;
453 }
454 else
455 {
456 shandle.lastError = engine->getLastError();
457 shandle.engine = nullptr;
458 delete engine;
459 #ifdef USING_JUCE
460 carla_standalone_juce_cleanup();
461 #endif
462 return false;
463 }
464 }
465
466 #ifdef BUILD_BRIDGE
carla_engine_init_bridge(CarlaHostHandle handle,const char audioBaseName[6+1],const char rtClientBaseName[6+1],const char nonRtClientBaseName[6+1],const char nonRtServerBaseName[6+1],const char * const clientName)467 bool carla_engine_init_bridge(CarlaHostHandle handle,
468 const char audioBaseName[6+1],
469 const char rtClientBaseName[6+1],
470 const char nonRtClientBaseName[6+1],
471 const char nonRtServerBaseName[6+1],
472 const char* const clientName)
473 {
474 CARLA_SAFE_ASSERT_RETURN(audioBaseName != nullptr && audioBaseName[0] != '\0', false);
475 CARLA_SAFE_ASSERT_RETURN(rtClientBaseName != nullptr && rtClientBaseName[0] != '\0', false);
476 CARLA_SAFE_ASSERT_RETURN(nonRtClientBaseName != nullptr && nonRtClientBaseName[0] != '\0', false);
477 CARLA_SAFE_ASSERT_RETURN(nonRtServerBaseName != nullptr && nonRtServerBaseName[0] != '\0', false);
478 CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false);
479 carla_debug("carla_engine_init_bridge(%p, \"%s\", \"%s\", \"%s\", \"%s\", \"%s\")",
480 handle, audioBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName, clientName);
481
482 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->isStandalone, "Must be a standalone host handle", false);
483 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine == nullptr, "Engine is already initialized", false);
484
485 CarlaScopedPointer<CarlaEngine> engine(CB::EngineInit::newBridge(audioBaseName,
486 rtClientBaseName,
487 nonRtClientBaseName,
488 nonRtServerBaseName));
489
490 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(engine != nullptr, "The selected audio driver is not available", false);
491
492 engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, CB::ENGINE_PROCESS_MODE_BRIDGE, nullptr);
493 engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, CB::ENGINE_TRANSPORT_MODE_BRIDGE, nullptr);
494
495 CarlaHostStandalone& shandle((CarlaHostStandalone&)*handle);
496
497 carla_engine_init_common(shandle, engine);
498
499 if (engine->init(clientName))
500 {
501 shandle.lastError = "No error";
502 shandle.engine = engine.release();
503 return true;
504 }
505 else
506 {
507 shandle.lastError = engine->getLastError();
508 return false;
509 }
510 }
511 #endif
512
carla_engine_close(CarlaHostHandle handle)513 bool carla_engine_close(CarlaHostHandle handle)
514 {
515 carla_debug("carla_engine_close(%p)", handle);
516
517 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->isStandalone, "Must be a standalone host handle", false);
518 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
519
520 CarlaHostStandalone& shandle((CarlaHostStandalone&)*handle);
521
522 CarlaEngine* const engine = shandle.engine;
523
524 engine->setAboutToClose();
525 engine->removeAllPlugins();
526
527 const bool closed = engine->close();
528
529 if (! closed)
530 shandle.lastError = engine->getLastError();
531
532 #ifndef BUILD_BRIDGE
533 shandle.logThread.stop();
534 #endif
535
536 shandle.engine = nullptr;
537 delete engine;
538
539 #ifdef USING_JUCE
540 carla_standalone_juce_cleanup();
541 #endif
542 return closed;
543 }
544
carla_engine_idle(CarlaHostHandle handle)545 void carla_engine_idle(CarlaHostHandle handle)
546 {
547 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->isStandalone,);
548
549 handle->engine->idle();
550
551 #ifdef USING_JUCE
552 if (handle->isStandalone)
553 carla_standalone_juce_idle();
554 #endif
555 }
556
carla_is_engine_running(CarlaHostHandle handle)557 bool carla_is_engine_running(CarlaHostHandle handle)
558 {
559 return (handle->engine != nullptr && handle->engine->isRunning());
560 }
561
carla_get_runtime_engine_info(CarlaHostHandle handle)562 const CarlaRuntimeEngineInfo* carla_get_runtime_engine_info(CarlaHostHandle handle)
563 {
564 static CarlaRuntimeEngineInfo retInfo;
565
566 // reset
567 retInfo.load = 0.0f;
568 retInfo.xruns = 0;
569
570 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retInfo);
571
572 retInfo.load = handle->engine->getDSPLoad();
573 retInfo.xruns = handle->engine->getTotalXruns();
574
575 return &retInfo;
576 }
577
578 #ifndef BUILD_BRIDGE
carla_get_runtime_engine_driver_device_info(CarlaHostHandle handle)579 const CarlaRuntimeEngineDriverDeviceInfo* carla_get_runtime_engine_driver_device_info(CarlaHostHandle handle)
580 {
581 static CarlaRuntimeEngineDriverDeviceInfo retInfo;
582
583 // reset
584 retInfo.name = gNullCharPtr;
585 retInfo.hints = 0x0;
586 retInfo.bufferSize = 0;
587 retInfo.bufferSizes = nullptr;
588 retInfo.sampleRate = 0.0;
589 retInfo.sampleRates = nullptr;
590
591 const char* audioDriver;
592 const char* audioDevice;
593
594 if (CarlaEngine* const engine = handle->engine)
595 {
596 audioDriver = engine->getCurrentDriverName();
597 audioDevice = engine->getOptions().audioDevice;
598
599 retInfo.bufferSize = engine->getBufferSize();
600 retInfo.sampleRate = engine->getSampleRate();
601 }
602 else if (handle->isStandalone)
603 {
604 CarlaHostStandalone& shandle((CarlaHostStandalone&)*handle);
605
606 audioDriver = shandle.engineOptions.audioDriver;
607 audioDevice = shandle.engineOptions.audioDevice;
608
609 retInfo.bufferSize = shandle.engineOptions.audioBufferSize;
610 retInfo.sampleRate = shandle.engineOptions.audioSampleRate;
611 }
612 else
613 {
614 return &retInfo;
615 }
616 CARLA_SAFE_ASSERT_RETURN(audioDriver != nullptr, &retInfo);
617 CARLA_SAFE_ASSERT_RETURN(audioDevice != nullptr, &retInfo);
618
619 uint index = 0;
620 uint count = CarlaEngine::getDriverCount();
621 for (; index<count; ++index)
622 {
623 const char* const testDriverName = CarlaEngine::getDriverName(index);
624 CARLA_SAFE_ASSERT_CONTINUE(testDriverName != nullptr);
625
626 if (std::strcmp(testDriverName, audioDriver) == 0)
627 break;
628 }
629 CARLA_SAFE_ASSERT_RETURN(index != count, &retInfo);
630
631 const EngineDriverDeviceInfo* const devInfo = CarlaEngine::getDriverDeviceInfo(index, audioDevice);
632 CARLA_SAFE_ASSERT_RETURN(devInfo != nullptr, &retInfo);
633
634 retInfo.name = audioDevice;
635 retInfo.hints = devInfo->hints;
636 retInfo.bufferSizes = devInfo->bufferSizes;
637 retInfo.sampleRates = devInfo->sampleRates;
638
639 return &retInfo;
640 }
641
carla_set_engine_buffer_size_and_sample_rate(CarlaHostHandle handle,uint bufferSize,double sampleRate)642 bool carla_set_engine_buffer_size_and_sample_rate(CarlaHostHandle handle, uint bufferSize, double sampleRate)
643 {
644 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, false);
645 carla_debug("carla_set_engine_buffer_size_and_sample_rate(%p, %u, %f)", handle, bufferSize, sampleRate);
646
647 return handle->engine->setBufferSizeAndSampleRate(bufferSize, sampleRate);
648 }
649
carla_show_engine_device_control_panel(CarlaHostHandle handle)650 bool carla_show_engine_device_control_panel(CarlaHostHandle handle)
651 {
652 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, false);
653 carla_debug("carla_show_engine_device_control_panel(%p)", handle);
654
655 return handle->engine->showDeviceControlPanel();
656 }
657 #endif // BUILD_BRIDGE
658
carla_clear_engine_xruns(CarlaHostHandle handle)659 void carla_clear_engine_xruns(CarlaHostHandle handle)
660 {
661 if (handle->engine != nullptr)
662 handle->engine->clearXruns();
663 }
664
carla_cancel_engine_action(CarlaHostHandle handle)665 void carla_cancel_engine_action(CarlaHostHandle handle)
666 {
667 if (handle->engine != nullptr)
668 handle->engine->setActionCanceled(true);
669 }
670
carla_set_engine_about_to_close(CarlaHostHandle handle)671 bool carla_set_engine_about_to_close(CarlaHostHandle handle)
672 {
673 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, true);
674 carla_debug("carla_set_engine_about_to_close(%p)", handle);
675
676 return handle->engine->setAboutToClose();
677 }
678
carla_set_engine_callback(CarlaHostHandle handle,EngineCallbackFunc func,void * ptr)679 void carla_set_engine_callback(CarlaHostHandle handle, EngineCallbackFunc func, void* ptr)
680 {
681 carla_debug("carla_set_engine_callback(%p, %p, %p)", handle, func, ptr);
682
683 if (handle->isStandalone)
684 {
685 CarlaHostStandalone& shandle((CarlaHostStandalone&)*handle);
686
687 shandle.engineCallback = func;
688 shandle.engineCallbackPtr = ptr;
689
690 #ifndef BUILD_BRIDGE
691 shandle.logThread.setCallback(func, ptr);
692 #endif
693 }
694
695 if (handle->engine != nullptr)
696 handle->engine->setCallback(func, ptr);
697 }
698
carla_set_engine_option(CarlaHostHandle handle,EngineOption option,int value,const char * valueStr)699 void carla_set_engine_option(CarlaHostHandle handle, EngineOption option, int value, const char* valueStr)
700 {
701 carla_debug("carla_set_engine_option(%p, %i:%s, %i, \"%s\")",
702 handle, option, CB::EngineOption2Str(option), value, valueStr);
703
704 if (handle->isStandalone)
705 {
706 CarlaHostStandalone& shandle((CarlaHostStandalone&)*handle);
707
708 switch (option)
709 {
710 case CB::ENGINE_OPTION_DEBUG:
711 break;
712
713 case CB::ENGINE_OPTION_PROCESS_MODE:
714 CARLA_SAFE_ASSERT_RETURN(value >= CB::ENGINE_PROCESS_MODE_SINGLE_CLIENT && value < CB::ENGINE_PROCESS_MODE_BRIDGE,);
715 shandle.engineOptions.processMode = static_cast<CB::EngineProcessMode>(value);
716 break;
717
718 case CB::ENGINE_OPTION_TRANSPORT_MODE:
719 CARLA_SAFE_ASSERT_RETURN(value >= CB::ENGINE_TRANSPORT_MODE_DISABLED && value <= CB::ENGINE_TRANSPORT_MODE_BRIDGE,);
720
721 // jack transport cannot be disabled in multi-client
722 if (shandle.engineOptions.processMode == CB::ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
723 && value != CB::ENGINE_TRANSPORT_MODE_JACK)
724 {
725 shandle.engineOptions.transportMode = CB::ENGINE_TRANSPORT_MODE_JACK;
726
727 if (shandle.engineCallback != nullptr)
728 shandle.engineCallback(shandle.engineCallbackPtr,
729 CB::ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED,
730 0,
731 CB::ENGINE_TRANSPORT_MODE_JACK,
732 0, 0, 0.0f,
733 shandle.engineOptions.transportExtra);
734 }
735 else
736 {
737 shandle.engineOptions.transportMode = static_cast<CB::EngineTransportMode>(value);
738 }
739
740 delete[] shandle.engineOptions.transportExtra;
741 if (value != CB::ENGINE_TRANSPORT_MODE_DISABLED && valueStr != nullptr)
742 shandle.engineOptions.transportExtra = carla_strdup_safe(valueStr);
743 else
744 shandle.engineOptions.transportExtra = nullptr;
745 break;
746
747 case CB::ENGINE_OPTION_FORCE_STEREO:
748 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
749 shandle.engineOptions.forceStereo = (value != 0);
750 break;
751
752 case CB::ENGINE_OPTION_PREFER_PLUGIN_BRIDGES:
753 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
754 shandle.engineOptions.preferPluginBridges = (value != 0);
755 break;
756
757 case CB::ENGINE_OPTION_PREFER_UI_BRIDGES:
758 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
759 shandle.engineOptions.preferUiBridges = (value != 0);
760 break;
761
762 case CB::ENGINE_OPTION_UIS_ALWAYS_ON_TOP:
763 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
764 shandle.engineOptions.uisAlwaysOnTop = (value != 0);
765 break;
766
767 case CB::ENGINE_OPTION_MAX_PARAMETERS:
768 CARLA_SAFE_ASSERT_RETURN(value >= 0,);
769 shandle.engineOptions.maxParameters = static_cast<uint>(value);
770 break;
771
772 case CB::ENGINE_OPTION_RESET_XRUNS:
773 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
774 shandle.engineOptions.resetXruns = (value != 0);
775 break;
776
777 case CB::ENGINE_OPTION_UI_BRIDGES_TIMEOUT:
778 CARLA_SAFE_ASSERT_RETURN(value >= 0,);
779 shandle.engineOptions.uiBridgesTimeout = static_cast<uint>(value);
780 break;
781
782 case CB::ENGINE_OPTION_AUDIO_BUFFER_SIZE:
783 CARLA_SAFE_ASSERT_RETURN(value >= 8,);
784 shandle.engineOptions.audioBufferSize = static_cast<uint>(value);
785 break;
786
787 case CB::ENGINE_OPTION_AUDIO_SAMPLE_RATE:
788 CARLA_SAFE_ASSERT_RETURN(value >= 22050,);
789 shandle.engineOptions.audioSampleRate = static_cast<uint>(value);
790 break;
791
792 case CB::ENGINE_OPTION_AUDIO_TRIPLE_BUFFER:
793 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
794 shandle.engineOptions.audioTripleBuffer = (value != 0);
795 break;
796
797 case CB::ENGINE_OPTION_AUDIO_DRIVER:
798 CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
799
800 if (shandle.engineOptions.audioDriver != nullptr)
801 delete[] shandle.engineOptions.audioDriver;
802
803 shandle.engineOptions.audioDriver = carla_strdup_safe(valueStr);
804 break;
805
806 case CB::ENGINE_OPTION_AUDIO_DEVICE:
807 CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
808
809 if (shandle.engineOptions.audioDevice != nullptr)
810 delete[] shandle.engineOptions.audioDevice;
811
812 shandle.engineOptions.audioDevice = carla_strdup_safe(valueStr);
813 break;
814
815 #ifndef BUILD_BRIDGE
816 case CB::ENGINE_OPTION_OSC_ENABLED:
817 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
818 shandle.engineOptions.oscEnabled = (value != 0);
819 break;
820
821 case CB::ENGINE_OPTION_OSC_PORT_TCP:
822 CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,);
823 shandle.engineOptions.oscPortTCP = value;
824 break;
825
826 case CB::ENGINE_OPTION_OSC_PORT_UDP:
827 CARLA_SAFE_ASSERT_RETURN(value <= 0 || value >= 1024,);
828 shandle.engineOptions.oscPortUDP = value;
829 break;
830 #endif
831
832 case CB::ENGINE_OPTION_FILE_PATH:
833 CARLA_SAFE_ASSERT_RETURN(value > CB::FILE_NONE,);
834 CARLA_SAFE_ASSERT_RETURN(value <= CB::FILE_MIDI,);
835 CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
836
837 switch (value)
838 {
839 case CB::FILE_AUDIO:
840 if (shandle.engineOptions.pathAudio != nullptr)
841 delete[] shandle.engineOptions.pathAudio;
842 shandle.engineOptions.pathAudio = carla_strdup_safe(valueStr);
843 break;
844 case CB::FILE_MIDI:
845 if (shandle.engineOptions.pathMIDI != nullptr)
846 delete[] shandle.engineOptions.pathMIDI;
847 shandle.engineOptions.pathMIDI = carla_strdup_safe(valueStr);
848 break;
849 }
850 break;
851
852 case CB::ENGINE_OPTION_PLUGIN_PATH:
853 CARLA_SAFE_ASSERT_RETURN(value > CB::PLUGIN_NONE,);
854 CARLA_SAFE_ASSERT_RETURN(value <= CB::PLUGIN_SFZ,);
855 CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,);
856
857 switch (value)
858 {
859 case CB::PLUGIN_LADSPA:
860 if (shandle.engineOptions.pathLADSPA != nullptr)
861 delete[] shandle.engineOptions.pathLADSPA;
862 shandle.engineOptions.pathLADSPA = carla_strdup_safe(valueStr);
863 break;
864 case CB::PLUGIN_DSSI:
865 if (shandle.engineOptions.pathDSSI != nullptr)
866 delete[] shandle.engineOptions.pathDSSI;
867 shandle.engineOptions.pathDSSI = carla_strdup_safe(valueStr);
868 break;
869 case CB::PLUGIN_LV2:
870 if (shandle.engineOptions.pathLV2 != nullptr)
871 delete[] shandle.engineOptions.pathLV2;
872 shandle.engineOptions.pathLV2 = carla_strdup_safe(valueStr);
873 break;
874 case CB::PLUGIN_VST2:
875 if (shandle.engineOptions.pathVST2 != nullptr)
876 delete[] shandle.engineOptions.pathVST2;
877 shandle.engineOptions.pathVST2 = carla_strdup_safe(valueStr);
878 break;
879 case CB::PLUGIN_VST3:
880 if (shandle.engineOptions.pathVST3 != nullptr)
881 delete[] shandle.engineOptions.pathVST3;
882 shandle.engineOptions.pathVST3 = carla_strdup_safe(valueStr);
883 break;
884 case CB::PLUGIN_SF2:
885 if (shandle.engineOptions.pathSF2 != nullptr)
886 delete[] shandle.engineOptions.pathSF2;
887 shandle.engineOptions.pathSF2 = carla_strdup_safe(valueStr);
888 break;
889 case CB::PLUGIN_SFZ:
890 if (shandle.engineOptions.pathSFZ != nullptr)
891 delete[] shandle.engineOptions.pathSFZ;
892 shandle.engineOptions.pathSFZ = carla_strdup_safe(valueStr);
893 break;
894 }
895 break;
896
897 case CB::ENGINE_OPTION_PATH_BINARIES:
898 CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
899
900 if (shandle.engineOptions.binaryDir != nullptr)
901 delete[] shandle.engineOptions.binaryDir;
902
903 shandle.engineOptions.binaryDir = carla_strdup_safe(valueStr);
904 break;
905
906 case CB::ENGINE_OPTION_PATH_RESOURCES:
907 CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
908
909 if (shandle.engineOptions.resourceDir != nullptr)
910 delete[] shandle.engineOptions.resourceDir;
911
912 shandle.engineOptions.resourceDir = carla_strdup_safe(valueStr);
913 break;
914
915 case CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR:
916 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
917 shandle.engineOptions.preventBadBehaviour = (value != 0);
918 break;
919
920 case CB::ENGINE_OPTION_FRONTEND_BACKGROUND_COLOR:
921 shandle.engineOptions.bgColor = static_cast<uint>(value);
922 break;
923
924 case CB::ENGINE_OPTION_FRONTEND_FOREGROUND_COLOR:
925 shandle.engineOptions.fgColor = static_cast<uint>(value);
926 break;
927
928 case CB::ENGINE_OPTION_FRONTEND_UI_SCALE:
929 CARLA_SAFE_ASSERT_RETURN(value > 0,);
930 shandle.engineOptions.uiScale = static_cast<float>(value) / 1000;
931 break;
932
933 case CB::ENGINE_OPTION_FRONTEND_WIN_ID: {
934 CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
935 const long long winId(std::strtoll(valueStr, nullptr, 16));
936 CARLA_SAFE_ASSERT_RETURN(winId >= 0,);
937 shandle.engineOptions.frontendWinId = static_cast<uintptr_t>(winId);
938 } break;
939
940 #if !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) && !defined(CARLA_OS_WIN)
941 case CB::ENGINE_OPTION_WINE_EXECUTABLE:
942 CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
943
944 if (shandle.engineOptions.wine.executable != nullptr)
945 delete[] shandle.engineOptions.wine.executable;
946
947 shandle.engineOptions.wine.executable = carla_strdup_safe(valueStr);
948 break;
949
950 case CB::ENGINE_OPTION_WINE_AUTO_PREFIX:
951 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
952 shandle.engineOptions.wine.autoPrefix = (value != 0);
953 break;
954
955 case CB::ENGINE_OPTION_WINE_FALLBACK_PREFIX:
956 CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr && valueStr[0] != '\0',);
957
958 if (shandle.engineOptions.wine.fallbackPrefix != nullptr)
959 delete[] shandle.engineOptions.wine.fallbackPrefix;
960
961 shandle.engineOptions.wine.fallbackPrefix = carla_strdup_safe(valueStr);
962 break;
963
964 case CB::ENGINE_OPTION_WINE_RT_PRIO_ENABLED:
965 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
966 shandle.engineOptions.wine.rtPrio = (value != 0);
967 break;
968
969 case CB::ENGINE_OPTION_WINE_BASE_RT_PRIO:
970 CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 89,);
971 shandle.engineOptions.wine.baseRtPrio = value;
972 break;
973
974 case CB::ENGINE_OPTION_WINE_SERVER_RT_PRIO:
975 CARLA_SAFE_ASSERT_RETURN(value >= 1 && value <= 99,);
976 shandle.engineOptions.wine.serverRtPrio = value;
977 break;
978 #endif
979
980 #ifndef BUILD_BRIDGE
981 case CB::ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT:
982 shandle.logThreadEnabled = (value != 0);
983 break;
984 #endif
985
986 case CB::ENGINE_OPTION_CLIENT_NAME_PREFIX:
987 if (shandle.engineOptions.clientNamePrefix != nullptr)
988 delete[] shandle.engineOptions.clientNamePrefix;
989
990 shandle.engineOptions.clientNamePrefix = valueStr != nullptr && valueStr[0] != '\0'
991 ? carla_strdup_safe(valueStr)
992 : nullptr;
993 break;
994
995 case CB::ENGINE_OPTION_PLUGINS_ARE_STANDALONE:
996 CARLA_SAFE_ASSERT_RETURN(value == 0 || value == 1,);
997 shandle.engineOptions.pluginsAreStandalone = (value != 0);
998 break;
999 }
1000 }
1001
1002 if (handle->engine != nullptr)
1003 handle->engine->setOption(option, value, valueStr);
1004 }
1005
carla_set_file_callback(CarlaHostHandle handle,FileCallbackFunc func,void * ptr)1006 void carla_set_file_callback(CarlaHostHandle handle, FileCallbackFunc func, void* ptr)
1007 {
1008 carla_debug("carla_set_file_callback(%p, %p, %p)", handle, func, ptr);
1009
1010 if (handle->isStandalone)
1011 {
1012 CarlaHostStandalone& shandle((CarlaHostStandalone&)*handle);
1013
1014 shandle.fileCallback = func;
1015 shandle.fileCallbackPtr = ptr;
1016 }
1017
1018 if (handle->engine != nullptr)
1019 handle->engine->setFileCallback(func, ptr);
1020 }
1021
1022 // --------------------------------------------------------------------------------------------------------------------
1023
carla_load_file(CarlaHostHandle handle,const char * filename)1024 bool carla_load_file(CarlaHostHandle handle, const char* filename)
1025 {
1026 CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false);
1027 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1028
1029 carla_debug("carla_load_file(%p, \"%s\")", handle, filename);
1030
1031 return handle->engine->loadFile(filename);
1032 }
1033
carla_load_project(CarlaHostHandle handle,const char * filename)1034 bool carla_load_project(CarlaHostHandle handle, const char* filename)
1035 {
1036 CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false);
1037 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1038
1039 carla_debug("carla_load_project(%p, \"%s\")", handle, filename);
1040
1041 return handle->engine->loadProject(filename, true);
1042 }
1043
carla_save_project(CarlaHostHandle handle,const char * filename)1044 bool carla_save_project(CarlaHostHandle handle, const char* filename)
1045 {
1046 CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false);
1047 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1048
1049 carla_debug("carla_save_project(%p, \"%s\")", handle, filename);
1050
1051 return handle->engine->saveProject(filename, true);
1052 }
1053
1054 #ifndef BUILD_BRIDGE
carla_get_current_project_folder(CarlaHostHandle handle)1055 const char* carla_get_current_project_folder(CarlaHostHandle handle)
1056 {
1057 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, gNullCharPtr);
1058
1059 carla_debug("carla_get_current_project_folder(%p)", handle);
1060
1061 if (const char* const ret = handle->engine->getCurrentProjectFolder())
1062 return ret;
1063
1064 return gNullCharPtr;
1065 }
1066
carla_get_current_project_filename(CarlaHostHandle handle)1067 const char* carla_get_current_project_filename(CarlaHostHandle handle)
1068 {
1069 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->isStandalone, gNullCharPtr);
1070
1071 carla_debug("carla_get_current_project_filename(%p)", handle);
1072
1073 if (const char* const ret = handle->engine->getCurrentProjectFilename())
1074 return ret;
1075
1076 return gNullCharPtr;
1077 }
1078
carla_clear_project_filename(CarlaHostHandle handle)1079 void carla_clear_project_filename(CarlaHostHandle handle)
1080 {
1081 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
1082
1083 carla_debug("carla_clear_project_filename(%p)", handle);
1084
1085 handle->engine->clearCurrentProjectFilename();
1086 }
1087
1088 // --------------------------------------------------------------------------------------------------------------------
1089
carla_patchbay_connect(CarlaHostHandle handle,bool external,uint groupIdA,uint portIdA,uint groupIdB,uint portIdB)1090 bool carla_patchbay_connect(CarlaHostHandle handle, bool external, uint groupIdA, uint portIdA, uint groupIdB, uint portIdB)
1091 {
1092 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1093
1094 carla_debug("carla_patchbay_connect(%p, %s, %u, %u, %u, %u)",
1095 handle, bool2str(external), groupIdA, portIdA, groupIdB, portIdB);
1096
1097 return handle->engine->patchbayConnect(external, groupIdA, portIdA, groupIdB, portIdB);
1098 }
1099
carla_patchbay_disconnect(CarlaHostHandle handle,bool external,uint connectionId)1100 bool carla_patchbay_disconnect(CarlaHostHandle handle, bool external, uint connectionId)
1101 {
1102 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1103
1104 carla_debug("carla_patchbay_disconnect(%p, %s, %i)", handle, bool2str(external), connectionId);
1105
1106 return handle->engine->patchbayDisconnect(external, connectionId);
1107 }
1108
carla_patchbay_set_group_pos(CarlaHostHandle handle,bool external,uint groupId,int x1,int y1,int x2,int y2)1109 bool carla_patchbay_set_group_pos(CarlaHostHandle handle, bool external, uint groupId, int x1, int y1, int x2, int y2)
1110 {
1111 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr && handle->engine->isRunning(),
1112 "Engine is not running", false);
1113
1114 carla_debug("carla_patchbay_set_group_pos(%p, %s, %u, %i, %i, %i, %i)",
1115 handle, bool2str(external), groupId, x1, y1, x2, y2);
1116
1117 if (handle->engine->isAboutToClose())
1118 return true;
1119
1120 return handle->engine->patchbaySetGroupPos(false, true, external, groupId, x1, y1, x2, y2);
1121 }
1122
carla_patchbay_refresh(CarlaHostHandle handle,bool external)1123 bool carla_patchbay_refresh(CarlaHostHandle handle, bool external)
1124 {
1125 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1126
1127 carla_debug("carla_patchbay_refresh(%p, %s)", handle, bool2str(external));
1128
1129 return handle->engine->patchbayRefresh(true, false, external);
1130 }
1131
1132 // --------------------------------------------------------------------------------------------------------------------
1133
carla_transport_play(CarlaHostHandle handle)1134 void carla_transport_play(CarlaHostHandle handle)
1135 {
1136 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->engine->isRunning(),);
1137
1138 carla_debug("carla_transport_play(%p)", handle);
1139
1140 handle->engine->transportPlay();
1141 }
1142
carla_transport_pause(CarlaHostHandle handle)1143 void carla_transport_pause(CarlaHostHandle handle)
1144 {
1145 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->engine->isRunning(),);
1146
1147 carla_debug("carla_transport_pause(%p)", handle);
1148
1149 handle->engine->transportPause();
1150 }
1151
carla_transport_bpm(CarlaHostHandle handle,double bpm)1152 void carla_transport_bpm(CarlaHostHandle handle, double bpm)
1153 {
1154 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->engine->isRunning(),);
1155
1156 carla_debug("carla_transport_bpm(%p, %f)", handle, bpm);
1157
1158 handle->engine->transportBPM(bpm);
1159 }
1160
carla_transport_relocate(CarlaHostHandle handle,uint64_t frame)1161 void carla_transport_relocate(CarlaHostHandle handle, uint64_t frame)
1162 {
1163 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->engine->isRunning(),);
1164
1165 carla_debug("carla_transport_relocate(%p, %i)", handle, frame);
1166
1167 handle->engine->transportRelocate(frame);
1168 }
1169
carla_get_current_transport_frame(CarlaHostHandle handle)1170 uint64_t carla_get_current_transport_frame(CarlaHostHandle handle)
1171 {
1172 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->engine->isRunning(), 0);
1173
1174 return handle->engine->getTimeInfo().frame;
1175 }
1176
carla_get_transport_info(CarlaHostHandle handle)1177 const CarlaTransportInfo* carla_get_transport_info(CarlaHostHandle handle)
1178 {
1179 static CarlaTransportInfo retTransInfo;
1180 retTransInfo.clear();
1181
1182 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->engine->isRunning(), &retTransInfo);
1183
1184 const CB::EngineTimeInfo& timeInfo(handle->engine->getTimeInfo());
1185
1186 retTransInfo.playing = timeInfo.playing;
1187 retTransInfo.frame = timeInfo.frame;
1188
1189 if (timeInfo.bbt.valid)
1190 {
1191 retTransInfo.bar = timeInfo.bbt.bar;
1192 retTransInfo.beat = timeInfo.bbt.beat;
1193 retTransInfo.tick = static_cast<int32_t>(timeInfo.bbt.tick + 0.5);
1194 retTransInfo.bpm = timeInfo.bbt.beatsPerMinute;
1195 }
1196
1197 return &retTransInfo;
1198 }
1199 #endif
1200
1201 // --------------------------------------------------------------------------------------------------------------------
1202
carla_get_current_plugin_count(CarlaHostHandle handle)1203 uint32_t carla_get_current_plugin_count(CarlaHostHandle handle)
1204 {
1205 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0);
1206
1207 carla_debug("carla_get_current_plugin_count(%p)", handle);
1208
1209 return handle->engine->getCurrentPluginCount();
1210 }
1211
carla_get_max_plugin_number(CarlaHostHandle handle)1212 uint32_t carla_get_max_plugin_number(CarlaHostHandle handle)
1213 {
1214 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0);
1215
1216 carla_debug("carla_get_max_plugin_number(%p)", handle);
1217
1218 return handle->engine->getMaxPluginNumber();
1219 }
1220
1221 // --------------------------------------------------------------------------------------------------------------------
1222
carla_add_plugin(CarlaHostHandle handle,BinaryType btype,PluginType ptype,const char * filename,const char * name,const char * label,int64_t uniqueId,const void * extraPtr,uint options)1223 bool carla_add_plugin(CarlaHostHandle handle,
1224 BinaryType btype, PluginType ptype,
1225 const char* filename, const char* name, const char* label, int64_t uniqueId,
1226 const void* extraPtr, uint options)
1227 {
1228 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1229
1230 carla_debug("carla_add_plugin(%p, %i:%s, %i:%s, \"%s\", \"%s\", \"%s\", " P_INT64 ", %p, %u)",
1231 handle,
1232 btype, CB::BinaryType2Str(btype),
1233 ptype, CB::PluginType2Str(ptype),
1234 filename, name, label, uniqueId, extraPtr, options);
1235
1236 return handle->engine->addPlugin(btype, ptype, filename, name, label, uniqueId, extraPtr, options);
1237 }
1238
carla_remove_plugin(CarlaHostHandle handle,uint pluginId)1239 bool carla_remove_plugin(CarlaHostHandle handle, uint pluginId)
1240 {
1241 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1242
1243 carla_debug("carla_remove_plugin(%p, %i)", handle, pluginId);
1244
1245 return handle->engine->removePlugin(pluginId);
1246 }
1247
carla_remove_all_plugins(CarlaHostHandle handle)1248 bool carla_remove_all_plugins(CarlaHostHandle handle)
1249 {
1250 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1251
1252 carla_debug("carla_remove_all_plugins(%p)", handle);
1253
1254 return handle->engine->removeAllPlugins();
1255 }
1256
1257 #ifndef BUILD_BRIDGE
carla_rename_plugin(CarlaHostHandle handle,uint pluginId,const char * newName)1258 bool carla_rename_plugin(CarlaHostHandle handle, uint pluginId, const char* newName)
1259 {
1260 CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0', false);
1261 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1262
1263 carla_debug("carla_rename_plugin(%p, %i, \"%s\")", handle, pluginId, newName);
1264
1265 return handle->engine->renamePlugin(pluginId, newName);
1266 }
1267
carla_clone_plugin(CarlaHostHandle handle,uint pluginId)1268 bool carla_clone_plugin(CarlaHostHandle handle, uint pluginId)
1269 {
1270 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1271
1272 carla_debug("carla_clone_plugin(%p, %i)", handle, pluginId);
1273
1274 return handle->engine->clonePlugin(pluginId);
1275 }
1276
carla_replace_plugin(CarlaHostHandle handle,uint pluginId)1277 bool carla_replace_plugin(CarlaHostHandle handle, uint pluginId)
1278 {
1279 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1280
1281 carla_debug("carla_replace_plugin(%p, %i)", handle, pluginId);
1282
1283 return handle->engine->replacePlugin(pluginId);
1284 }
1285
carla_switch_plugins(CarlaHostHandle handle,uint pluginIdA,uint pluginIdB)1286 bool carla_switch_plugins(CarlaHostHandle handle, uint pluginIdA, uint pluginIdB)
1287 {
1288 CARLA_SAFE_ASSERT_RETURN(pluginIdA != pluginIdB, false);
1289 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1290
1291 carla_debug("carla_switch_plugins(%p, %i, %i)", handle, pluginIdA, pluginIdB);
1292
1293 return handle->engine->switchPlugins(pluginIdA, pluginIdB);
1294 }
1295 #endif
1296
1297 // --------------------------------------------------------------------------------------------------------------------
1298
carla_load_plugin_state(CarlaHostHandle handle,uint pluginId,const char * filename)1299 bool carla_load_plugin_state(CarlaHostHandle handle, uint pluginId, const char* filename)
1300 {
1301 CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false);
1302 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr
1303 && handle->engine->isRunning(), "Engine is not running", false);
1304
1305 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1306 return plugin->loadStateFromFile(filename);
1307
1308 return false;
1309 }
1310
carla_save_plugin_state(CarlaHostHandle handle,uint pluginId,const char * filename)1311 bool carla_save_plugin_state(CarlaHostHandle handle, uint pluginId, const char* filename)
1312 {
1313 CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', false);
1314 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1315
1316 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1317 return plugin->saveStateToFile(filename);
1318
1319 return false;
1320 }
1321
carla_export_plugin_lv2(CarlaHostHandle handle,uint pluginId,const char * lv2path)1322 bool carla_export_plugin_lv2(CarlaHostHandle handle, uint pluginId, const char* lv2path)
1323 {
1324 CARLA_SAFE_ASSERT_RETURN(lv2path != nullptr && lv2path[0] != '\0', false);
1325 CARLA_SAFE_ASSERT_WITH_LAST_ERROR_RETURN(handle->engine != nullptr, "Engine is not initialized", false);
1326
1327 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1328 return plugin->exportAsLV2(lv2path);
1329
1330 return false;
1331 }
1332
1333 // --------------------------------------------------------------------------------------------------------------------
1334
carla_get_plugin_info(CarlaHostHandle handle,uint pluginId)1335 const CarlaPluginInfo* carla_get_plugin_info(CarlaHostHandle handle, uint pluginId)
1336 {
1337 static CarlaPluginInfo retInfo;
1338
1339 // reset
1340 retInfo.type = CB::PLUGIN_NONE;
1341 retInfo.category = CB::PLUGIN_CATEGORY_NONE;
1342 retInfo.hints = 0x0;
1343 retInfo.optionsAvailable = 0x0;
1344 retInfo.optionsEnabled = 0x0;
1345 retInfo.filename = gNullCharPtr;
1346 retInfo.name = gNullCharPtr;
1347 retInfo.iconName = gNullCharPtr;
1348 retInfo.uniqueId = 0;
1349
1350 // cleanup
1351 if (retInfo.label != gNullCharPtr)
1352 {
1353 delete[] retInfo.label;
1354 retInfo.label = gNullCharPtr;
1355 }
1356
1357 if (retInfo.maker != gNullCharPtr)
1358 {
1359 delete[] retInfo.maker;
1360 retInfo.maker = gNullCharPtr;
1361 }
1362
1363 if (retInfo.copyright != gNullCharPtr)
1364 {
1365 delete[] retInfo.copyright;
1366 retInfo.copyright = gNullCharPtr;
1367 }
1368
1369 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retInfo);
1370
1371 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1372 {
1373 char strBuf[STR_MAX+1];
1374 carla_zeroChars(strBuf, STR_MAX+1);
1375
1376 retInfo.type = plugin->getType();
1377 retInfo.category = plugin->getCategory();
1378 retInfo.hints = plugin->getHints();
1379 retInfo.filename = plugin->getFilename();
1380 retInfo.name = plugin->getName();
1381 retInfo.iconName = plugin->getIconName();
1382 retInfo.uniqueId = plugin->getUniqueId();
1383
1384 retInfo.optionsAvailable = plugin->getOptionsAvailable();
1385 retInfo.optionsEnabled = plugin->getOptionsEnabled();
1386
1387 if (plugin->getLabel(strBuf))
1388 retInfo.label = carla_strdup_safe(strBuf);
1389 if (plugin->getMaker(strBuf))
1390 retInfo.maker = carla_strdup_safe(strBuf);
1391 if (plugin->getCopyright(strBuf))
1392 retInfo.copyright = carla_strdup_safe(strBuf);
1393
1394 checkStringPtr(retInfo.filename);
1395 checkStringPtr(retInfo.name);
1396 checkStringPtr(retInfo.iconName);
1397 checkStringPtr(retInfo.label);
1398 checkStringPtr(retInfo.maker);
1399 checkStringPtr(retInfo.copyright);
1400 }
1401
1402 return &retInfo;
1403 }
1404
carla_get_audio_port_count_info(CarlaHostHandle handle,uint pluginId)1405 const CarlaPortCountInfo* carla_get_audio_port_count_info(CarlaHostHandle handle, uint pluginId)
1406 {
1407 static CarlaPortCountInfo retInfo;
1408 carla_zeroStruct(retInfo);
1409
1410 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retInfo);
1411
1412 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1413 {
1414 retInfo.ins = plugin->getAudioInCount();
1415 retInfo.outs = plugin->getAudioOutCount();
1416 }
1417
1418 return &retInfo;
1419 }
1420
carla_get_midi_port_count_info(CarlaHostHandle handle,uint pluginId)1421 const CarlaPortCountInfo* carla_get_midi_port_count_info(CarlaHostHandle handle, uint pluginId)
1422 {
1423 static CarlaPortCountInfo retInfo;
1424 carla_zeroStruct(retInfo);
1425
1426 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retInfo);
1427
1428 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1429 {
1430 retInfo.ins = plugin->getMidiInCount();
1431 retInfo.outs = plugin->getMidiOutCount();
1432 }
1433
1434 return &retInfo;
1435 }
1436
carla_get_parameter_count_info(CarlaHostHandle handle,uint pluginId)1437 const CarlaPortCountInfo* carla_get_parameter_count_info(CarlaHostHandle handle, uint pluginId)
1438 {
1439 static CarlaPortCountInfo retInfo;
1440 carla_zeroStruct(retInfo);
1441
1442 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retInfo);
1443
1444 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1445 plugin->getParameterCountInfo(retInfo.ins, retInfo.outs);
1446
1447 return &retInfo;
1448 }
1449
carla_get_parameter_info(CarlaHostHandle handle,uint pluginId,uint32_t parameterId)1450 const CarlaParameterInfo* carla_get_parameter_info(CarlaHostHandle handle, uint pluginId, uint32_t parameterId)
1451 {
1452 static CarlaParameterInfo retInfo;
1453
1454 // reset
1455 retInfo.scalePointCount = 0;
1456
1457 // cleanup
1458 if (retInfo.name != gNullCharPtr)
1459 {
1460 delete[] retInfo.name;
1461 retInfo.name = gNullCharPtr;
1462 }
1463
1464 if (retInfo.symbol != gNullCharPtr)
1465 {
1466 delete[] retInfo.symbol;
1467 retInfo.symbol = gNullCharPtr;
1468 }
1469
1470 if (retInfo.unit != gNullCharPtr)
1471 {
1472 delete[] retInfo.unit;
1473 retInfo.unit = gNullCharPtr;
1474 }
1475
1476 if (retInfo.comment != gNullCharPtr)
1477 {
1478 delete[] retInfo.comment;
1479 retInfo.comment = gNullCharPtr;
1480 }
1481
1482 if (retInfo.groupName != gNullCharPtr)
1483 {
1484 delete[] retInfo.groupName;
1485 retInfo.groupName = gNullCharPtr;
1486 }
1487
1488 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retInfo);
1489
1490 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1491 {
1492 char strBuf[STR_MAX+1];
1493 carla_zeroChars(strBuf, STR_MAX+1);
1494
1495 retInfo.scalePointCount = plugin->getParameterScalePointCount(parameterId);
1496
1497 if (plugin->getParameterName(parameterId, strBuf))
1498 {
1499 retInfo.name = carla_strdup_safe(strBuf);
1500 carla_zeroChars(strBuf, STR_MAX+1);
1501 }
1502
1503 if (plugin->getParameterSymbol(parameterId, strBuf))
1504 {
1505 retInfo.symbol = carla_strdup_safe(strBuf);
1506 carla_zeroChars(strBuf, STR_MAX+1);
1507 }
1508
1509 if (plugin->getParameterUnit(parameterId, strBuf))
1510 {
1511 retInfo.unit = carla_strdup_safe(strBuf);
1512 carla_zeroChars(strBuf, STR_MAX+1);
1513 }
1514
1515 if (plugin->getParameterComment(parameterId, strBuf))
1516 {
1517 retInfo.comment = carla_strdup_safe(strBuf);
1518 carla_zeroChars(strBuf, STR_MAX+1);
1519 }
1520
1521 if (plugin->getParameterGroupName(parameterId, strBuf))
1522 {
1523 retInfo.groupName = carla_strdup_safe(strBuf);
1524 carla_zeroChars(strBuf, STR_MAX+1);
1525 }
1526
1527 checkStringPtr(retInfo.name);
1528 checkStringPtr(retInfo.symbol);
1529 checkStringPtr(retInfo.unit);
1530 checkStringPtr(retInfo.comment);
1531 checkStringPtr(retInfo.groupName);
1532 }
1533
1534 return &retInfo;
1535 }
1536
carla_get_parameter_scalepoint_info(CarlaHostHandle handle,uint pluginId,uint32_t parameterId,uint32_t scalePointId)1537 const CarlaScalePointInfo* carla_get_parameter_scalepoint_info(CarlaHostHandle handle,
1538 uint pluginId,
1539 uint32_t parameterId,
1540 uint32_t scalePointId)
1541 {
1542 CARLA_ASSERT(handle->engine != nullptr);
1543
1544 static CarlaScalePointInfo retInfo;
1545
1546 // reset
1547 retInfo.value = 0.0f;
1548
1549 // cleanup
1550 if (retInfo.label != gNullCharPtr)
1551 {
1552 delete[] retInfo.label;
1553 retInfo.label = gNullCharPtr;
1554 }
1555
1556 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retInfo);
1557
1558 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1559 {
1560 char strBuf[STR_MAX+1];
1561
1562 retInfo.value = plugin->getParameterScalePointValue(parameterId, scalePointId);
1563
1564 carla_zeroChars(strBuf, STR_MAX+1);
1565 if (plugin->getParameterScalePointLabel(parameterId, scalePointId, strBuf))
1566 retInfo.label = carla_strdup_safe(strBuf);
1567
1568 checkStringPtr(retInfo.label);
1569 }
1570
1571 return &retInfo;
1572 }
1573
1574 // --------------------------------------------------------------------------------------------------------------------
1575
carla_get_parameter_data(CarlaHostHandle handle,uint pluginId,uint32_t parameterId)1576 const ParameterData* carla_get_parameter_data(CarlaHostHandle handle, uint pluginId, uint32_t parameterId)
1577 {
1578 static ParameterData retParamData;
1579
1580 // reset
1581 retParamData.type = CB::PARAMETER_UNKNOWN;
1582 retParamData.hints = 0x0;
1583 retParamData.index = CB::PARAMETER_NULL;
1584 retParamData.rindex = -1;
1585 retParamData.midiChannel = 0;
1586 retParamData.mappedControlIndex = CB::CONTROL_INDEX_NONE;
1587 retParamData.mappedMinimum = 0.0f;
1588 retParamData.mappedMaximum = 0.0f;
1589
1590 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retParamData);
1591
1592 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1593 {
1594 CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), &retParamData);
1595
1596 const ParameterData& pluginParamData(plugin->getParameterData(parameterId));
1597 retParamData.type = pluginParamData.type;
1598 retParamData.hints = pluginParamData.hints;
1599 retParamData.index = pluginParamData.index;
1600 retParamData.rindex = pluginParamData.rindex;
1601 retParamData.midiChannel = pluginParamData.midiChannel;
1602 retParamData.mappedControlIndex = pluginParamData.mappedControlIndex;
1603 retParamData.mappedMinimum = pluginParamData.mappedMinimum;
1604 retParamData.mappedMaximum = pluginParamData.mappedMaximum;
1605 }
1606
1607 return &retParamData;
1608 }
1609
carla_get_parameter_ranges(CarlaHostHandle handle,uint pluginId,uint32_t parameterId)1610 const ParameterRanges* carla_get_parameter_ranges(CarlaHostHandle handle, uint pluginId, uint32_t parameterId)
1611 {
1612 static ParameterRanges retParamRanges;
1613
1614 // reset
1615 retParamRanges.def = 0.0f;
1616 retParamRanges.min = 0.0f;
1617 retParamRanges.max = 1.0f;
1618 retParamRanges.step = 0.01f;
1619 retParamRanges.stepSmall = 0.0001f;
1620 retParamRanges.stepLarge = 0.1f;
1621
1622 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retParamRanges);
1623
1624 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1625 {
1626 CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), &retParamRanges);
1627
1628 const ParameterRanges& pluginParamRanges(plugin->getParameterRanges(parameterId));
1629 retParamRanges.def = pluginParamRanges.def;
1630 retParamRanges.min = pluginParamRanges.min;
1631 retParamRanges.max = pluginParamRanges.max;
1632 retParamRanges.step = pluginParamRanges.step;
1633 retParamRanges.stepSmall = pluginParamRanges.stepSmall;
1634 retParamRanges.stepLarge = pluginParamRanges.stepLarge;
1635 }
1636
1637 return &retParamRanges;
1638 }
1639
carla_get_midi_program_data(CarlaHostHandle handle,uint pluginId,uint32_t midiProgramId)1640 const MidiProgramData* carla_get_midi_program_data(CarlaHostHandle handle, uint pluginId, uint32_t midiProgramId)
1641 {
1642 static MidiProgramData retMidiProgData = { 0, 0, gNullCharPtr };
1643
1644 // reset
1645 retMidiProgData.bank = 0;
1646 retMidiProgData.program = 0;
1647
1648 if (retMidiProgData.name != gNullCharPtr)
1649 {
1650 delete[] retMidiProgData.name;
1651 retMidiProgData.name = gNullCharPtr;
1652 }
1653
1654 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retMidiProgData);
1655
1656 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1657 {
1658 CARLA_SAFE_ASSERT_RETURN(midiProgramId < plugin->getMidiProgramCount(), &retMidiProgData);
1659
1660 const MidiProgramData& pluginMidiProgData(plugin->getMidiProgramData(midiProgramId));
1661 retMidiProgData.bank = pluginMidiProgData.bank;
1662 retMidiProgData.program = pluginMidiProgData.program;
1663
1664 if (pluginMidiProgData.name != nullptr)
1665 {
1666 retMidiProgData.name = carla_strdup_safe(pluginMidiProgData.name);
1667 checkStringPtr(retMidiProgData.name);
1668 }
1669 else
1670 {
1671 retMidiProgData.name = gNullCharPtr;
1672 }
1673 }
1674
1675 return &retMidiProgData;
1676 }
1677
carla_get_custom_data(CarlaHostHandle handle,uint pluginId,uint32_t customDataId)1678 const CustomData* carla_get_custom_data(CarlaHostHandle handle, uint pluginId, uint32_t customDataId)
1679 {
1680 static CustomData retCustomData = { gNullCharPtr, gNullCharPtr, gNullCharPtr };
1681
1682 // reset
1683 if (retCustomData.type != gNullCharPtr)
1684 {
1685 delete[] retCustomData.type;
1686 retCustomData.type = gNullCharPtr;
1687 }
1688
1689 if (retCustomData.key != gNullCharPtr)
1690 {
1691 delete[] retCustomData.key;
1692 retCustomData.key = gNullCharPtr;
1693 }
1694
1695 if (retCustomData.value != gNullCharPtr)
1696 {
1697 delete[] retCustomData.value;
1698 retCustomData.value = gNullCharPtr;
1699 }
1700
1701 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, &retCustomData);
1702
1703 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1704 {
1705 CARLA_SAFE_ASSERT_RETURN(customDataId < plugin->getCustomDataCount(), &retCustomData)
1706
1707 const CustomData& pluginCustomData(plugin->getCustomData(customDataId));
1708 retCustomData.type = carla_strdup_safe(pluginCustomData.type);
1709 retCustomData.key = carla_strdup_safe(pluginCustomData.key);
1710 retCustomData.value = carla_strdup_safe(pluginCustomData.value);
1711 checkStringPtr(retCustomData.type);
1712 checkStringPtr(retCustomData.key);
1713 checkStringPtr(retCustomData.value);
1714 }
1715
1716 return &retCustomData;
1717 }
1718
carla_get_custom_data_value(CarlaHostHandle handle,uint pluginId,const char * type,const char * key)1719 const char* carla_get_custom_data_value(CarlaHostHandle handle, uint pluginId, const char* type, const char* key)
1720 {
1721 CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0', gNullCharPtr);
1722 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', gNullCharPtr);
1723 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, gNullCharPtr);
1724
1725 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1726 {
1727 const uint32_t count = plugin->getCustomDataCount();
1728
1729 if (count == 0)
1730 return gNullCharPtr;
1731
1732 static CarlaString customDataValue;
1733
1734 for (uint32_t i=0; i<count; ++i)
1735 {
1736 const CustomData& pluginCustomData(plugin->getCustomData(i));
1737
1738 if (std::strcmp(pluginCustomData.type, type) != 0)
1739 continue;
1740 if (std::strcmp(pluginCustomData.key, key) != 0)
1741 continue;
1742
1743 customDataValue = pluginCustomData.value;
1744 return customDataValue.buffer();
1745 }
1746 }
1747
1748 return gNullCharPtr;
1749 }
1750
carla_get_chunk_data(CarlaHostHandle handle,uint pluginId)1751 const char* carla_get_chunk_data(CarlaHostHandle handle, uint pluginId)
1752 {
1753 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, gNullCharPtr);
1754
1755 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1756 {
1757 CARLA_SAFE_ASSERT_RETURN(plugin->getOptionsEnabled() & CB::PLUGIN_OPTION_USE_CHUNKS, gNullCharPtr);
1758
1759 void* data = nullptr;
1760 const std::size_t dataSize(plugin->getChunkData(&data));
1761 CARLA_SAFE_ASSERT_RETURN(data != nullptr && dataSize > 0, gNullCharPtr);
1762
1763 static CarlaString chunkData;
1764
1765 chunkData = CarlaString::asBase64(data, static_cast<std::size_t>(dataSize));
1766 return chunkData.buffer();
1767 }
1768
1769 return gNullCharPtr;
1770 }
1771
1772 // --------------------------------------------------------------------------------------------------------------------
1773
carla_get_parameter_count(CarlaHostHandle handle,uint pluginId)1774 uint32_t carla_get_parameter_count(CarlaHostHandle handle, uint pluginId)
1775 {
1776 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0);
1777
1778 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1779 return plugin->getParameterCount();
1780
1781 return 0;
1782 }
1783
carla_get_program_count(CarlaHostHandle handle,uint pluginId)1784 uint32_t carla_get_program_count(CarlaHostHandle handle, uint pluginId)
1785 {
1786 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0);
1787
1788 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1789 return plugin->getProgramCount();
1790
1791 return 0;
1792 }
1793
carla_get_midi_program_count(CarlaHostHandle handle,uint pluginId)1794 uint32_t carla_get_midi_program_count(CarlaHostHandle handle, uint pluginId)
1795 {
1796 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0);
1797
1798 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1799 return plugin->getMidiProgramCount();
1800
1801 return 0;
1802 }
1803
carla_get_custom_data_count(CarlaHostHandle handle,uint pluginId)1804 uint32_t carla_get_custom_data_count(CarlaHostHandle handle, uint pluginId)
1805 {
1806 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0);
1807
1808 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1809 return plugin->getCustomDataCount();
1810
1811 return 0;
1812 }
1813
1814 // --------------------------------------------------------------------------------------------------------------------
1815
carla_get_parameter_text(CarlaHostHandle handle,uint pluginId,uint32_t parameterId)1816 const char* carla_get_parameter_text(CarlaHostHandle handle, uint pluginId, uint32_t parameterId)
1817 {
1818 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, gNullCharPtr);
1819
1820 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1821 {
1822 CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), gNullCharPtr);
1823
1824 static char textBuf[STR_MAX+1];
1825 carla_zeroChars(textBuf, STR_MAX+1);
1826
1827 if (! plugin->getParameterText(parameterId, textBuf))
1828 textBuf[0] = '\0';
1829
1830 return textBuf;
1831 }
1832
1833 return gNullCharPtr;
1834 }
1835
carla_get_program_name(CarlaHostHandle handle,uint pluginId,uint32_t programId)1836 const char* carla_get_program_name(CarlaHostHandle handle, uint pluginId, uint32_t programId)
1837 {
1838 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, nullptr);
1839
1840 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1841 {
1842 CARLA_SAFE_ASSERT_RETURN(programId < plugin->getProgramCount(), gNullCharPtr);
1843
1844 static char programName[STR_MAX+1];
1845 carla_zeroChars(programName, STR_MAX+1);
1846
1847 if (! plugin->getProgramName(programId, programName))
1848 programName[0] = '\0';
1849
1850 return programName;
1851 }
1852
1853 return gNullCharPtr;
1854 }
1855
carla_get_midi_program_name(CarlaHostHandle handle,uint pluginId,uint32_t midiProgramId)1856 const char* carla_get_midi_program_name(CarlaHostHandle handle, uint pluginId, uint32_t midiProgramId)
1857 {
1858 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, gNullCharPtr);
1859
1860 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1861 {
1862 CARLA_SAFE_ASSERT_RETURN(midiProgramId < plugin->getMidiProgramCount(), gNullCharPtr);
1863
1864 static char midiProgramName[STR_MAX+1];
1865 carla_zeroChars(midiProgramName, STR_MAX+1);
1866
1867 if (! plugin->getMidiProgramName(midiProgramId, midiProgramName))
1868 midiProgramName[0] = '\0';
1869
1870 return midiProgramName;
1871 }
1872
1873 return gNullCharPtr;
1874 }
1875
carla_get_real_plugin_name(CarlaHostHandle handle,uint pluginId)1876 const char* carla_get_real_plugin_name(CarlaHostHandle handle, uint pluginId)
1877 {
1878 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, gNullCharPtr);
1879
1880 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1881 {
1882 static char realPluginName[STR_MAX+1];
1883 carla_zeroChars(realPluginName, STR_MAX+1);
1884
1885 if (! plugin->getRealName(realPluginName))
1886 realPluginName[0] = '\0';
1887
1888 return realPluginName;
1889 }
1890
1891 return gNullCharPtr;
1892 }
1893
1894 // --------------------------------------------------------------------------------------------------------------------
1895
carla_get_current_program_index(CarlaHostHandle handle,uint pluginId)1896 int32_t carla_get_current_program_index(CarlaHostHandle handle, uint pluginId)
1897 {
1898 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, -1);
1899
1900 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1901 return plugin->getCurrentProgram();
1902
1903 return -1;
1904 }
1905
carla_get_current_midi_program_index(CarlaHostHandle handle,uint pluginId)1906 int32_t carla_get_current_midi_program_index(CarlaHostHandle handle, uint pluginId)
1907 {
1908 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, -1);
1909
1910 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1911 return plugin->getCurrentMidiProgram();
1912
1913 return -1;
1914 }
1915
1916 // --------------------------------------------------------------------------------------------------------------------
1917
carla_get_default_parameter_value(CarlaHostHandle handle,uint pluginId,uint32_t parameterId)1918 float carla_get_default_parameter_value(CarlaHostHandle handle, uint pluginId, uint32_t parameterId)
1919 {
1920 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0.0f);
1921
1922 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1923 {
1924 CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), 0.0f);
1925
1926 return plugin->getParameterRanges(parameterId).def;
1927 }
1928
1929 return 0.0f;
1930 }
1931
carla_get_current_parameter_value(CarlaHostHandle handle,uint pluginId,uint32_t parameterId)1932 float carla_get_current_parameter_value(CarlaHostHandle handle, uint pluginId, uint32_t parameterId)
1933 {
1934 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0.0f);
1935
1936 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1937 {
1938 CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(), 0.0f);
1939
1940 return plugin->getParameterValue(parameterId);
1941 }
1942
1943 return 0.0f;
1944 }
1945
carla_get_internal_parameter_value(CarlaHostHandle handle,uint pluginId,int32_t parameterId)1946 float carla_get_internal_parameter_value(CarlaHostHandle handle, uint pluginId, int32_t parameterId)
1947 {
1948 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1949 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, (parameterId == CB::PARAMETER_CTRL_CHANNEL) ? -1.0f : 0.0f);
1950 #else
1951 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0.0f);
1952 #endif
1953 CARLA_SAFE_ASSERT_RETURN(parameterId != CB::PARAMETER_NULL && parameterId > CB::PARAMETER_MAX, 0.0f);
1954
1955 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1956 return plugin->getInternalParameterValue(parameterId);
1957
1958 return 0.0f;
1959 }
1960
1961 // --------------------------------------------------------------------------------------------------------------------
1962
carla_get_plugin_latency(CarlaHostHandle handle,uint pluginId)1963 uint32_t carla_get_plugin_latency(CarlaHostHandle handle, uint pluginId)
1964 {
1965 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0);
1966
1967 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
1968 return plugin->getLatencyInFrames();
1969
1970 return 0;
1971 }
1972
1973 // --------------------------------------------------------------------------------------------------------------------
1974
carla_get_peak_values(CarlaHostHandle handle,uint pluginId)1975 const float* carla_get_peak_values(CarlaHostHandle handle, uint pluginId)
1976 {
1977 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, nullptr);
1978
1979 return handle->engine->getPeaks(pluginId);
1980 }
1981
carla_get_input_peak_value(CarlaHostHandle handle,uint pluginId,bool isLeft)1982 float carla_get_input_peak_value(CarlaHostHandle handle, uint pluginId, bool isLeft)
1983 {
1984 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0.0f);
1985
1986 return handle->engine->getInputPeak(pluginId, isLeft);
1987 }
1988
carla_get_output_peak_value(CarlaHostHandle handle,uint pluginId,bool isLeft)1989 float carla_get_output_peak_value(CarlaHostHandle handle, uint pluginId, bool isLeft)
1990 {
1991 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0.0f);
1992
1993 return handle->engine->getOutputPeak(pluginId, isLeft);
1994 }
1995
1996 // --------------------------------------------------------------------------------------------------------------------
1997
1998 CARLA_BACKEND_START_NAMESPACE
1999
2000 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2001 // defined in CarlaPluginInternal.cpp
2002 const void* carla_render_inline_display_internal(const CarlaPluginPtr& plugin, uint32_t width, uint32_t height);
2003 #endif
2004
2005 // defined in CarlaPluginLV2.cpp
2006 const void* carla_render_inline_display_lv2(const CarlaPluginPtr& plugin, uint32_t width, uint32_t height);
2007
2008 CARLA_BACKEND_END_NAMESPACE
2009
carla_render_inline_display(CarlaHostHandle handle,uint pluginId,uint32_t width,uint32_t height)2010 const CarlaInlineDisplayImageSurface* carla_render_inline_display(CarlaHostHandle handle,
2011 uint pluginId,
2012 uint32_t width, uint32_t height)
2013 {
2014 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->engine->isRunning(), nullptr);
2015
2016 if (handle->engine->isAboutToClose())
2017 return nullptr;
2018
2019 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2020 {
2021 switch (plugin->getType())
2022 {
2023 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2024 case CB::PLUGIN_INTERNAL:
2025 return (const CarlaInlineDisplayImageSurface*)CB::carla_render_inline_display_internal(plugin, width, height);
2026 #endif
2027 case CB::PLUGIN_LV2:
2028 return (const CarlaInlineDisplayImageSurface*)CB::carla_render_inline_display_lv2(plugin, width, height);
2029 default:
2030 return nullptr;
2031 }
2032 }
2033
2034 return nullptr;
2035 }
2036
2037 // --------------------------------------------------------------------------------------------------------------------
2038
carla_set_active(CarlaHostHandle handle,uint pluginId,bool onOff)2039 void carla_set_active(CarlaHostHandle handle, uint pluginId, bool onOff)
2040 {
2041 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2042
2043 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2044 plugin->setActive(onOff, true, false);
2045 }
2046
2047 #ifndef BUILD_BRIDGE
carla_set_drywet(CarlaHostHandle handle,uint pluginId,float value)2048 void carla_set_drywet(CarlaHostHandle handle, uint pluginId, float value)
2049 {
2050 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2051
2052 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2053 plugin->setDryWet(value, true, false);
2054 }
2055
carla_set_volume(CarlaHostHandle handle,uint pluginId,float value)2056 void carla_set_volume(CarlaHostHandle handle, uint pluginId, float value)
2057 {
2058 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2059
2060 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2061 plugin->setVolume(value, true, false);
2062 }
2063
carla_set_balance_left(CarlaHostHandle handle,uint pluginId,float value)2064 void carla_set_balance_left(CarlaHostHandle handle, uint pluginId, float value)
2065 {
2066 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2067
2068 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2069 plugin->setBalanceLeft(value, true, false);
2070 }
2071
carla_set_balance_right(CarlaHostHandle handle,uint pluginId,float value)2072 void carla_set_balance_right(CarlaHostHandle handle, uint pluginId, float value)
2073 {
2074 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2075
2076 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2077 plugin->setBalanceRight(value, true, false);
2078 }
2079
carla_set_panning(CarlaHostHandle handle,uint pluginId,float value)2080 void carla_set_panning(CarlaHostHandle handle, uint pluginId, float value)
2081 {
2082 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2083
2084 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2085 plugin->setPanning(value, true, false);
2086 }
2087
carla_set_ctrl_channel(CarlaHostHandle handle,uint pluginId,int8_t channel)2088 void carla_set_ctrl_channel(CarlaHostHandle handle, uint pluginId, int8_t channel)
2089 {
2090 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2091 CARLA_SAFE_ASSERT_RETURN(channel >= -1 && channel < MAX_MIDI_CHANNELS,);
2092
2093 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2094 plugin->setCtrlChannel(channel, true, false);
2095 }
2096 #endif
2097
carla_set_option(CarlaHostHandle handle,uint pluginId,uint option,bool yesNo)2098 void carla_set_option(CarlaHostHandle handle, uint pluginId, uint option, bool yesNo)
2099 {
2100 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2101
2102 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2103 plugin->setOption(option, yesNo, false);
2104 }
2105
2106 // --------------------------------------------------------------------------------------------------------------------
2107
carla_set_parameter_value(CarlaHostHandle handle,uint pluginId,uint32_t parameterId,float value)2108 void carla_set_parameter_value(CarlaHostHandle handle, uint pluginId, uint32_t parameterId, float value)
2109 {
2110 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2111
2112 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2113 {
2114 CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),);
2115
2116 plugin->setParameterValue(parameterId, value, true, true, false);
2117 }
2118 }
2119
2120 #ifndef BUILD_BRIDGE
2121
carla_set_parameter_midi_channel(CarlaHostHandle handle,uint pluginId,uint32_t parameterId,uint8_t channel)2122 void carla_set_parameter_midi_channel(CarlaHostHandle handle, uint pluginId, uint32_t parameterId, uint8_t channel)
2123 {
2124 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2125 CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
2126
2127 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2128 {
2129 CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),);
2130
2131 plugin->setParameterMidiChannel(parameterId, channel, true, false);
2132 }
2133 }
2134
carla_set_parameter_mapped_control_index(CarlaHostHandle handle,uint pluginId,uint32_t parameterId,int16_t index)2135 void carla_set_parameter_mapped_control_index(CarlaHostHandle handle, uint pluginId, uint32_t parameterId, int16_t index)
2136 {
2137 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2138 CARLA_SAFE_ASSERT_RETURN(index >= CB::CONTROL_INDEX_NONE && index <= CB::CONTROL_INDEX_MAX_ALLOWED,);
2139
2140 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2141 {
2142 CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),);
2143
2144 plugin->setParameterMappedControlIndex(parameterId, index, true, false, true);
2145 }
2146 }
2147
carla_set_parameter_mapped_range(CarlaHostHandle handle,uint pluginId,uint32_t parameterId,float minimum,float maximum)2148 void carla_set_parameter_mapped_range(CarlaHostHandle handle, uint pluginId, uint32_t parameterId, float minimum, float maximum)
2149 {
2150 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2151
2152 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2153 {
2154 CARLA_SAFE_ASSERT_RETURN(parameterId < plugin->getParameterCount(),);
2155
2156 plugin->setParameterMappedRange(parameterId, minimum, maximum, true, false);
2157 }
2158 }
2159
carla_set_parameter_touch(CarlaHostHandle handle,uint pluginId,uint32_t parameterId,bool touch)2160 void carla_set_parameter_touch(CarlaHostHandle handle, uint pluginId, uint32_t parameterId, bool touch)
2161 {
2162 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2163
2164 carla_debug("carla_set_parameter_touch(%p, %i, %i, %s)", handle, pluginId, parameterId, bool2str(touch));
2165 return handle->engine->touchPluginParameter(pluginId, parameterId, touch);
2166 }
2167 #endif
2168
2169 // --------------------------------------------------------------------------------------------------------------------
2170
carla_set_program(CarlaHostHandle handle,uint pluginId,uint32_t programId)2171 void carla_set_program(CarlaHostHandle handle, uint pluginId, uint32_t programId)
2172 {
2173 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2174
2175 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2176 {
2177 CARLA_SAFE_ASSERT_RETURN(programId < plugin->getProgramCount(),);
2178
2179 plugin->setProgram(static_cast<int32_t>(programId), true, true, false);
2180 }
2181 }
2182
carla_set_midi_program(CarlaHostHandle handle,uint pluginId,uint32_t midiProgramId)2183 void carla_set_midi_program(CarlaHostHandle handle, uint pluginId, uint32_t midiProgramId)
2184 {
2185 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2186
2187 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2188 {
2189 CARLA_SAFE_ASSERT_RETURN(midiProgramId < plugin->getMidiProgramCount(),);
2190
2191 plugin->setMidiProgram(static_cast<int32_t>(midiProgramId), true, true, false);
2192 }
2193 }
2194
2195 // --------------------------------------------------------------------------------------------------------------------
2196
carla_set_custom_data(CarlaHostHandle handle,uint pluginId,const char * type,const char * key,const char * value)2197 void carla_set_custom_data(CarlaHostHandle handle, uint pluginId, const char* type, const char* key, const char* value)
2198 {
2199 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2200 CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
2201 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
2202 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
2203
2204 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2205 plugin->setCustomData(type, key, value, true);
2206 }
2207
carla_set_chunk_data(CarlaHostHandle handle,uint pluginId,const char * chunkData)2208 void carla_set_chunk_data(CarlaHostHandle handle, uint pluginId, const char* chunkData)
2209 {
2210 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2211 CARLA_SAFE_ASSERT_RETURN(chunkData != nullptr && chunkData[0] != '\0',);
2212
2213 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2214 {
2215 CARLA_SAFE_ASSERT_RETURN(plugin->getOptionsEnabled() & CB::PLUGIN_OPTION_USE_CHUNKS,);
2216
2217 std::vector<uint8_t> chunk(carla_getChunkFromBase64String(chunkData));
2218 #ifdef CARLA_PROPER_CPP11_SUPPORT
2219 plugin->setChunkData(chunk.data(), chunk.size());
2220 #else
2221 plugin->setChunkData(&chunk.front(), chunk.size());
2222 #endif
2223 }
2224 }
2225
2226 // --------------------------------------------------------------------------------------------------------------------
2227
carla_prepare_for_save(CarlaHostHandle handle,uint pluginId)2228 void carla_prepare_for_save(CarlaHostHandle handle, uint pluginId)
2229 {
2230 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2231
2232 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2233 plugin->prepareForSave(false);
2234 }
2235
carla_reset_parameters(CarlaHostHandle handle,uint pluginId)2236 void carla_reset_parameters(CarlaHostHandle handle, uint pluginId)
2237 {
2238 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2239
2240 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2241 plugin->resetParameters();
2242 }
2243
carla_randomize_parameters(CarlaHostHandle handle,uint pluginId)2244 void carla_randomize_parameters(CarlaHostHandle handle, uint pluginId)
2245 {
2246 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2247
2248 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2249 plugin->randomizeParameters();
2250 }
2251
2252 #ifndef BUILD_BRIDGE
carla_send_midi_note(CarlaHostHandle handle,uint pluginId,uint8_t channel,uint8_t note,uint8_t velocity)2253 void carla_send_midi_note(CarlaHostHandle handle, uint pluginId, uint8_t channel, uint8_t note, uint8_t velocity)
2254 {
2255 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr && handle->engine->isRunning(),);
2256
2257 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2258 plugin->sendMidiSingleNote(channel, note, velocity, true, true, false);
2259 }
2260 #endif
2261
carla_set_custom_ui_title(CarlaHostHandle handle,uint pluginId,const char * title)2262 void carla_set_custom_ui_title(CarlaHostHandle handle, uint pluginId, const char* title)
2263 {
2264 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2265 CARLA_SAFE_ASSERT_RETURN(title != nullptr,);
2266
2267 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2268 plugin->setCustomUITitle(title);
2269 }
2270
carla_show_custom_ui(CarlaHostHandle handle,uint pluginId,bool yesNo)2271 void carla_show_custom_ui(CarlaHostHandle handle, uint pluginId, bool yesNo)
2272 {
2273 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr,);
2274
2275 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2276 plugin->showCustomUI(yesNo);
2277 }
2278
carla_embed_custom_ui(CarlaHostHandle handle,uint pluginId,void * ptr)2279 void* carla_embed_custom_ui(CarlaHostHandle handle, uint pluginId, void* ptr)
2280 {
2281 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, nullptr);
2282
2283 if (const CarlaPluginPtr plugin = handle->engine->getPlugin(pluginId))
2284 return plugin->embedCustomUI(ptr);
2285
2286 return nullptr;
2287 }
2288
2289 // --------------------------------------------------------------------------------------------------------------------
2290
carla_get_buffer_size(CarlaHostHandle handle)2291 uint32_t carla_get_buffer_size(CarlaHostHandle handle)
2292 {
2293 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0);
2294
2295 carla_debug("carla_get_buffer_size(%p)", handle);
2296 return handle->engine->getBufferSize();
2297 }
2298
carla_get_sample_rate(CarlaHostHandle handle)2299 double carla_get_sample_rate(CarlaHostHandle handle)
2300 {
2301 CARLA_SAFE_ASSERT_RETURN(handle->engine != nullptr, 0.0);
2302
2303 carla_debug("carla_get_sample_rate(%p)", handle);
2304 return handle->engine->getSampleRate();
2305 }
2306
2307 // --------------------------------------------------------------------------------------------------------------------
2308
carla_get_last_error(CarlaHostHandle handle)2309 const char* carla_get_last_error(CarlaHostHandle handle)
2310 {
2311 carla_debug("carla_get_last_error(%p)", handle);
2312
2313 if (handle->engine != nullptr)
2314 return handle->engine->getLastError();
2315
2316 return handle->isStandalone
2317 ? ((CarlaHostStandalone*)handle)->lastError.buffer()
2318 : gNullCharPtr;
2319 }
2320
carla_get_host_osc_url_tcp(CarlaHostHandle handle)2321 const char* carla_get_host_osc_url_tcp(CarlaHostHandle handle)
2322 {
2323 carla_debug("carla_get_host_osc_url_tcp(%p)", handle);
2324
2325 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
2326 if (handle->engine == nullptr)
2327 {
2328 carla_stderr2("carla_get_host_osc_url_tcp() failed, engine is not running");
2329 if (handle->isStandalone)
2330 ((CarlaHostStandalone*)handle)->lastError = "Engine is not running";
2331 return gNullCharPtr;
2332 }
2333
2334 const char* const path = handle->engine->getOscServerPathTCP();
2335
2336 if (path != nullptr && path[0] != '\0')
2337 return path;
2338
2339 static const char* const notAvailable = "(OSC TCP port not available)";
2340 return notAvailable;
2341 #else
2342 return "(OSC support not available in this build)";
2343
2344 // unused
2345 (void)handle;
2346 #endif
2347 }
2348
carla_get_host_osc_url_udp(CarlaHostHandle handle)2349 const char* carla_get_host_osc_url_udp(CarlaHostHandle handle)
2350 {
2351 carla_debug("carla_get_host_osc_url_udp(%p)", handle);
2352
2353 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
2354 if (handle->engine == nullptr)
2355 {
2356 carla_stderr2("carla_get_host_osc_url_udp() failed, engine is not running");
2357 if (handle->isStandalone)
2358 ((CarlaHostStandalone*)handle)->lastError = "Engine is not running";
2359 return gNullCharPtr;
2360 }
2361
2362 const char* const path = handle->engine->getOscServerPathUDP();
2363
2364 if (path != nullptr && path[0] != '\0')
2365 return path;
2366
2367 static const char* const notAvailable = "(OSC UDP port not available)";
2368 return notAvailable;
2369 #else
2370 return "(OSC support not available in this build)";
2371
2372 // unused
2373 (void)handle;
2374 #endif
2375 }
2376
2377 // --------------------------------------------------------------------------------------------------------------------
2378
2379 #ifndef CARLA_PLUGIN_EXPORT
2380 # define CARLA_PLUGIN_UI_CLASS_PREFIX Standalone
2381 # include "CarlaPluginUI.cpp"
2382 # undef CARLA_PLUGIN_UI_CLASS_PREFIX
2383 # include "CarlaDssiUtils.cpp"
2384 # include "CarlaMacUtils.cpp"
2385 # include "CarlaPatchbayUtils.cpp"
2386 # include "CarlaPipeUtils.cpp"
2387 # include "CarlaProcessUtils.cpp"
2388 # include "CarlaStateUtils.cpp"
2389 # include "utils/Information.cpp"
2390 # include "utils/Windows.cpp"
2391 #endif /* CARLA_PLUGIN_EXPORT */
2392
2393 // --------------------------------------------------------------------------------------------------------------------
2394