mirror of
https://github.com/lutris/lutris
synced 2024-10-07 08:19:07 +00:00
somewhat heavy refactoring
This commit is contained in:
parent
968304b986
commit
18204cee27
|
@ -32,8 +32,7 @@ from lutris.installer import Installer
|
|||
from lutris.config import check_config
|
||||
from lutris.gui.lutriswindow import LutrisWindow
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
log.logger.name = "Lutris Gaming Platform"
|
||||
log.logger.name = "Lutris"
|
||||
|
||||
def new_lutris_window():
|
||||
""" Returns an instantiated LutrisWindow object. """
|
||||
|
@ -48,7 +47,6 @@ def new_lutris_window():
|
|||
window.finish_initializing(builder, DATA_PATH)
|
||||
return window
|
||||
|
||||
check_config()
|
||||
|
||||
# Support for command line options.
|
||||
parser = optparse.OptionParser(version="%prog %ver")
|
||||
|
@ -70,6 +68,7 @@ if options.debug:
|
|||
else:
|
||||
log.logger.setLevel(log.logging.INFO)
|
||||
if options.verbose:
|
||||
log.logger.info("Verbose mode enabled")
|
||||
console = log.logging.StreamHandler()
|
||||
if options.debug:
|
||||
console.setLevel(log.logging.DEBUG)
|
||||
|
@ -81,6 +80,8 @@ if options.verbose:
|
|||
console.setFormatter(formatter)
|
||||
log.logger.addHandler(console)
|
||||
|
||||
check_config(force_wipe=True)
|
||||
|
||||
installer = False
|
||||
game = None
|
||||
if options.installer_file:
|
||||
|
|
|
@ -24,29 +24,49 @@ from os.path import join
|
|||
|
||||
import lutris.pga as pga
|
||||
import lutris.constants as constants
|
||||
from lutris.settings import PGA_PATH
|
||||
from lutris.constants import CONFIG_EXTENSION, GAME_CONFIG_PATH
|
||||
|
||||
from lutris.util import log
|
||||
from lutris.gconfwrapper import GconfWrapper
|
||||
from lutris.settings import PGA_DB, CONFIG_DIR, DATA_DIR, CACHE_DIR
|
||||
from lutris.constants import GAME_CONFIG_PATH
|
||||
|
||||
|
||||
def check_config():
|
||||
"""Check if configuration directories exists and create them if needed.
|
||||
def register_handler():
|
||||
gconf = GconfWrapper()
|
||||
defaults = (('/desktop/gnome/url-handlers/lutris/command', "lutris '%s'"),
|
||||
('/desktop/gnome/url-handlers/lutris/enabled', True),
|
||||
('/desktop/gnome/url-handlers/lutris/needs-terminal', False),)
|
||||
|
||||
"""
|
||||
config_paths = [constants.LUTRIS_CONFIG_PATH,
|
||||
constants.runner_config_path,
|
||||
constants.GAME_CONFIG_PATH,
|
||||
constants.COVER_PATH,
|
||||
constants.TMP_PATH,
|
||||
constants.ICON_PATH,
|
||||
constants.BANNER_PATH,
|
||||
constants.LUTRIS_CACHE_PATH,
|
||||
constants.LUTRIS_DATA_PATH]
|
||||
for config_path in config_paths:
|
||||
if not os.path.exists(config_path):
|
||||
os.mkdir(config_path)
|
||||
for key, value in defaults:
|
||||
log.logger.debug("registering gconf key %s" % key)
|
||||
gconf.set_key(key, value, override_type=True)
|
||||
|
||||
|
||||
def check_config(force_wipe=False):
|
||||
"""Check if initial configuration is correct."""
|
||||
directories = [CONFIG_DIR,
|
||||
CACHE_DIR,
|
||||
DATA_DIR,
|
||||
join(CONFIG_DIR, "runners"),
|
||||
join(CONFIG_DIR, "games"),
|
||||
join(DATA_DIR, "covers"),
|
||||
join(DATA_DIR, "icons"),
|
||||
join(DATA_DIR, "banners")]
|
||||
if not os.path.exists(CONFIG_DIR) or force_wipe:
|
||||
first_run = True
|
||||
else:
|
||||
first_run = False
|
||||
for directory in directories:
|
||||
if not os.path.exists(directory):
|
||||
log.logger.debug("creating directory %s" % directory)
|
||||
os.mkdir(directory)
|
||||
|
||||
if not os.path.isfile(PGA_DB) or force_wipe:
|
||||
log.logger.debug("creating PGA database in %s" % PGA_DB)
|
||||
|
||||
if not os.path.isfile(PGA_PATH):
|
||||
pga.create()
|
||||
if first_run:
|
||||
register_handler
|
||||
|
||||
|
||||
class LutrisConfig():
|
||||
|
@ -91,7 +111,7 @@ class LutrisConfig():
|
|||
|
||||
if self.game:
|
||||
game_config_full_path = join(GAME_CONFIG_PATH,
|
||||
self.game + CONFIG_EXTENSION)
|
||||
self.game + ".yml")
|
||||
if os.path.exists(game_config_full_path):
|
||||
try:
|
||||
content = file(game_config_full_path, 'r').read()
|
||||
|
@ -108,7 +128,7 @@ class LutrisConfig():
|
|||
|
||||
if self.runner:
|
||||
runner_config_full_path = join(constants.runner_config_path,
|
||||
self.runner + CONFIG_EXTENSION)
|
||||
self.runner + ".yml")
|
||||
if os.path.exists(runner_config_full_path):
|
||||
yaml_content = file(runner_config_full_path, 'r').read()
|
||||
self.runner_config = yaml.load(yaml_content)
|
||||
|
@ -164,7 +184,7 @@ class LutrisConfig():
|
|||
|
||||
logging.debug("removing %s", game_name)
|
||||
os.remove(join(GAME_CONFIG_PATH,
|
||||
game_name + CONFIG_EXTENSION))
|
||||
game_name + ".yml"))
|
||||
|
||||
def is_valid(self):
|
||||
"""Check the config data and return True if config is ok."""
|
||||
|
@ -175,7 +195,7 @@ class LutrisConfig():
|
|||
print "Error in %s config file : No runner" % self.game
|
||||
return False
|
||||
|
||||
def save(self, runner_type=None):
|
||||
def save(self, config_type=None):
|
||||
"""Save configuration file
|
||||
|
||||
The way to save config files can be set by the type argument
|
||||
|
@ -183,25 +203,24 @@ class LutrisConfig():
|
|||
"""
|
||||
|
||||
self.update_global_config()
|
||||
logging.debug("Saving config (type %s)", runner_type)
|
||||
logging.debug("Saving config (type %s)", config_type)
|
||||
logging.debug(self.config)
|
||||
if runner_type is None:
|
||||
runner_type = self.config_type
|
||||
if config_type is None:
|
||||
config_type = self.config_type
|
||||
yaml_config = yaml.dump(self.config, default_flow_style=False)
|
||||
|
||||
if runner_type == "system":
|
||||
if config_type == "system":
|
||||
file(constants.system_config_full_path, "w").write(yaml_config)
|
||||
elif runner_type == "runner":
|
||||
elif config_type == "runner":
|
||||
runner_config_path = join(constants.runner_config_path,
|
||||
self.runner + CONFIG_EXTENSION)
|
||||
self.runner + ".yml")
|
||||
file(runner_config_path, "w").write(yaml_config)
|
||||
elif runner_type == "game":
|
||||
elif config_type == "game":
|
||||
if not self.game:
|
||||
self.game = self.config["runner"] \
|
||||
+ "-" + self.config["realname"].replace(" ", "_")
|
||||
game_config_path = join(GAME_CONFIG_PATH,
|
||||
self.game.replace('/', '_') + \
|
||||
CONFIG_EXTENSION)
|
||||
self.game.replace('/', '_') + ".yml")
|
||||
config_file = file(game_config_path, "w")
|
||||
config_file.write(yaml_config)
|
||||
return self.game
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding:Utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2010 Mathieu Comandon <strider@strycore.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
try:
|
||||
from lutris.gconfwrapper import GconfWrapper
|
||||
GCONF_CAPABLE = True
|
||||
except GConfBindingsUnavailable:
|
||||
GCONF_CAPABLE = False
|
||||
|
||||
def register_lutris_handler():
|
||||
if not GCONF_CAPABLE:
|
||||
print "Can't find gconf bindings"
|
||||
return
|
||||
gconf = GconfWrapper()
|
||||
defaults = (('/desktop/gnome/url-handlers/lutris/command', "lutris '%s'"),
|
||||
('/desktop/gnome/url-handlers/lutris/enabled', True),
|
||||
('/desktop/gnome/url-handlers/lutris/needs-terminal', False),)
|
||||
|
||||
for key, value in defaults:
|
||||
if not gconf.has_key(key):
|
||||
gconf.set_key(key, value, override_type = True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
register_lutris_handler()
|
||||
|
|
@ -57,9 +57,7 @@ if not exists(DATA_PATH):
|
|||
print "DATA_PATH can't be found at : %s" % DATA_PATH
|
||||
exit
|
||||
|
||||
lutris_icon_file = "media/logo.svg"
|
||||
lutris_icon_path = join(DATA_PATH, lutris_icon_file)
|
||||
LUTRIS_ICON_PATH = lutris_icon_path
|
||||
LUTRIS_ICON = join(DATA_PATH, "media/logo.svg")
|
||||
|
||||
LUTRIS_CONFIG_PATH = join(BaseDirectory.xdg_config_home, 'lutris')
|
||||
LUTRIS_DATA_PATH = join(BaseDirectory.xdg_data_home, 'lutris')
|
||||
|
@ -72,5 +70,4 @@ GAME_CONFIG_PATH = join(LUTRIS_CONFIG_PATH, 'games')
|
|||
COVER_PATH = join(LUTRIS_CONFIG_PATH, 'covers')
|
||||
BANNER_PATH = join(LUTRIS_CONFIG_PATH, 'banners')
|
||||
ICON_PATH = join(expanduser('~'), '.icons')
|
||||
cache_path = LUTRIS_CACHE_PATH
|
||||
TMP_PATH = join(LUTRIS_CACHE_PATH, 'tmp')
|
||||
|
|
|
@ -21,17 +21,12 @@
|
|||
This class interacts with the window manager, xrandr, gconf, ...
|
||||
"""
|
||||
|
||||
import gconf
|
||||
import os.path
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from lutris.exceptions import GConfBindingsUnavailable
|
||||
# Don't force to import gconf, some users might not have it.
|
||||
try:
|
||||
import gconf
|
||||
from lutris.gconfwrapper import GconfWrapper
|
||||
GCONF_CAPABLE = True
|
||||
except GConfBindingsUnavailable:
|
||||
GCONF_CAPABLE = False
|
||||
from lutris.gconfwrapper import GconfWrapper
|
||||
|
||||
def make_compiz_rule(class_=None, title=None):
|
||||
"""Return a string formated for the Window Rules plugin"""
|
||||
|
|
|
@ -21,7 +21,7 @@ import threading
|
|||
|
||||
from lutris.util import log
|
||||
|
||||
class DownloadStoppedException:
|
||||
class DownloadStoppedException(Exception):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
@ -36,11 +36,10 @@ class Downloader(threading.Thread):
|
|||
self.dest = dest
|
||||
self.progress = 0
|
||||
self.kill = None
|
||||
print "init done"
|
||||
|
||||
def run(self):
|
||||
"""Start the download."""
|
||||
print "starting download"
|
||||
log.debug("Download of %s starting" % self.url)
|
||||
urllib.urlretrieve(self.url, self.dest, self._report_progress)
|
||||
return True
|
||||
|
||||
|
@ -52,6 +51,4 @@ class Downloader(threading.Thread):
|
|||
if self.kill is True:
|
||||
raise DownloadStoppedException
|
||||
except DownloadStoppedException:
|
||||
pass
|
||||
print "stopping download"
|
||||
|
||||
log.debug("stopping download")
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding:Utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2010 Mathieu Comandon <strider@strycore.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
class GConfBindingsUnavailable(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
|
@ -16,12 +16,12 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import subprocess
|
||||
import gobject
|
||||
import os
|
||||
import os.path
|
||||
import time
|
||||
import gtk
|
||||
import time
|
||||
import os.path
|
||||
import gobject
|
||||
import subprocess
|
||||
from signal import SIGKILL
|
||||
|
||||
from lutris.runners import import_runner
|
||||
|
@ -94,9 +94,7 @@ class LutrisGame(object):
|
|||
self.load_success = self.load_config()
|
||||
|
||||
def load_config(self):
|
||||
"""
|
||||
Load the game's configuration.
|
||||
"""
|
||||
""" Load the game's configuration. """
|
||||
self.game_config = LutrisConfig(game=self.name)
|
||||
if self.game_config.is_valid():
|
||||
self.runner_name = self.game_config["runner"]
|
||||
|
@ -171,7 +169,7 @@ class LutrisGame(object):
|
|||
logger.debug("Failed to set resolution %s"
|
||||
% config["system"]["resolution"])
|
||||
|
||||
#Setting OSS Wrapper
|
||||
#Setting OSS Wrapper
|
||||
if "oss_wrapper" in config["system"]:
|
||||
oss_wrapper = config["system"]["oss_wrapper"]
|
||||
|
||||
|
|
|
@ -17,23 +17,19 @@
|
|||
#
|
||||
|
||||
import os
|
||||
import gconf
|
||||
|
||||
from glib import GError
|
||||
|
||||
from lutris.exceptions import GConfBindingsUnavailable
|
||||
from lutris.util.log import logger
|
||||
|
||||
try:
|
||||
import gconf
|
||||
from glib import GError
|
||||
except ImportError:
|
||||
raise GConfBindingsUnavailable('Install python-gconf')
|
||||
|
||||
|
||||
class GconfWrapper():
|
||||
class GconfWrapper(object):
|
||||
def __init__(self):
|
||||
self.gconf_path = os.path.join(os.path.expanduser("~"), ".gconf")
|
||||
self.client = gconf.client_get_default()
|
||||
|
||||
def has_key(self, key):
|
||||
def has(self, key):
|
||||
key = self.client.get_string(key)
|
||||
if key:
|
||||
return True
|
||||
|
|
|
@ -18,7 +18,7 @@ import os
|
|||
import gtk.gdk
|
||||
import lutris.constants
|
||||
|
||||
from lutris.constants import LUTRIS_ICON_PATH
|
||||
from lutris.constants import LUTRIS_ICON
|
||||
|
||||
|
||||
class AboutLutrisDialog(gtk.AboutDialog):
|
||||
|
@ -48,8 +48,8 @@ class AboutLutrisDialog(gtk.AboutDialog):
|
|||
|
||||
#code for other initialization actions should be added here
|
||||
self.set_position(gtk.WIN_POS_CENTER)
|
||||
self.set_icon_from_file(lutris.constants.lutris_icon_path)
|
||||
self.set_logo(gtk.gdk.pixbuf_new_from_file(LUTRIS_ICON_PATH))
|
||||
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)
|
||||
|
|
|
@ -131,7 +131,7 @@ class AddGameDialog(gtk.Dialog):
|
|||
logging.debug(self.lutris_config.game_config)
|
||||
|
||||
if self.runner_class and realname:
|
||||
game_identifier = self.lutris_config.save(runner_type="game")
|
||||
game_identifier = self.lutris_config.save(config_type="game")
|
||||
self.game_info = {"name": realname,
|
||||
"runner": self.runner_class,
|
||||
"id": game_identifier}
|
||||
|
|
|
@ -87,7 +87,7 @@ class EditGameConfigDialog(gtk.Dialog):
|
|||
|
||||
def edit_game(self, widget=None):
|
||||
logging.debug(self.lutris_config.config)
|
||||
self.lutris_config.save(runner_type="game")
|
||||
self.lutris_config.save(config_type="game")
|
||||
self.destroy()
|
||||
|
||||
def close(self, widget=None):
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding:Utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2010 Mathieu Comandon <strider@strycore.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
"""Helpers for an Ubuntu application."""
|
||||
|
||||
__all__ = ['make_window',]
|
||||
|
||||
import os
|
||||
import gtk
|
||||
import gettext
|
||||
|
||||
from lutris.lutrisconfig import get_data_file
|
||||
|
||||
from gettext import gettext as _
|
||||
gettext.textdomain('lutris')
|
||||
|
||||
def get_builder(builder_file_name):
|
||||
"""Return a fully-instantiated gtk.Builder instance from specified ui
|
||||
file
|
||||
|
||||
:param builder_file_name: The name of the builder file, without extension.
|
||||
Assumed to be in the 'ui' directory under the data path.
|
||||
"""
|
||||
# Look for the ui file that describes the user interface.
|
||||
ui_filename = get_data_file('ui', '%s.ui' % (builder_file_name,))
|
||||
if not os.path.exists(ui_filename):
|
||||
ui_filename = None
|
||||
|
||||
builder = gtk.Builder()
|
||||
builder.set_translation_domain('lutris')
|
||||
builder.add_from_file(ui_filename)
|
||||
return builder
|
|
@ -15,7 +15,7 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
"""Installer module"""
|
||||
import os
|
||||
import gtk
|
||||
import yaml
|
||||
|
@ -26,7 +26,7 @@ import platform
|
|||
import subprocess
|
||||
import lutris.constants
|
||||
|
||||
from os.path import join, exists, expanduser
|
||||
from os.path import join, exists
|
||||
|
||||
from lutris.util import log
|
||||
from lutris.util.strings import slugify
|
||||
|
@ -35,7 +35,7 @@ from lutris.config import LutrisConfig
|
|||
from lutris.gui.common import ErrorDialog, DirectoryDialog
|
||||
from lutris.gui.widgets import DownloadProgressBox
|
||||
from lutris.shortcuts import create_launcher
|
||||
from lutris.constants import LUTRIS_CACHE_PATH, INSTALLER_URL, TMP_PATH,\
|
||||
from lutris.constants import LUTRIS_CACHE_PATH, INSTALLER_URL, TMP_PATH, \
|
||||
ICON_PATH, BANNER_PATH, GAME_CONFIG_PATH
|
||||
|
||||
|
||||
|
@ -84,6 +84,7 @@ def reporthook(piece, received_bytes, total_size):
|
|||
|
||||
|
||||
class Installer(gtk.Dialog):
|
||||
""" Installer class """
|
||||
def __init__(self, game, installer=False):
|
||||
self.lutris_config = None # Internal game config
|
||||
if not game:
|
||||
|
@ -198,7 +199,6 @@ class Installer(gtk.Dialog):
|
|||
urllib.urlretrieve(banner_url, banner_dest)
|
||||
except IOError:
|
||||
print "cant get banner to %s" % banner_dest
|
||||
pass
|
||||
|
||||
icon_url = 'http://lutris.net/media/game_icons/%s.png' % self.game_slug
|
||||
icon_path = join(ICON_PATH, "%s.png" % self.game_slug)
|
||||
|
@ -206,7 +206,6 @@ class Installer(gtk.Dialog):
|
|||
urllib.urlretrieve(icon_url, icon_path)
|
||||
except IOError:
|
||||
print "cant get icon"
|
||||
pass
|
||||
|
||||
# Download installer if not already there.
|
||||
if not os.path.exists(self.installer_path):
|
||||
|
@ -238,6 +237,7 @@ class Installer(gtk.Dialog):
|
|||
return success
|
||||
|
||||
def game_dir_set(self, widget=None):
|
||||
"""Set the installation directory based on the user's choice"""
|
||||
self.game_dir = widget.get_current_folder()
|
||||
if os.path.exists(self.game_dir):
|
||||
self.install_button.set_sensitive(True)
|
||||
|
@ -248,15 +248,13 @@ class Installer(gtk.Dialog):
|
|||
self.location_button.destroy()
|
||||
self.install_button.set_sensitive(False)
|
||||
|
||||
self.current_file = 0
|
||||
self.total_files = len(self.rules['files'])
|
||||
|
||||
for game_file in self.rules['files']:
|
||||
self.download_game_file(game_file)
|
||||
log.logger.debug("All files downloaded")
|
||||
self.install()
|
||||
|
||||
def download_game_file(self, game_file):
|
||||
"""Download a file referenced in the installer script"""
|
||||
file_id = game_file.keys()[0]
|
||||
# Game files can be either a string, containing the location of the
|
||||
# file to fetch or a dict with the possible options :
|
||||
|
@ -279,7 +277,6 @@ class Installer(gtk.Dialog):
|
|||
log.logger.debug("Downloading %s" % url)
|
||||
dest_path = self._download(url, filename, copyfile)
|
||||
self.gamefiles[file_id] = dest_path
|
||||
self.current_file += 1
|
||||
return True
|
||||
|
||||
def install(self):
|
||||
|
@ -299,8 +296,7 @@ class Installer(gtk.Dialog):
|
|||
'move': self._move,
|
||||
'delete': self.delete,
|
||||
'request_media': self._request_media,
|
||||
'run': self._run,
|
||||
'locate': self._locate}
|
||||
'run': self._run}
|
||||
if action_name not in mappings.keys():
|
||||
print "Action " + action_name + " not supported !"
|
||||
return False
|
||||
|
@ -427,8 +423,8 @@ class Installer(gtk.Dialog):
|
|||
elif url.startswith("$ASK_DIR"):
|
||||
#Ask the user where is located the file
|
||||
basename = url[9:]
|
||||
d = DirectoryDialog("Select location of file %s " % basename)
|
||||
file_path = d.folder
|
||||
dlg = DirectoryDialog("Select location of file %s " % basename)
|
||||
file_path = dlg.folder
|
||||
if copyfile is True:
|
||||
location = os.path.join(file_path, basename)
|
||||
shutil.copy(location, dest_dir)
|
||||
|
@ -505,6 +501,7 @@ class Installer(gtk.Dialog):
|
|||
return True
|
||||
|
||||
def _request_media(self, data):
|
||||
"""Prompt user to insert a removable media"""
|
||||
if 'default' in data:
|
||||
path = data['default']
|
||||
if os.path.exists(os.path.join(path, data['contains'])):
|
||||
|
@ -513,6 +510,7 @@ class Installer(gtk.Dialog):
|
|||
return False
|
||||
|
||||
def _run(self, data):
|
||||
"""Run an executable script"""
|
||||
exec_path = os.path.join(TMP_PATH, self.game_slug,
|
||||
self.gamefiles[data['file']])
|
||||
if not os.path.exists(exec_path):
|
||||
|
@ -522,9 +520,7 @@ class Installer(gtk.Dialog):
|
|||
os.popen('chmod +x %s' % exec_path)
|
||||
subprocess.call([exec_path])
|
||||
|
||||
def _locate(self):
|
||||
return None
|
||||
|
||||
def launch_game(self, widget, data=None):
|
||||
def launch_game(self, **kwargs):
|
||||
"""Launch a game after it's been installed"""
|
||||
lutris_game = LutrisGame(self.game_slug)
|
||||
lutris_game.play()
|
||||
|
|
|
@ -20,19 +20,26 @@
|
|||
import sqlite3
|
||||
|
||||
from lutris.util.strings import slugify
|
||||
from lutris.settings import PGA_PATH
|
||||
from lutris.util import log
|
||||
from lutris.settings import PGA_DB
|
||||
|
||||
|
||||
def connect():
|
||||
"""Connect to the local PGA database."""
|
||||
return sqlite3.connect(PGA_PATH)
|
||||
return sqlite3.connect(PGA_DB)
|
||||
|
||||
|
||||
def create():
|
||||
"""Create the local PGA database."""
|
||||
log.logger.debug("Running CREATE statement...")
|
||||
con = connect()
|
||||
query = 'create table games ' + \
|
||||
'(name text, slug text, machine text, runner text)'
|
||||
query = """CREATE TABLE games (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT,
|
||||
slug TEXT,
|
||||
machine TEXT,
|
||||
runner TEXT,
|
||||
lastplayed INTEGER)"""
|
||||
con.execute(query)
|
||||
con.commit()
|
||||
con.close()
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
###############################################################################
|
||||
|
||||
"""Runner for the Steam platform"""
|
||||
|
||||
import os
|
||||
import gtk
|
||||
|
||||
|
@ -26,10 +28,10 @@ from lutris.gui.common import QuestionDialog, DirectoryDialog
|
|||
from lutris.runners.wine import wine
|
||||
from lutris.config import LutrisConfig
|
||||
|
||||
|
||||
class steam(wine):
|
||||
"""Runner for the Steam platform."""
|
||||
|
||||
def __init__(self,settings=None):
|
||||
def __init__(self, settings=None):
|
||||
super(steam, self).__init__(settings)
|
||||
self.executable = "Steam.exe"
|
||||
self.package = None
|
||||
|
@ -44,8 +46,8 @@ class steam(wine):
|
|||
self.is_installable = False
|
||||
self.appid = "26800"
|
||||
self.game_options = [
|
||||
{'option': 'appid', 'type': 'string', 'label': 'appid'},
|
||||
{'option': 'args', 'type': 'string', 'label': 'arguments'}
|
||||
{'option': 'appid', 'type': 'string', 'label': 'appid'},
|
||||
{'option': 'args', 'type': 'string', 'label': 'arguments'}
|
||||
]
|
||||
if settings:
|
||||
self.appid = settings['game']['appid']
|
||||
|
@ -55,23 +57,22 @@ class steam(wine):
|
|||
self.args = ""
|
||||
|
||||
def install(self):
|
||||
q = QuestionDialog({
|
||||
dlg = QuestionDialog({
|
||||
'title': 'Installing Steam',
|
||||
'question': 'Do you already have Steam on your computer ?'
|
||||
})
|
||||
if q.result == gtk.RESPONSE_NO:
|
||||
if dlg.result == gtk.RESPONSE_NO:
|
||||
print "!!! NOT IMPLEMENTED !!!"
|
||||
|
||||
d = DirectoryDialog('Where is located Steam ?')
|
||||
dlg = DirectoryDialog('Where is located Steam ?')
|
||||
|
||||
config = LutrisConfig(runner='steam')
|
||||
config.runner_config = {'system': {'game_path': d.folder }}
|
||||
config.save(type='runner')
|
||||
config.runner_config = {'system': {'game_path': dlg.folder}}
|
||||
config.save(config_type='runner')
|
||||
|
||||
def is_installed(self):
|
||||
"""Checks if wine is installed and
|
||||
if the steam executable is on the harddrive
|
||||
|
||||
"""Checks if wine is installed and if the steam executable is on the
|
||||
harddrive
|
||||
"""
|
||||
if not self.check_depends():
|
||||
return False
|
||||
|
@ -103,7 +104,7 @@ class steam(wine):
|
|||
|
||||
def get_appid_list(self):
|
||||
self.game_list = []
|
||||
os.chdir(os.path.join(self.game_path,"appcache"))
|
||||
os.chdir(os.path.join(self.game_path, "appcache"))
|
||||
max_counter = 10010
|
||||
files = []
|
||||
counter = 0
|
||||
|
@ -117,36 +118,36 @@ class steam(wine):
|
|||
steam_apps = []
|
||||
for file in files:
|
||||
if file.endswith(".vdf"):
|
||||
test_file = open(file,"rb")
|
||||
test_file = open(file, "rb")
|
||||
appid = self.get_appid_from_filename(file)
|
||||
appname = self.get_name(test_file)
|
||||
if appname:
|
||||
steam_apps.append((appid,appname,file))
|
||||
steam_apps.append((appid, appname, file))
|
||||
test_file.close()
|
||||
|
||||
steam_apps.sort()
|
||||
steam_apps_file = open(
|
||||
os.path.join(os.path.expanduser("~"),"steamapps.txt"),"w"
|
||||
)
|
||||
os.path.join(os.path.expanduser("~"), "steamapps.txt"), "w"
|
||||
)
|
||||
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]))
|
||||
self.game_list.append((steam_app[0], steam_app[1]))
|
||||
steam_apps_file.close()
|
||||
|
||||
def play(self):
|
||||
if not self.check_depends():
|
||||
return {'error': 'RUNNER_NOT_INSTALLED',
|
||||
'runner': self.depends }
|
||||
'runner': self.depends}
|
||||
if not self.is_installed():
|
||||
return {'error': 'RUNNER_NOT_INSTALLED',
|
||||
'runner': self.__class__.__name__}
|
||||
|
||||
self.check_regedit_keys() #From parent wine runner
|
||||
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)
|
||||
command = ['wine', '"' + steam_full_path + '"', '-applaunch', self.appid, self.args]
|
||||
return {'command': command }
|
||||
|
||||
command = ['wine', '"%s"' % steam_full_path,
|
||||
'-applaunch', self.appid, self.args]
|
||||
return {'command': command}
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding:Utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2010 Mathieu Comandon <strider@strycore.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 3 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
import yaml
|
||||
import urlparse
|
||||
import os
|
||||
import hashlib
|
||||
import logging
|
||||
import lutris.constants
|
||||
|
||||
from lutris.tool.url_tool import UrlTool
|
||||
|
||||
|
||||
class LutrisInterpreter():
|
||||
def __init__(self, filename=None):
|
||||
self.valid_schemes = ('http', 'https', 'ftp')
|
||||
self.url_tool = UrlTool()
|
||||
self.files = {}
|
||||
self.dirs = {}
|
||||
self.dirs['cache'] = lutris.constants.cache_path
|
||||
self.dirs['gamedir'] = '/home/strider/Jeux'
|
||||
|
||||
if filename:
|
||||
self.load(filename)
|
||||
|
||||
def load(self, filename):
|
||||
self.config = yaml.load(file(filename, 'r').read())
|
||||
|
||||
def get_files(self):
|
||||
if not self.config:
|
||||
return False
|
||||
if 'files' in self.config:
|
||||
for filename in self.config['files']:
|
||||
file_id = filename.keys()[0]
|
||||
file_path = filename[file_id]
|
||||
url = urlparse.urlparse(file_path)
|
||||
if url.scheme:
|
||||
destfile = os.path.basename(url.path)
|
||||
destpath = lutris.constants.cache_path + destfile
|
||||
if not os.path.exists(destpath):
|
||||
self.url_tool.save_to(destpath, file_path)
|
||||
self.files[file_id] = destpath
|
||||
else:
|
||||
print 'not a url', file_id
|
||||
|
||||
def install(self):
|
||||
if not 'installer' in self.config:
|
||||
return False
|
||||
for directive in self.config['installer']:
|
||||
directive_name = directive.keys()[0]
|
||||
print directive_name
|
||||
if directive_name == 'md5_check':
|
||||
self.md5_check(directive)
|
||||
if directive_name == 'extract':
|
||||
extract_info = directive['extract']
|
||||
if 'newdir' in extract_info:
|
||||
dest = os.path.join(self.dirs[extract_info['destination']],
|
||||
extract_info['newdir'])
|
||||
if not os.path.exists(dest):
|
||||
os.mkdir(dest)
|
||||
self.dirs[extract_info['newdir']] = dest
|
||||
else:
|
||||
dest = self.dirs[extract_info['destination']]
|
||||
self.extract(extract_info['file'], dest)
|
||||
|
||||
def check_md5(self, file_id):
|
||||
print 'checking ', self.files[file_id]
|
||||
|
||||
def extract(self, archive, dest, options={}):
|
||||
if not 'method' in options:
|
||||
method = 'zip'
|
||||
else:
|
||||
method = options['method']
|
||||
print "extracting %s to %s " % (self.files[archive], dest)
|
||||
command = "unzip %s -d %s" % (self.files[archive], dest)
|
||||
os.system(command)
|
||||
|
||||
def move(self, source, destination):
|
||||
os.move
|
||||
|
||||
if __name__ == '__main__':
|
||||
filename = '/home/strider/Jeux/quake.lutris'
|
||||
interpreter = LutrisInterpreter(filename)
|
||||
interpreter.get_files()
|
||||
interpreter.install()
|
|
@ -1,9 +1,9 @@
|
|||
from os.path import realpath, normpath, dirname, join, exists, expanduser
|
||||
"""Settings module"""
|
||||
from os.path import join
|
||||
from xdg import BaseDirectory
|
||||
import sys
|
||||
|
||||
LUTRIS_CONFIG_PATH = join(BaseDirectory.xdg_config_home, 'lutris')
|
||||
LUTRIS_DATA_PATH = join(BaseDirectory.xdg_data_home, 'lutris')
|
||||
LUTRIS_CACHE_PATH = join(BaseDirectory.xdg_cache_home, 'lutris')
|
||||
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_PATH = join(LUTRIS_DATA_PATH, 'pga.db')
|
||||
PGA_DB = join(DATA_DIR, 'pga.db')
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
import sys
|
||||
""" xdg desktop file creator """
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
from xdg import BaseDirectory
|
||||
|
||||
# FIXME : why is this here ?
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from lutris.config import LutrisConfig
|
||||
from lutris.constants import ICON_PATH, TMP_PATH
|
||||
|
||||
|
||||
def create_launcher(game, desktop=False, menu=False):
|
||||
""" Create desktop file """
|
||||
config = LutrisConfig(game=game)
|
||||
desktop_dir = Popen(['xdg-user-dir', 'DESKTOP'],
|
||||
stdout=PIPE).communicate()[0]
|
||||
|
@ -43,6 +41,3 @@ Categories=Game""" % (
|
|||
shutil.copy(tmp_launcher_path,
|
||||
os.path.join(menu_path, launcher_filename))
|
||||
os.remove(tmp_launcher_path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
create_launcher("quake", desktop=True, menu=True)
|
||||
|
|
|
@ -15,16 +15,19 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
"""
|
||||
Threading module, used to launch games while keeping Lutris operational.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import logging
|
||||
import gobject
|
||||
import threading
|
||||
import subprocess
|
||||
import gobject
|
||||
from os.path import exists
|
||||
from signal import SIGKILL
|
||||
|
||||
from os import kill, killpg
|
||||
from os import kill
|
||||
|
||||
|
||||
class LutrisThread(threading.Thread):
|
||||
|
@ -45,7 +48,7 @@ class LutrisThread(threading.Thread):
|
|||
self.killswitch = killswitch
|
||||
|
||||
def run(self):
|
||||
self.timer_id = gobject.timeout_add(2000, self.poke_process)
|
||||
gobject.timeout_add(2000, self.poke_process)
|
||||
logging.debug(self.command)
|
||||
self.game_process = subprocess.Popen(self.command, shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
|
@ -64,8 +67,7 @@ class LutrisThread(threading.Thread):
|
|||
return True
|
||||
else:
|
||||
if self.killswitch is not None and not exists(self.killswitch):
|
||||
# How do be sure that pid + 1 is actually the game process ?
|
||||
#self.game_process.terminate()
|
||||
# How are we sure that pid + 1 is actually the game process ?
|
||||
kill(self.game_process.pid + 1, SIGKILL)
|
||||
self.pid = None
|
||||
return False
|
||||
|
@ -76,17 +78,3 @@ class LutrisThread(threading.Thread):
|
|||
self.pid = None
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class ThreadProcessReader(threading.Thread):
|
||||
def __init__(self, stdout):
|
||||
threading.Thread.__init__(self)
|
||||
self.stdout = stdout
|
||||
self.status = "running"
|
||||
self.seconds_left = 0
|
||||
|
||||
def run(self):
|
||||
seconds_max = 0
|
||||
process_ended = False
|
||||
while self.status == "running":
|
||||
line = self.stdout.read(80)
|
||||
|
|
|
@ -8,8 +8,8 @@ print xdg_config_dirs
|
|||
cache = xdg.Menu.parse("/etc/xdg/menus/applications.menu")
|
||||
print cache
|
||||
for entry in cache.getEntries():
|
||||
#print entry
|
||||
if str(entry) == 'Games':
|
||||
print entry
|
||||
if str(entry) in ('wine-wine'):
|
||||
print("youpi")
|
||||
for game in entry.getEntries():
|
||||
print "============"
|
||||
|
|
1
setup.py
1
setup.py
|
@ -100,4 +100,3 @@ on Linux.""",
|
|||
url='https://launchpad.net/lutris',
|
||||
cmdclass={'install': InstallAndUpdateDataDirectory}
|
||||
)
|
||||
|
||||
|
|
|
@ -28,31 +28,62 @@ class TestGConfWrapper(unittest.TestCase):
|
|||
self.gconf = GconfWrapper()
|
||||
|
||||
def runTest(self):
|
||||
self.assertEqual(self.gconf.has_key('/apps/metacity/general/button_layout'), True)
|
||||
self.assertEqual(self.gconf.has_key('/apps/metacity/general/bouton_disposition'), False)
|
||||
self.assertEqual(self.gconf.has_key('/foo/bar'), False)
|
||||
self.assertEqual(
|
||||
self.gconf.has('/apps/metacity/general/button_layout'), True
|
||||
)
|
||||
self.assertEqual(
|
||||
self.gconf.has('/apps/metacity/general/bouton_disposition'), False
|
||||
)
|
||||
self.assertEqual(self.gconf.has('/foo/bar'), False)
|
||||
|
||||
self.assertEqual(self.gconf.get_key('/foo/bar'), None)
|
||||
self.assertEqual(self.gconf.get_key('/apps/metacity/general/raise_on_click'), True)
|
||||
self.assertEqual(
|
||||
self.gconf.get_key('/foo/bar'), None
|
||||
)
|
||||
self.assertEqual(
|
||||
self.gconf.get_key('/apps/metacity/general/raise_on_click'), True
|
||||
)
|
||||
self.assertTrue(
|
||||
self.gconf.set_key('/apps/metacity/general/auto_raise_delay',
|
||||
500,
|
||||
override_type=True))
|
||||
self.assertEqual(self.gconf.get_key('/apps/metacity/general/auto_raise_delay'), 500)
|
||||
self.gconf.set_key('/apps/metacity/general/auto_raise_delay',
|
||||
500, override_type=True)
|
||||
)
|
||||
self.assertEqual(
|
||||
self.gconf.get_key('/apps/metacity/general/auto_raise_delay'), 500
|
||||
)
|
||||
self.assertTrue(
|
||||
self.gconf.set_key('/apps/metacity/general/raise_on_click', False)
|
||||
)
|
||||
self.assertEqual(
|
||||
self.gconf.get_key('/apps/metacity/general/raise_on_click'), False
|
||||
)
|
||||
self.assertTrue(
|
||||
self.gconf.set_key('/apps/metacity/general/raise_on_click', True)
|
||||
)
|
||||
self.assertEqual(
|
||||
self.gconf.get_key('/apps/metacity/general/raise_on_click'), True
|
||||
)
|
||||
|
||||
self.assertTrue(self.gconf.set_key('/apps/metacity/general/raise_on_click', False))
|
||||
self.assertEqual(self.gconf.get_key('/apps/metacity/general/raise_on_click'), False)
|
||||
self.assertTrue(self.gconf.set_key('/apps/metacity/general/raise_on_click', True))
|
||||
self.assertEqual(self.gconf.get_key('/apps/metacity/general/raise_on_click'), True)
|
||||
|
||||
self.assertTrue(self.gconf.set_key('/apps/metacity/general/auto_raise_delay', 499))
|
||||
self.assertEqual(self.gconf.get_key('/apps/metacity/general/auto_raise_delay'), 499)
|
||||
self.assertFalse(self.gconf.set_key('/apps/metacity/general/auto_raise_delay', "Five hundred"))
|
||||
self.assertTrue(self.gconf.set_key('/apps/metacity/general/auto_raise_delay', 500))
|
||||
self.assertTrue(
|
||||
self.gconf.set_key('/apps/metacity/general/auto_raise_delay', 499)
|
||||
)
|
||||
self.assertEqual(
|
||||
self.gconf.get_key('/apps/metacity/general/auto_raise_delay'), 499
|
||||
)
|
||||
self.assertFalse(
|
||||
self.gconf.set_key('/apps/metacity/general/auto_raise_delay',
|
||||
"Five hundred")
|
||||
)
|
||||
self.assertTrue(
|
||||
self.gconf.set_key('/apps/metacity/general/auto_raise_delay', 500)
|
||||
)
|
||||
|
||||
print 'testing new keys'
|
||||
self.assertTrue(self.gconf.set_key('/apps/lutris/tests/foo', "dressed like pazuzu", override_type = True))
|
||||
self.assertEqual(self.gconf.get_key('/apps/lutris/tests/foo'), "dressed like pazuzu")
|
||||
self.assertTrue(
|
||||
self.gconf.set_key('/apps/lutris/tests/foo', "dressed like pazuzu",
|
||||
override_type=True)
|
||||
)
|
||||
self.assertEqual(
|
||||
self.gconf.get_key('/apps/lutris/tests/foo'), "dressed like pazuzu"
|
||||
)
|
||||
self.assertEqual(self.gconf.all_dirs('/apps/lutris'), ['tests'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in a new issue