def manually_save_queue(self): filename = QtWidgets.QFileDialog.getSaveFileName( self, caption=t("Save Queue"), dir=os.path.expanduser("~"), filter=f"FastFlix Queue File (*.yaml)", ) if filename and filename[0]: save_queue(self.app.fastflix.conversion_list, filename[0], self.app.fastflix.config) message(t("Queue saved to") + f"{filename[0]}")
def start_app(worker_queue, status_queue, log_queue): app = create_app() app.fastflix = FastFlix() app.fastflix.log_queue = log_queue app.fastflix.status_queue = status_queue app.fastflix.worker_queue = worker_queue app.fastflix.config = Config() init_fastflix_directories(app) init_logging(app) register_app() upgraded = app.fastflix.config.upgrade_check() if upgraded: # No translation will be possible in this case message( f"Your config file has been upgraded to FastFlix's new YAML config format\n" f"{app.fastflix.config.config_path}", title="Upgraded", ) try: app.fastflix.config.load() except MissingFF: if reusables.win_based and ask_for_ffmpeg(): try: ProgressBar(app, [Task(t("Downloading FFmpeg"), latest_ffmpeg)], signal_task=True) app.fastflix.config.load() except Exception as err: logger.exception(str(err)) sys.exit(1) except Exception: # TODO give edit / delete options logger.exception(t("Could not load config file!")) sys.exit(1) startup_tasks = [ Task(t("Gather FFmpeg version"), ffmpeg_configuration), Task(t("Gather FFmpeg audio encoders"), ffmpeg_audio_encoders), Task(t("Initialize Encoders"), init_encoders), ] try: ProgressBar(app, startup_tasks) except Exception: logger.exception(f'{t("Could not start FastFlix")}!') sys.exit(1) container = Container(app) container.show() app.exec_()
def download_ffmpeg(self): ffmpeg_folder = Path(user_data_dir("FFmpeg", appauthor=False, roaming=True)) / "bin" ffmpeg = ffmpeg_folder / "ffmpeg.exe" ffprobe = ffmpeg_folder / "ffprobe.exe" try: self.pb = ProgressBar( self.app, [Task(t("Downloading FFmpeg"), latest_ffmpeg)], signal_task=True, can_cancel=True ) except FastFlixInternalException: pass except Exception as err: message(f"{t('Could not download the newest FFmpeg')}: {err}") else: if not ffmpeg.exists() or not ffprobe.exists(): message(f"{t('Could not locate the downloaded files at')} {ffmpeg_folder}!") else: self.app.fastflix.config.ffmpeg = ffmpeg self.app.fastflix.config.ffprobe = ffprobe self.pb = None
def latest_ffmpeg(signal, stop_signal, **_): stop = False def stop_me(): nonlocal stop stop = True stop_signal.connect(stop_me) ffmpeg_folder = Path(user_data_dir("FFmpeg", appauthor=False, roaming=True)) ffmpeg_folder.mkdir(exist_ok=True) url = "https://api.github.com/repos/BtbN/FFmpeg-Builds/releases/latest" try: data = requests.get(url, timeout=15).json() except Exception: message(t("Could not connect to github to check for newer versions.")) raise if stop: message(t("Download Cancelled")) return gpl_ffmpeg = [asset for asset in data["assets"] if asset["name"].endswith("win64-gpl.zip")] if not gpl_ffmpeg: message( t("Could not find any matching FFmpeg ending with 'win64-gpl.zip' with") + f" {t('latest release from')} <a href='https://github.com/BtbN/FFmpeg-Builds/releases/'>" "https://github.com/BtbN/FFmpeg-Builds/releases/</a> " ) raise req = requests.get(gpl_ffmpeg[0]["browser_download_url"], stream=True) filename = ffmpeg_folder / "ffmpeg-full.zip" with open(filename, "wb") as f: for i, block in enumerate(req.iter_content(chunk_size=1024)): if i % 1000 == 0.0: # logger.debug(f"Downloaded {i // 1000}MB") signal.emit(int(((i * 1024) / gpl_ffmpeg[0]["size"]) * 90)) f.write(block) if stop: f.close() Path(filename).unlink() message(t("Download Cancelled")) return if filename.stat().st_size < 1000: message(t("FFmpeg was not properly downloaded as the file size is too small")) try: Path(filename).unlink() except OSError: pass raise try: reusables.extract(filename, path=ffmpeg_folder) except Exception: message(f"{t('Could not extract FFmpeg files from')} {filename}!") raise if stop: Path(filename).unlink() message(t("Download Cancelled")) return signal.emit(95) try: shutil.rmtree(str(ffmpeg_folder / "bin"), ignore_errors=True) shutil.rmtree(str(ffmpeg_folder / "doc"), ignore_errors=True) Path(filename).unlink() except OSError: pass signal.emit(96) sub_dir = next(Path(ffmpeg_folder).glob("ffmpeg-*")) for item in os.listdir(sub_dir): try: shutil.move(str(sub_dir / item), str(ffmpeg_folder)) except Exception as err: message(f"{t('Error while moving files in')} {ffmpeg_folder}: {err}") raise signal.emit(98) shutil.rmtree(sub_dir, ignore_errors=True) signal.emit(100)
def start_app(worker_queue, status_queue, log_queue, queue_list, queue_lock): app = create_app() app.fastflix = FastFlix(queue=queue_list, queue_lock=queue_lock) app.fastflix.log_queue = log_queue app.fastflix.status_queue = status_queue app.fastflix.worker_queue = worker_queue app.fastflix.config = Config() init_fastflix_directories(app) init_logging(app) register_app() upgraded = app.fastflix.config.upgrade_check() if upgraded: # No translation will be possible in this case message( f"Your config file has been upgraded to FastFlix's new YAML config format\n" f"{app.fastflix.config.config_path}", title="Upgraded", ) try: app.fastflix.config.load() except MissingFF as err: if reusables.win_based and ask_for_ffmpeg(): try: ProgressBar(app, [Task(t("Downloading FFmpeg"), latest_ffmpeg)], signal_task=True) app.fastflix.config.load() except Exception as err: logger.exception(str(err)) sys.exit(1) else: logger.error(f"Could not find {err} location, please manually set in {app.fastflix.config.config_path}") sys.exit(1) except Exception: # TODO give edit / delete options logger.exception(t("Could not load config file!")) sys.exit(1) if app.fastflix.config.theme != "system": QtCore.QDir.addSearchPath(app.fastflix.config.theme, str(breeze_styles_path / app.fastflix.config.theme)) file = QtCore.QFile(f"{app.fastflix.config.theme}:stylesheet.qss") file.open(QtCore.QFile.OpenModeFlag.ReadOnly | QtCore.QFile.OpenModeFlag.Text) stream = QtCore.QTextStream(file) data = stream.readAll() if not reusables.win_based: data = data.replace("url(dark:", f"url({str(breeze_styles_path / 'dark')}/") data = data.replace("url(light:", f"url({str(breeze_styles_path / 'light')}/") data = data.replace("url(onyx:", f"url({str(breeze_styles_path / 'onyx')}/") app.setStyleSheet(data) logger.setLevel(app.fastflix.config.logging_level) startup_tasks = [ Task(t("Gather FFmpeg version"), ffmpeg_configuration), Task(t("Gather FFprobe version"), ffprobe_configuration), Task(t("Gather FFmpeg audio encoders"), ffmpeg_audio_encoders), Task(t("Determine OpenCL Support"), ffmpeg_opencl_support), Task(t("Initialize Encoders"), init_encoders), ] try: ProgressBar(app, startup_tasks) except Exception: logger.exception(f'{t("Could not start FastFlix")}!') sys.exit(1) container = Container(app) container.show() try: app.exec_() except Exception: logger.exception("Error while running FastFlix") raise
def start_app(worker_queue, status_queue, log_queue, queue_list, queue_lock): app = create_app() app.fastflix = FastFlix(queue=queue_list, queue_lock=queue_lock) app.fastflix.log_queue = log_queue app.fastflix.status_queue = status_queue app.fastflix.worker_queue = worker_queue app.fastflix.config = Config() init_fastflix_directories(app) init_logging(app) register_app() upgraded = app.fastflix.config.upgrade_check() if upgraded: # No translation will be possible in this case message( f"Your config file has been upgraded to FastFlix's new YAML config format\n" f"{app.fastflix.config.config_path}", title="Upgraded", ) try: app.fastflix.config.load() except MissingFF as err: if reusables.win_based and ask_for_ffmpeg(): try: ProgressBar(app, [Task(t("Downloading FFmpeg"), latest_ffmpeg)], signal_task=True) app.fastflix.config.load() except Exception as err: logger.exception(str(err)) sys.exit(1) else: logger.error( f"Could not find {err} location, please manually set in {app.fastflix.config.config_path}" ) sys.exit(1) except Exception: # TODO give edit / delete options logger.exception(t("Could not load config file!")) sys.exit(1) if app.fastflix.config.flat_ui: app.setStyleSheet(default_mode) logger.setLevel(app.fastflix.config.logging_level) startup_tasks = [ Task(t("Gather FFmpeg version"), ffmpeg_configuration), Task(t("Gather FFprobe version"), ffprobe_configuration), Task(t("Gather FFmpeg audio encoders"), ffmpeg_audio_encoders), Task(t("Initialize Encoders"), init_encoders), ] try: ProgressBar(app, startup_tasks) except Exception: logger.exception(f'{t("Could not start FastFlix")}!') sys.exit(1) container = Container(app) container.show() try: app.exec_() except Exception: logger.exception("Error while running FastFlix") raise
def required_info(logger, data_path, log_dir): if reusables.win_based: # This fixes the taskbar icon not always appearing try: import ctypes app_id = f"cdgriffith.fastflix.{__version__}".encode("utf-8") ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( app_id) except Exception: logger.exception( "Could not set application ID for Windows, please raise issue in github with above error" ) ffmpeg_folder = Path(user_data_dir("FFmpeg", appauthor=False, roaming=True)) ffmpeg = shutil.which("ffmpeg") if ffmpeg: ffmpeg = Path(ffmpeg).resolve() ffprobe = shutil.which("ffprobe") if ffprobe: ffprobe = Path(ffprobe).resolve() if ffmpeg_folder.exists(): for file in ffmpeg_folder.iterdir(): if file.is_file() and file.name.lower() in ("ffmpeg", "ffmpeg.exe"): ffmpeg = file if file.is_file() and file.name.lower() in ("ffprobe", "ffprobe.exe"): ffprobe = file if (not ffmpeg or not ffprobe) and (ffmpeg_folder / "bin").exists(): for file in (ffmpeg_folder / "bin").iterdir(): if file.is_file() and file.name.lower() in ("ffmpeg", "ffmpeg.exe"): ffmpeg = file if file.is_file() and file.name.lower() in ("ffprobe", "ffprobe.exe"): ffprobe = file logger.addHandler( logging.FileHandler(log_dir / f"flix_gui_{file_date()}.log", encoding="utf-8")) config_file = Path(data_path, "fastflix.json") logger.debug(f'Using config file "{config_file}"') if not config_file.exists(): config = Box({ "version": __version__, "work_dir": str(data_path), "disable_update_check": False }) config.to_json(filename=config_file, indent=2) else: try: config = Box.from_json(filename=config_file) except JSONDecodeError as err: logger.exception(f'Error with config file: "{config_file}"') error_message( msg=f"Bad config file: {config_file}" "<br> If you are unsure what to do, just delete the file" f"<br><br>Error: {err}", traceback=True, ) sys.exit(1) if "version" not in config or "work_dir" not in config: message( "Config file does not have all required fields, adding defaults" ) config.version = __version__ config.work_dir = str(data_path) config.disable_update_check = False config.to_json(filename=config_file, indent=2) if StrictVersion(config.version) < StrictVersion(__version__): message( f"<h2 style='text-align: center;'>Welcome to FastFlix {__version__}!</h2><br>" f"<p style='text-align: center; font-size: 15px;'>Please check out the changes made since your last " f"update ({config.version})<br>View the change log in the Help menu (Alt+H then C)<br></p>" ) config.version = __version__ config.to_json(filename=config_file, indent=2) if "ffmpeg" in config: ffmpeg = Path(config.ffmpeg) if "ffprobe" in config: ffprobe = Path(config.ffprobe) work_dir = Path(config.get("work_dir", data_path)) if not work_dir.exists(): try: work_dir.mkdir(parents=True, exist_ok=True) except OSError as err: logger.error(f"Cannot use specified working directory {work_dir}" f" - Falling back to {data_path} due to error: {err}") work_dir = data_path work_dir.mkdir(parents=True, exist_ok=True) if not ffmpeg or not ffprobe: qm = QtWidgets.QMessageBox if reusables.win_based: ret = qm.question( None, "FFmpeg not found!", f"<h2>FFmpeg not found!</h2> <br> Automatically download FFmpeg?", qm.Yes | qm.No, ) if ret == qm.Yes: try: windows_download_ffmpeg(ffmpeg_folder) except Exception as err: logger.exception("Could not download FFmpeg") sys.exit(2) else: ffmpeg = ffmpeg_folder / "bin" / "ffmpeg.exe" ffprobe = ffmpeg_folder / "bin" / "ffprobe.exe" else: sys.exit(1) else: qm.question( None, "FFmpeg not found!", "<h2>FFmpeg not found!</h2> " "Please <a href='https://ffmpeg.org/download.html'>download a static FFmpeg</a> and add it to PATH", qm.Close, ) sys.exit(1) else: logger.info(f"Using FFmpeg {ffmpeg}") logger.info(f"Using FFprobe {ffprobe}") try: flix = Flix(ffmpeg=ffmpeg, ffprobe=ffprobe) except FlixError: error_message("FFmpeg or FFmpeg could not be executed properly!<br>", traceback=True) sys.exit(1) if not config.get("disable_update_check"): latest_fastflix() return flix, work_dir, config_file