{"analyzedAt":"2022-07-07T11:38:32.188Z","collected":{"metadata":{"name":"nodecastor","scope":"unscoped","version":"0.1.9","description":"Node interface to ChromeCast","keywords":["google","chromecast"],"date":"2019-09-19T18:36:24.319Z","author":{"name":"Vincent Bernat"},"publisher":{"username":"bernat","email":"vincent@bernat.im"},"maintainers":[{"username":"bernat","email":"vincent@bernat.im"}],"repository":{"type":"git","url":"git://github.com/vincentbernat/nodecastor.git"},"links":{"npm":"https://www.npmjs.com/package/nodecastor","homepage":"https://github.com/vincentbernat/nodecastor#readme","repository":"https://github.com/vincentbernat/nodecastor","bugs":"https://github.com/vincentbernat/nodecastor/issues"},"license":"ISC","dependencies":{"argparse":"^1.0.10","backoff":"^2.3.0","lodash":"^4.17.11","mdns":"^2.2.2","protobufjs":"^6.8.8","winston":"^3.2.1"},"releases":[{"from":"2022-06-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1},{"from":"2022-04-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1},{"from":"2022-01-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1},{"from":"2021-07-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1},{"from":"2020-07-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1}],"readme":"Nodecastor\n==========\n\n[![NPM version](https://badge.fury.io/js/nodecastor.svg)](http://badge.fury.io/js/nodecastor)\n[![Dependency Status](https://img.shields.io/david/vincentbernat/nodecastor.svg)](https://david-dm.org/vincentbernat/nodecastor)\n[![npm](https://img.shields.io/npm/dm/nodecastor.svg?maxAge=2592000)]()\n\nThis library is an experiment to provide a sender API for Google\nChromecast devices using mDNS and some TLS protobuf protocol instead\nof the DIAL discovery protocol. Early Chromecasts made use of DIAL but\nGoogle [switched away from it][1]. While SSDP/DIAL support is still\npresent and some applications are still using it (like YouTube),\nexisting applications have to migrate to the new SDK using the new\nprotocol.\n\nThis library doesn't support DIAL/SSDP (and hence the applications\nrelying on it). See [nodecast][] instead.\n\n[1]: https://plus.google.com/+SebastianMauer/posts/83hTniKEDwN\n[nodecast]: https://github.com/wearefractal/nodecast\n\n# Install\n\n```bash\nnpm install nodecastor --save\n```\n\nYou may need this on Ubuntu:\n```bash\nsudo apt-get install libavahi-compat-libdnssd-dev\n```\n\n# Usage\n\nThis is still a work in progress. The API is not stable, the quality\nis pretty low and there are a lot of bugs.\n\n## Library\n\nTo use the library, you first need to discover what Chromecast devices\nare available on the network. This is an optional step as you can also\ndeclare a Chromecast manually from its IP address.\n\n```js\nconst util = require('util');\nconst nodecastor = require('nodecastor');\n\nnodecastor.scan()\n  .on('online', device => {\n    console.log('New device', util.inspect(device));\n  })\n  .on('offline', device => {\n    console.log('Removed device', util.inspect(device));\n  })\n  .start();\n```\n\nOn Linux, if no device is discovered, first check that your machine is\nable to do mDNS address resolution. The library used for this purpose\ndelegates this to the libc. You should have something like that in\n`/etc/nsswitch.conf`:\n\n    hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4\n\nBoth `online` and `offline` events will invoke the callback with a\n`CastDevice` instance. You can also create the `CastDevice` instance\nmanually:\n\n```js\nnew nodecastor.CastDevice({\n  friendlyName: 'My secret Chromecast',\n  address: '192.168.1.27',\n  port: 8009\n});\n```\n\nOnce you have a `CastDevice` instance, you need to wait for the\nconnection event. Then, you can request some informations about it:\n\n```js\nd.on('connect', () => {\n  d.status((err, s) => {\n    if (!err) {\n      console.log('Chromecast status', util.inspect(s));\n    }\n  });\n});\n```\n\nYou can get updated when the status of the Chromecast changes by\nlistening to the `status` event:\n\n```js\nd.on('status', status => {\n  console.log('Chromecast status updated', util.inspect(status));\n});\n```\n\nYou can also request an application. This will give you a\n`CastApplication` instance.\n\n```js\nd.application('YouTube', (err, a) => {\n  if (!err) {\n    console.log('YouTube application', util.inspect(a));\n  }\n});\n```\n\nOnce you have a `CastApplication` instance, you can request a\n`CastSession` instance for this application. For that, you can either\njoin an existing application (which should already be running) or you\ncan run a new instance.\n\n```js\na.run('urn:x-cast:com.google.cast.demo.tictactoe', (err, s) => {\n  if (!err) {\n    console.log('Got a session', util.inspect(s));\n  }\n});\na.join('urn:x-cast:com.google.cast.demo.tictactoe', (err, s) => {\n  if (!err) {\n    console.log('Joined a session', util.inspect(s));\n  }\n});\n```\n\nThe first parameter is the namespace you expect to run or join. Any\nmessages sent on this session will use the given namespace.\n\nYou can then send messages and receive answers (not all messages have\nto be answered):\n\n```js\ns.send({ data: 'hello' }, (err, data) => {\n  if (!err) {\n    console.log('Got an answer!', util.inspect(data));\n  }\n});\ns.on('message', data => {\n  console.log('Got an unexpected message', util.inspect(data));\n});\n```\n\nDon't use callbacks for messages that you don't expect answers\nfor. They will just leak memory...\n\nA `CastSession` object can emit a `close` event when the connection is\nclosed. A `CastDevice` object can emit a `disconnect` event when the\nconnection with the device is lost and a `connect` event when the\nconnection has been established (but there is no need to wait for such\nan event). You can close connection to a device with `.stop()`.\n\nAny object can take as an option a logger. For example:\n\n```js\nconst c = new CastDevice({\n  address: '192.168.1.27',\n  logger: console\n});\n```\n\nBy default, reconnection is tried on disconnect. Both `Scanner` and\n`CastDevice` constructors accept a `reconnect` object as an\noptions. When set to `false`, no reconnection will be retried:\n\n```js\nconst c = new CastDevice({\n  address: '192.168.1.27',\n  reconnect: false\n});\n```\n\nOtherwise, the provided object may contain some properties to\ninfluence the reconnection:\n\n```js\nconst c = new CastDevice({\n  address: '192.168.1.27',\n  reconnect: {\n    maxRetries: 10,\n    maxDelay: 10000, // ms\n    initialDelay: 100 // ms\n  }\n});\n```\n\n## Command-line helper\n\nThe functionality of this library can be tested with the `chromecast`\nhelper. Invoke it with `chromecast -h` to get help. It embeds some\nsimple examples too.\n\nThe Tic Tac Toe application is quite incomplete. It is expected to\nplay against a human player. Here is how to use it:\n\n 1. Download the [Chrome version from GitHub](https://github.com/googlecast/Cast-TicTacToe-chrome)\n 2. Direct a browser to it (`python -mSimpleHTTPServer` if you want a quick way to get a webserver to serve the files)\n 3. Start casting the application from Chrome.\n 4. Starts `chromecast tictactoe 192.168.1.24`.\n 5. On Chrome, click play.\n\nThe Dashkiosk application is a test for the [Dashkiosk project][].\n\n[Dashkiosk project]: https://github.com/vincentbernat/dashkiosk\n\n# Protocol description\n\nThere is no formal description of the protocol. However, you can look\nat `channel.js` which shows how to build low-level messages. The\nlower-level protocol is implemented directly in Chrome and the\nprotocol is described in `cast_channel.proto`.\n\nThe high-level protocol, used by the Chromecast extension, can be\ndiscovered by modifying the extension. The following code can be\nappended to `background_script.js`:\n\n```js\nchromesendAndLog = (channel, data) => {\n  console.log('[TAP CHROMECAST send]', data);\n  return chrome.cast.channel.send.apply(chrome.cast.channel, arguments);\n};\nchrome.cast.channel.onMessage.addListener((channel, data) => {\n  console.log('[TAP CHROMECAST recv]', data);\n});\n```\n\nAny occurrence of `chrome.cast.channel.send` needs to be replaced by\n`chromesendAndLog`. Monkey-patching seems to be ineffective because\nthe whole `chrome.cast.channel` seems to be erased everytime you\nconnect/disconnect to a Chromecast. Then, filter the log messages with\n`TAP CHROMECAST` in Chrome developper tools (click on\n`background.html` for the Chromecast extension in\n`chrome://extensions`).\n\n# Alternatives\n\n - [castv2-client][] is another Javascript implementation which also\n   provides a media player implementation.\n - [ChromeCast Java API v2][] is a Java implementation.\n\n[castv2-client]: https://github.com/thibauts/node-castv2-client\n[ChromeCast Java API v2]: https://github.com/vitalidze/chromecast-java-api-v2"},"npm":{"downloads":[{"from":"2022-07-06T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":0},{"from":"2022-06-30T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":12},{"from":"2022-06-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":62},{"from":"2022-04-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":232},{"from":"2022-01-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":454},{"from":"2021-07-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":867}],"starsCount":3},"github":{"starsCount":168,"forksCount":21,"subscribersCount":14,"issues":{"count":18,"openCount":5,"distribution":{"3600":5,"10800":1,"32400":3,"97200":2,"291600":0,"874800":0,"2624400":0,"7873200":2,"23619600":0,"70858800":1,"212576400":4},"isDisabled":false},"contributors":[{"username":"vincentbernat","commitsCount":41},{"username":"amilajack","commitsCount":4},{"username":"dav-m85","commitsCount":1},{"username":"dhleong","commitsCount":5},{"username":"dependabot[bot]","commitsCount":3}],"commits":[{"from":"2022-06-30T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":0},{"from":"2022-06-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":0},{"from":"2022-04-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1},{"from":"2022-01-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1},{"from":"2021-07-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1}]},"source":{"files":{"readmeSize":7302,"testsSize":0},"badges":[{"urls":{"original":"https://img.shields.io/david/vincentbernat/nodecastor.svg","service":"https://david-dm.org/vincentbernat/nodecastor.svg","shields":"https://img.shields.io/david/vincentbernat/nodecastor.svg","content":"https://img.shields.io/david/vincentbernat/nodecastor.json"},"info":{"service":"david","type":"dependencies","modifiers":{"statusType":"normal"}}},{"urls":{"original":"https://img.shields.io/npm/dm/nodecastor.svg?maxAge=2592000","shields":"https://img.shields.io/npm/dm/nodecastor.svg","content":"https://img.shields.io/npm/dm/nodecastor.json"},"info":{"service":"npm","type":"downloads","modifiers":{"type":"dm"}}}],"outdatedDependencies":{"argparse":{"required":"^1.0.10","stable":"2.0.1","latest":"2.0.1"}}}},"evaluation":{"quality":{"carefulness":0.355,"tests":0,"health":0.75,"branding":0.3},"popularity":{"communityInterest":211,"downloadsCount":77.33333333333333,"downloadsAcceleration":-0.040449010654490025,"dependentsCount":0},"maintenance":{"releasesFrequency":0.7591609589041095,"commitsFrequency":0.06400684931506849,"openIssues":0.8703703703703703,"issuesDistribution":0}},"score":{"final":0.38561347716007194,"detail":{"quality":0.5002936686282246,"popularity":0.1116171553599804,"maintenance":0.5613124919874612}}}