diff options
Diffstat (limited to '3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.pyx')
-rw-r--r-- | 3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.pyx | 537 |
1 files changed, 0 insertions, 537 deletions
diff --git a/3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.pyx b/3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.pyx deleted file mode 100644 index e43bd2b28b4..00000000000 --- a/3rdparty/portmidi/pm_python/pyportmidi/_pyportmidi.pyx +++ /dev/null @@ -1,537 +0,0 @@ -# pyPortMidi -# Python bindings for PortMidi -# John Harrison -# http://sound.media.mit.edu/~harrison -# harrison@media.mit.edu -# written in Pyrex -__version__="0.07" - -import array - -# CHANGES: - -# 0.0.5: (June 1st, 2009) -# Output no longer calls abort when it deallocates. -# Added abort and close methods. -# Need to call Abort() explicityly if you want that to happen. - - -# -# 0.0.3: (March 15, 2005) -# changed everything from tuples to lists -# return 4 values for PmRead instead of 3 (for SysEx) -# minor fixes for flexibility and error checking -# flushed out DistUtils package and added Mac and Linux compile support -# Markus Pfaff: added ability for WriteSysEx to accept lists as well -# as strings - -# 0.0.2: -# fixed pointer to function calls to avoid necessity of pyport library - -# 0.0.1: -# initial release - -cdef extern from "portmidi.h": - ctypedef enum PmError: - pmNoError = 0, - pmHostError = -10000, - pmInvalidDeviceId, #/* out of range or output device when input is requested or vice versa */ - pmInsufficientMemory, - pmBufferTooSmall, - pmBufferOverflow, - pmBadPtr, - pmBadData, #/* illegal midi data, e.g. missing EOX */ - pmInternalError, - pmBufferMaxSize, #/* buffer is already as large as it can be */ - PmError Pm_Initialize() - PmError Pm_Terminate() - ctypedef void PortMidiStream - ctypedef PortMidiStream PmStream # CHECK THIS! - ctypedef int PmDeviceID - int Pm_HasHostError( PortMidiStream * stream ) - char *Pm_GetErrorText( PmError errnum ) - Pm_GetHostErrorText(char * msg, unsigned int len) - ctypedef struct PmDeviceInfo: - int structVersion - char *interf #/* underlying MIDI API, e.g. MMSystem or DirectX */ - char *name #/* device name, e.g. USB MidiSport 1x1 */ - int input #/* true iff input is available */ - int output #/* true iff output is available */ - int opened #/* used by generic PortMidi code to do error checking on arguments */ - int Pm_CountDevices() - PmDeviceID Pm_GetDefaultInputDeviceID() - PmDeviceID Pm_GetDefaultOutputDeviceID() - ctypedef long PmTimestamp - ctypedef PmTimestamp (*PmTimeProcPtr)(void *time_info) - #PmBefore is not defined... - PmDeviceInfo* Pm_GetDeviceInfo( PmDeviceID id ) - PmError Pm_OpenInput( PortMidiStream** stream, - PmDeviceID inputDevice, - void *inputDriverInfo, - long bufferSize, - long (*PmPtr) (), # long = PtTimestamp - void *time_info ) - PmError Pm_OpenOutput( PortMidiStream** stream, - PmDeviceID outputDevice, - void *outputDriverInfo, - long bufferSize, - #long (*PmPtr) (), # long = PtTimestamp - PmTimeProcPtr time_proc, # long = PtTimestamp - void *time_info, - long latency ) - PmError Pm_SetFilter( PortMidiStream* stream, long filters ) - PmError Pm_Abort( PortMidiStream* stream ) - PmError Pm_Close( PortMidiStream* stream ) - ctypedef long PmMessage - ctypedef struct PmEvent: - PmMessage message - PmTimestamp timestamp - PmError Pm_Read( PortMidiStream *stream, PmEvent *buffer, long length ) - PmError Pm_Poll( PortMidiStream *stream) - int Pm_Channel(int channel) - PmError Pm_SetChannelMask(PortMidiStream *stream, int mask) - PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, long length ) - PmError Pm_WriteSysEx( PortMidiStream *stream, PmTimestamp when, unsigned char *msg) - -cdef extern from "porttime.h": - ctypedef enum PtError: - ptNoError = 0, - ptHostError = -10000, - ptAlreadyStarted, - ptAlreadyStopped, - ptInsufficientMemory - ctypedef long PtTimestamp - ctypedef void (* PtCallback)( PtTimestamp timestamp, void *userData ) - PtError Pt_Start(int resolution, PtCallback *callback, void *userData) - PtTimestamp Pt_Time() - -FILT_ACTIVE=0x1 -FILT_SYSEX=0x2 -FILT_CLOCK=0x4 -FILT_PLAY=0x8 -FILT_F9=0x10 -FILT_TICK=0x10 -FILT_FD=0x20 -FILT_UNDEFINED=0x30 -FILT_RESET=0x40 -FILT_REALTIME=0x7F -FILT_NOTE=0x80 -FILT_CHANNEL_AFTERTOUCH=0x100 -FILT_POLY_AFTERTOUCH=0x200 -FILT_AFTERTOUCH=0x300 -FILT_PROGRAM=0x400 -FILT_CONTROL=0x800 -FILT_PITCHBEND=0x1000 -FILT_MTC=0x2000 -FILT_SONG_POSITION=0x4000 -FILT_SONG_SELECT=0x8000 -FILT_TUNE=0x10000 -FALSE=0 -TRUE=1 - -def Initialize(): - """ -Initialize: call this first - """ - Pm_Initialize() - Pt_Start(1, NULL, NULL) # /* equiv to TIME_START: start timer w/ ms accuracy */ - -def Terminate(): - """ -Terminate: call this to clean up Midi streams when done. -If you do not call this on Windows machines when you are -done with MIDI, your system may crash. - """ - Pm_Terminate() - -def GetDefaultInputDeviceID(): - return Pm_GetDefaultInputDeviceID() - -def GetDefaultOutputDeviceID(): - return Pm_GetDefaultOutputDeviceID() - -def CountDevices(): - return Pm_CountDevices() - -def GetDeviceInfo(i): - """ -GetDeviceInfo(<device number>): returns 5 parameters - - underlying MIDI API - - device name - - TRUE iff input is available - - TRUE iff output is available - - TRUE iff device stream is already open - """ - cdef PmDeviceInfo *info - - # disregarding the constness from Pm_GetDeviceInfo, since pyrex doesn't do const. - info = <PmDeviceInfo *>Pm_GetDeviceInfo(i) - - if info <> NULL: return info.interf, info.name, info.input, info.output, info.opened - else: return - -def Time(): - """ -Time() returns the current time in ms -of the PortMidi timer - """ - return Pt_Time() - -def GetErrorText(err): - """ -GetErrorText(<err num>) returns human-readable error -messages translated from error numbers - """ - return Pm_GetErrorText(err) - -def Channel(chan): - """ -Channel(<chan>) is used with ChannelMask on input MIDI streams. -Example: to receive input on channels 1 and 10 on a MIDI - stream called MidiIn: -MidiIn.SetChannelMask(pypm.Channel(1) | pypm.Channel(10)) - -note: PyPortMidi Channel function has been altered from - the original PortMidi c call to correct for what - seems to be a bug --- i.e. channel filters were - all numbered from 0 to 15 instead of 1 to 16. - """ - return Pm_Channel(chan-1) - -cdef class Output: - """ -class Output: - define an output MIDI stream. Takes the form: - x = pypm.Output(MidiOutputDevice, latency) - latency is in ms. - If latency = 0 then timestamps for output are ignored. - """ - cdef int i - cdef PmStream *midi - cdef int debug - cdef int _aborted - - def __init__(self, OutputDevice, latency=0): - - cdef PmError err - #cdef PtTimestamp (*PmPtr) () - cdef PmTimeProcPtr PmPtr - - self.i = OutputDevice - self.debug = 0 - self._aborted = 0 - - if latency == 0: - PmPtr = NULL - else: - PmPtr = <PmTimeProcPtr>&Pt_Time - if self.debug: print "Opening Midi Output" - # Why is bufferSize 0 here? - err = Pm_OpenOutput(&(self.midi), self.i, NULL, 0, PmPtr, NULL, latency) - if err < 0: - s = Pm_GetErrorText(err) - # Something's amiss here - if we try to throw an Exception - # here, we crash. - if not err == -10000: - raise Exception,s - else: - print "Unable to open Midi OutputDevice=",OutputDevice," err=",s - - def __dealloc__(self): - if self.debug: print "Closing MIDI output stream and destroying instance" - #err = Pm_Abort(self.midi) - #if err < 0: raise Exception, Pm_GetErrorText(err) - err = Pm_Close(self.midi) - if err < 0: raise Exception, Pm_GetErrorText(err) - - - def _check_open(self): - """ checks to see if the midi is open, and if not, raises an error. - """ - - if self.midi == NULL: - raise Exception, "midi Output not open." - - if self._aborted: - raise Exception, "midi Output aborted. Need to call Close after Abort." - - def Close(self): - """ -Close() - closes a midi stream, flushing any pending buffers. - (PortMidi attempts to close open streams when the application - exits -- this is particularly difficult under Windows.) - """ - #if not self.midi: - # return - - err = Pm_Close(self.midi) - if err < 0: - raise Exception, Pm_GetErrorText(err) - #self.midi = NULL - - - def Abort(self): - """ -Abort() terminates outgoing messages immediately - The caller should immediately close the output port; - this call may result in transmission of a partial midi message. - There is no abort for Midi input because the user can simply - ignore messages in the buffer and close an input device at - any time. - """ - #if not self.midi: - # return - - err = Pm_Abort(self.midi) - if err < 0: - raise Exception, Pm_GetErrorText(err) - - self._aborted = 1 - - - def Write(self, data): - """ -Write(data) - output a series of MIDI information in the form of a list: - Write([[[status <,data1><,data2><,data3>],timestamp], - [[status <,data1><,data2><,data3>],timestamp],...]) - <data> fields are optional - example: choose program change 1 at time 20000 and - send note 65 with velocity 100 500 ms later. - Write([[[0xc0,0,0],20000],[[0x90,60,100],20500]]) - notes: - 1. timestamps will be ignored if latency = 0. - 2. To get a note to play immediately, send MIDI info with - timestamp read from function Time. - 3. understanding optional data fields: - Write([[[0xc0,0,0],20000]]) is equivalent to - Write([[[0xc0],20000]]) - """ - cdef PmEvent buffer[1024] - cdef PmError err - cdef int i - - self._check_open() - - - if len(data) > 1024: raise IndexError, 'maximum list length is 1024' - else: - for loop1 in range(len(data)): - if ((len(data[loop1][0]) > 4) | - (len(data[loop1][0]) < 1)): - raise IndexError, str(len(data[loop1][0]))+' arguments in event list' - buffer[loop1].message = 0 - for i in range(len(data[loop1][0])): - buffer[loop1].message = buffer[loop1].message + ((data[loop1][0][i]&0xFF) << (8*i)) - buffer[loop1].timestamp = data[loop1][1] - if self.debug: print loop1," : ",buffer[loop1].message," : ",buffer[loop1].timestamp - if self.debug: print "writing to midi buffer" - err= Pm_Write(self.midi, buffer, len(data)) - if err < 0: raise Exception, Pm_GetErrorText(err) - - def WriteShort(self, status, data1 = 0, data2 = 0): - """ -WriteShort(status <, data1><, data2>) - output MIDI information of 3 bytes or less. - data fields are optional - status byte could be: - 0xc0 = program change - 0x90 = note on - etc. - data bytes are optional and assumed 0 if omitted - example: note 65 on with velocity 100 - WriteShort(0x90,65,100) - """ - cdef PmEvent buffer[1] - cdef PmError err - self._check_open() - - buffer[0].timestamp = Pt_Time() - buffer[0].message = ((((data2) << 16) & 0xFF0000) | (((data1) << 8) & 0xFF00) | ((status) & 0xFF)) - if self.debug: print "Writing to MIDI buffer" - err = Pm_Write(self.midi, buffer, 1) # stream, buffer, length - if err < 0 : raise Exception, Pm_GetErrorText(err) - - def WriteSysEx(self, when, msg): - """ - WriteSysEx(<timestamp>,<msg>) - writes a timestamped system-exclusive midi message. - <msg> can be a *list* or a *string* - example: - (assuming y is an input MIDI stream) - y.WriteSysEx(0,'\\xF0\\x7D\\x10\\x11\\x12\\x13\\xF7') - is equivalent to - y.WriteSysEx(pypm.Time, - [0xF0, 0x7D, 0x10, 0x11, 0x12, 0x13, 0xF7]) - """ - cdef PmError err - cdef char *cmsg - cdef PtTimestamp CurTime - - self._check_open() - - if type(msg) is list: - msg = array.array('B',msg).tostring() # Markus Pfaff contribution - cmsg = msg - - CurTime = Pt_Time() - err = Pm_WriteSysEx(self.midi, when, <unsigned char *> cmsg) - if err < 0 : raise Exception, Pm_GetErrorText(err) - while Pt_Time() == CurTime: # wait for SysEx to go thru or...my - pass # win32 machine crashes w/ multiple SysEx - - - - - - - - - - - -cdef class Input: - """ -class Input: - define an input MIDI stream. Takes the form: - x = pypm.Input(MidiInputDevice) - """ - cdef PmStream *midi - cdef int debug - cdef int i - - def __init__(self, InputDevice, buffersize=4096): - cdef PmError err - self.i = InputDevice - self.debug = 0 - err= Pm_OpenInput(&(self.midi),self.i,NULL,buffersize,&Pt_Time,NULL) - if err < 0: raise Exception, Pm_GetErrorText(err) - if self.debug: print "MIDI input opened." - - def __dealloc__(self): - cdef PmError err - if self.debug: print "Closing MIDI input stream and destroying instance" - - err = Pm_Close(self.midi) - if err < 0: - raise Exception, Pm_GetErrorText(err) - - - - def _check_open(self): - """ checks to see if the midi is open, and if not, raises an error. - """ - - if self.midi == NULL: - raise Exception, "midi Input not open." - - - def Close(self): - """ -Close() - closes a midi stream, flushing any pending buffers. - (PortMidi attempts to close open streams when the application - exits -- this is particularly difficult under Windows.) - """ - #if not self.midi: - # return - - err = Pm_Close(self.midi) - if err < 0: - raise Exception, Pm_GetErrorText(err) - #self.midi = NULL - - - - def SetFilter(self, filters): - """ - SetFilter(<filters>) sets filters on an open input stream - to drop selected input types. By default, only active sensing - messages are filtered. To prohibit, say, active sensing and - sysex messages, call - SetFilter(stream, FILT_ACTIVE | FILT_SYSEX); - - Filtering is useful when midi routing or midi thru functionality - is being provided by the user application. - For example, you may want to exclude timing messages - (clock, MTC, start/stop/continue), while allowing note-related - messages to pass. Or you may be using a sequencer or drum-machine - for MIDI clock information but want to exclude any notes - it may play. - - Note: SetFilter empties the buffer after setting the filter, - just in case anything got through. - """ - cdef PmEvent buffer[1] - cdef PmError err - - self._check_open() - - - err = Pm_SetFilter(self.midi, filters) - - if err < 0: raise Exception, Pm_GetErrorText(err) - - while(Pm_Poll(self.midi) != pmNoError): - - err = Pm_Read(self.midi,buffer,1) - if err < 0: raise Exception, Pm_GetErrorText(err) - - def SetChannelMask(self, mask): - """ - SetChannelMask(<mask>) filters incoming messages based on channel. - The mask is a 16-bit bitfield corresponding to appropriate channels - Channel(<channel>) can assist in calling this function. - i.e. to set receive only input on channel 1, call with - SetChannelMask(Channel(1)) - Multiple channels should be OR'd together, like - SetChannelMask(Channel(10) | Channel(11)) - note: PyPortMidi Channel function has been altered from - the original PortMidi c call to correct for what - seems to be a bug --- i.e. channel filters were - all numbered from 0 to 15 instead of 1 to 16. - """ - cdef PmError err - - self._check_open() - - err = Pm_SetChannelMask(self.midi,mask) - if err < 0: raise Exception, Pm_GetErrorText(err) - - def Poll(self): - """ - Poll tests whether input is available, - returning TRUE, FALSE, or an error value. - """ - cdef PmError err - self._check_open() - - err = Pm_Poll(self.midi) - if err < 0: raise Exception, Pm_GetErrorText(err) - return err - - def Read(self,length): - """ -Read(length): returns up to <length> midi events stored in -the buffer and returns them as a list: -[[[status,data1,data2,data3],timestamp], - [[status,data1,data2,data3],timestamp],...] -example: Read(50) returns all the events in the buffer, - up to 50 events. - """ - cdef PmEvent buffer[1024] - - self._check_open() - - x = [] - - if length > 1024: raise IndexError, 'maximum buffer length is 1024' - if length < 1: raise IndexError, 'minimum buffer length is 1' - NumEvents = Pm_Read(self.midi,buffer,length) - if NumEvents < 0: raise Exception, Pm_GetErrorText(NumEvents) - x=[] - if NumEvents >= 1: - for loop in range(NumEvents): - x.append([[buffer[loop].message & 0xff, (buffer[loop].message >> 8) & 0xFF, (buffer[loop].message >> 16) & 0xFF, (buffer[loop].message >> 24) & 0xFF], buffer[loop].timestamp]) - return x |