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

Handling Chromecast sessions in single page apps: "session_error" #70

Closed
sergioavazquez opened this issue Jun 30, 2017 · 10 comments
Closed

Comments

@sergioavazquez
Copy link

I'm using React to build a single page app, and as I "re-mount" the player and cast I get different results. Sometimes it works, sometimes it doesn't. Sometimes it throws:

Unknown error: session_error
_getErrorMessage @ player.js:296
castSession.loadMedia.then @ player.js:240

steps to reproduce:

  • Mount Mediaelement player.
  • Cast to a chromecast device.
  • stop the cast and unmount the player.
  • Mount Mediaelement player.
  • Cast to a chromecast device.

I've been trying to clean up the cast session when unmounting the player so when I mount it again, the entire environment is exactly the same as when I mounted it and casted for the first time.

Casting works perfectly using the latest versions, mediaelement 4.2.2 and mediaelement-plugins 2.3.0.
Mounting and unmounting works fine when just using the player.

This is the function that throws the error as it fails to load media request: (player.js:231)

castSession.loadMedia(request).then(() => {
			// Autoplay media in the current position
			const currentTime = t.media.originalNode.currentTime;
			t.setCurrentTime(currentTime);
			t.play();

			const event = mejs.Utils.createEvent('play', t.media);
			t.media.dispatchEvent(event);
		}, (error) => {
			t._getErrorMessage(error);
		});

I do the following when unmounting to stop the cast, after pausing and removing the player:

          if(window.cast){
            let context = window.cast.framework.CastContext.getInstance();
            if(context.getSessionState() !== "NO_SESSION" && context.getSessionState() !== "SESSION_ENDED"){
              context.endCurrentSession(true);
            }

Cast stops. No errors.

Setting up a breakpoint in player.js:231 -> castSession.loadMedia(request).then(() => {
I found out that previous sessions still exists as more requests to loadMedia are being sent as I repeat the mounting-unmounting process over and over.

Steps to reproduce:
Mount a player with channel A as a source. Cast, stop, unmount.
Mount a player with channel B as a source. Cast, stop, unmount.

Now, mount the player again with channel C as source and cast with the breakpoint enabled.
Execution will stop due to the breakpoint on line 231.

If you wait, you'll see channel A being casted, which makes sense if you examine the request content while on break.
Resume execution.
Execution stops again due to a request to cast channel B.
Resume execution.
Channel B is now being casted....
Execution stops again due to a request to cast channel C.
Resume.

Notes:

  • I never got a session error while debugging and waiting for the cast to stream.

  • Sometimes I get several session_error messages at once. Because it's loading all the previous contents. Sometimes all of them throw the error, sometimes one of them, etc.

  • The event listener added on line 282 of chromecast.js remains being called for previous sessions as well:

t.media.addEventListener('loadedmetadata', () => {
			if (['SESSION_ENDING', 'SESSION_ENDED', 'NO_SESSION'].indexOf(castSession.getSessionState()) === -1 &&
				t.proxy instanceof DefaultPlayer) {
				t.proxy.pause();
				t.proxy = new ChromecastPlayer(t.remotePlayer, t.remotePlayerController, t.media, t.options);
			}
		});

It can be verified by setting a breakpoint on that line.

Bottom line I need to eliminate those sessions. Any ideas on how to achieve that?

Thanks in advance.

@rafa8626
Copy link
Contributor

rafa8626 commented Jul 1, 2017

Thanks for all these useful info. There's not a lot of sources on how to achieve this and I'll look more into Cast documentation but I have no idea how to remove the sessions since that's what I was trying to do originally. I'll keep looking and keep you posted. Thanks again

@rafa8626
Copy link
Contributor

rafa8626 commented Jul 1, 2017

Can you do me a favor: in Chromecast.js create a method called cleanchromecast and put the code you use the code you set up to remove the current session and see if it does any good

@rafa8626
Copy link
Contributor

rafa8626 commented Jul 1, 2017

Also take a look at this Fiddle and see if anything could work for you: https://jsfiddle.net/gurupras/sgLfcocq/

@rafa8626
Copy link
Contributor

rafa8626 commented Jul 1, 2017

I fond this snippet and maybe that's the answer. Can you try using this?

function stopCasting() {
  var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
  // End the session and pass 'true' to indicate
  // that receiver application should be stopped.
  castSession.endSession(true);
}

@sergioavazquez
Copy link
Author

I had already tried the last snippet but I added it to cleanchromecast(), added it on unmounting and all combinations I could come up with. Regardless of how you end the session, if you open chrome's console immediately afterwards, get the context instance (window.cast.framework.CastContext.getInstance()) and request a session (session.requestSession()), previous cast resumes. Apparently we need to kill the context, because as soon as you request a session on the same context everything you did on that context is still there.
I'm going to explore the fiddle you sent, but I believe the best and cleanest solution is to reset the context rather than having to handle sessions and a lot of code that I don't really need.
I tried removing the entire cast framework on unmounting with that purpose but that generates a lot of errors and I can't get it to cast again.
I'm going to keep digging...

@sergioavazquez
Copy link
Author

I tried creating a new context, since it's a singleton it should replace the previous one but apparently you cannot get a session from it so chomecast.js throws and error. Also tried to set up a castOption: resumeSavedSession to false but no luck...

@rafa8626
Copy link
Contributor

rafa8626 commented Jul 4, 2017

Thanks I'll keep looking in the documentation about how to do this properly or I'll ask the question directly if I'm at lost

@rafa8626
Copy link
Contributor

rafa8626 commented Jul 5, 2017

@sergioavazquez I have updated the plugin with a missing workflow to avoid loading a request more than once, and destroying Cast session properly. Please download the master branch and let me know if it worked for you. I tested on my local ReactJS env and seemed to work just fine.

@sergioavazquez
Copy link
Author

@rafa8626 you nailed it! It's working like a charm...

@rafa8626
Copy link
Contributor

rafa8626 commented Jul 5, 2017

Excellent news!! Thanks for testing this good team work

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

2 participants