Example #1
0
void CoreMidiDriver::readProc(const MIDIPacketList *packetList, void *readProcRefCon, void *srcConnRefCon) {
Q_UNUSED(srcConnRefCon)

	CoreMidiSession *data = (CoreMidiSession *)readProcRefCon;
	if (data->midiSession == NULL) {
		data->midiSession = driver->createMidiSession(data->sessionID);
	}
	QMidiStreamParser &qMidiStreamParser = *data->midiSession->getQMidiStreamParser();
	qMidiStreamParser.setTimestamp(MasterClock::getClockNanos());
	MIDIPacket const *packet = &packetList->packet[0];
	UInt32 numPackets = packetList->numPackets;
	while (numPackets > 0) {
		UInt32 packetLen = packet->length;
		if (packetLen > 0) {
			qMidiStreamParser.parseStream(packet->data, packetLen);
		}
		packet = MIDIPacketNext(packet);
		numPackets--;
	}
}
Example #2
0
void MidiApple::HandleReadCallback( const MIDIPacketList *pktlist, void *srcConnRefCon )
{
	const char * refName = (const char *) srcConnRefCon;

	MIDIEndpointRef endPointRef = m_inputDevices.value(refName);
	if( !m_inputSubs.contains( refName ) )
	{
//		qDebug("HandleReadCallback '%s' not subscribed",refName);
//		printQStringKeys("m_inputDevices", m_inputDevices);
		return;
	}
//	qDebug("HandleReadCallback '%s' subscribed",refName);
	bool continueSysEx = false;
	unsigned int nBytes;
	const MIDIPacket *packet = &pktlist->packet[0];
	unsigned char sysExMessage[SYSEX_LENGTH];
	unsigned int sysExLength = 0;
	
	for (uint32_t i=0; i<pktlist->numPackets; ++i)
	{
		nBytes = packet->length;
		// Check if this is the end of a continued SysEx message
		if (continueSysEx) {
			unsigned int lengthToCopy = qMin(nBytes, SYSEX_LENGTH - sysExLength);
			// Copy the message into our SysEx message buffer,
			// making sure not to overrun the buffer
			memcpy(sysExMessage + sysExLength, packet->data, lengthToCopy);
			sysExLength += lengthToCopy;
			// Check if the last byte is SysEx End.
			continueSysEx = (packet->data[nBytes - 1] == 0xF7);
			if (!continueSysEx || sysExLength == SYSEX_LENGTH) {
				// We would process the SysEx message here, as it is we're just ignoring it
				
				sysExLength = 0;
			}
		}
		else
		{
			UInt16 iByte, size;
			
			iByte = 0;
			while (iByte < nBytes)
			{
				size = 0;
				
				// First byte should be status
				unsigned char status = packet->data[iByte];
				if (status < 0xC0) {
					size = 3;
				}
				else if (status < 0xE0)
				{
					size = 2;
				}
				else if (status < 0xF0)
				{
					size = 3;
				}
				else if (status == 0xF0)
				{
					// MIDI SysEx then we copy the rest of the message into the SysEx message buffer
					unsigned int lengthLeftInMessage = nBytes - iByte;
					unsigned int lengthToCopy = qMin(lengthLeftInMessage, SYSEX_LENGTH);
					
					memcpy(sysExMessage + sysExLength, packet->data, lengthToCopy);
					sysExLength += lengthToCopy;
					
					size = 0;
					iByte = nBytes;
					
					// Check whether the message at the end is the end of the SysEx
					continueSysEx = (packet->data[nBytes - 1] != 0xF7);
				}
				else if (status < 0xF3)
				{
					size = 3;
				}
				else if (status == 0xF3)
				{
					size = 2;
				}
				else
				{
					size = 1;
				}
				
				unsigned char messageChannel = status & 0xF;
				const MidiEventTypes cmdtype = static_cast<MidiEventTypes>( status & 0xF0 );
				const int par1 = packet->data[iByte + 1];
				const int par2 = packet->data[iByte + 2];

				switch (cmdtype)
				{
					case MidiNoteOff: //0x80:
					case MidiNoteOn: //0x90:
					case MidiKeyPressure: //0xA0:
						notifyMidiPortList(m_inputSubs[refName],MidiEvent( cmdtype, messageChannel, par1 - KeysPerOctave, par2 & 0xff, &endPointRef ));
						break;
						
					case MidiControlChange: //0xB0:
					case MidiProgramChange: //0xC0:
					case MidiChannelPressure: //0xD0:
						notifyMidiPortList(m_inputSubs[refName],MidiEvent( cmdtype, messageChannel, par1, par2 & 0xff, &endPointRef ));
						break;
						
					case MidiPitchBend: //0xE0:
						notifyMidiPortList(m_inputSubs[refName],MidiEvent( cmdtype, messageChannel, par1 + par2 * 128, 0, &endPointRef ));
						break;
					case MidiActiveSensing: //0xF0
					case 0xF0:
						break;
					default:
						qDebug("endPointRef name='%s':Some other message %d", refName, cmdtype);
						break;
				}
				iByte += size;
			}
		}
		packet = MIDIPacketNext(packet);
	}
}
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);
    }
}