feat: video publishing (#42)
- Prepare webrtc abstraction ( for future wasm support ) - Added track publish support for videos - Added LogoTrack example to simple_room demo - Lot of cleanup - There are compiler warnings I'll solve on our v1 release
This commit is contained in:
@@ -24,11 +24,11 @@ pub enum ParticipantEvent {
|
||||
publication: RemoteTrackPublication,
|
||||
},
|
||||
TrackSubscribed {
|
||||
track: RemoteTrackHandle,
|
||||
track: RemoteTrack,
|
||||
publication: RemoteTrackPublication,
|
||||
},
|
||||
TrackUnsubscribed {
|
||||
track: RemoteTrackHandle,
|
||||
track: RemoteTrack,
|
||||
publication: RemoteTrackPublication,
|
||||
},
|
||||
TrackSubscriptionFailed {
|
||||
@@ -51,6 +51,12 @@ pub enum ParticipantEvent {
|
||||
ConnectionQualityChanged {
|
||||
quality: ConnectionQuality,
|
||||
},
|
||||
LocalTrackPublished {
|
||||
publication: LocalTrackPublication,
|
||||
},
|
||||
LocalTrackUnpublished {
|
||||
publication: LocalTrackPublication,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
@@ -83,21 +89,48 @@ impl From<proto::ConnectionQuality> for ConnectionQuality {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct ParticipantShared {
|
||||
pub(super) sid: Mutex<ParticipantSid>,
|
||||
pub(super) identity: Mutex<ParticipantIdentity>,
|
||||
pub(super) name: Mutex<String>,
|
||||
pub(super) metadata: Mutex<String>,
|
||||
pub(super) tracks: RwLock<HashMap<TrackSid, TrackPublication>>,
|
||||
pub(super) speaking: AtomicBool,
|
||||
pub(super) audio_level: AtomicU32,
|
||||
pub(super) connection_quality: AtomicU8,
|
||||
pub(super) dispatcher: Mutex<Dispatcher<ParticipantEvent>>,
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Participant {
|
||||
Local(LocalParticipant),
|
||||
Remote(RemoteParticipant),
|
||||
}
|
||||
|
||||
impl ParticipantShared {
|
||||
pub(super) fn new(
|
||||
impl Participant {
|
||||
enum_dispatch!(
|
||||
[Local, Remote];
|
||||
pub fn sid(self: &Self) -> ParticipantSid;
|
||||
pub fn identity(self: &Self) -> ParticipantIdentity;
|
||||
pub fn name(self: &Self) -> String;
|
||||
pub fn metadata(self: &Self) -> String;
|
||||
pub fn is_speaking(self: &Self) -> bool;
|
||||
pub fn audio_level(self: &Self) -> f32;
|
||||
pub fn connection_quality(self: &Self) -> ConnectionQuality;
|
||||
pub fn tracks(self: &Self) -> RwLockReadGuard<HashMap<TrackSid, TrackPublication>>;
|
||||
pub fn register_observer(self: &Self) -> mpsc::UnboundedReceiver<ParticipantEvent>;
|
||||
|
||||
// Internal functions
|
||||
pub(crate) fn set_speaking(self: &Self, speaking: bool) -> ();
|
||||
pub(crate) fn set_audio_level(self: &Self, level: f32) -> ();
|
||||
pub(crate) fn set_connection_quality(self: &Self, quality: ConnectionQuality) -> ();
|
||||
pub(crate) fn update_info(self: &Self, info: proto::ParticipantInfo) -> ();
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ParticipantInner {
|
||||
pub sid: Mutex<ParticipantSid>,
|
||||
pub identity: Mutex<ParticipantIdentity>,
|
||||
pub name: Mutex<String>,
|
||||
pub metadata: Mutex<String>,
|
||||
pub speaking: AtomicBool,
|
||||
pub tracks: RwLock<HashMap<TrackSid, TrackPublication>>,
|
||||
pub audio_level: AtomicU32,
|
||||
pub connection_quality: AtomicU8,
|
||||
pub dispatcher: Dispatcher<ParticipantEvent>,
|
||||
}
|
||||
|
||||
impl ParticipantInner {
|
||||
pub fn new(
|
||||
sid: ParticipantSid,
|
||||
identity: ParticipantIdentity,
|
||||
name: String,
|
||||
@@ -116,128 +149,64 @@ impl ParticipantShared {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_info(&self, info: proto::ParticipantInfo) {
|
||||
pub fn sid(&self) -> ParticipantSid {
|
||||
self.sid.lock().clone()
|
||||
}
|
||||
|
||||
pub fn identity(&self) -> ParticipantIdentity {
|
||||
self.identity.lock().clone()
|
||||
}
|
||||
|
||||
pub fn name(&self) -> String {
|
||||
self.name.lock().clone()
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> String {
|
||||
self.metadata.lock().clone()
|
||||
}
|
||||
|
||||
pub fn is_speaking(&self) -> bool {
|
||||
self.speaking.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
pub fn tracks(&self) -> RwLockReadGuard<HashMap<TrackSid, TrackPublication>> {
|
||||
self.tracks.read()
|
||||
}
|
||||
|
||||
pub fn audio_level(&self) -> f32 {
|
||||
f32::from_bits(self.audio_level.load(Ordering::SeqCst))
|
||||
}
|
||||
|
||||
pub fn connection_quality(&self) -> ConnectionQuality {
|
||||
self.connection_quality.load(Ordering::SeqCst).into()
|
||||
}
|
||||
|
||||
pub fn register_observer(&self) -> mpsc::UnboundedReceiver<ParticipantEvent> {
|
||||
self.dispatcher.register()
|
||||
}
|
||||
|
||||
pub fn update_info(&self, info: proto::ParticipantInfo) {
|
||||
*self.sid.lock() = info.sid.into();
|
||||
*self.identity.lock() = info.identity.into();
|
||||
*self.name.lock() = info.name;
|
||||
*self.metadata.lock() = info.metadata; // TODO(theomonnom): callback MetadataChanged
|
||||
}
|
||||
|
||||
pub(crate) fn set_speaking(&self, speaking: bool) {
|
||||
pub fn set_speaking(&self, speaking: bool) {
|
||||
self.speaking.store(speaking, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub(crate) fn set_audio_level(&self, audio_level: f32) {
|
||||
pub fn set_audio_level(&self, audio_level: f32) {
|
||||
self.audio_level
|
||||
.store(audio_level.to_bits(), Ordering::SeqCst)
|
||||
}
|
||||
|
||||
pub(crate) fn register_observer(&self) -> mpsc::UnboundedReceiver<ParticipantEvent> {
|
||||
self.dispatcher.lock().register()
|
||||
}
|
||||
|
||||
pub(crate) fn set_connection_quality(&self, quality: ConnectionQuality) {
|
||||
pub fn set_connection_quality(&self, quality: ConnectionQuality) {
|
||||
self.connection_quality
|
||||
.store(quality as u8, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub(crate) fn add_track_publication(&self, publication: TrackPublication) {
|
||||
pub fn add_track_publication(&self, publication: TrackPublication) {
|
||||
self.tracks.write().insert(publication.sid(), publication);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait ParticipantInternalTrait {
|
||||
fn set_speaking(&self, speaking: bool);
|
||||
fn set_audio_level(&self, level: f32);
|
||||
fn set_connection_quality(&self, quality: ConnectionQuality);
|
||||
fn update_info(self: &Arc<Self>, info: proto::ParticipantInfo, emit_events: bool);
|
||||
}
|
||||
|
||||
pub trait ParticipantTrait {
|
||||
fn sid(&self) -> ParticipantSid;
|
||||
fn identity(&self) -> ParticipantIdentity;
|
||||
fn name(&self) -> String;
|
||||
fn metadata(&self) -> String;
|
||||
fn is_speaking(&self) -> bool;
|
||||
fn audio_level(&self) -> f32;
|
||||
fn connection_quality(&self) -> ConnectionQuality;
|
||||
fn tracks(&self) -> RwLockReadGuard<HashMap<TrackSid, TrackPublication>>;
|
||||
fn register_observer(&self) -> mpsc::UnboundedReceiver<ParticipantEvent>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Participant {
|
||||
Local(Arc<LocalParticipant>),
|
||||
Remote(Arc<RemoteParticipant>),
|
||||
}
|
||||
|
||||
// TODO(theomonnom): Should I provide a WeakParticipant here ?
|
||||
|
||||
impl Participant {
|
||||
enum_dispatch!(
|
||||
[Local, Remote]
|
||||
fnc!(pub(crate), update_info, &Self, [info: proto::ParticipantInfo, emit_events: bool], ());
|
||||
fnc!(pub(crate), set_speaking, &Self, [speaking: bool], ());
|
||||
fnc!(pub(crate), set_audio_level, &Self, [audio_level: f32], ());
|
||||
fnc!(pub(crate), set_connection_quality, &Self, [quality: ConnectionQuality], ());
|
||||
);
|
||||
}
|
||||
|
||||
impl ParticipantTrait for Participant {
|
||||
enum_dispatch!(
|
||||
[Local, Remote]
|
||||
fnc!(sid, &Self, [], ParticipantSid);
|
||||
fnc!(identity, &Self, [], ParticipantIdentity);
|
||||
fnc!(name, &Self, [], String);
|
||||
fnc!(metadata, &Self, [], String);
|
||||
fnc!(is_speaking, &Self, [], bool);
|
||||
fnc!(audio_level, &Self, [], f32);
|
||||
fnc!(connection_quality, &Self, [], ConnectionQuality);
|
||||
fnc!(tracks, &Self, [], RwLockReadGuard<HashMap<TrackSid, TrackPublication>>);
|
||||
fnc!(register_observer, &Self, [], mpsc::UnboundedReceiver<ParticipantEvent>);
|
||||
);
|
||||
}
|
||||
|
||||
macro_rules! impl_participant_trait {
|
||||
($x:ty) => {
|
||||
impl crate::room::participant::ParticipantTrait for $x {
|
||||
fn sid(&self) -> ParticipantSid {
|
||||
self.shared.sid.lock().clone()
|
||||
}
|
||||
|
||||
fn identity(&self) -> ParticipantIdentity {
|
||||
self.shared.identity.lock().clone()
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
self.shared.name.lock().clone()
|
||||
}
|
||||
|
||||
fn metadata(&self) -> String {
|
||||
self.shared.metadata.lock().clone()
|
||||
}
|
||||
|
||||
fn is_speaking(&self) -> bool {
|
||||
self.shared.speaking.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
fn audio_level(&self) -> f32 {
|
||||
f32::from_bits(self.shared.audio_level.load(Ordering::SeqCst))
|
||||
}
|
||||
|
||||
fn connection_quality(&self) -> ConnectionQuality {
|
||||
self.shared.connection_quality.load(Ordering::SeqCst).into()
|
||||
}
|
||||
|
||||
fn tracks(&self) -> RwLockReadGuard<HashMap<TrackSid, TrackPublication>> {
|
||||
self.shared.tracks.read()
|
||||
}
|
||||
|
||||
fn register_observer(&self) -> mpsc::UnboundedReceiver<ParticipantEvent> {
|
||||
self.shared.register_observer()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(super) use impl_participant_trait;
|
||||
|
||||
Reference in New Issue
Block a user