mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			146 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { buildCastLoadRequest, castLoadMedia } from "./castUtils"
 | |
| import EventEmitter from 'events'
 | |
| 
 | |
| export default class CastPlayer extends EventEmitter {
 | |
|   constructor(ctx) {
 | |
|     super()
 | |
| 
 | |
|     this.ctx = ctx
 | |
|     this.player = null
 | |
|     this.playerController = null
 | |
| 
 | |
|     this.libraryItem = null
 | |
|     this.audioTracks = []
 | |
|     this.currentTrackIndex = 0
 | |
|     this.isHlsTranscode = null
 | |
|     this.currentTime = 0
 | |
|     this.playWhenReady = false
 | |
|     this.defaultPlaybackRate = 1
 | |
| 
 | |
|     // TODO: Use canDisplayType on receiver to check mime types
 | |
|     this.playableMimeTypes = []
 | |
| 
 | |
|     this.coverUrl = ''
 | |
|     this.castPlayerState = 'IDLE'
 | |
| 
 | |
|     // Supported audio codecs for chromecast
 | |
| 
 | |
|     this.supportedAudioCodecs = ['opus', 'mp3', 'aac', 'flac', 'webma', 'wav']
 | |
| 
 | |
|     this.initialize()
 | |
|   }
 | |
| 
 | |
|   get currentTrack() {
 | |
|     return this.audioTracks[this.currentTrackIndex] || {}
 | |
|   }
 | |
| 
 | |
|   initialize() {
 | |
|     this.player = this.ctx.$root.castPlayer
 | |
|     this.playerController = this.ctx.$root.castPlayerController
 | |
|     this.playerController.addEventListener(
 | |
|       cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, this.evtMediaInfoChanged.bind(this))
 | |
|   }
 | |
| 
 | |
|   evtMediaInfoChanged() {
 | |
|     // Use the current session to get an up to date media status.
 | |
|     let session = cast.framework.CastContext.getInstance().getCurrentSession()
 | |
|     if (!session) {
 | |
|       return
 | |
|     }
 | |
|     let media = session.getMediaSession()
 | |
|     if (!media) {
 | |
|       return
 | |
|     }
 | |
| 
 | |
|     var currentItemId = media.media.itemId
 | |
|     if (currentItemId && this.currentTrackIndex !== currentItemId - 1) {
 | |
|       this.currentTrackIndex = currentItemId - 1
 | |
|     }
 | |
| 
 | |
|     // TODO: Emit finished event
 | |
|     if (media.playerState !== this.castPlayerState) {
 | |
|       this.emit('stateChange', media.playerState)
 | |
|       this.castPlayerState = media.playerState
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   destroy() {
 | |
|     if (this.playerController) {
 | |
|       this.playerController.stop()
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   async set(libraryItem, tracks, isHlsTranscode, startTime, playWhenReady = false) {
 | |
|     this.libraryItem = libraryItem
 | |
|     this.audioTracks = tracks
 | |
|     this.isHlsTranscode = isHlsTranscode
 | |
|     this.playWhenReady = playWhenReady
 | |
| 
 | |
|     this.currentTime = startTime
 | |
| 
 | |
|     var coverImg = this.ctx.$store.getters['globals/getLibraryItemCoverSrc'](libraryItem)
 | |
|     if (process.env.NODE_ENV === 'development') {
 | |
|       this.coverUrl = coverImg
 | |
|     } else {
 | |
|       this.coverUrl = `${window.location.origin}${coverImg}`
 | |
|     }
 | |
| 
 | |
|     var request = buildCastLoadRequest(this.libraryItem, this.coverUrl, this.audioTracks, this.currentTime, playWhenReady, this.defaultPlaybackRate)
 | |
| 
 | |
|     var castSession = cast.framework.CastContext.getInstance().getCurrentSession()
 | |
|     await castLoadMedia(castSession, request)
 | |
|   }
 | |
| 
 | |
|   resetStream(startTime) {
 | |
|     // Cast only direct play for now
 | |
|   }
 | |
| 
 | |
|   playPause() {
 | |
|     if (this.playerController) this.playerController.playOrPause()
 | |
|   }
 | |
| 
 | |
|   play() {
 | |
|     if (this.playerController) this.playerController.playOrPause()
 | |
|   }
 | |
| 
 | |
|   pause() {
 | |
|     if (this.playerController) this.playerController.playOrPause()
 | |
|   }
 | |
| 
 | |
|   getCurrentTime() {
 | |
|     var currentTrackOffset = this.currentTrack.startOffset || 0
 | |
|     return this.player ? currentTrackOffset + this.player.currentTime : 0
 | |
|   }
 | |
| 
 | |
|   getDuration() {
 | |
|     if (!this.audioTracks.length) return 0
 | |
|     var lastTrack = this.audioTracks[this.audioTracks.length - 1]
 | |
|     return lastTrack.startOffset + lastTrack.duration
 | |
|   }
 | |
| 
 | |
|   setPlaybackRate(playbackRate) {
 | |
|     this.defaultPlaybackRate = playbackRate
 | |
|   }
 | |
| 
 | |
|   async seek(time, playWhenReady) {
 | |
|     if (!this.player) return
 | |
| 
 | |
|     this.playWhenReady = playWhenReady
 | |
|     if (time < this.currentTrack.startOffset || time > this.currentTrack.startOffset + this.currentTrack.duration) {
 | |
|       // Change Track
 | |
|       var request = buildCastLoadRequest(this.libraryItem, this.coverUrl, this.audioTracks, time, playWhenReady, this.defaultPlaybackRate)
 | |
|       var castSession = cast.framework.CastContext.getInstance().getCurrentSession()
 | |
|       await castLoadMedia(castSession, request)
 | |
|     } else {
 | |
|       var offsetTime = time - (this.currentTrack.startOffset || 0)
 | |
|       this.player.currentTime = Math.max(0, offsetTime)
 | |
|       this.playerController.seek()
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   setVolume(volume) {
 | |
|     if (!this.player) return
 | |
|     this.player.volumeLevel = volume
 | |
|     this.playerController.setVolumeLevel()
 | |
|   }
 | |
| } |