How to set a value as “Primary” in the Mac Address Book

October 22nd, 2007

Another Simple Answer to a Specific Question:

As of OS X 10.4.10, at least, the Mac Address has the concept of “Primary” email addresses, phone numbers and street addresses for each contact, but you cannot change them unless you install a plug-in.

My First Digg

October 21st, 2007

The other day, for the first time, I felt like I had something interesting and timely to say, so I submitted the story to Digg. Yeah, it was weak, but I read Digg regularly, and was curious about what would happen. It turns out, not much: I got a few hits and a handful of people yelled at me ((Which actually sounds like the Internet in a nutshell, now that I think about it)). Fortunately, at least a few people thought it was a good idea, because I got a couple of diggs. Which is good, because I avoided that pathetic, I-dugg-myself “1 digg”… which, I now understand, is the real reason one might not want to Digg one’s own work. But I digress…

In retrospect, my title, “Buy a new Mac now to avoid having to pay for Leopard on your old Macs”, was probably my first mistake. Not only does it sound like an ad and sound like piracy, it sounds like an ad about piracy. In my own defense, though, I swear that it didn’t occur to me that I was advocating piracy; I thought I was just pointing out a good deal. But no, let’s be clear: you can only install your copy of OS X on a single computer unless you purchase the family pack.

To be fair, though, I was suggesting that people buy a new Mac, which, at the absolute minimum will run you about $600… and I was suggesting it to people who already own at least one Mac. In other words, even if you’ve already made a significant financial investment, and you make an additional financial investment, it’s still piracy; people will yell at you if you suggest it.

This is why people hate Mac users.

Buy a new Mac now to avoid having to pay for Leopard on your old Macs

October 20th, 2007

If you’re thinking about buying a new Mac, do it now to avoid having to buy Leopard separately to upgrade your older Macs.

I just bought a new mini to replace my ailing Windows PC, and it came with a model-specific install/restore disc labeled “Mac mini: Mac OS X Install Disc”. Had I waited and bought a machine that shipped with Leopard, I wouldn’t be able to use that disc to upgrade my Quicksilver, my Powerbook, or (presumably) my old G4 mini. If I wanted to update those machines, I would be forced to spend $120 on a retail copy.

However, through December 31st Apple is offering a copy of Leopard for $10 to anyone who purchases a new Mac that comes with Tiger. If history is any indication, that disc should work for all models, and you’ll save $110.

Updated 10/21/2007: It’s been pointed out to me that, assuming that the Leopard software license matches the Tiger software license (PDF), installing this on more than one machine would be considered piracy, so I no longer officially advocate this course of action. Apologies to Apple, and to all the people who worked hard to make OS X a great operating system.

Things to Do

October 19th, 2007

My productivity dipped, not surprisingly, after a bout of food poisoning coinciding with the brief lull preceding the start of the fall television schedule prompted me to buy an Xbox 360. In an effort to get back on track, I’ve compiled a to-do list, of sorts, to jump-start my flagging… something.

Finish Video Server series.

I got off to a good start with my series of entries on ripping and encoding files for my iTunes/AppleTV video server, but I’m sort of stuck on what was to be the final entry- adding meta-data to the files to make them pretty. It comes down, in part, to not being sure how to distribute a couple of accompanying scripts. They’re too long to post as part of the entry, so they’ll need to be archived and put up for download as a tar file. The real sticking point, though, is that they need more documentation, and I just haven’t been able to bring myself to do it.

Rework skedevel.com.

Moving skettle.com to skedevel.com was far simpler than I’d hoped, but that was only the first step. I need to reduce the complexity of the site, removing the ill-conceived user-centric directory structure for public facing content, and making everything function privately. In other words, go back to a log-in to use the tools model, and decide after the fact what is publicly accessible. The .site.com model is great for complex social-networking type sites, but since I don’t hve much interest in doing that, the complexity is making everything else three times more difficult. While I’m in there, I also need to streamline the database access and see if I can come up with a way to benchmark the capacity of the site. It would be nice to know exactly what kind of pounding the codebase could take.

Implement OpenID on skettle.com.

I was driving back from Sacramento one night when I had a revelation about how one might implement decentralized centralized user authentication for Websites. When I started looking around to see if anyone was doing what I was thinking about, I found that the guys at sxip.org were doing almost exactly what I had thought of, though there were some issues with the implementation at the time. I carefully weighed my options, and rather than using my copious free time and obvious genius to get involved and fix the perceived problems, I think I elected to watch TV and play video games. Eventually the sxip technology morphed in OpenID, and, for the most part, it seems to work. I implemented one of the early incarnations of the library for the skedevel.com code, and for all I know it still works, but I’ve been less successful finding a good WordPress plugin. One guy seems pretty close, and if he hasn’t released a stable version by the time to get around to working on this, I’ll try playing around with his beta.

Unit testing and monitoring precautionmail.com.

One of my chief goals is to build a codebase I can use for rapid development of new sites. I had two sites in mind when I started, and one of them, precautionmail.com, I already built before realizing that it wasn’t very exciting and not something I had any desire to work on long term. However, that doesn’t mean don’t want to it stay up and running. Since it’s running on the same alpha code that runs skedevel.com, there’s a very real chance that any changes I make on skedevel will break precautionmail, and it’s unlikely I’d notice it for weeks, since, let’s face it, precautionmail is boring, and there’s not a lot of incentive to make sure it’s working properly. Therefore, I need to implement some sort of functionality to monitor that the major functions of the site are working correctly, beyond just some sort of simple pattern matching HTTP check (though that would be a good start). Since fully testing the site involves logging in, writing a message, and verifying that it was delivered after a preset period of time, there could be some fairly major engineering involved.

Find a new WordPress theme.

When I first implemented WordPress, I liked the default theme, and I thought that most people using WordPress would change the theme- thus rendering my site, using the default, kind of original. I don’t know if that’s the case or not, but I have decided that it’s always lame to use the default. Even I were the only one in world doing it, I would still be lame, because using the default is lame almost by definition.

Removing Duplicate Files from iTunes

September 29th, 2007

While iTunes has its issues, for the most part it makes for a fairly passable media organizer. As long as I let it do its job, I’m pretty happy with how it handles the files on the backend. When I moved my iTunes library to a new external drive, however, I came across a pretty egregious “bug” that left me with thousands of duplicate files and no good way to remove them.

By default, iTunes stores files in “/Users//Music/iTunes/iTunes Music”. When you drag and drop a file from your desktop, or wherever, it copies the file into this directory, tossing it into a subdirectory based on Artist and Album name and renaming it according to the track info you specify in iTunes. When you change the Album name or Track name, the file is is updated and moved automatically, so the location and name of the file always reflect what you see in iTunes. Personally, I like this behavior.

I didn’t run into problems until I attempted to move my files from the default directory to a directory on my new drive, a 500G firewire affair. At first, everything worked properly when I changed the settings; it took while, but it slowly copied all the the files to the new location, “/Data/iTunes”, and once it was done, everything was great. And everything remained great until I made the mistake of opening iTunes while my new drive was unmounted.

Little did I know that when iTunes couldn’t find “/Data/iTunes”, the new directory, it changed itself back to its default: “/Users//Music/iTunes/iTunes Music”. Upon finding all the files still there, it quickly settled in and changed all the entries in the database to point to these files. When I finally realized what had happened, I remounted the new drive and changed the iTunes directory again- and that’s when all my troubles began.

iTunes once again began to copy my files to new the drive- only this time, the files already existed. Rather than simply use the existing files, it created new copies, appended with ” 1″, and I was left with several thousand duplicate files and no easy way to remove them.

To deal with this issue, I wrote a simple PHP script to crawl through my iTunes directory and deal with files that end in ” 1″. In the case where both files exist (with and without ” 1″), the script compares the two files. If they are identical, it tries to rectify the situation by removing the old file and re-adding the remaining file to iTunes using osascript, OS X’s command line Applescript tool. Adding the file triggers iTunes to automatically rename the file properly, thus removing the ” 1″. By default, you’re prompted before any file is deleted. You can disable this by hitting ‘a’ at the prompt.

In the case where the two files are not equal, they are skipped. You’re going to have to deal with those manually. Sorry. It also has problems with files that contain special characters. You’ll have to deal with those as well… but come on- how many Blue Öyster Cult, Mötley Crüe or Björk songs do you have, anyway?

In the case where only one file exists, it will simply re-add the file to iTunes, on the theory that iTunes will fix it if the name is wrong, and ignore it otherwise.

fix_itunes_dupes.php

#!/usr/bin/php
<?php

/*
* Name: fix_itunes_dupes.php
* Author: patrick
* Usage: fix_itunes_dupes.php
*
* This script is provided AS-IS.  No warranty is either expressed or implied.
* Use at your own risk.
* Feel free to use, modify, duplicate, or take credit.
*/
// Set this variable to your iTunes directory.
$itunes_dir = "/Users/{$_ENV['USER']}/Music/iTunes/iTunes Music";

if (!file_exists($itunes_dir)) {
    exit("{$itunes_dir} does not exist.");
}

// Collect itunes files that end in " 1".
$find = "find \\"{$itunes_dir}\\" -type f -name \\"* 1.*\\"";
$files = explode("\n", `$find`);
$file_count = count($files) - 1;
// 'find' comes with a bonus carriage return.  Get rid of it or try to remove
// '.' (that's bad).
unset($files[$file_count]);
// Set some defaults.
$all = false;
$count = 0;

// Loop through the files.
foreach ($files as $file1) {
    $count++;
    print "Processing {$count}/{$file_count}:\n";
    // Skip Movies and TV Shows.
    if (preg_match("/\/Movies\//", $file1) || preg_match("/\/TV Shows\//", $file1)) {
        print "Skipping TV Show or Movie:\n";
        print "{$file1}\n";
    } else {
        preg_match("/^(.+) [0-9].([^.]+)$/", $file1, $matches);
        $file = "{$matches[1]}.{$matches[2]}";
        if (file_exists($file)) {
            $md5 = md5(file_get_contents($file));
            $md51 = md5(file_get_contents($file1));
            print "{$file} ({$md5})\n";
            print "{$file1} ({$md51})\n";
            if ($md5 == $md51) {
                // If the two files are identical, we can space one of them.
                print "{$file} = {$file1}\n";
                if (!$all) {
                    // Options are:
                    //  y - delete the file. default.
                    //  n - skip this file.
                    //  a - stop asking, just do them all.
                    //  q - quit.
                    print "Delete? [Y/n/a/q]: ";
                    $char = substr(fgets(STDIN), 0, 1);
                }
                if ($char == "q") {
                    exit;
                } elseif ($char != "n") {
                    if ($char == "a") {
                        $all     = true;
                    }
                    print "Deleting {$file}\n";
                    unlink($file);
                    add2itunes($file1);
                }
            } else {
                print "Files do not match.  Skipping.\n";
            }
        } else {
            // There is only one file; go ahead and add it to iTunes-
            // shouldn't hurt.
            print "{$file1} exists on its own.\n";
            add2itunes($file1);
        }
    }
    print "\n";
}

function add2itunes($file) {
    $file = preg_replace("/\//", ":", $file);
    // Please forgive the toothpicks- numerous files have 's.
    $command = "osascript -e \\"tell application \\\\"iTunes\\\\" to add file \\\\"{$file}\\\\" to playlist \\\\"Library\\\\" of source \\\\"Library\\\\"\\"\n";
    print $command;
    passthru($command);
    return;
}

?>

Sample Output

Processing 31/39:
/Data/iTunes/The Beastie Boys/Licensed To Ill/13 Time to Get Ill.m4a (42cbc19b9d2feb83899201793ee1e00e)
/Data/iTunes/The Beastie Boys/Licensed To Ill/13 Time to Get Ill 1.m4a (e2f49dfc12db5fb8f8d3954b9671870c)
Files do not match.  Skipping.
Processing 32/39:
/Data/iTunes/The Bloodhound Gang/One Fierce Beer Coaster/07 Asleep at the Wheel.mp3 (6d12ce65c4cba6748224e2262feba67a)
/Data/iTunes/The Bloodhound Gang/One Fierce Beer Coaster/07 Asleep at the Wheel 1.mp3 (6d12ce65c4cba6748224e2262feba67a)
/Data/iTunes/The Bloodhound Gang/One Fierce Beer Coaster/07 Asleep at the Wheel.mp3 = /Data/iTunes/The Bloodhound Gang/One Fierce Beer Coaster/07 Asleep at the Wheel 1.mp3
Delete? [Y/n/a/q]: y
Deleting /Data/iTunes/The Bloodhound Gang/One Fierce Beer Coaster/07 Asleep at the Wheel.mp3
osascript -e "tell application \"iTunes\" to add file \":Data:iTunes:The Bloodhound Gang:One Fierce Beer Coaster:07 Asleep at the Wheel 1.mp3\" to playlist \"Library\" of source \"Library\""
file track id 53184
Processing 33/39:
Skipping TV Show or Movie:
/Data/iTunes/TV Shows/Battlestar Galactica/3-03 Exodus_ Part 1.mp4

Video Server, Part 4: Converting

September 24th, 2007

This is Part Four of my series on building a video server using Apple’s iTunes/AppleTV combination. This article details the process of converting existing video files to a compatible format.

When I initially started this whole video thing, my goal was to get video on my iPod, so naturally one of the applications I came across when I was searching for tools to convert my collection of .avi files was the Videora iPod Converter by Red Kawa (v2.25). Though billed as an iPod converter, this front-end for ffmpeg allows you to set the output values to almost anything, making it ideal for converting an existing .avi file to any flavor of .mp4 you’d like.

At first I was put off by the ad-thick interface and the hideous design, but once I got past that I found a fairly full featured, functional application. Day to day usage is trivial, as the program is built around a “One-Click” queue that functions pretty much as intended, but getting it configured took a bit of work.

Step 1: Set the Video Output Folders.
After you start the program, choose “Settings” from the menu at the top of the screen. Chose “Devices” from the tabs menu that appears, then “iPod” from Device Settings. You have two fields for Video Output Folders: MPEG-4 Videos and H.264 Videos. I don’t know which is which, so I set both of them.

Fig 1: Set the Video Output Folders.

Step 2: Set the Encoding Profile and One-Click settings.
Change the tab from “Devices” to “Converter”. In the “Encoding Profiles” box, set Device to iPod, and Profile to “H.264 VGA 1024 kbps Stereo/160kbps”. In the “One-Click” box, set “Device” and “Profile”. I also set “Process Priority” to “High”, but this is the only thing I use this computer for.

Fig 2: Set the Encoding Profile and One-Click settings.

Step 3: Edit Profile, set General Properties.
Click on “Edit Profile”. Leave Name set to “H.264 VGA 1024 kbps Stereo/160kbps”, and change Encoder to “AppleTV 1-Pass – FFmpeg MINB”, if it’s not already set.

Fig 3: Edit Profile, set General Properties.

Step 4: Edit Profile, set Video Properties.
Click the “Video” option in the menu, and set the options as they appear in Fig 4. For the most part, I prefer to leave the resolution and aspect ratio alone, and make sure Auto Resize is not enabled. However, do make sure to set the Framerate value to “29.97”. A number of applications and hardware decoders can be touchy about this value.

Fig 4: Edit Profile, set Video Properties.

Step 5: Edit profile, set Audio Properties.
Click the “Audio” icon in the top menu, and compare the settings to Fig 5. To be perfectly honest, I don’t remember whether or not I changed any of the defaults, or if they matter.

Fig 5: Edit Profile, set Audio Properties

Step 6: Convert.
Once the profile has been configured, converting is a breeze. In the top menu click “Convert” and choose the “Current Conversion” tab. Click the “One-Click Convert” button to choose a list of .avi files. They will automatically be added to the queue and conversion will begin immediately. Completed files will be dropped in the Video Output Folders defined in Step 1, and should be fully iTunes compatible.

Fig 6: Convert.

Your mileage will vary, of course, but my conversions are usually a tad faster than realtime. A 42 minute file, for example, will usually take 30 to 40 minutes to complete, and the quality, while not stellar, is adequate. There are likely a number of places where this could be improved.

In the next article in this series, I will present the scripts and techniques I use to add meta-data to the video files, including plot descriptions, artwork and ratings.

Fixing a PHP CLI segmentation fault

September 17th, 2007

Another Short Answer to a Specific Question:

Sometimes, after an upgrade, any PHP script run from the command line causes a segmentation fault, even though the script seems to run fine. For example:

[03:13:01 argon:~]$ php -v
PHP 5.2.4 with Suhosin-Patch 0.9.6.2 (cli) (built: Sep 17 2007 02:28:25)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
Segmentation fault: 11 (core dumped)
[03:13:02 argon:~]$

Whenever this happens, I can usually resolve the problem by changing the order of the modules listed in extensions.ini. Three times out of four, moving “extension=session.so” to the top of the file fixes the problem.