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.

ReWirePlugin.cpp 32KB

10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  1. /*
  2. * Carla ReWire Plugin
  3. * Copyright (C) 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. #include "CarlaPluginInternal.hpp"
  18. #include "CarlaEngine.hpp"
  19. #ifdef WANT_REWIRE
  20. #include "CarlaLibUtils.hpp"
  21. #include "CarlaMathUtils.hpp"
  22. // -----------------------------------------------------
  23. CARLA_BACKEND_START_NAMESPACE
  24. #if 0
  25. }
  26. #endif
  27. // -----------------------------------------------------------------------
  28. // ReWire assumes sizeof(long) == 4
  29. typedef int32_t rlong;
  30. typedef uint32_t rulong;
  31. static_assert(sizeof(rlong) == 4, "Incorrect rlong size");
  32. static_assert(sizeof(rulong) == 4, "Incorrect rulong size");
  33. // rewire is not for linux, so for easy testing+development, we can skip this
  34. #ifndef CARLA_OS_LINUX
  35. static_assert(sizeof(long) == 4, "Incorrect long size");
  36. static_assert(sizeof(ulong) == 4, "Incorrect ulong size");
  37. static_assert(sizeof(long) == sizeof(rlong), "long size mismatch");
  38. static_assert(sizeof(ulong) == sizeof(rulong), "ulon size mismatch");
  39. #endif
  40. struct RwOpenInfo {
  41. rulong size1; // 16
  42. rulong size2; // 12
  43. rlong sampleRate;
  44. rlong bufferSize;
  45. };
  46. struct RwDevInfo {
  47. rulong size; // 8288
  48. char name[32];
  49. rlong channelCount; // max limited to 255
  50. char channelNames[256][32];
  51. rulong defaultChannels[8];
  52. rulong stereoPairs[4];
  53. rulong eventBufferSize;
  54. rlong version;
  55. };
  56. struct RwAudioInfo {
  57. rulong size; // 12
  58. rlong sampleRate;
  59. rlong bufferSize;
  60. };
  61. struct RwBusInfo {
  62. rulong size; // 40
  63. rulong channel;
  64. char name[32];
  65. };
  66. struct RwEventInfo {
  67. rulong size; // 132 FIXME?
  68. rulong bus[32];
  69. };
  70. struct RwEvent { // 24
  71. ushort type;
  72. uchar d1, d2;
  73. rulong s1, s2, s3, s4, s5;
  74. };
  75. struct RwEventBuffer {
  76. rulong size1; // 20
  77. rulong size2; // 24 (of RwEvent)
  78. rulong count;
  79. rulong maxCount;
  80. #ifndef CARLA_OS_LINUX // pointers on 64bit linux are size 8, skip this
  81. RwEvent* buf;
  82. #else
  83. rulong buf;
  84. #endif
  85. };
  86. struct RwAudioInInfo {
  87. rulong size; // 1116
  88. RwEventBuffer evBuf;
  89. rulong channels[8];
  90. #ifndef CARLA_OS_LINUX // pointers on 64bit linux are size 8, skip this
  91. float* audioBuf[256];
  92. #else
  93. rulong audioBuf[256];
  94. #endif
  95. rlong tickStart;
  96. rulong frames;
  97. rulong playMode;
  98. rulong tempo; // bpm
  99. rulong signNumerator;
  100. rulong signDenominator;
  101. rlong loopStartPos;
  102. rlong loopEndPos;
  103. rulong loopOn;
  104. };
  105. struct RwAudioOutInfo {
  106. rulong size; // 56
  107. RwEventBuffer evBuf;
  108. rulong channels[8];
  109. };
  110. static_assert(sizeof(RwOpenInfo) == 16, "Incorrect ReWire struct size");
  111. static_assert(sizeof(RwDevInfo) == 8288, "Incorrect ReWire struct size");
  112. static_assert(sizeof(RwAudioInfo) == 12, "Incorrect ReWire struct size");
  113. static_assert(sizeof(RwBusInfo) == 40, "Incorrect ReWire struct size");
  114. static_assert(sizeof(RwEventInfo) == 132, "Incorrect ReWire struct size");
  115. static_assert(sizeof(RwEvent) == 24, "Incorrect ReWire struct size");
  116. static_assert(sizeof(RwEventBuffer) == 20, "Incorrect ReWire struct size");
  117. static_assert(sizeof(RwAudioInInfo) == 1116, "Incorrect ReWire struct size");
  118. static_assert(sizeof(RwAudioOutInfo) == 56, "Incorrect ReWire struct size");
  119. // -----------------------------------------------------------------------
  120. typedef void (*Fn_RWDEFCloseDevice)();
  121. typedef void (*Fn_RWDEFDriveAudio)(RwAudioInInfo* in, RwAudioOutInfo* out);
  122. typedef void (*Fn_RWDEFGetDeviceInfo)(RwDevInfo* info);
  123. typedef void (*Fn_RWDEFGetDeviceNameAndVersion)(long* version, char* name);
  124. typedef void (*Fn_RWDEFGetEventBusInfo)(ushort index, RwBusInfo* info);
  125. typedef void (*Fn_RWDEFGetEventChannelInfo)(void* v1, void* v2);
  126. typedef void (*Fn_RWDEFGetEventControllerInfo)(void* v1, ushort index, void* v2);
  127. typedef void (*Fn_RWDEFGetEventInfo)(RwEventInfo* info);
  128. typedef void (*Fn_RWDEFGetEventNoteInfo)(void* v1, ushort index, void* v2);
  129. typedef void (*Fn_RWDEFIdle)();
  130. typedef char (*Fn_RWDEFIsCloseOK)();
  131. typedef char (*Fn_RWDEFIsPanelAppLaunched)();
  132. typedef int (*Fn_RWDEFLaunchPanelApp)();
  133. typedef int (*Fn_RWDEFOpenDevice)(RwOpenInfo* info);
  134. typedef int (*Fn_RWDEFQuitPanelApp)();
  135. typedef void (*Fn_RWDEFSetAudioInfo)(RwAudioInfo* info);
  136. // -----------------------------------------------------------------------------
  137. struct RewireBridge {
  138. void* lib;
  139. Fn_RWDEFCloseDevice RWDEFCloseDevice;
  140. Fn_RWDEFDriveAudio RWDEFDriveAudio;
  141. Fn_RWDEFGetDeviceInfo RWDEFGetDeviceInfo;
  142. Fn_RWDEFGetDeviceNameAndVersion RWDEFGetDeviceNameAndVersion;
  143. Fn_RWDEFGetEventBusInfo RWDEFGetEventBusInfo;
  144. Fn_RWDEFGetEventChannelInfo RWDEFGetEventChannelInfo;
  145. Fn_RWDEFGetEventControllerInfo RWDEFGetEventControllerInfo;
  146. Fn_RWDEFGetEventInfo RWDEFGetEventInfo;
  147. Fn_RWDEFGetEventNoteInfo RWDEFGetEventNoteInfo;
  148. Fn_RWDEFIdle RWDEFIdle;
  149. Fn_RWDEFIsCloseOK RWDEFIsCloseOK;
  150. Fn_RWDEFIsPanelAppLaunched RWDEFIsPanelAppLaunched;
  151. Fn_RWDEFLaunchPanelApp RWDEFLaunchPanelApp;
  152. Fn_RWDEFOpenDevice RWDEFOpenDevice;
  153. Fn_RWDEFQuitPanelApp RWDEFQuitPanelApp;
  154. Fn_RWDEFSetAudioInfo RWDEFSetAudioInfo;
  155. RewireBridge()
  156. : lib(nullptr),
  157. RWDEFCloseDevice(nullptr),
  158. RWDEFDriveAudio(nullptr),
  159. RWDEFGetDeviceInfo(nullptr),
  160. RWDEFGetDeviceNameAndVersion(nullptr),
  161. RWDEFGetEventBusInfo(nullptr),
  162. RWDEFGetEventChannelInfo(nullptr),
  163. RWDEFGetEventControllerInfo(nullptr),
  164. RWDEFGetEventInfo(nullptr),
  165. RWDEFGetEventNoteInfo(nullptr),
  166. RWDEFIdle(nullptr),
  167. RWDEFIsCloseOK(nullptr),
  168. RWDEFIsPanelAppLaunched(nullptr),
  169. RWDEFLaunchPanelApp(nullptr),
  170. RWDEFOpenDevice(nullptr),
  171. RWDEFQuitPanelApp(nullptr),
  172. RWDEFSetAudioInfo(nullptr) {}
  173. ~RewireBridge()
  174. {
  175. cleanup();
  176. }
  177. int init(const char* const filename)
  178. {
  179. CARLA_SAFE_ASSERT_RETURN(lib == nullptr, -2);
  180. CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', -2);
  181. lib = lib_open(filename);
  182. if (lib == nullptr)
  183. return -1;
  184. #define JOIN(a, b) a ## b
  185. #define LIB_SYMBOL(NAME) NAME = (Fn_##NAME)lib_symbol(lib, #NAME);
  186. //if (NAME == nullptr) cleanup(); return -2;
  187. LIB_SYMBOL(RWDEFCloseDevice)
  188. LIB_SYMBOL(RWDEFDriveAudio)
  189. LIB_SYMBOL(RWDEFGetDeviceInfo)
  190. LIB_SYMBOL(RWDEFGetDeviceNameAndVersion)
  191. LIB_SYMBOL(RWDEFGetEventBusInfo)
  192. LIB_SYMBOL(RWDEFGetEventChannelInfo)
  193. LIB_SYMBOL(RWDEFGetEventControllerInfo)
  194. LIB_SYMBOL(RWDEFGetEventInfo)
  195. LIB_SYMBOL(RWDEFGetEventNoteInfo)
  196. LIB_SYMBOL(RWDEFIdle)
  197. LIB_SYMBOL(RWDEFIsCloseOK)
  198. LIB_SYMBOL(RWDEFIsPanelAppLaunched)
  199. LIB_SYMBOL(RWDEFLaunchPanelApp)
  200. LIB_SYMBOL(RWDEFOpenDevice)
  201. LIB_SYMBOL(RWDEFQuitPanelApp)
  202. LIB_SYMBOL(RWDEFSetAudioInfo)
  203. #undef JOIN
  204. #undef LIB_SYMBOL
  205. return 0;
  206. }
  207. void cleanup()
  208. {
  209. if (lib != nullptr)
  210. {
  211. lib_close(lib);
  212. lib = nullptr;
  213. }
  214. RWDEFCloseDevice = nullptr;
  215. RWDEFDriveAudio = nullptr;
  216. RWDEFGetDeviceInfo = nullptr;
  217. RWDEFGetDeviceNameAndVersion = nullptr;
  218. RWDEFGetEventBusInfo = nullptr;
  219. RWDEFGetEventChannelInfo = nullptr;
  220. RWDEFGetEventControllerInfo = nullptr;
  221. RWDEFGetEventInfo = nullptr;
  222. RWDEFGetEventNoteInfo = nullptr;
  223. RWDEFIdle = nullptr;
  224. RWDEFIsCloseOK = nullptr;
  225. RWDEFIsPanelAppLaunched = nullptr;
  226. RWDEFLaunchPanelApp = nullptr;
  227. RWDEFOpenDevice = nullptr;
  228. RWDEFQuitPanelApp = nullptr;
  229. RWDEFSetAudioInfo = nullptr;
  230. }
  231. };
  232. // -----------------------------------------------------
  233. class ReWirePlugin : public CarlaPlugin
  234. {
  235. public:
  236. ReWirePlugin(CarlaEngine* const engine, const unsigned int id)
  237. : CarlaPlugin(engine, id),
  238. fIsOpen(false),
  239. fIsPanelLaunched(false),
  240. fLabel(nullptr)
  241. {
  242. carla_debug("ReWirePlugin::ReWirePlugin(%p, %i)", engine, id);
  243. carla_zeroStruct<RwAudioInInfo>(fRwAudioIn);
  244. fRwAudioIn.size = sizeof(RwAudioInInfo);
  245. carla_zeroStruct<RwAudioOutInfo>(fRwAudioOut);
  246. fRwAudioOut.size = sizeof(RwAudioOutInfo);
  247. }
  248. ~ReWirePlugin() override
  249. {
  250. carla_debug("ReWirePlugin::~ReWirePlugin()");
  251. // close panel
  252. if (fIsPanelLaunched)
  253. {
  254. fRw.RWDEFQuitPanelApp();
  255. fIsPanelLaunched = false;
  256. }
  257. pData->singleMutex.lock();
  258. pData->masterMutex.lock();
  259. if (pData->client != nullptr && pData->client->isActive())
  260. pData->client->deactivate();
  261. if (pData->active)
  262. {
  263. deactivate();
  264. pData->active = false;
  265. }
  266. if (fIsOpen)
  267. {
  268. for (; fRw.RWDEFIsCloseOK() == 0;)
  269. carla_msleep(2);
  270. fRw.RWDEFCloseDevice();
  271. fIsOpen = false;
  272. }
  273. if (fLabel != nullptr)
  274. {
  275. delete[] fLabel;
  276. fLabel = nullptr;
  277. }
  278. clearBuffers();
  279. }
  280. // -------------------------------------------------------------------
  281. // Information (base)
  282. PluginType getType() const noexcept override
  283. {
  284. return PLUGIN_REWIRE;
  285. }
  286. PluginCategory getCategory() const noexcept override
  287. {
  288. return PLUGIN_CATEGORY_SYNTH;
  289. }
  290. // -------------------------------------------------------------------
  291. // Information (count)
  292. // nothing
  293. // -------------------------------------------------------------------
  294. // Information (current data)
  295. int32_t getChunkData(void** const dataPtr) const noexcept override
  296. {
  297. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
  298. CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr, 0);
  299. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  300. // TODO
  301. return 0;
  302. }
  303. // -------------------------------------------------------------------
  304. // Information (per-plugin data)
  305. unsigned int getOptionsAvailable() const noexcept override
  306. {
  307. unsigned int options = 0x0;
  308. if (getMidiInCount() > 0)
  309. {
  310. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  311. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  312. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  313. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  314. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  315. }
  316. return options;
  317. }
  318. float getParameterValue(const uint32_t parameterId) const noexcept override
  319. {
  320. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  321. // TODO
  322. return 0.0f;
  323. }
  324. void getLabel(char* const strBuf) const noexcept override
  325. {
  326. CARLA_SAFE_ASSERT_RETURN(fLabel != nullptr,)
  327. std::strcpy(strBuf, fLabel);
  328. }
  329. void getRealName(char* const strBuf) const noexcept override
  330. {
  331. CARLA_SAFE_ASSERT_RETURN(fLabel != nullptr,)
  332. std::strcpy(strBuf, fLabel);
  333. }
  334. void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
  335. {
  336. CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,);
  337. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  338. // TODO
  339. CarlaPlugin::getParameterName(parameterId, strBuf);
  340. }
  341. void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
  342. {
  343. CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,);
  344. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  345. // TODO
  346. CarlaPlugin::getParameterUnit(parameterId, strBuf);
  347. }
  348. // -------------------------------------------------------------------
  349. // Set data (state)
  350. // nothing
  351. // -------------------------------------------------------------------
  352. // Set data (internal stuff)
  353. // nothing
  354. // -------------------------------------------------------------------
  355. // Set data (plugin-specific stuff)
  356. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  357. {
  358. CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,);
  359. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  360. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  361. // TODO
  362. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  363. }
  364. void setChunkData(const char* const stringData) override
  365. {
  366. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
  367. CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,);
  368. CARLA_SAFE_ASSERT_RETURN(stringData != nullptr,);
  369. // TODO
  370. }
  371. // -------------------------------------------------------------------
  372. // Set ui stuff
  373. void showCustomUI(const bool yesNo) override
  374. {
  375. if (yesNo)
  376. {
  377. if (! fRw.RWDEFIsPanelAppLaunched())
  378. fRw.RWDEFLaunchPanelApp();
  379. fIsPanelLaunched = true;
  380. }
  381. else
  382. {
  383. if (fRw.RWDEFIsPanelAppLaunched())
  384. fRw.RWDEFQuitPanelApp();
  385. fIsPanelLaunched = false;
  386. }
  387. }
  388. void idle() override
  389. {
  390. CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,);
  391. fRw.RWDEFIdle();
  392. // check if panel has been closed
  393. if (fIsPanelLaunched && ! fRw.RWDEFIsPanelAppLaunched())
  394. {
  395. // FIXME
  396. //fIsPanelLaunched = true;
  397. //pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
  398. // static int counter = 0;
  399. //
  400. // if (counter % 1000)
  401. // {
  402. // carla_stdout("Panel is closed?");
  403. // }
  404. //
  405. // ++counter;
  406. }
  407. CarlaPlugin::idle();
  408. }
  409. // -------------------------------------------------------------------
  410. // Plugin state
  411. void reload() override
  412. {
  413. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  414. CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,);
  415. carla_debug("ReWirePlugin::reload() - start");
  416. const EngineProcessMode processMode(pData->engine->getProccessMode());
  417. // Safely disable plugin for reload
  418. const ScopedDisabler sd(this);
  419. if (pData->active)
  420. deactivate();
  421. clearBuffers();
  422. uint32_t aIns, aOuts, mIns, mOuts, params;
  423. bool needsCtrlIn, needsCtrlOut;
  424. needsCtrlIn = needsCtrlOut = false;
  425. RwDevInfo devInfo;
  426. carla_zeroStruct<RwDevInfo>(devInfo);
  427. devInfo.size = sizeof(RwDevInfo);
  428. fRw.RWDEFGetDeviceInfo(&devInfo);
  429. if (devInfo.channelCount > 0)
  430. aIns = aOuts = static_cast<uint32_t>(devInfo.channelCount);
  431. mIns = mOuts = 0; // TODO, should always be 1
  432. params = 0; // TODO?
  433. if (aIns > 0)
  434. {
  435. pData->audioIn.createNew(aIns);
  436. }
  437. if (aOuts > 0)
  438. {
  439. pData->audioOut.createNew(aOuts);
  440. needsCtrlIn = true;
  441. }
  442. if (params > 0)
  443. {
  444. pData->param.createNew(params, false);
  445. needsCtrlIn = true;
  446. }
  447. const uint portNameSize(pData->engine->getMaxPortNameSize());
  448. CarlaString portName;
  449. // Audio Ins
  450. for (uint32_t j=0; j < aIns; ++j)
  451. {
  452. portName.clear();
  453. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  454. {
  455. portName = pData->name;
  456. portName += ":";
  457. }
  458. portName += "i";
  459. portName += devInfo.channelNames[j];
  460. portName.truncate(portNameSize);
  461. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  462. pData->audioIn.ports[j].rindex = j;
  463. }
  464. // Audio Outs
  465. for (uint32_t j=0; j < aOuts; ++j)
  466. {
  467. portName.clear();
  468. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  469. {
  470. portName = pData->name;
  471. portName += ":";
  472. }
  473. portName += "o";
  474. portName += devInfo.channelNames[j];
  475. portName.truncate(portNameSize);
  476. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  477. pData->audioOut.ports[j].rindex = j;
  478. }
  479. if (needsCtrlIn)
  480. {
  481. portName.clear();
  482. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  483. {
  484. portName = pData->name;
  485. portName += ":";
  486. }
  487. portName += "events-in";
  488. portName.truncate(portNameSize);
  489. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  490. }
  491. if (needsCtrlOut)
  492. {
  493. portName.clear();
  494. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  495. {
  496. portName = pData->name;
  497. portName += ":";
  498. }
  499. portName += "events-out";
  500. portName.truncate(portNameSize);
  501. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  502. }
  503. // plugin hints
  504. pData->hints = 0x0;
  505. pData->hints |= PLUGIN_IS_SYNTH;
  506. pData->hints |= PLUGIN_HAS_CUSTOM_UI;
  507. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  508. pData->hints |= PLUGIN_CAN_DRYWET;
  509. if (aOuts > 0)
  510. pData->hints |= PLUGIN_CAN_VOLUME;
  511. if (aOuts >= 2 && aOuts % 2 == 0)
  512. pData->hints |= PLUGIN_CAN_BALANCE;
  513. // extra plugin hints
  514. pData->extraHints = 0x0;
  515. if (mIns > 0)
  516. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  517. if (mOuts > 0)
  518. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;
  519. if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0))
  520. pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
  521. bufferSizeChanged(pData->engine->getBufferSize());
  522. if (pData->active)
  523. activate();
  524. carla_debug("ReWirePlugin::reload() - end");
  525. }
  526. // -------------------------------------------------------------------
  527. // Plugin processing
  528. void activate() noexcept override
  529. {
  530. CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,);
  531. // TODO
  532. }
  533. void deactivate() noexcept override
  534. {
  535. CARLA_SAFE_ASSERT_RETURN(fRw.lib != nullptr,);
  536. // TODO
  537. }
  538. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override
  539. {
  540. // --------------------------------------------------------------------------------------------------------
  541. // Check if active
  542. if (! pData->active)
  543. {
  544. // disable any output sound
  545. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  546. FLOAT_CLEAR(outBuffer[i], frames);
  547. return;
  548. }
  549. // --------------------------------------------------------------------------------------------------------
  550. // Check if needs reset
  551. if (pData->needsReset)
  552. {
  553. if (pData->latency > 0)
  554. {
  555. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  556. FLOAT_CLEAR(pData->latencyBuffers[i], pData->latency);
  557. }
  558. pData->needsReset = false;
  559. }
  560. // --------------------------------------------------------------------------------------------------------
  561. // Set TimeInfo
  562. const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
  563. //fRwAudioIn.playMode; // ???
  564. //fRwAudioIn.frames = timeInfo.frame; // not sure if buf or tranport frames
  565. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  566. {
  567. double ppqBar = double(timeInfo.bbt.bar - 1) * timeInfo.bbt.beatsPerBar;
  568. double ppqBeat = double(timeInfo.bbt.beat - 1);
  569. double ppqTick = double(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat;
  570. // PPQ Pos, ???
  571. fRwAudioIn.tickStart = static_cast<rlong>(ppqBar + ppqBeat + ppqTick);
  572. // Tempo
  573. fRwAudioIn.tempo = static_cast<rulong>(timeInfo.bbt.beatsPerMinute);
  574. // Bars
  575. //fTimeInfo.barStartPos = ppqBar;
  576. // Time Signature
  577. fRwAudioIn.signNumerator = static_cast<rulong>(timeInfo.bbt.beatsPerBar);
  578. fRwAudioIn.signDenominator = static_cast<rulong>(timeInfo.bbt.beatType);
  579. }
  580. else
  581. {
  582. fRwAudioIn.tickStart = 0;
  583. fRwAudioIn.tempo = 120;
  584. fRwAudioIn.signNumerator = 4;
  585. fRwAudioIn.signDenominator = 4;
  586. }
  587. // --------------------------------------------------------------------------------------------------------
  588. // Plugin processing (no events)
  589. {
  590. processSingle(inBuffer, outBuffer, frames, 0);
  591. } // End of Plugin processing (no events)
  592. }
  593. bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset)
  594. {
  595. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  596. if (pData->audioIn.count > 0)
  597. {
  598. CARLA_SAFE_ASSERT_RETURN(inBuffer != nullptr, false);
  599. }
  600. if (pData->audioOut.count > 0)
  601. {
  602. CARLA_SAFE_ASSERT_RETURN(outBuffer != nullptr, false);
  603. }
  604. // --------------------------------------------------------------------------------------------------------
  605. // Try lock, silence otherwise
  606. if (pData->engine->isOffline())
  607. {
  608. pData->singleMutex.lock();
  609. }
  610. else if (! pData->singleMutex.tryLock())
  611. {
  612. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  613. {
  614. for (uint32_t k=0; k < frames; ++k)
  615. outBuffer[i][k+timeOffset] = 0.0f;
  616. }
  617. return false;
  618. }
  619. // --------------------------------------------------------------------------------------------------------
  620. // Set audio buffers
  621. //rulong channels[8];
  622. fRwAudioIn.frames = frames;
  623. #ifndef CARLA_OS_LINUX
  624. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  625. {
  626. fRwAudioIn.audioBuf[i] = outBuffer[i]+timeOffset;
  627. FLOAT_COPY(fRwAudioIn.audioBuf[i], inBuffer[i]+timeOffset, frames);
  628. }
  629. #endif
  630. // --------------------------------------------------------------------------------------------------------
  631. // Run plugin
  632. fRw.RWDEFDriveAudio(&fRwAudioIn, &fRwAudioOut);
  633. #ifndef BUILD_BRIDGE
  634. // --------------------------------------------------------------------------------------------------------
  635. // Post-processing (dry/wet, volume and balance)
  636. {
  637. const bool doVolume = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && pData->postProc.volume != 1.0f;
  638. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && pData->postProc.dryWet != 1.0f;
  639. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && (pData->postProc.balanceLeft != -1.0f || pData->postProc.balanceRight != 1.0f);
  640. bool isPair;
  641. float bufValue, oldBufLeft[doBalance ? frames : 1];
  642. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  643. {
  644. // Dry/Wet
  645. if (doDryWet)
  646. {
  647. for (uint32_t k=0; k < frames; ++k)
  648. {
  649. bufValue = inBuffer[(pData->audioIn.count == 1) ? 0 : i][k+timeOffset];
  650. outBuffer[i][k+timeOffset] = (outBuffer[i][k+timeOffset] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  651. }
  652. }
  653. // Balance
  654. if (doBalance)
  655. {
  656. isPair = (i % 2 == 0);
  657. if (isPair)
  658. {
  659. CARLA_ASSERT(i+1 < pData->audioOut.count);
  660. FLOAT_COPY(oldBufLeft, outBuffer[i]+timeOffset, frames);
  661. }
  662. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  663. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  664. for (uint32_t k=0; k < frames; ++k)
  665. {
  666. if (isPair)
  667. {
  668. // left
  669. outBuffer[i][k+timeOffset] = oldBufLeft[k] * (1.0f - balRangeL);
  670. outBuffer[i][k+timeOffset] += outBuffer[i+1][k+timeOffset] * (1.0f - balRangeR);
  671. }
  672. else
  673. {
  674. // right
  675. outBuffer[i][k+timeOffset] = outBuffer[i][k+timeOffset] * balRangeR;
  676. outBuffer[i][k+timeOffset] += oldBufLeft[k] * balRangeL;
  677. }
  678. }
  679. }
  680. // Volume
  681. if (doVolume)
  682. {
  683. for (uint32_t k=0; k < frames; ++k)
  684. outBuffer[i][k+timeOffset] *= pData->postProc.volume;
  685. }
  686. }
  687. } // End of Post-processing
  688. #endif
  689. // --------------------------------------------------------------------------------------------------------
  690. pData->singleMutex.unlock();
  691. return true;
  692. }
  693. void bufferSizeChanged(const uint32_t newBufferSize) override
  694. {
  695. CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
  696. carla_debug("ReWirePlugin::bufferSizeChanged(%i)", newBufferSize);
  697. if (pData->active)
  698. deactivate();
  699. RwAudioInfo audioInfo;
  700. audioInfo.size = sizeof(RwAudioInfo);
  701. audioInfo.bufferSize = static_cast<rlong>(newBufferSize);
  702. audioInfo.sampleRate = static_cast<rlong>(pData->engine->getSampleRate());
  703. fRw.RWDEFSetAudioInfo(&audioInfo);
  704. if (pData->active)
  705. activate();
  706. }
  707. void sampleRateChanged(const double newSampleRate) override
  708. {
  709. CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
  710. carla_debug("ReWirePlugin::sampleRateChanged(%g)", newSampleRate);
  711. if (pData->active)
  712. deactivate();
  713. RwAudioInfo audioInfo;
  714. audioInfo.size = sizeof(RwAudioInfo);
  715. audioInfo.bufferSize = static_cast<rlong>(pData->engine->getBufferSize());
  716. audioInfo.sampleRate = static_cast<rlong>(newSampleRate);
  717. fRw.RWDEFSetAudioInfo(&audioInfo);
  718. if (pData->active)
  719. activate();
  720. }
  721. // -------------------------------------------------------------------
  722. // Plugin buffers
  723. // nothing
  724. // -------------------------------------------------------------------
  725. // Post-poned UI Stuff
  726. // nothing
  727. // -------------------------------------------------------------------
  728. protected:
  729. // TODO
  730. // -------------------------------------------------------------------
  731. public:
  732. bool init(const char* const filename, const char* const name)
  733. {
  734. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  735. // ---------------------------------------------------------------
  736. // first checks
  737. if (pData->client != nullptr)
  738. {
  739. pData->engine->setLastError("Plugin client is already registered");
  740. return false;
  741. }
  742. if (filename == nullptr || filename[0] == '\0')
  743. {
  744. pData->engine->setLastError("null filename");
  745. return false;
  746. }
  747. // ---------------------------------------------------------------
  748. // open DLL
  749. int ret = fRw.init(filename);
  750. if (ret != 0)
  751. {
  752. if (ret == -1)
  753. pData->engine->setLastError(lib_error(filename));
  754. else
  755. pData->engine->setLastError("Not a valid ReWire application");
  756. return false;
  757. }
  758. // ---------------------------------------------------------------
  759. // get info
  760. long version;
  761. char nameBuf[STR_MAX+1];
  762. carla_zeroChar(nameBuf, STR_MAX+1);
  763. fRw.RWDEFGetDeviceNameAndVersion(&version, nameBuf);
  764. if (nameBuf[0] == '\0')
  765. {
  766. pData->engine->setLastError("ReWire application has no name");
  767. return false;
  768. }
  769. fLabel = carla_strdup(nameBuf);
  770. if (name != nullptr && name[0] != '\0')
  771. pData->name = pData->engine->getUniquePluginName(name);
  772. else
  773. pData->name = pData->engine->getUniquePluginName(nameBuf);
  774. pData->filename = carla_strdup(filename);
  775. // ---------------------------------------------------------------
  776. // register client
  777. pData->client = pData->engine->addClient(this);
  778. if (pData->client == nullptr || ! pData->client->isOk())
  779. {
  780. pData->engine->setLastError("Failed to register plugin client");
  781. return false;
  782. }
  783. // ---------------------------------------------------------------
  784. // initialize app
  785. RwOpenInfo info;
  786. info.size1 = sizeof(RwOpenInfo);
  787. info.size2 = 12;
  788. info.bufferSize = static_cast<rlong>(pData->engine->getBufferSize());
  789. info.sampleRate = static_cast<rlong>(pData->engine->getSampleRate());
  790. ret = fRw.RWDEFOpenDevice(&info);
  791. carla_stdout("RW open ret = %i", ret);
  792. // TODO check ret
  793. fIsOpen = true;
  794. // ---------------------------------------------------------------
  795. // load plugin settings
  796. {
  797. // set default options
  798. pData->options = 0x0;
  799. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  800. pData->options |= PLUGIN_OPTION_USE_CHUNKS;
  801. // TODO
  802. if (getMidiInCount() > 0)
  803. {
  804. pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  805. pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  806. pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
  807. pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  808. }
  809. // set identifier string
  810. CarlaString identifier("ReWire/");
  811. identifier += fLabel;
  812. pData->identifier = identifier.dup();
  813. // load settings
  814. pData->options = pData->loadSettings(pData->options, getOptionsAvailable());
  815. // ignore settings, we need this anyway
  816. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  817. pData->options |= PLUGIN_OPTION_USE_CHUNKS;
  818. }
  819. return true;
  820. }
  821. private:
  822. RewireBridge fRw;
  823. RwAudioInInfo fRwAudioIn;
  824. RwAudioOutInfo fRwAudioOut;
  825. bool fIsOpen;
  826. bool fIsPanelLaunched;
  827. const char* fLabel;
  828. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ReWirePlugin)
  829. };
  830. CARLA_BACKEND_END_NAMESPACE
  831. #endif // WANT_REWIRE
  832. // -------------------------------------------------------------------------------------------------------------------
  833. CARLA_BACKEND_START_NAMESPACE
  834. CarlaPlugin* CarlaPlugin::newReWire(const Initializer& init)
  835. {
  836. carla_debug("CarlaPlugin::newReWire({%p, \"%s\", \"%s\"})", init.engine, init.filename, init.name);
  837. #ifdef WANT_REWIRE
  838. ReWirePlugin* const plugin(new ReWirePlugin(init.engine, init.id));
  839. if (! plugin->init(init.filename, init.name))
  840. {
  841. delete plugin;
  842. return nullptr;
  843. }
  844. plugin->reload();
  845. if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK && ! plugin->canRunInRack())
  846. {
  847. init.engine->setLastError("Carla's rack mode can only work with Stereo ReWire applications, sorry!");
  848. delete plugin;
  849. return nullptr;
  850. }
  851. return plugin;
  852. #else
  853. init.engine->setLastError("ReWire support not available");
  854. return nullptr;
  855. #endif
  856. }
  857. CARLA_BACKEND_END_NAMESPACE
  858. // -------------------------------------------------------------------------------------------------------------------