Page 1 of 1

MidiPlugin and sendNoteOff setting not used?

Posted: Mon Nov 25, 2019 4:31 pm
by tubaguy
Good day coder-types,

I've been attempting to determine why the Speed control feedback is not working on the APCmini. If I hardcode sendFeedback to use false for the sendNoteOff the APCmini will blink properly with the tap tempo, otherwise no amount of changing the input profile checkbox seems to have effect.

Near as I can tell, the only interaction for feedback is via the sendNoteOff value for the midi device (default is true in the constructor). Several code snips follow:

void MidiPlugin::sendFeedBack(quint32 universe, quint32 output, quint32 channel, uchar value, const QString &)
{
...
if (QLCMIDIProtocol::feedbackToMidi(channel, value, dev->midiChannel(), dev->sendNoteOff(),
&cmd, &data1, &data2) == true)

MidiPlugin::setParameter sets device setSendNoteOff
else if (name == "MIDISendNoteOff")
{
dev = qobject_cast<MidiDevice*>(outputDevice(line));
if (dev != NULL)
dev->setSendNoteOff(value.toBool());
}
I cannot locate any function that calls to QLCIOPlugin::setParameter (MidiPlugin::setParameter) with "MIDISendNoteOff" as the name.

Bug?

thx,
Jeff

Re: MidiPlugin and sendNoteOff setting not used?

Posted: Mon Nov 25, 2019 7:56 pm
by tubaguy
Other relevant details, this is 4.12.2 on Windows. I just loaded up an Ubuntu VM, where the APCmini is working fine.

Re: MidiPlugin and sendNoteOff setting not used?

Posted: Fri Nov 29, 2019 3:56 pm
by tubaguy
I am wondering if the trouble with the SendNoteOff is because windows MIDI devices do not line up. For instance, the Microsoft GS Wavetable Synth shows up first in the Output/Feedback checkbox list, but it is not in the Input section.

It looks that the SendNoteOff is only applied during the processing of an input device. I added a hack in universe.cpp that makes the APCmini work as expected by forcing the parameter with a feedback patch

Code: Select all

bool Universe::loadXMLPluginParameters(QXmlStreamReader &root, PatchTagType currentTag)
{
    if (root.name() != KXMLQLCUniversePluginParameters)
    {
        qWarning() << Q_FUNC_INFO << "PluginParameters node not found";
        return false;
    }

    QXmlStreamAttributes pluginAttrs = root.attributes();
    for (int i = 0; i < pluginAttrs.count(); i++)
    {
        QXmlStreamAttribute attr = pluginAttrs.at(i);
        if (currentTag == InputPatchTag)
        {
            InputPatch *ip = inputPatch();
            if (ip != NULL)
                ip->setPluginParameter(attr.name().toString(), attr.value().toString());
        }
        else if (currentTag == OutputPatchTag)
        {
            OutputPatch *op = outputPatch();
            if (op != NULL)
                op->setPluginParameter(attr.name().toString(), attr.value().toString());
        }
        else if (currentTag == FeedbackPatchTag)
        {
            OutputPatch *fbp = feedbackPatch();
            if (fbp != NULL)
                fbp->setPluginParameter(attr.name().toString(), attr.value().toString());
        }
    }
	// HACK for Windows Feedback noteoff
	if (currentTag == FeedbackPatchTag)
        {
            OutputPatch *fbp = feedbackPatch();
            if (fbp != NULL)
                fbp->setPluginParameter("MIDISendNoteOff", "false");
        }
	// End Hack
		
    root.skipCurrentElement();

    return true;

Re: MidiPlugin and sendNoteOff setting not used?

Posted: Tue Dec 10, 2019 3:20 pm
by tubaguy
I tested the theory that the MIDI inputs and Outputs on Windows is causing the problem, and the results were positive on my system. I added a hack to t he win32enumerator.cpp to skip the "Microsoft GS Wavetable Synth" and now the APC Mini feedback works properly. It is only a sample size of one, so if anyone else is running Windows with the APC Mini and can give it a try, that'd be great.

Code: Select all

void MidiEnumeratorPrivate::rescan()
{
    qDebug() << Q_FUNC_INFO;

    // OUTPUT
    // Destroy existing outputs since there is no way of knowing if something has
    // disappeared or appeared in the middle between 0 - midiOutGetNumDevs().
    while (m_outputDevices.isEmpty() == false)
        delete m_outputDevices.takeFirst();

    // Create new device instances for each valid midi output
    for (UINT id = 0; id < midiOutGetNumDevs(); id++)
    {
        QVariant uid = extractUID(id);
        QString name = extractOutputName(id);
		// HACK to skip MS wavetable
		if (name == "Microsoft GS Wavetable Synth")
			continue;
		// End HACK
        Win32MidiOutputDevice* dev = new Win32MidiOutputDevice(uid, name, id, this);
        m_outputDevices << dev;
    }

    // INPUT
    // Destroy existing inputs since there is no way of knowing if something has
    // disappeared or appeared in the middle between 0 - midiInGetNumDevs().
    while (m_inputDevices.isEmpty() == false)
        delete m_inputDevices.takeFirst();

    // Create new device instances for each valid midi input
    for (UINT id = 0; id < midiInGetNumDevs(); id++)
    {
        QVariant uid = extractUID(id);
        QString name = extractInputName(id);
        Win32MidiInputDevice* dev = new Win32MidiInputDevice(uid, name, id, this);
        m_inputDevices << dev;
    }

    emit configurationChanged();
}