mirror of
https://github.com/lutris/lutris
synced 2024-09-19 07:41:33 +00:00
Local install of snes9x
This commit is contained in:
parent
1c23f438c3
commit
344a1926ce
|
@ -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):
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
44
lutris/util/extract.py
Normal 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
|
Loading…
Reference in a new issue