This commit is contained in:
Milan Nikolic 2014-02-09 18:24:41 +01:00
parent 1bed133331
commit 4b6143f9a4
27 changed files with 788 additions and 731 deletions

4
m64py
View file

@ -48,8 +48,8 @@ def main():
QApplication.setAttribute(Qt.AA_X11InitThreads)
except AttributeError:
try:
Xlib = load_library('X11')
Xlib.XInitThreads()
xlib = load_library('X11')
xlib.XInitThreads()
except Exception:
pass

View file

@ -19,6 +19,7 @@ sys.path.insert(0, realpath("src"))
from m64py.core.defs import FRONTEND_VERSION
BASE_DIR = dirname(realpath(__file__))
class build_qt(Command):
user_options = []
@ -47,7 +48,7 @@ class build_qt(Command):
path.append(dirname(PyQt4.__file__))
os.putenv("PATH", os.pathsep.join(path))
if subprocess.call(["pyrcc4", qrc_file, "-o", py_file]) > 0:
self.warn("Unable to compile resource file %s" % (qrc_file))
self.warn("Unable to compile resource file %s" % qrc_file)
if not os.path.exists(py_file):
sys.exit(1)
os.putenv('PATH', origpath)
@ -62,9 +63,9 @@ class build_qt(Command):
elif filename.endswith('.qrc'):
self.compile_rc(join(dirpath, filename))
class build_exe(Command):
"""Needs PyQt4, pyUnRAR2, PyLZMA, PyWin32, PyInstaller, Inno Setup 5"""
user_options = []
arch = "i686-w64-mingw32"
url = "https://bitbucket.org/ecsv/mupen64plus-mxe-daily/get/master.zip"
@ -107,13 +108,13 @@ class build_exe(Command):
dest_path = join(self.dist_dir, "m64py")
shutil.copy(unrar_dll, dest_path)
shutil.copyfile(unrar_lic, join(dest_path, "doc", "unrar-license"))
for file in ["AUTHORS", "ChangeLog", "COPYING", "LICENSES", "README.md"]:
shutil.copy(join(BASE_DIR, file), dest_path)
for file_name in ["AUTHORS", "ChangeLog", "COPYING", "LICENSES", "README.md"]:
shutil.copy(join(BASE_DIR, file_name), dest_path)
def remove_files(self):
dest_path = join(self.dist_dir, "m64py")
for dirname in ["api", "include", "man6"]:
shutil.rmtree(join(dest_path, dirname))
for dir_name in ["api", "include", "man6"]:
shutil.rmtree(join(dest_path, dir_name))
def run_build_installer(self):
iss_file = ""
@ -148,6 +149,7 @@ class build_exe(Command):
self.remove_files()
self.run_build_installer()
class build_dmg(Command):
user_options = []
dist_dir = join(BASE_DIR, "dist", "macosx")
@ -187,14 +189,14 @@ class build_dmg(Command):
if not os.path.exists(dest_path):
os.mkdir(dest_path)
shutil.move(join(self.dist_dir, "M64Py.app"), dest_path)
for file in ["AUTHORS", "ChangeLog", "COPYING", "LICENSES", "README.md"]:
shutil.copy(join(BASE_DIR, file), dest_path)
for file_name in ["AUTHORS", "ChangeLog", "COPYING", "LICENSES", "README.md"]:
shutil.copy(join(BASE_DIR, file_name), dest_path)
shutil.copy(join(BASE_DIR, "test", "mupen64plus.v64"), dest_path)
def remove_files(self):
dest_path = join(self.dist_dir, "dmg", "M64Py.app", "Contents", "MacOS")
for dirname in ["include", "lib"]:
shutil.rmtree(join(dest_path, dirname))
for dir_name in ["include", "lib"]:
shutil.rmtree(join(dest_path, dir_name))
os.remove(join(self.dist_dir, "dmg", "M64Py.app", "Contents", "Resources", "icon-windowed.icns"))
def run_build_dmg(self):
@ -222,6 +224,7 @@ class build_dmg(Command):
self.set_plist()
self.run_build_dmg()
def set_sdl2():
opts_file = ""
opts_path = join(BASE_DIR, "src", "m64py", "opts.py")
@ -233,12 +236,12 @@ def set_sdl2():
opts_file += line + "\n"
with open(opts_path, "w") as opts: opts.write(opts_file)
def set_rthook():
import PyInstaller
hook_file = ""
module_dir = dirname(PyInstaller.__file__)
rthook = join(module_dir,
"loader", "rthooks", "pyi_rth_qt4plugins.py")
rthook = join(module_dir, "loader", "rthooks", "pyi_rth_qt4plugins.py")
with open(rthook, "r") as hook: data = hook.read()
if "sip.setapi" not in data:
lines = data.split("\n")
@ -250,6 +253,7 @@ def set_rthook():
hook_file += "sip.setapi('QVariant', 2)\n"
with open(rthook, "w") as hook: hook.write(hook_file)
class clean_local(Command):
pats = ['*.py[co]', '*_ui.py', '*_rc.py']
excludedirs = ['.git', 'build', 'dist']
@ -275,11 +279,13 @@ class clean_local(Command):
if any(fnmatch(fpath, p) for p in self.pats):
yield fpath
class mybuild(build):
def run(self):
self.run_command("build_qt")
build.run(self)
class myclean(clean):
def run(self):
self.run_command("clean_local")
@ -294,7 +300,8 @@ cmdclass = {
'clean_local': clean_local
}
setup(name = "m64py",
setup(
name = "m64py",
version = FRONTEND_VERSION,
description = "M64Py - A frontend for Mupen64Plus",
long_description = "M64Py is a Qt4 front-end (GUI) for Mupen64Plus 2.0, a cross-platform plugin-based Nintendo 64 emulator.",

View file

@ -28,7 +28,7 @@ try:
import UnRAR2
HAS_RAR = True
RAR_CMD = None
except:
except ImportError:
HAS_RAR = False
RAR_CMD = which("rar") or which("unrar")
@ -36,7 +36,7 @@ try:
from py7zlib import Archive7z
HAS_7Z = True
LZMA_CMD = None
except:
except ImportError:
HAS_7Z = False
LZMA_CMD = which("7z")
@ -52,6 +52,7 @@ ROM_TYPE = {
'40123780': 'n64 (wordswapped)'
}
class Archive():
"""Extracts ROM file from archive."""
@ -59,7 +60,7 @@ class Archive():
"""Opens archive."""
self.file = os.path.realpath(filename)
if not os.path.isfile(self.file) or not os.access(self.file, os.R_OK):
raise IOError("Cannot open %s. No such file." % (self.file))
raise IOError("Cannot open %s. No such file." % self.file)
self.filetype = self.get_filetype()
@ -77,16 +78,16 @@ class Archive():
elif RAR_CMD:
self.fd = RarCmd(self.file)
else:
raise IOError("UnRAR2 module or rar/unrar is needed for %s." % (self.file))
raise IOError("UnRAR2 module or rar/unrar is needed for %s." % self.file)
elif self.filetype == LZMA:
if HAS_7Z:
self.fd = Archive7z(open(self.file, 'rb'))
elif LZMA_CMD:
self.fd = LzmaCmd(self.file)
else:
raise IOError("lzma module or 7z is needed for %s." % (self.file))
raise IOError("lzma module or 7z is needed for %s." % self.file)
else:
raise IOError("File %s is not a N64 ROM file." % (self.file))
raise IOError("File %s is not a N64 ROM file." % self.file)
self.namelist = self.get_namelist()
@ -163,6 +164,7 @@ class Archive():
return ROM
return None
class RarCmd:
"""Extracts ROM file from RAR archive."""
@ -170,6 +172,7 @@ class RarCmd:
"""Opens archive."""
self.fd = None
self.file = archive
self.filename = None
self.namelist = self.namelist()
self.tempdir = tempfile.mkdtemp()
@ -200,6 +203,7 @@ class RarCmd:
self.fd.close()
shutil.rmtree(self.tempdir)
class LzmaCmd:
"""Extracts ROM file from 7z archive."""
@ -207,6 +211,7 @@ class LzmaCmd:
"""Opens archive."""
self.fd = None
self.file = archive
self.filename = None
self.namelist = self.namelist()
self.tempdir = tempfile.mkdtemp()

View file

@ -23,6 +23,7 @@ from m64py.frontend.log import log
SECTIONS_FUNC = C.CFUNCTYPE(None, C.c_void_p, C.c_char_p)
PARAMETERS_FUNC = C.CFUNCTYPE(None, C.c_void_p, C.c_char_p, C.c_int)
class Config:
"""Mupen64Plus configuration"""
@ -48,8 +49,7 @@ class Config:
"""Enumerates the list of sections in config file."""
self.m64p.ConfigListSections.argtypes = [C.c_void_p, C.c_void_p]
rval = self.m64p.ConfigListSections(
C.c_void_p(),
SECTIONS_FUNC(self.list_sections_callback))
C.c_void_p(), SECTIONS_FUNC(self.list_sections_callback))
if rval != M64ERR_SUCCESS:
log.debug("list_sections()")
log.warn(self.core.error_message(rval))
@ -171,8 +171,7 @@ class Config:
C.c_void_p, C.c_char_p, C.c_int, C.c_void_p, C.c_int]
rval = self.m64p.ConfigGetParameter(
self.config_handle, C.c_char_p(param_name),
C.c_int(param_type), param_value,
C.c_int(maxsize))
C.c_int(param_type), param_value, C.c_int(maxsize))
if rval != M64ERR_SUCCESS:
log.debug("get_parameter()")
log.warn(self.core.error_message(rval))
@ -189,8 +188,7 @@ class Config:
self.m64p.ConfigGetParameterHelp.argtypes = [
C.c_void_p, C.c_char_p, C.POINTER(C.c_int)]
rval = self.m64p.ConfigGetParameterType(
self.config_handle, C.c_char_p(param_name),
param_type)
self.config_handle, C.c_char_p(param_name), param_type)
if rval != M64ERR_SUCCESS:
log.debug("get_parameter_type()")
log.warn(self.core.error_message(rval))

View file

@ -40,6 +40,7 @@ def debug_callback(context, level, message):
elif level == M64MSG_VERBOSE and VERBOSE:
sys.stderr.write("%s: %s\n" % (context, message))
def state_callback(context, param, value):
if param == M64CORE_VIDEO_SIZE:
pass
@ -52,6 +53,7 @@ STATEFUNC = C.CFUNCTYPE(None, C.c_char_p, C.c_int, C.c_int)
DEBUG_CALLBACK = DEBUGFUNC(debug_callback)
STATE_CALLBACK = STATEFUNC(state_callback)
class Core:
"""Mupen64Plus Core library"""
@ -71,6 +73,7 @@ class Core:
self.rom_length = None
self.rom_header = m64p_rom_header()
self.rom_settings = m64p_rom_settings()
self.core_path = ""
self.core_name = "Mupen64Plus Core"
self.core_version = "Unknown"
self.core_sdl2 = False
@ -98,25 +101,40 @@ class Core:
if version:
plugin_type, plugin_version, plugin_api, plugin_name, plugin_cap = version
if plugin_type != M64PLUGIN_CORE:
raise Exception("library '%s' is invalid, this is not the emulator core." % (
raise Exception(
"library '%s' is invalid, "
"this is not the emulator core." % (
os.path.basename(self.core_path)))
elif plugin_version < MINIMUM_CORE_VERSION:
raise Exception("library '%s' is incompatible, core version %s is below minimum supported %s." % (
os.path.basename(self.core_path), version_split(plugin_version), version_split(MINIMUM_CORE_VERSION)))
raise Exception(
"library '%s' is incompatible, "
"core version %s is below minimum supported %s." % (
os.path.basename(self.core_path),
version_split(plugin_version),
version_split(MINIMUM_CORE_VERSION)))
elif plugin_api & 0xffff0000 != CORE_API_VERSION & 0xffff0000:
raise Exception("library '%s' is incompatible, core API major version %s doesn't match application (%s)." % (
os.path.basename(self.core_path), version_split(plugin_version), version_split(CORE_API_VERSION)))
raise Exception(
"library '%s' is incompatible, "
"core API major version %s doesn't match application (%s)." % (
os.path.basename(self.core_path),
version_split(plugin_version),
version_split(CORE_API_VERSION)))
else:
config_ver, debug_ver, vidext_ver = self.get_api_versions()
if config_ver & 0xffff0000 != CONFIG_API_VERSION & 0xffff0000:
raise Exception("emulator core '%s' is incompatible, config API major version %s doesn't match application: (%s)" % (
os.path.basename(self.core_path), version_split(self.config_version), version_split(CONFIG_API_VERSION)))
raise Exception(
"emulator core '%s' is incompatible, "
"config API major version %s doesn't match application: (%s)" % (
os.path.basename(self.core_path),
version_split(config_ver),
version_split(CONFIG_API_VERSION)))
self.core_name = plugin_name
self.core_version = plugin_version
if LDD_CMD:
proc = subprocess.Popen(LDD_CMD % self.core_path, shell=True,
proc = subprocess.Popen(
LDD_CMD % self.core_path, shell=True,
preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL))
proc.communicate()
if proc.returncode == 0:
@ -140,8 +158,8 @@ class Core:
def core_startup(self, path, use_vidext):
"""Initializes libmupen64plus for use by allocating memory,
creating data structures, and loading the configuration file."""
rval = self.m64p.CoreStartup(C.c_int(CORE_API_VERSION), None,
C.c_char_p(os.path.dirname(path)),
rval = self.m64p.CoreStartup(
C.c_int(CORE_API_VERSION), None, C.c_char_p(os.path.dirname(path)),
"Core", DEBUG_CALLBACK, "State", STATE_CALLBACK)
if rval == M64ERR_SUCCESS:
if use_vidext:
@ -206,8 +224,8 @@ class Core:
if version:
plugin_type, plugin_version, plugin_api, plugin_desc, plugin_cap = version
plugin_name = os.path.basename(plugin_path)
self.plugin_map[plugin_type][plugin_name] = (plugin_handle, plugin_path,
PLUGIN_NAME[plugin_type], plugin_desc, plugin_version)
self.plugin_map[plugin_type][plugin_name] = (
plugin_handle, plugin_path, PLUGIN_NAME[plugin_type], plugin_desc, plugin_version)
def plugin_startup(self, handle, name, desc):
"""This function initializes plugin for use by allocating memory,
@ -217,7 +235,7 @@ class Core:
if rval != M64ERR_SUCCESS:
log.debug("plugin_startup()")
log.warn(self.error_message(rval))
log.warn("%s failed to start." % (desc))
log.warn("%s failed to start." % desc)
def plugin_shutdown(self, handle, desc):
"""This function destroys data structures and releases
@ -226,9 +244,9 @@ class Core:
if rval != M64ERR_SUCCESS:
log.debug("plugin_shutdown()")
log.warn(self.error_message(rval))
log.warn("%s failed to stop." % (desc))
log.warn("%s failed to stop." % desc)
def attach_plugins(self, plugins={}):
def attach_plugins(self, plugins):
"""Attaches plugins to the emulator core."""
self.plugins = plugins
for plugin_type in PLUGIN_ORDER:
@ -241,8 +259,7 @@ class Core:
plugin_desc, plugin_version) = plugin_map
rval = self.m64p.CoreAttachPlugin(
C.c_int(plugin_type),
C.c_void_p(plugin_handle._handle))
C.c_int(plugin_type), C.c_void_p(plugin_handle._handle))
if rval != M64ERR_SUCCESS:
log.debug("attach_plugins()")
log.warn(self.error_message(rval))
@ -282,8 +299,7 @@ class Core:
if rval != M64ERR_SUCCESS:
log.debug("rom_open()")
log.warn(self.error_message(rval))
log.error("core failed to open ROM file '%s'." % (
filename))
log.error("core failed to open ROM file.")
del rombuffer
return rval
@ -359,8 +375,7 @@ class Core:
value of a state parameter."""
state_ptr = C.pointer(C.c_int())
rval = self.m64p.CoreDoCommand(
M64CMD_CORE_STATE_QUERY,
C.c_int(state), state_ptr)
M64CMD_CORE_STATE_QUERY, C.c_int(state), state_ptr)
if rval != M64ERR_SUCCESS:
log.debug("core_state_query()")
log.warn(self.error_message(rval))
@ -371,8 +386,7 @@ class Core:
parameter in the emulator core."""
value_ptr = C.pointer(C.c_int(value))
rval = self.m64p.CoreDoCommand(
M64CMD_CORE_STATE_SET,
C.c_int(state), value_ptr)
M64CMD_CORE_STATE_SET, C.c_int(state), value_ptr)
if rval != M64ERR_SUCCESS:
log.debug("core_state_set()")
log.warn(self.error_message(rval))
@ -458,8 +472,9 @@ class Core:
def add_cheat(self, cheat_name, cheat_code):
"""Adds a Cheat Function to a list of currently active cheats
which are applied to the open ROM, and set its state to Enabled"""
rval = self.m64p.CoreAddCheat(C.c_char_p(cheat_name),
C.pointer(cheat_code), C.c_int(C.sizeof(cheat_code)))
rval = self.m64p.CoreAddCheat(
C.c_char_p(cheat_name), C.pointer(cheat_code),
C.c_int(C.sizeof(cheat_code)))
if rval != M64ERR_SUCCESS:
log.debug("add_cheat()")
log.info("CoreAddCheat() failed for cheat code '%s'" % cheat_name)

View file

@ -162,6 +162,7 @@ M64P_SAVES = {
m64p_error = C.c_int
m64p_GLattr = C.c_int
class m64p_rom_header(C.Structure):
_fields_ = [
('init_PI_BSB_DOM1_LAT_REG', C.c_ubyte),
@ -181,6 +182,7 @@ class m64p_rom_header(C.Structure):
('Country_code', C.c_ushort)
]
class m64p_rom_settings(C.Structure):
_fields_ = [
('goodname', C.c_char * 256),
@ -191,12 +193,14 @@ class m64p_rom_settings(C.Structure):
('rumble', C.c_ubyte)
]
class m64p_cheat_code(C.Structure):
_fields_ = [
('address', C.c_uint),
('value', C.c_int),
]
class m64p_2d_size(C.Structure):
_fields_ = [
('uiWidth', C.c_uint),
@ -215,6 +219,7 @@ FuncSetCaption = C.CFUNCTYPE(m64p_error, C.c_char_p)
FuncToggleFS = C.CFUNCTYPE(m64p_error)
FuncResizeWindow = C.CFUNCTYPE(m64p_error, C.c_int, C.c_int)
class m64p_video_extension_functions(C.Structure):
_fields_ = [
('Functions', C.c_uint),

View file

@ -57,6 +57,7 @@ except Exception, err:
(1280, 960), (1152, 864), (1024, 768),
(800, 600), (640, 480), (320, 240)]
class Video():
"""Mupen64Plus video extension"""
@ -64,6 +65,7 @@ class Video():
"""Constructor."""
self.parent = None
self.widget = None
self.glformat = None
self.glcontext = None
def set_widget(self, parent):
@ -114,8 +116,7 @@ class Video():
"""Sets the caption text of the
emulator rendering window. """
title = "M64Py :: %s" % title
self.parent.emit(
SIGNAL("set_caption(PyQt_PyObject)"), title)
self.parent.emit(SIGNAL("set_caption(PyQt_PyObject)"), title)
return M64ERR_SUCCESS
def toggle_fs(self):

View file

@ -27,6 +27,7 @@ from m64py.frontend.log import log
from m64py.ui.cheat_ui import Ui_CheatDialog
from m64py.ui.choices_ui import Ui_ChoicesDialog
class Cheat(QDialog, Ui_CheatDialog):
"""Cheats dialog"""
@ -106,13 +107,13 @@ class Cheat(QDialog, Ui_CheatDialog):
def on_unmark_all(self):
"""Deactivates all cheats"""
iter = QTreeWidgetItemIterator(self.treeWidget)
while(iter.value()):
item = iter.value()
it = QTreeWidgetItemIterator(self.treeWidget)
while it.value():
item = it.value()
state = item.checkState(0)
if state == Qt.Checked:
item.setCheckState(0, Qt.Unchecked)
iter += 1
it += 1
def activate_cheat(self, item, column):
"""Activates selected cheat"""
@ -184,8 +185,7 @@ class Cheat(QDialog, Ui_CheatDialog):
cheat_codes = []
cheat_file = os.path.join(
self.parent.worker.core.config.get_path(
"SharedData"), 'mupencheat.txt')
self.parent.worker.core.config.get_path( "SharedData"), 'mupencheat.txt')
if not os.path.isfile(cheat_file) or not os.access(cheat_file, os.R_OK):
log.warn("cheat code database file '%s' not found." % cheat_file)
return None
@ -196,14 +196,12 @@ class Cheat(QDialog, Ui_CheatDialog):
self.parent.worker.core.rom_header.Country_code & 0xff)
rom_section = rom_section.upper()
code_re = re.compile(
'^([0-9A-F]{8})\s+([?|0-9A-F]{4})\s?(.*)$', re.M)
code_re = re.compile('^([0-9A-F]{8})\s+([?|0-9A-F]{4})\s?(.*)$', re.M)
try:
fd = open(cheat_file, 'r')
except IOError:
log.warn("couldn't open cheat code database file '%s'." % (
cheat_file))
log.warn("couldn't open cheat code database file '%s'." % cheat_file)
return None
else:
lines = [line.strip() for line in fd.readlines()]
@ -267,9 +265,10 @@ class Cheat(QDialog, Ui_CheatDialog):
if line:
# otherwise we don't know what this line is
log.warn("unrecognized line in cheat file: '%s'" % (line))
log.warn("unrecognized line in cheat file: '%s'" % line)
return None
class Choices(QDialog, Ui_ChoicesDialog):
"""Choices dialog"""

View file

@ -23,6 +23,7 @@ from m64py.ui.about_ui import Ui_AboutDialog
from m64py.ui.license_ui import Ui_LicenseDialog
from m64py.ui.archive_ui import Ui_ArchiveDialog
class AboutDialog(QDialog, Ui_AboutDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
@ -37,12 +38,14 @@ class AboutDialog(QDialog, Ui_AboutDialog):
self.labelAbout.setText(text)
self.show()
class LicenseDialog(QDialog, Ui_LicenseDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
self.setupUi(self)
self.show()
class InfoDialog(QMessageBox):
def __init__(self, parent=None, text=None):
QMessageBox.__init__(self, parent)
@ -50,6 +53,7 @@ class InfoDialog(QMessageBox):
self.setWindowTitle("Info")
self.show()
class ArchiveDialog(QDialog, Ui_ArchiveDialog):
def __init__(self, parent, files):
QDialog.__init__(self, parent)

View file

@ -14,7 +14,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtOpenGL import *
@ -22,6 +21,7 @@ from m64py.core.defs import *
from m64py.opts import SDL2
from m64py.frontend.keymap import QT2SDL, QT2SDL2
class GLWidget(QGLWidget):
toggle_fs = pyqtSignal()
@ -34,7 +34,7 @@ class GLWidget(QGLWidget):
self.setContentsMargins(QMargins())
self.setFocusPolicy(Qt.StrongFocus)
self.setFocus(True)
self.connect(self, SIGNAL("toggle_fs()"), self.toggle_fs)
self.connect(self, SIGNAL("toggle_fs()"), self.toggle_fullscreen)
def showEvent(self, event):
self.setFocus(True)
@ -47,7 +47,7 @@ class GLWidget(QGLWidget):
pass
def mouseDoubleClickEvent(self, event):
self.toggle_fs()
self.emit(SIGNAL("toggle_fs()"))
def keyPressEvent(self, event):
if self.worker.state == M64EMU_RUNNING:
@ -55,7 +55,7 @@ class GLWidget(QGLWidget):
modifiers = event.modifiers()
if modifiers & Qt.AltModifier and \
(key == Qt.Key_Enter or key == Qt.Key_Return):
self.toggle_fs()
self.emit(SIGNAL("toggle_fs()"))
elif key == Qt.Key_F3:
self.worker.save_title()
elif key == Qt.Key_F4:
@ -82,7 +82,7 @@ class GLWidget(QGLWidget):
except KeyError:
pass
def toggle_fs(self):
def toggle_fullscreen(self):
window = self.window()
if window.isFullScreen():
self.parent.menubar.show()

View file

@ -34,6 +34,7 @@ else:
KEY_RE = re.compile("([a-z]+)\((.*)\)")
AXIS_RE = re.compile("([a-z]+)\((.*?),(.*?)\)")
class Input(QDialog, Ui_InputDialog):
def __init__(self, parent):
@ -44,6 +45,9 @@ class Input(QDialog, Ui_InputDialog):
self.controller = 1
self.mode = 0
self.device = -1
self.opts = {}
self.keys = {}
self.section = None
self.is_joystick = False
self.set_section("Input-SDL-Control%d" % self.controller)
self.joystick = Joystick()
@ -104,11 +108,18 @@ class Input(QDialog, Ui_InputDialog):
self.comboController.addItem(
self.tr("Controller %s" % controller), controller)
for plugin, ptype in [(self.tr("None"), 1), (self.tr("Mem pak"), 2), (self.tr("Rumble pak"), 5)]:
for plugin, ptype in [
(self.tr("None"), 1),
(self.tr("Mem pak"), 2),
(self.tr("Rumble pak"), 5)
]:
self.comboPlugin.addItem(plugin, ptype)
for mode, mtype in [(self.tr("Fully Manual"), 0),
(self.tr("Auto with named SDL device"), 1), (self.tr("Fully Automatic"), 2)]:
for mode, mtype in [
(self.tr("Fully Manual"), 0),
(self.tr("Auto with named SDL device"), 1),
(self.tr("Fully Automatic"), 2)
]:
self.comboMode.addItem(mode, mtype)
devices = [(self.tr("Keyboard/Mouse"), -1)]
@ -226,19 +237,19 @@ class Input(QDialog, Ui_InputDialog):
for key, val in self.opts.items():
param, tooltip, widget, ptype = val
if ptype == M64TYPE_BOOL:
self.config.set_parameter(key,
widget.isChecked())
self.config.set_parameter(
key, widget.isChecked())
elif ptype == M64TYPE_INT:
self.config.set_parameter(key,
widget.itemData(widget.currentIndex()))
self.config.set_parameter(
key, widget.itemData(widget.currentIndex()))
elif ptype == M64TYPE_STRING:
if key in ["AnalogDeadzone", "AnalogPeak"]:
spin1, spin2 = widget
self.config.set_parameter(key,"%s,%s" % (
spin1.value(), spin2.value()))
else:
self.config.set_parameter(key,
str(widget.text()))
self.config.set_parameter(
key, str(widget.text()))
def get_keys(self):
self.keys = {
@ -284,7 +295,6 @@ class Input(QDialog, Ui_InputDialog):
self.get_key("Y Axis")[1], self.pushY_Axis_D)
}
def set_keys(self):
for key, val in self.keys.items():
ckey, widget = val
@ -405,7 +415,7 @@ class Input(QDialog, Ui_InputDialog):
from m64py.SDL2.keyboard import SDL_GetScancodeName
try:
text = SDL_GetScancodeName(KEYCODE2SCANCODE[int(sdl_key)])
except:
except Exception:
return self.tr("Select...")
else:
from m64py.SDL.keyboard import SDL_GetKeyName

View file

@ -39,6 +39,7 @@ JOYSTICK_SENSITIVITY = 0
SDL_JOYSTICK_DEFAULT_EVENT_TIMEOUT = 25
SDL_JOYSTICK_DEFAULT_AUTOREPEAT_DELAY = 250
class Joystick(QObject):
axis_value_changed = pyqtSignal(int, int)
@ -52,7 +53,6 @@ class Joystick(QObject):
joystick_deadzone=JOYSTICK_DEADZONE,
joystick_sensitivity=JOYSTICK_SENSITIVITY):
QObject.__init__(self)
self.joystick_timer = QTimer()
self.deadzones = {}
@ -81,8 +81,7 @@ class Joystick(QObject):
self.joystick_names.append(SDL_JoystickNameForIndex(i))
else:
self.joystick_names.append(SDL_JoystickName(i))
self.connect(self.joystick_timer, SIGNAL("timeout()"),
self.process_events)
self.connect(self.joystick_timer, SIGNAL("timeout()"), self.process_events)
else:
log.info("couldn't initialize SDL joystick support")

View file

@ -22,6 +22,7 @@ from PyQt4.QtGui import QDialog, QTextCursor
from m64py.ui.logview_ui import Ui_LogView
class Log:
def __init__(self, out=None, logview=None):
self.out = out
@ -31,8 +32,9 @@ class Log:
if self.out:
self.out.write(msg)
if self.logview:
self.logview.emit(
SIGNAL("msg_written(PyQt_PyObject)"), msg)
self.logview.emit(SIGNAL(
"msg_written(PyQt_PyObject)"), msg)
class LogView(QDialog, Ui_LogView):
msg_written = pyqtSignal(str)
@ -41,13 +43,14 @@ class LogView(QDialog, Ui_LogView):
QDialog.__init__(self, parent)
self.setupUi(self)
self.textEdit.setReadOnly(True)
self.connect(self, SIGNAL("msg_written(PyQt_PyObject)"),
self.on_msg_written)
self.connect(self, SIGNAL(
"msg_written(PyQt_PyObject)"), self.on_msg_written)
def on_msg_written(self, msg):
self.textEdit.moveCursor(QTextCursor.End)
self.textEdit.insertPlainText(msg)
class Logger():
def __init__(self):
log_format = 'Frontend: %(levelname)s: %(message)s'

View file

@ -33,6 +33,7 @@ from m64py.frontend.glwidget import GLWidget
from m64py.ui.mainwindow_ui import Ui_MainWindow
from m64py.frontend.recentfiles import RecentFiles
class MainWindow(QMainWindow, Ui_MainWindow):
"""Frontend main window"""
@ -55,9 +56,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
logview.setParent(self)
logview.setWindowFlags(Qt.Dialog)
self.statusbarLabel = QLabel()
self.statusbarLabel.setIndent(2)
self.statusbar.addPermanentWidget(self.statusbarLabel, 1)
self.statusbar_label = QLabel()
self.statusbar_label.setIndent(2)
self.statusbar.addPermanentWidget(self.statusbar_label, 1)
self.update_status(self.tr(
"Welcome to M64Py version %s." % FRONTEND_VERSION))
@ -66,6 +67,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
SIZE_2X: self.action2X,
SIZE_3X: self.action3X}
self.slots = {}
self.view = None
self.stack = None
self.glwidget = None
self.cheats = None
self.maximized = False
self.widgets_height = None
@ -73,8 +78,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.settings = Settings(self)
self.worker = Worker(self)
self.vidext = bool(int(
self.settings.qset.value("enable_vidext", 1)))
self.vidext = bool(
int(self.settings.qset.value("enable_vidext", 1)))
self.create_state_slots()
self.create_widgets()
@ -174,24 +179,15 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def connect_signals(self):
"""Connects signals."""
self.connect(self, SIGNAL("rom_opened()"),
self.on_rom_opened)
self.connect(self, SIGNAL("rom_closed()"),
self.on_rom_closed)
self.connect(self, SIGNAL("file_open(PyQt_PyObject, PyQt_PyObject)"),
self.file_open)
self.connect(self, SIGNAL("file_opening(PyQt_PyObject)"),
self.on_file_opening)
self.connect(self, SIGNAL("set_caption(PyQt_PyObject)"),
self.on_set_caption)
self.connect(self, SIGNAL("state_changed(PyQt_PyObject)"),
self.on_state_changed)
self.connect(self, SIGNAL("save_image(PyQt_PyObject)"),
self.on_save_image)
self.connect(self, SIGNAL("info_dialog(PyQt_PyObject)"),
self.on_info_dialog)
self.connect(self, SIGNAL("archive_dialog(PyQt_PyObject)"),
self.on_archive_dialog)
self.connect(self, SIGNAL("rom_opened()"), self.on_rom_opened)
self.connect(self, SIGNAL("rom_closed()"), self.on_rom_closed)
self.connect(self, SIGNAL("file_open(PyQt_PyObject, PyQt_PyObject)"), self.file_open)
self.connect(self, SIGNAL("file_opening(PyQt_PyObject)"), self.on_file_opening)
self.connect(self, SIGNAL("set_caption(PyQt_PyObject)"), self.on_set_caption)
self.connect(self, SIGNAL("state_changed(PyQt_PyObject)"), self.on_state_changed)
self.connect(self, SIGNAL("save_image(PyQt_PyObject)"), self.on_save_image)
self.connect(self, SIGNAL("info_dialog(PyQt_PyObject)"), self.on_info_dialog)
self.connect(self, SIGNAL("archive_dialog(PyQt_PyObject)"), self.on_archive_dialog)
def create_widgets(self):
"""Creates central widgets."""
@ -207,7 +203,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def create_state_slots(self):
"""Creates state slot actions."""
self.slots = {}
group = QActionGroup(self)
group.setExclusive(True)
for slot in range(10):
@ -226,7 +221,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
"""Creates window size actions."""
group = QActionGroup(self)
group.setExclusive(True)
size = self.settings.qset.value("size", SIZE_1X)
for num, size in enumerate(
sorted(self.sizes.keys()), 1):
width, height = size
@ -236,7 +230,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
action.setText("%dX" % num)
action.setToolTip("%sx%s" % (width, height))
self.connect(action, SIGNAL("triggered()"),
lambda w=w,h=h:self.resize(w, h))
lambda wi=w, he=h: self.resize(wi, he))
def file_open(self, filepath=None, filename=None):
"""Opens ROM file."""
@ -252,7 +246,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
def update_status(self, status):
"""Updates label in status bar."""
self.statusbarLabel.setText(status)
self.statusbar_label.setText(status)
def on_set_caption(self, title):
"""Sets window title."""
@ -485,6 +479,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
"""Shows log dialog."""
logview.show()
class View(QGraphicsView):
def __init__(self, parent=None):
QGraphicsView.__init__(self, parent)
@ -493,5 +488,4 @@ class View(QGraphicsView):
self.setStyleSheet("QGraphicsView {border:0px solid;margin:0px;}")
self.setResizeAnchor(QGraphicsView.AnchorViewCenter)
self.setScene(QGraphicsScene(self))
self.scene().addItem(
QGraphicsPixmapItem(QPixmap(":/images/front.png")))
self.scene().addItem(QGraphicsPixmapItem(QPixmap(":/images/front.png")))

View file

@ -21,12 +21,17 @@ from m64py.core.defs import *
from m64py.utils import format_label, format_options
from m64py.ui.plugin_ui import Ui_PluginDialog
class Plugin(QDialog, Ui_PluginDialog):
"""Plugin settings dialog"""
def __init__(self, parent):
QDialog.__init__(self, parent)
self.parent = parent
self.widgets = {}
self.items = None
self.config = None
self.section = None
self.setupUi(self)
def showEvent(self, event):
@ -61,7 +66,6 @@ class Plugin(QDialog, Ui_PluginDialog):
del item
def add_items(self):
self.widgets = {}
row1, row2 = 0, 0
for count, item in enumerate(self.items):
param_name, param_type = item
@ -101,7 +105,8 @@ class Plugin(QDialog, Ui_PluginDialog):
row2 += 1
widget = QCheckBox()
widget.setText(format_label(param_name))
if param_help: widget.setToolTip(param_help)
if param_help:
widget.setToolTip(param_help)
self.gridLayout.addWidget(widget, row2, 3)
self.widgets[param_name] = (widget, widget.__class__, opts)

View file

@ -17,6 +17,7 @@
from PyQt4.QtGui import QAction, QIcon, QPixmap
from PyQt4.QtCore import QFileInfo, SIGNAL
class RecentFiles():
"""Keeps track of last opened files."""
@ -24,8 +25,9 @@ class RecentFiles():
"""Constructor"""
self.parent = parent
self.max_recent = 5
self.recent_actions = []
self.recent_files = []
self.recent_actions = []
self.action_clear_history = QAction(self.parent)
self.create()
self.update()
@ -36,19 +38,18 @@ class RecentFiles():
action.setIcon(QIcon(QPixmap(":/icons/action_rom.png")))
self.recent_actions.append(action)
self.recent_actions[i].setVisible(False)
self.parent.connect(self.recent_actions[i],
SIGNAL("triggered()"), self.parent.file_open)
self.parent.connect(
self.recent_actions[i], SIGNAL("triggered()"), self.parent.file_open)
self.parent.menuRecent.addAction(self.recent_actions[i])
self.parent.menuRecent.addSeparator()
self.actionClearHistory = QAction(self.parent)
self.actionClearHistory.setText("&Clear history")
self.actionClearHistory.setEnabled(False)
self.actionClearHistory.setVisible(True)
self.actionClearHistory.setIcon(
self.action_clear_history.setText("&Clear history")
self.action_clear_history.setEnabled(False)
self.action_clear_history.setVisible(True)
self.action_clear_history.setIcon(
QIcon(QPixmap(":/icons/action_clear.png")))
self.parent.connect(self.actionClearHistory,
SIGNAL("triggered()"), self.clear)
self.parent.menuRecent.addAction(self.actionClearHistory)
self.parent.connect(
self.action_clear_history, SIGNAL("triggered()"), self.clear)
self.parent.menuRecent.addAction(self.action_clear_history)
def update(self):
"""Updates list of recent files."""
@ -63,7 +64,7 @@ class RecentFiles():
self.recent_files[i]).filePath())
for j in range(num_files, self.max_recent):
self.recent_actions[j].setVisible(False)
self.actionClearHistory.setEnabled((num_files > 0))
self.action_clear_history.setEnabled((num_files > 0))
def add(self, filepath):
"""Adds file to recent files list."""

View file

@ -20,6 +20,7 @@ from PyQt4.QtGui import QMessageBox
from m64py.utils import sl
class RomInfo():
"""ROM information dialog"""

View file

@ -29,11 +29,10 @@ from m64py.ui.romlist_ui import Ui_ROMList
try:
from m64py.ui import title_rc
from m64py.ui import snapshot_rc
bool(title_rc)
bool(snapshot_rc)
except ImportError:
pass
class ROMList(QMainWindow, Ui_ROMList):
"""ROM list window"""
@ -46,6 +45,11 @@ class ROMList(QMainWindow, Ui_ROMList):
self.setAttribute(Qt.WA_DeleteOnClose, True)
self.qset = self.parent.settings.qset
self.romlist = {}
self.title_item = None
self.snapshot_item = None
self.roms = self.qset.value("rom_list", [])
rect = self.frameGeometry()
rect.moveCenter(QDesktopWidget().availableGeometry().center())
self.move(rect.topLeft())
@ -70,7 +74,6 @@ class ROMList(QMainWindow, Ui_ROMList):
def init(self):
self.read_rom_list()
self.roms = self.qset.value("rom_list", [])
if bool(int(self.qset.value("show_available", 0))):
self.add_available_items(self.roms)
else:
@ -78,29 +81,20 @@ class ROMList(QMainWindow, Ui_ROMList):
def connect_signals(self):
"""Connects signals."""
self.listWidget.currentItemChanged.connect(
self.on_item_changed)
self.listWidget.itemDoubleClicked.connect(
self.on_item_activated)
self.listWidget.itemActivated.connect(
self.on_item_activated)
self.checkAvailable.clicked.connect(
self.on_available_clicked)
self.progressBar.valueChanged.connect(
self.on_progress_bar_changed)
self.pushRefresh.clicked.connect(
self.refresh_items)
self.pushOpen.clicked.connect(
self.on_item_open)
self.connect(self.reader, SIGNAL("finished()"),
self.add_available_items)
self.listWidget.currentItemChanged.connect(self.on_item_changed)
self.listWidget.itemDoubleClicked.connect(self.on_item_activated)
self.listWidget.itemActivated.connect(self.on_item_activated)
self.checkAvailable.clicked.connect(self.on_available_clicked)
self.progressBar.valueChanged.connect(self.on_progress_bar_changed)
self.pushRefresh.clicked.connect(self.refresh_items)
self.pushOpen.clicked.connect(self.on_item_open)
self.connect(self.reader, SIGNAL("finished()"), self.add_available_items)
def read_rom_list(self):
"""Reads ROM list from ini file."""
inifile = os.path.join(self.shared_data_path, "mupen64plus.ini")
self.parser.read(inifile)
sections = self.parser.sections()
self.romlist = {}
for section in sections:
items = self.parser.items(section)
self.romlist[section] = dict(items)
@ -180,7 +174,8 @@ class ROMList(QMainWindow, Ui_ROMList):
self.file_open(path, fname)
def on_item_changed(self, current, previous):
if not current: return
if not current:
return
md5, path, fname = current.data(Qt.UserRole)
title = QPixmap(os.path.join(
@ -197,20 +192,20 @@ class ROMList(QMainWindow, Ui_ROMList):
snapshot = QPixmap(":/images/default.png")
if previous is not None:
self.titleView.scene().removeItem(self.titleItem)
self.snapshotView.scene().removeItem(self.snapshotItem)
self.titleView.scene().removeItem(self.title_item)
self.snapshotView.scene().removeItem(self.snapshot_item)
title_pixmap = title.scaled(self.titleView.size(),
Qt.KeepAspectRatio, Qt.SmoothTransformation)
snapshot_pixmap = snapshot.scaled(self.snapshotView.size(),
Qt.KeepAspectRatio, Qt.SmoothTransformation)
title_pixmap = title.scaled(
self.titleView.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
snapshot_pixmap = snapshot.scaled(
self.snapshotView.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
titleItem = QGraphicsPixmapItem(title_pixmap)
snapshotItem = QGraphicsPixmapItem(snapshot_pixmap)
self.titleView.scene().addItem(titleItem)
self.snapshotView.scene().addItem(snapshotItem)
self.titleItem = titleItem
self.snapshotItem = snapshotItem
title_item = QGraphicsPixmapItem(title_pixmap)
snapshot_item = QGraphicsPixmapItem(snapshot_pixmap)
self.titleView.scene().addItem(title_item)
self.snapshotView.scene().addItem(snapshot_item)
self.title_item = title_item
self.snapshot_item = snapshot_item
def on_available_clicked(self):
is_checked = self.checkAvailable.isChecked()
@ -224,6 +219,7 @@ class ROMList(QMainWindow, Ui_ROMList):
self.reader.stop()
self.add_items()
class ROMReader(QThread):
"""ROM reader thread"""
@ -269,8 +265,7 @@ class ROMReader(QThread):
log.warn(str(err))
continue
percent = float(filenum) / float(num_files) * 100
self.parent.progressBar.emit(
SIGNAL("valueChanged(int)"), percent)
self.parent.progressBar.emit(SIGNAL("valueChanged(int)"), percent)
self.exit()
def stop(self):

View file

@ -28,6 +28,7 @@ from m64py.frontend.plugin import Plugin
from m64py.frontend.input import Input
from m64py.ui.settings_ui import Ui_Settings
class Settings(QDialog, Ui_Settings):
"""Settings dialog"""
@ -37,6 +38,8 @@ class Settings(QDialog, Ui_Settings):
self.setupUi(self)
self.core = None
self.plugins = []
self.emumode = []
self.combomap = {}
self.qset = QSettings("m64py", "m64py")
self.input = Input(self.parent)
self.add_items()
@ -61,12 +64,14 @@ class Settings(QDialog, Ui_Settings):
Plugin(self.parent)),
M64PLUGIN_INPUT: (
self.comboInput, self.pushButtonInput,
self.input)}
self.input)
}
self.emumode = [
QRadioButton(self.tr("Pure Interpreter")),
QRadioButton(self.tr("Cached Interpreter")),
QRadioButton(self.tr("Dynamic Recompiler"))]
QRadioButton(self.tr("Dynamic Recompiler"))
]
vbox = QVBoxLayout(self.groupEmuMode)
for widget in self.emumode:
@ -151,7 +156,7 @@ class Settings(QDialog, Ui_Settings):
desc = combo.itemData(index)
name = os.path.splitext(plugin)[0][12:]
section = "-".join([n.capitalize() for n in name.split("-")[0:2]])
return (section, desc)
return section, desc
def set_section(self, combo, button, settings):
if settings:
@ -171,10 +176,10 @@ class Settings(QDialog, Ui_Settings):
button.setEnabled(False)
def set_paths(self):
path_library = self.qset.value("Paths/Library",
find_library(CORE_NAME))
path_data = self.qset.value("Paths/Data",
self.core.config.get_path("SharedData"))
path_library = self.qset.value(
"Paths/Library", find_library(CORE_NAME))
path_data = self.qset.value(
"Paths/Data", self.core.config.get_path("SharedData"))
path_roms = self.qset.value("Paths/ROM")
try:
@ -266,19 +271,16 @@ class Settings(QDialog, Ui_Settings):
current = self.qset.value("Plugins/%s" % (
PLUGIN_NAME[plugin_type]), PLUGIN_DEFAULT[plugin_type])
index = combo.findText(current)
if index == -1: index = 0
if index == -1:
index = 0
combo.setCurrentIndex(index)
self.set_section(combo, button, settings)
def save_paths(self):
self.qset.setValue("Paths/Library",
self.pathLibrary.text())
self.qset.setValue("Paths/Plugins",
self.pathPlugins.text())
self.qset.setValue("Paths/Data",
self.pathData.text())
self.qset.setValue("Paths/ROM",
self.pathROM.text())
self.qset.setValue("Paths/Library", self.pathLibrary.text())
self.qset.setValue("Paths/Plugins", self.pathPlugins.text())
self.qset.setValue("Paths/Data", self.pathData.text())
self.qset.setValue("Paths/ROM", self.pathROM.text())
def save_video(self):
if not self.parent.vidext:
@ -294,24 +296,15 @@ class Settings(QDialog, Ui_Settings):
def save_core(self):
self.core.config.open_section("Core")
emumode = [n for n,m in enumerate(self.emumode) if m.isChecked()][0]
self.core.config.set_parameter("R4300Emulator",
emumode)
self.core.config.set_parameter("OnScreenDisplay",
self.checkOSD.isChecked())
self.core.config.set_parameter("NoCompiledJump",
self.checkNoCompiledJump.isChecked())
self.core.config.set_parameter("DisableExtraMem",
self.checkDisableExtraMem.isChecked())
self.core.config.set_parameter("DelaySI",
self.checkDelaySI.isChecked())
self.core.config.set_parameter("CountPerOp",
self.comboCountPerOp.currentIndex())
self.core.config.set_parameter("SharedDataPath",
self.pathData.text())
self.core.config.set_parameter("R4300Emulator", emumode)
self.core.config.set_parameter("OnScreenDisplay", self.checkOSD.isChecked())
self.core.config.set_parameter("NoCompiledJump", self.checkNoCompiledJump.isChecked())
self.core.config.set_parameter("DisableExtraMem", self.checkDisableExtraMem.isChecked())
self.core.config.set_parameter("DelaySI", self.checkDelaySI.isChecked())
self.core.config.set_parameter("CountPerOp", self.comboCountPerOp.currentIndex())
self.core.config.set_parameter("SharedDataPath", self.pathData.text())
def save_plugins(self):
for plugin_type in self.combomap:
combo, button, settings = self.combomap[plugin_type]
self.qset.setValue("Plugins/%s" %
PLUGIN_NAME[plugin_type],
combo.currentText())
self.qset.setValue("Plugins/%s" % PLUGIN_NAME[plugin_type], combo.currentText())

View file

@ -29,6 +29,7 @@ from m64py.core.vidext import video
from m64py.archive import Archive
from m64py.platform import DLL_EXT, DEFAULT_DYNLIB, SEARCH_DIRS
class Worker(QThread):
"""Mupen64Plus thread worker"""
@ -38,6 +39,9 @@ class Worker(QThread):
self.parent = parent
self.video = video
self.plugin_files = []
self.archive = None
self.filepath = None
self.filename = None
self.library_path = None
self.state = M64EMU_STOPPED
self.settings = self.parent.settings
@ -53,13 +57,13 @@ class Worker(QThread):
self.parent.settings.core = self.core
if self.parent.args:
self.parent.emit(SIGNAL("file_open(PyQt_PyObject, PyQt_PyObject)"),
self.parent.args[0], None)
self.parent.emit(SIGNAL(
"file_open(PyQt_PyObject, PyQt_PyObject)"), self.parent.args[0], None)
else:
self.parent.emit(SIGNAL("state_changed(PyQt_PyObject)"),
(False, False, False, False))
self.parent.emit(SIGNAL("info_dialog(PyQt_PyObject)"),
self.tr("Mupen64Plus library not found."))
self.parent.emit(SIGNAL(
"state_changed(PyQt_PyObject)"), (False, False, False, False))
self.parent.emit(SIGNAL(
"info_dialog(PyQt_PyObject)"), self.tr("Mupen64Plus library not found."))
def quit(self):
if self.state in [M64EMU_RUNNING, M64EMU_PAUSED]:
@ -230,11 +234,10 @@ class Worker(QThread):
if screenshot:
image_name = "%s.png" % self.core.rom_settings.MD5
try:
shutil.copyfile(screenshot,
os.path.join(dst_path, image_name))
shutil.copyfile(screenshot, os.path.join(dst_path, image_name))
log.info("Captured %s" % capture)
except IOError:
log.exception("couldn't save image %s" % image)
log.exception("couldn't save image %s" % image_name)
def save_title(self):
"""Saves title."""

View file

@ -51,6 +51,7 @@ def _environ_path(name):
else:
return []
class LibraryLoader(object):
def __init__(self):
self.other_dirs = []
@ -126,7 +127,7 @@ class DarwinLibraryLoader(LibraryLoader):
if os.path.pathsep in libname:
names = [libname]
else:
names = [format % libname for format in self.name_formats]
names = [f % libname for f in self.name_formats]
for dirname in self.getdirs(libname):
for name in names:
@ -194,23 +195,23 @@ class PosixLibraryLoader(LibraryLoader):
except IOError:
pass
directories.extend(['/lib', '/usr/lib', '/lib64',
'/usr/lib64', '/usr/games/lib', '/usr/games/lib64',
directories.extend(['/lib', '/usr/lib', '/lib64', '/usr/lib64',
'/usr/games/lib', '/usr/games/lib64',
'/usr/lib/x86_64-linux-gnu', '/usr/lib/i386-linux-gnu'])
cache = {}
lib_re = re.compile(r'lib(.*)\.s[ol]')
for dir in directories:
for d in directories:
try:
for path in glob.glob("%s/*.s[ol]*" % dir):
file = os.path.basename(path)
for path in glob.glob("%s/*.s[ol]*" % d):
f = os.path.basename(path)
# Index by filename
if file not in cache:
cache[file] = path
if f not in cache:
cache[f] = path
# Index by library name
match = lib_re.match(file)
match = lib_re.match(f)
if match:
library = match.group(1)
if library not in cache:
@ -225,10 +226,13 @@ class PosixLibraryLoader(LibraryLoader):
self._create_ld_so_cache()
result = self._ld_so_cache.get(libname)
if result: yield result
if result:
yield result
path = ctypes.util.find_library(libname)
if path: yield os.path.join("/lib",path)
if path:
yield os.path.join("/lib", path)
class _WindowsLibrary(object):
def __init__(self, path):
@ -244,9 +248,11 @@ class _WindowsLibrary(object):
self.windll = ctypes.windll.LoadLibrary(path)
def __getattr__(self, name):
try: return getattr(self.cdll,name)
try:
return getattr(self.cdll, name)
except AttributeError:
try: return getattr(self.windll,name)
try:
return getattr(self.windll, name)
except AttributeError:
raise

View file

@ -20,6 +20,7 @@ import subprocess
from m64py.frontend.log import log
class LinuxScreenSaver:
cookie = None
screensaver = None
@ -35,7 +36,8 @@ class LinuxScreenSaver:
def disable(self):
if self.screensaver:
try:
self.cookie = self.screensaver.Inhibit("M64Py", "Emulation started")
self.cookie = self.screensaver.Inhibit(
"M64Py", "Emulation started")
log.info("ScreenSaver disabled")
except Exception, err:
log.exception(str(err))
@ -49,6 +51,7 @@ class LinuxScreenSaver:
except Exception, err:
log.exception(str(err))
class DarwinScreenSaver:
def __init__(self):
try:
@ -70,6 +73,7 @@ class DarwinScreenSaver:
shell=True)
log.info("ScreenSaver enabled")
class WindowsScreenSaver:
sys_param_info = None
SPI_SETSCREENSAVEACTIVE = 17

View file

@ -27,8 +27,8 @@ class ImageView(QGraphicsView):
size = event.size()
for item in self.scene().items():
pixmap = item.pixmap()
pixmap = pixmap.scaled(size,
Qt.KeepAspectRatio, Qt.SmoothTransformation)
pixmap = pixmap.scaled(
size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
item.setPixmap(pixmap)
self.ensureVisible(item)
self.centerOn(item)

View file

@ -31,6 +31,8 @@ class InputButton(QPushButton):
QPushButton.__init__(self, parent)
self.key = None
self.parent = parent
self.input = None
self.joystick = None
self.setFocusPolicy(Qt.ClickFocus)
def showEvent(self, event):

View file

@ -17,6 +17,7 @@ import os
import re
from hashlib import md5
def md5sum(filename=None, filedata=None, buf_size=8192):
m = md5()
if filename:
@ -31,6 +32,7 @@ def md5sum(filename=None, filedata=None, buf_size=8192):
m.update(data)
return m.hexdigest()
def which(prog):
def is_exe(fpath):
return os.path.exists(fpath) and os.access(fpath, os.X_OK)
@ -45,11 +47,13 @@ def which(prog):
return filename
return None
def version_split(ver):
return "%d.%d.%d" % (
(((ver) >> 16) & 0xffff),
(((ver) >> 8) & 0xff),
(((ver) & 0xff)))
((ver >> 16) & 0xffff),
((ver >> 8) & 0xff),
((ver & 0xff)))
def sl(mot):
return ((mot & 0x000000FF) << 24) |\
@ -57,6 +61,7 @@ def sl(mot):
((mot & 0x00FF0000) >> 8) |\
((mot & 0xFF000000) >> 24)
def format_tooltip(tooltip):
if len(tooltip) > 80:
lines = tooltip.split(". ")
@ -67,6 +72,7 @@ def format_tooltip(tooltip):
tooltip += "\n"
return tooltip
def format_label(label):
words = label.split("_")
if len(words) > 1:
@ -75,6 +81,7 @@ def format_label(label):
label = label.capitalize()
return label
def format_options(param_help):
opts = {}
if not param_help: