1 //! Constants identifying the properties of a [`MediaStreamTrack`][media_stream_track] object, 2 //! as defined in the ["Media Capture and Streams"][media_track_supported_constraints] spec. 3 //! 4 //! [media_stream_track]: https://www.w3.org/TR/mediacapture-streams/#mediastreamtrack 5 //! [media_track_supported_constraints]: https://www.w3.org/TR/mediacapture-streams/#dom-mediatracksupportedconstraints 6 7 use std::{borrow::Cow, fmt::Display}; 8 9 #[cfg(feature = "serde")] 10 use serde::{Deserialize, Serialize}; 11 12 /// An identifier for a media track property. 13 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 14 #[cfg_attr(feature = "serde", serde(transparent))] 15 #[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] 16 pub struct MediaTrackProperty(Cow<'static, str>); 17 18 impl From<&MediaTrackProperty> for MediaTrackProperty { from(borrowed: &MediaTrackProperty) -> Self19 fn from(borrowed: &MediaTrackProperty) -> Self { 20 borrowed.clone() 21 } 22 } 23 24 impl From<String> for MediaTrackProperty { 25 /// Creates a property from an owned representation of its name. from(owned: String) -> Self26 fn from(owned: String) -> Self { 27 Self(Cow::Owned(owned)) 28 } 29 } 30 31 impl From<&str> for MediaTrackProperty { 32 /// Creates a property from an owned representation of its name. 33 /// 34 /// Use `MediaTrackProperty::named(str)` if your property name 35 /// is statically borrowed (i.e. `&'static str`). from(borrowed: &str) -> Self36 fn from(borrowed: &str) -> Self { 37 Self(Cow::Owned(borrowed.to_owned())) 38 } 39 } 40 41 impl Display for MediaTrackProperty { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 43 f.write_str(&self.0) 44 } 45 } 46 47 impl MediaTrackProperty { 48 /// Creates a property from a statically borrowed representation of its name. named(name: &'static str) -> Self49 pub const fn named(name: &'static str) -> Self { 50 Self(Cow::Borrowed(name)) 51 } 52 53 /// The property's name. name(&self) -> &str54 pub fn name(&self) -> &str { 55 &self.0 56 } 57 } 58 59 /// Standard properties that apply to both, audio and video device types. 60 pub mod common { 61 use super::*; 62 63 /// Names of common properties. 64 pub mod name { 65 use super::*; 66 67 /// The identifier of the device generating the content of the track, 68 /// as defined in the [spec][spec]. 69 /// 70 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-deviceid 71 pub static DEVICE_ID: MediaTrackProperty = MediaTrackProperty::named("deviceId"); 72 73 /// The document-unique group identifier for the device generating the content 74 /// of the track, as defined in the [spec][spec]. 75 /// 76 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-groupid 77 pub static GROUP_ID: MediaTrackProperty = MediaTrackProperty::named("groupId"); 78 } 79 80 /// Names of common properties. names() -> Vec<&'static MediaTrackProperty>81 pub fn names() -> Vec<&'static MediaTrackProperty> { 82 use self::name::*; 83 84 vec![&DEVICE_ID, &GROUP_ID] 85 } 86 } 87 88 /// Standard properties that apply only to audio device types. 89 pub mod audio_only { 90 use super::*; 91 92 /// Names of audio-only properties. 93 pub mod name { 94 use super::*; 95 96 /// Automatic gain control is often desirable on the input signal recorded 97 /// by the microphone, as defined in the [spec][spec]. 98 /// 99 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-autogaincontrol 100 pub static AUTO_GAIN_CONTROL: MediaTrackProperty = 101 MediaTrackProperty::named("autoGainControl"); 102 103 /// The number of independent channels of sound that the audio data contains, 104 /// i.e. the number of audio samples per sample frame, as defined in the [spec][spec]. 105 /// 106 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-channelcount 107 pub static CHANNEL_COUNT: MediaTrackProperty = MediaTrackProperty::named("channelCount"); 108 109 /// When one or more audio streams is being played in the processes of 110 /// various microphones, it is often desirable to attempt to remove 111 /// all the sound being played from the input signals recorded by the microphones. 112 /// This is referred to as echo cancellation, as defined in the [spec][spec]. 113 /// 114 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-echocancellation 115 pub static ECHO_CANCELLATION: MediaTrackProperty = 116 MediaTrackProperty::named("echoCancellation"); 117 118 /// The latency or latency range, in seconds, as defined in the [spec][spec]. 119 /// 120 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-latency 121 pub static LATENCY: MediaTrackProperty = MediaTrackProperty::named("latency"); 122 123 /// Noise suppression is often desirable on the input signal recorded by the microphone, 124 /// as defined in the [spec][spec]. 125 /// 126 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-noisesuppression 127 pub static NOISE_SUPPRESSION: MediaTrackProperty = 128 MediaTrackProperty::named("noiseSuppression"); 129 130 /// The sample rate in samples per second for the audio data, as defined in the [spec][spec]. 131 /// 132 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-samplerate 133 pub static SAMPLE_RATE: MediaTrackProperty = MediaTrackProperty::named("sampleRate"); 134 135 /// The linear sample size in bits. This constraint can only 136 /// be satisfied for audio devices that produce linear samples, as defined in the [spec][spec]. 137 /// 138 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-samplesize 139 pub static SAMPLE_SIZE: MediaTrackProperty = MediaTrackProperty::named("sampleSize"); 140 } 141 142 /// Names of all audio-only properties. names() -> Vec<&'static MediaTrackProperty>143 pub fn names() -> Vec<&'static MediaTrackProperty> { 144 use self::name::*; 145 146 vec![ 147 &AUTO_GAIN_CONTROL, 148 &CHANNEL_COUNT, 149 &ECHO_CANCELLATION, 150 &LATENCY, 151 &NOISE_SUPPRESSION, 152 &SAMPLE_RATE, 153 &SAMPLE_SIZE, 154 ] 155 } 156 } 157 158 /// Standard properties that apply only to video device types. 159 pub mod video_only { 160 use super::*; 161 162 /// Names of audio-only properties. 163 pub mod name { 164 use super::*; 165 166 /// The exact aspect ratio (width in pixels divided by height in pixels, 167 /// represented as a double rounded to the tenth decimal place), 168 /// as defined in the [spec][spec]. 169 /// 170 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-aspectratio 171 pub static ASPECT_RATIO: MediaTrackProperty = MediaTrackProperty::named("aspectRatio"); 172 173 /// The directions that the camera can face, as seen from the user's perspective, 174 /// as defined in the [spec][spec]. 175 /// 176 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-facingmode 177 pub static FACING_MODE: MediaTrackProperty = MediaTrackProperty::named("facingMode"); 178 179 /// The exact frame rate (frames per second) or frame rate range, 180 /// as defined in the [spec][spec]. 181 /// 182 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-framerate 183 pub static FRAME_RATE: MediaTrackProperty = MediaTrackProperty::named("frameRate"); 184 185 /// The height or height range, in pixels, as defined in the [spec][spec]. 186 /// 187 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-height 188 pub static HEIGHT: MediaTrackProperty = MediaTrackProperty::named("height"); 189 190 /// The width or width range, in pixels, as defined in the [spec][spec]. 191 /// 192 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-width 193 pub static WIDTH: MediaTrackProperty = MediaTrackProperty::named("width"); 194 195 /// The means by which the resolution can be derived by the client, as defined in the [spec][spec]. 196 /// 197 /// In other words, whether the client is allowed to use cropping and downscaling on the camera output. 198 /// 199 /// [spec]: https://www.w3.org/TR/mediacapture-streams/#dfn-resizemode 200 pub static RESIZE_MODE: MediaTrackProperty = MediaTrackProperty::named("resizeMode"); 201 } 202 203 /// Names of all video-only properties. names() -> Vec<&'static MediaTrackProperty>204 pub fn names() -> Vec<&'static MediaTrackProperty> { 205 use self::name::*; 206 vec![ 207 &ASPECT_RATIO, 208 &FACING_MODE, 209 &FRAME_RATE, 210 &HEIGHT, 211 &WIDTH, 212 &RESIZE_MODE, 213 ] 214 } 215 } 216 217 /// The union of all standard properties (i.e. common + audio + video). 218 pub mod all { 219 use super::*; 220 221 /// Names of all properties. 222 pub mod name { 223 pub use super::audio_only::name::*; 224 pub use super::common::name::*; 225 pub use super::video_only::name::*; 226 } 227 228 /// Names of all properties. names() -> Vec<&'static MediaTrackProperty>229 pub fn names() -> Vec<&'static MediaTrackProperty> { 230 let mut all = vec![]; 231 all.append(&mut self::common::names()); 232 all.append(&mut self::audio_only::names()); 233 all.append(&mut self::video_only::names()); 234 all 235 } 236 } 237 238 #[cfg(test)] 239 mod tests { 240 use super::*; 241 242 type Subject = MediaTrackProperty; 243 244 mod from { 245 use super::*; 246 247 #[test] owned()248 fn owned() { 249 let actuals = [Subject::from("string"), Subject::from("string".to_owned())]; 250 let expected = MediaTrackProperty(Cow::Owned("string".to_owned())); 251 252 for actual in actuals { 253 assert_eq!(actual, expected); 254 255 // TODO: remove feature-gate, once stabilized: 256 #[cfg(feature = "cow_is_borrowed")] 257 assert!(actual.0.is_owned()); 258 } 259 } 260 261 #[test] borrowed()262 fn borrowed() { 263 let actual = Subject::named("string"); 264 let expected = MediaTrackProperty(Cow::Borrowed("string")); 265 266 assert_eq!(actual, expected); 267 268 // TODO: remove feature-gate, once stabilized: 269 #[cfg(feature = "cow_is_borrowed")] 270 assert!(actual.0.is_borrowed()); 271 } 272 } 273 274 #[test] name()275 fn name() { 276 assert_eq!(Subject::named("string").name(), "string"); 277 } 278 279 #[test] to_string()280 fn to_string() { 281 assert_eq!(Subject::named("string").to_string(), "string"); 282 } 283 } 284 285 #[cfg(feature = "serde")] 286 #[cfg(test)] 287 mod serde_tests { 288 use crate::macros::test_serde_symmetry; 289 290 use super::*; 291 292 type Subject = MediaTrackProperty; 293 294 #[test] is_symmetric()295 fn is_symmetric() { 296 let subject = Subject::named("string"); 297 let json = serde_json::json!("string"); 298 299 test_serde_symmetry!(subject: subject, json: json); 300 } 301 } 302