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.

540 lines
15KB

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