Add linting for autopep8

This commit is contained in:
Matthew Stratford 2021-09-11 17:18:35 +01:00
parent 2941d90f60
commit e5e3267e75
10 changed files with 145 additions and 91 deletions

View file

@ -0,0 +1,3 @@
flake8
black
autopep8

View file

@ -1,4 +1,4 @@
autopep8 wheel
pygame==2.0.1 pygame==2.0.1
sanic==21.3.4 sanic==21.3.4
sanic-Cors==1.0.0 sanic-Cors==1.0.0

View file

@ -41,7 +41,7 @@ class FileManager:
while not terminator.terminate: while not terminator.terminate:
# If all channels have received the delete command, reset for the next one. # If all channels have received the delete command, reset for the next one.
if ( if (
self.channel_received == None self.channel_received is None
or self.channel_received == [True] * self.channel_count or self.channel_received == [True] * self.channel_count
): ):
self.channel_received = [False] * self.channel_count self.channel_received = [False] * self.channel_count
@ -60,18 +60,22 @@ class FileManager:
if command == "GETPLAN": if command == "GETPLAN":
if ( if (
self.channel_received != [False] * self.channel_count self.channel_received != [
False] * self.channel_count
and self.channel_received[channel] != True and self.channel_received[channel] != True
): ):
# We've already received a delete trigger on a channel, let's not delete the folder more than once. # We've already received a delete trigger on a channel, let's not delete the folder more than once.
# If the channel was already in the process of being deleted, the user has requested it again, so allow it. # If the channel was already in the process of being deleted, the user has
# requested it again, so allow it.
self.channel_received[channel] = True self.channel_received[channel] = True
continue continue
# Delete the previous show files! # Delete the previous show files!
# Note: The players load into RAM. If something is playing over the load, the source file can still be deleted. # Note: The players load into RAM. If something is playing over the load,
path: str = resolve_external_file_path("/music-tmp/") # the source file can still be deleted.
path: str = resolve_external_file_path(
"/music-tmp/")
if not os.path.isdir(path): if not os.path.isdir(path):
self.logger.log.warning( self.logger.log.warning(
@ -102,7 +106,8 @@ class FileManager:
) )
continue continue
self.channel_received[channel] = True self.channel_received[channel] = True
self.known_channels_preloaded = [False] * self.channel_count self.known_channels_preloaded = [
False] * self.channel_count
self.known_channels_normalised = [ self.known_channels_normalised = [
False False
] * self.channel_count ] * self.channel_count
@ -142,7 +147,8 @@ class FileManager:
sleep(0.2) sleep(0.2)
except Exception as e: except Exception as e:
self.logger.log.exception("Received unexpected exception: {}".format(e)) self.logger.log.exception(
"Received unexpected exception: {}".format(e))
del self.logger del self.logger
# Attempt to preload a file onto disk. # Attempt to preload a file onto disk.
@ -169,7 +175,8 @@ class FileManager:
) )
) )
# Getting the file name will only pull the new file if the file doesn't already exist, so this is not too inefficient. # Getting the file name will only pull the new file if the file doesn't
# already exist, so this is not too inefficient.
item_obj.filename, did_download = sync( item_obj.filename, did_download = sync(
self.api.get_filename(item_obj, True) self.api.get_filename(item_obj, True)
) )
@ -181,7 +188,8 @@ class FileManager:
if did_download: if did_download:
downloaded_something = True downloaded_something = True
self.logger.log.info( self.logger.log.info(
"File successfully preloaded: {}".format(item_obj.filename) "File successfully preloaded: {}".format(
item_obj.filename)
) )
break break
else: else:
@ -189,7 +197,8 @@ class FileManager:
# Let's try the next one. # Let's try the next one.
continue continue
# Tell the file manager that this channel is fully downloaded, this is so it can consider normalising once all channels have files. # Tell the file manager that this channel is fully downloaded, this is so
# it can consider normalising once all channels have files.
self.known_channels_preloaded[channel] = not downloaded_something self.known_channels_preloaded[channel] = not downloaded_something
self.next_channel_preload += 1 self.next_channel_preload += 1
@ -241,7 +250,8 @@ class FileManager:
normalised_something = True normalised_something = True
break # Now go let another channel have a go. break # Now go let another channel have a go.
except Exception as e: except Exception as e:
self.logger.log.exception("Failed to generate normalised file.", str(e)) self.logger.log.exception(
"Failed to generate normalised file.", str(e))
continue continue
self.known_channels_normalised[channel] = not normalised_something self.known_channels_normalised[channel] = not normalised_something

View file

@ -39,7 +39,8 @@ def startServer(notifications=False):
# Catch the handler being killed externally. # Catch the handler being killed externally.
except Exception as e: except Exception as e:
printer("Received Exception {} with args: {}".format(type(e).__name__, e.args)) printer("Received Exception {} with args: {}".format(
type(e).__name__, e.args))
if server and server.is_alive(): if server and server.is_alive():
server.terminate() server.terminate()
server.join() server.join()

View file

@ -12,7 +12,8 @@
"presenter-install": "cd presenter && git submodule update --init && yarn --network-timeout 100000", "presenter-install": "cd presenter && git submodule update --init && yarn --network-timeout 100000",
"presenter-make": "npm run presenter-install && (rm -r presenter-build || true) && cd presenter && yarn build-baps && cp -r build ../presenter-build && cd ../ && npm install", "presenter-make": "npm run presenter-install && (rm -r presenter-build || true) && cd presenter && yarn build-baps && cp -r build ../presenter-build && cd ../ && npm install",
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"presenter-start": "cd presenter && yarn start" "presenter-start": "cd presenter && yarn start",
"lint": "autopep8 -r ./*.py -a -a --ignore E402,E226,E24,W50,W690 --max-line-length 127 --in-place"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

125
player.py
View file

@ -20,29 +20,28 @@
# that we respond with something, FAIL or OKAY. The server doesn't like to be kept waiting. # that we respond with something, FAIL or OKAY. The server doesn't like to be kept waiting.
# Stop the Pygame Hello message. # Stop the Pygame Hello message.
import package
from baps_types.marker import Marker
from baps_types.plan import PlanItem
from helpers.logging_manager import LoggingManager
from helpers.state_manager import StateManager
from helpers.myradio_api import MyRadioAPI
from helpers.normalisation import get_normalised_filename_if_available
from threading import Timer
from syncer import sync
from mutagen.mp3 import MP3
from pygame import mixer
from typing import Any, Callable, Dict, List, Optional
import time
import json
import copy
import setproctitle
import multiprocessing
from queue import Empty
import os import os
os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "hide" os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "hide"
from queue import Empty
import multiprocessing
import setproctitle
import copy
import json
import time
from typing import Any, Callable, Dict, List, Optional
from pygame import mixer
from mutagen.mp3 import MP3
from syncer import sync
from threading import Timer
from helpers.normalisation import get_normalised_filename_if_available
from helpers.myradio_api import MyRadioAPI
from helpers.state_manager import StateManager
from helpers.logging_manager import LoggingManager
from baps_types.plan import PlanItem
from baps_types.marker import Marker
import package
# TODO ENUM # TODO ENUM
VALID_MESSAGE_SOURCES = ["WEBSOCKET", "UI", "CONTROLLER", "TEST", "ALL"] VALID_MESSAGE_SOURCES = ["WEBSOCKET", "UI", "CONTROLLER", "TEST", "ALL"]
@ -329,25 +328,28 @@ class Player:
# Right. So this may be confusing. # Right. So this may be confusing.
# So... If the user has just moved the loaded item in the channel (by removing above and readding) # So... If the user has just moved the loaded item in the channel (by removing above and readding)
# Then we want to re-associate the loaded_item object reference with the new one. # Then we want to re-associate the loaded_item object reference with the new one.
# The loaded item object before this change is now an ophan, which was kept around while the loaded item was potentially moved to another channel. # The loaded item object before this change is now an ophan, which was
# kept around while the loaded item was potentially moved to another
# channel.
if loaded_item.timeslotitemid == new_item_obj.timeslotitemid: if loaded_item.timeslotitemid == new_item_obj.timeslotitemid:
self.state.update("loaded_item", new_item_obj) self.state.update("loaded_item", new_item_obj)
# NOPE NOPE NOPE # NOPE NOPE NOPE
# THIS IS AN EXAMPLE OF WHAT NOT TO DO! # THIS IS AN EXAMPLE OF WHAT NOT TO DO!
# ONCE AGAIN, THE LOADED ITEM IS THE SAME OBJECT INSTANCE AS THE ONE IN THE SHOW PLAN (AS LONG AS IT HASN'T BEEN RE/MOVED) # ONCE AGAIN, THE LOADED ITEM IS THE SAME OBJECT INSTANCE AS THE ONE IN
# THE SHOW PLAN (AS LONG AS IT HASN'T BEEN RE/MOVED)
## loaded_item.weight = new_item_obj.weight # loaded_item.weight = new_item_obj.weight
# Bump the loaded_item's weight if we just added a new item above it. # Bump the loaded_item's weight if we just added a new item above it.
##elif loaded_item.weight >= new_item_obj.weight: # elif loaded_item.weight >= new_item_obj.weight:
## loaded_item.weight += 1 # loaded_item.weight += 1
# Else, new weight stays the same. # Else, new weight stays the same.
##else: # else:
## return True # return True
##self.state.update("loaded_item", loaded_item) # self.state.update("loaded_item", loaded_item)
return True return True
@ -422,12 +424,14 @@ class Player:
break break
if loaded_item is None: if loaded_item is None:
self.logger.log.error("Failed to find weight: {}".format(weight)) self.logger.log.error(
"Failed to find weight: {}".format(weight))
return False return False
reload = False reload = False
if loaded_item.filename == "" or loaded_item.filename is None: if loaded_item.filename == "" or loaded_item.filename is None:
self.logger.log.info("Filename is not specified, loading from API.") self.logger.log.info(
"Filename is not specified, loading from API.")
reload = True reload = True
elif not os.path.exists(loaded_item.filename): elif not os.path.exists(loaded_item.filename):
self.logger.log.warn( self.logger.log.warn(
@ -436,7 +440,8 @@ class Player:
reload = True reload = True
if reload: if reload:
loaded_item.filename = sync(self.api.get_filename(item=loaded_item)) loaded_item.filename = sync(
self.api.get_filename(item=loaded_item))
if not loaded_item.filename: if not loaded_item.filename:
return False return False
@ -462,7 +467,8 @@ class Player:
while load_attempt < 5: while load_attempt < 5:
load_attempt += 1 load_attempt += 1
try: try:
self.logger.log.info("Loading file: " + str(loaded_item.filename)) self.logger.log.info(
"Loading file: " + str(loaded_item.filename))
mixer.music.load(loaded_item.filename) mixer.music.load(loaded_item.filename)
except Exception: except Exception:
# We couldn't load that file. # We couldn't load that file.
@ -487,10 +493,12 @@ class Player:
# WARNING! Pygame / SDL can't seek .wav files :/ # WARNING! Pygame / SDL can't seek .wav files :/
self.state.update( self.state.update(
"length", "length",
mixer.Sound(loaded_item.filename).get_length() / 1000, mixer.Sound(
loaded_item.filename).get_length() / 1000,
) )
except Exception: except Exception:
self.logger.log.exception("Failed to update the length of item.") self.logger.log.exception(
"Failed to update the length of item.")
time.sleep(1) time.sleep(1)
continue # Try loading again. continue # Try loading again.
@ -505,7 +513,8 @@ class Player:
return True return True
self.logger.log.error("Failed to load track after numerous retries.") self.logger.log.error(
"Failed to load track after numerous retries.")
return False return False
return False return False
@ -610,7 +619,8 @@ class Player:
if set_loaded: if set_loaded:
try: try:
self.state.update( self.state.update(
"loaded_item", self.state.get()["loaded_item"].set_marker(marker) "loaded_item", self.state.get(
)["loaded_item"].set_marker(marker)
) )
except Exception as e: except Exception as e:
self.logger.log.error( self.logger.log.error(
@ -677,7 +687,8 @@ class Player:
def _potentially_end_tracklist(self): def _potentially_end_tracklist(self):
if self.tracklist_start_timer: if self.tracklist_start_timer:
self.logger.log.info("A tracklist start timer was running, cancelling.") self.logger.log.info(
"A tracklist start timer was running, cancelling.")
self.tracklist_start_timer.cancel() self.tracklist_start_timer.cancel()
self.tracklist_start_timer = None self.tracklist_start_timer = None
@ -708,7 +719,8 @@ class Player:
return return
self.state.update("tracklist_id", None) self.state.update("tracklist_id", None)
# This threads it, so it won't hang track loading if it fails. # This threads it, so it won't hang track loading if it fails.
self.tracklist_end_timer = Timer(1, self._tracklist_end, [tracklist_id]) self.tracklist_end_timer = Timer(
1, self._tracklist_end, [tracklist_id])
self.tracklist_end_timer.start() self.tracklist_end_timer.start()
else: else:
self.logger.log.warning( self.logger.log.warning(
@ -731,7 +743,8 @@ class Player:
tracklist_id = state["tracklist_id"] tracklist_id = state["tracklist_id"]
if not tracklist_id: if not tracklist_id:
if state["tracklist_mode"] == "fader-live" and not state["live"]: if state["tracklist_mode"] == "fader-live" and not state["live"]:
self.logger.log.info("Not tracklisting since fader is not live.") self.logger.log.info(
"Not tracklisting since fader is not live.")
else: else:
self.logger.log.info( self.logger.log.info(
"Tracklisting item: '{}'".format(loaded_item.name) "Tracklisting item: '{}'".format(loaded_item.name)
@ -742,7 +755,8 @@ class Player:
"Failed to tracklist '{}'".format(loaded_item.name) "Failed to tracklist '{}'".format(loaded_item.name)
) )
else: else:
self.logger.log.info("Tracklist id: '{}'".format(tracklist_id)) self.logger.log.info(
"Tracklist id: '{}'".format(tracklist_id))
self.state.update("tracklist_id", tracklist_id) self.state.update("tracklist_id", tracklist_id)
else: else:
self.logger.log.info( self.logger.log.info(
@ -857,7 +871,8 @@ class Player:
self.state.update( self.state.update(
"remaining", "remaining",
max(0, (self.state.get()["length"] - self.state.get()["pos_true"])), max(0, (self.state.get()["length"] -
self.state.get()["pos_true"])),
) )
def _ping_times(self): def _ping_times(self):
@ -904,7 +919,8 @@ class Player:
def _send_status(self): def _send_status(self):
# TODO This is hacky # TODO This is hacky
self._retMsg(str(self.status), okay_str=True, custom_prefix="ALL:STATUS:") self._retMsg(str(self.status), okay_str=True,
custom_prefix="ALL:STATUS:")
def _fix_and_update_weights(self, plan): def _fix_and_update_weights(self, plan):
def _sort_weight(e: PlanItem): def _sort_weight(e: PlanItem):
@ -949,7 +965,8 @@ class Player:
self.running = True self.running = True
self.out_q = out_q self.out_q = out_q
self.logger = LoggingManager("Player" + str(channel), debug=package.build_beta) self.logger = LoggingManager(
"Player" + str(channel), debug=package.build_beta)
self.api = MyRadioAPI(self.logger, server_state) self.api = MyRadioAPI(self.logger, server_state)
@ -963,7 +980,8 @@ class Player:
self.state.add_callback(self._send_status) self.state.add_callback(self._send_status)
self.state.update("channel", channel) self.state.update("channel", channel)
self.state.update("tracklist_mode", server_state.get()["tracklist_mode"]) self.state.update("tracklist_mode", server_state.get()[
"tracklist_mode"])
self.state.update( self.state.update(
"live", True "live", True
) # Channel is live until controller says it isn't. ) # Channel is live until controller says it isn't.
@ -975,7 +993,8 @@ class Player:
loaded_state = copy.copy(self.state.state) loaded_state = copy.copy(self.state.state)
if loaded_state["output"]: if loaded_state["output"]:
self.logger.log.info("Setting output to: " + str(loaded_state["output"])) self.logger.log.info("Setting output to: " +
str(loaded_state["output"]))
self.output(loaded_state["output"]) self.output(loaded_state["output"])
else: else:
self.logger.log.info("Using default output device.") self.logger.log.info("Using default output device.")
@ -996,7 +1015,8 @@ class Player:
if loaded_state["playing"] is True: if loaded_state["playing"] is True:
self.logger.log.info("Resuming playback on init.") self.logger.log.info("Resuming playback on init.")
self.unpause() # Use un-pause as we don't want to jump to a new position. # Use un-pause as we don't want to jump to a new position.
self.unpause()
else: else:
self.logger.log.info("No file was previously loaded to resume.") self.logger.log.info("No file was previously loaded to resume.")
@ -1012,7 +1032,8 @@ class Player:
self.last_msg_source = "" self.last_msg_source = ""
self.last_msg = "" self.last_msg = ""
self.logger.log.warn( self.logger.log.warn(
"Message from unknown sender source: {}".format(source) "Message from unknown sender source: {}".format(
source)
) )
continue continue
@ -1080,11 +1101,13 @@ class Player:
"UNLOAD": lambda: self._retMsg(self.unload()), "UNLOAD": lambda: self._retMsg(self.unload()),
"ADD": lambda: self._retMsg( "ADD": lambda: self._retMsg(
self.add_to_plan( self.add_to_plan(
json.loads(":".join(self.last_msg.split(":")[1:])) json.loads(
":".join(self.last_msg.split(":")[1:]))
) )
), ),
"REMOVE": lambda: self._retMsg( "REMOVE": lambda: self._retMsg(
self.remove_from_plan(int(self.last_msg.split(":")[1])) self.remove_from_plan(
int(self.last_msg.split(":")[1]))
), ),
"CLEAR": lambda: self._retMsg(self.clear_channel_plan()), "CLEAR": lambda: self._retMsg(self.clear_channel_plan()),
"SETMARKER": lambda: self._retMsg( "SETMARKER": lambda: self._retMsg(
@ -1105,7 +1128,8 @@ class Player:
) )
), ),
"SETLIVE": lambda: self._retMsg( "SETLIVE": lambda: self._retMsg(
self.set_live(self.last_msg.split(":")[1] == "True") self.set_live(
self.last_msg.split(":")[1] == "True")
), ),
} }
@ -1134,7 +1158,8 @@ class Player:
except SystemExit: except SystemExit:
self.logger.log.info("Received SystemExit") self.logger.log.info("Received SystemExit")
except Exception as e: except Exception as e:
self.logger.log.exception("Received unexpected Exception: {}".format(e)) self.logger.log.exception(
"Received unexpected Exception: {}".format(e))
self.logger.log.info("Quiting player " + str(channel)) self.logger.log.info("Quiting player " + str(channel))
self.quit() self.quit()

View file

@ -47,6 +47,7 @@ class PlayerHandler:
sleep(0.02) sleep(0.02)
except Exception as e: except Exception as e:
self.logger.log.exception("Received unexpected exception: {}".format(e)) self.logger.log.exception(
"Received unexpected exception: {}".format(e))
del self.logger del self.logger
_exit(0) _exit(0)

View file

@ -22,15 +22,12 @@ import json
from setproctitle import setproctitle from setproctitle import setproctitle
import psutil import psutil
from helpers.os_environment import isBundelled, isMacOS from helpers.os_environment import isMacOS
if not isMacOS(): if not isMacOS():
# Rip, this doesn't like threading on MacOS. # Rip, this doesn't like threading on MacOS.
import pyttsx3 import pyttsx3
if isBundelled():
import build
import package import package
from typing import Dict, List from typing import Dict, List
from helpers.state_manager import StateManager from helpers.state_manager import StateManager
@ -111,7 +108,8 @@ class BAPSicleServer:
log_function = self.logger.log.info log_function = self.logger.log.info
while ( while (
not terminator.terminate and self.state.get()["running_state"] == "running" not terminator.terminate and self.state.get()[
"running_state"] == "running"
): ):
for channel in range(self.state.get()["num_channels"]): for channel in range(self.state.get()["num_channels"]):
@ -122,7 +120,8 @@ class BAPSicleServer:
or not self.player[channel].is_alive() or not self.player[channel].is_alive()
or not psutil.pid_exists(self.player[channel].pid) or not psutil.pid_exists(self.player[channel].pid)
): ):
log_function("Player {} not running, (re)starting.".format(channel)) log_function(
"Player {} not running, (re)starting.".format(channel))
self.player[channel] = multiprocessing.Process( self.player[channel] = multiprocessing.Process(
target=player.Player, target=player.Player,
args=( args=(
@ -183,7 +182,8 @@ class BAPSicleServer:
): ):
log_function("Webserver not running, (re)starting.") log_function("Webserver not running, (re)starting.")
self.webserver = multiprocessing.Process( self.webserver = multiprocessing.Process(
target=WebServer, args=(self.player_to_q, self.ui_to_q, self.state) target=WebServer, args=(
self.player_to_q, self.ui_to_q, self.state)
) )
self.webserver.start() self.webserver.start()
@ -320,7 +320,8 @@ class BAPSicleServer:
self.player_handler.join(timeout=PROCESS_KILL_TIMEOUT_S) self.player_handler.join(timeout=PROCESS_KILL_TIMEOUT_S)
del self.player_handler del self.player_handler
# Now we've stopped everything else, now is the time to stop the players. This is to keep playing for as long as possible during a restart. # Now we've stopped everything else, now is the time to stop the players.
# This is to keep playing for as long as possible during a restart.
print("Stopping Players") print("Stopping Players")
for q in self.player_to_q: for q in self.player_to_q:
q.put("ALL:QUIT") q.put("ALL:QUIT")

View file

@ -1,4 +1,4 @@
from sanic import Sanic, log from sanic import Sanic
from sanic.exceptions import NotFound, abort from sanic.exceptions import NotFound, abort
from sanic.response import html, file, redirect from sanic.response import html, file, redirect
from sanic.response import json as resp_json from sanic.response import json as resp_json
@ -131,7 +131,8 @@ def ui_status(request):
for i in range(server_state.get()["num_channels"]): for i in range(server_state.get()["num_channels"]):
channel_states.append(status(i)) channel_states.append(status(i))
data = {"channels": channel_states, "ui_page": "status", "ui_title": "Status"} data = {"channels": channel_states,
"ui_page": "status", "ui_title": "Status"}
return render_template("status.html", data=data) return render_template("status.html", data=data)
@ -175,16 +176,20 @@ def ui_config_server_update(request):
server_state.update("ws_port", int(request.form.get("ws_port"))) server_state.update("ws_port", int(request.form.get("ws_port")))
serial_port = request.form.get("serial_port") serial_port = request.form.get("serial_port")
server_state.update("serial_port", None if serial_port == "None" else serial_port) server_state.update("serial_port", None if serial_port ==
"None" else serial_port)
# Because we're not showing the api key once it's set. # Because we're not showing the api key once it's set.
if "myradio_api_key" in request.form and request.form.get("myradio_api_key") != "": if "myradio_api_key" in request.form and request.form.get("myradio_api_key") != "":
server_state.update("myradio_api_key", request.form.get("myradio_api_key")) server_state.update("myradio_api_key",
request.form.get("myradio_api_key"))
server_state.update("myradio_base_url", request.form.get("myradio_base_url")) server_state.update("myradio_base_url",
request.form.get("myradio_base_url"))
server_state.update("myradio_api_url", request.form.get("myradio_api_url")) server_state.update("myradio_api_url", request.form.get("myradio_api_url"))
server_state.update( server_state.update(
"myradio_api_tracklist_source", request.form.get("myradio_api_tracklist_source") "myradio_api_tracklist_source", request.form.get(
"myradio_api_tracklist_source")
) )
server_state.update("tracklist_mode", request.form.get("tracklist_mode")) server_state.update("tracklist_mode", request.form.get("tracklist_mode"))
@ -195,9 +200,9 @@ def ui_config_server_update(request):
def ui_logs_list(request): def ui_logs_list(request):
files = os.listdir(resolve_external_file_path("/logs")) files = os.listdir(resolve_external_file_path("/logs"))
log_files = [] log_files = []
for file in files: for file_name in files:
if file.endswith(".log"): if file_name.endswith(".log"):
log_files.append(file.rstrip(".log")) log_files.append(file_name.rstrip(".log"))
log_files.sort() log_files.sort()
data = {"ui_page": "logs", "ui_title": "Logs", "logs": log_files} data = {"ui_page": "logs", "ui_title": "Logs", "logs": log_files}
@ -215,7 +220,7 @@ def ui_logs_render(request, path):
log_file = open(resolve_external_file_path("/logs/{}.log").format(path)) log_file = open(resolve_external_file_path("/logs/{}.log").format(path))
data = { data = {
"logs": log_file.read().splitlines()[ "logs": log_file.read().splitlines()[
-300 * page : (-300 * (page - 1) if page > 1 else None) -300 * page:(-300 * (page - 1) if page > 1 else None)
][::-1], ][::-1],
"ui_page": "logs", "ui_page": "logs",
"ui_title": "Logs - {}".format(path), "ui_title": "Logs - {}".format(path),
@ -380,7 +385,8 @@ def json_status(request):
async def audio_file(request, type: str, id: int): async def audio_file(request, type: str, id: int):
if type not in ["managed", "track"]: if type not in ["managed", "track"]:
abort(404) abort(404)
filename = resolve_external_file_path("music-tmp/{}-{}.mp3".format(type, id)) filename = resolve_external_file_path(
"music-tmp/{}-{}.mp3".format(type, id))
# Swap with a normalised version if it's ready, else returns original. # Swap with a normalised version if it's ready, else returns original.
filename = get_normalised_filename_if_available(filename) filename = get_normalised_filename_if_available(filename)
@ -411,7 +417,8 @@ app.static(
def status(channel: int): def status(channel: int):
while not player_from_q[channel].empty(): while not player_from_q[channel].empty():
player_from_q[channel].get() # Just waste any previous status responses. # Just waste any previous status responses.
player_from_q[channel].get()
player_to_q[channel].put("UI:STATUS") player_to_q[channel].put("UI:STATUS")
retries = 0 retries = 0
@ -421,7 +428,7 @@ def status(channel: int):
if response.startswith("UI:STATUS:"): if response.startswith("UI:STATUS:"):
response = response.split(":", 2)[2] response = response.split(":", 2)[2]
# TODO: Handle OKAY / FAIL # TODO: Handle OKAY / FAIL
response = response[response.index(":") + 1 :] response = response[response.index(":") + 1:]
try: try:
response = json.loads(response) response = json.loads(response)
except Exception as e: except Exception as e:

View file

@ -71,7 +71,8 @@ class WebsocketServer:
for channel in self.channel_to_q: for channel in self.channel_to_q:
channel.put("WEBSOCKET:STATUS") channel.put("WEBSOCKET:STATUS")
self.from_webstudio = asyncio.create_task(self.handle_from_webstudio(websocket)) self.from_webstudio = asyncio.create_task(
self.handle_from_webstudio(websocket))
try: try:
self.threads = await shield(asyncio.gather(self.from_webstudio)) self.threads = await shield(asyncio.gather(self.from_webstudio))
@ -93,7 +94,8 @@ class WebsocketServer:
await asyncio.wait([conn.send(message) for conn in self.baps_clients]) await asyncio.wait([conn.send(message) for conn in self.baps_clients])
except websockets.exceptions.ConnectionClosedError as e: except websockets.exceptions.ConnectionClosedError as e:
self.logger.log.error("Client Disconncted {}, {}".format(websocket, e)) self.logger.log.error(
"Client Disconncted {}, {}".format(websocket, e))
except Exception as e: except Exception as e:
self.logger.log.exception( self.logger.log.exception(
@ -176,13 +178,15 @@ class WebsocketServer:
except ValueError as e: except ValueError as e:
self.logger.log.exception( self.logger.log.exception(
"Error decoding extra data {} for command {} ".format(e, command) "Error decoding extra data {} for command {} ".format(
e, command)
) )
pass pass
# Stick the message together and send! # Stick the message together and send!
message += ( message += (
command # Put the command in at the end, in case MOVE etc changed it. # Put the command in at the end, in case MOVE etc changed it.
command
) )
if extra != "": if extra != "":
message += ":" + extra message += ":" + extra
@ -197,7 +201,8 @@ class WebsocketServer:
) )
else: else:
self.logger.log.error("Command missing from message. Data: {}".format(data)) self.logger.log.error(
"Command missing from message. Data: {}".format(data))
async def handle_to_webstudio(self): async def handle_to_webstudio(self):