|
|
|
@ -175,6 +175,12 @@ def pick_station_id_file(): |
|
|
|
return None |
|
|
|
return None |
|
|
|
return os.path.join(STATION_ID_DIR, random.choice(files)) |
|
|
|
return os.path.join(STATION_ID_DIR, random.choice(files)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def pick_random_track(): |
|
|
|
|
|
|
|
"""Return a random music track (relative path) from TRACKS.""" |
|
|
|
|
|
|
|
if not TRACKS: |
|
|
|
|
|
|
|
return None |
|
|
|
|
|
|
|
return random.choice(list(TRACKS.keys())) |
|
|
|
|
|
|
|
|
|
|
|
def set_rds(text: str): |
|
|
|
def set_rds(text: str): |
|
|
|
global rds_pipe |
|
|
|
global rds_pipe |
|
|
|
try: |
|
|
|
try: |
|
|
|
@ -352,6 +358,14 @@ def extract_album_art(path: str, rel_path: str, timeout: int = 10): |
|
|
|
|
|
|
|
|
|
|
|
return None |
|
|
|
return None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def display_title(path): |
|
|
|
|
|
|
|
"""Convert 'dir/a/b/Song - Title.ext' → 'Song - Title'.""" |
|
|
|
|
|
|
|
if not path: |
|
|
|
|
|
|
|
return None |
|
|
|
|
|
|
|
base = os.path.basename(path) |
|
|
|
|
|
|
|
title, _ = os.path.splitext(base) |
|
|
|
|
|
|
|
return title |
|
|
|
|
|
|
|
|
|
|
|
# ----------------------------- |
|
|
|
# ----------------------------- |
|
|
|
# Pump helper for decoder -> wrapper |
|
|
|
# Pump helper for decoder -> wrapper |
|
|
|
# ----------------------------- |
|
|
|
# ----------------------------- |
|
|
|
@ -602,6 +616,20 @@ def worker(): |
|
|
|
global queue, shuffle_mode, repeat_mode |
|
|
|
global queue, shuffle_mode, repeat_mode |
|
|
|
|
|
|
|
|
|
|
|
while True: |
|
|
|
while True: |
|
|
|
|
|
|
|
with queue_lock: |
|
|
|
|
|
|
|
if not queue: |
|
|
|
|
|
|
|
current_track = None |
|
|
|
|
|
|
|
empty = True |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
empty = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if empty: |
|
|
|
|
|
|
|
track = pick_random_track() |
|
|
|
|
|
|
|
if track: |
|
|
|
|
|
|
|
print(f"[WORKER] Queue empty — adding random track: {track}") |
|
|
|
|
|
|
|
with queue_lock: |
|
|
|
|
|
|
|
queue.append(track) |
|
|
|
|
|
|
|
stop_flag = False |
|
|
|
try: |
|
|
|
try: |
|
|
|
if stop_flag: |
|
|
|
if stop_flag: |
|
|
|
with queue_lock: |
|
|
|
with queue_lock: |
|
|
|
@ -632,18 +660,6 @@ def worker(): |
|
|
|
# No station id files; reset timer so we don't spin |
|
|
|
# No station id files; reset timer so we don't spin |
|
|
|
last_station_id_time = time.time() |
|
|
|
last_station_id_time = time.time() |
|
|
|
|
|
|
|
|
|
|
|
with queue_lock: |
|
|
|
|
|
|
|
if not queue: |
|
|
|
|
|
|
|
current_track = None |
|
|
|
|
|
|
|
empty = True |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
empty = False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if empty: |
|
|
|
|
|
|
|
write_silence(0.25) |
|
|
|
|
|
|
|
time.sleep(0.5) |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Shuffle only when building the play order |
|
|
|
# Shuffle only when building the play order |
|
|
|
if shuffle_mode: |
|
|
|
if shuffle_mode: |
|
|
|
with queue_lock: |
|
|
|
with queue_lock: |
|
|
|
@ -778,7 +794,7 @@ def album_art(name): |
|
|
|
@app.get("/queue") |
|
|
|
@app.get("/queue") |
|
|
|
def get_queue(): |
|
|
|
def get_queue(): |
|
|
|
with queue_lock: |
|
|
|
with queue_lock: |
|
|
|
return jsonify(list(queue)) |
|
|
|
return jsonify([display_title(item) for item in queue]) |
|
|
|
|
|
|
|
|
|
|
|
@app.post("/queue") |
|
|
|
@app.post("/queue") |
|
|
|
def add_to_queue(): |
|
|
|
def add_to_queue(): |
|
|
|
@ -805,7 +821,7 @@ def now_playing(): |
|
|
|
art_name = TRACKS[current_track].get("album_art") |
|
|
|
art_name = TRACKS[current_track].get("album_art") |
|
|
|
if art_name: |
|
|
|
if art_name: |
|
|
|
art = f"/album_art/{art_name}" |
|
|
|
art = f"/album_art/{art_name}" |
|
|
|
return jsonify({"track": current_track, "album_art": art}) |
|
|
|
return jsonify({"track": display_title(current_track), "album_art": art}) |
|
|
|
|
|
|
|
|
|
|
|
@app.post("/shuffle") |
|
|
|
@app.post("/shuffle") |
|
|
|
def set_shuffle(): |
|
|
|
def set_shuffle(): |
|
|
|
|