class PianoApp(wx.App): config = None functions_keymap = {} multi_voice = False active_channels = [] current_channel = 0 def OnInit(self): try: self.load_config() self.init_piano() self.init_ui() return True except UserError as user_error: wx.MessageBox(str(user_error), 'Erro', wx.OK | wx.ICON_ERROR) return False def load_config(self): self.config = Config(app.config_file_path()) def init_piano(self): self.create_midi_driver() self.piano = Piano(self.config.get_keymap_file_path('pianoeletronico.kmp'), self.midi_output) self.active_channels.append(0) self.piano.set_instrument(0, 0) def create_midi_driver(self): midi_output_factory = MidiOutputFactory() midi_output_driver = self.config.get_midi_output_driver(constants.MIDI_OUTPUT_DEFAULT_DRIVER) if midi_output_driver >= constants.MIDI_OUTPUT_DEFAULT_DRIVER: self.midi_output = midi_output_factory.factory_pygame(midi_output_driver ) elif midi_output_driver == constants.MIDI_OUTPUT_FLUIDSYNTH_DRIVER: self.midi_output = midi_output_factory.factory_fluidsynth(self.config.get_soundfont_file_path()) else: raise UserError('Erro de configuraĆ§Ć£o: MIDI driver inexistente') def init_ui(self): self.mainFrame = wx.Frame(parent = None, id = -1, title = 'Virtual Piano') self.mainFrame.Bind(wx.EVT_KEY_DOWN, self.on_key_down) self.mainFrame.Bind(wx.EVT_KEY_UP, self.on_key_up) self.functions_keymap = { wx.WXK_RIGHT: lambda evt: self.piano.next_instrument(self.current_channel), wx.WXK_LEFT: lambda evt: self.piano.previous_instrument(self.current_channel), wx.WXK_UP: lambda evt: self.tone_change_up(evt), wx.WXK_DOWN: lambda evt: self.tone_change_down(evt), wx.WXK_PAGEUP: lambda evt: self.next_channel(), wx.WXK_PAGEDOWN: lambda evt: self.previous_channel(), wx.WXK_DELETE: lambda evt: self.delete_current_channel(), wx.WXK_F2: lambda evt: self.select_instrument_by_number(self.current_channel), wx.WXK_F8: lambda evt: self.piano.volume_down(self.current_channel), wx.WXK_F9: lambda evt: self.piano.volume_up(self.current_channel), wx.WXK_BACK: self.toggle_multi_voice, wx.WXK_TAB: self.pan, } self.mainFrame.Show(True) def on_key_down(self, evt): key = evt.GetKeyCode() if key in self.functions_keymap: self.functions_keymap[key](evt) if self.multi_voice: for channel_number in self.active_channels: note = self.get_note_from_key_event(evt, channel_number) if note is not None: self.piano.note_on(note, channel_number) else: note = self.get_note_from_key_event(evt, self.current_channel) if note is not None: self.piano.note_on(note, self.current_channel) def on_key_up(self, evt): if self.multi_voice: for channel_number in self.active_channels: note = self.get_note_from_key_event(evt, channel_number) if note is not None: self.piano.note_off(note, channel_number) else: note = self.get_note_from_key_event(evt, self.current_channel) if note is not None: self.piano.note_off(note, self.current_channel) def get_note_from_key_event(self, evt, channel_number): key = evt.GetUnicodeKey() if key != wx.WXK_NONE: if key > 127: key = char.unicode_workaround(chr(key).encode('utf-8')) return self.piano.get_note(key, channel_number) def toggle_multi_voice(self, evt): self.piano.all_notes_off() self.multi_voice = not self.multi_voice def pan(self, evt): back = True if evt.GetModifiers() == wx.MOD_SHIFT else False self.piano.pan(back, self.current_channel) def next_channel(self): if self.current_channel == 15: return self.piano.all_notes_off() self.current_channel += 1 if not self.current_channel in self.active_channels: self.active_channels.append(self.current_channel) self.piano.get_channel(self.current_channel) def previous_channel(self): if self.current_channel == 0: return self.piano.all_notes_off() self.current_channel -= 1 def delete_current_channel(self): self.piano.delete_channel(self.current_channel) self.active_channels.remove(self.current_channel) self.current_channel -= 1 def tone_change_up(self, evt): key_modifier = evt.GetModifiers() if key_modifier == wx.MOD_SHIFT: self.piano.semitone_up(1, self.current_channel) else: self.piano.octave_up(self.current_channel) def tone_change_down(self, evt): key_modifier = evt.GetModifiers() if key_modifier == wx.MOD_SHIFT: self.piano.semitone_down(1, self.current_channel) else: self.piano.octave_down(self.current_channel) def select_instrument_by_number(self, target_channel): current_instrument = str(self.piano.get_instrument_for_channel(target_channel) + 1) pressed_ok, selected_instrument = edit_dialog(self.mainFrame, "Instrument", "Enter instrument number for channel %d (from 1 to 128):" % target_channel, current_instrument) if pressed_ok: try: instrument_number = int(selected_instrument) - 1 except ValueError: message_dialog(self.mainFrame, "Error", "Instrument not a number") return if instrument_number < 0 or instrument_number > 127: message_dialog(self.mainFrame, "Error", "Instrument number not in range from 1 to 128") return self.piano.set_instrument(instrument_number, target_channel)
class PianoApp(wx.App): functions_keymap = {} multi_voice = False def OnInit(self): self.init_piano() self.init_ui() return True def init_piano(self): keymap_filename = 'pianoeletronico.kmp' notes_manager = NotesManager() notes_manager.load_file(util.app_file_path(os.path.join('keymaps', keymap_filename))) self.midi = midi.Midi() self.midi_output = midi.Output(self.midi.get_default_output_id(), 0) self.piano = Piano(notes_manager, self.midi_output) self.piano.set_instrument(0, 0) def init_ui(self): self.mainFrame = wx.Frame(parent = None, id = -1, title = 'Virtual Piano') self.Bind(wx.EVT_KEY_DOWN, self.on_key_down) self.Bind(wx.EVT_KEY_UP, self.on_key_up) self.functions_keymap = { wx.WXK_RIGHT: lambda evt: self.piano.next_instrument(), wx.WXK_LEFT: lambda evt: self.piano.previous_instrument(), wx.WXK_UP: lambda evt: self.piano.octave_up(), wx.WXK_DOWN: lambda evt: self.piano.octave_down(), wx.WXK_PAGEUP: lambda evt: self.piano.next_channel(), wx.WXK_PAGEDOWN: lambda evt: self.piano.previous_channel(), wx.WXK_DELETE: lambda evt: self.piano.delete_current_channel(), wx.WXK_F8: lambda evt: self.piano.volume_down(), wx.WXK_F9: lambda evt: self.piano.volume_up(), wx.WXK_BACK: self.toggle_multi_voice, wx.WXK_TAB: self.pan, } self.mainFrame.Show(True) def on_key_down(self, evt): note = self.get_note_from_key_event(evt) if note is None: key = evt.GetKeyCode() if key in self.functions_keymap: self.functions_keymap[key](evt) else: if self.multi_voice: self.piano.note_on_multi(note) else: self.piano.note_on(note) def on_key_up(self, evt): note = self.get_note_from_key_event(evt) if note is None: return if self.multi_voice: self.piano.note_off_multi(note) else: self.piano.note_off(note) def get_note_from_key_event(self, evt): key = evt.GetUnicodeKey() if key != wx.WXK_NONE: if key > 127: key = unicode_workaround(chr(key).encode('utf-8')) return self.piano.notes_manager[key] if key in self.piano.notes_manager else None def toggle_multi_voice(self, evt): self.piano.all_notes_off() self.multi_voice = not self.multi_voice def pan(self, evt): back = True if evt.GetModifiers() == wx.MOD_SHIFT else False self.piano.pan(back)