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.

537 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. }
  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. CarlaEngine::close();
  63. return true;
  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 channel, 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. }
  236. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t midiEventCount, const MidiEvent* const midiEvents) override
  237. {
  238. // ---------------------------------------------------------------
  239. // Time Info
  240. const ::TimeInfo* timeInfo(PluginDescriptorClass::getTimeInfo());
  241. fTimeInfo.playing = timeInfo->playing;
  242. fTimeInfo.frame = timeInfo->frame;
  243. fTimeInfo.usecs = timeInfo->usecs;
  244. fTimeInfo.valid = 0x0;
  245. if (timeInfo->bbt.valid)
  246. {
  247. fTimeInfo.valid |= EngineTimeInfo::ValidBBT;
  248. fTimeInfo.bbt.bar = timeInfo->bbt.bar;
  249. fTimeInfo.bbt.beat = timeInfo->bbt.beat;
  250. fTimeInfo.bbt.tick = timeInfo->bbt.tick;
  251. fTimeInfo.bbt.barStartTick = timeInfo->bbt.barStartTick;
  252. fTimeInfo.bbt.beatsPerBar = timeInfo->bbt.beatsPerBar;
  253. fTimeInfo.bbt.beatType = timeInfo->bbt.beatType;
  254. fTimeInfo.bbt.ticksPerBeat = timeInfo->bbt.ticksPerBeat;
  255. fTimeInfo.bbt.beatsPerMinute = timeInfo->bbt.beatsPerMinute;
  256. }
  257. // ---------------------------------------------------------------
  258. // Initial checks
  259. if (kData->curPluginCount == 0)
  260. {
  261. carla_zeroFloat(outBuffer[0], frames);
  262. carla_zeroFloat(outBuffer[1], frames);
  263. return CarlaEngine::proccessPendingEvents();
  264. }
  265. // create audio buffers
  266. float* inBuf[2] = { inBuffer[0], inBuffer[1] };
  267. float* outBuf[2] = { outBuffer[0], outBuffer[1] };
  268. // process
  269. CarlaEngine::processRack(inBuf, outBuf, frames);
  270. CarlaEngine::proccessPendingEvents();
  271. return;
  272. // unused
  273. (void)midiEventCount;
  274. (void)midiEvents;
  275. }
  276. // -------------------------------------------------------------------
  277. // Plugin UI calls
  278. void uiShow(const bool show) override
  279. {
  280. return;
  281. // TODO
  282. // unused
  283. (void)show;
  284. }
  285. void uiIdle() override
  286. {
  287. CarlaEngine::idle();
  288. }
  289. void uiSetParameterValue(const uint32_t index, const float value) override
  290. {
  291. CARLA_ASSERT(index < getParameterCount());
  292. return;
  293. // TODO
  294. // unused
  295. (void)value;
  296. }
  297. void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override
  298. {
  299. return;
  300. // TODO
  301. // unused
  302. (void)bank;
  303. (void)program;
  304. }
  305. void uiSetCustomData(const char* const key, const char* const value) override
  306. {
  307. CARLA_ASSERT(key != nullptr);
  308. CARLA_ASSERT(value != nullptr);
  309. return;
  310. // TODO
  311. // unused
  312. (void)key;
  313. (void)value;
  314. }
  315. // -------------------------------------------------------------------
  316. // Plugin state calls
  317. char* getState() override
  318. {
  319. QString string;
  320. QTextStream out(&string);
  321. out << "<?xml version='1.0' encoding='UTF-8'?>\n";
  322. out << "<!DOCTYPE CARLA-PROJECT>\n";
  323. out << "<CARLA-PROJECT VERSION='1.0'>\n";
  324. bool firstPlugin = true;
  325. char strBuf[STR_MAX+1];
  326. for (unsigned int i=0; i < kData->curPluginCount; ++i)
  327. {
  328. CarlaPlugin* const plugin = kData->plugins[i].plugin;
  329. if (plugin != nullptr && plugin->enabled())
  330. {
  331. if (! firstPlugin)
  332. out << "\n";
  333. plugin->getRealName(strBuf);
  334. if (*strBuf != 0)
  335. out << QString(" <!-- %1 -->\n").arg(xmlSafeString(strBuf, true));
  336. out << " <Plugin>\n";
  337. out << getXMLFromSaveState(plugin->getSaveState());
  338. out << " </Plugin>\n";
  339. firstPlugin = false;
  340. }
  341. }
  342. out << "</CARLA-PROJECT>\n";
  343. return strdup(string.toUtf8().constData());
  344. }
  345. void setState(const char* const data) override
  346. {
  347. QDomDocument xml;
  348. xml.setContent(QString(data));
  349. QDomNode xmlNode(xml.documentElement());
  350. if (xmlNode.toElement().tagName() != "CARLA-PROJECT")
  351. {
  352. carla_stderr2("Not a valid Carla project");
  353. return;
  354. }
  355. QDomNode node(xmlNode.firstChild());
  356. while (! node.isNull())
  357. {
  358. if (node.toElement().tagName() == "Plugin")
  359. {
  360. const SaveState& saveState(getSaveStateDictFromXML(node));
  361. CARLA_ASSERT(saveState.type != nullptr);
  362. if (saveState.type == nullptr)
  363. continue;
  364. const void* extraStuff = nullptr;
  365. // FIXME
  366. //if (std::strcmp(saveState.type, "DSSI") == 0)
  367. // extraStuff = findDSSIGUI(saveState.binary, saveState.label);
  368. // TODO - proper find&load plugins
  369. if (addPlugin(getPluginTypeFromString(saveState.type), saveState.binary, saveState.name, saveState.label, extraStuff))
  370. {
  371. if (CarlaPlugin* plugin = getPlugin(kData->curPluginCount-1))
  372. plugin->loadSaveState(saveState);
  373. }
  374. }
  375. node = node.nextSibling();
  376. }
  377. }
  378. private:
  379. PluginDescriptorClassEND(CarlaEngineNative)
  380. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineNative)
  381. };
  382. // -----------------------------------------------------------------------
  383. static const PluginDescriptor carlaDesc = {
  384. /* category */ ::PLUGIN_CATEGORY_OTHER,
  385. /* hints */ static_cast< ::PluginHints>(::PLUGIN_IS_SYNTH|::PLUGIN_USES_SINGLE_THREAD|::PLUGIN_USES_STATE),
  386. /* audioIns */ 2,
  387. /* audioOuts */ 2,
  388. /* midiIns */ 1,
  389. /* midiOuts */ 1,
  390. /* paramIns */ 0,
  391. /* paramOuts */ 0,
  392. /* name */ "Carla-Plugin",
  393. /* label */ "carla",
  394. /* maker */ "falkTX",
  395. /* copyright */ "GNU GPL v2+",
  396. PluginDescriptorFILL(CarlaEngineNative)
  397. };
  398. void CarlaEngine::registerNativePlugin()
  399. {
  400. carla_register_native_plugin(&carlaDesc);
  401. }
  402. CARLA_BACKEND_END_NAMESPACE
  403. // -----------------------------------------------------------------------
  404. #endif // ! BUILD_BRIDGE