pub extern crate servo_media_audio as audio;
pub extern crate servo_media_player as player;
pub extern crate servo_media_streams as streams;
pub extern crate servo_media_traits as traits;
pub extern crate servo_media_webrtc as webrtc;
extern crate once_cell;
pub use traits::*;
use std::ops::Deref;
use std::sync::{Arc, Mutex};
use std::thread;
use audio::{
context::{AudioContext, AudioContextOptions},
sink::AudioSinkError,
};
use player::audio::AudioRenderer;
use player::context::PlayerGLContext;
use player::ipc_channel::ipc::IpcSender;
use player::video::VideoFrameRenderer;
use player::{Player, PlayerEvent, StreamType};
use streams::capture::MediaTrackConstraintSet;
use streams::device_monitor::MediaDeviceMonitor;
use streams::registry::MediaStreamId;
use streams::{MediaOutput, MediaSocket, MediaStreamType};
use webrtc::{WebRtcController, WebRtcSignaller};
use once_cell::sync::OnceCell;
pub struct ServoMedia(Box<dyn Backend>);
static INSTANCE: OnceCell<Arc<ServoMedia>> = OnceCell::new();
pub trait BackendInit {
fn init() -> Box<dyn Backend>;
}
pub trait Backend: Send + Sync {
fn create_player(
&self,
id: &ClientContextId,
stream_type: StreamType,
sender: IpcSender<PlayerEvent>,
video_renderer: Option<Arc<Mutex<dyn VideoFrameRenderer>>>,
audio_renderer: Option<Arc<Mutex<dyn AudioRenderer>>>,
gl_context: Box<dyn PlayerGLContext>,
) -> Arc<Mutex<dyn Player>>;
fn create_audiostream(&self) -> MediaStreamId;
fn create_videostream(&self) -> MediaStreamId;
fn create_stream_output(&self) -> Box<dyn MediaOutput>;
fn create_stream_and_socket(
&self,
ty: MediaStreamType,
) -> (Box<dyn MediaSocket>, MediaStreamId);
fn create_audioinput_stream(&self, set: MediaTrackConstraintSet) -> Option<MediaStreamId>;
fn create_videoinput_stream(&self, set: MediaTrackConstraintSet) -> Option<MediaStreamId>;
fn create_audio_context(
&self,
id: &ClientContextId,
options: AudioContextOptions,
) -> Result<Arc<Mutex<AudioContext>>, AudioSinkError>;
fn create_webrtc(&self, signaller: Box<dyn WebRtcSignaller>) -> WebRtcController;
fn can_play_type(&self, media_type: &str) -> SupportsMediaType;
fn set_capture_mocking(&self, _mock: bool) {}
fn mute(&self, _id: &ClientContextId, _val: bool) {}
fn suspend(&self, _id: &ClientContextId) {}
fn resume(&self, _id: &ClientContextId) {}
fn get_device_monitor(&self) -> Box<dyn MediaDeviceMonitor>;
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SupportsMediaType {
Maybe,
No,
Probably,
}
impl ServoMedia {
pub fn init<B: BackendInit>() {
thread::spawn(|| INSTANCE.get_or_init(|| Arc::new(ServoMedia(B::init()))));
}
pub fn init_with_backend<F>(backend_factory: F)
where
F: Fn() -> Box<dyn Backend> + Send + 'static,
{
thread::spawn(move || INSTANCE.get_or_init(|| Arc::new(ServoMedia(backend_factory()))));
}
pub fn get() -> Result<Arc<ServoMedia>, ()> {
Ok(INSTANCE.wait().clone())
}
}
impl Deref for ServoMedia {
type Target = dyn Backend + 'static;
fn deref(&self) -> &(dyn Backend + 'static) {
&*self.0
}
}