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.

550 lines
16KB

  1. /*
  2. * Carla LV2 Single Plugin
  3. * Copyright (C) 2017 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 doc/GPL.txt file.
  16. */
  17. // #define BUILD_BRIDGE
  18. #include "engine/CarlaEngineInternal.hpp"
  19. #include "CarlaPlugin.hpp"
  20. #include "CarlaBackendUtils.hpp"
  21. #include "CarlaEngineUtils.hpp"
  22. #include "CarlaLv2Utils.hpp"
  23. #include "CarlaUtils.h"
  24. // ---------------------------------------------------------------------------------------------------------------------
  25. CARLA_BACKEND_START_NAMESPACE
  26. class CarlaEngineLV2Single : public CarlaEngine
  27. {
  28. public:
  29. CarlaEngineLV2Single(const uint32_t bufferSize, const double sampleRate, const char* const bundlePath, const LV2_URID_Map* uridMap)
  30. : fPlugin(nullptr),
  31. fIsRunning(false),
  32. fIsOffline(false)
  33. {
  34. // xxxxx
  35. CarlaString resourceDir(bundlePath);
  36. resourceDir += CARLA_OS_SEP_STR "resources" CARLA_OS_SEP_STR;
  37. pData->bufferSize = bufferSize;
  38. pData->sampleRate = sampleRate;
  39. pData->initTime(nullptr);
  40. pData->options.processMode = ENGINE_PROCESS_MODE_BRIDGE;
  41. pData->options.transportMode = ENGINE_TRANSPORT_MODE_PLUGIN;
  42. pData->options.forceStereo = false;
  43. pData->options.preferPluginBridges = false;
  44. pData->options.preferUiBridges = false;
  45. init("LV2-Export");
  46. if (pData->options.resourceDir != nullptr)
  47. delete[] pData->options.resourceDir;
  48. if (pData->options.binaryDir != nullptr)
  49. delete[] pData->options.binaryDir;
  50. pData->options.resourceDir = resourceDir.dup();
  51. pData->options.binaryDir = carla_strdup(carla_get_library_folder());
  52. setCallback(_engine_callback, this);
  53. if (! addPlugin(BINARY_NATIVE, PLUGIN_VST2, "/usr/lib/vst/3BandEQ-vst.so", nullptr, nullptr, 0, nullptr, 0x0))
  54. {
  55. carla_stderr2("Failed to init plugin, possible reasons: %s", getLastError());
  56. return;
  57. }
  58. CARLA_SAFE_ASSERT_RETURN(pData->curPluginCount == 1,)
  59. fPlugin = pData->plugins[0].plugin;
  60. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  61. CARLA_SAFE_ASSERT_RETURN(fPlugin->isEnabled(),);
  62. fPorts.init(fPlugin);
  63. }
  64. ~CarlaEngineLV2Single()
  65. {
  66. close();
  67. }
  68. bool hasPlugin()
  69. {
  70. return fPlugin != nullptr;
  71. }
  72. // -----------------------------------------------------------------------------------------------------------------
  73. // LV2 functions
  74. void lv2_connect_port(const uint32_t port, void* const dataLocation)
  75. {
  76. fPorts.connectPort(port, dataLocation);
  77. }
  78. void lv2_activate()
  79. {
  80. CARLA_SAFE_ASSERT_RETURN(! fIsRunning,);
  81. fPlugin->activate();
  82. fIsRunning = true;
  83. }
  84. void lv2_deactivate()
  85. {
  86. CARLA_SAFE_ASSERT_RETURN(fIsRunning,);
  87. fIsRunning = false;
  88. fPlugin->deactivate();
  89. }
  90. void lv2_run(const uint32_t frames)
  91. {
  92. fIsOffline = (fPorts.freewheel != nullptr && *fPorts.freewheel >= 0.5f);
  93. // Check for updated parameters
  94. float curValue;
  95. for (uint32_t i=0; i < fPorts.numParams; ++i)
  96. {
  97. if (fPorts.paramsOut[i])
  98. continue;
  99. CARLA_SAFE_ASSERT_CONTINUE(fPorts.paramsPtr[i] != nullptr)
  100. curValue = *fPorts.paramsPtr[i];
  101. if (carla_isEqual(fPorts.paramsLast[i], curValue))
  102. continue;
  103. fPorts.paramsLast[i] = curValue;
  104. fPlugin->setParameterValue(i, curValue, false, false, false);
  105. }
  106. if (frames == 0)
  107. return fPorts.updateOutputs();
  108. if (fPlugin->tryLock(fIsOffline))
  109. {
  110. fPlugin->initBuffers();
  111. fPlugin->process(fPorts.audioIns, fPorts.audioOuts, nullptr, nullptr, frames);
  112. fPlugin->unlock();
  113. }
  114. else
  115. {
  116. for (uint32_t i=0; i<fPorts.numAudioOuts; ++i)
  117. carla_zeroFloats(fPorts.audioOuts[i], frames);
  118. }
  119. fPorts.updateOutputs();
  120. }
  121. protected:
  122. // -----------------------------------------------------------------------------------------------------------------
  123. // CarlaEngine virtual calls
  124. bool init(const char* const clientName) override
  125. {
  126. carla_stdout("CarlaEngineNative::init(\"%s\")", clientName);
  127. if (! pData->init(clientName))
  128. {
  129. close();
  130. setLastError("Failed to init internal data");
  131. return false;
  132. }
  133. return true;
  134. }
  135. bool close() override
  136. {
  137. fIsRunning = false;
  138. CarlaEngine::close();
  139. return true;
  140. }
  141. bool isRunning() const noexcept override
  142. {
  143. return fIsRunning;
  144. }
  145. bool isOffline() const noexcept override
  146. {
  147. return fIsOffline;
  148. }
  149. bool usesConstantBufferSize() const noexcept override
  150. {
  151. return true;
  152. }
  153. EngineType getType() const noexcept override
  154. {
  155. return kEngineTypePlugin;
  156. }
  157. const char* getCurrentDriverName() const noexcept override
  158. {
  159. return "LV2 Plugin";
  160. }
  161. void callback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr) noexcept override
  162. {
  163. CarlaEngine::callback(action, pluginId, value1, value2, value3, valueStr);
  164. //if (action == ENGINE_CALLBACK_IDLE && ! pData->aboutToClose)
  165. // pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_HOST_IDLE, 0, 0, nullptr, 0.0f);
  166. }
  167. void engineCallback(const EngineCallbackOpcode action, const uint pluginId, const int value1, const int value2, const float value3, const char* const valueStr)
  168. {
  169. carla_stdout("engineCallback(%i:%s, %u, %i, %i, %f, %s)", action, EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, valueStr);
  170. }
  171. // -----------------------------------------------------------------------------------------------------------------
  172. private:
  173. CarlaPlugin* fPlugin;
  174. bool fIsRunning;
  175. // Lv2 host data
  176. bool fIsOffline;
  177. struct Ports {
  178. uint32_t numAudioIns;
  179. uint32_t numAudioOuts;
  180. uint32_t numParams;
  181. const float** audioIns;
  182. /* */ float** audioOuts;
  183. float* freewheel;
  184. float* paramsLast;
  185. float** paramsPtr;
  186. bool* paramsOut;
  187. const CarlaPlugin* plugin;
  188. Ports()
  189. : numAudioIns(0),
  190. numAudioOuts(0),
  191. numParams(0),
  192. audioIns(nullptr),
  193. audioOuts(nullptr),
  194. freewheel(nullptr),
  195. paramsLast(nullptr),
  196. paramsPtr(nullptr),
  197. paramsOut(nullptr),
  198. plugin(nullptr) {}
  199. ~Ports()
  200. {
  201. if (audioIns != nullptr)
  202. {
  203. delete[] audioIns;
  204. audioIns = nullptr;
  205. }
  206. if (audioOuts != nullptr)
  207. {
  208. delete[] audioOuts;
  209. audioOuts = nullptr;
  210. }
  211. if (paramsLast != nullptr)
  212. {
  213. delete[] paramsLast;
  214. paramsLast = nullptr;
  215. }
  216. if (paramsPtr != nullptr)
  217. {
  218. delete[] paramsPtr;
  219. paramsPtr = nullptr;
  220. }
  221. if (paramsOut != nullptr)
  222. {
  223. delete[] paramsOut;
  224. paramsOut = nullptr;
  225. }
  226. }
  227. void init(const CarlaPlugin* const pl)
  228. {
  229. plugin = pl;
  230. if ((numAudioIns = plugin->getAudioInCount()) > 0)
  231. {
  232. audioIns = new const float*[numAudioIns];
  233. for (uint32_t i=0; i < numAudioIns; ++i)
  234. audioIns[i] = nullptr;
  235. }
  236. if ((numAudioOuts = plugin->getAudioOutCount()) > 0)
  237. {
  238. audioOuts = new float*[numAudioOuts];
  239. for (uint32_t i=0; i < numAudioOuts; ++i)
  240. audioOuts[i] = nullptr;
  241. }
  242. if ((numParams = plugin->getParameterCount()) > 0)
  243. {
  244. paramsLast = new float[numParams];
  245. paramsPtr = new float*[numParams];
  246. paramsOut = new bool[numParams];
  247. for (uint32_t i=0; i < numParams; ++i)
  248. {
  249. paramsLast[i] = plugin->getParameterValue(i);
  250. paramsPtr [i] = nullptr;
  251. paramsOut [i] = plugin->isParameterOutput(i);
  252. }
  253. }
  254. }
  255. void connectPort(const uint32_t port, void* const dataLocation) noexcept
  256. {
  257. uint32_t index = 0;
  258. for (uint32_t i=0; i < numAudioIns; ++i)
  259. {
  260. if (port == index++)
  261. {
  262. audioIns[i] = (float*)dataLocation;
  263. return;
  264. }
  265. }
  266. for (uint32_t i=0; i < numAudioOuts; ++i)
  267. {
  268. if (port == index++)
  269. {
  270. audioOuts[i] = (float*)dataLocation;
  271. return;
  272. }
  273. }
  274. if (port == index++)
  275. {
  276. freewheel = (float*)dataLocation;
  277. return;
  278. }
  279. for (uint32_t i=0; i < numParams; ++i)
  280. {
  281. if (port == index++)
  282. {
  283. paramsPtr[i] = (float*)dataLocation;
  284. return;
  285. }
  286. }
  287. }
  288. void updateOutputs() noexcept
  289. {
  290. for (uint32_t i=0; i < numParams; ++i)
  291. {
  292. if (! paramsOut[i])
  293. continue;
  294. paramsLast[i] = plugin->getParameterValue(i);
  295. if (paramsPtr[i] != nullptr)
  296. *paramsPtr[i] = paramsLast[i];
  297. }
  298. }
  299. CARLA_DECLARE_NON_COPY_STRUCT(Ports);
  300. } fPorts;
  301. #define handlePtr ((CarlaEngineLV2Single*)handle)
  302. static void _engine_callback(void* handle, EngineCallbackOpcode action, uint pluginId, int value1, int value2, float value3, const char* valueStr)
  303. {
  304. handlePtr->engineCallback(action, pluginId, value1, value2, value3, valueStr);
  305. }
  306. #undef handlePtr
  307. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineLV2Single)
  308. };
  309. CARLA_BACKEND_END_NAMESPACE
  310. // ---------------------------------------------------------------------------------------------------------------------
  311. // LV2 plugin descriptor functions
  312. CARLA_BACKEND_USE_NAMESPACE
  313. static LV2_Handle lv2_instantiate(const LV2_Descriptor* lv2Descriptor, double sampleRate, const char* bundlePath, const LV2_Feature* const* features)
  314. {
  315. carla_stdout("lv2_instantiate(%p, %g, %s, %p)", lv2Descriptor, sampleRate, bundlePath, features);
  316. const LV2_Options_Option* options = nullptr;
  317. const LV2_URID_Map* uridMap = nullptr;
  318. const LV2_URID_Unmap* uridUnmap = nullptr;
  319. for (int i=0; features[i] != nullptr; ++i)
  320. {
  321. if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
  322. options = (const LV2_Options_Option*)features[i]->data;
  323. else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
  324. uridMap = (const LV2_URID_Map*)features[i]->data;
  325. else if (std::strcmp(features[i]->URI, LV2_URID__unmap) == 0)
  326. uridUnmap = (const LV2_URID_Unmap*)features[i]->data;
  327. }
  328. if (options == nullptr || uridMap == nullptr)
  329. {
  330. carla_stderr("Host doesn't provide option or urid-map features");
  331. return nullptr;
  332. }
  333. uint32_t bufferSize = 0;
  334. for (int i=0; options[i].key != 0; ++i)
  335. {
  336. if (uridUnmap != nullptr) {
  337. carla_stdout("Host option %i:\"%s\"", i, uridUnmap->unmap(uridUnmap->handle, options[i].key));
  338. }
  339. if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
  340. {
  341. if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
  342. {
  343. const int value(*(const int*)options[i].value);
  344. CARLA_SAFE_ASSERT_CONTINUE(value > 0);
  345. bufferSize = static_cast<uint32_t>(value);
  346. }
  347. else
  348. {
  349. carla_stderr("Host provides nominalBlockLength but has wrong value type");
  350. }
  351. break;
  352. }
  353. if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
  354. {
  355. if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
  356. {
  357. const int value(*(const int*)options[i].value);
  358. CARLA_SAFE_ASSERT_CONTINUE(value > 0);
  359. bufferSize = static_cast<uint32_t>(value);
  360. }
  361. else
  362. {
  363. carla_stderr("Host provides maxBlockLength but has wrong value type");
  364. }
  365. // no break, continue in case host supports nominalBlockLength
  366. }
  367. }
  368. if (bufferSize == 0)
  369. {
  370. carla_stderr("Host doesn't provide bufferSize feature");
  371. return nullptr;
  372. }
  373. return new CarlaEngineLV2Single(bufferSize, sampleRate, bundlePath, uridMap);
  374. }
  375. #define instancePtr ((CarlaEngineLV2Single*)instance)
  376. static void lv2_connect_port(LV2_Handle instance, uint32_t port, void* dataLocation)
  377. {
  378. instancePtr->lv2_connect_port(port, dataLocation);
  379. }
  380. static void lv2_activate(LV2_Handle instance)
  381. {
  382. carla_stdout("lv2_activate(%p)", instance);
  383. instancePtr->lv2_activate();
  384. }
  385. static void lv2_run(LV2_Handle instance, uint32_t sampleCount)
  386. {
  387. instancePtr->lv2_run(sampleCount);
  388. }
  389. static void lv2_deactivate(LV2_Handle instance)
  390. {
  391. carla_stdout("lv2_deactivate(%p)", instance);
  392. instancePtr->lv2_deactivate();
  393. }
  394. static void lv2_cleanup(LV2_Handle instance)
  395. {
  396. carla_stdout("lv2_cleanup(%p)", instance);
  397. delete instancePtr;
  398. }
  399. static const void* lv2_extension_data(const char* uri)
  400. {
  401. carla_stdout("lv2_extension_data(\"%s\")", uri);
  402. return nullptr;
  403. }
  404. #undef instancePtr
  405. // ---------------------------------------------------------------------------------------------------------------------
  406. // Startup code
  407. CARLA_EXPORT
  408. const LV2_Descriptor* lv2_descriptor(uint32_t index)
  409. {
  410. carla_stdout("lv2_descriptor(%i)", index);
  411. if (index != 0)
  412. return nullptr;
  413. static CarlaString ret;
  414. if (ret.isEmpty())
  415. {
  416. using namespace juce;
  417. const File file(File::getSpecialLocation(File::currentExecutableFile).withFileExtension("ttl"));
  418. ret = String("file://" + file.getFullPathName()).toRawUTF8();
  419. }
  420. static const LV2_Descriptor desc = {
  421. /* URI */ ret.buffer(),
  422. /* instantiate */ lv2_instantiate,
  423. /* connect_port */ lv2_connect_port,
  424. /* activate */ lv2_activate,
  425. /* run */ lv2_run,
  426. /* deactivate */ lv2_deactivate,
  427. /* cleanup */ lv2_cleanup,
  428. /* extension_data */ lv2_extension_data
  429. };
  430. return &desc;
  431. }
  432. CARLA_EXPORT
  433. const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index)
  434. {
  435. carla_stdout("lv2ui_descriptor(%i)", index);
  436. return nullptr;
  437. }
  438. // ---------------------------------------------------------------------------------------------------------------------