示例#1
0
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());
}
示例#2
0
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);
    }
}
示例#5
0
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);
}
示例#7
0
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();
}