diff --git a/components/app/Appbar.vue b/components/app/Appbar.vue index 077f7a5a..737d43ef 100644 --- a/components/app/Appbar.vue +++ b/components/app/Appbar.vue @@ -80,11 +80,9 @@ export default { methods: { castClick() { if (this.$store.state.playerIsLocal) { - this.$toast.warn('Cannot cast downloaded media item') + this.$eventBus.$emit('cast-local-item') return } - - console.log('Cast Btn Click') AbsAudioPlayer.requestSession() }, clickShowSideDrawer() { diff --git a/components/app/AudioPlayer.vue b/components/app/AudioPlayer.vue index c28ebef4..0e48f330 100644 --- a/components/app/AudioPlayer.vue +++ b/components/app/AudioPlayer.vue @@ -4,7 +4,7 @@
expand_more
-
+
cast
@@ -12,6 +12,7 @@ more_vert
+

{{ isDirectPlayMethod ? 'Direct' : isLocalPlayMethod ? 'Local' : 'Transcode' }}

@@ -63,7 +64,7 @@
first_page replay_10 -
+
{{ seekLoading ? 'autorenew' : !isPlaying ? 'play_arrow' : 'pause' }}
@@ -159,7 +160,7 @@ export default { return this.showFullscreen ? 200 : 60 }, showCastBtn() { - return this.$store.state.isCastAvailable && !this.isLocalPlayMethod + return this.$store.state.isCastAvailable }, isCasting() { return this.mediaPlayer === 'cast-player' @@ -193,6 +194,9 @@ export default { isLocalPlayMethod() { return this.playMethod == this.$constants.PlayMethod.LOCAL }, + isDirectPlayMethod() { + return this.playMethod == this.$constants.PlayMethod.DIRECTPLAY + }, title() { if (this.playbackSession) return this.playbackSession.displayTitle return this.mediaMetadata ? this.mediaMetadata.title : 'Title' @@ -269,12 +273,10 @@ export default { this.showChapterModal = false }, castClick() { - console.log('Cast Btn Click') if (this.isLocalPlayMethod) { - this.$toast.warn('Cannot cast downloaded media items') + this.$eventBus.$emit('cast-local-item') return } - AbsAudioPlayer.requestSession() }, clickContainer() { diff --git a/components/app/AudioPlayerContainer.vue b/components/app/AudioPlayerContainer.vue index 584239fb..3b4ea5ee 100644 --- a/components/app/AudioPlayerContainer.vue +++ b/components/app/AudioPlayerContainer.vue @@ -168,10 +168,36 @@ export default { this.$refs.audioPlayer.closePlayback() } }, + castLocalItem() { + if (!this.serverLibraryItemId) { + this.$toast.error(`Cannot cast locally downloaded media`) + } else { + // Change to server library item + this.playServerLibraryItemAndCast(this.serverLibraryItemId) + } + }, + playServerLibraryItemAndCast(libraryItemId) { + var playbackRate = 1 + if (this.$refs.audioPlayer) { + playbackRate = this.$refs.audioPlayer.currentPlaybackRate || 1 + } + AbsAudioPlayer.prepareLibraryItem({ libraryItemId, episodeId: null, playWhenReady: false, playbackRate }) + .then((data) => { + console.log('Library item play response', JSON.stringify(data)) + AbsAudioPlayer.requestSession() + }) + .catch((error) => { + console.error('Failed', error) + }) + }, async playLibraryItem(payload) { var libraryItemId = payload.libraryItemId var episodeId = payload.episodeId + // When playing local library item and can also play this item from the server + // then store the server library item id so it can be used if a cast is made + var serverLibraryItemId = payload.serverLibraryItemId || null + if (libraryItemId.startsWith('local') && this.$store.state.isCasting) { const { value } = await Dialog.confirm({ title: 'Warning', @@ -195,6 +221,8 @@ export default { console.log('Library item play response', JSON.stringify(data)) if (!libraryItemId.startsWith('local')) { this.serverLibraryItemId = libraryItemId + } else { + this.serverLibraryItemId = serverLibraryItemId } }) .catch((error) => { @@ -228,6 +256,7 @@ export default { this.$eventBus.$on('play-item', this.playLibraryItem) this.$eventBus.$on('pause-item', this.pauseItem) this.$eventBus.$on('close-stream', this.closeStreamOnly) + this.$eventBus.$on('cast-local-item', this.castLocalItem) this.$store.commit('user/addSettingsListener', { id: 'streamContainer', meth: this.settingsUpdated }) }, beforeDestroy() { @@ -246,6 +275,7 @@ export default { this.$eventBus.$off('play-item', this.playLibraryItem) this.$eventBus.$off('pause-item', this.pauseItem) this.$eventBus.$off('close-stream', this.closeStreamOnly) + this.$eventBus.$off('cast-local-item', this.castLocalItem) this.$store.commit('user/removeSettingsListener', 'streamContainer') } } diff --git a/components/cards/LazyBookCard.vue b/components/cards/LazyBookCard.vue index da8207f2..eafbb09f 100644 --- a/components/cards/LazyBookCard.vue +++ b/components/cards/LazyBookCard.vue @@ -446,10 +446,6 @@ export default { this.selected = !this.selected this.$emit('select', this.libraryItem) }, - play() { - var eventBus = this.$eventBus || this.$nuxt.$eventBus - eventBus.$emit('play-item', { libraryItemId: this.libraryItemId }) - }, destroy() { // destroy the vue listeners, etc this.$destroy() diff --git a/ios/App/Podfile b/ios/App/Podfile index 584acebb..44119188 100644 --- a/ios/App/Podfile +++ b/ios/App/Podfile @@ -9,13 +9,13 @@ install! 'cocoapods', :disable_input_output_paths => true def capacitor_pods pod 'Capacitor', :path => '../../node_modules/@capacitor/ios' pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios' - pod 'CapacitorApp', :path => '../../node_modules/@capacitor/app' - pod 'CapacitorDialog', :path => '../../node_modules/@capacitor/dialog' - pod 'CapacitorHaptics', :path => '../../node_modules/@capacitor/haptics' - pod 'CapacitorNetwork', :path => '../../node_modules/@capacitor/network' - pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar' - pod 'CapacitorStorage', :path => '../../node_modules/@capacitor/storage' - pod 'RobingenzCapacitorAppUpdate', :path => '../../node_modules/@robingenz/capacitor-app-update' + pod 'CapacitorApp', :path => '..\..\node_modules\@capacitor\app' + pod 'CapacitorDialog', :path => '..\..\node_modules\@capacitor\dialog' + pod 'CapacitorHaptics', :path => '..\..\node_modules\@capacitor\haptics' + pod 'CapacitorNetwork', :path => '..\..\node_modules\@capacitor\network' + pod 'CapacitorStatusBar', :path => '..\..\node_modules\@capacitor\status-bar' + pod 'CapacitorStorage', :path => '..\..\node_modules\@capacitor\storage' + pod 'RobingenzCapacitorAppUpdate', :path => '..\..\node_modules\@robingenz\capacitor-app-update' end target 'App' do diff --git a/pages/item/_id.vue b/pages/item/_id.vue index 1c17d9c5..80430d1b 100644 --- a/pages/item/_id.vue +++ b/pages/item/_id.vue @@ -6,10 +6,13 @@
+ +

connected

+

{{ libraryItem.serverAddress }}

{{ title }}

- +

{{ seriesName }}

by {{ author }}

{{ $elapsedPretty(duration) }} @@ -31,7 +34,7 @@ play_arrow {{ isPlaying ? 'Playing' : 'Play' }} - + auto_stories Read {{ ebookFormat }} @@ -133,8 +136,14 @@ export default { var podcastMedia = this.localLibraryItem.media return podcastMedia ? podcastMedia.episodes || [] : [] }, - isConnected() { - return this.$store.state.socketConnected + serverLibraryItemId() { + if (!this.isLocal) return this.libraryItem.id + // Check if local library item is connected to the current server + if (!this.libraryItem.serverAddress || !this.libraryItem.libraryItemId) return null + if (this.$store.getters['user/getServerAddress'] === this.libraryItem.serverAddress) { + return this.libraryItem.libraryItemId + } + return null }, bookCoverAspectRatio() { return this.$store.getters['getBookCoverAspectRatio'] @@ -167,6 +176,10 @@ export default { series() { return this.mediaMetadata.series || [] }, + seriesName() { + // For books only on toJSONExpanded + return this.mediaMetadata.seriesName || '' + }, duration() { return this.media.duration }, @@ -237,6 +250,9 @@ export default { }, episodes() { return this.media.episodes || [] + }, + isCasting() { + return this.$store.state.isCasting } }, methods: { @@ -245,7 +261,12 @@ export default { }, playClick() { // Todo: Allow playing local or streaming - if (this.hasLocal) return this.$eventBus.$emit('play-item', { libraryItemId: this.localLibraryItem.id }) + if (this.hasLocal && this.serverLibraryItemId && this.isCasting) { + // If casting and connected to server for local library item then send server library item id + this.$eventBus.$emit('play-item', { libraryItemId: this.serverLibraryItemId }) + return + } + if (this.hasLocal) return this.$eventBus.$emit('play-item', { libraryItemId: this.localLibraryItem.id, serverLibraryItemId: this.serverLibraryItemId }) this.$eventBus.$emit('play-item', { libraryItemId: this.libraryItemId }) }, async clearProgressClick() { @@ -404,11 +425,11 @@ export default { }, mounted() { this.$eventBus.$on('new-local-library-item', this.newLocalLibraryItem) - // this.$server.socket.on('item_updated', this.itemUpdated) + this.$socket.on('item_updated', this.itemUpdated) }, beforeDestroy() { this.$eventBus.$off('new-local-library-item', this.newLocalLibraryItem) - // this.$server.socket.off('item_updated', this.itemUpdated) + this.$socket.off('item_updated', this.itemUpdated) } } \ No newline at end of file