Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement mediasession set positon state #24885

Merged
Next

implement MediaSession.setPositionState method

  • Loading branch information
shnmorimoto committed Dec 2, 2019
commit 274d4d2303fa2986da356dd2d05adcb48d796a2a
@@ -1925,6 +1925,18 @@ impl HTMLMediaElement {

media_session.send_event(event);
}

pub fn set_duration(&self, duration: f64) {
self.duration.set(duration);
}

pub fn reset(&self) {
if let Some(ref player) = *self.player.borrow() {
if let Err(e) = player.lock().unwrap().stop() {
eprintln!("Could not stop player {:?}", e);
}
}
}
}

// XXX Placeholder for [https://github.com/servo/servo/issues/22293]
@@ -9,10 +9,13 @@ use crate::dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaE
use crate::dom::bindings::codegen::Bindings::MediaMetadataBinding::MediaMetadataInit;
use crate::dom::bindings::codegen::Bindings::MediaMetadataBinding::MediaMetadataMethods;
use crate::dom::bindings::codegen::Bindings::MediaSessionBinding;
use crate::dom::bindings::codegen::Bindings::MediaSessionBinding::MediaPositionState;
use crate::dom::bindings::codegen::Bindings::MediaSessionBinding::MediaSessionAction;
use crate::dom::bindings::codegen::Bindings::MediaSessionBinding::MediaSessionActionHandler;
use crate::dom::bindings::codegen::Bindings::MediaSessionBinding::MediaSessionMethods;
use crate::dom::bindings::codegen::Bindings::MediaSessionBinding::MediaSessionPlaybackState;
use crate::dom::bindings::error::{Error, Fallible};
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString;
@@ -194,6 +197,62 @@ impl MediaSessionMethods for MediaSession {
None => self.action_handlers.borrow_mut().remove(&action.into()),
};
}

/// https://w3c.github.io/mediasession/#dom-mediasession-setpositionstate
fn SetPositionState(&self, state: &MediaPositionState) -> Fallible<()> {
// If the state is an empty dictionary then clear the position state.
if state.duration.is_none() && state.position.is_none() && state.playbackRate.is_none() {
This conversation was marked as resolved by jdm

This comment has been minimized.

Copy link
@shnmorimoto

shnmorimoto Nov 27, 2019

Author Contributor

https://w3c.github.io/mediasession/#dom-mediasession-setpositionstate

If the state is an empty dictionary then clear the position state.

Is the position state the combination of duration and playback_position and playbackRate in media_instance(type is HTMLMediaElement)?
And, Does clear mean to set at 0?

This comment has been minimized.

Copy link
@ferjm

ferjm Nov 28, 2019

Member

That's my understanding reading the spec.

Rather than setting these values to 0, I would expose a reset method in HTMLMediaElement which should call stop in the inner player. Like

if let Err(e) = player.lock().unwrap().stop() {

This comment has been minimized.

Copy link
@shnmorimoto

shnmorimoto Nov 29, 2019

Author Contributor

Thanks! I added the reset method, and fixed to use it.

if let Some(media_instance) = self.media_instance.get() {
media_instance.reset();
}
return Ok(());
}

// If the duration is not present or its value is null, throw a TypeError.
if state.duration.is_none() {
return Err(Error::Type(
"duration is not present or its value is null".to_owned(),
));
}

// If the duration is negative, throw a TypeError.
if let Some(state_duration) = state.duration {
if *state_duration < 0.0 {
return Err(Error::Type("duration is negative".to_owned()));
}
}

// If the position is negative or greater than duration, throw a TypeError.
if let Some(state_position) = state.position {
if *state_position < 0.0 {
return Err(Error::Type("position is negative".to_owned()));
}
if let Some(state_duration) = state.duration {
if *state_position > *state_duration {
return Err(Error::Type("position is greater than duration".to_owned()));
}
}
}

// If the playbackRate is zero throw a TypeError.
if let Some(state_playback_rate) = state.playbackRate {
if *state_playback_rate <= 0.0 {
return Err(Error::Type("playbackRate is zero".to_owned()));
}
}

// Update the position state and last position updated time.
if let Some(media_instance) = self.media_instance.get() {
media_instance.set_duration(state.duration.map(|v| *v).unwrap());
// If the playbackRate is not present or its value is null, set it to 1.0.
let _ =
media_instance.SetPlaybackRate(state.playbackRate.unwrap_or(Finite::wrap(1.0)))?;
// If the position is not present or its value is null, set it to zero.
media_instance.SetCurrentTime(state.position.unwrap_or(Finite::wrap(0.0)));
}

Ok(())
}
}

impl From<MediaSessionAction> for MediaSessionActionType {
@@ -42,6 +42,12 @@ dictionary MediaSessionSeekToActionDetails : MediaSessionActionDetails {
boolean? fastSeek;
};

dictionary MediaPositionState {
double duration;
double playbackRate;
double position;
};

callback MediaSessionActionHandler = void(/*MediaSessionActionDetails details*/);

[Exposed=Window]
@@ -52,6 +58,5 @@ interface MediaSession {

void setActionHandler(MediaSessionAction action, MediaSessionActionHandler? handler);

//void setPositionState(optional MediaPositionState? state);
[Throws] void setPositionState(optional MediaPositionState state = {});
};

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.