static void MidiIn_callback(double timestamp, std::vector<unsigned char> *message, void *opaque) { MidiIn *self = (MidiIn *) opaque; uint8 *data = (uint8*) malloc(message->size()); for(size_t i=0; i < message->size(); i++) data[i] = (*message)[i]; MidiMessage inMidi(data, message->size(), timestamp); free(data); #if PK_WINDOWS WaitForSingleObject(self->mutex); #else pthread_mutex_lock(&self->mutex); #endif if(self->callback) // called too fast to init? { PyGILState_STATE gil_state = PyGILState_Ensure(); PyObject *result = NULL; PyObject *args = NULL; PyMidiMessage *outMidi = (PyMidiMessage *) PyMidiMessage_new(); (*outMidi->m) = inMidi; args = Py_BuildValue("(O)", outMidi); result = PyEval_CallObject(self->callback, args); if(result == NULL) { PyThreadState_SetAsyncExc(self->calling_thread_id, 0); } Py_XDECREF(result); Py_XDECREF(args); Py_XDECREF(outMidi); PyGILState_Release(gil_state); } else { self->m_q->push(new MidiMessage(inMidi)); self->triggered = true; } #if PK_WINDOWS SetEvent(self->cond); ReleaseMutex(self->mutex); #else pthread_cond_signal(&self->cond); pthread_mutex_unlock(&self->mutex); #endif }
PyObject *PyMidiMessage_FromMidiMessage(const MidiMessage &m) { PyMidiMessage *result = (PyMidiMessage *) PyMidiMessage_new(); *(result->m) = m; return (PyObject *) result; }
PyObject *PyMidiMessage_new() { return PyMidiMessage_new(getMidiMessageType(), 0, 0); }
static PyObject * MidiIn_getMessage(MidiIn *self, PyObject *args) { PyObject *timeout = NULL; PyObject *result = NULL; if(!PyArg_ParseTuple(args, "|O:getMessage", &timeout)) return NULL; long ms = -1; if(timeout) { if(PyFloat_CheckExact(timeout)) ms = (long) PyFloat_AS_DOUBLE(timeout); #if ! PK_PYTHON3 else if(PyInt_CheckExact(timeout)) ms = PyInt_AS_LONG(timeout); #endif else if(PyLong_CheckExact(timeout)) ms = PyLong_AsLong(timeout); else { PyErr_Format(RtMidiError, "timeout value must be a number, not %s", timeout->ob_type->tp_name); return NULL; } if(ms < 0) { PyErr_SetString(RtMidiError, "timeout value must be a positive number"); return NULL; } } #if PK_WINDOWS WaitForSingleObject(self->mutex); #else pthread_mutex_lock(&self->mutex); #endif if(ms > -1 && self->triggered == false) { PyThreadState *_save = PyEval_SaveThread(); #if PK_WINDOWS WaitForSingleObject(self->cond, ms < 0 ? INFINITE : ms); #else if(ms < 0) { pthread_cond_wait(&self->cond, &self->mutex); } else { struct timeval now; gettimeofday(&now, 0); struct timespec time; TIMEVAL_TO_TIMESPEC(&now, &time); unsigned long sec = ms / 1000; unsigned long nsec = (ms % 1000) * 1000000; time.tv_sec += sec; time.tv_nsec += nsec; while(time.tv_nsec >= 1000000000) { time.tv_sec++; time.tv_nsec -= 1000000000; } pthread_cond_timedwait(&self->cond, &self->mutex, &time); } #endif PyEval_RestoreThread(_save); } if(self->m_q->size() > 0) { result = (PyObject *) PyMidiMessage_new(); MidiMessage *inMidi = self->m_q->front(); (*((PyMidiMessage *)result)->m) = (*inMidi); self->m_q->pop(); self->triggered = false; delete inMidi; } #if PK_WINDOWS ReleaseMutex(self->mutex); #else pthread_mutex_unlock(&self->mutex); #endif if(result) return result; Py_RETURN_NONE; }