From 30732305ff94fed7e35f590932610d8cfc85897a Mon Sep 17 00:00:00 2001 From: Adam Gotlib Date: Fri, 2 Sep 2016 04:18:48 +0200 Subject: [PATCH] Add playlists feature (#871) * Open multi-file torrents as playlists * Add `repeat` and `shuffle` options to the player * Autoplay first file in torrent * replaces `pickFileToPlay` feature * when reopening player, restores the most recently viewed file * Add playlist navigation buttons to Windows thumbar * Remove `repeat` and `shuffle` options This reverts commit 9284122461fdb57a3884e97f43495b2167a259dd. * Play files in order they appear in torrent * Clean up playlists code --- src/main/ipc.js | 5 + src/main/menu.js | 28 ++++ src/main/shortcuts.js | 10 ++ src/main/thumbar.js | 69 ++++++-- src/renderer/controllers/media-controller.js | 5 +- .../controllers/playback-controller.js | 154 ++++++++++++------ .../controllers/torrent-controller.js | 2 - src/renderer/lib/cast.js | 6 +- src/renderer/lib/errors.js | 13 +- src/renderer/lib/playlist.js | 85 ++++++++++ src/renderer/lib/torrent-player.js | 25 +-- src/renderer/main.js | 2 + src/renderer/pages/PlayerPage.js | 27 ++- src/renderer/pages/TorrentListPage.js | 13 +- src/renderer/webtorrent.js | 16 +- static/NextTrackThumbnailBarButton.png | Bin 0 -> 225 bytes static/PreviousTrackThumbnailBarButton.png | Bin 0 -> 233 bytes static/main.css | 20 ++- 18 files changed, 363 insertions(+), 117 deletions(-) create mode 100644 src/renderer/lib/playlist.js create mode 100644 static/NextTrackThumbnailBarButton.png create mode 100644 static/PreviousTrackThumbnailBarButton.png diff --git a/src/main/ipc.js b/src/main/ipc.js index ec6f4b1b..2e9ffc33 100644 --- a/src/main/ipc.js +++ b/src/main/ipc.js @@ -64,6 +64,11 @@ function init () { thumbar.enable() }) + ipc.on('onPlayerUpdate', function (e, ...args) { + menu.onPlayerUpdate(...args) + thumbar.onPlayerUpdate(...args) + }) + ipc.on('onPlayerClose', function () { menu.setPlayerOpen(false) powerSaveBlocker.disable() diff --git a/src/main/menu.js b/src/main/menu.js index 74067fa3..2e4d6373 100644 --- a/src/main/menu.js +++ b/src/main/menu.js @@ -3,6 +3,7 @@ module.exports = { setPlayerOpen, setWindowFocus, setAllowNav, + onPlayerUpdate, onToggleAlwaysOnTop, onToggleFullScreen } @@ -25,6 +26,8 @@ function init () { function setPlayerOpen (flag) { getMenuItem('Play/Pause').enabled = flag + getMenuItem('Skip Next').enabled = flag + getMenuItem('Skip Previous').enabled = flag getMenuItem('Increase Volume').enabled = flag getMenuItem('Decrease Volume').enabled = flag getMenuItem('Step Forward').enabled = flag @@ -32,6 +35,16 @@ function setPlayerOpen (flag) { getMenuItem('Increase Speed').enabled = flag getMenuItem('Decrease Speed').enabled = flag getMenuItem('Add Subtitles File...').enabled = flag + + if (flag === false) { + getMenuItem('Skip Next').enabled = false + getMenuItem('Skip Previous').enabled = false + } +} + +function onPlayerUpdate (hasNext, hasPrevious) { + getMenuItem('Skip Next').enabled = hasNext + getMenuItem('Skip Previous').enabled = hasPrevious } function setWindowFocus (flag) { @@ -187,6 +200,21 @@ function getMenuTemplate () { { type: 'separator' }, + { + label: 'Skip Next', + accelerator: 'N', + click: () => windows.main.dispatch('nextTrack'), + enabled: false + }, + { + label: 'Skip Previous', + accelerator: 'P', + click: () => windows.main.dispatch('previousTrack'), + enabled: false + }, + { + type: 'separator' + }, { label: 'Increase Volume', accelerator: 'CmdOrCtrl+Up', diff --git a/src/main/shortcuts.js b/src/main/shortcuts.js index 02bc2320..9fd71e8a 100644 --- a/src/main/shortcuts.js +++ b/src/main/shortcuts.js @@ -12,9 +12,19 @@ function enable () { 'MediaPlayPause', () => windows.main.dispatch('playPause') ) + electron.globalShortcut.register( + 'MediaNextTrack', + () => windows.main.dispatch('nextTrack') + ) + electron.globalShortcut.register( + 'MediaPreviousTrack', + () => windows.main.dispatch('previousTrack') + ) } function disable () { // Return the media key to the OS, so other apps can use it. electron.globalShortcut.unregister('MediaPlayPause') + electron.globalShortcut.unregister('MediaNextTrack') + electron.globalShortcut.unregister('MediaPreviousTrack') } diff --git a/src/main/thumbar.js b/src/main/thumbar.js index 749aa1a3..6793cfae 100644 --- a/src/main/thumbar.js +++ b/src/main/thumbar.js @@ -2,7 +2,8 @@ module.exports = { disable, enable, onPlayerPause, - onPlayerPlay + onPlayerPlay, + onPlayerUpdate } /** @@ -16,39 +17,75 @@ var config = require('../config') var windows = require('./windows') +const PREV_ICON = path.join(config.STATIC_PATH, 'PreviousTrackThumbnailBarButton.png') +const PLAY_ICON = path.join(config.STATIC_PATH, 'PlayThumbnailBarButton.png') +const PAUSE_ICON = path.join(config.STATIC_PATH, 'PauseThumbnailBarButton.png') +const NEXT_ICON = path.join(config.STATIC_PATH, 'NextTrackThumbnailBarButton.png') + +// Array indices for each button +const PREV = 0 +const PLAY_PAUSE = 1 +const NEXT = 2 + +var buttons = [] + /** * Show the Windows thumbnail toolbar buttons. */ function enable () { - update(false) + buttons = [ + { + tooltip: 'Previous Track', + icon: PREV_ICON, + click: () => windows.main.dispatch('previousTrack') + }, + { + tooltip: 'Pause', + icon: PAUSE_ICON, + click: () => windows.main.dispatch('playPause') + }, + { + tooltip: 'Next Track', + icon: NEXT_ICON, + click: () => windows.main.dispatch('nextTrack') + } + ] + update() } /** * Hide the Windows thumbnail toolbar buttons. */ function disable () { - windows.main.win.setThumbarButtons([]) + buttons = [] + update() } function onPlayerPause () { - update(true) + if (!isEnabled()) return + buttons[PLAY_PAUSE].tooltip = 'Play' + buttons[PLAY_PAUSE].icon = PLAY_ICON + update() } function onPlayerPlay () { - update(false) + if (!isEnabled()) return + buttons[PLAY_PAUSE].tooltip = 'Pause' + buttons[PLAY_PAUSE].icon = PAUSE_ICON + update() } -function update (isPaused) { - var icon = isPaused - ? 'PlayThumbnailBarButton.png' - : 'PauseThumbnailBarButton.png' +function onPlayerUpdate (state) { + if (!isEnabled()) return + buttons[PREV].flags = [ state.hasPrevious ? 'enabled' : 'disabled' ] + buttons[NEXT].flags = [ state.hasNext ? 'enabled' : 'disabled' ] + update() +} - var buttons = [ - { - tooltip: isPaused ? 'Play' : 'Pause', - icon: path.join(config.STATIC_PATH, icon), - click: () => windows.main.dispatch('playPause') - } - ] +function isEnabled () { + return buttons.length > 0 +} + +function update () { windows.main.win.setThumbarButtons(buttons) } diff --git a/src/renderer/controllers/media-controller.js b/src/renderer/controllers/media-controller.js index a3821683..128878a2 100644 --- a/src/renderer/controllers/media-controller.js +++ b/src/renderer/controllers/media-controller.js @@ -2,6 +2,8 @@ const electron = require('electron') const ipcRenderer = electron.ipcRenderer +const Playlist = require('../lib/playlist') + // Controls local play back: the