Skip to content

Commit

Permalink
NPM package release
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
superhawk610 committed Oct 13, 2017
1 parent f0c62e8 commit b8dd8c7
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 56 deletions.
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
MultiCast v0.2
MultiCast v1.0
=========

[![npm version](https://badge.fury.io/js/multicast.svg)](https://badge.fury.io/js/multicast)

:green_heart: A persistent solution to presenting content across multiple Chromecast devices, inspired by [Greenscreen](http://greenscreen.io/).

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

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.)

Clone this repository to your local machine, then head into the cloned directory and create a `.config` file for your setup.
Installation is a snap with NPM.

```shell
npm i multicast -g
multicast config
multicast start
```

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.

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.

```shell
git clone https://github.com/superhawk610/multicast
Expand Down Expand Up @@ -107,15 +119,6 @@ Run the application
node .
```

Alternatively, you may install multicast as a binary and run from there

```shell
npm install -g
multicast
```

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.

### Firewall Settings

In order for a Chromecast to establish and maintain a connection with a Cast sender, the sender must open two ports:
Expand Down
94 changes: 94 additions & 0 deletions app/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use strict';

const path = require('path')
const fs = require('fs')
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})

const configFile = path.resolve(__dirname, '..', '.config')

var ask = prompt => {
return new Promise(resolve => {
rl.question(prompt + ' ', res => resolve(res))
})
}

var demand = (prompt, validate) => {
return new Promise(resolve => {
rl.question(prompt + ' ', res => {
if (res != '') {
if (!validate) resolve(res)
else {
if (validate.test(res)) resolve(res)
else demand(prompt, validate).then(res => resolve(res))
}
} else demand(prompt, validate).then(res => resolve(res))
})
})
}

var saveOpts = (opts, callback) => {
fs.writeFile(configFile, JSON.stringify(opts, null, 2), callback)
}

var startConfig = () => {
var opts = {}

ask('Mongo host? (localhost)').then(res => {
opts.mongoHost = res || 'localhost'
}).then(() => ask('Mongo port? (27017)')).then(res => {
opts.mongoPort = res || 27017
}).then(() => ask('Mongo username? (none)')).then(res => {
opts.mongoUsername = res || ''
}).then(() => ask('Mongo password? (none)')).then(res => {
opts.mongoPassword = res || ''
}).then(() => ask('Mongo auth DB? (admin)')).then(res => {
opts.mongoAuthDB = res || 'admin'
}).then(() => {
console.log('')
console.log('Now we\'ll configure Chromecast integration.')
}).then(() => demand('Application ID?')).then(res => {
opts.appId = res
}).then(() => {
console.log('')
console.log('Does this look right?')
console.log('')
console.log(opts)
console.log('')
}).then(() => demand('(y/N)', /[yn]/i)).then(res => {
if(/y/i.test(res)) {
saveOpts(opts, () => {
console.log('')
console.log('Configuration updated! To get started, just run\n' +
'\n' +
' multicast start')
})
rl.close()
} else {
console.log('')
console.log('Alright, let\'s start over.')
console.log('')
startConfig()
}
})
}

/* Let's get started! */

/* credit to ASCII art goes to patorjk.com/software/taag/ */
console.log('')
console.log(' W E L C O M E T O')
console.log(`
███╗ ███╗██╗ ██╗██╗ ████████╗██╗ ██████╗ █████╗ ███████╗████████╗
████╗ ████║██║ ██║██║ ╚══██╔══╝██║██╔════╝██╔══██╗██╔════╝╚══██╔══╝
██╔████╔██║██║ ██║██║ ██║ ██║██║ ███████║███████╗ ██║
██║╚██╔╝██║██║ ██║██║ ██║ ██║██║ ██╔══██║╚════██║ ██║
██║ ╚═╝ ██║╚██████╔╝███████╗██║ ██║╚██████╗██║ ██║███████║ ██║
╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ `)
console.log('')
console.log('We\'ll start off by configuring database options. Just press [ENTER] after each.')

startConfig()
84 changes: 43 additions & 41 deletions build/js/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
var socket = io()

socket.on('connect', function () { })
socket.on('disconnect', function() {})
socket.on('disconnect', function() { })
socket.on('refresh', function() { location.reload(true) })

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

/* Google Cast */
cast.receiver.logger.setLevelValue(0);
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
console.log('Starting Receiver Manager');
// handler for the 'ready' event
castReceiverManager.onReady = function (event) {
console.log('Received Ready event: ' + JSON.stringify(event.data));
window.castReceiverManager.setApplicationState($(document).find('title').text());
};
// handler for 'senderconnected' event
castReceiverManager.onSenderConnected = function (event) {
console.log('Received Sender Connected event: ' + event.data);
console.log(window.castReceiverManager.getSender(event.data).userAgent);
};
// handler for 'senderdisconnected' event
castReceiverManager.onSenderDisconnected = function (event) {
console.log('Received Sender Disconnected event: ' + event.data);
if (window.castReceiverManager.getSenders().length == 0) {
window.close();
if (cast) {
cast.receiver.logger.setLevelValue(0);
window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
console.log('Starting Receiver Manager');
// handler for the 'ready' event
castReceiverManager.onReady = function (event) {
console.log('Received Ready event: ' + JSON.stringify(event.data));
window.castReceiverManager.setApplicationState($(document).find('title').text());
};
// handler for 'senderconnected' event
castReceiverManager.onSenderConnected = function (event) {
console.log('Received Sender Connected event: ' + event.data);
console.log(window.castReceiverManager.getSender(event.data).userAgent);
};
// handler for 'senderdisconnected' event
castReceiverManager.onSenderDisconnected = function (event) {
console.log('Received Sender Disconnected event: ' + event.data);
if (window.castReceiverManager.getSenders().length == 0) {
window.close();
}
};
// handler for 'systemvolumechanged' event
castReceiverManager.onSystemVolumeChanged = function (event) {
console.log('Received System Volume Changed event: ' + event.data['level'] + ' ' +
event.data['muted']);
};
// create a CastMessageBus to handle messages for a custom namespace
window.messageBus =
window.castReceiverManager.getCastMessageBus(
'urn:x-cast:com.unitedcatalystcorporation.ucc-utility');
// handler for the CastMessageBus message event
window.messageBus.onMessage = function (event) {
console.log('Message [' + event.senderId + ']: ' + event.data);
// display the message from the sender
displayText(event.data);
// inform all senders on the CastMessageBus of the incoming message event
// sender message listener will be invoked
window.messageBus.send(event.senderId, event.data);
}
};
// handler for 'systemvolumechanged' event
castReceiverManager.onSystemVolumeChanged = function (event) {
console.log('Received System Volume Changed event: ' + event.data['level'] + ' ' +
event.data['muted']);
};
// create a CastMessageBus to handle messages for a custom namespace
window.messageBus =
window.castReceiverManager.getCastMessageBus(
'urn:x-cast:com.unitedcatalystcorporation.ucc-utility');
// handler for the CastMessageBus message event
window.messageBus.onMessage = function (event) {
console.log('Message [' + event.senderId + ']: ' + event.data);
// display the message from the sender
displayText(event.data);
// inform all senders on the CastMessageBus of the incoming message event
// sender message listener will be invoked
window.messageBus.send(event.senderId, event.data);
}
// initialize the CastReceiverManager with an application status message
window.castReceiverManager.start({ statusText: 'Loading Hub...' });
console.log('Receiver Manager started');
// initialize the CastReceiverManager with an application status message
window.castReceiverManager.start({ statusText: 'Loading Hub...' });
console.log('Receiver Manager started');
}
16 changes: 15 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
#!/usr/bin/env node
require('./app/main.js')
if (process.argv.length == 2) { // run with no arguments, display help
console.log('Multicast is a persistent solution to presenting content across multiple Chromecast devices.')
console.log('')
console.log('USAGE: multicast <command> (--flags)')
console.log('')
console.log('Commands:')
console.log(' config run this first to set up Multicast')
console.log(' start start Multicast as a foreground process')
console.log('')
console.log('Flags:')
console.log(' --serve-only do not run the mDNS server (won\'t interrupt existing receivers)')
} else {
if (process.argv.find(arg => arg == 'config')) require('./app/config.js') // run configuration
else require('./app/main.js') // start application
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "multicast",
"version": "0.2.0",
"version": "1.0.0",
"description": "Service for persisting a session indefinitely across multiple Chromecast devices.",
"main": "index.js",
"scripts": {
"postinstall": "gulp",
"start": "node .",
"test": "echo \"No tests configured\"",
"config": "cp .config.template .config && echo -e \"Edit .config for your local installation, then run\n npm run start\""
"test": "echo \"No tests configured\""
},
"bin": {
"multicast": "index.js"
Expand Down

0 comments on commit b8dd8c7

Please sign in to comment.