From c1e2b9ec5c38dfee48c734571ccce9cff8006961 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Wed, 2 Mar 2016 04:14:17 -0800 Subject: [PATCH] add chromecast/airplay support --- main/index.css | 33 ++++++++++++++------ main/index.js | 77 ++++++++++++++++++++++++++++++++++++++++------- main/views/app.js | 32 +++++++++++++++++--- package.json | 3 ++ 4 files changed, 121 insertions(+), 24 deletions(-) diff --git a/main/index.css b/main/index.css index 111af115..dec9f138 100644 --- a/main/index.css +++ b/main/index.css @@ -70,30 +70,45 @@ body.drag::before { .torrent .metadata { float: left; - width: calc(100% - 80px); + width: calc(100% - 240px); color: #FFF; text-shadow: rgba(0, 0, 0, 0.5) 0 0 4px; } -.torrent .play { - float: right; - margin-top: 25px; - background-color: #C62828; +.btn { width: 50px; height: 50px; border-radius: 25px; color: #FFF; font-size: 24px; - padding-top: 14px; - padding-left: 3px; - text-align: center; transition: all 0.1s; + text-align: center; } -.torrent .play:not(.disabled):hover { +.btn:not(.disabled):hover { -webkit-filter: brightness(1.5); } +.torrent .btn { + float: right; + margin-top: 25px; + padding-top: 14px; + margin-left: 20px; +} + +.torrent .play { + background-color: #C62828; + padding-left: 3px; +} + +.torrent .chromecast { + background-color: #64B5F6; +} + +.torrent .airplay { + background-color: #607D8B; +} + .torrent .name { font-size: 1.6em; font-weight: bold; diff --git a/main/index.js b/main/index.js index d601763b..1cf772fb 100644 --- a/main/index.js +++ b/main/index.js @@ -1,9 +1,12 @@ /* global URL, Blob */ // var prettyBytes = require('pretty-bytes') +var airplay = require('airplay-js') +var chromecasts = require('chromecasts') var createTorrent = require('create-torrent') var dragDrop = require('drag-drop') var electron = require('electron') +var networkAddress = require('network-address') var path = require('path') var throttle = require('throttleit') var thunky = require('thunky') @@ -26,7 +29,11 @@ global.WEBTORRENT_ANNOUNCE = createTorrent.announceList }) var state = global.state = { - torrents: [] + torrents: [], + server: null, + player: null, + chromcast: null, + airplay: null } var currentVDom, rootElement, getClient, updateThrottled @@ -53,6 +60,15 @@ function init () { getClient(function () {}) dragDrop('body', onFiles) + + chromecasts().on('update', function (player) { + state.chromecasts = player + update() + }) + + airplay.createBrowser().on('deviceOn', function (player) { + state.airplay = player + }).start() } init() @@ -66,20 +82,23 @@ function update () { function handler (action, ...args) { console.log('handler: %s %o', action, args) if (action === 'addTorrent') { - var torrentId = args[0] - addTorrent(torrentId) + addTorrent(args[0] /* torrentId */) } if (action === 'seed') { - var files = args[0] - seed(files) + seed(args[0] /* files */) } if (action === 'openPlayer') { - var torrent = args[0] - openPlayer(torrent) + openPlayer(args[0] /* torrent */) } if (action === 'closePlayer') { closePlayer() } + if (action === 'openChromecast') { + openChromecast(args[0] /* torrent */) + } + if (action === 'openAirplay') { + openAirplay(args[0] /* torrent */) + } } electron.ipcRenderer.on('action', function (e, action, ...args) { @@ -161,7 +180,7 @@ function torrentReady (torrent) { update() } -function openPlayer (torrent) { +function startServer (torrent, cb) { // use largest file var index = torrent.files.indexOf(torrent.files.reduce(function (a, b) { return a.length > b.length ? a : b @@ -170,20 +189,56 @@ function openPlayer (torrent) { var server = torrent.createServer() server.listen(0, function () { var port = server.address().port - state.player = { + var urlSuffix = ':' + port + '/' + index + state.server = { server: server, - url: 'http://localhost:' + port + '/' + index + localURL: 'http://localhost' + urlSuffix, + networkURL: 'http://' + networkAddress() + urlSuffix } + cb() + }) +} + +function closeServer () { + state.server.server.destroy() + state.server = null +} + +function openPlayer (torrent) { + startServer(torrent, function () { + state.player = 'local' update() }) } function closePlayer () { - state.player.server.destroy() + closeServer() state.player = null update() } +function openChromecast (torrent) { + startServer(torrent, function () { + console.log(state.server.networkURL) + state.chromecast.play(state.server.networkURL, { title: torrent.name }) + state.chromecast.on('error', function (err) { + err.message = 'Chromecast: ' + err.message + onError(err) + }) + state.player = 'chromecast' + update() + }) +} + +function openAirplay (torrent) { + startServer(torrent, function () { + state.airplay.play(state.server.networkURL, 0, function () {}) + // TODO: handle airplay errors + state.player = 'airplay' + update() + }) +} + // function onTorrent (torrent) { // function updateSpeed () { // ipc.send('') diff --git a/main/views/app.js b/main/views/app.js index 7e66ad81..df67a454 100644 --- a/main/views/app.js +++ b/main/views/app.js @@ -3,10 +3,10 @@ module.exports = App var h = require('virtual-dom/h') function App (state, handler) { - if (state.player) { + if (state.player === 'local') { return h('.player', [ h('video', { - src: state.player.url, + src: state.server.localURL, autoplay: true, controls: true }), @@ -34,15 +34,39 @@ function App (state, handler) { })() ]) ]), - h('a.play', { + h('a.btn.play', { className: !torrent.ready ? 'disabled' : '', onclick: openPlayer - }, '▶') + }, '▶'), + (function () { + if (state.chromecast) { + return h('a.btn.chromecast', { + className: !torrent.ready ? 'disabled' : '', + onclick: openChromecast + }, 'C') + } + })(), + (function () { + if (state.airplay) { + return h('a.btn.airplay', { + className: !torrent.ready ? 'disabled' : '', + onclick: openAirplay + }, 'A') + } + })() ]) function openPlayer () { handler('openPlayer', torrent) } + + function openChromecast () { + handler('openChromecast', torrent) + } + + function openAirplay () { + handler('openAirplay', torrent) + } }) return h('.app', [ h('.torrent-list', list), diff --git a/package.json b/package.json index a32978be..6a4249f8 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,13 @@ "url": "https://github.com/feross/webtorrent-app/issues" }, "dependencies": { + "airplay-js": "^0.2.16", + "chromecasts": "^1.8.0", "create-torrent": "^3.22.1", "debug": "^2.2.0", "drag-drop": "^2.3.1", "electron-debug": "^0.5.0", + "network-address": "^1.1.0", "pretty-bytes": "^3.0.0", "throttleit": "^1.0.0", "thunky": "^0.1.0",