# Path: mididings/extra/per_channel.py
# class PerChannel(object):
#     """
#     Utility class, usable with Process() and Call(), that delegates events
#     to different instances of the same class, using one instance per
#     channel/port combination.
#     New instances are created as needed, using the given factory function,
#     when the first event with a new channel/port arrives.
#     """
#     def __init__(self, factory):
#         self.channel_proc = {}
#         self.factory = factory
# 
#     def __call__(self, ev):
#         k = (ev.port, ev.channel)
#         if k not in self.channel_proc:
#             self.channel_proc[k] = self.factory()
#         return self.channel_proc[k](ev)


import mididings as _m
import mididings.event as _event
import mididings.util as _util
from mididings.extra.per_channel import PerChannel as _PerChannel
    def __init__(self, polyphonic, reset):
        self.polyphonic = polyphonic
        self.reset = _util.note_number(reset) if reset is not None else None
        self.notes = []

    def __call__(self, ev):
        if ev.type == _m.NOTEON:
            if ev.note == self.reset:
                # reset all notes
                r = [_event.NoteOffEvent(ev.port, ev.channel, x, 0)
                        for x in self.notes]
                self.notes = []
                return r

            if self.polyphonic:
                if ev.note not in self.notes:
                    # turn note on
                    self.notes.append(ev.note)
                    return ev
                else:
                    # turn note off
                    self.notes.remove(ev.note)
                    return _event.NoteOffEvent(ev.port, ev.channel, ev.note, 0)
            else:
                # monophonic: turn off previous note, play new note
                if len(self.notes):
                    r = [_event.NoteOffEvent(
                                    ev.port, ev.channel, self.notes[0], 0)]
                else:
                    r = []

# Path: mididings/extra/per_channel.py
# class PerChannel(object):
#     """
#     Utility class, usable with Process() and Call(), that delegates events
#     to different instances of the same class, using one instance per
#     channel/port combination.
#     New instances are created as needed, using the given factory function,
#     when the first event with a new channel/port arrives.
#     """
#     def __init__(self, factory):
#         self.channel_proc = {}
#         self.factory = factory
# 
#     def __call__(self, ev):
#         k = (ev.port, ev.channel)
#         if k not in self.channel_proc:
#             self.channel_proc[k] = self.factory()
#         return self.channel_proc[k](ev)


# Path: mididings/extra/latch.py
import mididings as _m
import mididings.event as _event
import mididings.util as _util
from mididings.extra.per_channel import PerChannel as _PerChannel

    def __init__(self, polyphonic, reset):
        self.polyphonic = polyphonic
        self.reset = _util.note_number(reset) if reset is not None else None
        self.notes = []

    def __call__(self, ev):
        if ev.type == _m.NOTEON:
            if ev.note == self.reset:
                # reset all notes
                r = [_event.NoteOffEvent(ev.port, ev.channel, x, 0)
                        for x in self.notes]
                self.notes = []
                return r

            if self.polyphonic:
                if ev.note not in self.notes:
                    # turn note on
                    self.notes.append(ev.note)
                    return ev
                else:
                    # turn note off
                    self.notes.remove(ev.note)
                    return _event.NoteOffEvent(ev.port, ev.channel, ev.note, 0)
            else:
                # monophonic: turn off previous note, play new note
                if len(self.notes):
                    r = [_event.NoteOffEvent(
                                    ev.port, ev.channel, self.notes[0], 0)]
                else:
                    r = []

                self.notes = [ev.note]