fix: unsubscribe deadlock (#101)
This commit is contained in:
@@ -11,7 +11,7 @@ use livekit::webrtc::audio_stream::native::NativeAudioStream;
|
|||||||
use livekit::SimulateScenario;
|
use livekit::SimulateScenario;
|
||||||
use parking_lot::deadlock;
|
use parking_lot::deadlock;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::HashMap;
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
@@ -61,6 +61,8 @@ struct App {
|
|||||||
connection_failure: Option<String>,
|
connection_failure: Option<String>,
|
||||||
room_state: ConnectionState,
|
room_state: ConnectionState,
|
||||||
|
|
||||||
|
auto_subscribe: bool,
|
||||||
|
|
||||||
// Log events
|
// Log events
|
||||||
events: Vec<String>,
|
events: Vec<String>,
|
||||||
}
|
}
|
||||||
@@ -100,7 +102,8 @@ pub fn run(rt: tokio::runtime::Runtime) {
|
|||||||
lk_url: DEFAULT_URL.to_owned(),
|
lk_url: DEFAULT_URL.to_owned(),
|
||||||
lk_token: DEFAULT_TOKEN.to_owned(),
|
lk_token: DEFAULT_TOKEN.to_owned(),
|
||||||
connection_failure: None,
|
connection_failure: None,
|
||||||
room_state: ConnectionState::Connected,
|
room_state: ConnectionState::Unknown,
|
||||||
|
auto_subscribe: true,
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -342,6 +345,9 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
|
let connecting = self.state.connecting.load(Ordering::SeqCst);
|
||||||
|
let connected = self.state.session.lock().is_some();
|
||||||
|
|
||||||
egui::TopBottomPanel::top("top_panel").show(ui.ctx(), |ui| {
|
egui::TopBottomPanel::top("top_panel").show(ui.ctx(), |ui| {
|
||||||
egui::menu::bar(ui, |ui| {
|
egui::menu::bar(ui, |ui| {
|
||||||
ui.menu_button(
|
ui.menu_button(
|
||||||
@@ -397,11 +403,13 @@ impl App {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
egui::SidePanel::right("room_panel")
|
egui::SidePanel::left("left_panel")
|
||||||
|
.resizable(true)
|
||||||
.default_width(256.0)
|
.default_width(256.0)
|
||||||
.show(ui.ctx(), |ui| {
|
.show(ui.ctx(), |ui| {
|
||||||
ui.heading("Livekit - Connect to a room");
|
ui.add_space(8.0);
|
||||||
ui.separator();
|
ui.monospace("Livekit - Connect to a room");
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label("URL: ");
|
ui.label("URL: ");
|
||||||
@@ -414,10 +422,7 @@ impl App {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let connecting = self.state.connecting.load(Ordering::SeqCst);
|
ui.add_enabled_ui(!connected && !connecting, |ui| {
|
||||||
let session = self.state.session.lock();
|
|
||||||
|
|
||||||
ui.add_enabled_ui(!connecting && session.is_none(), |ui| {
|
|
||||||
if ui.button("Connect").clicked() {
|
if ui.button("Connect").clicked() {
|
||||||
self.connection_failure = None;
|
self.connection_failure = None;
|
||||||
let _ = self.cmd_tx.send(AsyncCmd::RoomConnect {
|
let _ = self.cmd_tx.send(AsyncCmd::RoomConnect {
|
||||||
@@ -431,13 +436,19 @@ impl App {
|
|||||||
ui.spinner();
|
ui.spinner();
|
||||||
}
|
}
|
||||||
|
|
||||||
if session.is_some() {
|
if connected {
|
||||||
if ui.button("Disconnect").clicked() {
|
if ui.button("Disconnect").clicked() {
|
||||||
let _ = self.cmd_tx.send(AsyncCmd::RoomDisconnect);
|
let _ = self.cmd_tx.send(AsyncCmd::RoomDisconnect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.add_enabled_ui(!connected && !connecting, |ui| {
|
||||||
|
ui.checkbox(&mut self.auto_subscribe, "Auto Subscribe");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(err) = &self.connection_failure {
|
if let Some(err) = &self.connection_failure {
|
||||||
ui.colored_label(egui::Color32::RED, err);
|
ui.colored_label(egui::Color32::RED, err);
|
||||||
}
|
}
|
||||||
@@ -461,11 +472,47 @@ impl App {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
egui::TopBottomPanel::bottom("bottom_panel")
|
egui::SidePanel::right("right_panel")
|
||||||
.default_height(128.0)
|
.resizable(true)
|
||||||
|
.default_width(256.0)
|
||||||
.show(ui.ctx(), |ui| {
|
.show(ui.ctx(), |ui| {
|
||||||
ui.label("Events");
|
ui.monospace("Tracks");
|
||||||
|
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||||
|
// Show all tracks
|
||||||
|
if let Some(session) = self.state.session.lock().as_ref() {
|
||||||
|
for (_, participant) in session.room.participants() {
|
||||||
|
for (_, track) in participant.tracks() {
|
||||||
|
let TrackPublication::Remote(track) = track else {
|
||||||
|
unreachable!();
|
||||||
|
};
|
||||||
|
|
||||||
|
ui.group(|ui| {
|
||||||
|
ui.label(format!("{} {}", track.sid().0, track.name()));
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label(format!("{:?}", track.source()));
|
||||||
|
|
||||||
|
if track.is_subscribed() {
|
||||||
|
ui.colored_label(egui::Color32::GREEN, "Subscribed");
|
||||||
|
} else {
|
||||||
|
ui.colored_label(egui::Color32::RED, "Unsubscribed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if track.is_muted() {
|
||||||
|
ui.colored_label(egui::Color32::DARK_GRAY, "Muted");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
egui::TopBottomPanel::bottom("bottom_panel")
|
||||||
|
.resizable(true)
|
||||||
|
.min_height(32.0)
|
||||||
|
.show(ui.ctx(), |ui| {
|
||||||
|
ui.monospace("Events");
|
||||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||||
for event in &self.events {
|
for event in &self.events {
|
||||||
ui.label(event);
|
ui.label(event);
|
||||||
|
|||||||
@@ -182,7 +182,8 @@ impl RemoteParticipant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove tracks that are no longer valid
|
// remove tracks that are no longer valid
|
||||||
for (sid, _) in self.inner.tracks.read().iter() {
|
let tracks = self.inner.tracks.read().clone();
|
||||||
|
for (sid, _) in &tracks {
|
||||||
if valid_tracks.contains(sid) {
|
if valid_tracks.contains(sid) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ impl RemoteTrackPublication {
|
|||||||
remote: Arc::new(RemoteInner {
|
remote: Arc::new(RemoteInner {
|
||||||
info: RwLock::new(RemoteInfo {
|
info: RwLock::new(RemoteInfo {
|
||||||
subscribed: false,
|
subscribed: false,
|
||||||
allowed: false,
|
allowed: true,
|
||||||
}),
|
}),
|
||||||
events: Default::default(),
|
events: Default::default(),
|
||||||
}),
|
}),
|
||||||
@@ -122,7 +122,12 @@ impl RemoteTrackPublication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn update_info(&self, info: proto::TrackInfo) {
|
pub(crate) fn update_info(&self, info: proto::TrackInfo) {
|
||||||
super::update_info(&self.inner, &TrackPublication::Remote(self.clone()), info);
|
super::update_info(
|
||||||
|
&self.inner,
|
||||||
|
&TrackPublication::Remote(self.clone()),
|
||||||
|
info.clone(),
|
||||||
|
);
|
||||||
|
self.inner.info.write().muted = info.muted;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn on_muted(&self, f: impl Fn(TrackPublication, Track) + Send + 'static) {
|
pub(crate) fn on_muted(&self, f: impl Fn(TrackPublication, Track) + Send + 'static) {
|
||||||
|
|||||||
Reference in New Issue
Block a user