class LearnDialog(QDialog, Ui_Dialog): NOTEON = 0x9 NOTEOFF = 0x8 MIDICTRL = 11 NEW_CELL_STYLE = ("#cell_frame {border: 0px; " "border-radius: 5px; " "background-color: rgb(217, 217, 217);}") NEW_CELL_STYLE_ROUND = ("#cell_frame {border: 0px; " "border-radius: 20px; " "background-color: rgb(217, 217, 217);}") NOTE_NAME = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] # send_midi_to values : START_STOP = 0 MASTER_VOLUME_CTRL = 1 CTRLS = 2 BLOCK_BUTTONS = 3 PLAY_BTN = 4 PAUSE_BTN = 5 REWIND_BTN = 6 GOTO_BTN = 7 RECORD_BTN = 8 SCENES_BTN = 9 updateUi = pyqtSignal() def __init__(self, parent, callback, device=None): super(LearnDialog, self).__init__(parent) self.gui = parent self.setupUi(self) self.callback = callback self.queue = Queue() if device is None: self.original_device = Device() else: self.original_device = device self.setWindowTitle("Edit %s" % device.name) # perform deep copy in order to keep original values if cancel is # clicked self.device = Device(deepcopy(self.original_device.mapping)) self.current_line = None self.current_row = None self.current_line_pitch = [] self.knownCtrl = set() self.knownBtn = set() self.block_bts_list = [] self.send_midi_to = None self.updateUi.connect(self.update) # set current device values self.name.setText(self.device.name) self.black_vel.setValue(self.device.black_vel) self.green_vel.setValue(self.device.green_vel) self.blink_green_vel.setValue(self.device.blink_green_vel) self.red_vel.setValue(self.device.red_vel) self.blink_red_vel.setValue(self.device.blink_red_vel) self.amber_vel.setValue(self.device.amber_vel) self.blink_amber_vel.setValue(self.device.blink_amber_vel) if self.device.master_volume_ctrl: (self.label_master_volume_ctrl.setText( self.displayCtrl(self.device.master_volume_ctrl))) if self.device.play_btn: self.playLabel.setText(self.displayBtn(self.device.play_btn)) if self.device.pause_btn: self.pauseLabel.setText(self.displayBtn(self.device.pause_btn)) if self.device.rewind_btn: self.rewindLabel.setText(self.displayBtn(self.device.rewind_btn)) if self.device.goto_btn: self.gotoLabel.setText(self.displayBtn(self.device.goto_btn)) if self.device.record_btn: self.recordLabel.setText(self.displayBtn(self.device.record_btn)) (self.init_command .setText("\n".join([", ".join([str(num) for num in init_cmd]) for init_cmd in self.device.init_command]))) for vol_btn in self.device.scene_buttons: (msg_type, channel, pitch, velocity) = vol_btn cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.scenesHorizontalLayout.addWidget(cell) for vol_btn in self.device.block_buttons: (msg_type, channel, pitch, velocity) = vol_btn cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.btsHorizontalLayout.addWidget(cell) for vol_ctrl in self.device.ctrls: (msg_type, channel, pitch) = vol_ctrl cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, pitch)) cell.setStyleSheet(self.NEW_CELL_STYLE_ROUND) self.ctrlsHorizontalLayout.addWidget(cell) for line in self.device.start_stop: if self.current_line is None: self.current_line = 0 self.firstLine.setText("Add Next line") else: self.current_line += 1 self.current_row = 0 for btn_key in line: (msg_type, channel, pitch, velocity) = btn_key cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.gridLayout.addWidget(cell, self.current_line, self.current_row) self.current_row += 1 # connect signals self.accepted.connect(self.onSave) self.firstLine.clicked.connect(self.onFirstLineClicked) self.learn_master_volume_ctrl.clicked.connect(self.onMasterVolumeCtrl) self.playButton.clicked.connect(self.onPlayButton) self.pauseButton.clicked.connect(self.onPauseButton) self.rewindButton.clicked.connect(self.onRewindButton) self.gotoButton.clicked.connect(self.onGotoButton) self.recordButton.clicked.connect(self.onRecordButton) self.sendInitButton.clicked.connect(self.onSendInit) self.learn_ctrls.clicked.connect(self.onCtrls) self.learn_block_bts.clicked.connect(self.onBlockBts) self.learn_scenes.clicked.connect(self.onScenesButton) self.stop1.clicked.connect(self.onStopClicked) self.stop2.clicked.connect(self.onStopClicked) self.stop3.clicked.connect(self.onStopClicked) self.stop4.clicked.connect(self.onStopClicked) self.learn_black.clicked.connect(self.onBlack) self.learn_green.clicked.connect(self.onGreen) self.learn_blink_green.clicked.connect(self.onBlinkGreen) self.learn_red.clicked.connect(self.onRed) self.learn_blink_red.clicked.connect(self.onBlinkRed) self.learn_amber.clicked.connect(self.onAmber) self.learn_blink_amber.clicked.connect(self.onBlinkAmber) self.black_vel.valueChanged.connect(self.onBlack) self.green_vel.valueChanged.connect(self.onGreen) self.blink_green_vel.valueChanged.connect(self.onBlinkGreen) self.red_vel.valueChanged.connect(self.onRed) self.blink_red_vel.valueChanged.connect(self.onBlinkRed) self.amber_vel.valueChanged.connect(self.onAmber) self.blink_amber_vel.valueChanged.connect(self.onBlinkAmber) self.show() def onFirstLineClicked(self): self.send_midi_to = self.START_STOP if self.current_line is None: self.current_line = 0 self.firstLine.setText("Add Next line") else: self.current_line += 1 self.current_line_pitch = [] self.device.start_stop.append(self.current_line_pitch) self.firstLine.setEnabled(False) self.current_row = 0 cell = LearnCell(self) self.gridLayout.addWidget(cell, self.current_line, self.current_row) def onMasterVolumeCtrl(self): self.send_midi_to = self.MASTER_VOLUME_CTRL def onPlayButton(self): self.send_midi_to = self.PLAY_BTN def onPauseButton(self): self.send_midi_to = self.PAUSE_BTN def onRewindButton(self): self.send_midi_to = self.REWIND_BTN def onGotoButton(self): self.send_midi_to = self.GOTO_BTN def onRecordButton(self): self.send_midi_to = self.RECORD_BTN def onScenesButton(self): self.send_midi_to = self.SCENES_BTN def onSendInit(self): try: for note in self.parseInitCommand(): self.gui.queue_out.put(note) except Exception as ex: QMessageBox.critical(self, "Invalid init commands", str(ex)) def onCtrls(self): self.send_midi_to = self.CTRLS def onBlockBts(self): self.send_midi_to = self.BLOCK_BUTTONS def onStopClicked(self): self.send_midi_to = None def onBlack(self): self.lightAllCell(self.black_vel.value()) def onGreen(self): self.lightAllCell(self.green_vel.value()) def onBlinkGreen(self): self.lightAllCell(self.blink_green_vel.value()) def onRed(self): self.lightAllCell(self.red_vel.value()) def onBlinkRed(self): self.lightAllCell(self.blink_red_vel.value()) def onAmber(self): self.lightAllCell(self.amber_vel.value()) def onBlinkAmber(self): self.lightAllCell(self.blink_amber_vel.value()) def lightAllCell(self, color): for line in self.device.start_stop: for data in line: (m, channel, pitch, v) = data note = ((self.NOTEON << 4) + channel, pitch, color) self.gui.queue_out.put(note) for btn_key in self.device.block_buttons: (msg_type, channel, pitch, velocity) = btn_key note = ((self.NOTEON << 4) + channel, pitch, color) self.gui.queue_out.put(note) def update(self): try: while True: data = self.queue.get(block=False) if len(data) == 3: status, pitch, vel = struct.unpack('3B', data) self.processNote(status, pitch, vel) except Empty: pass def processNote(self, status, pitch, velocity): channel = status & 0xF msg_type = status >> 4 # -1: special value for velocity sensitive pad btn_id = (msg_type, channel, pitch, -1 if velocity not in [0, 127] else velocity) btn_key = (msg_type >> 1, channel, pitch) ctrl_key = (msg_type, channel, pitch) if ctrl_key not in self.knownCtrl: # process controller if self.send_midi_to == self.MASTER_VOLUME_CTRL: if msg_type == self.MIDICTRL: self.device.master_volume_ctrl = ctrl_key (self.label_master_volume_ctrl .setText(self.displayCtrl(ctrl_key))) self.knownCtrl.add(ctrl_key) self.send_midi_to = None elif self.send_midi_to == self.PLAY_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.play_btn = btn_id self.playLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.PAUSE_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.pause_btn = btn_id self.pauseLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.REWIND_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.rewind_btn = btn_id self.rewindLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.GOTO_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.goto_btn = btn_id self.gotoLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.RECORD_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.record_btn = btn_id self.recordLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.CTRLS: if msg_type == self.MIDICTRL: cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, pitch)) cell.setStyleSheet(self.NEW_CELL_STYLE_ROUND) self.ctrlsHorizontalLayout.addWidget(cell) self.device.ctrls.append(ctrl_key) self.knownCtrl.add(ctrl_key) # then process other elif btn_key not in self.knownBtn: if self.send_midi_to == self.SCENES_BTN: cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.scenesHorizontalLayout.addWidget(cell) self.device.scene_buttons.append(btn_id) self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) if self.send_midi_to == self.BLOCK_BUTTONS: cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.btsHorizontalLayout.addWidget(cell) self.device.block_buttons.append(btn_id) self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) elif self.send_midi_to == self.START_STOP: self.current_line_pitch.append(btn_id) cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.gridLayout.addWidget(cell, self.current_line, self.current_row) self.current_row += 1 self.firstLine.setEnabled(True) self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) def accept(self): try: self.parseInitCommand() super(LearnDialog, self).accept() except Exception as ex: QMessageBox.critical(self, "Invalid init commands", str(ex)) def reject(self): self.gui.is_learn_device_mode = False self.gui.redraw() super(LearnDialog, self).reject() def onSave(self): self.device.name = str(self.name.text()) self.device.black_vel = int(self.black_vel.value()) self.device.green_vel = int(self.green_vel.value()) self.device.blink_green_vel = int(self.blink_green_vel.value()) self.device.red_vel = int(self.red_vel.value()) self.device.blink_red_vel = int(self.blink_red_vel.value()) self.device.amber_vel = int(self.amber_vel.value()) self.device.blink_amber_vel = int(self.blink_amber_vel.value()) self.device.mapping['init_command'] = self.parseInitCommand() self.original_device.updateMapping(self.device.mapping) self.gui.is_learn_device_mode = False self.callback(self.original_device) self.gui.redraw() def displayNote(self, note_dec): octave, note = divmod(note_dec, 12) octave += 1 note_str = self.NOTE_NAME[note] return note_str[:1] + str(octave) + note_str[1:] def displayCtrl(self, ctrl_key): (msg_type, channel, pitch) = ctrl_key if msg_type == self.NOTEON: type = "Note On" note = self.displayNote(pitch) elif msg_type == self.NOTEOFF: type = "Note Off" note = self.displayNote(pitch) elif msg_type == self.MIDICTRL: type = "Controller" note = str(pitch) else: type = "Type=%s" % msg_type return "Channel %s %s %s" % (channel + 1, type, note) def displayBtn(self, btn_id): (msg_type, channel, pitch, velocity) = btn_id ctrl_key = (msg_type, channel, pitch) return self.displayCtrl(ctrl_key) def parseInitCommand(self): raw_str = str(self.init_command.toPlainText()) init_commands = [] line = 1 for raw_line in raw_str.split("\n"): matches = _init_cmd_regexp.match(raw_line) if matches: byte1 = int(matches.group(1)) byte2 = int(matches.group(2)) byte3 = int(matches.group(3)) if not 0 <= byte1 < 256: raise Exception("First number out of range on line %s" % line) if not 0 <= byte2 < 256: raise Exception("Second number out of range on line %s" % line) if not 0 <= byte3 < 256: raise Exception("Third number out of range on line %s" % line) init_commands.append((byte1, byte2, byte3)) elif len(raw_line): raise Exception("Invalid format for Line %s :\n%s" % (line, raw_line)) line = line + 1 return init_commands
class LearnDialog(QDialog, Ui_Dialog): NOTEON = 0x9 NOTEOFF = 0x8 MIDICTRL = 11 NEW_CELL_STYLE = ("#cell_frame {border: 0px; " "border-radius: 5px; " "background-color: rgb(217, 217, 217);}") NEW_CELL_STYLE_ROUND = ("#cell_frame {border: 0px; " "border-radius: 20px; " "background-color: rgb(217, 217, 217);}") NOTE_NAME = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] # send_midi_to values : START_STOP = 0 MASTER_VOLUME_CTRL = 1 CTRLS = 2 BLOCK_BUTTONS = 3 PLAY_BTN = 4 PAUSE_BTN = 5 REWIND_BTN = 6 GOTO_BTN = 7 RECORD_BTN = 8 updateUi = pyqtSignal() def __init__(self, parent, callback, device=None): super(LearnDialog, self).__init__(parent) self.gui = parent self.setupUi(self) self.callback = callback self.queue = Queue() if device is None: self.original_device = Device() else: self.original_device = device self.setWindowTitle("Edit %s" % device.name) # perform deep copy in order to keep original values if cancel is # clicked self.device = Device(deepcopy(self.original_device.mapping)) self.current_line = None self.current_row = None self.current_line_pitch = [] self.knownCtrl = set() self.knownBtn = set() self.block_bts_list = [] self.send_midi_to = None self.updateUi.connect(self.update) # set current device values self.name.setText(self.device.name) self.black_vel.setValue(self.device.black_vel) self.green_vel.setValue(self.device.green_vel) self.blink_green_vel.setValue(self.device.blink_green_vel) self.red_vel.setValue(self.device.red_vel) self.blink_red_vel.setValue(self.device.blink_red_vel) self.amber_vel.setValue(self.device.amber_vel) self.blink_amber_vel.setValue(self.device.blink_amber_vel) if self.device.master_volume_ctrl: (self.label_master_volume_ctrl.setText( self.displayCtrl(self.device.master_volume_ctrl))) if self.device.play_btn: self.playLabel.setText(self.displayBtn(self.device.play_btn)) if self.device.pause_btn: self.pauseLabel.setText(self.displayBtn(self.device.pause_btn)) if self.device.rewind_btn: self.rewindLabel.setText(self.displayBtn(self.device.rewind_btn)) if self.device.goto_btn: self.gotoLabel.setText(self.displayBtn(self.device.goto_btn)) if self.device.record_btn: self.recordLabel.setText(self.displayBtn(self.device.record_btn)) (self.init_command .setText("\n".join([", ".join([str(num) for num in init_cmd]) for init_cmd in self.device.init_command]))) for vol_btn in self.device.block_buttons: (msg_type, channel, pitch, velocity) = vol_btn cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.btsHorizontalLayout.addWidget(cell) for vol_ctrl in self.device.ctrls: (msg_type, channel, pitch) = vol_ctrl cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, pitch)) cell.setStyleSheet(self.NEW_CELL_STYLE_ROUND) self.ctrlsHorizontalLayout.addWidget(cell) for line in self.device.start_stop: if self.current_line is None: self.current_line = 0 self.firstLine.setText("Add Next line") else: self.current_line += 1 self.current_row = 0 for btn_key in line: (msg_type, channel, pitch, velocity) = btn_key cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.gridLayout.addWidget(cell, self.current_line, self.current_row) self.current_row += 1 # connect signals self.accepted.connect(self.onSave) self.firstLine.clicked.connect(self.onFirstLineClicked) self.learn_master_volume_ctrl.clicked.connect(self.onMasterVolumeCtrl) self.playButton.clicked.connect(self.onPlayButton) self.pauseButton.clicked.connect(self.onPauseButton) self.rewindButton.clicked.connect(self.onRewindButton) self.gotoButton.clicked.connect(self.onGotoButton) self.recordButton.clicked.connect(self.onRecordButton) self.sendInitButton.clicked.connect(self.onSendInit) self.learn_ctrls.clicked.connect(self.onCtrls) self.learn_block_bts.clicked.connect(self.onBlockBts) self.stop1.clicked.connect(self.onStopClicked) self.stop2.clicked.connect(self.onStopClicked) self.stop3.clicked.connect(self.onStopClicked) self.learn_black.clicked.connect(self.onBlack) self.learn_green.clicked.connect(self.onGreen) self.learn_blink_green.clicked.connect(self.onBlinkGreen) self.learn_red.clicked.connect(self.onRed) self.learn_blink_red.clicked.connect(self.onBlinkRed) self.learn_amber.clicked.connect(self.onAmber) self.learn_blink_amber.clicked.connect(self.onBlinkAmber) self.black_vel.valueChanged.connect(self.onBlack) self.green_vel.valueChanged.connect(self.onGreen) self.blink_green_vel.valueChanged.connect(self.onBlinkGreen) self.red_vel.valueChanged.connect(self.onRed) self.blink_red_vel.valueChanged.connect(self.onBlinkRed) self.amber_vel.valueChanged.connect(self.onAmber) self.blink_amber_vel.valueChanged.connect(self.onBlinkAmber) self.show() def onFirstLineClicked(self): self.send_midi_to = self.START_STOP if self.current_line is None: self.current_line = 0 self.firstLine.setText("Add Next line") else: self.current_line += 1 self.current_line_pitch = [] self.device.start_stop.append(self.current_line_pitch) self.firstLine.setEnabled(False) self.current_row = 0 cell = LearnCell(self) self.gridLayout.addWidget(cell, self.current_line, self.current_row) def onMasterVolumeCtrl(self): self.send_midi_to = self.MASTER_VOLUME_CTRL def onPlayButton(self): self.send_midi_to = self.PLAY_BTN def onPauseButton(self): self.send_midi_to = self.PAUSE_BTN def onRewindButton(self): self.send_midi_to = self.REWIND_BTN def onGotoButton(self): self.send_midi_to = self.GOTO_BTN def onRecordButton(self): self.send_midi_to = self.RECORD_BTN def onSendInit(self): try: for note in self.parseInitCommand(): self.gui.queue_out.put(note) except Exception as ex: QMessageBox.critical(self, "Invalid init commands", str(ex)) def onCtrls(self): self.send_midi_to = self.CTRLS def onBlockBts(self): self.send_midi_to = self.BLOCK_BUTTONS def onStopClicked(self): self.send_midi_to = None def onBlack(self): self.lightAllCell(self.black_vel.value()) def onGreen(self): self.lightAllCell(self.green_vel.value()) def onBlinkGreen(self): self.lightAllCell(self.blink_green_vel.value()) def onRed(self): self.lightAllCell(self.red_vel.value()) def onBlinkRed(self): self.lightAllCell(self.blink_red_vel.value()) def onAmber(self): self.lightAllCell(self.amber_vel.value()) def onBlinkAmber(self): self.lightAllCell(self.blink_amber_vel.value()) def lightAllCell(self, color): for line in self.device.start_stop: for data in line: (m, channel, pitch, v) = data note = ((self.NOTEON << 4) + channel, pitch, color) self.gui.queue_out.put(note) for btn_key in self.device.block_buttons: (msg_type, channel, pitch, velocity) = btn_key note = ((self.NOTEON << 4) + channel, pitch, color) self.gui.queue_out.put(note) def update(self): try: while True: data = self.queue.get(block=False) if len(data) == 3: status, pitch, vel = struct.unpack('3B', data) self.processNote(status, pitch, vel) except Empty: pass def processNote(self, status, pitch, velocity): channel = status & 0xF msg_type = status >> 4 # -1: special value for velocity sensitive pad btn_id = (msg_type, channel, pitch, -1 if velocity not in [0, 127] else velocity) btn_key = (msg_type >> 1, channel, pitch) ctrl_key = (msg_type, channel, pitch) if ctrl_key not in self.knownCtrl: # process controller if self.send_midi_to == self.MASTER_VOLUME_CTRL: if msg_type == self.MIDICTRL: self.device.master_volume_ctrl = ctrl_key (self.label_master_volume_ctrl .setText(self.displayCtrl(ctrl_key))) self.knownCtrl.add(ctrl_key) self.send_midi_to = None elif self.send_midi_to == self.PLAY_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.play_btn = btn_id self.playLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.PAUSE_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.pause_btn = btn_id self.pauseLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.REWIND_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.rewind_btn = btn_id self.rewindLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.GOTO_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.goto_btn = btn_id self.gotoLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.RECORD_BTN: self.send_midi_to = None self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) self.device.record_btn = btn_id self.recordLabel.setText(self.displayCtrl(ctrl_key)) elif self.send_midi_to == self.CTRLS: if msg_type == self.MIDICTRL: cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, pitch)) cell.setStyleSheet(self.NEW_CELL_STYLE_ROUND) self.ctrlsHorizontalLayout.addWidget(cell) self.device.ctrls.append(ctrl_key) self.knownCtrl.add(ctrl_key) # then process other elif btn_key not in self.knownBtn: if self.send_midi_to == self.BLOCK_BUTTONS: cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.btsHorizontalLayout.addWidget(cell) self.device.block_buttons.append(btn_id) self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) elif self.send_midi_to == self.START_STOP: self.current_line_pitch.append(btn_id) cell = LearnCell(self) cell.label.setText("Ch %s\n%s" % (channel + 1, self.displayNote(pitch))) cell.setStyleSheet(self.NEW_CELL_STYLE) self.gridLayout.addWidget(cell, self.current_line, self.current_row) self.current_row += 1 self.firstLine.setEnabled(True) self.knownCtrl.add(ctrl_key) self.knownBtn.add(btn_key) def accept(self): try: self.parseInitCommand() super(LearnDialog, self).accept() except Exception as ex: QMessageBox.critical(self, "Invalid init commands", str(ex)) def reject(self): self.gui.is_learn_device_mode = False self.gui.redraw() super(LearnDialog, self).reject() def onSave(self): self.device.name = str(self.name.text()) self.device.black_vel = int(self.black_vel.value()) self.device.green_vel = int(self.green_vel.value()) self.device.blink_green_vel = int(self.blink_green_vel.value()) self.device.red_vel = int(self.red_vel.value()) self.device.blink_red_vel = int(self.blink_red_vel.value()) self.device.amber_vel = int(self.amber_vel.value()) self.device.blink_amber_vel = int(self.blink_amber_vel.value()) self.device.mapping['init_command'] = self.parseInitCommand() self.original_device.updateMapping(self.device.mapping) self.gui.is_learn_device_mode = False self.callback(self.original_device) self.gui.redraw() def displayNote(self, note_dec): octave, note = divmod(note_dec, 12) octave += 1 note_str = self.NOTE_NAME[note] return note_str[:1] + str(octave) + note_str[1:] def displayCtrl(self, ctrl_key): (msg_type, channel, pitch) = ctrl_key if msg_type == self.NOTEON: type = "Note On" note = self.displayNote(pitch) elif msg_type == self.NOTEOFF: type = "Note Off" note = self.displayNote(pitch) elif msg_type == self.MIDICTRL: type = "Controller" note = str(pitch) else: type = "Type=%s" % msg_type return "Channel %s %s %s" % (channel + 1, type, note) def displayBtn(self, btn_id): (msg_type, channel, pitch, velocity) = btn_id ctrl_key = (msg_type, channel, pitch) return self.displayCtrl(ctrl_key) def parseInitCommand(self): raw_str = str(self.init_command.toPlainText()) init_commands = [] line = 1 for raw_line in raw_str.split("\n"): matches = _init_cmd_regexp.match(raw_line) if matches: byte1 = int(matches.group(1)) byte2 = int(matches.group(2)) byte3 = int(matches.group(3)) if not 0 <= byte1 < 256: raise Exception("First number out of range on line %s" % line) if not 0 <= byte2 < 256: raise Exception("Second number out of range on line %s" % line) if not 0 <= byte3 < 256: raise Exception("Third number out of range on line %s" % line) init_commands.append((byte1, byte2, byte3)) elif len(raw_line): raise Exception("Invalid format for Line %s :\n%s" % (line, raw_line)) line = line + 1 return init_commands