Updating ComboBox via setSelectedId() not working in C++ with JUCE?

101 Views Asked by At

I am struggling to get my ComboBox to show a new selection by code. When creating the box, I use outputSelector.setSelectedId(1); which nicely shows the 1st item in the list when the program is “build”.

According to JUCE documentation, setSelectedId(new ID) should change the shown item in the ComboBox, but somehow that doesn't work.

At certain point, I want the shown output to change via outputSelector.setSelectedId(outID + 1, juce::dontSendNotification); after that I change my midiOutput via midiOutput = juce::MidiOutput::openDevice(outputSelector.getSelectedId() - 1);

The weird thing is, that it opens the correct port and sends a message, but the ComboBox isn’t updated. Changing the Notification doesn’t help either.

Below the complete code

I changed the code a bit and added a button for testing. That works if inside the function, but setting it from another function isn't working. Maybe someone has an idea

[code]

#pragma once

#include <JuceHeader.h>
inline int outID = 0;


class MyMidiComponent : public juce::Component,
    public juce::MidiInputCallback
    
{
public:
    MyMidiComponent()
    {
         addAndMakeVisible(outputSelector);
        outputSelector.setTextWhenNoChoicesAvailable("No MIDI Outputs Enabled");
        outputSelector.onChange = [this] { midiOutput = juce::MidiOutput::openDevice(outputSelector.getSelectedId() - 1); };
        midiOutputs = juce::MidiOutput::getDevices();
        if (midiOutputs.size() > 0)
        {
            outputSelector.addItemList(midiOutputs, 1);
            outputSelector.setSelectedId(1);
            outputSelector.setEnabled(true);
        }
        else
        {
            outputSelector.setTextWhenNoChoicesAvailable("No MIDI Outputs Available");
            outputSelector.setEnabled(false);
        }
        juce::MidiOutput::openDevice(outputSelector.getText());
        outputSelector.setBounds(400, 10, 240, 20);

        myButton.setButtonText("Set");
        myButton.setBounds(360, 10, 30, 20);
        myButton.onClick = [this]() { outputSelector.setSelectedId(outID + 1, juce::dontSendNotification); };
        addAndMakeVisible(myButton);
    }

    void sendMidiMessage(int outChannel, int cc0, int cc32, int pc, juce::String outPort)
    {
        outID = 1; // midiOutputs.indexOf(outPort);
        if (outID >= 0)
        {
            outputSelector.setSelectedId(outID + 1, juce::dontSendNotification);
            outputSelector.repaint();
            midiOutput = juce::MidiOutput::openDevice(outputSelector.getSelectedId() - 1);
        }
        if (midiOutput != nullptr)
        {
            juce::MidiMessage msg;
            if (cc0 >= 0)
                msg = juce::MidiMessage::controllerEvent(outChannel, 0, cc0);
            if (cc32 >= 0)
                msg = juce::MidiMessage::controllerEvent(outChannel, 32, cc32);
            if (pc >= 0)
                msg = juce::MidiMessage::programChange(outChannel, pc);
            midiOutput->sendMessageNow(msg);
        }
    }

    ~MyMidiComponent()
    {
        if (midiInput != nullptr)
        {
            midiInput->stop();
            midiInput.reset();
            deviceManager.removeMidiInputDeviceCallback(juce::MidiInput::getAvailableDevices()[inputSelector.getSelectedItemIndex()].identifier, this);
        }
        if (midiOutput != nullptr)
            midiOutput.reset();
    }

    void paint(juce::Graphics& g) override
    {
    }

    void resized() override
    {
    }

    
    // MIDI input callback

    void handleIncomingMidiMessage(juce::MidiInput* source, const juce::MidiMessage& message) override
    {
        midiOutput = juce::MidiOutput::openDevice(outID);
        if (midiOutput != nullptr)
        {
            midiOutput->sendMessageNow(message);
        }
    }

    
private:
    juce::AudioDeviceManager deviceManager;
    int lastInputIndex = 0;
    juce::ComboBox inputSelector, outputSelector;
    std::unique_ptr<juce::MidiInput> midiInput;
    std::unique_ptr<juce::MidiOutput> midiOutput;
    juce::StringArray midiOutputs;
    juce::StringArray midiInputs;
    juce::TextButton myButton;
    

    /** Starts listening to a MIDI input device, enabling it if necessary. */
    void setMidiInput(int index)
    {
        auto list = juce::MidiInput::getAvailableDevices();

        deviceManager.removeMidiInputDeviceCallback(list[lastInputIndex].identifier, this);

        auto newInput = list[index];

        if (!deviceManager.isMidiInputDeviceEnabled(newInput.identifier))
            deviceManager.setMidiInputDeviceEnabled(newInput.identifier, true);

        deviceManager.addMidiInputDeviceCallback(newInput.identifier, this);
        inputSelector.setSelectedId(index + 1, juce::dontSendNotification);

        lastInputIndex = index;
    }


    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MyMidiComponent)
};

[/code]

0

There are 0 best solutions below