How to use the persistence.persistent_attrs function in Persistence

To help you get started, we’ve selected a few Persistence examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github jpetazzo / griode / pickers.py View on Github external
[36, 35, None, None, 75, 56, None, 44],
    ],
)


class Melodic(enum.Enum):
    CHROMATIC = 1
    DIATONIC = 2
    MAGIC = 3


Drumkit = enum.Enum("Drumkit", list(DRUMKIT_MAPPINGS.keys()))



@persistent_attrs(root=48,
                  drumkit_mapping=Drumkit.FOUR_EIGHT,
                  melodic_mapping=Melodic.CHROMATIC)
class NotePicker(Gridget):

    def __init__(self, grid, channel):
        self.grid = grid
        self.surface = Surface(grid.surface)
        for button in "UP DOWN LEFT RIGHT".split():
            self.surface[button] = palette.CHANNEL[channel]
        self.channel = channel
        persistent_attrs_init(self, "{}__{}".format(self.grid.grid_name, channel))
        self.led2note = {}
        self.note2leds = collections.defaultdict(list)
        devicechain = self.grid.griode.devicechains[self.grid.channel]
        if devicechain.instrument.is_drumkit:
            self.mapping = self.drumkit_mapping
github jpetazzo / griode / griode.py View on Github external
from looper import Looper, LoopController
from gridgets import MENU, Menu
from mixer import Faders, Mixer
import notes
from palette import palette
from persistence import cache, persistent_attrs, persistent_attrs_init
from pickers import ColorPicker, InstrumentPicker, NotePicker, ScalePicker
import scales


log_format = "[%(levelname)s] %(filename)s:%(lineno)d %(funcName)s() -> %(message)s"
log_level = os.environ.get("LOG_LEVEL", "INFO").upper()
logging.basicConfig(level=log_level, format=log_format)


@persistent_attrs(key=notes.C, scale=scales.MAJOR)
class Griode(object):

    def __init__(self):
        persistent_attrs_init(self)
        self.synth = Fluidsynth()
        self.devicechains = [DeviceChain(self, i) for i in range(16)]
        self.grids = []
        self.cpu = CPU(self)
        self.clock = Clock(self)
        self.looper = Looper(self)
        self.mixer = Mixer(self)
        self.detect_devices()
        # FIXME: probably make this configurable somehow (env var...?)
        if False:
            from termpad import ASCIIGrid
            self.grids.append(ASCIIGrid(self, 0, 1))
github jpetazzo / griode / griode.py View on Github external
# Unmap the widget(s) that was "owning" that led
            if led in self.surface_map:
                self.surface_map[led].surface.parent.mask.remove(led)
            # Update the map
            self.surface_map[led] = gridget
            # Map the new widget
            gridget.surface.parent.mask.add(led)
            # Draw it
            self.surface[led] = gridget.surface[led]

    def tick(self, tick):
        pass

##############################################################################

@persistent_attrs(font_index=0, group_index=0, instr_index=0, bank_index=0)
class DeviceChain(object):

    def __init__(self, griode, channel):
        self.griode = griode
        self.channel = channel
        persistent_attrs_init(self, str(channel))
        self.latch = Latch(self)
        self.arpeggiator = Arpeggiator(self)
        self.program_change()

    # The variables `..._index` indicate which instrument is currently selected.
    # Note: perhaps this instrument does not exist. In that case, the
    # `instrument` property below will fallback to an (existing) one.
    @property
    def instrument(self):
        fonts = self.griode.synth.fonts
github jpetazzo / griode / sequencer.py View on Github external
def output(self, message):
        message.channel = self.channel
        devicechain = self.sequencer.griode.devicechains[self.channel]
        devicechain.send(message)
        # Send event to notepickers so that they can update LEDs if necessary
        for grid in self.sequencer.griode.grids:
            notepicker = grid.notepickers[self.channel]
            notepicker.send(message, self)
        # Update widgets (FIXME: this expensive, can we do better?)
        for grid in self.sequencer.griode.grids:
            controller = grid.sequencercontrollers[self.channel]
            controller.draw()


@persistent_attrs(notes=intervaltree.IntervalTree(), duration=24*8)
class Loop(object):

    def __init__(self, looper, number):
        self.looper = looper
        persistent_attrs_init(
            self, "C{:02}L{:02}".format(looper.channel, number))


class Note(object):

    def __init__(self, note, velocity):
        self.note = note
        self.velocity = velocity

    def __repr__(self):
        return ("Note(note={}, velocity={})"
github jpetazzo / griode / arpeggiator.py View on Github external
class MotifMode(enum.Enum):
    DISABLED = 1  # Do not use the motif, just spell out notes in buffer
    SCALE = 2     # Use the motif, mapping steps to the current scale
    BUFFER = 3    # Use the motif, mapping steps to the notes buffer


class ScaleKey(enum.Enum):  # Which note will be the root of the scale?
    FIRST = 1               # - the first note in the buffer
    LAST = 2                # - the last note in the buffer
    LOWER = 3               # - the lowest note in the buffer
    HIGHER = 4              # - the highest note in the buffer
    NEXT = 5                # - the next note in the buffer


@persistent_attrs(
    enabled=False, interval=6, pattern_length=4,
    pattern=[[4, 3, [0]], [1, 2, [0]], [3, 1, [0]], [1, 2, [0]]],
    note_order=NoteOrder.FIRST,
    motif_mode=MotifMode.DISABLED,
    scale_key=ScaleKey.FIRST,
)
class Arpeggiator(object):

    def __init__(self, devicechain):
        self.devicechain = devicechain
        persistent_attrs_init(self, str(devicechain.channel))
        self.notes = []
        self.next_note = 0  # That's a position in self.notes
        self.direction = 1  # Always 1, except when in BOUNCING mode
        self.latch_notes = set()
        self.playing = []
github jpetazzo / griode / looper.py View on Github external
elif (any(x!=y for x, y in zip(self.teacher_notes, student_notes))
                      or
                      len(student_notes) > len(self.teacher_notes)
                      or
                      self.student_loop.next_tick >= 2*self.tick_interval):
                    # Bzzzt wrong
                    logging.info("Bzzzt try again!")
                    logging.info("Teacher notes: {}"
                                 .format(self.teacher_notes))
                    logging.info("Student notes: {}"
                                 .format(student_notes))
                    self.flash(colors.RED)
                    self.teacher()


@persistent_attrs(beats_per_bar=4)
class Looper(object):

    def __init__(self, griode):
        self.griode = griode
        persistent_attrs_init(self)
        self.playing = False
        self.last_tick = 0            # Last (=current) tick
        self.loops_playing = set()    # Contains instances of Loop
        self.loops_recording = set()  # Also instances of Loop
        self.notes_recording = {}     # note -> (Note(), tick_when_started)
        self.notes_playing = []       # (stop_tick, channel, note)
        self.loops = {}
        self.teacher = Teacher(self)
        for row in range(1, 9):
            for column in range(1, 9):
                self.loops[row, column] = Loop(self, (row, column))
github jpetazzo / griode / clock.py View on Github external
from gridgets import Gridget, Surface
from palette import palette
from persistence import persistent_attrs, persistent_attrs_init


NUMBERS = """
###  #  ### ### # # ### ### ### ### ###
# #  #    #   # # # #   #     # # # # #
# #  #  ### ### ### ### ###   # ### ###
# #  #  #     #   #   # # #   # # #   #
###  #  ### ###   # ### ###   # ### ###
""".strip().split("\n")


@persistent_attrs(bpm=120)
class Clock(object):

    def __init__(self, griode):
        self.griode = griode
        persistent_attrs_init(self)
        self.tick = 0  # 24 ticks per quarter note
        self.next = time.time()
        self.cues = []

    def cue(self, when, func, args):
        self.cues.append((self.tick+when, func, args))

    def callback(self):
        expired_cues = [cue for cue in self.cues if cue[0] <= self.tick]
        for when, func, args in expired_cues:
            func(*args)
github jpetazzo / griode / mixer.py View on Github external
import enum
import logging
import mido

from gridgets import Gridget, Surface
from palette import palette
from persistence import persistent_attrs, persistent_attrs_init


class Page(enum.Enum):
    VOLUME = 1
    CHORUS = 2
    REVERB = 3


@persistent_attrs(volume=16*[96], chorus=16*[0], reverb=16*[0])
class Mixer(object):

    def __init__(self, griode):
        self.griode = griode
        persistent_attrs_init(self)
        # FIXME don't duplicate the CC mappings
        for cc, array in [
            (7, self.volume),
            (91, self.chorus),
            (93, self.reverb),
        ]:
            for channel, value in enumerate(array):
                m = mido.Message("control_change", control=cc, value=value)
                self.griode.devicechains[channel].send(m)
github jpetazzo / griode / griode.py View on Github external
klass = Keyboard
            if klass is not None:
                # FIXME find a better way than this for hotplug!
                if not initial:
                    logging.info("Detected hotplug of new device: {}".format(port_name))
                    time.sleep(4)
                self.grids.append(klass(self, port_name))
        for port_name in configured_ports - detected_ports:
            # Removing a device
            logging.info("Device {} is no longer plugged. Removing it."
                         .format(port_name))
            self.grids = [g for g in self.grids if g.grid_name != port_name]

##############################################################################

@persistent_attrs(channel=0)
class Grid(object):

    def __init__(self, griode, grid_name):
        self.griode = griode
        self.grid_name = grid_name
        persistent_attrs_init(self, grid_name)
        self.surface_map = {}  # maps leds to gridgets
        self.colorpicker = ColorPicker(self)
        self.faders = Faders(self)
        self.bpmsetter = BPMSetter(self)
        self.notepickers = [NotePicker(self, i) for i in range(16)]
        self.instrumentpickers = [InstrumentPicker(self, i) for i in range(16)]
        self.scalepicker = ScalePicker(self)
        self.arpconfigs = [ArpConfig(self, i) for i in range(16)]
        self.latchconfigs = [LatchConfig(self, i) for i in range(16)]
        self.loopcontroller = LoopController(self)
github jpetazzo / griode / latch.py View on Github external
import mido

from gridgets import Surface
from palette import palette
from persistence import persistent_attrs, persistent_attrs_init


@persistent_attrs(enabled=False)
class Latch(object):

    def __init__(self, devicechain):
        self.devicechain = devicechain
        persistent_attrs_init(self, str(devicechain.channel))
        self.notes = set()

    def send(self, message):
        if self.enabled and message.type == "note_on":
            note = message.note
            if message.velocity > 0:
                if note not in self.notes:
                    self.notes.add(note)
                    self.output(message)
                else:
                    self.notes.remove(note)