Offline Sound: No Flash, No File

I just did some tinkering with offline sound and it turns out you can embed an audio clip in an HTML file, and play it without using Flash. I could have demo’d this in a raw HTML file, but it was just as easy to stick it in a Tiddlywiki file. So I made a TiddlyWiki called JinglyWiki. Click on the button and it will play a sound. If you grab the file (safest using a tool like Curl or wget, as the browser will sometimes Save As something different), you can run it offline and it will still play the sound.

JinglyWiki started after an office conversation yesterday. We had a flaky wifi connection and were pleased to be able to play a beat on http://instantrimshot.com to signify a re-connection. This got us thinking about playing beats in Tiddlywiki. Jeremy mentioned the possibility of data: URIs, and I thought back to Reinier’s great effort in playing sound without Flash. I wondered if it would work with data: URIs and to my pleasant surprise, it did. At least in FF3, which is all I’ve tested so far. I also forgot how tiny the code is to play audio without Flash – you just add an element to the page.

The point of JinglyWiki is you can stick a 300K file on your local file system or a USB stick and play gratuitous sounds without being online. Your iPod cost you several hundred bucks, whereas JinglyWiki is entirely free. Free as in you can spend your money on beer instead. JinglyWiki may well be the best portable music player you never paid a penny for. Groovy.

It would be so much more useful with some code to dynamically generate WAVs, but that’s a project for another day.

As for the name, it’s a play on the much more important project Phil Hawksworth has initiated to build a JQuery based Tiddlywiki framework: JigglyWiki. I think this nascent effort is going to produce some wonderful plugins for the JQuery community and be an important enough project to derive novelty joke names out of :), so I’m setting the trend here.

The data itself is 15KB for about a second of voice content.

Here’s the plugin code. Trivial or wot?!!!

javascript

  1. config.macros.jingle = {}
  2. config.macros.jingle.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
  3.  
  4.   button = document.createElement("button");
  5.   button.style.fontSize = "4em";
  6.   button.innerHTML = "Play Me! Play Me!"
  7.   button.onclick = function(ev) {
  8.     startWav(SOUND_URL);
  9.   }
  10.   place.appendChild(button);
  11.  
  12.   // cancel dbl-click so we can follow our natural urge to click on the button incessantly
  13.   story.getTiddler(tiddler.title).ondblclick = function() {}
  14.  
  15. }
  16.  
  17. // non-flash sound handling adapted from http://www.zwitserloot.com/files/soundkit/soundcheck.html
  18.  
  19. var embedEl;
  20.  
  21. function startWav(uri) {
  22.         stopWav();
  23.         embedEl = document.createElement("embed");
  24.         embedEl.setAttribute("src", uri);
  25.         embedEl.setAttribute("hidden", true);
  26.         embedEl.setAttribute("autostart", true);
  27.         document.body.appendChild(embedEl);
  28. }
  29.  
  30. function stopWav() {
  31.   if (embedEl) document.body.removeChild(embedEl);
  32.   embedEl = null;
  33. }
  34.  
  35. // To make a new sound, cut and paste into hixie's handy Data URI Kitchen
  36. // http://software.hixie.ch/utilities/cgi/data/data.pl
  37.  
  38. var SOUND_URL="data:audio/x-wav,RIFF%17%1C%00%00WAVEfmt%20%10%00%00%00%01%00%01%00%40%1F%00%00%40 ........................" // snipped

Wanted: Massive Local Storage

Local storage – beyond 2KB cookies – is now a step closer with the latest Firefox effort. You get a local storage API like this:

javascript

  1. sessionStorage.setItem(..)
  2. globalStorage.namedItem(domain).setItem(..)

The fantastic thing is Brad Neuberg’s Dojo work means we can code independently of the local storage mechanism. Since IE also has local storage, as well as Flash, most bases are covered, or soon will be: Anyone with EITHER IE or Firefox or Flash will have local storage. (Incidentally, we had a discussion in the comments on Ajaxian about the possibility of S3 and other remote bindings as well, which I’m guessing Brad will implement at some point.)

But what I’d like to know, what I’d really really like to know, are the limits for these various techniques (I think Flash is 10MB per domain, right?)

As I’ve said before, there are valuable applications of massive storage – hundreds of gigs, e.g. media players that store data server-side, but cache content locally to cut down on the need for streaming from the server. Hopefully, these storage technologies won’t try to second-guess the imagination of web developers by setting a dumb arbitrary limit that “no-one would ever need more than”, like 100MB or 1GB or whatever.

If there’s room on my hard drive, and I trust the domain, let me store as much as I please.

Take the Ajax Challenge: What Can’t Ajax Do?

Working (offline) on Richer Plugin, I’ve expanded the list of reasons you’d want to use a Richer Plugin, i.e. Flash, Java Applets, Standalone clients, Firefox extensions etc.

Here’s the list of things Ajax can’t do on it’s own – what else is there?

  • Browser morphing Adding buttons, toolbars, bookmarks, icons; changing browser behaviour.
  • Local file access Reading and writing files on the user’s hard drive.
  • Sound Playing music and sound effects.
  • Rich graphics Providing rich graphics, changing dynamically. (This is gradually changing with the introduction of SVG in some browsers, but it’s no match for desktop graphics.)
  • Keyboard shortcuts Providing a full range of keyboard shortcuts while avoiding conflicts with the browser’s own keyboard shortcuts.
  • Hardware access Input from devices such as microphones, webcams, and gamepads; output to devices like printers and portable gadgets.
  • Extended communication Communication from the client machine to locations beyond just the base server, and in protcols other than plain old HTTP.
  • Operating system interaction Catching events such as shutdown initiation; changing preferences; popping up alerts; reading hardware information.

Take the Ajax Challenge: What Can’t Ajax Do?

Working (offline) on Richer Plugin, I’ve expanded the list of reasons you’d want to use a Richer Plugin, i.e. Flash, Java Applets, Standalone clients, Firefox extensions etc.

Here’s the list of things Ajax can’t do on it’s own – what else is there?

  • Browser morphing Adding buttons, toolbars, bookmarks, icons; changing browser behaviour.
  • Local file access Reading and writing files on the user’s hard drive.
  • Sound Playing music and sound effects.
  • Rich graphics Providing rich graphics, changing dynamically. (This is gradually changing with the introduction of SVG in some browsers, but it’s no match for desktop graphics.)
  • Keyboard shortcuts Providing a full range of keyboard shortcuts while avoiding conflicts with the browser’s own keyboard shortcuts.
  • Hardware access Input from devices such as microphones, webcams, and gamepads; output to devices like printers and portable gadgets.
  • Extended communication Communication from the client machine to locations beyond just the base server, and in protcols other than plain old HTTP.
  • Operating system interaction Catching events such as shutdown initiation; changing preferences; popping up alerts; reading hardware information.