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.

carla-vst.cpp 31KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2013-2017 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_PLUGIN_PATCHBAY
  18. # error CARLA_PLUGIN_PATCHBAY undefined
  19. #endif
  20. #ifndef CARLA_PLUGIN_SYNTH
  21. # error CARLA_PLUGIN_SYNTH undefined
  22. #endif
  23. #define CARLA_NATIVE_PLUGIN_VST
  24. #include "carla-base.cpp"
  25. #include "CarlaMathUtils.hpp"
  26. #include "AppConfig.h"
  27. #include "juce_core/juce_core.h"
  28. #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  29. # include "juce_gui_basics/juce_gui_basics.h"
  30. #else
  31. # include "juce_events/juce_events.h"
  32. #endif
  33. #ifdef VESTIGE_HEADER
  34. # include "vestige/aeffectx.h"
  35. #define effFlagsProgramChunks (1 << 5)
  36. #define effGetParamLabel 6
  37. #define effGetChunk 23
  38. #define effSetChunk 24
  39. #define effGetPlugCategory 35
  40. #define kPlugCategEffect 1
  41. #define kPlugCategSynth 2
  42. #define kVstVersion 2400
  43. struct ERect {
  44. int16_t top, left, bottom, right;
  45. };
  46. #else
  47. # include "vst2/aeffectx.h"
  48. #endif
  49. using juce::ScopedJuceInitialiser_GUI;
  50. using juce::SharedResourcePointer;
  51. static uint32_t d_lastBufferSize = 0;
  52. static double d_lastSampleRate = 0.0;
  53. static const int32_t kVstMidiEventSize = static_cast<int32_t>(sizeof(VstMidiEvent));
  54. // -----------------------------------------------------------------------
  55. class NativePlugin
  56. {
  57. public:
  58. static const uint32_t kMaxMidiEvents = 512;
  59. NativePlugin(const audioMasterCallback audioMaster, AEffect* const effect, const NativePluginDescriptor* desc)
  60. : fAudioMaster(audioMaster),
  61. fEffect(effect),
  62. fHandle(nullptr),
  63. fHost(),
  64. fDescriptor(desc),
  65. fBufferSize(d_lastBufferSize),
  66. fSampleRate(d_lastSampleRate),
  67. fIsActive(false),
  68. fMidiEventCount(0),
  69. fTimeInfo(),
  70. fVstRect(),
  71. fHostType(kHostTypeNull),
  72. fMidiOutEvents(),
  73. fStateChunk(nullptr),
  74. sJuceInitialiser()
  75. {
  76. fHost.handle = this;
  77. fHost.uiName = carla_strdup("CarlaVST");
  78. fHost.uiParentId = 0;
  79. // find resource dir
  80. using juce::File;
  81. using juce::String;
  82. File curExe = File::getSpecialLocation(File::currentExecutableFile).getLinkedTarget();
  83. File resDir = curExe.getSiblingFile("carla-resources");
  84. if (! resDir.exists())
  85. resDir = curExe.getSiblingFile("resources");
  86. if (! resDir.exists())
  87. resDir = File("/usr/share/carla/resources/");
  88. // find host type
  89. const String hostFilename(File::getSpecialLocation(File::hostApplicationPath).getFileName());
  90. if (hostFilename.startsWith("Bitwig"))
  91. fHostType = kHostTypeBitwig;
  92. fHost.resourceDir = carla_strdup(resDir.getFullPathName().toRawUTF8());
  93. fHost.get_buffer_size = host_get_buffer_size;
  94. fHost.get_sample_rate = host_get_sample_rate;
  95. fHost.is_offline = host_is_offline;
  96. fHost.get_time_info = host_get_time_info;
  97. fHost.write_midi_event = host_write_midi_event;
  98. fHost.ui_parameter_changed = host_ui_parameter_changed;
  99. fHost.ui_custom_data_changed = host_ui_custom_data_changed;
  100. fHost.ui_closed = host_ui_closed;
  101. fHost.ui_open_file = host_ui_open_file;
  102. fHost.ui_save_file = host_ui_save_file;
  103. fHost.dispatcher = host_dispatcher;
  104. fVstRect.top = 0;
  105. fVstRect.left = 0;
  106. fVstRect.bottom = 512;
  107. fVstRect.right = 740;
  108. init();
  109. }
  110. ~NativePlugin()
  111. {
  112. if (fIsActive)
  113. {
  114. // host has not de-activated the plugin yet, nasty!
  115. fIsActive = false;
  116. if (fDescriptor->deactivate != nullptr)
  117. fDescriptor->deactivate(fHandle);
  118. }
  119. if (fDescriptor->cleanup != nullptr && fHandle != nullptr)
  120. fDescriptor->cleanup(fHandle);
  121. fHandle = nullptr;
  122. if (fStateChunk != nullptr)
  123. {
  124. std::free(fStateChunk);
  125. fStateChunk = nullptr;
  126. }
  127. if (fHost.uiName != nullptr)
  128. {
  129. delete[] fHost.uiName;
  130. fHost.uiName = nullptr;
  131. }
  132. if (fHost.resourceDir != nullptr)
  133. {
  134. delete[] fHost.resourceDir;
  135. fHost.resourceDir = nullptr;
  136. }
  137. }
  138. bool init()
  139. {
  140. if (fDescriptor->instantiate == nullptr || fDescriptor->process == nullptr)
  141. {
  142. carla_stderr("Plugin is missing something...");
  143. return false;
  144. }
  145. fHandle = fDescriptor->instantiate(&fHost);
  146. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false);
  147. carla_zeroStructs(fMidiEvents, kMaxMidiEvents);
  148. carla_zeroStruct(fTimeInfo);
  149. return true;
  150. }
  151. // -------------------------------------------------------------------
  152. intptr_t vst_dispatcher(const int32_t opcode, const int32_t /*index*/, const intptr_t value, void* const ptr, const float opt)
  153. {
  154. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0);
  155. intptr_t ret = 0;
  156. switch (opcode)
  157. {
  158. case effSetSampleRate:
  159. if (carla_isEqual(fSampleRate, static_cast<double>(opt)))
  160. return 0;
  161. fSampleRate = opt;
  162. if (fDescriptor->dispatcher != nullptr)
  163. fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, opt);
  164. break;
  165. case effSetBlockSize:
  166. if (fBufferSize == static_cast<uint32_t>(value))
  167. return 0;
  168. fBufferSize = static_cast<uint32_t>(value);
  169. if (fDescriptor->dispatcher != nullptr)
  170. fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, value, nullptr, 0.0f);
  171. break;
  172. case effMainsChanged:
  173. if (value != 0)
  174. {
  175. fMidiEventCount = 0;
  176. carla_zeroStruct(fTimeInfo);
  177. // tell host we want MIDI events
  178. hostCallback(audioMasterWantMidi);
  179. // deactivate for possible changes
  180. if (fDescriptor->deactivate != nullptr && fIsActive)
  181. fDescriptor->deactivate(fHandle);
  182. // check if something changed
  183. const uint32_t bufferSize = static_cast<uint32_t>(hostCallback(audioMasterGetBlockSize));
  184. const double sampleRate = static_cast<double>(hostCallback(audioMasterGetSampleRate));
  185. if (bufferSize != 0 && fBufferSize != bufferSize)
  186. {
  187. fBufferSize = bufferSize;
  188. if (fDescriptor->dispatcher != nullptr)
  189. fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, (int32_t)value, nullptr, 0.0f);
  190. }
  191. if (carla_isNotZero(sampleRate) && carla_isNotEqual(fSampleRate, sampleRate))
  192. {
  193. fSampleRate = sampleRate;
  194. if (fDescriptor->dispatcher != nullptr)
  195. fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, (float)sampleRate);
  196. }
  197. if (fDescriptor->activate != nullptr)
  198. fDescriptor->activate(fHandle);
  199. fIsActive = true;
  200. }
  201. else
  202. {
  203. CARLA_SAFE_ASSERT_BREAK(fIsActive);
  204. if (fDescriptor->deactivate != nullptr)
  205. fDescriptor->deactivate(fHandle);
  206. fIsActive = false;
  207. }
  208. break;
  209. case effEditGetRect:
  210. *(ERect**)ptr = &fVstRect;
  211. ret = 1;
  212. break;
  213. case effEditOpen:
  214. if (fDescriptor->ui_show != nullptr)
  215. {
  216. char strBuf[0xff+1];
  217. strBuf[0xff] = '\0';
  218. std::snprintf(strBuf, 0xff, P_INTPTR, (intptr_t)ptr);
  219. // set CARLA_PLUGIN_EMBED_WINID for external process
  220. carla_setenv("CARLA_PLUGIN_EMBED_WINID", strBuf);
  221. // check if vst host is an old version of tracktion
  222. bool oldTracktionWorkaround = false;
  223. // tracktion doesn't export its version properly, use env var instead
  224. if (std::getenv("CARLA_TRACKTION_WORKAROUND") != nullptr)
  225. {
  226. carla_zeroChars(strBuf, 0xff+1);
  227. hostCallback(audioMasterGetProductString, 0, 0, strBuf, 0.0f);
  228. oldTracktionWorkaround = (std::strcmp(strBuf, "Tracktion") == 0);
  229. // if vst host is old tracktion, delay UI appearance for a bit (part 1)
  230. if (oldTracktionWorkaround)
  231. fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_NULL, (int32_t)0xDEADF00D, 0xC0C0B00B, nullptr, 0.0f);
  232. }
  233. // show UI now
  234. fDescriptor->ui_show(fHandle, true);
  235. // reset CARLA_PLUGIN_EMBED_WINID just in case
  236. carla_setenv("CARLA_PLUGIN_EMBED_WINID", "0");
  237. // if vst host is old tracktion, delay UI appearance for a bit (part 2)
  238. if (oldTracktionWorkaround)
  239. {
  240. carla_stdout("Old Tracktion detected, delaying UI appearance so it works properly...");
  241. for (int x=10; --x>=0;)
  242. {
  243. hostCallback(audioMasterIdle);
  244. carla_msleep(25);
  245. }
  246. }
  247. ret = 1;
  248. }
  249. break;
  250. case effEditClose:
  251. if (fDescriptor->ui_show != nullptr)
  252. {
  253. fDescriptor->ui_show(fHandle, false);
  254. ret = 1;
  255. }
  256. break;
  257. case effEditIdle:
  258. if (fDescriptor->ui_idle != nullptr)
  259. fDescriptor->ui_idle(fHandle);
  260. break;
  261. case effGetChunk:
  262. if (ptr == nullptr || fDescriptor->get_state == nullptr)
  263. return 0;
  264. if (fStateChunk != nullptr)
  265. std::free(fStateChunk);
  266. fStateChunk = fDescriptor->get_state(fHandle);
  267. if (fStateChunk == nullptr)
  268. return 0;
  269. ret = static_cast<intptr_t>(std::strlen(fStateChunk)+1);
  270. *(void**)ptr = fStateChunk;
  271. break;
  272. case effSetChunk:
  273. if (value <= 0 || fDescriptor->set_state == nullptr)
  274. return 0;
  275. if (value == 1)
  276. return 1;
  277. if (const char* const state = (const char*)ptr)
  278. {
  279. fDescriptor->set_state(fHandle, state);
  280. ret = 1;
  281. }
  282. break;
  283. case effProcessEvents:
  284. if (! fIsActive)
  285. {
  286. // host has not activated the plugin yet, nasty!
  287. vst_dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
  288. }
  289. if (const VstEvents* const events = (const VstEvents*)ptr)
  290. {
  291. if (events->numEvents == 0)
  292. break;
  293. for (int i=0, count=events->numEvents; i < count; ++i)
  294. {
  295. const VstMidiEvent* const vstMidiEvent((const VstMidiEvent*)events->events[i]);
  296. if (vstMidiEvent == nullptr)
  297. break;
  298. if (vstMidiEvent->type != kVstMidiType || vstMidiEvent->deltaFrames < 0)
  299. continue;
  300. if (fMidiEventCount >= kMaxMidiEvents)
  301. break;
  302. const uint32_t j(fMidiEventCount++);
  303. fMidiEvents[j].port = 0;
  304. fMidiEvents[j].time = static_cast<uint32_t>(vstMidiEvent->deltaFrames);
  305. fMidiEvents[j].size = 3;
  306. for (uint32_t k=0; k<3; ++k)
  307. fMidiEvents[j].data[k] = static_cast<uint8_t>(vstMidiEvent->midiData[k]);
  308. }
  309. }
  310. break;
  311. case effCanDo:
  312. if (const char* const canDo = (const char*)ptr)
  313. {
  314. if (std::strcmp(canDo, "receiveVstEvents") == 0)
  315. return 1;
  316. if (std::strcmp(canDo, "receiveVstMidiEvent") == 0)
  317. return 1;
  318. if (std::strcmp(canDo, "receiveVstTimeInfo") == 0)
  319. return 1;
  320. if (std::strcmp(canDo, "sendVstEvents") == 0)
  321. return 1;
  322. if (std::strcmp(canDo, "sendVstMidiEvent") == 0)
  323. return 1;
  324. }
  325. break;
  326. }
  327. return ret;
  328. }
  329. float vst_getParameter(const int32_t /*index*/)
  330. {
  331. return 0.0f;
  332. }
  333. void vst_setParameter(const int32_t /*index*/, const float /*value*/)
  334. {
  335. }
  336. void vst_processReplacing(const float** const inputs, float** const outputs, const int32_t sampleFrames)
  337. {
  338. if (sampleFrames <= 0)
  339. return;
  340. if (fHostType == kHostTypeBitwig && static_cast<int32_t>(fBufferSize) != sampleFrames)
  341. {
  342. // deactivate first if needed
  343. if (fIsActive && fDescriptor->deactivate != nullptr)
  344. fDescriptor->deactivate(fHandle);
  345. fBufferSize = static_cast<uint32_t>(sampleFrames);
  346. if (fDescriptor->dispatcher != nullptr)
  347. fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, sampleFrames, nullptr, 0.0f);
  348. // activate again
  349. if (fDescriptor->activate != nullptr)
  350. fDescriptor->activate(fHandle);
  351. fIsActive = true;
  352. }
  353. if (! fIsActive)
  354. {
  355. // host has not activated the plugin yet, nasty!
  356. vst_dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
  357. }
  358. static const int kWantVstTimeFlags(kVstTransportPlaying|kVstPpqPosValid|kVstTempoValid|kVstTimeSigValid);
  359. if (const VstTimeInfo* const vstTimeInfo = (const VstTimeInfo*)hostCallback(audioMasterGetTime, 0, kWantVstTimeFlags))
  360. {
  361. fTimeInfo.frame = static_cast<uint64_t>(vstTimeInfo->samplePos);
  362. fTimeInfo.playing = (vstTimeInfo->flags & kVstTransportPlaying);
  363. fTimeInfo.bbt.valid = ((vstTimeInfo->flags & kVstTempoValid) != 0 || (vstTimeInfo->flags & kVstTimeSigValid) != 0);
  364. // ticksPerBeat is not possible with VST
  365. fTimeInfo.bbt.ticksPerBeat = 960.0;
  366. if (vstTimeInfo->flags & kVstTempoValid)
  367. fTimeInfo.bbt.beatsPerMinute = vstTimeInfo->tempo;
  368. else
  369. fTimeInfo.bbt.beatsPerMinute = 120.0;
  370. if (vstTimeInfo->flags & (kVstPpqPosValid|kVstTimeSigValid))
  371. {
  372. const int ppqPerBar = vstTimeInfo->timeSigNumerator * 4 / vstTimeInfo->timeSigDenominator;
  373. const double barBeats = (std::fmod(vstTimeInfo->ppqPos, ppqPerBar) / ppqPerBar) * vstTimeInfo->timeSigDenominator;
  374. const double rest = std::fmod(barBeats, 1.0);
  375. fTimeInfo.bbt.bar = static_cast<int32_t>(vstTimeInfo->ppqPos)/ppqPerBar + 1;
  376. fTimeInfo.bbt.beat = static_cast<int32_t>(barBeats-rest+1.0);
  377. fTimeInfo.bbt.tick = static_cast<int32_t>(rest*fTimeInfo.bbt.ticksPerBeat+0.5);
  378. fTimeInfo.bbt.beatsPerBar = static_cast<float>(vstTimeInfo->timeSigNumerator);
  379. fTimeInfo.bbt.beatType = static_cast<float>(vstTimeInfo->timeSigDenominator);
  380. }
  381. else
  382. {
  383. fTimeInfo.bbt.bar = 1;
  384. fTimeInfo.bbt.beat = 1;
  385. fTimeInfo.bbt.tick = 0;
  386. fTimeInfo.bbt.beatsPerBar = 4.0f;
  387. fTimeInfo.bbt.beatType = 4.0f;
  388. }
  389. fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat*fTimeInfo.bbt.beatsPerBar*(fTimeInfo.bbt.bar-1);
  390. }
  391. fMidiOutEvents.numEvents = 0;
  392. if (fHandle != nullptr)
  393. // FIXME
  394. fDescriptor->process(fHandle, const_cast<float**>(inputs), outputs, static_cast<uint32_t>(sampleFrames), fMidiEvents, fMidiEventCount);
  395. fMidiEventCount = 0;
  396. if (fMidiOutEvents.numEvents > 0)
  397. hostCallback(audioMasterProcessEvents, 0, 0, &fMidiOutEvents, 0.0f);
  398. }
  399. protected:
  400. // -------------------------------------------------------------------
  401. bool handleWriteMidiEvent(const NativeMidiEvent* const event)
  402. {
  403. CARLA_SAFE_ASSERT_RETURN(fDescriptor->midiOuts > 0, false);
  404. CARLA_SAFE_ASSERT_RETURN(event != nullptr, false);
  405. CARLA_SAFE_ASSERT_RETURN(event->data[0] != 0, false);
  406. if (fMidiOutEvents.numEvents >= static_cast<int32_t>(kMaxMidiEvents))
  407. {
  408. // send current events
  409. hostCallback(audioMasterProcessEvents, 0, 0, &fMidiOutEvents, 0.0f);
  410. // clear
  411. fMidiOutEvents.numEvents = 0;
  412. }
  413. VstMidiEvent& vstMidiEvent(fMidiOutEvents.mdata[fMidiOutEvents.numEvents++]);
  414. vstMidiEvent.type = kVstMidiType;
  415. vstMidiEvent.byteSize = kVstMidiEventSize;
  416. uint8_t i=0;
  417. for (; i<event->size; ++i)
  418. vstMidiEvent.midiData[i] = static_cast<char>(event->data[i]);
  419. for (; i<4; ++i)
  420. vstMidiEvent.midiData[i] = 0;
  421. return true;
  422. }
  423. void handleUiParameterChanged(const uint32_t /*index*/, const float /*value*/) const
  424. {
  425. }
  426. void handleUiCustomDataChanged(const char* const /*key*/, const char* const /*value*/) const
  427. {
  428. }
  429. void handleUiClosed()
  430. {
  431. }
  432. const char* handleUiOpenFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const
  433. {
  434. // TODO
  435. return nullptr;
  436. }
  437. const char* handleUiSaveFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const
  438. {
  439. // TODO
  440. return nullptr;
  441. }
  442. intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
  443. {
  444. carla_debug("NativePlugin::handleDispatcher(%i, %i, " P_INTPTR ", %p, %f)", opcode, index, value, ptr, opt);
  445. switch (opcode)
  446. {
  447. case NATIVE_HOST_OPCODE_NULL:
  448. case NATIVE_HOST_OPCODE_UPDATE_PARAMETER:
  449. case NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM:
  450. case NATIVE_HOST_OPCODE_RELOAD_PARAMETERS:
  451. case NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS:
  452. case NATIVE_HOST_OPCODE_RELOAD_ALL:
  453. case NATIVE_HOST_OPCODE_UI_UNAVAILABLE:
  454. case NATIVE_HOST_OPCODE_INTERNAL_PLUGIN:
  455. break;
  456. case NATIVE_HOST_OPCODE_HOST_IDLE:
  457. hostCallback(audioMasterIdle);
  458. break;
  459. }
  460. // unused for now
  461. return 0;
  462. (void)index; (void)value; (void)ptr; (void)opt;
  463. }
  464. private:
  465. // VST stuff
  466. const audioMasterCallback fAudioMaster;
  467. AEffect* const fEffect;
  468. // Native data
  469. NativePluginHandle fHandle;
  470. NativeHostDescriptor fHost;
  471. const NativePluginDescriptor* const fDescriptor;
  472. // VST host data
  473. uint32_t fBufferSize;
  474. double fSampleRate;
  475. // Temporary data
  476. bool fIsActive;
  477. uint32_t fMidiEventCount;
  478. NativeMidiEvent fMidiEvents[kMaxMidiEvents];
  479. NativeTimeInfo fTimeInfo;
  480. ERect fVstRect;
  481. // Host data
  482. enum HostType {
  483. kHostTypeNull = 0,
  484. kHostTypeBitwig
  485. };
  486. HostType fHostType;
  487. // host callback
  488. intptr_t hostCallback(const int32_t opcode,
  489. const int32_t index = 0,
  490. const intptr_t value = 0,
  491. void* const ptr = nullptr,
  492. const float opt = 0.0f)
  493. {
  494. return fAudioMaster(fEffect, opcode, index, value, ptr, opt);
  495. }
  496. struct FixedVstEvents {
  497. int32_t numEvents;
  498. intptr_t reserved;
  499. VstEvent* data[kMaxMidiEvents];
  500. VstMidiEvent mdata[kMaxMidiEvents];
  501. FixedVstEvents()
  502. : numEvents(0),
  503. reserved(0)
  504. {
  505. for (uint32_t i=0; i<kMaxMidiEvents; ++i)
  506. data[i] = (VstEvent*)&mdata[i];
  507. carla_zeroStructs(mdata, kMaxMidiEvents);
  508. }
  509. CARLA_DECLARE_NON_COPY_STRUCT(FixedVstEvents);
  510. } fMidiOutEvents;
  511. char* fStateChunk;
  512. SharedResourcePointer<ScopedJuceInitialiser_GUI> sJuceInitialiser;
  513. // -------------------------------------------------------------------
  514. #define handlePtr ((NativePlugin*)handle)
  515. static uint32_t host_get_buffer_size(NativeHostHandle handle)
  516. {
  517. return handlePtr->fBufferSize;
  518. }
  519. static double host_get_sample_rate(NativeHostHandle handle)
  520. {
  521. return handlePtr->fSampleRate;
  522. }
  523. static bool host_is_offline(NativeHostHandle /*handle*/)
  524. {
  525. // TODO
  526. return false;
  527. }
  528. static const NativeTimeInfo* host_get_time_info(NativeHostHandle handle)
  529. {
  530. return &(handlePtr->fTimeInfo);
  531. }
  532. static bool host_write_midi_event(NativeHostHandle handle, const NativeMidiEvent* event)
  533. {
  534. return handlePtr->handleWriteMidiEvent(event);
  535. }
  536. static void host_ui_parameter_changed(NativeHostHandle handle, uint32_t index, float value)
  537. {
  538. handlePtr->handleUiParameterChanged(index, value);
  539. }
  540. static void host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value)
  541. {
  542. handlePtr->handleUiCustomDataChanged(key, value);
  543. }
  544. static void host_ui_closed(NativeHostHandle handle)
  545. {
  546. handlePtr->handleUiClosed();
  547. }
  548. static const char* host_ui_open_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
  549. {
  550. return handlePtr->handleUiOpenFile(isDir, title, filter);
  551. }
  552. static const char* host_ui_save_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
  553. {
  554. return handlePtr->handleUiSaveFile(isDir, title, filter);
  555. }
  556. static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  557. {
  558. return handlePtr->handleDispatcher(opcode, index, value, ptr, opt);
  559. }
  560. #undef handlePtr
  561. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePlugin)
  562. };
  563. // -----------------------------------------------------------------------
  564. struct VstObject {
  565. audioMasterCallback audioMaster;
  566. NativePlugin* plugin;
  567. };
  568. #ifdef VESTIGE_HEADER
  569. # define validObject effect != nullptr && effect->ptr3 != nullptr
  570. # define validPlugin effect != nullptr && effect->ptr3 != nullptr && ((VstObject*)effect->ptr3)->plugin != nullptr
  571. # define vstObjectPtr (VstObject*)effect->ptr3
  572. #else
  573. # define validObject effect != nullptr && effect->object != nullptr
  574. # define validPlugin effect != nullptr && effect->object != nullptr && ((VstObject*)effect->object)->plugin != nullptr
  575. # define vstObjectPtr (VstObject*)effect->object
  576. #endif
  577. #define pluginPtr (vstObjectPtr)->plugin
  578. static intptr_t vst_dispatcherCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt)
  579. {
  580. // handle base opcodes
  581. switch (opcode)
  582. {
  583. case effOpen:
  584. if (VstObject* const obj = vstObjectPtr)
  585. {
  586. // this must always be valid
  587. CARLA_SAFE_ASSERT_RETURN(obj->audioMaster != nullptr, 0);
  588. // some hosts call effOpen twice
  589. CARLA_SAFE_ASSERT_RETURN(obj->plugin == nullptr, 1);
  590. audioMasterCallback audioMaster = (audioMasterCallback)obj->audioMaster;
  591. d_lastBufferSize = static_cast<uint32_t>(audioMaster(effect, audioMasterGetBlockSize, 0, 0, nullptr, 0.0f));
  592. d_lastSampleRate = static_cast<double>(audioMaster(effect, audioMasterGetSampleRate, 0, 0, nullptr, 0.0f));
  593. // some hosts are not ready at this point or return 0 buffersize/samplerate
  594. if (d_lastBufferSize == 0)
  595. d_lastBufferSize = 2048;
  596. if (d_lastSampleRate <= 0.0)
  597. d_lastSampleRate = 44100.0;
  598. const NativePluginDescriptor* pluginDesc = nullptr;
  599. #if CARLA_PLUGIN_PATCHBAY
  600. # ifdef CARLA_PLUGIN_16CH
  601. const char* const pluginLabel = "carlapatchbay16";
  602. # else
  603. const char* const pluginLabel = "carlapatchbay";
  604. # endif
  605. #else
  606. const char* const pluginLabel = "carlarack";
  607. #endif
  608. PluginListManager& plm(PluginListManager::getInstance());
  609. for (LinkedList<const NativePluginDescriptor*>::Itenerator it = plm.descs.begin2(); it.valid(); it.next())
  610. {
  611. const NativePluginDescriptor* const& tmpDesc(it.getValue(nullptr));
  612. CARLA_SAFE_ASSERT_CONTINUE(tmpDesc != nullptr);
  613. if (std::strcmp(tmpDesc->label, pluginLabel) == 0)
  614. {
  615. pluginDesc = tmpDesc;
  616. break;
  617. }
  618. }
  619. CARLA_SAFE_ASSERT_RETURN(pluginDesc != nullptr, 0);
  620. obj->plugin = new NativePlugin(audioMaster, effect, pluginDesc);
  621. return 1;
  622. }
  623. return 0;
  624. case effClose:
  625. if (VstObject* const obj = vstObjectPtr)
  626. {
  627. NativePlugin* const plugin(obj->plugin);
  628. if (plugin != nullptr)
  629. {
  630. obj->plugin = nullptr;
  631. delete plugin;
  632. }
  633. #if 0
  634. /* This code invalidates the object created in VSTPluginMain
  635. * Probably not safe against all hosts */
  636. obj->audioMaster = nullptr;
  637. # ifdef VESTIGE_HEADER
  638. effect->ptr3 = nullptr;
  639. # else
  640. vstObjectPtr = nullptr;
  641. # endif
  642. delete obj;
  643. #endif
  644. return 1;
  645. }
  646. //delete effect;
  647. return 0;
  648. case effGetPlugCategory:
  649. #if CARLA_PLUGIN_SYNTH
  650. return kPlugCategSynth;
  651. #else
  652. return kPlugCategEffect;
  653. #endif
  654. case effGetEffectName:
  655. if (char* const cptr = (char*)ptr)
  656. {
  657. #if CARLA_PLUGIN_PATCHBAY
  658. # if CARLA_PLUGIN_SYNTH
  659. # ifdef CARLA_PLUGIN_16CH
  660. std::strncpy(cptr, "Carla-Patchbay16", 32);
  661. # else
  662. std::strncpy(cptr, "Carla-Patchbay", 32);
  663. # endif
  664. # else
  665. std::strncpy(cptr, "Carla-PatchbayFX", 32);
  666. # endif
  667. #else
  668. # if CARLA_PLUGIN_SYNTH
  669. std::strncpy(cptr, "Carla-Rack", 32);
  670. # else
  671. std::strncpy(cptr, "Carla-RackFX", 32);
  672. # endif
  673. #endif
  674. return 1;
  675. }
  676. return 0;
  677. case effGetVendorString:
  678. if (char* const cptr = (char*)ptr)
  679. {
  680. std::strncpy(cptr, "falkTX", 32);
  681. return 1;
  682. }
  683. return 0;
  684. case effGetProductString:
  685. if (char* const cptr = (char*)ptr)
  686. {
  687. #if CARLA_PLUGIN_PATCHBAY
  688. # if CARLA_PLUGIN_SYNTH
  689. # ifdef CARLA_PLUGIN_16CH
  690. std::strncpy(cptr, "CarlaPatchbay16", 32);
  691. # else
  692. std::strncpy(cptr, "CarlaPatchbay", 32);
  693. # endif
  694. # else
  695. std::strncpy(cptr, "CarlaPatchbayFX", 32);
  696. # endif
  697. #else
  698. # if CARLA_PLUGIN_SYNTH
  699. std::strncpy(cptr, "CarlaRack", 32);
  700. # else
  701. std::strncpy(cptr, "CarlaRackFX", 32);
  702. # endif
  703. #endif
  704. return 1;
  705. }
  706. return 0;
  707. case effGetVendorVersion:
  708. return CARLA_VERSION_HEX;
  709. case effGetVstVersion:
  710. return kVstVersion;
  711. };
  712. // handle advanced opcodes
  713. if (validPlugin)
  714. return pluginPtr->vst_dispatcher(opcode, index, value, ptr, opt);
  715. return 0;
  716. }
  717. static float vst_getParameterCallback(AEffect* effect, int32_t index)
  718. {
  719. if (validPlugin)
  720. return pluginPtr->vst_getParameter(index);
  721. return 0.0f;
  722. }
  723. static void vst_setParameterCallback(AEffect* effect, int32_t index, float value)
  724. {
  725. if (validPlugin)
  726. pluginPtr->vst_setParameter(index, value);
  727. }
  728. static void vst_processCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames)
  729. {
  730. if (validPlugin)
  731. pluginPtr->vst_processReplacing(const_cast<const float**>(inputs), outputs, sampleFrames);
  732. }
  733. static void vst_processReplacingCallback(AEffect* effect, float** inputs, float** outputs, int32_t sampleFrames)
  734. {
  735. if (validPlugin)
  736. pluginPtr->vst_processReplacing(const_cast<const float**>(inputs), outputs, sampleFrames);
  737. }
  738. #undef pluginPtr
  739. #undef validObject
  740. #undef validPlugin
  741. #undef vstObjectPtr
  742. // -----------------------------------------------------------------------
  743. CARLA_EXPORT
  744. #if defined(CARLA_OS_WIN) || defined(CARLA_OS_MAC)
  745. const AEffect* VSTPluginMain(audioMasterCallback audioMaster);
  746. #else
  747. const AEffect* VSTPluginMain(audioMasterCallback audioMaster) asm ("main");
  748. #endif
  749. CARLA_EXPORT
  750. const AEffect* VSTPluginMain(audioMasterCallback audioMaster)
  751. {
  752. // old version
  753. if (audioMaster(nullptr, audioMasterVersion, 0, 0, nullptr, 0.0f) == 0)
  754. return nullptr;
  755. AEffect* const effect(new AEffect);
  756. std::memset(effect, 0, sizeof(AEffect));
  757. // vst fields
  758. effect->magic = kEffectMagic;
  759. #ifdef VESTIGE_HEADER
  760. int32_t* const version = (int32_t*)&effect->unknown1;
  761. *version = CARLA_VERSION_HEX;
  762. #else
  763. effect->version = CARLA_VERSION_HEX;
  764. #endif
  765. static const int32_t uniqueId = CCONST('C', 'r', 'l', 'a');
  766. #if CARLA_PLUGIN_SYNTH
  767. # if CARLA_PLUGIN_PATCHBAY
  768. # ifdef CARLA_PLUGIN_16CH
  769. effect->uniqueID = uniqueId+5;
  770. # else
  771. effect->uniqueID = uniqueId+4;
  772. # endif
  773. # else
  774. effect->uniqueID = uniqueId+3;
  775. # endif
  776. #else
  777. # if CARLA_PLUGIN_PATCHBAY
  778. effect->uniqueID = uniqueId+2;
  779. # else
  780. effect->uniqueID = uniqueId+1;
  781. # endif
  782. #endif
  783. // plugin fields
  784. effect->numParams = 0;
  785. effect->numPrograms = 0;
  786. #ifdef CARLA_PLUGIN_16CH
  787. effect->numInputs = 16;
  788. effect->numOutputs = 16;
  789. #else
  790. effect->numInputs = 2;
  791. effect->numOutputs = 2;
  792. #endif
  793. // plugin flags
  794. effect->flags |= effFlagsCanReplacing;
  795. effect->flags |= effFlagsHasEditor;
  796. effect->flags |= effFlagsProgramChunks;
  797. #if CARLA_PLUGIN_SYNTH
  798. effect->flags |= effFlagsIsSynth;
  799. #endif
  800. // static calls
  801. effect->dispatcher = vst_dispatcherCallback;
  802. effect->process = vst_processCallback;
  803. effect->getParameter = vst_getParameterCallback;
  804. effect->setParameter = vst_setParameterCallback;
  805. effect->processReplacing = vst_processReplacingCallback;
  806. // pointers
  807. VstObject* const obj(new VstObject());
  808. obj->audioMaster = audioMaster;
  809. obj->plugin = nullptr;
  810. #ifdef VESTIGE_HEADER
  811. effect->ptr3 = obj;
  812. #else
  813. effect->object = obj;
  814. #endif
  815. return effect;
  816. }
  817. // -----------------------------------------------------------------------