static int start_portmidi(CSOUND *csound) { const char *errMsg = NULL; #if !defined(WIN32) csound_global_mutex_lock(); #endif if (!portmidi_init_cnt) { if (UNLIKELY(Pm_Initialize() != pmNoError)) errMsg = Str(" *** error initialising PortMIDI"); else if (UNLIKELY(Pt_Start(1, NULL, NULL) != ptNoError)) errMsg = Str(" *** error initialising PortTime"); } if (errMsg == NULL) portmidi_init_cnt++; #if !defined(WIN32) csound_global_mutex_unlock(); #endif if (UNLIKELY(errMsg != NULL)) { csound->ErrorMsg(csound, Str(errMsg)); return -1; } #if !defined(WIN32) csound_global_mutex_unlock(); #endif return csound->RegisterResetCallback(csound, NULL, stop_portmidi); }
void init() { PmError err1; PtError err2; if (isInit) return; mexPrintf("Initialising PortMidi\n"); MUTEX_LOCK; note = malloc(INPUT_BUFFER_SIZE*sizeof(int32_t)); channel = malloc(INPUT_BUFFER_SIZE*sizeof(int32_t)); velocity = malloc(INPUT_BUFFER_SIZE*sizeof(int32_t)); timestamp = malloc(INPUT_BUFFER_SIZE*sizeof(int32_t)); if (!(channel && note && velocity && timestamp)) { FREE(channel); FREE(note); FREE(velocity); FREE(timestamp); MUTEX_UNLOCK; mexErrMsgTxt("Could not allocate memory"); } else { MUTEX_UNLOCK; } err1 = Pm_Initialize(); reportPmError(err1); err2 = Pt_Start(1, receive_poll, NULL); reportPtError(err2); /* getting here means that PortMidi and PortTime are both fine */ mexAtExit(exitFunction); isInit = 1; }
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; }
void start_scheduler(struct scheduler * scheduler) { PtError err; err = Pt_Start(RESOLUTION_MS, *dispatch, scheduler); if (err != ptNoError) { printf("Error starting the timer\n"); exit(1); } }
/*! @function midi_start @abstract @discussion @param @result */ void midi_start() { Pm_Initialize(); Pt_Start(1, NULL, NULL); retval = Pm_OpenOutput(&mstream, 0,NULL,512,NULL,NULL,0); if(retval != pmNoError) { printf("error: %s \n", Pm_GetErrorText(retval)); } else /* set channel 1 to grand piano */ program_change(1, 1); }
AudioClock::AudioClock(Server *s, const char *osc) : Module(s, osc) { addMethodToServer("/Data", "ii", AudioClock::data1, this); addMethodToServer("/Data", "iiii", AudioClock::data2, this); sampleRate = SAMPLE_RATE; numPackets = 256; interval = (double)numPackets/sampleRate; output = (short *)malloc(numPackets*sizeof(short)); memset(output, 0, numPackets*sizeof(short)); Pt_Start(interval, this->render, this); }
void midiOpenDevice(int inId, int outId) { // Initialize time Pt_Start(TIME_RESOLUTION_MS, NULL, NULL); // Open input Pm_OpenInput(&in, inId, NULL, INPUT_BUFFER_SIZE, (PmTimestamp (*)(void *)) Pt_Time, NULL); Pm_SetFilter(in, PM_FILT_ACTIVE | PM_FILT_CLOCK); // Open output Pm_OpenOutput(&out, outId, NULL, OUTPUT_BUFFER_SIZE, (PmTimestamp (*)(void *)) Pt_Time, NULL, 0); }
void init() { PmError err; if (isInit) return; printf("Initialising PortMidi\n"); err = Pm_Initialize(); reportPmError(err); if (Pt_Start(1,NULL,NULL) == 0) { mexAtExit(exitFunction); isInit = 1; } else { Pm_Terminate(); mexErrMsgTxt("Could start PortMidi, but not PortTime."); } }
int AudioClock::data1(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { AudioClock *ac = (AudioClock *)user_data; int s = argv[0]->i; if (s > 0) { if (!Pt_Started()) Pt_Start(ac->interval, ac->render, ac); }else { if (Pt_Started()) Pt_Stop(); } return 0; }
int initMIDI() { try { midiCleanUp(); TPmErr(Pm_Initialize()); int nbDev = Pm_CountDevices(); int inIndex = 0; int outIndex = 0; int pmdid; for( int i = 0; i < nbDev ; ++i ) { const PmDeviceInfo* devInfo = Pm_GetDeviceInfo(i); if( devInfo->input ) { gNumMIDIInPorts++; gMidiInputIndexToPmDevIndex[inIndex++] = i; gMidiPmDevIndexToInputIndex[i] = inIndex; } if( devInfo->output ) { gNumMIDIOutPorts++; gMidiOutputIndexToPmDevIndex[outIndex++] = i; gMidiPmDevIndexToOutputIndex[i] = outIndex; } } for( int i = 0; i < gNumMIDIOutPorts; i++) { pmdid = gMidiOutputIndexToPmDevIndex[i]; Pm_OpenOutput(&gMIDIOutStreams[i], pmdid, NULL, 512, NULL, NULL, 0); } /* will call our function, PMProcessMidi() every millisecond */ Pt_Start(1, &PMProcessMidi, 0); /* start a timer with millisecond accuracy */ } catch(PmError) { return errFailed; } gMIDIInitialized = true; return errNone; }
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; }
int AudioClock::data2(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { AudioClock *ac = (AudioClock *)user_data; int i = argv[0]->i; int s = argv[3]->i; if (Pt_Started()) Pt_Stop(); ac->numPackets = 64 * (i/4); ac->interval = (double)ac->numPackets/ac->sampleRate; if (s > 0) { if (!Pt_Started()) Pt_Start(ac->interval, ac->render, ac); }else { if (Pt_Started()) Pt_Stop(); } return 0; }
/* * Method: Pt_TimeStart */ JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStart (JNIEnv *env, jclass c, jint resolution) { return Pt_Start(resolution, NULL, NULL); }
static PyObject * MidiListener_play(MidiListener *self) { int i, num_devices; PmError pmerr; /* always start the timer before you start midi */ Pt_Start(1, &process_midi, (void *)self); pmerr = Pm_Initialize(); if (pmerr) { PySys_WriteStdout("Portmidi warning: could not initialize Portmidi: %s\n", Pm_GetErrorText(pmerr)); } num_devices = Pm_CountDevices(); if (num_devices > 0) { if (self->mididev < num_devices) { if (self->mididev == -1) self->mididev = Pm_GetDefaultInputDeviceID(); const PmDeviceInfo *info = Pm_GetDeviceInfo(self->mididev); if (info != NULL) { if (info->input) { pmerr = Pm_OpenInput(&self->midiin[0], self->mididev, NULL, 100, NULL, NULL); if (pmerr) { PySys_WriteStdout("Portmidi warning: could not open midi input %d (%s): %s\n", self->mididev, info->name, Pm_GetErrorText(pmerr)); } else { self->midicount = 1; } } } } else if (self->mididev >= num_devices) { self->midicount = 0; for (i=0; i<num_devices; i++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(i); if (info != NULL) { if (info->input) { pmerr = Pm_OpenInput(&self->midiin[self->midicount], i, NULL, 100, NULL, NULL); if (pmerr) { PySys_WriteStdout("Portmidi warning: could not open midi input %d (%s): %s\n", i, info->name, Pm_GetErrorText(pmerr)); } else { self->midicount++; } } } } } } for (i=0; i<self->midicount; i++) { Pm_SetFilter(self->midiin[i], PM_FILT_ACTIVE | PM_FILT_CLOCK); } if (self->midicount > 0) self->active = 1; Py_INCREF(Py_None); return Py_None; };
int main() { int id; long n; const PmDeviceInfo *info; char line[STRING_MAX]; int spin; int done = FALSE; /* determine what type of test to run */ printf("begin PortMidi multithread test...\n"); /* note that it is safe to call PortMidi from the main thread for initialization and opening devices. You should not make any calls to PortMidi from this thread once the midi thread begins. to make PortMidi calls. */ /* make the message queues */ /* messages can be of any size and any type, but all messages in * a given queue must have the same size. We'll just use long's * for our messages in this simple example */ midi_to_main = Pm_QueueCreate(32, sizeof(long)); assert(midi_to_main != NULL); main_to_midi = Pm_QueueCreate(32, sizeof(long)); assert(main_to_midi != NULL); /* a little test of enqueue and dequeue operations. Ordinarily, * you would call Pm_Enqueue from one thread and Pm_Dequeue from * the other. Since the midi thread is not running, this is safe. */ n = 1234567890; Pm_Enqueue(midi_to_main, &n); n = 987654321; Pm_Enqueue(midi_to_main, &n); Pm_Dequeue(midi_to_main, &n); if (n != 1234567890) { exit_with_message("Pm_Dequeue produced unexpected result."); } Pm_Dequeue(midi_to_main, &n); if(n != 987654321) { exit_with_message("Pm_Dequeue produced unexpected result."); } /* always start the timer before you start midi */ Pt_Start(1, &process_midi, 0); /* start a timer with millisecond accuracy */ /* the timer will call our function, process_midi() every millisecond */ Pm_Initialize(); id = Pm_GetDefaultOutputDeviceID(); info = Pm_GetDeviceInfo(id); if (info == NULL) { printf("Could not open default output device (%d).", id); exit_with_message(""); } printf("Opening output device %s %s\n", info->interf, info->name); /* use zero latency because we want output to be immediate */ Pm_OpenOutput(&midi_out, id, DRIVER_INFO, OUTPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO, LATENCY); id = Pm_GetDefaultInputDeviceID(); info = Pm_GetDeviceInfo(id); if (info == NULL) { printf("Could not open default input device (%d).", id); exit_with_message(""); } printf("Opening input device %s %s\n", info->interf, info->name); Pm_OpenInput(&midi_in, id, DRIVER_INFO, INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO); active = TRUE; /* enable processing in the midi thread -- yes, this is a shared variable without synchronization, but this simple assignment is safe */ printf("Enter midi input; it will be transformed as specified by...\n"); printf("%s\n%s\n%s\n", "Type 'q' to quit, 'm' to monitor next pitch, t to toggle thru or", "type a number to specify transposition.", "Must terminate with [ENTER]"); while (!done) { long msg; int len; fgets(line, STRING_MAX, stdin); /* remove the newline: */ len = strlen(line); if (len > 0) line[len - 1] = 0; /* overwrite the newline char */ if (strcmp(line, "q") == 0) { msg = QUIT_MSG; Pm_Enqueue(main_to_midi, &msg); /* wait for acknowlegement */ do { spin = Pm_Dequeue(midi_to_main, &msg); } while (spin == 0); /* spin */ ; done = TRUE; /* leave the command loop and wrap up */ } else if (strcmp(line, "m") == 0) { msg = MONITOR_MSG; Pm_Enqueue(main_to_midi, &msg); printf("Waiting for note...\n"); do { spin = Pm_Dequeue(midi_to_main, &msg); } while (spin == 0); /* spin */ ; printf("... pitch is %ld\n", msg); } else if (strcmp(line, "t") == 0) { /* reading midi_thru asynchronously could give incorrect results, e.g. if you type "t" twice before the midi thread responds to the first one, but we'll do it this way anyway. Perhaps a more correct way would be to wait for an acknowledgement message containing the new state. */ printf("Setting THRU %s\n", (midi_thru ? "off" : "on")); msg = THRU_MSG; Pm_Enqueue(main_to_midi, &msg); } else if (sscanf(line, "%ld", &msg) == 1) { if (msg >= -127 && msg <= 127) { /* send transposition value */ printf("Transposing by %ld\n", msg); Pm_Enqueue(main_to_midi, &msg); } else { printf("Transposition must be within -127...127\n"); } } else { printf("%s\n%s\n%s\n", "Type 'q' to quit, 'm' to monitor next pitch, or", "type a number to specify transposition.", "Must terminate with [ENTER]"); } } /* at this point, midi thread is inactive and we need to shut down * the midi input and output */ Pt_Stop(); /* stop the timer */ Pm_QueueDestroy(midi_to_main); Pm_QueueDestroy(main_to_midi); /* Belinda! if close fails here, some memory is deleted, right??? */ Pm_Close(midi_in); Pm_Close(midi_out); printf("finished portMidi multithread test...enter any character to quit [RETURN]..."); fgets(line, STRING_MAX, stdin); return 0; }
int main() { char line[STRING_MAX]; int i; int len; int choice; PtTimestamp stop; printf("Latency histogram.\n"); period = 0; while (period < 1) { period = get_number("Choose timer period (in ms, >= 1): "); } printf("Benchmark with:\n\t%s\n\t%s\n\t%s\n\t%s\n", "1. No MIDI traffic", "2. MIDI input", "3. MIDI output", "4. MIDI input and output"); choice = get_number("? "); switch (choice) { case 1: test_in = 0; test_out = 0; break; case 2: test_in = 1; test_out = 0; break; case 3: test_in = 0; test_out = 1; break; case 4: test_in = 1; test_out = 1; break; default: assert(0); } if (test_in || test_out) { /* list device information */ for (i = 0; i < Pm_CountDevices(); i++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(i); if ((test_in && info->input) || (test_out && info->output)) { printf("%d: %s, %s", i, info->interf, info->name); if (info->input) printf(" (input)"); if (info->output) printf(" (output)"); printf("\n"); } } /* open stream(s) */ if (test_in) { int i = get_number("MIDI input device number: "); Pm_OpenInput(&in, i, NULL, INPUT_BUFFER_SIZE, (long (*)(void *)) Pt_Time, NULL); /* turn on filtering; otherwise, input might overflow in the 5-second period before timer callback starts reading midi */ Pm_SetFilter(in, PM_FILT_ACTIVE | PM_FILT_CLOCK); } if (test_out) { int i = get_number("MIDI output device number: "); PmEvent buffer[1]; Pm_OpenOutput(&out, i, NULL, OUTPUT_BUFFER_SIZE, (long (*)(void *)) Pt_Time, NULL, 0); /* no latency scheduling */ /* send a program change to force a status byte -- this fixes a problem with a buggy linux MidiSport driver, and shouldn't hurt anything else */ buffer[0].timestamp = 0; buffer[0].message = Pm_Message(0xC0, 0, 0); /* program change */ Pm_Write(out, buffer, 1); output_period = get_number( "MIDI out should be sent every __ callback iterations: "); assert(output_period >= 1); } } printf("%s%s", "Latency measurements will start in 5 seconds. ", "Type return to stop: "); Pt_Start(period, &pt_callback, 0); fgets(line, STRING_MAX, stdin); stop = Pt_Time(); Pt_Stop(); /* courteously turn off the last note, if necessary */ if (note_on) { PmEvent buffer[1]; buffer[0].timestamp = Pt_Time(NULL); buffer[0].message = Pm_Message(0x90, 60, 0); Pm_Write(out, buffer, 1); } /* print the histogram */ printf("Duration of test: %g seconds\n\n", max(0, stop - 5000) * 0.001); printf("Latency(ms) Number of occurrences\n"); /* avoid printing beyond last non-zero histogram entry */ len = min(HIST_LEN, max_latency + 1); for (i = 0; i < len; i++) { printf("%2d %10ld\n", i, histogram[i]); } printf("Number of points greater than %dms: %ld\n", HIST_LEN - 1, out_of_range); printf("Maximum latency: %ld milliseconds\n", max_latency); printf("\nNote that due to rounding, actual latency can be 1ms higher\n"); printf("than the numbers reported here.\n"); printf("Type return to exit..."); fgets(line, STRING_MAX, stdin); if(choice == 2) Pm_Close(in); else if(choice == 3) Pm_Close(out); else if(choice == 4) { Pm_Close(in); Pm_Close(out); } return 0; }
int Server_pm_init(Server *self) { int i = 0, ret = 0; PmError pmerr; if (self->midiActive == 0) { self->withPortMidi = 0; self->withPortMidiOut = 0; return 0; } pmerr = Pm_Initialize(); if (pmerr) { Server_warning(self, "Portmidi warning: could not initialize Portmidi: %s\n", Pm_GetErrorText(pmerr)); self->withPortMidi = 0; self->withPortMidiOut = 0; return -1; } else { Server_debug(self, "Portmidi initialized.\n"); self->withPortMidi = 1; self->withPortMidiOut = 1; } PyoPmBackendData *be_data = (PyoPmBackendData *) malloc(sizeof(PyoPmBackendData *)); self->midi_be_data = (void *) be_data; if (self->withPortMidi == 1) { self->midiin_count = self->midiout_count = 0; int num_devices = Pm_CountDevices(); Server_debug(self, "Portmidi number of devices: %d.\n", num_devices); if (num_devices > 0) { if (self->midi_input < num_devices) { if (self->midi_input == -1) self->midi_input = Pm_GetDefaultInputDeviceID(); Server_debug(self, "Midi input device : %d.\n", self->midi_input); const PmDeviceInfo *info = Pm_GetDeviceInfo(self->midi_input); if (info != NULL) { if (info->input) { pmerr = Pm_OpenInput(&be_data->midiin[0], self->midi_input, NULL, 100, NULL, NULL); if (pmerr) { Server_warning(self, "Portmidi warning: could not open midi input %d (%s): %s\n", self->midi_input, info->name, Pm_GetErrorText(pmerr)); self->withPortMidi = 0; } else { Server_debug(self, "Midi input (%s) opened.\n", info->name); self->midiin_count = 1; } } else { Server_warning(self, "Portmidi warning: Midi Device (%s), not an input device!\n", info->name); self->withPortMidi = 0; } } } else if (self->midi_input >= num_devices) { Server_debug(self, "Midi input device : all!\n"); self->midiin_count = 0; for (i=0; i<num_devices; i++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(i); if (info != NULL) { if (info->input) { pmerr = Pm_OpenInput(&be_data->midiin[self->midiin_count], i, NULL, 100, NULL, NULL); if (pmerr) { Server_warning(self, "Portmidi warning: could not open midi input %d (%s): %s\n", 0, info->name, Pm_GetErrorText(pmerr)); } else { Server_debug(self, "Midi input (%s) opened.\n", info->name); self->midiin_count++; } } } } if (self->midiin_count == 0) self->withPortMidi = 0; } else { Server_warning(self, "Portmidi warning: no input device!\n"); self->withPortMidi = 0; } if (self->midi_output < num_devices) { if (self->midi_output == -1) self->midi_output = Pm_GetDefaultOutputDeviceID(); Server_debug(self, "Midi output device : %d.\n", self->midi_output); const PmDeviceInfo *outinfo = Pm_GetDeviceInfo(self->midi_output); if (outinfo != NULL) { if (outinfo->output) { Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */ pmerr = Pm_OpenOutput(&be_data->midiout[0], self->midi_output, NULL, 0, NULL, NULL, 1); if (pmerr) { Server_warning(self, "Portmidi warning: could not open midi output %d (%s): %s\n", self->midi_output, outinfo->name, Pm_GetErrorText(pmerr)); self->withPortMidiOut = 0; if (Pt_Started()) Pt_Stop(); } else { Server_debug(self, "Midi output (%s) opened.\n", outinfo->name); self->midiout_count = 1; } } else { Server_warning(self, "Portmidi warning: Midi Device (%s), not an output device!\n", outinfo->name); self->withPortMidiOut = 0; } } } else if (self->midi_output >= num_devices) { Server_debug(self, "Midi output device : all!\n"); self->midiout_count = 0; Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */ for (i=0; i<num_devices; i++) { const PmDeviceInfo *outinfo = Pm_GetDeviceInfo(i); if (outinfo != NULL) { if (outinfo->output) { pmerr = Pm_OpenOutput(&be_data->midiout[self->midiout_count], i, NULL, 100, NULL, NULL, 1); if (pmerr) { Server_warning(self, "Portmidi warning: could not open midi output %d (%s): %s\n", 0, outinfo->name, Pm_GetErrorText(pmerr)); } else { Server_debug(self, "Midi output (%s) opened.\n", outinfo->name); self->midiout_count++; } } } } if (self->midiout_count == 0) { if (Pt_Started()) Pt_Stop(); self->withPortMidiOut = 0; } } else { Server_warning(self, "Portmidi warning: no output device!\n"); self->withPortMidiOut = 0; } if (self->withPortMidi == 0 && self->withPortMidiOut == 0) { Pm_Terminate(); Server_warning(self, "Portmidi closed.\n"); ret = -1; } } else { Server_warning(self, "Portmidi warning: no midi device found!\nPortmidi closed.\n"); self->withPortMidi = 0; self->withPortMidiOut = 0; Pm_Terminate(); ret = -1; } } if (self->withPortMidi == 1) { self->midi_count = 0; for (i=0; i<self->midiin_count; i++) { Pm_SetFilter(be_data->midiin[i], PM_FILT_ACTIVE | PM_FILT_CLOCK); } } return ret; }
PmError Pm_OpenOutput(PortMidiStream** stream, PmDeviceID outputDevice, void *outputDriverInfo, long bufferSize, PmTimeProcPtr time_proc, void *time_info, long latency ) { PmInternal *midi; PmError err = pmNoError; pm_hosterror = FALSE; *stream = NULL; /* arg checking */ if (outputDevice < 0 || outputDevice >= pm_descriptor_index) err = pmInvalidDeviceId; else if (!descriptors[outputDevice].pub.output) err = pmBadPtr; else if (descriptors[outputDevice].pub.opened) err = pmBadPtr; if (err != pmNoError) goto error_return; /* create portMidi internal data */ midi = (PmInternal *) pm_alloc(sizeof(PmInternal)); *stream = midi; if (!midi) { err = pmInsufficientMemory; goto error_return; } midi->device_id = outputDevice; midi->write_flag = TRUE; midi->time_proc = time_proc; /* if latency > 0, we need a time reference. If none is provided, use PortTime library */ if (time_proc == NULL && latency != 0) { if (!Pt_Started()) Pt_Start(1, 0, 0); /* time_get does not take a parameter, so coerce */ midi->time_proc = (PmTimeProcPtr) Pt_Time; } midi->time_info = time_info; /* when stream used, this buffer allocated and used by winmm_out_open; deleted by winmm_out_close */ midi->buffer_len = bufferSize; midi->buffer = NULL; midi->head = 0; /* unused by output */ midi->tail = 0; /* unused by output */ /* if latency zero, output immediate (timestamps ignored) */ /* if latency < 0, use 0 but don't return an error */ if (latency < 0) latency = 0; midi->latency = latency; midi->overflow = FALSE; /* not used */ midi->flush = FALSE; /* not used */ midi->sysex_in_progress = FALSE; midi->sysex_message = 0; /* unused by output */ midi->sysex_message_count = 0; /* unused by output */ midi->filters = 0; /* not used for output */ midi->sync_time = 0; midi->first_message = TRUE; midi->dictionary = descriptors[outputDevice].dictionary; descriptors[outputDevice].internalDescriptor = midi; /* open system dependent output device */ err = (*midi->dictionary->open)(midi, outputDriverInfo); if (err) { *stream = NULL; descriptors[outputDevice].internalDescriptor = NULL; /* free portMidi data */ pm_free(midi); } else { /* portMidi input open successful */ descriptors[outputDevice].pub.opened = TRUE; } error_return: return pm_errmsg(err); }
void sys_do_open_midi(int nmidiin, int *midiinvec, int nmidiout, int *midioutvec) { int i = 0, j, devno; int n = 0; PmError err; Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */ mac_nmidiindev = 0; for (i = 0; i < nmidiin; i++) { for (j = 0, devno = 0; j < Pm_CountDevices(); j++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(j); if (info->input) { if (devno == midiinvec[i]) { err = Pm_OpenInput(&mac_midiindevlist[mac_nmidiindev], j, NULL, 100, NULL, NULL); if (err) post("could not open midi input %d (%s): %s", j, info->name, Pm_GetErrorText(err)); else { if (sys_verbose) post("Midi Input (%s) opened.", info->name); mac_nmidiindev++; } } devno++; } } } mac_nmidioutdev = 0; for (i = 0; i < nmidiout; i++) { for (j = 0, devno = 0; j < Pm_CountDevices(); j++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(j); if (info->output) { if (devno == midioutvec[i]) { err = Pm_OpenOutput( &mac_midioutdevlist[mac_nmidioutdev], j, NULL, 0, NULL, NULL, 0); if (err) post("could not open midi output %d (%s): %s", j, info->name, Pm_GetErrorText(err)); else { if (sys_verbose) post("Midi Output (%s) opened.", info->name); mac_nmidioutdev++; } } devno++; } } } }