Ejemplo n.º 1
0
class TkApplicationWindow(AbstractApplicationWindow):

    def __init__(self, app):
        self.root = Tk()
        self.root.title("Llia")
        self.root.config(background=factory.bg())
        super(TkApplicationWindow, self).__init__(app, self.root)
        self.root.withdraw()
        if app.config()["enable-splash"]:
            splash = TkSplashWindow(self.root, app)
        self.root.deiconify()
        self.root.protocol("WM_DELETE_WINDOW", self.exit_app)
        self.llia_graph = None
        self._main = layout.BorderFrame(self.root)
        self._main.config(background=factory.bg())
        self._main.pack(anchor="nw", expand=True, fill=BOTH)
        self._progressbar = None
        self._init_status_panel()
        self._init_menu()
        self._init_center_frame(self._main.center)
        self.root.minsize(width=665, height=375)
        self.group_windows = []
        self.add_synth_group()
        self._scene_filename = ""
        
    def _init_status_panel(self):
        south = self._main.south
        south.configure(padx=4, pady=4)
        self._lab_status = factory.label(south, "", modal=False)
        b_panic = factory.panic_button(south)
        b_down = factory.button(south, "-")
        b_up = factory.button(south, "+")
        b_panic.grid(row=0, column=0)
        self._progressbar = Progressbar(south,mode="indeterminate")
        self._progressbar.grid(row=0,column=PROGRESSBAR_COLUMN, sticky='w', padx=8)
        self._lab_status.grid(row=0,column=4, sticky='w')
        south.config(background=factory.bg())
        b_down.configure(command=lambda: self.root.lower())
        b_up.configure(command=lambda: self.root.lift())
        self.update_progressbar(100, 0)
        
    def _tab_change_callback(self, event):
        self.llia_graph.sync()
    
    def _init_center_frame(self, master):
        nb = ttk.Notebook(master)
        nb.pack(expand=True, fill="both")
        frame_synths = layout.FlowGrid(nb, 6)
        frame_efx = layout.FlowGrid(nb, 6)
        frame_controllers = layout.FlowGrid(nb, 6)
        self.llia_graph = LliaGraph(nb, self.app)
        nb.add(frame_synths, text = "Synths")
        nb.add(frame_efx, text = "Effects")
        nb.add(frame_controllers, text = "Controllers")
        nb.add(self.llia_graph, text="Graph")
        nb.bind("<Button-1>", self._tab_change_callback)

        def display_info_callback(event):
            sp = event.widget.synth_spec
            msg = "%s:    %s" % (sp["format"],sp["description"])
            self.status(msg)

        def clear_info_callback(*_):
            self.status("")
        
        for st in con.SYNTH_TYPES:
            sp = specs[st]
            ttp = "Add %s Synthesizer (%s)" % (st, sp["description"])
            b = factory.logo_button(frame_synths, st, ttip=ttp)
            b.synth_spec = sp
            b.bind("<Button-1>", self._show_add_synth_dialog)
            b.bind("<Enter>", display_info_callback)
            b.bind("<Leave>", clear_info_callback)
            frame_synths.add(b)
        for st in con.EFFECT_TYPES:
            sp = specs[st]
            ttp = "Add %s Effect (%s)" % (st, sp["description"])
            b = factory.logo_button(frame_efx, st, ttip=ttp)
            b.synth_spec = sp
            b.bind("<Button-1>", self._show_add_efx_dialog)
            b.bind("<Enter>", display_info_callback)
            b.bind("<Leave>", clear_info_callback)
            frame_efx.add(b)
        for st in con.CONTROLLER_SYNTH_TYPES:
            sp = specs[st]
            ttp = "Add %s Effect (%s)" % (st, sp["description"])
            b = factory.logo_button(frame_controllers, st, ttip=ttp)
            b.synth_spec = sp
            b.bind("<Button-1>", self._show_add_controller_dialog)
            b.bind("<Enter>", display_info_callback)
            b.bind("<Leave>", clear_info_callback)
            frame_controllers.add(b)
    
    @staticmethod
    def menu(master):
        m = Menu(master, tearoff=0)
        m.config(background=factory.bg(), foreground=factory.fg())
        return m
    
    def _init_menu(self):
        main_menu = self.menu(self.root)
        self.root.config(menu=main_menu)
        file_menu = self.menu(main_menu)
        osc_menu = self.menu(main_menu)
        midi_menu = self.menu(main_menu)
        bus_menu = self.menu(main_menu)
        #buffer_menu = self.menu(main_menu)
        tune_menu = self.menu(main_menu)
        help_menu = self.menu(main_menu)
        main_menu.add_cascade(label="File", menu=file_menu)
        main_menu.add_cascade(label="OSC", menu=osc_menu)
        main_menu.add_cascade(label="MIDI", menu=midi_menu)
        #main_menu.add_cascade(label="Buses", menu=bus_menu)
        #main_menu.add_cascade(label="Buffers", menu=buffer_menu)
        #main_menu.add_cascade(label="Tune", menu=tune_menu)
        #main_menu.add_cascade(label="Help", menu=help_menu)
        self._init_file_menu(file_menu)
        self._init_osc_menu(osc_menu)
        self._init_midi_menu(midi_menu)
        self._init_bus_menu(bus_menu)
        #self._init_buffer_menu(buffer_menu)
        self._init_tune_menu(tune_menu)
        self._init_help_menu(help_menu)

    def _init_file_menu(self, fmenu):
        fmenu.add_command(label="Save Scene", command = self.save_scene)
        fmenu.add_command(label="Load Scene", command = self.load_scene)
        fmenu.add_separator()
        fmenu.add_command(label="Lliascript (Legacy)", command = self.show_history_editor)
        fmenu.add_separator()
        fmenu.add_command(label="New Synth Group", command = self._add_synth_group)
        fmenu.add_separator()
        fmenu.add_command(label="Restart", command = self._interactive_tabula_rasa)
        fmenu.add_command(label="Quit", command = self.exit_app)

    def _init_osc_menu(self, iomenu):
        iomenu.add_command(label="Ping", command = self.ping_global)
        iomenu.add_command(label="Dump", command = self.app.proxy.dump)
        iomenu.add_command(label="Toggle OSC Trace", command = self.toggle_osc_trace)

    def _init_midi_menu(self, mmenu):
        map_menu = self.menu(mmenu)
        mmenu.add_command(label = "Channel Names", command = self.show_channel_name_dialog)
        mmenu.add_command(label = "Controller Names", command = self.show_controller_name_dialog)
        mmenu.add_cascade(label = "MIDI Maps", menu = map_menu)
        mmenu.add_command(label = "Toggle MIDI Input Trace", command = self.toggle_midi_input_trace)
        mmenu.add_command(label = "Toggle MIDI Output Trace", command = self.toggle_midi_output_trace)
        mmenu.add_command(label = "Toggle Program Pretty Printer", command = self.toggle_program_pretty_printer)
        
    def _init_bus_menu(self, bmenu):
        bmenu.add_command(label="Audio", command=self.show_audiobus_dialog)
        bmenu.add_command(label="Control", command=self.show_controlbus_dialog)
        
    # def _init_buffer_menu(self, bmenu):
    #     bmenu.add_command(label="View Buffers", command=self.show_bufferlist_dialog)

    def _init_tune_menu(self, tmenu):
        tmenu.add_command(label = "FIX ME: Nothing to see here")

    def _init_help_menu(self, hmenu):
        pass
        
    def exit_gui(self):
        try:
            self.root.destroy()
        except:
            pass

    def confirm_exit(self):
        return tkMessageBox.askyesno("Exit Llia", "Exit Llia?")
        
    def exit_app(self):
        self.app.exit_()

    def as_widget(self):
        return self.root
        
    def status(self, msg):
        self._lab_status.config(text=str(msg))

    def warning(self, msg):
        msg = "WARNING: %s" % msg
        self._lab_status.config(text=msg)
        
    def clear_status(self):
        self.status("")
                                              
    def start_gui_loop(self):
        self.root.mainloop()

    def show_about_dialog(self):
        from llia.gui.tk.tk_about_dialog import TkAboutDialog
        dialog = TkAboutDialog(self.root, self.app)
        self.root.wait_window(dialog)

    def display_help(self, topic=None):
        pass
        
    def show_history_editor(self):
        from llia.gui.tk.tk_history import TkHistoryEditor
        dialog = TkHistoryEditor(self.root, self.app)
        self.root.wait_window(dialog)

    def ping_global(self):
        try:
            rs = self.app.proxy.ping()
            if rs:
                self.status("Ping OK")
            else:
                self.warning("Ping Error")
        except LliaPingError as err:
            self.warning(err.message)

    def toggle_osc_trace(self):
        LliaProxy.trace = not LliaProxy.trace
        if LliaProxy.trace:
            self.status("OSC transmission trace enabled")
        else:
            self.status("OSC transmission trace disabled")

    def show_channel_name_dialog(self):
        from llia.gui.tk.tk_channel_name_editor import TkChannelNameEditor
        dialog = TkChannelNameEditor(self.root, self.app)
        self.root.wait_window(dialog)
  
    def show_controller_name_dialog(self):
        from llia.gui.tk.tk_controller_name_editor import TkControllerNameEditor
        dialog = TkControllerNameEditor(self.root, self.app)
        self.root.wait_window(dialog)
    
    def toggle_midi_input_trace(self):
        flag = not self.app.midi_in_trace
        self.app.midi_in_trace = flag
        self.app.midi_receiver.enable_trace(flag)
        if flag:
            self.status("MIDI input trace enabled")
        else:
            self.status("MIDI output trace disabled")

    def toggle_midi_output_trace(self):
        self.status("MIDI output not available") # FIX ME

    def toggle_program_pretty_printer(self):
        self.app.pp_enabled = not self.app.pp_enabled
        if self.app.pp_enabled:
            self.status("Pretty printer enabled")
        else:
            self.status("Pretty printer disabled")
        
    def show_audiobus_dialog(self):
        from llia.gui.tk.tk_audiobus_editor import TkAudiobusEditor
        dialog = TkAudiobusEditor(self.root, self.app)
        self.root.wait_window(dialog)

    def show_controlbus_dialog(self):
        from llia.gui.tk.tk_controlbus_editor import TkControlbusEditor
        dialog = TkControlbusEditor(self.root, self.app)
        self.root.wait_window(dialog)

    # def show_bufferlist_dialog(self):
    #     from llia.gui.tk.tk_buffer_info import TkBufferListDialog
    #     dialog = TkBufferListDialog(self.root, self.app)
    #     self.root.wait_window(dialog)

    def _show_add_synth_dialog(self, event):
        w = event.widget
        st = w.config()["text"][-1]
        dialog = TkAddSynthDialog(self.root, self.app, st, False)
        self.root.wait_window(dialog)
        
    def _show_add_efx_dialog(self, event):
        w = event.widget
        st = w.config()["text"][-1]
        dialog = TkAddSynthDialog(self.root, self.app, st, is_efx=True, is_controller=False)
        self.root.wait_window(dialog)

    def _show_add_controller_dialog(self, event):
        w = event.widget
        st = w.config()["text"][-1]
        dialog = TkAddSynthDialog(self.root, self.app, st, is_efx=False, is_controller=True)
        self.root.wait_window(dialog)
        
    def _add_synth_group(self):
        sh = self.app.ls_parser.synthhelper
        sh.new_group()
        
    def add_synth_group(self, name=None):
        gw = GroupWindow(self.app, self.root, name)
        # gw.transient(self.root)  # If executed keeps main app window behind all other windows.
        self.group_windows.append(gw)
        self.status("Added new Synth Group Window")
        return gw

    def display_synth_editor(self, sid):
        try:
            swin = self[sid]
            grpid = swin.group_index
            grp = self.group_windows[grpid]
            #grp.deiconify()
            grp.show_synth_editor(sid)
        except (KeyError, IndexError):
            msg = "Can not find editor for %s" % sid
            self.warning(msg)

    def update_progressbar(self, count, value):
        self._progressbar.config(mode="determinate", maximum=count)
        self._progressbar.step()
        self.root.update_idletasks()
            
    def busy(self, flag, message=""):
        if message:
            self.status(message)
        self._progressbar.config(mode="indeterminate")
        if flag:
            self._progressbar.grid(row=0, column=PROGRESSBAR_COLUMN, sticky='w', padx=8)
            self._progressbar.start()
        else:
            self._progressbar.stop()
            # self._progressbar.grid_remove()
        self.root.update_idletasks()

    def save_scene(self, *_):
        options = {'defaultextension' : '.llia',
                   'filetypes' : [('Llia Scenes', '*.llia'),
                                  ('all files', '*')],
                   'initialfile' : self._scene_filename,
                   'parent' : self.root,
                   'title' : "Save Llia Scene"}
        filename = tkFileDialog.asksaveasfilename(**options)
        if filename:
            try:
                self.app.ls_parser.save_scene(filename)
                self._scene_filename = filename
                self.status("Scene saved as '%s'" % filename)
            except Exception as ex:
                self.warning(ex.message)
        else:
            self.status("Scene save canceld")    

    def load_scene(self, *_):
        options = {'defaultextension' : '.llia',
                   'filetypes' : [('Llia Scenes', '*.llia'),
                                  ('all files', '*')],
                   'initialfile' : self._scene_filename,
                   'parent' : self.root,
                   'title' : "Load Llia Scene"}
        filename = tkFileDialog.askopenfilename(**options)
        if filename:
            try:
                self.app.ls_parser.load_scene(filename)
                self.status("Scene '%s' loaded" % filename)
                self._scene_filename = filename
            except Exception as ex:
                self.warning(ex.message)
        else:
            self.status("Load scene canceld")
            
    def tabula_rasa(self):
        for grp in self.group_windows:
            grp.tabula_rasa()
        self.group_windows = []

    def _interactive_tabula_rasa(self, *_):
        # ISSUE: Check config and ask user confirmation before existing
        self.app.ls_parser.tabula_rasa()
Ejemplo n.º 2
0
class CoilSnakeFrontend:
    PREFS_FNAME = "prefs.yml"
    def __init__(self):
        try:
            with open(self.PREFS_FNAME, 'r') as f:
                self._prefs = yaml.load(f, Loader=yaml.CSafeLoader)
        except IOError:
            self._prefs = { 'title': 0 }
    def getPrefsValue(self, key):
        try:
            return self._prefs[key]
        except KeyError:
            return ""
    def savePrefs(self):
        with open(self.PREFS_FNAME, "w") as f:
            yaml.dump(self._prefs, f, Dumper=yaml.CSafeDumper)
    def toggleTitles(self):
        self._prefs["title"] = (~(self._prefs["title"]))|1
        self.savePrefs()
    def aboutMenu(self):
        am = Toplevel(self._root)
        #Label(am, text="CoilSnake " + CoilSnake._VERSION,
        #        font=("Helvetica", 16)).pack(fill=X)
        photo = PhotoImage(file="resources/logo.gif")
        photoLabel = Label(am, image=photo)
        photoLabel.photo = photo
        photoLabel.pack(fill='both', expand=1)

        Label(am,
                text=
                (("CoilSnake %s\n"
                + "Released on %s\n\n"
                + "Created by MrTenda\n"
                + "Logo art by Reg\n\n"
                + "With help from\n"
                + "  Penguin, Reg, H.S, Michael1,\n"
                + "  Mr. Accident, AnyoneEB, Goplat, Captain Bozo,\n"
                + "  and the rest of the PK Hack community.\n"
                + "\n"
                + "Running on Python %s") % (
                    CoilSnake._VERSION,
                    CoilSnake._RELEASE_DATE, python_version())),
                anchor="w",justify="left",bg="white",borderwidth=5,
                relief=GROOVE).pack(
                        fill='both', expand=1)
        Button(am, text="Toggle Alternate Titles",
                command=self.toggleTitles).pack(fill=X)
        Button(am, text="Close", command=am.destroy).pack(fill=X)
        am.resizable(False, False)
        am.title("About")
    def setText(self, entry, str):
        entry.delete(0, END)
        entry.insert(0, str)
        entry.xview(END)
    def setEmulatorExe(self):
        self._prefs["Emulator"] = tkFileDialog.askopenfilename(
                parent=self._root,
                title="Select an Emulator Executable",
                initialfile=self.getPrefsValue("Emulator"))
        self.savePrefs()
    def setCccExe(self):
        self._prefs["CCC"] = tkFileDialog.askopenfilename(
                parent=self._root,
                title="Select the CCC Executable",
                initialfile=self.getPrefsValue("CCC"))
        self.savePrefs()
    def toggleErrorDetails(self):
        if self.getPrefsValue("ErrorDetails") == "1":
            self._prefs["ErrorDetails"] = "0"
        else:
            self._prefs["ErrorDetails"] = "1"
    def browseForRom(self, entry, save=False):
        if save:
            fname = tkFileDialog.asksaveasfilename(
                    parent=self._root, title="Select an output ROM",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')])
        else:
            fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs', '*.sfc'), ('All files','*.*')])
        if len(fname) > 0:
            self.setText(entry, fname)
    def browseForProject(self, entry, save=False):
        fname = tkFileDialog.askdirectory(
                parent=self._root, title="Select a Project Directory",
                mustexist=(not save))
        self.setText(entry, fname)
    def runRom(self, entry):
        romFname = entry.get()
        if self.getPrefsValue("Emulator") == "":
            tkMessageBox.showerror(parent=self._root,
                    title="Error",
                    message="""Emulator executable not specified.
Please specify it in the Preferences menu.""")
        elif romFname != "":
            Popen([self.getPrefsValue("Emulator"), romFname])
    def resetConsole(self):
        self._console.delete(1.0, END)
        self._console.see(END)
    def doExport(self, romEntry, projEntry):
        if (romEntry.get() != "") and (projEntry.get() != ""):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            self._upgradeB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["export_rom"] = romEntry.get()
            self._prefs["export_proj"] = projEntry.get()
            self.savePrefs()

            self._progBar["value"] = 0
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(10)
            thread = Thread(target=self._doExportHelp,
                    args=(romEntry.get(), projEntry.get(),
                        time(), ))
            thread.start()
    def _doExportHelp(self, rom, proj, startTime):
        try:
            if self._cs.romToProj(rom, proj):
                print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError:", str(inst)
            if self.getPrefsValue("ErrorDetails") == "1":
                print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        self._upgradeB["state"] = NORMAL
        del(self._cs)
    def doImport(self, projEntry, cleanRomEntry, romEntry):
        if self.getPrefsValue("CCC") == "":
            tkMessageBox.showerror(parent=self._root,
                    title="Error",
                    message="""CCScript Compiler executable not specified.
Please specify it in the Preferences menu.""")
        elif ((projEntry.get() != "") and (cleanRomEntry.get() != "")
                and (romEntry.get() != "")):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            self._upgradeB["state"] = DISABLED
            self._importRunB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["import_proj"] = projEntry.get()
            self._prefs["import_baserom"] = cleanRomEntry.get()
            self._prefs["import_rom"] = romEntry.get()
            self.savePrefs()

            oldRom = cleanRomEntry.get()
            newRom = romEntry.get()
            projDir = projEntry.get()
            # Reset the progress bar
            self._progBar["value"] = 0

            self._console.delete(1.0, END)
            # Run CoilSnake as usual
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(10)
            thread = Thread(target=self._doImportHelp,
                    args=(projDir, oldRom, newRom, time()))
            thread.start()
    def _doImportHelp(self, proj, oldRom, newRom, startTime):
        try:
            if self._cs.projToRom(proj, oldRom, newRom,
                    self.getPrefsValue("CCC")):
                print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError:", str(inst)
            if self.getPrefsValue("ErrorDetails") == "1":
                print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        self._upgradeB["state"] = NORMAL
        self._importRunB["state"] = NORMAL
        del(self._cs)
    def doUpgrade(self, romEntry, projEntry):
        if (romEntry.get() != "") and (projEntry.get() != ""):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            self._upgradeB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["upgrade_rom"] = romEntry.get()
            self._prefs["upgrade_proj"] = projEntry.get()
            self.savePrefs()

            self._progBar["value"] = 0
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(10)
            thread = Thread(target=self._doUpgradeHelp,
                    args=(romEntry.get(), projEntry.get(),
                        time(), ))
            thread.start()
    def _doUpgradeHelp(self, rom, proj, startTime):
        try:
            if self._cs.upgradeProject(rom, proj):
                print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError:", str(inst)
            if self.getPrefsValue("ErrorDetails") == "1":
                print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        self._upgradeB["state"] = NORMAL
        del(self._cs)
    def expandRom(self, ex=False):
        r = Rom.Rom('resources/romtypes.yaml')
        fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM to expand",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')])
        if len(fname) > 0:
            r.load(fname)
            if ((not ex) and (len(r) >= 0x400000)) or (ex and (len(r) >= 0x600000)):
                tkMessageBox.showerror(parent=self._root, title="Error", message="This ROM is already expanded.")
            else:
                if ex:
                    r.expand(0x600000)
                else:
                    r.expand(0x400000)
                r.save(fname)
                del(r)
                tkMessageBox.showinfo(parent=self._root, title="Expansion Successful", message="Your ROM was expanded.")
    def expandRomEx(self):
        self.expandRom(ex=True)
    def addHeaderRom(self):
        r = Rom.Rom('resources/romtypes.yaml')
        fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM to which to add a header",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')])
        if len(fname) > 0:
            r.load(fname)
            r.addHeader()
            r.save(fname)
            del(r)
            tkMessageBox.showinfo(parent=self._root, title="Header Addition Successful", message="Your ROM was given a header.")
    def stripHeaderRom(self):
        r = Rom.Rom('resources/romtypes.yaml')
        fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM from which to remove a header",
                    filetypes=[('SNES ROMs','*.smc'), ('SNES ROMs','*.sfc'), ('All files','*.*')])
        if len(fname) > 0:
            r.load(fname)
            r.save(fname)
            del(r)
            tkMessageBox.showinfo(parent=self._root, title="Header Remove Successful", message="Your ROM's header was removed.")
    def main(self):
        self._root = Tk()
        if self.getPrefsValue("title") == 1:
            self._root.wm_title(getTitle() + " " + CoilSnake._VERSION)
        else:
            self._root.wm_title("CoilSnake" + " " + CoilSnake._VERSION)
            if self.getPrefsValue("title") == 0:
                self._prefs["title"] = 1
                self.savePrefs()

        menuBar = Menu(self._root)
        # Preferences pulldown menu
        prefMenu = Menu(menuBar, tearoff=0)
        prefMenu.add_command(label="CCScript Compiler Executable",
                command=self.setCccExe)
        prefMenu.add_command(label="Emulator Executable",
                command=self.setEmulatorExe)
        prefMenu.add_command(label="Toggle Error Details",
                command=self.toggleErrorDetails)
        menuBar.add_cascade(label="Preferences", menu=prefMenu)
        # Tools pulldown menu
        toolsMenu = Menu(menuBar, tearoff=0)
        toolsMenu.add_command(label="Expand ROM to 32 MBit",
                command=self.expandRom)
        toolsMenu.add_command(label="Expand ROM to 48 MBit",
                command=self.expandRomEx)
        toolsMenu.add_command(label="Add Header to ROM",
                command=self.addHeaderRom)
        toolsMenu.add_command(label="Remove Header from ROM",
                command=self.stripHeaderRom)
        menuBar.add_cascade(label="Tools", menu=toolsMenu)
        # Help menu
        helpMenu = Menu(menuBar, tearoff=0)
        helpMenu.add_command(label="About", command=self.aboutMenu)
        menuBar.add_cascade(label="Help", menu=helpMenu)

        self._root.config(menu=menuBar)


        # Left side: Export
        a=Label(self._root, text="ROM -> New Project",justify=CENTER).grid(
                row=0, column=1, columnspan=1)
        # ROM file selector
        Label(self._root, text="Input ROM:").grid(
                row=1, column=0, sticky=E)
        inRom = Entry(self._root)
        inRom.grid(row=1, column=1)
        self.setText(inRom, self.getPrefsValue("export_rom"))
        def browseTmp():
            self.browseForRom(inRom)
        def runTmp():
            self.runRom(inRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=1, column=2, sticky=W)
        Button(self._root, text="Run",
                command=runTmp).grid(row=1, column=3, sticky=W)
        # Project dir selector
        Label(self._root, text="Output Directory:").grid(
                row=2, column=0, sticky=E)
        outProj = Entry(self._root)
        outProj.grid(row=2, column=1)
        self.setText(outProj, self.getPrefsValue("export_proj"))
        def browseTmp():
            self.browseForProject(outProj, save=True)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=2, column=2, sticky=W)
        # Export Button
        def exportTmp():
            self.doExport(inRom, outProj)
        self._exportB = Button(self._root, text="Decompile", command=exportTmp)
        self._exportB.grid(row=3, column=1, columnspan=1, sticky=W+E)

        # Right side: Import
        Label(self._root, text="Project -> New ROM").grid(
                row=0, column=5, columnspan=1)
        # Base ROM file selector
        Label(self._root, text="Base Expanded ROM:").grid(
                row=1, column=4, sticky=E)
        baseRom = Entry(self._root)
        baseRom.grid(row=1, column=5)
        self.setText(baseRom, self.getPrefsValue("import_baserom"))
        def browseTmp():
            self.browseForRom(baseRom)
        def runTmp():
            self.runRom(baseRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=1, column=6)
        Button(self._root, text="Run",
                command=runTmp).grid(row=1, column=7, sticky=E+W)
        # Project dir selector
        Label(self._root, text="Project Directory:").grid(
                row=2, column=4, sticky=E)
        inProj = Entry(self._root, text=self.getPrefsValue("import_proj"))
        inProj.grid(row=2, column=5)
        self.setText(inProj, self.getPrefsValue("import_proj"))
        def browseTmp():
            self.browseForProject(inProj, save=False)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=2, column=6)
        # ROM file selector
        Label(self._root, text="Output ROM:").grid(
                row=3, column=4, sticky=E)
        outRom = Entry(self._root, text=self.getPrefsValue("import_rom"))
        outRom.grid(row=3, column=5)
        self.setText(outRom, self.getPrefsValue("import_rom"))
        def browseTmp():
            self.browseForRom(outRom, save=True)
        def runTmp():
            self.runRom(outRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=3, column=6)
        self._importRunB = Button(self._root, text="Run",
                command=runTmp)
        self._importRunB.grid(row=3, column=7, sticky=E+W)
        # Import Button
        def importTmp():
            self.doImport(inProj, baseRom, outRom)
        self._importB = Button(self._root, text="Compile", command=importTmp)
        self._importB.grid(row=4, column=5, columnspan=1, sticky=W+E)

        # Upgrade
        a=Label(self._root, text="Upgrade Project",justify=CENTER).grid(
                row=5, column=1, columnspan=1)
        # ROM file selector
        Label(self._root, text="Base ROM:").grid(
                row=6, column=0, sticky=E)
        upgradeRom = Entry(self._root)
        upgradeRom.grid(row=6, column=1)
        self.setText(upgradeRom, self.getPrefsValue("upgrade_rom"))
        def browseTmp():
            self.browseForRom(upgradeRom)
        def runTmp():
            self.runRom(upgradeRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=6, column=2, sticky=W)
        Button(self._root, text="Run",
                command=runTmp).grid(row=6, column=3, sticky=W)
        # Project dir selector
        Label(self._root, text="Project Directory:").grid(
                row=7, column=0, sticky=E)
        upgradeProj = Entry(self._root)
        upgradeProj.grid(row=7, column=1)
        self.setText(upgradeProj, self.getPrefsValue("upgrade_proj"))
        def browseTmp():
            self.browseForProject(upgradeProj, save=True)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=7, column=2, sticky=W)
        # Upgrade Button
        def upgradeTmp():
            self.doUpgrade(upgradeRom, upgradeProj)
        self._upgradeB = Button(self._root, text="Upgrade", command=upgradeTmp)
        self._upgradeB.grid(row=8, column=1, columnspan=1, sticky=W+E)

        # Progress bar
        self._progBar = Progressbar(self._root,
                orient=HORIZONTAL, mode='determinate')
        self._progBar.grid(row=9, column=0, columnspan=8, sticky=W+E)
        def updProg(dp):
            Progress.__updateProgress__(dp)
            # Note: The number of modules is hardcoded here as "19"
            self._progBar.step((90.0/19) * (dp/100.0))
        Progress.updateProgress = updProg

        # Console
        consoleFrame = Frame(self._root)
        consoleFrame.grid(row=10, column=0, columnspan=8, sticky=W+E)
        s = Scrollbar(consoleFrame)
        self._console = Text(consoleFrame, width=80, height=6)
        s.pack(side=RIGHT, fill=Y)
        self._console.pack(fill=X)
        s.config(command=self._console.yview)
        self._console.config(yscrollcommand=s.set)

        # Stdout Redirector
        class StdoutRedirector:
            def __init__(self, textArea):
                self._tA = textArea
            def write(self,str):
                if str.startswith("\b\b\b\b\b\b\b\b"):
                    self._tA.delete("end-9c", "end")
                    self._tA.insert(END, str[8:])
                else:
                    self._tA.insert(END, str)
                self._tA.see(END)
            def flush(self):
                pass
        self._consoleStdout = StdoutRedirector(self._console)
        sys.stdout = self._consoleStdout
        sys.stderr = self._consoleStdout

        self._root.mainloop()
Ejemplo n.º 3
0
class FindServer(Frame):

    def __init__(self, parent, controller):
        Frame.__init__(self, parent)
        self.selected = "";
        self.controller = controller
        label = Label(self, text="Select server", font=TITLE_FONT, justify=CENTER, anchor=CENTER)
        label.pack(side="top", fill="x", pady=10)
        
        self.button1 = Button(self, text="Next",state="disabled", command=self.callback_choose)
        button2 = Button(self, text="Refresh", command=self.callback_refresh)        
        button3 = Button(self, text="Back", command=self.callback_start)
        
        scrollbar = Scrollbar(self)
        self.mylist = Listbox(self, width=100, yscrollcommand = scrollbar.set )
        self.mylist.bind("<Double-Button-1>", self.twoClick)

        self.button1.pack()
        button2.pack()
        button3.pack()
        # create list with a scroolbar
        scrollbar.pack( side = "right", fill="y" )
        self.mylist.pack( side = "top", fill = "x", ipadx=20, ipady=20, padx=20, pady=20 )
        scrollbar.config( command = self.mylist.yview )
        # create a progress bar
        label2 = Label(self, text="Refresh progress bar", justify='center', anchor='center')
        label2.pack(side="top", fill="x")
        
        self.bar_lenght = 200
        self.pb = Progressbar(self, length=self.bar_lenght, mode='determinate')
        self.pb.pack(side="top", anchor='center', ipadx=20, ipady=20, padx=10, pady=10)
        self.pb.config(value=0)

    # to select he server user must double-click on it
    def twoClick(self, event):
        widget = event.widget
        selection=widget.curselection()
        value = widget.get(selection[0])
        self.selected = value
        self.button1.config(state="normal")
        # save the selected server in a global variable
        SELECTED_SERV = SERVER_LIST[selection[0]]
        set_globvar(SELECTED_SERV)      
    
    # listen for broadcasts from port 8192
    def listen_broadcasts(self, port, timeout):
        # Set the progress bar to 0
        self.pb.config(value=0)
        step_size = ((self.bar_lenght/(MAX_NR_OF_SERVERS+1))/2)
        list_of_servers = []
        # Initialize the listener
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        s.bind(('', port))
        s.settimeout(LISTENING_TIMEOUT)
        # Listen for a number of times to get multiple servers
        for _ in range(MAX_NR_OF_SERVERS + 1):
            # Update the progress bar
            self.pb.step(step_size)
            self.pb.update_idletasks()
            try:
                message, address = s.recvfrom(8192) 
                m_split = message.split(';')
                if m_split[0] == '\HELLO':
                    server_id = (m_split[1], address)
                    # Check if the server has not yet broadcasted itself.
                    if server_id not in list_of_servers:
                        list_of_servers.append(server_id)              
            except:
                pass
        # Close the socket
        s.close()
        if not list_of_servers:
            # If no server found, pop a warning message.
            tkMessageBox.showwarning("Find Servers", "No servers found. Refresh or create a new game.")
        # Set the progress bar back to 0
        self.pb.config(value=0)
        # Return the whole list of available servers
        return list_of_servers
    
    # service the refresh button
    def callback_refresh(self):
        global SERVER_LIST
        self.mylist.delete(0,END)
        SERVER_LIST = self.listen_broadcasts(BROADCASTING_PORT, LISTENING_TIMEOUT)
        for server_el in SERVER_LIST:
            self.mylist.insert(END,(" "+str(server_el[0])+"  IP: "+str(server_el[1])+"  Time: "+str(time.asctime())))
    
    def callback_choose(self):
        self.mylist.delete(0,END)
        self.button1.config(state="disabled")
        self.controller.show_frame("ChooseType")
        
    def callback_start(self):
        self.mylist.delete(0,END)
        self.button1.config(state="disabled")
        self.controller.show_frame("StartPage")
Ejemplo n.º 4
0
class ScreenShooterGui(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.title("WebSite ScreenShooter")
        self.geometry("390x420")

        self.mainFrame = Frame(self)
        self.mainFrame.pack(pady=5, padx=5)

        self.urlLabelFrame = Frame(self.mainFrame)
        self.urlLabelFrame.pack(pady=5, side=TOP, fill=X)
        self.urlImportLabel = Label(self.urlLabelFrame, text="web URLs:")
        self.urlImportLabel.pack(side=LEFT, padx=5)

        self.importTextFrame = Frame(self.mainFrame)
        self.importTextFrame.pack(pady=5, side=TOP, fill=X)
        self.yTextScrollbar = Scrollbar(self.importTextFrame)
        self.yTextScrollbar.pack(side=RIGHT, fill=Y)
        self.xTextScrollbar = Scrollbar(self.importTextFrame,
                                        orient=HORIZONTAL)
        self.xTextScrollbar.pack(side=BOTTOM, fill=X)
        self.importUrlsText = Text(self.importTextFrame,
                                   padx=5,
                                   pady=5,
                                   wrap=NONE,
                                   width=50,
                                   height=10,
                                   yscrollcommand=self.yTextScrollbar.set,
                                   xscrollcommand=self.xTextScrollbar.set)
        self.importUrlsText.pack(side=TOP, padx=5, pady=5, fill=X)
        self.yTextScrollbar.config(command=self.importUrlsText.yview)
        self.xTextScrollbar.config(command=self.importUrlsText.xview)

        self.outputLabelFrame = Frame(self.mainFrame)
        self.outputLabelFrame.pack(pady=5, side=TOP, fill=X)
        self.outputFileLabel = Label(self.outputLabelFrame,
                                     text="Path to the output folder:")
        self.outputFileLabel.pack(side=LEFT, padx=5)

        self.outputFieldFrame = Frame(self.mainFrame)
        self.outputFieldFrame.pack(pady=5, side=TOP, fill=X)
        self.outputFieldEntry = Entry(self.outputFieldFrame,
                                      name="outputFile",
                                      width=30)
        self.outputFieldEntry.pack(side=LEFT, padx=5)
        self.btnBrowse = Button(self.outputFieldFrame,
                                height=1,
                                width=6,
                                text="Browse...",
                                command=self.browse)
        self.btnBrowse.pack(side=RIGHT, padx=5)

        self.controlsFrame = Frame(self.mainFrame)
        self.controlsFrame.pack(pady=5, side=TOP, fill=X)
        self.btnClose = Button(self.controlsFrame,
                               height=1,
                               width=6,
                               text="Close",
                               command=self.close)
        self.btnClose.pack(side=LEFT, padx=5)
        self.btnRun = Button(self.controlsFrame,
                             height=1,
                             width=6,
                             text="Run",
                             command=self.run)
        self.btnRun.pack(side=RIGHT, padx=5)

        # *** PROGRESS BAR ***
        self.status = Progressbar(self.mainFrame,
                                  orient='horizontal',
                                  length=310,
                                  mode='determinate',
                                  value=0,
                                  maximum=100)
        self.status.pack(pady=5, padx=5, side=BOTTOM)

    def browse(self):
        outputPath = tkFileDialog.askdirectory(parent=self)
        self.outputFieldEntry.delete(0, last=END)
        self.outputFieldEntry.insert(0, outputPath)

    def close(self):
        self.destroy()

    def run(self):
        textUrls = self.importUrlsText.get('1.0', 'end')
        # creating a list ignoring empty values
        listOfUrls = [x for x in textUrls.split("\n") if x]
        stepAmount = 100 / len(listOfUrls)
        for i, url in enumerate(listOfUrls):
            url = url.strip()
            # dirty solution to find ebay items ids
            item_ids = re.findall(r'\/[1-4]\d{11,12}', url, re.I)
            if len(item_ids) > 0:
                output = '{root_path}/{url_base}_eBayItem-{item}.png'.format(
                    root_path=self.outputFieldEntry.get(),
                    url_base=url.split("/")[2],
                    item=str(item_ids[0][1:]))
            else:
                output = '{root_path}/{url_base}.png'.format(
                    root_path=self.outputFieldEntry.get(),
                    url_base=url.split("/")[2])

            # check if file already exists:
            if os.path.isfile(output):
                file_ver = '-({ver}).png'.format(ver=i)
                output = re.sub(r'\.png$', file_ver, output)

            screenshot(url, output)
            add_url_time(url, output)
            self.status.step(stepAmount)
            self.update()

    def mainloop(self):
        Tk.mainloop(self)
Ejemplo n.º 5
0
class CoilSnakeFrontend:
    PREFS_FNAME = "prefs.yml"
    def __init__(self):
        try:
            with open(self.PREFS_FNAME, 'r') as f:
                self._prefs = yaml.load(f, Loader=yaml.CSafeLoader)
        except IOError:
            self._prefs = {
                    'Emulator': "",
                    'CCC': "",
                    'import_proj': "",
                    'import_baserom': "",
                    'import_rom': "",
                    'export_proj': "",
                    'export_rom': "",
                    'title': 0,
                    }
    def savePrefs(self):
        with open(self.PREFS_FNAME, "w") as f:
            yaml.dump(self._prefs, f, Dumper=yaml.CSafeDumper)
    def toggleTitles(self):
        self._prefs["title"] = (~(self._prefs["title"]))|1
        self.savePrefs()
    def aboutMenu(self):
        am = Toplevel(self._root)
        Label(am, text="CoilSnake " + _version,
                font=("Helvetica", 16)).pack(fill=X)
        Label(am,
                text=
                "Released on " + _releaseDate + ".\n\n"
                + "Created by MrTenda.\n\n"
                + "With help from\n"
                + "  Penguin, Mr. Accident, Goplat,\n"
                + "  AnyoneEB, Captain Bozo,\n"
                + "  and the rest of the PK Hack community.",
                anchor="w",justify="left",bg="white",borderwidth=5,
                relief=GROOVE).pack(
                        fill='both', expand=1)
        Button(am, text="Toggle Alternate Titles",
                command=self.toggleTitles).pack(fill=X)
        Button(am, text="Close", command=am.destroy).pack(fill=X)
        am.resizable(False, False)
        am.title("About")
    def setText(self, entry, str):
        entry.delete(0, END)
        entry.insert(0, str)
        entry.xview(END)
    def setEmulatorExe(self):
        self._prefs["Emulator"] = tkFileDialog.askopenfilename(
                parent=self._root,
                title="Select an Emulator Executable",
                initialfile=self._prefs["Emulator"])
        self.savePrefs()
    def setCccExe(self):
        self._prefs["CCC"] = tkFileDialog.askopenfilename(
                parent=self._root,
                title="Select the CCC Executable",
                initialfile=self._prefs["CCC"])
        self.savePrefs()
    def browseForRom(self, entry, save=False):
        if save:
            fname = tkFileDialog.asksaveasfilename(
                    parent=self._root, title="Select an output ROM",
                    filetypes=[('SNES ROMs','*.smc'), ('All files','*.*')])
        else:
            fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM",
                    filetypes=[('SNES ROMs','*.smc'), ('All files','*.*')])
        self.setText(entry, fname)
    def browseForProject(self, entry, save=False):
        fname = tkFileDialog.askdirectory(
                parent=self._root, title="Select a Project Directory",
                mustexist=(not save))
        self.setText(entry, fname)
    def runRom(self, entry):
        romFname = entry.get()
        if self._prefs["Emulator"] == "":
            tkMessageBox.showerror(parent=self._root,
                    title="Error",
                    message="""Emulator executable not specified.
Please specify it in the Preferences menu.""")
        elif romFname != "":
            Popen([self._prefs["Emulator"], romFname])
    def resetConsole(self):
        self._console.delete(1.0, END)
        self._console.see(END)
    def doExport(self, romEntry, projEntry):
        if (romEntry.get() != "") and (projEntry.get() != ""):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["export_rom"] = romEntry.get()
            self._prefs["export_proj"] = projEntry.get()
            self.savePrefs()

            self._progBar["value"] = 0
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(10)
            thread = Thread(target=self._doExportHelp,
                    args=(romEntry.get(), projEntry.get()+"/Project.snake",
                        time(), ))
            thread.start()
    def _doExportHelp(self, rom, proj, startTime):
        try:
            self._cs.romToProj(rom, proj)
            print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError! Something went wrong:"
            print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        del(self._cs)
    def doImport(self, projEntry, cleanRomEntry, romEntry):
        if self._prefs["CCC"] == "":
            tkMessageBox.showerror(parent=self._root,
                    title="Error",
                    message="""CCScript Compiler executable not specified.
Please specify it in the Preferences menu.""")
        elif ((projEntry.get() != "") and (cleanRomEntry.get() != "")
                and (romEntry.get() != "")):
            # Update the GUI
            self.resetConsole()
            self._exportB["state"] = DISABLED
            self._importB["state"] = DISABLED
            self._importRunB["state"] = DISABLED
            # Save the fields to preferences
            self._prefs["import_proj"] = projEntry.get()
            self._prefs["import_baserom"] = cleanRomEntry.get()
            self._prefs["import_rom"] = romEntry.get()
            self.savePrefs()

            oldRom = cleanRomEntry.get()
            newRom = romEntry.get()
            projDir = projEntry.get()
            # Reset the progress bar
            self._progBar["value"] = 0
            # Copy the clean rom to the output rom
            self._console.delete(1.0, END)
            print "Copying ROM"
            copyfile(oldRom, newRom)
            self._progBar.step(2)
            # Get a list of the script filenames in projDir/ccscript
            scriptFnames = [ projDir + "/ccscript/" + x 
                    for x in listdir(projDir + "/ccscript")
                    if x.endswith('.ccs') ]
            # Compile scripts using the CCC, and put the data at $F00000
            print "Calling external CCScript Compiler"
            process = Popen(
                    [self._prefs["CCC"], "-n", "-o", newRom, "-s", "F00000",
                        "--summary", projDir + "/ccscript/summary.txt"] +
                    scriptFnames)
            process.wait()
            self._progBar.step(4)
            # Run CoilSnake as usual
            print "Initializing CoilSnake\n"
            self._cs = CoilSnake.CoilSnake()
            self._progBar.step(4)
            thread = Thread(target=self._doImportHelp,
                    args=(projDir+"/Project.snake", newRom, time()))
            thread.start()
    def _doImportHelp(self, proj, rom, startTime):
        try:
            self._cs.projToRom(proj, rom, rom)
            print "Done! (Took %0.2fs)" % (time()-startTime)
        except Exception as inst:
            print "\nError! Something went wrong:"
            print_exc()
        self._progBar["value"] = 0
        self._exportB["state"] = NORMAL
        self._importB["state"] = NORMAL
        self._importRunB["state"] = NORMAL
        del(self._cs)
    def expandRom(self, ex=False):
        r = Rom.Rom('romtypes.yaml')
        fname = tkFileDialog.askopenfilename(
                    parent=self._root, title="Select a ROM to expand",
                    filetypes=[('SNES ROMs','*.smc'), ('All files','*.*')])
        r.load(fname)
        EbRomExpander.expandRom(r, ex)
        r.save(fname)
        del(r)
        tkMessageBox.showinfo("Expansion Successful",
                "Your ROM was expanded.")
    def expandRomEx(self):
        self.expandRom(ex=True)
    def main(self):
        self._root = Tk()
        if self._prefs["title"] == 1:
            self._root.wm_title(getTitle() + " " + _version)
        else:
            self._root.wm_title("CoilSnake" + " " + _version)
            if self._prefs["title"] == 0:
                self._prefs["title"] = 1
                self.savePrefs()

        menuBar = Menu(self._root)
        # Preferences pulldown menu
        prefMenu = Menu(menuBar, tearoff=0)
        prefMenu.add_command(label="CCScript Compiler Executable",
                command=self.setCccExe)
        prefMenu.add_command(label="Emulator Executable",
                command=self.setEmulatorExe)
        menuBar.add_cascade(label="Preferences", menu=prefMenu)
        # Tools pulldown menu
        toolsMenu = Menu(menuBar, tearoff=0)
        toolsMenu.add_command(label="Expand ROM to 32 MBit",
                command=self.expandRom)
        toolsMenu.add_command(label="Expand ROM to 48 MBit",
                command=self.expandRomEx)
        menuBar.add_cascade(label="Tools", menu=toolsMenu)
        # Help menu
        helpMenu = Menu(menuBar, tearoff=0)
        helpMenu.add_command(label="About", command=self.aboutMenu)
        menuBar.add_cascade(label="Help", menu=helpMenu)

        self._root.config(menu=menuBar)


        # Left side: Export
        a=Label(self._root, text="ROM -> New Project",justify=CENTER).grid(
                row=0, column=1, columnspan=1)
        # ROM file selector
        Label(self._root, text="Input ROM:").grid(
                row=1, column=0, sticky=E)
        inRom = Entry(self._root)
        inRom.grid(row=1, column=1)
        self.setText(inRom, self._prefs["export_rom"])
        def browseTmp():
            self.browseForRom(inRom)
        def runTmp():
            self.runRom(inRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=1, column=2, sticky=W)
        Button(self._root, text="Run",
                command=runTmp).grid(row=1, column=3, sticky=W)
        # Project dir selector
        Label(self._root, text="Output Directory:").grid(
                row=2, column=0, sticky=E)
        outProj = Entry(self._root)
        outProj.grid(row=2, column=1)
        self.setText(outProj, self._prefs["export_proj"])
        def browseTmp():
            self.browseForProject(outProj, save=True)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=2, column=2, sticky=W)
        # Export Button
        def exportTmp():
            self.doExport(inRom, outProj)
        self._exportB = Button(self._root, text="Export", command=exportTmp)
        self._exportB.grid(row=4, column=1, columnspan=1, sticky=W+E)

        # Right side: Import
        Label(self._root, text="Project -> New ROM").grid(
                row=0, column=5, columnspan=1)
        # Base ROM file selector
        Label(self._root, text="Base Expanded ROM:").grid(
                row=1, column=4, sticky=E)
        baseRom = Entry(self._root)
        baseRom.grid(row=1, column=5)
        self.setText(baseRom, self._prefs["import_baserom"])
        def browseTmp():
            self.browseForRom(baseRom)
        def runTmp():
            self.runRom(baseRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=1, column=6)
        Button(self._root, text="Run",
                command=runTmp).grid(row=1, column=7, sticky=W)
        # Project dir selector
        Label(self._root, text="Project Directory:").grid(
                row=2, column=4, sticky=E)
        inProj = Entry(self._root, text=self._prefs["import_proj"])
        inProj.grid(row=2, column=5)
        self.setText(inProj, self._prefs["import_proj"])
        def browseTmp():
            self.browseForProject(inProj, save=False)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=2, column=6)
        # ROM file selector
        Label(self._root, text="Output ROM:").grid(
                row=3, column=4, sticky=E)
        outRom = Entry(self._root, text=self._prefs["import_rom"])
        outRom.grid(row=3, column=5)
        self.setText(outRom, self._prefs["import_rom"])
        def browseTmp():
            self.browseForRom(outRom, save=True)
        def runTmp():
            self.runRom(outRom)
        Button(self._root, text="Browse...",
                command=browseTmp).grid(row=3, column=6)
        self._importRunB = Button(self._root, text="Run",
                command=runTmp)
        self._importRunB.grid(row=3, column=7, sticky=W)
        # Import Button
        def importTmp():
            self.doImport(inProj, baseRom, outRom)
        self._importB = Button(self._root, text="Import", command=importTmp)
        self._importB.grid(row=4, column=5, columnspan=1, sticky=W+E)

        # Progress bar
        self._progBar = Progressbar(self._root,
                orient=HORIZONTAL, mode='determinate')
        self._progBar.grid(row=5, column=0, columnspan=8, sticky=W+E)
        def updProg(dp):
            Progress.__updateProgress__(dp)
            # Note: The number of modules is hardcoded here as "12"
            self._progBar.step((90.0/12) * (dp/100.0))
        Progress.updateProgress = updProg

        # Console
        consoleFrame = Frame(self._root)
        consoleFrame.grid(row=6, column=0, columnspan=8, sticky=W+E)
        s = Scrollbar(consoleFrame)
        self._console = Text(consoleFrame, width=80, height=6)
        s.pack(side=RIGHT, fill=Y)
        self._console.pack(fill=X)
        s.config(command=self._console.yview)
        self._console.config(yscrollcommand=s.set)

        # Stdout Redirector
        class StdoutRedirector:
            def __init__(self, textArea):
                self._tA = textArea
            def write(self,str):
                if str.startswith("\b\b\b\b\b\b\b\b"):
                    self._tA.delete("end-9c", "end")
                    self._tA.insert(END, str[8:])
                else:
                    self._tA.insert(END, str)
                self._tA.see(END)
            def flush(self):
                pass
        self._consoleStdout = StdoutRedirector(self._console)
        sys.stdout = self._consoleStdout
        sys.stderr = self._consoleStdout

        self._root.mainloop()
class RecordFrame(MyFrame):

    def __init__(self, parent):
        MyFrame.__init__(self, parent, 'Parametrize', (100,0))

        self.record_options = DataDumper.load_json_data(Constants.CONFIG_PATH)['record_options']
        self.record_time.set_value(self.record_options['duration'])
        self.thread = None

    def init_ui(self):
        MyFrame.init_ui(self)

        self.columnconfigure(0, weight=2, minsize=150)
        self.columnconfigure(1, weight=3, minsize=100)

        self.file_name      = TextEntry(self, 'Recorded file name')
        self.record_time    = TextEntry(self, 'Record time')
        self.progress_bar   = Progressbar(self, orient='horizontal', mode='determinate')

        self.progress_bar.grid(columnspan=2, sticky='NESW')

        Button(self, text='Record', command=self.threaded_record).grid(columnspan=2, sticky='NESW')

    def threaded_record(self):
        if self.thread == None or not self.thread.isAlive():
            self.thread = threading.Thread(target=self.record)
            self.thread.start()

    def record(self):

        frequency = int(self.record_options['frequency'])
        record_time = int(self.record_time.get_value())

        format = pyaudio.paInt16
        n_channels = 2
        chunk = 1024
        output_filename = Constants.RAW_FILES_PATH + self.file_name.get_value() + '.wav'

        splitted = self.file_name.get_value().split('/')
        if len(splitted) > 1:
            splitted = splitted[:-1]
            acc = Constants.RAW_FILES_PATH
            for el in splitted:
                acc += el + '/'
                if not os.path.isdir(acc):
                    os.mkdir(acc)

        audio = pyaudio.PyAudio()

        stream = audio.open(format=format, channels=n_channels,
                        rate=frequency, input=True,
                        frames_per_buffer=chunk)

        frames = []
        progress_step = 100. / int(frequency / chunk * record_time)


        for i in range(0, int(frequency / chunk * record_time)):
            data = stream.read(chunk)
            frames.append(data)
            self.progress_bar.step(progress_step)

        stream.stop_stream()
        stream.close()
        audio.terminate()

        waveFile = wave.open(output_filename, 'wb')
        waveFile.setnchannels(n_channels)
        waveFile.setsampwidth(audio.get_sample_size(format))
        waveFile.setframerate(frequency)
        waveFile.writeframes(b''.join(frames))
        waveFile.close()

        tkMessageBox.showinfo('Info', 'Finished recording')
        self.progress_bar.step(-100)
class LowerScrollingFrame(ScrollableFrame):
	#self.mangaFrame ==> the MangaFrame that we get our image and updates from
	def __init__(self,parent,*args,**kwargs):
		self.parent=parent
		ScrollableFrame.__init__(self,self.parent,*args,**kwargs)
		self.disableDynamicRows() #really annoying to have it on
		self.__body()
		self.mangaFrame=None
		self.imageNotFound=self.image=ImageTk.PhotoImage(Image.open("Image-not-found.gif"))
		self.image=self.imageNotFound
		self.redraw()

	def __body(self):
		self.BUTTONS={}
		self.BUTTONS["Update"]=Button(self,text="Update",command=self.updateManga)
		self.BUTTONS["CheckForUpdates"]=Button(self,text="Check Updates",command=self.updateManga_check)
		self.BUTTONS["Delete"]=Button(self,text="Delete",command=self.deleteManga)

		self.BUTTONS["Update"].grid(row=0,column=0,sticky=N+S+E+W)
		self.BUTTONS["CheckForUpdates"].grid(row=1,column=0,sticky='nsew')
		self.BUTTONS["Delete"].grid(row=2,column=0,sticky=N+S+E+W)

		self.LABELS={}
		self.LABELS["Status"]=Label(self,text="Status:\nUnknown")
		self.LABELS["ChapterCount"]=Label(self,text="Chapters:\nUnknown")
		self.LABELS["Updates"]=Label(self,text="Updates:\nUnknown")
		self.LABELS["Summary"]=LabelResizing(self,text="Summary:\n")
		self.LABELS["Picture"]=Label(self,image=None)
		self.LABELS["UpdatingStatus"]=Label(self,text="")

		self.LABELS["Status"].grid(row=0,column=1)
		self.LABELS["ChapterCount"].grid(row=1,column=1)
		self.LABELS["Updates"].grid(row=2,column=1)
		self.LABELS["Summary"].grid(row=3,column=0,sticky='nwe')
		self.LABELS["Picture"].grid(row=0,column=2,rowspan=5)
		self.LABELS["UpdatingStatus"].grid(row=5,column=0,columnspan=3)

		self.PROGRESSBAR=Progressbar(self)
		self.PROGRESSBAR.grid(row=6,column=0,columnspan=3,sticky=E+W)

		self.bindChidrenScrolling()
		self.grid_columnconfigure(0,weight=1)
		self.grid_columnconfigure(1,weight=2)

	def setManga(self,MangaFrame):
		#this should be a manga frame
		self.mangaFrame=MangaFrame
		self.image=self.mangaFrame.getImage()
		self.redraw()
	def redraw(self,*args):
		try:
			if self.mangaFrame.inProgress==False:self.BUTTONS["Update"].config(text="Update")
			else:self.BUTTONS["Update"].config(text="Cancel")
			self.LABELS["ChapterCount"].config(text="{} Chapters".format(self.mangaFrame.numberOfChapters()))
			self.LABELS["Updates"].config(text="{} Updates".format(self.mangaFrame.numberOfUpdates()))
			self.progressSet(self.mangaFrame.getProgress())
			self.LABELS["UpdatingStatus"].config(text=self.mangaFrame.getStatus())
			self.LABELS["Summary"].config(text="Summary: "+self.mangaFrame.getSummary())
		except Exception as e:
			print e
			self.LABELS["Status"].config(text="Status:\nUnknown")
			self.LABELS["ChapterCount"].config(text="Chapters:\nUnknown")
			self.LABELS["Updates"].config(text="Updates:\nUnknown")
			self.progressReset()
			self.LABELS["UpdatingStatus"].config(text="")
			self.LABELS["Summary"].config(text="Summary:\nUnknown")
		self.LABELS["Picture"].config(image=self.image)

	def progressSet(self,value):
		self.PROGRESSBAR.config(value=value)
	def progressStep(self,value):
		self.PROGRESSBAR.step(value)
	def progressReset(self):
		self.PROGRESSBAR.config(value=0)

	def updateManga(self):
		if not self.mangaFrame.inProgress:self.mangaFrame.updateManga(self)
		else: self.mangaFrame.cancelUpdate()
		self.redraw()
	def updateManga_check(self):
		self.mangaFrame.updateManga_check() #look to see if there are any updates
		self.redraw() #change the number we have for the number of updates
	def deleteManga(self):
		rmtree("files/"+self.mangaFrame.getName())
		self.parent.populateLibrary()
		self.mangaFrame=None
		self.image=self.imageNotFound
		self.redraw()
Ejemplo n.º 8
0
class TkSynthWindow(Frame):

    """
    Provides common synth editor elements: 
          bank editor
          MIDI tab
          Mapping tabs

     TkSynthWindow is customized by adding one or more TkSubEditor.
    """
    
    def __init__(self, master, sproxy):
        """
        Construct new TkSynthWindow

        master - The Tk container for self.  In practice this is an 
                 instance of llia.gui.tk.GroupWindow

        sproxy - An instance of llia.Proxy.
        """
        Frame.__init__(self, master)
        self.config(background=factory.bg())
        self.synth = sproxy
        self.synth.synth_editor = self
        self.app = sproxy.app
        self.sid = sproxy.sid
        self.group_index = -1
        factory.set_pallet(sproxy.specs["pallet"])
        main = factory.paned_window(self)
        main.pack(expand=True, fill="both")
        self.bank_editor = TkBankEditor(main, self, sproxy)
        self.bus_and_buffer_editor = None
        east = factory.frame(main)
        self.notebook = factory.notebook(east)
        self.notebook.pack(anchor="nw", expand=True, fill="both")
        south = factory.frame(east)
        south.pack(after=self.notebook, anchor="w", expand=True, fill="x")
        self._lab_status = factory.label(south, "<status>")
        self._lab_extended = factory.label(south, "")
        b_panic = factory.panic_button(south, command=self.panic)
        b_lower = factory.button(south, "-", command=self.lower_window)
        b_lift = factory.button(south, "+", command=self.lift_window)
        b_panic.grid(row=0, column=0)
        self._lab_status.grid(row=0, column=4, sticky='ew')
        self._lab_extended.grid(row=0,column=5,sticky='e',padx=16)
        self._lab_extended.config(fg="#f1f1cd")
        self._progressbar = Progressbar(south,mode="indeterminate")
        self._progressbar.grid(row=0,column=PROGRESSBAR_COLUMN, sticky='w', padx=8)
        south.config(background=factory.bg())
        main.add(self.bank_editor)
        main.add(east)
        self.list_channel = None
        self.list_keytab = None
        self.var_transpose = StringVar()
        self.var_keyrange_low = StringVar()
        self.var_keyrange_high = StringVar()
        self.var_bendrange = StringVar()
        self._init_midi_tab(self.notebook)
        self._init_map1_tab(self.notebook) # MIDI controllers and pitchwheel
        self._init_map2_tab(self.notebook) # velocity, aftertouch, keynumber
        self._init_info_tab(self.notebook)
        self._child_editors = {}
        self.update_progressbar(100, 0)
        
    def enable(self, flag):
        for ed in self._child_editors.values():
            ed.enable(flag)
        if flag:
            msg = ""
        else:
            msg = "Editor locked while in extended mode"
        self._lab_extended.config(text=msg)
        
    def panic(self):
        self.synth.osc_transmitter.x_all_notes_off()
        self.status("All notes off")
        
    def clear_status(self):
        self._lab_status.config(text="")
        
    def add_child_editor(self, child_name, child):
        # Adds child editor to list of editors without adding a notebook tab.
        self._child_editors[child_name] = child

    def _create_basic_tab(self,text):
        f = factory.frame(self.notebook)
        self.notebook.add(f, text=text)
        return f

    # icon_filename = "resources/%s/logo_32.png" % sy.specs["format"]
    # icon = factory.image(icon_filename)
    # group.notebook.add(swin, text=sy.sid, image=icon, compound="top")
    
    def _create_compund_tab(self,text,image_filename):
        try:
            icon = factory.image(image_filename)
            f = factory.frame(self.notebook)
            self.notebook.add(f,text=text,image=icon,compound="top")
            return f
        except IOError:
            msg = "IOError while loading image file '%s'" % image_filename
            print(msg)
            return self._create_basic_tab(text)
    
    def create_tab(self, tab_text, image_filename=""):
        if not image_filename:
            rs = self._create_basic_tab(tab_text)
        else:
            rs = self._create_compund_tab(tab_text,image_filename)
        return rs
       
    def remove_synth(self, *_):
        sid = self.synth.sid
        parser = self.app.ls_parser
        sh = parser.synthhelper
        sh.destroy_editor(sid)
        sh.remove_synth(sid, force=True)
        self.status("Removed synth: %s" % sid)

    def _init_info_tab(self, master):
        img = factory.image("resources/Tabs/info.png")
        frame = factory.frame(master)
        inner_frame = factory.frame(frame)
        master.add(frame, text="Info", image=img,compound="top")
        text_widget = factory.text_widget(inner_frame)
        text_widget.config(width=120, height=40)
        vsb = factory.scrollbar(inner_frame, orientation='vertical')
        vsb.config(command=text_widget.yview)
        text_widget.config(yscrollcommand=vsb.set, wrap='word',)
        text_widget.grid(row=0, column=0,sticky="ewns")
        vsb.grid(row=0, column=1, sticky='ns')
        inner_frame.grid(row=0, column=0, rowspan=8, columnspan=8, sticky="ewns")
        self._info_text_widget = text_widget

    def lift_window(self):
        mw = self.app.main_window()
        grp = mw.group_windows[self.group_index]
        grp.lift()
        self.status("Lift window")

    def lower_window(self):
        mw = self.app.main_window()
        grp = mw.group_windows[self.group_index]
        grp.lower()
        self.status("Lower window")
        
    def sync_program_tab(self):
        bnk = self.synth.bank()
        prog = bnk[None]
        slot = bnk.current_slot
        pp = self.synth.specs["pretty-printer"]
        if pp:
            txt = pp(prog, slot)
        else:
            txt = ""
        self._info_text_widget.delete(1.0, "end")
        self._info_text_widget.insert("end", txt)

    def _init_midi_tab(self, master):
        img = factory.image("resources/Tabs/midi.png")
        frame = factory.frame(master)
        master.add(frame, text = "Performance", image=img, compound="top")
        frame_channel = factory.frame(frame)
        frame_keytab = factory.frame(frame)
        lab_transpose = factory.label(frame, "Transpose")
        lab_keyrange = factory.label(frame, "Key Range")
        lab_bend = factory.label(frame, "Bend Range")
        self.list_channel = factory.listbox(frame_channel)
        sb_channel = factory.scrollbar(frame_channel)
        sb_channel.config(command=self.list_channel.yview)
        self.list_channel.config(yscrollcommand=sb_channel.set)
        self.list_keytab = factory.listbox(frame_keytab)
        sb_keytab = factory.scrollbar(frame_keytab)
        sb_keytab.config(command=self.list_keytab.yview)
        self.list_keytab.config(yscrollcommand=sb_keytab.set)
        spin_transpose = factory.int_spinbox(frame,self.var_transpose,-36,36)
        spin_keylow = factory.int_spinbox(frame,self.var_keyrange_low,0,127)
        spin_keyhigh = factory.int_spinbox(frame,self.var_keyrange_high,0,127)
        spin_bendrange = factory.int_spinbox(frame,self.var_bendrange, 0, 2400)
        factory.padding_label(frame).grid(row=0)
        lab_channel = factory.label(frame,"MIDI Input Channel")
        lab_channel.grid(row=0,column=0,columnspan=2, pady=8)
        frame_channel.grid(row=1, column=0, rowspan=4, columnspan=2,padx=8,pady=8)
        self.list_channel.pack(side="left", expand=True, fill="both")
        sb_channel.pack(after=self.list_channel, side="right", expand=True, fill="y")
        lab_ktab = factory.label(frame, "Key Table")
        lab_ktab.grid(row=0,column=2,columnspan=2,pady=8)
        frame_keytab.grid(row=1, column=2, rowspan=4, columnspan=2,padx=8,pady=8)
        self.list_keytab.pack(side="left", expand=True, fill="both")
        sb_keytab.pack(after=self.list_keytab, side="right", 
                       expand=True, fill="y")
        factory.padding_label(frame).grid(row=6)
        lab_transpose.grid(row=7, column=0, sticky="w", padx=4, pady=4)
        lab_keyrange.grid(row=8, column=0, sticky="w", padx=4, pady=4)
        lab_bend.grid(row=9, column=0, sticky="w", padx=4, pady=4)

        spin_transpose.grid(row=7, column=1, padx=4)
        spin_keylow.grid(row=8, column=1, padx=4)
        spin_keyhigh.grid(row=8, column=2, padx=4)
        spin_bendrange.grid(row=9, column=1, padx=4)
   
        def channel_callback(_):
            i = self.list_channel.curselection()[0]
            c = i+1
            self.synth.midi_input_channel(c)
            self.status("MIDI Input Channel = %s" % c)

        def keytab_callback(_):
            i = self.list_keytab.curselection()[0]
            kt = self.list_keytab.get(i)
            self.synth.keytable(kt)
            self.status("Using keytable: %s" % kt)

        def transpose_callback(*_):
            try:
                x = int(self.var_transpose.get())
                self.synth.transpose(x)
                self.status("Transpose = %s" % x)
            except ValueError:
                self.warning("Invalid transpose")
                
        def keyrange_callback(*_):
            try:
                a = int(self.var_keyrange_low.get())
                b = int(self.var_keyrange_high.get())
                a, b = min(a,b), max(a,b)
                self.synth.key_range((a,b))
                self.status("Key range = [%3d, %3d]" % (a, b))
            except ValueError:
                self.warning("Invalid keyrange")
                
        def bend_callback(*_):
            try:
                b = int(self.var_bendrange.get())
                self.synth.bend_range(b)
                self.status("Bend range = %s" % b)
            except ValueError:
                self.warning("Invalid Bendrange")
        
        self.list_channel.bind("<<ListboxSelect>>", channel_callback)
        self.list_keytab.bind("<<ListboxSelect>>", keytab_callback)
        spin_transpose.config(command=transpose_callback)
        spin_transpose.bind("<Return>", transpose_callback)
        spin_keylow.config(command=keyrange_callback)
        spin_keylow.bind("<Return>", keyrange_callback)
        spin_keyhigh.config(command=keyrange_callback)
        spin_keyhigh.bind("<Return>", keyrange_callback)
        spin_bendrange.config(command=bend_callback)
        spin_bendrange.bind("<Return>", bend_callback)

    def sync_midi_tab(self):
        self.list_channel.delete(0, "end")
        for c in self.app.config().channel_assignments.formatted_list():
            self.list_channel.insert("end", c)
        mic = self.synth.midi_input_channel()-1
        self.list_channel.selection_set(mic)
        self.list_keytab.delete(0, "end")
        target, index = self.synth.keytable(), 0
        for i, kt in enumerate(sorted(self.app.keytables.keys())):
            self.list_keytab.insert("end", kt)
            if target == kt: index = i
        self.list_keytab.selection_set(index)
        self.var_transpose.set(self.synth.transpose())
        lo, hi = self.synth.key_range()
        self.var_keyrange_low.set(lo)
        self.var_keyrange_high.set(hi)
        self.var_bendrange.set(self.synth.bend_range())

    # map1_tab -> MIDI controller, pitch wheel
    def _init_map1_tab(self, master):
        img = factory.image("resources/Tabs/map.png")
        HELP_TOPIC = "parameter-maps"
        frame = factory.frame(master)
        master.add(frame, text="Map1", image=img, compound="top")
        north = factory.label_frame(frame, "MIDI Controller Maps")
        south = factory.label_frame(frame, "Pitch Wheel Maps")
        north.grid(row=0, column=0, sticky="ew", padx=8, pady=8)
        south.grid(row=1, column=0, sticky="ew", padx=8, pady=8)

        def help_callback():
            self.app.main_window().display_help(HELP_TOPIC)
       
        list_cc_maps = factory.listbox(north, 
                                       ttip="Active MIDI controller maps")
        list_cc_maps.config(width=80, height=16)
        self.list_cc_maps = list_cc_maps
        sb = factory.scrollbar(north, orientation="vertical")
        sb.config(command=list_cc_maps.yview)
        list_cc_maps.config(yscrollcommand=sb.set)
        b_add_cc = factory.add_button(north, ttip="Add new controller map")
        b_delete_cc = factory.delete_button(north, 
                                            ttip="Delete controller map")
        list_cc_maps.grid(row=0, column=0, rowspan=4, 
                          columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, rowspan=4, sticky="ns")
        b_add_cc.grid(row=4, column=0, sticky="ew")
        b_delete_cc.grid(row=4, column=1, sticky="ew")

        list_pwheel_maps = factory.listbox(south, 
                                           ttip="Active pitch wheel maps")
        list_pwheel_maps.config(width=80, height=8)
        self.list_pwheel_maps = list_pwheel_maps
        sb = factory.scrollbar(south, orientation="vertical")

        sb.config(command=list_pwheel_maps.yview)
        list_pwheel_maps.config(yscrollcommand=sb.set)
        b_add_pw = factory.add_button(south, ttip="Add pitchwheel map")
        b_delete_pw = factory.delete_button(south, 
                                            ttip="Delete pitchwheel map")
        b_help = factory.help_button(south, command=help_callback)
        list_pwheel_maps.grid(row=0, column=0, rowspan=4,
                              columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, rowspan=4, sticky="ns")
        b_add_pw.grid(row=4, column=0, sticky="ew")
        b_delete_pw.grid(row=4, column=1, sticky="ew")
        b_help.grid(row=4, column=7, sticky="ew")

        def add_cc_callback():
            dialog = add_map_dialog(self.synth, "cc", self.app)

        def delete_cc_callback():
            dialog = delete_map_dialog(self, self.synth, "cc", self.app)

        def add_pw_callback():
            dialog = add_map_dialog(self.synth, "PitchWheel", self.app)

        def delete_pw_callback():
            dialog = delete_map_dialog(self, self.synth, "PitchWheel", self.app)

        b_add_cc.config(command=add_cc_callback)
        b_delete_cc.config(command=delete_cc_callback)
        b_add_pw.config(command=add_pw_callback)
        b_delete_pw.config(command=delete_pw_callback)
        
    def sync_map1_tab(self):
        perf = self.synth.bank()[None].performance
        cmaps = perf.controller_maps
        pwmaps = perf.pitchwheel_maps
        self.list_cc_maps.delete(0, "end")
        for ctrl, mapper in cmaps.items():
            s = str(mapper)
            for q in s.split('\n'):
                self.list_cc_maps.insert("end", q)
        self.list_pwheel_maps.delete(0, "end")
        for q in str(pwmaps).split('\n'):
            self.list_pwheel_maps.insert("end", q)

    def _init_map2_tab(self, master):
        img = factory.image("resources/Tabs/map.png")
        HELP_TOPIC = "parameter-maps"
        HEIGHT = 8
        frame = factory.frame(master)
        master.add(frame, text="Map2",image=img,compound="top")
        north = factory.label_frame(frame, "Velocity Maps")
        center = factory.label_frame(frame, "Aftertouch Maps")
        south = factory.label_frame(frame, "Keynumber Maps")
        north.grid(row=0, column=0, sticky="ew", padx=8, pady=8)
        center.grid(row=1, column=0, sticky="ew", padx=8)
        south.grid(row=2, column=0, sticky="ew", padx=8, pady=8)

        def help_callback():
            self.app.main_window().display_help(HELP_TOPIC)

        list_vel_maps = factory.listbox(north, ttip="Active velocity maps")
        list_vel_maps.config(width=80, height=HEIGHT)
        self.list_vel_maps = list_vel_maps
        sb = factory.scrollbar(north, orientation="vertical")
        sb.config(command=list_vel_maps.yview)
        list_vel_maps.config(yscrollcommand=sb.set)
        b_add_vel = factory.add_button(north, ttip="Add velocity map")
        b_delete_vel = factory.delete_button(north, 
                                             ttip="Delete velocity map")
        list_vel_maps.grid(row=0, column=0, columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, sticky="ns")
        b_add_vel.grid(row=1, column=0, sticky="ew")
        b_delete_vel.grid(row=1, column=1, sticky="ew")

        list_atouch_maps = factory.listbox(center, 
                                           ttip="Active after touch maps")
        list_atouch_maps.config(width=80, height=HEIGHT)
        self.list_atouch_maps = list_atouch_maps
        sb = factory.scrollbar(center, orientation="vertical")
        sb.config(command=list_atouch_maps.yview)
        list_atouch_maps.config(yscrollcommand=sb.set)
        b_add_atouch = factory.add_button(center, ttip="Add after touch map")
        b_delete_atouch = factory.delete_button(center, 
                                                ttip="Delete after touch map")
        list_atouch_maps.grid(row=0, column=0, columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, sticky="ns")
        b_add_atouch.grid(row=1, column=0, sticky="ew")
        b_delete_atouch.grid(row=1, column=1, sticky="ew")

        list_keynum_maps = factory.listbox(south, 
                                           ttip="Active key number maps")
        list_keynum_maps.config(width=80, height=HEIGHT)
        self.list_keynum_maps = list_keynum_maps
        sb = factory.scrollbar(south, orientation="vertical")
        sb.config(command=list_keynum_maps.yview)
        list_keynum_maps.config(yscrollcommand=sb.set)
        b_add_keynum = factory.add_button(south, ttip="Add key number map")
        b_delete_keynum = factory.delete_button(south, 
                                                ttip="Delete key number map")
	b_help = factory.help_button(south, command=help_callback)
        list_keynum_maps.grid(row=0, column=0, columnspan=8, sticky="ew")
        sb.grid(row=0, column=8, sticky="ns")
        b_add_keynum.grid(row=1, column=0, sticky="ew")
        b_delete_keynum.grid(row=1, column=1, sticky="ew")
        b_help.grid(row=1, column=7, sticky="ew")

        def add_map_callback(event):
            widget = event.widget
            if widget is b_add_vel:
                dialog = add_map_dialog(self.synth, "velocity", self.app)
            elif widget is b_add_atouch:
                dialog = add_map_dialog(self.synth, "aftertouch", self.app)
            elif widget is b_add_keynum:
                dialog = add_map_dialog(self.synth, "keynumber", self.app)
            else:
                msg = "Invalid widget - Should never see this"
                raise ValueError(msg)

        def delete_map_callback(event):
            widget = event.widget
            if widget is b_delete_vel:
                dialog = delete_map_dialog(self, self.synth, "velocity", self.app)
            elif widget is b_delete_atouch:
                dialog = delete_map_dialog(self, self.synth, "aftertouch", self.app)
            elif widget is b_delete_keynum:
                dialog = delete_map_dialog(self, self.synth, "keynumber", self.app)
            else:
                msg = "Invalid widget - Should never see this"
                raise ValueError(msg)

        b_add_vel.bind("<Button-1>", add_map_callback)
        b_add_atouch.bind("<Button-1>", add_map_callback)
        b_add_keynum.bind("<Button-1>", add_map_callback)
        b_delete_vel.bind("<Button-1>", delete_map_callback)
        b_delete_atouch.bind("<Button-1>", delete_map_callback)
        b_delete_keynum.bind("<Button-1>", delete_map_callback)
        
    def sync_map2_tab(self):
        perf = self.synth.bank()[None].performance
        vmaps = perf.velocity_maps
        atmaps = perf.aftertouch_maps
        knmaps = perf.keynumber_maps
        self.list_vel_maps.delete(0, 'end')
        self.list_atouch_maps.delete(0, 'end')
        self.list_keynum_maps.delete(0, 'end')
        for q in str(vmaps).split('\n'):
            self.list_vel_maps.insert('end', q)
        for q in str(atmaps).split('\n'):
            self.list_atouch_maps.insert('end', q)
        for q in str(knmaps).split('\n'):
            self.list_keynum_maps.insert('end', q)            
        
    def status(self, msg):
        self._lab_status.config(text = msg)

    def warning(self, msg):
        msg = "WARNING: %s" % msg
        self._lab_status.config(text = msg)

    def set_value(self, param, value):
        for ed in self._child_editors.items():
            ed.set_value(param, value)

    def set_aspect(self, param, value):
        for ed in self._child_editors.values():
            ed.set_value(param, value)
    
    def sync(self, *ignore):
        self.sync_program_tab()
        self.sync_midi_tab()
        self.sync_map1_tab()
        self.sync_map2_tab()
        if "bank" not in ignore:
            self.bank_editor.sync_no_propegate()
        for key, ed in self._child_editors.items():
            if key not in ignore:
                ed.sync(*ignore)
                
    def annotation_keys(self):
        """
        See TkSubEditor annotation
        """
        acc = []
        for ed in self._child_editors.values():
            acc += ed.annotation_keys()
        return acc

    def set_annotation(self, key, text):
        """
        See TkSubEditor annotation
        """
        for ed in self._child_editors.values():
            ed.annotation(key, text)

    def get_annotation(self, key):
        """
        See TkSubEditor annotation
        """
        rs = None
        for ed in self._child_editors.values():
            rs = ed.get_annotation(key)
            if rs != None:
                return rs
        return None

    def update_progressbar(self, count, value):
        """
        Set progress bar to position value/count, where.
        count - Expected number of steps.
        value - Current step number.
        """
        self._progressbar.config(mode="determinate", maximum=count)
        self._progressbar.step()
        self.update_idletasks()
    
    def busy(self, flag, message=""):
        """
        Set progress bar to 'busy'
        """
        if message:
            self.status(message)
        self._progressbar.config(mode="indeterminate")
        if flag:
            self._progressbar.grid(row=0,column=PROGRESSBAR_COLUMN, sticky='w', padx=8)
            self._progressbar.start()
        else:
            self._progressbar.stop()
        self.update_idletasks()