Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/media/mic_track.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ pub struct MicTrack {
}

impl MicTrack {
/// Track name used when publishing; also how the UI detects the mic is live.
pub const TRACK_NAME: &str = "microphone";
const TRACK_NAME: &str = "microphone";

pub fn new(room: Arc<Room>) -> Self {
Self { room, track: None }
Expand Down
28 changes: 0 additions & 28 deletions src/room/status_bar.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::media::MicTrack;
use crate::room::RoomContext;
use crate::service::AsyncCmd;
use crate::style::Palette;
use crate::ui::status_badge::StatusBadge;
use livekit::prelude::*;

Expand Down Expand Up @@ -40,13 +37,6 @@ impl egui::Widget for StatusBar<'_> {
.room
.filter(|r| r.connection_state() == ConnectionState::Connected);

let mic_active = room.is_some_and(|r| {
r.local_participant()
.track_publications()
.values()
.any(|p| p.name().as_str() == MicTrack::TRACK_NAME)
});

ui.horizontal(|ui| {
if let Some(err) = connection_failure {
ui.add(StatusBadge::error(format!("Connection failed: {err}")));
Expand All @@ -69,24 +59,6 @@ impl egui::Widget for StatusBar<'_> {
if connecting {
ui.add_enabled(false, egui::Button::new("Connecting...").min_size(size));
} else if room.is_some() {
let palette = Palette::for_theme(ui.theme());
let mic_label = if mic_active {
egui::RichText::new("Microphone").color(palette.bg_1)
} else {
egui::RichText::new("Microphone")
};
let mut mic_button = egui::Button::new(mic_label).min_size(size);
if mic_active {
mic_button = mic_button.fill(palette.fg_success);
}
let mic_tooltip = if mic_active {
"Microphone is publishing — click to stop (platform audio / ADM)"
} else {
"Publish microphone audio via platform audio (ADM)"
};
if ui.add(mic_button).on_hover_text(mic_tooltip).clicked() {
let _ = ctx.service.send(AsyncCmd::ToggleMic);
}
if ui
.add(egui::Button::new("Disconnect").min_size(size))
.clicked()
Expand Down
41 changes: 21 additions & 20 deletions src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ pub enum AsyncCmd {
TogglePublish {
source: LocalSource,
},
ToggleMic,
SubscribeTrack {
publication: RemoteTrackPublication,
},
Expand Down Expand Up @@ -70,22 +69,25 @@ pub enum DataStreamPayload {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LocalSource {
Capture(CaptureSource),
Mic,
Sine,
DataTrack,
}

impl LocalSource {
pub const ALL: [Self; 5] = [
pub const ALL: [Self; 6] = [
Self::Capture(CaptureSource::Gradient),
Self::Capture(CaptureSource::Logo),
Self::Capture(CaptureSource::Clock),
Self::Mic,
Self::Sine,
Self::DataTrack,
];

pub fn label(self) -> &'static str {
match self {
Self::Capture(source) => source.label(),
Self::Mic => "Audio: Microphone",
Self::Sine => "Audio: Sine Wave",
Self::DataTrack => "Data Track: Slider",
}
Expand All @@ -94,6 +96,7 @@ impl LocalSource {
pub fn description(self) -> &'static str {
match self {
Self::Capture(source) => source.description(),
Self::Mic => "Microphone audio via platform audio (ADM)",
Self::Sine => "Synthetic 440 Hz sine wave tone",
Self::DataTrack => "Integer from 0 to 512 set with a slider, sent as text",
}
Expand Down Expand Up @@ -253,6 +256,22 @@ async fn service_task(inner: Arc<ServiceInner>, mut cmd_rx: mpsc::UnboundedRecei
}
track.is_published()
}
LocalSource::Mic => {
// Cloned so `mic_track` can be borrowed mutably alongside it.
let Some(platform_audio) = self.platform_audio.clone() else {
log::error!("cannot toggle microphone: platform audio unavailable");
return false;
};
let result = if self.mic_track.is_published() {
self.mic_track.unpublish(&platform_audio).await
} else {
self.mic_track.publish(&platform_audio).await
};
if let Err(err) = result {
log::error!("failed to toggle microphone: {err}");
}
self.mic_track.is_published()
}
LocalSource::Sine => {
let result = if self.sine_track.is_published() {
self.sine_track.unpublish().await
Expand Down Expand Up @@ -417,24 +436,6 @@ async fn service_task(inner: Arc<ServiceInner>, mut cmd_rx: mpsc::UnboundedRecei
PublishState::Unpublished
});
}
AsyncCmd::ToggleMic => {
if let Some(state) = running_state.as_mut() {
// Clone the ref-counted handle to sidestep a disjoint borrow of
// `state` (mic_track is borrowed mutably below).
if let Some(platform_audio) = state.platform_audio.clone() {
let result = if state.mic_track.is_published() {
state.mic_track.unpublish(&platform_audio).await
} else {
state.mic_track.publish(&platform_audio).await
};
if let Err(err) = result {
log::error!("failed to toggle microphone: {err}");
}
} else {
log::error!("cannot toggle microphone: platform audio unavailable");
}
}
}
AsyncCmd::SubscribeTrack { publication } => {
publication.set_subscribed(true);
}
Expand Down
Loading