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 33KB

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