diff --git a/src/main/external-player.js b/src/main/external-player.js new file mode 100644 index 00000000..0f4648f3 --- /dev/null +++ b/src/main/external-player.js @@ -0,0 +1,65 @@ +module.exports = { + spawn, + kill, + checkInstall +} + +var cp = require('child_process') +var vlcCommand = require('vlc-command') + +var log = require('./log') +var windows = require('./windows') + +// holds a ChildProcess while we're playing a video in an external player, null otherwise +var proc + +function checkInstall (path, cb) { + // check for VLC if external player has not been specified by the user + // otherwise assume the player is installed + if (path == null) return vlcCommand((err) => cb(!err)) + process.nextTick(() => cb(true)) +} + +function spawn (path, url, title) { + if (path != null) return spawnExternal(path, [url]) + + // Try to find and use VLC if external player is not specified + vlcCommand(function (err, vlcPath) { + if (err) return windows.main.dispatch('externalPlayerNotFound') + var args = ['--play-and-exit', '--video-on-top', '--no-video-title-show', '--quiet', `--meta-title=${title}`, url] + spawnExternal(vlcPath, args) + }) +} + +function kill () { + if (!proc) return + log('Killing external player, pid ' + proc.pid) + proc.kill('SIGKILL') // kill -9 + proc = null +} + +function spawnExternal (path, args) { + log('Running external media player:', path + ' ' + args.join(' ')) + + proc = cp.spawn(path, args) + + // If it works, close the modal after a second + var closeModalTimeout = setTimeout(() => + windows.main.dispatch('exitModal'), 1000) + + proc.on('close', function (code) { + clearTimeout(closeModalTimeout) + if (!proc) return // Killed + log('External player exited with code ', code) + if (code === 0) { + windows.main.dispatch('backToList') + } else { + windows.main.dispatch('externalPlayerNotFound') + } + proc = null + }) + + proc.on('error', function (e) { + log('External player error', e) + }) +} diff --git a/src/main/ipc.js b/src/main/ipc.js index c5b5db87..ec6f4b1b 100644 --- a/src/main/ipc.js +++ b/src/main/ipc.js @@ -14,16 +14,13 @@ var menu = require('./menu') var powerSaveBlocker = require('./power-save-blocker') var shell = require('./shell') var shortcuts = require('./shortcuts') -var vlc = require('./vlc') +var externalPlayer = require('./external-player') var windows = require('./windows') var thumbar = require('./thumbar') // Messages from the main process, to be sent once the WebTorrent process starts var messageQueueMainToWebTorrent = [] -// holds a ChildProcess while we're playing a video in VLC, null otherwise -var vlcProcess - function init () { var ipc = electron.ipcMain @@ -115,52 +112,17 @@ function init () { ipc.on('setAllowNav', (e, ...args) => menu.setAllowNav(...args)) /** - * VLC - * TODO: Move most of this code to vlc.js + * External Media Player */ - ipc.on('checkForVLC', function (e) { - vlc.checkForVLC(function (isInstalled) { - windows.main.send('checkForVLC', isInstalled) + ipc.on('checkForExternalPlayer', function (e, path) { + externalPlayer.checkInstall(path, function (isInstalled) { + windows.main.send('checkForExternalPlayer', isInstalled) }) }) - ipc.on('vlcPlay', function (e, url, title) { - var args = ['--play-and-exit', '--video-on-top', '--no-video-title-show', '--quiet', `--meta-title=${title}`, url] - log('Running vlc ' + args.join(' ')) - - vlc.spawn(args, function (err, proc) { - if (err) return windows.main.dispatch('vlcNotFound') - vlcProcess = proc - - // If it works, close the modal after a second - var closeModalTimeout = setTimeout(() => - windows.main.dispatch('exitModal'), 1000) - - vlcProcess.on('close', function (code) { - clearTimeout(closeModalTimeout) - if (!vlcProcess) return // Killed - log('VLC exited with code ', code) - if (code === 0) { - windows.main.dispatch('backToList') - } else { - windows.main.dispatch('vlcNotFound') - } - vlcProcess = null - }) - - vlcProcess.on('error', function (e) { - log('VLC error', e) - }) - }) - }) - - ipc.on('vlcQuit', function () { - if (!vlcProcess) return - log('Killing VLC, pid ' + vlcProcess.pid) - vlcProcess.kill('SIGKILL') // kill -9 - vlcProcess = null - }) + ipc.on('openExternalPlayer', (e, ...args) => externalPlayer.spawn(...args)) + ipc.on('quitExternalPlayer', () => externalPlayer.kill()) // Capture all events var oldEmit = ipc.emit diff --git a/src/main/vlc.js b/src/main/vlc.js deleted file mode 100644 index b2ff659b..00000000 --- a/src/main/vlc.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = { - checkForVLC, - spawn -} - -var cp = require('child_process') -var vlcCommand = require('vlc-command') - -// Finds if VLC is installed on Mac, Windows, or Linux. -// Calls back with true or false: whether VLC was detected -function checkForVLC (cb) { - vlcCommand((err) => cb(!err)) -} - -// Spawns VLC with child_process.spawn() to return a ChildProcess object -// Calls back with (err, childProcess) -function spawn (args, cb) { - vlcCommand(function (err, vlcPath) { - if (err) return cb(err) - cb(null, cp.spawn(vlcPath, args)) - }) -} diff --git a/src/renderer/controllers/media-controller.js b/src/renderer/controllers/media-controller.js index 1de07781..a3821683 100644 --- a/src/renderer/controllers/media-controller.js +++ b/src/renderer/controllers/media-controller.js @@ -22,12 +22,12 @@ module.exports = class MediaController { if (state.location.url() === 'player') { state.playing.result = 'error' state.playing.location = 'error' - ipcRenderer.send('checkForVLC') - ipcRenderer.once('checkForVLC', function (e, isInstalled) { + ipcRenderer.send('checkForExternalPlayer', state.saved.prefs.externalPlayerPath) + ipcRenderer.once('checkForExternalPlayer', function (e, isInstalled) { state.modal = { id: 'unsupported-media-modal', error: error, - vlcInstalled: isInstalled + externalPlayerInstalled: isInstalled } }) } @@ -42,15 +42,16 @@ module.exports = class MediaController { this.state.playing.mouseStationarySince = new Date().getTime() } - vlcPlay () { - ipcRenderer.send('vlcPlay', this.state.server.localURL, this.state.window.title) - this.state.playing.location = 'vlc' + openExternalPlayer () { + var state = this.state + ipcRenderer.send('openExternalPlayer', state.saved.prefs.externalPlayerPath, state.server.localURL, state.window.title) + state.playing.location = 'external' } - vlcNotFound () { + externalPlayerNotFound () { var modal = this.state.modal if (modal && modal.id === 'unsupported-media-modal') { - modal.vlcNotFound = true + modal.externalPlayerNotFound = true } } } diff --git a/src/renderer/controllers/playback-controller.js b/src/renderer/controllers/playback-controller.js index 397b0e12..f68115e9 100644 --- a/src/renderer/controllers/playback-controller.js +++ b/src/renderer/controllers/playback-controller.js @@ -13,7 +13,7 @@ const State = require('../lib/state') const ipcRenderer = electron.ipcRenderer // Controls playback of torrents and files within torrents -// both local (