206 lines
5.1 KiB
CoffeeScript
206 lines
5.1 KiB
CoffeeScript
$ = jQuery
|
|
context = window
|
|
logger = context.JK.logger
|
|
rest = context.JK.Rest()
|
|
EVENTS = context.JK.EVENTS
|
|
|
|
BrowserMediaActions = @BrowserMediaActions
|
|
|
|
Howler._enableiOSAudio()
|
|
|
|
@BrowserMediaStore = Reflux.createStore(
|
|
{
|
|
listenables: BrowserMediaActions
|
|
audio: null
|
|
loaded: false
|
|
loading: false
|
|
playing: false
|
|
paused: false
|
|
load_error: false
|
|
id: null
|
|
media_type: null
|
|
cachedAudio: []
|
|
cache_size: 10
|
|
preload: true
|
|
|
|
playbackState:(position, time) ->
|
|
state = {}
|
|
if @playing
|
|
state.playbackState = 'play_start'
|
|
else if @paused
|
|
state.playbackState = 'play_pause'
|
|
else
|
|
state.playbackState = 'play_stop'
|
|
|
|
state.playbackStateChanged = !@state? || @state.isPlaying != @playing || @state.paused != @paused
|
|
state.positionUpdateChanged = !@state? || @state.positionMs != position
|
|
state.currentTimeChanged = !@state? || @state.time != time
|
|
state
|
|
|
|
changed: () ->
|
|
position = @onGetPlayPosition()
|
|
time = context.JK.prettyPrintSeconds(parseInt(position / 1000))
|
|
playbackState = @playbackState(position, time)
|
|
|
|
# XXX: how to deal with duration? no mention in Howler API
|
|
|
|
target = {id: @id, isPlaying: @playing, loaded: @loaded, paused: @paused, loading: @loading, load_error: @load_error, positionMs: position, time: time, durationMs: @onGetPlayDuration()}
|
|
$.extend(true, target, playbackState)
|
|
@state = target
|
|
@trigger(@state)
|
|
|
|
onLoad: (id, urls, media_type) ->
|
|
|
|
if @loading
|
|
logger.error("you can't switch to different audio while loading due to weird errors seen in Howler")
|
|
window.location.reload()
|
|
return
|
|
|
|
if @audio
|
|
@audio.stop()
|
|
@loaded = false
|
|
@loading = false
|
|
@playing = false
|
|
@paused = false
|
|
@load_error = false
|
|
|
|
@audio = null
|
|
@id = id
|
|
@media_type = media_type
|
|
@loading = @preload
|
|
@playing = false
|
|
@paused = false
|
|
|
|
|
|
for cacheItem in @cachedAudio
|
|
if cacheItem.id == id
|
|
# items in our own cache are only there if we saw that it fully loaded
|
|
@audio = cacheItem.audio
|
|
@loaded = true
|
|
@loading = false
|
|
|
|
unless @audio?
|
|
@audio = new Howl({
|
|
src: urls,
|
|
autoplay: false,
|
|
loop: false,
|
|
volume: 1,
|
|
preload: @preload,
|
|
onend: @onAudioEnded,
|
|
onload: @onAudioLoaded,
|
|
onloaderror: @onAudioLoadError,
|
|
onpause: @onAudioPause,
|
|
onplay: @onAudioPlay
|
|
})
|
|
@audio.jkid = id
|
|
|
|
@changed()
|
|
|
|
onPlay: () ->
|
|
logger.debug("BrowerMediaStore:play")
|
|
if @audio
|
|
@playing = true
|
|
@paused = false
|
|
@audio.play()
|
|
|
|
try
|
|
if !@audio.recorded_play
|
|
rest.postUserEvent({name: @media_type + '_play'}) if @media_type?
|
|
context.stats.write('web.' + @media_type + '.play', {
|
|
value: 1,
|
|
user_id: context.JK.currentUserId,
|
|
user_name: context.JK.currentUserName
|
|
}) if @media_type
|
|
|
|
@audio.recorded_play = true
|
|
catch e
|
|
logger.warn("BrowserMediaStore: unable to post user event")
|
|
|
|
onPause: () ->
|
|
if @audio
|
|
@playing = false
|
|
@paused = true
|
|
@audio.pause()
|
|
|
|
onStop: () ->
|
|
if @audio
|
|
@playing = false
|
|
@paused = false
|
|
try
|
|
@audio.pause()
|
|
catch e
|
|
@logger.info("unable to pause on stop", e)
|
|
try
|
|
@audio.seek(0)
|
|
catch e
|
|
@logger.info("unable to seek to beginning on stop", e)
|
|
|
|
|
|
onSeek: (pos) ->
|
|
if @audio
|
|
console.log("seek time", pos)
|
|
@audio.seek(pos / 1000)
|
|
|
|
onGetPlayPosition: () ->
|
|
if @audio
|
|
try
|
|
position = @audio.seek()
|
|
if position == @audio
|
|
return 0
|
|
position * 1000
|
|
catch e
|
|
return 0
|
|
else
|
|
0
|
|
|
|
onGetPlayDuration: () ->
|
|
if @audio
|
|
# XXX : how to determine duration?
|
|
try
|
|
duration = @audio.duration()
|
|
return Math.round(duration) * 1000
|
|
catch e
|
|
return 0
|
|
else
|
|
0
|
|
|
|
onAudioEnded: () ->
|
|
logger.debug("onAudioEnded")
|
|
@playing = false
|
|
@changed()
|
|
|
|
onAudioLoaded: () ->
|
|
logger.debug("onAudioLoaded", arguments)
|
|
@loaded = true
|
|
@loading = false
|
|
|
|
# add audio to cache, and ageout cached audio items if more than 10 \
|
|
if @cachedAudio.length >= @cache_size
|
|
audio = @cachedAudio.shift()
|
|
try
|
|
audio.audio.unload()
|
|
catch e
|
|
logger.error("unable to unload aged audio", @audio)
|
|
|
|
@cachedAudio.push({id: @audio.jkid, audio: @audio})
|
|
@changed()
|
|
|
|
onAudioLoadError: () ->
|
|
logger.debug("onAudioLoadError", arguments)
|
|
@load_error = true
|
|
@loading = false
|
|
@changed()
|
|
|
|
onAudioPause: () ->
|
|
logger.debug("onAudioPause")
|
|
|
|
@changed()
|
|
|
|
onAudioPlay: () ->
|
|
logger.debug("onAudioPlay")
|
|
@playing = true
|
|
@paused = false
|
|
@changed()
|
|
|
|
}
|
|
) |