# Path: mididings/units/base.py
# @_arguments.accept([_UNIT_TYPES], add_varargs=True)
# def Chain(units):
#     """
#     Units connected in series.
#     """
#     # handle a single list argument differently for backward compatibility
#     if len(units) == 1 and type(units[0]) == list:
#         units = units[0]
# 
#     return _Chain(units)
# 
# @_arguments.accept([_UNIT_TYPES], add_varargs=True,
#                    kwargs={'remove_duplicates': (True, False, None)})
# def Fork(units, **kwargs):
#     """
#     Units connected in parallel.
#     """
#     remove_duplicates = (kwargs['remove_duplicates']
#                             if 'remove_duplicates' in kwargs else None)
# 
#     # handle a single list argument differently for backward compatibility
#     if len(units) == 1 and type(units[0]) == list:
#         units = units[0]
# 
#     return _Fork(units, remove_duplicates)
# 
# _UNIT_TYPES = (_Unit, list, dict, _constants._EventType)
# 
# Path: mididings/units/filters.py
# @_unitrepr.accept(_arguments.flatten(_util.port_number), add_varargs=True)
# def PortFilter(ports):
#     """
#     PortFilter(ports, ...)
# 
#     Filter events by port name or number. The *ports* argument can be a single
#     port or a list of multiple ports.
#     """
#     return _Filter(_mididings.PortFilter(map(_util.actual, ports)))
# 
# @_unitrepr.accept(_arguments.flatten(_util.channel_number), add_varargs=True)
# def ChannelFilter(channels):
#     """
#     ChannelFilter(channels, ...)
# 
#     Filter events by channel number. The *channels* argument can be a single
#     channel number or a list of multiple channel numbers.
#     System events (which don't carry channel information) are discarded.
#     """
#     return _Filter(_mididings.ChannelFilter(map(_util.actual, channels)))
# 
# @_overload.mark(
#     """
#     KeyFilter(note_range)
#     KeyFilter(lower, upper)
#     KeyFilter(lower=...)
#     KeyFilter(upper=...)
#     KeyFilter(notes=...)
# 
#     Filter note events by key (note number or note range). All other events
#     are let through.
#     The last form expects its argument to be a list of individual note names
#     or numbers.
#     """
# )
# @_unitrepr.accept(_util.note_range)
# def KeyFilter(note_range):
#     return _Filter(_mididings.KeyFilter(note_range[0], note_range[1], []))
# 
# @_overload.mark(
#     """
#     VelocityFilter(value)
#     VelocityFilter(lower=...)
#     VelocityFilter(upper=...)
#     VelocityFilter(lower, upper)
# 
#     Filter note-on events by velocity. All other events are let through.
#     """
# )
# @_unitrepr.accept(_util.velocity_value)
# def VelocityFilter(value):
#     return _Filter(_mididings.VelocityFilter(value, value + 1))
# 
# @_unitrepr.accept(_arguments.flatten(_util.ctrl_number), add_varargs=True)
# def CtrlFilter(ctrls):
#     """
#     CtrlFilter(ctrls, ...)
# 
#     Filter control change events by controller number. The *ctrls* argument
#     can be a single controller or a list of multiple controller numbers.
#     All other events are discarded.
#     """
#     return _Filter(_mididings.CtrlFilter(ctrls))
# 
# @_overload.mark(
#     """
#     CtrlValueFilter(value)
#     CtrlValueFilter(lower=...)
#     CtrlValueFilter(upper=...)
#     CtrlValueFilter(lower, upper)
# 
#     Filter control change events by controller value. All other events are
#     discarded.
#     """
# )
# @_unitrepr.accept(_util.ctrl_value)
# def CtrlValueFilter(value):
#     return _Filter(_mididings.CtrlValueFilter(value, value + 1))
# 
# @_unitrepr.accept(_arguments.flatten(_util.program_number), add_varargs=True)
# def ProgramFilter(programs):
#     """
#     ProgramFilter(programs, ...)
# 
#     Filter program change events by program number. The *programs* argument
#     can be a single program number or a list of program numbers.
#     All other events are discarded.
#     """
#     return _Filter(_mididings.ProgramFilter(map(_util.actual, programs)))
# 
# @_overload.mark(
#     r"""
#     SysExFilter(sysex)
#     SysExFilter(manufacturer=...)
# 
#     Filter system exclusive events by the data they contain, specified as a
#     string or as a sequence of integers.
#     If *sysex* does not end with ``F7``, partial matches that start with the
#     given data bytes are accepted.
# 
#     Alternatively, a sysex manufacturer id can be specified, which may be
#     either a string or a sequence of integers, with a length of one or three
#     bytes.
# 
#     All non-sysex events are discarded.
#     """
# )
# @_unitrepr.accept(_functools.partial(_util.sysex_data, allow_partial=True))
# def SysExFilter(sysex):
#     partial = (sysex[-1] != '\xf7')
#     return _Filter(_mididings.SysExFilter(sysex, partial))


from mididings.units.base import Chain, Fork, _UNIT_TYPES
from mididings.units.filters import (
        PortFilter, ChannelFilter, KeyFilter, VelocityFilter,
        CtrlFilter, CtrlValueFilter, ProgramFilter, SysExFilter)
import mididings.overload as _overload
import mididings.arguments as _arguments
import mididings.util as _util
    _arguments.nullable(_arguments.flatten(_util.ctrl_number, tuple)):
        _UNIT_TYPES
})
def CtrlSplit(mapping):
    """
    CtrlSplit(mapping)

    Split events by controller number, with *mapping* being a dictionary of
    the form ``{ctrls: patch, ...}``.
    Non-control-change events are discarded.
    """
    return _make_split(CtrlFilter, mapping)


@_overload.mark(
    """
    CtrlValueSplit(threshold, patch_lower, patch_upper)
    CtrlValueSplit(mapping)

    Split events by controller value.

    The first version splits at a single threshold. The second version allows
    an arbitrary number of (possibly overlapping) value ranges, with *mapping*
    being a dictionary of the form ``{value: patch, ...}`` or
    ``{(lower, upper): patch, ...}``.

    Non-control-change events are discarded.

    """
)

# Path: mididings/units/base.py
# @_arguments.accept([_UNIT_TYPES], add_varargs=True)
# def Chain(units):
#     """
#     Units connected in series.
#     """
#     # handle a single list argument differently for backward compatibility
#     if len(units) == 1 and type(units[0]) == list:
#         units = units[0]
# 
#     return _Chain(units)
# 
# @_arguments.accept([_UNIT_TYPES], add_varargs=True,
#                    kwargs={'remove_duplicates': (True, False, None)})
# def Fork(units, **kwargs):
#     """
#     Units connected in parallel.
#     """
#     remove_duplicates = (kwargs['remove_duplicates']
#                             if 'remove_duplicates' in kwargs else None)
# 
#     # handle a single list argument differently for backward compatibility
#     if len(units) == 1 and type(units[0]) == list:
#         units = units[0]
# 
#     return _Fork(units, remove_duplicates)
# 
# _UNIT_TYPES = (_Unit, list, dict, _constants._EventType)
# 
# Path: mididings/units/filters.py
# @_unitrepr.accept(_arguments.flatten(_util.port_number), add_varargs=True)
# def PortFilter(ports):
#     """
#     PortFilter(ports, ...)
# 
#     Filter events by port name or number. The *ports* argument can be a single
#     port or a list of multiple ports.
#     """
#     return _Filter(_mididings.PortFilter(map(_util.actual, ports)))
# 
# @_unitrepr.accept(_arguments.flatten(_util.channel_number), add_varargs=True)
# def ChannelFilter(channels):
#     """
#     ChannelFilter(channels, ...)
# 
#     Filter events by channel number. The *channels* argument can be a single
#     channel number or a list of multiple channel numbers.
#     System events (which don't carry channel information) are discarded.
#     """
#     return _Filter(_mididings.ChannelFilter(map(_util.actual, channels)))
# 
# @_overload.mark(
#     """
#     KeyFilter(note_range)
#     KeyFilter(lower, upper)
#     KeyFilter(lower=...)
#     KeyFilter(upper=...)
#     KeyFilter(notes=...)
# 
#     Filter note events by key (note number or note range). All other events
#     are let through.
#     The last form expects its argument to be a list of individual note names
#     or numbers.
#     """
# )
# @_unitrepr.accept(_util.note_range)
# def KeyFilter(note_range):
#     return _Filter(_mididings.KeyFilter(note_range[0], note_range[1], []))
# 
# @_overload.mark(
#     """
#     VelocityFilter(value)
#     VelocityFilter(lower=...)
#     VelocityFilter(upper=...)
#     VelocityFilter(lower, upper)
# 
#     Filter note-on events by velocity. All other events are let through.
#     """
# )
# @_unitrepr.accept(_util.velocity_value)
# def VelocityFilter(value):
#     return _Filter(_mididings.VelocityFilter(value, value + 1))
# 
# @_unitrepr.accept(_arguments.flatten(_util.ctrl_number), add_varargs=True)
# def CtrlFilter(ctrls):
#     """
#     CtrlFilter(ctrls, ...)
# 
#     Filter control change events by controller number. The *ctrls* argument
#     can be a single controller or a list of multiple controller numbers.
#     All other events are discarded.
#     """
#     return _Filter(_mididings.CtrlFilter(ctrls))
# 
# @_overload.mark(
#     """
#     CtrlValueFilter(value)
#     CtrlValueFilter(lower=...)
#     CtrlValueFilter(upper=...)
#     CtrlValueFilter(lower, upper)
# 
#     Filter control change events by controller value. All other events are
#     discarded.
#     """
# )
# @_unitrepr.accept(_util.ctrl_value)
# def CtrlValueFilter(value):
#     return _Filter(_mididings.CtrlValueFilter(value, value + 1))
# 
# @_unitrepr.accept(_arguments.flatten(_util.program_number), add_varargs=True)
# def ProgramFilter(programs):
#     """
#     ProgramFilter(programs, ...)
# 
#     Filter program change events by program number. The *programs* argument
#     can be a single program number or a list of program numbers.
#     All other events are discarded.
#     """
#     return _Filter(_mididings.ProgramFilter(map(_util.actual, programs)))
# 
# @_overload.mark(
#     r"""
#     SysExFilter(sysex)
#     SysExFilter(manufacturer=...)
# 
#     Filter system exclusive events by the data they contain, specified as a
#     string or as a sequence of integers.
#     If *sysex* does not end with ``F7``, partial matches that start with the
#     given data bytes are accepted.
# 
#     Alternatively, a sysex manufacturer id can be specified, which may be
#     either a string or a sequence of integers, with a length of one or three
#     bytes.
# 
#     All non-sysex events are discarded.
#     """
# )
# @_unitrepr.accept(_functools.partial(_util.sysex_data, allow_partial=True))
# def SysExFilter(sysex):
#     partial = (sysex[-1] != '\xf7')
#     return _Filter(_mididings.SysExFilter(sysex, partial))


# Path: mididings/units/splits.py
from mididings.units.base import Chain, Fork, _UNIT_TYPES
from mididings.units.filters import (
        PortFilter, ChannelFilter, KeyFilter, VelocityFilter,
        CtrlFilter, CtrlValueFilter, ProgramFilter, SysExFilter)
import mididings.overload as _overload
import mididings.arguments as _arguments
import mididings.util as _util

    _arguments.nullable(_arguments.flatten(_util.ctrl_number, tuple)):
        _UNIT_TYPES
})
def CtrlSplit(mapping):
    """
    CtrlSplit(mapping)

    Split events by controller number, with *mapping* being a dictionary of
    the form ``{ctrls: patch, ...}``.
    Non-control-change events are discarded.
    """
    return _make_split(CtrlFilter, mapping)


@_overload.mark(
    """
    CtrlValueSplit(threshold, patch_lower, patch_upper)
    CtrlValueSplit(mapping)

    Split events by controller value.

    The first version splits at a single threshold. The second version allows
    an arbitrary number of (possibly overlapping) value ranges, with *mapping*
    being a dictionary of the form ``{value: patch, ...}`` or
    ``{(lower, upper): patch, ...}``.

    Non-control-change events are discarded.

    """
)

@_arguments.accept(_util.ctrl_limit, _UNIT_TYPES, _UNIT_TYPES)