# 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
from mididings.extra.per_channel import PerChannel as _PerChannel

def LimitPolyphony(max_polyphony, remove_oldest=True):
    """
    Limit the "MIDI polyphony".

    :param max_polyphony:
        The maximum number of simultaneous notes.

    :param remove_oldest:
        If true, the oldest notes will be stopped when the maximum polyphony
        is exceeded.
        If false, no new notes are accepted while *max_polyphony* notes
        are already held.

    Note that the actual polyphony of a connected synthesizer can still be
    higher than the limit set here, e.g. due to a long release phase.
    """
    return (_m.Filter(_m.NOTE) %
        _m.Process(_PerChannel(
            lambda: _LimitPolyphony(max_polyphony, remove_oldest))))


def MakeMonophonic():
    """
    Make the MIDI signal monophonic, i.e. only one note can be played at
    any given time.
    When one note is released while another is still held (but silent),
    the previous one will be retriggered.
    """
    return (_m.Filter(_m.NOTE) %

# 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/polyphony.py
import mididings as _m
import mididings.event as _event
from mididings.extra.per_channel import PerChannel as _PerChannel


def LimitPolyphony(max_polyphony, remove_oldest=True):
    """
    Limit the "MIDI polyphony".

    :param max_polyphony:
        The maximum number of simultaneous notes.

    :param remove_oldest:
        If true, the oldest notes will be stopped when the maximum polyphony
        is exceeded.
        If false, no new notes are accepted while *max_polyphony* notes
        are already held.

    Note that the actual polyphony of a connected synthesizer can still be
    higher than the limit set here, e.g. due to a long release phase.
    """
    return (_m.Filter(_m.NOTE) %
        _m.Process(_PerChannel(
            lambda: _LimitPolyphony(max_polyphony, remove_oldest))))


def MakeMonophonic():
    """
    Make the MIDI signal monophonic, i.e. only one note can be played at
    any given time.
    When one note is released while another is still held (but silent),
    the previous one will be retriggered.
    """
    return (_m.Filter(_m.NOTE) %

        _m.Process(_PerChannel(_MakeMonophonic)))