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

fix: Wait for loadstart when changing sources, instead of just ready. #4743

Merged
merged 6 commits into from
Nov 16, 2017

Conversation

misteroneill
Copy link
Member

The core goal here is to make sure the following works in light of some middleware process that makes setting the source more async than next tick:

player.src('...');
player.ready(() => player.play());

In fact, given this change, we should even be able to do:

player.src('...');
player.play();

Unlike #4665, which would have clarified/changed the meaning of "ready", it remains a reflection of the tech's state and we make better use of the ability to queue things on that state and on the middleware setSource process.

Requirements Checklist

  • Feature implemented / Bug fixed
  • Reviewed by Two Core Contributors

src/js/player.js Outdated

// Only calls the tech's play if we already have a src loaded
} else if (this.isReady_ && (this.src() || this.currentSrc())) {
// If the tech is not ready, queue up another call to `play()` for when it
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The key change in all this is that we kind of have a "checklist" of conditions before we can attempt playback.

First, we need the tech to be ready before anything else. When that's satisfied, play() gets called again.

Second, we need to make sure middleware isn't changing sources. When that's satisfied by a loadstart, we call play() again.

Finally, both conditions should be satisfied, so we can attempt playback if there's a source.

Copy link
Member

@gkatsev gkatsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable. Wondering if it's possible we fell through all the ifs in play.


this.playWaitingForReady_ = true;
this.ready(() => {
this.playWaitingForReady_ = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we set this in the constructor to a default value as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

src/js/player.js Outdated

// Finally, if we have a source, we can attempt playback for real.
} else if (this.src() || this.currentSrc()) {
return this.techGet_('play');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible that we end up in an else condition?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been trying to think of one that isn't captured by the previous two statements, but I haven't been able to. It probably makes sense to reverse this conditional block so the ready call comes in the else block.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, yeah, the only condition that we'd have that would be an else would be if the tech is ready, we're not changing sources, and we don't have a source.


playPromise.then(playFocus, ignoreRejectedPlayPromise);
if (isPromise(playPromise)) {
playPromise.then(playFocus, () => {});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not import silencePromise and use that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy/paste from my other PR, good call.

Copy link
Member Author

@misteroneill misteroneill Nov 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, actually, we can't because it's not silencing it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't? What the difference between ignoreRejectedPlayPromise and silencePromise?

Oh, I see. We are silencing the playPromise but we're also adding a playFocus handler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could potentially do something like:

if (isPromise(playPromise)) {
  silencePromise(playPromise);
  playPromise.then(playFocus);
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like overkill...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, either way. using silencePromise is probably extra explicit/clear but either is fine.

});

QUnit.test('can identify a Promise-like object', function(assert) {
assert.notOk(promise.isPromise({}));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertion messages?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess... 😛


beforeEach() {
this.clock = sinon.useFakeTimers();
this.player = TestHelpers.makePlayer({techOrder: ['html5']});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the html5 tech is required for testing, we'd want to wrap this file in a !IS_IE8.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it actually is. It can probably use the fake tech.

Copy link
Member

@gkatsev gkatsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to work for me and doesn't break videojs-playlist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed patch This PR can be added to a patch release.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants