mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Register media instance with session and prepare communication with embedder
This commit is contained in:
parent
9c329a7935
commit
4d147d2c56
8 changed files with 107 additions and 4 deletions
|
@ -474,6 +474,9 @@ pub struct Constellation<Message, LTF, STF> {
|
|||
|
||||
/// Mechanism to force the compositor to process events.
|
||||
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
|
||||
|
||||
/// Browser ID of the active media session, if any.
|
||||
active_media_session: Option<TopLevelBrowsingContextId>,
|
||||
}
|
||||
|
||||
/// State needed to construct a constellation.
|
||||
|
@ -843,6 +846,7 @@ where
|
|||
glplayer_threads: state.glplayer_threads,
|
||||
player_context: state.player_context,
|
||||
event_loop_waker: state.event_loop_waker,
|
||||
active_media_session: None,
|
||||
};
|
||||
|
||||
constellation.run();
|
||||
|
@ -1774,6 +1778,9 @@ where
|
|||
new_value,
|
||||
);
|
||||
},
|
||||
FromScriptMsg::MediaSessionEventMsg(browser_id, event) => {
|
||||
// TODO
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,10 @@ use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaE
|
|||
use crate::dom::bindings::codegen::Bindings::HTMLSourceElementBinding::HTMLSourceElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorConstants::*;
|
||||
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorBinding::NavigatorMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
|
||||
use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
|
||||
use crate::dom::bindings::codegen::UnionTypes::{
|
||||
|
@ -78,6 +80,7 @@ use net_traits::request::{Destination, Referrer};
|
|||
use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, Metadata};
|
||||
use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType};
|
||||
use script_layout_interface::HTMLMediaData;
|
||||
use script_traits::MediaSessionEvent;
|
||||
use servo_config::pref;
|
||||
use servo_media::player::audio::AudioRenderer;
|
||||
use servo_media::player::video::{VideoFrame, VideoFrameRenderer};
|
||||
|
@ -592,7 +595,6 @@ impl HTMLMediaElement {
|
|||
match (old_ready_state, ready_state) {
|
||||
(ReadyState::HaveNothing, ReadyState::HaveMetadata) => {
|
||||
task_source.queue_simple_event(self.upcast(), atom!("loadedmetadata"), &window);
|
||||
|
||||
// No other steps are applicable in this case.
|
||||
return;
|
||||
},
|
||||
|
@ -1883,6 +1885,12 @@ impl HTMLMediaElement {
|
|||
self.media_element_load_algorithm();
|
||||
}
|
||||
}
|
||||
|
||||
fn send_media_session_event(&self, event: MediaSessionEvent) {
|
||||
let global = self.global();
|
||||
let media_session = global.as_window().Navigator().MediaSession();
|
||||
media_session.send_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Placeholder for [https://github.com/servo/servo/issues/22293]
|
||||
|
|
|
@ -11,12 +11,13 @@ use crate::dom::bindings::codegen::Bindings::MediaSessionBinding::MediaSessionMe
|
|||
use crate::dom::bindings::codegen::Bindings::MediaSessionBinding::MediaSessionPlaybackState;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
||||
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
||||
use crate::dom::htmlmediaelement::HTMLMediaElement;
|
||||
use crate::dom::mediametadata::MediaMetadata;
|
||||
use crate::dom::window::Window;
|
||||
use crate::script_thread::ScriptThread;
|
||||
use dom_struct::dom_struct;
|
||||
use msg::constellation_msg::TopLevelBrowsingContextId;
|
||||
use script_traits::MediaSessionActionType;
|
||||
use script_traits::{MediaSessionActionType, MediaSessionEvent, ScriptMsg};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -30,6 +31,9 @@ pub struct MediaSession {
|
|||
/// https://w3c.github.io/mediasession/#supported-media-session-actions
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
action_handlers: DomRefCell<HashMap<MediaSessionActionType, Rc<MediaSessionActionHandler>>>,
|
||||
/// The media instance controlled by this media session.
|
||||
/// For now only HTMLMediaElements are controlled by media sessions.
|
||||
media_instance: MutNullableDom<HTMLMediaElement>,
|
||||
}
|
||||
|
||||
impl MediaSession {
|
||||
|
@ -40,6 +44,7 @@ impl MediaSession {
|
|||
metadata: Default::default(),
|
||||
playback_state: DomRefCell::new(MediaSessionPlaybackState::None),
|
||||
action_handlers: DomRefCell::new(HashMap::new()),
|
||||
media_instance: Default::default(),
|
||||
};
|
||||
ScriptThread::register_media_session(&media_session, browsing_context_id);
|
||||
media_session
|
||||
|
@ -63,6 +68,18 @@ impl MediaSession {
|
|||
}
|
||||
// TODO default action.
|
||||
}
|
||||
|
||||
pub fn send_event(&self, event: MediaSessionEvent) {
|
||||
let global = self.global();
|
||||
let browser_id = global
|
||||
.as_window()
|
||||
.window_proxy()
|
||||
.top_level_browsing_context_id();
|
||||
let _ = global
|
||||
.script_to_constellation_chan()
|
||||
.send(ScriptMsg::MediaSessionEventMsg(browser_id, event))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl MediaSessionMethods for MediaSession {
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::dom::promise::Promise;
|
|||
use crate::dom::serviceworkercontainer::ServiceWorkerContainer;
|
||||
use crate::dom::window::Window;
|
||||
use crate::dom::xr::XR;
|
||||
use crate::script_thread::ScriptThread;
|
||||
use dom_struct::dom_struct;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -192,7 +193,24 @@ impl NavigatorMethods for Navigator {
|
|||
|
||||
/// https://w3c.github.io/mediasession/#dom-navigator-mediasession
|
||||
fn MediaSession(&self) -> DomRoot<MediaSession> {
|
||||
self.mediasession
|
||||
.or_init(|| MediaSession::new(self.global().as_window()))
|
||||
self.mediasession.or_init(|| {
|
||||
// There is a single MediaSession instance per top level browsing context
|
||||
// and only one active MediaSession globally.
|
||||
//
|
||||
// MediaSession creation can happen in two cases:
|
||||
//
|
||||
// - If content gets `navigator.mediaSession`
|
||||
// - If a media instance (HTMLMediaElement so far) starts playing media.
|
||||
//
|
||||
// The MediaSession constructor is in charge of registering itself with
|
||||
// the script thread.
|
||||
let global = self.global();
|
||||
let window = global.as_window();
|
||||
let browsing_context_id = window.window_proxy().top_level_browsing_context_id();
|
||||
match ScriptThread::get_media_session(browsing_context_id) {
|
||||
Some(session) => session,
|
||||
None => MediaSession::new(window),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3993,6 +3993,19 @@ impl ScriptThread {
|
|||
.remove(&browsing_context_id);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_media_session(
|
||||
browsing_context_id: TopLevelBrowsingContextId,
|
||||
) -> Option<DomRoot<MediaSession>> {
|
||||
SCRIPT_THREAD_ROOT.with(|root| {
|
||||
let script_thread = unsafe { &*root.get().unwrap() };
|
||||
script_thread
|
||||
.media_sessions
|
||||
.borrow()
|
||||
.get(&browsing_context_id)
|
||||
.map(|s| DomRoot::from_ref(&**s))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ScriptThread {
|
||||
|
|
|
@ -1087,3 +1087,34 @@ pub enum MediaSessionActionType {
|
|||
/// The action intent is to move the playback time to a specific time.
|
||||
SeekTo,
|
||||
}
|
||||
|
||||
/// https://w3c.github.io/mediasession/#mediametadata
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct MediaMetadata {
|
||||
/// Title
|
||||
pub title: String,
|
||||
/// Artist
|
||||
pub artist: Option<String>,
|
||||
/// Album
|
||||
pub album: Option<String>,
|
||||
}
|
||||
|
||||
/// https://w3c.github.io/mediasession/#enumdef-mediasessionplaybackstate
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub enum MediaSessionPlaybackState {
|
||||
/// The browsing context does not specify whether it’s playing or paused.
|
||||
None_,
|
||||
/// The browsing context has paused media and it can be resumed.
|
||||
Playing,
|
||||
/// The browsing context is currently playing media and it can be paused.
|
||||
Paused,
|
||||
}
|
||||
|
||||
/// Type of events sent from script to the constellation about the media session.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub enum MediaSessionEvent {
|
||||
/// Indicates that the media metadata is available.
|
||||
SetMetadata(MediaMetadata),
|
||||
/// Indicates that the playback state has changed.
|
||||
PlaybackStateChange(MediaSessionPlaybackState),
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::DocumentState;
|
|||
use crate::IFrameLoadInfoWithData;
|
||||
use crate::LayoutControlMsg;
|
||||
use crate::LoadData;
|
||||
use crate::MediaSessionEvent;
|
||||
use crate::MessagePortMsg;
|
||||
use crate::PortMessageTask;
|
||||
use crate::StructuredSerializedData;
|
||||
|
@ -254,6 +255,9 @@ pub enum ScriptMsg {
|
|||
GetScreenSize(IpcSender<DeviceIntSize>),
|
||||
/// Get the available screen size (pixel)
|
||||
GetScreenAvailSize(IpcSender<DeviceIntSize>),
|
||||
/// Notifies the constellation about media session events
|
||||
/// (i.e. when there is metadata for the active media session, playback state changes...).
|
||||
MediaSessionEventMsg(TopLevelBrowsingContextId, MediaSessionEvent),
|
||||
}
|
||||
|
||||
impl fmt::Debug for ScriptMsg {
|
||||
|
@ -305,6 +309,7 @@ impl fmt::Debug for ScriptMsg {
|
|||
GetClientWindow(..) => "GetClientWindow",
|
||||
GetScreenSize(..) => "GetScreenSize",
|
||||
GetScreenAvailSize(..) => "GetScreenAvailSize",
|
||||
MediaSessionEventMsg(..) => "MediaSessionEventMsg",
|
||||
};
|
||||
write!(formatter, "ScriptMsg::{}", variant)
|
||||
}
|
||||
|
|
|
@ -449,6 +449,10 @@ where
|
|||
error!("Failed to store profile: {}", e);
|
||||
}
|
||||
},
|
||||
EmbedderMsg::MediaSession(_) => {
|
||||
debug!("MediaSession received");
|
||||
// TODO(ferjm)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue