2021-11-01 21:06:51 -05:00
< template >
< div >
2023-09-11 17:08:15 -05:00
< app-audio-player ref = "audioPlayer" :bookmarks = "bookmarks" :sleep-timer-running = "isSleepTimerRunning" :sleep-time-remaining = "sleepTimeRemaining" :serverLibraryItemId = "serverLibraryItemId" @ selectPlaybackSpeed = "showPlaybackSpeedModal = true" @ updateTime = "(t) => (currentTime = t)" @showSleepTimer ="showSleepTimer" @showBookmarks ="showBookmarks" / >
2021-11-01 21:06:51 -05:00
2021-12-11 13:20:20 -06:00
< modals-playback-speed-modal v-model = "showPlaybackSpeedModal" :playback-rate.sync="playbackSpeed" @update:playbackRate="updatePlaybackSpeed" @change="changePlaybackSpeed" / >
2023-02-04 16:57:55 -06:00
< modals-sleep-timer-modal v-model = "showSleepTimerModal" :current-time="sleepTimeRemaining" :sleep-timer-running="isSleepTimerRunning" :current-end-of-chapter-time="currentEndOfChapterTime" :is-auto="isAutoSleepTimer" @change="selectSleepTimeout" @cancel="cancelSleepTimer" @increase="increaseSleepTimer" @decrease="decreaseSleepTimer" / >
2022-04-23 14:19:56 -05:00
< modals-bookmarks-modal v-model = "showBookmarksModal" :bookmarks="bookmarks" :current-time="currentTime" :library-item-id="serverLibraryItemId" @select="selectBookmark" / >
2021-11-01 21:06:51 -05:00
< / div >
< / template >
< script >
2022-04-04 19:08:27 -05:00
import { AbsAudioPlayer } from '@/plugins/capacitor'
2022-04-17 16:59:49 -05:00
import { Dialog } from '@capacitor/dialog'
2021-11-01 21:06:51 -05:00
export default {
data ( ) {
return {
2022-08-19 16:36:56 -04:00
isReady : false ,
settingsLoaded : false ,
2021-11-01 21:06:51 -05:00
audioPlayerReady : false ,
stream : null ,
download : null ,
showPlaybackSpeedModal : false ,
2021-11-02 19:44:42 -05:00
showBookmarksModal : false ,
2021-11-01 21:06:51 -05:00
showSleepTimerModal : false ,
playbackSpeed : 1 ,
currentTime : 0 ,
isSleepTimerRunning : false ,
2021-11-26 18:27:18 -06:00
sleepTimerEndTime : 0 ,
2022-04-03 14:37:44 -05:00
sleepTimeRemaining : 0 ,
2023-02-04 16:57:55 -06:00
isAutoSleepTimer : false ,
2022-04-09 12:03:37 -05:00
onLocalMediaProgressUpdateListener : null ,
2021-11-01 21:06:51 -05:00
onSleepTimerEndedListener : null ,
2021-11-26 18:27:18 -06:00
onSleepTimerSetListener : null ,
2022-04-17 16:59:49 -05:00
onMediaPlayerChangedListener : null ,
2021-11-01 21:06:51 -05:00
sleepInterval : null ,
2022-04-23 14:19:56 -05:00
currentEndOfChapterTime : 0 ,
2022-08-11 17:36:27 -05:00
serverLibraryItemId : null ,
serverEpisodeId : null
2021-11-01 21:06:51 -05:00
}
} ,
computed : {
2021-11-02 19:44:42 -05:00
bookmarks ( ) {
2022-04-23 14:19:56 -05:00
if ( ! this . serverLibraryItemId ) return [ ]
return this . $store . getters [ 'user/getUserBookmarksForItem' ] ( this . serverLibraryItemId )
2023-02-17 17:14:49 -06:00
} ,
isIos ( ) {
return this . $platform === 'ios'
2021-11-01 21:06:51 -05:00
}
} ,
methods : {
2021-11-02 19:44:42 -05:00
showBookmarks ( ) {
this . showBookmarksModal = true
} ,
selectBookmark ( bookmark ) {
this . showBookmarksModal = false
if ( ! bookmark || isNaN ( bookmark . time ) ) return
2022-12-11 11:09:50 -06:00
const bookmarkTime = Number ( bookmark . time )
2021-11-02 19:44:42 -05:00
if ( this . $refs . audioPlayer ) {
this . $refs . audioPlayer . seek ( bookmarkTime )
}
} ,
2021-11-01 21:06:51 -05:00
onSleepTimerEnded ( { value : currentPosition } ) {
this . isSleepTimerRunning = false
if ( currentPosition ) {
console . log ( 'Sleep Timer Ended Current Position: ' + currentPosition )
}
} ,
2023-02-04 16:57:55 -06:00
onSleepTimerSet ( payload ) {
const { value : sleepTimeRemaining , isAuto } = payload
console . log ( 'SLEEP TIMER SET' , JSON . stringify ( payload ) )
2022-02-03 09:19:27 -06:00
if ( sleepTimeRemaining === 0 ) {
2021-11-26 18:27:18 -06:00
console . log ( 'Sleep timer canceled' )
this . isSleepTimerRunning = false
} else {
this . isSleepTimerRunning = true
}
2023-02-04 16:57:55 -06:00
this . isAutoSleepTimer = ! ! isAuto
2022-02-03 09:19:27 -06:00
this . sleepTimeRemaining = sleepTimeRemaining
2021-11-26 18:27:18 -06:00
} ,
2021-11-01 21:06:51 -05:00
showSleepTimer ( ) {
2022-04-02 12:12:00 -05:00
if ( this . $refs . audioPlayer && this . $refs . audioPlayer . currentChapter ) {
this . currentEndOfChapterTime = Math . floor ( this . $refs . audioPlayer . currentChapter . end )
2021-11-01 21:06:51 -05:00
} else {
this . currentEndOfChapterTime = 0
}
this . showSleepTimerModal = true
} ,
async selectSleepTimeout ( { time , isChapterTime } ) {
console . log ( 'Setting sleep timer' , time , isChapterTime )
2022-04-04 19:08:27 -05:00
var res = await AbsAudioPlayer . setSleepTimer ( { time : String ( time ) , isChapterTime } )
2021-11-01 21:06:51 -05:00
if ( ! res . success ) {
return this . $toast . error ( 'Sleep timer did not set, invalid time' )
}
} ,
2021-11-27 12:15:17 -06:00
increaseSleepTimer ( ) {
// Default time to increase = 5 min
2022-04-04 19:08:27 -05:00
AbsAudioPlayer . increaseSleepTime ( { time : '300000' } )
2021-11-27 12:15:17 -06:00
} ,
decreaseSleepTimer ( ) {
2022-04-04 19:08:27 -05:00
AbsAudioPlayer . decreaseSleepTime ( { time : '300000' } )
2021-11-27 12:15:17 -06:00
} ,
2021-11-01 21:06:51 -05:00
async cancelSleepTimer ( ) {
console . log ( 'Canceling sleep timer' )
2022-04-04 19:08:27 -05:00
await AbsAudioPlayer . cancelSleepTimer ( )
2021-11-01 21:06:51 -05:00
} ,
2022-04-02 12:12:00 -05:00
streamClosed ( ) {
2021-11-01 21:06:51 -05:00
console . log ( 'Stream Closed' )
} ,
streamProgress ( data ) {
if ( ! data . numSegments ) return
2023-06-19 12:37:44 -05:00
const chunks = data . chunks
2021-11-01 21:06:51 -05:00
if ( this . $refs . audioPlayer ) {
this . $refs . audioPlayer . setChunksReady ( chunks , data . numSegments )
}
} ,
streamReady ( ) {
console . log ( '[StreamContainer] Stream Ready' )
if ( this . $refs . audioPlayer ) {
this . $refs . audioPlayer . setStreamReady ( )
}
} ,
streamReset ( { streamId , startTime } ) {
2022-04-02 12:12:00 -05:00
console . log ( 'received stream reset' , streamId , startTime )
2021-11-01 21:06:51 -05:00
if ( this . $refs . audioPlayer ) {
if ( this . stream && this . stream . id === streamId ) {
this . $refs . audioPlayer . resetStream ( startTime )
}
}
} ,
2021-12-11 13:20:20 -06:00
updatePlaybackSpeed ( speed ) {
2021-11-02 19:44:42 -05:00
if ( this . $refs . audioPlayer ) {
2021-12-11 13:20:20 -06:00
console . log ( ` [AudioPlayerContainer] Update Playback Speed: ${ speed } ` )
2021-11-02 19:44:42 -05:00
this . $refs . audioPlayer . setPlaybackSpeed ( speed )
}
2021-12-11 13:20:20 -06:00
} ,
changePlaybackSpeed ( speed ) {
console . log ( ` [AudioPlayerContainer] Change Playback Speed: ${ speed } ` )
2021-11-01 21:06:51 -05:00
this . $store . dispatch ( 'user/updateUserSettings' , { playbackRate : speed } )
} ,
settingsUpdated ( settings ) {
2021-11-02 19:44:42 -05:00
console . log ( ` [AudioPlayerContainer] Settings Update | PlaybackRate: ${ settings . playbackRate } ` )
this . playbackSpeed = settings . playbackRate
2021-11-01 21:06:51 -05:00
if ( this . $refs . audioPlayer && this . $refs . audioPlayer . currentPlaybackRate !== settings . playbackRate ) {
2021-11-02 19:44:42 -05:00
console . log ( ` [AudioPlayerContainer] PlaybackRate Updated: ${ this . playbackSpeed } ` )
this . $refs . audioPlayer . setPlaybackSpeed ( this . playbackSpeed )
2021-11-01 21:06:51 -05:00
}
2022-08-19 16:36:56 -04:00
// Settings have been loaded (at least once, so it's safe to kickoff onReady)
2022-09-18 14:38:10 -04:00
if ( ! this . settingsLoaded ) {
this . settingsLoaded = true
this . notifyOnReady ( )
}
2021-11-01 21:06:51 -05:00
} ,
2021-12-05 18:31:47 -06:00
closeStreamOnly ( ) {
2022-04-02 12:12:00 -05:00
// If user logs out or disconnects from server and not playing local
if ( this . $refs . audioPlayer && ! this . $refs . audioPlayer . isLocalPlayMethod ) {
2022-04-11 18:38:01 -05:00
this . $refs . audioPlayer . closePlayback ( )
2021-12-05 18:31:47 -06:00
}
2022-03-23 17:59:14 -05:00
} ,
2022-05-04 19:31:56 -05:00
castLocalItem ( ) {
if ( ! this . serverLibraryItemId ) {
this . $toast . error ( ` Cannot cast locally downloaded media ` )
} else {
// Change to server library item
2022-08-11 17:36:27 -05:00
this . playServerLibraryItemAndCast ( this . serverLibraryItemId , this . serverEpisodeId )
2022-05-04 19:31:56 -05:00
}
} ,
2022-08-11 17:36:27 -05:00
playServerLibraryItemAndCast ( libraryItemId , episodeId ) {
2022-05-04 19:31:56 -05:00
var playbackRate = 1
if ( this . $refs . audioPlayer ) {
playbackRate = this . $refs . audioPlayer . currentPlaybackRate || 1
}
2022-08-11 17:36:27 -05:00
AbsAudioPlayer . prepareLibraryItem ( { libraryItemId , episodeId , playWhenReady : false , playbackRate } )
2022-05-04 19:31:56 -05:00
. then ( ( data ) => {
2022-06-19 11:57:19 -05:00
if ( data . error ) {
const errorMsg = data . error || 'Failed to play'
this . $toast . error ( errorMsg )
} else {
console . log ( 'Library item play response' , JSON . stringify ( data ) )
AbsAudioPlayer . requestSession ( )
}
2022-05-04 19:31:56 -05:00
} )
. catch ( ( error ) => {
console . error ( 'Failed' , error )
2022-06-19 11:57:19 -05:00
this . $toast . error ( 'Failed to play' )
2022-05-04 19:31:56 -05:00
} )
} ,
2022-04-10 20:31:47 -05:00
async playLibraryItem ( payload ) {
2022-12-11 11:09:50 -06:00
const libraryItemId = payload . libraryItemId
const episodeId = payload . episodeId
2023-01-15 14:58:26 -06:00
const startTime = payload . startTime
2023-02-11 22:57:06 +01:00
const startWhenReady = ! payload . paused
2022-04-10 20:31:47 -05:00
2022-05-04 19:31:56 -05:00
// 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
2022-12-11 11:09:50 -06:00
const serverLibraryItemId = payload . serverLibraryItemId || null
const serverEpisodeId = payload . serverEpisodeId || null
2022-05-04 19:31:56 -05:00
2022-04-17 16:59:49 -05:00
if ( libraryItemId . startsWith ( 'local' ) && this . $store . state . isCasting ) {
const { value } = await Dialog . confirm ( {
title : 'Warning' ,
message : ` Cannot cast downloaded media items. Confirm to close cast and play on your device. `
} )
if ( ! value ) {
return
}
}
2023-01-15 14:58:26 -06:00
// if already playing this item then jump to start time
if ( this . $store . getters [ 'getIsMediaStreaming' ] ( libraryItemId , episodeId ) ) {
console . log ( 'Already streaming item' , startTime )
if ( startTime !== undefined && startTime !== null ) {
// seek to start time
AbsAudioPlayer . seek ( { value : Math . floor ( startTime ) } )
2023-05-20 14:22:53 -05:00
} else if ( this . $refs . audioPlayer ) {
this . $refs . audioPlayer . play ( )
2023-01-15 14:58:26 -06:00
}
return
}
2022-04-23 14:19:56 -05:00
this . serverLibraryItemId = null
2022-08-11 17:36:27 -05:00
this . serverEpisodeId = null
2022-04-23 14:19:56 -05:00
2022-12-11 11:09:50 -06:00
let playbackRate = 1
2022-04-23 15:06:51 -05:00
if ( this . $refs . audioPlayer ) {
playbackRate = this . $refs . audioPlayer . currentPlaybackRate || 1
}
2022-04-08 18:07:31 -05:00
console . log ( 'Called playLibraryItem' , libraryItemId )
2023-02-11 22:57:06 +01:00
const preparePayload = { libraryItemId , episodeId , playWhenReady : startWhenReady , playbackRate }
2023-01-15 14:58:26 -06:00
if ( startTime !== undefined && startTime !== null ) preparePayload . startTime = startTime
AbsAudioPlayer . prepareLibraryItem ( preparePayload )
2022-03-28 19:53:53 -05:00
. then ( ( data ) => {
2022-06-19 11:57:19 -05:00
if ( data . error ) {
const errorMsg = data . error || 'Failed to play'
this . $toast . error ( errorMsg )
2022-05-04 19:31:56 -05:00
} else {
2022-06-19 11:57:19 -05:00
console . log ( 'Library item play response' , JSON . stringify ( data ) )
if ( ! libraryItemId . startsWith ( 'local' ) ) {
this . serverLibraryItemId = libraryItemId
} else {
this . serverLibraryItemId = serverLibraryItemId
}
2022-08-11 17:36:27 -05:00
if ( episodeId && ! episodeId . startsWith ( 'local' ) ) {
this . serverEpisodeId = episodeId
} else {
this . serverEpisodeId = serverEpisodeId
}
2022-04-23 14:19:56 -05:00
}
2022-03-28 19:53:53 -05:00
} )
. catch ( ( error ) => {
2022-04-08 18:07:31 -05:00
console . error ( 'Failed' , error )
2022-06-19 11:57:19 -05:00
this . $toast . error ( 'Failed to play' )
2022-03-28 19:53:53 -05:00
} )
2022-04-09 12:03:37 -05:00
} ,
2022-04-10 20:31:47 -05:00
pauseItem ( ) {
2023-09-10 17:51:53 -05:00
if ( this . $refs . audioPlayer && this . $refs . audioPlayer . isPlaying ) {
2022-04-10 20:31:47 -05:00
this . $refs . audioPlayer . pause ( )
}
} ,
2022-04-09 12:03:37 -05:00
onLocalMediaProgressUpdate ( localMediaProgress ) {
console . log ( 'Got local media progress update' , localMediaProgress . progress , JSON . stringify ( localMediaProgress ) )
this . $store . commit ( 'globals/updateLocalMediaProgress' , localMediaProgress )
2022-04-17 16:59:49 -05:00
} ,
onMediaPlayerChanged ( data ) {
2023-06-19 12:37:44 -05:00
this . $store . commit ( 'setMediaPlayer' , data . value )
2022-08-19 16:36:56 -04:00
} ,
onReady ( ) {
// The UI is reporting elsewhere we are ready
this . isReady = true
2023-02-17 17:47:46 -06:00
this . notifyOnReady ( )
2022-08-19 16:36:56 -04:00
} ,
notifyOnReady ( ) {
2023-11-12 13:36:23 -06:00
// TODO: was used on iOS to open last played media. May be removed
2023-02-17 17:47:46 -06:00
if ( ! this . isIos ) return
2022-08-19 16:36:56 -04:00
// If settings aren't loaded yet, native player will receive incorrect settings
console . log ( 'Notify on ready... settingsLoaded:' , this . settingsLoaded , 'isReady:' , this . isReady )
2023-02-17 17:14:49 -06:00
if ( this . settingsLoaded && this . isReady && this . $store . state . isFirstAudioLoad ) {
this . $store . commit ( 'setIsFirstAudioLoad' , false ) // Only run this once on app launch
2022-08-19 16:36:56 -04:00
AbsAudioPlayer . onReady ( )
}
2023-06-19 12:37:44 -05:00
} ,
playbackTimeUpdate ( currentTime ) {
this . $refs . audioPlayer ? . seek ( currentTime )
2023-09-10 17:51:53 -05:00
} ,
/ * *
* When device gains focus then refresh the timestamps in the audio player
* /
deviceFocused ( hasFocus ) {
2023-09-11 17:55:59 -05:00
if ( ! this . $store . state . currentPlaybackSession ) return
2023-09-10 17:51:53 -05:00
if ( hasFocus ) {
if ( ! this . $refs . audioPlayer ? . isPlaying ) {
const playbackSession = this . $store . state . currentPlaybackSession
if ( this . $refs . audioPlayer . isLocalPlayMethod ) {
const localLibraryItemId = playbackSession . localLibraryItem ? . id
const localEpisodeId = playbackSession . localEpisodeId
if ( ! localLibraryItemId ) {
console . error ( '[AudioPlayerContainer] device visibility: no local library item for session' , JSON . stringify ( playbackSession ) )
return
}
const localMediaProgress = this . $store . state . globals . localMediaProgress . find ( ( mp ) => {
if ( localEpisodeId ) return mp . localEpisodeId === localEpisodeId
return mp . localLibraryItemId === localLibraryItemId
} )
if ( localMediaProgress ) {
console . log ( '[AudioPlayerContainer] device visibility: found local media progress' , localMediaProgress . currentTime , 'last time in player is' , this . currentTime )
this . $refs . audioPlayer . currentTime = localMediaProgress . currentTime
this . $refs . audioPlayer . timeupdate ( )
} else {
console . error ( '[AudioPlayerContainer] device visibility: Local media progress not found' )
}
} else {
const libraryItemId = playbackSession . libraryItemId
const episodeId = playbackSession . episodeId
const url = episodeId ? ` /api/me/progress/ ${ libraryItemId } / ${ episodeId } ` : ` /api/me/progress/ ${ libraryItemId } `
2023-09-17 12:43:50 -05:00
this . $nativeHttp
. get ( url )
2023-09-10 17:51:53 -05:00
. then ( ( data ) => {
if ( ! this . $refs . audioPlayer ? . isPlaying && data . libraryItemId === libraryItemId ) {
console . log ( '[AudioPlayerContainer] device visibility: got server media progress' , data . currentTime , 'last time in player is' , this . currentTime )
this . $refs . audioPlayer . currentTime = data . currentTime
this . $refs . audioPlayer . timeupdate ( )
}
} )
. catch ( ( error ) => {
console . error ( '[AudioPlayerContainer] device visibility: Failed to get progress' , error )
} )
}
}
}
2021-11-01 21:06:51 -05:00
}
} ,
mounted ( ) {
2022-04-09 12:03:37 -05:00
this . onLocalMediaProgressUpdateListener = AbsAudioPlayer . addListener ( 'onLocalMediaProgressUpdate' , this . onLocalMediaProgressUpdate )
2022-04-04 19:08:27 -05:00
this . onSleepTimerEndedListener = AbsAudioPlayer . addListener ( 'onSleepTimerEnded' , this . onSleepTimerEnded )
this . onSleepTimerSetListener = AbsAudioPlayer . addListener ( 'onSleepTimerSet' , this . onSleepTimerSet )
2022-04-17 16:59:49 -05:00
this . onMediaPlayerChangedListener = AbsAudioPlayer . addListener ( 'onMediaPlayerChanged' , this . onMediaPlayerChanged )
2021-11-01 21:06:51 -05:00
this . playbackSpeed = this . $store . getters [ 'user/getUserSetting' ] ( 'playbackRate' )
2021-11-02 19:44:42 -05:00
console . log ( ` [AudioPlayerContainer] Init Playback Speed: ${ this . playbackSpeed } ` )
2021-11-01 21:06:51 -05:00
2022-08-19 16:36:56 -04:00
this . $eventBus . $on ( 'abs-ui-ready' , this . onReady )
2022-03-23 17:59:14 -05:00
this . $eventBus . $on ( 'play-item' , this . playLibraryItem )
2022-04-10 20:31:47 -05:00
this . $eventBus . $on ( 'pause-item' , this . pauseItem )
2022-04-02 12:12:00 -05:00
this . $eventBus . $on ( 'close-stream' , this . closeStreamOnly )
2022-05-04 19:31:56 -05:00
this . $eventBus . $on ( 'cast-local-item' , this . castLocalItem )
2022-12-17 14:48:56 -06:00
this . $eventBus . $on ( 'user-settings' , this . settingsUpdated )
2023-06-19 12:37:44 -05:00
this . $eventBus . $on ( 'playback-time-update' , this . playbackTimeUpdate )
2023-09-10 17:51:53 -05:00
this . $eventBus . $on ( 'device-focus-update' , this . deviceFocused )
2021-11-01 21:06:51 -05:00
} ,
beforeDestroy ( ) {
2022-04-09 12:03:37 -05:00
if ( this . onLocalMediaProgressUpdateListener ) this . onLocalMediaProgressUpdateListener . remove ( )
2021-11-01 21:06:51 -05:00
if ( this . onSleepTimerEndedListener ) this . onSleepTimerEndedListener . remove ( )
2021-11-26 18:27:18 -06:00
if ( this . onSleepTimerSetListener ) this . onSleepTimerSetListener . remove ( )
2022-04-17 16:59:49 -05:00
if ( this . onMediaPlayerChangedListener ) this . onMediaPlayerChangedListener . remove ( )
2021-11-01 21:06:51 -05:00
2022-08-19 16:36:56 -04:00
this . $eventBus . $off ( 'abs-ui-ready' , this . onReady )
2022-03-23 17:59:14 -05:00
this . $eventBus . $off ( 'play-item' , this . playLibraryItem )
2022-04-10 20:31:47 -05:00
this . $eventBus . $off ( 'pause-item' , this . pauseItem )
2022-04-02 12:12:00 -05:00
this . $eventBus . $off ( 'close-stream' , this . closeStreamOnly )
2022-05-04 19:31:56 -05:00
this . $eventBus . $off ( 'cast-local-item' , this . castLocalItem )
2022-12-17 14:48:56 -06:00
this . $eventBus . $off ( 'user-settings' , this . settingsUpdated )
2023-06-19 12:37:44 -05:00
this . $eventBus . $off ( 'playback-time-update' , this . playbackTimeUpdate )
2023-09-10 17:51:53 -05:00
this . $eventBus . $off ( 'device-focus-update' , this . deviceFocused )
2021-11-01 21:06:51 -05:00
}
}
< / script >