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