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

Should we have both onplaypause and onplay/onpause? #141

Closed
xxyzzzq opened this issue Oct 14, 2016 · 15 comments
Closed

Should we have both onplaypause and onplay/onpause? #141

xxyzzzq opened this issue Oct 14, 2016 · 15 comments
Assignees

Comments

@xxyzzzq
Copy link
Contributor

xxyzzzq commented Oct 14, 2016

onplaypause is actually identical with onplay/onpause plus a playback state boolean. The difference is that:

  • For onplaypause, the boolean is maintained by the page
  • For onplay/onpause, the boolean is decided by the UA. The UA should use its best guess or we could let the page tell the playback state through a new attribute (we need to add them).
@mounirlamouri
Copy link
Member

CC @avayvod @jernoble who might have opinions.

IMO, exposing playpause is good because websites will be able to have their own logic if needed. If the event isn't overridden, the UA would have to figure out if the website is playing or paused but I think we want to expose an API that doesn't require this.

I think the use case is even stronger when combined with the Audio Focus API because a website could take Audio Focus without actually playing (or without the UA being entirely aware of it). In which case, they have to be able to implement their own logic.

@jernoble
Copy link

Thanks @mounirlamouri. I just commented on @xxyzzzq 's pull request, but for clarity, I'll reproduce it here.

Both YouTube and Netflix have user-displayed playback state that does not match the element's playback state. Without an "onplaypause" command, UA controls will frequently have either no effect, or the wrong effect. So, I would either encourage adding a playbackstate attribute immediately, or adding the onplaypause command back.

@mounirlamouri
Copy link
Member

As said in the PR, the playpause was added back :) Question is whether we want to keep it and I think we should keep it instead of introducing playbackState.

@jernoble
Copy link

Aha. Okay, the argument for having a playbackState attribute is that the UA might want to present both a "Play" and "Pause" UI, rather than a combined "Play/Pause" UI. Knowing which UI to show would require the UA to have knowledge of the playback state, and for common use cases, the playback state of the underlying <video> element doesn't match the playback state which the page's custom controls presents.

@mounirlamouri
Copy link
Member

Do you mind elaborating? Do you mean that the page might still be playing without UA knowledge? or that the controls on the page would expose a different state? It's not entirely clear what the concern is here.

@jernoble
Copy link

Yes. As an example, Netflix will display a "playing" state while seeking, even though the underlying video element is paused. Without either a playbackState property or a playpause Action, the UA would send a play action in this state, not pause.

@mounirlamouri
Copy link
Member

I would like to propose this:

enum MediaSessionPlaybackState {
  "none",
  "paused",
  "playing",
  "stopped",
};

[Constructor(MediaSessionPlaybackInit init)]
interface MediaSessionPlayback {
  readonly attribute MediaSessionPlaybackState state;
};

dictionary MediaSessionPlaybackInit {
  required MediaSessionPlaybackState state;
};

partial interface MediaSession {
  attribute MediaSessionPlayback? playback;
};

The idea is that we could extend this object with new data such as speed or position in MediaSessionPlayback in the future. The spec will also specify that the UA may ignore the advertized playback state in cases where it believes the page is playing and want to make sure the user is able to pause it, for example.

I think this will allow us to drop the playpause event as proposed in issue #148

@jernoble @xxyzzzq WDYT?

@xxyzzzq
Copy link
Contributor Author

xxyzzzq commented Dec 9, 2016

Just to clarify. IIUC, the four states mean:

  • none: the default value, meaning that the playback state is unspecified and the UA should use its best guess to determine the playback state.
  • paused: the playback state is paused and the page wants to receive play event.
  • playing: the playback state is playing and the page wants to receive pause event.
  • stopped: the page does not want to play anything.

Is this correct?

@mounirlamouri
Copy link
Member

Yes 👍

@jernoble
Copy link

jernoble commented Dec 9, 2016

@mounirlamouri

The idea is that we could extend this object with new data such as speed or position in MediaSessionPlayback in the future.

So in that future world where we include speed and position in MediaSessionPlayback, in order to update the playback state of a MediaSession, you have to create an entirely new object? I.e.:

function updatePlaybackState(event) {
    var video = event.target;
    video.session.playback = new MediaSessionPlayback({
        state = video.paused ? "paused" : "playing",
        speed = video.session.playback.speed,
        position = video.session.playback.position,
    });
}

Doesn't that seem heavy-handed? Why not just make MediaSessionPlayback.state read-write?

@mounirlamouri
Copy link
Member

The idea of the playback state is that it should be updated when there are significant changes. For example, position should not be updated all the time but just when the rest is updated. Having a read-only object helps make this model more clear.

This said, I agree it is a bit too much. Another approach is to have a setPlayback({ state: "playing", ... }) method instead. Otherwise, we can simply make the attributes on the object read-write and UA will deal with various attributes being changed. WDYT?

@jernoble
Copy link

jernoble commented Dec 9, 2016

@mounirlamouri

The idea of the playback state is that it should be updated when there are significant changes.

And that's fine so long as there's a single property on MediaSessionPlayback. But moving forward, this pattern will impose an increasing cost on authors for every new property added to it.

Another approach is to have a setPlayback({ state: "playing", ... }) method instead. Otherwise, we can simply make the attributes on the object read-write and UA will deal with various attributes being changed.

The first idea is an improvement. But I don't think it's strictly necessary, especially with some spec-language like "enqueue a task to update the UA based on the new values in MediaSessionPlayback." If the properties were read-write, authors could freely modify MediaSessionPlayback, and in the next run-loop the UA could treat it like an entirely new object, just like as in the playback = new MediaSessionPlayback({...}) case.

@beaufortfrancois
Copy link
Contributor

beaufortfrancois commented Dec 13, 2016

I wish it would be as simple as

function updatePlaybackState(event) {
  var video = event.target;
  navigator.mediaSession.playback.state = video.paused ? "paused" : "playing";
}

or

function updatePlaybackState(event) {
  var video = event.target;
  navigator.mediaSession.playbackState = video.paused ? "paused" : "playing";
}

@mounirlamouri
Copy link
Member

Given that we have a need for playbackState, maybe just adding this is the best thing and we will simply add the other properties when needed.

@jernoble does that work for you?

@jernoble
Copy link

LGTM. 👍🏼

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants