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
|
from logging import INFO, ERROR, WARNING
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
|
import time
|
||||||
|
|
||||||
from baps_types.plan import PlanItem
|
from baps_types.plan import PlanItem
|
||||||
from helpers.os_environment import resolve_external_file_path
|
from helpers.os_environment import resolve_external_file_path
|
||||||
|
@ -219,6 +220,8 @@ class MyRadioAPI:
|
||||||
# Now check if the file already exists
|
# Now check if the file already exists
|
||||||
path: str = resolve_external_file_path("/music-tmp/")
|
path: str = resolve_external_file_path("/music-tmp/")
|
||||||
|
|
||||||
|
dl_suffix = ".downloading"
|
||||||
|
|
||||||
if not os.path.isdir(path):
|
if not os.path.isdir(path):
|
||||||
self._log("Music-tmp folder is missing, attempting to create.")
|
self._log("Music-tmp folder is missing, attempting to create.")
|
||||||
try:
|
try:
|
||||||
|
@ -230,19 +233,42 @@ class MyRadioAPI:
|
||||||
filename: str = resolve_external_file_path(
|
filename: str = resolve_external_file_path(
|
||||||
"/music-tmp/{}-{}.{}".format(itemType, id, format)
|
"/music-tmp/{}-{}.{}".format(itemType, id, format)
|
||||||
)
|
)
|
||||||
|
# Check if we already downloaded the file. If we did, give that.
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
|
self.logger.log.debug("Already got file. " + filename)
|
||||||
return (filename, False) if did_download else 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.
|
# 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")
|
request = await self.async_api_call(url, api_version="non")
|
||||||
|
|
||||||
if not request:
|
if not request:
|
||||||
return (None, False) if did_download else None
|
return (None, False) if did_download else None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(filename, "wb") as file:
|
with open(filename + dl_suffix, "wb") as file:
|
||||||
file.write(await request)
|
file.write(await request)
|
||||||
|
os.rename(filename + dl_suffix, filename)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._logException("Failed to write music file: {}".format(e))
|
self._logException("Failed to write music file: {}".format(e))
|
||||||
return (None, False) if did_download else None
|
return (None, False) if did_download else None
|
||||||
|
|
76
player.py
76
player.py
|
@ -412,40 +412,56 @@ class Player:
|
||||||
break
|
break
|
||||||
# TODO: Update the show plan filenames???
|
# TODO: Update the show plan filenames???
|
||||||
|
|
||||||
try:
|
load_attempt = 0
|
||||||
self.logger.log.info("Loading file: " +
|
while load_attempt < 5:
|
||||||
str(loaded_item.filename))
|
load_attempt += 1
|
||||||
mixer.music.load(loaded_item.filename)
|
try:
|
||||||
except Exception:
|
self.logger.log.info("Loading file: " +
|
||||||
# We couldn't load that file.
|
str(loaded_item.filename))
|
||||||
self.logger.log.exception(
|
mixer.music.load(loaded_item.filename)
|
||||||
"Couldn't load file: " + str(loaded_item.filename)
|
except Exception:
|
||||||
)
|
# We couldn't load that file.
|
||||||
return False
|
self.logger.log.exception(
|
||||||
|
"Couldn't load file: " + str(loaded_item.filename)
|
||||||
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:
|
time.sleep(1)
|
||||||
self.logger.log.exception(
|
continue # Try loading again.
|
||||||
"Failed to update the length of item.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
if loaded_item.cue > 0:
|
if not self.isLoaded:
|
||||||
self.seek(loaded_item.cue)
|
self.logger.log.error("Pygame loaded file without error, but never actually loaded.")
|
||||||
else:
|
time.sleep(1)
|
||||||
self.seek(0)
|
continue # Try loading again.
|
||||||
|
|
||||||
if self.state.get()["play_on_load"]:
|
try:
|
||||||
self.unpause()
|
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):
|
def unload(self):
|
||||||
if not self.isPlaying:
|
if not self.isPlaying:
|
||||||
|
|
Loading…
Reference in a new issue