mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Introduce embedder MediaSessionEvent and move active session to Servo
This commit is contained in:
parent
4d147d2c56
commit
89d9e3ad78
9 changed files with 90 additions and 61 deletions
|
@ -1778,9 +1778,6 @@ where
|
|||
new_value,
|
||||
);
|
||||
},
|
||||
FromScriptMsg::MediaSessionEventMsg(browser_id, event) => {
|
||||
// TODO
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -162,9 +162,9 @@ pub enum EmbedderMsg {
|
|||
Shutdown,
|
||||
/// Report a complete sampled profile
|
||||
ReportProfile(Vec<u8>),
|
||||
/// Sent when a media session is activated or deactivated.
|
||||
/// There can only be a single active media session.
|
||||
MediaSession(bool),
|
||||
/// Notifies the embedder about media session events
|
||||
/// (i.e. when there is metadata for the active media session, playback state changes...).
|
||||
MediaSessionEvent(MediaSessionEvent),
|
||||
}
|
||||
|
||||
impl Debug for EmbedderMsg {
|
||||
|
@ -197,7 +197,7 @@ impl Debug for EmbedderMsg {
|
|||
EmbedderMsg::AllowOpeningBrowser(..) => write!(f, "AllowOpeningBrowser"),
|
||||
EmbedderMsg::BrowserCreated(..) => write!(f, "BrowserCreated"),
|
||||
EmbedderMsg::ReportProfile(..) => write!(f, "ReportProfile"),
|
||||
EmbedderMsg::MediaSession(..) => write!(f, "MediaSession"),
|
||||
EmbedderMsg::MediaSessionEvent(..) => write!(f, "MediaSessionEvent"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,3 +206,34 @@ impl Debug for EmbedderMsg {
|
|||
/// the `String` content is expected to be extension (e.g, "doc", without the prefixing ".")
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct FilterPattern(pub String);
|
||||
|
||||
/// 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 embedder 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),
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ use crate::script_thread::ScriptThread;
|
|||
use crate::task_source::TaskSource;
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::resources::{self, Resource as EmbedderResource};
|
||||
use embedder_traits::{MediaMetadata, MediaSessionEvent};
|
||||
use euclid::default::Size2D;
|
||||
use headers::{ContentLength, ContentRange, HeaderMapExt};
|
||||
use html5ever::{LocalName, Prefix};
|
||||
|
@ -80,7 +81,6 @@ 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};
|
||||
|
@ -1727,6 +1727,14 @@ impl HTMLMediaElement {
|
|||
if self.Controls() {
|
||||
self.render_controls();
|
||||
}
|
||||
|
||||
// Send a media session event with the obtained metadata.
|
||||
self.send_media_session_event(MediaSessionEvent::SetMetadata(MediaMetadata {
|
||||
// TODO(ferjm) set url if no title.
|
||||
title: metadata.title.clone().unwrap_or("".to_string()),
|
||||
artist: None,
|
||||
album: None,
|
||||
}));
|
||||
},
|
||||
PlayerEvent::NeedData => {
|
||||
// The player needs more data.
|
||||
|
|
|
@ -16,8 +16,9 @@ use crate::dom::mediametadata::MediaMetadata;
|
|||
use crate::dom::window::Window;
|
||||
use crate::script_thread::ScriptThread;
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::{EmbedderMsg, MediaSessionEvent};
|
||||
use msg::constellation_msg::TopLevelBrowsingContextId;
|
||||
use script_traits::{MediaSessionActionType, MediaSessionEvent, ScriptMsg};
|
||||
use script_traits::MediaSessionActionType;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -71,14 +72,8 @@ impl MediaSession {
|
|||
|
||||
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();
|
||||
let window = global.as_window();
|
||||
window.send_to_embedder(EmbedderMsg::MediaSessionEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1087,34 +1087,3 @@ 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),
|
||||
}
|
||||
|
|
|
@ -255,9 +255,6 @@ 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 {
|
||||
|
@ -309,7 +306,6 @@ impl fmt::Debug for ScriptMsg {
|
|||
GetClientWindow(..) => "GetClientWindow",
|
||||
GetScreenSize(..) => "GetScreenSize",
|
||||
GetScreenAvailSize(..) => "GetScreenAvailSize",
|
||||
MediaSessionEventMsg(..) => "MediaSessionEventMsg",
|
||||
};
|
||||
write!(formatter, "ScriptMsg::{}", variant)
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ use constellation::{Constellation, InitialConstellationState, UnprivilegedPipeli
|
|||
use constellation::{FromCompositorLogger, FromScriptLogger};
|
||||
use crossbeam_channel::{unbounded, Sender};
|
||||
use embedder_traits::{EmbedderMsg, EmbedderProxy, EmbedderReceiver, EventLoopWaker};
|
||||
use embedder_traits::{MediaSessionEvent, MediaSessionPlaybackState};
|
||||
use env_logger::Builder as EnvLoggerBuilder;
|
||||
use euclid::{Scale, Size2D};
|
||||
#[cfg(all(
|
||||
|
@ -270,6 +271,9 @@ pub struct Servo<Window: WindowMethods + 'static + ?Sized> {
|
|||
embedder_receiver: EmbedderReceiver,
|
||||
embedder_events: Vec<(Option<BrowserId>, EmbedderMsg)>,
|
||||
profiler_enabled: bool,
|
||||
webgl_thread_data: Option<Rc<WebGLMainThread>>,
|
||||
/// Browser ID of the active media session, if any.
|
||||
active_media_session: Option<BrowserId>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -555,6 +559,8 @@ where
|
|||
embedder_receiver: embedder_receiver,
|
||||
embedder_events: Vec::new(),
|
||||
profiler_enabled: false,
|
||||
webgl_thread_data,
|
||||
active_media_session: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -744,6 +750,31 @@ where
|
|||
self.embedder_events.push(event);
|
||||
},
|
||||
|
||||
(EmbedderMsg::MediaSessionEvent(event), ShutdownState::NotShuttingDown) => {
|
||||
// Unlikely at this point, but we may receive events coming from
|
||||
// different media sessions, so we set the active media session based
|
||||
// on Playing events.
|
||||
// The last media session claiming to be in playing state is set to
|
||||
// the active media session.
|
||||
// Events coming from inactive media sessions are discarded.
|
||||
if self.active_media_session.is_some() {
|
||||
match event {
|
||||
MediaSessionEvent::PlaybackStateChange(ref state) => {
|
||||
match state {
|
||||
MediaSessionPlaybackState::Playing => (),
|
||||
_ => return,
|
||||
};
|
||||
},
|
||||
_ => (),
|
||||
};
|
||||
}
|
||||
self.active_media_session = top_level_browsing_context;
|
||||
self.embedder_events.push((
|
||||
top_level_browsing_context,
|
||||
EmbedderMsg::MediaSessionEvent(event),
|
||||
));
|
||||
},
|
||||
|
||||
(msg, ShutdownState::NotShuttingDown) => {
|
||||
self.embedder_events.push((top_level_browsing_context, msg));
|
||||
},
|
||||
|
|
|
@ -42,6 +42,7 @@ thread_local! {
|
|||
/// It will be called to notify embedder that some events are available,
|
||||
/// and that perform_updates need to be called
|
||||
pub use servo::embedder_traits::EventLoopWaker;
|
||||
pub use servo::embedder_traits::MediaSessionEvent;
|
||||
|
||||
pub struct InitOptions {
|
||||
pub args: Vec<String>,
|
||||
|
@ -130,8 +131,8 @@ pub trait HostTrait {
|
|||
fn get_clipboard_contents(&self) -> Option<String>;
|
||||
/// Sets system clipboard contents
|
||||
fn set_clipboard_contents(&self, contents: String);
|
||||
/// Called when a media session is activated or deactivated.
|
||||
fn on_media_session(&self, active: bool);
|
||||
/// Called when there is a new media session event.
|
||||
fn on_media_session_event(&self, event: MediaSessionEvent);
|
||||
}
|
||||
|
||||
pub struct ServoGlue {
|
||||
|
@ -583,8 +584,8 @@ impl ServoGlue {
|
|||
EmbedderMsg::HideIME => {
|
||||
self.callbacks.host_callbacks.on_ime_state_changed(false);
|
||||
},
|
||||
EmbedderMsg::MediaSession(active) => {
|
||||
self.callbacks.host_callbacks.on_media_session(active);
|
||||
EmbedderMsg::MediaSessionEvent(event) => {
|
||||
self.callbacks.host_callbacks.on_media_session_event(event);
|
||||
},
|
||||
EmbedderMsg::Status(..) |
|
||||
EmbedderMsg::SelectFiles(..) |
|
||||
|
|
|
@ -17,7 +17,7 @@ use env_logger;
|
|||
use log::LevelFilter;
|
||||
use simpleservo::{self, gl_glue, ServoGlue, SERVO};
|
||||
use simpleservo::{
|
||||
Coordinates, EventLoopWaker, HostTrait, InitOptions, MouseButton, VRInitOptions,
|
||||
Coordinates, EventLoopWaker, HostTrait, InitOptions, MediaSessionEvent, MouseButton, VRInitOptions,
|
||||
};
|
||||
use std::ffi::{CStr, CString};
|
||||
#[cfg(target_os = "windows")]
|
||||
|
@ -216,7 +216,8 @@ pub struct CHostCallbacks {
|
|||
pub on_ime_state_changed: extern "C" fn(show: bool),
|
||||
pub get_clipboard_contents: extern "C" fn() -> *const c_char,
|
||||
pub set_clipboard_contents: extern "C" fn(contents: *const c_char),
|
||||
pub on_media_session: extern "C" fn(active: bool),
|
||||
// TODO(ferjm) pass C representation of media event.
|
||||
pub on_media_session_event: extern "C" fn(),
|
||||
}
|
||||
|
||||
/// Servo options
|
||||
|
@ -710,8 +711,8 @@ impl HostTrait for HostCallbacks {
|
|||
(self.0.set_clipboard_contents)(contents.as_ptr());
|
||||
}
|
||||
|
||||
fn on_media_session(&self, active: bool) {
|
||||
debug!("on_media_session (active: {:?})", active);
|
||||
(self.0.on_media_session)(active);
|
||||
fn on_media_session_event(&self, event: MediaSessionEvent) {
|
||||
debug!("on_media_session_event (event: {:?})", event);
|
||||
(self.0.on_media_session_event)();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue