You've already forked RadioPlayer
mirror of
https://github.com/radio95-rnt/RadioPlayer.git
synced 2026-02-27 06:03:52 +01:00
proper?
This commit is contained in:
144
modules/web.py
144
modules/web.py
@@ -1,62 +1,108 @@
|
|||||||
import multiprocessing, json
|
import multiprocessing
|
||||||
|
import json
|
||||||
|
import threading
|
||||||
|
from functools import partial
|
||||||
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
|
from socketserver import ThreadingMixIn
|
||||||
|
from . import Track, PlayerModule
|
||||||
|
|
||||||
from . import PlayerModule, Track
|
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
|
||||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
"""Handle requests in a separate thread."""
|
||||||
|
|
||||||
manager = multiprocessing.Manager()
|
class APIHandler(BaseHTTPRequestHandler):
|
||||||
data = manager.dict()
|
def __init__(self, data, imc_q, *args, **kwargs):
|
||||||
data_lock = manager.Lock()
|
self.data = data
|
||||||
imc_q = manager.Queue()
|
self.imc_q = imc_q
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
class Handler(BaseHTTPRequestHandler):
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
global data
|
|
||||||
if self.path == "/api/playlist":
|
|
||||||
rdata = str(data["playlist"]).encode()
|
|
||||||
elif self.path == "/api/track":
|
|
||||||
rdata = str(data["track"]).encode()
|
|
||||||
else: rdata = b"?"
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-Length", str(len(rdata)))
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write(rdata)
|
|
||||||
def send_response(self, code, message=None):
|
|
||||||
self.send_response_only(code, message)
|
|
||||||
self.send_header('Server', self.version_string())
|
|
||||||
self.send_header('Date', self.date_time_string())
|
|
||||||
def do_POST(self):
|
|
||||||
global imc_q
|
|
||||||
if self.path == "/api/skip": imc_q.put({"name": "procman", "data": {"op": 2}})
|
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
|
self.send_header("Content-Type", "application/json")
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
|
||||||
def web(): HTTPServer(("0.0.0.0", 3001), Handler).serve_forever()
|
if self.path == "/api/playlist":
|
||||||
p = multiprocessing.Process(target=web)
|
rdata = json.loads(self.data.get("playlist", "[]"))
|
||||||
|
elif self.path == "/api/track":
|
||||||
|
rdata = json.loads(self.data.get("track", "{}"))
|
||||||
|
else:
|
||||||
|
rdata = {"error": "not found"}
|
||||||
|
|
||||||
|
self.wfile.write(json.dumps(rdata).encode('utf-8'))
|
||||||
|
|
||||||
|
def do_POST(self):
|
||||||
|
if self.path == "/api/skip":
|
||||||
|
self.imc_q.put({"name": "procman", "data": {"op": 2}})
|
||||||
|
response = {"status": "ok", "action": "skip requested"}
|
||||||
|
code = 200
|
||||||
|
else:
|
||||||
|
response = {"error": "not found"}
|
||||||
|
code = 404
|
||||||
|
|
||||||
|
self.send_response(code)
|
||||||
|
self.send_header("Content-Type", "application/json")
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(json.dumps(response).encode('utf-8'))
|
||||||
|
|
||||||
|
def web_server_process(data, imc_q):
|
||||||
|
handler = partial(APIHandler, data, imc_q)
|
||||||
|
httpd = ThreadingHTTPServer(("0.0.0.0", 3001), handler)
|
||||||
|
httpd.serve_forever()
|
||||||
|
|
||||||
|
|
||||||
class Module(PlayerModule):
|
class Module(PlayerModule):
|
||||||
def on_new_playlist(self, playlist: list[Track]) -> None:
|
def __init__(self):
|
||||||
global data, data_lock
|
self.manager = multiprocessing.Manager()
|
||||||
with data_lock:
|
self.data = self.manager.dict()
|
||||||
api_data = []
|
self.imc_q = self.manager.Queue()
|
||||||
for track in playlist: api_data.append({"path": str(track.path), "fade_out": track.fade_out, "fade_in": track.fade_in, "official": track.official, "args": track.args, "offset": track.offset})
|
|
||||||
data["playlist"] = json.dumps(api_data)
|
self.data["playlist"] = "[]"
|
||||||
def on_new_track(self, index: int, track: Track, next_track: Track | None) -> None:
|
self.data["track"] = "{}"
|
||||||
global data, data_lock
|
|
||||||
with data_lock:
|
self.ipc_thread_running = True
|
||||||
track_data = {"path": str(track.path), "fade_out": track.fade_out, "fade_in": track.fade_in, "official": track.official, "args": track.args, "offset": track.offset}
|
self.ipc_thread = threading.Thread(target=self._ipc_worker, daemon=True)
|
||||||
if next_track: next_track_data = {"path": str(next_track.path), "fade_out": next_track.fade_out, "fade_in": next_track.fade_in, "official": next_track.official, "args": next_track.args, "offset": next_track.offset}
|
self.ipc_thread.start()
|
||||||
else: next_track_data = None
|
|
||||||
data["track"] = json.dumps({"index": index, "track": track_data, "next_track": next_track_data})
|
self.web_process = multiprocessing.Process(target=web_server_process, args=(self.data, self.imc_q))
|
||||||
def progress(self, index: int, track: Track, elapsed: float, total: float, real_total: float) -> None:
|
self.web_process.start()
|
||||||
try: data = imc_q.get(False)
|
|
||||||
except Exception: return
|
def _ipc_worker(self):
|
||||||
|
while self.ipc_thread_running:
|
||||||
|
try:
|
||||||
|
message = self.imc_q.get()
|
||||||
|
|
||||||
|
if message is None:
|
||||||
|
break
|
||||||
|
|
||||||
|
self._imc.send(self, message["name"], message["data"])
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_new_playlist(self, playlist: list[Track]) -> None:
|
||||||
|
api_data = []
|
||||||
|
for track in playlist:
|
||||||
|
api_data.append({"path": str(track.path), "fade_out": track.fade_out, "fade_in": track.fade_in, "official": track.official, "args": track.args, "offset": track.offset})
|
||||||
|
self.data["playlist"] = json.dumps(api_data)
|
||||||
|
|
||||||
|
def on_new_track(self, index: int, track: Track, next_track: Track | None) -> None:
|
||||||
|
track_data = {"path": str(track.path), "fade_out": track.fade_out, "fade_in": track.fade_in, "official": track.official, "args": track.args, "offset": track.offset}
|
||||||
|
if next_track:
|
||||||
|
next_track_data = {"path": str(next_track.path), "fade_out": next_track.fade_out, "fade_in": next_track.fade_in, "official": next_track.official, "args": next_track.args, "offset": next_track.offset}
|
||||||
|
else:
|
||||||
|
next_track_data = None
|
||||||
|
self.data["track"] = json.dumps({"index": index, "track": track_data, "next_track": next_track_data})
|
||||||
|
|
||||||
self._imc.send(self, data["name"], data["data"])
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
global p
|
print("Shutting down Web API module...")
|
||||||
p.terminate()
|
|
||||||
p.join(1)
|
self.ipc_thread_running = False
|
||||||
p.kill()
|
self.imc_q.put(None)
|
||||||
|
self.ipc_thread.join(timeout=2)
|
||||||
|
|
||||||
|
if self.web_process.is_alive():
|
||||||
|
self.web_process.terminate()
|
||||||
|
self.web_process.join(timeout=2)
|
||||||
|
|
||||||
|
if self.web_process.is_alive():
|
||||||
|
self.web_process.kill()
|
||||||
|
|
||||||
module = Module()
|
module = Module()
|
||||||
p.start()
|
|
||||||
Reference in New Issue
Block a user