Skip to content

Commit 7fe10b3

Browse files
committed
Programs are now properties of ChannelEvents.
1 parent 7eb35ea commit 7fe10b3

File tree

1 file changed

+56
-22
lines changed

1 file changed

+56
-22
lines changed

midi.py

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -800,9 +800,10 @@ def __init__(self, **keywords):
800800
Create a new ChannelEvent object.
801801
802802
In addition to the keywords inherited from Event, ChannelEvents also
803-
accept the channel keyword.
803+
accept the channel and program keywords.
804804
"""
805805
self.channel = keywords.pop('channel', None)
806+
self.program = keywords.pop('program', None)
806807
super().__init__(**keywords)
807808

808809
@classmethod
@@ -813,7 +814,7 @@ def _parse(cls, source=None, status=None):
813814
type = status & 0xf0
814815
if type not in ChannelEvent._events:
815816
raise MIDIError(
816-
'Encountered an unkown event: {status:X}.'.format(
817+
'Encountered an unknown event: {status:X}.'.format(
817818
status=status))
818819
event = ChannelEvent._events[type]._parse(source)
819820
event.channel = channel
@@ -1378,16 +1379,24 @@ def parse(source):
13781379
sequence.append(event)
13791380
track += 1
13801381

1381-
def cumulative(event):
1382-
return event.time.cumulative
1383-
sequence.sort(key=cumulative)
1384-
1382+
sequence.sort(key=sequence._meta_sort_key)
1383+
sequence.sort(key=sequence._cumulative_sort_key)
13851384
to_delete = list()
1385+
programs = dict()
13861386
for index in range(len(sequence)):
13871387
event = sequence[index]
13881388
if isinstance(event, (SetTempo, SetTimeSignature)):
13891389
to_delete.append(index)
13901390
sequence.specification.add(event)
1391+
elif isinstance(event, ProgramChange):
1392+
to_delete.append(index)
1393+
programs[(event.track, event.channel)] = event.program
1394+
elif isinstance(event, ChannelEvent):
1395+
try:
1396+
event.program = programs[(event.track, event.channel)]
1397+
except KeyError:
1398+
event.program = Program()
1399+
programs[(event.track, event.channel)] = event.program
13911400
for index in reversed(to_delete):
13921401
del sequence[index]
13931402
return sequence
@@ -1457,27 +1466,50 @@ def offset(self, time):
14571466
event.time += time
14581467
self.specification.offset(time)
14591468

1469+
def events(self):
1470+
event_list = list()
1471+
programs = dict()
1472+
for event in self:
1473+
if isinstance(event, ChannelEvent):
1474+
program = programs.get((event.track, event.channel), None)
1475+
if event.program != program:
1476+
programs[(event.track, event.channel)] = event.program
1477+
event_list.append(ProgramChange(time=event.time,
1478+
program=event.program, track=event.track,
1479+
channel=event.channel))
1480+
return event_list
1481+
14601482
def sort(self, *, key=None, reverse=False):
14611483
if key == None:
1462-
def meta(event):
1463-
if isinstance(event, SetTempo):
1464-
return 0
1465-
elif isinstance(event, SetTimeSignature):
1466-
return 1
1467-
elif isinstance(event, ProgramChange):
1468-
return 2
1469-
else:
1470-
return 3
1471-
def track(event):
1472-
return event.track
1473-
def time(event):
1474-
return event.time
1475-
super().sort(key=meta, reverse=reverse)
1476-
super().sort(key=track, reverse=reverse)
1477-
super().sort(key=time, reverse=reverse)
1484+
super().sort(key=self._meta_sort_key, reverse=reverse)
1485+
super().sort(key=self._track_sort_key, reverse=reverse)
1486+
super().sort(key=self._time_sort_key, reverse=reverse)
14781487
else:
14791488
super().sort(key=key, reverse=False)
14801489

1490+
@staticmethod
1491+
def _meta_sort_key(event):
1492+
if isinstance(event, SetTempo):
1493+
return 0
1494+
elif isinstance(event, SetTimeSignature):
1495+
return 1
1496+
elif isinstance(event, ProgramChange):
1497+
return 2
1498+
else:
1499+
return 3
1500+
1501+
@staticmethod
1502+
def _track_sort_key(event):
1503+
return event.track
1504+
1505+
@staticmethod
1506+
def _time_sort_key(event):
1507+
return event.time
1508+
1509+
@staticmethod
1510+
def _cumulative_sort_key(event):
1511+
return event.time.cumulative
1512+
14811513
def __bytes__(self):
14821514
"""Bytes for writing to a MIDI file."""
14831515
array = bytearray()
@@ -1490,6 +1522,8 @@ def __bytes__(self):
14901522
array.extend(chunk.raw)
14911523

14921524
sequence = type(self)(self)
1525+
sequence.sort()
1526+
sequence.extend(sequence.events())
14931527
sequence.extend(self.specification.events(track=0))
14941528
sequence.sort()
14951529
for track in range(tracks):

0 commit comments

Comments
 (0)