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()
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()
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")
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)
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()
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()