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.

BridgePlugin.cpp 44KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521
  1. /*
  2. * Carla Bridge Plugin
  3. * Copyright (C) 2011-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 GPL.txt file
  16. */
  17. #include "CarlaPluginInternal.hpp"
  18. #ifndef BUILD_BRIDGE
  19. #include "CarlaBridgeUtils.hpp"
  20. #include "CarlaShmUtils.hpp"
  21. #include <cerrno>
  22. #include <ctime>
  23. #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  24. # include <sys/time.h>
  25. #endif
  26. #include <QtCore/QDir>
  27. #include <QtCore/QFile>
  28. #include <QtCore/QStringList>
  29. #include <QtCore/QTextStream>
  30. #define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
  31. /* check argument count */ \
  32. if (argc != argcToCompare) \
  33. { \
  34. carla_stderr("BridgePlugin::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \
  35. return 1; \
  36. } \
  37. if (argc > 0) \
  38. { \
  39. /* check for nullness */ \
  40. if (! (types && typesToCompare)) \
  41. { \
  42. carla_stderr("BridgePlugin::%s() - argument types are null", __FUNCTION__); \
  43. return 1; \
  44. } \
  45. /* check argument types */ \
  46. if (std::strcmp(types, typesToCompare) != 0) \
  47. { \
  48. carla_stderr("BridgePlugin::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \
  49. return 1; \
  50. } \
  51. }
  52. CARLA_BACKEND_START_NAMESPACE
  53. // -------------------------------------------------------------------------------------------------------------------
  54. // Engine Helpers
  55. extern void registerEnginePlugin(CarlaEngine* const engine, const unsigned int id, CarlaPlugin* const plugin);
  56. // -------------------------------------------------------------------------------------------------------------------
  57. shm_t shm_mkstemp(char* const fileBase)
  58. {
  59. static const char charSet[] = "abcdefghijklmnopqrstuvwxyz"
  60. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  61. "0123456789";
  62. const int size = (fileBase != nullptr) ? std::strlen(fileBase) : 0;
  63. shm_t shm;
  64. carla_shm_init(shm);
  65. if (size < 6)
  66. {
  67. errno = EINVAL;
  68. return shm;
  69. }
  70. if (std::strcmp(fileBase + size - 6, "XXXXXX") != 0)
  71. {
  72. errno = EINVAL;
  73. return shm;
  74. }
  75. while (true)
  76. {
  77. for (int c = size - 6; c < size; c++)
  78. {
  79. // Note the -1 to avoid the trailing '\0' in charSet.
  80. fileBase[c] = charSet[std::rand() % (sizeof(charSet) - 1)];
  81. }
  82. shm_t shm = carla_shm_create(fileBase);
  83. if (carla_is_shm_valid(shm) || errno != EEXIST)
  84. return shm;
  85. }
  86. }
  87. // -------------------------------------------------------------------------------------------------------------------
  88. struct BridgeParamInfo {
  89. float value;
  90. CarlaString name;
  91. CarlaString unit;
  92. BridgeParamInfo()
  93. : value(0.0f) {}
  94. };
  95. class BridgePlugin : public CarlaPlugin
  96. {
  97. public:
  98. BridgePlugin(CarlaEngine* const engine, const unsigned int id, const BinaryType btype, const PluginType ptype)
  99. : CarlaPlugin(engine, id),
  100. fBinaryType(btype),
  101. fPluginType(ptype),
  102. fInitiated(false),
  103. fInitError(false),
  104. fSaved(false),
  105. fParams(nullptr)
  106. {
  107. carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
  108. kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_BRIDGE);
  109. fHints |= PLUGIN_IS_BRIDGE;
  110. }
  111. ~BridgePlugin() override
  112. {
  113. carla_debug("BridgePlugin::~BridgePlugin()");
  114. kData->singleMutex.lock();
  115. kData->masterMutex.lock();
  116. if (kData->active)
  117. {
  118. deactivate();
  119. kData->active = false;
  120. }
  121. if (kData->osc.data.target != nullptr)
  122. {
  123. osc_send_hide(&kData->osc.data);
  124. osc_send_quit(&kData->osc.data);
  125. }
  126. kData->osc.data.free();
  127. // Wait a bit first, then force kill
  128. if (kData->osc.thread.isRunning() && ! kData->osc.thread.wait(kData->engine->getOptions().oscUiTimeout))
  129. {
  130. carla_stderr("Failed to properly stop Plugin Bridge thread");
  131. kData->osc.thread.terminate();
  132. }
  133. cleanup();
  134. //info.chunk.clear();
  135. }
  136. // -------------------------------------------------------------------
  137. // Information (base)
  138. BinaryType binaryType() const
  139. {
  140. return fBinaryType;
  141. }
  142. PluginType type() const override
  143. {
  144. return fPluginType;
  145. }
  146. PluginCategory category() override
  147. {
  148. return fInfo.category;
  149. }
  150. long uniqueId() const override
  151. {
  152. return fInfo.uniqueId;
  153. }
  154. // -------------------------------------------------------------------
  155. // Information (count)
  156. uint32_t midiInCount() const override
  157. {
  158. return fInfo.mIns;
  159. }
  160. uint32_t midiOutCount() const override
  161. {
  162. return fInfo.mOuts;
  163. }
  164. // -------------------------------------------------------------------
  165. // Information (current data)
  166. int32_t chunkData(void** const dataPtr) override
  167. {
  168. CARLA_ASSERT(fOptions & PLUGIN_OPTION_USE_CHUNKS);
  169. CARLA_ASSERT(dataPtr != nullptr);
  170. #if 0
  171. if (! info.chunk.isEmpty())
  172. {
  173. *dataPtr = info.chunk.data();
  174. return info.chunk.size();
  175. }
  176. #endif
  177. return 0;
  178. }
  179. // -------------------------------------------------------------------
  180. // Information (per-plugin data)
  181. unsigned int availableOptions() override
  182. {
  183. unsigned int options = 0x0;
  184. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  185. options |= PLUGIN_OPTION_USE_CHUNKS;
  186. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  187. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  188. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  189. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  190. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  191. return options;
  192. }
  193. #if 0
  194. double getParameterValue(const uint32_t parameterId) override
  195. {
  196. CARLA_ASSERT(parameterId < param.count);
  197. return params[parameterId].value;
  198. }
  199. #endif
  200. void getLabel(char* const strBuf) override
  201. {
  202. std::strncpy(strBuf, (const char*)fInfo.label, STR_MAX);
  203. }
  204. void getMaker(char* const strBuf) override
  205. {
  206. std::strncpy(strBuf, (const char*)fInfo.maker, STR_MAX);
  207. }
  208. void getCopyright(char* const strBuf) override
  209. {
  210. std::strncpy(strBuf, (const char*)fInfo.copyright, STR_MAX);
  211. }
  212. void getRealName(char* const strBuf) override
  213. {
  214. std::strncpy(strBuf, (const char*)fInfo.name, STR_MAX);
  215. }
  216. #if 0
  217. void getParameterName(const uint32_t parameterId, char* const strBuf) override
  218. {
  219. CARLA_ASSERT(parameterId < param.count);
  220. strncpy(strBuf, params[parameterId].name.toUtf8().constData(), STR_MAX);
  221. }
  222. void getParameterUnit(const uint32_t parameterId, char* const strBuf) override
  223. {
  224. CARLA_ASSERT(parameterId < param.count);
  225. strncpy(strBuf, params[parameterId].unit.toUtf8().constData(), STR_MAX);
  226. }
  227. #endif
  228. // -------------------------------------------------------------------
  229. // Set data (state)
  230. void prepareForSave() override
  231. {
  232. #if 0
  233. m_saved = false;
  234. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SAVE_NOW, "");
  235. for (int i=0; i < 200; ++i)
  236. {
  237. if (m_saved)
  238. break;
  239. carla_msleep(50);
  240. }
  241. if (! m_saved)
  242. carla_stderr("BridgePlugin::prepareForSave() - Timeout while requesting save state");
  243. else
  244. carla_debug("BridgePlugin::prepareForSave() - success!");
  245. #endif
  246. }
  247. // -------------------------------------------------------------------
  248. // Set data (internal stuff)
  249. // nothing
  250. // -------------------------------------------------------------------
  251. // Set data (plugin-specific stuff)
  252. #if 0
  253. void setParameterValue(const uint32_t parameterId, double value, const bool sendGui, const bool sendOsc, const bool sendCallback) override
  254. {
  255. CARLA_ASSERT(parameterId < param.count);
  256. params[parameterId].value = fixParameterValue(value, param.ranges[parameterId]);
  257. CarlaPlugin::setParameterValue(parameterId, value, sendGui, sendOsc, sendCallback);
  258. }
  259. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  260. {
  261. CARLA_ASSERT(type);
  262. CARLA_ASSERT(key);
  263. CARLA_ASSERT(value);
  264. if (sendGui)
  265. {
  266. // TODO - if type is chunk|binary, store it in a file and send path instead
  267. QString cData;
  268. cData = type;
  269. cData += "·";
  270. cData += key;
  271. cData += "·";
  272. cData += value;
  273. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CUSTOM, cData.toUtf8().constData());
  274. }
  275. CarlaPlugin::setCustomData(type, key, value, sendGui);
  276. }
  277. void setChunkData(const char* const stringData) override
  278. {
  279. CARLA_ASSERT(m_hints & PLUGIN_USES_CHUNKS);
  280. CARLA_ASSERT(stringData);
  281. QString filePath;
  282. filePath = QDir::tempPath();
  283. filePath += "/.CarlaChunk_";
  284. filePath += m_name;
  285. filePath = QDir::toNativeSeparators(filePath);
  286. QFile file(filePath);
  287. if (file.open(QIODevice::WriteOnly | QIODevice::Text))
  288. {
  289. QTextStream out(&file);
  290. out << stringData;
  291. file.close();
  292. osc_send_configure(&osc.data, CARLA_BRIDGE_MSG_SET_CHUNK, filePath.toUtf8().constData());
  293. }
  294. }
  295. #endif
  296. // -------------------------------------------------------------------
  297. // Set gui stuff
  298. void showGui(const bool yesNo) override
  299. {
  300. if (yesNo)
  301. osc_send_show(&kData->osc.data);
  302. else
  303. osc_send_hide(&kData->osc.data);
  304. }
  305. void idleGui() override
  306. {
  307. if (! kData->osc.thread.isRunning())
  308. carla_stderr2("TESTING: Bridge has closed!");
  309. CarlaPlugin::idleGui();
  310. }
  311. // -------------------------------------------------------------------
  312. // Plugin state
  313. void reload() override
  314. {
  315. carla_debug("BridgePlugin::reload() - start");
  316. CARLA_ASSERT(kData->engine != nullptr);
  317. if (kData->engine == nullptr)
  318. return;
  319. const ProcessMode processMode(kData->engine->getProccessMode());
  320. // Safely disable plugin for reload
  321. const ScopedDisabler sd(this);
  322. kData->clearBuffers();
  323. bool needsCtrlIn, needsCtrlOut;
  324. needsCtrlIn = needsCtrlOut = false;
  325. if (fInfo.aIns > 0)
  326. {
  327. kData->audioIn.createNew(fInfo.aIns);
  328. }
  329. if (fInfo.aOuts > 0)
  330. {
  331. kData->audioOut.createNew(fInfo.aOuts);
  332. needsCtrlIn = true;
  333. }
  334. if (fInfo.mIns > 0)
  335. needsCtrlIn = true;
  336. if (fInfo.mOuts > 0)
  337. needsCtrlOut = true;
  338. const uint portNameSize(kData->engine->maxPortNameSize());
  339. CarlaString portName;
  340. // Audio Ins
  341. for (uint32_t j=0; j < fInfo.aIns; ++j)
  342. {
  343. portName.clear();
  344. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  345. {
  346. portName = fName;
  347. portName += ":";
  348. }
  349. if (fInfo.aIns > 1)
  350. {
  351. portName += "input_";
  352. portName += CarlaString(j+1);
  353. }
  354. else
  355. portName += "input";
  356. portName.truncate(portNameSize);
  357. kData->audioIn.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true);
  358. kData->audioIn.ports[j].rindex = j;
  359. }
  360. // Audio Outs
  361. for (uint32_t j=0; j < fInfo.aOuts; ++j)
  362. {
  363. portName.clear();
  364. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  365. {
  366. portName = fName;
  367. portName += ":";
  368. }
  369. if (fInfo.aOuts > 1)
  370. {
  371. portName += "output_";
  372. portName += CarlaString(j+1);
  373. }
  374. else
  375. portName += "output";
  376. portName.truncate(portNameSize);
  377. kData->audioOut.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false);
  378. kData->audioOut.ports[j].rindex = j;
  379. }
  380. if (needsCtrlIn)
  381. {
  382. portName.clear();
  383. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  384. {
  385. portName = fName;
  386. portName += ":";
  387. }
  388. portName += "event-in";
  389. portName.truncate(portNameSize);
  390. kData->event.portIn = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true);
  391. }
  392. if (needsCtrlOut)
  393. {
  394. portName.clear();
  395. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  396. {
  397. portName = fName;
  398. portName += ":";
  399. }
  400. portName += "event-out";
  401. portName.truncate(portNameSize);
  402. kData->event.portOut = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, false);
  403. }
  404. //bufferSizeChanged(kData->engine->getBufferSize());
  405. //reloadPrograms(true);
  406. carla_debug("BridgePlugin::reload() - end");
  407. }
  408. // -------------------------------------------------------------------
  409. // Plugin processing
  410. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) override
  411. {
  412. uint32_t i, k;
  413. // --------------------------------------------------------------------------------------------------------
  414. // Check if active
  415. if (! kData->active)
  416. {
  417. // disable any output sound
  418. for (i=0; i < kData->audioOut.count; ++i)
  419. carla_zeroFloat(outBuffer[i], frames);
  420. return;
  421. }
  422. for (i=0; i < fInfo.aIns; ++i)
  423. carla_copyFloat(fShmAudioPool.data + i * frames, inBuffer[i], frames);
  424. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeProcess);
  425. rdwr_commitWrite(&fShmControl.data->ringBuffer);
  426. waitForServer();
  427. for (i=0; i < fInfo.aOuts; ++i)
  428. carla_copyFloat(outBuffer[i], fShmAudioPool.data + (i+fInfo.aIns) * frames, frames);
  429. }
  430. // -------------------------------------------------------------------
  431. // Plugin buffers
  432. // nothing
  433. // -------------------------------------------------------------------
  434. // Post-poned UI Stuff
  435. void uiParameterChange(const uint32_t index, const float value) override
  436. {
  437. CARLA_ASSERT(index < kData->param.count);
  438. if (index >= kData->param.count)
  439. return;
  440. if (kData->osc.data.target == nullptr)
  441. return;
  442. osc_send_control(&kData->osc.data, kData->param.data[index].rindex, value);
  443. }
  444. void uiProgramChange(const uint32_t index) override
  445. {
  446. CARLA_ASSERT(index < kData->prog.count);
  447. if (index >= kData->prog.count)
  448. return;
  449. if (kData->osc.data.target == nullptr)
  450. return;
  451. osc_send_program(&kData->osc.data, index);
  452. }
  453. void uiMidiProgramChange(const uint32_t index) override
  454. {
  455. CARLA_ASSERT(index < kData->midiprog.count);
  456. if (index >= kData->midiprog.count)
  457. return;
  458. if (kData->osc.data.target == nullptr)
  459. return;
  460. osc_send_midi_program(&kData->osc.data, index);
  461. }
  462. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) override
  463. {
  464. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  465. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  466. CARLA_ASSERT(velo > 0 && velo < MAX_MIDI_VALUE);
  467. if (channel >= MAX_MIDI_CHANNELS)
  468. return;
  469. if (note >= MAX_MIDI_NOTE)
  470. return;
  471. if (velo >= MAX_MIDI_VALUE)
  472. return;
  473. if (kData->osc.data.target == nullptr)
  474. return;
  475. uint8_t midiData[4] = { 0 };
  476. midiData[1] = MIDI_STATUS_NOTE_ON + channel;
  477. midiData[2] = note;
  478. midiData[3] = velo;
  479. osc_send_midi(&kData->osc.data, midiData);
  480. }
  481. void uiNoteOff(const uint8_t channel, const uint8_t note) override
  482. {
  483. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  484. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  485. if (channel >= MAX_MIDI_CHANNELS)
  486. return;
  487. if (note >= MAX_MIDI_NOTE)
  488. return;
  489. if (kData->osc.data.target == nullptr)
  490. return;
  491. uint8_t midiData[4] = { 0 };
  492. midiData[1] = MIDI_STATUS_NOTE_OFF + channel;
  493. midiData[2] = note;
  494. osc_send_midi(&kData->osc.data, midiData);
  495. }
  496. void bufferSizeChanged(const uint32_t newBufferSize) override
  497. {
  498. resizeAudioPool(newBufferSize);
  499. }
  500. // -------------------------------------------------------------------
  501. int setOscPluginBridgeInfo(const PluginBridgeInfoType type, const int argc, const lo_arg* const* const argv, const char* const types)
  502. {
  503. carla_stdout("setOscPluginBridgeInfo(%i, %i, %p, \"%s\")", type, argc, argv, types);
  504. switch (type)
  505. {
  506. case kPluginBridgeAudioCount:
  507. {
  508. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  509. const int32_t aIns = argv[0]->i;
  510. const int32_t aOuts = argv[1]->i;
  511. const int32_t aTotal = argv[2]->i;
  512. CARLA_ASSERT(aIns >= 0);
  513. CARLA_ASSERT(aOuts >= 0);
  514. CARLA_ASSERT(aIns + aOuts == aTotal);
  515. fInfo.aIns = aIns;
  516. fInfo.aOuts = aOuts;
  517. break;
  518. // unused
  519. (void)aTotal;
  520. }
  521. case kPluginBridgeMidiCount:
  522. {
  523. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  524. const int32_t mIns = argv[0]->i;
  525. const int32_t mOuts = argv[1]->i;
  526. const int32_t mTotal = argv[2]->i;
  527. CARLA_ASSERT(mIns >= 0);
  528. CARLA_ASSERT(mOuts >= 0);
  529. CARLA_ASSERT(mIns + mOuts == mTotal);
  530. fInfo.mIns = mIns;
  531. fInfo.mOuts = mOuts;
  532. break;
  533. // unused
  534. (void)mTotal;
  535. }
  536. #if 0
  537. case PluginBridgeParameterCount:
  538. {
  539. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iii");
  540. const int32_t pIns = argv[0]->i;
  541. const int32_t pOuts = argv[1]->i;
  542. const int32_t pTotal = argv[2]->i;
  543. CARLA_ASSERT(pIns >= 0);
  544. CARLA_ASSERT(pOuts >= 0);
  545. CARLA_ASSERT(pIns + pOuts <= pTotal);
  546. // delete old data
  547. if (param.count > 0)
  548. {
  549. delete[] param.data;
  550. delete[] param.ranges;
  551. delete[] params;
  552. }
  553. // create new if needed
  554. const int32_t maxParams = x_engine->getOptions().maxParameters;
  555. param.count = (pTotal < maxParams) ? pTotal : 0;
  556. if (param.count > 0)
  557. {
  558. param.data = new ParameterData[param.count];
  559. param.ranges = new ParameterRanges[param.count];
  560. params = new BridgeParamInfo[param.count];
  561. }
  562. else
  563. {
  564. param.data = nullptr;
  565. param.ranges = nullptr;
  566. params = nullptr;
  567. }
  568. break;
  569. Q_UNUSED(pIns);
  570. Q_UNUSED(pOuts);
  571. }
  572. case PluginBridgeProgramCount:
  573. {
  574. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  575. const int32_t count = argv[0]->i;
  576. CARLA_ASSERT(count >= 0);
  577. // delete old programs
  578. if (prog.count > 0)
  579. {
  580. for (uint32_t i=0; i < prog.count; ++i)
  581. {
  582. if (prog.names[i])
  583. free((void*)prog.names[i]);
  584. }
  585. delete[] prog.names;
  586. }
  587. prog.count = count;
  588. // create new if needed
  589. if (prog.count > 0)
  590. {
  591. prog.names = new const char* [prog.count];
  592. for (uint32_t i=0; i < prog.count; ++i)
  593. prog.names[i] = nullptr;
  594. }
  595. else
  596. prog.names = nullptr;
  597. break;
  598. }
  599. case PluginBridgeMidiProgramCount:
  600. {
  601. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  602. const int32_t count = argv[0]->i;
  603. // delete old programs
  604. if (midiprog.count > 0)
  605. {
  606. for (uint32_t i=0; i < midiprog.count; ++i)
  607. {
  608. if (midiprog.data[i].name)
  609. free((void*)midiprog.data[i].name);
  610. }
  611. delete[] midiprog.data;
  612. }
  613. // create new if needed
  614. midiprog.count = count;
  615. if (midiprog.count > 0)
  616. midiprog.data = new MidiProgramData[midiprog.count];
  617. else
  618. midiprog.data = nullptr;
  619. break;
  620. }
  621. #endif
  622. case kPluginBridgePluginInfo:
  623. {
  624. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "iissssh");
  625. const int32_t category = argv[0]->i;
  626. const int32_t hints = argv[1]->i;
  627. const char* const name = (const char*)&argv[2]->s;
  628. const char* const label = (const char*)&argv[3]->s;
  629. const char* const maker = (const char*)&argv[4]->s;
  630. const char* const copyright = (const char*)&argv[5]->s;
  631. const int64_t uniqueId = argv[6]->h;
  632. CARLA_ASSERT(category >= 0);
  633. CARLA_ASSERT(hints >= 0);
  634. CARLA_ASSERT(name);
  635. CARLA_ASSERT(label);
  636. CARLA_ASSERT(maker);
  637. CARLA_ASSERT(copyright);
  638. fHints = hints | PLUGIN_IS_BRIDGE;
  639. fInfo.category = static_cast<PluginCategory>(category);
  640. fInfo.uniqueId = uniqueId;
  641. fInfo.name = name;
  642. fInfo.label = label;
  643. fInfo.maker = maker;
  644. fInfo.copyright = copyright;
  645. if (fName.isEmpty())
  646. fName = kData->engine->getUniquePluginName(name);
  647. break;
  648. }
  649. #if 0
  650. case PluginBridgeParameterInfo:
  651. {
  652. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "iss");
  653. const int32_t index = argv[0]->i;
  654. const char* const name = (const char*)&argv[1]->s;
  655. const char* const unit = (const char*)&argv[2]->s;
  656. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  657. CARLA_ASSERT(name);
  658. CARLA_ASSERT(unit);
  659. if (index >= 0 && index < (int32_t)param.count)
  660. {
  661. params[index].name = QString(name);
  662. params[index].unit = QString(unit);
  663. }
  664. break;
  665. }
  666. case PluginBridgeParameterData:
  667. {
  668. CARLA_BRIDGE_CHECK_OSC_TYPES(6, "iiiiii");
  669. const int32_t index = argv[0]->i;
  670. const int32_t type = argv[1]->i;
  671. const int32_t rindex = argv[2]->i;
  672. const int32_t hints = argv[3]->i;
  673. const int32_t channel = argv[4]->i;
  674. const int32_t cc = argv[5]->i;
  675. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  676. CARLA_ASSERT(type >= 0);
  677. CARLA_ASSERT(rindex >= 0);
  678. CARLA_ASSERT(hints >= 0);
  679. CARLA_ASSERT(channel >= 0 && channel < 16);
  680. CARLA_ASSERT(cc >= -1);
  681. if (index >= 0 && index < (int32_t)param.count)
  682. {
  683. param.data[index].type = (ParameterType)type;
  684. param.data[index].index = index;
  685. param.data[index].rindex = rindex;
  686. param.data[index].hints = hints;
  687. param.data[index].midiChannel = channel;
  688. param.data[index].midiCC = cc;
  689. }
  690. break;
  691. }
  692. case PluginBridgeParameterRanges:
  693. {
  694. CARLA_BRIDGE_CHECK_OSC_TYPES(7, "idddddd");
  695. const int32_t index = argv[0]->i;
  696. const double def = argv[1]->d;
  697. const double min = argv[2]->d;
  698. const double max = argv[3]->d;
  699. const double step = argv[4]->d;
  700. const double stepSmall = argv[5]->d;
  701. const double stepLarge = argv[6]->d;
  702. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  703. CARLA_ASSERT(min < max);
  704. CARLA_ASSERT(def >= min);
  705. CARLA_ASSERT(def <= max);
  706. if (index >= 0 && index < (int32_t)param.count)
  707. {
  708. param.ranges[index].def = def;
  709. param.ranges[index].min = min;
  710. param.ranges[index].max = max;
  711. param.ranges[index].step = step;
  712. param.ranges[index].stepSmall = stepSmall;
  713. param.ranges[index].stepLarge = stepLarge;
  714. params[index].value = def;
  715. }
  716. break;
  717. }
  718. case PluginBridgeProgramInfo:
  719. {
  720. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "is");
  721. const int32_t index = argv[0]->i;
  722. const char* const name = (const char*)&argv[1]->s;
  723. CARLA_ASSERT(index >= 0 && index < (int32_t)prog.count);
  724. CARLA_ASSERT(name);
  725. if (index >= 0 && index < (int32_t)prog.count)
  726. {
  727. if (prog.names[index])
  728. free((void*)prog.names[index]);
  729. prog.names[index] = strdup(name);
  730. }
  731. break;
  732. }
  733. case PluginBridgeMidiProgramInfo:
  734. {
  735. CARLA_BRIDGE_CHECK_OSC_TYPES(4, "iiis");
  736. const int32_t index = argv[0]->i;
  737. const int32_t bank = argv[1]->i;
  738. const int32_t program = argv[2]->i;
  739. const char* const name = (const char*)&argv[3]->s;
  740. CARLA_ASSERT(index >= 0 && index < (int32_t)midiprog.count);
  741. CARLA_ASSERT(bank >= 0);
  742. CARLA_ASSERT(program >= 0 && program < 128);
  743. CARLA_ASSERT(name);
  744. if (index >= 0 && index < (int32_t)midiprog.count)
  745. {
  746. if (midiprog.data[index].name)
  747. free((void*)midiprog.data[index].name);
  748. midiprog.data[index].bank = bank;
  749. midiprog.data[index].program = program;
  750. midiprog.data[index].name = strdup(name);
  751. }
  752. break;
  753. }
  754. case PluginBridgeConfigure:
  755. {
  756. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "ss");
  757. const char* const key = (const char*)&argv[0]->s;
  758. const char* const value = (const char*)&argv[1]->s;
  759. CARLA_ASSERT(key);
  760. CARLA_ASSERT(value);
  761. if (! (key && value))
  762. {
  763. // invalid
  764. pass();
  765. }
  766. else if (std::strcmp(key, CARLA_BRIDGE_MSG_HIDE_GUI) == 0)
  767. {
  768. x_engine->callback(CALLBACK_SHOW_GUI, m_id, 0, 0, 0.0, nullptr);
  769. }
  770. else if (std::strcmp(key, CARLA_BRIDGE_MSG_SAVED) == 0)
  771. {
  772. m_saved = true;
  773. }
  774. break;
  775. }
  776. case PluginBridgeSetParameterValue:
  777. {
  778. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "id");
  779. const int32_t index = argv[0]->i;
  780. const double value = argv[1]->d;
  781. CARLA_ASSERT(index != PARAMETER_NULL);
  782. setParameterValueByRIndex(index, value, false, true, true);
  783. break;
  784. }
  785. case PluginBridgeSetDefaultValue:
  786. {
  787. CARLA_BRIDGE_CHECK_OSC_TYPES(2, "id");
  788. const int32_t index = argv[0]->i;
  789. const double value = argv[1]->d;
  790. CARLA_ASSERT(index >= 0 && index < (int32_t)param.count);
  791. if (index >= 0 && index < (int32_t)param.count)
  792. param.ranges[index].def = value;
  793. break;
  794. }
  795. case PluginBridgeSetProgram:
  796. {
  797. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  798. const int32_t index = argv[0]->i;
  799. CARLA_ASSERT(index < (int32_t)prog.count);
  800. setProgram(index, false, true, true, true);
  801. break;
  802. }
  803. case PluginBridgeSetMidiProgram:
  804. {
  805. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "i");
  806. const int32_t index = argv[0]->i;
  807. CARLA_ASSERT(index < (int32_t)midiprog.count);
  808. setMidiProgram(index, false, true, true, true);
  809. break;
  810. }
  811. case PluginBridgeSetCustomData:
  812. {
  813. CARLA_BRIDGE_CHECK_OSC_TYPES(3, "sss");
  814. const char* const type = (const char*)&argv[0]->s;
  815. const char* const key = (const char*)&argv[1]->s;
  816. const char* const value = (const char*)&argv[2]->s;
  817. CARLA_ASSERT(type);
  818. CARLA_ASSERT(key);
  819. CARLA_ASSERT(value);
  820. setCustomData(type, key, value, false);
  821. break;
  822. }
  823. case PluginBridgeSetChunkData:
  824. {
  825. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  826. const char* const chunkFileChar = (const char*)&argv[0]->s;
  827. CARLA_ASSERT(chunkFileChar);
  828. QString chunkFileStr(chunkFileChar);
  829. #ifndef Q_OS_WIN
  830. // Using Wine, fix temp dir
  831. if (m_binary == BINARY_WIN32 || m_binary == BINARY_WIN64)
  832. {
  833. // Get WINEPREFIX
  834. QString wineDir;
  835. if (const char* const WINEPREFIX = getenv("WINEPREFIX"))
  836. wineDir = QString(WINEPREFIX);
  837. else
  838. wineDir = QDir::homePath() + "/.wine";
  839. QStringList chunkFileStrSplit1 = chunkFileStr.split(":/");
  840. QStringList chunkFileStrSplit2 = chunkFileStrSplit1.at(1).split("\\");
  841. QString wineDrive = chunkFileStrSplit1.at(0).toLower();
  842. QString wineTMP = chunkFileStrSplit2.at(0);
  843. QString baseName = chunkFileStrSplit2.at(1);
  844. chunkFileStr = wineDir;
  845. chunkFileStr += "/drive_";
  846. chunkFileStr += wineDrive;
  847. chunkFileStr += "/";
  848. chunkFileStr += wineTMP;
  849. chunkFileStr += "/";
  850. chunkFileStr += baseName;
  851. chunkFileStr = QDir::toNativeSeparators(chunkFileStr);
  852. }
  853. #endif
  854. QFile chunkFile(chunkFileStr);
  855. if (chunkFile.open(QIODevice::ReadOnly))
  856. {
  857. info.chunk = chunkFile.readAll();
  858. chunkFile.close();
  859. chunkFile.remove();
  860. }
  861. break;
  862. }
  863. #endif
  864. case kPluginBridgeUpdateNow:
  865. {
  866. fInitiated = true;
  867. break;
  868. }
  869. case kPluginBridgeError:
  870. {
  871. CARLA_BRIDGE_CHECK_OSC_TYPES(1, "s");
  872. const char* const error = (const char*)&argv[0]->s;
  873. CARLA_ASSERT(error != nullptr);
  874. kData->engine->setLastError(error);
  875. fInitError = true;
  876. fInitiated = true;
  877. break;
  878. }
  879. }
  880. return 0;
  881. }
  882. // -------------------------------------------------------------------
  883. const void* getExtraStuff() override
  884. {
  885. return fBridgeBinary.isNotEmpty() ? (const char*)fBridgeBinary : nullptr;
  886. }
  887. bool init(const char* const filename, const char* const name, const char* const label, const char* const bridgeBinary)
  888. {
  889. CARLA_ASSERT(kData->engine != nullptr);
  890. CARLA_ASSERT(kData->client == nullptr);
  891. CARLA_ASSERT(filename != nullptr);
  892. // ---------------------------------------------------------------
  893. // first checks
  894. if (kData->engine == nullptr)
  895. {
  896. return false;
  897. }
  898. if (kData->client != nullptr)
  899. {
  900. kData->engine->setLastError("Plugin client is already registered");
  901. return false;
  902. }
  903. if (filename == nullptr)
  904. {
  905. kData->engine->setLastError("null filename");
  906. return false;
  907. }
  908. // ---------------------------------------------------------------
  909. // set info
  910. if (name != nullptr)
  911. fName = kData->engine->getUniquePluginName(name);
  912. fFilename = filename;
  913. // ---------------------------------------------------------------
  914. // register client
  915. kData->client = kData->engine->addClient(this);
  916. if (kData->client == nullptr || ! kData->client->isOk())
  917. {
  918. kData->engine->setLastError("Failed to register plugin client");
  919. return false;
  920. }
  921. // ---------------------------------------------------------------
  922. // SHM Audio Pool
  923. {
  924. char tmpFileBase[60];
  925. std::srand(std::time(NULL));
  926. std::sprintf(tmpFileBase, "/carla-bridge_shm_XXXXXX");
  927. fShmAudioPool.shm = shm_mkstemp(tmpFileBase);
  928. if (! carla_is_shm_valid(fShmAudioPool.shm))
  929. {
  930. //_cleanup();
  931. carla_stdout("Failed to open or create shared memory file #1");
  932. return false;
  933. }
  934. fShmAudioPool.filename = tmpFileBase;
  935. }
  936. // ---------------------------------------------------------------
  937. // SHM Control
  938. {
  939. char tmpFileBase[60];
  940. std::sprintf(tmpFileBase, "/carla-bridge_shc_XXXXXX");
  941. fShmControl.shm = shm_mkstemp(tmpFileBase);
  942. if (! carla_is_shm_valid(fShmControl.shm))
  943. {
  944. //_cleanup();
  945. carla_stdout("Failed to open or create shared memory file #2");
  946. return false;
  947. }
  948. fShmControl.filename = tmpFileBase;
  949. if (! carla_shm_map<BridgeShmControl>(fShmControl.shm, fShmControl.data))
  950. {
  951. //_cleanup();
  952. carla_stdout("Failed to mmap shared memory file");
  953. return false;
  954. }
  955. CARLA_ASSERT(fShmControl.data != nullptr);
  956. std::memset(fShmControl.data, 0, sizeof(BridgeShmControl));
  957. std::strcpy(fShmControl.data->ringBuffer.buf, "This thing is actually working!!!!");
  958. if (sem_init(&fShmControl.data->runServer, 1, 0) != 0)
  959. {
  960. //_cleanup();
  961. carla_stdout("Failed to initialize shared memory semaphore #1");
  962. return false;
  963. }
  964. if (sem_init(&fShmControl.data->runClient, 1, 0) != 0)
  965. {
  966. //_cleanup();
  967. carla_stdout("Failed to initialize shared memory semaphore #2");
  968. return false;
  969. }
  970. }
  971. // initial values
  972. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeBufferSize);
  973. rdwr_writeInt(&fShmControl.data->ringBuffer, kData->engine->getBufferSize());
  974. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSampleRate);
  975. rdwr_writeFloat(&fShmControl.data->ringBuffer, kData->engine->getSampleRate());
  976. rdwr_commitWrite(&fShmControl.data->ringBuffer);
  977. // register plugin now so we can receive OSC (and wait for it)
  978. fHints |= PLUGIN_IS_BRIDGE;
  979. registerEnginePlugin(kData->engine, fId, this);
  980. // init OSC
  981. {
  982. char shmIdStr[12+1] = { 0 };
  983. std::strncpy(shmIdStr, &fShmAudioPool.filename[fShmAudioPool.filename.length()-6], 6);
  984. std::strncat(shmIdStr, &fShmControl.filename[fShmControl.filename.length()-6], 6);
  985. kData->osc.thread.setOscData(bridgeBinary, label, getPluginTypeAsString(fPluginType), shmIdStr);
  986. kData->osc.thread.start();
  987. //kData->osc.thread.waitForStarted();
  988. }
  989. for (int i=0; i < 200; ++i)
  990. {
  991. if (fInitiated || ! kData->osc.thread.isRunning())
  992. break;
  993. carla_msleep(50);
  994. }
  995. if (! fInitiated)
  996. {
  997. // unregister so it gets handled properly
  998. registerEnginePlugin(kData->engine, fId, nullptr);
  999. if (kData->osc.thread.isRunning())
  1000. kData->osc.thread.terminate();
  1001. kData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");
  1002. return false;
  1003. }
  1004. else if (fInitError)
  1005. {
  1006. // unregister so it gets handled properly
  1007. registerEnginePlugin(kData->engine, fId, nullptr);
  1008. kData->osc.thread.quit();
  1009. // last error was set before
  1010. return false;
  1011. }
  1012. fBridgeBinary = bridgeBinary;
  1013. resizeAudioPool(kData->engine->getBufferSize());
  1014. rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeReadyWait);
  1015. rdwr_writeInt(&fShmControl.data->ringBuffer, fShmAudioPool.size);
  1016. rdwr_commitWrite(&fShmControl.data->ringBuffer);
  1017. waitForServer();
  1018. return true;
  1019. }
  1020. private:
  1021. const BinaryType fBinaryType;
  1022. const PluginType fPluginType;
  1023. bool fInitiated;
  1024. bool fInitError;
  1025. bool fSaved;
  1026. CarlaString fBridgeBinary;
  1027. struct BridgeAudioPool {
  1028. CarlaString filename;
  1029. float* data;
  1030. size_t size;
  1031. shm_t shm;
  1032. BridgeAudioPool()
  1033. : data(nullptr),
  1034. size(0)
  1035. {
  1036. carla_shm_init(shm);
  1037. }
  1038. } fShmAudioPool;
  1039. struct BridgeControl {
  1040. CarlaString filename;
  1041. BridgeShmControl* data;
  1042. shm_t shm;
  1043. BridgeControl()
  1044. : data(nullptr)
  1045. {
  1046. carla_shm_init(shm);
  1047. }
  1048. } fShmControl;
  1049. struct Info {
  1050. uint32_t aIns, aOuts;
  1051. uint32_t mIns, mOuts;
  1052. PluginCategory category;
  1053. long uniqueId;
  1054. CarlaString name;
  1055. CarlaString label;
  1056. CarlaString maker;
  1057. CarlaString copyright;
  1058. //QByteArray chunk;
  1059. Info()
  1060. : aIns(0),
  1061. aOuts(0),
  1062. mIns(0),
  1063. mOuts(0),
  1064. category(PLUGIN_CATEGORY_NONE),
  1065. uniqueId(0) {}
  1066. } fInfo;
  1067. BridgeParamInfo* fParams;
  1068. void cleanup()
  1069. {
  1070. if (fShmAudioPool.filename.isNotEmpty())
  1071. fShmAudioPool.filename.clear();
  1072. if (fShmControl.filename.isNotEmpty())
  1073. fShmControl.filename.clear();
  1074. if (fShmAudioPool.data != nullptr)
  1075. {
  1076. carla_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data, fShmAudioPool.size);
  1077. fShmAudioPool.data = nullptr;
  1078. }
  1079. fShmAudioPool.size = 0;
  1080. // and again
  1081. if (fShmControl.data != nullptr)
  1082. {
  1083. carla_shm_unmap(fShmControl.shm, fShmControl.data, sizeof(BridgeShmControl));
  1084. fShmControl.data = nullptr;
  1085. }
  1086. if (carla_is_shm_valid(fShmAudioPool.shm))
  1087. carla_shm_close(fShmAudioPool.shm);
  1088. if (carla_is_shm_valid(fShmControl.shm))
  1089. carla_shm_close(fShmControl.shm);
  1090. }
  1091. void resizeAudioPool(const uint32_t bufferSize)
  1092. {
  1093. if (fShmAudioPool.data != nullptr)
  1094. carla_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data, fShmAudioPool.size);
  1095. fShmAudioPool.size = (fInfo.aIns+fInfo.aOuts)*bufferSize*sizeof(float);
  1096. if (fShmAudioPool.size > 0)
  1097. fShmAudioPool.data = (float*)carla_shm_map(fShmAudioPool.shm, fShmAudioPool.size);
  1098. else
  1099. fShmAudioPool.data = nullptr;
  1100. }
  1101. void waitForServer()
  1102. {
  1103. sem_post(&fShmControl.data->runServer);
  1104. #ifdef CARLA_OS_MAC
  1105. alarm(5);
  1106. if (sem_wait(&fShmControl.data->runClient) == EINTR)
  1107. {
  1108. #else
  1109. timespec timeout;
  1110. # ifdef CARLA_OS_WIN
  1111. timeval now;
  1112. gettimeofday(&now, nullptr);
  1113. ts_timeout.tv_sec = now.tv_sec;
  1114. ts_timeout.tv_nsec = now.tv_usec * 1000;
  1115. # else
  1116. clock_gettime(CLOCK_REALTIME, &timeout);
  1117. # endif
  1118. timeout.tv_sec += 5;
  1119. if (sem_timedwait(&fShmControl.data->runClient, &timeout) != 0)
  1120. {
  1121. #endif
  1122. kData->active = false; // TODO
  1123. }
  1124. }
  1125. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin)
  1126. };
  1127. CARLA_BACKEND_END_NAMESPACE
  1128. #endif // ! BUILD_BRIDGE
  1129. CARLA_BACKEND_START_NAMESPACE
  1130. CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, PluginType ptype, const char* const bridgeBinary)
  1131. {
  1132. carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);
  1133. #ifndef BUILD_BRIDGE
  1134. if (bridgeBinary == nullptr)
  1135. {
  1136. init.engine->setLastError("Bridge not possible, bridge-binary not found");
  1137. return nullptr;
  1138. }
  1139. BridgePlugin* const plugin(new BridgePlugin(init.engine, init.id, btype, ptype));
  1140. if (! plugin->init(init.filename, init.name, init.label, bridgeBinary))
  1141. {
  1142. delete plugin;
  1143. return nullptr;
  1144. }
  1145. plugin->reload();
  1146. if (init.engine->getProccessMode() == PROCESS_MODE_CONTINUOUS_RACK && ! CarlaPluginProtectedData::canRunInRack(plugin))
  1147. {
  1148. init.engine->setLastError("Carla's rack mode can only work with Stereo Bridged plugins, sorry!");
  1149. delete plugin;
  1150. return nullptr;
  1151. }
  1152. return plugin;
  1153. #else
  1154. init.engine->setLastError("Plugin bridge support not available");
  1155. return nullptr;
  1156. // unused
  1157. (void)bridgeBinary;
  1158. #endif
  1159. }
  1160. #ifndef BUILD_BRIDGE
  1161. // -------------------------------------------------------------------
  1162. // Bridge Helper
  1163. int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeInfoType type,
  1164. const int argc, const lo_arg* const* const argv, const char* const types)
  1165. {
  1166. CARLA_ASSERT(plugin != nullptr && (plugin->hints() & PLUGIN_IS_BRIDGE) != 0);
  1167. return ((BridgePlugin*)plugin)->setOscPluginBridgeInfo(type, argc, argv, types);
  1168. }
  1169. BinaryType CarlaPluginGetBridgeBinaryType(CarlaPlugin* const plugin)
  1170. {
  1171. CARLA_ASSERT(plugin != nullptr && (plugin->hints() & PLUGIN_IS_BRIDGE) != 0);
  1172. return ((BridgePlugin*)plugin)->binaryType();
  1173. }
  1174. #endif
  1175. CARLA_BACKEND_END_NAMESPACE