generated from SteamDeckHomebrew/decky-plugin-template
-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathmain.py
151 lines (127 loc) · 6.02 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import decky # Old-style Decky import
import os
import subprocess
import json
from pathlib import Path
class Plugin:
async def _main(self):
decky.logger.info("Framegen plugin loaded")
async def _unload(self):
decky.logger.info("Framegen plugin unloaded.")
async def run_uninstall_fgmod(self) -> dict:
try:
result = subprocess.run(
["/bin/bash", Path(decky.DECKY_PLUGIN_DIR) / "assets" / "fgmod-remover.sh"],
capture_output=True,
text=True,
check=True
)
return {"status": "success", "output": result.stdout}
except subprocess.CalledProcessError as e:
decky.logger.error(e.output)
return {"status": "error", "message": str(e), "output": e.output}
async def run_install_fgmod(self) -> dict:
try:
assets_dir = Path(decky.DECKY_PLUGIN_DIR) / "assets"
prepare_script = assets_dir / "prepare.sh"
if not prepare_script.exists():
decky.logger.error(f"prepare.sh not found: {prepare_script}")
return {
"status": "error",
"message": f"prepare.sh not found in plugin assets."
}
# Ensure prepare.sh has execution permissions
prepare_script.chmod(0o755)
# Run prepare.sh directly from the plugin's assets folder
process = subprocess.run(
["/bin/bash", str(prepare_script)],
cwd=str(assets_dir), # Run in assets directory to use correct paths
capture_output=True,
text=True,
timeout=300
)
decky.logger.info(f"Script output:\n{process.stdout}")
decky.logger.error(f"Script errors:\n{process.stderr}")
if "All done!" not in process.stdout:
decky.logger.error("Installation did not complete successfully")
return {
"status": "error",
"message": process.stdout + process.stderr
}
return {
"status": "success",
"output": "You can now replace DLSS with FSR Frame Gen!"
}
except subprocess.TimeoutExpired:
decky.logger.error("Installation script timed out")
return {
"status": "error",
"message": "Installation timed out"
}
except subprocess.CalledProcessError as e:
decky.logger.error(f"Script error: {e.stderr}")
return {
"status": "error",
"message": e.stderr
}
except Exception as e:
decky.logger.error(f"Unexpected error: {str(e)}")
return {
"status": "error",
"message": str(e)
}
async def check_fgmod_path(self) -> dict:
path = Path(decky.HOME) / "fgmod"
required_files = [
"amd_fidelityfx_dx12.dll", "amd_fidelityfx_vk.dll", "d3dcompiler_47.dll", "DisableNvidiaSignatureChecks.reg",
"dlss-enabler.dll", "dlss-enabler-upscaler.dll", "dlssg_to_fsr3_amd_is_better-3.0.dll", "dlssg_to_fsr3_amd_is_better.dll",
"dlssg_to_fsr3.ini", "dxgi.dll", "dxvk.conf", "fakenvapi.ini", "fgmod", "fgmod-uninstaller.sh",
"libxess.dll", "nvapi64.dll", "nvngx.ini", "nvngx-wrapper.dll", "_nvngx.dll", "RestoreNvidiaSignatureChecks.reg"
]
if path.exists():
for file_name in required_files:
if not path.joinpath(file_name).exists():
return {"exists": False}
return {"exists": True}
else:
return {"exists": False}
async def list_installed_games(self) -> dict:
try:
steam_root = Path(decky.HOME) / ".steam" / "steam"
library_file = Path(steam_root) / "steamapps" / "libraryfolders.vdf"
if not library_file.exists():
return {"status": "error", "message": "libraryfolders.vdf not found"}
library_paths = []
with open(library_file, "r", encoding="utf-8", errors="replace") as file:
for line in file:
if '"path"' in line:
path = line.split('"path"')[1].strip().strip('"').replace("\\\\", "/")
library_paths.append(path)
games = []
for library_path in library_paths:
steamapps_path = Path(library_path) / "steamapps"
if not steamapps_path.exists():
continue
for appmanifest in steamapps_path.glob("appmanifest_*.acf"):
game_info = {"appid": None, "name": None}
try:
with open(appmanifest, "r", encoding="utf-8") as file:
for line in file:
if '"appid"' in line:
game_info["appid"] = line.split('"appid"')[1].strip().strip('"')
if '"name"' in line:
game_info["name"] = line.split('"name"')[1].strip().strip('"')
except UnicodeDecodeError as e:
decky.logger.error(f"Skipping {appmanifest} due to encoding issue: {e}")
finally:
pass # Ensures loop continues even if an error occurs
if game_info["appid"] and game_info["name"]:
games.append(game_info)
# Filter out games whose name contains "Proton" or "Steam Linux Runtime"
filtered_games = [g for g in games if "Proton" not in g["name"] and "Steam Linux Runtime" not in g["name"]]
return {"status": "success", "games": filtered_games}
except Exception as e:
decky.logger.error(str(e))
return {"status": "error", "message": str(e)}
async def log_error(self, error: str) -> None:
decky.logger.error(f"FRONTEND: {error}")