https://flic.kr/p/qSHsio

How not to create a stupid Rails extension that screams at you

Hello dear nonexistent readers, it’s story time again! This time, as last time, we’ll talk about how computers make our lives harder when we try to make them do stuff.

TL/DR of actually useful bits of info in this rant:

  • Spammers ruin everything. They suck.
  • Modern browsers make it impossible to just up and play sound at the user. Some kind of interaction is necessary beforehand (there are exceptions for sites that repeatedly use sound, like a video site), usually a button press etc. This actually makes a lot of sense and seems to be implemented pretty neatly.
  • Before fiddling endlessly with stuff and reading messy Stack Overflow answers, it makes super duper sense to take some minutes to read the actual browser docs…

Ok back to ranting

What I wanted to make was really stupid: An extension to the Rails active record framework, which would allow anyone to add a long-missed feature to validations: That when an error occurs, the page would not only display an error message but would also play a sound file really loudly that screams at you for being so stupid to cause errors.

Yeah yeah. One of those ideas that seemed hilarious at 2 am in the morning on the way home from the pub. Although this video, which is the inspiration, still cracks me up…

But I wanted to go at it really professionally. I had everything lined up – a list of requirements, possible bonus features (I18n for sound files? Try to play them in the Rails console as well?), plans for seeing how to create and publish a rubygem in 2019 (I made some gems before but the helpers around that kept changing), etc.

And so I spent quite some time on writing up lists of that. But I should have listened to a nagging feeling – that I should check first on how to actually play sound files in a browser on a page load. Because that sounded a bit like it might be misused and therefore be a bit tricky.

So I finally started on doing that. Some googling led to this SO question … which leads to a sinking feeling in my gut. There’s a whole lot of answers, all quite different, more or less contradicting, and lots of comments saying “doesn’t work in Browser x”…this seems like one of those browser-support-morasses where there’s a lot of history around a feature, everything evolved differently in different browsers, and lots of more or less smart people created workarounds and libraries and left a lot of deprecated info flying around online…i.e. the bad kind of web development. Been there. Not fun.

I also found something a bit more professional: https://developers.google.com/web/updates/2017/09/autoplay-policy-changes but it’s about videos? So I didn’t really read it.

But oh well, let’s actually do something. The first SO answer had something simple looking, so let’s make a test page:

<!doctype html>
<html lang=en>
  <head>
    <meta charset=utf-8>
    <title>Audio test</title>
  </head>
  <body>
    <p>Blah blah</p>
    
      var audio = new Audio("aaa.ogg");
      audio.play();
    
  </body>
</html>

Saving this as a .html file, and opened in a browser, it should directly play that “aaa.ogg” sound file. Easy peasy.

Right, we need a sound snippet, right? Let’s just record a quick soundbite (well, a scream, in keeping with the idea) with the Laptop microphone.

Another aside; On the joys and sorrows of using Ubuntu

I’m one of those freaks in web development that does not use a Mac. Sue me, I never got used to them – I was a Windows kid, then switched to Ubuntu when using Ruby/Rails on Windows was way, way too painful (never say the word “cygwin” to me…)

Ubuntu the good bit: Using the “home” button and typing “record” shows there are no programs installed that would help me, but asks if I want to install “Sound Recorder”. I say yes. Bam, it installs, and opens, and I can record sound. Takes like 20 seconds. Ain’t that something?

Buuut…ok where is my recording? Hello? Mr. Sound Recorder Program?

Not shown: A sensible UI

There is absolutely no way of actually interacting with your recordings – you can only play or delete them. After some educated guessing, it turns out the files end up in ~/Recordings. And they are in .ogg 😦

Ok back to playing .ogg files in the browser

Now we can put the aaa.ogg file in the same folder as the test html file, open it again, and….nothing.

Well except for this helpful error message (in the dev tools console): “Uncaught (in promise) DOMException” . Well fuck you too, Chrome. Googling reveals that this means “Autoplaying is not allowed, fool”.

Firefox has a much better error message: “NotAllowedError: The play method is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.”

So now we get to the end of this little adventure. After actually reading this (which I skimmed over earlier): https://developers.google.com/web/updates/2017/09/autoplay-policy-changes – well, it really makes sense, doesn’t it? If it’d be possible to just start playing sound/video files, all pages would be full of ads and other bits of junk that blared at you. Some more fiddling to actually see this in action:

<!doctype html>
<html lang=en>
  <head>
    <meta charset=utf-8>
    <title>Audio test</title>
  </head>
  <body>
    <p id="hovercraft">Press play on tape</p>
    <button id="tape">Play</button>
    
      var audio = new Audio("aaa.ogg");
      document.getElementById("tape").addEventListener('click', function() {
        audio.play();
      });
      document.getElementById("hovercraft").addEventListener('mouseover', function() {
        audio.play();
      });
    
  </body>
</html>

If you load this in a browser, and move the mouse pointer over the button, nothing happens. But if you click the button, the sound plays – and if you mouse over after that, it also plays. The button press is needed to demonstrate that the user actually wants something from the page, and after that it is allowed to play sounds directly.

Which is all well and good but it kinda makes the original idea moot – because the fun bit is the immediate screaming after you submit a form. No fun if you have to allow it first 😦

The moral of the story

Well, one learning is that browsers are really quite sophisticated – I never thought about the implications of having an Audio API and dealing with malicious websites. I think the approach taken is pretty neat here.

Also, I could have saved a whole lot of time by looking at that doc in the first place. This is something I thought I wasn’t bad at, but I went ahead and made a castle in the sky before checking for the obvious cloud zoning laws and stratospheric building construction permits 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s