refactor cast module

* refactor cast module

* fix standard

* remove debug dependency
This commit is contained in:
grunjol
2016-04-04 05:22:02 -03:00
committed by DC
parent 5d5a32858d
commit 4ee8a883bf
2 changed files with 167 additions and 96 deletions

View File

@@ -242,10 +242,10 @@ function dispatch (action, ...args) {
openTorrentContextMenu(args[0] /* infoHash */)
}
if (action === 'openChromecast') {
lazyLoadCast().openChromecast()
lazyLoadCast().open('chromecast')
}
if (action === 'openAirplay') {
lazyLoadCast().openAirplay()
lazyLoadCast().open('airplay')
}
if (action === 'stopCasting') {
lazyLoadCast().stopCasting()

View File

@@ -9,8 +9,7 @@ var state = require('../state')
// * Starts and stops casting, provides remote video controls
module.exports = {
init,
openChromecast,
openAirplay,
open,
stopCasting,
playPause,
seek,
@@ -21,50 +20,102 @@ module.exports = {
// Callback to notify module users when state has changed
var update
function init (callback) {
update = callback
// chromecast player implementation
function chromecastPlayer (player) {
function addEvents () {
player.on('error', function (err) {
player.errorMessage = err.message
update()
})
player.on('disconnect', function () {
state.playing.location = 'local'
update()
})
}
// Start polling Chromecast or Airplay, whenever we're connected
setInterval(() => pollCastStatus(state), 1000)
function open () {
var torrentSummary = state.saved.torrents.find((x) => x.infoHash === state.playing.infoHash)
player.play(state.server.networkURL, {
type: 'video/mp4',
title: config.APP_NAME + ' — ' + torrentSummary.name
}, function (err) {
if (err) {
state.playing.location = 'local'
} else {
state.playing.location = 'chromecast'
}
update()
})
}
// Listen for devices: Chromecast and Airplay
chromecasts.on('update', function (player) {
state.devices.chromecast = player
addChromecastEvents()
})
function playPause (callback) {
if (!state.playing.isPaused) player.pause(callback)
else player.play(null, null, callback)
}
var browser = airplay.createBrowser()
browser.on('deviceOn', function (player) {
state.devices.airplay = player
addAirplayEvents()
}).start()
}
function stop (callback) {
player.stop(callback)
}
function addChromecastEvents () {
state.devices.chromecast.on('error', function (err) {
state.devices.chromecast.errorMessage = err.message
update()
})
state.devices.chromecast.on('disconnect', function () {
state.playing.location = 'local'
update()
})
}
function addAirplayEvents () {}
// Update our state from the remote TV
function pollCastStatus (state) {
if (state.playing.location === 'chromecast') {
state.devices.chromecast.status(function (err, status) {
function status (state) {
player.status(function (err, status) {
if (err) return console.log('error getting %s status: %o', state.playing.location, err)
state.playing.isPaused = status.playerState === 'PAUSED'
state.playing.currentTime = status.currentTime
state.playing.volume = status.volume.muted ? 0 : status.volume.level
update()
})
} else if (state.playing.location === 'airplay') {
state.devices.airplay.status(function (status) {
}
function seek (time, callback) {
player.seek(time, callback)
}
function volume (volume, callback) {
player.volume(volume, callback)
}
addEvents()
return {
player: player,
open: open,
playPause: playPause,
stop: stop,
status: status,
seek: seek,
volume: volume
}
}
// airplay player implementation
function airplayPlayer (player) {
function open () {
player.play(state.server.networkURL, 0, function (res) {
if (res.statusCode !== 200) {
state.playing.location = 'local'
state.errors.push({
time: new Date().getTime(),
message: 'Couldn\'t connect to Airplay'
})
} else {
state.playing.location = 'airplay'
}
update()
})
}
function playPause (callback) {
if (!state.playing.isPaused) player.rate(0, callback)
else player.rate(1, callback)
}
function stop (callback) {
player.stop(callback)
}
function status (state) {
player.status(function (status) {
state.playing.isPaused = status.rate === 0
state.playing.currentTime = status.position
// TODO: get airplay volume, implementation needed. meanwhile set value in setVolume
@@ -73,54 +124,75 @@ function pollCastStatus (state) {
update()
})
}
}
function openChromecast () {
if (state.playing.location !== 'local') {
throw new Error('You can\'t connect to Chromecast when already connected to another device')
function seek (time, callback) {
player.scrub(time, callback)
}
state.playing.location = 'chromecast-pending'
var torrentSummary = state.saved.torrents.find((x) => x.infoHash === state.playing.infoHash)
state.devices.chromecast.play(state.server.networkURL, {
type: 'video/mp4',
title: config.APP_NAME + ' — ' + torrentSummary.name
}, function (err) {
state.playing.location = err ? 'local' : 'chromecast'
update()
})
update()
}
function openAirplay () {
if (state.playing.location !== 'local') {
throw new Error('You can\'t connect to Airplay when already connected to another device')
function volume (volume, callback) {
// TODO remove line below once we can fetch the information in status update
state.playing.volume = volume
volume = (volume - 1) * 30
player.volume(volume, callback)
}
state.playing.location = 'airplay-pending'
state.devices.airplay.play(state.server.networkURL, 0, function (res) {
if (res.statusCode !== 200) {
state.playing.location = 'local'
state.errors.push({
time: new Date().getTime(),
message: 'Couldn\'t connect to Airplay'
})
} else {
state.playing.location = 'airplay'
}
update()
return {
player: player,
open: open,
playPause: playPause,
stop: stop,
status: status,
seek: seek,
volume: volume
}
}
// start export functions
function init (callback) {
update = callback
// Start polling Chromecast or Airplay, whenever we're connected
setInterval(() => pollCastStatus(state), 1000)
// Listen for devices: Chromecast and Airplay
chromecasts.on('update', function (player) {
state.devices.chromecast = chromecastPlayer(player)
})
var browser = airplay.createBrowser()
browser.on('deviceOn', function (player) {
state.devices.airplay = airplayPlayer(player)
}).start()
}
// Update our state from the remote TV
function pollCastStatus (state) {
var device = getDevice()
if (device) {
device.status(state)
}
}
function open (location) {
if (state.playing.location !== 'local') {
throw new Error('You can\'t connect to ' + location + ' when already connected to another device')
}
state.playing.location = location + '-pending'
var device = getDevice(location)
if (device) {
getDevice(location).open()
}
update()
}
// Stops Chromecast or Airplay, move video back to local screen
function stopCasting () {
if (state.playing.location === 'chromecast') {
state.devices.chromecast.stop(stoppedCasting)
} else if (state.playing.location === 'airplay') {
state.devices.airplay.stop(stoppedCasting)
} else if (state.playing.location.endsWith('-pending')) {
// Connecting to Chromecast took too long or errored out. Let the user cancel
var device = getDevice()
if (device) {
device.stop(stoppedCasting)
} else {
stoppedCasting()
}
}
@@ -138,38 +210,37 @@ function isCasting () {
return state.playing.location === 'chromecast' || state.playing.location === 'airplay'
}
function playPause () {
var device
if (state.playing.location === 'chromecast') {
device = state.devices.chromecast
if (!state.playing.isPaused) device.pause(castCallback)
else device.play(null, null, castCallback)
function getDevice (location) {
if (location && state.devices[location]) {
return state.devices[location]
} else if (state.playing.location === 'chromecast') {
return state.devices.chromecast
} else if (state.playing.location === 'airplay') {
device = state.devices.airplay
if (!state.playing.isPaused) device.rate(0, castCallback)
else device.rate(1, castCallback)
return state.devices.airplay
}
}
function playPause () {
var device = getDevice()
if (device) {
device.playPause(castCallback)
}
}
function seek (time) {
if (state.playing.location === 'chromecast') {
state.devices.chromecast.seek(time, castCallback)
} else if (state.playing.location === 'airplay') {
state.devices.airplay.scrub(time, castCallback)
var device = getDevice()
if (device) {
device.seek(time, castCallback)
}
}
function setVolume (volume) {
if (state.playing.location === 'chromecast') {
state.devices.chromecast.volume(volume, castCallback)
} else if (state.playing.location === 'airplay') {
// TODO remove line below once we can fetch the information in status update
state.playing.volume = volume
volume = (volume - 1) * 30
state.devices.airplay.volume(volume, castCallback)
var device = getDevice()
if (device) {
device.volume(volume, castCallback)
}
}
function castCallback () {
console.log(state.playing.location + ' callback: %o', arguments)
console.log('%s callback: %o', state.playing.location, arguments)
}