Beispiel #1
0
def _start_backend():
    global _TheBackend
    if _TheBackend is None:
        _TheBackend = _mididings.create_backend(
            _setup.get_config('backend'), _setup.get_config('client_name'),
            _setup._in_portnames, _setup._out_portnames)
        if _TheBackend:
            _TheBackend.connect_ports(_setup._in_port_connections,
                                      _setup._out_port_connections)
Beispiel #2
0
def _start_backend():
    global _TheBackend
    if _TheBackend is None:
        _TheBackend = _mididings.create_backend(
            _setup.get_config('backend'),
            _setup.get_config('client_name'),
            _setup._in_portnames,
            _setup._out_portnames
        )
        if _TheBackend:
            _TheBackend.connect_ports(_setup._in_port_connections,
                                      _setup._out_port_connections)
Beispiel #3
0
    def run(self):
        self._quit = _threading.Event()

        # delay before actually sending any midi data (give qjackctl
        # patchbay time to react...)
        self._start_delay()

        self._call_hooks('on_start')

        initial_scene, initial_subscene = \
            self._parse_scene_number(_setup.get_config('initial_scene'))

        # start the actual event processing
        self.start(initial_scene, initial_subscene)

        try:
            # wait() with no timeout also blocks KeyboardInterrupt, but
            # a very long timeout doesn't. weird...
            while not self._quit.isSet():
                self._quit.wait(86400)
        except KeyboardInterrupt:
            pass
        finally:
            self._call_hooks('on_exit')
            global _TheEngine
            _TheEngine = None
Beispiel #4
0
 def _start_delay(self):
     delay = _setup.get_config('start_delay')
     if delay is not None:
         if delay > 0:
             _time.sleep(delay)
         else:
             raw_input("press enter to start midi processing...")
Beispiel #5
0
def note_number(note, allow_end=False):
    """
    note_number(note)

    Convert note name to note number.

    :param note:
        any valid :ref:`note description <notes>` (name or number).
    :return:
        MIDI note number.
    """
    if isinstance(note, int):
        r = note
    elif isinstance(note, str):
        note = note.lower()
        # find first digit
        for i in range(len(note)):
            if note[i].isdigit() or note[i] == '-':
                break
        try:
            name = note[:i]
            octave = int(note[i:])
            r = (_NOTE_NUMBERS[name] +
                 (octave + _setup.get_config('octave_offset')) * 12)
        except Exception:
            raise ValueError("invalid note name '%s'" % note)
    else:
        raise TypeError("note must be an integer or string")

    end = 128 if not allow_end else 129
    if not (0 <= r < end):
        raise ValueError("note number %d is out of range" % r)
    return r
Beispiel #6
0
    def run(self):
        self._quit = _threading.Event()

        # delay before actually sending any midi data (give qjackctl
        # patchbay time to react...)
        self._start_delay()

        self._call_hooks('on_start')

        initial_scene, initial_subscene = \
            self._parse_scene_number(_setup.get_config('initial_scene'))

        # start the actual event processing
        self.start(initial_scene, initial_subscene)

        try:
            # wait() with no timeout also blocks KeyboardInterrupt, but
            # a very long timeout doesn't. weird...
            while not self._quit.isSet():
                self._quit.wait(86400)
        except KeyboardInterrupt:
            pass
        finally:
            self._call_hooks('on_exit')
            global _TheEngine
            _TheEngine = None
Beispiel #7
0
 def _start_delay(self):
     delay = _setup.get_config('start_delay')
     if delay is not None:
         if delay > 0:
             _time.sleep(delay)
         else:
             raw_input("press enter to start midi processing...")
Beispiel #8
0
 def run_patch(self, patch, events):
     """
     Run the given events through the given patch, return the list of
     resulting events.
     """
     r = self.run_scenes({setup.get_config('data_offset'): patch}, events)
     return list(itertools.chain(*r))
Beispiel #9
0
 def run_patch(self, patch, events):
     """
     Run the given events through the given patch, return the list of
     resulting events.
     """
     r = self.run_scenes({ setup.get_config('data_offset'): patch }, events)
     return list(itertools.chain(*r))
Beispiel #10
0
def note_number(note, allow_end=False):
    """
    note_number(note)

    Convert note name to note number.

    :param note:
        any valid :ref:`note description <notes>` (name or number).
    :return:
        MIDI note number.
    """
    if isinstance(note, int):
        r = note
    elif isinstance(note, str):
        note = note.lower()
        # find first digit
        for i in range(len(note)):
            if note[i].isdigit() or note[i] == '-':
                break
        try:
            name = note[:i]
            octave = int(note[i:])
            r = (_NOTE_NUMBERS[name] +
                    (octave + _setup.get_config('octave_offset')) * 12)
        except Exception:
            raise ValueError("invalid note name '%s'" % note)
    else:
        raise TypeError("note must be an integer or string")

    end = 128 if not allow_end else 129
    if not (0 <= r < end):
        raise ValueError("note number %d is out of range" % r)
    return r
Beispiel #11
0
    def make_event(self, *args, **kwargs):
        """
        Create a new MIDI event. Attributes can be specified in args or
        kwargs, unspecified attributes are filled with random values.
        """
        type, port, channel, data1, data2, sysex = \
            itertools.islice(itertools.chain(args, itertools.repeat(None)), 6)

        for k, v in kwargs.items():
            if k == 'type': type = v
            if k == 'port': port = v
            elif k == 'channel': channel = v
            elif k in ('data1', 'note', 'ctrl'): data1 = v
            elif k in ('data2', 'velocity', 'value'): data2 = v
            elif k == 'program': data2 = v - setup.get_config('data_offset')
            elif k == 'sysex': sysex = v

        if type is None:
            if channel is None:
                type = random.choice(
                    list(set(constants._EVENT_TYPES.values()) - set([DUMMY])))
            else:
                type = random.choice([
                    NOTEON, NOTEOFF, CTRL, PITCHBEND, AFTERTOUCH,
                    POLY_AFTERTOUCH, PROGRAM
                ])
        elif type == NOTE:
            type = random.choice([NOTEON, NOTEOFF])
        elif misc.issequence(type):
            type = random.choice(type)

        if port is None:
            port = random.randrange(0, 42) + setup.get_config('data_offset')
        if channel is None:
            channel = random.randrange(0, 16) + setup.get_config('data_offset')
        if data1 is None:
            data1 = random.randrange(0, 128)
        if data2 is None:
            data2 = (random.randrange(1, 128) if type == NOTEON else
                     0 if type == NOTEOFF else random.randrange(0, 128))

        if type == SYSEX and sysex is None:
            sysex = [0xf0] + [
                random.randrange(0, 128) for n in range(random.randrange(1024))
            ] + [0xf7]

        return MidiEvent(type, port, channel, data1, data2, sysex)
Beispiel #12
0
def actual(n):
    """
    Subtract current data offset to get the "real" value used on the C++ side.
    """
    if isinstance(n, NoDataOffset):
        return int(n)
    else:
        return n - _setup.get_config('data_offset')
Beispiel #13
0
def actual(n):
    """
    Subtract current data offset to get the "real" value used on the C++ side.
    """
    if isinstance(n, NoDataOffset):
        return int(n)
    else:
        return n - _setup.get_config('data_offset')
Beispiel #14
0
    def __init__(self):
        _start_backend()

        verbose = not _setup.get_config('silent')
        # initialize C++ base class
        _mididings.Engine.__init__(self, _TheBackend, verbose)

        self._scenes = {}
Beispiel #15
0
    def __init__(self):
        _start_backend()

        verbose = not _setup.get_config('silent')
        # initialize C++ base class
        _mididings.Engine.__init__(self, _TheBackend, verbose)

        self._scenes = {}
Beispiel #16
0
    def make_event(self, *args, **kwargs):
        """
        Create a new MIDI event. Attributes can be specified in args or
        kwargs, unspecified attributes are filled with random values.
        """
        type, port, channel, data1, data2, sysex = \
            itertools.islice(itertools.chain(args, itertools.repeat(None)), 6)

        for k, v in kwargs.items():
            if k == 'type': type = v
            if k == 'port': port = v
            elif k == 'channel': channel = v
            elif k in ('data1', 'note', 'ctrl'): data1 = v
            elif k in ('data2', 'velocity', 'value'): data2 = v
            elif k == 'program': data2 = v - setup.get_config('data_offset')
            elif k == 'sysex': sysex = v

        if type is None:
            if channel is None:
                type = random.choice(list(set(constants._EVENT_TYPES.values())
                                        - set([DUMMY])))
            else:
                type = random.choice([NOTEON, NOTEOFF, CTRL, PITCHBEND,
                                      AFTERTOUCH, POLY_AFTERTOUCH, PROGRAM])
        elif type == NOTE:
            type = random.choice([NOTEON, NOTEOFF])
        elif misc.issequence(type):
            type = random.choice(type)

        if port is None:
            port = random.randrange(0, 42) + setup.get_config('data_offset')
        if channel is None:
            channel = random.randrange(0, 16) + setup.get_config('data_offset')
        if data1 is None:
            data1 = random.randrange(0, 128)
        if data2 is None:
            data2 = (random.randrange(1, 128) if type == NOTEON
                     else 0 if type == NOTEOFF
                     else random.randrange(0, 128))

        if type == SYSEX and sysex is None:
            sysex = [0xf0] + [random.randrange(0, 128)
                              for n in range(random.randrange(1024))] + [0xf7]

        return MidiEvent(type, port, channel, data1, data2, sysex)
Beispiel #17
0
def get_client_id():
    """
    Return client id
    """
    if _setup.get_config('backend') == 'alsa':
        return _TheEngine().get_client_id()
    uuid = _TheEngine().get_client_uuid()
    if uuid.isdigit():
        return int(uuid)
    return uuid
Beispiel #18
0
    def send_config(self):
        for p in self.notify_ports:
            # send data offset
            _liblo.send(p, '/mididings/data_offset',
                        _setup.get_config('data_offset'))

            # send list of scenes
            _liblo.send(p, '/mididings/begin_scenes')
            s = _engine.scenes()
            for n in sorted(s.keys()):
                _liblo.send(p, '/mididings/add_scene', n, s[n][0], *s[n][1])
            _liblo.send(p, '/mididings/end_scenes')
Beispiel #19
0
    def send_config(self):
        for p in self.notify_ports:
            # send data offset
            _liblo.send(p, '/mididings/data_offset',
                        _setup.get_config('data_offset'))

            # send list of scenes
            _liblo.send(p, '/mididings/begin_scenes')
            s = _engine.scenes()
            for n in sorted(s.keys()):
                _liblo.send(p, '/mididings/add_scene', n, s[n][0], *s[n][1])
            _liblo.send(p, '/mididings/end_scenes')
Beispiel #20
0
def note_name(note):
    """
    Get note name from note number.

    :param note:
        a MIDI note number.
    :return:
        note name as a string.
    """
    if not isinstance(note, int):
        raise TypeError("note must be an integer")
    return _NOTE_NAMES[note % 12] + str((note // 12) -
                                        _setup.get_config('octave_offset'))
Beispiel #21
0
def note_name(note):
    """
    Get note name from note number.

    :param note:
        a MIDI note number.
    :return:
        note name as a string.
    """
    if not isinstance(note, int):
        raise TypeError("note must be an integer")
    return _NOTE_NAMES[note % 12] + str(
                (note // 12) - _setup.get_config('octave_offset'))
Beispiel #22
0
    def wrapper(self, f, *args, **kwargs):
        # XXX: avoid circular import
        from mididings.setup import get_config

        if (not (hasattr(f, '_already_used') and f._already_used) and
                not get_config('silent')):
            if self.replacement:
                print("%s() is deprecated, please use %s() instead" %
                        (f.__name__, self.replacement))
            else:
                print("%s() is deprecated" % f.__name__)
            f._already_used = True
        return f(*args, **kwargs)
Beispiel #23
0
    def scene_switch_callback(self, scene, subscene):
        # scene and subscene parameters are the actual numbers without offset!
        if scene == -1:
            # no scene specified, use current
            scene = _mididings.Engine.current_scene(self)
        if subscene == -1:
            # no subscene specified, use first
            subscene = 0

        # save actual subscene index
        subscene_index = subscene

        # add data offset to scene/subscene numbers
        scene = _util.offset(scene)
        subscene = _util.offset(subscene)

        found = (scene in self._scenes
                 and (not subscene_index
                      or subscene_index < len(self._scenes[scene][1])))

        # get string representation of scene/subscene number
        if (subscene_index
                or (scene in self._scenes and len(self._scenes[scene][1]))):
            number = "%d.%d" % (scene, subscene)
        else:
            number = str(scene)

        if not _setup.get_config('silent'):
            if found:
                # get scene/subscene name
                scene_data = self._scenes[scene]
                if scene_data[1]:
                    name = "%s - %s" % (scene_data[0],
                                        scene_data[1][subscene_index])
                else:
                    name = scene_data[0]

                scene_desc = (("%s: %s" %
                               (number, name)) if name else str(number))
                print("switching to scene %s" % scene_desc)
            else:
                print("no such scene: %s" % number)

        if found:
            self._call_hooks('on_switch_scene', scene, subscene)
Beispiel #24
0
    def scene_switch_callback(self, scene, subscene):
        # scene and subscene parameters are the actual numbers without offset!
        if scene == -1:
            # no scene specified, use current
            scene = _mididings.Engine.current_scene(self)
        if subscene == -1:
            # no subscene specified, use first
            subscene = 0

        # save actual subscene index
        subscene_index = subscene

        # add data offset to scene/subscene numbers
        scene = _util.offset(scene)
        subscene = _util.offset(subscene)

        found = (scene in self._scenes and
                 (not subscene_index or
                    subscene_index < len(self._scenes[scene][1])))

        # get string representation of scene/subscene number
        if (subscene_index or
                (scene in self._scenes and len(self._scenes[scene][1]))):
            number = "%d.%d" % (scene, subscene)
        else:
            number = str(scene)

        if not _setup.get_config('silent'):
            if found:
                # get scene/subscene name
                scene_data = self._scenes[scene]
                if scene_data[1]:
                    name = "%s - %s" % (scene_data[0],
                                        scene_data[1][subscene_index])
                else:
                    name = scene_data[0]

                scene_desc = (("%s: %s" % (number, name)) if name
                                else str(number))
                print("switching to scene %s" % scene_desc)
            else:
                print("no such scene: %s" % number)

        if found:
            self._call_hooks('on_switch_scene', scene, subscene)
Beispiel #25
0
def offset(n):
    """
    Add current data offset.
    """
    return n + _setup.get_config('data_offset')
Beispiel #26
0
 def check_patch(self, patch, d):
     """
     Test the given patch. d must be a mapping from events to the expected
     list of resulting events.
     """
     self.check_scenes({ setup.get_config('data_offset'): patch }, d)
Beispiel #27
0
 def check_patch(self, patch, d):
     """
     Test the given patch. d must be a mapping from events to the expected
     list of resulting events.
     """
     self.check_scenes({setup.get_config('data_offset'): patch}, d)
Beispiel #28
0
def offset(n):
    """
    Add current data offset.
    """
    return n + _setup.get_config('data_offset')