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.

697 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 "/usr/share/zynaddsubfx/pixmaps"
  67. #define SOURCE_DIR "/usr/share/zynaddsubfx/examples"
  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->image(gModuleBackdrop);
  76. o->labeltype(FL_SHADOW_LABEL);
  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 *img = Fl_Shared_Image::get(PIXMAP_PATH "/knob.png"))
  350. Fl_Dial::default_image(img);
  351. else
  352. Fl_Dial::default_image(Fl_Shared_Image::get(SOURCE_DIR "/../pixmaps/knob.png"));
  353. if(Fl_Shared_Image *img = Fl_Shared_Image::get(PIXMAP_PATH "/window_backdrop.png"))
  354. Fl::scheme_bg(new Fl_Tiled_Image(img));
  355. else
  356. Fl::scheme_bg(new Fl_Tiled_Image(Fl_Shared_Image::get(SOURCE_DIR "/../pixmaps/window_backdrop.png")));
  357. if(Fl_Shared_Image *img = Fl_Shared_Image::get(PIXMAP_PATH "/module_backdrop.png"))
  358. gModuleBackdrop = new Fl_Tiled_Image(img);
  359. else
  360. gModuleBackdrop = new Fl_Tiled_Image(Fl_Shared_Image::get(SOURCE_DIR "/../pixmaps/module_backdrop.png"));
  361. Fl::background(50, 50, 50);
  362. Fl::background2(70, 70, 70);
  363. Fl::foreground(255, 255, 255);
  364. Fl_Theme::set("Cairo");
  365. }
  366. CARLA_ASSERT(fUi == nullptr);
  367. if (fUi == nullptr)
  368. {
  369. fUiClosed = 0;
  370. fUi = new MasterUI(kMaster, &fUiClosed);
  371. //fUi->npartcounter->callback(_npartcounterCallback, this);
  372. fUi->showUI();
  373. }
  374. }
  375. else if (fNextUiAction == 0)
  376. {
  377. CARLA_ASSERT(fUi != nullptr);
  378. if (fUi != nullptr)
  379. {
  380. delete fUi;
  381. fUi = nullptr;
  382. }
  383. }
  384. fNextUiAction = -1;
  385. if (fUiClosed != 0)
  386. {
  387. fUiClosed = 0;
  388. fNextUiAction = 0;
  389. kHost->ui_closed(kHost->handle);
  390. }
  391. Fl::check();
  392. Fl::unlock();
  393. #endif
  394. if (fChangeProgram)
  395. {
  396. fChangeProgram = false;
  397. loadProgram(kMaster, fNextBank, fNextProgram);
  398. fNextBank = 0;
  399. fNextProgram = 0;
  400. }
  401. carla_msleep(15);
  402. }
  403. #ifdef WANT_ZYNADDSUBFX_UI
  404. if (fQuit && fUi != nullptr)
  405. {
  406. Fl::lock();
  407. delete fUi;
  408. fUi = nullptr;
  409. Fl::check();
  410. Fl::unlock();
  411. }
  412. #endif
  413. }
  414. #ifdef WANT_ZYNADDSUBFX_UI
  415. void handlePartCounterCallback(Fl_Widget* widget)
  416. {
  417. carla_stdout("handlePartCounterCallback(%p)", widget);
  418. }
  419. static void _npartcounterCallback(Fl_Widget* widget, void* ptr)
  420. {
  421. ((ZynThread*)ptr)->handlePartCounterCallback(widget);
  422. }
  423. #endif
  424. private:
  425. Master* const kMaster;
  426. const HostDescriptor* const kHost;
  427. #ifdef WANT_ZYNADDSUBFX_UI
  428. MasterUI* fUi;
  429. int fUiClosed;
  430. int fNextUiAction;
  431. #endif
  432. bool fQuit;
  433. bool fChangeProgram;
  434. uint32_t fNextBank;
  435. uint32_t fNextProgram;
  436. };
  437. Master* const kMaster;
  438. const unsigned kSampleRate;
  439. ZynThread fThread;
  440. static int sInstanceCount;
  441. static NonRtList<ProgramInfo*> sPrograms;
  442. public:
  443. static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host)
  444. {
  445. if (sInstanceCount++ == 0)
  446. {
  447. CARLA_ASSERT(synth == nullptr);
  448. CARLA_ASSERT(denormalkillbuf == nullptr);
  449. synth = new SYNTH_T();
  450. synth->buffersize = host->get_buffer_size(host->handle);
  451. synth->samplerate = host->get_sample_rate(host->handle);
  452. synth->alias();
  453. config.init();
  454. config.cfg.SoundBufferSize = synth->buffersize;
  455. config.cfg.SampleRate = synth->samplerate;
  456. config.cfg.GzipCompression = 0;
  457. sprng(std::time(nullptr));
  458. denormalkillbuf = new float[synth->buffersize];
  459. for (int i=0; i < synth->buffersize; i++)
  460. denormalkillbuf[i] = (RND - 0.5f) * 1e-16;
  461. Master::getInstance();
  462. }
  463. return new ZynAddSubFxPlugin(host);
  464. }
  465. static void _cleanup(PluginHandle handle)
  466. {
  467. delete (ZynAddSubFxPlugin*)handle;
  468. if (--sInstanceCount == 0)
  469. {
  470. CARLA_ASSERT(synth != nullptr);
  471. CARLA_ASSERT(denormalkillbuf != nullptr);
  472. Master::deleteInstance();
  473. delete[] denormalkillbuf;
  474. denormalkillbuf = nullptr;
  475. delete synth;
  476. synth = nullptr;
  477. }
  478. }
  479. static void maybeInitPrograms(Master* const master)
  480. {
  481. static bool doSearch = true;
  482. if (! doSearch)
  483. return;
  484. doSearch = false;
  485. pthread_mutex_lock(&master->mutex);
  486. // refresh banks
  487. master->bank.rescanforbanks();
  488. for (uint32_t i=0, size = master->bank.banks.size(); i < size; i++)
  489. {
  490. if (master->bank.banks[i].dir.empty())
  491. continue;
  492. master->bank.loadbank(master->bank.banks[i].dir);
  493. for (unsigned int instrument = 0; instrument < BANK_SIZE; instrument++)
  494. {
  495. const std::string insName(master->bank.getname(instrument));
  496. if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
  497. continue;
  498. sPrograms.append(new ProgramInfo(i, instrument, insName.c_str()));
  499. }
  500. }
  501. pthread_mutex_unlock(&master->mutex);
  502. }
  503. static void loadProgram(Master* const master, const uint32_t bank, const uint32_t program)
  504. {
  505. const std::string& bankdir(master->bank.banks[bank].dir);
  506. if (! bankdir.empty())
  507. {
  508. pthread_mutex_lock(&master->mutex);
  509. master->bank.loadbank(bankdir);
  510. for (int i=0; i < NUM_MIDI_PARTS; i++)
  511. master->bank.loadfromslot(program, master->part[i]);
  512. master->applyparameters(false);
  513. pthread_mutex_unlock(&master->mutex);
  514. }
  515. }
  516. static void clearPrograms()
  517. {
  518. for (auto it = sPrograms.begin(); it.valid(); it.next())
  519. {
  520. ProgramInfo* const programInfo(*it);
  521. delete programInfo;
  522. }
  523. sPrograms.clear();
  524. }
  525. private:
  526. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin)
  527. };
  528. int ZynAddSubFxPlugin::sInstanceCount = 0;
  529. NonRtList<ZynAddSubFxPlugin::ProgramInfo*> ZynAddSubFxPlugin::sPrograms;
  530. struct ProgramsDestructor {
  531. ProgramsDestructor() {}
  532. ~ProgramsDestructor()
  533. {
  534. ZynAddSubFxPlugin::clearPrograms();
  535. }
  536. } programsDestructor;
  537. // -----------------------------------------------------------------------
  538. static const PluginDescriptor zynAddSubFxDesc = {
  539. /* category */ PLUGIN_CATEGORY_SYNTH,
  540. #ifdef WANT_ZYNADDSUBFX_UI
  541. /* hints */ static_cast<PluginHints>(PLUGIN_IS_SYNTH|PLUGIN_HAS_GUI/*|PLUGIN_USES_SINGLE_THREAD*/|PLUGIN_USES_STATE),
  542. #else
  543. /* hints */ static_cast<PluginHints>(PLUGIN_IS_SYNTH|PLUGIN_USES_STATE),
  544. #endif
  545. /* audioIns */ 2,
  546. /* audioOuts */ 2,
  547. /* midiIns */ 1,
  548. /* midiOuts */ 0,
  549. /* paramIns */ ZynAddSubFxPlugin::PARAMETER_COUNT,
  550. /* paramOuts */ 0,
  551. /* name */ "ZynAddSubFX",
  552. /* label */ "zynaddsubfx",
  553. /* maker */ "falkTX",
  554. /* copyright */ "GNU GPL v2+",
  555. PluginDescriptorFILL(ZynAddSubFxPlugin)
  556. };
  557. // -----------------------------------------------------------------------
  558. void carla_register_native_plugin_zynaddsubfx()
  559. {
  560. carla_register_native_plugin(&zynAddSubFxDesc);
  561. }
  562. // -----------------------------------------------------------------------