pylint validation in good progress, runners mostly ok

This commit is contained in:
Mathieu Comandon 2012-05-02 00:34:20 +02:00
parent 387d24ce86
commit 36e1223fc9
39 changed files with 652 additions and 527 deletions

View file

@ -0,0 +1 @@
"""Main Lutris package"""

View file

@ -153,6 +153,7 @@ class LutrisConfig():
return value
def get_system(self, key):
"""Return the value of 'key' for system config"""
try:
value = self.config["system"][key]
if str(value).lower() in ("false", "none", "no"):

View file

@ -20,31 +20,11 @@ from os.path import realpath, normpath, dirname, join, exists, expanduser
from xdg import BaseDirectory
import sys
name = "Lutris"
version = "0.2.6"
website = "http://lutris.net"
protocol_version = 1
INSTALLER_URL = "http://lutris.net/media/installers/"
#installer_prefix = "http://localhost:8000/media/installers/"
CONFIG_EXTENSION = ".yml"
license_id = 'GPL-3'
copyright = "(c) 2010 Lutris Gaming Platform"
authors = ["Mathieu Comandon <strycore@gmail.com>"]
artists = ["Ludovic Soulié <contact@yudoh.com>"]
license_text = """
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
LAUNCH_PATH = realpath(sys.path[0])
if LAUNCH_PATH.startswith('/usr'):
@ -56,7 +36,7 @@ else:
DATA_PATH = dirname(lutris.__file__)
if not exists(DATA_PATH):
print "DATA_PATH can't be found at : %s" % DATA_PATH
exit
exit()
LUTRIS_ICON = join(DATA_PATH, "media/logo.svg")
LUTRIS_CONFIG_PATH = join(BaseDirectory.xdg_config_home, 'lutris')

View file

@ -22,10 +22,12 @@ import threading
from lutris.util import log
class DownloadStoppedException(Exception):
""" Dummy exception for download canceled. """
def __init__(self):
pass
super(DownloadStoppedException, self).__init__()
class Downloader(threading.Thread):
"""Downloader class that doesn't block the program"""
@ -50,7 +52,7 @@ class Downloader(threading.Thread):
old_progress = self.progress
self.progress = ((piece * received_bytes)) / (total_size * 1.0)
if self.progress - old_progress > 0.05:
log.logger.debug("Progress: %0.2f%" % self.progress * 100)
log.logger.debug("Progress: %0.2f%%", self.progress * 100)
try:
if self.kill is True:

View file

@ -14,14 +14,20 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
### END LICENSE
import os
import gtk.gdk
import lutris.constants
"""About dialog"""
# pylint #37300 False positive F0401 on gtk.gdk import
# pylint: disable=F0401
import gtk.gdk
import os
from lutris import settings
from lutris.constants import LUTRIS_ICON
# pylint: disable=R0904, R0901
class AboutLutrisDialog(gtk.AboutDialog):
"""About dialog class"""
__gtype_name__ = "AboutLutrisDialog"
def __init__(self):
@ -50,13 +56,13 @@ class AboutLutrisDialog(gtk.AboutDialog):
self.set_position(gtk.WIN_POS_CENTER)
self.set_icon_from_file(LUTRIS_ICON)
self.set_logo(gtk.gdk.pixbuf_new_from_file(LUTRIS_ICON))
self.set_name(lutris.constants.name)
self.set_version(lutris.constants.version)
self.set_copyright(lutris.constants.copyright)
self.set_license(lutris.constants.license_text)
self.set_authors(lutris.constants.authors)
self.set_artists(lutris.constants.artists)
self.set_website(lutris.constants.website)
self.set_name(settings.PROJECT)
self.set_version(settings.VERSION)
self.set_copyright(settings.COPYRIGHT)
self.set_license(settings.LICENSE_TEXT)
self.set_authors(settings.AUTHORS)
self.set_artists(settings.ARTISTS)
self.set_website(settings.WEBSITE)
def NewAboutLutrisDialog(data_path):

View file

@ -19,35 +19,38 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
"""Dialog to add a game manually"""
import gtk
import logging
import lutris.runners
from lutris.runners import import_runner
from lutris.config import LutrisConfig
from lutris.util.log import logger
from lutris.gui.gameconfigvbox import GameConfigVBox
from lutris.gui.runnerconfigvbox import RunnerConfigVBox
from lutris.gui.systemconfigvbox import SystemConfigVBox
# pylint: disable=R0904
class AddGameDialog(gtk.Dialog):
""" Add game dialog class"""
def __init__(self, parent):
gtk.Dialog.__init__(self)
super(AddGameDialog, self).__init__()
self.parent_window = parent
self.set_title("Add a new game")
self.set_size_request(600, 500)
#Real name
realname_hbox = gtk.HBox()
self.realname_label = gtk.Label("Name")
realname_hbox.pack_start(self.realname_label, False, False, 5)
realname_label = gtk.Label("Name")
realname_hbox.pack_start(realname_label, False, False, 5)
self.realname_entry = gtk.Entry()
realname_hbox.pack_start(self.realname_entry)
self.vbox.pack_start(realname_hbox, False, False, 5)
self.lutris_config = LutrisConfig()
self.set_title("Add a new game")
self.set_size_request(600, 500)
#Runner
#get a list of available runners
runner_liststore = gtk.ListStore(str, str)
@ -58,28 +61,28 @@ class AddGameDialog(gtk.Dialog):
if hasattr(runner, "description"):
description = runner.description
else:
logging.debug("Please fix %s and add a description attribute"\
% runner_cls)
logger.debug("Please fix %s and add a description attribute",
runner_cls)
description = ""
if hasattr(runner, "machine"):
machine = runner.machine
else:
logging.debug("Please fix % and add a machine attribute"\
% runner_cls)
logger.debug("Please fix % and add a machine attribute",
runner_cls)
machine = ""
if runner.is_installed():
runner_liststore.append((machine + " (" + description + ")",
runner_name))
self.runner_combobox = gtk.ComboBox(runner_liststore)
self.runner_combobox.connect("changed", self.on_runner_changed)
runner_combobox = gtk.ComboBox(runner_liststore)
runner_combobox.connect("changed", self.on_runner_changed)
cell = gtk.CellRendererText()
self.runner_combobox.pack_start(cell, True)
self.runner_combobox.add_attribute(cell, 'text', 0)
self.vbox.pack_start(self.runner_combobox, False, True, 5)
runner_combobox.pack_start(cell, True)
runner_combobox.add_attribute(cell, 'text', 0)
self.vbox.pack_start(runner_combobox, False, True, 5)
self.notebook = gtk.Notebook()
self.vbox.pack_start(self.notebook)
notebook = gtk.Notebook()
self.vbox.pack_start(notebook)
#Game configuration
self.game_config_vbox = gtk.Label("Select a runner from the list")
@ -87,7 +90,7 @@ class AddGameDialog(gtk.Dialog):
self.conf_scroll_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
self.conf_scroll_window.add_with_viewport(self.game_config_vbox)
self.notebook.append_page(self.conf_scroll_window,
notebook.append_page(self.conf_scroll_window,
gtk.Label("Game configuration"))
#Runner configuration
@ -96,7 +99,7 @@ class AddGameDialog(gtk.Dialog):
self.runner_scroll_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
self.runner_scroll_window.add_with_viewport(self.runner_config_vbox)
self.notebook.append_page(self.runner_scroll_window,
notebook.append_page(self.runner_scroll_window,
gtk.Label("Runner configuration"))
#System configuration
@ -105,40 +108,39 @@ class AddGameDialog(gtk.Dialog):
self.system_scroll_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
self.system_scroll_window.add_with_viewport(self.system_config_vbox)
self.notebook.append_page(self.system_scroll_window,
notebook.append_page(self.system_scroll_window,
gtk.Label("System configuration"))
#Action area
cancel_button = gtk.Button(None, gtk.STOCK_CANCEL)
add_button = gtk.Button(None, gtk.STOCK_ADD)
self.action_area.pack_start(cancel_button)
self.action_area.pack_start(add_button)
cancel_button.connect("clicked", self.close)
add_button.connect("clicked", self.add_game)
#Finish
self.show_all()
self.run()
def add_game(self, button):
def add_game(self, _button):
"""OK button pressed in the Add Game Dialog"""
#Get name
realname = self.realname_entry.get_text()
#Get runner
self.lutris_config.config["realname"] = realname
self.lutris_config.config["runner"] = self.runner_class
logging.debug("saving")
logging.debug(self.lutris_config.config)
logging.debug(self.lutris_config.game_config)
logger.debug("saving")
logger.debug(self.lutris_config.config)
logger.debug(self.lutris_config.game_config)
if self.runner_class and realname:
game_identifier = self.lutris_config.save(config_type="game")
self.game_info = {"name": realname,
"runner": self.runner_class,
"id": game_identifier}
self.destroy()
def on_runner_changed(self, widget):
"""Action called when runner drop down is changed"""
selected_runner = widget.get_active()
scroll_windows_children = [self.conf_scroll_window.get_children(),
self.runner_scroll_window.get_children(),
@ -148,15 +150,15 @@ class AddGameDialog(gtk.Dialog):
child.destroy()
if selected_runner == 0:
self.no_runner_selected()
no_runner_label = gtk.Label("Choose a runner from the list")
no_runner_label.show()
self.runner_scroll_window.add_with_viewport(no_runner_label)
return
self.runner_class = widget.get_model()[selected_runner][1]
self.lutris_config = LutrisConfig(self.runner_class)
print self.runner_class
logging.debug("loading config before adding game : ")
logging.debug(self.lutris_config.config)
#Load game box
logger.debug("loading config before adding game : ")
logger.debug(self.lutris_config.config)
self.game_config_vbox = GameConfigVBox(self.lutris_config, "game")
self.conf_scroll_window.add_with_viewport(self.game_config_vbox)
self.conf_scroll_window.show_all()
@ -171,10 +173,6 @@ class AddGameDialog(gtk.Dialog):
self.system_scroll_window.add_with_viewport(self.system_config_vbox)
self.system_scroll_window.show_all()
def close(self, widget=None, other=None):
def close(self, _widget=None, _other=None):
"""Action received on dialog close"""
self.destroy()
def no_runner_selected(self):
no_runner_label = gtk.Label("Choose a runner from the list")
no_runner_label.show()
self.runner_scroll_window.add_with_viewport(no_runner_label)

View file

@ -19,72 +19,71 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Common message dialogs. """
"""Common message dialogs"""
import sys
import os
import pygtk
import gtk
from lutris.gui.widgets import DownloadProgressBox
class NoticeDialog(object):
# pylint: disable=R0901, R0904
class NoticeDialog(gtk.MessageDialog):
""" Displays a message to the user. """
def __init__(self, message):
dialog = gtk.MessageDialog(buttons=gtk.BUTTONS_OK)
dialog.set_markup(message)
dialog.run()
dialog.destroy()
super(NoticeDialog, self).__init__(buttons=gtk.BUTTONS_OK)
self.set_markup(message)
self.run()
self.destroy()
class ErrorDialog(object):
# pylint: disable=R0904
class ErrorDialog(gtk.MessageDialog):
""" Displays an error message. """
def __init__(self, message):
dialog = gtk.MessageDialog(buttons=gtk.BUTTONS_OK)
dialog.set_markup(message)
dialog.run()
dialog.destroy()
super(ErrorDialog, self).__init__(buttons=gtk.BUTTONS_OK)
self.set_markup(message)
self.run()
self.destroy()
class QuestionDialog(object):
class QuestionDialog(gtk.MessageDialog):
""" Asks a question. """
def __init__(self, settings):
dialog = gtk.MessageDialog(
super(QuestionDialog, self).__init__(
type=gtk.MESSAGE_QUESTION,
buttons=gtk.BUTTONS_YES_NO,
message_format=settings['question']
)
dialog.set_title(settings['title'])
self.result = dialog.run()
dialog.destroy()
self.set_title(settings['title'])
self.result = self.run()
self.destroy()
class DirectoryDialog:
class DirectoryDialog(gtk.FileChooserDialog):
"""Ask the user to select a directory"""
def __init__(self, message, default_path=None):
dialog = gtk.FileChooserDialog(
def __init__(self, message):
super(DirectoryDialog, self).__init__(
title=message,
action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE,
gtk.STOCK_OK, gtk.RESPONSE_OK)
gtk.STOCK_OK, gtk.RESPONSE_OK)
)
self.result = dialog.run()
self.folder = dialog.get_current_folder()
dialog.destroy()
self.result = self.run()
self.folder = self.get_current_folder()
self.destroy()
# pylint: disable=R0904
class DownloadDialog(gtk.Dialog):
""" Dialog showing a download in progress. """
def __init__(self, url, dest):
print "creating download dialog"
gtk.Dialog.__init__(self, "Downloading file")
self.quit_gtk = False
self.set_size_request(560, 100)
self.connect('destroy', self.destroy_cb)
params = {'url': url, 'dest': dest}
self.download_progress_box = DownloadProgressBox(params)
self.download_progress_box.connect('complete', self.download_complete)
#self.download_progress_box.connect('complete', self.download_complete)
label = gtk.Label('Downloading %s' % url)
label.set_padding(0, 0)
label.set_alignment(0.0, 1.0)
@ -94,13 +93,10 @@ class DownloadDialog(gtk.Dialog):
self.download_progress_box.start()
def destroy_cb(self, widget, data=None):
"""Action triggered when window is closed"""
self.download_cancel(None)
self.destroy()
if self.quit_gtk is True:
gtk.main_quit()
def download_cancel(self, widget, data=None):
def download_cancel(self, _widget, _data=None):
"""Action triggered when download is cancelled"""
self.download_progress_box.cancel()
def download_complete(self, widget, data=None):
print "download is complete"

View file

@ -18,18 +18,19 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
#Widget generators and their signal handlers
"""Widget generators and their signal handlers"""
import gtk
PADDING = 10
# pylint: disable=R0904
class Label(gtk.Label):
""" Standardised label for config vboxes"""
def __init__(self, str=None):
def __init__(self, message=None):
""" Custom init of label """
super(Label, self).__init__(str)
super(Label, self).__init__(message)
self.set_size_request(200, 30)
self.set_alignment(0.0, 0.5)
self.set_line_wrap(True)

View file

@ -19,6 +19,8 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
"""Game edition dialog"""
import logging
import gtk
from lutris.config import LutrisConfig
@ -27,7 +29,9 @@ from lutris.gui.runnerconfigvbox import RunnerConfigVBox
from lutris.gui.systemconfigvbox import SystemConfigVBox
# pylint: disable=R0904
class EditGameConfigDialog(gtk.Dialog):
"""Game config edit dialog"""
def __init__(self, parent, game):
self.parent_window = parent
self.game = game
@ -85,10 +89,12 @@ class EditGameConfigDialog(gtk.Dialog):
self.show_all()
self.run()
def edit_game(self, widget=None):
def edit_game(self, _widget=None):
"""Save the changes"""
logging.debug(self.lutris_config.config)
self.lutris_config.save(config_type="game")
self.destroy()
def close(self, widget=None):
def close(self, _widget=None):
"""Dialog destroy callback"""
self.destroy()

View file

@ -19,16 +19,17 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
import gtk
"""Container for game config options"""
import lutris.runners
import gtk
from lutris.runners import import_runner
from lutris.gui.configvbox import ConfigVBox
from lutris.runners import import_runner
# pylint: disable=R0901,R0904
class GameConfigVBox(ConfigVBox):
"""VBox for game options"""
def __init__(self, lutris_config, caller):
ConfigVBox.__init__(self, "game", caller)
self.lutris_config = lutris_config

View file

@ -19,11 +19,14 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
"""This is going away"""
import gtk
from lutris.runners import import_runner
from lutris.gui.configvbox import ConfigVBox
# pylint: disable=R0901,R0904
class InstallerConfigVBox(ConfigVBox):
"""This file is going to disapear anytime now."""
def __init__(self, lutris_config, caller):

View file

@ -19,6 +19,11 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
"""Dialog for game installer, probably shouldn't be here
NEEDS REVIEW
"""
import gtk
import logging
import subprocess
@ -32,6 +37,7 @@ from lutris.gui.systemconfigvbox import SystemConfigVBox
class InstallerDialog(gtk.Dialog):
"""Installer dialog class"""
def __init__(self, parent):
gtk.Dialog.__init__(self)
self.parent_window = parent
@ -58,14 +64,14 @@ class InstallerDialog(gtk.Dialog):
if hasattr(runner, "description"):
description = runner.description
else:
logging.debug("Please fix %s and add a description attribute"\
% runner_classname)
logging.debug("Please fix %s and add a description attribute",
runner_classname)
description = ""
if hasattr(runner, "machine"):
machine = runner.machine
else:
logging.debug("Please fix % and add a machine attribute"\
% runner_classname)
logging.debug("Please fix %s and add a machine attribute",
runner_classname)
machine = ""
if runner.is_installed() and runner.is_installable:
runner_liststore.append((machine + " (" + description + ")",
@ -145,6 +151,7 @@ class InstallerDialog(gtk.Dialog):
self.destroy()
def on_runner_changed(self, widget):
"""action called on runner changed"""
selected_runner = widget.get_active()
scroll_windows_children = [self.installer_scroll_window.get_children(),
self.runner_scroll_window.get_children(),
@ -176,7 +183,7 @@ class InstallerDialog(gtk.Dialog):
self.system_scroll_window.add_with_viewport(self.system_config_vbox)
self.system_scroll_window.show_all()
def close(self, widget=None, other=None):
def close(self, _widget=None, _other=None):
self.destroy()
def no_runner_selected(self):

View file

@ -106,8 +106,7 @@ class RunnersDialog(gtk.Dialog):
for runner in runner_list:
# Get runner details
runner_class = import_runner(runner)
runner_instance = runner_class()
runner_instance = import_runner(runner)
machine = runner_instance.machine
description = runner_instance.description

View file

@ -36,7 +36,7 @@ from lutris.gui.common import ErrorDialog, DirectoryDialog
from lutris.gui.widgets import DownloadProgressBox
from lutris.shortcuts import create_launcher
from lutris.settings import CONFIG_DIR, CACHE_DIR, DATA_DIR
from lutris.constants import INSTALLER_URL, GAME_CONFIG_PATH
from lutris.constants import INSTALLER_URL
def unzip(filename, dest=None):
@ -83,21 +83,24 @@ def reporthook(piece, received_bytes, total_size):
print "%d %%" % ((piece * received_bytes) * 100 / total_size)
# pylint: disable=R0904
class Installer(gtk.Dialog):
""" Installer class """
"""Installer class"""
def __init__(self, game, installer=False):
super(Installer, self).__init__()
self.lutris_config = None # Internal game config
if not game:
msg = "No game specified in this installer"
log.logger.error(msg)
ErrorDialog(msg)
return False
return
self.game_name = game # Name of the game
self.game_slug = slugify(self.game_name)
self.description = False
default_path = join(os.path.expanduser('~'), self.game_slug)
log.logger.debug("default path set to %s " % default_path)
self.game_dir = default_path
self.download_index = 0
self.rules = {} # Content of yaml file
self.actions = []
self.errors = []
@ -109,7 +112,6 @@ class Installer(gtk.Dialog):
self.installer_path = join(CACHE_DIR, self.game_name + ".yml")
else:
self.installer_path = installer
self.location_button = gtk.FileChooserButton("Select folder")
# FIXME: Wrong ! The runner should be loaded first in order to
@ -241,7 +243,7 @@ class Installer(gtk.Dialog):
if os.path.exists(self.game_dir):
self.install_button.set_sensitive(True)
def download_game_files(self, widget=None, data=None):
def download_game_files(self, _widget=None, _data=None):
""" Runs the actions to complete the install. """
dest_dir = join(CACHE_DIR, "installer/%s" % self.game_slug)
@ -252,13 +254,12 @@ class Installer(gtk.Dialog):
key, url = fileinfo.items()[0]
filename = os.path.basename(url)
self.gamefiles[key] = os.path.join(dest_dir, filename)
dest_file = os.path.join(dest_dir, filename)
self.location_button.destroy()
self.install_button.set_sensitive(False)
self.download_index = 0
self.process_downloads()
def process_downloads(self):
"""Download each file needed for the game"""
if self.download_index < len(self.rules["files"]):
log.logger.info(
"Downloading file %d of %d" % (self.download_index + 1,
@ -270,7 +271,7 @@ class Installer(gtk.Dialog):
log.logger.debug("All files downloaded")
self.install()
def download_complete(self, widget, data):
def download_complete(self, _widget, _data):
"""Action called on a completed download"""
self.download_index += 1
self.process_downloads()
@ -299,6 +300,7 @@ class Installer(gtk.Dialog):
self._download(url, filename, copyfile)
def install(self):
"""Actual game installation"""
log.logger.debug("Running installation")
if self.download_progress is not None:
@ -516,7 +518,7 @@ class Installer(gtk.Dialog):
os.popen('chmod +x %s' % exec_path)
subprocess.call([exec_path])
def launch_game(self, widget, data=None):
def launch_game(self, _widget, _data=None):
"""Launch a game after it's been installed"""
lutris_game = LutrisGame(self.game_slug)
lutris_game.play()

View file

@ -14,4 +14,8 @@ def import_runner(runner_name, config=None):
logger.error("Invalid runner %s" % runner)
logger.error(msg)
return runner_cls(config)
try:
instance = runner_cls(config)
except:
print runner_name
return instance

View file

@ -33,7 +33,7 @@ class dolphin(Runner):
Download link : http://dolphin.jcf129.com/dolphin-2.0.i686.tar.bz2
ppa : ppa:glennric/dolphin-emu
"""
def __init__(self):
def __init__(self, config):
""" class initialization """
super(dolphin, self).__init__()
self.package = "dolphin-emu"

View file

@ -34,8 +34,6 @@ class hatari(Runner):
self.package = "hatari"
self.executable = "hatari"
self.machine = "Atari ST computers"
self.is_installable = True
self.description = "AtariST emulator."
self.settings = settings
self.game_options = [
{"option": "disk-a", "type":"single", "label": "Floppy Disk A"},
@ -125,15 +123,14 @@ class hatari(Runner):
}
else:
return {'error': 'NO_BIOS'}
self.error_messages = self.error_messages + ["TOS path not set."]
if "disk-a" in game_settings:
self.diska = game_settings['disk-a']
self.arguments = self.arguments + ["--disk-a \"%s\"" % self.diska]
diska = game_settings['disk-a']
self.arguments = self.arguments + ["--disk-a \"%s\"" % diska]
if not self.is_installed():
return {'error': 'RUNNER_NOT_INSTALLED',
'runner': self.__class__.__name__}
if not os.path.exists(self.diska):
return {'error': 'FILE_NOT_FOUND', 'file': self.diska}
if not os.path.exists(diska):
return {'error': 'FILE_NOT_FOUND', 'file': diska}
command = [self.executable] + self.arguments
return {"command": command}

View file

@ -19,46 +19,59 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
'''Runner for intellivision games'''
from lutris.runners.runner import Runner
import os.path
# pylint: disable=C0103
class jzintv(Runner):
'''Runner for intellivision games'''
"""Intellivision Emulator"""
def __init__(self,settings = None):
def __init__(self, settings=None):
'''Constructor'''
super(jzintv, self).__init__()
self.package = "jzintv"
self.executable = "jzintv"
self.machine = "Intellivision"
#jzintv is not yet available as a package in Debian and Ubuntu,
#it requires some packaging
self.is_installable = False
self.description = "Intellivision Emulator"
self.game_options = [{"option":"rom","type":"single","label":"Rom File"}]
self.runner_options = [{"option": "bios_path", "type":"directory_chooser", "label":"Bios Path"},
{"option": "fullscreen", "type":"bool", "label":"Fullscreen"},
]
self.game_options = [{
"option":"rom",
"type":"single",
"label":"Rom File"
}]
self.runner_options = [
{
"option": "bios_path",
"type": "directory_chooser",
"label": "Bios Path"
},
{
"option": "fullscreen",
"type": "bool",
"label":"Fullscreen"
}
]
self.arguments = []
if settings:
if "fullscreen" in settings["jzintv"]:
if settings["jzintv"]["fullscreen"]:
self.arguments = self.arguments + ["-f"]
if "bios_path" in settings["jzintv"]:
self.arguments = self.arguments + ["--execimg=\"%s/exec.bin\"" % settings["jzintv"]["bios_path"] ]
self.arguments = self.arguments + ["--gromimg=\"%s/grom.bin\"" % settings["jzintv"]["bios_path"] ]
self.arguments += ["--execimg=\"%s/exec.bin\"" % \
settings["jzintv"]["bios_path"]]
self.arguments += ["--gromimg=\"%s/grom.bin\"" % \
settings["jzintv"]["bios_path"]]
else:
self.error_message = "Bios path not set"
romdir = os.path.dirname(settings["game"]["rom"])
romfile = os.path.basename(settings["game"]["rom"])
self.arguments = self.arguments + ["--rom-path=\"%s\"" % romdir+"/"]
self.arguments = self.arguments + ["\""+romfile+"\""]
self.arguments += ["--rom-path=\"%s/\"" % romdir]
self.arguments += ["\"%s\"" % romfile]
def play(self):
command = [self.executable] + self.arguments
return command

View file

@ -1,5 +1,3 @@
import logging
import os.path
# -*- coding:Utf-8 -*-
###############################################################################
## Lutris
@ -21,42 +19,60 @@ import os.path
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Linux runner """
import os
import stat
import os.path
import logging
from lutris.runners.runner import Runner
# pylint: disable=C0103
class linux(Runner):
def __init__(self,settings=None):
self.description = "Runs native games"
"""Runs native games"""
def __init__(self, config=None):
super(linux, self).__init__()
self.machine = "Linux games"
self.is_installable = True
self.ld_preload = None
self.installer_options = [{"option": "installer","type": "single","label": "Executable"}]
self.game_options = [ {"option": "exe", "type":"single", "label":"Executable"},
{"option": "args", "type": "string", "label": "Arguments"},
{"option": "ld_preload", "type": "single", "label": "Preload library"}]
self.game_path = None
self.installer_options = [{
"option": "installer",
"type": "single",
"label": "Executable"
}]
self.game_options = [
{
"option": "exe",
"type":"single",
"label":"Executable"
},
{
"option": "args",
"type": "string",
"label": "Arguments"
},
{
"option": "ld_preload",
"type": "single",
"label": "Preload library"
}
]
self.runner_options = []
if settings:
self.executable = settings["game"]["exe"]
if 'args' in settings['game']:
self.args = settings['game']['args']
else:
self.args = None
if 'ld_preload' in settings['game']:
self.ld_preload = settings['game']['ld_preload']
self.config = config
def get_install_command(self,installer_path):
def get_install_command(self, installer_path):
""" Launch install script (usually .bin or .sh) """
#Check if installer exists
if not os.path.exists(installer_path):
raise IOError
#Check if script is executable and make it executable if not
if not os.access(installer_path,os.X_OK):
if not os.access(installer_path, os.X_OK):
logging.debug("%s is not executable, setting it executable")
os.chmod(installer_path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
os.chmod(installer_path,
stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
return "x-terminal-emulator -e %s" % installer_path
@ -65,15 +81,20 @@ class linux(Runner):
return True
def play(self):
self.game_path = os.path.dirname(self.executable)
if not os.path.exists(self.executable):
return {'error': 'FILE_NOT_FOUND', 'file': self.executable }
executable = self.config["game"]["exe"]
if 'args' in self.config['game']:
args = self.config['game']['args']
else:
args = ""
if 'ld_preload' in self.config['game']:
self.ld_preload = self.config['game']['ld_preload']
self.game_path = os.path.dirname(executable)
if not os.path.exists(executable):
return {'error': 'FILE_NOT_FOUND', 'file': executable}
command = []
if self.ld_preload:
command.append("LD_PRELOAD=%s " % self.ld_preload)
command.append("./%s" % os.path.basename(self.executable))
if self.args:
for arg in self.args.split():
command.append(arg)
return {'command': command }
command.append("./%s" % os.path.basename(executable))
for arg in args.split():
command.append(arg)
return {'command': command}

View file

@ -19,6 +19,8 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Runner for multi-consoles (8bit mainly) """
import os
import subprocess
@ -29,14 +31,14 @@ from lutris.util.log import logger
# pylint: disable=C0103
class mednafen(Runner):
"""Use Mednafen"""
def __init__(self, settings=None):
super(mednafen, self).__init__()
self.executable = "mednafen"
self.is_installable = True
self.machine = """
Atari Lynx, Game Boy (Color), GameBoy Advance, NES,
PC Engine(TurboGrafx 16), SuperGrafx, Neo Geo Pocket (Color),
PC-FX, and WonderSwan (Color)"""
self.description = """Use Mednafen"""
self.package = "mednafen"
machine_choices = [("NES", "nes"),
("PC Engine", "pce"),
@ -60,19 +62,11 @@ class mednafen(Runner):
"type": "bool",
"label": "Fullscreen"
}]
if settings:
self.rom = settings["game"]["rom"]
self.machine = settings["game"]["machine"]
#Defaults
self.fullscreen = "1"
if "mednafen" in settings.config:
if "fs" in settings.config["mednafen"]:
if not settings.config["mednafen"]["fs"]:
self.fullscreen = "0"
self.settings = settings
def find_joysticks(self):
""" Detect connected joysticks and return their ids """
joy_ids = []
if not self.is_installed:
return False
output = subprocess.Popen(["mednafen", "dummy"],
@ -92,87 +86,89 @@ class mednafen(Runner):
index = joy.find("Unique ID:")
joy_id = joy[index + 11:]
logger.debug('Joystick found id %s ' % joy_id)
self.joy_ids.append(joy_id)
joy_ids.append(joy_id)
return joy_ids
def set_joystick_controls(self):
def set_joystick_controls(self, joy_ids):
""" Setup joystick mappings per machine """
nes_controls = [
"-nes.input.port1.gamepad.a",
"\"joystick " + self.joy_ids[0] + " 00000001\"",
"\"joystick " + joy_ids[0] + " 00000001\"",
"-nes.input.port1.gamepad.b",
"\"joystick " + self.joy_ids[0] + " 00000002\"",
"\"joystick " + joy_ids[0] + " 00000002\"",
"-nes.input.port1.gamepad.start",
"\"joystick " + self.joy_ids[0] + " 00000009\"",
"\"joystick " + joy_ids[0] + " 00000009\"",
"-nes.input.port1.gamepad.select",
"\"joystick " + self.joy_ids[0] + " 00000008\"",
"\"joystick " + joy_ids[0] + " 00000008\"",
"-nes.input.port1.gamepad.up",
"\"joystick " + self.joy_ids[0] + " 0000c001\"",
"\"joystick " + joy_ids[0] + " 0000c001\"",
"-nes.input.port1.gamepad.down",
"\"joystick " + self.joy_ids[0] + " 00008001\"",
"\"joystick " + joy_ids[0] + " 00008001\"",
"-nes.input.port1.gamepad.left",
"\"joystick " + self.joy_ids[0] + " 0000c000\"",
"\"joystick " + joy_ids[0] + " 0000c000\"",
"-nes.input.port1.gamepad.right",
"\"joystick " + self.joy_ids[0] + " 00008000\""
"\"joystick " + joy_ids[0] + " 00008000\""
]
gba_controls = [
"-gba.input.builtin.gamepad.a",
"\"joystick " + self.joy_ids[0] + " 00000001\"",
"\"joystick " + joy_ids[0] + " 00000001\"",
"-gba.input.builtin.gamepad.b",
"\"joystick " + self.joy_ids[0] + " 00000002\"",
"\"joystick " + joy_ids[0] + " 00000002\"",
"-gba.input.builtin.gamepad.shoulder_r",
"\"joystick " + self.joy_ids[0] + " 00000007\"",
"\"joystick " + joy_ids[0] + " 00000007\"",
"-gba.input.builtin.gamepad.shoulder_l",
"\"joystick " + self.joy_ids[0] + " 00000006\"",
"\"joystick " + joy_ids[0] + " 00000006\"",
"-gba.input.builtin.gamepad.start",
"\"joystick " + self.joy_ids[0] + " 00000009\"",
"\"joystick " + joy_ids[0] + " 00000009\"",
"-gba.input.builtin.gamepad.select",
"\"joystick " + self.joy_ids[0] + " 00000008\"",
"\"joystick " + joy_ids[0] + " 00000008\"",
"-gba.input.builtin.gamepad.up",
"\"joystick " + self.joy_ids[0] + " 0000c001\"",
"\"joystick " + joy_ids[0] + " 0000c001\"",
"-gba.input.builtin.gamepad.down",
"\"joystick " + self.joy_ids[0] + " 00008001\"",
"\"joystick " + joy_ids[0] + " 00008001\"",
"-gba.input.builtin.gamepad.left",
"\"joystick " + self.joy_ids[0] + " 0000c000\"",
"\"joystick " + joy_ids[0] + " 0000c000\"",
"-gba.input.builtin.gamepad.right",
"\"joystick " + self.joy_ids[0] + " 00008000\""
"\"joystick " + joy_ids[0] + " 00008000\""
]
gb_controls = [
"-gb.input.builtin.gamepad.a",
"\"joystick " + self.joy_ids[0] + " 00000001\"",
"\"joystick " + joy_ids[0] + " 00000001\"",
"-gb.input.builtin.gamepad.b",
"\"joystick " + self.joy_ids[0] + " 00000002\"",
"\"joystick " + joy_ids[0] + " 00000002\"",
"-gb.input.builtin.gamepad.start",
"\"joystick " + self.joy_ids[0] + " 00000009\"",
"\"joystick " + joy_ids[0] + " 00000009\"",
"-gb.input.builtin.gamepad.select",
"\"joystick " + self.joy_ids[0] + " 00000008\"",
"\"joystick " + joy_ids[0] + " 00000008\"",
"-gb.input.builtin.gamepad.up",
"\"joystick " + self.joy_ids[0] + " 0000c001\"",
"\"joystick " + joy_ids[0] + " 0000c001\"",
"-gb.input.builtin.gamepad.down",
"\"joystick " + self.joy_ids[0] + " 00008001\"",
"\"joystick " + joy_ids[0] + " 00008001\"",
"-gb.input.builtin.gamepad.left",
"\"joystick " + self.joy_ids[0] + " 0000c000\"",
"\"joystick " + joy_ids[0] + " 0000c000\"",
"-gb.input.builtin.gamepad.right",
"\"joystick " + self.joy_ids[0] + " 00008000\""
"\"joystick " + joy_ids[0] + " 00008000\""
]
pce_controls = [
"-pce.input.port1.gamepad.i",
"\"joystick " + self.joy_ids[0] + " 00000001\"",
"\"joystick " + joy_ids[0] + " 00000001\"",
"-pce.input.port1.gamepad.ii",
"\"joystick " + self.joy_ids[0] + " 00000002\"",
"\"joystick " + joy_ids[0] + " 00000002\"",
"-pce.input.port1.gamepad.run",
"\"joystick " + self.joy_ids[0] + " 00000009\"",
"\"joystick " + joy_ids[0] + " 00000009\"",
"-pce.input.port1.gamepad.select",
"\"joystick " + self.joy_ids[0] + " 00000008\"",
"\"joystick " + joy_ids[0] + " 00000008\"",
"-pce.input.port1.gamepad.up",
"\"joystick " + self.joy_ids[0] + " 0000c001\"",
"\"joystick " + joy_ids[0] + " 0000c001\"",
"-pce.input.port1.gamepad.down",
"\"joystick " + self.joy_ids[0] + " 00008001\"",
"\"joystick " + joy_ids[0] + " 00008001\"",
"-pce.input.port1.gamepad.left",
"\"joystick " + self.joy_ids[0] + " 0000c000\"",
"\"joystick " + joy_ids[0] + " 0000c000\"",
"-pce.input.port1.gamepad.right",
"\"joystick " + self.joy_ids[0] + " 00008000\""
"\"joystick " + joy_ids[0] + " 00008000\""
]
if self.machine == "pce":
@ -185,25 +181,34 @@ class mednafen(Runner):
controls = gb_controls
else:
controls = []
for control in controls:
self.options.append(control)
return controls
def play(self):
"""Runs the game"""
rom = self.settings["game"]["rom"]
machine = self.settings["game"]["machine"]
#Defaults
fullscreen = "1"
if "mednafen" in self.settings.config:
if "fs" in self.settings.config["mednafen"]:
if not self.settings.config["mednafen"]["fs"]:
fullscreen = "0"
resolution = get_current_resolution()
(resolutionx, resolutiony) = resolution.split("x")
xres = str(resolutionx)
yres = str(resolutiony)
self.options = ["-fs", self.fullscreen,
"-" + self.machine + ".xres", xres,
"-" + self.machine + ".yres", yres,
"-" + self.machine + ".stretch", "1",
"-" + self.machine + ".special", "hq4x",
"-" + self.machine + ".videoip", "1"]
self.joy_ids = []
self.find_joysticks()
if len(self.joy_ids) > 0:
self.set_joystick_controls()
options = ["-fs", fullscreen,
"-" + machine + ".xres", xres,
"-" + machine + ".yres", yres,
"-" + machine + ".stretch", "1",
"-" + machine + ".special", "hq4x",
"-" + machine + ".videoip", "1"]
joy_ids = self.find_joysticks()
if len(joy_ids) > 0:
controls = self.set_joystick_controls(joy_ids)
for control in controls:
options.append(control)
else:
logger.debug("No Joystick found")
@ -211,11 +216,11 @@ class mednafen(Runner):
return {'error': 'RUNNER_NOT_INSTALLED',
'runner': self.__class__.__name__}
if not os.path.exists(self.rom):
return {'error': 'FILE_NOT_FOUND', 'file': self.rom}
if not os.path.exists(rom):
return {'error': 'FILE_NOT_FOUND', 'file': rom}
command = [self.executable]
for option in self.options:
for option in options:
command.append(option)
command.append("\"" + self.rom + "\"")
command.append("\"" + rom + "\"")
return {'command': command}

View file

@ -19,13 +19,15 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Runner for Nintendo64 """
from lutris.runners.runner import Runner
import os.path
# pylint: disable=C0103
class mupen64plus(Runner):
'''Runner for Sega Genesis games'''
"""Nintendo 64 emulator"""
def __init__(self, settings=None):
super(mupen64plus, self).__init__()
@ -33,9 +35,6 @@ class mupen64plus(Runner):
self.executable = 'mupen64plus'
self.machine = "Nintendo 64"
self.arguments = ['--nogui']
self.is_installable = True
self.description = "Nintendo 64 emulator"
self.game_options = [{
'option': 'rom',
'type':'single',

View file

@ -44,8 +44,6 @@ class nulldc(wine):
def __init__(self, settings=None):
"""Initialize NullDC
TODO: Remove hardcoded stuff
joy2key $(xwininfo -root -tree | grep nullDC | grep -v VMU |\
awk '{print $1}') \
-X -rcfile ~/.joy2keyrc \
@ -61,8 +59,6 @@ class nulldc(wine):
config = LutrisConfig(runner=self.__class__.__name__)
self.nulldc_path = config.get_path()
self.executable = "nullDC_1.0.3_nommu.exe"
self.gamePath = "/mnt/seagate/games/Soul Calibur [NTSC-U]/"
self.gameIso = "disc.gdi"
self.args = ""
self.game_options = [{
'option': 'iso',

View file

@ -1,4 +1,3 @@
# -*- coding:Utf-8 -*-
###############################################################################
## Lutris
@ -20,33 +19,73 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Runner for Odyssey2 games """
from lutris.runners.runner import Runner
import os.path
# pylint: disable=C0103
class o2em(Runner):
'''Runner for Odyssey² games'''
"""Magnavox Oyssey² Emulator"""
def __init__(self,settings = None):
def __init__(self, settings=None):
'''Constructor'''
super(o2em, self).__init__()
self.package = "o2em"
self.executable = "o2em"
self.machine = "Odyssey 2"
#o2em is not yet available as a package in Debian and Ubuntu,
#it requires some packaging
self.is_installable = False
self.bios_path = os.path.join(os.path.expanduser("~"),".o2em/bios/")
self.bios_path = os.path.join(os.path.expanduser("~"), ".o2em/bios/")
self.description = "Magnavox Oyssey² Emulator"
bios_choices = [("Odyssey² bios","o2rom"),("French odyssey² Bios","c52"),("VP+ Bios","g7400"),("French VP+ Bios","jopac")]
controller_choices = [("Disable","0"),("Arrows keys and right shift","1"),("W,S,A,D,SPACE","2"),("Joystick","3")]
self.game_options = [{"option":"rom","type":"single","label":"Rom File"}]
self.runner_options = [{"option": "bios", "type":"one_choice", "choices":bios_choices,"label":"Bios"},
{"option": "first_controller", "type":"one_choice","choices":controller_choices,"label":"First controller"},
{"option": "second_controller", "type":"one_choice", "choices":controller_choices,"label":"Second controller"},
{"option": "fullscreen", "type":"bool", "label":"Fullscreen"},
{"option": "scanlines", "type":"bool", "label":"Scanlines"}]
bios_choices = [
("Odyssey² bios", "o2rom"),
("French odyssey² Bios", "c52"),
("VP+ Bios", "g7400"),
("French VP+ Bios", "jopac")
]
controller_choices = [
("Disable", "0"),
("Arrows keys and right shift", "1"),
("W,S,A,D,SPACE", "2"),
("Joystick", "3")
]
self.game_options = [{
"option": "rom",
"type": "single",
"label": "Rom File"
}]
self.runner_options = [
{
"option": "bios",
"type": "one_choice",
"choices":bios_choices,
"label":"Bios"
},
{
"option": "first_controller",
"type": "one_choice",
"choices": controller_choices,
"label":"First controller"
},
{
"option": "second_controller",
"type": "one_choice",
"choices": controller_choices,
"label": "Second controller"
},
{
"option": "fullscreen",
"type": "bool",
"label": "Fullscreen"
},
{
"option": "scanlines",
"type": "bool",
"label": "Scanlines"
}
]
self.arguments = ["-biosdir=\"%s\"" % self.bios_path]
if settings:
@ -57,16 +96,16 @@ class o2em(Runner):
if settings["o2em"]["scanlines"]:
self.arguments = self.arguments + ["-scanlines"]
if "first_controller" in settings["o2em"]:
self.arguments = self.arguments + ["-s1=%s" % settings["o2em"]["first_controller"]]
self.arguments += ["-s1=%s" % \
settings["o2em"]["first_controller"]]
if "second_controller" in settings["o2em"]:
self.arguments = self.arguments + ["-s2=%s" % settings["o2em"]["second_controller"]]
self.arguments += ["-s2=%s" % \
settings["o2em"]["second_controller"]]
romdir = os.path.dirname(settings["game"]["rom"])
romfile = os.path.basename(settings["game"]["rom"])
self.arguments = self.arguments + ["-romdir=\"%s\"" % romdir+"/"]
self.arguments = self.arguments + ["\""+romfile+"\""]
self.arguments = self.arguments + ["-romdir=\"%s\"/" % romdir]
self.arguments = self.arguments + ["\"%s\"" % romfile]
def play(self):
command = [self.executable] + self.arguments
return command

View file

@ -19,6 +19,8 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Runner for MSX games """
from lutris.runners.runner import Runner
@ -27,6 +29,7 @@ class openmsx(Runner):
'''Runner for MSX games'''
def __init__(self, settings=None):
'''Constructor'''
super(openmsx, self).__init__()
self.package = "openmsx"
self.executable = "openmsx"
self.machine = "MSX"

View file

@ -19,24 +19,24 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
"""Runner for Sega Master System"""
import os
from lutris.runners.runner import Runner
# pylint: disable=C0103
class osmose(Runner):
'''Runner for Sega Master System games'''
"""Sega Master System Emulator"""
def __init__(self, settings=None):
'''Constructor'''
super(osmose, self).__init__()
self.package = "osmose"
self.executable = "osmose"
self.machine = "Sega Master System"
#osmose is not yet available as a package in Debian and Ubuntu,
#it requires some packaging
self.is_installable = False
self.description = "Sega Master System Emulator"
self.game_options = [{
'option': 'rom',
'type': 'single',
@ -46,26 +46,24 @@ class osmose(Runner):
{'option': 'fullscreen', 'type': 'bool', 'label': 'Fullscreen'},
{'option': 'joy', 'type': 'bool', 'label': 'Use joystick'}
]
self.arguments = []
if settings:
self.settings = settings
self.settings = settings
def play(self):
arguments = []
if 'fullscreen' in self.settings['osmose']:
if self.settings['osmose']['fullscreen']:
self.arguments = self.arguments + ['-fs', '-bilinear']
arguments = arguments + ['-fs', '-bilinear']
if 'joy' in self.settings["osmose"]:
if self.settings['osmose']['joy']:
self.arguments = self.arguments + ['-joy']
arguments = arguments + ['-joy']
self.rom = self.settings['game']['rom']
self.arguments = self.arguments + ["\"" + self.rom + "\""]
rom = self.settings['game']['rom']
arguments = arguments + ["\"" + rom + "\""]
if not self.is_installed():
return {'error': 'RUNNER_NOT_INSTALLED',
'runner': self.__class__.__name__}
if not os.path.exists(self.rom):
if not os.path.exists(rom):
return {'error': 'FILE_NOT_FOUND',
'file': self.rom}
return {'command': [self.executable] + self.arguments}
'file': rom}
return {'command': [self.executable] + arguments}

View file

@ -25,7 +25,7 @@ from lutris.runners.runner import Runner
#pylint: disable=C0103
class pcsx(Runner):
""" Runner class for playstation games """
"""PlayStation emulator"""
def __init__(self, settings=None):
"""
pcsx-df is what seems the best candidate for a playstation emulator.
@ -35,10 +35,9 @@ class pcsx(Runner):
The package also lacks a maintainer :
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=510530
"""
super(pcsx, self).__init__()
self.executable = "pcsx"
self.package = "pcsx-df"
self.is_installable = False
self.description = "Runs PlayStation games"
self.machine = "Playstation"
self.game_options = [{"option":"iso", "type":"single", "label":"iso"}]
self.runner_options = []

View file

@ -19,18 +19,21 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Generic runner """
import subprocess
import platform
import hashlib
import logging
from lutris.config import LutrisConfig
from lutris.gui.common import ErrorDialog
from lutris.util.log import logger
# Pylint, are you from the past ?
# pylint: disable=R0921
class Runner(object):
"""Generic runner (base class for other runners) """
def __init__(self):
""" Initialize runner """
self.executable = None
@ -40,17 +43,29 @@ class Runner(object):
self.game = None
self.depends = None
@property
def description(self):
"""Return the class' docstring as the description"""
return self.__doc__
# pylint: disable=E0102,E1101,W0201
@description.setter
def description(self, value):
"""Leave the ability to override the docstring"""
self.__doc__ = value
def load(self, game):
""" Load a game """
self.game = game
def play(self):
pass
"""dummy method, must be implemented by derived runnners"""
raise NotImplementedError("Implement the play method in your runner")
def check_depends(self):
"""Check if all the dependencies for a runner are installed."""
if not self.depends:
return true
return True
classname = "lutris.runners." + self.depends
parts = classname.split('.')
@ -80,13 +95,19 @@ class Runner(object):
is_installed = True
return is_installed
# pylint: disable=R0201
def get_game_options(self):
return None
"""Not even sure that's used (well, let's see)"""
raise DeprecationWarning("WTF is this shit ?")
# pylint: disable=R0201
def get_runner_options(self):
return None
"""Not even sure that's used (well, let's see)"""
raise DeprecationWarning("WTF is this shit ?")
def get_game_path(self):
"""Seems suspicious, but still useful"""
logger.warning("get_game_path called, I'm 12 and what is this ?")
if hasattr(self, 'game_path'):
path = self.game_path
else:
@ -94,6 +115,8 @@ class Runner(object):
return path
def md5sum(self, filename):
"""checks the md5sum of a file, does not belong here"""
logger.warning("please remove md5sum from Runner")
md5check = hashlib.md5()
file_ = open(filename, "rb")
content = file_.readlines()
@ -122,19 +145,16 @@ class Runner(object):
package_manager = 'yum'
install_args = 'install'
else:
logging.error("The distribution you're running is not supported.")
logging.error("Edit runners/runner.py to add support for it")
logger.error("The distribution you're running is not supported.")
logger.error("Edit runners/runner.py to add support for it")
return False
stdout = subprocess.Popen("%s %s %s" % (package_manager,
install_args,
self.package),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()[0]
subprocess.Popen("%s %s %s" % (package_manager, install_args,
self.package),
shell=True, stderr=subprocess.PIPE)
return True
def write_config(self, id, name, fullpath):
def write_config(self, _id, name, fullpath):
"""Write game configuration to settings directory."""
system = self.__class__.__name__
index = fullpath.rindex("/")
@ -143,8 +163,12 @@ class Runner(object):
if path.startswith("file://"):
path = path[7:]
config = LutrisConfig()
config.config = {"main": {"path": path,
"exe": exe,
"realname": name,
"runner": system}}
config.save(id, values)
config.config = {
"main": {
"path": path,
"exe": exe,
"realname": name,
"runner": system
}
}
config.save(config_type="game")

View file

@ -18,7 +18,8 @@
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" ScummVM runner """
""" Runner for point and click adventure games. """
import os
import subprocess
@ -27,25 +28,52 @@ from lutris.runners.runner import Runner
from lutris.config import LutrisConfig
from ConfigParser import ConfigParser
SCUMMVM_CONFIG_FILE = os.path.join(os.path.expanduser("~"), ".scummvmrc")
def add_game(name, realname):
"""Add scummvm from the auto-import"""
lutris_config = LutrisConfig()
lutris_config.config = {"runner": "scummvm",
"realname": realname,
"name": name}
lutris_config.save("game")
def import_games():
"""
Parse the scummvm config file and imports
the games in Lutris config files.
"""
imported_games = []
if os.path.exists(SCUMMVM_CONFIG_FILE):
config_parser = ConfigParser()
config_parser.read(SCUMMVM_CONFIG_FILE)
config_sections = config_parser.sections()
if "scummvm" in config_sections:
config_sections.remove("scummvm")
for section in config_sections:
realname = config_parser.get(section, "description")
add_game(section, realname)
imported_games.append({'id': section,
'name': realname,
'runner': 'scummvm'})
return imported_games
# pylint: disable=C0103
class scummvm(Runner):
""" Runner for point and click adventure games. """
"""Runs LucasArts games based on the Scumm engine"""
def __init__(self, settings=None):
self.scummvm_config_file = os.path.join(os.path.expanduser("~"),
".scummvmrc")
super(scummvm, self).__init__()
self.executable = "scummvm"
self.package = "scummvm"
self.is_installable = True
self.description = "Runs LucasArts games based on the Scumm engine"
self.machine = "LucasArts point and click games"
self.gfxmode = "--gfx-mode=normal"
self.fullscreen = "-f" # -F for windowed
self.installer_options = [{'option': 'foo',
'type': "label",
'label': "Click on install to launch" \
+ "ScummVM and install the game"}]
self.game_options = []
self.installer_options = [{
'option': 'foo',
'type': "label",
'label': "Click on install to launch ScummVM and install the game"
}]
scaler_modes = [
("2x", "2x"),
("3x", "3x"),
@ -67,57 +95,35 @@ class scummvm(Runner):
"type": "one_choice",
"choices": scaler_modes}
]
self.settings = settings
def play(self):
settings = self.settings
gfxmode = "--gfx-mode=normal"
fullscreen = "-f" # -F for windowed
if isinstance(settings, LutrisConfig):
config = settings.config
if "scummvm" in config:
if "fullscreen" in config["scummvm"]:
if config["scummvm"]["fullscreen"] == False:
self.fullscreen = "-F"
fullscreen = "-F"
if "gfx-mode" in config["scummvm"]:
mode = config["scummvm"]["gfx-mode"]
self.gfxmode = "--gfx-mode=%s" % mode
self.game = settings["name"]
def play(self):
return [self.executable, self.fullscreen, self.gfxmode, self.game]
def import_games(self):
"""
Parse the scummvm config file and imports
the games in Lutris config files.
"""
imported_games = []
if os.path.exists(self.scummvm_config_file):
config_parser = ConfigParser()
config_parser.read(self.scummvm_config_file)
config_sections = config_parser.sections()
if "scummvm" in config_sections:
config_sections.remove("scummvm")
for section in config_sections:
realname = config_parser.get(section, "description")
self.add_game(section, realname)
imported_games.append({'id': section,
'name': realname,
'runner': 'scummvm'})
return imported_games
gfxmode = "--gfx-mode=%s" % mode
game = settings["name"]
return [self.executable, fullscreen, gfxmode, game]
# pylint: disable=R0201
def get_install_command(self):
command = "%s" % (self.executable)
return command
def add_game(self, name, realname):
lutris_config = LutrisConfig()
lutris_config.config = {"runner": "scummvm",
"realname": realname,
"name": name}
lutris_config.save("game")
"""WTF is this shit ?"""
raise DeprecationWarning
#command = "%s" % (self.executable)
#return command
def get_game_list(self):
""" Return the entire list of games supported by ScummVM """
scumm_output = subprocess.Popen(
[self.executable, "-z"],
["scummvm", "-z"],
stdout=subprocess.PIPE).communicate()[0]
game_list = str.split(scumm_output, "\n")
game_array = []

View file

@ -28,46 +28,44 @@ from lutris.runners.runner import Runner
# pylint: disable=C0103
class sdlmame(Runner):
""" Mame runner """
"""Runs arcade games with SDLMame"""
def __init__(self, settings=None):
""" Mame initialization """
super(sdlmame, self).__init__()
self.executable = "mame"
self.package = "sdlmame"
self.description = "Runs arcade games with SDLMame"
self.machine = "Arcade"
self.is_installable = False
self.fullscreen = True
self.game_options = [{"option": "rom",
"type":"single",
"label":"Rom file"}]
self.runner_options = [{"option":"windowed",
"type":"bool",
"label":"Windowed"}]
if settings:
self.romdir = os.path.dirname(settings["game"]["rom"])
self.rom = os.path.basename(settings["game"]["rom"])
self.mameconfigdir = os.path.join(os.path.expanduser("~"), ".mame")
if "sdlmame" in settings.config:
if "windowed" in settings["sdlmame"]:
self.fullscreen = not settings["sdlmame"]["windowed"]
self.settings = settings
def play(self):
""" Launch the game. """
if not os.path.exists(os.path.join(self.mameconfigdir, "mame.ini")):
settings = self.settings
fullscreen = True
if settings:
romdir = os.path.dirname(settings["game"]["rom"])
rom = os.path.basename(settings["game"]["rom"])
mameconfigdir = os.path.join(os.path.expanduser("~"), ".mame")
if "sdlmame" in settings.config:
if "windowed" in settings["sdlmame"]:
fullscreen = not settings["sdlmame"]["windowed"]
if not os.path.exists(os.path.join(mameconfigdir, "mame.ini")):
try:
os.makedirs(self.mameconfigdir)
os.makedirs(mameconfigdir)
except OSError:
pass
os.chdir(self.mameconfigdir)
os.chdir(mameconfigdir)
subprocess.Popen([self.executable, "-createconfig"],
stdout=subprocess.PIPE)
os.chdir(self.romdir)
arguments = []
if not self.fullscreen:
arguments = arguments + ["-window"]
return [self.executable,
"-inipath", self.mameconfigdir,
"-skip_gameinfo",
"-rompath", self.romdir, self.rom] + arguments
os.chdir(romdir)
arguments = []
if not fullscreen:
arguments = arguments + ["-window"]
return [self.executable,
"-inipath", mameconfigdir,
"-skip_gameinfo",
"-rompath", romdir, rom] + arguments

View file

@ -26,7 +26,7 @@ from lutris.runners.runner import Runner
# pylint: disable=C0103
class snes9x(Runner):
""" Uses snes9x to run SNES games """
"""Runs Super Nintendo games with Snes9x"""
def __init__(self, settings=None):
"""It seems that the best snes emulator around it snes9x-gtk
zsnes has no 64bit port
@ -34,7 +34,6 @@ class snes9x(Runner):
super(snes9x, self).__init__()
self.executable = "snes9x-gtk"
self.package = None
self.description = "Runs Super Nintendo games with Snes9x"
self.machine = "Super Nintendo"
self.is_installable = True
self.game_options = [{

View file

@ -29,33 +29,45 @@ from lutris.runners.wine import wine
from lutris.config import LutrisConfig
def get_name(steam_file):
"""Get game name from some weird steam file"""
data = steam_file.read(1000)
if "name" in data:
index_of_name = str.find(data, "name")
index = index_of_name + 5
char = "0"
name = ""
while ord(char) != 0x0:
char = data[index]
index = index + 1
name = name + char
return name[:-1]
def get_appid_from_filename(filename):
"""Get appid name from some weird steam file"""
if filename.endswith(".vdf"):
appid = filename[filename.find("_") + 1:filename.find(".")]
elif filename.endswith('.pkv'):
appid = filename[:filename.find("_")]
return appid
# pylint: disable=C0103
class steam(wine):
"""Runner for the Steam platform."""
"""Runs Steam games with Wine"""
def __init__(self, settings=None):
super(steam, self).__init__(settings)
self.executable = "Steam.exe"
self.package = None
self.description = "Runs Steam games with Wine"
self.machine = "Steam Platform"
#TODO : Put Steam Path in config file
config = LutrisConfig(runner=self.__class__.__name__)
self.game_path = config.get_path()
self.game_exe = "steam.exe"
self.arguments = []
self.depends = "wine"
self.is_installable = False
self.appid = "26800"
self.game_options = [
{'option': 'appid', 'type': 'string', 'label': 'appid'},
{'option': 'args', 'type': 'string', 'label': 'arguments'}
]
if settings:
self.appid = settings['game']['appid']
if 'args' in settings['game']:
self.args = settings['game']['args']
else:
self.args = ""
self.settings = settings
def install(self):
dlg = QuestionDialog({
@ -78,52 +90,33 @@ class steam(wine):
if not self.check_depends():
return False
if not self.game_path or \
not os.path.exists(os.path.join(self.game_path, self.game_exe)):
not os.path.exists(os.path.join(self.game_path, self.executable)):
return False
else:
return True
def get_name(self, steam_file):
data = steam_file.read(1000)
if "name" in data:
index_of_name = str.find(data, "name")
index = index_of_name + 5
char = "0"
name = ""
while ord(char) != 0x0:
char = data[index]
index = index + 1
name = name + char
return name[:-1]
def get_appid_from_filename(self, filename):
if filename.endswith(".vdf"):
appid = filename[filename.find("_") + 1:filename.find(".")]
elif filename.endswith('.pkv'):
appid = filename[:filename.find("_")]
return appid
def get_appid_list(self):
self.game_list = []
"""Return the list of appids of all user's games"""
game_list = []
os.chdir(os.path.join(self.game_path, "appcache"))
max_counter = 10010
files = []
counter = 0
for file in os.listdir("."):
for filename in os.listdir("."):
counter = counter + 1
if counter < max_counter:
files.append(file)
files.append(filename)
else:
break
steam_apps = []
for file in files:
if file.endswith(".vdf"):
test_file = open(file, "rb")
appid = self.get_appid_from_filename(file)
appname = self.get_name(test_file)
for filename in files:
if filename.endswith(".vdf"):
test_file = open(filename, "rb")
appid = get_appid_from_filename(filename)
appname = get_name(test_file)
if appname:
steam_apps.append((appid, appname, file))
steam_apps.append((appid, appname, filename))
test_file.close()
steam_apps.sort()
@ -133,10 +126,18 @@ class steam(wine):
for steam_app in steam_apps:
#steam_apps_file.write("%d\t%s\n" % (steam_app[0],steam_app[1]))
#print ("%d\t%s\n" % (steam_app[0],steam_app[1]))
self.game_list.append((steam_app[0], steam_app[1]))
game_list.append((steam_app[0], steam_app[1]))
steam_apps_file.close()
return game_list
def play(self):
settings = self.settings
if settings:
appid = settings['game']['appid']
if 'args' in settings['game']:
self.args = settings['game']['args']
else:
self.args = ""
if not self.check_depends():
return {'error': 'RUNNER_NOT_INSTALLED',
'runner': self.depends}
@ -145,10 +146,7 @@ class steam(wine):
'runner': self.__class__.__name__}
self.check_regedit_keys() # From parent wine runner
print self.game_path
print self.game_exe
steam_full_path = os.path.join(self.game_path, self.game_exe)
steam_full_path = os.path.join(self.game_path, self.executable)
command = ['wine', '"%s"' % steam_full_path,
'-applaunch', self.appid, self.args]
'-applaunch', appid, self.args]
return {'command': command}

View file

@ -20,24 +20,30 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
'''Runner for stella Atari 2600 emulator'''
from lutris.runners.runner import Runner
class stella(Runner):
'''Runner for stella Atari 2600 emulator'''
def __init__(self,settings = None):
# pylint: disable=C0103
class stella(Runner):
"""Atari 2600 games emulator"""
def __init__(self, settings=None):
'''Constructor'''
super(stella,self).__init__()
super(stella, self).__init__()
self.package = "stella"
self.executable = "stella"
self.machine = "Atari 2600"
self.description = "Run Atari 2600 games"
self.game_options = [{"option":"cart","type":"single","label":"Cartridge"}]
self.game_options = [{
"option": "cart",
"type": "single",
"label":"Cartridge"
}]
self.runner_options = []
if settings:
self.cart = settings["game"]["cart"]
def play(self):
command = ['stella',"\""+self.cart+"\""]
command = ['stella', "\"%s\"" % self.cart]
return {'command': command}

View file

@ -19,20 +19,21 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Runs Amiga games with UAE"""
import os
from lutris.runners.runner import Runner
# pylint: disable=C0103
class uae(Runner):
"""Runs Amiga games with UAE, yay"""
def __init__(self, settings=None):
super(uae, self).__init__()
self.package = "uae"
self.executable = "uae"
self.description = "Runs Amiga games with UAE"
self.machine = "Amiga"
self.uae_options = {}
self.is_installable = False
control_choices = [("Mouse", "mouse"), ("Joystick 1", "joy0"),
("Joystick 2", "joy1"), ("Keyboard 1", "kbd1"),
("Keyboard 2", "kbd2"), ("Keyboard 3", "kbd3")]
@ -174,9 +175,6 @@ class uae(Runner):
if inserted_disks == disks:
break
def get_game_options(self):
return {"file": self.file_options, "options": self.runner_options}
def play(self):
command = [self.executable]
for option in self.uae_options:

View file

@ -20,12 +20,14 @@
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
'''Runner for MSX games'''
from lutris.runners.runner import Runner
# pylint: disable=C0103
class vice(Runner):
'''Runner for MSX games'''
"""Commodore Emulator"""
def __init__(self, settings=None):
'''Constructor'''
super(vice, self).__init__()
@ -33,7 +35,6 @@ class vice(Runner):
self.executable = "x64"
self.machine = "Commodore 64"
self.arguments = []
self.description = "Commodore Emulator"
self.game_options = [{
"option": "disk",
"type": "single",

View file

@ -16,28 +16,53 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""Wine runner"""
import os
import subprocess
import logging
from os.path import exists
from lutris.runners.runner import Runner
from lutris.constants import TMP_PATH
from lutris.util.log import logger
from lutris.settings import CACHE_DIR
from lutris.runners.runner import Runner
def set_regedit(path, key, value):
"""Plays with the windows registry
path is something like HKEY_CURRENT_USER\Software\Wine\Direct3D
"""
logging.debug("Setting wine registry key : %s\\%s to %s",
path, key, value)
reg_path = os.path.join(CACHE_DIR, 'winekeys.reg')
#Make temporary reg file
reg_file = open(reg_path, "w")
reg_file.write("""REGEDIT4
[%s]
"%s"="%s"
""" % (path, key, value))
reg_file.close()
subprocess.call(["wine", "regedit", reg_path])
os.remove(reg_path)
def kill():
"""The kill command runs wineserver -k"""
os.popen("winserver -k")
# pylint: disable=C0103
class wine(Runner):
'''Run Windows games with Wine'''
def __init__(self, settings=None):
super(wine, self).__init__()
self.executable = 'wine'
self.package = 'wine'
self.machine = 'Windows games'
self.description = 'Run Windows games with Wine'
self.prefix = None
self.is_installable = True
self.installer_options = [{
'option': 'installer',
'type': 'single',
@ -109,59 +134,20 @@ class wine(Runner):
'type': 'one_choice',
'choices': desktop_choices}
]
self.settings = settings
reg_prefix = "HKEY_CURRENT_USER\Software\Wine"
self.reg_keys = {
"RenderTargetLockMode": r"%s\Direct3D" % reg_prefix,
"Audio": r"%s\Drivers" % reg_prefix,
"MouseWarpOverride": r"%s\DirectInput" % reg_prefix,
"Multisampling": r"%s\Direct3D" % reg_prefix,
"RenderTargetLockMode": r"%s\Direct3D" % reg_prefix,
"OffscreenRenderingMode": r"%s\Direct3D" % reg_prefix,
"DirectDrawRenderer": r"%s\Direct3D" % reg_prefix,
"Version": r"%s" % reg_prefix,
"Desktop": r"%s\Explorer" % reg_prefix
}
if settings:
if 'exe' in settings['game']:
self.gameExe = settings['game']['exe']
if 'args' in settings.config['game']:
self.args = settings['game']['args']
else:
self.args = None
if self.__class__.__name__ in settings.config:
logging.debug('loading wine specific settings')
self.wine_config = settings.config[self.__class__.__name__]
else:
self.wine_config = None
def set_regedit(self, path, key, value):
"""Plays with the windows registry
path is something like HKEY_CURRENT_USER\Software\Wine\Direct3D
"""
logging.debug("Setting wine registry key : %s\\%s to %s" %
(path, key, value))
reg_path = os.path.join(TMP_PATH, 'winekeys.reg')
#Make temporary reg file
reg_file = open(reg_path, "w")
reg_file.write("""REGEDIT4
[%s]
"%s"="%s"
""" % (path, key, value))
reg_file.close()
subprocess.call(["wine", "regedit", reg_path])
os.remove(reg_path)
def kill(self):
"""The kill command runs wineserver -k"""
os.popen("winserver -k")
def get_install_command(self, exe=None, iso=None):
def get_install_command(self, exe=None):
"""Return the installer command, either from an exe or an iso"""
if exe:
command = "%s %s" % (self.executable, exe)
@ -170,24 +156,35 @@ class wine(Runner):
return False
return command
def check_regedit_keys(self):
def check_regedit_keys(self, wine_config):
"""Resets regedit keys according to config"""
for key in self.reg_keys.keys():
if key in self.wine_config:
self.set_regedit(self.reg_keys[key], key,
self.wine_config[key])
if key in wine_config:
set_regedit(self.reg_keys[key], key, wine_config[key])
def play(self):
self.game_path = os.path.dirname(self.gameExe)
game_exe = os.path.basename(self.gameExe)
if not exists(self.game_path):
return {"error": "FILE_NOT_FOUND", "file": self.game_path}
settings = self.settings
if 'exe' in settings['game']:
game_exe = settings['game']['exe']
if 'args' in settings.config['game']:
arguments = settings['game']['args']
else:
arguments = None
if self.__class__.__name__ in settings.config:
logging.debug('loading wine specific settings')
wine_config = settings.config[self.__class__.__name__]
game_path = os.path.dirname(game_exe)
game_exe = os.path.basename(game_exe)
if not exists(game_path):
return {"error": "FILE_NOT_FOUND", "file": game_path}
command = []
if self.prefix and exists(self.prefix):
command.append("WINEPREFIX=%s ", self.prefix)
if "prefix" in wine_config and exists(wine_config['prefix']):
logger.debug("using WINEPREFIX %s", wine_config["prefix"])
command.append("WINEPREFIX=%s ", wine_config['prefix'])
command.append(self.executable)
command.append("\"" + game_exe + "\"")
if self.args:
for arg in self.args.split():
if arguments:
for arg in arguments.split():
command.append(arg)
self.check_regedit_keys()
self.check_regedit_keys(wine_config)
return {'command': command}

View file

@ -2,8 +2,30 @@
from os.path import join
from xdg import BaseDirectory
PROJECT = "Lutris"
VERSION = "0.2.7"
WEBSITE = "http://lutris.net"
COPYRIGHT = "(c) 2010 Lutris Gaming Platform"
AUTHORS = ["Mathieu Comandon <strycore@gmail.com>"]
ARTISTS = ["Ludovic Soulié <contact@yudoh.com>"]
CONFIG_DIR = join(BaseDirectory.xdg_config_home, 'lutris')
DATA_DIR = join(BaseDirectory.xdg_data_home, 'lutris')
CACHE_DIR = join(BaseDirectory.xdg_cache_home, 'lutris')
PGA_DB = join(DATA_DIR, 'pga.db')
LICENSE_TEXT = """
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

View file

@ -7,7 +7,7 @@ from xdg import BaseDirectory
from subprocess import Popen, PIPE
from lutris.config import LutrisConfig
from lutris.settings import CACHE_DIR, DATA_DIR
from lutris.settings import CACHE_DIR, DATA_DIR
def create_launcher(game, desktop=False, menu=False):

View file

@ -49,6 +49,7 @@ class LutrisThread(threading.Thread):
self.killswitch = killswitch
def attach_thread(self, thread):
"""Attach child process that need to be killed on game exit"""
self.child_processes.append(thread)
def run(self):

View file

@ -1,8 +1,6 @@
"""Surprise!"""
import xdg
from xdg.Menu import xdg_config_dirs
from xdg.Menu import Menu
CACHE = xdg.Menu.parse("/etc/xdg/menus/applications.menu")
print CACHE
for entry in CACHE.getEntries():