From 9783fc6092bdd90ae17ea75421f8fc7a1a9c7a90 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Fri, 30 Oct 2020 15:12:48 +0300 Subject: [PATCH 01/44] Rename [run ci] --- jason/CHANGELOG.md | 18 +- jason/demo/index.html | 96 +++--- jason/e2e-demo/js/index.js | 88 +++--- jason/e2e-demo/video-call.html | 10 +- jason/src/api/room.rs | 213 +++++++------ jason/src/media/constraints.rs | 6 +- .../media/media_exchange_state/controller.rs | 227 +++++++++++++ .../peer/media/media_exchange_state/mod.rs | 258 +++++++++++++++ jason/src/peer/media/mod.rs | 167 +++++----- jason/src/peer/media/mute_state/controller.rs | 215 ------------- jason/src/peer/media/mute_state/mod.rs | 236 -------------- jason/src/peer/media/receiver.rs | 74 +++-- jason/src/peer/media/sender.rs | 112 ++++--- jason/src/peer/mod.rs | 38 +-- jason/tests/api/room.rs | 297 +++++++++--------- jason/tests/peer/media.rs | 148 ++++----- jason/tests/peer/mod.rs | 42 +-- proto/client-api/src/lib.rs | 96 +++--- src/api/control/callback/mod.rs | 4 +- src/media/peer.rs | 115 +++---- src/media/track.rs | 82 ++--- .../peers/metrics/flowing_detector.rs | 12 +- tests/e2e/signalling/track_disable.rs | 140 +++++---- 23 files changed, 1421 insertions(+), 1273 deletions(-) create mode 100644 jason/src/peer/media/media_exchange_state/controller.rs create mode 100644 jason/src/peer/media/media_exchange_state/mod.rs delete mode 100644 jason/src/peer/media/mute_state/controller.rs delete mode 100644 jason/src/peer/media/mute_state/mod.rs diff --git a/jason/CHANGELOG.md b/jason/CHANGELOG.md index b4e42fb91..b4652d15a 100644 --- a/jason/CHANGELOG.md +++ b/jason/CHANGELOG.md @@ -26,11 +26,11 @@ All user visible changes to this project will be documented in this file. This p - Media management: - Library API: - - Mute/unmute local video/audio ([#40], [#81], [#97], [#144]): - - `Room.mute_audio()`; - - `Room.unmute_audio()`; - - `Room.mute_video()`; - - `Room.unmute_video()`. + - Disable/Enable local video/audio ([#40], [#81], [#97], [#144]): + - `Room.disable_audio()`; + - `Room.enable_audio()`; + - `Room.disable_video()`; + - `Room.enable_video()`. - `InputDeviceInfo` class obtainable via `MediaManager.enumerate_devices()` ([#46]); - `MediaManager` class obtainable via `Jason.media_manager()` ([#46]): - `MediaManager.enumerate_devices()`; @@ -51,10 +51,10 @@ All user visible changes to this project will be documented in this file. This p - `MediaTrack.on_enabled` and `MediaTrack.on_disabled` callbacks being called when `MediaTrack` is enabled or disabled ([#123], [#143]); - `ConnectionHandle.on_remote_track_added` callback being called when new receiver `MediaTrack` is added ([#123], [#143]); - Muting/unmuting remote video/audio ([#127]): - - `Room.mute_remote_audio`; - - `Room.unmute_remote_audio`; - - `Room.mute_remote_video`; - - `Room.unmute_remote_video`. + - `Room.disable_remote_audio`; + - `Room.enable_remote_audio`; + - `Room.disable_remote_video`; + - `Room.enable_remote_video`. - `MediaTrack.media_source_kind` function ([#145], [#146]). - Optional tracks support ([#106]); - Simultaneous device and display video tracks publishing and receiving ([#144]); diff --git a/jason/demo/index.html b/jason/demo/index.html index ac40d0811..330a8481f 100644 --- a/jason/demo/index.html +++ b/jason/demo/index.html @@ -37,10 +37,10 @@ let isVideoEnabledCheckbox = document.getElementById('is-video-enabled'); let isPublishingEnabledCheckbox = document.getElementById('is-publishing-enabled'); let usernameInput = document.getElementById('join__username'); - let muteAudioSendBtn = document.getElementById('control__mute_audio_send'); - let muteVideoSendBtn = document.getElementById('control__mute_video_send'); - let muteAudioRecvBtn = document.getElementById('control__mute_audio_recv'); - let muteVideoRecvBtn = document.getElementById('control__mute_video_recv'); + let disableAudioSendBtn = document.getElementById('control__disable_audio_send'); + let disableVideoSendBtn = document.getElementById('control__disable_video_send'); + let disableAudioRecvBtn = document.getElementById('control__disable_audio_recv'); + let disableVideoRecvBtn = document.getElementById('control__disable_video_recv'); let joinCallerButton = document.getElementById('join__join'); let connectionState = document.getElementById('connection-state__state'); let videoDiv = document.getElementById('remote-videos'); @@ -56,10 +56,10 @@ let videoPublishPolicy = 'Optional'; let isCallStarted = false; let isJoinedRoom = false; - let isAudioSendMuted = false; - let isVideoSendMuted = false; - let isAudioRecvMuted = false; - let isVideoRecvMuted = false; + let isAudioSendDisabled = false; + let isVideoSendDisabled = false; + let isAudioRecvDisabled = false; + let isVideoRecvDisabled = false; let isPublishingEnabled = true; let remote_videos = []; @@ -279,8 +279,8 @@ async function initLocalStream() { let constraints = await build_constraints( - isAudioSendMuted ? null : audioSelect, - isVideoSendMuted ? null : videoSelect + isAudioSendDisabled ? null : audioSelect, + isVideoSendDisabled ? null : videoSelect ); try { localTracks = await jason @@ -505,7 +505,7 @@ track.free(); } } - if (!isAudioSendMuted) { + if (!isAudioSendDisabled) { constraints = await initLocalStream(); } await room.set_local_media_settings(constraints); @@ -518,7 +518,7 @@ track.free(); } } - if (!isVideoSendMuted) { + if (!isVideoSendDisabled) { constraints = await initLocalStream(); } await room.set_local_media_settings(constraints); @@ -653,16 +653,16 @@ ); }); - muteAudioSendBtn.addEventListener('click', async () => { - if (isAudioSendMuted) { - await room.unmute_audio(); - isAudioSendMuted = false; - muteAudioSendBtn.textContent = 'Disable audio send'; + disableAudioSendBtn.addEventListener('click', async () => { + if (isAudioSendDisabled) { + await room.enable_audio(); + isAudioSendDisabled = false; + disableAudioSendBtn.textContent = 'Disable audio send'; if (!isCallStarted) { await initLocalStream(); } } else { - await room.mute_audio(); + await room.disable_audio(); for (const track of localTracks) { if (track.ptr > 0) { if (track.kind() === MediaKind.Audio && track.ptr > 0) { @@ -670,20 +670,20 @@ } } } - isAudioSendMuted = true; - muteAudioSendBtn.textContent = 'Enable audio send'; + isAudioSendDisabled = true; + disableAudioSendBtn.textContent = 'Enable audio send'; } }); - muteVideoSendBtn.addEventListener('click', async () => { - if (isVideoSendMuted) { - await room.unmute_video(); - isVideoSendMuted = false; - muteVideoSendBtn.textContent = 'Disable video send'; + disableVideoSendBtn.addEventListener('click', async () => { + if (isVideoSendDisabled) { + await room.enable_video(); + isVideoSendDisabled = false; + disableVideoSendBtn.textContent = 'Disable video send'; if (!isCallStarted) { await initLocalStream(); } } else { - await room.mute_video(); + await room.disable_video(); for (const track of localTracks) { if (track.ptr > 0) { if (track.kind() === MediaKind.Video && track.ptr > 0) { @@ -691,31 +691,31 @@ } } } - isVideoSendMuted = true; - muteVideoSendBtn.textContent = 'Enable video send'; + isVideoSendDisabled = true; + disableVideoSendBtn.textContent = 'Enable video send'; } }); - muteAudioRecvBtn.addEventListener('click', async () => { - if (isAudioRecvMuted) { - await room.unmute_remote_audio(); - isAudioRecvMuted = false; - muteAudioRecvBtn.textContent = 'Disable audio recv'; + disableAudioRecvBtn.addEventListener('click', async () => { + if (isAudioRecvDisabled) { + await room.enable_remote_audio(); + isAudioRecvDisabled = false; + disableAudioRecvBtn.textContent = 'Disable audio recv'; } else { - await room.mute_remote_audio(); - isAudioRecvMuted = true; - muteAudioRecvBtn.textContent = 'Enable audio recv'; + await room.disable_remote_audio(); + isAudioRecvDisabled = true; + disableAudioRecvBtn.textContent = 'Enable audio recv'; } }); - muteVideoRecvBtn.addEventListener('click', async () => { - if (isVideoRecvMuted) { - await room.unmute_remote_video(); - isVideoRecvMuted = false; - muteVideoRecvBtn.textContent = 'Disable video recv'; + disableVideoRecvBtn.addEventListener('click', async () => { + if (isVideoRecvDisabled) { + await room.enable_remote_video(); + isVideoRecvDisabled = false; + disableVideoRecvBtn.textContent = 'Disable video recv'; } else { - await room.mute_remote_video(); - isVideoRecvMuted = true; - muteVideoRecvBtn.textContent = 'Enable video recv'; + await room.disable_remote_video(); + isVideoRecvDisabled = true; + disableVideoRecvBtn.textContent = 'Enable video recv'; } }); @@ -847,12 +847,12 @@ diff --git a/jason/e2e-demo/js/index.js b/jason/e2e-demo/js/index.js index 511383646..0be1242a0 100644 --- a/jason/e2e-demo/js/index.js +++ b/jason/e2e-demo/js/index.js @@ -9,10 +9,10 @@ let remote_videos = {}; let joinCallerButton = document.getElementById('connection-settings__connect'); let usernameInput = document.getElementById('connection-settings__username'); let usernameMenuButton = document.getElementById('username-menu-button'); -let muteAudioSend = document.getElementById('control__mute_audio_send'); -let muteVideoSend = document.getElementById('control__mute_video_send'); -let muteAudioRecv = document.getElementById('control__mute_audio_recv'); -let muteVideoRecv = document.getElementById('control__mute_video_recv'); +let disableAudioSend = document.getElementById('control__disable_audio_send'); +let disableVideoSend = document.getElementById('control__disable_video_send'); +let disableAudioRecv = document.getElementById('control__disable_audio_recv'); +let disableVideoRecv = document.getElementById('control__disable_video_recv'); let closeApp = document.getElementById('control__close_app'); let audioSelect = document.getElementById('connect__select-device_audio'); let videoSelect = document.getElementById('connect__select-device_video'); @@ -449,16 +449,16 @@ window.onload = async function() { let isCallStarted = false; let localTracks = []; - let isAudioSendMuted = false; - let isVideoSendMuted = false; - let isAudioRecvMuted = false; - let isVideoRecvMuted = false; + let isAudioSendDisabled = false; + let isVideoSendDisabled = false; + let isAudioRecvDisabled = false; + let isVideoRecvDisabled = false; let room = await newRoom(); async function initLocalStream() { let constraints = await build_constraints( - isAudioSendMuted ? null : audioSelect, - isVideoSendMuted ? null : videoSelect + isAudioSendDisabled ? null : audioSelect, + isVideoSendDisabled ? null : videoSelect ); try { localTracks = await jason.media_manager().init_local_tracks(constraints) @@ -740,7 +740,7 @@ window.onload = async function() { track.free(); } } - if (!isAudioSendMuted) { + if (!isAudioSendDisabled) { constraints = await initLocalStream(); } await room.set_local_media_settings(constraints); @@ -757,7 +757,7 @@ window.onload = async function() { track.free(); } } - if (!isVideoSendMuted) { + if (!isVideoSendDisabled) { constraints = await initLocalStream(); } await room.set_local_media_settings(constraints); @@ -768,17 +768,17 @@ window.onload = async function() { videoSelect.addEventListener('change', videoSwitch); screenshareSwitchEl.addEventListener('change', videoSwitch); - muteAudioSend.addEventListener('click', async () => { + disableAudioSend.addEventListener('click', async () => { try { - if (isAudioSendMuted) { - await room.unmute_audio(); - isAudioSendMuted = false; - muteAudioSend.textContent = 'Disable audio send'; + if (isAudioSendDisabled) { + await room.enable_audio(); + isAudioSendDisabled = false; + disableAudioSend.textContent = 'Disable audio send'; if (!isCallStarted) { await initLocalStream(); } } else { - await room.mute_audio(); + await room.disable_audio(); for (const track of localTracks) { if (track.ptr > 0) { if (track.kind() === rust.MediaKind.Audio && track.ptr > 0) { @@ -786,24 +786,24 @@ window.onload = async function() { } } } - isAudioSendMuted = true; - muteAudioSend.textContent = 'Enable audio send'; + isAudioSendDisabled = true; + disableAudioSend.textContent = 'Enable audio send'; } } catch (e) { console.error(e.message()); } }); - muteVideoSend.addEventListener('click', async () => { + disableVideoSend.addEventListener('click', async () => { try { - if (isVideoSendMuted) { - await room.unmute_video(); - isVideoSendMuted = false; - muteVideoSend.textContent = 'Disable video send'; + if (isVideoSendDisabled) { + await room.enable_video(); + isVideoSendDisabled = false; + disableVideoSend.textContent = 'Disable video send'; if (!isCallStarted) { await initLocalStream(); } } else { - await room.mute_video(); + await room.disable_video(); for (const track of localTracks) { if (track.ptr > 0) { if (track.kind() === rust.MediaKind.Video && track.ptr > 0) { @@ -811,33 +811,33 @@ window.onload = async function() { } } } - isVideoSendMuted = true; - muteVideoSend.textContent = 'Enable video send'; + isVideoSendDisabled = true; + disableVideoSend.textContent = 'Enable video send'; } } catch (e) { console.error(e.trace()); } }); - muteAudioRecv.addEventListener('click', async () => { - if (isAudioRecvMuted) { - await room.unmute_remote_audio(); - isAudioRecvMuted = false; - muteAudioRecv.textContent = 'Disable audio recv' + disableAudioRecv.addEventListener('click', async () => { + if (isAudioRecvDisabled) { + await room.enable_remote_audio(); + isAudioRecvDisabled = false; + disableAudioRecv.textContent = 'Disable audio recv' } else { - await room.mute_remote_audio(); - isAudioRecvMuted = true; - muteAudioRecv.textContent = 'Enable audio recv' + await room.disable_remote_audio(); + isAudioRecvDisabled = true; + disableAudioRecv.textContent = 'Enable audio recv' } }); - muteVideoRecv.addEventListener('click', async () => { - if (isVideoRecvMuted) { - await room.unmute_remote_video(); - isVideoRecvMuted = false; - muteVideoRecv.textContent = 'Disable video recv' + disableVideoRecv.addEventListener('click', async () => { + if (isVideoRecvDisabled) { + await room.enable_remote_video(); + isVideoRecvDisabled = false; + disableVideoRecv.textContent = 'Disable video recv' } else { - await room.mute_remote_video(); - isVideoRecvMuted = true; - muteVideoRecv.textContent = 'Enable video recv' + await room.disable_remote_video(); + isVideoRecvDisabled = true; + disableVideoRecv.textContent = 'Enable video recv' } }); closeApp.addEventListener('click', () => { diff --git a/jason/e2e-demo/video-call.html b/jason/e2e-demo/video-call.html index 5ce58fe68..a1c42581e 100644 --- a/jason/e2e-demo/video-call.html +++ b/jason/e2e-demo/video-call.html @@ -71,7 +71,7 @@ margin: 3px; } - .bottom-btns__mute { + .bottom-btns__disable { flex-grow: 4; } @@ -204,12 +204,12 @@
- - + +
- - + +
+
+ + +
+
+ + +
From 864a7b198086118a2bf46328d93d4ce3f6268a12 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 5 Nov 2020 19:29:38 +0300 Subject: [PATCH 20/44] Impl receiver side muting/unmuting --- jason/src/peer/media/receiver.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index 71c7e3b20..acabd6f29 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -187,6 +187,11 @@ impl Receiver { if let Some(is_disabled) = track_patch.is_disabled_individual { self.media_exchange_state_controller.update(is_disabled); } + if let Some(is_muted) = track_patch.is_muted { + if let Some(track) = self.track.borrow().as_ref() { + track.set_enabled(!is_muted); + } + } } /// Checks whether general media exchange state of the [`Receiver`] is in From 31f7f537b584377f193a5cd5fb487c23f9e42f6a Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 5 Nov 2020 19:40:22 +0300 Subject: [PATCH 21/44] Reread [run ci] --- jason/src/media/constraints.rs | 8 +- jason/src/media/track.rs | 11 ++- jason/src/peer/media/mod.rs | 25 ++--- jason/src/peer/media/receiver.rs | 6 +- jason/src/peer/media/sender.rs | 4 +- .../media/transitable_state/media_exchange.rs | 18 ++-- jason/src/peer/media/transitable_state/mod.rs | 96 +++++++++---------- .../src/peer/media/transitable_state/mute.rs | 60 ++++++------ jason/src/peer/mod.rs | 6 +- jason/tests/peer/media.rs | 4 +- 10 files changed, 123 insertions(+), 115 deletions(-) diff --git a/jason/src/media/constraints.rs b/jason/src/media/constraints.rs index 4383730ec..2304ce633 100644 --- a/jason/src/media/constraints.rs +++ b/jason/src/media/constraints.rs @@ -160,8 +160,8 @@ struct AudioMediaTracksSettings { /// Indicator whether audio should be muted. /// - /// Any action with this flag should be performed only while disable/enable - /// actions by [`Room`]. This flag can't be changed by + /// Any action with this flag should be performed only while + /// muting/unmuting actions by [`Room`]. This flag can't be changed by /// [`MediaStreamSettings`] updating. is_muted: bool, } @@ -206,8 +206,8 @@ pub struct VideoTrackConstraints { /// Indicator whether video should be muted. /// - /// Any action with this flag should be performed only while disable/enable - /// actions by [`Room`]. This flag can't be changed by + /// Any action with this flag should be performed only while + /// muting/unmuting actions by [`Room`]. This flag can't be changed by /// [`MediaStreamSettings`] updating. is_muted: bool, } diff --git a/jason/src/media/track.rs b/jason/src/media/track.rs index 0b684253b..436c91ff8 100644 --- a/jason/src/media/track.rs +++ b/jason/src/media/track.rs @@ -92,7 +92,7 @@ impl DeeplyCloneableTrack { /// When all [`DeeplyCloneableTrack::childs`] are in muted state, then /// [`DeeplyCloneableTrack::root`] will be muted, otherwise /// [`DeeplyCloneableTrack::root`] will be unmuted. - fn update_root_enabled(&self) { + fn sync_root_mute_state(&self) { self.root .set_enabled(self.childs.iter().any(SysMediaStreamTrack::enabled)); } @@ -160,7 +160,7 @@ impl MediaStreamTrack { /// [`DeeplyCloneableTrack`] and provided [`SysMediaStreamTrack`], spawns /// listener for [`InnerMediaStreamTrack::enabled`] state changes. fn inner_new( - tracks: Rc>, + deeply_cloneable_track: Rc>, track: SysMediaStreamTrack, media_source_kind: MediaSourceKind, ) -> Self { @@ -171,7 +171,7 @@ impl MediaStreamTrack { }; let track = MediaStreamTrack(Rc::new(InnerMediaStreamTrack { - deeply_cloneable_track: tracks, + deeply_cloneable_track, enabled: ObservableCell::new(track.enabled()), on_enabled: Callback0::default(), on_disabled: Callback0::default(), @@ -255,7 +255,10 @@ impl MediaStreamTrack { pub fn set_enabled(&self, enabled: bool) { self.0.enabled.set(enabled); self.0.track.set_enabled(enabled); - self.0.deeply_cloneable_track.borrow().update_root_enabled(); + self.0 + .deeply_cloneable_track + .borrow() + .sync_root_mute_state(); } /// Returns root [`id`][1] of underlying [`DeeplyCloneableTrack`]. diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index 16a0a148a..8cbc42f16 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -46,7 +46,7 @@ pub use self::{ }; /// Transceiver's sending ([`Sender`]) or receiving ([`Receiver`]) side. -pub trait TransceiverSide: Disableable { +pub trait TransceiverSide: MediaStateControllable { /// Returns [`TrackId`] of this [`TransceiverSide`]. fn track_id(&self) -> TrackId; @@ -63,9 +63,9 @@ pub trait TransceiverSide: Disableable { fn is_transitable(&self) -> bool; } -/// Default functions for dealing with [`MediaExchangeStateController`] for -/// objects that use it. -pub trait Disableable { +/// Default functions for dealing with [`MediaExchangeStateController`] and +/// [`MuteStateController`] for objects that use it. +pub trait MediaStateControllable { /// Returns reference to the [`MediaExchangeStateController`]. fn media_exchange_state_controller( &self, @@ -74,13 +74,13 @@ pub trait Disableable { /// Returns reference to the [`MuteStateController`]. fn mute_state_controller(&self) -> Rc; - /// Returns [`MediaExchangeState`] of this [`Disableable`]. + /// Returns [`MediaExchangeState`] of this [`MediaStateControllable`]. #[inline] fn media_exchange_state(&self) -> MediaExchangeState { self.media_exchange_state_controller().state() } - /// Returns [`MuteState`] of this [`Disableable`]. + /// Returns [`MuteState`] of this [`MediaStateControllable`]. #[inline] fn mute_state(&self) -> MuteState { self.mute_state_controller().state() @@ -111,7 +111,7 @@ pub trait Disableable { } /// Returns `true` if [`Room`] should subscribe to the [`MediaState`] update - /// when updating [`Disableable`] to the provided [`MediaState`]. + /// when updating [`MediaStateControllable`] to the provided [`MediaState`]. fn is_subscription_needed(&self, desired_state: MediaState) -> bool { match desired_state { MediaState::MediaExchange(media_exchange) => { @@ -134,7 +134,8 @@ pub trait Disableable { } /// Returns `true` if [`Room`] should send [`TrackPatchCommand`] to the - /// server when updating [`Disableable`] to the provided [`MediaState`]. + /// server when updating [`MediaStateControllable`] to the provided + /// [`MediaState`]. fn is_track_patch_needed(&self, desired_state: MediaState) -> bool { match desired_state { MediaState::MediaExchange(media_exchange) => { @@ -161,8 +162,8 @@ pub trait Disableable { } /// Returns [`Future`] which will be resolved when [`MediaState`] of - /// this [`Disableable`] will be [`TransitableState::Stable`] or it is - /// dropped. + /// this [`MediaStateControllable`] will be [`TransitableState::Stable`] or + /// it is dropped. /// /// # Errors /// @@ -184,7 +185,7 @@ pub trait Disableable { } } - /// Stops state transition timer of this [`Disableable`]. + /// Stops state transition timer of this [`MediaStateControllable`]. #[inline] fn stop_media_state_transition_timeout(&self) { self.media_exchange_state_controller() @@ -192,7 +193,7 @@ pub trait Disableable { self.mute_state_controller().stop_transition_timeout(); } - /// Resets state transition timer of this [`Disableable`]. + /// Resets state transition timer of this [`MediaStateControllable`]. #[inline] fn reset_media_state_transition_timeout(&self) { self.media_exchange_state_controller() diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index acabd6f29..fa4ad9576 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -14,8 +14,8 @@ use web_sys::MediaStreamTrack as SysMediaStreamTrack; use crate::{ media::{MediaKind, MediaStreamTrack, RecvConstraints, TrackConstraints}, peer::{ - transceiver::Transceiver, Disableable, MediaConnections, PeerEvent, - TransceiverDirection, + transceiver::Transceiver, MediaConnections, MediaStateControllable, + PeerEvent, TransceiverDirection, }, }; @@ -277,7 +277,7 @@ impl Receiver { } } -impl Disableable for Receiver { +impl MediaStateControllable for Receiver { fn media_exchange_state_controller( &self, ) -> Rc { diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index 71c14cccc..72d2d5eb0 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -22,7 +22,7 @@ use super::{ MediaExchangeStateController, MediaState, MuteStateController, StableMediaExchangeState, StableMuteState, }, - Disableable, MediaConnections, MediaConnectionsError, Result, + MediaConnections, MediaConnectionsError, MediaStateControllable, Result, TransceiverSide, }; @@ -334,7 +334,7 @@ impl TransceiverSide for Sender { } } -impl Disableable for Sender { +impl MediaStateControllable for Sender { #[inline] fn media_exchange_state_controller( &self, diff --git a/jason/src/peer/media/transitable_state/media_exchange.rs b/jason/src/peer/media/transitable_state/media_exchange.rs index 2eeae967f..66108e369 100644 --- a/jason/src/peer/media/transitable_state/media_exchange.rs +++ b/jason/src/peer/media/transitable_state/media_exchange.rs @@ -5,14 +5,14 @@ use super::{InStable, InTransition}; /// State of the media publishing. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum StableMediaExchangeState { - /// [`Disableable`] is enabled. + /// [`MediaStateControllable`] is enabled. /// - /// [`Disableable`]: super::Disableable + /// [`MediaStateControllable`]: super::MediaStateControllable Enabled, - /// [`Disableable`] is disabled. + /// [`MediaStateControllable`] is disabled. /// - /// [`Disableable`]: super::Disableable + /// [`MediaStateControllable`]: super::MediaStateControllable Disabled, } @@ -67,14 +67,16 @@ impl From for StableMediaExchangeState { /// applied. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TransitionMediaExchangeState { - /// [`Disableable`] should be enabled, but awaits server permission. + /// [`MediaStateControllable`] should be enabled, but awaits server + /// permission. /// - /// [`Disableable`]: super::Disableable + /// [`MediaStateControllable`]: super::MediaStateControllable Enabling(StableMediaExchangeState), - /// [`Disableable`] should be disabled, but awaits server permission. + /// [`MediaStateControllable`] should be disabled, but awaits server + /// permission. /// - /// [`Disableable`]: super::Disableable + /// [`MediaStateControllable`]: super::MediaStateControllable Disabling(StableMediaExchangeState), } diff --git a/jason/src/peer/media/transitable_state/mod.rs b/jason/src/peer/media/transitable_state/mod.rs index 0fbdba639..c7b0e06ac 100644 --- a/jason/src/peer/media/transitable_state/mod.rs +++ b/jason/src/peer/media/transitable_state/mod.rs @@ -1,6 +1,6 @@ -//! [`Disableable`]s media exchange state. +//! [`MediaStateControllable`]s media exchange state. //! -//! [`Disableable`]: super::Disableable +//! [`MediaStateControllable`]: super::MediaStateControllable mod controller; mod media_exchange; @@ -24,7 +24,7 @@ pub type MediaExchangeState = /// [`TransitableState`] for the [`StableMuteState`]. pub type MuteState = TransitableState; -/// All media states which can be toggled in the [`Disableable`]. +/// All media states which can be toggled in the [`MediaStateControllable`]. #[derive(Clone, Copy, Debug, From)] pub enum MediaState { /// Sets `MediaStreamTrack.enabled` to the `true` of `false`. @@ -75,9 +75,34 @@ impl MediaState { } } -/// All media exchange states in which [`Disableable`] can be. +/// [`TransitableState::Stable`] variant of the [`TransitableState`]. +pub trait InStable: Clone + Copy + PartialEq { + type Transition: InTransition; + + /// Converts this [`InStable`] into [`InStable::Transition`]. + fn start_transition(self) -> Self::Transition; +} + +/// [`TransitableState::Transition`] variant of the [`TransitableState`]. +pub trait InTransition: Clone + Copy + PartialEq { + type Stable: InStable; + + /// Returns intention which this state indicates. + fn intended(self) -> Self::Stable; + + /// Sets inner [`InTransition::Stable`] state. + fn set_inner(self, inner: Self::Stable) -> Self; + + /// Returns inner [`InTransition::Stable`] state. + fn into_inner(self) -> Self::Stable; + + /// Returns opposite to this [`InTransition`]. + fn opposite(self) -> Self; +} + +/// All media exchange states in which [`MediaStateControllable`] can be. /// -/// [`Disableable`]: super::Disableable +/// [`MediaStateControllable`]: super::MediaStateControllable #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TransitableState { /// State of transition. @@ -87,30 +112,6 @@ pub enum TransitableState { Stable(S), } -impl From for MediaExchangeState { - fn from(from: StableMediaExchangeState) -> Self { - Self::Stable(from) - } -} - -impl From for MediaExchangeState { - fn from(from: TransitionMediaExchangeState) -> Self { - Self::Transition(from) - } -} - -impl From for MuteState { - fn from(from: StableMuteState) -> Self { - Self::Stable(from) - } -} - -impl From for MuteState { - fn from(from: TransitionMuteState) -> Self { - Self::Transition(from) - } -} - impl TransitableState where T: InTransition + Into>, @@ -155,29 +156,28 @@ where } } -/// [`TransitableState::Stable`] variant of the [`TransitableState`]. -pub trait InStable: Clone + Copy + PartialEq { - type Transition: InTransition; - - /// Converts this [`InStable`] into [`InStable::Transition`]. - fn start_transition(self) -> Self::Transition; +impl From for MediaExchangeState { + fn from(from: StableMediaExchangeState) -> Self { + Self::Stable(from) + } } -/// [`TransitableState::Transition`] variant of the [`TransitableState`]. -pub trait InTransition: Clone + Copy + PartialEq { - type Stable: InStable; - - /// Returns intention which this state indicates. - fn intended(self) -> Self::Stable; - - /// Sets inner [`InTransition::Stable`] state. - fn set_inner(self, inner: Self::Stable) -> Self; +impl From for MediaExchangeState { + fn from(from: TransitionMediaExchangeState) -> Self { + Self::Transition(from) + } +} - /// Returns inner [`InTransition::Stable`] state. - fn into_inner(self) -> Self::Stable; +impl From for MuteState { + fn from(from: StableMuteState) -> Self { + Self::Stable(from) + } +} - /// Returns opposite to this [`InTransition`]. - fn opposite(self) -> Self; +impl From for MuteState { + fn from(from: TransitionMuteState) -> Self { + Self::Transition(from) + } } #[cfg(test)] diff --git a/jason/src/peer/media/transitable_state/mute.rs b/jason/src/peer/media/transitable_state/mute.rs index 54e829a84..47520856c 100644 --- a/jason/src/peer/media/transitable_state/mute.rs +++ b/jason/src/peer/media/transitable_state/mute.rs @@ -5,10 +5,10 @@ use super::{InStable, InTransition}; /// State of the media mute state. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum StableMuteState { - /// [`Disableable`] is muted. + /// [`MediaStateControllable`] is muted. Muted, - /// [`Disableable`] is unmuted. + /// [`MediaStateControllable`] is unmuted. Unmuted, } @@ -22,6 +22,29 @@ impl StableMuteState { } } +impl From for StableMuteState { + #[inline] + fn from(is_muted: bool) -> Self { + if is_muted { + Self::Muted + } else { + Self::Unmuted + } + } +} + +impl InStable for StableMuteState { + type Transition = TransitionMuteState; + + #[inline] + fn start_transition(self) -> Self::Transition { + match self { + Self::Unmuted => TransitionMuteState::Muting(self), + Self::Muted => TransitionMuteState::Unmuting(self), + } + } +} + /// [`MuteState`] in transition to another /// [`StableMuteState`]. /// @@ -32,28 +55,19 @@ impl StableMuteState { /// applied. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TransitionMuteState { - /// [`Disableable`] should be muted, but awaits server permission. + /// [`MediaStateControllable`] should be muted, but awaits server + /// permission. /// - /// [`Disableable`]: super::Disableable + /// [`MediaStateControllable`]: super::MediaStateControllable Muting(StableMuteState), - /// [`Disableable`] should be unmuted, but awaits server permission. + /// [`MediaStateControllable`] should be unmuted, but awaits server + /// permission. /// - /// [`Disableable`]: super::Disableable + /// [`MediaStateControllable`]: super::MediaStateControllable Unmuting(StableMuteState), } -impl From for StableMuteState { - #[inline] - fn from(is_muted: bool) -> Self { - if is_muted { - Self::Muted - } else { - Self::Unmuted - } - } -} - impl InTransition for TransitionMuteState { type Stable = StableMuteState; @@ -88,15 +102,3 @@ impl InTransition for TransitionMuteState { } } } - -impl InStable for StableMuteState { - type Transition = TransitionMuteState; - - #[inline] - fn start_transition(self) -> Self::Transition { - match self { - Self::Unmuted => TransitionMuteState::Muting(self), - Self::Muted => TransitionMuteState::Unmuting(self), - } - } -} diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index 167bf6fa7..5e7b7e37b 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -45,9 +45,9 @@ pub use self::repo::MockPeerRepository; pub use self::{ conn::{IceCandidate, RTCPeerConnectionError, RtcPeerConnection, SdpType}, media::{ - Disableable, MediaConnections, MediaConnectionsError, MediaState, - Receiver, Sender, StableMediaExchangeState, StableMuteState, - TrackDirection, TransceiverSide, TransitableState, + MediaConnections, MediaConnectionsError, MediaState, + MediaStateControllable, Receiver, Sender, StableMediaExchangeState, + StableMuteState, TrackDirection, TransceiverSide, TransitableState, TransitionMediaExchangeState, TransitionMuteState, }, repo::{PeerRepository, Repository}, diff --git a/jason/tests/peer/media.rs b/jason/tests/peer/media.rs index 3dde12c47..6f38187d7 100644 --- a/jason/tests/peer/media.rs +++ b/jason/tests/peer/media.rs @@ -7,8 +7,8 @@ use medea_client_api_proto::{PeerId, TrackId, TrackPatchEvent}; use medea_jason::{ media::{LocalTracksConstraints, MediaManager, RecvConstraints}, peer::{ - Disableable, MediaConnections, RtcPeerConnection, SimpleTracksRequest, - StableMediaExchangeState, + MediaConnections, MediaStateControllable, RtcPeerConnection, + SimpleTracksRequest, StableMediaExchangeState, }, }; use wasm_bindgen_test::*; From df3d7577e79a3d44a96df410632c65c911a0aac9 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 5 Nov 2020 19:56:55 +0300 Subject: [PATCH 22/44] Upd CHANGELOGs --- CHANGELOG.md | 3 ++- jason/CHANGELOG.md | 7 ++++--- proto/client-api/CHANGELOG.md | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c42294ea7..a374dda69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,7 +40,7 @@ All user visible changes to this project will be documented in this file. This p - Emit `TracksApplied` event to create new and update existing tracks ([#105]); - `PeerConnection` renegotiation functionality ([#105]); - Calculate and send call quality score based on RTC stats ([#132]); - - Muting/unmuting `MediaTrack`s by receiver ([#127]); + - Enabling/disabling `MediaTrack`s by receiver ([#127], [#155]); - Send `TrackUpdate::IceRestart` based on RTC stats analysis ([#138]). - [Coturn] integration: - [Coturn] sessions destroying ([#84]); @@ -82,6 +82,7 @@ All user visible changes to this project will be documented in this file. This p [#135]: /../../pull/135 [#138]: /../../pull/138 [#153]: /../../pull/153 +[#155]: /../../pull/155 diff --git a/jason/CHANGELOG.md b/jason/CHANGELOG.md index b4652d15a..cc5a41891 100644 --- a/jason/CHANGELOG.md +++ b/jason/CHANGELOG.md @@ -26,7 +26,7 @@ All user visible changes to this project will be documented in this file. This p - Media management: - Library API: - - Disable/Enable local video/audio ([#40], [#81], [#97], [#144]): + - Disable/Enable local video/audio ([#40], [#81], [#97], [#144], [#155]): - `Room.disable_audio()`; - `Room.enable_audio()`; - `Room.disable_video()`; @@ -50,7 +50,7 @@ All user visible changes to this project will be documented in this file. This p - `Room.on_close` callback for WebSocket close initiated by server ([#55]); - `MediaTrack.on_enabled` and `MediaTrack.on_disabled` callbacks being called when `MediaTrack` is enabled or disabled ([#123], [#143]); - `ConnectionHandle.on_remote_track_added` callback being called when new receiver `MediaTrack` is added ([#123], [#143]); - - Muting/unmuting remote video/audio ([#127]): + - Enabling/disabling remote video/audio ([#127], [#155]): - `Room.disable_remote_audio`; - `Room.enable_remote_audio`; - `Room.disable_remote_video`; @@ -72,7 +72,7 @@ All user visible changes to this project will be documented in this file. This p - Signalling: - Emitting of RPC commands: - `AddPeerConnectionMetrics` with `IceConnectionState` and `PeerConnectionState` ([#71], [#87]); - - `ApplyTracks` for muting/unmuting ([#81]); + - `ApplyTracks` for enabling/disabling ([#81], [#155]); - `AddPeerConnectionStats` with `RtcStats` ([#90]); - Handling of RPC events: - `TracksApplied` with `TrackUpdate::Added`, `TrackUpdate::Updated` and `TrackUpdate::IceRestart` ([#105], [#138]); @@ -112,6 +112,7 @@ All user visible changes to this project will be documented in this file. This p [#144]: /../../pull/144 [#145]: /../../pull/145 [#146]: /../../pull/146 +[#155]: /../../pull/155 diff --git a/proto/client-api/CHANGELOG.md b/proto/client-api/CHANGELOG.md index fe125519f..0b4716091 100644 --- a/proto/client-api/CHANGELOG.md +++ b/proto/client-api/CHANGELOG.md @@ -55,7 +55,7 @@ All user visible changes to this project will be documented in this file. This p - `is_required` field to `AudioSettings` and `VideoSettings` ([#106]); - `TracksApplied` event with `TrackUpdate::Updated` and `TrackUpdate::Added` variants ([#81], [#105]); - `ConnectionQualityUpdated` event ([#132]); -- `TrackPatchEvent` and `TrackPatchCommand` types ([#127]); +- `TrackPatchEvent` and `TrackPatchCommand` types ([#127], [#155]); - `IceRestart` variant to `TrackUpdate` ([#138]); - `source_kind` field to `VideoSettings` type ([#145]); - `RoomId` and `Credential` types ([#148]). @@ -77,6 +77,7 @@ All user visible changes to this project will be documented in this file. This p [#138]: /../../pull/138 [#145]: /../../pull/145 [#148]: /../../pull/148 +[#155]: /../../pull/155 From 5998a7e799c2ff3f0b51816b57df3199fa6aefcd Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 5 Nov 2020 19:59:52 +0300 Subject: [PATCH 23/44] Minor fix [run ci] --- jason/tests/api/room.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jason/tests/api/room.rs b/jason/tests/api/room.rs index befaefd3d..4f23058c9 100644 --- a/jason/tests/api/room.rs +++ b/jason/tests/api/room.rs @@ -1481,7 +1481,7 @@ mod patches_generation { } } -/// Tests that muting and unmuting of remote audio works. +/// Tests that disabling and enabling of remote audio works. #[wasm_bindgen_test] async fn remote_disable_enable_audio() { let (audio_track, video_track) = get_test_recv_tracks(); @@ -1498,7 +1498,7 @@ async fn remote_disable_enable_audio() { assert!(peer.is_recv_audio_enabled()); } -/// Tests that muting and unmuting of remote video works. +/// Tests that disabling and enabling of remote video works. #[wasm_bindgen_test] async fn remote_disable_enable_video() { let (audio_track, video_track) = get_test_recv_tracks(); From 7db1144c6cbec920117827857382f5e53f6e4fdf Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 5 Nov 2020 20:04:53 +0300 Subject: [PATCH 24/44] Upd CHANGELOG --- CHANGELOG.md | 4 +++- jason/CHANGELOG.md | 7 +++++++ proto/client-api/CHANGELOG.md | 3 ++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a374dda69..5a08f6305 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,8 @@ All user visible changes to this project will be documented in this file. This p - `PeerConnection` renegotiation functionality ([#105]); - Calculate and send call quality score based on RTC stats ([#132]); - Enabling/disabling `MediaTrack`s by receiver ([#127], [#155]); - - Send `TrackUpdate::IceRestart` based on RTC stats analysis ([#138]). + - Send `TrackUpdate::IceRestart` based on RTC stats analysis ([#138]); + - Muting/unmuting `MediaTrack`s ([#156]). - [Coturn] integration: - [Coturn] sessions destroying ([#84]); - [Coturn] stats processing ([#94]). @@ -83,6 +84,7 @@ All user visible changes to this project will be documented in this file. This p [#138]: /../../pull/138 [#153]: /../../pull/153 [#155]: /../../pull/155 +[#156]: /../../pull/156 diff --git a/jason/CHANGELOG.md b/jason/CHANGELOG.md index cc5a41891..5bc1a2448 100644 --- a/jason/CHANGELOG.md +++ b/jason/CHANGELOG.md @@ -31,6 +31,11 @@ All user visible changes to this project will be documented in this file. This p - `Room.enable_audio()`; - `Room.disable_video()`; - `Room.enable_video()`. + - Mute/unmute local video/audio ([#156]): + - `Room.mute_audio()`; + - `Room.unmute_audio()`; + - `Room.mute_video()`; + - `Room.unmute_video()`. - `InputDeviceInfo` class obtainable via `MediaManager.enumerate_devices()` ([#46]); - `MediaManager` class obtainable via `Jason.media_manager()` ([#46]): - `MediaManager.enumerate_devices()`; @@ -74,6 +79,7 @@ All user visible changes to this project will be documented in this file. This p - `AddPeerConnectionMetrics` with `IceConnectionState` and `PeerConnectionState` ([#71], [#87]); - `ApplyTracks` for enabling/disabling ([#81], [#155]); - `AddPeerConnectionStats` with `RtcStats` ([#90]); + - `UpdateTracks` for muting/unmuting ([#156]). - Handling of RPC events: - `TracksApplied` with `TrackUpdate::Added`, `TrackUpdate::Updated` and `TrackUpdate::IceRestart` ([#105], [#138]); - `ConnectionQualityUpdated` ([#132]). @@ -113,6 +119,7 @@ All user visible changes to this project will be documented in this file. This p [#145]: /../../pull/145 [#146]: /../../pull/146 [#155]: /../../pull/155 +[#156]: /../../pull/156 diff --git a/proto/client-api/CHANGELOG.md b/proto/client-api/CHANGELOG.md index 0b4716091..e637b0a47 100644 --- a/proto/client-api/CHANGELOG.md +++ b/proto/client-api/CHANGELOG.md @@ -55,7 +55,7 @@ All user visible changes to this project will be documented in this file. This p - `is_required` field to `AudioSettings` and `VideoSettings` ([#106]); - `TracksApplied` event with `TrackUpdate::Updated` and `TrackUpdate::Added` variants ([#81], [#105]); - `ConnectionQualityUpdated` event ([#132]); -- `TrackPatchEvent` and `TrackPatchCommand` types ([#127], [#155]); +- `TrackPatchEvent` and `TrackPatchCommand` types ([#127], [#155], [#156]); - `IceRestart` variant to `TrackUpdate` ([#138]); - `source_kind` field to `VideoSettings` type ([#145]); - `RoomId` and `Credential` types ([#148]). @@ -78,6 +78,7 @@ All user visible changes to this project will be documented in this file. This p [#145]: /../../pull/145 [#148]: /../../pull/148 [#155]: /../../pull/155 +[#156]: /../../pull/156 From d2cdb73a1cf42d96b0d31245c7f4bf760747022c Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 12 Nov 2020 01:26:42 +0300 Subject: [PATCH 25/44] [run ci] From 6bc483dbe689034e079003d3f129fb9b4eb0409b Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 12 Nov 2020 12:09:18 +0300 Subject: [PATCH 26/44] Move more 'mockable' feature functions to the modules --- jason/src/peer/media/sender.rs | 22 +++++++++++----------- jason/src/peer/mod.rs | 28 +++++++++++++--------------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index 512982ece..654c4b0a3 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -243,14 +243,6 @@ impl Sender { self.transceiver.clone() } - /// Checks whether general media exchange state of the [`Sender`] is in - /// [`StableMediaExchangeState::Disabled`]. - #[cfg(feature = "mockable")] - pub fn is_general_disabled(&self) -> bool { - self.general_media_exchange_state.get() - == StableMediaExchangeState::Disabled - } - /// Checks whether general media exchange state of the [`Sender`] is in /// [`MediaExchangeState::Enabled`]. fn is_general_enabled(&self) -> bool { @@ -264,20 +256,28 @@ impl Sender { // cannot fail self.transceiver.set_send_track(None).await.unwrap(); } +} + +#[cfg(feature = "mockable")] +impl Sender { + /// Checks whether general media exchange state of the [`Sender`] is in + /// [`StableMediaExchangeState::Disabled`]. + pub fn is_general_disabled(&self) -> bool { + self.general_media_exchange_state.get() + == StableMediaExchangeState::Disabled + } /// Returns `true` if this [`Sender`] is disabled. - #[cfg(feature = "mockable")] pub fn is_disabled(&self) -> bool { self.media_exchange_state.is_disabled() } /// Returns `true` if this [`Sender`] is muted. - #[cfg(feature = "mockable")] pub fn is_muted(&self) -> bool { self.mute_state.is_muted() } - #[cfg(feature = "mockable")] + /// Returns `true` if this [`Sender`] is enabled. pub fn is_enabled(&self) -> bool { self.media_exchange_state.is_enabled() } diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index 3e7fb1c78..a77386178 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -515,21 +515,6 @@ impl PeerConnection { self.media_connections.is_recv_audio_enabled() } - /// Returns `true` if all [`Sender`]s video tracks are unmuted. - #[cfg(feature = "mockable")] - pub fn is_send_video_unmuted( - &self, - source_kind: Option, - ) -> bool { - self.media_connections.is_send_video_unmuted(source_kind) - } - - /// Returns `true` if all [`Sender`]s audio tracks are unmuted. - #[cfg(feature = "mockable")] - pub fn is_send_audio_unmuted(&self) -> bool { - self.media_connections.is_send_audio_unmuted() - } - /// Returns `true` if all [`Receiver`]s video tracks are enabled. pub fn is_recv_video_enabled(&self) -> bool { self.media_connections.is_recv_video_enabled() @@ -965,6 +950,19 @@ impl PeerConnection { ) -> bool { self.media_connections.is_send_video_enabled(source_kind) } + + /// Returns `true` if all [`Sender`]s video tracks are unmuted. + pub fn is_send_video_unmuted( + &self, + source_kind: Option, + ) -> bool { + self.media_connections.is_send_video_unmuted(source_kind) + } + + /// Returns `true` if all [`Sender`]s audio tracks are unmuted. + pub fn is_send_audio_unmuted(&self) -> bool { + self.media_connections.is_send_audio_unmuted() + } } impl Drop for PeerConnection { From 38c659beed51ad572bf72ce2d9fe15da42fdf4ac Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Mon, 16 Nov 2020 12:15:53 +0300 Subject: [PATCH 27/44] Reread --- jason/src/peer/media/mod.rs | 2 +- .../media/transitable_state/controller.rs | 8 ++--- .../transitable_state/media_exchange_state.rs | 34 +++++++++---------- .../media/transitable_state/mute_state.rs | 10 +++--- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index 2f8fbc37a..2186d4327 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -674,7 +674,7 @@ impl MediaConnections { /// [`RtcRtpTransceiver`]s via [`replaceTrack` method][1], changing its /// direction to `sendonly`. /// - /// Returns [`HashMap`] with [`media_exchange_state::State`]s updates for + /// Returns [`HashMap`] with [`media_exchange_state::Stable`]s updates for /// the [`Sender`]s. /// /// # Errors diff --git a/jason/src/peer/media/transitable_state/controller.rs b/jason/src/peer/media/transitable_state/controller.rs index 5774f9c10..8688d9c1f 100644 --- a/jason/src/peer/media/transitable_state/controller.rs +++ b/jason/src/peer/media/transitable_state/controller.rs @@ -19,10 +19,10 @@ use crate::{ use super::TransitableState; -/// [`TransitableStateController`] for the [`mute_state::Stable`]. +/// [`TransitableStateController`] for the [`mute_state`]. pub type MuteStateController = TransitableStateController; -/// [`TransitableStateController`] for the [`media_exchange_state::Stable`]. +/// [`TransitableStateController`] for the [`media_exchange_state`]. pub type MediaExchangeStateController = TransitableStateController< media_exchange_state::Stable, media_exchange_state::Transition, @@ -235,13 +235,13 @@ impl MediaExchangeStateController { } /// Checks whether [`TransitableStateController`]'s media exchange state - /// is in [`MediaExchangeState::Disabled`]. + /// is in [`media_exchange_state::Stable::Disabled`]. pub fn is_disabled(&self) -> bool { self.state.get() == media_exchange_state::Stable::Disabled.into() } /// Checks whether [`TransitableStateController`]'s media exchange state - /// is in [`MediaExchangeState::Enabled`]. + /// is in [`media_exchange_state::Stable::Enabled`]. pub fn is_enabled(&self) -> bool { self.state.get() == media_exchange_state::Stable::Enabled.into() } diff --git a/jason/src/peer/media/transitable_state/media_exchange_state.rs b/jason/src/peer/media/transitable_state/media_exchange_state.rs index 3a1158b9b..618df7ce6 100644 --- a/jason/src/peer/media/transitable_state/media_exchange_state.rs +++ b/jason/src/peer/media/transitable_state/media_exchange_state.rs @@ -17,7 +17,7 @@ pub enum Stable { } impl Stable { - /// Returns opposite to this [`StableMediaExchangeState`]. + /// Returns opposite to this [`Stable`]. pub fn opposite(self) -> Self { match self { Self::Enabled => Self::Disabled, @@ -29,14 +29,14 @@ impl Stable { impl InStable for Stable { type Transition = Transition; - /// Converts this [`StableMediaExchangeState`] into - /// [`MediaExchangeStateTransition`]. + /// Converts this [`Stable`] into + /// [`Transition`]. /// - /// [`StableMediaExchangeState::Enabled`] => - /// [`MediaExchangeStateTransition::Disabling`]. + /// [`Stable::Enabled`] => + /// [`Transition::Disabling`]. /// - /// [`StableMediaExchangeState::Disabled`] => - /// [`MediaExchangeStateTransition::Enabling`]. + /// [`Stable::Disabled`] => + /// [`Transition::Enabling`]. #[inline] fn start_transition(self) -> Self::Transition { match self { @@ -58,12 +58,12 @@ impl From for Stable { } /// [`MediaExchangeState`] in transition to another -/// [`StableMediaExchangeState`]. +/// [`Stable`]. /// -/// [`StableMediaExchangeState`] which is stored in -/// [`TransitionMediaExchangeState`] variants is a state which we already have, +/// [`Stable`] which is stored in +/// [`Transition`] variants is a state which we already have, /// but we still waiting for a desired state update. If desired state update -/// won't be received, then the stored [`StableMediaExchangeState`] will be +/// won't be received, then the stored [`Stable`] will be /// applied. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Transition { @@ -83,7 +83,7 @@ pub enum Transition { impl InTransition for Transition { type Stable = Stable; - /// Returns intention which this [`TransitionMediaExchangeState`] indicates. + /// Returns intention which this [`Transition`] indicates. #[inline] fn intended(self) -> Self::Stable { match self { @@ -92,7 +92,7 @@ impl InTransition for Transition { } } - /// Sets inner [`StableMediaExchangeState`]. + /// Sets inner [`Stable`]. #[inline] fn set_inner(self, inner: Self::Stable) -> Self { match self { @@ -101,7 +101,7 @@ impl InTransition for Transition { } } - /// Returns inner [`StableMediaExchangeState`]. + /// Returns inner [`Stable`]. #[inline] fn into_inner(self) -> Self::Stable { match self { @@ -109,9 +109,9 @@ impl InTransition for Transition { } } - /// Converts [`TransitionMediaExchangeState`] to the opposite - /// [`TransitionMediaExchangeState`] with a same inner - /// [`StableMediaExchangeState`]. + /// Converts [`Transition`] to the opposite + /// [`Transition`] with a same inner + /// [`Stable`]. #[inline] fn opposite(self) -> Self { match self { diff --git a/jason/src/peer/media/transitable_state/mute_state.rs b/jason/src/peer/media/transitable_state/mute_state.rs index c6f9615c4..f04f6fdef 100644 --- a/jason/src/peer/media/transitable_state/mute_state.rs +++ b/jason/src/peer/media/transitable_state/mute_state.rs @@ -13,7 +13,7 @@ pub enum Stable { } impl Stable { - /// Returns opposite to this [`StableMuteState`]. + /// Returns opposite to this [`Stable`]. pub fn opposite(self) -> Self { match self { Self::Muted => Self::Unmuted, @@ -46,12 +46,12 @@ impl InStable for Stable { } /// [`MuteState`] in transition to another -/// [`StableMuteState`]. +/// [`Stable`]. /// -/// [`StableMuteState`] which is stored in -/// [`TransitionMuteState`] variants is a state which we already have, +/// [`Stable`] which is stored in +/// [`Transition`] variants is a state which we already have, /// but we still waiting for a desired state update. If desired state update -/// won't be received, then the stored [`StableMuteState`] will be +/// won't be received, then the stored [`Stable`] will be /// applied. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Transition { From e422ca90330a41ce7c418dc8d1feef2dbe77a980 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Tue, 17 Nov 2020 12:51:35 +0300 Subject: [PATCH 28/44] Fix transition timers stopping --- jason/src/peer/media/receiver.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index 685228c47..91c6bac45 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -272,15 +272,30 @@ impl Receiver { } impl MediaStateControllable for Receiver { + #[inline] fn media_exchange_state_controller( &self, ) -> Rc { - self.media_exchange_state_controller.clone() + Rc::clone(&self.media_exchange_state_controller) } fn mute_state_controller(&self) -> Rc { unreachable!("Receivers muting is not implemented"); } + + /// Stops only [`MediaExchangeStateController`]'s state transition timer. + #[inline] + fn stop_media_state_transition_timeout(&self) { + self.media_exchange_state_controller() + .stop_transition_timeout(); + } + + /// Resets only [`MediaExchangeStateController`]'s state transition timer. + #[inline] + fn reset_media_state_transition_timeout(&self) { + self.media_exchange_state_controller() + .reset_transition_timeout(); + } } impl TransceiverSide for Receiver { From 33ad9c127a39a97d9aafad0787d5263bb938fb83 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Tue, 17 Nov 2020 13:40:06 +0300 Subject: [PATCH 29/44] Add tests [run ci] --- src/media/peer.rs | 142 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/src/media/peer.rs b/src/media/peer.rs index fe51add06..9f3986810 100644 --- a/src/media/peer.rs +++ b/src/media/peer.rs @@ -1652,4 +1652,146 @@ pub mod tests { } } } + + /// Tests for negotiationless [`TrackChange`]s. + mod negotiationless_changes { + use super::*; + + /// Checks that negotiationless changes will not start renegotiation. + #[test] + fn negotiationless_change_dont_triggers_negotiation() { + let track_patch = TrackPatchEvent { + id: TrackId(0), + muted: Some(true), + enabled_individual: None, + enabled_general: None, + }; + let changes = vec![TrackChange::TrackPatch(track_patch.clone())]; + + let mut negotiation_sub = MockPeerUpdatesSubscriber::new(); + negotiation_sub.expect_force_update().times(1).return_once( + move |peer_id: PeerId, updates: Vec| { + assert_eq!(peer_id, PeerId(0)); + assert_eq!( + updates, + vec![TrackUpdate::Updated(track_patch)] + ); + }, + ); + let mut peer = Peer::new( + PeerId(0), + MemberId::from("member-1"), + PeerId(1), + MemberId::from("member-2"), + false, + Rc::new(negotiation_sub), + ); + + peer.context.track_changes_queue = changes; + peer.commit_scheduled_changes(); + } + + /// Checks that [`TrackChange`] which doesn't requires negotiation with + /// [`TrackChange`] which requires negotiation will trigger negotiation. + #[test] + fn mixed_changeset_will_trigger_negotiation() { + let changes = vec![ + TrackChange::TrackPatch(TrackPatchEvent { + id: TrackId(0), + muted: Some(true), + enabled_individual: None, + enabled_general: None, + }), + TrackChange::TrackPatch(TrackPatchEvent { + id: TrackId(1), + muted: None, + enabled_individual: Some(true), + enabled_general: Some(true), + }), + ]; + + let mut negotiation_sub = MockPeerUpdatesSubscriber::new(); + negotiation_sub + .expect_negotiation_needed() + .times(1) + .return_once(move |peer_id: PeerId| { + assert_eq!(peer_id, PeerId(0)); + }); + + let mut peer = Peer::new( + PeerId(0), + MemberId::from("member-1"), + PeerId(1), + MemberId::from("member-2"), + false, + Rc::new(negotiation_sub), + ); + + peer.context.track_changes_queue = changes.clone(); + peer.commit_scheduled_changes(); + + let reversed_changes = { + let mut changes = changes; + changes.reverse(); + changes + }; + assert_eq!(peer.context.pending_track_updates, reversed_changes); + } + + /// Checks that [`TrackChange`] which changes negotiationless property + /// and negotiationful property will trigger negotiation. + #[test] + fn mixed_change_will_trigger_negotiation() { + let changes = vec![TrackChange::TrackPatch(TrackPatchEvent { + id: TrackId(0), + muted: Some(true), + enabled_individual: Some(true), + enabled_general: Some(true), + })]; + + let mut negotiation_sub = MockPeerUpdatesSubscriber::new(); + negotiation_sub + .expect_negotiation_needed() + .times(1) + .return_once(move |peer_id: PeerId| { + assert_eq!(peer_id, PeerId(0)); + }); + + let mut peer = Peer::new( + PeerId(0), + MemberId::from("member-1"), + PeerId(1), + MemberId::from("member-2"), + false, + Rc::new(negotiation_sub), + ); + + peer.context.track_changes_queue = changes.clone(); + peer.commit_scheduled_changes(); + + assert_eq!(peer.context.pending_track_updates, changes); + } + + /// Checks that [`TrackChange::is_negotiationless`] works correctly. + #[test] + fn is_negotiationless_works_fine() { + for ((enabled_general, enabled_individual, muted), expected) in &[ + ((None, None, Some(true)), true), + ((Some(true), Some(true), None), false), + ((Some(true), None, None), false), + ((Some(true), Some(true), Some(true)), false), + ] { + assert_eq!( + TrackChange::TrackPatch(TrackPatchEvent { + id: TrackId(0), + enabled_general: *enabled_general, + enabled_individual: *enabled_individual, + muted: *muted, + }) + .is_negotiationless(), + *expected + ); + } + } + } } From 1cc9ac2452f298cee06dfcd8c167f2f0c0ea60f2 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Wed, 18 Nov 2020 16:01:16 +0300 Subject: [PATCH 30/44] Refactor MediaStreamTrack deep cloning logic --- jason/src/api/room.rs | 5 +- jason/src/media/manager.rs | 32 ++-- jason/src/media/mod.rs | 3 +- jason/src/media/track.rs | 287 +++++++++++++++---------------- jason/src/peer/media/mod.rs | 3 +- jason/src/peer/media/receiver.rs | 3 +- jason/src/peer/media/sender.rs | 7 +- jason/src/peer/mod.rs | 5 +- jason/src/peer/tracks_request.rs | 7 +- jason/src/peer/transceiver.rs | 8 +- 10 files changed, 182 insertions(+), 178 deletions(-) diff --git a/jason/src/api/room.rs b/jason/src/api/room.rs index 1cc28da6b..1b56bff82 100644 --- a/jason/src/api/room.rs +++ b/jason/src/api/room.rs @@ -40,6 +40,7 @@ use crate::{ utils::{Callback1, HandlerDetachedError, JasonError, JsCaused, JsError}, JsMediaSourceKind, }; +use crate::media::LocalMediaStreamTrack; /// Reason of why [`Room`] has been closed. /// @@ -746,7 +747,7 @@ struct InnerRoom { /// Callback to be invoked when new local [`MediaStreamTrack`] will be /// added to this [`Room`]. - on_local_track: Callback1, + on_local_track: Callback1, /// Callback to be invoked when failed obtain [`MediaTrack`]s from /// [`MediaManager`] or failed inject stream into [`PeerConnection`]. @@ -1290,7 +1291,7 @@ impl PeerEventHandler for InnerRoom { /// Invokes `on_local_stream` [`Room`]'s callback. async fn on_new_local_track( &self, - track: MediaStreamTrack, + track: LocalMediaStreamTrack, ) -> Self::Output { self.on_local_track.call(track); Ok(()) diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 9096a0005..501463df6 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -7,6 +7,7 @@ use std::{ rc::{Rc, Weak}, }; +use crate::media::{MediaKind, LocalMediaStreamTrack}; use derive_more::Display; use js_sys::Promise; use medea_client_api_proto::MediaSourceKind; @@ -16,17 +17,20 @@ use wasm_bindgen_futures::{future_to_promise, JsFuture}; use web_sys::{ MediaDevices, MediaStream as SysMediaStream, MediaStreamConstraints as SysMediaStreamConstraints, + MediaStreamTrack as SysMediaStreamTrack, }; use crate::{ media::{ - track::{MediaStreamTrack, WeakMediaStreamTrack}, + track::{MediaStreamTrack}, MediaStreamSettings, MultiSourceTracksConstraints, }, utils::{window, HandlerDetachedError, JasonError, JsCaused, JsError}, }; use super::InputDeviceInfo; +use super::track::DeepTrack; +use super::track::{LocalMediaTrack, Strong, Soft}; // TODO: Screen capture API (https://w3.org/TR/screen-capture/) is in draft // stage atm, so there is no web-sys bindings for it. @@ -90,7 +94,7 @@ pub struct MediaManager(Rc); #[derive(Default)] struct InnerMediaManager { /// Obtained tracks storage - tracks: Rc>>, + tracks: Rc>>>, } impl InnerMediaManager { @@ -146,7 +150,7 @@ impl InnerMediaManager { async fn get_tracks( &self, mut caps: MediaStreamSettings, - ) -> Result> { + ) -> Result, bool)>> { let tracks_from_storage = self .get_from_storage(&mut caps) .into_iter() @@ -202,7 +206,7 @@ impl InnerMediaManager { fn get_from_storage( &self, caps: &mut MediaStreamSettings, - ) -> Vec { + ) -> Vec> { // cleanup weak links self.tracks .borrow_mut() @@ -220,7 +224,7 @@ impl InnerMediaManager { let track = storage .iter() .find(|track| caps.get_audio().satisfies(track.as_ref())) - .map(MediaStreamTrack::deep_clone); + .map(Clone::clone); if let Some(track) = track { caps.toggle_publish_audio(false); @@ -234,7 +238,7 @@ impl InnerMediaManager { .filter(|track| { caps.unconstrain_if_satisfies_video(track.as_ref()) }) - .map(MediaStreamTrack::deep_clone), + .map(Clone::clone), ); tracks @@ -249,7 +253,7 @@ impl InnerMediaManager { async fn get_user_media( &self, caps: SysMediaStreamConstraints, - ) -> Result> { + ) -> Result>> { use MediaManagerError::{CouldNotGetMediaDevices, GetUserMediaFailed}; let media_devices = window() @@ -277,10 +281,10 @@ impl InnerMediaManager { .unwrap() .unwrap() .map(|track| { - MediaStreamTrack::new(track.unwrap(), MediaSourceKind::Device) + LocalMediaTrack::new(track.unwrap().into(), MediaSourceKind::Device) }) .inspect(|track| { - storage.insert(track.root_id(), track.downgrade()); + storage.insert(track.id(), track.downgrade()); }) .collect(); @@ -296,7 +300,7 @@ impl InnerMediaManager { async fn get_display_media( &self, caps: SysMediaStreamConstraints, - ) -> Result> { + ) -> Result>> { use MediaManagerError::{ CouldNotGetMediaDevices, GetDisplayMediaFailed, GetUserMediaFailed, }; @@ -325,10 +329,10 @@ impl InnerMediaManager { .unwrap() .unwrap() .map(|tr| { - MediaStreamTrack::new(tr.unwrap(), MediaSourceKind::Display) + LocalMediaTrack::new(tr.unwrap().into(), MediaSourceKind::Display) }) .inspect(|track| { - storage.insert(track.root_id(), track.downgrade()); + storage.insert(track.id(), track.downgrade()); }) .collect(); @@ -355,7 +359,7 @@ impl MediaManager { pub async fn get_tracks>( &self, caps: I, - ) -> Result> { + ) -> Result, bool)>> { self.0.get_tracks(caps.into()).await } @@ -417,7 +421,7 @@ impl MediaManagerHandle { .map(|tracks| { tracks .into_iter() - .map(|(t, _)| t.new_root()) + .map(|(t, _)| LocalMediaStreamTrack::new(t.deep_clone())) .map(JsValue::from) .collect::() .into() diff --git a/jason/src/media/mod.rs b/jason/src/media/mod.rs index bfa2faa1f..ab2b6862c 100644 --- a/jason/src/media/mod.rs +++ b/jason/src/media/mod.rs @@ -18,8 +18,9 @@ pub use self::{ TrackConstraints, VideoSource, }, device_info::InputDeviceInfo, + track::DeepTrack, manager::{MediaManager, MediaManagerError, MediaManagerHandle}, - track::{JsMediaSourceKind, MediaStreamTrack}, + track::{JsMediaSourceKind, MediaStreamTrack, LocalMediaTrack, Strong, Soft, LocalMediaStreamTrack}, }; /// [MediaStreamTrack.kind][1] representation. diff --git a/jason/src/media/track.rs b/jason/src/media/track.rs index 436c91ff8..79294f8d4 100644 --- a/jason/src/media/track.rs +++ b/jason/src/media/track.rs @@ -45,87 +45,166 @@ impl From for JsMediaSourceKind { } } -/// Wrapper around [`SysMediaStreamTrack`] which can deeply clone underlying -/// [`SysMediaStreamTrack`] and will stop all cloned [`SysMediaStreamTrack`]s -/// when will be dropped. -/// -/// Root [`SysMediaStreamTrack`] (which can be obtained by -/// [`DeeplyCloneableTrack::get_root`]) will be muted when all child -/// [`SysMediaStreamTrack`]s are muted. -struct DeeplyCloneableTrack { - /// Root [`SysMediaStreamTrack`] which was obtained by gUM/gDM request. - root: SysMediaStreamTrack, - - /// Child [`SysMediaStreamTrack`] which are deeply cloned from the - /// [`DeeplyCloneableTrack::root`]. - childs: Vec, +#[wasm_bindgen] +pub struct LocalMediaStreamTrack(LocalMediaTrack); + +impl LocalMediaStreamTrack { + pub fn new(track: LocalMediaTrack) -> Self { + LocalMediaStreamTrack(track) + } +} + +#[wasm_bindgen] +impl LocalMediaStreamTrack { + /// Returns underlying [`SysMediaStreamTrack`] from this + /// [`MediaStreamTrack`]. + pub fn get_track(&self) -> SysMediaStreamTrack { + Clone::clone(self.0.as_ref()) + } + + /// Returns a [`String`] set to `audio` if the track is an audio track and + /// to `video`, if it is a video track. + #[wasm_bindgen(js_name = kind)] + pub fn js_kind(&self) -> MediaKind { + self.0.kind() + } + + /// Returns a [`String`] set to `device` if track is sourced from some + /// device (webcam/microphone) and to `display`, if track is captured via + /// [MediaDevices.getDisplayMedia()][1]. + /// + /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia + #[wasm_bindgen(js_name = media_source_kind)] + pub fn js_media_source_kind(&self) -> JsMediaSourceKind { + self.0.source_kind().into() + } +} + +#[derive(Clone, Debug)] +pub struct Soft(Weak); + +#[derive(Clone, Debug)] +pub struct Strong(Rc); + +#[derive(Clone, Debug)] +pub struct LocalMediaTrack { + source_kind: MediaSourceKind, + kind: MediaKind, + deep_track: S, } -impl DeeplyCloneableTrack { - /// Creates new [`DeeplyCloneableTrack`] with a provided - /// [`SysMediaStreamTrack`] as root track. - fn new(root: SysMediaStreamTrack) -> Self { +impl LocalMediaTrack { + /// Checks whether this weak reference can be upgraded to a strong one. + #[inline] + pub fn can_be_upgraded(&self) -> bool { + self.deep_track.0.strong_count() > 0 + } + + pub fn upgrade(&self) -> Option> { + Some(LocalMediaTrack { + deep_track: Strong(Weak::upgrade(&self.deep_track.0)?), + kind: self.kind, + source_kind: self.source_kind, + }) + } +} + +impl AsRef for LocalMediaTrack { + fn as_ref(&self) -> &SysMediaStreamTrack { + self.deep_track.0.track() + } +} + +impl LocalMediaTrack { + pub fn new(track: SysMediaStreamTrack, source_kind: MediaSourceKind) -> Self { + let kind = match track.kind().as_ref() { + "audio" => MediaKind::Audio, + "video" => MediaKind::Video, + _ => unreachable!(), + }; Self { - root, - childs: Vec::new(), + deep_track: Strong(DeepTrack::new(track)), + source_kind, + kind, } } - /// Returns ID of root [`SysMediaStreamTrack`]. - fn root_id(&self) -> String { - self.root.id() + pub fn set_enabled(&self, enabled: bool) { + self.deep_track.0.track().set_enabled(enabled); } - /// Deeply clones [`DeeplyCloneableTrack::root_track`], adds it to the - /// [`DeeplyCloneableTrack::childs`] and returns it. - fn new_child(&mut self) -> SysMediaStreamTrack { - let new_track = SysMediaStreamTrack::clone(&self.root); - let cloned_track = Clone::clone(&new_track); - self.childs.push(cloned_track); + pub fn id(&self) -> String { + self.deep_track.0.id() + } - new_track + pub fn source_kind(&self) -> MediaSourceKind { + self.source_kind } - /// Updates [`DeeplyCloneableTrack::root`] mute state based on - /// [`DeeplyCloneableTrack::childs`]. - /// - /// When all [`DeeplyCloneableTrack::childs`] are in muted state, then - /// [`DeeplyCloneableTrack::root`] will be muted, otherwise - /// [`DeeplyCloneableTrack::root`] will be unmuted. - fn sync_root_mute_state(&self) { - self.root - .set_enabled(self.childs.iter().any(SysMediaStreamTrack::enabled)); + pub fn kind(&self) -> MediaKind { + self.kind } - /// Returns [`DeeplyCloneableTrack::root`]. - /// - /// This [`SysMediaStreamTrack`] will be muted when all - /// [`DeeplyCloneableTrack::childs`] are muted. - fn get_root(&self) -> SysMediaStreamTrack { - Clone::clone(&self.root) + pub fn deep_clone(&self) -> Self { + Self { + deep_track: Strong(self.deep_track.0.deep_clone_track()), + source_kind: self.source_kind, + kind: self.kind + } + } + + pub fn downgrade(&self) -> LocalMediaTrack { + LocalMediaTrack { + deep_track: Soft(Rc::downgrade(&self.deep_track.0)), + kind: self.kind, + source_kind: self.source_kind + } + } +} + +#[derive(Clone, Debug)] +pub struct DeepTrack { + parent: Option>, + track: SysMediaStreamTrack, +} + +impl DeepTrack { + pub fn new(track: SysMediaStreamTrack) -> Rc { + Rc::new(Self { + parent: None, + track, + }) + } + + pub fn id(&self) -> String { + self.track.id() + } + + pub fn track(&self) -> &SysMediaStreamTrack { + &self.track + } + + pub fn deep_clone_track(self: &Rc) -> Rc { + let parent = Rc::clone(self); + let cloned_track = SysMediaStreamTrack::clone(&self.track); + Rc::new(Self { + parent: Some(parent), + track: cloned_track, + }) } } -impl Drop for DeeplyCloneableTrack { +impl Drop for DeepTrack { fn drop(&mut self) { - self.childs.drain(..).for_each(|track| { - track.stop(); - }); - self.root.stop(); + self.track.stop(); } } /// Wrapper around [`SysMediaStreamTrack`] to track when it's enabled or /// disabled. struct InnerMediaStreamTrack { - /// Underlying JS-side [`SysMediaStreamTrack`]. track: SysMediaStreamTrack, - /// Wrapper around [`SysMediaStreamTrack`] which can deeply clone - /// underlying [`SysMediaStreamTrack`] and will stop all cloned - /// [`SysMediaStreamTrack`]s when will be dropped. - deeply_cloneable_track: Rc>, - /// Underlying [`SysMediaStreamTrack`] kind. kind: MediaKind, @@ -159,8 +238,7 @@ impl MediaStreamTrack { /// Creates new [`MediaStreamTrack`] with a provided /// [`DeeplyCloneableTrack`] and provided [`SysMediaStreamTrack`], spawns /// listener for [`InnerMediaStreamTrack::enabled`] state changes. - fn inner_new( - deeply_cloneable_track: Rc>, + pub fn new( track: SysMediaStreamTrack, media_source_kind: MediaSourceKind, ) -> Self { @@ -171,13 +249,12 @@ impl MediaStreamTrack { }; let track = MediaStreamTrack(Rc::new(InnerMediaStreamTrack { - deeply_cloneable_track, enabled: ObservableCell::new(track.enabled()), + track, on_enabled: Callback0::default(), on_disabled: Callback0::default(), media_source_kind, kind, - track, })); let mut track_enabled_state_changes = @@ -204,44 +281,6 @@ impl MediaStreamTrack { track } - /// Creates new [`MediaStreamTrack`], spawns listener for - /// [`InnerMediaStreamTrack::enabled`] state changes. - pub fn new(track: T, media_source_kind: MediaSourceKind) -> Self - where - SysMediaStreamTrack: From, - { - let track = SysMediaStreamTrack::from(track); - let tracks = Rc::new(RefCell::new(DeeplyCloneableTrack::new( - Clone::clone(&track), - ))); - let track = tracks.borrow_mut().new_child(); - Self::inner_new(tracks, track, media_source_kind) - } - - /// Returns root [`MediaStreamTrack`] which will be muted when all its - /// childs are muted. - #[inline] - pub fn new_root(&self) -> Self { - Self::inner_new( - self.0.deeply_cloneable_track.clone(), - self.0.deeply_cloneable_track.borrow().get_root(), - self.0.media_source_kind, - ) - } - - /// Deeply clones this [`MediaStreamTrack`]. - /// - /// Returned [`MediaStreamTrack`] can be muted/unmuted without impacting to - /// the original [`MediaStreamTrack`]. - #[inline] - pub fn deep_clone(&self) -> Self { - Self::inner_new( - self.0.deeply_cloneable_track.clone(), - self.0.deeply_cloneable_track.borrow_mut().new_child(), - self.0.media_source_kind, - ) - } - /// Returns `true` if this [`MediaStreamTrack`] is enabled. #[inline] pub fn enabled(&self) -> &ObservableCell { @@ -255,10 +294,6 @@ impl MediaStreamTrack { pub fn set_enabled(&self, enabled: bool) { self.0.enabled.set(enabled); self.0.track.set_enabled(enabled); - self.0 - .deeply_cloneable_track - .borrow() - .sync_root_mute_state(); } /// Returns root [`id`][1] of underlying [`DeeplyCloneableTrack`]. @@ -266,8 +301,8 @@ impl MediaStreamTrack { /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack #[inline] - pub fn root_id(&self) -> String { - self.0.deeply_cloneable_track.borrow().root_id() + pub fn id(&self) -> String { + self.0.track.id() } /// Returns track kind (audio/video). @@ -276,14 +311,6 @@ impl MediaStreamTrack { self.0.kind } - /// Creates weak reference to underlying [MediaStreamTrack][2]. - /// - /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - #[inline] - pub fn downgrade(&self) -> WeakMediaStreamTrack { - WeakMediaStreamTrack(Rc::downgrade(&self.0)) - } - /// Returns this [`MediaStreamTrack`] media source kind. #[inline] pub fn media_source_kind(&self) -> MediaSourceKind { @@ -334,39 +361,3 @@ impl MediaStreamTrack { self.0.media_source_kind.into() } } - -impl AsRef for MediaStreamTrack { - #[inline] - fn as_ref(&self) -> &SysMediaStreamTrack { - &self.0.track - } -} - -impl Drop for MediaStreamTrack { - #[inline] - fn drop(&mut self) { - // Last strong ref being dropped, so stop underlying MediaTrack - if Rc::strong_count(&self.0) == 1 { - self.0.track.stop(); - } - } -} - -/// Weak reference to [MediaStreamTrack][1]. -/// -/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack -pub struct WeakMediaStreamTrack(Weak); - -impl WeakMediaStreamTrack { - /// Tries to upgrade this weak reference to a strong one. - #[inline] - pub fn upgrade(&self) -> Option { - self.0.upgrade().map(MediaStreamTrack) - } - - /// Checks whether this weak reference can be upgraded to a strong one. - #[inline] - pub fn can_be_upgraded(&self) -> bool { - self.0.strong_count() > 0 - } -} diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index 2186d4327..10c4a8025 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -43,6 +43,7 @@ pub use self::{ TransitableState, }, }; +use crate::media::{Strong, LocalMediaTrack}; /// Transceiver's sending ([`Sender`]) or receiving ([`Receiver`]) side. pub trait TransceiverSide: MediaStateControllable { @@ -693,7 +694,7 @@ impl MediaConnections { /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack pub async fn insert_local_tracks( &self, - tracks: &HashMap, + tracks: &HashMap>, ) -> Result> { let inner = self.0.borrow(); diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index 91c6bac45..c79fed763 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -26,6 +26,7 @@ use super::{ }, TransceiverSide, }; +use crate::media::DeepTrack; /// Representation of a remote [`MediaStreamTrack`] that is being received from /// some remote peer. It may have two states: `waiting` and `receiving`. @@ -144,7 +145,7 @@ impl Receiver { new_track: SysMediaStreamTrack, ) { if let Some(old_track) = self.track.borrow().as_ref() { - if old_track.root_id() == new_track.id() { + if old_track.id() == new_track.id() { return; } } diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index bc06c45b9..2711218e4 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -23,6 +23,7 @@ use super::{ MediaConnections, MediaConnectionsError, MediaStateControllable, Result, TransceiverSide, }; +use crate::media::{LocalMediaTrack, Strong}; /// Builder of the [`Sender`]. pub struct SenderBuilder<'a> { @@ -143,15 +144,17 @@ impl Sender { /// [`Sender`]. pub(super) async fn insert_track( self: Rc, - new_track: MediaStreamTrack, + new_track: LocalMediaTrack, ) -> Result<()> { // no-op if we try to insert same track if let Some(current_track) = self.transceiver.send_track() { - if new_track.root_id() == current_track.root_id() { + if new_track.id() == current_track.id() { return Ok(()); } } + let new_track = new_track.deep_clone(); + new_track.set_enabled( self.mute_state.state().cancel_transition() == mute_state::Stable::Unmuted.into(), diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index 656eaff89..91232b37b 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -55,6 +55,7 @@ pub use self::{ tracks_request::{SimpleTracksRequest, TracksRequest, TracksRequestError}, transceiver::TransceiverDirection, }; +use crate::media::{LocalMediaTrack, LocalMediaStreamTrack}; /// Errors that may occur in [RTCPeerConnection][1]. /// @@ -128,7 +129,7 @@ pub enum PeerEvent { /// [`RtcPeerConnection`] sent new local track to remote members. NewLocalTrack { /// Local [`MediaStreamTrack`] that is sent to remote members. - local_track: MediaStreamTrack, + local_track: LocalMediaStreamTrack, }, /// [`RtcPeerConnection`]'s [ICE connection][1] state changed. @@ -727,7 +728,7 @@ impl PeerConnection { for (track, is_new) in media_tracks { if is_new { let _ = self.peer_events_sender.unbounded_send( - PeerEvent::NewLocalTrack { local_track: track }, + PeerEvent::NewLocalTrack { local_track: LocalMediaStreamTrack::new(track) }, ); } } diff --git a/jason/src/peer/tracks_request.rs b/jason/src/peer/tracks_request.rs index c409a77e7..f085f50b1 100644 --- a/jason/src/peer/tracks_request.rs +++ b/jason/src/peer/tracks_request.rs @@ -16,6 +16,7 @@ use crate::{ utils::{JsCaused, JsError}, DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, }; +use crate::media::{Strong, LocalMediaTrack}; /// Errors that may occur when validating [`TracksRequest`] or /// parsing [`MediaStreamTrack`]s. @@ -137,8 +138,8 @@ impl SimpleTracksRequest { /// [`HashMap`] doesn't have the expected display video track. pub fn parse_tracks( &self, - tracks: Vec, - ) -> Result> { + tracks: Vec>, + ) -> Result>> { use TracksRequestError::{InvalidAudioTrack, InvalidVideoTrack}; let mut parsed_tracks = HashMap::new(); @@ -151,7 +152,7 @@ impl SimpleTracksRequest { MediaKind::Audio => { audio_tracks.push(track); } - MediaKind::Video => match track.media_source_kind() { + MediaKind::Video => match track.source_kind() { MediaSourceKind::Device => { device_video_tracks.push(track); } diff --git a/jason/src/peer/transceiver.rs b/jason/src/peer/transceiver.rs index 908a9f622..9ac4a12b4 100644 --- a/jason/src/peer/transceiver.rs +++ b/jason/src/peer/transceiver.rs @@ -8,13 +8,13 @@ use wasm_bindgen::JsValue; use wasm_bindgen_futures::JsFuture; use web_sys::{RtcRtpTransceiver, RtcRtpTransceiverDirection}; -use crate::media::MediaStreamTrack; +use crate::media::{MediaStreamTrack, LocalMediaTrack, Strong}; /// Wrapper around [`RtcRtpTransceiver`] which provides handy methods for /// direction changes. #[derive(Clone)] pub struct Transceiver { - send_track: RefCell>, + send_track: RefCell>>, transceiver: RtcRtpTransceiver, } @@ -54,7 +54,7 @@ impl Transceiver { /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack pub async fn set_send_track( &self, - new_track: Option, + new_track: Option>, ) -> Result<(), JsValue> { let sys_track = new_track.as_ref().map(AsRef::as_ref); JsFuture::from(self.transceiver.sender().replace_track(sys_track)) @@ -72,7 +72,7 @@ impl Transceiver { } /// Returns [`MediaStreamTrack`] that is being send to remote, if any. - pub fn send_track(&self) -> Option { + pub fn send_track(&self) -> Option> { self.send_track.borrow().clone() } From 58ebb5cf36145c47c528b8d3cd2148588fc9e077 Mon Sep 17 00:00:00 2001 From: alexlapa Date: Wed, 18 Nov 2020 16:01:05 +0200 Subject: [PATCH 31/44] refactor --- Makefile | 2 +- jason/CHANGELOG.md | 9 +- jason/src/api/room.rs | 186 ++++++++---------- jason/src/media/constraints.rs | 59 ++---- jason/src/media/manager.rs | 2 +- jason/src/peer/media/mod.rs | 2 +- jason/src/peer/media/receiver.rs | 8 +- jason/src/peer/media/sender.rs | 6 +- .../media/transitable_state/controller.rs | 66 ++----- jason/src/peer/media/transitable_state/mod.rs | 13 +- .../media/transitable_state/mute_state.rs | 4 +- jason/tests/peer/mod.rs | 11 +- proto/client-api/CHANGELOG.md | 8 +- proto/client-api/src/lib.rs | 12 +- src/media/peer.rs | 40 +--- 15 files changed, 172 insertions(+), 256 deletions(-) diff --git a/Makefile b/Makefile index c9e7daac7..f8525b700 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ CONTROL_MOCK_IMAGE_NAME := instrumentisto/medea-control-api-mock RUST_VER := 1.47 CHROME_VERSION := 86.0 -FIREFOX_VERSION := 82.0.2 +FIREFOX_VERSION := 82.0.3 crate-dir = . ifeq ($(crate),medea-jason) diff --git a/jason/CHANGELOG.md b/jason/CHANGELOG.md index 974015db9..817cc3f51 100644 --- a/jason/CHANGELOG.md +++ b/jason/CHANGELOG.md @@ -56,6 +56,11 @@ All user visible changes to this project will be documented in this file. This p - `Room.enable_remote_audio`; - `Room.disable_remote_video`; - `Room.enable_remote_video`. + - Muting/unmuting audio/video send ([#156]): + - `Room.mute_audio`; + - `Room.unmute_audio`; + - `Room.mute_video`; + - `Room.unmute_video`. - `MediaTrack.media_source_kind` function ([#145], [#146]). - Optional tracks support ([#106]); - Simultaneous device and display video tracks publishing and receiving ([#144]); @@ -73,9 +78,9 @@ All user visible changes to this project will be documented in this file. This p - Signalling: - Emitting of RPC commands: - `AddPeerConnectionMetrics` with `IceConnectionState` and `PeerConnectionState` ([#71], [#87]); - - `ApplyTracks` for enabling/disabling ([#81], [#155]); - `AddPeerConnectionStats` with `RtcStats` ([#90]); - - `UpdateTracks` for muting/unmuting ([#156]). + - Enabling/disabling audio/video send/receive via `UpdateTracks` command ([#81], [#155]); + - Muting/unmuting audio/video send via `UpdateTracks` ([#156]). - Handling of RPC events: - `TracksApplied` with `TrackUpdate::Added`, `TrackUpdate::Updated` and `TrackUpdate::IceRestart` ([#105], [#138]); - `ConnectionQualityUpdated` ([#132]). diff --git a/jason/src/api/room.rs b/jason/src/api/room.rs index 1b56bff82..156fceecf 100644 --- a/jason/src/api/room.rs +++ b/jason/src/api/room.rs @@ -300,32 +300,6 @@ impl RoomHandle { Ok(()) } - - /// Returns [`Promise`] which will switch [`MediaState`] of the provided - /// [`MediaKind`], [`TrackDirection`] and [`JsMediaSourceKind`] to the - /// provided [`MediaState`]. - fn media_state_toggle_promise( - &self, - media_state: S, - kind: MediaKind, - direction: TrackDirection, - source_kind: Option, - ) -> Promise - where - S: Into + 'static, - { - let this = Self(self.0.clone()); - future_to_promise(async move { - this.set_track_media_state( - media_state.into(), - kind, - direction, - source_kind.map(Into::into), - ) - .await?; - Ok(JsValue::UNDEFINED) - }) - } } #[wasm_bindgen] @@ -422,9 +396,38 @@ impl RoomHandle { }) } + /// Returns [`Promise`] which will switch [`MediaState`] of the provided + /// [`MediaKind`], [`TrackDirection`] and [`JsMediaSourceKind`] to the + /// provided [`MediaState`]. + /// + /// Helper function for all exported mute/unmute/enable/disable audio/video + /// send/receive methods. + fn change_media_state( + &self, + media_state: S, + kind: MediaKind, + direction: TrackDirection, + source_kind: Option, + ) -> Promise + where + S: Into + 'static, + { + let this = Self(self.0.clone()); + future_to_promise(async move { + this.set_track_media_state( + media_state.into(), + kind, + direction, + source_kind.map(Into::into), + ) + .await?; + Ok(JsValue::UNDEFINED) + }) + } + /// Mutes outbound audio in this [`Room`]. pub fn mute_audio(&self) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( mute_state::Stable::Muted, MediaKind::Audio, TrackDirection::Send, @@ -434,7 +437,7 @@ impl RoomHandle { /// Unmutes outbound audio in this [`Room`]. pub fn unmute_audio(&self) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( mute_state::Stable::Unmuted, MediaKind::Audio, TrackDirection::Send, @@ -447,7 +450,7 @@ impl RoomHandle { &self, source_kind: Option, ) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( mute_state::Stable::Muted, MediaKind::Video, TrackDirection::Send, @@ -460,7 +463,7 @@ impl RoomHandle { &self, source_kind: Option, ) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( mute_state::Stable::Unmuted, MediaKind::Video, TrackDirection::Send, @@ -470,7 +473,7 @@ impl RoomHandle { /// Disables outbound audio in this [`Room`]. pub fn disable_audio(&self) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Audio, TrackDirection::Send, @@ -480,7 +483,7 @@ impl RoomHandle { /// Enables outbound audio in this [`Room`]. pub fn enable_audio(&self) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Audio, TrackDirection::Send, @@ -495,7 +498,7 @@ impl RoomHandle { &self, source_kind: Option, ) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Video, TrackDirection::Send, @@ -510,7 +513,7 @@ impl RoomHandle { &self, source_kind: Option, ) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Video, TrackDirection::Send, @@ -520,7 +523,7 @@ impl RoomHandle { /// Disables inbound audio in this [`Room`]. pub fn disable_remote_audio(&self) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Audio, TrackDirection::Recv, @@ -530,7 +533,7 @@ impl RoomHandle { /// Disables inbound video in this [`Room`]. pub fn disable_remote_video(&self) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Video, TrackDirection::Recv, @@ -540,7 +543,7 @@ impl RoomHandle { /// Enables inbound audio in this [`Room`]. pub fn enable_remote_audio(&self) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Audio, TrackDirection::Recv, @@ -550,7 +553,7 @@ impl RoomHandle { /// Enables inbound video in this [`Room`]. pub fn enable_remote_video(&self) -> Promise { - self.media_state_toggle_promise( + self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Video, TrackDirection::Recv, @@ -804,21 +807,21 @@ impl InnerRoom { direction: TrackDirection, source_kind: Option, ) { - if let TrackDirection::Recv = direction { - match state { - MediaState::MediaExchange(media_exchange) => { - self.recv_constraints.set_enabled( - media_exchange == media_exchange_state::Stable::Enabled, - kind, - ); - } - MediaState::Mute(_) => { - unreachable!("Receivers muting is not implemented") - } + use media_exchange_state::Stable::Enabled; + use MediaState::{MediaExchange, Mute}; + use TrackDirection::{Recv, Send}; + + match (direction, state) { + (Send, _) => { + self.send_constraints + .set_media_state(state, kind, source_kind); + } + (Recv, MediaExchange(exchange)) => { + self.recv_constraints.set_enabled(exchange == Enabled, kind); + } + (Recv, Mute(_)) => { + unreachable!("Receivers muting is not implemented") } - } else { - self.send_constraints - .set_media_state(state, kind, source_kind); } } @@ -866,67 +869,48 @@ impl InnerRoom { #[allow(clippy::filter_map)] async fn update_media_states( &self, - desired_media_states: HashMap>, + desired_states: HashMap>, ) -> Result<(), Traced> { future::try_join_all( - desired_media_states + desired_states .into_iter() - .filter_map(|(peer_id, desired_media_states)| { - self.peers - .get(peer_id) - .map(|peer| (peer, desired_media_states)) + .filter_map(|(peer_id, desired_states)| { + self.peers.get(peer_id).map(|peer| (peer, desired_states)) }) - .map(|(peer, desired_media_states)| { + .map(|(peer, desired_states)| { let peer_id = peer.id(); let mut transitions_futs = Vec::new(); let mut tracks_patches = Vec::new(); - desired_media_states + desired_states .into_iter() - .filter_map(move |(track_id, desired_media_state)| { + .filter_map(move |(track_id, desired_state)| { peer.get_transceiver_side_by_id(track_id) - .map(|trnscvr| (trnscvr, desired_media_state)) + .map(|trnscvr| (trnscvr, desired_state)) }) - .filter_map(|(trnscvr, desired_media_state)| { - if trnscvr - .is_subscription_needed(desired_media_state) - { - let is_patch_needed = trnscvr - .is_track_patch_needed(desired_media_state); - Some(( - trnscvr, - desired_media_state, - is_patch_needed, - )) + .filter_map(|(trnscvr, desired_state)| { + if trnscvr.is_subscription_needed(desired_state) { + let need_patch = trnscvr + .is_track_patch_needed(desired_state); + Some((trnscvr, desired_state, need_patch)) } else { None } }) - .map( - |( - trnscvr, - desired_media_state, - should_be_patched, - )| { - trnscvr.media_state_transition_to( - desired_media_state, - )?; - transitions_futs.push( - trnscvr.when_media_state_stable( - desired_media_state, + .map(|(trnscvr, desired_state, need_patch)| { + trnscvr.media_state_transition_to(desired_state)?; + transitions_futs.push( + trnscvr.when_media_state_stable(desired_state), + ); + if need_patch { + tracks_patches.push( + desired_state.generate_track_patch( + trnscvr.track_id(), ), ); - if should_be_patched { - tracks_patches.push( - desired_media_state - .generate_track_patch( - trnscvr.track_id(), - ), - ); - } - - Ok(()) - }, - ) + } + + Ok(()) + }) .collect::>() .map_err(tracerr::map_from_and_wrap!(=> RoomError))?; if !tracks_patches.is_empty() { @@ -991,13 +975,13 @@ impl InnerRoom { ) -> Result<(), Traced> { self.send_constraints.constrain(settings); - let mut media_exchange_states_update = HashMap::new(); + let mut states_update = HashMap::new(); for peer in self.peers.get_all() { peer.update_local_stream(LocalStreamUpdateCriteria::all()) .await .map_err(tracerr::map_from_and_wrap!(=> RoomError)) .map(|new_media_exchange_states| { - media_exchange_states_update.insert( + states_update.insert( peer.id(), new_media_exchange_states .into_iter() @@ -1007,7 +991,7 @@ impl InnerRoom { })?; } - self.update_media_states(media_exchange_states_update) + self.update_media_states(states_update) .await .map_err(tracerr::map_from_and_wrap!()) } @@ -1288,7 +1272,7 @@ impl PeerEventHandler for InnerRoom { Ok(()) } - /// Invokes `on_local_stream` [`Room`]'s callback. + /// Invokes `on_local_track` [`Room`]'s callback. async fn on_new_local_track( &self, track: LocalMediaStreamTrack, diff --git a/jason/src/media/constraints.rs b/jason/src/media/constraints.rs index 1c7bf9eaf..f3ab6a17a 100644 --- a/jason/src/media/constraints.rs +++ b/jason/src/media/constraints.rs @@ -130,8 +130,8 @@ impl LocalTracksConstraints { /// Indicates whether provided [`MediaType`] is muted in the underlying /// [`MediaStreamSettings`]. #[inline] - pub fn is_muted(&self, kind: &MediaType) -> bool { - self.0.borrow().is_muted(kind) + pub fn muted(&self, kind: &MediaType) -> bool { + self.0.borrow().muted(kind) } /// Indicates whether provided [`MediaKind`] and [`MediaSourceKind`] are @@ -159,10 +159,6 @@ struct AudioMediaTracksSettings { enabled: bool, /// Indicator whether audio should be muted. - /// - /// Any action with this flag should be performed only while - /// muting/unmuting actions by [`Room`]. This flag can't be changed by - /// [`MediaStreamSettings`] updating. muted: bool, } @@ -205,10 +201,6 @@ pub struct VideoTrackConstraints { enabled: bool, /// Indicator whether video should be muted. - /// - /// Any action with this flag should be performed only while - /// muting/unmuting actions by [`Room`]. This flag can't be changed by - /// [`MediaStreamSettings`] updating. muted: bool, } @@ -413,23 +405,23 @@ impl MediaStreamSettings { match kind { MediaKind::Audio => match state { MediaState::Mute(muted) => { - self.toggle_audio_mute(muted == mute_state::Stable::Muted); + self.set_audio_muted(muted == mute_state::Stable::Muted); } MediaState::MediaExchange(media_exchange) => { - self.toggle_publish_audio( + self.set_audio_publish( media_exchange == media_exchange_state::Stable::Enabled, ); } }, MediaKind::Video => match state { MediaState::Mute(muted) => { - self.toggle_video_mute( + self.set_video_muted( muted == mute_state::Stable::Muted, source_kind, ); } MediaState::MediaExchange(media_exchange) => { - self.toggle_publish_video( + self.set_video_publish( media_exchange == media_exchange_state::Stable::Enabled, source_kind, ); @@ -438,15 +430,15 @@ impl MediaStreamSettings { } } - /// Sets the underlying [`AudioMediaTracksSettings::is_muted`] to the + /// Sets the underlying [`AudioMediaTracksSettings::muted`] to the /// given value. - fn toggle_audio_mute(&mut self, muted: bool) { + fn set_audio_muted(&mut self, muted: bool) { self.audio.muted = muted; } - /// Sets underlying [`VideoTrackConstraints::is_muted`] based on provided + /// Sets underlying [`VideoTrackConstraints::muted`] based on provided /// [`MediaSourceKind`] to the given value. - fn toggle_video_mute( + fn set_video_muted( &mut self, muted: bool, source_kind: Option, @@ -468,14 +460,14 @@ impl MediaStreamSettings { /// Sets the underlying [`AudioMediaTracksSettings::enabled`] to the /// given value. #[inline] - pub fn toggle_publish_audio(&mut self, enabled: bool) { + pub fn set_audio_publish(&mut self, enabled: bool) { self.audio.enabled = enabled; } /// Sets underlying [`VideoTrackConstraints::enabled`] based on provided /// [`MediaSourceKind`] to the given value. #[inline] - pub fn toggle_publish_video( + pub fn set_video_publish( &mut self, enabled: bool, source_kind: Option, @@ -531,28 +523,13 @@ impl MediaStreamSettings { /// Indicates whether the given [`MediaType`] is muted in this /// [`MediaStreamSettings`]. #[inline] - pub fn is_muted(&self, kind: &MediaType) -> bool { + pub fn muted(&self, kind: &MediaType) -> bool { match kind { - MediaType::Video(video) => { - self.is_track_muted(MediaKind::Video, video.source_kind) - } - MediaType::Audio(_) => { - self.is_track_muted(MediaKind::Audio, MediaSourceKind::Device) - } - } - } - - /// Indicates whether the given [`MediaKind`] and [`MediaSourceKind`] are - /// muted in this [`MediaStreamSettings`]. - fn is_track_muted(&self, kind: MediaKind, source: MediaSourceKind) -> bool { - match (kind, source) { - (MediaKind::Video, MediaSourceKind::Device) => { - self.device_video.muted - } - (MediaKind::Video, MediaSourceKind::Display) => { - self.display_video.muted - } - (MediaKind::Audio, _) => self.audio.muted, + MediaType::Video(video) => match video.source_kind { + MediaSourceKind::Device => self.device_video.muted, + MediaSourceKind::Display => self.display_video.muted, + }, + MediaType::Audio(_) => self.audio.muted, } } diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 501463df6..cd257cb84 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -227,7 +227,7 @@ impl InnerMediaManager { .map(Clone::clone); if let Some(track) = track { - caps.toggle_publish_audio(false); + caps.set_audio_publish(false); tracks.push(track); } } diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index 10c4a8025..1a26ebb5e 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -568,7 +568,7 @@ impl MediaConnections { media_exchange_state::Stable::Disabled }; let mute_state = if !send_constraints - .is_muted(&track.media_type) + .muted(&track.media_type) { mute_state::Stable::Unmuted } else if required { diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index c79fed763..eadd8cb7f 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -125,7 +125,7 @@ impl Receiver { /// Returns `true` if this [`Receiver`] is receives media data. pub fn is_receiving(&self) -> bool { - let enabled = self.media_exchange_state_controller.is_enabled(); + let enabled = self.media_exchange_state_controller.enabled(); let is_recv_direction = self.transceiver.borrow().as_ref().map_or(false, |trnsvr| { trnsvr.has_direction(TransceiverDirection::RECV) @@ -186,7 +186,7 @@ impl Receiver { self.update_general_media_exchange_state(enabled.into()); } if let Some(enabled) = track_patch.enabled_individual { - self.media_exchange_state_controller.update(enabled); + self.media_exchange_state_controller.update(enabled.into()); } if let Some(muted) = track_patch.muted { if let Some(track) = self.track.borrow().as_ref() { @@ -263,12 +263,12 @@ impl Receiver { /// Returns `true` if this [`Receiver`] is enabled. pub fn enabled(&self) -> bool { - self.media_exchange_state_controller.is_enabled() + self.media_exchange_state_controller.enabled() } /// Returns `true` if this [`Receiver`] is disabled. pub fn disabled(&self) -> bool { - self.media_exchange_state_controller.is_disabled() + self.media_exchange_state_controller.disabled() } } diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index 2711218e4..29ec11ee0 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -190,7 +190,7 @@ impl Sender { } if let Some(muted) = track.muted { - self.mute_state.update(muted); + self.mute_state.update(muted.into()); match mute_state::Stable::from(muted) { mute_state::Stable::Unmuted => { self.transceiver.set_sender_enabled(true); @@ -203,7 +203,7 @@ impl Sender { let mut requires_media_update = false; if let Some(enabled) = track.enabled_individual { let mute_state_before = self.media_exchange_state.state(); - self.media_exchange_state.update(enabled); + self.media_exchange_state.update(enabled.into()); if let ( MediaExchangeState::Stable(before), MediaExchangeState::Stable(after), @@ -218,7 +218,7 @@ impl Sender { } } if let Some(enabled) = track.enabled_individual { - self.media_exchange_state.update(enabled); + self.media_exchange_state.update(enabled.into()); } if let Some(enabled) = track.enabled_general { self.update_general_media_exchange_state(enabled.into()); diff --git a/jason/src/peer/media/transitable_state/controller.rs b/jason/src/peer/media/transitable_state/controller.rs index 8688d9c1f..3ea6cfe0b 100644 --- a/jason/src/peer/media/transitable_state/controller.rs +++ b/jason/src/peer/media/transitable_state/controller.rs @@ -10,7 +10,6 @@ use crate::{ peer::media::{ transitable_state::{ media_exchange_state, mute_state, InStable, InTransition, - MediaExchangeState, MuteState, }, MediaConnectionsError, Result, }, @@ -70,15 +69,14 @@ where if let TransitableState::Transition(_) = state { let weak_this = Rc::downgrade(&this); spawn_local(async move { - let mut transitions = - this.state.subscribe().skip(1); + let mut states = this.state.subscribe().skip(1); let (timeout, timeout_handle) = resettable_delay_for(Self::TRANSITION_TIMEOUT); this.timeout_handle .borrow_mut() .replace(timeout_handle); match future::select( - transitions.next(), + states.next(), Box::pin(timeout), ) .await @@ -169,80 +167,50 @@ where } .boxed_local() } -} -impl MuteStateController { /// Updates [`TransitableStateController::state`]. - /// - /// `Room.mute_audio` like `Promise`s will be resolved based on this - /// update. - pub(in super::super) fn update(&self, is_muted: bool) { - let new_mute_state = mute_state::Stable::from(is_muted); - let current_mute_state = self.state.get(); - - let mute_state_update: MuteState = match current_mute_state { - TransitableState::Stable(_) => new_mute_state.into(), + pub(in super::super) fn update(&self, new_state: S) { + let current_state = self.state.get(); + + let state_update = match current_state { + TransitableState::Stable(_) => new_state.into(), TransitableState::Transition(t) => { - if t.intended() == new_mute_state { - new_mute_state.into() + if t.intended() == new_state { + new_state.into() } else { - t.set_inner(new_mute_state).into() + t.set_inner(new_state).into() } } }; - self.state.set(mute_state_update); + self.state.set(state_update); } +} +impl MuteStateController { /// Checks whether [`TransitableStateController`]'s mute state /// is in [`mute_state::Stable::Muted`]. - pub fn is_muted(&self) -> bool { + pub fn muted(&self) -> bool { self.state.get() == mute_state::Stable::Muted.into() } /// Checks whether [`TransitableStateController`]'s mute state /// is in [`mute_state::Stable::Unmuted`]. - pub fn is_unmuted(&self) -> bool { + pub fn unmuted(&self) -> bool { self.state.get() == mute_state::Stable::Unmuted.into() } } impl MediaExchangeStateController { - /// Updates [`TransitableStateController::state`]. - /// - /// Real disable/enable __wouldn't__ be performed on this update. - /// - /// `Room.disable_audio` like `Promise`s will be resolved based on this - /// update. - pub(in super::super) fn update(&self, enabled: bool) { - let new_media_exchange_state = - media_exchange_state::Stable::from(enabled); - let current_media_exchange_state = self.state.get(); - - let media_exchange_state_update: MediaExchangeState = - match current_media_exchange_state { - TransitableState::Stable(_) => new_media_exchange_state.into(), - TransitableState::Transition(t) => { - if t.intended() == new_media_exchange_state { - new_media_exchange_state.into() - } else { - t.set_inner(new_media_exchange_state).into() - } - } - }; - - self.state.set(media_exchange_state_update); - } - /// Checks whether [`TransitableStateController`]'s media exchange state /// is in [`media_exchange_state::Stable::Disabled`]. - pub fn is_disabled(&self) -> bool { + pub fn disabled(&self) -> bool { self.state.get() == media_exchange_state::Stable::Disabled.into() } /// Checks whether [`TransitableStateController`]'s media exchange state /// is in [`media_exchange_state::Stable::Enabled`]. - pub fn is_enabled(&self) -> bool { + pub fn enabled(&self) -> bool { self.state.get() == media_exchange_state::Stable::Enabled.into() } } diff --git a/jason/src/peer/media/transitable_state/mod.rs b/jason/src/peer/media/transitable_state/mod.rs index 68576d8e2..749b50265 100644 --- a/jason/src/peer/media/transitable_state/mod.rs +++ b/jason/src/peer/media/transitable_state/mod.rs @@ -42,10 +42,10 @@ impl MediaState { /// this [`MediaState`]. /// /// If [`MediaState`] is [`MediaState::Mute`] then - /// [`TrackPatchCommand::is_muted`] will be [`Some`]. + /// [`TrackPatchCommand::muted`] will be [`Some`]. /// /// If [`MediaState`] is [`MediaState::MediaExchange`] then - /// [`TrackPatchCommand::is_disabled`] will be [`Some`]. + /// [`TrackPatchCommand::disabled`] will be [`Some`]. pub fn generate_track_patch(self, track_id: TrackId) -> TrackPatchCommand { match self { Self::Mute(mute) => TrackPatchCommand { @@ -116,15 +116,6 @@ where T: InTransition + Into>, S: InStable + Into>, { - /// Indicates whether [`TransitableState`] is stable (not in transition). - #[inline] - pub fn is_stable(self) -> bool { - match self { - TransitableState::Stable(_) => true, - TransitableState::Transition(_) => false, - } - } - /// Starts transition into the `desired_state` changing the state to /// [`TransitableState::Transition`]. /// diff --git a/jason/src/peer/media/transitable_state/mute_state.rs b/jason/src/peer/media/transitable_state/mute_state.rs index f04f6fdef..dbf7465ad 100644 --- a/jason/src/peer/media/transitable_state/mute_state.rs +++ b/jason/src/peer/media/transitable_state/mute_state.rs @@ -24,8 +24,8 @@ impl Stable { impl From for Stable { #[inline] - fn from(is_muted: bool) -> Self { - if is_muted { + fn from(muted: bool) -> Self { + if muted { Self::Muted } else { Self::Unmuted diff --git a/jason/tests/peer/mod.rs b/jason/tests/peer/mod.rs index c45d47362..6d8fa8763 100644 --- a/jason/tests/peer/mod.rs +++ b/jason/tests/peer/mod.rs @@ -28,8 +28,8 @@ use medea_jason::{ use wasm_bindgen_test::*; use crate::{ - delay_for, get_media_stream_settings, get_test_unrequired_tracks, - local_constraints, timeout, + delay_for, get_media_stream_settings, get_test_recv_tracks, + get_test_unrequired_tracks, local_constraints, timeout, }; wasm_bindgen_test_configure!(run_in_browser); @@ -877,7 +877,7 @@ mod peer_stats_caching { async fn reset_transition_timers() { let (tx, _) = mpsc::unbounded(); let manager = Rc::new(MediaManager::default()); - let (audio_track, video_track) = get_test_unrequired_tracks(); + let peer = PeerConnection::new( PeerId(1), tx, @@ -888,7 +888,10 @@ async fn reset_transition_timers() { Rc::new(RecvConstraints::default()), ) .unwrap(); - peer.get_offer(vec![audio_track, video_track], true) + + let (audio_tx, video_tx) = get_test_unrequired_tracks(); + let (audio_rx, video_rx) = get_test_recv_tracks(); + peer.get_offer(vec![audio_tx, video_tx, audio_rx, video_rx], true) .await .unwrap(); diff --git a/proto/client-api/CHANGELOG.md b/proto/client-api/CHANGELOG.md index b88f9cdc8..8a6e11096 100644 --- a/proto/client-api/CHANGELOG.md +++ b/proto/client-api/CHANGELOG.md @@ -55,7 +55,13 @@ All user visible changes to this project will be documented in this file. This p - `required` field to `AudioSettings` and `VideoSettings` ([#106], [#155]); - `TracksApplied` event with `TrackUpdate::Updated` and `TrackUpdate::Added` variants ([#81], [#105]); - `ConnectionQualityUpdated` event ([#132]); -- `TrackPatchEvent` and `TrackPatchCommand` types ([#127], [#155], [#156]); +- `TrackPatchCommand` ([#127]): + - `enabled` ([#127], [#155]); + - `muted` ([#156]). +- `TrackPatchEvent` ([#127]): + - `enabled_individual` ([#127], [#155]); + - `enabled_general` ([#127], [#155]); + - `muted` ([#156]). - `IceRestart` variant to `TrackUpdate` ([#138]); - `source_kind` field to `VideoSettings` type ([#145]); - `RoomId` and `Credential` types ([#148]); diff --git a/proto/client-api/src/lib.rs b/proto/client-api/src/lib.rs index d51248044..df736238b 100644 --- a/proto/client-api/src/lib.rs +++ b/proto/client-api/src/lib.rs @@ -543,16 +543,18 @@ pub struct TrackPatchEvent { /// really disabled. This is intention of this `Member`. pub enabled_individual: Option, - /// So intention of this `Member` (`enabled_individual`) can be - /// `false`, but real media exchange state can be `true`. - pub enabled_general: Option, - /// Media exchange state of the connection between `Member`s. /// /// This state indicates real media exchange state between `Member`s. But /// this state doesn't changes intention of this `Member`. /// - /// Mute state of the connection between `Member`s. + /// So intention of this `Member` (`enabled_individual`) can be + /// `false`, but real media exchange state can be `true`. + pub enabled_general: Option, + + /// `Track` mute state. Muting and unmuting can be performed without adding + /// / removing tracks from transceivers, hence renegotiation is not + /// required. pub muted: Option, } diff --git a/src/media/peer.rs b/src/media/peer.rs index 9f3986810..d630d57ec 100644 --- a/src/media/peer.rs +++ b/src/media/peer.rs @@ -366,7 +366,7 @@ pub enum TrackChange { impl TrackChange { /// Returns `true` if this [`TrackChange`] doesn't requires renegotiation. - fn is_negotiationless(&self) -> bool { + fn is_negotiation_state_agnostic(&self) -> bool { matches!( self, Self::TrackPatch(TrackPatchEvent { @@ -967,13 +967,15 @@ impl Peer { /// those changes as applied, so they can be retrieved via /// [`PeerStateMachine::get_updates`]. Calls /// [`PeerUpdatesSubscriber::negotiation_needed`] notifying subscriber that - /// this [`Peer`] has changes to negotiate. + /// this [`Peer`] has changes to negotiate. Changes that can be applied + /// regardless of negotiation state will be immediately force pushed to + /// [`PeerUpdatesSubscriber`]. fn commit_scheduled_changes(&mut self) { if !self.context.track_changes_queue.is_empty() { let mut negotiationless_changes = Vec::new(); for task in std::mem::take(&mut self.context.track_changes_queue) { let change = task.dispatch_with(self); - if change.is_negotiationless() { + if change.is_negotiation_state_agnostic() { negotiationless_changes.push(change); } else { self.context.pending_track_updates.push(change); @@ -993,7 +995,7 @@ impl Peer { } else { self.context .pending_track_updates - .extend(negotiationless_changes.into_iter()); + .append(&mut negotiationless_changes); self.context.peer_updates_sub.negotiation_needed(self.id()); } } @@ -1653,13 +1655,13 @@ pub mod tests { } } - /// Tests for negotiationless [`TrackChange`]s. - mod negotiationless_changes { + mod negotiation_state_agnostic_patches { use super::*; - /// Checks that negotiationless changes will not start renegotiation. + /// Checks that negotiation state agnostic changes will not start + /// renegotiation. #[test] - fn negotiationless_change_dont_triggers_negotiation() { + fn negotiation_state_agnostic_change_dont_trigger_negotiation() { let track_patch = TrackPatchEvent { id: TrackId(0), muted: Some(true), @@ -1771,27 +1773,5 @@ pub mod tests { assert_eq!(peer.context.pending_track_updates, changes); } - - /// Checks that [`TrackChange::is_negotiationless`] works correctly. - #[test] - fn is_negotiationless_works_fine() { - for ((enabled_general, enabled_individual, muted), expected) in &[ - ((None, None, Some(true)), true), - ((Some(true), Some(true), None), false), - ((Some(true), None, None), false), - ((Some(true), Some(true), Some(true)), false), - ] { - assert_eq!( - TrackChange::TrackPatch(TrackPatchEvent { - id: TrackId(0), - enabled_general: *enabled_general, - enabled_individual: *enabled_individual, - muted: *muted, - }) - .is_negotiationless(), - *expected - ); - } - } } } From adf4c1517490676e26c340a2b84d3010f7c21343 Mon Sep 17 00:00:00 2001 From: alexlapa Date: Thu, 19 Nov 2020 11:59:14 +0200 Subject: [PATCH 32/44] refactor --- jason/src/api/connection.rs | 6 +- jason/src/api/room.rs | 13 +- jason/src/media/manager.rs | 35 +- jason/src/media/mod.rs | 5 +- jason/src/media/track.rs | 543 ++++++++++++++++--------------- jason/src/peer/media/mod.rs | 6 +- jason/src/peer/media/receiver.rs | 7 +- jason/src/peer/media/sender.rs | 23 +- jason/src/peer/mod.rs | 12 +- jason/src/peer/tracks_request.rs | 8 +- jason/src/peer/transceiver.rs | 8 +- jason/tests/api/connection.rs | 8 +- jason/tests/media/constraints.rs | 22 +- jason/tests/media/manager.rs | 12 +- jason/tests/web.rs | 14 +- 15 files changed, 362 insertions(+), 360 deletions(-) diff --git a/jason/src/api/connection.rs b/jason/src/api/connection.rs index 8709f4a59..86103a3ad 100644 --- a/jason/src/api/connection.rs +++ b/jason/src/api/connection.rs @@ -10,7 +10,7 @@ use medea_client_api_proto::{ConnectionQualityScore, MemberId, PeerId}; use wasm_bindgen::prelude::*; use crate::{ - media::MediaStreamTrack, + media::track::remote, utils::{Callback0, Callback1, HandlerDetachedError}, }; @@ -103,7 +103,7 @@ struct InnerConnection { /// JS callback, that will be invoked when remote [`MediaStreamTrack`] is /// received. - on_remote_track_added: Callback1, + on_remote_track_added: Callback1, /// JS callback, that will be invoked when [`ConnectionQualityScore`] will /// be updated. @@ -167,7 +167,7 @@ impl Connection { /// Invokes [`InnerConnection::on_remote_track_added`] JS callback with the /// provided [`MediaStreamTrack`]. - pub fn add_remote_track(&self, track: MediaStreamTrack) { + pub fn add_remote_track(&self, track: remote::Track) { self.0.on_remote_track_added.call(track); } diff --git a/jason/src/api/room.rs b/jason/src/api/room.rs index 156fceecf..69698a3c1 100644 --- a/jason/src/api/room.rs +++ b/jason/src/api/room.rs @@ -24,8 +24,9 @@ use wasm_bindgen_futures::{future_to_promise, spawn_local}; use crate::{ api::connection::Connections, media::{ + track::{local, remote}, LocalTracksConstraints, MediaKind, MediaStreamSettings, - MediaStreamTrack, RecvConstraints, + RecvConstraints, }, peer::{ media_exchange_state, mute_state, LocalStreamUpdateCriteria, @@ -40,7 +41,6 @@ use crate::{ utils::{Callback1, HandlerDetachedError, JasonError, JsCaused, JsError}, JsMediaSourceKind, }; -use crate::media::LocalMediaStreamTrack; /// Reason of why [`Room`] has been closed. /// @@ -750,7 +750,7 @@ struct InnerRoom { /// Callback to be invoked when new local [`MediaStreamTrack`] will be /// added to this [`Room`]. - on_local_track: Callback1, + on_local_track: Callback1, /// Callback to be invoked when failed obtain [`MediaTrack`]s from /// [`MediaManager`] or failed inject stream into [`PeerConnection`]. @@ -1261,7 +1261,7 @@ impl PeerEventHandler for InnerRoom { async fn on_new_remote_track( &self, sender_id: MemberId, - track: MediaStreamTrack, + track: remote::Track, ) -> Self::Output { let conn = self .connections @@ -1273,10 +1273,7 @@ impl PeerEventHandler for InnerRoom { } /// Invokes `on_local_track` [`Room`]'s callback. - async fn on_new_local_track( - &self, - track: LocalMediaStreamTrack, - ) -> Self::Output { + async fn on_new_local_track(&self, track: local::JsTrack) -> Self::Output { self.on_local_track.call(track); Ok(()) } diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index cd257cb84..5810cf94b 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -7,7 +7,6 @@ use std::{ rc::{Rc, Weak}, }; -use crate::media::{MediaKind, LocalMediaStreamTrack}; use derive_more::Display; use js_sys::Promise; use medea_client_api_proto::MediaSourceKind; @@ -17,20 +16,17 @@ use wasm_bindgen_futures::{future_to_promise, JsFuture}; use web_sys::{ MediaDevices, MediaStream as SysMediaStream, MediaStreamConstraints as SysMediaStreamConstraints, - MediaStreamTrack as SysMediaStreamTrack, }; use crate::{ - media::{ - track::{MediaStreamTrack}, - MediaStreamSettings, MultiSourceTracksConstraints, - }, + media::{MediaStreamSettings, MultiSourceTracksConstraints}, utils::{window, HandlerDetachedError, JasonError, JsCaused, JsError}, }; -use super::InputDeviceInfo; -use super::track::DeepTrack; -use super::track::{LocalMediaTrack, Strong, Soft}; +use super::{ + track::local::{self, SharedPtr, WeakPtr}, + InputDeviceInfo, +}; // TODO: Screen capture API (https://w3.org/TR/screen-capture/) is in draft // stage atm, so there is no web-sys bindings for it. @@ -94,7 +90,7 @@ pub struct MediaManager(Rc); #[derive(Default)] struct InnerMediaManager { /// Obtained tracks storage - tracks: Rc>>>, + tracks: Rc>>>, } impl InnerMediaManager { @@ -150,7 +146,7 @@ impl InnerMediaManager { async fn get_tracks( &self, mut caps: MediaStreamSettings, - ) -> Result, bool)>> { + ) -> Result, bool)>> { let tracks_from_storage = self .get_from_storage(&mut caps) .into_iter() @@ -206,7 +202,7 @@ impl InnerMediaManager { fn get_from_storage( &self, caps: &mut MediaStreamSettings, - ) -> Vec> { + ) -> Vec> { // cleanup weak links self.tracks .borrow_mut() @@ -253,7 +249,7 @@ impl InnerMediaManager { async fn get_user_media( &self, caps: SysMediaStreamConstraints, - ) -> Result>> { + ) -> Result>> { use MediaManagerError::{CouldNotGetMediaDevices, GetUserMediaFailed}; let media_devices = window() @@ -281,7 +277,10 @@ impl InnerMediaManager { .unwrap() .unwrap() .map(|track| { - LocalMediaTrack::new(track.unwrap().into(), MediaSourceKind::Device) + local::Track::new( + track.unwrap().into(), + MediaSourceKind::Device, + ) }) .inspect(|track| { storage.insert(track.id(), track.downgrade()); @@ -300,7 +299,7 @@ impl InnerMediaManager { async fn get_display_media( &self, caps: SysMediaStreamConstraints, - ) -> Result>> { + ) -> Result>> { use MediaManagerError::{ CouldNotGetMediaDevices, GetDisplayMediaFailed, GetUserMediaFailed, }; @@ -329,7 +328,7 @@ impl InnerMediaManager { .unwrap() .unwrap() .map(|tr| { - LocalMediaTrack::new(tr.unwrap().into(), MediaSourceKind::Display) + local::Track::new(tr.unwrap().into(), MediaSourceKind::Display) }) .inspect(|track| { storage.insert(track.id(), track.downgrade()); @@ -359,7 +358,7 @@ impl MediaManager { pub async fn get_tracks>( &self, caps: I, - ) -> Result, bool)>> { + ) -> Result, bool)>> { self.0.get_tracks(caps.into()).await } @@ -421,7 +420,7 @@ impl MediaManagerHandle { .map(|tracks| { tracks .into_iter() - .map(|(t, _)| LocalMediaStreamTrack::new(t.deep_clone())) + .map(|(t, _)| local::JsTrack::new(t.fork())) .map(JsValue::from) .collect::() .into() diff --git a/jason/src/media/mod.rs b/jason/src/media/mod.rs index ab2b6862c..604c3911a 100644 --- a/jason/src/media/mod.rs +++ b/jason/src/media/mod.rs @@ -5,7 +5,7 @@ mod constraints; mod device_info; mod manager; -mod track; +pub mod track; use wasm_bindgen::prelude::*; @@ -18,9 +18,8 @@ pub use self::{ TrackConstraints, VideoSource, }, device_info::InputDeviceInfo, - track::DeepTrack, manager::{MediaManager, MediaManagerError, MediaManagerHandle}, - track::{JsMediaSourceKind, MediaStreamTrack, LocalMediaTrack, Strong, Soft, LocalMediaStreamTrack}, + track::JsMediaSourceKind, }; /// [MediaStreamTrack.kind][1] representation. diff --git a/jason/src/media/track.rs b/jason/src/media/track.rs index 79294f8d4..6d82cd644 100644 --- a/jason/src/media/track.rs +++ b/jason/src/media/track.rs @@ -2,19 +2,8 @@ //! //! [1]: https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack -use std::{ - cell::RefCell, - rc::{Rc, Weak}, -}; - -use futures::StreamExt; use medea_client_api_proto::MediaSourceKind; -use medea_reactive::ObservableCell; use wasm_bindgen::prelude::*; -use wasm_bindgen_futures::spawn_local; -use web_sys::MediaStreamTrack as SysMediaStreamTrack; - -use crate::{media::MediaKind, utils::Callback0}; /// Media source type. #[wasm_bindgen(js_name = MediaSourceKind)] @@ -45,319 +34,345 @@ impl From for JsMediaSourceKind { } } -#[wasm_bindgen] -pub struct LocalMediaStreamTrack(LocalMediaTrack); +pub mod local { -impl LocalMediaStreamTrack { - pub fn new(track: LocalMediaTrack) -> Self { - LocalMediaStreamTrack(track) - } -} + use std::rc::{Rc, Weak}; -#[wasm_bindgen] -impl LocalMediaStreamTrack { - /// Returns underlying [`SysMediaStreamTrack`] from this - /// [`MediaStreamTrack`]. - pub fn get_track(&self) -> SysMediaStreamTrack { - Clone::clone(self.0.as_ref()) - } + use derive_more::AsRef; + use medea_client_api_proto::MediaSourceKind; + use wasm_bindgen::prelude::*; + use web_sys::MediaStreamTrack as SysMediaStreamTrack; - /// Returns a [`String`] set to `audio` if the track is an audio track and - /// to `video`, if it is a video track. - #[wasm_bindgen(js_name = kind)] - pub fn js_kind(&self) -> MediaKind { - self.0.kind() - } + use crate::{media::MediaKind, JsMediaSourceKind}; - /// Returns a [`String`] set to `device` if track is sourced from some - /// device (webcam/microphone) and to `display`, if track is captured via - /// [MediaDevices.getDisplayMedia()][1]. - /// - /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - #[wasm_bindgen(js_name = media_source_kind)] - pub fn js_media_source_kind(&self) -> JsMediaSourceKind { - self.0.source_kind().into() + #[derive(Clone, Debug)] + pub struct Track { + source_kind: MediaSourceKind, + kind: MediaKind, + track: S, } -} -#[derive(Clone, Debug)] -pub struct Soft(Weak); + #[derive(Clone, Debug)] + pub struct WeakPtr(Weak); -#[derive(Clone, Debug)] -pub struct Strong(Rc); + #[derive(Clone, Debug)] + pub struct SharedPtr(Rc); -#[derive(Clone, Debug)] -pub struct LocalMediaTrack { - source_kind: MediaSourceKind, - kind: MediaKind, - deep_track: S, -} + impl Track { + /// Checks whether this weak reference can be upgraded to a strong one. + #[inline] + pub fn can_be_upgraded(&self) -> bool { + self.track.0.strong_count() > 0 + } -impl LocalMediaTrack { - /// Checks whether this weak reference can be upgraded to a strong one. - #[inline] - pub fn can_be_upgraded(&self) -> bool { - self.deep_track.0.strong_count() > 0 + pub fn upgrade(&self) -> Option> { + Some(Track { + track: SharedPtr(Weak::upgrade(&self.track.0)?), + kind: self.kind, + source_kind: self.source_kind, + }) + } } - pub fn upgrade(&self) -> Option> { - Some(LocalMediaTrack { - deep_track: Strong(Weak::upgrade(&self.deep_track.0)?), - kind: self.kind, - source_kind: self.source_kind, - }) + impl AsRef for Track { + fn as_ref(&self) -> &SysMediaStreamTrack { + self.track.0.as_ref().as_ref() + } } -} -impl AsRef for LocalMediaTrack { - fn as_ref(&self) -> &SysMediaStreamTrack { - self.deep_track.0.track() - } -} + impl Track { + pub fn new( + track: SysMediaStreamTrack, + source_kind: MediaSourceKind, + ) -> Self { + let kind = match track.kind().as_ref() { + "audio" => MediaKind::Audio, + "video" => MediaKind::Video, + _ => unreachable!(), + }; + Self { + track: SharedPtr(InnerTrack::new(track)), + source_kind, + kind, + } + } -impl LocalMediaTrack { - pub fn new(track: SysMediaStreamTrack, source_kind: MediaSourceKind) -> Self { - let kind = match track.kind().as_ref() { - "audio" => MediaKind::Audio, - "video" => MediaKind::Video, - _ => unreachable!(), - }; - Self { - deep_track: Strong(DeepTrack::new(track)), - source_kind, - kind, + pub fn set_enabled(&self, enabled: bool) { + self.track.0.as_ref().as_ref().set_enabled(enabled); } - } - pub fn set_enabled(&self, enabled: bool) { - self.deep_track.0.track().set_enabled(enabled); - } + pub fn id(&self) -> String { + self.track.0.id() + } - pub fn id(&self) -> String { - self.deep_track.0.id() - } + pub fn source_kind(&self) -> MediaSourceKind { + self.source_kind + } + + pub fn kind(&self) -> MediaKind { + self.kind + } + + pub fn fork(&self) -> Self { + Self { + track: SharedPtr(self.track.0.fork()), + source_kind: self.source_kind, + kind: self.kind, + } + } - pub fn source_kind(&self) -> MediaSourceKind { - self.source_kind + pub fn downgrade(&self) -> Track { + Track { + track: WeakPtr(Rc::downgrade(&self.track.0)), + kind: self.kind, + source_kind: self.source_kind, + } + } } - pub fn kind(&self) -> MediaKind { - self.kind + #[derive(AsRef, Clone, Debug)] + struct InnerTrack { + parent: Option>, + #[as_ref] + track: SysMediaStreamTrack, } - pub fn deep_clone(&self) -> Self { - Self { - deep_track: Strong(self.deep_track.0.deep_clone_track()), - source_kind: self.source_kind, - kind: self.kind + impl InnerTrack { + fn new(track: SysMediaStreamTrack) -> Rc { + Rc::new(Self { + parent: None, + track, + }) + } + + fn id(&self) -> String { + self.track.id() + } + + fn fork(self: &Rc) -> Rc { + let parent = Rc::clone(self); + let track = SysMediaStreamTrack::clone(&self.track); + Rc::new(Self { + parent: Some(parent), + track, + }) } } - pub fn downgrade(&self) -> LocalMediaTrack { - LocalMediaTrack { - deep_track: Soft(Rc::downgrade(&self.deep_track.0)), - kind: self.kind, - source_kind: self.source_kind + impl Drop for InnerTrack { + fn drop(&mut self) { + self.track.stop(); } } -} -#[derive(Clone, Debug)] -pub struct DeepTrack { - parent: Option>, - track: SysMediaStreamTrack, -} + #[wasm_bindgen(js_name = LocalMediaTrack)] + pub struct JsTrack(Track); -impl DeepTrack { - pub fn new(track: SysMediaStreamTrack) -> Rc { - Rc::new(Self { - parent: None, - track, - }) + impl JsTrack { + pub fn new(track: Track) -> Self { + JsTrack(track) + } } - pub fn id(&self) -> String { - self.track.id() - } + #[wasm_bindgen(js_class = LocalMediaTrack)] + impl JsTrack { + /// Returns underlying [`SysMediaStreamTrack`] from this + /// [`MediaStreamTrack`]. + pub fn get_track(&self) -> SysMediaStreamTrack { + Clone::clone(self.0.as_ref()) + } - pub fn track(&self) -> &SysMediaStreamTrack { - &self.track - } + /// Returns a [`String`] set to `audio` if the track is an audio track + /// and to `video`, if it is a video track. + #[wasm_bindgen(js_name = kind)] + pub fn js_kind(&self) -> MediaKind { + self.0.kind() + } - pub fn deep_clone_track(self: &Rc) -> Rc { - let parent = Rc::clone(self); - let cloned_track = SysMediaStreamTrack::clone(&self.track); - Rc::new(Self { - parent: Some(parent), - track: cloned_track, - }) + /// Returns a [`String`] set to `device` if track is sourced from some + /// device (webcam/microphone) and to `display`, if track is captured + /// via [MediaDevices.getDisplayMedia()][1]. + /// + /// [1]: https://tinyurl.com/y2anfntz + #[wasm_bindgen(js_name = media_source_kind)] + pub fn js_media_source_kind(&self) -> JsMediaSourceKind { + self.0.source_kind().into() + } } } -impl Drop for DeepTrack { - fn drop(&mut self) { - self.track.stop(); - } -} +pub mod remote { + use std::rc::Rc; -/// Wrapper around [`SysMediaStreamTrack`] to track when it's enabled or -/// disabled. -struct InnerMediaStreamTrack { - track: SysMediaStreamTrack, + use futures::StreamExt; + use medea_client_api_proto::MediaSourceKind; + use medea_reactive::ObservableCell; + use wasm_bindgen::prelude::*; + use wasm_bindgen_futures::spawn_local; + use web_sys::MediaStreamTrack as SysMediaStreamTrack; - /// Underlying [`SysMediaStreamTrack`] kind. - kind: MediaKind, + use crate::{media::MediaKind, utils::Callback0, JsMediaSourceKind}; - /// Underlying [`SysMediaStreamTrack`] source kind. - media_source_kind: MediaSourceKind, + /// Wrapper around [`SysMediaStreamTrack`] to track when it's enabled or + /// disabled. + struct Inner { + /// Underlying JS-side [`SysMediaStreamTrack`]. + track: SysMediaStreamTrack, + + /// Underlying [`SysMediaStreamTrack`] kind. + kind: MediaKind, - /// Callback to be invoked when this [`MediaStreamTrack`] is enabled. - on_enabled: Callback0, + /// Underlying [`SysMediaStreamTrack`] source kind. + media_source_kind: MediaSourceKind, - /// Callback to be invoked when this [`MediaStreamTrack`] is disabled. - on_disabled: Callback0, + /// Callback to be invoked when this [`MediaStreamTrack`] is enabled. + on_enabled: Callback0, - /// [enabled] property of [MediaStreamTrack][1]. + /// Callback to be invoked when this [`MediaStreamTrack`] is disabled. + on_disabled: Callback0, + + /// [enabled] property of [MediaStreamTrack][1]. + /// + /// [enabled]: https://tinyurl.com/y5byqdea + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack + enabled: ObservableCell, + } + + /// Strong reference to [MediaStreamTrack][1]. + /// + /// Track will be automatically stopped when there are no strong references + /// left. /// - /// [enabled]: https://tinyurl.com/y5byqdea /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack - enabled: ObservableCell, -} - -/// Strong reference to [MediaStreamTrack][1]. -/// -/// Track will be automatically stopped when there are no strong references -/// left. -/// -/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack -#[wasm_bindgen(js_name = MediaTrack)] -#[derive(Clone)] -pub struct MediaStreamTrack(Rc); - -impl MediaStreamTrack { - /// Creates new [`MediaStreamTrack`] with a provided - /// [`DeeplyCloneableTrack`] and provided [`SysMediaStreamTrack`], spawns - /// listener for [`InnerMediaStreamTrack::enabled`] state changes. - pub fn new( - track: SysMediaStreamTrack, - media_source_kind: MediaSourceKind, - ) -> Self { - let kind = match track.kind().as_ref() { - "audio" => MediaKind::Audio, - "video" => MediaKind::Video, - _ => unreachable!(), - }; - - let track = MediaStreamTrack(Rc::new(InnerMediaStreamTrack { - enabled: ObservableCell::new(track.enabled()), - track, - on_enabled: Callback0::default(), - on_disabled: Callback0::default(), - media_source_kind, - kind, - })); - - let mut track_enabled_state_changes = - track.enabled().subscribe().skip(1); - spawn_local({ - let weak_inner = Rc::downgrade(&track.0); - async move { - while let Some(enabled) = - track_enabled_state_changes.next().await - { - if let Some(track) = weak_inner.upgrade() { - if enabled { - track.on_enabled.call(); + #[wasm_bindgen(js_name = RemoteMediaTrack)] + #[derive(Clone)] + pub struct Track(Rc); + + impl Track { + /// Creates new [`Track`], spawns listener for + /// [`Inner::enabled`] state changes. + pub fn new(track: T, media_source_kind: MediaSourceKind) -> Self + where + SysMediaStreamTrack: From, + { + let track = SysMediaStreamTrack::from(track); + let kind = match track.kind().as_ref() { + "audio" => MediaKind::Audio, + "video" => MediaKind::Video, + _ => unreachable!(), + }; + + let track = Track(Rc::new(Inner { + enabled: ObservableCell::new(track.enabled()), + on_enabled: Callback0::default(), + on_disabled: Callback0::default(), + media_source_kind, + kind, + track, + })); + + let mut track_enabled_state_changes = + track.enabled().subscribe().skip(1); + spawn_local({ + let weak_inner = Rc::downgrade(&track.0); + async move { + while let Some(enabled) = + track_enabled_state_changes.next().await + { + if let Some(track) = weak_inner.upgrade() { + if enabled { + track.on_enabled.call(); + } else { + track.on_disabled.call(); + } } else { - track.on_disabled.call(); + break; } - } else { - break; } } - } - }); + }); - track - } + track + } - /// Returns `true` if this [`MediaStreamTrack`] is enabled. - #[inline] - pub fn enabled(&self) -> &ObservableCell { - &self.0.enabled - } + /// Returns `true` if this [`Track`] is enabled. + #[inline] + pub fn enabled(&self) -> &ObservableCell { + &self.0.enabled + } - /// Sets [`MediaStreamTrack::enabled`] to the provided value. - /// - /// Updates `enabled` in the underlying [`SysMediaStreamTrack`]. - #[inline] - pub fn set_enabled(&self, enabled: bool) { - self.0.enabled.set(enabled); - self.0.track.set_enabled(enabled); - } + /// Sets [`Track::enabled`] to the provided value. + /// + /// Updates `enabled` in the underlying [`SysMediaStreamTrack`]. + #[inline] + pub fn set_enabled(&self, enabled: bool) { + self.0.enabled.set(enabled); + self.0.track.set_enabled(enabled); + } - /// Returns root [`id`][1] of underlying [`DeeplyCloneableTrack`]. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id - /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - #[inline] - pub fn id(&self) -> String { - self.0.track.id() - } + /// Returns [`id`][1] of underlying [MediaStreamTrack][2]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] + pub fn id(&self) -> String { + self.0.track.id() + } - /// Returns track kind (audio/video). - #[inline] - pub fn kind(&self) -> MediaKind { - self.0.kind - } + /// Returns track kind (audio/video). + #[inline] + pub fn kind(&self) -> MediaKind { + self.0.kind + } - /// Returns this [`MediaStreamTrack`] media source kind. - #[inline] - pub fn media_source_kind(&self) -> MediaSourceKind { - self.0.media_source_kind + /// Returns this [`Track`] media source kind. + #[inline] + pub fn media_source_kind(&self) -> MediaSourceKind { + self.0.media_source_kind + } } -} -#[wasm_bindgen(js_class = MediaTrack)] -impl MediaStreamTrack { - /// Returns underlying [`SysMediaStreamTrack`] from this - /// [`MediaStreamTrack`]. - pub fn get_track(&self) -> SysMediaStreamTrack { - Clone::clone(&self.0.track) - } + #[wasm_bindgen(js_class = RemoteMediaTrack)] + impl Track { + /// Returns underlying [`SysMediaStreamTrack`] from this + /// [`Track`]. + pub fn get_track(&self) -> SysMediaStreamTrack { + Clone::clone(&self.0.track) + } - /// Returns is this [`MediaStreamTrack`] enabled. - #[wasm_bindgen(js_name = enabled)] - pub fn js_enabled(&self) -> bool { - self.0.enabled.get() - } + /// Returns is this [`Track`] enabled. + #[wasm_bindgen(js_name = enabled)] + pub fn js_enabled(&self) -> bool { + self.0.enabled.get() + } - /// Sets callback, which will be invoked when this [`MediaStreamTrack`] is - /// enabled. - pub fn on_enabled(&self, callback: js_sys::Function) { - self.0.on_enabled.set_func(callback); - } + /// Sets callback, which will be invoked when this [`Track`] + /// is enabled. + pub fn on_enabled(&self, callback: js_sys::Function) { + self.0.on_enabled.set_func(callback); + } - /// Sets callback, which will be invoked when this [`MediaStreamTrack`] is - /// enabled. - pub fn on_disabled(&self, callback: js_sys::Function) { - self.0.on_disabled.set_func(callback); - } + /// Sets callback, which will be invoked when this [`Track`] + /// is enabled. + pub fn on_disabled(&self, callback: js_sys::Function) { + self.0.on_disabled.set_func(callback); + } - /// Returns a [`String`] set to `audio` if the track is an audio track and - /// to `video`, if it is a video track. - #[wasm_bindgen(js_name = kind)] - pub fn js_kind(&self) -> MediaKind { - self.kind() - } + /// Returns a [`String`] set to `audio` if the track is an audio track + /// and to `video`, if it is a video track. + #[wasm_bindgen(js_name = kind)] + pub fn js_kind(&self) -> MediaKind { + self.kind() + } - /// Returns a [`String`] set to `device` if track is sourced from some - /// device (webcam/microphone) and to `display`, if track is captured via - /// [MediaDevices.getDisplayMedia()][1]. - /// - /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - #[wasm_bindgen(js_name = media_source_kind)] - pub fn js_media_source_kind(&self) -> JsMediaSourceKind { - self.0.media_source_kind.into() + /// Returns a [`String`] set to `device` if track is sourced from some + /// device (webcam/microphone) and to `display`, if track is captured + /// via [MediaDevices.getDisplayMedia()][1]. + /// + /// [1]: https://tinyurl.com/y2anfntz + #[wasm_bindgen(js_name = media_source_kind)] + pub fn js_media_source_kind(&self) -> JsMediaSourceKind { + self.0.media_source_kind.into() + } } } diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index 1a26ebb5e..dfa3715c6 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -18,7 +18,8 @@ use web_sys::RtcTrackEvent; use crate::{ media::{ - LocalTracksConstraints, MediaKind, MediaStreamTrack, RecvConstraints, + track::local::{self, SharedPtr}, + LocalTracksConstraints, MediaKind, RecvConstraints, }, peer::{ media::transitable_state::{MediaExchangeState, MuteState}, @@ -43,7 +44,6 @@ pub use self::{ TransitableState, }, }; -use crate::media::{Strong, LocalMediaTrack}; /// Transceiver's sending ([`Sender`]) or receiving ([`Receiver`]) side. pub trait TransceiverSide: MediaStateControllable { @@ -694,7 +694,7 @@ impl MediaConnections { /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack pub async fn insert_local_tracks( &self, - tracks: &HashMap>, + tracks: &HashMap>, ) -> Result> { let inner = self.0.borrow(); diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index eadd8cb7f..4813b6c1e 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -12,7 +12,7 @@ use proto::TrackId; use web_sys::MediaStreamTrack as SysMediaStreamTrack; use crate::{ - media::{MediaKind, MediaStreamTrack, RecvConstraints, TrackConstraints}, + media::{track::remote, MediaKind, RecvConstraints, TrackConstraints}, peer::{ transceiver::Transceiver, MediaConnections, MediaStateControllable, PeerEvent, TransceiverDirection, @@ -26,7 +26,6 @@ use super::{ }, TransceiverSide, }; -use crate::media::DeepTrack; /// Representation of a remote [`MediaStreamTrack`] that is being received from /// some remote peer. It may have two states: `waiting` and `receiving`. @@ -39,7 +38,7 @@ pub struct Receiver { sender_id: MemberId, transceiver: RefCell>, mid: RefCell>, - track: RefCell>, + track: RefCell>, general_media_exchange_state: Cell, is_track_notified: Cell, media_exchange_state_controller: Rc, @@ -151,7 +150,7 @@ impl Receiver { } let new_track = - MediaStreamTrack::new(new_track, self.caps.media_source_kind()); + remote::Track::new(new_track, self.caps.media_source_kind()); if self.enabled() { transceiver.add_direction(TransceiverDirection::RECV); diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index 29ec11ee0..a0944eb54 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -6,24 +6,21 @@ use medea_client_api_proto::{MediaSourceKind, TrackId, TrackPatchEvent}; use crate::{ media::{ - LocalTracksConstraints, MediaKind, MediaStreamTrack, TrackConstraints, - VideoSource, - }, - peer::{ - media::transitable_state::MediaExchangeState, - transceiver::{Transceiver, TransceiverDirection}, + track::local::{self, SharedPtr}, + LocalTracksConstraints, MediaKind, TrackConstraints, VideoSource, }, + peer::transceiver::{Transceiver, TransceiverDirection}, }; use super::{ media_exchange_state, mute_state, transitable_state::{ - MediaExchangeStateController, MediaState, MuteStateController, + MediaExchangeState, MediaExchangeStateController, MediaState, + MuteStateController, }, MediaConnections, MediaConnectionsError, MediaStateControllable, Result, TransceiverSide, }; -use crate::media::{LocalMediaTrack, Strong}; /// Builder of the [`Sender`]. pub struct SenderBuilder<'a> { @@ -144,7 +141,7 @@ impl Sender { /// [`Sender`]. pub(super) async fn insert_track( self: Rc, - new_track: LocalMediaTrack, + new_track: local::Track, ) -> Result<()> { // no-op if we try to insert same track if let Some(current_track) = self.transceiver.send_track() { @@ -153,7 +150,7 @@ impl Sender { } } - let new_track = new_track.deep_clone(); + let new_track = new_track.fork(); new_track.set_enabled( self.mute_state.state().cancel_transition() @@ -270,17 +267,17 @@ impl Sender { /// Returns `true` if this [`Sender`] is disabled. pub fn disabled(&self) -> bool { - self.media_exchange_state.is_disabled() + self.media_exchange_state.disabled() } /// Returns `true` if this [`Sender`] is muted. pub fn muted(&self) -> bool { - self.mute_state.is_muted() + self.mute_state.muted() } /// Returns `true` if this [`Sender`] is enabled. pub fn enabled(&self) -> bool { - self.media_exchange_state.is_enabled() + self.media_exchange_state.enabled() } } diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index 91232b37b..aca08ff30 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -31,8 +31,9 @@ use web_sys::{RtcIceConnectionState, RtcTrackEvent}; use crate::{ media::{ + track::{local, remote}, LocalTracksConstraints, MediaKind, MediaManager, MediaManagerError, - MediaStreamTrack, RecvConstraints, + RecvConstraints, }, utils::{JasonError, JsCaused, JsError}, MediaStreamSettings, @@ -55,7 +56,6 @@ pub use self::{ tracks_request::{SimpleTracksRequest, TracksRequest, TracksRequestError}, transceiver::TransceiverDirection, }; -use crate::media::{LocalMediaTrack, LocalMediaStreamTrack}; /// Errors that may occur in [RTCPeerConnection][1]. /// @@ -123,13 +123,13 @@ pub enum PeerEvent { sender_id: MemberId, /// Received [`MediaStreamTrack`]. - track: MediaStreamTrack, + track: remote::Track, }, /// [`RtcPeerConnection`] sent new local track to remote members. NewLocalTrack { /// Local [`MediaStreamTrack`] that is sent to remote members. - local_track: LocalMediaStreamTrack, + local_track: local::JsTrack, }, /// [`RtcPeerConnection`]'s [ICE connection][1] state changed. @@ -728,7 +728,9 @@ impl PeerConnection { for (track, is_new) in media_tracks { if is_new { let _ = self.peer_events_sender.unbounded_send( - PeerEvent::NewLocalTrack { local_track: LocalMediaStreamTrack::new(track) }, + PeerEvent::NewLocalTrack { + local_track: local::JsTrack::new(track), + }, ); } } diff --git a/jason/src/peer/tracks_request.rs b/jason/src/peer/tracks_request.rs index f085f50b1..0b4a12f4a 100644 --- a/jason/src/peer/tracks_request.rs +++ b/jason/src/peer/tracks_request.rs @@ -10,13 +10,13 @@ use tracerr::Traced; use crate::{ media::{ + track::local::{self, SharedPtr}, AudioTrackConstraints, MediaKind, MediaStreamSettings, - MediaStreamTrack, TrackConstraints, VideoSource, + TrackConstraints, VideoSource, }, utils::{JsCaused, JsError}, DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, }; -use crate::media::{Strong, LocalMediaTrack}; /// Errors that may occur when validating [`TracksRequest`] or /// parsing [`MediaStreamTrack`]s. @@ -138,8 +138,8 @@ impl SimpleTracksRequest { /// [`HashMap`] doesn't have the expected display video track. pub fn parse_tracks( &self, - tracks: Vec>, - ) -> Result>> { + tracks: Vec>, + ) -> Result>> { use TracksRequestError::{InvalidAudioTrack, InvalidVideoTrack}; let mut parsed_tracks = HashMap::new(); diff --git a/jason/src/peer/transceiver.rs b/jason/src/peer/transceiver.rs index 9ac4a12b4..b96c4a4c6 100644 --- a/jason/src/peer/transceiver.rs +++ b/jason/src/peer/transceiver.rs @@ -8,13 +8,13 @@ use wasm_bindgen::JsValue; use wasm_bindgen_futures::JsFuture; use web_sys::{RtcRtpTransceiver, RtcRtpTransceiverDirection}; -use crate::media::{MediaStreamTrack, LocalMediaTrack, Strong}; +use crate::media::track::local::{self, SharedPtr}; /// Wrapper around [`RtcRtpTransceiver`] which provides handy methods for /// direction changes. #[derive(Clone)] pub struct Transceiver { - send_track: RefCell>>, + send_track: RefCell>>, transceiver: RtcRtpTransceiver, } @@ -54,7 +54,7 @@ impl Transceiver { /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack pub async fn set_send_track( &self, - new_track: Option>, + new_track: Option>, ) -> Result<(), JsValue> { let sys_track = new_track.as_ref().map(AsRef::as_ref); JsFuture::from(self.transceiver.sender().replace_track(sys_track)) @@ -72,7 +72,7 @@ impl Transceiver { } /// Returns [`MediaStreamTrack`] that is being send to remote, if any. - pub fn send_track(&self) -> Option> { + pub fn send_track(&self) -> Option> { self.send_track.borrow().clone() } diff --git a/jason/tests/api/connection.rs b/jason/tests/api/connection.rs index b00075359..f759cd876 100644 --- a/jason/tests/api/connection.rs +++ b/jason/tests/api/connection.rs @@ -7,7 +7,7 @@ use futures::{ use medea_client_api_proto::PeerId; use medea_jason::{ api::{ConnectionHandle, Connections}, - media::{MediaKind, MediaStreamTrack}, + media::{track::remote, MediaKind}, }; use wasm_bindgen::{closure::Closure, JsValue}; use wasm_bindgen_test::*; @@ -44,7 +44,7 @@ async fn on_remote_track_added_fires() { let con = cons.get(&"bob".into()).unwrap(); let con_handle = con.new_handle(); - let (cb, test_result) = js_callback!(|track: MediaStreamTrack| { + let (cb, test_result) = js_callback!(|track: remote::Track| { cb_assert_eq!(track.kind(), MediaKind::Video); }); con_handle.on_remote_track_added(cb.into()).unwrap(); @@ -64,7 +64,7 @@ async fn tracks_are_added_to_connection() { let con_handle = con.new_handle(); let (tx, rx) = oneshot::channel(); - let closure = Closure::once_into_js(move |track: MediaStreamTrack| { + let closure = Closure::once_into_js(move |track: remote::Track| { assert!(tx.send(track).is_ok()); }); con_handle.on_remote_track_added(closure.into()).unwrap(); @@ -74,7 +74,7 @@ async fn tracks_are_added_to_connection() { assert_eq!(video_track.kind(), MediaKind::Video); let (tx, rx) = oneshot::channel(); - let closure = Closure::once_into_js(move |track: MediaStreamTrack| { + let closure = Closure::once_into_js(move |track: remote::Track| { assert!(tx.send(track).is_ok()); }); con_handle.on_remote_track_added(closure.into()).unwrap(); diff --git a/jason/tests/media/constraints.rs b/jason/tests/media/constraints.rs index 8ab823aba..422f1d67e 100644 --- a/jason/tests/media/constraints.rs +++ b/jason/tests/media/constraints.rs @@ -3,9 +3,9 @@ use medea_client_api_proto::{MediaSourceKind, VideoSettings}; use medea_jason::{ media::{ - AudioTrackConstraints, DeviceVideoTrackConstraints, JsMediaSourceKind, - MediaKind, MediaManager, MediaStreamSettings, - MultiSourceTracksConstraints, VideoSource, + AudioTrackConstraints, DeviceVideoTrackConstraints, MediaKind, + MediaManager, MediaStreamSettings, MultiSourceTracksConstraints, + VideoSource, }, utils::{get_property_by_name, window}, DisplayVideoTrackConstraints, @@ -152,7 +152,7 @@ async fn equal_constraints_produce_equal_streams() { .find(|(track, _)| track.kind() == MediaKind::Audio) .unwrap() .0; - assert_eq!(audio_track.root_id(), some_audio_track.root_id()); + assert_eq!(audio_track.id(), some_audio_track.id()); let video_track = &tracks .iter() @@ -164,7 +164,7 @@ async fn equal_constraints_produce_equal_streams() { .find(|(track, _)| track.kind() == MediaKind::Video) .unwrap() .0; - assert_eq!(video_track.root_id(), some_video_track.root_id()); + assert_eq!(video_track.id(), some_video_track.id()); } /// 1. If audio_devices.len() > 1 (otherwise this test makes no sense); @@ -199,7 +199,7 @@ async fn different_constraints_produce_different_streams() { .find(|(track, _)| track.kind() == MediaKind::Audio) .unwrap() .0; - assert_ne!(audio_track.root_id(), another_audio_track.root_id()); + assert_ne!(audio_track.id(), another_audio_track.id()); } } @@ -535,16 +535,10 @@ async fn simultaneous_device_and_display() { let display_video_track = video.pop().unwrap().0; assert_eq!(display_video_track.kind(), MediaKind::Video); assert!(display_video_constraints.satisfies(display_video_track.as_ref())); - assert_eq!( - display_video_track.js_media_source_kind(), - JsMediaSourceKind::Display - ); + assert_eq!(display_video_track.source_kind(), MediaSourceKind::Display); let device_video_track = video.pop().unwrap().0; assert_eq!(device_video_track.kind(), MediaKind::Video); assert!(device_video_constraints.satisfies(device_video_track.as_ref())); - assert_eq!( - device_video_track.js_media_source_kind(), - JsMediaSourceKind::Device - ); + assert_eq!(device_video_track.source_kind(), MediaSourceKind::Device); } diff --git a/jason/tests/media/manager.rs b/jason/tests/media/manager.rs index 3f8c045a0..04226b213 100644 --- a/jason/tests/media/manager.rs +++ b/jason/tests/media/manager.rs @@ -147,7 +147,7 @@ async fn same_track_for_same_constraints() { let (track2, track2_is_new) = tracks.pop().unwrap(); assert!(!track2_is_new); - assert_eq!(track1.root_id(), track2.root_id()); + assert_eq!(track1.id(), track2.id()); assert_eq!(track2.kind(), MediaKind::Audio); assert_eq!(mock_navigator.get_user_media_requests_count(), 1); } @@ -180,7 +180,7 @@ async fn new_track_if_previous_dropped() { assert_eq!(mock_navigator.get_user_media_requests_count(), 1); // now drop track, and we got new track and second getUserMedia request - let track1_id = track1.root_id(); + let track1_id = track1.id(); drop(track1); let mut tracks = media_manager.get_tracks(constraints).await.unwrap(); @@ -188,7 +188,7 @@ async fn new_track_if_previous_dropped() { let (track2, track2_is_new) = tracks.pop().unwrap(); assert!(track2_is_new); - assert_ne!(track2.root_id(), track1_id); + assert_ne!(track2.id(), track1_id); assert_eq!(track2.kind(), MediaKind::Audio); assert_eq!(mock_navigator.get_user_media_requests_count(), 2); @@ -246,8 +246,8 @@ async fn request_audio_video_then_audio_then_video() { let (video_track2, video_track2_is_new) = tracks.pop().unwrap(); assert!(!video_track2_is_new); - assert_eq!(audio_track.root_id(), audio_track2.root_id()); - assert_eq!(video_track.root_id(), video_track2.root_id()); + assert_eq!(audio_track.id(), audio_track2.id()); + assert_eq!(video_track.id(), video_track2.id()); assert_eq!(mock_navigator.get_user_media_requests_count(), 1); mock_navigator.stop(); } @@ -295,7 +295,7 @@ async fn display_track_is_cached() { let (video_track2, video_track2_is_new) = tracks.pop().unwrap(); assert!(!video_track2_is_new); - assert_eq!(video_track.root_id(), video_track2.root_id()); + assert_eq!(video_track.id(), video_track2.id()); assert_eq!(mock_navigator.get_display_media_requests_count(), 1); assert_eq!(mock_navigator.get_user_media_requests_count(), 1); diff --git a/jason/tests/web.rs b/jason/tests/web.rs index e1eeb627b..10aa6af8a 100644 --- a/jason/tests/web.rs +++ b/jason/tests/web.rs @@ -87,9 +87,7 @@ use medea_client_api_proto::{ TrackId, VideoSettings, }; use medea_jason::{ - media::{ - LocalTracksConstraints, MediaKind, MediaManager, MediaStreamTrack, - }, + media::{track::remote, LocalTracksConstraints, MediaKind, MediaManager}, peer::media_exchange_state, rpc::ApiUrl, utils::{window, JasonError}, @@ -286,20 +284,22 @@ async fn wait_and_check_test_result( }; } -async fn get_video_track() -> MediaStreamTrack { +async fn get_video_track() -> remote::Track { let manager = MediaManager::default(); let mut settings = MediaStreamSettings::new(); settings.device_video(DeviceVideoTrackConstraints::new()); let stream = manager.get_tracks(settings).await.unwrap(); - stream.into_iter().next().unwrap().0 + let track = Clone::clone(stream.into_iter().next().unwrap().0.as_ref()); + remote::Track::new(track, MediaSourceKind::Device) } -async fn get_audio_track() -> MediaStreamTrack { +async fn get_audio_track() -> remote::Track { let manager = MediaManager::default(); let mut settings = MediaStreamSettings::new(); settings.audio(AudioTrackConstraints::new()); let stream = manager.get_tracks(settings).await.unwrap(); - stream.into_iter().next().unwrap().0 + let track = Clone::clone(stream.into_iter().next().unwrap().0.as_ref()); + remote::Track::new(track, MediaSourceKind::Device) } /// Awaits provided [`LocalBoxFuture`] for `timeout` milliseconds. If within From 33bd1a26065486cb90fc50dea633538bd10b4b2b Mon Sep 17 00:00:00 2001 From: alexlapa Date: Thu, 19 Nov 2020 12:06:18 +0200 Subject: [PATCH 33/44] refactor --- jason/src/lib.rs | 1 + jason/src/media/track.rs | 378 -------------------------------- jason/src/media/track/local.rs | 163 ++++++++++++++ jason/src/media/track/mod.rs | 38 ++++ jason/src/media/track/remote.rs | 173 +++++++++++++++ 5 files changed, 375 insertions(+), 378 deletions(-) delete mode 100644 jason/src/media/track.rs create mode 100644 jason/src/media/track/local.rs create mode 100644 jason/src/media/track/mod.rs create mode 100644 jason/src/media/track/remote.rs diff --git a/jason/src/lib.rs b/jason/src/lib.rs index d59c34eec..18814d10c 100644 --- a/jason/src/lib.rs +++ b/jason/src/lib.rs @@ -29,6 +29,7 @@ pub use console_error_panic_hook::set_once as set_panic_hook; pub use self::{ api::{ConnectionHandle, Jason, RoomHandle}, media::{ + track::{local::JsTrack, remote::Track}, AudioTrackConstraints, DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, FacingMode, JsMediaSourceKind, MediaKind, MediaStreamSettings, diff --git a/jason/src/media/track.rs b/jason/src/media/track.rs deleted file mode 100644 index 6d82cd644..000000000 --- a/jason/src/media/track.rs +++ /dev/null @@ -1,378 +0,0 @@ -//! [MediaStreamTrack][1] related objects. -//! -//! [1]: https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack - -use medea_client_api_proto::MediaSourceKind; -use wasm_bindgen::prelude::*; - -/// Media source type. -#[wasm_bindgen(js_name = MediaSourceKind)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum JsMediaSourceKind { - /// Media is sourced from some media device (webcam or microphone). - Device, - - /// Media is obtained with screen-capture. - Display, -} - -impl From for MediaSourceKind { - fn from(val: JsMediaSourceKind) -> Self { - match val { - JsMediaSourceKind::Device => Self::Device, - JsMediaSourceKind::Display => Self::Display, - } - } -} - -impl From for JsMediaSourceKind { - fn from(val: MediaSourceKind) -> Self { - match val { - MediaSourceKind::Device => Self::Device, - MediaSourceKind::Display => Self::Display, - } - } -} - -pub mod local { - - use std::rc::{Rc, Weak}; - - use derive_more::AsRef; - use medea_client_api_proto::MediaSourceKind; - use wasm_bindgen::prelude::*; - use web_sys::MediaStreamTrack as SysMediaStreamTrack; - - use crate::{media::MediaKind, JsMediaSourceKind}; - - #[derive(Clone, Debug)] - pub struct Track { - source_kind: MediaSourceKind, - kind: MediaKind, - track: S, - } - - #[derive(Clone, Debug)] - pub struct WeakPtr(Weak); - - #[derive(Clone, Debug)] - pub struct SharedPtr(Rc); - - impl Track { - /// Checks whether this weak reference can be upgraded to a strong one. - #[inline] - pub fn can_be_upgraded(&self) -> bool { - self.track.0.strong_count() > 0 - } - - pub fn upgrade(&self) -> Option> { - Some(Track { - track: SharedPtr(Weak::upgrade(&self.track.0)?), - kind: self.kind, - source_kind: self.source_kind, - }) - } - } - - impl AsRef for Track { - fn as_ref(&self) -> &SysMediaStreamTrack { - self.track.0.as_ref().as_ref() - } - } - - impl Track { - pub fn new( - track: SysMediaStreamTrack, - source_kind: MediaSourceKind, - ) -> Self { - let kind = match track.kind().as_ref() { - "audio" => MediaKind::Audio, - "video" => MediaKind::Video, - _ => unreachable!(), - }; - Self { - track: SharedPtr(InnerTrack::new(track)), - source_kind, - kind, - } - } - - pub fn set_enabled(&self, enabled: bool) { - self.track.0.as_ref().as_ref().set_enabled(enabled); - } - - pub fn id(&self) -> String { - self.track.0.id() - } - - pub fn source_kind(&self) -> MediaSourceKind { - self.source_kind - } - - pub fn kind(&self) -> MediaKind { - self.kind - } - - pub fn fork(&self) -> Self { - Self { - track: SharedPtr(self.track.0.fork()), - source_kind: self.source_kind, - kind: self.kind, - } - } - - pub fn downgrade(&self) -> Track { - Track { - track: WeakPtr(Rc::downgrade(&self.track.0)), - kind: self.kind, - source_kind: self.source_kind, - } - } - } - - #[derive(AsRef, Clone, Debug)] - struct InnerTrack { - parent: Option>, - #[as_ref] - track: SysMediaStreamTrack, - } - - impl InnerTrack { - fn new(track: SysMediaStreamTrack) -> Rc { - Rc::new(Self { - parent: None, - track, - }) - } - - fn id(&self) -> String { - self.track.id() - } - - fn fork(self: &Rc) -> Rc { - let parent = Rc::clone(self); - let track = SysMediaStreamTrack::clone(&self.track); - Rc::new(Self { - parent: Some(parent), - track, - }) - } - } - - impl Drop for InnerTrack { - fn drop(&mut self) { - self.track.stop(); - } - } - - #[wasm_bindgen(js_name = LocalMediaTrack)] - pub struct JsTrack(Track); - - impl JsTrack { - pub fn new(track: Track) -> Self { - JsTrack(track) - } - } - - #[wasm_bindgen(js_class = LocalMediaTrack)] - impl JsTrack { - /// Returns underlying [`SysMediaStreamTrack`] from this - /// [`MediaStreamTrack`]. - pub fn get_track(&self) -> SysMediaStreamTrack { - Clone::clone(self.0.as_ref()) - } - - /// Returns a [`String`] set to `audio` if the track is an audio track - /// and to `video`, if it is a video track. - #[wasm_bindgen(js_name = kind)] - pub fn js_kind(&self) -> MediaKind { - self.0.kind() - } - - /// Returns a [`String`] set to `device` if track is sourced from some - /// device (webcam/microphone) and to `display`, if track is captured - /// via [MediaDevices.getDisplayMedia()][1]. - /// - /// [1]: https://tinyurl.com/y2anfntz - #[wasm_bindgen(js_name = media_source_kind)] - pub fn js_media_source_kind(&self) -> JsMediaSourceKind { - self.0.source_kind().into() - } - } -} - -pub mod remote { - use std::rc::Rc; - - use futures::StreamExt; - use medea_client_api_proto::MediaSourceKind; - use medea_reactive::ObservableCell; - use wasm_bindgen::prelude::*; - use wasm_bindgen_futures::spawn_local; - use web_sys::MediaStreamTrack as SysMediaStreamTrack; - - use crate::{media::MediaKind, utils::Callback0, JsMediaSourceKind}; - - /// Wrapper around [`SysMediaStreamTrack`] to track when it's enabled or - /// disabled. - struct Inner { - /// Underlying JS-side [`SysMediaStreamTrack`]. - track: SysMediaStreamTrack, - - /// Underlying [`SysMediaStreamTrack`] kind. - kind: MediaKind, - - /// Underlying [`SysMediaStreamTrack`] source kind. - media_source_kind: MediaSourceKind, - - /// Callback to be invoked when this [`MediaStreamTrack`] is enabled. - on_enabled: Callback0, - - /// Callback to be invoked when this [`MediaStreamTrack`] is disabled. - on_disabled: Callback0, - - /// [enabled] property of [MediaStreamTrack][1]. - /// - /// [enabled]: https://tinyurl.com/y5byqdea - /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack - enabled: ObservableCell, - } - - /// Strong reference to [MediaStreamTrack][1]. - /// - /// Track will be automatically stopped when there are no strong references - /// left. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack - #[wasm_bindgen(js_name = RemoteMediaTrack)] - #[derive(Clone)] - pub struct Track(Rc); - - impl Track { - /// Creates new [`Track`], spawns listener for - /// [`Inner::enabled`] state changes. - pub fn new(track: T, media_source_kind: MediaSourceKind) -> Self - where - SysMediaStreamTrack: From, - { - let track = SysMediaStreamTrack::from(track); - let kind = match track.kind().as_ref() { - "audio" => MediaKind::Audio, - "video" => MediaKind::Video, - _ => unreachable!(), - }; - - let track = Track(Rc::new(Inner { - enabled: ObservableCell::new(track.enabled()), - on_enabled: Callback0::default(), - on_disabled: Callback0::default(), - media_source_kind, - kind, - track, - })); - - let mut track_enabled_state_changes = - track.enabled().subscribe().skip(1); - spawn_local({ - let weak_inner = Rc::downgrade(&track.0); - async move { - while let Some(enabled) = - track_enabled_state_changes.next().await - { - if let Some(track) = weak_inner.upgrade() { - if enabled { - track.on_enabled.call(); - } else { - track.on_disabled.call(); - } - } else { - break; - } - } - } - }); - - track - } - - /// Returns `true` if this [`Track`] is enabled. - #[inline] - pub fn enabled(&self) -> &ObservableCell { - &self.0.enabled - } - - /// Sets [`Track::enabled`] to the provided value. - /// - /// Updates `enabled` in the underlying [`SysMediaStreamTrack`]. - #[inline] - pub fn set_enabled(&self, enabled: bool) { - self.0.enabled.set(enabled); - self.0.track.set_enabled(enabled); - } - - /// Returns [`id`][1] of underlying [MediaStreamTrack][2]. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id - /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - #[inline] - pub fn id(&self) -> String { - self.0.track.id() - } - - /// Returns track kind (audio/video). - #[inline] - pub fn kind(&self) -> MediaKind { - self.0.kind - } - - /// Returns this [`Track`] media source kind. - #[inline] - pub fn media_source_kind(&self) -> MediaSourceKind { - self.0.media_source_kind - } - } - - #[wasm_bindgen(js_class = RemoteMediaTrack)] - impl Track { - /// Returns underlying [`SysMediaStreamTrack`] from this - /// [`Track`]. - pub fn get_track(&self) -> SysMediaStreamTrack { - Clone::clone(&self.0.track) - } - - /// Returns is this [`Track`] enabled. - #[wasm_bindgen(js_name = enabled)] - pub fn js_enabled(&self) -> bool { - self.0.enabled.get() - } - - /// Sets callback, which will be invoked when this [`Track`] - /// is enabled. - pub fn on_enabled(&self, callback: js_sys::Function) { - self.0.on_enabled.set_func(callback); - } - - /// Sets callback, which will be invoked when this [`Track`] - /// is enabled. - pub fn on_disabled(&self, callback: js_sys::Function) { - self.0.on_disabled.set_func(callback); - } - - /// Returns a [`String`] set to `audio` if the track is an audio track - /// and to `video`, if it is a video track. - #[wasm_bindgen(js_name = kind)] - pub fn js_kind(&self) -> MediaKind { - self.kind() - } - - /// Returns a [`String`] set to `device` if track is sourced from some - /// device (webcam/microphone) and to `display`, if track is captured - /// via [MediaDevices.getDisplayMedia()][1]. - /// - /// [1]: https://tinyurl.com/y2anfntz - #[wasm_bindgen(js_name = media_source_kind)] - pub fn js_media_source_kind(&self) -> JsMediaSourceKind { - self.0.media_source_kind.into() - } - } -} diff --git a/jason/src/media/track/local.rs b/jason/src/media/track/local.rs new file mode 100644 index 000000000..d3f15d770 --- /dev/null +++ b/jason/src/media/track/local.rs @@ -0,0 +1,163 @@ +use std::rc::{Rc, Weak}; + +use derive_more::AsRef; +use medea_client_api_proto::MediaSourceKind; +use wasm_bindgen::prelude::*; +use web_sys::MediaStreamTrack as SysMediaStreamTrack; + +use crate::{media::MediaKind, JsMediaSourceKind}; + +#[derive(Clone, Debug)] +pub struct Track { + source_kind: MediaSourceKind, + kind: MediaKind, + track: S, +} + +#[derive(Clone, Debug)] +pub struct WeakPtr(Weak); + +#[derive(Clone, Debug)] +pub struct SharedPtr(Rc); + +impl Track { + /// Checks whether this weak reference can be upgraded to a strong one. + #[inline] + pub fn can_be_upgraded(&self) -> bool { + self.track.0.strong_count() > 0 + } + + pub fn upgrade(&self) -> Option> { + Some(Track { + track: SharedPtr(Weak::upgrade(&self.track.0)?), + kind: self.kind, + source_kind: self.source_kind, + }) + } +} + +impl AsRef for Track { + fn as_ref(&self) -> &SysMediaStreamTrack { + self.track.0.as_ref().as_ref() + } +} + +impl Track { + pub fn new( + track: SysMediaStreamTrack, + source_kind: MediaSourceKind, + ) -> Self { + let kind = match track.kind().as_ref() { + "audio" => MediaKind::Audio, + "video" => MediaKind::Video, + _ => unreachable!(), + }; + Self { + track: SharedPtr(InnerTrack::new(track)), + source_kind, + kind, + } + } + + pub fn set_enabled(&self, enabled: bool) { + self.track.0.as_ref().as_ref().set_enabled(enabled); + } + + pub fn id(&self) -> String { + self.track.0.id() + } + + pub fn source_kind(&self) -> MediaSourceKind { + self.source_kind + } + + pub fn kind(&self) -> MediaKind { + self.kind + } + + pub fn fork(&self) -> Self { + Self { + track: SharedPtr(self.track.0.fork()), + source_kind: self.source_kind, + kind: self.kind, + } + } + + pub fn downgrade(&self) -> Track { + Track { + track: WeakPtr(Rc::downgrade(&self.track.0)), + kind: self.kind, + source_kind: self.source_kind, + } + } +} + +#[derive(AsRef, Clone, Debug)] +struct InnerTrack { + parent: Option>, + #[as_ref] + track: SysMediaStreamTrack, +} + +impl InnerTrack { + fn new(track: SysMediaStreamTrack) -> Rc { + Rc::new(Self { + parent: None, + track, + }) + } + + fn id(&self) -> String { + self.track.id() + } + + fn fork(self: &Rc) -> Rc { + let parent = Rc::clone(self); + let track = SysMediaStreamTrack::clone(&self.track); + Rc::new(Self { + parent: Some(parent), + track, + }) + } +} + +impl Drop for InnerTrack { + fn drop(&mut self) { + self.track.stop(); + } +} + +#[wasm_bindgen(js_name = LocalMediaTrack)] +pub struct JsTrack(Track); + +impl JsTrack { + pub fn new(track: Track) -> Self { + JsTrack(track) + } +} + +#[wasm_bindgen(js_class = LocalMediaTrack)] +impl JsTrack { + /// Returns underlying [`SysMediaStreamTrack`] from this + /// [`MediaStreamTrack`]. + pub fn get_track(&self) -> SysMediaStreamTrack { + Clone::clone(self.0.as_ref()) + } + + /// Returns a [`String`] set to `audio` if the track is an audio track + /// and to `video`, if it is a video track. + #[wasm_bindgen(js_name = kind)] + pub fn js_kind(&self) -> MediaKind { + self.0.kind() + } + + /// Returns a [`String`] set to `device` if track is sourced from some + /// device (webcam/microphone) and to `display`, if track is captured + /// via [MediaDevices.getDisplayMedia()][1]. + /// + /// [1]: https://tinyurl.com/y2anfntz + #[wasm_bindgen(js_name = media_source_kind)] + pub fn js_media_source_kind(&self) -> JsMediaSourceKind { + self.0.source_kind().into() + } +} diff --git a/jason/src/media/track/mod.rs b/jason/src/media/track/mod.rs new file mode 100644 index 000000000..212a2c369 --- /dev/null +++ b/jason/src/media/track/mod.rs @@ -0,0 +1,38 @@ +//! [MediaStreamTrack][1] related objects. +//! +//! [1]: https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack + +pub mod local; +pub mod remote; + +use medea_client_api_proto::MediaSourceKind; +use wasm_bindgen::prelude::*; + +/// Media source type. +#[wasm_bindgen(js_name = MediaSourceKind)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum JsMediaSourceKind { + /// Media is sourced from some media device (webcam or microphone). + Device, + + /// Media is obtained with screen-capture. + Display, +} + +impl From for MediaSourceKind { + fn from(val: JsMediaSourceKind) -> Self { + match val { + JsMediaSourceKind::Device => Self::Device, + JsMediaSourceKind::Display => Self::Display, + } + } +} + +impl From for JsMediaSourceKind { + fn from(val: MediaSourceKind) -> Self { + match val { + MediaSourceKind::Device => Self::Device, + MediaSourceKind::Display => Self::Display, + } + } +} diff --git a/jason/src/media/track/remote.rs b/jason/src/media/track/remote.rs new file mode 100644 index 000000000..d0a98dc43 --- /dev/null +++ b/jason/src/media/track/remote.rs @@ -0,0 +1,173 @@ +use std::rc::Rc; + +use futures::StreamExt; +use medea_client_api_proto::MediaSourceKind; +use medea_reactive::ObservableCell; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::spawn_local; +use web_sys::MediaStreamTrack as SysMediaStreamTrack; + +use crate::{media::MediaKind, utils::Callback0, JsMediaSourceKind}; + +/// Wrapper around [`SysMediaStreamTrack`] to track when it's enabled or +/// disabled. +struct Inner { + /// Underlying JS-side [`SysMediaStreamTrack`]. + track: SysMediaStreamTrack, + + /// Underlying [`SysMediaStreamTrack`] kind. + kind: MediaKind, + + /// Underlying [`SysMediaStreamTrack`] source kind. + media_source_kind: MediaSourceKind, + + /// Callback to be invoked when this [`MediaStreamTrack`] is enabled. + on_enabled: Callback0, + + /// Callback to be invoked when this [`MediaStreamTrack`] is disabled. + on_disabled: Callback0, + + /// [enabled] property of [MediaStreamTrack][1]. + /// + /// [enabled]: https://tinyurl.com/y5byqdea + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack + enabled: ObservableCell, +} + +/// Strong reference to [MediaStreamTrack][1]. +/// +/// Track will be automatically stopped when there are no strong references +/// left. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack +#[wasm_bindgen(js_name = RemoteMediaTrack)] +#[derive(Clone)] +pub struct Track(Rc); + +impl Track { + /// Creates new [`Track`], spawns listener for + /// [`Inner::enabled`] state changes. + pub fn new(track: T, media_source_kind: MediaSourceKind) -> Self + where + SysMediaStreamTrack: From, + { + let track = SysMediaStreamTrack::from(track); + let kind = match track.kind().as_ref() { + "audio" => MediaKind::Audio, + "video" => MediaKind::Video, + _ => unreachable!(), + }; + + let track = Track(Rc::new(Inner { + enabled: ObservableCell::new(track.enabled()), + on_enabled: Callback0::default(), + on_disabled: Callback0::default(), + media_source_kind, + kind, + track, + })); + + let mut track_enabled_state_changes = + track.enabled().subscribe().skip(1); + spawn_local({ + let weak_inner = Rc::downgrade(&track.0); + async move { + while let Some(enabled) = + track_enabled_state_changes.next().await + { + if let Some(track) = weak_inner.upgrade() { + if enabled { + track.on_enabled.call(); + } else { + track.on_disabled.call(); + } + } else { + break; + } + } + } + }); + + track + } + + /// Returns `true` if this [`Track`] is enabled. + #[inline] + pub fn enabled(&self) -> &ObservableCell { + &self.0.enabled + } + + /// Sets [`Track::enabled`] to the provided value. + /// + /// Updates `enabled` in the underlying [`SysMediaStreamTrack`]. + #[inline] + pub fn set_enabled(&self, enabled: bool) { + self.0.enabled.set(enabled); + self.0.track.set_enabled(enabled); + } + + /// Returns [`id`][1] of underlying [MediaStreamTrack][2]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] + pub fn id(&self) -> String { + self.0.track.id() + } + + /// Returns track kind (audio/video). + #[inline] + pub fn kind(&self) -> MediaKind { + self.0.kind + } + + /// Returns this [`Track`] media source kind. + #[inline] + pub fn media_source_kind(&self) -> MediaSourceKind { + self.0.media_source_kind + } +} + +#[wasm_bindgen(js_class = RemoteMediaTrack)] +impl Track { + /// Returns underlying [`SysMediaStreamTrack`] from this + /// [`Track`]. + pub fn get_track(&self) -> SysMediaStreamTrack { + Clone::clone(&self.0.track) + } + + /// Returns is this [`Track`] enabled. + #[wasm_bindgen(js_name = enabled)] + pub fn js_enabled(&self) -> bool { + self.0.enabled.get() + } + + /// Sets callback, which will be invoked when this [`Track`] + /// is enabled. + pub fn on_enabled(&self, callback: js_sys::Function) { + self.0.on_enabled.set_func(callback); + } + + /// Sets callback, which will be invoked when this [`Track`] + /// is enabled. + pub fn on_disabled(&self, callback: js_sys::Function) { + self.0.on_disabled.set_func(callback); + } + + /// Returns a [`String`] set to `audio` if the track is an audio track + /// and to `video`, if it is a video track. + #[wasm_bindgen(js_name = kind)] + pub fn js_kind(&self) -> MediaKind { + self.kind() + } + + /// Returns a [`String`] set to `device` if track is sourced from some + /// device (webcam/microphone) and to `display`, if track is captured + /// via [MediaDevices.getDisplayMedia()][1]. + /// + /// [1]: https://tinyurl.com/y2anfntz + #[wasm_bindgen(js_name = media_source_kind)] + pub fn js_media_source_kind(&self) -> JsMediaSourceKind { + self.0.media_source_kind.into() + } +} From 29fe375eab10d5b7b2d11d511346a7539d5f71de Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 19 Nov 2020 14:17:21 +0300 Subject: [PATCH 34/44] Add docs --- jason/src/media/track/local.rs | 110 ++++++++++++++++++++++++++------ jason/src/media/track/remote.rs | 10 +-- 2 files changed, 96 insertions(+), 24 deletions(-) diff --git a/jason/src/media/track/local.rs b/jason/src/media/track/local.rs index d3f15d770..bf9dbf33d 100644 --- a/jason/src/media/track/local.rs +++ b/jason/src/media/track/local.rs @@ -1,3 +1,6 @@ +//! Implementation of the wrappers around [`SysMediaStreamTrack`] received from +//! the gUM/gDM request. + use std::rc::{Rc, Weak}; use derive_more::AsRef; @@ -7,19 +10,32 @@ use web_sys::MediaStreamTrack as SysMediaStreamTrack; use crate::{media::MediaKind, JsMediaSourceKind}; +/// [`Weak`] reference to the [`InnerTrack`]. +#[derive(Clone, Debug)] +pub struct WeakPtr(Weak); + +/// [`Rc`] reference to the [`InnerTrack`]. +#[derive(Clone, Debug)] +pub struct SharedPtr(Rc); + +/// Wrapper around [`SysMediaStreamTrack`] received from the gUM/gDM request. +/// +/// Can be forked by calling [`Track::fork`]. +/// +/// This [`Track`] will be stopped when all references to this [`Track`] and +/// forked [`Track`]s will be dropped. #[derive(Clone, Debug)] pub struct Track { + /// Underlying [`SysMediaStreamTrack`] source kind. source_kind: MediaSourceKind, + + /// Underlying [`SysMediaStreamTrack`] kind. kind: MediaKind, + + /// Actual reference to the [`SysMediaStreamTrack`]. track: S, } -#[derive(Clone, Debug)] -pub struct WeakPtr(Weak); - -#[derive(Clone, Debug)] -pub struct SharedPtr(Rc); - impl Track { /// Checks whether this weak reference can be upgraded to a strong one. #[inline] @@ -27,6 +43,10 @@ impl Track { self.track.0.strong_count() > 0 } + /// Upgrades [`Weak`] referenced [`Track`] to the [`Rc`] referenced + /// [`Track`]. + /// + /// Returns [`None`] if [`Weak`] reference can't be upgraded. pub fn upgrade(&self) -> Option> { Some(Track { track: SharedPtr(Weak::upgrade(&self.track.0)?), @@ -36,13 +56,8 @@ impl Track { } } -impl AsRef for Track { - fn as_ref(&self) -> &SysMediaStreamTrack { - self.track.0.as_ref().as_ref() - } -} - impl Track { + /// Returns new [`Rc`] referenced [`Track`]. pub fn new( track: SysMediaStreamTrack, source_kind: MediaSourceKind, @@ -59,22 +74,38 @@ impl Track { } } + /// Sets [`SysMediaStreamTrack`] `enabled` field to the provided one. pub fn set_enabled(&self, enabled: bool) { self.track.0.as_ref().as_ref().set_enabled(enabled); } + /// Returns [`id`][1] of underlying [MediaStreamTrack][2]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn id(&self) -> String { self.track.0.id() } + /// Returns this [`Track`] media source kind. pub fn source_kind(&self) -> MediaSourceKind { self.source_kind } + /// Returns track kind (audio/video). pub fn kind(&self) -> MediaKind { self.kind } + /// Returns fork of this [`Track`]. + /// + /// Returned [`Track`] is identical except for its unique id. + /// + /// Forked [`Track`] will hold reference to it's parent, so this [`Track`] + /// can't be dropped until all his forked [`Track`]s will be dropped. + /// + /// You can change properties of the forked [`Track`] without affecting the + /// original one. pub fn fork(&self) -> Self { Self { track: SharedPtr(self.track.0.fork()), @@ -83,6 +114,8 @@ impl Track { } } + /// Downgrades [`Rc`] referenced [`Track`] to the [`Weak`] referenced + /// [`Track`]. pub fn downgrade(&self) -> Track { Track { track: WeakPtr(Rc::downgrade(&self.track.0)), @@ -92,30 +125,69 @@ impl Track { } } +impl AsRef for Track { + fn as_ref(&self) -> &SysMediaStreamTrack { + self.track.0.as_ref().as_ref() + } +} + +/// Actual [`SysMediaStreamTrack`] with a strong reference to the it's parent +/// [`InnerTrack`]. +/// +/// When this [`InnerTrack`] is dropped - [`SysMediaStreamTrack::stop`] will be +/// performed. +/// +/// Note that all childs of this [`InnerTrack`] will hold strong reference to +/// this [`InnerTrack`], so it can be dropped only when all it's childs was +/// dropped. #[derive(AsRef, Clone, Debug)] struct InnerTrack { - parent: Option>, + /// Reference to the parent [`InnerTrack`]. + /// + /// Parent will be [`None`] if this [`InnerTrack`] wasn't forked from + /// another [`InnerTrack`]. + /// + /// This field used only for holding strong reference to the parent. + _parent: Option>, + + /// Actual [`SysMediaStreamTrack`]. #[as_ref] track: SysMediaStreamTrack, } impl InnerTrack { + /// Returns new root [`InnerTrack`] with a provided [`SysMediaStreamTrack`] + /// as underlying track. fn new(track: SysMediaStreamTrack) -> Rc { Rc::new(Self { - parent: None, + _parent: None, track, }) } + /// Returns [`id`][1] of underlying [MediaStreamTrack][2]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack fn id(&self) -> String { self.track.id() } + /// Returns fork of this [`InnerTrack`]. + /// + /// Returned [`InnerTrack`] is identical except for its unique id. + /// + /// Forked [`InnerTrack`] will hold reference to it's parent, so this + /// [`InnerTrack`] can't be dropped until all his forked [`InnerTrack`]s + /// will be dropped. + /// + /// You can change properties of the forked [`InnerTrack`] without affecting + /// the original one. fn fork(self: &Rc) -> Rc { let parent = Rc::clone(self); let track = SysMediaStreamTrack::clone(&self.track); Rc::new(Self { - parent: Some(parent), + _parent: Some(parent), track, }) } @@ -127,10 +199,12 @@ impl Drop for InnerTrack { } } +/// Wrapper around strongly referenced [`Track`] for the JS side. #[wasm_bindgen(js_name = LocalMediaTrack)] pub struct JsTrack(Track); impl JsTrack { + /// Wraps provided [`Track`] to the [`JsTrack`]. pub fn new(track: Track) -> Self { JsTrack(track) } @@ -146,8 +220,7 @@ impl JsTrack { /// Returns a [`String`] set to `audio` if the track is an audio track /// and to `video`, if it is a video track. - #[wasm_bindgen(js_name = kind)] - pub fn js_kind(&self) -> MediaKind { + pub fn kind(&self) -> MediaKind { self.0.kind() } @@ -156,8 +229,7 @@ impl JsTrack { /// via [MediaDevices.getDisplayMedia()][1]. /// /// [1]: https://tinyurl.com/y2anfntz - #[wasm_bindgen(js_name = media_source_kind)] - pub fn js_media_source_kind(&self) -> JsMediaSourceKind { + pub fn media_source_kind(&self) -> JsMediaSourceKind { self.0.source_kind().into() } } diff --git a/jason/src/media/track/remote.rs b/jason/src/media/track/remote.rs index d0a98dc43..0031cf13d 100644 --- a/jason/src/media/track/remote.rs +++ b/jason/src/media/track/remote.rs @@ -1,3 +1,6 @@ +//! Implementation of the wrapper around [`SysMediaStreamTrack`] received from +//! the remote side. + use std::rc::Rc; use futures::StreamExt; @@ -9,8 +12,8 @@ use web_sys::MediaStreamTrack as SysMediaStreamTrack; use crate::{media::MediaKind, utils::Callback0, JsMediaSourceKind}; -/// Wrapper around [`SysMediaStreamTrack`] to track when it's enabled or -/// disabled. +/// Wrapper around [`SysMediaStreamTrack`] received from the remote side to +/// track when it's enabled or disabled. struct Inner { /// Underlying JS-side [`SysMediaStreamTrack`]. track: SysMediaStreamTrack, @@ -36,9 +39,6 @@ struct Inner { /// Strong reference to [MediaStreamTrack][1]. /// -/// Track will be automatically stopped when there are no strong references -/// left. -/// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack #[wasm_bindgen(js_name = RemoteMediaTrack)] #[derive(Clone)] From c44fca2608c5494fcec8c1bd7331eee844c2fdf4 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 19 Nov 2020 14:31:08 +0300 Subject: [PATCH 35/44] Upgrade chromedriver to 87.0 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f8525b700..571d8b2fb 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ DEMO_IMAGE_NAME := instrumentisto/medea-demo CONTROL_MOCK_IMAGE_NAME := instrumentisto/medea-control-api-mock RUST_VER := 1.47 -CHROME_VERSION := 86.0 +CHROME_VERSION := 87.0 FIREFOX_VERSION := 82.0.3 crate-dir = . From 262efa98c2fb358589b34ed350a12b885f86d578 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 19 Nov 2020 14:55:27 +0300 Subject: [PATCH 36/44] Fix outdated docs --- jason/src/api/connection.rs | 8 ++++---- jason/src/api/room.rs | 4 ++-- jason/src/media/manager.rs | 6 +++--- jason/src/media/track/remote.rs | 4 ++-- jason/src/peer/media/receiver.rs | 8 ++++---- jason/src/peer/media/sender.rs | 6 +++--- jason/src/peer/tracks_request.rs | 12 ++++++------ jason/src/peer/transceiver.rs | 4 ++-- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/jason/src/api/connection.rs b/jason/src/api/connection.rs index 86103a3ad..709f06b74 100644 --- a/jason/src/api/connection.rs +++ b/jason/src/api/connection.rs @@ -101,7 +101,7 @@ struct InnerConnection { /// Current [`ConnectionQualityScore`] of this [`Connection`]. quality_score: Cell>, - /// JS callback, that will be invoked when remote [`MediaStreamTrack`] is + /// JS callback, that will be invoked when [`remote::Track`] is /// received. on_remote_track_added: Callback1, @@ -125,8 +125,8 @@ impl ConnectionHandle { upgrade_or_detached!(self.0).map(|inner| inner.remote_id.0.clone()) } - /// Sets callback, which will be invoked when new remote - /// [`MediaStreamTrack`] will be added to this [`Connection`]. + /// Sets callback, which will be invoked when new [`remote::Track`] will be + /// added to this [`Connection`]. pub fn on_remote_track_added( &self, f: js_sys::Function, @@ -166,7 +166,7 @@ impl Connection { } /// Invokes [`InnerConnection::on_remote_track_added`] JS callback with the - /// provided [`MediaStreamTrack`]. + /// provided [`remote::Track`]. pub fn add_remote_track(&self, track: remote::Track) { self.0.on_remote_track_added.call(track); } diff --git a/jason/src/api/room.rs b/jason/src/api/room.rs index 69698a3c1..dc13d1a14 100644 --- a/jason/src/api/room.rs +++ b/jason/src/api/room.rs @@ -142,7 +142,7 @@ enum RoomError { #[display(fmt = "Remote stream from unknown member")] UnknownRemoteMember, - /// Returned if [`MediaStreamTrack`] update failed. + /// Returned if [`Sender`]/[`Receiver`] update failed. #[display(fmt = "Failed to update Track with {} ID.", _0)] FailedTrackPatch(TrackId), @@ -320,7 +320,7 @@ impl RoomHandle { upgrade_or_detached!(self.0).map(|inner| inner.on_close.set_func(f)) } - /// Sets callback, which will be invoked when new local [`MediaStreamTrack`] + /// Sets callback, which will be invoked when new [`local::Track`] /// will be added to this [`Room`]. /// This might happen in such cases: /// 1. Media server initiates media request. diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 5810cf94b..97e586934 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -1,4 +1,4 @@ -//! Acquiring and storing [`MediaStreamTrack`]s. +//! Acquiring and storing [`local:Track`]s. use std::{ cell::RefCell, @@ -78,7 +78,7 @@ type Result = std::result::Result>; /// for further reusage. /// /// [`MediaManager`] stores weak references to -/// [`MediaStreamTrack`]s, so if there are no strong references to some track, +/// [`local::Track`]s, so if there are no strong references to some track, /// then this track is stopped and deleted from [`MediaManager`]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia @@ -128,7 +128,7 @@ impl InnerMediaManager { .collect()) } - /// Obtains [`MediaStreamTrack`]s based on a provided + /// Obtains [`local::Track`]s based on a provided /// [`MediaStreamSettings`]. This can be the tracks that were acquired /// earlier, or new tracks, acquired via [getUserMedia()][1] or/and /// [getDisplayMedia()][2] requests. diff --git a/jason/src/media/track/remote.rs b/jason/src/media/track/remote.rs index 0031cf13d..7e0924b39 100644 --- a/jason/src/media/track/remote.rs +++ b/jason/src/media/track/remote.rs @@ -24,10 +24,10 @@ struct Inner { /// Underlying [`SysMediaStreamTrack`] source kind. media_source_kind: MediaSourceKind, - /// Callback to be invoked when this [`MediaStreamTrack`] is enabled. + /// Callback to be invoked when this [`remote::Track`] is enabled. on_enabled: Callback0, - /// Callback to be invoked when this [`MediaStreamTrack`] is disabled. + /// Callback to be invoked when this [`remote::Track`] is disabled. on_disabled: Callback0, /// [enabled] property of [MediaStreamTrack][1]. diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index 4813b6c1e..a7dfe6983 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -27,11 +27,11 @@ use super::{ TransceiverSide, }; -/// Representation of a remote [`MediaStreamTrack`] that is being received from +/// Representation of a remote [`remote::Track`] that is being received from /// some remote peer. It may have two states: `waiting` and `receiving`. /// /// We can save related [`RtcRtpTransceiver`] and the actual -/// [`MediaStreamTrack`] only when [`MediaStreamTrack`] data arrives. +/// [`remote::Track`] only when [`remote::Track`] data arrives. pub struct Receiver { track_id: TrackId, caps: TrackConstraints, @@ -48,14 +48,14 @@ pub struct Receiver { impl Receiver { /// Creates new [`RtcRtpTransceiver`] if provided `mid` is `None`, otherwise /// creates [`Receiver`] without [`RtcRtpTransceiver`]. It will be injected - /// when [`MediaStreamTrack`] arrives. + /// when [`remote::Track`] arrives. /// /// Created [`RtcRtpTransceiver`] direction is set to /// [`TransceiverDirection::Inactive`] if media receiving is disabled in /// provided [`RecvConstraints`]. /// /// `track` field in the created [`Receiver`] will be `None`, since - /// [`Receiver`] must be created before the actual [`MediaStreamTrack`] data + /// [`Receiver`] must be created before the actual [`remote::Track`] data /// arrives. pub fn new( media_connections: &MediaConnections, diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index a0944eb54..42b248967 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -81,7 +81,7 @@ impl<'a> SenderBuilder<'a> { } } -/// Representation of a local [`MediaStreamTrack`] that is being sent to some +/// Representation of a [`local::Track`] that is being sent to some /// remote peer. pub struct Sender { track_id: TrackId, @@ -136,7 +136,7 @@ impl Sender { } } - /// Inserts provided [`MediaStreamTrack`] into provided [`Sender`]s + /// Inserts provided [`local::Track`] into provided [`Sender`]s /// transceiver. No-op if provided track already being used by this /// [`Sender`]. pub(super) async fn insert_track( @@ -248,7 +248,7 @@ impl Sender { == media_exchange_state::Stable::Enabled } - /// Drops [`MediaStreamTrack`] used by this [`Sender`]. Sets track used by + /// Drops [`local::Track`] used by this [`Sender`]. Sets track used by /// sending side of inner transceiver to `None`. async fn remove_track(&self) { // cannot fail diff --git a/jason/src/peer/tracks_request.rs b/jason/src/peer/tracks_request.rs index 0b4a12f4a..8ff848134 100644 --- a/jason/src/peer/tracks_request.rs +++ b/jason/src/peer/tracks_request.rs @@ -19,7 +19,7 @@ use crate::{ }; /// Errors that may occur when validating [`TracksRequest`] or -/// parsing [`MediaStreamTrack`]s. +/// parsing [`local::Track`]s. #[derive(Clone, Debug, Display, JsCaused)] pub enum TracksRequestError { /// [`TracksRequest`] contains multiple [`AudioTrackConstraints`]. @@ -42,15 +42,15 @@ pub enum TracksRequestError { #[display(fmt = "SimpleTracksRequest should have at least one track")] NoTracks, - /// Provided multiple audio [`MediaStreamTrack`]s. + /// Provided multiple audio [`local::Track`]s. #[display(fmt = "provided multiple audio MediaStreamTracks")] ExpectedAudioTracks, - /// Provided multiple device video [`MediaStreamTrack`]s. + /// Provided multiple device video [`local::Track`]s. #[display(fmt = "provided multiple device video MediaStreamTracks")] ExpectedDeviceVideoTracks, - /// Provided multiple display video [`MediaStreamTrack`]s. + /// Provided multiple display video [`local::Track`]s. #[display(fmt = "provided multiple display video MediaStreamTracks")] ExpectedDisplayVideoTracks, @@ -118,8 +118,8 @@ pub struct SimpleTracksRequest { } impl SimpleTracksRequest { - /// Parses [`MediaStreamTrack`]s and returns [`HashMap`] with [`TrackId`]s - /// and [`MediaStreamTracks`]s. + /// Parses [`local::Track`]s and returns [`HashMap`] with [`TrackId`]s + /// and [`local::Track`]s. /// /// # Errors /// diff --git a/jason/src/peer/transceiver.rs b/jason/src/peer/transceiver.rs index b96c4a4c6..4fa0270b4 100644 --- a/jason/src/peer/transceiver.rs +++ b/jason/src/peer/transceiver.rs @@ -71,12 +71,12 @@ impl Transceiver { self.transceiver.mid() } - /// Returns [`MediaStreamTrack`] that is being send to remote, if any. + /// Returns [`local::Track`] that is being send to remote, if any. pub fn send_track(&self) -> Option> { self.send_track.borrow().clone() } - /// Sets underlying [`MediaStreamTrack`] `enabled` field to the provided + /// Sets underlying [`local::Track`] `enabled` field to the provided /// `is_enabled`. /// /// No-op if [`Transceiver::send_track`] is currently [`None`]. From f4685ba4729dac8b47fab6c26dbba7a3191cf016 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 19 Nov 2020 15:28:31 +0300 Subject: [PATCH 37/44] Remove state machine from the local::Track and use Rc/Weak --- jason/src/media/manager.rs | 40 ++++---- jason/src/media/track/local.rs | 154 +++++++------------------------ jason/src/peer/media/mod.rs | 6 +- jason/src/peer/media/sender.rs | 8 +- jason/src/peer/tracks_request.rs | 14 +-- jason/src/peer/transceiver.rs | 12 +-- 6 files changed, 72 insertions(+), 162 deletions(-) diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 97e586934..e4a693a4c 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -23,10 +23,7 @@ use crate::{ utils::{window, HandlerDetachedError, JasonError, JsCaused, JsError}, }; -use super::{ - track::local::{self, SharedPtr, WeakPtr}, - InputDeviceInfo, -}; +use super::{track::local, InputDeviceInfo}; // TODO: Screen capture API (https://w3.org/TR/screen-capture/) is in draft // stage atm, so there is no web-sys bindings for it. @@ -90,7 +87,7 @@ pub struct MediaManager(Rc); #[derive(Default)] struct InnerMediaManager { /// Obtained tracks storage - tracks: Rc>>>, + tracks: Rc>>>, } impl InnerMediaManager { @@ -146,7 +143,7 @@ impl InnerMediaManager { async fn get_tracks( &self, mut caps: MediaStreamSettings, - ) -> Result, bool)>> { + ) -> Result, bool)>> { let tracks_from_storage = self .get_from_storage(&mut caps) .into_iter() @@ -202,24 +199,24 @@ impl InnerMediaManager { fn get_from_storage( &self, caps: &mut MediaStreamSettings, - ) -> Vec> { + ) -> Vec> { // cleanup weak links self.tracks .borrow_mut() - .retain(|_, track| track.can_be_upgraded()); + .retain(|_, track| Weak::strong_count(track) > 0); let mut tracks = Vec::new(); let storage: Vec<_> = self .tracks .borrow() .iter() - .map(|(_, track)| track.upgrade().unwrap()) + .map(|(_, track)| Weak::upgrade(track).unwrap()) .collect(); if caps.is_audio_enabled() { let track = storage .iter() - .find(|track| caps.get_audio().satisfies(track.as_ref())) + .find(|track| caps.get_audio().satisfies(track.sys_track())) .map(Clone::clone); if let Some(track) = track { @@ -232,7 +229,7 @@ impl InnerMediaManager { storage .iter() .filter(|track| { - caps.unconstrain_if_satisfies_video(track.as_ref()) + caps.unconstrain_if_satisfies_video(track.sys_track()) }) .map(Clone::clone), ); @@ -249,7 +246,7 @@ impl InnerMediaManager { async fn get_user_media( &self, caps: SysMediaStreamConstraints, - ) -> Result>> { + ) -> Result>> { use MediaManagerError::{CouldNotGetMediaDevices, GetUserMediaFailed}; let media_devices = window() @@ -277,13 +274,13 @@ impl InnerMediaManager { .unwrap() .unwrap() .map(|track| { - local::Track::new( + Rc::new(local::Track::new( track.unwrap().into(), MediaSourceKind::Device, - ) + )) }) .inspect(|track| { - storage.insert(track.id(), track.downgrade()); + storage.insert(track.id(), Rc::downgrade(track)); }) .collect(); @@ -299,7 +296,7 @@ impl InnerMediaManager { async fn get_display_media( &self, caps: SysMediaStreamConstraints, - ) -> Result>> { + ) -> Result>> { use MediaManagerError::{ CouldNotGetMediaDevices, GetDisplayMediaFailed, GetUserMediaFailed, }; @@ -328,10 +325,13 @@ impl InnerMediaManager { .unwrap() .unwrap() .map(|tr| { - local::Track::new(tr.unwrap().into(), MediaSourceKind::Display) + Rc::new(local::Track::new( + tr.unwrap().into(), + MediaSourceKind::Display, + )) }) .inspect(|track| { - storage.insert(track.id(), track.downgrade()); + storage.insert(track.id(), Rc::downgrade(track)); }) .collect(); @@ -358,7 +358,7 @@ impl MediaManager { pub async fn get_tracks>( &self, caps: I, - ) -> Result, bool)>> { + ) -> Result, bool)>> { self.0.get_tracks(caps.into()).await } @@ -420,7 +420,7 @@ impl MediaManagerHandle { .map(|tracks| { tracks .into_iter() - .map(|(t, _)| local::JsTrack::new(t.fork())) + .map(|(t, _)| local::JsTrack::new(Rc::new(t.fork()))) .map(JsValue::from) .collect::() .into() diff --git a/jason/src/media/track/local.rs b/jason/src/media/track/local.rs index bf9dbf33d..3e0832f82 100644 --- a/jason/src/media/track/local.rs +++ b/jason/src/media/track/local.rs @@ -1,62 +1,41 @@ -//! Implementation of the wrappers around [`SysMediaStreamTrack`] received from +//! Implementation of the wrapper around [`SysMediaStreamTrack`] received from //! the gUM/gDM request. -use std::rc::{Rc, Weak}; +use std::rc::Rc; -use derive_more::AsRef; use medea_client_api_proto::MediaSourceKind; use wasm_bindgen::prelude::*; use web_sys::MediaStreamTrack as SysMediaStreamTrack; use crate::{media::MediaKind, JsMediaSourceKind}; -/// [`Weak`] reference to the [`InnerTrack`]. -#[derive(Clone, Debug)] -pub struct WeakPtr(Weak); - -/// [`Rc`] reference to the [`InnerTrack`]. -#[derive(Clone, Debug)] -pub struct SharedPtr(Rc); - /// Wrapper around [`SysMediaStreamTrack`] received from the gUM/gDM request. /// /// Can be forked by calling [`Track::fork`]. /// /// This [`Track`] will be stopped when all references to this [`Track`] and /// forked [`Track`]s will be dropped. -#[derive(Clone, Debug)] -pub struct Track { +#[derive(Debug)] +pub struct Track { + /// Reference to the parent [`Track`]. + /// + /// Parent will be [`None`] if this [`Track`] wasn't forked from + /// another [`Track`]. + /// + /// This field used only for holding strong reference to the parent. + _parent: Option>, + + /// Actual [`SysMediaStreamTrack`]. + track: SysMediaStreamTrack, + /// Underlying [`SysMediaStreamTrack`] source kind. source_kind: MediaSourceKind, /// Underlying [`SysMediaStreamTrack`] kind. kind: MediaKind, - - /// Actual reference to the [`SysMediaStreamTrack`]. - track: S, } -impl Track { - /// Checks whether this weak reference can be upgraded to a strong one. - #[inline] - pub fn can_be_upgraded(&self) -> bool { - self.track.0.strong_count() > 0 - } - - /// Upgrades [`Weak`] referenced [`Track`] to the [`Rc`] referenced - /// [`Track`]. - /// - /// Returns [`None`] if [`Weak`] reference can't be upgraded. - pub fn upgrade(&self) -> Option> { - Some(Track { - track: SharedPtr(Weak::upgrade(&self.track.0)?), - kind: self.kind, - source_kind: self.source_kind, - }) - } -} - -impl Track { +impl Track { /// Returns new [`Rc`] referenced [`Track`]. pub fn new( track: SysMediaStreamTrack, @@ -68,7 +47,8 @@ impl Track { _ => unreachable!(), }; Self { - track: SharedPtr(InnerTrack::new(track)), + _parent: None, + track, source_kind, kind, } @@ -76,7 +56,7 @@ impl Track { /// Sets [`SysMediaStreamTrack`] `enabled` field to the provided one. pub fn set_enabled(&self, enabled: bool) { - self.track.0.as_ref().as_ref().set_enabled(enabled); + self.track.set_enabled(enabled); } /// Returns [`id`][1] of underlying [MediaStreamTrack][2]. @@ -84,7 +64,7 @@ impl Track { /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn id(&self) -> String { - self.track.0.id() + self.track.id() } /// Returns this [`Track`] media source kind. @@ -106,94 +86,24 @@ impl Track { /// /// You can change properties of the forked [`Track`] without affecting the /// original one. - pub fn fork(&self) -> Self { + pub fn fork(self: &Rc) -> Self { + let parent = Rc::clone(self); + let track = SysMediaStreamTrack::clone(&self.track); Self { - track: SharedPtr(self.track.0.fork()), - source_kind: self.source_kind, - kind: self.kind, - } - } - - /// Downgrades [`Rc`] referenced [`Track`] to the [`Weak`] referenced - /// [`Track`]. - pub fn downgrade(&self) -> Track { - Track { - track: WeakPtr(Rc::downgrade(&self.track.0)), + _parent: Some(parent), + track, kind: self.kind, source_kind: self.source_kind, } } -} - -impl AsRef for Track { - fn as_ref(&self) -> &SysMediaStreamTrack { - self.track.0.as_ref().as_ref() - } -} - -/// Actual [`SysMediaStreamTrack`] with a strong reference to the it's parent -/// [`InnerTrack`]. -/// -/// When this [`InnerTrack`] is dropped - [`SysMediaStreamTrack::stop`] will be -/// performed. -/// -/// Note that all childs of this [`InnerTrack`] will hold strong reference to -/// this [`InnerTrack`], so it can be dropped only when all it's childs was -/// dropped. -#[derive(AsRef, Clone, Debug)] -struct InnerTrack { - /// Reference to the parent [`InnerTrack`]. - /// - /// Parent will be [`None`] if this [`InnerTrack`] wasn't forked from - /// another [`InnerTrack`]. - /// - /// This field used only for holding strong reference to the parent. - _parent: Option>, - - /// Actual [`SysMediaStreamTrack`]. - #[as_ref] - track: SysMediaStreamTrack, -} -impl InnerTrack { - /// Returns new root [`InnerTrack`] with a provided [`SysMediaStreamTrack`] - /// as underlying track. - fn new(track: SysMediaStreamTrack) -> Rc { - Rc::new(Self { - _parent: None, - track, - }) - } - - /// Returns [`id`][1] of underlying [MediaStreamTrack][2]. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id - /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - fn id(&self) -> String { - self.track.id() - } - - /// Returns fork of this [`InnerTrack`]. - /// - /// Returned [`InnerTrack`] is identical except for its unique id. - /// - /// Forked [`InnerTrack`] will hold reference to it's parent, so this - /// [`InnerTrack`] can't be dropped until all his forked [`InnerTrack`]s - /// will be dropped. - /// - /// You can change properties of the forked [`InnerTrack`] without affecting - /// the original one. - fn fork(self: &Rc) -> Rc { - let parent = Rc::clone(self); - let track = SysMediaStreamTrack::clone(&self.track); - Rc::new(Self { - _parent: Some(parent), - track, - }) + /// Returns reference to the [`SysMediaStreamTrack`]. + pub fn sys_track(&self) -> &SysMediaStreamTrack { + &self.track } } -impl Drop for InnerTrack { +impl Drop for Track { fn drop(&mut self) { self.track.stop(); } @@ -201,11 +111,11 @@ impl Drop for InnerTrack { /// Wrapper around strongly referenced [`Track`] for the JS side. #[wasm_bindgen(js_name = LocalMediaTrack)] -pub struct JsTrack(Track); +pub struct JsTrack(Rc); impl JsTrack { /// Wraps provided [`Track`] to the [`JsTrack`]. - pub fn new(track: Track) -> Self { + pub fn new(track: Rc) -> Self { JsTrack(track) } } @@ -215,7 +125,7 @@ impl JsTrack { /// Returns underlying [`SysMediaStreamTrack`] from this /// [`MediaStreamTrack`]. pub fn get_track(&self) -> SysMediaStreamTrack { - Clone::clone(self.0.as_ref()) + Clone::clone(self.0.track.as_ref()) } /// Returns a [`String`] set to `audio` if the track is an audio track diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index dfa3715c6..3f1cf51a5 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -18,7 +18,7 @@ use web_sys::RtcTrackEvent; use crate::{ media::{ - track::local::{self, SharedPtr}, + track::local::{self}, LocalTracksConstraints, MediaKind, RecvConstraints, }, peer::{ @@ -694,7 +694,7 @@ impl MediaConnections { /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack pub async fn insert_local_tracks( &self, - tracks: &HashMap>, + tracks: &HashMap>, ) -> Result> { let inner = self.0.borrow(); @@ -703,7 +703,7 @@ impl MediaConnections { let mut media_exchange_state_updates = HashMap::new(); for sender in inner.senders.values() { if let Some(track) = tracks.get(&sender.track_id()).cloned() { - if sender.caps().satisfies(&track) { + if sender.caps().satisfies(track.sys_track()) { media_exchange_state_updates.insert( sender.track_id(), media_exchange_state::Stable::Enabled, diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index 42b248967..094483140 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -6,8 +6,8 @@ use medea_client_api_proto::{MediaSourceKind, TrackId, TrackPatchEvent}; use crate::{ media::{ - track::local::{self, SharedPtr}, - LocalTracksConstraints, MediaKind, TrackConstraints, VideoSource, + track::local, LocalTracksConstraints, MediaKind, TrackConstraints, + VideoSource, }, peer::transceiver::{Transceiver, TransceiverDirection}, }; @@ -141,7 +141,7 @@ impl Sender { /// [`Sender`]. pub(super) async fn insert_track( self: Rc, - new_track: local::Track, + new_track: Rc, ) -> Result<()> { // no-op if we try to insert same track if let Some(current_track) = self.transceiver.send_track() { @@ -158,7 +158,7 @@ impl Sender { ); self.transceiver - .set_send_track(Some(new_track)) + .set_send_track(Some(Rc::new(new_track))) .await .map_err(Into::into) .map_err(MediaConnectionsError::CouldNotInsertLocalTrack) diff --git a/jason/src/peer/tracks_request.rs b/jason/src/peer/tracks_request.rs index 8ff848134..1c97a4839 100644 --- a/jason/src/peer/tracks_request.rs +++ b/jason/src/peer/tracks_request.rs @@ -2,7 +2,7 @@ //! //! [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamconstraints -use std::{collections::HashMap, convert::TryFrom}; +use std::{collections::HashMap, convert::TryFrom, rc::Rc}; use derive_more::Display; use medea_client_api_proto::{MediaSourceKind, TrackId}; @@ -10,7 +10,7 @@ use tracerr::Traced; use crate::{ media::{ - track::local::{self, SharedPtr}, + track::local::{self}, AudioTrackConstraints, MediaKind, MediaStreamSettings, TrackConstraints, VideoSource, }, @@ -138,8 +138,8 @@ impl SimpleTracksRequest { /// [`HashMap`] doesn't have the expected display video track. pub fn parse_tracks( &self, - tracks: Vec>, - ) -> Result>> { + tracks: Vec>, + ) -> Result>> { use TracksRequestError::{InvalidAudioTrack, InvalidVideoTrack}; let mut parsed_tracks = HashMap::new(); @@ -165,7 +165,7 @@ impl SimpleTracksRequest { if let Some((id, audio)) = &self.audio { if let Some(track) = audio_tracks.into_iter().next() { - if audio.satisfies(track.as_ref()) { + if audio.satisfies(track.sys_track()) { parsed_tracks.insert(*id, track); } else { return Err(tracerr::new!(InvalidAudioTrack)); @@ -174,7 +174,7 @@ impl SimpleTracksRequest { } if let Some((id, device_video)) = &self.device_video { if let Some(track) = device_video_tracks.into_iter().next() { - if device_video.satisfies(track.as_ref()) { + if device_video.satisfies(track.sys_track()) { parsed_tracks.insert(*id, track); } else { return Err(tracerr::new!(InvalidVideoTrack)); @@ -183,7 +183,7 @@ impl SimpleTracksRequest { } if let Some((id, display_video)) = &self.display_video { if let Some(track) = display_video_tracks.into_iter().next() { - if display_video.satisfies(track.as_ref()) { + if display_video.satisfies(track.sys_track()) { parsed_tracks.insert(*id, track); } else { return Err(tracerr::new!(InvalidVideoTrack)); diff --git a/jason/src/peer/transceiver.rs b/jason/src/peer/transceiver.rs index 4fa0270b4..52403001c 100644 --- a/jason/src/peer/transceiver.rs +++ b/jason/src/peer/transceiver.rs @@ -1,6 +1,6 @@ //! [`RtcRtpTransceiver`] wrapper. -use std::cell::RefCell; +use std::{cell::RefCell, rc::Rc}; use bitflags::bitflags; use medea_client_api_proto::Direction as DirectionProto; @@ -8,13 +8,13 @@ use wasm_bindgen::JsValue; use wasm_bindgen_futures::JsFuture; use web_sys::{RtcRtpTransceiver, RtcRtpTransceiverDirection}; -use crate::media::track::local::{self, SharedPtr}; +use crate::media::track::local; /// Wrapper around [`RtcRtpTransceiver`] which provides handy methods for /// direction changes. #[derive(Clone)] pub struct Transceiver { - send_track: RefCell>>, + send_track: RefCell>>, transceiver: RtcRtpTransceiver, } @@ -54,9 +54,9 @@ impl Transceiver { /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack pub async fn set_send_track( &self, - new_track: Option>, + new_track: Option>, ) -> Result<(), JsValue> { - let sys_track = new_track.as_ref().map(AsRef::as_ref); + let sys_track = new_track.as_ref().map(|t| t.sys_track()); JsFuture::from(self.transceiver.sender().replace_track(sys_track)) .await .map(|_| { @@ -72,7 +72,7 @@ impl Transceiver { } /// Returns [`local::Track`] that is being send to remote, if any. - pub fn send_track(&self) -> Option> { + pub fn send_track(&self) -> Option> { self.send_track.borrow().clone() } From cdaba5b3716b0360be089ecbb2bb4e92e94d5f17 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 19 Nov 2020 15:39:16 +0300 Subject: [PATCH 38/44] Fix tests --- jason/tests/media/constraints.rs | 16 +++++++++------- jason/tests/media/track.rs | 8 +++++--- jason/tests/web.rs | 4 ++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/jason/tests/media/constraints.rs b/jason/tests/media/constraints.rs index 422f1d67e..4c4375477 100644 --- a/jason/tests/media/constraints.rs +++ b/jason/tests/media/constraints.rs @@ -41,7 +41,7 @@ async fn video_constraints_satisfies() { let track = tracks.pop().unwrap().0; assert_eq!(track.kind(), MediaKind::Video); - assert!(track_constraints.satisfies(track.as_ref())); + assert!(track_constraints.satisfies(track.sys_track())); } // 1. Get device id of non default audio device from enumerate_devices(); @@ -66,7 +66,7 @@ async fn audio_constraints_satisfies() { let track = tracks.pop().unwrap().0; assert_eq!(track.kind(), MediaKind::Audio); - assert!(track_constraints.satisfies(&track)); + assert!(track_constraints.satisfies(track.sys_track())); } // 1. Get device id of non default video device from enumerate_devices(); @@ -115,10 +115,10 @@ async fn both_constraints_satisfies() { let video_track = video.pop().unwrap().0; assert_eq!(audio_track.kind(), MediaKind::Audio); - assert!(audio_constraints.satisfies(&audio_track)); + assert!(audio_constraints.satisfies(audio_track.sys_track())); assert_eq!(video_track.kind(), MediaKind::Video); - assert!(video_constraints.satisfies(video_track.as_ref())); + assert!(video_constraints.satisfies(video_track.sys_track())); } // 1. Get device id of non default audio and video device from @@ -530,15 +530,17 @@ async fn simultaneous_device_and_display() { let audio_track = audio.pop().unwrap().0; assert_eq!(audio_track.kind(), MediaKind::Audio); - assert!(audio_constraints.satisfies(&audio_track)); + assert!(audio_constraints.satisfies(audio_track.sys_track())); let display_video_track = video.pop().unwrap().0; assert_eq!(display_video_track.kind(), MediaKind::Video); - assert!(display_video_constraints.satisfies(display_video_track.as_ref())); + assert!( + display_video_constraints.satisfies(display_video_track.sys_track()) + ); assert_eq!(display_video_track.source_kind(), MediaSourceKind::Display); let device_video_track = video.pop().unwrap().0; assert_eq!(device_video_track.kind(), MediaKind::Video); - assert!(device_video_constraints.satisfies(device_video_track.as_ref())); + assert!(device_video_constraints.satisfies(device_video_track.sys_track())); assert_eq!(device_video_track.source_kind(), MediaSourceKind::Device); } diff --git a/jason/tests/media/track.rs b/jason/tests/media/track.rs index d8754a5ca..7918cb1b6 100644 --- a/jason/tests/media/track.rs +++ b/jason/tests/media/track.rs @@ -1,5 +1,7 @@ #![cfg(target_arch = "wasm32")] +use std::rc::{Rc, Weak}; + use futures::channel::oneshot; use medea_jason::{ media::MediaManager, DeviceVideoTrackConstraints, MediaStreamSettings, @@ -22,13 +24,13 @@ async fn track_autostop() { assert_eq!(1, tracks.len()); let (strong_track, strong_track_is_new) = tracks.pop().unwrap(); assert!(strong_track_is_new); - let sys_track = Clone::clone(strong_track.as_ref()); - let weak_track = strong_track.downgrade(); + let sys_track = Clone::clone(strong_track.sys_track()); + let weak_track = Rc::downgrade(&strong_track); assert!(sys_track.ready_state() == MediaStreamTrackState::Live); drop(strong_track); assert!(sys_track.ready_state() == MediaStreamTrackState::Ended); - assert!(!weak_track.can_be_upgraded()); + assert_eq!(Weak::strong_count(&weak_track), 0); } #[wasm_bindgen_test] diff --git a/jason/tests/web.rs b/jason/tests/web.rs index 10aa6af8a..48e980e31 100644 --- a/jason/tests/web.rs +++ b/jason/tests/web.rs @@ -289,7 +289,7 @@ async fn get_video_track() -> remote::Track { let mut settings = MediaStreamSettings::new(); settings.device_video(DeviceVideoTrackConstraints::new()); let stream = manager.get_tracks(settings).await.unwrap(); - let track = Clone::clone(stream.into_iter().next().unwrap().0.as_ref()); + let track = Clone::clone(stream.into_iter().next().unwrap().0.sys_track()); remote::Track::new(track, MediaSourceKind::Device) } @@ -298,7 +298,7 @@ async fn get_audio_track() -> remote::Track { let mut settings = MediaStreamSettings::new(); settings.audio(AudioTrackConstraints::new()); let stream = manager.get_tracks(settings).await.unwrap(); - let track = Clone::clone(stream.into_iter().next().unwrap().0.as_ref()); + let track = Clone::clone(stream.into_iter().next().unwrap().0.sys_track()); remote::Track::new(track, MediaSourceKind::Device) } From c88053911a3dd266d0352a48b9f57a9e6137fbe4 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Thu, 19 Nov 2020 15:50:27 +0300 Subject: [PATCH 39/44] Upd CHANGELOG --- jason/CHANGELOG.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/jason/CHANGELOG.md b/jason/CHANGELOG.md index 817cc3f51..de16c0a71 100644 --- a/jason/CHANGELOG.md +++ b/jason/CHANGELOG.md @@ -40,8 +40,8 @@ All user visible changes to this project will be documented in this file. This p - `DeviceVideoTrackConstraints`, `DisplayVideoTrackConstraints` classes ([#78]); - `DeviceVideoTrackConstraints.ideal_facing_mode` and `DeviceVideoTrackConstraints.exact_facing_mode` functions ([#137]); - `FacingMode` enum ([#137]). - - `MediaKind` enum that provides `MediaTrack` and `InputDeviceInfo` kind ([#146]); - - `MediaSourceKind` enum that provides `MediaTrack` media source kind (`Device` or `Display`) ([#146]); + - `MediaKind` enum that provides `LocalMediaTrack`/`RemoteMediaTrack` and `InputDeviceInfo` kind ([#146]); + - `MediaSourceKind` enum that provides `MediaTrack` media source kind (`Device` or `Display`) ([#146], [#156]); - Room management: - `Jason.init_room()` ([#46]); - `Room.join()` ([#46]); @@ -61,7 +61,12 @@ All user visible changes to this project will be documented in this file. This p - `Room.unmute_audio`; - `Room.mute_video`; - `Room.unmute_video`. - - `MediaTrack.media_source_kind` function ([#145], [#146]). + - `RemoteMediaTrack`/`LocalMediaTrack` `media_source_kind` function ([#145], [#146], [#156]); + - `RemoteMediaTrack` class ([#156]); + - `RemoteMediaTrack` callbacks ([#123], [#156]): + - `RemoteMediaTrack.on_enabled`; + - `RemoteMediaTrack.on_disabled`. + - `LocalMediaTrack` class ([#156]). - Optional tracks support ([#106]); - Simultaneous device and display video tracks publishing and receiving ([#144]); - `RtcIceTransportPolicy` configuration ([#79]). From 03e307938cd721c987fbcce661333df5ccddfd98 Mon Sep 17 00:00:00 2001 From: alexlapa Date: Fri, 20 Nov 2020 09:49:25 +0200 Subject: [PATCH 40/44] refactor [run ci] --- Makefile | 2 +- jason/CHANGELOG.md | 7 +-- jason/src/api/room.rs | 19 ++++--- jason/src/media/constraints.rs | 14 +++--- jason/src/media/manager.rs | 38 +++++++------- jason/src/media/track/local.rs | 50 +++++++++---------- jason/src/media/track/remote.rs | 35 ++++++------- jason/src/peer/media/mod.rs | 37 +++++++------- jason/src/peer/media/receiver.rs | 15 +++++- jason/src/peer/media/sender.rs | 8 +-- jason/src/peer/media/transitable_state/mod.rs | 12 +++-- jason/src/peer/mod.rs | 18 +++---- jason/src/peer/tracks_request.rs | 5 +- jason/src/peer/transceiver.rs | 9 ++-- jason/tests/media/constraints.rs | 10 +++- 15 files changed, 141 insertions(+), 138 deletions(-) diff --git a/Makefile b/Makefile index 571d8b2fb..4ec6d5bac 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ CONTROL_MOCK_IMAGE_NAME := instrumentisto/medea-control-api-mock RUST_VER := 1.47 CHROME_VERSION := 87.0 -FIREFOX_VERSION := 82.0.3 +FIREFOX_VERSION := 83.0 crate-dir = . ifeq ($(crate),medea-jason) diff --git a/jason/CHANGELOG.md b/jason/CHANGELOG.md index de16c0a71..a0b666c2a 100644 --- a/jason/CHANGELOG.md +++ b/jason/CHANGELOG.md @@ -49,8 +49,8 @@ All user visible changes to this project will be documented in this file. This p - Ability to configure local media stream used by `Room` via `Room.set_local_media_settings()` ([#54], [#97], [#145]); - `Room.on_failed_local_media` callback ([#54], [#143]); - `Room.on_close` callback for WebSocket close initiated by server ([#55]); - - `MediaTrack.on_enabled` and `MediaTrack.on_disabled` callbacks being called when `MediaTrack` is enabled or disabled ([#123], [#143]); - - `ConnectionHandle.on_remote_track_added` callback being called when new receiver `MediaTrack` is added ([#123], [#143]); + - `RemoteMediaTrack.on_enabled` and `RemoteMediaTrack.on_disabled` callbacks being called when `RemoteMediaTrack` is enabled or disabled ([#123], [#143], [#156]); + - `ConnectionHandle.on_remote_track_added` callback being called when new receiver `RemoteMediaTrack` is added ([#123], [#143], [#156]); - Enabling/disabling remote video/audio ([#127], [#155]): - `Room.disable_remote_audio`; - `Room.enable_remote_audio`; @@ -63,9 +63,6 @@ All user visible changes to this project will be documented in this file. This p - `Room.unmute_video`. - `RemoteMediaTrack`/`LocalMediaTrack` `media_source_kind` function ([#145], [#146], [#156]); - `RemoteMediaTrack` class ([#156]); - - `RemoteMediaTrack` callbacks ([#123], [#156]): - - `RemoteMediaTrack.on_enabled`; - - `RemoteMediaTrack.on_disabled`. - `LocalMediaTrack` class ([#156]). - Optional tracks support ([#106]); - Simultaneous device and display video tracks publishing and receiving ([#144]); diff --git a/jason/src/api/room.rs b/jason/src/api/room.rs index dc13d1a14..76d68a7eb 100644 --- a/jason/src/api/room.rs +++ b/jason/src/api/room.rs @@ -380,7 +380,7 @@ impl RoomHandle { /// callback. /// /// [`PeerConnection`]: crate::peer::PeerConnection - /// [1]: https://tinyurl.com/rnxcavf + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia pub fn set_local_media_settings( &self, settings: &MediaStreamSettings, @@ -748,8 +748,8 @@ struct InnerRoom { /// Collection of [`Connection`]s with a remote [`Member`]s. connections: Connections, - /// Callback to be invoked when new local [`MediaStreamTrack`] will be - /// added to this [`Room`]. + /// Callback to be invoked when new local [`local::JsTrack`] will be added + /// to this [`Room`]. on_local_track: Callback1, /// Callback to be invoked when failed obtain [`MediaTrack`]s from @@ -958,7 +958,7 @@ impl InnerRoom { /// [`PeerConnection`]s in this [`Room`]. If [`MediaStreamSettings`] is /// configured for some [`Room`], then this [`Room`] can only send /// [`MediaStream`] that corresponds to this settings. - /// [`MediaStreamSettings`] update will change [`MediaStreamTrack`]s in all + /// [`MediaStreamSettings`] update will change [`local::Track`]s in all /// sending peers, so that might cause new [getUserMedia()][1] request. /// /// Media obtaining/injection errors are fired to `on_failed_local_media` @@ -968,7 +968,7 @@ impl InnerRoom { /// are should be enabled or disabled. /// /// [`PeerConnection`]: crate::peer::PeerConnection - /// [1]: https://tinyurl.com/rnxcavf + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia async fn set_local_media_settings( &self, settings: MediaStreamSettings, @@ -1257,7 +1257,7 @@ impl PeerEventHandler for InnerRoom { } /// Handles [`PeerEvent::NewRemoteTrack`] event and passes received - /// [`MediaStreamTrack`] to the related [`Connection`]. + /// [`remote::Track`] to the related [`Connection`]. async fn on_new_remote_track( &self, sender_id: MemberId, @@ -1273,8 +1273,11 @@ impl PeerEventHandler for InnerRoom { } /// Invokes `on_local_track` [`Room`]'s callback. - async fn on_new_local_track(&self, track: local::JsTrack) -> Self::Output { - self.on_local_track.call(track); + async fn on_new_local_track( + &self, + track: Rc, + ) -> Self::Output { + self.on_local_track.call(local::JsTrack::new(track)); Ok(()) } diff --git a/jason/src/media/constraints.rs b/jason/src/media/constraints.rs index f3ab6a17a..a975c4160 100644 --- a/jason/src/media/constraints.rs +++ b/jason/src/media/constraints.rs @@ -390,7 +390,7 @@ impl MediaStreamSettings { self.device_video.constraints.as_ref() } - /// Enables or disables (muted or unmutes) audio or video type in this + /// Changes [`MediaState`] of audio or video type in this /// [`MediaStreamSettings`]. /// /// If some type of the [`MediaStreamSettings`] is disabled, then this kind @@ -576,7 +576,7 @@ impl MediaStreamSettings { pub enum MultiSourceTracksConstraints { /// Only [getUserMedia()][1] request is required. /// - /// [1]: https://tinyurl.com/rnxcavf + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia Device(SysMediaStreamConstraints), /// Only [getDisplayMedia()][1] request is required. @@ -586,7 +586,7 @@ pub enum MultiSourceTracksConstraints { /// Both [getUserMedia()][1] and [getDisplayMedia()][2] are required. /// - /// [1]: https://tinyurl.com/rnxcavf + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia DeviceAndDisplay(SysMediaStreamConstraints, SysMediaStreamConstraints), } @@ -653,15 +653,13 @@ impl From for Option { } } -/// Constraints for the [`MediaKind::Video`] [`MediaStreamTrack`]. +/// Constraints for the [`MediaKind::Video`] [`local::Track`]. #[derive(Clone, Debug)] pub enum VideoSource { - /// [`MediaStreamTrack`] should be received from the `getUserMedia` - /// request. + /// [`local::Track`] should be received from the `getUserMedia` request. Device(DeviceVideoTrackConstraints), - /// [`MediaStreamTrack`] should be received from the `getDisplayMedia` - /// request. + /// [`local::Track`] should be received from the `getDisplayMedia` request. Display(DisplayVideoTrackConstraints), } diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index e4a693a4c..27a0f7cdc 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -51,7 +51,7 @@ pub enum MediaManagerError { /// Occurs if the [getUserMedia][1] request failed. /// - /// [1]: https://tinyurl.com/rnxcavf + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia #[display(fmt = "MediaDevices.getUserMedia() failed: {}", _0)] GetUserMediaFailed(JsError), @@ -138,7 +138,7 @@ impl InnerMediaManager { /// With [`MediaManagerError::GetDisplayMediaFailed`] if /// [getDisplayMedia()][2] request failed. /// - /// [1]: https://tinyurl.com/rnxcavf + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia async fn get_tracks( &self, @@ -189,13 +189,12 @@ impl InnerMediaManager { } } - /// Tries to find [`MediaStreamTrack`]s that satisfies - /// [`MediaStreamSettings`], from tracks that were acquired earlier to avoid - /// redundant [getUserMedia()][1]/[getDisplayMedia()][2] calls. + /// Tries to find [`local::Track`]s that satisfies [`MediaStreamSettings`], + /// from tracks that were acquired earlier to avoid redundant + /// [getUserMedia()][1]/[getDisplayMedia()][2] calls. /// - /// [1]: https://tinyurl.com/rnxcavf + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - #[allow(clippy::find_map, clippy::filter_map)] fn get_from_storage( &self, caps: &mut MediaStreamSettings, @@ -217,7 +216,7 @@ impl InnerMediaManager { let track = storage .iter() .find(|track| caps.get_audio().satisfies(track.sys_track())) - .map(Clone::clone); + .cloned(); if let Some(track) = track { caps.set_audio_publish(false); @@ -231,7 +230,7 @@ impl InnerMediaManager { .filter(|track| { caps.unconstrain_if_satisfies_video(track.sys_track()) }) - .map(Clone::clone), + .cloned(), ); tracks @@ -242,7 +241,7 @@ impl InnerMediaManager { /// refs. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastream - /// [2]: https://tinyurl.com/rnxcavf + /// [2]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia async fn get_user_media( &self, caps: SysMediaStreamConstraints, @@ -340,10 +339,9 @@ impl InnerMediaManager { } impl MediaManager { - /// Obtains [`MediaStreamTrack`]s based on a provided - /// [`MediaStreamSettings`]. This can be the tracks that were acquired - /// earlier, or new tracks, acquired via [getUserMedia()][1] or/and - /// [getDisplayMedia()][2] requests. + /// Obtains [`local::Track`]s based on a provided [`MediaStreamSettings`]. + /// This can be the tracks that were acquired earlier, or new tracks, + /// acquired via [getUserMedia()][1] or/and [getDisplayMedia()][2] requests. /// /// # Errors /// @@ -353,7 +351,7 @@ impl MediaManager { /// With [`MediaManagerError::GetDisplayMediaFailed`] if /// [getDisplayMedia()][2] request failed. /// - /// [1]: https://tinyurl.com/rnxcavf + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia pub async fn get_tracks>( &self, @@ -375,9 +373,9 @@ impl MediaManager { /// ([getUserMedia()][1]/[getDisplayMedia()][2]) and stores all received tracks /// for further reusage. /// -/// [`MediaManager`] stores weak references to [`MediaStreamTrack`]s, so if -/// there are no strong references to some track, then this track is stopped -/// and deleted from [`MediaManager`]. +/// [`MediaManager`] stores weak references to [`local::Track`]s, so if there +/// are no strong references to some track, then this track is stopped and +/// deleted from [`MediaManager`]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia @@ -408,7 +406,7 @@ impl MediaManagerHandle { }) } - /// Returns [`MediaStreamTrack`]s objects, built from provided + /// Returns [`local::JsTrack`]s objects, built from provided /// [`MediaStreamSettings`]. pub fn init_local_tracks(&self, caps: &MediaStreamSettings) -> Promise { let inner = upgrade_or_detached!(self.0, JasonError); @@ -420,7 +418,7 @@ impl MediaManagerHandle { .map(|tracks| { tracks .into_iter() - .map(|(t, _)| local::JsTrack::new(Rc::new(t.fork()))) + .map(|(t, _)| local::JsTrack::new(t)) .map(JsValue::from) .collect::() .into() diff --git a/jason/src/media/track/local.rs b/jason/src/media/track/local.rs index 3e0832f82..b3f7f294e 100644 --- a/jason/src/media/track/local.rs +++ b/jason/src/media/track/local.rs @@ -11,16 +11,13 @@ use crate::{media::MediaKind, JsMediaSourceKind}; /// Wrapper around [`SysMediaStreamTrack`] received from the gUM/gDM request. /// -/// Can be forked by calling [`Track::fork`]. -/// -/// This [`Track`] will be stopped when all references to this [`Track`] and -/// forked [`Track`]s will be dropped. +/// Underlying [`SysMediaStreamTrack`] is stopped on [`Track`] [`Drop`]. #[derive(Debug)] pub struct Track { /// Reference to the parent [`Track`]. /// - /// Parent will be [`None`] if this [`Track`] wasn't forked from - /// another [`Track`]. + /// Parent will be [`None`] if this [`Track`] wasn't forked from another + /// [`Track`]. /// /// This field used only for holding strong reference to the parent. _parent: Option>, @@ -36,7 +33,8 @@ pub struct Track { } impl Track { - /// Returns new [`Rc`] referenced [`Track`]. + /// Builds [`Track`] from provided [`SysMediaStreamTrack`] and + /// [`MediaSourceKind`]. pub fn new( track: SysMediaStreamTrack, source_kind: MediaSourceKind, @@ -54,7 +52,11 @@ impl Track { } } - /// Sets [`SysMediaStreamTrack`] `enabled` field to the provided one. + /// Changes [`enabled`][1] attribute on the underlying + /// [MediaStreamTrack][2]. + /// + /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn set_enabled(&self, enabled: bool) { self.track.set_enabled(enabled); } @@ -68,24 +70,23 @@ impl Track { } /// Returns this [`Track`] media source kind. - pub fn source_kind(&self) -> MediaSourceKind { + pub fn media_source_kind(&self) -> MediaSourceKind { self.source_kind } - /// Returns track kind (audio/video). + /// Returns [`Track`] kind (audio/video). pub fn kind(&self) -> MediaKind { self.kind } - /// Returns fork of this [`Track`]. + /// Forks this [`Track`]. /// - /// Returned [`Track`] is identical except for its unique id. + /// Creates new [`SysMediaStreamTrack`] from this [`Track`] + /// [`SysMediaStreamTrack`] using [`clone`][1] method. /// - /// Forked [`Track`] will hold reference to it's parent, so this [`Track`] - /// can't be dropped until all his forked [`Track`]s will be dropped. + /// Forked [`Track`] holds strong reference to this [`Track`]. /// - /// You can change properties of the forked [`Track`] without affecting the - /// original one. + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-clone pub fn fork(self: &Rc) -> Self { let parent = Rc::clone(self); let track = SysMediaStreamTrack::clone(&self.track); @@ -114,7 +115,7 @@ impl Drop for Track { pub struct JsTrack(Rc); impl JsTrack { - /// Wraps provided [`Track`] to the [`JsTrack`]. + /// Creates new [`JsTrack`] from provided [`Track`]. pub fn new(track: Rc) -> Self { JsTrack(track) } @@ -122,24 +123,23 @@ impl JsTrack { #[wasm_bindgen(js_class = LocalMediaTrack)] impl JsTrack { - /// Returns underlying [`SysMediaStreamTrack`] from this - /// [`MediaStreamTrack`]. + /// Returns underlying [`SysMediaStreamTrack`] from this [`JsTrack`]. pub fn get_track(&self) -> SysMediaStreamTrack { Clone::clone(self.0.track.as_ref()) } - /// Returns a [`String`] set to `audio` if the track is an audio track - /// and to `video`, if it is a video track. + /// Returns a [`MediaKind::Audio`] if the track is an audio track and to + /// [`MediaKind::Video`], if it is a video track. pub fn kind(&self) -> MediaKind { self.0.kind() } - /// Returns a [`String`] set to `device` if track is sourced from some - /// device (webcam/microphone) and to `display`, if track is captured - /// via [MediaDevices.getDisplayMedia()][1]. + /// Returns [`JsMediaSourceKind::Device`] if track is sourced from some + /// device (webcam/microphone) and [`JsMediaSourceKind::Display`], if track + /// is captured via [MediaDevices.getDisplayMedia()][1]. /// /// [1]: https://tinyurl.com/y2anfntz pub fn media_source_kind(&self) -> JsMediaSourceKind { - self.0.source_kind().into() + self.0.media_source_kind().into() } } diff --git a/jason/src/media/track/remote.rs b/jason/src/media/track/remote.rs index 7e0924b39..9dbcc0d2e 100644 --- a/jason/src/media/track/remote.rs +++ b/jason/src/media/track/remote.rs @@ -1,5 +1,5 @@ //! Implementation of the wrapper around [`SysMediaStreamTrack`] received from -//! the remote side. +//! the remote. use std::rc::Rc; @@ -12,8 +12,6 @@ use web_sys::MediaStreamTrack as SysMediaStreamTrack; use crate::{media::MediaKind, utils::Callback0, JsMediaSourceKind}; -/// Wrapper around [`SysMediaStreamTrack`] received from the remote side to -/// track when it's enabled or disabled. struct Inner { /// Underlying JS-side [`SysMediaStreamTrack`]. track: SysMediaStreamTrack, @@ -30,14 +28,14 @@ struct Inner { /// Callback to be invoked when this [`remote::Track`] is disabled. on_disabled: Callback0, - /// [enabled] property of [MediaStreamTrack][1]. + /// [enabled][1] property of [MediaStreamTrack][2]. /// - /// [enabled]: https://tinyurl.com/y5byqdea - /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack + /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled + /// [2]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack enabled: ObservableCell, } -/// Strong reference to [MediaStreamTrack][1]. +/// Wrapper around [MediaStreamTrack][1] received from the remote. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack #[wasm_bindgen(js_name = RemoteMediaTrack)] @@ -45,8 +43,8 @@ struct Inner { pub struct Track(Rc); impl Track { - /// Creates new [`Track`], spawns listener for - /// [`Inner::enabled`] state changes. + /// Creates new [`Track`], spawns listener for [`Inner::enabled`] state + /// changes. pub fn new(track: T, media_source_kind: MediaSourceKind) -> Self where SysMediaStreamTrack: From, @@ -130,8 +128,7 @@ impl Track { #[wasm_bindgen(js_class = RemoteMediaTrack)] impl Track { - /// Returns underlying [`SysMediaStreamTrack`] from this - /// [`Track`]. + /// Returns underlying [`SysMediaStreamTrack`] from this [`Track`]. pub fn get_track(&self) -> SysMediaStreamTrack { Clone::clone(&self.0.track) } @@ -142,28 +139,26 @@ impl Track { self.0.enabled.get() } - /// Sets callback, which will be invoked when this [`Track`] - /// is enabled. + /// Sets callback, which will be invoked when this [`Track`] is enabled. pub fn on_enabled(&self, callback: js_sys::Function) { self.0.on_enabled.set_func(callback); } - /// Sets callback, which will be invoked when this [`Track`] - /// is enabled. + /// Sets callback, which will be invoked when this [`Track`] is enabled. pub fn on_disabled(&self, callback: js_sys::Function) { self.0.on_disabled.set_func(callback); } - /// Returns a [`String`] set to `audio` if the track is an audio track - /// and to `video`, if it is a video track. + /// Returns a [`MediaKind::Audio`] if the track is an audio track and to + /// [`MediaKind::Video`], if it is a video track. #[wasm_bindgen(js_name = kind)] pub fn js_kind(&self) -> MediaKind { self.kind() } - /// Returns a [`String`] set to `device` if track is sourced from some - /// device (webcam/microphone) and to `display`, if track is captured - /// via [MediaDevices.getDisplayMedia()][1]. + /// Returns [`JsMediaSourceKind::Device`] if track is sourced from some + /// device (webcam/microphone) and [`JsMediaSourceKind::Display`], if track + /// is captured via [MediaDevices.getDisplayMedia()][1]. /// /// [1]: https://tinyurl.com/y2anfntz #[wasm_bindgen(js_name = media_source_kind)] diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index 3f1cf51a5..02c7c5a3c 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -218,13 +218,13 @@ pub enum TrackDirection { /// Errors that may occur in [`MediaConnections`] storage. #[derive(Clone, Debug, Display, JsCaused)] pub enum MediaConnectionsError { - /// Occurs when the provided [`MediaStreamTrack`] cannot be inserted into + /// Occurs when the provided [`local::Track`] cannot be inserted into /// provided [`Sender`]s transceiver. #[display(fmt = "Failed to insert Track to a sender: {}", _0)] CouldNotInsertLocalTrack(JsError), - /// Occurs when [`MediaStreamTrack`] discovered by [`RtcPeerConnection`] - /// could not be inserted into [`Receiver`]. + /// Occurs when [`remote::Track`] discovered by [`RtcPeerConnection`] could + /// not be inserted into [`Receiver`]. #[display( fmt = "Could not insert remote track with mid: {:?} into media \ connections", @@ -245,12 +245,11 @@ pub enum MediaConnectionsError { ReceiversWithoutMid, /// Occurs when inserted [`PeerMediaStream`] dont have all necessary - /// [`MediaStreamTrack`]s. + /// [`local::Track`]s. #[display(fmt = "Provided stream does not have all necessary Tracks")] InvalidMediaTracks, - /// Occurs when [`MediaStreamTrack`] of inserted [`PeerMediaStream`] does - /// not satisfy [`Sender`] constraints. + /// Occurs when [`local::Track`] does not satisfy [`Sender`] constraints. #[display(fmt = "Provided Track does not satisfy senders constraints")] InvalidMediaTrack, @@ -264,8 +263,7 @@ pub enum MediaConnectionsError { expected MediaExchangeState")] MediaStateTransitsIntoOppositeState, - /// Invalid [`medea_client_api_proto::TrackPatch`] for - /// [`MediaStreamTrack`]. + /// Invalid [`medea_client_api_proto::TrackPatch`] for [`local::Track`]. #[display(fmt = "Invalid TrackPatch for Track with {} ID.", _0)] InvalidTrackPatch(TrackId), @@ -421,7 +419,7 @@ impl MediaConnections { continue; } - let is_not_in_state = match state { + let not_in_state = match state { MediaState::Mute(mute_state) => { transceiver.mute_state() != mute_state.into() } @@ -429,7 +427,7 @@ impl MediaConnections { transceiver.media_exchange_state() != media_exchange.into() } }; - if is_not_in_state { + if not_in_state { return false; } } @@ -457,8 +455,8 @@ impl MediaConnections { .is_none() } - /// Returns mapping from a [`MediaStreamTrack`] ID to a `mid` of - /// this track's [`RtcRtpTransceiver`]. + /// Returns mapping from a [`proto::Track`] ID to a `mid` of this track's + /// [`RtcRtpTransceiver`]. /// /// # Errors /// @@ -624,7 +622,7 @@ impl MediaConnections { /// # Errors /// /// Errors with [`MediaConnectionsError::InvalidTrackPatch`] if - /// [`MediaStreamTrack`] with ID from [`proto::TrackPatch`] doesn't exist. + /// [`proto::Track`] with ID from [`proto::TrackPatch`] doesn't exist. pub async fn patch_tracks( &self, tracks: Vec, @@ -671,9 +669,8 @@ impl MediaConnections { /// Inserts provided tracks into [`Sender`]s based on track IDs. /// - /// [`MediaStreamTrack`]s are inserted into [`Sender`]'s - /// [`RtcRtpTransceiver`]s via [`replaceTrack` method][1], changing its - /// direction to `sendonly`. + /// [`local::Track`]s are inserted into [`Sender`]'s [`RtcRtpTransceiver`]s + /// via [`replaceTrack` method][1], changing its direction to `sendonly`. /// /// Returns [`HashMap`] with [`media_exchange_state::Stable`]s updates for /// the [`Sender`]s. @@ -681,14 +678,14 @@ impl MediaConnections { /// # Errors /// /// With [`MediaConnectionsError::InvalidMediaTracks`] if provided - /// [`HashMap`] doesn't contain required [`MediaStreamTrack`]. + /// [`HashMap`] doesn't contain required [`local::Track`]. /// /// With [`MediaConnectionsError::InvalidMediaTrack`] if some - /// [`MediaStreamTrack`] cannot be inserted into associated [`Sender`] - /// because of constraints mismatch. + /// [`local::Track`] cannot be inserted into associated [`Sender`] because + /// of constraints mismatch. /// /// With [`MediaConnectionsError::CouldNotInsertLocalTrack`] if some - /// [`MediaStreamTrack`] cannot be inserted into provided [`Sender`]s + /// [`local::Track`] cannot be inserted into provided [`Sender`]s /// transceiver. /// /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index a7dfe6983..dc11223d1 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -230,8 +230,8 @@ impl Receiver { } } - /// Updates [`TransceiverDirection`] and underlying [`MediaStreamTrack`] - /// based on the provided [`media_exchange_state::Stable`]. + /// Updates [`TransceiverDirection`] and underlying [`local::Track`] based + /// on the provided [`media_exchange_state::Stable`]. fn update_general_media_exchange_state( &self, new_state: media_exchange_state::Stable, @@ -280,6 +280,17 @@ impl MediaStateControllable for Receiver { } fn mute_state_controller(&self) -> Rc { + // Receivers can be muted, but currently they are muted directly by + // server events. + // + // There is no point to provide external API for muting receivers, since + // muting is pipelined after demuxing and decoding, so it wont reduce + // incoming traffic or CPU usage. Therefore receivers muting do not + // require MuteStateController's state management. + // + // Removing this unreachable! would require abstracting + // MuteStateController to some trait and creating some dummy + // implementation. Not worth it atm. unreachable!("Receivers muting is not implemented"); } diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index 094483140..2174a4dad 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -190,10 +190,10 @@ impl Sender { self.mute_state.update(muted.into()); match mute_state::Stable::from(muted) { mute_state::Stable::Unmuted => { - self.transceiver.set_sender_enabled(true); + self.transceiver.set_send_track_enabled(true); } mute_state::Stable::Muted => { - self.transceiver.set_sender_enabled(false); + self.transceiver.set_send_track_enabled(false); } } } @@ -316,12 +316,12 @@ impl MediaStateControllable for Sender { fn media_exchange_state_controller( &self, ) -> Rc { - self.media_exchange_state.clone() + Rc::clone(&self.media_exchange_state) } #[inline] fn mute_state_controller(&self) -> Rc { - self.mute_state.clone() + Rc::clone(&self.mute_state) } /// Sets current [`MediaExchangeState`] to diff --git a/jason/src/peer/media/transitable_state/mod.rs b/jason/src/peer/media/transitable_state/mod.rs index 749b50265..c478308c4 100644 --- a/jason/src/peer/media/transitable_state/mod.rs +++ b/jason/src/peer/media/transitable_state/mod.rs @@ -26,14 +26,18 @@ pub type MuteState = /// All media states which can be toggled in the [`MediaStateControllable`]. #[derive(Clone, Copy, Debug, From)] pub enum MediaState { - /// Sets `MediaStreamTrack.enabled` to the `true` of `false`. + /// Responsible for changing [enabled][1] property of [MediaStreamTrack][2]. /// - /// Doesn't requires renegotiation process, but traffic flow doesn't stops. + /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled + /// [2]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack Mute(mute_state::Stable), - /// Drops `MediaStreamTrack` if [`media_exchange_state::Stable::Disabled`]. + /// Responsible for changing [RTCRtpTransceiverDirection][1] to stop + /// traffic flow. /// - /// Requires renegotiation process and traffic flow will be stopped. + /// Requires renegotiation for changes to take effect. + /// + /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtptransceiverdirection MediaExchange(media_exchange_state::Stable), } diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index aca08ff30..f82affb74 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -77,8 +77,8 @@ pub enum PeerError { #[display(fmt = "{}", _0)] RtcPeerConnection(#[js(cause)] RTCPeerConnectionError), - /// Errors that may occur when validating [`TracksRequest`] or - /// parsing [`MediaStreamTrack`]s. + /// Errors that may occur when validating [`TracksRequest`] or parsing + /// [`loca::Track`]s. #[display(fmt = "{}", _0)] TracksRequest(#[js(cause)] TracksRequestError), } @@ -116,20 +116,20 @@ pub enum PeerEvent { sdp_mid: Option, }, - /// [`RtcPeerConnection`] received new [`MediaStreamTrack`] from remote + /// [`RtcPeerConnection`] received new [`remote::Track`] from remote /// sender. NewRemoteTrack { /// Remote `Member` ID. sender_id: MemberId, - /// Received [`MediaStreamTrack`]. + /// Received [`remote::Track`]. track: remote::Track, }, /// [`RtcPeerConnection`] sent new local track to remote members. NewLocalTrack { - /// Local [`MediaStreamTrack`] that is sent to remote members. - local_track: local::JsTrack, + /// Local [`local::Track`] that is sent to remote members. + local_track: Rc, }, /// [`RtcPeerConnection`]'s [ICE connection][1] state changed. @@ -725,12 +725,10 @@ impl PeerConnection { .await .map_err(tracerr::map_from_and_wrap!())?; - for (track, is_new) in media_tracks { + for (local_track, is_new) in media_tracks { if is_new { let _ = self.peer_events_sender.unbounded_send( - PeerEvent::NewLocalTrack { - local_track: local::JsTrack::new(track), - }, + PeerEvent::NewLocalTrack { local_track }, ); } } diff --git a/jason/src/peer/tracks_request.rs b/jason/src/peer/tracks_request.rs index 1c97a4839..909533ee3 100644 --- a/jason/src/peer/tracks_request.rs +++ b/jason/src/peer/tracks_request.rs @@ -10,8 +10,7 @@ use tracerr::Traced; use crate::{ media::{ - track::local::{self}, - AudioTrackConstraints, MediaKind, MediaStreamSettings, + track::local, AudioTrackConstraints, MediaKind, MediaStreamSettings, TrackConstraints, VideoSource, }, utils::{JsCaused, JsError}, @@ -152,7 +151,7 @@ impl SimpleTracksRequest { MediaKind::Audio => { audio_tracks.push(track); } - MediaKind::Video => match track.source_kind() { + MediaKind::Video => match track.media_source_kind() { MediaSourceKind::Device => { device_video_tracks.push(track); } diff --git a/jason/src/peer/transceiver.rs b/jason/src/peer/transceiver.rs index 52403001c..25adb7ec7 100644 --- a/jason/src/peer/transceiver.rs +++ b/jason/src/peer/transceiver.rs @@ -76,13 +76,10 @@ impl Transceiver { self.send_track.borrow().clone() } - /// Sets underlying [`local::Track`] `enabled` field to the provided - /// `is_enabled`. - /// - /// No-op if [`Transceiver::send_track`] is currently [`None`]. - pub fn set_sender_enabled(&self, is_enabled: bool) { + /// Sets underlying [`local::Track`] `enabled` field to the provided if any. + pub fn set_send_track_enabled(&self, enabled: bool) { if let Some(track) = self.send_track.borrow().as_ref() { - track.set_enabled(is_enabled); + track.set_enabled(enabled); } } } diff --git a/jason/tests/media/constraints.rs b/jason/tests/media/constraints.rs index 4c4375477..2df7b2fe8 100644 --- a/jason/tests/media/constraints.rs +++ b/jason/tests/media/constraints.rs @@ -537,10 +537,16 @@ async fn simultaneous_device_and_display() { assert!( display_video_constraints.satisfies(display_video_track.sys_track()) ); - assert_eq!(display_video_track.source_kind(), MediaSourceKind::Display); + assert_eq!( + display_video_track.media_source_kind(), + MediaSourceKind::Display + ); let device_video_track = video.pop().unwrap().0; assert_eq!(device_video_track.kind(), MediaKind::Video); assert!(device_video_constraints.satisfies(device_video_track.sys_track())); - assert_eq!(device_video_track.source_kind(), MediaSourceKind::Device); + assert_eq!( + device_video_track.media_source_kind(), + MediaSourceKind::Device + ); } From bf00c19b234ca7a0c6603de60e197f9d223cd963 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Wed, 25 Nov 2020 15:54:18 +0300 Subject: [PATCH 41/44] Fix private intra-doc [run ci] --- jason/src/api/room.rs | 24 +++++++++++++++---- jason/src/media/track/remote.rs | 4 ++-- jason/src/peer/media/receiver.rs | 2 ++ jason/src/peer/media/sender.rs | 10 +++----- .../media/transitable_state/controller.rs | 2 ++ src/signalling/peers/mod.rs | 2 +- 6 files changed, 29 insertions(+), 15 deletions(-) diff --git a/jason/src/api/room.rs b/jason/src/api/room.rs index 300df84b9..1ec124916 100644 --- a/jason/src/api/room.rs +++ b/jason/src/api/room.rs @@ -705,11 +705,11 @@ struct InnerRoom { /// Client to talk with media server via Client API RPC. rpc: Rc, - /// Constraints to local [`MediaStreamTrack`]s that are being published by + /// Constraints to local [`local::Track`]s that are being published by /// [`PeerConnection`]s in this [`Room`]. send_constraints: LocalTracksConstraints, - /// Constraints to the [`MediaStreamTrack`] received by [`PeerConnection`]s + /// Constraints to the [`remote::Track`] received by [`PeerConnection`]s /// in this [`Room`]. Used to disable or enable media receiving. recv_constraints: Rc, @@ -720,13 +720,15 @@ struct InnerRoom { peer_event_sender: mpsc::UnboundedSender, /// Collection of [`Connection`]s with a remote `Member`s. + /// + /// [`Connection`]: crate::api::Connection connections: Connections, /// Callback to be invoked when new local [`local::JsTrack`] will be added /// to this [`Room`]. on_local_track: Callback1, - /// Callback to be invoked when failed obtain [`MediaStreamTrack`]s from + /// Callback to be invoked when failed obtain [`local::Track`]s from /// [`MediaManager`] or failed inject stream into [`PeerConnection`]. /// /// [`MediaManager`]: crate::media::MediaManager @@ -912,6 +914,9 @@ impl InnerRoom { /// Returns `true` if all [`Sender`]s or [`Receiver`]s with a provided /// [`MediaKind`] and [`MediaSourceKind`] of this [`Room`] are in the /// provided [`MediaState`]. + /// + /// [`Sender`]: crate::peer::Sender + /// [`Receiver`]: crate::peer::Receiver pub fn is_all_peers_in_media_state( &self, kind: MediaKind, @@ -936,14 +941,14 @@ impl InnerRoom { /// Updates this [`Room`]s [`MediaStreamSettings`]. This affects all /// [`PeerConnection`]s in this [`Room`]. If [`MediaStreamSettings`] is /// configured for some [`Room`], then this [`Room`] can only send - /// [`MediaStream`] that corresponds to this settings. + /// [`local::Track`]s that corresponds to this settings. /// [`MediaStreamSettings`] update will change [`local::Track`]s in all /// sending peers, so that might cause new [getUserMedia()][1] request. /// /// Media obtaining/injection errors are fired to `on_failed_local_media` /// callback. /// - /// Will update [`media_exchange_state::State`]s of the [`Sender`]s which + /// Will update [`media_exchange_state::Stable`]s of the [`Sender`]s which /// are should be enabled or disabled. /// /// [1]: https://tinyurl.com/rnxcavf @@ -1052,6 +1057,8 @@ impl EventHandler for InnerRoom { /// /// If provided `sdp_offer` is `Some`, then offer is applied to a created /// peer, and [`Command::MakeSdpAnswer`] is emitted back to the RPC server. + /// + /// [`Connection`]: crate::api::Connection async fn on_peer_created( &self, peer_id: PeerId, @@ -1192,6 +1199,10 @@ impl EventHandler for InnerRoom { /// Updates [`Connection`]'s [`ConnectionQualityScore`] by calling /// [`Connection::update_quality_score`]. + /// + /// [`Connection`]: crate::api::Connection + /// [`Connection::update_quality_score`]: + /// crate::api::Connection::update_quality_score async fn on_connection_quality_updated( &self, partner_member_id: MemberId, @@ -1244,6 +1255,9 @@ impl PeerEventHandler for InnerRoom { /// Handles [`PeerEvent::NewRemoteTrack`] event and passes received /// [`remote::Track`] to the related [`Connection`]. + /// + /// [`Stream`]: futures::stream::Stream + /// [`Connection`]: crate::api::Connection async fn on_new_remote_track( &self, sender_id: MemberId, diff --git a/jason/src/media/track/remote.rs b/jason/src/media/track/remote.rs index 86d4a8718..c19901fc9 100644 --- a/jason/src/media/track/remote.rs +++ b/jason/src/media/track/remote.rs @@ -22,10 +22,10 @@ struct Inner { /// Underlying [`SysMediaStreamTrack`] source kind. media_source_kind: MediaSourceKind, - /// Callback to be invoked when this [`remote::Track`] is enabled. + /// Callback to be invoked when this [`Track`] is enabled. on_enabled: Callback0, - /// Callback to be invoked when this [`remote::Track`] is disabled. + /// Callback to be invoked when this [`Track`] is disabled. on_disabled: Callback0, /// [enabled][1] property of [MediaStreamTrack][2]. diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index 876cff737..18e9a37bc 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -232,6 +232,8 @@ impl Receiver { /// Updates [`TransceiverDirection`] and underlying [`local::Track`] based /// on the provided [`media_exchange_state::Stable`]. + /// + /// [`local::Track`]: crate::media::track::local::Track fn update_general_media_exchange_state( &self, new_state: media_exchange_state::Stable, diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index 13eab062e..59bb72cf2 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -107,15 +107,11 @@ impl Sender { } /// Updates [`Sender`]s general media exchange state based on the provided - /// [`StableMediaExchangeState`]. + /// [`media_exchange_state::Stable`]. /// /// Sets [`Sender`]s underlying transceiver direction to - /// [`TransceiverDirection::Inactive`] if provided media exchange state is - /// [`StableMediaExchangeState::Disabled`]. - /// - /// Emits [`PeerEvent::NewLocalStreamRequired`] if new state is - /// [`StableMediaExchangeState::Enabled`] and [`Sender`] does not have a - /// track to send. + /// [`TransceiverDirection::INACTIVE`] if provided media exchange state is + /// [`media_exchange_state::Stable::Disabled`]. fn update_general_media_exchange_state( &self, media_exchange_state: media_exchange_state::Stable, diff --git a/jason/src/peer/media/transitable_state/controller.rs b/jason/src/peer/media/transitable_state/controller.rs index 933b28196..f3ecdba61 100644 --- a/jason/src/peer/media/transitable_state/controller.rs +++ b/jason/src/peer/media/transitable_state/controller.rs @@ -59,6 +59,8 @@ where /// Spawns all needed [`Stream`] listeners for this /// [`TransitableStateController`]. + /// + /// [`Stream`]: futures::stream::Stream fn spawn(self: Rc) { // we don't care about initial state, cause transceiver is inactive atm let mut state_changes = self.state.subscribe().skip(1); diff --git a/src/signalling/peers/mod.rs b/src/signalling/peers/mod.rs index 385085e61..171c15847 100644 --- a/src/signalling/peers/mod.rs +++ b/src/signalling/peers/mod.rs @@ -466,7 +466,7 @@ impl PeersService { /// Creates and sets [`IceUser`], registers [`Peer`] in /// [`PeerTrafficWatcher`]. /// - /// [`IceUser`]: crate::media::ice_user::IceUser + /// [`IceUser`]: crate::turn::ice_user::IceUser async fn peer_post_construct( &self, peer_id: PeerId, From 2f6263e6bbddfcf81654354c0b712cfeb2122356 Mon Sep 17 00:00:00 2001 From: alexlapa Date: Wed, 25 Nov 2020 17:02:11 +0200 Subject: [PATCH 42/44] refactor [run ci] --- Cargo.lock | 24 +++++++++++----------- jason/src/media/manager.rs | 2 +- jason/src/media/track/local.rs | 34 ++++++++++++++++---------------- jason/src/media/track/remote.rs | 22 ++++++++++----------- jason/src/peer/media/mod.rs | 7 ++----- jason/src/peer/media/receiver.rs | 8 ++++---- jason/src/peer/media/sender.rs | 15 +++++++------- 7 files changed, 54 insertions(+), 58 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 08f847cbc..8cbf99bf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -84,9 +84,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "404df68c297f73b8d36c9c9056404913d25905a8f80127b0e5fe147c9c4b9f02" +checksum = "452299e87817ae5673910e53c243484ca38be3828db819b6011736fc6982e874" dependencies = [ "actix-codec", "actix-connect", @@ -260,9 +260,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88344b7a5ef27e5e09e73565379f69273dd3e2d29e82afc381b84d170d0a5631" +checksum = "3a89a7b133e734f6d1e555502d450408ae04105826aef7e3605019747d3ac732" dependencies = [ "actix-codec", "actix-http", @@ -549,9 +549,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "awc" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "425980a1e58e5030a3e4b065a3d577c8f0e16142ea9d81f30614eae810c98577" +checksum = "e9056f5e27b0d56bedd82f78eceaba0bcddcbbcbbefae3cd0a53994b28c96ff5" dependencies = [ "actix-codec", "actix-http", @@ -2703,14 +2703,14 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ - "dtoa", + "form_urlencoded", "itoa", + "ryu", "serde 1.0.117", - "url", ] [[package]] @@ -3571,9 +3571,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8716a166f290ff49dabc18b44aa407cb7c6dbe1aa0971b44b8a24b0ca35aae" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" [[package]] name = "unicode-width" diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 3b3de29ae..72607f50d 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -1,5 +1,5 @@ //! Acquiring and storing [`local::Track`]s. -/// [`local::Track`]: crate::media::track::local::Track + use std::{ cell::RefCell, collections::HashMap, diff --git a/jason/src/media/track/local.rs b/jason/src/media/track/local.rs index b3f7f294e..90813815f 100644 --- a/jason/src/media/track/local.rs +++ b/jason/src/media/track/local.rs @@ -1,17 +1,17 @@ -//! Implementation of the wrapper around [`SysMediaStreamTrack`] received from +//! Implementation of the wrapper around [`sys::MediaStreamTrack`] received from //! the gUM/gDM request. use std::rc::Rc; use medea_client_api_proto::MediaSourceKind; use wasm_bindgen::prelude::*; -use web_sys::MediaStreamTrack as SysMediaStreamTrack; +use web_sys as sys; use crate::{media::MediaKind, JsMediaSourceKind}; -/// Wrapper around [`SysMediaStreamTrack`] received from the gUM/gDM request. +/// Wrapper around [`sys::MediaStreamTrack`] received from the gUM/gDM request. /// -/// Underlying [`SysMediaStreamTrack`] is stopped on [`Track`] [`Drop`]. +/// Underlying [`sys::MediaStreamTrack`] is stopped on [`Track`] [`Drop`]. #[derive(Debug)] pub struct Track { /// Reference to the parent [`Track`]. @@ -22,21 +22,21 @@ pub struct Track { /// This field used only for holding strong reference to the parent. _parent: Option>, - /// Actual [`SysMediaStreamTrack`]. - track: SysMediaStreamTrack, + /// Actual [`sys::MediaStreamTrack`]. + track: sys::MediaStreamTrack, - /// Underlying [`SysMediaStreamTrack`] source kind. + /// Underlying [`sys::MediaStreamTrack`] source kind. source_kind: MediaSourceKind, - /// Underlying [`SysMediaStreamTrack`] kind. + /// Underlying [`sys::MediaStreamTrack`] kind. kind: MediaKind, } impl Track { - /// Builds [`Track`] from provided [`SysMediaStreamTrack`] and + /// Builds [`Track`] from provided [`sys::MediaStreamTrack`] and /// [`MediaSourceKind`]. pub fn new( - track: SysMediaStreamTrack, + track: sys::MediaStreamTrack, source_kind: MediaSourceKind, ) -> Self { let kind = match track.kind().as_ref() { @@ -81,15 +81,15 @@ impl Track { /// Forks this [`Track`]. /// - /// Creates new [`SysMediaStreamTrack`] from this [`Track`] - /// [`SysMediaStreamTrack`] using [`clone`][1] method. + /// Creates new [`sys::MediaStreamTrack`] from this [`Track`] + /// [`sys::MediaStreamTrack`] using [`clone`][1] method. /// /// Forked [`Track`] holds strong reference to this [`Track`]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-clone pub fn fork(self: &Rc) -> Self { let parent = Rc::clone(self); - let track = SysMediaStreamTrack::clone(&self.track); + let track = sys::MediaStreamTrack::clone(&self.track); Self { _parent: Some(parent), track, @@ -98,8 +98,8 @@ impl Track { } } - /// Returns reference to the [`SysMediaStreamTrack`]. - pub fn sys_track(&self) -> &SysMediaStreamTrack { + /// Returns reference to the [`sys::MediaStreamTrack`]. + pub fn sys_track(&self) -> &sys::MediaStreamTrack { &self.track } } @@ -123,8 +123,8 @@ impl JsTrack { #[wasm_bindgen(js_class = LocalMediaTrack)] impl JsTrack { - /// Returns underlying [`SysMediaStreamTrack`] from this [`JsTrack`]. - pub fn get_track(&self) -> SysMediaStreamTrack { + /// Returns underlying [`sys::MediaStreamTrack`] from this [`JsTrack`]. + pub fn get_track(&self) -> sys::MediaStreamTrack { Clone::clone(self.0.track.as_ref()) } diff --git a/jason/src/media/track/remote.rs b/jason/src/media/track/remote.rs index c19901fc9..e905c7cf6 100644 --- a/jason/src/media/track/remote.rs +++ b/jason/src/media/track/remote.rs @@ -1,4 +1,4 @@ -//! Implementation of the wrapper around [`SysMediaStreamTrack`] received from +//! Implementation of the wrapper around [`sys::MediaStreamTrack`] received from //! the remote. use std::rc::Rc; @@ -8,18 +8,18 @@ use medea_client_api_proto::MediaSourceKind; use medea_reactive::ObservableCell; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::spawn_local; -use web_sys::MediaStreamTrack as SysMediaStreamTrack; +use web_sys as sys; use crate::{media::MediaKind, utils::Callback0, JsMediaSourceKind}; struct Inner { - /// Underlying JS-side [`SysMediaStreamTrack`]. - track: SysMediaStreamTrack, + /// Underlying JS-side [`sys::MediaStreamTrack`]. + track: sys::MediaStreamTrack, - /// Underlying [`SysMediaStreamTrack`] kind. + /// Underlying [`sys::MediaStreamTrack`] kind. kind: MediaKind, - /// Underlying [`SysMediaStreamTrack`] source kind. + /// Underlying [`sys::MediaStreamTrack`] source kind. media_source_kind: MediaSourceKind, /// Callback to be invoked when this [`Track`] is enabled. @@ -47,9 +47,9 @@ impl Track { /// changes. pub fn new(track: T, media_source_kind: MediaSourceKind) -> Self where - SysMediaStreamTrack: From, + sys::MediaStreamTrack: From, { - let track = SysMediaStreamTrack::from(track); + let track = sys::MediaStreamTrack::from(track); let kind = match track.kind().as_ref() { "audio" => MediaKind::Audio, "video" => MediaKind::Video, @@ -97,7 +97,7 @@ impl Track { /// Sets [`Track::enabled`] to the provided value. /// - /// Updates `enabled` in the underlying [`SysMediaStreamTrack`]. + /// Updates `enabled` in the underlying [`sys::MediaStreamTrack`]. #[inline] pub fn set_enabled(&self, enabled: bool) { self.0.enabled.set(enabled); @@ -128,8 +128,8 @@ impl Track { #[wasm_bindgen(js_class = RemoteMediaTrack)] impl Track { - /// Returns underlying [`SysMediaStreamTrack`] from this [`Track`]. - pub fn get_track(&self) -> SysMediaStreamTrack { + /// Returns underlying [`sys::MediaStreamTrack`] from this [`Track`]. + pub fn get_track(&self) -> sys::MediaStreamTrack { Clone::clone(&self.0.track) } diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index a403686b6..19c326bcc 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -4,7 +4,7 @@ mod receiver; mod sender; -pub mod transitable_state; +mod transitable_state; use std::{cell::RefCell, collections::HashMap, convert::From, rc::Rc}; @@ -17,10 +17,7 @@ use tracerr::Traced; use web_sys::RtcTrackEvent; use crate::{ - media::{ - track::local::{self}, - LocalTracksConstraints, MediaKind, RecvConstraints, - }, + media::{track::local, LocalTracksConstraints, MediaKind, RecvConstraints}, peer::{ transceiver::Transceiver, LocalStreamUpdateCriteria, PeerEvent, TransceiverDirection, diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index 18e9a37bc..920ba3b29 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -9,7 +9,7 @@ use futures::channel::mpsc; use medea_client_api_proto as proto; use medea_client_api_proto::{MediaSourceKind, MemberId, TrackPatchEvent}; use proto::TrackId; -use web_sys::MediaStreamTrack as SysMediaStreamTrack; +use web_sys as sys; use crate::{ media::{track::remote, MediaKind, RecvConstraints, TrackConstraints}, @@ -133,15 +133,15 @@ impl Receiver { enabled && is_recv_direction } - /// Adds provided [`SysMediaStreamTrack`] and [`Transceiver`] to this + /// Adds provided [`sys::MediaStreamTrack`] and [`Transceiver`] to this /// [`Receiver`]. /// - /// Sets [`SysMediaStreamTrack::enabled`] same as [`Receiver::enabled`] of + /// Sets [`sys::MediaStreamTrack::enabled`] same as [`Receiver::enabled`] of /// this [`Receiver`]. pub fn set_remote_track( &self, transceiver: Transceiver, - new_track: SysMediaStreamTrack, + new_track: sys::MediaStreamTrack, ) { if let Some(old_track) = self.track.borrow().as_ref() { if old_track.id() == new_track.id() { diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index 59bb72cf2..60b88d168 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -63,16 +63,15 @@ impl<'a> SenderBuilder<'a> { .map_err(tracerr::wrap!())?, }; - let media_exchange_state_controller = + let media_exchange_state = MediaExchangeStateController::new(self.media_exchange_state); - let mute_state_controller = MuteStateController::new(self.mute_state); let this = Rc::new(Sender { track_id: self.track_id, caps: self.caps, general_media_exchange_state: Cell::new(self.media_exchange_state), - mute_state: mute_state_controller, + mute_state: MuteStateController::new(self.mute_state), transceiver, - media_exchange_state: media_exchange_state_controller, + media_exchange_state, required: self.required, send_constraints: self.send_constraints, }); @@ -114,11 +113,11 @@ impl Sender { /// [`media_exchange_state::Stable::Disabled`]. fn update_general_media_exchange_state( &self, - media_exchange_state: media_exchange_state::Stable, + new_state: media_exchange_state::Stable, ) { - if self.general_media_exchange_state.get() != media_exchange_state { - self.general_media_exchange_state.set(media_exchange_state); - match media_exchange_state { + if self.general_media_exchange_state.get() != new_state { + self.general_media_exchange_state.set(new_state); + match new_state { media_exchange_state::Stable::Enabled => { if self.enabled_in_cons() { self.transceiver From 95bc1cbb1be7611324acc2f17f2ef9aed6d71b73 Mon Sep 17 00:00:00 2001 From: alexlapa Date: Wed, 25 Nov 2020 17:33:04 +0200 Subject: [PATCH 43/44] refactor --- jason/src/api/room.rs | 5 ++--- jason/src/media/constraints.rs | 9 ++------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/jason/src/api/room.rs b/jason/src/api/room.rs index 1ec124916..a64102d0c 100644 --- a/jason/src/api/room.rs +++ b/jason/src/api/room.rs @@ -1198,11 +1198,10 @@ impl EventHandler for InnerRoom { } /// Updates [`Connection`]'s [`ConnectionQualityScore`] by calling - /// [`Connection::update_quality_score`]. + /// [`Connection::update_quality_score`][1]. /// /// [`Connection`]: crate::api::Connection - /// [`Connection::update_quality_score`]: - /// crate::api::Connection::update_quality_score + /// [1]: crate::api::Connection::update_quality_score async fn on_connection_quality_updated( &self, partner_member_id: MemberId, diff --git a/jason/src/media/constraints.rs b/jason/src/media/constraints.rs index 71c8477c7..7d8ea16b0 100644 --- a/jason/src/media/constraints.rs +++ b/jason/src/media/constraints.rs @@ -97,13 +97,8 @@ impl LocalTracksConstraints { self.0.borrow().clone() } - /// Enables or disables (mutes or unmutes) audio or video type in underlying - /// [`MediaStreamSettings`]. - /// - /// Doesn't do anything if no [`MediaStreamSettings`] was set. - /// - /// If some type of the [`MediaStreamSettings`] is disabled, then this kind - /// of media won't be published. + /// Changes underlying [`MediaStreamSettings`] based on provided + /// [`MediaState`]. #[inline] pub fn set_media_state( &self, From b259d3ec6f8d0f56e224d959b028bfec85c65063 Mon Sep 17 00:00:00 2001 From: tyranron Date: Thu, 26 Nov 2020 12:10:34 +0200 Subject: [PATCH 44/44] Corrections --- jason/src/api/room.rs | 12 +-- jason/src/media/constraints.rs | 19 ++-- jason/src/media/track/local.rs | 87 ++++++++++++------- jason/src/media/track/mod.rs | 4 +- jason/src/media/track/remote.rs | 52 ++++++----- jason/src/peer/media/mod.rs | 42 ++++++--- jason/src/peer/media/receiver.rs | 8 +- jason/src/peer/media/sender.rs | 16 +++- .../media/transitable_state/controller.rs | 48 ++++++---- .../transitable_state/media_exchange_state.rs | 13 +-- jason/src/peer/media/transitable_state/mod.rs | 24 +++-- .../media/transitable_state/mute_state.rs | 12 +-- jason/src/peer/mod.rs | 40 ++++++--- jason/src/peer/transceiver.rs | 3 +- src/media/peer.rs | 6 +- 15 files changed, 251 insertions(+), 135 deletions(-) diff --git a/jason/src/api/room.rs b/jason/src/api/room.rs index a64102d0c..0aa5ee5ed 100644 --- a/jason/src/api/room.rs +++ b/jason/src/api/room.rs @@ -304,8 +304,8 @@ impl RoomHandle { upgrade_or_detached!(self.0).map(|inner| inner.on_close.set_func(f)) } - /// Sets callback, which will be invoked when new [`local::Track`] - /// will be added to this [`Room`]. + /// Sets callback, which will be invoked when new [`local::Track`] will be + /// added to this [`Room`]. /// This might happen in such cases: /// 1. Media server initiates media request. /// 2. `disable_audio`/`enable_video` is called. @@ -384,8 +384,8 @@ impl RoomHandle { /// [`MediaKind`], [`TrackDirection`] and [`JsMediaSourceKind`] to the /// provided [`MediaState`]. /// - /// Helper function for all exported mute/unmute/enable/disable audio/video - /// send/receive methods. + /// Helper function for all the exported mute/unmute/enable/disable + /// audio/video send/receive methods. fn change_media_state( &self, media_state: S, @@ -1198,7 +1198,7 @@ impl EventHandler for InnerRoom { } /// Updates [`Connection`]'s [`ConnectionQualityScore`] by calling - /// [`Connection::update_quality_score`][1]. + /// [`Connection::update_quality_score()`][1]. /// /// [`Connection`]: crate::api::Connection /// [1]: crate::api::Connection::update_quality_score @@ -1255,8 +1255,8 @@ impl PeerEventHandler for InnerRoom { /// Handles [`PeerEvent::NewRemoteTrack`] event and passes received /// [`remote::Track`] to the related [`Connection`]. /// - /// [`Stream`]: futures::stream::Stream /// [`Connection`]: crate::api::Connection + /// [`Stream`]: futures::Stream async fn on_new_remote_track( &self, sender_id: MemberId, diff --git a/jason/src/media/constraints.rs b/jason/src/media/constraints.rs index 7d8ea16b0..9847b30b5 100644 --- a/jason/src/media/constraints.rs +++ b/jason/src/media/constraints.rs @@ -91,13 +91,14 @@ impl LocalTracksConstraints { self.0.borrow_mut().constrain(other) } - /// Clones underlying [`MediaStreamSettings`]. + /// Clones the underlying [`MediaStreamSettings`]. #[inline] + #[must_use] pub fn inner(&self) -> MediaStreamSettings { self.0.borrow().clone() } - /// Changes underlying [`MediaStreamSettings`] based on provided + /// Changes the underlying [`MediaStreamSettings`] basing on the provided /// [`MediaState`]. #[inline] pub fn set_media_state( @@ -114,6 +115,7 @@ impl LocalTracksConstraints { /// Indicates whether provided [`MediaType`] is enabled in the underlying /// [`MediaStreamSettings`]. #[inline] + #[must_use] pub fn enabled(&self, kind: &MediaType) -> bool { self.0.borrow().enabled(kind) } @@ -121,6 +123,7 @@ impl LocalTracksConstraints { /// Indicates whether provided [`MediaType`] is muted in the underlying /// [`MediaStreamSettings`]. #[inline] + #[must_use] pub fn muted(&self, kind: &MediaType) -> bool { self.0.borrow().muted(kind) } @@ -128,6 +131,7 @@ impl LocalTracksConstraints { /// Indicates whether provided [`MediaKind`] and [`MediaSourceKind`] are /// enabled in this [`LocalTracksConstraints`]. #[inline] + #[must_use] pub fn is_track_enabled( &self, kind: MediaKind, @@ -425,14 +429,14 @@ impl MediaStreamSettings { } } - /// Sets the underlying [`AudioMediaTracksSettings::muted`] to the - /// given value. + /// Sets the underlying [`AudioMediaTracksSettings::muted`] to the provided + /// value. fn set_audio_muted(&mut self, muted: bool) { self.audio.muted = muted; } - /// Sets underlying [`VideoTrackConstraints::muted`] based on provided - /// [`MediaSourceKind`] to the given value. + /// Sets the underlying [`VideoTrackConstraints::muted`] basing on the + /// provided [`MediaSourceKind`] to the given value. fn set_video_muted( &mut self, muted: bool, @@ -518,6 +522,7 @@ impl MediaStreamSettings { /// Indicates whether the given [`MediaType`] is muted in this /// [`MediaStreamSettings`]. #[inline] + #[must_use] pub fn muted(&self, kind: &MediaType) -> bool { match kind { MediaType::Video(video) => match video.source_kind { @@ -530,6 +535,8 @@ impl MediaStreamSettings { /// Indicates whether the given [`MediaKind`] and [`MediaSourceKind`] are /// enabled in this [`MediaStreamSettings`]. + #[inline] + #[must_use] pub fn is_track_enabled( &self, kind: MediaKind, diff --git a/jason/src/media/track/local.rs b/jason/src/media/track/local.rs index 90813815f..fea609f3c 100644 --- a/jason/src/media/track/local.rs +++ b/jason/src/media/track/local.rs @@ -1,5 +1,8 @@ -//! Implementation of the wrapper around [`sys::MediaStreamTrack`] received from -//! the gUM/gDM request. +//! Wrapper around [`sys::MediaStreamTrack`] received from +//! [getUserMedia()][1]/[getDisplayMedia()][2] request. +//! +//! [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia +//! [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia use std::rc::Rc; @@ -9,19 +12,16 @@ use web_sys as sys; use crate::{media::MediaKind, JsMediaSourceKind}; -/// Wrapper around [`sys::MediaStreamTrack`] received from the gUM/gDM request. +/// Wrapper around [`sys::MediaStreamTrack`] received from from +/// [getUserMedia()][1]/[getDisplayMedia()][2] request. /// -/// Underlying [`sys::MediaStreamTrack`] is stopped on [`Track`] [`Drop`]. +/// Underlying [`sys::MediaStreamTrack`] is stopped on this [`Track`]'s +/// [`Drop`]. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia +/// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia #[derive(Debug)] pub struct Track { - /// Reference to the parent [`Track`]. - /// - /// Parent will be [`None`] if this [`Track`] wasn't forked from another - /// [`Track`]. - /// - /// This field used only for holding strong reference to the parent. - _parent: Option>, - /// Actual [`sys::MediaStreamTrack`]. track: sys::MediaStreamTrack, @@ -30,11 +30,20 @@ pub struct Track { /// Underlying [`sys::MediaStreamTrack`] kind. kind: MediaKind, + + /// Reference to the parent [`Track`]. + /// + /// Parent will be [`None`] if this [`Track`] wasn't forked from another + /// [`Track`]. + /// + /// This field is used only for holding strong reference to the parent. + _parent: Option>, } impl Track { - /// Builds [`Track`] from provided [`sys::MediaStreamTrack`] and + /// Builds new [`Track`] from the provided [`sys::MediaStreamTrack`] and /// [`MediaSourceKind`]. + #[must_use] pub fn new( track: sys::MediaStreamTrack, source_kind: MediaSourceKind, @@ -45,10 +54,10 @@ impl Track { _ => unreachable!(), }; Self { - _parent: None, track, source_kind, kind, + _parent: None, } } @@ -57,65 +66,79 @@ impl Track { /// /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] pub fn set_enabled(&self, enabled: bool) { self.track.set_enabled(enabled); } - /// Returns [`id`][1] of underlying [MediaStreamTrack][2]. + /// Returns [`id`] of underlying [MediaStreamTrack][2]. /// - /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id + /// [`id`]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] + #[must_use] pub fn id(&self) -> String { self.track.id() } - /// Returns this [`Track`] media source kind. + /// Returns this [`Track`]'s media source kind. + #[inline] + #[must_use] pub fn media_source_kind(&self) -> MediaSourceKind { self.source_kind } - /// Returns [`Track`] kind (audio/video). + /// Returns this [`Track`]'s kind (audio/video). + #[inline] + #[must_use] pub fn kind(&self) -> MediaKind { self.kind } /// Forks this [`Track`]. /// - /// Creates new [`sys::MediaStreamTrack`] from this [`Track`] - /// [`sys::MediaStreamTrack`] using [`clone`][1] method. + /// Creates new [`sys::MediaStreamTrack`] from this [`Track`]'s + /// [`sys::MediaStreamTrack`] using [`clone()`][1] method. /// - /// Forked [`Track`] holds strong reference to this [`Track`]. + /// Forked [`Track`] will hold a strong reference to this [`Track`]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-clone + #[must_use] pub fn fork(self: &Rc) -> Self { let parent = Rc::clone(self); let track = sys::MediaStreamTrack::clone(&self.track); Self { - _parent: Some(parent), track, kind: self.kind, source_kind: self.source_kind, + _parent: Some(parent), } } - /// Returns reference to the [`sys::MediaStreamTrack`]. + /// Returns reference to the underlying [`sys::MediaStreamTrack`] of this + /// [`Track`]. + #[inline] + #[must_use] pub fn sys_track(&self) -> &sys::MediaStreamTrack { &self.track } } impl Drop for Track { + #[inline] fn drop(&mut self) { self.track.stop(); } } -/// Wrapper around strongly referenced [`Track`] for the JS side. +/// Wrapper around strongly referenced [`Track`] for JS side. #[wasm_bindgen(js_name = LocalMediaTrack)] pub struct JsTrack(Rc); impl JsTrack { - /// Creates new [`JsTrack`] from provided [`Track`]. + /// Creates new [`JsTrack`] from the provided [`Track`]. + #[inline] + #[must_use] pub fn new(track: Rc) -> Self { JsTrack(track) } @@ -123,22 +146,22 @@ impl JsTrack { #[wasm_bindgen(js_class = LocalMediaTrack)] impl JsTrack { - /// Returns underlying [`sys::MediaStreamTrack`] from this [`JsTrack`]. + /// Returns the underlying [`sys::MediaStreamTrack`] of this [`JsTrack`]. pub fn get_track(&self) -> sys::MediaStreamTrack { Clone::clone(self.0.track.as_ref()) } - /// Returns a [`MediaKind::Audio`] if the track is an audio track and to - /// [`MediaKind::Video`], if it is a video track. + /// Returns [`MediaKind::Audio`] if this [`JsTrack`] represents an audio + /// track, or [`MediaKind::Video`] if it represents a video track. pub fn kind(&self) -> MediaKind { self.0.kind() } - /// Returns [`JsMediaSourceKind::Device`] if track is sourced from some - /// device (webcam/microphone) and [`JsMediaSourceKind::Display`], if track - /// is captured via [MediaDevices.getDisplayMedia()][1]. + /// Returns [`JsMediaSourceKind::Device`] if this [`JsTrack`] is sourced + /// from some device (webcam/microphone), or [`JsMediaSourceKind::Display`] + /// if ot is captured via [MediaDevices.getDisplayMedia()][1]. /// - /// [1]: https://tinyurl.com/y2anfntz + /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia pub fn media_source_kind(&self) -> JsMediaSourceKind { self.0.media_source_kind().into() } diff --git a/jason/src/media/track/mod.rs b/jason/src/media/track/mod.rs index 212a2c369..1353d6748 100644 --- a/jason/src/media/track/mod.rs +++ b/jason/src/media/track/mod.rs @@ -1,6 +1,6 @@ //! [MediaStreamTrack][1] related objects. //! -//! [1]: https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack +//! [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub mod local; pub mod remote; @@ -20,6 +20,7 @@ pub enum JsMediaSourceKind { } impl From for MediaSourceKind { + #[inline] fn from(val: JsMediaSourceKind) -> Self { match val { JsMediaSourceKind::Device => Self::Device, @@ -29,6 +30,7 @@ impl From for MediaSourceKind { } impl From for JsMediaSourceKind { + #[inline] fn from(val: MediaSourceKind) -> Self { match val { MediaSourceKind::Device => Self::Device, diff --git a/jason/src/media/track/remote.rs b/jason/src/media/track/remote.rs index e905c7cf6..89ccf297e 100644 --- a/jason/src/media/track/remote.rs +++ b/jason/src/media/track/remote.rs @@ -1,5 +1,4 @@ -//! Implementation of the wrapper around [`sys::MediaStreamTrack`] received from -//! the remote. +//! Wrapper around [`sys::MediaStreamTrack`] received from the remote. use std::rc::Rc; @@ -12,6 +11,7 @@ use web_sys as sys; use crate::{media::MediaKind, utils::Callback0, JsMediaSourceKind}; +/// Inner reference-counted data of [`Track`]. struct Inner { /// Underlying JS-side [`sys::MediaStreamTrack`]. track: sys::MediaStreamTrack, @@ -28,7 +28,7 @@ struct Inner { /// Callback to be invoked when this [`Track`] is disabled. on_disabled: Callback0, - /// [enabled][1] property of [MediaStreamTrack][2]. + /// [`enabled`][1] property of [MediaStreamTrack][2]. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled /// [2]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack @@ -43,8 +43,11 @@ struct Inner { pub struct Track(Rc); impl Track { - /// Creates new [`Track`], spawns listener for `enabled` state - /// changes. + /// Creates new [`Track`] spawning a listener for its [`enabled`][1] + /// property changes. + /// + /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled + #[must_use] pub fn new(track: T, media_source_kind: MediaSourceKind) -> Self where sys::MediaStreamTrack: From, @@ -89,38 +92,45 @@ impl Track { track } - /// Returns `true` if this [`Track`] is enabled. + /// Indicates whether this [`Track`] is enabled. #[inline] + #[must_use] pub fn enabled(&self) -> &ObservableCell { &self.0.enabled } /// Sets [`Track::enabled`] to the provided value. /// - /// Updates `enabled` in the underlying [`sys::MediaStreamTrack`]. + /// Updates [`enabled`][1] property in the underlying + /// [`sys::MediaStreamTrack`]. + /// + /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled #[inline] pub fn set_enabled(&self, enabled: bool) { self.0.enabled.set(enabled); self.0.track.set_enabled(enabled); } - /// Returns [`id`][1] of underlying [MediaStreamTrack][2]. + /// Returns [`id`][1] of underlying [`sys::MediaStreamTrack`] of this + /// [`Track`]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id - /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack #[inline] + #[must_use] pub fn id(&self) -> String { self.0.track.id() } - /// Returns track kind (audio/video). + /// Returns this [`Track`]'s kind (audio/video). #[inline] + #[must_use] pub fn kind(&self) -> MediaKind { self.0.kind } - /// Returns this [`Track`] media source kind. + /// Returns this [`Track`]'s media source kind. #[inline] + #[must_use] pub fn media_source_kind(&self) -> MediaSourceKind { self.0.media_source_kind } @@ -128,39 +138,39 @@ impl Track { #[wasm_bindgen(js_class = RemoteMediaTrack)] impl Track { - /// Returns underlying [`sys::MediaStreamTrack`] from this [`Track`]. + /// Returns the underlying [`sys::MediaStreamTrack`] of this [`Track`]. pub fn get_track(&self) -> sys::MediaStreamTrack { Clone::clone(&self.0.track) } - /// Returns is this [`Track`] enabled. + /// Indicate whether this [`Track`] is enabled. #[wasm_bindgen(js_name = enabled)] pub fn js_enabled(&self) -> bool { self.0.enabled.get() } - /// Sets callback, which will be invoked when this [`Track`] is enabled. + /// Sets callback to invoke when this [`Track`] is enabled. pub fn on_enabled(&self, callback: js_sys::Function) { self.0.on_enabled.set_func(callback); } - /// Sets callback, which will be invoked when this [`Track`] is enabled. + /// Sets callback to invoke when this [`Track`] is disabled. pub fn on_disabled(&self, callback: js_sys::Function) { self.0.on_disabled.set_func(callback); } - /// Returns a [`MediaKind::Audio`] if the track is an audio track and to - /// [`MediaKind::Video`], if it is a video track. + /// Returns [`MediaKind::Audio`] if this [`Track`] represents an audio + /// track, or [`MediaKind::Video`] if it represents a video track. #[wasm_bindgen(js_name = kind)] pub fn js_kind(&self) -> MediaKind { self.kind() } - /// Returns [`JsMediaSourceKind::Device`] if track is sourced from some - /// device (webcam/microphone) and [`JsMediaSourceKind::Display`], if track - /// is captured via [MediaDevices.getDisplayMedia()][1]. + /// Returns [`JsMediaSourceKind::Device`] if this [`Track`] is sourced from + /// some device (webcam/microphone), or [`JsMediaSourceKind::Display`] if + /// it's captured via [MediaDevices.getDisplayMedia()][1]. /// - /// [1]: https://tinyurl.com/y2anfntz + /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia #[wasm_bindgen(js_name = media_source_kind)] pub fn js_media_source_kind(&self) -> JsMediaSourceKind { self.0.media_source_kind.into() diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index 19c326bcc..6118cf5f0 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -65,21 +65,25 @@ pub trait TransceiverSide: MediaStateControllable { /// [`MuteStateController`] for objects that use it. pub trait MediaStateControllable { /// Returns reference to the [`MediaExchangeStateController`]. + #[must_use] fn media_exchange_state_controller( &self, ) -> Rc; - /// Returns reference to the [`MuteStateController`]. + /// Returns a reference to the [`MuteStateController`]. + #[must_use] fn mute_state_controller(&self) -> Rc; /// Returns [`MediaExchangeState`] of this [`MediaStateControllable`]. #[inline] + #[must_use] fn media_exchange_state(&self) -> MediaExchangeState { self.media_exchange_state_controller().state() } /// Returns [`MuteState`] of this [`MediaStateControllable`]. #[inline] + #[must_use] fn mute_state(&self) -> MuteState { self.mute_state_controller().state() } @@ -108,10 +112,11 @@ pub trait MediaStateControllable { Ok(()) } - /// Returns `true` if [`Room`] should subscribe to the [`MediaState`] update + /// Indicates whether [`Room`] should subscribe to the [`MediaState`] update /// when updating [`MediaStateControllable`] to the provided [`MediaState`]. /// /// [`Room`]: crate::api::Room + #[must_use] fn is_subscription_needed(&self, desired_state: MediaState) -> bool { match desired_state { MediaState::MediaExchange(media_exchange) => { @@ -133,12 +138,13 @@ pub trait MediaStateControllable { } } - /// Returns `true` if [`Room`] should send [`TrackPatchCommand`] to the + /// Indicates whether [`Room`] should send [`TrackPatchCommand`] to the /// server when updating [`MediaStateControllable`] to the provided /// [`MediaState`]. /// /// [`TrackPatchCommand`]: medea_client_api_proto::TrackPatchCommand /// [`Room`]: crate::api::Room + #[must_use] fn is_track_patch_needed(&self, desired_state: MediaState) -> bool { match desired_state { MediaState::MediaExchange(media_exchange) => { @@ -164,17 +170,17 @@ pub trait MediaStateControllable { } } - /// Returns [`Future`] which will be resolved when [`MediaState`] of - /// this [`MediaStateControllable`] will be [`TransitableState::Stable`] or - /// it is dropped. + /// Returns [`Future`] which will be resolved when [`MediaState`] of this + /// [`MediaStateControllable`] will be [`TransitableState::Stable`] or it's + /// dropped. /// /// # Errors /// /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] - /// is returned if [`MediaState`] transits into the opposite to - /// the `desired_state`. + /// is returned if [`MediaState`] transits into the opposite to the + /// `desired_state`. /// - /// [`Future`]: futures::future::Future + /// [`Future`]: std::future::Future #[inline] fn when_media_state_stable( &self, @@ -405,9 +411,10 @@ impl MediaConnections { ) } - /// Returns `true` if all [`TransceiverSide`]s with provided - /// [`MediaKind`], [`TrackDirection`] and [`MediaSourceKind`] is in - /// provided [`MediaExchangeState`]. + /// Indicates whether all [`TransceiverSide`]s with provided [`MediaKind`], + /// [`TrackDirection`] and [`MediaSourceKind`] is in the provided + /// [`MediaExchangeState`]. + #[must_use] pub fn is_all_tracks_in_media_state( &self, kind: MediaKind, @@ -817,6 +824,7 @@ impl MediaConnections { impl MediaConnections { /// Indicates whether all [`Receiver`]s with [`MediaKind::Video`] are /// enabled. + #[must_use] pub fn is_recv_video_enabled(&self) -> bool { self.0 .borrow() @@ -827,6 +835,7 @@ impl MediaConnections { /// Indicates whether if all [`Receiver`]s with [`MediaKind::Audio`] are /// enabled. + #[must_use] pub fn is_recv_audio_enabled(&self) -> bool { self.0 .borrow() @@ -836,11 +845,13 @@ impl MediaConnections { } /// Returns [`Receiver`] with the provided [`TrackId`]. + #[must_use] pub fn get_receiver_by_id(&self, id: TrackId) -> Option> { self.0.borrow().receivers.get(&id).cloned() } /// Indicates whether all [`Sender`]s with [`MediaKind::Audio`] are enabled. + #[must_use] pub fn is_send_audio_enabled(&self) -> bool { self.0 .borrow() @@ -849,6 +860,7 @@ impl MediaConnections { } /// Indicates whether all [`Sender`]s with [`MediaKind::Video`] are enabled. + #[must_use] pub fn is_send_video_enabled( &self, source_kind: Option, @@ -862,7 +874,8 @@ impl MediaConnections { .all(|s| s.enabled()) } - /// Returns `true` if all [`Sender`]s video tracks are unmuted. + /// Indicates whether all [`Sender`]'s video tracks are unmuted. + #[must_use] pub fn is_send_video_unmuted( &self, source_kind: Option, @@ -877,7 +890,8 @@ impl MediaConnections { .is_none() } - /// Returns `true` if all [`Sender`]s audio tracks are unmuted. + /// Indicates whether all [`Sender`]'s audio tracks are unmuted. + #[must_use] pub fn is_send_audio_unmuted(&self) -> bool { self.0 .borrow() diff --git a/jason/src/peer/media/receiver.rs b/jason/src/peer/media/receiver.rs index 920ba3b29..324f10fa6 100644 --- a/jason/src/peer/media/receiver.rs +++ b/jason/src/peer/media/receiver.rs @@ -262,12 +262,16 @@ impl Receiver { } } - /// Returns `true` if this [`Receiver`] is enabled. + /// Indicates whether this [`Receiver`] is enabled. + #[inline] + #[must_use] pub fn enabled(&self) -> bool { self.media_exchange_state_controller.enabled() } - /// Returns `true` if this [`Receiver`] is disabled. + /// Indicates whether this [`Receiver`] is disabled. + #[inline] + #[must_use] pub fn disabled(&self) -> bool { self.media_exchange_state_controller.disabled() } diff --git a/jason/src/peer/media/sender.rs b/jason/src/peer/media/sender.rs index 60b88d168..d6d5b2323 100644 --- a/jason/src/peer/media/sender.rs +++ b/jason/src/peer/media/sender.rs @@ -253,24 +253,32 @@ impl Sender { #[cfg(feature = "mockable")] impl Sender { - /// Checks whether general media exchange state of the [`Sender`] is in + /// Indicates whether general media exchange state of this [`Sender`] is in /// [`StableMediaExchangeState::Disabled`]. + #[inline] + #[must_use] pub fn general_disabled(&self) -> bool { self.general_media_exchange_state.get() == media_exchange_state::Stable::Disabled } - /// Returns `true` if this [`Sender`] is disabled. + /// Indicates whether this [`Sender`] is disabled. + #[inline] + #[must_use] pub fn disabled(&self) -> bool { self.media_exchange_state.disabled() } - /// Returns `true` if this [`Sender`] is muted. + /// Indicates whether this [`Sender`] is muted. + #[inline] + #[must_use] pub fn muted(&self) -> bool { self.mute_state.muted() } - /// Returns `true` if this [`Sender`] is enabled. + /// Indicates whether this [`Sender`] is enabled. + #[inline] + #[must_use] pub fn enabled(&self) -> bool { self.media_exchange_state.enabled() } diff --git a/jason/src/peer/media/transitable_state/controller.rs b/jason/src/peer/media/transitable_state/controller.rs index f3ecdba61..b39c811dd 100644 --- a/jason/src/peer/media/transitable_state/controller.rs +++ b/jason/src/peer/media/transitable_state/controller.rs @@ -1,4 +1,4 @@ -//! Component that manages [`TransitableState`]. +//! Component managing [`TransitableState`]. use std::{cell::RefCell, rc::Rc, time::Duration}; @@ -21,13 +21,14 @@ use super::TransitableState; /// [`TransitableStateController`] for the [`mute_state`]. pub type MuteStateController = TransitableStateController; + /// [`TransitableStateController`] for the [`media_exchange_state`]. pub type MediaExchangeStateController = TransitableStateController< media_exchange_state::Stable, media_exchange_state::Transition, >; -/// Component that manages all kinds of [`TransitableState`]. +/// Component managing all kinds of [`TransitableState`]. pub struct TransitableStateController { /// Actual [`TransitableState`]. state: ObservableCell>, @@ -46,8 +47,9 @@ where #[cfg(feature = "mockable")] const TRANSITION_TIMEOUT: Duration = Duration::from_millis(500); - /// Returns new [`TransitableStateController`] with a provided + /// Returns new [`TransitableStateController`] with the provided /// [`InStable`] state. + #[must_use] pub(in super::super) fn new(state: S) -> Rc { let this = Rc::new(Self { state: ObservableCell::new(state.into()), @@ -57,12 +59,13 @@ where this } - /// Spawns all needed [`Stream`] listeners for this + /// Spawns all the required [`Stream`] listeners for this /// [`TransitableStateController`]. /// - /// [`Stream`]: futures::stream::Stream + /// [`Stream`]: futures::Stream fn spawn(self: Rc) { - // we don't care about initial state, cause transceiver is inactive atm + // We don't care about initial state, be cause transceiver is inactive + // at that moment. let mut state_changes = self.state.subscribe().skip(1); let weak_this = Rc::downgrade(&self); spawn_local(async move { @@ -118,12 +121,14 @@ where } /// Returns current [`TransitableStateController::state`]. + #[inline] + #[must_use] pub fn state(&self) -> TransitableState { self.state.get() } - /// Starts transition of the [`TransitableStateController::state`] to - /// the provided one. + /// Starts transition of the [`TransitableStateController::state`] to the + /// provided one. pub(in super::super) fn transition_to(&self, desired_state: S) { let current_state = self.state.get(); self.state.set(current_state.transition_to(desired_state)); @@ -139,11 +144,10 @@ where /// # Errors /// /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] - /// is returned if [`TransitableStateController`]'s - /// [`MediaState`] transits into the opposite to the - /// `desired_state`. + /// is returned if [`TransitableStateController`]'s [`MediaState`] transits + /// into the opposite to the `desired_state`. /// - /// [`Future`]: futures::future::Future + /// [`Future`]: std::future::Future /// [`MediaState`]: super::MediaState pub fn when_media_state_stable( &self, @@ -191,28 +195,36 @@ where } impl MuteStateController { - /// Checks whether [`TransitableStateController`]'s mute state - /// is in [`mute_state::Stable::Muted`]. + /// Indicates whether [`TransitableStateController`]'s mute state is in + /// [`mute_state::Stable::Muted`]. + #[inline] + #[must_use] pub fn muted(&self) -> bool { self.state.get() == mute_state::Stable::Muted.into() } - /// Checks whether [`TransitableStateController`]'s mute state - /// is in [`mute_state::Stable::Unmuted`]. + /// Indicates whether [`TransitableStateController`]'s mute state is in + /// [`mute_state::Stable::Unmuted`]. + #[inline] + #[must_use] pub fn unmuted(&self) -> bool { self.state.get() == mute_state::Stable::Unmuted.into() } } impl MediaExchangeStateController { - /// Checks whether [`TransitableStateController`]'s media exchange state + /// Indicates whether [`TransitableStateController`]'s media exchange state /// is in [`media_exchange_state::Stable::Disabled`]. + #[inline] + #[must_use] pub fn disabled(&self) -> bool { self.state.get() == media_exchange_state::Stable::Disabled.into() } - /// Checks whether [`TransitableStateController`]'s media exchange state + /// Indicates whether [`TransitableStateController`]'s media exchange state /// is in [`media_exchange_state::Stable::Enabled`]. + #[inline] + #[must_use] pub fn enabled(&self) -> bool { self.state.get() == media_exchange_state::Stable::Enabled.into() } diff --git a/jason/src/peer/media/transitable_state/media_exchange_state.rs b/jason/src/peer/media/transitable_state/media_exchange_state.rs index 6c76160f5..5fb8ecf2a 100644 --- a/jason/src/peer/media/transitable_state/media_exchange_state.rs +++ b/jason/src/peer/media/transitable_state/media_exchange_state.rs @@ -17,7 +17,9 @@ pub enum Stable { } impl Stable { - /// Returns opposite to this [`Stable`]. + /// Returns the opposite value to this [`Stable`]. + #[inline] + #[must_use] pub fn opposite(self) -> Self { match self { Self::Enabled => Self::Disabled, @@ -60,8 +62,8 @@ impl From for Stable { /// [`MediaExchangeState`] in transition to another [`Stable`]. /// /// [`Stable`] which is stored in [`Transition`] variants is a state which we -/// already have, but we still waiting for a desired state update. If desired -/// state update won't be received, then the stored [`Stable`] will be +/// have already, but we still waiting for the desired state update. If the +/// desired state update won't be received, then the stored [`Stable`] will be /// applied. /// /// [`MediaExchangeState`]: super::MediaExchangeState @@ -109,9 +111,8 @@ impl InTransition for Transition { } } - /// Converts [`Transition`] to the opposite - /// [`Transition`] with a same inner - /// [`Stable`]. + /// Converts [`Transition`] to the opposite [`Transition`] with the same + /// inner [`Stable`]. #[inline] fn opposite(self) -> Self { match self { diff --git a/jason/src/peer/media/transitable_state/mod.rs b/jason/src/peer/media/transitable_state/mod.rs index b0953ae9a..1d2b2ff6d 100644 --- a/jason/src/peer/media/transitable_state/mod.rs +++ b/jason/src/peer/media/transitable_state/mod.rs @@ -28,7 +28,7 @@ pub type MuteState = /// [`MediaStateControllable`]: crate::peer::MediaStateControllable #[derive(Clone, Copy, Debug, From)] pub enum MediaState { - /// Responsible for changing [enabled][1] property of + /// Responsible for changing [`enabled`][1] property of /// [MediaStreamTrack][2]. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled @@ -38,14 +38,14 @@ pub enum MediaState { /// Responsible for changing [RTCRtpTransceiverDirection][1] to stop /// traffic flow. /// - /// Requires renegotiation for changes to take effect. + /// Requires renegotiation for changes to take an effect. /// /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtptransceiverdirection MediaExchange(media_exchange_state::Stable), } impl MediaState { - /// Generates [`TrackPatchCommand`] with a provided [`TrackId`] based on + /// Generates [`TrackPatchCommand`] with a provided [`TrackId`] basing on /// this [`MediaState`]. /// /// If [`MediaState`] is [`MediaState::Mute`] then @@ -53,6 +53,7 @@ impl MediaState { /// /// If [`MediaState`] is [`MediaState::MediaExchange`] then /// [`TrackPatchCommand::enabled`] will be [`Some`]. + #[must_use] pub fn generate_track_patch(self, track_id: TrackId) -> TrackPatchCommand { match self { Self::Mute(mute) => TrackPatchCommand { @@ -70,7 +71,9 @@ impl MediaState { } } - /// Returns opposite to this [`mute_state::Stable`]. + /// Returns the opposite value to this [`mute_state::Stable`]. + #[inline] + #[must_use] pub fn opposite(self) -> Self { match self { Self::Mute(mute) => Self::Mute(mute.opposite()), @@ -86,6 +89,7 @@ pub trait InStable: Clone + Copy + PartialEq { type Transition: InTransition; /// Converts this [`InStable`] into [`InStable::Transition`]. + #[must_use] fn start_transition(self) -> Self::Transition; } @@ -94,15 +98,19 @@ pub trait InTransition: Clone + Copy + PartialEq { type Stable: InStable; /// Returns intention which this state indicates. + #[must_use] fn intended(self) -> Self::Stable; /// Sets inner [`InTransition::Stable`] state. + #[must_use] fn set_inner(self, inner: Self::Stable) -> Self; /// Returns inner [`InTransition::Stable`] state. + #[must_use] fn into_inner(self) -> Self::Stable; /// Returns opposite to this [`InTransition`]. + #[must_use] fn opposite(self) -> Self; } @@ -127,6 +135,7 @@ where /// [`TransitableState::Transition`]. /// /// No-op if already in the `desired_state`. + #[must_use] pub fn transition_to(self, desired_state: S) -> Self { if self == desired_state.into() { return self; @@ -143,8 +152,9 @@ where } } - /// Cancels ongoing transition if any. + /// Cancels an ongoing transition, if any. #[inline] + #[must_use] pub fn cancel_transition(self) -> Self { match self { Self::Stable(_) => self, @@ -154,24 +164,28 @@ where } impl From for MediaExchangeState { + #[inline] fn from(from: media_exchange_state::Stable) -> Self { Self::Stable(from) } } impl From for MediaExchangeState { + #[inline] fn from(from: media_exchange_state::Transition) -> Self { Self::Transition(from) } } impl From for MuteState { + #[inline] fn from(from: mute_state::Stable) -> Self { Self::Stable(from) } } impl From for MuteState { + #[inline] fn from(from: mute_state::Transition) -> Self { Self::Transition(from) } diff --git a/jason/src/peer/media/transitable_state/mute_state.rs b/jason/src/peer/media/transitable_state/mute_state.rs index 13ee64d28..9ff5e43b9 100644 --- a/jason/src/peer/media/transitable_state/mute_state.rs +++ b/jason/src/peer/media/transitable_state/mute_state.rs @@ -1,8 +1,8 @@ -//! State of the media mute state. +//! State of media mute state. use super::{InStable, InTransition}; -/// State of the media mute state. +/// State of media mute state. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Stable { /// [`MediaStateControllable`] is muted. @@ -17,7 +17,9 @@ pub enum Stable { } impl Stable { - /// Returns opposite to this [`Stable`]. + /// Returns the opposite value to this [`Stable`]. + #[inline] + #[must_use] pub fn opposite(self) -> Self { match self { Self::Muted => Self::Unmuted, @@ -52,8 +54,8 @@ impl InStable for Stable { /// [`MuteState`] in transition to another [`Stable`]. /// /// [`Stable`] which is stored in [`Transition`] variants is a state which we -/// already have, but we still waiting for a desired state update. If desired -/// state update won't be received, then the stored [`Stable`] will be +/// have already, but we still waiting for the desired state update. If the +/// desired state update won't be received, then the stored [`Stable`] will be /// applied. /// /// [`MuteState`]: super::MuteState diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index 6aba47a14..d7afcb261 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -394,10 +394,11 @@ impl PeerConnection { }; } - /// Returns `true` if all [`TransceiverSide`]s with a provided - /// [`MediaKind`], [`TrackDirection`] and [`MediaSourceKind`] is in the + /// Indicates whether all [`TransceiverSide`]s with the provided + /// [`MediaKind`], [`TrackDirection`] and [`MediaSourceKind`] are in the /// provided [`MediaState`]. #[inline] + #[must_use] pub fn is_all_transceiver_sides_in_media_state( &self, kind: MediaKind, @@ -604,9 +605,8 @@ impl PeerConnection { Ok(()) } - /// Updates [`local::Track`]s being used in [`PeerConnection`]s - /// [`Sender`]s. [`Sender`]s are chosen based on provided - /// [`LocalStreamUpdateCriteria`]. + /// Updates [`local::Track`]s being used in [`PeerConnection`]s [`Sender`]s. + /// [`Sender`]s are chosen based on provided [`LocalStreamUpdateCriteria`]. /// /// First of all make sure that [`PeerConnection`] [`Sender`]s are up to /// date (you set those with [`PeerConnection::create_tracks`]). If @@ -648,8 +648,7 @@ impl PeerConnection { /// With [`MediaConnectionsError::InvalidMediaTracks`], /// [`MediaConnectionsError::InvalidMediaTrack`] or /// [`MediaConnectionsError::CouldNotInsertLocalTrack`] if - /// [`local::Track`] couldn't inserted into [`PeerConnection`]s - /// [`Sender`]s. + /// [`local::Track`] couldn't inserted into [`PeerConnection`]s [`Sender`]s. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastream /// [2]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface @@ -923,34 +922,46 @@ impl PeerConnection { .map_err(tracerr::map_from_and_wrap!()) } - /// Indicates whether all [`Receiver`]s audio tracks are enabled. #[cfg(feature = "mockable")] + /// Indicates whether all [`Receiver`]s audio tracks are enabled. + #[inline] + #[must_use] pub fn is_recv_audio_enabled(&self) -> bool { self.media_connections.is_recv_audio_enabled() } - /// Indicates whether all [`Receiver`]s video tracks are enabled. #[cfg(feature = "mockable")] + /// Indicates whether all [`Receiver`]s video tracks are enabled. + #[inline] + #[must_use] pub fn is_recv_video_enabled(&self) -> bool { self.media_connections.is_recv_video_enabled() } /// Returns inner [`IceCandidate`]'s buffer length. Used in tests. + #[inline] + #[must_use] pub fn candidates_buffer_len(&self) -> usize { self.ice_candidates_buffer.borrow().len() } /// Lookups [`Sender`] by provided [`TrackId`]. + #[inline] + #[must_use] pub fn get_sender_by_id(&self, id: TrackId) -> Option> { self.media_connections.get_sender_by_id(id) } /// Indicates whether all [`Sender`]s audio tracks are enabled. + #[inline] + #[must_use] pub fn is_send_audio_enabled(&self) -> bool { self.media_connections.is_send_audio_enabled() } /// Indicates whether all [`Sender`]s video tracks are enabled. + #[inline] + #[must_use] pub fn is_send_video_enabled( &self, source_kind: Option, @@ -958,7 +969,9 @@ impl PeerConnection { self.media_connections.is_send_video_enabled(source_kind) } - /// Returns `true` if all [`Sender`]s video tracks are unmuted. + /// Indicates whether all [`Sender`]s video tracks are unmuted. + #[inline] + #[must_use] pub fn is_send_video_unmuted( &self, source_kind: Option, @@ -966,14 +979,17 @@ impl PeerConnection { self.media_connections.is_send_video_unmuted(source_kind) } - /// Returns `true` if all [`Sender`]s audio tracks are unmuted. + /// Indicates whether all [`Sender`]s audio tracks are unmuted. + #[inline] + #[must_use] pub fn is_send_audio_unmuted(&self) -> bool { self.media_connections.is_send_audio_unmuted() } } impl Drop for PeerConnection { - /// Drops `on_track` and `on_ice_candidate` callbacks to prevent leak. + /// Drops `on_track` and `on_ice_candidate` callbacks to prevent possible + /// leaks. fn drop(&mut self) { let _ = self.peer.on_track::>(None); let _ = self diff --git a/jason/src/peer/transceiver.rs b/jason/src/peer/transceiver.rs index 33dc58fc3..b28801f08 100644 --- a/jason/src/peer/transceiver.rs +++ b/jason/src/peer/transceiver.rs @@ -76,7 +76,8 @@ impl Transceiver { self.send_track.borrow().clone() } - /// Sets underlying [`local::Track`] `enabled` field to the provided if any. + /// Sets the underlying [`local::Track`]'s `enabled` field to the provided + /// value, if any. pub fn set_send_track_enabled(&self, enabled: bool) { if let Some(track) = self.send_track.borrow().as_ref() { track.set_enabled(enabled); diff --git a/src/media/peer.rs b/src/media/peer.rs index 727fd9692..934eba2a6 100644 --- a/src/media/peer.rs +++ b/src/media/peer.rs @@ -366,7 +366,9 @@ pub enum TrackChange { } impl TrackChange { - /// Returns `true` if this [`TrackChange`] doesn't requires renegotiation. + /// Indicates whether this [`TrackChange`] doesn't require renegotiation. + #[inline] + #[must_use] fn is_negotiation_state_agnostic(&self) -> bool { matches!( self, @@ -964,7 +966,7 @@ impl Peer { /// [`PeerStateMachine::get_updates`]. Calls /// [`PeerUpdatesSubscriber::negotiation_needed`] notifying subscriber that /// this [`Peer`] has changes to negotiate. Changes that can be applied - /// regardless of negotiation state will be immediately force pushed to + /// regardless of negotiation state will be immediately force-pushed to /// [`PeerUpdatesSubscriber`]. fn commit_scheduled_changes(&mut self) { if !self.context.track_changes_queue.is_empty() {