The Invisible AUDIO element#
Thu, 22 Jan 2015 19:26:47 +0000
I said this morning that I was going to replace the browser-native audio controls with something which looks (approximately, at least) consistent everywhere. There's another couple of reasons for wanting to revisit the way we render the audio element
- on the default Android browser, we don't get an
ended
event when the player gets to the end of the track, which means every five minutes I have to pick the phone up and unlock it and press 'remove' in the play queue to trigger the next track
- when the screen is sleeping or the tab is hidden, the
requestAnimationFrame
handler that triggers Om repaints is called late or not at all. Again, time to pick the phone up and unlock and ...
- I want/need to make it run on Windows, which does not support Ogg in
the
audio
element. Although in principle I could hang multiplesource
children onto the audio element and let the browser choose which one it likes best, rewriting the DOM after it has been parsed is said to be not a good idea which means using info from the JScanPlayType
method to choose the bext format for each track from those available for that track.
The nice thing about Om application state is that it's also a
perfectly ordinary Clojure atom and we can call add-watch
on it to
have a perfectly ordinary Clojure(Script) function called whenever it
changes. So what we're going to do is
- a new key in
app-state
to contain the desired player state
- an Om component to render a player UI, and update this desired state when buttons are clicked
- some event handlers to get news from the audio element and figure out what it might be doing (principally, has it reached the end of the track, or is it having connectivity issues) and update the desired state correspondingly
- a watch on app-state that calls the function currently named
sync-player-state
, which compares the desired state to what the audio element is actually doing, and updates the audio element appropriately