def load_keymap(self):
     try:
         base_note = int(self.keymap[self.keymap_offset]['note'])
     except:
         base_note = 60
     scale = libseq.getScale()
     tonic = libseq.getTonic()
     name = None
     self.keymap = []
     if scale == 0:
         # Map
         path = None
         for layer in self.zyngui.screens['layer'].layers:
             if layer.midi_chan == self.channel:
                 path = layer.get_presetpath()
                 break
         if path:
             path = path.split('#')[1]
             try:
                 with open(CONFIG_ROOT + "/keymaps.json") as json_file:
                     data = json.load(json_file)
                 if path in data:
                     name = data[path]
                     xml = minidom.parse(CONFIG_ROOT + "/%s.midnam" %
                                         (name))
                     notes = xml.getElementsByTagName('Note')
                     self.scale = []
                     for note in notes:
                         self.keymap.append({
                             'note':
                             int(note.attributes['Number'].value),
                             'name':
                             note.attributes['Name'].value
                         })
             except:
                 logging.warning("Unable to load keymaps.json")
     if name == None:  # Not found map
         # Scale
         if scale > 0:
             scale = scale - 1
         libseq.setScale(scale + 1)  # Use chromatic scale if map not found
         if scale == 0:
             for note in range(0, 128):
                 new_entry = {"note": note}
                 key = note % 12
                 if key in (1, 3, 6, 8, 10):  # Black notes
                     new_entry.update({"colour": "black"})
                 if key == 0:  # 'C'
                     new_entry.update({"name": "C%d" % (note // 12 - 1)})
                 self.keymap.append(new_entry)
                 if note <= base_note:
                     self.keymap_offset = len(self.keymap) - 1
                     self.selected_cell[1] = self.keymap_offset
             name = "Chromatic"
         else:
             with open(CONFIG_ROOT + "/scales.json") as json_file:
                 data = json.load(json_file)
             if len(data) <= scale:
                 scale = 0
             for octave in range(0, 9):
                 for offset in data[scale]['scale']:
                     note = tonic + offset + octave * 12
                     if note > 127:
                         break
                     self.keymap.append({
                         "note":
                         note,
                         "name":
                         "%s%d" % (self.notes[note % 12], note // 12 - 1)
                     })
                     if note <= base_note:
                         self.keymap_offset = len(self.keymap) - 1
                         self.selected_cell[1] = self.keymap_offset
             name = data[scale]['name']
     return name
 def draw_grid(self):
     clear_grid = (self.redraw_pending == 2)
     self.redraw_pending = 0
     if libseq.getSteps() == 0:
         return  #TODO: Should we clear grid?
     if self.keymap_offset > len(self.keymap) - self.zoom:
         self.keymap_offset = len(self.keymap) - self.zoom
     if self.keymap_offset < 0:
         self.keymap_offset = 0
     font = tkFont.Font(family=zynthian_gui_config.font_topbar[0],
                        size=self.fontsize)
     if clear_grid:
         self.grid_canvas.delete(tkinter.ALL)
         self.step_width = (self.grid_width - 2) / libseq.getSteps()
         self.draw_pianoroll()
         self.cells = [None] * self.zoom * libseq.getSteps()
         self.play_canvas.coords(
             "playCursor", 1 + self.playhead * self.step_width, 0,
             1 + self.playhead * self.step_width + self.step_width,
             PLAYHEAD_HEIGHT)
     # Draw cells of grid
     self.grid_canvas.itemconfig("gridcell", fill="black")
     # Redraw gridlines
     self.grid_canvas.delete("gridline")
     if libseq.getStepsPerBeat():
         for step in range(0,
                           libseq.getSteps() + 1, libseq.getStepsPerBeat()):
             self.grid_canvas.create_line(step * self.step_width,
                                          0,
                                          step * self.step_width,
                                          self.zoom * self.row_height - 1,
                                          fill=GRID_LINE,
                                          tags=("gridline"))
     # Delete existing note names
     self.piano_roll.delete("notename")
     for row in range(0, self.zoom):
         index = row + self.keymap_offset
         if (index >= len(self.keymap)):
             break
         if clear_grid:
             # Create last note labels in grid
             self.grid_canvas.create_text(
                 self.grid_width - self.select_thickness,
                 int(self.row_height * (self.zoom - row - 0.5)),
                 state="hidden",
                 tags=("lastnotetext%d" % (row), "lastnotetext"),
                 font=font,
                 anchor="e")
         self.draw_row(index)
         # Update pianoroll keys
         id = "row%d" % (row)
         try:
             name = self.keymap[index]["name"]
         except:
             name = None
         try:
             colour = self.keymap[index]["colour"]
         except:
             colour = "white"
         self.piano_roll.itemconfig(id, fill=colour)
         if name:
             self.piano_roll.create_text(
                 (2, self.row_height * (self.zoom - row - 0.5)),
                 text=name,
                 font=font,
                 anchor="w",
                 fill=CANVAS_BACKGROUND,
                 tags="notename")
         if self.keymap[index]['note'] % 12 == libseq.getTonic():
             self.grid_canvas.create_line(
                 0, (self.zoom - row) * self.row_height,
                 self.grid_width, (self.zoom - row) * self.row_height,
                 fill=GRID_LINE,
                 tags=("gridline"))
     # Set z-order to allow duration to show
     if clear_grid:
         for step in range(libseq.getSteps()):
             self.grid_canvas.tag_lower("step%d" % step)
     self.select_cell()
 def on_menu_change(self, params):
     menu_item = self.parent.param_editor_item
     value = params['value']
     if value < params['min']:
         value = params['min']
     if value > params['max']:
         value = params['max']
     params['value'] = value
     if menu_item == 'Pattern':
         self.pattern = value
         self.copy_source = value
         self.load_pattern(value)
     elif menu_item == 'Copy pattern':
         self.load_pattern(value)
         return "Copy %d => %d ?" % (self.copy_source, value)
     elif menu_item == 'Transpose pattern':
         if libseq.getScale() == 0:
             self.parent.hide_param_editor()
             return
         if libseq.getScale() > 1:
             # Only allow transpose when showing chromatic scale
             libseq.setScale(1)
             self.load_keymap()
             self.redraw_pending = 1
         if (value != 0 and libseq.getScale()):
             libseq.transpose(value)
             self.parent.set_param(menu_item, 'value', 0)
             self.keymap_offset = self.keymap_offset + value
             if self.keymap_offset > 128 - self.zoom:
                 self.keymap_offset = 128 - self.zoom
             elif self.keymap_offset < 0:
                 self.keymap_offset = 0
             else:
                 self.selected_cell[1] = self.selected_cell[1] + value
             self.redraw_pending = 1
             self.select_cell()
         return "Transpose +/-"
     elif menu_item == 'Vertical zoom':
         self.zoom = value
     elif menu_item == 'Steps per beat':
         steps_per_beat = STEPS_PER_BEAT[value]
         #			libseq.setStepsPerBeat(steps_per_beat)
         self.redraw_pending = 2
         value = steps_per_beat
     elif menu_item == 'Scale':
         libseq.setScale(value)
         name = self.load_keymap()
         self.redraw_pending = 1
         return "Keymap: %s" % (name)
     elif menu_item == 'Tonic':
         if value < 0:
             value = 11
         if value > 11:
             value = 0
         self.parent.set_param('Tonic', 'value', value)
         offset = value - libseq.getTonic()
         libseq.setTonic(value)
         self.load_keymap()
         self.redraw_pending = 1
         return "Tonic: %s" % (self.notes[value])
     elif menu_item == 'Input channel':
         if value == 0:
             libseq.setInputChannel(0xFF)
             return 'Input channel: None'
         libseq.setInputChannel(value - 1)
     elif menu_item == 'Rest note':
         if value < 0 or value > 127:
             value = 128
         libseq.setInputRest(value)
         if value > 127:
             return "Rest note: None"
         return "Rest note: %s%d(%d)" % ([
             'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'
         ][value % 12], int(value / 12) - 1, value)
     return "%s: %d" % (menu_item, value)