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.

704 lines
18KB

  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the GPL.txt file
  16. */
  17. // for UINT32_MAX
  18. #define __STDC_LIMIT_MACROS
  19. #include <cstdint>
  20. #include "CarlaNative.hpp"
  21. #include "CarlaMIDI.h"
  22. #include "CarlaString.hpp"
  23. #include "RtList.hpp"
  24. #include <QtCore/QThread>
  25. #include "zynaddsubfx/Misc/Master.h"
  26. #include "zynaddsubfx/Misc/Part.h"
  27. #include "zynaddsubfx/Misc/Util.h"
  28. #ifdef WANT_ZYNADDSUBFX_UI
  29. // FIXME
  30. # ifdef override
  31. # define override_hack
  32. # undef override
  33. # endif
  34. # include "zynaddsubfx/UI/common.H"
  35. # include "zynaddsubfx/UI/MasterUI.h"
  36. # include <FL/Fl_Shared_Image.H>
  37. # include <FL/Fl_Tiled_Image.H>
  38. # include <FL/Fl_Dial.H>
  39. # include <FL/Fl_Theme.H>
  40. # ifdef override_hack
  41. # define override
  42. # undef override_hack
  43. # endif
  44. #endif
  45. #include <ctime>
  46. #include <set>
  47. #include <string>
  48. // Dummy variables and functions for linking purposes
  49. const char* instance_name = nullptr;
  50. class WavFile;
  51. namespace Nio {
  52. bool start(void){return 1;}
  53. void stop(void){}
  54. bool setSource(std::string){return true;}
  55. bool setSink(std::string){return true;}
  56. std::set<std::string> getSources(void){return std::set<std::string>();}
  57. std::set<std::string> getSinks(void){return std::set<std::string>();}
  58. std::string getSource(void){return "";}
  59. std::string getSink(void){return "";}
  60. void waveNew(WavFile*){}
  61. void waveStart(void){}
  62. void waveStop(void){}
  63. void waveEnd(void){}
  64. }
  65. SYNTH_T* synth = nullptr;
  66. #ifdef WANT_ZYNADDSUBFX_UI
  67. #define PIXMAP_PATH "./resources/zynaddsubfx/"
  68. static Fl_Tiled_Image* gModuleBackdrop = nullptr;
  69. void set_module_parameters(Fl_Widget* o)
  70. {
  71. CARLA_ASSERT(gModuleBackdrop != nullptr);
  72. o->box(FL_DOWN_FRAME);
  73. o->align(o->align() | FL_ALIGN_IMAGE_BACKDROP);
  74. o->color(FL_BLACK);
  75. o->labeltype(FL_SHADOW_LABEL);
  76. if (gModuleBackdrop != nullptr)
  77. o->image(gModuleBackdrop);
  78. }
  79. #endif
  80. class ZynAddSubFxPlugin : public PluginDescriptorClass
  81. {
  82. public:
  83. enum Parameters {
  84. PARAMETER_COUNT = 0
  85. };
  86. ZynAddSubFxPlugin(const HostDescriptor* const host)
  87. : PluginDescriptorClass(host),
  88. kMaster(new Master()),
  89. kSampleRate(getSampleRate()),
  90. fThread(kMaster, host)
  91. {
  92. fThread.start();
  93. maybeInitPrograms(kMaster);
  94. //fThread.waitForStarted();
  95. }
  96. ~ZynAddSubFxPlugin() override
  97. {
  98. //ensure that everything has stopped
  99. pthread_mutex_lock(&kMaster->mutex);
  100. pthread_mutex_unlock(&kMaster->mutex);
  101. fThread.stop();
  102. fThread.wait();
  103. delete kMaster;
  104. }
  105. protected:
  106. // -------------------------------------------------------------------
  107. // Plugin parameter calls
  108. uint32_t getParameterCount() override
  109. {
  110. return PARAMETER_COUNT;
  111. }
  112. const Parameter* getParameterInfo(const uint32_t index) override
  113. {
  114. CARLA_ASSERT(index < getParameterCount());
  115. //if (index >= PARAMETER_COUNT)
  116. return nullptr;
  117. static Parameter param;
  118. param.ranges.step = PARAMETER_RANGES_DEFAULT_STEP;
  119. param.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL;
  120. param.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE;
  121. param.scalePointCount = 0;
  122. param.scalePoints = nullptr;
  123. switch (index)
  124. {
  125. #if 0
  126. case PARAMETER_MASTER:
  127. param.hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  128. param.name = "Master Volume";
  129. param.unit = nullptr;
  130. param.ranges.min = 0.0f;
  131. param.ranges.max = 100.0f;
  132. param.ranges.def = 100.0f;
  133. break;
  134. #endif
  135. }
  136. return &param;
  137. }
  138. float getParameterValue(const uint32_t index) override
  139. {
  140. CARLA_ASSERT(index < getParameterCount());
  141. switch (index)
  142. {
  143. #if 0
  144. case PARAMETER_MASTER:
  145. return kMaster->Pvolume;
  146. #endif
  147. default:
  148. return 0.0f;
  149. }
  150. }
  151. // -------------------------------------------------------------------
  152. // Plugin midi-program calls
  153. uint32_t getMidiProgramCount() override
  154. {
  155. return sPrograms.count();
  156. }
  157. const MidiProgram* getMidiProgramInfo(const uint32_t index) override
  158. {
  159. CARLA_ASSERT(index < getMidiProgramCount());
  160. if (index >= sPrograms.count())
  161. return nullptr;
  162. const ProgramInfo* const pInfo(sPrograms.getAt(index));
  163. static MidiProgram midiProgram;
  164. midiProgram.bank = pInfo->bank;
  165. midiProgram.program = pInfo->prog;
  166. midiProgram.name = pInfo->name;
  167. return &midiProgram;
  168. }
  169. // -------------------------------------------------------------------
  170. // Plugin state calls
  171. void setParameterValue(const uint32_t index, const float value) override
  172. {
  173. CARLA_ASSERT(index < getParameterCount());
  174. switch (index)
  175. {
  176. }
  177. return;
  178. // unused, TODO
  179. (void)value;
  180. }
  181. void setMidiProgram(const uint32_t bank, const uint32_t program) override
  182. {
  183. if (bank >= kMaster->bank.banks.size())
  184. return;
  185. if (program >= BANK_SIZE)
  186. return;
  187. bool isOffline = false;
  188. if (isOffline)
  189. loadProgram(kMaster, bank, program);
  190. else
  191. fThread.loadLater(bank, program);
  192. }
  193. void setCustomData(const char* const key, const char* const value)
  194. {
  195. CARLA_ASSERT(key != nullptr);
  196. CARLA_ASSERT(value != nullptr);
  197. if (std::strcmp(key, "CarlaAlternateFile1") == 0) // xmz
  198. kMaster->loadXML(value);
  199. if (std::strcmp(key, "CarlaAlternateFile2") == 0) // xiz
  200. kMaster->part[0]->loadXMLinstrument(value);
  201. }
  202. // -------------------------------------------------------------------
  203. // Plugin process calls
  204. void activate() override
  205. {
  206. // broken
  207. //for (int i=0; i < NUM_MIDI_PARTS; i++)
  208. // kMaster->setController(0, MIDI_CONTROL_ALL_SOUND_OFF, 0);
  209. }
  210. void process(float**, float** const outBuffer, const uint32_t frames, const uint32_t midiEventCount, const MidiEvent* const midiEvents) override
  211. {
  212. if (pthread_mutex_trylock(&kMaster->mutex) != 0)
  213. {
  214. carla_zeroFloat(outBuffer[0], frames);
  215. carla_zeroFloat(outBuffer[1], frames);
  216. return;
  217. }
  218. for (uint32_t i=0; i < midiEventCount; i++)
  219. {
  220. const MidiEvent* const midiEvent = &midiEvents[i];
  221. const uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent->data);
  222. const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent->data);
  223. if (MIDI_IS_STATUS_NOTE_OFF(status))
  224. {
  225. const uint8_t note = midiEvent->data[1];
  226. kMaster->noteOff(channel, note);
  227. }
  228. else if (MIDI_IS_STATUS_NOTE_ON(status))
  229. {
  230. const uint8_t note = midiEvent->data[1];
  231. const uint8_t velo = midiEvent->data[2];
  232. kMaster->noteOn(channel, note, velo);
  233. }
  234. else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
  235. {
  236. const uint8_t note = midiEvent->data[1];
  237. const uint8_t pressure = midiEvent->data[2];
  238. kMaster->polyphonicAftertouch(channel, note, pressure);
  239. }
  240. }
  241. kMaster->GetAudioOutSamples(frames, kSampleRate, outBuffer[0], outBuffer[1]);
  242. pthread_mutex_unlock(&kMaster->mutex);
  243. }
  244. #ifdef WANT_ZYNADDSUBFX_UI
  245. // -------------------------------------------------------------------
  246. // Plugin UI calls
  247. void uiShow(const bool show) override
  248. {
  249. if (show)
  250. fThread.uiShow();
  251. else
  252. fThread.uiHide();
  253. }
  254. #endif
  255. // -------------------------------------------------------------------
  256. // Plugin state calls
  257. char* getState() override
  258. {
  259. config.save();
  260. char* data = nullptr;
  261. kMaster->getalldata(&data);
  262. return data;
  263. }
  264. void setState(const char* const data) override
  265. {
  266. fThread.stopLoadLater();
  267. kMaster->putalldata((char*)data, 0);
  268. kMaster->applyparameters(true);
  269. }
  270. // -------------------------------------------------------------------
  271. private:
  272. struct ProgramInfo {
  273. uint32_t bank;
  274. uint32_t prog;
  275. const char* name;
  276. ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_)
  277. : bank(bank_),
  278. prog(prog_),
  279. name(carla_strdup(name_)) {}
  280. ~ProgramInfo()
  281. {
  282. if (name != nullptr)
  283. {
  284. delete[] name;
  285. name = nullptr;
  286. }
  287. }
  288. ProgramInfo() = delete;
  289. ProgramInfo(ProgramInfo&) = delete;
  290. ProgramInfo(const ProgramInfo&) = delete;
  291. };
  292. class ZynThread : public QThread
  293. {
  294. public:
  295. ZynThread(Master* const master, const HostDescriptor* const host)
  296. : kMaster(master),
  297. kHost(host),
  298. #ifdef WANT_ZYNADDSUBFX_UI
  299. fUi(nullptr),
  300. fUiClosed(0),
  301. fNextUiAction(-1),
  302. #endif
  303. fQuit(false),
  304. fChangeProgram(false),
  305. fNextBank(0),
  306. fNextProgram(0)
  307. {
  308. }
  309. ~ZynThread()
  310. {
  311. // must be closed by now
  312. #ifdef WANT_ZYNADDSUBFX_UI
  313. CARLA_ASSERT(fUi == nullptr);
  314. #endif
  315. CARLA_ASSERT(fQuit);
  316. }
  317. void loadLater(const uint32_t bank, const uint32_t program)
  318. {
  319. fNextBank = bank;
  320. fNextProgram = program;
  321. fChangeProgram = true;
  322. }
  323. void stopLoadLater()
  324. {
  325. fChangeProgram = false;
  326. fNextBank = 0;
  327. fNextProgram = 0;
  328. }
  329. void stop()
  330. {
  331. fQuit = true;
  332. quit();
  333. }
  334. #ifdef WANT_ZYNADDSUBFX_UI
  335. void uiShow()
  336. {
  337. fNextUiAction = 1;
  338. }
  339. void uiHide()
  340. {
  341. fNextUiAction = 0;
  342. }
  343. #endif
  344. protected:
  345. void run()
  346. {
  347. while (! fQuit)
  348. {
  349. #ifdef WANT_ZYNADDSUBFX_UI
  350. Fl::lock();
  351. if (fNextUiAction == 1)
  352. {
  353. static bool initialized = false;
  354. if (! initialized)
  355. {
  356. initialized = true;
  357. fl_register_images();
  358. Fl_Dial::default_style(Fl_Dial::PIXMAP_DIAL);
  359. if (Fl_Shared_Image* const img = Fl_Shared_Image::get(PIXMAP_PATH "knob.png"))
  360. Fl_Dial::default_image(img);
  361. if (Fl_Shared_Image* const img = Fl_Shared_Image::get(PIXMAP_PATH "window_backdrop.png"))
  362. Fl::scheme_bg(new Fl_Tiled_Image(img));
  363. if(Fl_Shared_Image* const img = Fl_Shared_Image::get(PIXMAP_PATH "module_backdrop.png"))
  364. gModuleBackdrop = new Fl_Tiled_Image(img);
  365. Fl::background(50, 50, 50);
  366. Fl::background2(70, 70, 70);
  367. Fl::foreground(255, 255, 255);
  368. Fl_Theme::set("Cairo");
  369. }
  370. CARLA_ASSERT(fUi == nullptr);
  371. if (fUi == nullptr)
  372. {
  373. fUiClosed = 0;
  374. fUi = new MasterUI(kMaster, &fUiClosed);
  375. //fUi->npartcounter->callback(_npartcounterCallback, this);
  376. fUi->showUI();
  377. }
  378. }
  379. else if (fNextUiAction == 0)
  380. {
  381. CARLA_ASSERT(fUi != nullptr);
  382. if (fUi != nullptr)
  383. {
  384. delete fUi;
  385. fUi = nullptr;
  386. }
  387. }
  388. fNextUiAction = -1;
  389. if (fUiClosed != 0)
  390. {
  391. fUiClosed = 0;
  392. fNextUiAction = 0;
  393. kHost->ui_closed(kHost->handle);
  394. }
  395. Fl::check();
  396. Fl::unlock();
  397. #endif
  398. if (fChangeProgram)
  399. {
  400. fChangeProgram = false;
  401. loadProgram(kMaster, fNextBank, fNextProgram);
  402. fNextBank = 0;
  403. fNextProgram = 0;
  404. }
  405. carla_msleep(15);
  406. }
  407. #ifdef WANT_ZYNADDSUBFX_UI
  408. if (fQuit && fUi != nullptr)
  409. {
  410. Fl::lock();
  411. delete fUi;
  412. fUi = nullptr;
  413. Fl::check();
  414. Fl::unlock();
  415. }
  416. #endif
  417. }
  418. #ifdef WANT_ZYNADDSUBFX_UI
  419. void handlePartCounterCallback(Fl_Widget* widget)
  420. {
  421. carla_stdout("handlePartCounterCallback(%p)", widget);
  422. }
  423. static void _npartcounterCallback(Fl_Widget* widget, void* ptr)
  424. {
  425. ((ZynThread*)ptr)->handlePartCounterCallback(widget);
  426. }
  427. #endif
  428. private:
  429. Master* const kMaster;
  430. const HostDescriptor* const kHost;
  431. #ifdef WANT_ZYNADDSUBFX_UI
  432. MasterUI* fUi;
  433. int fUiClosed;
  434. int fNextUiAction;
  435. #endif
  436. bool fQuit;
  437. bool fChangeProgram;
  438. uint32_t fNextBank;
  439. uint32_t fNextProgram;
  440. };
  441. Master* const kMaster;
  442. const unsigned kSampleRate;
  443. ZynThread fThread;
  444. static int sInstanceCount;
  445. static NonRtList<ProgramInfo*> sPrograms;
  446. public:
  447. static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host)
  448. {
  449. if (sInstanceCount++ == 0)
  450. {
  451. CARLA_ASSERT(synth == nullptr);
  452. CARLA_ASSERT(denormalkillbuf == nullptr);
  453. synth = new SYNTH_T();
  454. synth->buffersize = host->get_buffer_size(host->handle);
  455. synth->samplerate = host->get_sample_rate(host->handle);
  456. synth->alias();
  457. config.init();
  458. config.cfg.SoundBufferSize = synth->buffersize;
  459. config.cfg.SampleRate = synth->samplerate;
  460. config.cfg.GzipCompression = 0;
  461. sprng(std::time(nullptr));
  462. denormalkillbuf = new float[synth->buffersize];
  463. for (int i=0; i < synth->buffersize; i++)
  464. denormalkillbuf[i] = (RND - 0.5f) * 1e-16;
  465. Master::getInstance();
  466. }
  467. return new ZynAddSubFxPlugin(host);
  468. }
  469. static void _cleanup(PluginHandle handle)
  470. {
  471. delete (ZynAddSubFxPlugin*)handle;
  472. if (--sInstanceCount == 0)
  473. {
  474. CARLA_ASSERT(synth != nullptr);
  475. CARLA_ASSERT(denormalkillbuf != nullptr);
  476. Master::deleteInstance();
  477. delete[] denormalkillbuf;
  478. denormalkillbuf = nullptr;
  479. delete synth;
  480. synth = nullptr;
  481. }
  482. }
  483. static void maybeInitPrograms(Master* const master)
  484. {
  485. static bool doSearch = true;
  486. if (! doSearch)
  487. return;
  488. doSearch = false;
  489. pthread_mutex_lock(&master->mutex);
  490. // refresh banks
  491. master->bank.rescanforbanks();
  492. for (uint32_t i=0, size = master->bank.banks.size(); i < size; i++)
  493. {
  494. if (master->bank.banks[i].dir.empty())
  495. continue;
  496. master->bank.loadbank(master->bank.banks[i].dir);
  497. for (unsigned int instrument = 0; instrument < BANK_SIZE; instrument++)
  498. {
  499. const std::string insName(master->bank.getname(instrument));
  500. if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
  501. continue;
  502. sPrograms.append(new ProgramInfo(i, instrument, insName.c_str()));
  503. }
  504. }
  505. pthread_mutex_unlock(&master->mutex);
  506. }
  507. static void loadProgram(Master* const master, const uint32_t bank, const uint32_t program)
  508. {
  509. const std::string& bankdir(master->bank.banks[bank].dir);
  510. if (! bankdir.empty())
  511. {
  512. pthread_mutex_lock(&master->mutex);
  513. master->bank.loadbank(bankdir);
  514. for (int i=0; i < NUM_MIDI_PARTS; i++)
  515. master->bank.loadfromslot(program, master->part[i]);
  516. master->applyparameters(false);
  517. pthread_mutex_unlock(&master->mutex);
  518. }
  519. }
  520. static void clearPrograms()
  521. {
  522. for (auto it = sPrograms.begin(); it.valid(); it.next())
  523. {
  524. ProgramInfo* const programInfo(*it);
  525. delete programInfo;
  526. }
  527. sPrograms.clear();
  528. }
  529. private:
  530. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin)
  531. };
  532. int ZynAddSubFxPlugin::sInstanceCount = 0;
  533. NonRtList<ZynAddSubFxPlugin::ProgramInfo*> ZynAddSubFxPlugin::sPrograms;
  534. struct ProgramsDestructor {
  535. ProgramsDestructor() {}
  536. ~ProgramsDestructor()
  537. {
  538. ZynAddSubFxPlugin::clearPrograms();
  539. }
  540. } programsDestructor;
  541. // -----------------------------------------------------------------------
  542. static const PluginDescriptor zynAddSubFxDesc = {
  543. /* category */ PLUGIN_CATEGORY_SYNTH,
  544. #ifdef WANT_ZYNADDSUBFX_UI
  545. /* hints */ static_cast<PluginHints>(PLUGIN_IS_SYNTH|PLUGIN_HAS_GUI/*|PLUGIN_USES_SINGLE_THREAD*/|PLUGIN_USES_STATE),
  546. #else
  547. /* hints */ static_cast<PluginHints>(PLUGIN_IS_SYNTH|PLUGIN_USES_STATE),
  548. #endif
  549. /* audioIns */ 2,
  550. /* audioOuts */ 2,
  551. /* midiIns */ 1,
  552. /* midiOuts */ 0,
  553. /* paramIns */ ZynAddSubFxPlugin::PARAMETER_COUNT,
  554. /* paramOuts */ 0,
  555. /* name */ "ZynAddSubFX",
  556. /* label */ "zynaddsubfx",
  557. /* maker */ "falkTX",
  558. /* copyright */ "GNU GPL v2+",
  559. PluginDescriptorFILL(ZynAddSubFxPlugin)
  560. };
  561. // -----------------------------------------------------------------------
  562. void carla_register_native_plugin_zynaddsubfx()
  563. {
  564. carla_register_native_plugin(&zynAddSubFxDesc);
  565. }
  566. // -----------------------------------------------------------------------