Collection of tools useful for audio production
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.

1831 lines
58KB

  1. /*
  2. * Carla Backend
  3. * Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * 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 COPYING file
  16. */
  17. #include "carla_backend_standalone.hpp"
  18. #include "carla_plugin.hpp"
  19. #include "carla_native.h"
  20. // -------------------------------------------------------------------------------------------------------------------
  21. // Single, standalone engine
  22. struct CarlaBackendStandalone {
  23. CarlaBackend::CarlaEngineOptions options;
  24. CarlaBackend::CarlaEngine* engine;
  25. CarlaBackend::CallbackFunc callback;
  26. CarlaString lastError;
  27. CarlaString procName;
  28. bool started;
  29. CarlaBackendStandalone()
  30. : engine(nullptr),
  31. callback(nullptr),
  32. started(false) {}
  33. } standalone;
  34. // -------------------------------------------------------------------------------------------------------------------
  35. const char* get_extended_license_text()
  36. {
  37. qDebug("CarlaBackendStandalone::get_extended_license_text()");
  38. static CarlaString extendedLicenseText;
  39. if (extendedLicenseText.isEmpty())
  40. {
  41. QString text("<p>This current Carla build is using the following features and 3rd-party code:</p>");
  42. text += "<ul>";
  43. #ifdef WANT_LADSPA
  44. text += "<li>LADSPA plugin support, http://www.ladspa.org/</li>";
  45. #endif
  46. #ifdef WANT_DSSI
  47. text += "<li>DSSI plugin support, http://dssi.sourceforge.net/</li>";
  48. #endif
  49. #ifdef WANT_LV2
  50. text += "<li>LV2 plugin support, http://lv2plug.in/</li>";
  51. #endif
  52. #ifdef WANT_VST
  53. # ifdef VESTIGE_HEADER
  54. text += "<li>VST plugin support, using VeSTige header by Javier Serrano Polo</li>";
  55. # else
  56. text += "<li>VST plugin support, using official VST SDK 2.4 (trademark of Steinberg Media Technologies GmbH)</li>";
  57. # endif
  58. #endif
  59. #ifdef WANT_FLUIDSYNTH
  60. text += "<li>FluidSynth library for SF2 support, http://www.fluidsynth.org/</li>";
  61. #endif
  62. #ifdef WANT_LINUXSAMPLER
  63. text += "<li>LinuxSampler library for GIG and SFZ support*, http://www.linuxsampler.org/</li>";
  64. #endif
  65. text += "<li>liblo library for OSC support, http://liblo.sourceforge.net/</li>";
  66. #ifdef WANT_LV2
  67. text += "<li>serd, sord, sratom and lilv libraries for LV2 discovery, http://drobilla.net/software/lilv/</li>";
  68. #endif
  69. #ifdef CARLA_ENGINE_RTAUDIO
  70. text += "<li>RtAudio and RtMidi libraries for extra Audio and MIDI support, http://www.music.mcgill.ca/~gary/rtaudio/</li>";
  71. #endif
  72. text += "</ul>";
  73. #ifdef WANT_LINUXSAMPLER
  74. text += "<p>(*) Using LinuxSampler code in commercial hardware or software products is not allowed without prior written authorization by the authors.</p>";
  75. #endif
  76. extendedLicenseText = text.toUtf8().constData();
  77. }
  78. return extendedLicenseText;
  79. }
  80. unsigned int get_engine_driver_count()
  81. {
  82. qDebug("CarlaBackendStandalone::get_engine_driver_count()");
  83. return CarlaBackend::CarlaEngine::getDriverCount();
  84. }
  85. const char* get_engine_driver_name(unsigned int index)
  86. {
  87. qDebug("CarlaBackendStandalone::get_engine_driver_name(%i)", index);
  88. return CarlaBackend::CarlaEngine::getDriverName(index);
  89. }
  90. // -------------------------------------------------------------------------------------------------------------------
  91. unsigned int get_internal_plugin_count()
  92. {
  93. qDebug("CarlaBackendStandalone::get_internal_plugin_count()");
  94. return CarlaBackend::CarlaPlugin::getNativePluginCount();
  95. }
  96. const PluginInfo* get_internal_plugin_info(unsigned int plugin_id)
  97. {
  98. qDebug("CarlaBackendStandalone::get_internal_plugin_info(%i)", plugin_id);
  99. static PluginInfo info;
  100. const PluginDescriptor* const nativePlugin = CarlaBackend::CarlaPlugin::getNativePluginDescriptor(plugin_id);
  101. CARLA_ASSERT(nativePlugin);
  102. // as internal plugin, this must never fail
  103. if (! nativePlugin)
  104. return nullptr;
  105. info.type = CarlaBackend::PLUGIN_INTERNAL;
  106. info.category = static_cast<CarlaBackend::PluginCategory>(nativePlugin->category);
  107. info.hints = 0x0;
  108. info.name = nativePlugin->name;
  109. info.label = nativePlugin->label;
  110. info.maker = nativePlugin->maker;
  111. info.copyright = nativePlugin->copyright;
  112. if (nativePlugin->hints & PLUGIN_IS_SYNTH)
  113. info.hints |= CarlaBackend::PLUGIN_IS_SYNTH;
  114. if (nativePlugin->hints & PLUGIN_HAS_GUI)
  115. info.hints |= CarlaBackend::PLUGIN_HAS_GUI;
  116. if (nativePlugin->hints & PLUGIN_USES_SINGLE_THREAD)
  117. info.hints |= CarlaBackend::PLUGIN_USES_SINGLE_THREAD;
  118. return &info;
  119. }
  120. // -------------------------------------------------------------------------------------------------------------------
  121. bool engine_init(const char* driver_name, const char* client_name)
  122. {
  123. qDebug("CarlaBackendStandalone::engine_init(\"%s\", \"%s\")", driver_name, client_name);
  124. CARLA_ASSERT(! standalone.engine);
  125. standalone.engine = CarlaBackend::CarlaEngine::newDriverByName(driver_name);
  126. if (! standalone.engine)
  127. {
  128. standalone.lastError = "The seleted audio driver is not available!";
  129. return false;
  130. }
  131. #ifndef Q_OS_WIN
  132. // TODO: make this an option, put somewhere else
  133. if (! getenv("WINE_RT"))
  134. {
  135. carla_setenv("WINE_RT", "15");
  136. carla_setenv("WINE_SVR_RT", "10");
  137. }
  138. #endif
  139. standalone.engine->setCallback(standalone.callback, nullptr);
  140. standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_MODE, standalone.options.processMode, nullptr);
  141. standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_HIGH_PRECISION, standalone.options.processHighPrecision, nullptr);
  142. standalone.engine->setOption(CarlaBackend::OPTION_MAX_PARAMETERS, standalone.options.maxParameters, nullptr);
  143. standalone.engine->setOption(CarlaBackend::OPTION_PREFERRED_BUFFER_SIZE, standalone.options.preferredBufferSize, nullptr);
  144. standalone.engine->setOption(CarlaBackend::OPTION_PREFERRED_SAMPLE_RATE, standalone.options.preferredSampleRate, nullptr);
  145. standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo, nullptr);
  146. standalone.engine->setOption(CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS, standalone.options.useDssiVstChunks, nullptr);
  147. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES, standalone.options.preferPluginBridges, nullptr);
  148. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_UI_BRIDGES, standalone.options.preferUiBridges, nullptr);
  149. standalone.engine->setOption(CarlaBackend::OPTION_OSC_UI_TIMEOUT, standalone.options.oscUiTimeout, nullptr);
  150. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_POSIX32, 0, standalone.options.bridge_posix32);
  151. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_POSIX64, 0, standalone.options.bridge_posix64);
  152. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_WIN32, 0, standalone.options.bridge_win32);
  153. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_WIN64, 0, standalone.options.bridge_win64);
  154. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK2, 0, standalone.options.bridge_lv2gtk2);
  155. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK3, 0, standalone.options.bridge_lv2gtk3);
  156. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_QT4, 0, standalone.options.bridge_lv2qt4);
  157. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_X11, 0, standalone.options.bridge_lv2qt4);
  158. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_VST_HWND, 0, standalone.options.bridge_vsthwnd);
  159. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_VST_X11, 0, standalone.options.bridge_vstx11);
  160. if (standalone.procName.isNotEmpty())
  161. standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_NAME, 0, standalone.procName);
  162. standalone.started = standalone.engine->init(client_name);
  163. if (standalone.started)
  164. {
  165. standalone.lastError = "no error";
  166. }
  167. else if (standalone.engine)
  168. {
  169. delete standalone.engine;
  170. standalone.engine = nullptr;
  171. }
  172. return standalone.started;
  173. }
  174. bool engine_close()
  175. {
  176. qDebug("CarlaBackendStandalone::engine_close()");
  177. CARLA_ASSERT(standalone.engine);
  178. if (! standalone.engine)
  179. {
  180. standalone.lastError = "Engine is not started";
  181. return false;
  182. }
  183. standalone.engine->aboutToClose();
  184. standalone.engine->removeAllPlugins();
  185. bool closed = standalone.engine->close();
  186. standalone.started = false;
  187. // cleanup static data
  188. get_plugin_info(0);
  189. get_parameter_info(0, 0);
  190. get_parameter_scalepoint_info(0, 0, 0);
  191. get_chunk_data(0);
  192. get_program_name(0, 0);
  193. get_midi_program_name(0, 0);
  194. get_real_plugin_name(0);
  195. delete standalone.engine;
  196. standalone.engine = nullptr;
  197. return closed;
  198. }
  199. bool is_engine_running()
  200. {
  201. qDebug("CarlaBackendStandalone::is_engine_running()");
  202. return standalone.engine && standalone.engine->isRunning();
  203. }
  204. // -------------------------------------------------------------------------------------------------------------------
  205. short add_plugin(CarlaBackend::BinaryType btype, CarlaBackend::PluginType ptype, const char* filename, const char* const name, const char* label, void* extra_stuff)
  206. {
  207. qDebug("CarlaBackendStandalone::add_plugin(%s, %s, \"%s\", \"%s\", \"%s\", %p)", CarlaBackend::BinaryType2Str(btype), CarlaBackend::PluginType2Str(ptype), filename, name, label, extra_stuff);
  208. CARLA_ASSERT(standalone.engine);
  209. if (standalone.engine && standalone.engine->isRunning())
  210. return standalone.engine->addPlugin(btype, ptype, filename, name, label, extra_stuff);
  211. standalone.lastError = "Engine is not started";
  212. return -1;
  213. }
  214. bool remove_plugin(unsigned short plugin_id)
  215. {
  216. qDebug("CarlaBackendStandalone::remove_plugin(%i)", plugin_id);
  217. CARLA_ASSERT(standalone.engine);
  218. if (standalone.engine)
  219. return standalone.engine->removePlugin(plugin_id);
  220. standalone.lastError = "Engine is not started";
  221. return false;
  222. }
  223. // -------------------------------------------------------------------------------------------------------------------
  224. const PluginInfo* get_plugin_info(unsigned short plugin_id)
  225. {
  226. qDebug("CarlaBackendStandalone::get_plugin_info(%i)", plugin_id);
  227. CARLA_ASSERT(standalone.engine);
  228. static PluginInfo info;
  229. // reset
  230. info.type = CarlaBackend::PLUGIN_NONE;
  231. info.category = CarlaBackend::PLUGIN_CATEGORY_NONE;
  232. info.hints = 0x0;
  233. info.binary = nullptr;
  234. info.name = nullptr;
  235. info.uniqueId = 0;
  236. // cleanup
  237. if (info.label)
  238. {
  239. free((void*)info.label);
  240. info.label = nullptr;
  241. }
  242. if (info.maker)
  243. {
  244. free((void*)info.maker);
  245. info.maker = nullptr;
  246. }
  247. if (info.copyright)
  248. {
  249. free((void*)info.copyright);
  250. info.copyright = nullptr;
  251. }
  252. if (! standalone.engine)
  253. return &info;
  254. if (! standalone.started)
  255. return nullptr;
  256. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  257. if (plugin)
  258. {
  259. char strBufLabel[STR_MAX] = { 0 };
  260. char strBufMaker[STR_MAX] = { 0 };
  261. char strBufCopyright[STR_MAX] = { 0 };
  262. info.type = plugin->type();
  263. info.category = plugin->category();
  264. info.hints = plugin->hints();
  265. info.binary = plugin->filename();
  266. info.name = plugin->name();
  267. info.uniqueId = plugin->uniqueId();
  268. plugin->getLabel(strBufLabel);
  269. info.label = strdup(strBufLabel);
  270. plugin->getMaker(strBufMaker);
  271. info.maker = strdup(strBufMaker);
  272. plugin->getCopyright(strBufCopyright);
  273. info.copyright = strdup(strBufCopyright);
  274. return &info;
  275. }
  276. qCritical("CarlaBackendStandalone::get_plugin_info(%i) - could not find plugin", plugin_id);
  277. return &info;
  278. }
  279. const PortCountInfo* get_audio_port_count_info(unsigned short plugin_id)
  280. {
  281. qDebug("CarlaBackendStandalone::get_audio_port_count_info(%i)", plugin_id);
  282. CARLA_ASSERT(standalone.engine);
  283. static PortCountInfo info;
  284. // reset
  285. info.ins = 0;
  286. info.outs = 0;
  287. info.total = 0;
  288. if (! standalone.engine)
  289. return &info;
  290. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  291. if (plugin)
  292. {
  293. info.ins = plugin->audioInCount();
  294. info.outs = plugin->audioOutCount();
  295. info.total = info.ins + info.outs;
  296. return &info;
  297. }
  298. qCritical("CarlaBackendStandalone::get_audio_port_count_info(%i) - could not find plugin", plugin_id);
  299. return &info;
  300. }
  301. const PortCountInfo* get_midi_port_count_info(unsigned short plugin_id)
  302. {
  303. qDebug("CarlaBackendStandalone::get_midi_port_count_info(%i)", plugin_id);
  304. CARLA_ASSERT(standalone.engine);
  305. static PortCountInfo info;
  306. // reset
  307. info.ins = 0;
  308. info.outs = 0;
  309. info.total = 0;
  310. if (! standalone.engine)
  311. return &info;
  312. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  313. if (plugin)
  314. {
  315. info.ins = plugin->midiInCount();
  316. info.outs = plugin->midiOutCount();
  317. info.total = info.ins + info.outs;
  318. return &info;
  319. }
  320. qCritical("CarlaBackendStandalone::get_midi_port_count_info(%i) - could not find plugin", plugin_id);
  321. return &info;
  322. }
  323. const PortCountInfo* get_parameter_count_info(unsigned short plugin_id)
  324. {
  325. qDebug("CarlaBackendStandalone::get_parameter_count_info(%i)", plugin_id);
  326. CARLA_ASSERT(standalone.engine);
  327. static PortCountInfo info;
  328. // reset
  329. info.ins = 0;
  330. info.outs = 0;
  331. info.total = 0;
  332. if (! standalone.engine)
  333. return &info;
  334. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  335. if (plugin)
  336. {
  337. plugin->getParameterCountInfo(&info.ins, &info.outs, &info.total);
  338. return &info;
  339. }
  340. qCritical("CarlaBackendStandalone::get_parameter_count_info(%i) - could not find plugin", plugin_id);
  341. return &info;
  342. }
  343. const ParameterInfo* get_parameter_info(unsigned short plugin_id, uint32_t parameter_id)
  344. {
  345. qDebug("CarlaBackendStandalone::get_parameter_info(%i, %i)", plugin_id, parameter_id);
  346. CARLA_ASSERT(standalone.engine);
  347. static ParameterInfo info;
  348. // reset
  349. info.scalePointCount = 0;
  350. // cleanup
  351. if (info.name)
  352. {
  353. free((void*)info.name);
  354. info.name = nullptr;
  355. }
  356. if (info.symbol)
  357. {
  358. free((void*)info.symbol);
  359. info.symbol = nullptr;
  360. }
  361. if (info.unit)
  362. {
  363. free((void*)info.unit);
  364. info.unit = nullptr;
  365. }
  366. if (! standalone.engine)
  367. return &info;
  368. if (! standalone.started)
  369. return nullptr;
  370. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  371. if (plugin)
  372. {
  373. if (parameter_id < plugin->parameterCount())
  374. {
  375. char strBufName[STR_MAX] = { 0 };
  376. char strBufSymbol[STR_MAX] = { 0 };
  377. char strBufUnit[STR_MAX] = { 0 };
  378. info.scalePointCount = plugin->parameterScalePointCount(parameter_id);
  379. plugin->getParameterName(parameter_id, strBufName);
  380. info.name = strdup(strBufName);
  381. plugin->getParameterSymbol(parameter_id, strBufSymbol);
  382. info.symbol = strdup(strBufSymbol);
  383. plugin->getParameterUnit(parameter_id, strBufUnit);
  384. info.unit = strdup(strBufUnit);
  385. }
  386. else
  387. qCritical("CarlaBackendStandalone::get_parameter_info(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id);
  388. return &info;
  389. }
  390. qCritical("CarlaBackendStandalone::get_parameter_info(%i, %i) - could not find plugin", plugin_id, parameter_id);
  391. return &info;
  392. }
  393. const ScalePointInfo* get_parameter_scalepoint_info(unsigned short plugin_id, uint32_t parameter_id, uint32_t scalepoint_id)
  394. {
  395. qDebug("CarlaBackendStandalone::get_parameter_scalepoint_info(%i, %i, %i)", plugin_id, parameter_id, scalepoint_id);
  396. CARLA_ASSERT(standalone.engine);
  397. static ScalePointInfo info;
  398. // reset
  399. info.value = 0.0;
  400. // cleanup
  401. if (info.label)
  402. {
  403. free((void*)info.label);
  404. info.label = nullptr;
  405. }
  406. if (! standalone.engine)
  407. return &info;
  408. if (! standalone.started)
  409. return nullptr;
  410. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  411. if (plugin)
  412. {
  413. if (parameter_id < plugin->parameterCount())
  414. {
  415. if (scalepoint_id < plugin->parameterScalePointCount(parameter_id))
  416. {
  417. char strBufLabel[STR_MAX] = { 0 };
  418. info.value = plugin->getParameterScalePointValue(parameter_id, scalepoint_id);
  419. plugin->getParameterScalePointLabel(parameter_id, scalepoint_id, strBufLabel);
  420. info.label = strdup(strBufLabel);
  421. }
  422. else
  423. qCritical("CarlaBackendStandalone::get_parameter_scalepoint_info(%i, %i, %i) - scalepoint_id out of bounds", plugin_id, parameter_id, scalepoint_id);
  424. }
  425. else
  426. qCritical("CarlaBackendStandalone::get_parameter_scalepoint_info(%i, %i, %i) - parameter_id out of bounds", plugin_id, parameter_id, parameter_id);
  427. return &info;
  428. }
  429. qCritical("CarlaBackendStandalone::get_parameter_scalepoint_info(%i, %i, %i) - could not find plugin", plugin_id, parameter_id, scalepoint_id);
  430. return &info;
  431. }
  432. const GuiInfo* get_gui_info(unsigned short plugin_id)
  433. {
  434. qDebug("CarlaBackendStandalone::get_gui_info(%i)", plugin_id);
  435. CARLA_ASSERT(standalone.engine);
  436. static GuiInfo info;
  437. // reset
  438. info.type = CarlaBackend::GUI_NONE;
  439. info.resizable = false;
  440. if (! standalone.engine)
  441. return &info;
  442. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  443. if (plugin)
  444. {
  445. plugin->getGuiInfo(&info.type, &info.resizable);
  446. return &info;
  447. }
  448. qCritical("CarlaBackendStandalone::get_gui_info(%i) - could not find plugin", plugin_id);
  449. return &info;
  450. }
  451. // -------------------------------------------------------------------------------------------------------------------
  452. const CarlaBackend::ParameterData* get_parameter_data(unsigned short plugin_id, uint32_t parameter_id)
  453. {
  454. qDebug("CarlaBackendStandalone::get_parameter_data(%i, %i)", plugin_id, parameter_id);
  455. CARLA_ASSERT(standalone.engine);
  456. static CarlaBackend::ParameterData data;
  457. if (! standalone.engine)
  458. return &data;
  459. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  460. if (plugin)
  461. {
  462. if (parameter_id < plugin->parameterCount())
  463. return plugin->parameterData(parameter_id);
  464. qCritical("CarlaBackendStandalone::get_parameter_data(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id);
  465. return &data;
  466. }
  467. qCritical("CarlaBackendStandalone::get_parameter_data(%i, %i) - could not find plugin", plugin_id, parameter_id);
  468. return &data;
  469. }
  470. const CarlaBackend::ParameterRanges* get_parameter_ranges(unsigned short plugin_id, uint32_t parameter_id)
  471. {
  472. qDebug("CarlaBackendStandalone::get_parameter_ranges(%i, %i)", plugin_id, parameter_id);
  473. CARLA_ASSERT(standalone.engine);
  474. static CarlaBackend::ParameterRanges ranges;
  475. if (! standalone.engine)
  476. return &ranges;
  477. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  478. if (plugin)
  479. {
  480. if (parameter_id < plugin->parameterCount())
  481. return plugin->parameterRanges(parameter_id);
  482. qCritical("CarlaBackendStandalone::get_parameter_ranges(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id);
  483. return &ranges;
  484. }
  485. qCritical("CarlaBackendStandalone::get_parameter_ranges(%i, %i) - could not find plugin", plugin_id, parameter_id);
  486. return &ranges;
  487. }
  488. const CarlaBackend::MidiProgramData* get_midi_program_data(unsigned short plugin_id, uint32_t midi_program_id)
  489. {
  490. qDebug("CarlaBackendStandalone::get_midi_program_data(%i, %i)", plugin_id, midi_program_id);
  491. CARLA_ASSERT(standalone.engine);
  492. static CarlaBackend::MidiProgramData data;
  493. if (! standalone.engine)
  494. return &data;
  495. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  496. if (plugin)
  497. {
  498. if (midi_program_id < plugin->midiProgramCount())
  499. return plugin->midiProgramData(midi_program_id);
  500. qCritical("CarlaBackendStandalone::get_midi_program_data(%i, %i) - midi_program_id out of bounds", plugin_id, midi_program_id);
  501. return &data;
  502. }
  503. qCritical("CarlaBackendStandalone::get_midi_program_data(%i, %i) - could not find plugin", plugin_id, midi_program_id);
  504. return &data;
  505. }
  506. const CarlaBackend::CustomData* get_custom_data(unsigned short plugin_id, uint32_t custom_data_id)
  507. {
  508. qDebug("CarlaBackendStandalone::get_custom_data(%i, %i)", plugin_id, custom_data_id);
  509. CARLA_ASSERT(standalone.engine);
  510. static CarlaBackend::CustomData data;
  511. if (! standalone.engine)
  512. return &data;
  513. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  514. if (plugin)
  515. {
  516. if (custom_data_id < plugin->customDataCount())
  517. return plugin->customData(custom_data_id);
  518. qCritical("CarlaBackendStandalone::get_custom_data(%i, %i) - custom_data_id out of bounds", plugin_id, custom_data_id);
  519. return &data;
  520. }
  521. qCritical("CarlaBackendStandalone::get_custom_data(%i, %i) - could not find plugin", plugin_id, custom_data_id);
  522. return &data;
  523. }
  524. const char* get_chunk_data(unsigned short plugin_id)
  525. {
  526. qDebug("CarlaBackendStandalone::get_chunk_data(%i)", plugin_id);
  527. CARLA_ASSERT(standalone.engine);
  528. static const char* chunk_data = nullptr;
  529. // cleanup
  530. if (chunk_data)
  531. {
  532. free((void*)chunk_data);
  533. chunk_data = nullptr;
  534. }
  535. if (! standalone.engine)
  536. return nullptr;
  537. if (! standalone.started)
  538. return nullptr;
  539. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  540. if (plugin)
  541. {
  542. if (plugin->hints() & CarlaBackend::PLUGIN_USES_CHUNKS)
  543. {
  544. void* data = nullptr;
  545. const int32_t dataSize = plugin->chunkData(&data);
  546. if (data && dataSize >= 4)
  547. {
  548. const QByteArray chunk((const char*)data, dataSize);
  549. chunk_data = strdup(chunk.toBase64().constData());
  550. }
  551. else
  552. qCritical("CarlaBackendStandalone::get_chunk_data(%i) - got invalid chunk data", plugin_id);
  553. }
  554. else
  555. qCritical("CarlaBackendStandalone::get_chunk_data(%i) - plugin does not support chunks", plugin_id);
  556. return chunk_data;
  557. }
  558. qCritical("CarlaBackendStandalone::get_chunk_data(%i) - could not find plugin", plugin_id);
  559. return nullptr;
  560. }
  561. // -------------------------------------------------------------------------------------------------------------------
  562. uint32_t get_parameter_count(unsigned short plugin_id)
  563. {
  564. qDebug("CarlaBackendStandalone::get_parameter_count(%i)", plugin_id);
  565. CARLA_ASSERT(standalone.engine);
  566. if (! standalone.engine)
  567. return 0;
  568. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  569. if (plugin)
  570. return plugin->parameterCount();
  571. qCritical("CarlaBackendStandalone::get_parameter_count(%i) - could not find plugin", plugin_id);
  572. return 0;
  573. }
  574. uint32_t get_program_count(unsigned short plugin_id)
  575. {
  576. qDebug("CarlaBackendStandalone::get_program_count(%i)", plugin_id);
  577. CARLA_ASSERT(standalone.engine);
  578. if (! standalone.engine)
  579. return 0;
  580. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  581. if (plugin)
  582. return plugin->programCount();
  583. qCritical("CarlaBackendStandalone::get_program_count(%i) - could not find plugin", plugin_id);
  584. return 0;
  585. }
  586. uint32_t get_midi_program_count(unsigned short plugin_id)
  587. {
  588. qDebug("CarlaBackendStandalone::get_midi_program_count(%i)", plugin_id);
  589. CARLA_ASSERT(standalone.engine);
  590. if (! standalone.engine)
  591. return 0;
  592. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  593. if (plugin)
  594. return plugin->midiProgramCount();
  595. qCritical("CarlaBackendStandalone::get_midi_program_count(%i) - could not find plugin", plugin_id);
  596. return 0;
  597. }
  598. uint32_t get_custom_data_count(unsigned short plugin_id)
  599. {
  600. qDebug("CarlaBackendStandalone::get_custom_data_count(%i)", plugin_id);
  601. CARLA_ASSERT(standalone.engine);
  602. if (! standalone.engine)
  603. return 0;
  604. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  605. if (plugin)
  606. return plugin->customDataCount();
  607. qCritical("CarlaBackendStandalone::get_custom_data_count(%i) - could not find plugin", plugin_id);
  608. return 0;
  609. }
  610. // -------------------------------------------------------------------------------------------------------------------
  611. const char* get_parameter_text(unsigned short plugin_id, uint32_t parameter_id)
  612. {
  613. qDebug("CarlaBackendStandalone::get_parameter_text(%i, %i)", plugin_id, parameter_id);
  614. CARLA_ASSERT(standalone.engine);
  615. static char textBuf[STR_MAX];
  616. memset(textBuf, 0, sizeof(char)*STR_MAX);
  617. if (! standalone.engine)
  618. return nullptr;
  619. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  620. if (plugin)
  621. {
  622. if (parameter_id < plugin->parameterCount())
  623. {
  624. plugin->getParameterText(parameter_id, textBuf);
  625. return textBuf;
  626. }
  627. qCritical("CarlaBackendStandalone::get_parameter_text(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id);
  628. return nullptr;
  629. }
  630. qCritical("CarlaBackendStandalone::get_parameter_text(%i, %i) - could not find plugin", plugin_id, parameter_id);
  631. return nullptr;
  632. }
  633. const char* get_program_name(unsigned short plugin_id, uint32_t program_id)
  634. {
  635. qDebug("CarlaBackendStandalone::get_program_name(%i, %i)", plugin_id, program_id);
  636. CARLA_ASSERT(standalone.engine);
  637. static const char* program_name = nullptr;
  638. // cleanup
  639. if (program_name)
  640. {
  641. free((void*)program_name);
  642. program_name = nullptr;
  643. }
  644. if (! standalone.engine)
  645. return nullptr;
  646. if (! standalone.started)
  647. return nullptr;
  648. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  649. if (plugin)
  650. {
  651. if (program_id < plugin->programCount())
  652. {
  653. char strBuf[STR_MAX] = { 0 };
  654. plugin->getProgramName(program_id, strBuf);
  655. program_name = strdup(strBuf);
  656. return program_name;
  657. }
  658. qCritical("CarlaBackendStandalone::get_program_name(%i, %i) - program_id out of bounds", plugin_id, program_id);
  659. return nullptr;
  660. }
  661. qCritical("CarlaBackendStandalone::get_program_name(%i, %i) - could not find plugin", plugin_id, program_id);
  662. return nullptr;
  663. }
  664. const char* get_midi_program_name(unsigned short plugin_id, uint32_t midi_program_id)
  665. {
  666. qDebug("CarlaBackendStandalone::get_midi_program_name(%i, %i)", plugin_id, midi_program_id);
  667. CARLA_ASSERT(standalone.engine);
  668. static const char* midi_program_name = nullptr;
  669. // cleanup
  670. if (midi_program_name)
  671. {
  672. free((void*)midi_program_name);
  673. midi_program_name = nullptr;
  674. }
  675. if (! standalone.engine)
  676. return nullptr;
  677. if (! standalone.started)
  678. return nullptr;
  679. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  680. if (plugin)
  681. {
  682. if (midi_program_id < plugin->midiProgramCount())
  683. {
  684. char strBuf[STR_MAX] = { 0 };
  685. plugin->getMidiProgramName(midi_program_id, strBuf);
  686. midi_program_name = strdup(strBuf);
  687. return midi_program_name;
  688. }
  689. qCritical("CarlaBackendStandalone::get_midi_program_name(%i, %i) - program_id out of bounds", plugin_id, midi_program_id);
  690. return nullptr;
  691. }
  692. qCritical("CarlaBackendStandalone::get_midi_program_name(%i, %i) - could not find plugin", plugin_id, midi_program_id);
  693. return nullptr;
  694. }
  695. const char* get_real_plugin_name(unsigned short plugin_id)
  696. {
  697. qDebug("CarlaBackendStandalone::get_real_plugin_name(%i)", plugin_id);
  698. CARLA_ASSERT(standalone.engine);
  699. static const char* real_plugin_name = nullptr;
  700. // cleanup
  701. if (real_plugin_name)
  702. {
  703. free((void*)real_plugin_name);
  704. real_plugin_name = nullptr;
  705. }
  706. if (! standalone.engine)
  707. return nullptr;
  708. if (! standalone.started)
  709. return nullptr;
  710. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  711. if (plugin)
  712. {
  713. char strBuf[STR_MAX] = { 0 };
  714. plugin->getRealName(strBuf);
  715. real_plugin_name = strdup(strBuf);
  716. return real_plugin_name;
  717. }
  718. qCritical("CarlaBackendStandalone::get_real_plugin_name(%i) - could not find plugin", plugin_id);
  719. return nullptr;
  720. }
  721. // -------------------------------------------------------------------------------------------------------------------
  722. int32_t get_current_program_index(unsigned short plugin_id)
  723. {
  724. qDebug("CarlaBackendStandalone::get_current_program_index(%i)", plugin_id);
  725. CARLA_ASSERT(standalone.engine);
  726. if (! standalone.engine)
  727. return -1;
  728. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  729. if (plugin)
  730. return plugin->currentProgram();
  731. qCritical("CarlaBackendStandalone::get_current_program_index(%i) - could not find plugin", plugin_id);
  732. return -1;
  733. }
  734. int32_t get_current_midi_program_index(unsigned short plugin_id)
  735. {
  736. qDebug("CarlaBackendStandalone::get_current_midi_program_index(%i)", plugin_id);
  737. CARLA_ASSERT(standalone.engine);
  738. if (! standalone.engine)
  739. return -1;
  740. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  741. if (plugin)
  742. return plugin->currentMidiProgram();
  743. qCritical("CarlaBackendStandalone::get_current_midi_program_index(%i) - could not find plugin", plugin_id);
  744. return -1;
  745. }
  746. // -------------------------------------------------------------------------------------------------------------------
  747. double get_default_parameter_value(unsigned short plugin_id, uint32_t parameter_id)
  748. {
  749. qDebug("CarlaBackendStandalone::get_default_parameter_value(%i, %i)", plugin_id, parameter_id);
  750. CARLA_ASSERT(standalone.engine);
  751. if (! standalone.engine)
  752. return 0.0;
  753. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  754. if (plugin)
  755. {
  756. if (parameter_id < plugin->parameterCount())
  757. return plugin->parameterRanges(parameter_id)->def;
  758. qCritical("CarlaBackendStandalone::get_default_parameter_value(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id);
  759. return 0.0;
  760. }
  761. qCritical("CarlaBackendStandalone::get_default_parameter_value(%i, %i) - could not find plugin", plugin_id, parameter_id);
  762. return 0.0;
  763. }
  764. double get_current_parameter_value(unsigned short plugin_id, uint32_t parameter_id)
  765. {
  766. qDebug("CarlaBackendStandalone::get_current_parameter_value(%i, %i)", plugin_id, parameter_id);
  767. CARLA_ASSERT(standalone.engine);
  768. if (! standalone.engine)
  769. return 0.0;
  770. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  771. if (plugin)
  772. {
  773. if (parameter_id < plugin->parameterCount())
  774. return plugin->getParameterValue(parameter_id);
  775. qCritical("CarlaBackendStandalone::get_current_parameter_value(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id);
  776. return 0.0;
  777. }
  778. qCritical("CarlaBackendStandalone::get_current_parameter_value(%i, %i) - could not find plugin", plugin_id, parameter_id);
  779. return 0.0;
  780. }
  781. // -------------------------------------------------------------------------------------------------------------------
  782. double get_input_peak_value(unsigned short plugin_id, unsigned short port_id)
  783. {
  784. CARLA_ASSERT(standalone.engine);
  785. CARLA_ASSERT(port_id == 1 || port_id == 2);
  786. if (! standalone.engine)
  787. return 0.0;
  788. #if 0
  789. if (plugin_id >= standalone.engine->maxPluginNumber())
  790. {
  791. qCritical("CarlaBackendStandalone::get_input_peak_value(%i, %i) - invalid plugin value", plugin_id, port_id);
  792. return 0.0;
  793. }
  794. #endif
  795. if (port_id == 1 || port_id == 2)
  796. return standalone.engine->getInputPeak(plugin_id, port_id-1);
  797. qCritical("CarlaBackendStandalone::get_input_peak_value(%i, %i) - invalid port value", plugin_id, port_id);
  798. return 0.0;
  799. }
  800. double get_output_peak_value(unsigned short plugin_id, unsigned short port_id)
  801. {
  802. CARLA_ASSERT(standalone.engine);
  803. CARLA_ASSERT(port_id == 1 || port_id == 2);
  804. if (! standalone.engine)
  805. return 0.0;
  806. #if 0
  807. if (plugin_id >= standalone.engine->maxPluginNumber())
  808. {
  809. qCritical("CarlaBackendStandalone::get_input_peak_value(%i, %i) - invalid plugin value", plugin_id, port_id);
  810. return 0.0;
  811. }
  812. #endif
  813. if (port_id == 1 || port_id == 2)
  814. return standalone.engine->getOutputPeak(plugin_id, port_id-1);
  815. qCritical("CarlaBackendStandalone::get_output_peak_value(%i, %i) - invalid port value", plugin_id, port_id);
  816. return 0.0;
  817. }
  818. // -------------------------------------------------------------------------------------------------------------------
  819. void set_active(unsigned short plugin_id, bool onoff)
  820. {
  821. qDebug("CarlaBackendStandalone::set_active(%i, %s)", plugin_id, bool2str(onoff));
  822. CARLA_ASSERT(standalone.engine);
  823. if (! standalone.engine)
  824. return;
  825. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  826. if (plugin)
  827. return plugin->setActive(onoff, true, false);
  828. qCritical("CarlaBackendStandalone::set_active(%i, %s) - could not find plugin", plugin_id, bool2str(onoff));
  829. }
  830. void set_drywet(unsigned short plugin_id, double value)
  831. {
  832. qDebug("CarlaBackendStandalone::set_drywet(%i, %g)", plugin_id, value);
  833. CARLA_ASSERT(standalone.engine);
  834. if (! standalone.engine)
  835. return;
  836. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  837. if (plugin)
  838. return plugin->setDryWet(value, true, false);
  839. qCritical("CarlaBackendStandalone::set_drywet(%i, %g) - could not find plugin", plugin_id, value);
  840. }
  841. void set_volume(unsigned short plugin_id, double value)
  842. {
  843. qDebug("CarlaBackendStandalone::set_volume(%i, %g)", plugin_id, value);
  844. CARLA_ASSERT(standalone.engine);
  845. if (! standalone.engine)
  846. return;
  847. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  848. if (plugin)
  849. return plugin->setVolume(value, true, false);
  850. qCritical("CarlaBackendStandalone::set_volume(%i, %g) - could not find plugin", plugin_id, value);
  851. }
  852. void set_balance_left(unsigned short plugin_id, double value)
  853. {
  854. qDebug("CarlaBackendStandalone::set_balance_left(%i, %g)", plugin_id, value);
  855. CARLA_ASSERT(standalone.engine);
  856. if (! standalone.engine)
  857. return;
  858. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  859. if (plugin)
  860. return plugin->setBalanceLeft(value, true, false);
  861. qCritical("CarlaBackendStandalone::set_balance_left(%i, %g) - could not find plugin", plugin_id, value);
  862. }
  863. void set_balance_right(unsigned short plugin_id, double value)
  864. {
  865. qDebug("CarlaBackendStandalone::set_balance_right(%i, %g)", plugin_id, value);
  866. CARLA_ASSERT(standalone.engine);
  867. if (! standalone.engine)
  868. return;
  869. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  870. if (plugin)
  871. return plugin->setBalanceRight(value, true, false);
  872. qCritical("CarlaBackendStandalone::set_balance_right(%i, %g) - could not find plugin", plugin_id, value);
  873. }
  874. // -------------------------------------------------------------------------------------------------------------------
  875. void set_parameter_value(unsigned short plugin_id, uint32_t parameter_id, double value)
  876. {
  877. qDebug("CarlaBackendStandalone::set_parameter_value(%i, %i, %g)", plugin_id, parameter_id, value);
  878. CARLA_ASSERT(standalone.engine);
  879. if (! standalone.engine)
  880. return;
  881. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  882. if (plugin)
  883. {
  884. if (parameter_id < plugin->parameterCount())
  885. return plugin->setParameterValue(parameter_id, value, true, true, false);
  886. qCritical("CarlaBackendStandalone::set_parameter_value(%i, %i, %g) - parameter_id out of bounds", plugin_id, parameter_id, value);
  887. return;
  888. }
  889. qCritical("CarlaBackendStandalone::set_parameter_value(%i, %i, %g) - could not find plugin", plugin_id, parameter_id, value);
  890. }
  891. void set_parameter_midi_channel(unsigned short plugin_id, uint32_t parameter_id, uint8_t channel)
  892. {
  893. qDebug("CarlaBackendStandalone::set_parameter_midi_channel(%i, %i, %i)", plugin_id, parameter_id, channel);
  894. CARLA_ASSERT(standalone.engine);
  895. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  896. if (channel >= MAX_MIDI_CHANNELS)
  897. {
  898. qCritical("CarlaBackendStandalone::set_parameter_midi_channel(%i, %i, %i) - invalid channel number", plugin_id, parameter_id, channel);
  899. return;
  900. }
  901. if (! standalone.engine)
  902. return;
  903. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  904. if (plugin)
  905. {
  906. if (parameter_id < plugin->parameterCount())
  907. return plugin->setParameterMidiChannel(parameter_id, channel, true, false);
  908. qCritical("CarlaBackendStandalone::set_parameter_midi_channel(%i, %i, %i) - parameter_id out of bounds", plugin_id, parameter_id, channel);
  909. return;
  910. }
  911. qCritical("CarlaBackendStandalone::set_parameter_midi_channel(%i, %i, %i) - could not find plugin", plugin_id, parameter_id, channel);
  912. }
  913. void set_parameter_midi_cc(unsigned short plugin_id, uint32_t parameter_id, int16_t cc)
  914. {
  915. qDebug("CarlaBackendStandalone::set_parameter_midi_cc(%i, %i, %i)", plugin_id, parameter_id, cc);
  916. CARLA_ASSERT(standalone.engine);
  917. CARLA_ASSERT(cc >= -1 && cc <= 0x5F);
  918. if (cc < -1)
  919. {
  920. cc = -1;
  921. }
  922. else if (cc > 0x5F) // 95
  923. {
  924. qCritical("CarlaBackendStandalone::set_parameter_midi_cc(%i, %i, %i) - invalid cc number", plugin_id, parameter_id, cc);
  925. return;
  926. }
  927. if (! standalone.engine)
  928. return;
  929. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  930. if (plugin)
  931. {
  932. if (parameter_id < plugin->parameterCount())
  933. return plugin->setParameterMidiCC(parameter_id, cc, true, false);
  934. qCritical("CarlaBackendStandalone::set_parameter_midi_cc(%i, %i, %i) - parameter_id out of bounds", plugin_id, parameter_id, cc);
  935. return;
  936. }
  937. qCritical("CarlaBackendStandalone::set_parameter_midi_cc(%i, %i, %i) - could not find plugin", plugin_id, parameter_id, cc);
  938. }
  939. void set_program(unsigned short plugin_id, uint32_t program_id)
  940. {
  941. qDebug("CarlaBackendStandalone::set_program(%i, %i)", plugin_id, program_id);
  942. CARLA_ASSERT(standalone.engine);
  943. if (! standalone.engine)
  944. return;
  945. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  946. if (plugin)
  947. {
  948. if (program_id < plugin->programCount())
  949. return plugin->setProgram(program_id, true, true, false, true);
  950. qCritical("CarlaBackendStandalone::set_program(%i, %i) - program_id out of bounds", plugin_id, program_id);
  951. return;
  952. }
  953. qCritical("CarlaBackendStandalone::set_program(%i, %i) - could not find plugin", plugin_id, program_id);
  954. }
  955. void set_midi_program(unsigned short plugin_id, uint32_t midi_program_id)
  956. {
  957. qDebug("CarlaBackendStandalone::set_midi_program(%i, %i)", plugin_id, midi_program_id);
  958. CARLA_ASSERT(standalone.engine);
  959. if (! standalone.engine)
  960. return;
  961. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  962. if (plugin)
  963. {
  964. if (midi_program_id < plugin->midiProgramCount())
  965. return plugin->setMidiProgram(midi_program_id, true, true, false, true);
  966. qCritical("CarlaBackendStandalone::set_midi_program(%i, %i) - midi_program_id out of bounds", plugin_id, midi_program_id);
  967. return;
  968. }
  969. qCritical("CarlaBackendStandalone::set_midi_program(%i, %i) - could not find plugin", plugin_id, midi_program_id);
  970. }
  971. // -------------------------------------------------------------------------------------------------------------------
  972. void set_custom_data(unsigned short plugin_id, CarlaBackend::CustomDataType type, const char* key, const char* value)
  973. {
  974. qDebug("CarlaBackendStandalone::set_custom_data(%i, %i, \"%s\", \"%s\")", plugin_id, type, key, value);
  975. CARLA_ASSERT(standalone.engine);
  976. if (! standalone.engine)
  977. return;
  978. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  979. if (plugin)
  980. return plugin->setCustomData(type, key, value, true);
  981. qCritical("CarlaBackendStandalone::set_custom_data(%i, %i, \"%s\", \"%s\") - could not find plugin", plugin_id, type, key, value);
  982. }
  983. void set_chunk_data(unsigned short plugin_id, const char* chunk_data)
  984. {
  985. qDebug("CarlaBackendStandalone::set_chunk_data(%i, \"%s\")", plugin_id, chunk_data);
  986. CARLA_ASSERT(standalone.engine);
  987. if (! standalone.engine)
  988. return;
  989. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  990. if (plugin)
  991. {
  992. if (plugin->hints() & CarlaBackend::PLUGIN_USES_CHUNKS)
  993. return plugin->setChunkData(chunk_data);
  994. qCritical("CarlaBackendStandalone::set_chunk_data(%i, \"%s\") - plugin does not support chunks", plugin_id, chunk_data);
  995. return;
  996. }
  997. qCritical("CarlaBackendStandalone::set_chunk_data(%i, \"%s\") - could not find plugin", plugin_id, chunk_data);
  998. }
  999. void set_gui_container(unsigned short plugin_id, uintptr_t gui_addr)
  1000. {
  1001. qDebug("CarlaBackendStandalone::set_gui_container(%i, " P_UINTPTR ")", plugin_id, gui_addr);
  1002. CARLA_ASSERT(standalone.engine);
  1003. if (! standalone.engine)
  1004. return;
  1005. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  1006. if (plugin)
  1007. return plugin->setGuiContainer((GuiContainer*)CarlaBackend::getPointerFromAddress(gui_addr));
  1008. qCritical("CarlaBackendStandalone::set_gui_container(%i, " P_UINTPTR ") - could not find plugin", plugin_id, gui_addr);
  1009. }
  1010. // -------------------------------------------------------------------------------------------------------------------
  1011. void show_gui(unsigned short plugin_id, bool yesno)
  1012. {
  1013. qDebug("CarlaBackendStandalone::show_gui(%i, %s)", plugin_id, bool2str(yesno));
  1014. CARLA_ASSERT(standalone.engine);
  1015. if (! standalone.engine)
  1016. return;
  1017. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  1018. if (plugin)
  1019. return plugin->showGui(yesno);
  1020. qCritical("CarlaBackendStandalone::show_gui(%i, %s) - could not find plugin", plugin_id, bool2str(yesno));
  1021. }
  1022. void idle_guis()
  1023. {
  1024. CARLA_ASSERT(standalone.engine);
  1025. if (standalone.engine)
  1026. standalone.engine->idlePluginGuis();
  1027. }
  1028. // -------------------------------------------------------------------------------------------------------------------
  1029. void send_midi_note(unsigned short plugin_id, uint8_t channel, uint8_t note, uint8_t velocity)
  1030. {
  1031. qDebug("CarlaBackendStandalone::send_midi_note(%i, %i, %i, %i)", plugin_id, channel, note, velocity);
  1032. CARLA_ASSERT(standalone.engine);
  1033. if (! (standalone.engine && standalone.engine->isRunning()))
  1034. return;
  1035. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  1036. if (plugin)
  1037. return plugin->sendMidiSingleNote(channel, note, velocity, true, true, false);
  1038. qCritical("CarlaBackendStandalone::send_midi_note(%i, %i, %i, %i) - could not find plugin", plugin_id, channel, note, velocity);
  1039. }
  1040. void prepare_for_save(unsigned short plugin_id)
  1041. {
  1042. qDebug("CarlaBackendStandalone::prepare_for_save(%i)", plugin_id);
  1043. CARLA_ASSERT(standalone.engine);
  1044. if (! standalone.engine)
  1045. return;
  1046. CarlaBackend::CarlaPlugin* const plugin = standalone.engine->getPlugin(plugin_id);
  1047. if (plugin)
  1048. return plugin->prepareForSave();
  1049. qCritical("CarlaBackendStandalone::prepare_for_save(%i) - could not find plugin", plugin_id);
  1050. }
  1051. // -------------------------------------------------------------------------------------------------------------------
  1052. uint32_t get_buffer_size()
  1053. {
  1054. qDebug("CarlaBackendStandalone::get_buffer_size()");
  1055. CARLA_ASSERT(standalone.engine);
  1056. if (! standalone.engine)
  1057. return 0;
  1058. return standalone.engine->getBufferSize();
  1059. }
  1060. double get_sample_rate()
  1061. {
  1062. qDebug("CarlaBackendStandalone::get_sample_rate()");
  1063. CARLA_ASSERT(standalone.engine);
  1064. if (! standalone.engine)
  1065. return 0.0;
  1066. return standalone.engine->getSampleRate();
  1067. }
  1068. // -------------------------------------------------------------------------------------------------------------------
  1069. const char* get_last_error()
  1070. {
  1071. qDebug("CarlaBackendStandalone::get_last_error()");
  1072. if (standalone.engine)
  1073. return standalone.engine->getLastError();
  1074. return standalone.lastError;
  1075. }
  1076. const char* get_host_osc_url()
  1077. {
  1078. qDebug("CarlaBackendStandalone::get_host_osc_url()");
  1079. CARLA_ASSERT(standalone.engine);
  1080. if (! standalone.engine)
  1081. return nullptr;
  1082. return standalone.engine->getOscServerPathTCP();
  1083. }
  1084. // -------------------------------------------------------------------------------------------------------------------
  1085. void set_callback_function(CarlaBackend::CallbackFunc func)
  1086. {
  1087. qDebug("CarlaBackendStandalone::set_callback_function(%p)", func);
  1088. standalone.callback = func;
  1089. if (standalone.engine)
  1090. standalone.engine->setCallback(func, nullptr);
  1091. }
  1092. void set_option(CarlaBackend::OptionsType option, int value, const char* value_str)
  1093. {
  1094. qDebug("CarlaBackendStandalone::set_option(%s, %i, \"%s\")", CarlaBackend::OptionsType2Str(option), value, value_str);
  1095. // TODO
  1096. if (standalone.engine)
  1097. standalone.engine->setOption(option, value, value_str);
  1098. }
  1099. // -------------------------------------------------------------------------------------------------------------------
  1100. #define NSM_API_VERSION_MAJOR 1
  1101. #define NSM_API_VERSION_MINOR 0
  1102. class CarlaNSM
  1103. {
  1104. public:
  1105. CarlaNSM()
  1106. {
  1107. m_controlAddr = nullptr;
  1108. m_serverThread = nullptr;
  1109. m_isOpened = false;
  1110. m_isSaved = false;
  1111. }
  1112. ~CarlaNSM()
  1113. {
  1114. if (m_controlAddr)
  1115. lo_address_free(m_controlAddr);
  1116. if (m_serverThread)
  1117. {
  1118. lo_server_thread_stop(m_serverThread);
  1119. lo_server_thread_del_method(m_serverThread, "/reply", "ssss");
  1120. lo_server_thread_del_method(m_serverThread, "/nsm/client/open", "sss");
  1121. lo_server_thread_del_method(m_serverThread, "/nsm/client/save", "");
  1122. lo_server_thread_free(m_serverThread);
  1123. }
  1124. }
  1125. void announce(const char* const url, const int pid)
  1126. {
  1127. lo_address addr = lo_address_new_from_url(url);
  1128. int proto = lo_address_get_protocol(addr);
  1129. if (! m_serverThread)
  1130. {
  1131. // create new OSC thread
  1132. m_serverThread = lo_server_thread_new_with_proto(nullptr, proto, error_handler);
  1133. // register message handlers and start OSC thread
  1134. lo_server_thread_add_method(m_serverThread, "/reply", "ssss", _reply_handler, this);
  1135. lo_server_thread_add_method(m_serverThread, "/nsm/client/open", "sss", _nsm_open_handler, this);
  1136. lo_server_thread_add_method(m_serverThread, "/nsm/client/save", "", _nsm_save_handler, this);
  1137. lo_server_thread_start(m_serverThread);
  1138. }
  1139. lo_send_from(addr, lo_server_thread_get_server(m_serverThread), LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii",
  1140. "Carla", ":switch:", "carla", NSM_API_VERSION_MAJOR, NSM_API_VERSION_MINOR, pid);
  1141. lo_address_free(addr);
  1142. }
  1143. void replyOpen()
  1144. {
  1145. m_isOpened = true;
  1146. }
  1147. void replySave()
  1148. {
  1149. m_isSaved = true;
  1150. }
  1151. protected:
  1152. int reply_handler(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg)
  1153. {
  1154. qDebug("CarlaNSM::reply_handler(%s, %i, %p, %s, %p)", path, argc, argv, types, msg);
  1155. m_controlAddr = lo_address_new_from_url(lo_address_get_url(lo_message_get_source(msg)));
  1156. const char* const method = &argv[0]->s;
  1157. if (strcmp(method, "/nsm/server/announce") == 0 && standalone.callback)
  1158. standalone.callback(nullptr, CarlaBackend::CALLBACK_NSM_ANNOUNCE, 0, 0, 0, 0.0);
  1159. return 0;
  1160. }
  1161. int nsm_open_handler(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg)
  1162. {
  1163. qDebug("CarlaNSM::nsm_open_handler(\"%s\", \"%s\", %p, %i, %p)", path, types, argv, argc, msg);
  1164. if (! standalone.callback)
  1165. return 1;
  1166. const char* const projectPath = &argv[0]->s;
  1167. const char* const clientId = &argv[2]->s;
  1168. standalone.lastError = clientId;
  1169. standalone.callback(nullptr, CarlaBackend::CALLBACK_NSM_OPEN1, 0, 0, 0, 0.0);
  1170. standalone.lastError = projectPath;
  1171. standalone.callback(nullptr, CarlaBackend::CALLBACK_NSM_OPEN2, 0, 0, 0, 0.0);
  1172. for (int i=0; i < 30 && ! m_isOpened; i++)
  1173. carla_msleep(100);
  1174. if (m_controlAddr)
  1175. lo_send_from(m_controlAddr, lo_server_thread_get_server(m_serverThread), LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/open", "OK");
  1176. return 0;
  1177. }
  1178. int nsm_save_handler(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg)
  1179. {
  1180. qDebug("CarlaNSM::nsm_save_handler(\"%s\", \"%s\", %p, %i, %p)", path, types, argv, argc, msg);
  1181. if (! standalone.callback)
  1182. return 1;
  1183. standalone.callback(nullptr, CarlaBackend::CALLBACK_NSM_SAVE, 0, 0, 0, 0.0);
  1184. for (int i=0; i < 30 && ! m_isSaved; i++)
  1185. carla_msleep(100);
  1186. if (m_controlAddr)
  1187. lo_send_from(m_controlAddr, lo_server_thread_get_server(m_serverThread), LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/save", "OK");
  1188. return 0;
  1189. }
  1190. private:
  1191. lo_address m_controlAddr;
  1192. lo_server_thread m_serverThread;
  1193. bool m_isOpened, m_isSaved;
  1194. static int _reply_handler(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg, void* const data)
  1195. {
  1196. CARLA_ASSERT(data);
  1197. CarlaNSM* const _this_ = (CarlaNSM*)data;
  1198. return _this_->reply_handler(path, types, argv, argc, msg);
  1199. }
  1200. static int _nsm_open_handler(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg, void* const data)
  1201. {
  1202. CARLA_ASSERT(data);
  1203. CarlaNSM* const _this_ = (CarlaNSM*)data;
  1204. return _this_->nsm_open_handler(path, types, argv, argc, msg);
  1205. }
  1206. static int _nsm_save_handler(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg, void* const data)
  1207. {
  1208. CARLA_ASSERT(data);
  1209. CarlaNSM* const _this_ = (CarlaNSM*)data;
  1210. return _this_->nsm_save_handler(path, types, argv, argc, msg);
  1211. }
  1212. static void error_handler(const int num, const char* const msg, const char* const path)
  1213. {
  1214. qCritical("CarlaNSM::error_handler(%i, \"%s\", \"%s\")", num, msg, path);
  1215. }
  1216. };
  1217. static CarlaNSM carlaNSM;
  1218. void nsm_announce(const char* url, int pid)
  1219. {
  1220. carlaNSM.announce(url, pid);
  1221. }
  1222. void nsm_reply_open()
  1223. {
  1224. carlaNSM.replyOpen();
  1225. }
  1226. void nsm_reply_save()
  1227. {
  1228. carlaNSM.replySave();
  1229. }
  1230. // -------------------------------------------------------------------------------------------------------------------
  1231. #ifdef QTCREATOR_TEST
  1232. #include <QtGui/QApplication>
  1233. #include <QtGui/QDialog>
  1234. QDialog* vstGui = nullptr;
  1235. void main_callback(void* ptr, CarlaBackend::CallbackType action, unsigned short pluginId, int value1, int value2, double value3)
  1236. {
  1237. switch (action)
  1238. {
  1239. case CarlaBackend::CALLBACK_SHOW_GUI:
  1240. if (vstGui && ! value1)
  1241. vstGui->close();
  1242. break;
  1243. case CarlaBackend::CALLBACK_RESIZE_GUI:
  1244. vstGui->setFixedSize(value1, value2);
  1245. break;
  1246. default:
  1247. break;
  1248. }
  1249. Q_UNUSED(ptr);
  1250. Q_UNUSED(pluginId);
  1251. Q_UNUSED(value3);
  1252. }
  1253. void run_tests_standalone(short idMax)
  1254. {
  1255. for (short id = 0; id <= idMax; id++)
  1256. {
  1257. qDebug("------------------- TEST @%i: non-parameter calls --------------------", id);
  1258. get_plugin_info(id);
  1259. get_audio_port_count_info(id);
  1260. get_midi_port_count_info(id);
  1261. get_parameter_count_info(id);
  1262. get_gui_info(id);
  1263. get_chunk_data(id);
  1264. get_parameter_count(id);
  1265. get_program_count(id);
  1266. get_midi_program_count(id);
  1267. get_custom_data_count(id);
  1268. get_real_plugin_name(id);
  1269. get_current_program_index(id);
  1270. get_current_midi_program_index(id);
  1271. qDebug("------------------- TEST @%i: parameter calls [-1] --------------------", id);
  1272. get_parameter_info(id, -1);
  1273. get_parameter_scalepoint_info(id, -1, -1);
  1274. get_parameter_data(id, -1);
  1275. get_parameter_ranges(id, -1);
  1276. get_midi_program_data(id, -1);
  1277. get_custom_data(id, -1);
  1278. get_parameter_text(id, -1);
  1279. get_program_name(id, -1);
  1280. get_midi_program_name(id, -1);
  1281. get_default_parameter_value(id, -1);
  1282. get_current_parameter_value(id, -1);
  1283. get_input_peak_value(id, -1);
  1284. get_output_peak_value(id, -1);
  1285. qDebug("------------------- TEST @%i: parameter calls [0] --------------------", id);
  1286. get_parameter_info(id, 0);
  1287. get_parameter_scalepoint_info(id, 0, -1);
  1288. get_parameter_scalepoint_info(id, 0, 0);
  1289. get_parameter_data(id, 0);
  1290. get_parameter_ranges(id, 0);
  1291. get_midi_program_data(id, 0);
  1292. get_custom_data(id, 0);
  1293. get_parameter_text(id, 0);
  1294. get_program_name(id, 0);
  1295. get_midi_program_name(id, 0);
  1296. get_default_parameter_value(id, 0);
  1297. get_current_parameter_value(id, 0);
  1298. get_input_peak_value(id, 0);
  1299. get_input_peak_value(id, 1);
  1300. get_input_peak_value(id, 2);
  1301. get_output_peak_value(id, 0);
  1302. get_output_peak_value(id, 1);
  1303. get_output_peak_value(id, 2);
  1304. qDebug("------------------- TEST @%i: set extra data --------------------", id);
  1305. set_custom_data(id, CarlaBackend::CUSTOM_DATA_STRING, "", "");
  1306. set_chunk_data(id, nullptr);
  1307. set_gui_container(id, (uintptr_t)1);
  1308. qDebug("------------------- TEST @%i: gui stuff --------------------", id);
  1309. show_gui(id, false);
  1310. show_gui(id, true);
  1311. show_gui(id, true);
  1312. idle_guis();
  1313. idle_guis();
  1314. idle_guis();
  1315. qDebug("------------------- TEST @%i: other --------------------", id);
  1316. send_midi_note(id, 15, 127, 127);
  1317. send_midi_note(id, 0, 0, 0);
  1318. prepare_for_save(id);
  1319. prepare_for_save(id);
  1320. prepare_for_save(id);
  1321. }
  1322. }
  1323. int main(int argc, char* argv[])
  1324. {
  1325. using namespace CarlaBackend;
  1326. // Qt app
  1327. QApplication app(argc, argv);
  1328. // Qt gui (for vst)
  1329. vstGui = new QDialog(nullptr);
  1330. // set callback and options
  1331. set_callback_function(main_callback);
  1332. set_option(OPTION_PREFER_UI_BRIDGES, 0, nullptr);
  1333. //set_option(OPTION_PROCESS_MODE, PROCESS_MODE_CONTINUOUS_RACK, nullptr);
  1334. // start engine
  1335. if (! engine_init("JACK", "carla_demo"))
  1336. {
  1337. qCritical("failed to start backend engine, reason:\n%s", get_last_error());
  1338. delete vstGui;
  1339. return 1;
  1340. }
  1341. short id_ladspa = add_plugin(BINARY_NATIVE, PLUGIN_LADSPA, "/usr/lib/ladspa/LEET_eqbw2x2.so", "LADSPA plug name, test long name - "
  1342. "------- name ------------ name2 ----------- name3 ------------ name4 ------------ name5 ---------- name6", "leet_equalizer_bw2x2", nullptr);
  1343. short id_dssi = add_plugin(BINARY_NATIVE, PLUGIN_DSSI, "/usr/lib/dssi/fluidsynth-dssi.so", "DSSI pname, short-utf8 _ \xAE", "FluidSynth-DSSI", (void*)"/usr/lib/dssi/fluidsynth-dssi/FluidSynth-DSSI_gtk");
  1344. short id_native = add_plugin(BINARY_NATIVE, PLUGIN_INTERNAL, "", "ZynHere", "zynaddsubfx", nullptr);
  1345. //short id_lv2 = add_plugin(BINARY_NATIVE, PLUGIN_LV2, "FILENAME", "HAHA name!!!", "http://studionumbersix.com/foo/lv2/yc20", nullptr);
  1346. //short id_vst = add_plugin(BINARY_NATIVE, PLUGIN_LV2, "FILENAME", "HAHA name!!!", "http://studionumbersix.com/foo/lv2/yc20", nullptr);
  1347. if (id_ladspa < 0 || id_dssi < 0 || id_native < 0)
  1348. {
  1349. qCritical("failed to start load plugins, reason:\n%s", get_last_error());
  1350. delete vstGui;
  1351. return 1;
  1352. }
  1353. //const GuiInfo* const guiInfo = get_gui_info(id);
  1354. //if (guiInfo->type == CarlaBackend::GUI_INTERNAL_QT4 || guiInfo->type == CarlaBackend::GUI_INTERNAL_X11)
  1355. //{
  1356. // set_gui_data(id, 0, (uintptr_t)gui);
  1357. //gui->show();
  1358. //}
  1359. // activate
  1360. set_active(id_ladspa, true);
  1361. set_active(id_dssi, true);
  1362. set_active(id_native, true);
  1363. // start guis
  1364. show_gui(id_dssi, true);
  1365. carla_sleep(1);
  1366. // do tests
  1367. run_tests_standalone(id_dssi+1);
  1368. // lock
  1369. app.exec();
  1370. delete vstGui;
  1371. vstGui = nullptr;
  1372. remove_plugin(id_ladspa);
  1373. remove_plugin(id_dssi);
  1374. remove_plugin(id_native);
  1375. engine_close();
  1376. return 0;
  1377. }
  1378. #endif