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 }