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

Parts.cpp (6553B)


      1 #include "Parts.h"
      2 
      3 #include "PartButton.h"
      4 #include "VirusEditor.h"
      5 
      6 #include "VirusController.h"
      7 #include "VirusProcessor.h"
      8 #include "ParameterNames.h"
      9 
     10 #include "jucePluginEditorLib/pluginProcessor.h"
     11 #include "jucePluginEditorLib/patchmanager/savepatchdesc.h"
     12 
     13 #include "jucePluginLib/parameterbinding.h"
     14 
     15 #include "virusLib/device.h"
     16 
     17 namespace genericVirusUI
     18 {
     19 	Parts::Parts(VirusEditor& _editor) : m_editor(_editor)
     20 	{
     21 		_editor.findComponents<genericUI::Button<juce::DrawableButton>>(m_partSelect, "SelectPart");
     22 		_editor.findComponents<juce::Button>(m_presetPrev, "PresetPrev");
     23 		_editor.findComponents<juce::Button>(m_presetNext, "PresetNext");
     24 
     25 		_editor.findComponents<juce::Slider>(m_partVolume, "PartVolume");
     26 		_editor.findComponents<juce::Slider>(m_partPan, "PartPan");
     27 		_editor.findComponents<PartButton>(m_presetName, "PresetName");
     28 		_editor.findComponents<juce::Component>(m_partActive, "PartActive");
     29 
     30 		for(size_t i=0; i<m_partSelect.size(); ++i)
     31 		{
     32 			m_partSelect[i]->onClick = [this, i]{ selectPart(i); };
     33 			m_partSelect[i]->onDown = [this, i](const juce::MouseEvent& _e)
     34 			{
     35 				if(!_e.mods.isPopupMenu())
     36 					return false;
     37 				selectPartMidiChannel(i);
     38 				return true;
     39 			};
     40 
     41 			if(i < m_presetPrev.size())
     42 				m_presetPrev[i]->onClick = [this, i]{ selectPrevPreset(i); };
     43 
     44 			if(i < m_presetNext.size())
     45 				m_presetNext[i]->onClick = [this, i]{ selectNextPreset(i); };
     46 
     47 			m_presetName[i]->initalize(static_cast<uint8_t>(i));
     48 
     49 			const auto partVolume = _editor.getController().getParameterIndexByName(virus::g_paramPartVolume);
     50 			const auto partPanorama = _editor.getController().getParameterIndexByName(virus::g_paramPartPanorama);
     51 
     52 			_editor.getParameterBinding().bind(*m_partVolume[i], partVolume, static_cast<uint8_t>(i));
     53 			_editor.getParameterBinding().bind(*m_partPan[i], partPanorama, static_cast<uint8_t>(i));
     54 
     55 			m_partVolume[i]->getProperties().set("parameter", static_cast<int>(partVolume));
     56 			m_partPan[i]->getProperties().set("parameter", static_cast<int>(partPanorama));
     57 
     58 			m_partVolume[i]->getProperties().set("part", static_cast<int>(i));
     59 			m_partPan[i]->getProperties().set("part", static_cast<int>(i));
     60 		}
     61 
     62 		updateAll();
     63 
     64 		if(!m_partActive.empty())
     65 		{
     66 			for (const auto & partActive : m_partActive)
     67 			{
     68 				partActive->setInterceptsMouseClicks(false, false);
     69 				partActive->setVisible(false);
     70 			}
     71 
     72 			startTimer(1000/20);
     73 		}
     74 
     75 		m_onFrontpanelStateChanged.set(_editor.getController().onFrontPanelStateChanged, [this](const virusLib::FrontpanelState& _frontpanelState)
     76 		{
     77 			for(size_t i=0; i<m_frontpanelState.m_midiEventReceived.size(); ++i)
     78 				m_frontpanelState.m_midiEventReceived[i] |= _frontpanelState.m_midiEventReceived[i];
     79 		});
     80 	}
     81 
     82 	Parts::~Parts() = default;
     83 
     84 	void Parts::onProgramChange() const
     85 	{
     86 		updateAll();
     87 	}
     88 
     89 	void Parts::onPlayModeChanged() const
     90 	{
     91 		updateAll();
     92 	}
     93 
     94 	void Parts::onCurrentPartChanged() const
     95 	{
     96 		updateSelectedPart();
     97 	}
     98 
     99 	void Parts::selectPart(const size_t _part) const
    100 	{
    101 		m_editor.setPart(_part);
    102 	}
    103 
    104 	void Parts::selectPartMidiChannel(const size_t _part) const
    105 	{
    106 		const auto multiMode = m_editor.getController().isMultiMode();
    107 
    108 		if(!multiMode && _part > 0)
    109 			return;
    110 
    111 		juce::PopupMenu menu;
    112 
    113 		const auto idx = m_editor.getController().getParameterIndexByName(multiMode ? "Part Midi Channel" : "Midi Channel");
    114 		if(idx == pluginLib::Controller::InvalidParameterIndex)
    115 			return;
    116 
    117 		const auto v = m_editor.getController().getParameter(idx, static_cast<uint8_t>(multiMode ? _part : 0));
    118 
    119 		const std::string name = multiMode ? "Midi Channel " : "Global Midi Channel ";
    120 
    121 		for(uint8_t i=0; i<16; ++i)
    122 		{
    123 			menu.addItem(name + ' ' + std::to_string(i + 1), true, v->getUnnormalizedValue() == i, [v, i]
    124 			{
    125 				v->setUnnormalizedValueNotifyingHost(i, pluginLib::Parameter::Origin::Ui);
    126 			});
    127 		}
    128 
    129 		menu.showMenuAsync({});
    130 	}
    131 
    132 	void Parts::selectPrevPreset(size_t _part) const
    133 	{
    134 		if(m_presetPrev.size() == 1)
    135 			_part = m_editor.getController().getCurrentPart();
    136 
    137 		auto* pm = m_editor.getPatchManager();
    138 		if(pm && pm->selectPrevPreset(static_cast<uint32_t>(_part)))
    139 			return;
    140 		m_editor.getController().selectPrevPreset(static_cast<uint8_t>(_part));
    141 	}
    142 
    143 	void Parts::selectNextPreset(size_t _part) const
    144 	{
    145 		if(m_presetNext.size() == 1)
    146 			_part = m_editor.getController().getCurrentPart();
    147 
    148 		auto* pm = m_editor.getPatchManager();
    149 		if(pm && pm->selectNextPreset(static_cast<uint32_t>(_part)))
    150 			return;
    151 		m_editor.getController().selectNextPreset(static_cast<uint8_t>(_part));
    152 	}
    153 
    154 	void Parts::updatePresetNames() const
    155 	{
    156 		for(size_t i=0; i<m_presetName.size(); ++i)
    157 			m_presetName[i]->setButtonText(m_editor.getController().getCurrentPartPresetName(static_cast<uint8_t>(i)));
    158 	}
    159 
    160 	void Parts::updateSelectedPart() const
    161 	{
    162 		const auto part = m_editor.getController().getCurrentPart();
    163 
    164 		if(part < m_partSelect.size())
    165 			m_partSelect[part]->setToggleState(true, juce::dontSendNotification);
    166 
    167 		for(size_t i=0; i<m_partSelect.size(); ++i)
    168 		{
    169 			if(i == part)
    170 				continue;
    171 			m_partSelect[i]->setToggleState(false, juce::dontSendNotification);
    172 		}
    173 	}
    174 
    175 	void Parts::updateSingleOrMultiMode() const
    176 	{
    177 	    const auto multiMode = m_editor.getController().isMultiMode();
    178 
    179 		const auto partCount = multiMode ? static_cast<virus::VirusProcessor&>(m_editor.getProcessor()).getPartCount() : 1;
    180 
    181 		for(size_t i=0; i<m_partSelect.size(); ++i)
    182 		{
    183 			const bool visible = i < partCount;
    184 
    185 			VirusEditor::setEnabled(*m_partSelect[i], visible);
    186 			VirusEditor::setEnabled(*m_partPan[i], visible);
    187 			VirusEditor::setEnabled(*m_partVolume[i], visible);
    188 
    189 			if(i < m_presetPrev.size())
    190 				VirusEditor::setEnabled(*m_presetPrev[i], visible);
    191 
    192 			if(i < m_presetNext.size())
    193 				VirusEditor::setEnabled(*m_presetNext[i], visible);
    194 
    195 			m_presetName[i]->setVisible(visible);
    196 		}
    197 
    198 		const auto volumeParam = m_editor.getController().getParameterIndexByName(multiMode ? virus::g_paramPartVolume : virus::g_paramPatchVolume);
    199 		m_editor.getParameterBinding().bind(*m_partVolume[0], volumeParam, 0);
    200 		m_partVolume[0]->getProperties().set("parameter", static_cast<int>(volumeParam));
    201 	}
    202 
    203 	void Parts::timerCallback()
    204 	{
    205 		auto& fpState = m_frontpanelState;
    206 
    207 		const uint32_t maxPart = m_editor.getController().isMultiMode() ? 16 : 1;
    208 
    209 		for(uint32_t i=0; i<m_partActive.size(); ++i)
    210 		{
    211 			m_partActive[i]->setVisible(i < maxPart && fpState.m_midiEventReceived[i]);
    212 			fpState.m_midiEventReceived[i] = false;
    213 		}
    214 	}
    215 
    216 	void Parts::updateAll() const
    217 	{
    218 		updatePresetNames();
    219 		updateSelectedPart();
    220 		updateSingleOrMultiMode();
    221 	}
    222 }