diff options
Diffstat (limited to 'attic/muse2-oom/muse2/muse/driver/alsamidi.cpp')
-rw-r--r-- | attic/muse2-oom/muse2/muse/driver/alsamidi.cpp | 917 |
1 files changed, 0 insertions, 917 deletions
diff --git a/attic/muse2-oom/muse2/muse/driver/alsamidi.cpp b/attic/muse2-oom/muse2/muse/driver/alsamidi.cpp deleted file mode 100644 index c7ae07b5..00000000 --- a/attic/muse2-oom/muse2/muse/driver/alsamidi.cpp +++ /dev/null @@ -1,917 +0,0 @@ -//========================================================= -// MusE -// Linux Music Editor -// $Id: alsamidi.cpp,v 1.8.2.7 2009/11/19 04:20:33 terminator356 Exp $ -// (C) Copyright 2000-2001 Werner Schweer (ws@seh.de) -//========================================================= - -#include <stdio.h> - -#include "alsamidi.h" -#include "globals.h" -#include "midi.h" -#include "mididev.h" -#include "../midiport.h" -#include "../midiseq.h" -#include "../midictrl.h" -#include "../audio.h" -#include "mpevent.h" -//#include "sync.h" -#include "utils.h" -#include "audiodev.h" -#include "xml.h" - -static int alsaSeqFdi = -1; -static int alsaSeqFdo = -1; - -snd_seq_t* alsaSeq; -static snd_seq_addr_t musePort; - -//--------------------------------------------------------- -// MidiAlsaDevice -//--------------------------------------------------------- - -MidiAlsaDevice::MidiAlsaDevice(const snd_seq_addr_t& a, const QString& n) - : MidiDevice(n) - { - adr = a; - init(); - } - -//--------------------------------------------------------- -// selectWfd -//--------------------------------------------------------- - -int MidiAlsaDevice::selectWfd() - { - return alsaSeqFdo; - } - -//--------------------------------------------------------- -// open -//--------------------------------------------------------- - -QString MidiAlsaDevice::open() -{ - _openFlags &= _rwFlags; // restrict to available bits - snd_seq_port_subscribe_t* subs; - // Allocated on stack, no need to call snd_seq_port_subscribe_free() later. - snd_seq_port_subscribe_alloca(&subs); - - QString estr; - int wer = 0; - int rer = 0; - - // subscribe for writing - if (_openFlags & 1) - { - snd_seq_port_subscribe_set_sender(subs, &musePort); - snd_seq_port_subscribe_set_dest(subs, &adr); - // Not already subscribed (or error)? Then try subscribing. - if(snd_seq_get_port_subscription(alsaSeq, subs) < 0) - { - //int error = snd_seq_subscribe_port(alsaSeq, subs); - wer = snd_seq_subscribe_port(alsaSeq, subs); - //if (error < 0) - if(wer < 0) - //return QString("Play: ")+QString(snd_strerror(error)); - estr += (QString("Play: ") + QString(snd_strerror(wer)) + QString(" ")); - } - if(!wer) - _writeEnable = true; - } - - // subscribe for reading - if (_openFlags & 2) - { - snd_seq_port_subscribe_set_dest(subs, &musePort); - snd_seq_port_subscribe_set_sender(subs, &adr); - // Not already subscribed (or error)? Then try subscribing. - if(snd_seq_get_port_subscription(alsaSeq, subs) < 0) - { - //int error = snd_seq_subscribe_port(alsaSeq, subs); - rer = snd_seq_subscribe_port(alsaSeq, subs); - //if (error < 0) - if(rer < 0) - //return QString("Rec: ") + QString(snd_strerror(error)); - estr += (QString("Rec: ") + QString(snd_strerror(rer))); - } - if(!rer) - _readEnable = true; - } - - - if(wer < 0 || rer < 0) - return estr; - - return QString("OK"); -} - -//--------------------------------------------------------- -// close -//--------------------------------------------------------- - -void MidiAlsaDevice::close() -{ - snd_seq_port_subscribe_t* subs; - // Allocated on stack, no need to call snd_seq_port_subscribe_free() later. - snd_seq_port_subscribe_alloca(&subs); - - // Changed by T356. This function appears to be called only by MidiPort::setMidiDevice(), - // which closes then opens the device. - // Because the open flags are set BEFORE setMidiDevice() is called, we must ignore the flags. - // - // NOTE: Tested: The read unsubscribe works ok but not the write. - // As viewed in say, qjackctl, the connection is clearly lost, - // but strangely the events are still accepted, ie, playback notes - // are still heard etc. Tried an alsa midi device AND external fluidsynth inst. - // - // Also, jack running and with jack midi disabled, we get messages like - // MidiAlsaDevice::0x84512c0 putEvent(): midi write error: No such device - // dst 16:0 - // only sometimes (not when playing notes), but with jack midi turned on, - // we don't get the messages. With jack stopped we get the messages - // no matter if jack midi is turned on or not. - - //if (_openFlags & 1) { - //if (!(_openFlags & 1)) - { - snd_seq_port_subscribe_set_sender(subs, &musePort); - snd_seq_port_subscribe_set_dest(subs, &adr); - - // Already subscribed? Then unsubscribe. - if(!snd_seq_get_port_subscription(alsaSeq, subs)) - { - if(!snd_seq_unsubscribe_port(alsaSeq, subs)) - _writeEnable = false; - else - printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for writing\n"); - } - else - _writeEnable = false; - } - - //if (_openFlags & 2) { - //if (!(_openFlags & 2)) - { - snd_seq_port_subscribe_set_dest(subs, &musePort); - snd_seq_port_subscribe_set_sender(subs, &adr); - - // Already subscribed? Then unsubscribe. - if(!snd_seq_get_port_subscription(alsaSeq, subs)) - { - if(!snd_seq_unsubscribe_port(alsaSeq, subs)) - _readEnable = false; - else - printf("MidiAlsaDevice::close Error unsubscribing alsa midi port for reading\n"); - } - else - _readEnable = false; - } -} - -//--------------------------------------------------------- -// writeRouting -//--------------------------------------------------------- - -void MidiAlsaDevice::writeRouting(int level, Xml& xml) const -{ - // p3.3.45 - // If this device is not actually in use by the song, do not write any routes. - // This prevents bogus routes from being saved and propagated in the med file. - if(midiPort() == -1) - return; - - QString s; - /* - //if(rwFlags() & 2) // Readable - { - //RouteList* rl = _inRoutes; - //for (ciRoute r = rl->begin(); r != rl->end(); ++r) - for (ciRoute r = _inRoutes.begin(); r != _inRoutes.end(); ++r) - { - // Since an ALSA midi device supports read + write, this is the only way we can tell if this route is using the device as input. - if(r->type == Route::TRACK_ROUTE) - continue; - - if(!r->name().isEmpty()) - { - xml.tag(level++, "Route"); - - //xml.strTag(level, "srcNode", r->name()); - xml.tag(level, "source type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); - - //xml.strTag(level, "dstNode", name()); - xml.tag(level, "dest type=\"%d\" name=\"%s\"/", Route::ALSA_MIDI_ROUTE, name().toLatin1().constData()); - - xml.etag(level--, "Route"); - } - } - } - */ - - for (ciRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) - { - //if(r->type != Route::TRACK_ROUTE) - //{ - // printf("MidiAlsaDevice::writeRouting Warning out route is not TRACK_ROUTE type\n"); - // continue; - //} - - if(!r->name().isEmpty()) - { - //xml.tag(level++, "Route"); - - s = QT_TRANSLATE_NOOP("@default", "Route"); - if(r->channel != -1) - s += QString(QT_TRANSLATE_NOOP("@default", " channel=\"%1\"")).arg(r->channel); - xml.tag(level++, s.toLatin1().constData()); - - /* - //xml.strTag(level, "srcNode", name()); - if(r->channel != -1) - //xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::ALSA_MIDI_ROUTE, r->channel, name().toLatin1().constData()); - //xml.tag(level, "source type=\"%d\" channel=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, r->channel, name().toLatin1().constData()); - xml.tag(level, "source devtype=\"%d\" channel=\"%d\" name=\"%s\"/", MidiDevice::ALSA_MIDI, r->channel, name().toLatin1().constData()); - else - //xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::ALSA_MIDI_ROUTE, name().toLatin1().constData()); - //xml.tag(level, "source type=\"%d\" name=\"%s\"/", Route::MIDI_DEVICE_ROUTE, name().toLatin1().constData()); - */ - //xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::ALSA_MIDI, name().toLatin1().constData()); - xml.tag(level, "source devtype=\"%d\" name=\"%s\"/", MidiDevice::ALSA_MIDI, Xml::xmlString(name()).toLatin1().constData()); - - /* - //xml.strTag(level, "dstNode", r->name()); - if(r->channel != -1) - { - if(r->type == Route::MIDI_DEVICE_ROUTE) - xml.tag(level, "dest devtype=\"%d\" channel=\"%d\" name=\"%s\"/", r->device->deviceType(), r->channel, r->name().toLatin1().constData()); - else - xml.tag(level, "dest type=\"%d\" channel=\"%d\" name=\"%s\"/", r->type, r->channel, r->name().toLatin1().constData()); - } - else - { - if(r->type == Route::MIDI_DEVICE_ROUTE) - xml.tag(level, "dest devtype=\"%d\" name=\"%s\"/", r->device->deviceType(), r->name().toLatin1().constData()); - else - xml.tag(level, "dest type=\"%d\" name=\"%s\"/", r->type, r->name().toLatin1().constData()); - } - */ - - s = QT_TRANSLATE_NOOP("@default", "dest"); - if(r->type == Route::MIDI_DEVICE_ROUTE) - s += QString(QT_TRANSLATE_NOOP("@default", " devtype=\"%1\"")).arg(r->device->deviceType()); - else - if(r->type != Route::TRACK_ROUTE) - s += QString(QT_TRANSLATE_NOOP("@default", " type=\"%1\"")).arg(r->type); - //s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(r->name()); - s += QString(QT_TRANSLATE_NOOP("@default", " name=\"%1\"/")).arg(Xml::xmlString(r->name())); - xml.tag(level, s.toLatin1().constData()); - - xml.etag(level--, "Route"); - } - } -} - -//--------------------------------------------------------- -// putEvent -//--------------------------------------------------------- - -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 = musePort; - 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(); - // p3.3.37 - //if (a < 0x1000) { // 7 Bit Controller - if (a < CTRL_14_OFFSET) { // 7 Bit Controller - snd_seq_ev_set_controller(&event, chn, a, b); - } - //else if (a < 0x20000) { // 14 bit high resolution controller - 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 < 0x30000) { // RPN 7-Bit Controller - 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; - } - //else if (a < 0x40000) { // NRPN 7-Bit Controller - else if (a < CTRL_INTERNAL_OFFSET) { // NRPN 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_NONREGPARAM; - } - //else if (a < 0x60000) { // RPN14 Controller - else if (a < CTRL_NRPN14_OFFSET) { // RPN14 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_REGPARAM; - } - //else if (a < 0x70000) { // NRPN14 Controller - else if (a < CTRL_NONE_OFFSET) { // NRPN14 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_NONREGPARAM; - } - else { - printf("putEvent: unknown controller type 0x%x\n", a); - } - } -#endif - break; - case ME_PITCHBEND: - snd_seq_ev_set_pitchbend(&event, chn, a); - break; - case ME_POLYAFTER: - // chnEvent2(chn, 0xa0, a, b); - break; - case ME_AFTERTOUCH: - snd_seq_ev_set_chanpress(&event, chn, a); - break; - case ME_SYSEX: - { - const unsigned char* p = e.data(); - int n = e.len(); - int len = n + sizeof(event) + 2; - char buf[len]; - event.type = SND_SEQ_EVENT_SYSEX; - event.flags = SND_SEQ_EVENT_LENGTH_VARIABLE; - event.data.ext.len = n + 2; - event.data.ext.ptr = (void*)(buf + sizeof(event)); - memcpy(buf, &event, sizeof(event)); - char* pp = buf + sizeof(event); - *pp++ = 0xf0; - memcpy(pp, p, n); - pp += n; - *pp = 0xf7; - return putEvent(&event); - } - case ME_SONGPOS: - event.data.control.value = a; - event.type = SND_SEQ_EVENT_SONGPOS; - break; - case ME_CLOCK: - event.type = SND_SEQ_EVENT_CLOCK; - break; - case ME_START: - event.type = SND_SEQ_EVENT_START; - break; - case ME_CONTINUE: - event.type = SND_SEQ_EVENT_CONTINUE; - break; - case ME_STOP: - event.type = SND_SEQ_EVENT_STOP; - break; - default: - printf("MidiAlsaDevice::putEvent(): event type %d not implemented\n", - e.type()); - return true; - } - return putEvent(&event); - } - -//--------------------------------------------------------- -// putEvent -// return false if event is delivered -//--------------------------------------------------------- - -bool MidiAlsaDevice::putEvent(snd_seq_event_t* event) - { - int error; - - do { - error = snd_seq_event_output_direct(alsaSeq, event); - int len = snd_seq_event_length(event); - if (error == len) { -// printf(".");fflush(stdout); - return false; - } - if (error < 0) { - if (error == -12) { -// printf("?");fflush(stdout); - return true; - } - else { - fprintf(stderr, "MidiAlsaDevice::%p putEvent(): midi write error: %s\n", - this, snd_strerror(error)); - fprintf(stderr, " dst %d:%d\n", adr.client, adr.port); - //exit(-1); - } - } - else - fprintf(stderr, "MidiAlsaDevice::putEvent(): midi write returns %d, expected %d: %s\n", - error, len, snd_strerror(error)); - } while (error == -12); - return true; - } - -//--------------------------------------------------------- -// initMidiAlsa -// return true on error -//--------------------------------------------------------- - -bool initMidiAlsa() - { - if (debugMsg) - printf("initMidiAlsa\n"); - int error = snd_seq_open(&alsaSeq, "hw", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); - if (error < 0) { - fprintf(stderr, "Could not open ALSA sequencer: %s\n", - snd_strerror(error)); - return true; - } - const int inCap = SND_SEQ_PORT_CAP_SUBS_READ; - const int outCap = SND_SEQ_PORT_CAP_SUBS_WRITE; - - snd_seq_client_info_t *cinfo; - snd_seq_client_info_alloca(&cinfo); - snd_seq_client_info_set_client(cinfo, -1); - - while (snd_seq_query_next_client(alsaSeq, cinfo) >= 0) { - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca(&pinfo); - snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo)); - snd_seq_port_info_set_port(pinfo, -1); - - while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) { - unsigned int capability = snd_seq_port_info_get_capability(pinfo); - if ((capability & outCap) == 0) { - const char *name = snd_seq_port_info_get_name(pinfo); - if (strcmp("Timer", name) == 0 || - strcmp("Announce", name) == 0 || - strcmp("Receiver", name) == 0) - continue; - } - snd_seq_addr_t adr = *snd_seq_port_info_get_addr(pinfo); - MidiAlsaDevice* dev = new MidiAlsaDevice(adr, QString(snd_seq_port_info_get_name(pinfo))); - int flags = 0; - if (capability & outCap) - flags |= 1; - if (capability & inCap) - flags |= 2; - dev->setrwFlags(flags); - if (debugMsg) - printf("ALSA port add: <%s>, %d:%d flags %d 0x%0x\n", - snd_seq_port_info_get_name(pinfo), - adr.client, adr.port, - flags, capability); - midiDevices.add(dev); - - /* - // Experimental... Need to list 'sensible' devices first and ignore unwanted ones... - // Add instance last in midi device list. - for(int i = 0; i < MIDI_PORTS; ++i) - { - MidiPort* mp = &midiPorts[i]; - if(mp->device() == 0) - { - // midiSeq might not be initialzed yet! - //midiSeq->msgSetMidiDevice(mp, dev); - mp->setMidiDevice(dev); - - //muse->changeConfig(true); // save configuration file - //update(); - break; - } - } - */ - - } - } - - // p3.3.38 - //snd_seq_set_client_name(alsaSeq, "MusE Sequencer"); - snd_seq_set_client_name(alsaSeq, audioDevice->clientName()); - - int ci = snd_seq_poll_descriptors_count(alsaSeq, POLLIN); - int co = snd_seq_poll_descriptors_count(alsaSeq, POLLOUT); - - if (ci > 1 || co > 1) { - printf("ALSA midi: cannot handle more than one poll fd\n"); - abort(); - } - - struct pollfd pfdi[ci]; - struct pollfd pfdo[co]; - snd_seq_poll_descriptors(alsaSeq, pfdi, ci, POLLIN); - snd_seq_poll_descriptors(alsaSeq, pfdo, co, POLLOUT); - alsaSeqFdo = pfdo[0].fd; - alsaSeqFdi = pfdi[0].fd; - - int port = snd_seq_create_simple_port(alsaSeq, "MusE Port 0", - inCap | outCap | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_WRITE, - SND_SEQ_PORT_TYPE_APPLICATION); - if (port < 0) { - perror("create port"); - exit(1); - } - musePort.port = port; - musePort.client = snd_seq_client_id(alsaSeq); - - //----------------------------------------- - // subscribe to "Announce" - // this enables callbacks for any - // alsa port changes - //----------------------------------------- - - snd_seq_addr_t aadr; - aadr.client = SND_SEQ_CLIENT_SYSTEM; - aadr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; - - snd_seq_port_subscribe_t* subs; - snd_seq_port_subscribe_alloca(&subs); - snd_seq_port_subscribe_set_dest(subs, &musePort); - snd_seq_port_subscribe_set_sender(subs, &aadr); - error = snd_seq_subscribe_port(alsaSeq, subs); - if (error < 0) { - printf("Alsa: Subscribe System failed: %s", snd_strerror(error)); - return true; - } - return false; - } - -struct AlsaPort { - snd_seq_addr_t adr; - char* name; - int flags; - AlsaPort(snd_seq_addr_t a, const char* s, int f) { - adr = a; - name = strdup(s); - flags = f; - } - }; - -static std::list<AlsaPort> portList; - -//--------------------------------------------------------- -// alsaScanMidiPorts -//--------------------------------------------------------- - -void alsaScanMidiPorts() - { -// printf("alsa scan midi ports\n"); - const int inCap = SND_SEQ_PORT_CAP_SUBS_READ; - const int outCap = SND_SEQ_PORT_CAP_SUBS_WRITE; - - portList.clear(); - - snd_seq_client_info_t* cinfo; - snd_seq_client_info_alloca(&cinfo); - snd_seq_client_info_set_client(cinfo, 0); - - while (snd_seq_query_next_client(alsaSeq, cinfo) >= 0) { - snd_seq_port_info_t *pinfo; - snd_seq_port_info_alloca(&pinfo); - snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo)); - snd_seq_port_info_set_port(pinfo, -1); - while (snd_seq_query_next_port(alsaSeq, pinfo) >= 0) { - unsigned int capability = snd_seq_port_info_get_capability(pinfo); - if (((capability & outCap) == 0) - && ((capability & inCap) == 0)) - continue; - snd_seq_addr_t adr; - const char* name; - adr = *snd_seq_port_info_get_addr(pinfo); - name = snd_seq_port_info_get_name(pinfo); - if (adr.client == musePort.client && adr.port == musePort.port) - continue; - int flags = 0; - if (capability & outCap) - flags |= 1; - if (capability & inCap) - flags |= 2; -// printf("ALSA port add: <%s>, flags %d\n", name, flags); - portList.push_back(AlsaPort(adr, name, flags)); - } - } - // - // check for devices to delete - // - for (iMidiDevice i = midiDevices.begin(); i != midiDevices.end();) { - MidiAlsaDevice* d = dynamic_cast<MidiAlsaDevice*>(*i); - if (d == 0) { - ++i; - continue; - } - std::list<AlsaPort>::iterator k = portList.begin(); - for (; k != portList.end(); ++k) { - if (k->adr.client == d->adr.client - && k->adr.port == d->adr.port) { - break; - } - } - if (k == portList.end()) { - if (d->midiPort() != -1) - midiPorts[d->midiPort()].setMidiDevice(0); - iMidiDevice k = i; -// printf("erase device\n"); - ++i; - midiDevices.erase(k); - } - else { - ++i; - } - } - // - // check for devices to add - // - for (std::list<AlsaPort>::iterator k = portList.begin(); k != portList.end(); ++k) { - iMidiDevice i = midiDevices.begin(); -// printf("ALSA port: <%s>\n", k->name); - for (;i != midiDevices.end(); ++i) { - MidiAlsaDevice* d = dynamic_cast<MidiAlsaDevice*>(*i); - if (d == 0) - continue; - if ((k->adr.client == d->adr.client) && (k->adr.port == d->adr.port)) { - break; - } - } - if (i == midiDevices.end()) { - // add device - MidiAlsaDevice* dev = new MidiAlsaDevice(k->adr, - QString(k->name)); - dev->setrwFlags(k->flags); - midiDevices.add(dev); -// printf("add device\n"); - } - } - } - -//--------------------------------------------------------- -// alsaSelectRfd -//--------------------------------------------------------- - -int alsaSelectRfd() - { - return alsaSeqFdi; - } - -//--------------------------------------------------------- -// alsaSelectWfd -//--------------------------------------------------------- - -int alsaSelectWfd() - { - return alsaSeqFdo; - } - -//--------------------------------------------------------- -// processInput -//--------------------------------------------------------- - -void alsaProcessMidiInput() -{ - MidiRecordEvent event; - snd_seq_event_t* ev; - - for (;;) - { - int rv = snd_seq_event_input(alsaSeq, &ev); -// printf("AlsaInput %d\n", rv); - if (rv < 0) { -// printf("AlsaMidi: read error %s\n", snd_strerror(rv)); - return; - } - switch(ev->type) { - case SND_SEQ_EVENT_PORT_SUBSCRIBED: - case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: - return; - case SND_SEQ_EVENT_CLIENT_START: - case SND_SEQ_EVENT_CLIENT_EXIT: - // return; - // on first start of a software synthesizer we only - // get CLIENT_START event and no PORT_START, why? - - case SND_SEQ_EVENT_PORT_START: - case SND_SEQ_EVENT_PORT_EXIT: - alsaScanMidiPorts(); - audio->midiPortsChanged(); // signal gui - snd_seq_free_event(ev); - return; - } - - int curPort = -1; - MidiAlsaDevice* mdev = 0; - // - // find real source device - // - for (iMidiDevice i = midiDevices.begin(); i != midiDevices.end(); ++i) { - MidiAlsaDevice* d = dynamic_cast<MidiAlsaDevice*>(*i); - if (d && d->adr.client == ev->source.client - && d->adr.port == ev->source.port) { - curPort = d->midiPort(); - mdev = d; - } - } - - if (mdev == 0 || curPort == -1) { - if (debugMsg) { - fprintf(stderr, "no port %d:%d found for received alsa event\n", - ev->source.client, ev->source.port); - } - snd_seq_free_event(ev); - return; - } - - /* - if(curPort == -1) - { - if(mdev == 0) - { - if (debugMsg) - { - fprintf(stderr, "no port %d:%d found for received alsa event\n", - ev->source.client, ev->source.port); - } - } - else - { - // Allow the sync detect mechanisms to work, even if device is not assigned to a port. - if(ev->type == SND_SEQ_EVENT_CLOCK) - mdev->syncInfo().trigMCSyncDetect(); - else - if(ev->type == SND_SEQ_EVENT_TICK) - mdev->syncInfo().trigTickDetect(); - } - snd_seq_free_event(ev); - return; - } - */ - - event.setType(0); // mark as unused - event.setPort(curPort); - event.setB(0); - - switch(ev->type) - { - case SND_SEQ_EVENT_NOTEON: - case SND_SEQ_EVENT_KEYPRESS: - event.setChannel(ev->data.note.channel); - event.setType(ME_NOTEON); - event.setA(ev->data.note.note); - event.setB(ev->data.note.velocity); - break; - - case SND_SEQ_EVENT_NOTEOFF: - event.setChannel(ev->data.note.channel); - event.setType(ME_NOTEOFF); - event.setA(ev->data.note.note); - event.setB(ev->data.note.velocity); - break; - - case SND_SEQ_EVENT_CHANPRESS: - event.setChannel(ev->data.control.channel); - event.setType(ME_AFTERTOUCH); - event.setA(ev->data.control.value); - break; - - case SND_SEQ_EVENT_PGMCHANGE: - event.setChannel(ev->data.control.channel); - event.setType(ME_PROGRAM); - event.setA(ev->data.control.value); - break; - - case SND_SEQ_EVENT_PITCHBEND: - event.setChannel(ev->data.control.channel); - event.setType(ME_PITCHBEND); - event.setA(ev->data.control.value); - break; - - case SND_SEQ_EVENT_CONTROLLER: - event.setChannel(ev->data.control.channel); - event.setType(ME_CONTROLLER); - event.setA(ev->data.control.param); - event.setB(ev->data.control.value); - break; - - case SND_SEQ_EVENT_CLOCK: - midiSeq->realtimeSystemInput(curPort, ME_CLOCK); - //mdev->syncInfo().trigMCSyncDetect(); - break; - - case SND_SEQ_EVENT_START: - midiSeq->realtimeSystemInput(curPort, ME_START); - break; - - case SND_SEQ_EVENT_CONTINUE: - midiSeq->realtimeSystemInput(curPort, ME_CONTINUE); - break; - - case SND_SEQ_EVENT_STOP: - midiSeq->realtimeSystemInput(curPort, ME_STOP); - break; - - case SND_SEQ_EVENT_TICK: - midiSeq->realtimeSystemInput(curPort, ME_TICK); - //mdev->syncInfo().trigTickDetect(); - break; - - case SND_SEQ_EVENT_SYSEX: - - // TODO: Deal with large sysex, which are broken up into chunks! - // For now, do not accept if the first byte is not SYSEX or the last byte is not EOX, - // meaning it's a chunk, possibly with more chunks to follow. - if((*((unsigned char*)ev->data.ext.ptr) != ME_SYSEX) || - (*(((unsigned char*)ev->data.ext.ptr) + ev->data.ext.len - 1) != ME_SYSEX_END)) - { - printf("MusE: alsaProcessMidiInput sysex chunks not supported!\n"); - break; - } - - event.setTime(0); // mark as used - event.setType(ME_SYSEX); - event.setData((unsigned char*)(ev->data.ext.ptr)+1, - ev->data.ext.len-2); - break; - case SND_SEQ_EVENT_PORT_SUBSCRIBED: - case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: // write port is released - break; - case SND_SEQ_EVENT_SONGPOS: - midiSeq->setSongPosition(curPort, ev->data.control.value); - break; - case SND_SEQ_EVENT_SENSING: - break; - case SND_SEQ_EVENT_QFRAME: - midiSeq->mtcInputQuarter(curPort, ev->data.control.value); - break; - // case SND_SEQ_EVENT_CLIENT_START: - // case SND_SEQ_EVENT_CLIENT_EXIT: - // case SND_SEQ_EVENT_CLIENT_CHANGE: - // case SND_SEQ_EVENT_PORT_CHANGE: - // case SND_SEQ_EVENT_SONGSEL: - // case SND_SEQ_EVENT_TIMESIGN: - // case SND_SEQ_EVENT_KEYSIGN: - // case SND_SEQ_EVENT_SETPOS_TICK: - // case SND_SEQ_EVENT_SETPOS_TIME: - // case SND_SEQ_EVENT_TEMPO: - // case SND_SEQ_EVENT_TUNE_REQUEST: - // case SND_SEQ_EVENT_RESET: - - // case SND_SEQ_EVENT_NOTE: - // case SND_SEQ_EVENT_CONTROL14: - // case SND_SEQ_EVENT_NONREGPARAM: - // case SND_SEQ_EVENT_REGPARAM: - default: - printf("ALSA Midi input: type %d not handled\n", ev->type); - break; - } - if(event.type()) - { - mdev->recordEvent(event); - // p3.3.26 1/23/10 Moved to MidiDevice now. Anticipating Jack midi support, so don't make it ALSA specific. Tim. - //if(ev->type != SND_SEQ_EVENT_SYSEX) - // Trigger general activity indicator detector. Sysex has no channel, don't trigger. - // midiPorts[curPort].syncInfo().trigActDetect(event.channel()); - } - - snd_seq_free_event(ev); - if (rv == 0) - break; - } -} - |