Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2011 lines
64KB

  1. /*
  2. * Carla Standalone
  3. * Copyright (C) 2011-2013 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 GPL.txt file
  16. */
  17. #include "CarlaStandalone.hpp"
  18. #include "CarlaBackendUtils.hpp"
  19. #include "CarlaOscUtils.hpp"
  20. #include "CarlaEngine.hpp"
  21. #include "CarlaPlugin.hpp"
  22. #include "CarlaMIDI.h"
  23. #include "CarlaNative.h"
  24. #include <QtGui/QApplication>
  25. #if 0
  26. extern "C" {
  27. #include "siginfo.c"
  28. }
  29. #endif
  30. using CarlaBackend::CarlaEngine;
  31. using CarlaBackend::CarlaPlugin;
  32. using CarlaBackend::CallbackFunc;
  33. using CarlaBackend::EngineOptions;
  34. // -------------------------------------------------------------------------------------------------------------------
  35. // Single, standalone engine
  36. struct CarlaBackendStandalone {
  37. CallbackFunc callback;
  38. void* callbackPtr;
  39. CarlaEngine* engine;
  40. CarlaString lastError;
  41. CarlaString procName;
  42. #ifndef BUILD_BRIDGE
  43. EngineOptions options;
  44. #endif
  45. QApplication* app;
  46. bool needsInit;
  47. CarlaBackendStandalone()
  48. : callback(nullptr),
  49. callbackPtr(nullptr),
  50. engine(nullptr),
  51. app(qApp),
  52. needsInit(app == nullptr) {}
  53. void init()
  54. {
  55. if (! needsInit)
  56. return;
  57. if (app != nullptr)
  58. return;
  59. static int argc = 0;
  60. static char** argv = nullptr;
  61. app = new QApplication(argc, argv, true);
  62. }
  63. void close()
  64. {
  65. if (! needsInit)
  66. return;
  67. if (app == nullptr)
  68. return;
  69. app->quit();
  70. app->processEvents();
  71. delete app;
  72. app = nullptr;
  73. }
  74. } standalone;
  75. // -------------------------------------------------------------------------------------------------------------------
  76. // API
  77. const char* carla_get_extended_license_text()
  78. {
  79. carla_debug("carla_get_extended_license_text()");
  80. static CarlaString retText;
  81. if (retText.isEmpty())
  82. {
  83. retText = "<p>This current Carla build is using the following features and 3rd-party code:</p>";
  84. retText += "<ul>";
  85. #ifdef WANT_LADSPA
  86. retText += "<li>LADSPA plugin support, http://www.ladspa.org/</li>";
  87. #endif
  88. #ifdef WANT_DSSI
  89. retText += "<li>DSSI plugin support, http://dssi.sourceforge.net/</li>";
  90. #endif
  91. #ifdef WANT_LV2
  92. retText += "<li>LV2 plugin support, http://lv2plug.in/</li>";
  93. #endif
  94. #ifdef WANT_VST
  95. # ifdef VESTIGE_HEADER
  96. retText += "<li>VST plugin support, using VeSTige header by Javier Serrano Polo</li>";
  97. # else
  98. retText += "<li>VST plugin support, using official VST SDK 2.4 (trademark of Steinberg Media Technologies GmbH)</li>";
  99. # endif
  100. #endif
  101. #ifdef WANT_AUDIOFILE
  102. // TODO
  103. //retText += "<li>ZynAddSubFX plugin code, http://zynaddsubfx.sf.net/</li>";
  104. #endif
  105. #ifdef WANT_MIDIFILE
  106. // TODO
  107. //retText += "<li>ZynAddSubFX plugin code, http://zynaddsubfx.sf.net/</li>";
  108. #endif
  109. #ifdef WANT_ZYNADDSUBFX
  110. retText += "<li>ZynAddSubFX plugin code, http://zynaddsubfx.sf.net/</li>";
  111. #endif
  112. #ifdef WANT_FLUIDSYNTH
  113. retText += "<li>FluidSynth library for SF2 support, http://www.fluidsynth.org/</li>";
  114. #endif
  115. #ifdef WANT_LINUXSAMPLER
  116. retText += "<li>LinuxSampler library for GIG and SFZ support*, http://www.linuxsampler.org/</li>";
  117. #endif
  118. retText += "<li>liblo library for OSC support, http://liblo.sourceforge.net/</li>";
  119. #ifdef WANT_LV2
  120. retText += "<li>serd, sord, sratom and lilv libraries for LV2 discovery, http://drobilla.net/software/lilv/</li>";
  121. #endif
  122. #ifdef WANT_RTAUDIO
  123. retText += "<li>RtAudio and RtMidi libraries for extra Audio and MIDI support, http://www.music.mcgill.ca/~gary/rtaudio/</li>";
  124. #endif
  125. retText += "</ul>";
  126. #ifdef WANT_LINUXSAMPLER
  127. retText += "<p>(*) Using LinuxSampler code in commercial hardware or software products is not allowed without prior written authorization by the authors.</p>";
  128. #endif
  129. }
  130. return retText;
  131. }
  132. const char* carla_get_supported_file_types()
  133. {
  134. static CarlaString retText;
  135. if (retText.isEmpty())
  136. {
  137. // Base type
  138. retText = "*.carxp";
  139. // Sample kits
  140. #ifdef WANT_FLUIDSYNTH
  141. retText += ";*.sf2";
  142. #endif
  143. #ifdef WANT_LINUXSAMPLER
  144. retText += ";*.gig;*.sfz";
  145. #endif
  146. // Special files provided by internal plugins
  147. #ifdef WANT_AUDIOFILE
  148. retText += ";*.aac;*.flac;*.oga;*.ogg;*.mp3;*.wav";
  149. #endif
  150. #ifdef WANT_MIDIFILE
  151. retText += ";*.mid;*.midi";
  152. #endif
  153. }
  154. return retText;
  155. }
  156. // -------------------------------------------------------------------------------------------------------------------
  157. unsigned int carla_get_engine_driver_count()
  158. {
  159. carla_debug("carla_get_engine_driver_count()");
  160. return CarlaEngine::getDriverCount();
  161. }
  162. const char* carla_get_engine_driver_name(unsigned int index)
  163. {
  164. carla_debug("carla_get_engine_driver_name(%i)", index);
  165. return CarlaEngine::getDriverName(index);
  166. }
  167. // -------------------------------------------------------------------------------------------------------------------
  168. unsigned int carla_get_internal_plugin_count()
  169. {
  170. carla_debug("carla_get_internal_plugin_count()");
  171. return static_cast<unsigned int>(CarlaPlugin::getNativePluginCount());
  172. }
  173. const CarlaNativePluginInfo* carla_get_internal_plugin_info(unsigned int internalPluginId)
  174. {
  175. carla_debug("carla_get_internal_plugin_info(%i)", internalPluginId);
  176. static CarlaNativePluginInfo info;
  177. const PluginDescriptor* const nativePlugin = CarlaPlugin::getNativePluginDescriptor(internalPluginId);
  178. // as internal plugin, this must never fail
  179. CARLA_ASSERT(nativePlugin != nullptr);
  180. if (nativePlugin == nullptr)
  181. return nullptr;
  182. info.category = static_cast<CarlaPluginCategory>(nativePlugin->category);
  183. info.hints = 0x0;
  184. if (nativePlugin->hints & PLUGIN_IS_RTSAFE)
  185. info.hints |= CarlaBackend::PLUGIN_IS_RTSAFE;
  186. if (nativePlugin->hints & PLUGIN_IS_SYNTH)
  187. info.hints |= CarlaBackend::PLUGIN_IS_SYNTH;
  188. if (nativePlugin->hints & PLUGIN_HAS_GUI)
  189. info.hints |= CarlaBackend::PLUGIN_HAS_GUI;
  190. if (nativePlugin->hints & PLUGIN_USES_SINGLE_THREAD)
  191. info.hints |= CarlaBackend::PLUGIN_HAS_SINGLE_THREAD;
  192. info.audioIns = nativePlugin->audioIns;
  193. info.audioOuts = nativePlugin->audioOuts;
  194. info.midiIns = nativePlugin->midiIns;
  195. info.midiOuts = nativePlugin->midiOuts;
  196. info.parameterIns = nativePlugin->parameterIns;
  197. info.parameterOuts = nativePlugin->parameterOuts;
  198. info.name = nativePlugin->name;
  199. info.label = nativePlugin->label;
  200. info.maker = nativePlugin->maker;
  201. info.copyright = nativePlugin->copyright;
  202. return &info;
  203. }
  204. // -------------------------------------------------------------------------------------------------------------------
  205. bool carla_engine_init(const char* driverName, const char* clientName)
  206. {
  207. carla_debug("carla_engine_init(\"%s\", \"%s\")", driverName, clientName);
  208. CARLA_ASSERT(standalone.engine == nullptr);
  209. CARLA_ASSERT(driverName != nullptr);
  210. CARLA_ASSERT(clientName != nullptr);
  211. standalone.engine = CarlaEngine::newDriverByName(driverName);
  212. if (standalone.engine == nullptr)
  213. {
  214. standalone.lastError = "The seleted audio driver is not available!";
  215. return false;
  216. }
  217. #ifndef Q_OS_WIN
  218. // TODO: make this an option, put somewhere else
  219. if (getenv("WINE_RT") == nullptr)
  220. {
  221. carla_setenv("WINE_RT", "15");
  222. carla_setenv("WINE_SVR_RT", "10");
  223. }
  224. #endif
  225. if (standalone.callback != nullptr)
  226. standalone.engine->setCallback(standalone.callback, nullptr);
  227. #ifndef BUILD_BRIDGE
  228. standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_MODE, static_cast<int>(standalone.options.processMode), nullptr);
  229. standalone.engine->setOption(CarlaBackend::OPTION_TRANSPORT_MODE, static_cast<int>(standalone.options.transportMode), nullptr);
  230. standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo ? 1 : 0, nullptr);
  231. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES, standalone.options.preferPluginBridges ? 1 : 0, nullptr);
  232. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_UI_BRIDGES, standalone.options.preferUiBridges ? 1 : 0, nullptr);
  233. # ifdef WANT_DSSI
  234. standalone.engine->setOption(CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS, standalone.options.useDssiVstChunks ? 1 : 0, nullptr);
  235. # endif
  236. standalone.engine->setOption(CarlaBackend::OPTION_MAX_PARAMETERS, static_cast<int>(standalone.options.maxParameters), nullptr);
  237. standalone.engine->setOption(CarlaBackend::OPTION_PREFERRED_BUFFER_SIZE, static_cast<int>(standalone.options.preferredBufferSize), nullptr);
  238. standalone.engine->setOption(CarlaBackend::OPTION_PREFERRED_SAMPLE_RATE, static_cast<int>(standalone.options.preferredSampleRate), nullptr);
  239. standalone.engine->setOption(CarlaBackend::OPTION_OSC_UI_TIMEOUT, static_cast<int>(standalone.options.oscUiTimeout), nullptr);
  240. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_NATIVE, 0, standalone.options.bridge_native);
  241. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_POSIX32, 0, standalone.options.bridge_posix32);
  242. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_POSIX64, 0, standalone.options.bridge_posix64);
  243. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_WIN32, 0, standalone.options.bridge_win32);
  244. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_WIN64, 0, standalone.options.bridge_win64);
  245. # ifdef WANT_LV2
  246. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK2, 0, standalone.options.bridge_lv2Gtk2);
  247. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK3, 0, standalone.options.bridge_lv2Gtk3);
  248. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_QT4, 0, standalone.options.bridge_lv2Qt4);
  249. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_QT5, 0, standalone.options.bridge_lv2Qt5);
  250. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_COCOA, 0, standalone.options.bridge_lv2Cocoa);
  251. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_WINDOWS, 0, standalone.options.bridge_lv2Win);
  252. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_X11, 0, standalone.options.bridge_lv2X11);
  253. # endif
  254. # ifdef WANT_VST
  255. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_VST_COCOA, 0, standalone.options.bridge_vstCocoa);
  256. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_VST_HWND, 0, standalone.options.bridge_vstHWND);
  257. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_VST_X11, 0, standalone.options.bridge_vstX11);
  258. # endif
  259. if (standalone.procName.isNotEmpty())
  260. standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_NAME, 0, standalone.procName);
  261. #endif
  262. const bool initiated = standalone.engine->init(clientName);
  263. if (initiated)
  264. {
  265. standalone.lastError = "no error";
  266. standalone.init();
  267. }
  268. else
  269. {
  270. standalone.lastError = standalone.engine->getLastError();
  271. delete standalone.engine;
  272. standalone.engine = nullptr;
  273. }
  274. return initiated;
  275. }
  276. bool carla_engine_close()
  277. {
  278. carla_debug("carla_engine_close()");
  279. CARLA_ASSERT(standalone.engine != nullptr);
  280. if (standalone.engine == nullptr)
  281. {
  282. standalone.lastError = "Engine is not started";
  283. return false;
  284. }
  285. standalone.engine->setAboutToClose();
  286. standalone.engine->removeAllPlugins();
  287. const bool closed = standalone.engine->close();
  288. delete standalone.engine;
  289. standalone.engine = nullptr;
  290. standalone.close();
  291. return closed;
  292. }
  293. void carla_engine_idle()
  294. {
  295. CARLA_ASSERT(standalone.engine != nullptr);
  296. if (standalone.needsInit && standalone.app != nullptr)
  297. standalone.app->processEvents();
  298. if (standalone.engine != nullptr)
  299. standalone.engine->idle();
  300. }
  301. bool carla_is_engine_running()
  302. {
  303. carla_debug("carla_is_engine_running()");
  304. return (standalone.engine != nullptr && standalone.engine->isRunning());
  305. }
  306. void carla_set_engine_about_to_close()
  307. {
  308. carla_debug("carla_set_engine_about_to_close()");
  309. CARLA_ASSERT(standalone.engine != nullptr);
  310. if (standalone.engine != nullptr)
  311. standalone.engine->setAboutToClose();
  312. }
  313. void carla_set_engine_callback(CarlaBackend::CallbackFunc func, void* ptr)
  314. {
  315. carla_debug("carla_set_engine_callback(%p)", func);
  316. standalone.callback = func;
  317. standalone.callbackPtr = ptr;
  318. if (standalone.engine != nullptr)
  319. standalone.engine->setCallback(func, ptr);
  320. }
  321. #ifndef BUILD_BRIDGE
  322. void carla_set_engine_option(CarlaBackend::OptionsType option, int value, const char* valueStr)
  323. {
  324. carla_debug("carla_set_engine_option(%s, %i, \"%s\")", CarlaBackend::OptionsType2Str(option), value, valueStr);
  325. if (standalone.engine != nullptr)
  326. standalone.engine->setOption(option, value, valueStr);
  327. switch (option)
  328. {
  329. case CarlaBackend::OPTION_PROCESS_NAME:
  330. standalone.procName = valueStr;
  331. break;
  332. case CarlaBackend::OPTION_PROCESS_MODE:
  333. if (value < CarlaBackend::PROCESS_MODE_SINGLE_CLIENT || value > CarlaBackend::PROCESS_MODE_PATCHBAY)
  334. return carla_stderr2("carla_set_engine_option(OPTION_PROCESS_MODE, %i, \"%s\") - invalid value", value, valueStr);
  335. standalone.options.processMode = static_cast<CarlaBackend::ProcessMode>(value);
  336. break;
  337. case CarlaBackend::OPTION_TRANSPORT_MODE:
  338. if (value < CarlaBackend::TRANSPORT_MODE_INTERNAL || value > CarlaBackend::TRANSPORT_MODE_JACK)
  339. return carla_stderr2("carla_set_engine_option(OPTION_TRANSPORT_MODE, %i, \"%s\") - invalid value", value, valueStr);
  340. standalone.options.transportMode = static_cast<CarlaBackend::TransportMode>(value);
  341. break;
  342. case CarlaBackend::OPTION_FORCE_STEREO:
  343. standalone.options.forceStereo = (value != 0);
  344. break;
  345. case CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES:
  346. standalone.options.preferPluginBridges = (value != 0);
  347. break;
  348. case CarlaBackend::OPTION_PREFER_UI_BRIDGES:
  349. standalone.options.preferUiBridges = (value != 0);
  350. break;
  351. #ifdef WANT_DSSI
  352. case CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS:
  353. standalone.options.useDssiVstChunks = (value != 0);
  354. break;
  355. #endif
  356. case CarlaBackend::OPTION_MAX_PARAMETERS:
  357. standalone.options.maxParameters = (value > 0) ? static_cast<unsigned int>(value) : CarlaBackend::MAX_DEFAULT_PARAMETERS;
  358. break;
  359. case CarlaBackend::OPTION_OSC_UI_TIMEOUT:
  360. standalone.options.oscUiTimeout = static_cast<unsigned int>(value);
  361. break;
  362. case CarlaBackend::OPTION_PREFERRED_BUFFER_SIZE:
  363. standalone.options.preferredBufferSize = static_cast<unsigned int>(value);
  364. break;
  365. case CarlaBackend::OPTION_PREFERRED_SAMPLE_RATE:
  366. standalone.options.preferredSampleRate = static_cast<unsigned int>(value);
  367. break;
  368. #ifndef BUILD_BRIDGE
  369. case CarlaBackend::OPTION_PATH_BRIDGE_NATIVE:
  370. standalone.options.bridge_native = valueStr;
  371. break;
  372. case CarlaBackend::OPTION_PATH_BRIDGE_POSIX32:
  373. standalone.options.bridge_posix32 = valueStr;
  374. break;
  375. case CarlaBackend::OPTION_PATH_BRIDGE_POSIX64:
  376. standalone.options.bridge_posix64 = valueStr;
  377. break;
  378. case CarlaBackend::OPTION_PATH_BRIDGE_WIN32:
  379. standalone.options.bridge_win32 = valueStr;
  380. break;
  381. case CarlaBackend::OPTION_PATH_BRIDGE_WIN64:
  382. standalone.options.bridge_win64 = valueStr;
  383. break;
  384. #endif
  385. #ifdef WANT_LV2
  386. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK2:
  387. standalone.options.bridge_lv2Gtk2 = valueStr;
  388. break;
  389. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK3:
  390. standalone.options.bridge_lv2Gtk3 = valueStr;
  391. break;
  392. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_QT4:
  393. standalone.options.bridge_lv2Qt4 = valueStr;
  394. break;
  395. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_QT5:
  396. standalone.options.bridge_lv2Qt5 = valueStr;
  397. break;
  398. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_COCOA:
  399. standalone.options.bridge_lv2Cocoa = valueStr;
  400. break;
  401. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_WINDOWS:
  402. standalone.options.bridge_lv2Win = valueStr;
  403. break;
  404. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_X11:
  405. standalone.options.bridge_lv2X11 = valueStr;
  406. break;
  407. #endif
  408. #ifdef WANT_VST
  409. case CarlaBackend::OPTION_PATH_BRIDGE_VST_COCOA:
  410. standalone.options.bridge_vstCocoa = valueStr;
  411. break;
  412. case CarlaBackend::OPTION_PATH_BRIDGE_VST_HWND:
  413. standalone.options.bridge_vstHWND = valueStr;
  414. break;
  415. case CarlaBackend::OPTION_PATH_BRIDGE_VST_X11:
  416. standalone.options.bridge_vstX11 = valueStr;
  417. break;
  418. #endif
  419. }
  420. }
  421. #endif
  422. // -------------------------------------------------------------------------------------------------------------------
  423. bool carla_load_project(const char* filename)
  424. {
  425. carla_debug("carla_load_project(\"%s\")", filename);
  426. CARLA_ASSERT(standalone.engine != nullptr);
  427. CARLA_ASSERT(filename != nullptr);
  428. if (standalone.engine != nullptr)
  429. return standalone.engine->loadProject(filename);
  430. standalone.lastError = "Engine is not started";
  431. return false;
  432. }
  433. bool carla_save_project(const char* filename)
  434. {
  435. carla_debug("carla_save_project(\"%s\")", filename);
  436. CARLA_ASSERT(standalone.engine != nullptr);
  437. CARLA_ASSERT(filename != nullptr);
  438. if (standalone.engine != nullptr)
  439. return standalone.engine->saveProject(filename);
  440. standalone.lastError = "Engine is not started";
  441. return false;
  442. }
  443. // -------------------------------------------------------------------------------------------------------------------
  444. void carla_patchbay_connect(int portA, int portB)
  445. {
  446. carla_debug("carla_patchbay_connect(%i, %i)", portA, portB);
  447. CARLA_ASSERT(standalone.engine != nullptr);
  448. if (standalone.engine != nullptr)
  449. return standalone.engine->patchbayConnect(portA, portB);
  450. }
  451. void carla_patchbay_disconnect(int connectionId)
  452. {
  453. carla_debug("carla_patchbay_disconnect(%i)", connectionId);
  454. CARLA_ASSERT(standalone.engine != nullptr);
  455. if (standalone.engine != nullptr)
  456. return standalone.engine->patchbayDisconnect(connectionId);
  457. }
  458. void carla_patchbay_refresh()
  459. {
  460. carla_debug("carla_patchbay_refresh()");
  461. CARLA_ASSERT(standalone.engine != nullptr);
  462. if (standalone.engine != nullptr)
  463. return standalone.engine->patchbayRefresh();
  464. }
  465. // -------------------------------------------------------------------------------------------------------------------
  466. void carla_transport_play()
  467. {
  468. carla_debug("carla_transport_play()");
  469. CARLA_ASSERT(standalone.engine != nullptr);
  470. if (standalone.engine != nullptr)
  471. standalone.engine->transportPlay();
  472. }
  473. void carla_transport_pause()
  474. {
  475. carla_debug("carla_transport_pause()");
  476. CARLA_ASSERT(standalone.engine != nullptr);
  477. if (standalone.engine != nullptr)
  478. standalone.engine->transportPause();
  479. }
  480. void carla_transport_relocate(uint32_t frames)
  481. {
  482. carla_debug("carla_transport_relocate(%i)", frames);
  483. CARLA_ASSERT(standalone.engine != nullptr);
  484. if (standalone.engine != nullptr)
  485. standalone.engine->transportRelocate(frames);
  486. }
  487. uint32_t carla_get_current_transport_frame()
  488. {
  489. CARLA_ASSERT(standalone.engine != nullptr);
  490. if (standalone.engine != nullptr)
  491. {
  492. const CarlaBackend::EngineTimeInfo& timeInfo(standalone.engine->getTimeInfo());
  493. return timeInfo.frame;
  494. }
  495. return 0;
  496. }
  497. const CarlaTransportInfo* carla_get_transport_info()
  498. {
  499. CARLA_ASSERT(standalone.engine != nullptr);
  500. static CarlaTransportInfo info;
  501. if (standalone.engine != nullptr)
  502. {
  503. const CarlaBackend::EngineTimeInfo& timeInfo(standalone.engine->getTimeInfo());
  504. info.playing = timeInfo.playing;
  505. info.frame = timeInfo.frame;
  506. if (timeInfo.valid & timeInfo.ValidBBT)
  507. {
  508. info.bar = timeInfo.bbt.bar;
  509. info.beat = timeInfo.bbt.beat;
  510. info.tick = timeInfo.bbt.tick;
  511. info.bpm = timeInfo.bbt.beatsPerMinute;
  512. }
  513. else
  514. {
  515. info.bar = 0;
  516. info.beat = 0;
  517. info.tick = 0;
  518. info.bpm = 0.0;
  519. }
  520. }
  521. else
  522. {
  523. info.playing = false;
  524. info.frame = 0;
  525. info.bar = 0;
  526. info.beat = 0;
  527. info.tick = 0;
  528. info.bpm = 0.0;
  529. }
  530. return &info;
  531. }
  532. // -------------------------------------------------------------------------------------------------------------------
  533. bool carla_add_plugin(CarlaBackend::BinaryType btype, CarlaBackend::PluginType ptype, const char* filename, const char* const name, const char* label, const void* extraStuff)
  534. {
  535. carla_debug("carla_add_plugin(%s, %s, \"%s\", \"%s\", \"%s\", %p)", CarlaBackend::BinaryType2Str(btype), CarlaBackend::PluginType2Str(ptype), filename, name, label, extraStuff);
  536. CARLA_ASSERT(standalone.engine != nullptr);
  537. if (standalone.engine != nullptr && standalone.engine->isRunning())
  538. return standalone.engine->addPlugin(btype, ptype, filename, name, label, extraStuff);
  539. standalone.lastError = "Engine is not started";
  540. return false;
  541. }
  542. bool carla_remove_plugin(unsigned int pluginId)
  543. {
  544. carla_debug("carla_remove_plugin(%i)", pluginId);
  545. CARLA_ASSERT(standalone.engine != nullptr);
  546. if (standalone.engine != nullptr && standalone.engine->isRunning())
  547. return standalone.engine->removePlugin(pluginId);
  548. standalone.lastError = "Engine is not started";
  549. return false;
  550. }
  551. void carla_remove_all_plugins()
  552. {
  553. carla_debug("carla_remove_all_plugins()");
  554. CARLA_ASSERT(standalone.engine != nullptr);
  555. if (standalone.engine != nullptr && standalone.engine->isRunning())
  556. standalone.engine->removeAllPlugins();
  557. }
  558. bool carla_load_plugin_state(unsigned int pluginId, const char* filename)
  559. {
  560. carla_debug("carla_load_plugin_state(%i, \"%s\")", pluginId, filename);
  561. CARLA_ASSERT(standalone.engine != nullptr);
  562. if (standalone.engine == nullptr)
  563. return false;
  564. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  565. return plugin->loadStateFromFile(filename);
  566. carla_stderr2("carla_load_plugin_state(%i, \"%s\") - could not find plugin", pluginId, filename);
  567. return false;
  568. }
  569. bool carla_save_plugin_state(unsigned int pluginId, const char* filename)
  570. {
  571. carla_debug("carla_save_plugin_state(%i, \"%s\")", pluginId, filename);
  572. CARLA_ASSERT(standalone.engine != nullptr);
  573. if (standalone.engine == nullptr)
  574. return false;
  575. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  576. return plugin->saveStateToFile(filename);
  577. carla_stderr2("carla_save_plugin_state(%i, \"%s\") - could not find plugin", pluginId, filename);
  578. return false;
  579. }
  580. // -------------------------------------------------------------------------------------------------------------------
  581. const CarlaPluginInfo* carla_get_plugin_info(unsigned int pluginId)
  582. {
  583. carla_debug("carla_get_plugin_info(%i)", pluginId);
  584. CARLA_ASSERT(standalone.engine != nullptr);
  585. static CarlaPluginInfo info;
  586. // reset
  587. info.type = CarlaBackend::PLUGIN_NONE;
  588. info.category = CarlaBackend::PLUGIN_CATEGORY_NONE;
  589. info.hints = 0x0;
  590. info.hints = 0x0;
  591. info.binary = nullptr;
  592. info.name = nullptr;
  593. info.uniqueId = 0;
  594. info.latency = 0;
  595. info.optionsAvailable = 0x0;
  596. info.optionsEnabled = 0x0;
  597. // cleanup
  598. if (info.label != nullptr)
  599. {
  600. delete[] info.label;
  601. info.label = nullptr;
  602. }
  603. if (info.maker != nullptr)
  604. {
  605. delete[] info.maker;
  606. info.maker = nullptr;
  607. }
  608. if (info.copyright != nullptr)
  609. {
  610. delete[] info.copyright;
  611. info.copyright = nullptr;
  612. }
  613. if (standalone.engine == nullptr)
  614. return &info;
  615. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  616. {
  617. char strBufLabel[STR_MAX] = { 0 };
  618. char strBufMaker[STR_MAX] = { 0 };
  619. char strBufCopyright[STR_MAX] = { 0 };
  620. info.type = plugin->type();
  621. info.category = plugin->category();
  622. info.hints = plugin->hints();
  623. info.binary = plugin->filename();
  624. info.name = plugin->name();
  625. info.uniqueId = plugin->uniqueId();
  626. info.latency = plugin->latency();
  627. info.optionsAvailable = plugin->availableOptions();
  628. info.optionsEnabled = plugin->options();
  629. plugin->getLabel(strBufLabel);
  630. info.label = carla_strdup(strBufLabel);
  631. plugin->getMaker(strBufMaker);
  632. info.maker = carla_strdup(strBufMaker);
  633. plugin->getCopyright(strBufCopyright);
  634. info.copyright = carla_strdup(strBufCopyright);
  635. return &info;
  636. }
  637. carla_stderr2("carla_get_plugin_info(%i) - could not find plugin", pluginId);
  638. return &info;
  639. }
  640. const CarlaPortCountInfo* carla_get_audio_port_count_info(unsigned int pluginId)
  641. {
  642. carla_debug("carla_get_audio_port_count_info(%i)", pluginId);
  643. CARLA_ASSERT(standalone.engine != nullptr);
  644. static CarlaPortCountInfo info;
  645. // reset
  646. info.ins = 0;
  647. info.outs = 0;
  648. info.total = 0;
  649. if (standalone.engine == nullptr)
  650. return &info;
  651. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  652. {
  653. info.ins = plugin->audioInCount();
  654. info.outs = plugin->audioOutCount();
  655. info.total = info.ins + info.outs;
  656. return &info;
  657. }
  658. carla_stderr2("carla_get_audio_port_count_info(%i) - could not find plugin", pluginId);
  659. return &info;
  660. }
  661. const CarlaPortCountInfo* carla_get_midi_port_count_info(unsigned int pluginId)
  662. {
  663. carla_debug("carla_get_midi_port_count_info(%i)", pluginId);
  664. CARLA_ASSERT(standalone.engine != nullptr);
  665. static CarlaPortCountInfo info;
  666. // reset
  667. info.ins = 0;
  668. info.outs = 0;
  669. info.total = 0;
  670. if (standalone.engine == nullptr)
  671. return &info;
  672. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  673. {
  674. info.ins = plugin->midiInCount();
  675. info.outs = plugin->midiOutCount();
  676. info.total = info.ins + info.outs;
  677. return &info;
  678. }
  679. carla_stderr2("carla_get_midi_port_count_info(%i) - could not find plugin", pluginId);
  680. return &info;
  681. }
  682. const CarlaPortCountInfo* carla_get_parameter_count_info(unsigned int pluginId)
  683. {
  684. carla_debug("carla_get_parameter_count_info(%i)", pluginId);
  685. CARLA_ASSERT(standalone.engine != nullptr);
  686. static CarlaPortCountInfo info;
  687. // reset
  688. info.ins = 0;
  689. info.outs = 0;
  690. info.total = 0;
  691. if (standalone.engine == nullptr)
  692. return &info;
  693. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  694. {
  695. plugin->getParameterCountInfo(&info.ins, &info.outs, &info.total);
  696. return &info;
  697. }
  698. carla_stderr2("carla_get_parameter_count_info(%i) - could not find plugin", pluginId);
  699. return &info;
  700. }
  701. const CarlaParameterInfo* carla_get_parameter_info(unsigned int pluginId, uint32_t parameterId)
  702. {
  703. carla_debug("carla_get_parameter_info(%i, %i)", pluginId, parameterId);
  704. CARLA_ASSERT(standalone.engine != nullptr);
  705. static CarlaParameterInfo info;
  706. // reset
  707. info.scalePointCount = 0;
  708. // cleanup
  709. if (info.name != nullptr)
  710. {
  711. delete[] info.name;
  712. info.name = nullptr;
  713. }
  714. if (info.symbol != nullptr)
  715. {
  716. delete[] info.symbol;
  717. info.symbol = nullptr;
  718. }
  719. if (info.unit != nullptr)
  720. {
  721. delete[] info.unit;
  722. info.unit = nullptr;
  723. }
  724. if (standalone.engine == nullptr)
  725. return &info;
  726. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  727. {
  728. if (parameterId < plugin->parameterCount())
  729. {
  730. char strBufName[STR_MAX] = { 0 };
  731. char strBufSymbol[STR_MAX] = { 0 };
  732. char strBufUnit[STR_MAX] = { 0 };
  733. info.scalePointCount = plugin->parameterScalePointCount(parameterId);
  734. plugin->getParameterName(parameterId, strBufName);
  735. info.name = carla_strdup(strBufName);
  736. plugin->getParameterSymbol(parameterId, strBufSymbol);
  737. info.symbol = carla_strdup(strBufSymbol);
  738. plugin->getParameterUnit(parameterId, strBufUnit);
  739. info.unit = carla_strdup(strBufUnit);
  740. }
  741. else
  742. carla_stderr2("carla_get_parameter_info(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  743. return &info;
  744. }
  745. carla_stderr2("carla_get_parameter_info(%i, %i) - could not find plugin", pluginId, parameterId);
  746. return &info;
  747. }
  748. const CarlaScalePointInfo* carla_get_parameter_scalepoint_info(unsigned int pluginId, uint32_t parameterId, uint32_t scalePointId)
  749. {
  750. carla_debug("carla_get_parameter_scalepoint_info(%i, %i, %i)", pluginId, parameterId, scalePointId);
  751. CARLA_ASSERT(standalone.engine != nullptr);
  752. static CarlaScalePointInfo info;
  753. // reset
  754. info.value = 0.0f;
  755. // cleanup
  756. if (info.label != nullptr)
  757. {
  758. delete[] info.label;
  759. info.label = nullptr;
  760. }
  761. if (standalone.engine == nullptr)
  762. return &info;
  763. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  764. {
  765. if (parameterId < plugin->parameterCount())
  766. {
  767. if (scalePointId < plugin->parameterScalePointCount(parameterId))
  768. {
  769. char strBufLabel[STR_MAX] = { 0 };
  770. info.value = plugin->getParameterScalePointValue(parameterId, scalePointId);
  771. plugin->getParameterScalePointLabel(parameterId, scalePointId, strBufLabel);
  772. info.label = carla_strdup(strBufLabel);
  773. }
  774. else
  775. carla_stderr2("carla_get_parameter_scalepoint_info(%i, %i, %i) - scalePointId out of bounds", pluginId, parameterId, scalePointId);
  776. }
  777. else
  778. carla_stderr2("carla_get_parameter_scalepoint_info(%i, %i, %i) - parameterId out of bounds", pluginId, parameterId, scalePointId);
  779. return &info;
  780. }
  781. carla_stderr2("carla_get_parameter_scalepoint_info(%i, %i, %i) - could not find plugin", pluginId, parameterId, scalePointId);
  782. return &info;
  783. }
  784. // -------------------------------------------------------------------------------------------------------------------
  785. const CarlaBackend::ParameterData* carla_get_parameter_data(unsigned int pluginId, uint32_t parameterId)
  786. {
  787. carla_debug("carla_get_parameter_data(%i, %i)", pluginId, parameterId);
  788. CARLA_ASSERT(standalone.engine != nullptr);
  789. static CarlaBackend::ParameterData data;
  790. if (standalone.engine == nullptr)
  791. return &data;
  792. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  793. {
  794. if (parameterId < plugin->parameterCount())
  795. return &plugin->parameterData(parameterId);
  796. carla_stderr2("carla_get_parameter_data(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  797. return &data;
  798. }
  799. carla_stderr2("carla_get_parameter_data(%i, %i) - could not find plugin", pluginId, parameterId);
  800. return &data;
  801. }
  802. const CarlaBackend::ParameterRanges* carla_get_parameter_ranges(unsigned int pluginId, uint32_t parameterId)
  803. {
  804. carla_debug("carla_get_parameter_ranges(%i, %i)", pluginId, parameterId);
  805. CARLA_ASSERT(standalone.engine != nullptr);
  806. static CarlaBackend::ParameterRanges ranges;
  807. if (standalone.engine == nullptr)
  808. return &ranges;
  809. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  810. {
  811. if (parameterId < plugin->parameterCount())
  812. return &plugin->parameterRanges(parameterId);
  813. carla_stderr2("carla_get_parameter_ranges(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  814. return &ranges;
  815. }
  816. carla_stderr2("carla_get_parameter_ranges(%i, %i) - could not find plugin", pluginId, parameterId);
  817. return &ranges;
  818. }
  819. const CarlaBackend::MidiProgramData* carla_get_midi_program_data(unsigned int pluginId, uint32_t midiProgramId)
  820. {
  821. carla_debug("carla_get_midi_program_data(%i, %i)", pluginId, midiProgramId);
  822. CARLA_ASSERT(standalone.engine != nullptr);
  823. static CarlaBackend::MidiProgramData data;
  824. if (standalone.engine == nullptr)
  825. return &data;
  826. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  827. {
  828. if (midiProgramId < plugin->midiProgramCount())
  829. return &plugin->midiProgramData(midiProgramId);
  830. carla_stderr2("carla_get_midi_program_data(%i, %i) - midiProgramId out of bounds", pluginId, midiProgramId);
  831. return &data;
  832. }
  833. carla_stderr2("carla_get_midi_program_data(%i, %i) - could not find plugin", pluginId, midiProgramId);
  834. return &data;
  835. }
  836. const CarlaBackend::CustomData* carla_get_custom_data(unsigned int pluginId, uint32_t customDataId)
  837. {
  838. carla_debug("carla_get_custom_data(%i, %i)", pluginId, customDataId);
  839. CARLA_ASSERT(standalone.engine != nullptr);
  840. static CarlaBackend::CustomData data;
  841. if (standalone.engine == nullptr)
  842. return &data;
  843. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  844. {
  845. if (customDataId < plugin->customDataCount())
  846. return &plugin->customData(customDataId);
  847. carla_stderr2("carla_get_custom_data(%i, %i) - customDataId out of bounds", pluginId, customDataId);
  848. return &data;
  849. }
  850. carla_stderr2("carla_get_custom_data(%i, %i) - could not find plugin", pluginId, customDataId);
  851. return &data;
  852. }
  853. const char* carla_get_chunk_data(unsigned int pluginId)
  854. {
  855. carla_debug("carla_get_chunk_data(%i)", pluginId);
  856. CARLA_ASSERT(standalone.engine != nullptr);
  857. if (standalone.engine == nullptr)
  858. return nullptr;
  859. static CarlaString chunkData;
  860. // cleanup
  861. chunkData.clear();
  862. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  863. {
  864. if (plugin->options() & CarlaBackend::PLUGIN_OPTION_USE_CHUNKS)
  865. {
  866. void* data = nullptr;
  867. const int32_t dataSize = plugin->chunkData(&data);
  868. if (data != nullptr && dataSize >= 4)
  869. {
  870. chunkData.importBinaryAsBase64((const uint8_t*)data, static_cast<size_t>(dataSize));
  871. return (const char*)chunkData;
  872. }
  873. else
  874. carla_stderr2("carla_get_chunk_data(%i) - got invalid chunk data", pluginId);
  875. }
  876. else
  877. carla_stderr2("carla_get_chunk_data(%i) - plugin does not support chunks", pluginId);
  878. return nullptr;
  879. }
  880. carla_stderr2("carla_get_chunk_data(%i) - could not find plugin", pluginId);
  881. return nullptr;
  882. }
  883. // -------------------------------------------------------------------------------------------------------------------
  884. uint32_t carla_get_parameter_count(unsigned int pluginId)
  885. {
  886. carla_debug("carla_get_parameter_count(%i)", pluginId);
  887. CARLA_ASSERT(standalone.engine != nullptr);
  888. if (standalone.engine == nullptr)
  889. return 0;
  890. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  891. return plugin->parameterCount();
  892. carla_stderr2("carla_get_parameter_count(%i) - could not find plugin", pluginId);
  893. return 0;
  894. }
  895. uint32_t carla_get_program_count(unsigned int pluginId)
  896. {
  897. carla_debug("carla_get_program_count(%i)", pluginId);
  898. CARLA_ASSERT(standalone.engine != nullptr);
  899. if (standalone.engine == nullptr)
  900. return 0;
  901. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  902. return plugin->programCount();
  903. carla_stderr2("carla_get_program_count(%i) - could not find plugin", pluginId);
  904. return 0;
  905. }
  906. uint32_t carla_get_midi_program_count(unsigned int pluginId)
  907. {
  908. carla_debug("carla_get_midi_program_count(%i)", pluginId);
  909. CARLA_ASSERT(standalone.engine != nullptr);
  910. if (standalone.engine == nullptr)
  911. return 0;
  912. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  913. return plugin->midiProgramCount();
  914. carla_stderr2("carla_get_midi_program_count(%i) - could not find plugin", pluginId);
  915. return 0;
  916. }
  917. uint32_t carla_get_custom_data_count(unsigned int pluginId)
  918. {
  919. carla_debug("carla_get_custom_data_count(%i)", pluginId);
  920. CARLA_ASSERT(standalone.engine != nullptr);
  921. if (standalone.engine == nullptr)
  922. return 0;
  923. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  924. return plugin->customDataCount();
  925. carla_stderr2("carla_get_custom_data_count(%i) - could not find plugin", pluginId);
  926. return 0;
  927. }
  928. // -------------------------------------------------------------------------------------------------------------------
  929. const char* carla_get_parameter_text(unsigned int pluginId, uint32_t parameterId)
  930. {
  931. carla_debug("carla_get_parameter_text(%i, %i)", pluginId, parameterId);
  932. CARLA_ASSERT(standalone.engine != nullptr);
  933. if (standalone.engine == nullptr)
  934. return nullptr;
  935. static char textBuf[STR_MAX];
  936. carla_zeroMem(textBuf, sizeof(char)*STR_MAX);
  937. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  938. {
  939. if (parameterId < plugin->parameterCount())
  940. {
  941. plugin->getParameterText(parameterId, textBuf);
  942. return textBuf;
  943. }
  944. carla_stderr2("carla_get_parameter_text(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  945. return nullptr;
  946. }
  947. carla_stderr2("carla_get_parameter_text(%i, %i) - could not find plugin", pluginId, parameterId);
  948. return nullptr;
  949. }
  950. const char* carla_get_program_name(unsigned int pluginId, uint32_t programId)
  951. {
  952. carla_debug("carla_get_program_name(%i, %i)", pluginId, programId);
  953. CARLA_ASSERT(standalone.engine != nullptr);
  954. if (standalone.engine == nullptr)
  955. return nullptr;
  956. static char programName[STR_MAX];
  957. carla_zeroMem(programName, sizeof(char)*STR_MAX);
  958. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  959. {
  960. if (programId < plugin->programCount())
  961. {
  962. plugin->getProgramName(programId, programName);
  963. return programName;
  964. }
  965. carla_stderr2("carla_get_program_name(%i, %i) - programId out of bounds", pluginId, programId);
  966. return nullptr;
  967. }
  968. carla_stderr2("carla_get_program_name(%i, %i) - could not find plugin", pluginId, programId);
  969. return nullptr;
  970. }
  971. const char* carla_get_midi_program_name(unsigned int pluginId, uint32_t midiProgramId)
  972. {
  973. carla_debug("carla_get_midi_program_name(%i, %i)", pluginId, midiProgramId);
  974. CARLA_ASSERT(standalone.engine != nullptr);
  975. if (standalone.engine == nullptr)
  976. return nullptr;
  977. static char midiProgramName[STR_MAX];
  978. carla_zeroMem(midiProgramName, sizeof(char)*STR_MAX);
  979. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  980. {
  981. if (midiProgramId < plugin->midiProgramCount())
  982. {
  983. plugin->getMidiProgramName(midiProgramId, midiProgramName);
  984. return midiProgramName;
  985. }
  986. carla_stderr2("carla_get_midi_program_name(%i, %i) - midiProgramId out of bounds", pluginId, midiProgramId);
  987. return nullptr;
  988. }
  989. carla_stderr2("carla_get_midi_program_name(%i, %i) - could not find plugin", pluginId, midiProgramId);
  990. return nullptr;
  991. }
  992. const char* carla_get_real_plugin_name(unsigned int pluginId)
  993. {
  994. carla_debug("carla_get_real_plugin_name(%i)", pluginId);
  995. CARLA_ASSERT(standalone.engine != nullptr);
  996. if (standalone.engine == nullptr)
  997. return nullptr;
  998. static char realPluginName[STR_MAX];
  999. carla_zeroMem(realPluginName, sizeof(char)*STR_MAX);
  1000. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1001. {
  1002. plugin->getRealName(realPluginName);
  1003. return realPluginName;
  1004. }
  1005. carla_stderr2("carla_get_real_plugin_name(%i) - could not find plugin", pluginId);
  1006. return nullptr;
  1007. }
  1008. // -------------------------------------------------------------------------------------------------------------------
  1009. int32_t carla_get_current_program_index(unsigned int pluginId)
  1010. {
  1011. carla_debug("carla_get_current_program_index(%i)", pluginId);
  1012. CARLA_ASSERT(standalone.engine != nullptr);
  1013. if (standalone.engine == nullptr)
  1014. return -1;
  1015. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1016. return plugin->currentProgram();
  1017. carla_stderr2("carla_get_current_program_index(%i) - could not find plugin", pluginId);
  1018. return -1;
  1019. }
  1020. int32_t carla_get_current_midi_program_index(unsigned int pluginId)
  1021. {
  1022. carla_debug("carla_get_current_midi_program_index(%i)", pluginId);
  1023. CARLA_ASSERT(standalone.engine != nullptr);
  1024. if (standalone.engine == nullptr)
  1025. return -1;
  1026. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1027. return plugin->currentMidiProgram();
  1028. carla_stderr2("carla_get_current_midi_program_index(%i) - could not find plugin", pluginId);
  1029. return -1;
  1030. }
  1031. // -------------------------------------------------------------------------------------------------------------------
  1032. float carla_get_default_parameter_value(unsigned int pluginId, uint32_t parameterId)
  1033. {
  1034. carla_debug("carla_get_default_parameter_value(%i, %i)", pluginId, parameterId);
  1035. CARLA_ASSERT(standalone.engine != nullptr);
  1036. if (standalone.engine == nullptr)
  1037. return 0.0f;
  1038. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1039. {
  1040. if (parameterId < plugin->parameterCount())
  1041. return plugin->parameterRanges(parameterId).def;
  1042. carla_stderr2("carla_get_default_parameter_value(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  1043. return 0.0f;
  1044. }
  1045. carla_stderr2("carla_get_default_parameter_value(%i, %i) - could not find plugin", pluginId, parameterId);
  1046. return 0.0f;
  1047. }
  1048. float carla_get_current_parameter_value(unsigned int pluginId, uint32_t parameterId)
  1049. {
  1050. carla_debug("carla_get_current_parameter_value(%i, %i)", pluginId, parameterId);
  1051. CARLA_ASSERT(standalone.engine != nullptr);
  1052. if (standalone.engine == nullptr)
  1053. return 0.0f;
  1054. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1055. {
  1056. if (parameterId < plugin->parameterCount())
  1057. return plugin->getParameterValue(parameterId);
  1058. carla_stderr2("carla_get_current_parameter_value(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  1059. return 0.0f;
  1060. }
  1061. carla_stderr2("carla_get_current_parameter_value(%i, %i) - could not find plugin", pluginId, parameterId);
  1062. return 0.0f;
  1063. }
  1064. // -------------------------------------------------------------------------------------------------------------------
  1065. float carla_get_input_peak_value(unsigned int pluginId, unsigned short portId)
  1066. {
  1067. CARLA_ASSERT(standalone.engine != nullptr);
  1068. CARLA_ASSERT(portId == 1 || portId == 2);
  1069. if (standalone.engine == nullptr)
  1070. return 0.0f;
  1071. if (pluginId >= standalone.engine->currentPluginCount())
  1072. {
  1073. carla_stderr2("carla_get_input_peak_value(%i, %i) - invalid plugin value", pluginId, portId);
  1074. return 0.0f;
  1075. }
  1076. if (portId == 1 || portId == 2)
  1077. return standalone.engine->getInputPeak(pluginId, portId);
  1078. carla_stderr2("carla_get_input_peak_value(%i, %i) - invalid port value", pluginId, portId);
  1079. return 0.0f;
  1080. }
  1081. float carla_get_output_peak_value(unsigned int pluginId, unsigned short portId)
  1082. {
  1083. CARLA_ASSERT(standalone.engine != nullptr);
  1084. CARLA_ASSERT(portId == 1 || portId == 2);
  1085. if (standalone.engine == nullptr)
  1086. return 0.0f;
  1087. if (pluginId >= standalone.engine->currentPluginCount())
  1088. {
  1089. carla_stderr2("carla_get_input_peak_value(%i, %i) - invalid plugin value", pluginId, portId);
  1090. return 0.0f;
  1091. }
  1092. if (portId == 1 || portId == 2)
  1093. return standalone.engine->getOutputPeak(pluginId, portId);
  1094. carla_stderr2("carla_get_output_peak_value(%i, %i) - invalid port value", pluginId, portId);
  1095. return 0.0f;
  1096. }
  1097. // -------------------------------------------------------------------------------------------------------------------
  1098. void carla_set_option(unsigned int pluginId, unsigned int option, bool yesNo)
  1099. {
  1100. carla_debug("carla_set_option(%i, %i, %s)", pluginId, option, bool2str(yesNo));
  1101. CARLA_ASSERT(standalone.engine != nullptr);
  1102. if (standalone.engine == nullptr)
  1103. return;
  1104. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1105. return plugin->setOption(option, yesNo);
  1106. carla_stderr2("carla_set_option(%i, %i, %s) - could not find plugin", pluginId, option, bool2str(yesNo));
  1107. }
  1108. void carla_set_active(unsigned int pluginId, bool onOff)
  1109. {
  1110. carla_debug("carla_set_active(%i, %s)", pluginId, bool2str(onOff));
  1111. CARLA_ASSERT(standalone.engine != nullptr);
  1112. if (standalone.engine == nullptr)
  1113. return;
  1114. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1115. return plugin->setActive(onOff, true, false);
  1116. carla_stderr2("carla_set_active(%i, %s) - could not find plugin", pluginId, bool2str(onOff));
  1117. }
  1118. void carla_set_drywet(unsigned int pluginId, float value)
  1119. {
  1120. carla_debug("carla_set_drywet(%i, %f)", pluginId, value);
  1121. CARLA_ASSERT(standalone.engine != nullptr);
  1122. if (standalone.engine == nullptr)
  1123. return;
  1124. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1125. return plugin->setDryWet(value, true, false);
  1126. carla_stderr2("carla_set_drywet(%i, %f) - could not find plugin", pluginId, value);
  1127. }
  1128. void carla_set_volume(unsigned int pluginId, float value)
  1129. {
  1130. carla_debug("carla_set_volume(%i, %f)", pluginId, value);
  1131. CARLA_ASSERT(standalone.engine != nullptr);
  1132. if (standalone.engine == nullptr)
  1133. return;
  1134. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1135. return plugin->setVolume(value, true, false);
  1136. carla_stderr2("carla_set_volume(%i, %f) - could not find plugin", pluginId, value);
  1137. }
  1138. void carla_set_balance_left(unsigned int pluginId, float value)
  1139. {
  1140. carla_debug("carla_set_balance_left(%i, %f)", pluginId, value);
  1141. CARLA_ASSERT(standalone.engine != nullptr);
  1142. if (standalone.engine == nullptr)
  1143. return;
  1144. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1145. return plugin->setBalanceLeft(value, true, false);
  1146. carla_stderr2("carla_set_balance_left(%i, %f) - could not find plugin", pluginId, value);
  1147. }
  1148. void carla_set_balance_right(unsigned int pluginId, float value)
  1149. {
  1150. carla_debug("carla_set_balance_right(%i, %f)", pluginId, value);
  1151. CARLA_ASSERT(standalone.engine != nullptr);
  1152. if (standalone.engine == nullptr)
  1153. return;
  1154. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1155. return plugin->setBalanceRight(value, true, false);
  1156. carla_stderr2("carla_set_balance_right(%i, %f) - could not find plugin", pluginId, value);
  1157. }
  1158. void carla_set_panning(unsigned int pluginId, float value)
  1159. {
  1160. carla_debug("carla_set_panning(%i, %f)", pluginId, value);
  1161. CARLA_ASSERT(standalone.engine != nullptr);
  1162. if (standalone.engine == nullptr)
  1163. return;
  1164. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1165. return plugin->setPanning(value, true, false);
  1166. carla_stderr2("carla_set_panning(%i, %f) - could not find plugin", pluginId, value);
  1167. }
  1168. void carla_set_ctrl_channel(unsigned int pluginId, int8_t channel)
  1169. {
  1170. carla_debug("carla_set_ctrl_channel(%i, %i)", pluginId, channel);
  1171. CARLA_ASSERT(standalone.engine != nullptr);
  1172. if (standalone.engine == nullptr)
  1173. return;
  1174. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1175. return plugin->setCtrlChannel(channel, true, false);
  1176. carla_stderr2("carla_set_ctrl_channel(%i, %i) - could not find plugin", pluginId, channel);
  1177. }
  1178. // -------------------------------------------------------------------------------------------------------------------
  1179. void carla_set_parameter_value(unsigned int pluginId, uint32_t parameterId, float value)
  1180. {
  1181. carla_debug("carla_set_parameter_value(%i, %i, %f)", pluginId, parameterId, value);
  1182. CARLA_ASSERT(standalone.engine != nullptr);
  1183. if (standalone.engine == nullptr)
  1184. return;
  1185. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1186. {
  1187. if (parameterId < plugin->parameterCount())
  1188. return plugin->setParameterValue(parameterId, value, true, true, false);
  1189. carla_stderr2("carla_set_parameter_value(%i, %i, %f) - parameterId out of bounds", pluginId, parameterId, value);
  1190. return;
  1191. }
  1192. carla_stderr2("carla_set_parameter_value(%i, %i, %f) - could not find plugin", pluginId, parameterId, value);
  1193. }
  1194. void carla_set_parameter_midi_channel(unsigned int pluginId, uint32_t parameterId, uint8_t channel)
  1195. {
  1196. carla_debug("carla_set_parameter_midi_channel(%i, %i, %i)", pluginId, parameterId, channel);
  1197. CARLA_ASSERT(standalone.engine != nullptr);
  1198. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  1199. if (channel >= MAX_MIDI_CHANNELS)
  1200. {
  1201. carla_stderr2("carla_set_parameter_midi_channel(%i, %i, %i) - invalid channel number", pluginId, parameterId, channel);
  1202. return;
  1203. }
  1204. if (standalone.engine == nullptr)
  1205. return;
  1206. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1207. {
  1208. if (parameterId < plugin->parameterCount())
  1209. return plugin->setParameterMidiChannel(parameterId, channel, true, false);
  1210. carla_stderr2("carla_set_parameter_midi_channel(%i, %i, %i) - parameterId out of bounds", pluginId, parameterId, channel);
  1211. return;
  1212. }
  1213. carla_stderr2("carla_set_parameter_midi_channel(%i, %i, %i) - could not find plugin", pluginId, parameterId, channel);
  1214. }
  1215. void carla_set_parameter_midi_cc(unsigned int pluginId, uint32_t parameterId, int16_t cc)
  1216. {
  1217. carla_debug("carla_set_parameter_midi_cc(%i, %i, %i)", pluginId, parameterId, cc);
  1218. CARLA_ASSERT(standalone.engine != nullptr);
  1219. CARLA_ASSERT(cc >= -1 && cc <= 0x5F);
  1220. if (cc < -1)
  1221. {
  1222. cc = -1;
  1223. }
  1224. else if (cc > 0x5F) // 95
  1225. {
  1226. carla_stderr2("carla_set_parameter_midi_cc(%i, %i, %i) - invalid cc number", pluginId, parameterId, cc);
  1227. return;
  1228. }
  1229. if (standalone.engine == nullptr)
  1230. return;
  1231. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1232. {
  1233. if (parameterId < plugin->parameterCount())
  1234. return plugin->setParameterMidiCC(parameterId, cc, true, false);
  1235. carla_stderr2("carla_set_parameter_midi_cc(%i, %i, %i) - parameterId out of bounds", pluginId, parameterId, cc);
  1236. return;
  1237. }
  1238. carla_stderr2("carla_set_parameter_midi_cc(%i, %i, %i) - could not find plugin", pluginId, parameterId, cc);
  1239. }
  1240. void carla_set_program(unsigned int pluginId, uint32_t programId)
  1241. {
  1242. carla_debug("carla_set_program(%i, %i)", pluginId, programId);
  1243. CARLA_ASSERT(standalone.engine != nullptr);
  1244. if (standalone.engine == nullptr)
  1245. return;
  1246. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1247. {
  1248. if (programId < plugin->programCount())
  1249. return plugin->setProgram(static_cast<int32_t>(programId), true, true, false);
  1250. carla_stderr2("carla_set_program(%i, %i) - programId out of bounds", pluginId, programId);
  1251. return;
  1252. }
  1253. carla_stderr2("carla_set_program(%i, %i) - could not find plugin", pluginId, programId);
  1254. }
  1255. void carla_set_midi_program(unsigned int pluginId, uint32_t midiProgramId)
  1256. {
  1257. carla_debug("carla_set_midi_program(%i, %i)", pluginId, midiProgramId);
  1258. CARLA_ASSERT(standalone.engine != nullptr);
  1259. if (standalone.engine == nullptr)
  1260. return;
  1261. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1262. {
  1263. if (midiProgramId < plugin->midiProgramCount())
  1264. return plugin->setMidiProgram(static_cast<int32_t>(midiProgramId), true, true, false);
  1265. carla_stderr2("carla_set_midi_program(%i, %i) - midiProgramId out of bounds", pluginId, midiProgramId);
  1266. return;
  1267. }
  1268. carla_stderr2("carla_set_midi_program(%i, %i) - could not find plugin", pluginId, midiProgramId);
  1269. }
  1270. // -------------------------------------------------------------------------------------------------------------------
  1271. void carla_set_custom_data(unsigned int pluginId, const char* type, const char* key, const char* value)
  1272. {
  1273. carla_debug("carla_set_custom_data(%i, \"%s\", \"%s\", \"%s\")", pluginId, type, key, value);
  1274. CARLA_ASSERT(standalone.engine != nullptr);
  1275. if (standalone.engine == nullptr)
  1276. return;
  1277. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1278. return plugin->setCustomData(type, key, value, true);
  1279. carla_stderr2("carla_set_custom_data(%i, \"%s\", \"%s\", \"%s\") - could not find plugin", pluginId, type, key, value);
  1280. }
  1281. void carla_set_chunk_data(unsigned int pluginId, const char* chunkData)
  1282. {
  1283. carla_debug("carla_set_chunk_data(%i, \"%s\")", pluginId, chunkData);
  1284. CARLA_ASSERT(standalone.engine != nullptr);
  1285. if (standalone.engine == nullptr)
  1286. return;
  1287. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1288. {
  1289. if (plugin->options() & CarlaBackend::PLUGIN_OPTION_USE_CHUNKS)
  1290. return plugin->setChunkData(chunkData);
  1291. carla_stderr2("carla_set_chunk_data(%i, \"%s\") - plugin does not support chunks", pluginId, chunkData);
  1292. return;
  1293. }
  1294. carla_stderr2("carla_set_chunk_data(%i, \"%s\") - could not find plugin", pluginId, chunkData);
  1295. }
  1296. // -------------------------------------------------------------------------------------------------------------------
  1297. void carla_prepare_for_save(unsigned int pluginId)
  1298. {
  1299. carla_debug("carla_prepare_for_save(%i)", pluginId);
  1300. CARLA_ASSERT(standalone.engine != nullptr);
  1301. if (standalone.engine == nullptr)
  1302. return;
  1303. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1304. return plugin->prepareForSave();
  1305. carla_stderr2("carla_prepare_for_save(%i) - could not find plugin", pluginId);
  1306. }
  1307. void carla_send_midi_note(unsigned int pluginId, uint8_t channel, uint8_t note, uint8_t velocity)
  1308. {
  1309. carla_debug("carla_send_midi_note(%i, %i, %i, %i)", pluginId, channel, note, velocity);
  1310. CARLA_ASSERT(standalone.engine != nullptr);
  1311. if (standalone.engine == nullptr || ! standalone.engine->isRunning())
  1312. return;
  1313. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1314. return plugin->sendMidiSingleNote(channel, note, velocity, true, true, false);
  1315. carla_stderr2("carla_send_midi_note(%i, %i, %i, %i) - could not find plugin", pluginId, channel, note, velocity);
  1316. }
  1317. void carla_show_gui(unsigned int pluginId, bool yesno)
  1318. {
  1319. carla_debug("carla_show_gui(%i, %s)", pluginId, bool2str(yesno));
  1320. CARLA_ASSERT(standalone.engine != nullptr);
  1321. if (standalone.engine == nullptr)
  1322. return;
  1323. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1324. return plugin->showGui(yesno);
  1325. carla_stderr2("carla_show_gui(%i, %s) - could not find plugin", pluginId, bool2str(yesno));
  1326. }
  1327. // -------------------------------------------------------------------------------------------------------------------
  1328. uint32_t carla_get_buffer_size()
  1329. {
  1330. carla_debug("carla_get_buffer_size()");
  1331. CARLA_ASSERT(standalone.engine != nullptr);
  1332. if (standalone.engine == nullptr)
  1333. return 0;
  1334. return standalone.engine->getBufferSize();
  1335. }
  1336. double carla_get_sample_rate()
  1337. {
  1338. carla_debug("carla_get_sample_rate()");
  1339. CARLA_ASSERT(standalone.engine != nullptr);
  1340. if (standalone.engine == nullptr)
  1341. return 0.0;
  1342. return standalone.engine->getSampleRate();
  1343. }
  1344. // -------------------------------------------------------------------------------------------------------------------
  1345. const char* carla_get_last_error()
  1346. {
  1347. carla_debug("carla_get_last_error()");
  1348. if (standalone.engine != nullptr)
  1349. return standalone.engine->getLastError();
  1350. return standalone.lastError;
  1351. }
  1352. const char* carla_get_host_osc_url()
  1353. {
  1354. carla_debug("carla_get_host_osc_url()");
  1355. CARLA_ASSERT(standalone.engine != nullptr);
  1356. if (standalone.engine == nullptr)
  1357. return nullptr;
  1358. return standalone.engine->getOscServerPathTCP();
  1359. }
  1360. // -------------------------------------------------------------------------------------------------------------------
  1361. #define NSM_API_VERSION_MAJOR 1
  1362. #define NSM_API_VERSION_MINOR 2
  1363. class CarlaNSM
  1364. {
  1365. public:
  1366. CarlaNSM()
  1367. : fServerThread(nullptr),
  1368. fReplyAddr(nullptr),
  1369. fIsOpened(false),
  1370. fIsSaved(false)
  1371. {
  1372. }
  1373. ~CarlaNSM()
  1374. {
  1375. if (fReplyAddr != nullptr)
  1376. lo_address_free(fReplyAddr);
  1377. if (fServerThread != nullptr)
  1378. {
  1379. lo_server_thread_stop(fServerThread);
  1380. lo_server_thread_del_method(fServerThread, "/reply", "ssss");
  1381. lo_server_thread_del_method(fServerThread, "/nsm/client/open", "sss");
  1382. lo_server_thread_del_method(fServerThread, "/nsm/client/save", "");
  1383. lo_server_thread_free(fServerThread);
  1384. }
  1385. }
  1386. void announce(const char* const url, const int pid)
  1387. {
  1388. lo_address const addr = lo_address_new_from_url(url);
  1389. if (addr == nullptr)
  1390. return;
  1391. const int proto = lo_address_get_protocol(addr);
  1392. if (fServerThread == nullptr)
  1393. {
  1394. // create new OSC thread
  1395. fServerThread = lo_server_thread_new_with_proto(nullptr, proto, error_handler);
  1396. // register message handlers and start OSC thread
  1397. lo_server_thread_add_method(fServerThread, "/reply", "ssss", _reply_handler, this);
  1398. lo_server_thread_add_method(fServerThread, "/nsm/client/open", "sss", _open_handler, this);
  1399. lo_server_thread_add_method(fServerThread, "/nsm/client/save", "", _save_handler, this);
  1400. lo_server_thread_start(fServerThread);
  1401. }
  1402. lo_send_from(addr, lo_server_thread_get_server(fServerThread), LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii",
  1403. "Carla", ":switch:", "carla", NSM_API_VERSION_MAJOR, NSM_API_VERSION_MINOR, pid);
  1404. lo_address_free(addr);
  1405. }
  1406. void replyOpen()
  1407. {
  1408. fIsOpened = true;
  1409. }
  1410. void replySave()
  1411. {
  1412. fIsSaved = true;
  1413. }
  1414. protected:
  1415. int handleReply(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg)
  1416. {
  1417. carla_debug("CarlaNSM::handleReply(%s, %i, %p, %s, %p)", path, argc, argv, types, msg);
  1418. if (fReplyAddr != nullptr)
  1419. lo_address_free(fReplyAddr);
  1420. fIsOpened = false;
  1421. fIsSaved = false;
  1422. char* const url = lo_address_get_url(lo_message_get_source(msg));
  1423. fReplyAddr = lo_address_new_from_url(url);
  1424. std::free(url);
  1425. const char* const method = &argv[0]->s;
  1426. const char* const smName = &argv[2]->s;
  1427. if (std::strcmp(method, "/nsm/server/announce") == 0 && standalone.callback != nullptr)
  1428. standalone.callback(standalone.callbackPtr, CarlaBackend::CALLBACK_NSM_ANNOUNCE, 0, 0, 0, 0.0f, smName);
  1429. return 0;
  1430. }
  1431. int handleOpen(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg)
  1432. {
  1433. carla_debug("CarlaNSM::handleOpen(\"%s\", \"%s\", %p, %i, %p)", path, types, argv, argc, msg);
  1434. if (standalone.callback == nullptr)
  1435. return 1;
  1436. if (fServerThread == nullptr)
  1437. return 1;
  1438. if (fReplyAddr == nullptr)
  1439. return 1;
  1440. const char* const projectPath = &argv[0]->s;
  1441. const char* const clientId = &argv[2]->s;
  1442. char data[std::strlen(projectPath)+std::strlen(clientId)+2];
  1443. std::strcpy(data, projectPath);
  1444. std::strcat(data, ":");
  1445. std::strcat(data, clientId);
  1446. standalone.callback(nullptr, CarlaBackend::CALLBACK_NSM_OPEN, 0, 0, 0, 0.0f, data);
  1447. for (int i=0; i < 30 && ! fIsOpened; i++)
  1448. carla_msleep(100);
  1449. if (fIsOpened)
  1450. lo_send_from(fReplyAddr, lo_server_thread_get_server(fServerThread), LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/open", "OK");
  1451. return 0;
  1452. }
  1453. int handleSave(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg)
  1454. {
  1455. carla_debug("CarlaNSM::handleSave(\"%s\", \"%s\", %p, %i, %p)", path, types, argv, argc, msg);
  1456. if (standalone.callback == nullptr)
  1457. return 1;
  1458. if (fServerThread == nullptr)
  1459. return 1;
  1460. if (fReplyAddr == nullptr)
  1461. return 1;
  1462. standalone.callback(nullptr, CarlaBackend::CALLBACK_NSM_SAVE, 0, 0, 0, 0.0f, nullptr);
  1463. for (int i=0; i < 30 && ! fIsSaved; i++)
  1464. carla_msleep(100);
  1465. if (fIsSaved)
  1466. lo_send_from(fReplyAddr, lo_server_thread_get_server(fServerThread), LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/save", "OK");
  1467. return 0;
  1468. }
  1469. private:
  1470. lo_server_thread fServerThread;
  1471. lo_address fReplyAddr;
  1472. bool fIsOpened;
  1473. bool fIsSaved;
  1474. #define handlePtr ((CarlaNSM*)data)
  1475. static int _reply_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* data)
  1476. {
  1477. return handlePtr->handleReply(path, types, argv, argc, msg);
  1478. }
  1479. static int _open_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* data)
  1480. {
  1481. return handlePtr->handleOpen(path, types, argv, argc, msg);
  1482. }
  1483. static int _save_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* data)
  1484. {
  1485. return handlePtr->handleSave(path, types, argv, argc, msg);
  1486. }
  1487. #undef handlePtr
  1488. static void error_handler(int num, const char* msg, const char* path)
  1489. {
  1490. carla_stderr2("CarlaNSM::error_handler(%i, \"%s\", \"%s\")", num, msg, path);
  1491. }
  1492. };
  1493. static CarlaNSM gCarlaNSM;
  1494. void carla_nsm_announce(const char* url, int pid)
  1495. {
  1496. gCarlaNSM.announce(url, pid);
  1497. }
  1498. void carla_nsm_reply_open()
  1499. {
  1500. gCarlaNSM.replyOpen();
  1501. }
  1502. void carla_nsm_reply_save()
  1503. {
  1504. gCarlaNSM.replySave();
  1505. }
  1506. // -------------------------------------------------------------------------------------------------------------------
  1507. #ifdef BUILD_BRIDGE
  1508. bool carla_engine_init_bridge(const char* audioBaseName, const char* controlBaseName, const char* clientName)
  1509. {
  1510. carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\")", audioBaseName, controlBaseName, clientName);
  1511. CARLA_ASSERT(standalone.engine == nullptr);
  1512. CARLA_ASSERT(audioBaseName != nullptr);
  1513. CARLA_ASSERT(controlBaseName != nullptr);
  1514. CARLA_ASSERT(clientName != nullptr);
  1515. standalone.engine = CarlaEngine::newBridge(audioBaseName, controlBaseName);
  1516. if (standalone.engine == nullptr)
  1517. {
  1518. standalone.lastError = "The seleted audio driver is not available!";
  1519. return false;
  1520. }
  1521. if (standalone.callback != nullptr)
  1522. standalone.engine->setCallback(standalone.callback, nullptr);
  1523. standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_MODE, CarlaBackend::PROCESS_MODE_BRIDGE, nullptr);
  1524. standalone.engine->setOption(CarlaBackend::OPTION_TRANSPORT_MODE, CarlaBackend::TRANSPORT_MODE_BRIDGE, nullptr);
  1525. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES, false, nullptr);
  1526. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_UI_BRIDGES, false, nullptr);
  1527. // TODO - read from environment
  1528. #ifndef BUILD_BRIDGE
  1529. standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo ? 1 : 0, nullptr);
  1530. # ifdef WANT_DSSI
  1531. standalone.engine->setOption(CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS, standalone.options.useDssiVstChunks ? 1 : 0, nullptr);
  1532. # endif
  1533. standalone.engine->setOption(CarlaBackend::OPTION_MAX_PARAMETERS, static_cast<int>(standalone.options.maxParameters), nullptr);
  1534. #endif
  1535. const bool initiated = standalone.engine->init(clientName);
  1536. if (initiated)
  1537. {
  1538. standalone.lastError = "no error";
  1539. standalone.init();
  1540. }
  1541. else
  1542. {
  1543. standalone.lastError = standalone.engine->getLastError();
  1544. delete standalone.engine;
  1545. standalone.engine = nullptr;
  1546. }
  1547. return initiated;
  1548. }
  1549. CarlaEngine* carla_get_standalone_engine()
  1550. {
  1551. return standalone.engine;
  1552. }
  1553. #endif