diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..8ac9db7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: python +python: + - 2.6 + - 2.7 + - 3.2 + - 3.3 + - 3.4 + - nightly +before_install: + - date -u + - uname -a + - lsb_release -a + - sudo apt-get -qq update + - sudo apt-get install build-essential python-dev swig libasound2-dev +install: + - python setup.py install +script: + - nosetests diff --git a/README.mediawiki b/README.mediawiki index 50fff4a..c6907c9 100644 --- a/README.mediawiki +++ b/README.mediawiki @@ -25,6 +25,7 @@ feature set to offer. * A reader and writer, so you can read and write your MIDI tracks to disk. ==Installation== +First, make sure you have swig installed (www.swig.org) Follow the [http://docs.python.org/2/install/index.html normal procedure for Python module installation]: @@ -107,7 +108,7 @@ think about things in terms of milliseconds, or ticks, if you care about the bea A tick represents the lowest level resolution of a MIDI track. Tempo is always analogous with Beats per Minute (BPM) which is the same thing as Quarter notes per Minute (QPM). The Resolution is also known as the Pulses per Quarter note -(PPQ). It analogous to Ticks per Beat (TPM). +(PPQ). It analogous to Ticks per Beat (TPB). Tempo is set by two things. First, a saved MIDI file encodes an initial Resolution and Tempo. You use these values to initialize the sequencer timer. diff --git a/examples/example_1.py b/examples/example_1.py index 60acb87..f30b4ac 100644 --- a/examples/example_1.py +++ b/examples/example_1.py @@ -2,19 +2,36 @@ # Instantiate a MIDI Pattern (contains a list of tracks) pattern = midi.Pattern() # Instantiate a MIDI Track (contains a list of MIDI events) +pattern.append(midi.Track(( + midi.TimeSignatureEvent(tick=0,numerator=4,denominator=4, + metronome=24, + thirtyseconds=8), + midi.KeySignatureEvent(tick=0), + midi.EndOfTrackEvent(tick=1) + ))) track = midi.Track() -# Append the track to the pattern pattern.append(track) +#reverb +#track.append(midi.ControlChangeEvent(tick=0,data=[91,58])) +#track.append(midi.ControlChangeEvent(tick=0,data=[10,69])) +#msb +#track.append(midi.ControlChangeEvent(tick=0,channel=0,data=[0,0])) +#lsb +#track.append(midi.ControlChangeEvent(tick=0,channel=0,data=[32,0])) +#track.append(midi.ProgramChangeEvent(tick=0,channel=0,data=[24])) # Instantiate a MIDI note on event, append it to the track -on = midi.NoteOnEvent(tick=0, velocity=20, pitch=midi.G_3) -track.append(on) +track.append(midi.NoteOnEvent(tick=0, velocity=200, pitch=midi.G_4)) # Instantiate a MIDI note off event, append it to the track -off = midi.NoteOffEvent(tick=100, pitch=midi.G_3) -track.append(off) +track.append(midi.NoteOffEvent(tick=250, velocity=200, pitch=midi.G_4)) +track.append(midi.EndOfTrackEvent(tick=100)) +# some more notes +pattern.append(midi.Track(( + midi.NoteOnEvent(tick=200, velocity=200, pitch=(midi.F_4+1)), + midi.NoteOnEvent(tick=200, velocity=200, pitch=midi.A_4), + midi.NoteOnEvent(tick=200, velocity=200, pitch=midi.C_5), + midi.EndOfTrackEvent(tick=1)))) # Add the end of track event, append it to the track -eot = midi.EndOfTrackEvent(tick=1) -track.append(eot) # Print out the pattern -print pattern +print(pattern) # Save the pattern to disk midi.write_midifile("example.mid", pattern) diff --git a/examples/example_2.py b/examples/example_2.py index ecc4a87..1d09fb7 100644 --- a/examples/example_2.py +++ b/examples/example_2.py @@ -1,3 +1,3 @@ import midi pattern = midi.read_midifile("example.mid") -print pattern +print(pattern) diff --git a/examples/timidity.py b/examples/timidity.py new file mode 100644 index 0000000..8bb6701 --- /dev/null +++ b/examples/timidity.py @@ -0,0 +1,30 @@ +#!/usr/bin/env pypy +import midi +import subprocess as s + +def main(): + p = s.Popen(["timidity"]+['--verbose']*1+["-"],stdin=s.PIPE) + writer = midi.FileWriter(p.stdin) + writer.write_file_header(midi.Pattern(),2) + track = midi.Track(( + midi.TimeSignatureEvent(tick=0,numerator=4,denominator=4, + metronome=24, + thirtyseconds=8), + midi.KeySignatureEvent(tick=0), + midi.EndOfTrackEvent(tick=1) + )) + writer.write_track(track) + + def song(): + for i in range(5): + yield midi.NoteOnEvent(tick=i*100, velocity=200, pitch=(midi.G_5+i)) + yield midi.EndOfTrackEvent(tick=1) + writer.write_track(midi.Track(song())) + p.stdin.flush() + p.stdin.close() + p.wait() + + + +if __name__ == '__main__': + main() diff --git a/scripts/mididump.py b/scripts/mididump.py index 1497a3d..fff59ff 100644 --- a/scripts/mididump.py +++ b/scripts/mididump.py @@ -6,9 +6,9 @@ import sys if len(sys.argv) != 2: - print "Usage: {0} ".format(sys.argv[0]) + print("Usage: {0} ".format(sys.argv[0])) sys.exit(2) midifile = sys.argv[1] pattern = midi.read_midifile(midifile) -print repr(pattern) +print(repr(pattern)) diff --git a/scripts/mididumphw.py b/scripts/mididumphw.py index 42aef0b..640f754 100644 --- a/scripts/mididumphw.py +++ b/scripts/mididumphw.py @@ -6,4 +6,4 @@ s = sequencer.SequencerHardware() -print s +print(s) diff --git a/scripts/midilisten.py b/scripts/midilisten.py index b86ee5c..03eba64 100644 --- a/scripts/midilisten.py +++ b/scripts/midilisten.py @@ -8,7 +8,7 @@ import midi.sequencer as sequencer if len(sys.argv) != 3: - print "Usage: {0} ".format(sys.argv[0]) + print("Usage: {0} ".format(sys.argv[0])) exit(2) client = sys.argv[1] @@ -21,4 +21,4 @@ while True: event = seq.event_read() if event is not None: - print event + print(event) diff --git a/scripts/midiplay.py b/scripts/midiplay.py index fdddcce..51221eb 100644 --- a/scripts/midiplay.py +++ b/scripts/midiplay.py @@ -8,7 +8,7 @@ import midi.sequencer as sequencer if len(sys.argv) != 4: - print "Usage: {0} ".format(sys.argv[0]) + print("Usage: {0} ".format(sys.argv[0])) exit(2) client = sys.argv[1] @@ -43,4 +43,4 @@ time.sleep(.5) time.sleep(30) -print 'The end?' +print('The end?') diff --git a/setup.py b/setup.py index a7e5b4b..cbba66f 100755 --- a/setup.py +++ b/setup.py @@ -3,22 +3,22 @@ from distutils.core import setup, Extension __base__ = { - 'name':'midi', - 'version':'v0.2.3', - 'description':'Python MIDI API', - 'author':'giles hall', - 'author_email':'ghall@csh.rit.edu', - 'package_dir':{'midi':'src'}, - 'py_modules':['midi.containers', 'midi.__init__', 'midi.events', 'midi.util', 'midi.fileio', 'midi.constants'], - 'ext_modules':[], - 'ext_package':'', - 'scripts':['scripts/mididump.py', 'scripts/mididumphw.py', 'scripts/midiplay.py'], + 'name': 'midi', + 'version': 'v0.2.3', + 'description': 'Python MIDI API', + 'author': 'giles hall', + 'author_email': 'ghall@csh.rit.edu', + 'package_dir': {'midi':'src'}, + 'py_modules': ['midi.containers', 'midi.__init__', 'midi.events', 'midi.util', 'midi.fileio', 'midi.constants'], + 'ext_modules': [], + 'ext_package': '', + 'scripts': ['scripts/mididump.py', 'scripts/mididumphw.py', 'scripts/midiplay.py'], } def setup_alsa(ns): srclist = ["src/sequencer_alsa/sequencer_alsa.i"] extns = { - 'libraries':['asound'], + 'libraries': ['asound'], #'extra_compile_args':['-DSWIGRUNTIME_DEBUG'] } ext = Extension('_sequencer_alsa', srclist, **extns) @@ -38,7 +38,7 @@ def configure_platform(): setup_alsa(ns) pass else: - print "No sequencer available for '%s' platform." % platform + print("No sequencer available for '%s' platform." % platform) return ns if __name__ == "__main__": diff --git a/src/__init__.py b/src/__init__.py index 0092665..3ebfa3d 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,5 +1,5 @@ -from containers import * -from events import * +from .containers import * +from .events import * from struct import unpack, pack -from util import * -from fileio import * +from .util import * +from .fileio import * diff --git a/src/constants.py b/src/constants.py index fb329b7..96c6816 100644 --- a/src/constants.py +++ b/src/constants.py @@ -3,13 +3,13 @@ ## OCTAVE_MAX_VALUE = 12 -OCTAVE_VALUES = range( OCTAVE_MAX_VALUE ) +OCTAVE_VALUES = list(range( OCTAVE_MAX_VALUE)) -NOTE_NAMES = ['C','Cs','D','Ds','E','F','Fs','G','Gs','A','As','B'] +NOTE_NAMES = ['C', 'Cs', 'D', 'Ds', 'E', 'F', 'Fs', 'G', 'Gs', 'A', 'As', 'B'] WHITE_KEYS = [0, 2, 4, 5, 7, 9, 11] BLACK_KEYS = [1, 3, 6, 8, 10] NOTE_PER_OCTAVE = len( NOTE_NAMES ) -NOTE_VALUES = range( OCTAVE_MAX_VALUE * NOTE_PER_OCTAVE ) +NOTE_VALUES = list(range( OCTAVE_MAX_VALUE * NOTE_PER_OCTAVE)) NOTE_NAME_MAP_FLAT = {} NOTE_VALUE_MAP_FLAT = [] NOTE_NAME_MAP_SHARP = {} diff --git a/src/containers.py b/src/containers.py index 006dbac..9bffcdd 100644 --- a/src/containers.py +++ b/src/containers.py @@ -25,14 +25,14 @@ def __getitem__(self, item): if isinstance(item, slice): indices = item.indices(len(self)) return Pattern(resolution=self.resolution, format=self.format, - tracks=(super(Pattern, self).__getitem__(i) for i in xrange(*indices))) + tracks=(super(Pattern, self).__getitem__(i) for i in range(*indices))) else: return super(Pattern, self).__getitem__(item) def __getslice__(self, i, j): # The deprecated __getslice__ is still called when subclassing built-in types # for calls of the form List[i:j] - return self.__getitem__(slice(i,j)) + return self.__getitem__(slice(i, j)) class Track(list): def __init__(self, events=[], tick_relative=True): @@ -58,14 +58,14 @@ def make_ticks_rel(self): def __getitem__(self, item): if isinstance(item, slice): indices = item.indices(len(self)) - return Track((super(Track, self).__getitem__(i) for i in xrange(*indices))) + return Track((super(Track, self).__getitem__(i) for i in range(*indices))) else: return super(Track, self).__getitem__(item) def __getslice__(self, i, j): # The deprecated __getslice__ is still called when subclassing built-in types # for calls of the form List[i:j] - return self.__getitem__(slice(i,j)) + return self.__getitem__(slice(i, j)) def __repr__(self): return "midi.Track(\\\n %s)" % (pformat(list(self)).replace('\n', '\n '), ) diff --git a/src/events.py b/src/events.py index a62fbad..c049afe 100644 --- a/src/events.py +++ b/src/events.py @@ -14,24 +14,23 @@ def register_event(cls, event, bases): "Event %s already registered" % event.name cls.MetaEvents[event.metacommand] = event else: - raise ValueError, "Unknown bases class in event type: "+event.name + raise ValueError("Unknown bases class in event type: "+event.name) register_event = classmethod(register_event) +class AutoRegister(type): + def __init__(cls, name, bases, dict): + if name not in {'AbstractEvent', 'Event', 'MetaEvent', 'NoteEvent', + 'MetaEventWithText'}: + EventRegistry.register_event(cls, bases) -class AbstractEvent(object): - __slots__ = ['tick', 'data'] + +class AbstractEvent(object,metaclass=AutoRegister): name = "Generic MIDI Event" length = 0 statusmsg = 0x0 - class __metaclass__(type): - def __init__(cls, name, bases, dict): - if name not in ['AbstractEvent', 'Event', 'MetaEvent', 'NoteEvent', - 'MetaEventWithText']: - EventRegistry.register_event(cls, bases) - def __init__(self, **kw): - if type(self.length) == int: + if isinstance(self.length, int): defdata = [0] * self.length else: defdata = [] @@ -60,7 +59,6 @@ def __repr__(self): class Event(AbstractEvent): - __slots__ = ['channel'] name = 'Event' def __init__(self, **kw): @@ -110,7 +108,6 @@ def is_event(cls, statusmsg): """ class NoteEvent(Event): - __slots__ = ['pitch', 'velocity'] length = 2 def get_pitch(self): @@ -151,7 +148,6 @@ def set_value(self, val): value = property(get_value, set_value) class ControlChangeEvent(Event): - __slots__ = ['control', 'value'] statusmsg = 0xB0 length = 2 name = 'Control Change' @@ -169,7 +165,6 @@ def get_value(self): value = property(get_value, set_value) class ProgramChangeEvent(Event): - __slots__ = ['value'] statusmsg = 0xC0 length = 1 name = 'Program Change' @@ -181,7 +176,6 @@ def get_value(self): value = property(get_value, set_value) class ChannelAfterTouchEvent(Event): - __slots__ = ['value'] statusmsg = 0xD0 length = 1 name = 'Channel After Touch' @@ -193,7 +187,6 @@ def get_value(self): value = property(get_value, set_value) class PitchWheelEvent(Event): - __slots__ = ['pitch'] statusmsg = 0xE0 length = 2 name = 'Pitch Wheel' @@ -291,7 +284,6 @@ class EndOfTrackEvent(MetaEvent): metacommand = 0x2F class SetTempoEvent(MetaEvent): - __slots__ = ['bpm', 'mpqn'] name = 'Set Tempo' metacommand = 0x51 length = 3 @@ -304,7 +296,7 @@ def get_bpm(self): def get_mpqn(self): assert(len(self.data) == 3) - vals = [self.data[x] << (16 - (8 * x)) for x in xrange(3)] + vals = [self.data[x] << (16 - (8 * x)) for x in range(3)] return sum(vals) def set_mpqn(self, val): self.data = [(val >> (16 - (8 * x)) & 0xFF) for x in range(3)] @@ -315,7 +307,6 @@ class SmpteOffsetEvent(MetaEvent): metacommand = 0x54 class TimeSignatureEvent(MetaEvent): - __slots__ = ['numerator', 'denominator', 'metronome', 'thirtyseconds'] name = 'Time Signature' metacommand = 0x58 length = 4 @@ -345,7 +336,6 @@ def set_thirtyseconds(self, val): thirtyseconds = property(get_thirtyseconds, set_thirtyseconds) class KeySignatureEvent(MetaEvent): - __slots__ = ['alternatives', 'minor'] name = 'Key Signature' metacommand = 0x59 length = 2 diff --git a/src/fileio.py b/src/fileio.py index 2c1d793..92da246 100644 --- a/src/fileio.py +++ b/src/fileio.py @@ -1,8 +1,8 @@ -from containers import * -from events import * +from .containers import * +from .events import * from struct import unpack, pack -from constants import * -from util import * +from .constants import * +from .util import * class FileReader(object): def read(self, midifile): @@ -14,8 +14,8 @@ def read(self, midifile): def parse_file_header(self, midifile): # First four bytes are MIDI header magic = midifile.read(4) - if magic != 'MThd': - raise TypeError, "Bad header in MIDI file." + if magic != b'MThd': + raise TypeError("Bad header in MIDI file.",magic) # next four bytes are header size # next two bytes specify the format version # next two bytes specify the number of tracks @@ -35,8 +35,8 @@ def parse_file_header(self, midifile): def parse_track_header(self, midifile): # First four bytes are Track header magic = midifile.read(4) - if magic != 'MTrk': - raise TypeError, "Bad track header in MIDI file: " + magic + if magic != b'MTrk': + raise TypeError("Bad track header in MIDI file: ",magic) # next four bytes are track size trksz = unpack(">L", midifile.read(4))[0] return trksz @@ -56,21 +56,21 @@ def parse_midi_event(self, trackdata): # first datum is varlen representing delta-time tick = read_varlen(trackdata) # next byte is status message - stsmsg = ord(trackdata.next()) + stsmsg = next(trackdata) # is the event a MetaEvent? if MetaEvent.is_event(stsmsg): - cmd = ord(trackdata.next()) + cmd = next(trackdata) if cmd not in EventRegistry.MetaEvents: - raise Warning, "Unknown Meta MIDI Event: " + `cmd` + raise Warning("Unknown Meta MIDI Event: " + repr(cmd)) cls = EventRegistry.MetaEvents[cmd] datalen = read_varlen(trackdata) - data = [ord(trackdata.next()) for x in range(datalen)] + data = [next(trackdata) for x in range(datalen)] return cls(tick=tick, data=data) # is this event a Sysex Event? elif SysexEvent.is_event(stsmsg): data = [] while True: - datum = ord(trackdata.next()) + datum = next(trackdata) if datum == 0xF7: break data.append(datum) @@ -79,80 +79,100 @@ def parse_midi_event(self, trackdata): else: key = stsmsg & 0xF0 if key not in EventRegistry.Events: - assert self.RunningStatus, "Bad byte value" + assert self.RunningStatus, ("Bad byte value", tick, stsmsg, bytes(trackdata)) data = [] key = self.RunningStatus & 0xF0 cls = EventRegistry.Events[key] channel = self.RunningStatus & 0x0F data.append(stsmsg) - data += [ord(trackdata.next()) for x in range(cls.length - 1)] + data += [next(trackdata) for x in range(cls.length - 1)] return cls(tick=tick, channel=channel, data=data) else: self.RunningStatus = stsmsg cls = EventRegistry.Events[key] channel = self.RunningStatus & 0x0F - data = [ord(trackdata.next()) for x in range(cls.length)] + data = [next(trackdata) for x in range(cls.length)] return cls(tick=tick, channel=channel, data=data) - raise Warning, "Unknown MIDI Event: " + `stsmsg` + raise Warning("Unknown MIDI Event: " + repr(stsmsg)) class FileWriter(object): - def write(self, midifile, pattern): - self.write_file_header(midifile, pattern) + RunningStatus = None + def __init__(self,file): + self.file = file + def write(self, pattern): + self.write_file_header(pattern,len(pattern)) for track in pattern: - self.write_track(midifile, track) + self.write_track(track) - def write_file_header(self, midifile, pattern): + def write_file_header(self, pattern, length=None): + if length is None: + length = len(pattern) # First four bytes are MIDI header - packdata = pack(">LHHH", 6, - pattern.format, - len(pattern), - pattern.resolution) - midifile.write('MThd%s' % packdata) + packdata = pack(">LHHH", 6, + pattern.format, + length, + pattern.resolution) + self.file.write(b'MThd' + packdata) - def write_track(self, midifile, track): - buf = '' - self.RunningStatus = None + + def write_track(self, track): + hlen = len(self.encode_track_header(0)) + buf = bytearray(b'0'*hlen) for event in track: - buf += self.encode_midi_event(event) - buf = self.encode_track_header(len(buf)) + buf - midifile.write(buf) + buf.extend(self.encode_midi_event(event)) + buf[:hlen] = self.encode_track_header(len(buf)-hlen) + self.file.write(buf) + def write_track_header(self,track=None): + trklen = 1 if track is None else track if isinstance(track,int) else len(track) + self.file.write(self.encode_track_header(trklen)) + def encode_track_header(self, trklen): - return 'MTrk%s' % pack(">L", trklen) + return b'MTrk' + pack(">L", trklen) + def write_midi_event(self, event): + # be sure to write the track and pattern headers first + # can stream to timidity or fluidsynth this way + self.file.write(self.encode_midi_event(event)) + def encode_midi_event(self, event): - ret = '' - ret += write_varlen(event.tick) + ret = bytearray() + #assert hasattr(event,'tick'), event + assert isinstance(event.tick,int), event.tick + ret.extend(write_varlen(event.tick)) # is the event a MetaEvent? if isinstance(event, MetaEvent): - ret += chr(event.statusmsg) + chr(event.metacommand) - ret += write_varlen(len(event.data)) - ret += str.join('', map(chr, event.data)) + ret.append(event.statusmsg) + ret.append(event.metacommand) + ret.extend(write_varlen(len(event.data))) + ret.extend(event.data) # is this event a Sysex Event? elif isinstance(event, SysexEvent): - ret += chr(0xF0) - ret += str.join('', map(chr, event.data)) - ret += chr(0xF7) + ret.append(0xF0) + ret.extend(event.data) + ret.append(0xF7) # not a Meta MIDI event or a Sysex event, must be a general message elif isinstance(event, Event): - if not self.RunningStatus or \ - self.RunningStatus.statusmsg != event.statusmsg or \ - self.RunningStatus.channel != event.channel: - self.RunningStatus = event - ret += chr(event.statusmsg | event.channel) - ret += str.join('', map(chr, event.data)) + # why in the heeeeeeeeelp would you not write the status message + # here? doesn't matter if it's the same as last time. the byte + # needs to be there! + + ret.append(event.statusmsg | event.channel) + ret.extend(event.data) else: - raise ValueError, "Unknown MIDI Event: " + str(event) + raise ValueError("Unknown MIDI Event: " + str(event)) return ret def write_midifile(midifile, pattern): - if type(midifile) in (str, unicode): - midifile = open(midifile, 'wb') - writer = FileWriter() - return writer.write(midifile, pattern) + if type(midifile) in (str, str): + with open(midifile, 'wb') as out: + return write_midifile(out,pattern) + writer = FileWriter(midifile) + return writer.write(pattern) def read_midifile(midifile): - if type(midifile) in (str, unicode): - midifile = open(midifile, 'rb') + if type(midifile) in (str, bytes): + with open(midifile, 'rb') as inp: + return read_midifile(inp) reader = FileReader() return reader.read(midifile) diff --git a/src/sequencer.py b/src/sequencer.py index c7842d1..2f51e81 100644 --- a/src/sequencer.py +++ b/src/sequencer.py @@ -50,9 +50,9 @@ def __init__(self, stream, window): self.ttpts.append(stream.endoftrack.tick) self.ttpts = iter(self.ttpts) # Setup next tempo timepoint - self.ttp = self.ttpts.next() + self.ttp = next(self.ttpts) self.tempomap = iter(self.stream.tempomap) - self.tempo = self.tempomap.next() + self.tempo = next(self.tempomap) self.endoftrack = False def __iter__(self): @@ -67,7 +67,7 @@ def __next_edge(self): # We're past the tempo-marker. oldttp = self.ttp try: - self.ttp = self.ttpts.next() + self.ttp = next(self.ttpts) except StopIteration: # End of Track! self.window_edge = self.ttp @@ -77,11 +77,11 @@ def __next_edge(self): # account the tempo change. msused = (oldttp - lastedge) * self.tempo.mpt msleft = self.window_length - msused - self.tempo = self.tempomap.next() + self.tempo = next(self.tempomap) ticksleft = msleft / self.tempo.mpt self.window_edge = ticksleft + self.tempo.tick - def next(self): + def __next__(self): ret = [] self.__next_edge() if self.leftover: diff --git a/src/sequencer_alsa/__init__.py b/src/sequencer_alsa/__init__.py index 55dea93..fd22b26 100644 --- a/src/sequencer_alsa/__init__.py +++ b/src/sequencer_alsa/__init__.py @@ -1 +1 @@ -from sequencer import * +from .sequencer import * diff --git a/src/sequencer_alsa/sequencer.py b/src/sequencer_alsa/sequencer.py index 792d5c3..4f7ade2 100644 --- a/src/sequencer_alsa/sequencer.py +++ b/src/sequencer_alsa/sequencer.py @@ -1,8 +1,8 @@ import select -import sequencer_alsa as S +from . import sequencer_alsa as S import midi -__SWIG_NS_SET__ = set(['__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__swig_getmethods__', '__swig_setmethods__', '__weakref__', 'this', 'thisown']) +__SWIG_NS_SET__ = {'__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__swig_getmethods__', '__swig_setmethods__', '__weakref__', 'this', 'thisown'} def stringify(name, obj, indent=0): retstr = '' @@ -21,16 +21,16 @@ def stringify(name, obj, indent=0): class Sequencer(object): __ARGUMENTS__ = { - 'alsa_sequencer_name':'__sequencer__', - 'alsa_sequencer_stream':S.SND_SEQ_OPEN_DUPLEX, - 'alsa_sequencer_mode':S.SND_SEQ_NONBLOCK, - 'alsa_sequencer_type':'default', - 'alsa_port_name':'__port__', - 'alsa_port_caps':S.SND_SEQ_PORT_CAP_READ, - 'alsa_port_type':S.SND_SEQ_PORT_TYPE_MIDI_GENERIC, - 'alsa_queue_name':'__queue__', - 'sequencer_tempo':120, - 'sequencer_resolution':1000, + 'alsa_sequencer_name': '__sequencer__', + 'alsa_sequencer_stream': S.SND_SEQ_OPEN_DUPLEX, + 'alsa_sequencer_mode': S.SND_SEQ_NONBLOCK, + 'alsa_sequencer_type': 'default', + 'alsa_port_name': '__port__', + 'alsa_port_caps': S.SND_SEQ_PORT_CAP_READ, + 'alsa_port_type': S.SND_SEQ_PORT_TYPE_MIDI_GENERIC, + 'alsa_queue_name': '__queue__', + 'sequencer_tempo': 120, + 'sequencer_resolution': 1000, } DefaultArguments = {} @@ -71,7 +71,7 @@ def get_nonblock(self): def _error(self, errcode): strerr = S.snd_strerror(errcode) msg = "ALSAError[%d]: %s" % (errcode, strerr) - raise RuntimeError, msg + raise RuntimeError(msg) def _init_handle(self): ret = S.open_client(self.alsa_sequencer_name, @@ -268,7 +268,7 @@ def event_write(self, event, direct=False, relative=False, tick=False): seqev.data.control.value = event.pitch ## Unknown else: - print "Warning :: Unknown event type: %s" % event + print("Warning :: Unknown event type: %s" % event) return None err = S.snd_seq_event_output(self.client, seqev) @@ -323,7 +323,7 @@ def add_port(self, port, name, caps): self._ports[name] = port def __iter__(self): - return self._ports.itervalues() + return iter(self._ports.values()) def __len__(self): return len(self._ports) @@ -359,7 +359,7 @@ def init(self): self._query_clients() def __iter__(self): - return self._clients.itervalues() + return iter(self._clients.values()) def __len__(self): return len(self._clients) @@ -403,9 +403,9 @@ def _query_clients(self): class SequencerRead(Sequencer): DefaultArguments = { - 'sequencer_name':'__SequencerRead__', - 'sequencer_stream':not S.SND_SEQ_NONBLOCK, - 'alsa_port_caps':S.SND_SEQ_PORT_CAP_WRITE | S.SND_SEQ_PORT_CAP_SUBS_WRITE, + 'sequencer_name': '__SequencerRead__', + 'sequencer_stream': not S.SND_SEQ_NONBLOCK, + 'alsa_port_caps': S.SND_SEQ_PORT_CAP_WRITE | S.SND_SEQ_PORT_CAP_SUBS_WRITE, } def subscribe_port(self, client, port): diff --git a/src/sequencer_osx/cfstring-typemaps-example-1.0/setup.py b/src/sequencer_osx/cfstring-typemaps-example-1.0/setup.py index 945841e..c907fa4 100644 --- a/src/sequencer_osx/cfstring-typemaps-example-1.0/setup.py +++ b/src/sequencer_osx/cfstring-typemaps-example-1.0/setup.py @@ -4,5 +4,5 @@ setup(name = "cfstring-typemaps-example", version = "1.0", ext_modules = [Extension("_example", - ["example.i","example.c"], - extra_link_args=['-framework','CoreFoundation'])]) + ["example.i", "example.c"], + extra_link_args=['-framework', 'CoreFoundation'])]) diff --git a/src/sequencer_osx/sequencer_osx.py b/src/sequencer_osx/sequencer_osx.py index bb8228b..cde0408 100644 --- a/src/sequencer_osx/sequencer_osx.py +++ b/src/sequencer_osx/sequencer_osx.py @@ -17,21 +17,21 @@ def _swig_setattr_nondynamic(self,class_type,name,value,static=1): if type(value).__name__ == 'PySwigObject': self.__dict__[name] = value return - method = class_type.__swig_setmethods__.get(name,None) - if method: return method(self,value) - if (not static) or hasattr(self,name): + method = class_type.__swig_setmethods__.get(name, None) + if method: return method(self, value) + if (not static) or hasattr(self, name): self.__dict__[name] = value else: raise AttributeError("You cannot add attributes to %s" % self) -def _swig_setattr(self,class_type,name,value): - return _swig_setattr_nondynamic(self,class_type,name,value,0) +def _swig_setattr(self, class_type, name, value): + return _swig_setattr_nondynamic(self, class_type, name, value, 0) -def _swig_getattr(self,class_type,name): +def _swig_getattr(self, class_type, name): if (name == "thisown"): return self.this.own() - method = class_type.__swig_getmethods__.get(name,None) + method = class_type.__swig_getmethods__.get(name, None) if method: return method(self) - raise AttributeError,name + raise AttributeError(name) def _swig_repr(self): try: strthis = "proxy of " + self.this.__repr__() @@ -40,7 +40,7 @@ def _swig_repr(self): import types try: - _object = types.ObjectType + _object = object _newclass = 1 except AttributeError: class _object : pass diff --git a/src/sequencer_osx/test.py b/src/sequencer_osx/test.py index 97873e0..9ac90ae 100644 --- a/src/sequencer_osx/test.py +++ b/src/sequencer_osx/test.py @@ -1,9 +1,9 @@ import sequencer_osx -print "MIDIGetNumberOfDevices:", sequencer_osx._MIDIGetNumberOfDevices() +print("MIDIGetNumberOfDevices:", sequencer_osx._MIDIGetNumberOfDevices()) client = sequencer_osx._MIDIClientCreate("python") endpoint = sequencer_osx._MIDISourceCreate(client, "python-source") port = sequencer_osx._MIDIOutputPortCreate(client, "python-port") sequencer_osx._MIDIPortConnectSource(port, endpoint) -print client, endpoint, endpoint -raw_input() +print(client, endpoint, endpoint) +input() #sequencer_osx._MIDIClientDispose(handle) diff --git a/src/util.py b/src/util.py index 688730b..33898b0 100644 --- a/src/util.py +++ b/src/util.py @@ -3,7 +3,7 @@ def read_varlen(data): NEXTBYTE = 1 value = 0 while NEXTBYTE: - chr = ord(data.next()) + chr = next(data) # is the hi-bit set? if not (chr & 0x80): # no next BYTE @@ -17,22 +17,22 @@ def read_varlen(data): return value def write_varlen(value): - chr1 = chr(value & 0x7F) + b1 = value & 0x7F value >>= 7 if value: - chr2 = chr((value & 0x7F) | 0x80) + b2 = (value & 0x7F) | 0x80 value >>= 7 if value: - chr3 = chr((value & 0x7F) | 0x80) + b3 = (value & 0x7F) | 0x80 value >>= 7 if value: - chr4 = chr((value & 0x7F) | 0x80) - res = chr4 + chr3 + chr2 + chr1 + b4 = (value & 0x7F) | 0x80 + res = bytes((b4,b3,b2,b1)) else: - res = chr3 + chr2 + chr1 + res = bytes((b3,b2,b1)) else: - res = chr2 + chr1 + res = bytes((b2,b1)) else: - res = chr1 + res = bytes((b1,)) return res diff --git a/test.py b/test.py index a0719dc..b3d5db4 100644 --- a/test.py +++ b/test.py @@ -2,12 +2,12 @@ import pprint x = midi.FileReader() p = midi.read('a.mid') -print p -raw_input() +print(p) +input() midi.write('aa.mid', p) p = midi.read('aa.mid') -print p -raw_input() +print(p) +input() #midi.write('aaa.mid', p) #p = midi.read('aaa.mid') diff --git a/tests/tests.py b/tests/tests.py index 3e49b7c..d66771d 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -5,7 +5,7 @@ class TestMIDI(unittest.TestCase): def test_varlen(self): maxval = 0x0FFFFFFF - for inval in xrange(0, maxval, maxval / 1000): + for inval in range(0, maxval, maxval // 1000): datum = midi.write_varlen(inval) outval = midi.read_varlen(iter(datum)) self.assertEqual(inval, outval)