From 4c5b7c03b783979daf71397769bd0e62e66888ab Mon Sep 17 00:00:00 2001 From: alexlapa Date: Mon, 22 Feb 2021 14:03:37 +0200 Subject: [PATCH 01/19] init [skip ci] --- Makefile | 2 +- jason/Cargo.toml | 66 +-- jason/src/api/mod.rs | 172 +------- jason/src/api/wasm/connection_handle.rs | 42 ++ .../api/wasm/constraints_update_exception.rs | 42 ++ jason/src/api/wasm/input_device_info.rs | 47 ++ jason/src/api/wasm/jason.rs | 54 +++ jason/src/api/wasm/local_media_track.rs | 33 ++ jason/src/api/wasm/media_manager_handle.rs | 79 ++++ jason/src/api/wasm/media_stream_settings.rs | 155 +++++++ jason/src/api/wasm/mod.rs | 83 ++++ jason/src/api/wasm/reconnect_handle.rs | 66 +++ jason/src/api/wasm/remote_media_track.rs | 49 +++ jason/src/api/wasm/room_close_reason.rs | 30 ++ jason/src/api/wasm/room_handle.rs | 269 ++++++++++++ jason/src/{api => core}/connection.rs | 22 +- jason/src/{ => core}/media/constraints.rs | 404 ++++++------------ jason/src/{ => core}/media/manager.rs | 218 +++------- jason/src/{ => core}/media/mod.rs | 8 +- jason/src/{ => core}/media/track/local.rs | 86 ++-- jason/src/{ => core}/media/track/mod.rs | 22 +- jason/src/{ => core}/media/track/remote.rs | 83 ++-- jason/src/core/mod.rs | 152 +++++++ .../peer/component/ice_candidates.rs | 2 +- .../{ => core}/peer/component/local_sdp.rs | 8 +- jason/src/{ => core}/peer/component/mod.rs | 2 +- .../peer/component/tracks_repository.rs | 2 +- .../src/{ => core}/peer/component/watchers.rs | 2 +- jason/src/{ => core}/peer/media/mod.rs | 43 +- .../peer/media/receiver/component.rs | 21 +- .../src/{ => core}/peer/media/receiver/mod.rs | 22 +- .../{ => core}/peer/media/sender/component.rs | 26 +- jason/src/{ => core}/peer/media/sender/mod.rs | 12 +- .../media/transitable_state/controller.rs | 18 +- .../transitable_state/media_exchange_state.rs | 0 .../peer/media/transitable_state/mod.rs | 0 .../media/transitable_state/mute_state.rs | 0 jason/src/{ => core}/peer/mod.rs | 95 ++-- jason/src/{ => core}/peer/repo.rs | 18 +- .../{ => core}/peer/stream_update_criteria.rs | 2 +- jason/src/{ => core}/peer/tracks_request.rs | 29 +- jason/src/{api => core}/room.rs | 250 +++++------ jason/src/{ => core}/rpc/backoff_delayer.rs | 19 +- jason/src/{ => core}/rpc/heartbeat.rs | 19 +- jason/src/{ => core}/rpc/mod.rs | 39 +- jason/src/{ => core}/rpc/reconnect_handle.rs | 66 ++- jason/src/{ => core}/rpc/rpc_session.rs | 23 +- jason/src/{ => core}/rpc/websocket/client.rs | 22 +- jason/src/core/rpc/websocket/mod.rs | 13 + jason/src/core/utils/callback.rs | 86 ++++ jason/src/{ => core}/utils/component.rs | 10 +- jason/src/{ => core}/utils/errors.rs | 61 +-- jason/src/core/utils/mod.rs | 92 ++++ .../src/{ => core}/utils/resettable_delay.rs | 9 +- jason/src/lib.rs | 36 +- jason/src/platform/mod.rs | 157 +++++++ .../src/{peer => platform/wasm}/ice_server.rs | 0 .../wasm/input_device_info.rs} | 20 +- jason/src/platform/wasm/media_track.rs | 112 +++++ jason/src/platform/wasm/mod.rs | 249 +++++++++++ .../wasm/peer_connection.rs} | 69 ++- .../stats.rs => platform/wasm/rtc_stats.rs} | 17 +- .../{peer => platform/wasm}/transceiver.rs | 27 +- .../websocket => platform/wasm}/transport.rs | 142 ++---- .../wasm}/utils/event_listener.rs | 16 +- jason/src/platform/wasm/utils/mod.rs | 3 + jason/src/rpc/websocket/mod.rs | 19 - jason/src/utils/callback.rs | 155 ------- jason/src/utils/mod.rs | 199 --------- 69 files changed, 2651 insertions(+), 1765 deletions(-) create mode 100644 jason/src/api/wasm/connection_handle.rs create mode 100644 jason/src/api/wasm/constraints_update_exception.rs create mode 100644 jason/src/api/wasm/input_device_info.rs create mode 100644 jason/src/api/wasm/jason.rs create mode 100644 jason/src/api/wasm/local_media_track.rs create mode 100644 jason/src/api/wasm/media_manager_handle.rs create mode 100644 jason/src/api/wasm/media_stream_settings.rs create mode 100644 jason/src/api/wasm/mod.rs create mode 100644 jason/src/api/wasm/reconnect_handle.rs create mode 100644 jason/src/api/wasm/remote_media_track.rs create mode 100644 jason/src/api/wasm/room_close_reason.rs create mode 100644 jason/src/api/wasm/room_handle.rs rename jason/src/{api => core}/connection.rs (92%) rename jason/src/{ => core}/media/constraints.rs (80%) rename jason/src/{ => core}/media/manager.rs (63%) rename jason/src/{ => core}/media/mod.rs (89%) rename jason/src/{ => core}/media/track/local.rs (60%) rename jason/src/{ => core}/media/track/mod.rs (60%) rename jason/src/{ => core}/media/track/remote.rs (60%) create mode 100644 jason/src/core/mod.rs rename jason/src/{ => core}/peer/component/ice_candidates.rs (98%) rename jason/src/{ => core}/peer/component/local_sdp.rs (98%) rename jason/src/{ => core}/peer/component/mod.rs (99%) rename jason/src/{ => core}/peer/component/tracks_repository.rs (99%) rename jason/src/{ => core}/peer/component/watchers.rs (99%) rename jason/src/{ => core}/peer/media/mod.rs (96%) rename jason/src/{ => core}/peer/media/receiver/component.rs (96%) rename jason/src/{ => core}/peer/media/receiver/mod.rs (93%) rename jason/src/{ => core}/peer/media/sender/component.rs (97%) rename jason/src/{ => core}/peer/media/sender/mod.rs (97%) rename jason/src/{ => core}/peer/media/transitable_state/controller.rs (96%) rename jason/src/{ => core}/peer/media/transitable_state/media_exchange_state.rs (100%) rename jason/src/{ => core}/peer/media/transitable_state/mod.rs (100%) rename jason/src/{ => core}/peer/media/transitable_state/mute_state.rs (100%) rename jason/src/{ => core}/peer/mod.rs (93%) rename jason/src/{ => core}/peer/repo.rs (96%) rename jason/src/{ => core}/peer/stream_update_criteria.rs (98%) rename jason/src/{ => core}/peer/tracks_request.rs (95%) rename jason/src/{api => core}/room.rs (92%) rename jason/src/{ => core}/rpc/backoff_delayer.rs (82%) rename jason/src/{ => core}/rpc/heartbeat.rs (93%) rename jason/src/{ => core}/rpc/mod.rs (87%) rename jason/src/{ => core}/rpc/reconnect_handle.rs (59%) rename jason/src/{ => core}/rpc/rpc_session.rs (98%) rename jason/src/{ => core}/rpc/websocket/client.rs (98%) create mode 100644 jason/src/core/rpc/websocket/mod.rs create mode 100644 jason/src/core/utils/callback.rs rename jason/src/{ => core}/utils/component.rs (97%) rename jason/src/{ => core}/utils/errors.rs (62%) create mode 100644 jason/src/core/utils/mod.rs rename jason/src/{ => core}/utils/resettable_delay.rs (92%) create mode 100644 jason/src/platform/mod.rs rename jason/src/{peer => platform/wasm}/ice_server.rs (100%) rename jason/src/{media/device_info.rs => platform/wasm/input_device_info.rs} (80%) create mode 100644 jason/src/platform/wasm/media_track.rs create mode 100644 jason/src/platform/wasm/mod.rs rename jason/src/{peer/conn.rs => platform/wasm/peer_connection.rs} (93%) rename jason/src/{peer/stats.rs => platform/wasm/rtc_stats.rs} (88%) rename jason/src/{peer => platform/wasm}/transceiver.rs (91%) rename jason/src/{rpc/websocket => platform/wasm}/transport.rs (70%) rename jason/src/{ => platform/wasm}/utils/event_listener.rs (88%) create mode 100644 jason/src/platform/wasm/utils/mod.rs delete mode 100644 jason/src/rpc/websocket/mod.rs delete mode 100644 jason/src/utils/callback.rs delete mode 100644 jason/src/utils/mod.rs diff --git a/Makefile b/Makefile index 0fc095e4e..b1435ab56 100644 --- a/Makefile +++ b/Makefile @@ -172,7 +172,7 @@ up.demo: docker.up.demo # make up.dev up.dev: up.coturn - $(MAKE) -j3 up.jason docker.up.medea up.control + $(MAKE) -j up.jason docker.up.medea up.control up.medea: docker.up.medea diff --git a/jason/Cargo.toml b/jason/Cargo.toml index eee45bb17..13ec4a45a 100644 --- a/jason/Cargo.toml +++ b/jason/Cargo.toml @@ -24,13 +24,11 @@ mockable = ["downcast", "fragile", "mockall", "predicates-tree"] async-recursion = "0.3" async-trait = "0.1" bitflags = "1.2" -console_error_panic_hook = { version = "0.1", optional = true } derivative = "2.1" derive_more = "0.99" downcast = { version = "0.10", optional = true } fragile = { version = "1.0", optional = true } futures = "0.3" -js-sys = "0.3" log = "0.4" medea-client-api-proto = { version = "0.2", features = ["jason"] } medea-macro = "0.2" @@ -41,41 +39,45 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" tracerr = "0.1" url = "2.1" + +[target.wasm32-unknown-unknown.dependencies] +console_error_panic_hook = { version = "0.1", optional = true } +js-sys = "0.3" wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4" wasm-logger = "0.2" wee_alloc = { version = "0.4", optional = true } [dependencies.web-sys] - version = "0.3.47" - features = [ - "console", - "ConstrainDomStringParameters", "ConstrainDoubleRange", - "CloseEvent", - "DisplayMediaStreamConstraints", - "Event", "EventTarget", - "MediaDevices","MediaDeviceInfo", "MediaDeviceKind", - "MediaTrackConstraints", "MediaTrackSettings", - "MediaStream", "MediaStreamConstraints", - "MediaStreamTrack", "MediaStreamTrackState", - "MessageEvent", - "Navigator", - "RtcBundlePolicy", - "RtcConfiguration", - "RtcIceCandidate", "RtcIceCandidateInit", - "RtcIceConnectionState", - "RtcIceServer", - "RtcIceTransportPolicy", - "RtcOfferOptions", - "RtcPeerConnection", "RtcPeerConnectionIceEvent", - "RtcRtpReceiver", "RtcRtpSender", - "RtcRtpTransceiver", "RtcRtpTransceiverDirection", - "RtcRtpTransceiverInit", - "RtcSdpType", - "RtcSessionDescription", "RtcSessionDescriptionInit", - "RtcStats", - "RtcTrackEvent", - "WebSocket", "Window", - ] +version = "0.3.47" +features = [ + "console", + "ConstrainDomStringParameters", "ConstrainDoubleRange", + "CloseEvent", + "DisplayMediaStreamConstraints", + "Event", "EventTarget", + "MediaDevices","MediaDeviceInfo", "MediaDeviceKind", + "MediaTrackConstraints", "MediaTrackSettings", + "MediaStream", "MediaStreamConstraints", + "MediaStreamTrack", "MediaStreamTrackState", + "MessageEvent", + "Navigator", + "RtcBundlePolicy", + "RtcConfiguration", + "RtcIceCandidate", "RtcIceCandidateInit", + "RtcIceConnectionState", + "RtcIceServer", + "RtcIceTransportPolicy", + "RtcOfferOptions", + "RtcPeerConnection", "RtcPeerConnectionIceEvent", + "RtcRtpReceiver", "RtcRtpSender", + "RtcRtpTransceiver", "RtcRtpTransceiverDirection", + "RtcRtpTransceiverInit", + "RtcSdpType", + "RtcSessionDescription", "RtcSessionDescriptionInit", + "RtcStats", + "RtcTrackEvent", + "WebSocket", "Window", +] [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/jason/src/api/mod.rs b/jason/src/api/mod.rs index aca93c3e3..7d8830d9b 100644 --- a/jason/src/api/mod.rs +++ b/jason/src/api/mod.rs @@ -1,151 +1,25 @@ -//! External Jason API accessible from JS. - -mod connection; -mod room; - -use std::{cell::RefCell, rc::Rc}; - -use futures::FutureExt as _; -use wasm_bindgen::prelude::*; -use wasm_bindgen_futures::spawn_local; - -use crate::{ - media::{MediaManager, MediaManagerHandle}, - rpc::{ - ClientDisconnect, RpcSession, RpcTransport, WebSocketRpcClient, - WebSocketRpcSession, WebSocketRpcTransport, - }, - set_panic_hook, -}; - -#[doc(inline)] -pub use self::{ - connection::{Connection, ConnectionHandle, Connections}, - room::{ - ConstraintsUpdateException, Room, RoomCloseReason, RoomError, - RoomHandle, WeakRoom, +// #[cfg(all( +// target_arch = "wasm32", +// target_vendor = "unknown", +// target_os = "unknown" +// ))] +mod wasm; + +// #[cfg(all( +// target_arch = "wasm32", +// target_vendor = "unknown", +// target_os = "unknown" +// ))] +pub use wasm::{ + connection_handle::ConnectionHandle, + constraints_update_exception::ConstraintsUpdateException, + local_media_track::LocalMediaTrack, + media_stream_settings::{ + AudioTrackConstraints, DeviceVideoTrackConstraints, + DisplayVideoTrackConstraints, MediaStreamSettings, }, + reconnect_handle::ReconnectHandle, + remote_media_track::RemoteMediaTrack, + room_close_reason::RoomCloseReason, + FacingMode, MediaKind, MediaSourceKind, }; - -/// General library interface. -/// -/// Responsible for managing shared transports, local media -/// and room initialization. -#[wasm_bindgen] -pub struct Jason(Rc>); - -struct Inner { - /// [`Jason`]s [`MediaManager`]. It's shared across [`Room`]s since - /// [`MediaManager`] contains media tracks that can be used by multiple - /// [`Room`]s. - media_manager: Rc, - - /// [`Room`]s maintained by this [`Jason`] instance. - rooms: Vec, - - /// Connection with Media Server. Only one [`WebSocketRpcClient`] is - /// supported at the moment. - rpc: Rc, -} - -#[wasm_bindgen] -impl Jason { - /// Instantiates new [`Jason`] interface to interact with this library. - #[wasm_bindgen(constructor)] - pub fn new() -> Self { - set_panic_hook(); - wasm_logger::init(wasm_logger::Config::default()); - - Self::with_rpc_client(Rc::new(WebSocketRpcClient::new(Box::new( - |url| { - Box::pin(async move { - let ws = WebSocketRpcTransport::new(url) - .await - .map_err(|e| tracerr::new!(e))?; - Ok(Rc::new(ws) as Rc) - }) - }, - )))) - } - - /// Creates new [`Room`] and returns its [`RoomHandle`]. - pub fn init_room(&self) -> RoomHandle { - let rpc = Rc::clone(&self.0.borrow().rpc); - self.inner_init_room(WebSocketRpcSession::new(rpc)) - } - - /// Returns [`MediaManagerHandle`]. - pub fn media_manager(&self) -> MediaManagerHandle { - self.0.borrow().media_manager.new_handle() - } - - /// Closes the provided [`RoomHandle`]. - #[allow(clippy::needless_pass_by_value)] - pub fn close_room(&self, room_to_delete: RoomHandle) { - self.0.borrow_mut().rooms.retain(|room| { - let should_be_closed = room.inner_ptr_eq(&room_to_delete); - if should_be_closed { - room.set_close_reason(ClientDisconnect::RoomClosed.into()); - } - - !should_be_closed - }); - } - - /// Drops [`Jason`] API object, so all related objects (rooms, connections, - /// streams etc.) respectively. All objects related to this [`Jason`] API - /// object will be detached (you will still hold them, but unable to use). - pub fn dispose(self) { - self.0.borrow_mut().rooms.drain(..).for_each(|room| { - room.close(ClientDisconnect::RoomClosed.into()); - }); - } -} - -impl Jason { - /// Returns new [`Jason`] with the provided [`WebSocketRpcClient`]. - #[inline] - pub fn with_rpc_client(rpc: Rc) -> Self { - Self(Rc::new(RefCell::new(Inner { - rpc, - rooms: Vec::new(), - media_manager: Rc::new(MediaManager::default()), - }))) - } - - /// Returns [`RoomHandle`] for [`Room`]. - pub fn inner_init_room(&self, rpc: Rc) -> RoomHandle { - let on_normal_close = rpc.on_normal_close(); - let room = Room::new(rpc, Rc::clone(&self.0.borrow().media_manager)); - - let weak_room = room.downgrade(); - let weak_inner = Rc::downgrade(&self.0); - spawn_local(on_normal_close.map(move |reason| { - (|| { - let room = weak_room.upgrade()?; - let inner = weak_inner.upgrade()?; - let mut inner = inner.borrow_mut(); - let index = inner.rooms.iter().position(|r| r.ptr_eq(&room)); - if let Some(index) = index { - inner.rooms.remove(index).close(reason); - } - if inner.rooms.is_empty() { - inner.media_manager = Rc::default(); - } - - Some(()) - })(); - })); - - let handle = room.new_handle(); - self.0.borrow_mut().rooms.push(room); - handle - } -} - -impl Default for Jason { - #[inline] - fn default() -> Self { - Self::new() - } -} diff --git a/jason/src/api/wasm/connection_handle.rs b/jason/src/api/wasm/connection_handle.rs new file mode 100644 index 000000000..17e7f178c --- /dev/null +++ b/jason/src/api/wasm/connection_handle.rs @@ -0,0 +1,42 @@ +use derive_more::From; +use wasm_bindgen::prelude::*; + +use crate::core; + +/// Connection with a specific remote `Member`, that is used on JS side. +/// +/// Actually, represents a [`Weak`]-based handle to `InnerConnection`. +#[wasm_bindgen] +#[derive(From)] +pub struct ConnectionHandle(core::ConnectionHandle); + +#[wasm_bindgen] +impl ConnectionHandle { + /// Sets callback, which will be invoked when this `Connection` will close. + pub fn on_close(&self, cb: js_sys::Function) -> Result<(), JsValue> { + self.0.on_close(cb).map_err(JsValue::from) + } + + /// Returns remote `Member` ID. + pub fn get_remote_member_id(&self) -> Result { + self.0.get_remote_member_id().map_err(JsValue::from) + } + + /// Sets callback, which will be invoked when new [`remote::Track`] will be + /// added to this [`Connection`]. + pub fn on_remote_track_added( + &self, + cb: js_sys::Function, + ) -> Result<(), JsValue> { + self.0.on_remote_track_added(cb).map_err(JsValue::from) + } + + /// Sets callback, which will be invoked when connection quality score will + /// be updated by server. + pub fn on_quality_score_update( + &self, + cb: js_sys::Function, + ) -> Result<(), JsValue> { + self.0.on_quality_score_update(cb).map_err(JsValue::from) + } +} diff --git a/jason/src/api/wasm/constraints_update_exception.rs b/jason/src/api/wasm/constraints_update_exception.rs new file mode 100644 index 000000000..1c492557e --- /dev/null +++ b/jason/src/api/wasm/constraints_update_exception.rs @@ -0,0 +1,42 @@ +use derive_more::From; +use wasm_bindgen::prelude::*; + +use crate::core; + +/// JS exception for the [`RoomHandle::set_local_media_settings`]. +#[wasm_bindgen] +#[derive(Debug, From)] +#[from(forward)] +pub struct ConstraintsUpdateException(core::ConstraintsUpdateException); + +#[wasm_bindgen] +impl ConstraintsUpdateException { + /// Returns name of this [`ConstraintsUpdateException`]. + pub fn name(&self) -> String { + self.0.name() + } + + /// Returns [`JasonError`] if this [`ConstraintsUpdateException`] represents + /// `RecoveredException` or `RecoverFailedException`. + /// + /// Returns `undefined` otherwise. + pub fn recover_reason(&self) -> JsValue { + self.0.recover_reason() + } + + /// Returns [`js_sys::Array`] with the [`JasonError`]s if this + /// [`ConstraintsUpdateException`] represents `RecoverFailedException`. + /// + /// Returns `undefined` otherwise. + pub fn recover_fail_reasons(&self) -> JsValue { + self.0.recover_fail_reasons() + } + + /// Returns [`JasonError`] if this [`ConstraintsUpdateException`] represents + /// `ErroredException`. + /// + /// Returns `undefined` otherwise. + pub fn error(&self) -> JsValue { + self.0.error() + } +} diff --git a/jason/src/api/wasm/input_device_info.rs b/jason/src/api/wasm/input_device_info.rs new file mode 100644 index 000000000..3fc38c140 --- /dev/null +++ b/jason/src/api/wasm/input_device_info.rs @@ -0,0 +1,47 @@ +use derive_more::From; +use wasm_bindgen::prelude::*; + +use crate::platform; + +/// Representation of [MediaDeviceInfo][1]. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#device-info +#[wasm_bindgen] +#[derive(From)] +pub struct InputDeviceInfo(platform::InputDeviceInfo); + +#[wasm_bindgen] +impl InputDeviceInfo { + /// Returns unique identifier for the represented device. + pub fn device_id(&self) -> String { + self.0.device_id() + } + + /// Returns kind of the represented device. + /// + /// This representation of [MediaDeviceInfo][1] ONLY for input device. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#device-info + pub fn kind(&self) -> super::MediaKind { + self.0.kind().into() + } + + /// Returns label describing the represented device (for example + /// "External USB Webcam"). + /// If the device has no associated label, then returns an empty string. + pub fn label(&self) -> String { + self.0.label() + } + + /// Returns group identifier of the represented device. + /// + /// Two devices have the same group identifier if they belong to the same + /// physical device. For example, the audio input and output devices + /// representing the speaker and microphone of the same headset have the + /// same [groupId][1]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadeviceinfo-groupid + pub fn group_id(&self) -> String { + self.0.group_id() + } +} diff --git a/jason/src/api/wasm/jason.rs b/jason/src/api/wasm/jason.rs new file mode 100644 index 000000000..40b4de53c --- /dev/null +++ b/jason/src/api/wasm/jason.rs @@ -0,0 +1,54 @@ +use derive_more::From; +use wasm_bindgen::prelude::*; + +use crate::{ + core, + platform::{init_logger, set_panic_hook}, +}; + +use super::{ + media_manager_handle::MediaManagerHandle, room_handle::RoomHandle, +}; + +/// General library interface. +/// +/// Responsible for managing shared transports, local media +/// and room initialization. +#[wasm_bindgen] +#[derive(From)] +pub struct Jason(core::Jason); + +#[wasm_bindgen] +impl Jason { + /// Instantiates new [`Jason`] interface to interact with this library. + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + set_panic_hook(); + init_logger(); + + Self(core::Jason::new()) + } + + /// Creates new [`Room`] and returns its [`RoomHandle`]. + pub fn init_room(&self) -> RoomHandle { + self.0.init_room().into() + } + + /// Returns [`MediaManagerHandle`]. + pub fn media_manager(&self) -> MediaManagerHandle { + self.0.media_manager().into() + } + + /// Closes the provided [`RoomHandle`]. + #[allow(clippy::needless_pass_by_value)] + pub fn close_room(&self, room_to_delete: RoomHandle) { + self.0.close_room(room_to_delete.into()); + } + + /// Drops [`Jason`] API object, so all related objects (rooms, connections, + /// streams etc.) respectively. All objects related to this [`Jason`] API + /// object will be detached (you will still hold them, but unable to use). + pub fn dispose(self) { + self.0.dispose(); + } +} diff --git a/jason/src/api/wasm/local_media_track.rs b/jason/src/api/wasm/local_media_track.rs new file mode 100644 index 000000000..1a98fb919 --- /dev/null +++ b/jason/src/api/wasm/local_media_track.rs @@ -0,0 +1,33 @@ +use derive_more::From; + +use wasm_bindgen::prelude::*; + +use crate::core; + +/// Wrapper around strongly referenced [`Track`] for JS side. +#[wasm_bindgen] +#[derive(From)] +pub struct LocalMediaTrack(core::LocalMediaTrack); + +#[wasm_bindgen] +impl LocalMediaTrack { + /// Returns the underlying [`sys::MediaStreamTrack`] of this [`JsTrack`]. + pub fn get_track(&self) -> web_sys::MediaStreamTrack { + Clone::clone(&self.0.get_track().as_ref()) + } + + /// Returns [`MediaKind::Audio`] if this [`JsTrack`] represents an audio + /// track, or [`MediaKind::Video`] if it represents a video track. + pub fn kind(&self) -> super::MediaKind { + self.0.kind().into() + } + + /// 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://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia + pub fn media_source_kind(&self) -> super::MediaSourceKind { + self.0.media_source_kind().into() + } +} diff --git a/jason/src/api/wasm/media_manager_handle.rs b/jason/src/api/wasm/media_manager_handle.rs new file mode 100644 index 000000000..1b61d30b6 --- /dev/null +++ b/jason/src/api/wasm/media_manager_handle.rs @@ -0,0 +1,79 @@ +use derive_more::From; +use js_sys::Promise; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::future_to_promise; + +use crate::{api, core}; + +use super::input_device_info::InputDeviceInfo; + +/// JS side handle to [`MediaManager`]. +/// +/// [`MediaManager`] performs all media acquisition requests +/// ([getUserMedia()][1]/[getDisplayMedia()][2]) and stores all received tracks +/// for further reusage. +/// +/// [`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 +#[wasm_bindgen] +#[derive(From)] +pub struct MediaManagerHandle(core::MediaManagerHandle); + +#[wasm_bindgen] +#[allow(clippy::unused_self)] +impl MediaManagerHandle { + /// Returns array of [`InputDeviceInfo`] objects, which represent available + /// media input and output devices, such as microphones, cameras, and so + /// forth. + pub fn enumerate_devices(&self) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.enumerate_devices() + .await + .map(|devices| { + devices + .into_iter() + .fold(js_sys::Array::new(), |devices_info, info| { + devices_info.push(&JsValue::from( + InputDeviceInfo::from(info), + )); + devices_info + }) + .into() + }) + .map_err(JsValue::from) + }) + } + + /// Returns [`local::JsTrack`]s objects, built from provided + /// [`MediaStreamSettings`]. + pub fn init_local_tracks( + &self, + caps: &api::MediaStreamSettings, + ) -> Promise { + let this = self.0.clone(); + let caps = caps.clone(); + + future_to_promise(async move { + this.init_local_tracks(caps.into()) + .await + .map(|tracks| { + tracks + .into_iter() + .fold(js_sys::Array::new(), |tracks, track| { + tracks.push(&JsValue::from( + api::LocalMediaTrack::from(track), + )); + tracks + }) + .into() + }) + .map_err(JsValue::from) + }) + } +} diff --git a/jason/src/api/wasm/media_stream_settings.rs b/jason/src/api/wasm/media_stream_settings.rs new file mode 100644 index 000000000..3277ea7b0 --- /dev/null +++ b/jason/src/api/wasm/media_stream_settings.rs @@ -0,0 +1,155 @@ +use derive_more::{From, Into}; +use wasm_bindgen::prelude::*; + +use crate::{api::FacingMode, core::media}; + +/// [MediaStreamConstraints][1] wrapper. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamconstraints +#[wasm_bindgen] +#[derive(Clone, From, Into)] +pub struct MediaStreamSettings(media::MediaStreamSettings); + +#[wasm_bindgen] +impl MediaStreamSettings { + /// Creates new [`MediaStreamSettings`] with none constraints configured. + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + media::MediaStreamSettings::new().into() + } + + /// Specifies the nature and settings of the audio [MediaStreamTrack][1]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + pub fn audio(&mut self, constraints: AudioTrackConstraints) { + self.0.audio(constraints.into()) + } + + /// Set constraints that will be used to obtain local video sourced from + /// media device. + pub fn device_video(&mut self, constraints: DeviceVideoTrackConstraints) { + self.0.device_video(constraints.into()); + } + + /// Set constraints that will be used to capture local video from user + /// display. + pub fn display_video(&mut self, constraints: DisplayVideoTrackConstraints) { + self.0.display_video(constraints.into()); + } +} + +/// Constraints applicable to audio tracks. +#[wasm_bindgen] +#[derive(From, Into)] +pub struct AudioTrackConstraints(media::AudioTrackConstraints); + +#[wasm_bindgen] +impl AudioTrackConstraints { + /// Creates new [`AudioTrackConstraints`] with none constraints configured. + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + media::AudioTrackConstraints::new().into() + } + + /// Sets exact [deviceId][1] constraint. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#def-constraint-deviceId + pub fn device_id(&mut self, device_id: String) { + self.0.device_id(device_id); + } +} + +/// Constraints applicable to video tracks that are sourced from some media +/// device. +#[wasm_bindgen] +#[derive(From, Into)] +pub struct DeviceVideoTrackConstraints(media::DeviceVideoTrackConstraints); + +/// Constraints applicable to video tracks that are sourced from screen-capture. +#[wasm_bindgen] +impl DeviceVideoTrackConstraints { + /// Creates new [`DeviceVideoTrackConstraints`] with none constraints + /// configured. + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + media::DeviceVideoTrackConstraints::new().into() + } + + /// Sets exact [deviceId][1] constraint. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#def-constraint-deviceId + pub fn device_id(&mut self, device_id: String) { + self.0.device_id(device_id); + } + + /// Sets exact [facingMode][1] constraint. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring + pub fn exact_facing_mode(&mut self, facing_mode: FacingMode) { + self.0.exact_facing_mode(facing_mode); + } + + /// Sets ideal [facingMode][1] constraint. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring + pub fn ideal_facing_mode(&mut self, facing_mode: FacingMode) { + self.0.ideal_facing_mode(facing_mode) + } + + /// Sets exact [`height`][1] constraint. + /// + /// [1]: https://tinyurl.com/w3-streams#def-constraint-height + pub fn exact_height(&mut self, height: u32) { + self.0.exact_height(height) + } + + /// Sets ideal [`height`][1] constraint. + /// + /// [1]: https://tinyurl.com/w3-streams#def-constraint-height + pub fn ideal_height(&mut self, height: u32) { + self.0.ideal_height(height); + } + + /// Sets range of [`height`][1] constraint. + /// + /// [1]: https://tinyurl.com/w3-streams#def-constraint-height + pub fn height_in_range(&mut self, min: u32, max: u32) { + self.0.height_in_range(min, max); + } + + /// Sets exact [`width`][1] constraint. + /// + /// [1]: https://tinyurl.com/w3-streams#def-constraint-width + pub fn exact_width(&mut self, width: u32) { + self.0.exact_width(width); + } + + /// Sets ideal [`width`][1] constraint. + /// + /// [1]: https://tinyurl.com/w3-streams#def-constraint-width + pub fn ideal_width(&mut self, width: u32) { + self.0.ideal_width(width); + } + + /// Sets range of [`width`][1] constraint. + /// + /// [1]: https://tinyurl.com/w3-streams#def-constraint-width + pub fn width_in_range(&mut self, min: u32, max: u32) { + self.0.width_in_range(min, max); + } +} + +/// Constraints applicable to video tracks sourced from screen capture. +#[wasm_bindgen] +#[derive(From, Into)] +pub struct DisplayVideoTrackConstraints(media::DisplayVideoTrackConstraints); + +#[wasm_bindgen] +impl DisplayVideoTrackConstraints { + /// Creates new [`DisplayVideoTrackConstraints`] with none constraints + /// configured. + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + media::DisplayVideoTrackConstraints::new().into() + } +} diff --git a/jason/src/api/wasm/mod.rs b/jason/src/api/wasm/mod.rs new file mode 100644 index 000000000..419a44151 --- /dev/null +++ b/jason/src/api/wasm/mod.rs @@ -0,0 +1,83 @@ +use wasm_bindgen::prelude::*; + +pub mod connection_handle; +pub mod constraints_update_exception; +pub mod input_device_info; +pub mod jason; +pub mod local_media_track; +pub mod media_manager_handle; +pub mod media_stream_settings; +pub mod reconnect_handle; +pub mod remote_media_track; +pub mod room_close_reason; +pub mod room_handle; + +use crate::core; + +/// [MediaStreamTrack.kind][1] representation. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-kind +#[wasm_bindgen] +pub enum MediaKind { + /// Audio track. + Audio, + + /// Video track. + Video, +} + +impl From for MediaKind { + fn from(that: core::MediaKind) -> Self { + match that { + core::MediaKind::Audio => Self::Audio, + core::MediaKind::Video => Self::Video, + } + } +} + +#[wasm_bindgen] +pub enum MediaSourceKind { + /// Media is sourced from some media device (webcam or microphone). + Device, + + /// Media is obtained with screen-capture. + Display, +} + +impl From for MediaSourceKind { + fn from(that: core::MediaSourceKind) -> Self { + match that { + core::MediaSourceKind::Device => Self::Device, + core::MediaSourceKind::Display => Self::Display, + } + } +} + +impl Into for MediaSourceKind { + fn into(self) -> core::MediaSourceKind { + match self { + MediaSourceKind::Device => core::MediaSourceKind::Device, + MediaSourceKind::Display => core::MediaSourceKind::Display, + } + } +} + +/// Describes the directions that the camera can face, as seen from the user's +/// perspective. Representation of [VideoFacingModeEnum][1]. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#dom-videofacingmodeenum +#[wasm_bindgen] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum FacingMode { + /// Facing toward the user (a self-view camera). + User, + + /// Facing away from the user (viewing the environment). + Environment, + + /// Facing to the left of the user. + Left, + + /// Facing to the right of the user. + Right, +} diff --git a/jason/src/api/wasm/reconnect_handle.rs b/jason/src/api/wasm/reconnect_handle.rs new file mode 100644 index 000000000..275f4857c --- /dev/null +++ b/jason/src/api/wasm/reconnect_handle.rs @@ -0,0 +1,66 @@ +use derive_more::From; +use js_sys::Promise; +use wasm_bindgen::prelude::*; +use wasm_bindgen_futures::future_to_promise; + +use crate::core; + +/// Handle that JS side can reconnect to the Medea media server on +/// a connection loss with. +/// +/// This handle will be provided into `Room.on_connection_loss` callback. +#[wasm_bindgen] +#[derive(Clone, From)] +pub struct ReconnectHandle(core::ReconnectHandle); + +#[wasm_bindgen] +impl ReconnectHandle { + /// Tries to reconnect after the provided delay in milliseconds. + /// + /// If [`RpcSession`] is already reconnecting then new reconnection attempt + /// won't be performed. Instead, it will wait for the first reconnection + /// attempt result and use it here. + pub fn reconnect_with_delay(&self, delay_ms: u32) -> Promise { + let this = self.0.clone(); + future_to_promise(async move { + this.reconnect_with_delay(delay_ms).await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Tries to reconnect [`RpcSession`] in a loop with a growing backoff + /// delay. + /// + /// The first attempt to reconnect is guaranteed to happen no earlier than + /// `starting_delay_ms`. + /// + /// Also, it guarantees that delay between reconnection attempts won't be + /// greater than `max_delay_ms`. + /// + /// After each reconnection attempt, delay between reconnections will be + /// multiplied by the given `multiplier` until it reaches `max_delay_ms`. + /// + /// If [`RpcSession`] is already reconnecting then new reconnection attempt + /// won't be performed. Instead, it will wait for the first reconnection + /// attempt result and use it here. + /// + /// If `multiplier` is negative number than `multiplier` will be considered + /// as `0.0`. + pub fn reconnect_with_backoff( + &self, + starting_delay_ms: u32, + multiplier: f32, + max_delay: u32, + ) -> Promise { + let this = self.0.clone(); + future_to_promise(async move { + this.reconnect_with_backoff( + starting_delay_ms, + multiplier, + max_delay, + ) + .await?; + Ok(JsValue::UNDEFINED) + }) + } +} diff --git a/jason/src/api/wasm/remote_media_track.rs b/jason/src/api/wasm/remote_media_track.rs new file mode 100644 index 000000000..18d15af4d --- /dev/null +++ b/jason/src/api/wasm/remote_media_track.rs @@ -0,0 +1,49 @@ +use derive_more::From; +use wasm_bindgen::prelude::*; + +use crate::core; + +/// Wrapper around [MediaStreamTrack][1] received from the remote. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack +#[wasm_bindgen] +#[derive(Clone, From)] +pub struct RemoteMediaTrack(core::remote::Track); + +#[wasm_bindgen] +impl RemoteMediaTrack { + /// Returns the underlying [`platform::MediaStreamTrack`] of this [`Track`]. + pub fn get_track(&self) -> web_sys::MediaStreamTrack { + Clone::clone(self.0.get_track().as_ref()) + } + + /// Indicate whether this [`Track`] is enabled. + pub fn enabled(&self) -> bool { + self.0.enabled() + } + + /// Sets callback to invoke when this [`Track`] is enabled. + pub fn on_enabled(&self, cb: js_sys::Function) { + self.0.on_enabled(cb) + } + + /// Sets callback to invoke when this [`Track`] is disabled. + pub fn on_disabled(&self, cb: js_sys::Function) { + self.0.on_disabled(cb) + } + + /// Returns [`MediaKind::Audio`] if this [`Track`] represents an audio + /// track, or [`MediaKind::Video`] if it represents a video track. + pub fn kind(&self) -> super::MediaKind { + self.0.kind().into() + } + + /// 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://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia + pub fn media_source_kind(&self) -> super::MediaSourceKind { + self.0.media_source_kind().into() + } +} diff --git a/jason/src/api/wasm/room_close_reason.rs b/jason/src/api/wasm/room_close_reason.rs new file mode 100644 index 000000000..e73b02742 --- /dev/null +++ b/jason/src/api/wasm/room_close_reason.rs @@ -0,0 +1,30 @@ +use derive_more::From; +use wasm_bindgen::prelude::*; + +use crate::core; + +/// Reason of why [`Room`] has been closed. +/// +/// This struct is passed into `on_close_by_server` JS side callback. +#[wasm_bindgen] +#[derive(From)] +pub struct RoomCloseReason(core::RoomCloseReason); + +#[wasm_bindgen] +impl RoomCloseReason { + /// `wasm_bindgen` getter for [`RoomCloseReason::reason`] field. + pub fn reason(&self) -> String { + self.0.reason() + } + + /// `wasm_bindgen` getter for [`RoomCloseReason::is_closed_by_server`] + /// field. + pub fn is_closed_by_server(&self) -> bool { + self.0.is_closed_by_server() + } + + /// `wasm_bindgen` getter for [`RoomCloseReason::is_err`] field. + pub fn is_err(&self) -> bool { + self.0.is_err() + } +} diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs new file mode 100644 index 000000000..e7e7060f2 --- /dev/null +++ b/jason/src/api/wasm/room_handle.rs @@ -0,0 +1,269 @@ +use derive_more::{From, Into}; +use js_sys::Promise; +use wasm_bindgen::{prelude::*, JsValue}; +use wasm_bindgen_futures::future_to_promise; + +use crate::{api, api::MediaSourceKind, core, core::utils::JasonError}; + +/// JS side handle to `Room` where all the media happens. +/// +/// Actually, represents a [`Weak`]-based handle to `InnerRoom`. +/// +/// For using [`RoomHandle`] on Rust side, consider the `Room`. +#[wasm_bindgen] +#[derive(From, Into)] +pub struct RoomHandle(core::RoomHandle); + +#[wasm_bindgen] +impl RoomHandle { + /// Connects media server and enters [`Room`] with provided authorization + /// `token`. + /// + /// Authorization token has fixed format: + /// `{{ Host URL }}/{{ Room ID }}/{{ Member ID }}?token={{ Auth Token }}` + /// (e.g. `wss://medea.com/MyConf1/Alice?token=777`). + /// + /// Establishes connection with media server (if it doesn't already exist). + /// Fails if: + /// - `on_failed_local_media` callback is not set + /// - `on_connection_loss` callback is not set + /// - unable to connect to media server. + /// + /// Effectively returns `Result<(), JasonError>`. + pub fn join(&self, token: String) -> Promise { + let this = self.0.clone(); + future_to_promise(async move { + this.join(token).await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Sets callback, which will be invoked when new [`Connection`] with some + /// remote `Peer` is established. + /// + /// [`Connection`]: crate::api::Connection + pub fn on_new_connection( + &self, + cb: js_sys::Function, + ) -> Result<(), JsValue> { + self.0.on_new_connection(cb) + } + + /// Sets `on_close` callback, which will be invoked on [`Room`] close, + /// providing [`RoomCloseReason`]. + pub fn on_close(&self, cb: js_sys::Function) -> Result<(), JsValue> { + self.0.on_close(cb) + } + + /// 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. + /// 3. [`MediaStreamSettings`] updated via `set_local_media_settings`. + pub fn on_local_track(&self, cb: js_sys::Function) -> Result<(), JsValue> { + self.0.on_local_track(cb) + } + + /// Sets `on_failed_local_media` callback, which will be invoked on local + /// media acquisition failures. + pub fn on_failed_local_media( + &self, + cb: js_sys::Function, + ) -> Result<(), JsValue> { + self.0.on_failed_local_media(cb) + } + + /// Sets `on_connection_loss` callback, which will be invoked on connection + /// with server loss. + pub fn on_connection_loss( + &self, + cb: js_sys::Function, + ) -> Result<(), JsValue> { + self.0.on_connection_loss(cb) + } + + /// 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 media + /// tracks that correspond to this settings. [`MediaStreamSettings`] + /// update will change media tracks in all sending peers, so that might + /// cause new [getUserMedia()][1] request. + /// + /// Media obtaining/injection errors are additionally fired to + /// `on_failed_local_media` callback. + /// + /// If `stop_first` set to `true` then affected [`local::Track`]s will be + /// dropped before new [`MediaStreamSettings`] is applied. This is usually + /// required when changing video source device due to hardware limitations, + /// e.g. having an active track sourced from device `A` may hinder + /// [getUserMedia()][1] requests to device `B`. + /// + /// `rollback_on_fail` option configures [`MediaStreamSettings`] update + /// request to automatically rollback to previous settings if new settings + /// cannot be applied. + /// + /// If recovering from fail state isn't possible then affected media types + /// will be disabled. + /// + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia + pub fn set_local_media_settings( + &self, + settings: &api::MediaStreamSettings, + stop_first: bool, + rollback_on_fail: bool, + ) -> Promise { + let this = self.0.clone(); + let settings = settings.clone(); + + future_to_promise(async move { + this.set_local_media_settings( + settings.into(), + stop_first, + rollback_on_fail, + ) + .await + .map_err(api::ConstraintsUpdateException::from)?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Mutes outbound audio in this [`Room`]. + pub fn mute_audio(&self) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.mute_audio().await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Unmutes outbound audio in this [`Room`]. + pub fn unmute_audio(&self) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.unmute_audio().await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Mutes outbound video in this [`Room`]. + pub fn mute_video(&self, source_kind: Option) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.mute_video(source_kind.map(Into::into)).await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Unmutes outbound video in this [`Room`]. + pub fn unmute_video( + &self, + source_kind: Option, + ) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.unmute_video(source_kind.map(Into::into)) + .await + .map_err(JasonError::from)?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Disables outbound audio in this [`Room`]. + pub fn disable_audio(&self) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.disable_audio().await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Enables outbound audio in this [`Room`]. + pub fn enable_audio(&self) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.enable_audio().await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Disables outbound video. + /// + /// Affects only video with specific [`JsMediaSourceKind`] if specified. + pub fn disable_video( + &self, + source_kind: Option, + ) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.disable_video(source_kind.map(Into::into)) + .await + .map_err(JasonError::from)?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Enables outbound video. + /// + /// Affects only video with specific [`JsMediaSourceKind`] if specified. + pub fn enable_video( + &self, + source_kind: Option, + ) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.enable_video(source_kind.map(Into::into)) + .await + .map_err(JasonError::from)?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Disables inbound audio in this [`Room`]. + pub fn disable_remote_audio(&self) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.disable_remote_audio().await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Disables inbound video in this [`Room`]. + pub fn disable_remote_video(&self) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.disable_remote_video().await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Enables inbound audio in this [`Room`]. + pub fn enable_remote_audio(&self) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.enable_audio().await?; + Ok(JsValue::UNDEFINED) + }) + } + + /// Enables inbound video in this [`Room`]. + pub fn enable_remote_video(&self) -> Promise { + let this = self.0.clone(); + + future_to_promise(async move { + this.enable_remote_video().await?; + Ok(JsValue::UNDEFINED) + }) + } +} diff --git a/jason/src/api/connection.rs b/jason/src/core/connection.rs similarity index 92% rename from jason/src/api/connection.rs rename to jason/src/core/connection.rs index 52b1952fe..8d985caa0 100644 --- a/jason/src/api/connection.rs +++ b/jason/src/core/connection.rs @@ -7,11 +7,13 @@ use std::{ }; use medea_client_api_proto::{ConnectionQualityScore, MemberId, PeerId}; -use wasm_bindgen::prelude::*; use crate::{ - media::track::remote, - utils::{Callback0, Callback1, HandlerDetachedError}, + api, + core::{ + media::track::remote, + utils::{Callback0, Callback1, HandlerDetachedError, JasonError}, + }, }; /// Service which manages [`Connection`]s with the remote `Member`s. @@ -25,7 +27,7 @@ pub struct Connections { /// Callback from JS side which will be invoked on remote `Member` media /// stream arrival. - on_new_connection: Callback1, + on_new_connection: Callback1, } impl Connections { @@ -87,7 +89,6 @@ impl Connections { /// Connection with a specific remote `Member`, that is used on JS side. /// /// Actually, represents a [`Weak`]-based handle to `InnerConnection`. -#[wasm_bindgen] pub struct ConnectionHandle(Weak); /// Actual data of a connection with a specific remote `Member`. @@ -103,7 +104,7 @@ struct InnerConnection { /// JS callback, that will be invoked when [`remote::Track`] is /// received. - on_remote_track_added: Callback1, + on_remote_track_added: Callback1, /// JS callback, that will be invoked when [`ConnectionQualityScore`] will /// be updated. @@ -113,15 +114,14 @@ struct InnerConnection { on_close: Callback0, } -#[wasm_bindgen] impl ConnectionHandle { /// Sets callback, which will be invoked when this `Connection` will close. - pub fn on_close(&self, f: js_sys::Function) -> Result<(), JsValue> { + pub fn on_close(&self, f: js_sys::Function) -> Result<(), JasonError> { upgrade_or_detached!(self.0).map(|inner| inner.on_close.set_func(f)) } /// Returns remote `Member` ID. - pub fn get_remote_member_id(&self) -> Result { + pub fn get_remote_member_id(&self) -> Result { upgrade_or_detached!(self.0).map(|inner| inner.remote_id.0.clone()) } @@ -130,7 +130,7 @@ impl ConnectionHandle { pub fn on_remote_track_added( &self, f: js_sys::Function, - ) -> Result<(), JsValue> { + ) -> Result<(), JasonError> { upgrade_or_detached!(self.0) .map(|inner| inner.on_remote_track_added.set_func(f)) } @@ -140,7 +140,7 @@ impl ConnectionHandle { pub fn on_quality_score_update( &self, f: js_sys::Function, - ) -> Result<(), JsValue> { + ) -> Result<(), JasonError> { upgrade_or_detached!(self.0) .map(|inner| inner.on_quality_score_update.set_func(f)) } diff --git a/jason/src/media/constraints.rs b/jason/src/core/media/constraints.rs similarity index 80% rename from jason/src/media/constraints.rs rename to jason/src/core/media/constraints.rs index b434ab024..973d0bb8a 100644 --- a/jason/src/media/constraints.rs +++ b/jason/src/core/media/constraints.rs @@ -5,20 +5,21 @@ use std::{ rc::Rc, }; -use derive_more::{AsRef, Into}; use medea_client_api_proto::{ AudioSettings as ProtoAudioConstraints, MediaSourceKind, MediaType as ProtoTrackConstraints, MediaType, VideoSettings, }; -use wasm_bindgen::prelude::*; -use web_sys as sys; use crate::{ - media::MediaKind, - peer::{ - media_exchange_state, mute_state, LocalStreamUpdateCriteria, MediaState, + api::FacingMode, + core::{ + media::MediaKind, + peer::{ + media_exchange_state, mute_state, LocalStreamUpdateCriteria, + MediaState, + }, }, - utils::get_property_by_name, + platform::*, }; /// Local media stream for injecting into new created [`PeerConnection`]s. @@ -188,12 +189,11 @@ impl Default for AudioMediaTracksSettings { } } -/// Returns `true` if provided [`sys::MediaStreamTrack`] basically satisfies any -/// constraints with a provided [`MediaKind`]. +/// Returns `true` if provided [`MediaStreamTrack`] basically +/// satisfies any constraints with a provided [`MediaKind`]. #[inline] -fn satisfies_track(track: &sys::MediaStreamTrack, kind: MediaKind) -> bool { - track.kind() == kind.as_str() - && track.ready_state() == sys::MediaStreamTrackState::Live +fn satisfies_track(track: &MediaStreamTrack, kind: MediaKind) -> bool { + track.kind() == kind && track.ready_state() == MediaStreamTrackState::Live } /// [MediaStreamConstraints][1] for the video media type. @@ -270,11 +270,11 @@ impl VideoTrackConstraints { } impl VideoTrackConstraints { - /// Indicates whether the provided [`sys::MediaStreamTrack`] satisfies + /// Indicates whether the provided [`MediaStreamTrack`] satisfies /// device [`VideoTrackConstraints::constraints`]. /// /// Returns `false` if [`VideoTrackConstraints::constraints`] is not set. - fn satisfies(&self, track: &sys::MediaStreamTrack) -> bool { + pub fn satisfies>(&self, track: T) -> bool { self.constraints .as_ref() .filter(|_| self.enabled()) @@ -283,11 +283,11 @@ impl VideoTrackConstraints { } impl VideoTrackConstraints { - /// Indicates whether the provided [`sys::MediaStreamTrack`] satisfies + /// Indicates whether the provided [`MediaStreamTrack`] satisfies /// device [`VideoTrackConstraints::constraints`]. /// /// Returns `false` if [`VideoTrackConstraints::constraints`] is not set. - fn satisfies(&self, track: &sys::MediaStreamTrack) -> bool { + pub fn satisfies>(&self, track: T) -> bool { self.constraints .as_ref() .filter(|_| self.enabled()) @@ -298,7 +298,6 @@ impl VideoTrackConstraints { /// [MediaStreamConstraints][1] wrapper. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamconstraints -#[wasm_bindgen] #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct MediaStreamSettings { /// [MediaStreamConstraints][1] for the audio media type. @@ -317,10 +316,8 @@ pub struct MediaStreamSettings { display_video: VideoTrackConstraints, } -#[wasm_bindgen] impl MediaStreamSettings { /// Creates new [`MediaStreamSettings`] with none constraints configured. - #[wasm_bindgen(constructor)] pub fn new() -> Self { Self { audio: AudioMediaTracksSettings { @@ -363,21 +360,20 @@ impl MediaStreamSettings { } impl MediaStreamSettings { - /// Returns `true` if provided [`sys::MediaStreamTrack`] satisfies some of - /// the [`VideoTrackConstraints`] from this [`MediaStreamSettings`]. + /// Returns `true` if provided [`MediaStreamTrack`] satisfies some + /// of the [`VideoTrackConstraints`] from this [`MediaStreamSettings`]. /// /// Unconstrains [`VideoTrackConstraints`] which this - /// [`sys::MediaStreamTrack`] satisfies by calling + /// [`MediaStreamTrack`] satisfies by calling /// [`VideoTrackConstraints::unconstrain`]. pub fn unconstrain_if_satisfies_video(&mut self, track: T) -> bool where - T: AsRef, + T: AsRef, { - let track = track.as_ref(); - if self.device_video.satisfies(track.as_ref()) { + if self.device_video.satisfies(&track) { self.device_video.unconstrain(); true - } else if self.display_video.satisfies(track.as_ref()) { + } else if self.display_video.satisfies(&track) { self.display_video.unconstrain(); true } else { @@ -638,21 +634,18 @@ pub enum MultiSourceTracksConstraints { /// Only [getUserMedia()][1] request is required. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia - Device(sys::MediaStreamConstraints), + Device(MediaStreamConstraints), /// Only [getDisplayMedia()][1] request is required. /// /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - Display(sys::DisplayMediaStreamConstraints), + Display(DisplayMediaStreamConstraints), /// Both [getUserMedia()][1] and [getDisplayMedia()][2] are required. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - DeviceAndDisplay( - sys::MediaStreamConstraints, - sys::DisplayMediaStreamConstraints, - ), + DeviceAndDisplay(MediaStreamConstraints, DisplayMediaStreamConstraints), } impl From for Option { @@ -669,10 +662,9 @@ impl From for Option { constraints.device_video.constraints { device_cons - .get_or_insert_with(sys::MediaStreamConstraints::new) + .get_or_insert_with(MediaStreamConstraints::new) .video( - &sys::MediaTrackConstraints::from(device_video_cons) - .into(), + &MediaTrackConstraints::from(device_video_cons).into(), ); } } @@ -681,21 +673,18 @@ impl From for Option { constraints.display_video.constraints { display_cons - .get_or_insert_with(sys::DisplayMediaStreamConstraints::new) + .get_or_insert_with(DisplayMediaStreamConstraints::new) .video( - &sys::MediaTrackConstraints::from(display_video_cons) - .into(), + &MediaTrackConstraints::from(display_video_cons).into(), ); } } if is_device_audio_enabled { device_cons - .get_or_insert_with(sys::MediaStreamConstraints::new) + .get_or_insert_with(MediaStreamConstraints::new) .audio( - &sys::MediaTrackConstraints::from( - constraints.audio.constraints, - ) - .into(), + &MediaTrackConstraints::from(constraints.audio.constraints) + .into(), ); } @@ -750,8 +739,7 @@ impl VideoSource { /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack #[inline] - pub fn satisfies>(&self, track: T) -> bool { - let track = track.as_ref(); + pub fn satisfies>(&self, track: T) -> bool { match self { VideoSource::Display(display) => display.satisfies(&track), VideoSource::Device(device) => device.satisfies(track), @@ -796,7 +784,7 @@ impl TrackConstraints { /// [`TrackConstraints`]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - pub fn satisfies>(&self, track: T) -> bool { + pub fn satisfies>(&self, track: T) -> bool { match self { Self::Audio(audio) => audio.satisfies(&track), Self::Video(video) => video.satisfies(&track), @@ -853,12 +841,11 @@ impl From for TrackConstraints { // wasm-bindgen. /// Constraints applicable to audio tracks. -#[wasm_bindgen] #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct AudioTrackConstraints { /// The identifier of the device generating the content for the media /// track. - device_id: Option>, + device_id: Option>, /// Importance of this [`AudioTrackConstraints`]. /// @@ -867,10 +854,8 @@ pub struct AudioTrackConstraints { required: bool, } -#[wasm_bindgen] impl AudioTrackConstraints { /// Creates new [`AudioTrackConstraints`] with none constraints configured. - #[wasm_bindgen(constructor)] pub fn new() -> Self { Self::default() } @@ -879,19 +864,17 @@ impl AudioTrackConstraints { /// /// [1]: https://w3.org/TR/mediacapture-streams/#def-constraint-deviceId pub fn device_id(&mut self, device_id: String) { - self.device_id = Some(ConstrainString::Exact(DeviceId(device_id))); + self.device_id = Some(ConstrainString::Exact(device_id)); } -} -impl AudioTrackConstraints { /// Checks if provided [MediaStreamTrack][1] satisfies constraints /// contained. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - pub fn satisfies>(&self, track: T) -> bool { + pub fn satisfies>(&self, track: T) -> bool { let track = track.as_ref(); satisfies_track(track, MediaKind::Audio) - && ConstrainString::satisfies(&self.device_id, track) + && ConstrainString::satisfies(&self.device_id, &track.device_id()) // TODO returns Result } @@ -926,80 +909,19 @@ impl From for AudioTrackConstraints { } } -impl From for sys::MediaTrackConstraints { +impl From for MediaTrackConstraints { fn from(track_constraints: AudioTrackConstraints) -> Self { let mut constraints = Self::new(); if let Some(device_id) = track_constraints.device_id { - constraints.device_id(&sys::ConstrainDomStringParameters::from( - &device_id, - )); + constraints + .device_id(&ConstrainDomStringParameters::from(&device_id)); } constraints } } -/// Constraints applicable to [MediaStreamTrack][1]. -/// -/// Constraints provide a general control surface that allows applications to -/// both select an appropriate source for a track and, once selected, to -/// influence how a source operates. -/// -/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack -trait Constraint { - /// Constrained parameter field name. - const TRACK_SETTINGS_FIELD_NAME: &'static str; -} - -/// The identifier of the device generating the content of the -/// [MediaStreamTrack][1]. -/// -/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack -#[derive(AsRef, Clone, Debug, Eq, PartialEq)] -#[as_ref(forward)] -struct DeviceId(String); - -impl Constraint for DeviceId { - const TRACK_SETTINGS_FIELD_NAME: &'static str = "deviceId"; -} - -/// Height, in pixels, of the video. -#[derive(Clone, Copy, Debug, Eq, Into, PartialEq)] -struct Height(u32); - -impl Constraint for Height { - const TRACK_SETTINGS_FIELD_NAME: &'static str = "height"; -} - -/// Width, in pixels, of the video. -#[derive(Clone, Copy, Debug, Eq, Into, PartialEq)] -struct Width(u32); - -impl Constraint for Width { - const TRACK_SETTINGS_FIELD_NAME: &'static str = "width"; -} - -/// Describes the directions that the camera can face, as seen from the user's -/// perspective. Representation of [VideoFacingModeEnum][1]. -/// -/// [1]: https://w3.org/TR/mediacapture-streams/#dom-videofacingmodeenum -#[wasm_bindgen] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum FacingMode { - /// Facing toward the user (a self-view camera). - User, - - /// Facing away from the user (viewing the environment). - Environment, - - /// Facing to the left of the user. - Left, - - /// Facing to the right of the user. - Right, -} - impl AsRef for FacingMode { fn as_ref(&self) -> &str { match self { @@ -1011,65 +933,51 @@ impl AsRef for FacingMode { } } -impl Constraint for FacingMode { - const TRACK_SETTINGS_FIELD_NAME: &'static str = "facingMode"; -} - /// Representation of the [ConstrainULong][1]. Underlying value must fit in /// `[0, 4294967295]` range. /// /// [1]: https://tinyurl.com/w3-streams#dom-constrainulong #[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum ConstrainU32 { +enum ConstrainU32 { /// Must be the parameter's value. - Exact(T), + Exact(u32), /// Should be used if possible. - Ideal(T), + Ideal(u32), /// Parameter's value must be in this range. - Range(T, T), + Range(u32, u32), } -impl> ConstrainU32 { +impl ConstrainU32 { // It's up to `::TRACK_SETTINGS_FIELD_NAME` to guarantee // that such casts are safe. #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - fn satisfies(this: Option, track: &sys::MediaStreamTrack) -> bool { + fn satisfies(this: Option, setting: Option) -> bool { match this { None | Some(ConstrainU32::Ideal(_)) => true, - Some(ConstrainU32::Exact(exact)) => get_property_by_name( - &track.get_settings(), - T::TRACK_SETTINGS_FIELD_NAME, - |v| v.as_f64().map(|v| v as u32), - ) - .map_or(false, |val| val == exact.into()), - Some(ConstrainU32::Range(start, end)) => get_property_by_name( - &track.get_settings(), - T::TRACK_SETTINGS_FIELD_NAME, - |v| v.as_f64().map(|v| v as u32), - ) - .map_or(false, |val| val >= start.into() && val <= end.into()), + Some(ConstrainU32::Exact(exact)) => { + setting.map_or(false, |val| val == exact) + } + Some(ConstrainU32::Range(start, end)) => { + setting.map_or(false, |val| val >= start && val <= end) + } } } } -impl> From> - for sys::ConstrainDoubleRange -{ - fn from(from: ConstrainU32) -> Self { - let mut constraint = sys::ConstrainDoubleRange::new(); +impl From for ConstrainDoubleRange { + fn from(from: ConstrainU32) -> Self { + let mut constraint = ConstrainDoubleRange::new(); match from { ConstrainU32::Exact(val) => { - constraint.exact(f64::from(val.into())); + constraint.exact(f64::from(val)); } ConstrainU32::Ideal(val) => { - constraint.ideal(f64::from(val.into())); + constraint.ideal(f64::from(val)); } ConstrainU32::Range(min, max) => { - constraint - .min(f64::from(min.into())) - .max(f64::from(max.into())); + constraint.min(f64::from(min)).max(f64::from(max)); } } @@ -1089,25 +997,20 @@ enum ConstrainString { Ideal(T), } -impl> ConstrainString { - fn satisfies(this: &Option, track: &sys::MediaStreamTrack) -> bool { +impl> ConstrainString { + fn satisfies(this: &Option, setting: &Option) -> bool { match this { None | Some(ConstrainString::Ideal(_)) => true, - Some(ConstrainString::Exact(constrain)) => get_property_by_name( - &track.get_settings(), - T::TRACK_SETTINGS_FIELD_NAME, - |v| v.as_string(), - ) - .map_or(false, |id| id.as_str() == constrain.as_ref()), + Some(ConstrainString::Exact(constrain)) => setting + .as_ref() + .map_or(false, |val| val.as_ref() == constrain.as_ref()), } } } -impl> From<&ConstrainString> - for sys::ConstrainDomStringParameters -{ +impl> From<&ConstrainString> for ConstrainDomStringParameters { fn from(from: &ConstrainString) -> Self { - let mut constraint = sys::ConstrainDomStringParameters::new(); + let mut constraint = ConstrainDomStringParameters::new(); match from { ConstrainString::Exact(val) => { constraint.exact(&JsValue::from_str(val.as_ref())) @@ -1123,7 +1026,6 @@ impl> From<&ConstrainString> /// Constraints applicable to video tracks that are sourced from some media /// device. -#[wasm_bindgen] #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct DeviceVideoTrackConstraints { /// Importance of this [`DeviceVideoTrackConstraints`]. @@ -1134,69 +1036,23 @@ pub struct DeviceVideoTrackConstraints { /// The identifier of the device generating the content for the media /// track. - device_id: Option>, + device_id: Option>, /// Describes the directions that the camera can face, as seen from the /// user's perspective. facing_mode: Option>, /// Height of the video in pixels. - height: Option>, + height: Option, /// Width of the video in pixels. - width: Option>, -} - -impl DeviceVideoTrackConstraints { - /// Checks if provided [MediaStreamTrack][1] satisfies - /// [`DeviceVideoTrackConstraints`] contained. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - pub fn satisfies(&self, track: &sys::MediaStreamTrack) -> bool { - satisfies_track(track, MediaKind::Video) - && ConstrainString::satisfies(&self.device_id, track) - && ConstrainString::satisfies(&self.facing_mode, track) - && ConstrainU32::satisfies(self.height, track) - && ConstrainU32::satisfies(self.width, track) - && !guess_is_from_display(&track) - } - - /// Merges this [`DeviceVideoTrackConstraints`] with `another` one , meaning - /// that if some constraint is not set on this one, then it will be applied - /// from `another`. - pub fn merge(&mut self, another: DeviceVideoTrackConstraints) { - if self.device_id.is_none() && another.device_id.is_some() { - self.device_id = another.device_id; - } - if !self.required && another.required { - self.required = another.required; - } - if self.facing_mode.is_none() && another.facing_mode.is_some() { - self.facing_mode = another.facing_mode; - } - if self.height.is_none() && another.height.is_some() { - self.height = another.height; - } - if self.width.is_none() && another.width.is_some() { - self.width = another.width; - } - } - - /// Returns importance of this [`DeviceVideoTrackConstraints`]. - /// - /// If this [`DeviceVideoTrackConstraints`] is important then without this - /// [`DeviceVideoTrackConstraints`] call session can't be started. - pub fn required(&self) -> bool { - self.required - } + width: Option, } /// Constraints applicable to video tracks that are sourced from screen-capture. -#[wasm_bindgen] impl DeviceVideoTrackConstraints { /// Creates new [`DeviceVideoTrackConstraints`] with none constraints /// configured. - #[wasm_bindgen(constructor)] pub fn new() -> Self { Self::default() } @@ -1205,7 +1061,7 @@ impl DeviceVideoTrackConstraints { /// /// [1]: https://w3.org/TR/mediacapture-streams/#def-constraint-deviceId pub fn device_id(&mut self, device_id: String) { - self.device_id = Some(ConstrainString::Exact(DeviceId(device_id))); + self.device_id = Some(ConstrainString::Exact(device_id)); } /// Sets exact [facingMode][1] constraint. @@ -1226,47 +1082,93 @@ impl DeviceVideoTrackConstraints { /// /// [1]: https://tinyurl.com/w3-streams#def-constraint-height pub fn exact_height(&mut self, height: u32) { - self.height = Some(ConstrainU32::Exact(Height(height))); + self.height = Some(ConstrainU32::Exact(height)); } /// Sets ideal [`height`][1] constraint. /// /// [1]: https://tinyurl.com/w3-streams#def-constraint-height pub fn ideal_height(&mut self, height: u32) { - self.height = Some(ConstrainU32::Ideal(Height(height))); + self.height = Some(ConstrainU32::Ideal(height)); } /// Sets range of [`height`][1] constraint. /// /// [1]: https://tinyurl.com/w3-streams#def-constraint-height pub fn height_in_range(&mut self, min: u32, max: u32) { - self.height = Some(ConstrainU32::Range(Height(min), Height(max))); + self.height = Some(ConstrainU32::Range(min, max)); } /// Sets exact [`width`][1] constraint. /// /// [1]: https://tinyurl.com/w3-streams#def-constraint-width pub fn exact_width(&mut self, width: u32) { - self.width = Some(ConstrainU32::Exact(Width(width))); + self.width = Some(ConstrainU32::Exact(width)); } /// Sets ideal [`width`][1] constraint. /// /// [1]: https://tinyurl.com/w3-streams#def-constraint-width pub fn ideal_width(&mut self, width: u32) { - self.width = Some(ConstrainU32::Ideal(Width(width))); + self.width = Some(ConstrainU32::Ideal(width)); } /// Sets range of [`width`][1] constraint. /// /// [1]: https://tinyurl.com/w3-streams#def-constraint-width pub fn width_in_range(&mut self, min: u32, max: u32) { - self.width = Some(ConstrainU32::Range(Width(min), Width(max))); + self.width = Some(ConstrainU32::Range(min, max)); + } + + /// Checks if provided [MediaStreamTrack][1] satisfies + /// [`DeviceVideoTrackConstraints`] contained. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + // pub fn satisfies(&self, track: &MediaStreamTrack) -> bool { + pub fn satisfies>(&self, track: T) -> bool { + let track = track.as_ref(); + satisfies_track(track, MediaKind::Video) + && ConstrainString::satisfies(&self.device_id, &track.device_id()) + && ConstrainString::satisfies( + &self.facing_mode, + &track.facing_mode(), + ) + && ConstrainU32::satisfies(self.height, track.height()) + && ConstrainU32::satisfies(self.width, track.width()) + && !track.guess_is_from_display() + } + + /// Merges this [`DeviceVideoTrackConstraints`] with `another` one , meaning + /// that if some constraint is not set on this one, then it will be applied + /// from `another`. + pub fn merge(&mut self, another: DeviceVideoTrackConstraints) { + if self.device_id.is_none() && another.device_id.is_some() { + self.device_id = another.device_id; + } + if !self.required && another.required { + self.required = another.required; + } + if self.facing_mode.is_none() && another.facing_mode.is_some() { + self.facing_mode = another.facing_mode; + } + if self.height.is_none() && another.height.is_some() { + self.height = another.height; + } + if self.width.is_none() && another.width.is_some() { + self.width = another.width; + } + } + + /// Returns importance of this [`DeviceVideoTrackConstraints`]. + /// + /// If this [`DeviceVideoTrackConstraints`] is important then without this + /// [`DeviceVideoTrackConstraints`] call session can't be started. + pub fn required(&self) -> bool { + self.required } } /// Constraints applicable to video tracks sourced from screen capture. -#[wasm_bindgen] #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct DisplayVideoTrackConstraints { /// Importance of this [`DisplayVideoTrackConstraints`]. @@ -1277,15 +1179,22 @@ pub struct DisplayVideoTrackConstraints { } impl DisplayVideoTrackConstraints { + /// Creates new [`DisplayVideoTrackConstraints`] with none constraints + /// configured. + pub fn new() -> Self { + Self::default() + } + /// Checks if provided [MediaStreamTrack][1] satisfies /// [`DisplayVideoTrackConstraints`] contained. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack #[allow(clippy::unused_self)] #[inline] - pub fn satisfies(&self, track: &sys::MediaStreamTrack) -> bool { + pub fn satisfies>(&self, track: T) -> bool { + let track = track.as_ref(); satisfies_track(track, MediaKind::Video) - && guess_is_from_display(&track) + && track.guess_is_from_display() } /// Merges this [`DisplayVideoTrackConstraints`] with `another` one, @@ -1308,63 +1217,30 @@ impl DisplayVideoTrackConstraints { } } -#[wasm_bindgen] -impl DisplayVideoTrackConstraints { - /// Creates new [`DisplayVideoTrackConstraints`] with none constraints - /// configured. - #[wasm_bindgen(constructor)] - pub fn new() -> Self { - Self::default() - } -} - -/// Detects if video track captured from display searching [specific fields][1] -/// in its settings. Only works in Chrome atm. -/// -/// [1]: https://w3.org/TR/screen-capture/#extensions-to-mediatracksettings -fn guess_is_from_display(track: &sys::MediaStreamTrack) -> bool { - let settings = track.get_settings(); - - let has_display_surface = - get_property_by_name(&settings, "displaySurface", |val| { - val.as_string() - }) - .is_some(); - - if has_display_surface { - true - } else { - get_property_by_name(&settings, "logicalSurface", |val| val.as_string()) - .is_some() - } -} - -impl From for sys::MediaTrackConstraints { +impl From for MediaTrackConstraints { fn from(track_constraints: DeviceVideoTrackConstraints) -> Self { let mut constraints = Self::new(); if let Some(device_id) = track_constraints.device_id { - constraints.device_id(&sys::ConstrainDomStringParameters::from( - &device_id, - )); + constraints + .device_id(&ConstrainDomStringParameters::from(&device_id)); } if let Some(facing_mode) = track_constraints.facing_mode { - constraints.facing_mode(&sys::ConstrainDomStringParameters::from( - &facing_mode, - )); + constraints + .facing_mode(&ConstrainDomStringParameters::from(&facing_mode)); } if let Some(width) = track_constraints.width { - constraints.width(&sys::ConstrainDoubleRange::from(width)); + constraints.width(&ConstrainDoubleRange::from(width)); } if let Some(height) = track_constraints.height { - constraints.height(&sys::ConstrainDoubleRange::from(height)); + constraints.height(&ConstrainDoubleRange::from(height)); } constraints } } -impl From for sys::MediaTrackConstraints { +impl From for MediaTrackConstraints { fn from(_: DisplayVideoTrackConstraints) -> Self { Self::new() } diff --git a/jason/src/media/manager.rs b/jason/src/core/media/manager.rs similarity index 63% rename from jason/src/media/manager.rs rename to jason/src/core/media/manager.rs index 0d930c8fe..b740f6042 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/core/media/manager.rs @@ -3,52 +3,52 @@ use std::{ cell::RefCell, collections::HashMap, - convert::TryFrom, rc::{Rc, Weak}, }; use derive_more::Display; -use js_sys::Promise; use medea_client_api_proto::MediaSourceKind; use tracerr::Traced; -use wasm_bindgen::{prelude::*, JsValue}; -use wasm_bindgen_futures::{future_to_promise, JsFuture}; -use web_sys as sys; use crate::{ - media::{MediaStreamSettings, MultiSourceTracksConstraints}, - utils::{window, HandlerDetachedError, JasonError, JsCaused, JsError}, - MediaKind, + core::{ + media::{MediaKind, MediaStreamSettings, MultiSourceTracksConstraints}, + utils::{HandlerDetachedError, JasonError, JsCaused}, + }, + platform, }; -use super::{track::local, InputDeviceInfo}; +use super::track::local; + +use crate::platform::Error; /// Errors that may occur in a [`MediaManager`]. #[derive(Clone, Debug, Display, JsCaused)] +#[js(error = "platform::Error")] pub enum MediaManagerError { /// Occurs when cannot get access to [MediaDevices][1] object. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediadevices #[display(fmt = "Navigator.mediaDevices() failed: {}", _0)] - CouldNotGetMediaDevices(JsError), + CouldNotGetMediaDevices(Error), /// Occurs if the [getUserMedia][1] request failed. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia #[display(fmt = "MediaDevices.getUserMedia() failed: {}", _0)] - GetUserMediaFailed(JsError), + GetUserMediaFailed(Error), /// Occurs if the [getDisplayMedia()][1] request failed. /// /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia #[display(fmt = "MediaDevices.getDisplayMedia() failed: {}", _0)] - GetDisplayMediaFailed(JsError), + GetDisplayMediaFailed(Error), /// Occurs when cannot get info about connected [MediaDevices][1]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediadevices #[display(fmt = "MediaDevices.enumerateDevices() failed: {}", _0)] - EnumerateDevicesFailed(JsError), + EnumerateDevicesFailed(Error), /// Occurs when local track is [`ended`][1] right after [getUserMedia()][2] /// or [getDisplayMedia()][3] request. @@ -83,38 +83,9 @@ struct InnerMediaManager { } impl InnerMediaManager { - /// Returns the vector of [`InputDeviceInfo`] objects. - async fn enumerate_devices() -> Result> { - use MediaManagerError::{ - CouldNotGetMediaDevices, EnumerateDevicesFailed, - }; - - let devices = window() - .navigator() - .media_devices() - .map_err(JsError::from) - .map_err(CouldNotGetMediaDevices) - .map_err(tracerr::from_and_wrap!())?; - let devices = JsFuture::from( - devices - .enumerate_devices() - .map_err(JsError::from) - .map_err(EnumerateDevicesFailed) - .map_err(tracerr::from_and_wrap!())?, - ) - .await - .map_err(JsError::from) - .map_err(EnumerateDevicesFailed) - .map_err(tracerr::from_and_wrap!())?; - - Ok(js_sys::Array::from(&devices) - .values() - .into_iter() - .filter_map(|info| { - let info = web_sys::MediaDeviceInfo::from(info.unwrap()); - InputDeviceInfo::try_from(info).ok() - }) - .collect()) + /// Returns the vector of [`platform::InputDeviceInfo`] objects. + async fn enumerate_devices() -> Result> { + platform::enumerate_devices().await } /// Obtains [`local::Track`]s based on a provided @@ -207,7 +178,7 @@ impl InnerMediaManager { if caps.is_audio_enabled() { let track = storage .iter() - .find(|track| caps.get_audio().satisfies(track.sys_track())) + .find(|&track| caps.get_audio().satisfies(track.as_ref())) .cloned(); if let Some(track) = track { @@ -219,8 +190,8 @@ impl InnerMediaManager { tracks.extend( storage .iter() - .filter(|track| { - caps.unconstrain_if_satisfies_video(track.sys_track()) + .filter(|&track| { + caps.unconstrain_if_satisfies_video(track.as_ref()) }) .cloned(), ); @@ -236,31 +207,11 @@ impl InnerMediaManager { /// [2]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia async fn get_user_media( &self, - caps: sys::MediaStreamConstraints, + caps: platform::MediaStreamConstraints, ) -> Result>> { - use MediaManagerError::{CouldNotGetMediaDevices, GetUserMediaFailed}; - - let media_devices = window() - .navigator() - .media_devices() - .map_err(JsError::from) - .map_err(CouldNotGetMediaDevices) - .map_err(tracerr::from_and_wrap!())?; - - let stream = JsFuture::from( - media_devices - .get_user_media_with_constraints(&caps) - .map_err(JsError::from) - .map_err(GetUserMediaFailed) - .map_err(tracerr::from_and_wrap!())?, - ) - .await - .map(sys::MediaStream::from) - .map_err(JsError::from) - .map_err(GetUserMediaFailed) - .map_err(tracerr::from_and_wrap!())?; - - Ok(self.parse_and_save_tracks(stream, MediaSourceKind::Device)?) + let tracks = platform::get_user_media(caps).await?; + + Ok(self.parse_and_save_tracks(tracks, MediaSourceKind::Device)?) } /// Obtains new [MediaStream][1] making [getDisplayMedia()][2] call, saves @@ -271,42 +222,20 @@ impl InnerMediaManager { /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia async fn get_display_media( &self, - caps: sys::DisplayMediaStreamConstraints, + caps: platform::DisplayMediaStreamConstraints, ) -> Result>> { - use MediaManagerError::{ - CouldNotGetMediaDevices, GetDisplayMediaFailed, GetUserMediaFailed, - }; - - let media_devices = window() - .navigator() - .media_devices() - .map_err(JsError::from) - .map_err(CouldNotGetMediaDevices) - .map_err(tracerr::from_and_wrap!())?; - - let stream = JsFuture::from( - media_devices - .get_display_media_with_constraints(&caps) - .map_err(JsError::from) - .map_err(GetDisplayMediaFailed) - .map_err(tracerr::from_and_wrap!())?, - ) - .await - .map(sys::MediaStream::from) - .map_err(JsError::from) - .map_err(GetUserMediaFailed) - .map_err(tracerr::from_and_wrap!())?; - - Ok(self.parse_and_save_tracks(stream, MediaSourceKind::Display)?) + let tracks = platform::get_display_media(caps).await?; + + Ok(self.parse_and_save_tracks(tracks, MediaSourceKind::Display)?) } - /// Retrieves tracks from provided [`sys::MediaStream`], saves tracks weak - /// references in [`MediaManager`] tracks storage. + /// Retrieves tracks from provided [`platform::MediaStream`], saves tracks + /// weak references in [`MediaManager`] tracks storage. /// /// # Errors /// /// With [`MediaManagerError::LocalTrackIsEnded`] if at least one track from - /// the provided [`sys::MediaStream`] is in [`ended`][1] state. + /// the provided [`platform::MediaStream`] is in [`ended`][1] state. /// /// In case of error all tracks are stopped and are not saved in /// [`MediaManager`]'s tracks storage. @@ -315,32 +244,29 @@ impl InnerMediaManager { #[allow(clippy::needless_pass_by_value)] fn parse_and_save_tracks( &self, - stream: sys::MediaStream, + tracks: Vec, kind: MediaSourceKind, ) -> Result>> { use MediaManagerError::LocalTrackIsEnded; let mut storage = self.tracks.borrow_mut(); - let tracks: Vec<_> = js_sys::try_iter(&stream.get_tracks()) - .unwrap() - .unwrap() - .map(|tr| Rc::new(local::Track::new(tr.unwrap().into(), kind))) - .collect(); // Tracks returned by getDisplayMedia()/getUserMedia() request should be // `live`. Otherwise, we should err without caching tracks in // `MediaManager`. Tracks will be stopped on `Drop`. for track in &tracks { - if track.sys_track().ready_state() - != sys::MediaStreamTrackState::Live - { + if track.ready_state() != platform::MediaStreamTrackState::Live { return Err(tracerr::new!(LocalTrackIsEnded(track.kind()))); } } - for track in &tracks { - storage.insert(track.id(), Rc::downgrade(&track)); - } + let tracks = tracks + .into_iter() + .map(|tr| Rc::new(local::Track::new(tr, kind))) + .inspect(|track| { + storage.insert(track.id(), Rc::downgrade(track)); + }) + .collect(); Ok(tracks) } @@ -387,52 +313,40 @@ impl MediaManager { /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia -#[wasm_bindgen] +#[derive(Clone)] pub struct MediaManagerHandle(Weak); -#[wasm_bindgen] #[allow(clippy::unused_self)] impl MediaManagerHandle { - /// Returns array of [`InputDeviceInfo`] objects, which represent available - /// media input and output devices, such as microphones, cameras, and so - /// forth. - pub fn enumerate_devices(&self) -> Promise { - future_to_promise(async { - InnerMediaManager::enumerate_devices() - .await - .map(|devices| { - devices - .into_iter() - .fold(js_sys::Array::new(), |devices_info, info| { - devices_info.push(&JsValue::from(info)); - devices_info - }) - .into() - }) - .map_err(tracerr::wrap!(=> MediaManagerError)) - .map_err(|e| JasonError::from(e).into()) - }) + /// Returns array of [`platform::InputDeviceInfo`] objects, which represent + /// available media input and output devices, such as microphones, + /// cameras, and so forth. + pub async fn enumerate_devices( + &self, + ) -> std::result::Result, JasonError> { + InnerMediaManager::enumerate_devices() + .await + .map(|tracks| tracks) + .map_err(tracerr::wrap!(=> MediaManagerError)) + .map_err(|e| JasonError::from(e).into()) } /// 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); - let caps = caps.clone(); - future_to_promise(async move { - inner? - .get_tracks(caps) - .await - .map(|tracks| { - tracks - .into_iter() - .map(|(t, _)| local::JsTrack::new(t)) - .map(JsValue::from) - .collect::() - .into() - }) - .map_err(tracerr::wrap!(=> MediaManagerError)) - .map_err(|e| JasonError::from(e).into()) - }) + pub async fn init_local_tracks( + &self, + caps: MediaStreamSettings, + ) -> std::result::Result, JasonError> { + upgrade_or_detached!(self.0, JasonError)? + .get_tracks(caps) + .await + .map(|tracks| { + tracks + .into_iter() + .map(|(t, _)| local::LocalMediaTrack::new(t)) + .collect::>() + }) + .map_err(tracerr::wrap!(=> MediaManagerError)) + .map_err(|e| JasonError::from(e).into()) } } diff --git a/jason/src/media/mod.rs b/jason/src/core/media/mod.rs similarity index 89% rename from jason/src/media/mod.rs rename to jason/src/core/media/mod.rs index b88615f5c..031074dd7 100644 --- a/jason/src/media/mod.rs +++ b/jason/src/core/media/mod.rs @@ -3,31 +3,27 @@ //! [1]: https://w3.org/TR/mediacapture-streams mod constraints; -mod device_info; mod manager; pub mod track; use derive_more::Display; -use wasm_bindgen::prelude::*; #[doc(inline)] pub use self::{ constraints::{ AudioMediaTracksSettings, AudioTrackConstraints, - DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, FacingMode, + DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, LocalTracksConstraints, MediaStreamSettings, MultiSourceTracksConstraints, RecvConstraints, TrackConstraints, VideoSource, VideoTrackConstraints, }, - device_info::InputDeviceInfo, manager::{MediaManager, MediaManagerError, MediaManagerHandle}, - track::JsMediaSourceKind, + track::MediaSourceKind, }; /// [MediaStreamTrack.kind][1] representation. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-kind -#[wasm_bindgen] #[derive(Clone, Copy, Debug, Display, Eq, PartialEq)] pub enum MediaKind { /// Audio track. diff --git a/jason/src/media/track/local.rs b/jason/src/core/media/track/local.rs similarity index 60% rename from jason/src/media/track/local.rs rename to jason/src/core/media/track/local.rs index fea609f3c..7e3f2e6d1 100644 --- a/jason/src/media/track/local.rs +++ b/jason/src/core/media/track/local.rs @@ -1,4 +1,4 @@ -//! Wrapper around [`sys::MediaStreamTrack`] received from +//! Wrapper around [`platform::MediaStreamTrack`] received from //! [getUserMedia()][1]/[getDisplayMedia()][2] request. //! //! [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia @@ -6,30 +6,30 @@ use std::rc::Rc; -use medea_client_api_proto::MediaSourceKind; -use wasm_bindgen::prelude::*; -use web_sys as sys; +use derive_more::AsRef; +use medea_client_api_proto as proto; -use crate::{media::MediaKind, JsMediaSourceKind}; +use crate::{ + core::media::{MediaKind, MediaSourceKind}, + platform, +}; -/// Wrapper around [`sys::MediaStreamTrack`] received from from +/// Wrapper around [`platform::MediaStreamTrack`] received from from /// [getUserMedia()][1]/[getDisplayMedia()][2] request. /// -/// Underlying [`sys::MediaStreamTrack`] is stopped on this [`Track`]'s +/// Underlying [`platform::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)] +#[derive(Debug, AsRef)] pub struct Track { - /// Actual [`sys::MediaStreamTrack`]. - track: sys::MediaStreamTrack, + /// Actual [`platform::MediaStreamTrack`]. + #[as_ref] + track: platform::MediaStreamTrack, - /// Underlying [`sys::MediaStreamTrack`] source kind. - source_kind: MediaSourceKind, - - /// Underlying [`sys::MediaStreamTrack`] kind. - kind: MediaKind, + /// Underlying [`platform::MediaStreamTrack`] source kind. + source_kind: proto::MediaSourceKind, /// Reference to the parent [`Track`]. /// @@ -41,22 +41,16 @@ pub struct Track { } impl Track { - /// Builds new [`Track`] from the provided [`sys::MediaStreamTrack`] and - /// [`MediaSourceKind`]. + /// Builds new [`Track`] from the provided [`platform::MediaStreamTrack`] + /// and [`proto::MediaSourceKind`]. #[must_use] pub fn new( - track: sys::MediaStreamTrack, - source_kind: MediaSourceKind, + track: platform::MediaStreamTrack, + source_kind: proto::MediaSourceKind, ) -> Self { - let kind = match track.kind().as_ref() { - "audio" => MediaKind::Audio, - "video" => MediaKind::Video, - _ => unreachable!(), - }; Self { track, source_kind, - kind, _parent: None, } } @@ -84,7 +78,7 @@ impl Track { /// Returns this [`Track`]'s media source kind. #[inline] #[must_use] - pub fn media_source_kind(&self) -> MediaSourceKind { + pub fn media_source_kind(&self) -> proto::MediaSourceKind { self.source_kind } @@ -92,13 +86,13 @@ impl Track { #[inline] #[must_use] pub fn kind(&self) -> MediaKind { - self.kind + self.track.kind() } /// Forks this [`Track`]. /// - /// Creates new [`sys::MediaStreamTrack`] from this [`Track`]'s - /// [`sys::MediaStreamTrack`] using [`clone()`][1] method. + /// Creates new [`platform::MediaStreamTrack`] from this [`Track`]'s + /// [`platform::MediaStreamTrack`] using [`clone()`][1] method. /// /// Forked [`Track`] will hold a strong reference to this [`Track`]. /// @@ -106,22 +100,13 @@ impl Track { #[must_use] pub fn fork(self: &Rc) -> Self { let parent = Rc::clone(self); - let track = sys::MediaStreamTrack::clone(&self.track); + let track = platform::MediaStreamTrack::clone(&self.track); Self { track, - kind: self.kind, source_kind: self.source_kind, _parent: Some(parent), } } - - /// 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 { @@ -132,23 +117,20 @@ impl Drop for Track { } /// Wrapper around strongly referenced [`Track`] for JS side. -#[wasm_bindgen(js_name = LocalMediaTrack)] -pub struct JsTrack(Rc); +pub struct LocalMediaTrack(Rc); -impl JsTrack { +impl LocalMediaTrack { /// Creates new [`JsTrack`] from the provided [`Track`]. #[inline] #[must_use] pub fn new(track: Rc) -> Self { - JsTrack(track) + LocalMediaTrack(track) } -} -#[wasm_bindgen(js_class = LocalMediaTrack)] -impl JsTrack { - /// Returns the underlying [`sys::MediaStreamTrack`] of this [`JsTrack`]. - pub fn get_track(&self) -> sys::MediaStreamTrack { - Clone::clone(self.0.track.as_ref()) + /// Returns the underlying [`platform::MediaStreamTrack`] of this + /// [`JsTrack`]. + pub fn get_track(&self) -> &platform::MediaStreamTrack { + &self.0.track } /// Returns [`MediaKind::Audio`] if this [`JsTrack`] represents an audio @@ -157,12 +139,12 @@ impl JsTrack { self.0.kind() } - /// Returns [`JsMediaSourceKind::Device`] if this [`JsTrack`] is sourced - /// from some device (webcam/microphone), or [`JsMediaSourceKind::Display`] + /// Returns [`MediaSourceKind::Device`] if this [`JsTrack`] is sourced + /// from some device (webcam/microphone), or [`MediaSourceKind::Display`] /// if ot is captured via [MediaDevices.getDisplayMedia()][1]. /// /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - pub fn media_source_kind(&self) -> JsMediaSourceKind { + pub fn media_source_kind(&self) -> MediaSourceKind { self.0.media_source_kind().into() } } diff --git a/jason/src/media/track/mod.rs b/jason/src/core/media/track/mod.rs similarity index 60% rename from jason/src/media/track/mod.rs rename to jason/src/core/media/track/mod.rs index 1353d6748..747c593e4 100644 --- a/jason/src/media/track/mod.rs +++ b/jason/src/core/media/track/mod.rs @@ -5,13 +5,11 @@ pub mod local; pub mod remote; -use medea_client_api_proto::MediaSourceKind; -use wasm_bindgen::prelude::*; +use medea_client_api_proto as proto; /// Media source type. -#[wasm_bindgen(js_name = MediaSourceKind)] #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum JsMediaSourceKind { +pub enum MediaSourceKind { /// Media is sourced from some media device (webcam or microphone). Device, @@ -19,22 +17,22 @@ pub enum JsMediaSourceKind { Display, } -impl From for MediaSourceKind { +impl From for proto::MediaSourceKind { #[inline] - fn from(val: JsMediaSourceKind) -> Self { + fn from(val: MediaSourceKind) -> Self { match val { - JsMediaSourceKind::Device => Self::Device, - JsMediaSourceKind::Display => Self::Display, + MediaSourceKind::Device => Self::Device, + MediaSourceKind::Display => Self::Display, } } } -impl From for JsMediaSourceKind { +impl From for MediaSourceKind { #[inline] - fn from(val: MediaSourceKind) -> Self { + fn from(val: proto::MediaSourceKind) -> Self { match val { - MediaSourceKind::Device => Self::Device, - MediaSourceKind::Display => Self::Display, + proto::MediaSourceKind::Device => Self::Device, + proto::MediaSourceKind::Display => Self::Display, } } } diff --git a/jason/src/media/track/remote.rs b/jason/src/core/media/track/remote.rs similarity index 60% rename from jason/src/media/track/remote.rs rename to jason/src/core/media/track/remote.rs index 89ccf297e..9a8dd6bde 100644 --- a/jason/src/media/track/remote.rs +++ b/jason/src/core/media/track/remote.rs @@ -1,26 +1,26 @@ -//! Wrapper around [`sys::MediaStreamTrack`] received from the remote. +//! Wrapper around [`platform::MediaStreamTrack`] received from the remote. use std::rc::Rc; use futures::StreamExt; -use medea_client_api_proto::MediaSourceKind; +use medea_client_api_proto as proto; use medea_reactive::ObservableCell; -use wasm_bindgen::prelude::*; -use wasm_bindgen_futures::spawn_local; -use web_sys as sys; -use crate::{media::MediaKind, utils::Callback0, JsMediaSourceKind}; +use crate::{ + core::{ + media::{MediaKind, MediaSourceKind}, + utils::Callback0, + }, + platform::{self, spawn}, +}; /// Inner reference-counted data of [`Track`]. struct Inner { - /// Underlying JS-side [`sys::MediaStreamTrack`]. - track: sys::MediaStreamTrack, + /// Underlying JS-side [`platform::MediaStreamTrack`]. + track: platform::MediaStreamTrack, - /// Underlying [`sys::MediaStreamTrack`] kind. - kind: MediaKind, - - /// Underlying [`sys::MediaStreamTrack`] source kind. - media_source_kind: MediaSourceKind, + /// Underlying [`platform::MediaStreamTrack`] source kind. + media_source_kind: proto::MediaSourceKind, /// Callback to be invoked when this [`Track`] is enabled. on_enabled: Callback0, @@ -38,7 +38,6 @@ struct Inner { /// Wrapper around [MediaStreamTrack][1] received from the remote. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack -#[wasm_bindgen(js_name = RemoteMediaTrack)] #[derive(Clone)] pub struct Track(Rc); @@ -48,29 +47,22 @@ impl Track { /// /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled #[must_use] - pub fn new(track: T, media_source_kind: MediaSourceKind) -> Self + pub fn new(track: T, media_source_kind: proto::MediaSourceKind) -> Self where - sys::MediaStreamTrack: From, + platform::MediaStreamTrack: From, { - let track = sys::MediaStreamTrack::from(track); - let kind = match track.kind().as_ref() { - "audio" => MediaKind::Audio, - "video" => MediaKind::Video, - _ => unreachable!(), - }; - + let track = platform::MediaStreamTrack::from(track); 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({ + track.enabled_observable().subscribe().skip(1); + spawn({ let weak_inner = Rc::downgrade(&track.0); async move { while let Some(enabled) = @@ -95,14 +87,14 @@ impl Track { /// Indicates whether this [`Track`] is enabled. #[inline] #[must_use] - pub fn enabled(&self) -> &ObservableCell { + pub fn enabled_observable(&self) -> &ObservableCell { &self.0.enabled } /// Sets [`Track::enabled`] to the provided value. /// /// Updates [`enabled`][1] property in the underlying - /// [`sys::MediaStreamTrack`]. + /// [`platform::MediaStreamTrack`]. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled #[inline] @@ -111,7 +103,7 @@ impl Track { self.0.track.set_enabled(enabled); } - /// Returns [`id`][1] of underlying [`sys::MediaStreamTrack`] of this + /// Returns [`id`][1] of underlying [`platform::MediaStreamTrack`] of this /// [`Track`]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id @@ -125,27 +117,23 @@ impl Track { #[inline] #[must_use] pub fn kind(&self) -> MediaKind { - self.0.kind + self.0.track.kind() } /// Returns this [`Track`]'s media source kind. #[inline] #[must_use] pub fn media_source_kind(&self) -> MediaSourceKind { - self.0.media_source_kind + self.0.media_source_kind.into() } -} -#[wasm_bindgen(js_class = RemoteMediaTrack)] -impl Track { - /// Returns the underlying [`sys::MediaStreamTrack`] of this [`Track`]. - pub fn get_track(&self) -> sys::MediaStreamTrack { - Clone::clone(&self.0.track) + /// Returns the underlying [`platform::MediaStreamTrack`] of this [`Track`]. + pub fn get_track(&self) -> &platform::MediaStreamTrack { + &self.0.track } /// Indicate whether this [`Track`] is enabled. - #[wasm_bindgen(js_name = enabled)] - pub fn js_enabled(&self) -> bool { + pub fn enabled(&self) -> bool { self.0.enabled.get() } @@ -158,21 +146,4 @@ impl Track { pub fn on_disabled(&self, callback: js_sys::Function) { self.0.on_disabled.set_func(callback); } - - /// 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 this [`Track`] is sourced from - /// some device (webcam/microphone), or [`JsMediaSourceKind::Display`] if - /// it's 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() - } } diff --git a/jason/src/core/mod.rs b/jason/src/core/mod.rs new file mode 100644 index 000000000..491cdfecf --- /dev/null +++ b/jason/src/core/mod.rs @@ -0,0 +1,152 @@ +//! External Jason API accessible from JS. + +use futures::FutureExt as _; +use std::{cell::RefCell, rc::Rc}; + +use self::{ + media::MediaManager, + rpc::{ + ClientDisconnect, RpcSession, WebSocketRpcClient, WebSocketRpcSession, + }, +}; + +#[doc(inline)] +pub use self::{ + connection::{Connection, ConnectionHandle, Connections}, + media::{ + track::{local::LocalMediaTrack, remote}, + MediaKind, MediaManagerHandle, MediaSourceKind, + }, + room::{ + ConstraintsUpdateException, Room, RoomCloseReason, RoomError, + RoomHandle, WeakRoom, + }, + rpc::ReconnectHandle, +}; +use crate::platform::{ + spawn, + transport::{RpcTransport, WebSocketRpcTransport}, +}; + +#[macro_use] +pub mod utils; +mod connection; +pub mod media; +pub mod peer; +mod room; +pub mod rpc; + +/// General library interface. +/// +/// Responsible for managing shared transports, local media +/// and room initialization. +pub struct Jason(Rc>); + +pub struct Inner { + /// [`Jason`]s [`MediaManager`]. It's shared across [`Room`]s since + /// [`MediaManager`] contains media tracks that can be used by multiple + /// [`Room`]s. + media_manager: Rc, + + /// [`Room`]s maintained by this [`Jason`] instance. + rooms: Vec, + + /// Connection with Media Server. Only one [`WebSocketRpcClient`] is + /// supported at the moment. + rpc: Rc, +} + +impl Jason { + /// Instantiates new [`Jason`] interface to interact with this library. + pub fn new() -> Self { + Self::with_rpc_client(Rc::new(WebSocketRpcClient::new(Box::new( + |url| { + Box::pin(async move { + let ws = WebSocketRpcTransport::new(url) + .await + .map_err(|e| tracerr::new!(e))?; + Ok(Rc::new(ws) as Rc) + }) + }, + )))) + } + + /// Creates new [`Room`] and returns its [`RoomHandle`]. + pub fn init_room(&self) -> RoomHandle { + let rpc = Rc::clone(&self.0.borrow().rpc); + self.inner_init_room(WebSocketRpcSession::new(rpc)) + } + + /// Returns [`MediaManagerHandle`]. + pub fn media_manager(&self) -> MediaManagerHandle { + self.0.borrow().media_manager.new_handle() + } + + /// Closes the provided [`RoomHandle`]. + #[allow(clippy::needless_pass_by_value)] + pub fn close_room(&self, room_to_delete: RoomHandle) { + self.0.borrow_mut().rooms.retain(|room| { + let should_be_closed = room.inner_ptr_eq(&room_to_delete); + if should_be_closed { + room.set_close_reason(ClientDisconnect::RoomClosed.into()); + } + + !should_be_closed + }); + } + + /// Drops [`Jason`] API object, so all related objects (rooms, connections, + /// streams etc.) respectively. All objects related to this [`Jason`] API + /// object will be detached (you will still hold them, but unable to use). + pub fn dispose(self) { + self.0.borrow_mut().rooms.drain(..).for_each(|room| { + room.close(ClientDisconnect::RoomClosed.into()); + }); + } + + /// Returns new [`Jason`] with the provided [`WebSocketRpcClient`]. + #[inline] + pub fn with_rpc_client(rpc: Rc) -> Self { + Self(Rc::new(RefCell::new(Inner { + rpc, + rooms: Vec::new(), + media_manager: Rc::new(MediaManager::default()), + }))) + } + + /// Returns [`RoomHandle`] for [`Room`]. + pub fn inner_init_room(&self, rpc: Rc) -> RoomHandle { + let on_normal_close = rpc.on_normal_close(); + let room = Room::new(rpc, Rc::clone(&self.0.borrow().media_manager)); + + let weak_room = room.downgrade(); + let weak_inner = Rc::downgrade(&self.0); + spawn(on_normal_close.map(move |reason| { + (|| { + let room = weak_room.upgrade()?; + let inner = weak_inner.upgrade()?; + let mut inner = inner.borrow_mut(); + let index = inner.rooms.iter().position(|r| r.ptr_eq(&room)); + if let Some(index) = index { + inner.rooms.remove(index).close(reason); + } + if inner.rooms.is_empty() { + inner.media_manager = Rc::default(); + } + + Some(()) + })(); + })); + + let handle = room.new_handle(); + self.0.borrow_mut().rooms.push(room); + handle + } +} + +impl Default for Jason { + #[inline] + fn default() -> Self { + Self::new() + } +} diff --git a/jason/src/peer/component/ice_candidates.rs b/jason/src/core/peer/component/ice_candidates.rs similarity index 98% rename from jason/src/peer/component/ice_candidates.rs rename to jason/src/core/peer/component/ice_candidates.rs index c0599362c..f48cf9a88 100644 --- a/jason/src/peer/component/ice_candidates.rs +++ b/jason/src/core/peer/component/ice_candidates.rs @@ -6,7 +6,7 @@ use futures::stream::LocalBoxStream; use medea_client_api_proto::IceCandidate; use medea_reactive::ObservableHashSet; -use crate::{ +use crate::core::{ media::LocalTracksConstraints, utils::{AsProtoState, SynchronizableState}, }; diff --git a/jason/src/peer/component/local_sdp.rs b/jason/src/core/peer/component/local_sdp.rs similarity index 98% rename from jason/src/peer/component/local_sdp.rs rename to jason/src/core/peer/component/local_sdp.rs index 6d2d23f8f..e3ae39e39 100644 --- a/jason/src/peer/component/local_sdp.rs +++ b/jason/src/core/peer/component/local_sdp.rs @@ -13,9 +13,11 @@ use futures::{ StreamExt as _, }; use medea_reactive::ObservableCell; -use wasm_bindgen_futures::spawn_local; -use crate::utils::{resettable_delay_for, ResettableDelayHandle}; +use crate::{ + core::utils::{resettable_delay_for, ResettableDelayHandle}, + platform::spawn, +}; const DESCRIPTION_APPROVE_TIMEOUT: Duration = Duration::from_secs(10); @@ -150,7 +152,7 @@ impl LocalSdp { DESCRIPTION_APPROVE_TIMEOUT, self.0.is_rollback_timeout_stopped.get(), ); - spawn_local({ + spawn({ let this = self.clone(); async move { if let Either::Right(_) = diff --git a/jason/src/peer/component/mod.rs b/jason/src/core/peer/component/mod.rs similarity index 99% rename from jason/src/peer/component/mod.rs rename to jason/src/core/peer/component/mod.rs index 584c004cf..32403dcda 100644 --- a/jason/src/peer/component/mod.rs +++ b/jason/src/core/peer/component/mod.rs @@ -15,7 +15,7 @@ use medea_client_api_proto::{ use medea_reactive::{AllProcessed, ObservableCell, ProgressableCell}; use tracerr::Traced; -use crate::{ +use crate::core::{ media::LocalTracksConstraints, peer::{ media::{receiver, sender}, diff --git a/jason/src/peer/component/tracks_repository.rs b/jason/src/core/peer/component/tracks_repository.rs similarity index 99% rename from jason/src/peer/component/tracks_repository.rs rename to jason/src/core/peer/component/tracks_repository.rs index b515411c1..451dc8686 100644 --- a/jason/src/peer/component/tracks_repository.rs +++ b/jason/src/core/peer/component/tracks_repository.rs @@ -17,7 +17,7 @@ use medea_client_api_proto::TrackId; use medea_reactive::{AllProcessed, Guarded, ProgressableHashMap}; use tracerr::Traced; -use crate::{ +use crate::core::{ media::LocalTracksConstraints, peer::PeerError, utils::{AsProtoState, SynchronizableState, Updatable}, diff --git a/jason/src/peer/component/watchers.rs b/jason/src/core/peer/component/watchers.rs similarity index 99% rename from jason/src/peer/component/watchers.rs rename to jason/src/core/peer/component/watchers.rs index 1a1ef5803..ffce893f5 100644 --- a/jason/src/peer/component/watchers.rs +++ b/jason/src/core/peer/component/watchers.rs @@ -8,7 +8,7 @@ use medea_macro::watchers; use medea_reactive::Guarded; use tracerr::Traced; -use crate::{ +use crate::core::{ peer::{ component::{NegotiationState, SyncState}, media::{receiver, sender}, diff --git a/jason/src/peer/media/mod.rs b/jason/src/core/peer/media/mod.rs similarity index 96% rename from jason/src/peer/media/mod.rs rename to jason/src/core/peer/media/mod.rs index f1f392e08..a7290e8fe 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/core/peer/media/mod.rs @@ -16,20 +16,22 @@ use medea_client_api_proto::{MediaType, MemberId}; use medea_reactive::DroppedError; use proto::{MediaSourceKind, TrackId}; use tracerr::Traced; -use web_sys::RtcTrackEvent; #[cfg(feature = "mockable")] use crate::media::{LocalTracksConstraints, RecvConstraints}; use crate::{ - media::{track::local, MediaKind}, - peer::{ - transceiver::Transceiver, LocalStreamUpdateCriteria, PeerEvent, - TrackEvent, TransceiverDirection, + core::{ + media::{track::local, MediaKind}, + peer::{LocalStreamUpdateCriteria, PeerEvent, TrackEvent}, + utils::JsCaused, + }, + platform::{ + self, MediaStreamTrack, RtcPeerConnection, Transceiver, + TransceiverDirection, }, - utils::{JsCaused, JsError}, }; -use super::{conn::RtcPeerConnection, tracks_request::TracksRequest}; +use super::tracks_request::TracksRequest; pub use self::transitable_state::{ media_exchange_state, mute_state, InStable, InTransition, @@ -206,13 +208,14 @@ pub enum TrackDirection { /// Errors that may occur in [`MediaConnections`] storage. #[derive(Clone, Debug, Display, JsCaused)] +#[js(error = "platform::Error")] pub enum MediaConnectionsError { /// Occurs when the provided [`local::Track`] cannot be inserted into /// provided [`Sender`]s transceiver. /// /// [`Sender`]: self::sender::Sender #[display(fmt = "Failed to insert Track to a sender: {}", _0)] - CouldNotInsertLocalTrack(JsError), + CouldNotInsertLocalTrack(platform::Error), /// Occurs when [`remote::Track`] discovered by [`RtcPeerConnection`] could /// not be inserted into [`Receiver`]. @@ -226,9 +229,7 @@ pub enum MediaConnectionsError { )] CouldNotInsertRemoteTrack(String), - /// Could not find [`RtcRtpTransceiver`] by `mid`. - /// - /// [`RtcRtpTransceiver`]: web_sys::RtcRtpTransceiver + /// Could not find [`Transceiver`] by `mid`. #[display(fmt = "Unable to find Transceiver with provided mid: {}", _0)] TransceiverNotFound(String), @@ -454,7 +455,7 @@ impl MediaConnections { } /// Returns mapping from a [`proto::Track`] ID to a `mid` of this track's - /// [`RtcRtpTransceiver`]. + /// [`Transceiver`]. /// /// # Errors /// @@ -466,7 +467,6 @@ impl MediaConnections { /// /// [`Sender`]: self::sender::Sender /// [`Receiver`]: self::receiver::Receiver - /// [`RtcRtpTransceiver`]: web_sys::RtcRtpTransceiver /// [mid]: /// https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpTransceiver/mid pub fn get_mids(&self) -> Result> { @@ -494,7 +494,7 @@ impl MediaConnections { Ok(mids) } - /// Returns activity statuses of the all [`Sender`]s and [`Receiver`]s from + /// Returns app statuses of the all [`Sender`]s and [`Receiver`]s from /// this [`MediaConnections`]. /// /// [`Sender`]: self::sender::Sender @@ -578,7 +578,7 @@ impl MediaConnections { /// Inserts provided tracks into [`Sender`]s based on track IDs. /// - /// [`local::Track`]s are inserted into [`Sender`]'s [`RtcRtpTransceiver`]s + /// [`local::Track`]s are inserted into [`Sender`]'s [`Transceiver`]s /// via [`replaceTrack` method][1], changing its direction to `sendonly`. /// /// Returns [`HashMap`] with [`media_exchange_state::Stable`]s updates for @@ -598,7 +598,6 @@ impl MediaConnections { /// transceiver. /// /// [`Sender`]: self::sender::Sender - /// [`RtcRtpTransceiver`]: web_sys::RtcRtpTransceiver /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack pub async fn insert_local_tracks( &self, @@ -610,7 +609,7 @@ impl MediaConnections { let mut media_exchange_state_updates = HashMap::new(); for sender in self.0.borrow().senders.values() { if let Some(track) = tracks.get(&sender.state().id()).cloned() { - if sender.caps().satisfies(track.sys_track()) { + if sender.caps().satisfies(track.as_ref()) { media_exchange_state_updates.insert( sender.state().id(), media_exchange_state::Stable::Enabled, @@ -657,10 +656,12 @@ impl MediaConnections { /// /// [`Sender`]: self::sender::Sender /// [`Receiver`]: self::receiver::Receiver - pub fn add_remote_track(&self, track_event: &RtcTrackEvent) -> Result<()> { + pub fn add_remote_track( + &self, + track: MediaStreamTrack, + transceiver: Transceiver, + ) -> Result<()> { let inner = self.0.borrow(); - let transceiver = Transceiver::from(track_event.transceiver()); - let track = track_event.track(); // Cannot fail, since transceiver is guaranteed to be negotiated at this // point. let mid = transceiver.mid().unwrap(); @@ -668,7 +669,7 @@ impl MediaConnections { for receiver in inner.receivers.values() { if let Some(recv_mid) = &receiver.mid() { if recv_mid == &mid { - receiver.set_remote_track(transceiver, track); + receiver.set_remote_track(transceiver, track.into()); return Ok(()); } } diff --git a/jason/src/peer/media/receiver/component.rs b/jason/src/core/peer/media/receiver/component.rs similarity index 96% rename from jason/src/peer/media/receiver/component.rs rename to jason/src/core/peer/media/receiver/component.rs index dd1077fe9..28d0fabd9 100644 --- a/jason/src/peer/media/receiver/component.rs +++ b/jason/src/core/peer/media/receiver/component.rs @@ -14,18 +14,19 @@ use medea_reactive::{ }; use crate::{ - media::LocalTracksConstraints, - peer::{ - component::SyncState, - media::{ - transitable_state::media_exchange_state, InTransition, Result, + core::{ + media::{LocalTracksConstraints, MediaKind}, + peer::{ + component::SyncState, + media::{ + transitable_state::media_exchange_state, InTransition, Result, + }, + MediaExchangeState, MediaExchangeStateController, + MediaStateControllable, MuteStateController, TransceiverSide, }, - MediaExchangeState, MediaExchangeStateController, - MediaStateControllable, MuteStateController, TransceiverDirection, - TransceiverSide, + utils::{component, AsProtoState, SynchronizableState, Updatable}, }, - utils::{component, AsProtoState, SynchronizableState, Updatable}, - MediaKind, + platform::TransceiverDirection, }; use super::Receiver; diff --git a/jason/src/peer/media/receiver/mod.rs b/jason/src/core/peer/media/receiver/mod.rs similarity index 93% rename from jason/src/peer/media/receiver/mod.rs rename to jason/src/core/peer/media/receiver/mod.rs index 601855b43..14723a915 100644 --- a/jason/src/peer/media/receiver/mod.rs +++ b/jason/src/core/peer/media/receiver/mod.rs @@ -8,16 +8,16 @@ use futures::channel::mpsc; use medea_client_api_proto as proto; use medea_client_api_proto::{MediaType, MemberId}; use proto::TrackId; -use web_sys as sys; use crate::{ - media::{track::remote, MediaKind, RecvConstraints, TrackConstraints}, - peer::{ - media::{media_exchange_state, TrackEvent}, - transceiver::Transceiver, - MediaConnections, MediaStateControllable, PeerEvent, - TransceiverDirection, + core::{ + media::{track::remote, MediaKind, RecvConstraints, TrackConstraints}, + peer::{ + media::{media_exchange_state, TrackEvent}, + MediaConnections, MediaStateControllable, PeerEvent, + }, }, + platform::{MediaStreamTrack, Transceiver, TransceiverDirection}, }; use super::TransceiverSide; @@ -167,15 +167,15 @@ impl Receiver { ); } - /// Adds provided [`sys::MediaStreamTrack`] and [`Transceiver`] to this + /// Adds provided [`platform::MediaStreamTrack`] and [`Transceiver`] to this /// [`Receiver`]. /// - /// Sets [`sys::MediaStreamTrack::enabled`] same as [`Receiver::enabled`] of - /// this [`Receiver`]. + /// Sets [`platform::MediaStreamTrack::enabled`] same as + /// [`Receiver::enabled`] of this [`Receiver`]. pub fn set_remote_track( &self, transceiver: Transceiver, - new_track: sys::MediaStreamTrack, + new_track: 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/component.rs b/jason/src/core/peer/media/sender/component.rs similarity index 97% rename from jason/src/peer/media/sender/component.rs rename to jason/src/core/peer/media/sender/component.rs index da7485713..4b6fa96f3 100644 --- a/jason/src/peer/media/sender/component.rs +++ b/jason/src/core/peer/media/sender/component.rs @@ -12,20 +12,24 @@ use medea_reactive::{AllProcessed, Guarded, ObservableCell, ProgressableCell}; use tracerr::Traced; use crate::{ - media::{LocalTracksConstraints, TrackConstraints, VideoSource}, - peer::{ - self, - component::SyncState, + core::{ media::{ - media_exchange_state, mute_state, InTransition, MediaExchangeState, - MuteState, Result, + LocalTracksConstraints, MediaKind, TrackConstraints, VideoSource, }, - MediaConnectionsError, MediaExchangeStateController, MediaState, - MediaStateControllable, MuteStateController, PeerError, - TransceiverDirection, TransceiverSide, + peer::{ + self, + component::SyncState, + media::{ + media_exchange_state, mute_state, InTransition, + MediaExchangeState, MuteState, Result, + }, + MediaConnectionsError, MediaExchangeStateController, MediaState, + MediaStateControllable, MuteStateController, PeerError, + TransceiverSide, + }, + utils::{component, AsProtoState, SynchronizableState, Updatable}, }, - utils::{component, AsProtoState, SynchronizableState, Updatable}, - MediaKind, + platform::TransceiverDirection, }; use super::Sender; diff --git a/jason/src/peer/media/sender/mod.rs b/jason/src/core/peer/media/sender/mod.rs similarity index 97% rename from jason/src/peer/media/sender/mod.rs rename to jason/src/core/peer/media/sender/mod.rs index cdca10665..9a1bb8ba9 100644 --- a/jason/src/peer/media/sender/mod.rs +++ b/jason/src/core/peer/media/sender/mod.rs @@ -8,13 +8,13 @@ use futures::channel::mpsc; use medea_client_api_proto::TrackId; use crate::{ - media::{ - track::local, LocalTracksConstraints, MediaKind, TrackConstraints, - }, - peer::{ - transceiver::{Transceiver, TransceiverDirection}, - TrackEvent, + core::{ + media::{ + track::local, LocalTracksConstraints, MediaKind, TrackConstraints, + }, + peer::TrackEvent, }, + platform::{Transceiver, TransceiverDirection}, }; use super::{ diff --git a/jason/src/peer/media/transitable_state/controller.rs b/jason/src/core/peer/media/transitable_state/controller.rs similarity index 96% rename from jason/src/peer/media/transitable_state/controller.rs rename to jason/src/core/peer/media/transitable_state/controller.rs index 346c2f56f..9a20fc292 100644 --- a/jason/src/peer/media/transitable_state/controller.rs +++ b/jason/src/core/peer/media/transitable_state/controller.rs @@ -11,16 +11,18 @@ use futures::{ StreamExt as _, }; use medea_reactive::{Processed, ProgressableCell}; -use wasm_bindgen_futures::spawn_local; use crate::{ - peer::media::{ - transitable_state::{ - media_exchange_state, mute_state, InStable, InTransition, + core::{ + peer::media::{ + transitable_state::{ + media_exchange_state, mute_state, InStable, InTransition, + }, + MediaConnectionsError, Result, }, - MediaConnectionsError, Result, + utils::{resettable_delay_for, ResettableDelayHandle}, }, - utils::{resettable_delay_for, ResettableDelayHandle}, + platform::spawn, }; use super::TransitableState; @@ -81,13 +83,13 @@ where // at that moment. let mut state_changes = self.state.subscribe().skip(1); let weak_this = Rc::downgrade(&self); - spawn_local(async move { + spawn(async move { while let Some(state) = state_changes.next().await { let (state, _guard) = state.into_parts(); if let Some(this) = weak_this.upgrade() { if let TransitableState::Transition(_) = state { let weak_this = Rc::downgrade(&this); - spawn_local(async move { + spawn(async move { let mut states = this.state.subscribe().skip(1); let (timeout, timeout_handle) = resettable_delay_for( diff --git a/jason/src/peer/media/transitable_state/media_exchange_state.rs b/jason/src/core/peer/media/transitable_state/media_exchange_state.rs similarity index 100% rename from jason/src/peer/media/transitable_state/media_exchange_state.rs rename to jason/src/core/peer/media/transitable_state/media_exchange_state.rs diff --git a/jason/src/peer/media/transitable_state/mod.rs b/jason/src/core/peer/media/transitable_state/mod.rs similarity index 100% rename from jason/src/peer/media/transitable_state/mod.rs rename to jason/src/core/peer/media/transitable_state/mod.rs diff --git a/jason/src/peer/media/transitable_state/mute_state.rs b/jason/src/core/peer/media/transitable_state/mute_state.rs similarity index 100% rename from jason/src/peer/media/transitable_state/mute_state.rs rename to jason/src/core/peer/media/transitable_state/mute_state.rs diff --git a/jason/src/peer/mod.rs b/jason/src/core/peer/mod.rs similarity index 93% rename from jason/src/peer/mod.rs rename to jason/src/core/peer/mod.rs index a0816ebcb..d8def5b5d 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/core/peer/mod.rs @@ -3,14 +3,10 @@ //! [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface mod component; -mod conn; -mod ice_server; mod media; pub mod repo; -mod stats; mod stream_update_criteria; mod tracks_request; -mod transceiver; use std::{ cell::{Cell, RefCell}, @@ -28,24 +24,23 @@ use medea_client_api_proto::{ }; use medea_macro::dispatchable; use tracerr::Traced; -use wasm_bindgen_futures::spawn_local; -use web_sys::{RtcIceConnectionState, RtcTrackEvent}; use crate::{ - api::Connections, - media::{ - track::{local, remote}, - LocalTracksConstraints, MediaKind, MediaManager, MediaManagerError, - RecvConstraints, + core::{ + media::{ + track::{local, remote}, + LocalTracksConstraints, MediaKind, MediaManager, MediaManagerError, + MediaStreamSettings, RecvConstraints, + }, + utils::{JasonError, JsCaused}, + Connections, }, - utils::{JasonError, JsCaused, JsError}, - MediaStreamSettings, + platform::{self, spawn, MediaStreamTrack, Transceiver}, }; #[doc(inline)] pub use self::{ component::{Component, State}, - conn::{IceCandidate, RTCPeerConnectionError, RtcPeerConnection, SdpType}, media::{ media_exchange_state, mute_state, receiver, sender, MediaConnections, MediaConnectionsError, MediaExchangeState, @@ -53,16 +48,15 @@ pub use self::{ MuteState, MuteStateController, TrackDirection, TransceiverSide, TransitableState, TransitableStateController, }, - stats::RtcStats, stream_update_criteria::LocalStreamUpdateCriteria, tracks_request::{SimpleTracksRequest, TracksRequest, TracksRequestError}, - transceiver::{Transceiver, TransceiverDirection}, }; /// Errors that may occur in [RTCPeerConnection][1]. /// /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface #[derive(Clone, Debug, Display, From, JsCaused)] +#[js(error = "platform::Error")] pub enum PeerError { /// Errors that may occur in [`MediaConnections`] storage. #[display(fmt = "{}", _0)] @@ -77,7 +71,7 @@ pub enum PeerError { /// /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection #[display(fmt = "{}", _0)] - RtcPeerConnection(#[js(cause)] RTCPeerConnectionError), + RtcPeerConnection(#[js(cause)] platform::RTCPeerConnectionError), /// Errors that may occur when validating [`TracksRequest`] or parsing /// [`local::Track`]s. @@ -194,7 +188,7 @@ pub enum PeerEvent { peer_id: Id, /// [`RtcStats`] of this [`PeerConnection`]. - stats: RtcStats, + stats: platform::RtcStats, }, /// [`PeerConnection::update_local_stream`] was failed, so @@ -249,7 +243,7 @@ pub struct PeerConnection { id: Id, /// Underlying [`RtcPeerConnection`]. - peer: Rc, + peer: Rc, /// [`sender::Component`]s and [`receiver::Component`]s of this /// [`RtcPeerConnection`]. @@ -266,7 +260,7 @@ pub struct PeerConnection { /// Stores [`IceCandidate`]s received before remote description for /// underlying [`RtcPeerConnection`]. - ice_candidates_buffer: RefCell>, + ice_candidates_buffer: RefCell>, /// Last hashes of the all [`RtcStats`] which was already sent to the /// server, so we won't duplicate stats that were already sent. @@ -316,7 +310,7 @@ impl PeerConnection { recv_constraints: Rc, ) -> Result> { let peer = Rc::new( - RtcPeerConnection::new( + platform::RtcPeerConnection::new( state.ice_servers().clone(), state.force_relay(), ) @@ -328,7 +322,7 @@ impl PeerConnection { peer_events_sender.clone(), )); - spawn_local({ + spawn({ let peer_events_sender = peer_events_sender.clone(); let peer_id = state.id(); @@ -392,9 +386,9 @@ impl PeerConnection { // Bind to `track` event. let media_connections = Rc::clone(&peer.media_connections); peer.peer - .on_track(Some(move |track_event| { + .on_track(Some(move |track, transceiver| { if let Err(err) = - media_connections.add_remote_track(&track_event) + media_connections.add_remote_track(track, transceiver) { JasonError::from(err).print(); }; @@ -463,12 +457,12 @@ impl PeerConnection { self.media_connections.drop_send_tracks(kinds).await } - /// Filters out already sent stats, and send new statss from + /// Filters out already sent stats, and send new stats from /// provided [`RtcStats`]. #[allow(clippy::option_if_let_else)] - pub fn send_peer_stats(&self, stats: RtcStats) { + pub fn send_peer_stats(&self, stats: platform::RtcStats) { let mut stats_cache = self.sent_stats_cache.borrow_mut(); - let stats = RtcStats( + let stats = platform::RtcStats( stats .0 .into_iter() @@ -544,7 +538,7 @@ impl PeerConnection { fn on_ice_candidate( id: Id, sender: &mpsc::UnboundedSender, - candidate: IceCandidate, + candidate: platform::IceCandidate, ) { let _ = sender.unbounded_send(PeerEvent::IceCandidateDiscovered { peer_id: id, @@ -560,24 +554,8 @@ impl PeerConnection { fn on_ice_connection_state_changed( peer_id: Id, sender: &mpsc::UnboundedSender, - ice_connection_state: RtcIceConnectionState, + ice_connection_state: IceConnectionState, ) { - use RtcIceConnectionState as S; - - let ice_connection_state = match ice_connection_state { - S::New => IceConnectionState::New, - S::Checking => IceConnectionState::Checking, - S::Connected => IceConnectionState::Connected, - S::Completed => IceConnectionState::Completed, - S::Failed => IceConnectionState::Failed, - S::Disconnected => IceConnectionState::Disconnected, - S::Closed => IceConnectionState::Closed, - S::__Nonexhaustive => { - log::error!("Unknown ICE connection state"); - return; - } - }; - let _ = sender.unbounded_send(PeerEvent::IceConnectionStateChanged { peer_id, ice_connection_state, @@ -852,7 +830,7 @@ impl PeerConnection { /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface /// [2]: https://w3.org/TR/webrtc/#dom-peerconnection-setremotedescription async fn set_remote_answer(&self, answer: String) -> Result<()> { - self.set_remote_description(SdpType::Answer(answer)) + self.set_remote_description(platform::SdpType::Answer(answer)) .await .map_err(tracerr::wrap!()) } @@ -867,7 +845,7 @@ impl PeerConnection { /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface /// [2]: https://w3.org/TR/webrtc/#dom-peerconnection-setremotedescription async fn set_remote_offer(&self, offer: String) -> Result<()> { - self.set_remote_description(SdpType::Offer(offer)) + self.set_remote_description(platform::SdpType::Offer(offer)) .await .map_err(tracerr::wrap!()) } @@ -887,7 +865,10 @@ impl PeerConnection { /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface /// [2]: https://w3.org/TR/webrtc/#dom-peerconnection-setremotedescription /// [3]: https://w3.org/TR/webrtc/#dom-peerconnection-addicecandidate - async fn set_remote_description(&self, desc: SdpType) -> Result<()> { + async fn set_remote_description( + &self, + desc: platform::SdpType, + ) -> Result<()> { self.peer .set_remote_description(desc) .await @@ -939,11 +920,13 @@ impl PeerConnection { .await .map_err(tracerr::map_from_and_wrap!())?; } else { - self.ice_candidates_buffer.borrow_mut().push(IceCandidate { - candidate, - sdp_m_line_index, - sdp_mid, - }); + self.ice_candidates_buffer.borrow_mut().push( + platform::IceCandidate { + candidate, + sdp_m_line_index, + sdp_mid, + }, + ); } Ok(()) } @@ -1066,9 +1049,11 @@ impl Drop for PeerConnection { /// Drops `on_track` and `on_ice_candidate` callbacks to prevent possible /// leaks. fn drop(&mut self) { - let _ = self.peer.on_track::>(None); let _ = self .peer - .on_ice_candidate::>(None); + .on_track::>(None); + let _ = self + .peer + .on_ice_candidate::>(None); } } diff --git a/jason/src/peer/repo.rs b/jason/src/core/peer/repo.rs similarity index 96% rename from jason/src/peer/repo.rs rename to jason/src/core/peer/repo.rs index 5ea984da3..32e0a37eb 100644 --- a/jason/src/peer/repo.rs +++ b/jason/src/core/peer/repo.rs @@ -7,16 +7,18 @@ use medea_client_api_proto::{self as proto, PeerId}; use medea_macro::watchers; use medea_reactive::ObservableHashMap; use tracerr::Traced; -use wasm_bindgen_futures::spawn_local; use crate::{ - api::{Connections, RoomError}, - media::{LocalTracksConstraints, MediaManager, RecvConstraints}, - peer, - utils::{ - component, delay_for, AsProtoState, SynchronizableState, TaskHandle, - Updatable as _, + core::{ + media::{LocalTracksConstraints, MediaManager, RecvConstraints}, + peer, + utils::{ + component, AsProtoState, SynchronizableState, TaskHandle, + Updatable as _, + }, + Connections, RoomError, }, + platform::{delay_for, spawn}, }; use super::{PeerConnection, PeerEvent}; @@ -182,7 +184,7 @@ impl Repository { } }); - spawn_local(async move { + spawn(async move { fut.await.ok(); }); diff --git a/jason/src/peer/stream_update_criteria.rs b/jason/src/core/peer/stream_update_criteria.rs similarity index 98% rename from jason/src/peer/stream_update_criteria.rs rename to jason/src/core/peer/stream_update_criteria.rs index 15be7c176..1cc68edea 100644 --- a/jason/src/peer/stream_update_criteria.rs +++ b/jason/src/core/peer/stream_update_criteria.rs @@ -4,7 +4,7 @@ use std::ops::BitOrAssign; use medea_client_api_proto::{Direction, MediaSourceKind, MediaType, Track}; -use crate::MediaKind; +use crate::core::media::MediaKind; bitflags::bitflags! { pub struct Inner: u8 { diff --git a/jason/src/peer/tracks_request.rs b/jason/src/core/peer/tracks_request.rs similarity index 95% rename from jason/src/peer/tracks_request.rs rename to jason/src/core/peer/tracks_request.rs index d81ee33e7..c7b4f8568 100644 --- a/jason/src/peer/tracks_request.rs +++ b/jason/src/core/peer/tracks_request.rs @@ -9,17 +9,21 @@ use medea_client_api_proto::{MediaSourceKind, TrackId}; use tracerr::Traced; use crate::{ - media::{ - track::local, AudioTrackConstraints, MediaKind, MediaStreamSettings, - TrackConstraints, VideoSource, + core::{ + media::{ + track::local, AudioTrackConstraints, DeviceVideoTrackConstraints, + DisplayVideoTrackConstraints, MediaKind, MediaStreamSettings, + TrackConstraints, VideoSource, + }, + utils::JsCaused, }, - utils::{JsCaused, JsError}, - DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, + platform, }; /// Errors that may occur when validating [`TracksRequest`] or /// parsing [`local::Track`]s. #[derive(Clone, Debug, Display, JsCaused)] +#[js(error = "platform::Error")] pub enum TracksRequestError { /// [`TracksRequest`] contains multiple [`AudioTrackConstraints`]. #[display(fmt = "only one audio track is allowed in SimpleTracksRequest")] @@ -164,7 +168,7 @@ impl SimpleTracksRequest { if let Some((id, audio)) = &self.audio { if let Some(track) = audio_tracks.into_iter().next() { - if audio.satisfies(track.sys_track()) { + if audio.satisfies(track.as_ref()) { parsed_tracks.insert(*id, track); } else { return Err(tracerr::new!(InvalidAudioTrack)); @@ -173,7 +177,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.sys_track()) { + if device_video.satisfies(track.as_ref()) { parsed_tracks.insert(*id, track); } else { return Err(tracerr::new!(InvalidVideoTrack)); @@ -182,7 +186,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.sys_track()) { + if display_video.satisfies(track.as_ref()) { parsed_tracks.insert(*id, track); } else { return Err(tracerr::new!(InvalidVideoTrack)); @@ -225,9 +229,8 @@ impl SimpleTracksRequest { return Err(tracerr::new!( TracksRequestError::ExpectedAudioTracks )); - } else { - self.audio.take(); } + self.audio.take(); } } if let Some((_, device_video_caps)) = &self.device_video { @@ -236,9 +239,8 @@ impl SimpleTracksRequest { return Err(tracerr::new!( TracksRequestError::ExpectedDeviceVideoTracks )); - } else { - self.device_video.take(); } + self.device_video.take(); } } if let Some((_, display_video_caps)) = &self.display_video { @@ -247,9 +249,8 @@ impl SimpleTracksRequest { return Err(tracerr::new!( TracksRequestError::ExpectedDisplayVideoTracks )); - } else { - self.display_video.take(); } + self.display_video.take(); } } diff --git a/jason/src/api/room.rs b/jason/src/core/room.rs similarity index 92% rename from jason/src/api/room.rs rename to jason/src/core/room.rs index 7156920dc..ee5efd1f1 100644 --- a/jason/src/api/room.rs +++ b/jason/src/core/room.rs @@ -13,44 +13,43 @@ use derive_more::{Display, From}; use futures::{ channel::mpsc, future, FutureExt as _, StreamExt as _, TryFutureExt as _, }; -use js_sys::Promise; use medea_client_api_proto::{ self as proto, Command, ConnectionQualityScore, Event as RpcEvent, - EventHandler, IceCandidate, IceConnectionState, IceServer, MediaSourceKind, - MemberId, NegotiationRole, PeerConnectionState, PeerId, PeerMetrics, Track, - TrackId, TrackUpdate, + EventHandler, IceCandidate, IceConnectionState, IceServer, MemberId, + NegotiationRole, PeerConnectionState, PeerId, PeerMetrics, Track, TrackId, + TrackUpdate, }; use tracerr::Traced; -use wasm_bindgen::{prelude::*, JsValue}; -use wasm_bindgen_futures::{future_to_promise, spawn_local}; use crate::{ - api::connection::Connections, - media::{ - track::{local, remote}, - LocalTracksConstraints, MediaKind, MediaManager, MediaManagerError, - MediaStreamSettings, RecvConstraints, + api, + core::{ + media::{ + track::{local, remote}, + LocalTracksConstraints, MediaKind, MediaManager, MediaManagerError, + MediaSourceKind, MediaStreamSettings, RecvConstraints, + }, + peer::{ + self, media_exchange_state, mute_state, LocalStreamUpdateCriteria, + MediaConnectionsError, MediaState, PeerConnection, PeerError, + PeerEvent, PeerEventHandler, TrackDirection, + }, + rpc::{ + ClientDisconnect, CloseReason, ConnectionInfo, + ConnectionInfoParseError, ReconnectHandle, RpcSession, + SessionError, + }, + utils::{ + AsProtoState, Callback1, HandlerDetachedError, JasonError, JsCaused, + }, + Connections, }, - peer::{ - self, media_exchange_state, mute_state, LocalStreamUpdateCriteria, - MediaConnectionsError, MediaState, PeerConnection, PeerError, - PeerEvent, PeerEventHandler, RtcStats, TrackDirection, - }, - rpc::{ - ClientDisconnect, CloseReason, ConnectionInfo, - ConnectionInfoParseError, ReconnectHandle, RpcSession, SessionError, - }, - utils::{ - AsProtoState, Callback1, HandlerDetachedError, JasonError, JsCaused, - JsError, - }, - JsMediaSourceKind, + platform::{self, spawn}, }; /// Reason of why [`Room`] has been closed. /// /// This struct is passed into `on_close_by_server` JS side callback. -#[wasm_bindgen] pub struct RoomCloseReason { /// Indicator if [`Room`] is closed by server. /// @@ -87,22 +86,15 @@ impl RoomCloseReason { }, } } -} -#[wasm_bindgen] -impl RoomCloseReason { - /// `wasm_bindgen` getter for [`RoomCloseReason::reason`] field. pub fn reason(&self) -> String { self.reason.clone() } - /// `wasm_bindgen` getter for [`RoomCloseReason::is_closed_by_server`] - /// field. pub fn is_closed_by_server(&self) -> bool { self.is_closed_by_server } - /// `wasm_bindgen` getter for [`RoomCloseReason::is_err`] field. pub fn is_err(&self) -> bool { self.is_err } @@ -110,6 +102,7 @@ impl RoomCloseReason { /// Errors that may occur in a [`Room`]. #[derive(Clone, Debug, Display, From, JsCaused)] +#[js(error = "platform::Error")] pub enum RoomError { /// Returned if the mandatory callback wasn't set. #[display(fmt = "`{}` callback isn't set.", _0)] @@ -192,19 +185,25 @@ impl From for RoomError { /// Actually, represents a [`Weak`]-based handle to `InnerRoom`. /// /// For using [`RoomHandle`] on Rust side, consider the `Room`. -#[wasm_bindgen] +#[derive(Clone)] pub struct RoomHandle(Weak); impl RoomHandle { - /// Implements externally visible `RoomHandle::join`. + /// Connects media server and enters [`Room`] with provided authorization + /// `token`. /// - /// # Errors + /// Authorization token has fixed format: + /// `{{ Host URL }}/{{ Room ID }}/{{ Member ID }}?token={{ Auth Token }}` + /// (e.g. `wss://medea.com/MyConf1/Alice?token=777`). /// - /// With [`RoomError::CallbackNotSet`] if `on_failed_local_media` or - /// `on_connection_loss` callbacks are not set. + /// Establishes connection with media server (if it doesn't already exist). + /// Fails if: + /// - `on_failed_local_media` callback is not set + /// - `on_connection_loss` callback is not set + /// - unable to connect to media server. /// - /// With [`RoomError::SessionError`] if cannot connect to media server. - pub async fn inner_join(&self, url: String) -> Result<(), JasonError> { + /// Effectively returns `Result<(), JasonError>`. + pub async fn join(&self, url: String) -> Result<(), JasonError> { let inner = upgrade_or_detached!(self.0, JasonError)?; let connection_info: ConnectionInfo = url.parse().map_err( @@ -238,7 +237,7 @@ impl RoomHandle { new_state: MediaState, kind: MediaKind, direction: TrackDirection, - source_kind: Option, + source_kind: Option, ) -> Result<(), JasonError> { let inner = upgrade_or_detached!(self.0, JasonError)?; inner.set_constraints_media_state( @@ -254,7 +253,7 @@ impl RoomHandle { MediaState::MediaExchange(media_exchange_state::Stable::Enabled) ); - // Perform `getUuserMedia()`/`getDisplayMedia()` right away, so we can + // Perform `getUserMedia()`/`getDisplayMedia()` right away, so we can // fail fast without touching senders' states and starting all required // messaging. // Hold tracks through all process, to ensure that they will be reused @@ -300,10 +299,7 @@ impl RoomHandle { } Ok(()) } -} -#[wasm_bindgen] -impl RoomHandle { /// Sets callback, which will be invoked when new [`Connection`] with some /// remote `Peer` is established. /// @@ -318,7 +314,7 @@ impl RoomHandle { /// Sets `on_close` callback, which will be invoked on [`Room`] close, /// providing [`RoomCloseReason`]. - pub fn on_close(&mut self, f: js_sys::Function) -> Result<(), JsValue> { + pub fn on_close(&self, f: js_sys::Function) -> Result<(), JsValue> { upgrade_or_detached!(self.0).map(|inner| inner.on_close.set_func(f)) } @@ -353,28 +349,6 @@ impl RoomHandle { .map(|inner| inner.on_connection_loss.set_func(f)) } - /// Connects media server and enters [`Room`] with provided authorization - /// `token`. - /// - /// Authorization token has fixed format: - /// `{{ Host URL }}/{{ Room ID }}/{{ Member ID }}?token={{ Auth Token }}` - /// (e.g. `wss://medea.com/MyConf1/Alice?token=777`). - /// - /// Establishes connection with media server (if it doesn't already exist). - /// Fails if: - /// - `on_failed_local_media` callback is not set - /// - `on_connection_loss` callback is not set - /// - unable to connect to media server. - /// - /// Effectively returns `Result<(), JasonError>`. - pub fn join(&self, token: String) -> Promise { - let this = Self(self.0.clone()); - future_to_promise(async move { - this.inner_join(token).await?; - Ok(JsValue::undefined()) - }) - } - /// 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 media @@ -399,25 +373,20 @@ impl RoomHandle { /// will be disabled. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia - pub fn set_local_media_settings( + pub async fn set_local_media_settings( &self, - settings: &MediaStreamSettings, + settings: MediaStreamSettings, stop_first: bool, rollback_on_fail: bool, - ) -> Promise { - let inner = upgrade_or_detached!(self.0, JasonError); - let settings = settings.clone(); - future_to_promise(async move { - inner? - .set_local_media_settings( - settings, - stop_first, - rollback_on_fail, - ) - .await - .map_err(ConstraintsUpdateException::from)?; - Ok(JsValue::UNDEFINED) - }) + ) -> Result<(), ConstraintsUpdateException> { + let inner = upgrade_or_detached!(self.0, JasonError).unwrap(); // TODO: remove unwrap + + inner + .set_local_media_settings(settings, stop_first, rollback_on_fail) + .await + .map_err(ConstraintsUpdateException::from)?; + + Ok(()) } /// Returns [`Promise`] which will switch [`MediaState`] of the provided @@ -426,163 +395,173 @@ impl RoomHandle { /// /// Helper function for all the exported mute/unmute/enable/disable /// audio/video send/receive methods. - fn change_media_state( + async fn change_media_state( &self, media_state: S, kind: MediaKind, direction: TrackDirection, - source_kind: Option, - ) -> Promise + source_kind: Option, + ) -> Result<(), JasonError> 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) - }) + self.set_track_media_state( + media_state.into(), + kind, + direction, + source_kind.map(Into::into), + ) + .await?; + + Ok(()) } /// Mutes outbound audio in this [`Room`]. - pub fn mute_audio(&self) -> Promise { + pub async fn mute_audio(&self) -> Result<(), JasonError> { self.change_media_state( mute_state::Stable::Muted, MediaKind::Audio, TrackDirection::Send, None, ) + .await } /// Unmutes outbound audio in this [`Room`]. - pub fn unmute_audio(&self) -> Promise { + pub async fn unmute_audio(&self) -> Result<(), JasonError> { self.change_media_state( mute_state::Stable::Unmuted, MediaKind::Audio, TrackDirection::Send, None, ) + .await } /// Mutes outbound video in this [`Room`]. - pub fn mute_video( + pub async fn mute_video( &self, - source_kind: Option, - ) -> Promise { + source_kind: Option, + ) -> Result<(), JasonError> { self.change_media_state( mute_state::Stable::Muted, MediaKind::Video, TrackDirection::Send, source_kind, ) + .await } /// Unmutes outbound video in this [`Room`]. - pub fn unmute_video( + pub async fn unmute_video( &self, - source_kind: Option, - ) -> Promise { + source_kind: Option, + ) -> Result<(), JasonError> { self.change_media_state( mute_state::Stable::Unmuted, MediaKind::Video, TrackDirection::Send, source_kind, ) + .await } /// Disables outbound audio in this [`Room`]. - pub fn disable_audio(&self) -> Promise { + pub async fn disable_audio(&self) -> Result<(), JasonError> { self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Audio, TrackDirection::Send, None, ) + .await } /// Enables outbound audio in this [`Room`]. - pub fn enable_audio(&self) -> Promise { + pub async fn enable_audio(&self) -> Result<(), JasonError> { self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Audio, TrackDirection::Send, None, ) + .await } /// Disables outbound video. /// /// Affects only video with specific [`JsMediaSourceKind`] if specified. - pub fn disable_video( + pub async fn disable_video( &self, - source_kind: Option, - ) -> Promise { + source_kind: Option, + ) -> Result<(), JasonError> { self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Video, TrackDirection::Send, source_kind, ) + .await } /// Enables outbound video. /// /// Affects only video with specific [`JsMediaSourceKind`] if specified. - pub fn enable_video( + pub async fn enable_video( &self, - source_kind: Option, - ) -> Promise { + source_kind: Option, + ) -> Result<(), JasonError> { self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Video, TrackDirection::Send, source_kind, ) + .await } /// Disables inbound audio in this [`Room`]. - pub fn disable_remote_audio(&self) -> Promise { + pub async fn disable_remote_audio(&self) -> Result<(), JasonError> { self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Audio, TrackDirection::Recv, None, ) + .await } /// Disables inbound video in this [`Room`]. - pub fn disable_remote_video(&self) -> Promise { + pub async fn disable_remote_video(&self) -> Result<(), JasonError> { self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Video, TrackDirection::Recv, None, ) + .await } /// Enables inbound audio in this [`Room`]. - pub fn enable_remote_audio(&self) -> Promise { + pub async fn enable_remote_audio(&self) -> Result<(), JasonError> { self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Audio, TrackDirection::Recv, None, ) + .await } /// Enables inbound video in this [`Room`]. - pub fn enable_remote_video(&self) -> Promise { + pub async fn enable_remote_video(&self) -> Result<(), JasonError> { self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Video, TrackDirection::Recv, None, ) + .await } } @@ -638,7 +617,7 @@ impl Room { let room = Rc::new(InnerRoom::new(rpc, media_manager, tx)); let inner = Rc::downgrade(&room); - spawn_local(async move { + spawn(async move { loop { let event: RoomEvent = futures::select! { event = rpc_events_stream.select_next_some() => event, @@ -753,7 +732,7 @@ struct InnerRoom { /// Callback to be invoked when new local [`local::JsTrack`] will be added /// to this [`Room`]. - on_local_track: Callback1, + on_local_track: Callback1, /// Callback to be invoked when failed obtain [`local::Track`]s from /// [`MediaManager`] or failed inject stream into [`PeerConnection`]. @@ -762,10 +741,10 @@ struct InnerRoom { on_failed_local_media: Rc>, /// Callback to be invoked when [`RpcSession`] loses connection. - on_connection_loss: Callback1, + on_connection_loss: Callback1, /// JS callback which will be called when this [`Room`] will be closed. - on_close: Rc>, + on_close: Rc>, /// Reason of [`Room`] closing. /// @@ -777,12 +756,10 @@ struct InnerRoom { } /// JS exception for the [`RoomHandle::set_local_media_settings`]. -#[wasm_bindgen] #[derive(Debug, From)] #[from(forward)] pub struct ConstraintsUpdateException(JsConstraintsUpdateError); -#[wasm_bindgen] impl ConstraintsUpdateException { /// Returns name of this [`ConstraintsUpdateException`]. pub fn name(&self) -> String { @@ -992,13 +969,14 @@ impl InnerRoom { /// Toggles [`InnerRoom::recv_constraints`] or /// [`InnerRoom::send_constraints`] media exchange status based on the - /// provided [`TrackDirection`], [`MediaKind`] and [`MediaSourceKind`]. + /// provided [`TrackDirection`], [`MediaKind`] and + /// [`proto::MediaSourceKind`]. fn set_constraints_media_state( &self, state: MediaState, kind: MediaKind, direction: TrackDirection, - source_kind: Option, + source_kind: Option, ) { use media_exchange_state::Stable::Enabled; use MediaState::{MediaExchange, Mute}; @@ -1036,7 +1014,7 @@ impl InnerRoom { state: MediaState, kind: MediaKind, direction: TrackDirection, - source_kind: Option, + source_kind: Option, ) -> Result<(), Traced> { let disable_tracks: HashMap<_, _> = self .peers @@ -1143,10 +1121,10 @@ impl InnerRoom { } /// Returns [`local::Track`]s for the provided [`MediaKind`] and - /// [`MediaSourceKind`]. + /// [`proto::MediaSourceKind`]. /// - /// If [`MediaSourceKind`] is [`None`] then [`local::TrackHandle`]s for all - /// needed [`MediaSourceKind`]s will be returned. + /// If [`proto::MediaSourceKind`] is [`None`] then [`local::TrackHandle`]s + /// for all needed [`proto::MediaSourceKind`]s will be returned. /// /// # Errors /// @@ -1159,7 +1137,7 @@ impl InnerRoom { async fn get_local_tracks( &self, kind: MediaKind, - source_kind: Option, + source_kind: Option, ) -> Result>, Traced> { let requests: Vec<_> = self .peers @@ -1185,7 +1163,7 @@ impl InnerRoom { for (track, is_new) in tracks { if is_new { self.on_local_track - .call(local::JsTrack::new(Rc::clone(&track))); + .call(local::LocalMediaTrack::new(Rc::clone(&track))); } result.push(track); } @@ -1195,7 +1173,7 @@ impl InnerRoom { } /// Returns `true` if all [`Sender`]s or [`Receiver`]s with a provided - /// [`MediaKind`] and [`MediaSourceKind`] of this [`Room`] are in the + /// [`MediaKind`] and [`proto::MediaSourceKind`] of this [`Room`] are in the /// provided [`MediaState`]. /// /// [`Sender`]: crate::peer::Sender @@ -1204,7 +1182,7 @@ impl InnerRoom { &self, kind: MediaKind, direction: TrackDirection, - source_kind: Option, + source_kind: Option, state: MediaState, ) -> bool { self.peers @@ -1615,7 +1593,7 @@ impl PeerEventHandler for InnerRoom { &self, track: Rc, ) -> Self::Output { - self.on_local_track.call(local::JsTrack::new(track)); + self.on_local_track.call(local::LocalMediaTrack::new(track)); Ok(()) } @@ -1658,7 +1636,7 @@ impl PeerEventHandler for InnerRoom { async fn on_stats_update( &self, peer_id: PeerId, - stats: RtcStats, + stats: platform::RtcStats, ) -> Self::Output { self.rpc.send_command(Command::AddPeerConnectionMetrics { peer_id, diff --git a/jason/src/rpc/backoff_delayer.rs b/jason/src/core/rpc/backoff_delayer.rs similarity index 82% rename from jason/src/rpc/backoff_delayer.rs rename to jason/src/core/rpc/backoff_delayer.rs index cfd622cb4..cf84030fb 100644 --- a/jason/src/rpc/backoff_delayer.rs +++ b/jason/src/core/rpc/backoff_delayer.rs @@ -1,6 +1,8 @@ //! Delayer that increases delay time by provided multiplier on each call. -use crate::utils::{delay_for, JsDuration}; +use std::time::Duration; + +use crate::platform::delay_for; /// Delayer that increases delay time by provided multiplier on each call. /// @@ -13,10 +15,10 @@ pub struct BackoffDelayer { /// Delay of next [`BackoffDelayer::delay`] call. /// /// Will be increased by [`BackoffDelayer::delay`] call. - current_interval: JsDuration, + current_interval: Duration, /// Maximum delay for which this [`BackoffDelayer`] may delay. - max_interval: JsDuration, + max_interval: Duration, /// The multiplier by which [`BackoffDelayer::current_interval`] will be /// multiplied on [`BackoffDelayer::delay`] call. @@ -26,9 +28,9 @@ pub struct BackoffDelayer { impl BackoffDelayer { /// Creates and returns new [`BackoffDelayer`]. pub fn new( - starting_interval: JsDuration, + starting_interval: Duration, interval_multiplier: f32, - max_interval: JsDuration, + max_interval: Duration, ) -> Self { Self { current_interval: starting_interval, @@ -48,13 +50,14 @@ impl BackoffDelayer { } /// Returns current interval and increases it for next call. - fn get_delay(&mut self) -> JsDuration { + fn get_delay(&mut self) -> Duration { if self.is_max_interval_reached() { self.max_interval } else { let delay = self.current_interval; - self.current_interval = - self.current_interval * self.interval_multiplier; + self.current_interval = Duration::from_secs_f32( + self.current_interval.as_secs_f32() * self.interval_multiplier, + ); delay } } diff --git a/jason/src/rpc/heartbeat.rs b/jason/src/core/rpc/heartbeat.rs similarity index 93% rename from jason/src/rpc/heartbeat.rs rename to jason/src/core/rpc/heartbeat.rs index b1f11d997..d0b99a95b 100644 --- a/jason/src/rpc/heartbeat.rs +++ b/jason/src/core/rpc/heartbeat.rs @@ -1,32 +1,35 @@ //! Connection loss detection via ping/pong mechanism. -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, rc::Rc, time::Duration}; use derive_more::{Display, From, Mul}; use futures::{channel::mpsc, future, stream::LocalBoxStream, StreamExt as _}; use medea_client_api_proto::{ClientMsg, ServerMsg}; -use wasm_bindgen_futures::spawn_local; use crate::{ - rpc::{RpcTransport, TransportError}, - utils::{delay_for, JsCaused, JsDuration, JsError, TaskHandle}, + core::utils::{JsCaused, TaskHandle}, + platform::{ + self, delay_for, spawn, + transport::{RpcTransport, TransportError}, + }, }; /// Errors that may occur in [`Heartbeat`]. #[derive(Clone, Debug, Display, From, JsCaused)] +#[js(error = "platform::Error")] pub struct HeartbeatError(TransportError); /// Idle timeout of [`WebSocketRpcClient`]. /// /// [`WebSocketRpcClient`]: super::WebSocketRpcClient #[derive(Debug, Copy, Clone)] -pub struct IdleTimeout(pub JsDuration); +pub struct IdleTimeout(pub Duration); /// Ping interval of [`WebSocketRpcClient`]. /// /// [`WebSocketRpcClient`]: super::WebSocketRpcClient #[derive(Debug, Copy, Clone, Mul)] -pub struct PingInterval(pub JsDuration); +pub struct PingInterval(pub Duration); /// Inner data of [`Heartbeat`]. struct Inner { @@ -141,7 +144,7 @@ fn spawn_idle_watchdog_task(this: Rc>) -> TaskHandle { .retain(|sub| sub.unbounded_send(()).is_ok()); }); - spawn_local(async move { + spawn(async move { idle_watchdog_fut.await.ok(); }); @@ -166,7 +169,7 @@ fn spawn_ping_handle_task(this: Rc>) -> TaskHandle { } } }); - spawn_local(async move { + spawn(async move { handle_ping_fut.await.ok(); }); handle_ping_task.into() diff --git a/jason/src/rpc/mod.rs b/jason/src/core/rpc/mod.rs similarity index 87% rename from jason/src/rpc/mod.rs rename to jason/src/core/rpc/mod.rs index c99b45ec3..5327cc492 100644 --- a/jason/src/rpc/mod.rs +++ b/jason/src/core/rpc/mod.rs @@ -8,16 +8,17 @@ pub mod websocket; use std::str::FromStr; -use derive_more::{Display, From}; +use derive_more::{AsRef, Display, From}; use medea_client_api_proto::{ - CloseDescription, CloseReason as CloseByServerReason, Credential, MemberId, - RoomId, + CloseReason as CloseByServerReason, Credential, MemberId, RoomId, }; use tracerr::Traced; use url::Url; -use web_sys::CloseEvent; -use crate::utils::{JsCaused, JsError}; +use crate::{ + core::utils::JsCaused, + platform::{self, transport::TransportError}, +}; #[cfg(feature = "mockable")] pub use self::rpc_session::MockRpcSession; @@ -29,14 +30,12 @@ pub use self::{ rpc_session::{ RpcSession, SessionError, SessionState, WebSocketRpcSession, }, - websocket::{ - ClientDisconnect, RpcTransport, TransportError, WebSocketRpcClient, - WebSocketRpcTransport, - }, + websocket::{ClientDisconnect, WebSocketRpcClient}, }; /// [`Url`] to which transport layer will connect. -#[derive(Clone, Debug, Eq, From, PartialEq)] +#[derive(AsRef, Clone, Debug, Eq, From, PartialEq)] +#[as_ref(forward)] pub struct ApiUrl(Url); /// Information about [`RpcSession`] connection. @@ -80,6 +79,7 @@ impl ConnectionInfo { /// Errors which can occur while [`ConnectionInfo`] parsing from the [`str`]. #[derive(Debug, JsCaused, Display)] +#[js(error = "platform::Error")] pub enum ConnectionInfoParseError { /// [`Url::parse`] returned error. #[display(fmt = "Failed to parse provided URL: {:?}", _0)] @@ -186,6 +186,7 @@ pub enum ClosedStateReason { /// Errors that may occur in [`WebSocketRpcClient`]. #[derive(Clone, Debug, Display, From, JsCaused)] +#[js(error = "platform::Error")] pub enum RpcClientError { /// Occurs if WebSocket connection to remote media server failed. #[display(fmt = "Connection failed: {}", _0)] @@ -227,21 +228,3 @@ pub enum CloseMsg { /// `1000` without reason. Abnormal(u16), } - -impl From<&CloseEvent> for CloseMsg { - fn from(event: &CloseEvent) -> Self { - let code: u16 = event.code(); - match code { - 1000 => { - if let Ok(description) = - serde_json::from_str::(&event.reason()) - { - Self::Normal(code, description.reason) - } else { - Self::Abnormal(code) - } - } - _ => Self::Abnormal(code), - } - } -} diff --git a/jason/src/rpc/reconnect_handle.rs b/jason/src/core/rpc/reconnect_handle.rs similarity index 59% rename from jason/src/rpc/reconnect_handle.rs rename to jason/src/core/rpc/reconnect_handle.rs index 18609c886..a2847411f 100644 --- a/jason/src/rpc/reconnect_handle.rs +++ b/jason/src/core/rpc/reconnect_handle.rs @@ -3,25 +3,25 @@ use std::{rc::Weak, time::Duration}; use derive_more::Display; -use js_sys::Promise; -use wasm_bindgen::prelude::*; -use wasm_bindgen_futures::future_to_promise; use crate::{ - rpc::{BackoffDelayer, RpcSession}, - utils::{delay_for, HandlerDetachedError, JasonError, JsCaused, JsError}, + core::{ + rpc::{BackoffDelayer, RpcSession}, + utils::{HandlerDetachedError, JasonError, JsCaused}, + }, + platform::{self, delay_for}, }; /// Error which indicates that [`RpcSession`]'s (which this [`ReconnectHandle`] /// tries to reconnect) token is `None`. #[derive(Debug, Display, JsCaused)] +#[js(error = "platform::Error")] struct NoTokenError; /// Handle that JS side can reconnect to the Medea media server on /// a connection loss with. /// /// This handle will be provided into `Room.on_connection_loss` callback. -#[wasm_bindgen] #[derive(Clone)] pub struct ReconnectHandle(Weak); @@ -31,27 +31,22 @@ impl ReconnectHandle { pub fn new(rpc: Weak) -> Self { Self(rpc) } -} -#[wasm_bindgen] -impl ReconnectHandle { /// Tries to reconnect after the provided delay in milliseconds. /// /// If [`RpcSession`] is already reconnecting then new reconnection attempt /// won't be performed. Instead, it will wait for the first reconnection /// attempt result and use it here. - pub fn reconnect_with_delay(&self, delay_ms: u32) -> Promise { - let rpc = Clone::clone(&self.0); - future_to_promise(async move { - delay_for(Duration::from_millis(u64::from(delay_ms)).into()).await; + pub async fn reconnect_with_delay( + &self, + delay_ms: u32, + ) -> Result<(), JasonError> { + delay_for(Duration::from_millis(u64::from(delay_ms)).into()).await; - let rpc = upgrade_or_detached!(rpc, JsValue)?; - rpc.reconnect() - .await - .map_err(|e| JsValue::from(JasonError::from(e)))?; + let rpc = upgrade_or_detached!(self.0, JasonError)?; + rpc.reconnect().await.map_err(|e| JasonError::from(e))?; - Ok(JsValue::UNDEFINED) - }) + Ok(()) } /// Tries to reconnect [`RpcSession`] in a loop with a growing backoff @@ -72,29 +67,26 @@ impl ReconnectHandle { /// /// If `multiplier` is negative number than `multiplier` will be considered /// as `0.0`. - pub fn reconnect_with_backoff( + pub async fn reconnect_with_backoff( &self, starting_delay_ms: u32, multiplier: f32, max_delay: u32, - ) -> Promise { - let rpc = self.0.clone(); - future_to_promise(async move { - let mut backoff_delayer = BackoffDelayer::new( - Duration::from_millis(u64::from(starting_delay_ms)).into(), - multiplier, - Duration::from_millis(u64::from(max_delay)).into(), - ); + ) -> Result<(), JasonError> { + let mut backoff_delayer = BackoffDelayer::new( + Duration::from_millis(u64::from(starting_delay_ms)).into(), + multiplier, + Duration::from_millis(u64::from(max_delay)).into(), + ); + backoff_delayer.delay().await; + while upgrade_or_detached!(self.0, JasonError)? + .reconnect() + .await + .is_err() + { backoff_delayer.delay().await; - while upgrade_or_detached!(rpc, JsValue)? - .reconnect() - .await - .is_err() - { - backoff_delayer.delay().await; - } + } - Ok(JsValue::UNDEFINED) - }) + Ok(()) } } diff --git a/jason/src/rpc/rpc_session.rs b/jason/src/core/rpc/rpc_session.rs similarity index 98% rename from jason/src/rpc/rpc_session.rs rename to jason/src/core/rpc/rpc_session.rs index 8b9afb51e..2218604f1 100644 --- a/jason/src/rpc/rpc_session.rs +++ b/jason/src/core/rpc/rpc_session.rs @@ -15,18 +15,21 @@ use futures::{ use medea_client_api_proto::{Command, Event, MemberId, RoomId}; use medea_reactive::ObservableCell; use tracerr::Traced; -use wasm_bindgen_futures::spawn_local; use crate::{ - rpc::{ - websocket::RpcEventHandler, ClientDisconnect, CloseReason, - ConnectionInfo, RpcClientError, WebSocketRpcClient, + core::{ + rpc::{ + websocket::RpcEventHandler, ClientDisconnect, CloseReason, + ConnectionInfo, RpcClientError, WebSocketRpcClient, + }, + utils::JsCaused, }, - utils::{JsCaused, JsError}, + platform::{self, spawn}, }; /// Errors which are can be returned from the [`WebSocketRpcSession`]. #[derive(Clone, Debug, From, JsCaused, Display)] +#[js(error = "platform::Error")] pub enum SessionError { /// [`WebSocketRpcSession`] goes into [`SessionState::Finished`] and can't /// be used. @@ -75,7 +78,7 @@ pub trait RpcSession { /// new RPC connection. /// /// If [`RpcSession`] already in [`SessionState::Connecting`] then this - /// function will not perform one more connection try. It will subsribe + /// function will not perform one more connection try. It will subscribe /// to [`SessionState`] changes and wait for first connection result. /// And based on this result - this function will be resolved. /// @@ -249,7 +252,7 @@ impl WebSocketRpcSession { let mut state_updates = self.state.subscribe(); let weak_this = Rc::downgrade(self); - spawn_local(async move { + spawn(async move { while let Some(state) = state_updates.next().await { let this = upgrade_or_break!(weak_this); match state { @@ -290,7 +293,7 @@ impl WebSocketRpcSession { let mut client_on_connection_loss = self.client.on_connection_loss(); let weak_this = Rc::downgrade(self); - spawn_local(async move { + spawn(async move { while client_on_connection_loss.next().await.is_some() { let this = upgrade_or_break!(weak_this); @@ -322,7 +325,7 @@ impl WebSocketRpcSession { fn spawn_close_watcher(self: &Rc) { let on_normal_close = self.client.on_normal_close(); let weak_this = Rc::downgrade(self); - spawn_local(async move { + spawn(async move { let reason = on_normal_close.await.unwrap_or_else(|_| { ClientDisconnect::RpcClientUnexpectedlyDropped.into() }); @@ -336,7 +339,7 @@ impl WebSocketRpcSession { fn spawn_server_msg_listener(self: &Rc) { let mut server_msg_rx = self.client.subscribe(); let weak_this = Rc::downgrade(self); - spawn_local(async move { + spawn(async move { while let Some(msg) = server_msg_rx.next().await { let this = upgrade_or_break!(weak_this); msg.dispatch_with(this.as_ref()); diff --git a/jason/src/rpc/websocket/client.rs b/jason/src/core/rpc/websocket/client.rs similarity index 98% rename from jason/src/rpc/websocket/client.rs rename to jason/src/core/rpc/websocket/client.rs index a1e2bdf12..685c50d65 100644 --- a/jason/src/rpc/websocket/client.rs +++ b/jason/src/core/rpc/websocket/client.rs @@ -14,15 +14,19 @@ use medea_macro::dispatchable; use medea_reactive::ObservableCell; use serde::Serialize; use tracerr::Traced; -use wasm_bindgen_futures::spawn_local; use crate::{ - rpc::{ - websocket::transport::{RpcTransport, TransportError, TransportState}, - ApiUrl, CloseMsg, CloseReason, ClosedStateReason, Heartbeat, - IdleTimeout, PingInterval, RpcClientError, + core::{ + rpc::{ + ApiUrl, CloseMsg, CloseReason, ClosedStateReason, Heartbeat, + IdleTimeout, PingInterval, RpcClientError, + }, + utils::JasonError, + }, + platform::{ + spawn, + transport::{RpcTransport, TransportError, TransportState}, }, - utils::JasonError, }; /// Reasons of closing WebSocket RPC connection by a client side. @@ -353,7 +357,7 @@ impl WebSocketRpcClient { let mut on_idle = heartbeat.on_idle(); let weak_this = Rc::downgrade(&self); - spawn_local(async move { + spawn(async move { while on_idle.next().await.is_some() { if let Some(this) = weak_this.upgrade() { this.handle_connection_loss(ClosedStateReason::Idle); @@ -412,7 +416,7 @@ impl WebSocketRpcClient { // subscribe to transport close let mut transport_state_changes = transport.on_state_change(); let weak_this = Rc::downgrade(&self); - spawn_local(async move { + spawn(async move { while let Some(state) = transport_state_changes.next().await { if let Some(this) = weak_this.upgrade() { if let TransportState::Closed(msg) = state { @@ -425,7 +429,7 @@ impl WebSocketRpcClient { // subscribe to transport message received let weak_this = Rc::downgrade(&self); let mut on_socket_message = transport.on_message(); - spawn_local(async move { + spawn(async move { while let Some(msg) = on_socket_message.next().await { if let Some(this) = weak_this.upgrade() { this.on_transport_message(msg) diff --git a/jason/src/core/rpc/websocket/mod.rs b/jason/src/core/rpc/websocket/mod.rs new file mode 100644 index 000000000..943e168c9 --- /dev/null +++ b/jason/src/core/rpc/websocket/mod.rs @@ -0,0 +1,13 @@ +//! Implementation of the abstractions around [WebSocket] transport. +//! +//! [WebSocket]: https://developer.mozilla.org/ru/docs/WebSockets + +mod client; + +#[doc(inline)] +pub use self::client::{ + ClientDisconnect, ClientState, RpcEvent, RpcEventHandler, + RpcTransportFactory, WebSocketRpcClient, +}; +#[cfg(feature = "mockable")] +pub use self::transport::MockRpcTransport; diff --git a/jason/src/core/utils/callback.rs b/jason/src/core/utils/callback.rs new file mode 100644 index 000000000..3b0390607 --- /dev/null +++ b/jason/src/core/utils/callback.rs @@ -0,0 +1,86 @@ +//! Somewhat convenient wrappers around JS functions used as callbacks. + +use std::{cell::RefCell, marker::PhantomData}; + +use js_sys::Function as JsFunction; + +/// Wrapper for JS function with no arguments. +#[derive(Default)] +pub struct Callback0 { + f: RefCell>, +} + +impl Callback0 { + /// Sets inner JS function. + #[inline] + pub fn set_func(&self, f: JsFunction) { + self.f.borrow_mut().replace(f); + } + + /// Invokes JS function if any. + /// + /// Returns `None` if no callback is set, otherwise returns its invocation + /// result. + pub fn call(&self) -> Option> { + self.f.borrow().as_ref().map(|f| f.call0(&JsValue::NULL)) + } + + /// Indicates whether callback is set. + #[inline] + pub fn is_set(&self) -> bool { + self.f.borrow().as_ref().is_some() + } +} + +/// Wrapper for a single argument JS function. +pub struct Callback1 { + f: RefCell>, + _arg: PhantomData, +} + +impl Default for Callback1 { + #[inline] + fn default() -> Self { + Self { + f: RefCell::new(None), + _arg: PhantomData, + } + } +} + +impl Callback1 { + /// Sets inner JS function. + #[inline] + pub fn set_func(&self, f: JsFunction) { + self.f.borrow_mut().replace(f); + } + + /// Indicates if callback is set. + #[inline] + pub fn is_set(&self) -> bool { + self.f.borrow().as_ref().is_some() + } +} + +impl> Callback1 { + /// Invokes JS function if any. + /// + /// Returns `None` if no callback is set, otherwise returns its invocation + /// result. + pub fn call>(&self, arg: T) -> Option> { + self.f + .borrow() + .as_ref() + .map(|f| f.call1(&JsValue::NULL, &arg.into().into())) + } +} + +impl From for Callback1 { + #[inline] + fn from(f: JsFunction) -> Self { + Self { + f: RefCell::new(Some(f)), + _arg: PhantomData, + } + } +} diff --git a/jason/src/utils/component.rs b/jason/src/core/utils/component.rs similarity index 97% rename from jason/src/utils/component.rs rename to jason/src/core/utils/component.rs index 4b9bd7028..ea0b65f84 100644 --- a/jason/src/utils/component.rs +++ b/jason/src/core/utils/component.rs @@ -5,11 +5,13 @@ use std::rc::Rc; use derive_more::Deref; use futures::{future, Future, FutureExt as _, Stream, StreamExt}; use medea_reactive::AllProcessed; -use wasm_bindgen_futures::spawn_local; use crate::{ - media::LocalTracksConstraints, - utils::{JasonError, TaskHandle}, + core::{ + media::LocalTracksConstraints, + utils::{JasonError, TaskHandle}, + }, + platform::spawn, }; /// Abstraction over a state which can be transformed to the states from the @@ -137,7 +139,7 @@ impl WatchersSpawner { } } }); - spawn_local(fut.map(|_| ())); + spawn(fut.map(|_| ())); self.spawned_watchers.push(handle.into()); } diff --git a/jason/src/utils/errors.rs b/jason/src/core/utils/errors.rs similarity index 62% rename from jason/src/utils/errors.rs rename to jason/src/core/utils/errors.rs index 1b06c827c..88e457ca3 100644 --- a/jason/src/utils/errors.rs +++ b/jason/src/core/utils/errors.rs @@ -1,29 +1,15 @@ use std::{ - borrow::Cow, fmt::{Debug, Display}, rc::Rc, }; use derive_more::{Display, From}; use tracerr::{Trace, Traced}; -use wasm_bindgen::{prelude::*, JsCast}; +use wasm_bindgen::prelude::*; -pub use medea_macro::JsCaused; +use crate::platform; -/// Prints provided message with [`Console.error()`]. -/// -/// May be useful during development. -/// -/// __Unavailable in the release builds.__ -/// -/// [`Console.error()`]: https://tinyurl.com/psv3wqw -#[cfg(debug_assertions)] -pub fn console_error(msg: M) -where - M: Into, -{ - web_sys::console::error_1(&msg.into()); -} +pub use medea_macro::JsCaused; /// Representation of an error which can caused by error returned from the /// JS side. @@ -38,46 +24,6 @@ pub trait JsCaused { fn js_cause(self) -> Option; } -/// Wrapper for JS value which returned from JS side as error. -#[derive(Clone, Debug, Display, PartialEq)] -#[display(fmt = "{}: {}", name, message)] -pub struct JsError { - /// Name of JS error. - pub name: Cow<'static, str>, - - /// Message of JS error. - pub message: Cow<'static, str>, -} - -impl From for JsError { - fn from(val: JsValue) -> Self { - match val.dyn_into::() { - Ok(err) => Self { - name: Cow::Owned(err.name().into()), - message: Cow::Owned(err.message().into()), - }, - Err(val) => match val.as_string() { - Some(reason) => Self { - name: "Unknown JS error".into(), - message: reason.into(), - }, - None => Self { - name: "Unknown JS error".into(), - message: format!("{:?}", val).into(), - }, - }, - } - } -} - -impl From for js_sys::Error { - fn from(err: JsError) -> Self { - let error = Self::new(&err.message); - error.set_name(&err.name); - error - } -} - /// Representation of app error exported to JS side. /// /// Contains JS side error if it the cause and trace information. @@ -146,6 +92,7 @@ where /// Occurs if referenced value was dropped. #[derive(Debug, Display, JsCaused)] +#[js(error = "platform::Error")] #[display(fmt = "Handler is in detached state.")] pub struct HandlerDetachedError; diff --git a/jason/src/core/utils/mod.rs b/jason/src/core/utils/mod.rs new file mode 100644 index 000000000..f51894e66 --- /dev/null +++ b/jason/src/core/utils/mod.rs @@ -0,0 +1,92 @@ +//! Miscellaneous utility structs and functions. + +#[macro_use] +mod errors; + +mod callback; +pub mod component; +mod resettable_delay; + +use std::future::Future; + +use derive_more::From; +use futures::future::{self, AbortHandle}; +use medea_reactive::Guarded; + +#[doc(inline)] +pub use self::{ + callback::{Callback0, Callback1}, + component::{AsProtoState, Component, SynchronizableState, Updatable}, + errors::{HandlerDetachedError, JasonError, JsCaused, JsonParseError}, + resettable_delay::{resettable_delay_for, ResettableDelayHandle}, +}; + +/// Upgrades provided [`Weak`] reference, mapping it to a [`Result`] with +/// [`HandlerDetachedError`] and invokes [`Into::into`] on the error. +/// If the error type cannot be inferred, then you can provide a concrete type +/// (usually being [`JasonError`] or [`JsValue`]). +/// +/// [`Weak`]: std::rc::Weak +macro_rules! upgrade_or_detached { + ($v:expr) => {{ + $v.upgrade() + .ok_or_else(|| new_js_error!(HandlerDetachedError)) + }}; + ($v:expr, $err:ty) => {{ + $v.upgrade() + .ok_or_else(|| new_js_error!(HandlerDetachedError => $err)) + }}; +} + +/// Adds [`tracerr`] information to the provided error, wraps it into +/// [`JasonError`] and converts it into the expected error type. +/// +/// This macro has two syntaxes: +/// - `new_js_error!(DetachedStateError)` - converts provided error wrapped into +/// [`JasonError`] with [`Into::into`] automatically; +/// - `new_js_error!(DetachedStateError => platform::Error)` - annotates +/// explicitly which type conversion is required. +macro_rules! new_js_error { + ($e:expr) => { + $crate::utils::JasonError::from(tracerr::new!($e)).into() + }; + ($e:expr => $o:ty) => { + <$o>::from($crate::utils::JasonError::from(tracerr::new!($e))) + }; +} + +/// Wrapper around [`AbortHandle`] which aborts [`Future`] on [`Drop`]. +/// +/// [`Future`]: std::future::Future +#[derive(Debug, From)] +pub struct TaskHandle(AbortHandle); + +impl Drop for TaskHandle { + fn drop(&mut self) { + self.0.abort(); + } +} + +/// Tries to upgrade [`Weak`] reference breaks cycle if upgrade fails. +macro_rules! upgrade_or_break { + ($weak:tt) => { + if let Some(this) = $weak.upgrade() { + this + } else { + break; + } + }; +} + +/// Returns [`Future`] which will return the provided value being +/// [`Guarded::transpose()`]d. +/// +/// Intended for use in [`StreamExt::filter_map()`]. +/// +/// [`StreamExt::filter_map()`]: futures::StreamExt::filter_map +#[inline] +pub fn transpose_guarded( + val: Guarded>, +) -> impl Future>> { + future::ready(val.transpose()) +} diff --git a/jason/src/utils/resettable_delay.rs b/jason/src/core/utils/resettable_delay.rs similarity index 92% rename from jason/src/utils/resettable_delay.rs rename to jason/src/core/utils/resettable_delay.rs index 3721af2c0..098eb1a78 100644 --- a/jason/src/utils/resettable_delay.rs +++ b/jason/src/core/utils/resettable_delay.rs @@ -7,9 +7,8 @@ use futures::{ future, future::{AbortHandle, FutureExt}, }; -use wasm_bindgen_futures::spawn_local; -use crate::utils::delay_for; +use crate::platform::{delay_for, spawn}; type FutureResolver = Rc>>>; @@ -85,11 +84,11 @@ impl ResettableDelayHandle { let timeout = self.timeout; let (fut, abort) = future::abortable(async move { delay_for(timeout.into()).await; - if let Some(rslvr) = future_resolver.borrow_mut().take() { - let _ = rslvr.send(()); + if let Some(rsvr) = future_resolver.borrow_mut().take() { + let _ = rsvr.send(()); } }); - spawn_local(fut.map(|_| ())); + spawn(fut.map(|_| ())); self.abort_handle.replace(abort); } diff --git a/jason/src/lib.rs b/jason/src/lib.rs index dd441b60c..a389e0a0e 100644 --- a/jason/src/lib.rs +++ b/jason/src/lib.rs @@ -9,36 +9,8 @@ #![cfg_attr(not(feature = "mockable"), warn(missing_docs))] #![cfg_attr(feature = "mockable", allow(missing_docs))] -#[macro_use] -pub mod utils; +pub use self::core::utils; -pub mod api; -pub mod media; -pub mod peer; -pub mod rpc; - -// When the `console_error_panic_hook` feature is enabled, we can call the -// `set_panic_hook` function at least once during initialization, and then -// we will get better error messages if our code ever panics. -// -// For more details see: -// https://github.com/rustwasm/console_error_panic_hook#readme -#[cfg(feature = "console_error_panic_hook")] -pub use console_error_panic_hook::set_once as set_panic_hook; - -#[doc(inline)] -pub use self::{ - api::{ConnectionHandle, Jason, RoomCloseReason, RoomHandle}, - media::{ - track::{local::JsTrack, remote::Track}, - AudioTrackConstraints, DeviceVideoTrackConstraints, - DisplayVideoTrackConstraints, FacingMode, JsMediaSourceKind, MediaKind, - MediaStreamSettings, - }, -}; - -// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global -// allocator. -#[cfg(feature = "wee_alloc")] -#[global_allocator] -static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; +mod api; +mod core; +mod platform; diff --git a/jason/src/platform/mod.rs b/jason/src/platform/mod.rs new file mode 100644 index 000000000..194d7d590 --- /dev/null +++ b/jason/src/platform/mod.rs @@ -0,0 +1,157 @@ +// #[cfg(all( +// target_arch = "wasm32", +// target_vendor = "unknown", +// target_os = "unknown" +// ))] +mod wasm; + +// #[cfg(all( +// target_arch = "wasm32", +// target_vendor = "unknown", +// target_os = "unknown" +// ))] +pub use wasm::{ + delay_for, enumerate_devices, get_display_media, get_property_by_name, + get_user_media, init_logger, + input_device_info::InputDeviceInfo, + media_track::MediaStreamTrack, + peer_connection::{ + IceCandidate, RTCPeerConnectionError, RtcPeerConnection, SdpType, + }, + rtc_stats::{RtcStats, RtcStatsError}, + set_panic_hook, spawn, + transceiver::{Transceiver, TransceiverDirection}, + Error, +}; + +pub use web_sys::{ + ConstrainDomStringParameters, ConstrainDoubleRange, + DisplayMediaStreamConstraints, MediaDeviceInfo, MediaDeviceKind, + MediaStreamConstraints, MediaStreamTrackState, MediaTrackConstraints, +}; + +pub mod transport { + use derive_more::Display; + use futures::stream::LocalBoxStream; + use medea_client_api_proto::{ClientMsg, ServerMsg}; + use tracerr::Traced; + + pub use super::wasm::transport::WebSocketRpcTransport; + + use crate::{ + core::{ + rpc::{ClientDisconnect, CloseMsg}, + utils::JsonParseError, + }, + platform::{self, wasm::utils::EventListenerBindError}, + utils::JsCaused, + }; + + /// [`RpcTransport`] states. + #[derive(Clone, Copy, Debug, PartialEq)] + pub enum TransportState { + /// Socket has been created. The connection is not open yet. + /// + /// Reflects `CONNECTING` state from JS side + /// [`WebSocket.readyState`][1]. + /// + /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState + Connecting, + + /// The connection is open and ready to communicate. + /// + /// Reflects `OPEN` state from JS side [`WebSocket.readyState`][1]. + /// + /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState + Open, + + /// The connection is in the process of closing. + /// + /// Reflects `CLOSING` state from JS side [`WebSocket.readyState`][1]. + /// + /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState + Closing, + + /// The connection is closed or couldn't be opened. + /// + /// Reflects `CLOSED` state from JS side [`WebSocket.readyState`][1]. + /// + /// [`CloseMsg`] is the reason of why [`RpcTransport`] went into + /// this [`TransportState`]. + /// + /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState + Closed(CloseMsg), + } + + impl TransportState { + /// Returns `true` if socket can be closed. + pub fn can_close(self) -> bool { + matches!(self, Self::Connecting | Self::Open) + } + } + + /// RPC transport between a client and a server. + #[cfg_attr(feature = "mockable", mockall::automock)] + pub trait RpcTransport { + /// Returns [`LocalBoxStream`] of all messages received by this + /// transport. + fn on_message(&self) -> LocalBoxStream<'static, ServerMsg>; + + /// Sets reason, that will be sent to remote server when this transport + /// will be dropped. + fn set_close_reason(&self, reason: ClientDisconnect); + + /// Sends given [`ClientMsg`] to a server. + /// + /// # Errors + /// + /// Errors if sending [`ClientMsg`] fails. + fn send(&self, msg: &ClientMsg) -> Result<(), Traced>; + + /// Subscribes to a [`RpcTransport`]'s [`TransportState`] changes. + fn on_state_change(&self) -> LocalBoxStream<'static, TransportState>; + } + + /// Errors that may occur when working with [`WebSocketRpcClient`]. + /// + /// [`WebSocketRpcClient`]: super::WebSocketRpcClient + #[derive(Clone, Debug, Display, JsCaused, PartialEq)] + #[js(error = "platform::Error")] + pub enum TransportError { + /// Occurs when the port to which the connection is being attempted + /// is being blocked. + #[display(fmt = "Failed to create WebSocket: {}", _0)] + CreateSocket(platform::Error), + + /// Occurs when the connection close before becomes state active. + #[display(fmt = "Failed to init WebSocket")] + InitSocket, + + /// Occurs when [`ClientMsg`] cannot be parsed. + #[display(fmt = "Failed to parse client message: {}", _0)] + ParseClientMessage(JsonParseError), + + /// Occurs when [`ServerMsg`] cannot be parsed. + #[display(fmt = "Failed to parse server message: {}", _0)] + ParseServerMessage(JsonParseError), + + /// Occurs if the parsed message is not string. + #[display(fmt = "Message is not a string")] + MessageNotString, + + /// Occurs when a message cannot be send to server. + #[display(fmt = "Failed to send message: {}", _0)] + SendMessage(platform::Error), + + /// Occurs when handler failed to bind to some [WebSocket] event. Not + /// really supposed to ever happen. + /// + /// [WebSocket]: https://developer.mozilla.org/ru/docs/WebSockets + #[display(fmt = "Failed to bind to WebSocket event: {}", _0)] + WebSocketEventBindError(EventListenerBindError), // TODO: remove + + /// Occurs when message is sent to a closed socket. + #[display(fmt = "Underlying socket is closed")] + ClosedSocket, + } +} diff --git a/jason/src/peer/ice_server.rs b/jason/src/platform/wasm/ice_server.rs similarity index 100% rename from jason/src/peer/ice_server.rs rename to jason/src/platform/wasm/ice_server.rs diff --git a/jason/src/media/device_info.rs b/jason/src/platform/wasm/input_device_info.rs similarity index 80% rename from jason/src/media/device_info.rs rename to jason/src/platform/wasm/input_device_info.rs index 32a64d694..700ece3e8 100644 --- a/jason/src/media/device_info.rs +++ b/jason/src/platform/wasm/input_device_info.rs @@ -5,10 +5,8 @@ use std::convert::TryFrom; use derive_more::Display; -use wasm_bindgen::prelude::*; -use web_sys::{MediaDeviceInfo, MediaDeviceKind}; -use crate::media::MediaKind; +use crate::{core::media::MediaKind, platform}; /// Errors that may occur when parsing [MediaDeviceInfo][1]. /// @@ -23,29 +21,27 @@ pub enum Error { /// Representation of [MediaDeviceInfo][1]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#device-info -#[wasm_bindgen] pub struct InputDeviceInfo { media_kind: MediaKind, /// Actual underlying [MediaDeviceInfo][1] object. /// /// [1]: https://w3.org/TR/mediacapture-streams/#device-info - info: MediaDeviceInfo, + info: platform::MediaDeviceInfo, } -impl TryFrom for MediaKind { +impl TryFrom for MediaKind { type Error = Error; - fn try_from(value: MediaDeviceKind) -> Result { + fn try_from(value: platform::MediaDeviceKind) -> Result { match value { - MediaDeviceKind::Audioinput => Ok(Self::Audio), - MediaDeviceKind::Videoinput => Ok(Self::Video), + platform::MediaDeviceKind::Audioinput => Ok(Self::Audio), + platform::MediaDeviceKind::Videoinput => Ok(Self::Video), _ => Err(Error::NotInputDevice), } } } -#[wasm_bindgen] impl InputDeviceInfo { /// Returns unique identifier for the represented device. pub fn device_id(&self) -> String { @@ -81,10 +77,10 @@ impl InputDeviceInfo { } } -impl TryFrom for InputDeviceInfo { +impl TryFrom for InputDeviceInfo { type Error = Error; - fn try_from(info: MediaDeviceInfo) -> Result { + fn try_from(info: platform::MediaDeviceInfo) -> Result { Ok(Self { media_kind: MediaKind::try_from(info.kind())?, info, diff --git a/jason/src/platform/wasm/media_track.rs b/jason/src/platform/wasm/media_track.rs new file mode 100644 index 000000000..68d8524f5 --- /dev/null +++ b/jason/src/platform/wasm/media_track.rs @@ -0,0 +1,112 @@ +use derive_more::AsRef; + +use crate::{api::FacingMode, core, platform::get_property_by_name}; + +#[derive(AsRef, Clone, Debug)] +pub struct MediaStreamTrack { + #[as_ref] + sys_track: web_sys::MediaStreamTrack, + kind: core::MediaKind, +} + +impl From for MediaStreamTrack +where + web_sys::MediaStreamTrack: From, +{ + #[inline] + fn from(from: T) -> MediaStreamTrack { + let sys_track = web_sys::MediaStreamTrack::from(from); + let kind = match sys_track.kind().as_ref() { + "audio" => core::MediaKind::Audio, + "video" => core::MediaKind::Video, + _ => unreachable!(), + }; + + MediaStreamTrack { sys_track, kind } + } +} + +impl MediaStreamTrack { + pub fn id(&self) -> String { + self.sys_track.id() + } + + pub fn kind(&self) -> core::MediaKind { + self.kind + } + + pub fn ready_state(&self) -> web_sys::MediaStreamTrackState { + self.sys_track.ready_state() + } + + pub fn device_id(&self) -> Option { + get_property_by_name(&self.sys_track.get_settings(), "device_id", |v| { + v.as_string() + }) + } + + pub fn facing_mode(&self) -> Option { + let facing_mode = get_property_by_name( + &self.sys_track.get_settings(), + "facingMode", + |v| v.as_string(), + ); + facing_mode.and_then(|facing_mode| match facing_mode.as_ref() { + "user" => Some(FacingMode::User), + "environment" => Some(FacingMode::Environment), + "left" => Some(FacingMode::Left), + "right" => Some(FacingMode::Right), + _ => { + // TODO: log err + None + } + }) + } + + pub fn height(&self) -> Option { + get_property_by_name(&self.sys_track.get_settings(), "height", |v| { + v.as_f64().map(|v| v as u32) + }) + } + + pub fn width(&self) -> Option { + get_property_by_name(&self.sys_track.get_settings(), "width", |v| { + v.as_f64().map(|v| v as u32) + }) + } + + pub fn set_enabled(&self, enabled: bool) { + self.sys_track.set_enabled(enabled); + } + + pub fn stop(&self) { + self.sys_track.stop() + } + + pub fn enabled(&self) -> bool { + self.sys_track.enabled() + } + + /// Detects if video track captured from display searching [specific + /// fields][1] in its settings. Only works in Chrome atm. + /// + /// [1]: https://w3.org/TR/screen-capture/#extensions-to-mediatracksettings + pub fn guess_is_from_display(&self) -> bool { + let settings = self.sys_track.get_settings(); + + let has_display_surface = + get_property_by_name(&settings, "displaySurface", |val| { + val.as_string() + }) + .is_some(); + + if has_display_surface { + true + } else { + get_property_by_name(&settings, "logicalSurface", |val| { + val.as_string() + }) + .is_some() + } + } +} diff --git a/jason/src/platform/wasm/mod.rs b/jason/src/platform/wasm/mod.rs new file mode 100644 index 000000000..ffbd29dda --- /dev/null +++ b/jason/src/platform/wasm/mod.rs @@ -0,0 +1,249 @@ +use std::{ + borrow::Cow, + convert::{TryFrom as _, TryInto as _}, + time::Duration, +}; + +pub mod ice_server; +pub mod input_device_info; +pub mod media_track; +pub mod peer_connection; +pub mod rtc_stats; +pub mod transceiver; +pub mod transport; +pub mod utils; + +use derive_more::Display; +use futures::Future; +use js_sys::{Promise, Reflect}; +use tracerr::Traced; +use wasm_bindgen::{JsCast, JsValue}; +use wasm_bindgen_futures::JsFuture; +use web_sys::Window; + +use input_device_info::InputDeviceInfo; + +use crate::{ + core::media::MediaManagerError, + platform::{ + DisplayMediaStreamConstraints, MediaStreamConstraints, MediaStreamTrack, + }, +}; + +// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global +// allocator. +#[cfg(feature = "wee_alloc")] +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + +// When the `console_error_panic_hook` feature is enabled, we can call the +// `set_panic_hook` function at least once during initialization, and then +// we will get better error messages if our code ever panics. +// +// For more details see: +// https://github.com/rustwasm/console_error_panic_hook#readme +#[cfg(feature = "console_error_panic_hook")] +pub use console_error_panic_hook::set_once as set_panic_hook; + +pub fn init_logger() { + wasm_logger::init(wasm_logger::Config::default()); +} + +#[inline] +pub fn spawn(task: F) +where + F: Future + 'static, +{ + wasm_bindgen_futures::spawn_local(task); +} + +/// [`Future`] which resolves after the provided [`JsDuration`]. +/// +/// [`Future`]: std::future::Future +pub async fn delay_for(delay: Duration) { + let delay_ms = delay.as_millis().try_into().unwrap_or(i32::max_value()); + JsFuture::from(Promise::new(&mut |yes, _| { + window() + .set_timeout_with_callback_and_timeout_and_arguments_0( + &yes, delay_ms, + ) + .unwrap(); + })) + .await + .unwrap(); +} + +pub async fn enumerate_devices( +) -> Result, Traced> { + use MediaManagerError::{CouldNotGetMediaDevices, EnumerateDevicesFailed}; + + let devices = window() + .navigator() + .media_devices() + .map_err(Error::from) + .map_err(CouldNotGetMediaDevices) + .map_err(tracerr::from_and_wrap!())?; + let devices = JsFuture::from( + devices + .enumerate_devices() + .map_err(Error::from) + .map_err(EnumerateDevicesFailed) + .map_err(tracerr::from_and_wrap!())?, + ) + .await + .map_err(Error::from) + .map_err(EnumerateDevicesFailed) + .map_err(tracerr::from_and_wrap!())?; + + Ok(js_sys::Array::from(&devices) + .values() + .into_iter() + .filter_map(|info| { + let info = web_sys::MediaDeviceInfo::from(info.unwrap()); + InputDeviceInfo::try_from(info).ok() + }) + .collect()) +} + +pub async fn get_user_media( + caps: MediaStreamConstraints, +) -> Result, Traced> { + use MediaManagerError::{CouldNotGetMediaDevices, GetUserMediaFailed}; + + let media_devices = window() + .navigator() + .media_devices() + .map_err(Error::from) + .map_err(CouldNotGetMediaDevices) + .map_err(tracerr::from_and_wrap!())?; + + let stream = JsFuture::from( + media_devices + .get_user_media_with_constraints(&caps) + .map_err(Error::from) + .map_err(GetUserMediaFailed) + .map_err(tracerr::from_and_wrap!())?, + ) + .await + .map(web_sys::MediaStream::from) + .map_err(Error::from) + .map_err(GetUserMediaFailed) + .map_err(tracerr::from_and_wrap!())?; + + Ok(js_sys::try_iter(&stream.get_tracks()) + .unwrap() + .unwrap() + .map(|tr| MediaStreamTrack::from(tr.unwrap())) + .collect()) +} + +pub async fn get_display_media( + caps: DisplayMediaStreamConstraints, +) -> Result, Traced> { + use MediaManagerError::{ + CouldNotGetMediaDevices, GetDisplayMediaFailed, GetUserMediaFailed, + }; + + let media_devices = window() + .navigator() + .media_devices() + .map_err(Error::from) + .map_err(CouldNotGetMediaDevices) + .map_err(tracerr::from_and_wrap!())?; + + let stream = JsFuture::from( + media_devices + .get_display_media_with_constraints(&caps) + .map_err(Error::from) + .map_err(GetDisplayMediaFailed) + .map_err(tracerr::from_and_wrap!())?, + ) + .await + .map(web_sys::MediaStream::from) + .map_err(Error::from) + .map_err(GetUserMediaFailed) + .map_err(tracerr::from_and_wrap!())?; + + Ok(js_sys::try_iter(&stream.get_tracks()) + .unwrap() + .unwrap() + .map(|tr| MediaStreamTrack::from(tr.unwrap())) + .collect()) +} + +/// Wrapper for JS value which returned from JS side as error. +#[derive(Clone, Debug, Display, PartialEq)] +#[display(fmt = "{}: {}", name, message)] +pub struct Error { + /// Name of JS error. + pub name: Cow<'static, str>, + + /// Message of JS error. + pub message: Cow<'static, str>, +} + +impl From for Error { + fn from(val: JsValue) -> Self { + match val.dyn_into::() { + Ok(err) => Self { + name: Cow::Owned(err.name().into()), + message: Cow::Owned(err.message().into()), + }, + Err(val) => match val.as_string() { + Some(reason) => Self { + name: "Unknown JS error".into(), + message: reason.into(), + }, + None => Self { + name: "Unknown JS error".into(), + message: format!("{:?}", val).into(), + }, + }, + } + } +} + +impl From for js_sys::Error { + fn from(err: Error) -> Self { + let error = Self::new(&err.message); + error.set_name(&err.name); + error + } +} + +/// Returns property of JS object by name if its defined. +/// Converts the value with a given predicate. +pub fn get_property_by_name( + value: &T, + name: &str, + into: F, +) -> Option +where + T: AsRef, + F: Fn(wasm_bindgen::JsValue) -> Option, +{ + Reflect::get(value.as_ref(), &JsValue::from_str(name)) + .ok() + .map_or_else(|| None, into) +} + +/// Returns [`Window`] object. +/// +/// # Panics +/// +/// When global [`Window`] object is inaccessible. +pub fn window() -> Window { + // Cannot use `lazy_static` since `window` is `!Sync`. + // Safe to unwrap. + web_sys::window().unwrap() +} + +/// Wrapper around interval timer ID. +pub struct IntervalHandle(pub i32); + +impl Drop for IntervalHandle { + /// Clears interval with provided ID. + fn drop(&mut self) { + window().clear_interval_with_handle(self.0); + } +} diff --git a/jason/src/peer/conn.rs b/jason/src/platform/wasm/peer_connection.rs similarity index 93% rename from jason/src/peer/conn.rs rename to jason/src/platform/wasm/peer_connection.rs index fe627a465..e705c9ca3 100644 --- a/jason/src/peer/conn.rs +++ b/jason/src/platform/wasm/peer_connection.rs @@ -5,7 +5,9 @@ use std::{ }; use derive_more::{Display, From}; -use medea_client_api_proto::{IceServer, PeerConnectionState}; +use medea_client_api_proto::{ + IceConnectionState, IceServer, PeerConnectionState, +}; use tracerr::Traced; use wasm_bindgen_futures::JsFuture; use web_sys::{ @@ -17,15 +19,15 @@ use web_sys::{ }; use crate::{ - media::{MediaKind, TrackConstraints}, - peer::stats::{RtcStats, RtcStatsError}, - utils::{ - get_property_by_name, EventListener, EventListenerBindError, JsCaused, - JsError, + core::{ + media::{MediaKind, TrackConstraints}, + utils::JsCaused, }, + platform::{self, *}, }; -use super::{ice_server::RtcIceServers, TransceiverDirection}; +use super::ice_server::RtcIceServers; +use crate::platform::wasm::utils::{EventListener, EventListenerBindError}; /// [RTCIceCandidate][1] representation. /// @@ -79,6 +81,7 @@ pub enum SdpType { /// /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection #[derive(Clone, Debug, Display, From, JsCaused)] +#[js(error = "platform::Error")] pub enum RTCPeerConnectionError { /// Occurs when cannot adds new remote candidate to the /// [RTCPeerConnection][1]'s remote description. @@ -86,24 +89,24 @@ pub enum RTCPeerConnectionError { /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection #[display(fmt = "Failed to add ICE candidate: {}", _0)] #[from(ignore)] - AddIceCandidateFailed(JsError), + AddIceCandidateFailed(platform::Error), /// Occurs when cannot obtains [SDP answer][`SdpType::Answer`] from /// the underlying [RTCPeerConnection][`SysRtcPeerConnection`]. #[display(fmt = "Failed to create SDP answer: {}", _0)] #[from(ignore)] - CreateAnswerFailed(JsError), + CreateAnswerFailed(platform::Error), /// Occurs when a new [`RtcPeerConnection`] cannot be created. #[display(fmt = "Failed to create PeerConnection: {}", _0)] #[from(ignore)] - PeerCreationError(JsError), + PeerCreationError(platform::Error), /// Occurs when cannot obtains [SDP offer][`SdpType::Offer`] from /// the underlying [RTCPeerConnection][`SysRtcPeerConnection`] #[display(fmt = "Failed to create SDP offer: {}", _0)] #[from(ignore)] - CreateOfferFailed(JsError), + CreateOfferFailed(platform::Error), /// Occurs when handler failed to bind to some [`RtcPeerConnection`] event. /// Not really supposed to ever happen. @@ -121,19 +124,19 @@ pub enum RTCPeerConnectionError { /// [1]: https://tinyurl.com/w6hmt5f #[display(fmt = "PeerConnection.getStats() failed with error: {}", _0)] #[from(ignore)] - GetStatsException(JsError), + GetStatsException(platform::Error), /// Occurs if the local description associated with the /// [`RtcPeerConnection`] cannot be changed. #[display(fmt = "Failed to set local SDP description: {}", _0)] #[from(ignore)] - SetLocalDescriptionFailed(JsError), + SetLocalDescriptionFailed(platform::Error), /// Occurs if the description of the remote end of the /// [`RtcPeerConnection`] cannot be changed. #[display(fmt = "Failed to set remote SDP description: {}", _0)] #[from(ignore)] - SetRemoteDescriptionFailed(JsError), + SetRemoteDescriptionFailed(platform::Error), } type Result = std::result::Result>; @@ -249,7 +252,7 @@ impl RtcPeerConnection { let js_stats = JsFuture::from(self.peer.get_stats()).await.map_err(|e| { tracerr::new!(RTCPeerConnectionError::GetStatsException( - JsError::from(e) + platform::Error::from(e) )) })?; @@ -268,7 +271,7 @@ impl RtcPeerConnection { /// [2]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection-ontrack pub fn on_track(&self, f: Option) -> Result<()> where - F: 'static + FnMut(RtcTrackEvent), + F: 'static + FnMut(MediaStreamTrack, Transceiver), { let mut on_track = self.on_track.borrow_mut(); match f { @@ -281,7 +284,10 @@ impl RtcPeerConnection { Rc::clone(&self.peer), "track", move |msg: RtcTrackEvent| { - f(msg); + f( + MediaStreamTrack::from(msg.track()), + Transceiver::from(msg.transceiver()), + ); }, ) .map_err(tracerr::map_from_and_wrap!())?, @@ -339,8 +345,8 @@ impl RtcPeerConnection { /// Returns [`RtcIceConnectionState`] of this [`RtcPeerConnection`]. #[inline] #[must_use] - pub fn ice_connection_state(&self) -> RtcIceConnectionState { - self.peer.ice_connection_state() + pub fn ice_connection_state(&self) -> IceConnectionState { + parse_ice_connection_state(self.peer.ice_connection_state()) } /// Returns [`PeerConnectionState`] of this [`RtcPeerConnection`]. @@ -362,7 +368,7 @@ impl RtcPeerConnection { /// [1]: https://w3.org/TR/webrtc/#event-iceconnectionstatechange pub fn on_ice_connection_state_change(&self, f: Option) -> Result<()> where - F: 'static + FnMut(RtcIceConnectionState), + F: 'static + FnMut(IceConnectionState), { let mut on_ice_connection_state_changed = self.on_ice_connection_state_changed.borrow_mut(); @@ -377,7 +383,9 @@ impl RtcPeerConnection { Rc::clone(&self.peer), "iceconnectionstatechange", move |_| { - f(peer.ice_connection_state()); + f(parse_ice_connection_state( + peer.ice_connection_state(), + )); }, ) .map_err(tracerr::map_from_and_wrap!())?, @@ -736,3 +744,22 @@ fn get_peer_connection_state( } })) } + +fn parse_ice_connection_state( + state: RtcIceConnectionState, +) -> IceConnectionState { + use RtcIceConnectionState as S; + + match state { + S::New => IceConnectionState::New, + S::Checking => IceConnectionState::Checking, + S::Connected => IceConnectionState::Connected, + S::Completed => IceConnectionState::Completed, + S::Failed => IceConnectionState::Failed, + S::Disconnected => IceConnectionState::Disconnected, + S::Closed => IceConnectionState::Closed, + S::__Nonexhaustive => { + unreachable!("Unknown ICE connection state {:?}", state); + } + } +} diff --git a/jason/src/peer/stats.rs b/jason/src/platform/wasm/rtc_stats.rs similarity index 88% rename from jason/src/peer/stats.rs rename to jason/src/platform/wasm/rtc_stats.rs index 6a6f0e97f..3d2857eb9 100644 --- a/jason/src/peer/stats.rs +++ b/jason/src/platform/wasm/rtc_stats.rs @@ -12,7 +12,10 @@ use medea_client_api_proto::stats::{RtcStat, RtcStatsType}; use tracerr::Traced; use wasm_bindgen::{prelude::*, JsCast}; -use crate::utils::{get_property_by_name, JsCaused, JsError}; +use crate::{ + core::utils::JsCaused, + platform::{self, *}, +}; /// Entry of the JS RTC stats dictionary. struct RtcStatsReportEntry(JsString, JsValue); @@ -36,10 +39,10 @@ impl TryFrom for RtcStatsReportEntry { let id = id .dyn_into::() - .map_err(|e| tracerr::new!(Js(JsError::from(e))))?; + .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; let stats = stats .dyn_into::() - .map_err(|e| tracerr::new!(Js(JsError::from(e))))?; + .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; Ok(RtcStatsReportEntry(id, stats)) } @@ -65,13 +68,14 @@ impl TryFrom<&JsValue> for RtcStats { let iterator = entries_fn .call0(stats.as_ref()) - .map_err(|e| tracerr::new!(Js(JsError::from(e))))? + .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))? .unchecked_into::(); let mut stats = Vec::new(); for stat in iterator { - let stat = stat.map_err(|e| tracerr::new!(Js(JsError::from(e))))?; + let stat = + stat.map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; let stat = stat.unchecked_into::(); let stat = RtcStatsReportEntry::try_from(stat) .map_err(tracerr::map_from_and_wrap!())?; @@ -93,6 +97,7 @@ impl TryFrom<&JsValue> for RtcStats { /// Errors which can occur during deserialization of the [`RtcStatsType`]. #[derive(Clone, Debug, Display, From, JsCaused)] +#[js(error = "platform::Error")] pub enum RtcStatsError { /// [RTCStats.id][1] is undefined. /// @@ -108,7 +113,7 @@ pub enum RtcStatsError { /// Some JS error occurred. #[display(fmt = "Unexpected JS side error: {}", _0)] - Js(JsError), + Js(platform::Error), /// `RTCStats.entries` is undefined. #[display(fmt = "RTCStats.entries is undefined")] diff --git a/jason/src/peer/transceiver.rs b/jason/src/platform/wasm/transceiver.rs similarity index 91% rename from jason/src/peer/transceiver.rs rename to jason/src/platform/wasm/transceiver.rs index a97da4e7c..146796a85 100644 --- a/jason/src/peer/transceiver.rs +++ b/jason/src/platform/wasm/transceiver.rs @@ -8,7 +8,7 @@ use wasm_bindgen::JsValue; use wasm_bindgen_futures::JsFuture; use web_sys::{RtcRtpTransceiver, RtcRtpTransceiverDirection}; -use crate::media::track::local; +use crate::{core::media::track::local, platform::MediaStreamTrack}; /// Wrapper around [`RtcRtpTransceiver`] which provides handy methods for /// direction changes. @@ -59,12 +59,17 @@ impl Transceiver { if new_track.is_none() { self.send_track.replace(None); } - let sys_track = new_track.as_ref().map(|t| t.sys_track()); - JsFuture::from(self.transceiver.sender().replace_track(sys_track)) - .await - .map(|_| { - self.send_track.replace(new_track); - }) + let sys_track: Option<&MediaStreamTrack> = + new_track.as_ref().map(|t| (**t).as_ref()); + JsFuture::from( + self.transceiver + .sender() + .replace_track(sys_track.map(AsRef::as_ref)), + ) + .await + .map(|_| { + self.send_track.replace(new_track); + }) } /// Returns [`mid`] of this [`Transceiver`]. @@ -206,11 +211,11 @@ mod tests { } #[test] - fn from_trnsvr_direction_to_sys() { + fn from_trnscvr_direction_to_sys() { use RtcRtpTransceiverDirection as S; use TransceiverDirection as D; - for (trnsv_dir, sys_dir) in &[ + for (trnscvr_dir, sys_dir) in &[ (D::SEND, S::Sendonly), (D::RECV, S::Recvonly), (D::all(), S::Sendrecv), @@ -221,11 +226,11 @@ mod tests { } #[test] - fn from_sys_direction_to_trnsvr() { + fn from_sys_direction_to_trnscvr() { use RtcRtpTransceiverDirection as S; use TransceiverDirection as D; - for (sys_dir, trnsv_dir) in &[ + for (sys_dir, trnscvr_dir) in &[ (S::Sendonly, D::SEND), (S::Recvonly, D::RECV), (S::Sendrecv, D::all()), diff --git a/jason/src/rpc/websocket/transport.rs b/jason/src/platform/wasm/transport.rs similarity index 70% rename from jason/src/rpc/websocket/transport.rs rename to jason/src/platform/wasm/transport.rs index 8723c0448..1b9ee0f22 100644 --- a/jason/src/rpc/websocket/transport.rs +++ b/jason/src/platform/wasm/transport.rs @@ -4,84 +4,24 @@ use std::{cell::RefCell, convert::TryFrom, rc::Rc}; -use derive_more::{Display, From, Into}; +use derive_more::{From, Into}; use futures::{channel::mpsc, stream::LocalBoxStream, StreamExt}; -use medea_client_api_proto::{ClientMsg, ServerMsg}; +use medea_client_api_proto::{ClientMsg, CloseDescription, ServerMsg}; use medea_reactive::ObservableCell; use tracerr::Traced; use web_sys::{CloseEvent, Event, MessageEvent, WebSocket as SysWebSocket}; use crate::{ - rpc::{websocket::client::ClientDisconnect, ApiUrl, CloseMsg}, - utils::{ - EventListener, EventListenerBindError, JasonError, JsCaused, JsError, - JsonParseError, + core::{ + rpc::{websocket::ClientDisconnect, ApiUrl, CloseMsg}, + utils::JasonError, + }, + platform::{ + transport::{RpcTransport, TransportError, TransportState}, + wasm::utils::{EventListener, EventListenerBindError}, }, }; -/// RPC transport between a client and a server. -#[cfg_attr(feature = "mockable", mockall::automock)] -pub trait RpcTransport { - /// Returns [`LocalBoxStream`] of all messages received by this transport. - fn on_message(&self) -> LocalBoxStream<'static, ServerMsg>; - - /// Sets reason, that will be sent to remote server when this transport will - /// be dropped. - fn set_close_reason(&self, reason: ClientDisconnect); - - /// Sends given [`ClientMsg`] to a server. - /// - /// # Errors - /// - /// Errors if sending [`ClientMsg`] fails. - fn send(&self, msg: &ClientMsg) -> Result<(), Traced>; - - /// Subscribes to a [`RpcTransport`]'s [`TransportState`] changes. - fn on_state_change(&self) -> LocalBoxStream<'static, TransportState>; -} - -/// Errors that may occur when working with [`WebSocketRpcClient`]. -/// -/// [`WebSocketRpcClient`]: super::WebSocketRpcClient -#[derive(Clone, Debug, Display, JsCaused, PartialEq)] -pub enum TransportError { - /// Occurs when the port to which the connection is being attempted - /// is being blocked. - #[display(fmt = "Failed to create WebSocket: {}", _0)] - CreateSocket(JsError), - - /// Occurs when the connection close before becomes state active. - #[display(fmt = "Failed to init WebSocket")] - InitSocket, - - /// Occurs when [`ClientMsg`] cannot be parsed. - #[display(fmt = "Failed to parse client message: {}", _0)] - ParseClientMessage(JsonParseError), - - /// Occurs when [`ServerMsg`] cannot be parsed. - #[display(fmt = "Failed to parse server message: {}", _0)] - ParseServerMessage(JsonParseError), - - /// Occurs if the parsed message is not string. - #[display(fmt = "Message is not a string")] - MessageNotString, - - /// Occurs when a message cannot be send to server. - #[display(fmt = "Failed to send message: {}", _0)] - SendMessage(JsError), - - /// Occurs when handler failed to bind to some [WebSocket] event. Not - /// really supposed to ever happen. - /// - /// [WebSocket]: https://developer.mozilla.org/ru/docs/WebSockets - #[display(fmt = "Failed to bind to WebSocket event: {}", _0)] - WebSocketEventBindError(EventListenerBindError), - - /// Occurs when message is sent to a closed socket. - #[display(fmt = "Underlying socket is closed")] - ClosedSocket, -} - impl From for TransportError { fn from(err: EventListenerBindError) -> Self { Self::WebSocketEventBindError(err) @@ -108,48 +48,6 @@ impl TryFrom<&MessageEvent> for ServerMessage { } } -/// [`RpcTransport`] states. -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum TransportState { - /// Socket has been created. The connection is not open yet. - /// - /// Reflects `CONNECTING` state from JS side [`WebSocket.readyState`][1]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState - Connecting, - - /// The connection is open and ready to communicate. - /// - /// Reflects `OPEN` state from JS side [`WebSocket.readyState`][1]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState - Open, - - /// The connection is in the process of closing. - /// - /// Reflects `CLOSING` state from JS side [`WebSocket.readyState`][1]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState - Closing, - - /// The connection is closed or couldn't be opened. - /// - /// Reflects `CLOSED` state from JS side [`WebSocket.readyState`][1]. - /// - /// [`CloseMsg`] is the reason of why [`RpcTransport`] went into - /// this [`TransportState`]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState - Closed(CloseMsg), -} - -impl TransportState { - /// Returns `true` if socket can be closed. - pub fn can_close(self) -> bool { - matches!(self, Self::Connecting | Self::Open) - } -} - type Result> = std::result::Result; struct InnerSocket { @@ -243,9 +141,9 @@ impl WebSocketRpcTransport { /// fired before [WebSocket.onopen][2] callback. /// /// [1]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onclose - /// [2]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onopen + /// [2]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onopens pub async fn new(url: ApiUrl) -> Result { - let socket = Rc::new(RefCell::new(InnerSocket::new(url.0.as_str())?)); + let socket = Rc::new(RefCell::new(InnerSocket::new(url.as_ref())?)); { let mut socket_mut = socket.borrow_mut(); let inner = Rc::clone(&socket); @@ -387,3 +285,21 @@ impl Drop for WebSocketRpcTransport { inner.on_close_listener.take(); } } + +impl From<&CloseEvent> for CloseMsg { + fn from(event: &CloseEvent) -> Self { + let code: u16 = event.code(); + match code { + 1000 => { + if let Ok(description) = + serde_json::from_str::(&event.reason()) + { + Self::Normal(code, description.reason) + } else { + Self::Abnormal(code) + } + } + _ => Self::Abnormal(code), + } + } +} diff --git a/jason/src/utils/event_listener.rs b/jason/src/platform/wasm/utils/event_listener.rs similarity index 88% rename from jason/src/utils/event_listener.rs rename to jason/src/platform/wasm/utils/event_listener.rs index bcca5ff24..89e37a4a9 100644 --- a/jason/src/utils/event_listener.rs +++ b/jason/src/platform/wasm/utils/event_listener.rs @@ -3,20 +3,20 @@ use std::{ops::Deref, rc::Rc}; use derive_more::{Display, From}; use tracerr::Traced; use wasm_bindgen::{closure::Closure, convert::FromWasmAbi, JsCast}; -use web_sys::EventTarget; -use super::{errors::JsCaused, JsError}; +use crate::{core::utils::JsCaused, platform}; /// Failed to bind to [`EventTarget`][1] event. /// /// [1]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget #[derive(Clone, Debug, Display, From, JsCaused, PartialEq)] -pub struct EventListenerBindError(JsError); +#[js(error = "platform::Error")] +pub struct EventListenerBindError(platform::Error); /// Wrapper for closure that handles some [`EventTarget`] event. pub struct EventListener where - T: Deref, + T: Deref, { event_name: &'static str, target: Rc, @@ -25,7 +25,7 @@ where impl EventListener where - T: Deref, + T: Deref, A: FromWasmAbi + 'static, { /// Creates new [`EventListener`] from a given [`FnMut`] `closure`. @@ -48,7 +48,7 @@ where event_name, closure.as_ref().unchecked_ref(), ) - .map_err(JsError::from) + .map_err(platform::Error::from) .map_err(EventListenerBindError::from) .map_err(tracerr::wrap!())?; @@ -79,7 +79,7 @@ where event_name, closure.as_ref().unchecked_ref(), ) - .map_err(JsError::from) + .map_err(platform::Error::from) .map_err(EventListenerBindError::from) .map_err(tracerr::wrap!())?; @@ -93,7 +93,7 @@ where impl Drop for EventListener where - T: Deref, + T: Deref, { /// Drops [`EventListener`]'s closure and unregisters appropriate event /// handler. diff --git a/jason/src/platform/wasm/utils/mod.rs b/jason/src/platform/wasm/utils/mod.rs new file mode 100644 index 000000000..7a83975d2 --- /dev/null +++ b/jason/src/platform/wasm/utils/mod.rs @@ -0,0 +1,3 @@ +mod event_listener; + +pub use event_listener::{EventListener, EventListenerBindError}; diff --git a/jason/src/rpc/websocket/mod.rs b/jason/src/rpc/websocket/mod.rs deleted file mode 100644 index 51ce61c49..000000000 --- a/jason/src/rpc/websocket/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Implementation of the abstractions around [WebSocket] transport. -//! -//! [WebSocket]: https://developer.mozilla.org/ru/docs/WebSockets - -mod client; -mod transport; - -#[cfg(feature = "mockable")] -pub use self::transport::MockRpcTransport; -#[doc(inline)] -pub use self::{ - client::{ - ClientDisconnect, ClientState, RpcEvent, RpcEventHandler, - RpcTransportFactory, WebSocketRpcClient, - }, - transport::{ - RpcTransport, TransportError, TransportState, WebSocketRpcTransport, - }, -}; diff --git a/jason/src/utils/callback.rs b/jason/src/utils/callback.rs deleted file mode 100644 index d1ccd0e4e..000000000 --- a/jason/src/utils/callback.rs +++ /dev/null @@ -1,155 +0,0 @@ -//! Somewhat convenient wrappers around JS functions used as callbacks. - -use std::{cell::RefCell, marker::PhantomData}; - -use js_sys::Function as JsFunction; -use wasm_bindgen::JsValue; - -/// Wrapper for JS function with no arguments. -#[derive(Default)] -pub struct Callback0 { - f: RefCell>, -} - -impl Callback0 { - /// Sets inner JS function. - #[inline] - pub fn set_func(&self, f: JsFunction) { - self.f.borrow_mut().replace(f); - } - - /// Invokes JS function if any. - /// - /// Returns `None` if no callback is set, otherwise returns its invocation - /// result. - pub fn call(&self) -> Option> { - self.f.borrow().as_ref().map(|f| f.call0(&JsValue::NULL)) - } - - /// Indicates whether callback is set. - #[inline] - pub fn is_set(&self) -> bool { - self.f.borrow().as_ref().is_some() - } -} - -/// Wrapper for a single argument JS function. -pub struct Callback1 { - f: RefCell>, - _arg: PhantomData, -} - -impl Default for Callback1 { - #[inline] - fn default() -> Self { - Self { - f: RefCell::new(None), - _arg: PhantomData, - } - } -} - -impl> Callback1 { - /// Sets inner JS function. - #[inline] - pub fn set_func(&self, f: JsFunction) { - self.f.borrow_mut().replace(f); - } - - /// Invokes JS function if any. - /// - /// Returns `None` if no callback is set, otherwise returns its invocation - /// result. - pub fn call(&self, arg: A) -> Option> { - self.f - .borrow() - .as_ref() - .map(|f| f.call1(&JsValue::NULL, &arg.into())) - } - - /// Indicates if callback is set. - #[inline] - pub fn is_set(&self) -> bool { - self.f.borrow().as_ref().is_some() - } -} - -impl From for Callback1 { - #[inline] - fn from(f: JsFunction) -> Self { - Self { - f: RefCell::new(Some(f)), - _arg: PhantomData, - } - } -} - -/// Wrapper for a JS functions with two arguments. -/// -/// Can be used if you need to conditionally invoke function passing one of two -/// args, e.g. first arg in case of success, and second as error. -pub struct Callback2 { - f: RefCell>, - _arg1: PhantomData, - _arg2: PhantomData, -} - -impl Default for Callback2 { - #[inline] - fn default() -> Self { - Self { - f: RefCell::new(None), - _arg1: PhantomData, - _arg2: PhantomData, - } - } -} - -impl, A2: Into> Callback2 { - /// Sets inner JS function. - #[inline] - pub fn set_func(&self, f: JsFunction) { - self.f.borrow_mut().replace(f); - } - - /// Invokes JS function passing both arguments. - /// - /// Returns `None` if no callback is set, otherwise returns its invocation - /// result. - pub fn call( - &self, - arg1: Option, - arg2: Option, - ) -> Option> { - self.f.borrow().as_ref().map(|f| { - f.call2( - &JsValue::NULL, - &arg1.map_or(JsValue::NULL, Into::into), - &arg2.map_or(JsValue::NULL, Into::into), - ) - }) - } - - /// Invokes JS function passing only first argument. - #[inline] - pub fn call1(&self, arg1: A1) -> Option> { - self.call(Some(arg1), None) - } - - /// Invokes JS function passing only second argument. - #[inline] - pub fn call2(&self, arg2: A2) -> Option> { - self.call(None, Some(arg2)) - } -} - -impl From for Callback2 { - #[inline] - fn from(f: JsFunction) -> Self { - Self { - f: RefCell::new(Some(f)), - _arg1: PhantomData, - _arg2: PhantomData, - } - } -} diff --git a/jason/src/utils/mod.rs b/jason/src/utils/mod.rs deleted file mode 100644 index 5186e5092..000000000 --- a/jason/src/utils/mod.rs +++ /dev/null @@ -1,199 +0,0 @@ -//! Miscellaneous utility structs and functions. - -#[macro_use] -mod errors; - -mod callback; -pub mod component; -mod event_listener; -mod resettable_delay; - -use std::{convert::TryInto as _, future::Future, ops::Mul, time::Duration}; - -use derive_more::{From, Sub}; -use futures::future::{self, AbortHandle}; -use js_sys::{Promise, Reflect}; -use medea_reactive::Guarded; -use wasm_bindgen::prelude::*; -use wasm_bindgen_futures::JsFuture; -use web_sys::Window; - -#[cfg(debug_assertions)] -pub use self::errors::console_error; -#[doc(inline)] -pub use self::{ - callback::{Callback0, Callback1, Callback2}, - component::{AsProtoState, Component, SynchronizableState, Updatable}, - errors::{ - HandlerDetachedError, JasonError, JsCaused, JsError, JsonParseError, - }, - event_listener::{EventListener, EventListenerBindError}, - resettable_delay::{resettable_delay_for, ResettableDelayHandle}, -}; - -/// Returns [`Window`] object. -/// -/// # Panics -/// -/// When global [`Window`] object is inaccessible. -pub fn window() -> Window { - // Cannot use `lazy_static` since `window` is `!Sync`. - // Safe to unwrap. - web_sys::window().unwrap() -} - -/// Wrapper around [`Duration`] which can be transformed into [`i32`] for JS -/// side timers. -/// -/// Also [`JsDuration`] can be multiplied by [`f32`]. -#[derive(Clone, Copy, Debug, From, PartialEq, PartialOrd, Sub)] -pub struct JsDuration(Duration); - -impl JsDuration { - /// Converts this [`JsDuration`] into `i32` milliseconds. - /// - /// Unfortunately, [`web_sys`] believes that only `i32` can be passed to a - /// `setTimeout`. But it is unlikely we will need a duration of more, - /// than 596 hours, so it was decided to simply truncate the number. If we - /// will need a longer duration in the future, then we can implement this - /// with a few `setTimeout`s. - #[inline] - pub fn into_js_duration(self) -> i32 { - self.0.as_millis().try_into().unwrap_or(i32::max_value()) - } -} - -impl Mul for JsDuration { - type Output = Self; - - #[inline] - fn mul(self, rhs: u32) -> Self::Output { - Self(self.0 * rhs) - } -} - -impl Mul for JsDuration { - type Output = Self; - - #[inline] - fn mul(self, mut rhs: f32) -> Self::Output { - // Emulation of JS side's 'setTimeout' behavior which will be instantly - // resolved if call it with negative number. - if rhs < 0.0 { - rhs = 0.0; - }; - Self(self.0.mul_f64(rhs.into())) - } -} - -/// Wrapper around interval timer ID. -pub struct IntervalHandle(pub i32); - -impl Drop for IntervalHandle { - /// Clears interval with provided ID. - fn drop(&mut self) { - window().clear_interval_with_handle(self.0); - } -} - -/// Upgrades provided [`Weak`] reference, mapping it to a [`Result`] with -/// [`HandlerDetachedError`] and invokes [`Into::into`] on the error. -/// If the errot type cannot be inferred, then you can provide a concrete type -/// (usually being [`JasonError`] or [`JsValue`]). -/// -/// [`Weak`]: std::rc::Weak -macro_rules! upgrade_or_detached { - ($v:expr) => {{ - $v.upgrade() - .ok_or_else(|| new_js_error!(HandlerDetachedError)) - }}; - ($v:expr, $err:ty) => {{ - $v.upgrade() - .ok_or_else(|| new_js_error!(HandlerDetachedError => $err)) - }}; -} - -/// Adds [`tracerr`] information to the provided error, wraps it into -/// [`JasonError`] and converts it into the expected error type. -/// -/// This macro has two syntaxes: -/// - `new_js_error!(DetachedStateError)` - converts provided error wrapped into -/// [`JasonError`] with [`Into::into`] automatically; -/// - `new_js_error!(DetachedStateError => JsError)` - annotates explicitly -/// which type conversion is required. -macro_rules! new_js_error { - ($e:expr) => { - $crate::utils::JasonError::from(tracerr::new!($e)).into() - }; - ($e:expr => $o:ty) => { - <$o>::from($crate::utils::JasonError::from(tracerr::new!($e))) - }; -} - -/// Returns property of JS object by name if its defined. -/// Converts the value with a given predicate. -pub fn get_property_by_name( - value: &T, - name: &str, - into: F, -) -> Option -where - T: AsRef, - F: Fn(wasm_bindgen::JsValue) -> Option, -{ - Reflect::get(value.as_ref(), &JsValue::from_str(name)) - .ok() - .map_or_else(|| None, into) -} - -/// [`Future`] which resolves after the provided [`JsDuration`]. -/// -/// [`Future`]: std::future::Future -pub async fn delay_for(delay_ms: JsDuration) { - JsFuture::from(Promise::new(&mut |yes, _| { - window() - .set_timeout_with_callback_and_timeout_and_arguments_0( - &yes, - delay_ms.into_js_duration(), - ) - .unwrap(); - })) - .await - .unwrap(); -} - -/// Wrapper around [`AbortHandle`] which aborts [`Future`] on [`Drop`]. -/// -/// [`Future`]: std::future::Future -#[derive(Debug, From)] -pub struct TaskHandle(AbortHandle); - -impl Drop for TaskHandle { - fn drop(&mut self) { - self.0.abort(); - } -} - -/// Tries to upgrade [`Weak`] reference breaks cycle if upgrade fails. -macro_rules! upgrade_or_break { - ($weak:tt) => { - if let Some(this) = $weak.upgrade() { - this - } else { - break; - } - }; -} - -/// Returns [`Future`] which will return the provided value being -/// [`Guarded::transpose()`]d. -/// -/// Intended for use in [`StreamExt::filter_map()`]. -/// -/// [`StreamExt::filter_map()`]: futures::StreamExt::filter_map -#[inline] -pub fn transpose_guarded( - val: Guarded>, -) -> impl Future>> { - future::ready(val.transpose()) -} From fc9d3e3b02ce23170780cf2d5b07f5f2972d47f0 Mon Sep 17 00:00:00 2001 From: alexlapa Date: Thu, 25 Feb 2021 12:19:30 +0200 Subject: [PATCH 02/19] wip [skip ci] --- jason/Cargo.toml | 60 +-- jason/demo/index.html | 2 +- jason/e2e-demo/js/index.js | 2 +- jason/src/api/mod.rs | 5 + jason/src/api/wasm/connection_handle.rs | 22 +- .../api/wasm/constraints_update_exception.rs | 23 +- jason/src/api/wasm/jason_error.rs | 32 ++ jason/src/api/wasm/media_manager_handle.rs | 7 +- jason/src/api/wasm/media_stream_settings.rs | 18 +- jason/src/api/wasm/mod.rs | 6 +- jason/src/api/wasm/reconnect_handle.rs | 9 +- jason/src/api/wasm/remote_media_track.rs | 8 +- jason/src/api/wasm/room_handle.rs | 59 ++- jason/src/core/connection.rs | 39 +- jason/src/core/media/constraints.rs | 191 +++------ jason/src/core/media/manager.rs | 17 +- jason/src/core/media/mod.rs | 2 +- jason/src/core/media/track/mod.rs | 6 + jason/src/core/media/track/remote.rs | 25 +- jason/src/core/mod.rs | 22 +- jason/src/core/peer/component/local_sdp.rs | 4 +- jason/src/core/peer/media/mod.rs | 32 +- .../src/core/peer/media/receiver/component.rs | 10 +- jason/src/core/peer/media/receiver/mod.rs | 26 +- jason/src/core/peer/media/sender/component.rs | 8 +- jason/src/core/peer/media/sender/mod.rs | 15 +- .../media/transitable_state/controller.rs | 6 +- jason/src/core/peer/mod.rs | 12 +- jason/src/core/peer/repo.rs | 6 +- jason/src/core/room.rs | 107 ++--- jason/src/core/rpc/backoff_delayer.rs | 6 +- jason/src/core/rpc/heartbeat.rs | 21 +- jason/src/core/rpc/mod.rs | 11 +- jason/src/core/rpc/reconnect_handle.rs | 5 +- jason/src/core/rpc/rpc_session.rs | 10 +- jason/src/core/rpc/websocket/client.rs | 22 +- jason/src/core/rpc/websocket/mod.rs | 2 - jason/src/core/utils/callback.rs | 86 ---- jason/src/core/utils/component.rs | 4 +- jason/src/core/utils/errors.rs | 15 +- jason/src/core/utils/mod.rs | 2 - jason/src/core/utils/resettable_delay.rs | 6 +- jason/src/lib.rs | 6 +- jason/src/platform/mod.rs | 172 ++------ jason/src/platform/rtc_stats.rs | 34 ++ jason/src/platform/transport.rs | 123 ++++++ jason/src/platform/wasm/constraints.rs | 118 ++++++ jason/src/platform/wasm/input_device_info.rs | 23 +- jason/src/platform/wasm/media_track.rs | 29 +- jason/src/platform/wasm/mod.rs | 5 +- jason/src/platform/wasm/rtc_stats.rs | 92 ++--- jason/src/platform/wasm/transceiver.rs | 4 +- jason/src/platform/wasm/transport.rs | 2 +- jason/src/platform/wasm/utils/callback.rs | 45 +++ jason/src/platform/wasm/utils/function.rs | 29 ++ jason/src/platform/wasm/utils/mod.rs | 8 +- jason/tests/media/constraints.rs | 173 +++++--- jason/tests/media/manager.rs | 51 ++- jason/tests/media/mod.rs | 10 +- jason/tests/media/track.rs | 32 +- jason/tests/peer/media/mod.rs | 17 +- .../media/transitable_state/controller.rs | 4 +- jason/tests/peer/mod.rs | 17 +- jason/tests/{api => room}/connection.rs | 60 +-- jason/tests/{api => room}/mod.rs | 23 +- jason/tests/{api => room}/room.rs | 379 ++++++++++-------- jason/tests/rpc/backoff_delayer.rs | 2 +- jason/tests/rpc/heartbeat.rs | 6 +- jason/tests/rpc/mod.rs | 10 +- jason/tests/rpc/rpc_session.rs | 12 +- jason/tests/rpc/websocket.rs | 2 +- jason/tests/web.rs | 67 ++-- 72 files changed, 1417 insertions(+), 1109 deletions(-) create mode 100644 jason/src/api/wasm/jason_error.rs delete mode 100644 jason/src/core/utils/callback.rs create mode 100644 jason/src/platform/rtc_stats.rs create mode 100644 jason/src/platform/transport.rs create mode 100644 jason/src/platform/wasm/constraints.rs create mode 100644 jason/src/platform/wasm/utils/callback.rs create mode 100644 jason/src/platform/wasm/utils/function.rs rename jason/tests/{api => room}/connection.rs (64%) rename jason/tests/{api => room}/mod.rs (94%) rename jason/tests/{api => room}/room.rs (89%) diff --git a/jason/Cargo.toml b/jason/Cargo.toml index 13ec4a45a..e1bf277b6 100644 --- a/jason/Cargo.toml +++ b/jason/Cargo.toml @@ -48,36 +48,36 @@ wasm-bindgen-futures = "0.4" wasm-logger = "0.2" wee_alloc = { version = "0.4", optional = true } [dependencies.web-sys] -version = "0.3.47" -features = [ - "console", - "ConstrainDomStringParameters", "ConstrainDoubleRange", - "CloseEvent", - "DisplayMediaStreamConstraints", - "Event", "EventTarget", - "MediaDevices","MediaDeviceInfo", "MediaDeviceKind", - "MediaTrackConstraints", "MediaTrackSettings", - "MediaStream", "MediaStreamConstraints", - "MediaStreamTrack", "MediaStreamTrackState", - "MessageEvent", - "Navigator", - "RtcBundlePolicy", - "RtcConfiguration", - "RtcIceCandidate", "RtcIceCandidateInit", - "RtcIceConnectionState", - "RtcIceServer", - "RtcIceTransportPolicy", - "RtcOfferOptions", - "RtcPeerConnection", "RtcPeerConnectionIceEvent", - "RtcRtpReceiver", "RtcRtpSender", - "RtcRtpTransceiver", "RtcRtpTransceiverDirection", - "RtcRtpTransceiverInit", - "RtcSdpType", - "RtcSessionDescription", "RtcSessionDescriptionInit", - "RtcStats", - "RtcTrackEvent", - "WebSocket", "Window", -] + version = "0.3.47" + features = [ + "console", + "ConstrainDomStringParameters", "ConstrainDoubleRange", + "CloseEvent", + "DisplayMediaStreamConstraints", + "Event", "EventTarget", + "MediaDevices","MediaDeviceInfo", "MediaDeviceKind", + "MediaTrackConstraints", "MediaTrackSettings", + "MediaStream", "MediaStreamConstraints", + "MediaStreamTrack", "MediaStreamTrackState", + "MessageEvent", + "Navigator", + "RtcBundlePolicy", + "RtcConfiguration", + "RtcIceCandidate", "RtcIceCandidateInit", + "RtcIceConnectionState", + "RtcIceServer", + "RtcIceTransportPolicy", + "RtcOfferOptions", + "RtcPeerConnection", "RtcPeerConnectionIceEvent", + "RtcRtpReceiver", "RtcRtpSender", + "RtcRtpTransceiver", "RtcRtpTransceiverDirection", + "RtcRtpTransceiverInit", + "RtcSdpType", + "RtcSessionDescription", "RtcSessionDescriptionInit", + "RtcStats", + "RtcTrackEvent", + "WebSocket", "Window", + ] [dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/jason/demo/index.html b/jason/demo/index.html index 4128b7a0b..d48c4a5c0 100644 --- a/jason/demo/index.html +++ b/jason/demo/index.html @@ -534,7 +534,7 @@ console.error('Name: "' + err.name() + '";\nMessage: "' + err.message() + '";'); } } else if (name === 'ErroredException') { - alert('Fatal error occured while MediaStreamSettings update.'); + alert('Fatal error occurred while MediaStreamSettings update.'); } } }; diff --git a/jason/e2e-demo/js/index.js b/jason/e2e-demo/js/index.js index 1b9ad8002..cbbd53e9f 100644 --- a/jason/e2e-demo/js/index.js +++ b/jason/e2e-demo/js/index.js @@ -776,7 +776,7 @@ window.onload = async function() { console.error('Name: "' + err.name() + '";\nMessage: "' + err.message() + '";'); } } else if (name === 'ErroredException') { - alert('Fatal error occured while MediaStreamSettings update.'); + alert('Fatal error occurred while MediaStreamSettings update.'); } console.error("Changing video source failed: " + name); } diff --git a/jason/src/api/mod.rs b/jason/src/api/mod.rs index 7d8830d9b..d76bf46b6 100644 --- a/jason/src/api/mod.rs +++ b/jason/src/api/mod.rs @@ -13,7 +13,11 @@ mod wasm; pub use wasm::{ connection_handle::ConnectionHandle, constraints_update_exception::ConstraintsUpdateException, + input_device_info::InputDeviceInfo, + jason::Jason, + jason_error::JasonError, local_media_track::LocalMediaTrack, + media_manager_handle::MediaManagerHandle, media_stream_settings::{ AudioTrackConstraints, DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, MediaStreamSettings, @@ -21,5 +25,6 @@ pub use wasm::{ reconnect_handle::ReconnectHandle, remote_media_track::RemoteMediaTrack, room_close_reason::RoomCloseReason, + room_handle::RoomHandle, FacingMode, MediaKind, MediaSourceKind, }; diff --git a/jason/src/api/wasm/connection_handle.rs b/jason/src/api/wasm/connection_handle.rs index 17e7f178c..ff54c5ed7 100644 --- a/jason/src/api/wasm/connection_handle.rs +++ b/jason/src/api/wasm/connection_handle.rs @@ -1,7 +1,7 @@ use derive_more::From; use wasm_bindgen::prelude::*; -use crate::core; +use crate::{api::JasonError, core}; /// Connection with a specific remote `Member`, that is used on JS side. /// @@ -14,12 +14,18 @@ pub struct ConnectionHandle(core::ConnectionHandle); impl ConnectionHandle { /// Sets callback, which will be invoked when this `Connection` will close. pub fn on_close(&self, cb: js_sys::Function) -> Result<(), JsValue> { - self.0.on_close(cb).map_err(JsValue::from) + self.0 + .on_close(cb.into()) + .map_err(JasonError::from) + .map_err(JsValue::from) } /// Returns remote `Member` ID. pub fn get_remote_member_id(&self) -> Result { - self.0.get_remote_member_id().map_err(JsValue::from) + self.0 + .get_remote_member_id() + .map_err(JasonError::from) + .map_err(JsValue::from) } /// Sets callback, which will be invoked when new [`remote::Track`] will be @@ -28,7 +34,10 @@ impl ConnectionHandle { &self, cb: js_sys::Function, ) -> Result<(), JsValue> { - self.0.on_remote_track_added(cb).map_err(JsValue::from) + self.0 + .on_remote_track_added(cb.into()) + .map_err(JasonError::from) + .map_err(JsValue::from) } /// Sets callback, which will be invoked when connection quality score will @@ -37,6 +46,9 @@ impl ConnectionHandle { &self, cb: js_sys::Function, ) -> Result<(), JsValue> { - self.0.on_quality_score_update(cb).map_err(JsValue::from) + self.0 + .on_quality_score_update(cb.into()) + .map_err(JasonError::from) + .map_err(JsValue::from) } } diff --git a/jason/src/api/wasm/constraints_update_exception.rs b/jason/src/api/wasm/constraints_update_exception.rs index 1c492557e..ca6ff76d0 100644 --- a/jason/src/api/wasm/constraints_update_exception.rs +++ b/jason/src/api/wasm/constraints_update_exception.rs @@ -1,7 +1,9 @@ +use std::iter::FromIterator as _; + use derive_more::From; use wasm_bindgen::prelude::*; -use crate::core; +use crate::{api::JasonError, core}; /// JS exception for the [`RoomHandle::set_local_media_settings`]. #[wasm_bindgen] @@ -20,23 +22,28 @@ impl ConstraintsUpdateException { /// `RecoveredException` or `RecoverFailedException`. /// /// Returns `undefined` otherwise. - pub fn recover_reason(&self) -> JsValue { - self.0.recover_reason() + pub fn recover_reason(&self) -> Option { + self.0.recover_reason().map(Into::into) } /// Returns [`js_sys::Array`] with the [`JasonError`]s if this /// [`ConstraintsUpdateException`] represents `RecoverFailedException`. - /// - /// Returns `undefined` otherwise. pub fn recover_fail_reasons(&self) -> JsValue { - self.0.recover_fail_reasons() + js_sys::Array::from_iter( + self.0 + .recover_fail_reasons() + .into_iter() + .map(JasonError::from) + .map(JsValue::from), + ) + .into() } /// Returns [`JasonError`] if this [`ConstraintsUpdateException`] represents /// `ErroredException`. /// /// Returns `undefined` otherwise. - pub fn error(&self) -> JsValue { - self.0.error() + pub fn error(&self) -> Option { + self.0.error().map(Into::into) } } diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs new file mode 100644 index 000000000..901fbab16 --- /dev/null +++ b/jason/src/api/wasm/jason_error.rs @@ -0,0 +1,32 @@ +use derive_more::From; + +use wasm_bindgen::prelude::*; + +use crate::core; + +#[wasm_bindgen] +#[derive(From)] +pub struct JasonError(core::utils::JasonError); + +#[wasm_bindgen] +impl JasonError { + /// Returns name of error. + pub fn name(&self) -> String { + self.0.name() + } + + /// Returns message of errors. + pub fn message(&self) -> String { + self.0.message() + } + + /// Returns trace information of error. + pub fn trace(&self) -> String { + self.0.trace() + } + + /// Returns JS side error if it the cause. + pub fn source(&self) -> Option { + self.0.source() + } +} diff --git a/jason/src/api/wasm/media_manager_handle.rs b/jason/src/api/wasm/media_manager_handle.rs index 1b61d30b6..47948f7d8 100644 --- a/jason/src/api/wasm/media_manager_handle.rs +++ b/jason/src/api/wasm/media_manager_handle.rs @@ -3,7 +3,10 @@ use js_sys::Promise; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use crate::{api, core}; +use crate::{ + api::{self, JasonError}, + core, +}; use super::input_device_info::InputDeviceInfo; @@ -46,6 +49,7 @@ impl MediaManagerHandle { }) .into() }) + .map_err(JasonError::from) .map_err(JsValue::from) }) } @@ -73,6 +77,7 @@ impl MediaManagerHandle { }) .into() }) + .map_err(JasonError::from) .map_err(JsValue::from) }) } diff --git a/jason/src/api/wasm/media_stream_settings.rs b/jason/src/api/wasm/media_stream_settings.rs index 3277ea7b0..97aed3714 100644 --- a/jason/src/api/wasm/media_stream_settings.rs +++ b/jason/src/api/wasm/media_stream_settings.rs @@ -1,21 +1,21 @@ use derive_more::{From, Into}; use wasm_bindgen::prelude::*; -use crate::{api::FacingMode, core::media}; +use crate::{api::FacingMode, core}; /// [MediaStreamConstraints][1] wrapper. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamconstraints #[wasm_bindgen] #[derive(Clone, From, Into)] -pub struct MediaStreamSettings(media::MediaStreamSettings); +pub struct MediaStreamSettings(core::MediaStreamSettings); #[wasm_bindgen] impl MediaStreamSettings { /// Creates new [`MediaStreamSettings`] with none constraints configured. #[wasm_bindgen(constructor)] pub fn new() -> Self { - media::MediaStreamSettings::new().into() + core::MediaStreamSettings::new().into() } /// Specifies the nature and settings of the audio [MediaStreamTrack][1]. @@ -41,14 +41,14 @@ impl MediaStreamSettings { /// Constraints applicable to audio tracks. #[wasm_bindgen] #[derive(From, Into)] -pub struct AudioTrackConstraints(media::AudioTrackConstraints); +pub struct AudioTrackConstraints(core::AudioTrackConstraints); #[wasm_bindgen] impl AudioTrackConstraints { /// Creates new [`AudioTrackConstraints`] with none constraints configured. #[wasm_bindgen(constructor)] pub fn new() -> Self { - media::AudioTrackConstraints::new().into() + core::AudioTrackConstraints::new().into() } /// Sets exact [deviceId][1] constraint. @@ -63,7 +63,7 @@ impl AudioTrackConstraints { /// device. #[wasm_bindgen] #[derive(From, Into)] -pub struct DeviceVideoTrackConstraints(media::DeviceVideoTrackConstraints); +pub struct DeviceVideoTrackConstraints(core::DeviceVideoTrackConstraints); /// Constraints applicable to video tracks that are sourced from screen-capture. #[wasm_bindgen] @@ -72,7 +72,7 @@ impl DeviceVideoTrackConstraints { /// configured. #[wasm_bindgen(constructor)] pub fn new() -> Self { - media::DeviceVideoTrackConstraints::new().into() + core::DeviceVideoTrackConstraints::new().into() } /// Sets exact [deviceId][1] constraint. @@ -142,7 +142,7 @@ impl DeviceVideoTrackConstraints { /// Constraints applicable to video tracks sourced from screen capture. #[wasm_bindgen] #[derive(From, Into)] -pub struct DisplayVideoTrackConstraints(media::DisplayVideoTrackConstraints); +pub struct DisplayVideoTrackConstraints(core::DisplayVideoTrackConstraints); #[wasm_bindgen] impl DisplayVideoTrackConstraints { @@ -150,6 +150,6 @@ impl DisplayVideoTrackConstraints { /// configured. #[wasm_bindgen(constructor)] pub fn new() -> Self { - media::DisplayVideoTrackConstraints::new().into() + core::DisplayVideoTrackConstraints::new().into() } } diff --git a/jason/src/api/wasm/mod.rs b/jason/src/api/wasm/mod.rs index 419a44151..f777b8ce7 100644 --- a/jason/src/api/wasm/mod.rs +++ b/jason/src/api/wasm/mod.rs @@ -1,9 +1,11 @@ +use derive_more::Display; use wasm_bindgen::prelude::*; pub mod connection_handle; pub mod constraints_update_exception; pub mod input_device_info; pub mod jason; +pub mod jason_error; pub mod local_media_track; pub mod media_manager_handle; pub mod media_stream_settings; @@ -18,6 +20,7 @@ use crate::core; /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-kind #[wasm_bindgen] +#[derive(Clone, Copy, Debug, Display, Eq, PartialEq)] pub enum MediaKind { /// Audio track. Audio, @@ -36,6 +39,7 @@ impl From for MediaKind { } #[wasm_bindgen] +#[derive(Clone, Copy, Debug, Display, Eq, PartialEq)] pub enum MediaSourceKind { /// Media is sourced from some media device (webcam or microphone). Device, @@ -67,7 +71,7 @@ impl Into for MediaSourceKind { /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-videofacingmodeenum #[wasm_bindgen] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Display, Eq, PartialEq)] pub enum FacingMode { /// Facing toward the user (a self-view camera). User, diff --git a/jason/src/api/wasm/reconnect_handle.rs b/jason/src/api/wasm/reconnect_handle.rs index 275f4857c..efa49e167 100644 --- a/jason/src/api/wasm/reconnect_handle.rs +++ b/jason/src/api/wasm/reconnect_handle.rs @@ -3,7 +3,7 @@ use js_sys::Promise; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use crate::core; +use crate::{api::JasonError, core}; /// Handle that JS side can reconnect to the Medea media server on /// a connection loss with. @@ -23,7 +23,9 @@ impl ReconnectHandle { pub fn reconnect_with_delay(&self, delay_ms: u32) -> Promise { let this = self.0.clone(); future_to_promise(async move { - this.reconnect_with_delay(delay_ms).await?; + this.reconnect_with_delay(delay_ms) + .await + .map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -59,7 +61,8 @@ impl ReconnectHandle { multiplier, max_delay, ) - .await?; + .await + .map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } diff --git a/jason/src/api/wasm/remote_media_track.rs b/jason/src/api/wasm/remote_media_track.rs index 18d15af4d..8f3bff17b 100644 --- a/jason/src/api/wasm/remote_media_track.rs +++ b/jason/src/api/wasm/remote_media_track.rs @@ -1,4 +1,4 @@ -use derive_more::From; +use derive_more::{From, Into}; use wasm_bindgen::prelude::*; use crate::core; @@ -7,7 +7,7 @@ use crate::core; /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack #[wasm_bindgen] -#[derive(Clone, From)] +#[derive(Clone, From, Into)] pub struct RemoteMediaTrack(core::remote::Track); #[wasm_bindgen] @@ -24,12 +24,12 @@ impl RemoteMediaTrack { /// Sets callback to invoke when this [`Track`] is enabled. pub fn on_enabled(&self, cb: js_sys::Function) { - self.0.on_enabled(cb) + self.0.on_enabled(cb.into()) } /// Sets callback to invoke when this [`Track`] is disabled. pub fn on_disabled(&self, cb: js_sys::Function) { - self.0.on_disabled(cb) + self.0.on_disabled(cb.into()) } /// Returns [`MediaKind::Audio`] if this [`Track`] represents an audio diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index e7e7060f2..26addca6b 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -3,7 +3,11 @@ use js_sys::Promise; use wasm_bindgen::{prelude::*, JsValue}; use wasm_bindgen_futures::future_to_promise; -use crate::{api, api::MediaSourceKind, core, core::utils::JasonError}; +use crate::{ + api, + api::{JasonError, MediaSourceKind}, + core, +}; /// JS side handle to `Room` where all the media happens. /// @@ -32,8 +36,9 @@ impl RoomHandle { /// Effectively returns `Result<(), JasonError>`. pub fn join(&self, token: String) -> Promise { let this = self.0.clone(); + future_to_promise(async move { - this.join(token).await?; + this.join(token).await.map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -46,13 +51,19 @@ impl RoomHandle { &self, cb: js_sys::Function, ) -> Result<(), JsValue> { - self.0.on_new_connection(cb) + self.0 + .on_new_connection(cb.into()) + .map_err(JasonError::from) + .map_err(JsValue::from) } /// Sets `on_close` callback, which will be invoked on [`Room`] close, /// providing [`RoomCloseReason`]. pub fn on_close(&self, cb: js_sys::Function) -> Result<(), JsValue> { - self.0.on_close(cb) + self.0 + .on_close(cb.into()) + .map_err(JasonError::from) + .map_err(JsValue::from) } /// Sets callback, which will be invoked when new [`local::Track`] will be @@ -62,7 +73,10 @@ impl RoomHandle { /// 2. `disable_audio`/`enable_video` is called. /// 3. [`MediaStreamSettings`] updated via `set_local_media_settings`. pub fn on_local_track(&self, cb: js_sys::Function) -> Result<(), JsValue> { - self.0.on_local_track(cb) + self.0 + .on_local_track(cb.into()) + .map_err(JasonError::from) + .map_err(JsValue::from) } /// Sets `on_failed_local_media` callback, which will be invoked on local @@ -71,7 +85,10 @@ impl RoomHandle { &self, cb: js_sys::Function, ) -> Result<(), JsValue> { - self.0.on_failed_local_media(cb) + self.0 + .on_failed_local_media(cb.into()) + .map_err(JasonError::from) + .map_err(JsValue::from) } /// Sets `on_connection_loss` callback, which will be invoked on connection @@ -80,7 +97,10 @@ impl RoomHandle { &self, cb: js_sys::Function, ) -> Result<(), JsValue> { - self.0.on_connection_loss(cb) + self.0 + .on_connection_loss(cb.into()) + .map_err(JasonError::from) + .map_err(JsValue::from) } /// Updates this [`Room`]s [`MediaStreamSettings`]. This affects all @@ -133,7 +153,7 @@ impl RoomHandle { let this = self.0.clone(); future_to_promise(async move { - this.mute_audio().await?; + this.mute_audio().await.map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -143,7 +163,7 @@ impl RoomHandle { let this = self.0.clone(); future_to_promise(async move { - this.unmute_audio().await?; + this.unmute_audio().await.map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -153,7 +173,9 @@ impl RoomHandle { let this = self.0.clone(); future_to_promise(async move { - this.mute_video(source_kind.map(Into::into)).await?; + this.mute_video(source_kind.map(Into::into)) + .await + .map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -178,7 +200,7 @@ impl RoomHandle { let this = self.0.clone(); future_to_promise(async move { - this.disable_audio().await?; + this.disable_audio().await.map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -188,7 +210,7 @@ impl RoomHandle { let this = self.0.clone(); future_to_promise(async move { - this.enable_audio().await?; + this.enable_audio().await.map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -205,6 +227,7 @@ impl RoomHandle { future_to_promise(async move { this.disable_video(source_kind.map(Into::into)) .await + .map_err(JasonError::from) .map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) @@ -232,7 +255,9 @@ impl RoomHandle { let this = self.0.clone(); future_to_promise(async move { - this.disable_remote_audio().await?; + this.disable_remote_audio() + .await + .map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -242,7 +267,9 @@ impl RoomHandle { let this = self.0.clone(); future_to_promise(async move { - this.disable_remote_video().await?; + this.disable_remote_video() + .await + .map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -252,7 +279,7 @@ impl RoomHandle { let this = self.0.clone(); future_to_promise(async move { - this.enable_audio().await?; + this.enable_remote_audio().await.map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } @@ -262,7 +289,7 @@ impl RoomHandle { let this = self.0.clone(); future_to_promise(async move { - this.enable_remote_video().await?; + this.enable_remote_video().await.map_err(JasonError::from)?; Ok(JsValue::UNDEFINED) }) } diff --git a/jason/src/core/connection.rs b/jason/src/core/connection.rs index 8d985caa0..5672bf3cc 100644 --- a/jason/src/core/connection.rs +++ b/jason/src/core/connection.rs @@ -12,8 +12,9 @@ use crate::{ api, core::{ media::track::remote, - utils::{Callback0, Callback1, HandlerDetachedError, JasonError}, + utils::{HandlerDetachedError, JasonError}, }, + platform, }; /// Service which manages [`Connection`]s with the remote `Member`s. @@ -27,13 +28,16 @@ pub struct Connections { /// Callback from JS side which will be invoked on remote `Member` media /// stream arrival. - on_new_connection: Callback1, + on_new_connection: platform::Callback, } impl Connections { /// Sets callback, which will be invoked when new [`Connection`] is /// established. - pub fn on_new_connection(&self, f: js_sys::Function) { + pub fn on_new_connection( + &self, + f: platform::Function, + ) { self.on_new_connection.set_func(f); } @@ -48,7 +52,7 @@ impl Connections { let is_new = !self.connections.borrow().contains_key(remote_member_id); if is_new { let con = Connection::new(remote_member_id.clone()); - self.on_new_connection.call(con.new_handle()); + self.on_new_connection.call1(con.new_handle()); self.connections .borrow_mut() .insert(remote_member_id.clone(), con); @@ -79,7 +83,7 @@ impl Connections { // `on_close` callback is invoked here and not in `Drop` // implementation so `ConnectionHandle` is available during // callback invocation. - connection.0.on_close.call(); + connection.0.on_close.call0(); } } } @@ -104,19 +108,22 @@ struct InnerConnection { /// JS callback, that will be invoked when [`remote::Track`] is /// received. - on_remote_track_added: Callback1, + on_remote_track_added: platform::Callback, /// JS callback, that will be invoked when [`ConnectionQualityScore`] will /// be updated. - on_quality_score_update: Callback1, + on_quality_score_update: platform::Callback, /// JS callback, that will be invoked when this connection is closed. - on_close: Callback0, + on_close: platform::Callback<()>, } impl ConnectionHandle { /// Sets callback, which will be invoked when this `Connection` will close. - pub fn on_close(&self, f: js_sys::Function) -> Result<(), JasonError> { + pub fn on_close( + &self, + f: platform::Function<()>, + ) -> Result<(), JasonError> { upgrade_or_detached!(self.0).map(|inner| inner.on_close.set_func(f)) } @@ -129,7 +136,7 @@ impl ConnectionHandle { /// added to this [`Connection`]. pub fn on_remote_track_added( &self, - f: js_sys::Function, + f: platform::Function, ) -> Result<(), JasonError> { upgrade_or_detached!(self.0) .map(|inner| inner.on_remote_track_added.set_func(f)) @@ -139,7 +146,7 @@ impl ConnectionHandle { /// be updated by server. pub fn on_quality_score_update( &self, - f: js_sys::Function, + f: platform::Function, ) -> Result<(), JasonError> { upgrade_or_detached!(self.0) .map(|inner| inner.on_quality_score_update.set_func(f)) @@ -157,16 +164,16 @@ impl Connection { Self(Rc::new(InnerConnection { remote_id, quality_score: Cell::default(), - on_quality_score_update: Callback1::default(), - on_close: Callback0::default(), - on_remote_track_added: Callback1::default(), + on_quality_score_update: platform::Callback::default(), + on_close: platform::Callback::default(), + on_remote_track_added: platform::Callback::default(), })) } /// Invokes `on_remote_track_added` JS callback with the provided /// [`remote::Track`]. pub fn add_remote_track(&self, track: remote::Track) { - self.0.on_remote_track_added.call(track); + self.0.on_remote_track_added.call1(track); } /// Creates new [`ConnectionHandle`] for using [`Connection`] on JS side. @@ -178,7 +185,7 @@ impl Connection { /// Updates [`ConnectionQualityScore`] of this [`Connection`]. pub fn update_quality_score(&self, score: ConnectionQualityScore) { if self.0.quality_score.replace(Some(score)) != Some(score) { - self.0.on_quality_score_update.call(score as u8); + self.0.on_quality_score_update.call1(score as u8); } } } diff --git a/jason/src/core/media/constraints.rs b/jason/src/core/media/constraints.rs index 973d0bb8a..14519e262 100644 --- a/jason/src/core/media/constraints.rs +++ b/jason/src/core/media/constraints.rs @@ -11,15 +11,15 @@ use medea_client_api_proto::{ }; use crate::{ - api::FacingMode, + api, core::{ - media::MediaKind, + media::{track::MediaStreamTrackState, MediaKind}, peer::{ media_exchange_state, mute_state, LocalStreamUpdateCriteria, MediaState, }, }, - platform::*, + platform, }; /// Local media stream for injecting into new created [`PeerConnection`]s. @@ -192,7 +192,10 @@ impl Default for AudioMediaTracksSettings { /// Returns `true` if provided [`MediaStreamTrack`] basically /// satisfies any constraints with a provided [`MediaKind`]. #[inline] -fn satisfies_track(track: &MediaStreamTrack, kind: MediaKind) -> bool { +fn satisfies_track( + track: &platform::MediaStreamTrack, + kind: MediaKind, +) -> bool { track.kind() == kind && track.ready_state() == MediaStreamTrackState::Live } @@ -274,7 +277,10 @@ impl VideoTrackConstraints { /// device [`VideoTrackConstraints::constraints`]. /// /// Returns `false` if [`VideoTrackConstraints::constraints`] is not set. - pub fn satisfies>(&self, track: T) -> bool { + pub fn satisfies>( + &self, + track: T, + ) -> bool { self.constraints .as_ref() .filter(|_| self.enabled()) @@ -287,7 +293,10 @@ impl VideoTrackConstraints { /// device [`VideoTrackConstraints::constraints`]. /// /// Returns `false` if [`VideoTrackConstraints::constraints`] is not set. - pub fn satisfies>(&self, track: T) -> bool { + pub fn satisfies>( + &self, + track: T, + ) -> bool { self.constraints .as_ref() .filter(|_| self.enabled()) @@ -368,7 +377,7 @@ impl MediaStreamSettings { /// [`VideoTrackConstraints::unconstrain`]. pub fn unconstrain_if_satisfies_video(&mut self, track: T) -> bool where - T: AsRef, + T: AsRef, { if self.device_video.satisfies(&track) { self.device_video.unconstrain(); @@ -634,18 +643,21 @@ pub enum MultiSourceTracksConstraints { /// Only [getUserMedia()][1] request is required. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia - Device(MediaStreamConstraints), + Device(platform::MediaStreamConstraints), /// Only [getDisplayMedia()][1] request is required. /// /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - Display(DisplayMediaStreamConstraints), + Display(platform::DisplayMediaStreamConstraints), /// Both [getUserMedia()][1] and [getDisplayMedia()][2] are required. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - DeviceAndDisplay(MediaStreamConstraints, DisplayMediaStreamConstraints), + DeviceAndDisplay( + platform::MediaStreamConstraints, + platform::DisplayMediaStreamConstraints, + ), } impl From for Option { @@ -662,10 +674,8 @@ impl From for Option { constraints.device_video.constraints { device_cons - .get_or_insert_with(MediaStreamConstraints::new) - .video( - &MediaTrackConstraints::from(device_video_cons).into(), - ); + .get_or_insert_with(platform::MediaStreamConstraints::new) + .video(device_video_cons); } } if is_display_video_enabled { @@ -673,19 +683,16 @@ impl From for Option { constraints.display_video.constraints { display_cons - .get_or_insert_with(DisplayMediaStreamConstraints::new) - .video( - &MediaTrackConstraints::from(display_video_cons).into(), - ); + .get_or_insert_with( + platform::DisplayMediaStreamConstraints::new, + ) + .video(display_video_cons); } } if is_device_audio_enabled { device_cons - .get_or_insert_with(MediaStreamConstraints::new) - .audio( - &MediaTrackConstraints::from(constraints.audio.constraints) - .into(), - ); + .get_or_insert_with(platform::MediaStreamConstraints::new) + .audio(constraints.audio.constraints); } match (device_cons, display_cons) { @@ -739,7 +746,10 @@ impl VideoSource { /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack #[inline] - pub fn satisfies>(&self, track: T) -> bool { + pub fn satisfies>( + &self, + track: T, + ) -> bool { match self { VideoSource::Display(display) => display.satisfies(&track), VideoSource::Device(device) => device.satisfies(track), @@ -784,7 +794,10 @@ impl TrackConstraints { /// [`TrackConstraints`]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - pub fn satisfies>(&self, track: T) -> bool { + pub fn satisfies>( + &self, + track: T, + ) -> bool { match self { Self::Audio(audio) => audio.satisfies(&track), Self::Video(video) => video.satisfies(&track), @@ -833,19 +846,12 @@ impl From for TrackConstraints { } } -// TODO: Its gonna be a nightmare if we will add all possible constraints, -// especially if we will support all that `exact`/`min`/`max`/`ideal` -// stuff, will need major refactoring then. -// TODO: Using reflection to get fields values is pure evil, but there are no -// getters for WebIDL's dictionaries, should be wrapped or improved in -// wasm-bindgen. - /// Constraints applicable to audio tracks. #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct AudioTrackConstraints { /// The identifier of the device generating the content for the media /// track. - device_id: Option>, + pub device_id: Option>, /// Importance of this [`AudioTrackConstraints`]. /// @@ -871,7 +877,10 @@ impl AudioTrackConstraints { /// contained. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - pub fn satisfies>(&self, track: T) -> bool { + pub fn satisfies>( + &self, + track: T, + ) -> bool { let track = track.as_ref(); satisfies_track(track, MediaKind::Audio) && ConstrainString::satisfies(&self.device_id, &track.device_id()) @@ -909,26 +918,13 @@ impl From for AudioTrackConstraints { } } -impl From for MediaTrackConstraints { - fn from(track_constraints: AudioTrackConstraints) -> Self { - let mut constraints = Self::new(); - - if let Some(device_id) = track_constraints.device_id { - constraints - .device_id(&ConstrainDomStringParameters::from(&device_id)); - } - - constraints - } -} - -impl AsRef for FacingMode { +impl AsRef for api::FacingMode { fn as_ref(&self) -> &str { match self { - FacingMode::User => "user", - FacingMode::Environment => "environment", - FacingMode::Left => "left", - FacingMode::Right => "right", + api::FacingMode::User => "user", + api::FacingMode::Environment => "environment", + api::FacingMode::Left => "left", + api::FacingMode::Right => "right", } } } @@ -938,7 +934,7 @@ impl AsRef for FacingMode { /// /// [1]: https://tinyurl.com/w3-streams#dom-constrainulong #[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum ConstrainU32 { +pub enum ConstrainU32 { /// Must be the parameter's value. Exact(u32), @@ -966,25 +962,6 @@ impl ConstrainU32 { } } -impl From for ConstrainDoubleRange { - fn from(from: ConstrainU32) -> Self { - let mut constraint = ConstrainDoubleRange::new(); - match from { - ConstrainU32::Exact(val) => { - constraint.exact(f64::from(val)); - } - ConstrainU32::Ideal(val) => { - constraint.ideal(f64::from(val)); - } - ConstrainU32::Range(min, max) => { - constraint.min(f64::from(min)).max(f64::from(max)); - } - } - - constraint - } -} - /// Representation of the [ConstrainDOMString][1]. /// /// Can set exact (must be the parameter's value) and ideal (should be used if @@ -992,7 +969,7 @@ impl From for ConstrainDoubleRange { /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring #[derive(Clone, Copy, Debug, Eq, PartialEq)] -enum ConstrainString { +pub enum ConstrainString { Exact(T), Ideal(T), } @@ -1008,22 +985,6 @@ impl> ConstrainString { } } -impl> From<&ConstrainString> for ConstrainDomStringParameters { - fn from(from: &ConstrainString) -> Self { - let mut constraint = ConstrainDomStringParameters::new(); - match from { - ConstrainString::Exact(val) => { - constraint.exact(&JsValue::from_str(val.as_ref())) - } - ConstrainString::Ideal(val) => { - constraint.ideal(&JsValue::from_str(val.as_ref())) - } - }; - - constraint - } -} - /// Constraints applicable to video tracks that are sourced from some media /// device. #[derive(Clone, Debug, Default, Eq, PartialEq)] @@ -1036,17 +997,17 @@ pub struct DeviceVideoTrackConstraints { /// The identifier of the device generating the content for the media /// track. - device_id: Option>, + pub device_id: Option>, /// Describes the directions that the camera can face, as seen from the /// user's perspective. - facing_mode: Option>, + pub facing_mode: Option>, /// Height of the video in pixels. - height: Option, + pub height: Option, /// Width of the video in pixels. - width: Option, + pub width: Option, } /// Constraints applicable to video tracks that are sourced from screen-capture. @@ -1067,14 +1028,14 @@ impl DeviceVideoTrackConstraints { /// Sets exact [facingMode][1] constraint. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring - pub fn exact_facing_mode(&mut self, facing_mode: FacingMode) { + pub fn exact_facing_mode(&mut self, facing_mode: api::FacingMode) { self.facing_mode = Some(ConstrainString::Exact(facing_mode)); } /// Sets ideal [facingMode][1] constraint. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring - pub fn ideal_facing_mode(&mut self, facing_mode: FacingMode) { + pub fn ideal_facing_mode(&mut self, facing_mode: api::FacingMode) { self.facing_mode = Some(ConstrainString::Ideal(facing_mode)); } @@ -1124,8 +1085,10 @@ impl DeviceVideoTrackConstraints { /// [`DeviceVideoTrackConstraints`] contained. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - // pub fn satisfies(&self, track: &MediaStreamTrack) -> bool { - pub fn satisfies>(&self, track: T) -> bool { + pub fn satisfies>( + &self, + track: T, + ) -> bool { let track = track.as_ref(); satisfies_track(track, MediaKind::Video) && ConstrainString::satisfies(&self.device_id, &track.device_id()) @@ -1191,7 +1154,10 @@ impl DisplayVideoTrackConstraints { /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack #[allow(clippy::unused_self)] #[inline] - pub fn satisfies>(&self, track: T) -> bool { + pub fn satisfies>( + &self, + track: T, + ) -> bool { let track = track.as_ref(); satisfies_track(track, MediaKind::Video) && track.guess_is_from_display() @@ -1216,32 +1182,3 @@ impl DisplayVideoTrackConstraints { self.required } } - -impl From for MediaTrackConstraints { - fn from(track_constraints: DeviceVideoTrackConstraints) -> Self { - let mut constraints = Self::new(); - - if let Some(device_id) = track_constraints.device_id { - constraints - .device_id(&ConstrainDomStringParameters::from(&device_id)); - } - if let Some(facing_mode) = track_constraints.facing_mode { - constraints - .facing_mode(&ConstrainDomStringParameters::from(&facing_mode)); - } - if let Some(width) = track_constraints.width { - constraints.width(&ConstrainDoubleRange::from(width)); - } - if let Some(height) = track_constraints.height { - constraints.height(&ConstrainDoubleRange::from(height)); - } - - constraints - } -} - -impl From for MediaTrackConstraints { - fn from(_: DisplayVideoTrackConstraints) -> Self { - Self::new() - } -} diff --git a/jason/src/core/media/manager.rs b/jason/src/core/media/manager.rs index b740f6042..b9ffaeb66 100644 --- a/jason/src/core/media/manager.rs +++ b/jason/src/core/media/manager.rs @@ -12,7 +12,10 @@ use tracerr::Traced; use crate::{ core::{ - media::{MediaKind, MediaStreamSettings, MultiSourceTracksConstraints}, + media::{ + track::MediaStreamTrackState, MediaKind, MediaStreamSettings, + MultiSourceTracksConstraints, + }, utils::{HandlerDetachedError, JasonError, JsCaused}, }, platform, @@ -20,8 +23,6 @@ use crate::{ use super::track::local; -use crate::platform::Error; - /// Errors that may occur in a [`MediaManager`]. #[derive(Clone, Debug, Display, JsCaused)] #[js(error = "platform::Error")] @@ -30,25 +31,25 @@ pub enum MediaManagerError { /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediadevices #[display(fmt = "Navigator.mediaDevices() failed: {}", _0)] - CouldNotGetMediaDevices(Error), + CouldNotGetMediaDevices(platform::Error), /// Occurs if the [getUserMedia][1] request failed. /// /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia #[display(fmt = "MediaDevices.getUserMedia() failed: {}", _0)] - GetUserMediaFailed(Error), + GetUserMediaFailed(platform::Error), /// Occurs if the [getDisplayMedia()][1] request failed. /// /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia #[display(fmt = "MediaDevices.getDisplayMedia() failed: {}", _0)] - GetDisplayMediaFailed(Error), + GetDisplayMediaFailed(platform::Error), /// Occurs when cannot get info about connected [MediaDevices][1]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediadevices #[display(fmt = "MediaDevices.enumerateDevices() failed: {}", _0)] - EnumerateDevicesFailed(Error), + EnumerateDevicesFailed(platform::Error), /// Occurs when local track is [`ended`][1] right after [getUserMedia()][2] /// or [getDisplayMedia()][3] request. @@ -255,7 +256,7 @@ impl InnerMediaManager { // `live`. Otherwise, we should err without caching tracks in // `MediaManager`. Tracks will be stopped on `Drop`. for track in &tracks { - if track.ready_state() != platform::MediaStreamTrackState::Live { + if track.ready_state() != MediaStreamTrackState::Live { return Err(tracerr::new!(LocalTrackIsEnded(track.kind()))); } } diff --git a/jason/src/core/media/mod.rs b/jason/src/core/media/mod.rs index 031074dd7..2484070a7 100644 --- a/jason/src/core/media/mod.rs +++ b/jason/src/core/media/mod.rs @@ -2,7 +2,7 @@ //! //! [1]: https://w3.org/TR/mediacapture-streams -mod constraints; +pub mod constraints; mod manager; pub mod track; diff --git a/jason/src/core/media/track/mod.rs b/jason/src/core/media/track/mod.rs index 747c593e4..edf67238a 100644 --- a/jason/src/core/media/track/mod.rs +++ b/jason/src/core/media/track/mod.rs @@ -7,6 +7,12 @@ pub mod remote; use medea_client_api_proto as proto; +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum MediaStreamTrackState { + Live, + Ended, +} + /// Media source type. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum MediaSourceKind { diff --git a/jason/src/core/media/track/remote.rs b/jason/src/core/media/track/remote.rs index 9a8dd6bde..414175aaf 100644 --- a/jason/src/core/media/track/remote.rs +++ b/jason/src/core/media/track/remote.rs @@ -7,11 +7,8 @@ use medea_client_api_proto as proto; use medea_reactive::ObservableCell; use crate::{ - core::{ - media::{MediaKind, MediaSourceKind}, - utils::Callback0, - }, - platform::{self, spawn}, + core::media::{MediaKind, MediaSourceKind}, + platform, }; /// Inner reference-counted data of [`Track`]. @@ -23,10 +20,10 @@ struct Inner { media_source_kind: proto::MediaSourceKind, /// Callback to be invoked when this [`Track`] is enabled. - on_enabled: Callback0, + on_enabled: platform::Callback<()>, /// Callback to be invoked when this [`Track`] is disabled. - on_disabled: Callback0, + on_disabled: platform::Callback<()>, /// [`enabled`][1] property of [MediaStreamTrack][2]. /// @@ -54,15 +51,15 @@ impl Track { let track = platform::MediaStreamTrack::from(track); let track = Track(Rc::new(Inner { enabled: ObservableCell::new(track.enabled()), - on_enabled: Callback0::default(), - on_disabled: Callback0::default(), + on_enabled: platform::Callback::default(), + on_disabled: platform::Callback::default(), media_source_kind, track, })); let mut track_enabled_state_changes = track.enabled_observable().subscribe().skip(1); - spawn({ + platform::spawn({ let weak_inner = Rc::downgrade(&track.0); async move { while let Some(enabled) = @@ -70,9 +67,9 @@ impl Track { { if let Some(track) = weak_inner.upgrade() { if enabled { - track.on_enabled.call(); + track.on_enabled.call0(); } else { - track.on_disabled.call(); + track.on_disabled.call0(); } } else { break; @@ -138,12 +135,12 @@ impl Track { } /// Sets callback to invoke when this [`Track`] is enabled. - pub fn on_enabled(&self, callback: js_sys::Function) { + pub fn on_enabled(&self, callback: platform::Function<()>) { self.0.on_enabled.set_func(callback); } /// Sets callback to invoke when this [`Track`] is disabled. - pub fn on_disabled(&self, callback: js_sys::Function) { + pub fn on_disabled(&self, callback: platform::Function<()>) { self.0.on_disabled.set_func(callback); } } diff --git a/jason/src/core/mod.rs b/jason/src/core/mod.rs index 491cdfecf..069fc2d39 100644 --- a/jason/src/core/mod.rs +++ b/jason/src/core/mod.rs @@ -3,6 +3,8 @@ use futures::FutureExt as _; use std::{cell::RefCell, rc::Rc}; +use crate::platform; + use self::{ media::MediaManager, rpc::{ @@ -12,21 +14,19 @@ use self::{ #[doc(inline)] pub use self::{ - connection::{Connection, ConnectionHandle, Connections}, + connection::{ConnectionHandle, Connections}, media::{ - track::{local::LocalMediaTrack, remote}, - MediaKind, MediaManagerHandle, MediaSourceKind, + track::{local::LocalMediaTrack, remote, MediaStreamTrackState}, + AudioTrackConstraints, DeviceVideoTrackConstraints, + DisplayVideoTrackConstraints, MediaKind, MediaManagerHandle, + MediaSourceKind, MediaStreamSettings, }, room::{ ConstraintsUpdateException, Room, RoomCloseReason, RoomError, - RoomHandle, WeakRoom, + RoomHandle, }, rpc::ReconnectHandle, }; -use crate::platform::{ - spawn, - transport::{RpcTransport, WebSocketRpcTransport}, -}; #[macro_use] pub mod utils; @@ -62,10 +62,10 @@ impl Jason { Self::with_rpc_client(Rc::new(WebSocketRpcClient::new(Box::new( |url| { Box::pin(async move { - let ws = WebSocketRpcTransport::new(url) + let ws = platform::WebSocketRpcTransport::new(url) .await .map_err(|e| tracerr::new!(e))?; - Ok(Rc::new(ws) as Rc) + Ok(Rc::new(ws) as Rc) }) }, )))) @@ -121,7 +121,7 @@ impl Jason { let weak_room = room.downgrade(); let weak_inner = Rc::downgrade(&self.0); - spawn(on_normal_close.map(move |reason| { + platform::spawn(on_normal_close.map(move |reason| { (|| { let room = weak_room.upgrade()?; let inner = weak_inner.upgrade()?; diff --git a/jason/src/core/peer/component/local_sdp.rs b/jason/src/core/peer/component/local_sdp.rs index e3ae39e39..5b1936e45 100644 --- a/jason/src/core/peer/component/local_sdp.rs +++ b/jason/src/core/peer/component/local_sdp.rs @@ -16,7 +16,7 @@ use medea_reactive::ObservableCell; use crate::{ core::utils::{resettable_delay_for, ResettableDelayHandle}, - platform::spawn, + platform, }; const DESCRIPTION_APPROVE_TIMEOUT: Duration = Duration::from_secs(10); @@ -152,7 +152,7 @@ impl LocalSdp { DESCRIPTION_APPROVE_TIMEOUT, self.0.is_rollback_timeout_stopped.get(), ); - spawn({ + platform::spawn({ let this = self.clone(); async move { if let Either::Right(_) = diff --git a/jason/src/core/peer/media/mod.rs b/jason/src/core/peer/media/mod.rs index a7290e8fe..05417a523 100644 --- a/jason/src/core/peer/media/mod.rs +++ b/jason/src/core/peer/media/mod.rs @@ -18,17 +18,14 @@ use proto::{MediaSourceKind, TrackId}; use tracerr::Traced; #[cfg(feature = "mockable")] -use crate::media::{LocalTracksConstraints, RecvConstraints}; +use crate::core::media::{LocalTracksConstraints, RecvConstraints}; use crate::{ core::{ media::{track::local, MediaKind}, - peer::{LocalStreamUpdateCriteria, PeerEvent, TrackEvent}, + peer::{LocalStreamUpdateCriteria, PeerEvent}, utils::JsCaused, }, - platform::{ - self, MediaStreamTrack, RtcPeerConnection, Transceiver, - TransceiverDirection, - }, + platform, }; use super::tracks_request::TracksRequest; @@ -298,7 +295,7 @@ struct InnerMediaConnections { /// /// [`Sender`]: self::sender::Sender /// [`Receiver`]: self::receiver::Receiver - peer: Rc, + peer: Rc, /// [`PeerEvent`]s tx. peer_events_sender: mpsc::UnboundedSender, @@ -364,16 +361,21 @@ impl InnerMediaConnections { fn add_transceiver( &self, kind: MediaKind, - direction: TransceiverDirection, - ) -> Transceiver { - Transceiver::from(self.peer.add_transceiver(kind, direction)) + direction: platform::TransceiverDirection, + ) -> platform::Transceiver { + platform::Transceiver::from(self.peer.add_transceiver(kind, direction)) } /// Lookups [`Transceiver`] by the provided [`mid`]. /// /// [`mid`]: https://w3.org/TR/webrtc/#dom-rtptransceiver-mid - fn get_transceiver_by_mid(&self, mid: &str) -> Option { - self.peer.get_transceiver_by_mid(mid).map(Transceiver::from) + fn get_transceiver_by_mid( + &self, + mid: &str, + ) -> Option { + self.peer + .get_transceiver_by_mid(mid) + .map(platform::Transceiver::from) } } @@ -386,7 +388,7 @@ impl MediaConnections { /// [`RtcPeerConnection`]. #[inline] pub fn new( - peer: Rc, + peer: Rc, peer_events_sender: mpsc::UnboundedSender, ) -> Self { Self(RefCell::new(InnerMediaConnections { @@ -658,8 +660,8 @@ impl MediaConnections { /// [`Receiver`]: self::receiver::Receiver pub fn add_remote_track( &self, - track: MediaStreamTrack, - transceiver: Transceiver, + track: platform::MediaStreamTrack, + transceiver: platform::Transceiver, ) -> Result<()> { let inner = self.0.borrow(); // Cannot fail, since transceiver is guaranteed to be negotiated at this diff --git a/jason/src/core/peer/media/receiver/component.rs b/jason/src/core/peer/media/receiver/component.rs index 28d0fabd9..4a44e66b0 100644 --- a/jason/src/core/peer/media/receiver/component.rs +++ b/jason/src/core/peer/media/receiver/component.rs @@ -26,7 +26,7 @@ use crate::{ }, utils::{component, AsProtoState, SynchronizableState, Updatable}, }, - platform::TransceiverDirection, + platform, }; use super::Receiver; @@ -270,7 +270,7 @@ impl Component { track.set_enabled(false); } if let Some(trnscvr) = receiver.transceiver.borrow().as_ref() { - trnscvr.sub_direction(TransceiverDirection::RECV); + trnscvr.sub_direction(platform::TransceiverDirection::RECV); } } media_exchange_state::Stable::Enabled => { @@ -278,7 +278,7 @@ impl Component { track.set_enabled(true); } if let Some(trnscvr) = receiver.transceiver.borrow().as_ref() { - trnscvr.add_direction(TransceiverDirection::RECV); + trnscvr.add_direction(platform::TransceiverDirection::RECV); } } } @@ -403,9 +403,9 @@ impl TransceiverSide for State { impl State { /// Stabilizes [`MediaExchangeState`] of this [`State`]. pub fn stabilize(&self) { - use crate::peer::media::InTransition as _; + // use crate::core::peer::media::InTransition as _; - if let crate::peer::MediaExchangeState::Transition(transition) = + if let crate::core::peer::MediaExchangeState::Transition(transition) = self.enabled_individual.state() { self.enabled_individual.update(transition.intended()); diff --git a/jason/src/core/peer/media/receiver/mod.rs b/jason/src/core/peer/media/receiver/mod.rs index 14723a915..fa72bdcf2 100644 --- a/jason/src/core/peer/media/receiver/mod.rs +++ b/jason/src/core/peer/media/receiver/mod.rs @@ -13,11 +13,11 @@ use crate::{ core::{ media::{track::remote, MediaKind, RecvConstraints, TrackConstraints}, peer::{ - media::{media_exchange_state, TrackEvent}, - MediaConnections, MediaStateControllable, PeerEvent, + media::media_exchange_state, MediaConnections, + MediaStateControllable, PeerEvent, TrackEvent, }, }, - platform::{MediaStreamTrack, Transceiver, TransceiverDirection}, + platform, }; use super::TransceiverSide; @@ -33,7 +33,7 @@ pub struct Receiver { track_id: TrackId, caps: TrackConstraints, sender_id: MemberId, - transceiver: RefCell>, + transceiver: RefCell>, mid: RefCell>, track: RefCell>, is_track_notified: Cell, @@ -64,9 +64,9 @@ impl Receiver { let caps = TrackConstraints::from(state.media_type().clone()); let kind = MediaKind::from(&caps); let transceiver_direction = if state.enabled_individual() { - TransceiverDirection::RECV + platform::TransceiverDirection::RECV } else { - TransceiverDirection::INACTIVE + platform::TransceiverDirection::INACTIVE }; let transceiver = if state.mid().is_none() { @@ -144,7 +144,7 @@ impl Receiver { pub fn is_receiving(&self) -> bool { let is_recv_direction = self.transceiver.borrow().as_ref().map_or(false, |trnsvr| { - trnsvr.has_direction(TransceiverDirection::RECV) + trnsvr.has_direction(platform::TransceiverDirection::RECV) }); self.enabled_individual.get() && is_recv_direction @@ -174,8 +174,8 @@ impl Receiver { /// [`Receiver::enabled`] of this [`Receiver`]. pub fn set_remote_track( &self, - transceiver: Transceiver, - new_track: MediaStreamTrack, + transceiver: platform::Transceiver, + new_track: platform::MediaStreamTrack, ) { if let Some(old_track) = self.track.borrow().as_ref() { if old_track.id() == new_track.id() { @@ -187,9 +187,9 @@ impl Receiver { remote::Track::new(new_track, self.caps.media_source_kind()); if self.enabled() { - transceiver.add_direction(TransceiverDirection::RECV); + transceiver.add_direction(platform::TransceiverDirection::RECV); } else { - transceiver.sub_direction(TransceiverDirection::RECV); + transceiver.sub_direction(platform::TransceiverDirection::RECV); } new_track.set_enabled(self.enabled()); @@ -204,7 +204,7 @@ impl Receiver { /// /// No-op if provided with the same [`Transceiver`] as already exists in /// this [`Receiver`]. - pub fn replace_transceiver(&self, transceiver: Transceiver) { + pub fn replace_transceiver(&self, transceiver: platform::Transceiver) { if self.mid.borrow().as_ref() == transceiver.mid().as_ref() { self.transceiver.replace(Some(transceiver)); } @@ -214,7 +214,7 @@ impl Receiver { /// /// Returns [`None`] if this [`Receiver`] doesn't have [`Transceiver`]. #[inline] - pub fn transceiver(&self) -> Option { + pub fn transceiver(&self) -> Option { self.transceiver.borrow().clone() } diff --git a/jason/src/core/peer/media/sender/component.rs b/jason/src/core/peer/media/sender/component.rs index 4b6fa96f3..53ade3383 100644 --- a/jason/src/core/peer/media/sender/component.rs +++ b/jason/src/core/peer/media/sender/component.rs @@ -29,7 +29,7 @@ use crate::{ }, utils::{component, AsProtoState, SynchronizableState, Updatable}, }, - platform::TransceiverDirection, + platform, }; use super::Sender; @@ -445,11 +445,13 @@ impl Component { if sender.enabled_in_cons() { sender .transceiver - .add_direction(TransceiverDirection::SEND); + .add_direction(platform::TransceiverDirection::SEND); } } media_exchange_state::Stable::Disabled => { - sender.transceiver.sub_direction(TransceiverDirection::SEND); + sender + .transceiver + .sub_direction(platform::TransceiverDirection::SEND); } } diff --git a/jason/src/core/peer/media/sender/mod.rs b/jason/src/core/peer/media/sender/mod.rs index 9a1bb8ba9..fed03b614 100644 --- a/jason/src/core/peer/media/sender/mod.rs +++ b/jason/src/core/peer/media/sender/mod.rs @@ -14,7 +14,7 @@ use crate::{ }, peer::TrackEvent, }, - platform::{Transceiver, TransceiverDirection}, + platform, }; use super::{ @@ -28,7 +28,7 @@ pub use self::component::{Component, State}; pub struct Sender { track_id: TrackId, caps: TrackConstraints, - transceiver: Transceiver, + transceiver: platform::Transceiver, muted: Cell, enabled_individual: Cell, enabled_general: Cell, @@ -82,8 +82,10 @@ impl Sender { }) .and_then(|rcvr| rcvr.transceiver()) .unwrap_or_else(|| { - connections - .add_transceiver(kind, TransceiverDirection::INACTIVE) + connections.add_transceiver( + kind, + platform::TransceiverDirection::INACTIVE, + ) }), Some(mid) => connections .get_transceiver_by_mid(mid) @@ -128,7 +130,8 @@ impl Sender { #[inline] #[must_use] pub fn is_publishing(&self) -> bool { - self.transceiver.has_direction(TransceiverDirection::SEND) + self.transceiver + .has_direction(platform::TransceiverDirection::SEND) } /// Drops [`local::Track`] used by this [`Sender`]. Sets track used by @@ -177,7 +180,7 @@ impl Sender { /// Returns [`Transceiver`] of this [`Sender`]. #[inline] #[must_use] - pub fn transceiver(&self) -> Transceiver { + pub fn transceiver(&self) -> platform::Transceiver { self.transceiver.clone() } diff --git a/jason/src/core/peer/media/transitable_state/controller.rs b/jason/src/core/peer/media/transitable_state/controller.rs index 9a20fc292..80943fccf 100644 --- a/jason/src/core/peer/media/transitable_state/controller.rs +++ b/jason/src/core/peer/media/transitable_state/controller.rs @@ -22,7 +22,7 @@ use crate::{ }, utils::{resettable_delay_for, ResettableDelayHandle}, }, - platform::spawn, + platform, }; use super::TransitableState; @@ -83,13 +83,13 @@ where // at that moment. let mut state_changes = self.state.subscribe().skip(1); let weak_this = Rc::downgrade(&self); - spawn(async move { + platform::spawn(async move { while let Some(state) = state_changes.next().await { let (state, _guard) = state.into_parts(); if let Some(this) = weak_this.upgrade() { if let TransitableState::Transition(_) = state { let weak_this = Rc::downgrade(&this); - spawn(async move { + platform::spawn(async move { let mut states = this.state.subscribe().skip(1); let (timeout, timeout_handle) = resettable_delay_for( diff --git a/jason/src/core/peer/mod.rs b/jason/src/core/peer/mod.rs index d8def5b5d..5395b0726 100644 --- a/jason/src/core/peer/mod.rs +++ b/jason/src/core/peer/mod.rs @@ -35,7 +35,7 @@ use crate::{ utils::{JasonError, JsCaused}, Connections, }, - platform::{self, spawn, MediaStreamTrack, Transceiver}, + platform, }; #[doc(inline)] @@ -322,7 +322,7 @@ impl PeerConnection { peer_events_sender.clone(), )); - spawn({ + platform::spawn({ let peer_events_sender = peer_events_sender.clone(); let peer_id = state.id(); @@ -940,7 +940,7 @@ impl PeerConnection { /// /// Errors with [`PeerError::RtcPeerConnection`] if failed to get /// [`RtcStats`]. - pub async fn get_stats(&self) -> Result { + pub async fn get_stats(&self) -> Result { self.peer .get_stats() .await @@ -1049,9 +1049,9 @@ impl Drop for PeerConnection { /// Drops `on_track` and `on_ice_candidate` callbacks to prevent possible /// leaks. fn drop(&mut self) { - let _ = self - .peer - .on_track::>(None); + let _ = self.peer.on_track::>(None); let _ = self .peer .on_ice_candidate::>(None); diff --git a/jason/src/core/peer/repo.rs b/jason/src/core/peer/repo.rs index 32e0a37eb..6df425205 100644 --- a/jason/src/core/peer/repo.rs +++ b/jason/src/core/peer/repo.rs @@ -18,7 +18,7 @@ use crate::{ }, Connections, RoomError, }, - platform::{delay_for, spawn}, + platform, }; use super::{PeerConnection, PeerEvent}; @@ -170,7 +170,7 @@ impl Repository { ) -> TaskHandle { let (fut, abort) = future::abortable(async move { loop { - delay_for(Duration::from_secs(1).into()).await; + platform::delay_for(Duration::from_secs(1).into()).await; let peers = peers .borrow() @@ -184,7 +184,7 @@ impl Repository { } }); - spawn(async move { + platform::spawn(async move { fut.await.ok(); }); diff --git a/jason/src/core/room.rs b/jason/src/core/room.rs index ee5efd1f1..a1f67085a 100644 --- a/jason/src/core/room.rs +++ b/jason/src/core/room.rs @@ -39,12 +39,10 @@ use crate::{ ConnectionInfoParseError, ReconnectHandle, RpcSession, SessionError, }, - utils::{ - AsProtoState, Callback1, HandlerDetachedError, JasonError, JsCaused, - }, + utils::{AsProtoState, HandlerDetachedError, JasonError, JsCaused}, Connections, }, - platform::{self, spawn}, + platform, }; /// Reason of why [`Room`] has been closed. @@ -306,15 +304,18 @@ impl RoomHandle { /// [`Connection`]: crate::api::Connection pub fn on_new_connection( &self, - f: js_sys::Function, - ) -> Result<(), JsValue> { + f: platform::Function, + ) -> Result<(), JasonError> { upgrade_or_detached!(self.0) .map(|inner| inner.connections.on_new_connection(f)) } /// Sets `on_close` callback, which will be invoked on [`Room`] close, /// providing [`RoomCloseReason`]. - pub fn on_close(&self, f: js_sys::Function) -> Result<(), JsValue> { + pub fn on_close( + &self, + f: platform::Function, + ) -> Result<(), JasonError> { upgrade_or_detached!(self.0).map(|inner| inner.on_close.set_func(f)) } @@ -324,7 +325,10 @@ impl RoomHandle { /// 1. Media server initiates media request. /// 2. `disable_audio`/`enable_video` is called. /// 3. [`MediaStreamSettings`] updated via `set_local_media_settings`. - pub fn on_local_track(&self, f: js_sys::Function) -> Result<(), JsValue> { + pub fn on_local_track( + &self, + f: platform::Function, + ) -> Result<(), JasonError> { upgrade_or_detached!(self.0) .map(|inner| inner.on_local_track.set_func(f)) } @@ -333,8 +337,8 @@ impl RoomHandle { /// media acquisition failures. pub fn on_failed_local_media( &self, - f: js_sys::Function, - ) -> Result<(), JsValue> { + f: platform::Function, + ) -> Result<(), JasonError> { upgrade_or_detached!(self.0) .map(|inner| inner.on_failed_local_media.set_func(f)) } @@ -343,8 +347,8 @@ impl RoomHandle { /// with server loss. pub fn on_connection_loss( &self, - f: js_sys::Function, - ) -> Result<(), JsValue> { + f: platform::Function, + ) -> Result<(), JasonError> { upgrade_or_detached!(self.0) .map(|inner| inner.on_connection_loss.set_func(f)) } @@ -617,7 +621,7 @@ impl Room { let room = Rc::new(InnerRoom::new(rpc, media_manager, tx)); let inner = Rc::downgrade(&room); - spawn(async move { + platform::spawn(async move { loop { let event: RoomEvent = futures::select! { event = rpc_events_stream.select_next_some() => event, @@ -732,19 +736,19 @@ struct InnerRoom { /// Callback to be invoked when new local [`local::JsTrack`] will be added /// to this [`Room`]. - on_local_track: Callback1, + on_local_track: platform::Callback, /// Callback to be invoked when failed obtain [`local::Track`]s from /// [`MediaManager`] or failed inject stream into [`PeerConnection`]. /// /// [`MediaManager`]: crate::media::MediaManager - on_failed_local_media: Rc>, + on_failed_local_media: Rc>, /// Callback to be invoked when [`RpcSession`] loses connection. - on_connection_loss: Callback1, + on_connection_loss: platform::Callback, /// JS callback which will be called when this [`Room`] will be closed. - on_close: Rc>, + on_close: Rc>, /// Reason of [`Room`] closing. /// @@ -770,12 +774,14 @@ impl ConstraintsUpdateException { /// `RecoveredException` or `RecoverFailedException`. /// /// Returns `undefined` otherwise. - pub fn recover_reason(&self) -> JsValue { + pub fn recover_reason(&self) -> Option { use JsConstraintsUpdateError as E; match &self.0 { E::RecoverFailed { recover_reason, .. } - | E::Recovered { recover_reason, .. } => recover_reason.clone(), - _ => JsValue::UNDEFINED, + | E::Recovered { recover_reason, .. } => { + Some(recover_reason.clone()) + } + _ => None, } } @@ -783,13 +789,13 @@ impl ConstraintsUpdateException { /// [`ConstraintsUpdateException`] represents `RecoverFailedException`. /// /// Returns `undefined` otherwise. - pub fn recover_fail_reasons(&self) -> JsValue { + pub fn recover_fail_reasons(&self) -> Vec { match &self.0 { JsConstraintsUpdateError::RecoverFailed { recover_fail_reasons, .. } => recover_fail_reasons.clone(), - _ => JsValue::UNDEFINED, + _ => Vec::new(), } } @@ -797,10 +803,12 @@ impl ConstraintsUpdateException { /// `ErroredException`. /// /// Returns `undefined` otherwise. - pub fn error(&self) -> JsValue { + pub fn error(&self) -> Option { match &self.0 { - JsConstraintsUpdateError::Errored { reason } => reason.clone(), - _ => JsValue::UNDEFINED, + JsConstraintsUpdateError::Errored { reason } => { + Some(reason.clone()) + } + _ => None, } } } @@ -817,7 +825,7 @@ pub enum JsConstraintsUpdateError { #[display(fmt = "RecoveredException")] Recovered { /// [`JasonError`] due to which recovery happened. - recover_reason: JsValue, + recover_reason: JasonError, }, /// New [`MediaStreamSettings`] set failed and state recovering also @@ -825,16 +833,16 @@ pub enum JsConstraintsUpdateError { #[display(fmt = "RecoverFailedException")] RecoverFailed { /// [`JasonError`] due to which recovery happened. - recover_reason: JsValue, + recover_reason: JasonError, /// [`js_sys::Array`] with a [`JasonError`]s due to which recovery /// failed. - recover_fail_reasons: JsValue, + recover_fail_reasons: Vec, }, /// Some another error occurred. #[display(fmt = "ErroredException")] - Errored { reason: JsValue }, + Errored { reason: JasonError }, } /// Constraints errors which are can occur while updating @@ -914,12 +922,10 @@ impl From for JsConstraintsUpdateError { } => Self::RecoverFailed { recover_reason: JasonError::from(recover_reason).into(), recover_fail_reasons: { - let arr = js_sys::Array::new(); - for e in recover_fail_reasons { - arr.push(&JasonError::from(e).into()); - } - - arr.into() + recover_fail_reasons + .into_iter() + .map(JasonError::from) + .collect() }, }, E::Errored { error: reason } => Self::Errored { @@ -956,10 +962,10 @@ impl InnerRoom { send_constraints, recv_constraints, connections, - on_connection_loss: Callback1::default(), - on_failed_local_media: Rc::new(Callback1::default()), - on_local_track: Callback1::default(), - on_close: Rc::new(Callback1::default()), + on_connection_loss: platform::Callback::default(), + on_failed_local_media: Rc::new(platform::Callback::default()), + on_local_track: platform::Callback::default(), + on_close: Rc::new(platform::Callback::default()), close_reason: RefCell::new(CloseReason::ByClient { reason: ClientDisconnect::RoomUnexpectedlyDropped, is_err: true, @@ -1156,14 +1162,14 @@ impl InnerRoom { .map_err(tracerr::map_from_and_wrap!()) .map_err(|e| { self.on_failed_local_media - .call(JasonError::from(e.clone())); + .call1(JasonError::from(e.clone())); e })?; for (track, is_new) in tracks { if is_new { self.on_local_track - .call(local::LocalMediaTrack::new(Rc::clone(&track))); + .call1(local::LocalMediaTrack::new(Rc::clone(&track))); } result.push(track); } @@ -1347,7 +1353,7 @@ impl InnerRoom { fn handle_rpc_connection_lost(&self) { self.peers.connection_lost(); self.on_connection_loss - .call(ReconnectHandle::new(Rc::downgrade(&self.rpc))); + .call1(ReconnectHandle::new(Rc::downgrade(&self.rpc))); } /// Sends [`Command::SynchronizeMe`] with a current Client state to the @@ -1394,7 +1400,7 @@ impl EventHandler for InnerRoom { .insert_track(track, self.send_constraints.clone()) .map_err(|e| { self.on_failed_local_media - .call(JasonError::from(e.clone())); + .call1(JasonError::from(e.clone())); tracerr::map_from_and_new!(e) })?; } @@ -1486,7 +1492,7 @@ impl EventHandler for InnerRoom { .insert_track(&track, self.send_constraints.clone()) .map_err(|e| { self.on_failed_local_media - .call(JasonError::from(e.clone())); + .call1(JasonError::from(e.clone())); tracerr::map_from_and_new!(e) })?, TrackUpdate::Updated(track_patch) => { @@ -1593,7 +1599,8 @@ impl PeerEventHandler for InnerRoom { &self, track: Rc, ) -> Self::Output { - self.on_local_track.call(local::LocalMediaTrack::new(track)); + self.on_local_track + .call1(local::LocalMediaTrack::new(track)); Ok(()) } @@ -1648,7 +1655,7 @@ impl PeerEventHandler for InnerRoom { /// Handles [`PeerEvent::FailedLocalMedia`] event by invoking /// `on_failed_local_media` [`Room`]'s callback. async fn on_failed_local_media(&self, error: JasonError) -> Self::Output { - self.on_failed_local_media.call(error); + self.on_failed_local_media.call1(error); Ok(()) } @@ -1706,12 +1713,8 @@ impl Drop for InnerRoom { self.rpc.close_with_reason(reason); }; - if let Some(Err(e)) = self - .on_close - .call(RoomCloseReason::new(*self.close_reason.borrow())) - { - log::error!("Failed to call Room::on_close callback: {:?}", e); - } + self.on_close + .call1(RoomCloseReason::new(*self.close_reason.borrow())); } } diff --git a/jason/src/core/rpc/backoff_delayer.rs b/jason/src/core/rpc/backoff_delayer.rs index cf84030fb..eeac0b14c 100644 --- a/jason/src/core/rpc/backoff_delayer.rs +++ b/jason/src/core/rpc/backoff_delayer.rs @@ -2,7 +2,7 @@ use std::time::Duration; -use crate::platform::delay_for; +use crate::platform; /// Delayer that increases delay time by provided multiplier on each call. /// @@ -35,7 +35,7 @@ impl BackoffDelayer { Self { current_interval: starting_interval, max_interval, - interval_multiplier, + interval_multiplier: interval_multiplier.max(0_f32), } } @@ -46,7 +46,7 @@ impl BackoffDelayer { /// [`BackoffDelayer::interval_multiplier`] milliseconds, /// until [`BackoffDelayer::max_interval`] is reached. pub async fn delay(&mut self) { - delay_for(self.get_delay()).await; + platform::delay_for(self.get_delay()).await; } /// Returns current interval and increases it for next call. diff --git a/jason/src/core/rpc/heartbeat.rs b/jason/src/core/rpc/heartbeat.rs index d0b99a95b..9f98eddb8 100644 --- a/jason/src/core/rpc/heartbeat.rs +++ b/jason/src/core/rpc/heartbeat.rs @@ -8,16 +8,13 @@ use medea_client_api_proto::{ClientMsg, ServerMsg}; use crate::{ core::utils::{JsCaused, TaskHandle}, - platform::{ - self, delay_for, spawn, - transport::{RpcTransport, TransportError}, - }, + platform, }; /// Errors that may occur in [`Heartbeat`]. #[derive(Clone, Debug, Display, From, JsCaused)] #[js(error = "platform::Error")] -pub struct HeartbeatError(TransportError); +pub struct HeartbeatError(platform::TransportError); /// Idle timeout of [`WebSocketRpcClient`]. /// @@ -34,7 +31,7 @@ pub struct PingInterval(pub Duration); /// Inner data of [`Heartbeat`]. struct Inner { /// [`RpcTransport`] which heartbeats. - transport: Rc, + transport: Rc, /// Idle timeout of [`RpcTransport`]. idle_timeout: IdleTimeout, @@ -65,7 +62,7 @@ impl Inner { fn send_pong(&self, n: u32) { self.transport .send(&ClientMsg::Pong(n)) - .map_err(tracerr::wrap!(=> TransportError)) + .map_err(tracerr::wrap!(=> platform::TransportError)) .map_err(|e| log::error!("Failed to send pong: {}", e)) .ok(); } @@ -78,7 +75,7 @@ impl Heartbeat { /// Start this [`Heartbeat`] for the provided [`RpcTransport`] with /// the provided `idle_timeout` and `ping_interval`. pub fn start( - transport: Rc, + transport: Rc, ping_interval: PingInterval, idle_timeout: IdleTimeout, ) -> Self { @@ -132,19 +129,19 @@ fn spawn_idle_watchdog_task(this: Rc>) -> TaskHandle { let (idle_watchdog_fut, idle_watchdog_handle) = future::abortable(async move { let wait_for_ping = this.borrow().ping_interval * 2; - delay_for(wait_for_ping.0).await; + platform::delay_for(wait_for_ping.0).await; let last_ping_num = this.borrow().last_ping_num; this.borrow().send_pong(last_ping_num + 1); let idle_timeout = this.borrow().idle_timeout; - delay_for(idle_timeout.0 - wait_for_ping.0).await; + platform::delay_for(idle_timeout.0 - wait_for_ping.0).await; this.borrow_mut() .on_idle_subs .retain(|sub| sub.unbounded_send(()).is_ok()); }); - spawn(async move { + platform::spawn(async move { idle_watchdog_fut.await.ok(); }); @@ -169,7 +166,7 @@ fn spawn_ping_handle_task(this: Rc>) -> TaskHandle { } } }); - spawn(async move { + platform::spawn(async move { handle_ping_fut.await.ok(); }); handle_ping_task.into() diff --git a/jason/src/core/rpc/mod.rs b/jason/src/core/rpc/mod.rs index 5327cc492..375a9cbc9 100644 --- a/jason/src/core/rpc/mod.rs +++ b/jason/src/core/rpc/mod.rs @@ -15,10 +15,7 @@ use medea_client_api_proto::{ use tracerr::Traced; use url::Url; -use crate::{ - core::utils::JsCaused, - platform::{self, transport::TransportError}, -}; +use crate::{core::utils::JsCaused, platform}; #[cfg(feature = "mockable")] pub use self::rpc_session::MockRpcSession; @@ -30,7 +27,7 @@ pub use self::{ rpc_session::{ RpcSession, SessionError, SessionState, WebSocketRpcSession, }, - websocket::{ClientDisconnect, WebSocketRpcClient}, + websocket::{ClientDisconnect, RpcEvent, WebSocketRpcClient}, }; /// [`Url`] to which transport layer will connect. @@ -167,7 +164,7 @@ pub enum ClosedStateReason { ConnectionLost(CloseMsg), /// Error while creating connection between client and server. - ConnectionFailed(TransportError), + ConnectionFailed(platform::TransportError), /// Indicates that connection with server has never been established. NeverConnected, @@ -190,7 +187,7 @@ pub enum ClosedStateReason { pub enum RpcClientError { /// Occurs if WebSocket connection to remote media server failed. #[display(fmt = "Connection failed: {}", _0)] - RpcTransportError(#[js(cause)] TransportError), + RpcTransportError(#[js(cause)] platform::TransportError), /// Occurs if the heartbeat cannot be started. #[display(fmt = "Start heartbeat failed: {}", _0)] diff --git a/jason/src/core/rpc/reconnect_handle.rs b/jason/src/core/rpc/reconnect_handle.rs index a2847411f..e09bcfb40 100644 --- a/jason/src/core/rpc/reconnect_handle.rs +++ b/jason/src/core/rpc/reconnect_handle.rs @@ -9,7 +9,7 @@ use crate::{ rpc::{BackoffDelayer, RpcSession}, utils::{HandlerDetachedError, JasonError, JsCaused}, }, - platform::{self, delay_for}, + platform, }; /// Error which indicates that [`RpcSession`]'s (which this [`ReconnectHandle`] @@ -41,7 +41,8 @@ impl ReconnectHandle { &self, delay_ms: u32, ) -> Result<(), JasonError> { - delay_for(Duration::from_millis(u64::from(delay_ms)).into()).await; + platform::delay_for(Duration::from_millis(u64::from(delay_ms)).into()) + .await; let rpc = upgrade_or_detached!(self.0, JasonError)?; rpc.reconnect().await.map_err(|e| JasonError::from(e))?; diff --git a/jason/src/core/rpc/rpc_session.rs b/jason/src/core/rpc/rpc_session.rs index 2218604f1..645637718 100644 --- a/jason/src/core/rpc/rpc_session.rs +++ b/jason/src/core/rpc/rpc_session.rs @@ -24,7 +24,7 @@ use crate::{ }, utils::JsCaused, }, - platform::{self, spawn}, + platform, }; /// Errors which are can be returned from the [`WebSocketRpcSession`]. @@ -252,7 +252,7 @@ impl WebSocketRpcSession { let mut state_updates = self.state.subscribe(); let weak_this = Rc::downgrade(self); - spawn(async move { + platform::spawn(async move { while let Some(state) = state_updates.next().await { let this = upgrade_or_break!(weak_this); match state { @@ -293,7 +293,7 @@ impl WebSocketRpcSession { let mut client_on_connection_loss = self.client.on_connection_loss(); let weak_this = Rc::downgrade(self); - spawn(async move { + platform::spawn(async move { while client_on_connection_loss.next().await.is_some() { let this = upgrade_or_break!(weak_this); @@ -325,7 +325,7 @@ impl WebSocketRpcSession { fn spawn_close_watcher(self: &Rc) { let on_normal_close = self.client.on_normal_close(); let weak_this = Rc::downgrade(self); - spawn(async move { + platform::spawn(async move { let reason = on_normal_close.await.unwrap_or_else(|_| { ClientDisconnect::RpcClientUnexpectedlyDropped.into() }); @@ -339,7 +339,7 @@ impl WebSocketRpcSession { fn spawn_server_msg_listener(self: &Rc) { let mut server_msg_rx = self.client.subscribe(); let weak_this = Rc::downgrade(self); - spawn(async move { + platform::spawn(async move { while let Some(msg) = server_msg_rx.next().await { let this = upgrade_or_break!(weak_this); msg.dispatch_with(this.as_ref()); diff --git a/jason/src/core/rpc/websocket/client.rs b/jason/src/core/rpc/websocket/client.rs index 685c50d65..8138a0c09 100644 --- a/jason/src/core/rpc/websocket/client.rs +++ b/jason/src/core/rpc/websocket/client.rs @@ -23,10 +23,7 @@ use crate::{ }, utils::JasonError, }, - platform::{ - spawn, - transport::{RpcTransport, TransportError, TransportState}, - }, + platform, }; /// Reasons of closing WebSocket RPC connection by a client side. @@ -100,7 +97,7 @@ pub enum ClientState { /// Inner state of [`WebSocketRpcClient`]. struct Inner { /// Transport connection with remote media server. - sock: Option>, + sock: Option>, /// Connection loss detector via ping/pong mechanism. heartbeat: Option, @@ -143,7 +140,10 @@ pub type RpcTransportFactory = Box< ApiUrl, ) -> LocalBoxFuture< 'static, - Result, Traced>, + Result< + Rc, + Traced, + >, >, >; @@ -342,7 +342,7 @@ impl WebSocketRpcClient { /// [`RpcTransport`]. async fn start_heartbeat( self: Rc, - transport: Rc, + transport: Rc, rpc_settings: RpcSettings, ) -> Result<(), Traced> { let idle_timeout = IdleTimeout( @@ -357,7 +357,7 @@ impl WebSocketRpcClient { let mut on_idle = heartbeat.on_idle(); let weak_this = Rc::downgrade(&self); - spawn(async move { + platform::spawn(async move { while on_idle.next().await.is_some() { if let Some(this) = weak_this.upgrade() { this.handle_connection_loss(ClosedStateReason::Idle); @@ -416,10 +416,10 @@ impl WebSocketRpcClient { // subscribe to transport close let mut transport_state_changes = transport.on_state_change(); let weak_this = Rc::downgrade(&self); - spawn(async move { + platform::spawn(async move { while let Some(state) = transport_state_changes.next().await { if let Some(this) = weak_this.upgrade() { - if let TransportState::Closed(msg) = state { + if let platform::TransportState::Closed(msg) = state { this.handle_close_message(msg); } } @@ -429,7 +429,7 @@ impl WebSocketRpcClient { // subscribe to transport message received let weak_this = Rc::downgrade(&self); let mut on_socket_message = transport.on_message(); - spawn(async move { + platform::spawn(async move { while let Some(msg) = on_socket_message.next().await { if let Some(this) = weak_this.upgrade() { this.on_transport_message(msg) diff --git a/jason/src/core/rpc/websocket/mod.rs b/jason/src/core/rpc/websocket/mod.rs index 943e168c9..d5d893a4e 100644 --- a/jason/src/core/rpc/websocket/mod.rs +++ b/jason/src/core/rpc/websocket/mod.rs @@ -9,5 +9,3 @@ pub use self::client::{ ClientDisconnect, ClientState, RpcEvent, RpcEventHandler, RpcTransportFactory, WebSocketRpcClient, }; -#[cfg(feature = "mockable")] -pub use self::transport::MockRpcTransport; diff --git a/jason/src/core/utils/callback.rs b/jason/src/core/utils/callback.rs deleted file mode 100644 index 3b0390607..000000000 --- a/jason/src/core/utils/callback.rs +++ /dev/null @@ -1,86 +0,0 @@ -//! Somewhat convenient wrappers around JS functions used as callbacks. - -use std::{cell::RefCell, marker::PhantomData}; - -use js_sys::Function as JsFunction; - -/// Wrapper for JS function with no arguments. -#[derive(Default)] -pub struct Callback0 { - f: RefCell>, -} - -impl Callback0 { - /// Sets inner JS function. - #[inline] - pub fn set_func(&self, f: JsFunction) { - self.f.borrow_mut().replace(f); - } - - /// Invokes JS function if any. - /// - /// Returns `None` if no callback is set, otherwise returns its invocation - /// result. - pub fn call(&self) -> Option> { - self.f.borrow().as_ref().map(|f| f.call0(&JsValue::NULL)) - } - - /// Indicates whether callback is set. - #[inline] - pub fn is_set(&self) -> bool { - self.f.borrow().as_ref().is_some() - } -} - -/// Wrapper for a single argument JS function. -pub struct Callback1 { - f: RefCell>, - _arg: PhantomData, -} - -impl Default for Callback1 { - #[inline] - fn default() -> Self { - Self { - f: RefCell::new(None), - _arg: PhantomData, - } - } -} - -impl Callback1 { - /// Sets inner JS function. - #[inline] - pub fn set_func(&self, f: JsFunction) { - self.f.borrow_mut().replace(f); - } - - /// Indicates if callback is set. - #[inline] - pub fn is_set(&self) -> bool { - self.f.borrow().as_ref().is_some() - } -} - -impl> Callback1 { - /// Invokes JS function if any. - /// - /// Returns `None` if no callback is set, otherwise returns its invocation - /// result. - pub fn call>(&self, arg: T) -> Option> { - self.f - .borrow() - .as_ref() - .map(|f| f.call1(&JsValue::NULL, &arg.into().into())) - } -} - -impl From for Callback1 { - #[inline] - fn from(f: JsFunction) -> Self { - Self { - f: RefCell::new(Some(f)), - _arg: PhantomData, - } - } -} diff --git a/jason/src/core/utils/component.rs b/jason/src/core/utils/component.rs index ea0b65f84..705c6e9ae 100644 --- a/jason/src/core/utils/component.rs +++ b/jason/src/core/utils/component.rs @@ -11,7 +11,7 @@ use crate::{ media::LocalTracksConstraints, utils::{JasonError, TaskHandle}, }, - platform::spawn, + platform, }; /// Abstraction over a state which can be transformed to the states from the @@ -139,7 +139,7 @@ impl WatchersSpawner { } } }); - spawn(fut.map(|_| ())); + platform::spawn(fut.map(|_| ())); self.spawned_watchers.push(handle.into()); } diff --git a/jason/src/core/utils/errors.rs b/jason/src/core/utils/errors.rs index 88e457ca3..23adb8e52 100644 --- a/jason/src/core/utils/errors.rs +++ b/jason/src/core/utils/errors.rs @@ -5,7 +5,6 @@ use std::{ use derive_more::{Display, From}; use tracerr::{Trace, Traced}; -use wasm_bindgen::prelude::*; use crate::platform; @@ -27,7 +26,6 @@ pub trait JsCaused { /// Representation of app error exported to JS side. /// /// Contains JS side error if it the cause and trace information. -#[wasm_bindgen] #[derive(Clone, Debug, Display)] #[display(fmt = "{}: {}\n{}", name, message, trace)] pub struct JasonError { @@ -37,14 +35,6 @@ pub struct JasonError { source: Option, } -impl JasonError { - /// Prints error information to `console.error()`. - pub fn print(&self) { - log::error!("{}", self); - } -} - -#[wasm_bindgen] impl JasonError { /// Returns name of error. pub fn name(&self) -> String { @@ -65,6 +55,11 @@ impl JasonError { pub fn source(&self) -> Option { Clone::clone(&self.source) } + + /// Prints error information to `console.error()`. + pub fn print(&self) { + log::error!("{}", self); + } } impl From<(E, Trace)> for JasonError diff --git a/jason/src/core/utils/mod.rs b/jason/src/core/utils/mod.rs index f51894e66..a6a666d0f 100644 --- a/jason/src/core/utils/mod.rs +++ b/jason/src/core/utils/mod.rs @@ -3,7 +3,6 @@ #[macro_use] mod errors; -mod callback; pub mod component; mod resettable_delay; @@ -15,7 +14,6 @@ use medea_reactive::Guarded; #[doc(inline)] pub use self::{ - callback::{Callback0, Callback1}, component::{AsProtoState, Component, SynchronizableState, Updatable}, errors::{HandlerDetachedError, JasonError, JsCaused, JsonParseError}, resettable_delay::{resettable_delay_for, ResettableDelayHandle}, diff --git a/jason/src/core/utils/resettable_delay.rs b/jason/src/core/utils/resettable_delay.rs index 098eb1a78..22a6d64c1 100644 --- a/jason/src/core/utils/resettable_delay.rs +++ b/jason/src/core/utils/resettable_delay.rs @@ -8,7 +8,7 @@ use futures::{ future::{AbortHandle, FutureExt}, }; -use crate::platform::{delay_for, spawn}; +use crate::platform; type FutureResolver = Rc>>>; @@ -83,12 +83,12 @@ impl ResettableDelayHandle { let future_resolver = self.future_resolver.clone(); let timeout = self.timeout; let (fut, abort) = future::abortable(async move { - delay_for(timeout.into()).await; + platform::delay_for(timeout.into()).await; if let Some(rsvr) = future_resolver.borrow_mut().take() { let _ = rsvr.send(()); } }); - spawn(fut.map(|_| ())); + platform::spawn(fut.map(|_| ())); self.abort_handle.replace(abort); } diff --git a/jason/src/lib.rs b/jason/src/lib.rs index a389e0a0e..67bd19c06 100644 --- a/jason/src/lib.rs +++ b/jason/src/lib.rs @@ -11,6 +11,6 @@ pub use self::core::utils; -mod api; -mod core; -mod platform; +pub mod api; +pub mod core; +pub mod platform; diff --git a/jason/src/platform/mod.rs b/jason/src/platform/mod.rs index 194d7d590..79f534532 100644 --- a/jason/src/platform/mod.rs +++ b/jason/src/platform/mod.rs @@ -3,155 +3,31 @@ // target_vendor = "unknown", // target_os = "unknown" // ))] -mod wasm; - -// #[cfg(all( -// target_arch = "wasm32", -// target_vendor = "unknown", -// target_os = "unknown" -// ))] -pub use wasm::{ - delay_for, enumerate_devices, get_display_media, get_property_by_name, - get_user_media, init_logger, - input_device_info::InputDeviceInfo, - media_track::MediaStreamTrack, - peer_connection::{ - IceCandidate, RTCPeerConnectionError, RtcPeerConnection, SdpType, +pub use self::{ + rtc_stats::RtcStatsError, + transport::{ + RpcTransport, TransportError, TransportState, WebSocketRpcTransport, }, - rtc_stats::{RtcStats, RtcStatsError}, - set_panic_hook, spawn, - transceiver::{Transceiver, TransceiverDirection}, - Error, -}; - -pub use web_sys::{ - ConstrainDomStringParameters, ConstrainDoubleRange, - DisplayMediaStreamConstraints, MediaDeviceInfo, MediaDeviceKind, - MediaStreamConstraints, MediaStreamTrackState, MediaTrackConstraints, -}; - -pub mod transport { - use derive_more::Display; - use futures::stream::LocalBoxStream; - use medea_client_api_proto::{ClientMsg, ServerMsg}; - use tracerr::Traced; - - pub use super::wasm::transport::WebSocketRpcTransport; - - use crate::{ - core::{ - rpc::{ClientDisconnect, CloseMsg}, - utils::JsonParseError, + wasm::{ + constraints::{DisplayMediaStreamConstraints, MediaStreamConstraints}, + delay_for, enumerate_devices, get_display_media, get_property_by_name, + get_user_media, init_logger, + input_device_info::InputDeviceInfo, + media_track::MediaStreamTrack, + peer_connection::{ + IceCandidate, RTCPeerConnectionError, RtcPeerConnection, SdpType, }, - platform::{self, wasm::utils::EventListenerBindError}, - utils::JsCaused, - }; - - /// [`RpcTransport`] states. - #[derive(Clone, Copy, Debug, PartialEq)] - pub enum TransportState { - /// Socket has been created. The connection is not open yet. - /// - /// Reflects `CONNECTING` state from JS side - /// [`WebSocket.readyState`][1]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState - Connecting, - - /// The connection is open and ready to communicate. - /// - /// Reflects `OPEN` state from JS side [`WebSocket.readyState`][1]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState - Open, - - /// The connection is in the process of closing. - /// - /// Reflects `CLOSING` state from JS side [`WebSocket.readyState`][1]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState - Closing, - - /// The connection is closed or couldn't be opened. - /// - /// Reflects `CLOSED` state from JS side [`WebSocket.readyState`][1]. - /// - /// [`CloseMsg`] is the reason of why [`RpcTransport`] went into - /// this [`TransportState`]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState - Closed(CloseMsg), - } - - impl TransportState { - /// Returns `true` if socket can be closed. - pub fn can_close(self) -> bool { - matches!(self, Self::Connecting | Self::Open) - } - } - - /// RPC transport between a client and a server. - #[cfg_attr(feature = "mockable", mockall::automock)] - pub trait RpcTransport { - /// Returns [`LocalBoxStream`] of all messages received by this - /// transport. - fn on_message(&self) -> LocalBoxStream<'static, ServerMsg>; - - /// Sets reason, that will be sent to remote server when this transport - /// will be dropped. - fn set_close_reason(&self, reason: ClientDisconnect); - - /// Sends given [`ClientMsg`] to a server. - /// - /// # Errors - /// - /// Errors if sending [`ClientMsg`] fails. - fn send(&self, msg: &ClientMsg) -> Result<(), Traced>; - - /// Subscribes to a [`RpcTransport`]'s [`TransportState`] changes. - fn on_state_change(&self) -> LocalBoxStream<'static, TransportState>; - } - - /// Errors that may occur when working with [`WebSocketRpcClient`]. - /// - /// [`WebSocketRpcClient`]: super::WebSocketRpcClient - #[derive(Clone, Debug, Display, JsCaused, PartialEq)] - #[js(error = "platform::Error")] - pub enum TransportError { - /// Occurs when the port to which the connection is being attempted - /// is being blocked. - #[display(fmt = "Failed to create WebSocket: {}", _0)] - CreateSocket(platform::Error), - - /// Occurs when the connection close before becomes state active. - #[display(fmt = "Failed to init WebSocket")] - InitSocket, - - /// Occurs when [`ClientMsg`] cannot be parsed. - #[display(fmt = "Failed to parse client message: {}", _0)] - ParseClientMessage(JsonParseError), - - /// Occurs when [`ServerMsg`] cannot be parsed. - #[display(fmt = "Failed to parse server message: {}", _0)] - ParseServerMessage(JsonParseError), - - /// Occurs if the parsed message is not string. - #[display(fmt = "Message is not a string")] - MessageNotString, - - /// Occurs when a message cannot be send to server. - #[display(fmt = "Failed to send message: {}", _0)] - SendMessage(platform::Error), + rtc_stats::RtcStats, + set_panic_hook, spawn, + transceiver::{Transceiver, TransceiverDirection}, + utils::{Callback, EventListener, EventListenerBindError, Function}, + Error, + }, +}; - /// Occurs when handler failed to bind to some [WebSocket] event. Not - /// really supposed to ever happen. - /// - /// [WebSocket]: https://developer.mozilla.org/ru/docs/WebSockets - #[display(fmt = "Failed to bind to WebSocket event: {}", _0)] - WebSocketEventBindError(EventListenerBindError), // TODO: remove +#[cfg(feature = "mockable")] +pub use self::transport::MockRpcTransport; - /// Occurs when message is sent to a closed socket. - #[display(fmt = "Underlying socket is closed")] - ClosedSocket, - } -} +mod rtc_stats; +mod transport; +mod wasm; diff --git a/jason/src/platform/rtc_stats.rs b/jason/src/platform/rtc_stats.rs new file mode 100644 index 000000000..3c38a1951 --- /dev/null +++ b/jason/src/platform/rtc_stats.rs @@ -0,0 +1,34 @@ +use std::rc::Rc; + +use derive_more::{Display, From}; + +use crate::{platform, utils::JsCaused}; + +/// Errors which can occur during deserialization of the [`RtcStatsType`]. +#[derive(Clone, Debug, Display, From, JsCaused)] +#[js(error = "platform::Error")] +pub enum RtcStatsError { + /// [RTCStats.id][1] is undefined. + /// + /// [1]: https://w3.org/TR/webrtc/#dom-rtcstats-id + #[display(fmt = "RTCStats.id is undefined")] + UndefinedId, + + /// [RTCStats.stats] is undefined. + /// + /// [1]: https://w3.org/TR/webrtc-stats/#dfn-stats-object + #[display(fmt = "RTCStats.stats is undefined")] + UndefinedStats, + + /// Some JS error occurred. + #[display(fmt = "Unexpected JS side error: {}", _0)] + Js(platform::Error), + + /// `RTCStats.entries` is undefined. + #[display(fmt = "RTCStats.entries is undefined")] + UndefinedEntries, + + /// Error of [`RtcStats`] deserialization. + #[display(fmt = "Failed to deserialize into RtcStats: {}", _0)] + ParseError(Rc), +} diff --git a/jason/src/platform/transport.rs b/jason/src/platform/transport.rs new file mode 100644 index 000000000..b9998bbfd --- /dev/null +++ b/jason/src/platform/transport.rs @@ -0,0 +1,123 @@ +use derive_more::Display; +use futures::stream::LocalBoxStream; +use medea_client_api_proto::{ClientMsg, ServerMsg}; +use tracerr::Traced; + +use crate::{ + core::{ + rpc::{ClientDisconnect, CloseMsg}, + utils::JsonParseError, + }, + platform::{self, wasm::utils::EventListenerBindError}, + utils::JsCaused, +}; + +pub use super::wasm::transport::WebSocketRpcTransport; + +/// [`RpcTransport`] states. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum TransportState { + /// Socket has been created. The connection is not open yet. + /// + /// Reflects `CONNECTING` state from JS side + /// [`WebSocket.readyState`][1]. + /// + /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState + Connecting, + + /// The connection is open and ready to communicate. + /// + /// Reflects `OPEN` state from JS side [`WebSocket.readyState`][1]. + /// + /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState + Open, + + /// The connection is in the process of closing. + /// + /// Reflects `CLOSING` state from JS side [`WebSocket.readyState`][1]. + /// + /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState + Closing, + + /// The connection is closed or couldn't be opened. + /// + /// Reflects `CLOSED` state from JS side [`WebSocket.readyState`][1]. + /// + /// [`CloseMsg`] is the reason of why [`RpcTransport`] went into + /// this [`TransportState`]. + /// + /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState + Closed(CloseMsg), +} + +impl TransportState { + /// Returns `true` if socket can be closed. + pub fn can_close(self) -> bool { + matches!(self, Self::Connecting | Self::Open) + } +} + +/// RPC transport between a client and a server. +#[cfg_attr(feature = "mockable", mockall::automock)] +pub trait RpcTransport { + /// Returns [`LocalBoxStream`] of all messages received by this + /// transport. + fn on_message(&self) -> LocalBoxStream<'static, ServerMsg>; + + /// Sets reason, that will be sent to remote server when this transport + /// will be dropped. + fn set_close_reason(&self, reason: ClientDisconnect); + + /// Sends given [`ClientMsg`] to a server. + /// + /// # Errors + /// + /// Errors if sending [`ClientMsg`] fails. + fn send(&self, msg: &ClientMsg) -> Result<(), Traced>; + + /// Subscribes to a [`RpcTransport`]'s [`TransportState`] changes. + fn on_state_change(&self) -> LocalBoxStream<'static, TransportState>; +} + +/// Errors that may occur when working with [`WebSocketRpcClient`]. +/// +/// [`WebSocketRpcClient`]: super::WebSocketRpcClient +#[derive(Clone, Debug, Display, JsCaused, PartialEq)] +#[js(error = "platform::Error")] +pub enum TransportError { + /// Occurs when the port to which the connection is being attempted + /// is being blocked. + #[display(fmt = "Failed to create WebSocket: {}", _0)] + CreateSocket(platform::Error), + + /// Occurs when the connection close before becomes state active. + #[display(fmt = "Failed to init WebSocket")] + InitSocket, + + /// Occurs when [`ClientMsg`] cannot be parsed. + #[display(fmt = "Failed to parse client message: {}", _0)] + ParseClientMessage(JsonParseError), + + /// Occurs when [`ServerMsg`] cannot be parsed. + #[display(fmt = "Failed to parse server message: {}", _0)] + ParseServerMessage(JsonParseError), + + /// Occurs if the parsed message is not string. + #[display(fmt = "Message is not a string")] + MessageNotString, + + /// Occurs when a message cannot be send to server. + #[display(fmt = "Failed to send message: {}", _0)] + SendMessage(platform::Error), + + /// Occurs when handler failed to bind to some [WebSocket] event. Not + /// really supposed to ever happen. + /// + /// [WebSocket]: https://developer.mozilla.org/ru/docs/WebSockets + #[display(fmt = "Failed to bind to WebSocket event: {}", _0)] + WebSocketEventBindError(EventListenerBindError), // TODO: remove + + /// Occurs when message is sent to a closed socket. + #[display(fmt = "Underlying socket is closed")] + ClosedSocket, +} diff --git a/jason/src/platform/wasm/constraints.rs b/jason/src/platform/wasm/constraints.rs new file mode 100644 index 000000000..8ac6b95a9 --- /dev/null +++ b/jason/src/platform/wasm/constraints.rs @@ -0,0 +1,118 @@ +use crate::core::media::{ + constraints::{ConstrainString, ConstrainU32}, + AudioTrackConstraints, DeviceVideoTrackConstraints, + DisplayVideoTrackConstraints, +}; +use derive_more::{AsRef, Into}; +use web_sys::{ + ConstrainDomStringParameters, ConstrainDoubleRange, MediaTrackConstraints, +}; + +#[derive(AsRef, Debug, Into)] +pub struct MediaStreamConstraints(web_sys::MediaStreamConstraints); + +impl MediaStreamConstraints { + pub fn new() -> Self { + Self(web_sys::MediaStreamConstraints::new()) + } + + pub fn audio(&mut self, audio: AudioTrackConstraints) { + self.0.audio(&MediaTrackConstraints::from(audio).into()); + } + + pub fn video(&mut self, video: DeviceVideoTrackConstraints) { + self.0.video(&MediaTrackConstraints::from(video).into()); + } +} + +impl From for MediaTrackConstraints { + fn from(track_constraints: AudioTrackConstraints) -> Self { + let mut constraints = Self::new(); + + if let Some(device_id) = track_constraints.device_id { + constraints + .device_id(&ConstrainDomStringParameters::from(&device_id)); + } + + constraints + } +} + +impl From for MediaTrackConstraints { + fn from(track_constraints: DeviceVideoTrackConstraints) -> Self { + let mut constraints = Self::new(); + + if let Some(device_id) = track_constraints.device_id { + constraints + .device_id(&ConstrainDomStringParameters::from(&device_id)); + } + if let Some(facing_mode) = track_constraints.facing_mode { + constraints + .facing_mode(&ConstrainDomStringParameters::from(&facing_mode)); + } + if let Some(width) = track_constraints.width { + constraints.width(&ConstrainDoubleRange::from(width)); + } + if let Some(height) = track_constraints.height { + constraints.height(&ConstrainDoubleRange::from(height)); + } + + constraints + } +} + +impl From for ConstrainDoubleRange { + fn from(from: ConstrainU32) -> Self { + let mut constraint = ConstrainDoubleRange::new(); + match from { + ConstrainU32::Exact(val) => { + constraint.exact(f64::from(val)); + } + ConstrainU32::Ideal(val) => { + constraint.ideal(f64::from(val)); + } + ConstrainU32::Range(min, max) => { + constraint.min(f64::from(min)).max(f64::from(max)); + } + } + + constraint + } +} + +impl> From<&ConstrainString> for ConstrainDomStringParameters { + fn from(from: &ConstrainString) -> Self { + let mut constraint = ConstrainDomStringParameters::new(); + match from { + ConstrainString::Exact(val) => { + constraint.exact(&wasm_bindgen::JsValue::from_str(val.as_ref())) + } + ConstrainString::Ideal(val) => { + constraint.ideal(&wasm_bindgen::JsValue::from_str(val.as_ref())) + } + }; + + constraint + } +} + +#[derive(AsRef, Debug, Into)] +pub struct DisplayMediaStreamConstraints( + web_sys::DisplayMediaStreamConstraints, +); + +impl DisplayMediaStreamConstraints { + pub fn new() -> Self { + Self(web_sys::DisplayMediaStreamConstraints::new()) + } + + pub fn video(&mut self, video: DisplayVideoTrackConstraints) { + self.0.video(&MediaTrackConstraints::from(video).into()); + } +} + +impl From for MediaTrackConstraints { + fn from(_: DisplayVideoTrackConstraints) -> Self { + Self::new() + } +} diff --git a/jason/src/platform/wasm/input_device_info.rs b/jason/src/platform/wasm/input_device_info.rs index 700ece3e8..7a7e265c6 100644 --- a/jason/src/platform/wasm/input_device_info.rs +++ b/jason/src/platform/wasm/input_device_info.rs @@ -5,8 +5,9 @@ use std::convert::TryFrom; use derive_more::Display; +use web_sys as sys; -use crate::{core::media::MediaKind, platform}; +use crate::core; /// Errors that may occur when parsing [MediaDeviceInfo][1]. /// @@ -22,21 +23,21 @@ pub enum Error { /// /// [1]: https://w3.org/TR/mediacapture-streams/#device-info pub struct InputDeviceInfo { - media_kind: MediaKind, + media_kind: core::MediaKind, /// Actual underlying [MediaDeviceInfo][1] object. /// /// [1]: https://w3.org/TR/mediacapture-streams/#device-info - info: platform::MediaDeviceInfo, + info: sys::MediaDeviceInfo, } -impl TryFrom for MediaKind { +impl TryFrom for core::MediaKind { type Error = Error; - fn try_from(value: platform::MediaDeviceKind) -> Result { + fn try_from(value: sys::MediaDeviceKind) -> Result { match value { - platform::MediaDeviceKind::Audioinput => Ok(Self::Audio), - platform::MediaDeviceKind::Videoinput => Ok(Self::Video), + sys::MediaDeviceKind::Audioinput => Ok(Self::Audio), + sys::MediaDeviceKind::Videoinput => Ok(Self::Video), _ => Err(Error::NotInputDevice), } } @@ -53,7 +54,7 @@ impl InputDeviceInfo { /// This representation of [MediaDeviceInfo][1] ONLY for input device. /// /// [1]: https://w3.org/TR/mediacapture-streams/#device-info - pub fn kind(&self) -> MediaKind { + pub fn kind(&self) -> core::MediaKind { self.media_kind } @@ -77,12 +78,12 @@ impl InputDeviceInfo { } } -impl TryFrom for InputDeviceInfo { +impl TryFrom for InputDeviceInfo { type Error = Error; - fn try_from(info: platform::MediaDeviceInfo) -> Result { + fn try_from(info: sys::MediaDeviceInfo) -> Result { Ok(Self { - media_kind: MediaKind::try_from(info.kind())?, + media_kind: core::MediaKind::try_from(info.kind())?, info, }) } diff --git a/jason/src/platform/wasm/media_track.rs b/jason/src/platform/wasm/media_track.rs index 68d8524f5..e329ca5d8 100644 --- a/jason/src/platform/wasm/media_track.rs +++ b/jason/src/platform/wasm/media_track.rs @@ -1,6 +1,6 @@ use derive_more::AsRef; -use crate::{api::FacingMode, core, platform::get_property_by_name}; +use crate::{api, core, platform::get_property_by_name}; #[derive(AsRef, Clone, Debug)] pub struct MediaStreamTrack { @@ -35,27 +35,38 @@ impl MediaStreamTrack { self.kind } - pub fn ready_state(&self) -> web_sys::MediaStreamTrackState { - self.sys_track.ready_state() + pub fn ready_state(&self) -> core::MediaStreamTrackState { + let state = self.sys_track.ready_state(); + match state { + web_sys::MediaStreamTrackState::Live => { + core::MediaStreamTrackState::Live + } + web_sys::MediaStreamTrackState::Ended => { + core::MediaStreamTrackState::Ended + } + web_sys::MediaStreamTrackState::__Nonexhaustive => { + unreachable!("Unknown MediaStreamTrackState::{:?}", state) + } + } } pub fn device_id(&self) -> Option { - get_property_by_name(&self.sys_track.get_settings(), "device_id", |v| { + get_property_by_name(&self.sys_track.get_settings(), "deviceId", |v| { v.as_string() }) } - pub fn facing_mode(&self) -> Option { + pub fn facing_mode(&self) -> Option { let facing_mode = get_property_by_name( &self.sys_track.get_settings(), "facingMode", |v| v.as_string(), ); facing_mode.and_then(|facing_mode| match facing_mode.as_ref() { - "user" => Some(FacingMode::User), - "environment" => Some(FacingMode::Environment), - "left" => Some(FacingMode::Left), - "right" => Some(FacingMode::Right), + "user" => Some(api::FacingMode::User), + "environment" => Some(api::FacingMode::Environment), + "left" => Some(api::FacingMode::Left), + "right" => Some(api::FacingMode::Right), _ => { // TODO: log err None diff --git a/jason/src/platform/wasm/mod.rs b/jason/src/platform/wasm/mod.rs index ffbd29dda..ea116a93b 100644 --- a/jason/src/platform/wasm/mod.rs +++ b/jason/src/platform/wasm/mod.rs @@ -4,6 +4,7 @@ use std::{ time::Duration, }; +pub mod constraints; pub mod ice_server; pub mod input_device_info; pub mod media_track; @@ -119,7 +120,7 @@ pub async fn get_user_media( let stream = JsFuture::from( media_devices - .get_user_media_with_constraints(&caps) + .get_user_media_with_constraints(&caps.into()) .map_err(Error::from) .map_err(GetUserMediaFailed) .map_err(tracerr::from_and_wrap!())?, @@ -153,7 +154,7 @@ pub async fn get_display_media( let stream = JsFuture::from( media_devices - .get_display_media_with_constraints(&caps) + .get_display_media_with_constraints(&caps.into()) .map_err(Error::from) .map_err(GetDisplayMediaFailed) .map_err(tracerr::from_and_wrap!())?, diff --git a/jason/src/platform/wasm/rtc_stats.rs b/jason/src/platform/wasm/rtc_stats.rs index 3d2857eb9..891296419 100644 --- a/jason/src/platform/wasm/rtc_stats.rs +++ b/jason/src/platform/wasm/rtc_stats.rs @@ -4,7 +4,6 @@ use std::{convert::TryFrom, rc::Rc}; -use derive_more::{Display, From}; use js_sys::{ Array as JsArray, Function as JsFunction, Iterator as JsIterator, JsString, }; @@ -12,41 +11,7 @@ use medea_client_api_proto::stats::{RtcStat, RtcStatsType}; use tracerr::Traced; use wasm_bindgen::{prelude::*, JsCast}; -use crate::{ - core::utils::JsCaused, - platform::{self, *}, -}; - -/// Entry of the JS RTC stats dictionary. -struct RtcStatsReportEntry(JsString, JsValue); - -impl TryFrom for RtcStatsReportEntry { - type Error = Traced; - - fn try_from(value: JsArray) -> Result { - use RtcStatsError::{Js, UndefinedId, UndefinedStats}; - - let id = value.get(0); - let stats = value.get(1); - - if id.is_undefined() { - return Err(tracerr::new!(UndefinedId)); - } - - if stats.is_undefined() { - return Err(tracerr::new!(UndefinedStats)); - } - - let id = id - .dyn_into::() - .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; - let stats = stats - .dyn_into::() - .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; - - Ok(RtcStatsReportEntry(id, stats)) - } -} +use crate::platform::{self, get_property_by_name, RtcStatsError}; /// All available [`RtcStatsType`] of [`PeerConnection`]. /// @@ -94,32 +59,33 @@ impl TryFrom<&JsValue> for RtcStats { Ok(RtcStats(stats)) } } +/// Entry of the JS RTC stats dictionary. +struct RtcStatsReportEntry(JsString, JsValue); + +impl TryFrom for RtcStatsReportEntry { + type Error = Traced; + + fn try_from(value: JsArray) -> Result { + use RtcStatsError::{Js, UndefinedId, UndefinedStats}; + + let id = value.get(0); + let stats = value.get(1); + + if id.is_undefined() { + return Err(tracerr::new!(UndefinedId)); + } + + if stats.is_undefined() { + return Err(tracerr::new!(UndefinedStats)); + } -/// Errors which can occur during deserialization of the [`RtcStatsType`]. -#[derive(Clone, Debug, Display, From, JsCaused)] -#[js(error = "platform::Error")] -pub enum RtcStatsError { - /// [RTCStats.id][1] is undefined. - /// - /// [1]: https://w3.org/TR/webrtc/#dom-rtcstats-id - #[display(fmt = "RTCStats.id is undefined")] - UndefinedId, - - /// [RTCStats.stats] is undefined. - /// - /// [1]: https://w3.org/TR/webrtc-stats/#dfn-stats-object - #[display(fmt = "RTCStats.stats is undefined")] - UndefinedStats, - - /// Some JS error occurred. - #[display(fmt = "Unexpected JS side error: {}", _0)] - Js(platform::Error), - - /// `RTCStats.entries` is undefined. - #[display(fmt = "RTCStats.entries is undefined")] - UndefinedEntries, - - /// Error of [`RtcStats`] deserialization. - #[display(fmt = "Failed to deserialize into RtcStats: {}", _0)] - ParseError(Rc), + let id = id + .dyn_into::() + .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; + let stats = stats + .dyn_into::() + .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; + + Ok(RtcStatsReportEntry(id, stats)) + } } diff --git a/jason/src/platform/wasm/transceiver.rs b/jason/src/platform/wasm/transceiver.rs index 146796a85..4839939eb 100644 --- a/jason/src/platform/wasm/transceiver.rs +++ b/jason/src/platform/wasm/transceiver.rs @@ -221,7 +221,7 @@ mod tests { (D::all(), S::Sendrecv), (D::INACTIVE, S::Inactive), ] { - assert_eq!(S::from(*trnsv_dir), *sys_dir); + assert_eq!(S::from(*trnscvr_dir), *sys_dir); } } @@ -236,7 +236,7 @@ mod tests { (S::Sendrecv, D::all()), (S::Inactive, D::INACTIVE), ] { - assert_eq!(D::from(*sys_dir), *trnsv_dir); + assert_eq!(D::from(*sys_dir), *trnscvr_dir); } } } diff --git a/jason/src/platform/wasm/transport.rs b/jason/src/platform/wasm/transport.rs index 1b9ee0f22..6722a699f 100644 --- a/jason/src/platform/wasm/transport.rs +++ b/jason/src/platform/wasm/transport.rs @@ -32,7 +32,7 @@ impl From for TransportError { /// /// [1]: https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent #[derive(Clone, From, Into)] -pub struct ServerMessage(ServerMsg); +struct ServerMessage(ServerMsg); impl TryFrom<&MessageEvent> for ServerMessage { type Error = TransportError; diff --git a/jason/src/platform/wasm/utils/callback.rs b/jason/src/platform/wasm/utils/callback.rs new file mode 100644 index 000000000..421f1a6ad --- /dev/null +++ b/jason/src/platform/wasm/utils/callback.rs @@ -0,0 +1,45 @@ +//! Somewhat convenient wrappers around JS functions used as callbacks. + +use std::cell::RefCell; + +use crate::platform::Function; + +/// Wrapper for a single argument JS function. +pub struct Callback(RefCell>>); + +impl Default for Callback { + #[inline] + fn default() -> Self { + Self(RefCell::new(None)) + } +} + +impl Callback { + /// Sets inner JS function. + #[inline] + pub fn set_func(&self, f: Function) { + self.0.borrow_mut().replace(f); + } + + /// Indicates if callback is set. + #[inline] + pub fn is_set(&self) -> bool { + self.0.borrow().as_ref().is_some() + } +} + +impl Callback<()> { + pub fn call0(&self) { + self.0.borrow().as_ref().map(|f| f.call0()); + } +} + +impl> Callback { + /// Invokes JS function if any. + /// + /// Returns `None` if no callback is set, otherwise returns its invocation + /// result. + pub fn call1>(&self, arg: T) { + self.0.borrow().as_ref().map(|f| f.call1(arg.into())); + } +} diff --git a/jason/src/platform/wasm/utils/function.rs b/jason/src/platform/wasm/utils/function.rs new file mode 100644 index 000000000..4c95a5855 --- /dev/null +++ b/jason/src/platform/wasm/utils/function.rs @@ -0,0 +1,29 @@ +use std::marker::PhantomData; + +use wasm_bindgen::JsValue; + +pub struct Function { + inner: js_sys::Function, + _arg: PhantomData, +} + +impl Function<()> { + pub fn call0(&self) { + let _ = self.inner.call0(&JsValue::NULL); + } +} + +impl> Function { + pub fn call1(&self, arg: T) { + let _ = self.inner.call1(&JsValue::NULL, &arg.into()); + } +} + +impl From for Function { + fn from(func: js_sys::Function) -> Self { + Self { + inner: func, + _arg: Default::default(), + } + } +} diff --git a/jason/src/platform/wasm/utils/mod.rs b/jason/src/platform/wasm/utils/mod.rs index 7a83975d2..5e8af0602 100644 --- a/jason/src/platform/wasm/utils/mod.rs +++ b/jason/src/platform/wasm/utils/mod.rs @@ -1,3 +1,9 @@ +mod callback; mod event_listener; +mod function; -pub use event_listener::{EventListener, EventListenerBindError}; +pub use self::{ + callback::Callback, + event_listener::{EventListener, EventListenerBindError}, + function::Function, +}; diff --git a/jason/tests/media/constraints.rs b/jason/tests/media/constraints.rs index 2df7b2fe8..dfc567e4b 100644 --- a/jason/tests/media/constraints.rs +++ b/jason/tests/media/constraints.rs @@ -2,20 +2,19 @@ use medea_client_api_proto::{MediaSourceKind, VideoSettings}; use medea_jason::{ - media::{ - AudioTrackConstraints, DeviceVideoTrackConstraints, MediaKind, - MediaManager, MediaStreamSettings, MultiSourceTracksConstraints, - VideoSource, + core::media::{ + AudioTrackConstraints, DeviceVideoTrackConstraints, + DisplayVideoTrackConstraints, MediaKind, MediaManager, + MediaStreamSettings, MultiSourceTracksConstraints, VideoSource, }, - utils::{get_property_by_name, window}, - DisplayVideoTrackConstraints, + platform::get_property_by_name, }; use wasm_bindgen::JsValue; use wasm_bindgen_futures::JsFuture; use wasm_bindgen_test::*; use web_sys::{MediaDeviceInfo, MediaDeviceKind}; -use crate::is_firefox; +use crate::{is_firefox, window}; wasm_bindgen_test_configure!(run_in_browser); @@ -41,7 +40,7 @@ async fn video_constraints_satisfies() { let track = tracks.pop().unwrap().0; assert_eq!(track.kind(), MediaKind::Video); - assert!(track_constraints.satisfies(track.sys_track())); + assert!(track_constraints.satisfies(track.as_ref())); } // 1. Get device id of non default audio device from enumerate_devices(); @@ -66,7 +65,7 @@ async fn audio_constraints_satisfies() { let track = tracks.pop().unwrap().0; assert_eq!(track.kind(), MediaKind::Audio); - assert!(track_constraints.satisfies(track.sys_track())); + assert!(track_constraints.satisfies(track.as_ref())); } // 1. Get device id of non default video device from enumerate_devices(); @@ -115,10 +114,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.sys_track())); + assert!(audio_constraints.satisfies(audio_track.as_ref())); assert_eq!(video_track.kind(), MediaKind::Video); - assert!(video_constraints.satisfies(video_track.sys_track())); + assert!(video_constraints.satisfies(video_track.as_ref())); } // 1. Get device id of non default audio and video device from @@ -224,12 +223,18 @@ async fn multi_source_media_stream_constraints_build2() { match constraints { Some(MultiSourceTracksConstraints::Device(constraints)) => { - let has_video = - get_property_by_name(&constraints, "video", js_val_to_option) - .is_some(); - let has_audio = - get_property_by_name(&constraints, "audio", js_val_to_option) - .is_some(); + let has_video = get_property_by_name( + constraints.as_ref(), + "video", + js_val_to_option, + ) + .is_some(); + let has_audio = get_property_by_name( + constraints.as_ref(), + "audio", + js_val_to_option, + ) + .is_some(); assert!(!has_video); assert!(has_audio); @@ -250,12 +255,18 @@ async fn multi_source_media_stream_constraints_build3() { match constraints { Some(MultiSourceTracksConstraints::Device(constraints)) => { - let has_video = - get_property_by_name(&constraints, "video", js_val_to_option) - .is_some(); - let has_audio = - get_property_by_name(&constraints, "audio", js_val_to_option) - .is_some(); + let has_video = get_property_by_name( + constraints.as_ref(), + "video", + js_val_to_option, + ) + .is_some(); + let has_audio = get_property_by_name( + constraints.as_ref(), + "audio", + js_val_to_option, + ) + .is_some(); assert!(has_video); assert!(has_audio); @@ -279,18 +290,30 @@ async fn multi_source_media_stream_constraints_build4() { device, display, )) => { - let device_has_video = - get_property_by_name(&device, "video", js_val_to_option) - .is_some(); - let device_has_audio = - get_property_by_name(&device, "audio", js_val_to_option) - .is_some(); - let display_has_video = - get_property_by_name(&display, "video", js_val_to_option) - .is_some(); - let display_has_audio = - get_property_by_name(&display, "audio", js_val_to_option) - .is_some(); + let device_has_video = get_property_by_name( + device.as_ref(), + "video", + js_val_to_option, + ) + .is_some(); + let device_has_audio = get_property_by_name( + &device.as_ref(), + "audio", + js_val_to_option, + ) + .is_some(); + let display_has_video = get_property_by_name( + display.as_ref(), + "video", + js_val_to_option, + ) + .is_some(); + let display_has_audio = get_property_by_name( + display.as_ref(), + "audio", + js_val_to_option, + ) + .is_some(); assert!(!device_has_video); assert!(device_has_audio); @@ -312,12 +335,18 @@ async fn multi_source_media_stream_constraints_build5() { match constraints { Some(MultiSourceTracksConstraints::Device(constraints)) => { - let has_video = - get_property_by_name(&constraints, "video", js_val_to_option) - .is_some(); - let has_audio = - get_property_by_name(&constraints, "audio", js_val_to_option) - .is_some(); + let has_video = get_property_by_name( + constraints.as_ref(), + "video", + js_val_to_option, + ) + .is_some(); + let has_audio = get_property_by_name( + constraints.as_ref(), + "audio", + js_val_to_option, + ) + .is_some(); assert!(has_video); assert!(!has_audio); @@ -337,12 +366,18 @@ async fn multi_source_media_stream_constraints_build6() { match constraints { Some(MultiSourceTracksConstraints::Display(constraints)) => { - let has_video = - get_property_by_name(&constraints, "video", js_val_to_option) - .is_some(); - let has_audio = - get_property_by_name(&constraints, "audio", js_val_to_option) - .is_some(); + let has_video = get_property_by_name( + constraints.as_ref(), + "video", + js_val_to_option, + ) + .is_some(); + let has_audio = get_property_by_name( + constraints.as_ref(), + "audio", + js_val_to_option, + ) + .is_some(); assert!(has_video); assert!(!has_audio); @@ -373,12 +408,18 @@ async fn multi_source_media_stream_constraints_build7() { match constraints { Some(MultiSourceTracksConstraints::Device(constraints)) => { - let has_video = - get_property_by_name(&constraints, "video", js_val_to_option) - .is_some(); - let has_audio = - get_property_by_name(&constraints, "audio", js_val_to_option) - .is_some(); + let has_video = get_property_by_name( + constraints.as_ref(), + "video", + js_val_to_option, + ) + .is_some(); + let has_audio = get_property_by_name( + constraints.as_ref(), + "audio", + js_val_to_option, + ) + .is_some(); assert!(has_video); assert!(has_audio); @@ -398,12 +439,18 @@ async fn multi_source_media_stream_constraints_build8() { match constraints { Some(MultiSourceTracksConstraints::Device(constraints)) => { - let has_video = - get_property_by_name(&constraints, "video", js_val_to_option) - .is_some(); - let has_audio = - get_property_by_name(&constraints, "audio", js_val_to_option) - .is_some(); + let has_video = get_property_by_name( + constraints.as_ref(), + "video", + js_val_to_option, + ) + .is_some(); + let has_audio = get_property_by_name( + constraints.as_ref(), + "audio", + js_val_to_option, + ) + .is_some(); assert!(has_video); assert!(!has_audio); @@ -530,13 +577,11 @@ 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.sys_track())); + assert!(audio_constraints.satisfies(audio_track.as_ref())); let display_video_track = video.pop().unwrap().0; assert_eq!(display_video_track.kind(), MediaKind::Video); - assert!( - display_video_constraints.satisfies(display_video_track.sys_track()) - ); + assert!(display_video_constraints.satisfies(display_video_track.as_ref())); assert_eq!( display_video_track.media_source_kind(), MediaSourceKind::Display @@ -544,7 +589,7 @@ async fn simultaneous_device_and_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!(device_video_constraints.satisfies(device_video_track.as_ref())); assert_eq!( device_video_track.media_source_kind(), MediaSourceKind::Device diff --git a/jason/tests/media/manager.rs b/jason/tests/media/manager.rs index b0da7d9eb..c4a533bd9 100644 --- a/jason/tests/media/manager.rs +++ b/jason/tests/media/manager.rs @@ -8,9 +8,12 @@ use wasm_bindgen_test::*; use web_sys as sys; use medea_jason::{ - media::{MediaKind, MediaManager, MediaManagerError}, - AudioTrackConstraints, DeviceVideoTrackConstraints, - DisplayVideoTrackConstraints, MediaStreamSettings, + api, + core::{ + media::{MediaKind, MediaManager, MediaManagerError}, + AudioTrackConstraints, DeviceVideoTrackConstraints, + DisplayVideoTrackConstraints, MediaStreamSettings, + }, }; use crate::{get_jason_error, is_firefox, MockNavigator}; @@ -20,10 +23,12 @@ wasm_bindgen_test_configure!(run_in_browser); #[wasm_bindgen_test] async fn get_media_devices_info() { let media_manager = MediaManager::default(); - let devices = - JsFuture::from(media_manager.new_handle().enumerate_devices()) - .await - .unwrap(); + let devices = JsFuture::from( + api::MediaManagerHandle::from(media_manager.new_handle()) + .enumerate_devices(), + ) + .await + .unwrap(); let devices = JsArray::from(&devices); assert!(devices.length() >= 2); @@ -35,8 +40,11 @@ async fn failed_get_media_devices_info() { mock_navigator .error_enumerate_devices("failed_get_media_devices_info".into()); let media_manager = MediaManager::default(); - let result = - JsFuture::from(media_manager.new_handle().enumerate_devices()).await; + let result = JsFuture::from( + api::MediaManagerHandle::from(media_manager.new_handle()) + .enumerate_devices(), + ) + .await; mock_navigator.stop(); match result { Ok(_) => assert!(false), @@ -58,13 +66,14 @@ async fn failed_get_user_media() { mock_navigator.error_get_user_media("failed_get_user_media".into()); let media_manager = MediaManager::default(); let constraints = { - let mut constraints = MediaStreamSettings::new(); - constraints.audio(AudioTrackConstraints::new()); - constraints.device_video(DeviceVideoTrackConstraints::new()); + let mut constraints = api::MediaStreamSettings::new(); + constraints.audio(api::AudioTrackConstraints::new()); + constraints.device_video(api::DeviceVideoTrackConstraints::new()); constraints }; let result = JsFuture::from( - media_manager.new_handle().init_local_tracks(&constraints), + api::MediaManagerHandle::from(media_manager.new_handle()) + .init_local_tracks(&constraints), ) .await; mock_navigator.stop(); @@ -92,13 +101,14 @@ async fn failed_get_user_media2() { mock_navigator.error_get_user_media(error.into()); let media_manager = MediaManager::default(); let constraints = { - let mut constraints = MediaStreamSettings::new(); - constraints.audio(AudioTrackConstraints::new()); - constraints.device_video(DeviceVideoTrackConstraints::new()); + let mut constraints = api::MediaStreamSettings::new(); + constraints.audio(api::AudioTrackConstraints::new()); + constraints.device_video(api::DeviceVideoTrackConstraints::new()); constraints }; let result = JsFuture::from( - media_manager.new_handle().init_local_tracks(&constraints), + api::MediaManagerHandle::from(media_manager.new_handle()) + .init_local_tracks(&constraints), ) .await; mock_navigator.stop(); @@ -313,7 +323,7 @@ async fn new_tracks_should_be_live() { let mut constraints = MediaStreamSettings::new(); constraints.audio(AudioTrackConstraints::new()); - let track = Clone::clone( + let track: web_sys::MediaStreamTrack = Clone::clone( media_manager .get_tracks(constraints.clone()) .await @@ -321,8 +331,11 @@ async fn new_tracks_should_be_live() { .pop() .unwrap() .0 - .sys_track(), + .as_ref() + .as_ref() + .as_ref(), ); + let ended_track = track.clone(); ended_track.stop(); diff --git a/jason/tests/media/mod.rs b/jason/tests/media/mod.rs index 84cb0b066..2dcfd040e 100644 --- a/jason/tests/media/mod.rs +++ b/jason/tests/media/mod.rs @@ -9,11 +9,13 @@ use medea_client_api_proto::{ AudioSettings, Direction, MediaType, MemberId, Track, TrackId, }; use medea_jason::{ - media::{MediaManager, RecvConstraints}, - peer::{ - LocalStreamUpdateCriteria, MediaConnections, RtcPeerConnection, - SimpleTracksRequest, TransceiverDirection, + core::{ + media::{MediaManager, RecvConstraints}, + peer::{ + LocalStreamUpdateCriteria, MediaConnections, SimpleTracksRequest, + }, }, + platform::{RtcPeerConnection, TransceiverDirection}, }; use wasm_bindgen_test::*; diff --git a/jason/tests/media/track.rs b/jason/tests/media/track.rs index 7918cb1b6..38272fc0c 100644 --- a/jason/tests/media/track.rs +++ b/jason/tests/media/track.rs @@ -3,12 +3,12 @@ use std::rc::{Rc, Weak}; use futures::channel::oneshot; -use medea_jason::{ - media::MediaManager, DeviceVideoTrackConstraints, MediaStreamSettings, +use medea_jason::core::{ + media::{track::remote, MediaManager}, + DeviceVideoTrackConstraints, MediaStreamSettings, }; use wasm_bindgen::closure::Closure; use wasm_bindgen_test::*; -use web_sys::MediaStreamTrackState; use crate::{get_audio_track, timeout}; @@ -24,33 +24,34 @@ 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.sys_track()); + let sys_track = Clone::clone(strong_track.as_ref().as_ref().as_ref()); let weak_track = Rc::downgrade(&strong_track); - assert!(sys_track.ready_state() == MediaStreamTrackState::Live); + assert!(sys_track.ready_state() == web_sys::MediaStreamTrackState::Live); drop(strong_track); - assert!(sys_track.ready_state() == MediaStreamTrackState::Ended); + assert!(sys_track.ready_state() == web_sys::MediaStreamTrackState::Ended); assert_eq!(Weak::strong_count(&weak_track), 0); } #[wasm_bindgen_test] async fn on_track_enabled_works() { - let track = get_audio_track().await; + let api_track = get_audio_track().await; + let core_track: remote::Track = api_track.clone().into(); - let track_clone = track.clone(); + let core_track_clone = core_track.clone(); let (test_tx, test_rx) = oneshot::channel(); - track.on_enabled( + api_track.on_enabled( Closure::once_into_js(move || { - assert!(track_clone.js_enabled()); + assert!(core_track_clone.enabled()); test_tx.send(()).unwrap(); }) .into(), ); - track.set_enabled(false); - assert!(!track.js_enabled()); - track.set_enabled(true); - assert!(track.js_enabled()); + core_track.set_enabled(false); + assert!(!api_track.enabled()); + core_track.set_enabled(true); + assert!(api_track.enabled()); timeout(100, test_rx).await.unwrap().unwrap(); } @@ -63,12 +64,13 @@ async fn on_track_disabled_works() { let (test_tx, test_rx) = oneshot::channel(); track.on_disabled( Closure::once_into_js(move || { - assert!(!track_clone.js_enabled()); + assert!(!track_clone.enabled()); test_tx.send(()).unwrap(); }) .into(), ); + let track: remote::Track = track.into(); track.set_enabled(false); timeout(100, test_rx).await.unwrap().unwrap(); diff --git a/jason/tests/peer/media/mod.rs b/jason/tests/peer/media/mod.rs index 26ff8a7fc..02f6e118a 100644 --- a/jason/tests/peer/media/mod.rs +++ b/jason/tests/peer/media/mod.rs @@ -7,12 +7,15 @@ use std::{convert::TryFrom, mem, rc::Rc}; use futures::channel::mpsc; use medea_client_api_proto::{TrackId, TrackPatchEvent}; use medea_jason::{ - media::{LocalTracksConstraints, MediaManager, RecvConstraints}, - peer::{ - media_exchange_state, LocalStreamUpdateCriteria, MediaConnections, - MediaStateControllable, RtcPeerConnection, SimpleTracksRequest, + core::{ + media::{LocalTracksConstraints, MediaManager, RecvConstraints}, + peer::{ + media_exchange_state, LocalStreamUpdateCriteria, MediaConnections, + MediaStateControllable, SimpleTracksRequest, + }, + utils::Updatable as _, }, - utils::Updatable as _, + platform::RtcPeerConnection, }; use wasm_bindgen_test::*; @@ -154,7 +157,7 @@ async fn new_media_connections_with_disabled_video_tracks() { /// This tests checks that [`TrackPatch`] works as expected. mod sender_patch { use medea_client_api_proto::{AudioSettings, MediaType}; - use medea_jason::{ + use medea_jason::core::{ peer::{sender, MediaExchangeState}, utils::{AsProtoState, SynchronizableState}, }; @@ -286,7 +289,7 @@ mod sender_patch { mod receiver_patch { use medea_client_api_proto::{AudioSettings, MediaType, MemberId}; - use medea_jason::{ + use medea_jason::core::{ media::RecvConstraints, peer::{receiver, MediaExchangeState, PeerEvent}, utils::{AsProtoState, SynchronizableState}, diff --git a/jason/tests/peer/media/transitable_state/controller.rs b/jason/tests/peer/media/transitable_state/controller.rs index d9b72cca1..77f330647 100644 --- a/jason/tests/peer/media/transitable_state/controller.rs +++ b/jason/tests/peer/media/transitable_state/controller.rs @@ -1,7 +1,9 @@ //! Tests for the [`TransitableStateController`]. use futures::StreamExt; -use medea_jason::peer::{media_exchange_state, MediaExchangeStateController}; +use medea_jason::core::peer::{ + media_exchange_state, MediaExchangeStateController, +}; use wasm_bindgen_test::wasm_bindgen_test; use crate::timeout; diff --git a/jason/tests/peer/mod.rs b/jason/tests/peer/mod.rs index 4b5c4ef68..e9f089942 100644 --- a/jason/tests/peer/mod.rs +++ b/jason/tests/peer/mod.rs @@ -20,13 +20,18 @@ use medea_client_api_proto::{ VideoSettings, }; use medea_jason::{ - api::Connections, - media::{LocalTracksConstraints, MediaKind, MediaManager, RecvConstraints}, - peer::{ - self, media_exchange_state, MediaStateControllable, PeerEvent, - RtcStats, TrackDirection, + core::{ + media::{ + LocalTracksConstraints, MediaKind, MediaManager, RecvConstraints, + }, + peer::{ + self, media_exchange_state, MediaStateControllable, PeerEvent, + TrackDirection, + }, + utils::Updatable, + Connections, }, - utils::Updatable, + platform::RtcStats, }; use wasm_bindgen_test::*; diff --git a/jason/tests/api/connection.rs b/jason/tests/room/connection.rs similarity index 64% rename from jason/tests/api/connection.rs rename to jason/tests/room/connection.rs index f759cd876..227a579e3 100644 --- a/jason/tests/api/connection.rs +++ b/jason/tests/room/connection.rs @@ -5,10 +5,7 @@ use futures::{ StreamExt, }; use medea_client_api_proto::PeerId; -use medea_jason::{ - api::{ConnectionHandle, Connections}, - media::{track::remote, MediaKind}, -}; +use medea_jason::{api, core::Connections, platform}; use wasm_bindgen::{closure::Closure, JsValue}; use wasm_bindgen_test::*; @@ -22,13 +19,15 @@ wasm_bindgen_test_configure!(run_in_browser); async fn on_new_connection_fires() { let cons = Connections::default(); - let (cb, test_result) = js_callback!(|handle: ConnectionHandle| { + let (cb, test_result) = js_callback!(|handle: api::ConnectionHandle| { cb_assert_eq!( handle.get_remote_member_id().unwrap(), "bob".to_string() ); }); - cons.on_new_connection(cb.into()); + cons.on_new_connection(platform::Function::from(js_sys::Function::from( + cb, + ))); cons.create_connection(PeerId(1), &"bob".into()); @@ -43,13 +42,16 @@ 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: remote::Track| { - cb_assert_eq!(track.kind(), MediaKind::Video); + let (cb, test_result) = js_callback!(|track: api::RemoteMediaTrack| { + cb_assert_eq!(track.kind(), api::MediaKind::Video); }); - con_handle.on_remote_track_added(cb.into()).unwrap(); + con_handle + .on_remote_track_added(platform::Function::from( + js_sys::Function::from(cb), + )) + .unwrap(); - con.add_remote_track(get_video_track().await); + con.add_remote_track(get_video_track().await.into()); wait_and_check_test_result(test_result, || {}).await; } @@ -61,26 +63,26 @@ async fn tracks_are_added_to_connection() { cons.create_connection(PeerId(1), &"bob".into()); let con = cons.get(&"bob".into()).unwrap(); - let con_handle = con.new_handle(); + let con_handle = api::ConnectionHandle::from(con.new_handle()); let (tx, rx) = oneshot::channel(); - let closure = Closure::once_into_js(move |track: remote::Track| { + let closure = Closure::once_into_js(move |track: api::RemoteMediaTrack| { assert!(tx.send(track).is_ok()); }); con_handle.on_remote_track_added(closure.into()).unwrap(); - con.add_remote_track(get_video_track().await); + con.add_remote_track(get_video_track().await.into()); let video_track = timeout(100, rx).await.unwrap().unwrap(); - assert_eq!(video_track.kind(), MediaKind::Video); + assert_eq!(video_track.kind(), api::MediaKind::Video); let (tx, rx) = oneshot::channel(); - let closure = Closure::once_into_js(move |track: remote::Track| { + let closure = Closure::once_into_js(move |track: api::RemoteMediaTrack| { assert!(tx.send(track).is_ok()); }); con_handle.on_remote_track_added(closure.into()).unwrap(); - con.add_remote_track(get_audio_track().await); + con.add_remote_track(get_audio_track().await.into()); let audio_track = timeout(200, rx).await.unwrap().unwrap(); - assert_eq!(audio_track.kind(), MediaKind::Audio); + assert_eq!(audio_track.kind(), api::MediaKind::Audio); } #[wasm_bindgen_test] @@ -93,7 +95,9 @@ async fn on_closed_fires() { let (on_close, test_result) = js_callback!(|nothing: JsValue| { cb_assert_eq!(nothing.is_undefined(), true); }); - con_handle.on_close(on_close.into()).unwrap(); + con_handle + .on_close(platform::Function::from(js_sys::Function::from(on_close))) + .unwrap(); cons.close_connection(PeerId(1)); @@ -106,10 +110,13 @@ async fn two_peers_in_one_connection_works() { let (test_tx, mut test_rx) = mpsc::unbounded(); let on_new_connection = - Closure::wrap(Box::new(move |_: ConnectionHandle| { + Closure::wrap(Box::new(move |_: api::ConnectionHandle| { test_tx.unbounded_send(()).unwrap(); - }) as Box); - cons.on_new_connection(on_new_connection.as_ref().clone().into()); + }) as Box) + .into_js_value(); + cons.on_new_connection(platform::Function::from(js_sys::Function::from( + on_new_connection, + ))); cons.create_connection(PeerId(1), &"bob".into()); test_rx.next().await.unwrap(); @@ -124,10 +131,13 @@ async fn create_two_connections() { let (test_tx, mut test_rx) = mpsc::unbounded(); let on_new_connection = - Closure::wrap(Box::new(move |_: ConnectionHandle| { + Closure::wrap(Box::new(move |_: api::ConnectionHandle| { test_tx.unbounded_send(()).unwrap(); - }) as Box); - cons.on_new_connection(on_new_connection.as_ref().clone().into()); + }) as Box) + .into_js_value(); + cons.on_new_connection(platform::Function::from(js_sys::Function::from( + on_new_connection, + ))); cons.create_connection(PeerId(1), &"bob".into()); test_rx.next().await.unwrap(); diff --git a/jason/tests/api/mod.rs b/jason/tests/room/mod.rs similarity index 94% rename from jason/tests/api/mod.rs rename to jason/tests/room/mod.rs index 12942f799..d9d713ca8 100644 --- a/jason/tests/api/mod.rs +++ b/jason/tests/room/mod.rs @@ -11,11 +11,12 @@ use medea_client_api_proto::{ ClientMsg, CloseReason, Command, Event, ServerMsg, }; use medea_jason::{ - rpc::{ - websocket::{MockRpcTransport, TransportState}, - CloseMsg, RpcTransport, WebSocketRpcClient, + api, + core::{ + self, + rpc::{CloseMsg, WebSocketRpcClient}, }, - Jason, + platform::{MockRpcTransport, RpcTransport, TransportState}, }; use medea_reactive::ObservableCell; use wasm_bindgen::closure::Closure; @@ -54,14 +55,16 @@ async fn only_one_strong_rpc_rc_exists() { Ok(transport as Rc) }) }))); - let jason = Jason::with_rpc_client(ws.clone()); + let jason = api::Jason::from(core::Jason::with_rpc_client(ws.clone())); let room = jason.init_room(); room.on_failed_local_media(Closure::once_into_js(|| {}).into()) .unwrap(); room.on_connection_loss(Closure::once_into_js(|| {}).into()) .unwrap(); - room.inner_join(TEST_ROOM_URL.to_string()).await.unwrap(); + JsFuture::from(room.join(TEST_ROOM_URL.to_string())) + .await + .unwrap(); assert_eq!(Rc::strong_count(&ws), 3); jason.dispose(); @@ -102,7 +105,7 @@ async fn rpc_dropped_on_jason_dispose() { Ok(transport as Rc) }) }))); - let jason = Jason::with_rpc_client(ws); + let jason = api::Jason::from(core::Jason::with_rpc_client(ws)); let room = jason.init_room(); room.on_failed_local_media(Closure::once_into_js(|| {}).into()) @@ -157,7 +160,7 @@ async fn room_dispose_works() { }) }) })); - let jason = Jason::with_rpc_client(ws); + let jason = api::Jason::from(core::Jason::with_rpc_client(ws)); let room = jason.init_room(); room.on_failed_local_media(Closure::once_into_js(|| {}).into()) @@ -290,9 +293,9 @@ async fn room_closes_on_rpc_transport_close() { }) } }))); - let jason = Jason::with_rpc_client(ws); + let jason = api::Jason::from(core::Jason::with_rpc_client(ws)); - let mut room = jason.init_room(); + let room = jason.init_room(); room.on_failed_local_media(Closure::once_into_js(|| {}).into()) .unwrap(); room.on_connection_loss(Closure::once_into_js(|| {}).into()) diff --git a/jason/tests/api/room.rs b/jason/tests/room/room.rs similarity index 89% rename from jason/tests/api/room.rs rename to jason/tests/room/room.rs index 9a3481d85..f671eb0b2 100644 --- a/jason/tests/api/room.rs +++ b/jason/tests/room/room.rs @@ -1,9 +1,6 @@ #![cfg(target_arch = "wasm32")] -use std::{ - collections::{HashMap, HashSet}, - rc::Rc, -}; +use std::{collections::HashMap, rc::Rc}; use futures::{ channel::{ @@ -14,18 +11,17 @@ use futures::{ stream::{self, BoxStream, LocalBoxStream, StreamExt as _}, }; use medea_client_api_proto::{ - state, AudioSettings, Command, Direction, Event, IceConnectionState, + self as proto, Command, Direction, Event, IceConnectionState, MediaSourceKind, MediaType, MemberId, NegotiationRole, PeerId, PeerMetrics, Track, TrackId, TrackPatchCommand, TrackPatchEvent, TrackUpdate, VideoSettings, }; use medea_jason::{ - api::Room, - media::{AudioTrackConstraints, MediaKind, MediaStreamSettings}, - peer::PeerConnection, - rpc::MockRpcSession, - utils::{AsProtoState, JasonError, Updatable}, - DeviceVideoTrackConstraints, + api, + core::{ + media::MediaKind, peer::PeerConnection, rpc::MockRpcSession, + utils::Updatable, Room, + }, }; use wasm_bindgen_futures::{spawn_local, JsFuture}; use wasm_bindgen_test::*; @@ -63,7 +59,7 @@ fn get_test_room( async fn get_test_room_and_exist_peer( tracks: Vec, - media_stream_settings: Option, + media_stream_settings: Option, ) -> ( Room, Rc, @@ -107,11 +103,13 @@ async fn get_test_room_and_exist_peer( let room = Room::new(Rc::new(rpc), Rc::default()); if let Some(media_stream_settings) = &media_stream_settings { - JsFuture::from(room.new_handle().set_local_media_settings( - &media_stream_settings, - false, - false, - )) + JsFuture::from( + api::RoomHandle::from(room.new_handle()).set_local_media_settings( + &media_stream_settings, + false, + false, + ), + ) .await .unwrap(); } @@ -135,7 +133,7 @@ async fn get_test_room_and_exist_peer( async fn error_get_local_stream_on_new_peer() { let (event_tx, event_rx) = mpsc::unbounded(); let (room, _) = get_test_room(Box::pin(event_rx)); - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); JsFuture::from(room_handle.set_local_media_settings( &media_stream_settings(true, true), false, @@ -144,7 +142,7 @@ async fn error_get_local_stream_on_new_peer() { .await .unwrap(); - let (cb, test_result) = js_callback!(|err: JasonError| { + let (cb, test_result) = js_callback!(|err: api::JasonError| { cb_assert_eq!(&err.name(), "MediaManager"); cb_assert_eq!( &err.message(), @@ -184,23 +182,24 @@ async fn error_get_local_stream_on_new_peer() { #[wasm_bindgen_test] async fn error_join_room_without_on_failed_stream_callback() { let (room, _) = get_test_room(stream::pending().boxed()); - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); room_handle .on_connection_loss(js_sys::Function::new_no_args("")) .unwrap(); - match room_handle.inner_join(String::from(TEST_ROOM_URL)).await { - Ok(_) => unreachable!(), - Err(e) => { - assert_eq!(e.name(), "CallbackNotSet"); - assert_eq!( - e.message(), - "`Room.on_failed_local_media()` callback isn't set.", - ); - assert!(!e.trace().is_empty()); - } - } + let err = get_jason_error( + JsFuture::from(room_handle.join(String::from(TEST_ROOM_URL))) + .await + .unwrap_err(), + ); + + assert_eq!(err.name(), "CallbackNotSet"); + assert_eq!( + err.message(), + "`Room.on_failed_local_media()` callback isn't set.", + ); + assert!(!err.trace().is_empty()); } /// Tests `Room::join` if `on_connection_loss` callback was not set. @@ -213,23 +212,24 @@ async fn error_join_room_without_on_failed_stream_callback() { #[wasm_bindgen_test] async fn error_join_room_without_on_connection_loss_callback() { let (room, _) = get_test_room(stream::pending().boxed()); - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); room_handle .on_failed_local_media(js_sys::Function::new_no_args("")) .unwrap(); - match room_handle.inner_join(String::from(TEST_ROOM_URL)).await { - Ok(_) => unreachable!(), - Err(e) => { - assert_eq!(e.name(), "CallbackNotSet"); - assert_eq!( - e.message(), - "`Room.on_connection_loss()` callback isn't set.", - ); - assert!(!e.trace().is_empty()); - } - } + let err = get_jason_error( + JsFuture::from(room_handle.join(String::from(TEST_ROOM_URL))) + .await + .unwrap_err(), + ); + + assert_eq!(err.name(), "CallbackNotSet"); + assert_eq!( + err.message(), + "`Room.on_connection_loss()` callback isn't set.", + ); + assert!(!err.trace().is_empty()); } mod disable_recv_tracks { @@ -244,7 +244,7 @@ mod disable_recv_tracks { async fn check_transceivers_statuses() { let (event_tx, event_rx) = mpsc::unbounded(); let (room, mut commands_rx) = get_test_room(Box::pin(event_rx)); - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); JsFuture::from(room_handle.disable_remote_audio()) .await @@ -324,11 +324,11 @@ mod disable_recv_tracks { /// Tests disabling tracks publishing. mod disable_send_tracks { use medea_client_api_proto::{ - AudioSettings, Direction, MediaSourceKind, MediaType, MemberId, - TrackPatchCommand, VideoSettings, + AudioSettings, Direction, MediaType, MemberId, TrackPatchCommand, + VideoSettings, }; - use medea_jason::{ - media::{JsMediaSourceKind, MediaKind}, + use medea_jason::core::{ + media::MediaKind, peer::{media_exchange_state, TrackDirection}, }; @@ -345,11 +345,11 @@ mod disable_send_tracks { ) .await; - let handle = room.new_handle(); - assert!(JsFuture::from(handle.disable_audio()).await.is_ok()); + let room_handle = api::RoomHandle::from(room.new_handle()); + assert!(JsFuture::from(room_handle.disable_audio()).await.is_ok()); assert!(!peer.is_send_audio_enabled()); - assert!(JsFuture::from(handle.enable_audio()).await.is_ok()); + assert!(JsFuture::from(room_handle.enable_audio()).await.is_ok()); assert!(peer.is_send_audio_enabled()); } @@ -362,11 +362,13 @@ mod disable_send_tracks { ) .await; - let handle = room.new_handle(); - assert!(JsFuture::from(handle.disable_video(None)).await.is_ok()); + let room_handle = api::RoomHandle::from(room.new_handle()); + assert!(JsFuture::from(room_handle.disable_video(None)) + .await + .is_ok()); assert!(!peer.is_send_video_enabled(None)); - assert!(JsFuture::from(handle.enable_video(None)).await.is_ok()); + assert!(JsFuture::from(room_handle.enable_video(None)).await.is_ok()); assert!(peer.is_send_video_enabled(None)); } @@ -420,16 +422,20 @@ mod disable_send_tracks { return; } - let handle = room.new_handle(); - JsFuture::from(handle.disable_video(Some(JsMediaSourceKind::Device))) - .await - .unwrap(); + let room_handle = api::RoomHandle::from(room.new_handle()); + JsFuture::from( + room_handle.disable_video(Some(api::MediaSourceKind::Device)), + ) + .await + .unwrap(); assert!(!peer.is_send_video_enabled(Some(MediaSourceKind::Device))); assert!(peer.is_send_video_enabled(Some(MediaSourceKind::Display))); - JsFuture::from(handle.enable_video(Some(JsMediaSourceKind::Device))) - .await - .unwrap(); + JsFuture::from( + room_handle.enable_video(Some(api::MediaSourceKind::Device)), + ) + .await + .unwrap(); assert!(peer.is_send_video_enabled(Some(MediaSourceKind::Device))); assert!(peer.is_send_video_enabled(Some(MediaSourceKind::Display))); } @@ -455,18 +461,20 @@ mod disable_send_tracks { return; } - let handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); assert!(JsFuture::from( - handle.disable_video(Some(JsMediaSourceKind::Display)) + room_handle.disable_video(Some(api::MediaSourceKind::Display)) ) .await .is_ok()); assert!(!peer.is_send_video_enabled(Some(MediaSourceKind::Display))); assert!(peer.is_send_video_enabled(Some(MediaSourceKind::Device))); - JsFuture::from(handle.enable_video(Some(JsMediaSourceKind::Display))) - .await - .unwrap(); + JsFuture::from( + room_handle.enable_video(Some(api::MediaSourceKind::Display)), + ) + .await + .unwrap(); assert!(peer.is_send_video_enabled(Some(MediaSourceKind::Display))); assert!(peer.is_send_video_enabled(Some(MediaSourceKind::Device))); } @@ -491,10 +499,10 @@ mod disable_send_tracks { ) .await; - let handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); let (first, second) = futures::future::join( - JsFuture::from(handle.disable_audio()), - JsFuture::from(handle.disable_audio()), + JsFuture::from(room_handle.disable_audio()), + JsFuture::from(room_handle.disable_audio()), ) .await; first.unwrap(); @@ -528,10 +536,10 @@ mod disable_send_tracks { ) .await; - let handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); let (first, second) = futures::future::join( - JsFuture::from(handle.disable_video(None)), - JsFuture::from(handle.disable_video(None)), + JsFuture::from(room_handle.disable_video(None)), + JsFuture::from(room_handle.disable_video(None)), ) .await; first.unwrap(); @@ -574,11 +582,11 @@ mod disable_send_tracks { media_exchange_state::Stable::Enabled.into() )); - let handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); let (disable_audio_result, enable_audio_result) = futures::future::join( - JsFuture::from(handle.disable_audio()), - JsFuture::from(handle.enable_audio()), + JsFuture::from(room_handle.disable_audio()), + JsFuture::from(room_handle.enable_audio()), ) .await; disable_audio_result.unwrap_err(); @@ -621,11 +629,11 @@ mod disable_send_tracks { media_exchange_state::Stable::Enabled.into() )); - let handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); let (disable_video_result, enable_video_result) = futures::future::join( - JsFuture::from(handle.disable_video(None)), - JsFuture::from(handle.enable_video(None)), + JsFuture::from(room_handle.disable_video(None)), + JsFuture::from(room_handle.enable_video(None)), ) .await; disable_video_result.unwrap_err(); @@ -670,8 +678,8 @@ mod disable_send_tracks { media_exchange_state::Stable::Enabled.into() )); - let handle = room.new_handle(); - JsFuture::from(handle.disable_audio()).await.unwrap(); + let room_handle = api::RoomHandle::from(room.new_handle()); + JsFuture::from(room_handle.disable_audio()).await.unwrap(); assert!(peer.is_all_transceiver_sides_in_media_state( MediaKind::Audio, @@ -682,8 +690,8 @@ mod disable_send_tracks { let (disable_audio_result, enable_audio_result) = futures::future::join( - JsFuture::from(handle.disable_audio()), - JsFuture::from(handle.enable_audio()), + JsFuture::from(room_handle.disable_audio()), + JsFuture::from(room_handle.enable_audio()), ) .await; disable_audio_result.unwrap(); @@ -701,7 +709,9 @@ mod disable_send_tracks { async fn disable_audio_room_before_init_peer() { let (event_tx, event_rx) = mpsc::unbounded(); let (room, mut commands_rx) = get_test_room(Box::pin(event_rx)); - JsFuture::from(room.new_handle().set_local_media_settings( + let room_handle = api::RoomHandle::from(room.new_handle()); + + JsFuture::from(room_handle.set_local_media_settings( &media_stream_settings(true, true), false, false, @@ -709,9 +719,7 @@ mod disable_send_tracks { .await .unwrap(); - JsFuture::from(room.new_handle().disable_audio()) - .await - .unwrap(); + JsFuture::from(room_handle.disable_audio()).await.unwrap(); let (audio_track, video_track) = get_test_tracks(false, false); event_tx @@ -781,7 +789,9 @@ mod disable_send_tracks { async fn mute_audio_room_before_init_peer() { let (event_tx, event_rx) = mpsc::unbounded(); let (room, mut commands_rx) = get_test_room(Box::pin(event_rx)); - JsFuture::from(room.new_handle().set_local_media_settings( + let room_handle = api::RoomHandle::from(room.new_handle()); + + JsFuture::from(room_handle.set_local_media_settings( &media_stream_settings(true, true), false, false, @@ -789,9 +799,7 @@ mod disable_send_tracks { .await .unwrap(); - JsFuture::from(room.new_handle().mute_audio()) - .await - .unwrap(); + JsFuture::from(room_handle.mute_audio()).await.unwrap(); let (audio_track, video_track) = get_test_tracks(false, false); event_tx @@ -862,7 +870,9 @@ mod disable_send_tracks { async fn disable_video_room_before_init_peer() { let (event_tx, event_rx) = mpsc::unbounded(); let (room, mut commands_rx) = get_test_room(Box::pin(event_rx)); - JsFuture::from(room.new_handle().set_local_media_settings( + let room_handle = api::RoomHandle::from(room.new_handle()); + + JsFuture::from(room_handle.set_local_media_settings( &media_stream_settings(true, true), false, false, @@ -870,7 +880,7 @@ mod disable_send_tracks { .await .unwrap(); - JsFuture::from(room.new_handle().disable_video(None)) + JsFuture::from(room_handle.disable_video(None)) .await .unwrap(); @@ -942,7 +952,7 @@ mod disable_send_tracks { /// Tests for `RoomHandle.on_close` JS side callback. mod on_close_callback { use medea_client_api_proto::CloseReason as CloseByServerReason; - use medea_jason::rpc::{ClientDisconnect, CloseReason}; + use medea_jason::core::rpc::{ClientDisconnect, CloseReason}; use wasm_bindgen::{prelude::*, JsValue}; use wasm_bindgen_test::*; @@ -977,7 +987,7 @@ mod on_close_callback { #[wasm_bindgen_test] async fn closed_by_server() { let (room, _) = get_test_room(stream::pending().boxed()); - let mut room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); let (cb, test_result) = js_callback!(|closed: JsValue| { cb_assert_eq!(get_reason(&closed), "Finished"); @@ -1005,7 +1015,7 @@ mod on_close_callback { #[wasm_bindgen_test] async fn unexpected_room_drop() { let (room, _) = get_test_room(stream::pending().boxed()); - let mut room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); let (cb, test_result) = js_callback!(|closed: JsValue| { cb_assert_eq!(get_reason(&closed), "RoomUnexpectedlyDropped"); @@ -1030,7 +1040,7 @@ mod on_close_callback { #[wasm_bindgen_test] async fn normal_close_by_client() { let (room, _) = get_test_room(stream::pending().boxed()); - let mut room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); let (cb, test_result) = js_callback!(|closed: JsValue| { cb_assert_eq!(get_reason(&closed), "RoomUnexpectedlyDropped"); @@ -1052,7 +1062,7 @@ mod rpc_close_reason_on_room_drop { //! is provided to [`RpcClient`]. use futures::channel::oneshot; - use medea_jason::rpc::{ClientDisconnect, CloseReason}; + use medea_jason::core::rpc::{ClientDisconnect, CloseReason}; use super::*; @@ -1137,12 +1147,11 @@ mod rpc_close_reason_on_room_drop { /// Tests for [`TrackPatch`] generation in [`Room`]. mod patches_generation { use medea_client_api_proto::{ - AudioSettings, Direction, MediaSourceKind, MediaType, Track, TrackId, - TrackPatchCommand, VideoSettings, + AudioSettings, Direction, MediaType, Track, TrackId, TrackPatchCommand, + VideoSettings, }; - use medea_jason::{ - peer::{media_exchange_state, mute_state, MediaState}, - JsMediaSourceKind, + use medea_jason::core::peer::{ + media_exchange_state, mute_state, MediaState, }; use wasm_bindgen_futures::spawn_local; @@ -1162,7 +1171,7 @@ mod patches_generation { ( MediaType::Video(VideoSettings { required: false, - source_kind: MediaSourceKind::Device, + source_kind: proto::MediaSourceKind::Device, }), Direction::Send { receivers: Vec::new(), @@ -1286,7 +1295,7 @@ mod patches_generation { audio_and_device_video_tracks_content(), ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); spawn_local(async move { JsFuture::from(room_handle.disable_audio()) @@ -1328,7 +1337,7 @@ mod patches_generation { audio_and_device_video_tracks_content(), ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); spawn_local(async move { JsFuture::from(room_handle.disable_audio()) @@ -1389,7 +1398,7 @@ mod patches_generation { audio_and_device_video_tracks_content(), ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); spawn_local(async move { JsFuture::from(room_handle.enable_audio()).await.unwrap(); @@ -1424,7 +1433,7 @@ mod patches_generation { audio_and_device_video_tracks_content(), ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); spawn_local(async move { JsFuture::from(room_handle.disable_audio()) @@ -1458,7 +1467,7 @@ mod patches_generation { let mut tracks = audio_and_device_video_tracks_content(); tracks.push(( MediaType::Video(VideoSettings { - source_kind: MediaSourceKind::Display, + source_kind: proto::MediaSourceKind::Display, required: false, }), Direction::Send { @@ -1473,11 +1482,11 @@ mod patches_generation { ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); spawn_local(async move { JsFuture::from( - room_handle.disable_video(Some(JsMediaSourceKind::Device)), + room_handle.disable_video(Some(api::MediaSourceKind::Device)), ) .await .unwrap_err(); @@ -1514,7 +1523,7 @@ mod patches_generation { let mut tracks = audio_and_device_video_tracks_content(); tracks.push(( MediaType::Video(VideoSettings { - source_kind: MediaSourceKind::Display, + source_kind: proto::MediaSourceKind::Display, required: false, }), Direction::Send { @@ -1529,11 +1538,11 @@ mod patches_generation { ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); spawn_local(async move { JsFuture::from( - room_handle.disable_video(Some(JsMediaSourceKind::Display)), + room_handle.disable_video(Some(api::MediaSourceKind::Display)), ) .await .unwrap_err(); @@ -1566,7 +1575,7 @@ mod patches_generation { audio_and_device_video_tracks_content(), ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); spawn_local(async move { JsFuture::from(room_handle.mute_audio()).await.unwrap_err(); @@ -1594,7 +1603,7 @@ mod patches_generation { audio_and_device_video_tracks_content(), ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); spawn_local(async move { JsFuture::from(room_handle.unmute_audio()) @@ -1626,10 +1635,10 @@ async fn mute_unmute_audio() { ) .await; - let handle = room.new_handle(); - assert!(JsFuture::from(handle.mute_audio()).await.is_ok()); + let room_handle = api::RoomHandle::from(room.new_handle()); + assert!(JsFuture::from(room_handle.mute_audio()).await.is_ok()); assert!(!peer.is_send_audio_unmuted()); - assert!(JsFuture::from(handle.unmute_audio()).await.is_ok()); + assert!(JsFuture::from(room_handle.unmute_audio()).await.is_ok()); assert!(peer.is_send_audio_unmuted()); } @@ -1643,10 +1652,14 @@ async fn remote_disable_enable_audio() { ) .await; - let handle = room.new_handle(); - assert!(JsFuture::from(handle.disable_remote_audio()).await.is_ok()); + let room_handle = api::RoomHandle::from(room.new_handle()); + assert!(JsFuture::from(room_handle.disable_remote_audio()) + .await + .is_ok()); assert!(!peer.is_recv_audio_enabled()); - assert!(JsFuture::from(handle.enable_remote_audio()).await.is_ok()); + assert!(JsFuture::from(room_handle.enable_remote_audio()) + .await + .is_ok()); assert!(peer.is_recv_audio_enabled()); } @@ -1660,10 +1673,14 @@ async fn remote_disable_enable_video() { ) .await; - let handle = room.new_handle(); - assert!(JsFuture::from(handle.disable_remote_video()).await.is_ok()); + let room_handle = api::RoomHandle::from(room.new_handle()); + assert!(JsFuture::from(room_handle.disable_remote_video()) + .await + .is_ok()); assert!(!peer.is_recv_video_enabled()); - assert!(JsFuture::from(handle.enable_remote_video()).await.is_ok()); + assert!(JsFuture::from(room_handle.enable_remote_video()) + .await + .is_ok()); assert!(peer.is_recv_video_enabled()); } @@ -1761,7 +1778,7 @@ async fn only_one_gum_performed_on_enable() { Some(media_stream_settings(true, true)), ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); assert_eq!(mock.get_user_media_requests_count(), 1); event_tx @@ -1812,7 +1829,7 @@ async fn no_updates_sent_if_gum_fails_on_enable() { Some(media_stream_settings(true, false)), ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); assert_eq!(mock.get_user_media_requests_count(), 1); assert!(peer.is_send_audio_enabled()); @@ -1863,7 +1880,7 @@ async fn set_media_state_return_media_error() { Some(media_stream_settings(false, false)), ) .await; - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); JsFuture::from(room_handle.disable_audio()).await.unwrap(); mock.error_get_user_media(ERROR_MSG.into()); @@ -1959,7 +1976,8 @@ async fn send_enabling_holds_local_tracks() { }); let room = Room::new(Rc::new(rpc), Rc::default()); - JsFuture::from(room.new_handle().set_local_media_settings( + let room_handle = api::RoomHandle::from(room.new_handle()); + JsFuture::from(room_handle.set_local_media_settings( &media_stream_settings(true, true), false, false, @@ -1995,7 +2013,7 @@ async fn send_enabling_holds_local_tracks() { let mock = MockNavigator::new(); mock.error_get_user_media("foobar".into()); let err = get_jason_error( - JsFuture::from(room.new_handle().enable_video(None)) + JsFuture::from(room_handle.enable_video(None)) .await .unwrap_err(), ); @@ -2144,9 +2162,9 @@ mod set_local_media_settings { /// Returns [`MediaStreamSettings`] which requires that device ID should be /// `foobar`. - fn media_settings_with_device_id() -> MediaStreamSettings { - let mut settings = MediaStreamSettings::new(); - let mut device_video = DeviceVideoTrackConstraints::new(); + fn media_settings_with_device_id() -> api::MediaStreamSettings { + let mut settings = api::MediaStreamSettings::new(); + let mut device_video = api::DeviceVideoTrackConstraints::new(); device_video.device_id("foobar".to_string()); settings.device_video(device_video); @@ -2165,9 +2183,9 @@ mod set_local_media_settings { async fn error_inject_invalid_local_stream_into_new_peer() { let (event_tx, event_rx) = mpsc::unbounded(); let (room, _rx) = get_test_room(Box::pin(event_rx)); - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); - let (cb, test_result) = js_callback!(|err: JasonError| { + let (cb, test_result) = js_callback!(|err: api::JasonError| { cb_assert_eq!(&err.name(), "MediaConnections"); cb_assert_eq!( err.message(), @@ -2179,8 +2197,8 @@ mod set_local_media_settings { let (audio_track, video_track) = get_test_required_tracks(); - let mut constraints = MediaStreamSettings::new(); - constraints.audio(AudioTrackConstraints::new()); + let mut constraints = api::MediaStreamSettings::new(); + constraints.audio(api::AudioTrackConstraints::new()); JsFuture::from(room_handle.set_local_media_settings( &constraints, @@ -2213,7 +2231,7 @@ mod set_local_media_settings { /// 1. `on_failed_local_media` was invoked. #[wasm_bindgen_test] async fn error_inject_invalid_local_stream_into_room_on_exists_peer() { - let (cb, test_result) = js_callback!(|err: JasonError| { + let (cb, test_result) = js_callback!(|err: api::JasonError| { cb_assert_eq!(&err.name(), "TracksRequest"); cb_assert_eq!( &err.message(), @@ -2225,9 +2243,10 @@ mod set_local_media_settings { get_test_room_and_exist_peer(vec![audio_track, video_track], None) .await; - let mut constraints = MediaStreamSettings::new(); - constraints.audio(AudioTrackConstraints::new()); - let room_handle = room.new_handle(); + let mut constraints = api::MediaStreamSettings::new(); + constraints.audio(api::AudioTrackConstraints::new()); + + let room_handle = api::RoomHandle::from(room.new_handle()); room_handle.on_failed_local_media(cb.into()).unwrap(); let err = get_constraints_update_exception( JsFuture::from(room_handle.set_local_media_settings( @@ -2238,7 +2257,7 @@ mod set_local_media_settings { .await .unwrap_err(), ); - let err = get_jason_error(err.error()); + let err = err.error().unwrap(); assert_eq!(err.name(), "InvalidLocalTracks"); assert_eq!( err.message(), @@ -2270,15 +2289,16 @@ mod set_local_media_settings { ) .await; - let mut constraints = MediaStreamSettings::new(); + let mut constraints = api::MediaStreamSettings::new(); if add_audio { - constraints.audio(AudioTrackConstraints::new()); + constraints.audio(api::AudioTrackConstraints::new()); } if add_video { - constraints.device_video(DeviceVideoTrackConstraints::new()); + constraints + .device_video(api::DeviceVideoTrackConstraints::new()); } - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); room_handle.on_failed_local_media(closure.into()).unwrap(); let is_should_be_ok = @@ -2323,7 +2343,7 @@ mod set_local_media_settings { async fn set_local_media_stream_settings_updates_media_exchange_state() { let (event_tx, event_rx) = mpsc::unbounded(); let (room, commands_rx) = get_test_room(Box::pin(event_rx)); - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); room_handle .on_failed_local_media(js_sys::Function::new_no_args("")) .unwrap(); @@ -2378,11 +2398,11 @@ mod set_local_media_settings { #[wasm_bindgen_test] async fn disables_on_fail_if_no_rollback() { let (room, peer1, _peer2) = room_with_connected_peers().await; - + let room_handle = api::RoomHandle::from(room.new_handle()); let mock_navigator = MockNavigator::new(); mock_navigator.error_get_user_media("disables_on_fail".into()); let err = get_constraints_update_exception( - JsFuture::from(room.new_handle().set_local_media_settings( + JsFuture::from(room_handle.set_local_media_settings( &media_settings_with_device_id(), true, false, @@ -2393,7 +2413,7 @@ mod set_local_media_settings { mock_navigator.stop(); assert_eq!(&err.name(), "RecoveredException"); - let err = get_jason_error(err.recover_reason()); + let err = err.recover_reason().unwrap(); assert_eq!(err.name(), "CouldNotGetLocalMedia"); assert_eq!( @@ -2411,8 +2431,9 @@ mod set_local_media_settings { #[wasm_bindgen_test] async fn rollbacks_on_fail() { let (room, peer1, _peer2) = room_with_connected_peers().await; + let room_handle = api::RoomHandle::from(room.new_handle()); - JsFuture::from(room.new_handle().set_local_media_settings( + JsFuture::from(room_handle.set_local_media_settings( &media_stream_settings(true, true), false, false, @@ -2422,7 +2443,7 @@ mod set_local_media_settings { let mock_navigator = MockNavigator::new(); let err = get_constraints_update_exception( - JsFuture::from(room.new_handle().set_local_media_settings( + JsFuture::from(room_handle.set_local_media_settings( &media_settings_with_device_id(), true, true, @@ -2433,7 +2454,7 @@ mod set_local_media_settings { mock_navigator.stop(); assert_eq!(err.name(), "RecoveredException"); - let recover_reason = get_jason_error(err.recover_reason()); + let recover_reason = err.recover_reason().unwrap(); assert_eq!(recover_reason.name(), "CouldNotGetLocalMedia"); assert_eq!(mock_navigator.get_user_media_requests_count(), 2); @@ -2447,8 +2468,9 @@ mod set_local_media_settings { #[wasm_bindgen_test] async fn disables_on_rollback_fail() { let (room, peer1, _peer2) = room_with_connected_peers().await; + let room_handle = api::RoomHandle::from(room.new_handle()); - JsFuture::from(room.new_handle().set_local_media_settings( + JsFuture::from(room_handle.set_local_media_settings( &media_stream_settings(true, true), false, false, @@ -2459,7 +2481,7 @@ mod set_local_media_settings { let mock_navigator = MockNavigator::new(); mock_navigator.error_get_user_media("disables_on_rollback_fail".into()); let err = get_constraints_update_exception( - JsFuture::from(room.new_handle().set_local_media_settings( + JsFuture::from(room_handle.set_local_media_settings( &media_settings_with_device_id(), true, true, @@ -2470,7 +2492,7 @@ mod set_local_media_settings { mock_navigator.stop(); assert_eq!(err.name(), "RecoverFailedException"); - let recover_reason = get_jason_error(err.recover_reason()); + let recover_reason = err.recover_reason().unwrap(); assert_eq!(recover_reason.name(), "CouldNotGetLocalMedia"); assert_eq!( recover_reason.message(), @@ -2480,7 +2502,7 @@ mod set_local_media_settings { let recover_fail_reasons = js_sys::Array::from(&err.recover_fail_reasons()); assert_eq!(recover_fail_reasons.length(), 1); - let recover_fail_reason = get_jason_error(recover_fail_reasons.pop()); + let recover_fail_reason = err.recover_reason().unwrap(); assert_eq!( recover_fail_reason.message(), "Failed to get local tracks: MediaDevices.getUserMedia() failed: \ @@ -2497,8 +2519,9 @@ mod set_local_media_settings { #[wasm_bindgen_test] async fn doesnt_disables_if_not_stop_first() { let (room, peer1, _peer2) = room_with_connected_peers().await; + let room_handle = api::RoomHandle::from(room.new_handle()); - JsFuture::from(room.new_handle().set_local_media_settings( + JsFuture::from(room_handle.set_local_media_settings( &media_stream_settings(true, true), false, false, @@ -2511,7 +2534,7 @@ mod set_local_media_settings { .error_get_user_media("doesnt_disables_if_not_stop_first".into()); let err = get_constraints_update_exception( - JsFuture::from(room.new_handle().set_local_media_settings( + JsFuture::from(room_handle.set_local_media_settings( &media_settings_with_device_id(), false, true, @@ -2522,7 +2545,7 @@ mod set_local_media_settings { mock_navigator.stop(); assert_eq!(err.name(), "RecoveredException"); - let err = get_jason_error(err.recover_reason()); + let err = err.recover_reason().unwrap(); assert_eq!(err.name(), "CouldNotGetLocalMedia"); assert!(peer1.is_send_video_enabled(Some(MediaSourceKind::Device))); @@ -2531,7 +2554,23 @@ mod set_local_media_settings { } mod state_synchronization { - use super::*; + use std::{ + collections::{HashMap, HashSet}, + rc::Rc, + }; + + use futures::{channel::mpsc, stream, StreamExt as _}; + use medea_client_api_proto::{ + state, AudioSettings, Command, Event, MediaType, NegotiationRole, + PeerId, TrackId, + }; + use medea_jason::{ + core::{media::MediaManager, rpc::MockRpcSession, Room}, + utils::AsProtoState, + }; + use wasm_bindgen_test::*; + + use crate::timeout; /// Checks whether [`state::Room`] update can create a [`PeerConnection`] /// and its [`Sender`]s/[`Receiver`]s. @@ -2554,10 +2593,8 @@ mod state_synchronization { rpc_session.expect_send_command().returning(move |cmd| { let _ = command_tx.unbounded_send(cmd); }); - let room = Room::new( - Rc::new(rpc_session), - Rc::new(medea_jason::media::MediaManager::default()), - ); + let room = + Room::new(Rc::new(rpc_session), Rc::new(MediaManager::default())); let mut senders = HashMap::new(); senders.insert( @@ -2620,11 +2657,13 @@ mod state_synchronization { async fn intentions_are_sent_on_reconnect() { let (event_tx, event_rx) = mpsc::unbounded(); let (room, mut commands_rx) = get_test_room(Box::pin(event_rx)); - JsFuture::from(room.new_handle().set_local_media_settings( - &media_stream_settings(true, true), - false, - false, - )) + JsFuture::from( + api::RoomHandle::from(room.new_handle()).set_local_media_settings( + &media_stream_settings(true, true), + false, + false, + ), + ) .await .unwrap(); @@ -2646,7 +2685,7 @@ async fn intentions_are_sent_on_reconnect() { } } - let room_handle = room.new_handle(); + let room_handle = api::RoomHandle::from(room.new_handle()); let peer_state = room.get_peer_state_by_id(PeerId(1)).unwrap(); peer_state.connection_lost(); diff --git a/jason/tests/rpc/backoff_delayer.rs b/jason/tests/rpc/backoff_delayer.rs index 1cec9e3d7..8d32beefb 100644 --- a/jason/tests/rpc/backoff_delayer.rs +++ b/jason/tests/rpc/backoff_delayer.rs @@ -2,7 +2,7 @@ use std::time::Duration; -use medea_jason::rpc::BackoffDelayer; +use medea_jason::core::rpc::BackoffDelayer; use wasm_bindgen_test::*; use crate::timeout; diff --git a/jason/tests/rpc/heartbeat.rs b/jason/tests/rpc/heartbeat.rs index 02e1ee133..96a55874e 100644 --- a/jason/tests/rpc/heartbeat.rs +++ b/jason/tests/rpc/heartbeat.rs @@ -7,9 +7,9 @@ use futures::{ stream, StreamExt, }; use medea_client_api_proto::{ClientMsg, ServerMsg}; -use medea_jason::rpc::{ - websocket::MockRpcTransport, Heartbeat, IdleTimeout, PingInterval, - RpcTransport, +use medea_jason::{ + core::rpc::{Heartbeat, IdleTimeout, PingInterval}, + platform::{MockRpcTransport, RpcTransport}, }; use wasm_bindgen_test::*; diff --git a/jason/tests/rpc/mod.rs b/jason/tests/rpc/mod.rs index e4ff247ca..2cfe3926d 100644 --- a/jason/tests/rpc/mod.rs +++ b/jason/tests/rpc/mod.rs @@ -17,9 +17,9 @@ use futures::{ use medea_client_api_proto::{ ClientMsg, CloseReason, Command, Event, PeerId, RpcSettings, ServerMsg, }; -use medea_jason::rpc::{ - websocket::{MockRpcTransport, RpcEvent, TransportState}, - ClientDisconnect, CloseMsg, RpcTransport, WebSocketRpcClient, +use medea_jason::{ + core::rpc::{ClientDisconnect, CloseMsg, RpcEvent, WebSocketRpcClient}, + platform::{MockRpcTransport, RpcTransport, TransportState}, }; use wasm_bindgen_futures::spawn_local; use wasm_bindgen_test::*; @@ -260,7 +260,9 @@ mod on_close { assert_eq!( ws.on_normal_close().await.unwrap(), - medea_jason::rpc::CloseReason::ByServer(CloseReason::Finished) + medea_jason::core::rpc::CloseReason::ByServer( + CloseReason::Finished + ) ); } diff --git a/jason/tests/rpc/rpc_session.rs b/jason/tests/rpc/rpc_session.rs index ed6e67669..f7b13900e 100644 --- a/jason/tests/rpc/rpc_session.rs +++ b/jason/tests/rpc/rpc_session.rs @@ -11,10 +11,14 @@ use futures::{future, stream, FutureExt as _, StreamExt as _}; use medea_client_api_proto::{ ClientMsg, CloseReason, Command, Event, ServerMsg, }; -use medea_jason::rpc::{ - websocket::{MockRpcTransport, TransportState}, - CloseMsg, ConnectionInfo, RpcSession, RpcTransport, SessionError, - WebSocketRpcClient, WebSocketRpcSession, WebSocketRpcTransport, +use medea_jason::{ + core::rpc::{ + CloseMsg, ConnectionInfo, RpcSession, SessionError, WebSocketRpcClient, + WebSocketRpcSession, + }, + platform::{ + MockRpcTransport, RpcTransport, TransportState, WebSocketRpcTransport, + }, }; use wasm_bindgen_test::*; diff --git a/jason/tests/rpc/websocket.rs b/jason/tests/rpc/websocket.rs index 6e39d54e0..3fb1ef985 100644 --- a/jason/tests/rpc/websocket.rs +++ b/jason/tests/rpc/websocket.rs @@ -1,6 +1,6 @@ #![cfg(target_arch = "wasm32")] -use medea_jason::rpc::{TransportError, WebSocketRpcTransport}; +use medea_jason::platform::{TransportError, WebSocketRpcTransport}; use url::Url; use wasm_bindgen_test::*; diff --git a/jason/tests/web.rs b/jason/tests/web.rs index a83e0a4f2..bb0d0f63f 100644 --- a/jason/tests/web.rs +++ b/jason/tests/web.rs @@ -74,9 +74,9 @@ macro_rules! js_callback { }} } -mod api; mod media; mod peer; +mod room; mod rpc; mod utils; @@ -87,13 +87,16 @@ use medea_client_api_proto::{ TrackId, VideoSettings, }; use medea_jason::{ - api::ConstraintsUpdateException, - media::{track::remote, LocalTracksConstraints, MediaKind, MediaManager}, - peer::media_exchange_state, - rpc::ApiUrl, - utils::{window, JasonError}, - AudioTrackConstraints, DeviceVideoTrackConstraints, - DisplayVideoTrackConstraints, MediaStreamSettings, + api, + core::{ + media::{ + track::remote, LocalTracksConstraints, MediaKind, MediaManager, + }, + peer::media_exchange_state, + rpc::ApiUrl, + AudioTrackConstraints, DeviceVideoTrackConstraints, + MediaStreamSettings, + }, }; use url::Url; use wasm_bindgen::prelude::*; @@ -139,7 +142,7 @@ extern "C" { #[wasm_bindgen(inline_js = "export const get_jason_error = (err) => err;")] extern "C" { - fn get_jason_error(err: JsValue) -> JasonError; + fn get_jason_error(err: JsValue) -> api::JasonError; } #[wasm_bindgen( @@ -148,7 +151,7 @@ extern "C" { extern "C" { fn get_constraints_update_exception( err: JsValue, - ) -> ConstraintsUpdateException; + ) -> api::ConstraintsUpdateException; } pub fn get_test_required_tracks() -> (Track, Track) { @@ -257,14 +260,14 @@ pub async fn delay_for(delay_ms: i32) { fn media_stream_settings( is_audio_enabled: bool, is_video_enabled: bool, -) -> MediaStreamSettings { - let mut settings = MediaStreamSettings::new(); +) -> api::MediaStreamSettings { + let mut settings = api::MediaStreamSettings::new(); if is_audio_enabled { - settings.audio(AudioTrackConstraints::default()); + settings.audio(api::AudioTrackConstraints::new()); } if is_video_enabled { - settings.device_video(DeviceVideoTrackConstraints::default()); - settings.display_video(DisplayVideoTrackConstraints::default()); + settings.device_video(api::DeviceVideoTrackConstraints::new()); + settings.display_video(api::DisplayVideoTrackConstraints::new()); } settings @@ -275,8 +278,9 @@ fn local_constraints( is_video_enabled: bool, ) -> LocalTracksConstraints { let constraints = LocalTracksConstraints::default(); - constraints - .constrain(media_stream_settings(is_audio_enabled, is_video_enabled)); + constraints.constrain( + media_stream_settings(is_audio_enabled, is_video_enabled).into(), + ); constraints } @@ -303,26 +307,26 @@ async fn wait_and_check_test_result( }; } -async fn get_video_track() -> remote::Track { +async fn get_video_track() -> api::RemoteMediaTrack { let manager = MediaManager::default(); 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.sys_track()); - remote::Track::new(track, MediaSourceKind::Device) + let mut tracks = manager.get_tracks(settings).await.unwrap(); + let track = Clone::clone(tracks.pop().unwrap().0.as_ref().as_ref()); + remote::Track::new(track, MediaSourceKind::Device).into() } -async fn get_audio_track() -> remote::Track { +async fn get_audio_track() -> api::RemoteMediaTrack { let manager = MediaManager::default(); 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.sys_track()); - remote::Track::new(track, MediaSourceKind::Device) + let mut tracks = manager.get_tracks(settings).await.unwrap(); + let track = Clone::clone(tracks.pop().unwrap().0.as_ref().as_ref()); + remote::Track::new(track, MediaSourceKind::Device).into() } /// Awaits provided [`LocalBoxFuture`] for `timeout` milliseconds. If within -/// provided `timeout` time this [`LocalBoxFuture`] won'tbe resolved, then +/// provided `timeout` time this [`LocalBoxFuture`] won't be resolved, then /// `Err(String)` will be returned, otherwise a result of the provided /// [`LocalBoxFuture`] will be returned. async fn timeout(timeout_ms: i32, future: T) -> Result @@ -345,6 +349,17 @@ pub async fn yield_now() { delay_for(0).await; } +/// Returns [`Window`] object. +/// +/// # Panics +/// +/// When global [`Window`] object is inaccessible. +pub fn window() -> web_sys::Window { + // Cannot use `lazy_static` since `window` is `!Sync`. + // Safe to unwrap. + web_sys::window().unwrap() +} + // TODO: Might be extended to proc macro at some point. #[wasm_bindgen(inline_js = "export function is_firefox() { return \ navigator.userAgent.toLowerCase().indexOf('\ From 5684aa8548702840602173b94a2d6585ae349fbd Mon Sep 17 00:00:00 2001 From: alexlapa Date: Fri, 26 Feb 2021 10:07:54 +0200 Subject: [PATCH 03/19] wip --- .clippy.toml | 2 +- Cargo.lock | 136 ++++++--------- Makefile | 2 +- jason/Cargo.toml | 6 +- jason/src/api/mod.rs | 2 + jason/src/api/wasm/connection_handle.rs | 15 +- .../api/wasm/constraints_update_exception.rs | 4 +- jason/src/api/wasm/input_device_info.rs | 4 +- jason/src/api/wasm/jason.rs | 7 +- jason/src/api/wasm/jason_error.rs | 5 +- jason/src/api/wasm/local_media_track.rs | 31 ++-- jason/src/api/wasm/media_manager_handle.rs | 25 ++- jason/src/api/wasm/mod.rs | 3 + jason/src/api/wasm/reconnect_handle.rs | 4 + jason/src/api/wasm/remote_media_track.rs | 31 ++-- jason/src/api/wasm/room_close_reason.rs | 15 +- jason/src/api/wasm/room_handle.rs | 61 +++++-- jason/src/core/media/constraints.rs | 23 ++- jason/src/core/media/manager.rs | 7 +- jason/src/core/media/track/local.rs | 15 +- jason/src/core/media/track/mod.rs | 8 + jason/src/core/mod.rs | 9 +- jason/src/core/peer/media/mod.rs | 34 ++-- jason/src/core/peer/media/receiver/mod.rs | 22 ++- jason/src/core/peer/media/sender/mod.rs | 3 + .../transitable_state/media_exchange_state.rs | 8 +- .../core/peer/media/transitable_state/mod.rs | 6 +- .../media/transitable_state/mute_state.rs | 8 +- jason/src/core/peer/mod.rs | 96 +++++++---- jason/src/core/peer/repo.rs | 18 +- jason/src/core/room.rs | 132 +++++++------- jason/src/core/rpc/heartbeat.rs | 4 + jason/src/core/rpc/mod.rs | 2 + jason/src/core/rpc/reconnect_handle.rs | 9 +- jason/src/core/rpc/rpc_session.rs | 8 +- jason/src/core/rpc/websocket/client.rs | 65 ++++--- jason/src/core/utils/errors.rs | 15 +- jason/src/core/utils/resettable_delay.rs | 2 +- jason/src/lib.rs | 4 +- jason/src/platform/mod.rs | 17 +- jason/src/platform/rtc_stats.rs | 12 +- jason/src/platform/transport.rs | 46 +---- jason/src/platform/wasm/constraints.rs | 30 ++++ jason/src/platform/wasm/error.rs | 52 ++++++ jason/src/platform/wasm/media_devices.rs | 157 +++++++++++++++++ jason/src/platform/wasm/media_track.rs | 50 ++++++ jason/src/platform/wasm/mod.rs | 163 +----------------- jason/src/platform/wasm/peer_connection.rs | 62 ++----- jason/src/platform/wasm/rtc_stats.rs | 19 +- jason/src/platform/wasm/transport.rs | 28 +-- jason/src/platform/wasm/utils/callback.rs | 62 +++++-- jason/src/platform/wasm/utils/function.rs | 29 ---- jason/src/platform/wasm/utils/mod.rs | 5 +- jason/tests/rpc/backoff_delayer.rs | 7 +- 54 files changed, 893 insertions(+), 697 deletions(-) create mode 100644 jason/src/platform/wasm/error.rs create mode 100644 jason/src/platform/wasm/media_devices.rs delete mode 100644 jason/src/platform/wasm/utils/function.rs diff --git a/.clippy.toml b/.clippy.toml index 5892ca001..ca0b1bf84 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -12,7 +12,7 @@ doc-valid-idents = [ "ConstrainDOMString", "ConstrainULong", "DOMHighResTimeStamp", "getDisplayMedia", "getUserMedia", "gRPC", - "MediaDeviceKind", "MediaDeviceInfo", + "MediaDevices", "MediaDeviceKind", "MediaDeviceInfo", "MediaStream", "MediaStreamConstraints", "MediaStreamTrack", "MediaTrackConstraints", "MessageEvent", diff --git a/Cargo.lock b/Cargo.lock index 1532d0170..90b0d5bc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -348,9 +348,9 @@ dependencies = [ [[package]] name = "adler" -version = "0.2.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +checksum = "bedc89c5c7b5550ffb9372eb5c5ffc7f9f705cc3f4a128bd4669b9745f555093" [[package]] name = "aho-corasick" @@ -494,7 +494,7 @@ dependencies = [ "async-global-executor", "async-io", "async-lock", - "crossbeam-utils 0.8.2", + "crossbeam-utils 0.8.3", "futures-channel", "futures-core", "futures-io", @@ -883,7 +883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.2", + "crossbeam-utils 0.8.3", ] [[package]] @@ -910,14 +910,13 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae8f328835f8f5a6ceb6a7842a7f2d0c03692adb5c889347235d59194731fe3" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ "autocfg", "cfg-if 1.0.0", "lazy_static", - "loom", ] [[package]] @@ -942,12 +941,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.12.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11947000d710ff98138229f633039982f0fef2d9a3f546c21d610fee5f8631d5" +checksum = "a06d4a9551359071d1890820e3571252b91229e0712e7c36b08940e603c5a8fc" dependencies = [ - "darling_core 0.12.0", - "darling_macro 0.12.0", + "darling_core 0.12.2", + "darling_macro 0.12.2", ] [[package]] @@ -966,9 +965,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.12.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae53b4d9cc89c40314ccf2bf9e6ff1eb19c31e3434542445a41893dbf041aec2" +checksum = "b443e5fb0ddd56e0c9bfa47dc060c5306ee500cb731f2b91432dd65589a77684" dependencies = [ "fnv", "ident_case", @@ -991,11 +990,11 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.12.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9cd9ac4d50d023af5e710cae1501afb063efcd917bd3fc026e8ed6493cc9755" +checksum = "c0220073ce504f12a70efc4e7cdaea9e9b1b324872e7ad96a208056d7a638b81" dependencies = [ - "darling_core 0.12.0", + "darling_core 0.12.2", "quote 1.0.9", "syn 1.0.60", ] @@ -1023,7 +1022,7 @@ dependencies = [ "async-trait", "config", "deadpool", - "futures 0.3.12", + "futures 0.3.13", "log", "redis", "serde 1.0.123", @@ -1293,15 +1292,15 @@ dependencies = [ [[package]] name = "futures" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed" +checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150" +checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1" dependencies = [ "futures-channel", "futures-core", @@ -1314,9 +1313,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d31b7ec7efab6eefc7c57233bb10b847986139d88cc2f5a02a1ae6871a1846" +checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939" dependencies = [ "futures-core", "futures-sink", @@ -1324,15 +1323,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65" +checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" [[package]] name = "futures-executor" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e59fdc009a4b3096bf94f740a0f2424c082521f20a9b08c5c07c48d90fd9b9" +checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1" dependencies = [ "futures-core", "futures-task", @@ -1341,9 +1340,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500" +checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59" [[package]] name = "futures-lite" @@ -1362,9 +1361,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd" +checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7" dependencies = [ "proc-macro-hack", "proc-macro2 1.0.24", @@ -1374,26 +1373,23 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf5c69029bda2e743fddd0582d1083951d65cc9539aebf8812f36c3491342d6" +checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3" [[package]] name = "futures-task" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13de07eb8ea81ae445aca7b69f5f7bf15d7bf4912d8ca37d6645c77ae8a58d86" -dependencies = [ - "once_cell", -] +checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" [[package]] name = "futures-util" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632a8cd0f2a4b3fdea1657f08bde063848c3bd00f9bbf6e256b8be78802e624b" +checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1" dependencies = [ - "futures 0.1.30", + "futures 0.1.31", "futures-channel", "futures-core", "futures-io", @@ -1423,19 +1419,6 @@ version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -[[package]] -name = "generator" -version = "0.6.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9fed24fd1e18827652b4d55652899a1e9da8e54d91624dc3437a5bc3a9f9a9c" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "winapi 0.3.9", -] - [[package]] name = "generic-array" version = "0.14.4" @@ -1781,17 +1764,6 @@ dependencies = [ "value-bag", ] -[[package]] -name = "loom" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44c73b4636e497b4917eb21c33539efa3816741a2d3ff26c6316f1b529481a4" -dependencies = [ - "cfg-if 1.0.0", - "generator", - "scoped-tls", -] - [[package]] name = "lru-cache" version = "0.1.2" @@ -1841,7 +1813,7 @@ dependencies = [ "dotenv", "failure", "function_name", - "futures 0.3.12", + "futures 0.3.13", "humantime-serde", "lazy_static", "medea-client-api-proto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1954,7 +1926,7 @@ dependencies = [ "bytes 0.5.6", "deadpool", "derive_more", - "futures 0.3.12", + "futures 0.3.13", "once_cell", "regex", "tokio", @@ -1971,7 +1943,7 @@ dependencies = [ "bytes 0.5.6", "deadpool", "derive_more", - "futures 0.3.12", + "futures 0.3.13", "once_cell", "regex", "tokio", @@ -1990,7 +1962,7 @@ dependencies = [ "derive_more", "downcast", "fragile", - "futures 0.3.12", + "futures 0.3.13", "js-sys", "log", "medea-client-api-proto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2040,7 +2012,7 @@ dependencies = [ name = "medea-reactive" version = "0.1.0" dependencies = [ - "futures 0.3.12", + "futures 0.3.13", "tokio", ] @@ -2050,7 +2022,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8493c11328ceb1a0bb9b5c74af84ae4abb5386838605362dfb4c17f97fbc484" dependencies = [ - "futures 0.3.12", + "futures 0.3.13", ] [[package]] @@ -2073,9 +2045,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "miniz_oxide" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", "autocfg", @@ -2240,9 +2212,9 @@ checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" [[package]] name = "once_cell" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad167a2f54e832b82dbe003a046280dceffe5227b5f79e08e363a29638cfddd" +checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a" [[package]] name = "opaque-debug" @@ -2869,9 +2841,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486" +checksum = "43535db9747a4ba938c0ce0a98cc631a46ebf943c9e1d604e091df6007620bf6" dependencies = [ "itoa", "ryu", @@ -2915,7 +2887,7 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48b35457e9d855d3dc05ef32a73e0df1e2c0fd72c38796a4ee909160c8eeec2" dependencies = [ - "darling 0.12.0", + "darling 0.12.2", "proc-macro2 1.0.24", "quote 1.0.9", "syn 1.0.60", @@ -3649,9 +3621,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f77d3842f76ca899ff2dbcf231c5c65813dea431301d6eb686279c15c4464f12" +checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" dependencies = [ "cfg-if 1.0.0", "log", @@ -3705,7 +3677,7 @@ dependencies = [ "async-trait", "backtrace", "enum-as-inner", - "futures 0.3.12", + "futures 0.3.13", "idna", "lazy_static", "log", @@ -3724,7 +3696,7 @@ checksum = "6759e8efc40465547b0dfce9500d733c65f969a4cbbfbe3ccf68daaa46ef179e" dependencies = [ "backtrace", "cfg-if 0.1.10", - "futures 0.3.12", + "futures 0.3.13", "ipconfig", "lazy_static", "log", diff --git a/Makefile b/Makefile index 55736e8db..d12bffd46 100644 --- a/Makefile +++ b/Makefile @@ -172,7 +172,7 @@ up.demo: docker.up.demo # make up.dev up.dev: up.coturn - $(MAKE) -j up.jason docker.up.medea up.control + $(MAKE) -j3 up.jason docker.up.medea up.control up.medea: docker.up.medea diff --git a/jason/Cargo.toml b/jason/Cargo.toml index e1bf277b6..eee45bb17 100644 --- a/jason/Cargo.toml +++ b/jason/Cargo.toml @@ -24,11 +24,13 @@ mockable = ["downcast", "fragile", "mockall", "predicates-tree"] async-recursion = "0.3" async-trait = "0.1" bitflags = "1.2" +console_error_panic_hook = { version = "0.1", optional = true } derivative = "2.1" derive_more = "0.99" downcast = { version = "0.10", optional = true } fragile = { version = "1.0", optional = true } futures = "0.3" +js-sys = "0.3" log = "0.4" medea-client-api-proto = { version = "0.2", features = ["jason"] } medea-macro = "0.2" @@ -39,10 +41,6 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" tracerr = "0.1" url = "2.1" - -[target.wasm32-unknown-unknown.dependencies] -console_error_panic_hook = { version = "0.1", optional = true } -js-sys = "0.3" wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4" wasm-logger = "0.2" diff --git a/jason/src/api/mod.rs b/jason/src/api/mod.rs index d76bf46b6..349d2aa5c 100644 --- a/jason/src/api/mod.rs +++ b/jason/src/api/mod.rs @@ -1,3 +1,5 @@ +//! External Jason API. + // #[cfg(all( // target_arch = "wasm32", // target_vendor = "unknown", diff --git a/jason/src/api/wasm/connection_handle.rs b/jason/src/api/wasm/connection_handle.rs index ff54c5ed7..157d346d3 100644 --- a/jason/src/api/wasm/connection_handle.rs +++ b/jason/src/api/wasm/connection_handle.rs @@ -5,14 +5,18 @@ use crate::{api::JasonError, core}; /// Connection with a specific remote `Member`, that is used on JS side. /// -/// Actually, represents a [`Weak`]-based handle to `InnerConnection`. +/// Like all handlers it contains weak reference to object that is managed by +/// Rust, so its methods will fail if weak reference could not be upgraded. #[wasm_bindgen] #[derive(From)] pub struct ConnectionHandle(core::ConnectionHandle); #[wasm_bindgen] impl ConnectionHandle { - /// Sets callback, which will be invoked when this `Connection` will close. + /// Sets callback, which will be invoked when this [`Connection`] will + /// close. + /// + /// [`Connection`]: core::Connection pub fn on_close(&self, cb: js_sys::Function) -> Result<(), JsValue> { self.0 .on_close(cb.into()) @@ -28,8 +32,11 @@ impl ConnectionHandle { .map_err(JsValue::from) } - /// Sets callback, which will be invoked when new [`remote::Track`] will be - /// added to this [`Connection`]. + /// Sets callback, which will be invoked when new [`RemoteMediaTrack`] will + /// be added to this [`Connection`]. + /// + /// [`RemoteMediaTrack`]: crate::api::RemoteMediaTrack + /// [`Connection`]: core::Connection pub fn on_remote_track_added( &self, cb: js_sys::Function, diff --git a/jason/src/api/wasm/constraints_update_exception.rs b/jason/src/api/wasm/constraints_update_exception.rs index ca6ff76d0..9675710b8 100644 --- a/jason/src/api/wasm/constraints_update_exception.rs +++ b/jason/src/api/wasm/constraints_update_exception.rs @@ -5,7 +5,9 @@ use wasm_bindgen::prelude::*; use crate::{api::JasonError, core}; -/// JS exception for the [`RoomHandle::set_local_media_settings`]. +/// Exception returned from for the [`RoomHandle::set_local_media_settings`][1]. +/// +/// [1]: crate::core::RoomHandle::set_local_media_settings #[wasm_bindgen] #[derive(Debug, From)] #[from(forward)] diff --git a/jason/src/api/wasm/input_device_info.rs b/jason/src/api/wasm/input_device_info.rs index 3fc38c140..6e18e9113 100644 --- a/jason/src/api/wasm/input_device_info.rs +++ b/jason/src/api/wasm/input_device_info.rs @@ -1,7 +1,7 @@ use derive_more::From; use wasm_bindgen::prelude::*; -use crate::platform; +use crate::{api::MediaKind, platform}; /// Representation of [MediaDeviceInfo][1]. /// @@ -22,7 +22,7 @@ impl InputDeviceInfo { /// This representation of [MediaDeviceInfo][1] ONLY for input device. /// /// [1]: https://w3.org/TR/mediacapture-streams/#device-info - pub fn kind(&self) -> super::MediaKind { + pub fn kind(&self) -> MediaKind { self.0.kind().into() } diff --git a/jason/src/api/wasm/jason.rs b/jason/src/api/wasm/jason.rs index 40b4de53c..82dbe1170 100644 --- a/jason/src/api/wasm/jason.rs +++ b/jason/src/api/wasm/jason.rs @@ -2,14 +2,11 @@ use derive_more::From; use wasm_bindgen::prelude::*; use crate::{ + api::{MediaManagerHandle, RoomHandle}, core, platform::{init_logger, set_panic_hook}, }; -use super::{ - media_manager_handle::MediaManagerHandle, room_handle::RoomHandle, -}; - /// General library interface. /// /// Responsible for managing shared transports, local media @@ -29,7 +26,7 @@ impl Jason { Self(core::Jason::new()) } - /// Creates new [`Room`] and returns its [`RoomHandle`]. + /// Creates new `Room` and returns its [`RoomHandle`]. pub fn init_room(&self) -> RoomHandle { self.0.init_room().into() } diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs index 901fbab16..adfbf216e 100644 --- a/jason/src/api/wasm/jason_error.rs +++ b/jason/src/api/wasm/jason_error.rs @@ -4,6 +4,9 @@ use wasm_bindgen::prelude::*; use crate::core; +/// Representation of app error exported to JS side. +/// +/// Contains JS side error if it the cause and trace information. #[wasm_bindgen] #[derive(From)] pub struct JasonError(core::utils::JasonError); @@ -27,6 +30,6 @@ impl JasonError { /// Returns JS side error if it the cause. pub fn source(&self) -> Option { - self.0.source() + self.0.source().and_then(|a| a.sys_cause) } } diff --git a/jason/src/api/wasm/local_media_track.rs b/jason/src/api/wasm/local_media_track.rs index 1a98fb919..9ee137789 100644 --- a/jason/src/api/wasm/local_media_track.rs +++ b/jason/src/api/wasm/local_media_track.rs @@ -2,32 +2,43 @@ use derive_more::From; use wasm_bindgen::prelude::*; -use crate::core; +use crate::{ + api::{MediaKind, MediaSourceKind}, + core, +}; -/// Wrapper around strongly referenced [`Track`] for JS side. +/// Wrapper around local [MediaStreamTrack][1]. +/// +/// Backed by strong reference to actual track that implements auto stop on +/// drop. Can be manually dropped with `free()` call. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack #[wasm_bindgen] #[derive(From)] pub struct LocalMediaTrack(core::LocalMediaTrack); #[wasm_bindgen] impl LocalMediaTrack { - /// Returns the underlying [`sys::MediaStreamTrack`] of this [`JsTrack`]. + /// Returns the underlying [MediaStreamTrack][1]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack pub fn get_track(&self) -> web_sys::MediaStreamTrack { Clone::clone(&self.0.get_track().as_ref()) } - /// Returns [`MediaKind::Audio`] if this [`JsTrack`] represents an audio - /// track, or [`MediaKind::Video`] if it represents a video track. - pub fn kind(&self) -> super::MediaKind { + /// Returns [`MediaKind::Audio`] if this [`LocalMediaTrack`] represents an + /// audio track, or [`MediaKind::Video`] if it represents a video track. + pub fn kind(&self) -> MediaKind { self.0.kind().into() } - /// Returns [`JsMediaSourceKind::Device`] if this [`JsTrack`] is sourced - /// from some device (webcam/microphone), or [`JsMediaSourceKind::Display`] - /// if ot is captured via [MediaDevices.getDisplayMedia()][1]. + /// Returns [`MediaSourceKind::Device`] if this [`LocalMediaTrack`] is + /// sourced from some device (webcam/microphone), or + /// [`MediaSourceKind::Display`] if it is captured via + /// [MediaDevices.getDisplayMedia()][1]. /// /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - pub fn media_source_kind(&self) -> super::MediaSourceKind { + pub fn media_source_kind(&self) -> MediaSourceKind { self.0.media_source_kind().into() } } diff --git a/jason/src/api/wasm/media_manager_handle.rs b/jason/src/api/wasm/media_manager_handle.rs index 47948f7d8..74d6ce3e2 100644 --- a/jason/src/api/wasm/media_manager_handle.rs +++ b/jason/src/api/wasm/media_manager_handle.rs @@ -4,22 +4,24 @@ use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; use crate::{ - api::{self, JasonError}, + api::{InputDeviceInfo, JasonError, LocalMediaTrack, MediaStreamSettings}, core, }; -use super::input_device_info::InputDeviceInfo; - -/// JS side handle to [`MediaManager`]. +/// [`MediaManagerHandle`] is a weak ref to [`MediaManager`]. /// /// [`MediaManager`] performs all media acquisition requests /// ([getUserMedia()][1]/[getDisplayMedia()][2]) and stores all received tracks /// for further reusage. /// -/// [`MediaManager`] stores weak references to [`local::Track`]s, so if there +/// [`MediaManager`] stores weak references to [`LocalMediaTrack`]s, so if there /// are no strong references to some track, then this track is stopped and /// deleted from [`MediaManager`]. /// +/// Like all handlers it contains weak reference to object that is managed by +/// Rust, so its methods will fail if weak reference could not be upgraded. +/// +/// [`MediaManager`]: core::media::MediaManager /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia #[wasm_bindgen] @@ -54,12 +56,9 @@ impl MediaManagerHandle { }) } - /// Returns [`local::JsTrack`]s objects, built from provided + /// Returns [`LocalMediaTrack`]s objects, built from provided /// [`MediaStreamSettings`]. - pub fn init_local_tracks( - &self, - caps: &api::MediaStreamSettings, - ) -> Promise { + pub fn init_local_tracks(&self, caps: &MediaStreamSettings) -> Promise { let this = self.0.clone(); let caps = caps.clone(); @@ -70,9 +69,9 @@ impl MediaManagerHandle { tracks .into_iter() .fold(js_sys::Array::new(), |tracks, track| { - tracks.push(&JsValue::from( - api::LocalMediaTrack::from(track), - )); + tracks.push(&JsValue::from(LocalMediaTrack::from( + track, + ))); tracks }) .into() diff --git a/jason/src/api/wasm/mod.rs b/jason/src/api/wasm/mod.rs index f777b8ce7..166c2bbef 100644 --- a/jason/src/api/wasm/mod.rs +++ b/jason/src/api/wasm/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::new_without_default)] + use derive_more::Display; use wasm_bindgen::prelude::*; @@ -38,6 +40,7 @@ impl From for MediaKind { } } +/// Media source type. #[wasm_bindgen] #[derive(Clone, Copy, Debug, Display, Eq, PartialEq)] pub enum MediaSourceKind { diff --git a/jason/src/api/wasm/reconnect_handle.rs b/jason/src/api/wasm/reconnect_handle.rs index efa49e167..c25f9c203 100644 --- a/jason/src/api/wasm/reconnect_handle.rs +++ b/jason/src/api/wasm/reconnect_handle.rs @@ -20,6 +20,8 @@ impl ReconnectHandle { /// If [`RpcSession`] is already reconnecting then new reconnection attempt /// won't be performed. Instead, it will wait for the first reconnection /// attempt result and use it here. + /// + /// [`RpcSession`]: core::rpc::RpcSession pub fn reconnect_with_delay(&self, delay_ms: u32) -> Promise { let this = self.0.clone(); future_to_promise(async move { @@ -48,6 +50,8 @@ impl ReconnectHandle { /// /// If `multiplier` is negative number than `multiplier` will be considered /// as `0.0`. + /// + /// [`RpcSession`]: core::rpc::RpcSession pub fn reconnect_with_backoff( &self, starting_delay_ms: u32, diff --git a/jason/src/api/wasm/remote_media_track.rs b/jason/src/api/wasm/remote_media_track.rs index 8f3bff17b..d3e0750b6 100644 --- a/jason/src/api/wasm/remote_media_track.rs +++ b/jason/src/api/wasm/remote_media_track.rs @@ -1,7 +1,10 @@ use derive_more::{From, Into}; use wasm_bindgen::prelude::*; -use crate::core; +use crate::{ + api::{MediaKind, MediaSourceKind}, + core, +}; /// Wrapper around [MediaStreamTrack][1] received from the remote. /// @@ -12,38 +15,42 @@ pub struct RemoteMediaTrack(core::remote::Track); #[wasm_bindgen] impl RemoteMediaTrack { - /// Returns the underlying [`platform::MediaStreamTrack`] of this [`Track`]. + /// Returns the underlying [MediaStreamTrack][1] of this + /// [`RemoteMediaTrack`]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack pub fn get_track(&self) -> web_sys::MediaStreamTrack { Clone::clone(self.0.get_track().as_ref()) } - /// Indicate whether this [`Track`] is enabled. + /// Indicate whether this [`RemoteMediaTrack`] is enabled. pub fn enabled(&self) -> bool { self.0.enabled() } - /// Sets callback to invoke when this [`Track`] is enabled. + /// Sets callback to invoke when this [`RemoteMediaTrack`] is enabled. pub fn on_enabled(&self, cb: js_sys::Function) { self.0.on_enabled(cb.into()) } - /// Sets callback to invoke when this [`Track`] is disabled. + /// Sets callback to invoke when this [`RemoteMediaTrack`] is disabled. pub fn on_disabled(&self, cb: js_sys::Function) { self.0.on_disabled(cb.into()) } - /// Returns [`MediaKind::Audio`] if this [`Track`] represents an audio - /// track, or [`MediaKind::Video`] if it represents a video track. - pub fn kind(&self) -> super::MediaKind { + /// Returns [`MediaKind::Audio`] if this [`RemoteMediaTrack`] represents an + /// audio track, or [`MediaKind::Video`] if it represents a video track. + pub fn kind(&self) -> MediaKind { self.0.kind().into() } - /// Returns [`JsMediaSourceKind::Device`] if this [`Track`] is sourced from - /// some device (webcam/microphone), or [`JsMediaSourceKind::Display`] if - /// it's captured via [MediaDevices.getDisplayMedia()][1]. + /// Returns [`MediaSourceKind::Device`] if this [`RemoteMediaTrack`] is + /// sourced from some device (webcam/microphone), or + /// [`MediaSourceKind::Display`] if it's captured via + /// [MediaDevices.getDisplayMedia()][1]. /// /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia - pub fn media_source_kind(&self) -> super::MediaSourceKind { + pub fn media_source_kind(&self) -> MediaSourceKind { self.0.media_source_kind().into() } } diff --git a/jason/src/api/wasm/room_close_reason.rs b/jason/src/api/wasm/room_close_reason.rs index e73b02742..4b6fc465b 100644 --- a/jason/src/api/wasm/room_close_reason.rs +++ b/jason/src/api/wasm/room_close_reason.rs @@ -6,24 +6,31 @@ use crate::core; /// Reason of why [`Room`] has been closed. /// /// This struct is passed into `on_close_by_server` JS side callback. +/// +/// [`Room`]: core::Room #[wasm_bindgen] #[derive(From)] pub struct RoomCloseReason(core::RoomCloseReason); #[wasm_bindgen] impl RoomCloseReason { - /// `wasm_bindgen` getter for [`RoomCloseReason::reason`] field. + /// [`Room`] close reason. + /// + /// [`Room`]: core::Room pub fn reason(&self) -> String { self.0.reason() } - /// `wasm_bindgen` getter for [`RoomCloseReason::is_closed_by_server`] - /// field. + /// Whether [`Room`] was closed by server. + /// + /// [`Room`]: core::Room pub fn is_closed_by_server(&self) -> bool { self.0.is_closed_by_server() } - /// `wasm_bindgen` getter for [`RoomCloseReason::is_err`] field. + /// Whether [`Room`] close reason is considered as error + /// + /// [`Room`]: core::Room pub fn is_err(&self) -> bool { self.0.is_err() } diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index 26addca6b..360b432f5 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -4,16 +4,16 @@ use wasm_bindgen::{prelude::*, JsValue}; use wasm_bindgen_futures::future_to_promise; use crate::{ - api, - api::{JasonError, MediaSourceKind}, + api::{ + ConstraintsUpdateException, JasonError, MediaSourceKind, + MediaStreamSettings, + }, core, }; -/// JS side handle to `Room` where all the media happens. +/// JS side handle to [`Room`] where all the media happens. /// -/// Actually, represents a [`Weak`]-based handle to `InnerRoom`. -/// -/// For using [`RoomHandle`] on Rust side, consider the `Room`. +/// [`Room`]: core::Room #[wasm_bindgen] #[derive(From, Into)] pub struct RoomHandle(core::RoomHandle); @@ -34,6 +34,8 @@ impl RoomHandle { /// - unable to connect to media server. /// /// Effectively returns `Result<(), JasonError>`. + /// + /// [`Room`]: core::Room pub fn join(&self, token: String) -> Promise { let this = self.0.clone(); @@ -44,9 +46,9 @@ impl RoomHandle { } /// Sets callback, which will be invoked when new [`Connection`] with some - /// remote `Peer` is established. + /// remote `Member` is established. /// - /// [`Connection`]: crate::api::Connection + /// [`Connection`]: core::Connection pub fn on_new_connection( &self, cb: js_sys::Function, @@ -59,6 +61,9 @@ impl RoomHandle { /// Sets `on_close` callback, which will be invoked on [`Room`] close, /// providing [`RoomCloseReason`]. + /// + /// [`Room`]: core::Room + /// [`RoomCloseReason`]: crate::core::RoomCloseReason pub fn on_close(&self, cb: js_sys::Function) -> Result<(), JsValue> { self.0 .on_close(cb.into()) @@ -66,12 +71,15 @@ impl RoomHandle { .map_err(JsValue::from) } - /// Sets callback, which will be invoked when new [`local::Track`] will be - /// added to this [`Room`]. + /// Sets callback, which will be invoked when new [`LocalMediaTrack`] 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. /// 3. [`MediaStreamSettings`] updated via `set_local_media_settings`. + /// + /// [`Room`]: core::Room + /// [`LocalMediaTrack`]: crate::api::LocalMediaTrack pub fn on_local_track(&self, cb: js_sys::Function) -> Result<(), JsValue> { self.0 .on_local_track(cb.into()) @@ -113,7 +121,7 @@ impl RoomHandle { /// Media obtaining/injection errors are additionally fired to /// `on_failed_local_media` callback. /// - /// If `stop_first` set to `true` then affected [`local::Track`]s will be + /// If `stop_first` set to `true` then affected [`LocalMediaTrack`]s will be /// dropped before new [`MediaStreamSettings`] is applied. This is usually /// required when changing video source device due to hardware limitations, /// e.g. having an active track sourced from device `A` may hinder @@ -126,10 +134,13 @@ impl RoomHandle { /// If recovering from fail state isn't possible then affected media types /// will be disabled. /// + /// [`Room`]: core::Room + /// [`PeerConnection`]: core::peer::PeerConnection + /// [`LocalMediaTrack`]: crate::api::LocalMediaTrack /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia pub fn set_local_media_settings( &self, - settings: &api::MediaStreamSettings, + settings: &MediaStreamSettings, stop_first: bool, rollback_on_fail: bool, ) -> Promise { @@ -143,12 +154,14 @@ impl RoomHandle { rollback_on_fail, ) .await - .map_err(api::ConstraintsUpdateException::from)?; + .map_err(ConstraintsUpdateException::from)?; Ok(JsValue::UNDEFINED) }) } /// Mutes outbound audio in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn mute_audio(&self) -> Promise { let this = self.0.clone(); @@ -159,6 +172,8 @@ impl RoomHandle { } /// Unmutes outbound audio in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn unmute_audio(&self) -> Promise { let this = self.0.clone(); @@ -169,6 +184,8 @@ impl RoomHandle { } /// Mutes outbound video in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn mute_video(&self, source_kind: Option) -> Promise { let this = self.0.clone(); @@ -181,6 +198,8 @@ impl RoomHandle { } /// Unmutes outbound video in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn unmute_video( &self, source_kind: Option, @@ -196,6 +215,8 @@ impl RoomHandle { } /// Disables outbound audio in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn disable_audio(&self) -> Promise { let this = self.0.clone(); @@ -206,6 +227,8 @@ impl RoomHandle { } /// Enables outbound audio in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn enable_audio(&self) -> Promise { let this = self.0.clone(); @@ -217,7 +240,7 @@ impl RoomHandle { /// Disables outbound video. /// - /// Affects only video with specific [`JsMediaSourceKind`] if specified. + /// Affects only video with specific [`MediaSourceKind`] if specified. pub fn disable_video( &self, source_kind: Option, @@ -235,7 +258,7 @@ impl RoomHandle { /// Enables outbound video. /// - /// Affects only video with specific [`JsMediaSourceKind`] if specified. + /// Affects only video with specific [`MediaSourceKind`] if specified. pub fn enable_video( &self, source_kind: Option, @@ -251,6 +274,8 @@ impl RoomHandle { } /// Disables inbound audio in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn disable_remote_audio(&self) -> Promise { let this = self.0.clone(); @@ -263,6 +288,8 @@ impl RoomHandle { } /// Disables inbound video in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn disable_remote_video(&self) -> Promise { let this = self.0.clone(); @@ -275,6 +302,8 @@ impl RoomHandle { } /// Enables inbound audio in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn enable_remote_audio(&self) -> Promise { let this = self.0.clone(); @@ -285,6 +314,8 @@ impl RoomHandle { } /// Enables inbound video in this [`Room`]. + /// + /// [`Room`]: core::Room pub fn enable_remote_video(&self) -> Promise { let this = self.0.clone(); diff --git a/jason/src/core/media/constraints.rs b/jason/src/core/media/constraints.rs index 14519e262..2f7b3b895 100644 --- a/jason/src/core/media/constraints.rs +++ b/jason/src/core/media/constraints.rs @@ -1,4 +1,4 @@ -// TODO: Split to multiple modules. +//! Media tracks and streams constraints functionality. use std::{ cell::{Cell, RefCell}, @@ -24,7 +24,7 @@ use crate::{ /// Local media stream for injecting into new created [`PeerConnection`]s. /// -/// [`PeerConnection`]: crate::peer::PeerConnection +/// [`PeerConnection`]: crate::core::peer::PeerConnection #[derive(Clone, Debug, Default)] pub struct LocalTracksConstraints(Rc>); @@ -217,7 +217,7 @@ pub struct VideoTrackConstraints { /// actions by [`Room`]. This flag can't be changed by /// [`MediaStreamSettings`] updating. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room enabled: bool, /// Indicator whether video should be muted. @@ -238,7 +238,7 @@ impl VideoTrackConstraints { /// Returns `true` if this [`VideoTrackConstraints`] are enabled by the /// [`Room`] and constrained with [`VideoTrackConstraints::constraints`]. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room #[inline] fn enabled(&self) -> bool { self.enabled && self.is_constrained() @@ -277,6 +277,8 @@ impl VideoTrackConstraints { /// device [`VideoTrackConstraints::constraints`]. /// /// Returns `false` if [`VideoTrackConstraints::constraints`] is not set. + /// + /// [`MediaStreamTrack`]: platform::MediaStreamTrack pub fn satisfies>( &self, track: T, @@ -293,6 +295,8 @@ impl VideoTrackConstraints { /// device [`VideoTrackConstraints::constraints`]. /// /// Returns `false` if [`VideoTrackConstraints::constraints`] is not set. + /// + /// [`MediaStreamTrack`]: platform::MediaStreamTrack pub fn satisfies>( &self, track: T, @@ -375,6 +379,8 @@ impl MediaStreamSettings { /// Unconstrains [`VideoTrackConstraints`] which this /// [`MediaStreamTrack`] satisfies by calling /// [`VideoTrackConstraints::unconstrain`]. + /// + /// [`MediaStreamTrack`]: platform::MediaStreamTrack pub fn unconstrain_if_satisfies_video(&mut self, track: T) -> bool where T: AsRef, @@ -715,17 +721,17 @@ impl From for Option { /// Constraints for the [`MediaKind::Video`] [`local::Track`]. /// -/// [`local::Track`]: crate::media::track::local::Track +/// [`local::Track`]: crate::core::media::track::local::Track #[derive(Clone, Debug)] pub enum VideoSource { /// [`local::Track`] should be received from the `getUserMedia` request. /// - /// [`local::Track`]: crate::media::track::local::Track + /// [`local::Track`]: crate::core::media::track::local::Track Device(DeviceVideoTrackConstraints), /// [`local::Track`] should be received from the `getDisplayMedia` request. /// - /// [`local::Track`]: crate::media::track::local::Track + /// [`local::Track`]: crate::core::media::track::local::Track Display(DisplayVideoTrackConstraints), } @@ -948,7 +954,6 @@ pub enum ConstrainU32 { impl ConstrainU32 { // It's up to `::TRACK_SETTINGS_FIELD_NAME` to guarantee // that such casts are safe. - #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] fn satisfies(this: Option, setting: Option) -> bool { match this { None | Some(ConstrainU32::Ideal(_)) => true, @@ -970,7 +975,9 @@ impl ConstrainU32 { /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ConstrainString { + /// The exact required value for this property. Exact(T), + /// The ideal (target) value for this property. Ideal(T), } diff --git a/jason/src/core/media/manager.rs b/jason/src/core/media/manager.rs index b9ffaeb66..eec327f89 100644 --- a/jason/src/core/media/manager.rs +++ b/jason/src/core/media/manager.rs @@ -327,12 +327,11 @@ impl MediaManagerHandle { ) -> std::result::Result, JasonError> { InnerMediaManager::enumerate_devices() .await - .map(|tracks| tracks) .map_err(tracerr::wrap!(=> MediaManagerError)) - .map_err(|e| JasonError::from(e).into()) + .map_err(JasonError::from) } - /// Returns [`local::JsTrack`]s objects, built from provided + /// Returns [`local::LocalMediaTrack`]s objects, built from provided /// [`MediaStreamSettings`]. pub async fn init_local_tracks( &self, @@ -348,6 +347,6 @@ impl MediaManagerHandle { .collect::>() }) .map_err(tracerr::wrap!(=> MediaManagerError)) - .map_err(|e| JasonError::from(e).into()) + .map_err(JasonError::from) } } diff --git a/jason/src/core/media/track/local.rs b/jason/src/core/media/track/local.rs index 7e3f2e6d1..f6ea12e2f 100644 --- a/jason/src/core/media/track/local.rs +++ b/jason/src/core/media/track/local.rs @@ -120,7 +120,7 @@ impl Drop for Track { pub struct LocalMediaTrack(Rc); impl LocalMediaTrack { - /// Creates new [`JsTrack`] from the provided [`Track`]. + /// Creates new [`LocalMediaTrack`] from the provided [`Track`]. #[inline] #[must_use] pub fn new(track: Rc) -> Self { @@ -128,20 +128,21 @@ impl LocalMediaTrack { } /// Returns the underlying [`platform::MediaStreamTrack`] of this - /// [`JsTrack`]. + /// [`LocalMediaTrack`]. pub fn get_track(&self) -> &platform::MediaStreamTrack { &self.0.track } - /// Returns [`MediaKind::Audio`] if this [`JsTrack`] represents an audio - /// track, or [`MediaKind::Video`] if it represents a video track. + /// Returns [`MediaKind::Audio`] if this [`LocalMediaTrack`] represents an + /// audio track, or [`MediaKind::Video`] if it represents a video track. pub fn kind(&self) -> MediaKind { self.0.kind() } - /// Returns [`MediaSourceKind::Device`] if this [`JsTrack`] is sourced - /// from some device (webcam/microphone), or [`MediaSourceKind::Display`] - /// if ot is captured via [MediaDevices.getDisplayMedia()][1]. + /// Returns [`MediaSourceKind::Device`] if this [`LocalMediaTrack`] is + /// sourced from some device (webcam/microphone), or + /// [`MediaSourceKind::Display`] if ot is captured via + /// [MediaDevices.getDisplayMedia()][1]. /// /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia pub fn media_source_kind(&self) -> MediaSourceKind { diff --git a/jason/src/core/media/track/mod.rs b/jason/src/core/media/track/mod.rs index edf67238a..402d9e4c0 100644 --- a/jason/src/core/media/track/mod.rs +++ b/jason/src/core/media/track/mod.rs @@ -7,9 +7,17 @@ pub mod remote; use medea_client_api_proto as proto; +/// [MediaStreamTrack][1] liveness state. +/// +/// [1]: crate::platform::MediaStreamTrack #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum MediaStreamTrackState { + /// The track is active (the track's underlying media source is making a + /// best-effort attempt to provide data in real time). Live, + /// The track has ended (the track's underlying media source is no longer + /// providing data, and will never provide more data for this track). Once + /// a track enters this state, it never exits it. Ended, } diff --git a/jason/src/core/mod.rs b/jason/src/core/mod.rs index 069fc2d39..d4d6750a8 100644 --- a/jason/src/core/mod.rs +++ b/jason/src/core/mod.rs @@ -1,4 +1,7 @@ -//! External Jason API accessible from JS. +//! Platform agnostic functionality. + +// TODO: Remove when moving JasonError to api::wasm. +#![allow(clippy::missing_errors_doc)] use futures::FutureExt as _; use std::{cell::RefCell, rc::Rc}; @@ -14,7 +17,7 @@ use self::{ #[doc(inline)] pub use self::{ - connection::{ConnectionHandle, Connections}, + connection::{Connection, ConnectionHandle, Connections}, media::{ track::{local::LocalMediaTrack, remote, MediaStreamTrackState}, AudioTrackConstraints, DeviceVideoTrackConstraints, @@ -42,7 +45,7 @@ pub mod rpc; /// and room initialization. pub struct Jason(Rc>); -pub struct Inner { +struct Inner { /// [`Jason`]s [`MediaManager`]. It's shared across [`Room`]s since /// [`MediaManager`] contains media tracks that can be used by multiple /// [`Room`]s. diff --git a/jason/src/core/peer/media/mod.rs b/jason/src/core/peer/media/mod.rs index 05417a523..9f718d515 100644 --- a/jason/src/core/peer/media/mod.rs +++ b/jason/src/core/peer/media/mod.rs @@ -1,6 +1,6 @@ //! [`PeerConnection`] media management. //! -//! [`PeerConnection`]: crate::peer::PeerConnection +//! [`PeerConnection`]: crate::core::peer::PeerConnection pub mod receiver; pub mod sender; @@ -111,7 +111,7 @@ pub trait MediaStateControllable { /// Indicates whether [`Room`] should subscribe to the [`MediaState`] update /// when updating [`MediaStateControllable`] to the provided [`MediaState`]. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room #[must_use] fn is_subscription_needed(&self, desired_state: MediaState) -> bool { match desired_state { @@ -139,7 +139,7 @@ pub trait MediaStateControllable { /// [`MediaState`]. /// /// [`TrackPatchCommand`]: medea_client_api_proto::TrackPatchCommand - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room #[must_use] fn is_track_patch_needed(&self, desired_state: MediaState) -> bool { match desired_state { @@ -217,7 +217,8 @@ pub enum MediaConnectionsError { /// Occurs when [`remote::Track`] discovered by [`RtcPeerConnection`] could /// not be inserted into [`Receiver`]. /// - /// [`remote::Track`]: crate::media::track::remote::Track + /// [`remote::Track`]: crate::core::media::track::remote::Track + /// [`RtcPeerConnection`]: platform::RtcPeerConnection /// [`Receiver`]: self::receiver::Receiver #[display( fmt = "Could not insert remote track with mid: {:?} into media \ @@ -227,6 +228,8 @@ pub enum MediaConnectionsError { CouldNotInsertRemoteTrack(String), /// Could not find [`Transceiver`] by `mid`. + /// + /// [`Transceiver`]: platform::Transceiver #[display(fmt = "Unable to find Transceiver with provided mid: {}", _0)] TransceiverNotFound(String), @@ -293,6 +296,7 @@ struct InnerMediaConnections { /// Ref to parent [`RtcPeerConnection`]. Used to generate transceivers for /// [`Sender`]s and [`Receiver`]s. /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection /// [`Sender`]: self::sender::Sender /// [`Receiver`]: self::receiver::Receiver peer: Rc, @@ -358,6 +362,9 @@ impl InnerMediaConnections { } /// Creates [`Transceiver`] and adds it to the [`RtcPeerConnection`]. + /// + /// [`Transceiver`]: platform::Transceiver + /// [`RtcPeerConnection`]: platform::RtcPeerConnection fn add_transceiver( &self, kind: MediaKind, @@ -368,6 +375,7 @@ impl InnerMediaConnections { /// Lookups [`Transceiver`] by the provided [`mid`]. /// + /// [`Transceiver`]: platform::Transceiver /// [`mid`]: https://w3.org/TR/webrtc/#dom-rtptransceiver-mid fn get_transceiver_by_mid( &self, @@ -381,11 +389,15 @@ impl InnerMediaConnections { /// Storage of [`RtcPeerConnection`]'s [`sender::Component`] and /// [`receiver::Component`]. +/// +/// [`RtcPeerConnection`]: platform::RtcPeerConnection pub struct MediaConnections(RefCell); impl MediaConnections { /// Instantiates new [`MediaConnections`] storage for a given /// [`RtcPeerConnection`]. + /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection #[inline] pub fn new( peer: Rc, @@ -467,6 +479,7 @@ impl MediaConnections { /// Errors with [`MediaConnectionsError::ReceiversWithoutMid`] if some /// [`Receiver`] doesn't have [mid]. /// + /// [`Transceiver`]: platform::Transceiver /// [`Sender`]: self::sender::Sender /// [`Receiver`]: self::receiver::Receiver /// [mid]: @@ -599,6 +612,7 @@ impl MediaConnections { /// [`local::Track`] cannot be inserted into provided [`Sender`]s /// transceiver. /// + /// [`Transceiver`]: platform::Transceiver /// [`Sender`]: self::sender::Sender /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack pub async fn insert_local_tracks( @@ -645,11 +659,7 @@ impl MediaConnections { Ok(media_exchange_state_updates) } - /// Handles [`RtcTrackEvent`] by adding new track to the corresponding - /// [`Receiver`]. - /// - /// Returns ID of associated [`Sender`] and provided track [`TrackId`], if - /// any. + /// Ads new track to the corresponding [`Receiver`]. /// /// # Errors /// @@ -671,7 +681,7 @@ impl MediaConnections { for receiver in inner.receivers.values() { if let Some(recv_mid) = &receiver.mid() { if recv_mid == &mid { - receiver.set_remote_track(transceiver, track.into()); + receiver.set_remote_track(transceiver, track); return Ok(()); } } @@ -685,8 +695,10 @@ impl MediaConnections { /// [`Transceiver`], trying to find the corresponding [`Transceiver`] in /// [`RtcPeerConnection`] and to insert it into the [`Receiver`]. /// - /// [`mid`]: https://w3.org/TR/webrtc/#dom-rtptransceiver-mid /// [`Receiver`]: self::receiver::Receiver + /// [`mid`]: https://w3.org/TR/webrtc/#dom-rtptransceiver-mid + /// [`Transceiver`]: platform::Transceiver + /// [`RtcPeerConnection`]: platform::RtcPeerConnection pub fn sync_receivers(&self) { let inner = self.0.borrow(); for receiver in inner diff --git a/jason/src/core/peer/media/receiver/mod.rs b/jason/src/core/peer/media/receiver/mod.rs index fa72bdcf2..eb9715e45 100644 --- a/jason/src/core/peer/media/receiver/mod.rs +++ b/jason/src/core/peer/media/receiver/mod.rs @@ -5,8 +5,7 @@ mod component; use std::cell::{Cell, RefCell}; use futures::channel::mpsc; -use medea_client_api_proto as proto; -use medea_client_api_proto::{MediaType, MemberId}; +use medea_client_api_proto::{self as proto, MediaType, MemberId}; use proto::TrackId; use crate::{ @@ -27,8 +26,10 @@ pub use self::component::{Component, State}; /// 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 [`Transceiver`] and the actual -/// [`remote::Track`] only when [`remote::Track`] data arrives. +/// We can save related [`Transceiver`] and the actual [`remote::Track`] only +/// when [`remote::Track`] data arrives. +/// +/// [`Transceiver`]: platform::Transceiver pub struct Receiver { track_id: TrackId, caps: TrackConstraints, @@ -49,11 +50,15 @@ impl Receiver { /// when [`remote::Track`] arrives. /// /// Created [`Transceiver`] direction is set to - /// [`TransceiverDirection::INACTIVE`] if `enabled_individual` is `false`. + /// [`TransceiverDirection::INACTIVE`][1] if `enabled_individual` is + /// `false`. /// /// `track` field in the created [`Receiver`] will be `None`, since /// [`Receiver`] must be created before the actual [`remote::Track`] data /// arrives. + /// + /// [`Transceiver`]: platform::Transceiver + /// [1]: platform::TransceiverDirection::INACTIVE pub fn new( state: &State, media_connections: &MediaConnections, @@ -172,6 +177,8 @@ impl Receiver { /// /// Sets [`platform::MediaStreamTrack::enabled`] same as /// [`Receiver::enabled`] of this [`Receiver`]. + /// + /// [`Transceiver`]: platform::Transceiver pub fn set_remote_track( &self, transceiver: platform::Transceiver, @@ -204,6 +211,9 @@ impl Receiver { /// /// No-op if provided with the same [`Transceiver`] as already exists in /// this [`Receiver`]. + /// + /// [`Transceiver`]: platform::Transceiver + /// [`TransceiverDirection`]: platform::TransceiverDirection pub fn replace_transceiver(&self, transceiver: platform::Transceiver) { if self.mid.borrow().as_ref() == transceiver.mid().as_ref() { self.transceiver.replace(Some(transceiver)); @@ -213,6 +223,8 @@ impl Receiver { /// Returns [`Transceiver`] of this [`Receiver`]. /// /// Returns [`None`] if this [`Receiver`] doesn't have [`Transceiver`]. + /// + /// [`Transceiver`]: platform::Transceiver #[inline] pub fn transceiver(&self) -> Option { self.transceiver.borrow().clone() diff --git a/jason/src/core/peer/media/sender/mod.rs b/jason/src/core/peer/media/sender/mod.rs index fed03b614..a9e8f86fa 100644 --- a/jason/src/core/peer/media/sender/mod.rs +++ b/jason/src/core/peer/media/sender/mod.rs @@ -48,6 +48,7 @@ impl Sender { /// has [`Some`] [`mid`], but this [`mid`] isn't found in the /// [`MediaConnections`]. /// + /// [`Transceiver`]: platform::Transceiver /// [`mid`]: https://w3.org/TR/webrtc/#dom-rtptransceiver-mid pub fn new( state: &State, @@ -178,6 +179,8 @@ impl Sender { } /// Returns [`Transceiver`] of this [`Sender`]. + /// + /// [`Transceiver`]: platform::Transceiver #[inline] #[must_use] pub fn transceiver(&self) -> platform::Transceiver { diff --git a/jason/src/core/peer/media/transitable_state/media_exchange_state.rs b/jason/src/core/peer/media/transitable_state/media_exchange_state.rs index 5fb8ecf2a..76e6685f0 100644 --- a/jason/src/core/peer/media/transitable_state/media_exchange_state.rs +++ b/jason/src/core/peer/media/transitable_state/media_exchange_state.rs @@ -7,12 +7,12 @@ use super::{InStable, InTransition}; pub enum Stable { /// [`MediaStateControllable`] is enabled. /// - /// [`MediaStateControllable`]: crate::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable Enabled, /// [`MediaStateControllable`] is disabled. /// - /// [`MediaStateControllable`]: crate::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable Disabled, } @@ -72,13 +72,13 @@ pub enum Transition { /// [`MediaStateControllable`] should be enabled, but awaits server /// permission. /// - /// [`MediaStateControllable`]: crate::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable Enabling(Stable), /// [`MediaStateControllable`] should be disabled, but awaits server /// permission. /// - /// [`MediaStateControllable`]: crate::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable Disabling(Stable), } diff --git a/jason/src/core/peer/media/transitable_state/mod.rs b/jason/src/core/peer/media/transitable_state/mod.rs index 1d2b2ff6d..0374f364a 100644 --- a/jason/src/core/peer/media/transitable_state/mod.rs +++ b/jason/src/core/peer/media/transitable_state/mod.rs @@ -1,6 +1,6 @@ //! [`MediaStateControllable`]s media exchange state. //! -//! [`MediaStateControllable`]: crate::peer::MediaStateControllable +//! [`MediaStateControllable`]: crate::core::peer::MediaStateControllable mod controller; pub mod media_exchange_state; @@ -25,7 +25,7 @@ pub type MuteState = /// All media states which can be toggled in the [`MediaStateControllable`]. /// -/// [`MediaStateControllable`]: crate::peer::MediaStateControllable +/// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable #[derive(Clone, Copy, Debug, From)] pub enum MediaState { /// Responsible for changing [`enabled`][1] property of @@ -116,7 +116,7 @@ pub trait InTransition: Clone + Copy + PartialEq { /// All media exchange states in which [`MediaStateControllable`] can be. /// -/// [`MediaStateControllable`]: crate::peer::MediaStateControllable +/// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TransitableState { /// State of transition. diff --git a/jason/src/core/peer/media/transitable_state/mute_state.rs b/jason/src/core/peer/media/transitable_state/mute_state.rs index 9ff5e43b9..fa051f779 100644 --- a/jason/src/core/peer/media/transitable_state/mute_state.rs +++ b/jason/src/core/peer/media/transitable_state/mute_state.rs @@ -7,12 +7,12 @@ use super::{InStable, InTransition}; pub enum Stable { /// [`MediaStateControllable`] is muted. /// - /// [`MediaStateControllable`]: crate::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable Muted, /// [`MediaStateControllable`] is unmuted. /// - /// [`MediaStateControllable`]: crate::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable Unmuted, } @@ -64,13 +64,13 @@ pub enum Transition { /// [`MediaStateControllable`] should be muted, but awaits server /// permission. /// - /// [`MediaStateControllable`]: crate::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable Muting(Stable), /// [`MediaStateControllable`] should be unmuted, but awaits server /// permission. /// - /// [`MediaStateControllable`]: crate::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable Unmuting(Stable), } diff --git a/jason/src/core/peer/mod.rs b/jason/src/core/peer/mod.rs index 5395b0726..64191aa87 100644 --- a/jason/src/core/peer/mod.rs +++ b/jason/src/core/peer/mod.rs @@ -83,8 +83,8 @@ type Result = std::result::Result>; /// Events emitted from a [`Sender`] or a [`Receiver`]. /// -/// [`Receiver`]: crate::peer::receiver::Receiver -/// [`Sender`]: crate::peer::sender::Sender +/// [`Receiver`]: crate::core::peer::receiver::Receiver +/// [`Sender`]: crate::core::peer::sender::Sender #[derive(Debug)] pub enum TrackEvent { /// Intention of the `MediaTrack` to mute/unmute himself. @@ -106,14 +106,17 @@ pub enum TrackEvent { }, } +/// Events emitted from [`RtcPeerConnection`]. +/// +/// [`RtcPeerConnection`]: platform::RtcPeerConnection #[dispatchable(self: &Self, async_trait(?Send))] #[derive(Clone)] -/// Events emitted from [`RtcPeerConnection`]. pub enum PeerEvent { /// [`RtcPeerConnection`] discovered new ICE candidate. /// /// Wrapper around [RTCPeerConnectionIceEvent][1]. /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnectioniceevent IceCandidateDiscovered { /// ID of the [`PeerConnection`] that discovered new ICE candidate. @@ -140,6 +143,8 @@ pub enum PeerEvent { /// [`RtcPeerConnection`] received new [`remote::Track`] from remote /// sender. + /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection NewRemoteTrack { /// Remote `Member` ID. sender_id: MemberId, @@ -149,6 +154,8 @@ pub enum PeerEvent { }, /// [`RtcPeerConnection`] sent new local track to remote members. + /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection NewLocalTrack { /// Local [`local::Track`] that is sent to remote members. local_track: Rc, @@ -156,6 +163,7 @@ pub enum PeerEvent { /// [`RtcPeerConnection`]'s [ICE connection][1] state changed. /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection /// [1]: https://w3.org/TR/webrtc/#dfn-ice-connection-state IceConnectionStateChanged { /// ID of the [`PeerConnection`] that sends @@ -170,6 +178,7 @@ pub enum PeerEvent { /// [`RtcPeerConnection`]'s [connection][1] state changed. /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection /// [1]: https://w3.org/TR/webrtc/#dfn-ice-connection-state ConnectionStateChanged { /// ID of the [`PeerConnection`] that sends @@ -183,11 +192,18 @@ pub enum PeerEvent { }, /// [`RtcPeerConnection`]'s [`RtcStats`] update. + /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// [`RtcStats`]: platform::RtcStats StatsUpdate { /// ID of the [`PeerConnection`] for which [`RtcStats`] was sent. + /// + /// [`RtcStats`]: platform::RtcStats peer_id: Id, /// [`RtcStats`] of this [`PeerConnection`]. + /// + /// [`RtcStats`]: platform::RtcStats stats: platform::RtcStats, }, @@ -238,15 +254,21 @@ pub enum PeerEvent { } /// High-level wrapper around [`RtcPeerConnection`]. +/// +/// [`RtcPeerConnection`]: platform::RtcPeerConnection pub struct PeerConnection { /// Unique ID of [`PeerConnection`]. id: Id, /// Underlying [`RtcPeerConnection`]. + /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection peer: Rc, /// [`sender::Component`]s and [`receiver::Component`]s of this /// [`RtcPeerConnection`]. + /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection media_connections: Rc, /// [`MediaManager`] that will be used to acquire [`local::Track`]s. @@ -256,10 +278,15 @@ pub struct PeerConnection { peer_events_sender: mpsc::UnboundedSender, /// Indicates if underlying [`RtcPeerConnection`] has remote description. + /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection has_remote_description: Cell, /// Stores [`IceCandidate`]s received before remote description for /// underlying [`RtcPeerConnection`]. + /// + /// [`IceCandidate`]: platform::IceCandidate + /// [`RtcPeerConnection`]: platform::RtcPeerConnection ice_candidates_buffer: RefCell>, /// Last hashes of the all [`RtcStats`] which was already sent to the @@ -267,6 +294,8 @@ pub struct PeerConnection { /// /// Stores precomputed hashes, since we don't need access to actual stats /// values. + /// + /// [`RtcStats`]: platform::RtcStats sent_stats_cache: RefCell>, /// Local media stream constraints used in this [`PeerConnection`]. @@ -274,7 +303,7 @@ pub struct PeerConnection { /// Collection of [`Connection`]s with a remote `Member`s. /// - /// [`Connection`]: crate::api::Connection + /// [`Connection`]: crate::core::Connection connections: Rc, /// Sender for the [`TrackEvent`]s which should be processed by this @@ -301,6 +330,8 @@ impl PeerConnection { /// /// Errors with [`PeerError::RtcPeerConnection`] if some callback of /// [`RtcPeerConnection`] can't be set. + /// + /// [`RtcPeerConnection`]: platform::RtcPeerConnection pub fn new( state: &State, peer_events_sender: mpsc::UnboundedSender, @@ -351,49 +382,45 @@ impl PeerConnection { // Bind to `icecandidate` event. let id = peer.id; let sender = peer.peer_events_sender.clone(); - peer.peer - .on_ice_candidate(Some(move |candidate| { - Self::on_ice_candidate(id, &sender, candidate); - })) - .map_err(tracerr::map_from_and_wrap!())?; + peer.peer.on_ice_candidate(Some(move |candidate| { + Self::on_ice_candidate(id, &sender, candidate); + })); // Bind to `iceconnectionstatechange` event. let id = peer.id; let sender = peer.peer_events_sender.clone(); - peer.peer - .on_ice_connection_state_change(Some(move |ice_connection_state| { + peer.peer.on_ice_connection_state_change(Some( + move |ice_connection_state| { Self::on_ice_connection_state_changed( id, &sender, ice_connection_state, ); - })) - .map_err(tracerr::map_from_and_wrap!())?; + }, + )); // Bind to `connectionstatechange` event. let id = peer.id; let sender = peer.peer_events_sender.clone(); - peer.peer - .on_connection_state_change(Some(move |peer_connection_state| { + peer.peer.on_connection_state_change(Some( + move |peer_connection_state| { Self::on_connection_state_changed( id, &sender, peer_connection_state, ) - })) - .map_err(tracerr::map_from_and_wrap!())?; + }, + )); // Bind to `track` event. let media_connections = Rc::clone(&peer.media_connections); - peer.peer - .on_track(Some(move |track, transceiver| { - if let Err(err) = - media_connections.add_remote_track(track, transceiver) - { - JasonError::from(err).print(); - }; - })) - .map_err(tracerr::map_from_and_wrap!())?; + peer.peer.on_track(Some(move |track, transceiver| { + if let Err(err) = + media_connections.add_remote_track(track, transceiver) + { + JasonError::from(err).print(); + }; + })); Ok(Rc::new(peer)) } @@ -459,6 +486,8 @@ impl PeerConnection { /// Filters out already sent stats, and send new stats from /// provided [`RtcStats`]. + /// + /// [`RtcStats`]: platform::RtcStats #[allow(clippy::option_if_let_else)] pub fn send_peer_stats(&self, stats: platform::RtcStats) { let mut stats_cache = self.sent_stats_cache.borrow_mut(); @@ -497,6 +526,8 @@ impl PeerConnection { } /// Sends [`RtcStats`] update of this [`PeerConnection`] to the server. + /// + /// [`RtcStats`]: platform::RtcStats pub async fn scrape_and_send_peer_stats(&self) { match self.peer.get_stats().await { Ok(stats) => self.send_peer_stats(stats), @@ -902,12 +933,14 @@ impl PeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::AddIceCandidateFailed`] if - /// [RtcPeerConnection.addIceCandidate()][2] fails to add buffered + /// With [`RTCPeerConnectionError::AddIceCandidateFailed`][2] if + /// [RtcPeerConnection.addIceCandidate()][3] fails to add buffered /// [ICE candidates][1]. /// + /// /// [1]: https://tools.ietf.org/html/rfc5245#section-2 - /// [2]: https://w3.org/TR/webrtc/#dom-peerconnection-addicecandidate + /// [2]: platform::RTCPeerConnectionError::AddIceCandidateFailed + /// [3]: https://w3.org/TR/webrtc/#dom-peerconnection-addicecandidate pub async fn add_ice_candidate( &self, candidate: String, @@ -1049,11 +1082,10 @@ impl Drop for PeerConnection { /// Drops `on_track` and `on_ice_candidate` callbacks to prevent possible /// leaks. fn drop(&mut self) { - let _ = self.peer.on_track::>(None); - let _ = self - .peer + self.peer .on_ice_candidate::>(None); } } diff --git a/jason/src/core/peer/repo.rs b/jason/src/core/peer/repo.rs index 6df425205..c38d79c10 100644 --- a/jason/src/core/peer/repo.rs +++ b/jason/src/core/peer/repo.rs @@ -104,21 +104,21 @@ pub struct Repository { /// Channel for sending events produced by [`PeerConnection`] to [`Room`]. /// - /// [`PeerConnection`]: crate::peer::PeerConnection - /// [`Room`]: crate::api::Room + /// [`PeerConnection`]: crate::core::peer::PeerConnection + /// [`Room`]: crate::core::Room peer_event_sender: mpsc::UnboundedSender, /// Constraints to local [`local::Track`]s that are being published by /// [`PeerConnection`]s from this [`Repository`]. /// - /// [`PeerConnection`]: crate::peer::PeerConnection - /// [`Room`]: crate::api::Room - /// [`local::Track`]: crate::media::track::local::Track + /// [`PeerConnection`]: crate::core::peer::PeerConnection + /// [`Room`]: crate::core::Room + /// [`local::Track`]: crate::core::media::track::local::Track send_constraints: LocalTracksConstraints, /// Collection of [`Connection`]s with a remote `Member`s. /// - /// [`Connection`]: crate::api::Connection + /// [`Connection`]: crate::core::Connection connections: Rc, /// Constraints to the [`remote::Track`] received by [`PeerConnection`]s @@ -126,7 +126,7 @@ pub struct Repository { /// /// Used to disable or enable media receiving. /// - /// [`remote::Track`]: crate::media::track::remote::Track + /// [`remote::Track`]: crate::core::media::track::remote::Track recv_constraints: Rc, } @@ -135,7 +135,7 @@ impl Repository { /// /// Spawns [`RtcStats`] scrape task. /// - /// [`RtcStats`]: crate::peer::RtcStats + /// [`RtcStats`]: platform::RtcStats #[must_use] pub fn new( media_manager: Rc, @@ -170,7 +170,7 @@ impl Repository { ) -> TaskHandle { let (fut, abort) = future::abortable(async move { loop { - platform::delay_for(Duration::from_secs(1).into()).await; + platform::delay_for(Duration::from_secs(1)).await; let peers = peers .borrow() diff --git a/jason/src/core/room.rs b/jason/src/core/room.rs index a1f67085a..fb06ed497 100644 --- a/jason/src/core/room.rs +++ b/jason/src/core/room.rs @@ -85,14 +85,17 @@ impl RoomCloseReason { } } + /// [`Room`] close reason. pub fn reason(&self) -> String { self.reason.clone() } + /// Whether [`Room`] was closed by server. pub fn is_closed_by_server(&self) -> bool { self.is_closed_by_server } + /// Whether [`Room`] close reason is considered as error pub fn is_err(&self) -> bool { self.is_err } @@ -115,8 +118,6 @@ pub enum RoomError { /// Returned if [`PeerConnection`] cannot receive the local tracks from /// [`MediaManager`]. - /// - /// [`MediaManager`]: crate::media::MediaManager #[display(fmt = "Failed to get local tracks: {}", _0)] #[from(ignore)] CouldNotGetLocalMedia(#[js(cause)] PeerError), @@ -139,7 +140,7 @@ pub enum RoomError { /// Returned if [`track`] update failed. /// - /// [`track`]: crate::media::track + /// [`track`]: crate::core::media::track #[display(fmt = "Failed to update Track with {} ID.", _0)] #[from(ignore)] FailedTrackPatch(TrackId), @@ -301,7 +302,7 @@ impl RoomHandle { /// Sets callback, which will be invoked when new [`Connection`] with some /// remote `Peer` is established. /// - /// [`Connection`]: crate::api::Connection + /// [`Connection`]: crate::core::Connection pub fn on_new_connection( &self, f: platform::Function, @@ -383,7 +384,11 @@ impl RoomHandle { stop_first: bool, rollback_on_fail: bool, ) -> Result<(), ConstraintsUpdateException> { - let inner = upgrade_or_detached!(self.0, JasonError).unwrap(); // TODO: remove unwrap + let inner = (self.0).upgrade().ok_or_else(|| { + ConstraintsUpdateException::Errored(new_js_error!( + HandlerDetachedError + )) + })?; inner .set_local_media_settings(settings, stop_first, rollback_on_fail) @@ -394,7 +399,7 @@ impl RoomHandle { } /// Returns [`Promise`] which will switch [`MediaState`] of the provided - /// [`MediaKind`], [`TrackDirection`] and [`JsMediaSourceKind`] to the + /// [`MediaKind`], [`TrackDirection`] and [`MediaSourceKind`] to the /// provided [`MediaState`]. /// /// Helper function for all the exported mute/unmute/enable/disable @@ -494,7 +499,7 @@ impl RoomHandle { /// Disables outbound video. /// - /// Affects only video with specific [`JsMediaSourceKind`] if specified. + /// Affects only video with specific [`MediaSourceKind`] if specified. pub async fn disable_video( &self, source_kind: Option, @@ -510,7 +515,7 @@ impl RoomHandle { /// Enables outbound video. /// - /// Affects only video with specific [`JsMediaSourceKind`] if specified. + /// Affects only video with specific [`MediaSourceKind`] if specified. pub async fn enable_video( &self, source_kind: Option, @@ -701,7 +706,7 @@ impl Room { .map_or(false, |handle_inner| Rc::ptr_eq(&self.0, &handle_inner)) } - /// Downgrades this [`Room`] to a [`WeakRoom`] reference. + /// Downgrades this [`Room`] to a weak reference. #[inline] pub fn downgrade(&self) -> WeakRoom { WeakRoom(Rc::downgrade(&self.0)) @@ -731,7 +736,7 @@ struct InnerRoom { /// Collection of [`Connection`]s with a remote `Member`s. /// - /// [`Connection`]: crate::api::Connection + /// [`Connection`]: crate::core::Connection connections: Rc, /// Callback to be invoked when new local [`local::JsTrack`] will be added @@ -740,8 +745,6 @@ struct InnerRoom { /// Callback to be invoked when failed obtain [`local::Track`]s from /// [`MediaManager`] or failed inject stream into [`PeerConnection`]. - /// - /// [`MediaManager`]: crate::media::MediaManager on_failed_local_media: Rc>, /// Callback to be invoked when [`RpcSession`] loses connection. @@ -760,14 +763,37 @@ struct InnerRoom { } /// JS exception for the [`RoomHandle::set_local_media_settings`]. -#[derive(Debug, From)] -#[from(forward)] -pub struct ConstraintsUpdateException(JsConstraintsUpdateError); +#[derive(Debug, Display)] +pub enum ConstraintsUpdateException { + /// New [`MediaStreamSettings`] set failed and state was recovered + /// accordingly to the provided recover policy + /// (`rollback_on_fail`/`stop_first` arguments). + #[display(fmt = "RecoveredException")] + Recovered { + /// [`JasonError`] due to which recovery happened. + recover_reason: JasonError, + }, + + /// New [`MediaStreamSettings`] set failed and state recovering also + /// failed. + #[display(fmt = "RecoverFailedException")] + RecoverFailed { + /// [`JasonError`] due to which recovery happened. + recover_reason: JasonError, + + /// Vector of [`JasonError`]s due to which recovery failed. + recover_fail_reasons: Vec, + }, + + /// Some other error occurred. + #[display(fmt = "ErroredException")] + Errored(JasonError), +} impl ConstraintsUpdateException { /// Returns name of this [`ConstraintsUpdateException`]. pub fn name(&self) -> String { - self.0.to_string() + self.to_string() } /// Returns [`JasonError`] if this [`ConstraintsUpdateException`] represents @@ -775,23 +801,19 @@ impl ConstraintsUpdateException { /// /// Returns `undefined` otherwise. pub fn recover_reason(&self) -> Option { - use JsConstraintsUpdateError as E; - match &self.0 { - E::RecoverFailed { recover_reason, .. } - | E::Recovered { recover_reason, .. } => { + match &self { + Self::RecoverFailed { recover_reason, .. } + | Self::Recovered { recover_reason, .. } => { Some(recover_reason.clone()) } _ => None, } } - /// Returns [`js_sys::Array`] with the [`JasonError`]s if this - /// [`ConstraintsUpdateException`] represents `RecoverFailedException`. - /// - /// Returns `undefined` otherwise. + /// Returns vector of [`JasonError`]s if this due to which recovery failed. pub fn recover_fail_reasons(&self) -> Vec { - match &self.0 { - JsConstraintsUpdateError::RecoverFailed { + match &self { + Self::RecoverFailed { recover_fail_reasons, .. } => recover_fail_reasons.clone(), @@ -804,47 +826,13 @@ impl ConstraintsUpdateException { /// /// Returns `undefined` otherwise. pub fn error(&self) -> Option { - match &self.0 { - JsConstraintsUpdateError::Errored { reason } => { - Some(reason.clone()) - } + match &self { + Self::Errored(reason) => Some(reason.clone()), _ => None, } } } -/// [`ConstraintsUpdateError`] for JS side. -/// -/// Should be wrapped to [`ConstraintsUpdateException`] before returning to the -/// JS side. -#[derive(Debug, Display)] -pub enum JsConstraintsUpdateError { - /// New [`MediaStreamSettings`] set failed and state was recovered - /// accordingly to the provided recover policy - /// (`rollback_on_fail`/`stop_first` arguments). - #[display(fmt = "RecoveredException")] - Recovered { - /// [`JasonError`] due to which recovery happened. - recover_reason: JasonError, - }, - - /// New [`MediaStreamSettings`] set failed and state recovering also - /// failed. - #[display(fmt = "RecoverFailedException")] - RecoverFailed { - /// [`JasonError`] due to which recovery happened. - recover_reason: JasonError, - - /// [`js_sys::Array`] with a [`JasonError`]s due to which recovery - /// failed. - recover_fail_reasons: Vec, - }, - - /// Some another error occurred. - #[display(fmt = "ErroredException")] - Errored { reason: JasonError }, -} - /// Constraints errors which are can occur while updating /// [`MediaStreamSettings`] by [`InnerRoom::set_local_media_settings`] call. #[derive(Debug)] @@ -909,18 +897,18 @@ impl ConstraintsUpdateError { } } -impl From for JsConstraintsUpdateError { +impl From for ConstraintsUpdateException { fn from(from: ConstraintsUpdateError) -> Self { use ConstraintsUpdateError as E; match from { E::Recovered { recover_reason } => Self::Recovered { - recover_reason: JasonError::from(recover_reason).into(), + recover_reason: JasonError::from(recover_reason), }, E::RecoverFailed { recover_reason, recover_fail_reasons, } => Self::RecoverFailed { - recover_reason: JasonError::from(recover_reason).into(), + recover_reason: JasonError::from(recover_reason), recover_fail_reasons: { recover_fail_reasons .into_iter() @@ -928,9 +916,9 @@ impl From for JsConstraintsUpdateError { .collect() }, }, - E::Errored { error: reason } => Self::Errored { - reason: JasonError::from(reason).into(), - }, + E::Errored { error: reason } => { + Self::Errored(JasonError::from(reason)) + } } } } @@ -1380,7 +1368,7 @@ 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 + /// [`Connection`]: crate::core::Connection async fn on_peer_created( &self, peer_id: PeerId, @@ -1513,8 +1501,8 @@ impl EventHandler for InnerRoom { /// Updates [`Connection`]'s [`ConnectionQualityScore`] by calling /// [`Connection::update_quality_score()`][1]. /// - /// [`Connection`]: crate::api::Connection - /// [1]: crate::api::Connection::update_quality_score + /// [`Connection`]: crate::core::Connection + /// [1]: crate::core::Connection::update_quality_score async fn on_connection_quality_updated( &self, partner_member_id: MemberId, @@ -1578,7 +1566,7 @@ impl PeerEventHandler for InnerRoom { /// Handles [`PeerEvent::NewRemoteTrack`] event and passes received /// [`remote::Track`] to the related [`Connection`]. /// - /// [`Connection`]: crate::api::Connection + /// [`Connection`]: crate::core::Connection /// [`Stream`]: futures::Stream async fn on_new_remote_track( &self, diff --git a/jason/src/core/rpc/heartbeat.rs b/jason/src/core/rpc/heartbeat.rs index 9f98eddb8..6e6b01c65 100644 --- a/jason/src/core/rpc/heartbeat.rs +++ b/jason/src/core/rpc/heartbeat.rs @@ -74,6 +74,8 @@ pub struct Heartbeat(Rc>); impl Heartbeat { /// Start this [`Heartbeat`] for the provided [`RpcTransport`] with /// the provided `idle_timeout` and `ping_interval`. + /// + /// [`RpcTransport`]: platform::RpcTransport pub fn start( transport: Rc, ping_interval: PingInterval, @@ -110,6 +112,8 @@ impl Heartbeat { /// Returns [`LocalBoxStream`] to which will sent `()` when [`Heartbeat`] /// considers that [`RpcTransport`] is idle. + /// + /// [`RpcTransport`]: platform::RpcTransport pub fn on_idle(&self) -> LocalBoxStream<'static, ()> { let (on_idle_tx, on_idle_rx) = mpsc::unbounded(); self.0.borrow_mut().on_idle_subs.push(on_idle_tx); diff --git a/jason/src/core/rpc/mod.rs b/jason/src/core/rpc/mod.rs index 375a9cbc9..0544dd059 100644 --- a/jason/src/core/rpc/mod.rs +++ b/jason/src/core/rpc/mod.rs @@ -158,6 +158,8 @@ pub enum CloseReason { /// The reason of why [`WebSocketRpcClient`]/[`RpcTransport`] went into /// closed state. +/// +/// [`RpcTransport`]: platform::RpcTransport #[derive(Clone, Debug, PartialEq)] pub enum ClosedStateReason { /// Connection with server was lost. diff --git a/jason/src/core/rpc/reconnect_handle.rs b/jason/src/core/rpc/reconnect_handle.rs index e09bcfb40..646f0cfaa 100644 --- a/jason/src/core/rpc/reconnect_handle.rs +++ b/jason/src/core/rpc/reconnect_handle.rs @@ -41,11 +41,10 @@ impl ReconnectHandle { &self, delay_ms: u32, ) -> Result<(), JasonError> { - platform::delay_for(Duration::from_millis(u64::from(delay_ms)).into()) - .await; + platform::delay_for(Duration::from_millis(u64::from(delay_ms))).await; let rpc = upgrade_or_detached!(self.0, JasonError)?; - rpc.reconnect().await.map_err(|e| JasonError::from(e))?; + rpc.reconnect().await.map_err(JasonError::from)?; Ok(()) } @@ -75,9 +74,9 @@ impl ReconnectHandle { max_delay: u32, ) -> Result<(), JasonError> { let mut backoff_delayer = BackoffDelayer::new( - Duration::from_millis(u64::from(starting_delay_ms)).into(), + Duration::from_millis(u64::from(starting_delay_ms)), multiplier, - Duration::from_millis(u64::from(max_delay)).into(), + Duration::from_millis(u64::from(max_delay)), ); backoff_delayer.delay().await; while upgrade_or_detached!(self.0, JasonError)? diff --git a/jason/src/core/rpc/rpc_session.rs b/jason/src/core/rpc/rpc_session.rs index 645637718..65aabab04 100644 --- a/jason/src/core/rpc/rpc_session.rs +++ b/jason/src/core/rpc/rpc_session.rs @@ -119,9 +119,9 @@ pub trait RpcSession { /// connection loss, JS side user should select reconnection strategy with /// [`ReconnectHandle`] (or simply close [`Room`]). /// - /// [`ReconnectHandle`]: crate::rpc::RpcTransport - /// [`Room`]: crate::api::Room - /// [`RpcTransport`]: crate::rpc::RpcTransport + /// [`ReconnectHandle`]: platform::RpcTransport + /// [`Room`]: crate::core::Room + /// [`RpcTransport`]: platform::RpcTransport /// [`Stream`]: futures::Stream fn on_connection_loss(&self) -> LocalBoxStream<'static, ()>; @@ -136,7 +136,7 @@ pub trait RpcSession { /// /// Responsible for [`Room`] authorization and closing. /// -/// [`Room`]: crate::api::Room +/// [`Room`]: crate::core::Room pub struct WebSocketRpcSession { /// [WebSocket] based Rpc Client used to . /// diff --git a/jason/src/core/rpc/websocket/client.rs b/jason/src/core/rpc/websocket/client.rs index 8138a0c09..0d7e35201 100644 --- a/jason/src/core/rpc/websocket/client.rs +++ b/jason/src/core/rpc/websocket/client.rs @@ -31,27 +31,25 @@ use crate::{ pub enum ClientDisconnect { /// [`Room`] was dropped without any [`CloseReason`]. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room RoomUnexpectedlyDropped, /// [`Room`] was normally closed by JS side. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room RoomClosed, /// [`WebSocketRpcClient`] was unexpectedly dropped. - /// - /// [`WebSocketRpcClient`]: crate::rpc::WebSocketRpcClient RpcClientUnexpectedlyDropped, /// [`RpcTransport`] was unexpectedly dropped. /// - /// [`RpcTransport`]: crate::rpc::RpcTransport + /// [`RpcTransport`]: platform::RpcTransport RpcTransportUnexpectedlyDropped, /// [`WebSocketRpcSession`] was unexpectedly dropped. /// - /// [`WebSocketRpcSession`]: crate::rpc::WebSocketRpcSession + /// [`WebSocketRpcSession`]: crate::core::rpc::WebSocketRpcSession SessionUnexpectedlyDropped, } @@ -81,6 +79,8 @@ impl From for CloseReason { } /// State of [`WebSocketRpcClient`] and [`RpcTransport`]. +/// +/// [`RpcTransport`]: platform::RpcTransport #[derive(Clone, Debug, PartialEq)] pub enum ClientState { /// [`WebSocketRpcClient`] is currently establishing a connection to RPC @@ -112,6 +112,8 @@ struct Inner { /// Reason of [`WebSocketRpcClient`] closing. /// /// This reason will be provided to the underlying [`RpcTransport`]. + /// + /// [`RpcTransport`]: platform::RpcTransport close_reason: ClientDisconnect, /// Subscribers that will be notified when underlying transport connection @@ -121,12 +123,16 @@ struct Inner { /// Closure which will create new [`RpcTransport`]s for this /// [`WebSocketRpcClient`] on each /// [`WebSocketRpcClient:: establish_connection`] call. + /// + /// [`RpcTransport`]: platform::RpcTransport rpc_transport_factory: RpcTransportFactory, /// URL that [`RpcTransport`] will connect to. /// /// [`None`] if this [`WebSocketRpcClient`] has never been connected to /// a sever. + /// + /// [`RpcTransport`]: platform::RpcTransport url: Option, /// Current [`ClientState`] of this [`WebSocketRpcClient`]. @@ -135,6 +141,8 @@ struct Inner { /// Factory closure which creates [`RpcTransport`] for /// [`WebSocketRpcClient::establish_connection`] function. +/// +/// [`RpcTransport`]: platform::RpcTransport pub type RpcTransportFactory = Box< dyn Fn( ApiUrl, @@ -173,11 +181,11 @@ pub enum RpcEvent { /// Notification of the subscribers that [`WebSocketRpcClient`] is joined /// [`Room`] on Media Server. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room JoinedRoom { /// ID of the joined [`Room`]. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room room_id: RoomId, /// ID of the joined `Member`. @@ -187,16 +195,16 @@ pub enum RpcEvent { /// Notification of the subscribers that [`WebSocketRpcClient`] left /// [`Room`] on Media Server. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room LeftRoom { /// ID of the [`Room`] being left. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room room_id: RoomId, /// Reason of why the [`Room`] has been left. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room close_reason: CloseReason, }, @@ -204,7 +212,7 @@ pub enum RpcEvent { Event { /// ID of the [`Room`] for that this [`Event`] has been received for. /// - /// [`Room`]: crate::api::Room + /// [`Room`]: crate::core::Room room_id: RoomId, /// Received [`Event`]. @@ -312,14 +320,12 @@ impl WebSocketRpcClient { }, ServerMsg::RpcSettings(settings) => { self.update_settings( - IdleTimeout( - Duration::from_millis(settings.idle_timeout_ms.into()) - .into(), - ), - PingInterval( - Duration::from_millis(settings.ping_interval_ms.into()) - .into(), - ), + IdleTimeout(Duration::from_millis( + settings.idle_timeout_ms.into(), + )), + PingInterval(Duration::from_millis( + settings.ping_interval_ms.into(), + )), ) .map_err(tracerr::wrap!(=> RpcClientError)) .map_err(|e| { @@ -340,17 +346,19 @@ impl WebSocketRpcClient { /// Starts [`Heartbeat`] with provided [`RpcSettings`] for provided /// [`RpcTransport`]. + /// + /// [`RpcTransport`]: platform::RpcTransport async fn start_heartbeat( self: Rc, transport: Rc, rpc_settings: RpcSettings, ) -> Result<(), Traced> { - let idle_timeout = IdleTimeout( - Duration::from_millis(rpc_settings.idle_timeout_ms.into()).into(), - ); - let ping_interval = PingInterval( - Duration::from_millis(rpc_settings.ping_interval_ms.into()).into(), - ); + let idle_timeout = IdleTimeout(Duration::from_millis( + rpc_settings.idle_timeout_ms.into(), + )); + let ping_interval = PingInterval(Duration::from_millis( + rpc_settings.ping_interval_ms.into(), + )); let heartbeat = Heartbeat::start(transport, ping_interval, idle_timeout); @@ -561,8 +569,9 @@ impl WebSocketRpcClient { /// connection loss, JS side user should select reconnection strategy with /// [`ReconnectHandle`] (or simply close [`Room`]). /// - /// [`ReconnectHandle`]: crate::rpc::ReconnectHandle - /// [`Room`]: crate::api::Room + /// [`RpcTransport`]: platform::RpcTransport + /// [`ReconnectHandle`]: crate::core::rpc::ReconnectHandle + /// [`Room`]: crate::core::Room /// [`Stream`]: futures::Stream pub fn on_connection_loss(&self) -> LocalBoxStream<'static, ()> { let (tx, rx) = mpsc::unbounded(); diff --git a/jason/src/core/utils/errors.rs b/jason/src/core/utils/errors.rs index 23adb8e52..7aba000a5 100644 --- a/jason/src/core/utils/errors.rs +++ b/jason/src/core/utils/errors.rs @@ -23,16 +23,15 @@ pub trait JsCaused { fn js_cause(self) -> Option; } -/// Representation of app error exported to JS side. -/// -/// Contains JS side error if it the cause and trace information. +// TODO: Consider moving to api::wasm. +/// Abstract application error. #[derive(Clone, Debug, Display)] #[display(fmt = "{}: {}\n{}", name, message, trace)] pub struct JasonError { name: &'static str, message: String, trace: Trace, - source: Option, + source: Option, } impl JasonError { @@ -52,11 +51,11 @@ impl JasonError { } /// Returns JS side error if it the cause. - pub fn source(&self) -> Option { + pub fn source(&self) -> Option { Clone::clone(&self.source) } - /// Prints error information to `console.error()`. + /// Prints error information to default logger with `ERROR` level. pub fn print(&self) { log::error!("{}", self); } @@ -64,7 +63,7 @@ impl JasonError { impl From<(E, Trace)> for JasonError where - E::Error: Into, + E::Error: Into, { fn from((err, trace): (E, Trace)) -> Self { Self { @@ -78,7 +77,7 @@ where impl From> for JasonError where - E::Error: Into, + E::Error: Into, { fn from(traced: Traced) -> Self { Self::from(traced.into_parts()) diff --git a/jason/src/core/utils/resettable_delay.rs b/jason/src/core/utils/resettable_delay.rs index 22a6d64c1..a78ab244b 100644 --- a/jason/src/core/utils/resettable_delay.rs +++ b/jason/src/core/utils/resettable_delay.rs @@ -83,7 +83,7 @@ impl ResettableDelayHandle { let future_resolver = self.future_resolver.clone(); let timeout = self.timeout; let (fut, abort) = future::abortable(async move { - platform::delay_for(timeout.into()).await; + platform::delay_for(timeout).await; if let Some(rsvr) = future_resolver.borrow_mut().take() { let _ = rsvr.send(()); } diff --git a/jason/src/lib.rs b/jason/src/lib.rs index 67bd19c06..fe84f173e 100644 --- a/jason/src/lib.rs +++ b/jason/src/lib.rs @@ -3,7 +3,9 @@ //! [Medea]: https://github.com/instrumentisto/medea // TODO: Remove `clippy::must_use_candidate` once the issue below is resolved: -// https://github.com/rust-lang/rust-clippy/issues/4779 +// https://github.com/rust-lang/rust-clippy/issues/4779. +// Remove `clippy::missing_errors_doc` when moving JasonError to +// api::wasm. #![allow(clippy::module_name_repetitions, clippy::must_use_candidate)] #![deny(broken_intra_doc_links)] #![cfg_attr(not(feature = "mockable"), warn(missing_docs))] diff --git a/jason/src/platform/mod.rs b/jason/src/platform/mod.rs index 79f534532..d930ea8cb 100644 --- a/jason/src/platform/mod.rs +++ b/jason/src/platform/mod.rs @@ -1,8 +1,6 @@ -// #[cfg(all( -// target_arch = "wasm32", -// target_vendor = "unknown", -// target_os = "unknown" -// ))] +//! Platform specific functionality. + +#[doc(inline)] pub use self::{ rtc_stats::RtcStatsError, transport::{ @@ -10,9 +8,11 @@ pub use self::{ }, wasm::{ constraints::{DisplayMediaStreamConstraints, MediaStreamConstraints}, - delay_for, enumerate_devices, get_display_media, get_property_by_name, - get_user_media, init_logger, + delay_for, + error::Error, + get_property_by_name, init_logger, input_device_info::InputDeviceInfo, + media_devices::{enumerate_devices, get_display_media, get_user_media}, media_track::MediaStreamTrack, peer_connection::{ IceCandidate, RTCPeerConnectionError, RtcPeerConnection, SdpType, @@ -20,8 +20,7 @@ pub use self::{ rtc_stats::RtcStats, set_panic_hook, spawn, transceiver::{Transceiver, TransceiverDirection}, - utils::{Callback, EventListener, EventListenerBindError, Function}, - Error, + utils::{Callback, Function}, }, }; diff --git a/jason/src/platform/rtc_stats.rs b/jason/src/platform/rtc_stats.rs index 3c38a1951..538a6841c 100644 --- a/jason/src/platform/rtc_stats.rs +++ b/jason/src/platform/rtc_stats.rs @@ -5,6 +5,8 @@ use derive_more::{Display, From}; use crate::{platform, utils::JsCaused}; /// Errors which can occur during deserialization of the [`RtcStatsType`]. +/// +/// [`RtcStatsType`]: medea_client_api_proto::stats::RtcStatsType #[derive(Clone, Debug, Display, From, JsCaused)] #[js(error = "platform::Error")] pub enum RtcStatsError { @@ -20,15 +22,17 @@ pub enum RtcStatsError { #[display(fmt = "RTCStats.stats is undefined")] UndefinedStats, - /// Some JS error occurred. - #[display(fmt = "Unexpected JS side error: {}", _0)] - Js(platform::Error), + /// Some platform error occurred. + #[display(fmt = "Unexpected platform error: {}", _0)] + Platform(platform::Error), /// `RTCStats.entries` is undefined. #[display(fmt = "RTCStats.entries is undefined")] UndefinedEntries, - /// Error of [`RtcStats`] deserialization. + /// [`RtcStats`] deserialization error. + /// + /// [`RtcStats`]: platform::RtcStats #[display(fmt = "Failed to deserialize into RtcStats: {}", _0)] ParseError(Rc), } diff --git a/jason/src/platform/transport.rs b/jason/src/platform/transport.rs index b9998bbfd..87db57386 100644 --- a/jason/src/platform/transport.rs +++ b/jason/src/platform/transport.rs @@ -8,7 +8,7 @@ use crate::{ rpc::{ClientDisconnect, CloseMsg}, utils::JsonParseError, }, - platform::{self, wasm::utils::EventListenerBindError}, + platform, utils::JsCaused, }; @@ -18,35 +18,18 @@ pub use super::wasm::transport::WebSocketRpcTransport; #[derive(Clone, Copy, Debug, PartialEq)] pub enum TransportState { /// Socket has been created. The connection is not open yet. - /// - /// Reflects `CONNECTING` state from JS side - /// [`WebSocket.readyState`][1]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState Connecting, /// The connection is open and ready to communicate. - /// - /// Reflects `OPEN` state from JS side [`WebSocket.readyState`][1]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState Open, /// The connection is in the process of closing. - /// - /// Reflects `CLOSING` state from JS side [`WebSocket.readyState`][1]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState Closing, /// The connection is closed or couldn't be opened. /// - /// Reflects `CLOSED` state from JS side [`WebSocket.readyState`][1]. - /// - /// [`CloseMsg`] is the reason of why [`RpcTransport`] went into - /// this [`TransportState`]. - /// - /// [1]: https://developer.mozilla.org/docs/Web/API/WebSocket/readyState + /// [`CloseMsg`] is the reason of why [`RpcTransport`] went into this + /// [`TransportState`]. Closed(CloseMsg), } @@ -60,12 +43,11 @@ impl TransportState { /// RPC transport between a client and a server. #[cfg_attr(feature = "mockable", mockall::automock)] pub trait RpcTransport { - /// Returns [`LocalBoxStream`] of all messages received by this - /// transport. + /// Returns [`LocalBoxStream`] of all messages received by this transport. fn on_message(&self) -> LocalBoxStream<'static, ServerMsg>; - /// Sets reason, that will be sent to remote server when this transport - /// will be dropped. + /// Sets reason, that will be sent to remote server when this transport will + /// be dropped. fn set_close_reason(&self, reason: ClientDisconnect); /// Sends given [`ClientMsg`] to a server. @@ -79,18 +61,15 @@ pub trait RpcTransport { fn on_state_change(&self) -> LocalBoxStream<'static, TransportState>; } -/// Errors that may occur when working with [`WebSocketRpcClient`]. -/// -/// [`WebSocketRpcClient`]: super::WebSocketRpcClient +/// Errors that may occur when working with [`RpcTransport`]. #[derive(Clone, Debug, Display, JsCaused, PartialEq)] #[js(error = "platform::Error")] pub enum TransportError { - /// Occurs when the port to which the connection is being attempted - /// is being blocked. + /// Error encountered when trying to establish connection. #[display(fmt = "Failed to create WebSocket: {}", _0)] CreateSocket(platform::Error), - /// Occurs when the connection close before becomes state active. + /// Connection was closed before becoming active. #[display(fmt = "Failed to init WebSocket")] InitSocket, @@ -110,13 +89,6 @@ pub enum TransportError { #[display(fmt = "Failed to send message: {}", _0)] SendMessage(platform::Error), - /// Occurs when handler failed to bind to some [WebSocket] event. Not - /// really supposed to ever happen. - /// - /// [WebSocket]: https://developer.mozilla.org/ru/docs/WebSockets - #[display(fmt = "Failed to bind to WebSocket event: {}", _0)] - WebSocketEventBindError(EventListenerBindError), // TODO: remove - /// Occurs when message is sent to a closed socket. #[display(fmt = "Underlying socket is closed")] ClosedSocket, diff --git a/jason/src/platform/wasm/constraints.rs b/jason/src/platform/wasm/constraints.rs index 8ac6b95a9..f17ee6c5f 100644 --- a/jason/src/platform/wasm/constraints.rs +++ b/jason/src/platform/wasm/constraints.rs @@ -8,23 +8,39 @@ use web_sys::{ ConstrainDomStringParameters, ConstrainDoubleRange, MediaTrackConstraints, }; +/// [MediaStreamConstraints][1] wrapper. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamconstraints #[derive(AsRef, Debug, Into)] pub struct MediaStreamConstraints(web_sys::MediaStreamConstraints); impl MediaStreamConstraints { + /// Creates new [`MediaStreamConstraints`] with none constraints configured. pub fn new() -> Self { Self(web_sys::MediaStreamConstraints::new()) } + /// Specifies the nature and settings of the audio [MediaStreamTrack][1]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn audio(&mut self, audio: AudioTrackConstraints) { self.0.audio(&MediaTrackConstraints::from(audio).into()); } + /// Specifies the nature and settings of the video [MediaStreamTrack][1]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn video(&mut self, video: DeviceVideoTrackConstraints) { self.0.video(&MediaTrackConstraints::from(video).into()); } } +impl Default for MediaStreamConstraints { + fn default() -> Self { + Self::new() + } +} + impl From for MediaTrackConstraints { fn from(track_constraints: AudioTrackConstraints) -> Self { let mut constraints = Self::new(); @@ -96,16 +112,30 @@ impl> From<&ConstrainString> for ConstrainDomStringParameters { } } +/// [`DisplayMediaStreamConstraints`][1] wrapper. +/// +/// [1]: https://www.w3.org/TR/screen-capture/#dom-displaymediastreamconstraints #[derive(AsRef, Debug, Into)] pub struct DisplayMediaStreamConstraints( web_sys::DisplayMediaStreamConstraints, ); +impl Default for DisplayMediaStreamConstraints { + fn default() -> Self { + Self::new() + } +} + impl DisplayMediaStreamConstraints { + /// Creates new [`DisplayMediaStreamConstraints`] with none constraints + /// configured. pub fn new() -> Self { Self(web_sys::DisplayMediaStreamConstraints::new()) } + /// Specifies the nature and settings of the video [MediaStreamTrack][1]. + /// + /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn video(&mut self, video: DisplayVideoTrackConstraints) { self.0.video(&MediaTrackConstraints::from(video).into()); } diff --git a/jason/src/platform/wasm/error.rs b/jason/src/platform/wasm/error.rs new file mode 100644 index 000000000..2d651b826 --- /dev/null +++ b/jason/src/platform/wasm/error.rs @@ -0,0 +1,52 @@ +use std::borrow::Cow; + +use derive_more::Display; +use wasm_bindgen::{JsCast, JsValue}; + +use crate::platform; + +/// Wrapper for JS value which returned from JS side as error. +#[derive(Clone, Debug, Display, PartialEq)] +#[display(fmt = "{}: {}", name, message)] +pub struct Error { + /// Name of JS error. + pub name: Cow<'static, str>, + + /// Message of JS error. + pub message: Cow<'static, str>, + + /// Original JS error. + pub sys_cause: Option, +} + +impl From for platform::Error { + fn from(val: JsValue) -> Self { + match val.dyn_into::() { + Ok(err) => Self { + name: Cow::Owned(err.name().into()), + message: Cow::Owned(err.message().into()), + sys_cause: Some(err), + }, + Err(val) => match val.as_string() { + Some(reason) => Self { + name: "Unknown JS error".into(), + message: reason.into(), + sys_cause: None, + }, + None => Self { + name: "Unknown JS error".into(), + message: format!("{:?}", val).into(), + sys_cause: None, + }, + }, + } + } +} + +impl From for js_sys::Error { + fn from(err: platform::Error) -> Self { + let error = Self::new(&err.message); + error.set_name(&err.name); + error + } +} diff --git a/jason/src/platform/wasm/media_devices.rs b/jason/src/platform/wasm/media_devices.rs new file mode 100644 index 000000000..eded79dc6 --- /dev/null +++ b/jason/src/platform/wasm/media_devices.rs @@ -0,0 +1,157 @@ +use std::convert::TryFrom as _; +use wasm_bindgen_futures::JsFuture; + +use tracerr::Traced; + +use crate::{ + core::media::MediaManagerError, + platform::{ + DisplayMediaStreamConstraints, Error, InputDeviceInfo, + MediaStreamConstraints, MediaStreamTrack, + }, +}; + +use super::window; + +/// Collects information about the User Agent's available media input devices. +/// +/// Adapter for [MediaDevices.enumerateDevices()][1]. +/// +/// # Errors +/// +/// With [`MediaManagerError::CouldNotGetMediaDevices`] if could not get +/// [MediaDevices][2]. +/// +/// With [`MediaManagerError::EnumerateDevicesFailed`] if +/// [MediaDevices.enumerateDevices()][1] returns error. +/// +/// [1]: https://tinyurl.com/w3-streams/#dom-mediadevices-enumeratedevices +/// [2]: https://tinyurl.com/w3-streams/#mediadevices +pub async fn enumerate_devices( +) -> Result, Traced> { + use MediaManagerError::{CouldNotGetMediaDevices, EnumerateDevicesFailed}; + + let devices = window() + .navigator() + .media_devices() + .map_err(Error::from) + .map_err(CouldNotGetMediaDevices) + .map_err(tracerr::from_and_wrap!())?; + let devices = JsFuture::from( + devices + .enumerate_devices() + .map_err(Error::from) + .map_err(EnumerateDevicesFailed) + .map_err(tracerr::from_and_wrap!())?, + ) + .await + .map_err(Error::from) + .map_err(EnumerateDevicesFailed) + .map_err(tracerr::from_and_wrap!())?; + + Ok(js_sys::Array::from(&devices) + .values() + .into_iter() + .filter_map(|info| { + let info = web_sys::MediaDeviceInfo::from(info.unwrap()); + InputDeviceInfo::try_from(info).ok() + }) + .collect()) +} + +/// Prompts the user for permission to use a media input which produces vector +/// of [`MediaStreamTrack`]s containing the requested types of media. +/// +/// Adapter for [MediaDevices.getUserMedia()][1]. +/// +/// # Errors +/// +/// With [`MediaManagerError::CouldNotGetMediaDevices`] if could not get +/// [MediaDevices][2]. +/// +/// With [`MediaManagerError::GetUserMediaFailed`] if +/// [MediaDevices.getUserMedia()][1] returns error. +/// +/// [1]: https://tinyurl.com/w3-streams/#dom-mediadevices-getusermedia +/// [2]: https://tinyurl.com/w3-streams/#mediadevices +pub async fn get_user_media( + caps: MediaStreamConstraints, +) -> Result, Traced> { + use MediaManagerError::{CouldNotGetMediaDevices, GetUserMediaFailed}; + + let media_devices = window() + .navigator() + .media_devices() + .map_err(Error::from) + .map_err(CouldNotGetMediaDevices) + .map_err(tracerr::from_and_wrap!())?; + + let stream = JsFuture::from( + media_devices + .get_user_media_with_constraints(&caps.into()) + .map_err(Error::from) + .map_err(GetUserMediaFailed) + .map_err(tracerr::from_and_wrap!())?, + ) + .await + .map(web_sys::MediaStream::from) + .map_err(Error::from) + .map_err(GetUserMediaFailed) + .map_err(tracerr::from_and_wrap!())?; + + Ok(js_sys::try_iter(&stream.get_tracks()) + .unwrap() + .unwrap() + .map(|tr| MediaStreamTrack::from(tr.unwrap())) + .collect()) +} + +/// Prompts the user to select and grant permission to capture the contents of a +/// display or portion thereof (such as a window) as vector of +/// [`MediaStreamTrack`]. +/// +/// Adapter for [MediaDevices.getDisplayMedia()][1]. +/// +/// # Errors +/// +/// With [`MediaManagerError::CouldNotGetMediaDevices`] if could not get +/// [MediaDevices][2]. +/// +/// With [`MediaManagerError::GetUserMediaFailed`] if +/// [MediaDevices.getDisplayMedia()][1] returns error. +/// +/// [1]: https://www.w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia +/// [2]: https://tinyurl.com/w3-streams/#mediadevices +pub async fn get_display_media( + caps: DisplayMediaStreamConstraints, +) -> Result, Traced> { + use MediaManagerError::{ + CouldNotGetMediaDevices, GetDisplayMediaFailed, GetUserMediaFailed, + }; + + let media_devices = window() + .navigator() + .media_devices() + .map_err(Error::from) + .map_err(CouldNotGetMediaDevices) + .map_err(tracerr::from_and_wrap!())?; + + let stream = JsFuture::from( + media_devices + .get_display_media_with_constraints(&caps.into()) + .map_err(Error::from) + .map_err(GetDisplayMediaFailed) + .map_err(tracerr::from_and_wrap!())?, + ) + .await + .map(web_sys::MediaStream::from) + .map_err(Error::from) + .map_err(GetUserMediaFailed) + .map_err(tracerr::from_and_wrap!())?; + + Ok(js_sys::try_iter(&stream.get_tracks()) + .unwrap() + .unwrap() + .map(|tr| MediaStreamTrack::from(tr.unwrap())) + .collect()) +} diff --git a/jason/src/platform/wasm/media_track.rs b/jason/src/platform/wasm/media_track.rs index e329ca5d8..773521564 100644 --- a/jason/src/platform/wasm/media_track.rs +++ b/jason/src/platform/wasm/media_track.rs @@ -2,6 +2,12 @@ use derive_more::AsRef; use crate::{api, core, platform::get_property_by_name}; +/// Wrapper around [MediaStreamTrack][1] received from from +/// [getUserMedia()][2]/[getDisplayMedia()][3] request. +/// +/// [1]: https://www.w3.org/TR/mediacapture-streams/#mediastreamtrack +/// [2]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia +/// [3]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia #[derive(AsRef, Clone, Debug)] pub struct MediaStreamTrack { #[as_ref] @@ -27,14 +33,24 @@ where } impl MediaStreamTrack { + /// Returns [`id`] of underlying [MediaStreamTrack][2]. + /// + /// [`id`]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn id(&self) -> String { self.sys_track.id() } + /// Returns this [`MediaStreamTrack`]'s kind (audio/video). pub fn kind(&self) -> core::MediaKind { self.kind } + /// Returns [`MediaStreamTrackState`][1] of underlying + /// [MediaStreamTrack][2]. + /// + /// [1]: core::MediaStreamTrackState + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn ready_state(&self) -> core::MediaStreamTrackState { let state = self.sys_track.ready_state(); match state { @@ -50,12 +66,20 @@ impl MediaStreamTrack { } } + /// Return [`deviceId`][1] of underlying [MediaStreamTrack][2]. + /// + /// [1]: https://tinyurl.com/w3-streams/#dom-mediatracksettings-deviceid + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn device_id(&self) -> Option { get_property_by_name(&self.sys_track.get_settings(), "deviceId", |v| { v.as_string() }) } + /// Return [`facingMode`][1] of underlying [MediaStreamTrack][2]. + /// + /// [1]: https://tinyurl.com/w3-streams/#dom-mediatracksettings-facingmode + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn facing_mode(&self) -> Option { let facing_mode = get_property_by_name( &self.sys_track.get_settings(), @@ -74,26 +98,52 @@ impl MediaStreamTrack { }) } + /// Return [`height`][1] of underlying [MediaStreamTrack][2]. + /// + /// [1]: https://tinyurl.com/w3-streams/#dom-mediatracksettings-height + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn height(&self) -> Option { + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] get_property_by_name(&self.sys_track.get_settings(), "height", |v| { v.as_f64().map(|v| v as u32) }) } + /// Return [`width`][1] of underlying [MediaStreamTrack][2]. + /// + /// [1]: https://tinyurl.com/w3-streams/#dom-mediatracksettings-width + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn width(&self) -> Option { + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] get_property_by_name(&self.sys_track.get_settings(), "width", |v| { v.as_f64().map(|v| v as u32) }) } + /// 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.sys_track.set_enabled(enabled); } + /// Changes [`readyState`][1] attribute on the underlying + /// [MediaStreamTrack][2] to [`ended`][3]. + /// + /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-readystate + /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + /// [3]: https://tinyurl.com/w3-streams#idl-def-MediaStreamTrackState.ended pub fn stop(&self) { self.sys_track.stop() } + /// Returns [`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 enabled(&self) -> bool { self.sys_track.enabled() } diff --git a/jason/src/platform/wasm/mod.rs b/jason/src/platform/wasm/mod.rs index ea116a93b..3a7254be7 100644 --- a/jason/src/platform/wasm/mod.rs +++ b/jason/src/platform/wasm/mod.rs @@ -1,12 +1,10 @@ -use std::{ - borrow::Cow, - convert::{TryFrom as _, TryInto as _}, - time::Duration, -}; +use std::{convert::TryInto as _, time::Duration}; pub mod constraints; +pub mod error; pub mod ice_server; pub mod input_device_info; +pub mod media_devices; pub mod media_track; pub mod peer_connection; pub mod rtc_stats; @@ -14,23 +12,12 @@ pub mod transceiver; pub mod transport; pub mod utils; -use derive_more::Display; use futures::Future; use js_sys::{Promise, Reflect}; -use tracerr::Traced; -use wasm_bindgen::{JsCast, JsValue}; +use wasm_bindgen::JsValue; use wasm_bindgen_futures::JsFuture; use web_sys::Window; -use input_device_info::InputDeviceInfo; - -use crate::{ - core::media::MediaManagerError, - platform::{ - DisplayMediaStreamConstraints, MediaStreamConstraints, MediaStreamTrack, - }, -}; - // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global // allocator. #[cfg(feature = "wee_alloc")] @@ -46,10 +33,12 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[cfg(feature = "console_error_panic_hook")] pub use console_error_panic_hook::set_once as set_panic_hook; +/// Initialize [`wasm_logger`] with default [`wasm_logger::Config`]. pub fn init_logger() { wasm_logger::init(wasm_logger::Config::default()); } +/// Runs a Rust [`Future`] on the current thread. #[inline] pub fn spawn(task: F) where @@ -58,7 +47,7 @@ where wasm_bindgen_futures::spawn_local(task); } -/// [`Future`] which resolves after the provided [`JsDuration`]. +/// [`Future`] which resolves after the provided [`Duration`]. /// /// [`Future`]: std::future::Future pub async fn delay_for(delay: Duration) { @@ -74,144 +63,6 @@ pub async fn delay_for(delay: Duration) { .unwrap(); } -pub async fn enumerate_devices( -) -> Result, Traced> { - use MediaManagerError::{CouldNotGetMediaDevices, EnumerateDevicesFailed}; - - let devices = window() - .navigator() - .media_devices() - .map_err(Error::from) - .map_err(CouldNotGetMediaDevices) - .map_err(tracerr::from_and_wrap!())?; - let devices = JsFuture::from( - devices - .enumerate_devices() - .map_err(Error::from) - .map_err(EnumerateDevicesFailed) - .map_err(tracerr::from_and_wrap!())?, - ) - .await - .map_err(Error::from) - .map_err(EnumerateDevicesFailed) - .map_err(tracerr::from_and_wrap!())?; - - Ok(js_sys::Array::from(&devices) - .values() - .into_iter() - .filter_map(|info| { - let info = web_sys::MediaDeviceInfo::from(info.unwrap()); - InputDeviceInfo::try_from(info).ok() - }) - .collect()) -} - -pub async fn get_user_media( - caps: MediaStreamConstraints, -) -> Result, Traced> { - use MediaManagerError::{CouldNotGetMediaDevices, GetUserMediaFailed}; - - let media_devices = window() - .navigator() - .media_devices() - .map_err(Error::from) - .map_err(CouldNotGetMediaDevices) - .map_err(tracerr::from_and_wrap!())?; - - let stream = JsFuture::from( - media_devices - .get_user_media_with_constraints(&caps.into()) - .map_err(Error::from) - .map_err(GetUserMediaFailed) - .map_err(tracerr::from_and_wrap!())?, - ) - .await - .map(web_sys::MediaStream::from) - .map_err(Error::from) - .map_err(GetUserMediaFailed) - .map_err(tracerr::from_and_wrap!())?; - - Ok(js_sys::try_iter(&stream.get_tracks()) - .unwrap() - .unwrap() - .map(|tr| MediaStreamTrack::from(tr.unwrap())) - .collect()) -} - -pub async fn get_display_media( - caps: DisplayMediaStreamConstraints, -) -> Result, Traced> { - use MediaManagerError::{ - CouldNotGetMediaDevices, GetDisplayMediaFailed, GetUserMediaFailed, - }; - - let media_devices = window() - .navigator() - .media_devices() - .map_err(Error::from) - .map_err(CouldNotGetMediaDevices) - .map_err(tracerr::from_and_wrap!())?; - - let stream = JsFuture::from( - media_devices - .get_display_media_with_constraints(&caps.into()) - .map_err(Error::from) - .map_err(GetDisplayMediaFailed) - .map_err(tracerr::from_and_wrap!())?, - ) - .await - .map(web_sys::MediaStream::from) - .map_err(Error::from) - .map_err(GetUserMediaFailed) - .map_err(tracerr::from_and_wrap!())?; - - Ok(js_sys::try_iter(&stream.get_tracks()) - .unwrap() - .unwrap() - .map(|tr| MediaStreamTrack::from(tr.unwrap())) - .collect()) -} - -/// Wrapper for JS value which returned from JS side as error. -#[derive(Clone, Debug, Display, PartialEq)] -#[display(fmt = "{}: {}", name, message)] -pub struct Error { - /// Name of JS error. - pub name: Cow<'static, str>, - - /// Message of JS error. - pub message: Cow<'static, str>, -} - -impl From for Error { - fn from(val: JsValue) -> Self { - match val.dyn_into::() { - Ok(err) => Self { - name: Cow::Owned(err.name().into()), - message: Cow::Owned(err.message().into()), - }, - Err(val) => match val.as_string() { - Some(reason) => Self { - name: "Unknown JS error".into(), - message: reason.into(), - }, - None => Self { - name: "Unknown JS error".into(), - message: format!("{:?}", val).into(), - }, - }, - } - } -} - -impl From for js_sys::Error { - fn from(err: Error) -> Self { - let error = Self::new(&err.message); - error.set_name(&err.name); - error - } -} - /// Returns property of JS object by name if its defined. /// Converts the value with a given predicate. pub fn get_property_by_name( diff --git a/jason/src/platform/wasm/peer_connection.rs b/jason/src/platform/wasm/peer_connection.rs index e705c9ca3..f2de94996 100644 --- a/jason/src/platform/wasm/peer_connection.rs +++ b/jason/src/platform/wasm/peer_connection.rs @@ -23,11 +23,14 @@ use crate::{ media::{MediaKind, TrackConstraints}, utils::JsCaused, }, - platform::{self, *}, + platform::{ + self, get_property_by_name, wasm::utils::EventListener, + MediaStreamTrack, RtcStats, RtcStatsError, Transceiver, + TransceiverDirection, + }, }; use super::ice_server::RtcIceServers; -use crate::platform::wasm::utils::{EventListener, EventListenerBindError}; /// [RTCIceCandidate][1] representation. /// @@ -108,14 +111,7 @@ pub enum RTCPeerConnectionError { #[from(ignore)] CreateOfferFailed(platform::Error), - /// Occurs when handler failed to bind to some [`RtcPeerConnection`] event. - /// Not really supposed to ever happen. - #[display(fmt = "Failed to bind to RTCPeerConnection event: {}", _0)] - PeerConnectionEventBindFailed(EventListenerBindError), - - /// Occurs while getting and parsing [`RtcStats`] of [`PeerConnection`]. - /// - /// [`PeerConnection`]: super::PeerConnection + /// Occurs while getting and parsing [`RtcStats`] of [`RtcPeerConnection`]. #[display(fmt = "Failed to get RTCStats: {}", _0)] RtcStatsError(#[js(cause)] RtcStatsError), @@ -236,7 +232,7 @@ impl RtcPeerConnection { }) } - /// Returns [`RtcStats`] of this [`PeerConnection`]. + /// Returns [`RtcStats`] of this [`RtcPeerConnection`]. /// /// # Errors /// @@ -246,7 +242,6 @@ impl RtcPeerConnection { /// Errors with [`RTCPeerConnectionError::GetStatsException`] when /// [PeerConnection.getStats][1] promise throws exception. /// - /// [`PeerConnection`]: super::PeerConnection /// [1]: https://tinyurl.com/w6hmt5f pub async fn get_stats(&self) -> Result { let js_stats = @@ -262,14 +257,9 @@ impl RtcPeerConnection { /// Sets handler for [`RtcTrackEvent`] event (see [RTCTrackEvent][1] and /// [`ontrack` callback][2]). /// - /// # Errors - /// - /// Errors with [`RTCPeerConnectionError::PeerConnectionEventBindFailed`] if - /// [`EventListener`] binding fails. - /// /// [1]: https://w3.org/TR/webrtc/#rtctrackevent /// [2]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection-ontrack - pub fn on_track(&self, f: Option) -> Result<()> + pub fn on_track(&self, f: Option) where F: 'static + FnMut(MediaStreamTrack, Transceiver), { @@ -290,24 +280,18 @@ impl RtcPeerConnection { ); }, ) - .map_err(tracerr::map_from_and_wrap!())?, + .unwrap(), ); } } - Ok(()) } /// Sets handler for [`RtcPeerConnectionIceEvent`] event /// (see [RTCPeerConnectionIceEvent][1] and [`onicecandidate` callback][2]). /// - /// # Errors - /// - /// Errors with [`RTCPeerConnectionError::PeerConnectionEventBindFailed`] if - /// [`EventListener`] binding fails. - /// /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnectioniceevent /// [2]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection-onicecandidate - pub fn on_ice_candidate(&self, f: Option) -> Result<()> + pub fn on_ice_candidate(&self, f: Option) where F: 'static + FnMut(IceCandidate), { @@ -335,11 +319,10 @@ impl RtcPeerConnection { } }, ) - .map_err(tracerr::map_from_and_wrap!())?, + .unwrap(), ); } } - Ok(()) } /// Returns [`RtcIceConnectionState`] of this [`RtcPeerConnection`]. @@ -360,13 +343,8 @@ impl RtcPeerConnection { /// Sets handler for [`iceconnectionstatechange`][1] event. /// - /// # Errors - /// - /// Will return [`RTCPeerConnectionError::PeerConnectionEventBindFailed`] if - /// [`EventListener`] binding fails. - /// /// [1]: https://w3.org/TR/webrtc/#event-iceconnectionstatechange - pub fn on_ice_connection_state_change(&self, f: Option) -> Result<()> + pub fn on_ice_connection_state_change(&self, f: Option) where F: 'static + FnMut(IceConnectionState), { @@ -388,24 +366,16 @@ impl RtcPeerConnection { )); }, ) - .map_err(tracerr::map_from_and_wrap!())?, + .unwrap(), ); } } - Ok(()) } /// Sets handler for [`connectionstatechange`][1] event. /// - /// # Errors - /// - /// Will return [`RTCPeerConnectionError::PeerConnectionEventBindFailed`] if - /// [`EventListener`] binding fails. - /// This error can be ignored, since this event is currently implemented - /// only in Chrome and Safari. - /// /// [1]: https://w3.org/TR/webrtc/#event-connectionstatechange - pub fn on_connection_state_change(&self, f: Option) -> Result<()> + pub fn on_connection_state_change(&self, f: Option) where F: 'static + FnMut(PeerConnectionState), { @@ -446,11 +416,10 @@ impl RtcPeerConnection { } }, ) - .map_err(tracerr::map_from_and_wrap!())?, + .unwrap(), ); } } - Ok(()) } /// Adds remote [RTCPeerConnection][1]'s [ICE candidate][2] to this @@ -483,6 +452,7 @@ impl RtcPeerConnection { .map_err(Into::into) .map_err(RTCPeerConnectionError::AddIceCandidateFailed) .map_err(tracerr::wrap!())?; + Ok(()) } diff --git a/jason/src/platform/wasm/rtc_stats.rs b/jason/src/platform/wasm/rtc_stats.rs index 891296419..6a4fc10a6 100644 --- a/jason/src/platform/wasm/rtc_stats.rs +++ b/jason/src/platform/wasm/rtc_stats.rs @@ -13,9 +13,9 @@ use wasm_bindgen::{prelude::*, JsCast}; use crate::platform::{self, get_property_by_name, RtcStatsError}; -/// All available [`RtcStatsType`] of [`PeerConnection`]. +/// All available [`RtcStatsType`] of [`RtcPeerConnection`]. /// -/// [`PeerConnection`]: crate::peer::PeerConnection +/// [`RtcPeerConnection`]: platform::RtcPeerConnection #[derive(Clone, Debug)] pub struct RtcStats(pub Vec); @@ -23,7 +23,7 @@ impl TryFrom<&JsValue> for RtcStats { type Error = Traced; fn try_from(stats: &JsValue) -> Result { - use RtcStatsError::{Js, UndefinedEntries}; + use RtcStatsError::{Platform, UndefinedEntries}; let entries_fn = get_property_by_name(&stats, "entries", |func: JsValue| { @@ -33,14 +33,15 @@ impl TryFrom<&JsValue> for RtcStats { let iterator = entries_fn .call0(stats.as_ref()) - .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))? + .map_err(|e| tracerr::new!(Platform(platform::Error::from(e))))? .unchecked_into::(); let mut stats = Vec::new(); for stat in iterator { - let stat = - stat.map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; + let stat = stat.map_err(|e| { + tracerr::new!(Platform(platform::Error::from(e))) + })?; let stat = stat.unchecked_into::(); let stat = RtcStatsReportEntry::try_from(stat) .map_err(tracerr::map_from_and_wrap!())?; @@ -66,7 +67,7 @@ impl TryFrom for RtcStatsReportEntry { type Error = Traced; fn try_from(value: JsArray) -> Result { - use RtcStatsError::{Js, UndefinedId, UndefinedStats}; + use RtcStatsError::{Platform, UndefinedId, UndefinedStats}; let id = value.get(0); let stats = value.get(1); @@ -81,10 +82,10 @@ impl TryFrom for RtcStatsReportEntry { let id = id .dyn_into::() - .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; + .map_err(|e| tracerr::new!(Platform(platform::Error::from(e))))?; let stats = stats .dyn_into::() - .map_err(|e| tracerr::new!(Js(platform::Error::from(e))))?; + .map_err(|e| tracerr::new!(Platform(platform::Error::from(e))))?; Ok(RtcStatsReportEntry(id, stats)) } diff --git a/jason/src/platform/wasm/transport.rs b/jason/src/platform/wasm/transport.rs index 6722a699f..0b1eec307 100644 --- a/jason/src/platform/wasm/transport.rs +++ b/jason/src/platform/wasm/transport.rs @@ -18,16 +18,10 @@ use crate::{ }, platform::{ transport::{RpcTransport, TransportError, TransportState}, - wasm::utils::{EventListener, EventListenerBindError}, + wasm::utils::EventListener, }, }; -impl From for TransportError { - fn from(err: EventListenerBindError) -> Self { - Self::WebSocketEventBindError(err) - } -} - /// Wrapper for help to get [`ServerMsg`] from Websocket [MessageEvent][1]. /// /// [1]: https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent @@ -158,7 +152,7 @@ impl WebSocketRpcTransport { .set(TransportState::Closed(CloseMsg::from(&msg))); }, ) - .map_err(tracerr::map_from_and_wrap!())?, + .unwrap(), ); let inner = Rc::clone(&socket); @@ -170,7 +164,7 @@ impl WebSocketRpcTransport { inner.borrow().socket_state.set(TransportState::Open); }, ) - .map_err(tracerr::map_from_and_wrap!(=> TransportError))?, + .unwrap(), ); } @@ -179,8 +173,8 @@ impl WebSocketRpcTransport { if let Some(TransportState::Open) = state { let this = Self(socket); - this.set_on_close_listener()?; - this.set_on_message_listener()?; + this.set_on_close_listener(); + this.set_on_message_listener(); Ok(this) } else { @@ -190,7 +184,7 @@ impl WebSocketRpcTransport { /// Sets [`InnerSocket::on_close_listener`] which will update /// [`RpcTransport`]'s [`TransportState`] to [`TransportState::Closed`]. - fn set_on_close_listener(&self) -> Result<()> { + fn set_on_close_listener(&self) { let this = Rc::clone(&self.0); let on_close = EventListener::new_once( Rc::clone(&self.0.borrow().socket), @@ -201,15 +195,13 @@ impl WebSocketRpcTransport { .set(TransportState::Closed(CloseMsg::from(&msg))); }, ) - .map_err(tracerr::map_from_and_wrap!(=> TransportError))?; + .unwrap(); self.0.borrow_mut().on_close_listener = Some(on_close); - - Ok(()) } /// Sets [`InnerSocket::on_message_listener`] which will send /// [`ServerMessage`]s to [`WebSocketRpcTransport::on_message`] subscribers. - fn set_on_message_listener(&self) -> Result<()> { + fn set_on_message_listener(&self) { let this = Rc::clone(&self.0); let on_message = EventListener::new_mut( Rc::clone(&self.0.borrow().socket), @@ -232,11 +224,9 @@ impl WebSocketRpcTransport { }); }, ) - .map_err(tracerr::map_from_and_wrap!(=> TransportError))?; + .unwrap(); self.0.borrow_mut().on_message_listener = Some(on_message); - - Ok(()) } } diff --git a/jason/src/platform/wasm/utils/callback.rs b/jason/src/platform/wasm/utils/callback.rs index 421f1a6ad..907f907dd 100644 --- a/jason/src/platform/wasm/utils/callback.rs +++ b/jason/src/platform/wasm/utils/callback.rs @@ -1,19 +1,11 @@ //! Somewhat convenient wrappers around JS functions used as callbacks. -use std::cell::RefCell; - -use crate::platform::Function; +use std::{cell::RefCell, marker::PhantomData}; +use wasm_bindgen::JsValue; /// Wrapper for a single argument JS function. pub struct Callback(RefCell>>); -impl Default for Callback { - #[inline] - fn default() -> Self { - Self(RefCell::new(None)) - } -} - impl Callback { /// Sets inner JS function. #[inline] @@ -29,17 +21,55 @@ impl Callback { } impl Callback<()> { + /// Invokes JS function (if any). pub fn call0(&self) { - self.0.borrow().as_ref().map(|f| f.call0()); + if let Some(f) = self.0.borrow().as_ref() { + f.call0() + }; + } +} + +impl Default for Callback { + #[inline] + fn default() -> Self { + Self(RefCell::new(None)) } } impl> Callback { - /// Invokes JS function if any. - /// - /// Returns `None` if no callback is set, otherwise returns its invocation - /// result. + /// Invokes JS function (if any) with provided argument. pub fn call1>(&self, arg: T) { - self.0.borrow().as_ref().map(|f| f.call1(arg.into())); + if let Some(f) = self.0.borrow().as_ref() { + f.call1(arg.into()) + }; + } +} + +/// Typed wrapper for [`js_sys::Function`] with single argument and no result. +pub struct Function { + inner: js_sys::Function, + _arg: PhantomData, +} + +impl Function<()> { + /// Invokes JS function. + pub fn call0(&self) { + std::mem::drop(self.inner.call0(&JsValue::NULL)); + } +} + +impl> Function { + /// Invokes JS function with provided argument. + pub fn call1(&self, arg: T) { + std::mem::drop(self.inner.call1(&JsValue::NULL, &arg.into())); + } +} + +impl From for Function { + fn from(func: js_sys::Function) -> Self { + Self { + inner: func, + _arg: PhantomData::default(), + } } } diff --git a/jason/src/platform/wasm/utils/function.rs b/jason/src/platform/wasm/utils/function.rs deleted file mode 100644 index 4c95a5855..000000000 --- a/jason/src/platform/wasm/utils/function.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::marker::PhantomData; - -use wasm_bindgen::JsValue; - -pub struct Function { - inner: js_sys::Function, - _arg: PhantomData, -} - -impl Function<()> { - pub fn call0(&self) { - let _ = self.inner.call0(&JsValue::NULL); - } -} - -impl> Function { - pub fn call1(&self, arg: T) { - let _ = self.inner.call1(&JsValue::NULL, &arg.into()); - } -} - -impl From for Function { - fn from(func: js_sys::Function) -> Self { - Self { - inner: func, - _arg: Default::default(), - } - } -} diff --git a/jason/src/platform/wasm/utils/mod.rs b/jason/src/platform/wasm/utils/mod.rs index 5e8af0602..99a766a19 100644 --- a/jason/src/platform/wasm/utils/mod.rs +++ b/jason/src/platform/wasm/utils/mod.rs @@ -1,9 +1,8 @@ mod callback; mod event_listener; -mod function; +#[doc(inline)] pub use self::{ - callback::Callback, + callback::{Callback, Function}, event_listener::{EventListener, EventListenerBindError}, - function::Function, }; diff --git a/jason/tests/rpc/backoff_delayer.rs b/jason/tests/rpc/backoff_delayer.rs index 8d32beefb..a9cff5f04 100644 --- a/jason/tests/rpc/backoff_delayer.rs +++ b/jason/tests/rpc/backoff_delayer.rs @@ -10,8 +10,6 @@ use crate::timeout; wasm_bindgen_test_configure!(run_in_browser); /// Tests that `delay` multiplies by provided `multiplier`. -/// -/// Also this test checks that [`JsDuration`] correctly multiplies by [`f32`]. #[wasm_bindgen_test] async fn multiplier_works() { let mut delayer = BackoffDelayer::new( @@ -37,9 +35,8 @@ async fn max_delay_works() { timeout(103, delayer.delay()).await.unwrap(); } -/// Tests that multiplication of [`JsDuration`] by negative `multiplier` -/// will be calculated as `0` (this is default JS behavior which is recreated in -/// [`JsDuration`] implementation). +/// Tests that multiplication by negative `multiplier` will be calculated as +/// `0`. #[wasm_bindgen_test] async fn negative_multiplier() { let mut delayer = BackoffDelayer::new( From a32c9ae2398c11ff098a475b536460de21c6a05e Mon Sep 17 00:00:00 2001 From: alexlapa Date: Mon, 1 Mar 2021 10:05:53 +0200 Subject: [PATCH 04/19] impl --- .clippy.toml | 1 + jason/src/api/mod.rs | 71 +++++++-- jason/src/api/wasm/connection_handle.rs | 8 +- .../api/wasm/constraints_update_exception.rs | 6 +- jason/src/api/wasm/jason.rs | 6 +- jason/src/api/wasm/jason_error.rs | 4 +- jason/src/api/wasm/local_media_track.rs | 4 +- jason/src/api/wasm/media_manager_handle.rs | 6 +- jason/src/api/wasm/media_stream_settings.rs | 22 +-- jason/src/api/wasm/mod.rs | 32 +--- jason/src/api/wasm/reconnect_handle.rs | 8 +- jason/src/api/wasm/remote_media_track.rs | 4 +- jason/src/api/wasm/room_close_reason.rs | 12 +- jason/src/api/wasm/room_handle.rs | 40 ++--- jason/src/{core => }/connection.rs | 9 +- jason/src/{core/mod.rs => jason.rs} | 32 +--- jason/src/lib.rs | 15 +- jason/src/{core => }/media/constraints.rs | 101 +++++++------ jason/src/{core => }/media/manager.rs | 33 ++--- jason/src/{core => }/media/mod.rs | 2 +- jason/src/{core => }/media/track/local.rs | 11 +- jason/src/{core => }/media/track/mod.rs | 4 +- jason/src/{core => }/media/track/remote.rs | 13 +- .../peer/component/ice_candidates.rs | 6 +- .../{core => }/peer/component/local_sdp.rs | 4 +- jason/src/{core => }/peer/component/mod.rs | 2 +- .../peer/component/tracks_repository.rs | 9 +- .../src/{core => }/peer/component/watchers.rs | 43 +++--- jason/src/{core => }/peer/media/mod.rs | 80 +++++----- .../peer/media/receiver/component.rs | 37 ++--- .../src/{core => }/peer/media/receiver/mod.rs | 49 +++---- .../{core => }/peer/media/sender/component.rs | 67 +++++---- jason/src/{core => }/peer/media/sender/mod.rs | 22 ++- .../media/transitable_state/controller.rs | 16 +- .../transitable_state/media_exchange_state.rs | 8 +- .../peer/media/transitable_state/mod.rs | 9 +- .../media/transitable_state/mute_state.rs | 8 +- jason/src/{core => }/peer/mod.rs | 137 +++++++----------- jason/src/{core => }/peer/repo.rs | 42 +++--- .../{core => }/peer/stream_update_criteria.rs | 2 +- jason/src/{core => }/peer/tracks_request.rs | 12 +- jason/src/platform/mod.rs | 8 +- jason/src/platform/peer_connection.rs | 103 +++++++++++++ jason/src/platform/rtc_stats.rs | 6 +- jason/src/platform/transport.rs | 10 +- jason/src/platform/wasm/constraints.rs | 11 +- jason/src/platform/wasm/error.rs | 2 + jason/src/platform/wasm/input_device_info.rs | 14 +- jason/src/platform/wasm/media_devices.rs | 8 +- jason/src/platform/wasm/media_track.rs | 49 ++++--- jason/src/platform/wasm/mod.rs | 6 +- jason/src/platform/wasm/peer_connection.rs | 111 ++------------ jason/src/platform/wasm/rtc_stats.rs | 4 +- jason/src/platform/wasm/transceiver.rs | 9 +- jason/src/platform/wasm/transport.rs | 9 +- .../src/platform/wasm/utils/event_listener.rs | 4 +- jason/src/platform/wasm/utils/mod.rs | 2 + jason/src/{core => }/room.rs | 91 ++++++------ jason/src/{core => }/rpc/backoff_delayer.rs | 0 jason/src/{core => }/rpc/heartbeat.rs | 18 +-- jason/src/{core => }/rpc/mod.rs | 8 +- jason/src/{core => }/rpc/reconnect_handle.rs | 13 +- jason/src/{core => }/rpc/rpc_session.rs | 32 ++-- jason/src/{core => }/rpc/websocket/client.rs | 72 ++++----- jason/src/{core => }/rpc/websocket/mod.rs | 0 jason/src/{core => }/utils/component.rs | 6 +- jason/src/{core => }/utils/errors.rs | 2 + jason/src/{core => }/utils/mod.rs | 0 .../src/{core => }/utils/resettable_delay.rs | 0 jason/tests/media/constraints.rs | 2 +- jason/tests/media/manager.rs | 6 +- jason/tests/media/mod.rs | 8 +- jason/tests/media/track.rs | 8 +- jason/tests/peer/media/mod.rs | 16 +- .../media/transitable_state/controller.rs | 4 +- jason/tests/peer/mod.rs | 16 +- jason/tests/room/connection.rs | 2 +- jason/tests/room/mod.rs | 14 +- jason/tests/room/room.rs | 19 +-- jason/tests/rpc/backoff_delayer.rs | 2 +- jason/tests/rpc/heartbeat.rs | 2 +- jason/tests/rpc/mod.rs | 6 +- jason/tests/rpc/rpc_session.rs | 8 +- jason/tests/web.rs | 13 +- 84 files changed, 852 insertions(+), 869 deletions(-) rename jason/src/{core => }/connection.rs (97%) rename jason/src/{core/mod.rs => jason.rs} (84%) rename jason/src/{core => }/media/constraints.rs (93%) rename jason/src/{core => }/media/manager.rs (92%) rename jason/src/{core => }/media/mod.rs (98%) rename jason/src/{core => }/media/track/local.rs (92%) rename jason/src/{core => }/media/track/mod.rs (95%) rename jason/src/{core => }/media/track/remote.rs (92%) rename jason/src/{core => }/peer/component/ice_candidates.rs (92%) rename jason/src/{core => }/peer/component/local_sdp.rs (98%) rename jason/src/{core => }/peer/component/mod.rs (99%) rename jason/src/{core => }/peer/component/tracks_repository.rs (97%) rename jason/src/{core => }/peer/component/watchers.rs (91%) rename jason/src/{core => }/peer/media/mod.rs (93%) rename jason/src/{core => }/peer/media/receiver/component.rs (92%) rename jason/src/{core => }/peer/media/receiver/mod.rs (85%) rename jason/src/{core => }/peer/media/sender/component.rs (91%) rename jason/src/{core => }/peer/media/sender/mod.rs (93%) rename jason/src/{core => }/peer/media/transitable_state/controller.rs (96%) rename jason/src/{core => }/peer/media/transitable_state/media_exchange_state.rs (90%) rename jason/src/{core => }/peer/media/transitable_state/mod.rs (96%) rename jason/src/{core => }/peer/media/transitable_state/mute_state.rs (88%) rename jason/src/{core => }/peer/mod.rs (89%) rename jason/src/{core => }/peer/repo.rs (89%) rename jason/src/{core => }/peer/stream_update_criteria.rs (98%) rename jason/src/{core => }/peer/tracks_request.rs (97%) create mode 100644 jason/src/platform/peer_connection.rs rename jason/src/{core => }/room.rs (96%) rename jason/src/{core => }/rpc/backoff_delayer.rs (100%) rename jason/src/{core => }/rpc/heartbeat.rs (92%) rename jason/src/{core => }/rpc/mod.rs (97%) rename jason/src/{core => }/rpc/reconnect_handle.rs (90%) rename jason/src/{core => }/rpc/rpc_session.rs (96%) rename jason/src/{core => }/rpc/websocket/client.rs (91%) rename jason/src/{core => }/rpc/websocket/mod.rs (100%) rename jason/src/{core => }/utils/component.rs (98%) rename jason/src/{core => }/utils/errors.rs (98%) rename jason/src/{core => }/utils/mod.rs (100%) rename jason/src/{core => }/utils/resettable_delay.rs (100%) diff --git a/.clippy.toml b/.clippy.toml index ca0b1bf84..efe55d50f 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -30,5 +30,6 @@ doc-valid-idents = [ "RTCStats", "RTCStatsReport", "RTCTrackEvent", "RTCVideoSenderStats", + "VideoFacingModeEnum", "WebRTC", "WebSocket", ] diff --git a/jason/src/api/mod.rs b/jason/src/api/mod.rs index 349d2aa5c..9643bbcd1 100644 --- a/jason/src/api/mod.rs +++ b/jason/src/api/mod.rs @@ -1,17 +1,8 @@ //! External Jason API. -// #[cfg(all( -// target_arch = "wasm32", -// target_vendor = "unknown", -// target_os = "unknown" -// ))] mod wasm; -// #[cfg(all( -// target_arch = "wasm32", -// target_vendor = "unknown", -// target_os = "unknown" -// ))] +#[doc(inline)] pub use wasm::{ connection_handle::ConnectionHandle, constraints_update_exception::ConstraintsUpdateException, @@ -30,3 +21,63 @@ pub use wasm::{ room_handle::RoomHandle, FacingMode, MediaKind, MediaSourceKind, }; + +use crate::media; + +impl From for MediaKind { + fn from(that: media::MediaKind) -> Self { + match that { + media::MediaKind::Audio => Self::Audio, + media::MediaKind::Video => Self::Video, + } + } +} + +impl From for media::MediaKind { + fn from(that: MediaKind) -> Self { + match that { + MediaKind::Audio => Self::Audio, + MediaKind::Video => Self::Video, + } + } +} + +impl From for MediaSourceKind { + fn from(that: media::MediaSourceKind) -> Self { + match that { + media::MediaSourceKind::Device => Self::Device, + media::MediaSourceKind::Display => Self::Display, + } + } +} + +impl From for media::MediaSourceKind { + fn from(that: MediaSourceKind) -> Self { + match that { + MediaSourceKind::Device => Self::Device, + MediaSourceKind::Display => Self::Display, + } + } +} + +impl From for FacingMode { + fn from(that: media::FacingMode) -> Self { + match that { + media::FacingMode::User => Self::User, + media::FacingMode::Environment => Self::Environment, + media::FacingMode::Left => Self::Left, + media::FacingMode::Right => Self::Right, + } + } +} + +impl From for media::FacingMode { + fn from(val: FacingMode) -> Self { + match val { + FacingMode::User => Self::User, + FacingMode::Environment => Self::Environment, + FacingMode::Left => Self::Left, + FacingMode::Right => Self::Right, + } + } +} diff --git a/jason/src/api/wasm/connection_handle.rs b/jason/src/api/wasm/connection_handle.rs index 157d346d3..2e0888259 100644 --- a/jason/src/api/wasm/connection_handle.rs +++ b/jason/src/api/wasm/connection_handle.rs @@ -1,7 +1,7 @@ use derive_more::From; use wasm_bindgen::prelude::*; -use crate::{api::JasonError, core}; +use crate::{api::JasonError, connection}; /// Connection with a specific remote `Member`, that is used on JS side. /// @@ -9,14 +9,14 @@ use crate::{api::JasonError, core}; /// Rust, so its methods will fail if weak reference could not be upgraded. #[wasm_bindgen] #[derive(From)] -pub struct ConnectionHandle(core::ConnectionHandle); +pub struct ConnectionHandle(connection::ConnectionHandle); #[wasm_bindgen] impl ConnectionHandle { /// Sets callback, which will be invoked when this [`Connection`] will /// close. /// - /// [`Connection`]: core::Connection + /// [`Connection`]: connection::Connection pub fn on_close(&self, cb: js_sys::Function) -> Result<(), JsValue> { self.0 .on_close(cb.into()) @@ -36,7 +36,7 @@ impl ConnectionHandle { /// be added to this [`Connection`]. /// /// [`RemoteMediaTrack`]: crate::api::RemoteMediaTrack - /// [`Connection`]: core::Connection + /// [`Connection`]: connection::Connection pub fn on_remote_track_added( &self, cb: js_sys::Function, diff --git a/jason/src/api/wasm/constraints_update_exception.rs b/jason/src/api/wasm/constraints_update_exception.rs index 9675710b8..372799730 100644 --- a/jason/src/api/wasm/constraints_update_exception.rs +++ b/jason/src/api/wasm/constraints_update_exception.rs @@ -3,15 +3,15 @@ use std::iter::FromIterator as _; use derive_more::From; use wasm_bindgen::prelude::*; -use crate::{api::JasonError, core}; +use crate::{api::JasonError, room}; /// Exception returned from for the [`RoomHandle::set_local_media_settings`][1]. /// -/// [1]: crate::core::RoomHandle::set_local_media_settings +/// [1]: crate::api::RoomHandle::set_local_media_settings #[wasm_bindgen] #[derive(Debug, From)] #[from(forward)] -pub struct ConstraintsUpdateException(core::ConstraintsUpdateException); +pub struct ConstraintsUpdateException(room::ConstraintsUpdateException); #[wasm_bindgen] impl ConstraintsUpdateException { diff --git a/jason/src/api/wasm/jason.rs b/jason/src/api/wasm/jason.rs index 82dbe1170..d5548009e 100644 --- a/jason/src/api/wasm/jason.rs +++ b/jason/src/api/wasm/jason.rs @@ -3,7 +3,7 @@ use wasm_bindgen::prelude::*; use crate::{ api::{MediaManagerHandle, RoomHandle}, - core, + jason, platform::{init_logger, set_panic_hook}, }; @@ -13,7 +13,7 @@ use crate::{ /// and room initialization. #[wasm_bindgen] #[derive(From)] -pub struct Jason(core::Jason); +pub struct Jason(jason::Jason); #[wasm_bindgen] impl Jason { @@ -23,7 +23,7 @@ impl Jason { set_panic_hook(); init_logger(); - Self(core::Jason::new()) + Self(jason::Jason::new()) } /// Creates new `Room` and returns its [`RoomHandle`]. diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs index adfbf216e..c423d6e05 100644 --- a/jason/src/api/wasm/jason_error.rs +++ b/jason/src/api/wasm/jason_error.rs @@ -2,14 +2,14 @@ use derive_more::From; use wasm_bindgen::prelude::*; -use crate::core; +use crate::utils; /// Representation of app error exported to JS side. /// /// Contains JS side error if it the cause and trace information. #[wasm_bindgen] #[derive(From)] -pub struct JasonError(core::utils::JasonError); +pub struct JasonError(utils::JasonError); #[wasm_bindgen] impl JasonError { diff --git a/jason/src/api/wasm/local_media_track.rs b/jason/src/api/wasm/local_media_track.rs index 9ee137789..5875f8eb3 100644 --- a/jason/src/api/wasm/local_media_track.rs +++ b/jason/src/api/wasm/local_media_track.rs @@ -4,7 +4,7 @@ use wasm_bindgen::prelude::*; use crate::{ api::{MediaKind, MediaSourceKind}, - core, + media::track::local, }; /// Wrapper around local [MediaStreamTrack][1]. @@ -15,7 +15,7 @@ use crate::{ /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack #[wasm_bindgen] #[derive(From)] -pub struct LocalMediaTrack(core::LocalMediaTrack); +pub struct LocalMediaTrack(local::LocalMediaTrack); #[wasm_bindgen] impl LocalMediaTrack { diff --git a/jason/src/api/wasm/media_manager_handle.rs b/jason/src/api/wasm/media_manager_handle.rs index 74d6ce3e2..fc6c42160 100644 --- a/jason/src/api/wasm/media_manager_handle.rs +++ b/jason/src/api/wasm/media_manager_handle.rs @@ -5,7 +5,7 @@ use wasm_bindgen_futures::future_to_promise; use crate::{ api::{InputDeviceInfo, JasonError, LocalMediaTrack, MediaStreamSettings}, - core, + media, }; /// [`MediaManagerHandle`] is a weak ref to [`MediaManager`]. @@ -21,12 +21,12 @@ use crate::{ /// Like all handlers it contains weak reference to object that is managed by /// Rust, so its methods will fail if weak reference could not be upgraded. /// -/// [`MediaManager`]: core::media::MediaManager +/// [`MediaManager`]: media::MediaManager /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia #[wasm_bindgen] #[derive(From)] -pub struct MediaManagerHandle(core::MediaManagerHandle); +pub struct MediaManagerHandle(media::MediaManagerHandle); #[wasm_bindgen] #[allow(clippy::unused_self)] diff --git a/jason/src/api/wasm/media_stream_settings.rs b/jason/src/api/wasm/media_stream_settings.rs index 97aed3714..31e3606fd 100644 --- a/jason/src/api/wasm/media_stream_settings.rs +++ b/jason/src/api/wasm/media_stream_settings.rs @@ -1,21 +1,21 @@ use derive_more::{From, Into}; use wasm_bindgen::prelude::*; -use crate::{api::FacingMode, core}; +use crate::{api::FacingMode, media}; /// [MediaStreamConstraints][1] wrapper. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamconstraints #[wasm_bindgen] #[derive(Clone, From, Into)] -pub struct MediaStreamSettings(core::MediaStreamSettings); +pub struct MediaStreamSettings(media::MediaStreamSettings); #[wasm_bindgen] impl MediaStreamSettings { /// Creates new [`MediaStreamSettings`] with none constraints configured. #[wasm_bindgen(constructor)] pub fn new() -> Self { - core::MediaStreamSettings::new().into() + media::MediaStreamSettings::new().into() } /// Specifies the nature and settings of the audio [MediaStreamTrack][1]. @@ -41,14 +41,14 @@ impl MediaStreamSettings { /// Constraints applicable to audio tracks. #[wasm_bindgen] #[derive(From, Into)] -pub struct AudioTrackConstraints(core::AudioTrackConstraints); +pub struct AudioTrackConstraints(media::AudioTrackConstraints); #[wasm_bindgen] impl AudioTrackConstraints { /// Creates new [`AudioTrackConstraints`] with none constraints configured. #[wasm_bindgen(constructor)] pub fn new() -> Self { - core::AudioTrackConstraints::new().into() + media::AudioTrackConstraints::new().into() } /// Sets exact [deviceId][1] constraint. @@ -63,7 +63,7 @@ impl AudioTrackConstraints { /// device. #[wasm_bindgen] #[derive(From, Into)] -pub struct DeviceVideoTrackConstraints(core::DeviceVideoTrackConstraints); +pub struct DeviceVideoTrackConstraints(media::DeviceVideoTrackConstraints); /// Constraints applicable to video tracks that are sourced from screen-capture. #[wasm_bindgen] @@ -72,7 +72,7 @@ impl DeviceVideoTrackConstraints { /// configured. #[wasm_bindgen(constructor)] pub fn new() -> Self { - core::DeviceVideoTrackConstraints::new().into() + media::DeviceVideoTrackConstraints::new().into() } /// Sets exact [deviceId][1] constraint. @@ -86,14 +86,14 @@ impl DeviceVideoTrackConstraints { /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring pub fn exact_facing_mode(&mut self, facing_mode: FacingMode) { - self.0.exact_facing_mode(facing_mode); + self.0.exact_facing_mode(facing_mode.into()); } /// Sets ideal [facingMode][1] constraint. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring pub fn ideal_facing_mode(&mut self, facing_mode: FacingMode) { - self.0.ideal_facing_mode(facing_mode) + self.0.ideal_facing_mode(facing_mode.into()) } /// Sets exact [`height`][1] constraint. @@ -142,7 +142,7 @@ impl DeviceVideoTrackConstraints { /// Constraints applicable to video tracks sourced from screen capture. #[wasm_bindgen] #[derive(From, Into)] -pub struct DisplayVideoTrackConstraints(core::DisplayVideoTrackConstraints); +pub struct DisplayVideoTrackConstraints(media::DisplayVideoTrackConstraints); #[wasm_bindgen] impl DisplayVideoTrackConstraints { @@ -150,6 +150,6 @@ impl DisplayVideoTrackConstraints { /// configured. #[wasm_bindgen(constructor)] pub fn new() -> Self { - core::DisplayVideoTrackConstraints::new().into() + media::DisplayVideoTrackConstraints::new().into() } } diff --git a/jason/src/api/wasm/mod.rs b/jason/src/api/wasm/mod.rs index 166c2bbef..40331624b 100644 --- a/jason/src/api/wasm/mod.rs +++ b/jason/src/api/wasm/mod.rs @@ -1,3 +1,6 @@ +//! External Jason API for `wasm32-unknown-unknown` target, designed to be used +//! in web environment with Javascript. + #![allow(clippy::new_without_default)] use derive_more::Display; @@ -16,8 +19,6 @@ pub mod remote_media_track; pub mod room_close_reason; pub mod room_handle; -use crate::core; - /// [MediaStreamTrack.kind][1] representation. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-kind @@ -31,15 +32,6 @@ pub enum MediaKind { Video, } -impl From for MediaKind { - fn from(that: core::MediaKind) -> Self { - match that { - core::MediaKind::Audio => Self::Audio, - core::MediaKind::Video => Self::Video, - } - } -} - /// Media source type. #[wasm_bindgen] #[derive(Clone, Copy, Debug, Display, Eq, PartialEq)] @@ -51,24 +43,6 @@ pub enum MediaSourceKind { Display, } -impl From for MediaSourceKind { - fn from(that: core::MediaSourceKind) -> Self { - match that { - core::MediaSourceKind::Device => Self::Device, - core::MediaSourceKind::Display => Self::Display, - } - } -} - -impl Into for MediaSourceKind { - fn into(self) -> core::MediaSourceKind { - match self { - MediaSourceKind::Device => core::MediaSourceKind::Device, - MediaSourceKind::Display => core::MediaSourceKind::Display, - } - } -} - /// Describes the directions that the camera can face, as seen from the user's /// perspective. Representation of [VideoFacingModeEnum][1]. /// diff --git a/jason/src/api/wasm/reconnect_handle.rs b/jason/src/api/wasm/reconnect_handle.rs index c25f9c203..8f85a2762 100644 --- a/jason/src/api/wasm/reconnect_handle.rs +++ b/jason/src/api/wasm/reconnect_handle.rs @@ -3,7 +3,7 @@ use js_sys::Promise; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use crate::{api::JasonError, core}; +use crate::{api::JasonError, rpc}; /// Handle that JS side can reconnect to the Medea media server on /// a connection loss with. @@ -11,7 +11,7 @@ use crate::{api::JasonError, core}; /// This handle will be provided into `Room.on_connection_loss` callback. #[wasm_bindgen] #[derive(Clone, From)] -pub struct ReconnectHandle(core::ReconnectHandle); +pub struct ReconnectHandle(rpc::ReconnectHandle); #[wasm_bindgen] impl ReconnectHandle { @@ -21,7 +21,7 @@ impl ReconnectHandle { /// won't be performed. Instead, it will wait for the first reconnection /// attempt result and use it here. /// - /// [`RpcSession`]: core::rpc::RpcSession + /// [`RpcSession`]: rpc::RpcSession pub fn reconnect_with_delay(&self, delay_ms: u32) -> Promise { let this = self.0.clone(); future_to_promise(async move { @@ -51,7 +51,7 @@ impl ReconnectHandle { /// If `multiplier` is negative number than `multiplier` will be considered /// as `0.0`. /// - /// [`RpcSession`]: core::rpc::RpcSession + /// [`RpcSession`]: rpc::RpcSession pub fn reconnect_with_backoff( &self, starting_delay_ms: u32, diff --git a/jason/src/api/wasm/remote_media_track.rs b/jason/src/api/wasm/remote_media_track.rs index d3e0750b6..b1b14599a 100644 --- a/jason/src/api/wasm/remote_media_track.rs +++ b/jason/src/api/wasm/remote_media_track.rs @@ -3,7 +3,7 @@ use wasm_bindgen::prelude::*; use crate::{ api::{MediaKind, MediaSourceKind}, - core, + media::track::remote, }; /// Wrapper around [MediaStreamTrack][1] received from the remote. @@ -11,7 +11,7 @@ use crate::{ /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack #[wasm_bindgen] #[derive(Clone, From, Into)] -pub struct RemoteMediaTrack(core::remote::Track); +pub struct RemoteMediaTrack(remote::Track); #[wasm_bindgen] impl RemoteMediaTrack { diff --git a/jason/src/api/wasm/room_close_reason.rs b/jason/src/api/wasm/room_close_reason.rs index 4b6fc465b..0c632454e 100644 --- a/jason/src/api/wasm/room_close_reason.rs +++ b/jason/src/api/wasm/room_close_reason.rs @@ -1,36 +1,36 @@ use derive_more::From; use wasm_bindgen::prelude::*; -use crate::core; +use crate::room; /// Reason of why [`Room`] has been closed. /// /// This struct is passed into `on_close_by_server` JS side callback. /// -/// [`Room`]: core::Room +/// [`Room`]: room::Room #[wasm_bindgen] #[derive(From)] -pub struct RoomCloseReason(core::RoomCloseReason); +pub struct RoomCloseReason(room::RoomCloseReason); #[wasm_bindgen] impl RoomCloseReason { /// [`Room`] close reason. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn reason(&self) -> String { self.0.reason() } /// Whether [`Room`] was closed by server. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn is_closed_by_server(&self) -> bool { self.0.is_closed_by_server() } /// Whether [`Room`] close reason is considered as error /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn is_err(&self) -> bool { self.0.is_err() } diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index 360b432f5..0ded688cb 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -8,15 +8,15 @@ use crate::{ ConstraintsUpdateException, JasonError, MediaSourceKind, MediaStreamSettings, }, - core, + room, }; /// JS side handle to [`Room`] where all the media happens. /// -/// [`Room`]: core::Room +/// [`Room`]: room::Room #[wasm_bindgen] #[derive(From, Into)] -pub struct RoomHandle(core::RoomHandle); +pub struct RoomHandle(room::RoomHandle); #[wasm_bindgen] impl RoomHandle { @@ -35,7 +35,7 @@ impl RoomHandle { /// /// Effectively returns `Result<(), JasonError>`. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn join(&self, token: String) -> Promise { let this = self.0.clone(); @@ -48,7 +48,7 @@ impl RoomHandle { /// Sets callback, which will be invoked when new [`Connection`] with some /// remote `Member` is established. /// - /// [`Connection`]: core::Connection + /// [`Connection`]: crate::connection::Connection pub fn on_new_connection( &self, cb: js_sys::Function, @@ -62,8 +62,8 @@ impl RoomHandle { /// Sets `on_close` callback, which will be invoked on [`Room`] close, /// providing [`RoomCloseReason`]. /// - /// [`Room`]: core::Room - /// [`RoomCloseReason`]: crate::core::RoomCloseReason + /// [`Room`]: room::Room + /// [`RoomCloseReason`]: room::RoomCloseReason pub fn on_close(&self, cb: js_sys::Function) -> Result<(), JsValue> { self.0 .on_close(cb.into()) @@ -78,7 +78,7 @@ impl RoomHandle { /// 2. `disable_audio`/`enable_video` is called. /// 3. [`MediaStreamSettings`] updated via `set_local_media_settings`. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room /// [`LocalMediaTrack`]: crate::api::LocalMediaTrack pub fn on_local_track(&self, cb: js_sys::Function) -> Result<(), JsValue> { self.0 @@ -134,8 +134,8 @@ impl RoomHandle { /// If recovering from fail state isn't possible then affected media types /// will be disabled. /// - /// [`Room`]: core::Room - /// [`PeerConnection`]: core::peer::PeerConnection + /// [`Room`]: room::Room + /// [`PeerConnection`]: crate::peer::PeerConnection /// [`LocalMediaTrack`]: crate::api::LocalMediaTrack /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia pub fn set_local_media_settings( @@ -161,7 +161,7 @@ impl RoomHandle { /// Mutes outbound audio in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn mute_audio(&self) -> Promise { let this = self.0.clone(); @@ -173,7 +173,7 @@ impl RoomHandle { /// Unmutes outbound audio in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn unmute_audio(&self) -> Promise { let this = self.0.clone(); @@ -185,7 +185,7 @@ impl RoomHandle { /// Mutes outbound video in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn mute_video(&self, source_kind: Option) -> Promise { let this = self.0.clone(); @@ -199,7 +199,7 @@ impl RoomHandle { /// Unmutes outbound video in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn unmute_video( &self, source_kind: Option, @@ -216,7 +216,7 @@ impl RoomHandle { /// Disables outbound audio in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn disable_audio(&self) -> Promise { let this = self.0.clone(); @@ -228,7 +228,7 @@ impl RoomHandle { /// Enables outbound audio in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn enable_audio(&self) -> Promise { let this = self.0.clone(); @@ -275,7 +275,7 @@ impl RoomHandle { /// Disables inbound audio in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn disable_remote_audio(&self) -> Promise { let this = self.0.clone(); @@ -289,7 +289,7 @@ impl RoomHandle { /// Disables inbound video in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn disable_remote_video(&self) -> Promise { let this = self.0.clone(); @@ -303,7 +303,7 @@ impl RoomHandle { /// Enables inbound audio in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn enable_remote_audio(&self) -> Promise { let this = self.0.clone(); @@ -315,7 +315,7 @@ impl RoomHandle { /// Enables inbound video in this [`Room`]. /// - /// [`Room`]: core::Room + /// [`Room`]: room::Room pub fn enable_remote_video(&self) -> Promise { let this = self.0.clone(); diff --git a/jason/src/core/connection.rs b/jason/src/connection.rs similarity index 97% rename from jason/src/core/connection.rs rename to jason/src/connection.rs index 5672bf3cc..2dec2bd80 100644 --- a/jason/src/core/connection.rs +++ b/jason/src/connection.rs @@ -1,5 +1,8 @@ //! Connection with specific remote `Member`. +// TODO: Remove when moving JasonError to api::wasm. +#![allow(clippy::missing_errors_doc)] + use std::{ cell::{Cell, RefCell}, collections::{HashMap, HashSet}, @@ -10,11 +13,9 @@ use medea_client_api_proto::{ConnectionQualityScore, MemberId, PeerId}; use crate::{ api, - core::{ - media::track::remote, - utils::{HandlerDetachedError, JasonError}, - }, + media::track::remote, platform, + utils::{HandlerDetachedError, JasonError}, }; /// Service which manages [`Connection`]s with the remote `Member`s. diff --git a/jason/src/core/mod.rs b/jason/src/jason.rs similarity index 84% rename from jason/src/core/mod.rs rename to jason/src/jason.rs index d4d6750a8..88f3edf7d 100644 --- a/jason/src/core/mod.rs +++ b/jason/src/jason.rs @@ -1,44 +1,18 @@ //! Platform agnostic functionality. -// TODO: Remove when moving JasonError to api::wasm. -#![allow(clippy::missing_errors_doc)] - use futures::FutureExt as _; use std::{cell::RefCell, rc::Rc}; use crate::platform; -use self::{ - media::MediaManager, +use crate::{ + media::{MediaManager, MediaManagerHandle}, + room::{Room, RoomHandle}, rpc::{ ClientDisconnect, RpcSession, WebSocketRpcClient, WebSocketRpcSession, }, }; -#[doc(inline)] -pub use self::{ - connection::{Connection, ConnectionHandle, Connections}, - media::{ - track::{local::LocalMediaTrack, remote, MediaStreamTrackState}, - AudioTrackConstraints, DeviceVideoTrackConstraints, - DisplayVideoTrackConstraints, MediaKind, MediaManagerHandle, - MediaSourceKind, MediaStreamSettings, - }, - room::{ - ConstraintsUpdateException, Room, RoomCloseReason, RoomError, - RoomHandle, - }, - rpc::ReconnectHandle, -}; - -#[macro_use] -pub mod utils; -mod connection; -pub mod media; -pub mod peer; -mod room; -pub mod rpc; - /// General library interface. /// /// Responsible for managing shared transports, local media diff --git a/jason/src/lib.rs b/jason/src/lib.rs index fe84f173e..82db89260 100644 --- a/jason/src/lib.rs +++ b/jason/src/lib.rs @@ -3,16 +3,19 @@ //! [Medea]: https://github.com/instrumentisto/medea // TODO: Remove `clippy::must_use_candidate` once the issue below is resolved: -// https://github.com/rust-lang/rust-clippy/issues/4779. -// Remove `clippy::missing_errors_doc` when moving JasonError to -// api::wasm. +// https://github.com/rust-lang/rust-clippy/issues/4779 #![allow(clippy::module_name_repetitions, clippy::must_use_candidate)] #![deny(broken_intra_doc_links)] #![cfg_attr(not(feature = "mockable"), warn(missing_docs))] #![cfg_attr(feature = "mockable", allow(missing_docs))] -pub use self::core::utils; - +#[macro_use] +pub mod utils; pub mod api; -pub mod core; +pub mod connection; +pub mod jason; +pub mod media; +pub mod peer; pub mod platform; +pub mod room; +pub mod rpc; diff --git a/jason/src/core/media/constraints.rs b/jason/src/media/constraints.rs similarity index 93% rename from jason/src/core/media/constraints.rs rename to jason/src/media/constraints.rs index 2f7b3b895..eb42e6078 100644 --- a/jason/src/core/media/constraints.rs +++ b/jason/src/media/constraints.rs @@ -11,20 +11,35 @@ use medea_client_api_proto::{ }; use crate::{ - api, - core::{ - media::{track::MediaStreamTrackState, MediaKind}, - peer::{ - media_exchange_state, mute_state, LocalStreamUpdateCriteria, - MediaState, - }, + media::{track::MediaStreamTrackState, MediaKind}, + peer::{ + media_exchange_state, mute_state, LocalStreamUpdateCriteria, MediaState, }, platform, }; +/// Describes the directions that the camera can face, as seen from the user's +/// perspective. Representation of [VideoFacingModeEnum][1]. +/// +/// [1]: https://w3.org/TR/mediacapture-streams/#dom-videofacingmodeenum +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum FacingMode { + /// Facing toward the user (a self-view camera). + User, + + /// Facing away from the user (viewing the environment). + Environment, + + /// Facing to the left of the user. + Left, + + /// Facing to the right of the user. + Right, +} + /// Local media stream for injecting into new created [`PeerConnection`]s. /// -/// [`PeerConnection`]: crate::core::peer::PeerConnection +/// [`PeerConnection`]: crate::peer::PeerConnection #[derive(Clone, Debug, Default)] pub struct LocalTracksConstraints(Rc>); @@ -189,8 +204,8 @@ impl Default for AudioMediaTracksSettings { } } -/// Returns `true` if provided [`MediaStreamTrack`] basically -/// satisfies any constraints with a provided [`MediaKind`]. +/// Returns `true` if provided [`platform::MediaStreamTrack`] satisfies any +/// constraints with a provided [`MediaKind`]. #[inline] fn satisfies_track( track: &platform::MediaStreamTrack, @@ -217,7 +232,7 @@ pub struct VideoTrackConstraints { /// actions by [`Room`]. This flag can't be changed by /// [`MediaStreamSettings`] updating. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room enabled: bool, /// Indicator whether video should be muted. @@ -238,7 +253,7 @@ impl VideoTrackConstraints { /// Returns `true` if this [`VideoTrackConstraints`] are enabled by the /// [`Room`] and constrained with [`VideoTrackConstraints::constraints`]. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room #[inline] fn enabled(&self) -> bool { self.enabled && self.is_constrained() @@ -273,12 +288,10 @@ impl VideoTrackConstraints { } impl VideoTrackConstraints { - /// Indicates whether the provided [`MediaStreamTrack`] satisfies + /// Indicates whether the provided [`platform::MediaStreamTrack`] satisfies /// device [`VideoTrackConstraints::constraints`]. /// /// Returns `false` if [`VideoTrackConstraints::constraints`] is not set. - /// - /// [`MediaStreamTrack`]: platform::MediaStreamTrack pub fn satisfies>( &self, track: T, @@ -291,12 +304,10 @@ impl VideoTrackConstraints { } impl VideoTrackConstraints { - /// Indicates whether the provided [`MediaStreamTrack`] satisfies + /// Indicates whether the provided [`platform::MediaStreamTrack`] satisfies /// device [`VideoTrackConstraints::constraints`]. /// /// Returns `false` if [`VideoTrackConstraints::constraints`] is not set. - /// - /// [`MediaStreamTrack`]: platform::MediaStreamTrack pub fn satisfies>( &self, track: T, @@ -351,9 +362,8 @@ impl MediaStreamSettings { } } - /// Specifies the nature and settings of the audio [MediaStreamTrack][1]. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + /// Specifies the nature and settings of the audio + /// [`platform::MediaStreamTrack`]. pub fn audio(&mut self, constraints: AudioTrackConstraints) { self.audio.enabled = true; self.audio.constraints = constraints; @@ -373,14 +383,12 @@ impl MediaStreamSettings { } impl MediaStreamSettings { - /// Returns `true` if provided [`MediaStreamTrack`] satisfies some + /// Returns `true` if provided [`platform::MediaStreamTrack`] satisfies some /// of the [`VideoTrackConstraints`] from this [`MediaStreamSettings`]. /// /// Unconstrains [`VideoTrackConstraints`] which this - /// [`MediaStreamTrack`] satisfies by calling + /// [`platform::MediaStreamTrack`] satisfies by calling /// [`VideoTrackConstraints::unconstrain`]. - /// - /// [`MediaStreamTrack`]: platform::MediaStreamTrack pub fn unconstrain_if_satisfies_video(&mut self, track: T) -> bool where T: AsRef, @@ -721,17 +729,17 @@ impl From for Option { /// Constraints for the [`MediaKind::Video`] [`local::Track`]. /// -/// [`local::Track`]: crate::core::media::track::local::Track +/// [`local::Track`]: crate::media::track::local::Track #[derive(Clone, Debug)] pub enum VideoSource { /// [`local::Track`] should be received from the `getUserMedia` request. /// - /// [`local::Track`]: crate::core::media::track::local::Track + /// [`local::Track`]: crate::media::track::local::Track Device(DeviceVideoTrackConstraints), /// [`local::Track`] should be received from the `getDisplayMedia` request. /// - /// [`local::Track`]: crate::core::media::track::local::Track + /// [`local::Track`]: crate::media::track::local::Track Display(DisplayVideoTrackConstraints), } @@ -748,9 +756,8 @@ impl VideoSource { } } - /// Checks if provided [MediaStreamTrack][1] satisfies this [`VideoSource`]. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + /// Checks if provided [`platform::MediaStreamTrack`] satisfies this + /// [`VideoSource`]. #[inline] pub fn satisfies>( &self, @@ -796,10 +803,8 @@ pub enum TrackConstraints { } impl TrackConstraints { - /// Checks if provided [MediaStreamTrack][1] satisfies this + /// Checks if provided [`platform::MediaStreamTrack`] satisfies this /// [`TrackConstraints`]. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn satisfies>( &self, track: T, @@ -879,10 +884,8 @@ impl AudioTrackConstraints { self.device_id = Some(ConstrainString::Exact(device_id)); } - /// Checks if provided [MediaStreamTrack][1] satisfies constraints + /// Checks if provided [`platform::MediaStreamTrack`] satisfies constraints /// contained. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn satisfies>( &self, track: T, @@ -924,13 +927,13 @@ impl From for AudioTrackConstraints { } } -impl AsRef for api::FacingMode { +impl AsRef for FacingMode { fn as_ref(&self) -> &str { match self { - api::FacingMode::User => "user", - api::FacingMode::Environment => "environment", - api::FacingMode::Left => "left", - api::FacingMode::Right => "right", + FacingMode::User => "user", + FacingMode::Environment => "environment", + FacingMode::Left => "left", + FacingMode::Right => "right", } } } @@ -1008,7 +1011,7 @@ pub struct DeviceVideoTrackConstraints { /// Describes the directions that the camera can face, as seen from the /// user's perspective. - pub facing_mode: Option>, + pub facing_mode: Option>, /// Height of the video in pixels. pub height: Option, @@ -1035,14 +1038,14 @@ impl DeviceVideoTrackConstraints { /// Sets exact [facingMode][1] constraint. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring - pub fn exact_facing_mode(&mut self, facing_mode: api::FacingMode) { + pub fn exact_facing_mode(&mut self, facing_mode: FacingMode) { self.facing_mode = Some(ConstrainString::Exact(facing_mode)); } /// Sets ideal [facingMode][1] constraint. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-constraindomstring - pub fn ideal_facing_mode(&mut self, facing_mode: api::FacingMode) { + pub fn ideal_facing_mode(&mut self, facing_mode: FacingMode) { self.facing_mode = Some(ConstrainString::Ideal(facing_mode)); } @@ -1088,10 +1091,8 @@ impl DeviceVideoTrackConstraints { self.width = Some(ConstrainU32::Range(min, max)); } - /// Checks if provided [MediaStreamTrack][1] satisfies + /// Checks if provided [`platform::MediaStreamTrack`] satisfies /// [`DeviceVideoTrackConstraints`] contained. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack pub fn satisfies>( &self, track: T, @@ -1155,10 +1156,8 @@ impl DisplayVideoTrackConstraints { Self::default() } - /// Checks if provided [MediaStreamTrack][1] satisfies + /// Checks if provided [`platform::MediaStreamTrack`] satisfies /// [`DisplayVideoTrackConstraints`] contained. - /// - /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack #[allow(clippy::unused_self)] #[inline] pub fn satisfies>( diff --git a/jason/src/core/media/manager.rs b/jason/src/media/manager.rs similarity index 92% rename from jason/src/core/media/manager.rs rename to jason/src/media/manager.rs index eec327f89..2aeedc30d 100644 --- a/jason/src/core/media/manager.rs +++ b/jason/src/media/manager.rs @@ -1,5 +1,8 @@ //! Acquiring and storing [`local::Track`]s. +// TODO: Remove when moving JasonError to api::wasm. +#![allow(clippy::missing_errors_doc)] + use std::{ cell::RefCell, collections::HashMap, @@ -11,14 +14,12 @@ use medea_client_api_proto::MediaSourceKind; use tracerr::Traced; use crate::{ - core::{ - media::{ - track::MediaStreamTrackState, MediaKind, MediaStreamSettings, - MultiSourceTracksConstraints, - }, - utils::{HandlerDetachedError, JasonError, JsCaused}, + media::{ + track::MediaStreamTrackState, MediaKind, MediaStreamSettings, + MultiSourceTracksConstraints, }, platform, + utils::{HandlerDetachedError, JasonError, JsCaused}, }; use super::track::local; @@ -200,12 +201,11 @@ impl InnerMediaManager { tracks } - /// Obtains new [MediaStream][1] making [getUserMedia()][2] call, saves + /// Obtains new [`local::Track`]s making [getUserMedia()][1] call, saves /// received tracks weak refs to storage, returns list of tracks strong /// refs. /// - /// [1]: https://w3.org/TR/mediacapture-streams/#mediastream - /// [2]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia async fn get_user_media( &self, caps: platform::MediaStreamConstraints, @@ -215,12 +215,11 @@ impl InnerMediaManager { Ok(self.parse_and_save_tracks(tracks, MediaSourceKind::Device)?) } - /// Obtains new [MediaStream][1] making [getDisplayMedia()][2] call, saves + /// Obtains [`local::Track`]s making [getDisplayMedia()][1] call, saves /// received tracks weak refs to storage, returns list of tracks strong /// refs. /// - /// [1]: https://w3.org/TR/mediacapture-streams/#mediastream - /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia + /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia async fn get_display_media( &self, caps: platform::DisplayMediaStreamConstraints, @@ -230,13 +229,13 @@ impl InnerMediaManager { Ok(self.parse_and_save_tracks(tracks, MediaSourceKind::Display)?) } - /// Retrieves tracks from provided [`platform::MediaStream`], saves tracks - /// weak references in [`MediaManager`] tracks storage. + /// Retrieves tracks from provided [`platform::MediaStreamTrack`]s, saves + /// tracks weak references in [`MediaManager`] tracks storage. /// /// # Errors /// /// With [`MediaManagerError::LocalTrackIsEnded`] if at least one track from - /// the provided [`platform::MediaStream`] is in [`ended`][1] state. + /// the provided [`platform::MediaStreamTrack`]s is in [`ended`][1] state. /// /// In case of error all tracks are stopped and are not saved in /// [`MediaManager`]'s tracks storage. @@ -295,14 +294,14 @@ impl MediaManager { self.0.get_tracks(caps.into()).await } - /// Instantiates new [`MediaManagerHandle`] for use on JS side. + /// Instantiates new [`MediaManagerHandle`] for external use. #[inline] pub fn new_handle(&self) -> MediaManagerHandle { MediaManagerHandle(Rc::downgrade(&self.0)) } } -/// JS side handle to [`MediaManager`]. +/// External handle to [`MediaManager`]. /// /// [`MediaManager`] performs all media acquisition requests /// ([getUserMedia()][1]/[getDisplayMedia()][2]) and stores all received tracks diff --git a/jason/src/core/media/mod.rs b/jason/src/media/mod.rs similarity index 98% rename from jason/src/core/media/mod.rs rename to jason/src/media/mod.rs index 2484070a7..bcca63fae 100644 --- a/jason/src/core/media/mod.rs +++ b/jason/src/media/mod.rs @@ -12,7 +12,7 @@ use derive_more::Display; pub use self::{ constraints::{ AudioMediaTracksSettings, AudioTrackConstraints, - DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, + DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, FacingMode, LocalTracksConstraints, MediaStreamSettings, MultiSourceTracksConstraints, RecvConstraints, TrackConstraints, VideoSource, VideoTrackConstraints, diff --git a/jason/src/core/media/track/local.rs b/jason/src/media/track/local.rs similarity index 92% rename from jason/src/core/media/track/local.rs rename to jason/src/media/track/local.rs index f6ea12e2f..561ee8492 100644 --- a/jason/src/core/media/track/local.rs +++ b/jason/src/media/track/local.rs @@ -10,7 +10,7 @@ use derive_more::AsRef; use medea_client_api_proto as proto; use crate::{ - core::media::{MediaKind, MediaSourceKind}, + media::{MediaKind, MediaSourceKind}, platform, }; @@ -116,7 +116,11 @@ impl Drop for Track { } } -/// Wrapper around strongly referenced [`Track`] for JS side. +/// Strongly referenced [`Track`] 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 pub struct LocalMediaTrack(Rc); impl LocalMediaTrack { @@ -129,12 +133,14 @@ impl LocalMediaTrack { /// Returns the underlying [`platform::MediaStreamTrack`] of this /// [`LocalMediaTrack`]. + #[inline] pub fn get_track(&self) -> &platform::MediaStreamTrack { &self.0.track } /// Returns [`MediaKind::Audio`] if this [`LocalMediaTrack`] represents an /// audio track, or [`MediaKind::Video`] if it represents a video track. + #[inline] pub fn kind(&self) -> MediaKind { self.0.kind() } @@ -145,6 +151,7 @@ impl LocalMediaTrack { /// [MediaDevices.getDisplayMedia()][1]. /// /// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia + #[inline] pub fn media_source_kind(&self) -> MediaSourceKind { self.0.media_source_kind().into() } diff --git a/jason/src/core/media/track/mod.rs b/jason/src/media/track/mod.rs similarity index 95% rename from jason/src/core/media/track/mod.rs rename to jason/src/media/track/mod.rs index 402d9e4c0..f9fb3ffbc 100644 --- a/jason/src/core/media/track/mod.rs +++ b/jason/src/media/track/mod.rs @@ -16,8 +16,8 @@ pub enum MediaStreamTrackState { /// best-effort attempt to provide data in real time). Live, /// The track has ended (the track's underlying media source is no longer - /// providing data, and will never provide more data for this track). Once - /// a track enters this state, it never exits it. + /// providing data, and will never provide more data for this track). This + /// is a final state. Ended, } diff --git a/jason/src/core/media/track/remote.rs b/jason/src/media/track/remote.rs similarity index 92% rename from jason/src/core/media/track/remote.rs rename to jason/src/media/track/remote.rs index 414175aaf..855374c0e 100644 --- a/jason/src/core/media/track/remote.rs +++ b/jason/src/media/track/remote.rs @@ -7,13 +7,13 @@ use medea_client_api_proto as proto; use medea_reactive::ObservableCell; use crate::{ - core::media::{MediaKind, MediaSourceKind}, + media::{MediaKind, MediaSourceKind}, platform, }; /// Inner reference-counted data of [`Track`]. struct Inner { - /// Underlying JS-side [`platform::MediaStreamTrack`]. + /// Underlying platform-specific [`platform::MediaStreamTrack`]. track: platform::MediaStreamTrack, /// Underlying [`platform::MediaStreamTrack`] source kind. @@ -58,7 +58,7 @@ impl Track { })); let mut track_enabled_state_changes = - track.enabled_observable().subscribe().skip(1); + track.0.enabled.subscribe().skip(1); platform::spawn({ let weak_inner = Rc::downgrade(&track.0); async move { @@ -81,13 +81,6 @@ impl Track { track } - /// Indicates whether this [`Track`] is enabled. - #[inline] - #[must_use] - pub fn enabled_observable(&self) -> &ObservableCell { - &self.0.enabled - } - /// Sets [`Track::enabled`] to the provided value. /// /// Updates [`enabled`][1] property in the underlying diff --git a/jason/src/core/peer/component/ice_candidates.rs b/jason/src/peer/component/ice_candidates.rs similarity index 92% rename from jason/src/core/peer/component/ice_candidates.rs rename to jason/src/peer/component/ice_candidates.rs index f48cf9a88..f3fdd86de 100644 --- a/jason/src/core/peer/component/ice_candidates.rs +++ b/jason/src/peer/component/ice_candidates.rs @@ -6,12 +6,14 @@ use futures::stream::LocalBoxStream; use medea_client_api_proto::IceCandidate; use medea_reactive::ObservableHashSet; -use crate::core::{ +use crate::{ media::LocalTracksConstraints, utils::{AsProtoState, SynchronizableState}, }; -/// Store of all the [`IceCandidate`]s of a [`PeerComponent`]. +/// Store of all the [`IceCandidate`]s of a [`peer::Component`]. +/// +/// [`peer::Component`]: super::Component #[derive(Debug)] pub struct IceCandidates(RefCell>); diff --git a/jason/src/core/peer/component/local_sdp.rs b/jason/src/peer/component/local_sdp.rs similarity index 98% rename from jason/src/core/peer/component/local_sdp.rs rename to jason/src/peer/component/local_sdp.rs index 5b1936e45..6694b1144 100644 --- a/jason/src/core/peer/component/local_sdp.rs +++ b/jason/src/peer/component/local_sdp.rs @@ -15,8 +15,8 @@ use futures::{ use medea_reactive::ObservableCell; use crate::{ - core::utils::{resettable_delay_for, ResettableDelayHandle}, platform, + utils::{resettable_delay_for, ResettableDelayHandle}, }; const DESCRIPTION_APPROVE_TIMEOUT: Duration = Duration::from_secs(10); @@ -57,7 +57,7 @@ impl LocalSdp { /// Returns [`Stream`] into which `()` will be sent on every SDP offer /// approve. /// - /// [`Stream`]: futures::stream::Stream + /// [`Stream`]: futures::Stream #[inline] pub fn on_approve(&self) -> LocalBoxStream<'static, ()> { Box::pin(self.0.approved.subscribe().filter_map(|approved| { diff --git a/jason/src/core/peer/component/mod.rs b/jason/src/peer/component/mod.rs similarity index 99% rename from jason/src/core/peer/component/mod.rs rename to jason/src/peer/component/mod.rs index 32403dcda..584c004cf 100644 --- a/jason/src/core/peer/component/mod.rs +++ b/jason/src/peer/component/mod.rs @@ -15,7 +15,7 @@ use medea_client_api_proto::{ use medea_reactive::{AllProcessed, ObservableCell, ProgressableCell}; use tracerr::Traced; -use crate::core::{ +use crate::{ media::LocalTracksConstraints, peer::{ media::{receiver, sender}, diff --git a/jason/src/core/peer/component/tracks_repository.rs b/jason/src/peer/component/tracks_repository.rs similarity index 97% rename from jason/src/core/peer/component/tracks_repository.rs rename to jason/src/peer/component/tracks_repository.rs index 451dc8686..a6f9f44f5 100644 --- a/jason/src/core/peer/component/tracks_repository.rs +++ b/jason/src/peer/component/tracks_repository.rs @@ -17,7 +17,7 @@ use medea_client_api_proto::TrackId; use medea_reactive::{AllProcessed, Guarded, ProgressableHashMap}; use tracerr::Traced; -use crate::core::{ +use crate::{ media::LocalTracksConstraints, peer::PeerError, utils::{AsProtoState, SynchronizableState, Updatable}, @@ -29,6 +29,7 @@ use super::sender; /// [`Component`]. /// /// [`Component`]: super::Component +/// [`receiver::State`]: super::receiver::State #[derive(Debug, From)] pub struct TracksRepository( RefCell>>, @@ -43,6 +44,8 @@ impl TracksRepository { } /// Returns [`Future`] resolving once all inserts/removes are processed. + /// + /// [`Future`]: std::future::Future #[inline] pub fn when_all_processed(&self) -> AllProcessed<'static> { self.0.borrow().when_all_processed() @@ -62,6 +65,8 @@ impl TracksRepository { } /// Returns a [`Stream`] streaming the all [`TracksRepository::insert`]ions. + /// + /// [`Stream`]: futures::Stream #[inline] pub fn on_insert( &self, @@ -157,6 +162,8 @@ where /// Returns [`Future`] resolving once all tracks from this /// [`TracksRepository`] will be stabilized meaning that all track's /// components won't contain any pending state change transitions. + /// + /// [`Future`]: std::future::Future fn when_stabilized(&self) -> AllProcessed<'static> { let when_futs: Vec<_> = self .0 diff --git a/jason/src/core/peer/component/watchers.rs b/jason/src/peer/component/watchers.rs similarity index 91% rename from jason/src/core/peer/component/watchers.rs rename to jason/src/peer/component/watchers.rs index ffce893f5..f21ab9501 100644 --- a/jason/src/core/peer/component/watchers.rs +++ b/jason/src/peer/component/watchers.rs @@ -8,7 +8,7 @@ use medea_macro::watchers; use medea_reactive::Guarded; use tracerr::Traced; -use crate::core::{ +use crate::{ peer::{ component::{NegotiationState, SyncState}, media::{receiver, sender}, @@ -81,16 +81,18 @@ impl Component { /// Watcher for the [`State::senders`] insert update. /// - /// Waits until [`ReceiverComponent`]s creation is finished. + /// Waits until [`receiver::Component`]s creation is finished. /// /// Waits for a remote SDP offer apply if the current [`NegotiationRole`] is /// an [`Answerer`]. /// - /// Creates a new [`SenderComponent`], creates a new [`Connection`] with all - /// [`sender::State::receivers`] by calling - /// [`Connections::create_connection()`]. + /// Creates a new [`sender::Component`], creates a new [`Connection`] with + /// all [`sender::State::receivers`] by calling + /// [`Connections::create_connection()`][1]. /// /// [`Answerer`]: NegotiationRole::Answerer + /// [`Connection`]: crate::connection::Connection + /// [1]: crate::connection::Connections::create_connection #[watch(self.senders.on_insert())] async fn sender_added( peer: Rc, @@ -136,9 +138,12 @@ impl Component { /// Watcher for the [`State::receivers`] insert update. /// - /// Creates a new [`ReceiverComponent`], creates a new [`Connection`] with a - /// [`receiver::State::sender_id`] by calling - /// [`Connections::create_connection()`]. + /// Creates a new [`receiver::Component`], creates a new [`Connection`] with + /// a [`receiver::State::sender_id`] by calling + /// [`Connections::create_connection()`][1]. + /// + /// [`Connection`]: crate::connection::Connections + /// [1]: crate::connection::Connections::create_connection #[watch(self.receivers.on_insert())] async fn receiver_added( peer: Rc, @@ -164,15 +169,15 @@ impl Component { /// Watcher for the [`State::local_sdp`] updates. /// /// Sets [`PeerConnection`]'s SDP offer to the provided one and sends - /// a [`Command::MakeSdpOffer`] if the [`Sdp`] is a [`Sdp::Offer`] and - /// the [`NegotiationRole`] is an [`Offerer`]. + /// a [`PeerEvent::NewSdpOffer`] if [`NegotiationRole`] is an + /// [`NegotiationRole::Offerer`]. /// /// Sets [`PeerConnection`]'s SDP answer to the provided one and sends - /// a [`Command::MakeSdpAnswer`] if the [`Sdp`] is a [`Sdp::Offer`] and - /// the [`NegotiationRole`] is an [`Answerer`]. + /// a [`PeerEvent::NewSdpAnswer`] if [`NegotiationRole`] is an + /// [`NegotiationRole::Answerer`]. /// - /// Rollbacks [`PeerConnection`] to a stable state if the [`Sdp`] is a - /// [`Sdp::Rollback`] and the [`NegotiationRole`] is [`Some`]. + /// Rollbacks [`PeerConnection`] to a stable state if [`PeerConnection`] is + /// marked for rollback and [`NegotiationRole`] is [`Some`]. /// /// [`Answerer`]: NegotiationRole::Answerer /// [`Offerer`]: NegotiationRole::Offerer @@ -245,11 +250,11 @@ impl Component { /// Watcher for the SDP offer approving by server. /// - /// If the current [`NegotiationRole`] is an [`Offerer`] then - /// [`NegotiationState`] will transit to a [`WaitRemoteSdp`]. + /// If the current [`NegotiationRole`] is an [`NegotiationRole::Offerer`] + /// then [`NegotiationState`] will transit to a [`WaitRemoteSdp`]. /// - /// If the current [`NegotiationRole`] is an [`Answerer`] then - /// [`NegotiationState`] will transit to a [`Stable`]. + /// If the current [`NegotiationRole`] is an [`NegotiationRole::Answerer`] + /// then [`NegotiationState`] will transit to a [`Stable`]. /// /// [`Offerer`]: NegotiationRole::Offerer /// [`Stable`]: NegotiationState::Stable @@ -333,7 +338,7 @@ impl Component { /// Watcher for the [`State::negotiation_role`] updates. /// - /// Waits for [`SenderComponent`]s' and [`ReceiverComponent`]s' + /// Waits for [`sender::Component`]s' and [`receiver::Component`]s' /// creation/update, updates local `MediaStream` (if required) and /// renegotiates [`PeerConnection`]. #[watch(self.negotiation_role.subscribe().filter_map(future::ready))] diff --git a/jason/src/core/peer/media/mod.rs b/jason/src/peer/media/mod.rs similarity index 93% rename from jason/src/core/peer/media/mod.rs rename to jason/src/peer/media/mod.rs index 9f718d515..a5495eb8e 100644 --- a/jason/src/core/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -1,6 +1,6 @@ //! [`PeerConnection`] media management. //! -//! [`PeerConnection`]: crate::core::peer::PeerConnection +//! [`PeerConnection`]: crate::peer::PeerConnection pub mod receiver; pub mod sender; @@ -18,22 +18,26 @@ use proto::{MediaSourceKind, TrackId}; use tracerr::Traced; #[cfg(feature = "mockable")] -use crate::core::media::{LocalTracksConstraints, RecvConstraints}; +use crate::media::{LocalTracksConstraints, RecvConstraints}; use crate::{ - core::{ - media::{track::local, MediaKind}, - peer::{LocalStreamUpdateCriteria, PeerEvent}, - utils::JsCaused, - }, + media::{track::local, MediaKind}, + peer::{LocalStreamUpdateCriteria, PeerEvent}, platform, + utils::JsCaused, }; use super::tracks_request::TracksRequest; -pub use self::transitable_state::{ - media_exchange_state, mute_state, InStable, InTransition, - MediaExchangeState, MediaExchangeStateController, MediaState, MuteState, - MuteStateController, TransitableState, TransitableStateController, +#[doc(inline)] +pub use self::{ + receiver::Receiver, + sender::Sender, + transitable_state::{ + media_exchange_state, mute_state, InStable, InTransition, + MediaExchangeState, MediaExchangeStateController, MediaState, + MuteState, MuteStateController, TransitableState, + TransitableStateController, + }, }; /// Transceiver's sending ([`Sender`]) or receiving ([`Receiver`]) side. @@ -111,7 +115,7 @@ pub trait MediaStateControllable { /// Indicates whether [`Room`] should subscribe to the [`MediaState`] update /// when updating [`MediaStateControllable`] to the provided [`MediaState`]. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room #[must_use] fn is_subscription_needed(&self, desired_state: MediaState) -> bool { match desired_state { @@ -139,7 +143,7 @@ pub trait MediaStateControllable { /// [`MediaState`]. /// /// [`TrackPatchCommand`]: medea_client_api_proto::TrackPatchCommand - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room #[must_use] fn is_track_patch_needed(&self, desired_state: MediaState) -> bool { match desired_state { @@ -214,11 +218,11 @@ pub enum MediaConnectionsError { #[display(fmt = "Failed to insert Track to a sender: {}", _0)] CouldNotInsertLocalTrack(platform::Error), - /// Occurs when [`remote::Track`] discovered by [`RtcPeerConnection`] could - /// not be inserted into [`Receiver`]. + /// Occurs when [`remote::Track`] discovered by + /// [`platform::RtcPeerConnection`] could not be inserted into + /// [`Receiver`]. /// - /// [`remote::Track`]: crate::core::media::track::remote::Track - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// [`remote::Track`]: crate::media::track::remote::Track /// [`Receiver`]: self::receiver::Receiver #[display( fmt = "Could not insert remote track with mid: {:?} into media \ @@ -227,9 +231,7 @@ pub enum MediaConnectionsError { )] CouldNotInsertRemoteTrack(String), - /// Could not find [`Transceiver`] by `mid`. - /// - /// [`Transceiver`]: platform::Transceiver + /// Could not find [`platform::Transceiver`] by `mid`. #[display(fmt = "Unable to find Transceiver with provided mid: {}", _0)] TransceiverNotFound(String), @@ -293,10 +295,9 @@ type Result = std::result::Result>; /// Actual data of [`MediaConnections`] storage. struct InnerMediaConnections { - /// Ref to parent [`RtcPeerConnection`]. Used to generate transceivers for - /// [`Sender`]s and [`Receiver`]s. + /// Ref to parent [`platform::RtcPeerConnection`]. Used to generate + /// transceivers for [`Sender`]s and [`Receiver`]s. /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection /// [`Sender`]: self::sender::Sender /// [`Receiver`]: self::receiver::Receiver peer: Rc, @@ -361,10 +362,8 @@ impl InnerMediaConnections { } } - /// Creates [`Transceiver`] and adds it to the [`RtcPeerConnection`]. - /// - /// [`Transceiver`]: platform::Transceiver - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// Creates [`platform::Transceiver`] and adds it to the + /// [`platform::RtcPeerConnection`]. fn add_transceiver( &self, kind: MediaKind, @@ -373,9 +372,8 @@ impl InnerMediaConnections { platform::Transceiver::from(self.peer.add_transceiver(kind, direction)) } - /// Lookups [`Transceiver`] by the provided [`mid`]. + /// Lookups [`platform::Transceiver`] by the provided [`mid`]. /// - /// [`Transceiver`]: platform::Transceiver /// [`mid`]: https://w3.org/TR/webrtc/#dom-rtptransceiver-mid fn get_transceiver_by_mid( &self, @@ -387,17 +385,13 @@ impl InnerMediaConnections { } } -/// Storage of [`RtcPeerConnection`]'s [`sender::Component`] and +/// Storage of [`platform::RtcPeerConnection`]'s [`sender::Component`] and /// [`receiver::Component`]. -/// -/// [`RtcPeerConnection`]: platform::RtcPeerConnection pub struct MediaConnections(RefCell); impl MediaConnections { /// Instantiates new [`MediaConnections`] storage for a given - /// [`RtcPeerConnection`]. - /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// [`platform::RtcPeerConnection`]. #[inline] pub fn new( peer: Rc, @@ -469,7 +463,7 @@ impl MediaConnections { } /// Returns mapping from a [`proto::Track`] ID to a `mid` of this track's - /// [`Transceiver`]. + /// [`platform::Transceiver`]. /// /// # Errors /// @@ -479,7 +473,6 @@ impl MediaConnections { /// Errors with [`MediaConnectionsError::ReceiversWithoutMid`] if some /// [`Receiver`] doesn't have [mid]. /// - /// [`Transceiver`]: platform::Transceiver /// [`Sender`]: self::sender::Sender /// [`Receiver`]: self::receiver::Receiver /// [mid]: @@ -593,8 +586,9 @@ impl MediaConnections { /// Inserts provided tracks into [`Sender`]s based on track IDs. /// - /// [`local::Track`]s are inserted into [`Sender`]'s [`Transceiver`]s - /// via [`replaceTrack` method][1], changing its direction to `sendonly`. + /// [`local::Track`]s are inserted into [`Sender`]'s + /// [`platform::Transceiver`]s via [`replaceTrack` method][1], changing + /// its direction to `sendonly`. /// /// Returns [`HashMap`] with [`media_exchange_state::Stable`]s updates for /// the [`Sender`]s. @@ -612,7 +606,6 @@ impl MediaConnections { /// [`local::Track`] cannot be inserted into provided [`Sender`]s /// transceiver. /// - /// [`Transceiver`]: platform::Transceiver /// [`Sender`]: self::sender::Sender /// [1]: https://w3.org/TR/webrtc/#dom-rtcrtpsender-replacetrack pub async fn insert_local_tracks( @@ -692,13 +685,12 @@ impl MediaConnections { } /// Iterates over all [`Receiver`]s with [`mid`] and without - /// [`Transceiver`], trying to find the corresponding [`Transceiver`] in - /// [`RtcPeerConnection`] and to insert it into the [`Receiver`]. + /// [`platform::Transceiver`], trying to find the corresponding + /// [`platform::Transceiver`] in [`platform::RtcPeerConnection`] and to + /// insert it into the [`Receiver`]. /// /// [`Receiver`]: self::receiver::Receiver /// [`mid`]: https://w3.org/TR/webrtc/#dom-rtptransceiver-mid - /// [`Transceiver`]: platform::Transceiver - /// [`RtcPeerConnection`]: platform::RtcPeerConnection pub fn sync_receivers(&self) { let inner = self.0.borrow(); for receiver in inner diff --git a/jason/src/core/peer/media/receiver/component.rs b/jason/src/peer/media/receiver/component.rs similarity index 92% rename from jason/src/core/peer/media/receiver/component.rs rename to jason/src/peer/media/receiver/component.rs index 4a44e66b0..aba9132f6 100644 --- a/jason/src/core/peer/media/receiver/component.rs +++ b/jason/src/peer/media/receiver/component.rs @@ -14,19 +14,17 @@ use medea_reactive::{ }; use crate::{ - core::{ - media::{LocalTracksConstraints, MediaKind}, - peer::{ - component::SyncState, - media::{ - transitable_state::media_exchange_state, InTransition, Result, - }, - MediaExchangeState, MediaExchangeStateController, - MediaStateControllable, MuteStateController, TransceiverSide, + media::{LocalTracksConstraints, MediaKind}, + peer::{ + component::SyncState, + media::{ + transitable_state::media_exchange_state, InTransition, Result, }, - utils::{component, AsProtoState, SynchronizableState, Updatable}, + MediaExchangeState, MediaExchangeStateController, + MediaStateControllable, MuteStateController, TransceiverSide, }, platform, + utils::{component, AsProtoState, SynchronizableState, Updatable}, }; use super::Receiver; @@ -249,11 +247,14 @@ impl State { #[watchers] impl Component { - /// Watcher for the [`State::general_media_exchange_state`] update. + /// Watcher for the [`State::enabled_general`] updates. /// /// Updates [`Receiver`]'s general media exchange state. Adds or removes /// [`TransceiverDirection::RECV`] from the [`Transceiver`] of the /// [`Receiver`]. + /// + /// [`Transceiver`]: platform::Transceiver + /// [`TransceiverDirection::RECV`]: platform::TransceiverDirection::RECV #[watch(self.enabled_general.subscribe())] async fn general_media_exchange_state_changed( receiver: Rc, @@ -287,7 +288,8 @@ impl Component { Ok(()) } - /// Watcher for [`MediaExchangeState::Stable`] update. + /// Watcher for [`media_exchange_state::Stable`] media exchange state + /// updates. /// /// Updates [`Receiver::enabled_individual`] to the new state. #[inline] @@ -303,10 +305,13 @@ impl Component { Ok(()) } - /// Watcher for [`MediaExchangeState::Transition`] update. + /// Watcher for media exchange state [`media_exchange_state::Transition`] + /// updates. /// - /// Sends [`TrackEvent::MediaExchangeIntention`] with the provided + /// Sends [`TrackEvent::MediaExchangeIntention`][1] with the provided /// [`media_exchange_state`]. + /// + /// [1]: crate::peer::TrackEvent::MediaExchangeIntention #[inline] #[watch(self.enabled_individual.subscribe_transition())] async fn enabled_individual_transition_started( @@ -403,9 +408,7 @@ impl TransceiverSide for State { impl State { /// Stabilizes [`MediaExchangeState`] of this [`State`]. pub fn stabilize(&self) { - // use crate::core::peer::media::InTransition as _; - - if let crate::core::peer::MediaExchangeState::Transition(transition) = + if let crate::peer::MediaExchangeState::Transition(transition) = self.enabled_individual.state() { self.enabled_individual.update(transition.intended()); diff --git a/jason/src/core/peer/media/receiver/mod.rs b/jason/src/peer/media/receiver/mod.rs similarity index 85% rename from jason/src/core/peer/media/receiver/mod.rs rename to jason/src/peer/media/receiver/mod.rs index eb9715e45..bf5148fb7 100644 --- a/jason/src/core/peer/media/receiver/mod.rs +++ b/jason/src/peer/media/receiver/mod.rs @@ -9,27 +9,24 @@ use medea_client_api_proto::{self as proto, MediaType, MemberId}; use proto::TrackId; use crate::{ - core::{ - media::{track::remote, MediaKind, RecvConstraints, TrackConstraints}, - peer::{ - media::media_exchange_state, MediaConnections, - MediaStateControllable, PeerEvent, TrackEvent, - }, + media::{track::remote, MediaKind, RecvConstraints, TrackConstraints}, + peer::{ + media::media_exchange_state, MediaConnections, MediaStateControllable, + PeerEvent, TrackEvent, }, platform, }; use super::TransceiverSide; +#[doc(inline)] pub use self::component::{Component, State}; /// 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 [`Transceiver`] and the actual [`remote::Track`] only -/// when [`remote::Track`] data arrives. -/// -/// [`Transceiver`]: platform::Transceiver +/// We can save related [`platform::Transceiver`] and the actual +/// [`remote::Track`] only when [`remote::Track`] data arrives. pub struct Receiver { track_id: TrackId, caps: TrackConstraints, @@ -45,9 +42,9 @@ pub struct Receiver { } impl Receiver { - /// Creates new [`Transceiver`] if provided `mid` is `None`, otherwise - /// creates [`Receiver`] without [`Transceiver`]. It will be injected - /// when [`remote::Track`] arrives. + /// Creates new [`platform::Transceiver`] if provided `mid` is `None`, + /// otherwise creates [`Receiver`] without [`Transceiver`]. It will be + /// injected when [`remote::Track`] arrives. /// /// Created [`Transceiver`] direction is set to /// [`TransceiverDirection::INACTIVE`][1] if `enabled_individual` is @@ -172,13 +169,11 @@ impl Receiver { ); } - /// Adds provided [`platform::MediaStreamTrack`] and [`Transceiver`] to this - /// [`Receiver`]. + /// Adds provided [`platform::MediaStreamTrack`] and + /// [`platform::Transceiver`] to this [`Receiver`]. /// /// Sets [`platform::MediaStreamTrack::enabled`] same as /// [`Receiver::enabled`] of this [`Receiver`]. - /// - /// [`Transceiver`]: platform::Transceiver pub fn set_remote_track( &self, transceiver: platform::Transceiver, @@ -205,26 +200,24 @@ impl Receiver { self.maybe_notify_track(); } - /// Replaces [`Receiver`]'s [`Transceiver`] with a provided [`Transceiver`]. - /// - /// Doesn't update [`TransceiverDirection`] of the [`Transceiver`]. + /// Replaces [`Receiver`]'s [`platform::Transceiver`] with a provided + /// [`platform::Transceiver`]. /// - /// No-op if provided with the same [`Transceiver`] as already exists in - /// this [`Receiver`]. + /// Doesn't update [`platform::TransceiverDirection`] of the + /// [`platform::Transceiver`]. /// - /// [`Transceiver`]: platform::Transceiver - /// [`TransceiverDirection`]: platform::TransceiverDirection + /// No-op if provided with the same [`platform::Transceiver`] as already + /// exists in this [`Receiver`]. pub fn replace_transceiver(&self, transceiver: platform::Transceiver) { if self.mid.borrow().as_ref() == transceiver.mid().as_ref() { self.transceiver.replace(Some(transceiver)); } } - /// Returns [`Transceiver`] of this [`Receiver`]. - /// - /// Returns [`None`] if this [`Receiver`] doesn't have [`Transceiver`]. + /// Returns [`platform::Transceiver`] of this [`Receiver`]. /// - /// [`Transceiver`]: platform::Transceiver + /// Returns [`None`] if this [`Receiver`] doesn't have + /// [`platform::Transceiver`]. #[inline] pub fn transceiver(&self) -> Option { self.transceiver.borrow().clone() diff --git a/jason/src/core/peer/media/sender/component.rs b/jason/src/peer/media/sender/component.rs similarity index 91% rename from jason/src/core/peer/media/sender/component.rs rename to jason/src/peer/media/sender/component.rs index 53ade3383..f734e97c0 100644 --- a/jason/src/core/peer/media/sender/component.rs +++ b/jason/src/peer/media/sender/component.rs @@ -12,24 +12,20 @@ use medea_reactive::{AllProcessed, Guarded, ObservableCell, ProgressableCell}; use tracerr::Traced; use crate::{ - core::{ + media::{LocalTracksConstraints, MediaKind, TrackConstraints, VideoSource}, + peer::{ + self, + component::SyncState, media::{ - LocalTracksConstraints, MediaKind, TrackConstraints, VideoSource, + media_exchange_state, mute_state, InTransition, MediaExchangeState, + MuteState, Result, }, - peer::{ - self, - component::SyncState, - media::{ - media_exchange_state, mute_state, InTransition, - MediaExchangeState, MuteState, Result, - }, - MediaConnectionsError, MediaExchangeStateController, MediaState, - MediaStateControllable, MuteStateController, PeerError, - TransceiverSide, - }, - utils::{component, AsProtoState, SynchronizableState, Updatable}, + MediaConnectionsError, MediaExchangeStateController, MediaState, + MediaStateControllable, MuteStateController, PeerError, + TransceiverSide, }, platform, + utils::{component, AsProtoState, SynchronizableState, Updatable}, }; use super::Sender; @@ -38,12 +34,18 @@ use super::Sender; /// /// [`PartialEq`] implementation of this state ignores /// [`LocalTrackState::Failed`] content. +/// +/// [`local::Track`]: crate::media::track::local::Track #[derive(Debug, Clone)] enum LocalTrackState { /// Indicates that [`Sender`] is new, or [`local::Track`] is set. + /// + /// [`local::Track`]: crate::media::track::local::Track Stable, /// Indicates that [`Sender`] needs a new [`local::Track`]. + /// + /// [`local::Track`]: crate::media::track::local::Track NeedUpdate, /// Indicates that new [`local::Track`] getting is failed. @@ -51,6 +53,7 @@ enum LocalTrackState { /// Contains [`PeerError`] with which /// [getUserMedia()][1]/[getDisplayMedia()][2] request was failed. /// + /// [`local::Track`]: crate::media::track::local::Track /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia Failed(Traced), @@ -396,10 +399,13 @@ impl State { #[watchers] impl Component { - /// Watcher for [`MediaExchangeState::Transition`] update. + /// Watcher for media exchange state [`media_exchange_state::Transition`] + /// updates. /// - /// Sends [`TrackEvent::MediaExchangeIntention`] with the provided + /// Sends [`TrackEvent::MediaExchangeIntention`][1] with the provided /// [`media_exchange_state`]. + /// + /// [1]: crate::peer::TrackEvent::MediaExchangeIntention #[watch(self.enabled_individual.subscribe_transition())] async fn enabled_individual_transition_started( sender: Rc, @@ -410,10 +416,12 @@ impl Component { Ok(()) } - /// Watcher for [`MuteState::Transition`] update. + /// Watcher for mute state [`mute_state::Transition`] updates. /// - /// Sends [`TrackEvent::MuteUpdateIntention`] with the provided + /// Sends [`TrackEvent::MuteUpdateIntention`][1] with the provided /// [`mute_state`]. + /// + /// [1]: crate::peer::TrackEvent::MuteUpdateIntention #[watch(self.mute_state.subscribe_transition())] async fn mute_state_transition_watcher( sender: Rc, @@ -427,8 +435,11 @@ impl Component { /// Watcher for the [`State::enabled_general`] update. /// /// Updates [`Sender`]'s general media exchange state. Adds or removes - /// [`TransceiverDirection::SEND`] from the [`Transceiver`] of the - /// [`Receiver`]. + /// [`TransceiverDirection::SEND`] from the [`Transceiver`] of this + /// [`Sender`]. + /// + /// [`TransceiverDirection::SEND`]: platform::TransceiverDirection::SEND + /// [`Transceiver`]: platform::Transceiver #[watch(self.enabled_general.subscribe())] async fn enabled_general_state_changed( sender: Rc, @@ -436,7 +447,6 @@ impl Component { new_state: Guarded, ) -> Result<()> { let (new_state, _guard) = new_state.into_parts(); - sender .enabled_general .set(new_state == media_exchange_state::Stable::Enabled); @@ -458,15 +468,18 @@ impl Component { Ok(()) } - /// Watcher for the [`MediaExchangeState::Stable`] update. + /// Watcher for [`media_exchange_state::Stable`] media exchange state + /// updates. /// - /// Updates [`Receiver::enabled_individual`] to the `new_state`. + /// Updates [`Sender::enabled_individual`] to the `new_state`. /// /// Removes `MediaTrack` from [`Transceiver`] if `new_state` is /// [`media_exchange_state::Stable::Disabled`]. /// - /// Sets [`State::need_local_stream_update`] to the `true` if `new_state` is - /// [`media_exchange_state::Stable::Enabled`]. + /// Marks [`State::local_track_state`] as [`LocalTrackState::NeedUpdate`] if + /// `new_state` is [`media_exchange_state::Stable::Enabled`]. + /// + /// [`Transceiver`]: platform::Transceiver #[watch(self.enabled_individual.subscribe_stable())] async fn enabled_individual_stable_state_changed( sender: Rc, @@ -487,11 +500,13 @@ impl Component { Ok(()) } - /// Watcher for the [`MuteState::Stable`] update. + /// Watcher for the [`mute_state::Stable`] updates. /// /// Updates [`Sender`]'s mute state. /// /// Updates [`Sender`]'s [`Transceiver`] `MediaTrack.enabled` property. + /// + /// [`Transceiver`]: platform::Transceiver #[watch(self.mute_state.subscribe_stable())] async fn mute_state_stable_watcher( sender: Rc, diff --git a/jason/src/core/peer/media/sender/mod.rs b/jason/src/peer/media/sender/mod.rs similarity index 93% rename from jason/src/core/peer/media/sender/mod.rs rename to jason/src/peer/media/sender/mod.rs index a9e8f86fa..814a9ee5a 100644 --- a/jason/src/core/peer/media/sender/mod.rs +++ b/jason/src/peer/media/sender/mod.rs @@ -8,12 +8,10 @@ use futures::channel::mpsc; use medea_client_api_proto::TrackId; use crate::{ - core::{ - media::{ - track::local, LocalTracksConstraints, MediaKind, TrackConstraints, - }, - peer::TrackEvent, + media::{ + track::local, LocalTracksConstraints, MediaKind, TrackConstraints, }, + peer::TrackEvent, platform, }; @@ -22,6 +20,7 @@ use super::{ MediaStateControllable, Result, }; +#[doc(inline)] pub use self::component::{Component, State}; /// Representation of a [`local::Track`] that is being sent to some remote peer. @@ -37,10 +36,10 @@ pub struct Sender { } impl Sender { - /// Creates new [`Transceiver`] if provided `mid` is [`None`], otherwise - /// retrieves existing [`Transceiver`] via provided `mid` from a - /// provided [`MediaConnections`]. Errors if [`Transceiver`] lookup - /// fails. + /// Creates new [`platform::Transceiver`] if provided `mid` is [`None`], + /// otherwise retrieves existing [`platform::Transceiver`] via provided + /// `mid` from a provided [`MediaConnections`]. Errors if + /// [`platform::Transceiver`] lookup fails. /// /// # Errors /// @@ -48,7 +47,6 @@ impl Sender { /// has [`Some`] [`mid`], but this [`mid`] isn't found in the /// [`MediaConnections`]. /// - /// [`Transceiver`]: platform::Transceiver /// [`mid`]: https://w3.org/TR/webrtc/#dom-rtptransceiver-mid pub fn new( state: &State, @@ -178,9 +176,7 @@ impl Sender { Ok(()) } - /// Returns [`Transceiver`] of this [`Sender`]. - /// - /// [`Transceiver`]: platform::Transceiver + /// Returns [`platform::Transceiver`] of this [`Sender`]. #[inline] #[must_use] pub fn transceiver(&self) -> platform::Transceiver { diff --git a/jason/src/core/peer/media/transitable_state/controller.rs b/jason/src/peer/media/transitable_state/controller.rs similarity index 96% rename from jason/src/core/peer/media/transitable_state/controller.rs rename to jason/src/peer/media/transitable_state/controller.rs index 80943fccf..1680041ed 100644 --- a/jason/src/core/peer/media/transitable_state/controller.rs +++ b/jason/src/peer/media/transitable_state/controller.rs @@ -13,16 +13,14 @@ use futures::{ use medea_reactive::{Processed, ProgressableCell}; use crate::{ - core::{ - peer::media::{ - transitable_state::{ - media_exchange_state, mute_state, InStable, InTransition, - }, - MediaConnectionsError, Result, + peer::media::{ + transitable_state::{ + media_exchange_state, mute_state, InStable, InTransition, }, - utils::{resettable_delay_for, ResettableDelayHandle}, + MediaConnectionsError, Result, }, platform, + utils::{resettable_delay_for, ResettableDelayHandle}, }; use super::TransitableState; @@ -128,7 +126,7 @@ where /// Returns [`Stream`] into which the [`TransitableState::Stable`] updates /// will be emitted. /// - /// [`Stream`]: futures::stream::Stream + /// [`Stream`]: futures::Stream pub fn subscribe_stable(&self) -> LocalBoxStream<'static, S> { self.state .subscribe() @@ -146,7 +144,7 @@ where /// Returns [`Stream`] into which the [`TransitableState::Transition`] /// updates will be emitted. /// - /// [`Stream`]: futures::stream::Stream + /// [`Stream`]: futures::Stream pub fn subscribe_transition(&self) -> LocalBoxStream<'static, T> { self.state .subscribe() diff --git a/jason/src/core/peer/media/transitable_state/media_exchange_state.rs b/jason/src/peer/media/transitable_state/media_exchange_state.rs similarity index 90% rename from jason/src/core/peer/media/transitable_state/media_exchange_state.rs rename to jason/src/peer/media/transitable_state/media_exchange_state.rs index 76e6685f0..5fb8ecf2a 100644 --- a/jason/src/core/peer/media/transitable_state/media_exchange_state.rs +++ b/jason/src/peer/media/transitable_state/media_exchange_state.rs @@ -7,12 +7,12 @@ use super::{InStable, InTransition}; pub enum Stable { /// [`MediaStateControllable`] is enabled. /// - /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::peer::MediaStateControllable Enabled, /// [`MediaStateControllable`] is disabled. /// - /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::peer::MediaStateControllable Disabled, } @@ -72,13 +72,13 @@ pub enum Transition { /// [`MediaStateControllable`] should be enabled, but awaits server /// permission. /// - /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::peer::MediaStateControllable Enabling(Stable), /// [`MediaStateControllable`] should be disabled, but awaits server /// permission. /// - /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::peer::MediaStateControllable Disabling(Stable), } diff --git a/jason/src/core/peer/media/transitable_state/mod.rs b/jason/src/peer/media/transitable_state/mod.rs similarity index 96% rename from jason/src/core/peer/media/transitable_state/mod.rs rename to jason/src/peer/media/transitable_state/mod.rs index 0374f364a..429e680c8 100644 --- a/jason/src/core/peer/media/transitable_state/mod.rs +++ b/jason/src/peer/media/transitable_state/mod.rs @@ -1,6 +1,6 @@ //! [`MediaStateControllable`]s media exchange state. //! -//! [`MediaStateControllable`]: crate::core::peer::MediaStateControllable +//! [`MediaStateControllable`]: crate::peer::MediaStateControllable mod controller; pub mod media_exchange_state; @@ -9,6 +9,7 @@ pub mod mute_state; use derive_more::From; use medea_client_api_proto::{TrackId, TrackPatchCommand}; +#[doc(inline)] pub use self::controller::{ MediaExchangeStateController, MuteStateController, TransitableStateController, @@ -25,7 +26,7 @@ pub type MuteState = /// All media states which can be toggled in the [`MediaStateControllable`]. /// -/// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable +/// [`MediaStateControllable`]: crate::peer::MediaStateControllable #[derive(Clone, Copy, Debug, From)] pub enum MediaState { /// Responsible for changing [`enabled`][1] property of @@ -86,6 +87,7 @@ impl MediaState { /// [`TransitableState::Stable`] variant of the [`TransitableState`]. pub trait InStable: Clone + Copy + PartialEq { + /// Transition invariants of this [`InStable`]. type Transition: InTransition; /// Converts this [`InStable`] into [`InStable::Transition`]. @@ -95,6 +97,7 @@ pub trait InStable: Clone + Copy + PartialEq { /// [`TransitableState::Transition`] variant of the [`TransitableState`]. pub trait InTransition: Clone + Copy + PartialEq { + /// Stable invariants of this [`InTransition`]. type Stable: InStable; /// Returns intention which this state indicates. @@ -116,7 +119,7 @@ pub trait InTransition: Clone + Copy + PartialEq { /// All media exchange states in which [`MediaStateControllable`] can be. /// -/// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable +/// [`MediaStateControllable`]: crate::peer::MediaStateControllable #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TransitableState { /// State of transition. diff --git a/jason/src/core/peer/media/transitable_state/mute_state.rs b/jason/src/peer/media/transitable_state/mute_state.rs similarity index 88% rename from jason/src/core/peer/media/transitable_state/mute_state.rs rename to jason/src/peer/media/transitable_state/mute_state.rs index fa051f779..9ff5e43b9 100644 --- a/jason/src/core/peer/media/transitable_state/mute_state.rs +++ b/jason/src/peer/media/transitable_state/mute_state.rs @@ -7,12 +7,12 @@ use super::{InStable, InTransition}; pub enum Stable { /// [`MediaStateControllable`] is muted. /// - /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::peer::MediaStateControllable Muted, /// [`MediaStateControllable`] is unmuted. /// - /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::peer::MediaStateControllable Unmuted, } @@ -64,13 +64,13 @@ pub enum Transition { /// [`MediaStateControllable`] should be muted, but awaits server /// permission. /// - /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::peer::MediaStateControllable Muting(Stable), /// [`MediaStateControllable`] should be unmuted, but awaits server /// permission. /// - /// [`MediaStateControllable`]: crate::core::peer::MediaStateControllable + /// [`MediaStateControllable`]: crate::peer::MediaStateControllable Unmuting(Stable), } diff --git a/jason/src/core/peer/mod.rs b/jason/src/peer/mod.rs similarity index 89% rename from jason/src/core/peer/mod.rs rename to jason/src/peer/mod.rs index 64191aa87..7e7006931 100644 --- a/jason/src/core/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -3,7 +3,7 @@ //! [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface mod component; -mod media; +pub mod media; pub mod repo; mod stream_update_criteria; mod tracks_request; @@ -26,16 +26,14 @@ use medea_macro::dispatchable; use tracerr::Traced; use crate::{ - core::{ - media::{ - track::{local, remote}, - LocalTracksConstraints, MediaKind, MediaManager, MediaManagerError, - MediaStreamSettings, RecvConstraints, - }, - utils::{JasonError, JsCaused}, - Connections, + connection::Connections, + media::{ + track::{local, remote}, + LocalTracksConstraints, MediaKind, MediaManager, MediaManagerError, + MediaStreamSettings, RecvConstraints, }, platform, + utils::{JasonError, JsCaused}, }; #[doc(inline)] @@ -83,8 +81,8 @@ type Result = std::result::Result>; /// Events emitted from a [`Sender`] or a [`Receiver`]. /// -/// [`Receiver`]: crate::core::peer::receiver::Receiver -/// [`Sender`]: crate::core::peer::sender::Sender +/// [`Receiver`]: crate::peer::receiver::Receiver +/// [`Sender`]: crate::peer::sender::Sender #[derive(Debug)] pub enum TrackEvent { /// Intention of the `MediaTrack` to mute/unmute himself. @@ -106,17 +104,14 @@ pub enum TrackEvent { }, } -/// Events emitted from [`RtcPeerConnection`]. -/// -/// [`RtcPeerConnection`]: platform::RtcPeerConnection +/// Events emitted from [`platform::RtcPeerConnection`]. #[dispatchable(self: &Self, async_trait(?Send))] #[derive(Clone)] pub enum PeerEvent { - /// [`RtcPeerConnection`] discovered new ICE candidate. + /// [`platform::RtcPeerConnection`] discovered new ICE candidate. /// /// Wrapper around [RTCPeerConnectionIceEvent][1]. /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnectioniceevent IceCandidateDiscovered { /// ID of the [`PeerConnection`] that discovered new ICE candidate. @@ -141,10 +136,8 @@ pub enum PeerEvent { sdp_mid: Option, }, - /// [`RtcPeerConnection`] received new [`remote::Track`] from remote - /// sender. - /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// [`platform::RtcPeerConnection`] received new [`remote::Track`] from + /// remote sender. NewRemoteTrack { /// Remote `Member` ID. sender_id: MemberId, @@ -153,17 +146,14 @@ pub enum PeerEvent { track: remote::Track, }, - /// [`RtcPeerConnection`] sent new local track to remote members. - /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// [`platform::RtcPeerConnection`] sent new local track to remote members. NewLocalTrack { /// Local [`local::Track`] that is sent to remote members. local_track: Rc, }, - /// [`RtcPeerConnection`]'s [ICE connection][1] state changed. + /// [`platform::RtcPeerConnection`]'s [ICE connection][1] state changed. /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection /// [1]: https://w3.org/TR/webrtc/#dfn-ice-connection-state IceConnectionStateChanged { /// ID of the [`PeerConnection`] that sends @@ -176,9 +166,8 @@ pub enum PeerEvent { ice_connection_state: IceConnectionState, }, - /// [`RtcPeerConnection`]'s [connection][1] state changed. + /// [`platform::RtcPeerConnection`]'s [connection][1] state changed. /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection /// [1]: https://w3.org/TR/webrtc/#dfn-ice-connection-state ConnectionStateChanged { /// ID of the [`PeerConnection`] that sends @@ -191,19 +180,13 @@ pub enum PeerEvent { peer_connection_state: PeerConnectionState, }, - /// [`RtcPeerConnection`]'s [`RtcStats`] update. - /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection - /// [`RtcStats`]: platform::RtcStats + /// [`platform::RtcPeerConnection`]'s [`platform::RtcStats`] update. StatsUpdate { - /// ID of the [`PeerConnection`] for which [`RtcStats`] was sent. - /// - /// [`RtcStats`]: platform::RtcStats + /// ID of the [`PeerConnection`] for which [` platform::RtcStats`] was + /// sent. peer_id: Id, - /// [`RtcStats`] of this [`PeerConnection`]. - /// - /// [`RtcStats`]: platform::RtcStats + /// [` platform::RtcStats`] of this [`PeerConnection`]. stats: platform::RtcStats, }, @@ -253,22 +236,16 @@ pub enum PeerEvent { }, } -/// High-level wrapper around [`RtcPeerConnection`]. -/// -/// [`RtcPeerConnection`]: platform::RtcPeerConnection +/// High-level wrapper around [`platform::RtcPeerConnection`]. pub struct PeerConnection { /// Unique ID of [`PeerConnection`]. id: Id, - /// Underlying [`RtcPeerConnection`]. - /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// Underlying [`platform::RtcPeerConnection`]. peer: Rc, /// [`sender::Component`]s and [`receiver::Component`]s of this - /// [`RtcPeerConnection`]. - /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// [`platform::RtcPeerConnection`]. media_connections: Rc, /// [`MediaManager`] that will be used to acquire [`local::Track`]s. @@ -277,25 +254,19 @@ pub struct PeerConnection { /// [`PeerEvent`]s tx. peer_events_sender: mpsc::UnboundedSender, - /// Indicates if underlying [`RtcPeerConnection`] has remote description. - /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// Indicates if underlying [`platform::RtcPeerConnection`] has remote + /// description. has_remote_description: Cell, - /// Stores [`IceCandidate`]s received before remote description for - /// underlying [`RtcPeerConnection`]. - /// - /// [`IceCandidate`]: platform::IceCandidate - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// Stores [`platform::IceCandidate`]s received before remote description + /// for underlying [`platform::RtcPeerConnection`]. ice_candidates_buffer: RefCell>, - /// Last hashes of the all [`RtcStats`] which was already sent to the - /// server, so we won't duplicate stats that were already sent. + /// Last hashes of the all [`platform::RtcStats`] which was already sent to + /// the server, so we won't duplicate stats that were already sent. /// /// Stores precomputed hashes, since we don't need access to actual stats /// values. - /// - /// [`RtcStats`]: platform::RtcStats sent_stats_cache: RefCell>, /// Local media stream constraints used in this [`PeerConnection`]. @@ -303,7 +274,7 @@ pub struct PeerConnection { /// Collection of [`Connection`]s with a remote `Member`s. /// - /// [`Connection`]: crate::core::Connection + /// [`Connection`]: crate::connection::Connection connections: Rc, /// Sender for the [`TrackEvent`]s which should be processed by this @@ -321,17 +292,16 @@ impl PeerConnection { /// Provided `peer_events_sender` will be used to emit [`PeerEvent`]s from /// this peer. /// - /// Provided `ice_servers` will be used by created [`RtcPeerConnection`]. + /// Provided `ice_servers` will be used by created + /// [`platform::RtcPeerConnection`]. /// /// # Errors /// - /// Errors with [`PeerError::RtcPeerConnection`] if [`RtcPeerConnection`] - /// creating fails. + /// Errors with [`PeerError::RtcPeerConnection`] if + /// [`platform::RtcPeerConnection`] creating fails. /// /// Errors with [`PeerError::RtcPeerConnection`] if some callback of - /// [`RtcPeerConnection`] can't be set. - /// - /// [`RtcPeerConnection`]: platform::RtcPeerConnection + /// [`platform::RtcPeerConnection`] can't be set. pub fn new( state: &State, peer_events_sender: mpsc::UnboundedSender, @@ -427,9 +397,12 @@ impl PeerConnection { /// Handler [`TrackEvent`]s emitted from [`Sender`] or [`Receiver`]. /// - /// Sends [`PeerEvent::SendIntention`] with a [`Command::UpdateTracks`] on - /// [`TrackEvent::MediaExchangeIntention`] and - /// [`TrackEvent::MuteStateIntention`]. + /// Sends [`PeerEvent::MediaUpdateCommand`] with a [`Command::UpdateTracks`] + /// on [`TrackEvent::MediaExchangeIntention`] and + /// [`TrackEvent::MuteUpdateIntention`]. + /// + /// [`Sender`]: sender::Sender + /// [`Receiver`]: receiver::Receiver fn handle_track_event( peer_id: PeerId, peer_events_sender: &mpsc::UnboundedSender, @@ -485,9 +458,7 @@ impl PeerConnection { } /// Filters out already sent stats, and send new stats from - /// provided [`RtcStats`]. - /// - /// [`RtcStats`]: platform::RtcStats + /// provided [`platform::RtcStats`]. #[allow(clippy::option_if_let_else)] pub fn send_peer_stats(&self, stats: platform::RtcStats) { let mut stats_cache = self.sent_stats_cache.borrow_mut(); @@ -525,9 +496,8 @@ impl PeerConnection { } } - /// Sends [`RtcStats`] update of this [`PeerConnection`] to the server. - /// - /// [`RtcStats`]: platform::RtcStats + /// Sends [`platform::RtcStats`] update of this [`PeerConnection`] to the + /// server. pub async fn scrape_and_send_peer_stats(&self) { match self.peer.get_stats().await { Ok(stats) => self.send_peer_stats(stats), @@ -651,9 +621,9 @@ impl PeerConnection { } /// Track id to mid relations of all send tracks of this - /// [`RtcPeerConnection`]. mid is id of [`m= section`][1]. mids are received - /// directly from registered [`RTCRtpTransceiver`][2]s, and are being - /// allocated on sdp update. + /// [`platform::RtcPeerConnection`]. mid is id of [`m= section`][1]. mids + /// are received directly from registered [`RTCRtpTransceiver`][2]s, and + /// are being allocated on sdp update. /// /// # Errors /// @@ -698,7 +668,7 @@ impl PeerConnection { /// Constraints being used when requesting stream from [`MediaManager`] are /// a result of merging constraints received from this [`PeerConnection`] /// [`Sender`]s, which are configured by server during signalling, and - /// [`LocalTracksConstraints`], that are optionally configured by JS-side. + /// [`LocalTracksConstraints`]. /// /// Returns [`HashMap`] with [`media_exchange_state::Stable`]s updates for /// the [`Sender`]s. @@ -776,7 +746,7 @@ impl PeerConnection { /// /// # Errors /// - /// Errors with [`Media::TracksRequest`] if failed to create or merge + /// Errors with [`PeerError::TracksRequest`] if failed to create or merge /// [`SimpleTracksRequest`]. fn get_simple_tracks_request( &self, @@ -855,11 +825,12 @@ impl PeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::SetRemoteDescriptionFailed`] if + /// With [`RTCPeerConnectionError::SetRemoteDescriptionFailed`][3] if /// [RTCPeerConnection.setRemoteDescription()][2] fails. /// /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface /// [2]: https://w3.org/TR/webrtc/#dom-peerconnection-setremotedescription + /// [3]: platform::RTCPeerConnectionError::SetRemoteDescriptionFailed async fn set_remote_answer(&self, answer: String) -> Result<()> { self.set_remote_description(platform::SdpType::Answer(answer)) .await @@ -870,7 +841,7 @@ impl PeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::SetRemoteDescriptionFailed`] if + /// With [`platform::RTCPeerConnectionError::SetRemoteDescriptionFailed`] if /// [RTCPeerConnection.setRemoteDescription()][2] fails. /// /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface @@ -886,10 +857,10 @@ impl PeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::SetRemoteDescriptionFailed`] if + /// With [`platform::RTCPeerConnectionError::SetRemoteDescriptionFailed`] if /// [RTCPeerConnection.setRemoteDescription()][2] fails. /// - /// With [`RTCPeerConnectionError::AddIceCandidateFailed`] if + /// With [`platform::RTCPeerConnectionError::AddIceCandidateFailed`] if /// [RtcPeerConnection.addIceCandidate()][3] fails when adding buffered ICE /// candidates. /// diff --git a/jason/src/core/peer/repo.rs b/jason/src/peer/repo.rs similarity index 89% rename from jason/src/core/peer/repo.rs rename to jason/src/peer/repo.rs index c38d79c10..f9c0eda7c 100644 --- a/jason/src/core/peer/repo.rs +++ b/jason/src/peer/repo.rs @@ -9,16 +9,14 @@ use medea_reactive::ObservableHashMap; use tracerr::Traced; use crate::{ - core::{ - media::{LocalTracksConstraints, MediaManager, RecvConstraints}, - peer, - utils::{ - component, AsProtoState, SynchronizableState, TaskHandle, - Updatable as _, - }, - Connections, RoomError, + connection::Connections, + media::{LocalTracksConstraints, MediaManager, RecvConstraints}, + peer, platform, + room::RoomError, + utils::{ + component, AsProtoState, SynchronizableState, TaskHandle, + Updatable as _, }, - platform, }; use super::{PeerConnection, PeerEvent}; @@ -104,21 +102,19 @@ pub struct Repository { /// Channel for sending events produced by [`PeerConnection`] to [`Room`]. /// - /// [`PeerConnection`]: crate::core::peer::PeerConnection - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room peer_event_sender: mpsc::UnboundedSender, /// Constraints to local [`local::Track`]s that are being published by /// [`PeerConnection`]s from this [`Repository`]. /// - /// [`PeerConnection`]: crate::core::peer::PeerConnection - /// [`Room`]: crate::core::Room - /// [`local::Track`]: crate::core::media::track::local::Track + /// [`Room`]: crate::room::Room + /// [`local::Track`]: crate::media::track::local::Track send_constraints: LocalTracksConstraints, /// Collection of [`Connection`]s with a remote `Member`s. /// - /// [`Connection`]: crate::core::Connection + /// [`Connection`]: crate::connection::Connection connections: Rc, /// Constraints to the [`remote::Track`] received by [`PeerConnection`]s @@ -126,16 +122,14 @@ pub struct Repository { /// /// Used to disable or enable media receiving. /// - /// [`remote::Track`]: crate::core::media::track::remote::Track + /// [`remote::Track`]: crate::media::track::remote::Track recv_constraints: Rc, } impl Repository { - /// Returns new empty [`Repository`]. + /// Returns new empty [`platform::RtcStats`]. /// - /// Spawns [`RtcStats`] scrape task. - /// - /// [`RtcStats`]: platform::RtcStats + /// Spawns [`platform::RtcStats`] scrape task. #[must_use] pub fn new( media_manager: Rc, @@ -159,12 +153,10 @@ impl Repository { } /// Spawns task which will call [`PeerConnection::send_peer_stats`] of - /// all [`PeerConnection`]s every second and send updated [`RtcStats`] - /// to the server. + /// all [`PeerConnection`]s every second and send updated + /// [`platform::RtcStats`] to the server. /// /// Returns [`TaskHandle`] which will stop this task on [`Drop::drop()`]. - /// - /// [`RtcStats`]: crate::peer::RtcStats fn spawn_peers_stats_scrape_task( peers: Rc>>, ) -> TaskHandle { @@ -262,6 +254,8 @@ impl Component { /// /// Removes [`peer::Component`] and closes [`Connection`] by calling /// [`Connections::close_connection()`]. + /// + /// [`Connection`]: crate::connection::Connection #[inline] #[watch(self.0.borrow().on_remove())] async fn peer_removed( diff --git a/jason/src/core/peer/stream_update_criteria.rs b/jason/src/peer/stream_update_criteria.rs similarity index 98% rename from jason/src/core/peer/stream_update_criteria.rs rename to jason/src/peer/stream_update_criteria.rs index 1cc68edea..1489784f4 100644 --- a/jason/src/core/peer/stream_update_criteria.rs +++ b/jason/src/peer/stream_update_criteria.rs @@ -4,7 +4,7 @@ use std::ops::BitOrAssign; use medea_client_api_proto::{Direction, MediaSourceKind, MediaType, Track}; -use crate::core::media::MediaKind; +use crate::media::MediaKind; bitflags::bitflags! { pub struct Inner: u8 { diff --git a/jason/src/core/peer/tracks_request.rs b/jason/src/peer/tracks_request.rs similarity index 97% rename from jason/src/core/peer/tracks_request.rs rename to jason/src/peer/tracks_request.rs index c7b4f8568..27efb957c 100644 --- a/jason/src/core/peer/tracks_request.rs +++ b/jason/src/peer/tracks_request.rs @@ -9,15 +9,13 @@ use medea_client_api_proto::{MediaSourceKind, TrackId}; use tracerr::Traced; use crate::{ - core::{ - media::{ - track::local, AudioTrackConstraints, DeviceVideoTrackConstraints, - DisplayVideoTrackConstraints, MediaKind, MediaStreamSettings, - TrackConstraints, VideoSource, - }, - utils::JsCaused, + media::{ + track::local, AudioTrackConstraints, DeviceVideoTrackConstraints, + DisplayVideoTrackConstraints, MediaKind, MediaStreamSettings, + TrackConstraints, VideoSource, }, platform, + utils::JsCaused, }; /// Errors that may occur when validating [`TracksRequest`] or diff --git a/jason/src/platform/mod.rs b/jason/src/platform/mod.rs index d930ea8cb..1cd59f20a 100644 --- a/jason/src/platform/mod.rs +++ b/jason/src/platform/mod.rs @@ -1,7 +1,8 @@ -//! Platform specific functionality. +//! Platform-specific functionality. #[doc(inline)] pub use self::{ + peer_connection::{IceCandidate, RTCPeerConnectionError, SdpType}, rtc_stats::RtcStatsError, transport::{ RpcTransport, TransportError, TransportState, WebSocketRpcTransport, @@ -14,9 +15,7 @@ pub use self::{ input_device_info::InputDeviceInfo, media_devices::{enumerate_devices, get_display_media, get_user_media}, media_track::MediaStreamTrack, - peer_connection::{ - IceCandidate, RTCPeerConnectionError, RtcPeerConnection, SdpType, - }, + peer_connection::RtcPeerConnection, rtc_stats::RtcStats, set_panic_hook, spawn, transceiver::{Transceiver, TransceiverDirection}, @@ -27,6 +26,7 @@ pub use self::{ #[cfg(feature = "mockable")] pub use self::transport::MockRpcTransport; +mod peer_connection; mod rtc_stats; mod transport; mod wasm; diff --git a/jason/src/platform/peer_connection.rs b/jason/src/platform/peer_connection.rs new file mode 100644 index 000000000..46ca510e2 --- /dev/null +++ b/jason/src/platform/peer_connection.rs @@ -0,0 +1,103 @@ +//! Platform-agnostic functionality of [`platform::RtcPeerConnection`]. + +use derive_more::{Display, From}; + +use crate::{ + platform::{self, RtcStatsError}, + utils::JsCaused, +}; + +/// Representation of [RTCSdpType]. +/// +/// [RTCSdpType]: https://w3.org/TR/webrtc/#dom-rtcsdptype +pub enum SdpType { + /// [`offer` type][1] of SDP. + /// + /// [1]: https://w3.org/TR/webrtc/#dom-rtcsdptype-offer + Offer(String), + + /// [`answer` type][1] of SDP. + /// + /// [1]: https://w3.org/TR/webrtc/#dom-rtcsdptype-answer + Answer(String), +} + +/// [RTCIceCandidate][1] representation. +/// +/// [1]: https://w3.org/TR/webrtc/#rtcicecandidate-interface +pub struct IceCandidate { + /// [`candidate` field][2] of the discovered [RTCIceCandidate][1]. + /// + /// [1]: https://w3.org/TR/webrtc/#dom-rtcicecandidate + /// [2]: https://w3.org/TR/webrtc/#dom-rtcicecandidate-candidate + pub candidate: String, + + /// [`sdpMLineIndex` field][2] of the discovered [RTCIceCandidate][1]. + /// + /// [1]: https://w3.org/TR/webrtc/#dom-rtcicecandidate + /// [2]: https://w3.org/TR/webrtc/#dom-rtcicecandidate-sdpmlineindex + pub sdp_m_line_index: Option, + + /// [`sdpMid` field][2] of the discovered [RTCIceCandidate][1]. + /// + /// [1]: https://w3.org/TR/webrtc/#dom-rtcicecandidate + /// [2]: https://w3.org/TR/webrtc/#dom-rtcicecandidate-sdpmid + pub sdp_mid: Option, +} + +/// Errors that may occur during signaling between this and remote +/// [RTCPeerConnection][1] and event handlers setting errors. +/// +/// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection +#[derive(Clone, Debug, Display, From, JsCaused)] +#[js(error = "platform::Error")] +pub enum RTCPeerConnectionError { + /// Occurs when cannot adds new remote candidate to the + /// [RTCPeerConnection][1]'s remote description. + /// + /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection + #[display(fmt = "Failed to add ICE candidate: {}", _0)] + #[from(ignore)] + AddIceCandidateFailed(platform::Error), + + /// Occurs when cannot obtains [SDP answer][`SdpType::Answer`] from + /// the underlying [`platform::RtcPeerConnection`]. + #[display(fmt = "Failed to create SDP answer: {}", _0)] + #[from(ignore)] + CreateAnswerFailed(platform::Error), + + /// Occurs when a new [`platform::RtcPeerConnection`] cannot be created. + #[display(fmt = "Failed to create PeerConnection: {}", _0)] + #[from(ignore)] + PeerCreationError(platform::Error), + + /// Occurs when cannot obtains [SDP offer][`SdpType::Offer`] from + /// the underlying [`platform::RtcPeerConnection`]. + #[display(fmt = "Failed to create SDP offer: {}", _0)] + #[from(ignore)] + CreateOfferFailed(platform::Error), + + /// Occurs while getting and parsing [`platform::RtcStats`] of + /// [`platform::RtcPeerConnection`]. + #[display(fmt = "Failed to get RTCStats: {}", _0)] + RtcStatsError(#[js(cause)] RtcStatsError), + + /// [PeerConnection.getStats][1] promise thrown exception. + /// + /// [1]: https://tinyurl.com/w6hmt5f + #[display(fmt = "PeerConnection.getStats() failed with error: {}", _0)] + #[from(ignore)] + GetStatsException(platform::Error), + + /// Occurs if the local description associated with the + /// [`platform::RtcPeerConnection`] cannot be changed. + #[display(fmt = "Failed to set local SDP description: {}", _0)] + #[from(ignore)] + SetLocalDescriptionFailed(platform::Error), + + /// Occurs if the description of the remote end of the + /// [`platform::RtcPeerConnection`] cannot be changed. + #[display(fmt = "Failed to set remote SDP description: {}", _0)] + #[from(ignore)] + SetRemoteDescriptionFailed(platform::Error), +} diff --git a/jason/src/platform/rtc_stats.rs b/jason/src/platform/rtc_stats.rs index 538a6841c..a5da68e4f 100644 --- a/jason/src/platform/rtc_stats.rs +++ b/jason/src/platform/rtc_stats.rs @@ -1,3 +1,5 @@ +//! Platform-agnostic functionality of [`platform::RtcStats`]. + use std::rc::Rc; use derive_more::{Display, From}; @@ -30,9 +32,7 @@ pub enum RtcStatsError { #[display(fmt = "RTCStats.entries is undefined")] UndefinedEntries, - /// [`RtcStats`] deserialization error. - /// - /// [`RtcStats`]: platform::RtcStats + /// [`platform::RtcStats`] deserialization error. #[display(fmt = "Failed to deserialize into RtcStats: {}", _0)] ParseError(Rc), } diff --git a/jason/src/platform/transport.rs b/jason/src/platform/transport.rs index 87db57386..3a9012b55 100644 --- a/jason/src/platform/transport.rs +++ b/jason/src/platform/transport.rs @@ -1,17 +1,17 @@ +//! Platform-agnostic functionality of RPC Transport. + use derive_more::Display; use futures::stream::LocalBoxStream; use medea_client_api_proto::{ClientMsg, ServerMsg}; use tracerr::Traced; use crate::{ - core::{ - rpc::{ClientDisconnect, CloseMsg}, - utils::JsonParseError, - }, platform, - utils::JsCaused, + rpc::{ClientDisconnect, CloseMsg}, + utils::{JsCaused, JsonParseError}, }; +#[doc(inline)] pub use super::wasm::transport::WebSocketRpcTransport; /// [`RpcTransport`] states. diff --git a/jason/src/platform/wasm/constraints.rs b/jason/src/platform/wasm/constraints.rs index f17ee6c5f..1471f0f29 100644 --- a/jason/src/platform/wasm/constraints.rs +++ b/jason/src/platform/wasm/constraints.rs @@ -1,4 +1,6 @@ -use crate::core::media::{ +//! Media tracks and streams constraints functionality. + +use crate::media::{ constraints::{ConstrainString, ConstrainU32}, AudioTrackConstraints, DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, @@ -16,6 +18,7 @@ pub struct MediaStreamConstraints(web_sys::MediaStreamConstraints); impl MediaStreamConstraints { /// Creates new [`MediaStreamConstraints`] with none constraints configured. + #[inline] pub fn new() -> Self { Self(web_sys::MediaStreamConstraints::new()) } @@ -23,6 +26,7 @@ impl MediaStreamConstraints { /// Specifies the nature and settings of the audio [MediaStreamTrack][1]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] pub fn audio(&mut self, audio: AudioTrackConstraints) { self.0.audio(&MediaTrackConstraints::from(audio).into()); } @@ -30,6 +34,7 @@ impl MediaStreamConstraints { /// Specifies the nature and settings of the video [MediaStreamTrack][1]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] pub fn video(&mut self, video: DeviceVideoTrackConstraints) { self.0.video(&MediaTrackConstraints::from(video).into()); } @@ -114,7 +119,7 @@ impl> From<&ConstrainString> for ConstrainDomStringParameters { /// [`DisplayMediaStreamConstraints`][1] wrapper. /// -/// [1]: https://www.w3.org/TR/screen-capture/#dom-displaymediastreamconstraints +/// [1]: https://w3.org/TR/screen-capture/#dom-displaymediastreamconstraints #[derive(AsRef, Debug, Into)] pub struct DisplayMediaStreamConstraints( web_sys::DisplayMediaStreamConstraints, @@ -129,6 +134,7 @@ impl Default for DisplayMediaStreamConstraints { impl DisplayMediaStreamConstraints { /// Creates new [`DisplayMediaStreamConstraints`] with none constraints /// configured. + #[inline] pub fn new() -> Self { Self(web_sys::DisplayMediaStreamConstraints::new()) } @@ -136,6 +142,7 @@ impl DisplayMediaStreamConstraints { /// Specifies the nature and settings of the video [MediaStreamTrack][1]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] pub fn video(&mut self, video: DisplayVideoTrackConstraints) { self.0.video(&MediaTrackConstraints::from(video).into()); } diff --git a/jason/src/platform/wasm/error.rs b/jason/src/platform/wasm/error.rs index 2d651b826..a6b62b4f5 100644 --- a/jason/src/platform/wasm/error.rs +++ b/jason/src/platform/wasm/error.rs @@ -1,3 +1,5 @@ +//! More convenient wrapper for [`js_sys::Error`]. + use std::borrow::Cow; use derive_more::Display; diff --git a/jason/src/platform/wasm/input_device_info.rs b/jason/src/platform/wasm/input_device_info.rs index 7a7e265c6..9828f9a40 100644 --- a/jason/src/platform/wasm/input_device_info.rs +++ b/jason/src/platform/wasm/input_device_info.rs @@ -7,7 +7,7 @@ use std::convert::TryFrom; use derive_more::Display; use web_sys as sys; -use crate::core; +use crate::media::MediaKind; /// Errors that may occur when parsing [MediaDeviceInfo][1]. /// @@ -23,7 +23,7 @@ pub enum Error { /// /// [1]: https://w3.org/TR/mediacapture-streams/#device-info pub struct InputDeviceInfo { - media_kind: core::MediaKind, + media_kind: MediaKind, /// Actual underlying [MediaDeviceInfo][1] object. /// @@ -31,7 +31,7 @@ pub struct InputDeviceInfo { info: sys::MediaDeviceInfo, } -impl TryFrom for core::MediaKind { +impl TryFrom for MediaKind { type Error = Error; fn try_from(value: sys::MediaDeviceKind) -> Result { @@ -45,6 +45,7 @@ impl TryFrom for core::MediaKind { impl InputDeviceInfo { /// Returns unique identifier for the represented device. + #[inline] pub fn device_id(&self) -> String { self.info.device_id() } @@ -54,13 +55,15 @@ impl InputDeviceInfo { /// This representation of [MediaDeviceInfo][1] ONLY for input device. /// /// [1]: https://w3.org/TR/mediacapture-streams/#device-info - pub fn kind(&self) -> core::MediaKind { + #[inline] + pub fn kind(&self) -> MediaKind { self.media_kind } /// Returns label describing the represented device (for example /// "External USB Webcam"). /// If the device has no associated label, then returns an empty string. + #[inline] pub fn label(&self) -> String { self.info.label() } @@ -73,6 +76,7 @@ impl InputDeviceInfo { /// same [groupId][1]. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediadeviceinfo-groupid + #[inline] pub fn group_id(&self) -> String { self.info.group_id() } @@ -83,7 +87,7 @@ impl TryFrom for InputDeviceInfo { fn try_from(info: sys::MediaDeviceInfo) -> Result { Ok(Self { - media_kind: core::MediaKind::try_from(info.kind())?, + media_kind: MediaKind::try_from(info.kind())?, info, }) } diff --git a/jason/src/platform/wasm/media_devices.rs b/jason/src/platform/wasm/media_devices.rs index eded79dc6..8117034d8 100644 --- a/jason/src/platform/wasm/media_devices.rs +++ b/jason/src/platform/wasm/media_devices.rs @@ -1,10 +1,14 @@ +//! [MediaDevices][1] functionality. +//! +//! [1]: https://tinyurl.com/w3-streams/#mediadevices + use std::convert::TryFrom as _; use wasm_bindgen_futures::JsFuture; use tracerr::Traced; use crate::{ - core::media::MediaManagerError, + media::MediaManagerError, platform::{ DisplayMediaStreamConstraints, Error, InputDeviceInfo, MediaStreamConstraints, MediaStreamTrack, @@ -120,7 +124,7 @@ pub async fn get_user_media( /// With [`MediaManagerError::GetUserMediaFailed`] if /// [MediaDevices.getDisplayMedia()][1] returns error. /// -/// [1]: https://www.w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia +/// [1]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia /// [2]: https://tinyurl.com/w3-streams/#mediadevices pub async fn get_display_media( caps: DisplayMediaStreamConstraints, diff --git a/jason/src/platform/wasm/media_track.rs b/jason/src/platform/wasm/media_track.rs index 773521564..cc9263d74 100644 --- a/jason/src/platform/wasm/media_track.rs +++ b/jason/src/platform/wasm/media_track.rs @@ -1,18 +1,25 @@ +//! Wrapper around [MediaStreamTrack][1]. +//! +//! [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + use derive_more::AsRef; -use crate::{api, core, platform::get_property_by_name}; +use crate::{ + media::{track::MediaStreamTrackState, FacingMode, MediaKind}, + platform::get_property_by_name, +}; /// Wrapper around [MediaStreamTrack][1] received from from /// [getUserMedia()][2]/[getDisplayMedia()][3] request. /// -/// [1]: https://www.w3.org/TR/mediacapture-streams/#mediastreamtrack +/// [1]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack /// [2]: https://w3.org/TR/mediacapture-streams/#dom-mediadevices-getusermedia /// [3]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia #[derive(AsRef, Clone, Debug)] pub struct MediaStreamTrack { #[as_ref] sys_track: web_sys::MediaStreamTrack, - kind: core::MediaKind, + kind: MediaKind, } impl From for MediaStreamTrack @@ -23,8 +30,8 @@ where fn from(from: T) -> MediaStreamTrack { let sys_track = web_sys::MediaStreamTrack::from(from); let kind = match sys_track.kind().as_ref() { - "audio" => core::MediaKind::Audio, - "video" => core::MediaKind::Video, + "audio" => MediaKind::Audio, + "video" => MediaKind::Video, _ => unreachable!(), }; @@ -37,28 +44,28 @@ impl MediaStreamTrack { /// /// [`id`]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-id /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] pub fn id(&self) -> String { self.sys_track.id() } /// Returns this [`MediaStreamTrack`]'s kind (audio/video). - pub fn kind(&self) -> core::MediaKind { + #[inline] + pub fn kind(&self) -> MediaKind { self.kind } /// Returns [`MediaStreamTrackState`][1] of underlying /// [MediaStreamTrack][2]. /// - /// [1]: core::MediaStreamTrackState + /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrackstate /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - pub fn ready_state(&self) -> core::MediaStreamTrackState { + pub fn ready_state(&self) -> MediaStreamTrackState { let state = self.sys_track.ready_state(); match state { - web_sys::MediaStreamTrackState::Live => { - core::MediaStreamTrackState::Live - } + web_sys::MediaStreamTrackState::Live => MediaStreamTrackState::Live, web_sys::MediaStreamTrackState::Ended => { - core::MediaStreamTrackState::Ended + MediaStreamTrackState::Ended } web_sys::MediaStreamTrackState::__Nonexhaustive => { unreachable!("Unknown MediaStreamTrackState::{:?}", state) @@ -70,6 +77,7 @@ impl MediaStreamTrack { /// /// [1]: https://tinyurl.com/w3-streams/#dom-mediatracksettings-deviceid /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] pub fn device_id(&self) -> Option { get_property_by_name(&self.sys_track.get_settings(), "deviceId", |v| { v.as_string() @@ -80,19 +88,19 @@ impl MediaStreamTrack { /// /// [1]: https://tinyurl.com/w3-streams/#dom-mediatracksettings-facingmode /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack - pub fn facing_mode(&self) -> Option { + pub fn facing_mode(&self) -> Option { let facing_mode = get_property_by_name( &self.sys_track.get_settings(), "facingMode", |v| v.as_string(), ); facing_mode.and_then(|facing_mode| match facing_mode.as_ref() { - "user" => Some(api::FacingMode::User), - "environment" => Some(api::FacingMode::Environment), - "left" => Some(api::FacingMode::Left), - "right" => Some(api::FacingMode::Right), + "user" => Some(FacingMode::User), + "environment" => Some(FacingMode::Environment), + "left" => Some(FacingMode::Left), + "right" => Some(FacingMode::Right), _ => { - // TODO: log err + log::error!("Unknown FacingMode: {}", facing_mode); None } }) @@ -102,6 +110,7 @@ impl MediaStreamTrack { /// /// [1]: https://tinyurl.com/w3-streams/#dom-mediatracksettings-height /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] pub fn height(&self) -> Option { #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] get_property_by_name(&self.sys_track.get_settings(), "height", |v| { @@ -113,6 +122,7 @@ impl MediaStreamTrack { /// /// [1]: https://tinyurl.com/w3-streams/#dom-mediatracksettings-width /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] pub fn width(&self) -> Option { #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] get_property_by_name(&self.sys_track.get_settings(), "width", |v| { @@ -125,6 +135,7 @@ impl MediaStreamTrack { /// /// [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.sys_track.set_enabled(enabled); } @@ -135,6 +146,7 @@ impl MediaStreamTrack { /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-readystate /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack /// [3]: https://tinyurl.com/w3-streams#idl-def-MediaStreamTrackState.ended + #[inline] pub fn stop(&self) { self.sys_track.stop() } @@ -144,6 +156,7 @@ impl MediaStreamTrack { /// /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled /// [2]: https://w3.org/TR/mediacapture-streams/#mediastreamtrack + #[inline] pub fn enabled(&self) -> bool { self.sys_track.enabled() } diff --git a/jason/src/platform/wasm/mod.rs b/jason/src/platform/wasm/mod.rs index 3a7254be7..442cb5e22 100644 --- a/jason/src/platform/wasm/mod.rs +++ b/jason/src/platform/wasm/mod.rs @@ -1,3 +1,5 @@ +//! `wasm32`-platform-specific functionality. + use std::{convert::TryInto as _, time::Duration}; pub mod constraints; @@ -33,7 +35,9 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[cfg(feature = "console_error_panic_hook")] pub use console_error_panic_hook::set_once as set_panic_hook; -/// Initialize [`wasm_logger`] with default [`wasm_logger::Config`]. +/// Initialize [`wasm_logger`] as default application logger. +/// +/// [`wasm_logger`]: https://docs.rs/wasm-logger pub fn init_logger() { wasm_logger::init(wasm_logger::Config::default()); } diff --git a/jason/src/platform/wasm/peer_connection.rs b/jason/src/platform/wasm/peer_connection.rs index f2de94996..f48efcc04 100644 --- a/jason/src/platform/wasm/peer_connection.rs +++ b/jason/src/platform/wasm/peer_connection.rs @@ -1,10 +1,13 @@ +//! Wrapper around [RTCPeerConnection][1]. +//! +//! [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection + use std::{ cell::{Cell, RefCell}, convert::TryFrom as _, rc::Rc, }; -use derive_more::{Display, From}; use medea_client_api_proto::{ IceConnectionState, IceServer, PeerConnectionState, }; @@ -19,42 +22,16 @@ use web_sys::{ }; use crate::{ - core::{ - media::{MediaKind, TrackConstraints}, - utils::JsCaused, - }, + media::{MediaKind, TrackConstraints}, platform::{ - self, get_property_by_name, wasm::utils::EventListener, - MediaStreamTrack, RtcStats, RtcStatsError, Transceiver, - TransceiverDirection, + self, get_property_by_name, wasm::utils::EventListener, IceCandidate, + MediaStreamTrack, RTCPeerConnectionError, RtcStats, SdpType, + Transceiver, TransceiverDirection, }, }; use super::ice_server::RtcIceServers; -/// [RTCIceCandidate][1] representation. -/// -/// [1]: https://w3.org/TR/webrtc/#rtcicecandidate-interface -pub struct IceCandidate { - /// [`candidate` field][2] of the discovered [RTCIceCandidate][1]. - /// - /// [1]: https://w3.org/TR/webrtc/#dom-rtcicecandidate - /// [2]: https://w3.org/TR/webrtc/#dom-rtcicecandidate-candidate - pub candidate: String, - - /// [`sdpMLineIndex` field][2] of the discovered [RTCIceCandidate][1]. - /// - /// [1]: https://w3.org/TR/webrtc/#dom-rtcicecandidate - /// [2]: https://w3.org/TR/webrtc/#dom-rtcicecandidate-sdpmlineindex - pub sdp_m_line_index: Option, - - /// [`sdpMid` field][2] of the discovered [RTCIceCandidate][1]. - /// - /// [1]: https://w3.org/TR/webrtc/#dom-rtcicecandidate - /// [2]: https://w3.org/TR/webrtc/#dom-rtcicecandidate-sdpmid - pub sdp_mid: Option, -} - impl From<&TrackConstraints> for MediaKind { fn from(media_type: &TrackConstraints) -> Self { match media_type { @@ -64,77 +41,6 @@ impl From<&TrackConstraints> for MediaKind { } } -/// Representation of [RTCSdpType]. -/// -/// [RTCSdpType]: https://w3.org/TR/webrtc/#dom-rtcsdptype -pub enum SdpType { - /// [`offer` type][1] of SDP. - /// - /// [1]: https://w3.org/TR/webrtc/#dom-rtcsdptype-offer - Offer(String), - - /// [`answer` type][1] of SDP. - /// - /// [1]: https://w3.org/TR/webrtc/#dom-rtcsdptype-answer - Answer(String), -} - -/// Errors that may occur during signaling between this and remote -/// [RTCPeerConnection][1] and event handlers setting errors. -/// -/// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection -#[derive(Clone, Debug, Display, From, JsCaused)] -#[js(error = "platform::Error")] -pub enum RTCPeerConnectionError { - /// Occurs when cannot adds new remote candidate to the - /// [RTCPeerConnection][1]'s remote description. - /// - /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection - #[display(fmt = "Failed to add ICE candidate: {}", _0)] - #[from(ignore)] - AddIceCandidateFailed(platform::Error), - - /// Occurs when cannot obtains [SDP answer][`SdpType::Answer`] from - /// the underlying [RTCPeerConnection][`SysRtcPeerConnection`]. - #[display(fmt = "Failed to create SDP answer: {}", _0)] - #[from(ignore)] - CreateAnswerFailed(platform::Error), - - /// Occurs when a new [`RtcPeerConnection`] cannot be created. - #[display(fmt = "Failed to create PeerConnection: {}", _0)] - #[from(ignore)] - PeerCreationError(platform::Error), - - /// Occurs when cannot obtains [SDP offer][`SdpType::Offer`] from - /// the underlying [RTCPeerConnection][`SysRtcPeerConnection`] - #[display(fmt = "Failed to create SDP offer: {}", _0)] - #[from(ignore)] - CreateOfferFailed(platform::Error), - - /// Occurs while getting and parsing [`RtcStats`] of [`RtcPeerConnection`]. - #[display(fmt = "Failed to get RTCStats: {}", _0)] - RtcStatsError(#[js(cause)] RtcStatsError), - - /// [PeerConnection.getStats][1] promise thrown exception. - /// - /// [1]: https://tinyurl.com/w6hmt5f - #[display(fmt = "PeerConnection.getStats() failed with error: {}", _0)] - #[from(ignore)] - GetStatsException(platform::Error), - - /// Occurs if the local description associated with the - /// [`RtcPeerConnection`] cannot be changed. - #[display(fmt = "Failed to set local SDP description: {}", _0)] - #[from(ignore)] - SetLocalDescriptionFailed(platform::Error), - - /// Occurs if the description of the remote end of the - /// [`RtcPeerConnection`] cannot be changed. - #[display(fmt = "Failed to set remote SDP description: {}", _0)] - #[from(ignore)] - SetRemoteDescriptionFailed(platform::Error), -} - type Result = std::result::Result>; /// Representation of [RTCPeerConnection][1]. @@ -461,6 +367,7 @@ impl RtcPeerConnection { /// After this function returns, the offer returned by the next call to /// [`RtcPeerConnection::create_offer`] is automatically configured /// to trigger ICE restart. + #[inline] pub fn restart_ice(&self) { self.ice_restart.set(true); } diff --git a/jason/src/platform/wasm/rtc_stats.rs b/jason/src/platform/wasm/rtc_stats.rs index 6a4fc10a6..97623a189 100644 --- a/jason/src/platform/wasm/rtc_stats.rs +++ b/jason/src/platform/wasm/rtc_stats.rs @@ -13,9 +13,7 @@ use wasm_bindgen::{prelude::*, JsCast}; use crate::platform::{self, get_property_by_name, RtcStatsError}; -/// All available [`RtcStatsType`] of [`RtcPeerConnection`]. -/// -/// [`RtcPeerConnection`]: platform::RtcPeerConnection +/// All available [`RtcStatsType`] of [`platform::RtcPeerConnection`]. #[derive(Clone, Debug)] pub struct RtcStats(pub Vec); diff --git a/jason/src/platform/wasm/transceiver.rs b/jason/src/platform/wasm/transceiver.rs index 4839939eb..e364d68e0 100644 --- a/jason/src/platform/wasm/transceiver.rs +++ b/jason/src/platform/wasm/transceiver.rs @@ -8,7 +8,7 @@ use wasm_bindgen::JsValue; use wasm_bindgen_futures::JsFuture; use web_sys::{RtcRtpTransceiver, RtcRtpTransceiverDirection}; -use crate::{core::media::track::local, platform::MediaStreamTrack}; +use crate::{media::track::local, platform::MediaStreamTrack}; /// Wrapper around [`RtcRtpTransceiver`] which provides handy methods for /// direction changes. @@ -20,11 +20,13 @@ pub struct Transceiver { impl Transceiver { /// Returns current [`TransceiverDirection`] of this [`Transceiver`]. + #[inline] fn current_direction(&self) -> TransceiverDirection { TransceiverDirection::from(self.transceiver.direction()) } /// Disables provided [`TransceiverDirection`] of this [`Transceiver`]. + #[inline] pub fn sub_direction(&self, disabled_direction: TransceiverDirection) { self.transceiver.set_direction( (self.current_direction() - disabled_direction).into(), @@ -32,6 +34,7 @@ impl Transceiver { } /// Enables provided [`TransceiverDirection`] of this [`Transceiver`]. + #[inline] pub fn add_direction(&self, enabled_direction: TransceiverDirection) { self.transceiver.set_direction( (self.current_direction() | enabled_direction).into(), @@ -40,6 +43,7 @@ impl Transceiver { /// Indicates whether the provided [`TransceiverDirection`] is enabled for /// this [`Transceiver`]. + #[inline] pub fn has_direction(&self, direction: TransceiverDirection) -> bool { self.current_direction().contains(direction) } @@ -75,11 +79,13 @@ impl Transceiver { /// Returns [`mid`] of this [`Transceiver`]. /// /// [`mid`]: https://w3.org/TR/webrtc/#dom-rtptransceiver-mid + #[inline] pub fn mid(&self) -> Option { self.transceiver.mid() } /// Returns [`local::Track`] that is being send to remote, if any. + #[inline] pub fn send_track(&self) -> Option> { self.send_track.borrow().clone() } @@ -93,6 +99,7 @@ impl Transceiver { /// Sets the underlying [`local::Track`]'s `enabled` field to the provided /// value, if any. + #[inline] 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/jason/src/platform/wasm/transport.rs b/jason/src/platform/wasm/transport.rs index 0b1eec307..70e761be9 100644 --- a/jason/src/platform/wasm/transport.rs +++ b/jason/src/platform/wasm/transport.rs @@ -12,14 +12,12 @@ use tracerr::Traced; use web_sys::{CloseEvent, Event, MessageEvent, WebSocket as SysWebSocket}; use crate::{ - core::{ - rpc::{websocket::ClientDisconnect, ApiUrl, CloseMsg}, - utils::JasonError, - }, platform::{ transport::{RpcTransport, TransportError, TransportState}, wasm::utils::EventListener, }, + rpc::{websocket::ClientDisconnect, ApiUrl, CloseMsg}, + utils::JasonError, }; /// Wrapper for help to get [`ServerMsg`] from Websocket [MessageEvent][1]. @@ -231,6 +229,7 @@ impl WebSocketRpcTransport { } impl RpcTransport for WebSocketRpcTransport { + #[inline] fn on_message(&self) -> LocalBoxStream<'static, ServerMsg> { let (tx, rx) = mpsc::unbounded(); self.0.borrow_mut().on_message_subs.push(tx); @@ -238,6 +237,7 @@ impl RpcTransport for WebSocketRpcTransport { Box::pin(rx) } + #[inline] fn set_close_reason(&self, close_reason: ClientDisconnect) { self.0.borrow_mut().close_reason = close_reason; } @@ -260,6 +260,7 @@ impl RpcTransport for WebSocketRpcTransport { } } + #[inline] fn on_state_change(&self) -> LocalBoxStream<'static, TransportState> { self.0.borrow().socket_state.subscribe() } diff --git a/jason/src/platform/wasm/utils/event_listener.rs b/jason/src/platform/wasm/utils/event_listener.rs index 89e37a4a9..2317225f2 100644 --- a/jason/src/platform/wasm/utils/event_listener.rs +++ b/jason/src/platform/wasm/utils/event_listener.rs @@ -4,7 +4,7 @@ use derive_more::{Display, From}; use tracerr::Traced; use wasm_bindgen::{closure::Closure, convert::FromWasmAbi, JsCast}; -use crate::{core::utils::JsCaused, platform}; +use crate::{platform, utils::JsCaused}; /// Failed to bind to [`EventTarget`][1] event. /// @@ -14,6 +14,8 @@ use crate::{core::utils::JsCaused, platform}; pub struct EventListenerBindError(platform::Error); /// Wrapper for closure that handles some [`EventTarget`] event. +/// +/// [`EventTarget`]: web_sys::EventTarget pub struct EventListener where T: Deref, diff --git a/jason/src/platform/wasm/utils/mod.rs b/jason/src/platform/wasm/utils/mod.rs index 99a766a19..d7bcc03a0 100644 --- a/jason/src/platform/wasm/utils/mod.rs +++ b/jason/src/platform/wasm/utils/mod.rs @@ -1,3 +1,5 @@ +//! `wasm32`-specific utility structs and functions. + mod callback; mod event_listener; diff --git a/jason/src/core/room.rs b/jason/src/room.rs similarity index 96% rename from jason/src/core/room.rs rename to jason/src/room.rs index fb06ed497..b7bd7ed10 100644 --- a/jason/src/core/room.rs +++ b/jason/src/room.rs @@ -1,4 +1,7 @@ -//! Medea room. +//! Medea `Room`. + +// TODO: Remove when moving JasonError to api::wasm. +#![allow(clippy::missing_errors_doc)] use std::{ cell::RefCell, @@ -23,26 +26,23 @@ use tracerr::Traced; use crate::{ api, - core::{ - media::{ - track::{local, remote}, - LocalTracksConstraints, MediaKind, MediaManager, MediaManagerError, - MediaSourceKind, MediaStreamSettings, RecvConstraints, - }, - peer::{ - self, media_exchange_state, mute_state, LocalStreamUpdateCriteria, - MediaConnectionsError, MediaState, PeerConnection, PeerError, - PeerEvent, PeerEventHandler, TrackDirection, - }, - rpc::{ - ClientDisconnect, CloseReason, ConnectionInfo, - ConnectionInfoParseError, ReconnectHandle, RpcSession, - SessionError, - }, - utils::{AsProtoState, HandlerDetachedError, JasonError, JsCaused}, - Connections, + connection::Connections, + media::{ + track::{local, remote}, + LocalTracksConstraints, MediaKind, MediaManager, MediaManagerError, + MediaSourceKind, MediaStreamSettings, RecvConstraints, + }, + peer::{ + self, media_exchange_state, mute_state, LocalStreamUpdateCriteria, + MediaConnectionsError, MediaState, PeerConnection, PeerError, + PeerEvent, PeerEventHandler, TrackDirection, }, platform, + rpc::{ + ClientDisconnect, CloseReason, ConnectionInfo, + ConnectionInfoParseError, ReconnectHandle, RpcSession, SessionError, + }, + utils::{AsProtoState, HandlerDetachedError, JasonError, JsCaused}, }; /// Reason of why [`Room`] has been closed. @@ -140,7 +140,7 @@ pub enum RoomError { /// Returned if [`track`] update failed. /// - /// [`track`]: crate::core::media::track + /// [`track`]: crate::media::track #[display(fmt = "Failed to update Track with {} ID.", _0)] #[from(ignore)] FailedTrackPatch(TrackId), @@ -200,8 +200,6 @@ impl RoomHandle { /// - `on_failed_local_media` callback is not set /// - `on_connection_loss` callback is not set /// - unable to connect to media server. - /// - /// Effectively returns `Result<(), JasonError>`. pub async fn join(&self, url: String) -> Result<(), JasonError> { let inner = upgrade_or_detached!(self.0, JasonError)?; @@ -302,7 +300,7 @@ impl RoomHandle { /// Sets callback, which will be invoked when new [`Connection`] with some /// remote `Peer` is established. /// - /// [`Connection`]: crate::core::Connection + /// [`Connection`]: crate::connection::Connection pub fn on_new_connection( &self, f: platform::Function, @@ -398,9 +396,8 @@ impl RoomHandle { Ok(()) } - /// Returns [`Promise`] which will switch [`MediaState`] of the provided - /// [`MediaKind`], [`TrackDirection`] and [`MediaSourceKind`] to the - /// provided [`MediaState`]. + /// Changes [`MediaState`] of the provided [`MediaKind`], [`TrackDirection`] + /// and [`MediaSourceKind`] to the provided [`MediaState`]. /// /// Helper function for all the exported mute/unmute/enable/disable /// audio/video send/receive methods. @@ -736,11 +733,11 @@ struct InnerRoom { /// Collection of [`Connection`]s with a remote `Member`s. /// - /// [`Connection`]: crate::core::Connection + /// [`Connection`]: crate::connection::Connection connections: Rc, - /// Callback to be invoked when new local [`local::JsTrack`] will be added - /// to this [`Room`]. + /// Callback to be invoked when new local [`local::LocalMediaTrack`] will + /// be added to this [`Room`]. on_local_track: platform::Callback, /// Callback to be invoked when failed obtain [`local::Track`]s from @@ -750,7 +747,7 @@ struct InnerRoom { /// Callback to be invoked when [`RpcSession`] loses connection. on_connection_loss: platform::Callback, - /// JS callback which will be called when this [`Room`] will be closed. + /// Callback which will be called when this [`Room`] will be closed. on_close: Rc>, /// Reason of [`Room`] closing. @@ -762,7 +759,7 @@ struct InnerRoom { close_reason: RefCell, } -/// JS exception for the [`RoomHandle::set_local_media_settings`]. +/// Exception for the [`RoomHandle::set_local_media_settings`]. #[derive(Debug, Display)] pub enum ConstraintsUpdateException { /// New [`MediaStreamSettings`] set failed and state was recovered @@ -1117,17 +1114,15 @@ impl InnerRoom { /// Returns [`local::Track`]s for the provided [`MediaKind`] and /// [`proto::MediaSourceKind`]. /// - /// If [`proto::MediaSourceKind`] is [`None`] then [`local::TrackHandle`]s - /// for all needed [`proto::MediaSourceKind`]s will be returned. + /// If [`proto::MediaSourceKind`] is [`None`] then [`local::Track`]s for all + /// needed [`proto::MediaSourceKind`]s will be returned. /// /// # Errors /// - /// - [`RoomError::MediaManagerError`] if failed to obtain - /// [`local::TrackHandle`] from the [`MediaManager`]. + /// - [`RoomError::MediaManagerError`] if failed to obtain [`local::Track`] + /// from the [`MediaManager`]. /// - [`RoomError::PeerConnectionError`] if failed to get /// [`MediaStreamSettings`]. - /// - /// [`MediaStreamSettings`]: crate::MediaStreamSettings async fn get_local_tracks( &self, kind: MediaKind, @@ -1170,8 +1165,8 @@ impl InnerRoom { /// [`MediaKind`] and [`proto::MediaSourceKind`] of this [`Room`] are in the /// provided [`MediaState`]. /// - /// [`Sender`]: crate::peer::Sender - /// [`Receiver`]: crate::peer::Receiver + /// [`Sender`]: peer::media::Sender + /// [`Receiver`]: peer::media::Receiver pub fn is_all_peers_in_media_state( &self, kind: MediaKind, @@ -1196,7 +1191,7 @@ impl InnerRoom { /// Updates [`MediaState`]s to the provided `states_update` and disables all /// [`Sender`]s which are doesn't have [`local::Track`]. /// - /// [`Sender`]: crate::peer::Sender + /// [`Sender`]: peer::media::Sender async fn disable_senders_without_tracks( &self, peer: &Rc, @@ -1248,7 +1243,7 @@ impl InnerRoom { /// `true` then affected media types will be disabled. /// /// [1]: https://tinyurl.com/rnxcavf - /// [`Sender`]: crate::peer::Sender + /// [`Sender`]: peer::media::Sender #[async_recursion(?Send)] async fn set_local_media_settings( &self, @@ -1368,7 +1363,7 @@ 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::core::Connection + /// [`Connection`]: crate::connection::Connection async fn on_peer_created( &self, peer_id: PeerId, @@ -1460,8 +1455,8 @@ impl EventHandler for InnerRoom { /// Will start (re)negotiation process if `Some` [`NegotiationRole`] is /// provided. /// - /// [`Receiver`]: crate::peer::Receiver - /// [`Sender`]: crate::peer::Sender + /// [`Receiver`]: peer::media::Receiver + /// [`Sender`]: peer::media::Sender async fn on_tracks_applied( &self, peer_id: PeerId, @@ -1501,8 +1496,8 @@ impl EventHandler for InnerRoom { /// Updates [`Connection`]'s [`ConnectionQualityScore`] by calling /// [`Connection::update_quality_score()`][1]. /// - /// [`Connection`]: crate::core::Connection - /// [1]: crate::core::Connection::update_quality_score + /// [`Connection`]: crate::connection::Connection + /// [1]: crate::connection::Connection::update_quality_score async fn on_connection_quality_updated( &self, partner_member_id: MemberId, @@ -1566,7 +1561,7 @@ impl PeerEventHandler for InnerRoom { /// Handles [`PeerEvent::NewRemoteTrack`] event and passes received /// [`remote::Track`] to the related [`Connection`]. /// - /// [`Connection`]: crate::core::Connection + /// [`Connection`]: crate::connection::Connection /// [`Stream`]: futures::Stream async fn on_new_remote_track( &self, @@ -1681,7 +1676,7 @@ impl PeerEventHandler for InnerRoom { Ok(()) } - /// Handles [`PeerEvent::SendIntention`] event by sending the provided + /// Handles [`PeerEvent::MediaUpdateCommand`] event by sending the provided /// [`Command`] to Media Server. async fn on_media_update_command( &self, diff --git a/jason/src/core/rpc/backoff_delayer.rs b/jason/src/rpc/backoff_delayer.rs similarity index 100% rename from jason/src/core/rpc/backoff_delayer.rs rename to jason/src/rpc/backoff_delayer.rs diff --git a/jason/src/core/rpc/heartbeat.rs b/jason/src/rpc/heartbeat.rs similarity index 92% rename from jason/src/core/rpc/heartbeat.rs rename to jason/src/rpc/heartbeat.rs index 6e6b01c65..7f5c0e273 100644 --- a/jason/src/core/rpc/heartbeat.rs +++ b/jason/src/rpc/heartbeat.rs @@ -7,8 +7,8 @@ use futures::{channel::mpsc, future, stream::LocalBoxStream, StreamExt as _}; use medea_client_api_proto::{ClientMsg, ServerMsg}; use crate::{ - core::utils::{JsCaused, TaskHandle}, platform, + utils::{JsCaused, TaskHandle}, }; /// Errors that may occur in [`Heartbeat`]. @@ -30,13 +30,13 @@ pub struct PingInterval(pub Duration); /// Inner data of [`Heartbeat`]. struct Inner { - /// [`RpcTransport`] which heartbeats. + /// [`platform::RpcTransport`] which heartbeats. transport: Rc, - /// Idle timeout of [`RpcTransport`]. + /// Idle timeout of [`platform::RpcTransport`]. idle_timeout: IdleTimeout, - /// Ping interval of [`RpcTransport`]. + /// Ping interval of [`platform::RpcTransport`]. ping_interval: PingInterval, /// [`TaskHandle`] for [`Future`] which sends [`ClientMsg::Pong`] on @@ -72,10 +72,8 @@ impl Inner { pub struct Heartbeat(Rc>); impl Heartbeat { - /// Start this [`Heartbeat`] for the provided [`RpcTransport`] with - /// the provided `idle_timeout` and `ping_interval`. - /// - /// [`RpcTransport`]: platform::RpcTransport + /// Start this [`Heartbeat`] for the provided [`platform::RpcTransport`] + /// with the provided `idle_timeout` and `ping_interval`. pub fn start( transport: Rc, ping_interval: PingInterval, @@ -111,9 +109,7 @@ impl Heartbeat { } /// Returns [`LocalBoxStream`] to which will sent `()` when [`Heartbeat`] - /// considers that [`RpcTransport`] is idle. - /// - /// [`RpcTransport`]: platform::RpcTransport + /// considers that [`platform::RpcTransport`] is idle. pub fn on_idle(&self) -> LocalBoxStream<'static, ()> { let (on_idle_tx, on_idle_rx) = mpsc::unbounded(); self.0.borrow_mut().on_idle_subs.push(on_idle_tx); diff --git a/jason/src/core/rpc/mod.rs b/jason/src/rpc/mod.rs similarity index 97% rename from jason/src/core/rpc/mod.rs rename to jason/src/rpc/mod.rs index 0544dd059..1458dfdfe 100644 --- a/jason/src/core/rpc/mod.rs +++ b/jason/src/rpc/mod.rs @@ -15,7 +15,7 @@ use medea_client_api_proto::{ use tracerr::Traced; use url::Url; -use crate::{core::utils::JsCaused, platform}; +use crate::{platform, utils::JsCaused}; #[cfg(feature = "mockable")] pub use self::rpc_session::MockRpcSession; @@ -156,10 +156,8 @@ pub enum CloseReason { }, } -/// The reason of why [`WebSocketRpcClient`]/[`RpcTransport`] went into -/// closed state. -/// -/// [`RpcTransport`]: platform::RpcTransport +/// The reason of why [`WebSocketRpcClient`]/[`platform::RpcTransport`] went +/// into closed state. #[derive(Clone, Debug, PartialEq)] pub enum ClosedStateReason { /// Connection with server was lost. diff --git a/jason/src/core/rpc/reconnect_handle.rs b/jason/src/rpc/reconnect_handle.rs similarity index 90% rename from jason/src/core/rpc/reconnect_handle.rs rename to jason/src/rpc/reconnect_handle.rs index 646f0cfaa..8a6631840 100644 --- a/jason/src/core/rpc/reconnect_handle.rs +++ b/jason/src/rpc/reconnect_handle.rs @@ -1,15 +1,16 @@ //! Reconnection for [`RpcSession`]. +// TODO: Remove when moving JasonError to api::wasm. +#![allow(clippy::missing_errors_doc)] + use std::{rc::Weak, time::Duration}; use derive_more::Display; use crate::{ - core::{ - rpc::{BackoffDelayer, RpcSession}, - utils::{HandlerDetachedError, JasonError, JsCaused}, - }, platform, + rpc::{BackoffDelayer, RpcSession}, + utils::{HandlerDetachedError, JasonError, JsCaused}, }; /// Error which indicates that [`RpcSession`]'s (which this [`ReconnectHandle`] @@ -18,8 +19,8 @@ use crate::{ #[js(error = "platform::Error")] struct NoTokenError; -/// Handle that JS side can reconnect to the Medea media server on -/// a connection loss with. +/// External handle that is used to reconnect to the Medea media server on +/// connection loss. /// /// This handle will be provided into `Room.on_connection_loss` callback. #[derive(Clone)] diff --git a/jason/src/core/rpc/rpc_session.rs b/jason/src/rpc/rpc_session.rs similarity index 96% rename from jason/src/core/rpc/rpc_session.rs rename to jason/src/rpc/rpc_session.rs index 65aabab04..18eb7d5e1 100644 --- a/jason/src/core/rpc/rpc_session.rs +++ b/jason/src/rpc/rpc_session.rs @@ -1,3 +1,7 @@ +//! Wrapper for [WebSocket] based transport that implements `Room` management. +//! +//! [WebSocket]: https://developer.mozilla.org/ru/docs/WebSockets + use std::{ cell::{Cell, RefCell}, rc::Rc, @@ -17,14 +21,12 @@ use medea_reactive::ObservableCell; use tracerr::Traced; use crate::{ - core::{ - rpc::{ - websocket::RpcEventHandler, ClientDisconnect, CloseReason, - ConnectionInfo, RpcClientError, WebSocketRpcClient, - }, - utils::JsCaused, - }, platform, + rpc::{ + websocket::RpcEventHandler, ClientDisconnect, CloseReason, + ConnectionInfo, RpcClientError, WebSocketRpcClient, + }, + utils::JsCaused, }; /// Errors which are can be returned from the [`WebSocketRpcSession`]. @@ -115,14 +117,12 @@ pub trait RpcSession { /// Subscribe to connection loss events. /// - /// Connection loss is any unexpected [`RpcTransport`] close. In case of - /// connection loss, JS side user should select reconnection strategy with - /// [`ReconnectHandle`] (or simply close [`Room`]). + /// Connection loss is any unexpected [`platform::RpcTransport`] close. In + /// case of connection loss, client side user should select reconnection + /// strategy with [`ReconnectHandle`] (or simply close [`Room`]). /// - /// [`ReconnectHandle`]: platform::RpcTransport - /// [`Room`]: crate::core::Room - /// [`RpcTransport`]: platform::RpcTransport - /// [`Stream`]: futures::Stream + /// [`ReconnectHandle`]: crate::rpc::ReconnectHandle + /// [`Room`]: crate::room::Room fn on_connection_loss(&self) -> LocalBoxStream<'static, ()>; /// Subscribe to reconnected events. @@ -136,9 +136,9 @@ pub trait RpcSession { /// /// Responsible for [`Room`] authorization and closing. /// -/// [`Room`]: crate::core::Room +/// [`Room`]: crate::room::Room pub struct WebSocketRpcSession { - /// [WebSocket] based Rpc Client used to . + /// [WebSocket] based Rpc Client used to talk with `Medea` server. /// /// [WebSocket]: https://developer.mozilla.org/ru/docs/WebSockets client: Rc, diff --git a/jason/src/core/rpc/websocket/client.rs b/jason/src/rpc/websocket/client.rs similarity index 91% rename from jason/src/core/rpc/websocket/client.rs rename to jason/src/rpc/websocket/client.rs index 0d7e35201..2b455c563 100644 --- a/jason/src/core/rpc/websocket/client.rs +++ b/jason/src/rpc/websocket/client.rs @@ -16,14 +16,12 @@ use serde::Serialize; use tracerr::Traced; use crate::{ - core::{ - rpc::{ - ApiUrl, CloseMsg, CloseReason, ClosedStateReason, Heartbeat, - IdleTimeout, PingInterval, RpcClientError, - }, - utils::JasonError, - }, platform, + rpc::{ + ApiUrl, CloseMsg, CloseReason, ClosedStateReason, Heartbeat, + IdleTimeout, PingInterval, RpcClientError, + }, + utils::JasonError, }; /// Reasons of closing WebSocket RPC connection by a client side. @@ -31,25 +29,23 @@ use crate::{ pub enum ClientDisconnect { /// [`Room`] was dropped without any [`CloseReason`]. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room RoomUnexpectedlyDropped, - /// [`Room`] was normally closed by JS side. + /// [`Room`] was normally closed bu client. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room RoomClosed, /// [`WebSocketRpcClient`] was unexpectedly dropped. RpcClientUnexpectedlyDropped, - /// [`RpcTransport`] was unexpectedly dropped. - /// - /// [`RpcTransport`]: platform::RpcTransport + /// [`platform::RpcTransport`] was unexpectedly dropped. RpcTransportUnexpectedlyDropped, /// [`WebSocketRpcSession`] was unexpectedly dropped. /// - /// [`WebSocketRpcSession`]: crate::core::rpc::WebSocketRpcSession + /// [`WebSocketRpcSession`]: crate::rpc::WebSocketRpcSession SessionUnexpectedlyDropped, } @@ -78,9 +74,7 @@ impl From for CloseReason { } } -/// State of [`WebSocketRpcClient`] and [`RpcTransport`]. -/// -/// [`RpcTransport`]: platform::RpcTransport +/// State of [`WebSocketRpcClient`] and [`platform::RpcTransport`]. #[derive(Clone, Debug, PartialEq)] pub enum ClientState { /// [`WebSocketRpcClient`] is currently establishing a connection to RPC @@ -111,38 +105,31 @@ struct Inner { /// Reason of [`WebSocketRpcClient`] closing. /// - /// This reason will be provided to the underlying [`RpcTransport`]. - /// - /// [`RpcTransport`]: platform::RpcTransport + /// This reason will be provided to the underlying + /// [`platform::RpcTransport`]. close_reason: ClientDisconnect, /// Subscribers that will be notified when underlying transport connection /// is lost. on_connection_loss_subs: Vec>, - /// Closure which will create new [`RpcTransport`]s for this + /// Closure which will create new [`platform::RpcTransport`]s for this /// [`WebSocketRpcClient`] on each /// [`WebSocketRpcClient:: establish_connection`] call. - /// - /// [`RpcTransport`]: platform::RpcTransport rpc_transport_factory: RpcTransportFactory, - /// URL that [`RpcTransport`] will connect to. + /// URL that [`platform::RpcTransport`] will connect to. /// /// [`None`] if this [`WebSocketRpcClient`] has never been connected to /// a sever. - /// - /// [`RpcTransport`]: platform::RpcTransport url: Option, /// Current [`ClientState`] of this [`WebSocketRpcClient`]. state: ObservableCell, } -/// Factory closure which creates [`RpcTransport`] for +/// Factory closure which creates [`platform::RpcTransport`] for /// [`WebSocketRpcClient::establish_connection`] function. -/// -/// [`RpcTransport`]: platform::RpcTransport pub type RpcTransportFactory = Box< dyn Fn( ApiUrl, @@ -181,11 +168,11 @@ pub enum RpcEvent { /// Notification of the subscribers that [`WebSocketRpcClient`] is joined /// [`Room`] on Media Server. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room JoinedRoom { /// ID of the joined [`Room`]. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room room_id: RoomId, /// ID of the joined `Member`. @@ -195,16 +182,16 @@ pub enum RpcEvent { /// Notification of the subscribers that [`WebSocketRpcClient`] left /// [`Room`] on Media Server. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room LeftRoom { /// ID of the [`Room`] being left. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room room_id: RoomId, /// Reason of why the [`Room`] has been left. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room close_reason: CloseReason, }, @@ -212,7 +199,7 @@ pub enum RpcEvent { Event { /// ID of the [`Room`] for that this [`Event`] has been received for. /// - /// [`Room`]: crate::core::Room + /// [`Room`]: crate::room::Room room_id: RoomId, /// Received [`Event`]. @@ -345,9 +332,7 @@ impl WebSocketRpcClient { } /// Starts [`Heartbeat`] with provided [`RpcSettings`] for provided - /// [`RpcTransport`]. - /// - /// [`RpcTransport`]: platform::RpcTransport + /// [`platform::RpcTransport`]. async fn start_heartbeat( self: Rc, transport: Rc, @@ -565,13 +550,12 @@ impl WebSocketRpcClient { /// Subscribe to connection loss events. /// - /// Connection loss is any unexpected [`RpcTransport`] close. In case of - /// connection loss, JS side user should select reconnection strategy with - /// [`ReconnectHandle`] (or simply close [`Room`]). + /// Connection loss is any unexpected [`platform::RpcTransport`] close. In + /// case of connection loss, client side user should select reconnection + /// strategy with [`ReconnectHandle`] (or simply close [`Room`]). /// - /// [`RpcTransport`]: platform::RpcTransport - /// [`ReconnectHandle`]: crate::core::rpc::ReconnectHandle - /// [`Room`]: crate::core::Room + /// [`ReconnectHandle`]: crate::rpc::ReconnectHandle + /// [`Room`]: crate::room::Room /// [`Stream`]: futures::Stream pub fn on_connection_loss(&self) -> LocalBoxStream<'static, ()> { let (tx, rx) = mpsc::unbounded(); diff --git a/jason/src/core/rpc/websocket/mod.rs b/jason/src/rpc/websocket/mod.rs similarity index 100% rename from jason/src/core/rpc/websocket/mod.rs rename to jason/src/rpc/websocket/mod.rs diff --git a/jason/src/core/utils/component.rs b/jason/src/utils/component.rs similarity index 98% rename from jason/src/core/utils/component.rs rename to jason/src/utils/component.rs index 705c6e9ae..3814dcb9d 100644 --- a/jason/src/core/utils/component.rs +++ b/jason/src/utils/component.rs @@ -7,11 +7,9 @@ use futures::{future, Future, FutureExt as _, Stream, StreamExt}; use medea_reactive::AllProcessed; use crate::{ - core::{ - media::LocalTracksConstraints, - utils::{JasonError, TaskHandle}, - }, + media::LocalTracksConstraints, platform, + utils::{JasonError, TaskHandle}, }; /// Abstraction over a state which can be transformed to the states from the diff --git a/jason/src/core/utils/errors.rs b/jason/src/utils/errors.rs similarity index 98% rename from jason/src/core/utils/errors.rs rename to jason/src/utils/errors.rs index 7aba000a5..1b45f9b65 100644 --- a/jason/src/core/utils/errors.rs +++ b/jason/src/utils/errors.rs @@ -1,3 +1,5 @@ +//! Helpers for application errors. + use std::{ fmt::{Debug, Display}, rc::Rc, diff --git a/jason/src/core/utils/mod.rs b/jason/src/utils/mod.rs similarity index 100% rename from jason/src/core/utils/mod.rs rename to jason/src/utils/mod.rs diff --git a/jason/src/core/utils/resettable_delay.rs b/jason/src/utils/resettable_delay.rs similarity index 100% rename from jason/src/core/utils/resettable_delay.rs rename to jason/src/utils/resettable_delay.rs diff --git a/jason/tests/media/constraints.rs b/jason/tests/media/constraints.rs index dfc567e4b..dd645cdd9 100644 --- a/jason/tests/media/constraints.rs +++ b/jason/tests/media/constraints.rs @@ -2,7 +2,7 @@ use medea_client_api_proto::{MediaSourceKind, VideoSettings}; use medea_jason::{ - core::media::{ + media::{ AudioTrackConstraints, DeviceVideoTrackConstraints, DisplayVideoTrackConstraints, MediaKind, MediaManager, MediaStreamSettings, MultiSourceTracksConstraints, VideoSource, diff --git a/jason/tests/media/manager.rs b/jason/tests/media/manager.rs index c4a533bd9..d13bfe92b 100644 --- a/jason/tests/media/manager.rs +++ b/jason/tests/media/manager.rs @@ -9,10 +9,10 @@ use web_sys as sys; use medea_jason::{ api, - core::{ - media::{MediaKind, MediaManager, MediaManagerError}, + media::{ AudioTrackConstraints, DeviceVideoTrackConstraints, - DisplayVideoTrackConstraints, MediaStreamSettings, + DisplayVideoTrackConstraints, MediaKind, MediaManager, + MediaManagerError, MediaStreamSettings, }, }; diff --git a/jason/tests/media/mod.rs b/jason/tests/media/mod.rs index 2dcfd040e..1e040a0a0 100644 --- a/jason/tests/media/mod.rs +++ b/jason/tests/media/mod.rs @@ -9,12 +9,8 @@ use medea_client_api_proto::{ AudioSettings, Direction, MediaType, MemberId, Track, TrackId, }; use medea_jason::{ - core::{ - media::{MediaManager, RecvConstraints}, - peer::{ - LocalStreamUpdateCriteria, MediaConnections, SimpleTracksRequest, - }, - }, + media::{MediaManager, RecvConstraints}, + peer::{LocalStreamUpdateCriteria, MediaConnections, SimpleTracksRequest}, platform::{RtcPeerConnection, TransceiverDirection}, }; use wasm_bindgen_test::*; diff --git a/jason/tests/media/track.rs b/jason/tests/media/track.rs index 38272fc0c..0df7487d5 100644 --- a/jason/tests/media/track.rs +++ b/jason/tests/media/track.rs @@ -3,9 +3,9 @@ use std::rc::{Rc, Weak}; use futures::channel::oneshot; -use medea_jason::core::{ - media::{track::remote, MediaManager}, - DeviceVideoTrackConstraints, MediaStreamSettings, +use medea_jason::media::{ + track::remote, DeviceVideoTrackConstraints, MediaManager, + MediaStreamSettings, }; use wasm_bindgen::closure::Closure; use wasm_bindgen_test::*; @@ -70,7 +70,7 @@ async fn on_track_disabled_works() { .into(), ); - let track: remote::Track = track.into(); + let track = remote::Track::from(track); track.set_enabled(false); timeout(100, test_rx).await.unwrap().unwrap(); diff --git a/jason/tests/peer/media/mod.rs b/jason/tests/peer/media/mod.rs index 02f6e118a..1311f2495 100644 --- a/jason/tests/peer/media/mod.rs +++ b/jason/tests/peer/media/mod.rs @@ -7,15 +7,13 @@ use std::{convert::TryFrom, mem, rc::Rc}; use futures::channel::mpsc; use medea_client_api_proto::{TrackId, TrackPatchEvent}; use medea_jason::{ - core::{ - media::{LocalTracksConstraints, MediaManager, RecvConstraints}, - peer::{ - media_exchange_state, LocalStreamUpdateCriteria, MediaConnections, - MediaStateControllable, SimpleTracksRequest, - }, - utils::Updatable as _, + media::{LocalTracksConstraints, MediaManager, RecvConstraints}, + peer::{ + media_exchange_state, LocalStreamUpdateCriteria, MediaConnections, + MediaStateControllable, SimpleTracksRequest, }, platform::RtcPeerConnection, + utils::Updatable as _, }; use wasm_bindgen_test::*; @@ -157,7 +155,7 @@ async fn new_media_connections_with_disabled_video_tracks() { /// This tests checks that [`TrackPatch`] works as expected. mod sender_patch { use medea_client_api_proto::{AudioSettings, MediaType}; - use medea_jason::core::{ + use medea_jason::{ peer::{sender, MediaExchangeState}, utils::{AsProtoState, SynchronizableState}, }; @@ -289,7 +287,7 @@ mod sender_patch { mod receiver_patch { use medea_client_api_proto::{AudioSettings, MediaType, MemberId}; - use medea_jason::core::{ + use medea_jason::{ media::RecvConstraints, peer::{receiver, MediaExchangeState, PeerEvent}, utils::{AsProtoState, SynchronizableState}, diff --git a/jason/tests/peer/media/transitable_state/controller.rs b/jason/tests/peer/media/transitable_state/controller.rs index 77f330647..d9b72cca1 100644 --- a/jason/tests/peer/media/transitable_state/controller.rs +++ b/jason/tests/peer/media/transitable_state/controller.rs @@ -1,9 +1,7 @@ //! Tests for the [`TransitableStateController`]. use futures::StreamExt; -use medea_jason::core::peer::{ - media_exchange_state, MediaExchangeStateController, -}; +use medea_jason::peer::{media_exchange_state, MediaExchangeStateController}; use wasm_bindgen_test::wasm_bindgen_test; use crate::timeout; diff --git a/jason/tests/peer/mod.rs b/jason/tests/peer/mod.rs index e9f089942..b660f95d5 100644 --- a/jason/tests/peer/mod.rs +++ b/jason/tests/peer/mod.rs @@ -20,18 +20,14 @@ use medea_client_api_proto::{ VideoSettings, }; use medea_jason::{ - core::{ - media::{ - LocalTracksConstraints, MediaKind, MediaManager, RecvConstraints, - }, - peer::{ - self, media_exchange_state, MediaStateControllable, PeerEvent, - TrackDirection, - }, - utils::Updatable, - Connections, + connection::Connections, + media::{LocalTracksConstraints, MediaKind, MediaManager, RecvConstraints}, + peer::{ + self, media_exchange_state, MediaStateControllable, PeerEvent, + TrackDirection, }, platform::RtcStats, + utils::Updatable, }; use wasm_bindgen_test::*; diff --git a/jason/tests/room/connection.rs b/jason/tests/room/connection.rs index 227a579e3..f00b41614 100644 --- a/jason/tests/room/connection.rs +++ b/jason/tests/room/connection.rs @@ -5,7 +5,7 @@ use futures::{ StreamExt, }; use medea_client_api_proto::PeerId; -use medea_jason::{api, core::Connections, platform}; +use medea_jason::{api, connection::Connections, platform}; use wasm_bindgen::{closure::Closure, JsValue}; use wasm_bindgen_test::*; diff --git a/jason/tests/room/mod.rs b/jason/tests/room/mod.rs index d9d713ca8..002bb9fff 100644 --- a/jason/tests/room/mod.rs +++ b/jason/tests/room/mod.rs @@ -12,11 +12,9 @@ use medea_client_api_proto::{ }; use medea_jason::{ api, - core::{ - self, - rpc::{CloseMsg, WebSocketRpcClient}, - }, + jason::Jason, platform::{MockRpcTransport, RpcTransport, TransportState}, + rpc::{CloseMsg, WebSocketRpcClient}, }; use medea_reactive::ObservableCell; use wasm_bindgen::closure::Closure; @@ -55,7 +53,7 @@ async fn only_one_strong_rpc_rc_exists() { Ok(transport as Rc) }) }))); - let jason = api::Jason::from(core::Jason::with_rpc_client(ws.clone())); + let jason = api::Jason::from(Jason::with_rpc_client(ws.clone())); let room = jason.init_room(); room.on_failed_local_media(Closure::once_into_js(|| {}).into()) @@ -105,7 +103,7 @@ async fn rpc_dropped_on_jason_dispose() { Ok(transport as Rc) }) }))); - let jason = api::Jason::from(core::Jason::with_rpc_client(ws)); + let jason = api::Jason::from(Jason::with_rpc_client(ws)); let room = jason.init_room(); room.on_failed_local_media(Closure::once_into_js(|| {}).into()) @@ -160,7 +158,7 @@ async fn room_dispose_works() { }) }) })); - let jason = api::Jason::from(core::Jason::with_rpc_client(ws)); + let jason = api::Jason::from(Jason::with_rpc_client(ws)); let room = jason.init_room(); room.on_failed_local_media(Closure::once_into_js(|| {}).into()) @@ -293,7 +291,7 @@ async fn room_closes_on_rpc_transport_close() { }) } }))); - let jason = api::Jason::from(core::Jason::with_rpc_client(ws)); + let jason = api::Jason::from(Jason::with_rpc_client(ws)); let room = jason.init_room(); room.on_failed_local_media(Closure::once_into_js(|| {}).into()) diff --git a/jason/tests/room/room.rs b/jason/tests/room/room.rs index f671eb0b2..4e1c1db78 100644 --- a/jason/tests/room/room.rs +++ b/jason/tests/room/room.rs @@ -17,11 +17,8 @@ use medea_client_api_proto::{ VideoSettings, }; use medea_jason::{ - api, - core::{ - media::MediaKind, peer::PeerConnection, rpc::MockRpcSession, - utils::Updatable, Room, - }, + api, media::MediaKind, peer::PeerConnection, room::Room, + rpc::MockRpcSession, utils::Updatable, }; use wasm_bindgen_futures::{spawn_local, JsFuture}; use wasm_bindgen_test::*; @@ -327,7 +324,7 @@ mod disable_send_tracks { AudioSettings, Direction, MediaType, MemberId, TrackPatchCommand, VideoSettings, }; - use medea_jason::core::{ + use medea_jason::{ media::MediaKind, peer::{media_exchange_state, TrackDirection}, }; @@ -952,7 +949,7 @@ mod disable_send_tracks { /// Tests for `RoomHandle.on_close` JS side callback. mod on_close_callback { use medea_client_api_proto::CloseReason as CloseByServerReason; - use medea_jason::core::rpc::{ClientDisconnect, CloseReason}; + use medea_jason::rpc::{ClientDisconnect, CloseReason}; use wasm_bindgen::{prelude::*, JsValue}; use wasm_bindgen_test::*; @@ -1062,7 +1059,7 @@ mod rpc_close_reason_on_room_drop { //! is provided to [`RpcClient`]. use futures::channel::oneshot; - use medea_jason::core::rpc::{ClientDisconnect, CloseReason}; + use medea_jason::rpc::{ClientDisconnect, CloseReason}; use super::*; @@ -1150,9 +1147,7 @@ mod patches_generation { AudioSettings, Direction, MediaType, Track, TrackId, TrackPatchCommand, VideoSettings, }; - use medea_jason::core::peer::{ - media_exchange_state, mute_state, MediaState, - }; + use medea_jason::peer::{media_exchange_state, mute_state, MediaState}; use wasm_bindgen_futures::spawn_local; use crate::{is_firefox, timeout}; @@ -2565,7 +2560,7 @@ mod state_synchronization { PeerId, TrackId, }; use medea_jason::{ - core::{media::MediaManager, rpc::MockRpcSession, Room}, + media::MediaManager, room::Room, rpc::MockRpcSession, utils::AsProtoState, }; use wasm_bindgen_test::*; diff --git a/jason/tests/rpc/backoff_delayer.rs b/jason/tests/rpc/backoff_delayer.rs index a9cff5f04..f37d9d81d 100644 --- a/jason/tests/rpc/backoff_delayer.rs +++ b/jason/tests/rpc/backoff_delayer.rs @@ -2,7 +2,7 @@ use std::time::Duration; -use medea_jason::core::rpc::BackoffDelayer; +use medea_jason::rpc::BackoffDelayer; use wasm_bindgen_test::*; use crate::timeout; diff --git a/jason/tests/rpc/heartbeat.rs b/jason/tests/rpc/heartbeat.rs index 96a55874e..9e2519c02 100644 --- a/jason/tests/rpc/heartbeat.rs +++ b/jason/tests/rpc/heartbeat.rs @@ -8,8 +8,8 @@ use futures::{ }; use medea_client_api_proto::{ClientMsg, ServerMsg}; use medea_jason::{ - core::rpc::{Heartbeat, IdleTimeout, PingInterval}, platform::{MockRpcTransport, RpcTransport}, + rpc::{Heartbeat, IdleTimeout, PingInterval}, }; use wasm_bindgen_test::*; diff --git a/jason/tests/rpc/mod.rs b/jason/tests/rpc/mod.rs index 2cfe3926d..f29262c18 100644 --- a/jason/tests/rpc/mod.rs +++ b/jason/tests/rpc/mod.rs @@ -18,8 +18,8 @@ use medea_client_api_proto::{ ClientMsg, CloseReason, Command, Event, PeerId, RpcSettings, ServerMsg, }; use medea_jason::{ - core::rpc::{ClientDisconnect, CloseMsg, RpcEvent, WebSocketRpcClient}, platform::{MockRpcTransport, RpcTransport, TransportState}, + rpc::{ClientDisconnect, CloseMsg, RpcEvent, WebSocketRpcClient}, }; use wasm_bindgen_futures::spawn_local; use wasm_bindgen_test::*; @@ -260,9 +260,7 @@ mod on_close { assert_eq!( ws.on_normal_close().await.unwrap(), - medea_jason::core::rpc::CloseReason::ByServer( - CloseReason::Finished - ) + medea_jason::rpc::CloseReason::ByServer(CloseReason::Finished) ); } diff --git a/jason/tests/rpc/rpc_session.rs b/jason/tests/rpc/rpc_session.rs index f7b13900e..c8c03dcfd 100644 --- a/jason/tests/rpc/rpc_session.rs +++ b/jason/tests/rpc/rpc_session.rs @@ -12,13 +12,13 @@ use medea_client_api_proto::{ ClientMsg, CloseReason, Command, Event, ServerMsg, }; use medea_jason::{ - core::rpc::{ - CloseMsg, ConnectionInfo, RpcSession, SessionError, WebSocketRpcClient, - WebSocketRpcSession, - }, platform::{ MockRpcTransport, RpcTransport, TransportState, WebSocketRpcTransport, }, + rpc::{ + CloseMsg, ConnectionInfo, RpcSession, SessionError, WebSocketRpcClient, + WebSocketRpcSession, + }, }; use wasm_bindgen_test::*; diff --git a/jason/tests/web.rs b/jason/tests/web.rs index bb0d0f63f..cb038d2df 100644 --- a/jason/tests/web.rs +++ b/jason/tests/web.rs @@ -88,15 +88,12 @@ use medea_client_api_proto::{ }; use medea_jason::{ api, - core::{ - media::{ - track::remote, LocalTracksConstraints, MediaKind, MediaManager, - }, - peer::media_exchange_state, - rpc::ApiUrl, - AudioTrackConstraints, DeviceVideoTrackConstraints, - MediaStreamSettings, + media::{ + track::remote, AudioTrackConstraints, DeviceVideoTrackConstraints, + LocalTracksConstraints, MediaKind, MediaManager, MediaStreamSettings, }, + peer::media_exchange_state, + rpc::ApiUrl, }; use url::Url; use wasm_bindgen::prelude::*; From aab9eee8d661540b7d522ccebda181370c9b32b3 Mon Sep 17 00:00:00 2001 From: alexlapa Date: Mon, 1 Mar 2021 20:22:05 +0200 Subject: [PATCH 05/19] reread --- Cargo.lock | 48 +++++++++++----------- jason/src/api/mod.rs | 2 +- jason/src/api/wasm/jason.rs | 2 +- jason/src/api/wasm/reconnect_handle.rs | 8 +++- jason/src/api/wasm/room_close_reason.rs | 3 +- jason/src/api/wasm/room_handle.rs | 3 ++ jason/src/connection.rs | 21 ++++------ jason/src/jason.rs | 6 +-- jason/src/lib.rs | 2 +- jason/src/peer/component/watchers.rs | 4 +- jason/src/peer/media/receiver/component.rs | 3 +- jason/src/peer/media/receiver/mod.rs | 7 ++-- jason/src/peer/media/sender/component.rs | 14 +++---- jason/src/platform/wasm/error.rs | 8 ---- jason/src/platform/wasm/peer_connection.rs | 1 - jason/src/platform/wasm/transport.rs | 2 +- jason/src/room.rs | 26 +++++------- jason/tests/media/manager.rs | 1 - 18 files changed, 73 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 90b0d5bc3..6ae27aaed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -348,9 +348,9 @@ dependencies = [ [[package]] name = "adler" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bedc89c5c7b5550ffb9372eb5c5ffc7f9f705cc3f4a128bd4669b9745f555093" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" @@ -1672,9 +1672,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "js-sys" -version = "0.3.47" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65" +checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78" dependencies = [ "wasm-bindgen", ] @@ -2841,9 +2841,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43535db9747a4ba938c0ce0a98cc631a46ebf943c9e1d604e091df6007620bf6" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" dependencies = [ "itoa", "ryu", @@ -3831,9 +3831,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be" +checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" dependencies = [ "cfg-if 1.0.0", "serde 1.0.123", @@ -3843,9 +3843,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7" +checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8" dependencies = [ "bumpalo", "lazy_static", @@ -3858,9 +3858,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de431a2910c86679c34283a33f66f4e4abd7e0aec27b6669060148872aadf94" +checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3870,9 +3870,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c" +checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b" dependencies = [ "quote 1.0.9", "wasm-bindgen-macro-support", @@ -3880,9 +3880,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385" +checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", @@ -3893,15 +3893,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.70" +version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64" +checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1" [[package]] name = "wasm-bindgen-test" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d4da138503a4cf86801b94d95781ee3619faa8feca830569cc6b54997b8b5c" +checksum = "2ea9e4f0050d5498a160e6b9d278a9699598e445b51dacd05598da55114c801a" dependencies = [ "console_error_panic_hook", "js-sys", @@ -3913,9 +3913,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3199c33f06500c731d5544664c24d0c2b742b98debc6b1c6f0c6d6e8fb7c19b" +checksum = "43f40402f495d92df6cdd0d329e7cc2580c8f99bcd74faff0e468923a764b7d4" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", @@ -3934,9 +3934,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.47" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3" +checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/jason/src/api/mod.rs b/jason/src/api/mod.rs index 9643bbcd1..007f9df08 100644 --- a/jason/src/api/mod.rs +++ b/jason/src/api/mod.rs @@ -1,4 +1,4 @@ -//! External Jason API. +//! External `Jason` API. mod wasm; diff --git a/jason/src/api/wasm/jason.rs b/jason/src/api/wasm/jason.rs index d5548009e..4d75695a4 100644 --- a/jason/src/api/wasm/jason.rs +++ b/jason/src/api/wasm/jason.rs @@ -7,7 +7,7 @@ use crate::{ platform::{init_logger, set_panic_hook}, }; -/// General library interface. +/// General JS side library interface. /// /// Responsible for managing shared transports, local media /// and room initialization. diff --git a/jason/src/api/wasm/reconnect_handle.rs b/jason/src/api/wasm/reconnect_handle.rs index 8f85a2762..9af5ca4ca 100644 --- a/jason/src/api/wasm/reconnect_handle.rs +++ b/jason/src/api/wasm/reconnect_handle.rs @@ -8,7 +8,13 @@ use crate::{api::JasonError, rpc}; /// Handle that JS side can reconnect to the Medea media server on /// a connection loss with. /// -/// This handle will be provided into `Room.on_connection_loss` callback. +/// This handle will be provided into [`RoomHandle.on_connection_loss`] +/// callback. +/// +/// Like all handlers it contains weak reference to object that is managed by +/// Rust, so its methods will fail if weak reference could not be upgraded. +/// +/// [`RoomHandle.on_connection_loss`]: crate::api::RoomHandle.on_connection_loss #[wasm_bindgen] #[derive(Clone, From)] pub struct ReconnectHandle(rpc::ReconnectHandle); diff --git a/jason/src/api/wasm/room_close_reason.rs b/jason/src/api/wasm/room_close_reason.rs index 0c632454e..561a6ea77 100644 --- a/jason/src/api/wasm/room_close_reason.rs +++ b/jason/src/api/wasm/room_close_reason.rs @@ -5,9 +5,10 @@ use crate::room; /// Reason of why [`Room`] has been closed. /// -/// This struct is passed into `on_close_by_server` JS side callback. +/// This struct is passed into [`RoomHandle::on_close`] JS side callback. /// /// [`Room`]: room::Room +/// [`RoomHandle::on_close`]: crate::api::RoomHandle::on_close #[wasm_bindgen] #[derive(From)] pub struct RoomCloseReason(room::RoomCloseReason); diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index 0ded688cb..6bd555d8c 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -13,6 +13,9 @@ use crate::{ /// JS side handle to [`Room`] where all the media happens. /// +/// Like all handlers it contains weak reference to object that is managed by +/// Rust, so its methods will fail if weak reference could not be upgraded. +/// /// [`Room`]: room::Room #[wasm_bindgen] #[derive(From, Into)] diff --git a/jason/src/connection.rs b/jason/src/connection.rs index 2dec2bd80..23200ea31 100644 --- a/jason/src/connection.rs +++ b/jason/src/connection.rs @@ -27,8 +27,7 @@ pub struct Connections { /// Remote [`MemberId`] to [`Connection`] with that `Member`. connections: RefCell>, - /// Callback from JS side which will be invoked on remote `Member` media - /// stream arrival. + /// Callback that will be invoked on remote `Member` media arrival. on_new_connection: platform::Callback, } @@ -91,15 +90,14 @@ impl Connections { } } -/// Connection with a specific remote `Member`, that is used on JS side. +/// External handler to [`Connection`] with remote `Member`. /// /// Actually, represents a [`Weak`]-based handle to `InnerConnection`. pub struct ConnectionHandle(Weak); /// Actual data of a connection with a specific remote `Member`. /// -/// Shared between JS side ([`ConnectionHandle`]) and Rust side -/// ([`Connection`]). +/// Shared between external [`ConnectionHandle`] and Rust side [`Connection`]. struct InnerConnection { /// Remote `Member` ID. remote_id: MemberId, @@ -107,15 +105,14 @@ struct InnerConnection { /// Current [`ConnectionQualityScore`] of this [`Connection`]. quality_score: Cell>, - /// JS callback, that will be invoked when [`remote::Track`] is - /// received. + /// Callback, that will be invoked when [`remote::Track`] is received. on_remote_track_added: platform::Callback, - /// JS callback, that will be invoked when [`ConnectionQualityScore`] will - /// be updated. + /// Callback, that will be invoked when [`ConnectionQualityScore`] is + /// updated. on_quality_score_update: platform::Callback, - /// JS callback, that will be invoked when this connection is closed. + /// Callback, that will be invoked when current [`Connection`] is closed. on_close: platform::Callback<()>, } @@ -171,13 +168,13 @@ impl Connection { })) } - /// Invokes `on_remote_track_added` JS callback with the provided + /// Invokes `on_remote_track_added` callback with the provided /// [`remote::Track`]. pub fn add_remote_track(&self, track: remote::Track) { self.0.on_remote_track_added.call1(track); } - /// Creates new [`ConnectionHandle`] for using [`Connection`] on JS side. + /// Creates new external handle to current [`Connection`]. #[inline] pub fn new_handle(&self) -> ConnectionHandle { ConnectionHandle(Rc::downgrade(&self.0)) diff --git a/jason/src/jason.rs b/jason/src/jason.rs index 88f3edf7d..f9b26e7c6 100644 --- a/jason/src/jason.rs +++ b/jason/src/jason.rs @@ -1,4 +1,4 @@ -//! Platform agnostic functionality. +//! General library interface. use futures::FutureExt as _; use std::{cell::RefCell, rc::Rc}; @@ -15,8 +15,8 @@ use crate::{ /// General library interface. /// -/// Responsible for managing shared transports, local media -/// and room initialization. +/// Responsible for managing shared transports, local media and room +/// initialization. pub struct Jason(Rc>); struct Inner { diff --git a/jason/src/lib.rs b/jason/src/lib.rs index 82db89260..a27341251 100644 --- a/jason/src/lib.rs +++ b/jason/src/lib.rs @@ -1,4 +1,4 @@ -//! Client library for Medea media server. +//! Client library for [Medea] media server. //! //! [Medea]: https://github.com/instrumentisto/medea diff --git a/jason/src/peer/component/watchers.rs b/jason/src/peer/component/watchers.rs index f21ab9501..16f72b225 100644 --- a/jason/src/peer/component/watchers.rs +++ b/jason/src/peer/component/watchers.rs @@ -169,11 +169,11 @@ impl Component { /// Watcher for the [`State::local_sdp`] updates. /// /// Sets [`PeerConnection`]'s SDP offer to the provided one and sends - /// a [`PeerEvent::NewSdpOffer`] if [`NegotiationRole`] is an + /// a [`PeerEvent::NewSdpOffer`] if [`NegotiationRole`] is /// [`NegotiationRole::Offerer`]. /// /// Sets [`PeerConnection`]'s SDP answer to the provided one and sends - /// a [`PeerEvent::NewSdpAnswer`] if [`NegotiationRole`] is an + /// a [`PeerEvent::NewSdpAnswer`] if [`NegotiationRole`] is /// [`NegotiationRole::Answerer`]. /// /// Rollbacks [`PeerConnection`] to a stable state if [`PeerConnection`] is diff --git a/jason/src/peer/media/receiver/component.rs b/jason/src/peer/media/receiver/component.rs index aba9132f6..b064e017f 100644 --- a/jason/src/peer/media/receiver/component.rs +++ b/jason/src/peer/media/receiver/component.rs @@ -250,10 +250,9 @@ impl Component { /// Watcher for the [`State::enabled_general`] updates. /// /// Updates [`Receiver`]'s general media exchange state. Adds or removes - /// [`TransceiverDirection::RECV`] from the [`Transceiver`] of the + /// [`TransceiverDirection::RECV`] from the [`platform::Transceiver`] of the /// [`Receiver`]. /// - /// [`Transceiver`]: platform::Transceiver /// [`TransceiverDirection::RECV`]: platform::TransceiverDirection::RECV #[watch(self.enabled_general.subscribe())] async fn general_media_exchange_state_changed( diff --git a/jason/src/peer/media/receiver/mod.rs b/jason/src/peer/media/receiver/mod.rs index bf5148fb7..7a34268fd 100644 --- a/jason/src/peer/media/receiver/mod.rs +++ b/jason/src/peer/media/receiver/mod.rs @@ -43,10 +43,10 @@ pub struct Receiver { impl Receiver { /// Creates new [`platform::Transceiver`] if provided `mid` is `None`, - /// otherwise creates [`Receiver`] without [`Transceiver`]. It will be - /// injected when [`remote::Track`] arrives. + /// otherwise creates [`Receiver`] without [`platform::Transceiver`]. It + /// will be injected when [`remote::Track`] arrives. /// - /// Created [`Transceiver`] direction is set to + /// Created [`platform::Transceiver`] direction is set to /// [`TransceiverDirection::INACTIVE`][1] if `enabled_individual` is /// `false`. /// @@ -54,7 +54,6 @@ impl Receiver { /// [`Receiver`] must be created before the actual [`remote::Track`] data /// arrives. /// - /// [`Transceiver`]: platform::Transceiver /// [1]: platform::TransceiverDirection::INACTIVE pub fn new( state: &State, diff --git a/jason/src/peer/media/sender/component.rs b/jason/src/peer/media/sender/component.rs index f734e97c0..33635d877 100644 --- a/jason/src/peer/media/sender/component.rs +++ b/jason/src/peer/media/sender/component.rs @@ -435,11 +435,10 @@ impl Component { /// Watcher for the [`State::enabled_general`] update. /// /// Updates [`Sender`]'s general media exchange state. Adds or removes - /// [`TransceiverDirection::SEND`] from the [`Transceiver`] of this - /// [`Sender`]. + /// [`TransceiverDirection::SEND`] from the [`platform::Transceiver`] of + /// this [`Sender`]. /// /// [`TransceiverDirection::SEND`]: platform::TransceiverDirection::SEND - /// [`Transceiver`]: platform::Transceiver #[watch(self.enabled_general.subscribe())] async fn enabled_general_state_changed( sender: Rc, @@ -473,13 +472,11 @@ impl Component { /// /// Updates [`Sender::enabled_individual`] to the `new_state`. /// - /// Removes `MediaTrack` from [`Transceiver`] if `new_state` is + /// Removes `MediaTrack` from [`platform::Transceiver`] if `new_state` is /// [`media_exchange_state::Stable::Disabled`]. /// /// Marks [`State::local_track_state`] as [`LocalTrackState::NeedUpdate`] if /// `new_state` is [`media_exchange_state::Stable::Enabled`]. - /// - /// [`Transceiver`]: platform::Transceiver #[watch(self.enabled_individual.subscribe_stable())] async fn enabled_individual_stable_state_changed( sender: Rc, @@ -504,9 +501,8 @@ impl Component { /// /// Updates [`Sender`]'s mute state. /// - /// Updates [`Sender`]'s [`Transceiver`] `MediaTrack.enabled` property. - /// - /// [`Transceiver`]: platform::Transceiver + /// Updates [`Sender`]'s [`platform::Transceiver`] `MediaTrack.enabled` + /// property. #[watch(self.mute_state.subscribe_stable())] async fn mute_state_stable_watcher( sender: Rc, diff --git a/jason/src/platform/wasm/error.rs b/jason/src/platform/wasm/error.rs index a6b62b4f5..c2834858d 100644 --- a/jason/src/platform/wasm/error.rs +++ b/jason/src/platform/wasm/error.rs @@ -44,11 +44,3 @@ impl From for platform::Error { } } } - -impl From for js_sys::Error { - fn from(err: platform::Error) -> Self { - let error = Self::new(&err.message); - error.set_name(&err.name); - error - } -} diff --git a/jason/src/platform/wasm/peer_connection.rs b/jason/src/platform/wasm/peer_connection.rs index f48efcc04..4a6d20fab 100644 --- a/jason/src/platform/wasm/peer_connection.rs +++ b/jason/src/platform/wasm/peer_connection.rs @@ -358,7 +358,6 @@ impl RtcPeerConnection { .map_err(Into::into) .map_err(RTCPeerConnectionError::AddIceCandidateFailed) .map_err(tracerr::wrap!())?; - Ok(()) } diff --git a/jason/src/platform/wasm/transport.rs b/jason/src/platform/wasm/transport.rs index 70e761be9..807b9b2dd 100644 --- a/jason/src/platform/wasm/transport.rs +++ b/jason/src/platform/wasm/transport.rs @@ -133,7 +133,7 @@ impl WebSocketRpcTransport { /// fired before [WebSocket.onopen][2] callback. /// /// [1]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onclose - /// [2]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onopens + /// [2]: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onopen pub async fn new(url: ApiUrl) -> Result { let socket = Rc::new(RefCell::new(InnerSocket::new(url.as_ref())?)); { diff --git a/jason/src/room.rs b/jason/src/room.rs index b7bd7ed10..0eb81ac94 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -47,7 +47,7 @@ use crate::{ /// Reason of why [`Room`] has been closed. /// -/// This struct is passed into `on_close_by_server` JS side callback. +/// This struct is passed into [`RoomHandle::on_close`] callback. pub struct RoomCloseReason { /// Indicator if [`Room`] is closed by server. /// @@ -64,8 +64,7 @@ pub struct RoomCloseReason { } impl RoomCloseReason { - /// Creates new [`RoomCloseReason`] with provided [`CloseReason`] - /// converted into [`String`]. + /// Creates new [`RoomCloseReason`] with provided [`CloseReason`]. /// /// `is_err` may be `true` only on closing by client. /// @@ -179,11 +178,7 @@ impl From for RoomError { } } -/// JS side handle to `Room` where all the media happens. -/// -/// Actually, represents a [`Weak`]-based handle to `InnerRoom`. -/// -/// For using [`RoomHandle`] on Rust side, consider the `Room`. +/// External handle to [`Room`]. #[derive(Clone)] pub struct RoomHandle(Weak); @@ -251,7 +246,7 @@ impl RoomHandle { ); // Perform `getUserMedia()`/`getDisplayMedia()` right away, so we can - // fail fast without touching senders' states and starting all required + // fail fast without touching senders states and starting all required // messaging. // Hold tracks through all process, to ensure that they will be reused // without additional requests. @@ -587,8 +582,6 @@ impl WeakRoom { /// [`Room`] where all the media happens (manages concrete [`PeerConnection`]s, /// handles media server events, etc). -/// -/// For using [`Room`] on JS side, consider the [`RoomHandle`]. pub struct Room(Rc); impl Room { @@ -680,8 +673,8 @@ impl Room { self.0.set_close_reason(reason); } - /// Creates new [`RoomHandle`] used by JS side. You can create them as many - /// as you need. + /// Creates new external handle to [`Room`]. You can create them as many as + /// you need. #[inline] pub fn new_handle(&self) -> RoomHandle { RoomHandle(Rc::downgrade(&self.0)) @@ -712,7 +705,7 @@ impl Room { /// Actual data of a [`Room`]. /// -/// Shared between JS side ([`RoomHandle`]) and Rust side ([`Room`]). +/// Shared between external [`RoomHandle`] and Rust side ([`Room`]). struct InnerRoom { /// Client to talk with media server via Client API RPC. rpc: Rc, @@ -752,10 +745,11 @@ struct InnerRoom { /// Reason of [`Room`] closing. /// - /// This [`CloseReason`] will be provided into `on_close` JS callback. + /// This [`CloseReason`] will be provided into [`RoomHandle::on_close`] + /// callback. /// /// Note that `None` will be considered as error and `is_err` will be - /// `true` in [`CloseReason`] provided to JS callback. + /// `true` in [`CloseReason`] provided to callback. close_reason: RefCell, } diff --git a/jason/tests/media/manager.rs b/jason/tests/media/manager.rs index d13bfe92b..c2c8817a5 100644 --- a/jason/tests/media/manager.rs +++ b/jason/tests/media/manager.rs @@ -335,7 +335,6 @@ async fn new_tracks_should_be_live() { .as_ref() .as_ref(), ); - let ended_track = track.clone(); ended_track.stop(); From bb02351e562b4fa0e1f8ae3a07bfb08d2c06f9fe Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Tue, 2 Mar 2021 17:31:40 +0300 Subject: [PATCH 06/19] Move JasonError to api::wasm --- jason/src/api/wasm/jason_error.rs | 57 ++++++++++++++++--- jason/src/connection.rs | 5 +- jason/src/media/manager.rs | 6 +- jason/src/peer/mod.rs | 5 +- jason/src/platform/mod.rs | 2 +- jason/src/platform/peer_connection.rs | 2 +- jason/src/platform/wasm/peer_connection.rs | 20 +++---- jason/src/platform/wasm/transport.rs | 2 +- jason/src/room.rs | 6 +- jason/src/rpc/reconnect_handle.rs | 6 +- jason/src/rpc/websocket/client.rs | 2 +- jason/src/utils/component.rs | 3 +- jason/src/utils/errors.rs | 64 +--------------------- jason/src/utils/mod.rs | 10 ++-- 14 files changed, 81 insertions(+), 109 deletions(-) diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs index c423d6e05..16c3e6630 100644 --- a/jason/src/api/wasm/jason_error.rs +++ b/jason/src/api/wasm/jason_error.rs @@ -1,35 +1,76 @@ -use derive_more::From; +use std::{ + fmt::{Debug, Display}, +}; +use derive_more::From; +use derive_more::{Display}; +use tracerr::{Trace, Traced}; +use crate::utils::JsCaused; use wasm_bindgen::prelude::*; -use crate::utils; +use crate::platform; /// Representation of app error exported to JS side. /// /// Contains JS side error if it the cause and trace information. #[wasm_bindgen] -#[derive(From)] -pub struct JasonError(utils::JasonError); +#[derive(From, Clone, Debug, Display)] +#[display(fmt = "{}: {}\n{}", name, message, trace)] +pub struct JasonError { + name: &'static str, + message: String, + trace: Trace, + source: Option, +} #[wasm_bindgen] impl JasonError { /// Returns name of error. pub fn name(&self) -> String { - self.0.name() + self.name.to_string() } /// Returns message of errors. pub fn message(&self) -> String { - self.0.message() + self.message.clone() } /// Returns trace information of error. pub fn trace(&self) -> String { - self.0.trace() + self.trace.to_string() } /// Returns JS side error if it the cause. pub fn source(&self) -> Option { - self.0.source().and_then(|a| a.sys_cause) + self.source.clone().and_then(|e| e.sys_cause) + } + + /// Prints error information to default logger with `ERROR` level. + pub fn print(&self) { + log::error!("{}", self); + } + +} + +impl From<(E, Trace)> for JasonError + where + E::Error: Into, +{ + fn from((err, trace): (E, Trace)) -> Self { + Self { + name: err.name(), + message: err.to_string(), + trace, + source: err.js_cause().map(Into::into), + } + } +} + +impl From> for JasonError + where + E::Error: Into, +{ + fn from(traced: Traced) -> Self { + Self::from(traced.into_parts()) } } diff --git a/jason/src/connection.rs b/jason/src/connection.rs index 23200ea31..2116d63b4 100644 --- a/jason/src/connection.rs +++ b/jason/src/connection.rs @@ -1,8 +1,5 @@ //! Connection with specific remote `Member`. -// TODO: Remove when moving JasonError to api::wasm. -#![allow(clippy::missing_errors_doc)] - use std::{ cell::{Cell, RefCell}, collections::{HashMap, HashSet}, @@ -15,7 +12,7 @@ use crate::{ api, media::track::remote, platform, - utils::{HandlerDetachedError, JasonError}, + api::JasonError, }; /// Service which manages [`Connection`]s with the remote `Member`s. diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 2aeedc30d..1b90d3414 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -1,8 +1,5 @@ //! Acquiring and storing [`local::Track`]s. -// TODO: Remove when moving JasonError to api::wasm. -#![allow(clippy::missing_errors_doc)] - use std::{ cell::RefCell, collections::HashMap, @@ -19,7 +16,8 @@ use crate::{ MultiSourceTracksConstraints, }, platform, - utils::{HandlerDetachedError, JasonError, JsCaused}, + api::JasonError, + utils::{JsCaused}, }; use super::track::local; diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index 7e7006931..9b8a3f6d8 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -33,7 +33,8 @@ use crate::{ MediaStreamSettings, RecvConstraints, }, platform, - utils::{JasonError, JsCaused}, + utils::{JsCaused}, + api::JasonError, }; #[doc(inline)] @@ -69,7 +70,7 @@ pub enum PeerError { /// /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection #[display(fmt = "{}", _0)] - RtcPeerConnection(#[js(cause)] platform::RTCPeerConnectionError), + RtcPeerConnection(#[js(cause)] platform::RtcPeerConnectionError), /// Errors that may occur when validating [`TracksRequest`] or parsing /// [`local::Track`]s. diff --git a/jason/src/platform/mod.rs b/jason/src/platform/mod.rs index 1cd59f20a..27e46c1da 100644 --- a/jason/src/platform/mod.rs +++ b/jason/src/platform/mod.rs @@ -2,7 +2,7 @@ #[doc(inline)] pub use self::{ - peer_connection::{IceCandidate, RTCPeerConnectionError, SdpType}, + peer_connection::{IceCandidate, RtcPeerConnectionError, SdpType}, rtc_stats::RtcStatsError, transport::{ RpcTransport, TransportError, TransportState, WebSocketRpcTransport, diff --git a/jason/src/platform/peer_connection.rs b/jason/src/platform/peer_connection.rs index 46ca510e2..1a1fe90ee 100644 --- a/jason/src/platform/peer_connection.rs +++ b/jason/src/platform/peer_connection.rs @@ -51,7 +51,7 @@ pub struct IceCandidate { /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection #[derive(Clone, Debug, Display, From, JsCaused)] #[js(error = "platform::Error")] -pub enum RTCPeerConnectionError { +pub enum RtcPeerConnectionError { /// Occurs when cannot adds new remote candidate to the /// [RTCPeerConnection][1]'s remote description. /// diff --git a/jason/src/platform/wasm/peer_connection.rs b/jason/src/platform/wasm/peer_connection.rs index 4a6d20fab..0e34fde3b 100644 --- a/jason/src/platform/wasm/peer_connection.rs +++ b/jason/src/platform/wasm/peer_connection.rs @@ -25,7 +25,7 @@ use crate::{ media::{MediaKind, TrackConstraints}, platform::{ self, get_property_by_name, wasm::utils::EventListener, IceCandidate, - MediaStreamTrack, RTCPeerConnectionError, RtcStats, SdpType, + MediaStreamTrack, RtcPeerConnectionError, RtcStats, SdpType, Transceiver, TransceiverDirection, }, }; @@ -41,7 +41,7 @@ impl From<&TrackConstraints> for MediaKind { } } -type Result = std::result::Result>; +type Result = std::result::Result>; /// Representation of [RTCPeerConnection][1]. /// @@ -125,7 +125,7 @@ impl RtcPeerConnection { peer_conf.ice_servers(&RtcIceServers::from(ice_servers)); let peer = SysRtcPeerConnection::new_with_configuration(&peer_conf) .map_err(Into::into) - .map_err(RTCPeerConnectionError::PeerCreationError) + .map_err(RtcPeerConnectionError::PeerCreationError) .map_err(tracerr::wrap!())?; Ok(Self { @@ -152,7 +152,7 @@ impl RtcPeerConnection { pub async fn get_stats(&self) -> Result { let js_stats = JsFuture::from(self.peer.get_stats()).await.map_err(|e| { - tracerr::new!(RTCPeerConnectionError::GetStatsException( + tracerr::new!(RtcPeerConnectionError::GetStatsException( platform::Error::from(e) )) })?; @@ -356,7 +356,7 @@ impl RtcPeerConnection { ) .await .map_err(Into::into) - .map_err(RTCPeerConnectionError::AddIceCandidateFailed) + .map_err(RtcPeerConnectionError::AddIceCandidateFailed) .map_err(tracerr::wrap!())?; Ok(()) } @@ -392,7 +392,7 @@ impl RtcPeerConnection { JsFuture::from(peer.set_local_description(&desc)) .await .map_err(Into::into) - .map_err(RTCPeerConnectionError::SetLocalDescriptionFailed) + .map_err(RtcPeerConnectionError::SetLocalDescriptionFailed) .map_err(tracerr::wrap!())?; Ok(()) @@ -441,7 +441,7 @@ impl RtcPeerConnection { let answer = JsFuture::from(self.peer.create_answer()) .await .map_err(Into::into) - .map_err(RTCPeerConnectionError::CreateAnswerFailed) + .map_err(RtcPeerConnectionError::CreateAnswerFailed) .map_err(tracerr::wrap!())?; let answer = RtcSessionDescription::from(answer).sdp(); @@ -465,7 +465,7 @@ impl RtcPeerConnection { )) .await .map_err(Into::into) - .map_err(RTCPeerConnectionError::SetLocalDescriptionFailed) + .map_err(RtcPeerConnectionError::SetLocalDescriptionFailed) .map_err(tracerr::wrap!())?; Ok(()) @@ -495,7 +495,7 @@ impl RtcPeerConnection { ) .await .map_err(Into::into) - .map_err(RTCPeerConnectionError::CreateOfferFailed) + .map_err(RtcPeerConnectionError::CreateOfferFailed) .map_err(tracerr::wrap!())?; let offer = RtcSessionDescription::from(create_offer).sdp(); @@ -533,7 +533,7 @@ impl RtcPeerConnection { JsFuture::from(self.peer.set_remote_description(&description)) .await .map_err(Into::into) - .map_err(RTCPeerConnectionError::SetRemoteDescriptionFailed) + .map_err(RtcPeerConnectionError::SetRemoteDescriptionFailed) .map_err(tracerr::wrap!())?; Ok(()) diff --git a/jason/src/platform/wasm/transport.rs b/jason/src/platform/wasm/transport.rs index 807b9b2dd..2dffd543f 100644 --- a/jason/src/platform/wasm/transport.rs +++ b/jason/src/platform/wasm/transport.rs @@ -16,8 +16,8 @@ use crate::{ transport::{RpcTransport, TransportError, TransportState}, wasm::utils::EventListener, }, + api::JasonError, rpc::{websocket::ClientDisconnect, ApiUrl, CloseMsg}, - utils::JasonError, }; /// Wrapper for help to get [`ServerMsg`] from Websocket [MessageEvent][1]. diff --git a/jason/src/room.rs b/jason/src/room.rs index 0eb81ac94..255117811 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -1,8 +1,5 @@ //! Medea `Room`. -// TODO: Remove when moving JasonError to api::wasm. -#![allow(clippy::missing_errors_doc)] - use std::{ cell::RefCell, collections::{HashMap, HashSet}, @@ -38,11 +35,12 @@ use crate::{ PeerEvent, PeerEventHandler, TrackDirection, }, platform, + api::JasonError, rpc::{ ClientDisconnect, CloseReason, ConnectionInfo, ConnectionInfoParseError, ReconnectHandle, RpcSession, SessionError, }, - utils::{AsProtoState, HandlerDetachedError, JasonError, JsCaused}, + utils::{AsProtoState, JsCaused, HandlerDetachedError}, }; /// Reason of why [`Room`] has been closed. diff --git a/jason/src/rpc/reconnect_handle.rs b/jason/src/rpc/reconnect_handle.rs index 8a6631840..285aeae02 100644 --- a/jason/src/rpc/reconnect_handle.rs +++ b/jason/src/rpc/reconnect_handle.rs @@ -1,8 +1,5 @@ //! Reconnection for [`RpcSession`]. -// TODO: Remove when moving JasonError to api::wasm. -#![allow(clippy::missing_errors_doc)] - use std::{rc::Weak, time::Duration}; use derive_more::Display; @@ -10,7 +7,8 @@ use derive_more::Display; use crate::{ platform, rpc::{BackoffDelayer, RpcSession}, - utils::{HandlerDetachedError, JasonError, JsCaused}, + api::JasonError, + utils::{JsCaused}, }; /// Error which indicates that [`RpcSession`]'s (which this [`ReconnectHandle`] diff --git a/jason/src/rpc/websocket/client.rs b/jason/src/rpc/websocket/client.rs index 2b455c563..5665fafae 100644 --- a/jason/src/rpc/websocket/client.rs +++ b/jason/src/rpc/websocket/client.rs @@ -21,7 +21,7 @@ use crate::{ ApiUrl, CloseMsg, CloseReason, ClosedStateReason, Heartbeat, IdleTimeout, PingInterval, RpcClientError, }, - utils::JasonError, + api::JasonError, }; /// Reasons of closing WebSocket RPC connection by a client side. diff --git a/jason/src/utils/component.rs b/jason/src/utils/component.rs index 3814dcb9d..33049647d 100644 --- a/jason/src/utils/component.rs +++ b/jason/src/utils/component.rs @@ -9,7 +9,8 @@ use medea_reactive::AllProcessed; use crate::{ media::LocalTracksConstraints, platform, - utils::{JasonError, TaskHandle}, + api::JasonError, + utils::{TaskHandle}, }; /// Abstraction over a state which can be transformed to the states from the diff --git a/jason/src/utils/errors.rs b/jason/src/utils/errors.rs index 1b45f9b65..c1fb99b19 100644 --- a/jason/src/utils/errors.rs +++ b/jason/src/utils/errors.rs @@ -1,12 +1,11 @@ //! Helpers for application errors. use std::{ - fmt::{Debug, Display}, + fmt::{Debug}, rc::Rc, }; use derive_more::{Display, From}; -use tracerr::{Trace, Traced}; use crate::platform; @@ -25,67 +24,6 @@ pub trait JsCaused { fn js_cause(self) -> Option; } -// TODO: Consider moving to api::wasm. -/// Abstract application error. -#[derive(Clone, Debug, Display)] -#[display(fmt = "{}: {}\n{}", name, message, trace)] -pub struct JasonError { - name: &'static str, - message: String, - trace: Trace, - source: Option, -} - -impl JasonError { - /// Returns name of error. - pub fn name(&self) -> String { - String::from(self.name) - } - - /// Returns message of errors. - pub fn message(&self) -> String { - self.message.clone() - } - - /// Returns trace information of error. - pub fn trace(&self) -> String { - self.trace.to_string() - } - - /// Returns JS side error if it the cause. - pub fn source(&self) -> Option { - Clone::clone(&self.source) - } - - /// Prints error information to default logger with `ERROR` level. - pub fn print(&self) { - log::error!("{}", self); - } -} - -impl From<(E, Trace)> for JasonError -where - E::Error: Into, -{ - fn from((err, trace): (E, Trace)) -> Self { - Self { - name: err.name(), - message: err.to_string(), - trace, - source: err.js_cause().map(Into::into), - } - } -} - -impl From> for JasonError -where - E::Error: Into, -{ - fn from(traced: Traced) -> Self { - Self::from(traced.into_parts()) - } -} - /// Occurs if referenced value was dropped. #[derive(Debug, Display, JsCaused)] #[js(error = "platform::Error")] diff --git a/jason/src/utils/mod.rs b/jason/src/utils/mod.rs index a6a666d0f..6b957f074 100644 --- a/jason/src/utils/mod.rs +++ b/jason/src/utils/mod.rs @@ -15,7 +15,7 @@ use medea_reactive::Guarded; #[doc(inline)] pub use self::{ component::{AsProtoState, Component, SynchronizableState, Updatable}, - errors::{HandlerDetachedError, JasonError, JsCaused, JsonParseError}, + errors::{HandlerDetachedError, JsCaused, JsonParseError}, resettable_delay::{resettable_delay_for, ResettableDelayHandle}, }; @@ -28,11 +28,11 @@ pub use self::{ macro_rules! upgrade_or_detached { ($v:expr) => {{ $v.upgrade() - .ok_or_else(|| new_js_error!(HandlerDetachedError)) + .ok_or_else(|| new_js_error!($crate::utils::HandlerDetachedError)) }}; ($v:expr, $err:ty) => {{ $v.upgrade() - .ok_or_else(|| new_js_error!(HandlerDetachedError => $err)) + .ok_or_else(|| new_js_error!($crate::utils::HandlerDetachedError => $err)) }}; } @@ -46,10 +46,10 @@ macro_rules! upgrade_or_detached { /// explicitly which type conversion is required. macro_rules! new_js_error { ($e:expr) => { - $crate::utils::JasonError::from(tracerr::new!($e)).into() + $crate::api::JasonError::from(tracerr::new!($e)).into() }; ($e:expr => $o:ty) => { - <$o>::from($crate::utils::JasonError::from(tracerr::new!($e))) + <$o>::from($crate::api::JasonError::from(tracerr::new!($e))) }; } From 6ec7deeb0bf8078350deff9bf8cf4b95541b0d23 Mon Sep 17 00:00:00 2001 From: alexlapa Date: Tue, 2 Mar 2021 18:05:49 +0200 Subject: [PATCH 07/19] cargo update, upd firefox e2e --- Cargo.lock | 1017 +++++++++++++++++++++++++++++++++++++++++++++++----- Makefile | 3 +- 2 files changed, 939 insertions(+), 81 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ae27aaed..44938c724 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,8 +29,8 @@ dependencies = [ "parking_lot", "pin-project 0.4.27", "smallvec", - "tokio", - "tokio-util", + "tokio 0.2.25", + "tokio-util 0.3.1", "trust-dns-proto", "trust-dns-resolver", ] @@ -47,8 +47,8 @@ dependencies = [ "futures-sink", "log", "pin-project 0.4.27", - "tokio", - "tokio-util", + "tokio 0.2.25", + "tokio-util 0.3.1", ] [[package]] @@ -100,7 +100,7 @@ dependencies = [ "bitflags", "brotli2", "bytes 0.5.6", - "cookie", + "cookie 0.14.4", "copyless", "derive_more", "either", @@ -110,7 +110,7 @@ dependencies = [ "futures-core", "futures-util", "fxhash", - "h2", + "h2 0.2.7", "http", "httparse", "indexmap", @@ -125,8 +125,8 @@ dependencies = [ "regex", "serde 1.0.123", "serde_json", - "serde_urlencoded", - "sha-1", + "serde_urlencoded 0.7.0", + "sha-1 0.9.4", "slab", "time 0.2.25", ] @@ -166,7 +166,7 @@ dependencies = [ "futures-channel", "futures-util", "smallvec", - "tokio", + "tokio 0.2.25", ] [[package]] @@ -182,7 +182,7 @@ dependencies = [ "futures-channel", "futures-util", "log", - "mio", + "mio 0.6.23", "mio-uds", "num_cpus", "slab", @@ -292,7 +292,7 @@ dependencies = [ "regex", "serde 1.0.123", "serde_json", - "serde_urlencoded", + "serde_urlencoded 0.7.0", "socket2", "time 0.2.25", "tinyvec", @@ -505,7 +505,7 @@ dependencies = [ "memchr", "num_cpus", "once_cell", - "pin-project-lite 0.2.4", + "pin-project-lite 0.2.5", "pin-utils", "slab", "wasm-bindgen-futures", @@ -517,7 +517,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22068c0c19514942eefcfd4daf8976ef1aad84e61539f95cd200c35202f80af5" dependencies = [ - "async-stream-impl", + "async-stream-impl 0.2.1", + "futures-core", +] + +[[package]] +name = "async-stream" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3670df70cbc01729f901f94c887814b3c68db038aad1329a418bae178bc5295c" +dependencies = [ + "async-stream-impl 0.3.0", "futures-core", ] @@ -532,6 +542,17 @@ dependencies = [ "syn 1.0.60", ] +[[package]] +name = "async-stream-impl" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3548b8efc9f8e8a5a0a2808c5bd8451a9031b9e5b879a79590304ae928b0a70" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.60", +] + [[package]] name = "async-task" version = "4.0.3" @@ -593,7 +614,7 @@ dependencies = [ "rand 0.7.3", "serde 1.0.123", "serde_json", - "serde_urlencoded", + "serde_urlencoded 0.7.0", ] [[package]] @@ -645,13 +666,34 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.4", +] + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.4", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -688,12 +730,27 @@ dependencies = [ "libc", ] +[[package]] +name = "bstr" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" +dependencies = [ + "memchr", +] + [[package]] name = "bumpalo" version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "byteorder" version = "1.4.2" @@ -768,7 +825,7 @@ dependencies = [ "atty", "bitflags", "strsim 0.8.0", - "textwrap", + "textwrap 0.11.0", "unicode-width", "vec_map", ] @@ -783,8 +840,8 @@ dependencies = [ "bytes 1.0.1", "futures-util", "memchr", - "pin-project-lite 0.2.4", - "tokio", + "pin-project-lite 0.2.5", + "tokio 0.2.25", ] [[package]] @@ -836,9 +893,18 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "cookie" -version = "0.14.3" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" +dependencies = [ + "time 0.1.43", +] + +[[package]] +name = "cookie" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784ad0fbab4f3e9cef09f20e0aea6000ae08d2cb98ac4c0abc53df18803d702f" +checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" dependencies = [ "percent-encoding", "time 0.2.25", @@ -851,6 +917,22 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" +[[package]] +name = "core-foundation" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" + [[package]] name = "cpuid-bool" version = "0.1.2" @@ -929,6 +1011,54 @@ dependencies = [ "syn 1.0.60", ] +[[package]] +name = "cucumber_rust" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cc67008716666beb00d20d63debed61b55c78f1ccdf4efb629ddae3205d0f52" +dependencies = [ + "async-stream 0.3.0", + "async-trait", + "clap", + "cucumber_rust_codegen", + "cute_custom_default", + "futures 0.3.13", + "futures-timer", + "gherkin_rust", + "globwalk", + "inventory", + "pathdiff", + "regex", + "shh", + "termcolor", + "textwrap 0.12.1", + "thiserror", +] + +[[package]] +name = "cucumber_rust_codegen" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebf7a94fedf6f251d5cb208ea536496a191c552509a052976af59792199cbc8" +dependencies = [ + "inflections", + "itertools 0.9.0", + "proc-macro2 1.0.24", + "quote 1.0.9", + "regex", + "syn 1.0.60", +] + +[[package]] +name = "cute_custom_default" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed431abf442833fd62ad7cc527a3833d969155c803f0dcf7f8a68db8adddc4c5" +dependencies = [ + "quote 1.0.9", + "syn 1.0.60", +] + [[package]] name = "darling" version = "0.10.2" @@ -1010,7 +1140,7 @@ dependencies = [ "crossbeam-queue", "num_cpus", "serde 1.0.123", - "tokio", + "tokio 0.2.25", ] [[package]] @@ -1081,13 +1211,22 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.4", ] [[package]] @@ -1190,6 +1329,33 @@ dependencies = [ "synstructure", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fantoccini" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49ba709e57aca51a97b5f6a81e5be479dff7739422f10f7292d3aaaa5d2a7a9" +dependencies = [ + "base64 0.13.0", + "cookie 0.14.4", + "futures-core", + "futures-util", + "http", + "hyper 0.14.4", + "hyper-tls", + "mime", + "serde 1.0.123", + "serde_json", + "tokio 1.2.0", + "url", + "webdriver", +] + [[package]] name = "fastrand" version = "1.4.0" @@ -1232,6 +1398,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -1355,7 +1536,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.4", + "pin-project-lite 0.2.5", "waker-fn", ] @@ -1383,6 +1564,12 @@ version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + [[package]] name = "futures-util" version = "0.3.13" @@ -1397,7 +1584,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.4", + "pin-project-lite 0.2.5", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1419,6 +1606,15 @@ version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.4" @@ -1451,12 +1647,64 @@ dependencies = [ "wasi 0.10.2+wasi-snapshot-preview1", ] +[[package]] +name = "gherkin_rust" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f70e36c2b9e5ec714060599e3a983dc7a9123f32c5c63ee638c1e024f36d5c1" +dependencies = [ + "heck", + "peg", + "quote 1.0.9", + "serde 1.0.123", + "serde_json", + "syn 1.0.60", + "textwrap 0.12.1", + "thiserror", + "typed-builder", +] + +[[package]] +name = "ghost" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.60", +] + [[package]] name = "gimli" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" +[[package]] +name = "globset" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags", + "ignore", + "walkdir", +] + [[package]] name = "gloo-timers" version = "0.2.1" @@ -1484,18 +1732,62 @@ dependencies = [ "http", "indexmap", "slab", - "tokio", - "tokio-util", + "tokio 0.2.25", + "tokio-util 0.3.1", "tracing", "tracing-futures", ] +[[package]] +name = "h2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d832b01df74254fe364568d6ddc294443f61cbec82816b60904303af87efae78" +dependencies = [ + "bytes 1.0.1", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio 1.2.0", + "tokio-util 0.6.3", + "tracing", +] + [[package]] name = "hashbrown" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +[[package]] +name = "headers" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62689dc57c7456e69712607ffcbd0aa1dfcccf9af73727e9b25bc1825375cac3" +dependencies = [ + "base64 0.13.0", + "bitflags", + "bytes 1.0.1", + "headers-core", + "http", + "mime", + "sha-1 0.8.2", + "time 0.1.43", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + [[package]] name = "heck" version = "0.3.2" @@ -1546,6 +1838,16 @@ dependencies = [ "http", ] +[[package]] +name = "http-body" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994" +dependencies = [ + "bytes 1.0.1", + "http", +] + [[package]] name = "httparse" version = "1.3.5" @@ -1584,20 +1886,57 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.2.7", "http", - "http-body", + "http-body 0.3.1", "httparse", "httpdate", "itoa", "pin-project 1.0.5", "socket2", - "tokio", + "tokio 0.2.25", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8e946c2b1349055e0b72ae281b238baf1a3ea7307c7e9f9d64673bdd9c26ac7" +dependencies = [ + "bytes 1.0.1", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.1", + "http", + "http-body 0.4.0", + "httparse", + "httpdate", + "itoa", + "pin-project 1.0.5", + "socket2", + "tokio 1.2.0", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes 1.0.1", + "hyper 0.14.4", + "native-tls", + "tokio 1.2.0", + "tokio-native-tls", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1615,6 +1954,24 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "ignore" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c" +dependencies = [ + "crossbeam-utils 0.8.3", + "globset", + "lazy_static", + "log", + "memchr", + "regex", + "same-file", + "thread_local", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "1.6.1" @@ -1625,6 +1982,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + [[package]] name = "instant" version = "0.1.9" @@ -1634,6 +1997,28 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "inventory" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f" +dependencies = [ + "ctor", + "ghost", + "inventory-impl", +] + +[[package]] +name = "inventory-impl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.60", +] + [[package]] name = "iovec" version = "0.1.4" @@ -1652,9 +2037,15 @@ dependencies = [ "socket2", "widestring", "winapi 0.3.9", - "winreg", + "winreg 0.6.2", ] +[[package]] +name = "ipnet" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" + [[package]] name = "itertools" version = "0.8.2" @@ -1664,6 +2055,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.7" @@ -1725,9 +2125,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213" [[package]] name = "linked-hash-map" @@ -1801,28 +2201,35 @@ dependencies = [ "actix-rt", "actix-web", "actix-web-actors", + "async-recursion", "async-trait", "awc", "bytes 0.5.6", "chrono", "config", + "cucumber_rust", "deadpool", "deadpool-redis", "derive_builder", "derive_more", "dotenv", "failure", + "fantoccini", "function_name", "futures 0.3.13", "humantime-serde", + "hyper 0.14.4", "lazy_static", "medea-client-api-proto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "medea-control-api-mock", "medea-control-api-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "medea-coturn-telnet-client 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "medea-macro 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "medea-macro 0.2.0", "mockall", + "once_cell", "rand 0.8.3", "redis", + "reqwest", "rust-argon2", "rust-crypto", "serde 1.0.123", @@ -1838,10 +2245,14 @@ dependencies = [ "smart-default", "subtle", "tempfile", - "tokio", + "tokio 0.2.25", + "tokio 1.2.0", + "tokio-util 0.6.3", "toml", "tonic", "url", + "uuid", + "webdriver", ] [[package]] @@ -1929,8 +2340,8 @@ dependencies = [ "futures 0.3.13", "once_cell", "regex", - "tokio", - "tokio-util", + "tokio 0.2.25", + "tokio-util 0.3.1", ] [[package]] @@ -1946,8 +2357,8 @@ dependencies = [ "futures 0.3.13", "once_cell", "regex", - "tokio", - "tokio-util", + "tokio 0.2.25", + "tokio-util 0.3.1", ] [[package]] @@ -2013,7 +2424,7 @@ name = "medea-reactive" version = "0.1.0" dependencies = [ "futures 0.3.13", - "tokio", + "tokio 0.2.25", ] [[package]] @@ -2043,6 +2454,16 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime_guess" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -2066,12 +2487,25 @@ dependencies = [ "kernel32-sys", "libc", "log", - "miow", + "miow 0.2.2", "net2", "slab", "winapi 0.2.8", ] +[[package]] +name = "mio" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5dede4e2065b3842b8b0af444119f3aa331cc7cc2dd20388bfb0f5d5a38823a" +dependencies = [ + "libc", + "log", + "miow 0.3.6", + "ntapi", + "winapi 0.3.9", +] + [[package]] name = "mio-uds" version = "0.6.8" @@ -2080,7 +2514,7 @@ checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" dependencies = [ "iovec", "libc", - "mio", + "mio 0.6.23", ] [[package]] @@ -2095,6 +2529,16 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "miow" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +dependencies = [ + "socket2", + "winapi 0.3.9", +] + [[package]] name = "mockall" version = "0.9.1" @@ -2128,6 +2572,24 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1255076139a83bb467426e7f8d0134968a8118844faa755985e077cf31850333" +[[package]] +name = "native-tls" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nb-connect" version = "1.0.3" @@ -2166,6 +2628,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "num-integer" version = "0.1.44" @@ -2211,16 +2682,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" [[package]] -name = "once_cell" -version = "1.7.0" +name = "once_cell" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl" +version = "0.10.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "lazy_static", + "libc", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] -name = "opaque-debug" -version = "0.3.0" +name = "openssl-sys" +version = "0.9.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] [[package]] name = "parking" @@ -2253,6 +2763,39 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "pathdiff" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877630b3de15c0b64cc52f659345724fbf6bdad9bd9566699fc53688f3c34a34" + +[[package]] +name = "peg" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f76678828272f177ac33b7e2ac2e3e73cc6c1cd1e3e387928aa69562fa51367" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "636d60acf97633e48d266d7415a9355d4389cea327a193f87df395d88cd2b14d" +dependencies = [ + "peg-runtime", + "proc-macro2 1.0.24", + "quote 1.0.9", +] + +[[package]] +name = "peg-runtime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555b1514d2d99d78150d3c799d4c357a3e2c2a8062cd108e93a06d9057629c5" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -2311,15 +2854,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c917123afa01924fc84bb20c4c03f004d9c38e5127e3c039bbf7f4b9c76a2f6b" +checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439697af366c49a6d0a010c56a0d97685bc140ce0d377b13a2ea2aa42d64a827" +checksum = "0cf491442e4b033ed1c722cb9f0df5fcfcf4de682466c46469c36bc47dc5548a" [[package]] name = "pin-utils" @@ -2327,6 +2870,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + [[package]] name = "polling" version = "2.0.2" @@ -2432,7 +2981,7 @@ checksum = "02b10678c913ecbd69350e8535c3aef91a8676c0773fc1d7b95cdd196d7f2f26" dependencies = [ "bytes 0.5.6", "heck", - "itertools", + "itertools 0.8.2", "log", "multimap", "petgraph", @@ -2449,7 +2998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "537aa19b95acde10a12fec4301466386f757403de4cd4e5b4fa78fb5ecb18f72" dependencies = [ "anyhow", - "itertools", + "itertools 0.8.2", "proc-macro2 1.0.24", "quote 1.0.9", "syn 1.0.60", @@ -2647,10 +3196,10 @@ dependencies = [ "futures-util", "itoa", "percent-encoding", - "pin-project-lite 0.1.11", + "pin-project-lite 0.1.12", "sha1", - "tokio", - "tokio-util", + "tokio 0.2.25", + "tokio-util 0.3.1", "url", ] @@ -2700,6 +3249,41 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "reqwest" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0460542b551950620a3648c6aa23318ac6b3cd779114bd873209e6e8b5eb1c34" +dependencies = [ + "base64 0.13.0", + "bytes 1.0.1", + "encoding_rs", + "futures-core", + "futures-util", + "http", + "http-body 0.4.0", + "hyper 0.14.4", + "hyper-tls", + "ipnet", + "js-sys", + "lazy_static", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite 0.2.5", + "serde 1.0.123", + "serde_json", + "serde_urlencoded 0.7.0", + "tokio 1.2.0", + "tokio-native-tls", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.7.0", +] + [[package]] name = "resolv-conf" version = "0.7.0" @@ -2773,6 +3357,25 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi 0.3.9", +] + [[package]] name = "scoped-tls" version = "1.0.0" @@ -2785,6 +3388,29 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "security-framework" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfd318104249865096c8da1dfabf09ddbb6d0330ea176812a62ec75e40c4166" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee48cdde5ed250b0d3252818f646e174ab414036edb884dde62d80a3ac6082d" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "0.9.0" @@ -2859,6 +3485,18 @@ dependencies = [ "serde 0.8.23", ] +[[package]] +name = "serde_urlencoded" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +dependencies = [ + "dtoa", + "itoa", + "serde 1.0.123", + "url", +] + [[package]] name = "serde_urlencoded" version = "0.7.0" @@ -2927,17 +3565,29 @@ dependencies = [ "syn 1.0.60", ] +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + [[package]] name = "sha-1" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfebf75d25bd900fd1e7d11501efab59bc846dbc76196839663e6637bba9f25f" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if 1.0.0", "cpuid-bool", - "digest", - "opaque-debug", + "digest 0.9.0", + "opaque-debug 0.3.0", ] [[package]] @@ -2946,6 +3596,16 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +[[package]] +name = "shh" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5205eb079ac8be8ec77b7470aff4a050610d42c32819deee362ca414c926d3ab" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "signal-hook-registry" version = "1.3.0" @@ -3222,6 +3882,25 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal_size" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -3231,6 +3910,16 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789" +dependencies = [ + "terminal_size", + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.24" @@ -3345,16 +4034,32 @@ dependencies = [ "lazy_static", "libc", "memchr", - "mio", + "mio 0.6.23", "mio-uds", "num_cpus", - "pin-project-lite 0.1.11", + "pin-project-lite 0.1.12", "signal-hook-registry", "slab", - "tokio-macros", + "tokio-macros 0.2.6", "winapi 0.3.9", ] +[[package]] +name = "tokio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a" +dependencies = [ + "autocfg", + "bytes 1.0.1", + "libc", + "memchr", + "mio 0.7.9", + "num_cpus", + "pin-project-lite 0.2.5", + "tokio-macros 1.1.0", +] + [[package]] name = "tokio-macros" version = "0.2.6" @@ -3366,6 +4071,27 @@ dependencies = [ "syn 1.0.60", ] +[[package]] +name = "tokio-macros" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.60", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio 1.2.0", +] + [[package]] name = "tokio-util" version = "0.3.1" @@ -3377,8 +4103,22 @@ dependencies = [ "futures-io", "futures-sink", "log", - "pin-project-lite 0.1.11", - "tokio", + "pin-project-lite 0.1.12", + "tokio 0.2.25", +] + +[[package]] +name = "tokio-util" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebb7cb2f00c5ae8df755b252306272cd1790d39728363936e01827e11f0b017b" +dependencies = [ + "bytes 1.0.1", + "futures-core", + "futures-sink", + "log", + "pin-project-lite 0.2.5", + "tokio 1.2.0", ] [[package]] @@ -3396,21 +4136,21 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74a5d6e7439ecf910463667080de772a9c7ddf26bc9fb4f3252ac3862e43337d" dependencies = [ - "async-stream", + "async-stream 0.2.1", "async-trait", "base64 0.12.3", "bytes 0.5.6", "futures-core", "futures-util", "http", - "http-body", - "hyper", + "http-body 0.3.1", + "hyper 0.13.10", "percent-encoding", "pin-project 0.4.27", "prost", "prost-derive", - "tokio", - "tokio-util", + "tokio 0.2.25", + "tokio-util 0.3.1", "tower", "tower-balance", "tower-load", @@ -3462,7 +4202,7 @@ dependencies = [ "pin-project 0.4.27", "rand 0.7.3", "slab", - "tokio", + "tokio 0.2.25", "tower-discover", "tower-layer", "tower-load", @@ -3480,7 +4220,7 @@ checksum = "c4887dc2a65d464c8b9b66e0e4d51c2fd6cf5b3373afc72805b0a60bce00446a" dependencies = [ "futures-core", "pin-project 0.4.27", - "tokio", + "tokio 0.2.25", "tower-layer", "tower-service", "tracing", @@ -3511,7 +4251,7 @@ checksum = "92c3040c5dbed68abffaa0d4517ac1a454cd741044f33ab0eefab6b8d1361404" dependencies = [ "futures-core", "pin-project 0.4.27", - "tokio", + "tokio 0.2.25", "tower-layer", "tower-load", "tower-service", @@ -3526,7 +4266,7 @@ dependencies = [ "futures-core", "log", "pin-project 0.4.27", - "tokio", + "tokio 0.2.25", "tower-discover", "tower-service", ] @@ -3549,7 +4289,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce50370d644a0364bf4877ffd4f76404156a248d104e2cc234cd391ea5cdc965" dependencies = [ - "tokio", + "tokio 0.2.25", "tower-service", ] @@ -3563,7 +4303,7 @@ dependencies = [ "futures-util", "indexmap", "log", - "tokio", + "tokio 0.2.25", "tower-service", ] @@ -3575,7 +4315,7 @@ checksum = "e6727956aaa2f8957d4d9232b308fe8e4e65d99db30f42b225646e86c9b6a952" dependencies = [ "futures-core", "pin-project 0.4.27", - "tokio", + "tokio 0.2.25", "tower-layer", "tower-service", ] @@ -3593,7 +4333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "127b8924b357be938823eaaec0608c482d40add25609481027b96198b2e4b31e" dependencies = [ "pin-project 0.4.27", - "tokio", + "tokio 0.2.25", "tower-layer", "tower-service", ] @@ -3627,7 +4367,7 @@ checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" dependencies = [ "cfg-if 1.0.0", "log", - "pin-project-lite 0.2.4", + "pin-project-lite 0.2.5", "tracing-attributes", "tracing-core", ] @@ -3684,7 +4424,7 @@ dependencies = [ "rand 0.7.3", "smallvec", "thiserror", - "tokio", + "tokio 0.2.25", "url", ] @@ -3704,7 +4444,7 @@ dependencies = [ "resolv-conf", "smallvec", "thiserror", - "tokio", + "tokio 0.2.25", "trust-dns-proto", ] @@ -3714,12 +4454,32 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "typed-builder" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f85f4270f4f449a3f2c0cf2aecc8415e388a597aeacc7d55fc749c5c968c8533" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.60", +] + [[package]] name = "typenum" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -3774,6 +4534,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9232eb53352b4442e40d7900465dfc534e8cb2dc8f18656fcb2ac16112b5593" + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.2", +] + [[package]] name = "value-bag" version = "1.0.0-alpha.6" @@ -3783,6 +4558,12 @@ dependencies = [ "ctor", ] +[[package]] +name = "vcpkg" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" + [[package]] name = "vec-arena" version = "1.0.0" @@ -3807,6 +4588,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi 0.3.9", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" @@ -3817,6 +4609,32 @@ dependencies = [ "try-lock", ] +[[package]] +name = "warp" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41be6df54c97904af01aa23e613d4521eed7ab23537cede692d4058f6449407" +dependencies = [ + "bytes 0.5.6", + "futures 0.3.13", + "headers", + "http", + "hyper 0.13.10", + "log", + "mime", + "mime_guess", + "pin-project 0.4.27", + "scoped-tls", + "serde 1.0.123", + "serde_json", + "serde_urlencoded 0.6.1", + "tokio 0.2.25", + "tower-service", + "tracing", + "tracing-futures", + "urlencoding", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -3942,6 +4760,27 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webdriver" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ff28d617c8e5648fb34eff57357ae44cd8ed792bbe11b5901a4f4a528d7b201" +dependencies = [ + "base64 0.12.3", + "bytes 0.5.6", + "cookie 0.12.0", + "http", + "log", + "serde 1.0.123", + "serde_derive", + "serde_json", + "time 0.1.43", + "tokio 0.2.25", + "unicode-segmentation", + "url", + "warp", +] + [[package]] name = "wee_alloc" version = "0.4.5" @@ -4006,6 +4845,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -4021,6 +4869,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "winreg" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/Makefile b/Makefile index 7e1ab3581..0f27cfd74 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ IMAGE_NAME := $(strip \ RUST_VER := 1.50 CHROME_VERSION := 88.0 -FIREFOX_VERSION := 85.0.2 +FIREFOX_VERSION := 86.0 crate-dir = . ifeq ($(crate),medea-jason) @@ -480,6 +480,7 @@ endif dockerized=$(dockerized) tag=$(tag) debug=$(debug) @make wait.port port=4444 endif + sleep 5 cargo test --test e2e ifeq ($(up),yes) @make docker.down.e2e From 2ae8807a8001b8704056a34744ea0c3be6f762cc Mon Sep 17 00:00:00 2001 From: alexlapa Date: Wed, 3 Mar 2021 12:26:02 +0200 Subject: [PATCH 08/19] revert --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 0f27cfd74..002a7e1b8 100644 --- a/Makefile +++ b/Makefile @@ -480,7 +480,6 @@ endif dockerized=$(dockerized) tag=$(tag) debug=$(debug) @make wait.port port=4444 endif - sleep 5 cargo test --test e2e ifeq ($(up),yes) @make docker.down.e2e From b2e63f387bd66929f504489b3a7462e911120050 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Wed, 3 Mar 2021 09:42:26 -0500 Subject: [PATCH 09/19] Remove JasonError usage from core --- jason/src/api/wasm/connection_handle.rs | 4 +- .../api/wasm/constraints_update_exception.rs | 4 +- jason/src/api/wasm/jason_error.rs | 2 +- jason/src/api/wasm/media_manager_handle.rs | 4 +- jason/src/api/wasm/reconnect_handle.rs | 4 +- jason/src/api/wasm/room_handle.rs | 4 +- jason/src/connection.rs | 31 +++-- jason/src/media/manager.rs | 15 +- jason/src/peer/mod.rs | 7 +- jason/src/platform/wasm/transport.rs | 3 +- jason/src/room.rs | 128 ++++++++++-------- jason/src/rpc/mod.rs | 2 +- jason/src/rpc/reconnect_handle.rs | 31 +++-- jason/src/rpc/websocket/client.rs | 5 +- jason/src/utils/component.rs | 6 +- jason/src/utils/errors.rs | 8 -- jason/src/utils/mod.rs | 39 ++---- 17 files changed, 162 insertions(+), 135 deletions(-) diff --git a/jason/src/api/wasm/connection_handle.rs b/jason/src/api/wasm/connection_handle.rs index 2e0888259..e589b14dd 100644 --- a/jason/src/api/wasm/connection_handle.rs +++ b/jason/src/api/wasm/connection_handle.rs @@ -1,7 +1,9 @@ use derive_more::From; use wasm_bindgen::prelude::*; -use crate::{api::JasonError, connection}; +use crate::{connection}; + +use super::jason_error::JasonError; /// Connection with a specific remote `Member`, that is used on JS side. /// diff --git a/jason/src/api/wasm/constraints_update_exception.rs b/jason/src/api/wasm/constraints_update_exception.rs index 372799730..c953a96a5 100644 --- a/jason/src/api/wasm/constraints_update_exception.rs +++ b/jason/src/api/wasm/constraints_update_exception.rs @@ -3,7 +3,9 @@ use std::iter::FromIterator as _; use derive_more::From; use wasm_bindgen::prelude::*; -use crate::{api::JasonError, room}; +use crate::{room}; + +use super::jason_error::JasonError; /// Exception returned from for the [`RoomHandle::set_local_media_settings`][1]. /// diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs index 16c3e6630..7bbffea22 100644 --- a/jason/src/api/wasm/jason_error.rs +++ b/jason/src/api/wasm/jason_error.rs @@ -5,10 +5,10 @@ use std::{ use derive_more::From; use derive_more::{Display}; use tracerr::{Trace, Traced}; -use crate::utils::JsCaused; use wasm_bindgen::prelude::*; use crate::platform; +use crate::utils::JsCaused; /// Representation of app error exported to JS side. /// diff --git a/jason/src/api/wasm/media_manager_handle.rs b/jason/src/api/wasm/media_manager_handle.rs index fc6c42160..41dd7ff1b 100644 --- a/jason/src/api/wasm/media_manager_handle.rs +++ b/jason/src/api/wasm/media_manager_handle.rs @@ -4,10 +4,12 @@ use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; use crate::{ - api::{InputDeviceInfo, JasonError, LocalMediaTrack, MediaStreamSettings}, + api::{InputDeviceInfo, LocalMediaTrack, MediaStreamSettings}, media, }; +use super::jason_error::JasonError; + /// [`MediaManagerHandle`] is a weak ref to [`MediaManager`]. /// /// [`MediaManager`] performs all media acquisition requests diff --git a/jason/src/api/wasm/reconnect_handle.rs b/jason/src/api/wasm/reconnect_handle.rs index 9af5ca4ca..c3f05bb6f 100644 --- a/jason/src/api/wasm/reconnect_handle.rs +++ b/jason/src/api/wasm/reconnect_handle.rs @@ -3,7 +3,9 @@ use js_sys::Promise; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use crate::{api::JasonError, rpc}; +use crate::{rpc}; + +use super::jason_error::JasonError; /// Handle that JS side can reconnect to the Medea media server on /// a connection loss with. diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index 6bd555d8c..b2b6da74a 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -5,12 +5,14 @@ use wasm_bindgen_futures::future_to_promise; use crate::{ api::{ - ConstraintsUpdateException, JasonError, MediaSourceKind, + ConstraintsUpdateException, MediaSourceKind, MediaStreamSettings, }, room, }; +use super::jason_error::JasonError; + /// JS side handle to [`Room`] where all the media happens. /// /// Like all handlers it contains weak reference to object that is managed by diff --git a/jason/src/connection.rs b/jason/src/connection.rs index 2116d63b4..39a6ae8d5 100644 --- a/jason/src/connection.rs +++ b/jason/src/connection.rs @@ -7,12 +7,14 @@ use std::{ }; use medea_client_api_proto::{ConnectionQualityScore, MemberId, PeerId}; +use derive_more::Display; +use tracerr::Traced; use crate::{ api, media::track::remote, platform, - api::JasonError, + utils::JsCaused, }; /// Service which manages [`Connection`]s with the remote `Member`s. @@ -87,6 +89,17 @@ impl Connections { } } +/// Errors that may occur in a [`ConnectionHandle`]. +#[derive(Clone, Copy, Debug, Display, JsCaused)] +#[js(error = "platform::Error")] +pub enum ConnectionError { + /// [`ConnectionHandle`]'s [`Weak`] pointer is detached. + #[display(fmt = "Connection is in detached state")] + Detached, +} + +gen_upgrade_macro!(ConnectionError::Detached); + /// External handler to [`Connection`] with remote `Member`. /// /// Actually, represents a [`Weak`]-based handle to `InnerConnection`. @@ -118,13 +131,13 @@ impl ConnectionHandle { pub fn on_close( &self, f: platform::Function<()>, - ) -> Result<(), JasonError> { - upgrade_or_detached!(self.0).map(|inner| inner.on_close.set_func(f)) + ) -> Result<(), Traced> { + upgrade!(self.0).map(|inner| inner.on_close.set_func(f)) } /// Returns remote `Member` ID. - pub fn get_remote_member_id(&self) -> Result { - upgrade_or_detached!(self.0).map(|inner| inner.remote_id.0.clone()) + pub fn get_remote_member_id(&self) -> Result> { + upgrade!(self.0).map(|inner| inner.remote_id.0.clone()) } /// Sets callback, which will be invoked when new [`remote::Track`] will be @@ -132,8 +145,8 @@ impl ConnectionHandle { pub fn on_remote_track_added( &self, f: platform::Function, - ) -> Result<(), JasonError> { - upgrade_or_detached!(self.0) + ) -> Result<(), Traced> { + upgrade!(self.0) .map(|inner| inner.on_remote_track_added.set_func(f)) } @@ -142,8 +155,8 @@ impl ConnectionHandle { pub fn on_quality_score_update( &self, f: platform::Function, - ) -> Result<(), JasonError> { - upgrade_or_detached!(self.0) + ) -> Result<(), Traced> { + upgrade!(self.0) .map(|inner| inner.on_quality_score_update.set_func(f)) } } diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 1b90d3414..22e338adf 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -16,7 +16,6 @@ use crate::{ MultiSourceTracksConstraints, }, platform, - api::JasonError, utils::{JsCaused}, }; @@ -58,6 +57,10 @@ pub enum MediaManagerError { /// [3]: https://w3.org/TR/screen-capture#dom-mediadevices-getdisplaymedia #[display(fmt = "{} track is ended", _0)] LocalTrackIsEnded(MediaKind), + + /// [`MediaManagerHandle`]'s [`Weak`] pointer is detached. + #[display(fmt = "MediaManager is in detached state")] + Detached, } type Result = std::result::Result>; @@ -299,6 +302,8 @@ impl MediaManager { } } +gen_upgrade_macro!(MediaManagerError::Detached); + /// External handle to [`MediaManager`]. /// /// [`MediaManager`] performs all media acquisition requests @@ -321,11 +326,10 @@ impl MediaManagerHandle { /// cameras, and so forth. pub async fn enumerate_devices( &self, - ) -> std::result::Result, JasonError> { + ) -> Result> { InnerMediaManager::enumerate_devices() .await .map_err(tracerr::wrap!(=> MediaManagerError)) - .map_err(JasonError::from) } /// Returns [`local::LocalMediaTrack`]s objects, built from provided @@ -333,8 +337,8 @@ impl MediaManagerHandle { pub async fn init_local_tracks( &self, caps: MediaStreamSettings, - ) -> std::result::Result, JasonError> { - upgrade_or_detached!(self.0, JasonError)? + ) -> Result> { + upgrade!(self.0)? .get_tracks(caps) .await .map(|tracks| { @@ -344,6 +348,5 @@ impl MediaManagerHandle { .collect::>() }) .map_err(tracerr::wrap!(=> MediaManagerError)) - .map_err(JasonError::from) } } diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index 9b8a3f6d8..ded06c637 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -388,8 +388,9 @@ impl PeerConnection { peer.peer.on_track(Some(move |track, transceiver| { if let Err(err) = media_connections.add_remote_track(track, transceiver) + .map_err(tracerr::map_from_and_wrap!(=> PeerError)) { - JasonError::from(err).print(); + log::error!("{}", err); }; })); @@ -500,10 +501,10 @@ impl PeerConnection { /// Sends [`platform::RtcStats`] update of this [`PeerConnection`] to the /// server. pub async fn scrape_and_send_peer_stats(&self) { - match self.peer.get_stats().await { + match self.peer.get_stats().await.map_err(tracerr::map_from_and_wrap!(=> PeerError)) { Ok(stats) => self.send_peer_stats(stats), Err(e) => { - JasonError::from(e).print(); + log::error!("{}", e); } }; } diff --git a/jason/src/platform/wasm/transport.rs b/jason/src/platform/wasm/transport.rs index 2dffd543f..bad13b13f 100644 --- a/jason/src/platform/wasm/transport.rs +++ b/jason/src/platform/wasm/transport.rs @@ -16,7 +16,6 @@ use crate::{ transport::{RpcTransport, TransportError, TransportState}, wasm::utils::EventListener, }, - api::JasonError, rpc::{websocket::ClientDisconnect, ApiUrl, CloseMsg}, }; @@ -211,7 +210,7 @@ impl WebSocketRpcTransport { Err(e) => { // TODO: protocol versions mismatch? should drop // connection if so - JasonError::from(tracerr::new!(e)).print(); + log::error!("{}", tracerr::new!(e)); return; } }; diff --git a/jason/src/room.rs b/jason/src/room.rs index 255117811..cff9e1723 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -40,7 +40,7 @@ use crate::{ ClientDisconnect, CloseReason, ConnectionInfo, ConnectionInfoParseError, ReconnectHandle, RpcSession, SessionError, }, - utils::{AsProtoState, JsCaused, HandlerDetachedError}, + utils::{AsProtoState, JsCaused}, }; /// Reason of why [`Room`] has been closed. @@ -154,6 +154,14 @@ pub enum RoomError { /// [`peer::repo::Component`] returned [`MediaManagerError`]. #[display(fmt = "Failed to get local tracks: {}", _0)] MediaManagerError(#[js(cause)] MediaManagerError), + + /// [`ConnectionInfo`] parsing failed. + #[display(fmt = "Failed to parse ConnectionInfo: {}", _0)] + ConnectionInfoParse(ConnectionInfoParseError), + + /// [`RoomHandle`]'s [`Weak`] pointer is detached. + #[display(fmt = "Room is in detached state")] + Detached, } impl From for RoomError { @@ -176,6 +184,8 @@ impl From for RoomError { } } +gen_upgrade_macro!(RoomError::Detached); + /// External handle to [`Room`]. #[derive(Clone)] pub struct RoomHandle(Weak); @@ -193,23 +203,23 @@ impl RoomHandle { /// - `on_failed_local_media` callback is not set /// - `on_connection_loss` callback is not set /// - unable to connect to media server. - pub async fn join(&self, url: String) -> Result<(), JasonError> { - let inner = upgrade_or_detached!(self.0, JasonError)?; + pub async fn join(&self, url: String) -> Result<(), Traced> { + let inner = upgrade!(self.0)?; let connection_info: ConnectionInfo = url.parse().map_err( - tracerr::map_from_and_wrap!(=> ConnectionInfoParseError), + tracerr::map_from_and_wrap!(), )?; if !inner.on_failed_local_media.is_set() { - return Err(JasonError::from(tracerr::new!( + return Err(tracerr::new!( RoomError::CallbackNotSet("Room.on_failed_local_media()") - ))); + )); } if !inner.on_connection_loss.is_set() { - return Err(JasonError::from(tracerr::new!( + return Err(tracerr::new!( RoomError::CallbackNotSet("Room.on_connection_loss()") - ))); + )); } Rc::clone(&inner.rpc) @@ -228,8 +238,8 @@ impl RoomHandle { kind: MediaKind, direction: TrackDirection, source_kind: Option, - ) -> Result<(), JasonError> { - let inner = upgrade_or_detached!(self.0, JasonError)?; + ) -> Result<(), Traced> { + let inner = upgrade!(self.0)?; inner.set_constraints_media_state( new_state, kind, @@ -252,7 +262,7 @@ impl RoomHandle { inner .get_local_tracks(kind, source_kind) .await - .map_err(tracerr::map_from_and_wrap!(=> RoomError))? + .map_err(tracerr::map_from_and_wrap!())? } else { Vec::new() }; @@ -266,7 +276,7 @@ impl RoomHandle { if let Err(e) = inner .toggle_media_state(new_state, kind, direction, source_kind) .await - .map_err(tracerr::map_from_and_wrap!(=> RoomError)) + .map_err(tracerr::map_from_and_wrap!()) { if direction_send && enabling { inner.set_constraints_media_state( @@ -297,8 +307,8 @@ impl RoomHandle { pub fn on_new_connection( &self, f: platform::Function, - ) -> Result<(), JasonError> { - upgrade_or_detached!(self.0) + ) -> Result<(), Traced> { + upgrade!(self.0) .map(|inner| inner.connections.on_new_connection(f)) } @@ -307,8 +317,8 @@ impl RoomHandle { pub fn on_close( &self, f: platform::Function, - ) -> Result<(), JasonError> { - upgrade_or_detached!(self.0).map(|inner| inner.on_close.set_func(f)) + ) -> Result<(), Traced> { + upgrade!(self.0).map(|inner| inner.on_close.set_func(f)) } /// Sets callback, which will be invoked when new [`local::Track`] will be @@ -320,8 +330,8 @@ impl RoomHandle { pub fn on_local_track( &self, f: platform::Function, - ) -> Result<(), JasonError> { - upgrade_or_detached!(self.0) + ) -> Result<(), Traced> { + upgrade!(self.0) .map(|inner| inner.on_local_track.set_func(f)) } @@ -330,8 +340,8 @@ impl RoomHandle { pub fn on_failed_local_media( &self, f: platform::Function, - ) -> Result<(), JasonError> { - upgrade_or_detached!(self.0) + ) -> Result<(), Traced> { + upgrade!(self.0) .map(|inner| inner.on_failed_local_media.set_func(f)) } @@ -340,8 +350,8 @@ impl RoomHandle { pub fn on_connection_loss( &self, f: platform::Function, - ) -> Result<(), JasonError> { - upgrade_or_detached!(self.0) + ) -> Result<(), Traced> { + upgrade!(self.0) .map(|inner| inner.on_connection_loss.set_func(f)) } @@ -376,9 +386,9 @@ impl RoomHandle { rollback_on_fail: bool, ) -> Result<(), ConstraintsUpdateException> { let inner = (self.0).upgrade().ok_or_else(|| { - ConstraintsUpdateException::Errored(new_js_error!( - HandlerDetachedError - )) + ConstraintsUpdateException::Errored( + tracerr::new!(RoomError::Detached) + ) })?; inner @@ -400,7 +410,7 @@ impl RoomHandle { kind: MediaKind, direction: TrackDirection, source_kind: Option, - ) -> Result<(), JasonError> + ) -> Result<(), Traced> where S: Into + 'static, { @@ -416,7 +426,7 @@ impl RoomHandle { } /// Mutes outbound audio in this [`Room`]. - pub async fn mute_audio(&self) -> Result<(), JasonError> { + pub async fn mute_audio(&self) -> Result<(), Traced> { self.change_media_state( mute_state::Stable::Muted, MediaKind::Audio, @@ -424,10 +434,11 @@ impl RoomHandle { None, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Unmutes outbound audio in this [`Room`]. - pub async fn unmute_audio(&self) -> Result<(), JasonError> { + pub async fn unmute_audio(&self) -> Result<(), Traced> { self.change_media_state( mute_state::Stable::Unmuted, MediaKind::Audio, @@ -435,13 +446,14 @@ impl RoomHandle { None, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Mutes outbound video in this [`Room`]. pub async fn mute_video( &self, source_kind: Option, - ) -> Result<(), JasonError> { + ) -> Result<(), Traced> { self.change_media_state( mute_state::Stable::Muted, MediaKind::Video, @@ -449,13 +461,14 @@ impl RoomHandle { source_kind, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Unmutes outbound video in this [`Room`]. pub async fn unmute_video( &self, source_kind: Option, - ) -> Result<(), JasonError> { + ) -> Result<(), Traced> { self.change_media_state( mute_state::Stable::Unmuted, MediaKind::Video, @@ -463,10 +476,11 @@ impl RoomHandle { source_kind, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Disables outbound audio in this [`Room`]. - pub async fn disable_audio(&self) -> Result<(), JasonError> { + pub async fn disable_audio(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Audio, @@ -474,10 +488,11 @@ impl RoomHandle { None, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Enables outbound audio in this [`Room`]. - pub async fn enable_audio(&self) -> Result<(), JasonError> { + pub async fn enable_audio(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Audio, @@ -485,6 +500,7 @@ impl RoomHandle { None, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Disables outbound video. @@ -493,7 +509,7 @@ impl RoomHandle { pub async fn disable_video( &self, source_kind: Option, - ) -> Result<(), JasonError> { + ) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Video, @@ -501,6 +517,7 @@ impl RoomHandle { source_kind, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Enables outbound video. @@ -509,7 +526,7 @@ impl RoomHandle { pub async fn enable_video( &self, source_kind: Option, - ) -> Result<(), JasonError> { + ) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Video, @@ -517,10 +534,11 @@ impl RoomHandle { source_kind, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Disables inbound audio in this [`Room`]. - pub async fn disable_remote_audio(&self) -> Result<(), JasonError> { + pub async fn disable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Audio, @@ -528,10 +546,11 @@ impl RoomHandle { None, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Disables inbound video in this [`Room`]. - pub async fn disable_remote_video(&self) -> Result<(), JasonError> { + pub async fn disable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Disabled, MediaKind::Video, @@ -539,10 +558,11 @@ impl RoomHandle { None, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Enables inbound audio in this [`Room`]. - pub async fn enable_remote_audio(&self) -> Result<(), JasonError> { + pub async fn enable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Audio, @@ -550,10 +570,11 @@ impl RoomHandle { None, ) .await + .map_err(tracerr::map_from_and_wrap!()) } /// Enables inbound video in this [`Room`]. - pub async fn enable_remote_video(&self) -> Result<(), JasonError> { + pub async fn enable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Enabled, MediaKind::Video, @@ -561,6 +582,7 @@ impl RoomHandle { None, ) .await + .map_err(tracerr::map_from_and_wrap!()) } } @@ -628,16 +650,16 @@ impl Room { match event { RoomEvent::RpcEvent(event) => { if let Err(err) = - event.dispatch_with(inner.deref()).await + event.dispatch_with(inner.deref()).await.map_err(tracerr::map_from_and_wrap!(=> RoomError)) { - JasonError::from(err).print(); + log::error!("{}", err); }; } RoomEvent::PeerEvent(event) => { if let Err(err) = - event.dispatch_with(inner.deref()).await + event.dispatch_with(inner.deref()).await.map_err(tracerr::map_from_and_wrap!(=> RoomError)) { - JasonError::from(err).print(); + log::error!("{}", err); }; } RoomEvent::RpcClientLostConnection => { @@ -760,7 +782,7 @@ pub enum ConstraintsUpdateException { #[display(fmt = "RecoveredException")] Recovered { /// [`JasonError`] due to which recovery happened. - recover_reason: JasonError, + recover_reason: Traced, }, /// New [`MediaStreamSettings`] set failed and state recovering also @@ -768,15 +790,15 @@ pub enum ConstraintsUpdateException { #[display(fmt = "RecoverFailedException")] RecoverFailed { /// [`JasonError`] due to which recovery happened. - recover_reason: JasonError, + recover_reason: Traced, /// Vector of [`JasonError`]s due to which recovery failed. - recover_fail_reasons: Vec, + recover_fail_reasons: Vec>, }, /// Some other error occurred. #[display(fmt = "ErroredException")] - Errored(JasonError), + Errored(Traced), } impl ConstraintsUpdateException { @@ -789,7 +811,7 @@ impl ConstraintsUpdateException { /// `RecoveredException` or `RecoverFailedException`. /// /// Returns `undefined` otherwise. - pub fn recover_reason(&self) -> Option { + pub fn recover_reason(&self) -> Option> { match &self { Self::RecoverFailed { recover_reason, .. } | Self::Recovered { recover_reason, .. } => { @@ -800,7 +822,7 @@ impl ConstraintsUpdateException { } /// Returns vector of [`JasonError`]s if this due to which recovery failed. - pub fn recover_fail_reasons(&self) -> Vec { + pub fn recover_fail_reasons(&self) -> Vec> { match &self { Self::RecoverFailed { recover_fail_reasons, @@ -814,7 +836,7 @@ impl ConstraintsUpdateException { /// `ErroredException`. /// /// Returns `undefined` otherwise. - pub fn error(&self) -> Option { + pub fn error(&self) -> Option> { match &self { Self::Errored(reason) => Some(reason.clone()), _ => None, @@ -891,22 +913,22 @@ impl From for ConstraintsUpdateException { use ConstraintsUpdateError as E; match from { E::Recovered { recover_reason } => Self::Recovered { - recover_reason: JasonError::from(recover_reason), + recover_reason: tracerr::new!(recover_reason), }, E::RecoverFailed { recover_reason, recover_fail_reasons, } => Self::RecoverFailed { - recover_reason: JasonError::from(recover_reason), + recover_reason: tracerr::new!(recover_reason), recover_fail_reasons: { recover_fail_reasons .into_iter() - .map(JasonError::from) + .map(tracerr::map_from_and_wrap!()) .collect() }, }, E::Errored { error: reason } => { - Self::Errored(JasonError::from(reason)) + Self::Errored(tracerr::new!(reason)) } } } diff --git a/jason/src/rpc/mod.rs b/jason/src/rpc/mod.rs index 1458dfdfe..48263c7a7 100644 --- a/jason/src/rpc/mod.rs +++ b/jason/src/rpc/mod.rs @@ -75,7 +75,7 @@ impl ConnectionInfo { } /// Errors which can occur while [`ConnectionInfo`] parsing from the [`str`]. -#[derive(Debug, JsCaused, Display)] +#[derive(Clone, Debug, JsCaused, Display)] #[js(error = "platform::Error")] pub enum ConnectionInfoParseError { /// [`Url::parse`] returned error. diff --git a/jason/src/rpc/reconnect_handle.rs b/jason/src/rpc/reconnect_handle.rs index 285aeae02..5171a890a 100644 --- a/jason/src/rpc/reconnect_handle.rs +++ b/jason/src/rpc/reconnect_handle.rs @@ -2,20 +2,31 @@ use std::{rc::Weak, time::Duration}; +use tracerr::Traced; use derive_more::Display; +use derive_more::From; use crate::{ platform, rpc::{BackoffDelayer, RpcSession}, - api::JasonError, utils::{JsCaused}, }; +use crate::rpc::SessionError; -/// Error which indicates that [`RpcSession`]'s (which this [`ReconnectHandle`] -/// tries to reconnect) token is `None`. -#[derive(Debug, Display, JsCaused)] +/// Errors that may occur in a [`ReconnectHandle`]. +#[derive(Clone, From, Display, JsCaused)] #[js(error = "platform::Error")] -struct NoTokenError; +pub enum ReconnectError { + /// Some [`SessionError`] occurred while reconnecting. + #[display(fmt = "{}", _0)] + Session(#[js(cause)] SessionError), + + /// [`ReconnectHandle`]'s [`Weak`] pointer is detached. + #[display(fmt = "Reconnector is in detached state")] + Detached, +} + +gen_upgrade_macro!(ReconnectError::Detached); /// External handle that is used to reconnect to the Medea media server on /// connection loss. @@ -39,11 +50,11 @@ impl ReconnectHandle { pub async fn reconnect_with_delay( &self, delay_ms: u32, - ) -> Result<(), JasonError> { + ) -> Result<(), Traced> { platform::delay_for(Duration::from_millis(u64::from(delay_ms))).await; - let rpc = upgrade_or_detached!(self.0, JasonError)?; - rpc.reconnect().await.map_err(JasonError::from)?; + let rpc = upgrade!(self.0)?; + rpc.reconnect().await.map_err(tracerr::map_from_and_wrap!())?; Ok(()) } @@ -71,14 +82,14 @@ impl ReconnectHandle { starting_delay_ms: u32, multiplier: f32, max_delay: u32, - ) -> Result<(), JasonError> { + ) -> Result<(), Traced> { let mut backoff_delayer = BackoffDelayer::new( Duration::from_millis(u64::from(starting_delay_ms)), multiplier, Duration::from_millis(u64::from(max_delay)), ); backoff_delayer.delay().await; - while upgrade_or_detached!(self.0, JasonError)? + while upgrade!(self.0)? .reconnect() .await .is_err() diff --git a/jason/src/rpc/websocket/client.rs b/jason/src/rpc/websocket/client.rs index 5665fafae..ebd9acf67 100644 --- a/jason/src/rpc/websocket/client.rs +++ b/jason/src/rpc/websocket/client.rs @@ -21,7 +21,6 @@ use crate::{ ApiUrl, CloseMsg, CloseReason, ClosedStateReason, Heartbeat, IdleTimeout, PingInterval, RpcClientError, }, - api::JasonError, }; /// Reasons of closing WebSocket RPC connection by a client side. @@ -526,9 +525,9 @@ impl WebSocketRpcClient { if let Some(socket) = socket_borrow.as_ref() { if let Err(err) = - socket.send(&ClientMsg::Command { room_id, command }) + socket.send(&ClientMsg::Command { room_id, command }).map_err(tracerr::map_from_and_wrap!(=> RpcClientError)) { - JasonError::from(err).print() + log::error!("{}", err); } } } diff --git a/jason/src/utils/component.rs b/jason/src/utils/component.rs index 33049647d..81d17a55c 100644 --- a/jason/src/utils/component.rs +++ b/jason/src/utils/component.rs @@ -1,6 +1,7 @@ //! Implementation of the [`Component`]. use std::rc::Rc; +use std::fmt::Display; use derive_more::Deref; use futures::{future, Future, FutureExt as _, Stream, StreamExt}; @@ -9,7 +10,6 @@ use medea_reactive::AllProcessed; use crate::{ media::LocalTracksConstraints, platform, - api::JasonError, utils::{TaskHandle}, }; @@ -125,7 +125,7 @@ impl WatchersSpawner { F: Fn(Rc, Rc, V) -> H + 'static, R: Stream + Unpin + 'static, H: Future> + 'static, - E: Into, + E: Display, { let obj = Rc::clone(&self.obj); let state = Rc::clone(&self.state); @@ -134,7 +134,7 @@ impl WatchersSpawner { if let Err(e) = (handle)(Rc::clone(&obj), Rc::clone(&state), value).await { - Into::::into(e).print(); + log::error!("{}", e); } } }); diff --git a/jason/src/utils/errors.rs b/jason/src/utils/errors.rs index c1fb99b19..6df083f77 100644 --- a/jason/src/utils/errors.rs +++ b/jason/src/utils/errors.rs @@ -7,8 +7,6 @@ use std::{ use derive_more::{Display, From}; -use crate::platform; - pub use medea_macro::JsCaused; /// Representation of an error which can caused by error returned from the @@ -24,12 +22,6 @@ pub trait JsCaused { fn js_cause(self) -> Option; } -/// Occurs if referenced value was dropped. -#[derive(Debug, Display, JsCaused)] -#[js(error = "platform::Error")] -#[display(fmt = "Handler is in detached state.")] -pub struct HandlerDetachedError; - /// Wrapper for [`serde_json::error::Error`] that provides [`Clone`], [`Debug`], /// [`Display`] implementations. #[derive(Clone, Debug, Display, From)] diff --git a/jason/src/utils/mod.rs b/jason/src/utils/mod.rs index 6b957f074..868cc81e7 100644 --- a/jason/src/utils/mod.rs +++ b/jason/src/utils/mod.rs @@ -15,41 +15,18 @@ use medea_reactive::Guarded; #[doc(inline)] pub use self::{ component::{AsProtoState, Component, SynchronizableState, Updatable}, - errors::{HandlerDetachedError, JsCaused, JsonParseError}, + errors::{JsCaused, JsonParseError}, resettable_delay::{resettable_delay_for, ResettableDelayHandle}, }; -/// Upgrades provided [`Weak`] reference, mapping it to a [`Result`] with -/// [`HandlerDetachedError`] and invokes [`Into::into`] on the error. -/// If the error type cannot be inferred, then you can provide a concrete type -/// (usually being [`JasonError`] or [`JsValue`]). -/// -/// [`Weak`]: std::rc::Weak -macro_rules! upgrade_or_detached { - ($v:expr) => {{ - $v.upgrade() - .ok_or_else(|| new_js_error!($crate::utils::HandlerDetachedError)) - }}; - ($v:expr, $err:ty) => {{ - $v.upgrade() - .ok_or_else(|| new_js_error!($crate::utils::HandlerDetachedError => $err)) - }}; -} - -/// Adds [`tracerr`] information to the provided error, wraps it into -/// [`JasonError`] and converts it into the expected error type. -/// -/// This macro has two syntaxes: -/// - `new_js_error!(DetachedStateError)` - converts provided error wrapped into -/// [`JasonError`] with [`Into::into`] automatically; -/// - `new_js_error!(DetachedStateError => platform::Error)` - annotates -/// explicitly which type conversion is required. -macro_rules! new_js_error { +macro_rules! gen_upgrade_macro { ($e:expr) => { - $crate::api::JasonError::from(tracerr::new!($e)).into() - }; - ($e:expr => $o:ty) => { - <$o>::from($crate::api::JasonError::from(tracerr::new!($e))) + macro_rules! upgrade { + ($v:expr) => { + $v.upgrade() + .ok_or_else(|| tracerr::new!($e)) + }; + } }; } From a85a4acc5ac57f00a00fc73ef08645c8536d9d3d Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Wed, 3 Mar 2021 09:47:26 -0500 Subject: [PATCH 10/19] Fmt --- jason/src/api/wasm/connection_handle.rs | 2 +- .../api/wasm/constraints_update_exception.rs | 2 +- jason/src/api/wasm/jason_error.rs | 19 ++--- jason/src/api/wasm/reconnect_handle.rs | 2 +- jason/src/api/wasm/room_handle.rs | 5 +- jason/src/connection.rs | 19 ++--- jason/src/media/manager.rs | 2 +- jason/src/peer/mod.rs | 17 ++-- jason/src/room.rs | 77 ++++++++++--------- jason/src/rpc/reconnect_handle.rs | 18 ++--- jason/src/rpc/websocket/client.rs | 5 +- jason/src/utils/component.rs | 9 +-- jason/src/utils/errors.rs | 5 +- jason/src/utils/mod.rs | 3 +- 14 files changed, 84 insertions(+), 101 deletions(-) diff --git a/jason/src/api/wasm/connection_handle.rs b/jason/src/api/wasm/connection_handle.rs index e589b14dd..cad34627b 100644 --- a/jason/src/api/wasm/connection_handle.rs +++ b/jason/src/api/wasm/connection_handle.rs @@ -1,7 +1,7 @@ use derive_more::From; use wasm_bindgen::prelude::*; -use crate::{connection}; +use crate::connection; use super::jason_error::JasonError; diff --git a/jason/src/api/wasm/constraints_update_exception.rs b/jason/src/api/wasm/constraints_update_exception.rs index c953a96a5..4e427e98c 100644 --- a/jason/src/api/wasm/constraints_update_exception.rs +++ b/jason/src/api/wasm/constraints_update_exception.rs @@ -3,7 +3,7 @@ use std::iter::FromIterator as _; use derive_more::From; use wasm_bindgen::prelude::*; -use crate::{room}; +use crate::room; use super::jason_error::JasonError; diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs index 7bbffea22..5fde76f01 100644 --- a/jason/src/api/wasm/jason_error.rs +++ b/jason/src/api/wasm/jason_error.rs @@ -1,14 +1,10 @@ -use std::{ - fmt::{Debug, Display}, -}; +use std::fmt::{Debug, Display}; -use derive_more::From; -use derive_more::{Display}; +use derive_more::{Display, From}; use tracerr::{Trace, Traced}; use wasm_bindgen::prelude::*; -use crate::platform; -use crate::utils::JsCaused; +use crate::{platform, utils::JsCaused}; /// Representation of app error exported to JS side. /// @@ -49,12 +45,11 @@ impl JasonError { pub fn print(&self) { log::error!("{}", self); } - } impl From<(E, Trace)> for JasonError - where - E::Error: Into, +where + E::Error: Into, { fn from((err, trace): (E, Trace)) -> Self { Self { @@ -67,8 +62,8 @@ impl From<(E, Trace)> for JasonError } impl From> for JasonError - where - E::Error: Into, +where + E::Error: Into, { fn from(traced: Traced) -> Self { Self::from(traced.into_parts()) diff --git a/jason/src/api/wasm/reconnect_handle.rs b/jason/src/api/wasm/reconnect_handle.rs index c3f05bb6f..87d2acd0e 100644 --- a/jason/src/api/wasm/reconnect_handle.rs +++ b/jason/src/api/wasm/reconnect_handle.rs @@ -3,7 +3,7 @@ use js_sys::Promise; use wasm_bindgen::prelude::*; use wasm_bindgen_futures::future_to_promise; -use crate::{rpc}; +use crate::rpc; use super::jason_error::JasonError; diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index b2b6da74a..0b0d4136f 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -4,10 +4,7 @@ use wasm_bindgen::{prelude::*, JsValue}; use wasm_bindgen_futures::future_to_promise; use crate::{ - api::{ - ConstraintsUpdateException, MediaSourceKind, - MediaStreamSettings, - }, + api::{ConstraintsUpdateException, MediaSourceKind, MediaStreamSettings}, room, }; diff --git a/jason/src/connection.rs b/jason/src/connection.rs index 39a6ae8d5..7c130561a 100644 --- a/jason/src/connection.rs +++ b/jason/src/connection.rs @@ -6,16 +6,11 @@ use std::{ rc::{Rc, Weak}, }; -use medea_client_api_proto::{ConnectionQualityScore, MemberId, PeerId}; use derive_more::Display; +use medea_client_api_proto::{ConnectionQualityScore, MemberId, PeerId}; use tracerr::Traced; -use crate::{ - api, - media::track::remote, - platform, - utils::JsCaused, -}; +use crate::{api, media::track::remote, platform, utils::JsCaused}; /// Service which manages [`Connection`]s with the remote `Member`s. #[derive(Default)] @@ -136,7 +131,9 @@ impl ConnectionHandle { } /// Returns remote `Member` ID. - pub fn get_remote_member_id(&self) -> Result> { + pub fn get_remote_member_id( + &self, + ) -> Result> { upgrade!(self.0).map(|inner| inner.remote_id.0.clone()) } @@ -146,8 +143,7 @@ impl ConnectionHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0) - .map(|inner| inner.on_remote_track_added.set_func(f)) + upgrade!(self.0).map(|inner| inner.on_remote_track_added.set_func(f)) } /// Sets callback, which will be invoked when connection quality score will @@ -156,8 +152,7 @@ impl ConnectionHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0) - .map(|inner| inner.on_quality_score_update.set_func(f)) + upgrade!(self.0).map(|inner| inner.on_quality_score_update.set_func(f)) } } diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 22e338adf..de94122ce 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -16,7 +16,7 @@ use crate::{ MultiSourceTracksConstraints, }, platform, - utils::{JsCaused}, + utils::JsCaused, }; use super::track::local; diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index ded06c637..21b6d4df1 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -26,6 +26,7 @@ use medea_macro::dispatchable; use tracerr::Traced; use crate::{ + api::JasonError, connection::Connections, media::{ track::{local, remote}, @@ -33,8 +34,7 @@ use crate::{ MediaStreamSettings, RecvConstraints, }, platform, - utils::{JsCaused}, - api::JasonError, + utils::JsCaused, }; #[doc(inline)] @@ -386,9 +386,9 @@ impl PeerConnection { // Bind to `track` event. let media_connections = Rc::clone(&peer.media_connections); peer.peer.on_track(Some(move |track, transceiver| { - if let Err(err) = - media_connections.add_remote_track(track, transceiver) - .map_err(tracerr::map_from_and_wrap!(=> PeerError)) + if let Err(err) = media_connections + .add_remote_track(track, transceiver) + .map_err(tracerr::map_from_and_wrap!(=> PeerError)) { log::error!("{}", err); }; @@ -501,7 +501,12 @@ impl PeerConnection { /// Sends [`platform::RtcStats`] update of this [`PeerConnection`] to the /// server. pub async fn scrape_and_send_peer_stats(&self) { - match self.peer.get_stats().await.map_err(tracerr::map_from_and_wrap!(=> PeerError)) { + match self + .peer + .get_stats() + .await + .map_err(tracerr::map_from_and_wrap!(=> PeerError)) + { Ok(stats) => self.send_peer_stats(stats), Err(e) => { log::error!("{}", e); diff --git a/jason/src/room.rs b/jason/src/room.rs index cff9e1723..67c66f31e 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -23,6 +23,7 @@ use tracerr::Traced; use crate::{ api, + api::JasonError, connection::Connections, media::{ track::{local, remote}, @@ -35,7 +36,6 @@ use crate::{ PeerEvent, PeerEventHandler, TrackDirection, }, platform, - api::JasonError, rpc::{ ClientDisconnect, CloseReason, ConnectionInfo, ConnectionInfoParseError, ReconnectHandle, RpcSession, SessionError, @@ -206,20 +206,19 @@ impl RoomHandle { pub async fn join(&self, url: String) -> Result<(), Traced> { let inner = upgrade!(self.0)?; - let connection_info: ConnectionInfo = url.parse().map_err( - tracerr::map_from_and_wrap!(), - )?; + let connection_info: ConnectionInfo = + url.parse().map_err(tracerr::map_from_and_wrap!())?; if !inner.on_failed_local_media.is_set() { - return Err(tracerr::new!( - RoomError::CallbackNotSet("Room.on_failed_local_media()") - )); + return Err(tracerr::new!(RoomError::CallbackNotSet( + "Room.on_failed_local_media()" + ))); } if !inner.on_connection_loss.is_set() { - return Err(tracerr::new!( - RoomError::CallbackNotSet("Room.on_connection_loss()") - )); + return Err(tracerr::new!(RoomError::CallbackNotSet( + "Room.on_connection_loss()" + ))); } Rc::clone(&inner.rpc) @@ -308,8 +307,7 @@ impl RoomHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0) - .map(|inner| inner.connections.on_new_connection(f)) + upgrade!(self.0).map(|inner| inner.connections.on_new_connection(f)) } /// Sets `on_close` callback, which will be invoked on [`Room`] close, @@ -331,8 +329,7 @@ impl RoomHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0) - .map(|inner| inner.on_local_track.set_func(f)) + upgrade!(self.0).map(|inner| inner.on_local_track.set_func(f)) } /// Sets `on_failed_local_media` callback, which will be invoked on local @@ -341,8 +338,7 @@ impl RoomHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0) - .map(|inner| inner.on_failed_local_media.set_func(f)) + upgrade!(self.0).map(|inner| inner.on_failed_local_media.set_func(f)) } /// Sets `on_connection_loss` callback, which will be invoked on connection @@ -351,8 +347,7 @@ impl RoomHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0) - .map(|inner| inner.on_connection_loss.set_func(f)) + upgrade!(self.0).map(|inner| inner.on_connection_loss.set_func(f)) } /// Updates this [`Room`]s [`MediaStreamSettings`]. This affects all @@ -386,9 +381,9 @@ impl RoomHandle { rollback_on_fail: bool, ) -> Result<(), ConstraintsUpdateException> { let inner = (self.0).upgrade().ok_or_else(|| { - ConstraintsUpdateException::Errored( - tracerr::new!(RoomError::Detached) - ) + ConstraintsUpdateException::Errored(tracerr::new!( + RoomError::Detached + )) })?; inner @@ -434,7 +429,7 @@ impl RoomHandle { None, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Unmutes outbound audio in this [`Room`]. @@ -446,7 +441,7 @@ impl RoomHandle { None, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Mutes outbound video in this [`Room`]. @@ -461,7 +456,7 @@ impl RoomHandle { source_kind, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Unmutes outbound video in this [`Room`]. @@ -476,7 +471,7 @@ impl RoomHandle { source_kind, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Disables outbound audio in this [`Room`]. @@ -488,7 +483,7 @@ impl RoomHandle { None, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Enables outbound audio in this [`Room`]. @@ -500,7 +495,7 @@ impl RoomHandle { None, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Disables outbound video. @@ -517,7 +512,7 @@ impl RoomHandle { source_kind, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Enables outbound video. @@ -534,7 +529,7 @@ impl RoomHandle { source_kind, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Disables inbound audio in this [`Room`]. @@ -546,7 +541,7 @@ impl RoomHandle { None, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Disables inbound video in this [`Room`]. @@ -558,7 +553,7 @@ impl RoomHandle { None, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Enables inbound audio in this [`Room`]. @@ -570,7 +565,7 @@ impl RoomHandle { None, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } /// Enables inbound video in this [`Room`]. @@ -582,7 +577,7 @@ impl RoomHandle { None, ) .await - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) } } @@ -649,15 +644,23 @@ impl Room { if let Some(inner) = inner.upgrade() { match event { RoomEvent::RpcEvent(event) => { - if let Err(err) = - event.dispatch_with(inner.deref()).await.map_err(tracerr::map_from_and_wrap!(=> RoomError)) + if let Err(err) = event + .dispatch_with(inner.deref()) + .await + .map_err( + tracerr::map_from_and_wrap!(=> RoomError), + ) { log::error!("{}", err); }; } RoomEvent::PeerEvent(event) => { - if let Err(err) = - event.dispatch_with(inner.deref()).await.map_err(tracerr::map_from_and_wrap!(=> RoomError)) + if let Err(err) = event + .dispatch_with(inner.deref()) + .await + .map_err( + tracerr::map_from_and_wrap!(=> RoomError), + ) { log::error!("{}", err); }; diff --git a/jason/src/rpc/reconnect_handle.rs b/jason/src/rpc/reconnect_handle.rs index 5171a890a..92bc6e02d 100644 --- a/jason/src/rpc/reconnect_handle.rs +++ b/jason/src/rpc/reconnect_handle.rs @@ -2,16 +2,14 @@ use std::{rc::Weak, time::Duration}; +use derive_more::{Display, From}; use tracerr::Traced; -use derive_more::Display; -use derive_more::From; use crate::{ platform, - rpc::{BackoffDelayer, RpcSession}, - utils::{JsCaused}, + rpc::{BackoffDelayer, RpcSession, SessionError}, + utils::JsCaused, }; -use crate::rpc::SessionError; /// Errors that may occur in a [`ReconnectHandle`]. #[derive(Clone, From, Display, JsCaused)] @@ -54,7 +52,9 @@ impl ReconnectHandle { platform::delay_for(Duration::from_millis(u64::from(delay_ms))).await; let rpc = upgrade!(self.0)?; - rpc.reconnect().await.map_err(tracerr::map_from_and_wrap!())?; + rpc.reconnect() + .await + .map_err(tracerr::map_from_and_wrap!())?; Ok(()) } @@ -89,11 +89,7 @@ impl ReconnectHandle { Duration::from_millis(u64::from(max_delay)), ); backoff_delayer.delay().await; - while upgrade!(self.0)? - .reconnect() - .await - .is_err() - { + while upgrade!(self.0)?.reconnect().await.is_err() { backoff_delayer.delay().await; } diff --git a/jason/src/rpc/websocket/client.rs b/jason/src/rpc/websocket/client.rs index ebd9acf67..a8e06235b 100644 --- a/jason/src/rpc/websocket/client.rs +++ b/jason/src/rpc/websocket/client.rs @@ -524,8 +524,9 @@ impl WebSocketRpcClient { let socket_borrow = &self.0.borrow().sock; if let Some(socket) = socket_borrow.as_ref() { - if let Err(err) = - socket.send(&ClientMsg::Command { room_id, command }).map_err(tracerr::map_from_and_wrap!(=> RpcClientError)) + if let Err(err) = socket + .send(&ClientMsg::Command { room_id, command }) + .map_err(tracerr::map_from_and_wrap!(=> RpcClientError)) { log::error!("{}", err); } diff --git a/jason/src/utils/component.rs b/jason/src/utils/component.rs index 81d17a55c..92afb95bf 100644 --- a/jason/src/utils/component.rs +++ b/jason/src/utils/component.rs @@ -1,17 +1,12 @@ //! Implementation of the [`Component`]. -use std::rc::Rc; -use std::fmt::Display; +use std::{fmt::Display, rc::Rc}; use derive_more::Deref; use futures::{future, Future, FutureExt as _, Stream, StreamExt}; use medea_reactive::AllProcessed; -use crate::{ - media::LocalTracksConstraints, - platform, - utils::{TaskHandle}, -}; +use crate::{media::LocalTracksConstraints, platform, utils::TaskHandle}; /// Abstraction over a state which can be transformed to the states from the /// [`medea_client_api_proto::state`]. diff --git a/jason/src/utils/errors.rs b/jason/src/utils/errors.rs index 6df083f77..6ed11c4c2 100644 --- a/jason/src/utils/errors.rs +++ b/jason/src/utils/errors.rs @@ -1,9 +1,6 @@ //! Helpers for application errors. -use std::{ - fmt::{Debug}, - rc::Rc, -}; +use std::{fmt::Debug, rc::Rc}; use derive_more::{Display, From}; diff --git a/jason/src/utils/mod.rs b/jason/src/utils/mod.rs index 868cc81e7..0c193861c 100644 --- a/jason/src/utils/mod.rs +++ b/jason/src/utils/mod.rs @@ -23,8 +23,7 @@ macro_rules! gen_upgrade_macro { ($e:expr) => { macro_rules! upgrade { ($v:expr) => { - $v.upgrade() - .ok_or_else(|| tracerr::new!($e)) + $v.upgrade().ok_or_else(|| tracerr::new!($e)) }; } }; From 024fc83966fb45a66e65fdc280ec3805d09a8cc0 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Wed, 3 Mar 2021 10:11:59 -0500 Subject: [PATCH 11/19] Fix docs --- jason/src/connection.rs | 18 +++++- jason/src/media/manager.rs | 11 ++++ jason/src/room.rs | 93 ++++++++++++++++++++++++++++++- jason/src/rpc/mod.rs | 2 +- jason/src/rpc/reconnect_handle.rs | 10 ++++ jason/src/utils/component.rs | 4 +- 6 files changed, 133 insertions(+), 5 deletions(-) diff --git a/jason/src/connection.rs b/jason/src/connection.rs index 7c130561a..13f0ca7cb 100644 --- a/jason/src/connection.rs +++ b/jason/src/connection.rs @@ -123,6 +123,10 @@ struct InnerConnection { impl ConnectionHandle { /// Sets callback, which will be invoked when this `Connection` will close. + /// + /// # Errors + /// + /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade failed. pub fn on_close( &self, f: platform::Function<()>, @@ -131,6 +135,10 @@ impl ConnectionHandle { } /// Returns remote `Member` ID. + /// + /// # Errors + /// + /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade failed. pub fn get_remote_member_id( &self, ) -> Result> { @@ -139,6 +147,10 @@ impl ConnectionHandle { /// Sets callback, which will be invoked when new [`remote::Track`] will be /// added to this [`Connection`]. + /// + /// # Errors + /// + /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade failed. pub fn on_remote_track_added( &self, f: platform::Function, @@ -147,7 +159,11 @@ impl ConnectionHandle { } /// Sets callback, which will be invoked when connection quality score will - /// be updated by server. + /// be updated by a server. + /// + /// # Errors + /// + /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade failed. pub fn on_quality_score_update( &self, f: platform::Function, diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index de94122ce..63df8ae5b 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -324,6 +324,12 @@ impl MediaManagerHandle { /// Returns array of [`platform::InputDeviceInfo`] objects, which represent /// available media input and output devices, such as microphones, /// cameras, and so forth. + /// + /// # Errors + /// + /// With [`MediaManagerError::CouldNotGetMediaDevices`] or + /// [`MediaManagerError::EnumerateDevicesFailed`] if devices enumeration is + /// failed. pub async fn enumerate_devices( &self, ) -> Result> { @@ -334,6 +340,11 @@ impl MediaManagerHandle { /// Returns [`local::LocalMediaTrack`]s objects, built from provided /// [`MediaStreamSettings`]. + /// + /// # Errors + /// + /// With [`MediaManagerError::Detached`] if [`Weak`] pointer upgrade is + /// failed. pub async fn init_local_tracks( &self, caps: MediaStreamSettings, diff --git a/jason/src/room.rs b/jason/src/room.rs index 67c66f31e..5962ef230 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -203,6 +203,18 @@ impl RoomHandle { /// - `on_failed_local_media` callback is not set /// - `on_connection_loss` callback is not set /// - unable to connect to media server. + /// + /// # Errors + /// + /// With [`RoomError::CallbackNotSet`] if `on_failed_local_media` or + /// `on_connection_loss` callbacks is not set. + /// + /// With [`RoomError::ConnectionInfoParse`] if provided URL parsing fails. + /// + /// With [`RoomError::Detached`] if [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::SessionError`] if connecting to the RPC server is + /// failed. pub async fn join(&self, url: String) -> Result<(), Traced> { let inner = upgrade!(self.0)?; @@ -293,7 +305,7 @@ impl RoomHandle { ) .await?; } - return Err(e.into()); + return Err(e); } } Ok(()) @@ -302,6 +314,10 @@ impl RoomHandle { /// Sets callback, which will be invoked when new [`Connection`] with some /// remote `Peer` is established. /// + /// # Errors + /// + /// With [`RoomError::Detached`] if [`Weak`] pointer upgrade fails. + /// /// [`Connection`]: crate::connection::Connection pub fn on_new_connection( &self, @@ -312,6 +328,10 @@ impl RoomHandle { /// Sets `on_close` callback, which will be invoked on [`Room`] close, /// providing [`RoomCloseReason`]. + /// + /// # Errors + /// + /// With [`RoomError::Detached`] if [`Weak`] pointer upgrade fails. pub fn on_close( &self, f: platform::Function, @@ -325,6 +345,10 @@ impl RoomHandle { /// 1. Media server initiates media request. /// 2. `disable_audio`/`enable_video` is called. /// 3. [`MediaStreamSettings`] updated via `set_local_media_settings`. + /// + /// # Errors + /// + /// With [`RoomError::Detached`] if [`Weak`] pointer upgrade fails. pub fn on_local_track( &self, f: platform::Function, @@ -334,6 +358,10 @@ impl RoomHandle { /// Sets `on_failed_local_media` callback, which will be invoked on local /// media acquisition failures. + /// + /// # Errors + /// + /// With [`RoomError::Detached`] if [`Weak`] pointer upgrade fails. pub fn on_failed_local_media( &self, f: platform::Function, @@ -343,6 +371,10 @@ impl RoomHandle { /// Sets `on_connection_loss` callback, which will be invoked on connection /// with server loss. + /// + /// # Errors + /// + /// With [`RoomError::Detached`] if [`Weak`] pointer upgrade fails. pub fn on_connection_loss( &self, f: platform::Function, @@ -373,6 +405,17 @@ impl RoomHandle { /// If recovering from fail state isn't possible then affected media types /// will be disabled. /// + /// # Errors + /// + /// With [`ConstraintsUpdateException::Errored`] if error while provided + /// [`MediaStreamSettings`] applying occured. + /// + /// With [`ConstraintsUpdateException::Recovered`] if + /// [`MediaStreamSettings`] are rollbacked because error occured. + /// + /// With [`ConstraintsUpdateException::RecoverFailed`] if + /// [`MediaStreamSettings`] rollback failed. + /// /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia pub async fn set_local_media_settings( &self, @@ -421,6 +464,10 @@ impl RoomHandle { } /// Mutes outbound audio in this [`Room`]. + /// + /// # Errors + /// + /// Errors if muting audio is failed. pub async fn mute_audio(&self) -> Result<(), Traced> { self.change_media_state( mute_state::Stable::Muted, @@ -433,6 +480,10 @@ impl RoomHandle { } /// Unmutes outbound audio in this [`Room`]. + /// + /// # Errors + /// + /// Errors if unmuting audio is failed. pub async fn unmute_audio(&self) -> Result<(), Traced> { self.change_media_state( mute_state::Stable::Unmuted, @@ -445,6 +496,10 @@ impl RoomHandle { } /// Mutes outbound video in this [`Room`]. + /// + /// # Errors + /// + /// Errors if muting video is failed. pub async fn mute_video( &self, source_kind: Option, @@ -460,6 +515,10 @@ impl RoomHandle { } /// Unmutes outbound video in this [`Room`]. + /// + /// # Errors + /// + /// Errors if unmuting video is failed. pub async fn unmute_video( &self, source_kind: Option, @@ -475,6 +534,10 @@ impl RoomHandle { } /// Disables outbound audio in this [`Room`]. + /// + /// # Errors + /// + /// Errors if disabling audio is failed. pub async fn disable_audio(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Disabled, @@ -487,6 +550,10 @@ impl RoomHandle { } /// Enables outbound audio in this [`Room`]. + /// + /// # Errors + /// + /// Errors if enabling audio is failed. pub async fn enable_audio(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Enabled, @@ -501,6 +568,10 @@ impl RoomHandle { /// Disables outbound video. /// /// Affects only video with specific [`MediaSourceKind`] if specified. + /// + /// # Errors + /// + /// Errors if disabling video is failed. pub async fn disable_video( &self, source_kind: Option, @@ -518,6 +589,10 @@ impl RoomHandle { /// Enables outbound video. /// /// Affects only video with specific [`MediaSourceKind`] if specified. + /// + /// # Errors + /// + /// Errors if enabling video is failed. pub async fn enable_video( &self, source_kind: Option, @@ -533,6 +608,10 @@ impl RoomHandle { } /// Disables inbound audio in this [`Room`]. + /// + /// # Errors + /// + /// Errors if disabling remote audio is failed. pub async fn disable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Disabled, @@ -545,6 +624,10 @@ impl RoomHandle { } /// Disables inbound video in this [`Room`]. + /// + /// # Errors + /// + /// Errors if disabling remote video is failed. pub async fn disable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Disabled, @@ -557,6 +640,10 @@ impl RoomHandle { } /// Enables inbound audio in this [`Room`]. + /// + /// # Errors + /// + /// Errors if enabling remote audio is failed. pub async fn enable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Enabled, @@ -569,6 +656,10 @@ impl RoomHandle { } /// Enables inbound video in this [`Room`]. + /// + /// # Errors + /// + /// Errors if enabling remote video is failed. pub async fn enable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( media_exchange_state::Stable::Enabled, diff --git a/jason/src/rpc/mod.rs b/jason/src/rpc/mod.rs index 48263c7a7..888fc6b7a 100644 --- a/jason/src/rpc/mod.rs +++ b/jason/src/rpc/mod.rs @@ -23,7 +23,7 @@ pub use self::rpc_session::MockRpcSession; pub use self::{ backoff_delayer::BackoffDelayer, heartbeat::{Heartbeat, HeartbeatError, IdleTimeout, PingInterval}, - reconnect_handle::ReconnectHandle, + reconnect_handle::{ReconnectError, ReconnectHandle}, rpc_session::{ RpcSession, SessionError, SessionState, WebSocketRpcSession, }, diff --git a/jason/src/rpc/reconnect_handle.rs b/jason/src/rpc/reconnect_handle.rs index 92bc6e02d..cc35b7e06 100644 --- a/jason/src/rpc/reconnect_handle.rs +++ b/jason/src/rpc/reconnect_handle.rs @@ -45,6 +45,12 @@ impl ReconnectHandle { /// If [`RpcSession`] is already reconnecting then new reconnection attempt /// won't be performed. Instead, it will wait for the first reconnection /// attempt result and use it here. + /// + /// # Errors + /// + /// With [`ReconnectError::Detached`] if [`Weak`] pointer upgrade failed. + /// + /// With [`ReconnectError::Session`] if error while reconnecting occurred. pub async fn reconnect_with_delay( &self, delay_ms: u32, @@ -77,6 +83,10 @@ impl ReconnectHandle { /// /// If `multiplier` is negative number than `multiplier` will be considered /// as `0.0`. + /// + /// # Errors + /// + /// With [`ReconnectError::Detached`] if [`Weak`] pointer upgrade failed. pub async fn reconnect_with_backoff( &self, starting_delay_ms: u32, diff --git a/jason/src/utils/component.rs b/jason/src/utils/component.rs index 92afb95bf..06ebe4c1c 100644 --- a/jason/src/utils/component.rs +++ b/jason/src/utils/component.rs @@ -110,8 +110,8 @@ pub struct WatchersSpawner { impl WatchersSpawner { /// Spawns watchers for the provided [`Stream`]. /// - /// If watcher returns an error then this error will be converted into the - /// [`JasonError`] and printed with a [`JasonError::print()`]. + /// If watcher returns an error then this error will be printed to the error + /// log. /// /// You can stop all listeners tasks spawned by this function by /// [`Drop`]ping [`Component`]. From 1a4e6a6ff477c1a5058f93df724672bba579ba3e Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Wed, 3 Mar 2021 10:20:36 -0500 Subject: [PATCH 12/19] Fix docs --- jason/src/api/wasm/jason_error.rs | 5 ----- jason/src/peer/mod.rs | 14 +++++++------- jason/src/platform/wasm/peer_connection.rs | 22 +++++++++++----------- jason/src/room.rs | 12 ++++++------ 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs index 5fde76f01..f6f4c51be 100644 --- a/jason/src/api/wasm/jason_error.rs +++ b/jason/src/api/wasm/jason_error.rs @@ -40,11 +40,6 @@ impl JasonError { pub fn source(&self) -> Option { self.source.clone().and_then(|e| e.sys_cause) } - - /// Prints error information to default logger with `ERROR` level. - pub fn print(&self) { - log::error!("{}", self); - } } impl From<(E, Trace)> for JasonError diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index 21b6d4df1..f85217777 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -832,12 +832,12 @@ impl PeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::SetRemoteDescriptionFailed`][3] if + /// With [`RtcPeerConnectionError::SetRemoteDescriptionFailed`][3] if /// [RTCPeerConnection.setRemoteDescription()][2] fails. /// /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface /// [2]: https://w3.org/TR/webrtc/#dom-peerconnection-setremotedescription - /// [3]: platform::RTCPeerConnectionError::SetRemoteDescriptionFailed + /// [3]: platform::RtcPeerConnectionError::SetRemoteDescriptionFailed async fn set_remote_answer(&self, answer: String) -> Result<()> { self.set_remote_description(platform::SdpType::Answer(answer)) .await @@ -848,7 +848,7 @@ impl PeerConnection { /// /// # Errors /// - /// With [`platform::RTCPeerConnectionError::SetRemoteDescriptionFailed`] if + /// With [`platform::RtcPeerConnectionError::SetRemoteDescriptionFailed`] if /// [RTCPeerConnection.setRemoteDescription()][2] fails. /// /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface @@ -864,10 +864,10 @@ impl PeerConnection { /// /// # Errors /// - /// With [`platform::RTCPeerConnectionError::SetRemoteDescriptionFailed`] if + /// With [`platform::RtcPeerConnectionError::SetRemoteDescriptionFailed`] if /// [RTCPeerConnection.setRemoteDescription()][2] fails. /// - /// With [`platform::RTCPeerConnectionError::AddIceCandidateFailed`] if + /// With [`platform::RtcPeerConnectionError::AddIceCandidateFailed`] if /// [RtcPeerConnection.addIceCandidate()][3] fails when adding buffered ICE /// candidates. /// @@ -911,13 +911,13 @@ impl PeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::AddIceCandidateFailed`][2] if + /// With [`RtcPeerConnectionError::AddIceCandidateFailed`][2] if /// [RtcPeerConnection.addIceCandidate()][3] fails to add buffered /// [ICE candidates][1]. /// /// /// [1]: https://tools.ietf.org/html/rfc5245#section-2 - /// [2]: platform::RTCPeerConnectionError::AddIceCandidateFailed + /// [2]: platform::RtcPeerConnectionError::AddIceCandidateFailed /// [3]: https://w3.org/TR/webrtc/#dom-peerconnection-addicecandidate pub async fn add_ice_candidate( &self, diff --git a/jason/src/platform/wasm/peer_connection.rs b/jason/src/platform/wasm/peer_connection.rs index 0e34fde3b..e96f97df9 100644 --- a/jason/src/platform/wasm/peer_connection.rs +++ b/jason/src/platform/wasm/peer_connection.rs @@ -108,7 +108,7 @@ impl RtcPeerConnection { /// /// # Errors /// - /// Errors with [`RTCPeerConnectionError::PeerCreationError`] if + /// Errors with [`RtcPeerConnectionError::PeerCreationError`] if /// [`SysRtcPeerConnection`] creation fails. pub fn new(ice_servers: I, is_force_relayed: bool) -> Result where @@ -142,10 +142,10 @@ impl RtcPeerConnection { /// /// # Errors /// - /// Errors with [`RTCPeerConnectionError::RtcStatsError`] if getting or + /// Errors with [`RtcPeerConnectionError::RtcStatsError`] if getting or /// parsing of [`RtcStats`] fails. /// - /// Errors with [`RTCPeerConnectionError::GetStatsException`] when + /// Errors with [`RtcPeerConnectionError::GetStatsException`] when /// [PeerConnection.getStats][1] promise throws exception. /// /// [1]: https://tinyurl.com/w6hmt5f @@ -333,7 +333,7 @@ impl RtcPeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::AddIceCandidateFailed`] if + /// With [`RtcPeerConnectionError::AddIceCandidateFailed`] if /// [RtcPeerConnection.addIceCandidate()][3] fails. /// /// [1]: https://w3.org/TR/webrtc/#rtcpeerconnection-interface @@ -375,7 +375,7 @@ impl RtcPeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::SetLocalDescriptionFailed`] if + /// With [`RtcPeerConnectionError::SetLocalDescriptionFailed`] if /// [RtcPeerConnection.setLocalDescription()][1] fails. /// /// [1]: https://w3.org/TR/webrtc/#dom-peerconnection-setlocaldescription @@ -402,7 +402,7 @@ impl RtcPeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::SetLocalDescriptionFailed`] if + /// With [`RtcPeerConnectionError::SetLocalDescriptionFailed`] if /// [RtcPeerConnection.setLocalDescription()][1] fails. /// /// [1]: https://w3.org/TR/webrtc/#dom-peerconnection-setlocaldescription @@ -416,7 +416,7 @@ impl RtcPeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::SetLocalDescriptionFailed`] if + /// With [`RtcPeerConnectionError::SetLocalDescriptionFailed`] if /// [RtcPeerConnection.setLocalDescription()][1] fails. /// /// [1]: https://w3.org/TR/webrtc/#dom-peerconnection-setlocaldescription @@ -433,7 +433,7 @@ impl RtcPeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::CreateAnswerFailed`] if + /// With [`RtcPeerConnectionError::CreateAnswerFailed`] if /// [RtcPeerConnection.createAnswer()][1] fails. /// /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection-createanswer @@ -453,7 +453,7 @@ impl RtcPeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::SetLocalDescriptionFailed`] if + /// With [`RtcPeerConnectionError::SetLocalDescriptionFailed`] if /// [RtcPeerConnection.setLocalDescription()][1] fails. /// /// [1]: https://w3.org/TR/webrtc/#dom-peerconnection-setlocaldescription @@ -479,7 +479,7 @@ impl RtcPeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::CreateOfferFailed`] if + /// With [`RtcPeerConnectionError::CreateOfferFailed`] if /// [RtcPeerConnection.createOffer()][1] fails. /// /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection-createoffer @@ -510,7 +510,7 @@ impl RtcPeerConnection { /// /// # Errors /// - /// With [`RTCPeerConnectionError::SetRemoteDescriptionFailed`] if + /// With [`RtcPeerConnectionError::SetRemoteDescriptionFailed`] if /// [RTCPeerConnection.setRemoteDescription()][1] fails. /// /// [1]: https://w3.org/TR/webrtc/#dom-peerconnection-setremotedescription diff --git a/jason/src/room.rs b/jason/src/room.rs index 5962ef230..ba4791af3 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -875,7 +875,7 @@ pub enum ConstraintsUpdateException { /// (`rollback_on_fail`/`stop_first` arguments). #[display(fmt = "RecoveredException")] Recovered { - /// [`JasonError`] due to which recovery happened. + /// [`RoomError`] due to which recovery happened. recover_reason: Traced, }, @@ -883,10 +883,10 @@ pub enum ConstraintsUpdateException { /// failed. #[display(fmt = "RecoverFailedException")] RecoverFailed { - /// [`JasonError`] due to which recovery happened. + /// [`RoomError`] due to which recovery happened. recover_reason: Traced, - /// Vector of [`JasonError`]s due to which recovery failed. + /// Vector of [`RoomError`]s due to which recovery failed. recover_fail_reasons: Vec>, }, @@ -901,7 +901,7 @@ impl ConstraintsUpdateException { self.to_string() } - /// Returns [`JasonError`] if this [`ConstraintsUpdateException`] represents + /// Returns [`RoomError`] if this [`ConstraintsUpdateException`] represents /// `RecoveredException` or `RecoverFailedException`. /// /// Returns `undefined` otherwise. @@ -915,7 +915,7 @@ impl ConstraintsUpdateException { } } - /// Returns vector of [`JasonError`]s if this due to which recovery failed. + /// Returns vector of [`RoomError`]s if this due to which recovery failed. pub fn recover_fail_reasons(&self) -> Vec> { match &self { Self::RecoverFailed { @@ -926,7 +926,7 @@ impl ConstraintsUpdateException { } } - /// Returns [`JasonError`] if this [`ConstraintsUpdateException`] represents + /// Returns [`RoomError`] if this [`ConstraintsUpdateException`] represents /// `ErroredException`. /// /// Returns `undefined` otherwise. From eea39ce7874b642643172e1d75b1b2765a2aa8c2 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Wed, 3 Mar 2021 12:27:57 -0500 Subject: [PATCH 13/19] Minor doc [skip ci] --- jason/src/utils/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jason/src/utils/mod.rs b/jason/src/utils/mod.rs index 0c193861c..438465c8e 100644 --- a/jason/src/utils/mod.rs +++ b/jason/src/utils/mod.rs @@ -19,6 +19,10 @@ pub use self::{ resettable_delay::{resettable_delay_for, ResettableDelayHandle}, }; +/// Generates `upgrade!` macro which can upgrade [`Weak`] pointer, mapping it to +/// a [`Result`] with `$e` error. +/// +/// [`Weak`]: std::rc::Weak macro_rules! gen_upgrade_macro { ($e:expr) => { macro_rules! upgrade { From 99f4b8ed1704a3f0e7da8e25b02abf3ed5dacdba Mon Sep 17 00:00:00 2001 From: alexlapa Date: Tue, 9 Mar 2021 15:33:13 +0200 Subject: [PATCH 14/19] fix merge, review --- .../api/wasm/constraints_update_exception.rs | 4 +-- jason/src/api/wasm/jason_error.rs | 10 ++++--- jason/src/api/wasm/room_handle.rs | 4 +-- jason/src/connection.rs | 30 ++++++++++++------- jason/src/media/constraints.rs | 14 ++++----- jason/src/media/manager.rs | 18 +++++------ jason/src/media/track/remote.rs | 6 ++-- jason/src/peer/component/watchers.rs | 18 +++++------ jason/src/peer/media/mod.rs | 6 ++-- jason/src/peer/mod.rs | 2 +- jason/src/peer/repo.rs | 4 +-- jason/src/platform/mod.rs | 2 +- jason/src/platform/wasm/media_devices.rs | 28 ++++++++--------- jason/src/platform/wasm/media_track.rs | 8 ++--- jason/src/platform/wasm/transceiver.rs | 8 ++--- jason/src/platform/wasm/transport.rs | 6 ++-- jason/src/room.rs | 29 +++++++++++------- jason/src/rpc/reconnect_handle.rs | 20 +++++++++---- jason/src/rpc/rpc_session.rs | 2 +- jason/src/rpc/websocket/client.rs | 10 +++---- jason/src/utils/component.rs | 14 ++++----- jason/src/utils/mod.rs | 14 --------- 22 files changed, 135 insertions(+), 122 deletions(-) diff --git a/jason/src/api/wasm/constraints_update_exception.rs b/jason/src/api/wasm/constraints_update_exception.rs index e29833017..8ad8aafa7 100644 --- a/jason/src/api/wasm/constraints_update_exception.rs +++ b/jason/src/api/wasm/constraints_update_exception.rs @@ -7,7 +7,7 @@ use std::iter::FromIterator as _; use derive_more::From; use wasm_bindgen::prelude::*; -use crate::connection; +use crate::room; use super::jason_error::JasonError; @@ -44,7 +44,7 @@ impl ConstraintsUpdateException { .map(JasonError::from) .map(JsValue::from), ) - .into() + .into() } /// Returns [`JasonError`] if this [`ConstraintsUpdateException`] represents diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs index 998958ff5..97009274d 100644 --- a/jason/src/api/wasm/jason_error.rs +++ b/jason/src/api/wasm/jason_error.rs @@ -1,3 +1,5 @@ +//! App error exported to JS side. + use std::fmt::{Debug, Display}; use derive_more::{Display, From}; @@ -43,8 +45,8 @@ impl JasonError { } impl From<(E, Trace)> for JasonError - where - E::Error: Into, +where + E::Error: Into, { fn from((err, trace): (E, Trace)) -> Self { Self { @@ -57,8 +59,8 @@ impl From<(E, Trace)> for JasonError } impl From> for JasonError - where - E::Error: Into, +where + E::Error: Into, { fn from(traced: Traced) -> Self { Self::from(traced.into_parts()) diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index 2c7cd7dc3..026029ce1 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -162,8 +162,8 @@ impl RoomHandle { stop_first, rollback_on_fail, ) - .await - .map_err(ConstraintsUpdateException::from)?; + .await + .map_err(ConstraintsUpdateException::from)?; Ok(JsValue::UNDEFINED) }) } diff --git a/jason/src/connection.rs b/jason/src/connection.rs index 3c2d5292d..96e312cfc 100644 --- a/jason/src/connection.rs +++ b/jason/src/connection.rs @@ -96,8 +96,6 @@ pub enum ConnectionError { Detached, } -gen_upgrade_macro!(ConnectionError::Detached); - /// External handler to a [`Connection`] with a remote `Member`. /// /// Actually, represents a [`Weak`]-based handle to `InnerConnection`. @@ -128,23 +126,29 @@ impl ConnectionHandle { /// /// # Errors /// - /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade failed. + /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade fails. pub fn on_close( &self, f: platform::Function<()>, ) -> Result<(), Traced> { - upgrade!(self.0).map(|inner| inner.on_close.set_func(f)) + self.0 + .upgrade() + .ok_or_else(|| tracerr::new!(ConnectionError::Detached)) + .map(|inner| inner.on_close.set_func(f)) } /// Returns remote `Member` ID. /// /// # Errors /// - /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade failed. + /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade fails. pub fn get_remote_member_id( &self, ) -> Result> { - upgrade!(self.0).map(|inner| inner.remote_id.0.clone()) + self.0 + .upgrade() + .ok_or_else(|| tracerr::new!(ConnectionError::Detached)) + .map(|inner| inner.remote_id.0.clone()) } /// Sets callback, invoked when a new [`remote::Track`] will is added to @@ -152,12 +156,15 @@ impl ConnectionHandle { /// /// # Errors /// - /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade failed. + /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade fails. pub fn on_remote_track_added( &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0).map(|inner| inner.on_remote_track_added.set_func(f)) + self.0 + .upgrade() + .ok_or_else(|| tracerr::new!(ConnectionError::Detached)) + .map(|inner| inner.on_remote_track_added.set_func(f)) } /// Sets callback, invoked when a connection quality score is updated by @@ -165,12 +172,15 @@ impl ConnectionHandle { /// /// # Errors /// - /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade failed. + /// With [`ConnectionError::Detached`] if [`Weak`] pointer upgrade fails. pub fn on_quality_score_update( &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0).map(|inner| inner.on_quality_score_update.set_func(f)) + self.0 + .upgrade() + .ok_or_else(|| tracerr::new!(ConnectionError::Detached)) + .map(|inner| inner.on_quality_score_update.set_func(f)) } } diff --git a/jason/src/media/constraints.rs b/jason/src/media/constraints.rs index 346f66fc9..2db251dee 100644 --- a/jason/src/media/constraints.rs +++ b/jason/src/media/constraints.rs @@ -403,8 +403,8 @@ impl MediaStreamSettings { /// [`VideoTrackConstraints::unconstrain()`]. #[must_use] pub fn unconstrain_if_satisfies_video(&mut self, track: T) -> bool - where - T: AsRef, + where + T: AsRef, { if self.device_video.satisfies(&track) { self.device_video.unconstrain(); @@ -698,7 +698,7 @@ impl From for Option { if is_device_video_enabled { if let Some(device_video_cons) = - constraints.device_video.constraints + constraints.device_video.constraints { device_cons .get_or_insert_with(platform::MediaStreamConstraints::new) @@ -707,7 +707,7 @@ impl From for Option { } if is_display_video_enabled { if let Some(display_video_cons) = - constraints.display_video.constraints + constraints.display_video.constraints { display_cons .get_or_insert_with( @@ -1147,9 +1147,9 @@ impl DeviceVideoTrackConstraints { satisfies_track(track, MediaKind::Video) && ConstrainString::satisfies(&self.device_id, &track.device_id()) && ConstrainString::satisfies( - &self.facing_mode, - &track.facing_mode(), - ) + &self.facing_mode, + &track.facing_mode(), + ) && ConstrainU32::satisfies(self.height, track.height()) && ConstrainU32::satisfies(self.width, track.width()) && !track.guess_is_from_display() diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 38cd1cfc9..3689c2a57 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -58,8 +58,8 @@ pub enum MediaManagerError { #[display(fmt = "{} track is ended", _0)] LocalTrackIsEnded(MediaKind), - /// [`MediaManagerHandle`]'s [`Weak`] pointer is detached. - #[display(fmt = "MediaManager is in detached state")] + /// [`MediaManagerHandle`]'s inner [`Weak`] pointer could not be upgraded. + #[display(fmt = "MediaManagerHandle is in detached state")] Detached, } @@ -303,8 +303,6 @@ impl MediaManager { } } -gen_upgrade_macro!(MediaManagerError::Detached); - /// External handle to a [`MediaManager`]. /// /// [`MediaManager`] performs all media acquisition requests @@ -329,7 +327,7 @@ impl MediaManagerHandle { /// # Errors /// /// With [`MediaManagerError::CouldNotGetMediaDevices`] or - /// [`MediaManagerError::EnumerateDevicesFailed`] if devices enumeration is + /// [`MediaManagerError::EnumerateDevicesFailed`] if devices enumeration /// failed. pub async fn enumerate_devices( &self, @@ -344,14 +342,16 @@ impl MediaManagerHandle { /// /// # Errors /// - /// With [`MediaManagerError::Detached`] if [`Weak`] pointer upgrade is - /// failed. + /// With [`MediaManagerError::Detached`] if [`Weak`] pointer upgrade fails. pub async fn init_local_tracks( &self, caps: MediaStreamSettings, ) -> Result> { - upgrade!(self.0)? - .get_tracks(caps) + let this = self + .0 + .upgrade() + .ok_or_else(|| tracerr::new!(MediaManagerError::Detached))?; + this.get_tracks(caps) .await .map(|tracks| { tracks diff --git a/jason/src/media/track/remote.rs b/jason/src/media/track/remote.rs index 1d80d72fe..168ec5782 100644 --- a/jason/src/media/track/remote.rs +++ b/jason/src/media/track/remote.rs @@ -45,8 +45,8 @@ impl Track { /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled #[must_use] pub fn new(track: T, media_source_kind: proto::MediaSourceKind) -> Self - where - platform::MediaStreamTrack: From, + where + platform::MediaStreamTrack: From, { let track = platform::MediaStreamTrack::from(track); let track = Track(Rc::new(Inner { @@ -63,7 +63,7 @@ impl Track { let weak_inner = Rc::downgrade(&track.0); async move { while let Some(enabled) = - track_enabled_state_changes.next().await + track_enabled_state_changes.next().await { if let Some(track) = weak_inner.upgrade() { if enabled { diff --git a/jason/src/peer/component/watchers.rs b/jason/src/peer/component/watchers.rs index c46652260..d68346abf 100644 --- a/jason/src/peer/component/watchers.rs +++ b/jason/src/peer/component/watchers.rs @@ -37,8 +37,8 @@ impl Component { candidate.sdp_m_line_index, candidate.sdp_mid, ) - .await - .map_err(tracerr::map_from_and_wrap!()) + .await + .map_err(tracerr::map_from_and_wrap!()) } /// Watcher for the [`State::remote_sdp`] update. @@ -118,7 +118,7 @@ impl Component { peer.send_constraints.clone(), peer.track_events_sender.clone(), ) - .map_err(tracerr::map_from_and_wrap!()) + .map_err(tracerr::map_from_and_wrap!()) { Ok(sender) => sender, Err(e) => { @@ -300,7 +300,7 @@ impl Component { state.when_all_receivers_processed().into(), state.remote_sdp.when_all_processed().into(), ]) - .await; + .await; match negotiation_state { NegotiationState::Stable => { @@ -353,14 +353,14 @@ impl Component { state.when_all_senders_processed().into(), state.when_all_receivers_processed().into(), ]) - .await; + .await; medea_reactive::when_all_processed(vec![ state.senders.when_stabilized().into(), state.receivers.when_stabilized().into(), state.when_all_updated().into(), ]) - .await; + .await; } NegotiationRole::Answerer(remote_sdp) => { state.when_all_receivers_processed().await; @@ -372,13 +372,13 @@ impl Component { state.remote_sdp.when_all_processed().into(), state.senders.when_updated().into(), ]) - .await; + .await; medea_reactive::when_all_processed(vec![ state.senders.when_stabilized().into(), state.receivers.when_stabilized().into(), ]) - .await; + .await; } } @@ -412,7 +412,7 @@ impl Component { /// Waits for [`State::senders`] update and calls /// [`State::update_local_stream()`]. #[watch( - self.maybe_update_local_stream.subscribe().filter(|v| future::ready(*v)) + self.maybe_update_local_stream.subscribe().filter(|v| future::ready(*v)) )] async fn maybe_local_stream_update_needed( peer: Rc, diff --git a/jason/src/peer/media/mod.rs b/jason/src/peer/media/mod.rs index 6e2953407..98c8937b1 100644 --- a/jason/src/peer/media/mod.rs +++ b/jason/src/peer/media/mod.rs @@ -225,9 +225,9 @@ pub enum MediaConnectionsError { /// [`remote::Track`]: crate::media::track::remote::Track /// [`Receiver`]: self::receiver::Receiver #[display( - fmt = "Could not insert remote track with mid: {:?} into media \ + fmt = "Could not insert remote track with mid: {:?} into media \ connections", - _0 + _0 )] CouldNotInsertRemoteTrack(String), @@ -648,7 +648,7 @@ impl MediaConnections { Ok::<(), Traced>(()) }, )) - .await?; + .await?; Ok(media_exchange_state_updates) } diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index 0f83a40c7..ee3e8766b 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -70,7 +70,7 @@ pub enum PeerError { /// /// [1]: https://w3.org/TR/webrtc/#dom-rtcpeerconnection #[display(fmt = "{}", _0)] - RtcPeerConnection(#[js(cause)] platform::RTCPeerConnectionError), + RtcPeerConnection(#[js(cause)] platform::RtcPeerConnectionError), /// Errors that may occur when validating [`TracksRequest`] or parsing /// [`local::Track`]s. diff --git a/jason/src/peer/repo.rs b/jason/src/peer/repo.rs index 38470cb36..44cc344a8 100644 --- a/jason/src/peer/repo.rs +++ b/jason/src/peer/repo.rs @@ -172,7 +172,7 @@ impl Repository { future::join_all( peers.iter().map(|p| p.scrape_and_send_peer_stats()), ) - .await; + .await; } }); @@ -241,7 +241,7 @@ impl Component { Rc::clone(&peers.connections), Rc::clone(&peers.recv_constraints), ) - .map_err(tracerr::map_from_and_wrap!())?, + .map_err(tracerr::map_from_and_wrap!())?, new_peer, ); diff --git a/jason/src/platform/mod.rs b/jason/src/platform/mod.rs index 8e9eae9b9..3bddbe95e 100644 --- a/jason/src/platform/mod.rs +++ b/jason/src/platform/mod.rs @@ -6,7 +6,7 @@ pub mod transport; pub mod wasm; pub use self::{ - peer_connection::{IceCandidate, RTCPeerConnectionError, SdpType}, + peer_connection::{IceCandidate, RtcPeerConnectionError, SdpType}, rtc_stats::RtcStatsError, transport::{ RpcTransport, TransportError, TransportState, WebSocketRpcTransport, diff --git a/jason/src/platform/wasm/media_devices.rs b/jason/src/platform/wasm/media_devices.rs index 835459f3d..946648733 100644 --- a/jason/src/platform/wasm/media_devices.rs +++ b/jason/src/platform/wasm/media_devices.rs @@ -48,10 +48,10 @@ pub async fn enumerate_devices( .map_err(EnumerateDevicesFailed) .map_err(tracerr::from_and_wrap!())?, ) - .await - .map_err(Error::from) - .map_err(EnumerateDevicesFailed) - .map_err(tracerr::from_and_wrap!())?; + .await + .map_err(Error::from) + .map_err(EnumerateDevicesFailed) + .map_err(tracerr::from_and_wrap!())?; Ok(js_sys::Array::from(&devices) .values() @@ -97,11 +97,11 @@ pub async fn get_user_media( .map_err(GetUserMediaFailed) .map_err(tracerr::from_and_wrap!())?, ) - .await - .map(web_sys::MediaStream::from) - .map_err(Error::from) - .map_err(GetUserMediaFailed) - .map_err(tracerr::from_and_wrap!())?; + .await + .map(web_sys::MediaStream::from) + .map_err(Error::from) + .map_err(GetUserMediaFailed) + .map_err(tracerr::from_and_wrap!())?; Ok(js_sys::try_iter(&stream.get_tracks()) .unwrap() @@ -147,11 +147,11 @@ pub async fn get_display_media( .map_err(GetDisplayMediaFailed) .map_err(tracerr::from_and_wrap!())?, ) - .await - .map(web_sys::MediaStream::from) - .map_err(Error::from) - .map_err(GetUserMediaFailed) - .map_err(tracerr::from_and_wrap!())?; + .await + .map(web_sys::MediaStream::from) + .map_err(Error::from) + .map_err(GetUserMediaFailed) + .map_err(tracerr::from_and_wrap!())?; Ok(js_sys::try_iter(&stream.get_tracks()) .unwrap() diff --git a/jason/src/platform/wasm/media_track.rs b/jason/src/platform/wasm/media_track.rs index 26f327b6e..16dfd9426 100644 --- a/jason/src/platform/wasm/media_track.rs +++ b/jason/src/platform/wasm/media_track.rs @@ -23,8 +23,8 @@ pub struct MediaStreamTrack { } impl From for MediaStreamTrack - where - web_sys::MediaStreamTrack: From, +where + web_sys::MediaStreamTrack: From, { #[inline] fn from(from: T) -> MediaStreamTrack { @@ -118,7 +118,7 @@ impl MediaStreamTrack { #[must_use] pub fn height(&self) -> Option { #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - get_property_by_name(&self.sys_track.get_settings(), "height", |v| { + get_property_by_name(&self.sys_track.get_settings(), "height", |v| { v.as_f64().map(|v| v as u32) }) } @@ -131,7 +131,7 @@ impl MediaStreamTrack { #[must_use] pub fn width(&self) -> Option { #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] - get_property_by_name(&self.sys_track.get_settings(), "width", |v| { + get_property_by_name(&self.sys_track.get_settings(), "width", |v| { v.as_f64().map(|v| v as u32) }) } diff --git a/jason/src/platform/wasm/transceiver.rs b/jason/src/platform/wasm/transceiver.rs index 3c14af26c..86364e594 100644 --- a/jason/src/platform/wasm/transceiver.rs +++ b/jason/src/platform/wasm/transceiver.rs @@ -72,10 +72,10 @@ impl Transceiver { .sender() .replace_track(sys_track.map(AsRef::as_ref)), ) - .await - .map(|_| { - self.send_track.replace(new_track); - }) + .await + .map(|_| { + self.send_track.replace(new_track); + }) } /// Returns [`mid`] of this [`Transceiver`]. diff --git a/jason/src/platform/wasm/transport.rs b/jason/src/platform/wasm/transport.rs index 3d726a4ad..bad13b13f 100644 --- a/jason/src/platform/wasm/transport.rs +++ b/jason/src/platform/wasm/transport.rs @@ -149,7 +149,7 @@ impl WebSocketRpcTransport { .set(TransportState::Closed(CloseMsg::from(&msg))); }, ) - .unwrap(), + .unwrap(), ); let inner = Rc::clone(&socket); @@ -161,7 +161,7 @@ impl WebSocketRpcTransport { inner.borrow().socket_state.set(TransportState::Open); }, ) - .unwrap(), + .unwrap(), ); } @@ -192,7 +192,7 @@ impl WebSocketRpcTransport { .set(TransportState::Closed(CloseMsg::from(&msg))); }, ) - .unwrap(); + .unwrap(); self.0.borrow_mut().on_close_listener = Some(on_close); } diff --git a/jason/src/room.rs b/jason/src/room.rs index 6d03b6808..9ba9ed165 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -190,7 +190,12 @@ impl From for RoomError { } } -gen_upgrade_macro!(RoomError::Detached); +macro_rules! upgrade_inner { + ($v:expr) => { + $v.upgrade() + .ok_or_else(|| tracerr::new!(RoomError::Detached)) + }; +} /// External handle to a [`Room`]. #[derive(Clone)] @@ -210,16 +215,16 @@ impl RoomHandle { /// # Errors /// /// With [`RoomError::CallbackNotSet`] if `on_failed_local_media` or - /// `on_connection_loss` callbacks is not set. + /// `on_connection_loss` callback is not set. /// /// With [`RoomError::ConnectionInfoParse`] if provided URL parsing fails. /// /// With [`RoomError::Detached`] if [`Weak`] pointer upgrade fails. /// - /// With [`RoomError::SessionError`] if connecting to the RPC server is - /// failed. + /// With [`RoomError::SessionError`] when unable to connect to a media + /// server. pub async fn join(&self, url: String) -> Result<(), Traced> { - let inner = upgrade!(self.0)?; + let inner = upgrade_inner!(self.0)?; let connection_info: ConnectionInfo = url.parse().map_err(tracerr::map_from_and_wrap!())?; @@ -253,7 +258,7 @@ impl RoomHandle { direction: TrackDirection, source_kind: Option, ) -> Result<(), Traced> { - let inner = upgrade!(self.0)?; + let inner = upgrade_inner!(self.0)?; inner.set_constraints_media_state( new_state, kind, @@ -326,7 +331,8 @@ impl RoomHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0).map(|inner| inner.connections.on_new_connection(f)) + upgrade_inner!(self.0) + .map(|inner| inner.connections.on_new_connection(f)) } /// Sets `on_close` callback, invoked on this [`Room`] close, providing a @@ -339,7 +345,7 @@ impl RoomHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0).map(|inner| inner.on_close.set_func(f)) + upgrade_inner!(self.0).map(|inner| inner.on_close.set_func(f)) } /// Sets callback, invoked when a new [`local::Track`] is added to this @@ -357,7 +363,7 @@ impl RoomHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0).map(|inner| inner.on_local_track.set_func(f)) + upgrade_inner!(self.0).map(|inner| inner.on_local_track.set_func(f)) } /// Sets `on_failed_local_media` callback, invoked on a local media @@ -370,7 +376,8 @@ impl RoomHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0).map(|inner| inner.on_failed_local_media.set_func(f)) + upgrade_inner!(self.0) + .map(|inner| inner.on_failed_local_media.set_func(f)) } /// Sets `on_connection_loss` callback, invoked when a connection with @@ -383,7 +390,7 @@ impl RoomHandle { &self, f: platform::Function, ) -> Result<(), Traced> { - upgrade!(self.0).map(|inner| inner.on_connection_loss.set_func(f)) + upgrade_inner!(self.0).map(|inner| inner.on_connection_loss.set_func(f)) } /// Updates this [`Room`]s [`MediaStreamSettings`]. This affects all diff --git a/jason/src/rpc/reconnect_handle.rs b/jason/src/rpc/reconnect_handle.rs index 1673ea419..637045532 100644 --- a/jason/src/rpc/reconnect_handle.rs +++ b/jason/src/rpc/reconnect_handle.rs @@ -24,8 +24,6 @@ pub enum ReconnectError { Detached, } -gen_upgrade_macro!(ReconnectError::Detached); - /// External handle used to reconnect to a media server when connection is lost. /// /// This handle will be passed to a `Room.on_connection_loss` callback. @@ -49,7 +47,7 @@ impl ReconnectHandle { /// /// # Errors /// - /// With [`ReconnectError::Detached`] if [`Weak`] pointer upgrade failed. + /// With [`ReconnectError::Detached`] if [`Weak`] pointer upgrade fails. /// /// With [`ReconnectError::Session`] if error while reconnecting occurred. pub async fn reconnect_with_delay( @@ -58,7 +56,10 @@ impl ReconnectHandle { ) -> Result<(), Traced> { platform::delay_for(Duration::from_millis(u64::from(delay_ms))).await; - let rpc = upgrade!(self.0)?; + let rpc = self + .0 + .upgrade() + .ok_or_else(|| tracerr::new!(ReconnectError::Detached))?; rpc.reconnect() .await .map_err(tracerr::map_from_and_wrap!())?; @@ -87,7 +88,7 @@ impl ReconnectHandle { /// /// # Errors /// - /// With [`ReconnectError::Detached`] if [`Weak`] pointer upgrade failed. + /// With [`ReconnectError::Detached`] if [`Weak`] pointer upgrade fails. pub async fn reconnect_with_backoff( &self, starting_delay_ms: u32, @@ -100,7 +101,14 @@ impl ReconnectHandle { Duration::from_millis(u64::from(max_delay)), ); backoff_delayer.delay().await; - while upgrade!(self.0)?.reconnect().await.is_err() { + while self + .0 + .upgrade() + .ok_or_else(|| tracerr::new!(ReconnectError::Detached))? + .reconnect() + .await + .is_err() + { backoff_delayer.delay().await; } diff --git a/jason/src/rpc/rpc_session.rs b/jason/src/rpc/rpc_session.rs index 76880203f..8ded73a56 100644 --- a/jason/src/rpc/rpc_session.rs +++ b/jason/src/rpc/rpc_session.rs @@ -41,7 +41,7 @@ pub enum SessionError { /// [`WebSocketRpcSession`] doesn't have any credentials to authorize with. #[display( - fmt = "RPC Session doesn't have any credentials to authorize with" + fmt = "RPC Session doesn't have any credentials to authorize with" )] NoCredentials, diff --git a/jason/src/rpc/websocket/client.rs b/jason/src/rpc/websocket/client.rs index 3d55f874e..d77f6a2f5 100644 --- a/jason/src/rpc/websocket/client.rs +++ b/jason/src/rpc/websocket/client.rs @@ -313,11 +313,11 @@ impl WebSocketRpcClient { settings.ping_interval_ms.into(), )), ) - .map_err(tracerr::wrap!(=> RpcClientError)) - .map_err(|e| { - log::error!("Failed to update socket settings: {}", e) - }) - .ok(); + .map_err(tracerr::wrap!(=> RpcClientError)) + .map_err(|e| { + log::error!("Failed to update socket settings: {}", e) + }) + .ok(); None } ServerMsg::Ping(_) => None, diff --git a/jason/src/utils/component.rs b/jason/src/utils/component.rs index bafe68681..06ebe4c1c 100644 --- a/jason/src/utils/component.rs +++ b/jason/src/utils/component.rs @@ -1,6 +1,6 @@ //! Implementation of the [`Component`]. -use std::rc::Rc; +use std::{fmt::Display, rc::Rc}; use derive_more::Deref; use futures::{future, Future, FutureExt as _, Stream, StreamExt}; @@ -116,18 +116,18 @@ impl WatchersSpawner { /// You can stop all listeners tasks spawned by this function by /// [`Drop`]ping [`Component`]. pub fn spawn(&mut self, mut rx: R, handle: F) - where - F: Fn(Rc, Rc, V) -> H + 'static, - R: Stream + Unpin + 'static, - H: Future> + 'static, - E: Display, + where + F: Fn(Rc, Rc, V) -> H + 'static, + R: Stream + Unpin + 'static, + H: Future> + 'static, + E: Display, { let obj = Rc::clone(&self.obj); let state = Rc::clone(&self.state); let (fut, handle) = future::abortable(async move { while let Some(value) = rx.next().await { if let Err(e) = - (handle)(Rc::clone(&obj), Rc::clone(&state), value).await + (handle)(Rc::clone(&obj), Rc::clone(&state), value).await { log::error!("{}", e); } diff --git a/jason/src/utils/mod.rs b/jason/src/utils/mod.rs index 438465c8e..e331d13ca 100644 --- a/jason/src/utils/mod.rs +++ b/jason/src/utils/mod.rs @@ -19,20 +19,6 @@ pub use self::{ resettable_delay::{resettable_delay_for, ResettableDelayHandle}, }; -/// Generates `upgrade!` macro which can upgrade [`Weak`] pointer, mapping it to -/// a [`Result`] with `$e` error. -/// -/// [`Weak`]: std::rc::Weak -macro_rules! gen_upgrade_macro { - ($e:expr) => { - macro_rules! upgrade { - ($v:expr) => { - $v.upgrade().ok_or_else(|| tracerr::new!($e)) - }; - } - }; -} - /// Wrapper around [`AbortHandle`] which aborts [`Future`] on [`Drop`]. /// /// [`Future`]: std::future::Future From dcd1b22d9e0143f68da1b701beffa1c673ac589a Mon Sep 17 00:00:00 2001 From: alexlapa Date: Tue, 9 Mar 2021 18:12:49 +0200 Subject: [PATCH 15/19] fix merge, review --- jason/src/api/wasm/room_handle.rs | 2 +- jason/src/room.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index 026029ce1..c877201ac 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -167,7 +167,7 @@ impl RoomHandle { Ok(JsValue::UNDEFINED) }) } - + // TODO: document mute/umute/enable/disable/local/remote errors section. /// Mutes outbound audio in this [`Room`]. /// /// [`Room`]: room::Room diff --git a/jason/src/room.rs b/jason/src/room.rs index 9ba9ed165..b86f5aab5 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -473,6 +473,7 @@ impl RoomHandle { Ok(()) } + // TODO: document mute/umute/enable/disable/local/remote errors section. /// Mutes outbound audio in this [`Room`]. /// /// # Errors From ae5bc5706bae81961d623e5d6aa0b67d45ecfed4 Mon Sep 17 00:00:00 2001 From: Semen Evdokimov Date: Tue, 9 Mar 2021 12:29:21 -0500 Subject: [PATCH 16/19] Add error docs --- jason/src/api/wasm/room_handle.rs | 82 ++++++++++++++++++++++++++++++- jason/src/room.rs | 54 +++++++++++++++----- 2 files changed, 123 insertions(+), 13 deletions(-) diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index c877201ac..666f496df 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -167,9 +167,15 @@ impl RoomHandle { Ok(JsValue::UNDEFINED) }) } - // TODO: document mute/umute/enable/disable/local/remote errors section. + /// Mutes outbound audio in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::unmute_audio`] was called while muting. + /// /// [`Room`]: room::Room pub fn mute_audio(&self) -> Promise { let this = self.0.clone(); @@ -182,6 +188,12 @@ impl RoomHandle { /// Unmutes outbound audio in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::mute_audio`] was called while unmuting. + /// /// [`Room`]: room::Room pub fn unmute_audio(&self) -> Promise { let this = self.0.clone(); @@ -194,6 +206,12 @@ impl RoomHandle { /// Mutes outbound video in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::unmute_video`] was called while muting. + /// /// [`Room`]: room::Room pub fn mute_video(&self, source_kind: Option) -> Promise { let this = self.0.clone(); @@ -208,6 +226,12 @@ impl RoomHandle { /// Unmutes outbound video in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::mute_video`] was called while unmuting. + /// /// [`Room`]: room::Room pub fn unmute_video( &self, @@ -225,6 +249,16 @@ impl RoomHandle { /// Disables outbound audio in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and ` MediaExchangeState of Sender can't be + /// transited into disabled state, because this Sender is required.` message + /// if server forbids audio track disabling. + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::enable_audio`] was called while disabling. + /// /// [`Room`]: room::Room pub fn disable_audio(&self) -> Promise { let this = self.0.clone(); @@ -237,6 +271,12 @@ impl RoomHandle { /// Enables outbound audio in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::disable_audio`] was called while enabling. + /// /// [`Room`]: room::Room pub fn enable_audio(&self) -> Promise { let this = self.0.clone(); @@ -250,6 +290,16 @@ impl RoomHandle { /// Disables outbound video. /// /// Affects only video with a specific [`MediaSourceKind`] if specified. + /// + /// # Errors + /// + /// With `MediaConnections` name and ` MediaExchangeState of Sender can't be + /// transited into disabled state, because this Sender is required.` message + /// if server forbids a video track disabling. + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::enable_video`] was called while disabling. pub fn disable_video( &self, source_kind: Option, @@ -268,6 +318,12 @@ impl RoomHandle { /// Enables outbound video. /// /// Affects only video with a specific [`MediaSourceKind`] if specified. + /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::disable_video`] was called while enabling. pub fn enable_video( &self, source_kind: Option, @@ -284,6 +340,12 @@ impl RoomHandle { /// Disables inbound audio in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::enable_remote_audio`] was called while disabling. + /// /// [`Room`]: room::Room pub fn disable_remote_audio(&self) -> Promise { let this = self.0.clone(); @@ -298,6 +360,12 @@ impl RoomHandle { /// Disables inbound video in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::enable_remote_video`] was called while disabling. + /// /// [`Room`]: room::Room pub fn disable_remote_video(&self) -> Promise { let this = self.0.clone(); @@ -312,6 +380,12 @@ impl RoomHandle { /// Enables inbound audio in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::disable_remote_audio`] was called while enabling. + /// /// [`Room`]: room::Room pub fn enable_remote_audio(&self) -> Promise { let this = self.0.clone(); @@ -324,6 +398,12 @@ impl RoomHandle { /// Enables inbound video in this [`Room`]. /// + /// # Errors + /// + /// With `MediaConnections` name and `MediaState of Sender transits into + /// opposite to expected MediaExchangeState` message if + /// [`RoomHandle::disable_remote_video`] was called while enabling. + /// /// [`Room`]: room::Room pub fn enable_remote_video(&self) -> Promise { let this = self.0.clone(); diff --git a/jason/src/room.rs b/jason/src/room.rs index b86f5aab5..6a813efa8 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -478,7 +478,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if muting audio is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::unmute_audio`] + /// was called while muting. #[inline] pub async fn mute_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -495,7 +497,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if unmuting audio is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::mute_audio`] was + /// called while unmuting. #[inline] pub async fn unmute_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -512,7 +516,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if muting video is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::unmute_video`] + /// was called while muting. #[inline] pub async fn mute_video( &self, @@ -532,7 +538,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if unmuting video is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::mute_video`] was + /// called while unmuting. #[inline] pub async fn unmute_video( &self, @@ -552,7 +560,12 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if disabling audio is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// CannotDisableRequiredSender)` if server forbids audio track disabling. + /// + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::enable_audio`] + /// was called while disabling. #[inline] pub async fn disable_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -569,7 +582,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if enabling audio is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::disable_audio`] + /// was called while enabling. #[inline] pub async fn enable_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -588,7 +603,12 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if disabling video is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// CannotDisableRequiredSender)` if server forbids some track disabling. + /// + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::enable_video`] + /// was called while disabling. #[inline] pub async fn disable_video( &self, @@ -610,7 +630,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if enabling video is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::disable_video`] + /// was called while enabling. #[inline] pub async fn enable_video( &self, @@ -630,7 +652,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if disabling remote audio is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if + /// [`RoomHandle::enable_remote_audio`] was called while disabling. #[inline] pub async fn disable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -647,7 +671,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if disabling remote video is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if + /// [`RoomHandle::enable_remote_video`] was called while disabling. #[inline] pub async fn disable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( @@ -664,7 +690,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if enabling remote audio is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if + /// [`RoomHandle::disable_remote_audio`] was called while enabling. #[inline] pub async fn enable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -681,7 +709,9 @@ impl RoomHandle { /// /// # Errors /// - /// Errors if enabling remote video is failed. + /// With `RoomError::MediaConnections(MediaConnectionsError:: + /// MediaStateTransitsIntoOppositeState)` if + /// [`RoomHandle::disable_remote_video`] was called while enabling. #[inline] pub async fn enable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( From ae3dab6c3927c7b6aa0f4217bd8db8f7374d4c9b Mon Sep 17 00:00:00 2001 From: alexlapa Date: Wed, 10 Mar 2021 10:26:03 +0200 Subject: [PATCH 17/19] corrections --- Cargo.lock | 330 ++++++++++++------------------ Makefile | 1 + jason/src/api/wasm/room_handle.rs | 76 +++---- jason/src/room.rs | 129 ++++++++---- 4 files changed, 251 insertions(+), 285 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44938c724..9e6638e98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,10 +123,10 @@ dependencies = [ "pin-project 1.0.5", "rand 0.7.3", "regex", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "serde_urlencoded 0.7.0", - "sha-1 0.9.4", + "sha-1", "slab", "time 0.2.25", ] @@ -138,7 +138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" dependencies = [ "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -151,7 +151,7 @@ dependencies = [ "http", "log", "regex", - "serde 1.0.123", + "serde 1.0.124", ] [[package]] @@ -290,7 +290,7 @@ dependencies = [ "mime", "pin-project 1.0.5", "regex", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "serde_urlencoded 0.7.0", "socket2", @@ -323,7 +323,7 @@ checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -334,7 +334,7 @@ checksum = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -481,7 +481,7 @@ checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -505,7 +505,7 @@ dependencies = [ "memchr", "num_cpus", "once_cell", - "pin-project-lite 0.2.5", + "pin-project-lite 0.2.6", "pin-utils", "slab", "wasm-bindgen-futures", @@ -539,7 +539,7 @@ checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -550,7 +550,7 @@ checksum = "a3548b8efc9f8e8a5a0a2808c5bd8451a9031b9e5b879a79590304ae928b0a70" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -561,13 +561,13 @@ checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "async-trait" -version = "0.1.42" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d" +checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -612,7 +612,7 @@ dependencies = [ "mime", "percent-encoding", "rand 0.7.3", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "serde_urlencoded 0.7.0", ] @@ -666,34 +666,13 @@ dependencies = [ "constant_time_eq", ] -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.4", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -745,12 +724,6 @@ version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - [[package]] name = "byteorder" version = "1.4.2" @@ -840,7 +813,7 @@ dependencies = [ "bytes 1.0.1", "futures-util", "memchr", - "pin-project-lite 0.2.5", + "pin-project-lite 0.2.6", "tokio 0.2.25", ] @@ -862,7 +835,7 @@ dependencies = [ "lazy_static", "nom", "rust-ini", - "serde 1.0.123", + "serde 1.0.124", "serde-hjson", "serde_json", "toml", @@ -1008,7 +981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19" dependencies = [ "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1046,7 +1019,7 @@ dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", "regex", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1056,7 +1029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed431abf442833fd62ad7cc527a3833d969155c803f0dcf7f8a68db8adddc4c5" dependencies = [ "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1090,7 +1063,7 @@ dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", "strsim 0.9.3", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1104,7 +1077,7 @@ dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", "strsim 0.10.0", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1115,7 +1088,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core 0.10.2", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1126,7 +1099,7 @@ checksum = "c0220073ce504f12a70efc4e7cdaea9e9b1b324872e7ad96a208056d7a638b81" dependencies = [ "darling_core 0.12.2", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1139,7 +1112,7 @@ dependencies = [ "config", "crossbeam-queue", "num_cpus", - "serde 1.0.123", + "serde 1.0.124", "tokio 0.2.25", ] @@ -1155,7 +1128,7 @@ dependencies = [ "futures 0.3.13", "log", "redis", - "serde 1.0.123", + "serde 1.0.124", ] [[package]] @@ -1166,7 +1139,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1179,7 +1152,7 @@ dependencies = [ "derive_builder_core", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1191,7 +1164,7 @@ dependencies = [ "darling 0.10.2", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1202,7 +1175,7 @@ checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1211,22 +1184,13 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.4", + "generic-array", ] [[package]] @@ -1298,7 +1262,7 @@ dependencies = [ "heck", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1325,16 +1289,10 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "synstructure", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fantoccini" version = "0.17.3" @@ -1349,9 +1307,9 @@ dependencies = [ "hyper 0.14.4", "hyper-tls", "mime", - "serde 1.0.123", + "serde 1.0.124", "serde_json", - "tokio 1.2.0", + "tokio 1.3.0", "url", "webdriver", ] @@ -1536,7 +1494,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.5", + "pin-project-lite 0.2.6", "waker-fn", ] @@ -1549,7 +1507,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1584,7 +1542,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.5", + "pin-project-lite 0.2.6", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1606,15 +1564,6 @@ version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.14.4" @@ -1649,16 +1598,16 @@ dependencies = [ [[package]] name = "gherkin_rust" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f70e36c2b9e5ec714060599e3a983dc7a9123f32c5c63ee638c1e024f36d5c1" +checksum = "68ff71b5e012707c7c18bdb710e07736898aba0451f6ffbd435c892dd993053c" dependencies = [ "heck", "peg", "quote 1.0.9", - "serde 1.0.123", + "serde 1.0.124", "serde_json", - "syn 1.0.60", + "syn 1.0.63", "textwrap 0.12.1", "thiserror", "typed-builder", @@ -1672,7 +1621,7 @@ checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -1752,8 +1701,8 @@ dependencies = [ "http", "indexmap", "slab", - "tokio 1.2.0", - "tokio-util 0.6.3", + "tokio 1.3.0", + "tokio-util 0.6.4", "tracing", ] @@ -1765,9 +1714,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" [[package]] name = "headers" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62689dc57c7456e69712607ffcbd0aa1dfcccf9af73727e9b25bc1825375cac3" +checksum = "f0b7591fb62902706ae8e7aaff416b1b0fa2c0fd0878b46dc13baa3712d8a855" dependencies = [ "base64 0.13.0", "bitflags", @@ -1775,7 +1724,7 @@ dependencies = [ "headers-core", "http", "mime", - "sha-1 0.8.2", + "sha-1", "time 0.1.43", ] @@ -1873,7 +1822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac34a56cfd4acddb469cc7fff187ed5ac36f498ba085caf8bbc725e3ff474058" dependencies = [ "humantime", - "serde 1.0.123", + "serde 1.0.124", ] [[package]] @@ -1918,7 +1867,7 @@ dependencies = [ "itoa", "pin-project 1.0.5", "socket2", - "tokio 1.2.0", + "tokio 1.3.0", "tower-service", "tracing", "want", @@ -1933,7 +1882,7 @@ dependencies = [ "bytes 1.0.1", "hyper 0.14.4", "native-tls", - "tokio 1.2.0", + "tokio 1.3.0", "tokio-native-tls", ] @@ -1974,9 +1923,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" +checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" dependencies = [ "autocfg", "hashbrown", @@ -2016,7 +1965,7 @@ checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -2125,9 +2074,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213" +checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" [[package]] name = "linked-hash-map" @@ -2232,7 +2181,7 @@ dependencies = [ "reqwest", "rust-argon2", "rust-crypto", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "serde_yaml", "serial_test", @@ -2246,8 +2195,8 @@ dependencies = [ "subtle", "tempfile", "tokio 0.2.25", - "tokio 1.2.0", - "tokio-util 0.6.3", + "tokio 1.3.0", + "tokio-util 0.6.4", "toml", "tonic", "url", @@ -2262,7 +2211,7 @@ dependencies = [ "async-trait", "derive_more", "medea-macro 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "serde_with", ] @@ -2276,7 +2225,7 @@ dependencies = [ "async-trait", "derive_more", "medea-macro 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "serde_with", ] @@ -2295,7 +2244,7 @@ dependencies = [ "humantime-serde", "medea-control-api-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "slog", "slog-async", @@ -2381,7 +2330,7 @@ dependencies = [ "medea-reactive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "mockall", "predicates-tree", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "tracerr", "url", @@ -2402,7 +2351,7 @@ dependencies = [ "medea-jason", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "synstructure", ] @@ -2415,7 +2364,7 @@ dependencies = [ "Inflector", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "synstructure", ] @@ -2563,7 +2512,7 @@ dependencies = [ "cfg-if 1.0.0", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -2687,12 +2636,6 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - [[package]] name = "opaque-debug" version = "0.3.0" @@ -2838,7 +2781,7 @@ checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -2849,7 +2792,7 @@ checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -2860,9 +2803,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cf491442e4b033ed1c722cb9f0df5fcfcf4de682466c46469c36bc47dc5548a" +checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" [[package]] name = "pin-utils" @@ -3001,7 +2944,7 @@ dependencies = [ "itertools 0.8.2", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -3251,9 +3194,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0460542b551950620a3648c6aa23318ac6b3cd779114bd873209e6e8b5eb1c34" +checksum = "bf12057f289428dbf5c591c74bf10392e4a8003f993405a902f20117019022d4" dependencies = [ "base64 0.13.0", "bytes 1.0.1", @@ -3271,11 +3214,11 @@ dependencies = [ "mime", "native-tls", "percent-encoding", - "pin-project-lite 0.2.5", - "serde 1.0.123", + "pin-project-lite 0.2.6", + "serde 1.0.124", "serde_json", "serde_urlencoded 0.7.0", - "tokio 1.2.0", + "tokio 1.3.0", "tokio-native-tls", "url", "wasm-bindgen", @@ -3390,9 +3333,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfd318104249865096c8da1dfabf09ddbb6d0330ea176812a62ec75e40c4166" +checksum = "d493c5f39e02dfb062cd8f33301f90f9b13b650e8c1b1d0fd75c19dd64bff69d" dependencies = [ "bitflags", "core-foundation", @@ -3434,9 +3377,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" [[package]] name = "serde" -version = "1.0.123" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" +checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" dependencies = [ "serde_derive", ] @@ -3456,13 +3399,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.123" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" +checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -3473,7 +3416,7 @@ checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" dependencies = [ "itoa", "ryu", - "serde 1.0.123", + "serde 1.0.124", ] [[package]] @@ -3493,7 +3436,7 @@ checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" dependencies = [ "dtoa", "itoa", - "serde 1.0.123", + "serde 1.0.124", "url", ] @@ -3506,7 +3449,7 @@ dependencies = [ "form_urlencoded", "itoa", "ryu", - "serde 1.0.123", + "serde 1.0.124", ] [[package]] @@ -3515,7 +3458,7 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b44be9227e214a0420707c9ca74c2d4991d9955bae9415a8f93f05cebf561be5" dependencies = [ - "serde 1.0.123", + "serde 1.0.124", "serde_with_macros", ] @@ -3528,7 +3471,7 @@ dependencies = [ "darling 0.12.2", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -3539,7 +3482,7 @@ checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" dependencies = [ "dtoa", "linked-hash-map 0.5.4", - "serde 1.0.123", + "serde 1.0.124", "yaml-rust", ] @@ -3562,19 +3505,7 @@ checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", -] - -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", + "syn 1.0.63", ] [[package]] @@ -3583,11 +3514,11 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfebf75d25bd900fd1e7d11501efab59bc846dbc76196839663e6637bba9f25f" dependencies = [ - "block-buffer 0.9.0", + "block-buffer", "cfg-if 1.0.0", "cpuid-bool", - "digest 0.9.0", - "opaque-debug 0.3.0", + "digest", + "opaque-debug", ] [[package]] @@ -3661,7 +3592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a" dependencies = [ "chrono", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "slog", ] @@ -3715,7 +3646,7 @@ checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -3766,9 +3697,9 @@ checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "serde 1.0.123", + "serde 1.0.124", "serde_derive", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -3780,11 +3711,11 @@ dependencies = [ "base-x", "proc-macro2 1.0.24", "quote 1.0.9", - "serde 1.0.123", + "serde 1.0.124", "serde_derive", "serde_json", "sha1", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -3830,9 +3761,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.60" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" +checksum = "8fd9bc7ccc2688b3344c2f48b9b546648b25ce0b20fc717ee7fa7981a8ca9717" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", @@ -3847,7 +3778,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "unicode-xid 0.2.1", ] @@ -3937,7 +3868,7 @@ checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -4003,7 +3934,7 @@ dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", "standback", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -4046,9 +3977,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a" +checksum = "8d56477f6ed99e10225f38f9f75f872f29b8b8bd8c0b946f63345bb144e9eeda" dependencies = [ "autocfg", "bytes 1.0.1", @@ -4056,7 +3987,7 @@ dependencies = [ "memchr", "mio 0.7.9", "num_cpus", - "pin-project-lite 0.2.5", + "pin-project-lite 0.2.6", "tokio-macros 1.1.0", ] @@ -4068,7 +3999,7 @@ checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -4079,7 +4010,7 @@ checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -4089,7 +4020,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" dependencies = [ "native-tls", - "tokio 1.2.0", + "tokio 1.3.0", ] [[package]] @@ -4109,16 +4040,16 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebb7cb2f00c5ae8df755b252306272cd1790d39728363936e01827e11f0b017b" +checksum = "ec31e5cc6b46e653cf57762f36f71d5e6386391d88a72fd6db4508f8f676fb29" dependencies = [ "bytes 1.0.1", "futures-core", "futures-sink", "log", - "pin-project-lite 0.2.5", - "tokio 1.2.0", + "pin-project-lite 0.2.6", + "tokio 1.3.0", ] [[package]] @@ -4127,7 +4058,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" dependencies = [ - "serde 1.0.123", + "serde 1.0.124", ] [[package]] @@ -4169,7 +4100,7 @@ dependencies = [ "proc-macro2 1.0.24", "prost-build", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -4367,7 +4298,7 @@ checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" dependencies = [ "cfg-if 1.0.0", "log", - "pin-project-lite 0.2.5", + "pin-project-lite 0.2.6", "tracing-attributes", "tracing-core", ] @@ -4380,7 +4311,7 @@ checksum = "a8a9bd1db7706f2373a190b0d067146caa39350c486f3d455b0e33b431f94c07" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -4410,12 +4341,12 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" [[package]] name = "trust-dns-proto" -version = "0.19.6" +version = "0.19.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53861fcb288a166aae4c508ae558ed18b53838db728d4d310aad08270a7d4c2b" +checksum = "1cad71a0c0d68ab9941d2fb6e82f8fb2e86d9945b94e1661dd0aaea2b88215a9" dependencies = [ "async-trait", - "backtrace", + "cfg-if 1.0.0", "enum-as-inner", "futures 0.3.13", "idna", @@ -4430,11 +4361,10 @@ dependencies = [ [[package]] name = "trust-dns-resolver" -version = "0.19.6" +version = "0.19.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6759e8efc40465547b0dfce9500d733c65f969a4cbbfbe3ccf68daaa46ef179e" +checksum = "710f593b371175db53a26d0b38ed2978fafb9e9e8d3868b1acd753ea18df0ceb" dependencies = [ - "backtrace", "cfg-if 0.1.10", "futures 0.3.13", "ipconfig", @@ -4462,7 +4392,7 @@ checksum = "f85f4270f4f449a3f2c0cf2aecc8415e388a597aeacc7d55fc749c5c968c8533" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", ] [[package]] @@ -4625,7 +4555,7 @@ dependencies = [ "mime_guess", "pin-project 0.4.27", "scoped-tls", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "serde_urlencoded 0.6.1", "tokio 0.2.25", @@ -4654,7 +4584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" dependencies = [ "cfg-if 1.0.0", - "serde 1.0.123", + "serde 1.0.124", "serde_json", "wasm-bindgen-macro", ] @@ -4670,7 +4600,7 @@ dependencies = [ "log", "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "wasm-bindgen-shared", ] @@ -4704,7 +4634,7 @@ checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.9", - "syn 1.0.60", + "syn 1.0.63", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4771,7 +4701,7 @@ dependencies = [ "cookie 0.12.0", "http", "log", - "serde 1.0.123", + "serde 1.0.124", "serde_derive", "serde_json", "time 0.1.43", diff --git a/Makefile b/Makefile index 002a7e1b8..b4ab8b68f 100644 --- a/Makefile +++ b/Makefile @@ -159,6 +159,7 @@ down.medea: docker.down.medea up.control: cargo build -p medea-control-api-mock + make wait.port port=6565 cargo run -p medea-control-api-mock $(if $(call eq,$(background),yes),&,) diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index 666f496df..74282e8f0 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -172,9 +172,8 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::unmute_audio`] was called while muting. + /// With `name = 'MediaConnections'` if [`RoomHandle::unmute_audio`] is + /// called while muting or server didn't approve state transition. /// /// [`Room`]: room::Room pub fn mute_audio(&self) -> Promise { @@ -190,9 +189,8 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::mute_audio`] was called while unmuting. + /// With `name = 'MediaConnections'` if [`RoomHandle::mute_audio`] is + /// called while unmuting or server didn't approve state transition. /// /// [`Room`]: room::Room pub fn unmute_audio(&self) -> Promise { @@ -208,9 +206,8 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::unmute_video`] was called while muting. + /// With `name = 'MediaConnections'` if [`RoomHandle::unmute_video`] is + /// called while muting or server didn't approve state transition. /// /// [`Room`]: room::Room pub fn mute_video(&self, source_kind: Option) -> Promise { @@ -228,9 +225,8 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::mute_video`] was called while unmuting. + /// With `name = 'MediaConnections'` if [`RoomHandle::mute_video`] is + /// called while unmuting or server didn't approve state transition. /// /// [`Room`]: room::Room pub fn unmute_video( @@ -251,13 +247,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and ` MediaExchangeState of Sender can't be - /// transited into disabled state, because this Sender is required.` message - /// if server forbids audio track disabling. - /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::enable_audio`] was called while disabling. + /// With `name = 'MediaConnections'` if target sender is configured as + /// `required` by media server or [`RoomHandle::enable_audio`] is called + /// while disabling or server didn't approve state transition. /// /// [`Room`]: room::Room pub fn disable_audio(&self) -> Promise { @@ -273,9 +265,11 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::disable_audio`] was called while enabling. + /// With `name = 'MediaConnections'` if [`RoomHandle::disable_audio`] was + /// called while enabling or server didn't approve state transition. + /// + /// With `name = 'MediaManagerError'` if media acquisition request to User + /// Agent failed. /// /// [`Room`]: room::Room pub fn enable_audio(&self) -> Promise { @@ -293,13 +287,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and ` MediaExchangeState of Sender can't be - /// transited into disabled state, because this Sender is required.` message - /// if server forbids a video track disabling. - /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::enable_video`] was called while disabling. + /// With `name = 'MediaConnections'` if target sender is configured as + /// `required` by media server or [`RoomHandle::enable_video`] is called + /// while disabling or server didn't approve state transition. pub fn disable_video( &self, source_kind: Option, @@ -321,9 +311,11 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::disable_video`] was called while enabling. + /// With `name = 'MediaConnections'` if [`RoomHandle::disable_video`] was + /// called while enabling or server didn't approve state transition. + /// + /// With `name = 'MediaManagerError'` if media acquisition request to User + /// Agent failed. pub fn enable_video( &self, source_kind: Option, @@ -342,9 +334,8 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::enable_remote_audio`] was called while disabling. + /// With `name = 'MediaConnections'` if [`RoomHandle::enable_remote_audio`] + /// is called while disabling or server didn't approve state transition. /// /// [`Room`]: room::Room pub fn disable_remote_audio(&self) -> Promise { @@ -362,9 +353,8 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::enable_remote_video`] was called while disabling. + /// With `name = 'MediaConnections'` if [`RoomHandle::enable_remote_video`] + /// is called while disabling or server didn't approve state transition. /// /// [`Room`]: room::Room pub fn disable_remote_video(&self) -> Promise { @@ -382,9 +372,8 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::disable_remote_audio`] was called while enabling. + /// With `name = 'MediaConnections'` if [`RoomHandle::disable_remote_audio`] + /// is called while enabling or server didn't approve state transition. /// /// [`Room`]: room::Room pub fn enable_remote_audio(&self) -> Promise { @@ -400,9 +389,8 @@ impl RoomHandle { /// /// # Errors /// - /// With `MediaConnections` name and `MediaState of Sender transits into - /// opposite to expected MediaExchangeState` message if - /// [`RoomHandle::disable_remote_video`] was called while enabling. + /// With `name = 'MediaConnections'` if [`RoomHandle::disable_remote_video`] + /// is called while enabling or server didn't approve state transition. /// /// [`Room`]: room::Room pub fn enable_remote_video(&self) -> Promise { diff --git a/jason/src/room.rs b/jason/src/room.rs index 6a813efa8..e66eb8fa7 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -473,14 +473,16 @@ impl RoomHandle { Ok(()) } - // TODO: document mute/umute/enable/disable/local/remote errors section. /// Mutes outbound audio in this [`Room`]. /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::unmute_audio`] - /// was called while muting. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::unmute_audio`] is called while muting or media server + /// didn't approve state transition. #[inline] pub async fn mute_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -497,9 +499,12 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::mute_audio`] was - /// called while unmuting. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::mute_audio`] is called while muting or media server + /// didn't approve state transition. #[inline] pub async fn unmute_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -516,9 +521,12 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::unmute_video`] - /// was called while muting. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::unmute_video`] is called while muting or media server + /// didn't approve state transition. #[inline] pub async fn mute_video( &self, @@ -538,9 +546,12 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::mute_video`] was - /// called while unmuting. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::mute_video`] is called while muting or media server + /// didn't approve state transition. #[inline] pub async fn unmute_video( &self, @@ -560,12 +571,16 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// CannotDisableRequiredSender)` if server forbids audio track disabling. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::enable_audio`] - /// was called while disabling. + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::CannotDisableRequiredSender`] if audio track + /// sender is configured as `required`. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::enable_audio`] is called while disabling or server didn't + /// approve state transition. #[inline] pub async fn disable_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -582,9 +597,17 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::disable_audio`] - /// was called while enabling. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::disable_audio`] is called while enabling or server didn't + /// approve state transition. + /// + /// With [`RoomError::MediaManagerError`] with + /// [`MediaManagerError::CouldNotGetMediaDevices`] or + /// [`MediaManagerError::GetUserMediaFailed`] if media acquisition request + /// failed. #[inline] pub async fn enable_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -603,12 +626,16 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// CannotDisableRequiredSender)` if server forbids some track disabling. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::enable_video`] - /// was called while disabling. + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::CannotDisableRequiredSender`] video track + /// sender is configured as `required`. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::enable_video`] is called while disabling or server didn't + /// approve state transition. #[inline] pub async fn disable_video( &self, @@ -630,9 +657,17 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if [`RoomHandle::disable_video`] - /// was called while enabling. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::disable_video`] is called while enabling or server didn't + /// approve state transition. + /// + /// With [`RoomError::MediaManagerError`] with + /// [`MediaManagerError::CouldNotGetMediaDevices`] or + /// [`MediaManagerError::GetUserMediaFailed`] if media acquisition request + /// failed. #[inline] pub async fn enable_video( &self, @@ -652,9 +687,12 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if - /// [`RoomHandle::enable_remote_audio`] was called while disabling. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::enable_remote_audio`] is called while disabling or media + /// server didn't approve state transition. #[inline] pub async fn disable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -671,9 +709,12 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if - /// [`RoomHandle::enable_remote_video`] was called while disabling. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::enable_remote_video`] is called while disabling or media + /// server didn't approve state transition. #[inline] pub async fn disable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( @@ -690,9 +731,12 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if - /// [`RoomHandle::disable_remote_audio`] was called while enabling. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::disable_remote_audio`] is called while enabling or media + /// server didn't approve state transition. #[inline] pub async fn enable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -709,9 +753,12 @@ impl RoomHandle { /// /// # Errors /// - /// With `RoomError::MediaConnections(MediaConnectionsError:: - /// MediaStateTransitsIntoOppositeState)` if - /// [`RoomHandle::disable_remote_video`] was called while enabling. + /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// + /// With [`RoomError::MediaConnections`] with + /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if + /// [`RoomHandle::disable_remote_video`] is called while enabling or media + /// server didn't approve state transition. #[inline] pub async fn enable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( From 4326a31d60b3e2d1e762bb868db2d33a2ea81a34 Mon Sep 17 00:00:00 2001 From: alexlapa Date: Wed, 10 Mar 2021 13:08:32 +0200 Subject: [PATCH 18/19] corrections --- jason/src/api/wasm/jason_error.rs | 2 +- jason/src/media/manager.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs index 97009274d..e38cb3c49 100644 --- a/jason/src/api/wasm/jason_error.rs +++ b/jason/src/api/wasm/jason_error.rs @@ -25,7 +25,7 @@ pub struct JasonError { impl JasonError { /// Returns a name of this error. pub fn name(&self) -> String { - self.name.to_string() + self.name.to_owned() } /// Returns a message of this errors. diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index 3689c2a57..fa3426450 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -343,6 +343,18 @@ impl MediaManagerHandle { /// # Errors /// /// With [`MediaManagerError::Detached`] if [`Weak`] pointer upgrade fails. + /// + /// With [`MediaManagerError::CouldNotGetMediaDevices`] if media devices + /// request to UA failed. + /// + /// With [`MediaManagerError::GetUserMediaFailed`] if [getUserMedia()][1] + /// request failed. + /// + /// With [`MediaManagerError::GetDisplayMediaFailed`] if + /// [getDisplayMedia()][2] request failed. + /// + /// [1]: https://tinyurl.com/w3-streams#dom-mediadevices-getusermedia + /// [2]: https://w3.org/TR/screen-capture/#dom-mediadevices-getdisplaymedia pub async fn init_local_tracks( &self, caps: MediaStreamSettings, From ed930d953d668c1fbd1a16c2cacf74801756c074 Mon Sep 17 00:00:00 2001 From: tyranron Date: Wed, 10 Mar 2021 16:43:44 +0200 Subject: [PATCH 19/19] Corrections --- .../api/wasm/constraints_update_exception.rs | 2 +- jason/src/api/wasm/jason_error.rs | 15 ++- jason/src/api/wasm/media_manager_handle.rs | 2 +- jason/src/api/wasm/media_stream_settings.rs | 3 +- jason/src/api/wasm/mod.rs | 8 +- jason/src/api/wasm/reconnect_handle.rs | 2 +- jason/src/api/wasm/room_handle.rs | 66 ++++++----- jason/src/connection.rs | 3 - jason/src/media/manager.rs | 2 +- jason/src/peer/mod.rs | 8 +- jason/src/room.rs | 112 +++++++++--------- jason/src/rpc/mod.rs | 2 +- jason/src/rpc/reconnect_handle.rs | 12 +- jason/src/rpc/websocket/client.rs | 4 +- 14 files changed, 131 insertions(+), 110 deletions(-) diff --git a/jason/src/api/wasm/constraints_update_exception.rs b/jason/src/api/wasm/constraints_update_exception.rs index 8ad8aafa7..2881073d4 100644 --- a/jason/src/api/wasm/constraints_update_exception.rs +++ b/jason/src/api/wasm/constraints_update_exception.rs @@ -9,7 +9,7 @@ use wasm_bindgen::prelude::*; use crate::room; -use super::jason_error::JasonError; +use super::JasonError; /// Exception returned from [`RoomHandle::set_local_media_settings()`][1]. /// diff --git a/jason/src/api/wasm/jason_error.rs b/jason/src/api/wasm/jason_error.rs index e38cb3c49..2bbb0e2ae 100644 --- a/jason/src/api/wasm/jason_error.rs +++ b/jason/src/api/wasm/jason_error.rs @@ -15,30 +15,41 @@ use crate::{platform, utils::JsCaused}; #[derive(From, Clone, Debug, Display)] #[display(fmt = "{}: {}\n{}", name, message, trace)] pub struct JasonError { + /// Name of this [`JasonError`]. name: &'static str, + + /// Message describing this [`JasonError`]. message: String, + + /// [`Trace`] information of this [`JasonError`]. trace: Trace, + + /// Optional cause of this [`JasonError`] as a JS side error. source: Option, } #[wasm_bindgen] impl JasonError { /// Returns a name of this error. + #[must_use] pub fn name(&self) -> String { self.name.to_owned() } - /// Returns a message of this errors. + /// Returns a message of this error. + #[must_use] pub fn message(&self) -> String { self.message.clone() } /// Returns a trace information of this error. + #[must_use] pub fn trace(&self) -> String { self.trace.to_string() } /// Returns a JS side error if it's the cause. + #[must_use] pub fn source(&self) -> Option { self.source.clone().and_then(|e| e.sys_cause) } @@ -48,6 +59,7 @@ impl From<(E, Trace)> for JasonError where E::Error: Into, { + #[inline] fn from((err, trace): (E, Trace)) -> Self { Self { name: err.name(), @@ -62,6 +74,7 @@ impl From> for JasonError where E::Error: Into, { + #[inline] fn from(traced: Traced) -> Self { Self::from(traced.into_parts()) } diff --git a/jason/src/api/wasm/media_manager_handle.rs b/jason/src/api/wasm/media_manager_handle.rs index 28d677cbd..9700c7df0 100644 --- a/jason/src/api/wasm/media_manager_handle.rs +++ b/jason/src/api/wasm/media_manager_handle.rs @@ -12,7 +12,7 @@ use crate::{ media, }; -use super::jason_error::JasonError; +use super::JasonError; /// [`MediaManagerHandle`] is a weak reference to a [`MediaManager`]. /// diff --git a/jason/src/api/wasm/media_stream_settings.rs b/jason/src/api/wasm/media_stream_settings.rs index 8c01d3498..99ff4927c 100644 --- a/jason/src/api/wasm/media_stream_settings.rs +++ b/jason/src/api/wasm/media_stream_settings.rs @@ -71,7 +71,8 @@ impl AudioTrackConstraints { #[derive(From, Into)] pub struct DeviceVideoTrackConstraints(media::DeviceVideoTrackConstraints); -/// Constraints applicable to video tracks that are sourced from screen-capture. +/// Constraints applicable to video tracks that are sourced from a screen +/// capturing. #[wasm_bindgen] impl DeviceVideoTrackConstraints { /// Creates new [`DeviceVideoTrackConstraints`] with none constraints diff --git a/jason/src/api/wasm/mod.rs b/jason/src/api/wasm/mod.rs index 6481556de..72d7e5e5c 100644 --- a/jason/src/api/wasm/mod.rs +++ b/jason/src/api/wasm/mod.rs @@ -3,9 +3,6 @@ //! //! [`Jason`]: crate::api::Jason -use derive_more::Display; -use wasm_bindgen::prelude::*; - pub mod connection_handle; pub mod constraints_update_exception; pub mod input_device_info; @@ -19,6 +16,11 @@ pub mod remote_media_track; pub mod room_close_reason; pub mod room_handle; +use derive_more::Display; +use wasm_bindgen::prelude::*; + +pub use self::jason_error::JasonError; + /// [MediaStreamTrack.kind][1] representation. /// /// [1]: https://w3.org/TR/mediacapture-streams/#dom-mediastreamtrack-kind diff --git a/jason/src/api/wasm/reconnect_handle.rs b/jason/src/api/wasm/reconnect_handle.rs index 9e86bea81..948f3ad07 100644 --- a/jason/src/api/wasm/reconnect_handle.rs +++ b/jason/src/api/wasm/reconnect_handle.rs @@ -7,7 +7,7 @@ use wasm_bindgen_futures::future_to_promise; use crate::rpc; -use super::jason_error::JasonError; +use super::JasonError; /// Handle that JS side can reconnect to a media server with when a connection /// is lost. diff --git a/jason/src/api/wasm/room_handle.rs b/jason/src/api/wasm/room_handle.rs index 74282e8f0..76cd2069d 100644 --- a/jason/src/api/wasm/room_handle.rs +++ b/jason/src/api/wasm/room_handle.rs @@ -12,7 +12,7 @@ use crate::{ room, }; -use super::jason_error::JasonError; +use super::JasonError; /// JS side handle to a [`Room`] where all the media happens. /// @@ -172,8 +172,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::unmute_audio`] is - /// called while muting or server didn't approve state transition. + /// With `name = 'MediaConnections'` if [`RoomHandle::unmute_audio()`] was + /// called while muting or a media server didn't approve this state + /// transition. /// /// [`Room`]: room::Room pub fn mute_audio(&self) -> Promise { @@ -189,8 +190,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::mute_audio`] is - /// called while unmuting or server didn't approve state transition. + /// With `name = 'MediaConnections'` if [`RoomHandle::mute_audio()`] was + /// called while unmuting or a media server didn't approve this state + /// transition. /// /// [`Room`]: room::Room pub fn unmute_audio(&self) -> Promise { @@ -206,8 +208,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::unmute_video`] is - /// called while muting or server didn't approve state transition. + /// With `name = 'MediaConnections'` if [`RoomHandle::unmute_video()`] was + /// called while muting or a media server didn't approve this state + /// transition. /// /// [`Room`]: room::Room pub fn mute_video(&self, source_kind: Option) -> Promise { @@ -225,8 +228,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::mute_video`] is - /// called while unmuting or server didn't approve state transition. + /// With `name = 'MediaConnections'` if [`RoomHandle::mute_video()`] was + /// called while unmuting or a media server didn't approve this state + /// transition. /// /// [`Room`]: room::Room pub fn unmute_video( @@ -247,9 +251,10 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if target sender is configured as - /// `required` by media server or [`RoomHandle::enable_audio`] is called - /// while disabling or server didn't approve state transition. + /// With `name = 'MediaConnections'` if the target sender is configured as + /// `required` by a media server or [`RoomHandle::enable_audio()`] was + /// called while disabling or a media server didn't approve this state + /// transition. /// /// [`Room`]: room::Room pub fn disable_audio(&self) -> Promise { @@ -265,8 +270,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::disable_audio`] was - /// called while enabling or server didn't approve state transition. + /// With `name = 'MediaConnections'` if [`RoomHandle::disable_audio()`] was + /// called while enabling or a media server didn't approve this state + /// transition. /// /// With `name = 'MediaManagerError'` if media acquisition request to User /// Agent failed. @@ -287,9 +293,10 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if target sender is configured as - /// `required` by media server or [`RoomHandle::enable_video`] is called - /// while disabling or server didn't approve state transition. + /// With `name = 'MediaConnections'` if the target sender is configured as + /// `required` by a media server or [`RoomHandle::enable_video()`] was + /// called while disabling or a media server didn't approve this state + /// transition. pub fn disable_video( &self, source_kind: Option, @@ -311,8 +318,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::disable_video`] was - /// called while enabling or server didn't approve state transition. + /// With `name = 'MediaConnections'` if [`RoomHandle::disable_video()`] was + /// called while enabling or a media server didn't approve this state + /// transition. /// /// With `name = 'MediaManagerError'` if media acquisition request to User /// Agent failed. @@ -334,8 +342,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::enable_remote_audio`] - /// is called while disabling or server didn't approve state transition. + /// With `name = 'MediaConnections'` if + /// [`RoomHandle::enable_remote_audio()`] was called while disabling or a + /// media server didn't approve this state transition. /// /// [`Room`]: room::Room pub fn disable_remote_audio(&self) -> Promise { @@ -353,8 +362,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::enable_remote_video`] - /// is called while disabling or server didn't approve state transition. + /// With `name = 'MediaConnections'` if + /// [`RoomHandle::enable_remote_video()`] was called while disabling or + /// a media server didn't approve this state transition. /// /// [`Room`]: room::Room pub fn disable_remote_video(&self) -> Promise { @@ -372,8 +382,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::disable_remote_audio`] - /// is called while enabling or server didn't approve state transition. + /// With `name = 'MediaConnections'` if + /// [`RoomHandle::disable_remote_audio()`] was called while enabling or a + /// media server didn't approve this state transition. /// /// [`Room`]: room::Room pub fn enable_remote_audio(&self) -> Promise { @@ -389,8 +400,9 @@ impl RoomHandle { /// /// # Errors /// - /// With `name = 'MediaConnections'` if [`RoomHandle::disable_remote_video`] - /// is called while enabling or server didn't approve state transition. + /// With `name = 'MediaConnections'` if + /// [`RoomHandle::disable_remote_video()`] was called while enabling or a + /// media server didn't approve this state transition. /// /// [`Room`]: room::Room pub fn enable_remote_video(&self) -> Promise { diff --git a/jason/src/connection.rs b/jason/src/connection.rs index 96e312cfc..6cff08a88 100644 --- a/jason/src/connection.rs +++ b/jason/src/connection.rs @@ -1,8 +1,5 @@ //! [`Connection`] with a specific remote `Member`. -// TODO: Remove when moving `JasonError` to `api::wasm`. -#![allow(clippy::missing_errors_doc)] - use std::{ cell::{Cell, RefCell}, collections::{HashMap, HashSet}, diff --git a/jason/src/media/manager.rs b/jason/src/media/manager.rs index fa3426450..d57bb7284 100644 --- a/jason/src/media/manager.rs +++ b/jason/src/media/manager.rs @@ -345,7 +345,7 @@ impl MediaManagerHandle { /// With [`MediaManagerError::Detached`] if [`Weak`] pointer upgrade fails. /// /// With [`MediaManagerError::CouldNotGetMediaDevices`] if media devices - /// request to UA failed. + /// request to User Agent failed. /// /// With [`MediaManagerError::GetUserMediaFailed`] if [getUserMedia()][1] /// request failed. diff --git a/jason/src/peer/mod.rs b/jason/src/peer/mod.rs index ee3e8766b..6a5e98b39 100644 --- a/jason/src/peer/mod.rs +++ b/jason/src/peer/mod.rs @@ -386,11 +386,11 @@ impl PeerConnection { // Bind to `track` event. let media_connections = Rc::clone(&peer.media_connections); peer.peer.on_track(Some(move |track, transceiver| { - if let Err(err) = media_connections + if let Err(e) = media_connections .add_remote_track(track, transceiver) .map_err(tracerr::map_from_and_wrap!(=> PeerError)) { - log::error!("{}", err); + log::error!("{}", e); }; })); @@ -508,9 +508,7 @@ impl PeerConnection { .map_err(tracerr::map_from_and_wrap!(=> PeerError)) { Ok(stats) => self.send_peer_stats(stats), - Err(e) => { - log::error!("{}", e); - } + Err(e) => log::error!("{}", e), }; } diff --git a/jason/src/room.rs b/jason/src/room.rs index e66eb8fa7..545522a09 100644 --- a/jason/src/room.rs +++ b/jason/src/room.rs @@ -217,7 +217,8 @@ impl RoomHandle { /// With [`RoomError::CallbackNotSet`] if `on_failed_local_media` or /// `on_connection_loss` callback is not set. /// - /// With [`RoomError::ConnectionInfoParse`] if provided URL parsing fails. + /// With [`RoomError::ConnectionInfoParse`] if the provided URL parsing + /// fails. /// /// With [`RoomError::Detached`] if [`Weak`] pointer upgrade fails. /// @@ -418,11 +419,11 @@ impl RoomHandle { /// /// # Errors /// - /// With [`ConstraintsUpdateException::Errored`] if error while provided - /// [`MediaStreamSettings`] applying occured. + /// With [`ConstraintsUpdateException::Errored`] if and error has occurred + /// while applying the provided [`MediaStreamSettings`]. /// /// With [`ConstraintsUpdateException::Recovered`] if - /// [`MediaStreamSettings`] are rollbacked because error occured. + /// [`MediaStreamSettings`] are rolled-back because an error had occurred. /// /// With [`ConstraintsUpdateException::RecoverFailed`] if /// [`MediaStreamSettings`] rollback failed. @@ -468,21 +469,20 @@ impl RoomHandle { direction, source_kind.map(Into::into), ) - .await?; - - Ok(()) + .await + .map_err(tracerr::wrap!()) } /// Mutes outbound audio in this [`Room`]. /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::unmute_audio`] is called while muting or media server - /// didn't approve state transition. + /// [`RoomHandle::unmute_audio()`] was called while muting or a media server + /// didn't approve this state transition. #[inline] pub async fn mute_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -499,12 +499,12 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::mute_audio`] is called while muting or media server - /// didn't approve state transition. + /// [`RoomHandle::mute_audio`] was called while muting or a media server + /// didn't approve this state transition. #[inline] pub async fn unmute_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -521,12 +521,12 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::unmute_video`] is called while muting or media server - /// didn't approve state transition. + /// [`RoomHandle::unmute_video()`] was called while muting or a media server + /// didn't approve this state transition. #[inline] pub async fn mute_video( &self, @@ -546,12 +546,12 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::mute_video`] is called while muting or media server - /// didn't approve state transition. + /// [`RoomHandle::mute_video()`] was called while muting or a media server + /// didn't approve this state transition. #[inline] pub async fn unmute_video( &self, @@ -571,16 +571,16 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with - /// [`MediaConnectionsError::CannotDisableRequiredSender`] if audio track + /// [`MediaConnectionsError::CannotDisableRequiredSender`] if audio track's /// sender is configured as `required`. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::enable_audio`] is called while disabling or server didn't - /// approve state transition. + /// [`RoomHandle::enable_audio()`] was called while disabling or a media + /// server didn't approve this state transition. #[inline] pub async fn disable_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -597,12 +597,12 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::disable_audio`] is called while enabling or server didn't - /// approve state transition. + /// [`RoomHandle::disable_audio`] was called while enabling or a media + /// server didn't approve this state transition. /// /// With [`RoomError::MediaManagerError`] with /// [`MediaManagerError::CouldNotGetMediaDevices`] or @@ -626,16 +626,16 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with - /// [`MediaConnectionsError::CannotDisableRequiredSender`] video track + /// [`MediaConnectionsError::CannotDisableRequiredSender`] video track's /// sender is configured as `required`. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::enable_video`] is called while disabling or server didn't - /// approve state transition. + /// [`RoomHandle::enable_video()`] was called while disabling or a media + /// server didn't approve this state transition. #[inline] pub async fn disable_video( &self, @@ -657,12 +657,12 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::disable_video`] is called while enabling or server didn't - /// approve state transition. + /// [`RoomHandle::disable_video()`] was called while enabling or a media + /// server didn't approve this state transition. /// /// With [`RoomError::MediaManagerError`] with /// [`MediaManagerError::CouldNotGetMediaDevices`] or @@ -687,12 +687,12 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::enable_remote_audio`] is called while disabling or media - /// server didn't approve state transition. + /// [`RoomHandle::enable_remote_audio()`] was called while disabling or a + /// media server didn't approve this state transition. #[inline] pub async fn disable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -709,12 +709,12 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::enable_remote_video`] is called while disabling or media - /// server didn't approve state transition. + /// [`RoomHandle::enable_remote_video()`] was called while disabling or a + /// media server didn't approve this state transition. #[inline] pub async fn disable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( @@ -731,12 +731,12 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::disable_remote_audio`] is called while enabling or media - /// server didn't approve state transition. + /// [`RoomHandle::disable_remote_audio()`] was called while enabling or a + /// media server didn't approve this state transition. #[inline] pub async fn enable_remote_audio(&self) -> Result<(), Traced> { self.change_media_state( @@ -753,12 +753,12 @@ impl RoomHandle { /// /// # Errors /// - /// With [`RoomError::Detached`] if inner [`Weak`] pointer upgrade fails. + /// With [`RoomError::Detached`] if an inner [`Weak`] pointer upgrade fails. /// /// With [`RoomError::MediaConnections`] with /// [`MediaConnectionsError::MediaStateTransitsIntoOppositeState`] if - /// [`RoomHandle::disable_remote_video`] is called while enabling or media - /// server didn't approve state transition. + /// [`RoomHandle::disable_remote_video()`] was called while enabling or a + /// media server didn't approve this state transition. #[inline] pub async fn enable_remote_video(&self) -> Result<(), Traced> { self.change_media_state( @@ -835,25 +835,25 @@ impl Room { if let Some(inner) = inner.upgrade() { match event { RoomEvent::RpcEvent(event) => { - if let Err(err) = event + if let Err(e) = event .dispatch_with(inner.deref()) .await .map_err( tracerr::map_from_and_wrap!(=> RoomError), ) { - log::error!("{}", err); + log::error!("{}", e); }; } RoomEvent::PeerEvent(event) => { - if let Err(err) = event + if let Err(e) = event .dispatch_with(inner.deref()) .await .map_err( tracerr::map_from_and_wrap!(=> RoomError), ) { - log::error!("{}", err); + log::error!("{}", e); }; } RoomEvent::RpcClientLostConnection => { @@ -975,7 +975,7 @@ pub enum ConstraintsUpdateException { /// (`rollback_on_fail`/`stop_first` arguments). #[display(fmt = "RecoveredException")] Recovered { - /// [`RoomError`] due to which recovery happened. + /// [`RoomError`] due to which recovery has happened. recover_reason: Traced, }, @@ -983,10 +983,10 @@ pub enum ConstraintsUpdateException { /// failed. #[display(fmt = "RecoverFailedException")] RecoverFailed { - /// [`RoomError`] due to which recovery happened. + /// [`RoomError`] due to which recovery has happened. recover_reason: Traced, - /// Vector of [`RoomError`]s due to which recovery failed. + /// Vector of [`RoomError`]s due to which recovery has failed. recover_fail_reasons: Vec>, }, @@ -1003,8 +1003,8 @@ impl ConstraintsUpdateException { self.to_string() } - /// Returns [`RoomError`] if this [`ConstraintsUpdateException`] represents - /// `RecoveredException` or `RecoverFailedException`. + /// Returns a [`RoomError`] if this [`ConstraintsUpdateException`] + /// represents a `RecoveredException` or a `RecoverFailedException`. /// /// Returns `undefined` otherwise. #[inline] @@ -1032,8 +1032,8 @@ impl ConstraintsUpdateException { } } - /// Returns [`RoomError`] if this [`ConstraintsUpdateException`] represents - /// an `ErroredException`. + /// Returns a [`RoomError`] if this [`ConstraintsUpdateException`] + /// represents an `ErroredException`. /// /// Returns `undefined` otherwise. #[inline] diff --git a/jason/src/rpc/mod.rs b/jason/src/rpc/mod.rs index 726a9c94f..a6c464b01 100644 --- a/jason/src/rpc/mod.rs +++ b/jason/src/rpc/mod.rs @@ -75,7 +75,7 @@ impl ConnectionInfo { } /// Errors which can occur while [`ConnectionInfo`] parsing from the [`str`]. -#[derive(Clone, Debug, JsCaused, Display)] +#[derive(Clone, Debug, Display, JsCaused)] #[js(error = "platform::Error")] pub enum ConnectionInfoParseError { /// [`Url::parse`] returned error. diff --git a/jason/src/rpc/reconnect_handle.rs b/jason/src/rpc/reconnect_handle.rs index 637045532..5a1359d1e 100644 --- a/jason/src/rpc/reconnect_handle.rs +++ b/jason/src/rpc/reconnect_handle.rs @@ -11,11 +11,11 @@ use crate::{ utils::JsCaused, }; -/// Errors that may occur in a [`ReconnectHandle`]. +/// Errors occurring in a [`ReconnectHandle`]. #[derive(Clone, From, Display, JsCaused)] #[js(error = "platform::Error")] pub enum ReconnectError { - /// Some [`SessionError`] occurred while reconnecting. + /// Some [`SessionError`] has occurred while reconnecting. #[display(fmt = "{}", _0)] Session(#[js(cause)] SessionError), @@ -49,7 +49,8 @@ impl ReconnectHandle { /// /// With [`ReconnectError::Detached`] if [`Weak`] pointer upgrade fails. /// - /// With [`ReconnectError::Session`] if error while reconnecting occurred. + /// With [`ReconnectError::Session`] if error while reconnecting has + /// occurred. pub async fn reconnect_with_delay( &self, delay_ms: u32, @@ -60,11 +61,8 @@ impl ReconnectHandle { .0 .upgrade() .ok_or_else(|| tracerr::new!(ReconnectError::Detached))?; - rpc.reconnect() - .await - .map_err(tracerr::map_from_and_wrap!())?; - Ok(()) + rpc.reconnect().await.map_err(tracerr::map_from_and_wrap!()) } /// Tries to reconnect [`RpcSession`] in a loop with a growing backoff diff --git a/jason/src/rpc/websocket/client.rs b/jason/src/rpc/websocket/client.rs index d77f6a2f5..ee26b38c2 100644 --- a/jason/src/rpc/websocket/client.rs +++ b/jason/src/rpc/websocket/client.rs @@ -524,11 +524,11 @@ impl WebSocketRpcClient { let socket_borrow = &self.0.borrow().sock; if let Some(socket) = socket_borrow.as_ref() { - if let Err(err) = socket + if let Err(e) = socket .send(&ClientMsg::Command { room_id, command }) .map_err(tracerr::map_from_and_wrap!(=> RpcClientError)) { - log::error!("{}", err); + log::error!("{}", e); } } }