Skip to content

Commit b8dd8c7

Browse files
committed
NPM package release
- bump major version - multicast can now be installed as a global NPM package (addresses #9) - added explanation when run with no arguments - added config interface for initial setup - check if cast is defined before referencing in client.js
1 parent f0c62e8 commit b8dd8c7

File tree

5 files changed

+169
-56
lines changed

5 files changed

+169
-56
lines changed

README.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
MultiCast v0.2
1+
MultiCast v1.0
22
=========
33

4+
[![npm version](https://badge.fury.io/js/multicast.svg)](https://badge.fury.io/js/multicast)
5+
46
:green_heart: A persistent solution to presenting content across multiple Chromecast devices, inspired by [Greenscreen](http://greenscreen.io/).
57

68
Developed with Node, Express, and Mongo.
@@ -78,7 +80,17 @@ Once you've done this, log in to the [Cast Developer SDK Console](https://cast.g
7880

7981
You now need to register your Chromecast devices as developer devices. For each device, locate the Serial Number (located on the back of the device and on the box), click **Add New Device**, and enter the Serial Number and a brief Description. (**NOTE**: This may take up to 15 minutes to take effect. Go grab a cup of coffee and then head back.)
8082

81-
Clone this repository to your local machine, then head into the cloned directory and create a `.config` file for your setup.
83+
Installation is a snap with NPM.
84+
85+
```shell
86+
npm i multicast -g
87+
multicast config
88+
multicast start
89+
```
90+
91+
Head over to `http://YOUR_LOCAL_IP:3944/` in your browser to get started, then simply follow the [Usage](#usage) guide to get off the ground.
92+
93+
For development, you can install locally via Github - clone this repository to your local machine, then head into the cloned directory and create a `.config` file for your setup.
8294

8395
```shell
8496
git clone https://github.com/superhawk610/multicast
@@ -107,15 +119,6 @@ Run the application
107119
node .
108120
```
109121

110-
Alternatively, you may install multicast as a binary and run from there
111-
112-
```shell
113-
npm install -g
114-
multicast
115-
```
116-
117-
Head over to `http://YOUR_LOCAL_IP:3944/` in your browser to get started, then simply follow the [Usage](#usage) guide to get off the ground.
118-
119122
### Firewall Settings
120123

121124
In order for a Chromecast to establish and maintain a connection with a Cast sender, the sender must open two ports:

app/config.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
'use strict';
2+
3+
const path = require('path')
4+
const fs = require('fs')
5+
const readline = require('readline')
6+
const rl = readline.createInterface({
7+
input: process.stdin,
8+
output: process.stdout
9+
})
10+
11+
const configFile = path.resolve(__dirname, '..', '.config')
12+
13+
var ask = prompt => {
14+
return new Promise(resolve => {
15+
rl.question(prompt + ' ', res => resolve(res))
16+
})
17+
}
18+
19+
var demand = (prompt, validate) => {
20+
return new Promise(resolve => {
21+
rl.question(prompt + ' ', res => {
22+
if (res != '') {
23+
if (!validate) resolve(res)
24+
else {
25+
if (validate.test(res)) resolve(res)
26+
else demand(prompt, validate).then(res => resolve(res))
27+
}
28+
} else demand(prompt, validate).then(res => resolve(res))
29+
})
30+
})
31+
}
32+
33+
var saveOpts = (opts, callback) => {
34+
fs.writeFile(configFile, JSON.stringify(opts, null, 2), callback)
35+
}
36+
37+
var startConfig = () => {
38+
var opts = {}
39+
40+
ask('Mongo host? (localhost)').then(res => {
41+
opts.mongoHost = res || 'localhost'
42+
}).then(() => ask('Mongo port? (27017)')).then(res => {
43+
opts.mongoPort = res || 27017
44+
}).then(() => ask('Mongo username? (none)')).then(res => {
45+
opts.mongoUsername = res || ''
46+
}).then(() => ask('Mongo password? (none)')).then(res => {
47+
opts.mongoPassword = res || ''
48+
}).then(() => ask('Mongo auth DB? (admin)')).then(res => {
49+
opts.mongoAuthDB = res || 'admin'
50+
}).then(() => {
51+
console.log('')
52+
console.log('Now we\'ll configure Chromecast integration.')
53+
}).then(() => demand('Application ID?')).then(res => {
54+
opts.appId = res
55+
}).then(() => {
56+
console.log('')
57+
console.log('Does this look right?')
58+
console.log('')
59+
console.log(opts)
60+
console.log('')
61+
}).then(() => demand('(y/N)', /[yn]/i)).then(res => {
62+
if(/y/i.test(res)) {
63+
saveOpts(opts, () => {
64+
console.log('')
65+
console.log('Configuration updated! To get started, just run\n' +
66+
'\n' +
67+
' multicast start')
68+
})
69+
rl.close()
70+
} else {
71+
console.log('')
72+
console.log('Alright, let\'s start over.')
73+
console.log('')
74+
startConfig()
75+
}
76+
})
77+
}
78+
79+
/* Let's get started! */
80+
81+
/* credit to ASCII art goes to patorjk.com/software/taag/ */
82+
console.log('')
83+
console.log(' W E L C O M E T O')
84+
console.log(`
85+
███╗ ███╗██╗ ██╗██╗ ████████╗██╗ ██████╗ █████╗ ███████╗████████╗
86+
████╗ ████║██║ ██║██║ ╚══██╔══╝██║██╔════╝██╔══██╗██╔════╝╚══██╔══╝
87+
██╔████╔██║██║ ██║██║ ██║ ██║██║ ███████║███████╗ ██║
88+
██║╚██╔╝██║██║ ██║██║ ██║ ██║██║ ██╔══██║╚════██║ ██║
89+
██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║╚██████╗██║ ██║███████║ ██║
90+
╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ `)
91+
console.log('')
92+
console.log('We\'ll start off by configuring database options. Just press [ENTER] after each.')
93+
94+
startConfig()

build/js/client.js

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
var socket = io()
33

44
socket.on('connect', function () { })
5-
socket.on('disconnect', function() {})
5+
socket.on('disconnect', function() { })
66
socket.on('refresh', function() { location.reload(true) })
77

88
socket.on('register', function(device_id) {
@@ -24,44 +24,46 @@ socket.on('push', function(opts) {
2424
})
2525

2626
/* Google Cast */
27-
cast.receiver.logger.setLevelValue(0);
28-
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
29-
console.log('Starting Receiver Manager');
30-
// handler for the 'ready' event
31-
castReceiverManager.onReady = function (event) {
32-
console.log('Received Ready event: ' + JSON.stringify(event.data));
33-
window.castReceiverManager.setApplicationState($(document).find('title').text());
34-
};
35-
// handler for 'senderconnected' event
36-
castReceiverManager.onSenderConnected = function (event) {
37-
console.log('Received Sender Connected event: ' + event.data);
38-
console.log(window.castReceiverManager.getSender(event.data).userAgent);
39-
};
40-
// handler for 'senderdisconnected' event
41-
castReceiverManager.onSenderDisconnected = function (event) {
42-
console.log('Received Sender Disconnected event: ' + event.data);
43-
if (window.castReceiverManager.getSenders().length == 0) {
44-
window.close();
27+
if (cast) {
28+
cast.receiver.logger.setLevelValue(0);
29+
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
30+
console.log('Starting Receiver Manager');
31+
// handler for the 'ready' event
32+
castReceiverManager.onReady = function (event) {
33+
console.log('Received Ready event: ' + JSON.stringify(event.data));
34+
window.castReceiverManager.setApplicationState($(document).find('title').text());
35+
};
36+
// handler for 'senderconnected' event
37+
castReceiverManager.onSenderConnected = function (event) {
38+
console.log('Received Sender Connected event: ' + event.data);
39+
console.log(window.castReceiverManager.getSender(event.data).userAgent);
40+
};
41+
// handler for 'senderdisconnected' event
42+
castReceiverManager.onSenderDisconnected = function (event) {
43+
console.log('Received Sender Disconnected event: ' + event.data);
44+
if (window.castReceiverManager.getSenders().length == 0) {
45+
window.close();
46+
}
47+
};
48+
// handler for 'systemvolumechanged' event
49+
castReceiverManager.onSystemVolumeChanged = function (event) {
50+
console.log('Received System Volume Changed event: ' + event.data['level'] + ' ' +
51+
event.data['muted']);
52+
};
53+
// create a CastMessageBus to handle messages for a custom namespace
54+
window.messageBus =
55+
window.castReceiverManager.getCastMessageBus(
56+
'urn:x-cast:com.unitedcatalystcorporation.ucc-utility');
57+
// handler for the CastMessageBus message event
58+
window.messageBus.onMessage = function (event) {
59+
console.log('Message [' + event.senderId + ']: ' + event.data);
60+
// display the message from the sender
61+
displayText(event.data);
62+
// inform all senders on the CastMessageBus of the incoming message event
63+
// sender message listener will be invoked
64+
window.messageBus.send(event.senderId, event.data);
4565
}
46-
};
47-
// handler for 'systemvolumechanged' event
48-
castReceiverManager.onSystemVolumeChanged = function (event) {
49-
console.log('Received System Volume Changed event: ' + event.data['level'] + ' ' +
50-
event.data['muted']);
51-
};
52-
// create a CastMessageBus to handle messages for a custom namespace
53-
window.messageBus =
54-
window.castReceiverManager.getCastMessageBus(
55-
'urn:x-cast:com.unitedcatalystcorporation.ucc-utility');
56-
// handler for the CastMessageBus message event
57-
window.messageBus.onMessage = function (event) {
58-
console.log('Message [' + event.senderId + ']: ' + event.data);
59-
// display the message from the sender
60-
displayText(event.data);
61-
// inform all senders on the CastMessageBus of the incoming message event
62-
// sender message listener will be invoked
63-
window.messageBus.send(event.senderId, event.data);
64-
}
65-
// initialize the CastReceiverManager with an application status message
66-
window.castReceiverManager.start({ statusText: 'Loading Hub...' });
67-
console.log('Receiver Manager started');
66+
// initialize the CastReceiverManager with an application status message
67+
window.castReceiverManager.start({ statusText: 'Loading Hub...' });
68+
console.log('Receiver Manager started');
69+
}

index.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,16 @@
11
#!/usr/bin/env node
2-
require('./app/main.js')
2+
if (process.argv.length == 2) { // run with no arguments, display help
3+
console.log('Multicast is a persistent solution to presenting content across multiple Chromecast devices.')
4+
console.log('')
5+
console.log('USAGE: multicast <command> (--flags)')
6+
console.log('')
7+
console.log('Commands:')
8+
console.log(' config run this first to set up Multicast')
9+
console.log(' start start Multicast as a foreground process')
10+
console.log('')
11+
console.log('Flags:')
12+
console.log(' --serve-only do not run the mDNS server (won\'t interrupt existing receivers)')
13+
} else {
14+
if (process.argv.find(arg => arg == 'config')) require('./app/config.js') // run configuration
15+
else require('./app/main.js') // start application
16+
}

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"name": "multicast",
3-
"version": "0.2.0",
3+
"version": "1.0.0",
44
"description": "Service for persisting a session indefinitely across multiple Chromecast devices.",
55
"main": "index.js",
66
"scripts": {
7+
"postinstall": "gulp",
78
"start": "node .",
8-
"test": "echo \"No tests configured\"",
9-
"config": "cp .config.template .config && echo -e \"Edit .config for your local installation, then run\n npm run start\""
9+
"test": "echo \"No tests configured\""
1010
},
1111
"bin": {
1212
"multicast": "index.js"

0 commit comments

Comments
 (0)