Sunday, March 30, 2014

iTunes Home Media Sharing

As a human, I own several sets of DVDs for my favorite TV shows, and I'm always looking for how I can watch them without having to deal with physical matter. I will never buy another DVD player, and the one I have was only passed down to me like a family heirloom—but the kind that will be pitched into the dumpster once it breaks (or thoughtfully recycled, yeah yeah, whatever). I long ago digitized my DVD collection, but I wanted to move past the era of having to hook my laptop up to a TV and control it with a wireless keyboard.

Having an iPad, I tried out iTunes home media sharing, which was awesome at first. Simply add all your movies to iTunes, which takes a couple of clicks, and maybe iTunes will try to copy them all behind the scenes to a more suitable directory, but myeh. Then enable home sharing in there and on your iPad. Next go find that Videos app you've never used, and hopefully it will now sport a new 'Shared' tab at the top. And, after a few reboots, retries, and excruciating password changes, it does!

Then the troubles begin in earnest. Click on your library and wait the minute or two while your thousand-odd items load:
<ipanema>Do do doo do dooo do do doo,
I'm waiting to load my home library,
And as it freezes, each time it freezes,
Go "Aggghhhghghghgh ..."</
ipanema>
Then scroll down the infinite, unsearchable icon wall of death to find the series you want to watch. Ordering is strictly alphabetical, so if all you have in your library is one episode of Friends and, say, a million episodes of Doctor Who, then I hope you like scrolling. Bear in mind that the tiny movie title snippets are really hard to read during this step.
Search? No. ... List view? No. ...
At least a link to the start of each letter? No.
So you finally get around the video you want to watch—but move fast! The Videos app is slowly replacing every gray thumbnail with a frame from the start of the movies. Seems like this should be helpful, but the frames are often corrupted, and the movie title disappears once the frame is loaded—because the identity of every video should be obvious after that, right? Not so much:
You can tell all 200+ Friends episodes apart judging
from just a single skewed frame of each, right?
At least once you start watching the video everything goes mostly okay. ... Unless the connection goes stale, or your computer goes to sleep, or a butterfly lands on your router, or something. Since then the stream will freeze, and you'll try reopening the video a bunch of times, only to find that the only remedy is to force-restart the Videos app and start the whole process over from the loading screen.

And one more thing. When you're watching some show sequentially, it would be great if Videos would show you your recent watch history, so you could always pick up right where you left off, huh? … Yeah, that'd be awesome. Tell Apple that for me if you ever get the chance.

Friday, March 21, 2014

CSS Solar System

So I recently undertook a little project to build a solar system model out of CSS. "Is such a thing even advisable?" is the obvious question. Turns out the internet has already been there in droves:


  • Wow, this is cool.
  • Holy cats, this is neat.


But I had a different idea of making a solar system model that peaks in on the side of a page in the header section, kind of like a company logo. Since the internet had not come up with that exact idea, I went ahead. The one constraint I wanted was to make the design responsive so that the solar system would resize along with the window.

Turns out the answer is just lots and lots of border-radius and position: absolute—same as everything in life:


http://unicontroller.appspot.com/solarsystem
http://jsfiddle.net/pbaumstarck/hfbq8/

So, victory? Kind of. Because it took about 250 lines of CSS (with no empties) to effect this. The clincher was getting the planets' and orbit lines' positions right depended on a fair amount of math. A set of equations had to be solved for each planet individually, and the answers hard-coded. I wanted to reduce the amount of CSS, while also making the calculations depend on variables. Then I could easily tweak everything without having to redo 8n calculations every time.

I decided to try out LESS. I dived in and was quickly reducing the line count with just nested rules. The real space-saving came when I replaced the eight individual sets of rules for the planets (sorry, Pluto) with a single loop that solved the equations using variables.

In all the LESS solution took up only 100 lines of code—60% off the CSS. But this bargain takes on a Faustian character when you consider the Less code it took to effect. Stuff like:


.-(@i: 1) when (@i <= length(@planet_names)) {
  @name: e(extract(@planet_names, @i));
  @color: extract(@planet_colors, @i);
  @size: extract(@planet_sizes, @i);
  @orbit-radius: @start-orbit + (@i - 1) * @orbit-increment;
  @orbit-height: @start-orbit-height * @orbit-radius / @start-orbit;
  .planet.@{name} {
    background: fade(@color, @fade-value);
    border-radius: @size;
    height: @size;
    left: @orbit-radius;
    margin-left: -@size / 2;
    position: absolute;
    top: (68px - @size) / 2;
    width: @size;
  }
  .@{name}.orbit {
    height: @orbit-height;
    left: -@orbit-radius;
    position: absolute;
    top: (@height - @orbit-height) / 2;
    width: @orbit-radius * 2;
  }
  .-((@i + 1));
} .-;


Yes, that's really how for loops work. Actually it's not a loop since the Less people did not want to allow mutable l-values, so they made all named entities be constants in their scopes. Thus to get iterative behavior you have to write a recursive mixin that calls itself with the iteration number, and that uses branch execution to trigger the exit condition. And then apparently .- struck them as a really good name for an anonymous mixin, so voilĂ . … No, that doesn't look hacked at all.

Next time I might try out Sass, which combines the hierarchical rules of Less with Jinja-style templating to get variables and loops. Now that makes sense. Templating engines were designed to streamline writing redundant languages using proven programming idioms. Sass uses that to mitigate the tedious bits of CSS, while promoting things like hierarchical rules to the core. ++.

Monday, March 10, 2014

RegexWorks

AngularJS is civilization. And one demo application I thought to build for it was a regular expression workshop. We all know the problem with regexes: they're powerful but messy. It comes from the fact that they're one complexity level below context-free grammars (i.e., programming languages), so theoretically they shouldn't be able to get so complex that you can hurt yourself, and so everyone's at liberty to hack away.

I made RegexWorks as a test framework for regexes where you can easily do in-depth, at-a-glance debugging. You have space to enter text, which gets split into different lines (or however else you want), and all the regexes are applied to them in parallel. And you can add an arbitrary number of regexes that do matching or replacing. An output section next to the input shows you the result of running the regexes on each line.

The real magic is in the debug matrix at the bottom, that shows you the effect of each regex on each line, so you can track the effects of multiple cascaded substitutions and matchings. And it all uses AngularJS to get instant feedback without any messy event listening or DOM manipulation.




Because it uses AngularJS, however, it updates everything once you change anything. So it'd probably be a bad idea to paste, like, the last few days' worth of logs from your Apache server into the input and start futzing with the regexes. It won't run fast. Best to limit yourself to about a hundred sample lines that you want to hack with.

I set up some demo links that pre-fill everything to get you started. The first just has some 'foo'-'bar' text, and the second runs regexes over Hamlet's "To be or not to be" soliloquy.

Sunday, March 9, 2014

Nyan Bars

Progress bars made out of ASCII characters! Easy to learn the syntax and create your own custom progress bar. Written as a jQuery plugin.




The code parses the text input manually, character by character (link). Normally you're not supposed to write a parser by hand. —Seriously, kids, don't try this at home. But, if the grammar is simple enough, then you might be able to manage it. I recommend the approach I used here: keep track of the parser's state using an enum, move character by character, and use an ifelse to handle all state–input combinations and to organize the state transitions.

Update 2014.4.12

I've been thinking for a while about doing another wave of work on this project. I think it should be possible to easily do things like modulate the color and weight of each piece of text, so that you could make an actual rainbow-colored Nyan Cat. Here's a syntax idea:

{{r#f00|g#0f0|b#00f}}

Meaning 'an animated character showing first a red "r", next a green "g", and finally a blue "b".' The hash symbol is natural for representing colors, and you could escape it if you wanted an actual hash sign.

But you could also generalize that into hash tags to specify common CSS styles or explicit key–value pairs:

{{r#bold|g#italics|b#font-weight:small-caps}}

Then I should rework the site to have saving and sharing features, so that people could work on awesome, multi-colored text animations and show them off (I put a similar, very simple thing on http://jsondiff.itsagoldenage.com).

The only big problem with this is that the Nyan Bars syntax is already hard to read and orchestrate when there's lots of stuff going on, and right now it's just writing down the characters you see. Add CSS and markup syntax to everything and it becomes impossible to gist what a syntax pattern does by inspection alone.

I would definitely need a more advanced designer than just a textarea. Something that would allow you to expand and collapse the multi-character segments, so that you can inspect them in a WYSIWYG fashion, then click in to modify them. Might be an interesting AngularJS project, since it has a more detailed control aspect than other things I've done. Suggestions welcome, here or @PaulBaumstarck.