medea_jason/platform/dart/
media_track.rs

1//! Representation of a [MediaStreamTrack][0].
2//!
3//! [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
4
5use dart_sys::Dart_Handle;
6use medea_macro::dart_bridge;
7
8use crate::{
9    media::{
10        FacingMode, MediaKind, MediaSourceKind, NoiseSuppressionLevel,
11        track::MediaStreamTrackState,
12    },
13    platform::{
14        self,
15        dart::utils::{
16            NonNullDartValueArgExt as _, callback::Callback,
17            dart_string_into_rust, handle::DartHandle,
18        },
19        utils::dart_future::FutureFromDart,
20    },
21};
22
23#[dart_bridge("flutter/lib/src/native/platform/media_track.g.dart")]
24mod media_stream_track {
25    use std::{os::raw::c_char, ptr};
26
27    use dart_sys::Dart_Handle;
28
29    use crate::{api::DartValueArg, platform::Error};
30
31    extern "C" {
32        /// Returns [ID][1] of the provided [MediaStreamTrack][0].
33        ///
34        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
35        /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-id
36        pub fn id(track: Dart_Handle) -> Result<ptr::NonNull<c_char>, Error>;
37
38        /// Returns [device ID][1] of the provided [MediaStreamTrack][0].
39        ///
40        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
41        /// [1]: https://w3.org/TR/mediacapture-streams#dfn-deviceid
42        pub fn device_id(
43            track: Dart_Handle,
44        ) -> Result<ptr::NonNull<c_char>, Error>;
45
46        /// Returns [kind][1] of the provided [MediaStreamTrack][0].
47        ///
48        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
49        /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-kind
50        pub fn kind(track: Dart_Handle) -> Result<i64, Error>;
51
52        /// Returns [facing mode][1] of the provided [MediaStreamTrack][0].
53        ///
54        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
55        /// [1]: https://tinyurl.com/w3-streams#def-constraint-facingMode
56        pub fn facing_mode(
57            track: Dart_Handle,
58        ) -> Result<ptr::NonNull<DartValueArg<Option<i64>>>, Error>;
59
60        /// Returns [height][1] of the provided [MediaStreamTrack][0].
61        ///
62        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
63        /// [1]: https://tinyurl.com/w3-streams#dom-mediatracksettings-height
64        pub fn height(
65            track: Dart_Handle,
66        ) -> Result<ptr::NonNull<DartValueArg<Option<u32>>>, Error>;
67
68        /// Returns [width][1] of the provided [MediaStreamTrack][0].
69        ///
70        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
71        /// [1]: https://tinyurl.com/w3-streams#dom-mediatracksettings-width
72        pub fn width(
73            track: Dart_Handle,
74        ) -> Result<ptr::NonNull<DartValueArg<Option<u32>>>, Error>;
75
76        /// Returns [enabled][1] field of the provided [MediaStreamTrack][0].
77        ///
78        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
79        /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled
80        pub fn enabled(track: Dart_Handle) -> Result<bool, Error>;
81
82        /// Sets [enabled][1] field of the provided [MediaStreamTrack][0].
83        ///
84        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
85        /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-enabled
86        pub fn set_enabled(
87            track: Dart_Handle,
88            is_enabled: bool,
89        ) -> Result<(), Error>;
90
91        /// Returns [readiness state][1] of the provided [MediaStreamTrack][0].
92        ///
93        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
94        /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-readystate
95        pub fn ready_state(track: Dart_Handle) -> Result<Dart_Handle, Error>;
96
97        /// [Stops][1] the provided [MediaStreamTrack][0].
98        ///
99        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
100        /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-stop
101        pub fn stop(track: Dart_Handle) -> Result<Dart_Handle, Error>;
102
103        /// Sets [`onended`][1] event handler of the provided
104        /// [MediaStreamTrack][0].
105        ///
106        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
107        /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-onended
108        pub fn on_ended(
109            track: Dart_Handle,
110            cb: Dart_Handle,
111        ) -> Result<(), Error>;
112
113        /// Creates a new instance of [MediaStreamTrack][0] depending on the
114        /// same media source as the provided one has.
115        ///
116        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
117        pub fn clone(track: Dart_Handle) -> Result<Dart_Handle, Error>;
118
119        /// Disposes the provided [MediaStreamTrack][0].
120        ///
121        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
122        pub fn dispose(track: Dart_Handle) -> Result<Dart_Handle, Error>;
123
124        /// Indicates whether an `OnAudioLevelChangedCallback` is supported for
125        /// this [MediaStreamTrack][0].
126        ///
127        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
128        pub fn is_on_audio_level_available(
129            track: Dart_Handle,
130        ) -> Result<bool, Error>;
131
132        /// Sets the provided `OnAudioLevelChangedCallback` for the provided
133        /// [MediaStreamTrack][0].
134        ///
135        /// It's called for live [MediaStreamTrack][0]s when their audio level
136        /// changes.
137        ///
138        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
139        pub fn on_audio_level_changed(
140            track: Dart_Handle,
141            cb: Dart_Handle,
142        ) -> Result<(), Error>;
143
144        /// Indicates whether the provided [MediaStreamTrack][0] supports audio
145        /// processing functions.
146        ///
147        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
148        pub fn is_audio_processing_available(
149            track: Dart_Handle,
150        ) -> Result<bool, Error>;
151
152        /// Toggles noise suppression for the provided [MediaStreamTrack][0].
153        ///
154        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
155        pub fn set_noise_suppression_enabled(
156            track: Dart_Handle,
157            enable: bool,
158        ) -> Result<Dart_Handle, Error>;
159
160        /// Configures a noise suppression level for the provided
161        /// [MediaStreamTrack][0].
162        ///
163        /// __NOTE__: Only supported on desktop platforms.
164        ///
165        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
166        pub fn set_noise_suppression_level(
167            track: Dart_Handle,
168            level: i64,
169        ) -> Result<Dart_Handle, Error>;
170
171        /// Toggles echo cancellation for the provided [MediaStreamTrack][0].
172        ///
173        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
174        pub fn set_echo_cancellation_enabled(
175            track: Dart_Handle,
176            enable: bool,
177        ) -> Result<Dart_Handle, Error>;
178
179        /// Toggles auto gain control for the provided [MediaStreamTrack][0].
180        ///
181        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
182        pub fn set_auto_gain_control_enabled(
183            track: Dart_Handle,
184            enable: bool,
185        ) -> Result<Dart_Handle, Error>;
186
187        /// Toggles high-pass filter for the provided [MediaStreamTrack][0].
188        ///
189        /// __NOTE__: Only supported on desktop platforms.
190        ///
191        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
192        pub fn set_high_pass_filter_enabled(
193            track: Dart_Handle,
194            enable: bool,
195        ) -> Result<Dart_Handle, Error>;
196
197        /// Indicates whether noise suppression is enabled for the provided
198        /// [MediaStreamTrack][0].
199        ///
200        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
201        pub fn is_noise_suppression_enabled(
202            track: Dart_Handle,
203        ) -> Result<Dart_Handle, Error>;
204
205        /// Returns the current configured noise suppression level of the
206        /// provided [MediaStreamTrack][0].
207        ///
208        /// __NOTE__: Only supported on desktop platforms.
209        ///
210        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
211        pub fn get_noise_suppression_level(
212            track: Dart_Handle,
213        ) -> Result<Dart_Handle, Error>;
214
215        /// Indicates whether auto gain control is enabled for the provided
216        /// [MediaStreamTrack][0].
217        ///
218        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
219        pub fn is_auto_gain_control_enabled(
220            track: Dart_Handle,
221        ) -> Result<Dart_Handle, Error>;
222
223        /// Indicates whether echo cancellation is enabled for the provided
224        /// [MediaStreamTrack][0].
225        ///
226        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
227        pub fn is_echo_cancellation_enabled(
228            track: Dart_Handle,
229        ) -> Result<Dart_Handle, Error>;
230
231        /// Indicates whether high-pass filter is enabled for the provided
232        /// [MediaStreamTrack][0].
233        ///
234        /// __NOTE__: Only supported on desktop platforms.
235        ///
236        /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
237        pub fn is_high_pass_filter_enabled(
238            track: Dart_Handle,
239        ) -> Result<Dart_Handle, Error>;
240    }
241}
242
243/// Representation of a [MediaStreamTrack][0] received from a
244/// [getUserMedia()][1] or a [getDisplayMedia()][2] request.
245///
246/// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
247/// [1]: https://w3.org/TR/mediacapture-streams#dom-mediadevices-getusermedia
248/// [2]: https://w3.org/TR/screen-capture#dom-mediadevices-getdisplaymedia
249#[derive(Clone, Debug)]
250pub struct MediaStreamTrack {
251    /// Pointer on the [MediaStreamTrack][0]
252    ///
253    /// [0]: https://w3.org/TR/mediacapture-streams#mediastreamtrack
254    inner: DartHandle,
255
256    /// Media source type of this [`MediaStreamTrack`].
257    source_kind: Option<MediaSourceKind>,
258}
259
260impl MediaStreamTrack {
261    /// Creates a new [`MediaStreamTrack`].
262    #[must_use]
263    pub const fn new(
264        inner: DartHandle,
265        source_kind: Option<MediaSourceKind>,
266    ) -> Self {
267        Self { inner, source_kind }
268    }
269
270    /// Returns the underlying [`Dart_Handle`] of this [`MediaStreamTrack`].
271    #[must_use]
272    pub fn handle(&self) -> Dart_Handle {
273        self.inner.get()
274    }
275
276    /// Returns [ID][1] of this [`MediaStreamTrack`].
277    ///
278    /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-id
279    #[must_use]
280    pub fn id(&self) -> String {
281        let id = unsafe { media_stream_track::id(self.inner.get()) }.unwrap();
282        unsafe { dart_string_into_rust(id) }
283    }
284
285    /// Returns [device ID][1] of this [`MediaStreamTrack`].
286    ///
287    /// [1]: https://w3.org/TR/mediacapture-streams#dfn-deviceid
288    #[expect(clippy::unwrap_in_result, reason = "unrelated")]
289    #[inline]
290    #[must_use]
291    pub fn device_id(&self) -> Option<String> {
292        let device_id =
293            unsafe { media_stream_track::device_id(self.inner.get()) }.unwrap();
294        Some(unsafe { dart_string_into_rust(device_id) })
295    }
296
297    /// Returns [kind][1] of this [`MediaStreamTrack`].
298    ///
299    /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-kind
300    #[inline]
301    #[must_use]
302    pub fn kind(&self) -> MediaKind {
303        MediaKind::try_from(
304            unsafe { media_stream_track::kind(self.inner.get()) }.unwrap(),
305        )
306        .unwrap()
307    }
308
309    /// Returns [facing mode][1] of this [`MediaStreamTrack`].
310    ///
311    /// [1]: https://tinyurl.com/w3-streams#dom-mediatracksettings-facingmode
312    #[expect(clippy::unwrap_in_result, reason = "unrelated")]
313    #[must_use]
314    pub fn facing_mode(&self) -> Option<FacingMode> {
315        let facing_mode =
316            unsafe { media_stream_track::facing_mode(self.inner.get()) }
317                .unwrap();
318        Option::<i64>::try_from(unsafe { facing_mode.unbox() })
319            .unwrap()
320            .map(FacingMode::try_from)
321            .transpose()
322            .unwrap()
323    }
324
325    /// Returns [height][1] of this [`MediaStreamTrack`].
326    ///
327    /// [1]: https://tinyurl.com/w3-streams#dom-mediatracksettings-height
328    #[expect(clippy::unwrap_in_result, reason = "unrelated")]
329    #[must_use]
330    pub fn height(&self) -> Option<u32> {
331        let height =
332            unsafe { media_stream_track::height(self.inner.get()) }.unwrap();
333        Option::try_from(unsafe { height.unbox() }).unwrap()
334    }
335
336    /// Returns [width][1] of this [`MediaStreamTrack`].
337    ///
338    /// [1]: https://tinyurl.com/w3-streams#dom-mediatracksettings-width
339    #[expect(clippy::unwrap_in_result, reason = "unrelated")]
340    #[must_use]
341    pub fn width(&self) -> Option<u32> {
342        let width =
343            unsafe { media_stream_track::width(self.inner.get()) }.unwrap();
344        Option::try_from(unsafe { width.unbox() }).unwrap()
345    }
346
347    /// Returns [enabled][1] field of this [`MediaStreamTrack`].
348    ///
349    /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-enabled
350    #[inline]
351    #[must_use]
352    pub fn enabled(&self) -> bool {
353        unsafe { media_stream_track::enabled(self.inner.get()) }.unwrap()
354    }
355
356    /// Sets [enabled][1] field of this [`MediaStreamTrack`].
357    ///
358    /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-enabled
359    pub fn set_enabled(&self, enabled: bool) {
360        unsafe { media_stream_track::set_enabled(self.inner.get(), enabled) }
361            .unwrap();
362    }
363
364    /// Returns [readiness state][1] of this [`MediaStreamTrack`].
365    ///
366    /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-readystate
367    pub async fn ready_state(&self) -> MediaStreamTrackState {
368        let handle = self.inner.get();
369        let state = unsafe { media_stream_track::ready_state(handle) }.unwrap();
370        let state =
371            unsafe { FutureFromDart::execute::<i64>(state) }.await.unwrap();
372
373        match state {
374            0 => MediaStreamTrackState::Live,
375            1 => MediaStreamTrackState::Ended,
376            _ => unreachable!("Unknown `MediaStreamTrackState`: {state}"),
377        }
378    }
379
380    /// [Stops][1] this [`MediaStreamTrack`].
381    ///
382    /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-stop
383    #[inline]
384    pub fn stop(&self) -> impl Future<Output = ()> + 'static + use<> {
385        let inner = self.inner.clone();
386        async move {
387            let fut = unsafe { media_stream_track::stop(inner.get()) }.unwrap();
388            unsafe { FutureFromDart::execute::<()>(fut) }.await.unwrap();
389        }
390    }
391
392    /// Detects whether this video [`MediaStreamTrack`] is captured from
393    /// display, searching for [specific fields][1] in its settings.
394    ///
395    /// Only works in Chrome browser at the moment.
396    ///
397    /// [1]: https://w3.org/TR/screen-capture#extensions-to-mediatracksettings
398    #[must_use]
399    pub fn guess_is_from_display(&self) -> bool {
400        self.source_kind == Some(MediaSourceKind::Display)
401    }
402
403    /// Forks this [`MediaStreamTrack`], by creating a new [`MediaStreamTrack`]
404    /// from this [`MediaStreamTrack`] using a [`clone()`][1] method.
405    ///
406    /// __NOTE__: It won't clone [`MediaStreamTrack`]'s event handlers.
407    ///
408    /// # Naming
409    ///
410    /// The name of this method intentionally diverges from [the spec one][1] to
411    /// not interfere with [`Clone`] trait.
412    ///
413    /// [1]: https://w3.org/TR/mediacapture-streams#dom-mediastreamtrack-clone
414    pub async fn fork(&self) -> Self {
415        let fut =
416            unsafe { media_stream_track::clone(self.inner.get()) }.unwrap();
417        let new_track: DartHandle =
418            unsafe { FutureFromDart::execute(fut) }.await.unwrap();
419        Self::new(new_track, self.source_kind)
420    }
421
422    /// Sets [`onended`][1] event handler of this [`MediaStreamTrack`].
423    ///
424    /// [1]: https://tinyurl.com/w3-streams#dom-mediastreamtrack-onended
425    pub fn on_ended<F>(&self, f: Option<F>)
426    where
427        F: 'static + FnOnce(),
428    {
429        if let Some(cb) = f {
430            let cb = Callback::from_once(|(): ()| cb());
431            unsafe {
432                media_stream_track::on_ended(self.inner.get(), cb.into_dart())
433            }
434            .unwrap();
435        }
436    }
437
438    /// Indicates whether an `OnAudioLevelChangedCallback` is supported for this
439    /// [`MediaStreamTrack`].
440    #[must_use]
441    pub fn is_on_audio_level_available(&self) -> bool {
442        unsafe {
443            media_stream_track::is_on_audio_level_available(self.inner.get())
444        }
445        .unwrap()
446    }
447
448    /// Sets the provided `OnAudioLevelChangedCallback` for this
449    /// [`MediaStreamTrack`].
450    ///
451    /// It's called for live [`MediaStreamTrack`]s when their audio level
452    /// changes.
453    ///
454    /// # Errors
455    ///
456    /// Never errors.
457    #[expect(clippy::unwrap_in_result, reason = "unrelated and intended")]
458    pub fn on_audio_level_changed<F>(
459        &self,
460        mut f: F,
461    ) -> Result<(), platform::Error>
462    where
463        F: 'static + FnMut(i32),
464    {
465        let cb = Callback::from_fn_mut(move |value: i32| f(value));
466
467        unsafe {
468            media_stream_track::on_audio_level_changed(
469                self.inner.get(),
470                cb.into_dart(),
471            )
472        }
473        .unwrap();
474
475        Ok(())
476    }
477
478    /// Indicates whether this [`MediaStreamTrack`] supports audio processing
479    /// functions:
480    /// - [`MediaStreamTrack::is_noise_suppression_enabled()`]
481    /// - [`MediaStreamTrack::set_noise_suppression_enabled()`]
482    /// - [`MediaStreamTrack::get_noise_suppression_level()`]
483    /// - [`MediaStreamTrack::set_noise_suppression_level()`]
484    /// - [`MediaStreamTrack::is_echo_cancellation_enabled()`]
485    /// - [`MediaStreamTrack::set_echo_cancellation_enabled()`]
486    /// - [`MediaStreamTrack::is_auto_gain_control_enabled()`]
487    /// - [`MediaStreamTrack::set_auto_gain_control_enabled()`]
488    /// - [`MediaStreamTrack::is_high_pass_filter_enabled()`]
489    /// - [`MediaStreamTrack::set_high_pass_filter_enabled()`]
490    #[must_use]
491    pub fn is_audio_processing_available(&self) -> bool {
492        unsafe {
493            media_stream_track::is_audio_processing_available(self.inner.get())
494        }
495        .unwrap()
496    }
497
498    /// Toggles noise suppression for this [`MediaStreamTrack`].
499    ///
500    /// # Errors
501    ///
502    /// With a [`platform::Error`] if platform call errors.
503    pub async fn set_noise_suppression_enabled(
504        &self,
505        enabled: bool,
506    ) -> Result<(), platform::Error> {
507        let fut = unsafe {
508            media_stream_track::set_noise_suppression_enabled(
509                self.inner.get(),
510                enabled,
511            )
512        }?;
513        unsafe { FutureFromDart::execute::<()>(fut) }.await
514    }
515
516    /// Configures a [`NoiseSuppressionLevel`] for this [`MediaStreamTrack`].
517    ///
518    /// __NOTE__: Only supported on desktop platforms.
519    ///
520    /// # Errors
521    ///
522    /// With a [`platform::Error`] if platform call errors.
523    pub async fn set_noise_suppression_level(
524        &self,
525        level: NoiseSuppressionLevel,
526    ) -> Result<(), platform::Error> {
527        let fut = unsafe {
528            media_stream_track::set_noise_suppression_level(
529                self.inner.get(),
530                level as i64,
531            )
532        }?;
533        unsafe { FutureFromDart::execute::<()>(fut) }.await
534    }
535
536    /// Toggles acoustic echo cancellation for this [`MediaStreamTrack`].
537    ///
538    /// # Errors
539    ///
540    /// With a [`platform::Error`] if platform call errors.
541    pub async fn set_echo_cancellation_enabled(
542        &self,
543        enabled: bool,
544    ) -> Result<(), platform::Error> {
545        let fut = unsafe {
546            media_stream_track::set_echo_cancellation_enabled(
547                self.inner.get(),
548                enabled,
549            )
550        }?;
551        unsafe { FutureFromDart::execute::<()>(fut) }.await
552    }
553
554    /// Toggles auto gain control for this [`MediaStreamTrack`].
555    ///
556    /// # Errors
557    ///
558    /// With a [`platform::Error`] if platform call errors.
559    pub async fn set_auto_gain_control_enabled(
560        &self,
561        enabled: bool,
562    ) -> Result<(), platform::Error> {
563        let fut = unsafe {
564            media_stream_track::set_auto_gain_control_enabled(
565                self.inner.get(),
566                enabled,
567            )
568        }?;
569        unsafe { FutureFromDart::execute::<()>(fut) }.await
570    }
571
572    /// Toggles high-pass filter for this [`MediaStreamTrack`].
573    ///
574    /// __NOTE__: Only supported on desktop platforms.
575    ///
576    /// # Errors
577    ///
578    /// With a [`platform::Error`] if platform call errors.
579    pub async fn set_high_pass_filter_enabled(
580        &self,
581        enabled: bool,
582    ) -> Result<(), platform::Error> {
583        let fut = unsafe {
584            media_stream_track::set_high_pass_filter_enabled(
585                self.inner.get(),
586                enabled,
587            )
588        }?;
589        unsafe { FutureFromDart::execute::<()>(fut) }.await
590    }
591
592    /// Indicates whether noise suppression is enabled for this
593    /// [`MediaStreamTrack`].
594    ///
595    /// # Errors
596    ///
597    /// With a [`platform::Error`] if platform call errors.
598    pub async fn is_noise_suppression_enabled(
599        &self,
600    ) -> Result<bool, platform::Error> {
601        let fut = unsafe {
602            media_stream_track::is_noise_suppression_enabled(self.inner.get())
603        }?;
604        unsafe { FutureFromDart::execute::<bool>(fut) }.await
605    }
606
607    /// Returns the current configured [`NoiseSuppressionLevel`] of this
608    /// [`MediaStreamTrack`].
609    ///
610    /// __NOTE__: Only supported on desktop platforms.
611    ///
612    /// # Errors
613    ///
614    /// With a [`platform::Error`] if platform call errors.
615    pub async fn get_noise_suppression_level(
616        &self,
617    ) -> Result<NoiseSuppressionLevel, platform::Error> {
618        let fut = unsafe {
619            media_stream_track::get_noise_suppression_level(self.inner.get())
620        }?;
621        let level = unsafe { FutureFromDart::execute::<i64>(fut) }.await?;
622
623        Ok(NoiseSuppressionLevel::try_from(level).unwrap())
624    }
625
626    /// Indicates whether auto gain control is enabled for this
627    /// [`MediaStreamTrack`].
628    ///
629    /// # Errors
630    ///
631    /// With a [`platform::Error`] if platform call errors.
632    pub async fn is_auto_gain_control_enabled(
633        &self,
634    ) -> Result<bool, platform::Error> {
635        let fut = unsafe {
636            media_stream_track::is_auto_gain_control_enabled(self.inner.get())
637        }?;
638        unsafe { FutureFromDart::execute::<bool>(fut) }.await
639    }
640
641    /// Indicates whether echo cancellation is enabled for this
642    /// [`MediaStreamTrack`].
643    ///
644    /// # Errors
645    ///
646    /// With a [`platform::Error`] if platform call errors.
647    pub async fn is_echo_cancellation_enabled(
648        &self,
649    ) -> Result<bool, platform::Error> {
650        let fut = unsafe {
651            media_stream_track::is_echo_cancellation_enabled(self.inner.get())
652        }?;
653        unsafe { FutureFromDart::execute::<bool>(fut) }.await
654    }
655
656    /// Indicates whether high-pass filter is enabled for this
657    /// [`MediaStreamTrack`].
658    ///
659    /// __NOTE__: Only supported on desktop platforms.
660    ///
661    /// # Errors
662    ///
663    /// With a [`platform::Error`] if platform call errors.
664    pub async fn is_high_pass_filter_enabled(
665        &self,
666    ) -> Result<bool, platform::Error> {
667        let fut = unsafe {
668            media_stream_track::is_high_pass_filter_enabled(self.inner.get())
669        }?;
670        unsafe { FutureFromDart::execute::<bool>(fut) }.await
671    }
672}
673
674impl Drop for MediaStreamTrack {
675    fn drop(&mut self) {
676        let track = self.inner.clone();
677        platform::spawn(async move {
678            let fut =
679                unsafe { media_stream_track::dispose(track.get()) }.unwrap();
680            unsafe { FutureFromDart::execute::<()>(fut) }.await.unwrap();
681        });
682    }
683}