From 2ef7a3e1d350caba5ce6719a342bab7011c9f9a4 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Tue, 29 Dec 2015 04:27:35 -0500 Subject: [PATCH 001/181] Add ZDoom support --- README.rst | 2 +- lutris/migrations/update_runners.py | 2 +- lutris/runners/__init__.py | 2 +- lutris/runners/zdoom.py | 44 ++++++++++++++++++++++ share/lutris/media/runner_icons/zdoom.png | Bin 0 -> 5552 bytes 5 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 lutris/runners/zdoom.py create mode 100644 share/lutris/media/runner_icons/zdoom.png diff --git a/README.rst b/README.rst index c033559ca..6a32bcd6b 100644 --- a/README.rst +++ b/README.rst @@ -45,6 +45,7 @@ We currently support the following runners: * Frotz * Jzintv * O2em +* ZDoom Runners that will be added in future versions of Lutris: @@ -162,4 +163,3 @@ You can always reach us on: * Twitter: https://twitter.com/LutrisGaming * Google+: https://plus.google.com/+LutrisNet * Email: contact@lutris.net - diff --git a/lutris/migrations/update_runners.py b/lutris/migrations/update_runners.py index 3b4ae999d..ae63dc06f 100644 --- a/lutris/migrations/update_runners.py +++ b/lutris/migrations/update_runners.py @@ -12,5 +12,5 @@ def migrate(): 'gens', 'hatari', 'jzintv', 'mame', 'mednafen', 'mess', 'mupen64plus', 'nulldc', 'o2em', 'osmose', 'pcsxr', 'reicast', 'ResidualVM', 'residualvm', 'scummvm', - 'snes9x', 'stella', 'vice', 'virtualjaguar']: + 'snes9x', 'stella', 'vice', 'virtualjaguar', 'zdoom']: shutil.rmtree(path) diff --git a/lutris/runners/__init__.py b/lutris/runners/__init__.py index c7fa6aa5b..1280b397b 100644 --- a/lutris/runners/__init__.py +++ b/lutris/runners/__init__.py @@ -19,7 +19,7 @@ __all__ = ( # Sega "osmose", "dgen", "reicast", # Misc legacy systems - "frotz", "jzintv", "o2em", + "frotz", "jzintv", "o2em", "zdoom" ) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py new file mode 100644 index 000000000..29df31b26 --- /dev/null +++ b/lutris/runners/zdoom.py @@ -0,0 +1,44 @@ +import os +from lutris import settings +from lutris.runners.runner import Runner + +class zdoom(Runner): + description = "ZDoom DOOM Game Engine" + human_name = "ZDoom" + platform = "PC" + game_options = [ + # TODO: Add options from http://zdoom.org/wiki/Command_line_parameters . + ] + runner_options = [ + # TODO: Add options from http://zdoom.org/wiki/Command_line_parameters . + ] + + def get_executable(self): + return os.path.join(settings.RUNNER_DIR, 'zdoom/zdoom') + + @property + def working_dir(self): + option = self.game_config.get('working_dir') + if option: + return option + if self.game_path: + return self.game_path + if self.game_exe: + return os.path.dirname(self.game_exe) + else: + return super(wine, self).working_dir + + def play(self): + command = [ + self.get_executable() + ] + + resolution = self.runner_config.get("resolution") + if resolution: + if resolution == 'desktop': + resolution = display.get_current_resolution() + width, height = resolution.split('x') + command.append("-width %s" % width) + command.append("-height %s" % height) + + return {'command': command} diff --git a/share/lutris/media/runner_icons/zdoom.png b/share/lutris/media/runner_icons/zdoom.png new file mode 100644 index 0000000000000000000000000000000000000000..8d9634ebef700d1c096b070e7130b65f410ae934 GIT binary patch literal 5552 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 Date: Mon, 11 Jan 2016 18:57:26 -0500 Subject: [PATCH 002/181] Add ZDoom configuration --- lutris/runners/zdoom.py | 66 ++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 29df31b26..6607a097e 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -7,10 +7,50 @@ class zdoom(Runner): human_name = "ZDoom" platform = "PC" game_options = [ - # TODO: Add options from http://zdoom.org/wiki/Command_line_parameters . + { + 'option': 'main_file', + 'type': 'file', + 'label': 'WAD file', + 'help': ("The game data, commonly called a WAD file.") + } ] runner_options = [ - # TODO: Add options from http://zdoom.org/wiki/Command_line_parameters . + { + "option": "2", + "label": "Pixel Doubling", + "type": "bool", + 'default': False + }, + { + "option": "4", + "label": "Pixel Quadrupling", + "type": "bool", + 'default': False + }, + { + "option": "nostartup", + "label": "Disable Startup Screens", + "type": "bool", + 'default': False + }, + { + "option": "nosound", + "label": "Disable Both Music and Sound Effects", + "type": "bool", + 'default': False, + }, + { + "option": "nosfx", + "label": "Disable Sound Effects", + "type": "bool", + 'default': False + }, + { + "option": "nomusic", + "label": "Disable Music", + "type": "bool", + 'default': False + } ] def get_executable(self): @@ -18,15 +58,8 @@ class zdoom(Runner): @property def working_dir(self): - option = self.game_config.get('working_dir') - if option: - return option - if self.game_path: - return self.game_path - if self.game_exe: - return os.path.dirname(self.game_exe) - else: - return super(wine, self).working_dir + return os.path.dirname(self.main_file) \ + or super(zdoom, self).working_dir def play(self): command = [ @@ -41,4 +74,15 @@ class zdoom(Runner): command.append("-width %s" % width) command.append("-height %s" % height) + # Append any boolean options. + boolOptions = ['nomusic', 'nosfx', 'nosound', '2', '4', 'nostartup'] + for option in boolOptions: + if self.runner_config.get(option): + command.append('-%s' % option) + + # Append the wad file to load, if provided. + wad = self.game_config.get('main_file') + if wad: + command.append('-iwad %s' % wad) + return {'command': command} From 31dc58216c1a8c5204731d710fd293c0f8793ec6 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Thu, 25 Feb 2016 03:36:30 -0800 Subject: [PATCH 003/181] Make sure setup.py runs with python2 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5e7c01f6a..16d2e950c 100755 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python2 # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- # # This program is free software: you can redistribute it and/or modify From 7ea6a259d58a6f637f3aca3893ec9da4e9a517be Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 26 Feb 2016 22:55:54 -0800 Subject: [PATCH 004/181] Make atari800 compliant with the base install method --- lutris/runners/atari800.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lutris/runners/atari800.py b/lutris/runners/atari800.py index 23c521741..d5e62e854 100644 --- a/lutris/runners/atari800.py +++ b/lutris/runners/atari800.py @@ -82,24 +82,24 @@ class atari800(Runner): } ] - def install(self): - success = super(atari800, self).install() - if not success: - return False - config_path = os.path.expanduser("~/.atari800") - if not os.path.exists(config_path): - os.makedirs(config_path) - bios_archive = os.path.join(config_path, 'atari800-bioses.zip') - dlg = DownloadDialog(self.bios_url, bios_archive) - dlg.run() - if not os.path.exists(bios_archive): - ErrorDialog("Could not download Atari800 BIOS archive") - return - extract.extract_archive(bios_archive, config_path) - os.remove(bios_archive) - config = LutrisConfig(runner_slug='atari800') - config.raw_runner_config.update({'bios_path': config_path}) - config.save() + def install(self, version=None, downloader=None, callback=None): + def on_runner_installed(): + config_path = system.create_folder("~/.atari800") + bios_archive = os.path.join(config_path, 'atari800-bioses.zip') + dlg = DownloadDialog(self.bios_url, bios_archive) + dlg.run() + if not os.path.exists(bios_archive): + ErrorDialog("Could not download Atari800 BIOS archive") + return + extract.extract_archive(bios_archive, config_path) + os.remove(bios_archive) + config = LutrisConfig(runner_slug='atari800') + config.raw_runner_config.update({'bios_path': config_path}) + config.save() + if callback: + callback() + + super(atari800, self).install(version, downloader, on_runner_installed) def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'atari800/bin/atari800') From 7c63d4c1cd6918c7aacf1fb16b554a359ac9a587 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 26 Feb 2016 22:56:26 -0800 Subject: [PATCH 005/181] Make o2em compliant with the base install method --- lutris/runners/o2em.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lutris/runners/o2em.py b/lutris/runners/o2em.py index 51037763b..0de8b0fd1 100644 --- a/lutris/runners/o2em.py +++ b/lutris/runners/o2em.py @@ -8,6 +8,7 @@ class o2em(Runner): human_name = "O2EM" description = "Magnavox Oyssey² Emulator" platform = "Magnavox Odyssey 2, Phillips Videopac+" + bios_path = os.path.expanduser("~/.o2em/bios") checksums = { 'o2rom': "562d5ebf9e030a40d6fabfc2f33139fd", @@ -73,18 +74,19 @@ class o2em(Runner): } ] - def install(self): - super(o2em, self).install() - bios_path = os.path.expanduser("~/.o2em/bios") - if not os.path.exists(bios_path): - os.makedirs(bios_path) + def install(self, version=None, downloader=None, callback=None): + def on_runner_installed(): + if not os.path.exists(self.bios_path): + os.makedirs(self.bios_path) + if callback: + callback() + super(o2em, self).install(version, downloader, on_runner_installed) def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'o2em/o2em') def play(self): - bios_path = os.path.join(os.path.expanduser("~"), ".o2em/bios/") - arguments = ["-biosdir=%s" % bios_path] + arguments = ["-biosdir=%s" % self.bios_path] if self.runner_config.get("fullscreen"): arguments.append("-fullscreen") From 3ef6e53f10ec524ae2d50f4f5cbacb6dccc26ec7 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 26 Feb 2016 23:01:21 -0800 Subject: [PATCH 006/181] Make hatari compliant with the base install method --- lutris/runners/hatari.py | 46 ++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/lutris/runners/hatari.py b/lutris/runners/hatari.py index 5316f7f8d..4c72d93cf 100644 --- a/lutris/runners/hatari.py +++ b/lutris/runners/hatari.py @@ -4,6 +4,7 @@ from lutris import settings from lutris.config import LutrisConfig from lutris.gui.dialogs import QuestionDialog, FileDialog from lutris.runners.runner import Runner +from lutris.util import system class hatari(Runner): @@ -99,31 +100,26 @@ class hatari(Runner): } ] - def install(self): - success = super(hatari, self).install() - if not success: - return False - config_path = os.path.expanduser('~/.hatari') - if not os.path.exists(config_path): - os.makedirs(config_path) - bios_path = os.path.expanduser('~/.hatari/bios') - if not os.path.exists(bios_path): - os.makedirs(bios_path) - dlg = QuestionDialog({ - 'question': "Do you want to select an Atari ST BIOS file?", - 'title': "Use BIOS file?", - }) - if dlg.result == dlg.YES: - bios_dlg = FileDialog("Select a BIOS file") - bios_filename = bios_dlg.filename - if not bios_filename: - return - shutil.copy(bios_filename, bios_path) - bios_path = os.path.join(bios_path, os.path.basename(bios_filename)) - config = LutrisConfig(runner_slug='hatari') - config.raw_runner_config.update({'bios_file': bios_path}) - config.save() - return True + def install(self, version=None, downloader=None, callback=None): + def on_runner_installed(): + bios_path = system.create_folder('~/.hatari/bios') + dlg = QuestionDialog({ + 'question': "Do you want to select an Atari ST BIOS file?", + 'title': "Use BIOS file?", + }) + if dlg.result == dlg.YES: + bios_dlg = FileDialog("Select a BIOS file") + bios_filename = bios_dlg.filename + if not bios_filename: + return + shutil.copy(bios_filename, bios_path) + bios_path = os.path.join(bios_path, os.path.basename(bios_filename)) + config = LutrisConfig(runner_slug='hatari') + config.raw_runner_config.update({'bios_file': bios_path}) + config.save() + if callback: + callback() + super(hatari, self).install() def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'hatari/bin/hatari') From a73c15e493a8bd789fba24d8bdec6e88560f34de Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 26 Feb 2016 23:06:15 -0800 Subject: [PATCH 007/181] Make pcsxr compliant with the base install method --- lutris/runners/pcsxr.py | 61 ++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/lutris/runners/pcsxr.py b/lutris/runners/pcsxr.py index ec59d5992..56a39456a 100644 --- a/lutris/runners/pcsxr.py +++ b/lutris/runners/pcsxr.py @@ -4,7 +4,7 @@ from lutris import settings from lutris.config import LutrisConfig from lutris.gui.dialogs import QuestionDialog, FileDialog from lutris.runners.runner import Runner -from lutris.util.system import find_executable +from lutris.util import system class pcsxr(Runner): @@ -51,42 +51,35 @@ class pcsxr(Runner): # System wide available emulator candidates = ('pcsx', 'pcsxr') for candidate in candidates: - executable = find_executable(candidate) + executable = system.find_executable(candidate) if executable: return executable - def install(self): - success = super(pcsxr, self).install() - if not success: - return False - config_path = os.path.expanduser('~/.pcsxr') - if not os.path.exists(config_path): - os.makedirs(config_path) - - # Bios - bios_path = os.path.expanduser('~/.pcsxr/bios') - if not os.path.exists(bios_path): - os.makedirs(bios_path) - dlg = QuestionDialog({ - 'question': ("Do you want to select a Playstation BIOS file?\n\n" - "The BIOS is the core code running the machine.\n" - "PCSX-Reloaded includes an emulated BIOS, but it is " - "still incomplete. \n" - "Using an original BIOS avoids some bugs and reduced " - "compatibility \n" - "with some games."), - 'title': "Use BIOS file?", - }) - if dlg.result == dlg.YES: - bios_dlg = FileDialog("Select a BIOS file") - bios_src = bios_dlg.filename - shutil.copy(bios_src, bios_path) - # Save bios in config - bios_path = os.path.join(bios_path, os.path.basename(bios_src)) - config = LutrisConfig(runner_slug='pcsxr') - config.raw_runner_config.update({'bios': bios_path}) - config.save() - return True + def install(self, version=None, downloader=None, callback=None): + def on_runner_installed(): + bios_path = system.create_folder('~/.pcsxr/bios') + dlg = QuestionDialog({ + 'question': ("Do you want to select a Playstation BIOS file?\n\n" + "The BIOS is the core code running the machine.\n" + "PCSX-Reloaded includes an emulated BIOS, but it is " + "still incomplete. \n" + "Using an original BIOS avoids some bugs and reduced " + "compatibility \n" + "with some games."), + 'title': "Use BIOS file?", + }) + if dlg.result == dlg.YES: + bios_dlg = FileDialog("Select a BIOS file") + bios_src = bios_dlg.filename + shutil.copy(bios_src, bios_path) + # Save bios in config + bios_path = os.path.join(bios_path, os.path.basename(bios_src)) + config = LutrisConfig(runner_slug='pcsxr') + config.raw_runner_config.update({'bios': bios_path}) + config.save() + if callback: + callback() + super(pcsxr, self).install(version, downloader, on_runner_installed) def play(self): """Run Playstation game.""" From 11e4ff9323d51f0d3371a64ebf4780180646c2ce Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 26 Feb 2016 23:16:16 -0800 Subject: [PATCH 008/181] Make Steam install method raise an error --- lutris/runners/steam.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lutris/runners/steam.py b/lutris/runners/steam.py index 85ec8e437..259c7a0e0 100644 --- a/lutris/runners/steam.py +++ b/lutris/runners/steam.py @@ -1,8 +1,8 @@ import os import time import subprocess +from lutris.runners import NonInstallableRunnerError from lutris.runners.runner import Runner -from lutris.gui.dialogs import NoticeDialog from lutris.thread import LutrisThread from lutris.util.log import logger from lutris.util import system @@ -152,11 +152,12 @@ class steam(Runner): return steamapps_paths[0] def install(self): - message = "Steam for Linux installation is not handled by Lutris.\n" \ + raise NonInstallableRunnerError( + "Steam for Linux installation is not handled by Lutris.\n" \ "Please go to " \ "http://steampowered.com" \ " or install Steam with the package provided by your distribution." - NoticeDialog(message) + ) def install_game(self, appid, generate_acf=False): logger.debug("Installing steam game %s", appid) From a5359817366c9580d84aa69d2b5d03083539af63 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 26 Feb 2016 23:39:59 -0800 Subject: [PATCH 009/181] Update WineSteam install method --- lutris/runners/winesteam.py | 40 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index c50846b07..495153273 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -31,18 +31,6 @@ def get_steam_installer_dest(): return os.path.join(settings.TMP_PATH, "SteamInstall.msi") -def download_steam(downloader=None, callback=None, callback_data=None): - """Downloads steam with `downloader` then calls `callback`""" - steam_installer_path = get_steam_installer_dest() - if not downloader: - dialog = DownloadDialog(STEAM_INSTALLER_URL, steam_installer_path) - dialog.run() - else: - downloader(STEAM_INSTALLER_URL, - steam_installer_path, callback, callback_data) - return steam_installer_path - - def is_running(): pid = system.get_pid('Steam.exe$') if pid: @@ -64,6 +52,7 @@ class winesteam(wine.wine): human_name = "Wine Steam" platform = "Steam for Windows" runnable_alone = True + depends_on = wine.wine game_options = [ { 'option': 'appid', @@ -224,17 +213,26 @@ class winesteam(wine.wine): if path: return path - def install(self, installer_path=None, version=None): - if not self.is_wine_installed(): - wine.wine().install(version=version) - prefix = self.get_or_create_default_prefix() - if not self.get_steam_path(): - if not installer_path: - installer_path = get_steam_installer_dest() - download_steam() + def install(self, version=None, downloader=None, callback=None): + installer_path = get_steam_installer_dest() + + def on_steam_downloaded(): + prefix = self.get_or_create_default_prefix() self.msi_exec(installer_path, quiet=True, prefix=prefix, wine_path=self.get_executable()) - return True + if callback: + callback() + + if not self.is_wine_installed(): + # FIXME find another way to do that (already fixed from the install game + # dialog) + wine.wine().install(version=version, downloader=downloader) + if downloader: + downloader(STEAM_INSTALLER_URL, installer_path, on_steam_downloaded) + else: + dialog = DownloadDialog(STEAM_INSTALLER_URL, installer_path) + dialog.run() + on_steam_downloaded() def is_wine_installed(self): return super(winesteam, self).is_installed() From c0b2b668ae845cac5a566b386e24fc8142f07c3d Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 27 Feb 2016 00:40:02 -0800 Subject: [PATCH 010/181] Install runner before starting installation --- lutris/gui/installgamedialog.py | 6 +- lutris/installer/commands.py | 25 ++++---- lutris/installer/interpreter.py | 109 ++++++++++++++++++-------------- lutris/runners/__init__.py | 8 +++ lutris/runners/runner.py | 25 +++++--- lutris/runners/wine.py | 3 +- lutris/util/system.py | 7 ++ 7 files changed, 109 insertions(+), 74 deletions(-) diff --git a/lutris/gui/installgamedialog.py b/lutris/gui/installgamedialog.py index e7fa9dab4..7151f7416 100644 --- a/lutris/gui/installgamedialog.py +++ b/lutris/gui/installgamedialog.py @@ -265,7 +265,7 @@ class InstallerDialog(Gtk.Window): def on_install_clicked(self, button): """Let the interpreter take charge of the next stages.""" button.hide() - self.interpreter.iter_game_files() + self.interpreter.check_runner_install() def ask_user_for_file(self, message): self.clean_widgets() @@ -315,8 +315,8 @@ class InstallerDialog(Gtk.Window): {'url': file_uri, 'dest': dest_file}, cancelable=True ) self.download_progress.cancel_button.hide() - callback_function = callback or self.on_download_complete - self.download_progress.connect('complete', callback_function, data) + callback = callback or self.on_download_complete + self.download_progress.connect('complete', callback, data) self.widget_box.pack_start(self.download_progress, False, False, 10) self.download_progress.show() self.download_progress.start() diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index cb4977822..b81419ebe 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -12,7 +12,7 @@ from lutris.util import extract, devices, system from lutris.util.fileio import EvilConfigParser, MultiOrderedDict from lutris.util.log import logger -from lutris.runners import wine, import_task, import_runner, InvalidRunner +from lutris.runners import wine, import_task, import_runner from lutris.thread import LutrisThread @@ -265,6 +265,15 @@ class CommandsMixin(object): dest_file.write(line) os.rename(tmp_filename, filename) + def _get_task_runner_and_name(self, task_name): + if '.' in task_name: + # Run a task from a different runner + # than the one for this installer + runner_name, task_name = task_name.split('.') + else: + runner_name = self.script["runner"] + return runner_name, task_name + def task(self, data): """Directive triggering another function specific to a runner. @@ -274,18 +283,8 @@ class CommandsMixin(object): self._check_required_params('name', data, 'task') if self.parent: GLib.idle_add(self.parent.cancel_button.set_sensitive, False) - task_name = data.pop('name') - if '.' in task_name: - # Run a task from a different runner - # than the one for this installer - runner_name, task_name = task_name.split('.') - else: - runner_name = self.script["runner"] - try: - runner_class = import_runner(runner_name) - except InvalidRunner: - GLib.idle_add(self.parent.cancel_button.set_sensitive, True) - raise ScriptingError('Invalid runner provided %s', runner_name) + runner_name, task_name = self._get_task_runner_and_name(data.pop('name')) + runner_class = import_runner(runner_name) runner = runner_class() # Check/install Wine runner at version specified in the script diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index 539524366..2dd704d38 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -19,7 +19,11 @@ from lutris.util.log import logger from lutris.util.steam import get_app_state_log from lutris.config import LutrisConfig, make_game_config_id -from lutris.runners import wine, winesteam, steam + +from lutris.runners import ( + wine, winesteam, steam, import_runner, + InvalidRunner, NonInstallableRunnerError, RunnerInstallationError +) def fetch_script(game_ref): @@ -53,6 +57,7 @@ class ScriptInterpreter(CommandsMixin): self.user_inputs = [] self.steam_data = {} self.script = script + self.runners_to_install = [] if not self.script: return if not self.is_valid(): @@ -268,37 +273,58 @@ class ScriptInterpreter(CommandsMixin): self.steam_data['platform'] = "linux" self.install_steam_game(steam.steam, is_game_files=True) - def check_steam_install(self): - """Checks that the required version of Steam is installed. - Return a boolean indicating whether is it or not. + def check_runner_install(self): + """Check if the runner is installed before starting the installation + Install the required runner(s) if necessary. This should handle runner + dependencies (wine for winesteam) or runners used for installer tasks. """ - if self.steam_data['platform'] == 'windows': - # Check that wine is installed - wine_runner = wine.wine() - if not wine_runner.is_installed(): - logger.debug('Wine is not installed') - wine_runner.install( - downloader=self.parent.start_download, - callback=self.check_steam_install + required_runners = [] + runner = self.get_runner_class(self.runner) + if runner.depends_on is not None: + required_runners.append(runner.depends_on()) + required_runners.append(runner()) + + for command in self.script.get('installer', []): + command_name, command_params = self._get_command_name_and_params(command) + if command_name == 'task': + runner_name, _task_name = self._get_task_runner_and_name( + command_params['name'] ) - return False - # Getting data from Wine Steam - steam_runner = winesteam.winesteam() - if not steam_runner.is_installed(): - logger.debug('Winesteam not installed') - winesteam.download_steam( - downloader=self.parent.start_download, - callback=self.on_steam_downloaded - ) - return False - return True + runner_names = [r.name for r in required_runners] + if runner_name not in runner_names: + required_runners.append(self.get_runner_class(runner_name)()) + + for runner in required_runners: + if not runner.is_installed(): + self.runners_to_install.append(runner) + self.install_runners() + + def install_runners(self): + if not self.runners_to_install: + self.iter_game_files() else: - steam_runner = steam.steam() - if not steam_runner.is_installed(): - raise ScriptingError( - "Install Steam for Linux and start installer again" - ) - return True + runner = self.runners_to_install.pop(0) + self.install_runner(runner) + + def install_runner(self, runner): + logger.debug('Installing {}'.format(runner.name)) + try: + runner.install( + version=None, # FIXME set to the correct wine version if any + downloader=self.parent.start_download, + callback=self.install_runners + ) + except (NonInstallableRunnerError, RunnerInstallationError) as ex: + logger.error(ex.message) + raise ScriptingError(ex.message) + + def get_runner_class(self, runner_name): + try: + runner = import_runner(runner_name) + except InvalidRunner: + GLib.idle_add(self.parent.cancel_button.set_sensitive, True) + raise ScriptingError('Invalid runner provided %s', runner_name) + return runner def file_selected(self, file_path): file_id = self.current_file_id @@ -358,9 +384,7 @@ class ScriptInterpreter(CommandsMixin): else: self._finish_install() - def _map_command(self, command_data): - """Map a directive from the `installer` section to an internal - method.""" + def _get_command_name_and_params(self, command_data): if isinstance(command_data, dict): command_name = command_data.keys()[0] command_params = command_data[command_name] @@ -369,6 +393,12 @@ class ScriptInterpreter(CommandsMixin): command_params = {} command_name = command_name.replace("-", "_") command_name = command_name.strip("_") + return command_name, command_params + + def _map_command(self, command_data): + """Map a directive from the `installer` section to an internal + method.""" + command_name, command_params = self._get_command_name_and_params(command_data) if not hasattr(self, command_name): raise ScriptingError("The command %s does not exists" % command_name) @@ -558,9 +588,6 @@ class ScriptInterpreter(CommandsMixin): # Check if Steam is installed, save the method's arguments so it can # be called again once Steam is installed. self.steam_data['callback_args'] = (runner_class, is_game_files) - is_installed = self.check_steam_install() - if not is_installed: - return 'STOP' steam_runner = self._get_steam_runner(runner_class) self.steam_data['is_game_files'] = is_game_files @@ -642,18 +669,6 @@ class ScriptInterpreter(CommandsMixin): os.path.join(data_path, self.steam_data['steam_rel_path']) self.iter_game_files() - def on_steam_downloaded(self, *args): - logger.debug("Steam downloaded") - dest = winesteam.get_steam_installer_dest() - winesteam_runner = winesteam.winesteam() - AsyncCall(winesteam_runner.install, self.on_winesteam_installed, dest) - - def on_winesteam_installed(self, *args): - logger.debug("Winesteam installed") - callback_args = self.steam_data['callback_args'] - self.parent.add_spinner() - self.install_steam_game(*callback_args) - def eject_wine_disc(self): prefix = self.target_path wine_path = wine.get_wine_version_exe(self._get_wine_version()) diff --git a/lutris/runners/__init__.py b/lutris/runners/__init__.py index 82903db70..9cad66842 100644 --- a/lutris/runners/__init__.py +++ b/lutris/runners/__init__.py @@ -27,6 +27,14 @@ class InvalidRunner(Exception): pass +class RunnerInstallationError(Exception): + pass + + +class NonInstallableRunnerError(Exception): + pass + + def get_runner_module(runner_name): if runner_name not in __all__: raise InvalidRunner("Invalid runner name '%s'", runner_name) diff --git a/lutris/runners/runner.py b/lutris/runners/runner.py index f2b53160d..6671767f9 100644 --- a/lutris/runners/runner.py +++ b/lutris/runners/runner.py @@ -15,6 +15,7 @@ from lutris.util.extract import extract_archive from lutris.util.log import logger from lutris.util import system from lutris.util.http import Request +from lutris.runners import RunnerInstallationError def get_arch(): @@ -37,6 +38,7 @@ class Runner(object): runner_options = [] system_options_override = [] context_menu_entries = [] + depends_on = None def __init__(self, config=None): """Initialize runner.""" @@ -202,7 +204,7 @@ class Runner(object): response_content = response.json if response_content: versions = response_content.get('versions') or [] - arch = get_arch() + arch = 'i386' if version: if version.endswith('-i386') or version.endswith('-x86_64'): version, arch = version.rsplit('-', 1) @@ -234,10 +236,16 @@ class Runner(object): def install(self, version=None, downloader=None, callback=None): """Install runner using package management systems.""" + logger.debug("Installing %s (version=%s, downloader=%s, callback=%s)", + self.name, version, downloader, callback) runner_info = self.get_runner_info(version) if not runner_info: + raise RunnerInstallationError( + '{} is not available for the {} architecture'.format( + self.name, self.arch + ) + ) dialogs.ErrorDialog( - 'This runner is not available for your platform' ) return False opts = {} @@ -253,8 +261,7 @@ class Runner(object): opts['dest'] = os.path.join(settings.RUNNER_DIR, self.name, dirname) url = runner_info['url'] - is_extracted = self.download_and_extract(url, **opts) - return is_extracted + self.download_and_extract(url, **opts) def download_and_extract(self, url, dest=None, **opts): merge_single = opts.get('merge_single', False) @@ -271,12 +278,12 @@ class Runner(object): 'merge_single': merge_single, 'callback': callback } + print "LAUNCHING DOWNLOADER" downloader(url, runner_archive, self.on_downloaded, extract_args) else: dialog = dialogs.DownloadDialog(url, runner_archive) dialog.run() - return self.extract(archive=runner_archive, dest=dest, - merge_single=merge_single) + self.extract(archive=runner_archive, dest=dest, merge_single=merge_single) def on_downloaded(self, widget, data, user_data): """GObject callback received by downloader""" @@ -285,14 +292,12 @@ class Runner(object): def extract(self, archive=None, dest=None, merge_single=None, callback=None): if not os.path.exists(archive): - logger.error("Can't find %s, aborting install", archive) - return False + # TODO Check install methods to catch RunnerInstallationError + raise RunnerInstallationError("Failed to extract {}", archive) extract_archive(archive, dest, merge_single=merge_single) os.remove(archive) if callback: callback() - else: - return True def remove_game_data(self, game_path=None): system.remove_folder(game_path) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index a61cb9fce..5f9988009 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -68,7 +68,8 @@ def create_prefix(prefix, wine_dir=None, arch='win32'): } system.execute([wineboot_path], env=env) if not os.path.exists(os.path.join(prefix, 'system.reg')): - logger.error('No system.reg found after prefix creation. Prefix might not be valid') + logger.error('No system.reg found after prefix creation. ' + 'Prefix might not be valid') logger.info('%s Prefix created in %s', arch, prefix) if prefix: diff --git a/lutris/util/system.py b/lutris/util/system.py index 3a9fba808..b072eac46 100644 --- a/lutris/util/system.py +++ b/lutris/util/system.py @@ -146,6 +146,13 @@ def remove_folder(path): shutil.rmtree(path) +def create_folder(path): + path = os.path.expanduser(path) + if not os.path.exists(path): + os.makedirs(path) + return path + + def is_removeable(path, excludes=None): """Check if a folder is safe to remove (not system or home, ...)""" if not path: From 0644aa8fa247b73470461db19d38aead998bec0c Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 27 Feb 2016 00:59:05 -0800 Subject: [PATCH 011/181] Remove code to install runner before tasks + install correct wine version + callback fixes --- lutris/installer/commands.py | 17 ++--------------- lutris/installer/interpreter.py | 4 ++-- lutris/runners/atari800.py | 2 +- lutris/runners/hatari.py | 2 +- lutris/runners/o2em.py | 2 +- lutris/runners/pcsxr.py | 2 +- lutris/runners/winesteam.py | 2 +- 7 files changed, 9 insertions(+), 22 deletions(-) diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index b81419ebe..0ecf23729 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -22,7 +22,7 @@ class CommandsMixin(object): def __init__(self): raise RuntimeError("Don't instanciate this class, it's a mixin!!!!!!!!!!!!!!!!") - def _get_wine_version(self): + def _get_runner_version(self): if self.script.get('wine'): return wine.support_legacy_version(self.script['wine'].get('version')) @@ -284,29 +284,16 @@ class CommandsMixin(object): if self.parent: GLib.idle_add(self.parent.cancel_button.set_sensitive, False) runner_name, task_name = self._get_task_runner_and_name(data.pop('name')) - runner_class = import_runner(runner_name) - runner = runner_class() # Check/install Wine runner at version specified in the script # TODO : move this, the runner should be installed before the install # starts wine_version = None if runner_name == 'wine': - wine_version = self._get_wine_version() + wine_version = self._get_runner_version() if wine_version and task_name == 'wineexec': - if not wine.is_version_installed(wine_version): - Gdk.threads_init() - Gdk.threads_enter() - runner.install(wine_version) - Gdk.threads_leave() data['wine_path'] = wine.get_wine_version_exe(wine_version) - # Check/install other runner - elif not runner.is_installed(): - Gdk.threads_init() - Gdk.threads_enter() - runner.install() - Gdk.threads_leave() for key in data: data[key] = self._substitute(data[key]) diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index 2dd704d38..32fa66133 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -310,7 +310,7 @@ class ScriptInterpreter(CommandsMixin): logger.debug('Installing {}'.format(runner.name)) try: runner.install( - version=None, # FIXME set to the correct wine version if any + version=self._get_runner_version(), downloader=self.parent.start_download, callback=self.install_runners ) @@ -671,5 +671,5 @@ class ScriptInterpreter(CommandsMixin): def eject_wine_disc(self): prefix = self.target_path - wine_path = wine.get_wine_version_exe(self._get_wine_version()) + wine_path = wine.get_wine_version_exe(self._get_runner_version()) wine.eject_disc(wine_path, prefix) diff --git a/lutris/runners/atari800.py b/lutris/runners/atari800.py index d5e62e854..363539094 100644 --- a/lutris/runners/atari800.py +++ b/lutris/runners/atari800.py @@ -83,7 +83,7 @@ class atari800(Runner): ] def install(self, version=None, downloader=None, callback=None): - def on_runner_installed(): + def on_runner_installed(*args): config_path = system.create_folder("~/.atari800") bios_archive = os.path.join(config_path, 'atari800-bioses.zip') dlg = DownloadDialog(self.bios_url, bios_archive) diff --git a/lutris/runners/hatari.py b/lutris/runners/hatari.py index 4c72d93cf..2b111d722 100644 --- a/lutris/runners/hatari.py +++ b/lutris/runners/hatari.py @@ -101,7 +101,7 @@ class hatari(Runner): ] def install(self, version=None, downloader=None, callback=None): - def on_runner_installed(): + def on_runner_installed(*args): bios_path = system.create_folder('~/.hatari/bios') dlg = QuestionDialog({ 'question': "Do you want to select an Atari ST BIOS file?", diff --git a/lutris/runners/o2em.py b/lutris/runners/o2em.py index 0de8b0fd1..3ad863b59 100644 --- a/lutris/runners/o2em.py +++ b/lutris/runners/o2em.py @@ -75,7 +75,7 @@ class o2em(Runner): ] def install(self, version=None, downloader=None, callback=None): - def on_runner_installed(): + def on_runner_installed(*args): if not os.path.exists(self.bios_path): os.makedirs(self.bios_path) if callback: diff --git a/lutris/runners/pcsxr.py b/lutris/runners/pcsxr.py index 56a39456a..06b128ea9 100644 --- a/lutris/runners/pcsxr.py +++ b/lutris/runners/pcsxr.py @@ -56,7 +56,7 @@ class pcsxr(Runner): return executable def install(self, version=None, downloader=None, callback=None): - def on_runner_installed(): + def on_runner_installed(*args): bios_path = system.create_folder('~/.pcsxr/bios') dlg = QuestionDialog({ 'question': ("Do you want to select a Playstation BIOS file?\n\n" diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index 495153273..d1354075c 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -216,7 +216,7 @@ class winesteam(wine.wine): def install(self, version=None, downloader=None, callback=None): installer_path = get_steam_installer_dest() - def on_steam_downloaded(): + def on_steam_downloaded(*args): prefix = self.get_or_create_default_prefix() self.msi_exec(installer_path, quiet=True, prefix=prefix, wine_path=self.get_executable()) From bcf0f71adc38e24857bb2256bc95720f3ff9dd7d Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 27 Feb 2016 01:09:31 -0800 Subject: [PATCH 012/181] Add callback info for Hatari --- lutris/runners/hatari.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lutris/runners/hatari.py b/lutris/runners/hatari.py index 2b111d722..7eaa897d4 100644 --- a/lutris/runners/hatari.py +++ b/lutris/runners/hatari.py @@ -119,7 +119,9 @@ class hatari(Runner): config.save() if callback: callback() - super(hatari, self).install() + super(hatari, self).install(version=version, + downloader=downloader, + callback=on_runner_installed) def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'hatari/bin/hatari') From ee06cc0d121a9bca59d6636d9dbaf9ea6f6247a0 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 27 Feb 2016 01:10:12 -0800 Subject: [PATCH 013/181] Don't default to i386 for runners other than wine --- lutris/runners/runner.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lutris/runners/runner.py b/lutris/runners/runner.py index 6671767f9..b6c7005f0 100644 --- a/lutris/runners/runner.py +++ b/lutris/runners/runner.py @@ -204,7 +204,10 @@ class Runner(object): response_content = response.json if response_content: versions = response_content.get('versions') or [] - arch = 'i386' + if self.name == 'wine': + arch = 'i386' + else: + arch = self.arch if version: if version.endswith('-i386') or version.endswith('-x86_64'): version, arch = version.rsplit('-', 1) From 405fb3016ed4259062ca3f11865770d36ea5ac6a Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 27 Feb 2016 01:10:37 -0800 Subject: [PATCH 014/181] Launch callback for runner installers without a downloader --- lutris/runners/runner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lutris/runners/runner.py b/lutris/runners/runner.py index b6c7005f0..93e101006 100644 --- a/lutris/runners/runner.py +++ b/lutris/runners/runner.py @@ -281,12 +281,13 @@ class Runner(object): 'merge_single': merge_single, 'callback': callback } - print "LAUNCHING DOWNLOADER" downloader(url, runner_archive, self.on_downloaded, extract_args) else: dialog = dialogs.DownloadDialog(url, runner_archive) dialog.run() self.extract(archive=runner_archive, dest=dest, merge_single=merge_single) + if callback: + callback() def on_downloaded(self, widget, data, user_data): """GObject callback received by downloader""" From d245c04b0a878d8162314e0ddaee8315feb43ee5 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 27 Feb 2016 01:11:53 -0800 Subject: [PATCH 015/181] Launch callback for runner installers without a downloader (bis) --- lutris/runners/runner.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lutris/runners/runner.py b/lutris/runners/runner.py index 93e101006..e2c873c50 100644 --- a/lutris/runners/runner.py +++ b/lutris/runners/runner.py @@ -285,9 +285,8 @@ class Runner(object): else: dialog = dialogs.DownloadDialog(url, runner_archive) dialog.run() - self.extract(archive=runner_archive, dest=dest, merge_single=merge_single) - if callback: - callback() + self.extract(archive=runner_archive, dest=dest, merge_single=merge_single, + callback=callback) def on_downloaded(self, widget, data, user_data): """GObject callback received by downloader""" From 970f0486b398e4299532982e5442a960f48b5080 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Tue, 1 Mar 2016 12:24:28 +0100 Subject: [PATCH 016/181] Typo --- lutris/installer/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index 32fa66133..f0ed8ff56 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -400,7 +400,7 @@ class ScriptInterpreter(CommandsMixin): method.""" command_name, command_params = self._get_command_name_and_params(command_data) if not hasattr(self, command_name): - raise ScriptingError("The command %s does not exists" + raise ScriptingError('The command "%s" does not exist.' % command_name) return getattr(self, command_name), command_params From dc5d13439b71083517828404cd95e6adf82a7a5f Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 1 Mar 2016 21:00:29 -0800 Subject: [PATCH 017/181] Update koku-xinput-wine path to the lib bundled in the runtime --- lutris/runners/wine.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 5f9988009..997749676 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -1,5 +1,4 @@ import os -import time import shlex import subprocess @@ -640,11 +639,10 @@ class wine(Runner): return system.get_pids_using_file(exe) def get_xinput_path(self): - xinput_path = os.path.abspath( - os.path.join(datapath.get(), 'lib/koku-xinput-wine.so') - ) - logger.debug('Preloading %s', xinput_path) - return xinput_path + xinput_path = os.path.join(settings.RUNTIME_DIR, + 'lib32/koku-xinput-wine/koku-xinput-wine.so') + if os.path.exists(xinput_path): + return xinput_path def play(self): game_exe = self.game_exe @@ -657,7 +655,12 @@ class wine(Runner): launch_info['env'] = self.get_env(full=False) if self.runner_config.get('xinput'): - launch_info['ld_preload'] = self.get_xinput_path() + xinput_path = self.get_xinput_path() + if xinput_path: + logger.debug('Preloading %s', xinput_path) + launch_info['ld_preload'] = self.get_xinput_path() + else: + logger.error('Missing koku-xinput-wine.so, Xinput won\'t be enabled') command = [self.get_executable()] if game_exe.endswith(".msi"): From f178e8c04a39abf83989bad671b4595657f48079 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Thu, 3 Mar 2016 17:58:50 +0100 Subject: [PATCH 018/181] Fix one-line "execute" installer command --- lutris/installer/commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index 0ecf23729..37fe60815 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -52,14 +52,17 @@ class CommandsMixin(object): def execute(self, data): """Run an executable file.""" args = [] + terminal = None if isinstance(data, dict): self._check_required_params('file', data, 'execute') file_ref = data['file'] args_string = data.get('args', '') for arg in shlex.split(args_string): args.append(self._substitute(arg)) + terminal = data.get('terminal') else: file_ref = data + # Determine whether 'file' value is a file id or a path exec_path = self._get_file(file_ref) or self._substitute(file_ref) if not exec_path: @@ -70,7 +73,6 @@ class CommandsMixin(object): exec_path) self.chmodx(exec_path) - terminal = data.get('terminal') if terminal: terminal = system.get_default_terminal() From 09b0a526593aa87df3ddae1c8fa9c39bcc92561e Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 06:01:12 -0800 Subject: [PATCH 019/181] This is not how strip should be used --- lutris/runners/wine.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 997749676..000b2f036 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -505,11 +505,13 @@ class wine(Runner): def system_wine_version(self): """Return the version of Wine installed on the system.""" try: - version = subprocess.check_output(["wine", "--version"]) + version = subprocess.check_output(["wine", "--version"]).strip() except OSError: return "not installed" else: - return version.strip('wine-\n') + if version.startswith('wine-'): + version = version[5:] + return version @property def wine_arch(self): From 290fb1720b58db69149c974061dc7a33c7418dcc Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 08:28:35 -0800 Subject: [PATCH 020/181] Add support for WineHQ devel and staging --- lutris/runners/wine.py | 66 ++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 000b2f036..120f0be2f 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -12,6 +12,11 @@ from lutris.runners.runner import Runner from lutris.thread import LutrisThread WINE_DIR = os.path.join(settings.RUNNER_DIR, "wine") +WINE_PATHS = { + 'winehq-devel': '/opt/wine-devel/bin/wine', + 'winehq-staging': '/opt/wine-staging/bin/wine', + 'system': 'wine', +} def set_regedit(path, key, value='', type='REG_SZ', wine_path=None, @@ -249,6 +254,18 @@ def get_default_version(): return installed_versions[0] +def get_system_wine_version(wine_path="wine"): + """Return the version of Wine installed on the system.""" + try: + version = subprocess.check_output([wine_path, "--version"]).strip() + except OSError: + return + else: + if version.startswith('wine-'): + version = version[5:] + return version + + def support_legacy_version(version): """Since Lutris 0.3.7, wine version contains architecture and optional info. Call this to keep existing games compatible with previous @@ -341,11 +358,22 @@ class wine(Runner): ] def get_wine_version_choices(): - return ( - [('System (%s)' % self.system_wine_version, 'system')] + - [('Custom (select executable below)', 'custom')] + - [(version, version) for version in get_wine_versions()] + versions = [] + labels = { + 'winehq-devel': 'WineHQ devel (%s)', + 'winehq-staging': 'WineHQ staging (%s)', + 'system': 'System (%s)', + } + for build in sorted(WINE_PATHS.keys()): + version = get_system_wine_version(WINE_PATHS[build]) + if version: + versions.append((labels[build] % version, build)) + + versions.append( + ('Custom (select executable below)', 'custom') ) + versions += [(v, v) for v in get_wine_versions()] + return versions self.runner_options = [ { @@ -501,18 +529,6 @@ class wine(Runner): else: return super(wine, self).working_dir - @property - def system_wine_version(self): - """Return the version of Wine installed on the system.""" - try: - version = subprocess.check_output(["wine", "--version"]).strip() - except OSError: - return "not installed" - else: - if version.startswith('wine-'): - version = version[5:] - return version - @property def wine_arch(self): """Return the wine architecture. @@ -541,9 +557,9 @@ class wine(Runner): if not version: return - if version == 'system': - if system.find_executable('wine'): - return 'wine' + if version in WINE_PATHS.keys(): + if system.find_executable(WINE_PATHS[version]): + return WINE_PATHS[version] # Fall back on bundled Wine version = get_default_version() elif version == 'custom': @@ -554,18 +570,6 @@ class wine(Runner): return os.path.join(path, version, 'bin/wine') def is_installed(self): - version = self.get_version() - if version == 'system': - if system.find_executable('wine'): - return True - else: - return False - elif version == 'custom': - custom_path = self.runner_config.get('custom_wine_path', '') - if os.path.exists(custom_path): - return True - else: - return False executable = self.get_executable() if executable: return os.path.exists(executable) From dfd96df9f708d6fbfe6e43a825d50cbba8bc566e Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 14:15:25 -0800 Subject: [PATCH 021/181] Add Xephyr support in system options --- lutris/game.py | 19 ++++++++++++++++++- lutris/sysoptions.py | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lutris/game.py b/lutris/game.py index b08a3c15a..d4640fb2d 100644 --- a/lutris/game.py +++ b/lutris/game.py @@ -166,6 +166,9 @@ class Game(object): system_config = self.runner.system_config self.original_outputs = display.get_outputs() gameplay_info = self.runner.play() + + env = {} + logger.debug("Launching %s: %s" % (self.name, gameplay_info)) if 'error' in gameplay_info: show_error_message(gameplay_info) @@ -199,6 +202,21 @@ class Game(object): if primusrun and system.find_executable('primusrun'): launch_arguments.insert(0, 'primusrun') + xephyr = system_config.get('xephyr') or 'off' + if xephyr != 'off': + if xephyr == '8bpp': + xephyr_depth = '8' + else: + xephyr_depth = '16' + xephyr_resolution = system_config.get('xephyr_resolution') or '640x480' + xephyr_command = ['Xephyr', ':2', '-ac', '-screen', + xephyr_resolution + 'x' + xephyr_depth, '-glamor', + '-reset', '-terminate', '-fullscreen'] + xephyr_thread = LutrisThread(xephyr_command) + xephyr_thread.start() + time.sleep(3) + env['DISPLAY'] = ':2' + prefix_command = system_config.get("prefix_command") or '' if prefix_command.strip(): launch_arguments.insert(0, prefix_command) @@ -214,7 +232,6 @@ class Game(object): self.state = self.STATE_STOPPED return # Env vars - env = {} game_env = gameplay_info.get('env') or {} env.update(game_env) system_env = system_config.get('env') or {} diff --git a/lutris/sysoptions.py b/lutris/sysoptions.py index f2d91fd77..01095e8db 100644 --- a/lutris/sysoptions.py +++ b/lutris/sysoptions.py @@ -150,6 +150,25 @@ system_options = [ 'condition': system.find_executable('xboxdrv'), 'help': ("Command line options for xboxdrv, a driver for XBOX 360" "controllers. Requires the xboxdrv package installed.") + }, + { + 'option': 'xephyr', + 'type': 'choice', + 'label': "Use Xephyr", + 'type': 'choice', + 'choices': ( + ('Off', 'off'), + ('8BPP (256 colors)', '8bpp'), + ('16BPP (65536 colors)', '16bpp') + ), + 'default': 'off', + 'advanced': True, + 'help': "Run program in Xephyr to support 8BPP and 16BPP color modes", + }, + { + 'option': 'xephyr_resolution', + 'type': 'string', + 'label': 'Xephyr resolution' } ] From d077965307597e21c751bf3d41f4dd8f9b3cf9e3 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Tue, 1 Mar 2016 12:24:28 +0100 Subject: [PATCH 022/181] Typo --- lutris/installer/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index 32fa66133..f0ed8ff56 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -400,7 +400,7 @@ class ScriptInterpreter(CommandsMixin): method.""" command_name, command_params = self._get_command_name_and_params(command_data) if not hasattr(self, command_name): - raise ScriptingError("The command %s does not exists" + raise ScriptingError('The command "%s" does not exist.' % command_name) return getattr(self, command_name), command_params From 00c261f6813a495f73529b0ed80e88a1f9b74be0 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 1 Mar 2016 21:00:29 -0800 Subject: [PATCH 023/181] Update koku-xinput-wine path to the lib bundled in the runtime --- lutris/runners/wine.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 5f9988009..997749676 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -1,5 +1,4 @@ import os -import time import shlex import subprocess @@ -640,11 +639,10 @@ class wine(Runner): return system.get_pids_using_file(exe) def get_xinput_path(self): - xinput_path = os.path.abspath( - os.path.join(datapath.get(), 'lib/koku-xinput-wine.so') - ) - logger.debug('Preloading %s', xinput_path) - return xinput_path + xinput_path = os.path.join(settings.RUNTIME_DIR, + 'lib32/koku-xinput-wine/koku-xinput-wine.so') + if os.path.exists(xinput_path): + return xinput_path def play(self): game_exe = self.game_exe @@ -657,7 +655,12 @@ class wine(Runner): launch_info['env'] = self.get_env(full=False) if self.runner_config.get('xinput'): - launch_info['ld_preload'] = self.get_xinput_path() + xinput_path = self.get_xinput_path() + if xinput_path: + logger.debug('Preloading %s', xinput_path) + launch_info['ld_preload'] = self.get_xinput_path() + else: + logger.error('Missing koku-xinput-wine.so, Xinput won\'t be enabled') command = [self.get_executable()] if game_exe.endswith(".msi"): From 4013ac5d9ab33e127e2686e6fa8fe83ab1e3441f Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Thu, 3 Mar 2016 17:58:50 +0100 Subject: [PATCH 024/181] Fix one-line "execute" installer command --- lutris/installer/commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index 0ecf23729..37fe60815 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -52,14 +52,17 @@ class CommandsMixin(object): def execute(self, data): """Run an executable file.""" args = [] + terminal = None if isinstance(data, dict): self._check_required_params('file', data, 'execute') file_ref = data['file'] args_string = data.get('args', '') for arg in shlex.split(args_string): args.append(self._substitute(arg)) + terminal = data.get('terminal') else: file_ref = data + # Determine whether 'file' value is a file id or a path exec_path = self._get_file(file_ref) or self._substitute(file_ref) if not exec_path: @@ -70,7 +73,6 @@ class CommandsMixin(object): exec_path) self.chmodx(exec_path) - terminal = data.get('terminal') if terminal: terminal = system.get_default_terminal() From 066cdb079e5a4620f0a094f3c586a18de15cd57c Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 06:01:12 -0800 Subject: [PATCH 025/181] This is not how strip should be used --- lutris/runners/wine.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 997749676..000b2f036 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -505,11 +505,13 @@ class wine(Runner): def system_wine_version(self): """Return the version of Wine installed on the system.""" try: - version = subprocess.check_output(["wine", "--version"]) + version = subprocess.check_output(["wine", "--version"]).strip() except OSError: return "not installed" else: - return version.strip('wine-\n') + if version.startswith('wine-'): + version = version[5:] + return version @property def wine_arch(self): From 1303767a39ecc6835874ca1e48cb36fbd079e11b Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 08:28:35 -0800 Subject: [PATCH 026/181] Add support for WineHQ devel and staging --- lutris/runners/wine.py | 66 ++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 000b2f036..120f0be2f 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -12,6 +12,11 @@ from lutris.runners.runner import Runner from lutris.thread import LutrisThread WINE_DIR = os.path.join(settings.RUNNER_DIR, "wine") +WINE_PATHS = { + 'winehq-devel': '/opt/wine-devel/bin/wine', + 'winehq-staging': '/opt/wine-staging/bin/wine', + 'system': 'wine', +} def set_regedit(path, key, value='', type='REG_SZ', wine_path=None, @@ -249,6 +254,18 @@ def get_default_version(): return installed_versions[0] +def get_system_wine_version(wine_path="wine"): + """Return the version of Wine installed on the system.""" + try: + version = subprocess.check_output([wine_path, "--version"]).strip() + except OSError: + return + else: + if version.startswith('wine-'): + version = version[5:] + return version + + def support_legacy_version(version): """Since Lutris 0.3.7, wine version contains architecture and optional info. Call this to keep existing games compatible with previous @@ -341,11 +358,22 @@ class wine(Runner): ] def get_wine_version_choices(): - return ( - [('System (%s)' % self.system_wine_version, 'system')] + - [('Custom (select executable below)', 'custom')] + - [(version, version) for version in get_wine_versions()] + versions = [] + labels = { + 'winehq-devel': 'WineHQ devel (%s)', + 'winehq-staging': 'WineHQ staging (%s)', + 'system': 'System (%s)', + } + for build in sorted(WINE_PATHS.keys()): + version = get_system_wine_version(WINE_PATHS[build]) + if version: + versions.append((labels[build] % version, build)) + + versions.append( + ('Custom (select executable below)', 'custom') ) + versions += [(v, v) for v in get_wine_versions()] + return versions self.runner_options = [ { @@ -501,18 +529,6 @@ class wine(Runner): else: return super(wine, self).working_dir - @property - def system_wine_version(self): - """Return the version of Wine installed on the system.""" - try: - version = subprocess.check_output(["wine", "--version"]).strip() - except OSError: - return "not installed" - else: - if version.startswith('wine-'): - version = version[5:] - return version - @property def wine_arch(self): """Return the wine architecture. @@ -541,9 +557,9 @@ class wine(Runner): if not version: return - if version == 'system': - if system.find_executable('wine'): - return 'wine' + if version in WINE_PATHS.keys(): + if system.find_executable(WINE_PATHS[version]): + return WINE_PATHS[version] # Fall back on bundled Wine version = get_default_version() elif version == 'custom': @@ -554,18 +570,6 @@ class wine(Runner): return os.path.join(path, version, 'bin/wine') def is_installed(self): - version = self.get_version() - if version == 'system': - if system.find_executable('wine'): - return True - else: - return False - elif version == 'custom': - custom_path = self.runner_config.get('custom_wine_path', '') - if os.path.exists(custom_path): - return True - else: - return False executable = self.get_executable() if executable: return os.path.exists(executable) From add4eeb66b81bab506cc5b16c3e1f480c58a6cf5 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 14:15:25 -0800 Subject: [PATCH 027/181] Add Xephyr support in system options --- lutris/game.py | 19 ++++++++++++++++++- lutris/sysoptions.py | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lutris/game.py b/lutris/game.py index b08a3c15a..d4640fb2d 100644 --- a/lutris/game.py +++ b/lutris/game.py @@ -166,6 +166,9 @@ class Game(object): system_config = self.runner.system_config self.original_outputs = display.get_outputs() gameplay_info = self.runner.play() + + env = {} + logger.debug("Launching %s: %s" % (self.name, gameplay_info)) if 'error' in gameplay_info: show_error_message(gameplay_info) @@ -199,6 +202,21 @@ class Game(object): if primusrun and system.find_executable('primusrun'): launch_arguments.insert(0, 'primusrun') + xephyr = system_config.get('xephyr') or 'off' + if xephyr != 'off': + if xephyr == '8bpp': + xephyr_depth = '8' + else: + xephyr_depth = '16' + xephyr_resolution = system_config.get('xephyr_resolution') or '640x480' + xephyr_command = ['Xephyr', ':2', '-ac', '-screen', + xephyr_resolution + 'x' + xephyr_depth, '-glamor', + '-reset', '-terminate', '-fullscreen'] + xephyr_thread = LutrisThread(xephyr_command) + xephyr_thread.start() + time.sleep(3) + env['DISPLAY'] = ':2' + prefix_command = system_config.get("prefix_command") or '' if prefix_command.strip(): launch_arguments.insert(0, prefix_command) @@ -214,7 +232,6 @@ class Game(object): self.state = self.STATE_STOPPED return # Env vars - env = {} game_env = gameplay_info.get('env') or {} env.update(game_env) system_env = system_config.get('env') or {} diff --git a/lutris/sysoptions.py b/lutris/sysoptions.py index f2d91fd77..01095e8db 100644 --- a/lutris/sysoptions.py +++ b/lutris/sysoptions.py @@ -150,6 +150,25 @@ system_options = [ 'condition': system.find_executable('xboxdrv'), 'help': ("Command line options for xboxdrv, a driver for XBOX 360" "controllers. Requires the xboxdrv package installed.") + }, + { + 'option': 'xephyr', + 'type': 'choice', + 'label': "Use Xephyr", + 'type': 'choice', + 'choices': ( + ('Off', 'off'), + ('8BPP (256 colors)', '8bpp'), + ('16BPP (65536 colors)', '16bpp') + ), + 'default': 'off', + 'advanced': True, + 'help': "Run program in Xephyr to support 8BPP and 16BPP color modes", + }, + { + 'option': 'xephyr_resolution', + 'type': 'string', + 'label': 'Xephyr resolution' } ] From 700d5bb746942b2b2201189c5eee668a86901eaf Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 14:41:45 -0800 Subject: [PATCH 028/181] Release 0.3.7.4 --- Makefile | 2 +- debian/changelog | 9 +++++++++ lutris.spec | 2 +- lutris/settings.py | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index bec81092d..975c0e3b5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION="0.3.7.3" +VERSION="0.3.7.4" cover: rm tests/fixtures/pga.db -f diff --git a/debian/changelog b/debian/changelog index b5b302d14..dc711087f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +lutris (0.3.7.4) xenial; urgency=medium + + * Add support for Xephyr + * Detect Wine versions installed from WineHQ + * Update koku-xinput-wine to work with the build provided in the runtime + * Always install the required runner when a game is installed + + -- Mathieu Comandon Sun, 06 Mar 2016 14:37:09 -0800 + lutris (0.3.7.3) xenial; urgency=medium * Add PCSX2 runner diff --git a/lutris.spec b/lutris.spec index fbc380ed1..58281d38e 100644 --- a/lutris.spec +++ b/lutris.spec @@ -1,7 +1,7 @@ %{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} Name: lutris -Version: 0.3.7.3 +Version: 0.3.7.4 Release: 2%{?dist} Summary: Install and play any video game easily diff --git a/lutris/settings.py b/lutris/settings.py index 769fdedbb..f24f689e3 100644 --- a/lutris/settings.py +++ b/lutris/settings.py @@ -5,7 +5,7 @@ from gi.repository import GLib from lutris.util.settings import SettingsIO PROJECT = "Lutris" -VERSION = "0.3.7.3" +VERSION = "0.3.7.4" COPYRIGHT = "(c) 2010-2016 Lutris Gaming Platform" AUTHORS = ["Mathieu Comandon ", "Pascal Reinhard (Xodetaetl) Date: Sun, 6 Mar 2016 14:48:50 -0800 Subject: [PATCH 029/181] Use native Debian format --- debian/source/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/source/format b/debian/source/format index 163aaf8d8..89ae9db8f 100644 --- a/debian/source/format +++ b/debian/source/format @@ -1 +1 @@ -3.0 (quilt) +3.0 (native) From e81e3bc9506aa60418099fb9be7d701999f96a26 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 14:53:55 -0800 Subject: [PATCH 030/181] It's tar.xz for the source archives now --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 975c0e3b5..38256e71b 100644 --- a/Makefile +++ b/Makefile @@ -35,4 +35,4 @@ clean: build-all: deb upload: - scp build/lutris_${VERSION}.tar.gz lutris.net:/srv/releases/ + scp build/lutris_${VERSION}.tar.xz lutris.net:/srv/releases/ From 8b72249daed35c71aa8da66e01b504af34b78262 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 14:57:33 -0800 Subject: [PATCH 031/181] Update to tar.xz on the spec file too --- lutris.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris.spec b/lutris.spec index 58281d38e..aead88bbe 100644 --- a/lutris.spec +++ b/lutris.spec @@ -8,7 +8,7 @@ Summary: Install and play any video game easily License: GPL-3.0+ Group: Amusements/Games/Other URL: http://lutris.net -Source0: http://lutris.net/releases/lutris_%{version}.tar.gz +Source0: http://lutris.net/releases/lutris_%{version}.tar.xz BuildArch: noarch From 19e57eddadc4dca3a2e86e4d08130ff6464c645d Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Mon, 7 Mar 2016 09:33:38 -0800 Subject: [PATCH 032/181] Cast runner_slug to a string in Runner configs --- lutris/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/config.py b/lutris/config.py index 7bb237381..94c98e5c0 100644 --- a/lutris/config.py +++ b/lutris/config.py @@ -127,7 +127,7 @@ class LutrisConfig(object): """ def __init__(self, runner_slug=None, game_config_id=None, level=None): self.game_config_id = game_config_id - self.runner_slug = runner_slug + self.runner_slug = str(runner_slug) # Cascaded config sections (for reading) self.game_config = {} From dc7c45c0360380f18054bfb62df9d9f16f69522e Mon Sep 17 00:00:00 2001 From: ProdessorKaos64 Date: Tue, 23 Feb 2016 18:37:17 -0500 Subject: [PATCH 033/181] update debian/ to use cleaner pybuild system --- debian/compat | 2 +- debian/control | 18 +++++++++++++----- debian/rules | 9 +++++---- debian/source/format | 1 + 4 files changed, 20 insertions(+), 10 deletions(-) create mode 100644 debian/source/format diff --git a/debian/compat b/debian/compat index 1e8b31496..ec635144f 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -6 +9 diff --git a/debian/control b/debian/control index 91c67f851..967945065 100644 --- a/debian/control +++ b/debian/control @@ -1,15 +1,18 @@ Source: lutris Section: games Priority: optional -Build-Depends: cdbs, - debhelper, +Build-Depends: debhelper, + libsdl2-2.0-0:i386, + libstdc++6:i386, + libgcc1:i386, + libc6:i386, python, dh-python, gir1.2-gtk-3.0, gir1.2-glib-2.0, python-gi, - libgirepository1.0-dev, -Maintainer: Mathieu Comandon + libgirepository1.0-dev +Maintainer: Michael DeGuzis Standards-Version: 3.9.5 Vcs-Git: https://github.com/lutris/lutris Homepage: https://lutris.net @@ -19,7 +22,12 @@ Package: lutris Architecture: any Depends: ${misc:Depends}, ${python:Depends}, - python-yaml, python-dbus, gir1.2-gtk-3.0, xdg-user-dirs, libc6-i386 [amd64], + python-yaml, + python-dbus, + gir1.2-gtk-3.0, + xdg-user-dirs, + python-xdg, + libc6-i386 [amd64], lib32gcc1 [amd64] Description: Install and play any video game easily Lutris is a gaming platform for GNU/Linux. Its goal is to make diff --git a/debian/rules b/debian/rules index a97fc775f..a5acdfa87 100755 --- a/debian/rules +++ b/debian/rules @@ -1,6 +1,7 @@ #!/usr/bin/make -f -DEB_PYTHON2_MODULE_PACKAGES=lutris - -include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/python-distutils.mk +# This file was automatically generated by stdeb 0.8.2 at +# Fri, 29 Jan 2016 08:11:44 -0500 +export PYBUILD_NAME=lutris +%: + dh $@ --with python2 --buildsystem=pybuild diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 000000000..163aaf8d8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) From 46ff2959569fc7f5da6070251b65302399ce84e1 Mon Sep 17 00:00:00 2001 From: mikeyd Date: Thu, 25 Feb 2016 06:51:00 -0500 Subject: [PATCH 034/181] remvoe 32 bit libs, koku-xinput-wine removed See: https://github.com/lutris/lutris/pull/256 --- debian/control | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/debian/control b/debian/control index 967945065..ab601061c 100644 --- a/debian/control +++ b/debian/control @@ -2,17 +2,13 @@ Source: lutris Section: games Priority: optional Build-Depends: debhelper, - libsdl2-2.0-0:i386, - libstdc++6:i386, - libgcc1:i386, - libc6:i386, python, dh-python, gir1.2-gtk-3.0, gir1.2-glib-2.0, python-gi, libgirepository1.0-dev -Maintainer: Michael DeGuzis +Maintainer: Mathieu Comandon Standards-Version: 3.9.5 Vcs-Git: https://github.com/lutris/lutris Homepage: https://lutris.net From 474b69b18059fef94e3c1ec69cb961d2a3bf9d05 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 14:41:45 -0800 Subject: [PATCH 035/181] Release 0.3.7.4 --- Makefile | 2 +- debian/changelog | 9 +++++++++ lutris.spec | 2 +- lutris/settings.py | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index bec81092d..975c0e3b5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION="0.3.7.3" +VERSION="0.3.7.4" cover: rm tests/fixtures/pga.db -f diff --git a/debian/changelog b/debian/changelog index b5b302d14..dc711087f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +lutris (0.3.7.4) xenial; urgency=medium + + * Add support for Xephyr + * Detect Wine versions installed from WineHQ + * Update koku-xinput-wine to work with the build provided in the runtime + * Always install the required runner when a game is installed + + -- Mathieu Comandon Sun, 06 Mar 2016 14:37:09 -0800 + lutris (0.3.7.3) xenial; urgency=medium * Add PCSX2 runner diff --git a/lutris.spec b/lutris.spec index fbc380ed1..58281d38e 100644 --- a/lutris.spec +++ b/lutris.spec @@ -1,7 +1,7 @@ %{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} Name: lutris -Version: 0.3.7.3 +Version: 0.3.7.4 Release: 2%{?dist} Summary: Install and play any video game easily diff --git a/lutris/settings.py b/lutris/settings.py index 769fdedbb..f24f689e3 100644 --- a/lutris/settings.py +++ b/lutris/settings.py @@ -5,7 +5,7 @@ from gi.repository import GLib from lutris.util.settings import SettingsIO PROJECT = "Lutris" -VERSION = "0.3.7.3" +VERSION = "0.3.7.4" COPYRIGHT = "(c) 2010-2016 Lutris Gaming Platform" AUTHORS = ["Mathieu Comandon ", "Pascal Reinhard (Xodetaetl) Date: Sun, 6 Mar 2016 14:48:50 -0800 Subject: [PATCH 036/181] Use native Debian format --- debian/source/format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/source/format b/debian/source/format index 163aaf8d8..89ae9db8f 100644 --- a/debian/source/format +++ b/debian/source/format @@ -1 +1 @@ -3.0 (quilt) +3.0 (native) From 277d89c1de0bdcb85364651e604b3d0c139375e6 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 14:53:55 -0800 Subject: [PATCH 037/181] It's tar.xz for the source archives now --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 975c0e3b5..38256e71b 100644 --- a/Makefile +++ b/Makefile @@ -35,4 +35,4 @@ clean: build-all: deb upload: - scp build/lutris_${VERSION}.tar.gz lutris.net:/srv/releases/ + scp build/lutris_${VERSION}.tar.xz lutris.net:/srv/releases/ From 51a2315caeb4b0e974cadcd10dc6633bd7b86da6 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 6 Mar 2016 14:57:33 -0800 Subject: [PATCH 038/181] Update to tar.xz on the spec file too --- lutris.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris.spec b/lutris.spec index 58281d38e..aead88bbe 100644 --- a/lutris.spec +++ b/lutris.spec @@ -8,7 +8,7 @@ Summary: Install and play any video game easily License: GPL-3.0+ Group: Amusements/Games/Other URL: http://lutris.net -Source0: http://lutris.net/releases/lutris_%{version}.tar.gz +Source0: http://lutris.net/releases/lutris_%{version}.tar.xz BuildArch: noarch From 3d28518df8f07ed6c408415e0e2a2bb0a8413998 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Mon, 7 Mar 2016 09:33:38 -0800 Subject: [PATCH 039/181] Cast runner_slug to a string in Runner configs --- lutris/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/config.py b/lutris/config.py index 7bb237381..94c98e5c0 100644 --- a/lutris/config.py +++ b/lutris/config.py @@ -127,7 +127,7 @@ class LutrisConfig(object): """ def __init__(self, runner_slug=None, game_config_id=None, level=None): self.game_config_id = game_config_id - self.runner_slug = runner_slug + self.runner_slug = str(runner_slug) # Cascaded config sections (for reading) self.game_config = {} From bd1fb3bf114d9b8e160eb0beed3f8ace1c74f33a Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Mon, 7 Mar 2016 09:56:09 -0800 Subject: [PATCH 040/181] Don't substitute Boolean values --- lutris/installer/interpreter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index f0ed8ff56..64107ab28 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -520,6 +520,8 @@ class ScriptInterpreter(CommandsMixin): config[key] = dict( [(k, self._substitute(v)) for (k, v) in value.iteritems()] ) + elif isinstance(value, bool): + config[key] = value else: config[key] = self._substitute(value) return config From 31e6a56711b327265051a116d5bce795e3ac49ee Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Mon, 7 Mar 2016 09:59:15 -0800 Subject: [PATCH 041/181] Release 0.3.7.5 --- Makefile | 2 +- debian/changelog | 7 +++++++ lutris.spec | 2 +- lutris/settings.py | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 38256e71b..47c217459 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION="0.3.7.4" +VERSION="0.3.7.5" cover: rm tests/fixtures/pga.db -f diff --git a/debian/changelog b/debian/changelog index dc711087f..a67ed9853 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +lutris (0.3.7.5) xenial; urgency=medium + + * Fix a bug where booleans in scripts would be converted to strings + * Update Debian package source format + + -- Mathieu Comandon Mon, 07 Mar 2016 09:57:29 -0800 + lutris (0.3.7.4) xenial; urgency=medium * Add support for Xephyr diff --git a/lutris.spec b/lutris.spec index aead88bbe..f890b34a1 100644 --- a/lutris.spec +++ b/lutris.spec @@ -1,7 +1,7 @@ %{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} Name: lutris -Version: 0.3.7.4 +Version: 0.3.7.5 Release: 2%{?dist} Summary: Install and play any video game easily diff --git a/lutris/settings.py b/lutris/settings.py index f24f689e3..44e2c79fd 100644 --- a/lutris/settings.py +++ b/lutris/settings.py @@ -5,7 +5,7 @@ from gi.repository import GLib from lutris.util.settings import SettingsIO PROJECT = "Lutris" -VERSION = "0.3.7.4" +VERSION = "0.3.7.5" COPYRIGHT = "(c) 2010-2016 Lutris Gaming Platform" AUTHORS = ["Mathieu Comandon ", "Pascal Reinhard (Xodetaetl) Date: Mon, 7 Mar 2016 09:59:15 -0800 Subject: [PATCH 042/181] Release 0.3.7.5 --- Makefile | 2 +- debian/changelog | 7 +++++++ lutris.spec | 2 +- lutris/settings.py | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 38256e71b..47c217459 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION="0.3.7.4" +VERSION="0.3.7.5" cover: rm tests/fixtures/pga.db -f diff --git a/debian/changelog b/debian/changelog index dc711087f..a67ed9853 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +lutris (0.3.7.5) xenial; urgency=medium + + * Fix a bug where booleans in scripts would be converted to strings + * Update Debian package source format + + -- Mathieu Comandon Mon, 07 Mar 2016 09:57:29 -0800 + lutris (0.3.7.4) xenial; urgency=medium * Add support for Xephyr diff --git a/lutris.spec b/lutris.spec index aead88bbe..f890b34a1 100644 --- a/lutris.spec +++ b/lutris.spec @@ -1,7 +1,7 @@ %{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} Name: lutris -Version: 0.3.7.4 +Version: 0.3.7.5 Release: 2%{?dist} Summary: Install and play any video game easily diff --git a/lutris/settings.py b/lutris/settings.py index f24f689e3..44e2c79fd 100644 --- a/lutris/settings.py +++ b/lutris/settings.py @@ -5,7 +5,7 @@ from gi.repository import GLib from lutris.util.settings import SettingsIO PROJECT = "Lutris" -VERSION = "0.3.7.4" +VERSION = "0.3.7.5" COPYRIGHT = "(c) 2010-2016 Lutris Gaming Platform" AUTHORS = ["Mathieu Comandon ", "Pascal Reinhard (Xodetaetl) Date: Mon, 7 Mar 2016 09:56:09 -0800 Subject: [PATCH 043/181] Don't substitute Boolean values --- lutris/installer/interpreter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index f0ed8ff56..64107ab28 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -520,6 +520,8 @@ class ScriptInterpreter(CommandsMixin): config[key] = dict( [(k, self._substitute(v)) for (k, v) in value.iteritems()] ) + elif isinstance(value, bool): + config[key] = value else: config[key] = self._substitute(value) return config From 35e2e8b057e0f656101c33cf290f3739151b2887 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Mon, 7 Mar 2016 13:40:32 -0800 Subject: [PATCH 044/181] Make winecfg non blocking when called from the contextual menu --- lutris/runners/wine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 120f0be2f..0e4ef672a 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -586,7 +586,7 @@ class wine(Runner): def run_winecfg(self, *args): winecfg(wine_path=self.get_executable(), prefix=self.prefix_path, - arch=self.wine_arch) + arch=self.wine_arch, blocking=False) def run_regedit(self, *args): wineexec("regedit", wine_path=self.get_executable(), prefix=self.prefix_path) From b5dcf7471dee9a2478cc3289c385fc6003ac37be Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Thu, 10 Mar 2016 11:03:52 -0800 Subject: [PATCH 045/181] Update Winetricks --- share/lutris/bin/winetricks | 3007 +++++++++++++++-------------------- 1 file changed, 1272 insertions(+), 1735 deletions(-) diff --git a/share/lutris/bin/winetricks b/share/lutris/bin/winetricks index f1da4656e..b1affec27 100755 --- a/share/lutris/bin/winetricks +++ b/share/lutris/bin/winetricks @@ -2,7 +2,7 @@ # Name of this version of winetricks (YYYYMMDD) # (This doesn't change often, use the sha1sum of the file when reporting problems) -WINETRICKS_VERSION=20150826 +WINETRICKS_VERSION=20160219 # This is a utf-8 file # You should see an o with two dots over it here [ö] @@ -26,7 +26,7 @@ WINETRICKS_VERSION=20150826 # - aria2c, wget, or curl is needed for downloading. # - sha1sum or openssl is needed for verifying downloads. # - zenity is needed by the GUI, though it can limp along somewhat with kdialog. -# - xdg-open (if present) or open (for Mac OSX) is used to open download pages +# - xdg-open (if present) or open (for Mac OSX) is used to open download pages # for the user when downloads cannot be fully automated. # - sudo is used to mount .iso images if the user cached them with -k option. # - perl is used to munge steam config files @@ -42,7 +42,7 @@ WINETRICKS_VERSION=20150826 # # Copyright # Copyright (C) 2007-2014 Dan Kegel -# Copyright (C) 2008-2015 Austin English +# Copyright (C) 2008-2016 Austin English # Copyright (C) 2010-2011 Phil Blankenship # Copyright (C) 2010-2015 Shannon VanWagner # Copyright (C) 2010 Belhorma Bendebiche @@ -62,6 +62,7 @@ WINETRICKS_VERSION=20150826 # Copyright (C) 2011 Matthew Bozarth # Copyright (C) 2013-2014 Andrey Gusev # Copyright (C) 2013-2015 Hillwood Yang +# Copyright (C) 2013,2016 André Hentschel # # License # This program is free software; you can redistribute it and/or @@ -400,7 +401,7 @@ w_read_key() mkdir -p "$W_CACHE/$W_PACKAGE" - # backwards compatibile location + # backwards compatible location # Auth doesn't belong in cache, since restoring it requires user input _W_keyfile="$W_CACHE/$W_PACKAGE/key.txt" if ! test -f "$_W_keyfile" @@ -414,22 +415,22 @@ w_read_key() da*) _W_keymsg="Angiv venligst registrerings-nøglen for pakken '$_PACKAGE'" _W_nokeymsg="Ingen nøgle angivet" ;; - de*) _W_keymsg="Bitte einen Key für Pakete '$W_PACKAGE' eingeben" + de*) _W_keymsg="Bitte einen Key für Paket '$W_PACKAGE' eingeben" _W_nokeymsg="Keinen Key eingegeben?" ;; pl*) _W_keymsg="Proszę podać klucz dla programu '$W_PACKAGE'" _W_nokeymsg="Nie podano klucza" ;; + ru*) _W_keymsg="Пожалуйста, введите ключ для приложения '$W_PACKAGE'" + _W_nokeymsg="Ключ не введён" + ;; uk*) _W_keymsg="Будь ласка, введіть ключ для додатка '$W_PACKAGE'" _W_nokeymsg="Ключ не надано" ;; zh_CN*) _W_keymsg="按任意键为 '$W_PACKAGE'" _W_nokeymsg="No key given" ;; - zh_TW*) _W_keymsg="按任意鍵為 '$W_PACKAGE'" - _W_nokeymsg="No key given" - ;; - zh_HK*) _W_keymsg="按任意鍵為 '$W_PACKAGE'" + zh_TW*|zh_HK*) _W_keymsg="按任意鍵為 '$W_PACKAGE'" _W_nokeymsg="No key given" ;; *) _W_keymsg="Please enter the key for app '$W_PACKAGE'" @@ -576,6 +577,7 @@ w_dotnet_verify() dotnet35sp1) version="3.5 SP1" ;; dotnet40) version="4 Client" ;; dotnet45) version="4.5" ;; + dotnet452) version="4.5.2" ;; *) echo error ; exit 1 ;; esac w_call dotnet_verifier @@ -606,7 +608,7 @@ w_dotnet_verify() { process, close, setupverifier2.exe break - } + } } " dn_status=$? @@ -732,28 +734,32 @@ w_download_to() else w_die "Please install wget or aria2c (or, if those aren't available, curl)" fi - if test $? != 0 + if test $? = 0 + then + # Need to decompress .exe's that are compressed, else cygwin fails + # Also affects ttf files on github + _W_filetype=`which file 2>/dev/null` + case $_W_filetype-$_W_file in + /*-*.exe|/*-*.ttf|/*-*.zip) + case `file "$_W_file"` in + *:*gzip*) mv "$_W_file" "$_W_file.gz"; gunzip < "$_W_file.gz" > "$_W_file";; + esac + esac + + # On cygwin, .exe's must be marked +x + case "$_W_file" in + *.exe) chmod +x "$_W_file" ;; + esac + + cd "$_W_dl_olddir" + unset _W_dl_olddir + elif test $tries = 2 then test -f "$_W_file" && rm "$_W_file" w_die "Downloading $_W_url failed" fi - # Need to decompress .exe's that are compressed, else cygwin fails - # Also affects ttf files on github - _W_filetype=`which file 2>/dev/null` - case $_W_filetype-$_W_file in - /*-*.exe|/*-*.ttf|/*-*.zip) - case `file "$_W_file"` in - *:*gzip*) mv "$_W_file" "$_W_file.gz"; gunzip < "$_W_file.gz" > "$_W_file";; - esac - esac - - # On cygwin, .exe's must be marked +x - case "$_W_file" in - *.exe) chmod +x "$_W_file" ;; - esac - - cd "$_W_dl_olddir" - unset _W_dl_olddir + # Download from the Wayback Machine on second try + _W_url="https://web.archive.org/web/$_W_url" done if test "$3" && test ! "$checksum_ok" @@ -884,12 +890,12 @@ w_download_manual_to() case $LANG in da*) _W_dlmsg="Hent venligst filen $_W_file fra $_W_url og placér den i $W_CACHE/$_W_packagename, kør derefter dette skript.";; - de*) _W_dlmsg="Bitte laden Sie $_W_file von $_W_url runter, stellen Sie's in $W_CACHE/$_W_packagename, dann wiederholen Sie diesen Kommando.";; + de*) _W_dlmsg="Bitte laden Sie $_W_file von $_W_url runter, stellen Sie's in $W_CACHE/$_W_packagename, dann wiederholen Sie dieses Kommando.";; pl*) _W_dlmsg="Proszę pobrać plik $_W_file z $_W_url, następnie umieścić go w $W_CACHE/$_W_packagename, a na końcu uruchomić ponownie ten skrypt.";; + ru*) _W_dlmsg="Пожалуйста, скачайте файл $_W_file по адресу $_W_url, и поместите его в $W_CACHE/$_W_packagename, а затем запустите winetricks заново.";; uk*) _W_dlmsg="Будь ласка, звантажте $_W_file з $_W_url, розташуйте в $W_CACHE/$_W_packagename, потім запустіть скрипт знову.";; zh_CN*) _W_dlmsg="请从 $_W_url 下载 $_W_file,并置放于 $W_CACHE/$_W_packagename, 然后重新运行 winetricks.";; - zh_TW*) _W_dlmsg="請從 $_W_url 下載 $_W_file,并置放於 $W_CACHE/$_W_packagename, 然后重新執行 winetricks.";; - zh_HK*) _W_dlmsg="請從 $_W_url 下載 $_W_file,并置放於 $W_CACHE/$_W_packagename, 然后重新執行 winetricks.";; + zh_TW*|zh_HK*) _W_dlmsg="請從 $_W_url 下載 $_W_file,并置放於 $W_CACHE/$_W_packagename, 然后重新執行 winetricks.";; *) _W_dlmsg="Please download $_W_file from $_W_url, place it in $W_CACHE/$_W_packagename, then re-run this script.";; esac @@ -902,7 +908,12 @@ w_download_manual_to() w_die "$_W_dlmsg" # FIXME: wait in loop until file is finished? fi - # FIXME: verify $sha1sum of $file + + if test "$_W_sha1sum" + then + w_verify_sha1sum $_W_sha1sum "$W_CACHE/$_W_packagename/$_W_file" + fi + unset _W_url _W_file _W_sha1sum _W_dlmsg } @@ -1177,17 +1188,6 @@ fi w_steam_safemode fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\Steam" "steam.exe -login $W_STEAM_ID $W_STEAM_PASSWORD -applaunch $_W_steamid" - - myexec="Exec=env WINEPREFIX=\"$WINEPREFIX\" wine cmd /c 'C:\\\\\\\\Run-$W_PACKAGE.bat'" - mymenu="$XDG_DATA_HOME/applications/wine/Programs/Steam/$_W_steamtitle.desktop" - if test -f "$mymenu" && w_workaround_wine_bug 26487 "Fixing system menu" - then - sed -i "s,Exec=.*,$myexec," "$mymenu" - else - w_warn "bug: could not find system menu entry $_W_steamtitle" - fi - unset _W_steamid _W_steamtitle } @@ -1202,7 +1202,7 @@ fi # other_files # Extra installer files, in one string, space-separated. # reader_control -# If set, the control id of the configuration pannel checkbox controling +# If set, the control id of the configuration panel checkbox controling # Adobe Reader installation. # Some games don't have it, some games do with different ids. # run_command @@ -1313,11 +1313,6 @@ winetricks_load_gog() WinWait, Setup - $game_title, Exit Installer ControlClick, TMCoPShadowButton1 ; Exit Installer " - - if test "$run_command"x != ""x - then - w_declare_exe "$W_PROGRAMS_X86_WIN\\GOG.com\\$install_dir" "$run_command" - fi } #---------------------------------------------------------------- @@ -1403,7 +1398,7 @@ w_ahk_do() fi _W_CR=`printf \\\\r` - cat <<_EOF_ | sed "s/\$/$CR/" > "$W_TMP"/tmp.ahk + cat <<_EOF_ | sed "s/\$/$_W_CR/" > "$W_TMP"/tmp.ahk w_opt_unattended = ${W_OPT_UNATTENDED:-0} $@ _EOF_ @@ -1489,93 +1484,201 @@ w_override_all_dlls() # Disable all known native Microsoft DLLs in favor of Wine's builtin ones # Generated with # find ~/wine-git/dlls -maxdepth 1 -type d -print | sed 's,.*/,,' | sort | fmt -50 | sed 's/$/ \\/' + # Last updated: 2015-09-28 w_override_dlls builtin \ acledit aclui activeds actxprxy adsiid advapi32 \ - advpack amstream apphelp appwiz.cpl atl atl80 \ - authz avicap32 avifil32 avifile.dll16 avrt \ - bcrypt browseui cabinet capi2032 cards cfgmgr32 \ - clusapi comcat comctl32 comdlg32 commdlg.dll16 \ - comm.drv16 compobj.dll16 compstui credui crtdll \ - crypt32 cryptdlg cryptdll cryptnet cryptui \ - ctapi32 ctl3d32 ctl3d.dll16 ctl3dv2.dll16 d3d10 \ - d3d10core d3d8 d3d9 d3dcompiler_33 d3dcompiler_34 \ + advpack amstream api-ms-win-core-com-l1-1-0 \ + api-ms-win-core-console-l1-1-0 \ + api-ms-win-core-datetime-l1-1-0 \ + api-ms-win-core-datetime-l1-1-1 \ + api-ms-win-core-debug-l1-1-0 \ + api-ms-win-core-debug-l1-1-1 \ + api-ms-win-core-errorhandling-l1-1-0 \ + api-ms-win-core-errorhandling-l1-1-1 \ + api-ms-win-core-errorhandling-l1-1-2 \ + api-ms-win-core-fibers-l1-1-0 \ + api-ms-win-core-fibers-l1-1-1 \ + api-ms-win-core-file-l1-1-0 \ + api-ms-win-core-file-l1-2-0 \ + api-ms-win-core-file-l2-1-0 \ + api-ms-win-core-file-l2-1-1 \ + api-ms-win-core-handle-l1-1-0 \ + api-ms-win-core-heap-l1-1-0 \ + api-ms-win-core-heap-l1-2-0 \ + api-ms-win-core-heap-obsolete-l1-1-0 \ + api-ms-win-core-interlocked-l1-1-0 \ + api-ms-win-core-interlocked-l1-2-0 \ + api-ms-win-core-io-l1-1-1 \ + api-ms-win-core-kernel32-legacy-l1-1-0 \ + api-ms-win-core-libraryloader-l1-1-0 \ + api-ms-win-core-libraryloader-l1-1-1 \ + api-ms-win-core-localization-l1-2-0 \ + api-ms-win-core-localization-l1-2-1 \ + api-ms-win-core-localization-obsolete-l1-1-0 \ + api-ms-win-core-localregistry-l1-1-0 \ + api-ms-win-core-memory-l1-1-0 \ + api-ms-win-core-memory-l1-1-1 \ + api-ms-win-core-misc-l1-1-0 \ + api-ms-win-core-namedpipe-l1-1-0 \ + api-ms-win-core-namedpipe-l1-2-0 \ + api-ms-win-core-processenvironment-l1-1-0 \ + api-ms-win-core-processenvironment-l1-2-0 \ + api-ms-win-core-processthreads-l1-1-0 \ + api-ms-win-core-processthreads-l1-1-1 \ + api-ms-win-core-processthreads-l1-1-2 \ + api-ms-win-core-profile-l1-1-0 \ + api-ms-win-core-psapi-l1-1-0 \ + api-ms-win-core-registry-l1-1-0 \ + api-ms-win-core-rtlsupport-l1-1-0 \ + api-ms-win-core-rtlsupport-l1-2-0 \ + api-ms-win-core-shlwapi-legacy-l1-1-0 \ + api-ms-win-core-string-l1-1-0 \ + api-ms-win-core-synch-l1-1-0 \ + api-ms-win-core-synch-l1-2-0 \ + api-ms-win-core-sysinfo-l1-1-0 \ + api-ms-win-core-sysinfo-l1-2-0 \ + api-ms-win-core-sysinfo-l1-2-1 \ + api-ms-win-core-threadpool-legacy-l1-1-0 \ + api-ms-win-core-timezone-l1-1-0 \ + api-ms-win-core-url-l1-1-0 \ + api-ms-win-core-util-l1-1-0 \ + api-ms-win-core-winrt-error-l1-1-0 \ + api-ms-win-core-winrt-error-l1-1-1 \ + api-ms-win-core-winrt-l1-1-0 \ + api-ms-win-core-winrt-string-l1-1-0 \ + api-ms-win-core-xstate-l2-1-0 \ + api-ms-win-crt-conio-l1-1-0 \ + api-ms-win-crt-convert-l1-1-0 \ + api-ms-win-crt-environment-l1-1-0 \ + api-ms-win-crt-filesystem-l1-1-0 \ + api-ms-win-crt-heap-l1-1-0 \ + api-ms-win-crt-locale-l1-1-0 \ + api-ms-win-crt-math-l1-1-0 \ + api-ms-win-crt-multibyte-l1-1-0 \ + api-ms-win-crt-private-l1-1-0 \ + api-ms-win-crt-process-l1-1-0 \ + api-ms-win-crt-runtime-l1-1-0 \ + api-ms-win-crt-stdio-l1-1-0 \ + api-ms-win-crt-string-l1-1-0 \ + api-ms-win-crt-time-l1-1-0 \ + api-ms-win-crt-utility-l1-1-0 \ + api-ms-win-downlevel-advapi32-l1-1-0 \ + api-ms-win-downlevel-advapi32-l2-1-0 \ + api-ms-win-downlevel-normaliz-l1-1-0 \ + api-ms-win-downlevel-ole32-l1-1-0 \ + api-ms-win-downlevel-shell32-l1-1-0 \ + api-ms-win-downlevel-shlwapi-l1-1-0 \ + api-ms-win-downlevel-shlwapi-l2-1-0 \ + api-ms-win-downlevel-user32-l1-1-0 \ + api-ms-win-downlevel-version-l1-1-0 \ + api-ms-win-eventing-provider-l1-1-0 \ + api-ms-win-ntuser-dc-access-l1-1-0 \ + api-ms-win-security-base-l1-1-0 \ + api-ms-win-security-base-l1-2-0 \ + api-ms-win-security-sddl-l1-1-0 \ + api-ms-win-service-core-l1-1-1 \ + api-ms-win-service-management-l1-1-0 \ + api-ms-win-service-winsvc-l1-2-0 apphelp \ + appwiz.cpl atl atl100 atl110 atl80 atl90 authz \ + avicap32 avifil32 avifile.dll16 avrt bcrypt \ + browseui cabinet capi2032 cards cfgmgr32 clusapi \ + combase comcat comctl32 comdlg32 commdlg.dll16 \ + comm.drv16 compobj.dll16 compstui comsvcs connect \ + credui crtdll crypt32 cryptdlg cryptdll cryptext \ + cryptnet cryptui ctapi32 ctl3d32 ctl3d.dll16 \ + ctl3dv2.dll16 d2d1 d3d10 d3d10_1 d3d10core \ + d3d11 d3d8 d3d9 d3dcompiler_33 d3dcompiler_34 \ d3dcompiler_35 d3dcompiler_36 d3dcompiler_37 \ d3dcompiler_38 d3dcompiler_39 d3dcompiler_40 \ d3dcompiler_41 d3dcompiler_42 d3dcompiler_43 \ - d3dim d3drm d3dx10_33 d3dx10_34 d3dx10_35 \ - d3dx10_36 d3dx10_37 d3dx10_38 d3dx10_39 \ - d3dx10_40 d3dx10_41 d3dx10_42 d3dx10_43 \ - d3dx9_24 d3dx9_25 d3dx9_26 d3dx9_27 d3dx9_28 \ - d3dx9_29 d3dx9_30 d3dx9_31 d3dx9_32 d3dx9_33 \ - d3dx9_34 d3dx9_35 d3dx9_36 d3dx9_37 d3dx9_38 \ - d3dx9_39 d3dx9_40 d3dx9_41 d3dx9_42 d3dx9_43 \ - d3dxof dbgeng dbghelp dciman32 ddeml.dll16 \ - ddraw ddrawex devenum dhcpcsvc dinput dinput8 \ - dispdib.dll16 dispex display.drv16 dlls dmband \ - dmcompos dmime dmloader dmscript dmstyle dmsynth \ - dmusic dmusic32 dnsapi dplay dplayx dpnaddr \ - dpnet dpnhpast dpnlobby dpwsockx drmclien \ - dsound dssenh dswave dwmapi dxdiagn dxerr8 \ - dxerr9 dxgi dxguid explorerframe faultrep \ - fltlib fusion fwpuclnt gameux gdi32 gdi.exe16 \ - gdiplus glu32 gphoto2.ds gpkcsp hal hhctrl.ocx \ - hid hlink hnetcfg httpapi iccvid icmp ieframe \ - ifsmgr.vxd imaadp32.acm imagehlp imm32 imm.dll16 \ - inetcomm inetcpl.cpl inetmib1 infosoft initpki \ - inkobj inseng iphlpapi itircl itss jscript \ - kernel32 keyboard.drv16 krnl386.exe16 ktmw32 \ - loadperf localspl localui lz32 lzexpand.dll16 \ - mapi32 mapistub mciavi32 mcicda mciqtz32 mciseq \ - mciwave mgmtapi midimap mlang mmcndmgr mmdevapi \ + d3dcompiler_46 d3dcompiler_47 d3dim d3drm \ + d3dx10_33 d3dx10_34 d3dx10_35 d3dx10_36 d3dx10_37 \ + d3dx10_38 d3dx10_39 d3dx10_40 d3dx10_41 d3dx10_42 \ + d3dx10_43 d3dx11_42 d3dx11_43 d3dx9_24 d3dx9_25 \ + d3dx9_26 d3dx9_27 d3dx9_28 d3dx9_29 d3dx9_30 \ + d3dx9_31 d3dx9_32 d3dx9_33 d3dx9_34 d3dx9_35 \ + d3dx9_36 d3dx9_37 d3dx9_38 d3dx9_39 d3dx9_40 \ + d3dx9_41 d3dx9_42 d3dx9_43 d3dxof davclnt \ + dbgeng dbghelp dciman32 ddeml.dll16 ddraw \ + ddrawex devenum dhcpcsvc difxapi dinput \ + dinput8 dispdib.dll16 dispex display.drv16 \ + dlls dmband dmcompos dmime dmloader dmscript \ + dmstyle dmsynth dmusic dmusic32 dnsapi dplay \ + dplayx dpnaddr dpnet dpnhpast dpnlobby dpvoice \ + dpwsockx drmclien dsound dssenh dswave dwmapi \ + dwrite dxdiagn dxerr8 dxerr9 dxgi dxguid dxva2 \ + evr explorerframe ext-ms-win-gdi-devcaps-l1-1-0 \ + faultrep fltlib fntcache fontsub fusion fwpuclnt \ + gameux gdi32 gdi.exe16 gdiplus glu32 gphoto2.ds \ + gpkcsp hal hhctrl.ocx hid hidclass.sys hlink \ + hnetcfg httpapi iccvid icmp ieframe ifsmgr.vxd \ + imaadp32.acm imagehlp imm32 imm.dll16 inetcomm \ + inetcpl.cpl inetmib1 infosoft initpki inkobj \ + inseng iphlpapi itircl itss joy.cpl jscript \ + jsproxy kernel32 keyboard.drv16 krnl386.exe16 \ + ksuser ktmw32 loadperf localspl localui lz32 \ + lzexpand.dll16 mapi32 mapistub mciavi32 mcicda \ + mciqtz32 mciseq mciwave mf mfplat mfreadwrite \ + mgmtapi midimap mlang mmcndmgr mmdevapi \ mmdevldr.vxd mmsystem.dll16 monodebg.vxd \ mountmgr.sys mouse.drv16 mpr mprapi msacm32 \ - msacm32.drv msacm.dll16 msadp32.acm mscat32 mscms \ - mscoree msctf msdaps msdmo msftedit msg711.acm \ - msgsm32.acm mshtml mshtml.tlb msi msident msimg32 \ - msimsg msimtf msisip msisys.ocx msnet32 mspatcha \ - msrle32 mssign32 mssip32 mstask msvcirt msvcm80 \ - msvcm90 msvcp100 msvcp60 msvcp70 msvcp71 msvcp80 \ - msvcp90 msvcr100 msvcr70 msvcr71 msvcr80 msvcr90 \ - msvcrt msvcrt20 msvcrt40 msvcrtd msvfw32 msvidc32 \ - msvideo.dll16 mswsock msxml msxml2 msxml3 msxml4 \ - msxml6 nddeapi netapi32 newdev normaliz npmshtml \ - ntdll ntdsapi ntoskrnl.exe ntprint objsel \ - odbc32 odbccp32 ole2conv.dll16 ole2disp.dll16 \ - ole2.dll16 ole2nls.dll16 ole2prox.dll16 \ - ole2thk.dll16 ole32 oleacc oleaut32 olecli32 \ - olecli.dll16 oledb32 oledlg olepro32 olesvr32 \ - olesvr.dll16 olethk32 openal32 opencl opengl32 \ - pdh photometadatahandler pidgen powrprof printui \ - propsys psapi pstorec qcap qedit qmgr qmgrprxy \ - quartz query rasapi16.dll16 rasapi32 rasdlg \ - regapi resutils riched20 riched32 rpcrt4 rsabase \ - rsaenh rstrtmgr rtutils samlib sane.ds scarddlg \ - sccbase schannel scrrun secur32 security sensapi \ - serialui setupapi setupx.dll16 sfc sfc_os shdoclc \ - shdocvw shell32 shell.dll16 shfolder shlwapi \ - slbcsp slc snmpapi softpub sound.drv16 spoolss \ - stdole2.tlb stdole32.tlb sti storage.dll16 \ - stress.dll16 strmbase strmiids svrapi sxs \ - system.drv16 t2embed tapi32 toolhelp.dll16 \ - traffic twain_32 twain.dll16 typelib.dll16 \ - unicows updspapi url urlmon usbd.sys user32 \ - userenv user.exe16 usp10 uuid uxtheme vbscript \ - vcomp vcomp100 vdhcp.vxd vdmdbg ver.dll16 \ - version vmm.vxd vnbt.vxd vnetbios.vxd vtdapi.vxd \ - vwin32.vxd w32skrnl w32sys.dll16 wbemprox wer \ - wevtapi wiaservc win32s16.dll16 win87em.dll16 \ - winaspi.dll16 windebug.dll16 windowscodecs \ - winealsa.drv winecoreaudio.drv winecrt0 \ - wined3d winegstreamer winejoystick.drv winemapi \ - winemp3.acm wineoss.drv wineps16.drv16 wineps.drv \ - wineqtdecoder winequartz.drv winex11.drv wing32 \ + msacm32.drv msacm.dll16 msadp32.acm msasn1 \ + mscat32 mscms mscoree msctf msctfp msdaps \ + msdmo msftedit msg711.acm msgsm32.acm mshtml \ + mshtml.tlb msi msident msimg32 msimsg msimtf \ + msisip msisys.ocx msls31 msnet32 mspatcha msrle32 \ + msscript.ocx mssign32 mssip32 mstask msvcirt \ + msvcm80 msvcm90 msvcp100 msvcp110 msvcp120 \ + msvcp120_app msvcp60 msvcp70 msvcp71 msvcp80 \ + msvcp90 msvcr100 msvcr110 msvcr120 msvcr120_app \ + msvcr70 msvcr71 msvcr80 msvcr90 msvcrt msvcrt20 \ + msvcrt40 msvcrtd msvfw32 msvidc32 msvideo.dll16 \ + mswsock msxml msxml2 msxml3 msxml4 msxml6 \ + nddeapi ndis.sys netapi32 netcfgx netprofm \ + newdev normaliz npmshtml npptools ntdll ntdsapi \ + ntoskrnl.exe ntprint objsel odbc32 odbccp32 \ + odbccu32 ole2conv.dll16 ole2disp.dll16 ole2.dll16 \ + ole2nls.dll16 ole2prox.dll16 ole2thk.dll16 \ + ole32 oleacc oleaut32 olecli32 olecli.dll16 \ + oledb32 oledlg olepro32 olesvr32 olesvr.dll16 \ + olethk32 openal32 opencl opengl32 packager pdh \ + photometadatahandler pidgen powrprof printui \ + prntvpt propsys psapi pstorec qcap qedit qmgr \ + qmgrprxy quartz query rasapi16.dll16 rasapi32 \ + rasdlg regapi resutils riched20 riched32 \ + rpcrt4 rsabase rsaenh rstrtmgr rtutils \ + samlib sane.ds scarddlg sccbase schannel \ + schedsvc scrrun scsiport.sys secur32 security \ + sensapi serialui setupapi setupx.dll16 sfc \ + sfc_os shdoclc shdocvw shell32 shell.dll16 \ + shfolder shlwapi slbcsp slc snmpapi softpub \ + sound.drv16 spoolss stdole2.tlb stdole32.tlb \ + sti storage.dll16 stress.dll16 strmbase strmiids \ + svrapi sxs system.drv16 t2embed tapi32 taskschd \ + toolhelp.dll16 traffic twain_32 twain.dll16 \ + typelib.dll16 ucrtbase unicows updspapi url \ + urlmon usbd.sys user32 userenv user.exe16 usp10 \ + uuid uxtheme vbscript vcomp vcomp100 vcomp110 \ + vcomp90 vdhcp.vxd vdmdbg ver.dll16 version \ + vmm.vxd vnbt.vxd vnetbios.vxd vssapi vtdapi.vxd \ + vwin32.vxd w32skrnl w32sys.dll16 wbemdisp \ + wbemprox webservices wer wevtapi wiaservc \ + win32s16.dll16 win87em.dll16 winaspi.dll16 \ + windebug.dll16 windowscodecs windowscodecsext \ + winealsa.drv winecoreaudio.drv winecrt0 wined3d \ + winegstreamer winejoystick.drv winemac.drv \ + winemapi winemp3.acm wineoss.drv wineps16.drv16 \ + wineps.drv wineqtdecoder winex11.drv wing32 \ wing.dll16 winhttp wininet winmm winnls32 \ winnls.dll16 winscard winsock.dll16 winspool.drv \ winsta wintab32 wintab.dll16 wintrust wlanapi \ - wldap32 wmi wmiutils wmvcore wnaspi32 wow32 \ - ws2_32 wshom.ocx wsnmp32 wsock32 wtsapi32 wuapi \ - wuaueng xapofx1_1 xinput1_1 xinput1_2 xinput1_3 \ - xinput9_1_0 xmllite xolehlp xpsprint \ + wldap32 wmi wmiutils wmp wmvcore wnaspi32 wow32 \ + wpcap ws2_32 wshom.ocx wsnmp32 wsock32 wtsapi32 \ + wuapi wuaueng x3daudio1_1 x3daudio1_2 x3daudio1_3 \ + x3daudio1_4 x3daudio1_5 x3daudio1_6 x3daudio1_7 \ + xapofx1_1 xapofx1_3 xapofx1_4 xapofx1_5 xaudio2_7 \ + xaudio2_8 xinput1_1 xinput1_2 xinput1_3 xinput1_4 \ + xinput9_1_0 xmllite xolehlp xpsprint xpssvcs \ # blank line so you don't have to remove the extra trailing \ } @@ -1825,6 +1928,7 @@ w_wine_version() 1.6|1.6-rc*) _W_minor=6; _W_micro=0;; 1.6.*) _W_minor=6; _W_micro=`echo $2 | sed 's/.*\.//'`;; 1.7.*) _W_minor=7; _W_micro=`echo $2 | sed 's/.*\.//'`;; + 1.8.*) _W_minor=8; _W_micro=`echo $2 | sed 's/.*\.//'`;; *) w_die "bug: unrecognized version $2";; esac @@ -1921,10 +2025,10 @@ w_workaround_wine_bug() da*) w_warn "Arbejder uden om wine-fejl ${1} $_W_msg" ;; de*) w_warn "Wine-Fehler ${1} wird umgegangen $_W_msg" ;; pl*) w_warn "Obchodzenie błędu w wine ${1} $_W_msg" ;; + ru*) w_warn "Обход ошибки ${1} $_W_msg" ;; uk*) w_warn "Обхід помилки ${1} $_W_msg" ;; zh_CN*) w_warn "绕过 wine bug ${1} $_W_msg" ;; - zh_TW*) w_warn "繞過 wine bug ${1} $_W_msg" ;; - zh_HK*) w_warn "繞過 wine bug ${1} $_W_msg" ;; + zh_TW*|zh_HK*) w_warn "繞過 wine bug ${1} $_W_msg" ;; *) w_warn "Working around wine bug ${1} $_W_msg" ;; esac winetricks_stats_log_command w_workaround_wine_bug-$1 @@ -2006,26 +2110,11 @@ w_metadata() esac } -# Function for verbs to register their main executable [or, if name is given, -# other executables] -# Example: -# w_declare_exe "$W_PROGRAMS_X86_WIN\\WorldOfGooDemo" WorldOfGoo.exe [name] +# Function for verbs to register their main executable [or, if name is given, other executables] +# Deprecated. No-op for backwards compatibility w_declare_exe() { - _W_dir="$1" - _W_exe="$2" - if test "$3" - then - _W_name="$3" - else - _W_name="$W_PACKAGE" - fi - cat > "$W_DRIVE_C/run-$_W_name.bat" <<__EOF__ -${W_PROGRAMS_DRIVE}: -cd "$_W_dir" -$_W_exe %* -__EOF__ - unset _W_dir _W_exe _W_name + w_warn "w_declare_exe is deprecated, now a noop" } # Checks that a conflicting verb is not already installed in the prefix @@ -2121,7 +2210,7 @@ w_do_call() echo "$1 already installed, skipping" return 0 fi - + # Don't install if a conflicting verb is already installed: if test "$WINETRICKS_FORCE" != 1 && test "$conflicts" && test -f "$WINEPREFIX/winetricks.log" then @@ -2341,6 +2430,18 @@ winetricks_get_prefix_var() winetricks_prefixmenu() { case $LANG in + ru*) _W_msg_title="Winetricks - выберите путь wine (wineprefix)" + _W_msg_body='Что вы хотите сделать?' + _W_msg_apps='Установить программу' + _W_msg_games='Установить игру' + _W_msg_benchmarks='Установить приложение для оценки производительности' + _W_msg_default="Выберите путь для wine по умолчанию" + _W_msg_unattended0="Отключить автоматическую установку" + _W_msg_unattended1="Включить автоматическую установку" + _W_msg_showbroken0="Спрятать нерабочие программы (например, использующие DRM)" + _W_msg_showbroken1="Отобразить нерабочие программы (например, использующие DRM)" + _W_msg_help="Просмотр справки (в веб браузере)" + ;; uk*) _W_msg_title="Winetricks - виберіть wineprefix" _W_msg_body='Що Ви хочете зробити?' _W_msg_apps='Встановити додаток' @@ -2365,33 +2466,33 @@ winetricks_prefixmenu() _W_msg_showbroken1="有问题的程序 (例如那些有数字版权问题)" _W_msg_help="查看帮助" ;; - zh_TW*) _W_msg_title="Windows 應用裝載向導 - 選取一個 wine 容器" + zh_TW*|zh_HK*) _W_msg_title="Windows 應用安裝向導 - 選取一個 wine 容器" _W_msg_body='君欲何為?' - _W_msg_apps='裝載一個 windows 應用' - _W_msg_games='裝載一個游戲' - _W_msg_benchmarks='裝載一個基准測試軟體' + _W_msg_apps='安裝一個 windows 應用' + _W_msg_games='安裝一個游戲' + _W_msg_benchmarks='安裝一個基准測試軟體' _W_msg_default="選取預設的 wine 容器" - _W_msg_unattended0="禁用靜默裝載" - _W_msg_unattended1="啟用靜默裝載" + _W_msg_unattended0="禁用靜默安裝" + _W_msg_unattended1="啟用靜默安裝" _W_msg_showbroken0="隱藏有問題的程式 (例如那些有數字版權問題)" _W_msg_showbroken1="有問題的程式 (例如那些有數字版權問題)" _W_msg_help="檢視輔助說明" ;; - zh_HK*) _W_msg_title="Windows 應用裝載向導 - 選取一個 wine 容器" - _W_msg_body='君欲何為?' - _W_msg_apps='裝載一個 windows 應用' - _W_msg_games='裝載一個游戲' - _W_msg_benchmarks='裝載一個基准測試軟體' - _W_msg_default="選取預設的 wine 容器" - _W_msg_unattended0="禁用靜默裝載" - _W_msg_unattended1="啟用靜默裝載" - _W_msg_showbroken0="隱藏有問題的程式 (例如那些有數字版權問題)" - _W_msg_showbroken1="有問題的程式 (例如那些有數字版權問題)" - _W_msg_help="檢視輔助說明" + de*) _W_msg_title="Winetricks - wineprefix auswählen" + _W_msg_body='Was möchten Sie tun?' + _W_msg_apps='Eine Programm installieren' + _W_msg_games='Ein Spiel installieren' + _W_msg_benchmarks='Ein Benchmark installieren' + _W_msg_default="Standard wineprefix auswählen" + _W_msg_unattended0="Automatische Installation deaktivieren" + _W_msg_unattended1="Automatische Installation aktivieren" + _W_msg_showbroken0="Defekte Programme nicht anzeigen (z.B. solche mit DRM Problemen)" + _W_msg_showbroken1="Defekte Programme anzeigen (z.B. solche mit DRM Problemen)" + _W_msg_help="Hilfe anzeigen" ;; *) _W_msg_title="Winetricks - choose a wineprefix" _W_msg_body='What do you want to do?' - _W_msg_apps='Install an app' + _W_msg_apps='Install an application' _W_msg_games='Install a game' _W_msg_benchmarks='Install a benchmark' _W_msg_default="Select the default wineprefix" @@ -2444,7 +2545,12 @@ winetricks_prefixmenu() else _W_msg_name="$p" fi - printf %s " FALSE prefix='$p' 'Select $_W_msg_name' " + case $LANG in + zh_CN*) printf %s " FALSE prefix='$p' '选择管理 $_W_msg_name' " ;; + zh_TW*|zh_HK*) printf %s " FALSE prefix='$p' '選擇管理 $_W_msg_name' " ;; + de*) printf %s " FALSE prefix='$p' '$_W_msg_name auswählen' " ;; + *) printf %s " FALSE prefix='$p' 'Select $_W_msg_name' " ;; + esac done >> "$WINETRICKS_WORKDIR"/zenity.sh fi printf %s " FALSE $_W_cmd_unattended '$_W_msg_unattended'" >> "$WINETRICKS_WORKDIR"/zenity.sh @@ -2499,6 +2605,7 @@ winetricks_mainmenu() _W_msg_winecfg='Run winecfg' _W_msg_regedit='Run regedit' _W_msg_taskmgr='Run taskmgr' + _W_msg_uninstaller='Run uninstaller' _W_msg_shell='Run a commandline shell (for debugging)' _W_msg_folder='Browse files' _W_msg_annihilate="Delete ALL DATA AND APPLICATIONS INSIDE THIS WINEPREFIX" @@ -2507,13 +2614,14 @@ winetricks_mainmenu() _W_msg_body='Was möchten Sie tun?' _W_msg_dlls="Windows-DLL installieren" _W_msg_fonts='Schriftart installieren' - _W_msg_settings='Change Wine settings' - _W_msg_winecfg='Run winecfg' - _W_msg_regedit='Run regedit' - _W_msg_taskmgr='Run taskmgr' - _W_msg_shell='Run a commandline shell (for debugging)' - _W_msg_folder='Browse files' - _W_msg_annihilate="Delete ALL DATA AND APPLICATIONS INSIDE THIS WINEPREFIX" + _W_msg_settings='Wine Einstellungen ändern' + _W_msg_winecfg='winecfg starten' + _W_msg_regedit='regedit starten' + _W_msg_taskmgr='taskmgr starten' + _W_msg_uninstaller='uninstaller starten' + _W_msg_shell='Eine Kommandozeile zum debuggen starten' + _W_msg_folder='Ordner durchsuchen' + _W_msg_annihilate="ALLE DATEIEN UND PROGRAMME IN DIESEM WINEPREFIX Löschen" ;; pl*) _W_msg_title="Winetricks - obecny prefiks to \"$WINEPREFIX\"" _W_msg_body='What would you like to do to this wineprefix?' @@ -2523,10 +2631,24 @@ winetricks_mainmenu() _W_msg_winecfg='Uruchom winecfg' _W_msg_regedit='Uruchom regedit' _W_msg_taskmgr='Uruchom taskmgr' + _W_msg_uninstaller='Run uninstaller' _W_msg_shell='Uruchom powłokę wiersza poleceń (dla debugowania)' _W_msg_folder='Przeglądaj pliki' _W_msg_annihilate="Usuń WSZYSTKIE DANE I APLIKACJE WEWNĄTRZ TEGO WINEPREFIXA" ;; + ru*) _W_msg_title="Winetricks - текущий путь для wine (wineprefix) \"$WINEPREFIX\"" + _W_msg_body='Что вы хотите сделать с этим wineprefix?' + _W_msg_dlls="Установить DLL библиотеку или компонент Windows" + _W_msg_fonts='Установить шрифт' + _W_msg_settings='Поменять настройки' + _W_msg_winecfg='Запустить winecfg (редактор настроек wine)' + _W_msg_regedit='Запустить regedit (редактор рееста)' + _W_msg_taskmgr='Запустить taskmgr (менеджер задач)' + _W_msg_uninstaller='Запустить uninstaller (деинсталятор)' + _W_msg_shell='Запустить графический терминал (для отладки)' + _W_msg_folder='Проводник файлов' + _W_msg_annihilate="Удалить ВСЕ ДАННЫЕ И ПРИЛОЖЕНИЯ В ЭТОМ WINEPREFIX" + ;; uk*) _W_msg_title="Winetricks - поточний prefix \"$WINEPREFIX\"" _W_msg_body='Що Ви хочете зробити для цього wineprefix?' _W_msg_dlls="Встановити Windows DLL чи компонент(и)" @@ -2535,6 +2657,7 @@ winetricks_mainmenu() _W_msg_winecfg='Запустити winecfg' _W_msg_regedit='Запустити regedit' _W_msg_taskmgr='Запустити taskmgr' + _W_msg_uninstaller='Run uninstaller' _W_msg_shell='Запуск командної оболонки (для налагодження)' _W_msg_folder='Перегляд файлів' _W_msg_annihilate="Видалити УСІ ДАНІ ТА ПРОГРАМИ З ЦЬОГО WINEPREFIX" @@ -2547,23 +2670,12 @@ winetricks_mainmenu() _W_msg_winecfg='运行 winecfg' _W_msg_regedit='运行注册表' _W_msg_taskmgr='运行任务管理器' + _W_msg_uninstaller='运行卸载程序' _W_msg_shell='运行命令提示窗口 (作为调试)' _W_msg_folder='浏览容器中的文件' _W_msg_annihilate="删除当前容器所有相关文件,包括启动器,完全卸载" ;; - zh_TW*) _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\"" - _W_msg_body='管理目前容器' - _W_msg_dlls="裝載 Windows DLL 或套件" - _W_msg_fonts='裝載字型' - _W_msg_settings='修改設定' - _W_msg_winecfg='執行 winecfg' - _W_msg_regedit='執行註冊表' - _W_msg_taskmgr='執行工作管理者' - _W_msg_shell='執行指令輔助說明視窗 (作為除錯)' - _W_msg_folder='瀏覽容器中的檔案' - _W_msg_annihilate="移除目前容器所有相依檔案,包括啟動器,完全卸載" - ;; - zh_HK*) _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\"" + zh_TW*|zh_HK*) _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\"" _W_msg_body='管理目前容器' _W_msg_dlls="裝載 Windows DLL 或套件" _W_msg_fonts='裝載字型' @@ -2571,6 +2683,7 @@ winetricks_mainmenu() _W_msg_winecfg='執行 winecfg' _W_msg_regedit='執行註冊表' _W_msg_taskmgr='執行工作管理者' + _W_msg_uninstaller='執行反安裝程式' _W_msg_shell='執行指令輔助說明視窗 (作為除錯)' _W_msg_folder='瀏覽容器中的檔案' _W_msg_annihilate="移除目前容器所有相依檔案,包括啟動器,完全卸載" @@ -2583,6 +2696,7 @@ winetricks_mainmenu() _W_msg_winecfg='Run winecfg' _W_msg_regedit='Run regedit' _W_msg_taskmgr='Run taskmgr' + _W_msg_uninstaller='Run uninstaller' _W_msg_shell='Run a commandline shell (for debugging)' _W_msg_folder='Browse files' _W_msg_annihilate="Delete ALL DATA AND APPLICATIONS INSIDE THIS WINEPREFIX" @@ -2603,15 +2717,16 @@ winetricks_mainmenu() --height $WINETRICKS_MENU_HEIGHT \ --width $WINETRICKS_MENU_WIDTH \ --hide-column 2 \ - FALSE dlls '$_W_msg_dlls' \ - FALSE fonts '$_W_msg_fonts' \ - FALSE settings '$_W_msg_settings' \ - FALSE winecfg '$_W_msg_winecfg' \ - FALSE regedit '$_W_msg_regedit' \ - FALSE taskmgr '$_W_msg_taskmgr' \ - FALSE shell '$_W_msg_shell' \ - FALSE folder '$_W_msg_folder' \ - FALSE annihilate '$_W_msg_annihilate' \ + FALSE dlls '$_W_msg_dlls' \ + FALSE fonts '$_W_msg_fonts' \ + FALSE settings '$_W_msg_settings' \ + FALSE winecfg '$_W_msg_winecfg' \ + FALSE regedit '$_W_msg_regedit' \ + FALSE taskmgr '$_W_msg_taskmgr' \ + FALSE uninstaller '$_W_msg_uninstaller' \ + FALSE shell '$_W_msg_shell' \ + FALSE folder '$_W_msg_folder' \ + FALSE annihilate '$_W_msg_annihilate' \ " ) > "$WINETRICKS_WORKDIR"/zenity.sh sh "$WINETRICKS_WORKDIR"/zenity.sh | tr '|' ' ' @@ -2623,15 +2738,16 @@ winetricks_mainmenu() --separate-output \ --radiolist \ "$_W_msg_body"\ - dlls "$_W_msg_dlls" off \ - fonts "$_W_msg_fonts" off \ - settings "$_W_msg_settings" off \ - winecfg "$_W_msg_winecfg" off \ - regedit "$_W_msg_regedit" off \ - taskmgr "$_W_msg_taskmgr" off \ - shell "$_W_msg_shell" off \ - folder "$_W_msg_folder" off \ - annihilate "$_W_msg_annihilate" off \ + dlls "$_W_msg_dlls" off \ + fonts "$_W_msg_fonts" off \ + settings "$_W_msg_settings" off \ + winecfg "$_W_msg_winecfg" off \ + regedit "$_W_msg_regedit" off \ + taskmgr "$_W_msg_taskmgr" off \ + uninstaller "$_W_msg_uninstaller" off \ + shell "$_W_msg_shell" off \ + folder "$_W_msg_folder" off \ + annihilate "$_W_msg_annihilate" off \ $_W_cmd_unattended "$_W_msg_unattended" off \ ;; @@ -2646,22 +2762,22 @@ winetricks_settings_menu() da*) _W_msg_title='Vælg en pakke' _W_msg_body='Which settings would you like to change?' ;; - de*) _W_msg_title='Pakete auswählen' - _W_msg_body='Which settings would you like to change?' + de*) _W_msg_title="Winetricks - Aktueller Prefix ist \"$WINEPREFIX\"" + _W_msg_body='Welche Einstellungen möchten Sie ändern?' ;; pl*) _W_msg_title="Winetricks - obecny prefiks to \"$WINEPREFIX\"" _W_msg_body='Which settings would you like to change?' ;; + ru*) _W_msg_title="Winetricks - текущий путь wine (wineprefix) \"$WINEPREFIX\"" + _W_msg_body='Какие настройки вы хотите изменить?' + ;; uk*) _W_msg_title="Winetricks - поточний prefix \"$WINEPREFIX\"" _W_msg_body='Які налаштування Ви хочете змінити?' ;; zh_CN*) _W_msg_title="Windows 应用安装向导 - 当前容器路径是 \"$WINEPREFIX\"" _W_msg_body='君欲更改哪项设置?' ;; - zh_TW*) _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\"" - _W_msg_body='君欲變更哪項設定?' - ;; - zh_HK*) _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\"" + zh_TW*|zh_HK*) _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\"" _W_msg_body='君欲變更哪項設定?' ;; *) _W_msg_title="Winetricks - current prefix is \"$WINEPREFIX\"" @@ -2690,7 +2806,7 @@ winetricks_settings_menu() --list \ --checklist \ --column '' \ - --column Paket \ + --column Einstellung \ --column Name \ --height $WINETRICKS_MENU_HEIGHT \ --width $WINETRICKS_MENU_WIDTH \ @@ -2708,6 +2824,18 @@ winetricks_settings_menu() --width $WINETRICKS_MENU_WIDTH \ " ;; + ru*) printf %s "zenity \ + --title '$_W_msg_title' \ + --text '$_W_msg_body' \ + --list \ + --checklist \ + --column '' \ + --column Установка \ + --column Имя \ + --height $WINETRICKS_MENU_HEIGHT \ + --width $WINETRICKS_MENU_WIDTH \ + " + ;; uk*) printf %s "zenity \ --title '$_W_msg_title' \ --text '$_W_msg_body' \ @@ -2732,19 +2860,7 @@ winetricks_settings_menu() --width $WINETRICKS_MENU_WIDTH \ " ;; - zh_TW*) printf %s "zenity \ - --title '$_W_msg_title' \ - --text '$_W_msg_body' \ - --list \ - --checklist \ - --column '' \ - --column 設定 \ - --column 標題 \ - --height $WINETRICKS_MENU_HEIGHT \ - --width $WINETRICKS_MENU_WIDTH \ - " - ;; - zh_HK*) printf %s "zenity \ + zh_TW*|zh_HK*) printf %s "zenity \ --title '$_W_msg_title' \ --text '$_W_msg_body' \ --list \ @@ -2814,14 +2930,18 @@ winetricks_showmenu() _W_msg_body='Vilken pakke vil du installere?' _W_cached="cached" ;; - de*) _W_msg_title='Pakete auswählen' - _W_msg_body='Welche Pakete möchten Sie installieren?' + de*) _W_msg_title="Winetricks - Aktueller Prefix ist \"$WINEPREFIX\"" + _W_msg_body='Welche Paket(e) möchten Sie installieren?' _W_cached="gecached" ;; pl*) _W_msg_title="Winetricks - obecny prefiks to \"$WINEPREFIX\"" _W_msg_body='Które paczki chesz zainstalować?' _W_cached="zarchiwizowane" ;; + ru*) _W_msg_title="Winetricks - текущий путь wine (wineprefix) \"$WINEPREFIX\"" + _W_msg_body='Какое приложение(я) вы хотите установить?' + _W_cached="в кэше" + ;; uk*) _W_msg_title="Winetricks - поточний prefix \"$WINEPREFIX\"" _W_msg_body='Які пакунки Ви хочете встановити?' _W_cached="кешовано" @@ -2830,11 +2950,7 @@ winetricks_showmenu() _W_msg_body='君欲安装何种应用?' _W_cached="已缓存" ;; - zh_TW*) _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\"" - _W_msg_body='君欲裝載何種應用?' - _W_cached="已緩存" - ;; - zh_HK*) _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\"" + zh_TW*|zh_HK*) _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\"" _W_msg_body='君欲裝載何種應用?' _W_cached="已緩存" ;; @@ -2902,6 +3018,24 @@ winetricks_showmenu() --width $WINETRICKS_MENU_WIDTH \ " ;; + ru*) printf %s "zenity \ + --title '$_W_msg_title' \ + --text '$_W_msg_body' \ + --list \ + --checklist \ + --column '' \ + --column Пакет \ + --column Название \ + --column Издатель \ + --column Год \ + --column Источник \ + --column Статус \ + --column 'Размер (МБ)' \ + --column 'Время (сек)' \ + --height $WINETRICKS_MENU_HEIGHT \ + --width $WINETRICKS_MENU_WIDTH \ + " + ;; uk*) printf %s "zenity \ --title '$_W_msg_title' \ --text '$_W_msg_body' \ @@ -2938,25 +3072,7 @@ winetricks_showmenu() --width $WINETRICKS_MENU_WIDTH \ " ;; - zh_TW*) printf %s "zenity \ - --title '$_W_msg_title' \ - --text '$_W_msg_body' \ - --list \ - --checklist \ - --column '' \ - --column 包名 \ - --column 軟體名 \ - --column 發行商 \ - --column 發行年 \ - --column 媒介 \ - --column 狀態 \ - --column '檔案大小 (MB)' \ - --column '時間 (秒)' \ - --height $WINETRICKS_MENU_HEIGHT \ - --width $WINETRICKS_MENU_WIDTH \ - " - ;; - zh_HK*) printf %s "zenity \ + zh_TW*|zh_HK*) printf %s "zenity \ --title '$_W_msg_title' \ --text '$_W_msg_body' \ --list \ @@ -3124,7 +3240,7 @@ winetricks_is_installed() esac if test -d "$_W_prefix/dosdevices" then - # 'win7 vcrun2005' creates diffrent file than 'winxp vcrun2005' + # 'win7 vcrun2005' creates different file than 'winxp vcrun2005' # so let it specify multiple, separated by | _W_IFS="$IFS" IFS='|' @@ -3226,10 +3342,10 @@ winetricks_list_all() da*) _W_cached="cached" ; _W_download="kan hentes" ;; de*) _W_cached="gecached" ; _W_download="herunterladbar";; pl*) _W_cached="zarchiwizowane" ; _W_download="do pobrania" ;; + ru*) _W_cached="в кэше" ; _W_download="доступно для скачивания" ;; uk*) _W_cached="кешовано" ; _W_download="завантажуване" ;; zh_CN*) _W_cached="已缓存" ; _W_download="可下载" ;; - zh_TW*) _W_cached="已緩存" ; _W_download="可下載" ;; - zh_HK*) _W_cached="已緩存" ; _W_download="可下載" ;; + zh_TW*|zh_HK*) _W_cached="已緩存" ; _W_download="可下載" ;; *) _W_cached="cached" ; _W_download="downloadable" ;; esac @@ -3464,12 +3580,12 @@ winetricks_cache_iso() then case $LANG in da*) w_warn "Forkert disk [$_W_volname] indsat. Indsæt venligst disken [$_W_expected_volname]" ;; - de*) w_warn "Falsche Disk [$_W_volname] eingelegt. Bitte legen Sie Disk [$_W_expected_volname] ein!" ;; - pl*) w_warn "Włożono zły dysk [$_W_volname]. Proszę włożyć dysk [$_W_expected_volname]" ;; - uk*) w_warn "Неправильний диск [$_W_volname]. Будь ласка, вставте диск [$_W_expected_volname]" ;; + de*) w_warn "Falsche Disk [$_W_volname] eingelegt. Bitte legen Sie Disk [$_W_expected_volname] ein!" ;; + pl*) w_warn "Włożono zły dysk [$_W_volname]. Proszę włożyć dysk [$_W_expected_volname]" ;; + ru*) w_warn "Неверный диск [$_W_volname]. Пожалуйста, вставьте диск [$_W_expected_volname]" ;; + uk*) w_warn "Неправильний диск [$_W_volname]. Будь ласка, вставте диск [$_W_expected_volname]" ;; zh_CN*) w_warn " [$_W_volname] 光盘插入错误,请插入光盘 [$_W_expected_volname]" ;; - zh_TW*) w_warn " [$_W_volname] 光槃插入錯誤,請插入光槃 [$_W_expected_volname]" ;; - zh_HK*) w_warn " [$_W_volname] 光槃插入錯誤,請插入光槃 [$_W_expected_volname]" ;; + zh_TW*|zh_HK*) w_warn " [$_W_volname] 光碟插入錯誤,請插入光碟 [$_W_expected_volname]" ;; *) w_warn "Wrong disc [$_W_volname] inserted. Please insert disc [$_W_expected_volname]" ;; esac @@ -3685,12 +3801,12 @@ winetricks_mount_real_volume() case $LANG in da*)_W_mountmsg="Indsæt venligst disken '$_W_expected_volname' (krævet af pakken '$_PACKAGE')" ;; - de*)_W_mountmsg="Disc '$_W_expected_volname' bitte einlegen (für Pakete '$W_PACKAGE')" ;; + de*)_W_mountmsg="Bitte Disk '$_W_expected_volname' einlegen (für Paket '$W_PACKAGE')" ;; pl*) _W_mountmsg="Proszę włożyć dysk '$_W_expected_volname' (potrzebny paczce '$W_PACKAGE')" ;; + ru*) _W_mountmsg="Пожалуйста, вставьте том '$_W_expected_volname' (требуется для пакета '$W_PACKAGE')" ;; uk*) _W_mountmsg="Будь ласка, вставте том '$_W_expected_volname' (потрібний для пакунка '$W_PACKAGE')" ;; zh_CN*) _W_mountmsg="请插入卷 '$_W_expected_volname' (为包 '$W_PACKAGE 所需')" ;; - zh_TW*) _W_mountmsg="請插入卷 '$_W_expected_volname' (為包 '$W_PACKAGE 所需')" ;; - zh_HK*) _W_mountmsg="請插入卷 '$_W_expected_volname' (為包 '$W_PACKAGE 所需')" ;; + zh_TW*|zh_HK*) _W_mountmsg="請插入卷 '$_W_expected_volname' (為包 '$W_PACKAGE 所需')" ;; *) _W_mountmsg="Please insert volume '$_W_expected_volname' (needed for package '$W_PACKAGE')" ;; esac @@ -3754,6 +3870,10 @@ winetricks_set_unattended() # Might want to trim our stable of variables here a bit... W_UNATTENDED_DASH_Q="-q" W_UNATTENDED_SLASH_Q="/q" + W_UNATTENDED_SLASH_QN="/qn" + W_UNATTENDED_SLASH_QNT="/qnt" + W_UNATTENDED_SLASH_QT="/qt" + W_UNATTENDED_SLASH_QUIET="/quiet" W_UNATTENDED_SLASH_S="/S" W_UNATTENDED_DASH_SILENT="-silent" W_UNATTENDED_SLASH_SILENT="/silent" @@ -3762,6 +3882,10 @@ winetricks_set_unattended() W_OPT_UNATTENDED="" W_UNATTENDED_DASH_Q="" W_UNATTENDED_SLASH_Q="" + W_UNATTENDED_SLASH_QN="" + W_UNATTENDED_SLASH_QNT="" + W_UNATTENDED_SLASH_QT="" + W_UNATTENDED_SLASH_QUIET="" W_UNATTENDED_SLASH_S="" W_UNATTENDED_DASH_SILENT="" W_UNATTENDED_SLASH_SILENT="" @@ -3770,7 +3894,7 @@ winetricks_set_unattended() } # Usage: winetricks_set_wineprefix [bottlename] -# Bottlename must not contain spaces, slashes, or other special charaters +# Bottlename must not contain spaces, slashes, or other special characters # If bottlename is omitted, the default bottle (~/.wine) is used. winetricks_set_wineprefix() { @@ -3788,7 +3912,7 @@ winetricks_set_wineprefix() # The folder-name is localized! W_PROGRAMS_WIN="`w_expand_env ProgramFiles`" case "$W_PROGRAMS_WIN" in - "") w_die "$WINE cmd.exe /c echo '%ProgramFiles%' returned empty string, error message \"`cat $W_TMP_EARLY/early_wine.err.txt`\" ";; + "") w_die "$WINE cmd.exe /c echo '%ProgramFiles%' returned empty string, error message \"`cat $W_TMP_EARLY/early_wine.err.txt`\" ";; %*) w_die "$WINE cmd.exe /c echo '%ProgramFiles%' returned unexpanded string '$W_PROGRAMS_WIN' ... this can be caused by a corrupt wineprefix, by an old wine, or by not owning $WINEPREFIX" ;; *unknown*) w_die "$WINE cmd.exe /c echo '%ProgramFiles%' returned a string containing the word 'unknown', as if a voice had cried out in terror, and was suddenly silenced." ;; esac @@ -3995,15 +4119,14 @@ winetricks_init() ;; *) WINE="${WINE:-wine}" - # Find wineserver. Some distros (Debian) don't have it on the path, - # on the mistaken understanding that user scripts never need it :-( - # If wineserver is from wine-development set WINE to wine-development. - # FIXME: get packagers to put wineserver on the path. + # Find wineserver. + # Some distros (Debian before wine 1.8-2) don't have it on the path. for x in \ "$WINESERVER" \ "${WINE}server" \ "`which wineserver 2> /dev/null`" \ "`dirname $WINE`/server/wineserver" \ + /usr/bin/wineserver-development \ /usr/lib/wine/wineserver \ /usr/lib/i386-kfreebsd-gnu/wine/wineserver \ /usr/lib/i386-linux-gnu/wine/wineserver \ @@ -4021,7 +4144,7 @@ winetricks_init() if test -x "$x" then case "$x" in - /usr/lib/*/wine-development/wineserver) + /usr/lib/*/wine-development/wineserver|/usr/bin/wineserver-development) if test -x /usr/bin/wine-development then WINE="/usr/bin/wine-development" @@ -4058,7 +4181,7 @@ winetricks_init() unset _abswine ;; esac - winetricks_set_wineprefix + winetricks_set_wineprefix $1 # FIXME: don't hardcode W_PROGRAMS_DRIVE=c @@ -4078,6 +4201,8 @@ winetricks_init() wine-1.4) WINETRICKS_WINE_VERSION="wine-1.4.0"; export WINETRICKS_WINE_VERSION;; wine-1.6-*) WINETRICKS_WINE_VERSION="wine-1.6.0"; export WINETRICKS_WINE_VERSION;; wine-1.6) WINETRICKS_WINE_VERSION="wine-1.6.0"; export WINETRICKS_WINE_VERSION;; + wine-1.8-*) WINETRICKS_WINE_VERSION="wine-1.8.0"; export WINETRICKS_WINE_VERSION;; + wine-1.8) WINETRICKS_WINE_VERSION="wine-1.8.0"; export WINETRICKS_WINE_VERSION;; esac WINETRICKS_WINE_MINOR=`echo $WINETRICKS_WINE_VERSION | sed 's/wine-1\.\([0-9]*\)\..*/\1/'` WINETRICKS_WINE_MICRO=`echo $WINETRICKS_WINE_VERSION | sed 's/wine-1.[0-9][0-9]*\.\([0-9]*\).*/\1/'` @@ -4107,24 +4232,37 @@ _EOF_ ;; de*) cat <<_EOF_ -Usage: $0 [options] [verb|path-to-verb] ... +Benutzung: $0 [options] [Kommando|Verb|Pfad-zu-Verb] ... Angegebene Verben ausführen. -Jeder Verb installiert z.B. eine Anwendung oder ändert eine Einstellung. +Jedes Verb installiert eine Anwendung oder ändert eine Einstellung. + Optionen: --k|--keep_isos: isos local speichern (erlaubt spätere Installierung ohne Disk) --q|--unattended: keine Fragen stellen, alles automatisch installieren --r|--ddrescue: alternative Zugriffsmodus (hilft bei gekratzten Disks) --v|--verbose: alle ausgeführten Kommandos anzeigen --V|--version: Programmversion anzeigen --h|--help: diese Hilfemeldung anzeigen -Verben: -apps: Typ 'Andwendungen' auswählen -games: Typ 'Spiele' auswählen -list: Verben von ausgewählte Typ auflisten -list-cached: Verben für schon gecachte Installers auflisten -list-download: Verben für herunterladbare Anwendungen auflisten -list-manual-download: list applications which can be downloaded with some help from the user -list-installed: Verben für schon installlierte Programme auflisten + --force Nicht prüfen ob Pakete bereits installiert wurden + --gui GUI Diagnosen anzeigen, auch wenn von der Kommandozeile gestartet + --isolate Jedes Programm oder Spiel in eigener Bottle (WINEPREFIX) installieren +-k, --keep_isos ISOs local speichern (erlaubt spätere Installation ohne Disk) + --no-clean Temp Verzeichnisse nicht löschen (nützlich beim debuggen) +-q, --unattended Keine Fragen stellen, alles automatisch installieren +-r, --ddrescue Alternativer Zugriffsmodus (hilft bei zerkratzten Disks) + --showbroken Auch Verben anzeigen die momentan in Wine nicht funktionieren + --verify Wenn Möglisch automatische GUI Tests für Verben starten +-v, --verbose Alle ausgeführten Kommandos anzeigen +-h, --help Diese Hilfemeldung anzeigen +-V, --version Programmversion anzeigen und Beenden + +Kommandos: +list Kategorien auflisten +list-all Alle Kategorien und deren Verben auflisten +apps list Verben der Kategorie 'Anwendungen' auflisten +benchmarks list Verben der Kategorie 'Benchmarks' auflisten +dlls list Verben der Kategorie 'DLLs' auflisten +games list Verben der Kategorie 'Spiele' auflisten +settings list Verben der Kategorie 'Einstellungen' auflisten +list-cached Verben für bereits gecachte Installers auflisten +list-download Verben für automatisch herunterladbare Anwendungen auflisten +list-manual-download Verben für vom Benutzer herunterladbare Anwendungen auflisten +list-installed Bereits installierte Verben auflisten +prefix=foobar WINEPREFIX=$W_PREFIXES_ROOT/foobar auswählen _EOF_ ;; *) @@ -4198,7 +4336,7 @@ then # Which GUI helper to use (none/zenity/kdialog). See winetricks_detect_gui. WINETRICKS_GUI=none # Default to a shared prefix: - WINETRICKS_OPT_SHAREDPREFIX=1 + WINETRICKS_OPT_SHAREDPREFIX=${WINETRICKS_OPT_SHAREDPREFIX:-1} # Handle options before init, to avoid starting wine for --help or --version while winetricks_handle_option $1 @@ -4206,19 +4344,25 @@ then shift done - winetricks_init + # Workaround for https://github.com/Winetricks/winetricks/issues/599 + # If --isolate is used, pass verb to winetricks_init, so it can set the wineprefix using winetricks_set_wineprefix() + # Otherwise, an arch mismatch between ${WINEPREFIX:-$HOME/.wine} and the prefix to be made for the isolated app would cause it to fail + case $WINETRICKS_OPT_SHAREDPREFIX in + 0) winetricks_init $1 ;; + *) winetricks_init ;; + esac fi winetricks_install_app() { case $LANG in da*) fail_msg="Installationen af pakken $1 fejlede" ;; - de*) fail_msg="Installieren von Pakete $1 gescheitert" ;; + de*) fail_msg="Installieren von Paket $1 gescheitert" ;; pl*) fail_msg="Niepowodzenie przy instalacji paczki $1" ;; + ru*) fail_msg="Ошибка установки пакета $1" ;; uk*) fail_msg="Помилка встановлення пакунка $1" ;; zh_CN*) fail_msg="$1 安装失败" ;; - zh_TW*) fail_msg="$1 裝載失敗" ;; - zh_HK*) fail_msg="$1 裝載失敗" ;; + zh_TW*|zh_HK*) fail_msg="$1 安裝失敗" ;; *) fail_msg="Failed to install package $1" ;; esac @@ -4269,6 +4413,14 @@ helper_d3dx9_xx() do w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F "$dllname.dll" "$x" done + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F "*$dllname*x64*" "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F "$dllname.dll" "$x" + done + fi w_override_dlls native $dllname } @@ -4305,9 +4457,9 @@ helper_win7sp1() #--------------------------------------------------------- w_metadata adobeair dlls \ - title="Adobe AIR 15.0" \ + title="Adobe AIR 20.x" \ publisher="Adobe" \ - year="2014" \ + year="2015" \ media="download" \ file1="AdobeAIRInstaller.exe" \ installed_file1="$W_COMMONFILES_X86_WIN/Adobe AIR/Versions/1.0/Adobe AIR.dll" \ @@ -4324,9 +4476,14 @@ load_adobeair() # 2014-03-01: 4.0 sha1sum 0034bdd4e0b2ce0fa6198b0b715fba85754d9a57 # http://helpx.adobe.com/en/flash-player/release-note/fp_12_air_4_release_notes.html # 2014-09-30: 15.0 sha1sum 46341f1358bc6e0b9ddeae3591662a2ac68dc360 - # 2014-11-24: i15.0.0.356 sha1sum c0e6b8b1ed5ffa282945d21b21f8a5e03febc904 - w_download http://airdownload.adobe.com/air/win/download/15.0/AdobeAIRInstaller.exe c0e6b8b1ed5ffa282945d21b21f8a5e03febc904 - cd "$W_CACHE"/adobeair + # 2014-11-24: 15.0.0.356 sha1sum c0e6b8b1ed5ffa282945d21b21f8a5e03febc904 + # 2015-11-06: 19.x sha1sum 3bc2a568204a3a9b59ca347ab49585f0c5fab279 + # 2015-12-27: 20.0 sha1sum 9c10b7be43771869c381c73197c9a0fcd1b727cf + # 2015-12-29: 20.0.0.233 (had to check with strings on Adobe AIR.dll) sha1sum 7161fb8b47721485882f52720f8b41dbfe3b69d0 + # 2016-02-17: 20.0.0.260 (strings 'Adobe AIR.dll' | grep 20\\. ) sha1sum 2fdd561556fe881c4e5538d4ee37f523871befd3 + + w_download http://airdownload.adobe.com/air/win/download/20.0/AdobeAIRInstaller.exe 2fdd561556fe881c4e5538d4ee37f523871befd3 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" AdobeAIRInstaller.exe $W_UNATTENDED_DASH_SILENT } @@ -4366,7 +4523,7 @@ load_art2kmin() { # See http://www.microsoft.com/downloads/details.aspx?familyid=d9ae78d9-9dc6-4b38-9fa6-2c745a175aed&displaylang=en w_download http://download.microsoft.com/download/D/2/A/D2A2FC8B-0447-491C-A5EF-E8AA3A74FB98/AccessRuntime.exe 571811b7536e97cf4e4e53bbf8260cddd69f9b2d - cd "$W_CACHE"/art2kmin + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" AccessRuntime.exe $W_UNATTENDED_SLASH_Q } @@ -4417,7 +4574,7 @@ w_metadata cabinet dlls \ load_cabinet() { # http://www.microsoft.com/downloads/en/details.aspx?FamilyId=9AD000F2-CAE7-493D-B0F3-AE36C570ADE8&displaylang=en - w_download http://web.archive.org/web/20080731135848/http://download.microsoft.com/download/3/b/f/3bf74b01-16ba-472d-9a8c-42b2b4fa0d76/mdac_typ.exe f68594d1f578c3b47bf0639c46c11c5da161feee + w_download http://download.microsoft.com/download/3/b/f/3bf74b01-16ba-472d-9a8c-42b2b4fa0d76/mdac_typ.exe f68594d1f578c3b47bf0639c46c11c5da161feee w_try_cabextract --directory="$W_TMP" "$W_CACHE"/cabinet/$file1 w_try cp "$W_TMP"/cabinet.dll "$W_SYSTEM32_DLLS"/cabinet.dll @@ -4436,8 +4593,8 @@ w_metadata cmd dlls \ load_cmd() { - w_download http://download.microsoft.com/download/8/d/c/8dc79965-dfbc-4b25-9546-e23bc4b791c6/Q811493_W2K_SP4_X86_EN.exe ac6e28cfd12942e74aa08bddf7715705edb85b6b - w_try_cabextract --directory="$W_SYSTEM32_DLLS" "$W_CACHE"/cmd/Q811493_W2K_SP4_X86_EN.exe -F cmd.exe + w_download ftp://ftp.sunet.se/pub/security/vendor/microsoft/win2000/Security_Bulletins/Q811493_W2K_SP4_X86_EN.exe ac6e28cfd12942e74aa08bddf7715705edb85b6b + w_try_cabextract --directory="$W_SYSTEM32_DLLS" "$W_CACHE/$W_PACKAGE/$file1" -F cmd.exe w_override_dlls native,builtin cmd.exe } @@ -4454,9 +4611,11 @@ w_metadata comctl32 dlls \ load_comctl32() { - # http://www.microsoft.com/downloads/details.aspx?familyid=6f94d31a-d1e0-4658-a566-93af0d8d4a1e - #w_download http://download.microsoft.com/download/platformsdk/redist/5.80.2614.3600/w9xnt4/en-us/cc32inst.exe 94c3c494258cc54bd65d2f0153815737644bffde - w_download $WINETRICKS_SOURCEFORGE/pocmin/Win%2095_98%20Controls/Win%2095_98%20Controls/CC32inst.exe 94c3c494258cc54bd65d2f0153815737644bffde cc32inst.exe + # 2011-01-17: http://www.microsoft.com/downloads/details.aspx?familyid=6f94d31a-d1e0-4658-a566-93af0d8d4a1e + # 2012-08-11: w_download http://download.microsoft.com/download/platformsdk/redist/5.80.2614.3600/w9xnt4/en-us/cc32inst.exe 94c3c494258cc54bd65d2f0153815737644bffde + # 2016/01/07: w_download ftp://ftp.ie.debian.org/disk1/download.sourceforge.net/pub/sourceforge/p/po/pocmin/Win%2095_98%20Controls/Win%2095_98%20Controls/CC32inst.exe + + w_download ftp://ftp.ie.debian.org/disk1/download.sourceforge.net/pub/sourceforge/p/po/pocmin/Win%2095_98%20Controls/Win%2095_98%20Controls/CC32inst.exe 94c3c494258cc54bd65d2f0153815737644bffde cc32inst.exe w_try "$WINE" "$W_CACHE"/comctl32/cc32inst.exe "/T:$W_TMP_WIN" /c $W_UNATTENDED_SLASH_Q w_try_unzip "$W_TMP" "$W_TMP"/comctl32.exe @@ -4507,14 +4666,14 @@ w_metadata comdlg32ocx dlls \ publisher="Microsoft" \ year="2009" \ media="download" \ - file1="comdlg32.cab" \ + file1="ComDlg32.cab" \ installed_file1="$W_SYSTEM32_DLLS_WIN/comdlg32.ocx" load_comdlg32ocx() { # By analogy with vb5 version in http://support.microsoft.com/kb/168917 - w_download http://activex.microsoft.com/controls/vb6/comdlg32.cab d4f3e193c6180eccd73bad53a8500beb5b279cbf - w_try_cabextract --directory="$W_TMP" "$W_CACHE"/comdlg32ocx/comdlg32.cab + w_download http://activex.microsoft.com/controls/vb6/ComDlg32.cab d4f3e193c6180eccd73bad53a8500beb5b279cbf + w_try_cabextract --directory="$W_TMP" "$W_CACHE"/comdlg32ocx/${file1} w_try cp "$W_TMP"/comdlg32.ocx "$W_SYSTEM32_DLLS"/comdlg32.ocx w_try_regsvr comdlg32.ocx } @@ -4552,8 +4711,12 @@ w_metadata binkw32 dlls \ load_binkw32() { # Mirror: http://www.dlldump.com/download-dll-files_new.php/dllfiles/B/binkw32.dll/1.0q/download.html - # Checksum of the decompressed file: 613f81f82e12131e86ae60dd318941f40db2200f - w_download http://www.down-dll.com/dll/b/__32-binkw32.dll3.0.0.0.zip 991f77e8df513ccb8663dc4a2753fbf90338ef5c + # Sha1sum of the decompressed file: 613f81f82e12131e86ae60dd318941f40db2200f + # + # Zip sha1sum: + # 2015-03-28: 991f77e8df513ccb8663dc4a2753fbf90338ef5c + # 2015-12-27: 6a30900885390ef361dbb67444a7944143db36bf + w_download http://www.down-dll.com/dll/b/__32-binkw32.dll3.0.0.0.zip 6a30900885390ef361dbb67444a7944143db36bf w_try_unzip "$W_TMP" "$W_CACHE"/binkw32/__32-binkw32.dll3.0.0.0.zip w_try cp "$W_TMP"/binkw32.dll "$W_SYSTEM32_DLLS"/binkw32.dll @@ -4583,6 +4746,14 @@ load_d3dcompiler_43() do w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F "$dllname.dll" "$x" done + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F "*$dllname*x64*" "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F "$dllname.dll" "$x" + done + fi w_override_dlls native $dllname } @@ -4627,6 +4798,14 @@ load_d3dx9() do w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F 'd3dx9*.dll' "$x" done + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F '*d3dx9*x64*' "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'd3dx9*.dll' "$x" + done + fi # For now, not needed, but when Wine starts preferring our builtin dll over native it will be. w_override_dlls native d3dx9_24 d3dx9_25 d3dx9_26 d3dx9_27 d3dx9_28 d3dx9_29 d3dx9_30 @@ -4760,6 +4939,14 @@ load_d3dx9_43() do w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F "$dllname.dll" "$x" done + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F "*$dllname*x64*" "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F "$dllname.dll" "$x" + done + fi w_override_dlls native $dllname } @@ -4785,6 +4972,14 @@ load_d3dx11_42() do w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F "$dllname.dll" "$x" done + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F "*$dllname*x64*" "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F "$dllname.dll" "$x" + done + fi w_override_dlls native $dllname } @@ -4810,6 +5005,14 @@ load_d3dx11_43() do w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F "$dllname.dll" "$x" done + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F "*$dllname*x64*" "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F "$dllname.dll" "$x" + done + fi w_override_dlls native $dllname } @@ -4821,12 +5024,12 @@ w_metadata d3dx10 dlls \ publisher="Microsoft" \ year="2010" \ media="download" \ - file1="../directx9/directx_feb2010_redist.exe" \ + file1="../directx9/directx_Jun2010_redist.exe" \ installed_file1="$W_SYSTEM32_DLLS_WIN/d3dx10_33.dll" load_d3dx10() { - helper_directx_dl + helper_directx_Jun2010 # Kinder, less invasive directx10 - only extract and override d3dx10_??.dll w_try_cabextract -d "$W_TMP" -L -F '*d3dx10*x86*' "$W_CACHE"/directx9/$DIRECTX_NAME @@ -4834,6 +5037,14 @@ load_d3dx10() do w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F 'd3dx10*.dll' "$x" done + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F '*d3dx10*x64*' "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'd3dx10*.dll' "$x" + done + fi # For now, not needed, but when Wine starts preferring our builtin dll over native it will be. w_override_dlls native d3dx10_33 d3dx10_34 d3dx10_35 d3dx10_36 d3dx10_37 @@ -5044,7 +5255,7 @@ load_directx9() # See http://code.google.com/p/winezeug/issues/detail?id=71 w_set_winver winxp - cd "$W_CACHE"/directx9 + cd "$W_CACHE/$W_PACKAGE" WINEDLLOVERRIDES="wintrust=b,mscoree=,ddraw,d3d8,d3d9,dsound,dinput=n" \ w_try "$WINE" $DIRECTX_NAME /t:"$W_TMP_WIN" $W_UNATTENDED_SLASH_Q @@ -5321,16 +5532,11 @@ load_dotnet20() # FIXME: verify on pristine windows XP: if w_workaround_wine_bug 34803 then - "$WINE" reg delete 'HKLM\Software\Microsoft\.NETFramework\v2.0.50727\SBSDisabled' + "$WINE" reg delete 'HKLM\Software\Microsoft\.NETFramework\v2.0.50727\SBSDisabled' /f fi - cd "$W_CACHE"/dotnet20 - if w_workaround_wine_bug 30845 "Using native fusion while installing..." 1.5.8, - then - w_try env WINEDLLOVERRIDES=mscoree,fusion=n "$WINE" dotnetfx.exe ${W_OPT_UNATTENDED:+/q /c:"install.exe /q"} - else - w_try "$WINE" dotnetfx.exe ${W_OPT_UNATTENDED:+/q /c:"install.exe /q"} - fi + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" dotnetfx.exe ${W_OPT_UNATTENDED:+/q /c:"install.exe /q"} w_unset_winver # We can't stop installing dotnet20 in win2K mode until wine supports @@ -5341,11 +5547,6 @@ load_dotnet20() # This affects Victoria 2 demo, see http://forum.paradoxplaza.com/forum/showthread.php?p=11523967 rm -f "$W_SYSTEM32_DLLS"/msvc?80.dll - if w_workaround_wine_bug 30162 "Dirty hack, killing off mscorsvw.exe" 1.5.31, - then - w_killall "mscorsvw.exe" - fi - W_NGEN_CMD="w_try $WINE $DRIVE_C/windows/Microsoft.NET/Framework/v2.0.50727/ngen.exe executequeueditems" } @@ -5374,7 +5575,7 @@ load_dotnet20sdk() w_call dotnet20 - cd "$W_CACHE"/dotnet20sdk + cd "$W_CACHE/$W_PACKAGE" w_ahk_do " SetTitleMatchMode, 2 run, setup.exe ${W_OPT_UNATTENDED:+/q /c:"install.exe /q"} @@ -5458,7 +5659,7 @@ load_dotnet20sp1() # Workaround Wine/Mono integration: "$WINE" reg add "HKLM\\Software\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727" /v Version /t REG_SZ /d "2.0.50727" /f - cd "$W_CACHE"/dotnet20sp1 + cd "$W_CACHE/$W_PACKAGE" "$WINE" NetFx20SP1_x86.exe ${W_OPT_UNATTENDED:+/q} status=$? @@ -5507,28 +5708,13 @@ load_dotnet20sp2() w_call dotnet20 - WINEDLLOVERRIDES= - if w_workaround_wine_bug 22521 "Adding registry key, setting windows version so installer works" - then - # Recipe from http://bugs.winehq.org/show_bug.cgi?id=22521 - "$WINE" reg add "HKLM\Software\Microsoft\Net Framework Setup\NDP\v2.0.50727" /v Version /d "2.0.50727" /f - # Stop services - # Recipe from http://bugs.winehq.org/show_bug.cgi?id=16956 - $WINESERVER -k - # Fight a race condition, see bug 16956 comment 43 - w_set_winver win2k - $WINESERVER -w - WINEDLLOVERRIDES=regsvcs.exe,mscorsvw.exe=b - export WINEDLLOVERRIDES - fi - # FIXME: verify on pristine windows XP: if w_workaround_wine_bug 34803 then - "$WINE" reg delete 'HKLM\Software\Microsoft\.NETFramework\v2.0.50727\SBSDisabled' + "$WINE" reg delete 'HKLM\Software\Microsoft\.NETFramework\v2.0.50727\SBSDisabled' /f fi - cd "$W_CACHE"/dotnet20sp2 + cd "$W_CACHE/$W_PACKAGE" w_ahk_do " SetTitleMatchMode, 2 run, NetFx20SP2_x86.exe ${W_OPT_UNATTENDED:+ /q /c:"install.exe /q"} @@ -5575,17 +5761,17 @@ w_metadata dotnet30 dlls \ publisher="Microsoft" \ year="2006" \ media="download" \ - conflicts="dotnet11 dotnet20sp1 dotnet20sp2 dotnet30sp1 dotnet35 dotnet35sp1 dotnet45" \ + conflicts="dotnet11 dotnet20sp1 dotnet20sp2 dotnet30sp1 dotnet35 dotnet35sp1 dotnet45 dotnet452" \ file1="dotnetfx3.exe" \ installed_file1="c:/windows/Microsoft.NET/Framework/v3.0/Microsoft .NET Framework 3.0/logo.bmp" load_dotnet30() { # http://msdn.microsoft.com/en-us/netframework/bb264589.aspx - w_download http://web.archive.org/web/20120509084326/http://download.microsoft.com/download/3/F/0/3F0A922C-F239-4B9B-9CB0-DF53621C57D9/dotnetfx3.exe f3d2c3c7e4c0c35450cf6dab1f9f2e9e7ff50039 + w_download http://download.microsoft.com/download/3/F/0/3F0A922C-F239-4B9B-9CB0-DF53621C57D9/dotnetfx3.exe f3d2c3c7e4c0c35450cf6dab1f9f2e9e7ff50039 w_call remove_mono - + if test -f /proc/sys/kernel/yama/ptrace_scope then case `cat /proc/sys/kernel/yama/ptrace_scope` in @@ -5622,18 +5808,9 @@ load_dotnet30() # OK if this fails, that just means you have an older wine. "$WINE" sc delete "FontCache3.0.0.0" - if w_workaround_wine_bug 30845 "Using native fusion..." ,1.5.6 - then - # Either adding this registry key - #$WINE reg add 'HKLM\Software\Microsoft\.NETFramework' /v InstallRoot /d 'C:\Windows\Microsoft.NET\Framework\' /f - # or using native mscoree and fusion - WINEDLLOVERRIDES=mscoree,fusion=n - export WINEDLLOVERRIDES - # will let install start - fi WINEDLLOVERRIDES="ngen.exe,mscorsvw.exe=b;$WINEDLLOVERRIDES" - cd "$W_CACHE"/dotnet30 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" $file1 ${W_OPT_UNATTENDED:+ /q /c:"install.exe /q"} # Doesn't install any ngen.exe @@ -5658,7 +5835,7 @@ w_metadata dotnet30sp1 dlls \ load_dotnet30sp1() { - # FIXME: URL? + # FIXME: URL? w_download http://download.microsoft.com/download/8/F/E/8FEEE89D-9E4F-4BA3-993E-0FFEA8E21E1B/NetFx30SP1_x86.exe 8d779e337920b097aa0c01859912950606e9fc12 # Recipe from http://bugs.winehq.org/show_bug.cgi?id=25060#c10 w_download http://download.microsoft.com/download/2/5/2/2526f55d-32bc-410f-be18-164ba67ae07d/XPSEP%20XP%20and%20Server%202003%2032%20bit.msi 5d332ebd1025e294adafe72030fe33db707b2c82 "XPSEP XP and Server 2003 32 bit.msi" @@ -5721,7 +5898,7 @@ load_dotnet35() w_call msxml3 fi - "$WINE" reg delete "HKLM\\Software\\Microsoft\\NET Framework Setup\\NDP\\v3.5" + "$WINE" reg delete "HKLM\\Software\\Microsoft\\NET Framework Setup\\NDP\\v3.5" /f # See also http://blogs.msdn.com/astebner/archive/2008/07/17/8745415.aspx cd "$W_TMP" @@ -5770,7 +5947,7 @@ load_dotnet35sp1() WINEDLLOVERRIDES=ngen.exe,mscorsvw.exe=b export WINEDLLOVERRIDES - cd "$W_CACHE"/dotnet35sp1 + cd "$W_CACHE/$W_PACKAGE" w_ahk_do " SetTitleMatchMode, 2 run, dotnetfx35.exe /lang:ENU $W_UNATTENDED_SLASH_Q @@ -5827,11 +6004,6 @@ load_dotnet40() # http://www.microsoft.com/download/en/details.aspx?id=17718 w_download http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe 58da3d74db353aad03588cbb5cea8234166d8b99 - if w_workaround_wine_bug 30707 "Need to get gacutil.exe" 1.5.5, - then - w_download_manual http://www.mediafire.com/?v8rw5h1ra7maod4 gacutil-net40.tar.bz2 d40cc1249ea051338c064aff5ba0f1a5f24b59a5 - fi - w_call remove_mono # Remove Mono registry entry: @@ -5848,26 +6020,6 @@ load_dotnet40() "$WINE" reg add "HKLM\\Software\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full" /v Install /t REG_DWORD /d 0001 /f "$WINE" reg add "HKLM\\Software\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full" /v Version /t REG_SZ /d "4.0.30319" /f - if w_workaround_wine_bug 30707 "Manually registering assemblies" 1.5.5, - then - cd "$W_TMP" - tar -xvjf "$W_CACHE/$W_PACKAGE/gacutil-net40.tar.bz2" - - for assembly in $W_WINDIR_UNIX/Microsoft.NET/Framework/v4.0.30319/*.[dD]ll - do - "$WINE" "$W_TMP/gacutil.exe" /i "$(w_pathconv -w $assembly)" /f - done - - for assembly in $W_WINDIR_UNIX/Microsoft.NET/Framework/v4.0.30319/WPF/*.[dD]ll - do - # Some of the dlls aren't assemblies. FIXME: Should filter them based on that.. - "$WINE" "$W_TMP/gacutil.exe" /i "$(w_pathconv -w $assembly)" /f || true - done - - mkdir -p "$W_WINDIR_UNIX/Microsoft.NET/assembly/GAC_32/System.EnterpriseServices/v4.0_4.0.0.0__b03f5f7f11d50a3a" - cp "$W_WINDIR_UNIX/Microsoft.NET/Framework/v4.0.30319/System.EnterpriseServices.dll" "$W_WINDIR_UNIX/Microsoft.NET/assembly/GAC_32/System.EnterpriseServices/v4.0_4.0.0.0__b03f5f7f11d50a3a" - fi - W_NGEN_CMD="$WINE $WINEPREFIX/drive_c/windows/Microsoft.NET/Framework/v4.0.30319/ngen.exe executequeueditems" } @@ -5932,6 +6084,63 @@ verify_dotnet45() w_dotnet_verify dotnet45 } +#---------------------------------------------------------------- + +w_metadata dotnet452 dlls \ + title="MS .NET 4.5.2" \ + publisher="Microsoft" \ + year="2012" \ + media="download" \ + conflicts="dotnet20 dotnet20sdk dotnet20sp1 dotnet20sp2 dotnet35sp1 dotnet40 dotnet45 vjrun20" \ + file1="dotnetfx45_full_x86_x64.exe" \ + installed_file1="c:/windows/Microsoft.NET/Framework/v4.0.30319/Microsoft.Windows.ApplicationServer.Applications.45.man" + +load_dotnet452() +{ + if [ $W_ARCH = win64 ] + then + w_warn "This package may not work on a 64-bit installation" + fi + + # http://www.microsoft.com/download/en/details.aspx?id=17718 + w_download http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe 89f86f9522dc7a8a965facce839abb790a285a63 + + w_call remove_mono + + # Remove Mono registry entry: + "$WINE" reg delete "HKLM\Software\Microsoft\NET Framework Setup\NDP\v4" /f + + w_try rm -f "$W_WINDIR_UNIX/system32/mscoree.dll" + + # See https://appdb.winehq.org/objectManager.php?sClass=version&iId=25478 for Focht's recipe + w_call dotnet35 + w_call dotnet40 + w_set_winver win7 + + cd "$W_CACHE/$W_PACKAGE" + + WINEDLLOVERRIDES=fusion=b "$WINE" NDP452-KB2901907-x86-x64-AllOS-ENU.exe ${W_OPT_UNATTENDED:+/q /c:"install.exe /q"} + status=$? + + case $status in + 0) ;; + 105) echo "exit status $status - normal, user selected 'restart now'" ;; + 194) echo "exit status $status - normal, user selected 'restart later'" ;; + *) w_die "exit status $status - $W_PACKAGE installation failed" ;; + esac + + w_override_dlls native mscoree + + w_warn "Setting Windows version to 2003, otherwise applications using .NET 4.5 will subtly fail" + w_set_winver win2k3 +} + +verify_dotnet452() +{ + w_dotnet_verify dotnet452 +} + + #---------------------------------------------------------------- w_metadata dotnet_verifier dlls \ @@ -5949,10 +6158,10 @@ load_dotnet_verifier() # 2014/01/23: sha1sum 8818f3460826145e2a66bb91727afa7cd531037b # 2014/11/22: sha1sum 47de0b849c4c3d354df23588c709108e7816d788 # 2015/07/31: sha1sum 32f24526a5716737281dc260451b60a641b23c7e - w_download http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Components-PostAttachments/00-08-99-90-04/netfx_5F00_setupverifier_5F00_new.zip 32f24526a5716737281dc260451b60a641b23c7e - - cd "$W_CACHE"/dotnet_verifier + # 2015/12/27: sha1sum b9712da2943e057668f21f68c473657a205c5cb8 + w_download http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Components-PostAttachments/00-08-99-90-04/netfx_5F00_setupverifier_5F00_new.zip b9712da2943e057668f21f68c473657a205c5cb8 + cd "$W_CACHE/$W_PACKAGE" w_try_unzip "$W_SYSTEM32_DLLS" netfx_5F00_setupverifier_5F00_new.zip netfx_setupverifier.exe } @@ -6053,7 +6262,7 @@ load_flash() #w_download https://fpdownload.macromedia.com/get/flashplayer/pdc/14.0.0.176/install_flash_player_ax.exe 16231b509d8e689dc34ae36597d41c4fb1b3a67e # 2014-10-02 w_download http://download.macromedia.com/pub/flashplayer/installers/archive/fp_14.0.0.176_archive.zip 40df72ab2c22bcd4442aa35eb586000776129982 - + w_try_unzip "$W_TMP" "$W_CACHE"/flash/fp_14.0.0.176_archive.zip fp_14.0.0.176_archive/14_0_r0_176/flashplayer14_0r0_176_winax.exe cd "$W_TMP"/fp_14.0.0.176_archive/14_0_r0_176 w_try "$WINE" flashplayer14_0r0_176_winax.exe ${W_OPT_UNATTENDED:+ /install} @@ -6135,8 +6344,8 @@ w_metadata gdiplus_winxp dlls \ load_gdiplus_winxp() { w_download_manual http://download.cnet.com/NET-Framework-1-0-GDIPLUS-DLL-Security-Update/3000-10250_4-10732223.html NDP1.0sp2-KB830348-X86-Enu.exe 6113cd89d77525958295ccbd73b5fb8b89abd0aa - cd "$W_CACHE"/gdiplus - w_try_cabextract -d "$W_TMP" -F FL_gdiplus_dll_____X86.3643236F_FC70_11D3_A536_0090278A1BB8 "$W_CACHE"/gdiplus_winxp/$file1 + cd "$W_CACHE/$W_PACKAGE" + w_try_cabextract -d "$W_TMP" -F FL_gdiplus_dll_____X86.3643236F_FC70_11D3_A536_0090278A1BB8 "$W_CACHE/${W_PACKAGE}/$file1" w_try cp "$W_TMP/FL_gdiplus_dll_____X86.3643236F_FC70_11D3_A536_0090278A1BB8" "$W_SYSTEM32_DLLS/gdiplus.dll" # For some reason, native,builtin isn't good enough...? @@ -6157,8 +6366,29 @@ load_glidewrapper() { w_download http://www.zeckensack.de/glide/archive/GlideWrapper084c.exe 7a9d60a18b660473742b476465e9aea7bd5ab6f8 cd "$W_CACHE/$W_PACKAGE" + + # The installer opens its README in a web-browser, really annoying when doing make check/test: + # FIXME: maybe we should back up this key first? + if test ${W_OPT_UNATTENDED} + then + cat > "$W_TMP"/disable-browser.reg <<_EOF_ +REGEDIT4 + +[HKEY_CURRENT_USER\Software\Wine\WineBrowser] +"Browsers"="" + +_EOF_ + w_try_regedit "$W_TMP_WIN"\\disable-browser.reg + + fi + # NSIS installer w_try "$WINE" $file1 ${W_OPT_UNATTENDED:+ /S} + + if test ${W_OPT_UNATTENDED} + then + "$WINE" reg delete "HKEY_CURRENT_USER\Software\Wine\WineBrowser" /v Browsers /f || true + fi } #---------------------------------------------------------------- @@ -6178,7 +6408,7 @@ load_gfw() w_download http://download.microsoft.com/download/5/5/8/55846E20-4A46-4EF8-B272-7F988BC9090A/gfwlivesetupmin.exe 6f9e0ba052c68c8b51bb0e3ce6024d0e1c7b20b2 # FIXME: Depends on .Net 20, but is it really needed? For now, skip it. - cd "$W_CACHE"/gfw + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" gfwlivesetupmin.exe /nodotnet $W_UNATTENDED_SLASH_Q w_call msasn1 @@ -6216,7 +6446,7 @@ w_metadata gmdls dlls \ load_gmdls() { - w_download_to directx8 http://web.archive.org/web/20070403193305/http://download.microsoft.com/download/whistler/Update/8.1/W982KMeXP/EN-US/DX81Redist.exe ea2345f602741343e97a5ece5d1d2c3cc44296c3 + w_download_to directx8 http://download.microsoft.com/download/whistler/Update/8.1/W982KMeXP/EN-US/DX81Redist.exe ea2345f602741343e97a5ece5d1d2c3cc44296c3 w_try_unzip "$W_TMP" "$W_CACHE"/directx8/DX81Redist.exe "*/*/DirectX.cab" w_try_cabextract -d "$W_TMP" -F gm16.dls "$W_TMP"/*/*/DirectX.cab @@ -6263,7 +6493,7 @@ load_dirac() # Avoid mfc90 not found error. (DiracSplitter-libschroedinger.ax needs mfc90 to register itself, I think.) w_call vcrun2008 - cd "$W_CACHE"/dirac + cd "$W_CACHE/$W_PACKAGE" w_ahk_do " SetTitleMatchMode, 2 run DiracDirectShowFilter-1.0.2.exe @@ -6299,7 +6529,7 @@ w_metadata ffdshow dlls \ load_ffdshow() { w_download $WINETRICKS_SOURCEFORGE/ffdshow-tryout/ffdshow_beta7_rev3154_20091209.exe 8534c31489e51df70ee9583438d6211e6f0696d0 - cd "$W_CACHE"/ffdshow + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" ffdshow_beta7_rev3154_20091209.exe $W_UNATTENDED_SLASH_SILENT } @@ -6340,7 +6570,7 @@ load_icodecs() # 2014-04-11: http://www.cucusoft.com/codecdownload/codinstl.exe (linked from http://www.cucusoft.com/codec.asp) w_download "http://www.cucusoft.com/codecdownload/codinstl.exe" 2c5d64f472abe3f601ce352dcca75b4f02996f8a - cd "$W_CACHE"/icodecs + cd "$W_CACHE/$W_PACKAGE" w_ahk_do " SetTitleMatchMode, 2 @@ -6385,12 +6615,39 @@ load_jet40() # See also http://bugs.winehq.org/show_bug.cgi?id=6085 # FIXME: "failed with error 2" w_download http://www.autoxplorer.com/exe/Jet40SP8_9xNT.exe 8cd25342030857969ede2d8fcc34f3f7bcc2d6d4 - cd "$W_CACHE"/jet40 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" jet40sp8_9xnt.exe $W_UNATTENDED_SLASH_Q } #---------------------------------------------------------------- +w_metadata ie8_kb2936068 dlls \ + title="Cumulative Security Update for Internet Explorer 8" \ + publisher="Microsoft" \ + year="2014" \ + media="download" \ + file1="IE8-WindowsXP-KB2936068-x86-ENU.exe" \ + installed_file1="c:/windows/KB2936068-IE8.log" + +load_ie8_kb2936068() +{ + w_call ie8 + + w_download https://download.microsoft.com/download/3/8/C/38CE0ABB-01FD-4C0A-A569-BC5E82C34A17/IE8-WindowsXP-KB2936068-x86-ENU.exe 1bdeb741085b8f1ef6efc83f8615121373107347 + + if [ $W_UNATTENDED_SLASH_Q ] + then + quiet="$W_UNATTENDED_SLASH_QUIET /forcerestart" + else + quiet="" + fi + + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" IE8-WindowsXP-KB2936068-x86-ENU.exe $quiet +} + +#---------------------------------------------------------------- + w_metadata kde apps \ title="KDE on Windows" \ publisher="various" \ @@ -6417,18 +6674,22 @@ load_kde() w_metadata kindle apps \ title="Amazon Kindle" \ publisher="Amazon" \ - year="2015" \ + year="2016" \ media="download" \ - file1="KindleForPC-installer.exe" \ + file1="KindleForPC-installer-1.15.43061.exe" \ installed_exe1="$W_PROGRAMS_WIN/Amazon/Kindle/Kindle.exe" \ homepage="http://www.amazon.com/gp/feature.html/?docId=1000426311" load_kindle() { - w_download http://kindleforpc.amazon.com/40666/KindleForPC-installer.exe 10e8c82587f8c08b77e5ed55dd94d9851a2a899c - cd "$W_CACHE"/kindle + w_download http://kindleforpc.amazon.com/43061/KindleForPC-installer-1.15.43061.exe 27364a6867aac562426494312c2b3f4b673f13e2 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" $file1 ${W_OPT_UNATTENDED:+ /S} - w_declare_exe "$W_PROGRAMS_WIN\\Amazon\\Kindle" Kindle.exe + + if w_workaround_wine_bug 39980 "Installing native vcrun2008" + then + w_call vcrun2008 + fi } #---------------------------------------------------------------- @@ -6473,10 +6734,11 @@ load_mdac27() fi # http://www.microsoft.com/downloads/en/details.aspx?FamilyId=9AD000F2-CAE7-493D-B0F3-AE36C570ADE8&displaylang=en - w_download http://web.archive.org/web/20060202021126/http://download.microsoft.com/download/3/b/f/3bf74b01-16ba-472d-9a8c-42b2b4fa0d76/mdac_typ.exe f68594d1f578c3b47bf0639c46c11c5da161feee + w_download http://download.microsoft.com/download/3/b/f/3bf74b01-16ba-472d-9a8c-42b2b4fa0d76/mdac_typ.exe f68594d1f578c3b47bf0639c46c11c5da161feee load_native_mdac w_set_winver nt40 - w_try "$WINE" "$W_CACHE"/mdac27/mdac_typ.exe ${W_OPT_UNATTENDED:+ /q /C:"setup /QNT"} + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" mdac_typ.exe ${W_OPT_UNATTENDED:+ /q /C:"setup $W_UNATTENDED_SLASH_QNT"} w_unset_winver } @@ -6496,13 +6758,8 @@ load_mdac28() w_download http://download.microsoft.com/download/4/a/a/4aafff19-9d21-4d35-ae81-02c48dcbbbff/MDAC_TYP.EXE 4fbc272c79da59e38818924d8575accb0af776fb load_native_mdac w_set_winver nt40 - cd "$W_CACHE"/mdac28 - if [ $W_UNATTENDED_SLASH_Q ] - then - w_try "$WINE" mdac_typ.exe /q /C:"setup /QNT" - else - w_try "$WINE" mdac_typ.exe - fi + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" mdac_typ.exe ${W_OPT_UNATTENDED:+ /q /C:"setup $W_UNATTENDED_SLASH_QNT"} w_unset_winver } @@ -6691,23 +6948,50 @@ load_msctf() #---------------------------------------------------------------- +w_metadata msdxmocx dlls \ + title="MS Windows Media Player 2 ActiveX control for VB6" \ + publisher="Microsoft" \ + year="1999" \ + media="download" \ + file1="mpfull.exe" \ + installed_file1="$W_SYSTEM32_DLLS_WIN/msdxm.ocx" + +load_msdxmocx() +{ + # Previously at http://www.oldapps.com/windows_media_player.php?old_windows_media_player=3?download + # (2015/12/01) Iceweasel gave a security warning (!), but clamscan and virustotal.com report it as clean + # + # (2016/02/18) Since then, oldapps.com removed it. It's on a Finnish mirror, where it's been since 2001/10/20 + # Found using http://www.filewatcher.com/m/mpfull.exe.3593680-0.html + # The sha1sum is different. Perhaps Iceweasel was right. This one is also clean according to clamscan/virustotal.com + + w_download ftp://www.define.fi/Pub/Fixes/Microsoft/Windows%2095/mpfull.exe 99691df6ac455233230faac7514bdea781ba0ce3 + + w_try_cabextract --directory="$W_SYSTEM32_DLLS" "$W_CACHE/$W_PACKAGE/${file1}" + w_try_regsvr msdxm.ocx +} + +#---------------------------------------------------------------- + w_metadata msflxgrd dlls \ title="MS FlexGrid Control (msflxgrd.ocx)" \ publisher="Microsoft" \ year="2009" \ media="download" \ - file1="msflxgrd.cab" \ - installed_file1="$W_SYSTEM32_DLLS_WIN/MSFlxGrd.Ocx" + file1="MsFlxGrd.cab" \ + installed_file1="$W_SYSTEM32_DLLS_WIN/MSFLXGRD.OCX" load_msflxgrd() { # http://msdn.microsoft.com/en-us/library/aa240864(VS.60).aspx # may 2011: f497c3b390cd80d5bcd1f13d5c0c68b206369aa7 - w_download http://activex.microsoft.com/controls/vb6/msflxgrd.cab f497c3b390cd80d5bcd1f13d5c0c68b206369aa7 + # 2015/11/09: Removed from Microsoft.com, archive.org has an older copy: + # 2015/11/09: 3d6c04e923781d4ce0d3ab62189b8de352ab25d5 + w_download http://activex.microsoft.com/controls/vb6/MsFlxGrd.cab 3d6c04e923781d4ce0d3ab62189b8de352ab25d5 - w_try_cabextract --directory="$W_TMP" "$W_CACHE"/msflxgrd/msflxgrd.cab + w_try_cabextract --directory="$W_TMP" "$W_CACHE"/msflxgrd/${file1} w_try cp -f "$W_TMP"/[Mm][Ss][Ff][Ll][Xx][Gg][Rr][Dd].[Oo][Cc][Xx] "$W_SYSTEM32_DLLS" - w_try_regsvr MSFlxGrd.Ocx + w_try_regsvr MSFLXGRD.OCX } #---------------------------------------------------------------- @@ -6718,7 +7002,7 @@ w_metadata mshflxgd dlls \ year="2009" \ media="download" \ file1="MSHFLXGD.CAB" \ - installed_file1="$W_SYSTEM32_DLLS_WIN/mshflxgd.ocx" + installed_file1="$W_SYSTEM32_DLLS_WIN/MSHFLXGD.OCX" load_mshflxgd() { @@ -6726,11 +7010,13 @@ load_mshflxgd() # orig: 5f9c7a81022949bfe39b50f2bbd799c448bb7377 # Jan 2009: 7ad74e589d5eefcee67fa14e65417281d237a6b6 # May 2009: bd8aa796e16e5f213414af78931e0379d9cbe292 - w_download http://activex.microsoft.com/controls/vb6/MSHFLXGD.CAB bd8aa796e16e5f213414af78931e0379d9cbe292 + # 2015/11/09: Removed from Microsoft.com, archive.org has the original copy: + # 2015/11/09: 5f9c7a81022949bfe39b50f2bbd799c448bb7377 + w_download http://activex.microsoft.com/controls/vb6/MSHFLXGD.CAB 5f9c7a81022949bfe39b50f2bbd799c448bb7377 w_try_cabextract --directory="$W_TMP" "$W_CACHE"/mshflxgd/MSHFLXGD.CAB w_try cp -f "$W_TMP"/[Mm][Ss][Hh][Ff][Ll][Xx][Gg][Dd].[Oo][Cc][Xx] "$W_SYSTEM32_DLLS" - w_try_regsvr mshflxgd.ocx + w_try_regsvr MSHFLXGD.OCX } #---------------------------------------------------------------- @@ -6805,7 +7091,9 @@ load_msmask() # http://bugs.winehq.org/show_bug.cgi?id=2934 # old: 3c6b26f68053364ea2e09414b615dbebafb9d5c3 # May 2009: 30e55679e4a13fe4d9620404476f215f93239292 - w_download http://activex.microsoft.com/controls/vb6/MSMASK32.CAB 30e55679e4a13fe4d9620404476f215f93239292 + # 2015/11/09: Removed from Microsoft.com, archive.org has an older copy: + # 2015/11/09: bdd2bb3a32d18926a048f302aff18b1e6d250d9d + w_download http://activex.microsoft.com/controls/vb6/MSMASK32.CAB bdd2bb3a32d18926a048f302aff18b1e6d250d9d w_try_cabextract --directory="$W_TMP" "$W_CACHE"/msmask/MSMASK32.CAB w_try cp -f "$W_TMP"/[Mm][Ss][Mm][Aa][Ss][Kk]32.[Oo][Cc][Xx] "$W_SYSTEM32_DLLS"/msmask32.ocx w_try_regsvr msmask32.ocx @@ -6844,12 +7132,12 @@ load_msxml3() # Service Pack 5 #w_download http://download.microsoft.com/download/a/5/e/a5e03798-2454-4d4b-89a3-4a47579891d8/msxml3.msi # Service Pack 7 - w_download http://web.archive.org/web/20070314193356/http://download.microsoft.com/download/8/8/8/888f34b7-4f54-4f06-8dac-fa29b19f33dd/msxml3.msi d4c2178dfb807e1a0267fce0fd06b8d51106d913 + w_download http://download.microsoft.com/download/8/8/8/888f34b7-4f54-4f06-8dac-fa29b19f33dd/msxml3.msi d4c2178dfb807e1a0267fce0fd06b8d51106d913 # it won't install on top of wine's msxml3, which has a pretty high version number, so delete wine's fake dll rm "$W_SYSTEM32_DLLS"/msxml3.dll w_override_dlls native msxml3 - cd "$W_CACHE"/msxml3 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" msiexec /i msxml3.msi $W_UNATTENDED_SLASH_Q } @@ -6872,7 +7160,7 @@ load_msxml4() # SP3 (2009): http://www.microsoft.com/downloads/details.aspx?familyid=7F6C0CB4-7A5E-4790-A7CF-9E139E6819C0 w_download http://download.microsoft.com/download/A/2/D/A2D8587D-0027-4217-9DAD-38AFDB0A177E/msxml.msi aa70c5c1a7a069af824947bcda1d9893a895318b w_override_dlls native,builtin msxml4 - cd "$W_CACHE"/msxml4 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" msiexec /i msxml.msi $W_UNATTENDED_SLASH_Q } @@ -6944,7 +7232,7 @@ w_metadata ogg dlls \ load_ogg() { w_download http://downloads.xiph.org/releases/oggdsf/opencodecs_0.85.17777.exe 386cf7cd29ffcbf8705eff8c8233de448ecf33ab - cd "$W_CACHE"/ogg + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" $file1 $W_UNATTENDED_SLASH_S } @@ -7082,9 +7370,9 @@ w_metadata physx dlls \ load_physx() { - # Has a minor issue, see bug report http://bugs.winehq.org/show_bug.cgi?id=34167 + # Has a minor issue, see bug report http://bugs.winehq.org/show_bug.cgi?id=34167 w_download http://uk.download.nvidia.com/Windows/9.14.0702/PhysX-9.14.0702-SystemSoftware.msi 81e2d38e2356e807ad80cdf150ed5acfff839c8b - cd "$W_CACHE"/physx + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" msiexec /i PhysX-9.14.0702-SystemSoftware.msi $W_UNATTENDED_SLASH_Q } @@ -7157,35 +7445,16 @@ w_metadata quicktime72 dlls \ publisher="Apple" \ year="2010" \ media="download" \ - file1="quicktimeplayer72.exe" \ + file1="QuickTimeInstaller.exe" \ installed_file1="c:/windows/Installer/{95A890AA-B3B1-44B6-9C18-A8F7AB3EE7FC}/QTPlayer.ico" load_quicktime72() { - # http://www.apple.com/support/downloads/quicktime72forwindows.html - # http://www.oldapps.com/quicktime_player.php?old_quicktime=6 - w_download http://download.oldapps.com/Quicktime/quicktimeplayer72.exe bb89981f10cf21de57b9453e53cf81b9194271a9 + # https://support.apple.com/downloads/quicktime + w_download http://appldnld.apple.com.edgesuite.net/content.info.apple.com/QuickTime/061-2915.20070710.pO94c/QuickTimeInstaller.exe bb89981f10cf21de57b9453e53cf81b9194271a9 - unset QUICKTIME_QUIET - if test "$W_UNATTENDED_SLASH_Q" != "" - then - QUICKTIME_QUIET="/qn" # ISSETUPDRIVEN=0 - fi - - if w_workaround_wine_bug 9366 "" 1.1.22, - then - w_call gdiplus - w_call vcrun2005 # no bug number, but same era - fi - - if w_workaround_wine_bug 1347 - then - w_warn "Setting vista mode to avoid blacking the whole screen in quicktime" - w_set_winver vista - fi - - cd "$W_CACHE"/quicktime72 - w_try "$WINE" quicktimeplayer72.exe ALLUSERS=1 DESKTOP_SHORTCUTS=0 QTTaskRunFlags=0 QTINFO.BISQTPRO=1 SCHEDULE_ASUW=0 REBOOT_REQUIRED=No $QUICKTIME_QUIET > /dev/null 2>&1 + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" ${file1} ALLUSERS=1 DESKTOP_SHORTCUTS=0 QTTaskRunFlags=0 QTINFO.BISQTPRO=1 SCHEDULE_ASUW=0 REBOOT_REQUIRED=No $W_UNATTENDED_SLASH_QN > /dev/null 2>&1 if w_workaround_wine_bug 11681 then @@ -7221,26 +7490,8 @@ load_quicktime76() # http://www.apple.com/quicktime/download/ w_download http://appldnld.apple.com/QuickTime/041-0025.20101207.Ptrqt/QuickTimeInstaller.exe 1eec8904f041d9e0ad3459788bdb690e45dbc38e - unset QUICKTIME_QUIET - if test "$W_UNATTENDED_SLASH_Q" - then - QUICKTIME_QUIET="/qn" # ISSETUPDRIVEN=0 - fi - - if w_workaround_wine_bug 9366 "" 1.1.22, - then - w_call gdiplus - w_call vcrun2005 # no bug number, but same era - fi - - if w_workaround_wine_bug 1347 - then - w_warn "Setting vista mode to avoid blacking the whole screen in quicktime" - w_set_winver vista - fi - - cd "$W_CACHE"/quicktime76 - w_try "$WINE" QuickTimeInstaller.exe ALLUSERS=1 DESKTOP_SHORTCUTS=0 QTTaskRunFlags=0 QTINFO.BISQTPRO=1 SCHEDULE_ASUW=0 REBOOT_REQUIRED=No $QUICKTIME_QUIET > /dev/null 2>&1 + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" QuickTimeInstaller.exe ALLUSERS=1 DESKTOP_SHORTCUTS=0 QTTaskRunFlags=0 QTINFO.BISQTPRO=1 SCHEDULE_ASUW=0 REBOOT_REQUIRED=No $W_UNATTENDED_SLASH_QN > /dev/null 2>&1 if w_workaround_wine_bug 11681 then @@ -7436,9 +7687,12 @@ load_shockwave() { # 2015-03-30 sha1sum: 9f2d4d929e7210ae9fb633881127b21586ffd8ce # 2015-04-27 sha1sum: 244e6a5c5fa2dd26c136bc5b402f6cad588763d7 # 2015-08-02 sha1sum: e2efa2eb7db0a6de08905cd61bb3efcf58fda994 + # 2015-11-09 sha1sum: d13420a6fdc4f8d9c45c5ee6767974f0f0054cdc + # 2015-12-27 sha1sum: 3ac6d85e54dffb2940c89fc10e63363a47ec96d0 + # 2016-02-18 sha1sum: 45147a791e3f71bd67ead1622d9120060dd196e5 - w_download http://fpdownload.macromedia.com/get/shockwave/default/english/win95nt/latest/sw_lic_full_installer.msi e2efa2eb7db0a6de08905cd61bb3efcf58fda994 - cd "$W_CACHE"/shockwave + w_download http://fpdownload.macromedia.com/get/shockwave/default/english/win95nt/latest/sw_lic_full_installer.msi 45147a791e3f71bd67ead1622d9120060dd196e5 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" msiexec /i sw_lic_full_installer.msi $W_UNATTENDED_SLASH_Q } @@ -7475,16 +7729,16 @@ w_metadata tabctl32 dlls \ publisher="Microsoft" \ year="2009" \ media="download" \ - file1="tabctl32.cab" \ + file1="TABCTL32.CAB" \ installed_file1="$W_SYSTEM32_DLLS_WIN/tabctl32.ocx" load_tabctl32() { # http://msdn.microsoft.com/en-us/library/aa240864(VS.60).aspx # Nov 2012: tabctl32 - w_download http://activex.microsoft.com/controls/vb6/tabctl32.cab beca51d05924a5466ab80eb0f8d0cdf8bc1ac697 + w_download http://activex.microsoft.com/controls/vb6/TABCTL32.CAB beca51d05924a5466ab80eb0f8d0cdf8bc1ac697 - w_try_cabextract --directory="$W_TMP" "$W_CACHE"/tabctl32/tabctl32.cab + w_try_cabextract --directory="$W_TMP" "$W_CACHE"/tabctl32/${file1} w_try cp -f "$W_TMP"/[Tt][Aa][Bb][Cc][Tt][Ll][3][2].[Oo][Cc][Xx] "$W_SYSTEM32_DLLS" w_try_regsvr tabctl32.ocx } @@ -7598,7 +7852,7 @@ w_metadata vb5run dlls \ load_vb5run() { w_download http://download.microsoft.com/download/vb50pro/utility/1/win98/en-us/msvbvm50.exe 28bfaf09b8ac32cf5ffa81252f3e2fadcb3a8f27 - cd "$W_CACHE"/vb5run + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" msvbvm50.exe $W_UNATTENDED_SLASH_Q } @@ -7633,7 +7887,7 @@ load_vb6run() rm -f "$W_SYSTEM32_DLLS"/olepro32.dll rm -f "$W_SYSTEM32_DLLS"/stdole2.tlb - cd "$W_CACHE"/vb6run + cd "$W_CACHE/$W_PACKAGE" # Exits with status 43 for some reason? "$WINE" vbrun60sp6.exe $W_UNATTENDED_SLASH_Q @@ -7773,7 +8027,7 @@ w_metadata vcrun2003 dlls \ publisher="Microsoft" \ year="2003" \ media="download" \ - file1="BZEditW32_1.6.5_Installer.exe" \ + file1="BZEditW32_1.6.5.exe" \ installed_file1="$W_SYSTEM32_DLLS_WIN/msvcp71.dll" load_vcrun2003() @@ -7781,8 +8035,9 @@ load_vcrun2003() # Load the Visual C++ 2003 runtime libraries # Sadly, I know of no Microsoft URL for these echo "Installing BZFlag (which comes with the Visual C++ 2003 runtimes)" - w_download $WINETRICKS_SOURCEFORGE/bzflag/BZEditW32_1.6.5_Installer.exe bdd1b32c4202fd77e6513fd507c8236888b09121 - w_try "$WINE" "$W_CACHE"/vcrun2003/BZEditW32_1.6.5_Installer.exe $W_UNATTENDED_SLASH_S + # winetricks-test can't handle ${file1} in url since it does a raw parsing :/ + w_download $WINETRICKS_SOURCEFORGE/bzflag/BZEditW32_1.6.5.exe bdd1b32c4202fd77e6513fd507c8236888b09121 + w_try "$WINE" "$W_CACHE"/vcrun2003/${file1} $W_UNATTENDED_SLASH_S w_try cp "$W_PROGRAMS_X86_UNIX/BZEdit1.6.5"/m*71* "$W_SYSTEM32_DLLS" } @@ -7810,7 +8065,7 @@ load_vcrun2005() # http://support.microsoft.com/kb/2538242 w_download http://download.microsoft.com/download/8/B/4/8B42259F-5D70-43F4-AC2E-4B208FD8D66A/vcredist_x86.EXE b8fab0bb7f62a24ddfe77b19cd9a1451abd7b847 - cd "$W_CACHE"/vcrun2005 + cd "$W_CACHE/$W_PACKAGE" w_override_dlls native,builtin atl80 msvcm80 msvcp80 msvcr80 vcomp w_try "$WINE" $file1 $W_UNATTENDED_SLASH_Q } @@ -7832,7 +8087,7 @@ load_vcrun2008() # http://support.microsoft.com/kb/2538242 w_download http://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x86.exe 470640aa4bb7db8e69196b5edb0010933569e98d w_override_dlls native,builtin atl90 msvcm90 msvcp90 msvcr90 vcomp90 - cd "$W_CACHE"/vcrun2008 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" $file1 $W_UNATTENDED_SLASH_Q } @@ -7851,13 +8106,8 @@ load_vcrun2010() # See http://www.microsoft.com/downloads/details.aspx?FamilyID=a7b7a05e-6de6-4d3a-a423-37bf0912db84 w_download http://download.microsoft.com/download/5/B/C/5BC5DBB3-652D-4DCE-B14A-475AB85EEF6E/vcredist_x86.exe 372d9c1670343d3fb252209ba210d4dc4d67d358 - if w_workaround_wine_bug 23427 "" 1.3.5, - then - w_call msxml3 - fi - w_override_dlls native,builtin msvcp100 msvcr100 vcomp100 atl100 - cd "$W_CACHE"/vcrun2010 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" vcredist_x86.exe $W_UNATTENDED_SLASH_Q case "$W_ARCH" in @@ -7898,21 +8148,31 @@ load_vcrun2012() w_download http://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe 96b377a27ac5445328cbaae210fc4f0aaa750d3f w_override_dlls native,builtin atl110 msvcp110 msvcr110 vcomp110 - cd "$W_CACHE"/vcrun2012 - if w_workaround_wine_bug 17273 "Manually extracting dlls" - then - w_try_cabextract --directory="$W_TMP" vcredist_x86.exe - w_try_cabextract --directory="$W_TMP" "$W_TMP/a2" - w_try_cabextract --directory="$W_TMP" "$W_TMP/a3" - cp "$W_TMP"/F_CENTRAL_atl110_x86 "$W_SYSTEM32_DLLS"/atl110.dll - cp "$W_TMP"/F_CENTRAL_mfc110_x86 "$W_SYSTEM32_DLLS"/mfc110.dll - cp "$W_TMP"/F_CENTRAL_mfc110u_x86 "$W_SYSTEM32_DLLS"/mfc110u.dll - cp "$W_TMP"/F_CENTRAL_msvcp110_x86 "$W_SYSTEM32_DLLS"/msvcp110.dll - cp "$W_TMP"/F_CENTRAL_msvcr110_x86 "$W_SYSTEM32_DLLS"/msvcr110.dll - cp "$W_TMP"/F_CENTRAL_vcomp110_x86 "$W_SYSTEM32_DLLS"/vcomp110.dll - else - w_try "$WINE" vcredist_x86.exe $W_UNATTENDED_SLASH_Q - fi + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" vcredist_x86.exe $W_UNATTENDED_SLASH_Q + + case "$W_ARCH" in + win64) + # Also install the 64 bit version + # 2015/10/19: 1a5d93dddbc431ab27b1da711cd3370891542797 + w_download http://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe 1a5d93dddbc431ab27b1da711cd3370891542797 + if w_workaround_wine_bug 30713 "Manually extracting the 64-bit dlls" + then + rm -f "$W_TMP"/* # Avoid permission error + w_try_cabextract --directory="$W_TMP" vcredist_x64.exe + w_try_cabextract --directory="$W_TMP" "$W_TMP/a2" + w_try_cabextract --directory="$W_TMP" "$W_TMP/a3" + cp "$W_TMP"/F_CENTRAL_atl110_x64 "$W_SYSTEM64_DLLS"/atl110.dll + cp "$W_TMP"/F_CENTRAL_mfc110_x64 "$W_SYSTEM64_DLLS"/mfc110.dll + cp "$W_TMP"/F_CENTRAL_mfc110u_x64 "$W_SYSTEM64_DLLS"/mfc110u.dll + cp "$W_TMP"/F_CENTRAL_msvcp110_x64 "$W_SYSTEM64_DLLS"/msvcp110.dll + cp "$W_TMP"/F_CENTRAL_msvcr110_x64 "$W_SYSTEM64_DLLS"/msvcr110.dll + cp "$W_TMP"/F_CENTRAL_vcomp110_x64 "$W_SYSTEM64_DLLS"/vcomp110.dll + else + w_try "$WINE" vcredist_x64.exe $W_UNATTENDED_SLASH_Q + fi + ;; + esac } #---------------------------------------------------------------- @@ -7933,20 +8193,86 @@ load_vcrun2013() w_download http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe df7f0a73bfa077e483e51bfb97f5e2eceedfb6a3 w_override_dlls native,builtin atl120 msvcp120 msvcr120 vcomp120 - cd "$W_CACHE"/vcrun2013 - if w_workaround_wine_bug 17273 "Manually extracting dlls" - then - w_try_cabextract --directory="$W_TMP" vcredist_x86.exe - w_try_cabextract --directory="$W_TMP" "$W_TMP/a2" - w_try_cabextract --directory="$W_TMP" "$W_TMP/a3" - cp "$W_TMP"/F_CENTRAL_mfc120_x86 "$W_SYSTEM32_DLLS"/mfc120.dll - cp "$W_TMP"/F_CENTRAL_mfc120u_x86 "$W_SYSTEM32_DLLS"/mfc120u.dll - cp "$W_TMP"/F_CENTRAL_msvcp120_x86 "$W_SYSTEM32_DLLS"/msvcp120.dll - cp "$W_TMP"/F_CENTRAL_msvcr120_x86 "$W_SYSTEM32_DLLS"/msvcr120.dll - cp "$W_TMP"/F_CENTRAL_vcomp120_x86 "$W_SYSTEM32_DLLS"/vcomp120.dll - else - w_try "$WINE" vcredist_x86.exe $W_UNATTENDED_SLASH_Q - fi + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" vcredist_x86.exe $W_UNATTENDED_SLASH_Q + + case "$W_ARCH" in + win64) + # Also install the 64 bit version + # 2015/10/19: 8bf41ba9eef02d30635a10433817dbb6886da5a2 + w_download http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe 8bf41ba9eef02d30635a10433817dbb6886da5a2 + if w_workaround_wine_bug 30713 "Manually extracting the 64-bit dlls" + then + rm -f "$W_TMP"/* # Avoid permission error + w_try_cabextract --directory="$W_TMP" vcredist_x64.exe + w_try_cabextract --directory="$W_TMP" "$W_TMP/a2" + w_try_cabextract --directory="$W_TMP" "$W_TMP/a3" + cp "$W_TMP"/F_CENTRAL_mfc120_x64 "$W_SYSTEM64_DLLS"/mfc120.dll + cp "$W_TMP"/F_CENTRAL_mfc120u_x64 "$W_SYSTEM64_DLLS"/mfc120u.dll + cp "$W_TMP"/F_CENTRAL_msvcp120_x64 "$W_SYSTEM64_DLLS"/msvcp120.dll + cp "$W_TMP"/F_CENTRAL_msvcr120_x64 "$W_SYSTEM64_DLLS"/msvcr120.dll + cp "$W_TMP"/F_CENTRAL_vcomp120_x64 "$W_SYSTEM64_DLLS"/vcomp120.dll + else + w_try "$WINE" vcredist_x64.exe $W_UNATTENDED_SLASH_Q + fi + ;; + esac +} + +#---------------------------------------------------------------- + +w_metadata vcrun2015 dlls \ + title="Visual C++ 2015 libraries (concrt140.dll,mfc140.dll,mfc140u.dll,mfcm140.dll,mfcm140u.dll,msvcp140.dll,vcamp140.dll,vccorlib140.dll,vcomp140.dll,vcruntime140.dll)" \ + publisher="Microsoft" \ + year="2015" \ + media="download" \ + file1="vc_redist.x86.exe" \ + installed_file1="$W_SYSTEM32_DLLS_WIN/mfc140.dll" + +load_vcrun2015() +{ + # https://www.microsoft.com/en-us/download/details.aspx?id=48145 + # 2015/10/12: bfb74e498c44d3a103ca3aa2831763fb417134d1 + w_download https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe bfb74e498c44d3a103ca3aa2831763fb417134d1 + + w_override_dlls native,builtin atl140 msvcp140 msvcr140 vcomp140 + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" vc_redist.x86.exe $W_UNATTENDED_SLASH_Q + + case "$W_ARCH" in + win64) + # Also install the 64 bit version + # 2015/10/12: 3155cb0f146b927fcc30647c1a904cd162548c8c + w_download https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe 3155cb0f146b927fcc30647c1a904cd162548c8c + if w_workaround_wine_bug 30713 "Manually extracting the 64-bit dlls" + then + rm -f "$W_TMP"/* # Avoid permission error + w_try_cabextract --directory="$W_TMP" vc_redist.x64.exe + w_try_cabextract --directory="$W_TMP" "$W_TMP/a10" + w_try_cabextract --directory="$W_TMP" "$W_TMP/a11" + cp "$W_TMP"/concrt140.dll "$W_SYSTEM64_DLLS"/concrt140.dll + cp "$W_TMP"/mfc140.dll "$W_SYSTEM64_DLLS"/mfc140.dll + cp "$W_TMP"/mfc140u.dll "$W_SYSTEM64_DLLS"/mfc140u.dll + cp "$W_TMP"/mfcm140.dll "$W_SYSTEM64_DLLS"/mfcm140.dll + cp "$W_TMP"/mfcm140u.dll "$W_SYSTEM64_DLLS"/mfcm140u.dll + cp "$W_TMP"/msvcp140.dll "$W_SYSTEM64_DLLS"/msvcp140.dll + cp "$W_TMP"/vcamp140.dll "$W_SYSTEM64_DLLS"/vcamp140.dll + cp "$W_TMP"/vccorlib140.dll "$W_SYSTEM64_DLLS"/vccorlib140.dll + cp "$W_TMP"/vcomp140.dll "$W_SYSTEM64_DLLS"/vcomp140.dll + cp "$W_TMP"/vcruntime140.dll "$W_SYSTEM64_DLLS"/vcruntime140.dll + + w_override_dlls native,builtin api-ms-win-crt-heap-l1-1-0 api-ms-win-crt-locale-l1-1-0 api-ms-win-crt-math-l1-1-0.dll api-ms-win-crt-runtime-l1-1-0 api-ms-win-crt-stdio-l1-1-0 ucrtbase vcruntime140 + cp "$W_TMP"/api_ms_win_crt_heap_l1_1_0.dll "$W_SYSTEM64_DLLS"/api-ms-win-crt-heap-l1-1-0.dll + cp "$W_TMP"/api_ms_win_crt_locale_l1_1_0.dll "$W_SYSTEM64_DLLS"/api-ms-win-crt-locale-l1-1-0.dll + cp "$W_TMP"/api_ms_win_crt_math_l1_1_0.dll "$W_SYSTEM64_DLLS"/api-ms-win-crt-math-l1-1-0.dll + cp "$W_TMP"/api_ms_win_crt_runtime_l1_1_0.dll "$W_SYSTEM64_DLLS"/api-ms-win-crt-runtime-l1-1-0.dll + cp "$W_TMP"/api_ms_win_crt_stdio_l1_1_0.dll "$W_SYSTEM64_DLLS"/api-ms-win-crt-stdio-l1-1-0.dll + cp "$W_TMP"/ucrtbase.dll "$W_SYSTEM64_DLLS"/ucrtbase.dll + else + w_try "$WINE" vc_redist.x64.exe $W_UNATTENDED_SLASH_Q + fi + ;; + esac } #---------------------------------------------------------------- @@ -7972,13 +8298,8 @@ load_vjrun20() # See http://www.microsoft.com/downloads/details.aspx?FamilyId=E9D87F37-2ADC-4C32-95B3-B5E3A21BAB2C w_download http://download.microsoft.com/download/9/2/3/92338cd0-759f-4815-8981-24b437be74ef/vjredist.exe 80a098e36b90d159da915aebfbfbacf35f302bd8 - - if [ $W_UNATTENDED_SLASH_Q ] - then - w_try "$WINE" "$W_CACHE"/vjrun20/vjredist.exe /q /C:"install /QNT" - else - w_try "$WINE" "$W_CACHE"/vjrun20/vjredist.exe - fi + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" vjredist.exe ${W_OPT_UNATTENDED:+ /q /C:"install $W_UNATTENDED_SLASH_QNT"} } #---------------------------------------------------------------- @@ -8072,7 +8393,7 @@ load_wmi() w_set_winver win98 w_override_dlls native,builtin wbemprox wmiutils # Note: there is a crash in the background towards the end, doesn't seem to hurt; see http://bugs.winehq.org/show_bug.cgi?id=7920 - cd "$W_CACHE"/wmi + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" wmi9x.exe $W_UNATTENDED_SLASH_S w_unset_winver } @@ -8116,7 +8437,7 @@ load_wsh56vb() # See also http://www.microsoft.com/downloads/details.aspx?familyid=4F728263-83A3-464B-BCC0-54E63714BC75 w_download http://download.microsoft.com/download/IE60/Patch/Q318089/W9XNT4Me/EN-US/vbs56men.exe 48f14a93db33caff271da0c93f334971f9d7cb22 - cd "$W_CACHE"/wsh56vb + cd "$W_CACHE/$W_PACKAGE" w_override_dlls native,builtin vbscript # setupapi looks at the versions in new and original vbscript.dll, and wine's original is newer than wsh56vb's, so have to nuke the original w_try rm "$W_SYSTEM32_DLLS/vbscript.dll" @@ -8170,12 +8491,31 @@ load_xact() w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F 'x3daudio*.dll' "$x" w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F 'xapofx*.dll' "$x" done + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F '*_xact_*x64*' "$W_CACHE"/directx9/$DIRECTX_NAME + w_try_cabextract -d "$W_TMP" -L -F '*_x3daudio_*x64*' "$W_CACHE"/directx9/$DIRECTX_NAME + w_try_cabextract -d "$W_TMP" -L -F '*_xaudio_*x64*' "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'xactengine*.dll' "$x" + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'xaudio*.dll' "$x" + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'x3daudio*.dll' "$x" + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'xapofx*.dll' "$x" + done + fi - # Register xactengine?_?.dll, xaudio?_?.dll - for x in "$W_SYSTEM32_DLLS"/xactengine* "$W_SYSTEM32_DLLS"/xaudio* + # Register xactengine?_?.dll + for x in "$W_SYSTEM32_DLLS"/xactengine* do w_try_regsvr `basename "$x"` done + + # and xaudio?_?.dll, but not xaudio2_8 (unsupported) + for x in 0 1 2 3 4 5 6 7 + do + w_try_regsvr `basename "$W_SYSTEM32_DLLS/xaudio2_${x}"` + done } #---------------------------------------------------------------- @@ -8203,12 +8543,31 @@ load_xact_jun2010() w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F 'x3daudio*.dll' "$x" w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F 'xapofx*.dll' "$x" done + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F '*_xact_*x64*' "$W_CACHE"/directx9/$DIRECTX_NAME + w_try_cabextract -d "$W_TMP" -L -F '*_x3daudio_*x64*' "$W_CACHE"/directx9/$DIRECTX_NAME + w_try_cabextract -d "$W_TMP" -L -F '*_xaudio_*x64*' "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'xactengine*.dll' "$x" + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'xaudio*.dll' "$x" + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'x3daudio*.dll' "$x" + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'xapofx*.dll' "$x" + done + fi - # Register xactengine?_?.dll, xaudio?_?.dll - for x in "$W_SYSTEM32_DLLS"/xactengine* "$W_SYSTEM32_DLLS"/xaudio* + # Register xactengine?_?.dll + for x in "$W_SYSTEM32_DLLS"/xactengine* do w_try_regsvr `basename "$x"` done + + # and xaudio?_?.dll, but not xaudio2_8 (unsupported) + for x in 0 1 2 3 4 5 6 7 + do + w_try_regsvr `basename "$W_SYSTEM32_DLLS/xaudio2_${x}"` + done } #---------------------------------------------------------------- @@ -8230,10 +8589,14 @@ load_xinput() do w_try_cabextract -d "$W_SYSTEM32_DLLS" -L -F 'xinput*.dll' "$x" done - w_try_regsvr xinput1_1.dll - w_try_regsvr xinput1_2.dll - w_try_regsvr xinput1_3.dll - w_try_regsvr xinput9_1_0.dll + if test "$W_ARCH" = "win64" + then + w_try_cabextract -d "$W_TMP" -L -F '*_xinput_*x64*' "$W_CACHE"/directx9/$DIRECTX_NAME + for x in "$W_TMP"/*x64.cab + do + w_try_cabextract -d "$W_SYSTEM64_DLLS" -L -F 'xinput*.dll' "$x" + done + fi w_override_dlls native xinput1_1 w_override_dlls native xinput1_2 w_override_dlls native xinput1_3 @@ -8260,20 +8623,10 @@ load_xmllite() *) w_die "sorry, xmllite install not yet implemented for language $LANG" ;; esac - if w_workaround_wine_bug 16013 - then - # Find instructions to create this file in dlls/wintrust/tests/crypt.c - w_download https://github.com/Winetricks/winetricks/raw/master/files/winetest.cat ac8f50dd54d011f3bb1dd79240dae9378748449f - # Put a dummy catalog file in place - mkdir -p "$W_SYSTEM32_DLLS"/catroot/\{f750e6c3-38ee-11d1-85e5-00c04fc295ee\} - w_try cp -f "$W_CACHE"/xmllite/winetest.cat "$W_SYSTEM32_DLLS"/catroot/\{f750e6c3-38ee-11d1-85e5-00c04fc295ee\}/oem0.cat - if test ! "$W_OPT_UNATTENDED" - then - w_warn "xmllite's interactive installer will hang at the end, but otherwise work." - fi - fi + # Doesn't install in newer versions: + w_set_winver winxp - cd "$W_CACHE"/xmllite + cd "$W_CACHE/$W_PACKAGE" w_override_dlls native xmllite case $LANG in en*) w_try "$WINE" WindowsXP-KB915865-v11-x86-ENU.exe $W_UNATTENDED_SLASH_Q ;; @@ -8281,6 +8634,8 @@ load_xmllite() de*) w_try "$WINE" WindowsXP-KB915865-v11-x86-DEU.exe $W_UNATTENDED_SLASH_Q ;; ja*) w_try "$WINE" WindowsXP-KB915865-v11-x86-JPN.exe $W_UNATTENDED_SLASH_Q ;; esac + + w_unset_winver } #---------------------------------------------------------------- @@ -8297,8 +8652,8 @@ load_xna31() { w_call dotnet20sp2 w_download http://download.microsoft.com/download/5/9/1/5912526C-B950-4662-99B6-119A83E60E5C/xnafx31_redist.msi bdd33b677c9576a63ff2a6f65e12c0563cc116e6 - cd "$W_CACHE"/xna31 - w_try "$WINE" msiexec ${W_OPT_UNATTENDED:+/quiet} /i $file1 + cd "$W_CACHE/$W_PACKAGE" + w_try "$WINE" msiexec $W_UNATTENDED_SLASH_QUIET /i $file1 } #---------------------------------------------------------------- @@ -8317,8 +8672,8 @@ load_xna40() w_call dotnet40 # http://www.microsoft.com/en-us/download/details.aspx?id=20914 w_download http://download.microsoft.com/download/A/C/2/AC2C903B-E6E8-42C2-9FD7-BEBAC362A930/xnafx40_redist.msi 49efdc29f65fc8263c196338552c7009fc96c5de - cd "$W_CACHE"/xna40 - w_try "$WINE" msiexec ${W_OPT_UNATTENDED:+/quiet} /i $file1 + cd "$W_CACHE/$W_PACKAGE" + w_try "$WINE" msiexec $W_UNATTENDED_SLASH_QUIET /i $file1 } #---------------------------------------------------------------- @@ -8335,11 +8690,7 @@ load_xvid() { w_call vcrun6 w_download http://www.koepi.info/Xvid-1.3.2-20110601.exe 0a11498a96f75ad019c4c7d06161504140337dc0 - cd "$W_CACHE"/xvid - if w_workaround_wine_bug 27380 "Installing msvcr80 to avoid crash in setavi32.exe" - then - w_call vcrun2008 - fi + cd "$W_CACHE"/"$W_PACKAGE" w_try "$WINE" $file1 ${W_OPT_UNATTENDED:+ --mode unattended --decode_divx 1 --decode_3ivx 1 --decode_other 1} } @@ -8464,17 +8815,17 @@ w_metadata corefonts fonts \ load_corefonts() { # FIXME: why is this commented out? Should be removed or enabled. - #w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/andale32.exe c4db8cbe42c566d12468f5fdad38c43721844c69 - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/arial32.exe 6d75f8436f39ab2da5c31ce651b7443b4ad2916e - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/arialb32.exe d45cdab84b7f4c1efd6d1b369f50ed0390e3d344 - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/comic32.exe 2371d0327683dcc5ec1684fe7c275a8de1ef9a51 - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/courie32.exe 06a745023c034f88b4135f5e294fece1a3c1b057 - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/georgi32.exe 90e4070cb356f1d811acb943080bf97e419a8f1e - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/impact32.exe 86b34d650cfbbe5d3512d49d2545f7509a55aad2 - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/times32.exe 20b79e65cdef4e2d7195f84da202499e3aa83060 - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/trebuc32.exe 50aab0988423efcc9cf21fac7d64d534d6d0a34a - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/verdan32.exe f5b93cedf500edc67502f116578123618c64a42a - w_download ftp://ftp.netbsd.org/pub/pkgsrc/distfiles/ms-ttf/webdin32.exe 2fb4a42c53e50bc70707a7b3c57baf62ba58398f + #w_download ftp://ftp.fi.debian.org/gentoo/distfiles/andale32.exe c4db8cbe42c566d12468f5fdad38c43721844c69 + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/arial32.exe 6d75f8436f39ab2da5c31ce651b7443b4ad2916e + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/arialb32.exe d45cdab84b7f4c1efd6d1b369f50ed0390e3d344 + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/comic32.exe 2371d0327683dcc5ec1684fe7c275a8de1ef9a51 + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/courie32.exe 06a745023c034f88b4135f5e294fece1a3c1b057 + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/georgi32.exe 90e4070cb356f1d811acb943080bf97e419a8f1e + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/impact32.exe 86b34d650cfbbe5d3512d49d2545f7509a55aad2 + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/times32.exe 20b79e65cdef4e2d7195f84da202499e3aa83060 + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/trebuc32.exe 50aab0988423efcc9cf21fac7d64d534d6d0a34a + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/verdan32.exe f5b93cedf500edc67502f116578123618c64a42a + w_download ftp://ftp.fi.debian.org/gentoo/distfiles/webdin32.exe 2fb4a42c53e50bc70707a7b3c57baf62ba58398f # Natively installed versions of these fonts will cause the installers # to exit silently. Because there are apps out there that depend on the @@ -8670,6 +9021,40 @@ load_fakejapanese() #---------------------------------------------------------------- +w_metadata fakejapanese_ipamona fonts \ + title="Creates aliases for Japanese fonts using IPAMona fonts" \ + publisher="Jun Kobayashi" \ + year="2008" + +load_fakejapanese_ipamona() +{ + w_call ipamona + + # Aliases to set: + # MS UI Gothic --> IPAMonaUIGothic + # MS Gothic (MS ゴシック) --> IPAMonaGothic + # MS PGothic (MS Pゴシック) --> IPAMonaPGothic + # MS Mincho (MS 明朝) --> IPAMonaMincho + # MS PMincho (MS P明朝) --> IPAMonaPMincho + + jpname_msgothic="$(echo "MS ゴシック" | iconv -f utf8 -t cp932)" + jpname_mspgothic="$(echo "MS Pゴシック" | iconv -f utf8 -t cp932)" + jpname_msmincho="$(echo "MS 明朝" | iconv -f utf8 -t cp932)" + jpname_mspmincho="$(echo "MS P明朝" | iconv -f utf8 -t cp932)" + + w_register_font_replacement "MS UI Gothic" "IPAMonaUIGothic" + w_register_font_replacement "MS Gothic" "IPAMonaGothic" + w_register_font_replacement "MS PGothic" "IPAMonaPGothic" + w_register_font_replacement "MS Mincho" "IPAMonaMincho" + w_register_font_replacement "MS PMincho" "IPAMonaPMincho" + w_register_font_replacement "$jpname_msgothic" "IPAMonaGothic" + w_register_font_replacement "$jpname_mspgothic" "IPAMonaPGothic" + w_register_font_replacement "$jpname_msmincho" "IPAMonaMincho" + w_register_font_replacement "$jpname_mspmincho" "IPAMonaPMincho" +} + +#---------------------------------------------------------------- + w_metadata fakekorean fonts \ title="Creates aliases for Korean fonts using Baekmuk fonts" \ publisher="Wooderart Inc. / kldp.net" \ @@ -8728,7 +9113,7 @@ load_fontfix() # SDKSetup encountered an error: The type initializer for 'Microsoft.WizardFramework.WizardSettings' threw an exception # and WINEDEBUG=+relay,+seh shows an exception very quickly after # Call KERNEL32.CreateFileW(0c83b36c L"Z:\\USR\\SHARE\\FONTS\\TRUETYPE\\TTF-ORIYA-FONTS\\SAMYAK-ORIYA.TTF",80000000,00000001,00000000,00000003,00000080,00000000) ret=70d44091 - if xlsfonts 2>/dev/null | egrep -i "samyak|oriya" + if xlsfonts 2>/dev/null | egrep -i "samyak.*oriya" then w_die "Please uninstall the Samyak/Oriya font, e.g. 'sudo dpkg -r ttf-oriya-fonts', then log out and log in again. That font causes strange crashes in .net programs." fi @@ -8736,6 +9121,33 @@ load_fontfix() #---------------------------------------------------------------- +w_metadata ipamona fonts \ + title="IPAMona Japanese fonts" \ + publisher="Jun Kobayashi" \ + year="2008" \ + media="download" \ + file1="opfc-ModuleHP-1.1.1_withIPAMonaFonts-1.0.8.tar.gz" \ + installed_file1="$W_FONTSDIR_WIN/ipag-mona.ttf" \ + homepage="http://www.geocities.jp/ipa_mona/" + +load_ipamona() +{ + w_download http://www.geocities.jp/ipa_mona/$file1 57dd13ab58c0005d3ee2932539e4987ab0242bc7 + + cd "$W_TMP" + + gunzip -dc "$W_CACHE/$W_PACKAGE/$file1" | tar -xf - + w_try mv *IPAMonaFonts*/fonts/*.ttf "$W_FONTSDIR_UNIX" + + w_register_font ipagui-mona.ttf "IPAMonaUIGothic" + w_register_font ipag-mona.ttf "IPAMonaGothic" + w_register_font ipagp-mona.ttf "IPAMonaPGothic" + w_register_font ipam-mona.ttf "IPAMonaMincho" + w_register_font ipamp-mona.ttf "IPAMonaPMincho" +} + +#---------------------------------------------------------------- + w_metadata liberation fonts \ title="Red Hat Liberation fonts (Sans, Serif, Mono)" \ publisher="Red Hat" \ @@ -8963,6 +9375,24 @@ load_allfonts() # Apps #---------------------------------------------------------------- +w_metadata 3m_library apps \ + title="3M Cloud Library" \ + publisher="3M Company" \ + year="2015" \ + media="download" \ + file1="3M-TM-Cloud-Library-PC-App-LIVE-Installer-1.51.735677.exe" \ + installed_exe1="$W_PROGRAMS_X86_WIN/3M(TM) Cloud Library PC App/3MCloudLibrary.exe" + homepage="http://www.3m.com/us/library/eBook/index.html" + +load_3m_library() +{ + w_download http://www.3m.com/us/library/eBook/docs/3M-TM-Cloud-Library-PC-App-LIVE-Installer-1.51.735677.exe 810dc5f6b74ab7b34893288ee44ef7dc563a4ee7 + cd "$W_CACHE/$W_PACKAGE" + w_try "$WINE" 3M-TM-Cloud-Library-PC-App-LIVE-Installer-1.51.735677.exe $W_UNATTENDED_SLASH_S +} + +#---------------------------------------------------------------- + w_metadata 7zip apps \ title="7-Zip 15.05 beta" \ publisher="Igor Pavlov" \ @@ -8976,7 +9406,6 @@ load_7zip() w_download http://www.7-zip.org/a/7z1505.exe ece8bbd4c8903095d44e99196219c953a1d47bfd cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" 7z1505.exe $W_UNATTENDED_SLASH_S - w_declare_exe "$W_PROGRAMS_X86_WIN\\7-Zip" "7zFM.exe" } #---------------------------------------------------------------- @@ -8992,15 +9421,14 @@ w_metadata abiword apps \ load_abiword() { w_download http://www.abisource.com/downloads/abiword/2.8.6/Windows/abiword-setup-2.8.6.exe a91acd3f60e842d23556032d34f1600602768318 - cd "$W_CACHE"/abiword + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" abiword-setup-2.8.6.exe $W_UNATTENDED_SLASH_S - w_declare_exe "$W_PROGRAMS_X86_WIN\\AbiWord\\bin" AbiWord.exe } #---------------------------------------------------------------- w_metadata adobe_diged apps \ - title="Adobe Digital Editions" \ + title="Adobe Digital Editions 1.7" \ publisher="Adobe" \ year="2011" \ media="download" \ @@ -9013,8 +9441,43 @@ load_adobe_diged() w_download http://kb2.adobe.com/cps/403/kb403051/attachments/setup.exe 4c79685408fa6ca12ef8bb0e0eaa4a846e21f915 # NSIS installer w_try "$WINE" "$W_CACHE"/$W_PACKAGE/setup.exe ${W_OPT_UNATTENDED:+ /S} - w_declare_exe "$W_PROGRAMS_X86_WIN\\Adobe\\Adobe Digital Editions" \ - digitaleditions.exe +} + +#---------------------------------------------------------------- + +w_metadata adobe_diged4 apps \ + title="Adobe Digital Editions 4.5" \ + publisher="Adobe" \ + year="2015" \ + media="download" \ + file1="ADE_4.5_Installer.exe" \ + installed_exe1="$W_PROGRAMS_X86_WIN/Adobe/Adobe Digital Editions 4.5/DigitalEditions.exe" \ + homepage="http://www.adobe.com/products/digitaleditions/" + +load_adobe_diged4() +{ + w_download http://download.adobe.com/pub/adobe/digitaleditions/ADE_4.5_Installer.exe + + if w_workaround_wine_bug 32323 + then + w_call corefonts + fi + if [ ! -x "`which winbindd 2>/dev/null`" ] + then + w_warn "Adobe Digital Editions 4.5 requires winbind (part of samba) to be installed, but winbind was not detected." + fi + + w_call dotnet40 + + #w_call win7 + cd "$W_CACHE/$W_PACKAGE" + w_ahk_do " + SetTitleMatchMode, 2 + run, ${file1} ${W_OPT_UNATTENDED:+ /S} + winwait, Installing Adobe Digital Editions + ControlClick, Button1 ; Don't install Norton Internet Security + ControlClick, Static19 ; Next + " } #---------------------------------------------------------------- @@ -9046,7 +9509,6 @@ load_audible() WinWait, AudibleManager ; the dang thing starts up WinKill " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Audible\\Bin" Manager.exe } #---------------------------------------------------------------- @@ -9080,7 +9542,6 @@ load_audibledm() WinWait, Audible Download Manager ; the dang thing starts up WinKill " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Audible\\Bin" AudibleDownloadHelper.exe } #---------------------------------------------------------------- @@ -9097,7 +9558,7 @@ load_autohotkey() { W_BROWSERAGENT=1 \ w_download http://www.autohotkey.com/download/AutoHotkey104805_Install.exe 13e5a9ca6d5b7705f1cd02560c3af4d38b1904fc - cd "$W_CACHE"/autohotkey + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" AutoHotkey104805_Install.exe $W_UNATTENDED_SLASH_S } @@ -9114,10 +9575,8 @@ w_metadata cmake apps \ load_cmake() { w_download http://www.cmake.org/files/v2.8/cmake-2.8.11.2-win32-x86.exe d79af5715c0ad48d78bb731cce93b5ad89b16512 - cd "$W_CACHE"/cmake + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" cmake-2.8.11.2-win32-x86.exe $W_UNATTENDED_SLASH_S - - w_declare_exe "$W_PROGRAMS_X86_WIN\\CMake 2.8\\bin" "cmake-gui.exe" } #---------------------------------------------------------------- @@ -9160,18 +9619,12 @@ load_controlpad() echo "If setup says 'Unable to start DDE ...', press Ignore" cd "$W_TMP" - case "$W_UNATTENDED_SLASH_Q" in - "") quiet="" ;; - *) quiet="/qt" - esac - w_try "$WINE" setup $quiet + w_try "$WINE" setup $W_UNATTENDED_SLASH_QT if ! test -f "$W_SYSTEM32_DLLS"/FM20.DLL then w_die "Install failed. Please report, If you just wanted fm20.dll, try installing art2min instead." fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\ActiveX Control Pad" "PED.EXE" } #---------------------------------------------------------------- @@ -9223,14 +9676,6 @@ load_dxdiag() then w_call directmusic fi - if w_workaround_wine_bug 25715 "" 1.7.28, - then - w_call quartz - fi - if w_workaround_wine_bug 25716 "" 1.7.29, - then - w_call devenum - fi } #---------------------------------------------------------------- @@ -9245,10 +9690,49 @@ w_metadata emu8086 apps \ load_emu8086() { - w_download https://web.archive.org/web/20140209022335/http://emu8086.com/emu8086.zip fa3b2451cbc46fd2e3aa2670fa4d81ae8e75c7db + w_download http://emu8086.com/emu8086.zip fa3b2451cbc46fd2e3aa2670fa4d81ae8e75c7db w_try_unzip "$W_TMP" "$W_CACHE/$W_PACKAGE"/$file1 w_try "$WINE" "$W_TMP/Setup.exe" $W_UNATTENDED_SLASH_SILENT - w_declare_exe "c:\\emu8086" "emu8086.exe" +} + +#---------------------------------------------------------------- + +w_metadata ev3 apps \ + title="Lego Mindstorms EV3 Home Edition" \ + publisher="Lego" \ + year="2014" \ + media="download" \ + file1="LMS-EV3-WIN32-ENUS-01-01-01-full-setup.exe" \ + installed_exe1="$W_PROGRAMS_X86_WIN/LEGO Software/LEGO MINDSTORMS EV3 Home Edition/MindstormsEV3.exe" + +load_ev3() +{ + if w_workaround_wine_bug 40192 "Installing vcrun2005 as Wine does not have MFC80.dll" + then + w_call vcrun2005 + fi + + if w_workaround_wine_bug 40193 "Installing IE8 is built-in Gecko is not sufficient" + then + w_call ie8 + fi + + w_call dotnet40 + + w_download http://esd.lego.com.edgesuite.net/digitaldelivery/mindstorms/6ecda7c2-1189-4816-b2dd-440e22d65814/public/LMS-EV3-WIN32-ENUS-01-01-01-full-setup.exe 855c914d9a3cf0f4793a046872658fd661389671 + + cd "$W_CACHE"/"$W_PACKAGE" + w_try "$WINE" LMS-EV3-WIN32-ENUS-01-01-01-full-setup.exe + + if w_workaround_wine_bug 40174 "Setting override for urlmon.dll to native to avoid crash" + then + w_override_dlls native urlmon + fi + + if w_workaround_wine_bug 34897 "Installing update KB2936068 to work around bug 34897" + then + w_call ie8_kb2936068 + fi } #---------------------------------------------------------------- @@ -9263,16 +9747,9 @@ w_metadata firefox apps \ load_firefox() { - if w_workaround_wine_bug 29077 "" 1.7.25, - then - w_warn "Visit about:config, search for dom.ipc, and set those booleans false if you want to use flash." - fi - w_download "https://download.mozilla.org/?product=firefox-39.0-SSL&os=win&lang=en-US" 75eccbd9b2d44210b551c9a5045f03f01e899528 "$file1" - cd "$W_CACHE"/firefox + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" "$file1" ${W_OPT_UNATTENDED:+ -ms} - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Mozilla Firefox" firefox.exe } #---------------------------------------------------------------- @@ -9292,7 +9769,6 @@ load_fontxplorer() cd "$W_CACHE/fontxplorer" w_try "$WINE" Font_Xplorer_122_Free.exe $W_UNATTENDED_SLASH_S - w_declare_exe "$W_PROGRAMS_X86_WIN\\Font Xplorer" "FXplorer.exe" } #---------------------------------------------------------------- @@ -9310,7 +9786,6 @@ load_foobar2000() w_download_manual http://www.foobar2000.org/download foobar2000_v1.3.6.exe 77d1c3aa766853701d29e46b3018aaf1e1b5dd39 cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" $file1 $W_UNATTENDED_SLASH_S - w_declare_exe "$W_PROGRAMS_X86_WIN\\foobar2000" "foobar2000.exe" } #---------------------------------------------------------------- @@ -9325,11 +9800,6 @@ w_metadata iceweasel apps \ load_iceweasel() { - if w_workaround_wine_bug 29077 "" 1.7.25, - then - w_warn "Visit about:config, search for dom.ipc, and set those booleans false if you want to use flash." - fi - w_download https://ftp.gnu.org/gnu/gnuzilla/31.7.0/icecat-31.7.0.en-US.win32.zip cf52a728c1af29065b7dc7bdddc9265a79eb5328 w_try_unzip "${W_PROGRAMS_X86_UNIX}" "${W_CACHE}/${W_PACKAGE}/${file1}" } @@ -9383,11 +9853,11 @@ load_irfanview() ControlClick, Button1 ; deselect chrome googsrch Sleep 900 ControlClick, Button18 ; Next - Sleep 1000 + Sleep 1000 winwait, Setup, INI Sleep 1000 ControlClick, Button23 ; Next - Sleep 1000 + Sleep 1000 winwait, Setup, You want to change winactivate, Setup, really Sleep 900 @@ -9405,7 +9875,6 @@ load_irfanview() else w_try "$WINE" $file1 fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\IrfanView" "i_view32.exe" } #---------------------------------------------------------------- @@ -9416,8 +9885,8 @@ w_metadata ie6 dlls \ title="Internet Explorer 6" \ publisher="Microsoft" \ year="2002" \ - media="manual_download" \ - file1="msie60.exe" \ + media="download" \ + file1="ie60.exe" \ installed_file1="c:/Program Files/Internet Explorer/iedetect.dll" load_ie6() @@ -9428,16 +9897,17 @@ load_ie6() w_die "This package does not work on a 64-bit installation" fi - w_download_manual http://www.oldversion.com/download-Internet-Explorer-6.0.html msie60.exe 8e483db28ff01a7cabd39147ab6c59753ea1f533 + w_download http://download.oldapps.com/Internet_Explorer/ie60.exe 8e483db28ff01a7cabd39147ab6c59753ea1f533 cd "$W_TMP" - "$WINE" "$W_CACHE"/ie6/$file1 + "$WINE" "$W_CACHE"/"$W_PACKAGE"/$file1 w_call msls31 # Unregister Wine IE if [ ! -f "$W_SYSTEM32_DLLS"/plugin.ocx ] then + w_override_dlls builtin iexplore.exe w_try "$WINE" iexplore -unregserver fi @@ -9518,24 +9988,27 @@ w_metadata ie7 dlls \ load_ie7() { - if w_workaround_wine_bug 21947 "Working around heap corruption (see also bug 26016)" 1.7.19, - then - echo "This fails in about 1 of 30 runs (see bug 26016), just retry if that happens" - fi - # Unregister Wine IE if grep -q -i "wine placeholder" "$W_PROGRAMS_X86_UNIX/Internet Explorer/iexplore.exe" then + w_override_dlls builtin iexplore.exe w_try "$WINE" iexplore -unregserver fi # Change the override to the native so we are sure we use and register them - w_override_dlls native,builtin iexplore.exe itircl itss jscript mshtml msimtf shdoclc shdocvw shlwapi urlmon wininet xmllite + w_override_dlls native,builtin itircl itss jscript mshtml msimtf shdoclc shdocvw shlwapi urlmon wininet xmllite + + # IE7 installer will check the version number of iexplore.exe which causes IE7 installer to fail on wine-1.9.0+ + w_override_dlls native iexplore.exe # Bundled updspapi cannot work on wine w_override_dlls builtin updspapi # Remove the fake dlls from the existing WINEPREFIX + if [ -f "$W_PROGRAMS_X86_UNIX/Internet Explorer/iexplore.exe" ] + then + mv "$W_PROGRAMS_X86_UNIX/Internet Explorer/iexplore.exe" "$W_PROGRAMS_X86_UNIX/Internet Explorer/iexplore.exe.bak" + fi for dll in itircl itss jscript mshtml msimtf shdoclc shdocvw shlwapi urlmon do test -f "$W_SYSTEM32_DLLS"/$dll.dll && @@ -9550,16 +10023,6 @@ load_ie7() mkdir -p "$W_SYSTEM32_DLLS"/catroot/\{f750e6c3-38ee-11d1-85e5-00c04fc295ee\} w_try cp -f "$W_CACHE"/ie7/winetest.cat "$W_SYSTEM32_DLLS"/catroot/\{f750e6c3-38ee-11d1-85e5-00c04fc295ee\}/oem0.cat - # Install - w_download http://download.microsoft.com/download/3/8/8/38889DC1-848C-4BF2-8335-86C573AD86D9/IE7-WindowsXP-x86-enu.exe d39b89c360fbaa9706b5181ae4718100687a5326 - if test "$W_UNATTENDED_SLASH_Q" = "" - then - quiet="" - else - quiet="/quiet" - fi - cd "$W_CACHE"/ie7 - # KLUDGE: if / is writable (as on MacOSX?), having a z: mapping to it # causes ie7 to put temporary directories on Z:\ # so hide it temporarily. This is not very robust! @@ -9569,12 +10032,11 @@ load_ie7() mv "$WINEPREFIX/dosdevices/z:" "$WINEPREFIX/dosdevices/z:.bak_wt" fi - if w_workaround_wine_bug 21947 "Working around heap corruption (see also bug 26016)" 1.7.19, - then - WINEDEBUG=warn+heap "$WINE" IE7-WindowsXP-x86-enu.exe $quiet - else - "$WINE" IE7-WindowsXP-x86-enu.exe $quiet - fi + # Install + w_download http://download.microsoft.com/download/3/8/8/38889DC1-848C-4BF2-8335-86C573AD86D9/IE7-WindowsXP-x86-enu.exe d39b89c360fbaa9706b5181ae4718100687a5326 + cd "$W_CACHE/$W_PACKAGE" + + "$WINE" IE7-WindowsXP-x86-enu.exe $W_UNATTENDED_SLASH_QUIET # IE7 exits with 194 to signal a reboot status=$? @@ -9585,7 +10047,6 @@ load_ie7() *) w_die "exit status $status - $W_PACKAGE installation failed" ;; esac - if test -w / then # END KLUDGE: restore z:, assuming user didn't kill us @@ -9637,18 +10098,26 @@ load_ie8() if grep -q -i "wine placeholder" "$W_PROGRAMS_X86_UNIX/Internet Explorer/iexplore.exe" #if [ ! -f "$W_SYSTEM32_DLLS"/plugin.ocx ] then + w_override_dlls builtin iexplore.exe w_try "$WINE" iexplore -unregserver fi w_call msls31 # Change the override to the native so we are sure we use and register them - w_override_dlls native,builtin iexplore.exe itircl itss jscript msctf mshtml shdoclc shdocvw shlwapi urlmon wininet xmllite + w_override_dlls native,builtin itircl itss jscript msctf mshtml shdoclc shdocvw shlwapi urlmon wininet xmllite + + # IE8 installer will check the version number of iexplore.exe which causes IE8 installer to fail on wine-1.9.0+ + w_override_dlls native iexplore.exe # Bundled updspapi cannot work on wine w_override_dlls builtin updspapi # Remove the fake dlls from the existing WINEPREFIX + if [ -f "$W_PROGRAMS_X86_UNIX/Internet Explorer/iexplore.exe" ] + then + mv "$W_PROGRAMS_X86_UNIX/Internet Explorer/iexplore.exe" "$W_PROGRAMS_X86_UNIX/Internet Explorer/iexplore.exe.bak" + fi for dll in browseui.dll inseng.dll itircl itss jscript msctf mshtml shdoclc shdocvw shlwapi urlmon do test -f "$W_SYSTEM32_DLLS"/$dll.dll && @@ -9664,13 +10133,13 @@ load_ie8() w_try cp -f "$W_CACHE"/ie8/winetest.cat "$W_SYSTEM32_DLLS"/catroot/\{f750e6c3-38ee-11d1-85e5-00c04fc295ee\}/oem0.cat w_download http://download.microsoft.com/download/C/C/0/CC0BD555-33DD-411E-936B-73AC6F95AE11/IE8-WindowsXP-x86-ENU.exe e489483e5001f95da04e1ebf3c664173baef3e26 - if [ $W_UNATTENDED_SLASH_Q ] + if [ $W_UNATTENDED_SLASH_QUIET ] then - quiet="/quiet /forcerestart" + quiet="$W_UNATTENDED_SLASH_QUIET /forcerestart" else quiet="" fi - cd "$W_CACHE"/ie8 + cd "$W_CACHE/$W_PACKAGE" # KLUDGE: if / is writable, having a z: mapping to it causes ie8 to put temporary directories on Z:\ # so hide it temporarily. This is not very robust! @@ -9739,9 +10208,8 @@ w_metadata kobo apps \ load_kobo() { w_download http://download.kobobooks.com/desktop/1/KoboSetup.exe 31a5f5583edf4b716b9feacb857d2170104cabd9 - cd "$W_CACHE"/kobo + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" $file1 ${W_OPT_UNATTENDED:+ /S} - w_declare_exe "$W_PROGRAMS_X86_WIN\\Kobo" "Kobo.exe" } #---------------------------------------------------------------- @@ -9761,7 +10229,7 @@ load_mingw() cd "$W_CACHE/mingw" w_try "$WINE" "$file1" - + w_append_path 'C:\MinGW\bin' w_try "$WINE" mingw-get update w_try "$WINE" mingw-get install gcc msys-base @@ -9804,8 +10272,6 @@ load_mspaint() w_download http://download.microsoft.com/download/0/A/4/0A40DF5C-2BAE-4C63-802A-84C33B34AC98/WindowsXP-KB978706-x86-ENU.exe f4e076b3867c2f08b6d258316aa0e11d6822b8d7 w_try $WINE "$W_CACHE"/mspaint/WindowsXP-KB978706-x86-ENU.exe /q /x:"$W_TMP"/WindowsXP-KB978706-x86-ENU w_try cp -f "$W_TMP"/WindowsXP-KB978706-x86-ENU/SP3GDR/mspaint.exe "$W_WINDIR_UNIX"/mspaint.exe - - w_declare_exe "$W_WINDIR_UNIX" "mspaint.exe" } #---------------------------------------------------------------- @@ -9826,10 +10292,9 @@ load_nook() # 7 Oct 2011 sha1sum 3b0301bd55471cc47cced44501547411fac9fcea # 7 Mar 2012 sha1sum e7060a63b9b303ddd820de762d9df254e1c931bc w_download http://images.barnesandnoble.com/PResources/download/eReader2/bndr2_setup_latest.exe e7060a63b9b303ddd820de762d9df254e1c931bc - cd "$W_CACHE"/nook + cd "$W_CACHE/$W_PACKAGE" "$WINE" $file1 ${W_OPT_UNATTENDED:+ /S} # normally has exit status 199? - w_declare_exe "$W_PROGRAMS_WIN\\Barnes & Noble\\BNDesktopReader" "BNDReader.exe" } #---------------------------------------------------------------- @@ -9898,12 +10363,6 @@ load_office2003pro() } WinWaitClose " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office11" WINWORD.EXE word2003 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office11" EXCEL.EXE excel2003 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office11" POWERPNT.EXE powerpoint2003 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office11" MSACCESS.EXE access2003 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office11" OUTLOOK.EXE outlook2003 } #---------------------------------------------------------------- @@ -9961,14 +10420,6 @@ $W_CACHE/$W_PACKAGE/key.txt and rerun." else w_try "$WINE" ${W_ISO_MOUNT_LETTER}:setup.exe fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office12" WINWORD.EXE word2007 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office12" EXCEL.EXE excel2007 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office12" POWERPNT.EXE powerpoint2007 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office12" MSACCESS.EXE access2007 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office12" OUTLOOK.EXE outlook2007 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office12" MSPUB.EXE publisher2007 - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Office\\Office12" INFOPATH.EXE infopath2007 } #---------------------------------------------------------------- @@ -9986,7 +10437,6 @@ load_opera() w_download ftp://ftp.opera.com/pub/opera/win/1150/en/Opera_1150_en_Setup.exe df50c7aed50e92af858e8834f833dd0543014b46 cd "$W_CACHE"/$W_PACKAGE w_try "$WINE" $file1 ${W_OPT_UNATTENDED:+ /silent /launchopera 0 /allusers} - w_declare_exe "$W_PROGRAMS_X86_WIN\\Opera" opera.exe } #---------------------------------------------------------------- @@ -10000,15 +10450,15 @@ w_metadata picasa39 apps \ load_picasa39() { - w_download http://dl.google.com/picasa/picasa39-setup.exe 39b2df46dbc423e250371e826026a2827f55b956 + # 2015/01/17: 39b2df46dbc423e250371e826026a2827f55b956 + # 2015/09/21: 55907fc84b1d9d6a450463869b16927f07737298 + # 2016/01/02: b3f7e2ee168811cb1d924eb34afe2b0d8153f89f + + w_download http://dl.google.com/picasa/picasa39-setup.exe b3f7e2ee168811cb1d924eb34afe2b0d8153f89f if w_workaround_wine_bug 29434 "Picasa 3.9 fails to authenticate with Google" then w_warn "Picasa 3.9 authentication to the Google account is currently broken under wine. See http://bugs.winehq.org/show_bug.cgi?id=29434 for more details." fi - if w_workaround_wine_bug 37729 "Picasa updater crashes during install unless dotnet20 loaded" - then - w_call dotnet20 - fi cd "$W_CACHE"/$W_PACKAGE w_ahk_do " SetTitleMatchMode, 2 @@ -10037,7 +10487,25 @@ load_picasa39() } WinWaitClose " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Google\\Picasa3" "Picasa3.exe" +} + +#---------------------------------------------------------------- + +w_metadata protectionid apps \ + title="Protection ID" \ + publisher="CDKiLLER & TippeX" \ + year="2015" \ + media="download" \ + file1="ProtectionId.670.halloween.2015.rar" \ + installed_file1="$W_SYSTEM32_DLLS_WIN/protection_id.exe" + +load_protectionid() +{ + w_download http://pid.gamecopyworld.com/dl.php?f=ProtectionId.670.halloween.2015.rar a307e15f28d00959cffddd8fda073aac6df943c8 "$file1" + cd "$W_SYSTEM32_DLLS" + w_try_unrar "${W_CACHE}/${W_PACKAGE}/${file1}" + # ProtectionId.670.halloween.2015 has a different executable name than usual, this may need to be disabled on next update: + mv Protection_ID.eXe protection_id.exe } #---------------------------------------------------------------- @@ -10085,16 +10553,12 @@ load_psdkwin7() { # http://www.microsoft.com/downloads/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&displaylang=en w_call dotnet20 - if w_workaround_wine_bug 21509 "" 1.2, - then - w_call gdiplus # work around http://bugs.winehq.org/show_bug.cgi?id=21509 - fi w_call mfc42 # need mfc42u, or setup will abort # don't have a working unattended recipe. Maybe we'll have to # do an autohotkey script until msft gets its act together: # http://social.msdn.microsoft.com/Forums/en-US/windowssdk/thread/c053b616-7d5b-405d-9841-ec465a8e21d5 w_download http://download.microsoft.com/download/7/A/B/7ABD2203-C472-4036-8BA0-E505528CCCB7/winsdk_web.exe a01dcc67a38f461e80ea649edf1353f306582507 - cd "$W_CACHE"/psdkwin7 + cd "$W_CACHE/$W_PACKAGE" if w_workaround_wine_bug 21596 then w_warn "When given a choice, select only C++ compilers and headers, the other options don't work yet. See http://bugs.winehq.org/show_bug.cgi?id=21596" @@ -10139,14 +10603,16 @@ load_psdkwin71() w_call mfc42 # need mfc42u, or setup will abort # http://www.microsoft.com/downloads/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&displaylang=en w_download http://download.microsoft.com/download/A/6/A/A6AC035D-DA3F-4F0C-ADA4-37C8E5D34E3D/winsdk_web.exe a8717ebb20a69c7efa85232bcb9899b8b07f98cf - cd "$W_CACHE"/psdkwin71 + if w_workaround_wine_bug 21596 then w_warn "When given a choice, select only C++ compilers and headers, the other options don't work yet. See http://bugs.winehq.org/show_bug.cgi?id=21596" fi + # don't have a working unattended recipe. Maybe we'll have to # do an autohotkey script until msft gets its act together: # http://social.msdn.microsoft.com/Forums/en-US/windowssdk/thread/c053b616-7d5b-405d-9841-ec465a8e21d5 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" winsdk_web.exe if w_workaround_wine_bug 21362 @@ -10205,7 +10671,7 @@ load_python26() w_die "This installer is broken under $WINETRICKS_WINE_VERSION. Please upgrade Wine. See https://code.google.com/p/winetricks/issues/detail?id=347 for more info." fi - cd "$W_CACHE"/python26 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" msiexec /i python-2.6.2.msi ALLUSERS=1 $W_UNATTENDED_SLASH_Q w_ahk_do " @@ -10263,7 +10729,8 @@ load_python26_setuptools() { w_call python26 - w_download https://bootstrap.pypa.io/ez_setup.py 90b05e9298b7963eaec6de050c8fc751ce6a2a29 + # Not checking sha1sum, script frequently updates and there aren't stable versions + w_download https://bootstrap.pypa.io/ez_setup.py cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" "C:\Python26\python.exe" ${file1} @@ -10287,7 +10754,7 @@ load_spotify() # updates too frequently to check checksum :-( w_download http://www.spotify.com/download/Spotify%20Installer.exe - cd "$W_CACHE"/spotify + cd "$W_CACHE/$W_PACKAGE" # w_download doesn't handle renaming for us without a checksum, tsk. # And autohotkey thinks % is a variable reference. if test ! -f SpotifyInstaller.exe @@ -10295,11 +10762,6 @@ load_spotify() cp Spotify%20Installer.exe SpotifyInstaller.exe fi - if w_workaround_wine_bug 27476 "Installing winhttp to work around a facebook integration crash on login and install" - then - w_call ie7 - fi - # Install is silent by default, and always starts app # So all we have to do here is close app if we want unattended install w_ahk_do " @@ -10313,8 +10775,6 @@ load_spotify() sleep 1000 Process, Close, SpotifyWebHelper.exe " - - w_declare_exe "c:\\users\\$LOGNAME\\Application Data\\Spotify" spotify.exe } #---------------------------------------------------------------- @@ -10331,32 +10791,13 @@ load_safari() { w_download http://appldnld.apple.com.edgesuite.net/content.info.apple.com/Safari5/061-7138.20100607.Y7U87/SafariSetup.exe e56d5d79d9cfbb85ac46ac78aa497d7f3d8dbc3d - cd "$W_CACHE"/$W_PACKAGE - - if w_workaround_wine_bug 21146 - then - w_try mkdir -p "$W_APPDATA_UNIX/Apple Computer/Preferences" - cat > "$W_APPDATA_UNIX/Apple Computer/Preferences/com.apple.Safari.plist" <<_EOF_ - - - - - LastDisplayedWelcomePageVersionString - 4.0 - - -_EOF_ - fi - if test $W_OPT_UNATTENDED then w_warn "Safari's silent install is broken under wine. See http://bugs.winehq.org/show_bug.cgi?id=23493. You should do a regular install if you want to use Safari." - w_try "$WINE" SafariSetup.exe /qn - else - w_try "$WINE" SafariSetup.exe fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\Safari" "Safari.exe" + cd "$W_CACHE"/$W_PACKAGE + w_try "$WINE" SafariSetup.exe $W_UNATTENDED_SLASH_QN } #---------------------------------------------------------------- @@ -10400,20 +10841,6 @@ load_sketchup() } WinWaitClose " - - if w_workaround_wine_bug 14045 "Setting GLConfig Display HW_OK to 1" 1.3.18, - then - cat > "$W_TMP"/glconfigdisplay.reg <<_EOF_ -REGEDIT4 - -[HKEY_CURRENT_USER\Software\Google\SketchUp8\GLConfig\Display] -"HW_OK"="1" - -_EOF_ - w_try_regedit "$W_TMP_WIN"\\glconfigdisplay.reg - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Google\\Google SketchUp 8" "SketchUp.exe" } #---------------------------------------------------------------- @@ -10434,16 +10861,19 @@ load_steam() # 11 Dec 2014 7ad8fbeffa6c963b821f80129c15c9d8e85f9a4a # 6 Jan 2015 e04aefe8bc894f11f211edec8e8a008abe0147d2 # 21 Jun 2015 0e8046d40c38d817338135ec73a5b217cc340cf5 - w_download http://media.steampowered.com/client/installer/SteamSetup.exe 0e8046d40c38d817338135ec73a5b217cc340cf5 - cd "$W_CACHE"/steam + # 29 Dec 2015 728e3c82fd57c68cbbdb64965719081ffee6272c + w_download http://media.steampowered.com/client/installer/SteamSetup.exe 728e3c82fd57c68cbbdb64965719081ffee6272c + cd "$W_CACHE/$W_PACKAGE" + # Should be fixed in newer steam versions, since 2012. Commenting out for a while before removing in case users need to revert locally + # # Install corefonts first, so if the user doesn't have cabextract/Wine with cab support, we abort before installing Steam. # FIXME: support using Wine's cab support - if ! test -f "$W_FONTSDIR_UNIX/Times.TTF" && \ - w_workaround_wine_bug 22751 "Installing corefonts to prevent a Steam crash" - then - w_call corefonts - fi + #if ! test -f "$W_FONTSDIR_UNIX/Times.TTF" && \ + # w_workaround_wine_bug 22751 "Installing corefonts to prevent a Steam crash" + #then + # w_call corefonts + #fi if test $W_OPT_UNATTENDED then @@ -10475,13 +10905,6 @@ load_steam() then w_override_dlls disabled gameoverlayrenderer fi - - if w_workaround_wine_bug 31320 "Disabling dwrite.dll to prevent a Steam crash." - then - w_override_dlls disabled dwrite - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Steam" "Steam.exe" } #---------------------------------------------------------------- @@ -10503,26 +10926,15 @@ load_uplay() # 16 Feb 2014 ? sha1sum 19f98632ad1ff330c647f8ff1a3a15b44238c709 # Changes too frequently, don't check anymore w_download http://static3.cdn.ubi.com/orbit/launcher_installer/UplayInstaller.exe - cd "$W_CACHE"/uplay + cd "$W_CACHE/$W_PACKAGE" # NSIS installer w_try "$WINE" UplayInstaller.exe ${W_OPT_UNATTENDED:+ /S} - if w_workaround_wine_bug 33742 "Using native crypt32 so uplay's autoupdater doesn't abort" - then - # Directx9 and game installation often fails with native crypt32, - # so set it to native for Uplay.exe only. - w_call crypt32 - w_override_dlls default crypt32 - w_override_app_dlls Uplay.exe native crypt32 - fi - if w_workaround_wine_bug 33673 "Installing gdiplus to work around slow navigation" then w_call gdiplus fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Ubisoft\\Ubisoft Game Launcher" "Uplay.exe" } #---------------------------------------------------------------- @@ -10550,8 +10962,6 @@ load_utorrent() w_download_manual "http://www.oldapps.com/utorrent.php?old_utorrent=38" utorrent_2.2.1.exe c6d9a80c02898139b17194d10293f17ecef054cb w_try cp -f "$W_CACHE/utorrent/$file1" "$W_WINDIR_UNIX"/utorrent.exe - - w_declare_exe "c:\\windows" "utorrent.exe" } #---------------------------------------------------------------- @@ -10585,8 +10995,6 @@ load_utorrent3() 0|1) ;; *) w_die "Note: utorrent installer returned status '$status'. Aborting." ;; esac - - w_declare_exe "$W_DRIVE_C\\users\\$LOGNAME\\Application Data\\uTorrent" "uTorrent.exe" } #---------------------------------------------------------------- @@ -10603,10 +11011,6 @@ load_vc2005express() { # Thanks to http://blogs.msdn.com/astebner/articles/551674.aspx for the recipe w_call dotnet20 - if w_workaround_wine_bug 20029 "" 1.3.9, - then - w_call msxml6 - fi # http://blogs.msdn.com/b/astebner/archive/2006/03/14/551674.aspx # http://go.microsoft.com/fwlink/?linkid=57034 @@ -10624,10 +11028,6 @@ load_vc2005express() w_try "$WINE" Ixpvc.exe /t:"$W_TMP_WIN" /q:a /c:"msiexec /i vcsetup.msi VSEXTUI=1 ADDLOCAL=ALL REBOOT=ReallySuppress" else - if w_workaround_wine_bug 25331 - then - w_warn "Install fails with wine older than 1.1.35. With wine-1.3.5 or higher, interactive install fails, but quiet mode (-q option) may work." - fi w_try "$WINE" setup.exe w_ahk_do " SetTitleMatchMode, 2 @@ -10635,8 +11035,6 @@ load_vc2005express() WinWaitClose, Visual C++ 2005 Express Edition Setup " fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Visual Studio 8\\Common7\\IDE" "VCExpress.exe" } #---------------------------------------------------------------- @@ -10656,7 +11054,7 @@ load_vc2005expresssp1() if w_workaround_wine_bug 37375 then w_warn "Installer currently fails" - fi + fi w_download http://download.microsoft.com/download/7/7/3/7737290f-98e8-45bf-9075-85cc6ae34bf1/VS80sp1-KB926748-X86-INTL.exe 8b9a0172efad64774aa122f29e093ad2043b308d w_try $WINE "$W_CACHE"/vc2005expresssp1/VS80sp1-KB926748-X86-INTL.exe } @@ -10673,24 +11071,9 @@ w_metadata vc2005trial apps \ load_vc2005trial() { - if w_workaround_wine_bug 26162 "Install fails with spurious error about custom action" ,1.3.4 1.3.15, - then - w_die "Please upgrade to wine-1.3.15 or later to install this app" - fi - if w_workaround_wine_bug 25331 "Install fails with error about custom rollback actions" 1.1.35,1.3.4 1.3.13, - then - w_die "Please upgrade to wine-1.3.15 or later to install this app" - fi - if w_workaround_wine_bug 27987 "Install fails with error about CA_RollbackHelpTransaction" ,1.3.19 1.3.37, - then - w_die "Please upgrade to wine-1.3.37 or later to install this app" - fi w_call dotnet20 - if w_workaround_wine_bug 20029 "Installing native msxml6" 1.3.9, - then - w_call msxml6 - fi - # Without mfc42.dll, pidgen.dll won't load, and the app claims "A trial edition is alread installed..." + + # Without mfc42.dll, pidgen.dll won't load, and the app claims "A trial edition is already installed..." w_call mfc42 w_download http://download.microsoft.com/download/6/f/5/6f5f7a01-50bb-422d-8742-c099c8896969/En_vs_2005_vsts_180_Trial.img f66ae07618d67e693ca0524d3582208c20e07823 @@ -10728,8 +11111,6 @@ load_vc2005trial() controlclick, button2 winwaitclose, Finish Page " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Visual Studio 8\\Common7\\IDE" "devenv.exe" } #---------------------------------------------------------------- @@ -10755,8 +11136,6 @@ load_vc2008express() # See also http://blogs.msdn.com/b/astebner/archive/2008/04/25/8425198.aspx cd "$W_TMP"/VCExpress w_try "$WINE" setup.exe $W_UNATTENDED_SLASH_Q - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Visual Studio 9.0\\Common7\\IDE" "VCExpress.exe" } #---------------------------------------------------------------- @@ -10771,16 +11150,6 @@ w_metadata vc2010express apps \ load_vc2010express() { - if w_workaround_wine_bug 32654 "Installing windows codecs to work around startup crash" - then - w_call windowscodecs - fi - if w_workaround_wine_bug 32280 "Replacing mono with dotnet40 to avoid fatal 'Unknown Error'" - then - # "w_call remove_mono" might suffice - w_call dotnet40 - fi - w_download http://download.microsoft.com/download/1/E/5/1E5F1C0A-0D5B-426A-A603-1798B951DDAE/VS2010Express1.iso adef5e361a1f64374f520b9a2d03c54ee43721c6 # Unpack ISO @@ -10802,8 +11171,6 @@ load_vc2010express() fi w_try $WINE setup.exe $W_UNATTENDED_SLASH_Q - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Visual Studio 10.0\\Common7\\IDE" "VCExpress.exe" } #---------------------------------------------------------------- @@ -10820,9 +11187,8 @@ w_metadata vlc apps \ load_vlc() { w_download http://get.videolan.org/vlc/2.2.1/win32/vlc-2.2.1-win32.exe 4cbcea9764b6b657d2147645eeb5b973b642530e - cd "$W_CACHE"/vlc + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" $file1 ${W_OPT_UNATTENDED:+ /S} - w_declare_exe "$W_PROGRAMS_X86_WIN\\VideoLAN\\VLC" vlc.exe } #---------------------------------------------------------------- @@ -10852,25 +11218,25 @@ load_winamp() WinWait, Installer Language, Please select Sleep 500 ControlClick, Button1 ; OK - WinWait, Winamp Installer, Welcome to the Winamp installer + WinWait, Winamp Installer, Welcome to the Winamp installer Sleep 500 ControlClick, Button2 ; Next - WinWait, Winamp Installer, License Agreement + WinWait, Winamp Installer, License Agreement Sleep 500 ControlClick, Button2 ; I Agree - WinWait, Winamp Installer, Choose Install Location + WinWait, Winamp Installer, Choose Install Location Sleep 500 ControlClick, Button2 ; Next - WinWait, Winamp Installer, Choose Components + WinWait, Winamp Installer, Choose Components Sleep 500 ControlClick, Button2 ; Next for Full install - WinWait, Winamp Installer, Choose Start Options + WinWait, Winamp Installer, Choose Start Options Sleep 500 - ControlClick, Button4 ; uncheck start menu entry + ControlClick, Button4 ; uncheck start menu entry Sleep 500 - ControlClick, Button5 ; uncheck ql icon + ControlClick, Button5 ; uncheck ql icon Sleep 500 - ControlClick, Button6 ; uncheck deskto icon + ControlClick, Button6 ; uncheck deskto icon Sleep 500 ControlClick, Button2 ; Install WinWait, Winamp Installer, Installation Complete @@ -10883,7 +11249,6 @@ load_winamp() else w_try "$WINE" "$file1" fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\Winamp" "winamp.exe" } #---------------------------------------------------------------- @@ -10905,10 +11270,8 @@ load_wme9() # See also http://www.microsoft.com/downloads/details.aspx?FamilyID=5691ba02-e496-465a-bba9-b2f1182cdf24 w_download http://download.microsoft.com/download/8/1/f/81f9402f-efdd-439d-b2a4-089563199d47/WMEncoder.exe 7a3f8781f3e5705651992ef0150ee30bc1295116 - cd "$W_CACHE"/wme9 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" WMEncoder.exe $W_UNATTENDED_SLASH_Q - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Windows Media Components\\Encoder" "wmenc.exe" } #---------------------------------------------------------------- @@ -10964,20 +11327,12 @@ load_wmp9() # Wine's pidgen is too stubby, crashes, see wine bug 31111 w_override_app_dlls MPSetup.exe native pidgen - # Have to run twice; see http://bugs.winehq.org/show_bug.cgi?id=1886 - cd "$W_CACHE"/wmp9 + cd "$W_CACHE"/"$W_PACKAGE" w_try "$WINE" MPSetup.exe $W_UNATTENDED_SLASH_Q - if w_workaround_wine_bug 1886 "Re-installing since it does not work on the first try." 1.5.23, - then - w_try "$WINE" MPSetup.exe $W_UNATTENDED_SLASH_Q - fi - load_wm9codecs w_unset_winver - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Windows Media Player" "wmplayer.exe" } #---------------------------------------------------------------- @@ -11007,7 +11362,7 @@ load_wmp10() w_download http://download.microsoft.com/download/1/2/a/12a31f29-2fa9-4f50-b95d-e45ef7013f87/MP10Setup.exe 69862273a5d9d97b4a2e5a3bd93898d259e86657 # Crashes on exit, but otherwise ok; see http://bugs.winehq.org/show_bug.cgi?id=12633 - cd "$W_CACHE"/wmp10 + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" MP10Setup.exe $W_UNATTENDED_SLASH_Q # Disable WMP's services, since they depend on unimplemented stuff, they trigger the GUI debugger several times @@ -11017,8 +11372,6 @@ load_wmp10() load_wm9codecs w_unset_winver - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Windows Media Player" "wmplayer.exe" } #---------------------------------------------------------------- @@ -11073,14 +11426,6 @@ load_3dmark2000() Send {Enter} ; Finish WinWaitClose " - - cat > "$W_DRIVE_C/run-$W_PACKAGE.bat" <<__EOF__ -c: -cd "$W_PROGRAMS_X86_WIN\MadOnion.com\3DMark2000" -REM possible wine cmd bug: "3dmark2000" aborts, but ".\3dmark2000" works -.\3DMark2000 %* -__EOF__ - } #---------------------------------------------------------------- @@ -11126,8 +11471,6 @@ load_3dmark2001() } WinWaitClose " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\MadOnion.com\\3DMark2001 SE" "3DMark2001SE.exe" } #---------------------------------------------------------------- @@ -11187,7 +11530,6 @@ load_3dmark03() } WinWaitClose, 3DMark03 - InstallShield Wizard, Complete " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Futuremark\\3DMark03" "3DMark03.exe" } #---------------------------------------------------------------- @@ -11237,8 +11579,6 @@ load_3dmark05() w_warn "You must run the app with the -nosysteminfo option to avoid a crash on startup" ARGS="-nosysteminfo" fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Futuremark\\3DMark05" "3DMark05 $ARGS" } #---------------------------------------------------------------- @@ -11281,12 +11621,7 @@ load_3dmark06() WinWaitClose, ahk_class #32770, Complete " - if w_workaround_wine_bug 9210 - then - w_warn "The benchmark may warn that shader model 2.0 is not present. You can ignore this, but if you want to work around it, see http://bugs.winehq.org/show_bug.cgi?id=9210 for a patch." - fi - - if w_workaround_wine_bug 0 "Installing shader compiler..." + if w_workaround_wine_bug 24417 "Installing shader compiler..." then # "Demo" button doesn't work without this. d3dcompiler_43 related. w_call d3dx9_28 @@ -11299,8 +11634,6 @@ load_3dmark06() w_warn "You must run the app with the -nosysteminfo option to avoid a crash on startup" ARGS="-nosysteminfo" fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Futuremark\\3DMark06" "3DMark06 $ARGS" } #---------------------------------------------------------------- @@ -11347,17 +11680,6 @@ load_unigine_heaven() } winwaitclose " - - if w_workaround_wine_bug 22614 "setting video memory to 1024M" 1.3.23, - then - # hope your card actually has 1GB of RAM - w_call videomemorysize=1024 - fi - - # Should start Heaven.exe, but that doesn't run in Wine - # Should give option to run Heaven_gl.bat (even works in Wine) - # or the dx10 or dx11 versions (doesn't). - w_declare_exe "$W_PROGRAMS_X86_WIN\\Unigine\\Heaven" "cmd /c Heaven_d3d9.bat" } #---------------------------------------------------------------- @@ -11408,14 +11730,6 @@ load_algodoo_demo() } WinWaitClose, Algodoo, Completing " - - # Since we declined the msvc runtime installer (right?), we have to do it here - if w_workaround_wine_bug 23815 - then - w_call vcrun2008 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Algodoo" "Algodoo.exe" } #---------------------------------------------------------------- @@ -11458,10 +11772,8 @@ load_amnesia_tdd_demo() WinWait, Amnesia - The Dark Descent Demo, finished ControlClick, TNewButton4 WinWaitClose, Amnesia - The Dark Descent Demo, finished - } + } " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Amnesia - The Dark Descent Demo\\redist" "Amnesia.exe" } #---------------------------------------------------------------- @@ -11479,11 +11791,6 @@ load_aoe3_demo() w_download "http://download.microsoft.com/download/a/5/2/a525997e-8423-435b-b694-08118d235064/aoe3trial.exe" 2b0a123243092d79f910db5691d99d469f7c17c3 - if w_workaround_wine_bug 24897 "Installing msxml4 to avoid font problem" 1.3.9, - then - w_call msxml4 - fi - cd "$W_CACHE/$W_PACKAGE" w_ahk_do " @@ -11505,15 +11812,6 @@ load_aoe3_demo() WinWaitClose " - if w_workaround_wine_bug 24911 "Installing devnum, dmsynth, and quartz to get sound working" 1.3.9, - then - # On some systems, only quartz is needed? - # appdb says that l3codecx is also needed? - w_call devenum - w_call dmsynth - w_call quartz - fi - if w_workaround_wine_bug 24912 then # kill off lingering installer @@ -11525,8 +11823,6 @@ load_aoe3_demo() PID=`ps augxw | grep IDriver | grep -v grep | awk '{print $2}'` kill $PID fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Games\\Age of Empires III Trial" "age3.exe" } #---------------------------------------------------------------- @@ -11563,8 +11859,6 @@ load_aoe_demo() } WinWaitClose, Microsoft Age of Empires Trial Version " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Games\\Age of Empires Trial" "empires" } #---------------------------------------------------------------- @@ -11608,35 +11902,9 @@ load_acreedbro() } WinWaitClose " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Ubisoft\\Assassin's Creed Brotherhood" AssassinsCreedBrotherhood.exe w_download http://static3.cdn.ubi.com/ac_brotherhood/ac_brotherhood_1.01_ww.exe a2b76f16616709cc16537b0e98faa4181ca904ce - if w_workaround_wine_bug 26562 "Disabling glsl for smoother rendering" - then - w_call glsl=disabled - - # And turn off after-effects to fix depth of field problem caused - # by disabling glsl... - cd "$W_DRIVE_C/users/$LOGNAME/My Documents" - dir="Ubisoft/Assassin's Creed Brotherhood" - file="$dir/ACBrotherhood.ini" - if test -f "$file" - then - mv "$file" "$file.old" - sed 's,PostFX=[0-9]*,PostFX=0,' < "$file.old" > "$file" - else - mkdir -p "$dir" - echo "[Graphics]" > "$file" - echo "PostFX=0" >> "$file" - fi - fi - - if w_workaround_wine_bug 26583 "Installing native d3dx9_36" - then - w_call d3dx9_36 - fi - # FIXME: figure out why these executables don't exit, and do a proper workaround or fix sleep 10 if ps augxw | grep -i exe | egrep 'winemenubuilder.exe|setup.exe|PnkBstrA.exe | egrep -v egrep' @@ -11670,27 +11938,6 @@ load_acreedbro() } WinWaitClose " - - if test `which wine-hotfix-6971` 2> /dev/null - then - if w_workaround_wine_bug 6971 "Pointing menu and icon at wine-hotfix-6971 to fix mouse problems" - then - myexec="Exec=env WINEPREFIX=\"$WINEPREFIX\" wine-hotfix-6971 cmd /c 'C:\\\\\\\\Run-$W_PACKAGE.bat'" - - mymenu="$HOME/Desktop/Assassin's Creed Brotherhood.desktop" - if test -f "$mymenu" - then - sed -i "s,Exec=.*,$myexec," "$mymenu" - fi - mymenu="$XDG_DATA_HOME/applications/wine/Programs/Ubisoft/Assassin's Creed Brotherhood/Assassin's Creed Brotherhood.desktop" - if test -f "$mymenu" - then - sed -i "s,Exec=.*,$myexec," "$mymenu" - fi - fi - else - w_workaround_wine_bug 6971 "Please upgrade to wine-1.3.23 or later; see http://wiki.winehq.org/Bug6971" 1.3.23, - fi } #---------------------------------------------------------------- @@ -11740,7 +11987,6 @@ load_atmosphir() } winwaitclose " - w_declare_exe "$W_PROGRAMS_X86_WIN/Minor Studios/Atmosphir" Atmosphir.exe } #---------------------------------------------------------------- @@ -11801,11 +12047,9 @@ load_avatar_demo() } winwaitclose AVATAR " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Ubisoft\\Demo\\James Cameron's AVATAR - THE GAME (Demo)\\bin" "AvatarDemo.exe" - - w_workaround_wine_bug 26590 "If game seems slow, try winetricks glsl=disabled" } +#---------------------------------------------------------------- w_metadata bttf101 games \ title="Back to the Future Episode 1" \ @@ -11819,11 +12063,6 @@ load_bttf101() { w_download_manual http://www.telltalegames.com/bttf bttf_101_setup.exe 9b15e26d9b4d454f714d6559efe509562df9c10b - if w_workaround_wine_bug 26371 "Installing d3dx9_36 to work around crash" - then - w_call d3dx9_36 - fi - cd "$W_CACHE/$W_PACKAGE" w_ahk_do " SetWinDelay 1000 @@ -11847,8 +12086,6 @@ load_bttf101() } WinWaitClose " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Telltale Games\\Back to the Future The Game\\Episode 1" BackToTheFuture101.exe } #---------------------------------------------------------------- @@ -11863,11 +12100,6 @@ w_metadata bioshock_demo games \ load_bioshock_demo() { - if w_workaround_wine_bug 6971 "Setting mwo=force... please upgrade to wine-1.3.23" 1.3.23, - then - w_call mwo=force - fi - w_download http://us.download.nvidia.com/downloads/nZone/demos/nzd_BioShockPC.zip 7a19186602cec5210e4505b58965e8c04945b3cf w_info "Unzipping demo, installer will start in about 30 seconds." @@ -11906,8 +12138,6 @@ load_bioshock_demo() winwaitclose sleep 3000 ; wait for splash screen to close " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\2K Games\\BioShock Demo\\Builds\\Release" "Bioshock.exe" } #---------------------------------------------------------------- @@ -11918,14 +12148,11 @@ w_metadata bioshock2 games \ year="2010" \ media="dvd" \ file1="BIOSHOCK_2.iso" \ - wine_showstoppers="7065" \ installed_exe1="$W_PROGRAMS_X86_WIN/2K Games/BioShock 2/SP/Builds/Binaries/Bioshock2Launcher.exe" \ installed_exe2="$W_PROGRAMS_X86_WIN/2K Games/BioShock 2/MP/Builds/Binaries/Bioshock2Launcher.exe" load_bioshock2() { - w_workaround_wine_bug 7065 "This game won't work in Wine because its disc check fails." - w_mount BIOSHOCK_2 w_ahk_do " SetWinDelay 1000 @@ -11950,8 +12177,6 @@ load_bioshock2() controlclick Button4 ; Finish } " - w_declare_exe "$W_PROGRAMS_X86_WIN\\2K Games\\BioShock 2\\SP\\Builds\\Binaries" Bioshock2Launcher.exe - w_declare_exe "$W_PROGRAMS_X86_WIN\\2K Games\\BioShock 2\\MP\\Builds\\Binaries" Bioshock2Launcher.exe bioshock2_mp } #---------------------------------------------------------------- @@ -12041,8 +12266,6 @@ load_bfbc2() then w_warn 'If the game says "No CD/DVD error", try "sudo mount -o remount,unhide,uid=`uid -u`". See http://bugs.winehq.org/show_bug.cgi?id=22961 for more info.' fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\Battlefield Bad Company 2" "BFBC2Game.exe" } #---------------------------------------------------------------- @@ -12087,13 +12310,6 @@ load_bladekitten_demo() } WinWaitClose " - - if w_workaround_wine_bug 24681 - then - w_set_app_winver BladeKitten_Demo.exe win2k - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Krome Studios\\Blade Kitten Demo" "BladeKitten_Demo.exe" } #---------------------------------------------------------------- @@ -12114,10 +12330,6 @@ load_cnc_tiberian_sun() # FIXME: we need a progress indicator when unpacking large archives w_info "Unpacking rar file. This will take a minute." w_try_unrar "$W_CACHE/$W_PACKAGE/$file1" - - w_declare_exe \ - "$W_PROGRAMS_X86_WIN\\EA Games\\Command & Conquer The First Decade\\Command & Conquer(tm) Tiberian Sun(tm)\\SUN" \ - Game.exe } #---------------------------------------------------------------- @@ -12161,13 +12373,6 @@ load_cnc3_demo() winwaitclose, Conquer 3, Launch the program " - - if w_workaround_wine_bug 19159 - then - w_call vd=800x600 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\Command & Conquer 3 Tiberium Wars Demo" "CNC3Demo.exe" } #---------------------------------------------------------------- @@ -12214,8 +12419,6 @@ load_cnc_redalert3_demo() WinWaitClose " fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\Red Alert 3 Demo" RA3Demo.exe } #---------------------------------------------------------------- @@ -12252,7 +12455,6 @@ load_cim_demo() w_download_manual http://www.fileplanet.com/218762/210000/fileinfo/Cities-in-Motion-Demo cim-demo-1-0-8.exe d40408b59bc0e6e33b564e9bbb55dbab6c44c630 cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" cim-demo-1-0-8.exe ${W_OPT_UNATTENDED:+ /sp- /silent /norestart} - w_declare_exe "$W_PROGRAMS_X86_WIN\\Cities In Motion Demo" "Cities In Motion.exe" } #---------------------------------------------------------------- @@ -12312,13 +12514,6 @@ load_cod_demo() else setvar= fi - cat > "$W_DRIVE_C/run-$W_PACKAGE.bat" <<__EOF__ -$setvar -c: -cd "$W_PROGRAMS_X86_WIN\\Call of Duty Single Player Demo" -CoDSP.exe %* -__EOF__ - } #---------------------------------------------------------------- @@ -12405,13 +12600,6 @@ load_cod1() else setvar= fi - cat > "$W_DRIVE_C/run-$W_PACKAGE.bat" <<__EOF__ -$setvar -c: -cd "$W_PROGRAMS_X86_WIN\\Call of Duty" -CoDSP.exe %* -__EOF__ - w_warn "This game is copy-protected, and requires the real disc in a real drive to run." } @@ -12464,8 +12652,6 @@ load_cod4mw_demo() } WinWaitClose,WinZip Self-Extractor - CoD4MWDemoSetup_v2 " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Activision\\Call of Duty 4 - Modern Warfare Demo" "iw3sp.exe" } #---------------------------------------------------------------- @@ -12529,20 +12715,7 @@ load_cod5_waw() " # FIXME: Install latest updates - - if w_workaround_wine_bug 16241 "Working around sound bug by setting Win7 mode" 1.3.12, - then - set_app_winver CodWaW.exe win7 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Activision\\Call of Duty - World at War" "CoDWaW.exe" - - if w_workaround_wine_bug 219 - then - w_warn "This game's copy-protection scheme does not currently work in Wine." - else - w_warn "This game is copy-protected, and requires the real disc in a real drive to run." - fi + w_warn "This game is copy-protected, and requires the real disc in a real drive to run." } #---------------------------------------------------------- @@ -12582,8 +12755,6 @@ load_cojbib_demo() winwaitclose Call of Juarez " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Ubisoft\\Demo\\Techland\\Call of Juarez - Bound in Blood SP Demo" "CoJBiBDemo_x86.exe" } #---------------------------------------------------------------- @@ -12624,17 +12795,6 @@ load_civ4_demo() } winwaitclose " - - if w_workaround_wine_bug 6856 - then - w_call msxml3 - fi - if w_workaround_wine_bug 6856 # part 2, still need to file a bug - then - w_call d3dx9_26 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Firaxis Games\\Sid Meier's Civilization 4 Demo" "Civilization4.exe" } #---------------------------------------------------------------- @@ -12653,7 +12813,6 @@ load_crayonphysics_demo() w_download http://crayonphysicsdeluxe.s3.amazonaws.com/crayon_release52demo.exe 4ffd64c630f69e7cf024ef946c2c64c8c4ce4eac # Inno Setup installer w_try "$WINE" "$W_CACHE/$W_PACKAGE/$file1" ${W_OPT_UNATTENDED:+ /sp- /silent /norestart} - w_declare_exe "$W_PROGRAMS_X86_WIN\\Crayon Physics Deluxe Demo" crayon.exe } #---------------------------------------------------------------- @@ -12717,11 +12876,6 @@ load_crysis2() } winwaitclose " - - if w_workaround_wine_bug 26283 - then - w_warn "The game has some nasty flickering, see http://bugs.winehq.org/show_bug.cgi?id=26283" - fi } #---------------------------------------------------------------- @@ -12761,8 +12915,6 @@ load_csi6_demo() WinWaitClose } " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Ubisoft\\Telltale Games\\CSI - Fatal Conspiracy Demo" "CSI6Demo.exe" } #---------------------------------------------------------------- @@ -12815,9 +12967,6 @@ load_darknesswithin2_demo() then w_call d3dx9_36 fi - - # you have to cd to the directory containing DarkLineage.exe before running it - w_declare_exe "$W_PROGRAMS_X86_WIN\\Iceberg Interactive\\Darkness Within 2 Demo" "DarkLineage.exe" } #---------------------------------------------------------------- @@ -12868,7 +13017,6 @@ load_darkspore() } WinWaitClose, InstallShield Wizard " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\Darkspore\\DarksporeBin" "Darkspore.exe" } #---------------------------------------------------------------- @@ -12886,18 +13034,6 @@ load_dcuo() { # The installer would take care of this, but let's do it first w_call flash - if w_workaround_wine_bug 26298 "Installing microsoft runtime libraries" - then - w_call vcrun2005 - fi - if w_workaround_wine_bug 27279 "Installing microsoft XAct audio" - then - w_call xact - fi - if w_workaround_wine_bug 25906 "Installing ie8" - then - w_call ie8 - fi w_mount "DCUO - Disc 1" w_ahk_do " @@ -12971,7 +13107,6 @@ load_dcuo() winwaitclose " w_warn "Now let the wookie install itself, and then quit." - w_declare_exe "$W_PROGRAMS_X86_WIN\\Sony Online Entertainment\\Installed Games\\DC Universe Online Live" LaunchPad.exe } #---------------------------------------------------------------- @@ -13032,37 +13167,27 @@ load_deadspace() controlclick, Button5 controlclick, Button1 " - - if w_workaround_wine_bug 26079 - then - w_call d3dx9_36 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\Dead Space" "Dead Space.exe" } #---------------------------------------------------------------- w_metadata deadspace2 games \ - title="Dead Space 2 (drm broken on wine)" \ + title="Dead Space 2" \ publisher="EA" \ year="2011" \ media="dvd" \ file1="Disc1.iso" \ file2="Disc2.iso" \ installed_exe1="$W_PROGRAMS_X86_WIN/EA Games/Dead Space 2/deadspace2.exe" \ - wine_showstoppers="25853" load_deadspace2() { - if w_workaround_wine_bug 25853 - then - w_warn "Non-steam versions of this game do not run on Wine because Wine does not support the version of SecuROM they use. Proceed only if you want to run into this problem." - fi w_read_key w_mount Disc1 + # FIXME: this bug was fixed in 1.3.36, so this is unneccessary + # # Work around bug 25963 (fails to switch discs) w_warn "Copying discs to hard drive. This will take a few minutes." cd "$W_TMP" @@ -13157,13 +13282,6 @@ load_deadspace2() } WinWaitClose, Product activation " - - if w_workaround_wine_bug 21230 - then - w_call d3dx9_36 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\EA Games\\Dead Space 2" deadspace2.exe } #---------------------------------------------------------------- @@ -13180,8 +13298,6 @@ load_deusex2_demo() { w_download_manual "http://www.techpowerup.com/downloads/1730/Deus_Ex:_Invisible_War_Demo.html" dxiw_demo.zip ccae48fb046d912b3714ea1b4be4294e74bb3092 - w_workaround_wine_bug 6971 "Please upgrade to wine-1.3.23 or later; see http://wiki.winehq.org/Bug6971" 1.3.23, - w_try unzip "$W_CACHE/$W_PACKAGE/dxiw_demo.zip" -d "$W_TMP" cd "$W_TMP" w_ahk_do " @@ -13210,8 +13326,6 @@ load_deusex2_demo() controlclick button4 winwaitclose Deus Ex, Complete " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Deus Ex - Invisible War Demo\\System" "DX2.exe" } #---------------------------------------------------------------- @@ -13284,9 +13398,6 @@ load_diablo2() ControlClick &Cancel, Diablo II" # Dagnabbit, the darn updater starts the game after it updates, no matter what I do? w_killall "Game.exe" - - # Runs better in window - w_declare_exe "$W_PROGRAMS_X86_WIN\\Diablo II" "Diablo II.exe -d3d9 -w" } w_metadata digitanks_demo games \ @@ -13305,11 +13416,10 @@ load_digitanks_demo() w_download "http://static.digitanks.com/files/digitanks.exe" e54ffb07232f434bcfaf7b3d43ddf9affa93ef15 cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" $file1 ${W_OPT_UNATTENDED:+ /S} - if w_workaround_wine_bug 26915 "installing corefonts" + if w_workaround_wine_bug 8060 "installing corefonts" then w_call corefonts fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\Digitanks" digitanksdemo.exe } w_metadata dirt2_demo games \ @@ -13369,8 +13479,6 @@ load_dirt2_demo() } WinWaitClose, DiRT2 Demo - InstallShield Wizard, Complete " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Codemasters\\DiRT2 Demo" "dirt2.exe" } #---------------------------------------------------------------- @@ -13449,8 +13557,6 @@ load_divinity2_demo() then w_call wmp9 fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Divinity II - Ego Draconis - Demo\\Bin" "Divinity2_Demo.exe" } #---------------------------------------------------------------- @@ -13492,7 +13598,6 @@ load_demolition_company_demo() } winwaitclose, Setup - Demolition " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Demolition Company Demo\\" "DemolitionCompany.exe" } #---------------------------------------------------------------- @@ -13509,25 +13614,10 @@ load_dragonage() { w_read_key - if w_workaround_wine_bug 22191 "Installer has a non-fatal crash on exit" - then - w_call nocrashdialog - fi # game can do this, why do we need to? w_call physx - if w_workaround_wine_bug 24837 "Installing C++ runtime library" - then - w_call vcrun2005 - fi - if test "$WINETRICKS_OPT_KEEPISOS" != 1 && \ - test ! -f "$W_CACHE/dragonage/DragonAge.iso" && \ - w_workaround_wine_bug 26459 "Making and mounting an .iso to work around 'Failed to authenticate the disk' error. After each reboot, you'll need to do [sudo mount -o ro,loop '$W_CACHE/dragonage/DragonAge.iso' /mnt/winetricks] to play Dragon Age. Someday this will be automated." - then - WINETRICKS_OPT_KEEPISOS=1 w_mount DragonAge - else - w_mount DragonAge - fi + w_mount DragonAge w_ahk_do " SetWinDelay 1000 @@ -13570,11 +13660,6 @@ load_dragonage() else cp -f "$ini" "$ini.old" fi - if w_workaround_wine_bug 22308 "Setting EnableFrameBufferEffects=0 to work around blurry cut scenes" - then - sed 's,EnableFrameBufferEffects=1,EnableFrameBufferEffects=0,' < "$ini" > "$ini.new" - mv -f "$ini.new" "$ini" - fi if w_workaround_wine_bug 22383 "use strictdrawordering to avoid video problems" then w_call strictdrawordering=enabled @@ -13584,15 +13669,6 @@ load_dragonage() sed 's,UseVSync=1,UseVSync=0,' < "$ini" > "$ini.new" mv -f "$ini.new" "$ini" fi - if w_workaround_wine_bug 26435 "Setting SoundDisabled=0 to fix sound" - then - sed 's,SoundDisabled=1,SoundDisabled=0,' < "$ini" > "$ini.new" - mv -f "$ini.new" "$ini" - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Dragon Age" "bin_ship\\daorigins.exe" - - w_workaround_wine_bug 26211 "You may need to kill DAO or its launcher after each run. The Process view of taskmgr makes this relatively easy." } #---------------------------------------------------------------- @@ -13611,7 +13687,7 @@ load_dragonage_ue() w_mount DRAGONAGE Setup.exe 1 - # Annoyingly, it runs a webrowser so you can activate the extra stuff. Disable that, and w_warn the user after install: + # Annoyingly, it runs a webbrowser so you can activate the extra stuff. Disable that, and w_warn the user after install: WINEDLLOVERRIDES="winebrowser.exe=" export WINEDLLOVERRIDES @@ -13658,11 +13734,6 @@ load_dragonage_ue() winwaitclose " - if w_workaround_wine_bug 22307 - then - w_warn "Turn off frame buffer effects to avoid blurry cut scenes. See http://bugs.winehq.org/show_bug.cgi?id=22307" - fi - if w_workaround_wine_bug 22383 then w_try_winetricks strictdrawordering=enabled @@ -13679,8 +13750,6 @@ load_dragonage_ue() fi w_warn "To activate the additional content, visit http://social.bioware.com/redeem_code.php?path=/dragonage/pc/dlcactivate/en" - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Dragon Age" "bin_ship\\daorigins.exe" } #---------------------------------------------------------------- @@ -13721,16 +13790,6 @@ load_dragonage2_demo() } winwaitclose " - if w_workaround_wine_bug 26205 "installing DirectX runtime libraries" - then - w_call d3dx9_36 - w_call d3dx11_43 - fi - if w_workaround_wine_bug 26211 "installing native devenum to get sound in logo movie" - then - w_call devenum - fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\Dragon Age 2 Demo" "DragonAge2Launcher.exe" } #---------------------------------------------------------------- @@ -13748,11 +13807,6 @@ load_eve() # http://www.eveonline.com/download/?fallback=1& w_download http://content.eveonline.com/561078/EVE_Online_Installer_561078.exe 5b5f0cd4fbd42f82b1d1cccb2e22ddeed97d1d3a - if w_workaround_wine_bug 18221 - then - w_call corefonts - fi - cd "$W_CACHE/$W_PACKAGE" w_ahk_do " run, $file1 @@ -13775,7 +13829,6 @@ load_eve() } WinWaitClose, EVE Online " - w_declare_exe "$W_PROGRAMS_X86_WIN\\CCP\\EVE" "eve.exe" } #---------------------------------------------------------------- @@ -13800,12 +13853,6 @@ load_fable_tlc() w_call mfc42 fi - if test ! -f "$W_CACHE/$W_PACKAGE/FABLE_DISC_1.iso" && w_workaround_wine_bug 24940 - then - # FIXME: port load_harder from winetricks and use it when caching first disc? - w_warn "If the installer can't read from the CD, try using ddrescue to make image of first disc, and place in $W_CACHE/$W_PACKAGE/FABLE_DISC_1.iso" - fi - w_mount FABLE_DISK_1 w_ahk_do " SetTitleMatchMode, 2 @@ -13901,8 +13948,6 @@ _EOF_ then w_call d3dx9_36 fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Games\\Fable - The Lost Chapters" "Fable.exe" } #---------------------------------------------------------------- @@ -13941,7 +13986,6 @@ load_farmsim2011_demo() ControlClick TNewButton2 ; Finish WinWaitClose " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Farming Simulator 2011 Demo" game.exe } #---------------------------------------------------------------- @@ -14004,13 +14048,6 @@ load_fifa11_demo() } WinWaitClose " - - if w_workaround_wine_bug 22161 - then - w_call d3dx9_36 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\EA Sports\\FIFA 11 Demo\\Game" "fifa.exe" } #---------------------------------------------------------------- @@ -14049,12 +14086,6 @@ load_hon() } winwaitclose, Heroes of Newerth, Finish " - if w_workaround_wine_bug 25919 "disabling mmdevapi to fix sound and avoid crash" - then - w_override_dlls disabled mmdevapi - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Heroes of Newerth" "hon.exe" } #---------------------------------------------------------------- @@ -14100,8 +14131,6 @@ load_hordesoforcs2_demo() } winwaitclose Orcs " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Hordes of Orcs 2 Demo" "HoO2.exe" } #---------------------------------------------------------------- @@ -14113,13 +14142,10 @@ w_metadata mfsxde games \ media="dvd" \ file1="FSX DISK 1.iso" \ file2="FSX DISK 2.iso" \ - installed_exe1="$W_PROGRAMS_X86_WIN/Microsoft Games/Microsoft Flight Simulator X/fsx.exe" \ - wine_showstoppers="26411" + installed_exe1="$W_PROGRAMS_X86_WIN/Microsoft Games/Microsoft Flight Simulator X/fsx.exe" load_mfsxde() { - w_workaround_wine_bug 26411 "Game hangs on first screen for me" - if w_workaround_wine_bug 25139 "Setting virtual desktop so license screen shows up on first run" then w_call vd=1024x768 @@ -14182,8 +14208,6 @@ load_mfsxde() ; Setup doesn't close on its own, because this process doesn't exit cleanly process, close, IDriver.exe " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Games\\Microsoft Flight Simulator X" "fsx.exe" } #---------------------------------------------------------------- @@ -14230,8 +14254,6 @@ load_mfsx_demo() ; Setup doesn't close on its own, because this process doesn't exit cleanly process, close, IDriver.exe " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Games\\Microsoft Flight Simulator X" "fsx.exe" } #---------------------------------------------------------------- @@ -14242,18 +14264,12 @@ w_metadata gothic4_demo games \ year="2010" \ media="manual_download" \ file1="ArcaniA_Gothic4_Demo_Setup.zip" \ - installed_exe1="$W_PROGRAMS_X86_WIN/JoWooD Entertainment AG/ArcaniA - Gothic 4 Demo/Arcania.exe" \ - wine_showstoppers="7065" + installed_exe1="$W_PROGRAMS_X86_WIN/JoWooD Entertainment AG/ArcaniA - Gothic 4 Demo/Arcania.exe" # http://appdb.winehq.org/objectManager.php?sClass=version&iId=21507 load_gothic4_demo() { - if w_workaround_wine_bug 7065 - then - w_warn "Non-steam versions of this game do not run on Wine because Wine does not support the version of SecuROM they use. Proceed only if you want to run into this problem." - fi - w_download_manual http://www.gamershell.com/download_63874.shtml ArcaniA_Gothic4_Demo_Setup.zip d36024c0235878c4589234a56cc8b6e05da5c593 cd "$W_TMP" @@ -14307,18 +14323,6 @@ load_gothic4_demo() } winwaitclose " - - if w_workaround_wine_bug 21939 - then - w_call wmp9 - fi - - if w_workaround_wine_bug 24250 - then - w_call vcrun2008 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\JoWooD Entertainment AG\\ArcaniA - Gothic 4 Demo" "Arcania.exe" } #---------------------------------------------------------------- @@ -14382,8 +14386,6 @@ load_gta_vc() w_call vd=800x600 fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\Rockstar Games\\Grand Theft Auto Vice City" gta-vc.exe - myexec="Exec=env WINEPREFIX=\"$WINEPREFIX\" wine cmd /c 'C:\\\\\\\\Run-gta_vc.bat'" mymenu="$XDG_DATA_HOME/applications/wine/Programs/Rockstar Games/Grand Theft Auto Vice City/Play GTA Vice City.desktop" if test -f "$mymenu" && w_workaround_wine_bug 26304 "Fixing system menu" @@ -14424,8 +14426,6 @@ load_guildwars() Sleep 4000 WinClose, ahk_class ArenaNet_Dx_Window_Class " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Guild Wars" "Gw.exe" } #---------------------------------------------------------------- @@ -14442,11 +14442,6 @@ w_metadata hegemonygold_demo games \ load_hegemonygold_demo() { - if w_workaround_wine_bug 25767 - then - w_warn "This game works, but has some rendering glitches in Wine." - fi - # 6 Mar 2011: 8c4d8aa8f997b106c78b065a4b200e5e1ab846a8 # 28 Apr 2011: 93677013fc17f014b1640bed070e8bb1b2a17445 # 25 Jun 2011: 4069656ea3c3760b67d1c5adff37de7472955f72 @@ -14483,8 +14478,6 @@ load_hegemonygold_demo() } WinWaitClose,Hegemony " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Longbow Digital Arts\\Hegemony Gold" "Hegemony Gold.exe" } #---------------------------------------------------------------- @@ -14506,11 +14499,6 @@ load_hegemony_demo() cd "$W_CACHE/$W_PACKAGE" - if w_workaround_wine_bug 24819 - then - w_override_dlls disabled gameux - fi - w_ahk_do " SetTitleMatchMode, 2 run, Hegemony_Philip_of_Macedon_Installer.exe @@ -14552,8 +14540,6 @@ load_hegemony_demo() } WinWaitClose,Hegemony " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Longbow Digital Arts\\Hegemony Philip of Macedon" "Hegemony Philip of Macedon.exe" } #---------------------------------------------------------------- @@ -14602,8 +14588,6 @@ load_hphbp_demo() # Won't really work on cygwin, but that's ok. cd "$W_PROGRAMS_X86_UNIX/Electronic Arts" ln -s "Harry Potter and the Half-Blood Prince"* "Harry Potter and the Half-Blood Prince Demo" - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\Harry Potter and the Half-Blood Prince Demo\\pc" hp6_demo.exe } #---------------------------------------------------------------- @@ -14620,13 +14604,7 @@ load_imvu() { w_download http://static-akm.imvu.com/imvufiles/installers/InstallIMVU_465.0_st_c.exe 3a5c6c335227a5709c5772f91d8407edd07d4012 - if w_workaround_wine_bug 28541 "Installing Visual C++ 2008 runtime to avoid crash on startup" - then - w_call vcrun2008 - fi - cd "$W_CACHE/$W_PACKAGE" - w_ahk_do " SetTitleMatchMode, 2 SetWinDelay 500 @@ -14646,8 +14624,6 @@ load_imvu() } winwaitclose " - - w_declare_exe "c:\\users\\$LOGNAME\\Application Data\\IMVUClient" "IMVUClient.exe" } #---------------------------------------------------------------- @@ -14665,12 +14641,6 @@ w_metadata kotor1 games \ load_kotor1() { - # without virtual desktop, some in-game resolutions cause a crash. - if w_workaround_wine_bug 16596 - then - w_call vd=800x600 - fi - w_mount "KOTOR_1" w_ahk_do " SetTitleMatchMode 2 @@ -14736,8 +14706,6 @@ load_kotor1() } winwaitclose Star Wars, Complete " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\LucasArts\\SWKotOR" "swkotor.exe" } #---------------------------------------------------------------- @@ -14796,8 +14764,6 @@ load_losthorizon_demo() } WinWaitClose " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Deep Silver\\Lost Horizon Demo" "fsasgame.exe" } #---------------------------------------------------------------- @@ -14856,8 +14822,6 @@ load_lego_potc_demo() } winwaitclose, LEGO " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Disney Interactive Studios\\LEGO Pirates DEMO" LEGOPiratesDEMO.exe } #---------------------------------------------------------------- @@ -14903,17 +14867,10 @@ load_lhp_demo() winwaitclose, LEGO, Finish " - if w_workaround_wine_bug 23397 - then - w_warn "If sound stutters, try switching to OSS sound in winecfg (winetricks sound=oss)" - fi - # Work around locale issues by symlinking the app's directory to not have a funny char # Won't really work on cygwin, but that's ok. cd "$W_PROGRAMS_X86_UNIX/WB Games" ln -s LEGO*Harry\ Potter*DEMO LEGO_Harry_Potter_DEMO - - w_declare_exe "$W_PROGRAMS_X86_WIN\\WB Games\\LEGO_Harry_Potter_DEMO" "LEGOHarryPotterDEMO.exe" } #---------------------------------------------------------------- @@ -14945,12 +14902,6 @@ load_lswcs() } winwaitclose, LEGO " - # Installer crashes at end (http://bugs.winehq.org/show_bug.cgi?id=22529) but this doesn't seem to hurt. - # Wait for all processes to exit, else unmount will fail - #$W_WINESERVER -w - - w_declare_exe "$W_PROGRAMS_X86_WIN\\LucasArts\\LEGO Star Wars - The Complete Saga" "LEGOStarWarsSaga.exe" - w_warn "This game is copy-protected, and requires the real disc in a real drive to run." } @@ -15009,8 +14960,6 @@ load_lemonysnicket() } WinWaitClose, Lemony " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Activision\\Lemony Snicket's A Series of Unfortunate Events" System\\game.exe } #---------------------------------------------------------------- @@ -15046,7 +14995,6 @@ load_luxor_ar() } winwaitclose " - w_declare_exe "$W_PROGRAMS_X86_WIN\\MumboJumbo\\Luxor Amun Rising" "Luxor AR.exe" } #---------------------------------------------------------------- @@ -15066,28 +15014,11 @@ load_masseffect2() w_mount MassEffect2 w_read_key - if w_workaround_wine_bug 22091 "May hang or crash at end of install, but should install ok." - then - w_call nocrashdialog - fi - - if w_workaround_wine_bug 23126 "Installing C runtime library" 1.3.0, - then - w_call vcrun2005 - fi - if w_workaround_wine_bug 23125 "Installing d3dx10 libraries" 1.3.0, - then - w_call d3dx10 - fi # FIXME: only do this for nvidia cards if w_workaround_wine_bug 23151 "Disabling glsl" then w_call glsl=disabled fi - if w_workaround_wine_bug 22919 "Installing physx" - then - w_call physx - fi w_ahk_do " SetTitleMatchMode, 2 @@ -15137,9 +15068,6 @@ load_masseffect2() sleep 1000 } " - w_workaround_wine_bug 6971 "Please upgrade to wine-1.3.23 or later; see http://wiki.winehq.org/Bug6971" 1.3.23, - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Mass Effect 2\\Binaries" "MassEffect2.EXE" } #---------------------------------------------------------------- @@ -15156,28 +15084,11 @@ load_masseffect2_demo() { w_download http://static.cdn.ea.com/bioware/u/f/eagames/bioware/masseffect2/ME2_DEMO/MassEffect2DemoEN.exe cda9a25387a98e29772b3ccdcf609f87188285e2 - if w_workaround_wine_bug 22091 "May hang or crash at end of install, but should install ok." - then - w_call nocrashdialog - fi - - if w_workaround_wine_bug 23126 "Installing C runtime library" 1.3.0, - then - w_call vcrun2005 - fi - if w_workaround_wine_bug 23125 "Installing d3dx10 libraries" 1.3.0, - then - w_call d3dx10 - fi # FIXME: only do this for nvidia cards if w_workaround_wine_bug 23151 "Disabling glsl" then w_call glsl=disabled fi - if w_workaround_wine_bug 22919 "Installing physx" - then - w_call physx - fi # Don't let self-extractor write into $W_CACHE case "$OS" in @@ -15222,42 +15133,6 @@ load_masseffect2_demo() sleep 1000 } " - if test `which wine-hotfix-6971` 2> /dev/null - then - if w_workaround_wine_bug 6971 "Pointing menu and icon at wine-hotfix-6971 so mouse will work, assuming your X supports XInput2" - then - w_declare_exe "$W_PROGRAMS_X86_WIN\\Mass Effect 2 Demo\\Binaries" "MassEffect2.EXE" - myexec="Exec=env WINEPREFIX=\"$XDG_DATA_HOME/wineprefixes/masseffect2_demo\" wine-hotfix-6971 cmd /c 'C:\\\\\\Run-masseffect2_demo.bat'" - - mymenu="$HOME/Desktop/Mass Effect 2 Demo.desktop" - me2tries=0 - while test ! -f "$mymenu" - do - if test $me2tries -gt 120 - then - w_die "timeout waiting for winemenubuilder to finish :-(" - fi - me2tries=`expr $me2tries + 1` - echo "waiting for winemenubuilder to finish..." - sleep 1 - done - unset me2tries - if test -f "$mymenu" - then - # this is a hack, hopefully the wine bug will be fixed soon - sed -i "s,Exec=.*,$myexec," "$mymenu" - fi - mymenu="$XDG_DATA_HOME/applications/wine/Programs/Mass Effect 2 Demo/Mass Effect 2 Demo.desktop" - if test -f "$mymenu" - then - # this is a hack, hopefully the wine bug will be fixed soon - sed -i "s,Exec=.*,$myexec," "$mymenu" - fi - fi - else - w_workaround_wine_bug 6971 "Please upgrade to wine-1.3.23 or later; see http://wiki.winehq.org/Bug6971" 1.3.23, || true - fi - } #---------------------------------------------------------------- @@ -15278,8 +15153,6 @@ load_maxmagicmarker_demo() # Work around bug in game?! cd "$W_PROGRAMS_X86_UNIX/$W_PACKAGE" mv "max and the magic markerdemo pc" "max and the magic markerdemo pc"_Data - - w_declare_exe "$W_PROGRAMS_X86_WIN\\$W_PACKAGE" "max and the magic markerdemo pc.exe" } #---------------------------------------------------------------- @@ -15343,7 +15216,6 @@ load_mdk() cd "$W_DRIVE_C/SHINY/MDK" w_try_unzip . "$W_CACHE/$W_PACKAGE"/patch-mdk3dfx.zip - w_declare_exe "C:\\SHINY\\MDK" "MDK3DFX.EXE" # TODO: wine fails to install menu items, add a workaround for that } @@ -15386,8 +15258,6 @@ load_menofwar() ControlClick, TNewButton1, Setup - Men of War, Setup has finished } " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Aspyr\\Men of War" "mow.exe" } #---------------------------------------------------------------- @@ -15403,13 +15273,6 @@ w_metadata mb_warband_demo games \ load_mb_warband_demo() { - if w_workaround_wine_bug 23207 "" 1.3.23, - then - w_die "Please upgrade to wine-1.3.23 or later, built with gcc-4.4.5 or later, else game crashes on startup." - fi - w_workaround_wine_bug 6971 "Please upgrade to wine-1.3.23 or later; see http://wiki.winehq.org/Bug6971" 1.3.23, - # Mouse still doesn't work quite right after picking menu, see bug 25705. - w_download "http://download.taleworlds.com/mb_warband_setup_1143.exe" 94fb829068678e27bcd67d9e0fde7f08c51a23af cd "$W_CACHE/$W_PACKAGE" @@ -15427,8 +15290,6 @@ load_mb_warband_demo() } winwaitclose Warband " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Mount&Blade Warband" "mb_warband.exe" } #---------------------------------------------------------------- @@ -15445,24 +15306,6 @@ load_mise() { w_download_manual "http://www.direct2drive.com/8241/product/Buy-The-Secret-of-Monkey-Island(R):-Special-Edition-Download" SecretOfMonkeyIslandSE_ddsetup.zip 2e32458698c9ec7ebce94ae5c57531a3fe1dbb9e - if w_workaround_wine_bug 22161 - then - # Doesn't crash, but you only get a black screen and a flood of d3dx fixme's without native d3dx9_36 - w_call d3dx9_36 - fi - - if w_workaround_wine_bug 24545 - then - # Game wants to install directx, but we delete it. It really only needs xact for x3daudio?_?.dll - w_call xact - fi - - if w_workaround_wine_bug 24547 - then - # It really does need vcrun2005, for msvp80.dll (and potentially one stub from msvcr80) - w_call vcrun2005 - fi - mkdir -p "$W_TMP/$W_PACKAGE" cd "$W_TMP/$W_PACKAGE" @@ -15521,8 +15364,6 @@ load_mise() Process, Close, MISE.exe " fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\LucasArts\\The Secret of Monkey Island Special Edition" "MISE.exe" } #---------------------------------------------------------------- @@ -15565,7 +15406,6 @@ load_myth2_demo() } winwaitclose " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Myth II Demo" "Myth II Demo.exe" } #---------------------------------------------------------------- @@ -15634,90 +15474,6 @@ load_nfsshift_demo() } winwaitclose, Setup, Finish " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\Need for Speed SHIFT Demo" "shiftdemo.exe" -} - -#---------------------------------------------------------------- - -w_metadata nfsworld games \ - title="Need For Speed World" \ - publisher="EA" \ - year="2013" \ - media="download" \ - file1="setup_nfsw" \ - installed_exe1="$W_PROGRAMS_X86_WIN/Electronic Arts/Need For Speed World/GameLauncher.exe" - -load_nfsworld() -{ - w_workaround_wine_bug 27048 "The patcher will probably put up an error dialog and then hang. When this happens, kill it and try again. It should succeed after the fourth or so try." - - w_workaround_wine_bug 27047 "Game fails with corrupt executable error in wine-1.3.19 and earlier" 1.3.20, - - # This changes frequently, I fear - # Be careful to update $file1 when you update the url - # 1.8.40.65 9b1f10af09350e2b3f5ccbc679dbea628e9f432d0 ? - # 1.8.40.1229 f355fcad20dd6267910bec93a318224718ab5de7 - # 4 July 2013 1.8.40.1509 6f76c74ae07d36470931bac74b44548d1a319ce0 - w_download http://static.cdn.ea.com/blackbox/u/f/NFSWO/1509/launcher/weblaunch_1.8.40.1509/setup_nfsw.exe 6f76c74ae07d36470931bac74b44548d1a319ce0 - - # pre-1.6 versions of wine also needed ie7? - if w_workaround_wine_bug 25658 "Installing dotnet20 so launcher does not just exit" - then - w_call dotnet20 - fi - - if w_workaround_wine_bug 28652 "Installing gdiplus so launcher does not look horrible (and to work around crash bug 33880, too)" - then - w_call gdiplus - fi - - if test "$W_OPT_UNATTENDED" && w_workaround_wine_bug 25961 "Installing vcrun2008 just to make unattended install easier" - then - w_call vcrun2008 - fi - - if w_workaround_wine_bug 26915 "installing corefonts so help works" - then - w_call corefonts - fi - - cd "$W_CACHE/$W_PACKAGE" - w_ahk_do " - SetWinDelay 500 - SetTitleMatchMode, 2 - run $file1 - winwait, Language - if ( w_opt_unattended > 0 ) { - ControlClick TNewButton1 ; Next - winwait Setup - Need For Speed - ControlClick TNewButton1 ; Next - winwait Setup - Need For Speed, License - ControlClick TNewRadioButton1 ; Accept - sleep 1000 - ControlClick TNewButton2 ; Next - winwait Setup - Need For Speed, be installed - ControlClick TNewButton3 ; Next - winwait Setup - Need For Speed, be downloaded - ControlClick TNewButton4 ; Next - winwait Setup - Need For Speed, shortcuts - ControlClick TNewButton5 ; Next - winwait Setup - Need For Speed, Tasks - ControlClick TNewButton5 ; Next - winwait Setup - Need For Speed, Ready to Install - ControlClick TNewButton5 ; Next - } - winwait Setup - Need For Speed, Completing - if ( w_opt_unattended > 0 ) { - send {Space} ; uncheck readme - send {Tab} - send {Space} ; uncheck launch - sleep 1000 ; let launch uncheck take effect? - ControlClick TNewButton5 ; Finish - } - winwaitclose - " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\Need For Speed World" GameLauncher.exe } #---------------------------------------------------------------- @@ -15754,7 +15510,6 @@ load_njcwp_trial() else w_try "$WINE" $file1 fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\NJStar Chinese WP" "njstar.exe" } #---------------------------------------------------------------- @@ -15791,7 +15546,6 @@ load_njjwp_trial() else w_try "$WINE" $file1 fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\NJStar Japanese WP" "njstarj.exe" } #---------------------------------------------------------------- @@ -15842,8 +15596,6 @@ load_oblivion() then w_call d3dx9_36 fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Bethesda Softworks\\Oblivion" "Oblivion.exe" } #---------------------------------------------------------------- @@ -15863,7 +15615,6 @@ load_penpenxmas() cd "$W_CACHE/$W_PACKAGE" "$WINE" PenPenXmasOlympics100.exe $W_UNATTENDED_SLASH_S - w_declare_exe "$W_PROGRAMS_X86_WIN\\PPO" "PPO.exe" } #---------------------------------------------------------------- @@ -15898,8 +15649,6 @@ load_plantsvszombies() } WinWaitClose " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\PopCap Games\\Plants vs. Zombies" "PlantsVsZombies.exe" } #---------------------------------------------------------------- @@ -15954,98 +15703,62 @@ load_popfs() ControlClick, Button4 } " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Ubisoft\\Prince of Persia The Forgotten Sands" "Prince of Persia.exe" -} - -#---------------------------------------------------------------- - -w_metadata puzzleagent_demo games \ - title="Puzzle Agent Demo" \ - publisher="Telltale Games" \ - year="2010" \ - media="download" \ - file1="PuzzleAgent_PC_Setup.exe" \ - installed_exe1="$W_PROGRAMS_X86_WIN/Telltale Games/Puzzle Agent/Puzzle Agent/Grickle101.exe" - -load_puzzleagent_demo() -{ - w_download http://telltale.vo.llnwd.net/o15/games/puzzleagent/100/PuzzleAgent_PC_Setup.exe ac0012889fd80237928207c9d19b02f5968761a4 - - cd "$W_CACHE/$W_PACKAGE" - - w_ahk_do " - Run, PuzzleAgent_PC_Setup.exe - SetTitleMatchMode, 2 - WinWait,Puzzle Agent Setup, Welcome - if ( w_opt_unattended > 0 ) { - Sleep 500 - ControlClick Button2 ; Next - WinWait,Puzzle Agent Setup, properly - Sleep 500 - ControlClick Button5 ;DirectX - Sleep 500 - ControlClick Button2 ; Next - WinWait,Puzzle Agent Setup, before - Sleep 500 - ControlClick Button2 ; Agree - WinWait,Puzzle Agent Setup, different - Sleep 500 - ControlClick Button2 ; Install - WinWait,Puzzle Agent Setup, your - Sleep 500 - ControlClick Button4 ; Play - Sleep 500 - ControlClick Button5 ; will - Sleep 500 - ControlClick Button2 ; Finish - } - WinWaitClose, Puzzle Agent - " - - if w_workaround_wine_bug 25210 "" 1.3.8, - then - w_call vcrun2008 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Telltale Games\\Puzzle Agent\\Puzzle Agent" "Grickle101.exe" } #---------------------------------------------------------------- w_metadata qq apps \ - title="QQ 6.3 (Chinese chat app)" \ + title="QQ 8.0(Chinese chat app)" \ publisher="Tencent" \ - year="2014" \ + year="2015" \ media="download" \ - file1="QQ6.3.exe" \ - installed_exe1="$W_PROGRAMS_X86_WIN/Tencent/QQ/Bin/QQ.exe" \ + file1="QQ8.0.exe" \ + file2="QQ.tar.gz"\ + installed_exe1="$W_PROGRAMS_X86_WIN/Tencent/QQ/Bin/QQScLauncher.exe" \ homepage="http://www.qq.com" \ unattended="no" load_qq() { - w_download http://dldir1.qq.com/qqfile/qq/QQ6.3/12369/QQ6.3.exe cebe73a2f8b7299ba0f01aba779e0e4a7dbd173b + w_download http://dldir1.qq.com/qqfile/qq/QQ8.0/16968/QQ8.0.exe ef92f3863113971c95a79aa75e601893d803826c + w_download http://hillwoodhome.net/wine/QQ.tar.gz 08de45d3e5bb34b22e7c33e1163daec69742db58 - if w_workaround_wine_bug 29636 "Installing native riched20 to work around crash bug" + if w_workaround_wine_bug 5162 "Installing native riched20 to work around can't input username." then w_call riched20 fi - if w_workaround_wine_bug 34566 "Installing native ctf to work around crash" - then - w_call msctf - fi - # Make sure chinese fonts are available w_call fakechinese # uses mfc42u.dll w_call mfc42 + if w_workaround_wine_bug 38171 "Installing desktop file to work around bug" + then + cd "$W_TMP/" + tar -zxf "$W_CACHE/qq/QQ.tar.gz" + mkdir -p $HOME/.local/share/applications/wine/Programs/腾讯软件/QQ + mkdir -p $HOME/.local/share/icons/hicolor/48x48/apps + mkdir -p $HOME/.local/share/icons/hicolor/256x256/apps + w_try mv QQ/腾讯QQ.desktop ~/.local/share/applications/wine/Programs/腾讯软件/QQ + w_try mv QQ/48x48/QQ.png ~/.local/share/icons/hicolor/48x48/apps + w_try mv QQ/256x256/QQ.png ~/.local/share/icons/hicolor/256x256/apps + echo Exec=env WINEPREFIX="$WINEPREFIX" "$WINE" $W_PROGRAMS_X86_WIN\/Tencent\/QQ\/bin\/QQScLauncher.exe >> $HOME/.local/share/applications/wine/Programs/腾讯软件/QQ/腾讯QQ.desktop + fi + + if w_workaround_wine_bug 39657 "Disable ntoskrnl.exe to work around can't be started bug" + then + w_override_dlls disabled ntoskrnl.exe + fi + + if w_workaround_wine_bug 37680 "Disable txplatform.exe to work around QQ can't be quit cleanly" + then + w_override_dlls disabled txplatform.exe + fi + cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" "$file1" - w_declare_exe "$W_PROGRAMS_X86_WIN\\Tencent\\QQ\\Bin" QQ.exe } #---------------------------------------------------------------- @@ -16069,16 +15782,16 @@ load_qqintl() w_call riched20 fi - if w_workaround_wine_bug 34566 "Installing native ctf to work around crash" - then - w_call msctf - fi - if w_workaround_wine_bug 37617 "Installing native wininet to work around crash" then w_call wininet fi + if w_workaround_wine_bug 37680 "Disable txplatform.exe to work around QQ can't be quit cleanly" + then + w_override_dlls disabled txplatform.exe + fi + # Make sure chinese fonts are available w_call fakechinese @@ -16087,7 +15800,6 @@ load_qqintl() cd "$W_CACHE/$W_PACKAGE" w_try "$WINE" "$file1" - w_declare_exe "$W_PROGRAMS_X86_WIN\\Tencent\\QQIntl\\Bin" QQ.exe } #---------------------------------------------------------------- @@ -16106,10 +15818,6 @@ load_ragnarok() then w_call vcrun6 fi - if w_workaround_wine_bug 28228 "Installing Visual C++ 2008 runtime" - then - w_call vcrun2008 - fi # publisher puts SHA1 checksums on download page, nice # BDA295E3A2A57CD02BD122ED7BF4836AC012369A @@ -16153,11 +15861,6 @@ load_rct3deluxe() { w_mount RCT3 - if w_workaround_wine_bug 26396 - then - w_call quartz - fi - # FIXME: make videos and music work # Game still doesn't show .wmv logo videos nor play .wma background audio in menu # though it does in Jake's screencast. Loading wmp9 and devenum gets it to @@ -16197,8 +15900,6 @@ load_rct3deluxe() } WinWaitClose Setup - RollerCoaster Tycoon 3, finished " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Atari\\RollerCoaster Tycoon 3" RCT3.EXE } #---------------------------------------------------------------- @@ -16218,16 +15919,6 @@ load_rayman2_demo() cd "$W_TMP" w_try unzip "$W_CACHE/$W_PACKAGE/rayman2high.zip" - if w_workaround_wine_bug 16596 - then - w_call vd=800x600 - fi - - if w_workaround_wine_bug 21159 - then - w_call dinput - fi - w_ahk_do " SetWinDelay 500 SetTitleMatchMode, 3 @@ -16266,8 +15957,6 @@ load_rayman2_demo() # this is a hack, hopefully the wine bug will be fixed soon sed -i "s,Exec=.*,$myexec," "$mymenu" fi - - w_declare_exe "c:\\UbiSoft\\Rayman2Demo" "Rayman2Demo.exe" } #---------------------------------------------------------------- @@ -16304,8 +15993,6 @@ load_riseofnations_demo() then w_call directmusic fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Games\\Rise of Nations Trial" "nations.exe" } #---------------------------------------------------------------- @@ -16339,8 +16026,6 @@ load_secondlife() } winwaitclose " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\SecondLifeViewer" "SecondLife.exe" } #---------------------------------------------------------------- @@ -16356,16 +16041,6 @@ w_metadata sims3 games \ load_sims3() { - if w_workaround_wine_bug 22350 "Launcher needs .net" - then - w_call dotnet20 - fi - - if w_workaround_wine_bug 21517 "Old wine needs native DirectX for this game" 1.3.8, - then - w_call d3dx9_36 - fi - w_read_key w_mount Sims3 @@ -16417,8 +16092,6 @@ load_sims3() } winwaitclose " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\The Sims 3\\Game\\Bin" "TS3.exe" } #---------------------------------------------------------------- @@ -16434,11 +16107,6 @@ w_metadata simsmed games \ load_simsmed() { - if w_workaround_wine_bug 21517 "Old wine needs native DirectX for this game" 1.3.8, - then - w_call d3dx9_36 - fi - w_read_key w_mount TSimsM @@ -16523,23 +16191,6 @@ load_simsmed() } winwaitclose " - - if w_workaround_wine_bug 25535 ".net 4 doesn't install on Wine, fixing menu to run game directly" - then - myexec="Exec=env WINEPREFIX=\"$WINEPREFIX\" wine cmd /c 'C:\\\\\\\\Run-$W_PACKAGE.bat'" - mymenu="$XDG_DATA_HOME/applications/wine/Programs/Electronic Arts/The Sims Medieval/The Sims™ Medieval.desktop" - if test -f "$mymenu" - then - sed -i "s,Exec=.*,$myexec," "$mymenu" - fi - mymenu="$HOME/Desktop/The Sims™ Medieval.desktop" - if test -f "$mymenu" - then - sed -i "s,Exec=.*,$myexec," "$mymenu" - fi - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\The Sims Medieval\\Game\\Bin" "TSM.exe" } #---------------------------------------------------------------- @@ -16618,8 +16269,6 @@ load_sims3_gen() } winwaitclose " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\The Sims 3 Generations/Game/Bin" "TS3EP04.exe" } #---------------------------------------------------------------- @@ -16634,16 +16283,6 @@ w_metadata splitsecond games \ load_splitsecond() { - if w_workaround_wine_bug 22774 "" 1.3.0 - then - w_warn "On wine, install takes an extra 7 minutes at the end, please be patient." - fi - - if w_workaround_wine_bug 22865 - then - w_warn "This game is currently unplayable on wine due to rendering problems; see winehq bug 22865." - fi - # Key is used in first run activation, no need to read it here. w_mount SplitSecond @@ -16683,8 +16322,6 @@ load_splitsecond() sleep 500 ControlClick, Button4, Split " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Disney Interactive Studios\\Split Second" "SplitSecond.exe" } #---------------------------------------------------------------- @@ -16706,11 +16343,6 @@ load_splitsecond_demo() w_warn "On wine, install takes an extra 7 minutes at the end, please be patient." fi - if w_workaround_wine_bug 22865 - then - w_warn "This game is currently unplayable on wine due to rendering problems; see winehq bug 22865." - fi - cd "$W_CACHE/$W_PACKAGE" w_ahk_do " SetTitleMatchMode, 2 @@ -16736,8 +16368,6 @@ load_splitsecond_demo() ControlClick, Button1, Split, completed ControlClick, Button4, Split, completed " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Disney Interactive Studios\\Split Second Demo" "SplitSecondDEMO.exe" } #---------------------------------------------------------------- @@ -16800,8 +16430,6 @@ load_spore() } winwaitclose, SPORE, complete " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\SPORE\\Sporebin" "SporeApp.exe" } #---------------------------------------------------------------- @@ -16853,8 +16481,6 @@ load_spore_cc_demo() else w_try "$WINE" "$file1" fi - w_declare_exe "$W_PROGRAMS_X86_WIN\\Electronic Arts\\SPORE\\Sporebin" \ - "SporeCreatureCreator.exe" } #---------------------------------------------------------------- @@ -16922,8 +16548,6 @@ load_starcraft2_demo() process, close, SC2.exe } " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\StarCraft II Demo" "StarCraft II.exe" } #---------------------------------------------------------------- @@ -16940,15 +16564,6 @@ load_theundergarden_demo() { w_download_manual http://www.bigdownload.com/games/the-undergarden/pc/the-undergarden-demo TheUnderGarden_PC_B34_SRTB.30_28OCT10.exe acf90c422ac2f2f242100f39bedfe7df0c95f7a - if w_workaround_wine_bug 25384 - then - w_call vcrun2008 - fi - if w_workaround_wine_bug 25385 - then - w_call d3dx9_36 - fi - cd "$W_CACHE/$W_PACKAGE" w_ahk_do " @@ -17011,8 +16626,6 @@ load_theundergarden_demo() } WinWaitClose,Setup,launched " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\The UnderGarden" "TheUndergarden.exe" } #---------------------------------------------------------------- @@ -17027,12 +16640,6 @@ w_metadata tmnationsforever games \ load_tmnationsforever() { - if w_workaround_wine_bug 20915 - then - # FIXME: script this? - w_warn "To fix choppy sound/low fps, try setting Settings/Advanced/Audio to portaudio when starting the game." - fi - # Before: cab0cf66db0471bc2674a3b1aebc35de0bca6ed0 # 29 Mar 2011: 23388798d5c90ad4a233b4cd7e9fcafd69756978 w_download "http://files.trackmaniaforever.com/tmnationsforever_setup.exe" 23388798d5c90ad4a233b4cd7e9fcafd69756978 @@ -17077,8 +16684,6 @@ load_tmnationsforever() } WinWaitClose " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\TmNationsForever" "TmForever.exe" } #---------------------------------------------------------------- @@ -17128,8 +16733,6 @@ load_trainztcc_2004() winwaitclose " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Auran\\TRS2004" "TRS2004.exe" - # And, while we're at it, also install the accompanying paint shed app cd ${W_ISO_MOUNT_ROOT}/TRAINZ_PAINTSHED w_ahk_do " @@ -17153,7 +16756,6 @@ load_trainztcc_2004() } winwaitclose " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Auran\\Trainz Paint Shed" "Trainz Paint Shed.exe" paintshed } #---------------------------------------------------------------- @@ -17192,7 +16794,6 @@ load_sammax301_demo() } winwaitclose Sam and Max The Penal Zone Setup " - w_declare_exe "$W_PROGRAMS_X86_WIN\\Telltale Games\\Sam and Max - The Devil's Playhouse\\The Penal Zone" "SamMax301.exe" } #---------------------------------------------------------------- @@ -17228,13 +16829,6 @@ load_sammax304_demo() } WinWaitClose " - - if w_workaround_wine_bug 24250 "Installing visual C++ runtimes" 1.3.15, - then - w_call vcrun2005 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Telltale Games\\Sam and Max - The Devil's Playhouse\\Beyond the Alley of the Dolls" "SamMax304.exe" } #---------------------------------------------------------------- @@ -17251,11 +16845,6 @@ load_tropico3_demo() { w_download_manual "http://www.tropico3.com/?p=downloads" Tropico3Demo.exe e031749db346ac3a87a675787c81eb1ca8cb5909 - if w_workaround_wine_bug 24819 "Disabling gameux" - then - w_override_dlls disabled gameux - fi - cd "$W_CACHE/$W_PACKAGE" w_ahk_do " @@ -17279,15 +16868,6 @@ load_tropico3_demo() } WinWaitClose " - - w_workaround_wine_bug 16328 "seawater is invisible in this wine, please update to 1.3.9 or later" 1.3.9, - - if w_workaround_wine_bug 24845 "disabling mmdevapi to fix sound" 1.3.21, - then - w_override_dlls disabled mmdevapi - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Kalypso\\Tropico 3 Demo" "Tropico3 Demo.exe" } #---------------------------------------------------------------- @@ -17351,26 +16931,6 @@ load_singularity() } " - if w_workaround_wine_bug 6971 "Setting mwo=force... please upgrade to wine-1.3.23" 1.3.23, - then - w_call mwo=force - fi - - if w_workaround_wine_bug 22548 - then - echo "Disabling \'depth of field\'" - cat > "$W_TMP"/dof.reg <<_EOF_ -REGEDIT4 - -[HKEY_CURRENT_USER\Software\Activision\Singularity] -"DepthOfField"=dword:00000000 - -_EOF_ - w_try_regedit "$W_TMP_WIN"\\dof.reg - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Activision\\Singularity(TM)\\Binaries" "Singularity.exe" - # Clean up crap left over in c:\ when the installer runs the vc 2008 redistributable installer cd "$W_DRIVE_C" rm -f VC_RED.* eula.*.txt globdata.ini install.exe install.ini install.res.*.dll vcredist.bmp @@ -17392,8 +16952,6 @@ load_wglgears() mkdir -p "$W_PROGRAMS_X86_UNIX/misc" cp "$W_CACHE"/wglgears/wglgears.exe "$W_PROGRAMS_X86_UNIX/misc" chmod +x "$W_PROGRAMS_X86_UNIX/misc/wglgears.exe" - - w_declare_exe "$W_PROGRAMS_X86_WIN\\misc" wglgears.exe } #---------------------------------------------------------------- @@ -17455,8 +17013,6 @@ load_stalker_pripyat_bench() w_call d3dx9_31 w_call d3dx9_42 fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Call Of Pripyat Benchmark" "Benchmark.exe" } #---------------------------------------------------------------- @@ -17494,8 +17050,6 @@ load_torchlight() } WinWaitClose, Torchlight Setup " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Runic Games\\Torchlight" Torchlight.exe } #---------------------------------------------------------------- @@ -17558,13 +17112,6 @@ load_twfc() } " - if w_workaround_wine_bug 6971 "Setting mwo=force... please upgrade to wine-1.3.23" 1.3.23, - then - w_call mwo=force - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Activision\\Transformers - War for Cybertron\\Binaries" "TWFC.exe" - # Clean up crap left over in c:\ when the installer runs the vc 2008 redistributable installer cd "$W_DRIVE_C" rm -f VC_RED.* eula.*.txt globdata.ini install.exe install.ini install.res.*.dll vcredist.bmp @@ -17599,8 +17146,6 @@ load_typingofthedead_demo() ; installer crashes here? Sleep 20000 " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\SEGA\\TOD-Demo" "Tod_e_demo.exe" } #---------------------------------------------------------------- @@ -17667,15 +17212,6 @@ load_ut3() } WinWaitClose " - - if w_workaround_wine_bug 6971 "Setting mwo=force... please upgrade to wine-1.3.23" 1.3.23, - then - w_call mwo=force - w_warn "Mouse will be disabled in in-game menu. Must use keyboard to navigate. Alternately, patch wine as described in bug 6971 to use xinput2." - fi - - # FIXME: enter user's key if -q - w_declare_exe "$W_PROGRAMS_X86_WIN\\Unreal Tournament 3\\Binaries" "UT3.exe" } #---------------------------------------------------------------- @@ -17720,7 +17256,6 @@ load_wog() } winwaitclose, World of Goo Setup " - w_declare_exe "$W_PROGRAMS_X86_WIN\\WorldOfGooDemo" WorldOfGoo.exe } #---------------------------------------------------------------- @@ -17757,8 +17292,6 @@ load_zootycoon2_demo() winwaitactive, Zoo Tycoon 2 Trial, COMPLETE winclose, Zoo Tycoon 2 Trial, COMPLETE " - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Microsoft Games\\Zoo Tycoon 2 Trial Version" "zt2demoretail.exe" } #---------------------------------------------------------------- @@ -17854,7 +17387,6 @@ w_metadata bioshock2_steam games \ publisher="2k" \ year="2010" \ media="download" \ - wine_showstoppers="7065" \ installed_exe1="$W_PROGRAMS_X86_WIN/Steam/steamapps/common/bioshock2/blort.exe" load_bioshock2_steam() @@ -17927,29 +17459,6 @@ w_metadata ruse_demo_steam games \ load_ruse_demo_steam() { w_steam_install_game 33310 "R.U.S.E." - - if w_workaround_wine_bug 21939 "Installing Windows Media so game can start" - then - w_call wmp9 - fi - - if w_workaround_wine_bug 22016 "Turning off HDR to avoid washed out graphics" - then - for dir in "$W_PROGRAMS_X86_UNIX/Steam/userdata"/*/config - do - file=../33310/local/Option.ini - if test -f $file - then - sed -i "s/UseHDR = true/UseHDR = false/" $file - else - mkdir -p ../33310/local - cat > "$file" <<_EOF_ -[advanced_video] - UseHDR = false -_EOF_ - fi - done - fi } #---------------------------------------------------------------- @@ -17978,13 +17487,6 @@ w_metadata trine_steam games \ load_trine_steam() { w_steam_install_game 35700 "Trine" - - if w_workaround_wine_bug 21939 "Installing Windows Media Player so game can start" - then - w_call wmp9 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Steam\\steamapps\\common\\trine" "trine_launcher.exe" } #---------------------------------------------------------------- @@ -17999,13 +17501,6 @@ w_metadata trine_demo_steam games \ load_trine_demo_steam() { w_steam_install_game 35710 "Trine Demo" - - if w_workaround_wine_bug 21939 "Installing Windows Media Player so game can start" - then - w_call wmp9 - fi - - w_declare_exe "$W_PROGRAMS_X86_WIN\\Steam\\steamapps\\common\\trine demo" "trine_launcher.exe" } #---------------------------------------------------------------- @@ -18019,10 +17514,6 @@ w_metadata wormsreloaded_demo_steam games \ load_wormsreloaded_demo_steam() { - if w_workaround_wine_bug 26646 "Installing xact to enable sound" - then - w_call xact - fi w_steam_install_game 22690 "Worms Reloaded Demo" } @@ -18424,6 +17915,42 @@ _EOF_ #---------------------------------------------------------------- +w_metadata hidewineexports=enable settings \ + title="Enable hiding wine exports from applications (wine-staging)" +w_metadata hidewineexports=disable settings \ + title="Disable hiding wine exports from applications (wine-staging)" + +load_hidewineexports() +{ + # Wine exports some functions allowing apps to query the wine version and + # information about the host environment. Using these functions, some apps + # will intentionally terminate if they can detect that they are running in + # a wine environment. + # + # Hiding these wine exports is only available in wine-staging. + # See https://bugs.winehq.org/show_bug.cgi?id=38656 + case $arg in + enable) + local registry_value="\"Y\"" + ;; + disable) + local registry_value="-" + ;; + *) w_die "Unexpected argument, $arg";; + esac + + cat > "$W_TMP"/set-wineexports.reg <<_EOF_ +REGEDIT4 + +[HKEY_CURRENT_USER\Software\Wine] +"HideWineExports"=$registry_value + +_EOF_ + w_try_regedit "$W_TMP"/set-wineexports.reg +} + +#---------------------------------------------------------------- + w_metadata hosts settings \ title_uk="Додати порожні файли у C:\windows\system32\drivers\etc\{hosts,services}" \ title="Add empty C:\windows\system32\drivers\etc\{hosts,services} files" @@ -18563,6 +18090,9 @@ w_metadata sound=disabled settings \ w_metadata sound=oss settings \ title_uk="Поставити звуковий драйвер OSS" \ title="Set sound driver to OSS" +w_metadata sound=pulse settings \ + title_uk="Поставити звуковий драйвер PulseAudio" \ + title="Set sound driver to PulseAudio" load_sound() { @@ -19039,6 +18569,12 @@ winetricks_stats_init() case $WINETRICKS_GUI in zenity) case $LANG in + de*) + title="Einmalige Frage zur Hilfe an der Winetricks Entwicklung" + question="Möchten Sie die Winetricks Entwicklung unterstützen indem Sie Winetricks Statistiken übermitteln lassen? Sie können die Übermittlung jederzeit mit 'winetricks --optout' ausschalten" + thanks="Danke! Sie bekommen diese Frage nicht mehr gestellt. Sie können die Übermittlung jederzeit mit 'winetricks --optout' wieder ausschalten" + declined="OK, Winetricks wird *keine* Statistiken übermitteln. Sie bekommen diese Frage nicht mehr gestellt." + ;; *) title="One-time question about helping Winetricks development" question="Would you like to help winetricks development by letting winetricks report statistics? You can turn reporting off at any time with the command 'winetricks --optout'" @@ -19167,7 +18703,7 @@ execute_command() # Hard-coded verbs main) WINETRICKS_CURMENU=main ;; - help) w_open_webpage http://winetricks.org/help ;; + help) w_open_webpage https://code.google.com/archive/p/winetricks/wikis ;; list) winetricks_list_all ;; list-cached) winetricks_list_cached ;; list-download) winetricks_list_download ;; @@ -19192,6 +18728,7 @@ execute_command() winecfg) "$WINE" winecfg ;; regedit) "$WINE" regedit ;; taskmgr) "$WINE" taskmgr & ;; + uninstaller) "$WINE" uninstaller ;; shell) winetricks_shell ;; # These have to come before *=disabled to avoid looking like dlls From 4955996d0298809b5ee19a8dda3d3bb568ff7946 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Thu, 10 Mar 2016 11:28:48 -0800 Subject: [PATCH 046/181] Add Playstation support for Mednafen --- lutris/runners/mednafen.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lutris/runners/mednafen.py b/lutris/runners/mednafen.py index a6e2573db..1b105d8e9 100644 --- a/lutris/runners/mednafen.py +++ b/lutris/runners/mednafen.py @@ -14,10 +14,13 @@ class mednafen(Runner): "GameBoy Advance, NES, PC Engine (TurboGrafx 16), PC-FX, " "SuperGrafx, NeoGeo Pocket, NeoGeo Pocket Color, WonderSwan") package = "mednafen" - machine_choices = (("NES", "nes"), - ("PC Engine", "pce"), - ('Game Boy', 'gb'), - ('Game Boy Advance', 'gba')) + machine_choices = ( + ("NES", "nes"), + ("PC Engine", "pce"), + ('Game Boy', 'gb'), + ('Game Boy Advance', 'gba'), + ('Playstation', 'psx') + ) game_options = [ { "option": "main_file", From 2a4f6a460102ef90194ddfb0c56e868386528f77 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Thu, 10 Mar 2016 15:26:16 -0800 Subject: [PATCH 047/181] Do not monitor wdfmgr.exe --- lutris/thread.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/thread.py b/lutris/thread.py index 3dcd664ac..5ea950475 100644 --- a/lutris/thread.py +++ b/lutris/thread.py @@ -166,7 +166,7 @@ class LutrisThread(threading.Thread): 'bash', 'control', 'lutris', 'PnkBstrA.exe', 'python', 'regedit', 'sh', 'steam', 'Steam.exe', 'steamer', 'steamerrorrepor', 'SteamService.ex', 'steamwebhelper', 'steamwebhelper.', 'tee', - 'tr', 'winecfg.exe', 'zenity', + 'tr', 'winecfg.exe', 'zenity', 'wdfmgr.exe' ) if child.name in excluded: continue From 20647c6881483594fcd4a657109e07ff956eed33 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 11 Mar 2016 08:28:00 -0800 Subject: [PATCH 048/181] Add PULSE_LATENCY_MSEC system option --- lutris/game.py | 4 ++++ lutris/sysoptions.py | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/lutris/game.py b/lutris/game.py index d4640fb2d..9ddefc637 100644 --- a/lutris/game.py +++ b/lutris/game.py @@ -217,6 +217,10 @@ class Game(object): time.sleep(3) env['DISPLAY'] = ':2' + pulse_latency = system_config.get('pulse_latency') + if pulse_latency: + env['PULSE_LATENCY_MSEC'] = '60' + prefix_command = system_config.get("prefix_command") or '' if prefix_command.strip(): launch_arguments.insert(0, prefix_command) diff --git a/lutris/sysoptions.py b/lutris/sysoptions.py index 01095e8db..51993e9b6 100644 --- a/lutris/sysoptions.py +++ b/lutris/sysoptions.py @@ -133,6 +133,17 @@ system_options = [ 'condition': system.find_executable('pulseaudio'), 'help': "Restart PulseAudio before launching the game." }, + { + 'option': 'pulse_latency', + 'type': 'bool', + 'label': 'Reduce PulseAudio latency', + 'default': False, + 'advanced': True, + 'condition': system.find_executable('pulseaudio'), + 'help': ('Set the environment variable PULSE_LATENCY_MSEC=60 to improve ' + 'audio quality on some games') + + }, { 'option': 'killswitch', 'type': 'string', From 8efcdff73e1163bbd3368eb9d75ab0686aafc175 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 11 Mar 2016 08:55:05 -0800 Subject: [PATCH 049/181] Add missing quotes in test case --- tests/test_installer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_installer.py b/tests/test_installer.py index 253e08a4b..9d4440aac 100644 --- a/tests/test_installer.py +++ b/tests/test_installer.py @@ -48,4 +48,4 @@ class TestScriptInterpreter(TestCase): {'_substitute': 'foo'} ) self.assertEqual(ex.exception.message, - "The command substitute does not exists") + "The command \"substitute\" does not exist.") From 2a7b6a5320c0ad0cbc3b1e7bc268b44b1663c3e2 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 22 Mar 2016 09:43:19 -0700 Subject: [PATCH 050/181] Update supported runner list in README --- README.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index c033559ca..3c347ebb7 100644 --- a/README.rst +++ b/README.rst @@ -39,6 +39,8 @@ We currently support the following runners: * Mupen64 Plus * Dolphin * PCSXR +* PPSSPP +* PCSX2 * Osmose * GenS * Reicast @@ -46,10 +48,6 @@ We currently support the following runners: * Jzintv * O2em -Runners that will be added in future versions of Lutris: - -* PPSSPP -* PCSX2 Installer scripts ================= From 74f718d194a48af104a2eabca187ca2d62478d6c Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 25 Mar 2016 14:55:58 -0700 Subject: [PATCH 051/181] Add Floppy drive 1 & 2 to MESS options --- lutris/runners/mess.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lutris/runners/mess.py b/lutris/runners/mess.py index d42a31ff0..bb000d910 100644 --- a/lutris/runners/mess.py +++ b/lutris/runners/mess.py @@ -35,6 +35,8 @@ class mess(Runner): 'label': "Storage type", 'choices': [ ("Floppy disk", 'flop'), + ("Floppy drive 1", 'flop1'), + ("Floppy drive 2", 'flop2'), ("Cassette (tape)", 'cass'), ("Cartridge", 'cart'), ("Snapshot", 'snapshot'), From c7d52f62b52a58a6e60713ff45ff2b3242d66e52 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 2 Apr 2016 13:27:08 -0700 Subject: [PATCH 052/181] Return absolute path for system wine versions --- lutris/runners/wine.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 0e4ef672a..d50df4130 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -558,8 +558,9 @@ class wine(Runner): return if version in WINE_PATHS.keys(): - if system.find_executable(WINE_PATHS[version]): - return WINE_PATHS[version] + abs_path = system.find_executable(WINE_PATHS[version]) + if abs_path: + return abs_path # Fall back on bundled Wine version = get_default_version() elif version == 'custom': From b7127db915fc9caf8288e3c2d0a064ee518d9e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frederik=20=E2=80=9CFreso=E2=80=9D=20S=2E=20Olesen?= Date: Sun, 10 Apr 2016 17:51:01 +0200 Subject: [PATCH 053/181] Make the "Warning:" in "Installation" section bold. --- INSTALL.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/INSTALL.rst b/INSTALL.rst index 5203739e2..6980a58fc 100644 --- a/INSTALL.rst +++ b/INSTALL.rst @@ -21,9 +21,10 @@ the following command as root:: $ python setup.py install -Warning: there is no way to cleanly uninstall programs installed with setup.py -other than manuall deleting the created files. Prefer installing Lutris -through distribution packages or run it directly from the source directory:: +**Warning:** there is no way to cleanly uninstall programs installed with +setup.py other than manuall deleting the created files. Prefer installing +Lutris through distribution packages or run it directly from the source +directory:: cd /path/to/lutris/source ./bin/lutris From 500591dc134fde41daa3bdcb1e1c9f68bd947b8b Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Fri, 4 Mar 2016 16:26:28 +0100 Subject: [PATCH 054/181] Escape white space in wine.set_regedit_file() file path --- lutris/runners/wine.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index d50df4130..b8969e56b 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -50,7 +50,7 @@ def set_regedit(path, key, value='', type='REG_SZ', wine_path=None, def set_regedit_file(filename, wine_path=None, prefix=None, arch='win32'): """Apply a regedit file to the Windows registry.""" - wineexec('regedit', args="/S " + filename, wine_path=wine_path, prefix=prefix, + wineexec('regedit', args="/S '%s'" % (filename), wine_path=wine_path, prefix=prefix, arch=arch, blocking=True) @@ -117,7 +117,7 @@ def wineexec(executable, args="", wine_path=None, prefix=None, arch=None, command = [wine_path] if executable: command.append(executable) - command += args.split() + command += shlex.split(args) if blocking: return system.execute(command, env=env, cwd=working_dir) else: From 5ca9ca560a0fc627543967974c1867e42d0b32d4 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 16 Apr 2016 16:29:08 -0700 Subject: [PATCH 055/181] Disable wine desktop if no setting is provided --- lutris/runners/wine.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index b8969e56b..74ec3bbe9 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -598,9 +598,24 @@ class wine(Runner): def run_joycpl(self, *args): joycpl(prefix=self.prefix_path, wine_path=self.get_executable()) + def set_wine_desktop(self, enable_desktop=False): + path = self.reg_keys['Desktop'] + + if enable_desktop: + set_regedit(path, 'Desktop', 'WineDesktop', + wine_path=self.get_executable(), + prefix=self.prefix_path, + arch=self.wine_arch) + else: + delete_registry_key(path, + wine_path=self.get_executable(), + prefix=self.prefix_path, + arch=self.wine_arch) + def set_regedit_keys(self): """Reset regedit keys according to config.""" prefix = self.prefix_path + enable_wine_desktop = False for key, path in self.reg_keys.iteritems(): value = self.runner_config.get(key) or 'auto' if not value or value == 'auto': @@ -608,10 +623,12 @@ class wine(Runner): prefix=prefix, arch=self.wine_arch) elif key in self.runner_config: if key == 'Desktop' and value is True: - value = 'WineDesktop' - set_regedit(path, key, value, - wine_path=self.get_executable(), prefix=prefix, - arch=self.wine_arch) + enable_wine_desktop = True + else: + set_regedit(path, key, value, + wine_path=self.get_executable(), prefix=prefix, + arch=self.wine_arch) + self.set_wine_desktop(enable_wine_desktop) overrides = self.runner_config.get('overrides') or {} overrides_path = "%s\DllOverrides" % self.reg_prefix for dll, value in overrides.iteritems(): From d777ab9e26fb3a154c64ed5996ca519c4eee9e32 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Thu, 21 Apr 2016 19:09:35 +0200 Subject: [PATCH 056/181] Fixes lutris/lutris#263 Uses subprocess.check_call() to call xdg_open and fallback to Gtk.open_uri() if xdg-open returns an error. --- lutris/gui/lutriswindow.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 7a1c1c702..a365f8264 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -2,6 +2,7 @@ # pylint: disable=E0611 import os import time +import subprocess from gi.repository import Gtk, Gdk, GLib @@ -386,7 +387,10 @@ class LutrisWindow(object): connection_label.set_text(connection_status) def on_register_account(self, *args): - Gtk.show_uri(None, "http://lutris.net/user/register", Gdk.CURRENT_TIME) + try: + subprocess.check_call(["xdg-open", "https://lutris.net/user/register"]) + except CalledProcessError: + Gtk.show_uri(None, "https://lutris.net/user/register", Gdk.CURRENT_TIME) def on_synchronize_manually(self, *args): """Callback when Synchronize Library is activated.""" From 62c0da20f703d6f9ec49014a24472f77e4606be9 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Fri, 22 Apr 2016 20:24:10 +0200 Subject: [PATCH 057/181] Set GTK to use dark theme by default --- lutris/gui/lutriswindow.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 7a1c1c702..7a18b820f 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -70,6 +70,10 @@ class LutrisWindow(object): self.sidebar_visible = \ settings.read_setting('sidebar_visible') in ['true', None] + # Set GTK to prefer dark theme + gtksettings = Gtk.Settings.get_default() + gtksettings.set_property("gtk-application-prefer-dark-theme", True) + # Load view logger.debug("Loading view") self.game_store = GameStore([], self.icon_type, filter_installed) From 58c154966c5937839f4abc415e71eef67298e7b1 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 22 Apr 2016 12:55:22 -0700 Subject: [PATCH 058/181] fix reference to CalledProcessError --- lutris/gui/lutriswindow.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 77a6f01cd..fa927a7cb 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -391,10 +391,11 @@ class LutrisWindow(object): connection_label.set_text(connection_status) def on_register_account(self, *args): + register_url = "https://lutris.net/user/register" try: - subprocess.check_call(["xdg-open", "https://lutris.net/user/register"]) - except CalledProcessError: - Gtk.show_uri(None, "https://lutris.net/user/register", Gdk.CURRENT_TIME) + subprocess.check_call(["xdg-open", register_url]) + except subprocess.CalledProcessError: + Gtk.show_uri(None, register_url, Gdk.CURRENT_TIME) def on_synchronize_manually(self, *args): """Callback when Synchronize Library is activated.""" From 6160ba7a5026ba5774b667da1ff64935d53291bd Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Fri, 22 Apr 2016 22:04:58 +0200 Subject: [PATCH 059/181] Redesign of the Connect dialog Made the Connect dialog more compliant with the GTK/Gnome design guidelines. - Titled the window properly - Added suggested-action CSS style to the Connect button - Made the window modal - Aligned the labels and input fields --- share/lutris/ui/dialog-lutris-login.ui | 180 +++++++++++-------------- 1 file changed, 75 insertions(+), 105 deletions(-) diff --git a/share/lutris/ui/dialog-lutris-login.ui b/share/lutris/ui/dialog-lutris-login.ui index cff715652..824b33aa5 100644 --- a/share/lutris/ui/dialog-lutris-login.ui +++ b/share/lutris/ui/dialog-lutris-login.ui @@ -1,32 +1,26 @@ - + - - True - False - network-wired - True - - - True - False - dialog-cancel - True - False 5 + Connect to lutris.net + False + True + center-on-parent + True dialog False vertical - 2 + 15 False - end + True + center Forgot password? @@ -34,6 +28,7 @@ True False True + center none http://lutris.net/user/password/reset/ @@ -49,11 +44,10 @@ True True True - image2 True - False + True True 1 @@ -66,11 +60,13 @@ True True True - image1 True + - False + True True 2 @@ -84,106 +80,80 @@ - + True False - 0 - none + start + 6 + 6 - + True False - 15 - 15 - 15 - 15 - - - True - False - 14 - True - - - True - False - 0 - Username - - - 0 - 0 - 1 - 1 - - - - - True - False - 0 - Password - - - 0 - 1 - 1 - 1 - - - - - True - True - True - True - 30 - - 32 - none - - - - 1 - 0 - 1 - 1 - - - - - True - True - True - 1024 - False - - - - - 1 - 1 - 1 - 1 - - - - + end + 83 + Password + right + + 0 + 1 + - - + + True False - <b>Login to lutris.net</b> - True + end + 83 + Username + right + + 0 + 0 + + + + + True + True + start + True + 1024 + False + + 36 + password + + + + 1 + 1 + + + + + True + True + start + True + 30 + + 36 + none + + + + 1 + 0 + - True + False True - 1 + 0 From 8911a0f8dce71b745e597fa5f601ba3f679e43d8 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 23 Apr 2016 00:10:39 +0200 Subject: [PATCH 060/181] Fixes lutris/lutris#269 Hides the "Connecting to your Lutris.net account to sync your library" link when the user connects. --- lutris/gui/lutriswindow.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index fa927a7cb..5e25396f2 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -83,6 +83,7 @@ class LutrisWindow(object): logger.debug("Connecting signals") self.main_box = self.builder.get_object('main_box') self.splash_box = self.builder.get_object('splash_box') + self.connect_link = self.builder.get_object('connect_link') # View menu installed_games_only_menuitem =\ self.builder.get_object('filter_installed') @@ -361,6 +362,7 @@ class LutrisWindow(object): """Callback when a user connects to his account.""" login_dialog = dialogs.ClientLoginDialog(self.window) login_dialog.connect('connected', self.on_connect_success) + self.connect_link.hide() def on_connect_success(self, dialog, credentials): if isinstance(credentials, str): @@ -373,6 +375,7 @@ class LutrisWindow(object): def on_disconnect(self, *args): api.disconnect() self.toggle_connection(False) + self.connect_link.show() def toggle_connection(self, is_connected, username=None): disconnect_menuitem = self.builder.get_object('disconnect_menuitem') From 7864d8b3749374bdb4ee70f5c63dde84a18c5997 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 23 Apr 2016 00:47:46 +0200 Subject: [PATCH 061/181] Fixes lutris/lutris#272 Properly hides and show the sidebar when toggled on and off. --- lutris/gui/lutriswindow.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index a365f8264..5ec30d9a9 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -139,8 +139,8 @@ class LutrisWindow(object): self.view.contextual_menu = self.menu # Sidebar - sidebar_paned = self.builder.get_object('sidebar_paned') - sidebar_paned.set_position(150) + self.sidebar_paned = self.builder.get_object('sidebar_paned') + self.sidebar_paned.set_position(150) self.sidebar_treeview = SidebarTreeView() self.sidebar_treeview.connect('cursor-changed', self.on_sidebar_changed) self.sidebar_viewport = self.builder.get_object('sidebar_viewport') @@ -155,6 +155,8 @@ class LutrisWindow(object): self.builder.connect_signals(self) self.connect_signals() + self.statusbar = self.builder.get_object("statusbar") + # XXX Hide PGA config menu item until it actually gets implemented pga_menuitem = self.builder.get_object('pga_menuitem') pga_menuitem.hide() @@ -654,10 +656,18 @@ class LutrisWindow(object): def toggle_sidebar(self, _widget=None): if self.sidebar_visible: - self.sidebar_viewport.hide() + self.sidebar_paned.remove(self.games_scrollwindow) + self.main_box.remove(self.sidebar_paned) + self.main_box.remove(self.statusbar) + self.main_box.pack_start(self.games_scrollwindow, True, True, 0) + self.main_box.pack_start(self.statusbar, False, False, 0) settings.write_setting('sidebar_visible', 'false') else: - self.sidebar_viewport.show() + self.main_box.remove(self.games_scrollwindow) + self.sidebar_paned.add2(self.games_scrollwindow) + self.main_box.remove(self.statusbar) + self.main_box.pack_start(self.sidebar_paned, True, True, 0) + self.main_box.pack_start(self.statusbar, False, False, 0) settings.write_setting('sidebar_visible', 'true') self.sidebar_visible = not self.sidebar_visible From 736d43eb9a7d48fc9300eda2d53b553a9bf19356 Mon Sep 17 00:00:00 2001 From: MrTimscampi Date: Sat, 23 Apr 2016 01:42:17 +0200 Subject: [PATCH 062/181] Fixes lutris/lutris#262 Removes the fixed width/height of the window in the ui file and applies the size from the settings to the window at launch. --- lutris/gui/lutriswindow.py | 2 ++ share/lutris/ui/LutrisWindow.ui | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 7a18b820f..ac8373643 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -63,6 +63,8 @@ class LutrisWindow(object): width = int(settings.read_setting('width') or 800) height = int(settings.read_setting('height') or 600) self.window_size = (width, height) + window = self.builder.get_object('window') + window.resize(width, height) view_type = self.get_view_type() self.icon_type = self.get_icon_type(view_type) filter_installed = \ diff --git a/share/lutris/ui/LutrisWindow.ui b/share/lutris/ui/LutrisWindow.ui index 76f4175bb..bc68c4f43 100644 --- a/share/lutris/ui/LutrisWindow.ui +++ b/share/lutris/ui/LutrisWindow.ui @@ -1,5 +1,5 @@ - + @@ -79,10 +79,9 @@ view-list-symbolic - 640 - 300 False Lutris + center ../media/lutris.svg lutris From cb91950e46c54fde1cf49f948023ed338bd4f5e4 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 23 Apr 2016 12:39:31 -0700 Subject: [PATCH 063/181] Reduce amount of logs when steam games are being installed --- lutris/installer/interpreter.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index 64107ab28..b52dcfd11 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -58,6 +58,7 @@ class ScriptInterpreter(CommandsMixin): self.steam_data = {} self.script = script self.runners_to_install = [] + self.prev_states = [] # Previous states for the Steam installer if not self.script: return if not self.is_valid(): @@ -631,13 +632,16 @@ class ScriptInterpreter(CommandsMixin): steam_runner = self._get_steam_runner() states = get_app_state_log(steam_runner.steam_data_dir, appid, self.install_start_time) - logger.debug(states) + if states != self.prev_states: + logger.debug("Steam installation status:") + logger.debug(states) + self.prev_states = states + if states and states.pop().startswith('Fully Installed'): self._on_steam_game_installed() logger.debug('Steam game has finished installing') return False else: - logger.debug('Steam game still installing') return True def _on_steam_game_installed(self, *args): From 36b0f006e158446ee8c0594ec6db98399ec939a6 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 23 Apr 2016 17:27:43 -0700 Subject: [PATCH 064/181] Do not alter steam states --- lutris/installer/interpreter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index b52dcfd11..04bfca3f6 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -637,9 +637,9 @@ class ScriptInterpreter(CommandsMixin): logger.debug(states) self.prev_states = states - if states and states.pop().startswith('Fully Installed'): - self._on_steam_game_installed() + if states and states[-1].startswith('Fully Installed'): logger.debug('Steam game has finished installing') + self._on_steam_game_installed() return False else: return True From 448d7bee30d22f9f19a129bd3aadc09b0b80c32f Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Fri, 15 Apr 2016 13:32:10 +0200 Subject: [PATCH 065/181] chmodx only if necessary in "execute" directive --- docs/installers.rst | 3 ++- lutris/installer/commands.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/installers.rst b/docs/installers.rst index 97a88d5ab..7b4444493 100644 --- a/docs/installers.rst +++ b/docs/installers.rst @@ -206,7 +206,8 @@ Execute files with the ``execute`` directive. Use the ``file`` parameter to reference a ``file id`` or a path, ``args`` to add command arguments, ``terminal`` (set to "true") to execute in a new terminal window. The command is executed within the Lutris Runtime (resolving most shared -library dependencies). +library dependencies). The file is made executable if necessary, no need to run +chmodx before. Example: diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index 37fe60815..4092f48ca 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -71,7 +71,8 @@ class CommandsMixin(object): if not os.path.exists(exec_path): raise ScriptingError("Unable to find required executable", exec_path) - self.chmodx(exec_path) + if not os.access(exec_path, os.X_OK): + self.chmodx(exec_path) if terminal: terminal = system.get_default_terminal() From 747377e5d9400e6b59cfb59ef57990300c13f9ef Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Fri, 15 Apr 2016 13:51:44 +0200 Subject: [PATCH 066/181] Add working_dir param to "execute" directive --- docs/installers.rst | 5 +++-- lutris/installer/commands.py | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/installers.rst b/docs/installers.rst index 7b4444493..628e24279 100644 --- a/docs/installers.rst +++ b/docs/installers.rst @@ -193,7 +193,7 @@ Example: Making a file executable ------------------------ -Marking the file as executable is done with the ``chmodx`` command. It is often +Marking the file as executable is done with the ``chmodx`` directive. It is often needed for games that ship in a zip file, which does not retain file permissions. @@ -204,7 +204,8 @@ Executing a file Execute files with the ``execute`` directive. Use the ``file`` parameter to reference a ``file id`` or a path, ``args`` to add command arguments, -``terminal`` (set to "true") to execute in a new terminal window. +``terminal`` (set to "true") to execute in a new terminal window, ``working_dir`` +to set the directory to execute the command in (defaults to the install path). The command is executed within the Lutris Runtime (resolving most shared library dependencies). The file is made executable if necessary, no need to run chmodx before. diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index 4092f48ca..2f9eb0e72 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -53,6 +53,7 @@ class CommandsMixin(object): """Run an executable file.""" args = [] terminal = None + working_dir = None if isinstance(data, dict): self._check_required_params('file', data, 'execute') file_ref = data['file'] @@ -60,6 +61,7 @@ class CommandsMixin(object): for arg in shlex.split(args_string): args.append(self._substitute(arg)) terminal = data.get('terminal') + working_dir = data.get('working_dir') else: file_ref = data @@ -77,6 +79,9 @@ class CommandsMixin(object): if terminal: terminal = system.get_default_terminal() + if not working_dir or not os.path.exists(working_dir): + working_dir = self.target_path + command = [exec_path] + args logger.debug("Executing %s" % command) thread = LutrisThread(command, env=runtime.get_env(), term=terminal, From 0c4521ac030fb60a2506d1748c4c7538b143dc1a Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Mon, 25 Apr 2016 12:15:32 +0200 Subject: [PATCH 067/181] Look for Steam in ~/.local/.steam/steam + case insensitive search --- lutris/runners/steam.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lutris/runners/steam.py b/lutris/runners/steam.py index 259c7a0e0..da515b304 100644 --- a/lutris/runners/steam.py +++ b/lutris/runners/steam.py @@ -104,15 +104,15 @@ class steam(Runner): def steam_data_dir(self): """Return dir where Steam files lie.""" candidates = ( - "~/.local/share/Steam/", - "~/.local/share/steam/", - "~/.steam/", - "~/.Steam/", + "~/.local/share/steam/SteamApps", + "~/.steam/steam/SteamApps", + "~/.steam/SteamApps", ) for candidate in candidates: path = os.path.expanduser(candidate) - if os.path.isdir(path): - return path + path = system.fix_path_case(path) + if path: + return path.rstrip('sSteamAp') def get_executable(self): return system.find_executable('steam') @@ -153,9 +153,9 @@ class steam(Runner): def install(self): raise NonInstallableRunnerError( - "Steam for Linux installation is not handled by Lutris.\n" \ - "Please go to " \ - "http://steampowered.com" \ + "Steam for Linux installation is not handled by Lutris.\n" + "Please go to " + "http://steampowered.com" " or install Steam with the package provided by your distribution." ) From 497c9324652d1d04d373da8f5a4b08401df40549 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Mon, 25 Apr 2016 19:22:36 +0200 Subject: [PATCH 068/181] Upadte AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index a52a94f3e..efbe24e23 100644 --- a/AUTHORS +++ b/AUTHORS @@ -10,3 +10,4 @@ Contributors: Ivan mikeyd Travis Nickles + Patrick Griffis From 48e564640be54706fb8a545b4a90e4f0e8c2dc25 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Fri, 29 Apr 2016 18:17:23 +0200 Subject: [PATCH 069/181] Show all installed runners in sidebar --- lutris/gui/sidebar.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lutris/gui/sidebar.py b/lutris/gui/sidebar.py index 1c3c571c9..d36ee7f1d 100644 --- a/lutris/gui/sidebar.py +++ b/lutris/gui/sidebar.py @@ -47,7 +47,8 @@ class SidebarTreeView(Gtk.TreeView): self.connect('button-press-event', self.popup_contextual_menu) self.runners = sorted(lutris.runners.__all__) - self.used_runners = pga.get_used_runners() + self.installed_runners = [runner.name for runner in + lutris.runners.get_installed()] self.load_all_runners() self.update() self.expand_all() @@ -73,10 +74,10 @@ class SidebarTreeView(Gtk.TreeView): def filter_rule(self, model, iter, data): if model[iter][0] == 'runners': return True - return model[iter][0] in self.used_runners + return model[iter][0] in self.installed_runners def update(self): - self.used_runners = pga.get_used_runners() + self.used_runners = lutris.runners.get_installed() self.model_filter.refilter() self.expand_all() From 3cdb9c45f78514dcb7be7bfe42512a2f36598757 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Fri, 29 Apr 2016 17:35:15 +0200 Subject: [PATCH 070/181] Workaround for 64bit Wine failing to create win32 prefix on existing dir --- lutris/runners/wine.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 74ec3bbe9..0c8cbb1c4 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -1,5 +1,6 @@ import os import shlex +import shutil import subprocess from textwrap import dedent @@ -62,6 +63,12 @@ def delete_registry_key(key, wine_path=None, prefix=None, arch='win32'): def create_prefix(prefix, wine_dir=None, arch='win32'): """Create a new Wine prefix.""" logger.debug("Creating a %s prefix in %s", arch, prefix) + + # Avoid issue of 64bit Wine refusing to create win32 prefix + # over an existing empty folder. + if os.path.isdir(prefix) and not os.listdir(prefix): + os.rmdir(prefix) + if not wine_dir: wine_dir = os.path.dirname(wine().get_executable()) wineboot_path = os.path.join(wine_dir, 'wineboot') From ed6955c8185fe407b6eb0f657bb8f6289f2789f0 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Fri, 29 Apr 2016 16:51:47 +0200 Subject: [PATCH 071/181] Installers: Point $CACHE to CACHE_DIR/installer/ --- lutris/installer/interpreter.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index 04bfca3f6..040b1a592 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -90,7 +90,7 @@ class ScriptInterpreter(CommandsMixin): return os.path.expanduser(os.path.join(games_dir, self.game_slug)) @property - def download_cache_path(self): + def cache_path(self): return os.path.join(settings.CACHE_DIR, "installer/%s" % self.game_slug) @@ -149,8 +149,8 @@ class ScriptInterpreter(CommandsMixin): def iter_game_files(self): if self.files: # Create cache dir if needed - if not os.path.exists(self.download_cache_path): - os.mkdir(self.download_cache_path) + if not os.path.exists(self.cache_path): + os.mkdir(self.cache_path) if self.target_path and self.should_create_target: os.makedirs(self.target_path) @@ -204,7 +204,7 @@ class ScriptInterpreter(CommandsMixin): file_uri = pga_uri # Setup destination path - dest_file = os.path.join(self.download_cache_path, filename) + dest_file = os.path.join(self.cache_path, filename) if file_uri.startswith("N/A"): # Ask the user where the file is located @@ -345,6 +345,9 @@ class ScriptInterpreter(CommandsMixin): if self.target_path and os.path.exists(self.target_path): os.chdir(self.target_path) + if not os.path.exists(self.cache_path): + os.mkdir(self.cache_path) + # Add steam installation to commands if it's a Steam game if self.runner in ('steam', 'winesteam'): try: @@ -533,8 +536,8 @@ class ScriptInterpreter(CommandsMixin): def cleanup(self): os.chdir(os.path.expanduser('~')) - if os.path.exists(self.download_cache_path): - shutil.rmtree(self.download_cache_path) + if os.path.exists(self.cache_path): + shutil.rmtree(self.cache_path) # -------------- # Revert install @@ -559,7 +562,7 @@ class ScriptInterpreter(CommandsMixin): """Replace path aliases with real paths.""" replacements = { "GAMEDIR": self.target_path, - "CACHE": settings.CACHE_DIR, + "CACHE": self.cache_path, "HOME": os.path.expanduser("~"), "DISC": self.game_disc, "USER": os.getenv('USER'), From 0be2e60c2ebcf931703eaca34a54cefba5ebbc15 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Thu, 12 May 2016 16:24:34 +0200 Subject: [PATCH 072/181] Update AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index efbe24e23..fd72f9d17 100644 --- a/AUTHORS +++ b/AUTHORS @@ -11,3 +11,4 @@ Contributors: mikeyd Travis Nickles Patrick Griffis + Julien Machiels From e1e6ddf0a67a25d631fa0a17e6b82d15e0284532 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 20 May 2016 08:16:44 -0700 Subject: [PATCH 073/181] Add no-cef-sandbox to winesteam arguments --- lutris/runners/winesteam.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index d1354075c..41eb0e31d 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -153,7 +153,15 @@ class winesteam(wine.wine): @property def launch_args(self): - return [self.get_executable(), self.get_steam_path(), '-no-dwrite'] + args = [self.get_executable(), self.get_steam_path()] + + # Fix invisible text in Steam + args.append('-no-dwrite') + + # Try to fix Steam's browser. Never worked but it's supposed to... + args.append('-no-cef-sandox') + + return args def get_open_command(self, registry): """Return Steam's Open command, useful for locating steam when it has From dffe1e410b76a016f70059731930acb00e793062 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Fri, 29 Apr 2016 18:17:23 +0200 Subject: [PATCH 074/181] Show all installed runners in sidebar --- lutris/gui/sidebar.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lutris/gui/sidebar.py b/lutris/gui/sidebar.py index 1c3c571c9..d36ee7f1d 100644 --- a/lutris/gui/sidebar.py +++ b/lutris/gui/sidebar.py @@ -47,7 +47,8 @@ class SidebarTreeView(Gtk.TreeView): self.connect('button-press-event', self.popup_contextual_menu) self.runners = sorted(lutris.runners.__all__) - self.used_runners = pga.get_used_runners() + self.installed_runners = [runner.name for runner in + lutris.runners.get_installed()] self.load_all_runners() self.update() self.expand_all() @@ -73,10 +74,10 @@ class SidebarTreeView(Gtk.TreeView): def filter_rule(self, model, iter, data): if model[iter][0] == 'runners': return True - return model[iter][0] in self.used_runners + return model[iter][0] in self.installed_runners def update(self): - self.used_runners = pga.get_used_runners() + self.used_runners = lutris.runners.get_installed() self.model_filter.refilter() self.expand_all() From 9f7a2ce65c3ba3a362ff6665c38da74babc78672 Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Fri, 29 Apr 2016 17:35:15 +0200 Subject: [PATCH 075/181] Workaround for 64bit Wine failing to create win32 prefix on existing dir --- lutris/runners/wine.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 74ec3bbe9..0c8cbb1c4 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -1,5 +1,6 @@ import os import shlex +import shutil import subprocess from textwrap import dedent @@ -62,6 +63,12 @@ def delete_registry_key(key, wine_path=None, prefix=None, arch='win32'): def create_prefix(prefix, wine_dir=None, arch='win32'): """Create a new Wine prefix.""" logger.debug("Creating a %s prefix in %s", arch, prefix) + + # Avoid issue of 64bit Wine refusing to create win32 prefix + # over an existing empty folder. + if os.path.isdir(prefix) and not os.listdir(prefix): + os.rmdir(prefix) + if not wine_dir: wine_dir = os.path.dirname(wine().get_executable()) wineboot_path = os.path.join(wine_dir, 'wineboot') From 8cfc3ccf374e5149e89e2569a288d17c764c705b Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Fri, 29 Apr 2016 16:51:47 +0200 Subject: [PATCH 076/181] Installers: Point $CACHE to CACHE_DIR/installer/ --- lutris/installer/interpreter.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lutris/installer/interpreter.py b/lutris/installer/interpreter.py index 04bfca3f6..040b1a592 100644 --- a/lutris/installer/interpreter.py +++ b/lutris/installer/interpreter.py @@ -90,7 +90,7 @@ class ScriptInterpreter(CommandsMixin): return os.path.expanduser(os.path.join(games_dir, self.game_slug)) @property - def download_cache_path(self): + def cache_path(self): return os.path.join(settings.CACHE_DIR, "installer/%s" % self.game_slug) @@ -149,8 +149,8 @@ class ScriptInterpreter(CommandsMixin): def iter_game_files(self): if self.files: # Create cache dir if needed - if not os.path.exists(self.download_cache_path): - os.mkdir(self.download_cache_path) + if not os.path.exists(self.cache_path): + os.mkdir(self.cache_path) if self.target_path and self.should_create_target: os.makedirs(self.target_path) @@ -204,7 +204,7 @@ class ScriptInterpreter(CommandsMixin): file_uri = pga_uri # Setup destination path - dest_file = os.path.join(self.download_cache_path, filename) + dest_file = os.path.join(self.cache_path, filename) if file_uri.startswith("N/A"): # Ask the user where the file is located @@ -345,6 +345,9 @@ class ScriptInterpreter(CommandsMixin): if self.target_path and os.path.exists(self.target_path): os.chdir(self.target_path) + if not os.path.exists(self.cache_path): + os.mkdir(self.cache_path) + # Add steam installation to commands if it's a Steam game if self.runner in ('steam', 'winesteam'): try: @@ -533,8 +536,8 @@ class ScriptInterpreter(CommandsMixin): def cleanup(self): os.chdir(os.path.expanduser('~')) - if os.path.exists(self.download_cache_path): - shutil.rmtree(self.download_cache_path) + if os.path.exists(self.cache_path): + shutil.rmtree(self.cache_path) # -------------- # Revert install @@ -559,7 +562,7 @@ class ScriptInterpreter(CommandsMixin): """Replace path aliases with real paths.""" replacements = { "GAMEDIR": self.target_path, - "CACHE": settings.CACHE_DIR, + "CACHE": self.cache_path, "HOME": os.path.expanduser("~"), "DISC": self.game_disc, "USER": os.getenv('USER'), From 3b366116aa4a1228ae5dbb3f615d77df8766c67a Mon Sep 17 00:00:00 2001 From: Xodetaetl Date: Thu, 12 May 2016 16:24:34 +0200 Subject: [PATCH 077/181] Update AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index efbe24e23..fd72f9d17 100644 --- a/AUTHORS +++ b/AUTHORS @@ -11,3 +11,4 @@ Contributors: mikeyd Travis Nickles Patrick Griffis + Julien Machiels From 7632d0182d43cda026a382b2cce00eae76e2de43 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 20 May 2016 08:36:53 -0700 Subject: [PATCH 078/181] Use system.path_exists in Atari800 runner --- lutris/runners/atari800.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lutris/runners/atari800.py b/lutris/runners/atari800.py index 363539094..89486a0cf 100644 --- a/lutris/runners/atari800.py +++ b/lutris/runners/atari800.py @@ -88,7 +88,7 @@ class atari800(Runner): bios_archive = os.path.join(config_path, 'atari800-bioses.zip') dlg = DownloadDialog(self.bios_url, bios_archive) dlg.run() - if not os.path.exists(bios_archive): + if not system.path_exists(bios_archive): ErrorDialog("Could not download Atari800 BIOS archive") return extract.extract_archive(bios_archive, config_path) @@ -134,7 +134,7 @@ class atari800(Runner): arguments.append("-%s" % self.runner_config["machine"]) bios_path = self.runner_config.get("bios_path") - if not os.path.exists(bios_path): + if not system.path_exists(bios_path): return {'error': 'NO_BIOS'} good_bios = self.find_good_bioses(bios_path) for bios in good_bios.keys(): @@ -142,7 +142,7 @@ class atari800(Runner): arguments.append(os.path.join(bios_path, good_bios[bios])) rom = self.game_config.get('main_file') or '' - if not os.path.exists(rom): + if not system.path_exists(rom): return {'error': 'FILE_NOT_FOUND', 'file': rom} arguments.append(rom) From ebbf72fc5dbce2cb7943f895a4ef0467121612a6 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 21 May 2016 13:41:26 -0700 Subject: [PATCH 079/181] Fully silence stderr output (Fixes #280) --- lutris/util/system.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lutris/util/system.py b/lutris/util/system.py index b072eac46..aa7098b6b 100644 --- a/lutris/util/system.py +++ b/lutris/util/system.py @@ -24,18 +24,23 @@ def execute(command, env=None, cwd=None, log_errors=False): # Piping stderr can cause slowness in the programs, use carefully # (especially when using regedit with wine) if log_errors: - stderr_config = subprocess.PIPE + stderr_handler = subprocess.PIPE + stderr_needs_closing = False else: - stderr_config = None + stderr_handler = open(os.devnull, 'w') + stderr_needs_closing = True try: stdout, stderr = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE, - stderr=stderr_config, + stderr=stderr_handler, env=existing_env, cwd=cwd).communicate() except OSError as ex: logger.error('Could not run command %s: %s', command, ex) return + finally: + if stderr_needs_closing: + stderr_handler.close() if stderr and log_errors: logger.error(stderr) return stdout.strip() From cdb3a52b1d3b74fce2c419f47ba0e1a0da0ab0f6 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 21 May 2016 13:52:58 -0700 Subject: [PATCH 080/181] Get rid of deprecated xpad and ypad in Glade files --- share/lutris/ui/LutrisWindow.ui | 8 -------- share/lutris/ui/dialog-client-update.ui | 2 -- share/lutris/ui/dialog-pga-sources.ui | 1 - 3 files changed, 11 deletions(-) diff --git a/share/lutris/ui/LutrisWindow.ui b/share/lutris/ui/LutrisWindow.ui index bc68c4f43..2862b35df 100644 --- a/share/lutris/ui/LutrisWindow.ui +++ b/share/lutris/ui/LutrisWindow.ui @@ -67,14 +67,12 @@ True False - 4 16 view-grid-symbolic True False - 4 16 view-list-symbolic @@ -750,7 +748,6 @@ False - 2 ../media/gamepad.png @@ -762,7 +759,6 @@ False - 2 ../media/gamepad.png @@ -774,7 +770,6 @@ False - 2 ../media/gamepad.png @@ -786,7 +781,6 @@ False - 2 ../media/gamepad.png @@ -799,8 +793,6 @@ True False - 5 - 5 Lutris 1 0 diff --git a/share/lutris/ui/dialog-client-update.ui b/share/lutris/ui/dialog-client-update.ui index ea2fcfb42..1cbea98df 100644 --- a/share/lutris/ui/dialog-client-update.ui +++ b/share/lutris/ui/dialog-client-update.ui @@ -61,8 +61,6 @@ True False - 40 - 30 A new version of Lutris is available! diff --git a/share/lutris/ui/dialog-pga-sources.ui b/share/lutris/ui/dialog-pga-sources.ui index 3a8d8a0df..b4a35bc3e 100644 --- a/share/lutris/ui/dialog-pga-sources.ui +++ b/share/lutris/ui/dialog-pga-sources.ui @@ -76,7 +76,6 @@ True False 0 - 5 <b>Personnal Game Archives sources</b> True From abdba7f7827a27975cd448627c23dc3c76cc4d79 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 21 May 2016 13:55:43 -0700 Subject: [PATCH 081/181] Remove deprecated GtkAlignment paddings --- share/lutris/ui/LutrisWindow.ui | 4 ---- 1 file changed, 4 deletions(-) diff --git a/share/lutris/ui/LutrisWindow.ui b/share/lutris/ui/LutrisWindow.ui index 2862b35df..76604a3b2 100644 --- a/share/lutris/ui/LutrisWindow.ui +++ b/share/lutris/ui/LutrisWindow.ui @@ -597,10 +597,6 @@ True False - 50 - 50 - 150 - 150 True From baabe7ae14b362ac0efa480f94b819d5b9c81ac1 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 21 May 2016 15:20:25 -0700 Subject: [PATCH 082/181] Remove xalign and yalign deprecated properties --- share/lutris/ui/LutrisWindow.ui | 5 ----- share/lutris/ui/dialog-client-update.ui | 1 - 2 files changed, 6 deletions(-) diff --git a/share/lutris/ui/LutrisWindow.ui b/share/lutris/ui/LutrisWindow.ui index 76604a3b2..1a3585ed3 100644 --- a/share/lutris/ui/LutrisWindow.ui +++ b/share/lutris/ui/LutrisWindow.ui @@ -546,7 +546,6 @@ False Grid view view_grid_symbolic - 0 True False @@ -564,7 +563,6 @@ False List view view_list_symbolic - 0 True False switch_grid_view_btn @@ -638,7 +636,6 @@ True True True - queue none @@ -791,7 +788,6 @@ False Lutris 1 - 0 True @@ -804,7 +800,6 @@ True False label - 1 True diff --git a/share/lutris/ui/dialog-client-update.ui b/share/lutris/ui/dialog-client-update.ui index 1cbea98df..b3dec1dfc 100644 --- a/share/lutris/ui/dialog-client-update.ui +++ b/share/lutris/ui/dialog-client-update.ui @@ -40,7 +40,6 @@ True True True - 0.56000000238418579 From 2ec77a1bdb9f3ae8fa619212786c6e2df00b8280 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 21 May 2016 15:21:34 -0700 Subject: [PATCH 083/181] Remove deprecated GtkImage:use-stock --- share/lutris/ui/LutrisWindow.ui | 8 -------- 1 file changed, 8 deletions(-) diff --git a/share/lutris/ui/LutrisWindow.ui b/share/lutris/ui/LutrisWindow.ui index 1a3585ed3..c67f4cd21 100644 --- a/share/lutris/ui/LutrisWindow.ui +++ b/share/lutris/ui/LutrisWindow.ui @@ -176,7 +176,6 @@ configure the default options True image1 - False @@ -187,7 +186,6 @@ False True image3 - False @@ -336,7 +334,6 @@ False True image4 - False @@ -347,7 +344,6 @@ False True image5 - False @@ -364,7 +360,6 @@ False True image6 - False @@ -375,7 +370,6 @@ False True image7 - False @@ -392,7 +386,6 @@ False True image2 - False @@ -417,7 +410,6 @@ False True image8 - False From adc0d6aa394c62f1fd3c0678a0accf3d0c5bc1ae Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 21 May 2016 15:26:12 -0700 Subject: [PATCH 084/181] Replace GtkImageMenuItem with GtkMenuItem --- share/lutris/ui/LutrisWindow.ui | 80 ++++----------------------------- 1 file changed, 8 insertions(+), 72 deletions(-) diff --git a/share/lutris/ui/LutrisWindow.ui b/share/lutris/ui/LutrisWindow.ui index c67f4cd21..d2c5b388e 100644 --- a/share/lutris/ui/LutrisWindow.ui +++ b/share/lutris/ui/LutrisWindow.ui @@ -3,62 +3,6 @@ - - True - False - preferences-desktop - True - 1 - - - True - False - text-x-generic - True - 1 - - - True - False - application-exit - True - 1 - - - True - False - media-playback-start - True - 1 - - - True - False - media-playback-stop - True - 1 - - - True - False - list-add - True - 1 - - - True - False - list-remove - True - 1 - - - True - False - help-about - True - 1 - False True @@ -167,7 +111,7 @@ - + _Preferences True False @@ -175,17 +119,15 @@ configure the default options configure the default options True - image1 - + _Quit True False True - image3 @@ -328,22 +270,20 @@ True False - + _Play True False True - image4 - + _Stop True False True - image5 @@ -354,22 +294,20 @@ - + _Add True False True - image6 - + _Remove True False True - image7 @@ -380,12 +318,11 @@ - + View last game's _log True False True - image2 @@ -404,12 +341,11 @@ True False - + _About True False True - image8 From de9e0babfd330955d8cd7c8b10b40c77d8ef8fd5 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 21 May 2016 15:28:31 -0700 Subject: [PATCH 085/181] Remove deprecated margin-right --- share/lutris/ui/LutrisWindow.ui | 1 - 1 file changed, 1 deletion(-) diff --git a/share/lutris/ui/LutrisWindow.ui b/share/lutris/ui/LutrisWindow.ui index d2c5b388e..76d075920 100644 --- a/share/lutris/ui/LutrisWindow.ui +++ b/share/lutris/ui/LutrisWindow.ui @@ -437,7 +437,6 @@ True False - 10 True From 813b0f289cd3c8f8865d723bb6f035a0616632f9 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 21 May 2016 15:34:59 -0700 Subject: [PATCH 086/181] Remove GtkAlignment on splash_box --- share/lutris/ui/LutrisWindow.ui | 173 ++++++++++++++++---------------- 1 file changed, 84 insertions(+), 89 deletions(-) diff --git a/share/lutris/ui/LutrisWindow.ui b/share/lutris/ui/LutrisWindow.ui index 76d075920..defb7dc3d 100644 --- a/share/lutris/ui/LutrisWindow.ui +++ b/share/lutris/ui/LutrisWindow.ui @@ -1,5 +1,5 @@ - + @@ -112,21 +112,21 @@ - _Preferences True False True configure the default options configure the default options + _Preferences True - _Quit True False + _Quit True @@ -271,18 +271,18 @@ False - _Play True False + _Play True - _Stop True False + _Stop True @@ -295,18 +295,18 @@ - _Add True False + _Add True - _Remove True False + _Remove True @@ -319,9 +319,9 @@ - View last game's _log True False + View last game's _log True @@ -342,9 +342,9 @@ False - _About True False + _About True @@ -519,95 +519,90 @@ - + True False + vertical + 10 + top - + True False - vertical - 10 - top - - - True - False - Welcome to Lutris - - - - - - False - False - 0 - - - - - True - False - There are no games currently installed, you can start adding some by: - 4 - - - False - False - 1 - - - - - Manually adding a game installed on your hard drive - True - True - True - none - - - - False - False - 2 - - - - - Connecting to your Lutris.net account to sync your library - True - True - True - none - - - - False - False - 3 - - - - - Browsing Lutris.net for games to install - True - True - True - none - http://lutris.net/games/ - - - False - False - 4 - - + Welcome to Lutris + + + + + False + False + 0 + + + + + True + False + There are no games currently installed, you can start adding some by: + 4 + + + False + False + 1 + + + + + Manually adding a game installed on your hard drive + True + True + True + none + + + + False + False + 2 + + + + + Connecting to your Lutris.net account to sync your library + True + True + True + none + + + + False + False + 3 + + + + + Browsing Lutris.net for games to install + True + True + True + none + http://lutris.net/games/ + + + False + False + 4 + - False - False + True + True + 40 2 From 68baf8da4be5c4a05cb0b0daf8770a359dd5f7d8 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 10 Jun 2016 21:07:04 -0700 Subject: [PATCH 087/181] Remove unresponsive client error message --- bin/lutris | 8 -------- 1 file changed, 8 deletions(-) diff --git a/bin/lutris b/bin/lutris index 146bc1b09..f90cefdfe 100755 --- a/bin/lutris +++ b/bin/lutris @@ -126,14 +126,6 @@ if type(lutris) is dbus.Interface: lutris.is_running() except dbus.exceptions.DBusException as e: logger.debug(e) - q = dialogs.QuestionDialog( - {'title': "Error", - 'question': ("Lutris is already running \n" - "but seems unresponsive,\n" - "do you want to restart it?")} - ) - if q.result == Gtk.ResponseType.NO: - exit() try: # Get existing process' PID dbus_proxy = bus.get_object('org.freedesktop.DBus', From 8c625cb64dffbc1a7ea56b397c73a0d4a52d69fe Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 10 Jun 2016 21:23:47 -0700 Subject: [PATCH 088/181] Leave FIXME note about broken D-Bus error handling --- bin/lutris | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/lutris b/bin/lutris index f90cefdfe..7926ceee1 100755 --- a/bin/lutris +++ b/bin/lutris @@ -40,7 +40,6 @@ if LAUNCH_PATH != "/usr/bin": SOURCE_PATH = normpath(os.path.join(LAUNCH_PATH, '..')) sys.path.insert(0, SOURCE_PATH) -from lutris.gui import dialogs from lutris.migrations import migrate from lutris import pga, runtime @@ -126,6 +125,11 @@ if type(lutris) is dbus.Interface: lutris.is_running() except dbus.exceptions.DBusException as e: logger.debug(e) + + # FIXME This whole thing below is utterly broken and I've never seen + # the expected behavior happen. Now, if only I knew how to reproduce + # this state, maybe I might be able to write a fix but I still have no + # idea what's causing this non-responsive DBus thing. try: # Get existing process' PID dbus_proxy = bus.get_object('org.freedesktop.DBus', From de64faa9c7ed88ab2ffe348d55d581ae65e10ede Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 10 Jun 2016 21:27:47 -0700 Subject: [PATCH 089/181] Change logging priorities in DBus fails --- bin/lutris | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/lutris b/bin/lutris index 7926ceee1..b66d219e0 100755 --- a/bin/lutris +++ b/bin/lutris @@ -124,7 +124,7 @@ if type(lutris) is dbus.Interface: try: lutris.is_running() except dbus.exceptions.DBusException as e: - logger.debug(e) + logger.error(e) # FIXME This whole thing below is utterly broken and I've never seen # the expected behavior happen. Now, if only I knew how to reproduce @@ -138,8 +138,10 @@ if type(lutris) is dbus.Interface: pid = dbus_interface.GetConnectionUnixProcessID(lutris.bus_name) os.kill(pid, signal.SIGKILL) - except OSError, dbus.exceptions.DBusException: - logger.debug(e) + except (OSError, dbus.exceptions.DBusException) as ex: + logger.error("Lutris was non responsive, we tried, we failed and failed " + "some more. Please now try to restart Lutris") + logger.error(ex) exit() # Give up :( else: time.sleep(1) # Wait for bus name to be available again From eb18106c5952b14676c9af9fe00e203fd863c657 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 11 Jun 2016 15:07:29 -0700 Subject: [PATCH 090/181] Remove unused imports --- lutris/gui/sidebar.py | 1 - lutris/installer/commands.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lutris/gui/sidebar.py b/lutris/gui/sidebar.py index d36ee7f1d..8135fcf3c 100644 --- a/lutris/gui/sidebar.py +++ b/lutris/gui/sidebar.py @@ -1,7 +1,6 @@ from gi.repository import Gtk, GdkPixbuf import lutris.runners -from lutris import pga from lutris.gui.runnerinstalldialog import RunnerInstallDialog from lutris.gui.config_dialogs import RunnerConfigDialog from lutris.gui.widgets import get_runner_icon diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index 2f9eb0e72..6c6f3373a 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -3,7 +3,7 @@ import os import shutil import shlex -from gi.repository import Gdk, GLib +from gi.repository import GLib from .errors import ScriptingError @@ -12,7 +12,7 @@ from lutris.util import extract, devices, system from lutris.util.fileio import EvilConfigParser, MultiOrderedDict from lutris.util.log import logger -from lutris.runners import wine, import_task, import_runner +from lutris.runners import wine, import_task from lutris.thread import LutrisThread From 9e5b8d7a39dc169bf918632092ca7d355ce5e828 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 11 Jun 2016 15:10:16 -0700 Subject: [PATCH 091/181] Do variable subsitution on write_config --- lutris/installer/commands.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index 6c6f3373a..2da196f41 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -327,9 +327,9 @@ class CommandsMixin(object): return True def write_config(self, params): + """Write a key-value pair into an INI type config file.""" self._check_required_params(['file', 'section', 'key', 'value'], params, 'write_config') - """Write a key-value pair into an INI type config file.""" # Get file config_file = self._get_file(params['file']) if not config_file: @@ -345,9 +345,11 @@ class CommandsMixin(object): parser.optionxform = str # Preserve text case parser.read(config_file) + value = self._substitute(params['value']) + if not parser.has_section(params['section']): parser.add_section(params['section']) - parser.set(params['section'], params['key'], params['value']) + parser.set(params['section'], params['key'], value) with open(config_file, 'wb') as f: parser.write(f) From e7e2ee71e7d7b21d041afe05e2db059a0fd64973 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 11 Jun 2016 16:46:42 -0700 Subject: [PATCH 092/181] Make LutrisWindow a subclass of Gtk.Application --- lutris/gui/lutriswindow.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index e7eaaa1d0..0b16b5112 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -4,7 +4,7 @@ import os import time import subprocess -from gi.repository import Gtk, Gdk, GLib +from gi.repository import Gtk, Gdk, GLib, Gio from lutris import api, pga, runtime, settings, shortcuts from lutris.game import Game, get_game_list @@ -37,10 +37,14 @@ def load_view(view, store): return view -class LutrisWindow(object): +class LutrisWindow(Gtk.Application): """Handler class for main window signals.""" def __init__(self, service=None): + Gtk.Application.__init__( + self, application_id="net.lutris.main", + flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE + ) ui_filename = os.path.join( datapath.get(), 'ui', 'LutrisWindow.ui' ) From 5fe3c7af702f6448ef268b8819c150c7682653c5 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 12 Jun 2016 23:07:18 -0700 Subject: [PATCH 093/181] Disable runner state polling as stated in issue #295 --- lutris/gui/lutriswindow.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 0b16b5112..fd1687967 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -311,7 +311,15 @@ class LutrisWindow(Gtk.Application): for game_id in uninstalled.difference(added): self.view.set_uninstalled(game_id) - self.sidebar_treeview.update() + # See: https://github.com/lutris/lutris/issues/295 + # This is disabled because it polls for the install state for every + # runner every 5 seconds. Runner installations and removals should + # notify the application of changes and make it act accordingly. + # The "Are we there yet?" pattern shouldn't be used outside the Process + # Monitor! + # Note: The code above regarding installed and uninstalled games has + # the exact same problem but should be solved with issue #212. + # self.sidebar_treeview.update() if first_run: icons_sync = AsyncCall(self.sync_icons, None, stoppable=True) From 3f1650df1d78aa7af7f8632cce25589d299a807f Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 14 Jun 2016 00:48:30 -0700 Subject: [PATCH 094/181] Send installed runners notification to the sidebar --- lutris/gui/lutriswindow.py | 10 ---------- lutris/gui/sidebar.py | 20 +++++++++++--------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index fd1687967..4d5ef21b8 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -311,16 +311,6 @@ class LutrisWindow(Gtk.Application): for game_id in uninstalled.difference(added): self.view.set_uninstalled(game_id) - # See: https://github.com/lutris/lutris/issues/295 - # This is disabled because it polls for the install state for every - # runner every 5 seconds. Runner installations and removals should - # notify the application of changes and make it act accordingly. - # The "Are we there yet?" pattern shouldn't be used outside the Process - # Monitor! - # Note: The code above regarding installed and uninstalled games has - # the exact same problem but should be solved with issue #212. - # self.sidebar_treeview.update() - if first_run: icons_sync = AsyncCall(self.sync_icons, None, stoppable=True) self.threads_stoppers.append(icons_sync.stop_request.set) diff --git a/lutris/gui/sidebar.py b/lutris/gui/sidebar.py index 8135fcf3c..01bd16c4e 100644 --- a/lutris/gui/sidebar.py +++ b/lutris/gui/sidebar.py @@ -1,8 +1,9 @@ -from gi.repository import Gtk, GdkPixbuf +from gi.repository import Gtk, GdkPixbuf, GObject -import lutris.runners +from lutris import runners from lutris.gui.runnerinstalldialog import RunnerInstallDialog from lutris.gui.config_dialogs import RunnerConfigDialog +from lutris.gui.runnersdialog import RunnersDialog from lutris.gui.widgets import get_runner_icon SLUG = 0 @@ -44,10 +45,10 @@ class SidebarTreeView(Gtk.TreeView): self.set_fixed_height_mode(True) self.connect('button-press-event', self.popup_contextual_menu) + GObject.add_emission_hook(RunnersDialog, "runner-installed", self.update) - self.runners = sorted(lutris.runners.__all__) - self.installed_runners = [runner.name for runner in - lutris.runners.get_installed()] + self.runners = sorted(runners.__all__) + self.installed_runners = [runner.name for runner in runners.get_installed()] self.load_all_runners() self.update() self.expand_all() @@ -56,7 +57,7 @@ class SidebarTreeView(Gtk.TreeView): """Append runners to the model.""" runner_node = self.model.append(None, ['runners', None, "Runners"]) for slug in self.runners: - name = lutris.runners.import_runner(slug).human_name + name = runners.import_runner(slug).human_name icon = get_runner_icon(slug, format='pixbuf', size=(16, 16)) self.model.append(runner_node, [slug, icon, name]) @@ -75,10 +76,11 @@ class SidebarTreeView(Gtk.TreeView): return True return model[iter][0] in self.installed_runners - def update(self): - self.used_runners = lutris.runners.get_installed() + def update(self, *args): + self.used_runners = runners.get_installed() self.model_filter.refilter() self.expand_all() + return True def popup_contextual_menu(self, view, event): if event.button != 3: @@ -107,7 +109,7 @@ class ContextualMenu(Gtk.Menu): self.append(menuitem) def popup(self, event, runner_slug, parent_window): - self.runner = lutris.runners.import_runner(runner_slug)() + self.runner = runners.import_runner(runner_slug)() self.parent_window = parent_window # Clear existing menu From 3f2cdcf36447cf6b4eb43f742c79f8b1b9a07599 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 14 Jun 2016 16:13:19 -0700 Subject: [PATCH 095/181] Add python-gi to dependencies --- debian/control | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control b/debian/control index ab601061c..edd6b3bc0 100644 --- a/debian/control +++ b/debian/control @@ -20,6 +20,7 @@ Depends: ${misc:Depends}, ${python:Depends}, python-yaml, python-dbus, + python-gi, gir1.2-gtk-3.0, xdg-user-dirs, python-xdg, From ff470107c5f6d474bd5602b84ef5f8c430b65400 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 19 Jun 2016 10:31:30 -0700 Subject: [PATCH 096/181] Remove Network category from .desktop file (Fixes #297) --- share/applications/lutris.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/applications/lutris.desktop b/share/applications/lutris.desktop index d709f90e2..e0d49acf5 100644 --- a/share/applications/lutris.desktop +++ b/share/applications/lutris.desktop @@ -2,7 +2,7 @@ Version=1.0 Name=Lutris Comment=Lutris application -Categories=Game;Network; +Categories=Game; Exec=lutris %U Icon=lutris Terminal=false From 5a5847184f6c24724ffb8a3e06465f1c94c44ab6 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 19 Jun 2016 15:19:15 -0700 Subject: [PATCH 097/181] Try saving svg icon as plain svg instead of Inkscape svg --- share/icons/hicolor/scalable/apps/lutris.svg | 900 +++++++++---------- 1 file changed, 405 insertions(+), 495 deletions(-) diff --git a/share/icons/hicolor/scalable/apps/lutris.svg b/share/icons/hicolor/scalable/apps/lutris.svg index 8fa23fb83..fac80a754 100644 --- a/share/icons/hicolor/scalable/apps/lutris.svg +++ b/share/icons/hicolor/scalable/apps/lutris.svg @@ -1,6 +1,4 @@ - - - + width="256" + height="256" + id="svg4023"> + gradientTransform="matrix(0.9975,0.0701,-0.0701,0.9975,18.782,-36.411)" + x2="205.08" + gradientUnits="userSpaceOnUse" + y2="115.93" + id="linearGradient3356"> + id="stop281" /> + id="stop283" /> + id="stop285" /> + id="stop287" /> + gradientTransform="matrix(0.9925,0.1219,-0.1219,0.9925,41.424,-64.904)" + x2="187.02" + gradientUnits="userSpaceOnUse" + y2="127.33" + id="linearGradient3354"> + id="stop238" /> + id="stop240" /> + id="stop242" /> + id="stop244" /> + id="stop246" /> + id="stop248" /> - - - - - - - - - - - - - - - - + x2="250.97" + gradientUnits="userSpaceOnUse" + y2="44.581001" + id="linearGradient3352"> + id="stop229" /> + id="stop231" /> + + + + + + + + + + + + + + + + + width="1080" + height="608" + xlink:href="#XMLID_12_" + id="use186" /> + width="1080" + height="608" + xlink:href="#XMLID_10_" + id="use174" /> + gradientTransform="matrix(1.8951,-0.15171,0.15171,1.8951,-100.87,455.18)" + x2="300.22" + gradientUnits="userSpaceOnUse" + y2="14.798" + id="linearGradient3455"> + id="stop154" /> + id="stop156" /> + id="stop158" /> + id="stop160" /> + width="1080" + height="608" + xlink:href="#XMLID_7_" + id="use147" /> + gradientTransform="matrix(1.9006,0.04962,-0.04962,1.9006,-33.292,342.14)" + x2="269.69" + gradientUnits="userSpaceOnUse" + y2="134.67999" + id="linearGradient3467"> + id="stop121" /> + id="stop123" /> + id="stop125" /> + id="stop127" /> + id="stop129" /> + id="stop131" /> + id="stop133" /> - - - - - - - - - - - - + y2="265.23001" + id="linearGradient3334"> + offset="0" + style="stop-color:#1C1C1C" + id="stop46" /> - - - - - + id="stop48" /> + id="stop50" /> + offset="1" + id="stop52" /> + + + + + + + + + + + + + + + + + + gradientTransform="matrix(-0.6804,-0.7328,0.7328,-0.6804,685.75,990.43)" + y1="274.41" + gradientUnits="userSpaceOnUse" + y2="274.41" + id="linearGradient4015"> + id="stop29" /> + id="stop31" /> + id="stop33" /> + id="stop35" /> image/svg+xml - + + transform="matrix(1.1026044,0,0,1.1419768,-285.52752,-484.2768)" + id="layer1"> + cx="228.33" + cy="94.502998" + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + style="fill:url(#linearGradient4015);stroke:#1a171b;stroke-width:1.50199997" + id="circle37" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g39"> + style="fill:url(#linearGradient3334)" + id="path54" /> + style="fill:url(#linearGradient3336)" + id="path67" /> + style="opacity:0.62999998;fill:url(#linearGradient3338)" + id="path88" /> + id="path90" /> + style="fill:#3d3d3d" + id="path92" /> + cy="96.607002" + ry="6.2610002" + transform="matrix(0.9768,-0.2141,0.2141,0.9768,-15.368,51.344)" + rx="12.754" + id="ellipse94" /> + cy="95.696999" + ry="5.4429998" + transform="matrix(0.9768,-0.2142,0.2142,0.9768,-15.172,51.351)" + rx="11.09" + style="fill:#5c5c5c" + id="ellipse96" /> + cy="94.522003" + ry="4.5320001" + transform="matrix(0.9768,-0.2142,0.2142,0.9768,-14.932,51.251)" + rx="9.2340002" + id="ellipse98" /> + cy="93.778" + ry="3.848" + transform="matrix(0.9768,-0.214,0.214,0.9768,-14.767,51.176)" + rx="7.8369999" + style="fill:#757575" + id="ellipse100" /> @@ -514,278 +458,244 @@ + style="fill:#e85c0f" + id="path110" /> + style="fill:#1a171b" + id="path112" /> + style="fill:#f19300" + id="path114" /> + style="opacity:0.3;fill:#ffffff" + id="path116" /> + cy="89.210999" + ry="0.801" + transform="matrix(0.9935,0.1137,-0.1137,0.9935,11.834,-29.02)" + rx="1.187" + style="opacity:0.34000017;fill:#ffffff" + id="ellipse118" /> + style="fill:url(#linearGradient3467)" + id="path135" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g137"> + id="path139" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g141"> + id="XMLID_7_" /> + width="1080" + height="608" + xlink:href="#XMLID_7_" + id="use3925" /> + clip-path="url(#XMLID_27_)" + id="g149"> + xlink:href="data:image/png;base64,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 0roTRu0AAAAASUVORK5CYII=" + width="153" + id="image151" /> + style="fill:url(#linearGradient3455)" + id="path162" /> + id="g164"> + style="fill:#ffffff" + id="path166" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g168"> + id="XMLID_10_" /> + width="1080" + height="608" + xlink:href="#XMLID_10_" + id="use3937" /> + clip-path="url(#XMLID_29_)" + id="g176"> + xlink:href="data:image/png;base64,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" + width="169" + id="image178" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g180"> + id="XMLID_12_" /> + width="1080" + height="608" + xlink:href="#XMLID_12_" + id="use3946" /> + id="g188"> + xlink:href="data:image/png;base64,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" + width="205" + id="image190" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g192"> + style="fill:url(#linearGradient3344)" + id="path199" /> + style="fill:url(#linearGradient3431)" + id="path206" /> + style="fill:url(#linearGradient3428)" + id="path213" /> + style="fill:url(#linearGradient3425)" + id="path220" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g222"> + id="path226" /> + style="fill:url(#linearGradient3352)" + id="path233" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g235"> + style="fill:url(#linearGradient3354)" + id="path250" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g252"> + id="path256" /> + id="path258" /> + id="path260" /> - + + style="fill:#a6a7a9" + id="path264" /> + style="fill:#ffffff" + id="path266" /> + style="opacity:0.4;fill:#1a171b" + id="path268" /> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g276"> + style="fill:url(#linearGradient3356)" + id="path289" /> + style="fill:#363636" + id="path291" /> + id="path293" /> + style="opacity:0.4;fill:#ffffff" + id="path295" /> From be19fc5820506f8c0e79aea055305996ac7784c5 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 24 Jun 2016 01:25:21 -0700 Subject: [PATCH 098/181] Add Desmume runner --- lutris/runners/__init__.py | 2 +- lutris/runners/desmume.py | 28 ++++++++++++++++++++ share/lutris/media/runner_icons/desmume.png | Bin 0 -> 3953 bytes 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 lutris/runners/desmume.py create mode 100644 share/lutris/media/runner_icons/desmume.png diff --git a/lutris/runners/__init__.py b/lutris/runners/__init__.py index 9cad66842..3580bd6ce 100644 --- a/lutris/runners/__init__.py +++ b/lutris/runners/__init__.py @@ -13,7 +13,7 @@ __all__ = ( # Atari "stella", "atari800", "hatari", "virtualjaguar", # Nintendo - "snes9x", "mupen64plus", "dolphin", + "snes9x", "mupen64plus", "dolphin", "desmume", # Sony "pcsxr", "ppsspp", "pcsx2", # Sega diff --git a/lutris/runners/desmume.py b/lutris/runners/desmume.py new file mode 100644 index 000000000..a31f2e46f --- /dev/null +++ b/lutris/runners/desmume.py @@ -0,0 +1,28 @@ +import os + +from lutris import settings +from lutris.runners.runner import Runner + + +class desmume(Runner): + human_name = "DeSmuME" + platform = 'Nintendo DS' + description = 'Nintendo DS emulator' + game_options = [{ + 'option': 'main_file', + 'type': 'file', + 'label': 'ROM file', + 'help': ("The game data, commonly called a ROM image.") + }] + + def get_executable(self): + return os.path.join(settings.RUNNER_DIR, 'desmume/bin/desmume') + + def play(self): + """Run the game.""" + arguments = [self.get_executable()] + rom = self.game_config.get('main_file') or '' + if not os.path.exists(rom): + return {'error': 'FILE_NOT_FOUND', 'file': rom} + arguments.append(rom) + return {"command": arguments} diff --git a/share/lutris/media/runner_icons/desmume.png b/share/lutris/media/runner_icons/desmume.png new file mode 100644 index 0000000000000000000000000000000000000000..bd58ddaf5a8260a4b9808d551b9603eb9d78edfc GIT binary patch literal 3953 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 LNkvXXu0mjflb=y; literal 0 HcmV?d00001 From 9f8195858bfb6104b47f05c0770b9b0650ac353b Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 26 Jun 2016 18:27:23 -0700 Subject: [PATCH 099/181] I'm done with calling Steam.exe -shutdown, most annoying thing ever --- lutris/runners/winesteam.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index 41eb0e31d..8274d3cdd 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -387,12 +387,8 @@ class winesteam(wine.wine): def shutdown(self): """Shutdown Steam in a clean way.""" - pid = system.get_pid('Steam.exe$') - if not pid: - return - p = subprocess.Popen(self.launch_args + ['-shutdown'], - env=self.get_env()) - p.wait() + wineserver = self.get_executable + 'server' + subprocess.Popen(wineserver + ['-k'], env=self.get_env()) def stop(self): if self.runner_config.get('quit_steam_on_exit'): From 5c61e571d306edf780c538547abf7c5deec20cea Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 26 Jun 2016 19:07:20 -0700 Subject: [PATCH 100/181] Fix wineserver call --- lutris/runners/winesteam.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index 8274d3cdd..72d8d864c 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -387,7 +387,7 @@ class winesteam(wine.wine): def shutdown(self): """Shutdown Steam in a clean way.""" - wineserver = self.get_executable + 'server' + wineserver = self.get_executable() + 'server' subprocess.Popen(wineserver + ['-k'], env=self.get_env()) def stop(self): From 7e2be3b03f4acfb317ef0b59dedd89ae7e7e7823 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 26 Jun 2016 19:46:05 -0700 Subject: [PATCH 101/181] Fix wineserver call more --- lutris/runners/winesteam.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index 72d8d864c..b807578da 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -388,7 +388,7 @@ class winesteam(wine.wine): def shutdown(self): """Shutdown Steam in a clean way.""" wineserver = self.get_executable() + 'server' - subprocess.Popen(wineserver + ['-k'], env=self.get_env()) + subprocess.Popen([wineserver, '-k'], env=self.get_env()) def stop(self): if self.runner_config.get('quit_steam_on_exit'): From 33269a8d1c17d81f5a80c8870517de3925eac647 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Mon, 27 Jun 2016 11:08:12 -0700 Subject: [PATCH 102/181] Update svg icon for Qt compatibility --- share/icons/hicolor/scalable/apps/lutris.svg | 935 ++++++++----------- share/lutris/media/lutris.svg | 587 ++++-------- 2 files changed, 545 insertions(+), 977 deletions(-) diff --git a/share/icons/hicolor/scalable/apps/lutris.svg b/share/icons/hicolor/scalable/apps/lutris.svg index fac80a754..f07b1101c 100644 --- a/share/icons/hicolor/scalable/apps/lutris.svg +++ b/share/icons/hicolor/scalable/apps/lutris.svg @@ -6,696 +6,525 @@ xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" - version="1.1" - width="256" + id="svg4023" height="256" - id="svg4023"> + width="256" + version="1.1"> + gradientUnits="userSpaceOnUse" + x2="205.08" + gradientTransform="matrix(1.896447,0.13327412,-0.13327412,1.896447,-11.666662,297.72541)" + y1="57.817001" + x1="215.33"> + offset="0" /> + offset=".3366" /> + offset=".8733" /> + offset="1" /> + gradientUnits="userSpaceOnUse" + x2="187.02" + gradientTransform="matrix(1.886941,0.23175628,-0.23175628,1.886941,31.380309,243.55452)" + y1="114.44" + x1="164.7"> + offset="0" /> + offset=".2029" /> + offset=".4243" /> + offset=".6365" /> + offset=".8334" /> + offset="1" /> + gradientUnits="userSpaceOnUse" + x2="250.97" + gradientTransform="matrix(1.9006296,0.04962132,-0.04962132,1.9006296,-33.291101,342.13554)" + y1="44.581001" + x1="238.63"> + offset="0" /> + offset="1" /> + gradientUnits="userSpaceOnUse" + x2="251.64999" + gradientTransform="matrix(1.9006,0.04962,-0.04962,1.9006,-33.292,342.14)" + y1="104.7" + x1="186.39999"> + offset="0" /> + offset="1" /> + gradientUnits="userSpaceOnUse" + x2="249.33" + gradientTransform="matrix(1.9006,0.04962,-0.04962,1.9006,-33.292,342.14)" + y1="46.689999" + x1="237.39"> + offset=".3315" /> + offset=".9831" /> - - - - - - - - - - - - - - - - - - - - - - - + y1="62.097" + x1="239.48"> + + + + + + + + + offset=".2865" /> + + + + + + + offset=".2393" /> + offset=".4077" /> + offset=".572" /> + offset=".7288" /> + offset=".875" /> + offset="1" /> + gradientUnits="userSpaceOnUse" + x2="204.39999" + gradientTransform="matrix(1.8888422,0.21654668,-0.21654668,1.8888422,55.9229,72.35906)" + y1="217.71001" + x1="204.39999"> + offset="0" /> + offset=".2232" /> + offset=".6282" /> + id="stop52" + offset="1" /> + gradientUnits="userSpaceOnUse" + x2="202.74001" + gradientTransform="matrix(1.8888422,0.21654668,-0.21654668,1.8888422,55.9229,72.35906)" + y1="210.75" + x1="202.74001"> + offset="0" /> + offset=".3176" /> + offset=".6733" /> + offset="1" /> + gradientUnits="userSpaceOnUse" + x2="229.39" + gradientTransform="matrix(1.8888422,0.21654668,-0.21654668,1.8888422,55.540758,72.530168)" + y1="257.54001" + x1="176.17"> + offset="0" /> + offset=".0907" /> + offset=".2274" /> + offset=".3649" /> + offset=".5002" /> + offset=".6328" /> + offset=".7621" /> + offset=".8863" /> + id="stop86" + offset="1" /> + gradientUnits="userSpaceOnUse" + y1="274.41" + gradientTransform="matrix(-0.6804,-0.7328,0.7328,-0.6804,685.75,990.43)" + x2="1015.9" + x1="919.75"> + offset=".2865" /> + offset=".4507" /> + offset=".775" /> + offset="1" /> - - - - image/svg+xml - - - - - + id="layer1" + transform="matrix(1.1026044,0,0,1.1419768,-285.52752,-484.2768)"> + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + cy="94.502998" + cx="228.33" + r="48.063999" /> + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="g108"> + + + + + - - - - - - - - - - - - - - + d="m 319.63,575.89 c 0,0 11.92,22.093 51.023,28.829 39.101,6.7358 53.652,5.6921 77.738,-5.1065 14.221,-6.7738 19.458,-15.918 25.171,-25.053 -1.2016,18.774 -23.582,41.517 -23.582,41.517 0,0 -32.934,30.563 -73.979,29.846 -41.046,-0.71676 -58.882,-15.11 -58.882,-15.11 l 2.5114,-54.922 z" /> + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + d="m 485.35,479.51 -0.65779,-8.9145 c 0,0 -1.1711,-7.8042 -2.1502,-13.05 -0.97719,-5.2434 -4.846,-9.4525 -12.264,-14.203 -7.4164,-4.7491 -18.268,-8.251 -28.061,-9.0989 -8.1179,-0.69963 -21.169,3.2567 -24.624,3.7852 l -0.18449,-0.63498 c -45.112,-31.878 -119.38,1.7224 -138.31,36.384 -14.804,27.11 -19.829,43.228 -16.257,71.628 4.3841,34.869 24.696,76.609 69.801,91.677 l -10.16,-58.98 c -9.0495,-10.563 -13.454,-48.021 37.656,-72.632 21.534,-10.367 52.082,-12.048 76.027,-3.0495 l 2.8175,1.1426 c 8.9126,5.0989 16.213,6.1198 16.213,6.1198 l 11.12,3.4943 9.7244,-0.38785 5.8574,-3.3004 c 0,0 6.0646,-3.4525 7.4506,-7.3955 1.3878,-3.9392 0.8308,-9.8308 0.8308,-9.8308 l -2.8232,-7.7244 -2.0038,-5.0361 z" /> - - - - - - - - - - - - - - - - - - - - - + id="path166" /> + + + + + + + + + + + + + + + - - - - - - - + d="m 379.7,545.71 c 0,0 2.7129,2.0095 2.865,0.82129 0.14828,-1.1863 -27.137,-103.72 -27.137,-103.72 0,0 18.314,75.839 24.272,102.89 z" /> + + + + d="m 382.69,438.83 13.894,99.85 -2.8004,-15.316 -12.207,-82.525 c 0,0 1.0057,-1.1141 1.1141,-2.0095 z" /> diff --git a/share/lutris/media/lutris.svg b/share/lutris/media/lutris.svg index 8fa23fb83..f07b1101c 100644 --- a/share/lutris/media/lutris.svg +++ b/share/lutris/media/lutris.svg @@ -1,6 +1,4 @@ - - - + version="1.1"> - - - - - - - - - - - - - image/svg+xml - - - - - + r="48.063999" /> + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + transform="matrix(1.9012,0,0,1.9012,-47.375,366.95)" + id="g108"> + + + + + - - - - - - - - - - - - - - + d="m 319.63,575.89 c 0,0 11.92,22.093 51.023,28.829 39.101,6.7358 53.652,5.6921 77.738,-5.1065 14.221,-6.7738 19.458,-15.918 25.171,-25.053 -1.2016,18.774 -23.582,41.517 -23.582,41.517 0,0 -32.934,30.563 -73.979,29.846 -41.046,-0.71676 -58.882,-15.11 -58.882,-15.11 l 2.5114,-54.922 z" /> + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + d="m 485.35,479.51 -0.65779,-8.9145 c 0,0 -1.1711,-7.8042 -2.1502,-13.05 -0.97719,-5.2434 -4.846,-9.4525 -12.264,-14.203 -7.4164,-4.7491 -18.268,-8.251 -28.061,-9.0989 -8.1179,-0.69963 -21.169,3.2567 -24.624,3.7852 l -0.18449,-0.63498 c -45.112,-31.878 -119.38,1.7224 -138.31,36.384 -14.804,27.11 -19.829,43.228 -16.257,71.628 4.3841,34.869 24.696,76.609 69.801,91.677 l -10.16,-58.98 c -9.0495,-10.563 -13.454,-48.021 37.656,-72.632 21.534,-10.367 52.082,-12.048 76.027,-3.0495 l 2.8175,1.1426 c 8.9126,5.0989 16.213,6.1198 16.213,6.1198 l 11.12,3.4943 9.7244,-0.38785 5.8574,-3.3004 c 0,0 6.0646,-3.4525 7.4506,-7.3955 1.3878,-3.9392 0.8308,-9.8308 0.8308,-9.8308 l -2.8232,-7.7244 -2.0038,-5.0361 z" /> + + + + + d="m 420.36,435.53 c 0,0 8.7206,-1.5589 17.472,-2.7566 8.7529,-1.1939 15.859,0.78326 22.89,3.4525 7.0267,2.6692 14.363,8.0229 15.937,9.1312 1.5704,1.1103 6.4069,6.7529 7.2871,13.896 0.88023,7.1426 1.9981,12.156 1.7148,16.063 -0.27946,3.9088 2.2548,9.135 2.2548,9.135 0,0 9.867,17.344 -6.5723,26.704 -13.002,7.1331 -35.867,-3.251 -38.673,-4.751 0,0 -13.911,-5.7035 -22.603,-6.8194 0.0552,-2.1331 0.3004,-3.095 0.3004,-3.095 0,0 12.694,2.9012 17.781,5.7034 5.0894,2.8042 16.742,6.4905 16.742,6.4905 0,0 16.785,7.1274 25.671,0.7757 8.886,-6.3518 10.357,-10.69 8.7681,-18.027 -1.5856,-7.3384 -3.7225,-7.3936 -4.6616,-12.226 0,0 -0.74147,-5.713 -1.1198,-11.595 -0.38022,-5.8841 -1.7643,-14.285 -6.9867,-18.692 -5.2244,-4.4088 -13.285,-9.2472 -17.519,-10.605 -4.2358,-1.3555 -15.034,-3.5951 -20.935,-2.5038 -5.9012,1.0912 -18.456,3.2434 -18.456,3.2434 l 0.70913,-3.5228 z" /> + d="m 441.58,435.61 c 0,0 -20.882,10.838 -23.747,11.192 0.94867,-1.8384 1.3859,-3.232 1.5285,-6.5019 0.14075,-3.2662 1.1065,-8.232 4.7472,-9.1883 3.6445,-0.95628 6.2643,0.74337 10.365,1.9221 4.0951,1.1749 4.5951,2.2244 7.1065,2.5761 z" /> - - - - - - - - - - - - - - - - - - + d="m 420.11,499.6 c -36.751,-4.2947 -65.474,7.1008 -79.428,17.926 -13.954,10.823 -22.078,22.751 -22.158,44.411 -0.078,21.662 22.844,32.021 22.844,32.021 12.285,5.3194 31.173,11.892 45.485,13.249 19.337,1.8365 32.968,1.0666 42.399,-0.55131 l 9.2187,-2.3023 c -24.666,9.7149 -70.054,7.0267 -100.31,-9.0513 -23.837,-12.762 -23.099,-31.552 -22.32,-42.719 0.78138,-11.167 10.454,-35.673 42.285,-48.649 31.833,-12.972 62.407,-7.4126 62.407,-7.4126" /> + + + + + + + + + d="m 323.36,574.37 65.651,16.892 c 0,0 8.9221,2.9886 17.673,-3.1388 0.30231,-0.21111 59.238,-48.196 59.54,-48.428 -0.11028,0.20142 -58.94,48.215 -59.215,48.496 -2.1483,2.1996 -9.4259,5.7358 -18.074,3.7244 -9.7586,-2.2681 -65.574,-17.546 -65.574,-17.546 z" /> - - - - - - - + d="m 379.7,545.71 c 0,0 2.7129,2.0095 2.865,0.82129 0.14828,-1.1863 -27.137,-103.72 -27.137,-103.72 0,0 18.314,75.839 24.272,102.89 z" /> + + + + d="m 382.69,438.83 13.894,99.85 -2.8004,-15.316 -12.207,-82.525 c 0,0 1.0057,-1.1141 1.1141,-2.0095 z" /> From b6788572663d917a410a55f6f818c2aa6a1e6acf Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Thu, 30 Jun 2016 00:12:11 -0700 Subject: [PATCH 103/181] Add Aspect Ratio and Scaler options on Mednafen --- lutris/runners/mednafen.py | 50 +++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/lutris/runners/mednafen.py b/lutris/runners/mednafen.py index 1b105d8e9..3cf825272 100644 --- a/lutris/runners/mednafen.py +++ b/lutris/runners/mednafen.py @@ -43,6 +43,43 @@ class mednafen(Runner): "type": "bool", "label": "Fullscreen", "default": False, + }, + { + "option": "stretch", + "type": "choice", + "label": "Aspect ratio", + "choices": ( + ("Disabled", "0"), + ("Stretched", "full"), + ("Preserve aspect ratio", "aspect"), + ("Integer scale", "aspect_int"), + ("Multiple of 2 scale", "aspect_mult2"), + ), + "default": "0" + }, + { + "option": "scaler", + "type": "choice", + "label": "Video scaler", + "choices": ( + ("none", "none"), + ("hq2x", "hq2x"), + ("hq3x", "hq3x"), + ("hq4x", "hq4x"), + ("scale2x", "scale2x"), + ("scale3x", "scale3x"), + ("scale4x", "scale4x"), + ("2xsai", "2xsai"), + ("super2xsai", "super2xsai"), + ("supereagle", "supereagle"), + ("nn2x", "nn2x"), + ("nn3x", "nn3x"), + ("nn4x", "nn4x"), + ("nny2x", "nny2x"), + ("nny3x", "nny3x"), + ("nny4x", "nny4x"), + ), + "default": "hq4x", } ] @@ -191,10 +228,15 @@ class mednafen(Runner): rom = self.game_config.get('main_file') or '' machine = self.game_config.get('machine') or '' - if self.runner_config.get("fs"): + fullscreen = self.runner_config.get("fs") or "0" + if fullscreen is True: fullscreen = "1" - else: + elif fullscreen is False: fullscreen = "0" + + stretch = self.runner_config.get('stretch') or "0" + scaler = self.runner_config.get('scaler') or "hq4x" + resolution = get_current_resolution() (resolutionx, resolutiony) = resolution.split("x") xres = str(resolutionx) @@ -202,8 +244,8 @@ class mednafen(Runner): options = ["-fs", fullscreen, "-" + machine + ".xres", xres, "-" + machine + ".yres", yres, - "-" + machine + ".stretch", "1", - "-" + machine + ".special", "hq4x", + "-" + machine + ".stretch", stretch, + "-" + machine + ".special", scaler, "-" + machine + ".videoip", "1"] joy_ids = self.find_joysticks() if len(joy_ids) > 0: From 2b374af4b233fdb5f75db6576659adb2eb382690 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Thu, 30 Jun 2016 21:13:31 -0700 Subject: [PATCH 104/181] Add support for Citra --- lutris/runners/__init__.py | 2 +- lutris/runners/citra.py | 28 ++++++++++++++++++++++ share/lutris/media/runner_icons/citra.png | Bin 0 -> 14250 bytes 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 lutris/runners/citra.py create mode 100644 share/lutris/media/runner_icons/citra.png diff --git a/lutris/runners/__init__.py b/lutris/runners/__init__.py index 3580bd6ce..2cb12b642 100644 --- a/lutris/runners/__init__.py +++ b/lutris/runners/__init__.py @@ -13,7 +13,7 @@ __all__ = ( # Atari "stella", "atari800", "hatari", "virtualjaguar", # Nintendo - "snes9x", "mupen64plus", "dolphin", "desmume", + "snes9x", "mupen64plus", "dolphin", "desmume", "citra", # Sony "pcsxr", "ppsspp", "pcsx2", # Sega diff --git a/lutris/runners/citra.py b/lutris/runners/citra.py new file mode 100644 index 000000000..935e1a44c --- /dev/null +++ b/lutris/runners/citra.py @@ -0,0 +1,28 @@ +import os + +from lutris import settings +from lutris.runners.runner import Runner + + +class citra(Runner): + human_name = "Citra" + platform = 'Nintendo 3DS' + description = 'Nintendo 3DS emulator' + game_options = [{ + 'option': 'main_file', + 'type': 'file', + 'label': 'ROM file', + 'help': ("The game data, commonly called a ROM image.") + }] + + def get_executable(self): + return os.path.join(settings.RUNNER_DIR, 'citra/citra-qt') + + def play(self): + """Run the game.""" + arguments = [self.get_executable()] + rom = self.game_config.get('main_file') or '' + if not os.path.exists(rom): + return {'error': 'FILE_NOT_FOUND', 'file': rom} + arguments.append(rom) + return {"command": arguments} diff --git a/share/lutris/media/runner_icons/citra.png b/share/lutris/media/runner_icons/citra.png new file mode 100644 index 0000000000000000000000000000000000000000..0c0debc89a2370a8c7426382de81d39d55bcf773 GIT binary patch literal 14250 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 NIVoky8gbL0{{@Ybxu5_5 literal 0 HcmV?d00001 From d0bd837be669563d3928c044585b7d23bf0dad0c Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 2 Jul 2016 11:43:45 -0700 Subject: [PATCH 105/181] Do not use system winetricks (Fixes #302) --- lutris/runners/wine.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 0c8cbb1c4..bc548dc08 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -135,8 +135,7 @@ def wineexec(executable, args="", wine_path=None, prefix=None, arch=None, def winetricks(app, prefix=None, winetricks_env=None, silent=True): """Execute winetricks.""" - path = (system.find_executable('winetricks') - or os.path.join(datapath.get(), 'bin/winetricks')) + path = os.path.join(datapath.get(), 'bin/winetricks') arch = detect_prefix_arch(prefix) or 'win32' if not winetricks_env: winetricks_env = wine().get_executable() From dfd1f4ef665a42b3d268cc7ac32935c104ee9e67 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Mon, 4 Jul 2016 23:02:04 -0700 Subject: [PATCH 106/181] Add restrict to single core system option --- lutris/game.py | 7 +++++++ lutris/sysoptions.py | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/lutris/game.py b/lutris/game.py index 9ddefc637..cba7561d5 100644 --- a/lutris/game.py +++ b/lutris/game.py @@ -225,6 +225,13 @@ class Game(object): if prefix_command.strip(): launch_arguments.insert(0, prefix_command) + single_cpu = system_config.get('single_cpu') or False + if single_cpu: + logger.info('The game will run on a single CPU core') + launch_arguments.insert(0, '0') + launch_arguments.insert(0, '-c') + launch_arguments.insert(0, 'taskset') + terminal = system_config.get('terminal') if terminal: terminal = system_config.get("terminal_app", diff --git a/lutris/sysoptions.py b/lutris/sysoptions.py index 51993e9b6..7550a15ad 100644 --- a/lutris/sysoptions.py +++ b/lutris/sysoptions.py @@ -114,6 +114,14 @@ system_options = [ 'help': ("Command line instructions to add in front of the game's " "execution command.") }, + { + 'option': 'single_cpu', + 'type': 'bool', + 'label': 'Restrict to single core', + 'advanced': True, + 'default': False, + 'help': "Restrict the game to a single CPU core." + }, { 'option': 'disable_runtime', 'type': 'bool', From deb919e1bedbca8a5719b5d25cde1a483c1f781f Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 5 Jul 2016 12:19:14 -0700 Subject: [PATCH 107/181] Add psmisc as a dependency (Fixes #302) --- debian/control | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control b/debian/control index edd6b3bc0..f11897a8b 100644 --- a/debian/control +++ b/debian/control @@ -24,6 +24,7 @@ Depends: ${misc:Depends}, gir1.2-gtk-3.0, xdg-user-dirs, python-xdg, + psmisc, libc6-i386 [amd64], lib32gcc1 [amd64] Description: Install and play any video game easily From 65bb9b9d2fbd6daf2e75ee89cfabb3f1eb1069a4 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Fri, 8 Jul 2016 17:48:33 -0400 Subject: [PATCH 108/181] Add Skill as an option --- lutris/runners/zdoom.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 6607a097e..09f80bfb3 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -2,6 +2,8 @@ import os from lutris import settings from lutris.runners.runner import Runner +# ZDoom Runner +# http://zdoom.org/wiki/Command_line_parameters class zdoom(Runner): description = "ZDoom DOOM Game Engine" human_name = "ZDoom" @@ -50,6 +52,20 @@ class zdoom(Runner): "label": "Disable Music", "type": "bool", 'default': False + }, + { + "option": "skill", + "label": "Skill", + "type": "choice", + "default": '', + "choices": { + ("None", ''), + ("Please Don't Kill Me (0)", '0'), + ("Will This Hurt? (1)", '1'), + ("Bring On The Pain (2)", '2'), + ("Extreme Carnage (3)", '3'), + ("Insanity! (4)", '4'), + } } ] @@ -80,6 +96,11 @@ class zdoom(Runner): if self.runner_config.get(option): command.append('-%s' % option) + # Append the skill level. + skill = self.game_config.get('skill') + if skill: + command.append('-skill %s' % skill) + # Append the wad file to load, if provided. wad = self.game_config.get('main_file') if wad: From 99cd961748f00cc8a0e3da7e25dc1dcb5c9cc809 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 9 Jul 2016 23:54:45 -0700 Subject: [PATCH 109/181] Add inotify test script --- steamwatch.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 steamwatch.py diff --git a/steamwatch.py b/steamwatch.py new file mode 100644 index 000000000..a185ec72d --- /dev/null +++ b/steamwatch.py @@ -0,0 +1,31 @@ +import os +import pyinotify + +watch_manager = pyinotify.WatchManager() + + +class EventHandler(pyinotify.ProcessEvent): + def process_IN_MODIFY(self, event): + print "MODIFY" + print event.pathname + print event + + def process_IN_CREATE(self, event): + print "CREATE" + print event.pathname + print event + print event.maskname + + def process_IN_DELETE(self, event): + print "DELETE" + print event.pathname + print event + +steam_path = os.path.expanduser("~/test") + +handler = EventHandler() +# mask = pyinotify.ALL_EVENTS +mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY +notifier = pyinotify.Notifier(watch_manager, handler) +wdd = watch_manager.add_watch(steam_path, mask, rec=True) +notifier.loop() From 2c8351374520dc1ba1580986d2e0f5253b9472ee Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 10 Jul 2016 13:11:48 -0400 Subject: [PATCH 110/181] Fix zdoom file and executable args --- lutris/runners/zdoom.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 09f80bfb3..9be39d527 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -14,6 +14,12 @@ class zdoom(Runner): 'type': 'file', 'label': 'WAD file', 'help': ("The game data, commonly called a WAD file.") + }, + { + 'option': 'file', + 'type': 'file', + 'label': 'PWAD file', + 'help': ("Used to load one or more PWAD files which generally contain user-created levels.") } ] runner_options = [ @@ -70,7 +76,7 @@ class zdoom(Runner): ] def get_executable(self): - return os.path.join(settings.RUNNER_DIR, 'zdoom/zdoom') + return os.path.join(settings.RUNNER_DIR, 'zdoom') @property def working_dir(self): @@ -106,4 +112,9 @@ class zdoom(Runner): if wad: command.append('-iwad %s' % wad) + # Append the pwad files to load, if provided. + pwad = self.game_config.get('file') + if pwad: + command.append('-file %s' % pwad) + return {'command': command} From ec0c8aae28a4483e575a3328e68d47274b9f896b Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 10 Jul 2016 13:28:00 -0400 Subject: [PATCH 111/181] Add the warp argument --- lutris/runners/zdoom.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 9be39d527..0cfffb080 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -20,6 +20,12 @@ class zdoom(Runner): 'type': 'file', 'label': 'PWAD file', 'help': ("Used to load one or more PWAD files which generally contain user-created levels.") + }, + { + 'option': 'warp', + 'type': 'string', + 'label': 'Warp to map', + 'help': ("Starts the game on the given map.") } ] runner_options = [ @@ -107,6 +113,11 @@ class zdoom(Runner): if skill: command.append('-skill %s' % skill) + # Append the warp map. + warp = self.game_config.get('warp') + if warp: + command.append('-warp %s' % warp) + # Append the wad file to load, if provided. wad = self.game_config.get('main_file') if wad: From c7df4e7a2aff519fcfd60d78c2b441020c9c81b4 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 10 Jul 2016 13:43:08 -0400 Subject: [PATCH 112/181] Fix command arguments for zdoom --- lutris/runners/zdoom.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 0cfffb080..7484acf09 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -84,8 +84,13 @@ class zdoom(Runner): def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'zdoom') + @property + def main_file(self): + return self.game_config.get('main_file') or '' + @property def working_dir(self): + """Return the working directory to use when running the game.""" return os.path.dirname(self.main_file) \ or super(zdoom, self).working_dir @@ -109,23 +114,27 @@ class zdoom(Runner): command.append('-%s' % option) # Append the skill level. - skill = self.game_config.get('skill') + skill = self.runner_config.get('skill') if skill: - command.append('-skill %s' % skill) + command.append('-skill') + command.append(skill) # Append the warp map. warp = self.game_config.get('warp') if warp: - command.append('-warp %s' % warp) + command.append('-warp') + command.append(warp) # Append the wad file to load, if provided. wad = self.game_config.get('main_file') if wad: - command.append('-iwad %s' % wad) + command.append('-iwad') + command.append(wad) # Append the pwad files to load, if provided. pwad = self.game_config.get('file') if pwad: - command.append('-file %s' % pwad) + command.append('-file') + command.append(pwad) return {'command': command} From bf7b995dc9a455e4ecd9409c26f9dcfdaf7388be Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 10 Jul 2016 15:08:44 -0400 Subject: [PATCH 113/181] Tweak working_dir game path selection --- lutris/runners/zdoom.py | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 7484acf09..8693fb06e 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -17,7 +17,7 @@ class zdoom(Runner): }, { 'option': 'file', - 'type': 'file', + 'type': 'string', 'label': 'PWAD file', 'help': ("Used to load one or more PWAD files which generally contain user-created levels.") }, @@ -72,11 +72,11 @@ class zdoom(Runner): "default": '', "choices": { ("None", ''), - ("Please Don't Kill Me (0)", '0'), - ("Will This Hurt? (1)", '1'), - ("Bring On The Pain (2)", '2'), - ("Extreme Carnage (3)", '3'), - ("Insanity! (4)", '4'), + ("I'm Too Young To Die (0)", '0'), + ("Hey, Not Too Rough (1)", '1'), + ("Hurt Me Plenty (2)", '2'), + ("Ultra-Violence (3)", '3'), + ("Nightmare! (4)", '4'), } } ] @@ -84,15 +84,10 @@ class zdoom(Runner): def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'zdoom') - @property - def main_file(self): - return self.game_config.get('main_file') or '' - @property def working_dir(self): - """Return the working directory to use when running the game.""" - return os.path.dirname(self.main_file) \ - or super(zdoom, self).working_dir + # Run in the installed game's directory. + return self.game_path def play(self): command = [ @@ -111,30 +106,29 @@ class zdoom(Runner): boolOptions = ['nomusic', 'nosfx', 'nosound', '2', '4', 'nostartup'] for option in boolOptions: if self.runner_config.get(option): - command.append('-%s' % option) + command.append("-%s" % option) # Append the skill level. skill = self.runner_config.get('skill') if skill: - command.append('-skill') - command.append(skill) + command.append("-skill %s" % skill) # Append the warp map. warp = self.game_config.get('warp') if warp: - command.append('-warp') - command.append(warp) + command.append("-warp %s" % warp) # Append the wad file to load, if provided. wad = self.game_config.get('main_file') if wad: - command.append('-iwad') - command.append(wad) + command.append("-iwad %s" % wad) # Append the pwad files to load, if provided. pwad = self.game_config.get('file') if pwad: - command.append('-file') - command.append(pwad) + command.append("-file %s" % pwad) + + # TODO: Find out why the paths are not found correctly. Something wrong with working_dir? + print(command) return {'command': command} From 4775d489613bdd2ec3806403f6f59bae0bfac2a2 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 24 Jul 2016 02:30:02 -0700 Subject: [PATCH 114/181] Fix button mapping on Mednafen --- lutris/runners/mednafen.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lutris/runners/mednafen.py b/lutris/runners/mednafen.py index 3cf825272..2bed615dc 100644 --- a/lutris/runners/mednafen.py +++ b/lutris/runners/mednafen.py @@ -133,9 +133,9 @@ class mednafen(Runner): nes_controls = [ "-nes.input.port1.gamepad.a", - "joystick {} {}".format(joy_ids[0], BTN_A), - "-nes.input.port1.gamepad.b", "joystick {} {}".format(joy_ids[0], BTN_B), + "-nes.input.port1.gamepad.b", + "joystick {} {}".format(joy_ids[0], BTN_A), "-nes.input.port1.gamepad.start", "joystick {} {}".format(joy_ids[0], BTN_START), "-nes.input.port1.gamepad.select", @@ -152,9 +152,9 @@ class mednafen(Runner): gba_controls = [ "-gba.input.builtin.gamepad.a", - "joystick {} {}".format(joy_ids[0], BTN_A), - "-gba.input.builtin.gamepad.b", "joystick {} {}".format(joy_ids[0], BTN_B), + "-gba.input.builtin.gamepad.b", + "joystick {} {}".format(joy_ids[0], BTN_A), "-gba.input.builtin.gamepad.shoulder_r", "joystick {} {}".format(joy_ids[0], BTN_R), "-gba.input.builtin.gamepad.shoulder_l", @@ -194,9 +194,9 @@ class mednafen(Runner): pce_controls = [ "-pce.input.port1.gamepad.i", - "joystick {} {}".format(joy_ids[0], BTN_A), - "-pce.input.port1.gamepad.ii", "joystick {} {}".format(joy_ids[0], BTN_B), + "-pce.input.port1.gamepad.ii", + "joystick {} {}".format(joy_ids[0], BTN_A), "-pce.input.port1.gamepad.run", "joystick {} {}".format(joy_ids[0], BTN_START), "-pce.input.port1.gamepad.select", From ffdb19f475e318d4fbdd22dc6e061b6e624ec96a Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 24 Jul 2016 20:42:37 -0700 Subject: [PATCH 115/181] Update Apple II machines for MESS --- lutris/runners/mess.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lutris/runners/mess.py b/lutris/runners/mess.py index bb000d910..1650d1a96 100644 --- a/lutris/runners/mess.py +++ b/lutris/runners/mess.py @@ -22,7 +22,8 @@ class mess(Runner): ("Amstrad CPC 464", 'cpc464'), ("Amstrad CPC 6128", 'cpc6128'), ("Amstrad GX4000", 'gx4000'), - ("Apple II", 'apple2'), + ("Apple II", 'apple2ee'), + ("Apple IIGS", 'apple2gs'), ("Commodore 64", 'c64'), ("ZX Spectrum", 'spectrum'), ("ZX Spectrum 128", 'spec128'), From f50b88e8511fa1ce18113acc455295ea1523561f Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 29 Jul 2016 19:21:28 -0700 Subject: [PATCH 116/181] Rename utils.devices to utils.disks --- lutris/installer/commands.py | 4 ++-- lutris/util/{devices.py => disks.py} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename lutris/util/{devices.py => disks.py} (100%) diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index 2da196f41..05dacfaea 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -8,7 +8,7 @@ from gi.repository import GLib from .errors import ScriptingError from lutris import runtime -from lutris.util import extract, devices, system +from lutris.util import extract, disks, system from lutris.util.fileio import EvilConfigParser, MultiOrderedDict from lutris.util.log import logger @@ -154,7 +154,7 @@ class CommandsMixin(object): return 'STOP' def _find_matching_disc(self, widget, requires): - drives = devices.get_mounted_discs() + drives = disks.get_mounted_discs() for drive in drives: mount_point = drive.get_root().get_path() required_abspath = os.path.join(mount_point, requires) diff --git a/lutris/util/devices.py b/lutris/util/disks.py similarity index 100% rename from lutris/util/devices.py rename to lutris/util/disks.py From 8c346915bb05eea70ebc3226466fc578f7cd311e Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 29 Jul 2016 20:28:20 -0700 Subject: [PATCH 117/181] Add joystick choices in Reicast --- lutris/runners/reicast.py | 76 ++++++++++++++++++++++++++++++++++----- lutris/util/joypad.py | 12 +++++++ 2 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 lutris/util/joypad.py diff --git a/lutris/runners/reicast.py b/lutris/runners/reicast.py index b56d6c163..d700a1676 100644 --- a/lutris/runners/reicast.py +++ b/lutris/runners/reicast.py @@ -1,7 +1,10 @@ # -*- coding: utf-8 -*- +import re import os +from collections import Counter from lutris import settings from lutris.runners.runner import Runner +from lutris.util import joypad class reicast(Runner): @@ -17,14 +20,71 @@ class reicast(Runner): "Supported formats: ISO, CDI") }] - runner_options = [ - { - "option": "fullscreen", - "type": "bool", - "label": "Fullscreen", - 'default': False, - } - ] + def __init__(self, config=None): + super(reicast, self).__init__(config) + + self._joypads = None + + self.runner_options = [ + { + 'option': 'fullscreen', + 'type': 'bool', + 'label': 'Fullscreen', + 'default': False, + }, + { + 'option': 'device_id_1', + 'type': 'choice', + 'label': 'Joypad 1', + 'choices': self.get_joypads(), + 'default': '-1' + }, + { + 'option': 'device_id_2', + 'type': 'choice', + 'label': 'Joypad 2', + 'choices': self.get_joypads(), + 'default': '-1' + }, + { + 'option': 'device_id_3', + 'type': 'choice', + 'label': 'Joypad 3', + 'choices': self.get_joypads(), + 'default': '-1' + }, + { + 'option': 'device_id_4', + 'type': 'choice', + 'label': 'Joypad 4', + 'choices': self.get_joypads(), + 'default': '-1' + } + ] + + def get_joypads(self): + """Return list of joypad in a format usable in the options""" + if self._joypads: + return self._joypads + joypad_list = [('No joystick', '-1')] + joypad_devices = joypad.get_joypads() + name_counter = Counter([j[1] for j in joypad_devices]) + name_indexes = {} + for (dev, joy_name) in joypad_devices: + dev_id = re.findall(r'(\d+)', dev)[0] + if name_counter[joy_name] > 1: + if joy_name not in name_indexes: + index = 1 + else: + index = name_indexes[joy_name] + 1 + name_indexes[joy_name] = index + else: + index = 0 + if index: + joy_name += " (%d)" % index + joypad_list.append((joy_name, dev_id)) + self._joypads = joypad_list + return joypad_list def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'reicast/reicast.elf') diff --git a/lutris/util/joypad.py b/lutris/util/joypad.py new file mode 100644 index 000000000..be3d6172d --- /dev/null +++ b/lutris/util/joypad.py @@ -0,0 +1,12 @@ +try: + import evdev +except ImportError: + evdev = None + + +def get_joypads(): + """Return a list of tuples with the device and the joypad name""" + if not evdev: + return [] + device_names = evdev.list_devices() + return [(dev, evdev.InputDevice(dev).name) for dev in device_names] From 69b369d49989bf0a5b984085fefda98cc25cad1a Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 29 Jul 2016 22:45:45 -0700 Subject: [PATCH 118/181] Apply joypad config to Reicast --- lutris/runners/reicast.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lutris/runners/reicast.py b/lutris/runners/reicast.py index d700a1676..d3fd9153a 100644 --- a/lutris/runners/reicast.py +++ b/lutris/runners/reicast.py @@ -97,4 +97,8 @@ class reicast(Runner): "-config", "config:image={}".format(iso), "-config", "x11:fullscreen={}".format(fullscreen) ] + for index in range(1, 5): + config_string = 'device_id_%d' % index + joy_id = self.runner_config.get(config_string) or '-1' + command.append('input:evdev_{}={}'.format(config_string, joy_id)) return {'command': command} From 43595eb732049446174bab27f6ac14f6bacb0d4d Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 00:04:01 -0700 Subject: [PATCH 119/181] Setup mappings on post-install + write Reicast config to file --- lutris/runners/reicast.py | 56 +++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/lutris/runners/reicast.py b/lutris/runners/reicast.py index d3fd9153a..e2b082758 100644 --- a/lutris/runners/reicast.py +++ b/lutris/runners/reicast.py @@ -1,10 +1,13 @@ # -*- coding: utf-8 -*- import re import os +import shutil +from ConfigParser import ConfigParser from collections import Counter from lutris import settings from lutris.runners.runner import Runner -from lutris.util import joypad +from lutris.util import joypad, system +from lutris.gui.dialogs import NoticeDialog class reicast(Runner): @@ -62,6 +65,18 @@ class reicast(Runner): } ] + def install(self, version=None, downloader=None, callback=None): + def on_runner_installed(*args): + mapping_path = system.create_folder('~/.reicast/mappings') + mapping_source = os.path.join(settings.RUNNER_DIR, 'reicast/mappings') + for mapping_file in os.listdir(mapping_source): + shutil.copy(os.path.join(mapping_source, mapping_file), mapping_path) + + system.create_folder('~/.reicast/data') + NoticeDialog("You have to copy valid BIOS files to ~/.reicast/data " + "before playing") + super(reicast, self).install(version, downloader, on_runner_installed) + def get_joypads(self): """Return list of joypad in a format usable in the options""" if self._joypads: @@ -89,16 +104,41 @@ class reicast(Runner): def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'reicast/reicast.elf') + def write_config(self, config): + parser = ConfigParser() + + config_path = os.path.expanduser('~/.reicast/emu.cfg') + if os.path.exists(config_path): + with open(config_path, 'r') as config_file: + parser.read(config_file) + + for section in config: + if not parser.has_section(section): + parser.add_section(section) + for (key, value) in config[section].iteritems(): + parser.set(section, key, value) + + with open(config_path, 'w') as config_file: + parser.write(config_file) + def play(self): - iso = self.game_config.get('iso') fullscreen = '1' if self.runner_config.get('fullscreen') else '0' - command = [ - self.get_executable(), - "-config", "config:image={}".format(iso), - "-config", "x11:fullscreen={}".format(fullscreen) - ] + reicast_config = { + 'x11': { + 'fullscreen': fullscreen + }, + 'input': {} + } + reicast_config['input'] = {} for index in range(1, 5): config_string = 'device_id_%d' % index joy_id = self.runner_config.get(config_string) or '-1' - command.append('input:evdev_{}={}'.format(config_string, joy_id)) + reicast_config['input']['evdev_{}'.format(config_string)] = joy_id + self.write_config(reicast_config) + + iso = self.game_config.get('iso') + command = [ + self.get_executable(), + "-config", "config:image={}".format(iso), + ] return {'command': command} From 5e2b917baa7311f80e3edbab96111161b6da0d44 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 00:08:03 -0700 Subject: [PATCH 120/181] Set number of players to number of connected joysticks --- lutris/runners/reicast.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lutris/runners/reicast.py b/lutris/runners/reicast.py index e2b082758..4aaf754ad 100644 --- a/lutris/runners/reicast.py +++ b/lutris/runners/reicast.py @@ -127,13 +127,21 @@ class reicast(Runner): 'x11': { 'fullscreen': fullscreen }, - 'input': {} + 'input': {}, + 'players': { + 'nb': '1' + } } + players = 1 reicast_config['input'] = {} for index in range(1, 5): config_string = 'device_id_%d' % index joy_id = self.runner_config.get(config_string) or '-1' reicast_config['input']['evdev_{}'.format(config_string)] = joy_id + if index > 1 and joy_id != '-1': + players += 1 + reicast_config['players']['nb'] = players + self.write_config(reicast_config) iso = self.game_config.get('iso') From ad92eba01941f28611c18801e8cafe1819c72fbe Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 03:55:43 -0700 Subject: [PATCH 121/181] Add option to hide Wine crash dialogs --- lutris/runners/wine.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index bc548dc08..04b31c453 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -342,6 +342,7 @@ class wine(Runner): "StrictDrawOrdering": r"%s\Direct3D" % reg_prefix, "Desktop": r"%s\Explorer" % reg_prefix, "WineDesktop": r"%s\Explorer\Desktops" % reg_prefix, + "ShowCrashDialog": r"%s\WineDbg" % reg_prefix } core_processes = ( @@ -499,6 +500,12 @@ class wine(Runner): "for your system. Alsa is the default for modern" "Linux distributions.") }, + { + 'option': 'ShowCrashDialog', + 'label': 'Show crash dialogs', + 'type': 'bool', + 'default': False + }, { 'option': 'show_debug', 'label': 'Output debugging info', @@ -624,14 +631,22 @@ class wine(Runner): enable_wine_desktop = False for key, path in self.reg_keys.iteritems(): value = self.runner_config.get(key) or 'auto' - if not value or value == 'auto': + if not value or value == 'auto' and key != 'ShowCrashDialog': delete_registry_key(path, wine_path=self.get_executable(), prefix=prefix, arch=self.wine_arch) elif key in self.runner_config: if key == 'Desktop' and value is True: enable_wine_desktop = True else: - set_regedit(path, key, value, + if key == 'ShowCrashDialog': + if value is True: + value = '00000001' + else: + value = '00000000' + type = 'REG_DWORD' + else: + type = 'REG_SZ' + set_regedit(path, key, value, type=type, wine_path=self.get_executable(), prefix=prefix, arch=self.wine_arch) self.set_wine_desktop(enable_wine_desktop) From d86826e4499f01dfecc6afc5cdbbce8a560632fe Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 13:13:48 -0700 Subject: [PATCH 122/181] Add readu_button reference function --- lutris/util/joypad.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lutris/util/joypad.py b/lutris/util/joypad.py index be3d6172d..37254d20a 100644 --- a/lutris/util/joypad.py +++ b/lutris/util/joypad.py @@ -10,3 +10,20 @@ def get_joypads(): return [] device_names = evdev.list_devices() return [(dev, evdev.InputDevice(dev).name) for dev in device_names] + + +def read_button(device): + """Reference function for reading controller buttons and axis values. + Not to be used as is. + """ + for event in device.read_loop(): + if event.type == evdev.ecodes.EV_KEY and event.value == 0: + print "button %s (%s): %s" % (event.code, hex(event.code), event.value) + if event.type == evdev.ecodes.EV_ABS: + sticks = (0, 1, 3, 4) + if event.code not in sticks or abs(event.value) > 5000: + print "axis %s (%s): %s" % (event.code, hex(event.code), event.value) + + # Unreacheable return statement, to return the even, place a 'break' in the + # for loop + return event From 3b3c88e198720080c8e7cb8dd8c6d72236a2abc0 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 14:11:11 -0700 Subject: [PATCH 123/181] Bring installer dialog to front when created --- lutris/gui/installgamedialog.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lutris/gui/installgamedialog.py b/lutris/gui/installgamedialog.py index 7151f7416..2e9c23163 100644 --- a/lutris/gui/installgamedialog.py +++ b/lutris/gui/installgamedialog.py @@ -82,6 +82,7 @@ class InstallerDialog(Gtk.Window): self.continue_handler = None self.get_scripts() + self.present() def add_button(self, label, handler=None): button = Gtk.Button.new_with_mnemonic(label) From ac8fa163c68858f87752c792481d4df66cd2a9be Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 16:15:17 -0700 Subject: [PATCH 124/181] Add base classes for Steam watcher --- lutris/util/steam.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 24f897cc3..1496bb8fb 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -1,5 +1,7 @@ import os import time +import threading +import pyinotify from lutris.util.log import logger from collections import OrderedDict from lutris.util.system import fix_path_case @@ -197,3 +199,39 @@ def get_app_state_log(steam_data_dir, appid, start_time=None): if line[0].endswith("state changed"): state_log.append(line[1][:-2]) return state_log + + +class SteamWatchHandler(pyinotify.ProcessEvent): + def process_IN_MODIFY(self, event): + path = event.pathname + if not path.endswith('.acf'): + return + logger.info('MODIFY %s', path) + + def process_IN_CREATE(self, event): + path = event.pathname + if not path.endswith('.acf'): + return + logger.info('CREATE %s', path) + + def process_IN_DELETE(self, event): + path = event.pathname + if not path.endswith('.acf'): + return + logger.info('DELETE %s', path) + + +class SteamWatcher(threading.Thread): + def __init__(self, steamapps_paths): + self.steamapps_paths = steamapps_paths + super(SteamWatcher, self).__init__() + self.start() + + def run(self): + watch_manager = pyinotify.WatchManager() + event_handler = SteamWatchHandler() + mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY + notifier = pyinotify.Notifier(watch_manager, event_handler) + for steamapp_path in self.steamapps_paths: + watch_manager.add_watch(steamapp_path, mask, rec=True) + notifier.loop() From bcc64801ae7ec39619f454ac22667f2c9a76ea1f Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 16:15:52 -0700 Subject: [PATCH 125/181] Remove steamwatch test script --- steamwatch.py | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 steamwatch.py diff --git a/steamwatch.py b/steamwatch.py deleted file mode 100644 index a185ec72d..000000000 --- a/steamwatch.py +++ /dev/null @@ -1,31 +0,0 @@ -import os -import pyinotify - -watch_manager = pyinotify.WatchManager() - - -class EventHandler(pyinotify.ProcessEvent): - def process_IN_MODIFY(self, event): - print "MODIFY" - print event.pathname - print event - - def process_IN_CREATE(self, event): - print "CREATE" - print event.pathname - print event - print event.maskname - - def process_IN_DELETE(self, event): - print "DELETE" - print event.pathname - print event - -steam_path = os.path.expanduser("~/test") - -handler = EventHandler() -# mask = pyinotify.ALL_EVENTS -mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY -notifier = pyinotify.Notifier(watch_manager, handler) -wdd = watch_manager.add_watch(steam_path, mask, rec=True) -notifier.loop() From 9e0e1111844e8445c9091a6566e1c7fd129ef6cd Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 16:56:27 -0700 Subject: [PATCH 126/181] lol, no --- bin/lutris | 9 ++++++++- lutris/runners/steam.py | 5 ++--- lutris/runners/winesteam.py | 7 +++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/bin/lutris b/bin/lutris index b66d219e0..d68c2ae32 100755 --- a/bin/lutris +++ b/bin/lutris @@ -62,8 +62,10 @@ parser.add_option("-l", "--list-games", action="store_true", dest="list_games", help="List games in database") parser.add_option("-o", "--installed", action="store_true", dest="list_installed", help="Only list installed games") -parser.add_option("-s", "--list-steam", action="store_true", +parser.add_option("--list-steam", action="store_true", help="List Steam (Windows) games") +parser.add_option("--list-steam-folders", action="store_true", + help="List all known Steam library folders") parser.add_option("-j", "--json", action="store_true", dest="json", help="Display the list of games in JSON format") parser.add_option("--reinstall", action="store_true", help="Reinstall game") @@ -101,10 +103,15 @@ if options.list_games: ).encode('utf-8') exit() if options.list_steam: + # FIXME: this returns a list of appids + # FIXME: this only works for Wine Steam games from lutris.runners import winesteam steam_runner = winesteam.winesteam() print steam_runner.get_appid_list() exit() +if options.list_steam_folders: + pass + exit() check_config(force_wipe=False) diff --git a/lutris/runners/steam.py b/lutris/runners/steam.py index da515b304..e18577006 100644 --- a/lutris/runners/steam.py +++ b/lutris/runners/steam.py @@ -84,8 +84,7 @@ class steam(Runner): return False return self.game_path - @property - def steam_config(self): + def get_steam_config(self): """Return the "Steam" part of Steam's config.vdf as a dict.""" steam_data_dir = self.steam_data_dir if not steam_data_dir: @@ -135,7 +134,7 @@ class steam(Runner): if main_dir and os.path.isdir(main_dir): dirs.append(main_dir) # Custom dirs - steam_config = self.steam_config + steam_config = self.get_steam_config() if steam_config: i = 1 while ('BaseInstallFolder_%s' % i) in steam_config: diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index b807578da..bae225fd3 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -173,8 +173,7 @@ class winesteam(wine.wine): parts = value.split("\"") return parts[1].strip('\\') - @property - def steam_config(self): + def get_steam_config(self): """Return the "Steam" part of Steam's config.vfd as a dict""" steam_data_dir = self.steam_data_dir if not steam_data_dir: @@ -258,7 +257,7 @@ class winesteam(wine.wine): def get_appid_list(self): """Return the list of appids of all user's games""" - config = self.steam_config + config = self.get_steam_config() if config: apps = config['apps'] return apps.keys() @@ -282,7 +281,7 @@ class winesteam(wine.wine): if main_dir and os.path.isdir(main_dir): dirs.append(main_dir) # Custom dirs - steam_config = self.steam_config + steam_config = self.get_steam_config() if steam_config: i = 1 while ('BaseInstallFolder_%s' % i) in steam_config: From 3a5e480c12f72090a323134d574dc03bbd0faf11 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 16:57:26 -0700 Subject: [PATCH 127/181] Naming --- lutris/runners/winesteam.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index bae225fd3..7a5207946 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -257,9 +257,9 @@ class winesteam(wine.wine): def get_appid_list(self): """Return the list of appids of all user's games""" - config = self.get_steam_config() - if config: - apps = config['apps'] + steam_config = self.get_steam_config() + if steam_config: + apps = steam_config['apps'] return apps.keys() def get_game_path_from_appid(self, appid): From a0bb7ee719ecaad01ae343a2d1c93f743d2e9c87 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 17:50:30 -0700 Subject: [PATCH 128/181] Implement list-steam-folders --- bin/lutris | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bin/lutris b/bin/lutris index d68c2ae32..65b1e22c6 100755 --- a/bin/lutris +++ b/bin/lutris @@ -107,10 +107,17 @@ if options.list_steam: # FIXME: this only works for Wine Steam games from lutris.runners import winesteam steam_runner = winesteam.winesteam() - print steam_runner.get_appid_list() + for appid in steam_runner.get_appid_list(): + print appid exit() if options.list_steam_folders: - pass + from lutris.runners import winesteam, steam + winesteam_runner = winesteam.winesteam() + steam_runner = steam.steam() + for folder in steam_runner.get_steamapps_dirs(): + print folder + for folder in winesteam_runner.get_steamapps_dirs(): + print folder exit() From 7aa4a872d60000167bba122bdba91dc0e02c3b33 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 10 Jul 2016 13:11:48 -0400 Subject: [PATCH 129/181] Fix zdoom file and executable args --- lutris/runners/zdoom.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 09f80bfb3..9be39d527 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -14,6 +14,12 @@ class zdoom(Runner): 'type': 'file', 'label': 'WAD file', 'help': ("The game data, commonly called a WAD file.") + }, + { + 'option': 'file', + 'type': 'file', + 'label': 'PWAD file', + 'help': ("Used to load one or more PWAD files which generally contain user-created levels.") } ] runner_options = [ @@ -70,7 +76,7 @@ class zdoom(Runner): ] def get_executable(self): - return os.path.join(settings.RUNNER_DIR, 'zdoom/zdoom') + return os.path.join(settings.RUNNER_DIR, 'zdoom') @property def working_dir(self): @@ -106,4 +112,9 @@ class zdoom(Runner): if wad: command.append('-iwad %s' % wad) + # Append the pwad files to load, if provided. + pwad = self.game_config.get('file') + if pwad: + command.append('-file %s' % pwad) + return {'command': command} From 2e943cdf3eed30ade4cef5d027798499761b9cfc Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 10 Jul 2016 13:28:00 -0400 Subject: [PATCH 130/181] Add the warp argument --- lutris/runners/zdoom.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 9be39d527..0cfffb080 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -20,6 +20,12 @@ class zdoom(Runner): 'type': 'file', 'label': 'PWAD file', 'help': ("Used to load one or more PWAD files which generally contain user-created levels.") + }, + { + 'option': 'warp', + 'type': 'string', + 'label': 'Warp to map', + 'help': ("Starts the game on the given map.") } ] runner_options = [ @@ -107,6 +113,11 @@ class zdoom(Runner): if skill: command.append('-skill %s' % skill) + # Append the warp map. + warp = self.game_config.get('warp') + if warp: + command.append('-warp %s' % warp) + # Append the wad file to load, if provided. wad = self.game_config.get('main_file') if wad: From f15cf0ab47d81a57deb4644883566ba8a7b61396 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 10 Jul 2016 13:43:08 -0400 Subject: [PATCH 131/181] Fix command arguments for zdoom --- lutris/runners/zdoom.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 0cfffb080..7484acf09 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -84,8 +84,13 @@ class zdoom(Runner): def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'zdoom') + @property + def main_file(self): + return self.game_config.get('main_file') or '' + @property def working_dir(self): + """Return the working directory to use when running the game.""" return os.path.dirname(self.main_file) \ or super(zdoom, self).working_dir @@ -109,23 +114,27 @@ class zdoom(Runner): command.append('-%s' % option) # Append the skill level. - skill = self.game_config.get('skill') + skill = self.runner_config.get('skill') if skill: - command.append('-skill %s' % skill) + command.append('-skill') + command.append(skill) # Append the warp map. warp = self.game_config.get('warp') if warp: - command.append('-warp %s' % warp) + command.append('-warp') + command.append(warp) # Append the wad file to load, if provided. wad = self.game_config.get('main_file') if wad: - command.append('-iwad %s' % wad) + command.append('-iwad') + command.append(wad) # Append the pwad files to load, if provided. pwad = self.game_config.get('file') if pwad: - command.append('-file %s' % pwad) + command.append('-file') + command.append(pwad) return {'command': command} From 54076bf1c395a493f5cf1ec81897693d54952ffe Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Sun, 10 Jul 2016 15:08:44 -0400 Subject: [PATCH 132/181] Tweak working_dir game path selection --- lutris/runners/zdoom.py | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/lutris/runners/zdoom.py b/lutris/runners/zdoom.py index 7484acf09..8693fb06e 100644 --- a/lutris/runners/zdoom.py +++ b/lutris/runners/zdoom.py @@ -17,7 +17,7 @@ class zdoom(Runner): }, { 'option': 'file', - 'type': 'file', + 'type': 'string', 'label': 'PWAD file', 'help': ("Used to load one or more PWAD files which generally contain user-created levels.") }, @@ -72,11 +72,11 @@ class zdoom(Runner): "default": '', "choices": { ("None", ''), - ("Please Don't Kill Me (0)", '0'), - ("Will This Hurt? (1)", '1'), - ("Bring On The Pain (2)", '2'), - ("Extreme Carnage (3)", '3'), - ("Insanity! (4)", '4'), + ("I'm Too Young To Die (0)", '0'), + ("Hey, Not Too Rough (1)", '1'), + ("Hurt Me Plenty (2)", '2'), + ("Ultra-Violence (3)", '3'), + ("Nightmare! (4)", '4'), } } ] @@ -84,15 +84,10 @@ class zdoom(Runner): def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'zdoom') - @property - def main_file(self): - return self.game_config.get('main_file') or '' - @property def working_dir(self): - """Return the working directory to use when running the game.""" - return os.path.dirname(self.main_file) \ - or super(zdoom, self).working_dir + # Run in the installed game's directory. + return self.game_path def play(self): command = [ @@ -111,30 +106,29 @@ class zdoom(Runner): boolOptions = ['nomusic', 'nosfx', 'nosound', '2', '4', 'nostartup'] for option in boolOptions: if self.runner_config.get(option): - command.append('-%s' % option) + command.append("-%s" % option) # Append the skill level. skill = self.runner_config.get('skill') if skill: - command.append('-skill') - command.append(skill) + command.append("-skill %s" % skill) # Append the warp map. warp = self.game_config.get('warp') if warp: - command.append('-warp') - command.append(warp) + command.append("-warp %s" % warp) # Append the wad file to load, if provided. wad = self.game_config.get('main_file') if wad: - command.append('-iwad') - command.append(wad) + command.append("-iwad %s" % wad) # Append the pwad files to load, if provided. pwad = self.game_config.get('file') if pwad: - command.append('-file') - command.append(pwad) + command.append("-file %s" % pwad) + + # TODO: Find out why the paths are not found correctly. Something wrong with working_dir? + print(command) return {'command': command} From c8e77559206094e47597f2d3b78ab38fed772481 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 24 Jul 2016 02:30:02 -0700 Subject: [PATCH 133/181] Fix button mapping on Mednafen --- lutris/runners/mednafen.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lutris/runners/mednafen.py b/lutris/runners/mednafen.py index 3cf825272..2bed615dc 100644 --- a/lutris/runners/mednafen.py +++ b/lutris/runners/mednafen.py @@ -133,9 +133,9 @@ class mednafen(Runner): nes_controls = [ "-nes.input.port1.gamepad.a", - "joystick {} {}".format(joy_ids[0], BTN_A), - "-nes.input.port1.gamepad.b", "joystick {} {}".format(joy_ids[0], BTN_B), + "-nes.input.port1.gamepad.b", + "joystick {} {}".format(joy_ids[0], BTN_A), "-nes.input.port1.gamepad.start", "joystick {} {}".format(joy_ids[0], BTN_START), "-nes.input.port1.gamepad.select", @@ -152,9 +152,9 @@ class mednafen(Runner): gba_controls = [ "-gba.input.builtin.gamepad.a", - "joystick {} {}".format(joy_ids[0], BTN_A), - "-gba.input.builtin.gamepad.b", "joystick {} {}".format(joy_ids[0], BTN_B), + "-gba.input.builtin.gamepad.b", + "joystick {} {}".format(joy_ids[0], BTN_A), "-gba.input.builtin.gamepad.shoulder_r", "joystick {} {}".format(joy_ids[0], BTN_R), "-gba.input.builtin.gamepad.shoulder_l", @@ -194,9 +194,9 @@ class mednafen(Runner): pce_controls = [ "-pce.input.port1.gamepad.i", - "joystick {} {}".format(joy_ids[0], BTN_A), - "-pce.input.port1.gamepad.ii", "joystick {} {}".format(joy_ids[0], BTN_B), + "-pce.input.port1.gamepad.ii", + "joystick {} {}".format(joy_ids[0], BTN_A), "-pce.input.port1.gamepad.run", "joystick {} {}".format(joy_ids[0], BTN_START), "-pce.input.port1.gamepad.select", From 9f4174ac7a07fccbdd5b9bec725dc990a2bffbb8 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sun, 24 Jul 2016 20:42:37 -0700 Subject: [PATCH 134/181] Update Apple II machines for MESS --- lutris/runners/mess.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lutris/runners/mess.py b/lutris/runners/mess.py index bb000d910..1650d1a96 100644 --- a/lutris/runners/mess.py +++ b/lutris/runners/mess.py @@ -22,7 +22,8 @@ class mess(Runner): ("Amstrad CPC 464", 'cpc464'), ("Amstrad CPC 6128", 'cpc6128'), ("Amstrad GX4000", 'gx4000'), - ("Apple II", 'apple2'), + ("Apple II", 'apple2ee'), + ("Apple IIGS", 'apple2gs'), ("Commodore 64", 'c64'), ("ZX Spectrum", 'spectrum'), ("ZX Spectrum 128", 'spec128'), From 38c135f0b4e38f8e889089bf29d58028dc6f3c42 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 29 Jul 2016 19:21:28 -0700 Subject: [PATCH 135/181] Rename utils.devices to utils.disks --- lutris/installer/commands.py | 4 ++-- lutris/util/{devices.py => disks.py} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename lutris/util/{devices.py => disks.py} (100%) diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index 2da196f41..05dacfaea 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -8,7 +8,7 @@ from gi.repository import GLib from .errors import ScriptingError from lutris import runtime -from lutris.util import extract, devices, system +from lutris.util import extract, disks, system from lutris.util.fileio import EvilConfigParser, MultiOrderedDict from lutris.util.log import logger @@ -154,7 +154,7 @@ class CommandsMixin(object): return 'STOP' def _find_matching_disc(self, widget, requires): - drives = devices.get_mounted_discs() + drives = disks.get_mounted_discs() for drive in drives: mount_point = drive.get_root().get_path() required_abspath = os.path.join(mount_point, requires) diff --git a/lutris/util/devices.py b/lutris/util/disks.py similarity index 100% rename from lutris/util/devices.py rename to lutris/util/disks.py From e7871b748798e475d2a7591451b7605186c1da0e Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 29 Jul 2016 20:28:20 -0700 Subject: [PATCH 136/181] Add joystick choices in Reicast --- lutris/runners/reicast.py | 76 ++++++++++++++++++++++++++++++++++----- lutris/util/joypad.py | 12 +++++++ 2 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 lutris/util/joypad.py diff --git a/lutris/runners/reicast.py b/lutris/runners/reicast.py index b56d6c163..d700a1676 100644 --- a/lutris/runners/reicast.py +++ b/lutris/runners/reicast.py @@ -1,7 +1,10 @@ # -*- coding: utf-8 -*- +import re import os +from collections import Counter from lutris import settings from lutris.runners.runner import Runner +from lutris.util import joypad class reicast(Runner): @@ -17,14 +20,71 @@ class reicast(Runner): "Supported formats: ISO, CDI") }] - runner_options = [ - { - "option": "fullscreen", - "type": "bool", - "label": "Fullscreen", - 'default': False, - } - ] + def __init__(self, config=None): + super(reicast, self).__init__(config) + + self._joypads = None + + self.runner_options = [ + { + 'option': 'fullscreen', + 'type': 'bool', + 'label': 'Fullscreen', + 'default': False, + }, + { + 'option': 'device_id_1', + 'type': 'choice', + 'label': 'Joypad 1', + 'choices': self.get_joypads(), + 'default': '-1' + }, + { + 'option': 'device_id_2', + 'type': 'choice', + 'label': 'Joypad 2', + 'choices': self.get_joypads(), + 'default': '-1' + }, + { + 'option': 'device_id_3', + 'type': 'choice', + 'label': 'Joypad 3', + 'choices': self.get_joypads(), + 'default': '-1' + }, + { + 'option': 'device_id_4', + 'type': 'choice', + 'label': 'Joypad 4', + 'choices': self.get_joypads(), + 'default': '-1' + } + ] + + def get_joypads(self): + """Return list of joypad in a format usable in the options""" + if self._joypads: + return self._joypads + joypad_list = [('No joystick', '-1')] + joypad_devices = joypad.get_joypads() + name_counter = Counter([j[1] for j in joypad_devices]) + name_indexes = {} + for (dev, joy_name) in joypad_devices: + dev_id = re.findall(r'(\d+)', dev)[0] + if name_counter[joy_name] > 1: + if joy_name not in name_indexes: + index = 1 + else: + index = name_indexes[joy_name] + 1 + name_indexes[joy_name] = index + else: + index = 0 + if index: + joy_name += " (%d)" % index + joypad_list.append((joy_name, dev_id)) + self._joypads = joypad_list + return joypad_list def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'reicast/reicast.elf') diff --git a/lutris/util/joypad.py b/lutris/util/joypad.py new file mode 100644 index 000000000..be3d6172d --- /dev/null +++ b/lutris/util/joypad.py @@ -0,0 +1,12 @@ +try: + import evdev +except ImportError: + evdev = None + + +def get_joypads(): + """Return a list of tuples with the device and the joypad name""" + if not evdev: + return [] + device_names = evdev.list_devices() + return [(dev, evdev.InputDevice(dev).name) for dev in device_names] From 5e67b758396b5e3369d595433840278187f28b6e Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Fri, 29 Jul 2016 22:45:45 -0700 Subject: [PATCH 137/181] Apply joypad config to Reicast --- lutris/runners/reicast.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lutris/runners/reicast.py b/lutris/runners/reicast.py index d700a1676..d3fd9153a 100644 --- a/lutris/runners/reicast.py +++ b/lutris/runners/reicast.py @@ -97,4 +97,8 @@ class reicast(Runner): "-config", "config:image={}".format(iso), "-config", "x11:fullscreen={}".format(fullscreen) ] + for index in range(1, 5): + config_string = 'device_id_%d' % index + joy_id = self.runner_config.get(config_string) or '-1' + command.append('input:evdev_{}={}'.format(config_string, joy_id)) return {'command': command} From 0d9bd831e11c79195bd4f4de33d52b92632f0758 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 00:04:01 -0700 Subject: [PATCH 138/181] Setup mappings on post-install + write Reicast config to file --- lutris/runners/reicast.py | 56 +++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/lutris/runners/reicast.py b/lutris/runners/reicast.py index d3fd9153a..e2b082758 100644 --- a/lutris/runners/reicast.py +++ b/lutris/runners/reicast.py @@ -1,10 +1,13 @@ # -*- coding: utf-8 -*- import re import os +import shutil +from ConfigParser import ConfigParser from collections import Counter from lutris import settings from lutris.runners.runner import Runner -from lutris.util import joypad +from lutris.util import joypad, system +from lutris.gui.dialogs import NoticeDialog class reicast(Runner): @@ -62,6 +65,18 @@ class reicast(Runner): } ] + def install(self, version=None, downloader=None, callback=None): + def on_runner_installed(*args): + mapping_path = system.create_folder('~/.reicast/mappings') + mapping_source = os.path.join(settings.RUNNER_DIR, 'reicast/mappings') + for mapping_file in os.listdir(mapping_source): + shutil.copy(os.path.join(mapping_source, mapping_file), mapping_path) + + system.create_folder('~/.reicast/data') + NoticeDialog("You have to copy valid BIOS files to ~/.reicast/data " + "before playing") + super(reicast, self).install(version, downloader, on_runner_installed) + def get_joypads(self): """Return list of joypad in a format usable in the options""" if self._joypads: @@ -89,16 +104,41 @@ class reicast(Runner): def get_executable(self): return os.path.join(settings.RUNNER_DIR, 'reicast/reicast.elf') + def write_config(self, config): + parser = ConfigParser() + + config_path = os.path.expanduser('~/.reicast/emu.cfg') + if os.path.exists(config_path): + with open(config_path, 'r') as config_file: + parser.read(config_file) + + for section in config: + if not parser.has_section(section): + parser.add_section(section) + for (key, value) in config[section].iteritems(): + parser.set(section, key, value) + + with open(config_path, 'w') as config_file: + parser.write(config_file) + def play(self): - iso = self.game_config.get('iso') fullscreen = '1' if self.runner_config.get('fullscreen') else '0' - command = [ - self.get_executable(), - "-config", "config:image={}".format(iso), - "-config", "x11:fullscreen={}".format(fullscreen) - ] + reicast_config = { + 'x11': { + 'fullscreen': fullscreen + }, + 'input': {} + } + reicast_config['input'] = {} for index in range(1, 5): config_string = 'device_id_%d' % index joy_id = self.runner_config.get(config_string) or '-1' - command.append('input:evdev_{}={}'.format(config_string, joy_id)) + reicast_config['input']['evdev_{}'.format(config_string)] = joy_id + self.write_config(reicast_config) + + iso = self.game_config.get('iso') + command = [ + self.get_executable(), + "-config", "config:image={}".format(iso), + ] return {'command': command} From 62c5f3a046e9b617a5b759a23af01ea47fe42f0f Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 00:08:03 -0700 Subject: [PATCH 139/181] Set number of players to number of connected joysticks --- lutris/runners/reicast.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lutris/runners/reicast.py b/lutris/runners/reicast.py index e2b082758..4aaf754ad 100644 --- a/lutris/runners/reicast.py +++ b/lutris/runners/reicast.py @@ -127,13 +127,21 @@ class reicast(Runner): 'x11': { 'fullscreen': fullscreen }, - 'input': {} + 'input': {}, + 'players': { + 'nb': '1' + } } + players = 1 reicast_config['input'] = {} for index in range(1, 5): config_string = 'device_id_%d' % index joy_id = self.runner_config.get(config_string) or '-1' reicast_config['input']['evdev_{}'.format(config_string)] = joy_id + if index > 1 and joy_id != '-1': + players += 1 + reicast_config['players']['nb'] = players + self.write_config(reicast_config) iso = self.game_config.get('iso') From 1fb1e0f86f148eb42d5f442bfbd488dc30d21aae Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 03:55:43 -0700 Subject: [PATCH 140/181] Add option to hide Wine crash dialogs --- lutris/runners/wine.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index bc548dc08..04b31c453 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -342,6 +342,7 @@ class wine(Runner): "StrictDrawOrdering": r"%s\Direct3D" % reg_prefix, "Desktop": r"%s\Explorer" % reg_prefix, "WineDesktop": r"%s\Explorer\Desktops" % reg_prefix, + "ShowCrashDialog": r"%s\WineDbg" % reg_prefix } core_processes = ( @@ -499,6 +500,12 @@ class wine(Runner): "for your system. Alsa is the default for modern" "Linux distributions.") }, + { + 'option': 'ShowCrashDialog', + 'label': 'Show crash dialogs', + 'type': 'bool', + 'default': False + }, { 'option': 'show_debug', 'label': 'Output debugging info', @@ -624,14 +631,22 @@ class wine(Runner): enable_wine_desktop = False for key, path in self.reg_keys.iteritems(): value = self.runner_config.get(key) or 'auto' - if not value or value == 'auto': + if not value or value == 'auto' and key != 'ShowCrashDialog': delete_registry_key(path, wine_path=self.get_executable(), prefix=prefix, arch=self.wine_arch) elif key in self.runner_config: if key == 'Desktop' and value is True: enable_wine_desktop = True else: - set_regedit(path, key, value, + if key == 'ShowCrashDialog': + if value is True: + value = '00000001' + else: + value = '00000000' + type = 'REG_DWORD' + else: + type = 'REG_SZ' + set_regedit(path, key, value, type=type, wine_path=self.get_executable(), prefix=prefix, arch=self.wine_arch) self.set_wine_desktop(enable_wine_desktop) From df9206e110d1d0201cb3b04593bbbad99b8fca0b Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 13:13:48 -0700 Subject: [PATCH 141/181] Add readu_button reference function --- lutris/util/joypad.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lutris/util/joypad.py b/lutris/util/joypad.py index be3d6172d..37254d20a 100644 --- a/lutris/util/joypad.py +++ b/lutris/util/joypad.py @@ -10,3 +10,20 @@ def get_joypads(): return [] device_names = evdev.list_devices() return [(dev, evdev.InputDevice(dev).name) for dev in device_names] + + +def read_button(device): + """Reference function for reading controller buttons and axis values. + Not to be used as is. + """ + for event in device.read_loop(): + if event.type == evdev.ecodes.EV_KEY and event.value == 0: + print "button %s (%s): %s" % (event.code, hex(event.code), event.value) + if event.type == evdev.ecodes.EV_ABS: + sticks = (0, 1, 3, 4) + if event.code not in sticks or abs(event.value) > 5000: + print "axis %s (%s): %s" % (event.code, hex(event.code), event.value) + + # Unreacheable return statement, to return the even, place a 'break' in the + # for loop + return event From 5139dc9a7d415a8baa1755256da7a325f86f173e Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Sat, 30 Jul 2016 14:11:11 -0700 Subject: [PATCH 142/181] Bring installer dialog to front when created --- lutris/gui/installgamedialog.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lutris/gui/installgamedialog.py b/lutris/gui/installgamedialog.py index 7151f7416..2e9c23163 100644 --- a/lutris/gui/installgamedialog.py +++ b/lutris/gui/installgamedialog.py @@ -82,6 +82,7 @@ class InstallerDialog(Gtk.Window): self.continue_handler = None self.get_scripts() + self.present() def add_button(self, label, handler=None): button = Gtk.Button.new_with_mnemonic(label) From 295df757c0489bbed8e1194b56731e2d4c2e7f18 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 2 Aug 2016 13:51:23 -0700 Subject: [PATCH 143/181] Launch Steamatcher with the main UI --- bin/lutris | 13 ++++++------- lutris/gui/lutriswindow.py | 5 ++++- lutris/sync.py | 6 +++++- lutris/util/steam.py | 26 ++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/bin/lutris b/bin/lutris index 65b1e22c6..20cf257fb 100755 --- a/bin/lutris +++ b/bin/lutris @@ -49,6 +49,7 @@ from lutris.game import Game from lutris.gui.installgamedialog import InstallerDialog from lutris.settings import VERSION from lutris.util import service +from lutris.util.steam import get_steamapps_paths # Support for command line options. parser = optparse.OptionParser(version="%prog " + VERSION) @@ -111,13 +112,11 @@ if options.list_steam: print appid exit() if options.list_steam_folders: - from lutris.runners import winesteam, steam - winesteam_runner = winesteam.winesteam() - steam_runner = steam.steam() - for folder in steam_runner.get_steamapps_dirs(): - print folder - for folder in winesteam_runner.get_steamapps_dirs(): - print folder + steamapps_paths = get_steamapps_paths() + for path in steamapps_paths['linux']: + print path + for path in steamapps_paths['windows']: + print path exit() diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 4d5ef21b8..10db5a711 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -14,6 +14,7 @@ from lutris.util import display, resources from lutris.util.log import logger from lutris.util.jobs import AsyncCall from lutris.util import datapath +from lutris.util.steam import SteamWatcher, get_steamapps_paths from lutris.gui import dialogs from lutris.gui.sidebar import SidebarTreeView @@ -187,6 +188,8 @@ class LutrisWindow(Gtk.Application): # Timers self.timer_ids = [GLib.timeout_add(300, self.refresh_status), GLib.timeout_add(10000, self.on_sync_timer)] + steamapps_paths = get_steamapps_paths(flat=True) + self.steam_watcher = SteamWatcher(steamapps_paths) def init_game_store(self): logger.debug("Getting game list") @@ -212,7 +215,6 @@ class LutrisWindow(Gtk.Application): def check_update(self): """Verify availability of client update.""" - pass def on_version_received(version, error): if not version: @@ -423,6 +425,7 @@ class LutrisWindow(Gtk.Application): return True def on_resize(self, widget, *args): + """WTF is this doing?""" self.window_size = widget.get_size() def on_destroy(self, *args): diff --git a/lutris/sync.py b/lutris/sync.py index e03b7a0ec..0fb8ad1af 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -137,7 +137,11 @@ class Sync(object): return updated def sync_steam_local(self): - """Sync Steam games in library with Steam and Wine Steam""" + """Sync Steam games in library with Steam and Wine Steam + + FIXME: This is the guilty method that causes grief to everyone, most of it should + probably disappear + """ steamrunner = steam() winesteamrunner = winesteam() installed = set() diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 1496bb8fb..69b9b4ab4 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -201,6 +201,30 @@ def get_app_state_log(steam_data_dir, appid, start_time=None): return state_log +def get_steamapps_paths(flat=False): + from lutris.runners import winesteam, steam + if flat: + steamapps_paths = [] + else: + steamapps_paths = { + 'linux': [], + 'windows': [] + } + winesteam_runner = winesteam.winesteam() + steam_runner = steam.steam() + for folder in steam_runner.get_steamapps_dirs(): + if flat: + steamapps_paths.append(folder) + else: + steamapps_paths['linux'].append(folder) + for folder in winesteam_runner.get_steamapps_dirs(): + if flat: + steamapps_paths.append(folder) + else: + steamapps_paths['windows'].append(folder) + return steamapps_paths + + class SteamWatchHandler(pyinotify.ProcessEvent): def process_IN_MODIFY(self, event): path = event.pathname @@ -232,6 +256,8 @@ class SteamWatcher(threading.Thread): event_handler = SteamWatchHandler() mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY notifier = pyinotify.Notifier(watch_manager, event_handler) + logger.info(self.steamapps_paths) for steamapp_path in self.steamapps_paths: + logger.info('Watching Steam folder %s', steamapp_path) watch_manager.add_watch(steamapp_path, mask, rec=True) notifier.loop() From 755c39a62c4ab5387b069e29317910d6d6d1e537 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 2 Aug 2016 14:03:25 -0700 Subject: [PATCH 144/181] Extract get_appmanifests --- lutris/sync.py | 12 ++++-------- lutris/util/steam.py | 7 +++++++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lutris/sync.py b/lutris/sync.py index 0fb8ad1af..f93c867b1 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -205,16 +205,12 @@ class Sync(object): if not runner.is_installed(): return [] installed = [] - dirs = runner.get_steamapps_dirs() - for dirname in dirs: - appmanifests = [f for f in os.listdir(dirname) - if re.match(r'^appmanifest_\d+.acf$', f)] - for filename in appmanifests: + steamapps_paths = runner.get_steamapps_dirs() + for steamapps_path in steamapps_paths: + for filename in steam.get_appmanifests(steamapps_path): basename, ext = os.path.splitext(filename) steamid = int(basename[12:]) - appmanifest_path = os.path.join( - dirname, "appmanifest_%s.acf" % str(steamid) - ) + appmanifest_path = os.path.join(steamapps_path, filename) with open(appmanifest_path, "r") as appmanifest_file: appmanifest = vdf_parse(appmanifest_file, {}) appstate = appmanifest.get('AppState') or {} diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 69b9b4ab4..e22460e38 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -1,4 +1,5 @@ import os +import re import time import threading import pyinotify @@ -201,6 +202,12 @@ def get_app_state_log(steam_data_dir, appid, start_time=None): return state_log +def get_appmanifests(steamapps_path): + """Return the list for all appmanifest files in a Steam library folder""" + return [f for f in os.listdir(steamapps_path) + if re.match(r'^appmanifest_\d+.acf$', f)] + + def get_steamapps_paths(flat=False): from lutris.runners import winesteam, steam if flat: From 5b0ce862da0a9fbe2bf5f04166464f5bc1be87fa Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 2 Aug 2016 14:22:20 -0700 Subject: [PATCH 145/181] Create AppManifest class --- lutris/sync.py | 12 +++--------- lutris/util/steam.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lutris/sync.py b/lutris/sync.py index f93c867b1..814af7b97 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -1,4 +1,3 @@ -# -*- coding:Utf-8 -*- """Synchronization of the game library with server and local data.""" import os import re @@ -208,13 +207,8 @@ class Sync(object): steamapps_paths = runner.get_steamapps_dirs() for steamapps_path in steamapps_paths: for filename in steam.get_appmanifests(steamapps_path): - basename, ext = os.path.splitext(filename) - steamid = int(basename[12:]) appmanifest_path = os.path.join(steamapps_path, filename) - with open(appmanifest_path, "r") as appmanifest_file: - appmanifest = vdf_parse(appmanifest_file, {}) - appstate = appmanifest.get('AppState') or {} - is_installed = appstate.get('LastOwner') or '0' - if not is_installed == '0': - installed.append(steamid) + appmanifest = steam.AppManifest(appmanifest_path) + if appmanifest.is_installed: + installed.append(appmanifest.steamid) return installed diff --git a/lutris/util/steam.py b/lutris/util/steam.py index e22460e38..705759f42 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -268,3 +268,24 @@ class SteamWatcher(threading.Thread): logger.info('Watching Steam folder %s', steamapp_path) watch_manager.add_watch(steamapp_path, mask, rec=True) notifier.loop() + + +class AppManifest: + def __init__(self, appmanifest_path): + filename = os.path.basename(appmanifest_path) + self.steamid = re.findall(r'(\d+)', filename)[0] + with open(appmanifest_path, "r") as appmanifest_file: + self.appmanifest_data = vdf_parse(appmanifest_file, {}) + + @property + def app_state(self): + return self.appmanifest_data.get('AppState') or {} + + @property + def name(self): + return self.app_state.get('name') + + @property + def is_installed(self): + last_owner = self.appstate.get('LastOwner') or '0' + return last_owner != '0' From 8ab9254740dcdcee4e8a1928c5c7fea438588b8a Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 2 Aug 2016 15:05:23 -0700 Subject: [PATCH 146/181] Move get_app_states to AppManifest class --- lutris/util/steam.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 705759f42..e6b797a53 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -131,18 +131,6 @@ def get_path_from_appmanifest(steamapps_path, appid): return install_path -def get_app_states(steamapps_path, appid): - """Return the states of a Steam game.""" - states = [] - if not steamapps_path: - return states - manifest_info = get_manifest_info(steamapps_path, appid) - state_flags = manifest_info.get('AppState', {}).get('StateFlags', 0) - state_flags = bin(int(state_flags))[:1:-1] - for index, flag in enumerate(state_flags): - if flag == '1': - states.append(APP_STATE_FLAGS[index + 1]) - return states def _get_last_content_log(steam_data_dir): @@ -289,3 +277,14 @@ class AppManifest: def is_installed(self): last_owner = self.appstate.get('LastOwner') or '0' return last_owner != '0' + + @property + def states(self): + """Return the states of a Steam game.""" + states = [] + state_flags = self.app_state.get('StateFlags', 0) + state_flags = bin(int(state_flags))[:1:-1] + for index, flag in enumerate(state_flags): + if flag == '1': + states.append(APP_STATE_FLAGS[index + 1]) + return states From c79e8c4532811b20ae684bca8abffc1747923408 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 2 Aug 2016 15:19:59 -0700 Subject: [PATCH 147/181] Add get_install_path to AppManifest --- lutris/util/steam.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index e6b797a53..e429532f9 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -101,36 +101,26 @@ def read_config(steam_data_dir): return config -def get_manifest_info(steamapps_path, appid): - """Given the steam apps path and appid, return the corresponding - appmanifest info.""" +def get_appmanifest_from_appid(steamapps_path, appid): + """Given the steam apps path and appid, return the corresponding appmanifest""" if not steamapps_path: raise ValueError("steamapps_path is mandatory") if not os.path.exists(steamapps_path): raise IOError("steamapps_path must be a valid directory") if not appid: raise ValueError("Missing mandatory appid") - appmanifest_path = os.path.join(steamapps_path, - "appmanifest_%s.acf" % appid) + appmanifest_path = os.path.join(steamapps_path, "appmanifest_%s.acf" % appid) if not os.path.exists(appmanifest_path): - return {} - with open(appmanifest_path, "r") as appmanifest_file: - config = vdf_parse(appmanifest_file, {}) - return config + return + return AppManifest(appmanifest_path) def get_path_from_appmanifest(steamapps_path, appid): """Return the path where a Steam game is installed.""" - config = get_manifest_info(steamapps_path, appid) - if not config: + appmanifest = get_appmanifest_from_appid(steamapps_path, appid) + if not appmanifest: return - installdir = config.get('AppState', {}).get('installdir') - install_path = fix_path_case(os.path.join(steamapps_path, "common", - installdir)) - if install_path and os.path.exists(install_path): - return install_path - - + return appmanifest.get_install_path() def _get_last_content_log(steam_data_dir): @@ -260,7 +250,7 @@ class SteamWatcher(threading.Thread): class AppManifest: def __init__(self, appmanifest_path): - filename = os.path.basename(appmanifest_path) + self.steamapps_path, filename = os.path.split(appmanifest_path) self.steamid = re.findall(r'(\d+)', filename)[0] with open(appmanifest_path, "r") as appmanifest_file: self.appmanifest_data = vdf_parse(appmanifest_file, {}) @@ -273,6 +263,10 @@ class AppManifest: def name(self): return self.app_state.get('name') + @property + def installdir(self): + return self.app_state.get('installdir') + @property def is_installed(self): last_owner = self.appstate.get('LastOwner') or '0' @@ -288,3 +282,9 @@ class AppManifest: if flag == '1': states.append(APP_STATE_FLAGS[index + 1]) return states + + def get_install_path(self): + install_path = fix_path_case(os.path.join(self.steamapps_path, "common", + self.installdir)) + if install_path: + return install_path From 0dc3a112d0615b74e56cd95d75d00be5de7083e4 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Tue, 2 Aug 2016 15:36:13 -0700 Subject: [PATCH 148/181] Make is_installed a method --- lutris/sync.py | 2 +- lutris/util/steam.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lutris/sync.py b/lutris/sync.py index 814af7b97..d5cf78601 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -209,6 +209,6 @@ class Sync(object): for filename in steam.get_appmanifests(steamapps_path): appmanifest_path = os.path.join(steamapps_path, filename) appmanifest = steam.AppManifest(appmanifest_path) - if appmanifest.is_installed: + if appmanifest.is_installed(): installed.append(appmanifest.steamid) return installed diff --git a/lutris/util/steam.py b/lutris/util/steam.py index e429532f9..1cd5969b5 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -267,11 +267,6 @@ class AppManifest: def installdir(self): return self.app_state.get('installdir') - @property - def is_installed(self): - last_owner = self.appstate.get('LastOwner') or '0' - return last_owner != '0' - @property def states(self): """Return the states of a Steam game.""" @@ -283,7 +278,13 @@ class AppManifest: states.append(APP_STATE_FLAGS[index + 1]) return states + def is_installed(self): + last_owner = self.appstate.get('LastOwner') or '0' + return last_owner != '0' + def get_install_path(self): + if not self.installdir: + return install_path = fix_path_case(os.path.join(self.steamapps_path, "common", self.installdir)) if install_path: From 187f54619f9335a44a90f151fb2542bce8046a69 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 14:45:31 -0700 Subject: [PATCH 149/181] Implement SteamWatcher callback + fixes --- lutris/gui/lutriswindow.py | 7 ++++++- lutris/sync.py | 7 +++---- lutris/util/steam.py | 17 +++++++++++++---- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 10db5a711..037b2c608 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -189,7 +189,12 @@ class LutrisWindow(Gtk.Application): self.timer_ids = [GLib.timeout_add(300, self.refresh_status), GLib.timeout_add(10000, self.on_sync_timer)] steamapps_paths = get_steamapps_paths(flat=True) - self.steam_watcher = SteamWatcher(steamapps_paths) + self.steam_watcher = SteamWatcher(steamapps_paths, self.on_steam_game_changed) + + def on_steam_game_changed(self, operation, path): + print "woot woot i'm a callback" + print operation + print path def init_game_store(self): logger.debug("Getting game list") diff --git a/lutris/sync.py b/lutris/sync.py index d5cf78601..3ac0ec9c4 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -1,13 +1,12 @@ """Synchronization of the game library with server and local data.""" import os -import re from lutris import api, config, pga from lutris.runners.steam import steam from lutris.runners.winesteam import winesteam +from lutris.util.steam import get_appmanifests, AppManifest from lutris.util import resources from lutris.util.log import logger -from lutris.util.steam import vdf_parse class Sync(object): @@ -206,9 +205,9 @@ class Sync(object): installed = [] steamapps_paths = runner.get_steamapps_dirs() for steamapps_path in steamapps_paths: - for filename in steam.get_appmanifests(steamapps_path): + for filename in get_appmanifests(steamapps_path): appmanifest_path = os.path.join(steamapps_path, filename) - appmanifest = steam.AppManifest(appmanifest_path) + appmanifest = AppManifest(appmanifest_path) if appmanifest.is_installed(): installed.append(appmanifest.steamid) return installed diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 1cd5969b5..780f21141 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -211,34 +211,44 @@ def get_steamapps_paths(flat=False): class SteamWatchHandler(pyinotify.ProcessEvent): + def __init__(self, callback=None): + self.callback = callback + def process_IN_MODIFY(self, event): path = event.pathname if not path.endswith('.acf'): return logger.info('MODIFY %s', path) + if self.callback: + self.callback('modify', path) def process_IN_CREATE(self, event): path = event.pathname if not path.endswith('.acf'): return logger.info('CREATE %s', path) + if self.callback: + self.callback('create', path) def process_IN_DELETE(self, event): path = event.pathname if not path.endswith('.acf'): return logger.info('DELETE %s', path) + if self.callback: + self.callback('delete', path) class SteamWatcher(threading.Thread): - def __init__(self, steamapps_paths): + def __init__(self, steamapps_paths, callback=None): self.steamapps_paths = steamapps_paths + self.callback = callback super(SteamWatcher, self).__init__() self.start() def run(self): watch_manager = pyinotify.WatchManager() - event_handler = SteamWatchHandler() + event_handler = SteamWatchHandler(self.callback) mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY notifier = pyinotify.Notifier(watch_manager, event_handler) logger.info(self.steamapps_paths) @@ -279,8 +289,7 @@ class AppManifest: return states def is_installed(self): - last_owner = self.appstate.get('LastOwner') or '0' - return last_owner != '0' + return 'Fully Installed' in self.states def get_install_path(self): if not self.installdir: From 3061f8e8cbb5c1175287908a10fb92837a0fa188 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 14:59:31 -0700 Subject: [PATCH 150/181] In add_or_update only generate slug for new games --- lutris/pga.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lutris/pga.py b/lutris/pga.py index 2c48fe15b..06a4e0f1d 100644 --- a/lutris/pga.py +++ b/lutris/pga.py @@ -210,11 +210,11 @@ def add_or_update(name, runner, slug=None, **kwargs): FIXME probably not the desired behavior since it disallows multiple games with the same slug """ - if not slug: - slug = slugify(name) if 'id' in kwargs: game = get_game_by_field(kwargs['id'], 'id') else: + if not slug: + slug = slugify(name) game = get_game_by_field(slug, 'slug') kwargs['name'] = name kwargs['runner'] = runner From 1e79848b199fe59c47a5d3b5295fc4be89685abe Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 15:00:12 -0700 Subject: [PATCH 151/181] Extract mark_as_(un)installed in the steam module --- lutris/sync.py | 36 ++++++++++-------------------------- lutris/util/steam.py | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/lutris/sync.py b/lutris/sync.py index 3ac0ec9c4..7fcc6e944 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -150,32 +150,22 @@ class Sync(object): installed_winesteamapps = self.get_installed_steamapps(winesteamrunner) for game_info in self.library: - slug = game_info['slug'] runner = game_info['runner'] - steamid = game_info['steamid'] + steamid = str(game_info['steamid']) installed_in_steam = steamid in installed_steamapps installed_in_winesteam = steamid in installed_winesteamapps # Set installed if not game_info['installed']: - if not installed_in_steam: # (Linux Steam only) + if installed_in_steam: + runner_name = 'steam' + elif installed_in_winesteam: + runner_name = 'winesteam' + if not game_info['configpath']: + continue + else: continue - logger.debug("Setting %s as installed" % game_info['name']) - config_id = (game_info['configpath'] - or config.make_game_config_id(slug)) - game_id = pga.add_or_update( - name=game_info['name'], - runner='steam', - slug=slug, - installed=1, - configpath=config_id, - ) - game_config = config.LutrisConfig( - runner_slug='steam', - game_config_id=config_id, - ) - game_config.raw_game_config.update({'appid': str(steamid)}) - game_config.save() + game_id = steam.mark_as_installed(steamid, runner_name, game_info) installed.add(game_id) # Set uninstalled @@ -187,13 +177,7 @@ class Sync(object): if runner == 'winesteam' and not winesteamrunner.is_installed(): continue logger.debug("Setting %(name)s (%(steamid)s) as uninstalled", game_info) - - game_id = pga.add_or_update( - name=game_info['name'], - runner='', - slug=game_info['slug'], - installed=0 - ) + game_id = steam.mark_as_uninstalled(game_info) uninstalled.add(game_id) return (installed, uninstalled) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 780f21141..f81e877ce 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -3,9 +3,11 @@ import re import time import threading import pyinotify -from lutris.util.log import logger from collections import OrderedDict +from lutris import pga +from lutris.util.log import logger from lutris.util.system import fix_path_case +from lutris.config import make_game_config_id, LutrisConfig APP_STATE_FLAGS = [ @@ -210,6 +212,37 @@ def get_steamapps_paths(flat=False): return steamapps_paths +def mark_as_installed(steamid, runner_name, game_info): + for key in ['name', 'slug']: + assert game_info[key] + logger.debug("Setting %s as installed" % game_info['name']) + config_id = (game_info['config_path'] or make_game_config_id(game_info['slug'])) + game_id = pga.add_or_update( + name=game_info['name'], + runner=runner_name, + slug=game_info['slug'], + installed=1, + configpath=config_id, + ) + game_config = LutrisConfig( + runner_slug=runner_name, + game_config_id=config_id, + ) + game_config.raw_game_config.update({'appid': steamid}) + game_config.save() + return game_id + + +def mark_as_uninstalled(game_info): + assert 'id' in game_info + game_id = pga.add_or_update( + id=game_info['id'], + runner='', + installed=0 + ) + return game_id + + class SteamWatchHandler(pyinotify.ProcessEvent): def __init__(self, callback=None): self.callback = callback From f27d351766e0dfb9be25781fe82deea5adc3e32b Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 15:32:51 -0700 Subject: [PATCH 152/181] Add db_query function and pga.get_steam_games --- lutris/pga.py | 40 ++++++++++++++++++---------------------- lutris/util/sql.py | 14 ++++++++++++++ lutris/util/steam.py | 1 + 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/lutris/pga.py b/lutris/pga.py index 06a4e0f1d..1370a6d9b 100644 --- a/lutris/pga.py +++ b/lutris/pga.py @@ -145,28 +145,24 @@ def get_table_length(table='games'): def get_games(name_filter=None, filter_installed=False): """Get the list of every game in database.""" - with sql.db_cursor(PGA_DB) as cursor: - query = "select * from games" - params = () - filters = [] - if name_filter: - params = (name_filter, ) - filters.append("name LIKE ?") - if filter_installed: - filters.append("installed = 1") - if filters: - query += " WHERE " + " AND ".join([f for f in filters]) - query += " ORDER BY slug" - rows = cursor.execute(query, params) - results = rows.fetchall() - column_names = [column[0] for column in cursor.description] - game_list = [] - for row in results: - game_info = {} - for index, column in enumerate(column_names): - game_info[column] = row[index] - game_list.append(game_info) - return game_list + query = "select * from games" + params = () + filters = [] + if name_filter: + params = (name_filter, ) + filters.append("name LIKE ?") + if filter_installed: + filters.append("installed = 1") + if filters: + query += " WHERE " + " AND ".join([f for f in filters]) + query += " ORDER BY slug" + return sql.db_query(PGA_DB, query, params) + + +def get_steam_games(): + """Return the games with a SteamID""" + query = "select * from games where steamid is not null and steamid != ''" + return sql.db_query(PGA_DB, query) def get_game_by_field(value, field='slug', all=False): diff --git a/lutris/util/sql.py b/lutris/util/sql.py index 01a896b97..1ad9cb4a8 100644 --- a/lutris/util/sql.py +++ b/lutris/util/sql.py @@ -81,6 +81,20 @@ def db_select(db_path, table, fields=None, condition=None): return results +def db_query(db_path, query, params=()): + with db_cursor(db_path) as cursor: + cursor.execute(query, params) + rows = cursor.fetchall() + column_names = [column[0] for column in cursor.description] + results = [] + for row in rows: + row_data = {} + for index, column in enumerate(column_names): + row_data[column] = row[index] + results.append(row_data) + return results + + def _decode_utf8_values(values_list): """Return a tuple of values with UTF-8 string values being decoded.""" i = 0 diff --git a/lutris/util/steam.py b/lutris/util/steam.py index f81e877ce..da1aed903 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -224,6 +224,7 @@ def mark_as_installed(steamid, runner_name, game_info): installed=1, configpath=config_id, ) + game_config = LutrisConfig( runner_slug=runner_name, game_config_id=config_id, From 4a2c90690f3f650e9865e65cec88a11b9a1bb20e Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 16:18:57 -0700 Subject: [PATCH 153/181] add_or_update doesn't require any mandatory parameters --- lutris/pga.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lutris/pga.py b/lutris/pga.py index 1370a6d9b..8d7e180bc 100644 --- a/lutris/pga.py +++ b/lutris/pga.py @@ -201,26 +201,27 @@ def add_games_bulk(games): return inserted_ids -def add_or_update(name, runner, slug=None, **kwargs): +def add_or_update(**params): """ FIXME probably not the desired behavior since it disallows multiple games with the same slug """ - if 'id' in kwargs: - game = get_game_by_field(kwargs['id'], 'id') + slug = params.get('slug') + name = params.get('name') + id = params.get('id') + assert any([slug, name, id]) + if 'id' in params: + game = get_game_by_field(params['id'], 'id') else: if not slug: slug = slugify(name) game = get_game_by_field(slug, 'slug') - kwargs['name'] = name - kwargs['runner'] = runner - kwargs['slug'] = slug if game: game_id = game['id'] - sql.db_update(PGA_DB, "games", kwargs, ('id', game_id)) + sql.db_update(PGA_DB, "games", params, ('id', game_id)) return game_id else: - return add_game(**kwargs) + return add_game(**params) def delete_game(id): From ebf798049fac8519479d805f911f6005d1413f1c Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 16:31:55 -0700 Subject: [PATCH 154/181] Add steam.sync_with_lutris function --- lutris/gui/lutriswindow.py | 4 +++- lutris/sync.py | 2 +- lutris/util/steam.py | 39 +++++++++++++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 037b2c608..0b76a9780 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -14,7 +14,7 @@ from lutris.util import display, resources from lutris.util.log import logger from lutris.util.jobs import AsyncCall from lutris.util import datapath -from lutris.util.steam import SteamWatcher, get_steamapps_paths +from lutris.util.steam import SteamWatcher, get_steamapps_paths, sync_with_lutris from lutris.gui import dialogs from lutris.gui.sidebar import SidebarTreeView @@ -175,6 +175,8 @@ class LutrisWindow(Gtk.Application): self.init_game_store() + sync_with_lutris() + self.update_runtime() # Connect account and/or sync diff --git a/lutris/sync.py b/lutris/sync.py index 7fcc6e944..4faa49632 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -1,7 +1,7 @@ """Synchronization of the game library with server and local data.""" import os -from lutris import api, config, pga +from lutris import api, pga from lutris.runners.steam import steam from lutris.runners.winesteam import winesteam from lutris.util.steam import get_appmanifests, AppManifest diff --git a/lutris/util/steam.py b/lutris/util/steam.py index da1aed903..320db94e7 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -7,6 +7,7 @@ from collections import OrderedDict from lutris import pga from lutris.util.log import logger from lutris.util.system import fix_path_case +from lutris.util.strings import slugify from lutris.config import make_game_config_id, LutrisConfig @@ -216,8 +217,9 @@ def mark_as_installed(steamid, runner_name, game_info): for key in ['name', 'slug']: assert game_info[key] logger.debug("Setting %s as installed" % game_info['name']) - config_id = (game_info['config_path'] or make_game_config_id(game_info['slug'])) + config_id = (game_info.get('config_path') or make_game_config_id(game_info['slug'])) game_id = pga.add_or_update( + steamid=steamid, name=game_info['name'], runner=runner_name, slug=game_info['slug'], @@ -236,6 +238,8 @@ def mark_as_installed(steamid, runner_name, game_info): def mark_as_uninstalled(game_info): assert 'id' in game_info + assert 'name' in game_info + logger.debug('Setting %s as uninstalled' % game_info['name']) game_id = pga.add_or_update( id=game_info['id'], runner='', @@ -244,6 +248,35 @@ def mark_as_uninstalled(game_info): return game_id +def sync_with_lutris(): + steamapps_paths = get_steamapps_paths() + steam_games_in_lutris = pga.get_steam_games() + steamids_in_lutris = set([str(game['steamid']) for game in steam_games_in_lutris]) + seen_ids = set() + for platform in steamapps_paths: + for steamapps_path in steamapps_paths[platform]: + appmanifests = get_appmanifests(steamapps_path) + for appmanifest_file in appmanifests: + steamid = re.findall(r'(\d+)', appmanifest_file)[0] + seen_ids.add(steamid) + if steamid not in steamids_in_lutris and platform == 'linux': + appmanifest_path = os.path.join(steamapps_path, appmanifest_file) + appmanifest = AppManifest(appmanifest_path) + if appmanifest.is_installed(): + game_info = { + 'name': appmanifest.name, + 'slug': appmanifest.slug, + } + mark_as_installed(steamid, 'steam', game_info) + unavailable_ids = steamids_in_lutris.difference(seen_ids) + for steamid in unavailable_ids: + for game in steam_games_in_lutris: + if str(game['steamid']) == steamid \ + and game['installed'] \ + and game['runner'] in ('steam', 'winesteam'): + mark_as_uninstalled(game) + + class SteamWatchHandler(pyinotify.ProcessEvent): def __init__(self, callback=None): self.callback = callback @@ -307,6 +340,10 @@ class AppManifest: def name(self): return self.app_state.get('name') + @property + def slug(self): + return slugify(self.name) + @property def installdir(self): return self.app_state.get('installdir') From c34db5f04ab214cca7368ca7d288c8aabbc0e284 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 16:36:21 -0700 Subject: [PATCH 155/181] inotify watches shouldn't be recursive --- lutris/util/steam.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 320db94e7..bae14c04c 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -321,7 +321,7 @@ class SteamWatcher(threading.Thread): logger.info(self.steamapps_paths) for steamapp_path in self.steamapps_paths: logger.info('Watching Steam folder %s', steamapp_path) - watch_manager.add_watch(steamapp_path, mask, rec=True) + watch_manager.add_watch(steamapp_path, mask, rec=False) notifier.loop() From 256866a15d6a938ea9fe2ab5b95184be0e68e8b2 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 16:58:44 -0700 Subject: [PATCH 156/181] Add get_platform and get_runner_name in AppManifest --- lutris/util/steam.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index bae14c04c..fb5493398 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -329,8 +329,9 @@ class AppManifest: def __init__(self, appmanifest_path): self.steamapps_path, filename = os.path.split(appmanifest_path) self.steamid = re.findall(r'(\d+)', filename)[0] - with open(appmanifest_path, "r") as appmanifest_file: - self.appmanifest_data = vdf_parse(appmanifest_file, {}) + if os.path.exists(appmanifest_path): + with open(appmanifest_path, "r") as appmanifest_file: + self.appmanifest_data = vdf_parse(appmanifest_file, {}) @property def app_state(self): @@ -369,3 +370,20 @@ class AppManifest: self.installdir)) if install_path: return install_path + + def get_platform(self): + steamapps_paths = get_steamapps_paths() + if self.steamapps_path in steamapps_paths['linux']: + return 'linux' + elif self.steamapps_path in steamapps_paths['windows']: + return 'windows' + else: + raise ValueError("Can't find %s in %s" + % (self.steamapps_path, steamapps_paths)) + + def get_runner_name(self): + platform = self.get_platform() + if platform == 'linux': + return 'steam' + else: + return 'winesteam' From 59426be9d5a4fc98956890be1e2873110afc53dd Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 17:14:09 -0700 Subject: [PATCH 157/181] Remove all sync_local related code and setup callbacks --- lutris/gui/lutriswindow.py | 53 ++++++++++-------------------- lutris/sync.py | 67 ++------------------------------------ lutris/util/steam.py | 6 ++-- 3 files changed, 23 insertions(+), 103 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 0b76a9780..40bea94ce 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -14,7 +14,7 @@ from lutris.util import display, resources from lutris.util.log import logger from lutris.util.jobs import AsyncCall from lutris.util import datapath -from lutris.util.steam import SteamWatcher, get_steamapps_paths, sync_with_lutris +from lutris.util import steam from lutris.gui import dialogs from lutris.gui.sidebar import SidebarTreeView @@ -173,9 +173,11 @@ class LutrisWindow(Gtk.Application): pga_menuitem = self.builder.get_object('pga_menuitem') pga_menuitem.hide() - self.init_game_store() + # Sync local lutris library with current Steam games before setting up + # view + steam.sync_with_lutris() - sync_with_lutris() + self.init_game_store() self.update_runtime() @@ -188,15 +190,17 @@ class LutrisWindow(Gtk.Application): self.sync_library() # Timers - self.timer_ids = [GLib.timeout_add(300, self.refresh_status), - GLib.timeout_add(10000, self.on_sync_timer)] - steamapps_paths = get_steamapps_paths(flat=True) - self.steam_watcher = SteamWatcher(steamapps_paths, self.on_steam_game_changed) + self.timer_ids = [GLib.timeout_add(300, self.refresh_status)] + steamapps_paths = steam.get_steamapps_paths(flat=True) + self.steam_watcher = steam.SteamWatcher(steamapps_paths, + self.on_steam_game_changed) def on_steam_game_changed(self, operation, path): - print "woot woot i'm a callback" - print operation - print path + appmanifest = steam.AppManifest(path) + if operation == 'DELETE': + print "Uninstalling", appmanifest.steamid + elif operation in ('MODIFY', 'CREATE'): + print appmanifest.is_installed() def init_game_store(self): logger.debug("Getting game list") @@ -295,31 +299,22 @@ class LutrisWindow(Gtk.Application): """Synchronize games with local stuff and server.""" def update_gui(result, error): if result: - added, updated, installed, uninstalled = result + added, updated = result # , installed, uninstalled = result self.switch_splash_screen() self.game_store.fill_store(added) - GLib.idle_add(self.update_existing_games, - added, updated, installed, uninstalled, True) + GLib.idle_add(self.update_existing_games, added, updated, True) else: logger.error("No results returned when syncing the library") self.set_status("Syncing library") AsyncCall(Sync().sync_all, update_gui) - def update_existing_games(self, added, updated, installed, uninstalled, - first_run=False): + def update_existing_games(self, added, updated, first_run=False): + # , installed, uninstalled, first_run=False): for game_id in updated.difference(added): self.view.update_row(pga.get_game_by_field(game_id, 'id')) - for game_id in installed.difference(added): - if not self.view.get_row_by_id(game_id): - self.view.add_game(game_id) - self.view.set_installed(Game(game_id)) - - for game_id in uninstalled.difference(added): - self.view.set_uninstalled(game_id) - if first_run: icons_sync = AsyncCall(self.sync_icons, None, stoppable=True) self.threads_stoppers.append(icons_sync.stop_request.set) @@ -419,18 +414,6 @@ class LutrisWindow(Gtk.Application): """Callback when Synchronize Library is activated.""" self.sync_library() - def on_sync_timer(self): - if (not self.running_game - or self.running_game.state == Game.STATE_STOPPED): - - def update_gui(result, error): - if result: - self.update_existing_games(set(), set(), *result) - else: - logger.error('No results while syncing local Steam database') - AsyncCall(Sync().sync_local, update_gui) - return True - def on_resize(self, widget, *args): """WTF is this doing?""" self.window_size = widget.get_size() diff --git a/lutris/sync.py b/lutris/sync.py index 4faa49632..691eff3f9 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -4,7 +4,7 @@ import os from lutris import api, pga from lutris.runners.steam import steam from lutris.runners.winesteam import winesteam -from lutris.util.steam import get_appmanifests, AppManifest +from lutris.util.steam import get_appmanifests, AppManifest, mark_as_installed, mark_as_uninstalled from lutris.util import resources from lutris.util.log import logger @@ -15,8 +15,7 @@ class Sync(object): def sync_all(self): added, updated = self.sync_from_remote() - installed, uninstalled = self.sync_local() - return added, updated, installed, uninstalled + return added, updated def sync_local(self): """Synchronize games state with local third parties.""" @@ -133,65 +132,3 @@ class Sync(object): logger.debug("%d games updated", len(updated)) return updated - - def sync_steam_local(self): - """Sync Steam games in library with Steam and Wine Steam - - FIXME: This is the guilty method that causes grief to everyone, most of it should - probably disappear - """ - steamrunner = steam() - winesteamrunner = winesteam() - installed = set() - uninstalled = set() - - # Get installed steamapps - installed_steamapps = self.get_installed_steamapps(steamrunner) - installed_winesteamapps = self.get_installed_steamapps(winesteamrunner) - - for game_info in self.library: - runner = game_info['runner'] - steamid = str(game_info['steamid']) - installed_in_steam = steamid in installed_steamapps - installed_in_winesteam = steamid in installed_winesteamapps - - # Set installed - if not game_info['installed']: - if installed_in_steam: - runner_name = 'steam' - elif installed_in_winesteam: - runner_name = 'winesteam' - if not game_info['configpath']: - continue - else: - continue - game_id = steam.mark_as_installed(steamid, runner_name, game_info) - installed.add(game_id) - - # Set uninstalled - elif not (installed_in_steam or installed_in_winesteam): - if runner not in ['steam', 'winesteam']: - continue - if runner == 'steam' and not steamrunner.is_installed(): - continue - if runner == 'winesteam' and not winesteamrunner.is_installed(): - continue - logger.debug("Setting %(name)s (%(steamid)s) as uninstalled", game_info) - game_id = steam.mark_as_uninstalled(game_info) - uninstalled.add(game_id) - return (installed, uninstalled) - - @staticmethod - def get_installed_steamapps(runner): - """Return a list of appIDs of the installed Steam games.""" - if not runner.is_installed(): - return [] - installed = [] - steamapps_paths = runner.get_steamapps_dirs() - for steamapps_path in steamapps_paths: - for filename in get_appmanifests(steamapps_path): - appmanifest_path = os.path.join(steamapps_path, filename) - appmanifest = AppManifest(appmanifest_path) - if appmanifest.is_installed(): - installed.append(appmanifest.steamid) - return installed diff --git a/lutris/util/steam.py b/lutris/util/steam.py index fb5493398..99286e15f 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -287,7 +287,7 @@ class SteamWatchHandler(pyinotify.ProcessEvent): return logger.info('MODIFY %s', path) if self.callback: - self.callback('modify', path) + self.callback('MODIFY', path) def process_IN_CREATE(self, event): path = event.pathname @@ -295,7 +295,7 @@ class SteamWatchHandler(pyinotify.ProcessEvent): return logger.info('CREATE %s', path) if self.callback: - self.callback('create', path) + self.callback('CREATE', path) def process_IN_DELETE(self, event): path = event.pathname @@ -303,7 +303,7 @@ class SteamWatchHandler(pyinotify.ProcessEvent): return logger.info('DELETE %s', path) if self.callback: - self.callback('delete', path) + self.callback('DELETE', path) class SteamWatcher(threading.Thread): From 00a717b5a97b52603b8bd385999b92d6fe16528e Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 17:15:22 -0700 Subject: [PATCH 158/181] Remove all steam related imports from the sync module --- lutris/sync.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lutris/sync.py b/lutris/sync.py index 691eff3f9..6eef2f477 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -1,10 +1,5 @@ """Synchronization of the game library with server and local data.""" -import os - from lutris import api, pga -from lutris.runners.steam import steam -from lutris.runners.winesteam import winesteam -from lutris.util.steam import get_appmanifests, AppManifest, mark_as_installed, mark_as_uninstalled from lutris.util import resources from lutris.util.log import logger From ba30966f56b63bca71a98eea5297fba2b507f27e Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 17:18:59 -0700 Subject: [PATCH 159/181] Actually remove sync_local --- lutris/sync.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lutris/sync.py b/lutris/sync.py index 6eef2f477..2e221f807 100644 --- a/lutris/sync.py +++ b/lutris/sync.py @@ -12,11 +12,6 @@ class Sync(object): added, updated = self.sync_from_remote() return added, updated - def sync_local(self): - """Synchronize games state with local third parties.""" - installed, uninstalled = self.sync_steam_local() - return installed, uninstalled - def sync_from_remote(self): """Synchronize from remote to local library. From 9c7dab1e78938e501db20b44bdd9576257e1b94d Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 17:35:12 -0700 Subject: [PATCH 160/181] Implement Steam game removal with inotify --- lutris/gui/lutriswindow.py | 8 +++++++- lutris/pga.py | 2 +- lutris/util/steam.py | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 40bea94ce..f34171693 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -198,7 +198,13 @@ class LutrisWindow(Gtk.Application): def on_steam_game_changed(self, operation, path): appmanifest = steam.AppManifest(path) if operation == 'DELETE': - print "Uninstalling", appmanifest.steamid + runner_name = appmanifest.get_runner_name() + games = pga.get_game_by_field(appmanifest.steamid, field='steamid', all=True) + for game in games: + if game['runner'] == runner_name: + steam.mark_as_uninstalled(game) + self.remove_game_from_view(game['id']) + break elif operation in ('MODIFY', 'CREATE'): print appmanifest.is_installed() diff --git a/lutris/pga.py b/lutris/pga.py index 8d7e180bc..e3559a6a4 100644 --- a/lutris/pga.py +++ b/lutris/pga.py @@ -167,7 +167,7 @@ def get_steam_games(): def get_game_by_field(value, field='slug', all=False): """Query a game based on a database field""" - if field not in ('slug', 'installer_slug', 'id', 'configpath'): + if field not in ('slug', 'installer_slug', 'id', 'configpath', 'steamid'): raise ValueError("Can't query by field '%s'" % field) game_result = sql.db_select(PGA_DB, "games", condition=(field, value)) if game_result: diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 99286e15f..4a2c66e6e 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -216,7 +216,7 @@ def get_steamapps_paths(flat=False): def mark_as_installed(steamid, runner_name, game_info): for key in ['name', 'slug']: assert game_info[key] - logger.debug("Setting %s as installed" % game_info['name']) + logger.info("Setting %s as installed" % game_info['name']) config_id = (game_info.get('config_path') or make_game_config_id(game_info['slug'])) game_id = pga.add_or_update( steamid=steamid, @@ -239,7 +239,7 @@ def mark_as_installed(steamid, runner_name, game_info): def mark_as_uninstalled(game_info): assert 'id' in game_info assert 'name' in game_info - logger.debug('Setting %s as uninstalled' % game_info['name']) + logger.info('Setting %s as uninstalled' % game_info['name']) game_id = pga.add_or_update( id=game_info['id'], runner='', From 9b337b6d9da76a77ade642dbe8a180463c20e45f Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 17:45:15 -0700 Subject: [PATCH 161/181] Implement adding Steam games with inotify --- lutris/gui/lutriswindow.py | 22 +++++++++++++++++++--- lutris/util/steam.py | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index f34171693..66ee09d0e 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -197,16 +197,32 @@ class LutrisWindow(Gtk.Application): def on_steam_game_changed(self, operation, path): appmanifest = steam.AppManifest(path) + runner_name = appmanifest.get_runner_name() + games = pga.get_game_by_field(appmanifest.steamid, field='steamid', all=True) if operation == 'DELETE': - runner_name = appmanifest.get_runner_name() - games = pga.get_game_by_field(appmanifest.steamid, field='steamid', all=True) for game in games: if game['runner'] == runner_name: steam.mark_as_uninstalled(game) self.remove_game_from_view(game['id']) break elif operation in ('MODIFY', 'CREATE'): - print appmanifest.is_installed() + if not appmanifest.is_installed(): + return + if runner_name == 'windows': + return + game_info = None + for game in games: + if game['installed'] == 0: + game_info = game + if not game_info: + game_info = { + 'name': appmanifest.name, + 'slug': appmanifest.slug, + } + game_id = steam.mark_as_installed(appmanifest.steamid, + runner_name, + game_info) + self.add_game_to_view(game_id) def init_game_store(self): logger.debug("Getting game list") diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 4a2c66e6e..007e821b0 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -219,7 +219,7 @@ def mark_as_installed(steamid, runner_name, game_info): logger.info("Setting %s as installed" % game_info['name']) config_id = (game_info.get('config_path') or make_game_config_id(game_info['slug'])) game_id = pga.add_or_update( - steamid=steamid, + steamid=int(steamid), name=game_info['name'], runner=runner_name, slug=game_info['slug'], From 3488b514c2ad16296c5f3a13a04a7571fcc16dfe Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 17:46:05 -0700 Subject: [PATCH 162/181] Remove logging messages from SteamWatchHandler --- lutris/util/steam.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 007e821b0..bb195e5a4 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -285,7 +285,6 @@ class SteamWatchHandler(pyinotify.ProcessEvent): path = event.pathname if not path.endswith('.acf'): return - logger.info('MODIFY %s', path) if self.callback: self.callback('MODIFY', path) @@ -293,7 +292,6 @@ class SteamWatchHandler(pyinotify.ProcessEvent): path = event.pathname if not path.endswith('.acf'): return - logger.info('CREATE %s', path) if self.callback: self.callback('CREATE', path) @@ -301,7 +299,6 @@ class SteamWatchHandler(pyinotify.ProcessEvent): path = event.pathname if not path.endswith('.acf'): return - logger.info('DELETE %s', path) if self.callback: self.callback('DELETE', path) From 5a270af1c61a1ac3b4017181c65989458c24e8f0 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 18:08:04 -0700 Subject: [PATCH 163/181] Simplify SteamWatchHandler --- lutris/util/steam.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index bb195e5a4..2cd68e549 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -278,29 +278,22 @@ def sync_with_lutris(): class SteamWatchHandler(pyinotify.ProcessEvent): - def __init__(self, callback=None): + def __init__(self, callback): self.callback = callback def process_IN_MODIFY(self, event): - path = event.pathname - if not path.endswith('.acf'): - return - if self.callback: - self.callback('MODIFY', path) + self.process_event('MODIFY', event.pathname) def process_IN_CREATE(self, event): - path = event.pathname - if not path.endswith('.acf'): - return - if self.callback: - self.callback('CREATE', path) + self.process_event('CREATE', event.pathname) def process_IN_DELETE(self, event): - path = event.pathname + self.process_event('DELETE', event.pathname) + + def process_event(self, event_type, path): if not path.endswith('.acf'): return - if self.callback: - self.callback('DELETE', path) + self.callback(event_type, path) class SteamWatcher(threading.Thread): From 91a0eb4889a478e5ac9d33aefa6113cebf64df70 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 18:13:19 -0700 Subject: [PATCH 164/181] Add python-pyinotify to dependencies --- debian/control | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control b/debian/control index f11897a8b..da1d0d80c 100644 --- a/debian/control +++ b/debian/control @@ -21,6 +21,7 @@ Depends: ${misc:Depends}, python-yaml, python-dbus, python-gi, + python-pyinotify, gir1.2-gtk-3.0, xdg-user-dirs, python-xdg, From 8b637dfe62fcd9ee0286a91d4ae77a29872e101a Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 18:16:22 -0700 Subject: [PATCH 165/181] Make python-pyinotify optional --- lutris/util/steam.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 2cd68e549..056ac500f 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -2,7 +2,10 @@ import os import re import time import threading -import pyinotify +try: + import pyinotify +except ImportError: + pyinotify = None from collections import OrderedDict from lutris import pga from lutris.util.log import logger @@ -298,10 +301,14 @@ class SteamWatchHandler(pyinotify.ProcessEvent): class SteamWatcher(threading.Thread): def __init__(self, steamapps_paths, callback=None): - self.steamapps_paths = steamapps_paths - self.callback = callback - super(SteamWatcher, self).__init__() - self.start() + if not pyinotify: + logger.error("pyinotify is not installed, " + "Lutris won't keep track of steam games") + else: + self.steamapps_paths = steamapps_paths + self.callback = callback + super(SteamWatcher, self).__init__() + self.start() def run(self): watch_manager = pyinotify.WatchManager() From 28b7173c39c2f7415e5f8727b406deaa878a56db Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 18:18:29 -0700 Subject: [PATCH 166/181] ProcessEvent might not be available --- lutris/util/steam.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 056ac500f..ee625f611 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -4,8 +4,10 @@ import time import threading try: import pyinotify + from pyinotify import ProcessEvent except ImportError: pyinotify = None + ProcessEvent = object from collections import OrderedDict from lutris import pga from lutris.util.log import logger @@ -280,7 +282,7 @@ def sync_with_lutris(): mark_as_uninstalled(game) -class SteamWatchHandler(pyinotify.ProcessEvent): +class SteamWatchHandler(ProcessEvent): def __init__(self, callback): self.callback = callback From c1dd6ffc286b73bb16e00ada7c8592d9e56b23f5 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 18:25:42 -0700 Subject: [PATCH 167/181] steam.sync_with_lutris should also reinstall previously installed games --- lutris/util/steam.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index ee625f611..ee62e9a4d 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -264,6 +264,7 @@ def sync_with_lutris(): for appmanifest_file in appmanifests: steamid = re.findall(r'(\d+)', appmanifest_file)[0] seen_ids.add(steamid) + game_info = None if steamid not in steamids_in_lutris and platform == 'linux': appmanifest_path = os.path.join(steamapps_path, appmanifest_file) appmanifest = AppManifest(appmanifest_path) @@ -273,6 +274,13 @@ def sync_with_lutris(): 'slug': appmanifest.slug, } mark_as_installed(steamid, 'steam', game_info) + else: + for game in steam_games_in_lutris: + if str(game['steamid']) == steamid and not game['installed']: + game_info = game + break + if game_info: + mark_as_installed(steamid, 'steam', game_info) unavailable_ids = steamids_in_lutris.difference(seen_ids) for steamid in unavailable_ids: for game in steam_games_in_lutris: From 1419e231bdba4f7be8c12184ad185203b2c74e96 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 18:30:55 -0700 Subject: [PATCH 168/181] Use the correct runner for steam game re-installation --- lutris/util/steam.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index ee62e9a4d..c7631f5f9 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -280,7 +280,11 @@ def sync_with_lutris(): game_info = game break if game_info: - mark_as_installed(steamid, 'steam', game_info) + appmanifest_path = os.path.join(steamapps_path, appmanifest_file) + appmanifest = AppManifest(appmanifest_path) + if appmanifest.is_installed(): + runner_name = appmanifest.get_runner_name() + mark_as_installed(steamid, runner_name, game_info) unavailable_ids = steamids_in_lutris.difference(seen_ids) for steamid in unavailable_ids: for game in steam_games_in_lutris: From dfe52768c610c0561c4ea2bf97d2139a7e8ab87f Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 18:37:40 -0700 Subject: [PATCH 169/181] Add some logging, remove some logging --- lutris/gui/lutriswindow.py | 3 +++ lutris/util/steam.py | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index 66ee09d0e..ac80cd447 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -444,12 +444,15 @@ class LutrisWindow(Gtk.Application): """Signal for window close.""" # Stop cancellable running threads for stopper in self.threads_stoppers: + logger.debug("Stopping %s", stopper) stopper() if self.running_game: + logger.info("%s is still running, stopping it", self.running_game.name) self.running_game.stop() if self.service: + logger.debug('Stopping service') self.service.stop() # Save settings diff --git a/lutris/util/steam.py b/lutris/util/steam.py index c7631f5f9..420bb173f 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -329,7 +329,6 @@ class SteamWatcher(threading.Thread): event_handler = SteamWatchHandler(self.callback) mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY notifier = pyinotify.Notifier(watch_manager, event_handler) - logger.info(self.steamapps_paths) for steamapp_path in self.steamapps_paths: logger.info('Watching Steam folder %s', steamapp_path) watch_manager.add_watch(steamapp_path, mask, rec=False) From 03e5664b5c3a0742365426d2559dfeb9ad0f4e9c Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 19:21:53 -0700 Subject: [PATCH 170/181] Make SteamWatcher stoppable --- lutris/gui/lutriswindow.py | 1 + lutris/util/steam.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index ac80cd447..b3a3207c5 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -446,6 +446,7 @@ class LutrisWindow(Gtk.Application): for stopper in self.threads_stoppers: logger.debug("Stopping %s", stopper) stopper() + self.steam_watcher.stop() if self.running_game: logger.info("%s is still running, stopping it", self.running_game.name) diff --git a/lutris/util/steam.py b/lutris/util/steam.py index 420bb173f..9acf36cb6 100644 --- a/lutris/util/steam.py +++ b/lutris/util/steam.py @@ -315,6 +315,7 @@ class SteamWatchHandler(ProcessEvent): class SteamWatcher(threading.Thread): def __init__(self, steamapps_paths, callback=None): + self.notifier = None if not pyinotify: logger.error("pyinotify is not installed, " "Lutris won't keep track of steam games") @@ -322,17 +323,23 @@ class SteamWatcher(threading.Thread): self.steamapps_paths = steamapps_paths self.callback = callback super(SteamWatcher, self).__init__() + self.daemon = True self.start() def run(self): watch_manager = pyinotify.WatchManager() event_handler = SteamWatchHandler(self.callback) mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY - notifier = pyinotify.Notifier(watch_manager, event_handler) + self.notifier = pyinotify.Notifier(watch_manager, event_handler) for steamapp_path in self.steamapps_paths: logger.info('Watching Steam folder %s', steamapp_path) watch_manager.add_watch(steamapp_path, mask, rec=False) - notifier.loop() + self.notifier.loop() + + def stop(self): + if self.notifier: + self.notifier.stop() + print self.notifier class AppManifest: From 7bcbbf1c527372b681cdd29685c5aae78df9d217 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 19:23:17 -0700 Subject: [PATCH 171/181] Won't hurt to make LutrisThread a daemon thread as well (or will it?) --- lutris/thread.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lutris/thread.py b/lutris/thread.py index 5ea950475..376ef4f0c 100644 --- a/lutris/thread.py +++ b/lutris/thread.py @@ -42,6 +42,7 @@ class LutrisThread(threading.Thread): self.max_cycles_without_children = 15 self.startup_time = time.time() self.monitoring_started = False + self.daemon = True if cwd: self.cwd = cwd From 2fdca6fb8d27ecf3ba2756c0f48439553f691b7c Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 19:25:01 -0700 Subject: [PATCH 172/181] And while we're at it, make it the default for AsyncCall --- lutris/util/jobs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lutris/util/jobs.py b/lutris/util/jobs.py index 2b238049b..e521fc295 100644 --- a/lutris/util/jobs.py +++ b/lutris/util/jobs.py @@ -17,7 +17,7 @@ class AsyncCall(threading.Thread): kwargs=kwargs) self.function = function self.on_done = on_done if on_done else lambda r, e: None - self.daemon = kwargs.pop('daemon', False) + self.daemon = kwargs.pop('daemon', True) self.start() From 3e1688743093b8b23df22aec098f51a59db6012c Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 20:21:30 -0700 Subject: [PATCH 173/181] Make WineSteam installation blocking --- lutris/runners/wine.py | 4 ++-- lutris/runners/winesteam.py | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lutris/runners/wine.py b/lutris/runners/wine.py index 04b31c453..e1a091421 100644 --- a/lutris/runners/wine.py +++ b/lutris/runners/wine.py @@ -591,12 +591,12 @@ class wine(Runner): return False @classmethod - def msi_exec(cls, msi_file, quiet=False, prefix=None, wine_path=None): + def msi_exec(cls, msi_file, quiet=False, prefix=None, wine_path=None, working_dir=None, blocking=False): msi_args = "/i %s" % msi_file if quiet: msi_args += " /q" return wineexec("msiexec", args=msi_args, prefix=prefix, - wine_path=wine_path) + wine_path=wine_path, working_dir=working_dir, blocking=blocking) def run_winecfg(self, *args): winecfg(wine_path=self.get_executable(), prefix=self.prefix_path, diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index 7a5207946..65f76f7d7 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -225,8 +225,12 @@ class winesteam(wine.wine): def on_steam_downloaded(*args): prefix = self.get_or_create_default_prefix() - self.msi_exec(installer_path, quiet=True, prefix=prefix, - wine_path=self.get_executable()) + self.msi_exec(installer_path, + quiet=True, + prefix=prefix, + wine_path=self.get_executable(), + working_dir="/tmp", + blocking=True) if callback: callback() From 59edf1fe1a84d0319c98196f841f07856ab4f4c4 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 20:21:54 -0700 Subject: [PATCH 174/181] Check that appids are passed to steam commands --- lutris/runners/winesteam.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lutris/runners/winesteam.py b/lutris/runners/winesteam.py index 65f76f7d7..00ef736d1 100644 --- a/lutris/runners/winesteam.py +++ b/lutris/runners/winesteam.py @@ -328,10 +328,14 @@ class winesteam(wine.wine): return default_prefix def install_game(self, appid, generate_acf=False): + if not appid: + raise ValueError("Missing appid in winesteam.install_game") command = self.launch_args + ["steam://install/%s" % appid] subprocess.Popen(command, env=self.get_env()) def validate_game(self, appid): + if not appid: + raise ValueError("Missing appid in winesteam.validate_game") command = self.launch_args + ["steam://validate/%s" % appid] subprocess.Popen(command, env=self.get_env()) From 58b6528df30d9d04a30ef82bab10c5c2b4cb1883 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 21:06:40 -0700 Subject: [PATCH 175/181] Check that the LutrisThread has a game_process in watch_children --- lutris/thread.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lutris/thread.py b/lutris/thread.py index 376ef4f0c..a80037923 100644 --- a/lutris/thread.py +++ b/lutris/thread.py @@ -148,6 +148,9 @@ class LutrisThread(threading.Thread): def watch_children(self): """Poke at the running process(es).""" + if not self.game_process: + logger.error('No game process available') + return False process = Process(self.rootpid) num_children = 0 num_watched_children = 0 From 46d2dd4e71f50e592c8b65878238e570120356fb Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 21:30:11 -0700 Subject: [PATCH 176/181] Make the dark theme an option --- lutris/gui/lutriswindow.py | 19 ++++++++++++++++--- share/lutris/ui/LutrisWindow.ui | 11 +++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lutris/gui/lutriswindow.py b/lutris/gui/lutriswindow.py index b3a3207c5..92bc31909 100644 --- a/lutris/gui/lutriswindow.py +++ b/lutris/gui/lutriswindow.py @@ -78,9 +78,11 @@ class LutrisWindow(Gtk.Application): self.sidebar_visible = \ settings.read_setting('sidebar_visible') in ['true', None] - # Set GTK to prefer dark theme - gtksettings = Gtk.Settings.get_default() - gtksettings.set_property("gtk-application-prefer-dark-theme", True) + # Set theme to dark if set in the settings + dark_theme_menuitem = self.builder.get_object('dark_theme_menuitem') + use_dark_theme = settings.read_setting('dark_theme') == 'true' + dark_theme_menuitem.set_active(use_dark_theme) + self.set_dark_theme(use_dark_theme) # Load view logger.debug("Loading view") @@ -224,6 +226,10 @@ class LutrisWindow(Gtk.Application): game_info) self.add_game_to_view(game_id) + def set_dark_theme(self, is_dark): + gtksettings = Gtk.Settings.get_default() + gtksettings.set_property("gtk-application-prefer-dark-theme", is_dark) + def init_game_store(self): logger.debug("Getting game list") game_list = get_game_list() @@ -386,6 +392,13 @@ class LutrisWindow(Gtk.Application): # Callbacks # --------- + def on_dark_theme_toggled(self, widget): + use_dark_theme = widget.get_active() + setting_value = 'true' if use_dark_theme else 'false' + logger.debug("Dark theme now %s", setting_value) + settings.write_setting('dark_theme', setting_value) + self.set_dark_theme(use_dark_theme) + def on_clear_search(self, widget, icon_pos, event): if icon_pos == Gtk.EntryIconPosition.SECONDARY: widget.set_text('') diff --git a/share/lutris/ui/LutrisWindow.ui b/share/lutris/ui/LutrisWindow.ui index defb7dc3d..011a2fe77 100644 --- a/share/lutris/ui/LutrisWindow.ui +++ b/share/lutris/ui/LutrisWindow.ui @@ -238,6 +238,15 @@ + + + True + False + Use _dark theme + True + + + True @@ -473,6 +482,7 @@ False Grid view view_grid_symbolic + 0.5 True False @@ -490,6 +500,7 @@ False List view view_list_symbolic + 0.5 True False switch_grid_view_btn From dd289c6032fa1e69930845336b7518c824004a81 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 22:09:49 -0700 Subject: [PATCH 177/181] Catch OSErrors when launching games --- lutris/game.py | 5 +++++ lutris/thread.py | 12 +++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lutris/game.py b/lutris/game.py index cba7561d5..96503b425 100644 --- a/lutris/game.py +++ b/lutris/game.py @@ -318,6 +318,11 @@ class Game(object): def beat(self): """Watch the game's process(es).""" + if self.game_thread.error: + dialogs.ErrorDialog("Error lauching the game:\n" + + self.game_thread.error) + self.on_game_quit() + return False self.game_log = self.game_thread.stdout killswitch_engage = self.killswitch and \ not os.path.exists(self.killswitch) diff --git a/lutris/thread.py b/lutris/thread.py index a80037923..342c54516 100644 --- a/lutris/thread.py +++ b/lutris/thread.py @@ -43,6 +43,7 @@ class LutrisThread(threading.Thread): self.startup_time = time.time() self.monitoring_started = False self.daemon = True + self.error = None if cwd: self.cwd = cwd @@ -78,6 +79,8 @@ class LutrisThread(threading.Thread): env = os.environ.copy() env.update(self.env) self.game_process = self.execute_process(self.command, env) + if not self.game_process: + return for line in iter(self.game_process.stdout.readline, ''): self.stdout += line if self.debug_output: @@ -106,9 +109,12 @@ class LutrisThread(threading.Thread): self.game_process = self.execute_process([self.terminal, '-e', file_path]) def execute_process(self, command, env=None): - return subprocess.Popen(command, bufsize=1, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - cwd=self.cwd, env=env) + try: + return subprocess.Popen(command, bufsize=1, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + cwd=self.cwd, env=env) + except OSError as ex: + self.error = ex.strerror def iter_children(self, process, topdown=True, first=True): if self.runner and self.runner.name.startswith('wine') and first: From f9b83846da0ccae6c3915024e3a536dc3c450e1c Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 23:26:07 -0700 Subject: [PATCH 178/181] Rename the method that asks for a disc to ask_for_disc --- lutris/gui/installgamedialog.py | 2 +- lutris/installer/commands.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lutris/gui/installgamedialog.py b/lutris/gui/installgamedialog.py index 2e9c23163..cfbddaf34 100644 --- a/lutris/gui/installgamedialog.py +++ b/lutris/gui/installgamedialog.py @@ -332,7 +332,7 @@ class InstallerDialog(Gtk.Window): # "Commands" stage # ---------------- - def wait_for_user_action(self, message, callback, data=None): + def ask_for_disc(self, message, callback, data=None): """Ask the user to do something.""" time.sleep(0.3) self.clean_widgets() diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index 05dacfaea..c2cbdfa30 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -149,7 +149,7 @@ class CommandsMixin(object): ) if self.runner == 'wine': GLib.idle_add(self.parent.eject_button.show) - GLib.idle_add(self.parent.wait_for_user_action, message, + GLib.idle_add(self.parent.ask_for_disc, message, self._find_matching_disc, requires) return 'STOP' From e3173a328b0b5baba86cfce4fef64d368e415b0a Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Wed, 3 Aug 2016 23:58:17 -0700 Subject: [PATCH 179/181] Add a browse button to locate CDROM mount points --- lutris/gui/dialogs.py | 5 ++-- lutris/gui/installgamedialog.py | 41 ++++++++++++++++++++++++++------- lutris/installer/commands.py | 17 ++++++++------ lutris/util/disks.py | 10 ++++---- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/lutris/gui/dialogs.py b/lutris/gui/dialogs.py index 1aa07e0a0..8c27ee38b 100644 --- a/lutris/gui/dialogs.py +++ b/lutris/gui/dialogs.py @@ -77,12 +77,13 @@ class QuestionDialog(Gtk.MessageDialog): class DirectoryDialog(Gtk.FileChooserDialog): """Ask the user to select a directory.""" - def __init__(self, message): + def __init__(self, message, parent=None): super(DirectoryDialog, self).__init__( title=message, action=Gtk.FileChooserAction.SELECT_FOLDER, buttons=('_Cancel', Gtk.ResponseType.CLOSE, - '_OK', Gtk.ResponseType.OK) + '_OK', Gtk.ResponseType.OK), + parent=parent ) self.result = self.run() self.folder = self.get_current_folder() diff --git a/lutris/gui/installgamedialog.py b/lutris/gui/installgamedialog.py index cfbddaf34..437b333fc 100644 --- a/lutris/gui/installgamedialog.py +++ b/lutris/gui/installgamedialog.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- import os import time from gi.repository import Gtk, Pango @@ -8,7 +9,7 @@ from lutris import pga, settings, shortcuts from lutris.installer import interpreter from lutris.game import Game from lutris.gui.config_dialogs import AddGameDialog -from lutris.gui.dialogs import NoInstallerDialog +from lutris.gui.dialogs import NoInstallerDialog, DirectoryDialog from lutris.gui.widgets import DownloadProgressBox, FileChooserEntry from lutris.util import display, jobs from lutris.util.log import logger @@ -332,19 +333,43 @@ class InstallerDialog(Gtk.Window): # "Commands" stage # ---------------- - def ask_for_disc(self, message, callback, data=None): - """Ask the user to do something.""" + def ask_for_disc(self, message, callback, requires): + """Ask the user to do insert a CD-ROM.""" time.sleep(0.3) self.clean_widgets() label = Gtk.Label(label=message) label.set_use_markup(True) self.widget_box.add(label) label.show() - button = Gtk.Button(label='Ok') - button.connect('clicked', callback, data) - self.widget_box.add(button) - button.grab_focus() - button.show() + + buttons_box = Gtk.Box() + buttons_box.show() + buttons_box.set_margin_top(40) + buttons_box.set_margin_bottom(40) + self.widget_box.add(buttons_box) + + autodetect_button = Gtk.Button(label='Autodetect') + autodetect_button.connect('clicked', callback, requires) + autodetect_button.grab_focus() + autodetect_button.show() + buttons_box.pack_start(autodetect_button, True, True, 40) + + browse_button = Gtk.Button(label='Browse…') + callback_data = { + 'callback': callback, + 'requires': requires + } + browse_button.connect('clicked', self.on_browse_clicked, callback_data) + browse_button.show() + buttons_box.pack_start(browse_button, True, True, 40) + + def on_browse_clicked(self, widget, callback_data): + dialog = DirectoryDialog("Select the folder where the disc is mounted", + parent=self) + folder = dialog.folder + callback = callback_data['callback'] + requires = callback_data['requires'] + callback(widget, requires, folder) def on_eject_clicked(self, widget, data=None): self.interpreter.eject_wine_disc() diff --git a/lutris/installer/commands.py b/lutris/installer/commands.py index c2cbdfa30..aa633cbe8 100644 --- a/lutris/installer/commands.py +++ b/lutris/installer/commands.py @@ -140,7 +140,8 @@ class CommandsMixin(object): requires = data.get('requires') message = data.get( 'message', - "Insert game disc or mount disk image and click OK." + "Insert or mount game disc and click Autodetect or\n" + "use Browse if the disc is mounted on a non standard location." ) message += ( "\n\nLutris is looking for a mounted disk drive or image \n" @@ -153,15 +154,17 @@ class CommandsMixin(object): self._find_matching_disc, requires) return 'STOP' - def _find_matching_disc(self, widget, requires): - drives = disks.get_mounted_discs() + def _find_matching_disc(self, widget, requires, extra_path=None): + if extra_path: + drives = [extra_path] + else: + drives = disks.get_mounted_discs() for drive in drives: - mount_point = drive.get_root().get_path() - required_abspath = os.path.join(mount_point, requires) + required_abspath = os.path.join(drive, requires) required_abspath = system.fix_path_case(required_abspath) if required_abspath: - logger.debug("Found %s on cdrom %s" % (requires, mount_point)) - self.game_disc = mount_point + logger.debug("Found %s on cdrom %s" % (requires, drive)) + self.game_disc = drive self._iter_commands() break diff --git a/lutris/util/disks.py b/lutris/util/disks.py index d55fd299a..fb1b7785e 100644 --- a/lutris/util/disks.py +++ b/lutris/util/disks.py @@ -10,14 +10,14 @@ def get_mounted_discs(): vm = Gio.VolumeMonitor.get() drives = [] - for m in vm.get_mounts(): - if m.get_volume(): - device = m.get_volume().get_identifier('unix-device') + for mount in vm.get_mounts(): + if mount.get_volume(): + device = mount.get_volume().get_identifier('unix-device') if not device: - logger.debug("No device for mount %s", m.get_name()) + logger.debug("No device for mount %s", mount.get_name()) continue # Device is a disk drive or ISO image if '/dev/sr' in device or '/dev/loop' in device: - drives.append(m) + drives.append(mount.get_root().get_path()) return drives From 30a2ca51d74e93f116f6cb7d5bb3f9e21d8b8749 Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Thu, 4 Aug 2016 00:24:20 -0700 Subject: [PATCH 180/181] Bump to version 0.3.8 --- Makefile | 2 +- debian/changelog | 15 +++++++++++++++ lutris/settings.py | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 47c217459..b6d1a32d5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION="0.3.7.5" +VERSION="0.3.8" cover: rm tests/fixtures/pga.db -f diff --git a/debian/changelog b/debian/changelog index a67ed9853..8ee5479a1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,18 @@ +lutris (0.3.8) xenial; urgency=medium + + * Add option to use the dark GTK theme variant + * Add Desmume runner + * Add option to limit games to a single CPU core + * Fix button mappings on mednafen + * Improve Reicast installation + * Add controller support to Reicast + * Disable Wine crash dialogs by default + * Sync steam games without depending on the remote library + * Use inotify to detect changes in Steam folders + * Allow to browse for mounted CD images during installation + + -- Mathieu Comandon Thu, 04 Aug 2016 00:13:38 -0700 + lutris (0.3.7.5) xenial; urgency=medium * Fix a bug where booleans in scripts would be converted to strings diff --git a/lutris/settings.py b/lutris/settings.py index 44e2c79fd..7fbd1fdc4 100644 --- a/lutris/settings.py +++ b/lutris/settings.py @@ -5,7 +5,7 @@ from gi.repository import GLib from lutris.util.settings import SettingsIO PROJECT = "Lutris" -VERSION = "0.3.7.5" +VERSION = "0.3.8" COPYRIGHT = "(c) 2010-2016 Lutris Gaming Platform" AUTHORS = ["Mathieu Comandon ", "Pascal Reinhard (Xodetaetl) Date: Thu, 4 Aug 2016 01:23:08 -0700 Subject: [PATCH 181/181] Update lutris.spec --- lutris.spec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lutris.spec b/lutris.spec index f890b34a1..636bc963d 100644 --- a/lutris.spec +++ b/lutris.spec @@ -1,7 +1,7 @@ %{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} Name: lutris -Version: 0.3.7.5 +Version: 0.3.8 Release: 2%{?dist} Summary: Install and play any video game easily @@ -18,11 +18,11 @@ BuildRequires: python-devel %if 0%{?fedora_version} BuildRequires: pygobject3, python3-gobject -Requires: pygobject3, PyYAML, pyxdg +Requires: pygobject3, PyYAML, pyxdg, dbus-python %endif %if 0%{?rhel_version} || 0%{?centos_version} BuildRequires: pygobject3 -Requires: pygobject3, PyYAML +Requires: pygobject3, PyYAML, pyxdg, dbus-python %endif %if 0%{?suse_version} BuildRequires: python-gobject @@ -30,7 +30,7 @@ BuildRequires: update-desktop-files # Needed to workaround "directories not owned by a package" issue BuildRequires: hicolor-icon-theme BuildRequires: polkit -Requires: python-gobject, python-gtk, python-PyYAML, python-xdg +Requires: python-gobject, python-gtk, python-PyYAML, python-xdg, dbus-1-python %endif %if 0%{?fedora_version} || 0%{?suse_version} BuildRequires: fdupes