Skip to main content

servo_media_gstreamer/
device_monitor.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::cell::RefCell;
6
7use gstreamer::DeviceMonitor as GstDeviceMonitor;
8use gstreamer::prelude::*;
9use servo_media_streams::device_monitor::{MediaDeviceInfo, MediaDeviceKind, MediaDeviceMonitor};
10
11pub struct GStreamerDeviceMonitor {
12    devices: RefCell<Option<Vec<MediaDeviceInfo>>>,
13}
14
15impl GStreamerDeviceMonitor {
16    pub fn new() -> Self {
17        Self {
18            devices: RefCell::new(None),
19        }
20    }
21
22    fn get_devices(&self) -> Result<Vec<MediaDeviceInfo>, ()> {
23        const AUDIO_SOURCE: &str = "Audio/Source";
24        const AUDIO_SINK: &str = "Audio/Sink";
25        const VIDEO_SOURCE: &str = "Video/Source";
26        let device_monitor = GstDeviceMonitor::new();
27        let audio_caps = gstreamer_audio::AudioCapsBuilder::new().build();
28        device_monitor.add_filter(Some(AUDIO_SOURCE), Some(&audio_caps));
29        device_monitor.add_filter(Some(AUDIO_SINK), Some(&audio_caps));
30        let video_caps = gstreamer_video::VideoCapsBuilder::new().build();
31        device_monitor.add_filter(Some(VIDEO_SOURCE), Some(&video_caps));
32        let devices = device_monitor
33            .devices()
34            .iter()
35            .filter_map(|device| {
36                let display_name = device.display_name().as_str().to_owned();
37                Some(MediaDeviceInfo {
38                    device_id: display_name.clone(),
39                    kind: match device.device_class().as_str() {
40                        AUDIO_SOURCE => MediaDeviceKind::AudioInput,
41                        AUDIO_SINK => MediaDeviceKind::AudioOutput,
42                        VIDEO_SOURCE => MediaDeviceKind::VideoInput,
43                        _ => return None,
44                    },
45                    label: display_name,
46                })
47            })
48            .collect();
49        Ok(devices)
50    }
51}
52
53impl MediaDeviceMonitor for GStreamerDeviceMonitor {
54    fn enumerate_devices(&self) -> Option<Vec<MediaDeviceInfo>> {
55        {
56            if let Some(ref devices) = *self.devices.borrow() {
57                return Some(devices.clone());
58            }
59        }
60        let devices = self.get_devices().ok()?;
61        *self.devices.borrow_mut() = Some(devices.clone());
62        Some(devices)
63    }
64}