Example #1
0
    def __init__(self, container, pat):
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)

        #Clean MIDI Input
        while container.conn.midi_input_event_pending():
            container.conn.get_midi_input_event()
                
        self.container = container
        self.container.conn.refresh_connections()
        self.synth_list = self.container.conn.get_output_list()
        self.pat = pat
        
        self.set_title("Edit Pattern " + pat.get_name())
        self.set_resizable(True)
        self.connect("destroy", self.close_dialog)

        # A vBox to contain the pattern menu and track list
        self.vbox = gtk.VBox(False, 0)

        #HBox for the pattern options
        hbox = gtk.HBox(False,0)

        #Add new Track
        btn_add_track = gtk.Button("Add _Track")
        btn_add_track.connect("clicked", self.add_track, None)
        btn_add_track.show()
        hbox.pack_start(btn_add_track, True, True, 4)
        
        #Paste new Track
        btn_paste_track = gtk.Button("_Paste Track")
        btn_paste_track.connect("clicked", self.paste_track, None)
        btn_paste_track.show()
        hbox.pack_start(btn_paste_track, True, True, 4)
    
        #MIDI Input
        lbl_midi_input = gtk.Label("MIDI Input:")
        lbl_midi_input.show()
        hbox.pack_start(lbl_midi_input, False, False, 0)
        self.cbo_midi_input = gtk.combo_box_new_text()
        i = 0
        for t in self.container.conn.get_input_devices():
            self.cbo_midi_input.append_text(t)
            if t == self.container.conn.input_device:
                self.cbo_midi_input.set_active(i)
            i = i + 1
        self.cbo_midi_input.connect('changed', self.cbo_midi_input_changed)
        self.cbo_midi_input.show()
        hbox.pack_start(self.cbo_midi_input, False, False, 4)
    
        #Pattern Length
        lbl_len = gtk.Label("Len:")
        lbl_len.show()
        hbox.pack_start(lbl_len, False, False, 0)
        self.adj_len = gtk.Adjustment(value=pat.get_len(), lower=1, upper=64, step_incr=1)
        spn_len = gtk.SpinButton(self.adj_len, 0, 0)
        spn_len.show()
        hbox.pack_start(spn_len, False, False, 4)
                
        #Traditional Change Length
        btn_len = gtk.Button("Change Length")
        btn_len.connect("clicked", self.btn_len_clicked, None)
        btn_len.show()
        hbox.pack_start(btn_len, True, True, 4)
    
        #Expand Track
        btn_expand = gtk.Button("Expand Track")
        btn_expand.connect("clicked", self.btn_expand_clicked, None)
        btn_expand.show()
        hbox.pack_start(btn_expand, True, True, 4)
    
        hbox.show()
        self.vbox.pack_start(hbox, False, False, 0)
        
        #GUI for Tracks

        self.ntb_tracks = gtk.Notebook()
        self.ntb_tracks.connect("switch-page", self.nbt_tracks_switch_page, None)
        self.ntb_tracks.set_tab_pos(gtk.POS_TOP)
        
        self.tw = TrackWidget(pat.get_tracks()[0], self)
        
        for track in pat.get_tracks():
            track_gui = self.draw_track(track)
            if track.get_name():
                lbl_track_name = gtk.Label(track.get_name())
            else:
                lbl_track_name = gtk.Label('Untitled')
            lbl_track_name.show()
            self.ntb_tracks.append_page(track_gui, lbl_track_name)
            track_gui.show()


        self.ntb_tracks.show()

        self.vbox.pack_start(self.ntb_tracks, False, False, 0)

        self.vbox.pack_start(self.tw.get(), True, True, 0)

        self.controller_editor_widget = ControllerEditorWidget(self)
        self.controller_editor_widget.show()
        self.vbox.pack_start(self.controller_editor_widget, False, False, 0)
        
        self.pitchbend_editor_widget = PitchbendEditorWidget(self)
        self.pitchbend_editor_widget.show()
        self.vbox.pack_start(self.pitchbend_editor_widget, False, False, 0)

        self.tw.piano_roll.set_controller_editor_widget(
            self.controller_editor_widget)
        self.tw.piano_roll.set_pitchbend_editor_widget(
            self.pitchbend_editor_widget)

        self.vbox.show()

        self.add(self.vbox)
        self.tw.piano_roll.notes_area.grab_focus()
Example #2
0
class PatternWindow(gtk.Window):
    def __init__(self, container, pat):
        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)

        #Clean MIDI Input
        while container.conn.midi_input_event_pending():
            container.conn.get_midi_input_event()
                
        self.container = container
        self.container.conn.refresh_connections()
        self.synth_list = self.container.conn.get_output_list()
        self.pat = pat
        
        self.set_title("Edit Pattern " + pat.get_name())
        self.set_resizable(True)
        self.connect("destroy", self.close_dialog)

        # A vBox to contain the pattern menu and track list
        self.vbox = gtk.VBox(False, 0)

        #HBox for the pattern options
        hbox = gtk.HBox(False,0)

        #Add new Track
        btn_add_track = gtk.Button("Add _Track")
        btn_add_track.connect("clicked", self.add_track, None)
        btn_add_track.show()
        hbox.pack_start(btn_add_track, True, True, 4)
        
        #Paste new Track
        btn_paste_track = gtk.Button("_Paste Track")
        btn_paste_track.connect("clicked", self.paste_track, None)
        btn_paste_track.show()
        hbox.pack_start(btn_paste_track, True, True, 4)
    
        #MIDI Input
        lbl_midi_input = gtk.Label("MIDI Input:")
        lbl_midi_input.show()
        hbox.pack_start(lbl_midi_input, False, False, 0)
        self.cbo_midi_input = gtk.combo_box_new_text()
        i = 0
        for t in self.container.conn.get_input_devices():
            self.cbo_midi_input.append_text(t)
            if t == self.container.conn.input_device:
                self.cbo_midi_input.set_active(i)
            i = i + 1
        self.cbo_midi_input.connect('changed', self.cbo_midi_input_changed)
        self.cbo_midi_input.show()
        hbox.pack_start(self.cbo_midi_input, False, False, 4)
    
        #Pattern Length
        lbl_len = gtk.Label("Len:")
        lbl_len.show()
        hbox.pack_start(lbl_len, False, False, 0)
        self.adj_len = gtk.Adjustment(value=pat.get_len(), lower=1, upper=64, step_incr=1)
        spn_len = gtk.SpinButton(self.adj_len, 0, 0)
        spn_len.show()
        hbox.pack_start(spn_len, False, False, 4)
                
        #Traditional Change Length
        btn_len = gtk.Button("Change Length")
        btn_len.connect("clicked", self.btn_len_clicked, None)
        btn_len.show()
        hbox.pack_start(btn_len, True, True, 4)
    
        #Expand Track
        btn_expand = gtk.Button("Expand Track")
        btn_expand.connect("clicked", self.btn_expand_clicked, None)
        btn_expand.show()
        hbox.pack_start(btn_expand, True, True, 4)
    
        hbox.show()
        self.vbox.pack_start(hbox, False, False, 0)
        
        #GUI for Tracks

        self.ntb_tracks = gtk.Notebook()
        self.ntb_tracks.connect("switch-page", self.nbt_tracks_switch_page, None)
        self.ntb_tracks.set_tab_pos(gtk.POS_TOP)
        
        self.tw = TrackWidget(pat.get_tracks()[0], self)
        
        for track in pat.get_tracks():
            track_gui = self.draw_track(track)
            if track.get_name():
                lbl_track_name = gtk.Label(track.get_name())
            else:
                lbl_track_name = gtk.Label('Untitled')
            lbl_track_name.show()
            self.ntb_tracks.append_page(track_gui, lbl_track_name)
            track_gui.show()


        self.ntb_tracks.show()

        self.vbox.pack_start(self.ntb_tracks, False, False, 0)

        self.vbox.pack_start(self.tw.get(), True, True, 0)

        self.controller_editor_widget = ControllerEditorWidget(self)
        self.controller_editor_widget.show()
        self.vbox.pack_start(self.controller_editor_widget, False, False, 0)
        
        self.pitchbend_editor_widget = PitchbendEditorWidget(self)
        self.pitchbend_editor_widget.show()
        self.vbox.pack_start(self.pitchbend_editor_widget, False, False, 0)

        self.tw.piano_roll.set_controller_editor_widget(
            self.controller_editor_widget)
        self.tw.piano_roll.set_pitchbend_editor_widget(
            self.pitchbend_editor_widget)

        self.vbox.show()

        self.add(self.vbox)
        self.tw.piano_roll.notes_area.grab_focus()

    def close_dialog(self, widget, data=None):
        self.tw.btn_stop_clicked(self.tw)
        if self.tw.piano_roll.midi_keyboard_listen:
            gobject.source_remove(self.tw.piano_roll.midi_keyboard_listen)

        self.destroy()
        
    #Callback for Add Track Button
    def add_track(self, widget, data=None):
        track = self.pat.add_track()
        track_gui = self.draw_track(track)
        lbl_track_name = gtk.Label('Untitled')
        lbl_track_name.show()
        self.ntb_tracks.append_page(track_gui, lbl_track_name)
        track_gui.show()
        self.ntb_tracks.set_current_page(self.ntb_tracks.get_n_pages()-1)
        self.tw.piano_roll.notes_area.grab_focus()
        
        self.container.save_state = False
        
    #Callback for Paste Track Button

    def paste_track(self, widget, data=None):
        clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
        clipboard.request_text(self.paste_track_clipboard_text_received)
        
    # signal handler called when the clipboard returns text data
    def paste_track_clipboard_text_received(self, clipboard, text, data):
        if not text or text == '':
            return
            
        lines = text.split("\n")
        if not len(lines):
            return
            
        if lines[0] != 'Track':
            return

        track = self.pat.add_track()

        level = 0
        for line in lines:

            if line == "Track":
                level = 2
            
            if line == "Notes":
                level = 3

            if level == 2:
                if line[:5] == "Len: ":
                    track.set_len(int(line[5:]))
                elif line[:6] == "Name: ":
                    track.set_name(line[6:])
                elif line[:8] == "Volume: ":
                    track.set_volume(int(line[8:]))
                elif line[:7] == "Synth: ":
                    track.set_synth(line[7:])
                elif line[:6] == "Port: ":
                    track.set_port(int(line[6:]))
            elif level == 3:
                if line == "Notes":
                    pass
                elif line == "EndNotes":
                    level = 2
                else:
                    (note, pos, duration, volume) = line.split(', ')
                    track.add_note(int(note),int(pos),int(duration), int(volume))

        track.set_name("Copy of " + track.get_name())
        track_gui = self.draw_track(track)
        if track.get_name():
            lbl_track_name = gtk.Label(track.get_name())
        else:
            lbl_track_name = gtk.Label('Untitled')
        lbl_track_name.show()
        self.ntb_tracks.append_page(track_gui, lbl_track_name)
        track_gui.show()
        self.ntb_tracks.set_current_page(self.ntb_tracks.get_n_pages()-1)
        self.tw.piano_roll.notes_area.grab_focus()
        self.container.save_state = False

    def cbo_midi_input_changed(self, widget, data= None):
        input_device = widget.get_active_text()
        self.container.conn.change_input_device(input_device)
        self.container.conf.value['input_device'] = input_device
        
    def btn_len_clicked(self, widget, data=None):
        self.pat.set_len(int(self.adj_len.get_value()))
        self.tw.piano_roll.notes_area.set_size_request(self.pat.get_len() * (BEAT_WIDTH + KEY_SPACE * TICKS_PER_BEAT)+32, 128 * (KEY_HEIGHT + KEY_SPACE))
        self.tw.piano_roll.paint_roll()
        self.tw.piano_roll.notes_area_paint_selection()
        
        self.controller_editor_widget.area_resize()
        self.pitchbend_editor_widget.area_resize()
                
        self.container.save_state = False
        
    def btn_expand_clicked(self, widget, data=None):
        old_len = self.pat.get_len()
        new_len = int(self.adj_len.get_value())

        
        if new_len > old_len:
            self.pat.set_len(new_len)
            for track in self.pat.get_tracks():
                for (note, time, duration, volume) in track.get_notes():
                    if time < ((new_len-old_len)*TICKS_PER_BEAT):
                        track.add_note(note, time+old_len*TICKS_PER_BEAT, duration, volume)
                    
        else:
            for track in self.pat.get_tracks():
                del_notes = []
                for (note, time, duration, volume) in track.get_notes():
                    if time >= (new_len*TICKS_PER_BEAT):
                        del_notes.append((time, note, duration))
                        
                for (time, note, duration) in del_notes:
                    track.del_note(time, note, duration)
                        
            self.pat.set_len(new_len)
                        
        self.tw.piano_roll.notes_area.set_size_request(self.pat.get_len() * (BEAT_WIDTH + KEY_SPACE * TICKS_PER_BEAT)+32, 128 * (KEY_HEIGHT + KEY_SPACE))
        self.tw.paint_roll()
        self.tw.paint_selection()

        self.controller_editor_widget.area_resize()
        self.pitchbend_editor_widget.area_resize()
                
        self.container.save_state = False
        
    #Creates a line for a track
    def draw_track(self, track):
        hbox = gtk.HBox(False,0)
        
        btn_track_copy = gtk.Button("Copy Track")
        btn_track_copy.connect("clicked", self.btn_track_copy_clicked, track)
        btn_track_copy.show()
        hbox.pack_start(btn_track_copy, False, False, 4)
        
        btn_track_del = gtk.Button("Del Track")
        btn_track_del.connect("clicked", self.del_track, (track, hbox))
        btn_track_del.show()
        hbox.pack_start(btn_track_del, False, False, 4)
        
        #track Name
        lbl_track_name = gtk.Label('Name:')
        lbl_track_name.show()
        hbox.pack_start(lbl_track_name, False, False, 4)
        txt_track_name = gtk.Entry()
        txt_track_name.set_text(track.get_name())
        txt_track_name.set_max_length(30)
        txt_track_name.connect("changed", self.txt_track_name_change, track, hbox)
        txt_track_name.show()
        hbox.pack_start(txt_track_name, True, True, 4)
        
        lbl_track_synth = gtk.Label("Synth:")
        lbl_track_synth.show()
        hbox.pack_start(lbl_track_synth, False, False, 4)
        cbo_track_synth = gtk.combo_box_new_text()
        
        i = 0
        for t in self.synth_list:
            cbo_track_synth.append_text(t)
            if t == track.get_synth():
                cbo_track_synth.set_active(i)
            i = i + 1
        
        cbo_track_synth.connect('changed', self.cbo_track_synth_change, track)
        
        cbo_track_synth.show()
        hbox.pack_start(cbo_track_synth, False, False, 4)

        lbl_track_port = gtk.Label("Port:")
        lbl_track_port.show()
        hbox.pack_start(lbl_track_port, False, False, 0)
        adj_track_port = gtk.Adjustment(value=track.get_port(), lower=0, upper=32, step_incr=1)
        adj_track_port.connect("value_changed", self.adj_track_port_change, track)
        spn_track_port = gtk.SpinButton(adj_track_port, 0, 0)
        spn_track_port.show()
        hbox.pack_start(spn_track_port, False, False, 4)

        hbox.show()
        
        return hbox

    def btn_track_copy_clicked(self, widget, data=None):
        track = data
    
        text = ''
        text += "Track\n"
        text += "Len: " + str(track.get_len()) + "\n"
        text += "Name: " + track.get_name() + "\n"
        text += "Volume: " + str(track.get_volume()) + "\n"
        text += "Synth: " + track.get_synth() + "\n"
        text += "Port: " + str(track.get_port()) + "\n"
        
        text += "Notes\n"
        for note_descriptor in track.get_notes():
            text += "%i, %i, %i, %i\n" % note_descriptor
        text += "EndNotes\n"
        
        text += "EndTrack\n"
        
        clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
        clipboard.set_text(text)        
        self.tw.piano_roll.notes_area.grab_focus()

    def txt_track_name_change(self, widget, data, child):
        data.set_name(widget.get_text())
        self.ntb_tracks.set_tab_label_text(child, data.get_name())
        self.container.save_state = False

    def cbo_track_synth_change(self, widget, data=None):
        #Silence Please... we are changing synth
        synth_conn = self.container.conn.get_port(data.get_synth())
        if synth_conn != None: 
            port = data.get_port()
            for note in range(128):
                synth_conn.note_off(note, port)

        data.set_synth(self.synth_list[widget.get_active()])
        self.container.save_state = False
        self.tw.piano_roll.notes_area.grab_focus()
                
    def adj_track_port_change(self, widget, data=None):
        if data.get_port() != int(widget.get_value()):
            #Silence Please... we are changing port
            synth_conn = self.container.conn.get_port(data.get_synth())
            if synth_conn != None: 
                port = data.get_port()
                for note in range(128):
                    synth_conn.note_off(note, port)
            data.set_port(int(widget.get_value()))
            self.container.save_state = False
            #self.area.grab_focus()
        
    #Callback for Del Track Button
    def del_track(self, widget, data=None):
        
        if len(self.pat.get_tracks()) == 1:
            dialog = gtk.MessageDialog(self, gtk.DIALOG_MODAL , gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
                    "Can't delete last track in pattern.")            
            dialog.run()
            dialog.destroy()
            return
            
        (track, track_gui) = data

        dialog = gtk.MessageDialog(self, gtk.DIALOG_MODAL , gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO,
                "Delete track " + track.get_name() + "?")
                
        response = dialog.run()
        dialog.destroy()
        
        if response != gtk.RESPONSE_YES:
            return
        page = self.ntb_tracks.get_current_page()    
        self.ntb_tracks.remove_page(page)
        self.pat.del_track(track)
        page = self.ntb_tracks.get_current_page()    
        self.tw.load_track(self.pat.get_tracks()[page])
        self.controller_editor_widget.redraw()
        self.pitchbend_editor_widget.redraw()
        self.container.save_state = False
        
    def nbt_tracks_switch_page(self, notebook, page, page_num, data):
        self.tw.load_track(self.pat.get_tracks()[page_num])
        #Dirty trick to avoid an error when controller widget still not loaded
        try:
            self.controller_editor_widget.redraw()
            self.pitchbend_editor_widget.redraw()
        except:
            pass
        #Nasty grab focus for tabs.
        gobject.timeout_add(0,self.tw.grab_focus)