diff options
| author | xXJSONDeruloXx <danielhimebauch@gmail.com> | 2025-07-13 00:04:54 -0400 |
|---|---|---|
| committer | xXJSONDeruloXx <danielhimebauch@gmail.com> | 2025-07-13 00:04:54 -0400 |
| commit | 77494457e2a4f5c80c3a2f7acb054b12d918d8ad (patch) | |
| tree | fad4c4dd2ce69a850b56078444427866dedce9fa /src/services/installation_service.py | |
| parent | 6cfcaa6c169cb8c898775eee276ff2497ab8f45c (diff) | |
| download | decky-lsfg-vk-77494457e2a4f5c80c3a2f7acb054b12d918d8ad.tar.gz decky-lsfg-vk-77494457e2a4f5c80c3a2f7acb054b12d918d8ad.zip | |
restructure for maintainability
Diffstat (limited to 'src/services/installation_service.py')
| -rw-r--r-- | src/services/installation_service.py | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/services/installation_service.py b/src/services/installation_service.py new file mode 100644 index 0000000..92d5132 --- /dev/null +++ b/src/services/installation_service.py @@ -0,0 +1,205 @@ +import os +import zipfile +import shutil +import tempfile +from typing import Dict, Any +import decky + + +class InstallationService: + """Service for handling lsfg-vk installation and uninstallation""" + + def __init__(self): + self.user_home = os.path.expanduser("~") + self.local_lib_dir = os.path.join(self.user_home, ".local", "lib") + self.local_share_dir = os.path.join(self.user_home, ".local", "share", "vulkan", "implicit_layer.d") + self.lsfg_script_path = os.path.join(self.user_home, "lsfg") + + # File paths + self.lib_file = os.path.join(self.local_lib_dir, "liblsfg-vk.so") + self.json_file = os.path.join(self.local_share_dir, "VkLayer_LS_frame_generation.json") + + async def install(self) -> Dict[str, Any]: + """Install lsfg-vk by extracting the zip file to ~/.local""" + try: + # Get the path to the lsfg-vk_archlinux.zip file in the bin directory + plugin_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + zip_path = os.path.join(plugin_dir, "bin", "lsfg-vk_archlinux.zip") + + # Check if the zip file exists + if not os.path.exists(zip_path): + decky.logger.error(f"lsfg-vk_archlinux.zip not found at {zip_path}") + return {"success": False, "error": "lsfg-vk_archlinux.zip file not found"} + + # Create directories if they don't exist + os.makedirs(self.local_lib_dir, exist_ok=True) + os.makedirs(self.local_share_dir, exist_ok=True) + + # Extract the zip file + with zipfile.ZipFile(zip_path, 'r') as zip_ref: + # Use /tmp for temporary extraction since we may not have write permissions in plugin dir + with tempfile.TemporaryDirectory() as temp_dir: + zip_ref.extractall(temp_dir) + + # Look for the extracted files and copy them to the correct locations + for root, dirs, files in os.walk(temp_dir): + for file in files: + src_file = os.path.join(root, file) + if file.endswith('.so'): + # Copy library files to ~/.local/lib + dst_file = os.path.join(self.local_lib_dir, file) + shutil.copy2(src_file, dst_file) + decky.logger.info(f"Copied {file} to {dst_file}") + elif file.endswith('.json'): + # Copy JSON files to ~/.local/share/vulkan/implicit_layer.d + dst_file = os.path.join(self.local_share_dir, file) + shutil.copy2(src_file, dst_file) + decky.logger.info(f"Copied {file} to {dst_file}") + + # Create the lsfg script + self._create_lsfg_script() + + decky.logger.info("lsfg-vk installed successfully") + return {"success": True, "message": "lsfg-vk installed successfully"} + + except Exception as e: + decky.logger.error(f"Error installing lsfg-vk: {str(e)}") + return {"success": False, "error": str(e)} + + def _create_lsfg_script(self): + """Create the lsfg script in home directory""" + script_content = """#!/bin/bash + +export ENABLE_LSFG=1 +export LSFG_MULTIPLIER=2 +export LSFG_FLOW_SCALE=1.0 +# export LSFG_HDR=1 +# export LSFG_PERF_MODE=1 +# export MESA_VK_WSI_PRESENT_MODE=immediate # - disable vsync + +# Execute the passed command with the environment variables set +exec "$@" +""" + + with open(self.lsfg_script_path, 'w') as script_file: + script_file.write(script_content) + + # Make the script executable + os.chmod(self.lsfg_script_path, 0o755) + decky.logger.info(f"Created executable lsfg script at {self.lsfg_script_path}") + + async def check_installation(self) -> Dict[str, Any]: + """Check if lsfg-vk is already installed""" + try: + lib_exists = os.path.exists(self.lib_file) + json_exists = os.path.exists(self.json_file) + script_exists = os.path.exists(self.lsfg_script_path) + + decky.logger.info(f"Installation check: lib={lib_exists}, json={json_exists}, script={script_exists}") + + return { + "installed": lib_exists and json_exists, + "lib_exists": lib_exists, + "json_exists": json_exists, + "script_exists": script_exists, + "lib_path": self.lib_file, + "json_path": self.json_file, + "script_path": self.lsfg_script_path + } + + except Exception as e: + decky.logger.error(f"Error checking lsfg-vk installation: {str(e)}") + return {"installed": False, "error": str(e)} + + async def uninstall(self) -> Dict[str, Any]: + """Uninstall lsfg-vk by removing the installed files""" + try: + removed_files = [] + + # Remove library file if it exists + if os.path.exists(self.lib_file): + os.remove(self.lib_file) + removed_files.append(self.lib_file) + decky.logger.info(f"Removed {self.lib_file}") + + # Remove JSON file if it exists + if os.path.exists(self.json_file): + os.remove(self.json_file) + removed_files.append(self.json_file) + decky.logger.info(f"Removed {self.json_file}") + + # Remove lsfg script if it exists + if os.path.exists(self.lsfg_script_path): + os.remove(self.lsfg_script_path) + removed_files.append(self.lsfg_script_path) + decky.logger.info(f"Removed {self.lsfg_script_path}") + + if not removed_files: + return {"success": True, "message": "No lsfg-vk files found to remove"} + + decky.logger.info("lsfg-vk uninstalled successfully") + return { + "success": True, + "message": f"lsfg-vk uninstalled successfully. Removed {len(removed_files)} files.", + "removed_files": removed_files + } + + except Exception as e: + decky.logger.error(f"Error uninstalling lsfg-vk: {str(e)}") + return {"success": False, "error": str(e)} + + def cleanup_on_uninstall(self) -> None: + """Clean up lsfg-vk files when the plugin is uninstalled""" + try: + decky.logger.info(f"Checking for lsfg-vk files to clean up:") + decky.logger.info(f" Library file: {self.lib_file}") + decky.logger.info(f" JSON file: {self.json_file}") + decky.logger.info(f" lsfg script: {self.lsfg_script_path}") + + removed_files = [] + + # Remove library file if it exists + if os.path.exists(self.lib_file): + decky.logger.info(f"Found library file, attempting to remove: {self.lib_file}") + try: + os.remove(self.lib_file) + removed_files.append(self.lib_file) + decky.logger.info(f"Successfully removed {self.lib_file}") + except Exception as e: + decky.logger.error(f"Failed to remove {self.lib_file}: {str(e)}") + else: + decky.logger.info(f"Library file not found: {self.lib_file}") + + # Remove JSON file if it exists + if os.path.exists(self.json_file): + decky.logger.info(f"Found JSON file, attempting to remove: {self.json_file}") + try: + os.remove(self.json_file) + removed_files.append(self.json_file) + decky.logger.info(f"Successfully removed {self.json_file}") + except Exception as e: + decky.logger.error(f"Failed to remove {self.json_file}: {str(e)}") + else: + decky.logger.info(f"JSON file not found: {self.json_file}") + + # Remove lsfg script if it exists + if os.path.exists(self.lsfg_script_path): + decky.logger.info(f"Found lsfg script, attempting to remove: {self.lsfg_script_path}") + try: + os.remove(self.lsfg_script_path) + removed_files.append(self.lsfg_script_path) + decky.logger.info(f"Successfully removed {self.lsfg_script_path}") + except Exception as e: + decky.logger.error(f"Failed to remove {self.lsfg_script_path}: {str(e)}") + else: + decky.logger.info(f"lsfg script not found: {self.lsfg_script_path}") + + if removed_files: + decky.logger.info(f"Cleaned up {len(removed_files)} lsfg-vk files during plugin uninstall: {removed_files}") + else: + decky.logger.info("No lsfg-vk files found to clean up during plugin uninstall") + + except Exception as e: + decky.logger.error(f"Error cleaning up lsfg-vk files during uninstall: {str(e)}") + import traceback + decky.logger.error(f"Traceback: {traceback.format_exc()}") |
