(function () { 'use strict'; var CastPlayer = function () { this.castSession = null; this.mediaSession = null; this.volume = 1.0; }; CastPlayer.prototype.initializeCastPlayer = function () { if (!window.chrome) { return; } if (!chrome.cast || !chrome.cast.isAvailable) { setTimeout(this.initializeCastPlayer.bind(this), 1000); return; } var applicationID = "4FBFE470"; var sessionRequest = new chrome.cast.SessionRequest(applicationID); var apiConfig = new chrome.cast.ApiConfig(sessionRequest, this.sessionListener.bind(this), this.receiverListener.bind(this)); chrome.cast.initialize(apiConfig, this.onInitSuccess.bind(this), this.onError.bind(this)); }; /** * session listener during initialization */ CastPlayer.prototype.sessionListener = function (s) { this.log('New session ID:' + s.sessionId); this.castSession = s; this.setCastControlsVisible(true); if (this.castSession.media.length > 0) { this.log('Found ' + this.castSession.media.length + ' existing media sessions.'); this.onMediaDiscovered('onRequestSessionSuccess_', this.castSession.media[0]); } this.castSession.addMediaListener(this.onMediaDiscovered.bind(this, 'addMediaListener')); this.castSession.addUpdateListener(this.sessionUpdateListener.bind(this)); this.syncControls(); }; /** * receiver listener during initialization */ CastPlayer.prototype.receiverListener = function (e) { if (e === 'available') { this.log("receiver found"); $("#castOn").show(); $("#castOff").hide(); } else { this.log("receiver list empty"); $("#castOn").hide(); $("#castOff").hide(); } }; /** * session update listener */ CastPlayer.prototype.sessionUpdateListener = function (isAlive) { var message = isAlive ? 'Session Updated' : 'Session Removed'; message += ': ' + this.castSession.sessionId; this.log(message); if (!isAlive) { this.castSession = null; this.setCastControlsVisible(false); } }; CastPlayer.prototype.onInitSuccess = function () { this.log("init success"); }; CastPlayer.prototype.onError = function () { this.log("error"); }; CastPlayer.prototype.setCastControlsVisible = function (visible) { $("#player").toggle(!visible); $("#castPlayer").toggle(visible); $("#castOff").toggle(visible); $("#castOn").toggle(!visible); }; /** * launch app and request session */ CastPlayer.prototype.launchCastApp = function () { this.log("launching app..."); chrome.cast.requestSession(this.onRequestSessionSuccess.bind(this), this.onLaunchError.bind(this)); }; /** * Stops the running receiver application associated with the session. */ CastPlayer.prototype.stopCastApp = function () { this.castSession.stop(this.onStopAppSuccess.bind(this, 'Session stopped'), this.onError.bind(this)); }; /** * Callback function for stop app success */ CastPlayer.prototype.onStopAppSuccess = function (message) { console.log(message); this.currentMediaSession = null; this.syncControls(); }; /** * callback on success for requestSession call * @param {Object} s A non-null new session. */ CastPlayer.prototype.onRequestSessionSuccess = function (s) { this.log("session success: " + s.sessionId); this.castSession = s; var position = -1; if (!$('#audioPlayer').get(0).paused) { position = $('#audioPlayer').get(0).currentTime; $('#audioPlayer').get(0).pause(); } this.setCastControlsVisible(true); this.castSession.addUpdateListener(this.sessionUpdateListener.bind(this)); this.syncControls(); // Continue song at same position? if (position != -1) { skip(getCurrentSongIndex(), position); } }; CastPlayer.prototype.onLaunchError = function () { this.log("launch error"); }; CastPlayer.prototype.loadCastMedia = function (song, position) { if (!this.castSession) { this.log("no session"); return; } this.log("loading..." + song.remoteStreamUrl); var mediaInfo = new chrome.cast.media.MediaInfo(song.remoteStreamUrl); mediaInfo.contentType = song.contentType; mediaInfo.streamType = chrome.cast.media.StreamType.BUFFERED; mediaInfo.duration = song.duration; mediaInfo.metadata = new chrome.cast.media.MusicTrackMediaMetadata(); mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.MUSIC_TRACK; mediaInfo.metadata.songName = song.title; mediaInfo.metadata.title = song.title; mediaInfo.metadata.albumName = song.album; mediaInfo.metadata.artist = song.artist; mediaInfo.metadata.trackNumber = song.trackNumber; mediaInfo.metadata.images = [new chrome.cast.Image(song.remoteCoverArtUrl)]; mediaInfo.metadata.releaseYear = song.year; var request = new chrome.cast.media.LoadRequest(mediaInfo); request.autoplay = true; request.currentTime = position; this.castSession.loadMedia(request, this.onMediaDiscovered.bind(this, 'loadMedia'), this.onMediaError.bind(this)); }; /** * callback on success for loading media */ CastPlayer.prototype.onMediaDiscovered = function (how, ms) { this.mediaSession = ms; this.log("new media session ID:" + this.mediaSession.mediaSessionId + ' (' + how + ')'); this.log(ms); this.mediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this)); }; /** * callback on media loading error * @param {Object} e A non-null media object */ CastPlayer.prototype.onMediaError = function (e) { this.log("media error"); }; /** * callback for media status event */ CastPlayer.prototype.onMediaStatusUpdate = function () { this.log(this.mediaSession.playerState); if (this.mediaSession.playerState === chrome.cast.media.PlayerState.IDLE && this.mediaSession.idleReason === "FINISHED") { onNext(repeatEnabled); } this.syncControls(); }; CastPlayer.prototype.playCast = function () { if (!this.mediaSession) { return; } this.mediaSession.play(null, this.mediaCommandSuccessCallback.bind(this, "playing started for " + this.mediaSession.sessionId), this.onError.bind(this)); $("#castPlay").hide(); $("#castPause").show(); }; CastPlayer.prototype.pauseCast = function () { if (!this.mediaSession) { return; } this.mediaSession.pause(null, this.mediaCommandSuccessCallback.bind(this, "paused " + this.mediaSession.sessionId), this.onError.bind(this)); $("#castPlay").show(); $("#castPause").hide(); }; /** * set receiver volume * @param {Number} level A number for volume level * @param {Boolean} mute A true/false for mute/unmute */ CastPlayer.prototype.setCastVolume = function (level, mute) { if (!this.castSession) return; if (!mute) { this.castSession.setReceiverVolumeLevel(level, this.mediaCommandSuccessCallback.bind(this, 'media set-volume done'), this.onError.bind(this)); this.volume = level; } else { this.castSession.setReceiverMuted(true, this.mediaCommandSuccessCallback.bind(this, 'media set-volume done'), this.onError.bind(this)); } $("#castMuteOn").toggle(!mute); $("#castMuteOff").toggle(mute); }; CastPlayer.prototype.castMuteOn = function () { this.setCastVolume(this.volume, true); }; CastPlayer.prototype.castMuteOff = function () { this.setCastVolume(this.volume, false); }; /** * callback on success for media commands * @param {string} info A message string */ CastPlayer.prototype.mediaCommandSuccessCallback = function (info) { this.log(info); }; CastPlayer.prototype.syncControls = function () { if (this.castSession && this.castSession.receiver.volume) { this.volume = this.castSession.receiver.volume.level; var muted = this.castSession.receiver.volume.muted; $("#castMuteOn").toggle(!muted); $("#castMuteOff").toggle(muted); document.getElementById("castVolume").value = this.volume * 100; } var playing = this.mediaSession && this.mediaSession.playerState === chrome.cast.media.PlayerState.PLAYING; $("#castPause").toggle(playing); $("#castPlay").toggle(!playing); }; CastPlayer.prototype.log = function (message) { console.log(message); }; window.CastPlayer = CastPlayer; })();