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
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
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. /*
  2. * Carla Bridge Plugin
  3. * Copyright (C) 2012-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 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
  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 HAVE_JUCE
  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 HAVE_JUCE
  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
  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
  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. return; (void)argc; (void)argv;
  213. }
  214. // ---------------------------------------------------------------------
  215. // plugin management
  216. void saveNow()
  217. {
  218. CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,);
  219. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  220. carla_debug("CarlaPluginClient::saveNow()");
  221. fPlugin->prepareForSave();
  222. for (uint32_t i=0; i < fPlugin->getCustomDataCount(); ++i)
  223. {
  224. const CarlaBackend::CustomData& cdata(fPlugin->getCustomData(i));
  225. fEngine->oscSend_bridge_set_custom_data(cdata.type, cdata.key, cdata.value);
  226. }
  227. if (fPlugin->getOptionsEnabled() & CarlaBackend::PLUGIN_OPTION_USE_CHUNKS)
  228. {
  229. void* data = nullptr;
  230. int32_t dataSize = fPlugin->getChunkData(&data);
  231. if (data && dataSize >= 4)
  232. {
  233. #if 0
  234. QString filePath;
  235. filePath = QDir::tempPath();
  236. #ifdef Q_OS_WIN
  237. filePath += "\\.CarlaChunk_";
  238. #else
  239. filePath += "/.CarlaChunk_";
  240. #endif
  241. filePath += fPlugin->getName();
  242. QFile file(filePath);
  243. if (file.open(QIODevice::WriteOnly))
  244. {
  245. QByteArray chunk((const char*)data, dataSize);
  246. file.write(chunk);
  247. file.close();
  248. fEngine->oscSend_bridge_set_chunk_data(filePath.toUtf8().constData());
  249. }
  250. #endif
  251. }
  252. }
  253. fEngine->oscSend_bridge_configure(CARLA_BRIDGE_MSG_SAVED, "");
  254. }
  255. void setParameterMidiChannel(const uint32_t index, const uint8_t channel)
  256. {
  257. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  258. carla_debug("CarlaPluginClient::setParameterMidiChannel(%i, %i)", index, channel);
  259. fPlugin->setParameterMidiChannel(index, channel, false, false);
  260. }
  261. void setParameterMidiCC(const uint32_t index, const int16_t cc)
  262. {
  263. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  264. carla_debug("CarlaPluginClient::setParameterMidiCC(%i, %i)", index, cc);
  265. fPlugin->setParameterMidiCC(index, cc, false, false);
  266. }
  267. void setCustomData(const char* const type, const char* const key, const char* const value)
  268. {
  269. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  270. carla_debug("CarlaPluginClient::setCustomData(\"%s\", \"%s\", \"%s\")", type, key, value);
  271. fPlugin->setCustomData(type, key, value, true);
  272. }
  273. void setChunkData(const char* const filePath)
  274. {
  275. CARLA_SAFE_ASSERT_RETURN(filePath != nullptr && filePath[0] != '\0',);
  276. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  277. carla_debug("CarlaPluginClient::setChunkData(\"%s\")", filePath);
  278. #if 0
  279. QString chunkFilePath(filePath);
  280. #ifdef CARLA_OS_WIN
  281. if (chunkFilePath.startsWith("/"))
  282. {
  283. // running under Wine, posix host
  284. chunkFilePath = chunkFilePath.replace(0, 1, "Z:/");
  285. chunkFilePath = QDir::toNativeSeparators(chunkFilePath);
  286. }
  287. #endif
  288. QFile chunkFile(chunkFilePath);
  289. if (fPlugin != nullptr && chunkFile.open(QIODevice::ReadOnly | QIODevice::Text))
  290. {
  291. QTextStream in(&chunkFile);
  292. QString stringData(in.readAll());
  293. chunkFile.close();
  294. chunkFile.remove();
  295. fPlugin->setChunkData(stringData.toUtf8().constData());
  296. }
  297. #endif
  298. }
  299. // ---------------------------------------------------------------------
  300. protected:
  301. void handleCallback(const CarlaBackend::EngineCallbackOpcode action, const int value1, const int value2, const float value3, const char* const valueStr)
  302. {
  303. CARLA_BACKEND_USE_NAMESPACE;
  304. // TODO
  305. switch (action)
  306. {
  307. case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED:
  308. if (isOscControlRegistered())
  309. sendOscControl(value1, value3);
  310. break;
  311. case ENGINE_CALLBACK_UI_STATE_CHANGED:
  312. if (! isOscControlRegistered())
  313. {
  314. if (value1 != 1 && gIsInitiated)
  315. gCloseNow = true;
  316. }
  317. else
  318. {
  319. // show-gui button
  320. fEngine->oscSend_bridge_configure(CARLA_BRIDGE_MSG_HIDE_GUI, "");
  321. }
  322. break;
  323. default:
  324. break;
  325. }
  326. return;
  327. (void)value2;
  328. (void)value3;
  329. (void)valueStr;
  330. }
  331. private:
  332. CarlaBackend::CarlaPlugin* fPlugin;
  333. const CarlaBackend::CarlaEngine* fEngine;
  334. CarlaString fProjFileName;
  335. static void callback(void* ptr, CarlaBackend::EngineCallbackOpcode action, unsigned int pluginId, int value1, int value2, float value3, const char* valueStr)
  336. {
  337. carla_debug("CarlaPluginClient::callback(%p, %i:%s, %i, %i, %i, %f, \"%s\")", ptr, action, CarlaBackend::EngineCallbackOpcode2Str(action), pluginId, value1, value2, value3, valueStr);
  338. CARLA_SAFE_ASSERT_RETURN(ptr != nullptr,);
  339. CARLA_SAFE_ASSERT_RETURN(pluginId == 0,);
  340. return ((CarlaPluginClient*)ptr)->handleCallback(action, value1, value2, value3, valueStr);
  341. }
  342. };
  343. // -------------------------------------------------------------------------
  344. int CarlaBridgeOsc::handleMsgShow()
  345. {
  346. carla_debug("CarlaBridgeOsc::handleMsgShow()");
  347. #ifdef HAVE_JUCE
  348. const juce::MessageManagerLock mmLock;
  349. #endif
  350. if (carla_get_plugin_info(0)->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
  351. carla_show_custom_ui(0, true);
  352. return 0;
  353. }
  354. int CarlaBridgeOsc::handleMsgHide()
  355. {
  356. carla_debug("CarlaBridgeOsc::handleMsgHide()");
  357. #ifdef HAVE_JUCE
  358. const juce::MessageManagerLock mmLock;
  359. #endif
  360. if (carla_get_plugin_info(0)->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
  361. carla_show_custom_ui(0, false);
  362. return 0;
  363. }
  364. int CarlaBridgeOsc::handleMsgQuit()
  365. {
  366. carla_debug("CarlaBridgeOsc::handleMsgQuit()");
  367. gCloseNow = true;
  368. return 0;
  369. }
  370. // -------------------------------------------------------------------------
  371. int CarlaBridgeOsc::handleMsgPluginSaveNow()
  372. {
  373. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  374. carla_debug("CarlaBridgeOsc::handleMsgPluginSaveNow()");
  375. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  376. plugClient->saveNow();
  377. return 0;
  378. }
  379. int CarlaBridgeOsc::handleMsgPluginSetParameterMidiChannel(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  380. {
  381. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ii");
  382. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  383. carla_debug("CarlaBridgeOsc::handleMsgPluginSetParameterMidiChannel()");
  384. const int32_t index = argv[0]->i;
  385. const int32_t channel = argv[1]->i;
  386. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  387. CARLA_SAFE_ASSERT_RETURN(channel >= 0 && channel < MAX_MIDI_CHANNELS, 0);
  388. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  389. plugClient->setParameterMidiChannel(static_cast<uint32_t>(index), static_cast<uint8_t>(channel));
  390. return 0;
  391. }
  392. int CarlaBridgeOsc::handleMsgPluginSetParameterMidiCC(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  393. {
  394. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "ii");
  395. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  396. carla_debug("CarlaBridgeOsc::handleMsgPluginSetParameterMidiCC()");
  397. const int32_t index = argv[0]->i;
  398. const int32_t cc = argv[1]->i;
  399. CARLA_SAFE_ASSERT_RETURN(index >= 0, 0);
  400. CARLA_SAFE_ASSERT_RETURN(cc >= 1 && cc < 0x5F, 0);
  401. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  402. plugClient->setParameterMidiCC(static_cast<uint32_t>(index), static_cast<int16_t>(cc));
  403. return 0;
  404. }
  405. int CarlaBridgeOsc::handleMsgPluginSetChunk(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  406. {
  407. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(1, "s");
  408. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  409. carla_debug("CarlaBridgeOsc::handleMsgPluginSetChunk()");
  410. const char* const chunkFile = (const char*)&argv[0]->s;
  411. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  412. plugClient->setChunkData(chunkFile);
  413. return 0;
  414. }
  415. int CarlaBridgeOsc::handleMsgPluginSetCustomData(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  416. {
  417. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(3, "sss");
  418. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, 1);
  419. carla_debug("CarlaBridgeOsc::handleMsgPluginSetCustomData()");
  420. const char* const type = (const char*)&argv[0]->s;
  421. const char* const key = (const char*)&argv[1]->s;
  422. const char* const value = (const char*)&argv[2]->s;
  423. CarlaPluginClient* const plugClient((CarlaPluginClient*)fClient);
  424. plugClient->setCustomData(type, key, value);
  425. return 0;
  426. }
  427. CARLA_BRIDGE_END_NAMESPACE
  428. // -------------------------------------------------------------------------
  429. CarlaPlugin* CarlaPlugin::newJACK(const CarlaPlugin::Initializer&)
  430. {
  431. return nullptr;
  432. }
  433. // -------------------------------------------------------------------------
  434. int main(int argc, char* argv[])
  435. {
  436. CARLA_BRIDGE_USE_NAMESPACE;
  437. // ---------------------------------------------------------------------
  438. // Check argument count
  439. if (argc != 7)
  440. {
  441. carla_stdout("usage: %s <osc-url|\"null\"> <type> <filename> <name|\"(none)\"> <label> <uniqueId>", argv[0]);
  442. return 1;
  443. }
  444. // ---------------------------------------------------------------------
  445. // Get args
  446. const char* const oscUrl = argv[1];
  447. const char* const stype = argv[2];
  448. const char* const filename = argv[3];
  449. const char* name = argv[4];
  450. const char* label = argv[5];
  451. const int64_t uniqueId = static_cast<int64_t>(std::atol(argv[6]));
  452. // ---------------------------------------------------------------------
  453. // Setup args
  454. const char* const shmIds(std::getenv("ENGINE_BRIDGE_SHM_IDS"));
  455. const bool useBridge = (shmIds != nullptr);
  456. const bool useOsc = (std::strcmp(oscUrl, "null") != 0 && std::strcmp(oscUrl, "(null)") != 0 && std::strcmp(oscUrl, "NULL") != 0);
  457. if (std::strcmp(name, "(none)") == 0)
  458. name = nullptr;
  459. //if (std::strlen(label) == 0)
  460. // label = nullptr;
  461. char bridgeBaseAudioName[6+1];
  462. char bridgeBaseControlName[6+1];
  463. char bridgeBaseTimeName[6+1];
  464. if (useBridge)
  465. {
  466. CARLA_SAFE_ASSERT_RETURN(std::strlen(shmIds) == 6*3, 1);
  467. std::strncpy(bridgeBaseAudioName, shmIds, 6);
  468. std::strncpy(bridgeBaseControlName, shmIds+6, 6);
  469. std::strncpy(bridgeBaseTimeName, shmIds+12, 6);
  470. bridgeBaseAudioName[6] = '\0';
  471. bridgeBaseControlName[6] = '\0';
  472. bridgeBaseTimeName[6] = '\0';
  473. }
  474. else
  475. {
  476. bridgeBaseAudioName[0] = '\0';
  477. bridgeBaseControlName[0] = '\0';
  478. bridgeBaseTimeName[0] = '\0';
  479. }
  480. // ---------------------------------------------------------------------
  481. // Check plugin type
  482. CarlaBackend::PluginType itype(CarlaBackend::getPluginTypeFromString(stype));
  483. if (itype == CarlaBackend::PLUGIN_NONE)
  484. {
  485. carla_stderr("Invalid plugin type '%s'", stype);
  486. return 1;
  487. }
  488. // ---------------------------------------------------------------------
  489. // Set client name
  490. CarlaString clientName((name != nullptr) ? name : label);
  491. //if (clientName.isEmpty())
  492. // clientName = File(filename).getFileNameWithoutExtension().toRawUTF8();
  493. // ---------------------------------------------------------------------
  494. // Set extraStuff
  495. const void* extraStuff = nullptr;
  496. if (itype == CarlaBackend::PLUGIN_FILE_GIG || itype == CarlaBackend::PLUGIN_FILE_SF2)
  497. {
  498. if (label == nullptr)
  499. label = clientName;
  500. if (std::strstr(label, " (16 outs)") == 0)
  501. extraStuff = "true";
  502. }
  503. // ---------------------------------------------------------------------
  504. // Init plugin client
  505. CarlaPluginClient client(useBridge, clientName, bridgeBaseAudioName, bridgeBaseControlName, bridgeBaseTimeName);
  506. if (! client.isOk())
  507. {
  508. carla_stderr("Failed to init engine, error was:\n%s", carla_get_last_error());
  509. return 1;
  510. }
  511. // ---------------------------------------------------------------------
  512. // Init OSC
  513. if (useOsc)
  514. client.oscInit(oscUrl);
  515. // ---------------------------------------------------------------------
  516. // Listen for ctrl+c or sigint/sigterm events
  517. initSignalHandler();
  518. // ---------------------------------------------------------------------
  519. // Init plugin
  520. int ret;
  521. if (carla_add_plugin(CarlaBackend::BINARY_NATIVE, itype, filename, name, label, uniqueId, extraStuff))
  522. {
  523. if (useOsc)
  524. {
  525. client.sendOscUpdate();
  526. client.sendOscBridgeUpdate();
  527. }
  528. else
  529. {
  530. carla_set_active(0, true);
  531. if (const CarlaPluginInfo* const pluginInfo = carla_get_plugin_info(0))
  532. {
  533. if (pluginInfo->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
  534. carla_show_custom_ui(0, true);
  535. }
  536. }
  537. client.ready(!useOsc);
  538. gIsInitiated = true;
  539. client.exec(argc, argv);
  540. carla_set_engine_about_to_close();
  541. carla_remove_plugin(0);
  542. ret = 0;
  543. }
  544. else
  545. {
  546. const char* const lastError(carla_get_last_error());
  547. carla_stderr("Plugin failed to load, error was:\n%s", lastError);
  548. if (useOsc)
  549. client.sendOscBridgeError(lastError);
  550. ret = 1;
  551. }
  552. // ---------------------------------------------------------------------
  553. // Close OSC
  554. if (useOsc)
  555. client.oscClose();
  556. return ret;
  557. }