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.

460 lines
13KB

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