feat: add status indicator and improve UI layout in multicast frontend
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user