Пример #1
0
void qxgeditMidiDevice::sendSysex (
	unsigned char *pSysex, unsigned short iSysex ) const
{
#ifdef CONFIG_DEBUG
	fprintf(stderr, "qxgeditMidiDevice::sendSysex(%p, %u)", pSysex, iSysex);
	fprintf(stderr, " sysex {");
	for (unsigned short i = 0; i < iSysex; ++i)
		fprintf(stderr, " %02x", pSysex[i]);
	fprintf(stderr, " }\n");
#endif

	// Don't do anything else if engine
	// has not been activated...
	if (m_pAlsaSeq == NULL)
		return;

	// Initialize sequencer event...
	snd_seq_event_t ev;
	snd_seq_ev_clear(&ev);

	// Addressing...
	snd_seq_ev_set_source(&ev, m_iAlsaPort);
	snd_seq_ev_set_subs(&ev);

	// The event will be direct...
	snd_seq_ev_set_direct(&ev);

	// Just set SYSEX stuff and send it out..
	ev.type = SND_SEQ_EVENT_SYSEX;
	snd_seq_ev_set_sysex(&ev, iSysex, pSysex);
	snd_seq_event_output_direct(m_pAlsaSeq, &ev);
}
Пример #2
0
void ALSAMidiDriver::send_sysex(uint8 status,const uint8 *msg,uint16 length) {
	unsigned char buf[1024];

	if (length > 511) {
		perr << "ALSAMidiDriver: "
			 << "Cannot send SysEx block - data too large" << std::endl;
		return;
	}
	buf[0] = status;
	memcpy(buf + 1, msg, length);
	snd_seq_ev_set_sysex(&ev, length + 1, &buf);
	send_event(1);
}
Пример #3
0
void MidiDriver_ALSA::sysEx(const byte *msg, uint16 length) {
	unsigned char buf[266];

	assert(length + 2 <= ARRAYSIZE(buf));

	// Add SysEx frame
	buf[0] = 0xF0;
	memcpy(buf + 1, msg, length);
	buf[length + 1] = 0xF7;

	// Send it
	snd_seq_ev_set_sysex(&ev, length + 2, &buf);
	send_event(1);
}
Пример #4
0
/* Send sysex buffer (buffer must contain complete sysex msg w/ SYSEX & EOX) */
int
midi_send_sysex(int port, void *buf, int buflen)
{
  int err;
  snd_seq_event_t sendev;

  if (port >= MAX_PORTS) return -1;
 
  snd_seq_ev_clear(&sendev);
  snd_seq_ev_set_source(&sendev, ports[port]);
  snd_seq_ev_set_subs(&sendev);
  snd_seq_ev_set_sysex(&sendev, buflen, buf);
  snd_seq_ev_set_direct(&sendev);
  err = snd_seq_event_output_direct(seq, &sendev);
  if (err < 0)
    eprintf("Couldn't send MIDI sysex: %s\n", snd_strerror(err));
  return err;
}
Пример #5
0
void MidiDriver_ALSA::sysEx(const byte *msg, uint16 length) {
	if (!_isOpen) {
		warning("MidiDriver_ALSA: Got SysEx while not open");
		return;
	}

	unsigned char buf[266];

	assert(length + 2 <= ARRAYSIZE(buf));

	// Add SysEx frame
	buf[0] = 0xF0;
	memcpy(buf + 1, msg, length);
	buf[length + 1] = 0xF7;

	// Send it
	snd_seq_ev_set_sysex(&ev, length + 2, &buf);
	send_event(1);
}
Пример #6
0
/* takes an native event, encodes to alsa event, 
   puts it in the queue */
void 
midibus::sysex( event *a_e24 )
{
    lock();

    snd_seq_event_t ev;
   
    /* clear event */
    snd_seq_ev_clear( &ev );
    snd_seq_ev_set_priority( &ev, 1 );

    /* set source */
    snd_seq_ev_set_source(&ev, m_local_addr_port );
    snd_seq_ev_set_subs(&ev);
    
    // its immediate 
    snd_seq_ev_set_direct( &ev );

    
    unsigned char *data = a_e24->get_sysex();
    long data_size =  a_e24->get_size();
    for( long offset = 0;
	 offset < data_size;
	 offset += c_midibus_sysex_chunk ){

      long data_left = data_size - offset;

      snd_seq_ev_set_sysex( &ev, 
			       min( data_left, c_midibus_sysex_chunk), 
			       &data[offset] ); 
      
      /* pump it into the queue */
      snd_seq_event_output_direct(m_seq, &ev);

      usleep(80000);
      
      flush();

    }

    unlock();
}
void AlsaMidiOutputDevice::writeSysEx(QByteArray message)
{
    if(message.isEmpty())
        return;

    if (isOpen() == false)
        return;

    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);

    snd_seq_ev_set_sysex (&ev, message.count(), message.data());

    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);
}
Пример #8
0
void
midibus::sysex (event * e24)
{
#ifdef SEQ64_HAVE_LIBASOUND
    automutex locker(m_mutex);
    snd_seq_event_t ev;
    snd_seq_ev_clear(&ev);                              /* clear event      */
    snd_seq_ev_set_priority(&ev, 1);
    snd_seq_ev_set_source(&ev, m_local_addr_port);      /* set source       */
    snd_seq_ev_set_subs(&ev);
    snd_seq_ev_set_direct(&ev);                         /* it's immediate   */

    /*
     *  Replaced by a vector of midibytes:
     *
     *      midibyte * data = e24->get_sysex();
     *
     *  This is a bit tricky, and relies on the standard property of
     *  std::vector where all n elements of the vector are guaranteed to be
     *  stored contiguously (in order to be accessible via random-access
     *  iterators).
     */

    event::SysexContainer & data = e24->get_sysex();
    int data_size = e24->get_sysex_size();
    for (int offset = 0; offset < data_size; offset += c_midibus_sysex_chunk)
    {
        int data_left = data_size - offset;
        snd_seq_ev_set_sysex
        (
            &ev, min(data_left, c_midibus_sysex_chunk), &data[offset]
        );
        snd_seq_event_output_direct(m_seq, &ev);        /* pump into queue  */
        usleep(SEQ64_USLEEP_US);
        flush();
    }
#endif  // SEQ64_HAVE_LIBASOUND
}
Пример #9
0
/**************************************************************************
 *		modLongData					[internal]
 */
static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
{
    int		len_add = 0;
    LPBYTE	lpData, lpNewData = NULL;
    snd_seq_event_t event;

    TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);

    /* Note: MS doc does not say much about the dwBytesRecorded member of the MIDIHDR structure
     * but it seems to be used only for midi input.
     * Taking a look at the WAVEHDR structure (which is quite similar) confirms this assumption.
     */
    
    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;
    }

    lpData = (LPBYTE) lpMidiHdr->lpData;
    
    if (lpData == NULL)
	return MIDIERR_UNPREPARED;
    if (!(lpMidiHdr->dwFlags & MHDR_PREPARED))
	return MIDIERR_UNPREPARED;
    if (lpMidiHdr->dwFlags & MHDR_INQUEUE)
	return MIDIERR_STILLPLAYING;
    lpMidiHdr->dwFlags &= ~MHDR_DONE;
    lpMidiHdr->dwFlags |= MHDR_INQUEUE;

    /* FIXME: MS doc is not 100% clear. Will lpData only contain system exclusive
     * data, or can it also contain raw MIDI data, to be split up and sent to
     * modShortData() ?
     * If the latest is true, then the following WARNing will fire up
     */
    if (lpData[0] != 0xF0 || lpData[lpMidiHdr->dwBufferLength - 1] != 0xF7) {
	WARN("Alleged system exclusive buffer is not correct\n\tPlease report with MIDI file\n");
	lpNewData = HeapAlloc(GetProcessHeap(), 0, lpMidiHdr->dwBufferLength + 2);
    }

    TRACE("dwBufferLength=%lu !\n", lpMidiHdr->dwBufferLength);
    TRACE("                 %02X %02X %02X ... %02X %02X %02X\n",
	  lpData[0], lpData[1], lpData[2], lpData[lpMidiHdr->dwBufferLength-3],
	  lpData[lpMidiHdr->dwBufferLength-2], lpData[lpMidiHdr->dwBufferLength-1]);

    switch (MidiOutDev[wDevID].caps.wTechnology) {
    case MOD_FMSYNTH:
	/* FIXME: I don't think there is much to do here */
	break;
    case MOD_MIDIPORT:
	if (lpData[0] != 0xF0) {
	    /* Send start of System Exclusive */
	    len_add = 1;
	    lpData[0] = 0xF0;
	    memcpy(lpNewData, lpData, lpMidiHdr->dwBufferLength);
	    WARN("Adding missing 0xF0 marker at the beginning of "
		 "system exclusive byte stream\n");
	}
	if (lpData[lpMidiHdr->dwBufferLength-1] != 0xF7) {
	    /* Send end of System Exclusive */
	    memcpy(lpData + len_add, lpData, lpMidiHdr->dwBufferLength);
            lpNewData[lpMidiHdr->dwBufferLength + len_add - 1] = 0xF0;
	    len_add++;
	    WARN("Adding missing 0xF7 marker at the end of "
		 "system exclusive byte stream\n");
	}
	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);
	TRACE("client = %d port = %d\n", MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port);
	snd_seq_ev_set_sysex(&event, lpMidiHdr->dwBufferLength + len_add, lpNewData ? lpNewData : lpData);
	snd_seq_event_output_direct(midiSeq, &event);
	if (lpNewData)
		HeapFree(GetProcessHeap(), 0, lpData);
	break;
    default:
	WARN("Technology not supported (yet) %d !\n",
	     MidiOutDev[wDevID].caps.wTechnology);
	return MMSYSERR_NOTENABLED;
    }

    lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
    lpMidiHdr->dwFlags |= MHDR_DONE;
    if (MIDI_NotifyClient(wDevID, MOM_DONE, (DWORD)lpMidiHdr, 0L) != MMSYSERR_NOERROR) {
	WARN("can't notify client !\n");
	return MMSYSERR_INVALPARAM;
    }
    return MMSYSERR_NOERROR;
}
Пример #10
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;
}
Пример #11
0
// MIDI clip freewheeling event enqueue method (needed for export).
void qtractorMidiClip::enqueue_export ( qtractorTrack *pTrack,
	qtractorMidiEvent *pEvent, unsigned long iTime, float fGain ) const
{
	qtractorSession *pSession = pTrack->session();
	if (pSession == NULL)
		return;

	snd_seq_event_t ev;
	snd_seq_ev_clear(&ev);

	snd_seq_ev_schedule_tick(&ev, 0, 0, iTime);

	switch (pEvent->type()) {
	case qtractorMidiEvent::NOTEON:
		ev.type = SND_SEQ_EVENT_NOTE;
		ev.data.note.channel  = pTrack->midiChannel();
		ev.data.note.note     = pEvent->note();
		ev.data.note.velocity = int(fGain * float(pEvent->value())) & 0x7f;
		ev.data.note.duration = pEvent->duration();
		break;
	case qtractorMidiEvent::KEYPRESS:
		ev.type = SND_SEQ_EVENT_KEYPRESS;
		ev.data.note.channel  = pTrack->midiChannel();
		ev.data.note.note     = pEvent->note();
		ev.data.note.velocity = pEvent->velocity();
		ev.data.note.duration = 0;
		break;
	case qtractorMidiEvent::CONTROLLER:
		ev.type = SND_SEQ_EVENT_CONTROLLER;
		ev.data.control.channel = pTrack->midiChannel();
		ev.data.control.param   = pEvent->controller();
		ev.data.control.value   = pEvent->value();
		break;
	case qtractorMidiEvent::PGMCHANGE:
		ev.type = SND_SEQ_EVENT_PGMCHANGE;
		ev.data.control.channel = pTrack->midiChannel();
		ev.data.control.value   = pEvent->value();
		break;
	case qtractorMidiEvent::CHANPRESS:
		ev.type = SND_SEQ_EVENT_CHANPRESS;
		ev.data.control.channel = pTrack->midiChannel();
		ev.data.control.value   = pEvent->value();
		break;
	case qtractorMidiEvent::PITCHBEND:
		ev.type = SND_SEQ_EVENT_PITCHBEND;
		ev.data.control.channel = pTrack->midiChannel();
		ev.data.control.value   = pEvent->pitchBend();
		break;
	case qtractorMidiEvent::SYSEX:
		ev.type = SND_SEQ_EVENT_SYSEX;
		snd_seq_ev_set_sysex(&ev, pEvent->sysex_len(), pEvent->sysex());
		break;
	default:
		break;
	}

	qtractorTimeScale::Cursor& cursor = pSession->timeScale()->cursor();
	qtractorTimeScale::Node *pNode = cursor.seekTick(iTime);
	const unsigned long t1 = pNode->frameFromTick(iTime);
	unsigned long t2 = t1;
	if (ev.type == SND_SEQ_EVENT_NOTE
		&& ev.data.note.duration > 0) {
		iTime += (ev.data.note.duration - 1);
		pNode = cursor.seekTick(iTime);
		t2 += (pNode->frameFromTick(iTime) - t1);
	}

	// Do it for the MIDI track plugins...
	qtractorMidiManager *pMidiManager
		= (pTrack->pluginList())->midiManager();
	if (pMidiManager)
		pMidiManager->queued(&ev, t1, t2);

	// And for the MIDI output plugins as well...
	// Target MIDI bus...
	qtractorMidiBus *pMidiBus
		= static_cast<qtractorMidiBus *> (pTrack->outputBus());
	if (pMidiBus && pMidiBus->pluginList_out()) {
		pMidiManager = (pMidiBus->pluginList_out())->midiManager();
		if (pMidiManager)
			pMidiManager->queued(&ev, t1, t2);
	}
}