void MIDIDevice::outputDMX(const QByteArray& universe) { MIDIOut* plugin = static_cast<MIDIOut*> (parent()); Q_ASSERT(plugin != NULL); Q_ASSERT(plugin->alsa() != NULL); Q_ASSERT(m_address != NULL); /* Setup a common event structure for all values */ snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_dest(&ev, m_address->client, m_address->port); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); /* Since MIDI devices can have only 128 real channels, we don't attempt to write more than that */ for (unsigned char channel = 0; channel < MAX_MIDI_DMX_CHANNELS; channel++) { /* Scale 0-255 to 0-127 */ char scaled = DMX2MIDI(universe[channel]); /* Since MIDI is so slow, we only send values that are actually changed. */ if (m_values[channel] == scaled) continue; /* Store the changed MIDI value */ m_values[channel] = scaled; if (mode() == Note) { if (scaled == 0) { /* 0 is sent as a note off command */ snd_seq_ev_set_noteoff(&ev, midiChannel(), channel, scaled); } else { /* 1-127 is sent as note on command */ snd_seq_ev_set_noteon(&ev, midiChannel(), channel, scaled); } snd_seq_event_output(plugin->alsa(), &ev); } else { /* Control change */ snd_seq_ev_set_controller(&ev, midiChannel(), channel, scaled); snd_seq_event_output_buffer(plugin->alsa(), &ev); } } /* Make sure that all values go to the MIDI endpoint */ snd_seq_drain_output(plugin->alsa()); }
bool QLCMIDIProtocol::feedbackToMidi(quint32 channel, uchar value, uchar midiChannel, uchar* cmd, uchar* data1, uchar* data2, bool* data2Valid) { if (channel >= CHANNEL_OFFSET_NOTE && channel <= CHANNEL_OFFSET_NOTE_MAX) { if (value == 0) *cmd = MIDI_NOTE_OFF; else *cmd = MIDI_NOTE_ON; *cmd |= midiChannel; *data1 = static_cast <uchar> (channel - CHANNEL_OFFSET_NOTE); *data2 = DMX2MIDI(value); *data2Valid = true; } else if (/*channel >= CHANNEL_OFFSET_CONTROL_CHANGE &&*/ channel <= CHANNEL_OFFSET_CONTROL_CHANGE_MAX) { *cmd = MIDI_CONTROL_CHANGE | midiChannel; *data1 = static_cast <uchar> (channel - CHANNEL_OFFSET_CONTROL_CHANGE); *data2 = DMX2MIDI(value); *data2Valid = true; } else if (channel >= CHANNEL_OFFSET_NOTE_AFTERTOUCH && channel <= CHANNEL_OFFSET_NOTE_AFTERTOUCH_MAX) { *cmd = MIDI_NOTE_AFTERTOUCH | midiChannel; *data1 = static_cast <uchar> (channel - CHANNEL_OFFSET_NOTE_AFTERTOUCH); *data2 = DMX2MIDI(value); *data2Valid = true; } else if (channel == CHANNEL_OFFSET_CHANNEL_AFTERTOUCH) { *cmd = MIDI_CHANNEL_AFTERTOUCH | midiChannel; *data1 = DMX2MIDI(value); *data2Valid = false; } else if (channel == CHANNEL_OFFSET_PROGRAM_CHANGE) { *cmd = MIDI_PROGRAM_CHANGE | midiChannel; *data1 = DMX2MIDI(value); *data2Valid = false; } else if (channel == CHANNEL_OFFSET_PITCH_WHEEL) { *cmd = MIDI_PITCH_WHEEL | midiChannel; *data1 = DMX2MIDI(value); *data2Valid = false; } else { return false; } return true; }
void Win32MidiOutputDevice::writeUniverse(const QByteArray& universe) { if (isOpen() == false) return; for (BYTE channel = 0; channel < MAX_MIDI_DMX_CHANNELS && channel < universe.size(); channel++) { /* Scale 0-255 to 0-127 */ char scaled = DMX2MIDI(uchar(universe[channel])); /* Since MIDI is so slow, we only send values that are actually changed. */ if (m_universe[channel] == scaled) continue; /* Store the changed MIDI value */ m_universe[channel] = scaled; if (mode() == Note) { if (scaled == 0) { /* Zero is sent as a note off command */ sendData(MIDI_NOTE_OFF | (BYTE) midiChannel(), channel, scaled); } else { /* 1-127 are sent as note on commands */ sendData(MIDI_NOTE_ON | (BYTE) midiChannel(), channel, scaled); } } else if (mode() == ProgramChange) { /* Program change */ sendData(MIDI_PROGRAM_CHANGE | (BYTE) midiChannel(), channel, (BYTE)scaled); } else { //qDebug() << "[writeUniverse] MIDI: " << midiChannel() << ", channel: " << channel << ", value: " << scaled; /* Control change */ sendData(MIDI_CONTROL_CHANGE | (BYTE) midiChannel(), channel, (BYTE)scaled); } } }
void AlsaMidiOutputDevice::writeChannel(ushort channel, uchar value) { // m_universe contains scaled values (0-127), so we have to compare scaled value as well // however, since writeUniverse scales the value again, we have to store unscaled value. char scaled = DMX2MIDI(value); if (channel < ushort(m_universe.size()) && m_universe[channel] != scaled) { QByteArray tmp(m_universe); for (uchar ch = 0; ch < MAX_MIDI_DMX_CHANNELS && ch < tmp.size(); ++ch) { char midi = tmp[ch]; tmp[ch] = (char)MIDI2DMX(midi); } tmp[channel] = value; writeUniverse(tmp); } }
void MIDIDevice::outputDMX(const QByteArray& universe) { /* If there's no output port or a destination, the endpoint probably doesn't have a MIDI OUT port. */ if (m_outPort == 0 || m_destination == 0) return; Byte buffer[512]; // Should be enough for 128 channels MIDIPacketList* list = (MIDIPacketList*) buffer; MIDIPacket* packet = MIDIPacketListInit(list); /* Since MIDI devices can have only 128 real channels, we don't attempt to write more than that */ for (Byte channel = 0; channel < MAX_MIDI_DMX_CHANNELS; channel++) { Byte cmd[3]; cmd[1] = channel; cmd[2] = DMX2MIDI(universe[channel]); /* Since MIDI is so slow, we only send values that are actually changed. */ if (m_values[channel] == cmd[2]) continue; /* Store the changed MIDI value. */ m_values[channel] = cmd[2]; if (m_mode == Note) { if (cmd[2] == 0) { /* Zero is sent as a note off command */ cmd[0] = MIDI_NOTE_OFF; } else { /* 1-127 is sent as note on command */ cmd[0] = MIDI_NOTE_ON; } } else { /* Control change */ cmd[0] = MIDI_CONTROL_CHANGE; } /* Encode MIDI channel to the command */ cmd[0] |= (Byte) midiChannel(); /* Add the MIDI command to the packet list */ packet = MIDIPacketListAdd(list, sizeof(buffer), packet, 0, sizeof(cmd), cmd); if (packet == 0) { qWarning() << "MIDIOut buffer overflow"; break; } } /* Send the MIDI packet list */ OSStatus s = MIDISend(m_outPort, m_destination, list); if (s != 0) qWarning() << "Unable to send MIDI data to" << name(); }
void AlsaMidiOutputDevice::writeUniverse(const QByteArray& universe) { if (isOpen() == false) return; // Setup a common event structure for all values snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_dest(&ev, m_receiver_address->client, m_receiver_address->port); //snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); // Since MIDI devices can have only 128 real channels, we don't // attempt to write more than that. for (uchar channel = 0; channel < MAX_MIDI_DMX_CHANNELS && channel < universe.size(); channel++) { // Scale 0-255 to 0-127 char scaled = DMX2MIDI(universe[channel]); bool invalidData = false; // Since MIDI is so slow, we only send values that are actually changed if (m_universe[channel] == scaled) continue; // Store the changed MIDI value m_universe[channel] = scaled; if (mode() == Note) { qDebug() << "Send out NOTE"; // 0 is sent as a note off // 1-127 is sent as note on if (scaled == 0) snd_seq_ev_set_noteoff(&ev, midiChannel(), channel, scaled); else snd_seq_ev_set_noteon(&ev, midiChannel(), channel, scaled); snd_seq_event_output(m_alsa, &ev); } else if (mode() == ProgramChange) { qDebug() << "Send out Program Change"; snd_seq_ev_set_pgmchange(&ev, midiChannel(), channel); } else if (mode() == ControlChange) { qDebug() << "Send out CC. Channel: " << midiChannel() << ", CC: " << channel << ", val: " << scaled; // Control change snd_seq_ev_set_controller(&ev, midiChannel(), channel, scaled); } else invalidData = true; if (!invalidData) if (snd_seq_event_output(m_alsa, &ev) < 0) qDebug() << "snd_seq_event_output ERROR"; } // Make sure that all values go to the MIDI endpoint snd_seq_drain_output(m_alsa); }
bool QLCMIDIProtocol::feedbackToMidi(quint32 channel, uchar value, uchar midiChannel, uchar* cmd, uchar* data1, uchar* data2, bool* data2Valid) { // for OMNI mode, retrieve the original MIDI channel where data was sent if (midiChannel == MAX_MIDI_CHANNELS) midiChannel = channel >> 12; // Remove the 4 MSB bits to retrieve the QLC+ channel to be processed channel = channel & 0x0FFF; if (channel <= CHANNEL_OFFSET_CONTROL_CHANGE_MAX) { *cmd = MIDI_CONTROL_CHANGE | midiChannel; *data1 = static_cast <uchar> (channel - CHANNEL_OFFSET_CONTROL_CHANGE); *data2 = DMX2MIDI(value); *data2Valid = true; } else if (channel >= CHANNEL_OFFSET_NOTE && channel <= CHANNEL_OFFSET_NOTE_MAX) { if (value == 0) *cmd = MIDI_NOTE_OFF; else *cmd = MIDI_NOTE_ON; *cmd |= midiChannel; *data1 = static_cast <uchar> (channel - CHANNEL_OFFSET_NOTE); *data2 = DMX2MIDI(value); *data2Valid = true; } else if (channel >= CHANNEL_OFFSET_NOTE_AFTERTOUCH && channel <= CHANNEL_OFFSET_NOTE_AFTERTOUCH_MAX) { *cmd = MIDI_NOTE_AFTERTOUCH | midiChannel; *data1 = static_cast <uchar> (channel - CHANNEL_OFFSET_NOTE_AFTERTOUCH); *data2 = DMX2MIDI(value); *data2Valid = true; } else if (channel >= CHANNEL_OFFSET_PROGRAM_CHANGE && channel <= CHANNEL_OFFSET_PROGRAM_CHANGE_MAX) { *cmd = MIDI_PROGRAM_CHANGE | midiChannel; *data1 = DMX2MIDI(value); *data2Valid = false; } else if (channel == CHANNEL_OFFSET_CHANNEL_AFTERTOUCH) { *cmd = MIDI_CHANNEL_AFTERTOUCH | midiChannel; *data1 = DMX2MIDI(value); *data2Valid = false; } else if (channel == CHANNEL_OFFSET_PITCH_WHEEL) { *cmd = MIDI_PITCH_WHEEL | midiChannel; *data1 = DMX2MIDI(value); *data2Valid = false; } //else if (channel == MIDI_BEATC_CLOCK) //{ // Don't send feedback to MIDI clock //} else { return false; } return true; }
void CoreMidiOutputDevice::writeUniverse(const QByteArray& universe) { if (isOpen() == false) return; Byte buffer[512]; // Should be enough for 128 channels MIDIPacketList* list = (MIDIPacketList*) buffer; MIDIPacket* packet = MIDIPacketListInit(list); /* Since MIDI devices can have only 128 real channels, we don't attempt to write more than that */ for (Byte channel = 0; channel < MAX_MIDI_DMX_CHANNELS && channel < universe.size(); channel++) { Byte cmd[3]; cmd[1] = channel; cmd[2] = DMX2MIDI(uchar(universe[channel])); /* Since MIDI is so slow, we only send values that are actually changed. */ if (uchar(m_universe[channel]) == cmd[2]) continue; /* Store the changed MIDI value. */ m_universe[channel] = cmd[2]; if (mode() == Note) { if (cmd[2] == 0) { /* Zero is sent as a note off command */ cmd[0] = MIDI_NOTE_OFF; } else { /* 1-127 is sent as note on command */ cmd[0] = MIDI_NOTE_ON; } } else if (mode() == ProgramChange) { /* Program change */ cmd[0] = MIDI_PROGRAM_CHANGE; } else { /* Control change */ cmd[0] = MIDI_CONTROL_CHANGE; } /* Encode MIDI channel to the command */ cmd[0] |= (Byte) midiChannel(); /* Add the MIDI command to the packet list */ packet = MIDIPacketListAdd(list, sizeof(buffer), packet, 0, sizeof(cmd), cmd); if (packet == 0) { qWarning() << "MIDIOut buffer overflow"; break; } } /* Send the MIDI packet list */ OSStatus s = MIDISend(m_outPort, m_destination, list); if (s != 0) qWarning() << Q_FUNC_INFO << "Unable to send MIDI data to" << name(); }