From 52fa523df10f2179751811d5bda8da0da2feb4f8 Mon Sep 17 00:00:00 2001 From: kuhaku Date: Sun, 13 Jun 2021 15:31:43 +0000 Subject: [PATCH] Add support for External Players (closes #418) (#1271) * feat: add support for opening videos/playlists in external players (like mpv) #418 Signed-off-by: Randshot * feat: move external player settings into own section feat: add warnings for when the external player doesn't support the current action (e.g. reversing playlists) feat: add toggle in settings for ignoring unsupported action warnings Signed-off-by: Randshot * improvement: do not append start offset argument when the watch progress is 0 Signed-off-by: Randshot * fix: fix undefined showToast error when clicking on the external player playlist button Signed-off-by: Randshot * feat: add icon button for external player to watch-video-info (below video player) component improvement: refactor the code for opening the external player into a separate function in utils.js Signed-off-by: Randshot * feat: add support for ytdl protocol urls (supportsYtdlProtocol) chore: fix lint error Signed-off-by: Randshot * feat: add support for passing default playback rate to external player improvement: add warning message for when the external player does not support starting playback at a given offset chore: rename reverse, shuffle, and loopPlaylist fields for consistency Signed-off-by: Randshot * feat: add setting for custom external player command line arguments Signed-off-by: Randshot * chore: fix lint error Signed-off-by: Randshot * improvement(watch-video-info.js): change the default for playlistId back to null (consistent with other occurrences) improvement(utils.js/openInExternalPlayer): also check for empty playlistId string fix(watch-video-info.js): fix merge error Signed-off-by: Randshot * improvement(components/ft-list-video): check whether watch history is turned on, before adding a video to it fix(store/utils): fix playlistReverse typo, causing `undefined` being set as a command line argument fix(store/utils): check for 'string' type, instead of `null` and `undefined` fix(views/Watch): fix getPlaylistIndex returning an incorrect index, when reverse was turned on chore(locales/en-US): fix thumbnail and suppress typo chore(locales/en_GB): fix thumbnail and suppress typo Signed-off-by: Randshot * feat: pause player when opening video in external player Signed-off-by: Randshot * feat(externalPlayer): refactor externalPlayerCmdArguments into a separate static file `static/external-player-map.json` chore(components/ft-list-video): fix lint error Signed-off-by: Randshot * Revert "feat: pause player when opening video in external player" This reverts commit 28b4713334bf941be9e403abf517bb4b89beb04f. * feat: pause the app's player when opening video in external player * This commit addresses above requested changes. improvement(components/external-player-settings): move `externalPlayer` check to `ft-flex-box` improvement(components/external-player-settings): use `update*` methods, instead of `handle*` improvement(store/utils): move child_process invocation to `main/index.js` via IPC call to renderer improvement(store/utils): use `dispatch` for calling actions improvement(store/utils): get external player related settings directly in the action improvement(renderer/App): move `checkExternalPlayer` call down into `usingElectron` if statement fix(renderer/App): fix lint error improvement(components/ft-list-playlist): remove unnecessary payload fields fix(components/ft-list-playlist): fix typo in component name improvement(components/ft-list-video): remove unnecessary payload fields improvement(components/watch-video-info): remove unnecessary payload fields improvement(views/Settings): add `usingElectron` condition Signed-off-by: Randshot * fix(store/utils): fix toast message error Signed-off-by: Randshot * fix(store/utils): fix a few code mess-ups Co-authored-by: Svallinn <41585298+Svallinn@users.noreply.github.com> --- src/main/index.js | 6 + src/renderer/App.js | 17 +- .../external-player-settings.js | 53 +++++ .../external-player-settings.sass | 1 + .../external-player-settings.vue | 56 +++++ .../ft-list-playlist/ft-list-playlist.js | 35 ++- .../ft-list-playlist/ft-list-playlist.vue | 10 + .../components/ft-list-video/ft-list-video.js | 51 ++++- .../ft-list-video/ft-list-video.vue | 10 + .../watch-video-info/watch-video-info.js | 43 +++- .../watch-video-info/watch-video-info.vue | 8 + .../watch-video-playlist.vue | 5 + src/renderer/sass-partials/_ft-list-item.sass | 10 + src/renderer/sass-partials/_settings.sass | 2 +- src/renderer/store/modules/settings.js | 4 + src/renderer/store/modules/utils.js | 204 +++++++++++++++++- src/renderer/views/Playlist/Playlist.vue | 1 + src/renderer/views/Settings/Settings.js | 7 + src/renderer/views/Settings/Settings.vue | 1 + src/renderer/views/Watch/Watch.js | 27 +++ src/renderer/views/Watch/Watch.vue | 8 +- static/external-player-map.json | 23 ++ static/locales/en-US.yaml | 33 +++ static/locales/en_GB.yaml | 35 +++ 24 files changed, 641 insertions(+), 9 deletions(-) create mode 100644 src/renderer/components/external-player-settings/external-player-settings.js create mode 100644 src/renderer/components/external-player-settings/external-player-settings.sass create mode 100644 src/renderer/components/external-player-settings/external-player-settings.vue create mode 100644 static/external-player-map.json diff --git a/src/main/index.js b/src/main/index.js index a5c0c5340..910d205c3 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -4,6 +4,7 @@ import { } from 'electron' import Datastore from 'nedb' import path from 'path' +import cp from 'child_process' if (process.argv.includes('--version')) { console.log(`v${app.getVersion()}`) @@ -397,6 +398,11 @@ function runApp() { } }) + ipcMain.on('openInExternalPlayer', (_, payload) => { + const child = cp.spawn(payload.executable, payload.args, { detached: true, stdio: 'ignore' }) + child.unref() + }) + app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() diff --git a/src/renderer/App.js b/src/renderer/App.js index 11af0ef6c..fed5bf3a6 100644 --- a/src/renderer/App.js +++ b/src/renderer/App.js @@ -76,6 +76,9 @@ export default Vue.extend({ }, defaultProfile: function () { return this.$store.getters.getDefaultProfile + }, + externalPlayer: function () { + return this.$store.getters.getExternalPlayer } }, mounted: function () { @@ -87,8 +90,6 @@ export default Vue.extend({ this.checkThemeSettings() await this.checkLocale() - this.dataReady = true - if (this.usingElectron) { console.log('User is using Electron') ipcRenderer = require('electron').ipcRenderer @@ -96,8 +97,11 @@ export default Vue.extend({ this.openAllLinksExternally() this.enableOpenUrl() this.setBoundsOnClose() + await this.checkExternalPlayer() } + this.dataReady = true + setTimeout(() => { this.checkForNewUpdates() this.checkForNewBlogPosts() @@ -230,6 +234,14 @@ export default Vue.extend({ } }, + checkExternalPlayer: async function () { + const payload = { + isDev: this.isDev, + externalPlayer: this.externalPlayer + } + this.getExternalPlayerCmdArgumentsData(payload) + }, + handleUpdateBannerClick: function (response) { if (response !== false) { this.showReleaseNotes = true @@ -406,6 +418,7 @@ export default Vue.extend({ 'getRegionData', 'getYoutubeUrlInfo', 'getLocale', + 'getExternalPlayerCmdArgumentsData', 'setUpListenerToSyncSettings' ]) } diff --git a/src/renderer/components/external-player-settings/external-player-settings.js b/src/renderer/components/external-player-settings/external-player-settings.js new file mode 100644 index 000000000..62a150400 --- /dev/null +++ b/src/renderer/components/external-player-settings/external-player-settings.js @@ -0,0 +1,53 @@ +import Vue from 'vue' +import { mapActions } from 'vuex' +import FtCard from '../ft-card/ft-card.vue' +import FtSelect from '../ft-select/ft-select.vue' +import FtInput from '../ft-input/ft-input.vue' +import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue' +import FtFlexBox from '../ft-flex-box/ft-flex-box.vue' + +export default Vue.extend({ + name: 'ExternalPlayerSettings', + components: { + 'ft-card': FtCard, + 'ft-select': FtSelect, + 'ft-input': FtInput, + 'ft-toggle-switch': FtToggleSwitch, + 'ft-flex-box': FtFlexBox + }, + data: function () { + return {} + }, + computed: { + isDev: function () { + return process.env.NODE_ENV === 'development' + }, + + externalPlayerNames: function () { + return this.$store.getters.getExternalPlayerNames + }, + externalPlayerValues: function () { + return this.$store.getters.getExternalPlayerValues + }, + externalPlayer: function () { + return this.$store.getters.getExternalPlayer + }, + externalPlayerExecutable: function () { + return this.$store.getters.getExternalPlayerExecutable + }, + externalPlayerIgnoreWarnings: function () { + return this.$store.getters.getExternalPlayerIgnoreWarnings + }, + externalPlayerCustomArgs: function () { + return this.$store.getters.getExternalPlayerCustomArgs + } + }, + methods: { + ...mapActions([ + 'updateExternalPlayer', + 'updateExternalPlayerExecutable', + 'updateExternalPlayerIgnoreWarnings', + 'updateExternalPlayerCustomArgs' + ]) + } +}) diff --git a/src/renderer/components/external-player-settings/external-player-settings.sass b/src/renderer/components/external-player-settings/external-player-settings.sass new file mode 100644 index 000000000..05cb0dfb9 --- /dev/null +++ b/src/renderer/components/external-player-settings/external-player-settings.sass @@ -0,0 +1 @@ +@use "../../sass-partials/settings" diff --git a/src/renderer/components/external-player-settings/external-player-settings.vue b/src/renderer/components/external-player-settings/external-player-settings.vue new file mode 100644 index 000000000..8a945fea8 --- /dev/null +++ b/src/renderer/components/external-player-settings/external-player-settings.vue @@ -0,0 +1,56 @@ + + +