├── .gitignore
├── .jshintrc
├── Gruntfile.js
├── LICENSE
├── README.md
├── bower.json
├── chromecast.js
├── examples
├── receiver.html
└── sender.html
├── package.json
└── src
└── chromecast.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /.settings
2 | /.project
3 | /bower_components
4 | /node_modules
5 | .DS_Store
6 | /docs
7 | /chromecast-bundle.js
8 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": false,
6 | "curly": true,
7 | "eqeqeq": true,
8 | "immed": true,
9 | "indent": 4,
10 | "latedef": true,
11 | "newcap": true,
12 | "noarg": true,
13 | "quotmark": "single",
14 | "regexp": true,
15 | "undef": true,
16 | "unused": true,
17 | "strict": true,
18 | "trailing": true,
19 | "smarttabs": true,
20 | "white": true,
21 | "globals": {
22 | "chrome": true,
23 | "window": true,
24 | "cast": true,
25 | "define": true
26 | }
27 | }
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function (grunt) {
2 | 'use strict';
3 |
4 | var _ = require('lodash');
5 | var Q = require('q');
6 |
7 | require('load-grunt-tasks')(grunt);
8 | grunt.initConfig({
9 | pkg: grunt.file.readJSON('package.json'),
10 |
11 | watch: {
12 | dev: {
13 | files: [
14 | 'src/*.js', 'examples/*.html'
15 | ],
16 | tasks: [
17 | 'test'
18 | ],
19 | options: {
20 | nospawn: true,
21 | livereload: '<%= portscanner.portLiveReload %>'
22 | }
23 | }
24 | },
25 |
26 | jshint: {
27 | options: grunt.file.readJSON('./.jshintrc'),
28 | test: {
29 | files: {
30 | src: [
31 | 'src/*.js'
32 | ]
33 | },
34 | }
35 | },
36 |
37 | open: {
38 | dev: {
39 | path: 'http://localhost:<%= portscanner.port %>/examples/sender.html'
40 | },
41 | docs: {
42 | path: 'http://localhost:<%= portscanner.port %>/docs/readme.html'
43 | }
44 | },
45 |
46 | docco: {
47 | docs: {
48 | src: [
49 | 'README.md', 'src/*.js'
50 | ],
51 | options: {
52 | output: 'docs/'
53 | }
54 | }
55 | },
56 |
57 | connect: {
58 | dev: {
59 | options: {
60 | port: '<%= portscanner.port %>',
61 | base: '',
62 | middleware: function (connect) {
63 | var connectLiveReload = require('connect-livereload');
64 |
65 | return [
66 | connectLiveReload({
67 | port: grunt.config('portscanner.portLiveReload')
68 | }),
69 | connect.static(require('path').resolve('./'))
70 | ];
71 | }
72 | }
73 | }
74 | },
75 |
76 | uglify: {
77 | dist: {
78 | files: {
79 | 'chromecast.js': ['chromecast-bundle.js']
80 | }
81 | }
82 | },
83 |
84 | browserify: {
85 | dist: {
86 | files: {
87 | 'chromecast-bundle.js': ['src/chromecast.js']
88 | }
89 | }
90 | }
91 | });
92 |
93 | grunt.registerTask('portscanner', 'find a free tcp port', function () {
94 | var done = this.async();
95 | var Task = {
96 | initialize: function () {
97 | this.deferred = new Q();
98 |
99 | return this;
100 | },
101 | findPort: function (name) {
102 | var portscanner = require('portscanner');
103 | var deferred = Q.defer();
104 |
105 | this.deferred = this.deferred.then(function (p_port) {
106 | var port = p_port || 5000;
107 |
108 | portscanner.findAPortNotInUse(port, 6000, 'localhost', _.bind(function (error, port) {
109 | grunt.config.set(name, port);
110 |
111 | console.log(name, port);
112 | deferred.resolve(port + 1);
113 | }, this));
114 |
115 | return deferred.promise;
116 | });
117 |
118 | return this;
119 | },
120 | execute: function () {
121 | this.findPort('portscanner.port').findPort('portscanner.portLiveReload');
122 |
123 | return this.deferred;
124 | }
125 | };
126 |
127 | Object.create(Task).initialize().execute().then(function () {
128 | done();
129 | });
130 | });
131 |
132 |
133 | grunt.registerTask('test', [
134 | 'jshint:test', 'compile'
135 | ]);
136 | grunt.registerTask('default', [
137 | 'test'
138 | ]);
139 | grunt.registerTask('serverdev', [
140 | 'docco:docs', 'portscanner', 'connect:dev', 'open:docs', 'open:dev', 'watch'
141 | ]);
142 | grunt.registerTask('compile', [
143 | 'browserify:dist', 'uglify:dist'
144 | ]);
145 | };
146 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Marc Buils
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # chromecastjs
2 |
3 | ## Current version
4 |
5 | v0.1.0
6 |
7 | ## Licence
8 |
9 | MIT
10 |
11 | ## Author
12 |
13 | Marc Buils from Marc Buils Consultant Compagny (France)
14 |
15 | (and sorry for my english. I work it, but currently it is very bad...)
16 |
17 |
18 | ## Description
19 |
20 | JavaScript project based on ChromeCast API to build ChromeCast apps very easy
21 |
22 | AMD and CommonJS compatible
23 |
24 | Here all the requirements you need before to build the output files or to launch the dev mode:
25 |
26 | - [NodeJS](http://nodejs.org/download/)
27 | - [Grunt](http://gruntjs.com/) ```npm install -g grunt-cli```
28 | - [PhantomJS](http://phantomjs.org/download.html) ```npm install -g phantomjs```
29 | - [Bower](http://bower.io/) ```npm install -g bower```
30 |
31 |
32 | ## Getting Started
33 |
34 | A Chromecast app is composed by
35 | - Sender application to start your application from a device (on Google Chrome with ChromeCast plugin)
36 | - Receiver application open on chromecast
37 |
38 | ### Install
39 |
40 | - Bower
41 | > bower install --save-dev chromecastjs
42 |
43 | ### Sender example
44 | ```html
45 |
46 |
47 |
48 | Hello World
49 |
50 |
51 |
52 |
53 |
54 |
57 | |
58 |
59 |
60 |
61 |
62 |
83 |
84 |
85 | ```
86 |
87 |
88 | ### Receiver example
89 | ```html
90 |
91 |
92 |
93 | Cast Hello Text
94 |
95 |
96 | Talk to me
97 |
98 |
111 |
112 |
113 | ```
114 |
115 | ## Usage
116 |
117 | > chromecast.createSender({options})
118 |
119 | Create a chromecastjs sender instance
120 |
121 | > chromecast.createReceiver({options})
122 |
123 | Create a chromecastjs receiver instance
124 |
125 |
126 | ### Sender
127 |
128 | _WARNING: no message can be sent during the first second after initialize_
129 |
130 |
131 | #### API
132 |
133 | > on({event name}, {callback})
134 |
135 | Register an event (see Getting Started / Sender / API / Events)
136 |
137 |
138 | > sendMessage({message})
139 |
140 | Send a message to the receiver app
141 |
142 |
143 | #### Events
144 |
145 | - message
146 | - session
147 | - initSuccess
148 | - error
149 | - success
150 | - stopappsuccess
151 | - sessionupdatelistener
152 | - listener
153 |
154 |
155 | ### Receiver
156 |
157 | #### API
158 |
159 | > on({event name}, {callback})
160 |
161 | Register an event (see Getting Started / Sender / API / Events)
162 |
163 |
164 | > sendMessage({message})
165 |
166 | Send a message to the receiver app
167 |
168 |
169 | > getSenders()
170 |
171 | Get list of senders
172 |
173 |
174 | > disconnect()
175 |
176 | Close the app
177 |
178 |
179 | #### Events
180 |
181 | - message
182 | - ready
183 | - senderconnected
184 | - senderdisconnected
185 | - systemvolumechanged
186 |
187 |
188 | ## Development
189 |
190 | ### Getting sources
191 |
192 | This is how to launch the app quickly in dev mode:
193 |
194 | > * clone the git repository:
195 | > ```bash
196 | > git clone https://github.com/marcbuils/chromecastjs.git
197 | > ```
198 | >
199 | > * Run in chromecastjs folder:
200 | >
201 | > ```bash
202 | > # Dependencies
203 | > npm install; bower install
204 | > # Start watcher for development
205 | > grunt start
206 | > ```
207 |
208 | ### Sending pull request
209 |
210 | This is how to send a pull request:
211 | - Fork the project on your github account
212 | - Clone the project on local (see Development/Getting sources)
213 | - Add feature / bugfixed
214 | - Start test
215 |
216 | > * Run in chromecastjs folder:
217 | >
218 | > ```bash
219 | > grunt test
220 | > ```
221 |
222 | - Commit and create a pull request with description of your modification
223 |
224 | (: THANKS FOR YOUR PARTICIPATION :)
225 |
226 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chromecastjs",
3 | "version": "0.1.0",
4 | "homepage": "https://github.com/marcbuils/chromecastjs",
5 | "authors": [
6 | "marc.buils "
7 | ],
8 | "description": "JavaScript project based on ChromeCast API to build ChromeCast apps very easy",
9 | "main": "chromecast.js",
10 | "moduleType": [
11 | "amd",
12 | "globals"
13 | ],
14 | "keywords": [
15 | "chromecast",
16 | "google",
17 | "chrome",
18 | "cast",
19 | "js",
20 | "javascript",
21 | "api"
22 | ],
23 | "license": "MIT",
24 | "ignore": [
25 | "**/.*",
26 | "node_modules",
27 | "bower_components",
28 | "test",
29 | "tests"
30 | ],
31 | "devDependencies": {
32 | "cast_sender": "http://www.gstatic.com/cv/js/sender/v1/cast_sender.js",
33 | "cast_receiver": "http://www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/chromecast.js:
--------------------------------------------------------------------------------
1 | !function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g")&&(a=a.replace(r,">")),-1!=a.indexOf('"')&&(a=a.replace(s,""")),-1!=a.indexOf("'")&&(a=a.replace(t,"'")),a):a},p=/&/g,q=//g,s=/"/g,t=/'/g,u=/[&<>"']/,v=function(a,b){return b>a?-1:a>b?1:0},w=function(a,b){b.unshift(a),m.call(this,n.apply(null,b)),b.shift()};l(w,m),w.prototype.name="AssertionError";var x,y,z,A,B=function(a,b){if(!a){var c="Assertion failed";if(b)var c=c+(": "+b),d=Array.prototype.slice.call(arguments,2);throw new w(""+c,d||[])}},C=function(a){throw new w("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1))},D=Array.prototype,E=D.indexOf?function(a,b,c){return B(null!=a.length),D.indexOf.call(a,b,c)}:function(a,b,c){if(c=null==c?0:0>c?Math.max(0,a.length+c):c,e(a))return e(b)&&1==b.length?a.indexOf(b,c):-1;for(;c0){for(var c=Array(b),d=0;b>d;d++)c[d]=a[d];return c}return[]},G=function(a){var b,c=[],d=0;for(b in a)c[d++]=b;return c},H=function(a){var b,c={};for(b in a)c[b]=a[b];return c},I="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),J=function(a){for(var b,c,d=1;dparseFloat(U)){N=String(X);break a}}N=U}var Y=N,Z={},$=function(a){var b;if(!(b=Z[a])){b=0;for(var c=String(Y).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),d=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),e=Math.max(c.length,d.length),f=0;0==b&&e>f;f++){var g=c[f]||"",h=d[f]||"",i=/(\d*)(\D*)/g,j=/(\d*)(\D*)/g;do{var k=i.exec(g)||["","",""],l=j.exec(h)||["","",""];if(0==k[0].length&&0==l[0].length)break;b=v(0==k[1].length?0:parseInt(k[1],10),0==l[1].length?0:parseInt(l[1],10))||v(0==k[2].length,0==l[2].length)||v(k[2],l[2])}while(0==b)}b=Z[a]=b>=0}return b},_=b.document,ab=_&&P?S()||("CSS1Compat"==_.compatMode?parseInt(Y,10):5):void 0,bb=function(a){return cb(a||arguments.callee.caller,[])},cb=function(a,b){var c=[];if(0<=E(b,a))c.push("[...circular reference...]");else if(a&&50>b.length){c.push(db(a)+"(");for(var d=a.arguments,e=0;e0&&c.push(", ");var f;switch(f=d[e],typeof f){case"object":f=f?"object":"null";break;case"string":break;case"number":f=String(f);break;case"boolean":f=f?"true":"false";break;case"function":f=(f=db(f))?f:"[fn]";break;default:f=typeof f}40=tb(this).value)for("function"==d(c)&&(c=c()),a=this.Db(a,c,e),c="log:"+a.Ha,b.console&&(b.console.timeStamp?b.console.timeStamp(c):b.console.markTimeline&&b.console.markTimeline(c)),b.msWriteProfilerMark&&b.msWriteProfilerMark(c),c=this;c;){e=c;var f=a;if(e.T)for(var g=0,h=void 0;h=e.T[g];g++)h(f);c=c.getParent()}},hb.prototype.Db=function(a,d,f){var g=new fb(a,String(d),this.Ua);if(f){g.ra=f;var h,i=arguments.callee.caller;try{var j,k=c("window.location.href");if(e(f))j={message:f,name:"Unknown error",lineNumber:"Not available",fileName:k,stack:"Not available"};else{var l,m,n=!1;try{l=f.lineNumber||f.Ob||"Not available"}catch(p){l="Not available",n=!0}try{m=f.fileName||f.filename||f.sourceURL||b.$googDebugFname||k}catch(q){m="Not available",n=!0}j=!n&&f.lineNumber&&f.fileName&&f.stack&&f.message&&f.name?f:{message:f.message||"Not available",name:f.name||"UnknownError",lineNumber:l,fileName:m,stack:f.stack||"Not available"}}h="Message: "+o(j.message)+'\nUrl: '+j.fileName+"\nLine: "+j.lineNumber+"\n\nBrowser stack:\n"+o(j.stack+"-> ")+"[end]\n\nJS stack traversal:\n"+o(bb(i)+"-> ")}catch(r){h="Exception trying to expose exception! You win, we lose. "+r}g.qa=h}return g};var ub=function(a,b,c){a.log(kb,b,c)};hb.prototype.info=function(a,b){this.log(mb,a,b)};var vb=function(a,b){a.log(ob,b,void 0)},wb=function(a,b){a.log(pb,b,void 0)},xb={},yb=null,zb=function(){yb||(yb=new hb(""),xb[""]=yb,yb.ya(nb))},Ab=function(a){zb();var b;if(!(b=xb[a])){b=new hb(a);var c=a.lastIndexOf("."),d=a.substr(c+1),c=Ab(a.substr(0,c));c.xa||(c.xa={}),c.xa[d]=b,b.da=c,xb[a]=b}return b},Bb=function(){};Bb.prototype.Ta=!1,Bb.prototype.G=function(){this.Ta||(this.Ta=!0,this.d())};var Cb=function(a,b){a.V||(a.V=[]),a.V.push(h(b,void 0))};Bb.prototype.d=function(){if(this.V)for(;this.V.length;)this.V.shift()()};var Db=function(a){a&&"function"==typeof a.G&&a.G()},Eb=function(a,b){this.type=a,this.currentTarget=this.target=b,this.defaultPrevented=this.B=!1,this.Qa=!0};Eb.prototype.d=function(){},Eb.prototype.G=function(){},Eb.prototype.stopPropagation=function(){this.B=!0},Eb.prototype.preventDefault=function(){this.defaultPrevented=!0,this.Qa=!1},k("cast.receiver.VERSION","2.0.0");var Fb=Ab("cast");k("cast.receiver.logger",Fb),k("cast.receiver.LoggerLevel",{DEBUG:0,VERBOSE:400,INFO:800,ERROR:1e3,NONE:1500}),Fb.Wa=function(a){Fb.ya(sb(a))},Fb.setLevelValue=Fb.Wa,Fb.Wa(1e3);var Gb=function(){this.Va=j()},Hb=new Gb;Gb.prototype.set=function(a){this.Va=a},Gb.prototype.reset=function(){this.set(j())},Gb.prototype.get=function(){return this.Va};var Ib=function(a){this.rb=a||"",this.sb=Hb};a=Ib.prototype,a.tb=!0,a.La=!0,a.vb=!0,a.ub=!0,a.Ma=!1,a.wb=!1;var Jb=function(a){return 10>a?"0"+a:String(a)},Kb=function(a,b){var c=(a.Pa-b)/1e3,d=c.toFixed(3),e=0;if(1>c)e=2;else for(;100>c;)e++,c*=10;for(;0=9);var Rb=Qb,Sb=P&&!$("9");!R||$("528"),Q&&$("1.9b")||P&&$("8")||O&&$("9.5")||R&&$("528"),Q&&!$("8")||P&&$("9");var Tb=function(a,b){if(Eb.call(this,a?a.type:""),this.relatedTarget=this.currentTarget=this.target=null,this.charCode=this.keyCode=this.button=this.screenY=this.screenX=this.clientY=this.clientX=this.offsetY=this.offsetX=0,this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1,this.U=this.state=null,a){var c=this.type=a.type;this.target=a.target||a.srcElement,this.currentTarget=b;var d=a.relatedTarget;if(d){if(Q){var e;a:{try{Pb(d.nodeName),e=!0;break a}catch(f){}e=!1}e||(d=null)}}else"mouseover"==c?d=a.fromElement:"mouseout"==c&&(d=a.toElement);this.relatedTarget=d,this.offsetX=R||void 0!==a.offsetX?a.offsetX:a.layerX,this.offsetY=R||void 0!==a.offsetY?a.offsetY:a.layerY,this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX=a.screenX||0,this.screenY=a.screenY||0,this.button=a.button,this.keyCode=a.keyCode||0,this.charCode=a.charCode||("keypress"==c?a.keyCode:0),this.ctrlKey=a.ctrlKey,this.altKey=a.altKey,this.shiftKey=a.shiftKey,this.metaKey=a.metaKey,this.state=a.state,this.U=a,a.defaultPrevented&&this.preventDefault()}};l(Tb,Eb),Tb.prototype.stopPropagation=function(){Tb.n.stopPropagation.call(this),this.U.stopPropagation?this.U.stopPropagation():this.U.cancelBubble=!0},Tb.prototype.preventDefault=function(){Tb.n.preventDefault.call(this);var a=this.U;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,Sb)try{(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)&&(a.keyCode=-1)}catch(b){}},Tb.prototype.d=function(){};var Ub="closure_listenable_"+(1e6*Math.random()|0),Vb=function(a){try{return!(!a||!a[Ub])}catch(b){return!1}},Wb=0,Xb=function(a,b,c,d,e){this.w=a,this.ca=null,this.src=b,this.type=c,this.$=!!d,this.ba=e,this.key=++Wb,this.J=this.aa=!1},Yb=function(a){a.J=!0,a.w=null,a.ca=null,a.src=null,a.ba=null},Zb=function(a){this.src=a,this.g={},this.S=0};Zb.prototype.add=function(a,b,c,d,e){var f=this.g[a];f||(f=this.g[a]=[],this.S++);var g=_b(f,b,d,e);return g>-1?(a=f[g],c||(a.aa=!1)):(a=new Xb(b,this.src,a,!!d,e),a.aa=c,f.push(a)),a},Zb.prototype.remove=function(a,b,c,d){if(!(a in this.g))return!1;var e=this.g[a];return b=_b(e,b,c,d),b>-1?(Yb(e[b]),B(null!=e.length),D.splice.call(e,b,1),0==e.length&&(delete this.g[a],this.S--),!0):!1};var $b=function(a,b){var c=b.type;if(c in a.g){var d,e=a.g[c],f=E(e,b);(d=f>=0)&&(B(null!=e.length),D.splice.call(e,f,1)),d&&(Yb(b),0==a.g[c].length&&(delete a.g[c],a.S--))}};Zb.prototype.wa=function(a,b,c,d){a=this.g[a];var e=-1;return a&&(e=_b(a,b,c,d)),e>-1?a[e]:null};var _b=function(a,b,c,d){for(var e=0;ed.keyCode||void 0!=d.returnValue)){a:{var g=!1;if(0==d.keyCode)try{d.keyCode=-1;break a}catch(h){g=!0}(g||void 0==d.returnValue)&&(d.returnValue=!0)}for(d=[],g=e.currentTarget;g;g=g.parentNode)d.push(g);for(var g=a.type,i=d.length-1;!e.B&&i>=0;i--)e.currentTarget=d[i],f&=hc(d[i],g,!0,e);for(i=0;!e.B&&i>>0),mc=function(a){return B(a,"Listener can not be null."),"function"==d(a)?a:(B(a.handleEvent,"An object listener must have handleEvent method."),a[lc]||(a[lc]=function(b){return a.handleEvent(b)}))},nc=function(){this.r=new Zb(this),this.Cb=this};l(nc,Bb),nc.prototype[Ub]=!0,a=nc.prototype,a.sa=null,a.addEventListener=function(a,b,c,d){dc(this,a,b,c,d)},a.removeEventListener=function(a,b,c,d){fc(this,a,b,c,d)},a.dispatchEvent=function(a){pc(this);var b,c=this.sa;if(c){b=[];for(var d=1;c;c=c.sa)b.push(c),B(1e3>++d,"infinite loop")}if(c=this.Cb,d=a.type||a,e(a))a=new Eb(a,c);else if(a instanceof Eb)a.target=a.target||c;else{var f=a;a=new Eb(d,c),J(a,f)}var g,f=!0;if(b)for(var h=b.length-1;!a.B&&h>=0;h--)g=a.currentTarget=b[h],f=oc(g,d,!0,a)&&f;if(a.B||(g=a.currentTarget=c,f=oc(g,d,!0,a)&&f,a.B||(f=oc(g,d,!1,a)&&f)),b)for(h=0;!a.B&&h2147483647?-1:b.setTimeout(a,c||0)},sc=function(a,b){nc.call(this),this.lb=void 0!==a?a:!0,this.ia=b||vc,this.Z=this.ia(this.Q)};l(sc,nc),a=sc.prototype,a.i=null,a.q=null,a.F=void 0,a.ja=!1,a.Q=0;var tc=sc.prototype,uc=Ab("goog.net.WebSocket");tc.a=uc;var vc=function(a){return Math.min(1e3*Math.pow(2,a),6e4)};a=sc.prototype,a.open=function(a,c){B(b.WebSocket,"This browser does not support WebSocket"),B(!this.P(),"The WebSocket is already open"),null!=this.D&&b.clearTimeout(this.D),this.D=null,this.q=a,(this.F=c)?(qc(this.a,"Opening the WebSocket on "+this.q+" with protocol "+this.F),this.i=new WebSocket(this.q,this.F)):(qc(this.a,"Opening the WebSocket on "+this.q),this.i=new WebSocket(this.q)),this.i.onopen=h(this.nb,this),this.i.onclose=h(this.mb,this),this.i.onmessage=h(this.K,this),this.i.onerror=h(this.ga,this)},a.close=function(){null!=this.D&&b.clearTimeout(this.D),this.D=null,this.i&&(qc(this.a,"Closing the WebSocket."),this.ja=!0,this.i.close(),this.i=null)},a.send=function(a){B(this.P(),"Cannot send without an open socket"),this.i.send(a)},a.P=function(){return!!this.i&&1==this.i.readyState},a.nb=function(){qc(this.a,"WebSocket opened on "+this.q),this.dispatchEvent("d"),this.Q=0,this.Z=this.ia(this.Q)},a.mb=function(a){if(qc(this.a,"The WebSocket on "+this.q+" closed."),this.dispatchEvent("a"),this.i=null,this.ja)qc(this.a,"The WebSocket closed normally."),this.q=null,this.F=void 0;else{var b=this.a;b&&ub(b,"The WebSocket disconnected unexpectedly: "+a.data,void 0),this.lb&&(qc(this.a,"Seconds until next reconnect attempt: "+Math.floor(this.Z/1e3)),this.D=rc(h(this.open,this,this.q,this.F),this.Z,this),this.Q++,this.Z=this.ia(this.Q))}this.ja=!1},a.K=function(a){this.dispatchEvent(new wc(a.data))},a.ga=function(a){a=a.data;var b=this.a;b&&ub(b,"An error occurred: "+a,void 0),this.dispatchEvent(new xc(a))},a.d=function(){sc.n.d.call(this),this.close()};var wc=function(a){Eb.call(this,"c"),this.message=a};l(wc,Eb);var xc=function(a){Eb.call(this,"b"),this.data=a};l(xc,Eb);var yc=function(a,b){nc.call(this),this.u=b,this.la=!0,this.I=a,this.onClose=this.onMessage=null,dc(this.I,this.u,this.ua,!1,this)};l(yc,nc),k("cast.receiver.CastChannel",yc),yc.EventType={MESSAGE:"message",CLOSE:"close"};var zc=function(a,b){Eb.call(this,a),this.message=b};l(zc,Eb),yc.Event=zc,yc.prototype.a=Ab("cast.receiver.CastChannel"),yc.prototype.s=function(){return"CastChannel["+this.u+" "+this.I.v()+"]"},yc.prototype.v=function(){return this.I.v()},yc.prototype.getNamespace=yc.prototype.v,yc.prototype.Ib=function(){return this.u},yc.prototype.getSenderId=yc.prototype.Ib,yc.prototype.ua=function(a){wb(this.a,"Dispatching CastChannel message ["+this.I.v()+", "+this.u+"]: "+a.data),a=new zc("message",a.data),this.onMessage&&this.onMessage(a),this.dispatchEvent(a)},yc.prototype.close=function(){if(this.la){this.la=!1,this.a.info("Closing CastChannel ["+this.I.v()+", "+this.u+"]");var a=new zc("close",this.u);this.onClose&&this.onClose(a),this.dispatchEvent(a),this.G()}},yc.prototype.send=function(a){if(!this.la)throw Error("Invalid state, socket not open");this.I.send(this.u,a)},yc.prototype.send=yc.prototype.send,yc.prototype.d=function(){yc.n.d.call(this),wb(this.a,"Disposed "+this.s())},k("cast.receiver.system.NAMESPACE_PREFIX","urn:x-cast:"),k("cast.receiver.system.ApplicationData",function(){this.name=this.id="",this.sessionId=0,this.namespaces=[],this.launchingSenderId=""}),k("cast.receiver.system.Sender",function(){this.userAgent=this.id=""});var Ac=function(){nc.call(this),this.j=null;var a=new sc(!0);this.j&&this.j.G(),this.j=a,Cb(this,i(Db,this.j)),dc(this.j,"d",this.Ab,!1,this),dc(this.j,"a",this.zb,!1,this),dc(this.j,"b",this.ga,!1,this),dc(this.j,"c",this.K,!1,this)};l(Ac,nc);var Bc=function(a,b,c){Eb.call(this,a),this.senderId=b,this.data=c};l(Bc,Eb),Ac.prototype.a=Ab("cast.receiver.IpcChannel");var Cc=function(a,b){vb(a.a,"IpcChannel "+b),a.dispatchEvent(new Bc("urn:x-cast:com.google.cast.system","SystemSender",JSON.stringify({type:b})))};a=Ac.prototype,a.Ab=function(){Cc(this,"opened")},a.zb=function(){Cc(this,"closed")},a.ga=function(){Cc(this,"error")},a.K=function(a){vb(this.a,"Received message: "+a.message);var b=(a=JSON.parse(a.message))&&a.namespace;a&&b&&a.senderId&&a.data?this.dispatchEvent(new Bc(b,a.senderId,a.data)):ub(this.a,"IpcChannel Message received is invalid")},a.open=function(){this.a.info("Opening message bus websocket"),this.j.open("ws://localhost:8008/v2/ipc")},a.close=function(){this.a.info("Closing message bus websocket"),this.j.close()},a.P=function(){return this.j.P()},a.send=function(a,b,c){if(!this.P)throw Error("Underlying websocket is not open");a=JSON.stringify({namespace:a,senderId:b,data:c}),vb(this.a,"IPC message sent: "+a),this.j.send(a)},a.d=function(){Ac.n.d.call(this),wb(this.a,"Disposed IpcChannel")};var Dc=function(a,b,c,d){for(nc.call(this),this.p=a,this.t=b,this.R=d||"STRING",this.onMessage=null,this.serializeMessage=this.yb,this.deserializeMessage=this.xb,this.e={},a=0;aa.maxInactivity)throw Error("config.maxInactivity must be greater than or equal to 5 seconds.");J(this.N,a||{})}this.Ia=!0,this.t.open()},Fc.prototype.start=Fc.prototype.start,Fc.prototype.stop=function(){this.G(),window.close()},Fc.prototype.stop=Fc.prototype.stop,Fc.prototype.Kb=function(){return this.Y},Fc.prototype.isSystemReady=Fc.prototype.Kb,Fc.prototype.Jb=function(){return G(this.o)},Fc.prototype.getSenders=Fc.prototype.Jb,Fc.prototype.Hb=function(a){return this.o[a]?H(this.o[a]):null},Fc.prototype.getSender=Fc.prototype.Hb,Fc.prototype.Eb=function(){return this.ha},Fc.prototype.getApplicationData=Fc.prototype.Eb,Fc.prototype.Lb=function(a){if(this.Y){var b={type:"setappstate"};void 0!=a&&(b.statusText=a),this.O.send("SystemSender",b)}else this.N.statusText=a},Fc.prototype.setApplicationState=Fc.prototype.Lb,Fc.prototype.Ca=function(a,b){if("urn:x-cast:com.google.cast.system"==a)throw Error("Protected namespace");if(0!=a.lastIndexOf("urn:x-cast:",0))throw Error("Invalid namespace prefix");if(!this.k[a]){if(this.Ia)throw Error("New namespaces can not be requested after start has been called");this.k[a]=new Dc(a,this.t,G(this.o),b),Cb(this,i(Db,this.k[a]))}if(b&&this.k[a].Sa()!=b)throw Error("Invalid messageType for the namespace");return this.k[a]},Fc.prototype.getCastMessageBus=Fc.prototype.Ca,Fc.prototype.qb=function(a){var b=a.data;switch(wb(this.a,"CastReceiverManager message received: "+a.data),b.type){case"opened":this.a.info("Underlying message bus is open");var c=G(this.k),d=this.N.statusText;a={type:"ready"},d&&(a.statusText=d),a.activeNamespaces=c,a.version="2.0.0",a.messagesVersion="1.0",this.O.send("SystemSender",a),this.N.maxInactivity&&this.O.send("SystemSender",{type:"startheartbeat",maxInactivity:this.N.maxInactivity});break;case"closed":this.Y=!1,this.dispatchEvent("shutdown");break;case"error":this.dispatchEvent("error");break;case"ready":this.ha={id:b.applicationId,name:b.applicationName,sessionId:b.sessionId,namespaces:G(this.k),launchingSenderId:b.launchingSenderId},this.Y=!0,this.a.info("Dispatching CastReceiverManager system ready event ["+this.ha+"]"),c=new Gc("ready",this.ha),this.onReady&&this.onReady(c),this.dispatchEvent(c);break;case"senderconnected":d={id:b.senderId,userAgent:b.userAgent},this.a.info("Dispatching CastReceiverManager sender connected event ["+d.id+"]"),d.id in this.o&&ub(this.a,"Unexpected connected message for already connected sender: "+d.id),this.o[d.id]=d,a=new Gc("senderconnected",d.id);for(c in this.k){var b=this.k[c],e=d.id;e in b.e?ub(b.a,"Unexpected sender already registered ["+b.p+", "+e+"]"):(b.a.info("Registering sender ["+b.p+", "+e+"]"),b.e[e]=null)}this.onSenderConnected&&this.onSenderConnected(a),this.dispatchEvent(a);break;case"senderdisconnected":if(c=b.senderId,this.a.info("Dispatching sender disconnected event ["+c+"]"),c in this.o){delete this.o[c],a=new Gc("senderdisconnected",c);for(d in this.k)b=this.k[d],e=c,e in b.e&&(b.a.info("Unregistering sender ["+b.p+", "+e+"]"),b.e[e]&&b.e[e].close(),delete b.e[e]);this.onSenderDisconnected&&this.onSenderDisconnected(a),this.dispatchEvent(a)}else ub(this.a,"Unknown sender disconnected: "+c);break;case"volumechanged":c={level:b.level,muted:b.muted},this.a.info("Dispatching system volume changed event ["+c.level+", "+c.muted+"]"),c=new Gc("systemvolumechanged",c),this.onSystemVolumeChanged&&this.onSystemVolumeChanged(c),this.dispatchEvent(c);break;case"visibilitychanged":c=b.visible,this.a.info("Dispatching visibility changed event "+c),c=new Gc("visibilitychanged",c),this.onVisibilityChanged&&this.onVisibilityChanged(c),this.dispatchEvent(c);break;default:throw Error("Unexpected message type: "+b.type)}},Fc.prototype.d=function(){Fc.n.d.call(this),delete Fc.ma,vb(this.a,"Disposed "+this.s())},k("cast.receiver.media.MEDIA_NAMESPACE","urn:x-cast:com.google.cast.media"),k("cast.receiver.media.StreamType",{BUFFERED:"BUFFERED",LIVE:"LIVE",NONE:"NONE"});var Ic={INVALID_PLAYER_STATE:"INVALID_PLAYER_STATE",LOAD_FAILED:"LOAD_FAILED",LOAD_CANCELLED:"LOAD_CANCELLED",INVALID_REQUEST:"INVALID_REQUEST"};k("cast.receiver.media.ErrorType",Ic),k("cast.receiver.media.ErrorReason",{INVALID_COMMAND:"INVALID_COMMAND",INVALID_PARAMS:"INVALID_PARAMS",INVALID_MEDIA_SESSION_ID:"INVALID_MEDIA_SESSION_ID",DUPLICATE_REQUEST_ID:"DUPLICATE_REQUEST_ID"}),k("cast.receiver.media.IdleReason",{CANCELLED:"CANCELLED",INTERRUPTED:"INTERRUPTED",FINISHED:"FINISHED",ERROR:"ERROR"}),k("cast.receiver.media.SeekResumeState",{Rb:"PLAYBACK_START",Qb:"PLAYBACK_PAUSE"}),k("cast.receiver.media.PlayerState",{IDLE:"IDLE",PLAYING:"PLAYING",PAUSED:"PAUSED",BUFFERING:"BUFFERING"});var Jc=function(){this.contentId="",this.streamType="NONE",this.contentType="",this.customData=this.duration=this.metadata=void 0};k("cast.receiver.media.MediaInformation",Jc);var Kc=function(){this.muted=this.level=void 0};k("cast.receiver.media.Volume",Kc),k("cast.receiver.media.MediaStatus",function(){this.mediaSessionId=0,this.media=void 0,this.playbackRate=1,this.playerState="IDLE",this.idleReason=void 0,this.supportedMediaCommands=this.currentTime=0,this.volume={level:0,muted:!1},this.customData=void 0}),k("cast.receiver.media.Command",{PAUSE:1,SEEK:2,STREAM_VOLUME:4,STREAM_MUTE:8});var Lc=function(a,b){nc.call(this),this.X=Fc.Da().Ca("urn:x-cast:com.google.cast.media","JSON"),this.fa=0,this.Xa=1,this.Ya=b||15,this.Aa=this.za=this.C=this.W=this.h=this.b=this.c=null,this.l=!1,this.ea=0,this.L=this.f=null,this.customizedStatusCallback=this.Za,this.onLoad=this.eb,this.onPlay=this.hb,this.onSeek=this.ib,this.onPause=this.gb,this.onStop=this.kb,this.onSetVolume=this.jb,this.onMetadataLoaded=this.fb,this.onLoadMetadataError=this.cb,this.onEnded=this.$a,this.onError=this.ab,this.onGetStatus=this.bb,this.Ea(a),this.X.onMessage=this.K.bind(this),rc(h(this.Ba,this),1e3)};l(Lc,nc),k("cast.receiver.MediaManager",Lc),Lc.EventType={LOAD:"load",STOP:"stop",PAUSE:"pause",PLAY:"play",SEEK:"seek",SET_VOLUME:"setvolume",GET_STATUS:"getstatus"};var Mc=function(a,b,c){Eb.call(this,a),this.data=b,this.senderId=c};l(Mc,Eb),Lc.Event=Mc;var Nc=function(){this.requestId=0,this.mediaSessionId=void 0,this.customData=null};Lc.RequestData=Nc;var Oc=function(){this.media=new Jc,this.autoplay=!1,this.currentTime=0};l(Oc,Nc),Lc.LoadRequestData=Oc;var Pc=function(){this.volume=new Kc
2 | };l(Pc,Nc),Lc.VolumeRequestData=Pc,l(Pc,Nc),Lc.SeekRequestData=function(){this.resumeState=void 0,this.currentTime=0},l(Mc,Eb),Lc.LoadInfo=function(a,b){this.message=a,this.senderId=b},Lc.prototype.a=Ab("cast.receiver.MediaManager"),Lc.prototype.s=function(){return"MediaManager"},Lc.prototype.Gb=function(){return this.h},Lc.prototype.getMediaInformation=Lc.prototype.Gb,Lc.prototype.Nb=function(a,b,c){if(b=void 0==b||b,c&&!b)throw Error("No broadcast call but status customData has been provided");this.h=a,b&&this.m(!0,null,c)},Lc.prototype.setMediaInformation=Lc.prototype.Nb,Lc.prototype.K=function(a){var b=a.data;a=a.senderId;var c=b.type,d=b.requestId;if("number"==typeof d&&d==Math.floor(d))if(void 0!=b.mediaSessionId&&b.mediaSessionId!=this.fa||"LOAD"!=c&&"GET_STATUS"!=c&&("IDLE"==Qc(this)||void 0==b.mediaSessionId))ub(this.a,"Invalid media session ID: "+b.mediaSessionId),this.M(a,d,"INVALID_REQUEST","INVALID_MEDIA_SESSION_ID");else{wb(this.a,"MediaManager message received ["+a+"] "+JSON.stringify(b)),delete b.type;var e=null;switch(c){case"LOAD":this.a.info("Dispatching MediaManager load event"),b.media?(this.f?this.ka("LOAD_CANCELLED"):this.h&&this.H("INTERRUPTED"),this.f={senderId:a,message:b},this.ea=b.currentTime||0,this.h=b.media,this.fa++,b=new Mc("load",b,a),this.onLoad&&this.onLoad(b),this.dispatchEvent(b),e=null):(ub(this.a,"media is mandatory"),e={type:"INVALID_REQUEST",reason:"INVALID_PARAMS"});break;case"GET_STATUS":this.a.info("Dispatching MediaManager getStatus event"),b=new Mc("getstatus",b,a),this.onGetStatus&&this.onGetStatus(b),this.dispatchEvent(b),e=null;break;case"PLAY":this.a.info("Dispatching MediaManager play event"),b=new Mc("play",b,a),this.onPlay&&this.onPlay(b),this.dispatchEvent(b),e=null;break;case"SEEK":void 0==b.currentTime?(ub(this.a,"currentTime is mandatory"),e={type:"INVALID_REQUEST",reason:"INVALID_PARAMS"}):(this.a.info("Dispatching MediaManager seek event"),b=new Mc("seek",b,a),this.onSeek&&this.onSeek(b),this.dispatchEvent(b),e=null);break;case"STOP":this.a.info("Dispatching MediaManager stop event"),b=new Mc("stop",b,a),this.onStop&&this.onStop(b),this.dispatchEvent(b),e=null;break;case"PAUSE":this.a.info("Dispatching MediaManager pause event"),b=new Mc("pause",b,a),this.onPause&&this.onPause(b),this.dispatchEvent(b),e=null;break;case"SET_VOLUME":!b.volume||void 0==b.volume.level&&void 0==b.volume.muted?(ub(this.a,"volume is invalid"),e={type:"INVALID_REQUEST",reason:"INVALID_PARAMS"}):void 0!=b.volume.level&&0>b.volume.level||11e3*(this.C-a),b!=this.l?(wb(this.a,"Buffering state changed, isPlayerBuffering: "+this.l+" old time: "+a+" current time: "+this.C),this.m(!1)):!this.l&&(a=1e3*(this.C-this.za)-(Date.now()-this.Aa),a>1e3||-1e3>a)&&(wb(this.a,"Time drifted: "+a),this.m(!1))}},Lc.prototype.m=function(a,b,c){this.b||this.c?(wb(this.a,"Sending broadcast status message"),a=Rc(this,a,c),null!=a&&(a.requestId=b||0,this.X.Fa(a),Sc(this))):ub(this.a,"Not sending broadcast status message, state is invalid")},Lc.prototype.broadcastStatus=Lc.prototype.m,Lc.prototype.Mb=function(a){wb(this.a,"Setting IDLE reason: "+a),this.L=a},Lc.prototype.setIdleReason=Lc.prototype.Mb,Lc.prototype.M=function(a,b,c,d,e){this.a.info("Sending error message to "+a);var f={};f.requestId=b,f.type=c,d&&(f.reason=d),e&&(f.customData=e),this.X.send(a,f)},Lc.prototype.sendError=Lc.prototype.M,Lc.prototype.Ka=function(a,b,c,d){this.b||this.c?(wb(this.a,"Sending status message to "+a),c=Rc(this,c,d),null!=c&&(c.requestId=b,this.X.send(a,c),Sc(this))):(ub(this.a,"State is invalid"),this.M(a,b,"INVALID_PLAYER_STATE",null,d))},Lc.prototype.sendStatus=Lc.prototype.Ka,Lc.prototype.Za=function(a){return a},Lc.prototype.eb=function(a){var b=a.data;this.c?b.media&&b.media.contentId&&this.c.load(b.media.contentId,!!b.autoplay,b.currentTime):(this.b.autoplay=!1,b.media&&a.data.media.contentId&&(this.b.src=b.media.contentId),this.b.autoplay=void 0!=b.autoplay?b.autoplay:!0,this.b.load())},Lc.prototype.Ea=function(a){a.getState?(this.b&&(Uc(this),this.b=null),this.c!=a&&(Uc(this),this.c=a,Tc(this))):(this.c&&(Uc(this),this.c=null),this.b!=a&&(Uc(this),this.b=a,Tc(this)))},Lc.prototype.setMediaElement=Lc.prototype.Ea;var Tc=function(a){a.c?(a.c.registerErrorCallback(a.oa.bind(a)),a.c.registerEndedCallback(a.na.bind(a)),a.c.registerLoadCallback(a.pa.bind(a))):(dc(a.b,"loadedmetadata",a.pa,!1,a),dc(a.b,"error",a.oa,!1,a),dc(a.b,"ended",a.na,!1,a))},Uc=function(a){a.c?(a.c.unregisterErrorCallback(),a.c.unregisterEndedCallback(),a.c.unregisterLoadCallback()):(fc(a.b,"loadedmetadata",a.pa,!1,a),fc(a.b,"error",a.oa,!1,a),fc(a.b,"ended",a.na,!1,a))};Lc.prototype.pa=function(){this.f&&(this.a.info("Metadata loaded"),this.h&&(this.h.duration=this.c?this.c.getDurationSec():this.b.duration),this.l=!0,this.onMetadataLoaded?this.onMetadataLoaded(this.f):this.f=null)},Lc.prototype.fb=function(a){a.message.currentTime&&this.b&&(this.b.currentTime=a.message.currentTime),this.Ra()},Lc.prototype.oa=function(a){this.f?(ub(this.a,"Load metadata error"),this.onLoadMetadataError?this.onLoadMetadataError(this.f):this.f=null):this.onError&&this.onError(a)},Lc.prototype.ka=function(a,b){this.f?(this.M(this.f.senderId,this.f.message.requestId,a||"LOAD_FAILED",null,b),this.f=null):ub(this.a,"Not sending LOAD error as there is no on going LOAD request")},Lc.prototype.sendLoadError=Lc.prototype.ka,Lc.prototype.Ra=function(a){this.f?(this.m(!0,this.f.message.requestId,a),this.f=null):ub(this.a,"Not sending status as there is no on going LOAD request")},Lc.prototype.sendLoadComplete=Lc.prototype.Ra,a=Lc.prototype,a.ab=function(){this.H("ERROR")},a.cb=function(){this.H("ERROR",!1),this.ka("LOAD_FAILED")},a.na=function(){this.onEnded&&this.onEnded()},a.$a=function(){this.H("FINISHED")},a.bb=function(a){wb(this.a,"onGetStatus"),this.Ka(a.senderId,a.data.requestId,!0)},a.hb=function(a){wb(this.a,"onPlay"),this.c?this.c.play():this.b.play(),this.m(!1,a.data.requestId)},a.ib=function(a){a=a.data,wb(this.a,"onSeek: "+JSON.stringify(a)),this.c?(this.c.seek(a.currentTime,a.resumeState),"PAUSED"!=this.c.getState()&&(this.l=!0)):(this.b.currentTime=a.currentTime,"PLAYBACK_START"==a.resumeState&&this.b.paused?this.b.play():"PLAYBACK_PAUSE"!=a.resumeState||this.b.paused||this.b.pause(),this.b.paused||(this.l=!0)),this.m(!1,a.requestId)},a.kb=function(a){this.H("CANCELLED",!0,a.data.requestId)},a.H=function(a,b,c,d){if(b=void 0==b||b,(d||c)&&!b)throw Error("customData and requestId should only be provided in broadcast mode");this.h?(this.c?this.c.reset():(this.a.info("Resetting media element"),this.b.removeAttribute("src"),this.ea=0,this.b.load()),a&&(this.L=a),this.W=this.h,this.h=null,b&&this.m(!1,c,d)):this.a.info("Nothing to reset, Media is already null")},Lc.prototype.resetMediaElement=Lc.prototype.H,Lc.prototype.gb=function(a){this.c?this.c.pause():this.b.pause(),this.m(!1,a.data.requestId)},Lc.prototype.jb=function(a){a=a.data,this.c?this.c.setVolume(a.volume):(void 0!=a.volume.level&&(this.b.volume=a.volume.level),void 0!=a.volume.muted&&(this.b.muted=a.volume.muted)),this.m(!1,a.requestId)},Lc.prototype.d=function(){Lc.n.d.call(this),wb(this.a,"Disposed "+this.s())}}).call(window)},{}],2:[function(){!function(){var a=window.chrome||{};a.cast=a.cast||{},a.cast.media=a.cast.media||{},a.cast.ApiBootstrap_=function(){},a.cast.ApiBootstrap_.EXTENSION_IDS=["boadgeojelhgndaghljhdicfkmllpafd","dliochdbjfkdbacpmhlcpmleaejidimm","hfaagokkkhdbgiakmmlclaapfelnkoah","fmfcbgogabcbclcofgocippekhfcmgfj","enhhojjnijigcajfphajepfemndkmdlo"],a.cast.ApiBootstrap_.findInstalledExtension_=function(b){a.cast.ApiBootstrap_.findInstalledExtensionHelper_(0,b)},a.cast.ApiBootstrap_.findInstalledExtensionHelper_=function(b,c){b==a.cast.ApiBootstrap_.EXTENSION_IDS.length?c(null):a.cast.ApiBootstrap_.isExtensionInstalled_(a.cast.ApiBootstrap_.EXTENSION_IDS[b],function(d){d?c(a.cast.ApiBootstrap_.EXTENSION_IDS[b]):a.cast.ApiBootstrap_.findInstalledExtensionHelper_(b+1,c)})},a.cast.ApiBootstrap_.getCastSenderUrl_=function(a){return"chrome-extension://"+a+"/cast_sender.js"},a.cast.ApiBootstrap_.isExtensionInstalled_=function(b,c){var d=new XMLHttpRequest;d.onreadystatechange=function(){4==d.readyState&&200==d.status&&c(!0)},d.onerror=function(){c(!1)},d.open("GET",a.cast.ApiBootstrap_.getCastSenderUrl_(b),!0),d.send()},a.cast.ApiBootstrap_.findInstalledExtension_(function(b){if(b){console.log("Found cast extension: "+b),a.cast.extensionId=b;var c=document.createElement("script");c.src=a.cast.ApiBootstrap_.getCastSenderUrl_(b),(document.head||document.documentElement).appendChild(c)}else{var d="No cast extension found";console.log(d);var e=window.__onGCastApiAvailable;e&&"function"==typeof e&&e(!1,d)}})}()},{}],3:[function(a){!function(a,b){"use strict";"function"==typeof define&&define.amd?define([],b):a.chromecast=b()}(window,function(){"use strict";var b,c,d={},e={};return b={bind:function(a,b){return function(){a.apply(b,arguments)}},extend:function(a){var b,c,d={};for(b=1;b0&&b.extend(this._options,a),this._options},_trigger:function(a,b){var c,d,e;if(this._events&&this._events[a])for(d=this._events[a],c=0;c
2 |
3 |
4 | Cast Hello Text
5 |
23 |
24 |
25 | Talk to me
26 |
27 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/examples/sender.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello World
5 |
32 |
33 |
34 |
35 |
36 |
37 |
40 | |
41 |
42 |
43 |
44 |
45 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chromecastjs",
3 | "version": "0.1.0",
4 | "description": "JavaScript project based on ChromeCast API to build ChromeCast apps very easy",
5 | "main": "chromecast.js",
6 | "directories": {
7 | "examples": "examples"
8 | },
9 | "dependencies": {},
10 | "devDependencies": {
11 | "connect-livereload": "~0.3.2",
12 | "grunt": "~0.4.4",
13 | "grunt-contrib-connect": "~0.7.1",
14 | "grunt-docco-multi": "~0.0.2",
15 | "grunt-open": "~0.2.3",
16 | "load-grunt-tasks": "~0.4.0",
17 | "lodash": "~2.4.1",
18 | "portscanner": "~0.2.2",
19 | "q": "~1.0.1",
20 | "grunt-contrib-watch": "~0.6.1",
21 | "grunt-contrib-jshint": "~0.9.2",
22 | "browserify": "~3.38.0",
23 | "grunt-browserify": "~2.0.1",
24 | "grunt-contrib-uglify": "~0.4.0"
25 | },
26 | "scripts": {
27 | "test": "grunt test"
28 | },
29 | "repository": {
30 | "type": "git",
31 | "url": "git://github.com/marcbuils/chromecastjs.git"
32 | },
33 | "keywords": [
34 | "chromecast",
35 | "google",
36 | "chrome",
37 | "cast",
38 | "js",
39 | "javascript",
40 | "api"
41 | ],
42 | "author": "Marc Buils",
43 | "license": "MIT",
44 | "bugs": {
45 | "url": "https://github.com/marcbuils/chromecastjs/issues"
46 | },
47 | "homepage": "https://github.com/marcbuils/chromecastjs"
48 | }
49 |
--------------------------------------------------------------------------------
/src/chromecast.js:
--------------------------------------------------------------------------------
1 | (function (root, factory) {
2 | 'use strict';
3 |
4 | if (typeof define === 'function' && define.amd) {
5 | define([], factory);
6 | } else {
7 | root.chromecast = factory();
8 | }
9 | }(window, function () {
10 | 'use strict';
11 |
12 | var utils, Common, Sender = {}, Receiver = {};
13 |
14 | utils = {
15 | bind: function (callback, context) {
16 | return function () {
17 | callback.apply(context, arguments);
18 | };
19 | },
20 |
21 | extend: function (target) {
22 | var attr = {};
23 | var i, origin;
24 |
25 | for (i = 1; i < arguments.length; i++) {
26 | origin = arguments[i];
27 | for (attr in origin) {
28 | if (origin.hasOwnProperty(attr)) {
29 | target[attr] = origin[attr];
30 | }
31 | }
32 | }
33 | },
34 |
35 | create: function (Module) {
36 | var Obj = function () {};
37 | Obj.prototype = Module;
38 |
39 | return new Obj();
40 | }
41 | };
42 |
43 | Common = {
44 | _events: null,
45 | _options: null,
46 |
47 | on: function (event, callback) {
48 | if (!this._events) {
49 | this._events = {};
50 | }
51 | if (!this._events[event]) {
52 | this._events[event] = [];
53 | }
54 | this._events[event].push(callback);
55 |
56 | return this;
57 | },
58 |
59 | options: function (opt) {
60 | if (!this._options) {
61 | this._options = {};
62 | }
63 | if (arguments.length > 0) {
64 | utils.extend(this._options, opt);
65 | }
66 | return this._options;
67 | },
68 |
69 | _trigger: function (eventName, data) {
70 | var i, events, event;
71 |
72 | if (!this._events || !this._events[eventName]) {
73 | return;
74 | }
75 |
76 | events = this._events[eventName];
77 | for (i = 0; i < events.length; i++) {
78 | event = events[i];
79 | event.call(this, data);
80 | }
81 | }
82 | };
83 |
84 | utils.extend(Sender, Common, {
85 | _session: null,
86 |
87 | initialize: function (options) {
88 | this.options(options);
89 | setTimeout(utils.bind(this._initializeCast, this), 1000);
90 | return this;
91 | },
92 |
93 | sendMessage: function (message) {
94 | var options = this.options();
95 |
96 | if (!this._isAvailable()) {
97 | return this;
98 | }
99 | this._session.sendMessage(options.namespace, message, utils.bind(this._success, this), utils.bind(this._error, this));
100 |
101 | return this;
102 | },
103 |
104 | start: function () {
105 | var options = this.options();
106 |
107 | chrome.cast.requestSession(utils.bind(function (e) {
108 | this._session = e;
109 | this._session.addUpdateListener(utils.bind(this._sessionUpdateListener, this));
110 | this._session.addMessageListener(options.namespace, utils.bind(this._receiverMessage, this));
111 | }, this), utils.bind(this._error, this));
112 |
113 | return this;
114 | },
115 |
116 | _initializeCast: function () {
117 | var options = this.options();
118 | var sessionRequest;
119 | var apiConfig;
120 |
121 | if (!this._isAvailable()) {
122 | return this;
123 | }
124 |
125 | sessionRequest = new chrome.cast.SessionRequest(options.applicationID);
126 | apiConfig = new chrome.cast.ApiConfig(
127 | sessionRequest,
128 | utils.bind(this._sessionListener, this),
129 | utils.bind(this._receiverListener, this));
130 | chrome.cast.initialize(apiConfig, utils.bind(this._initSuccess, this), utils.bind(this._error, this));
131 |
132 | return this;
133 | },
134 |
135 | _isAvailable: function () {
136 | return chrome && chrome.cast && chrome.cast.isAvailable;
137 | },
138 |
139 | _sessionListener: function (event) {
140 | var options = this.options();
141 |
142 | this._trigger('session', event);
143 | this._session = event;
144 | this._session.addUpdateListener(utils.bind(this._sessionUpdateListener, this));
145 | this._session.addMessageListener(options.namespace, utils.bind(this._receiverMessage, this));
146 | },
147 |
148 |
149 | _initSuccess: function () {
150 | this._trigger('initialized');
151 | },
152 |
153 | _error: function (message) {
154 | this._trigger('error', message);
155 | },
156 |
157 | _success: function (message) {
158 | this._trigger('success', message);
159 | },
160 |
161 | _stopAppSuccess: function () {
162 | this._trigger('stopappsuccess');
163 | },
164 |
165 | _sessionUpdateListener: function (isAlive) {
166 | this._trigger('sessionupdatelistener', isAlive);
167 |
168 | if (!isAlive) {
169 | this._session = null;
170 | }
171 | },
172 |
173 | _receiverMessage: function (namespace, message) {
174 | this._trigger('message', { namespace: namespace, message: message });
175 | },
176 |
177 | _receiverListener: function (e) {
178 | this._trigger('listener', e);
179 | },
180 |
181 | _stopApp: function () {
182 | this._session.stop(
183 | utils.bind(this._stopAppSuccess, this),
184 | utils.bind(this._error, this));
185 | }
186 | });
187 |
188 | utils.extend(Receiver, Common, {
189 | _castReceiverManager: null,
190 | _messageBus: null,
191 |
192 | initialize: function (options) {
193 | this.options(options);
194 | this._initializeCast();
195 | return this;
196 | },
197 |
198 | getSenders: function () {
199 | this._castReceiverManager.getSenders();
200 | return this;
201 | },
202 |
203 | disconnect: function () {
204 | window.close();
205 | return this;
206 | },
207 |
208 | setApplicationState: function (state) {
209 | this._castReceiverManager.setApplicationState(state);
210 | return this;
211 | },
212 |
213 | _initializeCast: function () {
214 | var options = this.options();
215 | var castReceiverManager, messageBus;
216 |
217 | cast.receiver.logger.setLevelValue(0);
218 | castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
219 | castReceiverManager.onReady = utils.bind(this._ready, this);
220 | castReceiverManager.onSenderConnected = utils.bind(this._senderConnected, this);
221 | castReceiverManager.onSenderDisconnected = utils.bind(this._senderDisconnected, this);
222 | castReceiverManager.onSystemVolumeChanged = utils.bind(this._systemVolumeChanged, this);
223 |
224 | messageBus = castReceiverManager.getCastMessageBus(options.namespace);
225 | messageBus.onMessage = utils.bind(this._message, this);
226 |
227 | this._messageBus = messageBus;
228 | this._castReceiverManager = castReceiverManager;
229 |
230 | castReceiverManager.start({ statusText: 'starting' });
231 | },
232 |
233 | _ready: function (event) {
234 | this._trigger('ready', event);
235 | this._castReceiverManager.setApplicationState('ready');
236 | },
237 |
238 | _senderConnected: function (event) {
239 | this._trigger('senderconnected', event);
240 | },
241 |
242 | _senderDisconnected: function (event) {
243 | this._trigger('senderdisconnected', event);
244 | },
245 |
246 | _systemVolumeChanged: function (event) {
247 | this._trigger('systemvolumechanged', event);
248 | },
249 |
250 | _message: function (event) {
251 | this._trigger('message', event);
252 | this._messageBus.send(event.senderId, event.data);
253 | }
254 | });
255 |
256 | return {
257 | createSender: function (options) {
258 | require('../bower_components/cast_sender/index');
259 | return utils.create(Sender).initialize(options);
260 | },
261 | createReceiver: function (options) {
262 | require('../bower_components/cast_receiver/index');
263 | return utils.create(Receiver).initialize(options);
264 | }
265 | };
266 | }));
267 |
--------------------------------------------------------------------------------