jam-cloud/web/app/assets/javascripts/react-components/stores/BrowserMediaStore.js.coffee

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()
}
)