mirror of
https://github.com/lutris/lutris
synced 2024-11-02 07:10:17 +00:00
broken but cleaner
This commit is contained in:
parent
4428127ceb
commit
43cb1af48f
5 changed files with 353 additions and 259 deletions
187
bin/lutris
187
bin/lutris
|
@ -17,16 +17,17 @@
|
|||
|
||||
import sys
|
||||
import os
|
||||
|
||||
import gtk
|
||||
import gobject
|
||||
|
||||
# optional Launchpad integration
|
||||
# this shouldn't crash if not found as it is simply used for bug reporting
|
||||
try:
|
||||
import LaunchpadIntegration
|
||||
launchpad_available = True
|
||||
except:
|
||||
launchpad_available = False
|
||||
|
||||
import gobject
|
||||
LAUNCHPAD_AVAILABLE = True
|
||||
except ImportError:
|
||||
LAUNCHPAD_AVAILABLE = False
|
||||
|
||||
# Check if we are working in the source tree or from the installed
|
||||
# package and mangle the python path accordingly
|
||||
|
@ -39,6 +40,7 @@ else:
|
|||
fullPath = os.getcwd()
|
||||
sys.path.insert(0, os.path.dirname(fullPath))
|
||||
|
||||
|
||||
from lutris.coverflow.coverflow import coverflow
|
||||
from lutris.gui.dictionary_grid import DictionaryGrid
|
||||
import lutris.runners
|
||||
|
@ -59,6 +61,7 @@ from lutris.gui.google_image_dialog import GoogleImageDialog
|
|||
from lutris.gui.edit_game_config_dialog import EditGameConfigDialog
|
||||
|
||||
class LutrisWindow(gtk.Window):
|
||||
""" Main Lutris window """
|
||||
__gtype_name__ = "LutrisWindow"
|
||||
|
||||
def __init__(self):
|
||||
|
@ -69,8 +72,8 @@ class LutrisWindow(gtk.Window):
|
|||
self.builder = builder
|
||||
self.builder.connect_signals(self)
|
||||
|
||||
global launchpad_available
|
||||
if launchpad_available:
|
||||
global LAUNCHPAD_AVAILABLE
|
||||
if LAUNCHPAD_AVAILABLE:
|
||||
# see https://wiki.ubuntu.com/UbuntuDevelopment/Internationalisation/Coding for more information
|
||||
# about LaunchpadIntegration
|
||||
helpmenu = self.builder.get_object('menu3')
|
||||
|
@ -78,11 +81,11 @@ class LutrisWindow(gtk.Window):
|
|||
LaunchpadIntegration.set_sourcepackagename('lutris')
|
||||
LaunchpadIntegration.add_items(helpmenu, 0, False, True)
|
||||
else:
|
||||
launchpad_available = False
|
||||
LAUNCHPAD_AVAILABLE = False
|
||||
|
||||
self.game_cover_image = self.builder.get_object("game_cover_image")
|
||||
self.game_cover_image.set_from_file("data/media/background.png")
|
||||
|
||||
|
||||
self.set_title("Lutris")
|
||||
|
||||
#Load Lutris configuration
|
||||
|
@ -92,7 +95,7 @@ class LutrisWindow(gtk.Window):
|
|||
game_rename = "Rename", self.edit_game_name
|
||||
game_config = "Configure", self.edit_game_configuration
|
||||
game_get_cover = "Get cover", self.get_cover
|
||||
menu_actions = [game_rename,game_config,game_get_cover]
|
||||
menu_actions = [game_rename, game_config, game_get_cover]
|
||||
self.menu = gtk.Menu()
|
||||
for item in menu_actions:
|
||||
if item == None:
|
||||
|
@ -101,12 +104,12 @@ class LutrisWindow(gtk.Window):
|
|||
subitem = gtk.ImageMenuItem(item[0])
|
||||
subitem.connect("activate", item[1])
|
||||
self.menu.append(subitem)
|
||||
self.menu.show_all()
|
||||
|
||||
self.menu.show_all()
|
||||
|
||||
#Status bar
|
||||
self.status_label = self.builder.get_object("status_label")
|
||||
self.status_label.set_text("Game on!")
|
||||
|
||||
|
||||
self.joystick_icons = []
|
||||
self.joystick_icons.append(self.builder.get_object("js0image"))
|
||||
self.joystick_icons.append(self.builder.get_object("js1image"))
|
||||
|
@ -115,15 +118,16 @@ class LutrisWindow(gtk.Window):
|
|||
for joystick_icon in self.joystick_icons:
|
||||
joystick_icon.hide()
|
||||
|
||||
#Toolbar
|
||||
# Toolbar
|
||||
self.toolbar = self.builder.get_object("lutris_toolbar")
|
||||
|
||||
#Game list
|
||||
# Game list
|
||||
self.game_list = self.get_game_list()
|
||||
self.game_list_grid_view = DictionaryGrid(self.game_list,["Game Name","Runner"])
|
||||
self.game_list_grid_view.connect('row-activated',self.game_launch)
|
||||
self.game_list_grid_view = DictionaryGrid(self.game_list,
|
||||
["Game Name", "Runner"])
|
||||
self.game_list_grid_view.connect('row-activated', self.game_launch)
|
||||
self.game_list_grid_view.connect("cursor-changed", self.select_game)
|
||||
self.game_list_grid_view.connect("button-press-event", self.mouse_menu)
|
||||
self.game_list_grid_view.connect("button-press-event", self.mouse_menu)
|
||||
self.game_list_grid_view.show()
|
||||
|
||||
self.game_column = self.game_list_grid_view.get_column(0)
|
||||
|
@ -138,36 +142,35 @@ class LutrisWindow(gtk.Window):
|
|||
self.timer_id = gobject.timeout_add(1000, self.refresh_status)
|
||||
|
||||
def refresh_status(self):
|
||||
###FIXME !!
|
||||
# if hasattr(self.running_game.game_process, "pid"):
|
||||
# self.status_text = "Game is running (pid: %s)" % str(self.running_game.game_process.pid)
|
||||
# self.status_bar.push(self.status_bar_context_id,self.status_text)
|
||||
# else:
|
||||
# self.status_bar.push(self.status_bar_context_id,"Welcome to Lutris")
|
||||
for index in range(0,3):
|
||||
# FIXME !!
|
||||
# if hasattr(self.running_game.game_process, "pid"):
|
||||
# self.status_text = "Game is running (pid: %s)" % str(self.running_game.game_process.pid)
|
||||
# self.status_bar.push(self.status_bar_context_id,self.status_text)
|
||||
# else:
|
||||
# self.status_bar.push(self.status_bar_context_id,"Welcome to Lutris")
|
||||
for index in range(0, 3):
|
||||
if os.path.exists("/dev/input/js%d" % index):
|
||||
self.joystick_icons[index].show()
|
||||
else:
|
||||
self.joystick_icons[index].hide()
|
||||
return True
|
||||
|
||||
|
||||
def get_game_list(self):
|
||||
game_list = []
|
||||
for file in os.listdir(lutris.constants.game_config_path):
|
||||
if file.endswith(lutris.constants.config_extension):
|
||||
game_name = file[:len(file)-len(lutris.constants.config_extension)]
|
||||
game_name = file[:len(file) - len(lutris.constants.config_extension)]
|
||||
Game = LutrisGame(game_name)
|
||||
if not Game.load_success:
|
||||
message = "Error while loading configuration for %s" % game_name
|
||||
error_dialog = gtk.MessageDialog(parent=self, flags=0,
|
||||
type=gtk.MESSAGE_ERROR,
|
||||
buttons=gtk.BUTTONS_OK,
|
||||
error_dialog = gtk.MessageDialog(parent=self, flags=0,
|
||||
type=gtk.MESSAGE_ERROR,
|
||||
buttons=gtk.BUTTONS_OK,
|
||||
message_format=message)
|
||||
error_dialog.run()
|
||||
error_dialog.destroy()
|
||||
game_list.append({"Game Name":Game.real_name,"Runner":Game.runner_name,"name":game_name})
|
||||
return game_list
|
||||
game_list.append({"Game Name":Game.real_name, "Runner":Game.runner_name, "name":game_name})
|
||||
return game_list
|
||||
|
||||
def about(self, widget, data=None):
|
||||
"""about - display the about box for lutris """
|
||||
|
@ -177,14 +180,15 @@ class LutrisWindow(gtk.Window):
|
|||
|
||||
def quit(self, widget, data=None):
|
||||
"""quit - signal handler for closing the LutrisWindow"""
|
||||
|
||||
self.destroy()
|
||||
|
||||
def on_destroy(self, widget, data=None):
|
||||
"""on_destroy - called when the LutrisWindow is close. """
|
||||
#clean up code for saving application state should be added here
|
||||
gtk.main_quit()
|
||||
|
||||
def mouse_menu(self,widget,event):
|
||||
|
||||
def mouse_menu(self, widget, event):
|
||||
if event.button == 3:
|
||||
(model, self.paths) = widget.get_selection().get_selected_rows()
|
||||
try:
|
||||
|
@ -192,9 +196,9 @@ class LutrisWindow(gtk.Window):
|
|||
except IndexError:
|
||||
return
|
||||
if len(self.paths) > 0:
|
||||
self.menu.popup(None, None, None, event.button, event.time)
|
||||
self.menu.popup(None, None, None, event.button, event.time)
|
||||
|
||||
def remove_game(self,widget,data=None):
|
||||
def remove_game(self, widget, data=None):
|
||||
"""Remove game configuration file
|
||||
Note: this won't delete the actual game"""
|
||||
if not self.gameName:
|
||||
|
@ -212,7 +216,7 @@ class LutrisWindow(gtk.Window):
|
|||
model, select_iter = gameSelection.get_selected()
|
||||
game_name = model.get_value(select_iter, 2)
|
||||
return game_name["name"]
|
||||
|
||||
|
||||
def select_game(self, treeview):
|
||||
gameSelection = treeview.get_selection()
|
||||
model, select_iter = gameSelection.get_selected()
|
||||
|
@ -220,47 +224,47 @@ class LutrisWindow(gtk.Window):
|
|||
self.gameName = model.get_value(select_iter, 2)["name"]
|
||||
self.set_game_cover()
|
||||
|
||||
def on_mount_iso_menuitem_activate(self,widget):
|
||||
mount_iso_dialog = MountIsoDialog()
|
||||
|
||||
def on_fullscreen_clicked(self,widget):
|
||||
game = lutris.coverflow.coverflow.coverflow()
|
||||
if game:
|
||||
if game == "NOCOVERS":
|
||||
|
||||
def on_fullscreen_clicked(self, widget):
|
||||
""" Switch to coverflow mode """
|
||||
coverflow = lutris.coverflow.coverflow.coverflow()
|
||||
if coverflow:
|
||||
if coverflow == "NOCOVERS":
|
||||
logging.error("Add some covers to these games first !")
|
||||
return
|
||||
if game == "NOPYGLET":
|
||||
if coverflow == "NOPYGLET":
|
||||
logging.debug("python-pyglet is not installed")
|
||||
return
|
||||
filename = os.path.basename(game)
|
||||
filename = os.path.basename(coverflow)
|
||||
game_name = filename[:filename.rfind(".")]
|
||||
running_game = LutrisGame(game_name)
|
||||
running_game.play()
|
||||
|
||||
def reset(self,widget,data=None):
|
||||
if hasattr(self,"running_game"):
|
||||
|
||||
def reset(self, widget, data=None):
|
||||
if hasattr(self, "running_game"):
|
||||
self.running_game.quit_game()
|
||||
else:
|
||||
LutrisDesktopControl().reset_desktop()
|
||||
|
||||
def install_game(self,widget,data=None):
|
||||
def install_game(self, widget, data=None):
|
||||
installer_dialog = InstallerDialog(self)
|
||||
|
||||
def add_game(self,widget,data=None):
|
||||
def add_game(self, widget, data=None):
|
||||
add_game_dialog = AddGameDialog(self)
|
||||
if hasattr(add_game_dialog,"game_info"):
|
||||
if hasattr(add_game_dialog, "game_info"):
|
||||
game_info = add_game_dialog.game_info
|
||||
self.game_list_grid_view.append_row(game_info)
|
||||
|
||||
def import_cedega(self,widget,data=None):
|
||||
|
||||
def import_cedega(self, widget, data=None):
|
||||
cedega = lutris.runners.cedega.cedega()
|
||||
cedega.import_games()
|
||||
self.get_game_list()
|
||||
|
||||
def import_steam(self,widget,data=None):
|
||||
def import_steam(self, widget, data=None):
|
||||
logging.debug("Import from steam not yet implemented")
|
||||
|
||||
def import_scummvm(self,widget,data=None):
|
||||
def import_scummvm(self, widget, data=None):
|
||||
scummvm = lutris.runners.scummvm.scummvm()
|
||||
scummvm.import_games()
|
||||
games = self.get_game_list()
|
||||
|
@ -271,55 +275,59 @@ class LutrisWindow(gtk.Window):
|
|||
if game['name'] not in current_game_names:
|
||||
self.game_list_grid_view.append_row(game)
|
||||
|
||||
def on_getfromftp_clicked(self,widget,data=None):
|
||||
def on_getfromftp_clicked(self, widget, data=None):
|
||||
FtpDialog()
|
||||
|
||||
def system_preferences(self,widget,data=None):
|
||||
def system_preferences(self, widget, data=None):
|
||||
SystemConfigDialog()
|
||||
|
||||
def runner_preferences(self,widget,data=None):
|
||||
def runner_preferences(self, widget, data=None):
|
||||
RunnersDialog()
|
||||
|
||||
def edit_game_name(self,button):
|
||||
"""Change game name"""
|
||||
self.game_cell.set_property('editable',True)
|
||||
self.game_list_grid_view.set_cursor(self.paths[0][0],self.game_column,True)
|
||||
def on_mount_iso_menuitem_activate(self, widget):
|
||||
MountIsoDialog()
|
||||
|
||||
def game_name_edited_callback(self,widget,index,new_name):
|
||||
def edit_game_name(self, button):
|
||||
"""Change game name"""
|
||||
self.game_cell.set_property('editable', True)
|
||||
self.game_list_grid_view.set_cursor(self.paths[0][0], self.game_column, True)
|
||||
|
||||
def game_name_edited_callback(self, widget, index, new_name):
|
||||
self.game_list_grid_view.get_model()[index][0] = new_name
|
||||
new_name_game_config = LutrisConfig(game=self.get_selected_game())
|
||||
new_name_game_config.config["realname"] =new_name
|
||||
new_name_game_config.config["realname"] = new_name
|
||||
new_name_game_config.save(type="game")
|
||||
self.game_cell.set_property('editable',False)
|
||||
self.game_cell.set_property('editable', False)
|
||||
|
||||
def edit_game_configuration(self,button):
|
||||
def edit_game_configuration(self, button):
|
||||
"""Edit game preferences"""
|
||||
game = self.get_selected_game()
|
||||
EditGameConfigDialog(self,game)
|
||||
EditGameConfigDialog(self, game)
|
||||
|
||||
def get_cover(self,button):
|
||||
def get_cover(self, button):
|
||||
"""Fetch cover from Google Image"""
|
||||
game = self.get_selected_game()
|
||||
GoogleImageDialog(game)
|
||||
|
||||
|
||||
def set_game_cover(self):
|
||||
if self.gameName:
|
||||
extensions = ["png", "jpg", "jpeg"]
|
||||
for extension in extensions:
|
||||
coverFile = os.path.join(lutris.constants.cover_path, self.gameName + "." + extension)
|
||||
coverFile = os.path.join(lutris.constants.cover_path,
|
||||
self.gameName + "." + extension)
|
||||
if os.path.exists(coverFile):
|
||||
#Resize the image
|
||||
cover_pixbuf = gtk.gdk.pixbuf_new_from_file(coverFile)
|
||||
dest_w = 250.0
|
||||
h = cover_pixbuf.get_height()
|
||||
w = cover_pixbuf.get_width()
|
||||
dest_h = h * (dest_w/w)
|
||||
self.game_cover_image.set_from_pixbuf(cover_pixbuf.scale_simple(int(dest_w),int(dest_h),gtk.gdk.INTERP_BILINEAR))
|
||||
dest_h = h * (dest_w / w)
|
||||
self.game_cover_image.set_from_pixbuf(cover_pixbuf.scale_simple(int(dest_w), int(dest_h), gtk.gdk.INTERP_BILINEAR))
|
||||
return
|
||||
else:
|
||||
self.game_cover_image.set_from_file("data/media/background.png")
|
||||
def NewLutrisWindow():
|
||||
"""NewLutrisWindow - returns a fully instantiated
|
||||
def new_lutris_window():
|
||||
"""new_lutris_window - returns a fully instantiated
|
||||
LutrisWindow object. Use this function rather than
|
||||
creating a LutrisWindow directly.
|
||||
"""
|
||||
|
@ -336,36 +344,39 @@ def NewLutrisWindow():
|
|||
return window
|
||||
|
||||
if __name__ == "__main__":
|
||||
#support for command line options
|
||||
import logging, optparse
|
||||
# Support for command line options.
|
||||
import logging
|
||||
import optparse
|
||||
parser = optparse.OptionParser(version="%prog %ver")
|
||||
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Show debug messages")
|
||||
parser.add_option("-v", "--verbose", action="store_true",
|
||||
dest="verbose", help="Show debug messages")
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
#set the logging level to show debug messages
|
||||
# Set the logging level to show debug messages.
|
||||
if options.verbose:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logging.debug('logging enabled')
|
||||
#run the application
|
||||
|
||||
# Run the application.
|
||||
game = None
|
||||
for arg in args:
|
||||
if arg.startswith('lutris://'):
|
||||
print 'will install : ' + arg[9:]
|
||||
print 'Installing ' + arg[9:]
|
||||
game = arg[9:]
|
||||
break
|
||||
if game:
|
||||
#TODO: Fetch the .lutris file
|
||||
#Todo : install the game
|
||||
installer = Installer(game)
|
||||
installer.install()
|
||||
#window = lutris.gui.InstallerDialog(name=game)
|
||||
success = installer.pre_install()
|
||||
if not success:
|
||||
print "Unable to install game"
|
||||
else:
|
||||
print "Ready! Launching installer."
|
||||
installer.install()
|
||||
exit()
|
||||
else:
|
||||
window = NewLutrisWindow()
|
||||
window.show()
|
||||
lutris_window = new_lutris_window()
|
||||
lutris_window.show()
|
||||
gtk.gdk.threads_init()
|
||||
gtk.gdk.threads_enter()
|
||||
gtk.main()
|
||||
gtk.gdk.threads_leave()
|
||||
|
||||
|
||||
|
|
|
@ -19,11 +19,10 @@
|
|||
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
|
||||
import gtk
|
||||
import lutris.runners
|
||||
import logging
|
||||
|
||||
import lutris.runners
|
||||
from lutris.config import LutrisConfig
|
||||
from lutris.game_config_vbox import GameConfigVBox
|
||||
from lutris.runner_config_vbox import RunnerConfigVBox
|
||||
|
@ -119,7 +118,7 @@ class AddGameDialog(gtk.Dialog):
|
|||
logging.debug(self.lutris_config.game_config)
|
||||
|
||||
if self.runner_class and realname:
|
||||
game_identifier = self.lutris_config.save(type = "game")
|
||||
game_identifier = self.lutris_config.save(type="game")
|
||||
self.game_info = {"Game Name": realname, "Runner": self.runner_class , "name": game_identifier}
|
||||
self.destroy()
|
||||
|
||||
|
@ -155,7 +154,7 @@ class AddGameDialog(gtk.Dialog):
|
|||
self.system_config_scrolled_window.show_all()
|
||||
|
||||
|
||||
def close(self, widget = None, other = None):
|
||||
def close(self, widget=None, other=None):
|
||||
self.destroy()
|
||||
|
||||
def no_runner_selected(self):
|
||||
|
|
|
@ -22,30 +22,32 @@
|
|||
import yaml
|
||||
import os
|
||||
import logging
|
||||
import copy
|
||||
import lutris.constants as constants
|
||||
|
||||
class LutrisConfig():
|
||||
def __init__(self, runner=None, game=None):
|
||||
def __init__(self, runner = None, game = None):
|
||||
#Check if configuration directories exists and create them if needed.
|
||||
config_paths = [constants.lutris_config_path, \
|
||||
constants.runner_config_path, \
|
||||
constants.game_config_path, \
|
||||
constants.cover_path, \
|
||||
constants.tmp_path ]
|
||||
config_paths = [
|
||||
constants.lutris_config_path,
|
||||
constants.runner_config_path,
|
||||
constants.game_config_path,
|
||||
constants.cover_path,
|
||||
constants.tmp_path,
|
||||
constants.cache_path
|
||||
]
|
||||
for config_path in config_paths:
|
||||
if not os.path.exists(config_path):
|
||||
os.mkdir(config_path)
|
||||
|
||||
|
||||
#Initialize configuration
|
||||
self.config = {}
|
||||
self.game_config = {}
|
||||
self.runner_config = {}
|
||||
self.system_config = {}
|
||||
|
||||
|
||||
self.game = None
|
||||
self.runner = None
|
||||
|
||||
|
||||
#By default config type is system, it can also be runner and game
|
||||
#this means that when you call lutris_config_instance["key"] is will
|
||||
#pick up the right configuration depending of config_type
|
||||
|
@ -63,14 +65,14 @@ class LutrisConfig():
|
|||
if self.system_config is None:
|
||||
self.system_config = {}
|
||||
else:
|
||||
file(constants.system_config_full_path,"w+")
|
||||
file(constants.system_config_full_path, "w+")
|
||||
|
||||
if self.game:
|
||||
game_config_full_path = os.path.join(constants.game_config_path,
|
||||
self.game + constants.config_extension)
|
||||
if os.path.exists(game_config_full_path):
|
||||
try:
|
||||
self.game_config = yaml.load(file(game_config_full_path,'r').read())
|
||||
self.game_config = yaml.load(file(game_config_full_path, 'r').read())
|
||||
self.runner = self.game_config["runner"]
|
||||
except yaml.scanner.ScannerError:
|
||||
logging.debug("error parsing config file %s" % game_config_full_path)
|
||||
|
@ -81,10 +83,10 @@ class LutrisConfig():
|
|||
runner_config_full_path = os.path.join(constants.runner_config_path,
|
||||
self.runner + constants.config_extension)
|
||||
if os.path.exists(runner_config_full_path):
|
||||
self.runner_config = yaml.load(file(runner_config_full_path,'r').read())
|
||||
self.runner_config = yaml.load(file(runner_config_full_path, 'r').read())
|
||||
self.update_global_config()
|
||||
|
||||
def __getitem__(self,key):
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Allows to access config data directly by keys"""
|
||||
if self.config_type == "game":
|
||||
value = self.game_config[key]
|
||||
|
@ -94,7 +96,7 @@ class LutrisConfig():
|
|||
value = self.system_config[key]
|
||||
return value
|
||||
|
||||
def __setitem__(self,key,value):
|
||||
def __setitem__(self, key, value):
|
||||
if self.config_type == "game":
|
||||
self.game_config[key] = value
|
||||
elif self.config_type == "runner":
|
||||
|
@ -109,7 +111,7 @@ class LutrisConfig():
|
|||
self.config[key].update(self.system_config[key])
|
||||
else:
|
||||
self.config[key] = self.system_config[key]
|
||||
|
||||
|
||||
for key in self.runner_config.keys():
|
||||
if key in self.config:
|
||||
self.config[key].update(self.runner_config[key])
|
||||
|
@ -122,12 +124,12 @@ class LutrisConfig():
|
|||
self.config[key].update(self.game_config[key])
|
||||
else:
|
||||
self.config[key] = self.game_config[key]
|
||||
|
||||
def remove(self,game_name):
|
||||
logging.debug("removing %s" % game_name)
|
||||
os.remove(os.path.join(constants.game_config_path,game_name+constants.config_extension))
|
||||
|
||||
def save(self,type=None):
|
||||
def remove(self, game_name):
|
||||
logging.debug("removing %s" % game_name)
|
||||
os.remove(os.path.join(constants.game_config_path, game_name + constants.config_extension))
|
||||
|
||||
def save(self, type = None):
|
||||
"""Save configuration file
|
||||
The way to save config files can be set by the type argument
|
||||
or with self.config_type"""
|
||||
|
@ -137,38 +139,39 @@ class LutrisConfig():
|
|||
logging.debug(self.config)
|
||||
if type is None:
|
||||
type = self.config_type
|
||||
yaml_config = yaml.dump(self.config,default_flow_style=False)
|
||||
|
||||
yaml_config = yaml.dump(self.config, default_flow_style = False)
|
||||
|
||||
if type == "system":
|
||||
file(constants.system_config_full_path,"w").write(yaml_config)
|
||||
file(constants.system_config_full_path, "w").write(yaml_config)
|
||||
elif type == "runner":
|
||||
runner_config_path = os.path.join(constants.runner_config_path,self.runner+constants.config_extension)
|
||||
file(runner_config_path,"w").write(yaml_config)
|
||||
runner_config_path = os.path.join(constants.runner_config_path, self.runner + constants.config_extension)
|
||||
file(runner_config_path, "w").write(yaml_config)
|
||||
elif type == "game":
|
||||
if not self.game:
|
||||
self.game = self.config["runner"] + "-" + self.config["realname"].replace(" ","_")
|
||||
self.game = self.config["runner"] + "-" + self.config["realname"].replace(" ", "_")
|
||||
self.game_config_path = os.path.join(constants.game_config_path,
|
||||
self.game.replace('/','_') + constants.config_extension)
|
||||
config_file = file(self.game_config_path,"w")
|
||||
self.game.replace('/', '_') + constants.config_extension)
|
||||
config_file = file(self.game_config_path, "w")
|
||||
config_file.write(yaml_config)
|
||||
return self.game
|
||||
else:
|
||||
print "Config type is %s or %s" % (self.config_type, type)
|
||||
print "i don't know how to save this yet"
|
||||
|
||||
|
||||
def get_path(self,runner):
|
||||
|
||||
|
||||
def get_path(self, runner = None, default = None):
|
||||
"""Gets the path to install games for a given runner"""
|
||||
|
||||
if "system" in self.config:
|
||||
if "game_path" in self.config["system"]:
|
||||
return self.config["system"]["game_path"]
|
||||
logging.debug("Fail !")
|
||||
logging.debug(self.config)
|
||||
return os.path.expanduser("~")
|
||||
|
||||
if __name__ == "__main__":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logging.basicConfig(level = logging.DEBUG)
|
||||
logging.debug('logging enabled')
|
||||
lc = LutrisConfig(runner="wine")
|
||||
lc = LutrisConfig(runner = "wine")
|
||||
print "system config : "
|
||||
print lc.system_config
|
||||
print "runner config : "
|
||||
|
@ -180,7 +183,7 @@ if __name__ == "__main__":
|
|||
print ("* testing games *")
|
||||
print ("*****************")
|
||||
|
||||
lc = LutrisConfig(game="wine-Ghostbusters")
|
||||
lc = LutrisConfig(game = "wine-Ghostbusters")
|
||||
print "system config : "
|
||||
print lc.system_config
|
||||
print ("-----------------------")
|
||||
|
@ -193,4 +196,4 @@ if __name__ == "__main__":
|
|||
print "global config"
|
||||
print lc.config
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import sys
|
|||
name = "Lutris"
|
||||
version = "0.2"
|
||||
website = "http://lutris.net"
|
||||
#installer_prefix = "http://localhost:8000/media/installers/"
|
||||
installer_prefix = "http://lutris.net/media/installers/"
|
||||
config_extension = ".yml"
|
||||
license = 'GPL-3'
|
||||
|
@ -53,6 +52,7 @@ lutris_icon_path = os.path.join(sys.path[0], lutris_icon_file)
|
|||
#Config files
|
||||
lutris_config_path = os.path.join(os.path.expanduser('~'), '.config', 'lutris')
|
||||
system_config_file = 'system' + config_extension
|
||||
protocol_version = 1
|
||||
|
||||
system_config_full_path = os.path.join(lutris_config_path, system_config_file)
|
||||
runner_config_path = os.path.join(lutris_config_path, 'runners"')
|
||||
|
|
|
@ -1,170 +1,251 @@
|
|||
# -*- coding:Utf-8 -*-
|
||||
###############################################################################
|
||||
## Lutris
|
||||
##
|
||||
## Copyright (C) 2009 Mathieu Comandon strycore@gmail.com
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
###############################################################################
|
||||
|
||||
""" Here is your docstring ... """
|
||||
|
||||
import os
|
||||
import logging
|
||||
import yaml
|
||||
import shutil
|
||||
import urllib
|
||||
import urllib2
|
||||
import logging
|
||||
import subprocess
|
||||
import shutil
|
||||
import time
|
||||
import yaml
|
||||
import platform
|
||||
from lutris.config import LutrisConfig
|
||||
|
||||
import lutris.constants
|
||||
from distutils.command.install_data import install_data
|
||||
from lutris.config import LutrisConfig
|
||||
|
||||
def unzip(filename):
|
||||
"""Unzips a file"""
|
||||
|
||||
subprocess.Popen(["_unzip", 'o', filename])
|
||||
|
||||
def unrar(filename):
|
||||
"""Unrar a file"""
|
||||
|
||||
subprocess.Popen(["_unrar", "x", filename])
|
||||
|
||||
def untgz(filename):
|
||||
"""Untgz a file"""
|
||||
|
||||
subprocess.Popen(["tar", "xzf", filename])
|
||||
|
||||
def run_installer(filename):
|
||||
"""Run an installer of .sh or .run type"""
|
||||
|
||||
subprocess.Popen(["chmod", "+x", filename])
|
||||
subprocess.Popen([filename])
|
||||
|
||||
def reporthook(arg1, received_bytes, total_size):
|
||||
"""Follows the progress of a download"""
|
||||
print "What is this ? : %d " % arg1
|
||||
print "received_bytes : %d " % received_bytes
|
||||
print "total_size : %d" % total_size
|
||||
|
||||
def check_md5(data):
|
||||
""" Calculates the checksum of a file and validates it. """
|
||||
|
||||
print 'checking md5 for file ' + self.gamefiles[data['file']]
|
||||
print 'expecting ' + data['value']
|
||||
print "NOT IMPLEMENTED"
|
||||
return True
|
||||
|
||||
class Installer():
|
||||
""" Lutris installer """
|
||||
|
||||
def __init__(self, game):
|
||||
self.supported_protocol_version = 1
|
||||
|
||||
self.lutris_config = LutrisConfig()
|
||||
self.website_url = lutris.constants.installer_prefix
|
||||
self.installer_cache = lutris.constants.cache_path
|
||||
self.gameName = game
|
||||
self.game_name = game
|
||||
self.installer_dest_path = os.path.join(lutris.constants.cache_path,
|
||||
self.game_name + ".yml")
|
||||
# Stores a list of actions that will be sent back to the user
|
||||
# in order to complete the installation
|
||||
self.installer_user_actions = []
|
||||
|
||||
# Actions that the installer has to run
|
||||
# in order to complete the install.
|
||||
self.installer_actions = []
|
||||
|
||||
# List of errors that occurred while installing the game
|
||||
self.installer_errors = []
|
||||
|
||||
# ???
|
||||
self.install_data = []
|
||||
|
||||
# Essential game information to create Lutris launcher
|
||||
self.game_info = {}
|
||||
#FIXME : The thing that should not be
|
||||
self.gamesDir = "/media/seagate300/games/"
|
||||
self.gameDir = os.path.join(self.gamesDir, self.gameName)
|
||||
if not os.path.exists(self.gameDir):
|
||||
os.mkdir(self.gameDir)
|
||||
self.lutrisConfigDir = lutris.constants.lutris_config_path
|
||||
self.installer_dest_path = os.path.join(self.installer_cache, self.gameName + ".yml")
|
||||
#WTF ?
|
||||
self.totalDownloaded = 0
|
||||
|
||||
# Dictionary of the files needed to install the game
|
||||
self.gamefiles = {}
|
||||
|
||||
|
||||
def set_games_dir(self, path):
|
||||
""" Set the base path where the game will be installed """
|
||||
|
||||
self.games_dir = path
|
||||
|
||||
def pre_install(self):
|
||||
"""Reads the installer and checks everything is OK
|
||||
before beginning the install process
|
||||
"""
|
||||
|
||||
success = self.save_installer_content()
|
||||
if not success:
|
||||
return False
|
||||
success = self.parseconfig()
|
||||
self.games_dir = self.lutris_config.get_path(
|
||||
runner=self.game_info['runner'])
|
||||
if not self.games_dir:
|
||||
self.installer_user_actions.append("ask_games_dir")
|
||||
|
||||
self.game_dir = os.path.join(self.games_dir, self.game_name)
|
||||
if not os.path.exists(self.game_dir):
|
||||
os.mkdir(self.game_dir)
|
||||
|
||||
return success
|
||||
|
||||
def install(self):
|
||||
self.save_installer_content()
|
||||
success = self.parseconfig()
|
||||
if success:
|
||||
self.writeConfig()
|
||||
else:
|
||||
print "Installer failed"
|
||||
""" Runs the actions to complete the install. """
|
||||
|
||||
def save_installer_content(self):
|
||||
print 'downloading installer for ' + self.gameName
|
||||
full_url = self.website_url + self.gameName + '.yml'
|
||||
request = urllib2.Request(url = full_url)
|
||||
f = urllib2.urlopen(request)
|
||||
os.chdir(self.game_dir)
|
||||
|
||||
installer_file = open(self.installer_dest_path, "w")
|
||||
installer_file.write(f.read())
|
||||
installer_file.close()
|
||||
#TODO : Check size
|
||||
|
||||
def parseconfig(self):
|
||||
self.install_data = yaml.load(file(self.installer_dest_path, 'r').read())
|
||||
|
||||
#Checking protocol
|
||||
protocol_version = self.install_data['protocol']
|
||||
if protocol_version != self.supported_protocol_version:
|
||||
print "Wrong protocol version (Expected %d, got %d)" % (self.supported_protocol_version, protocol_version)
|
||||
return False
|
||||
|
||||
mandatory_fields = ['version', 'runner', 'name']
|
||||
optional_fields = ['exe']
|
||||
for field in mandatory_fields:
|
||||
self.game_info[field] = self.install_data[field]
|
||||
for field in optional_fields:
|
||||
if field in self.install_data:
|
||||
self.game_info[field] = self.install_data[field]
|
||||
files = self.install_data['files']
|
||||
self.gamefiles = {}
|
||||
for gamefile in files:
|
||||
file_id = gamefile.keys()[0]
|
||||
dest_path = self.download(gamefile[file_id])
|
||||
self.gamefiles[file_id] = dest_path
|
||||
installer_actions = self.install_data['installer']
|
||||
|
||||
#FIXME ?
|
||||
os.chdir(self.gameDir)
|
||||
|
||||
for action in installer_actions:
|
||||
for action in self.installer_actions:
|
||||
action_name = action.keys()[0]
|
||||
action_data = action[action_name]
|
||||
mappings = {
|
||||
'check_md5': self.check_md5,
|
||||
'extract' : self.extract,
|
||||
'move' : self.move,
|
||||
'delete': self.delete
|
||||
'check_md5': check_md5,
|
||||
'extract' : self._extract,
|
||||
'move' : self._move
|
||||
}
|
||||
if action_name not in mappings.keys():
|
||||
print "Action " + action_name + " not supported !"
|
||||
return False
|
||||
mappings[action_name](action_data)
|
||||
return True
|
||||
def writeConfig(self):
|
||||
config_filename = os.path.join(self.lutrisConfigDir,
|
||||
"games" , self.game_info['runner'] + "-" + self.gameName + ".yml")
|
||||
config_file = open(config_filename, "w")
|
||||
config_data = {
|
||||
'game': {},
|
||||
'realname': self.game_info['name'],
|
||||
'runner': self.game_info['runner']
|
||||
}
|
||||
|
||||
if('exe' in self.game_info):
|
||||
config_data['game']['exe'] = os.path.join(self.gameDir, self.game_info['exe'])
|
||||
|
||||
yaml_config = yaml.dump(config_data, default_flow_style=False)
|
||||
file(config_filename, "w").write(yaml_config)
|
||||
self.write_config()
|
||||
|
||||
def reporthook(self, arg1, bytes, totalSize):
|
||||
self.totalDownloaded = self.totalDownloaded + bytes
|
||||
#print self.totalDownloaded / totalSize * 100.0
|
||||
def save_installer_content(self):
|
||||
""" Save the downloaded installer to disk. """
|
||||
|
||||
def download(self, url):
|
||||
logging.debug('Downloading ' + url)
|
||||
destFile = os.path.join(self.gamesDir, self.gameName, url.split("/")[-1])
|
||||
if os.path.exists(destFile):
|
||||
return destFile
|
||||
if url.startswith("file://"):
|
||||
shutil.copy(url[7:], self.gameDir)
|
||||
print 'downloading installer for ' + self.game_name
|
||||
|
||||
full_url = lutris.constants.installer_prefix + self.game_name + '.yml'
|
||||
request = urllib2.Request(url=full_url)
|
||||
try:
|
||||
response = urllib2.urlopen(request)
|
||||
except urllib2.URLError:
|
||||
print "Server is unreachable"
|
||||
self.installer_errors.append("SERVER_UNREACHABLE")
|
||||
success = False
|
||||
else:
|
||||
urllib.urlretrieve(url, destFile, self.reporthook)
|
||||
return destFile
|
||||
installer_file = open(self.installer_dest_path, "w")
|
||||
installer_file.write(response.read())
|
||||
installer_file.close()
|
||||
success = True
|
||||
finally:
|
||||
return success
|
||||
|
||||
def check_md5(self, data):
|
||||
print 'checking md5 for file ' + self.gamefiles[data['file']]
|
||||
print 'expecting ' + data['value']
|
||||
print "NOT IMPLEMENTED"
|
||||
return True
|
||||
def parseconfig(self):
|
||||
""" Reads the installer file. """
|
||||
|
||||
self.install_data = yaml.load(file(self.installer_dest_path,
|
||||
'r').read())
|
||||
|
||||
#Checking protocol
|
||||
protocol_version = self.install_data['protocol']
|
||||
if protocol_version != lutris.constants.protocol_version:
|
||||
print("Wrong protocol version (Expected %d, got %d)" %
|
||||
(lutris.constants.protocol_version, protocol_version))
|
||||
return False
|
||||
|
||||
#Script version
|
||||
self.game_info['version'] = self.install_data['version']
|
||||
#Runner
|
||||
self.game_info['runner'] = self.install_data['runner']
|
||||
#Name
|
||||
self.game_info['name'] = self.install_data['name']
|
||||
files = self.install_data['files']
|
||||
|
||||
for gamefile in files:
|
||||
file_id = gamefile.keys()[0]
|
||||
dest_path = self._download(gamefile[file_id])
|
||||
self.gamefiles[file_id] = dest_path
|
||||
self.installer_actions = self.install_data['installer']
|
||||
|
||||
def write_config(self):
|
||||
""" Writes the game configration as a Lutris launcher. """
|
||||
config_filename = os.path.join(lutris.constants.lutris_config_path, "games",
|
||||
self.game_name + ".conf")
|
||||
config_file = open(config_filename, "w")
|
||||
config_file.write("[main]\n")
|
||||
config_file.write("path = " + self.game_dir + "\n")
|
||||
if('exe' in self.game_info):
|
||||
config_file.write("exe = " + self.game_info['exe'] + "\n")
|
||||
config_file.write("runner = " + self.game_info['runner'])
|
||||
config_file.close()
|
||||
|
||||
|
||||
|
||||
def _download(self, url):
|
||||
""" Downloads a file. """
|
||||
|
||||
logging.debug('Downloading ' + url)
|
||||
dest_dir = os.path.join(lutris.constants.tmp_path, self.game_name)
|
||||
if not os.path.exists(dest_dir):
|
||||
os.mkdir(dest_dir)
|
||||
dest_file = os.path.join(dest_dir, url.split("/")[-1])
|
||||
if os.path.exists(dest_file):
|
||||
return dest_file
|
||||
if url.startswith("file://"):
|
||||
shutil.copy(url[7:], self.game_dir)
|
||||
else:
|
||||
urllib.urlretrieve(url, dest_file, reporthook)
|
||||
return dest_file
|
||||
|
||||
|
||||
|
||||
def _extract(self, data):
|
||||
""" Extracts a file, guessing the compression method """
|
||||
|
||||
def extract(self, data):
|
||||
print 'extracting ' + data['file']
|
||||
filename = self.gamefiles[data['file']]
|
||||
print "NOT IMPLEMENTED"
|
||||
extension = filename[filename.rfind(".") + 1:]
|
||||
|
||||
if extension == "zip":
|
||||
self.unzip(filename)
|
||||
unzip(filename)
|
||||
|
||||
def move(self, data):
|
||||
src = os.path.join(self.gameDir, data['src'])
|
||||
if not os.path.exists(src):
|
||||
time.sleep(1)
|
||||
if not os.path.exists(src):
|
||||
return False
|
||||
def _move(self, data):
|
||||
""" Moves a file. """
|
||||
src = data['src']
|
||||
destination_alias = data['dst']
|
||||
if destination_alias == 'gamedir':
|
||||
dst = self.gameDir;
|
||||
dst = self.game_dir
|
||||
else:
|
||||
dst = '/tmp'
|
||||
|
||||
print "Moving %s to %s" % (src, dst)
|
||||
shutil.move(src, dst)
|
||||
|
||||
def unzip(self, file):
|
||||
subprocess.call(["unzip", '-o', '-qq', file])
|
||||
try:
|
||||
shutil.move(src, dst)
|
||||
except ValueError:
|
||||
print "Could not move the file, destination already exists ?"
|
||||
|
||||
def unrar(self, file):
|
||||
subprocess.Popen(["unrar", "x", file])
|
||||
|
||||
def untgz(self, file):
|
||||
subprocess.Popen(["tar", "xzf", file])
|
||||
|
||||
def runInstaller(self, file):
|
||||
subprocess.Popen(["chmod", "+x", file])
|
||||
subprocess.Popen([file])
|
||||
def delete(self, data):
|
||||
print "let's not delete anything right now, m'kay ?"
|
||||
|
||||
if __name__ == "__main__":
|
||||
quakeInstall = LutrisInstaller("quake")
|
||||
quakeInstall.install()
|
||||
|
|
Loading…
Reference in a new issue