Created
April 10, 2023 15:45
-
-
Save jackpmorgan/2b34532cc0e4bd94ea44595659d5eb60 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function(instance, context) { | |
class HowlerPlayer { | |
constructor(audioUrl, title, artist, album, artworkSrc) { | |
const _audioUrl = audioUrl; | |
const _title = title; | |
const _artist = artist; | |
const _album = album; | |
const _artworkSrc = artworkSrc; | |
this.createdTimestamp = Date.now(); | |
this.formatDuration = (durationInSeconds) => { | |
const minutes = Math.floor(durationInSeconds / 60); | |
const seconds = Math.floor(durationInSeconds % 60).toString().padStart(2, '0'); | |
return `${minutes}:${seconds}`; | |
}; | |
this.audio = new Howl({ | |
src: [_audioUrl], | |
html5: true, | |
volume: 1, | |
autoplay: false, | |
autoUnlock: true, | |
onload: () => { | |
const duration = this.duration(); | |
const formattedDuration = this.formatDuration(duration); | |
instance.publishState('duration', duration); | |
instance.publishState('durationstring', `${formattedDuration}`); | |
instance.publishState('isloaded', true); | |
this.updateMediaSession(_title, _artist, _album, _artworkSrc); | |
}, | |
}); | |
this.audio.on('end', () => { | |
instance.publishState('isplaying', false); | |
this.audio.stop(instance.data.playID); | |
instance.triggerEvent('onEnd'); | |
navigator.mediaSession.playbackState = 'paused'; | |
}); | |
this.audio.on('playerror', () => { | |
if (!instance.data.player) { | |
return; | |
} | |
this.audio.once('unlock', () => { | |
instance.publishState('isplaying', false); | |
console.log('Device is locked, unable to play the next song'); | |
this.audio.play(instance.data.playID); | |
navigator.mediaSession.playbackState = 'playing'; | |
instance.triggerEvent('onPlay'); | |
}); | |
}); | |
} | |
//Class methods | |
play() { | |
this.audio.play(); | |
instance.triggerEvent('onPlay'); | |
this.onSeekUpdate((seekPosition) => { | |
const formattedPosition = this.formatDuration(seekPosition); | |
this.updateMediaSessionPositionState(); | |
}); | |
} | |
onSeekUpdate(callback) { | |
const createdTimestamp = this.createdTimestamp; | |
const update = () => { | |
if (createdTimestamp !== instance.data.player.createdTimestamp) return; | |
callback(this.seek()); | |
requestAnimationFrame(update); | |
}; | |
update(); | |
} | |
updateMediaSessionPositionState() { | |
if ('mediaSession' in navigator) { | |
navigator.mediaSession.setPositionState({ | |
duration: this.duration(), | |
playbackRate: 1, | |
position: this.seek(), | |
}); | |
} | |
} | |
pause() { | |
this.audio.pause(instance.data.playID); | |
instance.triggerEvent('onPause'); | |
} | |
seek(position) { | |
if (typeof position !== 'undefined') { | |
this.audio.seek(position); | |
} else { | |
return this.audio.seek(); | |
} | |
instance.triggerEvent('onSeek'); | |
} | |
stop() { | |
this.audio.stop(instance.data.playID); | |
instance.triggerEvent('onStop'); | |
} | |
duration() { | |
return this.audio.duration(); | |
} | |
updateMediaSession(_title, _artist, _album, _artworkSrc) { | |
const getArtworkData = (src) => { | |
if (!src) { | |
return null; | |
} | |
if (!src.startsWith('http')) { | |
src = `https:${src}`; | |
} | |
const extension = src.match(/\.(png|jpg|jpeg|gif|bmp|webp|svg)$/i); | |
if (!extension) { | |
return null; | |
} | |
const typeMap = { | |
png: 'image/png', | |
jpg: 'image/jpeg', | |
jpeg: 'image/jpeg', | |
gif: 'image/gif', | |
bmp: 'image/bmp', | |
webp: 'image/webp', | |
svg: 'image/svg+xml', | |
}; | |
const type = typeMap[extension[1].toLowerCase()]; | |
return [{ | |
src, | |
type | |
}]; | |
}; | |
if ('mediaSession' in navigator) { | |
navigator.mediaSession.metadata = new MediaMetadata({ | |
title: _title, | |
artist: _artist, | |
album: _album, | |
artwork: getArtworkData(_artworkSrc), | |
}); | |
console.log(navigator.mediaSession.metadata) | |
navigator.mediaSession.setActionHandler('play', () => { | |
this.play(); | |
}); | |
navigator.mediaSession.setActionHandler('pause', () => { | |
this.pause(); | |
}); | |
navigator.mediaSession.setActionHandler('seekbackward', () => { | |
this.seek(this.seek() - 10); | |
}); | |
navigator.mediaSession.setActionHandler('seekforward', () => { | |
this.seek(this.seek() + 10); | |
}); | |
navigator.mediaSession.setActionHandler('stop', () => { | |
this.stop(); | |
}); | |
navigator.mediaSession.setActionHandler('seekto', (details) => { | |
if (details.fastSeek && 'fastSeek' in this.audio) { | |
this.audio.fastSeek(details.seekTime); | |
} else { | |
this.seek(details.seekTime); | |
} | |
}); | |
} | |
} | |
} | |
window.HowlerPlayer = HowlerPlayer; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment