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.

601 lines
18KB

  1. /*
  2. * Carla Plugin Engine (Native)
  3. * Copyright (C) 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. #ifndef BUILD_BRIDGE
  18. #include "CarlaEngineInternal.hpp"
  19. #include "CarlaStateUtils.hpp"
  20. #include "CarlaNative.hpp"
  21. #include <QtCore/QTextStream>
  22. CARLA_BACKEND_START_NAMESPACE
  23. // -----------------------------------------------------------------------
  24. class CarlaEngineNative : public PluginDescriptorClass,
  25. public CarlaEngine
  26. {
  27. public:
  28. CarlaEngineNative(const HostDescriptor* const host)
  29. : PluginDescriptorClass(host),
  30. CarlaEngine()
  31. {
  32. carla_debug("CarlaEngineNative::CarlaEngineNative()");
  33. // set-up engine
  34. fOptions.processMode = PROCESS_MODE_CONTINUOUS_RACK;
  35. fOptions.transportMode = TRANSPORT_MODE_PLUGIN;
  36. fOptions.forceStereo = true;
  37. fOptions.preferPluginBridges = false;
  38. fOptions.preferUiBridges = false;
  39. init("Carla-Plugin");
  40. }
  41. ~CarlaEngineNative() override
  42. {
  43. carla_debug("CarlaEngineNative::~CarlaEngineNative()");
  44. setAboutToClose();
  45. removeAllPlugins();
  46. close();
  47. }
  48. protected:
  49. // -------------------------------------
  50. // CarlaEngine virtual calls
  51. bool init(const char* const clientName) override
  52. {
  53. carla_debug("CarlaEngineNative::init(\"%s\")", clientName);
  54. fBufferSize = PluginDescriptorClass::getBufferSize();
  55. fSampleRate = PluginDescriptorClass::getSampleRate();
  56. CarlaEngine::init(clientName);
  57. return true;
  58. }
  59. bool close() override
  60. {
  61. carla_debug("CarlaEngineNative::close()");
  62. proccessPendingEvents();
  63. return CarlaEngine::close();
  64. }
  65. bool isRunning() const override
  66. {
  67. return true;
  68. }
  69. bool isOffline() const override
  70. {
  71. return false;
  72. }
  73. EngineType type() const override
  74. {
  75. return kEngineTypePlugin;
  76. }
  77. // -------------------------------------------------------------------
  78. // Plugin parameter calls
  79. uint32_t getParameterCount() override
  80. {
  81. if (kData->curPluginCount == 0 || kData->plugins == nullptr)
  82. return 0;
  83. CarlaPlugin* const plugin(kData->plugins[0].plugin);
  84. if (plugin == nullptr || ! plugin->enabled())
  85. return 0;
  86. return kData->plugins[0].plugin->parameterCount();
  87. }
  88. const Parameter* getParameterInfo(const uint32_t index) override
  89. {
  90. if (index >= getParameterCount())
  91. return nullptr;
  92. CarlaPlugin* const plugin(kData->plugins[0].plugin);
  93. if (plugin == nullptr || ! plugin->enabled())
  94. return nullptr;
  95. static ::Parameter param;
  96. static char strBufName[STR_MAX+1];
  97. static char strBufUnit[STR_MAX+1];
  98. const ParameterData& paramData(plugin->parameterData(index));
  99. const ParameterRanges& paramRanges(plugin->parameterRanges(index));
  100. plugin->getParameterName(index, strBufName);
  101. plugin->getParameterUnit(index, strBufUnit);
  102. unsigned int hints = 0x0;
  103. if (paramData.hints & PARAMETER_IS_BOOLEAN)
  104. hints |= ::PARAMETER_IS_BOOLEAN;
  105. if (paramData.hints & PARAMETER_IS_INTEGER)
  106. hints |= ::PARAMETER_IS_INTEGER;
  107. if (paramData.hints & PARAMETER_IS_LOGARITHMIC)
  108. hints |= ::PARAMETER_IS_LOGARITHMIC;
  109. if (paramData.hints & PARAMETER_IS_AUTOMABLE)
  110. hints |= ::PARAMETER_IS_AUTOMABLE;
  111. if (paramData.hints & PARAMETER_USES_SAMPLERATE)
  112. hints |= ::PARAMETER_USES_SAMPLE_RATE;
  113. if (paramData.hints & PARAMETER_USES_SCALEPOINTS)
  114. hints |= ::PARAMETER_USES_SCALEPOINTS;
  115. if (paramData.hints & PARAMETER_USES_CUSTOM_TEXT)
  116. hints |= ::PARAMETER_USES_CUSTOM_TEXT;
  117. if (paramData.type == PARAMETER_INPUT || paramData.type == PARAMETER_OUTPUT)
  118. {
  119. if (paramData.hints & PARAMETER_IS_ENABLED)
  120. hints |= ::PARAMETER_IS_ENABLED;
  121. if (paramData.type == PARAMETER_OUTPUT)
  122. hints |= ::PARAMETER_IS_OUTPUT;
  123. }
  124. param.hints = static_cast< ::ParameterHints>(hints);
  125. param.name = strBufName;
  126. param.unit = strBufUnit;
  127. param.ranges.def = paramRanges.def;
  128. param.ranges.min = paramRanges.min;
  129. param.ranges.max = paramRanges.max;
  130. param.ranges.step = paramRanges.step;
  131. param.ranges.stepSmall = paramRanges.stepSmall;
  132. param.ranges.stepLarge = paramRanges.stepLarge;
  133. param.scalePointCount = 0; // TODO
  134. param.scalePoints = nullptr;
  135. return &param;
  136. }
  137. float getParameterValue(const uint32_t index) override
  138. {
  139. if (index >= getParameterCount())
  140. return 0.0f;
  141. CarlaPlugin* const plugin(kData->plugins[0].plugin);
  142. if (plugin == nullptr || ! plugin->enabled())
  143. return 0.0f;
  144. return plugin->getParameterValue(index);
  145. }
  146. const char* getParameterText(const uint32_t index) override
  147. {
  148. if (index >= getParameterCount())
  149. return nullptr;
  150. CarlaPlugin* const plugin(kData->plugins[0].plugin);
  151. if (plugin == nullptr || ! plugin->enabled())
  152. return nullptr;
  153. static char strBuf[STR_MAX+1];
  154. plugin->getParameterText(index, strBuf);
  155. return strBuf;
  156. }
  157. // -------------------------------------------------------------------
  158. // Plugin midi-program calls
  159. uint32_t getMidiProgramCount() override
  160. {
  161. if (kData->curPluginCount == 0 || kData->plugins == nullptr)
  162. return 0;
  163. CarlaPlugin* const plugin(kData->plugins[0].plugin);
  164. if (plugin == nullptr || ! plugin->enabled())
  165. return 0.0f;
  166. return plugin->midiProgramCount();
  167. }
  168. const MidiProgram* getMidiProgramInfo(const uint32_t index) override
  169. {
  170. if (index >= getMidiProgramCount())
  171. return nullptr;
  172. CarlaPlugin* const plugin(kData->plugins[0].plugin);
  173. if (plugin == nullptr || ! plugin->enabled())
  174. return nullptr;
  175. static ::MidiProgram midiProg;
  176. {
  177. const MidiProgramData& midiProgData(plugin->midiProgramData(index));
  178. midiProg.bank = midiProgData.bank;
  179. midiProg.program = midiProgData.program;
  180. midiProg.name = midiProgData.name;
  181. }
  182. return &midiProg;
  183. }
  184. // -------------------------------------------------------------------
  185. // Plugin state calls
  186. void setParameterValue(const uint32_t index, const float value) override
  187. {
  188. if (index >= getParameterCount())
  189. return;
  190. CarlaPlugin* const plugin(kData->plugins[0].plugin);
  191. if (plugin == nullptr || ! plugin->enabled())
  192. return;
  193. plugin->setParameterValue(index, value, false, false, false);
  194. }
  195. void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
  196. {
  197. if (kData->curPluginCount == 0 || kData->plugins == nullptr)
  198. return;
  199. CarlaPlugin* const plugin(kData->plugins[0].plugin);
  200. if (plugin == nullptr || ! plugin->enabled())
  201. return;
  202. plugin->setMidiProgramById(bank, program, false, false, false);
  203. }
  204. void setCustomData(const char* const key, const char* const value) override
  205. {
  206. CARLA_ASSERT(key != nullptr);
  207. CARLA_ASSERT(value != nullptr);
  208. return;
  209. // TODO
  210. // unused
  211. (void)key;
  212. (void)value;
  213. }
  214. // -------------------------------------------------------------------
  215. // Plugin process calls
  216. void activate() override
  217. {
  218. for (uint32_t i=0; i < kData->curPluginCount; ++i)
  219. {
  220. CarlaPlugin* const plugin(kData->plugins[i].plugin);
  221. if (plugin == nullptr || ! plugin->enabled())
  222. continue;
  223. plugin->setActive(true, true, false);
  224. }
  225. }
  226. void deactivate() override
  227. {
  228. for (uint32_t i=0; i < kData->curPluginCount; ++i)
  229. {
  230. CarlaPlugin* const plugin(kData->plugins[i].plugin);
  231. if (plugin == nullptr || ! plugin->enabled())
  232. continue;
  233. plugin->setActive(false, true, false);
  234. }
  235. // just in case
  236. proccessPendingEvents();
  237. }
  238. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t midiEventCount, const ::MidiEvent* const midiEvents) override
  239. {
  240. if (kData->curPluginCount == 0)
  241. {
  242. carla_zeroFloat(outBuffer[0], frames);
  243. carla_zeroFloat(outBuffer[1], frames);
  244. return CarlaEngine::proccessPendingEvents();
  245. }
  246. // ---------------------------------------------------------------
  247. // Time Info
  248. const ::TimeInfo* timeInfo(PluginDescriptorClass::getTimeInfo());
  249. fTimeInfo.playing = timeInfo->playing;
  250. fTimeInfo.frame = timeInfo->frame;
  251. fTimeInfo.usecs = timeInfo->usecs;
  252. fTimeInfo.valid = 0x0;
  253. if (timeInfo->bbt.valid)
  254. {
  255. fTimeInfo.valid |= EngineTimeInfo::ValidBBT;
  256. fTimeInfo.bbt.bar = timeInfo->bbt.bar;
  257. fTimeInfo.bbt.beat = timeInfo->bbt.beat;
  258. fTimeInfo.bbt.tick = timeInfo->bbt.tick;
  259. fTimeInfo.bbt.barStartTick = timeInfo->bbt.barStartTick;
  260. fTimeInfo.bbt.beatsPerBar = timeInfo->bbt.beatsPerBar;
  261. fTimeInfo.bbt.beatType = timeInfo->bbt.beatType;
  262. fTimeInfo.bbt.ticksPerBeat = timeInfo->bbt.ticksPerBeat;
  263. fTimeInfo.bbt.beatsPerMinute = timeInfo->bbt.beatsPerMinute;
  264. }
  265. // ---------------------------------------------------------------
  266. // initialize input events
  267. carla_zeroStruct<EngineEvent>(kData->bufEvent.in, INTERNAL_EVENT_COUNT);
  268. {
  269. uint32_t engineEventIndex = 0;
  270. for (uint32_t i=0; i < midiEventCount && engineEventIndex < INTERNAL_EVENT_COUNT; ++i)
  271. {
  272. const ::MidiEvent& midiEvent(midiEvents[i]);
  273. if (midiEvent.size > 4)
  274. continue;
  275. const uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
  276. const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent.data);
  277. // we don't want some events
  278. if (status == MIDI_STATUS_PROGRAM_CHANGE)
  279. continue;
  280. // handle note/sound off properly
  281. if (status == MIDI_STATUS_CONTROL_CHANGE)
  282. {
  283. const uint8_t control = midiEvent.data[1];
  284. if (MIDI_IS_CONTROL_BANK_SELECT(control))
  285. continue;
  286. if (control == MIDI_CONTROL_ALL_SOUND_OFF || control == MIDI_CONTROL_ALL_NOTES_OFF)
  287. {
  288. EngineEvent& engineEvent(kData->bufEvent.in[engineEventIndex++]);
  289. engineEvent.clear();
  290. engineEvent.type = kEngineEventTypeControl;
  291. engineEvent.time = midiEvent.time;
  292. engineEvent.channel = channel;
  293. engineEvent.ctrl.type = (control == MIDI_CONTROL_ALL_SOUND_OFF) ? kEngineControlEventTypeAllSoundOff : kEngineControlEventTypeAllNotesOff;
  294. engineEvent.ctrl.param = 0;
  295. engineEvent.ctrl.value = 0.0f;
  296. continue;
  297. }
  298. }
  299. EngineEvent& engineEvent(kData->bufEvent.in[engineEventIndex++]);
  300. engineEvent.clear();
  301. engineEvent.type = kEngineEventTypeMidi;
  302. engineEvent.time = midiEvent.time;
  303. engineEvent.channel = channel;
  304. engineEvent.midi.data[0] = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
  305. engineEvent.midi.data[1] = midiEvent.data[1];
  306. engineEvent.midi.data[2] = midiEvent.data[2];
  307. engineEvent.midi.data[3] = midiEvent.data[3];
  308. engineEvent.midi.size = midiEvent.size;
  309. }
  310. }
  311. // ---------------------------------------------------------------
  312. // create audio buffers
  313. float* inBuf[2] = { inBuffer[0], inBuffer[1] };
  314. float* outBuf[2] = { outBuffer[0], outBuffer[1] };
  315. // ---------------------------------------------------------------
  316. // process
  317. CarlaEngine::processRack(inBuf, outBuf, frames);
  318. CarlaEngine::proccessPendingEvents();
  319. }
  320. // -------------------------------------------------------------------
  321. // Plugin UI calls
  322. void uiShow(const bool show) override
  323. {
  324. return;
  325. // TODO
  326. // unused
  327. (void)show;
  328. }
  329. void uiIdle() override
  330. {
  331. CarlaEngine::idle();
  332. }
  333. void uiSetParameterValue(const uint32_t index, const float value) override
  334. {
  335. if (index >= getParameterCount())
  336. return;
  337. CarlaPlugin* const plugin(kData->plugins[0].plugin);
  338. if (plugin == nullptr || ! plugin->enabled())
  339. return;
  340. plugin->uiParameterChange(index, value);
  341. }
  342. void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override
  343. {
  344. return;
  345. // TODO
  346. // unused
  347. (void)channel;
  348. (void)bank;
  349. (void)program;
  350. }
  351. void uiSetCustomData(const char* const key, const char* const value) override
  352. {
  353. CARLA_ASSERT(key != nullptr);
  354. CARLA_ASSERT(value != nullptr);
  355. return;
  356. // TODO
  357. // unused
  358. (void)key;
  359. (void)value;
  360. }
  361. // -------------------------------------------------------------------
  362. // Plugin state calls
  363. char* getState() override
  364. {
  365. QString string;
  366. QTextStream out(&string);
  367. out << "<?xml version='1.0' encoding='UTF-8'?>\n";
  368. out << "<!DOCTYPE CARLA-PROJECT>\n";
  369. out << "<CARLA-PROJECT VERSION='1.0'>\n";
  370. bool firstPlugin = true;
  371. char strBuf[STR_MAX+1];
  372. for (unsigned int i=0; i < kData->curPluginCount; ++i)
  373. {
  374. CarlaPlugin* const plugin = kData->plugins[i].plugin;
  375. if (plugin != nullptr && plugin->enabled())
  376. {
  377. if (! firstPlugin)
  378. out << "\n";
  379. plugin->getRealName(strBuf);
  380. if (*strBuf != 0)
  381. out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true));
  382. out << " <Plugin>\n";
  383. out << getXMLFromSaveState(plugin->getSaveState());
  384. out << " </Plugin>\n";
  385. firstPlugin = false;
  386. }
  387. }
  388. out << "</CARLA-PROJECT>\n";
  389. return strdup(string.toUtf8().constData());
  390. }
  391. void setState(const char* const data) override
  392. {
  393. QDomDocument xml;
  394. xml.setContent(QString(data));
  395. QDomNode xmlNode(xml.documentElement());
  396. if (xmlNode.toElement().tagName() != "CARLA-PROJECT")
  397. {
  398. carla_stderr2("Not a valid Carla project");
  399. return;
  400. }
  401. QDomNode node(xmlNode.firstChild());
  402. while (! node.isNull())
  403. {
  404. if (node.toElement().tagName() == "Plugin")
  405. {
  406. const SaveState& saveState(getSaveStateDictFromXML(node));
  407. CARLA_ASSERT(saveState.type != nullptr);
  408. if (saveState.type == nullptr)
  409. continue;
  410. const void* extraStuff = nullptr;
  411. // FIXME
  412. //if (std::strcmp(saveState.type, "DSSI") == 0)
  413. // extraStuff = findDSSIGUI(saveState.binary, saveState.label);
  414. // TODO - proper find&load plugins
  415. if (addPlugin(getPluginTypeFromString(saveState.type), saveState.binary, saveState.name, saveState.label, extraStuff))
  416. {
  417. if (CarlaPlugin* plugin = getPlugin(kData->curPluginCount-1))
  418. plugin->loadSaveState(saveState);
  419. }
  420. }
  421. node = node.nextSibling();
  422. }
  423. }
  424. // -------------------------------------------------------------------
  425. private:
  426. PluginDescriptorClassEND(CarlaEngineNative)
  427. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNative)
  428. };
  429. // -----------------------------------------------------------------------
  430. static const PluginDescriptor carlaDesc = {
  431. /* category */ ::PLUGIN_CATEGORY_OTHER,
  432. /* hints */ static_cast< ::PluginHints>(::PLUGIN_IS_SYNTH|::PLUGIN_USES_SINGLE_THREAD|::PLUGIN_USES_STATE),
  433. /* audioIns */ 2,
  434. /* audioOuts */ 2,
  435. /* midiIns */ 1,
  436. /* midiOuts */ 1,
  437. /* paramIns */ 0,
  438. /* paramOuts */ 0,
  439. /* name */ "Carla-Plugin",
  440. /* label */ "carla",
  441. /* maker */ "falkTX",
  442. /* copyright */ "GNU GPL v2+",
  443. PluginDescriptorFILL(CarlaEngineNative)
  444. };
  445. void CarlaEngine::registerNativePlugin()
  446. {
  447. carla_register_native_plugin(&carlaDesc);
  448. }
  449. CARLA_BACKEND_END_NAMESPACE
  450. // -----------------------------------------------------------------------
  451. #endif // ! BUILD_BRIDGE