From 867a55fbdab76d3225c07e4ef3a98ac1a8f73e7f Mon Sep 17 00:00:00 2001 From: Matthew Shotton Date: Wed, 6 Jan 2016 17:03:55 +0000 Subject: [PATCH 1/5] added ability to copy/deepcopy events by replacing property() getter/setters with @property decorator and removed __slots__ on some event classes, fixes #60, #40 --- src/events.py | 126 +++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 58 deletions(-) diff --git a/src/events.py b/src/events.py index 24f41eb..8d79e3b 100644 --- a/src/events.py +++ b/src/events.py @@ -111,20 +111,21 @@ def is_event(cls, statusmsg): """ class NoteEvent(Event): - __slots__ = ['pitch', 'velocity'] length = 2 - def get_pitch(self): + @property + def pitch(self): return self.data[0] - def set_pitch(self, val): + @pitch.setter + def pitch(self, val): self.data[0] = val - pitch = property(get_pitch, set_pitch) - def get_velocity(self): + @property + def velocity(self): return self.data[1] - def set_velocity(self, val): + @velocity.setter + def velocity(self, val): self.data[1] = val - velocity = property(get_velocity, set_velocity) class NoteOnEvent(NoteEvent): statusmsg = 0x90 @@ -139,73 +140,77 @@ class AfterTouchEvent(Event): length = 2 name = 'After Touch' - def get_pitch(self): + @property + def pitch(self): return self.data[0] - def set_pitch(self, val): + @pitch.setter + def pitch(self, val): self.data[0] = val - pitch = property(get_pitch, set_pitch) - def get_value(self): + @property + def value(self): return self.data[1] - def set_value(self, val): + @value.setter + def value(self, val): self.data[1] = val - value = property(get_value, set_value) + class ControlChangeEvent(Event): - __slots__ = ['control', 'value'] statusmsg = 0xB0 length = 2 name = 'Control Change' - def set_control(self, val): + @property + def control(self, val): self.data[0] = val - def get_control(self): + @control.setter + def control(self): return self.data[0] - control = property(get_control, set_control) - def set_value(self, val): + @property + def value(self, val): self.data[1] = val - def get_value(self): + @value.setter + def value(self): return self.data[1] - value = property(get_value, set_value) class ProgramChangeEvent(Event): - __slots__ = ['value'] statusmsg = 0xC0 length = 1 name = 'Program Change' - def set_value(self, val): + @property + def value(self, val): self.data[0] = val - def get_value(self): + @value.setter + def value(self): return self.data[0] - value = property(get_value, set_value) class ChannelAfterTouchEvent(Event): - __slots__ = ['value'] statusmsg = 0xD0 length = 1 name = 'Channel After Touch' - def set_value(self, val): + @property + def value(self, val): self.data[1] = val - def get_value(self): + @value.setter + def value(self): return self.data[1] - value = property(get_value, set_value) class PitchWheelEvent(Event): - __slots__ = ['pitch'] statusmsg = 0xE0 length = 2 name = 'Pitch Wheel' - def get_pitch(self): + @property + def pitch(self): return ((self.data[1] << 7) | self.data[0]) - 0x2000 - def set_pitch(self, pitch): + @pitch.setter + def pitch(self, pitch): value = pitch + 0x2000 self.data[0] = value & 0x7F self.data[1] = (value >> 7) & 0x7F - pitch = property(get_pitch, set_pitch) class SysexEvent(Event): statusmsg = 0xF0 @@ -302,77 +307,82 @@ class EndOfTrackEvent(MetaEvent): metacommand = 0x2F class SetTempoEvent(MetaEvent): - __slots__ = ['bpm', 'mpqn'] name = 'Set Tempo' metacommand = 0x51 length = 3 - def set_bpm(self, bpm): + @property + def bpm(self, bpm): self.mpqn = int(float(6e7) / bpm) - def get_bpm(self): + @bpm.setter + def bpm(self): return float(6e7) / self.mpqn - bpm = property(get_bpm, set_bpm) - def get_mpqn(self): + @property + def mpqn(self): assert(len(self.data) == 3) vals = [self.data[x] << (16 - (8 * x)) for x in xrange(3)] return sum(vals) - def set_mpqn(self, val): + @mpqn.setter + def mpqn(self, val): self.data = [(val >> (16 - (8 * x)) & 0xFF) for x in range(3)] - mpqn = property(get_mpqn, set_mpqn) class SmpteOffsetEvent(MetaEvent): name = 'SMPTE Offset' metacommand = 0x54 class TimeSignatureEvent(MetaEvent): - __slots__ = ['numerator', 'denominator', 'metronome', 'thirtyseconds'] name = 'Time Signature' metacommand = 0x58 length = 4 - def get_numerator(self): + @property + def numerator(self): return self.data[0] - def set_numerator(self, val): + @numerator.setter + def numerator(self, val): self.data[0] = val - numerator = property(get_numerator, set_numerator) - def get_denominator(self): + @property + def denominator(self): return 2 ** self.data[1] - def set_denominator(self, val): + @denominator.setter + def denominator(self, val): self.data[1] = int(math.log(val, 2)) - denominator = property(get_denominator, set_denominator) - def get_metronome(self): + @property + def metronome(self): return self.data[2] - def set_metronome(self, val): + @metronome.setter + def metronome(self, val): self.data[2] = val - metronome = property(get_metronome, set_metronome) - def get_thirtyseconds(self): + @property + def thirtyseconds(self): return self.data[3] - def set_thirtyseconds(self, val): + @thirtyseconds.setter + def thirtyseconds(self, val): self.data[3] = val - thirtyseconds = property(get_thirtyseconds, set_thirtyseconds) class KeySignatureEvent(MetaEvent): - __slots__ = ['alternatives', 'minor'] name = 'Key Signature' metacommand = 0x59 length = 2 - def get_alternatives(self): + @property + def alternatives(self): d = self.data[0] return d - 256 if d > 127 else d - def set_alternatives(self, val): + @alternatives.setter + def alternatives(self, val): self.data[0] = 256 + val if val < 0 else val - alternatives = property(get_alternatives, set_alternatives) - def get_minor(self): + @property + def minor(self): return self.data[1] + @minor.setter def set_minor(self, val): self.data[1] = val - minor = property(get_minor, set_minor) class SequencerSpecificEvent(MetaEvent): name = 'Sequencer Specific' From 5a2efe49f13d4918899c5b38cf3fcc1f5d43bc56 Mon Sep 17 00:00:00 2001 From: Matthew Shotton Date: Thu, 7 Jan 2016 17:06:34 +0000 Subject: [PATCH 2/5] fixed passing text into instantiation of anything subclassed from MetaEventWithText --- src/events.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/events.py b/src/events.py index 8d79e3b..d64b97e 100644 --- a/src/events.py +++ b/src/events.py @@ -231,6 +231,8 @@ def __init__(self, **kw): super(MetaEventWithText, self).__init__(**kw) if 'text' not in kw: self.text = ''.join(chr(datum) for datum in self.data) + else: + self.data = [ord(datum) for datum in self.text] def __repr__(self): return self.__baserepr__(['text']) From a32feda724ab3f160cb9b9eed7a92df5756bb9c9 Mon Sep 17 00:00:00 2001 From: Matthew Shotton Date: Tue, 12 Jan 2016 17:36:37 +0000 Subject: [PATCH 3/5] made events hashable so they can be used as dictionary keys --- src/events.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/events.py b/src/events.py index d64b97e..b1b5a58 100644 --- a/src/events.py +++ b/src/events.py @@ -46,6 +46,13 @@ def __cmp__(self, other): elif self.tick > other.tick: return 1 return cmp(self.data, other.data) + def __hash__(self): + h = 0 + for i, datum in enumerate(self.data): + h += datum << i*8 + h += (self.tick << len(self.data)*8) + return h + def __baserepr__(self, keys=[]): keys = ['tick'] + keys + ['data'] body = [] From f319ce97d36b088b3d95945bfee126903720aee9 Mon Sep 17 00:00:00 2001 From: Matthew Shotton Date: Fri, 19 Feb 2016 20:58:24 +0000 Subject: [PATCH 4/5] fixed bpm setter --- src/events.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/events.py b/src/events.py index b1b5a58..9661a83 100644 --- a/src/events.py +++ b/src/events.py @@ -321,11 +321,11 @@ class SetTempoEvent(MetaEvent): length = 3 @property - def bpm(self, bpm): - self.mpqn = int(float(6e7) / bpm) - @bpm.setter def bpm(self): return float(6e7) / self.mpqn + @bpm.setter + def bpm(self, bpm): + self.mpqn = int(float(6e7) / bpm) @property def mpqn(self): From 98e8f167b7f3437ad8616fc45d86b729c7722776 Mon Sep 17 00:00:00 2001 From: Matthew Shotton Date: Fri, 19 Feb 2016 21:02:06 +0000 Subject: [PATCH 5/5] fixed setter/property swap in a bunch of places --- src/events.py | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/events.py b/src/events.py index 9661a83..3bbf39c 100644 --- a/src/events.py +++ b/src/events.py @@ -166,32 +166,37 @@ class ControlChangeEvent(Event): statusmsg = 0xB0 length = 2 name = 'Control Change' - + @property - def control(self, val): - self.data[0] = val - @control.setter def control(self): return self.data[0] - + + @control.setter + def control(self, val): + self.data[0] = val + @property - def value(self, val): - self.data[1] = val - @value.setter def value(self): return self.data[1] + @value.setter + def value(self, val): + self.data[1] = val + + class ProgramChangeEvent(Event): statusmsg = 0xC0 length = 1 name = 'Program Change' - + @property - def value(self, val): - self.data[0] = val - @value.setter def value(self): return self.data[0] + + @value.setter + def value(self, val): + self.data[0] = val + class ChannelAfterTouchEvent(Event): statusmsg = 0xD0 @@ -199,12 +204,14 @@ class ChannelAfterTouchEvent(Event): name = 'Channel After Touch' @property - def value(self, val): - self.data[1] = val - @value.setter def value(self): return self.data[1] + @value.setter + def value(self, val): + self.data[1] = val + + class PitchWheelEvent(Event): statusmsg = 0xE0 length = 2