/* * the somethingStupid parameter can be set to simulate a program crash. * We want PortMidi to close Midi ports automatically in the event of a * crash because Windows does not (and this may cause an OS crash) */ void main_test_input(unsigned int somethingStupid) { PmStream * midi; PmError status, length; PmEvent buffer[1]; int num = 10; int i = get_number("Type input number: "); /* It is recommended to start timer before Midi; otherwise, PortMidi may start the timer with its (default) parameters */ TIME_START; /* open input device */ Pm_OpenInput(&midi, i, DRIVER_INFO, INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO); printf("Midi Input opened. Reading %d Midi messages...\n", num); Pm_SetFilter(midi, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX); /* empty the buffer after setting filter, just in case anything got through */ while (Pm_Poll(midi)) { Pm_Read(midi, buffer, 1); } /* now start paying attention to messages */ i = 0; /* count messages as they arrive */ while (i < num) { status = Pm_Poll(midi); if (status == TRUE) { length = Pm_Read(midi,buffer, 1); if (length > 0) { printf("Got message %d: time %ld, %2lx %2lx %2lx\n", i, (long) buffer[0].timestamp, (long) Pm_MessageStatus(buffer[0].message), (long) Pm_MessageData1(buffer[0].message), (long) Pm_MessageData2(buffer[0].message)); i++; } else { assert(0); } } /* simulate crash if somethingStupid is 1 or 2 */ if ((i > (num/2)) && (somethingStupid == 1)) { doSomethingStupid(); } else if ((i > (num/2)) && (somethingStupid == 2)) { doSomethingReallyStupid(); } } /* close device (this not explicitly needed in most implementations) */ printf("ready to close..."); Pm_Close(midi); printf("done closing..."); }
bool inputAvailable() { if(Pm_Poll(in) == 1 || nbEventWaiting > 0) return true; else if(Pm_Poll(in) == 0) return false; //else // printf("Error while reading midi input.\r\n"); return false; }
void QMidiSequencer::run() { while(true) { if (Pm_Poll(m_midi) == TRUE) { int size = Pm_Read(m_midi,m_buffer, 256); for(int i=0; i<size; i++) { int type = Pm_MessageStatus(m_buffer[i].message); int chan = Pm_MessageData1(m_buffer[i].message); int value = Pm_MessageData2(m_buffer[i].message); //std::cout << "midi : " << QString::number(type).toStdString() << " | " << QString::number(chan).toStdString() << " | " << QString::number(value).toStdString() << std::endl; /*qDebug(QString::number(type).toStdString().c_str()); qDebug(QString::number(chan).toStdString().c_str()); qDebug(QString::number(value).toStdString().c_str()); qDebug("\n");*/ if( chan == 74 || chan == 10 || chan == 7 ) emit controllerValueChanged(type*chan,value); else if( (chan == 72 || chan == 73) ) emit noteOn(type,type+chan,value); /*else if( type == 144 && value == 0 ) emit noteOff(type, chan);*/ } } this->msleep(10); } }
void process_midi(PtTimestamp timestamp, void *userData) { PmError result; PmEvent buffer; /* just one message at a time */ int i, status, data1, data2; PyObject *tup = NULL; MidiListener *server = (MidiListener *)userData; if (server->active == 0) return; PyGILState_STATE s = PyGILState_Ensure(); do { for (i=0; i<server->midicount; i++) { result = Pm_Poll(server->midiin[i]); if (result) { if (Pm_Read(server->midiin[i], &buffer, 1) == pmBufferOverflow) continue; status = Pm_MessageStatus(buffer.message); data1 = Pm_MessageData1(buffer.message); data2 = Pm_MessageData2(buffer.message); tup = PyTuple_New(3); PyTuple_SetItem(tup, 0, PyInt_FromLong(status)); PyTuple_SetItem(tup, 1, PyInt_FromLong(data1)); PyTuple_SetItem(tup, 2, PyInt_FromLong(data2)); PyObject_Call((PyObject *)server->midicallable, tup, NULL); } } } while (result); PyGILState_Release(s); Py_XDECREF(tup); }
void PortMidiDriver::read() { if (!inputStream) return; PmEvent buffer[1]; while (Pm_Poll(inputStream)) { int n = Pm_Read(inputStream, buffer, 1); if (n > 0) { int status = Pm_MessageStatus(buffer[0].message); int type = status & 0xF0; int channel = status & 0x0F; if (type == ME_NOTEON) { int pitch = Pm_MessageData1(buffer[0].message); int velo = Pm_MessageData2(buffer[0].message); mscore->midiNoteReceived(channel, pitch, velo); } else if (type == ME_NOTEOFF) { int pitch = Pm_MessageData1(buffer[0].message); (void)Pm_MessageData2(buffer[0].message); // read but ignore mscore->midiNoteReceived(channel, pitch, 0); } else if (type == ME_CONTROLLER) { int param = Pm_MessageData1(buffer[0].message); int value = Pm_MessageData2(buffer[0].message); mscore->midiCtrlReceived(param, value); } } } }
void* MIDIInputPoll(MIDIInput* self) { PmEvent buffer[64]; int result; while (self->mRunning) { if (Pm_Poll(self->mStream)) { result = Pm_Read(self->mStream, buffer, 64); // result is an error number if (result < 0) { TTLogError("MidiPoll error\n"); } // result is the number of midi events else { MIDIParserFrom parser; for (TTInt32 i = 0; i < result; i++) { // if the parsing is done : pass address and value if (parser.parse(Pm_MessageStatus(buffer[i].message), Pm_MessageData1(buffer[i].message), Pm_MessageData2(buffer[i].message))) self->mProtocol->receivedMessage(self->mApplication, parser.address, parser.value); } } } self->mPollingThread->sleep(1); } return NULL; }
/* * Method: Pm_Poll */ JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Poll (JNIEnv *env, jclass cl, jobject jstream) { CLASS(c, jstream); ADDRESS_FID(fid, c); return Pm_Poll(PMSTREAM(jstream, fid)); }
bool PortMidiDriver::init() { inputId = getDeviceIn(preferences.getString(PREF_IO_PORTMIDI_INPUTDEVICE)); if (inputId == -1) inputId = Pm_GetDefaultInputDeviceID(); if (inputId == pmNoDevice) return false; outputId = getDeviceOut(preferences.getString(PREF_IO_PORTMIDI_OUTPUTDEVICE)); // Note: allow init even if outputId == pmNoDevice, since input is more important than output. static const int DRIVER_INFO = 0; static const int TIME_INFO = 0; Pt_Start(20, 0, 0); // timer started, 20 millisecond accuracy PmError error = Pm_OpenInput(&inputStream, inputId, (void*)DRIVER_INFO, preferences.getInt(PREF_IO_PORTMIDI_INPUTBUFFERCOUNT), ((PmTimeProcPtr) Pt_Time), (void*)TIME_INFO); if (error != pmNoError) { const char* p = Pm_GetErrorText(error); qDebug("PortMidi: open input (id=%d) failed: %s", int(inputId), p); Pt_Stop(); return false; } Pm_SetFilter(inputStream, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX); PmEvent buffer[1]; while (Pm_Poll(inputStream)) Pm_Read(inputStream, buffer, 1); if (outputId != pmNoDevice) { error = Pm_OpenOutput(&outputStream, outputId, (void*)DRIVER_INFO, preferences.getInt(PREF_IO_PORTMIDI_OUTPUTBUFFERCOUNT), ((PmTimeProcPtr) Pt_Time), (void*)TIME_INFO, preferences.getInt(PREF_IO_PORTMIDI_OUTPUTLATENCYMILLISECONDS)); if (error != pmNoError) { const char* p = Pm_GetErrorText(error); qDebug("PortMidi: open output (id=%d) failed: %s", int(outputId), p); Pt_Stop(); return false; } } timer = new QTimer(); timer->setInterval(20); // 20 msec timer->start(); timer->connect(timer, SIGNAL(timeout()), seq, SLOT(midiInputReady())); return true; }
bool osd_poll_midi_channel(osd_midi_device *dev) { #ifndef DISABLE_MIDI PmError chk = Pm_Poll(dev->pmStream); return (chk == pmGotData) ? true : false; #else return false; #endif }
/* callback function for PortTime -- computes histogram */ void pt_callback(PtTimestamp timestamp, void *userData) { PtTimestamp difference = timestamp - previous_callback_time - period; previous_callback_time = timestamp; /* allow 5 seconds for the system to settle down */ if (timestamp < 5000) return; iteration++; /* send a note on/off if user requested it */ if (test_out && (iteration % output_period == 0)) { PmEvent buffer[1]; buffer[0].timestamp = Pt_Time(NULL); if (note_on) { /* note off */ buffer[0].message = Pm_Message(0x90, 60, 0); note_on = 0; } else { /* note on */ buffer[0].message = Pm_Message(0x90, 60, 100); note_on = 1; } Pm_Write(out, buffer, 1); iteration = 0; } /* read all waiting events (if user requested) */ if (test_in) { PmError status; PmEvent buffer[1]; do { status = Pm_Poll(in); if (status == TRUE) { Pm_Read(in,buffer,1); } } while (status == TRUE); } if (difference < 0) return; /* ignore when system is "catching up" */ /* update the histogram */ if (difference < HIST_LEN) { histogram[difference]++; } else { out_of_range++; } if (max_latency < difference) max_latency = difference; }
void receive_poll(PtTimestamp ts, void *userData) { int count, command; PmEvent event; if (inStream==NULL) return; if (Pm_Poll(inStream)!=TRUE) return; while ((count = Pm_Read(inStream, &event, 1))) { if (count == 1) { /* there seems to be a constant stream of MIDI events, not all of which are interesting */ /* the status has the command in the highest 4 bits and the channel in the lowest 4 bits */ command = Pm_MessageStatus(event.message) & MIDI_CODE_MASK; if ((command == MIDI_ON_NOTE) || (command == MIDI_OFF_NOTE ) || (command == MIDI_CH_PROGRAM ) || (command == MIDI_CTRL) || (command == MIDI_POLY_TOUCH ) || (command == MIDI_TOUCH ) || (command == MIDI_BEND )) { MUTEX_LOCK; channel [numReceived] = (Pm_MessageStatus(event.message) & MIDI_CHN_MASK); note [numReceived] = Pm_MessageData1(event.message); velocity [numReceived] = Pm_MessageData2(event.message); timestamp [numReceived] = event.timestamp; if (verbose) { mexPrintf("channel = %2d, note = %3d, velocity = %3d, timestamp = %d\n", channel[numReceived], note[numReceived], velocity[numReceived], timestamp[numReceived]); mexEvalString("try, drawnow limitrate nocallbacks; end"); } if (numReceived==INPUT_BUFFER_SIZE) mexWarnMsgTxt("midi buffer overrun"); else numReceived++; MUTEX_UNLOCK; } } else mexWarnMsgTxt(Pm_GetErrorText(count)); } }
void receive_poll(PtTimestamp ts, void *userData) { int count, command; unsigned int latest; PmEvent event; if (inStream==NULL) return; if (Pm_Poll(inStream)!=TRUE) return; while ((count = Pm_Read(inStream, &event, 1))) { if (count == 1) { /* there seems to be a constant stream of MIDI events, not all of which are interesting */ /* the status has the command in the highest 4 bits and the channel in the lowest 4 bits */ command = Pm_MessageStatus(event.message) & MIDI_CODE_MASK; if ((command == MIDI_ON_NOTE) || (command == MIDI_OFF_NOTE ) || (command == MIDI_CH_PROGRAM ) || (command == MIDI_CTRL) || (command == MIDI_POLY_TOUCH ) || (command == MIDI_TOUCH ) || (command == MIDI_BEND )) { /* store the latest event at the end of the ring buffer */ latest = WRAP(numReceived, INPUT_BUFFER_SIZE); numReceived++; channel [latest] = (double)(Pm_MessageStatus(event.message) & MIDI_CHN_MASK); note [latest] = (double)Pm_MessageData1(event.message); velocity [latest] = (double)Pm_MessageData2(event.message); timestamp [latest] = (double)event.timestamp; if (verbose) { mexPrintf("channel = %2d, note = %3d, velocity = %3d, timestamp = %g\n", (int)channel[latest], (int)note[latest], (int)velocity[latest], timestamp[latest]); mexEvalString("try, drawnow limitrate nocallbacks; end"); } } } else mexWarnMsgTxt(Pm_GetErrorText(count)); } }
int midibus::poll_for_midi () { if (m_pm_num) { PmError err = Pm_Poll(m_pms); if (err == FALSE) { return 0; } if (err == TRUE) { return 1; } errprintf("Pm_Poll: %s\n", Pm_GetErrorText(err)); } return 0; }
void portmidiGetEvents(Server *self) { int i; PmError result; PmEvent buffer; PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data; for (i=0; i<self->midiin_count; i++) { do { result = Pm_Poll(be_data->midiin[i]); if (result) { if (Pm_Read(be_data->midiin[i], &buffer, 1) == pmBufferOverflow) continue; self->midiEvents[self->midi_count++] = PmEventToPyoMidiEvent(buffer); } } while (result); } }
bool PortMidiDriver::init() { inputId = getDeviceIn(preferences.portMidiInput); if(inputId == -1) inputId = Pm_GetDefaultInputDeviceID(); outputId = Pm_GetDefaultOutputDeviceID(); if (inputId == pmNoDevice) return false; static const int INPUT_BUFFER_SIZE = 100; static const int DRIVER_INFO = 0; static const int TIME_INFO = 0; Pt_Start(20, 0, 0); // timer started, 20 millisecond accuracy PmError error = Pm_OpenInput(&inputStream, inputId, (void*)DRIVER_INFO, INPUT_BUFFER_SIZE, ((long (*)(void*)) Pt_Time), (void*)TIME_INFO); if (error != pmNoError) { const char* p = Pm_GetErrorText(error); qDebug("PortMidi: open input (id=%d) failed: %s", int(inputId), p); Pt_Stop(); return false; } Pm_SetFilter(inputStream, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX); PmEvent buffer[1]; while (Pm_Poll(inputStream)) Pm_Read(inputStream, buffer, 1); timer = new QTimer(); timer->setInterval(20); // 20 msec timer->start(); timer->connect(timer, SIGNAL(timeout()), seq, SLOT(midiInputReady())); return true; }
void MidiSession::read() { while(active) { auto available = Pm_Poll(midiStream); if(available) { numEvents = Pm_Read(midiStream, events, 1); buffer.events.resize(numEvents); for(auto i = 0; i < numEvents; i++) { write(&events[i]); MidiEvent event; event.status = Pm_MessageStatus(events[i].message); event.note = Pm_MessageData1(events[i].message); event.velocity = Pm_MessageData2(events[i].message); event.timeStamp = events[i].timestamp; if(event.isNoteOff()) { event.channel = event.status - 127; } if(event.isNoteOn()) event.channel = event.status - 143; if (event.isPolyAftertouch()) event.channel = event.status = 159; buffer.events[i] = event; } for(auto& listener: listeners) listener->addBuffer(buffer); } } }
void PortMidiDriver::read() { static const int THRESHOLD = 3; // iterations required before consecutive drum notes are not considered part of a chord static int active = 0; static int iter = 0; //for some reason, some users could have "active" blocked in < 0 if (active < 0) active = 0; if (!inputStream) return; PmEvent buffer[1]; iter = (iter >= THRESHOLD) ? iter : (iter+1); while (Pm_Poll(inputStream)) { int n = Pm_Read(inputStream, buffer, 1); if (n > 0) { int status = Pm_MessageStatus(buffer[0].message); int type = status & 0xF0; int channel = status & 0x0F; if (type == ME_NOTEON) { int pitch = Pm_MessageData1(buffer[0].message); int velo = Pm_MessageData2(buffer[0].message); mscore->midiNoteReceived(channel, pitch, velo); } else if (type == ME_NOTEOFF) { int pitch = Pm_MessageData1(buffer[0].message); (void)Pm_MessageData2(buffer[0].message); // read but ignore mscore->midiNoteReceived(channel, pitch, 0); } else if (type == ME_CONTROLLER) { int param = Pm_MessageData1(buffer[0].message); int value = Pm_MessageData2(buffer[0].message); mscore->midiCtrlReceived(param, value); } } } }
bool osd_poll_midi_channel(osd_midi_device *dev) { PmError chk = Pm_Poll(dev->pmStream); return (chk == pmGotData) ? true : false; }
static int OpenMidiInDevice_(CSOUND *csound, void **userData, const char *dev) { int cntdev, devnum, opendevs, i; PmEvent buffer; PmError retval; PmDeviceInfo *info; // PortMidiStream *midistream; pmall_data *data = NULL; pmall_data *next = NULL; if (start_portmidi(csound) != 0) return -1; /* check if there are any devices available */ cntdev = portMidi_getDeviceCount(0); portMidi_listDevices(csound, 0); /* look up device in list */ if (dev == NULL || dev[0] == '\0') devnum = portMidi_getPackedDeviceID((int)Pm_GetDefaultInputDeviceID(), 0); else if (UNLIKELY((dev[0] < '0' || dev[0] > '9') && dev[0] != 'a')) { portMidiErrMsg(csound, Str("error: must specify a device number (>=0) or" " 'a' for all, not a name")); return -1; } else if (dev[0] != 'a') { devnum = (int)atoi(dev); if (UNLIKELY(devnum < 0 || devnum >= cntdev)) { portMidiErrMsg(csound, Str("error: device number is out of range")); return -1; } } else { // allow to proceed if 'a' is given even if there are no MIDI devices devnum = -1; } if (UNLIKELY(cntdev < 1 && (dev==NULL || dev[0] != 'a'))) { return portMidiErrMsg(csound, Str("no input devices are available")); } opendevs = 0; for (i = 0; i < cntdev; i++) { if (devnum == i || devnum == -1) { if (opendevs == 0) { data = (pmall_data *) malloc(sizeof(pmall_data)); next = data; data->next = NULL; opendevs++; } else { next->next = (pmall_data *) malloc(sizeof(pmall_data)); next = next->next; next->next = NULL; opendevs++; } info = portMidi_getDeviceInfo(i, 0); if (info->interf != NULL) csound->Message(csound, Str("PortMIDI: Activated input device %d: '%s' (%s)\n"), i, info->name, info->interf); else csound->Message(csound, Str("PortMIDI: Activated input device %d: '%s'\n"), i, info->name); retval = Pm_OpenInput(&next->midistream, (PmDeviceID) portMidi_getRealDeviceID(i, 0), NULL, 512L, (PmTimeProcPtr) NULL, NULL); if (UNLIKELY(retval != pmNoError)) { // Prevent leaking memory from "data" if (data) { next = data->next; free(data); } return portMidiErrMsg(csound, Str("error opening input device %d: %s"), i, Pm_GetErrorText(retval)); } /* only interested in channel messages (note on, control change, etc.) */ /* GAB: fixed for portmidi v.23Aug06 */ Pm_SetFilter(next->midistream, (PM_FILT_ACTIVE | PM_FILT_SYSEX)); /* empty the buffer after setting filter */ while (Pm_Poll(next->midistream) == TRUE) { Pm_Read(next->midistream, &buffer, 1); } } } *userData = (void*) data; /* report success */ return 0; }
bool osd_midi_device_pm::poll() { PmError chk = Pm_Poll(pmStream); return (chk == pmGotData) ? true : false; }
/* timer "interrupt" for processing midi data */ static void PMProcessMidi(PtTimestamp timestamp, void *userData) { ScopeMutexLock mulo(&gPmStreamMutex); PmError result; PmEvent buffer; /* just one message at a time */ for( int i = 0 ; i < gNumMIDIInPorts; ++i ) { int pmdid = gMidiInputIndexToPmDevIndex[i]; PmStream* midi_in = gMIDIInStreams[i]; if( midi_in ) { while(result = Pm_Poll(midi_in)) { long Tstatus, data1, data2; if (Pm_Read(midi_in, &buffer, 1) == pmBufferOverflow) continue; // unless there was overflow, we should have a message now Tstatus = Pm_MessageStatus(buffer.message); data1 = Pm_MessageData1(buffer.message); data2 = Pm_MessageData2(buffer.message); // +---------------------------------------------+ // | Lock the interp. mutex and dispatch message | // +---------------------------------------------+ pthread_mutex_lock (&gLangMutex); // it is needed -jamesmcc if (compiledOK) { VMGlobals *g = gMainVMGlobals; uint8 status = static_cast<uint8>(Tstatus & 0xF0); uint8 chan = static_cast<uint8>(Tstatus & 0x0F); g->canCallOS = false; // cannot call the OS ++g->sp; SetObject(g->sp, s_midiin->u.classobj); // Set the class MIDIIn //set arguments: ++g->sp; SetInt(g->sp, pmdid); //src // ++g->sp; SetInt(g->sp, status); //status ++g->sp; SetInt(g->sp, chan); //chan //if(status & 0x80) // set the running status for voice messages //gRunningStatus = ((status >> 4) == 0xF) ? 0 : pkt->data[i]; // keep also additional info switch (status) { case 0x80 : //noteOff ++g->sp; SetInt(g->sp, data1); ++g->sp; SetInt(g->sp, data2); runInterpreter(g, s_midiNoteOffAction, 5); break; case 0x90 : //noteOn ++g->sp; SetInt(g->sp, data1); ++g->sp; SetInt(g->sp, data2); runInterpreter(g, data2 ? s_midiNoteOnAction : s_midiNoteOffAction, 5); break; case 0xA0 : //polytouch ++g->sp; SetInt(g->sp, data1); ++g->sp; SetInt(g->sp, data2); runInterpreter(g, s_midiPolyTouchAction, 5); break; case 0xB0 : //control ++g->sp; SetInt(g->sp, data1); ++g->sp; SetInt(g->sp, data2); runInterpreter(g, s_midiControlAction, 5); break; case 0xC0 : //program ++g->sp; SetInt(g->sp, data1); runInterpreter(g, s_midiProgramAction, 4); break; case 0xD0 : //touch ++g->sp; SetInt(g->sp, data1); runInterpreter(g, s_midiTouchAction, 4); break; case 0xE0 : //bend ++g->sp; SetInt(g->sp, (data2 << 7) | data1); runInterpreter(g, s_midiBendAction, 4); break; /*case 0xF0 : // only the first Pm_Event will carry the 0xF0 byte // sysex message will be terminated by the EOX status byte 0xF7 midiProcessSystemPacket(data1, data2, chan); break; default : // data byte => continuing sysex message if(gRunningStatus && !gSysexFlag) { // handle running status status = gRunningStatus & 0xF0; // accept running status only inside a packet beginning chan = gRunningStatus & 0x0F; // with a valid status byte SetInt(g->sp, chan); --i; //goto L; // parse again with running status set // mv - get next byte } chan = 0; i += midiProcessSystemPacket(pkt, chan); // process sysex packet break; */ } g->canCallOS = false; } pthread_mutex_unlock (&gLangMutex); } } // if (midi_in) } // for loop until numMIDIInPorts }
static int ReadMidiData_(CSOUND *csound, void *userData, unsigned char *mbuf, int nbytes) { int n, retval, st, d1, d2; PmEvent mev; pmall_data *data; /* * Reads from MIDI input device linked list. */ n = 0; data = (pmall_data *)userData; while (data) { retval = Pm_Poll(data->midistream); if (retval != FALSE) { if (UNLIKELY(retval < 0)) return portMidiErrMsg(csound, Str("error polling input device")); while ((retval = Pm_Read(data->midistream, &mev, 1L)) > 0) { st = (int)Pm_MessageStatus(mev.message); d1 = (int)Pm_MessageData1(mev.message); d2 = (int)Pm_MessageData2(mev.message); /* unknown message or sysex data: ignore */ if (UNLIKELY(st < 0x80)) continue; /* ignore most system messages */ if (UNLIKELY(st >= 0xF0 && !(st == 0xF8 || st == 0xFA || st == 0xFB || st == 0xFC || st == 0xFF))) continue; nbytes -= (datbyts[(st - 0x80) >> 4] + 1); if (UNLIKELY(nbytes < 0)) { portMidiErrMsg(csound, Str("buffer overflow in MIDI input")); break; } /* channel messages */ n += (datbyts[(st - 0x80) >> 4] + 1); switch (datbyts[(st - 0x80) >> 4]) { case 0: *mbuf++ = (unsigned char) st; break; case 1: *mbuf++ = (unsigned char) st; *mbuf++ = (unsigned char) d1; break; case 2: *mbuf++ = (unsigned char) st; *mbuf++ = (unsigned char) d1; *mbuf++ = (unsigned char) d2; break; } } if (UNLIKELY(retval < 0)) { portMidiErrMsg(csound, Str("read error %d"), retval); if (n < 1) n = -1; } } data = data->next; } /* return the number of bytes read */ return n; }
/* timer interrupt for processing midi data */ void process_midi(PtTimestamp timestamp, void *userData) { PmError result; PmEvent buffer; /* just one message at a time */ long msg; /* do nothing until initialization completes */ if (!active) return; /* check for messages */ do { result = Pm_Dequeue(main_to_midi, &msg); if (result) { if (msg >= -127 && msg <= 127) transpose = msg; else if (msg == QUIT_MSG) { /* acknowledge receipt of quit message */ Pm_Enqueue(midi_to_main, &msg); active = FALSE; return; } else if (msg == MONITOR_MSG) { /* main has requested a pitch. monitor is a flag that * records the request: */ monitor = TRUE; } else if (msg == THRU_MSG) { /* toggle Thru on or off */ midi_thru = !midi_thru; } } } while (result); /* see if there is any midi input to process */ do { result = Pm_Poll(midi_in); if (result) { long status, data1, data2; if (Pm_Read(midi_in, &buffer, 1) == pmBufferOverflow) continue; if (midi_thru) Pm_Write(midi_out, &buffer, 1); /* unless there was overflow, we should have a message now */ status = Pm_MessageStatus(buffer.message); data1 = Pm_MessageData1(buffer.message); data2 = Pm_MessageData2(buffer.message); if ((status & 0xF0) == 0x90 || (status & 0xF0) == 0x80) { /* this is a note-on or note-off, so transpose and send */ data1 += transpose; /* keep within midi pitch range, keep proper pitch class */ while (data1 > 127) data1 -= 12; while (data1 < 0) data1 += 12; /* send the message */ buffer.message = Pm_Message(status, data1, data2); Pm_Write(midi_out, &buffer, 1); /* if monitor is set, send the pitch to the main thread */ if (monitor) { Pm_Enqueue(midi_to_main, &data1); monitor = FALSE; /* only send one pitch per request */ } } } } while (result); }
void main_test_both() { int i = 0; int in, out; PmStream * midi, * midiOut; PmEvent buffer[1]; PmError status, length; int num = 10; in = get_number("Type input number: "); out = get_number("Type output number: "); /* In is recommended to start timer before PortMidi */ TIME_START; Pm_OpenOutput(&midiOut, out, DRIVER_INFO, OUTPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO, latency); printf("Midi Output opened with %ld ms latency.\n", (long) latency); /* open input device */ Pm_OpenInput(&midi, in, DRIVER_INFO, INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO); printf("Midi Input opened. Reading %d Midi messages...\n",num); Pm_SetFilter(midi, PM_FILT_ACTIVE | PM_FILT_CLOCK); /* empty the buffer after setting filter, just in case anything got through */ while (Pm_Poll(midi)) { Pm_Read(midi, buffer, 1); } i = 0; while (i < num) { status = Pm_Poll(midi); if (status == TRUE) { length = Pm_Read(midi,buffer,1); if (length > 0) { Pm_Write(midiOut, buffer, 1); printf("Got message %d: time %ld, %2lx %2lx %2lx\n", i, (long) buffer[0].timestamp, (long) Pm_MessageStatus(buffer[0].message), (long) Pm_MessageData1(buffer[0].message), (long) Pm_MessageData2(buffer[0].message)); i++; } else { assert(0); } } } /* close midi devices */ Pm_Close(midi); Pm_Close(midiOut); Pm_Terminate(); }