gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

n2xEditor.cpp (7057B)


      1 #include "n2xEditor.h"
      2 
      3 #include "n2xArp.h"
      4 #include "n2xController.h"
      5 #include "n2xFileType.h"
      6 #include "n2xFocusedParameter.h"
      7 #include "n2xLcd.h"
      8 #include "n2xLfo.h"
      9 #include "n2xMasterVolume.h"
     10 #include "n2xOctLed.h"
     11 #include "n2xOutputMode.h"
     12 #include "n2xPart.h"
     13 #include "n2xParts.h"
     14 #include "n2xPatchManager.h"
     15 #include "n2xPluginProcessor.h"
     16 #include "n2xSlider.h"
     17 #include "n2xVmMap.h"
     18 
     19 #include "jucePluginEditorLib/midiPorts.h"
     20 
     21 #include "jucePluginLib/parameterbinding.h"
     22 #include "jucePluginLib/pluginVersion.h"
     23 
     24 #include "n2xLib/n2xdevice.h"
     25 #include "n2xLib/n2xromloader.h"
     26 
     27 namespace n2xJucePlugin
     28 {
     29 	Editor::Editor(jucePluginEditorLib::Processor& _processor, pluginLib::ParameterBinding& _binding, const jucePluginEditorLib::Skin& _skin)
     30 	: jucePluginEditorLib::Editor(_processor, _binding, _skin)
     31 	, m_controller(dynamic_cast<Controller&>(_processor.getController()))
     32 	, m_parameterBinding(_binding)
     33 	{
     34 		create();
     35 
     36 		addMouseListener(this, true);
     37 		{
     38 			// Init Patch Manager
     39 			const auto container = findComponent("ContainerPatchManager");
     40 			constexpr auto scale = 0.8f;
     41 			const float x = static_cast<float>(container->getX());
     42 			const float y = static_cast<float>(container->getY());
     43 			const float w = static_cast<float>(container->getWidth());
     44 			const float h = static_cast<float>(container->getHeight());
     45 			container->setTransform(juce::AffineTransform::scale(scale, scale));
     46 			container->setSize(static_cast<int>(w / scale),static_cast<int>(h / scale));
     47 			container->setTopLeftPosition(static_cast<int>(x / scale),static_cast<int>(y / scale));
     48 
     49 			setPatchManager(new PatchManager(*this, container));
     50 		}
     51 
     52 		if(auto* versionNumber = findComponentT<juce::Label>("VersionNumber", false))
     53 		{
     54 			versionNumber->setText(pluginLib::Version::getVersionString(), juce::dontSendNotification);
     55 		}
     56 
     57 		if(auto* romSelector = findComponentT<juce::ComboBox>("RomSelector"))
     58 		{
     59 			const auto rom = n2x::RomLoader::findROM();
     60 
     61 			if(rom.isValid())
     62 			{
     63 				constexpr int id = 1;
     64 
     65 				const auto name = juce::File(rom.getFilename()).getFileName();
     66 				romSelector->addItem(name, id);
     67 			}
     68 			else
     69 			{
     70 				romSelector->addItem("<No ROM found>", 1);
     71 			}
     72 			romSelector->setSelectedId(1);
     73 			romSelector->setInterceptsMouseClicks(false, false);
     74 		}
     75 
     76 		m_arp.reset(new Arp(*this));
     77 		m_focusedParameter.reset(new FocusedParameter(*this));
     78 		m_lcd.reset(new Lcd(*this));
     79 		for(uint8_t i=0; i<m_lfos.size(); ++i)
     80 			m_lfos[i].reset(new Lfo(*this, i));
     81 		m_masterVolume.reset(new MasterVolume(*this));
     82 		m_octLed.reset(new OctLed(*this));
     83 		m_outputMode.reset(new OutputMode(*this));
     84 		m_parts.reset(new Parts(*this));
     85 		m_vmMap.reset(new VmMap(*this, m_parameterBinding));
     86 		m_midiPorts.reset(new jucePluginEditorLib::MidiPorts(*this, getProcessor()));
     87 
     88 		onPartChanged.set(m_controller.onCurrentPartChanged, [this](const uint8_t& _part)
     89 		{
     90 			setCurrentPart(_part);
     91 			m_parameterBinding.setPart(_part);
     92 		});
     93 
     94 		if(auto* bt = findComponentT<juce::Button>("button_store"))
     95 		{
     96 			bt->onClick = [this]
     97 			{
     98 				onBtSave();
     99 			};
    100 		}
    101 
    102 		if(auto* bt = findComponentT<juce::Button>("PresetPrev"))
    103 		{
    104 			bt->onClick = [this]
    105 			{
    106 				onBtPrev();
    107 			};
    108 		}
    109 
    110 		if(auto* bt = findComponentT<juce::Button>("PresetNext"))
    111 		{
    112 			bt->onClick = [this]
    113 			{
    114 				onBtNext();
    115 			};
    116 		}
    117 
    118 		m_onSelectedPatchChanged.set(getPatchManager()->onSelectedPatchChanged, [this](const uint32_t& _part, const pluginLib::patchDB::PatchKey& _patchKey)
    119 		{
    120 			onSelectedPatchChanged(static_cast<uint8_t>(_part), _patchKey);
    121 		});
    122 	}
    123 
    124 	Editor::~Editor()
    125 	{
    126 		m_arp.reset();
    127 		m_focusedParameter.reset();
    128 		m_lcd.reset();
    129 		for (auto& lfo : m_lfos)
    130 			lfo.reset();
    131 		m_masterVolume.reset();
    132 		m_octLed.reset();
    133 		m_outputMode.reset();
    134 		m_parts.reset();
    135 		m_vmMap.reset();
    136 		m_midiPorts.reset();
    137 		m_onSelectedPatchChanged.reset();
    138 	}
    139 
    140 	std::pair<std::string, std::string> Editor::getDemoRestrictionText() const
    141 	{
    142 		return {};
    143 	}
    144 
    145 	genericUI::Button<juce::DrawableButton>* Editor::createJuceComponent(genericUI::Button<juce::DrawableButton>* _button, genericUI::UiObject& _object, const std::string& _name, const juce::DrawableButton::ButtonStyle _buttonStyle)
    146 	{
    147 		if(	_name == "PerfSlotActiveA" || 
    148 			_name == "PerfSlotActiveB" || 
    149 			_name == "PerfSlotActiveC" || 
    150 			_name == "PerfSlotActiveD")
    151 			return new Part(*this, _name, _buttonStyle);
    152 
    153 		return jucePluginEditorLib::Editor::createJuceComponent(_button, _object, _name, _buttonStyle);
    154 	}
    155 
    156 	std::string Editor::getCurrentPatchName() const
    157 	{
    158 		const auto part = m_controller.getCurrentPart();
    159 		if(!m_activePatchNames[part].empty())
    160 			return m_activePatchNames[part];
    161 		return m_controller.getPatchName(part);
    162 	}
    163 
    164 	void Editor::onPatchActivated(const pluginLib::patchDB::PatchPtr& _patch, const uint32_t _part)
    165 	{
    166 		const auto isMulti = _patch->sysex.size() == n2x::g_multiDumpSize;
    167 
    168 		const auto name = _patch->getName();
    169 
    170 		setCurrentPatchName(_part, name);
    171 
    172 		if(isMulti)
    173 		{
    174 			for (uint8_t p=0; p<m_activePatchNames.size(); ++p)
    175 			{
    176 				if(p == _part)
    177 					continue;
    178 
    179 				// set patch name for all parts if the source is a multi
    180 				setCurrentPatchName(p, name);
    181 
    182 				// set patch manager selection so that all parts have the multi selected
    183 				getPatchManager()->setSelectedPatch(p, _patch);
    184 			}
    185 		}
    186 
    187 		m_lcd->updatePatchName();
    188 	}
    189 
    190 	genericUI::Slider* Editor::createJuceComponent(genericUI::Slider* _slider, genericUI::UiObject& _object)
    191 	{
    192 		return new Slider(*this);
    193 	}
    194 
    195 	void Editor::modifierKeysChanged(const juce::ModifierKeys& modifiers)
    196 	{
    197 		jucePluginEditorLib::Editor::modifierKeysChanged(modifiers);
    198 
    199 		m_vmMap->setEnabled(modifiers.isShiftDown());
    200 	}
    201 
    202 	void Editor::createExportFileTypeMenu(juce::PopupMenu& _menu, const std::function<void(pluginLib::FileType)>& _func) const
    203 	{
    204 		_menu.addItem(".nl2", [this, _func]{_func(fileType::g_nl2);});
    205 		jucePluginEditorLib::Editor::createExportFileTypeMenu(_menu, _func);
    206 	}
    207 
    208 	void Editor::mouseEnter(const juce::MouseEvent& _ev)
    209 	{
    210 		m_focusedParameter->onMouseEnter(_ev);
    211 	}
    212 
    213 	void Editor::onBtSave() const
    214 	{
    215 		juce::PopupMenu menu;
    216 
    217 		if(getPatchManager()->createSaveMenuEntries(menu, "Program"))
    218 			menu.addSeparator();
    219 
    220 		getPatchManager()->createSaveMenuEntries(menu, "Performance", 1);
    221 
    222 		menu.showMenuAsync({});
    223 	}
    224 
    225 	void Editor::onBtPrev() const
    226 	{
    227 		getPatchManager()->selectPrevPreset(m_controller.getCurrentPart());
    228 	}
    229 
    230 	void Editor::onBtNext() const
    231 	{
    232 		getPatchManager()->selectNextPreset(m_controller.getCurrentPart());
    233 	}
    234 
    235 	void Editor::setCurrentPatchName(uint8_t _part, const std::string& _name)
    236 	{
    237 		if(m_activePatchNames[_part] == _name)
    238 			return;
    239 
    240 		m_activePatchNames[_part] = _name;
    241 
    242 		if(m_controller.getCurrentPart() == _part)
    243 			m_lcd->updatePatchName();
    244 	}
    245 
    246 	void Editor::onSelectedPatchChanged(uint8_t _part, const pluginLib::patchDB::PatchKey& _patchKey)
    247 	{
    248 		auto source = _patchKey.source;
    249 		if(!source)
    250 			return;
    251 
    252 		if(source->patches.empty())
    253 			source = getPatchManager()->getDataSource(*source);
    254 
    255 		if(const auto patch = source->getPatch(_patchKey))
    256 			setCurrentPatchName(_part, patch->getName());
    257 	}
    258 }