From 42306dd630d7a827846fa2ae344e3e5e34819855 Mon Sep 17 00:00:00 2001 From: omegadot Date: Thu, 26 Sep 2013 21:58:38 -0400 Subject: [PATCH 1/3] First commit. Took out some network interface checks, will probably replace with pythonic method. Changed from keyboard to joy input but will end up with a config backed setup to support keyboard input for those using an encoder or something (me). Currently dorking with getting a universal kill keypress. The stuff in currently doesn't work at all. --- pimame_files/menu.py | 196 +++++++++++++++++++++++++------------------ 1 file changed, 116 insertions(+), 80 deletions(-) mode change 100644 => 100755 pimame_files/menu.py diff --git a/pimame_files/menu.py b/pimame_files/menu.py old mode 100644 new mode 100755 index fb1a35c..fcb5ed5 --- a/pimame_files/menu.py +++ b/pimame_files/menu.py @@ -1,68 +1,84 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Topmenu and the submenus are based of the example found at this location http://blog.skeltonnetworks.com/2010/03/python-curses-custom-menu/ -# The rest of the work was done by Matthew Bennett and he requests you keep these two mentions when you reuse the code :-) -# Basic code refactoring by Andrew Scheller - +""" +Topmenu and the submenus are based of the example found at this location: +http://blog.skeltonnetworks.com/2010/03/python-curses-custom-menu/ + +The rest of the work was done by Matthew Bennett and he requests you keep +these two mentions when you reuse the code :-) +Basic code refactoring by Andrew Scheller +""" +import subprocess +import curses, os +import pygame +import sys import subprocess -import curses, os #curses is the interface for capturing key presses on the menu, os launches the files -screen = curses.initscr() #initializes a new window for capturing key presses -curses.noecho() # Disables automatic echoing of key presses (prevents program from input each key twice) -curses.cbreak() # Disables line buffering (runs each key as it is pressed rather than waiting for the return key to pressed) -curses.start_color() # Lets you use colors when highlighting selected menu option +from signal import SIGTERM +import threading + +pygame.init() +pygame.joystick.init() +js_count = pygame.joystick.get_count() +for i in range(js_count): + js = pygame.joystick.Joystick(i) + js.init() + +screen = curses.initscr() +curses.noecho() +curses.cbreak() +curses.start_color() screen.keypad(1) # Capture input from keypad -wlan = subprocess.check_output("/sbin/ifconfig wlan0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}' ", shell=True) -ether = subprocess.check_output("/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}' ", shell=True) - -myip = '' -if wlan != '': - myip += wlan -if ether != '': - myip += ' ' + ether - -if myip != '': - myip = "Your IP is: " + myip + " - " - - # Change this to use different colors when highlighting -curses.init_pair(1,curses.COLOR_BLACK, curses.COLOR_WHITE) # Sets up color pair #1, it does black text with white background +# Sets up color pair #1, it does black text with white background +curses.init_pair(1,curses.COLOR_BLACK, curses.COLOR_WHITE) h = curses.color_pair(1) #h is the coloring for a highlighted menu option n = curses.A_NORMAL #n is the coloring for a non highlighted menu option MENU = "menu" COMMAND = "command" - menu_data = { - 'title': "PiMAME Menu (v0.7.9)", 'type': MENU, 'subtitle': "Please select an option...", + 'title': "PiMAME Menu (v0.7.9)", 'type': MENU, + 'subtitle': "Please select an option...", 'options': [ { 'title': "Arcade", 'type': MENU, 'subtitle': "Arcade Emulators", 'options': [ { 'title': "AdvanceMAME", 'type': COMMAND, 'command': 'advmenu' }, { 'title': "Neo Geo (GNGeo)", 'type': COMMAND, 'command': 'gngeo -i roms/' }, - { 'title': "MAME4All", 'type': COMMAND, 'command': '/home/pi/emulators/mame4all-pi/mame' }, - { 'title': "FBA (CPS1, CPS2, Neo Geo)", 'type': COMMAND, 'command': '/home/pi/emulators/fba/fbacapex' }, + { 'title': "MAME4All", 'type': COMMAND, + 'command': '/home/pi/emulators/mame4all-pi/mame' }, + { 'title': "FBA (CPS1, CPS2, Neo Geo)", 'type': COMMAND, + 'command': '/home/pi/emulators/fba/fbacapex' }, ] }, { 'title': "Consoles", 'type': MENU, 'subtitle': "Console Emulators", 'options': [ - { 'title': "PlayStation 1 (PCSX_ReARMed)", 'type': COMMAND, 'command': '/home/pi/emulators/pcsx_rearmed/pcsx' }, - { 'title': "Genesis (DGen)", 'type': COMMAND, 'command': 'advmenu -cfg advmenu-dgen.rc' }, - { 'title': "SNES (PiSNES / SNES9x Advmenu)", 'type': COMMAND, 'command': 'advmenu -cfg advmenu-snes.rc' }, - { 'title': "NES (AdvanceMESS)", 'type': COMMAND, 'command': 'advmenu -cfg advmenu-nes.rc' }, - { 'title': "Gameboy (Gearboy Advmenu)", 'type': COMMAND, 'command': 'advmenu -cfg advmenu-gameboy.rc' }, - { 'title': "Gameboy Advance (gpsp)", 'type': COMMAND, 'command': '/home/pi/emulators/gpsp/gpsp' }, + { 'title': "PlayStation 1 (PCSX_ReARMed)", 'type': COMMAND, + 'command': '/home/pi/emulators/pcsx_rearmed/pcsx' }, + { 'title': "Genesis (DGen)", 'type': COMMAND, + 'command': 'advmenu -cfg advmenu-dgen.rc' }, + { 'title': "SNES (PiSNES / SNES9x Advmenu)", 'type': COMMAND, + 'command': '/home/pi/emulators/pisnes/snes9x.gui' }, + { 'title': "NES (AdvanceMESS)", 'type': COMMAND, + 'command': 'advmenu -cfg advmenu-nes.rc' }, + { 'title': "Gameboy (Gearboy Advmenu)", 'type': COMMAND, + 'command': 'advmenu -cfg advmenu-gameboy.rc' }, + { 'title': "Gameboy Advance (gpsp)", 'type': COMMAND, + 'command': '/home/pi/emulators/gpsp/gpsp' }, { 'title': "Atari 2600 (Stella)", 'type': COMMAND, 'command': 'stella' }, { 'title': "Commodore 64 (VICE)", 'type': COMMAND, 'command': 'x64' }, ] }, - { 'title': "CaveStory (NXEngine)", 'type': COMMAND, 'command': '/home/pi/emulators/cs.sh' }, + { 'title': "CaveStory (NXEngine)", 'type': COMMAND, + 'command': '/home/pi/emulators/cs.sh' }, { 'title': "ScummVM", 'type': COMMAND, 'command': 'scummvm' }, - { 'title': "Tools", 'type': MENU, 'subtitle': myip, + { 'title': "Tools", 'type': MENU, 'subtitle': 'PIMAME', 'options': [ - { 'title': "Install PIP (http://pip.sheacob.com/about.html)", 'type': COMMAND, 'command': 'sudo /home/pi/pimame_files/pipinstall.py' }, - { 'title': "Remove PIP", 'type': COMMAND, 'command': 'sudo /home/pi/pimame_files/pipinstall.py -r' }, + { 'title': "Install PIP (http://pip.sheacob.com/about.html)", + 'type': COMMAND, 'command': 'sudo /home/pi/pimame_files/pipinstall.py' }, + { 'title': "Remove PIP", 'type': COMMAND, + 'command': 'sudo /home/pi/pimame_files/pipinstall.py -r' }, { 'title': "raspi-config", 'type': COMMAND, 'command': 'sudo raspi-config' }, { 'title': "Reboot", 'type': COMMAND, 'command': 'sudo reboot' }, { 'title': "Shutdown", 'type': COMMAND, 'command': 'sudo poweroff' }, @@ -71,8 +87,8 @@ ] } -# This function displays the appropriate menu and returns the option selected -def runmenu(menu, parent): +def run_menu(menu, parent): + """ displays the appropriate menu and returns the option selected """ # work out what text to display as the last menu option if parent is None: @@ -82,77 +98,97 @@ def runmenu(menu, parent): optioncount = len(menu['options']) # how many options in this menu - pos=0 #pos is the zero-based index of the hightlighted menu option. Every time runmenu is called, position returns to 0, when runmenu ends the position is returned and tells the program what option has been selected - oldpos=None # used to prevent the screen being redrawn every time - x = None #control for while loop, let's you scroll through options until return key is pressed then returns pos to program + #pos is the zero-based index of the hightlighted menu option. Every time + #run_menu is called, position returns to 0, when run_menu ends the position + #is returned and tells the program what option has been selected + pos=0 + # used to prevent the screen being redrawn every time + oldpos=None + #control for while loop, let's you scroll through options + #until return key is pressed then returns pos to program + x = None # Loop until return key is pressed - - while x !=ord('c'): if pos != oldpos: oldpos = pos - screen.clear() #clears previous screen on key press and updates display based on pos + screen.clear() screen.border(0) - screen.addstr(2,2, menu['title'], curses.A_STANDOUT) # Title for this menu - screen.addstr(4,2, menu['subtitle'], curses.A_BOLD) #Subtitle for this menu + screen.addstr(2,2, menu['title'], curses.A_STANDOUT) + screen.addstr(4,2, menu['subtitle'], curses.A_BOLD) # Display all the menu items, showing the 'pos' item highlighted for index in range(optioncount): textstyle = n if pos==index: textstyle = h - screen.addstr(5+index,4, "%d - %s" % (index+1, menu['options'][index]['title']), textstyle) + screen.addstr(5+index,4, "%d - %s" % (index+1, + menu['options'][index]['title']), textstyle) # Now display Exit/Return at bottom of menu textstyle = n if pos==optioncount: textstyle = h - screen.addstr(5+optioncount,4, "%d - %s" % (optioncount+1, lastoption), textstyle) + screen.addstr(5+optioncount,4, "%d - %s" % (optioncount+1, lastoption), + textstyle) screen.refresh() # finished updating screen - x = screen.getch() # Gets user input + #x = screen.getch() # Gets user input + #Need to back with config file. That's next up. if x == ord('\n'): x = ord('c') - - # What is user input? - if x >= ord('1') and x <= ord(str(optioncount+1)): - pos = x - ord('0') - 1 # convert keypress back to a number, then subtract 1 to get index - elif x == 258: # down arrow - if pos < optioncount: - pos += 1 - else: pos = 0 - elif x == 8: # down arrow - if pos < optioncount: - pos += 1 - else: pos = 0 - elif x == 259: # up arrow - if pos > 0: - pos += -1 - else: pos = optioncount - elif x == 259: # up arrow - if pos > 0: - pos += -1 - else: pos = optioncount - elif x != ord('\n'): - curses.flash() - + for event in pygame.event.get(): + if event.type == pygame.JOYBUTTONDOWN: + if event.dict['button'] == 3: + x = ord('c') + curses.flash() + if event.type == pygame.JOYAXISMOTION: + d = event.dict + if d['axis'] == 1 and d['value'] < 0: + pos += -1 + elif d['axis'] == 1 and d['value'] > 0: + pos += 1 # return index of the selected item return pos -# This function calls showmenu and then acts on the selected item -def processmenu(menu, parent=None): +def kill_emu(pid): + """ + Meant to be popped off in a thread to kill the emu with a button combo. + Still working on this...it's probably bad.s + """ + joys = [pygame.joystick.Joystick(i) for i in range(js_count)] + for i in joys: + i.init() + while True: + print i.get_button(8) + #os.kill(pid, SIGTERM) + #break + +def process_menu(menu, parent=None): + """ This function calls showmenu and then acts on the selected item """ + optioncount = len(menu['options']) exitmenu = False while not exitmenu: #Loop until the user exits the menu - getin = runmenu(menu, parent) + getin = run_menu(menu, parent) if getin == optioncount: exitmenu = True elif menu['options'][getin]['type'] == COMMAND: - os.system(menu['options'][getin]['command']) # run the command + try: + game = subprocess.Popen(menu['options'][getin]['command'].split(), + stderr = subprocess.PIPE, stdout = subprocess.PIPE) + pid = game.pid + except: continue + #threading.Thread(target=kill_emu(pid)).start() elif menu['options'][getin]['type'] == MENU: - processmenu(menu['options'][getin], menu) # display the submenu + process_menu(menu['options'][getin], menu) # display the submenu # Main program -processmenu(menu_data) -curses.endwin() #VITAL! This closes out the menu system and returns you to the bash prompt. +def main(): + process_menu(menu_data) + #VITAL! This closes out the menu system and returns you to the bash prompt. + curses.endwin() + +if __name__ == '__main__': + main() + curses.endwin() \ No newline at end of file From b190d1c7ae1c33277486d2fb9b2e59e883df7680 Mon Sep 17 00:00:00 2001 From: omegadot Date: Thu, 26 Sep 2013 22:14:55 -0400 Subject: [PATCH 2/3] Took off artifact from the end. --- pimame_files/menu.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pimame_files/menu.py b/pimame_files/menu.py index fcb5ed5..ba7ddec 100755 --- a/pimame_files/menu.py +++ b/pimame_files/menu.py @@ -191,4 +191,3 @@ def main(): if __name__ == '__main__': main() - curses.endwin() \ No newline at end of file From a1432c3cdfe3ea585e1f7621655f2143a77cbeaf Mon Sep 17 00:00:00 2001 From: omegadot Date: Fri, 27 Sep 2013 21:57:08 -0400 Subject: [PATCH 3/3] Fixed stupid except: continue mistake. Should be pass... --- pimame_files/menu.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pimame_files/menu.py b/pimame_files/menu.py index ba7ddec..31d31a3 100755 --- a/pimame_files/menu.py +++ b/pimame_files/menu.py @@ -59,7 +59,7 @@ { 'title': "Genesis (DGen)", 'type': COMMAND, 'command': 'advmenu -cfg advmenu-dgen.rc' }, { 'title': "SNES (PiSNES / SNES9x Advmenu)", 'type': COMMAND, - 'command': '/home/pi/emulators/pisnes/snes9x.gui' }, + 'command': 'zsnes' }, { 'title': "NES (AdvanceMESS)", 'type': COMMAND, 'command': 'advmenu -cfg advmenu-nes.rc' }, { 'title': "Gameboy (Gearboy Advmenu)", 'type': COMMAND, @@ -178,7 +178,7 @@ def process_menu(menu, parent=None): game = subprocess.Popen(menu['options'][getin]['command'].split(), stderr = subprocess.PIPE, stdout = subprocess.PIPE) pid = game.pid - except: continue + except: pass #threading.Thread(target=kill_emu(pid)).start() elif menu['options'][getin]['type'] == MENU: process_menu(menu['options'][getin], menu) # display the submenu