Introducing MagicWorker.js (Apr 13, 2013)

On GitHub: lgarron/MagicWorker.js

You can almost use a .html file like a .app / .exe program… that happens to run in your browser. I wanted to fix the “almost”.

Web Workers

I like making self-contained “web apps”. I was recently porting Josef Jelinek’s ACube program to Javascript for ACube.js. It’s actually very easy to compile C++ to Javascript using Emscripten, and the resulting code runs very fast. However, a fast web app is rather annoying to use if it doesn’t respond while it’s running. Web workers are a great solution to this: Just create a worker in a background thread using

new Worker("worker-file.js");

and communicate by sending JSON messages. Here’s a full working example:

simple.html:

<script>
  var worker = new Worker("simple-worker.js");
  worker.addEventListener("message", function(e) {document.write(e.data)}, false);
  worker.postMessage("Hi!");
</script>

simple-worker.js:

this.addEventListener('message', function(e) {
  this.postMessage("Hello! You sent: " + e.data);
}, false);

The API is pretty simple, but very easy to use and extend. With enough work, this allows you to create HTML files / web apps (with significant computation) that are almost as useful as native applications.

However, there’s a problem: Because of security restrictions, Chrome won’t let you load worker-file.js dynamically if you opened simple.html from your hard drive.

So, I’ve wanted a workaround for this since a while. When I write an HTML app, I don’t always want my users to have to be online to use it. No, the application cache is not a good solution. I want someone be able to download my source code, run it, and be able to edit and test it without having to start a local server. This also makes it easier to test for me, and it’s got that “tinker factor”. I’m a fan of making my work tinkerable, because that’s how I learned to code, and I think it’s the best way to get someone hacking.

First Workaround: Inline Web Workers

It is possible to create a web worker using a different method, if you have the source code of it in a string: this involves creating a blob from the string, giving it a fake URL, and then loading the web worker from that URL. It’s roundabout, but it works on Chrome offline these days. (When I was working on Mark 2 in late 2011, it didn’t.) Here’s how our simple example would work now:

two-sources.html

<script>
  try {
    var worker = new Worker("two-sources-worker.js");
  }
  catch (e) {
    var workerSource = "this.addEventListener(\"message\", function(e) {\n  this.postMessage(\"Hello! You sent: \" + e.data);\n}, false);";
    var blob = new Blob([workerSource]);
    var url = window.URL.createObjectURL(blob);
    var worker = new Worker(url);
  }

  worker.addEventListener("message", function(e) {document.write(e.data)}, false);
  worker.postMessage("Hi!");
</script>

two-sources-worker.js:

this.addEventListener("message", function(e) {
  this.postMessage("Hello! You sent: " + e.data);
}, false);

Unfortunately, this means we have to maintain two copies of the web worker source code. It would be nice if we could load the source of two-sources-worker.js in a way that pleases Chrome, e.g. by adding an extra script tag (or even something like a dummy image tag) and loading its source, but I don’t know of a way. However, the dynamic nature of Javascript has one very useful feature: calling toString() on a function gives us a string of its source code! We can put the source code of the web worker in a function, which we can either create a worker from directly, or use with a script tag to create an inline worker. The code grows once more:

one-source.html

...
    var src = workerCode.toString();
    // Remove the outer "function(){" and "}" parts of the source:
    src = src.slice(0, src.lastIndexOf("}")).substring(src.indexOf("{") + 1);
    var blob = new Blob([src]);
...

one-source-worker.js

var workerCode = function() {
  this.addEventListener("message", function(e) {
    this.postMessage("Hello! You sent: " + e.data);
  }, false);
};

// Detect if we're in a web worker:
if (typeof importScripts === 'function') {
  workerCode();
}

There’s significantly more machinery, but it’s very DRY. Moreover, most of it is the same every time.

MagicWorker.js

That’s where MagicWorker.js comes in. After a lot of experimenting to see what actually worked, I combined all the tricky work into one file. The instructions simplify to this:

  • 1) Add MagicWorker.js to your project.
  • 2) Include MagicWorker.js in your webpage using a normal script tag, followed by each of your web worker files:

    <script src="MagicWorker.js"></script>
    <script src="change-this-to-your-worker-file-name.js"></script>
    
  • 3) Modify each web worker file by prepending the lines:

    (function(f) {if (typeof MagicWorker !== "undefined") {
        MagicWorker.register("change-this-to-your-worker-file-name.js", f);
    } else {f()}})(function() {
    

and appending the line:

    });

(Change "change-this-to-your-worker-file-name.js" to the name of the file.)

Our example in MagicWorker.js:

magical.js:

<script src="MagicWorker.js"></script>
<script src="worker-magical.js"></script>
<script>
  var worker = new Worker("worker-magical.js");
  worker.addEventListener("message", function(e) {document.write(e.data)}, false);
  worker.postMessage("Hi!");
</script>

worker-magical.js:

(function(f) {if (typeof MagicWorker !== "undefined") {
    MagicWorker.register("worker-magical.js", f);
} else {f()}})(function() {

  this.addEventListener("message", function(e) {
    this.postMessage("Hello! You sent: " + e.data);
  }, false);

});

If you remove the MagicWorker.js import, everything still runs fine when you’re not in Chrome offline. That’s the kind of transparency I was aiming for. No need to pre-compile, handle multiple versions of the source, or change a lot of code. Just a drop-in file and a straightforward way to include any web worker file in the process.

The source is on GitHub at lgarron/MagicWorker.js. It also contains all the examples from this post, in case you want to play around with them. There’s also some interesting work to be done. Perhaps someday there will be a nice way to do offline workers in Chrome, but maybe there’s already something more satisfactory right now. Or maybe there are simple tweaks to make this work for shared workers.

I’m still pretty excited, though. .html is the new .exe.

Javascript, Programming, Web No Comments

DJing Friday Night Waltz (Mar 24, 2012)

I’ve been to Friday Night Waltz for over two and a half years, and last night I had the pleasure to DJ the evening, which was awesome. I’ve become notorious for hacking so many pieces that everybody cringes at something or other I’ve done, but fortunately the music tonight was well-received – even the dozen or so new pieces. I have a lot to thank Jason Anderson for that, who is very good at constructive crticism for set lists.

[The full set list is at the end of this post. For now, it's also available for streaming here.]

Tonight was the last night of Finals Week at Stanford (and apparently also Vintage Invasion) so some of my friends already had Spring Break plans and turnout was not huge (which means more space for dancing, though!). But it was certainly over 100 people, which was pretty cool.

Some highlights:

  • Jen was nice enough to drive me over to the venue at 18:00 to test the speaker balance. Unfortunately, it was a bit confusing, and even with Nick’s help I didn’t get a reasonable balance until right before I had to cede the speakers to Cristophe, who was teaching his Waltz for the Moon (from Final Fantasy VIII) choreography lesson. But after that the balance was fine. Whew….
  • Caroline suggested Waltz for the Moon to me for a waltz a while ago, and it was interesting to see a relatively faithful choreo.
  • No one remembers Chip’s Challenge. Or Cro-Mag Rally.
  • Despite trying to be careful, I once pressed the wrong button, and iTunes advanced to an unexpected song: Never Gonna Give You Up. That’s the third time my computer’s rickrolled me by now. In the category of planned rickrolls, it turns out the drums at the beginning of Never Gonna Give You Up blend pretty well with the beginning of Kerry Sets; everyone went right on dancing!
  • Scott has a metric called the “11:30 retention rate” for measuring how many people stayed because they liked the song. Apparently I did pretty well on that, and I did get a few compliments. So hopefully I’ll get to be back some times this year. It was certainly a lot of fun.

Some Notes

I certainly didn’t know everything about what I was doing. So:

  • Ask Scott to connect the tinny church speakers, and figure out how to adjust the volume *early on* during setup.
  • DJ from the floor instead of the table (although the table looks more impressive).
  • Leave  12 seconds between songs by default instead of 8. Make sure people are finding partners before you start the song
  • Talk slower and make sure the mic volume / balance reaches the room well.
  • Make it clear to the dancers when a song between sets is an extra song.
  • Aiming for sets of decreasing length is a good idea.
  • Don’t forget to include a line dance that everyone knows, like Tokyo Polka
  • Most important: The music should be a bit more quiet than one might expect. It should be loud enough to give a clear, lively beat, but not so loud that the dancers can’t socialize without raising their voices. (Unfortunately, it’s very hard to judge this from the stage, because the reverb is rather chaotic.)

Friday Night Waltz Set List – March 23, 2012

Note: Many of the songs I played were significantly different versions/edits from the ones linked here.

Set 1

  1. [Cross-Step Waltz] Trine Main Theme (Cross-Step) — Ari Pulkkinen
  2. [Polka] I Will Dance (When I Walk Away) — Katzenjammer
  3. [Rotary Waltz] Love Will Come Through — Travis
  4. [4-Count Swing] You Belong With Me — Taylor Swift
  5. [Cross-Step Waltz] Lighthouse — The Hush Sound
  6. [Cha-Cha] 5 Years Time — Noah and the Whale
  7. [Rotary Waltz] Someone Like You (Instrumental Waltz) — Adele
  8. [Tango] Blue Tango — Leroy Anderson
  9. [Lindy Hop] Holiday — Green Day
  10. [Cross-Step Waltz] Between — Vienna Teng
  11. [Congress of Vienna] Congress of Vienna — Bangers & Mash
Set Break:
  1. [Waltz for the Moon Choreography] Waltz for the Moon (Dance Scene) — Final Fantasy VIII 8 Soundtrack
  2. [Polka] CHIP01 Remix — Lemon Demon

Set 2

  1. [Cross-Step Waltz] The Winner is (Cross-Step) — DeVotchKa
  2. [Schottische] Best Friends — Madagascar Soundtrack
  3. [Lindy Hop] Runaround Sue — Dion
  4. [Redowa / Rotary Waltz] Yun Bap — Dae Jang Geum
  5. [Hustle] Friday Night Waltz (Parody) — Duck Sauce (via gobarbra.com)
  6. [Polka] Save Me, San Francisco — Train
  7. [Rotary Waltz] I’m With You — Avril Lavigne
  8. [Salsa] Arranca — Manzanita
  9. [Bohemian National Polka] Feuerfest Polka — Josef Strauss
  10. [Fast Waltz] Married Life — Michael Giacchino
  11. [Swing] So They Say (Swing) — Dr. Horrible Cast
  12. [Cross-Step Waltz Mixer] The Clock Stopped — KGB
Set Break:
  1. [Peanut Butter Jelly Time] Peanut Butter Jelly Time — The Buckwheat Boys

Set 3

  1. [Rotary Waltz] Trine 2 Main Theme — Ari Pulkkinen
  2. [6-Count Swing] L-O-V-E — Nat King Cole
  3. [Schottische] Stuck Like Glue — Sugarland
  4. [Rotary / Viennese Waltz] Potter Waltz — Harry Potter And The Goblet Of Fire
  5. [Cross-Step Waltz] Sadame — Satou Naoki
  6. [West Coast Swing] Rolling in the Deep — Adele
  7. [Rotary Waltz] Caribbean Blue — Enya
  8. [Sweet Lindy] Beyond the Sea — Bobby Darin
  9. [Congress of Vienna] Congress of Vienna (Accelerating) — Bangers & Mash
  10. [Swing / Cha-Cha] 1234 — Feist
  11. [Fast Polka] He’s a Pirate (Polka) — DJ Scotty
Set Break:
  1. [Birthday Waltz] Piano Man (Classical) — Jeff Ginger

Set 4

  1. [Cross-Step Waltz] La Dispute — Yann Tiersen
  2. ( [Special Kerry Sets] Special Kerry Sets – Rick Astley )
  3. [Kerry Polka Sets] Cry of The Celts (Irish Kerry Set) — Ronan Hardiman
  4. [Club 2-Step] Science Songs — Jonny Berliner
  5. [Rotary Waltz] The Only Exception — Paramore
  6. [Tango] Triangle Tango — Cirque Du Soleil
  7. [Polka] Kung Fu Dancing — DJ Gauffie
  8. [Fast Waltz / Redowa] Odenall Pi — E.S. Posthumus
  9. [One-Step] Cro-Rag Rally China Theme — Cro-Mag Rally
  10. [Lindy Hop] Crazy Little Thing Called Love — Queen
  11. [Redowa] Wavin’ Flag (Instrumental Redowa) — K’naan
  12. [Accelerating Waltz] Accelerating Waltz (Scott and Fran’s Paso Doble) – Strictly Ballroom Soundtrack
  13. [Cross-Step Waltz] Down to Earth — Peter Gabriel
Uncategorized No Comments

Hello Word…Press (Jul 20, 2009)

My site has been out-of-date for too long. I will soon be replacing the home page with this blog, and try to organize the pages with some custom menu system.

For now, this is a test post.

2x2x2 with RSS icon stickers, rendered in POV-Ray

2x2x2 with RSS icon stickers, rendered in POV-Ray

Meta 2 Comments

Switching to Dvorak (Mar 12, 2009)

Dvorak

Dvorak

Why? I might as well learn to touchtype, and Dvorak is a sort of unofficial standard among cubers.

Here’s what got me to switch:

  • A wiki link in an
    arbitrary post
    led me to
    Macky’s familiar site.
  • I decided to peruse his Dvorak page.
  • He linked to the Dvorak Zine. I was still
    unsure, so I decided to read it. If it didn’t convince me, I would just forget about switching.
  • It was enough. :-)
  • March 11, 2009, 20:35:33PM, #rubik on irc.ircstorm.net:

    “lgarron: shellie: This is the first sentence I’ve written in Dvorak. :-)”

    Forgot to ;tell, but who cares? Further lines from my first Dvorak conversation (selected, related lines from others in parentheses):

     20:36:48 <%lgarron> This is going to be messy for a while. :-/
    (20:36:29 <+Ethan_Rosen> lgarron, keep going)
    (20:36:34 <+Ethan_Rosen> never look back)
     20:37:24 <%lgarron> Ethan_Rosen: Tryingv
    (20:37:32 <+Dene> lgarron: YAY!)
    (20:37:38 <+Dene> JOIN US!)
    (20:37:49 <+Dene> Oh man all us dvorakers are such a good influence)
     20:38:55 <%lgarron> Hmm, keyboard shortcuts are going to be annoying.
     20:40:33 <%lgarron> The quick brown fox jumps over the lazy dog.
     20:41:04 <%lgarron> "The" is fun. :-)
    (20:41:30 < qq> it's like you make a mistake every time you type a word)
     20:42:26 <%lgarron> qq: I'm doing that right now. :-P

I haven’t looked back. I use “Dvorak – Qwerty ⌘”, which preserves he arrangement of shortcut keys like copy/paste.
I used Keyboard Viewer for a while, but since I’d memoed the Dvorak layout, I eventually dropped it
(I began this page as my first blind touch-typing practice). For encouragement, I also got two friends to switch.

I almost got sick of typing too slow, but to prevent myself from ever reverting (even temporarily), I decided to switch my keys around physically (see picture).
I can now cheat by looking at the keyboard, but at least I can get used to it before I gain actual speed.
I’m also trying Caps Lock for Delete,
especially because of frequent learning errors.

Most credit definitely goes to the Dvorak Zine for simple, entertaining inspiration.

Trivia:

Uncategorized 1 Comment

My Songs (Dec 24, 2008)

I finally uploaded most of my songs into a songs database.

Music, Old Updates No Comments

Stanford University (Apr 29, 2008)

I will be attending Stanford University in the fall of 2008.

Stanford Seal

Thanks to UC Davis, UCLA, and UC Berkeley for also admitting me.

Old Updates, School No Comments

I’m Still Alive (Mar 28, 2008)

Small note: While the content may still be useful, this site is woefully out of date (hey, I can average under my listed OH PB!). I’m hoping to improve it this summer. I’ve still been cubing, though I do most of it sneakretly by posting videos, contributing to the speedsolving.com forum, etc.

Cubing, Meta, Old Updates No Comments

Frank Morris Facts (Mar 28, 2008)

It seems the time has come for Frank Morris Facts.

Cubing, Old Updates No Comments

You know you’ve been cubing too long when… (Nov 11, 2007)

You know you’ve been cubing too long when…

Cubing, Old Updates No Comments

SUMaC (Jul 15, 2007)

I’m going to SUMaC.

Not sure how that will influence this website…

Old Updates No Comments