Artists – What many names can do

(this title brought to courtesy of Beres Hammond, who’s “What One Dance Can Do” bubbled to the front when coming up with names for this post)

I’ve had a recurring problem ladies and gentlemen, in that artist names have been driving me crazy.

Here’s the situation.  An artist is named “artist”, and she publishes albums in this name.  Then the artist decides to change her name to “artois”, and publishes further names under this new name.  And so on and so forth.

The problem, then, is trying to determine which albums belong to a particular artist, regardless of pseudonym.  The problem can even crop up when, say, a gospel artist works with a choir and publishes an album with the choir’s name.  You want to give credit where credit is due, so the album artist field dutifully contains both the primary artist and the contributing choir.  But what happens when the artist publishes a solo album?

I’ve turned this one around in my mind for some time.  It becomes a problem when listing artists, in which case a single artist can be listed 2, 3, even 4 times.  Or when trying to browse an artist’s discography.

Part 1 of the solution was to introduce an “artist alias” field into the backend database, which is intended to contain the most recent pseudonym for that artist.  This isn’t the same as “TLC” vs. “Left Eye”; rather, it’s intended for people like “Puff Daddy”, aka “P. Diddy” aka “Puff Daddy” aka “P. Diddy and the Bad Boy Family”, etc.

OK, so we then had the ability to search on alias.  And the alias field is a calculated field, in that it will return the value of the artist field if the alias is empty.  Groovy.

However there was still the problem of listing and browsing.  You’d think that the artist alias would be enough, but you’d be wrong.  Take Bobby Valentino, aka Bobby V., aka Bobby Wilson.  I don’t believe he’s published any names under Bobby Wilson, yet that’s his current psuedonym (in this case, his real name).

Now, it would be fine – I think – to browse Bobby’s discography using nothing other than the Bobby Wilson alias.  However, we get into major problems when we want to see all songs where Bobby Wilson is the primary artist.  Those songs may exist on albums that are not Bobby Wilson albums at all – ie, soundtracks – or he may have still been going by Bobby Valentino at the time.

Basically, you’d need to search by all known aliases in those cases.

So after much consternation, I finally put together the code to make this happen.  Works a treat.  You have to take some care when putting together a manual search, as you have to understand exactly what it is you’re searching.  This is a fairly standard condition though, I think.  Otherwise, use the plethora of buttons and links which will do the heavy lifting for you.

While I was at it, I decided to tackle another dilemma: handling artist names that contain quotes.

Quotes are Bad News(tm) in the programming world.  You have to escape them, which isn’t bad.  But still, they can cause major problems.  Take the following example:

Give me all albums by Damian "Junion Gong" Marley, or by Lisa "Left Eye" Lopes.

Those are both valid artist pseudonyms.  And, if you construct the search with two artist fields OR’d together, you’re fine.

But in some cases – and this is true for our discography browsing code – you use a search specified like this:

artist is "Lisa "Left Eye" Lopes" or "Damian "Junior Gong" Marley"

There may be any number of reasons why you have to use this format versus the one above.  In my case it’s due to restrictions in the code and how parms are passed around.

Regardless, what you’ve got there are nested quotes.  And previously, my code would spit it out and give some unknown result.

No longer.  There are some basic assumptions that you can make:

  • a quote followed by a non-whitespace character is an opening quote
  • a quote followed by a whitespace character (or end-of-line) is a closing quote

There may be more, and more complexity, but you get the picture.  And indeed, these may be rules that you enforce rather than simply assume to be true.  With those rules in place, the code can now track nesting levels.  Escaping is another simple step away.

DP’s 2010 Gift-List

My my my… we haven’t been this early since 2006!

The only reason I’m posting so early is because Shelly recently (ie, yesterdy) asked me what I want for Christmas.  And although she bemoaned the traditionally high-roller nature of the items on this list, I calmly reminder her that all of these lists have featured items as cheap as a pair of socks.  And some even cheaper (again, 2006… not so good of a year?)

I also can’t believe that there was no list for 2009???  Very odd, that one.  Perhaps the arrival of a son was gift enough 🙂

Anyhow, time to reflect on things that have dropped off the list because they’ve been acquired by yours truly:

  • Canon EOS Rebel DSLR.  Yup, took the plunge and picked this up after it was on sale for $210 off.  Shelly thought it would have been a good idea to wait for Boxing Day sales, but in my books you can’t argue a 23% discount.  That, and having realized that Mr. Man (ie, the aforementioned son) is growing by leaps and bounds, I no longer wanted to let good photo opportunities pass by.
  • New laptop.  This news isn’t so new, but it was on the 2008 list.  Completeness, you know?

Okay, on to the good stuff!

(as always, this list is subject to change)

From previous lists, and in no particular order:

  • An electric toothbrush, with induction recharging.  Yes, I’m still using Mr. Whiny
  • Dress socks, assorted colors (including black) (no brown either, I picked these up recently – I guess that leaves blue..?)
  • White undershirts and vests
  • Winter scarf/scarves: black, grey, blue, brown… RECEIVED!!!
  • Casual and/or dress belts; last time I checked ye olde waist is in the 32-34 range

Staples:

  • Clothing (ask Shelly, she knows more about this than I do apparently).
  • Kicks (ie, sneaks… you know sneakers.  Again, ask Shelly.  Size 11 1/2 or 12).

New for 2010:

  • a 55mm-200+mm Canon EF-mount IS zoom lens.  This would have to fit a Canon EOS Rebel T1i (hence the EF mount).
  • A camera bag with shoulder strap, capable of holding an SLR camera w/ attached lens, plus one additional lens.  Nothing too huge, just large enough for the mentioned items – plus the obligatory (slim-) pockets for stuff like memory cards.
    [Edit: This is nice, in form if not in price]
  • Door-frame-mounted chin-up/exercise bar.  Shelly has a good idea what this is all about, so you bettah axe somebody.
  • A storage shed (!) for the backyard.  Hey, why not.  It would get used, trust me.
  • An Apple iPad.  Oh my goodness, did I just say that?  It’s not so much that I want an iPad – rather, it’s that I want a touch-optimized tablet.  The Win7-based bad boys are too $$$ and lame.  The Android guys are either too small (7″ and smaller) or have resistive touchscreens (blyech) or are running some 1.x variant of Android (too old).  Perhaps Google will have released Chromium OS by Christmas time, in which case a 10″ Chromium tablet with a capacitive touchscreen and WiFi (no 3G) would be purrfect.  ***NOTE*** – I’ve changed my mind on the 7″ Android tablet, after having done some reading on the Samsung Galaxy Tab.  I like it so much (in reviews) that I’d burn my Rogers Hardware Upgrade on it.  So ya, holla at ya boy if this gift fits your bill.
    I’ve since decided that a tablet will not work – but the HTC Desire Z certainly would! Unfortunately Rogers sucks large grapes re: worthwhile Android phones so I guess I’ll be holding on to my HUP for a little longer.  Somebody on the Interwebs suggested HUP’ing to an iPhone4 and selling it, which would then offset the cost of a no-contract Desire Z from Bell – but apparently i4’s aren’t selling so well…?  I dunno… if you have a Bell hardware upgrade that you have no use for, well, consider gift-wrapping it and sending it my way – I’ll slap some Benjamins on that bad boy and everybody’s happy! RECEIVED!!!
  • Some 1TB USB2.0 external hard drives, and a PCI USB 2.0 card.  I’ve given up on the TeraStation NAS, and I need the PCI card since my home server only supports USB 1.1. RECEIVED(1)!!!
  • An electric finish nailer (not pneumatic!).  Ideally, one that’s versatile enough for hardwood flooring as well as baseboards.  Otherwise, one that’s suitable for trim and general woodworking projects.  These things are plenty handy, I wish I had one.  A used unit from the Home Depot rental store would be just fine (hint – talk to somebody at a Home Depot rental store to get the 411 on these things)

Wifey say, wifey do: zone drag/drop active

I don’t really know what to say about the titles that I come up with.  I mean, they’re my ideas, so I can’t sit here and shake my head in disbelief or some mild form of pity.  But really, what the heck does this one mean?

Well, at least the second part is fairly self-explanatory – to a degree.  It’s now possible to drag-and-drop an album or song directly onto a zone while in the browse view.  The idea is that you can queue up – or begin playing – an album/song without going through the steps that previously existed (and still exist) to perform this apparently arduous task.

Yes – “apparently” – and this is where the first part of our interesting title is explained.  One day, a long long time ago, Shelly said that it really should be possible to drag-and-drop an album onto a zone.  I believe that I was in the midst of showing her the ability to drag-and-drop an album/song onto the working list and have the item added to the list.

I’m not sure what prompted her to make this suggestion.  The thing is, the drag/drop facility is only available on platforms that support dragging – like a laptop or desktop – and not at all on platforms like smartphones which have no concept of how to perform a drag/drop action.  And – you guessed it – Shelly users her smartphone to interact with the system.

Nevertheless, I said “yes ma’am” and eventually got to work.  And the fruits were fully realized today (well, a couple of days ago but polished a bit today) with code that makes Shelly’s suggestion a reality.  As I said, from the browse view, you can drag an album/song over the existing play icon, which will cause a popup to be dynamically created containing all of the zones.  Finish the drag/drop operation by dropping the album/song on one of these zones, et voila, Something Happens(tm).

That “something” is dependent on a few things.  For an unloaded/unlinked zone, the operation will always end with the zone being shown and playback started.  Depending on your prefs, you may be asked if you want the zone to be linked.

For a zone that is already linked, the operation will cause the dragged item to be added to the linked list.  You remain on the browse view, but there is a helpful popup that says “Added” just to confirm that, indeed, Something Was Done(tm).

Now, the 5-billion-dollar question is: is this really necessary?

Well let’s look at the title for the most obvious answer: Wifey say, wifey do.  Wifey said “Do it”, and now wifey can do it.  Easy breezy.

Okay, how about a more general discussion?

I’ll oblige.  If you have the ability to perform this drag/drop operation, then you have the ability to use the other nifty features presented by the interface – most notably, the ability to take advantage of dynamically-loaded popups and inline information.  Previously – and currently – the steps to play an album or song (we’ll just say an “entry”) could most easily be performed by clicking the popup icon for that entry, clicking the play icon in the resulting popup, and then clicking the zone in the resulting zone list that got dynamically loaded into the popup.  This operation would always result in you getting transferred to the zone, where playback would have been started.  In the case of a zone that was previously linked, the linked list would be overwritten (unless the list was not an auto-generated linked list – in which case you’d get an error).

So if anything, that’s three clicks and waiting around for two dynamic operations to complete (the popup and the inline zone list) before anything could happen.

With the new drag/drop ability, you really only click once and you have to wait for one dynamic operation to complete – ie, the popup containing the zone list.

So from that point of view, I suppose I can agree that the new method is indeed more efficient.  I have to wonder how many times in one session a user is likely to load an entry to a zone – or in other words, how much impact this increased efficiency would have in the real world – but I suppose one can’t argue when it comes to the inherent goodness that is “increasing efficiency”.

But wait… perhaps there’s more to this.

What really makes this worthwhile is that the code is linked-status-aware.  Meaning, it does different things depending on the linked status of the destination zone.  This was alluded to earlier, but allow me to focus on it in more detail.

While it’s all well and good to drop an album on a zone and call it a day for the next 60 minutes, what happens if you’re putting together a 4-hour playlist of albums – or a 60-minute playlist of songs?  Now we’re no longer talking about loading a single entry to a list.

The previous (and still existent) optimal method for doing this would have been to create a new playlist and select it as the working list – or perhaps to load the first entry to the zone, then select the resulting list as the working list.  This doesn’t always work well if you’re working with albums, as the system isn’t guaranteed to create a linked list for a single album depending on how your prefs are set.  But supposing that it’s set appropriately, either of these methods would get you pointed in the correct direction.

Then, you could drag/drop additional entries to the list – or use a pulldown, or a checkmark,  or whatever other method you liked.  But the point is that you’d want to select the list that ended up getting linked to the zone of interest.  Or, if you manually created the list, then you’d select this list as the one that you will eventually load to the zone of interest.

With this new method, the only thing you need to know is what zone you want to work with.  You could have an entirely different list selected, or no list at all.  The list is not important – only the zone.  So the new sequence of events becomes: drag/drop an entry to the zone, return to your browse results, and drag/drop more entries to the zone.  The backend will take those additional entries and add them to the list associated with the zone.

You can see that this method offers clear benefits.  Again, there’s no need to work with or even know which list is linked to the zone.  This is especially useful if your current working list was used as part of the criteria in your current search.  Changing your working list to become the linked list would alter your search results, which may make it difficult to select more entries to add to the working list.

But most crucially, you get to take advantage of the increased efficiency that we discovered previously.  Yes, you could already drag/drop entries onto your working list – ie, the same efficiency that drag/drop onto a zone offers (better efficiency in fact, since there’s even less dynamic loading going on) but again, this only factors in if you select the linked list as your working list.  Now, even without selecting the relevant linked list, you can drag/drop and end up at the same place.

So ya, that’s cool.  I did some initial work in the backend to allow the user to drop a search result onto a zone as well.  I don’t have  draggable defined for this, but once I define one then it should Just Work(tm).  Truthfully it would also be nice to be able to drag/drop multiple items at once.   This may be straightforward for the backend to handle, but I imagine the frontend would need some serious work.  I’ll hold off on getting that going, but I suppose it is a project to look forward to.

From a technical point of view, I will say that getting this to work took a few days, but the hooks were mostly present to make it all go.  The stuff that I added amounted to handling a new breed of popups, which are non-modal and presented more as a menu anchored by an element on the page.  This comes with the need to define a relationship to that anchor, manage timers (which close the menu appropriately), clean up everything when a drop occurs or a drag is cancelled, and defined special “action” elements to overcome z-index issues.  The action elements – “actionables”, as I call them – were already necessary for regular drag/drop operations (again, due to z-index issues) but needed to be extended to work with menu-ish popups.

C’est tout.

What fresh eyes can bring

Last week I attended a 5-day training course, and on the last day (Friday) I came back to the office since training ended at about 12PM.  This course of action was frowned upon by some, who insisted that when you attend “this sort of thing” the expectation is that you go home if it finishes early.

That didn’t sit well with me, so like I said, I found myself at work.  I felt strangely refreshed and renewed.  Not sure why, but it was almost like coming back from vacation.  Except better – for me at least, since being away on vacation often carries stressors of its own.

Anyhoo, today I came in and went about my usual routine – which includes connecting to home so that I can stream music from the audio system.  At some point I needed to move some entries around in a playlist, and for whatever reason it hit me that there was some trivial code that I could implement to make that process (moving entries around) nicer.

You may recall that I spent a whole bunch of time in the past coding my own dynamic-reordering solution, which lets me reorder records in a table without having to refresh the whole page.  The concept isn’t novel, but in my case I was never comfortable with using DHTML to simply swap rows around; I wanted to the backend to feed updated info to the frontend, since there’s more happening than just swapping visual elements.  So my solution was to clear the table and have it refresh itself from the backend.

I was never 100% comfortable with this, for a number of reasons, but it dawned on my today that I didn’t need to refresh the whole table; rather, I only needed to refresh those rows that would be affected by the reorder.

So that’s what I did.  And it’s quite nice, if I may say so myself.

This is the sort of thing I hope to bring to web-based projects at work – finding little, novel evolutions to the code that bring noticeable improvements to the UI.

Anyhow, that’s all.