generativefm / generative.fm

A platform for playing generative music in the browser.
https://generative.fm
MIT License
1.59k stars 86 forks source link

Implement mediaSession api to support pause, next, etc #62

Closed ryanramage closed 5 years ago

ryanramage commented 5 years ago

I listen to generative.fm on my mobile android via a bluetooth headset. It would be amazing if I could pause and do next track with my bluetooth controls. I have tested the mediaSession api, and it easily supports this. It would be amazing if generative.fm added this. Here is an example of it working, with code snippets.

https://googlechrome.github.io/samples/media-session/audio.html

I would be up for doing a pull request if you'd like.

Thanks!

alexbainter commented 5 years ago

Nice, this should be quick for me to add with a Redux middleware. I'm going to see if I can squeeze it into the next release.

ryanramage commented 5 years ago

ok, it was a little harder. One issue is that the mediaSession api only works on audio tags currently. So this is what what I got working. I added the following into index.jsx. Understanding the following

if (navigator.mediaSession) {

  function playAudio() {
    var audio = document.createElement('audio');
    audio.src = './silence.mp3'; // silence must be at least 5 seconds https://freesound.org/people/silentspeaker/sounds/426895/

    // to keep the controls open, must loop
    audio.addEventListener('ended', function() {
      this.currentTime = 0;
      this.play();
    }, false);

    audio.play().then(_ => {
      let playing = true;
      navigator.mediaSession.setActionHandler('play', function() {
        console.log('play');
        audio.play()
        store.dispatch(play());
      });
      navigator.mediaSession.setActionHandler('pause', function() {
        console.log('Pause');
        if (playing) {
          audio.pause()
          store.dispatch(stop());
        }
        else {
          audio.play()
          store.dispatch(play())
        }
        playing = !playing
      });
      navigator.mediaSession.setActionHandler('nexttrack', function() {
        console.log('next');
        store.dispatch(next());
      });
    }).catch(error => { console.log(error); });
  }
  document.addEventListener('DOMContentLoaded', function () {
    document.querySelectorAll('.control-button').forEach(b => {
      b.addEventListener('click', playAudio)
    })
  })
}
alexbainter commented 5 years ago

That is super helpful research, thanks. The silent audio is not an issue, that was actually the same hack I had to do to get audio to behave on iOS devices.