Fix player flakiness

* No more pause icon in the file list
* Reset state.playng completely after each play
* Fixes #318: false "cannot add dupe torrent" error
This commit is contained in:
DC
2016-04-06 00:58:34 -07:00
parent 8629fc956d
commit 85b6ca0639
4 changed files with 95 additions and 79 deletions

View File

@@ -20,6 +20,7 @@ var TorrentPlayer = require('./lib/torrent-player')
var util = require('./util')
var {setDispatch} = require('./lib/dispatcher')
setDispatch(dispatch)
var State = require('./state')
// This dependency is the slowest-loading, so we lazy load it
var Cast = null
@@ -34,7 +35,7 @@ var crashReporter = electron.crashReporter
var dialog = remote.require('dialog')
// For easy debugging in Developer Tools
var state = global.state = require('./state')
var state = global.state = State.getInitialState()
var vdomLoop
@@ -116,7 +117,7 @@ function init () {
function lazyLoadCast () {
if (!Cast) {
Cast = require('./lib/cast')
Cast.init(update) // Search the local network for Chromecast and Airplays
Cast.init(state, update) // Search the local network for Chromecast and Airplays
}
return Cast
}
@@ -391,7 +392,7 @@ function loadState (cb) {
console.log('loaded state from ' + cfg.filePath)
// populate defaults if they're not there
state.saved = Object.assign({}, state.defaultSavedState, data)
state.saved = Object.assign({}, State.getDefaultSavedState(), data)
state.saved.torrents.forEach(function (torrentSummary) {
if (torrentSummary.displayName) torrentSummary.name = torrentSummary.displayName
})
@@ -741,8 +742,7 @@ function pickFileToPlay (files) {
function stopServer () {
ipcRenderer.send('wt-stop-server')
state.playing.infoHash = null
state.playing.fileIndex = null
state.playing = State.getDefaultPlayState()
state.server = null
}
@@ -766,12 +766,12 @@ function openPlayer (infoHash, index, cb) {
update()
}, 10000) /* give it a few seconds */
if (['downloading', 'seeding'].includes(torrentSummary.status)) {
openPlayerFromActiveTorrent(torrentSummary, index, timeout, cb)
} else {
if (torrentSummary.status === 'paused') {
startTorrentingSummary(torrentSummary)
ipcRenderer.once('wt-ready-' + torrentSummary.infoHash,
() => openPlayerFromActiveTorrent(torrentSummary, index, timeout, cb))
} else {
openPlayerFromActiveTorrent(torrentSummary, index, timeout, cb)
}
}

View File

@@ -15,13 +15,36 @@ var chromecasts = require('chromecasts')()
var dlnacasts = require('dlnacasts')()
var config = require('../../config')
var state = require('../state')
// App state. Cast modifies state.playing and state.errors in response to events
var state
// Callback to notify module users when state has changed
var update
// setInterval() for updating cast status
var statusInterval = null
// Start looking for cast devices on the local network
function init (appState, callback) {
state = appState
update = callback
// Listen for devices: Chromecast, DLNA and Airplay
chromecasts.on('update', function (player) {
state.devices.chromecast = chromecastPlayer(player)
})
dlnacasts.on('update', function (player) {
state.devices.dlna = dlnaPlayer(player)
})
var browser = airplay.createBrowser()
browser.on('deviceOn', function (player) {
state.devices.airplay = airplayPlayer(player)
}).start()
}
// chromecast player implementation
function chromecastPlayer (player) {
function addEvents () {
@@ -238,25 +261,6 @@ function dlnaPlayer (player) {
}
}
// start export functions
function init (callback) {
update = callback
// Listen for devices: Chromecast, DLNA and Airplay
chromecasts.on('update', function (player) {
state.devices.chromecast = chromecastPlayer(player)
})
dlnacasts.on('update', function (player) {
state.devices.dlna = dlnaPlayer(player)
})
var browser = airplay.createBrowser()
browser.on('deviceOn', function (player) {
state.devices.airplay = airplayPlayer(player)
}).start()
}
// Start polling cast device state, whenever we're connected
function startStatusInterval () {
statusInterval = setInterval(function () {

View File

@@ -5,22 +5,62 @@ var config = require('../config')
var LocationHistory = require('./lib/location-history')
module.exports = {
/*
* Temporary state disappears once the program exits.
* It can contain complex objects like open connections, etc.
*/
client: null, /* the WebTorrent client */
server: null, /* local WebTorrent-to-HTTP server */
prev: {}, /* used for state diffing in updateElectron() */
location: new LocationHistory(),
window: {
bounds: null, /* {x, y, width, height } */
isFocused: true,
isFullScreen: false,
title: config.APP_WINDOW_TITLE
},
selectedInfoHash: null, /* the torrent we've selected to view details. see state.torrents */
playing: { /* the media (audio or video) that we're currently playing */
getInitialState,
getDefaultPlayState,
getDefaultSavedState
}
function getInitialState () {
return {
/*
* Temporary state disappears once the program exits.
* It can contain complex objects like open connections, etc.
*/
client: null, /* the WebTorrent client */
server: null, /* local WebTorrent-to-HTTP server */
prev: {}, /* used for state diffing in updateElectron() */
location: new LocationHistory(),
window: {
bounds: null, /* {x, y, width, height } */
isFocused: true,
isFullScreen: false,
title: config.APP_WINDOW_TITLE
},
selectedInfoHash: null, /* the torrent we've selected to view details. see state.torrents */
playing: getDefaultPlayState(), /* the media (audio or video) that we're currently playing */
devices: { /* playback devices like Chromecast and AppleTV */
airplay: null, /* airplay client. finds and manages AppleTVs */
chromecast: null /* chromecast client. finds and manages Chromecasts */
},
dock: {
badge: 0,
progress: 0
},
modal: null, /* modal popover */
errors: [], /* user-facing errors */
nextTorrentKey: 1, /* identify torrents for IPC between the main and webtorrent windows */
/*
* Saved state is read from and written to a file every time the app runs.
* It should be simple and minimal and must be JSON.
*
* Config path:
*
* OS X ~/Library/Application Support/WebTorrent/config.json
* Linux (XDG) $XDG_CONFIG_HOME/WebTorrent/config.json
* Linux (Legacy) ~/.config/WebTorrent/config.json
* Windows (> Vista) %LOCALAPPDATA%/WebTorrent/config.json
* Windows (XP, 2000) %USERPROFILE%/Local Settings/Application Data/WebTorrent/config.json
*
* Also accessible via `require('application-config')('WebTorrent').filePath`
*/
saved: {}
}
}
/* Whenever we stop playing video or audio, here's what we reset state.playing to */
function getDefaultPlayState () {
return {
infoHash: null, /* the info hash of the torrent we're playing */
fileIndex: null, /* the zero-based index within the torrent */
location: 'local', /* 'local', 'chromecast', 'airplay' */
@@ -31,37 +71,12 @@ module.exports = {
isStalled: false,
lastTimeUpdate: 0, /* Unix time in ms */
mouseStationarySince: 0 /* Unix time in ms */
},
devices: { /* playback devices like Chromecast and AppleTV */
airplay: null, /* airplay client. finds and manages AppleTVs */
chromecast: null /* chromecast client. finds and manages Chromecasts */
},
dock: {
badge: 0,
progress: 0
},
modal: null, /* modal popover */
errors: [], /* user-facing errors */
nextTorrentKey: 1, /* identify torrents for IPC between the main and webtorrent windows */
}
}
/*
* Saved state is read from and written to a file every time the app runs.
* It should be simple and minimal and must be JSON.
*
* Config path:
*
* OS X ~/Library/Application Support/WebTorrent/config.json
* Linux (XDG) $XDG_CONFIG_HOME/WebTorrent/config.json
* Linux (Legacy) ~/.config/WebTorrent/config.json
* Windows (> Vista) %LOCALAPPDATA%/WebTorrent/config.json
* Windows (XP, 2000) %USERPROFILE%/Local Settings/Application Data/WebTorrent/config.json
*
* Also accessible via `require('application-config')('WebTorrent').filePath`
*/
saved: {},
/* If the saved state file doesn't exist yet, here's what we use instead */
defaultSavedState: {
/* If the saved state file doesn't exist yet, here's what we use instead */
function getDefaultSavedState () {
return {
version: 1, /* make sure we can upgrade gracefully later */
torrents: [
{

View File

@@ -201,7 +201,7 @@ function TorrentList (state) {
// First, find out how much of the file we've downloaded
var isDone = file.numPiecesPresent === file.numPieces
var progress = ''
if (torrentSummary.progress) {
if (torrentSummary.progress && torrentSummary.progress.files) {
var fileProg = torrentSummary.progress.files[index]
progress = Math.round(100 * fileProg.numPiecesPresent / fileProg.numPieces) + '%'
}
@@ -211,10 +211,7 @@ function TorrentList (state) {
var icon
var rowClass = ''
var handleClick
if (state.playing.infoHash === infoHash && state.playing.fileIndex === index) {
icon = 'pause_arrow' /* playing? add option to pause */
handleClick = undefined // TODO: pause audio
} else if (TorrentPlayer.isPlayable(file)) {
if (TorrentPlayer.isPlayable(file)) {
icon = 'play_arrow' /* playable? add option to play */
handleClick = dispatcher('play', infoHash, index)
} else {