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.

666 lines
20KB

  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. #ifdef JACKBRIDGE_EXPORT
  29. // -------------------------------------------------------------------
  30. bool jackbridge_is_ok() noexcept
  31. {
  32. return true;
  33. }
  34. #endif
  35. // -------------------------------------------------------------------
  36. CARLA_BACKEND_START_NAMESPACE
  37. #if 0
  38. } // Fix editor indentation
  39. #endif
  40. // -------------------------------------------------------------------
  41. template<typename T>
  42. bool jackbridge_shm_map2(char* shm, T*& value)
  43. {
  44. value = (T*)jackbridge_shm_map(shm, sizeof(T));
  45. return (value != nullptr);
  46. }
  47. struct BridgeAudioPool {
  48. CarlaString filename;
  49. float* data;
  50. char shm[32];
  51. BridgeAudioPool()
  52. : data(nullptr)
  53. {
  54. carla_zeroChar(shm, 32);
  55. jackbridge_shm_init(shm);
  56. }
  57. ~BridgeAudioPool()
  58. {
  59. // should be cleared by now
  60. CARLA_ASSERT(data == nullptr);
  61. clear();
  62. }
  63. bool attach()
  64. {
  65. jackbridge_shm_attach(shm, filename);
  66. return jackbridge_shm_is_valid(shm);
  67. }
  68. void clear()
  69. {
  70. filename.clear();
  71. data = nullptr;
  72. if (jackbridge_shm_is_valid(shm))
  73. jackbridge_shm_close(shm);
  74. }
  75. CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
  76. };
  77. struct BridgeControl : public CarlaRingBuffer<StackBuffer> {
  78. CarlaString filename;
  79. BridgeShmControl* data;
  80. char shm[32];
  81. BridgeControl()
  82. : CarlaRingBuffer<StackBuffer>(),
  83. data(nullptr)
  84. {
  85. carla_zeroChar(shm, 32);
  86. jackbridge_shm_init(shm);
  87. }
  88. ~BridgeControl()
  89. {
  90. // should be cleared by now
  91. CARLA_ASSERT(data == nullptr);
  92. clear();
  93. }
  94. bool attach()
  95. {
  96. jackbridge_shm_attach(shm, filename);
  97. return jackbridge_shm_is_valid(shm);
  98. }
  99. void clear()
  100. {
  101. filename.clear();
  102. data = nullptr;
  103. if (jackbridge_shm_is_valid(shm))
  104. jackbridge_shm_close(shm);
  105. }
  106. bool mapData()
  107. {
  108. CARLA_ASSERT(data == nullptr);
  109. if (jackbridge_shm_map2<BridgeShmControl>(shm, data))
  110. {
  111. setRingBuffer(&data->buffer, false);
  112. return true;
  113. }
  114. return false;
  115. }
  116. PluginBridgeOpcode readOpcode()
  117. {
  118. return static_cast<PluginBridgeOpcode>(readInt());
  119. }
  120. CARLA_DECLARE_NON_COPY_STRUCT(BridgeControl)
  121. };
  122. struct BridgeTime {
  123. CarlaString filename;
  124. BridgeTimeInfo* info;
  125. char shm[32];
  126. BridgeTime()
  127. : info(nullptr)
  128. {
  129. carla_zeroChar(shm, 32);
  130. jackbridge_shm_init(shm);
  131. }
  132. ~BridgeTime()
  133. {
  134. // should be cleared by now
  135. CARLA_ASSERT(info == nullptr);
  136. clear();
  137. }
  138. bool attach()
  139. {
  140. jackbridge_shm_attach(shm, filename);
  141. return jackbridge_shm_is_valid(shm);
  142. }
  143. void clear()
  144. {
  145. filename.clear();
  146. info = nullptr;
  147. if (jackbridge_shm_is_valid(shm))
  148. jackbridge_shm_close(shm);
  149. }
  150. bool mapData()
  151. {
  152. CARLA_ASSERT(info == nullptr);
  153. return jackbridge_shm_map2<BridgeTimeInfo>(shm, info);
  154. }
  155. CARLA_DECLARE_NON_COPY_STRUCT(BridgeTime)
  156. };
  157. // -------------------------------------------------------------------
  158. class CarlaEngineBridge : public CarlaEngine,
  159. public CarlaThread
  160. {
  161. public:
  162. CarlaEngineBridge(const char* const audioBaseName, const char* const controlBaseName, const char* const timeBaseName)
  163. : CarlaEngine(),
  164. CarlaThread("CarlaEngineBridge"),
  165. fIsRunning(false),
  166. fNextUIState(-1)
  167. {
  168. carla_stdout("CarlaEngineBridge::CarlaEngineBridge(%s, %s, %s)", audioBaseName, controlBaseName, timeBaseName);
  169. fShmAudioPool.filename = "/carla-bridge_shm_";
  170. fShmAudioPool.filename += audioBaseName;
  171. fShmControl.filename = "/carla-bridge_shc_";
  172. fShmControl.filename += controlBaseName;
  173. fShmTime.filename = "/carla-bridge_sht_";
  174. fShmTime.filename += timeBaseName;
  175. }
  176. ~CarlaEngineBridge() noexcept override
  177. {
  178. carla_debug("CarlaEngineBridge::~CarlaEngineBridge()");
  179. }
  180. // -------------------------------------
  181. // CarlaEngine virtual calls
  182. bool init(const char* const clientName) override
  183. {
  184. carla_debug("CarlaEngineBridge::init(\"%s\")", clientName);
  185. // SHM Audio Pool
  186. {
  187. if (! fShmAudioPool.attach())
  188. {
  189. carla_stdout("Failed to open or create shared memory file #1");
  190. return false;
  191. }
  192. }
  193. // SHM Control
  194. {
  195. if (! fShmControl.attach())
  196. {
  197. carla_stdout("Failed to open or create shared memory file #2");
  198. // clear
  199. fShmAudioPool.clear();
  200. return false;
  201. }
  202. if (! fShmControl.mapData())
  203. {
  204. carla_stdout("Failed to map shared memory file #2");
  205. // clear
  206. fShmControl.clear();
  207. fShmAudioPool.clear();
  208. return false;
  209. }
  210. }
  211. // SHM Transport
  212. {
  213. if (! fShmTime.attach())
  214. {
  215. carla_stdout("Failed to open or create shared memory file #3");
  216. // clear
  217. fShmControl.clear();
  218. fShmAudioPool.clear();
  219. return false;
  220. }
  221. if (! fShmTime.mapData())
  222. {
  223. carla_stdout("Failed to map shared memory file #3");
  224. // clear
  225. fShmTime.clear();
  226. fShmControl.clear();
  227. fShmAudioPool.clear();
  228. return false;
  229. }
  230. }
  231. // Read values from memory
  232. PluginBridgeOpcode opcode;
  233. opcode = fShmControl.readOpcode();
  234. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeOpcodeNull, opcode);
  235. const uint32_t stackBufferSize = fShmControl.readUInt();
  236. CARLA_SAFE_ASSERT_INT2(stackBufferSize == sizeof(StackBuffer), stackBufferSize, sizeof(StackBuffer));
  237. const uint32_t shmStructSize = fShmControl.readUInt();
  238. CARLA_SAFE_ASSERT_INT2(shmStructSize == sizeof(BridgeShmControl), shmStructSize, sizeof(BridgeShmControl));
  239. const uint32_t timeStructSize = fShmControl.readUInt();
  240. CARLA_SAFE_ASSERT_INT2(timeStructSize == sizeof(BridgeTimeInfo), timeStructSize, sizeof(BridgeTimeInfo));
  241. opcode = fShmControl.readOpcode();
  242. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeOpcodeSetBufferSize, opcode);
  243. pData->bufferSize = fShmControl.readUInt();
  244. opcode = fShmControl.readOpcode();
  245. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeOpcodeSetSampleRate, opcode);
  246. pData->sampleRate = fShmControl.readFloat();
  247. carla_stdout("Carla Client Info:");
  248. carla_stdout(" BufferSize: %i", pData->bufferSize);
  249. carla_stdout(" SampleRate: %f", pData->sampleRate);
  250. carla_stdout(" sizeof(StackBuffer): %i/" P_SIZE, stackBufferSize, sizeof(StackBuffer));
  251. carla_stdout(" sizeof(BridgeShmControl): %i/" P_SIZE, shmStructSize, sizeof(BridgeShmControl));
  252. carla_stdout(" sizeof(BridgeTimeInfo): %i/" P_SIZE, timeStructSize, sizeof(BridgeTimeInfo));
  253. CarlaThread::startThread();
  254. CarlaEngine::init(clientName);
  255. return true;
  256. }
  257. bool close() override
  258. {
  259. carla_debug("CarlaEnginePlugin::close()");
  260. CarlaEngine::close();
  261. CarlaThread::stopThread(6000);
  262. fShmTime.clear();
  263. fShmControl.clear();
  264. fShmAudioPool.clear();
  265. return true;
  266. }
  267. bool isRunning() const noexcept override
  268. {
  269. return fIsRunning;
  270. }
  271. bool isOffline() const noexcept override
  272. {
  273. return false;
  274. }
  275. EngineType getType() const noexcept override
  276. {
  277. return kEngineTypeBridge;
  278. }
  279. const char* getCurrentDriverName() const noexcept
  280. {
  281. return "Bridge";
  282. }
  283. void idle() noexcept override
  284. {
  285. CarlaEngine::idle();
  286. if (fNextUIState == -1 || ! fIsRunning)
  287. return;
  288. try {
  289. carla_show_custom_ui(0, bool(fNextUIState));
  290. } CARLA_SAFE_EXCEPTION("bridge show_custom_ui");
  291. fNextUIState = -1;
  292. }
  293. // -------------------------------------
  294. // CarlaThread virtual calls
  295. void run() override
  296. {
  297. fIsRunning = true;
  298. // TODO - set RT permissions
  299. carla_debug("CarlaEngineBridge::run()");
  300. for (; ! shouldThreadExit();)
  301. {
  302. if (! jackbridge_sem_timedwait(&fShmControl.data->runServer, 5))
  303. {
  304. if (errno == ETIMEDOUT)
  305. {
  306. fIsRunning = false;
  307. signalThreadShouldExit();
  308. return;
  309. }
  310. }
  311. for (; fShmControl.isDataAvailableForReading();)
  312. {
  313. const PluginBridgeOpcode opcode(fShmControl.readOpcode());
  314. if (opcode != kPluginBridgeOpcodeProcess) {
  315. carla_debug("CarlaEngineBridge::run() - got opcode: %s", PluginBridgeOpcode2str(opcode));
  316. }
  317. switch (opcode)
  318. {
  319. case kPluginBridgeOpcodeNull:
  320. break;
  321. case kPluginBridgeOpcodeSetAudioPool: {
  322. const int64_t poolSize(fShmControl.readLong());
  323. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  324. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
  325. break;
  326. }
  327. case kPluginBridgeOpcodeSetBufferSize: {
  328. const uint32_t bufferSize(fShmControl.readUInt());
  329. bufferSizeChanged(bufferSize);
  330. break;
  331. }
  332. case kPluginBridgeOpcodeSetSampleRate: {
  333. const float sampleRate(fShmControl.readFloat());
  334. sampleRateChanged(sampleRate);
  335. break;
  336. }
  337. case kPluginBridgeOpcodeSetParameterRt:
  338. case kPluginBridgeOpcodeSetParameterNonRt:{
  339. const int32_t index(fShmControl.readInt());
  340. const float value(fShmControl.readFloat());
  341. CarlaPlugin* const plugin(getPluginUnchecked(0));
  342. if (plugin != nullptr && plugin->isEnabled())
  343. {
  344. if (index == PARAMETER_ACTIVE)
  345. {
  346. plugin->setActive((value > 0.0f), false, false);
  347. break;
  348. }
  349. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  350. plugin->setParameterValue(static_cast<uint32_t>(index), value, (opcode == kPluginBridgeOpcodeSetParameterNonRt), false, false);
  351. }
  352. break;
  353. }
  354. case kPluginBridgeOpcodeSetProgram: {
  355. const int32_t index(fShmControl.readInt());
  356. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  357. CarlaPlugin* const plugin(getPluginUnchecked(0));
  358. if (plugin != nullptr && plugin->isEnabled())
  359. {
  360. plugin->setProgram(index, false, false, false);
  361. //plugin->postponeRtEvent(kPluginPostRtEventProgramChange, index, 0, 0.0f);
  362. }
  363. break;
  364. }
  365. case kPluginBridgeOpcodeSetMidiProgram: {
  366. const int32_t index(fShmControl.readInt());
  367. CARLA_SAFE_ASSERT_BREAK(index >= 0);
  368. CarlaPlugin* const plugin(getPluginUnchecked(0));
  369. if (plugin != nullptr && plugin->isEnabled())
  370. {
  371. plugin->setMidiProgram(index, false, false, false);
  372. //plugin->postponeRtEvent(kPluginPostRtEventMidiProgramChange, index, 0, 0.0f);
  373. }
  374. break;
  375. }
  376. case kPluginBridgeOpcodePrepareForSave: {
  377. carla_prepare_for_save(0);
  378. for (uint32_t i=0, count=carla_get_custom_data_count(0); i<count; ++i)
  379. {
  380. const CarlaBackend::CustomData* const cdata(carla_get_custom_data(0, i));
  381. CARLA_SAFE_ASSERT_CONTINUE(cdata != nullptr);
  382. oscSend_bridge_set_custom_data(cdata->type, cdata->key, cdata->value);
  383. }
  384. //if (fPlugin->getOptionsEnabled() & CarlaBackend::PLUGIN_OPTION_USE_CHUNKS)
  385. {
  386. //if (const char* const chunkData = carla_get_chunk_data(0))
  387. {
  388. #if 0
  389. QString filePath;
  390. filePath = QDir::tempPath();
  391. #ifdef Q_OS_WIN
  392. filePath += "\\.CarlaChunk_";
  393. #else
  394. filePath += "/.CarlaChunk_";
  395. #endif
  396. filePath += fPlugin->getName();
  397. QFile file(filePath);
  398. if (file.open(QIODevice::WriteOnly))
  399. {
  400. QByteArray chunk((const char*)data, dataSize);
  401. file.write(chunk);
  402. file.close();
  403. fEngine->oscSend_bridge_set_chunk_data(filePath.toUtf8().constData());
  404. }
  405. #endif
  406. }
  407. }
  408. carla_stdout("-----------------------------------------------------, got prepare for save");
  409. oscSend_bridge_configure(CARLA_BRIDGE_MSG_SAVED, "");
  410. break;
  411. }
  412. case kPluginBridgeOpcodeMidiEvent: {
  413. const int64_t time(fShmControl.readLong());
  414. const int32_t size(fShmControl.readInt());
  415. CARLA_SAFE_ASSERT_BREAK(time >= 0);
  416. CARLA_SAFE_ASSERT_BREAK(size > 0 && size <= 4);
  417. uint8_t data[size];
  418. for (int32_t i=0; i < size; ++i)
  419. data[i] = fShmControl.readByte();
  420. CARLA_SAFE_ASSERT_BREAK(pData->events.in != nullptr);
  421. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  422. {
  423. EngineEvent& event(pData->events.in[i]);
  424. if (event.type != kEngineEventTypeNull)
  425. continue;
  426. event.fillFromMidiData(static_cast<uint8_t>(size), data);
  427. break;
  428. }
  429. break;
  430. }
  431. case kPluginBridgeOpcodeProcess: {
  432. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  433. CarlaPlugin* const plugin(getPluginUnchecked(0));
  434. BridgeTimeInfo* const bridgeInfo(fShmTime.info);
  435. CARLA_SAFE_ASSERT_BREAK(bridgeInfo != nullptr);
  436. if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(true)) // FIXME - always lock?
  437. {
  438. const uint32_t inCount(plugin->getAudioInCount());
  439. const uint32_t outCount(plugin->getAudioOutCount());
  440. float* inBuffer[inCount];
  441. float* outBuffer[outCount];
  442. for (uint32_t i=0; i < inCount; ++i)
  443. inBuffer[i] = fShmAudioPool.data + i*pData->bufferSize;
  444. for (uint32_t i=0; i < outCount; ++i)
  445. outBuffer[i] = fShmAudioPool.data + (i+inCount)*pData->bufferSize;
  446. EngineTimeInfo& timeInfo(pData->timeInfo);
  447. timeInfo.playing = bridgeInfo->playing;
  448. timeInfo.frame = bridgeInfo->frame;
  449. timeInfo.usecs = bridgeInfo->usecs;
  450. timeInfo.valid = bridgeInfo->valid;
  451. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  452. {
  453. timeInfo.bbt.bar = bridgeInfo->bar;
  454. timeInfo.bbt.beat = bridgeInfo->beat;
  455. timeInfo.bbt.tick = bridgeInfo->tick;
  456. timeInfo.bbt.beatsPerBar = bridgeInfo->beatsPerBar;
  457. timeInfo.bbt.beatType = bridgeInfo->beatType;
  458. timeInfo.bbt.ticksPerBeat = bridgeInfo->ticksPerBeat;
  459. timeInfo.bbt.beatsPerMinute = bridgeInfo->beatsPerMinute;
  460. timeInfo.bbt.barStartTick = bridgeInfo->barStartTick;
  461. }
  462. plugin->initBuffers();
  463. plugin->process(inBuffer, outBuffer, pData->bufferSize);
  464. plugin->unlock();
  465. }
  466. // clear buffer
  467. CARLA_SAFE_ASSERT_BREAK(pData->events.in != nullptr);
  468. if (pData->events.in[0].type != kEngineEventTypeNull)
  469. carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount);
  470. break;
  471. }
  472. case kPluginBridgeOpcodeShowUI:
  473. carla_stdout("-----------------------------------------------------, got SHOW UI");
  474. fNextUIState = 1;
  475. break;
  476. case kPluginBridgeOpcodeHideUI:
  477. carla_stdout("-----------------------------------------------------, got HIDE UI");
  478. fNextUIState = 0;
  479. break;
  480. case kPluginBridgeOpcodeQuit:
  481. signalThreadShouldExit();
  482. fIsRunning = false;
  483. break;
  484. default:
  485. carla_stderr2("Unhandled Plugin opcode %i", opcode);
  486. break;
  487. }
  488. }
  489. if (! jackbridge_sem_post(&fShmControl.data->runClient))
  490. carla_stderr2("Could not post to semaphore");
  491. }
  492. fIsRunning = false;
  493. callback(ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);
  494. }
  495. private:
  496. BridgeAudioPool fShmAudioPool;
  497. BridgeControl fShmControl;
  498. BridgeTime fShmTime;
  499. volatile bool fIsRunning;
  500. volatile int fNextUIState;
  501. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge)
  502. };
  503. // -----------------------------------------
  504. CarlaEngine* CarlaEngine::newBridge(const char* const audioBaseName, const char* const controlBaseName, const char* const timeBaseName)
  505. {
  506. return new CarlaEngineBridge(audioBaseName, controlBaseName, timeBaseName);
  507. }
  508. CARLA_BACKEND_END_NAMESPACE
  509. // -----------------------------------------------------------------------
  510. #if defined(CARLA_OS_WIN) && ! defined(__WINE__)
  511. extern "C" __declspec (dllexport)
  512. #else
  513. extern "C" __attribute__ ((visibility("default")))
  514. #endif
  515. void carla_register_native_plugin_carla();
  516. void carla_register_native_plugin_carla(){}
  517. // -----------------------------------------------------------------------