#include "python2.5/Python.h" #include #include #include #include #define BUFFERSIZE 4096 static PyObject * pymidi_close(PyObject *self, PyObject *args) { HMIDIOUT *handle; unsigned long status; int handlesize; char error[BUFFERSIZE] = "Unknown error closing MIDI device"; if (!PyArg_ParseTuple(args, "s#", &handle, &handlesize) || \ handlesize != sizeof(HMIDIOUT)) { PyErr_SetString(PyExc_SyntaxError, "Expected MIDI filehandle"); return NULL; } status = midiOutClose(*handle); if (status) { midiOutGetErrorText(status, error, BUFFERSIZE); PyErr_SetString(PyExc_IOError, error); return NULL; } return Py_BuildValue("i", status); } static PyObject * pymidi_open(PyObject *self, PyObject *args) { char *mode; char *filename; unsigned long status; HMIDIOUT handle; char error[BUFFERSIZE] = "Unknown error opening MIDI device"; if (!PyArg_ParseTuple(args, "ss", &filename, &mode)) { PyErr_SetString(PyExc_SyntaxError, "Required: file name and mode string"); return NULL; } // only supports MIDI output to MIDI Mapper if (strcmp(filename, "/dev/midi") != 0) { PyErr_SetString(PyExc_SyntaxError, "File specification must be '/dev/midi'"); return NULL; } if ((strcmp(mode, "w") != 0) && (strcmp(mode, "wb") != 0)) { PyErr_SetString(PyExc_NotImplementedError, "Only 'w' and 'wb' modes supported"); return NULL; } status = midiOutOpen(&handle, (UINT) -1, 0, 0, CALLBACK_NULL); if (status) { midiOutGetErrorText(status, error, BUFFERSIZE); PyErr_SetString(PyExc_IOError, error); return NULL; } return Py_BuildValue("s#", &handle, sizeof(HMIDIOUT)); } static PyObject * pymidi_write(PyObject *self, PyObject *args) { HMIDIOUT *handle; int handlesize; unsigned long status; int event[4] = {0, 0, 0, 0}; DWORD packedevent = 0; char eventstring[BUFFERSIZE] = ""; char error[BUFFERSIZE] = "Unknown error sending MIDI event"; if ( /* put most common cases first for speed */ PyArg_ParseTuple(args, "s#(iii)", &handle, &handlesize, &event[0], &event[1], &event[2]) || \ PyArg_ParseTuple(args, "s#(ii)", &handle, &handlesize, &event[0], &event[1]) || \ PyArg_ParseTuple(args, "s#(i)", &handle, &handlesize, &event[0])) { PyErr_Clear(); /* ignore any failures above */ if (strlen(eventstring) > 0) { PyErr_SetString(PyExc_NotImplementedError, "No sysex messages nor other oddball events allowed yet"); return NULL; } if (handlesize != sizeof(HMIDIOUT)) { PyErr_SetString(PyExc_ValueError, "Corrupted HMIDIOUT filehandle"); return NULL; } } else { return NULL; } packedevent = (UCHAR)event[0] | \ ((UCHAR)event[1] << 8) | \ ((UCHAR)event[2] << 16) | \ ((UCHAR)event[3] << 24); status = midiOutShortMsg(*handle, packedevent); if (status) { midiOutGetErrorText(status, error, BUFFERSIZE); PyErr_SetString(PyExc_IOError, error); return NULL; } return Py_BuildValue("i", status); } static PyMethodDef pymidiMethods[] = { {"open", pymidi_open, METH_VARARGS, "Open the default MIDI device for output"}, {"write", pymidi_write, METH_VARARGS, "Write a MIDI event to the open device"}, {"close", pymidi_close, METH_VARARGS, "Close MIDI device"}, {NULL, NULL, 0, NULL} }; PyMODINIT_FUNC initpymidi(void) { (void) Py_InitModule("pymidi", pymidiMethods); }