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