AppleScripts for iPhoto Library Manager

UPDATED REVIEW

The original version was published just weeks before Apple’s un-announced release of iLife '08, which included an upgrade of iPhoto to version 7.0. A few months later, Apple released the announced Mac OS X version 10.5 (Leopard). Brian Webster of Fat Cat Software did a tremendous job of keeping iPhoto Library Manager up to date and relevant through these events. What follows is a re-visit of the original review’s AppleScript information.

Versions for testing:

Original Review:
Mac OS X 10.4.10
iPhoto Library Manager Version 3.2.6b1 (3.2.6b1) ($19.95, Shareware)
3.2.6b1 version upgraded to 3.2.6 on 20 July 2007

Updated Review:
Mac OS X 10.5
iPhoto Library Manager Version 3.4
iPhoto Version 7.1
Scripts tested on iBook G4 and Intel iMac

iPhoto Library Manager (iPLM) takes iPhoto to the next level. Period. If you are an avid photographer, enjoy iPhoto, and would like to have more organizational control over your work, the full version of iPhoto Library Manager is a bargain. If you also enjoy AppleScript, and would like to automate some of your photographic workflows, you cannot live without iPhoto Library Manager. I am a member of that last group; I have used iPhoto since 2002 and have been very pleased with the improvements Apple has made since then. At the same time, there are a few things that are still clunky; using multiple libraries, moving photos from one library to another (and still retaining keywords, ratings, etc.), and creating image folders to sync with my iPod. Once I got iPhoto Library Manager on my machine, however, all that changed. It is simplicity itself to work with all the different libraries, move images wherever I want them, and do other things I had never even imagined. Add to that the powerful AppleScript abilities, and I honestly admit that I cannot live without this product.

The graphical user interface (GUI) is simple, uncluttered, and self-explanatory; I did not have to go to Help section just to get started. I was able to locate all my previously created libraries and add them to the list; making new ones was simple and quick. Brian Webster, the developer, also provides plenty of timely little hints in the bottom of the main window as gentle reminders of details to keep users from getting too confused about what they are trying to do. Drag and drop support is excellent and reliable.

Keyboard shortcuts work flawlessly, and certainly simplify tasks. Got a disc of images from your brother in law to import into a library somewhere? No problem. Just be sure that the Library you want as your final destination is highlighted (it does not have to be open at the time) in the iPhoto Library Manager Library window, and press Command-I. You can select the entire disk, a folder on the disk, or individual images. They will be efficiently imported into the highlighted library.

Library merging is smooth, and kind of fun to watch, in a psychedelic way. It is still the simplest method on the market today to preserve keywords, ratings, and comments between iPhoto libraries (regardless of the iPhoto version the old libraries were created with) and is certainly a chief selling point of this product. Currently, only full libraries can be merged (see Pipe Dreams below) together.

Shortcuts to libraries provide a level of coolness that I have not seen in many shareware programs. If you have a few libraries that you access regularly, you can easily create shortcuts to them with Command-L (clickable files that immediately launch a library) and put them in the right hand (non-application) side of your dock.

The preferences that a user can set are a little intimidating at first, because the developer really has tried to think of EVERYTHING. I cannot even begin to describe the feeling of total control one develops by spending some time in those three panes. Unless you are a seasoned user of iPhoto, figuring out your own personal tastes will probably take some time (and some trial and error) to understand all the settings, but it is well worth the effort.

If you are still nervous, don’t worry, the Help section for Preferences is well written and very useful, as are nearly all the other Help sections. In fact, there is a link to Apple’s site to an undocumented feature for rebuilding an iPhoto library, through iPLM’s help tree. The only Help section that seemed confusing to me were the instructions for creating an iPod folder. All went well through the creation and configuration of the iPod folders, but the Update was not intuitive enough, nor did the Help pages present an easy to follow order in which to do all the steps in the correctly. I actually linked the iPod folder while it was still empty, and had to re-link it after I clicked Update.

The AppleScript functionality of iPhoto Library Manager is unbelievable. Brian Webster clearly understood that not all users would necessarily like to do things his way, or strictly via the GUI, so he has provided AppleScript access to all the preferences as well as the most vital actions that iPhoto Library Manager does in the background. This level of scriptability provides practically infinite possibilities for a user who desires customization and automation.

The following are scripts to demonstrate the usefulness of iPhoto Library Manager:

Finding all your libraries

I am ashamed to admit that over time, I have created numerous iPhoto libraries all over the place. I started in my root user folder, then put some in my Pictures folder, then a few in Documents, etc., etc. Not a pretty sight, and I certainly had no idea where all these things were located to bring them all into iPhoto Library Manager, so I came up with this script (Explanatory notes in script):


set user_Folder to characters 1 thru -2 of (POSIX path of (path to home folder)) as string --This removes the terminal slash from the POSIX path.
set all_user_Libs to every paragraph of (do shell script "find " & user_Folder & " -name AlbumData.xml \\! -path " & user_Folder & "/Library/\\*") --Shell syntax courtesy Gary Kerbaugh--This returns a list of all the AlbumData.xml files, which are located in the root directory of all iPhoto albums. The shell script above ignores any files in the user's Library, since there actually is an AlbumData.xml file there, although it is not associated with an iPhoto Library. The returned list looks like this: {"/Users/casdvm/Documents/Cathouse/AlbumData.xml", "/Users/casdvm/Documents/Family/AlbumData.xml", ....}
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "/AlbumData.xml"
set user_Lib_paths to {}
repeat with aul in all_user_Libs
	set end of user_Lib_paths to text item 1 of (contents of aul) --This creates a list of the paths to the acual iPhoto library by removing the /AlbumData.xml portion of the file path.
end repeat
set AppleScript's text item delimiters to astid
--Our list now looks like this: {"/Users/casdvm/Documents/Cathouse", "/Users/casdvm/Documents/Family", ....}
tell application "iPhoto Library Manager" to set current_Libs to location of libraries
--iPhoto Library Manager tracks two important properties for each library, the name and the location. Since we only need the location for now, our list of current library locations yields this data: {"/Users/casdvm/Pictures/iPhoto Library", "/Users/casdvm/Pictures/Review01", "/Volumes/Ricoh/Smith Collection"}

repeat with ulb in user_Lib_paths --We now cycle through all the paths generated in the first portion to see if they are already in the iPhoto Library Manager database.
	if current_Libs does not contain ulb then
		set new_lib_loc to (POSIX file (ulb's contents)) --Once a path is found that is NOT known to iPhoto Library Manager, we need to convert the POSIX path to a Mac path for the [make new library] to function correctly. Although iPhoto Library Manager displays POSIX paths in its GUI, it cannot make a library with that information.
		tell application "iPhoto Library Manager" to make new library with properties {location:new_lib_loc} --Make a new library using the path that iPhoto Library Manager does not currently recognize.
		display dialog "New library at: " & new_lib_loc giving up after 2
	else
		display dialog (ulb's contents) & " is in list." giving up after 2
	end if
end repeat

This script can get off to a slow start, since the shell script scans through the entire user tree. It could easily be modified to only search certain folders, which would speed it up immensely. The name of each library is automatically derived by iPhoto Library Manager from the name of the folder that contains the AlbumData.xml file.

UPDATE
IPLM no longer returns POSIX style paths when this line is invoked: tell application “iPhoto Library Manager” to set current_Libs to location of libraries, so some alteration to the script was necessary for this to function under Leopard and iPhoto 7.1:

set user_Folder to characters 1 thru -2 of (POSIX path of (path to home folder)) as string --This removes the terminal slash from the POSIX path.
set all_user_Libs to every paragraph of (do shell script "find " & user_Folder & " -name AlbumData.xml \\! -path " & user_Folder & "/Library/\\*") --Shell syntax courtesy Gary Kerbaugh--This returns a list of all the AlbumData.xml files, which are located in the root directory of all iPhoto albums. The shell script above ignores any files in the user's Library, since there actually is an AlbumData.xml file there, although it is not associated with an iPhoto Library. The returned list looks like this: {"/Users/casdvm/Documents/Cathouse/AlbumData.xml", "/Users/casdvm/Documents/Family/AlbumData.xml", ....}
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "AlbumData.xml"
set user_Lib_paths to {}
repeat with aul in all_user_Libs
	set end of user_Lib_paths to text item 1 of (contents of aul) --This creates a list of the POSIX paths to the acual iPhoto library by removing the AlbumData.xml portion of the file path.
end repeat
set AppleScript's text item delimiters to astid
--Our list of found directories now looks like this: {"/Users/casdvm/Documents/Cathouse/", "/Users/casdvm/Documents/Family/", ....}
set current_Libs to {}
tell application "iPhoto Library Manager" --Now, we need to get the locations of any libraries already in the iPhoto Library Manager database.
	set current_Libs_Raw to location of libraries --This returns a list of non-POSIX paths, like this: {file "VelociDrive:Users:casdvm:Pictures:iPhoto Library:", file "VelociDrive:Users:casdvm:Documents:Empty Docs:", file "VelociDrive:Users:casdvm:Pictures:Empty Pictures:"}.  Since we need them in POSIX format, this next repeat will convert them for comparison later on.
	repeat with clr in current_Libs_Raw
		set end of current_Libs to (POSIX path of clr)
	end repeat
end tell

--iPhoto Library Manager tracks two important properties for each library, the name and the location. Since we only need the location for now, our list of current library locations yields this data: {"/Users/casdvm/Pictures/iPhoto Library/", "/Users/casdvm/Documents/Empty Docs/", "/Users/casdvm/Pictures/Empty Pictures/"}

repeat with ulb in user_Lib_paths --We now cycle through all the paths generated in the first portion to see if they are already in the iPhoto Library Manager database.
	if current_Libs does not contain ulb then
		set new_lib_loc to (POSIX file (ulb's contents)) --Once a path is found that is NOT known to iPhoto Library Manager, we need to convert the POSIX path to a Mac path for the [make new library] to function correctly. Although iPhoto Library Manager displays POSIX paths in its GUI, it cannot make a library with that information.
		tell application "iPhoto Library Manager" to make new library with properties {location:new_lib_loc} --Make a new library using the path that iPhoto Library Manager does not currently recognize.
		display dialog "New library at: " & new_lib_loc giving up after 2
	else
		display dialog (ulb's contents) & " is already in list." giving up after 2
	end if
end repeat

One Library for One Camera

Another cool thing is to have a certain library open up whenever a specific camera is plugged into the computer. This is a bit more tricky, and there are actually a couple of ways to do it. One way (see Setting a default iPhoto library for importing from a camera on the iPhoto Library Manager blog) involves switching the Preferences for Image Capture to launch an AppleScript. I discarded this idea because of the annoying habit iPhoto has of always begging to be first on the list. So, I let iPhoto retain its narcissistic dominance and used launchd to watch the /Volumes path for changes. (For more complete instructions on this method, see this tutorial on using launchd in AppleScript.) Here is the .plist file I used. It is embedded as text in an AppleScript for easy downloading (it will not compile as a plist in your Script Editor, it must be saved as text from a text editor.)


-- Copy the following from your Script Editor to a text editor and edit from there, saving as text:
"<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>WatchForCamera</string>
	<key>LowPriorityIO</key>
	<true/>
	<key>Nice</key>
	<integer>1</integer>
	<key>Program</key>
	<string>/usr/bin/osascript</string>
	<key>ProgramArguments</key>
	<array>
		<string>osascript</string>
		<string>COMPLETE POSIX PATH TO DESIRED APPLESCRIPT HERE</string>
	</array>
	<key>ServiceDescription</key>
	<string>Runs Applescript directly when Volumes Path changes</string>
	<key>WatchPaths</key>
	<array>
		<string>/Volumes</string>
	</array>
</dict>
</plist>"

Which, in turn, launches this simple AppleScript whenever the /Volumes path changes:


if (list disks) contains "NIKON D70S" then
	delay 2
	tell application "iPhoto Library Manager"
		set current_Lib to name of every library whose current is true
		if current_Lib does not contain "Dadman Photos" then
			open library named "Dadman Photos"
		end if
	end tell
end if

You need to do a couple of things (other than putting your own paths and camera names in these files) to make this work smoothly. First, be sure that the image cards you are using in whichever camera(s) you want to automate have been formatted by that camera. Once that is the case, plug the camera into the computer, and run this script:


list disks

You now know the name that the computer assigns to that camera/card, and can use it in the AppleScript above to switch libraries whenever that camera is plugged in. You also need to know the name of the library that iPhoto Library Manager is to call up. Those names are always present in the GUI, or for you copy and paste fans, just run this:


tell application "iPhoto Library Manager" to name of libraries

You can now just copy the name of a library from that list, paste into your script, and be done with it. Be advised that since this Launch Agent is watching the /Volumes path, and at any time that path changes, the AppleScript will be launched. As long as your camera is not hooked up, or you are in the proper library, nothing will happen, so keep that in mind as you go.

UPDATE
This portion worked flawlessly on the Intel iMac as written, but was quirky on the iBook G4, although it would eventually get around to it once you ran the list disks command all by itself…

Reclaiming old iPhoto discs

Those of us that have used iPhoto for years have stacks of CDs and DVDs of all our old libraries, because external drives large enough to hold all that stuff have only recently become affordable. So, we go out and buy a huge drive, then get depressed about how long it is going to take to transfer all those images into one (or more) iPhoto libraries on the new drive. iPhoto Library Manager can help automate and smooth that task as well.

To understand how iPhoto Library Manager can assist, it helps to know something about the recent version(s) of iPhoto. Every iPhoto library now has an AlbumData.xml file associated with it, which is necessary for iPhoto Library Manager to interact with iPhoto, and which none of your old (or new) optical discs of data will possess, nor can they even be written to the disc. To get an older version of iPhoto data to be recognized by a later version of iPhoto, it all has to be copied back onto a hard drive of some kind. I chose to use an 8 GB USB drive, since I did not want either my native hard drive or the new remote drive to have to be written and erased a bunch of times. (Of course, that is not actually necessary, but since I wanted to merge my discs together into larger libraries, the intermediate drive made sense for me.)

For this to work, you need to insert the iPhoto disk into your Mac, and wait for iPhoto to finish loading and recognizing the disk Library. Time for that varies in accordance with the version of iPhoto your disk was originally created under. Once iPhoto is finished, launch this script and watch the fun! (Explanatory notes in script):


set ip_Source to item 1 of (choose from list (list disks) with prompt "Source disc:") --Select the Source disk.
set ip_Dest to item 1 of (choose from list (list disks) with prompt "Temporary destination:") & ":iPhotoTEMP:" --By selecting the temporary drive, a folder will be created to hold the data.
tell application "iPhoto Library Manager" to set all_Libs to name of libraries
set merge_Lib to item 1 of (choose from list all_Libs with prompt "Choose the Library to Merge into:") --Select the final resting place for the soon to be merged library.
with timeout of weeks seconds --Depending on the size of your disc, this stuff is going to take awhile.
	do shell script "ditto -rsrc " & (quoted form of POSIX path of ip_Source) & space & (quoted form of POSIX path of ip_Dest) --First, copy everything on the disc to the Temporary Drive. Time consuming, but not as much as what is coming up later. Better wait a few minutes before you run off.
	tell application "Finder"
		set iphl to every folder of folder ip_Dest as Unicode text --We need to know the path of the destination for iPhoto Library Manager to make a new library
		eject disk ip_Source --need to eject disc here, since every time iPhoto launches during the later procedures, it will ALWAYS default to the disc library, regardless of what iPLM tells it to do.
	end tell
	tell application "iPhoto Library Manager"
		set new_Lib to make new library with properties {location:iphl, name:"Temporary"} --Location does not need to be in POSIX format, although the Location view in the iPLM GUI shows it that way.
		open new_Lib --This is also a time consuming step, especially on older discs, as iPhoto has to re-organize everything and write the new AlbumData.xml file. iPhoto will pop up a dialog box first, so you need to hang around until that happens, then you can go make a sandwich or watch some TV.
	end tell
	set xml_File to iphl & "AlbumData.xml" --This section is necessary for iPhoto to take the time to create the new "AlbumData.xml" file on the temporary drive. The Merge cannot function until that is finished. This repeat loop simply waits until the file has finished writing before allowing the next iPhoto Library Manager tell block to take over.
	repeat
		try
			alias xml_File
			exit repeat
		on error
			delay 10
		end try
	end repeat
	tell application "iPhoto Library Manager"
		merge (every library whose current is true) to library merge_Lib --Here is where the merge happens.
	end tell
end timeout
do shell script "rm -r " & (quoted form of POSIX path of ip_Dest) --removes the stuff from the temporary drive, making it ready for the next disc.
tell application "iPhoto Library Manager"
	open library merge_Lib --Need to swich to the merged library so that the old one can be deleted in the next line.
	delete library "Temporary" --Now that it has been merged, and the temporary drive data has been deleted, this libary needs to be removed.
end tell

OK, maybe it’s not such a simple script, but as long as you have been a good and careful photographer all these years, that merge library command is the ultimate power trip. It will preserve keywords, ratings, comments, original and modified images, exposure, date/time, and on and on. It is my opinion that this single command is what sets iPhoto Library Manager apart from any other iPhoto management product (or script) out there. It just works, and you can set it up however you want, either in the preferences pane, or via AppleScript.

On the other hand, if you have been a lazy photographer (like me) lo these many years, and you need to add keywords to your images, I have put together a little AppleScript Studio application called, iPhoto Reclaim 1.0) to help automate that. It requires the installation of Keyword Assistant as well as iPhoto Library Manager to function properly.

UPDATE
The script listed here works just fine as written. Since this was published, I have used both the script listed here and the iPhoto Reclaim 1.0 application (available at ScriptBuilders) to reclaim a large stack of CDs and DVDs of older iPhoto Libraries. Although they definitely sped up the process, I also ended up destroying an 8GB Mini Disk Drive about halfway through the discs. I ended up using a backup HD for the remaining discs, and had no problems at all. In fact, that drive was connected via FireWire and sped up the process even more. You should also know that iPhoto Reclaim will ONLY function under OS X 10.4.xx (Tiger) with iPhoto version 6.x. Keyword Assistant is no longer supported in the current (or future) version(s) of iPhoto.

Some Irritants

Of course, nobody is perfect. Here are a few things I found less than satisfying:

  1. The first time you create a new library, the save panel defaults to Documents. Of course, once you choose another folder (like say, Pictures), that is new default thereafter. A small detail, yes, but so many other small details in this product are good, this just seems missing.
    As of version 3.2.6, this became the default behavior

  2. Even with the Import preferences set correctly, the Merge function creates a bunch of Rolls when activated. It would be nice to have similar merge options to reduce the creation of all those Rolls.

  3. Although the Help section is EXTREMELY well written, I would prefer buttons that naturally go to the next topic when working through a procedure (like the aforementioned iPod folder creation).

  4. I created 2 iPod folders, but I am not sure that I can use more than one at a time. I like the variety, but perhaps some suggestions as to how to use multiple iPod folders would be nice.

Pipe Dreams

And, since I have committed myself to using this software in the future, here are some things I would like to see in coming versions:

  1. Although a small thing (as noted above), it would be nice to have the Pictures folder as the default for making a new library.
    As of version 3.2.6, this became the default behavior

  2. Thumbnail views of images without iPhoto being open. That is certainly possible; it can be done with Automator.

  3. Provide AppleScript access to the number of photos merged, imported, or skipped, as well as access to the final panel report, instead of requiring a mouse click to continue after a completed merge.

  4. Automatically locate and load iPhoto libraries on a machine or on connected drives. Although I think I came up with a nifty method, I am confident that Mr. Webster can do it better.

  5. A discounted pricing scheme for multiple licenses. Am I the only one that uses multiple Macs?

  6. A preference to automatically launch iPhoto with Radio button selected Library, without having to click the Launch or Relaunch iPhoto icon. The Import function proves that there is a difference between a library name being highlighted, and the radio button being clicked. Creating a preference that automatically launches the radio button selection would be smooth.

  7. Although I think Merge is a great function, I believe the future potential to be greater than the present form. It is handy to have the list of libraries to merge together on the left side of the merge window, but it would also be nice to have some information about how many images are in each Library. It would be REALLY cool to be able to merge albums from different libraries into a new library as well. Right now, you can only do that with drag and drop.

  8. iPhoto Library Manager Access to a disc library, although I understand that without the AlbumData.xml file, this is probably a real pipe dream, and will never be realized. I can certainly mention it though…

This is sort of off topic from the original post, but I thought I would share anyway.

I found this post while looking for some way to move iPhoto Events from one iPhoto Library to another. Unfortunately, if you turn on iPhoto sharing between computers, you cannot see events on the remote machine.

iPLM does a nice job of moving Events between libraries. You have to change the popup above the middle pane of iPLM from “Albums” in Library Name to “Events” in Library Name, then you can just drag the Event name onto the other Library in the fist pane of iPLM.

But is gets very tedious to compare what Events you have on each computer, so I wrote the script below that will compare two open libraries in iPhoto Library Manager. When the Dialog box comes up at the end, you can just go over to iPLM and drag the events missing in each from one library to the other.

if someone wants to get more ambitious, you could go the next step and script moving the events, which is why I made a list containing the roll numbers (the iPLM model refers to events as rolls). Script also needs basic stuff like handling errors if there are not two open libraries in iPLM or more than 2, but this works.

Using
iPhoto 09 version 8.1.2 (424)
iPLM Version 3.5.7 (3.5.7)




set Library1nameList to {}
set Library2nameList to {}
set in1not2names to {}
set in1not2rollNumber to {}
set in2not1names to {}
set in2not1rollNumber to {}



tell application "iPhoto Library Manager"
	tell library 1
		repeat with i from 1 to count of rolls
			tell roll i
				set end of Library1nameList to name
			end tell
		end repeat
	end tell
end tell

--return Library1nameList

tell application "iPhoto Library Manager"
	tell library 2
		repeat with i from 1 to count of rolls
			tell roll i
				set end of Library2nameList to name
			end tell
		end repeat
	end tell
end tell


repeat with rollNum from 1 to count of items of Library1nameList
	set n to item rollNum of Library1nameList
	if n is not in Library2nameList then
		set end of in1not2names to n
		set end of in1not2rollNumber to rollNum
	end if
end repeat



repeat with rollNum from 1 to count of items of Library2nameList
	set n to item rollNum of Library1nameList
	if n is not in Library1nameList then
		set end of in2not1names to n
		set end of in2not1rollNumber to rollNum
	end if
end repeat

set text item delimiters to return

display dialog "These events are in Library 1 and not library 2" & return & return & in1not2names & return & return & "These events are in Library 2 and not library 1" & return & return & in2not1names