1pub extern crate servo_media_audio as audio;
2pub extern crate servo_media_player as player;
3pub extern crate servo_media_streams as streams;
4pub extern crate servo_media_traits as traits;
5pub extern crate servo_media_webrtc as webrtc;
6
7extern crate once_cell;
8
9pub use traits::*;
10
11use std::ops::Deref;
12use std::sync::{Arc, Mutex};
13use std::thread;
14
15use audio::{
16 context::{AudioContext, AudioContextOptions},
17 sink::AudioSinkError,
18};
19use player::audio::AudioRenderer;
20use player::context::PlayerGLContext;
21use player::ipc_channel::ipc::IpcSender;
22use player::video::VideoFrameRenderer;
23use player::{Player, PlayerEvent, StreamType};
24use streams::capture::MediaTrackConstraintSet;
25use streams::device_monitor::MediaDeviceMonitor;
26use streams::registry::MediaStreamId;
27use streams::{MediaOutput, MediaSocket, MediaStreamType};
28use webrtc::{WebRtcController, WebRtcSignaller};
29
30use once_cell::sync::OnceCell;
31
32pub struct ServoMedia(Box<dyn Backend>);
33
34static INSTANCE: OnceCell<Arc<ServoMedia>> = OnceCell::new();
35
36pub trait BackendInit {
37 fn init() -> Box<dyn Backend>;
38}
39
40pub trait BackendDeInit {
41 fn deinit(&self) {}
42}
43
44pub trait Backend: Send + Sync {
45 fn create_player(
46 &self,
47 id: &ClientContextId,
48 stream_type: StreamType,
49 sender: IpcSender<PlayerEvent>,
50 video_renderer: Option<Arc<Mutex<dyn VideoFrameRenderer>>>,
51 audio_renderer: Option<Arc<Mutex<dyn AudioRenderer>>>,
52 gl_context: Box<dyn PlayerGLContext>,
53 ) -> Arc<Mutex<dyn Player>>;
54 fn create_audiostream(&self) -> MediaStreamId;
55 fn create_videostream(&self) -> MediaStreamId;
56 fn create_stream_output(&self) -> Box<dyn MediaOutput>;
57 fn create_stream_and_socket(
58 &self,
59 ty: MediaStreamType,
60 ) -> (Box<dyn MediaSocket>, MediaStreamId);
61 fn create_audioinput_stream(&self, set: MediaTrackConstraintSet) -> Option<MediaStreamId>;
62 fn create_videoinput_stream(&self, set: MediaTrackConstraintSet) -> Option<MediaStreamId>;
63 fn create_audio_context(
64 &self,
65 id: &ClientContextId,
66 options: AudioContextOptions,
67 ) -> Result<Arc<Mutex<AudioContext>>, AudioSinkError>;
68 fn create_webrtc(&self, signaller: Box<dyn WebRtcSignaller>) -> WebRtcController;
69 fn can_play_type(&self, media_type: &str) -> SupportsMediaType;
70 fn set_capture_mocking(&self, _mock: bool) {}
71 fn mute(&self, _id: &ClientContextId, _val: bool) {}
76 fn suspend(&self, _id: &ClientContextId) {}
84 fn resume(&self, _id: &ClientContextId) {}
90
91 fn get_device_monitor(&self) -> Box<dyn MediaDeviceMonitor>;
92}
93
94#[derive(Clone, Copy, Debug, PartialEq)]
95pub enum SupportsMediaType {
96 Maybe,
97 No,
98 Probably,
99}
100
101impl ServoMedia {
102 pub fn init<B: BackendInit>() {
103 thread::spawn(|| INSTANCE.get_or_init(|| Arc::new(ServoMedia(B::init()))));
104 }
105
106 pub fn init_with_backend<F>(backend_factory: F)
107 where
108 F: Fn() -> Box<dyn Backend> + Send + 'static,
109 {
110 thread::spawn(move || INSTANCE.get_or_init(|| Arc::new(ServoMedia(backend_factory()))));
111 }
112
113 pub fn get() -> Arc<ServoMedia> {
114 INSTANCE.wait().clone()
115 }
116}
117
118impl Deref for ServoMedia {
119 type Target = dyn Backend + 'static;
120 fn deref(&self) -> &(dyn Backend + 'static) {
121 &*self.0
122 }
123}