Local install of snes9x

This commit is contained in:
Mathieu Comandon 2012-11-11 21:34:28 +01:00
parent 1c23f438c3
commit 344a1926ce
8 changed files with 121 additions and 78 deletions

View file

@ -45,13 +45,15 @@ def register_handler():
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"),
DATA_DIR,
join(DATA_DIR, "covers"),
join(DATA_DIR, "icons"),
join(DATA_DIR, "banners"),
join(DATA_DIR, "runners"),
join(DATA_DIR, "lib"),
CACHE_DIR,
join(CACHE_DIR, "installer")]
for directory in directories:
if not os.path.exists(directory):

View file

@ -20,9 +20,7 @@
import urllib
import threading
import re
from lutris.util import log
from lutris.util.log import logger
class DownloadStoppedException(Exception):
@ -45,7 +43,7 @@ class Downloader(threading.Thread):
def run(self):
"""Start the download."""
log.logger.debug("Download of %s starting" % self.url)
logger.debug("Download of %s starting" % self.url)
urllib.urlretrieve(self.url, self.dest, self._report_progress)
return True
@ -54,10 +52,9 @@ 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)
logger.debug("Progress: %0.2f%%", self.progress * 100)
try:
if self.kill is True:
raise DownloadStoppedException
except DownloadStoppedException:
log.logger.debug("stopping download")
logger.debug("stopping download")

View file

@ -75,11 +75,12 @@ class DirectoryDialog(Gtk.FileChooserDialog):
class DownloadDialog(Gtk.Dialog):
""" Dialog showing a download in progress. """
def __init__(self, url, dest):
super(DownloadDialog, self).__init__(self, "Downloading file")
super(DownloadDialog, self).__init__("Downloading file")
self.set_size_request(560, 100)
self.connect('destroy', self.destroy_cb)
#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)
label = Gtk.Label(label='Downloading %s' % url)
label.set_padding(0, 0)
label.set_alignment(0.0, 1.0)
@ -90,9 +91,12 @@ class DownloadDialog(Gtk.Dialog):
def destroy_cb(self, widget, data=None):
"""Action triggered when window is closed"""
self.download_cancel(None)
self.destroy()
def download_complete(self, _widget, _data):
self.destroy()
def download_cancel(self, _widget, _data=None):
"""Action triggered when download is cancelled"""
self.download_progress_box.cancel()
#self.download_progress_box.cancel()
pass

View file

@ -377,17 +377,18 @@ class DownloadProgressBox(Gtk.HBox):
None, (GObject.TYPE_PYOBJECT,))}
def __init__(self, params, cancelable=True):
GObject.GObject.__init__(self, False, 2)
#GObject.GObject.__init__(self, False, 2)
super(DownloadProgressBox, self).__init__()
self.downloader = None
self.progressbar = Gtk.ProgressBar()
self.progressbar.show()
self.pack_start(self.progressbar, True)
self.pack_start(self.progressbar, True, True, 10)
self.cancel_button = Gtk.Button(stock=Gtk.STOCK_CANCEL)
if cancelable:
self.cancel_button.show()
self.cancel_button.set_sensitive(False)
self.cancel_button.connect('clicked', self.__stop_download)
self.pack_end(self.cancel_button, False)
self.cancel_button.connect('clicked', self._stop_download)
self.pack_end(self.cancel_button, False, False, 10)
self.url = params['url']
self.dest = params['dest']
@ -412,14 +413,15 @@ class DownloadProgressBox(Gtk.HBox):
return False
return True
def __stop_download(self):
def _stop_download(self):
"""Stop the current download."""
self.downloader.kill = True
self.cancel_button.set_sensitive(False)
def cancel(self):
"""Cancel the current download."""
self.downloader.kill()
if self.downloader:
self.downloader.kill = True
class FileChooserEntry(Gtk.Box):

View file

@ -357,8 +357,7 @@ class Installer(Gtk.Dialog):
'move': self._move,
'request_media': self._request_media,
'run': self._run,
'runner': self._runner_task
}
'runner': self._runner_task}
if action_name not in mappings.keys():
log.logger.error("Action " + action_name + " not supported !")
continue

View file

@ -1,26 +1,5 @@
# -*- coding:Utf-8 -*-
###############################################################################
## Lutris
##
## Copyright (C) 2009, 2010 Mathieu Comandon <strycore@gmail.com>
##
## 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, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Generic runner """
import subprocess
import platform
import hashlib
@ -30,8 +9,6 @@ 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):
@ -48,7 +25,6 @@ class Runner(object):
"""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"""
@ -75,20 +51,15 @@ class Runner(object):
module = getattr(module, component)
runner = getattr(module, self.depends)
runner_instance = runner()
return runner_instance.is_installed()
def is_installed(self):
""" Check if runner is installed
Return a boolean
"""
"""Return True if runner is installed else False"""
is_installed = False
if not self.executable:
return False
result = subprocess.Popen(
['which', self.executable],
stdout=subprocess.PIPE).communicate()[0]
result = subprocess.Popen(['which', self.executable],
stdout=subprocess.PIPE).communicate()[0]
if result == '':
is_installed = False
else:
@ -139,6 +110,7 @@ class Runner(object):
logger.error("Edit runners/runner.py to add support for it")
return False
if self.package is None:
ErrorDialog('This runner is not yet installable')
logger.error("The requested runner %s can't be installed",
self.__class__.__name__)
return

View file

@ -1,27 +1,23 @@
# -*- coding:Utf-8 -*-
###############################################################################
## Lutris
##
## Copyright (C) 2009 Mathieu Comandon strycore@gmail.com
##
## 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, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
###############################################################################
""" Super Nintendo runner """
import os
import urllib
import platform
from lutris.runners.runner import Runner
from lutris.constants import TMP_PATH, LUTRIS_DATA_PATH
from lutris.util.extract import extract_archive, decompress_gz
SNES9X_VERSION = "snes9x-1.53"
SNES9X_32 = "http://lutris.net/files/runners/%s-gtk-81-i386.tar.bz2" \
% SNES9X_VERSION
SNES9X_64 = "http://lutris.net/files/runners/%s-gtk-81-x86_64.tar.bz2" \
% SNES9X_VERSION
LIBPNG_32 = NotImplemented
LIBPNG_64 = "http://lutris.net/files/lib64/libpng14.so.14.12.0.gz"
RUNNER_DIR = os.path.join(LUTRIS_DATA_PATH, "runners/")
SNES9X_RUNNER_DIR = os.path.join(RUNNER_DIR, SNES9X_VERSION)
# pylint: disable=C0103
@ -39,13 +35,40 @@ class snes9x(Runner):
self.game_options = [{"option": "rom",
"type": "file_chooser",
"label": "ROM"}]
self.runner_options = [{
"option": "fullscreen",
"type": "bool",
"label": "Fullscreen"
}]
self.runner_options = [{"option": "fullscreen",
"type": "bool",
"label": "Fullscreen"}]
if settings:
self.rom = settings["game"]["rom"]
def play(self):
return [self.executable, "\"%s\"" % self.rom]
def get_executable_path(self):
local_path = os.path.join(SNES9X_RUNNER_DIR, self.executable)
return local_path if os.path.exists(local_path) else self.executable
def is_installed(self):
installed = os.path.exists(os.path.join(SNES9X_RUNNER_DIR,
self.executable))
if not installed:
installed = super(snes9x, self).is_installed()
return installed
def install(self):
arch = platform.architecture()[0]
tarball_url = SNES9X_64 if arch == '64bit' else SNES9X_32
tarball_file = os.path.basename(tarball_url)
dest = os.path.join(TMP_PATH, tarball_file)
urllib.urlretrieve(tarball_url, dest)
extract_archive(dest, RUNNER_DIR)
lib_dir = os.path.join(SNES9X_RUNNER_DIR, "lib")
os.mkdir(lib_dir)
libpng_url = LIBPNG_64 if arch == '64bit' else LIBPNG_32
libpng_file = os.path.basename(libpng_url)
lib_abspath = os.path.join(lib_dir, libpng_file)
urllib.urlretrieve(libpng_url, lib_abspath)
lib_abspath = decompress_gz(lib_abspath)
os.link(lib_abspath, lib_abspath[:-5])
os.link(lib_abspath, lib_abspath[:-8])

44
lutris/util/extract.py Normal file
View file

@ -0,0 +1,44 @@
import os
import tarfile
import zipfile
import gzip
from lutris.util.log import logger
def extract_archive(path, to_directory='.'):
path = os.path.abspath(path)
logger.debug("Extracting %s to %s", path, to_directory)
if path.endswith('.zip'):
opener, mode = zipfile.ZipFile, 'r'
elif path.endswith('.tar.gz') or path.endswith('.tgz'):
opener, mode = tarfile.open, 'r:gz'
elif path.endswith('.tar.bz2') or path.endswith('.tbz'):
opener, mode = tarfile.open, 'r:bz2'
else:
raise ValueError(
"Could not extract `%s` as no appropriate extractor is found"
% path)
cwd = os.getcwd()
os.chdir(to_directory)
handler = opener(path, mode)
handler.extractall()
handler.close()
os.chdir(cwd)
def decompress_gz(file_path):
"""Decompress a gzip file"""
if file_path.endswith('.gz'):
dest_path = file_path[:-3]
else:
raise ValueError("unsupported file type")
f = gzip.open(file_path, 'rb')
file_content = f.read()
f.close()
dest_file = open(dest_path, 'wb')
dest_file.write(file_content)
dest_file.close()
return dest_path