示例#1
0
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)
示例#2
0
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)