cast_video_element.js revision 5f1c94371a64b3196d4be9466099bb892df9b88e
15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)'use strict'; 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/** 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Inverval for updating media info (in ms). 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {number} 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @const 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)var MEDIA_UPDATE_INTERVAL = 250; 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/** 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * The namespace for communication between the cast and the player. 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {string} 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @const 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)var CAST_MESSAGE_NAMESPACE = 'urn:x-cast:com.google.chromeos.videoplayer'; 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/** 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * This class is the dummy class which has same interface as VideoElement. This 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * behaves like VideoElement, and is used for making Chromecast player 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * controlled instead of the true Video Element tag. 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {MediaManager} media Media manager with the media to play. 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {chrome.cast.Session} session Session to play a video on. 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @constructor 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)function CastVideoElement(media, session) { 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.mediaManager_ = media; 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.mediaInfo_ = null; 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castMedia_ = null; 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_ = session; 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.currentTime_ = null; 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.src_ = ''; 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.volume_ = 100; 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.currentMediaPlayerState_ = null; 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.currentMediaCurrentTime_ = null; 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.currentMediaDuration_ = null; 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.playInProgress_ = false; 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.pauseInProgress_ = false; 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onMessageBound_ = this.onMessage_.bind(this); 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastMediaUpdatedBound_ = this.onCastMediaUpdated_.bind(this); 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_.addMessageListener( 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CAST_MESSAGE_NAMESPACE, this.onMessageBound_); 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)CastVideoElement.prototype = { 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __proto__: cr.EventTarget.prototype, 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Prepares for unloading this objects. 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dispose: function() { 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.unloadMedia_(); 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_.removeMessageListener( 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CAST_MESSAGE_NAMESPACE, this.onMessageBound_); 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Returns a parent node. This must always be null. 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {Element} 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get parentNode() { 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return null; 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * The total time of the video (in sec). 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {?number} 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get duration() { 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return this.currentMediaDuration_; 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * The current timestamp of the video (in sec). 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {?number} 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get currentTime() { 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (this.castMedia_) { 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (this.castMedia_.idleReason === chrome.cast.media.IdleReason.FINISHED) 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return this.currentMediaDuration_; // Returns the duration. 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return this.castMedia_.getEstimatedTime(); 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return null; 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) set currentTime(currentTime) { 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(yoshiki): Support seek. 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * If this video is pauses or not. 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {boolean} 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get paused() { 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!this.castMedia_) 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return !this.playInProgress_ && 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (this.pauseInProgress_ || 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castMedia_.playerState === chrome.cast.media.PlayerState.PAUSED); 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * If this video is ended or not. 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {boolean} 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get ended() { 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!this.castMedia_) 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return this.castMedia_.idleReason === chrome.cast.media.IdleReason.FINISHED; 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * If this video is seelable or not. 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {boolean} 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get seekable() { 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(yoshiki): Support seek. 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Value of the volume 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {number} 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get volume() { 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return this.castSession_.receiver.volume.muted ? 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 0 : 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_.receiver.volume.level; 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) set volume(volume) { 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var VOLUME_EPS = 0.01; // Threshold for ignoring a small change. 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Ignores < 1% change. 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (Math.abs(this.castSession_.receiver.volume.level - volume) < VOLUME_EPS) 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (this.castSession_.receiver.volume.muted) { 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (volume < VOLUME_EPS) 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Unmute before setting volume. 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_.setReceiverMuted(false, 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function() {}, 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastCommandError_.wrap(this)); 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_.setReceiverVolumeLevel(volume, 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function() {}, 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastCommandError_.wrap(this)); 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (volume < VOLUME_EPS) { 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_.setReceiverMuted(true, 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function() {}, 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastCommandError_.wrap(this)); 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_.setReceiverVolumeLevel(volume, 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function() {}, 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastCommandError_.wrap(this)); 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Returns the source of the current video. 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {?string} 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get src() { 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return null; 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) set src(value) { 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Do nothing. 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Plays the video. 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) play: function() { 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var play = function() { 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castMedia_.play(null, 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function() { 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.playInProgress_ = false; 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.wrap(this), 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function(error) { 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.playInProgress_ = false; 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastCommandError_(error); 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.wrap(this)); 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.wrap(this); 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.playInProgress_ = true; 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!this.castMedia_) 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.load(play); 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) play(); 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Pauses the video. 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pause: function() { 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!this.castMedia_) 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.pauseInProgress_ = true; 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castMedia_.pause(null, 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function() { 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.pauseInProgress_ = false; 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.wrap(this), 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function(error) { 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.pauseInProgress_ = false; 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastCommandError_(error); 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.wrap(this)); 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Loads the video. 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) load: function(opt_callback) { 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var sendTokenPromise = this.mediaManager_.getToken().then(function(token) { 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.token_ = token; 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.sendMessage_({message: 'push-token', token: token}); 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.bind(this)); 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Promise.all([ 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sendTokenPromise, 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.mediaManager_.getUrl(), 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.mediaManager_.getMime(), 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.mediaManager_.getThumbnail()]). 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) then(function(results) { 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var url = results[1]; 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var mime = results[2]; 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var thumbnailUrl = results[3]; 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.mediaInfo_ = new chrome.cast.media.MediaInfo(url); 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.mediaInfo_.contentType = mime; 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.mediaInfo_.customData = { 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tokenRequired: true, 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) thumbnailUrl: thumbnailUrl, 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var request = new chrome.cast.media.LoadRequest(this.mediaInfo_); 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new Promise( 2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_.loadMedia.bind(this.castSession_, request)). 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) then(function(media) { 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onMediaDiscovered_(media); 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (opt_callback) 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) opt_callback(); 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.bind(this)); 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.bind(this)).catch(function(error) { 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.unloadMedia_(); 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.dispatchEvent(new Event('error')); 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) console.error('Cast failed.', error.stack || error); 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.bind(this)); 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Unloads the video. 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unloadMedia_: function() { 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (this.castMedia_) { 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castMedia_.stop(null, 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function() {}, 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function(error) { 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Ignores session error, since session may already be closed. 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (error.code !== chrome.cast.ErrorCode.SESSION_ERROR) 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastCommandError_(error); 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.wrap(this)); 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castMedia_.removeUpdateListener(this.onCastMediaUpdatedBound_); 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castMedia_ = null; 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) clearInterval(this.updateTimerId_); 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Sends the message to cast. 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {Object} message Message to be sent (Must be JSON-able object). 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sendMessage_: function(message) { 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castSession_.sendMessage(CAST_MESSAGE_NAMESPACE, message); 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Invoked when receiving a message from the cast. 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {string} namespace Namespace of the message. 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {string} messageAsJson Content of message as json format. 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) onMessage_: function(namespace, messageAsJson) { 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (namespace !== CAST_MESSAGE_NAMESPACE || !messageAsJson) 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var message = JSON.parse(messageAsJson); 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (message['message'] === 'request-token') { 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (message['previousToken'] === this.token_) { 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.mediaManager_.getToken().then(function(token) { 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.sendMessage_({message: 'push-token', token: token}); 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(yoshiki): Revokes the previous token. 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.bind(this)).catch(function(error) { 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Send an empty token as an error. 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.sendMessage_({message: 'push-token', token: ''}); 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(yoshiki): Revokes the previous token. 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) console.error(error.stack || error); 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }); 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) console.error( 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'New token is requested, but the previous token mismatches.'); 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * This method is called periodically to update media information while the 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * media is loaded. 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) onPeriodicalUpdateTimer_: function() { 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!this.castMedia_) 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (this.castMedia_.playerState === chrome.cast.media.PlayerState.PLAYING) 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastMediaUpdated_(true); 3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * This method should be called when a media file is loaded. 3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {chrome.cast.Media} media Media object which was discovered. 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) onMediaDiscovered_: function(media) { 3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (this.castMedia_ !== null) { 3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.unloadMedia_(); 3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) console.info('New media is found and the old media is overridden.'); 3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.castMedia_ = media; 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onCastMediaUpdated_(true); 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Notify that the metadata of the video is ready. 3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.dispatchEvent(new Event('loadedmetadata')); 3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) media.addUpdateListener(this.onCastMediaUpdatedBound_); 3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.updateTimerId_ = setInterval(this.onPeriodicalUpdateTimer_.bind(this), 3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MEDIA_UPDATE_INTERVAL); 3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * This method should be called when a media command to cast is failed. 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {Object} error Object representing the error. 3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) onCastCommandError_: function(error) { 3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.unloadMedia_(); 3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.dispatchEvent(new Event('error')); 3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) console.error('Error on sending command to cast.', error.stack || error); 3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * This is called when any media data is updated and by the periodical timer 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * is fired. 3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {boolean} alive Media availability. False if it's unavailable. 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) onCastMediaUpdated_: function(alive) { 3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!this.castMedia_) 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var media = this.castMedia_; 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (this.currentMediaPlayerState_ !== media.playerState) { 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var oldPlayState = false; 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var oldState = this.currentMediaPlayerState_; 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (oldState === chrome.cast.media.PlayerState.BUFFERING || 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) oldState === chrome.cast.media.PlayerState.PLAYING) { 3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) oldPlayState = true; 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var newPlayState = false; 3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var newState = media.playerState; 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (newState === chrome.cast.media.PlayerState.BUFFERING || 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) newState === chrome.cast.media.PlayerState.PLAYING) { 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) newPlayState = true; 3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!oldPlayState && newPlayState) 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.dispatchEvent(new Event('play')); 3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (oldPlayState && !newPlayState) 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.dispatchEvent(new Event('pause')); 3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.currentMediaPlayerState_ = newState; 3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (this.currentMediaCurrentTime_ !== media.getEstimatedTime()) { 4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.currentMediaCurrentTime_ = media.getEstimatedTime(); 4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.dispatchEvent(new Event('timeupdate')); 4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (this.currentMediaDuration_ !== media.media.duration) { 4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.currentMediaDuration_ = media.media.duration; 4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.dispatchEvent(new Event('durationchange')); 4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Media is being unloaded. 4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!alive) { 4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.unloadMedia_(); 4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }, 4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 417