Saturday, December 27, 2008

My first Drupal module(s)!

I'd nearly given up learning the Drupal content management system, after it took me two hours to change a font on a static web page. But I needed to procrastinate something even more difficult than changing fonts in Drupal, so I decided to try, try again.

The first interesting thing I wanted to try in Drupal was feed aggregation. I love the idea of feed aggregators like Tumblr, FriendFeed, and Swurl, but I'm unsatisfied with the limitations on what or how many feeds you can use. The output (from Tumblr in particular) can also be rough-looking. Why oh why can't they handle quotation marks in titles right. I'm no regex champion, but I suspect even I, PHP fledgling, could write the fix to that. Surely they've noticed that posts titled "Barack Obama - "Yes We Can"" aren't very appealing? (I had to go out of my way for Blogger to let me make it that ugly.) Finally, I'd like to enhance the output of at least one feed with additional content from my own database, which is completely impossible with Tumblr, Swurl, or FriendFeed.

So I've been checking out Drupal's feed aggregators. I tried Aggregator and FeedAPI my first day using Drupal, so I doubt I assessed their usability fairly. I'll try them again when (if) I understand CCK and Views. But when I tried the ActivityStream module, my enthusiasm for Drupal was restored! Not only did it do significant portions of what I want done (Flickr, last.fm, and delicious feeds), but it looked dead easy to add new feeds by making new sub-modules.

It was indeed dead easy. To add a Goodreads sub-module, I copied and pasted the delicious sub-module. I opened the two delicious files and replaced the word "delicious" with "goodreads". I opened my module list and saw my new module. I turned it on, entered my Goodreads info, and holy shit it worked! My recent Goodreads activity was interspersed with the Twitter, delicious, last.fm, and Flickr info I'd already added. I decided sleep could wait until I made five modules like my Goodreads modules, for Blogger, StumbleUpon, YouTube videos, YouTube favorites, and Hulu.

My new modules are far from perfect. I have a list a page long of improvements I want to make (like handling quotation marks in titles...). But the beauty of Drupal, and open source in general, is that I have access to the code to make those improvements. All I can do with Tumblr is gripe and hope they fix it.

Thus far, it seems to me that in Drupal, it's much more fun doing hard things like feed aggregation than doing easy things like changing fonts. I think this explains why people hate Drupal, then love it. To beginners doing something "easy" like trying to change fonts and put files where they want them, Drupal seems like a ridiculous thing to be excited about. To people who've just done something "hard" that they've wanted to do for years in the space of ten minutes (that's what she said), Drupal seems pretty awesome.

Thursday, December 25, 2008

A very Hulu Christmas

A white Christmas is very nice, but an extremely snowy week-before-Christmas meant my Christmas plans changed to staying in with the cats. We may order Thai food later to honor my husband's Christmas traditions. To honor mine, there must be cornflake cookies, bean dip, and television. The food is achieved, but the t.v. was harder. For starters, I have no television set. Fortunately, the Internet is almost a satisfactory video-watching alternative. Here's what I've tracked down so far.

How The Grinch Stole Christmas
A classic. I haven't watched it all the way through yet, but it was choppy. I paused it to let the whole thing load in hopes of improvement.

Rudolph the Red-Nosed Reindeer
Another classic. Might be choppy.

Bing Crosby - White Christmas
One of my favorite Christmas songs.

John Lennon - Happy Xmas (War is Over)

Trey Parker and Matt Stone - The Spirit Of Christmas
What would Brian Boitano do?

American Dad - Best Christmas Story Never Told
The "War on Christmas" hilariously embodied. On Hulu, so shouldn't be choppy.

American Dad - Most Adequate Christmas Ever
Stan learns a Christmas lesson. On Hulu, so shouldn't be choppy.

santa claus on cribs
Not for children, though they probably won't catch the double entendre.

Elmo & Patsy - Grandma Got Run Over By A Reindeer
There was nothing funnier than this song to a certain ten-year-old in December 1985.

The Simpsons - Christmas Epidsode

Alfred Hitchcock Presents - Back for Christmas
Christmas is about giving.

The Madagascar Penguins - A Christmas Caper

Santa Beats Up Guy In Mall

Tom And Jerry - The Night Before Christmas
I was never that enthusiastic about the super-violent Itchy and Scratchy style Warner Brothers cartoons, but I think this one's okay.

NewsRadio - X-Mas Story
On Hulu, so shouldn't be choppy. I haven't watched it yet, but I'd bet money this is at least 4 out of 5 stars, as all NewsRadios are.

NewsRadio - Stupid Holiday Charity Talent Show
On Hulu, so shouldn't be choppy. I haven't watched it yet, but I'd bet money this is at least 4 out of 5 stars, as all NewsRadios are.

Saturday Night Live - Two A-holes Buying a Christmas Tree

Saturday Night Live - Christmas For The Jews Song

Saturday Night Live - Hanukkah Harry

Saturday Night Live- Two A-holes In A Live Nativity Scene

The Twilight Zone - The Night Of The Meek

Alfred Hitchcock Presents - The Festive Season
Bleak, quality entertainment. On Hulu, so shouldn't be choppy.

Jay Leno - Bizarre Christmas Musicians

The Colbert Report - December 11, 2008

Bones - The Santa In The Slush
I haven't checked out this show yet. Perhaps I'll start with this one. On Hulu, so it shouldn't be choppy.

The Office - Moroccan Christmas
Haven't watched yet. On Hulu, so shouldn't be choppy.

30 Rock - Christmas Special

MadTV- Best of Christmas Sketches
Hit and miss, but worth it just for The Reinfather.

Do They Know It's Christmas?

Full Metal Christmas

Sketchy's Super-Happy Christmas Film
I haven't watched it yet, but stop-motion and Christmas do go together.

Three's Company Christmas

Space Ghost Christmas

Santa Claus Conquers The Martians, Part I
Santa Claus Conquers The Martians, Part II
Santa Claus Conquers The Martians, Part III
Santa Claus Conquers The Martians, Part IV
Santa Claus Conquers The Martians, Part V

The A-Team - Holiday In The Hills

Nestor The Long-Eared Christmas Donkey

William S. Burroughs - The Junky's Christmas

I've only included videos that interest me, but here are links to searches so you can see what I've left out:
Hulu
GUBA
StumbleVideo
YouTube
Dailymotion
FunnyorDie
CBS

Wednesday, December 17, 2008

How to write a playlist maker script

I got an email asking for tips on writing a playlist maker script.

Using PHP, my process was this:
1. Choose a playlist format. My favorite playlists are Windows Media Player WPL files, which use the SMIL subtype of XML. There are tons of other types of playlists. Songbird and Winamp both use M3U, for example. Unfortunately, most playlist file types, including M3U, are not as "smart" as WPL files, in that they want the exact path to a single song on a user's computer, rather than just an artist name or song title. WPL files will take an artist or song name and give you a playlist of everything in your library that matches. I don't understand why Songbird and Winamp don't handle WPL or SMIL files (yet?). After I figured out which playlist format I wanted, I right-clicked a WPL file I'd made, opened it in Notepad, and used it to cut and paste the top, bottom, and repeating bits of the playlist code where needed in the following steps.

2. Find a source of artists or song names you want in your playlist. The best way was to use an RSS feed, but for my iLike and last.fm tag playlist makers, I scraped the source code of some web pages, which is messy, but it works. You can also offer a way to paste in or upload a list of artists.

3. Write an HTML form (called, for example, input.html) that takes user input (like a last.fm username) to get the source you want. The "Submit" button on the form will take you to your playlist making code (playlistmaker.php, for example).

4. Write code to convert your input (such as a last.fm username) into a URL to an XML or HTML file and get that file ready to be used. For example:
$handle = fopen("http://ws.audioscrobbler.com/1.0/user/".$username."/topartists.txt?type=overall", "r");

5. Write code to make an array of only artists or song names using your source. The exact code will vary depending on the source of artists or song names. This is the trickiest part, and I'd give examples of how I've done it, but it's different nearly every time, and I'm sure my ways are not especially elegant. One thing I'd like to do better is parsing the actual XML instead of finding where the artists turn up in the array and using numeric indices to grab the artists or song names.

6. Create a variable that will contain the entire text you want in the playlist file ($wpl, for example). Paste in the top bit of the playlist text. For a WPL file:
$wpl = "<?wpl version=\"1.0\"?>
<smil>
<head>
<meta name="\" content="\">
<title>".$username."</title>
</head>
<body>
<seq>
<smartplaylist version="\">";

7. Write a loop that adds the section of the playlist that repeats for each artist or song name to your playlist variable ($wpl., for example). Concatenate in the artist or song name variable. Make sure you convert HTML characters, as ampersands will render your playlist utterly worthless. For example, where the artist names are in $data[2]:
while ($data = fgetcsv($handle, 1000, ",")) {
$wpl.="<querySet>
<sourceFilter id=\"{4202947A-A563-4B05-A754-A1B4B5989849}\" name=\"Music in my library\">
<fragment name=\"Album Artist\">
<argument name=\"condition\"<Contains>/argument>
<argument name=\"value\">" . htmlspecialchars($data[2]) . "</argument>
</fragment>
</sourceFilter>
</querySet>";
}

8. Finish off your playlist text variable by pasting in the end text of the playlist variable (again, $wpl.). For a WPL file:
$wpl.="
</smartPlaylist>
</seq>
</body>
</smil>";

9. Create a new file containing your playlist variable text as follows:
$handle = fopen("filename.wpl","w");

10. Offer a link to download the new file.

11. Try it out!

Optional tweaks:
12. WPL playlist files offer you the option of finding an artist name that "Contains" the word "Bell" (for example), or finding an artist that "Is" the word "Bell." After the band "Bell" made Belle and Sebastian turn up in a festival playlist I made (oh, the brief crushing excitement), I added a conditional so that if the artist name is 5 characters or shorter, I use "Is", and if it's longer, I use "Contains". It's still inexact, and it's an area I'd like to improve. Handling "The" (Pixies, Beatles, Raveonettes) is another thing I'd like to work out at some point. Here's an example of one of my conditionals where the artist names are in $data[2]:
while ($data = fgetcsv($handle, 1000, ",")) {
$limit=6;
$num=count($data[2]);
for ($i=0;$i<$num;$i++) {
$len[$i]=strlen($data[2]);
if ($len[$i]<$limit) {
$wpl.="<querySet>
<sourceFilter id=\"{4202947A-A563-4B05-A754-A1B4B5989849}\" name=\"Music in my library\">
<fragment name=\"Album Artist\">
<argument name=\"condition\">Is</argument>
<argument name=\"value\">" . htmlspecialchars($data[2]) . "</argument>
</fragment>
</sourceFilter>
</querySet>";
}
else {
$wpl.="<querySet>
<sourceFilter id=\"{4202947A-A563-4B05-A754-A1B4B5989849}\" name=\"Music in my library\">
<fragment name=\"Album Artist\">
<argument name=\"condition\"<Contains>/argument>
<argument name=\"value\">" . htmlspecialchars($data[2]) . "</argument>
</fragment>
</sourceFilter>
</querySet>";
}
}
}

13. Greasemonkey! Using a tiny bit of Javascript, you can put a link to your playlist making code on relevant source pages. Clicking this link will give you the option to look at one of my Greasemonkey scripts. You'll especially want to change:
  • @include to reference the page you'd like to put a link on.
  • The link to the script that makes your playlist.
  • @name
  • @namespace
  • Colors (I'm using last.fm grey. Meh.)

You can grab the username for the last.fm URL they came from by putting this at the top of your playlist maker script (playlistmaker.php, for example):
$url = getenv("HTTP_REFERER");
$elements=explode("/", $url);
unset($url);
$username=$elements[4];
unset($elements);

Here's a zip folder with code for the input form and playlist maker, as well as a Greasemonkey playlist maker for a last.fm listener's most-played artists. This was one of the first things I did when I was learning PHP, so it's far, far, far from perfect. But feel free to use any bits of it you like. I'm not litigious.


I am crawling up a learning curve (Drupal) myself right now, but if you have questions or suggestions, comments are open.

For anyone more interested in making playlists than playlist-maker scripts, my playlist makers are here.