bool QLCMIDIProtocol::midiToInput(uchar cmd, uchar data1, uchar data2, uchar midiChannel, quint32* channel, uchar* value) { /* Check if cmd is a MIDI COMMAND byte */ if (!MIDI_IS_CMD(cmd)) return false; /** Use a special handler function for system common messages */ if (MIDI_IS_SYSCOMMON(cmd)) return midiSysCommonToInput(cmd, data1, data2, channel, value); /* Check that the command came on the correct MIDI channel */ if (midiChannel <= 0xF && MIDI_CH(cmd) != midiChannel) return false; switch(MIDI_CMD(cmd)) { case MIDI_NOTE_OFF: *channel = CHANNEL_OFFSET_NOTE + quint32(data1); *value = 0; return true; case MIDI_NOTE_ON: *channel = CHANNEL_OFFSET_NOTE + quint32(data1); *value = MIDI2DMX(data2); return true; case MIDI_NOTE_AFTERTOUCH: *channel = CHANNEL_OFFSET_NOTE_AFTERTOUCH + quint32(data1); *value = MIDI2DMX(data2); return true; case MIDI_CONTROL_CHANGE: *channel = CHANNEL_OFFSET_CONTROL_CHANGE + quint32(data1); *value = MIDI2DMX(data2); return true; case MIDI_PROGRAM_CHANGE: *channel = CHANNEL_OFFSET_PROGRAM_CHANGE; *value = MIDI2DMX(data1); return true; case MIDI_CHANNEL_AFTERTOUCH: *channel = CHANNEL_OFFSET_CHANNEL_AFTERTOUCH; *value = MIDI2DMX(data1); return true; case MIDI_PITCH_WHEEL: *channel = CHANNEL_OFFSET_PITCH_WHEEL; *value = MIDI2DMX(data2); return true; default: return false; } }
static void MidiInProc(const MIDIPacketList* pktList, void* readProcRefCon, void* srcConnRefCon) { Q_UNUSED(readProcRefCon); CoreMidiInputDevice* self = static_cast<CoreMidiInputDevice*>(srcConnRefCon); Q_ASSERT(self != 0); // Go thru all packets in the midi packet list const MIDIPacket* packet = &pktList->packet[0]; for (quint32 p = 0; p < pktList->numPackets && packet != NULL; ++p) { // Go thru all simultaneously-occurring messages in the packet for (quint32 i = 0; i < packet->length && i < 256; ++i) { uchar cmd = 0; uchar data1 = 0; uchar data2 = 0; quint32 channel = 0; uchar value = 0; // MIDI Command cmd = packet->data[0]; if (!MIDI_IS_CMD(cmd)) continue; // Not a MIDI command. Skip to the next byte. if (cmd == MIDI_SYSEX) break; // Sysex reserves the whole packet. Not interested. // 1 or 2 MIDI Data bytes if (packet->length > (i + 1) && !MIDI_IS_CMD(packet->data[i + 1])) { data1 = packet->data[++i]; if (packet->length > (i + 1) && !MIDI_IS_CMD(packet->data[i + 1])) data2 = packet->data[++i]; else // no data2 ? Could be a Program Change, so act like Linux // and give it a value data2 = 127; } if (cmd >= MIDI_BEAT_CLOCK && cmd <= MIDI_BEAT_STOP) { if (self->processMBC(cmd) == false) continue; } // Convert the data to QLC input channel & value if (QLCMIDIProtocol::midiToInput(cmd, data1, data2, self->midiChannel(), &channel, &value) == true) { self->emitValueChanged(channel, value); // for MIDI beat clock signals, // generate a synthetic release event if (cmd >= MIDI_BEAT_CLOCK && cmd <= MIDI_BEAT_STOP) self->emitValueChanged(channel, 0); } } // Get the next packet in the packet list packet = MIDIPacketNext(packet); } }