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.

482 lines
14KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2014 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. #ifndef BUILD_BRIDGE
  18. # error This file should not be compiled if not building bridge
  19. #endif
  20. #include "CarlaEngineInternal.hpp"
  21. #include "CarlaPlugin.hpp"
  22. #include "CarlaBackendUtils.hpp"
  23. #include "CarlaBridgeUtils.hpp"
  24. #include "CarlaMIDI.h"
  25. #include "jackbridge/JackBridge.hpp"
  26. #include <cerrno>
  27. #include <ctime>
  28. CARLA_BACKEND_START_NAMESPACE
  29. #if 0
  30. } // Fix editor indentation
  31. #endif
  32. // -------------------------------------------------------------------
  33. template<typename T>
  34. bool jackbridge_shm_map2(char* shm, T*& value)
  35. {
  36. value = (T*)jackbridge_shm_map(shm, sizeof(T));
  37. return (value != nullptr);
  38. }
  39. struct BridgeAudioPool {
  40. CarlaString filename;
  41. float* data;
  42. char shm[32];
  43. BridgeAudioPool()
  44. : data(nullptr)
  45. {
  46. carla_zeroChar(shm, 32);
  47. jackbridge_shm_init(shm);
  48. }
  49. ~BridgeAudioPool()
  50. {
  51. // should be cleared by now
  52. CARLA_ASSERT(data == nullptr);
  53. clear();
  54. }
  55. bool attach()
  56. {
  57. jackbridge_shm_attach(shm, filename.getBuffer());
  58. return jackbridge_shm_is_valid(shm);
  59. }
  60. void clear()
  61. {
  62. filename.clear();
  63. data = nullptr;
  64. if (jackbridge_shm_is_valid(shm))
  65. jackbridge_shm_close(shm);
  66. }
  67. };
  68. struct BridgeControl : public RingBufferControl<StackRingBuffer> {
  69. CarlaString filename;
  70. BridgeShmControl* data;
  71. char shm[32];
  72. BridgeControl()
  73. : RingBufferControl(nullptr),
  74. data(nullptr)
  75. {
  76. carla_zeroChar(shm, 32);
  77. jackbridge_shm_init(shm);
  78. }
  79. ~BridgeControl()
  80. {
  81. // should be cleared by now
  82. CARLA_ASSERT(data == nullptr);
  83. clear();
  84. }
  85. bool attach()
  86. {
  87. jackbridge_shm_attach(shm, filename.getBuffer());
  88. return jackbridge_shm_is_valid(shm);
  89. }
  90. void clear()
  91. {
  92. filename.clear();
  93. data = nullptr;
  94. if (jackbridge_shm_is_valid(shm))
  95. jackbridge_shm_close(shm);
  96. }
  97. bool mapData()
  98. {
  99. CARLA_ASSERT(data == nullptr);
  100. if (jackbridge_shm_map2<BridgeShmControl>(shm, data))
  101. {
  102. setRingBuffer(&data->ringBuffer, false);
  103. return true;
  104. }
  105. return false;
  106. }
  107. PluginBridgeOpcode readOpcode()
  108. {
  109. return static_cast<PluginBridgeOpcode>(readInt());
  110. }
  111. };
  112. // -------------------------------------------------------------------
  113. class CarlaEngineBridge : public CarlaEngine,
  114. public CarlaThread
  115. {
  116. public:
  117. CarlaEngineBridge(const char* const audioBaseName, const char* const controlBaseName)
  118. : CarlaEngine(),
  119. CarlaThread("CarlaEngineBridge"),
  120. fIsRunning(false)
  121. {
  122. carla_debug("CarlaEngineBridge::CarlaEngineBridge()");
  123. fShmAudioPool.filename = "/carla-bridge_shm_";
  124. fShmAudioPool.filename += audioBaseName;
  125. fShmControl.filename = "/carla-bridge_shc_";
  126. fShmControl.filename += controlBaseName;
  127. }
  128. ~CarlaEngineBridge() override
  129. {
  130. carla_debug("CarlaEngineBridge::~CarlaEngineBridge()");
  131. }
  132. // -------------------------------------
  133. // CarlaEngine virtual calls
  134. bool init(const char* const clientName) override
  135. {
  136. carla_debug("CarlaEngineBridge::init(\"%s\")", clientName);
  137. // SHM Audio Pool
  138. {
  139. if (! fShmAudioPool.attach())
  140. {
  141. carla_stdout("Failed to open or create shared memory file #1");
  142. return false;
  143. }
  144. }
  145. // SHM Control
  146. {
  147. if (! fShmControl.attach())
  148. {
  149. carla_stdout("Failed to open or create shared memory file #2");
  150. // clear
  151. fShmAudioPool.clear();
  152. return false;
  153. }
  154. if (! fShmControl.mapData())
  155. {
  156. carla_stdout("Failed to mmap shared memory file");
  157. // clear
  158. fShmControl.clear();
  159. fShmAudioPool.clear();
  160. return false;
  161. }
  162. }
  163. // Read values from memory
  164. PluginBridgeOpcode opcode;
  165. opcode = fShmControl.readOpcode();
  166. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeOpcodeNull, opcode);
  167. const uint32_t structSize = fShmControl.readUInt();
  168. CARLA_SAFE_ASSERT_INT2(structSize == sizeof(BridgeShmControl), structSize, sizeof(BridgeShmControl));
  169. carla_stderr("Struct Size: %i", structSize);
  170. opcode = fShmControl.readOpcode();
  171. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeOpcodeSetBufferSize, opcode);
  172. pData->bufferSize = fShmControl.readUInt();
  173. carla_stderr("BufferSize: %i", pData->bufferSize);
  174. opcode = fShmControl.readOpcode();
  175. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeOpcodeSetSampleRate, opcode);
  176. pData->sampleRate = fShmControl.readFloat();
  177. carla_stderr("SampleRate: %f", pData->sampleRate);
  178. CarlaThread::start();
  179. CarlaEngine::init(clientName);
  180. return true;
  181. }
  182. bool close() override
  183. {
  184. carla_debug("CarlaEnginePlugin::close()");
  185. CarlaEngine::close();
  186. CarlaThread::stop(6000);
  187. fShmControl.clear();
  188. fShmAudioPool.clear();
  189. return true;
  190. }
  191. bool isRunning() const noexcept override
  192. {
  193. return fIsRunning;
  194. }
  195. bool isOffline() const noexcept override
  196. {
  197. return false;
  198. }
  199. EngineType getType() const noexcept override
  200. {
  201. return kEngineTypeBridge;
  202. }
  203. const char* getCurrentDriverName() const noexcept
  204. {
  205. return "Bridge";
  206. }
  207. // -------------------------------------
  208. // CarlaThread virtual calls
  209. void run() override
  210. {
  211. fIsRunning = true;
  212. // TODO - set RT permissions
  213. carla_debug("CarlaEngineBridge::run()");
  214. for (; ! shouldExit();)
  215. {
  216. if (! jackbridge_sem_timedwait(&fShmControl.data->runServer, 5))
  217. {
  218. if (errno == ETIMEDOUT)
  219. {
  220. fIsRunning = false;
  221. signalShouldExit();
  222. return;
  223. }
  224. }
  225. for (; fShmControl.isDataAvailable();)
  226. {
  227. const PluginBridgeOpcode opcode(fShmControl.readOpcode());
  228. if (opcode != kPluginBridgeOpcodeProcess)
  229. {
  230. carla_debug("CarlaEngineBridge::run() - got opcode: %s", PluginBridgeOpcode2str(opcode));
  231. }
  232. switch (opcode)
  233. {
  234. case kPluginBridgeOpcodeNull:
  235. break;
  236. case kPluginBridgeOpcodeSetAudioPool: {
  237. const int64_t poolSize(fShmControl.readLong());
  238. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  239. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, size_t(poolSize));
  240. break;
  241. }
  242. case kPluginBridgeOpcodeSetBufferSize: {
  243. const uint32_t bufferSize(fShmControl.readUInt());
  244. bufferSizeChanged(bufferSize);
  245. break;
  246. }
  247. case kPluginBridgeOpcodeSetSampleRate: {
  248. const float sampleRate(fShmControl.readFloat());
  249. sampleRateChanged(sampleRate);
  250. break;
  251. }
  252. case kPluginBridgeOpcodeSetParameter: {
  253. const int32_t index(fShmControl.readInt());
  254. const float value(fShmControl.readFloat());
  255. CarlaPlugin* const plugin(getPluginUnchecked(0));
  256. if (plugin != nullptr && plugin->isEnabled())
  257. {
  258. plugin->setParameterValueByRealIndex(index, value, false, false, false);
  259. //if (index >= 0)
  260. // plugin->postponeRtEvent(kPluginPostRtEventParameterChange, index, 0, value);
  261. }
  262. break;
  263. }
  264. case kPluginBridgeOpcodeSetProgram: {
  265. const int32_t index(fShmControl.readInt());
  266. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  267. CarlaPlugin* const plugin(getPluginUnchecked(0));
  268. if (plugin != nullptr && plugin->isEnabled())
  269. {
  270. plugin->setProgram(index, false, false, false);
  271. //plugin->postponeRtEvent(kPluginPostRtEventProgramChange, index, 0, 0.0f);
  272. }
  273. break;
  274. }
  275. case kPluginBridgeOpcodeSetMidiProgram: {
  276. const int32_t index(fShmControl.readInt());
  277. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  278. CarlaPlugin* const plugin(getPluginUnchecked(0));
  279. if (plugin != nullptr && plugin->isEnabled())
  280. {
  281. plugin->setMidiProgram(index, false, false, false);
  282. //plugin->postponeRtEvent(kPluginPostRtEventMidiProgramChange, index, 0, 0.0f);
  283. }
  284. break;
  285. }
  286. case kPluginBridgeOpcodeMidiEvent: {
  287. const int64_t time(fShmControl.readLong());
  288. const int32_t size(fShmControl.readInt());
  289. CARLA_SAFE_ASSERT_BREAK(time >= 0);
  290. CARLA_SAFE_ASSERT_BREAK(size > 0 && size <= 4);
  291. uint8_t data[size];
  292. for (int32_t i=0; i < size; ++i)
  293. data[i] = static_cast<uint8_t>(fShmControl.readChar());
  294. CARLA_SAFE_ASSERT_BREAK(pData->bufEvents.in != nullptr);
  295. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  296. {
  297. EngineEvent& event(pData->bufEvents.in[i]);
  298. if (event.type != kEngineEventTypeNull)
  299. continue;
  300. event.fillFromMidiData(static_cast<uint8_t>(size), data);
  301. break;
  302. }
  303. break;
  304. }
  305. case kPluginBridgeOpcodeProcess: {
  306. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  307. CarlaPlugin* const plugin(getPluginUnchecked(0));
  308. if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(true)) // FIXME - always lock?
  309. {
  310. const uint32_t inCount(plugin->getAudioInCount());
  311. const uint32_t outCount(plugin->getAudioOutCount());
  312. float* inBuffer[inCount];
  313. float* outBuffer[outCount];
  314. for (uint32_t i=0; i < inCount; ++i)
  315. inBuffer[i] = fShmAudioPool.data + i*pData->bufferSize;
  316. for (uint32_t i=0; i < outCount; ++i)
  317. outBuffer[i] = fShmAudioPool.data + (i+inCount)*pData->bufferSize;
  318. plugin->initBuffers();
  319. plugin->process(inBuffer, outBuffer, pData->bufferSize);
  320. plugin->unlock();
  321. }
  322. // clear buffer
  323. CARLA_SAFE_ASSERT_BREAK(pData->bufEvents.in != nullptr);
  324. if (pData->bufEvents.in[0].type != kEngineEventTypeNull)
  325. carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kMaxEngineEventInternalCount);
  326. break;
  327. }
  328. case kPluginBridgeOpcodeQuit:
  329. signalShouldExit();
  330. fIsRunning = false;
  331. break;
  332. }
  333. }
  334. if (! jackbridge_sem_post(&fShmControl.data->runClient))
  335. carla_stderr2("Could not post to semaphore");
  336. }
  337. fIsRunning = false;
  338. }
  339. private:
  340. BridgeAudioPool fShmAudioPool;
  341. BridgeControl fShmControl;
  342. volatile bool fIsRunning;
  343. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge)
  344. };
  345. // -----------------------------------------
  346. CarlaEngine* CarlaEngine::newBridge(const char* const audioBaseName, const char* const controlBaseName)
  347. {
  348. return new CarlaEngineBridge(audioBaseName, controlBaseName);
  349. }
  350. CARLA_BACKEND_END_NAMESPACE
  351. // -----------------------------------------------------------------------
  352. // Extra stuff for linking purposes
  353. CARLA_BACKEND_START_NAMESPACE
  354. CarlaEngine* CarlaEngine::newRtAudio(const AudioApi) { return nullptr; }
  355. unsigned int CarlaEngine::getRtAudioApiCount() { return 0; }
  356. const char* CarlaEngine::getRtAudioApiName(const unsigned int) { return nullptr; }
  357. const char* const* CarlaEngine::getRtAudioApiDeviceNames(const unsigned int) { return nullptr; }
  358. const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const unsigned int, const char* const) { return nullptr; }
  359. #ifdef HAVE_JUCE
  360. CarlaEngine* CarlaEngine::newJuce(const AudioApi) { return nullptr; }
  361. unsigned int CarlaEngine::getJuceApiCount() { return 0; }
  362. const char* CarlaEngine::getJuceApiName(const unsigned int) { return nullptr; }
  363. const char* const* CarlaEngine::getJuceApiDeviceNames(const unsigned int) { return nullptr; }
  364. const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const unsigned int, const char* const) { return nullptr; }
  365. #endif
  366. CARLA_BACKEND_END_NAMESPACE
  367. // -----------------------------------------------------------------------
  368. #if defined(CARLA_OS_WIN) && ! defined(__WINE__)
  369. extern "C" __declspec (dllexport)
  370. #else
  371. extern "C" __attribute__ ((visibility("default")))
  372. #endif
  373. void carla_register_native_plugin_carla();
  374. void carla_register_native_plugin_carla(){}
  375. // -----------------------------------------------------------------------