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.

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