midiPorts.cpp (4608B)
1 #include "midiPorts.h" 2 3 #include "pluginProcessor.h" 4 5 #include "juceUiLib/editor.h" 6 #include "juceUiLib/messageBox.h" 7 8 namespace 9 { 10 constexpr const char* const g_none = "<none>"; 11 12 void initComboBox(juce::ComboBox* _combo, const juce::Array<juce::MidiDeviceInfo>& _entries, const juce::String& _selectedEntry) 13 { 14 int inIndex = 0; 15 16 _combo->addItem(g_none, 1); 17 18 for (int i = 0; i < _entries.size(); i++) 19 { 20 const auto& input = _entries[i]; 21 22 if (input.identifier == _selectedEntry) 23 inIndex = i + 1; 24 25 _combo->addItem(input.name, i+2); 26 } 27 28 _combo->setSelectedItemIndex(inIndex, juce::dontSendNotification); 29 } 30 31 uint32_t createMenu(juce::PopupMenu& _menu, const juce::Array<juce::MidiDeviceInfo>& _devices, const juce::String& _current, const std::function<void(juce::String)>& _onSelect) 32 { 33 _menu.addItem(g_none, true, _current.isEmpty(), [_onSelect] 34 { 35 _onSelect({}); 36 }); 37 38 for (const auto& device : _devices) 39 { 40 _menu.addItem(device.name, true, device.identifier == _current, [id = device.identifier, _onSelect] 41 { 42 _onSelect(id); 43 }); 44 } 45 return _devices.size(); 46 } 47 } 48 49 namespace jucePluginEditorLib 50 { 51 MidiPorts::MidiPorts(const genericUI::Editor& _editor, Processor& _processor) : m_processor(_processor) 52 { 53 m_midiIn = _editor.findComponentT<juce::ComboBox>("MidiIn" , false); 54 m_midiOut = _editor.findComponentT<juce::ComboBox>("MidiOut", false); 55 56 if(m_midiIn) 57 { 58 initComboBox(m_midiIn, juce::MidiInput::getAvailableDevices(), getMidiPorts().getInputId()); 59 m_midiIn->onChange = [this]{ updateMidiInput(m_midiIn->getSelectedItemIndex()); }; 60 } 61 62 if(m_midiOut) 63 { 64 initComboBox(m_midiOut, juce::MidiOutput::getAvailableDevices(), getMidiPorts().getOutputId()); 65 m_midiOut->onChange = [this]{ updateMidiOutput(m_midiOut->getSelectedItemIndex()); }; 66 } 67 } 68 69 void MidiPorts::createMidiInputMenu(juce::PopupMenu& _menu, pluginLib::MidiPorts& _ports) 70 { 71 createMenu(_menu, juce::MidiInput::getAvailableDevices(), _ports.getInputId(), [&_ports](const juce::String& _id) 72 { 73 if(!_ports.setMidiInput(_id)) 74 showMidiPortFailedMessage(_ports.getProcessor(), "Input"); 75 }); 76 } 77 78 void MidiPorts::createMidiOutputMenu(juce::PopupMenu& _menu, pluginLib::MidiPorts& _ports) 79 { 80 createMenu(_menu, juce::MidiOutput::getAvailableDevices(), _ports.getOutputId(), [&_ports](const juce::String& _id) 81 { 82 if(!_ports.setMidiOutput(_id)) 83 showMidiPortFailedMessage(_ports.getProcessor(), "Output"); 84 }); 85 } 86 87 void MidiPorts::createMidiPortsMenu(juce::PopupMenu& _menu, pluginLib::MidiPorts& _ports) 88 { 89 juce::PopupMenu inputs, outputs, ports; 90 91 createMidiInputMenu(inputs, _ports); 92 createMidiOutputMenu(outputs, _ports); 93 94 ports.addSubMenu("Input", inputs); 95 ports.addSubMenu("Output", outputs); 96 97 _menu.addSubMenu("MIDI Ports", ports); 98 } 99 100 pluginLib::MidiPorts& MidiPorts::getMidiPorts() const 101 { 102 return m_processor.getMidiPorts(); 103 } 104 105 void MidiPorts::showMidiPortFailedMessage(const char* _name) const 106 { 107 showMidiPortFailedMessage(m_processor, _name); 108 } 109 110 void MidiPorts::showMidiPortFailedMessage(const pluginLib::Processor& _processor, const char* _name) 111 { 112 genericUI::MessageBox::showOk(juce::MessageBoxIconType::WarningIcon, _processor.getProperties().name, 113 std::string("Failed to open Midi ") + _name + ".\n\n" 114 "Make sure that the device is not already in use by another program."); 115 } 116 117 void MidiPorts::updateMidiInput(int _index) const 118 { 119 const auto list = juce::MidiInput::getAvailableDevices(); 120 121 if (_index <= 0) 122 { 123 m_midiIn->setSelectedItemIndex(_index, juce::dontSendNotification); 124 return; 125 } 126 127 _index--; 128 129 const auto newInput = list[_index]; 130 131 if (!getMidiPorts().setMidiInput(newInput.identifier)) 132 { 133 showMidiPortFailedMessage("Input"); 134 m_midiIn->setSelectedItemIndex(0, juce::dontSendNotification); 135 return; 136 } 137 138 m_midiIn->setSelectedItemIndex(_index + 1, juce::dontSendNotification); 139 } 140 141 void MidiPorts::updateMidiOutput(int _index) const 142 { 143 const auto list = juce::MidiOutput::getAvailableDevices(); 144 145 if (_index == 0) 146 { 147 m_midiOut->setSelectedItemIndex(_index, juce::dontSendNotification); 148 getMidiPorts().setMidiOutput({}); 149 return; 150 } 151 _index--; 152 const auto newOutput = list[_index]; 153 if (!getMidiPorts().setMidiOutput(newOutput.identifier)) 154 { 155 showMidiPortFailedMessage("Output"); 156 m_midiOut->setSelectedItemIndex(0, juce::dontSendNotification); 157 return; 158 } 159 160 m_midiOut->setSelectedItemIndex(_index + 1, juce::dontSendNotification); 161 } 162 }