# Path: mididings/units/base.py
# class _Unit(object):
#     """
#     Wrapper class for all units.
#     """
#     def __init__(self, unit):
#         self.unit = unit
# 
#     def __rshift__(self, other):
#         """
#         Connect units in series (operator >>).
#         """
#         if not isinstance(other, _UNIT_TYPES):
#             return NotImplemented
#         return _join_units(_Chain, self, other)
# 
#     def __rrshift__(self, other):
#         """
#         Connect units in series (operator >>).
#         """
#         if not isinstance(other, _UNIT_TYPES):
#             return NotImplemented
#         return _join_units(_Chain, other, self)
# 
#     def __floordiv__(self, other):
#         """
#         Connect units in parallel (operator //).
#         """
#         if not isinstance(other, _UNIT_TYPES):
#             return NotImplemented
#         return _join_units(_Fork, self, other)
# 
#     def __rfloordiv__(self, other):
#         """
#         Connect units in parallel (operator //).
#         """
#         if not isinstance(other, _UNIT_TYPES):
#             return NotImplemented
#         return _join_units(_Fork, other, self)
# 
#     def __pos__(self):
#         """
#         Apply to duplicate (unary operator +)
#         """
#         return self.add()
# 
#     def add(self):
#         return Fork([ Pass(), self ])
# 
#     def __repr__(self):
#         return _unitrepr.unit_to_string(self)
# 
# @_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)
# 
# @_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)
# 
# _UNIT_TYPES = (_Unit, list, dict, _constants._EventType)
# 
# Path: mididings/units/generators.py
# @_overload.partial((_constants.EVENT_PORT, _constants.EVENT_CHANNEL))
# @_unitrepr.accept(_util.port_number_ref, _util.channel_number_ref,
#                   _util.program_number_ref)
# def Program(port, channel, program):
#     """
#     Program(program)
#     Program(port, channel, program)
# 
#     Create a program change event, replacing the incoming event.
#     """
#     return _Unit(_mididings.Generator(
#         _constants.PROGRAM,
#         _util.actual_ref(port),
#         _util.actual_ref(channel),
#         0,
#         _util.actual_ref(program)
#     ))
# 
# @_overload.partial((_constants.EVENT_PORT, _constants.EVENT_CHANNEL))
# @_unitrepr.accept(_util.port_number_ref, _util.channel_number_ref,
#                   _util.ctrl_number_ref, _util.ctrl_value_ref)
# def Ctrl(port, channel, ctrl, value):
#     """
#     Ctrl(ctrl, value)
#     Ctrl(port, channel, ctrl, value)
# 
#     Create a control change event, replacing the incoming event.
#     """
#     return _Unit(_mididings.Generator(
#         _constants.CTRL,
#         _util.actual_ref(port),
#         _util.actual_ref(channel),
#         ctrl,
#         value
#     ))
# 
# Path: mididings/units/modifiers.py
# @_unitrepr.accept(_util.port_number)
# def Port(port):
#     """
#     Port(port)
# 
#     Change the event's port number.
#     """
#     return _Unit(_mididings.Port(_util.actual(port)))
# 
# @_unitrepr.accept(_util.channel_number)
# def Channel(channel):
#     """
#     Channel(channel)
# 
#     Change the event's channel number.
#     """
#     return _Unit(_mididings.Channel(_util.actual(channel)))


from mididings.units.base import _Unit, Fork, Chain, _UNIT_TYPES
from mididings.units.generators import Program, Ctrl
from mididings.units.modifiers import Port, Channel
import mididings.unitrepr as _unitrepr
import mididings.util as _util
import functools as _functools
import copy as _copy
    the *ctrls* argument can contain a mapping from controller numbers to
    their respective values.

    If *port* or *channel* are ``None``, events will be routed to the first
    port/channel.
    """
    if port is None:
        port = _util.offset(0)
    if channel is None:
        channel = _util.offset(0)

    if isinstance(program, tuple):
        bank, program = program
    else:
        bank = None

    init = []

    if bank is not None:
        init.append(Ctrl(port, channel, 0, bank // 128))
        init.append(Ctrl(port, channel, 32, bank % 128))

    if program is not None:
        init.append(Program(port, channel, program))

    if volume is not None:
        init.append(Ctrl(port, channel, 7, volume))
    if pan is not None:
        init.append(Ctrl(port, channel, 10, pan))
    if expression is not None:

# Path: mididings/units/base.py
# class _Unit(object):
#     """
#     Wrapper class for all units.
#     """
#     def __init__(self, unit):
#         self.unit = unit
# 
#     def __rshift__(self, other):
#         """
#         Connect units in series (operator >>).
#         """
#         if not isinstance(other, _UNIT_TYPES):
#             return NotImplemented
#         return _join_units(_Chain, self, other)
# 
#     def __rrshift__(self, other):
#         """
#         Connect units in series (operator >>).
#         """
#         if not isinstance(other, _UNIT_TYPES):
#             return NotImplemented
#         return _join_units(_Chain, other, self)
# 
#     def __floordiv__(self, other):
#         """
#         Connect units in parallel (operator //).
#         """
#         if not isinstance(other, _UNIT_TYPES):
#             return NotImplemented
#         return _join_units(_Fork, self, other)
# 
#     def __rfloordiv__(self, other):
#         """
#         Connect units in parallel (operator //).
#         """
#         if not isinstance(other, _UNIT_TYPES):
#             return NotImplemented
#         return _join_units(_Fork, other, self)
# 
#     def __pos__(self):
#         """
#         Apply to duplicate (unary operator +)
#         """
#         return self.add()
# 
#     def add(self):
#         return Fork([ Pass(), self ])
# 
#     def __repr__(self):
#         return _unitrepr.unit_to_string(self)
# 
# @_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)
# 
# @_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)
# 
# _UNIT_TYPES = (_Unit, list, dict, _constants._EventType)
# 
# Path: mididings/units/generators.py
# @_overload.partial((_constants.EVENT_PORT, _constants.EVENT_CHANNEL))
# @_unitrepr.accept(_util.port_number_ref, _util.channel_number_ref,
#                   _util.program_number_ref)
# def Program(port, channel, program):
#     """
#     Program(program)
#     Program(port, channel, program)
# 
#     Create a program change event, replacing the incoming event.
#     """
#     return _Unit(_mididings.Generator(
#         _constants.PROGRAM,
#         _util.actual_ref(port),
#         _util.actual_ref(channel),
#         0,
#         _util.actual_ref(program)
#     ))
# 
# @_overload.partial((_constants.EVENT_PORT, _constants.EVENT_CHANNEL))
# @_unitrepr.accept(_util.port_number_ref, _util.channel_number_ref,
#                   _util.ctrl_number_ref, _util.ctrl_value_ref)
# def Ctrl(port, channel, ctrl, value):
#     """
#     Ctrl(ctrl, value)
#     Ctrl(port, channel, ctrl, value)
# 
#     Create a control change event, replacing the incoming event.
#     """
#     return _Unit(_mididings.Generator(
#         _constants.CTRL,
#         _util.actual_ref(port),
#         _util.actual_ref(channel),
#         ctrl,
#         value
#     ))
# 
# Path: mididings/units/modifiers.py
# @_unitrepr.accept(_util.port_number)
# def Port(port):
#     """
#     Port(port)
# 
#     Change the event's port number.
#     """
#     return _Unit(_mididings.Port(_util.actual(port)))
# 
# @_unitrepr.accept(_util.channel_number)
# def Channel(channel):
#     """
#     Channel(channel)
# 
#     Change the event's channel number.
#     """
#     return _Unit(_mididings.Channel(_util.actual(channel)))


# Path: mididings/units/init.py
from mididings.units.base import _Unit, Fork, Chain, _UNIT_TYPES
from mididings.units.generators import Program, Ctrl
from mididings.units.modifiers import Port, Channel
import mididings.unitrepr as _unitrepr
import mididings.util as _util
import functools as _functools
import copy as _copy

    the *ctrls* argument can contain a mapping from controller numbers to
    their respective values.

    If *port* or *channel* are ``None``, events will be routed to the first
    port/channel.
    """
    if port is None:
        port = _util.offset(0)
    if channel is None:
        channel = _util.offset(0)

    if isinstance(program, tuple):
        bank, program = program
    else:
        bank = None

    init = []

    if bank is not None:
        init.append(Ctrl(port, channel, 0, bank // 128))
        init.append(Ctrl(port, channel, 32, bank % 128))

    if program is not None:
        init.append(Program(port, channel, program))

    if volume is not None:
        init.append(Ctrl(port, channel, 7, volume))
    if pan is not None:
        init.append(Ctrl(port, channel, 10, pan))
    if expression is not None:

        init.append(Ctrl(port, channel, 11, expression))