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

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 }