PmError Pm_Close( PortMidiStream *stream ) { PmInternal *midi = (PmInternal *) stream; PmError err = pmNoError; /* arg checking */ if (midi == NULL) /* midi must point to something */ err = pmBadPtr; /* if it is an open device, the device_id will be valid */ else if (midi->device_id < 0 || midi->device_id >= pm_descriptor_index) err = pmBadPtr; /* and the device should be in the opened state */ else if (!descriptors[midi->device_id].pub.opened) err = pmBadPtr; if (err != pmNoError) goto error_return; /* close the device */ err = (*midi->dictionary->close)(midi); /* even if an error occurred, continue with cleanup */ descriptors[midi->device_id].internalDescriptor = NULL; descriptors[midi->device_id].pub.opened = FALSE; pm_free(midi->buffer); pm_free(midi); error_return: return pm_errmsg(err); }
PMEXPORT PmError Pm_Poll( PortMidiStream *stream ) { PmInternal *midi = (PmInternal *) stream; PmError err; pm_hosterror = FALSE; /* arg checking */ if(midi == NULL) err = pmBadPtr; else if (!descriptors[midi->device_id].pub.opened) err = pmBadPtr; else if (!descriptors[midi->device_id].pub.input) err = pmBadPtr; else err = (*(midi->dictionary->poll))(midi); if (err != pmNoError) { if (err == pmHostError) { midi->dictionary->host_error(midi, pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); pm_hosterror = TRUE; } return pm_errmsg(err); } return !Pm_QueueEmpty(midi->queue); }
int Pm_CountDevices( void ) { PmError err = Pm_Initialize(); if (err) return pm_errmsg(err); return pm_descriptor_index; }
/* returns number of longs actually read, or error code When the reader wants data: if overflow_flag: do not get anything empty the buffer (read_ptr = write_ptr) clear overflow_flag return pmBufferOverflow get data return number of messages */ PmError Pm_Read(PortMidiStream *stream, PmEvent *buffer, long length) { PmInternal *midi = (PmInternal *) stream; int n = 0; long head; PmError err = pmNoError; /* arg checking */ if(midi == NULL) err = pmBadPtr; else if(Pm_HasHostError(midi)) err = pmHostError; else if(!descriptors[midi->device_id].pub.opened) err = pmBadPtr; else if(!descriptors[midi->device_id].pub.input) err = pmBadPtr; /* First poll for data in the buffer... * This either simply checks for data, or attempts first to fill the buffer * with data from the MIDI hardware; this depends on the implementation. * We could call Pm_Poll here, but that would redo a lot of redundant * parameter checking, so I copied some code from Pm_Poll to here: */ else err = (*(midi->dictionary->poll))(midi); if (err != pmNoError) { return pm_errmsg(err); } head = midi->head; while (head != midi->tail && n < length) { PmEvent event = midi->buffer[head++]; *buffer++ = event; if (head == midi->buffer_len) head = 0; n++; } midi->head = head; if (midi->overflow) { midi->head = midi->tail; midi->overflow = FALSE; return pm_errmsg(pmBufferOverflow); } return n; }
PmError Pm_SetChannelMask(PortMidiStream *stream, int mask) { PmInternal *midi = (PmInternal *) stream; PmError err = pmNoError; if (midi == NULL) err = pmBadPtr; else midi->channel_mask = mask; return pm_errmsg(err); }
/* * returns number of messages actually read, or error code */ PMEXPORT int Pm_Read(PortMidiStream *stream, PmEvent *buffer, int32_t length) { PmInternal *midi = (PmInternal *) stream; int n = 0; PmError err = pmNoError; pm_hosterror = FALSE; /* arg checking */ if(midi == NULL) err = pmBadPtr; else if(!descriptors[midi->device_id].pub.opened) err = pmBadPtr; else if(!descriptors[midi->device_id].pub.input) err = pmBadPtr; /* First poll for data in the buffer... * This either simply checks for data, or attempts first to fill the buffer * with data from the MIDI hardware; this depends on the implementation. * We could call Pm_Poll here, but that would redo a lot of redundant * parameter checking, so I copied some code from Pm_Poll to here: */ else err = (*(midi->dictionary->poll))(midi); if (err != pmNoError) { if (err == pmHostError) { midi->dictionary->host_error(midi, pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); pm_hosterror = TRUE; } return pm_errmsg(err); } while (n < length) { PmError err = Pm_Dequeue(midi->queue, buffer++); if (err == pmBufferOverflow) { /* ignore the data we have retreived so far */ return pm_errmsg(pmBufferOverflow); } else if (err == 0) { /* empty queue */ break; } n++; } return n; }
PmError Pm_SetFilter(PortMidiStream *stream, long filters) { PmInternal *midi = (PmInternal *) stream; PmError err = pmNoError; /* arg checking */ if (midi == NULL) err = pmBadPtr; else if (!descriptors[midi->device_id].pub.opened) err = pmBadPtr; else midi->filters = filters; return pm_errmsg(err); }
PmError Pm_Abort( PortMidiStream* stream ) { PmInternal *midi = (PmInternal *) stream; PmError err; /* arg checking */ if (midi == NULL) err = pmBadPtr; if (!descriptors[midi->device_id].pub.output) err = pmBadPtr; if (!descriptors[midi->device_id].pub.opened) err = pmBadPtr; else err = (*midi->dictionary->abort)(midi); return pm_errmsg(err); }
PmError Pm_Poll( PortMidiStream *stream ) { PmInternal *midi = (PmInternal *) stream; PmError err; /* arg checking */ if(midi == NULL) err = pmBadPtr; else if(Pm_HasHostError(midi)) err = pmHostError; else if(!descriptors[midi->device_id].pub.opened) err = pmBadPtr; else if(!descriptors[midi->device_id].pub.input) err = pmBadPtr; else err = (*(midi->dictionary->poll))(midi); if (err != pmNoError) return pm_errmsg(err); else return midi->head != midi->tail; }
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); }
PmError Pm_OpenInput(PortMidiStream** stream, PmDeviceID inputDevice, void *inputDriverInfo, long bufferSize, PmTimeProcPtr time_proc, void *time_info) { PmInternal *midi; PmError err = pmNoError; pm_hosterror = FALSE; *stream = NULL; /* arg checking */ if (inputDevice < 0 || inputDevice >= pm_descriptor_index) err = pmInvalidDeviceId; else if (!descriptors[inputDevice].pub.input) err = pmBadPtr; else if(descriptors[inputDevice].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 = inputDevice; midi->write_flag = FALSE; midi->time_proc = time_proc; midi->time_info = time_info; /* windows adds timestamps in the driver and these are more accurate than using a time_proc, so do not automatically provide a time proc. Non-win implementations may want to provide a default time_proc in their system-specific midi_out_open() method. */ if (bufferSize <= 0) bufferSize = 256; /* default buffer size */ else bufferSize++; /* buffer holds N-1 msgs, so increase request by 1 */ midi->buffer_len = bufferSize; /* portMidi input storage */ midi->buffer = (PmEvent *) pm_alloc(sizeof(PmEvent) * midi->buffer_len); if (!midi->buffer) { /* free portMidi data */ *stream = NULL; pm_free(midi); err = pmInsufficientMemory; goto error_return; } midi->head = 0; midi->tail = 0; midi->latency = 0; /* not used */ midi->overflow = FALSE; midi->flush = FALSE; midi->sysex_in_progress = FALSE; midi->sysex_message = 0; midi->sysex_message_count = 0; midi->filters = PM_FILT_ACTIVE; midi->sync_time = 0; midi->first_message = TRUE; midi->dictionary = descriptors[inputDevice].dictionary; descriptors[inputDevice].internalDescriptor = midi; /* open system dependent input device */ err = (*midi->dictionary->open)(midi, inputDriverInfo); if (err) { *stream = NULL; descriptors[inputDevice].internalDescriptor = NULL; /* free portMidi data */ pm_free(midi->buffer); pm_free(midi); } else { /* portMidi input open successful */ descriptors[inputDevice].pub.opened = TRUE; } error_return: return pm_errmsg(err); }