98 lines
2.5 KiB
Python
98 lines
2.5 KiB
Python
import os
|
|
import random
|
|
from run_utils import AMBIENCE_PATH, AMBIENCE_OPTIONS_PATH, AUDIO_DIR, parse_ambience_options
|
|
|
|
try:
|
|
import miniaudio
|
|
HAS_AUDIO = True
|
|
except ImportError:
|
|
HAS_AUDIO = False
|
|
|
|
|
|
class AmbiencePlayer:
|
|
def __init__(self):
|
|
self.current_ambience = 'silence'
|
|
self._last_mtime = 0
|
|
self._options = {}
|
|
self._device = None
|
|
self._stream = None
|
|
self._muted = False
|
|
self.load_options()
|
|
|
|
@property
|
|
def available(self):
|
|
return HAS_AUDIO
|
|
|
|
@property
|
|
def ambience_name(self):
|
|
return self.current_ambience
|
|
|
|
@property
|
|
def is_muted(self):
|
|
return self._muted
|
|
|
|
def toggle_mute(self):
|
|
self._muted = not self._muted
|
|
if self._muted:
|
|
self._stop()
|
|
else:
|
|
self._load_current()
|
|
|
|
def load_options(self):
|
|
self._options = parse_ambience_options()
|
|
|
|
def _stop(self):
|
|
if self._device:
|
|
try:
|
|
self._device.close()
|
|
except Exception:
|
|
pass
|
|
self._device = None
|
|
self._stream = None
|
|
|
|
def poll(self):
|
|
if not HAS_AUDIO:
|
|
return
|
|
try:
|
|
mtime = os.path.getmtime(AMBIENCE_PATH)
|
|
except OSError:
|
|
return
|
|
if mtime == self._last_mtime:
|
|
return
|
|
self._last_mtime = mtime
|
|
try:
|
|
name = AMBIENCE_PATH.read_text().strip().lower()
|
|
except OSError:
|
|
return
|
|
self.current_ambience = name
|
|
self._stop()
|
|
if not self._muted and name != 'silence' and name in self._options:
|
|
self._play_current()
|
|
|
|
def _switch_to(self, name):
|
|
if name == self.current_ambience:
|
|
return
|
|
self.current_ambience = name
|
|
self._stop()
|
|
if self._muted or name == 'silence' or name not in self._options:
|
|
return
|
|
self._play_current()
|
|
|
|
def _play_current(self):
|
|
tracks = self._options.get(self.current_ambience, [])
|
|
valid = [t for t in tracks if t.exists()]
|
|
if not valid:
|
|
return
|
|
track = random.choice(valid)
|
|
try:
|
|
self._stream = miniaudio.stream_file(str(track))
|
|
self._device = miniaudio.PlaybackDevice()
|
|
self._device.start(self._stream)
|
|
except Exception:
|
|
self.current_ambience = None
|
|
self._stop()
|
|
|
|
def _load_current(self):
|
|
if self.current_ambience and self.current_ambience != 'silence':
|
|
self._play_current()
|