Пример #1
0
static void Func_ProgramChange( int channel, int program )
{
    snd_seq_event_t ev;
    snd_seq_ev_clear(&ev);
    snd_seq_ev_set_pgmchange(&ev, channel, program);
    sequence_event(&ev);
}
Пример #2
0
bool MidiAlsaDevice::putMidiEvent(const MidiPlayEvent& e)
{
    if (midiOutputTrace)
    {
        printf("MidiOut: midiAlsa: ");
        e.dump();
    }
    int chn = e.channel();
    int a = e.dataA();
    int b = e.dataB();

    snd_seq_event_t event;
    memset(&event, 0, sizeof (event));
    event.queue = SND_SEQ_QUEUE_DIRECT;
    event.source = losPort;
    event.dest = adr;

    switch (e.type())
    {
        case ME_NOTEON:
            snd_seq_ev_set_noteon(&event, chn, a, b);
            break;
        case ME_NOTEOFF:
            snd_seq_ev_set_noteoff(&event, chn, a, 0);
            break;
        case ME_PROGRAM:
            snd_seq_ev_set_pgmchange(&event, chn, a);
            break;
        case ME_CONTROLLER:
#if 1
            snd_seq_ev_set_controller(&event, chn, a, b);
#else
        {
            int a = e.dataA();
            int b = e.dataB();
            int chn = e.channel();
            if (a < CTRL_14_OFFSET)
            { // 7 Bit Controller
                snd_seq_ev_set_controller(&event, chn, a, b);
            }
            else if (a < CTRL_RPN_OFFSET)
            { // 14 bit high resolution controller
                int ctrlH = (a >> 8) & 0x7f;
                int ctrlL = a & 0x7f;
                a = (ctrlH << 7) + ctrlL;
                snd_seq_ev_set_controller(&event, chn, a, b);
                event.type = SND_SEQ_EVENT_CONTROL14;
            }
            else if (a < CTRL_NRPN_OFFSET)
            { // RPN 7-Bit Controller
                int ctrlH = (a >> 8) & 0x7f;
                int ctrlL = a & 0x7f;
                a = (ctrlH << 7) + ctrlL;
                b <<= 7;
                snd_seq_ev_set_controller(&event, chn, a, b);
                event.type = SND_SEQ_EVENT_REGPARAM;
            }
Пример #3
0
void MidiDriver_ALSA::send(uint32 b) {
	unsigned int midiCmd[4];
	ev.type = SND_SEQ_EVENT_OSS;

	midiCmd[3] = (b & 0xFF000000) >> 24;
	midiCmd[2] = (b & 0x00FF0000) >> 16;
	midiCmd[1] = (b & 0x0000FF00) >> 8;
	midiCmd[0] = (b & 0x000000FF);
	ev.data.raw32.d[0] = midiCmd[0];
	ev.data.raw32.d[1] = midiCmd[1];
	ev.data.raw32.d[2] = midiCmd[2];

	unsigned char chanID = midiCmd[0] & 0x0F;
	switch (midiCmd[0] & 0xF0) {
	case 0x80:
		snd_seq_ev_set_noteoff(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0x90:
		snd_seq_ev_set_noteon(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0xA0:
		snd_seq_ev_set_keypress(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0xB0:
		/* is it this simple ? Wow... */
		snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0xC0:
		snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]);
		send_event(0);
		break;
	case 0xD0:
		snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]);
		send_event(1);
		break;
	case 0xE0:{
			// long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4;
			// snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
			long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000;
			snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
			send_event(1);
		}
		break;

	default:
		warning("Unknown MIDI Command: %08x", (int)b);
		/* I don't know if this works but, well... */
		send_event(1);
		break;
	}
}
Пример #4
0
void ALSAMidiDriver::send(uint32 b) {
	unsigned int midiCmd[4];
	ev.type = SND_SEQ_EVENT_OSS;

	midiCmd[3] = (b & 0xFF000000) >> 24;
	midiCmd[2] = (b & 0x00FF0000) >> 16;
	midiCmd[1] = (b & 0x0000FF00) >> 8;
	midiCmd[0] = (b & 0x000000FF);
	ev.data.raw32.d[0] = midiCmd[0];
	ev.data.raw32.d[1] = midiCmd[1];
	ev.data.raw32.d[2] = midiCmd[2];

	unsigned char chanID = midiCmd[0] & 0x0F;
	switch (midiCmd[0] & 0xF0) {
	case 0x80:
		snd_seq_ev_set_noteoff(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0x90:
		snd_seq_ev_set_noteon(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0xB0:
		/* is it this simple ? Wow... */
		snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0xC0:
		snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]);
		send_event(0);
		break;
	case 0xD0:
		snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]);
		send_event(0);
		break;
	case 0xE0:{
			// long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4;
			// snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
			long theBend = (static_cast<long>(midiCmd[1]) + static_cast<long>(midiCmd[2] << 7)) - 0x2000;
			snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
			send_event(1);
		}
		break;

	default:
		perr << "ALSAMidiDriver: Unknown Command: "
			 << std::hex << static_cast<int>(b) << std::dec << std::endl;
		/* I don't know if this works but, well... */
		send_event(1);
		break;
	}
}
Пример #5
0
void prog_alsa(void* seqq, unsigned char chan, unsigned char indx)
{
    ALSA_SEQ* seq = (ALSA_SEQ*)seqq;
    snd_seq_event_t ev;

    snd_seq_ev_clear(&ev);
    snd_seq_ev_set_source(&ev, seq->g_port);
    snd_seq_ev_set_subs(&ev);
    snd_seq_ev_set_direct(&ev);
    //... // set event type, data, so on..

    snd_seq_ev_set_pgmchange(&ev, chan, indx);

    snd_seq_event_output(seq->g_seq, &ev);
    snd_seq_drain_output(seq->g_seq);
}
Пример #6
0
void sys_alsa_putmidimess(int portno, int a, int b, int c)
{
    int channel;
    snd_seq_event_t ev;
    snd_seq_ev_clear(&ev);
    if (portno >= 0 && portno < alsa_nmidiout)
    {
        if (a >= 224)   // pitchbend
        {
            channel = a-224;
            snd_seq_ev_set_pitchbend(&ev, channel, (((c<<7)|b)-8192)); /* b and c are already correct but alsa needs to recalculate them */
        }
        else if (a >= 208)      // touch
        {
            channel = a-208;
            snd_seq_ev_set_chanpress(&ev,channel,b);
        }
        else if (a >= 192)      // program
        {
            channel = a-192;
            snd_seq_ev_set_pgmchange(&ev,channel,b);
        }
        else if (a >= 176)      // controller
        {
            channel = a-176;
            snd_seq_ev_set_controller(&ev,channel,b,c);
        }
        else if (a >= 160)      // polytouch
        {
            channel = a-160;
            snd_seq_ev_set_keypress(&ev,channel,b,c);
        }
        else if (a >= 144)      // note
        {
            channel = a-144;
            if (c)
                snd_seq_ev_set_noteon(&ev,channel,b,c);
            else
                snd_seq_ev_set_noteoff(&ev,channel,b,c);
        }
        snd_seq_ev_set_direct(&ev);
        snd_seq_ev_set_subs(&ev);
        snd_seq_ev_set_source(&ev,alsa_midioutfd[portno]);
        snd_seq_event_output_direct(midi_handle,&ev);
    }
    //post("%d %d %d\n",a,b,c);
}
Пример #7
0
static void program_change(snd_seq_t *seq, int port, int chan, int program)
{
    snd_seq_event_t ev;

    snd_seq_ev_clear(&ev);
    snd_seq_ev_set_source(&ev, port);
    snd_seq_ev_set_subs(&ev);
    snd_seq_ev_set_direct(&ev);
    //... // set event type, data, so on..
    //set_event_time(&ev, Mf_currtime);
    //snd_seq_ev_schedule_tick(&ev, q, 0, Mf_currtime);

    snd_seq_ev_set_pgmchange(&ev, chan, program);

    int rc = snd_seq_event_output(seq, &ev);
    if (rc < 0) {
        printf("written = %i (%s)\n", rc, snd_strerror(rc));
    }
    snd_seq_drain_output(seq);
}
void AlsaMidiOutputDevice::writeFeedback(uchar cmd, uchar data1, uchar data2)
{
    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);

    uchar midiCmd = MIDI_CMD(cmd);
    uchar midiCh = MIDI_CH(cmd);

    bool invalidCmd = false;

    switch(midiCmd)
    {
    case MIDI_NOTE_OFF:
        snd_seq_ev_set_noteoff(&ev, midiCh, data1, data2);
        break;

    case MIDI_NOTE_ON:
        snd_seq_ev_set_noteon(&ev, midiCh, data1, data2);
        break;

    case MIDI_CONTROL_CHANGE:
        snd_seq_ev_set_controller(&ev, midiCh, data1, data2);
        break;

    case MIDI_PROGRAM_CHANGE:
        snd_seq_ev_set_pgmchange(&ev, midiCh, data1);
        break;

    case MIDI_NOTE_AFTERTOUCH:
        snd_seq_ev_set_keypress(&ev, midiCh, data1, data2);
        break;

    case MIDI_CHANNEL_AFTERTOUCH:
        snd_seq_ev_set_chanpress(&ev, midiCh, data1);
        break;

    case MIDI_PITCH_WHEEL:
        snd_seq_ev_set_pitchbend(&ev, midiCh, ((data1 & 0x7f) | ((data2 & 0x7f) << 7)) - 8192);
        break;

    default:
        // What to do here ??
        invalidCmd = true;
        break;
    }

    if (!invalidCmd)
    {
        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);
}
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);
}
Пример #10
0
void MidiDriver_ALSA::send(uint32 b) {
	if (!_isOpen) {
		warning("MidiDriver_ALSA: Got event while not open");
		return;
	}

	unsigned int midiCmd[4];
	ev.type = SND_SEQ_EVENT_OSS;

	midiCmd[3] = (b & 0xFF000000) >> 24;
	midiCmd[2] = (b & 0x00FF0000) >> 16;
	midiCmd[1] = (b & 0x0000FF00) >> 8;
	midiCmd[0] = (b & 0x000000FF);
	ev.data.raw32.d[0] = midiCmd[0];
	ev.data.raw32.d[1] = midiCmd[1];
	ev.data.raw32.d[2] = midiCmd[2];

	unsigned char chanID = midiCmd[0] & 0x0F;
	switch (midiCmd[0] & 0xF0) {
	case 0x80:
		snd_seq_ev_set_noteoff(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0x90:
		snd_seq_ev_set_noteon(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0xA0:
		snd_seq_ev_set_keypress(&ev, chanID, midiCmd[1], midiCmd[2]);
		send_event(1);
		break;
	case 0xB0:
		/* is it this simple ? Wow... */
		snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]);

		// We save the volume of the first MIDI channel here to utilize it in
		// our workaround for broken USB-MIDI cables.
		if (chanID == 0 && midiCmd[1] == 0x07)
			_channel0Volume = midiCmd[2];

		send_event(1);
		break;
	case 0xC0:
		snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]);
		send_event(0);

		// Send a volume change command to work around a firmware bug in common
		// USB-MIDI cables. If the first MIDI command in a USB packet is a
		// Cx or Dx command, the second command in the packet is dropped
		// somewhere.
		send(0x07B0 | (_channel0Volume << 16));
		break;
	case 0xD0:
		snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]);
		send_event(1);

		// Send a volume change command to work around a firmware bug in common
		// USB-MIDI cables. If the first MIDI command in a USB packet is a
		// Cx or Dx command, the second command in the packet is dropped
		// somewhere.
		send(0x07B0 | (_channel0Volume << 16));
		break;
	case 0xE0: {
		// long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4;
		// snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
		long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000;
		snd_seq_ev_set_pitchbend(&ev, chanID, theBend);
		send_event(1);
		} break;

	default:
		warning("Unknown MIDI Command: %08x", (int)b);
		/* I don't know if this works but, well... */
		send_event(1);
		break;
	}
}
Пример #11
0
void MidiAlsaSeq::processOutEvent( const MidiEvent& event, const MidiTime& time, const MidiPort* port )
{
	// HACK!!! - need a better solution which isn't that easy since we
	// cannot store const-ptrs in our map because we need to call non-const
	// methods of MIDI-port - it's a mess...
	MidiPort* p = const_cast<MidiPort *>( port );

	snd_seq_event_t ev;
	snd_seq_ev_clear( &ev );
	snd_seq_ev_set_source( &ev, ( m_portIDs[p][1] != -1 ) ?
					m_portIDs[p][1] : m_portIDs[p][0] );
	snd_seq_ev_set_subs( &ev );
	snd_seq_ev_schedule_tick( &ev, m_queueID, 1, static_cast<int>( time ) );
	ev.queue =  m_queueID;
	switch( event.type() )
	{
		case MidiNoteOn:
			snd_seq_ev_set_noteon( &ev,
						event.channel(),
						event.key() + KeysPerOctave,
						event.velocity() );
			break;

		case MidiNoteOff:
			snd_seq_ev_set_noteoff( &ev,
						event.channel(),
						event.key() + KeysPerOctave,
						event.velocity() );
			break;

		case MidiKeyPressure:
			snd_seq_ev_set_keypress( &ev,
						event.channel(),
						event.key() + KeysPerOctave,
						event.velocity() );
			break;

		case MidiControlChange:
			snd_seq_ev_set_controller( &ev,
						event.channel(),
						event.controllerNumber(),
						event.controllerValue() );
			break;

		case MidiProgramChange:
			snd_seq_ev_set_pgmchange( &ev,
						event.channel(),
						event.program() );
			break;

		case MidiChannelPressure:
			snd_seq_ev_set_chanpress( &ev,
						event.channel(),
						event.channelPressure() );
			break;

		case MidiPitchBend:
			snd_seq_ev_set_pitchbend( &ev,
						event.channel(),
						event.param( 0 ) - 8192 );
			break;

		default:
			qWarning( "MidiAlsaSeq: unhandled output event %d\n", (int) event.type() );
			return;
	}

	m_seqMutex.lock();
	snd_seq_event_output( m_seqHandle, &ev );
	snd_seq_drain_output( m_seqHandle );
	m_seqMutex.unlock();

}
Пример #12
0
void SendMidiCommand(int nIdPortOut, char *buf)
{
	/*
	   MIDI COMMANDS
	   -------------------------------------------------------------------
	   name                 status      param 1          param 2
	   -------------------------------------------------------------------
	   note off             0x80+C       key #            velocity
	   note on              0x90+C       key #            velocity
	   poly key pressure    0xA0+C       key #            pressure value
	   control change       0xB0+C       control #        control value
	   program change       0xC0+C       program #        --
	   mono key pressure    0xD0+C       pressure value   --
	   pitch bend           0xE0+C       range (LSB)      range (MSB)
	   system               0xF0+C       manufacturer     model
	   -------------------------------------------------------------------
	   C is the channel number, from 0 to 15;
	   -------------------------------------------------------------------
	   source: http://ftp.ec.vanderbilt.edu/computermusic/musc216site/MIDI.Commands.html
	
	   In this program the pitch bend range will be transmitter as 
	   one single 8-bit number. So the end result is that MIDI commands 
	   will be transmitted as 3 bytes, starting with the operation byte:
	
	   buf[0] --> operation/channel
	   buf[1] --> param1
	   buf[2] --> param2        (param2 not transmitted on program change or key press)


	snd_seq_event_t ev;
	snd_seq_ev_clear(&ev);
	snd_seq_ev_set_source(&ev, nIdPortOut);
	snd_seq_ev_set_subs(&ev);
	snd_seq_ev_set_direct(&ev);

	snd_seq_ev_set_noteoff(&ev, 0, note, 60);
	
	snd_seq_event_output(t_seq, &ev);


   */

	snd_seq_event_t t_event;
	snd_seq_ev_clear(&t_event);
									//			printf("Serial  port: %u\n", nIdPortOut);
	snd_seq_ev_set_source(&t_event, nIdPortOutA);
	snd_seq_ev_set_subs(&t_event);
	snd_seq_ev_set_direct(&t_event);

	int operation, channel, param1, param2;

	operation = buf[0] & 0xF0;
	channel   = buf[0] & 0x0F;
	param1    = buf[1];
	param2    = buf[2];

	switch (operation)
	{
		case 0x80:
			printf("OUT   ==> 0x%x Note off           0x%x 0x%x 0x%x\n", operation, channel, param1, param2);
			snd_seq_ev_set_noteoff(&t_event, channel, param1, param2);
			break;
			
		case 0x90:
			printf("OUT   ==> 0x%x Note on            0x%x 0x%x 0x%x\n", operation, channel, param1, param2);
			snd_seq_ev_set_noteon(&t_event, channel, param1, param2);
			break;
			
		case 0xA0:
			printf("OUT   ==> 0x%x Pressure change    0x%x 0x%x 0x%x\n", operation, channel, param1, param2);
			snd_seq_ev_set_keypress(&t_event, channel, param1, param2);
			break;

		case 0xB0:
			printf("OUT   ==> 0x%x Controller change  0x%x 0x%x 0x%x\n", operation, channel, param1, param2);
			snd_seq_ev_set_controller(&t_event, channel, param1, param2);
			break;

		case 0xC0:
			printf("OUT   ==> 0x%x Program change     0x%x 0x%x 0x%x\n", operation, channel, param1);
			snd_seq_ev_set_pgmchange(&t_event, channel, param1);
			break;

		case 0xD0:
			printf("OUT   ==> 0x%x Channel change     0x%x 0x%x 0x%x\n", operation, channel, param1);
			snd_seq_ev_set_chanpress(&t_event, channel, param1);
			break;

		case 0xE0:
			param1 = (param1 & 0x7F) + ((param2 & 0x7F) << 7);
			printf("OUT   ==> 0x%x Pitch bend         %03u %05i\n", operation, channel, param1);
			snd_seq_ev_set_pitchbend(&t_event, channel, param1 - 8192); // in alsa MIDI we want signed int
			break;

		/* Not implementing system commands (0xF0) */
			
		default:
			printf("OUT       0x%x Unknown MIDI cmd   %03u %03u %03u\n", operation, channel, param1, param2);
			break;
	}

	snd_seq_event_output_direct(t_seq, &t_event);
	//snd_seq_drain_output(t_seq);
	//snd_seq_event_output(t_seq, &t_event);

}
Пример #13
0
void sys_alsa_putmidimess(int portno, int a, int b, int c)
{
    if (portno >= 0 && portno < alsa_nmidiout)
    {
        snd_seq_event_t ev;
        snd_seq_ev_clear(&ev);
        int status = a & 0xf0;
        int channel = a & 0x0f;
        status = (status >= MIDI_SYSEX) ? status : (status & 0xf0);
        switch (status)
        {
            case MIDI_NOTEON:
                snd_seq_ev_set_noteon(&ev, channel, b, c);
                break;
            case MIDI_NOTEOFF:
                snd_seq_ev_set_noteoff(&ev, channel, b, c);
                break;
            case MIDI_POLYAFTERTOUCH:
                snd_seq_ev_set_chanpress(&ev, channel, b);
                break;
            case MIDI_CONTROLCHANGE:
                snd_seq_ev_set_controller(&ev, channel, b, c);
                break;
            case MIDI_PROGRAMCHANGE:
                snd_seq_ev_set_pgmchange(&ev, channel, b);
                break;
            case MIDI_AFTERTOUCH:
                snd_seq_ev_set_chanpress(&ev, channel, b);
                break;
            case MIDI_PITCHBEND:
                /* b and c are already correct but alsa needs to recalculate them */
                snd_seq_ev_set_pitchbend(&ev, channel, (((c<<7)|b)-8192));
                break;
            case MIDI_TIMECODE:
                ev.type = SND_SEQ_EVENT_QFRAME;
                snd_seq_ev_set_fixed(&ev);
                ev.data.raw8.d[0] = a & 0xff; /* status */
                ev.data.raw8.d[1] = b & 0x7f; /* data */
                break;
            case MIDI_SONGPOS:
                ev.type = SND_SEQ_EVENT_SONGPOS;
                snd_seq_ev_set_fixed(&ev);
                ev.data.raw8.d[0] = a & 0xff; /* status */
                ev.data.raw8.d[1] = b & 0x7f; /* data */
                ev.data.raw8.d[2] = c & 0x7f; /* data */
                break;
            case MIDI_SONGSELECT:
                ev.type = SND_SEQ_EVENT_SONGSEL;
                snd_seq_ev_set_fixed(&ev);
                ev.data.raw8.d[0] = a & 0xff; /* status */
                ev.data.raw8.d[1] = b & 0x7f; /* data */
                break;
            default:
                bug("couldn't put alsa midi message");
                break;
        }
        snd_seq_ev_set_direct(&ev);
        snd_seq_ev_set_subs(&ev);
        snd_seq_ev_set_source(&ev, alsa_midioutfd[portno]);
        snd_seq_event_output_direct(midi_handle, &ev);
    }
    //post("%d %d %d\n", a, b, c);
}
Пример #14
0
/**************************************************************************
 * 			modData					[internal]
 */
static DWORD modData(WORD wDevID, DWORD dwParam)
{
    BYTE	evt = LOBYTE(LOWORD(dwParam));
    BYTE	d1  = HIBYTE(LOWORD(dwParam));
    BYTE	d2  = LOBYTE(HIWORD(dwParam));
    
    TRACE("(%04X, %08lX);\n", wDevID, dwParam);

    if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
    if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;

    if (midiSeq == NULL) {
	WARN("can't play !\n");
	return MIDIERR_NODEVICE;
    }
    switch (MidiOutDev[wDevID].caps.wTechnology) {
    case MOD_SYNTH:
    case MOD_MIDIPORT:
	{
	    int handled = 1; /* Assume event is handled */
            snd_seq_event_t event;
            snd_seq_ev_clear(&event);
            snd_seq_ev_set_direct(&event);
            snd_seq_ev_set_source(&event, port_out);
            snd_seq_ev_set_dest(&event, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port);
	    
	    switch (evt & 0xF0) {
	    case MIDI_CMD_NOTE_OFF:
		snd_seq_ev_set_noteoff(&event, evt&0x0F, d1, d2);
		break;
	    case MIDI_CMD_NOTE_ON:
		snd_seq_ev_set_noteon(&event, evt&0x0F, d1, d2);
		break;
	    case MIDI_CMD_NOTE_PRESSURE:
		snd_seq_ev_set_keypress(&event, evt&0x0F, d1, d2);
		break;
	    case MIDI_CMD_CONTROL:
		snd_seq_ev_set_controller(&event, evt&0x0F, d1, d2);
		break;
	    case MIDI_CMD_BENDER:
		snd_seq_ev_set_pitchbend(&event, evt&0x0F, ((WORD)d2 << 7 | (WORD)d1) - 0x2000);
		break;
	    case MIDI_CMD_PGM_CHANGE:
		snd_seq_ev_set_pgmchange(&event, evt&0x0F, d1);
		break;
	    case MIDI_CMD_CHANNEL_PRESSURE:
		snd_seq_ev_set_chanpress(&event, evt&0x0F, d1);
		break;
	    case MIDI_CMD_COMMON_SYSEX:
		switch (evt & 0x0F) {
		case 0x00:	/* System Exclusive, don't do it on modData,
				 * should require modLongData*/
		case 0x01:	/* Undefined */
		case 0x04:	/* Undefined. */
		case 0x05:	/* Undefined. */
		case 0x07:	/* End of Exclusive. */
		case 0x09:	/* Undefined. */
		case 0x0D:	/* Undefined. */
		    handled = 0;
		    break;
		case 0x06:	/* Tune Request */
		case 0x08:	/* Timing Clock. */
		case 0x0A:	/* Start. */
		case 0x0B:	/* Continue */
		case 0x0C:	/* Stop */
		case 0x0E: 	/* Active Sensing. */
		    /* FIXME: Is this function suitable for these purposes
		       (and also Song Select and Song Position Pointer) */
	            snd_seq_ev_set_sysex(&event, 1, &evt);
		    break;
		case 0x0F: 	/* Reset */
				/* snd_seq_ev_set_sysex(&event, 1, &evt);
				   this other way may be better */
		    {
			BYTE reset_sysex_seq[] = {MIDI_CMD_COMMON_SYSEX, 0x7e, 0x7f, 0x09, 0x01, 0xf7};
			snd_seq_ev_set_sysex(&event, sizeof(reset_sysex_seq), reset_sysex_seq);
		    }
		    break;
		case 0x03:	/* Song Select. */
		    {
			BYTE buf[2];
			buf[0] = evt;
			buf[1] = d1;
			snd_seq_ev_set_sysex(&event, sizeof(buf), buf);
	            }
	            break;
		case 0x02:	/* Song Position Pointer. */
		    {
			BYTE buf[3];
			buf[0] = evt;
			buf[1] = d1;
			buf[2] = d2;
			snd_seq_ev_set_sysex(&event, sizeof(buf), buf);
	            }
		    break;
		}
		break;
	    }
	    if (handled)
                snd_seq_event_output_direct(midiSeq, &event);
	}
	break;
    default:
	WARN("Technology not supported (yet) %d !\n",
	     MidiOutDev[wDevID].caps.wTechnology);
	return MMSYSERR_NOTENABLED;
    }

    return MMSYSERR_NOERROR;
}
Пример #15
0
/** main 
 *
 */
int
main ( int argc, char **argv )
{
	int keys = 0;
	int mc_offset = 0;

	snd_seq_event_t ev;

	int patch = 0;
	int bank = 0;

	fprintf( stderr, "lsmi-keyhack" " v" VERSION "\n" );

	get_args( argc, argv );

	fprintf( stderr, "Registering MIDI port...\n" );

	seq = open_client( CLIENT_NAME );

	if ( NULL == seq )
	{
		fprintf( stderr, "Error opening alsa sequencer!\n" );
		exit( 1 );
	}

	if ( ( port = open_output_port( seq ) ) < 0 )
	{
		fprintf( stderr, "Error opening MIDI output port!\n" );
		exit( 1 );
	}

	if ( sub_name )
	{
		snd_seq_addr_t addr;

		if ( snd_seq_parse_address( seq, &addr, sub_name ) < 0 )
			fprintf( stderr, "Couldn't parse address '%s'", sub_name );
		else if ( snd_seq_connect_to( seq, port, addr.client, addr.port ) <
				  0 )
		{
			fprintf( stderr, "Error creating subscription for port %i:%i",
					 addr.client, addr.port );
			exit( 1 );
		}
	}

	fprintf( stderr, "Initializing keyboard...\n" );

	if ( -1 == ( fd = open( device, O_RDWR ) ) )
	{
		fprintf( stderr, "Error opening event interface! (%s)\n",
				 strerror( errno ) );
		exit( 1 );
	}

	init_keyboard();

	set_traps();

	update_leds();

	fprintf( stderr, "Opening database...\n" );

	if ( database == defaultdatabase )
	{
		char *home = getenv( "HOME" );

		database = malloc( strlen( home ) + strlen( defaultdatabase ) + 2 );

		sprintf( database, "%s/%s", home, defaultdatabase );
	}

	if ( -1 == open_database( database ) )
	{
		fprintf( stderr, "******Key database missing or invalid******\n"
				 "Entering learning mode...\n"
				 "Make sure your \"keyboard\" device is connected!\n" );

		learn_mode();
	}

	analyze_map( &keys, &mc_offset );

	octave_min = ( mc_offset / 12 ) + 1;
	octave_max = 9 - ( ( keys - mc_offset ) / 12 );

	fprintf( stderr,
			 "%i keys, middle C is %ith from the left, lowest MIDI octave == %i, highest, %i\n",
			 keys, mc_offset + 1, octave_min, octave_max );

	fprintf( stderr, "Waiting for events...\n" );

	for ( ;; )
	{
		int keyi, newstate;

		keyi = get_keypress( &newstate );

		snd_seq_ev_clear( &ev );

		if ( map[keyi].control )
		{
			snd_seq_event_t e;

			if ( newstate == UP )
				continue;

			switch ( map[keyi].control )
			{
					/* All notes off */
					snd_seq_ev_set_controller( &ev, channel, 123, 0 );
					send_event( &ev );
					snd_seq_ev_clear( &ev );

				case CKEY_EXIT:
					fprintf( stderr, "Exiting...\n" );

					if ( close_database( database ) < 0 )
						fprintf( stderr, "Error saving database!\n" );

					clean_up();

					exit( 0 );

				case CKEY_MODE:

					prog_mode =
						prog_mode + 1 >
						NUM_PROG_MODES - 1 ? 0 : prog_mode + 1;
					fprintf( stderr, "Input mode change to %s\n",
							 mode_names[prog_mode] );

					update_leds();

					break;

				case CKEY_OCTAVE_DOWN:
					octave = min( octave - 1, octave_min );
					break;
				case CKEY_OCTAVE_UP:
					octave = max( octave + 1, octave_max );
					break;
				case CKEY_CHANNEL_DOWN:
					channel = min( channel - 1, 0 );
					break;
				case CKEY_CHANNEL_UP:
					channel = max( channel + 1, 15 );
					break;
				case CKEY_PATCH_DOWN:
					if ( patch == 0 && bank > 0 )
					{
						bank = min( bank - 1, 0 );
						patch = 127;

						snd_seq_ev_set_controller( &e, channel, 0, bank );
						send_event( &e );
					}
					else
						patch = min( patch - 1, 0 );

					snd_seq_ev_set_pgmchange( &ev, channel, patch );
					break;
				case CKEY_PATCH_UP:
					if ( patch == 127 && bank < 127 )
					{
						bank = max( bank + 1, 127 );
						patch = 0;

						snd_seq_ev_set_controller( &e, channel, 0, bank );
						send_event( &e );
					}
					else
						patch = max( patch + 1, 127 );

					snd_seq_ev_set_pgmchange( &ev, channel, patch );
					break;

				case CKEY_NUMERIC:
				{
					struct timeval tv;

					gettimeofday( &tv, NULL );
					/* Timeout in 5 secs */

					if ( tv.tv_sec - timeout.tv_sec >= 5 )
					{
						prog_index = 0;
					}

					timeout = tv;

					if ( prog_index == 0 )
						printf( "INPUT %s #: ", mode_names[prog_mode] );
				}

					prog_buf[prog_index++] = 48 + map[keyi].number;
					printf( "%i", map[keyi].number );
					fflush( stdout );

					if ( prog_index == 2 && prog_mode == CHANNEL )
					{

						/* FIXME: all notes off->channel */

						prog_buf[++prog_index] = '\0';
						channel = atoi( prog_buf );

						channel = max( channel, 15 );

						prog_index = 0;

						printf( " ENTER\n" );
					}
					else if ( prog_index == 3 )
					{
						prog_buf[++prog_index] = '\0';

						switch ( prog_mode )
						{
							case PATCH:
								patch = atoi( prog_buf );

								patch = max( patch, 127 );

								snd_seq_ev_set_pgmchange( &ev, channel,
														  patch );

								break;
							case BANK:
								bank = atoi( prog_buf );

								bank = max( bank, 127 );

								snd_seq_ev_set_controller( &ev, channel, 0,
														   bank );
								break;
							default:
								fprintf( stderr, "Internal error!\n" );
						}

						prog_index = 0;
						printf( " ENTER\n" );
					}

					break;
				default:
					fprintf( stderr, "Internal error!\n" );
			}

			send_event( &ev );

			continue;
		}
		else
			switch ( map[keyi].ev_type )
			{
				case SND_SEQ_EVENT_CONTROLLER:

					snd_seq_ev_set_controller( &ev, channel,
											   map[keyi].number,
											   newstate == DOWN ? 127 : 0 );

					break;

				case SND_SEQ_EVENT_NOTE:

					if ( newstate == DOWN )
						snd_seq_ev_set_noteon( &ev, channel,
											   map[keyi].number +
											   ( 12 * octave ), 64 );
					else
						snd_seq_ev_set_noteoff( &ev, channel,
												map[keyi].number +
												( 12 * octave ), 64 );
					break;

				default:
					fprintf( stderr, "Key has invalid mapping!\n" );
					break;
			}

		send_event( &ev );
	}
}