Keeping iTunes Lists in Sync

Since switching over to iTunes as a media manager, one my my never ending challenges has been to maintain media directories for Tivo integration via PyTivo. My first project in this regard was AtomicSage; however, this is unable to synchronize iTunes playlists with my media share.

Using AtomicSage together with AtomicParsely, my media directory is kept up to date when video content is added to my iTunes library. However, I have historically maintained a *NOW SHOWING* sub-directory for Tivo where unwatched videos are listed and there isn’t an easy way to keep this in sync with unwatched content in iTunes.

My first attempt at this will be using an AppleScript that extracts selected videos from iTunes and then this list is queried from a short Perl script. Doug Adam’s has a nearly perfect script for doing this – Export Selected Tracks to XML. After setting this up in my iTunes script directory, I then pieced together this little script for converting the resulting XML into symbolic links on my server filesystem.

#!/usr/bin/perl
#
# Script to link unwatched movie extract from iTunes.
# User "Export Selected Tracks to XML" from Doug Adams
# to generate the file:
#
# http://dougscripts.com/itunes/scripts/ss.php?sp=exportselectedtracksxml
#
# AUTHOR: Eric W. Sarjeant <[email protected]>
# DATE: 30-JUN-2013
#
use XML::XPath;
use XML::XPath::XMLParser;
use URI::Escape;
use File::Basename;

my $parser = new XML::XPath->new(filename=>"unwatched.xml");

my $iTunesUri='file://localhost/Volumes/Videos';
my $iTunesPath='/export/video';
my $TivoPath='/tivo/Movies';

# cleanup existing directory
my $TivoDir = $TivoPath . '/*NOW SHOWING*';
opendir (DIR, $TivoDir) or die $!;

while (my $file = readdir(DIR))
{
  next unless (-f "$TivoDir/$file");
  next unless ($file =~ m/\.m4v$/);
  unlink ("$TivoDir/$file");
}

closedir(DIR);

# enumerate all file references - this is a little funky
# find key=Location and the next is a filepath
my $nodeset = $parser->find("//dict/key[text()='Location']/following-sibling::string[1]");

foreach my $node ($nodeset->get_nodelist)
{
  my $srcpath = uri_unescape($node->string_value);
  $srcpath =~ s/$iTunesUri/$iTunesPath/;

  my $basefile = basename($srcpath);
  my $destpath = "$TivoDir/$basefile";

  next unless ($destpath =~ m/\.m4v$/);
  print $srcpath . " -> " . $destpath . "\n";
  link ($srcpath, $destpath);

}

The idea behind this setup is my iTunes media folder is on the same Linux file server that is running the PyTivo service. This can be accomplished using NFS of course, although given the limited resources needed to run PyTivo and share some directories you should be able to do this on most modern PC workstations.

You may need a few dependencies for doing this, XPath is not included by default. To install this using CPAN:

perl -MCPAN -e 'install XML::XPath'

As far as I can remember, this was the only Perl module that I had to install. Feel free to adapt this script to whatever your needs might be, most of the path settings can be adjusted at the top of the file.