Whole Home Automation – what’s new?

Time sure is flying.  Sometime in spring I made tentative plans to see “The Expendables” with a friend in August.  At the time I thought that the date – August 13th – was soooo far away.

Ya, right.

I’m not here to bemoan the rapid passing of Time though; I’ll leave that for another entry – which may or may not ever get written btw.  No, I’m here to continue the chronicle that is my Whole Home Automation journey.

Now, I can’t say that the scope of the project has changed.  It’s still limited to audio and surveillance.  On the surveillance side there’s not much to report; occupant detection is working, and although I haven’t hacked any USB Bluetooth dongles I can also say that the system is working acceptably as-is so I’m in no rush to change things.

On the audio front it’s been a case of small updates and bugfixes here and there.  One of the bigger useability updates has been to allow the download of a .zip file of select tracks.  This makes it easy to download a selection of tracks to a local device, or download an entire album to Shelly’s phone.  It’s not something that I’ll use often, but it’s nice to have.

Something that should be more useful for me, however, is a project I just completed that’s physically removed from the system at home – but interacts with it nonetheless.  I’m talking about playback of streaming zones, and in particular, playback of streaming zones using _my_ Windows Mobile smartphone.

Here’s the scenario.  I’ve got some tracks queued on a streaming zone.  I hop in the car, connect to home, and start playing that zone through my phone (and obviously through the car stereo).  Then I hit a joint that’s bangin’ – or lame – and I want to repeat that joint or skip it altogether.

Traditionally this has been possible, but it meant having a browser open on the phone and connected to the zone page for the streaming zone in question.  You press a transport control on the webpage, and some seconds later (up to 15 seconds in some cases) the streaming buffer gets around to reflecting the changes.

“Wouldn’t it better”, I wondered, “if you could use the player’s transport controls to control the zone directly?!?”

Yes, it would.  And so now it is.

I toyed with the idea of writing an app from scratch.  And while this is something I may still do, the opening lines of this entry are quite clear in this respect: Time is at a premium.  Sometimes you have to settle with something that works rather than something that’s perfect.  It’s not a mantra that I usually adopt, but in some cases – as with the Bluetooth dongle – it’s acceptable.

So as it turns out, GSPlayer is open-source.  It’s a player I’ve used in the past, and I think that I passed it over in favour of PocketMusic because the latter is purtier and has bigger buttons.  But if the buttons aren’t useful, then who cares?  That, and PocketMusic has some stability issues – to the tune of often requiring a soft-reset of the entire phone.

Anyhow, I modified GSPlayer and captured transport control events so that it will send RPC commands to the backend server.  So if I press the “next track” button in GSPlayer, it will tell the backend to move to the next track.  It will also disconnect/reconnect the stream to make sure the streaming buffer is cleared.

And of course, it only does all of this if a stream is active *and* that stream appears to be connected to my server.

So ya, that’s that.  I did a quick test on my phone and it seems to work.  I’m off to run a few errands shortly and I’ll do the trial-by-fire at that point.

What’s this? No updates?

Something (somebody…?) has been keeping me busy. Sorry!

A couple of interesting developments, all of a techie nature.

One… is that I got hit by a drive-by virus infection at work the other day. Imagine that – me, getting a computer virus! I became aware of its presense almost immediately, as I tend to do a lot of work online and I was suddenly unable to do anything. Existing connections – like the VPN to my home network – continued to work fine, but I couldn’t visit new sites.

The culprit was some trojan or whatever that was opening untold numbers of TCP connections in an attempt to send email. And while I suppose that this is a good, self-serving way to propagate, it’s not terribly inconspicuous. However, it took an entire day to get the thing removed; the eventual victor was a tool named ComboFix.

But that’s neither here nor there.  The point of interest is that Firefox has been Behaving Badly(tm) since then, using copious amounts of CPU every time it changes pages.  I suspect it’s been damaged in some way – or maybe it’s trying to phone home somewhere – but suffice it to say that it’s now maddeningly frustrating to use.  I can’t see any phone-home connections, but that hasn’t stopped 2.x, 3.0 and 3.5 from all being naughty in this regard.

chrome-205_noshadowSo I’ve been using Google Chrome for my browsing needs.  Again, that’s neither here nor there.  The real message… which is quite selfish really… is that I’ve been using Chrome with the Whole Home Audio web interface and it’s quite a slick experience.  Which is to say – in a very, very, very long-winded way – that I’ve come a long way from Firefox-dependence with respect to said interface.

I still don’t have workable drag-drop support, and its absence is notable during some playlist maintenance operations.  But with this one exception it’s all slick as snot.

And while I’m on the topic of the Whole Home Audio interface… I made a small discovery the other day with IIS’ setup that was potentially causing some consternation.  The interface will show you what’s playing on a particular zone, and the page which shows this information is very dynamic; a draggable, self-updating time bar; a self-updating, dynamic tracklist; a dynamic track position time counter, and some other goodies.

Anyhoo, this all is made possible with XHR objects, all of which make their requests back to IIS.  IIS normally logs every HTTP request, but when you’re making one call every second it gets a little silly.  (On a side note, I may look into using a keepalive connection to do these updates; I don’t know if anybody else does this, but it’s an idea that could reduce the overhead of handling all of these sequential async requests)  Sooooo… the XHR objects would make their requests to a virtual directory which was told to not log any requests.  Great.

Except that, for whatever reason, I had configured this virtual directory with its own “application”.  I have no idea why I would have done this if the only thing I was trying to accomplish was to keep logging in check.  So that config has been removed, and since then the XHR requests have worked as expected.

What else?  Oh yes.

lastfm

The collection is constantly growing, especially since I made a ton of room on my disk by moving some movies to my netbook.  So as any music listener knows, it’s nice to discover new music.  Having a kick-@ss way of navigating my existing collection is great, but what about discovering similar music or artists?

Last.fm is great for this kind of thing.  And even greater is the API, which allows my music application to query their database.  Today I’ve got a button that can retrieve similar artists and even populate a playlist with their albums.  Using that I’ve added a considerable number of new artists to the stable.  The next step, I think, is to make use of their “scrobbling” feature – allowing my application to update a last.fm user profile with tracks played, so that last.fm can make better recommendations.

This comes dangerously close to the “user” feature that the wifey nixed, but I think I can work around it; I’ll make a playlist “property” which is associated with a last.fm profile, and if you play from a linked playlist then my app will scrobble to the associated last.fm user profile.

So I guess those are the biggies, for now.  Some other small stuff, nothing blogworthy though.  So that’s it fer now.

Useful, or crammed?

New article on Piper’s Pages:

Something was bothering me with my fancy-shmancy AJAX/DHTML popups in the Home Audio interface.

It manifested itself mostly when adjusting track BPMs for a new album.  Basically, one has the ability to browse on an album’s tracks, then get the track popup for any particular track and – using forward/back navigation in the popup – move around the browse entries via the track popup.

This is cool in practice.  You can see more detailed deets for browse entries (as well as options like track suggestions) and quickly compare between tracks by clicking prev/next.  No need to display the popup, close it, then display the popup for another track in the results.  Same goes for albums, of course.

So when BPM’ing an album, I had two options: 1) use the quick-edit links so that I could get the edit popup straight from the browse results, or (2) display track details and use the edit link from the popup which then loaded the edit popup.

It was kinda nice using the second option, because sometimes you don’t need to edit the BPM and you can just next-next-next through the entire list – no need to scroll the list, figure out which track you’re working on, then click to get the details popup or the edit popup.

BUT… sometimes you’re not sure if the BPM that’s in the DBMS is correct, you want to use the edit popup so that you can tap out the beats and see if it’s a match.  If it’s a match, you close the edit popup – but the entry doesn’t highlight since you didn’t change anything, so you lose visual reference as to where you are in the list.

You could use the details popup, then go to the edit popup, but same problem – once you closed the edit popup you were back to a list of tracks with no visual reference as to what you last looked at.

And this underlined a more general problem – with all these dynamic popups, what happens if you want to go back one popup?  What happens if you want to display the details popup, then the edit popup, but then go back to the details popup so you can “next” to the next entry?

One way to do this is to keep a history in the backend of popups you’ve looked at.  Problem is – and this has cropped up before – the application is purposely free-flowing, and you can have multiple windows/tabs open all using the same session (sharing the same search history, context, etc.)  If you’ve got popups going in two windows, the history will be intermingled and thus useless.

So I took a different approach.  Instead of a popup yielding more popups, I decided that additional popups could be dynamically loaded into the first popup.  So for example, you get track details in a popup, then click to edit BPMs and the edit dialog is loaded into the current popup rather than appearing as a new popup.  Submit your changes and the main popup remains.

Works a treat.

The only problem is that the popup is meant to be somewhat small relative to the main interface, and when we start dynamically inserting some of these other popups – ie, the zone selector – the popup gets to be a little large and looks a little “crammed” – hence the title of this article.  But I think that’s a small price to pay for the increased usefulness (again, linking back to the title of this article), and I can probably make it more palatable with careful application of visual styling elements (via CSS).

Yup, so that’s that yo.

I also added the ability to start a new search using a popup – not just a saved search as before, but actually specifying search conditions.  Not all of the fields are displayed in the popup as they are when you actually navigate over to the search page, but in concert with dynamic search fields it offers a handy way of firing off a quick search.

Werd up.

Eat my shorts! AJAX drag-and-drop baby!

New article on Piper’s Pages:

In my neverending quest to learn (everything?) AJAX, I decided to dip my fingertips into the pond that is drag-and-drop.

Probably the most famous of AJAX techniques, it allows you to grab something on a page and move it somewhere else – either because you like to assert your creativity, or because you want to Do Something(tm) (like add an item to shopping cart).

Well ladies and gents, we’ve taken our implementation of drag-and-drop to a Whole New Level(tm).

You may recall that we’ve had AJAX popups for ages now (ages <= 1 year) and you could grab those popups and move ’em around, just cause they might be covering stuff you want to see. Cool, but… that didn’t DO anything really.

So here’s what I envisioned.

I envisioned an interface with multiple panes – one for browsing, one may contain a zone, and another may contain a list. It would be wicked and wild if you could drag an album on your list or onto the zone to queue that album.

This obviously requires more kung-fu than just moving popups around the screen.

So…. if I’m not mistaken I’ve been using Scriptaculous for the popup dragging, and after trying to bake my own more-advanced solution I realized that Scriptaculous could do what I wanted (and it was even using the same terminology I was using – “draggables” and “droppables”).

So the first crack at this yielded the ability to drag stuff from the browse view onto the link that indicates your working list. That causes the album/song to be added (or removed) from said list, which also happens to flick the checkmark for that item (this happens as a result of existing code).

Okay, so that’s cool I guess, but said checkmark could simply be clicked to achieve the same results. Nothing really new here folks, so move along!

My pleasure. My next effort was to enable drag-and-drop table reordering. Currently, in list view, you’ve got teeny weeny icons that you can use to move a row up or down, one at a time. Sure, you can select a bunch of rows and move them all up or down at once, but again they’ll move one at a time.

With these handy dandy scrolling tables, it sure would be nice to grab a row by the scruff of its neck and manhandle it into a new position, right?

Yes, it would. And while Scriptaculous provides an easy breezy way to get this done, fact is that my implementation of dynamic tables is slightly incompatible with Scriptaculous. If I had to actually take time to explain why, I would say that it has to do with my padding process – which means that in any given table, some of the rows have actual data and some do not. I use different DOM ID prefixes to track this, but even if I used a seperate array to do the same thing I’m pretty sure we’d run into context issues: does it make sense to reorder a row that hasn’t been filled in yet?

Sure, the way I’m registering draggable items means those rows wouldn’t be considered draggable by Scriptaculous until they were force-fed useable data by backend, but… why are you trying to convince me to use Scriptaculous for this??? Look, the fact is I wanted to keep my DOM ID convention, and I don’t like the way Scriptaculous reports the new ordering to the backend. When you’ve got a table that can contain, oh, 30000 rows the last thing you want to do is iterate through a serialized list of row IDs and tell a DBMS to reorder based on that list. Ugh.

So I baked my own solution, which was based on the work I did (and partially abandoned) for effort 1.

And… it works!

At least in Firefox. It looks like it wants to work in Chrome and Opera, but I’ve got stoopid text selection issues to overcome still. But at least the concept works, and admittedly it’s quite handy.

So ya – drag-and-drop/table-reordering with backend updates. Funky fresh.

What the HECK is this Whole Home Audio thing?

Glad you asked.

For the past x years I’ve been toiling away on a combination of software and hardware at home that allows me and the wifey to play selections from my vast collection of music to various rooms around the house (and beyond).

If you visit Piper’s Pages, you’ll find a post (login as guest) that begins the record of how this endeavour began.  Yes, it began 4 years ago.

And it’s still going strong.

Browse interface

Browse interface

The project, in today’s form, uses a web interface to browse/search the collection.  The search options are quite powerful (confusingly so?) and can be saved for frequent use, you can create playlists of songs and albums, you can have the system suggest similar music.  There are statistics – including scoring and ranking – and metadata pulled from external sources.  We’ve even got BPM info.

music_zoneThere are a slew of maintenance scripts that power this thing, and no less than three disparate “servers” that go into making it all happen. Currently we’ve got two physical zone – family room and basement – and another four virtual zones for streaming.

So that’s the short intro.  For more you’ll have to visit Piper’s Pages and check out the DP’s Corner database.