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.

CarlaStandalone.cpp 76KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423
  1. /*
  2. * Carla Standalone
  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 "CarlaStandalone.hpp"
  18. #include "CarlaBackendUtils.hpp"
  19. #include "CarlaOscUtils.hpp"
  20. #include "CarlaEngine.hpp"
  21. #include "CarlaPlugin.hpp"
  22. #include "CarlaMIDI.h"
  23. #include "CarlaNative.h"
  24. #ifndef BUILD_BRIDGE
  25. # include "CarlaStyle.hpp"
  26. # include <QtCore/QSettings>
  27. #else
  28. # include <QtCore/Qt>
  29. #endif
  30. #if defined(NDEBUG) && ! (defined(CARLA_OS_WIN) || defined(BUILD_BRIDGE))
  31. # define WANT_LOGS
  32. # include <fcntl.h>
  33. # include <QtCore/QThread>
  34. #endif
  35. #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
  36. # include <QtWidgets/QApplication>
  37. #else
  38. # include <QtGui/QApplication>
  39. #endif
  40. using CarlaBackend::CarlaEngine;
  41. using CarlaBackend::CarlaPlugin;
  42. using CarlaBackend::CallbackFunc;
  43. using CarlaBackend::EngineOptions;
  44. using CarlaBackend::EngineTimeInfo;
  45. #ifdef WANT_LOGS
  46. // -------------------------------------------------------------------------------------------------------------------
  47. // Log thread
  48. class LogThread : public QThread
  49. {
  50. public:
  51. LogThread()
  52. : fStop(false),
  53. fCallback(nullptr),
  54. fCallbackPtr(nullptr)
  55. {
  56. pipe(fPipe);
  57. fflush(stdout);
  58. fflush(stderr);
  59. //pipefd[1] = ::dup(STDOUT_FILENO);
  60. //pipefd[1] = ::dup(STDERR_FILENO);
  61. dup2(fPipe[1], STDOUT_FILENO);
  62. dup2(fPipe[1], STDERR_FILENO);
  63. fcntl(fPipe[0], F_SETFL, O_NONBLOCK);
  64. }
  65. ~LogThread()
  66. {
  67. fflush(stdout);
  68. fflush(stderr);
  69. close(fPipe[0]);
  70. close(fPipe[1]);
  71. }
  72. void ready(CallbackFunc callback, void* callbackPtr)
  73. {
  74. CARLA_ASSERT(callback != nullptr);
  75. fCallback = callback;
  76. fCallbackPtr = callbackPtr;
  77. start();
  78. }
  79. void stop()
  80. {
  81. fStop = true;
  82. if (isRunning())
  83. wait();
  84. }
  85. protected:
  86. void run()
  87. {
  88. if (fCallback == nullptr)
  89. return;
  90. while (! fStop)
  91. {
  92. int i, r, lastRead;
  93. static char bufTemp[1024+1] = { '\0' };
  94. static char bufRead[1024+1];
  95. static char bufSend[2048+1];
  96. while ((r = read(fPipe[0], bufRead, sizeof(char)*1024)) > 0)
  97. {
  98. bufRead[r] = '\0';
  99. lastRead = 0;
  100. for (i=0; i < r; ++i)
  101. {
  102. CARLA_ASSERT(bufRead[i] != '\0');
  103. if (bufRead[i] == '\n')
  104. {
  105. std::strcpy(bufSend, bufTemp);
  106. std::strncat(bufSend, bufRead+lastRead, i-lastRead);
  107. bufSend[std::strlen(bufTemp)+i-lastRead] = '\0';
  108. lastRead = i;
  109. bufTemp[0] = '\0';
  110. fCallback(fCallbackPtr, CarlaBackend::CALLBACK_DEBUG, 0, 0, 0, 0.0f, bufSend);
  111. }
  112. }
  113. CARLA_ASSERT(i == r);
  114. CARLA_ASSERT(lastRead < r);
  115. if (lastRead > 0 && lastRead < r-1)
  116. {
  117. std::strncpy(bufTemp, bufRead+lastRead, r-lastRead);
  118. bufTemp[r-lastRead] = '\0';
  119. }
  120. }
  121. carla_msleep(20);
  122. }
  123. }
  124. private:
  125. int fPipe[2];
  126. bool fStop;
  127. CallbackFunc fCallback;
  128. void* fCallbackPtr;
  129. };
  130. #endif
  131. // -------------------------------------------------------------------------------------------------------------------
  132. // Single, standalone engine
  133. struct CarlaBackendStandalone {
  134. CallbackFunc callback;
  135. void* callbackPtr;
  136. CarlaEngine* engine;
  137. CarlaString lastError;
  138. CarlaString procName;
  139. EngineOptions options;
  140. QApplication* app;
  141. bool needsInit;
  142. #ifdef WANT_LOGS
  143. LogThread logThread;
  144. #endif
  145. CarlaBackendStandalone()
  146. : callback(nullptr),
  147. callbackPtr(nullptr),
  148. engine(nullptr),
  149. app(qApp),
  150. needsInit(app == nullptr)
  151. {
  152. #ifndef BUILD_BRIDGE
  153. if (app != nullptr)
  154. {
  155. QSettings settings;
  156. if (settings.value("Main/UseProTheme", true).toBool())
  157. {
  158. CarlaStyle* const style(new CarlaStyle());
  159. app->setStyle(style);
  160. style->ready(app);
  161. QString color(settings.value("Main/ProThemeColor", "Black").toString());
  162. if (color == "System")
  163. pass(); //style->setColorScheme(CarlaStyle::COLOR_SYSTEM);
  164. else
  165. style->setColorScheme(CarlaStyle::COLOR_BLACK);
  166. }
  167. }
  168. #endif
  169. }
  170. ~CarlaBackendStandalone()
  171. {
  172. CARLA_ASSERT(engine == nullptr);
  173. #ifdef WANT_LOGS
  174. logThread.stop();
  175. #endif
  176. }
  177. void init()
  178. {
  179. if (! needsInit)
  180. return;
  181. if (app != nullptr)
  182. return;
  183. // try again, app might be registered now
  184. app = qApp;
  185. if (app != nullptr)
  186. {
  187. needsInit = false;
  188. return;
  189. }
  190. static int argc = 0;
  191. static char** argv = nullptr;
  192. app = new QApplication(argc, argv, true);
  193. }
  194. void close()
  195. {
  196. if (! needsInit)
  197. return;
  198. if (app == nullptr)
  199. return;
  200. app->quit();
  201. app->processEvents();
  202. delete app;
  203. app = nullptr;
  204. }
  205. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(CarlaBackendStandalone)
  206. } standalone;
  207. // -------------------------------------------------------------------------------------------------------------------
  208. // API
  209. const char* carla_get_extended_license_text()
  210. {
  211. carla_debug("carla_get_extended_license_text()");
  212. static CarlaString retText;
  213. if (retText.isEmpty())
  214. {
  215. CarlaString text1, text2;
  216. text1 += "<p>This current Carla build is using the following features and 3rd-party code:</p>";
  217. text1 += "<ul>";
  218. // Plugin formats
  219. #ifdef WANT_LADSPA
  220. text1 += "<li>LADSPA plugin support, http://www.ladspa.org/</li>";
  221. #endif
  222. #ifdef WANT_DSSI
  223. text1 += "<li>DSSI plugin support, http://dssi.sourceforge.net/</li>";
  224. #endif
  225. #ifdef WANT_LV2
  226. text1 += "<li>LV2 plugin support, http://lv2plug.in/</li>";
  227. #endif
  228. #ifdef WANT_VST
  229. # ifdef VESTIGE_HEADER
  230. text1 += "<li>VST plugin support, using VeSTige header by Javier Serrano Polo</li>";
  231. # else
  232. text1 += "<li>VST plugin support, using official VST SDK 2.4 (trademark of Steinberg Media Technologies GmbH)</li>";
  233. # endif
  234. #endif
  235. // Sample kit libraries
  236. #ifdef WANT_FLUIDSYNTH
  237. text1 += "<li>FluidSynth library for SF2 support, http://www.fluidsynth.org/</li>";
  238. #endif
  239. #ifdef WANT_LINUXSAMPLER
  240. text1 += "<li>LinuxSampler library for GIG and SFZ support*, http://www.linuxsampler.org/</li>";
  241. #endif
  242. // Internal plugins
  243. #ifdef WANT_OPENGL
  244. text1 += "<li>DISTRHO Mini-Series plugin code, based on LOSER-dev suite by Michael Gruhn</li>";
  245. #endif
  246. text1 += "<li>NekoFilter plugin code, based on lv2fil by Nedko Arnaudov and Fons Adriaensen</li>";
  247. //text1 += "<li>SunVox library file support, http://www.warmplace.ru/soft/sunvox/</li>"; // unfinished
  248. #ifdef WANT_AUDIOFILE
  249. text1 += "<li>AudioDecoder library for Audio file support, by Robin Gareus</li>";
  250. #endif
  251. #ifdef WANT_MIDIFILE
  252. text1 += "<li>LibSMF library for MIDI file support, http://libsmf.sourceforge.net/</li>";
  253. #endif
  254. #ifdef WANT_ZYNADDSUBFX
  255. text1 += "<li>ZynAddSubFX plugin code, http://zynaddsubfx.sf.net/</li>";
  256. # ifdef WANT_ZYNADDSUBFX_UI
  257. text1 += "<li>ZynAddSubFX UI using NTK, http://non.tuxfamily.org/wiki/NTK</li>";
  258. # endif
  259. #endif
  260. // misc libs
  261. text1 += "<li>liblo library for OSC support, http://liblo.sourceforge.net/</li>";
  262. #ifdef WANT_LV2
  263. text1 += "<li>serd, sord, sratom and lilv libraries for LV2 discovery, http://drobilla.net/software/lilv/</li>";
  264. #endif
  265. #ifdef WANT_RTAUDIO
  266. text1 += "<li>RtAudio+RtMidi libraries for extra Audio and MIDI support, http://www.music.mcgill.ca/~gary/rtaudio/</li>";
  267. #endif
  268. text1 += "</ul>";
  269. // code snippets
  270. text2 += "<p>Additionally, Carla uses code snippets from the following projects:</p>";
  271. text2 += "<ul>";
  272. text2 += "<li>Pointer and data leak utils from JUCE, http://www.rawmaterialsoftware.com/juce.php</li>";
  273. text2 += "<li>Shared memory utils from dssi-vst, http://www.breakfastquay.com/dssi-vst/</li>";
  274. text2 += "<li>Real-time memory pool, by Nedko Arnaudov</li>";
  275. text2 += "</ul>";
  276. // LinuxSampler GPL exception
  277. #ifdef WANT_LINUXSAMPLER
  278. text2 += "<p>(*) Using LinuxSampler code in commercial hardware or software products is not allowed without prior written authorization by the authors.</p>";
  279. #endif
  280. retText += text1;
  281. retText += text2;
  282. }
  283. return retText;
  284. }
  285. const char* carla_get_supported_file_types()
  286. {
  287. carla_debug("carla_get_supported_file_types()");
  288. static CarlaString retText;
  289. if (retText.isEmpty())
  290. {
  291. // Base types
  292. retText += "*.carxp;*.carxs";
  293. // Sample kits
  294. #ifdef WANT_FLUIDSYNTH
  295. retText += ";*.sf2";
  296. #endif
  297. #ifdef WANT_LINUXSAMPLER
  298. retText += ";*.gig;*.sfz";
  299. #endif
  300. // Files provided by internal plugins
  301. #ifdef WANT_AUDIOFILE
  302. retText += ";*.aiff;*.flac;*.oga;*.ogg;*.w64;*.wav";
  303. # ifdef HAVE_FFMPEG
  304. retText += ";*.3g2;*.3gp;*.aac;*.ac3;*.amr;*.ape;*.mp2;*.mp3;*.mpc;*.wma";
  305. # endif
  306. #endif
  307. #ifdef WANT_MIDIFILE
  308. retText += ";*.mid;*.midi";
  309. #endif
  310. // Plugin presets
  311. #ifdef WANT_ZYNADDSUBFX
  312. retText += ";*.xmz;*.xiz";
  313. #endif
  314. }
  315. return retText;
  316. }
  317. // -------------------------------------------------------------------------------------------------------------------
  318. unsigned int carla_get_engine_driver_count()
  319. {
  320. carla_debug("carla_get_engine_driver_count()");
  321. return CarlaEngine::getDriverCount();
  322. }
  323. const char* carla_get_engine_driver_name(unsigned int index)
  324. {
  325. carla_debug("carla_get_engine_driver_name(%i)", index);
  326. return CarlaEngine::getDriverName(index);
  327. }
  328. const char** carla_get_engine_driver_device_names(unsigned int index)
  329. {
  330. carla_debug("carla_get_engine_driver_device_names(%i)", index);
  331. return CarlaEngine::getDriverDeviceNames(index);
  332. }
  333. // -------------------------------------------------------------------------------------------------------------------
  334. unsigned int carla_get_internal_plugin_count()
  335. {
  336. carla_debug("carla_get_internal_plugin_count()");
  337. #ifdef WANT_NATIVE
  338. return static_cast<unsigned int>(CarlaPlugin::getNativePluginCount());
  339. #endif
  340. return 0;
  341. }
  342. const CarlaNativePluginInfo* carla_get_internal_plugin_info(unsigned int internalPluginId)
  343. {
  344. carla_debug("carla_get_internal_plugin_info(%i)", internalPluginId);
  345. static CarlaNativePluginInfo info;
  346. #ifdef WANT_NATIVE
  347. const PluginDescriptor* const nativePlugin(CarlaPlugin::getNativePluginDescriptor(internalPluginId));
  348. // as internal plugin, this must never fail
  349. CARLA_ASSERT(nativePlugin != nullptr);
  350. if (nativePlugin == nullptr)
  351. return nullptr;
  352. info.category = static_cast<CarlaPluginCategory>(nativePlugin->category);
  353. info.hints = 0x0;
  354. if (nativePlugin->hints & PLUGIN_IS_RTSAFE)
  355. info.hints |= CarlaBackend::PLUGIN_IS_RTSAFE;
  356. if (nativePlugin->hints & PLUGIN_IS_SYNTH)
  357. info.hints |= CarlaBackend::PLUGIN_IS_SYNTH;
  358. if (nativePlugin->hints & PLUGIN_HAS_GUI)
  359. info.hints |= CarlaBackend::PLUGIN_HAS_GUI;
  360. if (nativePlugin->hints & PLUGIN_USES_GUI_AS_FILE)
  361. info.hints |= CarlaBackend::PLUGIN_HAS_GUI_AS_FILE;
  362. if (nativePlugin->hints & PLUGIN_USES_SINGLE_THREAD)
  363. info.hints |= CarlaBackend::PLUGIN_HAS_SINGLE_THREAD;
  364. info.audioIns = nativePlugin->audioIns;
  365. info.audioOuts = nativePlugin->audioOuts;
  366. info.midiIns = nativePlugin->midiIns;
  367. info.midiOuts = nativePlugin->midiOuts;
  368. info.parameterIns = nativePlugin->parameterIns;
  369. info.parameterOuts = nativePlugin->parameterOuts;
  370. info.name = nativePlugin->name;
  371. info.label = nativePlugin->label;
  372. info.maker = nativePlugin->maker;
  373. info.copyright = nativePlugin->copyright;
  374. #endif
  375. return &info;
  376. #ifndef WANT_NATIVE
  377. // unused
  378. (void)internalPluginId;
  379. #endif
  380. }
  381. // -------------------------------------------------------------------------------------------------------------------
  382. bool carla_engine_init(const char* driverName, const char* clientName)
  383. {
  384. carla_debug("carla_engine_init(\"%s\", \"%s\")", driverName, clientName);
  385. CARLA_ASSERT(standalone.engine == nullptr);
  386. CARLA_ASSERT(driverName != nullptr);
  387. CARLA_ASSERT(clientName != nullptr);
  388. #ifndef NDEBUG
  389. static bool showWarning = true;
  390. if (showWarning && standalone.callback != nullptr)
  391. {
  392. standalone.callback(standalone.callbackPtr, CarlaBackend::CALLBACK_DEBUG, 0, 0, 0, 0.0f, "Debug builds don't use this, check the console instead");
  393. showWarning = false;
  394. }
  395. #endif
  396. #ifdef Q_OS_WIN
  397. carla_setenv("WINEASIO_CLIENT_NAME", clientName);
  398. #endif
  399. // TODO: make this an option, put somewhere else
  400. if (getenv("WINE_RT") == nullptr)
  401. {
  402. carla_setenv("WINE_RT", "15");
  403. carla_setenv("WINE_SVR_RT", "10");
  404. }
  405. if (standalone.engine != nullptr)
  406. {
  407. standalone.lastError = "Engine is already running";
  408. return false;
  409. }
  410. standalone.engine = CarlaEngine::newDriverByName(driverName);
  411. if (standalone.engine == nullptr)
  412. {
  413. standalone.lastError = "The seleted audio driver is not available!";
  414. return false;
  415. }
  416. if (standalone.callback != nullptr)
  417. standalone.engine->setCallback(standalone.callback, nullptr);
  418. #ifndef BUILD_BRIDGE
  419. standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_MODE, static_cast<int>(standalone.options.processMode), nullptr);
  420. # if 0 // disabled for now
  421. standalone.engine->setOption(CarlaBackend::OPTION_TRANSPORT_MODE, static_cast<int>(standalone.options.transportMode), nullptr);
  422. # endif
  423. standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo ? 1 : 0, nullptr);
  424. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES, standalone.options.preferPluginBridges ? 1 : 0, nullptr);
  425. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_UI_BRIDGES, standalone.options.preferUiBridges ? 1 : 0, nullptr);
  426. # ifdef WANT_DSSI
  427. standalone.engine->setOption(CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS, standalone.options.useDssiVstChunks ? 1 : 0, nullptr);
  428. # endif
  429. standalone.engine->setOption(CarlaBackend::OPTION_MAX_PARAMETERS, static_cast<int>(standalone.options.maxParameters), nullptr);
  430. standalone.engine->setOption(CarlaBackend::OPTION_OSC_UI_TIMEOUT, static_cast<int>(standalone.options.oscUiTimeout), nullptr);
  431. standalone.engine->setOption(CarlaBackend::OPTION_JACK_AUTOCONNECT, standalone.options.jackAutoConnect ? 1 : 0, nullptr);
  432. standalone.engine->setOption(CarlaBackend::OPTION_JACK_TIMEMASTER, standalone.options.jackTimeMaster ? 1 : 0, nullptr);
  433. # ifdef WANT_RTAUDIO
  434. standalone.engine->setOption(CarlaBackend::OPTION_RTAUDIO_BUFFER_SIZE, static_cast<int>(standalone.options.rtaudioBufferSize), nullptr);
  435. standalone.engine->setOption(CarlaBackend::OPTION_RTAUDIO_SAMPLE_RATE, static_cast<int>(standalone.options.rtaudioSampleRate), nullptr);
  436. standalone.engine->setOption(CarlaBackend::OPTION_RTAUDIO_DEVICE, 0, (const char*)standalone.options.rtaudioDevice);
  437. # endif
  438. standalone.engine->setOption(CarlaBackend::OPTION_PATH_RESOURCES, 0, (const char*)standalone.options.resourceDir);
  439. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_NATIVE, 0, (const char*)standalone.options.bridge_native);
  440. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_POSIX32, 0, (const char*)standalone.options.bridge_posix32);
  441. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_POSIX64, 0, (const char*)standalone.options.bridge_posix64);
  442. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_WIN32, 0, (const char*)standalone.options.bridge_win32);
  443. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_WIN64, 0, (const char*)standalone.options.bridge_win64);
  444. # ifdef WANT_LV2
  445. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK2, 0, (const char*)standalone.options.bridge_lv2Gtk2);
  446. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK3, 0, (const char*)standalone.options.bridge_lv2Gtk3);
  447. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_QT4, 0, (const char*)standalone.options.bridge_lv2Qt4);
  448. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_QT5, 0, (const char*)standalone.options.bridge_lv2Qt5);
  449. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_COCOA, 0, (const char*)standalone.options.bridge_lv2Cocoa);
  450. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_WINDOWS, 0, (const char*)standalone.options.bridge_lv2Win);
  451. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_LV2_X11, 0, (const char*)standalone.options.bridge_lv2X11);
  452. # endif
  453. # ifdef WANT_VST
  454. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_VST_COCOA, 0, (const char*)standalone.options.bridge_vstCocoa);
  455. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_VST_HWND, 0, (const char*)standalone.options.bridge_vstHWND);
  456. standalone.engine->setOption(CarlaBackend::OPTION_PATH_BRIDGE_VST_X11, 0, (const char*)standalone.options.bridge_vstX11);
  457. # endif
  458. if (standalone.procName.isNotEmpty())
  459. standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_NAME, 0, (const char*)standalone.procName);
  460. #endif
  461. if (standalone.engine->init(clientName))
  462. {
  463. standalone.lastError = "no error";
  464. standalone.init();
  465. return true;
  466. }
  467. else
  468. {
  469. standalone.lastError = standalone.engine->getLastError();
  470. delete standalone.engine;
  471. standalone.engine = nullptr;
  472. return false;
  473. }
  474. }
  475. bool carla_engine_close()
  476. {
  477. carla_debug("carla_engine_close()");
  478. CARLA_ASSERT(standalone.engine != nullptr);
  479. if (standalone.engine == nullptr)
  480. {
  481. standalone.lastError = "Engine is not started";
  482. return false;
  483. }
  484. standalone.engine->setAboutToClose();
  485. standalone.engine->removeAllPlugins();
  486. const bool closed(standalone.engine->close());
  487. if (! closed)
  488. standalone.lastError = standalone.engine->getLastError();
  489. delete standalone.engine;
  490. standalone.engine = nullptr;
  491. standalone.close();
  492. return closed;
  493. }
  494. void carla_engine_idle()
  495. {
  496. CARLA_ASSERT(standalone.engine != nullptr);
  497. if (standalone.needsInit && standalone.app != nullptr)
  498. standalone.app->processEvents();
  499. if (standalone.engine != nullptr)
  500. standalone.engine->idle();
  501. }
  502. bool carla_is_engine_running()
  503. {
  504. carla_debug("carla_is_engine_running()");
  505. return (standalone.engine != nullptr && standalone.engine->isRunning());
  506. }
  507. void carla_set_engine_about_to_close()
  508. {
  509. carla_debug("carla_set_engine_about_to_close()");
  510. CARLA_ASSERT(standalone.engine != nullptr);
  511. if (standalone.engine != nullptr)
  512. standalone.engine->setAboutToClose();
  513. }
  514. void carla_set_engine_callback(CarlaCallbackFunc func, void* ptr)
  515. {
  516. carla_debug("carla_set_engine_callback(%p)", func);
  517. standalone.callback = func;
  518. standalone.callbackPtr = ptr;
  519. #ifdef WANT_LOGS
  520. standalone.logThread.ready(func, ptr);
  521. #endif
  522. if (standalone.engine != nullptr)
  523. standalone.engine->setCallback(func, ptr);
  524. }
  525. void carla_set_engine_option(CarlaOptionsType option, int value, const char* valueStr)
  526. {
  527. carla_debug("carla_set_engine_option(%s, %i, \"%s\")", CarlaBackend::OptionsType2Str(option), value, valueStr);
  528. switch (option)
  529. {
  530. case CarlaBackend::OPTION_PROCESS_NAME:
  531. standalone.procName = valueStr;
  532. break;
  533. case CarlaBackend::OPTION_PROCESS_MODE:
  534. if (value < CarlaBackend::PROCESS_MODE_SINGLE_CLIENT || value > CarlaBackend::PROCESS_MODE_PATCHBAY)
  535. return carla_stderr2("carla_set_engine_option(OPTION_PROCESS_MODE, %i, \"%s\") - invalid value", value, valueStr);
  536. standalone.options.processMode = static_cast<CarlaBackend::ProcessMode>(value);
  537. break;
  538. case CarlaBackend::OPTION_TRANSPORT_MODE:
  539. #if 0 // disabled for now
  540. if (value < CarlaBackend::TRANSPORT_MODE_INTERNAL || value > CarlaBackend::TRANSPORT_MODE_JACK)
  541. return carla_stderr2("carla_set_engine_option(OPTION_TRANSPORT_MODE, %i, \"%s\") - invalid value", value, valueStr);
  542. standalone.options.transportMode = static_cast<CarlaBackend::TransportMode>(value);
  543. #endif
  544. break;
  545. case CarlaBackend::OPTION_FORCE_STEREO:
  546. standalone.options.forceStereo = (value != 0);
  547. break;
  548. case CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES:
  549. standalone.options.preferPluginBridges = (value != 0);
  550. break;
  551. case CarlaBackend::OPTION_PREFER_UI_BRIDGES:
  552. standalone.options.preferUiBridges = (value != 0);
  553. break;
  554. #ifdef WANT_DSSI
  555. case CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS:
  556. standalone.options.useDssiVstChunks = (value != 0);
  557. break;
  558. #endif
  559. case CarlaBackend::OPTION_MAX_PARAMETERS:
  560. if (value <= 0)
  561. return carla_stderr2("carla_set_engine_option(OPTION_MAX_PARAMETERS, %i, \"%s\") - invalid value", value, valueStr);
  562. standalone.options.maxParameters = static_cast<unsigned int>(value);
  563. break;
  564. case CarlaBackend::OPTION_OSC_UI_TIMEOUT:
  565. if (value <= 0)
  566. return carla_stderr2("carla_set_engine_option(OPTION_OSC_UI_TIMEOUT, %i, \"%s\") - invalid value", value, valueStr);
  567. standalone.options.oscUiTimeout = static_cast<unsigned int>(value);
  568. break;
  569. case CarlaBackend::OPTION_JACK_AUTOCONNECT:
  570. standalone.options.jackAutoConnect = (value != 0);
  571. break;
  572. case CarlaBackend::OPTION_JACK_TIMEMASTER:
  573. standalone.options.jackTimeMaster = (value != 0);
  574. break;
  575. #ifdef WANT_RTAUDIO
  576. case CarlaBackend::OPTION_RTAUDIO_BUFFER_SIZE:
  577. if (value <= 0)
  578. return carla_stderr2("carla_set_engine_option(OPTION_RTAUDIO_BUFFER_SIZE, %i, \"%s\") - invalid value", value, valueStr);
  579. standalone.options.rtaudioBufferSize = static_cast<unsigned int>(value);
  580. break;
  581. case CarlaBackend::OPTION_RTAUDIO_SAMPLE_RATE:
  582. if (value <= 0)
  583. return carla_stderr2("carla_set_engine_option(OPTION_RTAUDIO_SAMPLE_RATE, %i, \"%s\") - invalid value", value, valueStr);
  584. standalone.options.rtaudioSampleRate = static_cast<unsigned int>(value);
  585. break;
  586. case CarlaBackend::OPTION_RTAUDIO_DEVICE:
  587. standalone.options.rtaudioDevice = valueStr;
  588. break;
  589. #endif
  590. case CarlaBackend::OPTION_PATH_RESOURCES:
  591. standalone.options.resourceDir = valueStr;
  592. break;
  593. #ifndef BUILD_BRIDGE
  594. case CarlaBackend::OPTION_PATH_BRIDGE_NATIVE:
  595. standalone.options.bridge_native = valueStr;
  596. break;
  597. case CarlaBackend::OPTION_PATH_BRIDGE_POSIX32:
  598. standalone.options.bridge_posix32 = valueStr;
  599. break;
  600. case CarlaBackend::OPTION_PATH_BRIDGE_POSIX64:
  601. standalone.options.bridge_posix64 = valueStr;
  602. break;
  603. case CarlaBackend::OPTION_PATH_BRIDGE_WIN32:
  604. standalone.options.bridge_win32 = valueStr;
  605. break;
  606. case CarlaBackend::OPTION_PATH_BRIDGE_WIN64:
  607. standalone.options.bridge_win64 = valueStr;
  608. break;
  609. #endif
  610. #ifdef WANT_LV2
  611. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK2:
  612. standalone.options.bridge_lv2Gtk2 = valueStr;
  613. break;
  614. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_GTK3:
  615. standalone.options.bridge_lv2Gtk3 = valueStr;
  616. break;
  617. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_QT4:
  618. standalone.options.bridge_lv2Qt4 = valueStr;
  619. break;
  620. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_QT5:
  621. standalone.options.bridge_lv2Qt5 = valueStr;
  622. break;
  623. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_COCOA:
  624. standalone.options.bridge_lv2Cocoa = valueStr;
  625. break;
  626. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_WINDOWS:
  627. standalone.options.bridge_lv2Win = valueStr;
  628. break;
  629. case CarlaBackend::OPTION_PATH_BRIDGE_LV2_X11:
  630. standalone.options.bridge_lv2X11 = valueStr;
  631. break;
  632. #endif
  633. #ifdef WANT_VST
  634. case CarlaBackend::OPTION_PATH_BRIDGE_VST_COCOA:
  635. standalone.options.bridge_vstCocoa = valueStr;
  636. break;
  637. case CarlaBackend::OPTION_PATH_BRIDGE_VST_HWND:
  638. standalone.options.bridge_vstHWND = valueStr;
  639. break;
  640. case CarlaBackend::OPTION_PATH_BRIDGE_VST_X11:
  641. standalone.options.bridge_vstX11 = valueStr;
  642. break;
  643. #endif
  644. }
  645. if (standalone.engine != nullptr)
  646. standalone.engine->setOption(option, value, valueStr);
  647. }
  648. // -------------------------------------------------------------------------------------------------------------------
  649. bool carla_load_filename(const char* filename)
  650. {
  651. carla_debug("carla_load_filename(\"%s\")", filename);
  652. CARLA_ASSERT(standalone.engine != nullptr);
  653. CARLA_ASSERT(filename != nullptr);
  654. if (standalone.engine != nullptr && standalone.engine->isRunning())
  655. return standalone.engine->loadFilename(filename);
  656. standalone.lastError = "Engine is not started";
  657. return false;
  658. }
  659. bool carla_load_project(const char* filename)
  660. {
  661. carla_debug("carla_load_project(\"%s\")", filename);
  662. CARLA_ASSERT(standalone.engine != nullptr);
  663. CARLA_ASSERT(filename != nullptr);
  664. if (standalone.engine != nullptr && standalone.engine->isRunning())
  665. return standalone.engine->loadProject(filename);
  666. standalone.lastError = "Engine is not started";
  667. return false;
  668. }
  669. bool carla_save_project(const char* filename)
  670. {
  671. carla_debug("carla_save_project(\"%s\")", filename);
  672. CARLA_ASSERT(standalone.engine != nullptr);
  673. CARLA_ASSERT(filename != nullptr);
  674. if (standalone.engine != nullptr) // allow to save even if engine stopped
  675. return standalone.engine->saveProject(filename);
  676. standalone.lastError = "Engine is not started";
  677. return false;
  678. }
  679. // -------------------------------------------------------------------------------------------------------------------
  680. bool carla_patchbay_connect(int portA, int portB)
  681. {
  682. carla_debug("carla_patchbay_connect(%i, %i)", portA, portB);
  683. CARLA_ASSERT(standalone.engine != nullptr);
  684. if (standalone.engine != nullptr && standalone.engine->isRunning())
  685. return standalone.engine->patchbayConnect(portA, portB);
  686. standalone.lastError = "Engine is not started";
  687. return false;
  688. }
  689. bool carla_patchbay_disconnect(int connectionId)
  690. {
  691. carla_debug("carla_patchbay_disconnect(%i)", connectionId);
  692. CARLA_ASSERT(standalone.engine != nullptr);
  693. if (standalone.engine != nullptr && standalone.engine->isRunning())
  694. return standalone.engine->patchbayDisconnect(connectionId);
  695. standalone.lastError = "Engine is not started";
  696. return false;
  697. }
  698. void carla_patchbay_refresh()
  699. {
  700. carla_debug("carla_patchbay_refresh()");
  701. CARLA_ASSERT(standalone.engine != nullptr);
  702. if (standalone.engine != nullptr && standalone.engine->isRunning())
  703. standalone.engine->patchbayRefresh();
  704. }
  705. // -------------------------------------------------------------------------------------------------------------------
  706. void carla_transport_play()
  707. {
  708. carla_debug("carla_transport_play()");
  709. CARLA_ASSERT(standalone.engine != nullptr);
  710. if (standalone.engine != nullptr && standalone.engine->isRunning())
  711. standalone.engine->transportPlay();
  712. }
  713. void carla_transport_pause()
  714. {
  715. carla_debug("carla_transport_pause()");
  716. CARLA_ASSERT(standalone.engine != nullptr);
  717. if (standalone.engine != nullptr && standalone.engine->isRunning())
  718. standalone.engine->transportPause();
  719. }
  720. void carla_transport_relocate(uint32_t frames)
  721. {
  722. carla_debug("carla_transport_relocate(%i)", frames);
  723. CARLA_ASSERT(standalone.engine != nullptr);
  724. if (standalone.engine != nullptr && standalone.engine->isRunning())
  725. standalone.engine->transportRelocate(frames);
  726. }
  727. uint32_t carla_get_current_transport_frame()
  728. {
  729. CARLA_ASSERT(standalone.engine != nullptr);
  730. if (standalone.engine != nullptr)
  731. {
  732. const EngineTimeInfo& timeInfo(standalone.engine->getTimeInfo());
  733. return timeInfo.frame;
  734. }
  735. return 0;
  736. }
  737. const CarlaTransportInfo* carla_get_transport_info()
  738. {
  739. CARLA_ASSERT(standalone.engine != nullptr);
  740. static CarlaTransportInfo info;
  741. if (standalone.engine != nullptr)
  742. {
  743. const EngineTimeInfo& timeInfo(standalone.engine->getTimeInfo());
  744. info.playing = timeInfo.playing;
  745. info.frame = timeInfo.frame;
  746. if (timeInfo.valid & timeInfo.ValidBBT)
  747. {
  748. info.bar = timeInfo.bbt.bar;
  749. info.beat = timeInfo.bbt.beat;
  750. info.tick = timeInfo.bbt.tick;
  751. info.bpm = timeInfo.bbt.beatsPerMinute;
  752. }
  753. else
  754. {
  755. info.bar = 0;
  756. info.beat = 0;
  757. info.tick = 0;
  758. info.bpm = 0.0;
  759. }
  760. }
  761. else
  762. {
  763. info.playing = false;
  764. info.frame = 0;
  765. info.bar = 0;
  766. info.beat = 0;
  767. info.tick = 0;
  768. info.bpm = 0.0;
  769. }
  770. return &info;
  771. }
  772. // -------------------------------------------------------------------------------------------------------------------
  773. bool carla_add_plugin(CarlaBinaryType btype, CarlaPluginType ptype, const char* filename, const char* const name, const char* label, const void* extraStuff)
  774. {
  775. carla_debug("carla_add_plugin(%s, %s, \"%s\", \"%s\", \"%s\", %p)", CarlaBackend::BinaryType2Str(btype), CarlaBackend::PluginType2Str(ptype), filename, name, label, extraStuff);
  776. CARLA_ASSERT(standalone.engine != nullptr);
  777. if (standalone.engine != nullptr && standalone.engine->isRunning())
  778. return standalone.engine->addPlugin(btype, ptype, filename, name, label, extraStuff);
  779. standalone.lastError = "Engine is not started";
  780. return false;
  781. }
  782. bool carla_remove_plugin(unsigned int pluginId)
  783. {
  784. carla_debug("carla_remove_plugin(%i)", pluginId);
  785. CARLA_ASSERT(standalone.engine != nullptr);
  786. if (standalone.engine != nullptr && standalone.engine->isRunning())
  787. return standalone.engine->removePlugin(pluginId);
  788. standalone.lastError = "Engine is not started";
  789. return false;
  790. }
  791. void carla_remove_all_plugins()
  792. {
  793. carla_debug("carla_remove_all_plugins()");
  794. CARLA_ASSERT(standalone.engine != nullptr);
  795. if (standalone.engine != nullptr && standalone.engine->isRunning())
  796. standalone.engine->removeAllPlugins();
  797. }
  798. const char* carla_rename_plugin(unsigned int pluginId, const char* newName)
  799. {
  800. carla_debug("carla_rename_plugin(%i, \"%s\")", pluginId, newName);
  801. CARLA_ASSERT(standalone.engine != nullptr);
  802. if (standalone.engine != nullptr && standalone.engine->isRunning())
  803. return standalone.engine->renamePlugin(pluginId, newName);
  804. standalone.lastError = "Engine is not started";
  805. return nullptr;
  806. }
  807. bool carla_clone_plugin(unsigned int pluginId)
  808. {
  809. carla_debug("carla_clone_plugin(%i)", pluginId);
  810. CARLA_ASSERT(standalone.engine != nullptr);
  811. if (standalone.engine != nullptr && standalone.engine->isRunning())
  812. return standalone.engine->clonePlugin(pluginId);
  813. standalone.lastError = "Engine is not started";
  814. return false;
  815. }
  816. bool carla_replace_plugin(unsigned int pluginId)
  817. {
  818. carla_debug("carla_replace_plugin(%i)", pluginId);
  819. CARLA_ASSERT(standalone.engine != nullptr);
  820. if (standalone.engine != nullptr && standalone.engine->isRunning())
  821. return standalone.engine->replacePlugin(pluginId);
  822. standalone.lastError = "Engine is not started";
  823. return false;
  824. }
  825. bool carla_switch_plugins(unsigned int pluginIdA, unsigned int pluginIdB)
  826. {
  827. carla_debug("carla_switch_plugins(%i, %i)", pluginIdA, pluginIdB);
  828. CARLA_ASSERT(standalone.engine != nullptr);
  829. if (standalone.engine != nullptr && standalone.engine->isRunning())
  830. return standalone.engine->switchPlugins(pluginIdA, pluginIdB);
  831. standalone.lastError = "Engine is not started";
  832. return false;
  833. }
  834. // -------------------------------------------------------------------------------------------------------------------
  835. bool carla_load_plugin_state(unsigned int pluginId, const char* filename)
  836. {
  837. carla_debug("carla_load_plugin_state(%i, \"%s\")", pluginId, filename);
  838. CARLA_ASSERT(standalone.engine != nullptr);
  839. if (standalone.engine == nullptr || ! standalone.engine->isRunning())
  840. {
  841. standalone.lastError = "Engine is not started";
  842. return false;
  843. }
  844. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  845. return plugin->loadStateFromFile(filename);
  846. carla_stderr2("carla_load_plugin_state(%i, \"%s\") - could not find plugin", pluginId, filename);
  847. return false;
  848. }
  849. bool carla_save_plugin_state(unsigned int pluginId, const char* filename)
  850. {
  851. carla_debug("carla_save_plugin_state(%i, \"%s\")", pluginId, filename);
  852. CARLA_ASSERT(standalone.engine != nullptr);
  853. if (standalone.engine == nullptr)
  854. {
  855. standalone.lastError = "Engine is not started";
  856. return false;
  857. }
  858. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  859. return plugin->saveStateToFile(filename);
  860. carla_stderr2("carla_save_plugin_state(%i, \"%s\") - could not find plugin", pluginId, filename);
  861. return false;
  862. }
  863. // -------------------------------------------------------------------------------------------------------------------
  864. const CarlaPluginInfo* carla_get_plugin_info(unsigned int pluginId)
  865. {
  866. carla_debug("carla_get_plugin_info(%i)", pluginId);
  867. CARLA_ASSERT(standalone.engine != nullptr);
  868. static CarlaPluginInfo info;
  869. // reset
  870. info.type = CarlaBackend::PLUGIN_NONE;
  871. info.category = CarlaBackend::PLUGIN_CATEGORY_NONE;
  872. info.hints = 0x0;
  873. info.hints = 0x0;
  874. info.binary = nullptr;
  875. info.name = nullptr;
  876. info.uniqueId = 0;
  877. info.latency = 0;
  878. info.optionsAvailable = 0x0;
  879. info.optionsEnabled = 0x0;
  880. // cleanup
  881. if (info.label != nullptr)
  882. {
  883. delete[] info.label;
  884. info.label = nullptr;
  885. }
  886. if (info.maker != nullptr)
  887. {
  888. delete[] info.maker;
  889. info.maker = nullptr;
  890. }
  891. if (info.copyright != nullptr)
  892. {
  893. delete[] info.copyright;
  894. info.copyright = nullptr;
  895. }
  896. if (standalone.engine == nullptr)
  897. return &info;
  898. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  899. {
  900. char strBufLabel[STR_MAX+1] = { '\0' };
  901. char strBufMaker[STR_MAX+1] = { '\0' };
  902. char strBufCopyright[STR_MAX+1] = { '\0' };
  903. info.type = plugin->type();
  904. info.category = plugin->category();
  905. info.hints = plugin->hints();
  906. info.binary = plugin->filename();
  907. info.name = plugin->name();
  908. info.uniqueId = plugin->uniqueId();
  909. info.latency = plugin->latency();
  910. info.optionsAvailable = plugin->availableOptions();
  911. info.optionsEnabled = plugin->options();
  912. plugin->getLabel(strBufLabel);
  913. info.label = carla_strdup(strBufLabel);
  914. plugin->getMaker(strBufMaker);
  915. info.maker = carla_strdup(strBufMaker);
  916. plugin->getCopyright(strBufCopyright);
  917. info.copyright = carla_strdup(strBufCopyright);
  918. return &info;
  919. }
  920. carla_stderr2("carla_get_plugin_info(%i) - could not find plugin", pluginId);
  921. return &info;
  922. }
  923. const CarlaPortCountInfo* carla_get_audio_port_count_info(unsigned int pluginId)
  924. {
  925. carla_debug("carla_get_audio_port_count_info(%i)", pluginId);
  926. CARLA_ASSERT(standalone.engine != nullptr);
  927. static CarlaPortCountInfo info;
  928. // reset
  929. info.ins = 0;
  930. info.outs = 0;
  931. info.total = 0;
  932. if (standalone.engine == nullptr)
  933. return &info;
  934. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  935. {
  936. info.ins = plugin->audioInCount();
  937. info.outs = plugin->audioOutCount();
  938. info.total = info.ins + info.outs;
  939. return &info;
  940. }
  941. carla_stderr2("carla_get_audio_port_count_info(%i) - could not find plugin", pluginId);
  942. return &info;
  943. }
  944. const CarlaPortCountInfo* carla_get_midi_port_count_info(unsigned int pluginId)
  945. {
  946. carla_debug("carla_get_midi_port_count_info(%i)", pluginId);
  947. CARLA_ASSERT(standalone.engine != nullptr);
  948. static CarlaPortCountInfo info;
  949. // reset
  950. info.ins = 0;
  951. info.outs = 0;
  952. info.total = 0;
  953. if (standalone.engine == nullptr)
  954. return &info;
  955. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  956. {
  957. info.ins = plugin->midiInCount();
  958. info.outs = plugin->midiOutCount();
  959. info.total = info.ins + info.outs;
  960. return &info;
  961. }
  962. carla_stderr2("carla_get_midi_port_count_info(%i) - could not find plugin", pluginId);
  963. return &info;
  964. }
  965. const CarlaPortCountInfo* carla_get_parameter_count_info(unsigned int pluginId)
  966. {
  967. carla_debug("carla_get_parameter_count_info(%i)", pluginId);
  968. CARLA_ASSERT(standalone.engine != nullptr);
  969. static CarlaPortCountInfo info;
  970. // reset
  971. info.ins = 0;
  972. info.outs = 0;
  973. info.total = 0;
  974. if (standalone.engine == nullptr)
  975. return &info;
  976. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  977. {
  978. plugin->getParameterCountInfo(&info.ins, &info.outs, &info.total);
  979. return &info;
  980. }
  981. carla_stderr2("carla_get_parameter_count_info(%i) - could not find plugin", pluginId);
  982. return &info;
  983. }
  984. const CarlaParameterInfo* carla_get_parameter_info(unsigned int pluginId, uint32_t parameterId)
  985. {
  986. carla_debug("carla_get_parameter_info(%i, %i)", pluginId, parameterId);
  987. CARLA_ASSERT(standalone.engine != nullptr);
  988. static CarlaParameterInfo info;
  989. // reset
  990. info.scalePointCount = 0;
  991. // cleanup
  992. if (info.name != nullptr)
  993. {
  994. delete[] info.name;
  995. info.name = nullptr;
  996. }
  997. if (info.symbol != nullptr)
  998. {
  999. delete[] info.symbol;
  1000. info.symbol = nullptr;
  1001. }
  1002. if (info.unit != nullptr)
  1003. {
  1004. delete[] info.unit;
  1005. info.unit = nullptr;
  1006. }
  1007. if (standalone.engine == nullptr)
  1008. return &info;
  1009. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1010. {
  1011. if (parameterId < plugin->parameterCount())
  1012. {
  1013. char strBufName[STR_MAX+1] = { '\0' };
  1014. char strBufSymbol[STR_MAX+1] = { '\0' };
  1015. char strBufUnit[STR_MAX+1] = { '\0' };
  1016. info.scalePointCount = plugin->parameterScalePointCount(parameterId);
  1017. plugin->getParameterName(parameterId, strBufName);
  1018. info.name = carla_strdup(strBufName);
  1019. plugin->getParameterSymbol(parameterId, strBufSymbol);
  1020. info.symbol = carla_strdup(strBufSymbol);
  1021. plugin->getParameterUnit(parameterId, strBufUnit);
  1022. info.unit = carla_strdup(strBufUnit);
  1023. }
  1024. else
  1025. carla_stderr2("carla_get_parameter_info(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  1026. return &info;
  1027. }
  1028. carla_stderr2("carla_get_parameter_info(%i, %i) - could not find plugin", pluginId, parameterId);
  1029. return &info;
  1030. }
  1031. const CarlaScalePointInfo* carla_get_parameter_scalepoint_info(unsigned int pluginId, uint32_t parameterId, uint32_t scalePointId)
  1032. {
  1033. carla_debug("carla_get_parameter_scalepoint_info(%i, %i, %i)", pluginId, parameterId, scalePointId);
  1034. CARLA_ASSERT(standalone.engine != nullptr);
  1035. static CarlaScalePointInfo info;
  1036. // reset
  1037. info.value = 0.0f;
  1038. // cleanup
  1039. if (info.label != nullptr)
  1040. {
  1041. delete[] info.label;
  1042. info.label = nullptr;
  1043. }
  1044. if (standalone.engine == nullptr)
  1045. return &info;
  1046. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1047. {
  1048. if (parameterId < plugin->parameterCount())
  1049. {
  1050. if (scalePointId < plugin->parameterScalePointCount(parameterId))
  1051. {
  1052. char strBufLabel[STR_MAX+1] = { '\0' };
  1053. info.value = plugin->getParameterScalePointValue(parameterId, scalePointId);
  1054. plugin->getParameterScalePointLabel(parameterId, scalePointId, strBufLabel);
  1055. info.label = carla_strdup(strBufLabel);
  1056. }
  1057. else
  1058. carla_stderr2("carla_get_parameter_scalepoint_info(%i, %i, %i) - scalePointId out of bounds", pluginId, parameterId, scalePointId);
  1059. }
  1060. else
  1061. carla_stderr2("carla_get_parameter_scalepoint_info(%i, %i, %i) - parameterId out of bounds", pluginId, parameterId, scalePointId);
  1062. return &info;
  1063. }
  1064. carla_stderr2("carla_get_parameter_scalepoint_info(%i, %i, %i) - could not find plugin", pluginId, parameterId, scalePointId);
  1065. return &info;
  1066. }
  1067. // -------------------------------------------------------------------------------------------------------------------
  1068. const CarlaParameterData* carla_get_parameter_data(unsigned int pluginId, uint32_t parameterId)
  1069. {
  1070. carla_debug("carla_get_parameter_data(%i, %i)", pluginId, parameterId);
  1071. CARLA_ASSERT(standalone.engine != nullptr);
  1072. static CarlaParameterData data;
  1073. if (standalone.engine == nullptr)
  1074. return &data;
  1075. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1076. {
  1077. if (parameterId < plugin->parameterCount())
  1078. return &plugin->parameterData(parameterId);
  1079. carla_stderr2("carla_get_parameter_data(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  1080. return &data;
  1081. }
  1082. carla_stderr2("carla_get_parameter_data(%i, %i) - could not find plugin", pluginId, parameterId);
  1083. return &data;
  1084. }
  1085. const CarlaParameterRanges* carla_get_parameter_ranges(unsigned int pluginId, uint32_t parameterId)
  1086. {
  1087. carla_debug("carla_get_parameter_ranges(%i, %i)", pluginId, parameterId);
  1088. CARLA_ASSERT(standalone.engine != nullptr);
  1089. static CarlaParameterRanges ranges;
  1090. if (standalone.engine == nullptr)
  1091. return &ranges;
  1092. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1093. {
  1094. if (parameterId < plugin->parameterCount())
  1095. return &plugin->parameterRanges(parameterId);
  1096. carla_stderr2("carla_get_parameter_ranges(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  1097. return &ranges;
  1098. }
  1099. carla_stderr2("carla_get_parameter_ranges(%i, %i) - could not find plugin", pluginId, parameterId);
  1100. return &ranges;
  1101. }
  1102. const CarlaMidiProgramData* carla_get_midi_program_data(unsigned int pluginId, uint32_t midiProgramId)
  1103. {
  1104. carla_debug("carla_get_midi_program_data(%i, %i)", pluginId, midiProgramId);
  1105. CARLA_ASSERT(standalone.engine != nullptr);
  1106. static CarlaMidiProgramData data;
  1107. if (standalone.engine == nullptr)
  1108. return &data;
  1109. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1110. {
  1111. if (midiProgramId < plugin->midiProgramCount())
  1112. return &plugin->midiProgramData(midiProgramId);
  1113. carla_stderr2("carla_get_midi_program_data(%i, %i) - midiProgramId out of bounds", pluginId, midiProgramId);
  1114. return &data;
  1115. }
  1116. carla_stderr2("carla_get_midi_program_data(%i, %i) - could not find plugin", pluginId, midiProgramId);
  1117. return &data;
  1118. }
  1119. const CarlaCustomData* carla_get_custom_data(unsigned int pluginId, uint32_t customDataId)
  1120. {
  1121. carla_debug("carla_get_custom_data(%i, %i)", pluginId, customDataId);
  1122. CARLA_ASSERT(standalone.engine != nullptr);
  1123. static CarlaCustomData data;
  1124. if (standalone.engine == nullptr)
  1125. return &data;
  1126. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1127. {
  1128. if (customDataId < plugin->customDataCount())
  1129. return &plugin->customData(customDataId);
  1130. carla_stderr2("carla_get_custom_data(%i, %i) - customDataId out of bounds", pluginId, customDataId);
  1131. return &data;
  1132. }
  1133. carla_stderr2("carla_get_custom_data(%i, %i) - could not find plugin", pluginId, customDataId);
  1134. return &data;
  1135. }
  1136. const char* carla_get_chunk_data(unsigned int pluginId)
  1137. {
  1138. carla_debug("carla_get_chunk_data(%i)", pluginId);
  1139. CARLA_ASSERT(standalone.engine != nullptr);
  1140. if (standalone.engine == nullptr)
  1141. return nullptr;
  1142. static CarlaString chunkData;
  1143. // cleanup
  1144. chunkData.clear();
  1145. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1146. {
  1147. if (plugin->options() & CarlaBackend::PLUGIN_OPTION_USE_CHUNKS)
  1148. {
  1149. void* data = nullptr;
  1150. const int32_t dataSize = plugin->chunkData(&data);
  1151. if (data != nullptr && dataSize > 0)
  1152. {
  1153. QByteArray chunk(QByteArray((char*)data, dataSize).toBase64());
  1154. chunkData = chunk.constData();
  1155. return (const char*)chunkData;
  1156. }
  1157. else
  1158. carla_stderr2("carla_get_chunk_data(%i) - got invalid chunk data", pluginId);
  1159. }
  1160. else
  1161. carla_stderr2("carla_get_chunk_data(%i) - plugin does not support chunks", pluginId);
  1162. return nullptr;
  1163. }
  1164. carla_stderr2("carla_get_chunk_data(%i) - could not find plugin", pluginId);
  1165. return nullptr;
  1166. }
  1167. // -------------------------------------------------------------------------------------------------------------------
  1168. uint32_t carla_get_parameter_count(unsigned int pluginId)
  1169. {
  1170. carla_debug("carla_get_parameter_count(%i)", pluginId);
  1171. CARLA_ASSERT(standalone.engine != nullptr);
  1172. if (standalone.engine == nullptr)
  1173. return 0;
  1174. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1175. return plugin->parameterCount();
  1176. carla_stderr2("carla_get_parameter_count(%i) - could not find plugin", pluginId);
  1177. return 0;
  1178. }
  1179. uint32_t carla_get_program_count(unsigned int pluginId)
  1180. {
  1181. carla_debug("carla_get_program_count(%i)", pluginId);
  1182. CARLA_ASSERT(standalone.engine != nullptr);
  1183. if (standalone.engine == nullptr)
  1184. return 0;
  1185. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1186. return plugin->programCount();
  1187. carla_stderr2("carla_get_program_count(%i) - could not find plugin", pluginId);
  1188. return 0;
  1189. }
  1190. uint32_t carla_get_midi_program_count(unsigned int pluginId)
  1191. {
  1192. carla_debug("carla_get_midi_program_count(%i)", pluginId);
  1193. CARLA_ASSERT(standalone.engine != nullptr);
  1194. if (standalone.engine == nullptr)
  1195. return 0;
  1196. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1197. return plugin->midiProgramCount();
  1198. carla_stderr2("carla_get_midi_program_count(%i) - could not find plugin", pluginId);
  1199. return 0;
  1200. }
  1201. uint32_t carla_get_custom_data_count(unsigned int pluginId)
  1202. {
  1203. carla_debug("carla_get_custom_data_count(%i)", pluginId);
  1204. CARLA_ASSERT(standalone.engine != nullptr);
  1205. if (standalone.engine == nullptr)
  1206. return 0;
  1207. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1208. return plugin->customDataCount();
  1209. carla_stderr2("carla_get_custom_data_count(%i) - could not find plugin", pluginId);
  1210. return 0;
  1211. }
  1212. // -------------------------------------------------------------------------------------------------------------------
  1213. const char* carla_get_parameter_text(unsigned int pluginId, uint32_t parameterId)
  1214. {
  1215. carla_debug("carla_get_parameter_text(%i, %i)", pluginId, parameterId);
  1216. CARLA_ASSERT(standalone.engine != nullptr);
  1217. if (standalone.engine == nullptr)
  1218. return nullptr;
  1219. static char textBuf[STR_MAX+1];
  1220. carla_fill<char>(textBuf, STR_MAX+1, '\0');
  1221. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1222. {
  1223. if (parameterId < plugin->parameterCount())
  1224. {
  1225. plugin->getParameterText(parameterId, textBuf);
  1226. return textBuf;
  1227. }
  1228. carla_stderr2("carla_get_parameter_text(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  1229. return nullptr;
  1230. }
  1231. carla_stderr2("carla_get_parameter_text(%i, %i) - could not find plugin", pluginId, parameterId);
  1232. return nullptr;
  1233. }
  1234. const char* carla_get_program_name(unsigned int pluginId, uint32_t programId)
  1235. {
  1236. carla_debug("carla_get_program_name(%i, %i)", pluginId, programId);
  1237. CARLA_ASSERT(standalone.engine != nullptr);
  1238. if (standalone.engine == nullptr)
  1239. return nullptr;
  1240. static char programName[STR_MAX+1];
  1241. carla_fill<char>(programName, STR_MAX+1, '\0');
  1242. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1243. {
  1244. if (programId < plugin->programCount())
  1245. {
  1246. plugin->getProgramName(programId, programName);
  1247. return programName;
  1248. }
  1249. carla_stderr2("carla_get_program_name(%i, %i) - programId out of bounds", pluginId, programId);
  1250. return nullptr;
  1251. }
  1252. carla_stderr2("carla_get_program_name(%i, %i) - could not find plugin", pluginId, programId);
  1253. return nullptr;
  1254. }
  1255. const char* carla_get_midi_program_name(unsigned int pluginId, uint32_t midiProgramId)
  1256. {
  1257. carla_debug("carla_get_midi_program_name(%i, %i)", pluginId, midiProgramId);
  1258. CARLA_ASSERT(standalone.engine != nullptr);
  1259. if (standalone.engine == nullptr)
  1260. return nullptr;
  1261. static char midiProgramName[STR_MAX+1];
  1262. carla_fill<char>(midiProgramName, STR_MAX+1, '\0');
  1263. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1264. {
  1265. if (midiProgramId < plugin->midiProgramCount())
  1266. {
  1267. plugin->getMidiProgramName(midiProgramId, midiProgramName);
  1268. return midiProgramName;
  1269. }
  1270. carla_stderr2("carla_get_midi_program_name(%i, %i) - midiProgramId out of bounds", pluginId, midiProgramId);
  1271. return nullptr;
  1272. }
  1273. carla_stderr2("carla_get_midi_program_name(%i, %i) - could not find plugin", pluginId, midiProgramId);
  1274. return nullptr;
  1275. }
  1276. const char* carla_get_real_plugin_name(unsigned int pluginId)
  1277. {
  1278. carla_debug("carla_get_real_plugin_name(%i)", pluginId);
  1279. CARLA_ASSERT(standalone.engine != nullptr);
  1280. if (standalone.engine == nullptr)
  1281. return nullptr;
  1282. static char realPluginName[STR_MAX+1];
  1283. carla_fill<char>(realPluginName, STR_MAX+1, '\0');
  1284. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1285. {
  1286. plugin->getRealName(realPluginName);
  1287. return realPluginName;
  1288. }
  1289. carla_stderr2("carla_get_real_plugin_name(%i) - could not find plugin", pluginId);
  1290. return nullptr;
  1291. }
  1292. // -------------------------------------------------------------------------------------------------------------------
  1293. int32_t carla_get_current_program_index(unsigned int pluginId)
  1294. {
  1295. carla_debug("carla_get_current_program_index(%i)", pluginId);
  1296. CARLA_ASSERT(standalone.engine != nullptr);
  1297. if (standalone.engine == nullptr)
  1298. return -1;
  1299. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1300. return plugin->currentProgram();
  1301. carla_stderr2("carla_get_current_program_index(%i) - could not find plugin", pluginId);
  1302. return -1;
  1303. }
  1304. int32_t carla_get_current_midi_program_index(unsigned int pluginId)
  1305. {
  1306. carla_debug("carla_get_current_midi_program_index(%i)", pluginId);
  1307. CARLA_ASSERT(standalone.engine != nullptr);
  1308. if (standalone.engine == nullptr)
  1309. return -1;
  1310. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1311. return plugin->currentMidiProgram();
  1312. carla_stderr2("carla_get_current_midi_program_index(%i) - could not find plugin", pluginId);
  1313. return -1;
  1314. }
  1315. // -------------------------------------------------------------------------------------------------------------------
  1316. float carla_get_default_parameter_value(unsigned int pluginId, uint32_t parameterId)
  1317. {
  1318. carla_debug("carla_get_default_parameter_value(%i, %i)", pluginId, parameterId);
  1319. CARLA_ASSERT(standalone.engine != nullptr);
  1320. if (standalone.engine == nullptr)
  1321. return 0.0f;
  1322. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1323. {
  1324. if (parameterId < plugin->parameterCount())
  1325. return plugin->parameterRanges(parameterId).def;
  1326. carla_stderr2("carla_get_default_parameter_value(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  1327. return 0.0f;
  1328. }
  1329. carla_stderr2("carla_get_default_parameter_value(%i, %i) - could not find plugin", pluginId, parameterId);
  1330. return 0.0f;
  1331. }
  1332. float carla_get_current_parameter_value(unsigned int pluginId, uint32_t parameterId)
  1333. {
  1334. carla_debug("carla_get_current_parameter_value(%i, %i)", pluginId, parameterId);
  1335. CARLA_ASSERT(standalone.engine != nullptr);
  1336. if (standalone.engine == nullptr)
  1337. return 0.0f;
  1338. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1339. {
  1340. if (parameterId < plugin->parameterCount())
  1341. return plugin->getParameterValue(parameterId);
  1342. carla_stderr2("carla_get_current_parameter_value(%i, %i) - parameterId out of bounds", pluginId, parameterId);
  1343. return 0.0f;
  1344. }
  1345. carla_stderr2("carla_get_current_parameter_value(%i, %i) - could not find plugin", pluginId, parameterId);
  1346. return 0.0f;
  1347. }
  1348. // -------------------------------------------------------------------------------------------------------------------
  1349. float carla_get_input_peak_value(unsigned int pluginId, unsigned short portId)
  1350. {
  1351. CARLA_ASSERT(standalone.engine != nullptr);
  1352. CARLA_ASSERT(portId == 1 || portId == 2);
  1353. if (standalone.engine == nullptr)
  1354. return 0.0f;
  1355. return standalone.engine->getInputPeak(pluginId, portId);
  1356. }
  1357. float carla_get_output_peak_value(unsigned int pluginId, unsigned short portId)
  1358. {
  1359. CARLA_ASSERT(standalone.engine != nullptr);
  1360. CARLA_ASSERT(portId == 1 || portId == 2);
  1361. if (standalone.engine == nullptr)
  1362. return 0.0f;
  1363. return standalone.engine->getOutputPeak(pluginId, portId);
  1364. }
  1365. // -------------------------------------------------------------------------------------------------------------------
  1366. void carla_set_option(unsigned int pluginId, unsigned int option, bool yesNo)
  1367. {
  1368. carla_debug("carla_set_option(%i, %i, %s)", pluginId, option, bool2str(yesNo));
  1369. CARLA_ASSERT(standalone.engine != nullptr);
  1370. if (standalone.engine == nullptr)
  1371. return;
  1372. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1373. return plugin->setOption(option, yesNo);
  1374. carla_stderr2("carla_set_option(%i, %i, %s) - could not find plugin", pluginId, option, bool2str(yesNo));
  1375. }
  1376. void carla_set_active(unsigned int pluginId, bool onOff)
  1377. {
  1378. carla_debug("carla_set_active(%i, %s)", pluginId, bool2str(onOff));
  1379. CARLA_ASSERT(standalone.engine != nullptr);
  1380. if (standalone.engine == nullptr)
  1381. return;
  1382. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1383. return plugin->setActive(onOff, true, false);
  1384. carla_stderr2("carla_set_active(%i, %s) - could not find plugin", pluginId, bool2str(onOff));
  1385. }
  1386. #ifndef BUILD_BRIDGE
  1387. void carla_set_drywet(unsigned int pluginId, float value)
  1388. {
  1389. carla_debug("carla_set_drywet(%i, %f)", pluginId, value);
  1390. CARLA_ASSERT(standalone.engine != nullptr);
  1391. if (standalone.engine == nullptr)
  1392. return;
  1393. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1394. return plugin->setDryWet(value, true, false);
  1395. carla_stderr2("carla_set_drywet(%i, %f) - could not find plugin", pluginId, value);
  1396. }
  1397. void carla_set_volume(unsigned int pluginId, float value)
  1398. {
  1399. carla_debug("carla_set_volume(%i, %f)", pluginId, value);
  1400. CARLA_ASSERT(standalone.engine != nullptr);
  1401. if (standalone.engine == nullptr)
  1402. return;
  1403. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1404. return plugin->setVolume(value, true, false);
  1405. carla_stderr2("carla_set_volume(%i, %f) - could not find plugin", pluginId, value);
  1406. }
  1407. void carla_set_balance_left(unsigned int pluginId, float value)
  1408. {
  1409. carla_debug("carla_set_balance_left(%i, %f)", pluginId, value);
  1410. CARLA_ASSERT(standalone.engine != nullptr);
  1411. if (standalone.engine == nullptr)
  1412. return;
  1413. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1414. return plugin->setBalanceLeft(value, true, false);
  1415. carla_stderr2("carla_set_balance_left(%i, %f) - could not find plugin", pluginId, value);
  1416. }
  1417. void carla_set_balance_right(unsigned int pluginId, float value)
  1418. {
  1419. carla_debug("carla_set_balance_right(%i, %f)", pluginId, value);
  1420. CARLA_ASSERT(standalone.engine != nullptr);
  1421. if (standalone.engine == nullptr)
  1422. return;
  1423. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1424. return plugin->setBalanceRight(value, true, false);
  1425. carla_stderr2("carla_set_balance_right(%i, %f) - could not find plugin", pluginId, value);
  1426. }
  1427. void carla_set_panning(unsigned int pluginId, float value)
  1428. {
  1429. carla_debug("carla_set_panning(%i, %f)", pluginId, value);
  1430. CARLA_ASSERT(standalone.engine != nullptr);
  1431. if (standalone.engine == nullptr)
  1432. return;
  1433. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1434. return plugin->setPanning(value, true, false);
  1435. carla_stderr2("carla_set_panning(%i, %f) - could not find plugin", pluginId, value);
  1436. }
  1437. #endif
  1438. void carla_set_ctrl_channel(unsigned int pluginId, int8_t channel)
  1439. {
  1440. carla_debug("carla_set_ctrl_channel(%i, %i)", pluginId, channel);
  1441. CARLA_ASSERT(standalone.engine != nullptr);
  1442. if (standalone.engine == nullptr)
  1443. return;
  1444. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1445. return plugin->setCtrlChannel(channel, true, false);
  1446. carla_stderr2("carla_set_ctrl_channel(%i, %i) - could not find plugin", pluginId, channel);
  1447. }
  1448. // -------------------------------------------------------------------------------------------------------------------
  1449. void carla_set_parameter_value(unsigned int pluginId, uint32_t parameterId, float value)
  1450. {
  1451. carla_debug("carla_set_parameter_value(%i, %i, %f)", pluginId, parameterId, value);
  1452. CARLA_ASSERT(standalone.engine != nullptr);
  1453. if (standalone.engine == nullptr)
  1454. return;
  1455. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1456. {
  1457. if (parameterId < plugin->parameterCount())
  1458. return plugin->setParameterValue(parameterId, value, true, true, false);
  1459. carla_stderr2("carla_set_parameter_value(%i, %i, %f) - parameterId out of bounds", pluginId, parameterId, value);
  1460. return;
  1461. }
  1462. carla_stderr2("carla_set_parameter_value(%i, %i, %f) - could not find plugin", pluginId, parameterId, value);
  1463. }
  1464. #ifndef BUILD_BRIDGE
  1465. void carla_set_parameter_midi_channel(unsigned int pluginId, uint32_t parameterId, uint8_t channel)
  1466. {
  1467. carla_debug("carla_set_parameter_midi_channel(%i, %i, %i)", pluginId, parameterId, channel);
  1468. CARLA_ASSERT(standalone.engine != nullptr);
  1469. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  1470. if (channel >= MAX_MIDI_CHANNELS)
  1471. {
  1472. carla_stderr2("carla_set_parameter_midi_channel(%i, %i, %i) - invalid channel number", pluginId, parameterId, channel);
  1473. return;
  1474. }
  1475. if (standalone.engine == nullptr)
  1476. return;
  1477. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1478. {
  1479. if (parameterId < plugin->parameterCount())
  1480. return plugin->setParameterMidiChannel(parameterId, channel, true, false);
  1481. carla_stderr2("carla_set_parameter_midi_channel(%i, %i, %i) - parameterId out of bounds", pluginId, parameterId, channel);
  1482. return;
  1483. }
  1484. carla_stderr2("carla_set_parameter_midi_channel(%i, %i, %i) - could not find plugin", pluginId, parameterId, channel);
  1485. }
  1486. void carla_set_parameter_midi_cc(unsigned int pluginId, uint32_t parameterId, int16_t cc)
  1487. {
  1488. carla_debug("carla_set_parameter_midi_cc(%i, %i, %i)", pluginId, parameterId, cc);
  1489. CARLA_ASSERT(standalone.engine != nullptr);
  1490. CARLA_ASSERT(cc >= -1 && cc <= 0x5F);
  1491. if (cc < -1)
  1492. {
  1493. cc = -1;
  1494. }
  1495. else if (cc > 0x5F) // 95
  1496. {
  1497. carla_stderr2("carla_set_parameter_midi_cc(%i, %i, %i) - invalid cc number", pluginId, parameterId, cc);
  1498. return;
  1499. }
  1500. if (standalone.engine == nullptr)
  1501. return;
  1502. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1503. {
  1504. if (parameterId < plugin->parameterCount())
  1505. return plugin->setParameterMidiCC(parameterId, cc, true, false);
  1506. carla_stderr2("carla_set_parameter_midi_cc(%i, %i, %i) - parameterId out of bounds", pluginId, parameterId, cc);
  1507. return;
  1508. }
  1509. carla_stderr2("carla_set_parameter_midi_cc(%i, %i, %i) - could not find plugin", pluginId, parameterId, cc);
  1510. }
  1511. #endif
  1512. // -------------------------------------------------------------------------------------------------------------------
  1513. void carla_set_program(unsigned int pluginId, uint32_t programId)
  1514. {
  1515. carla_debug("carla_set_program(%i, %i)", pluginId, programId);
  1516. CARLA_ASSERT(standalone.engine != nullptr);
  1517. if (standalone.engine == nullptr)
  1518. return;
  1519. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1520. {
  1521. if (programId < plugin->programCount())
  1522. return plugin->setProgram(static_cast<int32_t>(programId), true, true, false);
  1523. carla_stderr2("carla_set_program(%i, %i) - programId out of bounds", pluginId, programId);
  1524. return;
  1525. }
  1526. carla_stderr2("carla_set_program(%i, %i) - could not find plugin", pluginId, programId);
  1527. }
  1528. void carla_set_midi_program(unsigned int pluginId, uint32_t midiProgramId)
  1529. {
  1530. carla_debug("carla_set_midi_program(%i, %i)", pluginId, midiProgramId);
  1531. CARLA_ASSERT(standalone.engine != nullptr);
  1532. if (standalone.engine == nullptr)
  1533. return;
  1534. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1535. {
  1536. if (midiProgramId < plugin->midiProgramCount())
  1537. return plugin->setMidiProgram(static_cast<int32_t>(midiProgramId), true, true, false);
  1538. carla_stderr2("carla_set_midi_program(%i, %i) - midiProgramId out of bounds", pluginId, midiProgramId);
  1539. return;
  1540. }
  1541. carla_stderr2("carla_set_midi_program(%i, %i) - could not find plugin", pluginId, midiProgramId);
  1542. }
  1543. // -------------------------------------------------------------------------------------------------------------------
  1544. void carla_set_custom_data(unsigned int pluginId, const char* type, const char* key, const char* value)
  1545. {
  1546. carla_debug("carla_set_custom_data(%i, \"%s\", \"%s\", \"%s\")", pluginId, type, key, value);
  1547. CARLA_ASSERT(standalone.engine != nullptr);
  1548. if (standalone.engine == nullptr)
  1549. return;
  1550. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1551. return plugin->setCustomData(type, key, value, true);
  1552. carla_stderr2("carla_set_custom_data(%i, \"%s\", \"%s\", \"%s\") - could not find plugin", pluginId, type, key, value);
  1553. }
  1554. void carla_set_chunk_data(unsigned int pluginId, const char* chunkData)
  1555. {
  1556. carla_debug("carla_set_chunk_data(%i, \"%s\")", pluginId, chunkData);
  1557. CARLA_ASSERT(standalone.engine != nullptr);
  1558. if (standalone.engine == nullptr)
  1559. return;
  1560. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1561. {
  1562. if (plugin->options() & CarlaBackend::PLUGIN_OPTION_USE_CHUNKS)
  1563. return plugin->setChunkData(chunkData);
  1564. carla_stderr2("carla_set_chunk_data(%i, \"%s\") - plugin does not support chunks", pluginId, chunkData);
  1565. return;
  1566. }
  1567. carla_stderr2("carla_set_chunk_data(%i, \"%s\") - could not find plugin", pluginId, chunkData);
  1568. }
  1569. // -------------------------------------------------------------------------------------------------------------------
  1570. void carla_prepare_for_save(unsigned int pluginId)
  1571. {
  1572. carla_debug("carla_prepare_for_save(%i)", pluginId);
  1573. CARLA_ASSERT(standalone.engine != nullptr);
  1574. if (standalone.engine == nullptr)
  1575. return;
  1576. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1577. return plugin->prepareForSave();
  1578. carla_stderr2("carla_prepare_for_save(%i) - could not find plugin", pluginId);
  1579. }
  1580. #ifndef BUILD_BRIDGE
  1581. void carla_send_midi_note(unsigned int pluginId, uint8_t channel, uint8_t note, uint8_t velocity)
  1582. {
  1583. carla_debug("carla_send_midi_note(%i, %i, %i, %i)", pluginId, channel, note, velocity);
  1584. CARLA_ASSERT(standalone.engine != nullptr);
  1585. if (standalone.engine == nullptr || ! standalone.engine->isRunning())
  1586. return;
  1587. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1588. return plugin->sendMidiSingleNote(channel, note, velocity, true, true, false);
  1589. carla_stderr2("carla_send_midi_note(%i, %i, %i, %i) - could not find plugin", pluginId, channel, note, velocity);
  1590. }
  1591. #endif
  1592. void carla_show_gui(unsigned int pluginId, bool yesno)
  1593. {
  1594. carla_debug("carla_show_gui(%i, %s)", pluginId, bool2str(yesno));
  1595. CARLA_ASSERT(standalone.engine != nullptr);
  1596. if (standalone.engine == nullptr)
  1597. return;
  1598. if (CarlaPlugin* const plugin = standalone.engine->getPlugin(pluginId))
  1599. return plugin->showGui(yesno);
  1600. carla_stderr2("carla_show_gui(%i, %s) - could not find plugin", pluginId, bool2str(yesno));
  1601. }
  1602. // -------------------------------------------------------------------------------------------------------------------
  1603. uint32_t carla_get_buffer_size()
  1604. {
  1605. carla_debug("carla_get_buffer_size()");
  1606. CARLA_ASSERT(standalone.engine != nullptr);
  1607. if (standalone.engine == nullptr)
  1608. return 0;
  1609. return standalone.engine->getBufferSize();
  1610. }
  1611. double carla_get_sample_rate()
  1612. {
  1613. carla_debug("carla_get_sample_rate()");
  1614. CARLA_ASSERT(standalone.engine != nullptr);
  1615. if (standalone.engine == nullptr)
  1616. return 0.0;
  1617. return standalone.engine->getSampleRate();
  1618. }
  1619. // -------------------------------------------------------------------------------------------------------------------
  1620. const char* carla_get_last_error()
  1621. {
  1622. carla_debug("carla_get_last_error()");
  1623. if (standalone.engine != nullptr)
  1624. return standalone.engine->getLastError();
  1625. return standalone.lastError;
  1626. }
  1627. const char* carla_get_host_osc_url_tcp()
  1628. {
  1629. carla_debug("carla_get_host_osc_url_tcp()");
  1630. CARLA_ASSERT(standalone.engine != nullptr);
  1631. if (standalone.engine == nullptr)
  1632. {
  1633. standalone.lastError = "Engine is not started";
  1634. return nullptr;
  1635. }
  1636. return standalone.engine->getOscServerPathTCP();
  1637. }
  1638. const char* carla_get_host_osc_url_udp()
  1639. {
  1640. carla_debug("carla_get_host_osc_url_udp()");
  1641. CARLA_ASSERT(standalone.engine != nullptr);
  1642. if (standalone.engine == nullptr)
  1643. {
  1644. standalone.lastError = "Engine is not started";
  1645. return nullptr;
  1646. }
  1647. return standalone.engine->getOscServerPathUDP();
  1648. }
  1649. // -------------------------------------------------------------------------------------------------------------------
  1650. #define NSM_API_VERSION_MAJOR 1
  1651. #define NSM_API_VERSION_MINOR 2
  1652. class CarlaNSM
  1653. {
  1654. public:
  1655. CarlaNSM()
  1656. : fServerThread(nullptr),
  1657. fReplyAddr(nullptr),
  1658. fIsReady(false),
  1659. fIsOpened(false),
  1660. fIsSaved(false)
  1661. {
  1662. }
  1663. ~CarlaNSM()
  1664. {
  1665. if (fReplyAddr != nullptr)
  1666. lo_address_free(fReplyAddr);
  1667. if (fServerThread != nullptr)
  1668. {
  1669. lo_server_thread_stop(fServerThread);
  1670. lo_server_thread_del_method(fServerThread, "/reply", "ssss");
  1671. lo_server_thread_del_method(fServerThread, "/nsm/client/open", "sss");
  1672. lo_server_thread_del_method(fServerThread, "/nsm/client/save", "");
  1673. lo_server_thread_free(fServerThread);
  1674. }
  1675. }
  1676. void announce(const char* const url, const char* appName, const int pid)
  1677. {
  1678. lo_address const addr = lo_address_new_from_url(url);
  1679. if (addr == nullptr)
  1680. return;
  1681. const int proto = lo_address_get_protocol(addr);
  1682. if (fServerThread == nullptr)
  1683. {
  1684. // create new OSC thread
  1685. fServerThread = lo_server_thread_new_with_proto(nullptr, proto, error_handler);
  1686. // register message handlers and start OSC thread
  1687. lo_server_thread_add_method(fServerThread, "/reply", "ssss", _reply_handler, this);
  1688. lo_server_thread_add_method(fServerThread, "/nsm/client/open", "sss", _open_handler, this);
  1689. lo_server_thread_add_method(fServerThread, "/nsm/client/save", "", _save_handler, this);
  1690. lo_server_thread_start(fServerThread);
  1691. }
  1692. #ifndef BUILD_ANSI_TEST
  1693. lo_send_from(addr, lo_server_thread_get_server(fServerThread), LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii",
  1694. "Carla", ":switch:", appName, NSM_API_VERSION_MAJOR, NSM_API_VERSION_MINOR, pid);
  1695. #endif
  1696. lo_address_free(addr);
  1697. }
  1698. void ready()
  1699. {
  1700. fIsReady = true;
  1701. }
  1702. void replyOpen()
  1703. {
  1704. fIsOpened = true;
  1705. }
  1706. void replySave()
  1707. {
  1708. fIsSaved = true;
  1709. }
  1710. protected:
  1711. int handleReply(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg)
  1712. {
  1713. carla_debug("CarlaNSM::handleReply(%s, %i, %p, %s, %p)", path, argc, argv, types, msg);
  1714. if (fReplyAddr != nullptr)
  1715. lo_address_free(fReplyAddr);
  1716. fIsOpened = false;
  1717. fIsSaved = false;
  1718. char* const url = lo_address_get_url(lo_message_get_source(msg));
  1719. fReplyAddr = lo_address_new_from_url(url);
  1720. std::free(url);
  1721. const char* const method = &argv[0]->s;
  1722. const char* const smName = &argv[2]->s;
  1723. // wait max 6 secs for host to init
  1724. for (int i=0; i < 60 && ! fIsReady; ++i)
  1725. carla_msleep(100);
  1726. if (std::strcmp(method, "/nsm/server/announce") == 0 && standalone.callback != nullptr)
  1727. standalone.callback(standalone.callbackPtr, CarlaBackend::CALLBACK_NSM_ANNOUNCE, 0, 0, 0, 0.0f, smName);
  1728. return 0;
  1729. #ifndef DEBUG
  1730. // unused
  1731. (void)path;
  1732. (void)types;
  1733. (void)argc;
  1734. #endif
  1735. }
  1736. int handleOpen(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg)
  1737. {
  1738. carla_debug("CarlaNSM::handleOpen(\"%s\", \"%s\", %p, %i, %p)", path, types, argv, argc, msg);
  1739. if (standalone.callback == nullptr)
  1740. return 1;
  1741. if (fServerThread == nullptr)
  1742. return 1;
  1743. if (fReplyAddr == nullptr)
  1744. return 1;
  1745. const char* const projectPath = &argv[0]->s;
  1746. const char* const clientId = &argv[2]->s;
  1747. char data[std::strlen(projectPath)+std::strlen(clientId)+2];
  1748. std::strcpy(data, projectPath);
  1749. std::strcat(data, ":");
  1750. std::strcat(data, clientId);
  1751. fIsOpened = false;
  1752. standalone.callback(nullptr, CarlaBackend::CALLBACK_NSM_OPEN, 0, 0, 0, 0.0f, data);
  1753. // wait max 10 secs to open
  1754. for (int i=0; i < 100 && ! fIsOpened; ++i)
  1755. carla_msleep(100);
  1756. #ifndef BUILD_ANSI_TEST
  1757. if (fIsOpened)
  1758. lo_send_from(fReplyAddr, lo_server_thread_get_server(fServerThread), LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/open", "OK");
  1759. #endif
  1760. return 0;
  1761. #ifndef DEBUG
  1762. // unused
  1763. (void)path;
  1764. (void)types;
  1765. (void)argc;
  1766. (void)msg;
  1767. #endif
  1768. }
  1769. int handleSave(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg)
  1770. {
  1771. carla_debug("CarlaNSM::handleSave(\"%s\", \"%s\", %p, %i, %p)", path, types, argv, argc, msg);
  1772. if (standalone.callback == nullptr)
  1773. return 1;
  1774. if (fServerThread == nullptr)
  1775. return 1;
  1776. if (fReplyAddr == nullptr)
  1777. return 1;
  1778. fIsSaved = false;
  1779. standalone.callback(nullptr, CarlaBackend::CALLBACK_NSM_SAVE, 0, 0, 0, 0.0f, nullptr);
  1780. // wait max 10 secs to save
  1781. for (int i=0; i < 100 && ! fIsSaved; ++i)
  1782. carla_msleep(100);
  1783. #ifndef BUILD_ANSI_TEST
  1784. if (fIsSaved)
  1785. lo_send_from(fReplyAddr, lo_server_thread_get_server(fServerThread), LO_TT_IMMEDIATE, "/reply", "ss", "/nsm/client/save", "OK");
  1786. #endif
  1787. return 0;
  1788. #ifndef DEBUG
  1789. // unused
  1790. (void)path;
  1791. (void)types;
  1792. (void)argv;
  1793. (void)argc;
  1794. (void)msg;
  1795. #endif
  1796. }
  1797. private:
  1798. lo_server_thread fServerThread;
  1799. lo_address fReplyAddr;
  1800. bool fIsReady; // used to startup, only once
  1801. bool fIsOpened;
  1802. bool fIsSaved;
  1803. #define handlePtr ((CarlaNSM*)data)
  1804. static int _reply_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* data)
  1805. {
  1806. return handlePtr->handleReply(path, types, argv, argc, msg);
  1807. }
  1808. static int _open_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* data)
  1809. {
  1810. return handlePtr->handleOpen(path, types, argv, argc, msg);
  1811. }
  1812. static int _save_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* data)
  1813. {
  1814. return handlePtr->handleSave(path, types, argv, argc, msg);
  1815. }
  1816. #undef handlePtr
  1817. static void error_handler(int num, const char* msg, const char* path)
  1818. {
  1819. carla_stderr2("CarlaNSM::error_handler(%i, \"%s\", \"%s\")", num, msg, path);
  1820. }
  1821. };
  1822. static CarlaNSM gCarlaNSM;
  1823. void carla_nsm_announce(const char* url, const char* appName, int pid)
  1824. {
  1825. gCarlaNSM.announce(url, appName, pid);
  1826. }
  1827. void carla_nsm_ready()
  1828. {
  1829. gCarlaNSM.ready();
  1830. }
  1831. void carla_nsm_reply_open()
  1832. {
  1833. gCarlaNSM.replyOpen();
  1834. }
  1835. void carla_nsm_reply_save()
  1836. {
  1837. gCarlaNSM.replySave();
  1838. }
  1839. // -------------------------------------------------------------------------------------------------------------------
  1840. #ifdef BUILD_BRIDGE
  1841. CarlaEngine* carla_get_standalone_engine()
  1842. {
  1843. return standalone.engine;
  1844. }
  1845. bool carla_engine_init_bridge(const char* audioBaseName, const char* controlBaseName, const char* clientName)
  1846. {
  1847. carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\")", audioBaseName, controlBaseName, clientName);
  1848. CARLA_ASSERT(standalone.engine == nullptr);
  1849. CARLA_ASSERT(audioBaseName != nullptr);
  1850. CARLA_ASSERT(controlBaseName != nullptr);
  1851. CARLA_ASSERT(clientName != nullptr);
  1852. standalone.engine = CarlaEngine::newBridge(audioBaseName, controlBaseName);
  1853. if (standalone.engine == nullptr)
  1854. {
  1855. standalone.lastError = "The seleted audio driver is not available!";
  1856. return false;
  1857. }
  1858. if (standalone.callback != nullptr)
  1859. standalone.engine->setCallback(standalone.callback, nullptr);
  1860. standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_MODE, CarlaBackend::PROCESS_MODE_BRIDGE, nullptr);
  1861. standalone.engine->setOption(CarlaBackend::OPTION_TRANSPORT_MODE, CarlaBackend::TRANSPORT_MODE_BRIDGE, nullptr);
  1862. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES, false, nullptr);
  1863. standalone.engine->setOption(CarlaBackend::OPTION_PREFER_UI_BRIDGES, false, nullptr);
  1864. // TODO - read from environment
  1865. #if 0
  1866. standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo ? 1 : 0, nullptr);
  1867. # ifdef WANT_DSSI
  1868. standalone.engine->setOption(CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS, standalone.options.useDssiVstChunks ? 1 : 0, nullptr);
  1869. # endif
  1870. standalone.engine->setOption(CarlaBackend::OPTION_MAX_PARAMETERS, static_cast<int>(standalone.options.maxParameters), nullptr);
  1871. #endif
  1872. if (standalone.engine->init(clientName))
  1873. {
  1874. standalone.lastError = "no error";
  1875. standalone.init();
  1876. return true;
  1877. }
  1878. else
  1879. {
  1880. standalone.lastError = standalone.engine->getLastError();
  1881. delete standalone.engine;
  1882. standalone.engine = nullptr;
  1883. return false;
  1884. }
  1885. }
  1886. #endif