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.

CarlaBridgePlugin.cpp 20KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. /*
  2. * Carla Bridge Plugin
  3. * Copyright (C) 2012-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 "CarlaBridgeClient.hpp"
  18. #include "CarlaEngine.hpp"
  19. #include "CarlaPlugin.hpp"
  20. #include "CarlaHost.h"
  21. #include "CarlaBackendUtils.hpp"
  22. #include "CarlaBridgeUtils.hpp"
  23. #include "CarlaMIDI.h"
  24. #ifdef CARLA_OS_UNIX
  25. # include <signal.h>
  26. #endif
  27. #ifdef HAVE_JUCE_UI
  28. # include "juce_gui_basics.h"
  29. using juce::JUCEApplication;
  30. using juce::JUCEApplicationBase;
  31. using juce::String;
  32. using juce::Timer;
  33. #endif
  34. // -------------------------------------------------------------------------
  35. static bool gIsInitiated = false;
  36. static volatile bool gCloseNow = false;
  37. static volatile bool gSaveNow = false;
  38. #ifdef CARLA_OS_WIN
  39. static BOOL WINAPI winSignalHandler(DWORD dwCtrlType)
  40. {
  41. if (dwCtrlType == CTRL_C_EVENT)
  42. {
  43. gCloseNow = true;
  44. return TRUE;
  45. }
  46. return FALSE;
  47. }
  48. #elif defined(CARLA_OS_LINUX)
  49. static void closeSignalHandler(int)
  50. {
  51. gCloseNow = true;
  52. }
  53. static void saveSignalHandler(int)
  54. {
  55. gSaveNow = true;
  56. }
  57. #endif
  58. static void initSignalHandler()
  59. {
  60. #ifdef CARLA_OS_WIN
  61. SetConsoleCtrlHandler(winSignalHandler, TRUE);
  62. #elif defined(CARLA_OS_LINUX)
  63. struct sigaction sint;
  64. struct sigaction sterm;
  65. struct sigaction susr1;
  66. sint.sa_handler = closeSignalHandler;
  67. sint.sa_flags = SA_RESTART;
  68. sint.sa_restorer = nullptr;
  69. sigemptyset(&sint.sa_mask);
  70. sigaction(SIGINT, &sint, nullptr);
  71. sterm.sa_handler = closeSignalHandler;
  72. sterm.sa_flags = SA_RESTART;
  73. sterm.sa_restorer = nullptr;
  74. sigemptyset(&sterm.sa_mask);
  75. sigaction(SIGTERM, &sterm, nullptr);
  76. susr1.sa_handler = saveSignalHandler;
  77. susr1.sa_flags = SA_RESTART;
  78. susr1.sa_restorer = nullptr;
  79. sigemptyset(&susr1.sa_mask);
  80. sigaction(SIGUSR1, &susr1, nullptr);
  81. #endif
  82. }
  83. // -------------------------------------------------------------------------
  84. #ifdef HACE_JUCE_UI
  85. static CarlaBridge::CarlaBridgeClient* gBridgeClient = nullptr;
  86. class CarlaJuceApp : public JUCEApplication,
  87. Timer
  88. {
  89. public:
  90. CarlaJuceApp() {}
  91. ~CarlaJuceApp() {}
  92. void initialise(const String&) override
  93. {
  94. startTimer(30);
  95. }
  96. void shutdown() override
  97. {
  98. gCloseNow = true;
  99. stopTimer();
  100. }
  101. const String getApplicationName() override
  102. {
  103. return "CarlaPlugin";
  104. }
  105. const String getApplicationVersion() override
  106. {
  107. return CARLA_VERSION_STRING;
  108. }
  109. void timerCallback() override
  110. {
  111. carla_engine_idle();
  112. if (gBridgeClient != nullptr)
  113. gBridgeClient->oscIdle();
  114. if (gCloseNow)
  115. {
  116. quit();
  117. gCloseNow = false;
  118. }
  119. }
  120. };
  121. static JUCEApplicationBase* juce_CreateApplication() { return new CarlaJuceApp(); }
  122. #endif
  123. // -------------------------------------------------------------------------
  124. CARLA_BRIDGE_START_NAMESPACE
  125. #if 0
  126. } // Fix editor indentation
  127. #endif
  128. // -------------------------------------------------------------------------
  129. class CarlaPluginClient : public CarlaBridgeClient
  130. {
  131. public:
  132. CarlaPluginClient(const bool useBridge, const char* const clientName, const char* const audioBaseName, const char* const controlBaseName, const char* const timeBaseName)
  133. : CarlaBridgeClient(nullptr),
  134. fPlugin(nullptr),
  135. fEngine(nullptr)
  136. {
  137. CARLA_ASSERT(clientName != nullptr && clientName[0] != '\0');
  138. carla_debug("CarlaPluginClient::CarlaPluginClient(%s, \"%s\", %s, %s, %s)", bool2str(useBridge), clientName, audioBaseName, controlBaseName, timeBaseName);
  139. carla_set_engine_callback(callback, this);
  140. if (useBridge)
  141. carla_engine_init_bridge(audioBaseName, controlBaseName, timeBaseName, clientName);
  142. else
  143. carla_engine_init("JACK", clientName);
  144. fEngine = carla_get_engine();
  145. }
  146. ~CarlaPluginClient() override
  147. {
  148. carla_debug("CarlaPluginClient::~CarlaPluginClient()");
  149. #ifdef HACE_JUCE_UI
  150. gBridgeClient = nullptr;
  151. #endif
  152. carla_engine_close();
  153. }
  154. bool isOk() const noexcept
  155. {
  156. return (fEngine != nullptr);
  157. }
  158. void oscInit(const char* const url)
  159. {
  160. CarlaBridgeClient::oscInit(url);
  161. fEngine->setOscBridgeData(&fOscData);
  162. }
  163. void ready(const bool doSaveLoad)
  164. {
  165. fPlugin = fEngine->getPlugin(0);
  166. if (doSaveLoad)
  167. {
  168. fProjFileName = fPlugin->getName();
  169. fProjFileName += ".carxs";
  170. //if (! File::isAbsolutePath((const char*)fProjFileName))
  171. // fProjFileName = File::getCurrentWorkingDirectory().getChildFile((const char*)fProjFileName).getFullPathName().toRawUTF8();
  172. //if (! fPlugin->loadStateFromFile(fProjFileName))
  173. // carla_stderr("Plugin preset load failed, error was:\n%s", fEngine->getLastError());
  174. }
  175. }
  176. #ifndef HAVE_JUCE_UI
  177. void idle()
  178. {
  179. CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,);
  180. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  181. carla_engine_idle();
  182. CarlaBridgeClient::oscIdle();
  183. if (gSaveNow)
  184. {
  185. gSaveNow = false;
  186. if (fProjFileName.isNotEmpty())
  187. {
  188. if (! fPlugin->saveStateToFile(fProjFileName))
  189. carla_stderr("Plugin preset save failed, error was:\n%s", fEngine->getLastError());
  190. }
  191. }
  192. if (gCloseNow)
  193. {
  194. //gCloseNow = false;
  195. // close something?
  196. }
  197. }
  198. #endif
  199. void exec(int argc, char* argv[])
  200. {
  201. #ifdef HAVE_JUCE_UI
  202. gBridgeClient = this;
  203. JUCEApplicationBase::createInstance = &juce_CreateApplication;
  204. JUCEApplicationBase::main(JUCE_MAIN_FUNCTION_ARGS);
  205. #else
  206. for (; ! gCloseNow;)
  207. {
  208. idle();
  209. carla_msleep(24);
  210. }
  211. #endif
  212. // may be unused
  213. return; (void)argc; (void)argv;
  214. }
  215. // ---------------------------------------------------------------------
  216. // plugin management
  217. void saveNow()
  218. {
  219. CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,);
  220. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  221. carla_debug("CarlaPluginClient::saveNow()");
  222. fPlugin->prepareForSave();
  223. for (uint32_t i=0; i < fPlugin->getCustomDataCount(); ++i)
  224. {
  225. const CarlaBackend::CustomData& cdata(fPlugin->getCustomData(i));
  226. fEngine->oscSend_bridge_set_custom_data(cdata.type, cdata.key, cdata.value);
  227. }
  228. if (fPlugin->getOptionsEnabled() & CarlaBackend::PLUGIN_OPTION_USE_CHUNKS)
  229. {
  230. void* data = nullptr;
  231. int32_t dataSize = fPlugin->getChunkData(&data);
  232. if (data && dataSize >= 4)
  233. {
  234. #if 0
  235. QString filePath;
  236. filePath = QDir::tempPath();
  237. #ifdef Q_OS_WIN
  238. filePath += "\\.CarlaChunk_";
  239. #else
  240. filePath += "/.CarlaChunk_";
  241. #endif
  242. filePath += fPlugin->getName();
  243. QFile file(filePath);
  244. if (file.open(QIODevice::WriteOnly))
  245. {
  246. QByteArray chunk((const char*)data, dataSize);
  247. file.write(chunk);
  248. file.close();
  249. fEngine->oscSend_bridge_set_chunk_data(filePath.toUtf8().constData());
  250. }
  251. #endif
  252. }
  253. }
  254. fEngine->oscSend_bridge_configure(CARLA_BRIDGE_MSG_SAVED, "");
  255. }
  256. void setParameterMidiChannel(const uint32_t index, const uint8_t channel)
  257. {
  258. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  259. carla_debug("CarlaPluginClient::setParameterMidiChannel(%i, %i)", index, channel);
  260. fPlugin->setParameterMidiChannel(index, channel, false, false);
  261. }
  262. void setParameterMidiCC(const uint32_t index, const int16_t cc)
  263. {
  264. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  265. carla_debug("CarlaPluginClient::setParameterMidiCC(%i, %i)", index, cc);
  266. fPlugin->setParameterMidiCC(index, cc, false, false);
  267. }
  268. void setCustomData(const char* const type, const char* const key, const char* const value)
  269. {
  270. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  271. carla_debug("CarlaPluginClient::setCustomData(\"%s\", \"%s\", \"%s\")", type, key, value);
  272. fPlugin->setCustomData(type, key, value, true);
  273. }
  274. void setChunkData(const char* const filePath)
  275. {
  276. CARLA_SAFE_ASSERT_RETURN(filePath != nullptr && filePath[0] != '\0',);
  277. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  278. carla_debug("CarlaPluginClient::setChunkData(\"%s\")", filePath);
  279. #if 0
  280. QString chunkFilePath(filePath);
  281. #ifdef CARLA_OS_WIN
  282. if (chunkFilePath.startsWith("/"))
  283. {
  284. // running under Wine, posix host
  285. chunkFilePath = chunkFilePath.replace(0, 1, "Z:/");
  286. chunkFilePath = QDir::toNativeSeparators(chunkFilePath);
  287. }
  288. #endif
  289. QFile chunkFile(chunkFilePath);
  290. if (fPlugin != nullptr && chunkFile.open(QIODevice::ReadOnly | QIODevice::Text))
  291. {
  292. QTextStream in(&chunkFile);
  293. QString stringData(in.readAll());
  294. chunkFile.close();
  295. chunkFile.remove();
  296. fPlugin->setChunkData(stringData.toUtf8().constData());
  297. }
  298. #endif
  299. }
  300. // ---------------------------------------------------------------------
  301. protected:
  302. void handleCallback(const CarlaBackend::EngineCallbackOpcode action, const int value1, const int value2, const float value3, const char* const valueStr)
  303. {
  304. CARLA_BACKEND_USE_NAMESPACE;
  305. // TODO
  306. switch (action)
  307. {
  308. case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED:
  309. if (isOscControlRegistered())
  310. {
  311. CARLA_SAFE_ASSERT_RETURN(value1 >= 0,);
  312. fEngine->oscSend_bridge_parameter_value(static_cast<uint32_t>(value1), value3);
  313. }
  314. break;
  315. case ENGINE_CALLBACK_UI_STATE_CHANGED:
  316. if (! isOscControlRegistered())
  317. {
  318. if (value1 != 1 && gIsInitiated)
  319. gCloseNow = true;
  320. }
  321. else
  322. {
  323. // show-gui button
  324. fEngine->oscSend_bridge_configure(CARLA_BRIDGE_MSG_HIDE_GUI, "");
  325. }
  326. break;
  327. default:
  328. break;
  329. }
  330. return;
  331. (void)value2;
  332. (void)value3;
  333. (void)valueStr;
  334. }
  335. private:
  336. CarlaBackend::CarlaPlugin* fPlugin;
  337. const CarlaBackend::CarlaEngine* fEngine;
  338. CarlaString fProjFileName;
  339. static void callback(void* ptr, CarlaBackend::EngineCallbackOpcode action, unsigned int pluginId, int value1, int value2, float value3, const char* valueStr)
  340. {
  341. carla_debug("CarlaPluginClient::callback(%p, %i:%s, %i, %i, %i, %f, \"%s\")", ptr, action, CarlaBackend::EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, valueStr);
  342. CARLA_SAFE_ASSERT_RETURN(ptr != nullptr,);
  343. CARLA_SAFE_ASSERT_RETURN(pluginId == 0,);
  344. return ((CarlaPluginClient*)ptr)->handleCallback(action, value1, value2, value3, valueStr);
  345. }
  346. };
  347. // -------------------------------------------------------------------------
  348. int CarlaBridgeOsc::handleMsgShow()
  349. {
  350. carla_debug("CarlaBridgeOsc::handleMsgShow()");
  351. #ifdef HACE_JUCE_UI
  352. const juce::MessageManagerLock mmLock;
  353. #endif
  354. if (carla_get_plugin_info(0)->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
  355. carla_show_custom_ui(0, true);
  356. return 0;
  357. }
  358. int CarlaBridgeOsc::handleMsgHide()
  359. {
  360. carla_debug("CarlaBridgeOsc::handleMsgHide()");
  361. #ifdef HACE_JUCE_UI
  362. const juce::MessageManagerLock mmLock;
  363. #endif
  364. if (carla_get_plugin_info(0)->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
  365. carla_show_custom_ui(0, false);
  366. return 0;
  367. }
  368. int CarlaBridgeOsc::handleMsgQuit()
  369. {
  370. carla_debug("CarlaBridgeOsc::handleMsgQuit()");
  371. gCloseNow = true;
  372. return 0;
  373. }
  374. // -------------------------------------------------------------------------
  375. int CarlaBridgeOsc::handleMsgPluginSaveNow()
  376. {
  377. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  378. carla_debug("CarlaBridgeOsc::handleMsgPluginSaveNow()");
  379. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  380. plugClient->saveNow();
  381. return 0;
  382. }
  383. int CarlaBridgeOsc::handleMsgPluginSetParameterMidiChannel(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  384. {
  385. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ii");
  386. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  387. carla_debug("CarlaBridgeOsc::handleMsgPluginSetParameterMidiChannel()");
  388. const int32_t index = argv[0]->i;
  389. const int32_t channel = argv[1]->i;
  390. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  391. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  392. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  393. plugClient->setParameterMidiChannel(static_cast<uint32_t>(index), static_cast<uint8_t>(channel));
  394. return 0;
  395. }
  396. int CarlaBridgeOsc::handleMsgPluginSetParameterMidiCC(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  397. {
  398. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ii");
  399. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  400. carla_debug("CarlaBridgeOsc::handleMsgPluginSetParameterMidiCC()");
  401. const int32_t index = argv[0]->i;
  402. const int32_t cc = argv[1]->i;
  403. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  404. CARLA_SAFE_ASSERT_RETURN(cc >= 1 && cc < 0x5F, 0);
  405. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  406. plugClient->setParameterMidiCC(static_cast<uint32_t>(index), static_cast<int16_t>(cc));
  407. return 0;
  408. }
  409. int CarlaBridgeOsc::handleMsgPluginSetChunk(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  410. {
  411. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(1, "s");
  412. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  413. carla_debug("CarlaBridgeOsc::handleMsgPluginSetChunk()");
  414. const char* const chunkFile = (const char*)&argv[0]->s;
  415. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  416. plugClient->setChunkData(chunkFile);
  417. return 0;
  418. }
  419. int CarlaBridgeOsc::handleMsgPluginSetCustomData(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  420. {
  421. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(3, "sss");
  422. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  423. carla_debug("CarlaBridgeOsc::handleMsgPluginSetCustomData()");
  424. const char* const type = (const char*)&argv[0]->s;
  425. const char* const key = (const char*)&argv[1]->s;
  426. const char* const value = (const char*)&argv[2]->s;
  427. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  428. plugClient->setCustomData(type, key, value);
  429. return 0;
  430. }
  431. CARLA_BRIDGE_END_NAMESPACE
  432. // -------------------------------------------------------------------------
  433. int main(int argc, char* argv[])
  434. {
  435. CARLA_BRIDGE_USE_NAMESPACE;
  436. // ---------------------------------------------------------------------
  437. // Check argument count
  438. if (argc != 7)
  439. {
  440. carla_stdout("usage: %s <osc-url|\"null\"> <type> <filename> <name|\"(none)\"> <label> <uniqueId>", argv[0]);
  441. return 1;
  442. }
  443. // ---------------------------------------------------------------------
  444. // Get args
  445. const char* const oscUrl = argv[1];
  446. const char* const stype = argv[2];
  447. const char* const filename = argv[3];
  448. const char* name = argv[4];
  449. const char* label = argv[5];
  450. const int64_t uniqueId = static_cast<int64_t>(std::atol(argv[6]));
  451. // ---------------------------------------------------------------------
  452. // Setup args
  453. const char* const shmIds(std::getenv("ENGINE_BRIDGE_SHM_IDS"));
  454. const bool useBridge = (shmIds != nullptr);
  455. const bool useOsc = (std::strcmp(oscUrl, "null") != 0 && std::strcmp(oscUrl, "(null)") != 0 && std::strcmp(oscUrl, "NULL") != 0);
  456. if (std::strcmp(name, "(none)") == 0)
  457. name = nullptr;
  458. //if (std::strlen(label) == 0)
  459. // label = nullptr;
  460. char bridgeBaseAudioName[6+1];
  461. char bridgeBaseControlName[6+1];
  462. char bridgeBaseTimeName[6+1];
  463. if (useBridge)
  464. {
  465. CARLA_SAFE_ASSERT_RETURN(std::strlen(shmIds) == 6*3, 1);
  466. std::strncpy(bridgeBaseAudioName, shmIds, 6);
  467. std::strncpy(bridgeBaseControlName, shmIds+6, 6);
  468. std::strncpy(bridgeBaseTimeName, shmIds+12, 6);
  469. bridgeBaseAudioName[6] = '\0';
  470. bridgeBaseControlName[6] = '\0';
  471. bridgeBaseTimeName[6] = '\0';
  472. }
  473. else
  474. {
  475. bridgeBaseAudioName[0] = '\0';
  476. bridgeBaseControlName[0] = '\0';
  477. bridgeBaseTimeName[0] = '\0';
  478. }
  479. // ---------------------------------------------------------------------
  480. // Check plugin type
  481. CarlaBackend::PluginType itype(CarlaBackend::getPluginTypeFromString(stype));
  482. if (itype == CarlaBackend::PLUGIN_NONE)
  483. {
  484. carla_stderr("Invalid plugin type '%s'", stype);
  485. return 1;
  486. }
  487. // ---------------------------------------------------------------------
  488. // Set client name
  489. CarlaString clientName((name != nullptr) ? name : label);
  490. //if (clientName.isEmpty())
  491. // clientName = File(filename).getFileNameWithoutExtension().toRawUTF8();
  492. // ---------------------------------------------------------------------
  493. // Set extraStuff
  494. const void* extraStuff = nullptr;
  495. if (itype == CarlaBackend::PLUGIN_GIG || itype == CarlaBackend::PLUGIN_SF2)
  496. {
  497. if (label == nullptr)
  498. label = clientName;
  499. if (std::strstr(label, " (16 outs)") == 0)
  500. extraStuff = "true";
  501. }
  502. // ---------------------------------------------------------------------
  503. // Init plugin client
  504. CarlaPluginClient client(useBridge, clientName, bridgeBaseAudioName, bridgeBaseControlName, bridgeBaseTimeName);
  505. if (! client.isOk())
  506. {
  507. carla_stderr("Failed to init engine, error was:\n%s", carla_get_last_error());
  508. return 1;
  509. }
  510. // ---------------------------------------------------------------------
  511. // Init OSC
  512. if (useOsc)
  513. client.oscInit(oscUrl);
  514. // ---------------------------------------------------------------------
  515. // Listen for ctrl+c or sigint/sigterm events
  516. initSignalHandler();
  517. // ---------------------------------------------------------------------
  518. // Init plugin
  519. int ret;
  520. if (carla_add_plugin(CarlaBackend::BINARY_NATIVE, itype, filename, name, label, uniqueId, extraStuff))
  521. {
  522. if (useOsc)
  523. {
  524. client.sendOscUpdate();
  525. client.sendOscBridgeUpdate();
  526. }
  527. else
  528. {
  529. carla_set_active(0, true);
  530. if (const CarlaPluginInfo* const pluginInfo = carla_get_plugin_info(0))
  531. {
  532. if (pluginInfo->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
  533. carla_show_custom_ui(0, true);
  534. }
  535. }
  536. client.ready(!useOsc);
  537. gIsInitiated = true;
  538. client.exec(argc, argv);
  539. carla_set_engine_about_to_close();
  540. carla_remove_plugin(0);
  541. ret = 0;
  542. }
  543. else
  544. {
  545. const char* const lastError(carla_get_last_error());
  546. carla_stderr("Plugin failed to load, error was:\n%s", lastError);
  547. if (useOsc)
  548. client.sendOscBridgeError(lastError);
  549. ret = 1;
  550. }
  551. // ---------------------------------------------------------------------
  552. // Close OSC
  553. if (useOsc)
  554. client.oscClose();
  555. return ret;
  556. }