Fix race condition with file manager preloading.
This commit is contained in:
parent
05b64fb317
commit
c0cc6ff418
2 changed files with 74 additions and 32 deletions
|
@ -22,6 +22,7 @@ import json
|
|||
from logging import INFO, ERROR, WARNING
|
||||
import os
|
||||
import requests
|
||||
import time
|
||||
|
||||
from baps_types.plan import PlanItem
|
||||
from helpers.os_environment import resolve_external_file_path
|
||||
|
@ -219,6 +220,8 @@ class MyRadioAPI:
|
|||
# Now check if the file already exists
|
||||
path: str = resolve_external_file_path("/music-tmp/")
|
||||
|
||||
dl_suffix = ".downloading"
|
||||
|
||||
if not os.path.isdir(path):
|
||||
self._log("Music-tmp folder is missing, attempting to create.")
|
||||
try:
|
||||
|
@ -230,19 +233,42 @@ class MyRadioAPI:
|
|||
filename: str = resolve_external_file_path(
|
||||
"/music-tmp/{}-{}.{}".format(itemType, id, format)
|
||||
)
|
||||
|
||||
# Check if we already downloaded the file. If we did, give that.
|
||||
if os.path.isfile(filename):
|
||||
self.logger.log.debug("Already got file. " + filename)
|
||||
return (filename, False) if did_download else filename
|
||||
|
||||
# If something else (another channel, the preloader etc) is downloading the track, wait for it.
|
||||
if os.path.isfile(filename + dl_suffix):
|
||||
time_waiting_s = 0
|
||||
self.logger.log.debug("Waiting for download to complete from another worker. " + filename)
|
||||
while time_waiting_s < 20:
|
||||
# TODO: Make something better here.
|
||||
# If the connectivity is super poor or we're loading reeaaaalllly long files, this may be annoying, but this is just in case somehow the other api download gives up.
|
||||
if os.path.isfile(filename):
|
||||
# Now the file is downloaded successfully
|
||||
return (filename, False) if did_download else filename
|
||||
time_waiting_s +=1
|
||||
self.logger.log.debug("Still waiting")
|
||||
time.sleep(1)
|
||||
|
||||
# File doesn't exist, download it.
|
||||
try:
|
||||
# Just create the file to stop other sources from trying to download too.
|
||||
open(filename + dl_suffix, "a").close()
|
||||
except Exception:
|
||||
self.logger.log.exception("Couldn't create new temp file.")
|
||||
return (None, False) if did_download else None
|
||||
|
||||
request = await self.async_api_call(url, api_version="non")
|
||||
|
||||
if not request:
|
||||
return (None, False) if did_download else None
|
||||
|
||||
try:
|
||||
with open(filename, "wb") as file:
|
||||
with open(filename + dl_suffix, "wb") as file:
|
||||
file.write(await request)
|
||||
os.rename(filename + dl_suffix, filename)
|
||||
except Exception as e:
|
||||
self._logException("Failed to write music file: {}".format(e))
|
||||
return (None, False) if did_download else None
|
||||
|
|
76
player.py
76
player.py
|
@ -412,40 +412,56 @@ class Player:
|
|||
break
|
||||
# TODO: Update the show plan filenames???
|
||||
|
||||
try:
|
||||
self.logger.log.info("Loading file: " +
|
||||
str(loaded_item.filename))
|
||||
mixer.music.load(loaded_item.filename)
|
||||
except Exception:
|
||||
# We couldn't load that file.
|
||||
self.logger.log.exception(
|
||||
"Couldn't load file: " + str(loaded_item.filename)
|
||||
)
|
||||
return False
|
||||
|
||||
try:
|
||||
if ".mp3" in loaded_item.filename:
|
||||
song = MP3(loaded_item.filename)
|
||||
self.state.update("length", song.info.length)
|
||||
else:
|
||||
self.state.update(
|
||||
"length", mixer.Sound(
|
||||
loaded_item.filename).get_length() / 1000
|
||||
load_attempt = 0
|
||||
while load_attempt < 5:
|
||||
load_attempt += 1
|
||||
try:
|
||||
self.logger.log.info("Loading file: " +
|
||||
str(loaded_item.filename))
|
||||
mixer.music.load(loaded_item.filename)
|
||||
except Exception:
|
||||
# We couldn't load that file.
|
||||
self.logger.log.exception(
|
||||
"Couldn't load file: " + str(loaded_item.filename)
|
||||
)
|
||||
except Exception:
|
||||
self.logger.log.exception(
|
||||
"Failed to update the length of item.")
|
||||
return False
|
||||
time.sleep(1)
|
||||
continue # Try loading again.
|
||||
|
||||
if loaded_item.cue > 0:
|
||||
self.seek(loaded_item.cue)
|
||||
else:
|
||||
self.seek(0)
|
||||
if not self.isLoaded:
|
||||
self.logger.log.error("Pygame loaded file without error, but never actually loaded.")
|
||||
time.sleep(1)
|
||||
continue # Try loading again.
|
||||
|
||||
if self.state.get()["play_on_load"]:
|
||||
self.unpause()
|
||||
try:
|
||||
if ".mp3" in loaded_item.filename:
|
||||
song = MP3(loaded_item.filename)
|
||||
self.state.update("length", song.info.length)
|
||||
else:
|
||||
self.state.update(
|
||||
"length", mixer.Sound(
|
||||
loaded_item.filename).get_length() / 1000
|
||||
)
|
||||
except Exception:
|
||||
self.logger.log.exception(
|
||||
"Failed to update the length of item.")
|
||||
time.sleep(1)
|
||||
continue # Try loading again.
|
||||
|
||||
return True
|
||||
# Everything worked, we made it!
|
||||
if loaded_item.cue > 0:
|
||||
self.seek(loaded_item.cue)
|
||||
else:
|
||||
self.seek(0)
|
||||
|
||||
if self.state.get()["play_on_load"]:
|
||||
self.unpause()
|
||||
|
||||
return True
|
||||
|
||||
self.logger.log.error("Failed to load track after numerous retries.")
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
def unload(self):
|
||||
if not self.isPlaying:
|
||||
|
|
Loading…
Reference in a new issue