summaryrefslogtreecommitdiff
path: root/main.py
diff options
context:
space:
mode:
Diffstat (limited to 'main.py')
-rw-r--r--main.py180
1 files changed, 166 insertions, 14 deletions
diff --git a/main.py b/main.py
index 65a10da..3d24f94 100644
--- a/main.py
+++ b/main.py
@@ -1,4 +1,8 @@
import os
+import tarfile
+import shutil
+import subprocess
+import tempfile
# The decky plugin module is located at decky-loader/plugin
# For easy intellisense checkout the decky-loader code repo
@@ -7,35 +11,183 @@ import decky
import asyncio
class Plugin:
- # A normal method. It can be called from the TypeScript side using @decky/api.
- async def add(self, left: int, right: int) -> int:
- return left + right
+ async def install_lsfg_vk(self) -> dict:
+ """Install lsfg-vk by extracting the tar.gz file to ~/.local"""
+ try:
+ # Get the path to the lsfg-vk-latest.tar.gz file in the bin directory
+ plugin_dir = os.path.dirname(os.path.realpath(__file__))
+ tar_path = os.path.join(plugin_dir, "bin", "lsfg-vk-latest.tar.gz")
+
+ # Check if the tar.gz file exists
+ if not os.path.exists(tar_path):
+ decky.logger.error(f"lsfg-vk-latest.tar.gz not found at {tar_path}")
+ return {"success": False, "error": "lsfg-vk-latest.tar.gz file not found"}
+
+ # Get the user's home directory
+ user_home = os.path.expanduser("~")
+ local_lib_dir = os.path.join(user_home, ".local", "lib")
+ local_share_dir = os.path.join(user_home, ".local", "share", "vulkan", "implicit_layer.d")
+
+ # Create directories if they don't exist
+ os.makedirs(local_lib_dir, exist_ok=True)
+ os.makedirs(local_share_dir, exist_ok=True)
+
+ # Extract the tar.gz file
+ with tarfile.open(tar_path, 'r:gz') as tar_ref:
+ # Use /tmp for temporary extraction since we may not have write permissions in plugin dir
+ with tempfile.TemporaryDirectory() as temp_dir:
+ tar_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(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(local_share_dir, file)
+ shutil.copy2(src_file, dst_file)
+ decky.logger.info(f"Copied {file} to {dst_file}")
+
+ # temp_dir will be automatically cleaned up
+
+ 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)}
- async def long_running(self):
- await asyncio.sleep(15)
- # Passing through a bunch of random data, just as an example
- await decky.emit("timer_event", "Hello from the backend!", True, 2)
+ async def check_lsfg_vk_installed(self) -> dict:
+ """Check if lsfg-vk is already installed"""
+ try:
+ user_home = os.path.expanduser("~")
+ lib_file = os.path.join(user_home, ".local", "lib", "liblsfg-vk.so")
+ json_file = os.path.join(user_home, ".local", "share", "vulkan", "implicit_layer.d", "VkLayer_LS_frame_generation.json")
+
+ lib_exists = os.path.exists(lib_file)
+ json_exists = os.path.exists(json_file)
+
+ return {
+ "installed": lib_exists and json_exists,
+ "lib_exists": lib_exists,
+ "json_exists": json_exists,
+ "lib_path": lib_file,
+ "json_path": json_file
+ }
+
+ except Exception as e:
+ decky.logger.error(f"Error checking lsfg-vk installation: {str(e)}")
+ return {"installed": False, "error": str(e)}
+
+ async def uninstall_lsfg_vk(self) -> dict:
+ """Uninstall lsfg-vk by removing the installed files"""
+ try:
+ user_home = os.path.expanduser("~")
+ lib_file = os.path.join(user_home, ".local", "lib", "liblsfg-vk.so")
+ json_file = os.path.join(user_home, ".local", "share", "vulkan", "implicit_layer.d", "VkLayer_LS_frame_generation.json")
+
+ removed_files = []
+
+ # Remove library file if it exists
+ if os.path.exists(lib_file):
+ os.remove(lib_file)
+ removed_files.append(lib_file)
+ decky.logger.info(f"Removed {lib_file}")
+
+ # Remove JSON file if it exists
+ if os.path.exists(json_file):
+ os.remove(json_file)
+ removed_files.append(json_file)
+ decky.logger.info(f"Removed {json_file}")
+
+ 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)}
+
+ async def check_lossless_scaling_dll(self) -> dict:
+ """Check if Lossless Scaling DLL is available at the expected paths"""
+ try:
+ # Check environment variable first
+ dll_path = os.getenv("LSFG_DLL_PATH")
+ if dll_path and dll_path.strip():
+ dll_path_str = dll_path.strip()
+ if os.path.exists(dll_path_str):
+ return {
+ "detected": True,
+ "path": dll_path_str,
+ "source": "LSFG_DLL_PATH environment variable"
+ }
+
+ # Check XDG_DATA_HOME path
+ data_dir = os.getenv("XDG_DATA_HOME")
+ if data_dir and data_dir.strip():
+ dll_path_str = os.path.join(data_dir.strip(), "Steam", "steamapps", "common", "Lossless Scaling", "Lossless.dll")
+ if os.path.exists(dll_path_str):
+ return {
+ "detected": True,
+ "path": dll_path_str,
+ "source": "XDG_DATA_HOME Steam directory"
+ }
+
+ # Check HOME/.local/share path
+ home_dir = os.getenv("HOME")
+ if home_dir and home_dir.strip():
+ dll_path_str = os.path.join(home_dir.strip(), ".local", "share", "Steam", "steamapps", "common", "Lossless Scaling", "Lossless.dll")
+ if os.path.exists(dll_path_str):
+ return {
+ "detected": True,
+ "path": dll_path_str,
+ "source": "HOME/.local/share Steam directory"
+ }
+
+ # DLL not found in any expected location
+ return {
+ "detected": False,
+ "path": None,
+ "source": None,
+ "message": "Lossless Scaling DLL not found in expected locations"
+ }
+
+ except Exception as e:
+ decky.logger.error(f"Error checking Lossless Scaling DLL: {str(e)}")
+ return {
+ "detected": False,
+ "path": None,
+ "source": None,
+ "error": str(e)
+ }
# Asyncio-compatible long-running code, executed in a task when the plugin is loaded
async def _main(self):
- self.loop = asyncio.get_event_loop()
- decky.logger.info("Hello World!")
+ decky.logger.info("lsfg-vk Installer loaded!")
# Function called first during the unload process, utilize this to handle your plugin being stopped, but not
# completely removed
async def _unload(self):
- decky.logger.info("Goodnight World!")
+ decky.logger.info("lsfg-vk Installer unloading")
pass
# Function called after `_unload` during uninstall, utilize this to clean up processes and other remnants of your
# plugin that may remain on the system
async def _uninstall(self):
- decky.logger.info("Goodbye World!")
+ decky.logger.info("lsfg-vk Installer uninstalled")
pass
- async def start_timer(self):
- self.loop.create_task(self.long_running())
-
# Migrations that should be performed before entering `_main()`.
async def _migration(self):
decky.logger.info("Migrating")