medicastor v1.0.0
medicastor
This library is an experiment to provide a sender API for Google Chromecast devices using mDNS and some TLS protobuf protocol instead of the DIAL discovery protocol. Early Chromecasts made use of DIAL but Google switched away from it. While SSDP/DIAL support is still present and some applications are still using it (like YouTube), existing applications have to migrate to the new SDK using the new protocol.
This library doesn't support DIAL/SSDP (and hence the applications relying on it). See nodecast instead.
Install
npm install medicastor --saveYou may need this on Ubuntu:
sudo apt-get install libavahi-compat-libdnssd-devUsage
This is still a work in progress. The API is not stable, the quality is pretty low and there are a lot of bugs.
Library
To use the library, you first need to discover what Chromecast devices are available on the network. This is an optional step as you can also declare a Chromecast manually from its IP address.
const util = require('util');
const medicastor = require('medicastor');
medicastor.scan()
.on('online', device => {
console.log('New device', util.inspect(device));
})
.on('offline', device => {
console.log('Removed device', util.inspect(device));
})
.start();On Linux, if no device is discovered, first check that your machine is
able to do mDNS address resolution. The library used for this purpose
delegates this to the libc. You should have something like that in
/etc/nsswitch.conf:
hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4Both online and offline events will invoke the callback with a
CastDevice instance. You can also create the CastDevice instance
manually:
new medicastor.CastDevice({
friendlyName: 'My secret Chromecast',
address: '192.168.1.27',
port: 8009
});Once you have a CastDevice instance, you need to wait for the
connection event. Then, you can request some informations about it:
d.on('connect', () => {
d.status((err, s) => {
if (!err) {
console.log('Chromecast status', util.inspect(s));
}
});
});You can get updated when the status of the Chromecast changes by
listening to the status event:
d.on('status', status => {
console.log('Chromecast status updated', util.inspect(status));
});You can also request an application. This will give you a
CastApplication instance.
d.application('YouTube', (err, a) => {
if (!err) {
console.log('YouTube application', util.inspect(a));
}
});Once you have a CastApplication instance, you can request a
CastSession instance for this application. For that, you can either
join an existing application (which should already be running) or you
can run a new instance.
a.run('urn:x-cast:com.google.cast.demo.tictactoe', (err, s) => {
if (!err) {
console.log('Got a session', util.inspect(s));
}
});
a.join('urn:x-cast:com.google.cast.demo.tictactoe', (err, s) => {
if (!err) {
console.log('Joined a session', util.inspect(s));
}
});The first parameter is the namespace you expect to run or join. Any messages sent on this session will use the given namespace.
You can then send messages and receive answers (not all messages have to be answered):
s.send({ data: 'hello' }, (err, data) => {
if (!err) {
console.log('Got an answer!', util.inspect(data));
}
});
s.on('message', data => {
console.log('Got an unexpected message', util.inspect(data));
});Don't use callbacks for messages that you don't expect answers for. They will just leak memory...
A CastSession object can emit a close event when the connection is
closed. A CastDevice object can emit a disconnect event when the
connection with the device is lost and a connect event when the
connection has been established (but there is no need to wait for such
an event). You can close connection to a device with .stop().
Any object can take as an option a logger. For example:
const c = new CastDevice({
address: '192.168.1.27',
logger: console
});By default, reconnection is tried on disconnect. Both Scanner and
CastDevice constructors accept a reconnect object as an
options. When set to false, no reconnection will be retried:
const c = new CastDevice({
address: '192.168.1.27',
reconnect: false
});Otherwise, the provided object may contain some properties to influence the reconnection:
const c = new CastDevice({
address: '192.168.1.27',
reconnect: {
maxRetries: 10,
maxDelay: 10000, // ms
initialDelay: 100 // ms
}
});Command-line helper
The functionality of this library can be tested with the chromecast
helper. Invoke it with chromecast -h to get help. It embeds some
simple examples too.
The Tic Tac Toe application is quite incomplete. It is expected to play against a human player. Here is how to use it:
- Download the Chrome version from GitHub
- Direct a browser to it (
python -mSimpleHTTPServerif you want a quick way to get a webserver to serve the files) - Start casting the application from Chrome.
- Starts
chromecast tictactoe 192.168.1.24. - On Chrome, click play.
The Dashkiosk application is a test for the Dashkiosk project.
Protocol description
There is no formal description of the protocol. However, you can look
at channel.js which shows how to build low-level messages. The
lower-level protocol is implemented directly in Chrome and the
protocol is described in cast_channel.proto.
The high-level protocol, used by the Chromecast extension, can be
discovered by modifying the extension. The following code can be
appended to background_script.js:
chromesendAndLog = (channel, data) => {
console.log('[TAP CHROMECAST send]', data);
return chrome.cast.channel.send.apply(chrome.cast.channel, arguments);
};
chrome.cast.channel.onMessage.addListener((channel, data) => {
console.log('[TAP CHROMECAST recv]', data);
});Any occurrence of chrome.cast.channel.send needs to be replaced by
chromesendAndLog. Monkey-patching seems to be ineffective because
the whole chrome.cast.channel seems to be erased everytime you
connect/disconnect to a Chromecast. Then, filter the log messages with
TAP CHROMECAST in Chrome developper tools (click on
background.html for the Chromecast extension in
chrome://extensions).
Alternatives
- castv2-client is another Javascript implementation which also provides a media player implementation.
- ChromeCast Java API v2 is a Java implementation.
4 years ago