mirror of
https://github.com/derrod/legendary.git
synced 2025-08-26 20:11:04 +00:00
2021-02-05_00-02-05
This commit is contained in:
parent
736983992c
commit
5ecd04abb0
|
@ -18,7 +18,8 @@ from typing import List, Dict
|
|||
from uuid import uuid4
|
||||
|
||||
from legendary.api.egs import EPCAPI
|
||||
from legendary.downloader.manager import DLManager
|
||||
#from legendary.downloader.manager import DLManager
|
||||
from legendary.gui.manager2 import DLManager
|
||||
from legendary.lfs.egl import EPCLFS
|
||||
from legendary.lfs.lgndry import LGDLFS
|
||||
from legendary.utils.lfs import clean_filename, delete_folder, delete_filelist
|
||||
|
@ -705,9 +706,10 @@ class LegendaryCore:
|
|||
dl_optimizations: bool = False, dl_timeout: int = 10,
|
||||
repair: bool = False, repair_use_latest: bool = False,
|
||||
disable_delta: bool = False, override_delta_manifest: str = '',
|
||||
egl_guid: str = '', main_window="cli") -> (DLManager, AnalysisResult, ManifestMeta):
|
||||
egl_guid: str = '', main_window = "cli") -> (DLManager, AnalysisResult, ManifestMeta):
|
||||
# load old manifest
|
||||
old_manifest = None
|
||||
print("prepare",main_window.get_title())
|
||||
|
||||
# load old manifest if we have one
|
||||
if override_old_manifest:
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
class log_dlm:
|
||||
def create(main_window):
|
||||
def create(self, main_window):
|
||||
if main_window == "cli":
|
||||
print(main_window)
|
||||
return "cli"
|
||||
else:
|
||||
bar = Gtk.ProgressBar()
|
||||
main_window.login_vbox.pack_end(bar, False, False, 10)
|
||||
print(main_window)
|
||||
return bar
|
||||
|
||||
def update(self, perc, processed_chunks, num_chunk_tasks, rt_hours, rt_minutes, rt_seconds, hours, minutes, seconds, total_dl, total_write, total_used, dl_speed, dl_unc_speed, w_speed, r_speed, obj_out):
|
||||
|
@ -50,6 +56,7 @@ class log_dlm:
|
|||
def update_gui(self, perc, processed_chunks, num_chunk_tasks, rt_hours, rt_minutes, rt_seconds, hours, minutes, seconds, total_dl, total_write, total_used, dl_speed, dl_unc_speed, w_speed, r_speed, bar):
|
||||
bar.set_fraction(perc)
|
||||
bar.set_text(f"{dl_speed / 1024 / 1024:.02f} MiB/s - {(perc*100):.02f}% - ETA: {hours:02d}:{minutes:02d}:{seconds:02d}")
|
||||
print(bar.get_text())
|
||||
|
||||
def update_cli(self, perc, processed_chunks, num_chunk_tasks, rt_hours, rt_minutes, rt_seconds, hours, minutes, seconds, total_dl, total_write, total_used, dl_speed, dl_unc_speed, w_speed, r_speed):
|
||||
perc *= 100
|
||||
|
@ -67,36 +74,22 @@ class log_dlm:
|
|||
|
||||
|
||||
|
||||
def init(parent):
|
||||
bar = Gtk.ProgressBar()
|
||||
parent.login_vbox.pack_end(bar, False, False, 10)
|
||||
return bar
|
||||
def update(self, perc, processed_chunks, num_chunk_tasks, rt_hours, rt_minutes, rt_seconds, hours, minutes, seconds, total_dl, total_write, total_used, dl_speed, dl_unc_speed, w_speed, r_speed):
|
||||
self.
|
||||
f'= Progress: {perc:.02f}% ({processed_chunks}/{num_chunk_tasks}), '
|
||||
f'Running for {rt_hours:02d}:{rt_minutes:02d}:{rt_seconds:02d}, '
|
||||
f'ETA: {hours:02d}:{minutes:02d}:{seconds:02d}')
|
||||
f' - Downloaded: {total_dl / 1024 / 1024:.02f} MiB, '
|
||||
f'Written: {total_write / 1024 / 1024:.02f} MiB')
|
||||
f' - Cache usage: {total_used} MiB, active tasks: {self.active_tasks}')
|
||||
f' + Download\t- {dl_speed / 1024 / 1024:.02f} MiB/s (raw) '
|
||||
f'/ {dl_unc_speed / 1024 / 1024:.02f} MiB/s (decompressed)')
|
||||
f' + Disk\t- {w_speed / 1024 / 1024:.02f} MiB/s (write) / '
|
||||
f'{r_speed / 1024 / 1024:.02f} MiB/s (read)')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
self.log.info(f'= Progress: {perc:.02f}% ({processed_chunks}/{num_chunk_tasks}), '
|
||||
f'Running for {rt_hours:02d}:{rt_minutes:02d}:{rt_seconds:02d}, '
|
||||
f'ETA: {hours:02d}:{minutes:02d}:{seconds:02d}')
|
||||
self.log.info(f' - Downloaded: {total_dl / 1024 / 1024:.02f} MiB, '
|
||||
f'Written: {total_write / 1024 / 1024:.02f} MiB')
|
||||
self.log.info(f' - Cache usage: {total_used} MiB, active tasks: {self.active_tasks}')
|
||||
self.log.info(f' + Download\t- {dl_speed / 1024 / 1024:.02f} MiB/s (raw) '
|
||||
f'/ {dl_unc_speed / 1024 / 1024:.02f} MiB/s (decompressed)')
|
||||
self.log.info(f' + Disk\t- {w_speed / 1024 / 1024:.02f} MiB/s (write) / '
|
||||
f'{r_speed / 1024 / 1024:.02f} MiB/s (read)')
|
||||
|
||||
|
||||
#
|
||||
# self.log.info(f'= Progress: {perc:.02f}% ({processed_chunks}/{num_chunk_tasks}), '
|
||||
# f'Running for {rt_hours:02d}:{rt_minutes:02d}:{rt_seconds:02d}, '
|
||||
# f'ETA: {hours:02d}:{minutes:02d}:{seconds:02d}')
|
||||
# self.log.info(f' - Downloaded: {total_dl / 1024 / 1024:.02f} MiB, '
|
||||
# f'Written: {total_write / 1024 / 1024:.02f} MiB')
|
||||
# self.log.info(f' - Cache usage: {total_used} MiB, active tasks: {self.active_tasks}')
|
||||
# self.log.info(f' + Download\t- {dl_speed / 1024 / 1024:.02f} MiB/s (raw) '
|
||||
# f'/ {dl_unc_speed / 1024 / 1024:.02f} MiB/s (decompressed)')
|
||||
# self.log.info(f' + Disk\t- {w_speed / 1024 / 1024:.02f} MiB/s (write) / '
|
||||
# f'{r_speed / 1024 / 1024:.02f} MiB/s (read)')
|
||||
|
|
|
@ -138,6 +138,7 @@ class FileWorker(Process):
|
|||
logger = logging.getLogger(self.name)
|
||||
logger.setLevel(self.log_level)
|
||||
logger.debug(f'Download worker reporting for duty!')
|
||||
print(f'Download worker reporting for duty! {self.name}')
|
||||
|
||||
last_filename = ''
|
||||
current_file = None
|
||||
|
@ -145,7 +146,9 @@ class FileWorker(Process):
|
|||
while True:
|
||||
try:
|
||||
try:
|
||||
j = self.q.get(timeout=10.0)
|
||||
print(f'j = self.q.get - {self.name}')
|
||||
#j = self.q.get(timeout=10.0)
|
||||
j = self.q.get(timeout=0.5)
|
||||
except Empty:
|
||||
logger.warning('Writer queue empty!')
|
||||
continue
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import gi
|
||||
import sys
|
||||
# insert at 1, 0 is the script path (or '' in REPL)
|
||||
sys.path.insert(1, '../..')
|
||||
|
||||
import webbrowser
|
||||
import time
|
||||
from multiprocessing import freeze_support, Queue as MPQueue
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
import legendary.core
|
||||
import legendary.cli
|
||||
core = legendary.core.LegendaryCore()
|
||||
cli = legendary.cli.LegendaryCLI()
|
||||
|
||||
class args_obj:
|
||||
base_path = ''
|
||||
|
@ -566,7 +576,7 @@ def install_gtk(app_name, app_title, parent):
|
|||
f"reset_sdl:\t\t {args.reset_sdl}",
|
||||
sep='\n'
|
||||
)
|
||||
return 1
|
||||
#return 1
|
||||
|
||||
# TODO:
|
||||
if install_dialog_response != Gtk.ResponseType.OK:
|
||||
|
@ -577,7 +587,7 @@ def install_gtk(app_name, app_title, parent):
|
|||
if igame.needs_verification:
|
||||
repair_mode = True
|
||||
repair_file = None
|
||||
if repair_mode:
|
||||
if args.repair_mode:
|
||||
args.no_install = args.repair_and_update is False
|
||||
repair_file = os.path.join(core.lgd.get_tmp_path(), f'{app_name}.repair')
|
||||
|
||||
|
@ -643,7 +653,7 @@ def install_gtk(app_name, app_title, parent):
|
|||
# else:
|
||||
# args.install_tag = config_tags.split(',')
|
||||
|
||||
log_gtk('Preparing download...')
|
||||
print('Preparing download...')
|
||||
# todo use status queue to print progress from CLI
|
||||
# This has become a little ridiculous hasn't it?
|
||||
dlm, analysis, igame = core.prepare_download(game=game, base_game=base_game, base_path=args.base_path,
|
||||
|
@ -662,7 +672,7 @@ def install_gtk(app_name, app_title, parent):
|
|||
repair=args.repair_mode,
|
||||
repair_use_latest=args.repair_and_update,
|
||||
disable_delta=args.disable_delta,
|
||||
override_delta_manifest=args.override_delta_manifest
|
||||
override_delta_manifest=args.override_delta_manifest,
|
||||
main_window=parent)
|
||||
|
||||
# game is either up to date or hasn't changed, so we have nothing to do
|
||||
|
@ -680,21 +690,21 @@ def install_gtk(app_name, app_title, parent):
|
|||
# check if install tags have changed, if they did; try deleting files that are no longer required.
|
||||
if old_igame and old_igame.install_tags != igame.install_tags:
|
||||
old_igame.install_tags = igame.install_tags
|
||||
self.log_gtk('Deleting now untagged files.')
|
||||
log_gtk('Deleting now untagged files.')
|
||||
core.uninstall_tag(old_igame)
|
||||
core.install_game(old_igame)
|
||||
|
||||
exit(0)
|
||||
|
||||
log_gtk(f'Install size: {analysis.install_size / 1024 / 1024:.02f} MiB')
|
||||
print(f'Install size: {analysis.install_size / 1024 / 1024:.02f} MiB')
|
||||
compression = (1 - (analysis.dl_size / analysis.uncompressed_dl_size)) * 100
|
||||
log_gtk(f'Download size: {analysis.dl_size / 1024 / 1024:.02f} MiB '
|
||||
print(f'Download size: {analysis.dl_size / 1024 / 1024:.02f} MiB '
|
||||
f'(Compression savings: {compression:.01f}%)')
|
||||
log_gtk(f'Reusable size: {analysis.reuse_size / 1024 / 1024:.02f} MiB (chunks) / '
|
||||
print(f'Reusable size: {analysis.reuse_size / 1024 / 1024:.02f} MiB (chunks) / '
|
||||
f'{analysis.unchanged / 1024 / 1024:.02f} MiB (unchanged / skipped)')
|
||||
|
||||
res = core.check_installation_conditions(analysis=analysis, install=igame, game=game,
|
||||
updating=self.core.is_installed(app_name),
|
||||
updating=core.is_installed(app_name),
|
||||
ignore_space_req=args.ignore_space)
|
||||
|
||||
if res.warnings or res.failures:
|
||||
|
@ -710,16 +720,17 @@ def install_gtk(app_name, app_title, parent):
|
|||
log_gtk('Installation cannot proceed, exiting.')
|
||||
exit(1)
|
||||
|
||||
log_gtk('Downloads are resumable, you can interrupt the download with '
|
||||
print('Downloads are resumable, you can interrupt the download with '
|
||||
'CTRL-C and resume it using the same command later on.')
|
||||
|
||||
start_t = time.time()
|
||||
|
||||
try:
|
||||
# set up logging stuff (should be moved somewhere else later)
|
||||
dlm.logging_queue = self.logging_queue
|
||||
dlm.logging_queue = cli.logging_queue
|
||||
dlm.proc_debug = args.dlm_debug
|
||||
|
||||
#print("parent:",parent)
|
||||
dlm.start()
|
||||
dlm.join()
|
||||
except Exception as e:
|
||||
|
@ -728,60 +739,60 @@ def install_gtk(app_name, app_title, parent):
|
|||
f'The following exception occurred while waiting for the downloader to finish: {e!r}. '
|
||||
f'Try restarting the process, the resume file will be used to start where it failed. '
|
||||
f'If it continues to fail please open an issue on GitHub.')
|
||||
else:
|
||||
end_t = time.time()
|
||||
if not args.no_install:
|
||||
# Allow setting savegame directory at install time so sync-saves will work immediately
|
||||
if game.supports_cloud_saves and args.save_path:
|
||||
igame.save_path = args.save_path
|
||||
#else:
|
||||
# end_t = time.time()
|
||||
# if not args.no_install:
|
||||
# # Allow setting savegame directory at install time so sync-saves will work immediately
|
||||
# if game.supports_cloud_saves and args.save_path:
|
||||
# igame.save_path = args.save_path
|
||||
|
||||
postinstall = self.core.install_game(igame)
|
||||
if postinstall:
|
||||
self._handle_postinstall(postinstall, igame, yes=args.yes)
|
||||
# postinstall = self.core.install_game(igame)
|
||||
# if postinstall:
|
||||
# self._handle_postinstall(postinstall, igame, yes=args.yes)
|
||||
|
||||
dlcs = self.core.get_dlc_for_game(game.app_name)
|
||||
if dlcs:
|
||||
print('The following DLCs are available for this game:')
|
||||
for dlc in dlcs:
|
||||
print(f' - {dlc.app_title} (App name: {dlc.app_name}, version: {dlc.app_version})')
|
||||
print('Manually installing DLCs works the same; just use the DLC app name instead.')
|
||||
# dlcs = self.core.get_dlc_for_game(game.app_name)
|
||||
# if dlcs:
|
||||
# print('The following DLCs are available for this game:')
|
||||
# for dlc in dlcs:
|
||||
# print(f' - {dlc.app_title} (App name: {dlc.app_name}, version: {dlc.app_version})')
|
||||
# print('Manually installing DLCs works the same; just use the DLC app name instead.')
|
||||
|
||||
install_dlcs = True
|
||||
if not args.yes:
|
||||
if not get_boolean_choice(f'Do you wish to automatically install DLCs?'):
|
||||
install_dlcs = False
|
||||
# install_dlcs = True
|
||||
# if not args.yes:
|
||||
# if not get_boolean_choice(f'Do you wish to automatically install DLCs?'):
|
||||
# install_dlcs = False
|
||||
|
||||
if install_dlcs:
|
||||
_yes, _app_name = args.yes, app_name
|
||||
args.yes = True
|
||||
for dlc in dlcs:
|
||||
app_name = dlc.app_name
|
||||
self.install_game(args)
|
||||
args.yes, app_name = _yes, _app_name
|
||||
# if install_dlcs:
|
||||
# _yes, _app_name = args.yes, app_name
|
||||
# args.yes = True
|
||||
# for dlc in dlcs:
|
||||
# app_name = dlc.app_name
|
||||
# self.install_game(args)
|
||||
# args.yes, app_name = _yes, _app_name
|
||||
|
||||
if game.supports_cloud_saves and not game.is_dlc:
|
||||
# todo option to automatically download saves after the installation
|
||||
# args does not have the required attributes for sync_saves in here,
|
||||
# not sure how to solve that elegantly.
|
||||
log_gtk(f'This game supports cloud saves, syncing is handled by the "sync-saves" command.To download saves for this game run "legendary sync-saves {app_name}"')
|
||||
# if game.supports_cloud_saves and not game.is_dlc:
|
||||
# # todo option to automatically download saves after the installation
|
||||
# # args does not have the required attributes for sync_saves in here,
|
||||
# # not sure how to solve that elegantly.
|
||||
# log_gtk(f'This game supports cloud saves, syncing is handled by the "sync-saves" command.To download saves for this game run "legendary sync-saves {app_name}"')
|
||||
|
||||
old_igame = self.core.get_installed_game(game.app_name)
|
||||
if old_igame and args.repair_mode and os.path.exists(repair_file):
|
||||
if old_igame.needs_verification:
|
||||
old_igame.needs_verification = False
|
||||
self.core.install_game(old_igame)
|
||||
# old_igame = self.core.get_installed_game(game.app_name)
|
||||
# if old_igame and args.repair_mode and os.path.exists(repair_file):
|
||||
# if old_igame.needs_verification:
|
||||
# old_igame.needs_verification = False
|
||||
# self.core.install_game(old_igame)
|
||||
|
||||
log_gtk('Removing repair file.')
|
||||
os.remove(repair_file)
|
||||
# log_gtk('Removing repair file.')
|
||||
# os.remove(repair_file)
|
||||
|
||||
# check if install tags have changed, if they did; try deleting files that are no longer required.
|
||||
if old_igame and old_igame.install_tags != igame.install_tags:
|
||||
old_igame.install_tags = igame.install_tags
|
||||
log_gtk('Deleting now untagged files.')
|
||||
core.uninstall_tag(old_igame)
|
||||
core.install_game(old_igame)
|
||||
# # check if install tags have changed, if they did; try deleting files that are no longer required.
|
||||
# if old_igame and old_igame.install_tags != igame.install_tags:
|
||||
# old_igame.install_tags = igame.install_tags
|
||||
# log_gtk('Deleting now untagged files.')
|
||||
# core.uninstall_tag(old_igame)
|
||||
# core.install_game(old_igame)
|
||||
|
||||
log_gtk(f'Finished installation process in {end_t - start_t:.02f} seconds.')
|
||||
# log_gtk(f'Finished installation process in {end_t - start_t:.02f} seconds.')
|
||||
|
||||
class main_window(Gtk.Window):
|
||||
def __init__(self):
|
||||
|
|
|
@ -17,13 +17,17 @@ from threading import Condition, Thread
|
|||
from legendary.downloader.workers import DLWorker, FileWorker
|
||||
from legendary.models.downloading import *
|
||||
from legendary.models.manifest import ManifestComparison, Manifest
|
||||
from legendary.downloader.log_dlm import log_dlm
|
||||
|
||||
log_dlm = log_dlm()
|
||||
|
||||
class DLManager(Process):
|
||||
def __init__(self, download_dir, base_url, cache_dir=None, status_q=None,
|
||||
max_workers=0, update_interval=1.0, dl_timeout=10, resume_file=None,
|
||||
max_shared_memory=1024 * 1024 * 1024, main_window="cli"):
|
||||
super().__init__(name='DLManager')
|
||||
print("plip",main_window.get_title())
|
||||
self.main_window = main_window
|
||||
self.log = logging.getLogger('DLM')
|
||||
self.proc_debug = False
|
||||
|
||||
|
@ -577,7 +581,7 @@ class DLManager(Process):
|
|||
self.log.info(f'Download Manager running with process-id: {os.getpid()}')
|
||||
|
||||
try:
|
||||
self.run_real(main_window)
|
||||
self.run_real(self.main_window)
|
||||
except KeyboardInterrupt:
|
||||
self.log.warning('Immediate exit requested!')
|
||||
self.running = False
|
||||
|
@ -616,6 +620,9 @@ class DLManager(Process):
|
|||
|
||||
self.log.debug(f'Created {len(self.sms)} shared memory segments.')
|
||||
|
||||
obj_out = log_dlm.create(main_window)
|
||||
print("created obj_out")
|
||||
|
||||
# Create queues
|
||||
self.dl_worker_queue = MPQueue(-1)
|
||||
self.writer_queue = MPQueue(-1)
|
||||
|
@ -634,7 +641,9 @@ class DLManager(Process):
|
|||
writer_p = FileWorker(self.writer_queue, self.writer_result_q, self.dl_dir,
|
||||
self.shared_memory.name, self.cache_dir, self.logging_queue)
|
||||
self.children.append(writer_p)
|
||||
print("created obj_ou1t")
|
||||
writer_p.start()
|
||||
print("created obj_ou2t")
|
||||
|
||||
num_chunk_tasks = sum(isinstance(t, ChunkTask) for t in self.tasks)
|
||||
num_dl_tasks = len(self.chunks_to_dl)
|
||||
|
@ -660,8 +669,6 @@ class DLManager(Process):
|
|||
self.threads.append(Thread(target=self.dl_results_handler, args=(task_cond,)))
|
||||
self.threads.append(Thread(target=self.fw_results_handler, args=(shm_cond,)))
|
||||
|
||||
obj_out = log_dlm.create(main_window)
|
||||
|
||||
for t in self.threads:
|
||||
t.start()
|
||||
|
||||
|
@ -728,6 +735,7 @@ class DLManager(Process):
|
|||
r_speed,
|
||||
obj_out
|
||||
)
|
||||
print("updated obj_out")
|
||||
|
||||
# send status update to back to instantiator (if queue exists)
|
||||
if self.status_queue:
|
||||
|
|
Loading…
Reference in a new issue