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.

739 lines
19KB

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