feat: add status indicator and improve UI layout in multicast frontend

This commit is contained in:
pstruebi
2025-09-22 12:30:03 +02:00
parent 75849080f1
commit c2fd0a8c46
2 changed files with 38 additions and 9 deletions

View File

@@ -6,6 +6,9 @@ import requests
from auracast import auracast_config
import logging as log
# Set page configuration (tab title and icon) before using other Streamlit APIs
st.set_page_config(page_title="Castbox", page_icon="", layout="centered")
# Track whether WebRTC stream is active across Streamlit reruns
if 'stream_started' not in st.session_state:
st.session_state['stream_started'] = False
@@ -30,7 +33,7 @@ try:
except Exception:
saved_settings = {}
st.title("🎙️ Auracast Audio Mode Control")
st.title("Auracast Audio Mode Control")
# Audio mode selection with persisted default
# Note: backend persists 'USB' for any device:<name> source (including AES67). We default to 'USB' in that case.
@@ -154,6 +157,7 @@ if audio_mode == "Demo":
st.session_state['demo_stream_started'] = False
if r.get('was_running'):
st.info("Demo stream stopped.")
st.rerun()
else:
st.info("Demo stream was not running.")
except Exception as e:
@@ -277,8 +281,22 @@ else:
else:
input_device = None
start_stream = st.button("Start Auracast")
stop_stream = st.button("Stop Auracast")
# Buttons and status on a single row (4 columns: start, stop, spacer, status)
c_start, c_stop, c_spacer, c_status = st.columns([1, 1, 1, 2], gap="small", vertical_alignment="center")
with c_start:
start_stream = st.button("Start Auracast")
with c_stop:
stop_stream = st.button("Stop Auracast")
# c_spacer intentionally left empty to push status to the far right
with c_status:
# Fetch current status from backend and render using Streamlit widgets (no HTML)
try:
status_resp = requests.get(f"{BACKEND_URL}/status", timeout=0.8)
status_json = status_resp.json() if status_resp.ok else {}
except Exception:
status_json = {}
is_streaming = bool(status_json.get("is_streaming", False))
st.write("🟢 Streaming" if is_streaming else "🔴 Stopped")
# If gain slider moved while streaming, send update to JS without restarting
if audio_mode == "Webapp" and st.session_state.get('stream_started'):
@@ -295,6 +313,7 @@ else:
r = requests.post(f"{BACKEND_URL}/stop_audio").json()
if r['was_running']:
st.success("Stream Stopped!")
st.rerun()
else:
st.success("Stream was not running.")
except Exception as e:
@@ -351,6 +370,7 @@ else:
r = requests.post(f"{BACKEND_URL}/init", json=config.model_dump())
if r.status_code == 200:
st.success("Stream Started!")
st.rerun()
else:
st.error(f"Failed to initialize: {r.text}")
except Exception as e:

View File

@@ -102,8 +102,17 @@ async def initialize(conf: auracast_config.AuracastConfigGroup):
# Derive audio_mode and input_device from first BIG audio_source
first_source = conf.bigs[0].audio_source if conf.bigs else ''
if first_source.startswith('device:'):
audio_mode_persist = 'USB'
input_device_name = first_source.split(':', 1)[1] if ':' in first_source else None
# Determine if the device is a USB or Network(AES67) PipeWire input
try:
usb_names = {d.get('name') for _, d in list_usb_pw_inputs(refresh=False)}
net_names = {d.get('name') for _, d in list_network_pw_inputs(refresh=False)}
except Exception:
usb_names, net_names = set(), set()
if input_device_name in net_names:
audio_mode_persist = 'AES67'
else:
audio_mode_persist = 'USB'
# Map device name to current index for use with sounddevice
device_index = get_device_index_by_name(input_device_name) if input_device_name else None
# Patch config to use index for sounddevice (but persist name)
@@ -307,11 +316,11 @@ async def _autostart_from_settings():
except Exception:
log.warning("Autostart task failed", exc_info=True)
# @app.on_event("startup")
# async def _startup_autostart_event():
# # Spawn the autostart task without blocking startup
# asyncio.create_task(_autostart_from_settings())
#TODO: enable and test this
@app.on_event("startup")
async def _startup_autostart_event():
# Spawn the autostart task without blocking startup
asyncio.create_task(_autostart_from_settings())
@app.post("/refresh_audio_inputs")