diff --git a/mobile/android/base/ChromeCast.java b/mobile/android/base/ChromeCast.java index 6f2a11209d5..b7187558d01 100644 --- a/mobile/android/base/ChromeCast.java +++ b/mobile/android/base/ChromeCast.java @@ -45,6 +45,9 @@ class ChromeCast implements GeckoMediaPlayer { private GoogleApiClient apiClient; private RemoteMediaPlayer remoteMediaPlayer; private boolean canMirror; + private String mSessionId; + private MirrorChannel mMirrorChannel; + private boolean mApplicationStarted = false; // Callback to start playback of a url on a remote device private class VideoPlayCallback implements ResultCallback, @@ -90,6 +93,7 @@ class ChromeCast implements GeckoMediaPlayer { remoteMediaPlayer = new RemoteMediaPlayer(); remoteMediaPlayer.setOnStatusUpdatedListener(this); remoteMediaPlayer.setOnMetadataUpdatedListener(this); + mSessionId = result.getSessionId(); try { Cast.CastApi.setMessageReceivedCallbacks(apiClient, remoteMediaPlayer.getNamespace(), remoteMediaPlayer); @@ -99,7 +103,7 @@ class ChromeCast implements GeckoMediaPlayer { startPlayback(); } else { - callback.sendError(null); + callback.sendError(status.toString()); } } @@ -122,7 +126,7 @@ class ChromeCast implements GeckoMediaPlayer { } debug("Media load failed " + result.getStatus()); - callback.sendError(null); + callback.sendError(result.getStatus().toString()); } }); @@ -133,7 +137,7 @@ class ChromeCast implements GeckoMediaPlayer { debug("Problem opening media during loading", e); } - callback.sendError(null); + callback.sendError(""); } } @@ -188,6 +192,8 @@ class ChromeCast implements GeckoMediaPlayer { @Override public void onConnected(Bundle connectionHint) { if (!apiClient.isConnected()) { + debug("Connection failed"); + callback.sendError("Not connected"); return; } @@ -219,14 +225,34 @@ class ChromeCast implements GeckoMediaPlayer { callback.sendSuccess(null); } + public boolean verifySession(final EventCallback callback) { + if (apiClient == null || !apiClient.isConnected()) { + debug("Can't play. No connection"); + callback.sendError("Not connected"); + return false; + } + + if (mSessionId == null) { + debug("Can't play. No session"); + callback.sendError("No session"); + return false; + } + + return true; + } + public void play(final EventCallback callback) { + if (!verifySession(callback)) { + return; + } + remoteMediaPlayer.play(apiClient).setResultCallback(new ResultCallback() { @Override public void onResult(MediaChannelResult result) { Status status = result.getStatus(); if (!status.isSuccess()) { - debug("Unable to toggle pause: " + status.getStatusCode()); - callback.sendError(null); + debug("Unable to play: " + status.getStatusCode()); + callback.sendError(status.toString()); } else { callback.sendSuccess(null); } @@ -235,13 +261,17 @@ class ChromeCast implements GeckoMediaPlayer { } public void pause(final EventCallback callback) { + if (!verifySession(callback)) { + return; + } + remoteMediaPlayer.pause(apiClient).setResultCallback(new ResultCallback() { @Override public void onResult(MediaChannelResult result) { Status status = result.getStatus(); if (!status.isSuccess()) { - debug("Unable to toggle pause: " + status.getStatusCode()); - callback.sendError(null); + debug("Unable to pause: " + status.getStatusCode()); + callback.sendError(status.toString()); } else { callback.sendSuccess(null); } @@ -250,6 +280,10 @@ class ChromeCast implements GeckoMediaPlayer { } public void end(final EventCallback callback) { + if (!verifySession(callback)) { + return; + } + Cast.CastApi.stopApplication(apiClient).setResultCallback(new ResultCallback() { @Override public void onResult(Status result) { @@ -257,6 +291,7 @@ class ChromeCast implements GeckoMediaPlayer { try { Cast.CastApi.removeMessageReceivedCallbacks(apiClient, remoteMediaPlayer.getNamespace()); remoteMediaPlayer = null; + mSessionId = null; apiClient.disconnect(); apiClient = null; @@ -271,18 +306,13 @@ class ChromeCast implements GeckoMediaPlayer { } if (callback != null) { - callback.sendError(null); + callback.sendError(result.getStatus().toString()); } } }); } - private String mSessionId; - MirrorChannel mMirrorChannel; - boolean mApplicationStarted = false; - class MirrorChannel implements MessageReceivedCallback { - /** * @return custom namespace */ @@ -347,7 +377,7 @@ class ChromeCast implements GeckoMediaPlayer { GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Casting:Mirror", route.getId())); } else { - callback.sendError(null); + callback.sendError(status.toString()); } } } diff --git a/mobile/android/chrome/content/CastingApps.js b/mobile/android/chrome/content/CastingApps.js index 179e4ac0c5b..72aad7c0fbe 100644 --- a/mobile/android/chrome/content/CastingApps.js +++ b/mobile/android/chrome/content/CastingApps.js @@ -542,8 +542,11 @@ var CastingApps = { } this.session.remoteMedia.shutdown(); - this.session.app.stop(); + this._shutdown(); + }, + _shutdown: function() { + this.session.app.stop(); let video = this.session.videoRef.get(); if (video) { this._sendEventToVideo(video, { active: false }); @@ -571,6 +574,7 @@ var CastingApps = { onRemoteMediaStop: function(aRemoteMedia) { sendMessageToJava({ type: "Casting:Stopped" }); + this._shutdown(); }, onRemoteMediaStatus: function(aRemoteMedia) { diff --git a/mobile/android/modules/MediaPlayerApp.jsm b/mobile/android/modules/MediaPlayerApp.jsm index 6828c6d8112..bdf11948246 100644 --- a/mobile/android/modules/MediaPlayerApp.jsm +++ b/mobile/android/modules/MediaPlayerApp.jsm @@ -36,14 +36,18 @@ function MediaPlayerApp(service) { MediaPlayerApp.prototype = { start: function start(callback) { - send("MediaPlayer:Start", { id: this.id }, (result) => { - if (callback) callback(true); + send("MediaPlayer:Start", { id: this.id }, (result, err) => { + if (callback) { + callback(err == null); + } }); }, stop: function stop(callback) { - send("MediaPlayer:Stop", { id: this.id }, (result) => { - if (callback) callback(true); + send("MediaPlayer:Stop", { id: this.id }, (result, err) => { + if (callback) { + callback(err == null); + } }); }, @@ -54,8 +58,10 @@ MediaPlayerApp.prototype = { }, mirror: function mirror(callback) { - send("MediaPlayer:Mirror", { id: this.id }, (result) => { - if (callback) callback(true); + send("MediaPlayer:Mirror", { id: this.id }, (result, err) => { + if (callback) { + callback(err == null); + } }); } } @@ -75,7 +81,7 @@ function RemoteMedia(id, listener) { RemoteMedia.prototype = { shutdown: function shutdown() { - this._send("MediaPlayer:End", {}, (result) => { + this._send("MediaPlayer:End", {}, (result, err) => { this._status = "shutdown"; if ("onRemoteMediaStop" in this._listener) { this._listener.onRemoteMediaStop(this); @@ -84,19 +90,37 @@ RemoteMedia.prototype = { }, play: function play() { - this._send("MediaPlayer:Play", {}, (result) => { + this._send("MediaPlayer:Play", {}, (result, err) => { + if (err) { + Cu.reportError("Can't play " + err); + this.shutdown(); + return; + } + this._status = "started"; }); }, pause: function pause() { - this._send("MediaPlayer:Pause", {}, (result) => { + this._send("MediaPlayer:Pause", {}, (result, err) => { + if (err) { + Cu.reportError("Can't pause " + err); + this.shutdown(); + return; + } + this._status = "paused"; }); }, load: function load(aData) { - this._send("MediaPlayer:Load", aData, (result) => { + this._send("MediaPlayer:Load", aData, (result, err) => { + if (err) { + Cu.reportError("Can't load " + err); + this.shutdown(); + return; + } + this._status = "started"; }) },