{slots_used}/{MAX_CONCURRENT_GAMES} game slots in use
DOSBox games
| Game | Release | Publisher | Size | Status | Actions | | Volume |
{''.join(rows) if rows else '| No game manifests found on the share |
'}
"""
class Handler(BaseHTTPRequestHandler):
def log_message(self, fmt, *args):
pass
def _send_html(self, body, status=200):
encoded = body.encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(encoded)))
self.end_headers()
self.wfile.write(encoded)
def _send_file(self, path, content_type):
try:
with open(path, "rb") as f:
content = f.read()
except OSError:
self._send_html("Not found", status=404)
return
self.send_response(200)
self.send_header("Content-Type", content_type)
self.send_header("Content-Length", str(len(content)))
self.end_headers()
self.wfile.write(content)
def do_GET(self):
path = urlparse(self.path).path
if path == "/":
host = self.headers.get("Host", "localhost").rsplit(":", 1)[0]
self._send_html(render_page(host))
elif path == "/pcm-worklet.js":
self._send_file(os.path.join(SCRIPTS_HOME, "pcm-worklet.js"), "application/javascript")
else:
self._send_html("Not found", status=404)
def do_POST(self):
action = urlparse(self.path).path.lstrip("/")
if action not in ("install", "uninstall", "start", "stop", "volume"):
self._send_html("Not found", status=404)
return
length = int(self.headers.get("Content-Length", 0))
body = self.rfile.read(length).decode("utf-8")
params = parse_qs(body)
name = params.get("name", [""])[0]
if action == "volume":
# Fired on every slider tick via fetch(), not a form submit - no page navigation.
try:
level = int(params.get("level", ["100"])[0])
except ValueError:
level = 100
set_volume(name, level)
self.send_response(204)
self.end_headers()
return
games = discover_games()
if name in games:
manifest = games[name]
if action == "install":
threading.Thread(target=install_game, args=(name, manifest), daemon=True).start()
elif action == "uninstall":
threading.Thread(target=uninstall_game, args=(name,), daemon=True).start()
elif action == "start":
program_id = params.get("program", [""])[0]
threading.Thread(target=start_game, args=(name, manifest, program_id), daemon=True).start()
elif action == "stop":
threading.Thread(target=stop_game, args=(name,), daemon=True).start()
# No redirect: the client's own doAction()/refresh() re-fetches "/" itself and
# replaces #content in place, never navigating the page (see render_page()'s JS).
self.send_response(204)
self.end_headers()
if __name__ == "__main__":
ThreadingHTTPServer(("0.0.0.0", SETUP_PORT), Handler).serve_forever()