void MidiJackDevice::recordEvent(MidiRecordEvent& event)/*{{{*/ { if (audio->isPlaying()) event.setLoopNum(audio->loopCount()); if (midiInputTrace) { printf("Jack MidiInput: "); event.dump(); } int typ = event.type(); if (_port != -1) { //call our midimonitor with the data, it can then decide what to do monitorEvent(event); } // // process midi event input filtering and // transformation // processMidiInputTransformPlugins(event); if (filterEvent(event, midiRecordType, false)) return; if (!applyMidiInputTransformation(event)) { if (midiInputTrace) printf(" midi input transformation: event filtered\n"); return; } // // transfer noteOn events to gui for step recording and keyboard // remote control // if (typ == ME_NOTEON) { int pv = ((event.dataA() & 0xff) << 8) + (event.dataB() & 0xff); song->putEvent(pv); } //This was not sending noteoff events at all sometimes causing strange endless note in step rec else if(typ == ME_NOTEOFF) { int pv = ((event.dataA() & 0xff) << 8) + (0x00); song->putEvent(pv); } // Do not bother recording if it is NOT actually being used by a port. // Because from this point on, process handles things, by selected port. if (_port == -1) return; // Split the events up into channel fifos. Special 'channel' number 17 for sysex events. unsigned int ch = (typ == ME_SYSEX) ? kMaxMidiChannels : event.channel(); if (_recordFifo[ch].put(MidiPlayEvent(event))) printf("MidiJackDevice::recordEvent: fifo channel %d overflow\n", ch); }/*}}}*/
void MidiJackDevice::eventReceived(jack_midi_event_t* ev)/*{{{*/ { MidiRecordEvent event; event.setB(0); // NOTE: From LOS-2. Not done here in LOS-1 (yet). // move all events 2*segmentSize into the future to get // jitterfree playback // // cycle n-1 n n+1 // -+----------+----------+----------+- // ^ ^ ^ // catch process play // // const SeqTime* st = audio->seqTime(); unsigned pos = audio->pos().frame(); event.setTime(pos + ev->time); event.setChannel(*(ev->buffer) & 0xf); int type = *(ev->buffer) & 0xf0; int a = *(ev->buffer + 1) & 0x7f; int b = *(ev->buffer + 2) & 0x7f; event.setType(type); switch (type) { case ME_NOTEON: case ME_NOTEOFF: case ME_CONTROLLER: event.setA(*(ev->buffer + 1)); event.setB(*(ev->buffer + 2)); break; case ME_PROGRAM: case ME_AFTERTOUCH: event.setA(*(ev->buffer + 1)); break; case ME_PITCHBEND: event.setA(((b << 7) + a) - 8192); break; case ME_SYSEX: { int type = *(ev->buffer) & 0xff; switch (type) { case ME_SYSEX: // TODO: Deal with large sysex, which are broken up into chunks! // For now, do not accept if the last byte is not EOX, meaning it's a chunk with more chunks to follow. if (*(((unsigned char*) ev->buffer) + ev->size - 1) != ME_SYSEX_END) { printf("MidiJackDevice::eventReceived sysex chunks not supported!\n"); return; } //event.setTime(0); // mark as used event.setType(ME_SYSEX); event.setData((unsigned char*) (ev->buffer + 1), ev->size - 2); break; case ME_MTC_QUARTER: case ME_SONGPOS: case ME_CLOCK: case ME_TICK: case ME_START: case ME_CONTINUE: case ME_STOP: return; default: printf("MidiJackDevice::eventReceived unsupported system event 0x%02x\n", type); return; } } break; default: printf("MidiJackDevice::eventReceived unknown event 0x%02x\n", type); //printf("MidiJackDevice::eventReceived unknown event 0x%02x size:%d buf:0x%02x 0x%02x 0x%02x ...0x%02x\n", type, ev->size, *(ev->buffer), *(ev->buffer + 1), *(ev->buffer + 2), *(ev->buffer + (ev->size - 1))); return; } if (midiInputTrace) { printf("MidiInput<%s>: ", name().toLatin1().constData()); event.dump(); } #ifdef JACK_MIDI_DEBUG printf("MidiJackDevice::eventReceived time:%d type:%d ch:%d A:%d B:%d\n", event.time(), event.type(), event.channel(), event.dataA(), event.dataB()); #endif // Let recordEvent handle it from here, with timestamps, filtering, gui triggering etc. recordEvent(event); }/*}}}*/
void MidiDevice::recordEvent(MidiRecordEvent& event) { if(MusEGlobal::audio->isPlaying()) event.setLoopNum(MusEGlobal::audio->loopCount()); if (MusEGlobal::midiInputTrace) { fprintf(stderr, "MidiInput: "); dumpMPEvent(&event); } int typ = event.type(); if(_port != -1) { int idin = MusEGlobal::midiPorts[_port].syncInfo().idIn(); //--------------------------------------------------- // filter some SYSEX events //--------------------------------------------------- if (typ == ME_SYSEX) { const unsigned char* p = event.data(); int n = event.len(); if (n >= 4) { if ((p[0] == 0x7f) && ((p[1] == 0x7f) || (idin == 0x7f) || (p[1] == idin))) { if (p[2] == 0x06) { MusEGlobal::midiSyncContainer.mmcInput(_port, p, n); return; } if (p[2] == 0x01) { MusEGlobal::midiSyncContainer.mtcInputFull(_port, p, n); return; } } else if (p[0] == 0x7e) { MusEGlobal::midiSyncContainer.nonRealtimeSystemSysex(_port, p, n); return; } } } else // Trigger general activity indicator detector. Sysex has no channel, don't trigger. MusEGlobal::midiPorts[_port].syncInfo().trigActDetect(event.channel()); } // // process midi event input filtering and // transformation // processMidiInputTransformPlugins(event); if (filterEvent(event, MusEGlobal::midiRecordType, false)) return; if (!applyMidiInputTransformation(event)) { if (MusEGlobal::midiInputTrace) fprintf(stderr, " midi input transformation: event filtered\n"); return; } // // transfer noteOn and Off events to gui for step recording and keyboard // remote control (changed by flo93: added noteOff-events) // if (typ == ME_NOTEON) { int pv = ((event.dataA() & 0xff)<<8) + (event.dataB() & 0xff); MusEGlobal::song->putEvent(pv); } else if (typ == ME_NOTEOFF) { int pv = ((event.dataA() & 0xff)<<8) + (0x00); //send an event with velo=0 MusEGlobal::song->putEvent(pv); } // Do not bother recording if it is NOT actually being used by a port. // Because from this point on, process handles things, by selected port. if(_port == -1) return; // Split the events up into channel fifos. Special 'channel' number 17 for sysex events. unsigned int ch = (typ == ME_SYSEX)? MusECore::MUSE_MIDI_CHANNELS : event.channel(); if(_recordFifo[ch].put(event)) fprintf(stderr, "MidiDevice::recordEvent: fifo channel %d overflow\n", ch); }