############################################################################### # # itunes_open_library.pl # # This script will accept an argument for the path containing the iTunes Library. # It will edit the "iTunes Prefs.xml" file so that iTunes will open with that # Library. # # Copyright (C) 2007 Robert Jacobson # written by: Robert Jacobson (http://mysite.verizon.net/teridon/itunesscripts) # Last Updated: 29 Sep 2007 # Version 1.0 # # This script is GPL v2. see http://www.gnu.org/copyleft/gpl.html # ############################################################################### use File::Basename; my $PROGNAME = basename($0); my $VERSION = "1.0"; my $AUTHOR = "Robert Jacobson"; my $HOMEPAGE = "http://mysite.verizon.net/teridon/"; my $YEAR = 2007; my $GNU_URL = "http://www.gnu.org/copyleft/gpl.html"; { print "**************************************************************\n" . "$PROGNAME version $VERSION\n" . "Copyright (C) $YEAR $AUTHOR\n" . "Visit $HOMEPAGE for updates\n" . "$PROGNAME comes with ABSOLUTELY NO WARRANTY;\n". "This is free software, and you are welcome\n" . "to redistribute it under certain conditions\n" . "for details see $GNU_URL.\n" . "**************************************************************\n" . "\n" ; } use strict; use Win32::OLE; # use Win32::TieRegistry ( Delimiter=>"/" ); use XML::Simple; use MIME::Base64; use Encode; use Getopt::Std; my $DEBUG = 0; our($opt_d, $opt_b); getopts('db'); if ($opt_d) { $DEBUG = 1; } my $shell = Win32::OLE->new('WScript.Shell') or die Win32::OLE->LastError(); my $folder; # Ensure program was passed a valid iTunes Library location. if ($#ARGV < 0) { $shell->Popup("You must specify an iTunes Library folder as the first argument", undef, "$0 error", 0); exit; } else { # Check for valid folder $folder = $ARGV[0]; if ($folder !~ /default/i) { if (! -d "$folder" ) { $shell->Popup("The argument $folder is not a folder!", undef, "$0 error", 0); exit; } else { # Now check that folder has an 'iTunes Library.itl' file in it if (! -f "${folder}\\iTunes Library.itl") { $shell->Popup("The folder $folder is not an iTunes Library folder!", undef, "$0 error", 0); exit; } } } } # Exit iTunes if it is open my $WMI = Win32::OLE->GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2") or die Win32::OLE->LastError; my $query = $WMI->ExecQuery("Select * from Win32_Process Where Name = 'iTunes.exe'"); my @list = Win32::OLE::Enum->All($query); for my $item (@list) { my $name = (split(/\./,$item->Name()))[0]; $shell->AppActivate($name); $shell->SendKeys("%(fx)"); } # Wait for iTunes to exit completely while ($query->Count){ if ($DEBUG) {print "Waiting for iTunes to exit...\n";} sleep 1; $query = $WMI->ExecQuery("Select * from Win32_Process Where Name = 'iTunes.exe'"); } # # Find path to iTunes.exe # my $swKey= $Registry->{"LMachine/Software/"}; # my $iTunesPath = $swKey->{"Microsoft/Windows/CurrentVersion/App Paths/iTunes.exe"}->{"/"}; # if ($iTunesPath !~ "iTunes.exe") { # $shell->Popup("Could not find the path to iTunes.exe!", undef, "$0 error", 0); # exit; # } # Path to Preferences XML my $appdir = $ENV{'APPDATA'} . '\Apple Computer\iTunes'; my $file = $appdir . '\iTunesPrefs.xml'; if (! -f $file) { $shell->Popup("Could not find your iTunesPrefs.xml at path\n $file!", undef, "$0 error", 0); exit; } my $xs = XML::Simple->new( NormaliseSpace => 2, ); my $lib_key = "iTunes Library Location:1"; my $libxml_key = "iTunes Library XML Location:1"; my $xmlfile = "iTunes Library.xml"; my $xmlfile2 = "iTunes Music Library.xml"; # Check the current my $xml = $xs->XMLin($file) or die "could not find iTunesPrefs file: $!"; my $foundlib = 0; my $foundxml = 0; my $prefs_lib_path; my $prefs_xmllib_path; for my $dict ( @{$xml->{dict}->{dict}} ) { my $key = $dict->{key}; my $data = $dict->{data}; if (ref($key) eq 'ARRAY') { #print "sub:\n"; my $i = 0; foreach my $subkey (@{$key}) { #print "$subkey\n"; my $value = ${$data}[$i]; $value =~ s/\s+//g; #print "$value\n"; if ($subkey =~ /$lib_key/) { if ($DEBUG) {print "current library path data: $value\n";} $foundlib = 1; $prefs_lib_path = decode("UTF-16LE", decode_base64($value)); print "Library location is $prefs_lib_path\n"; } if ($subkey =~ /$libxml_key/) { if ($DEBUG) {print "current XML library path data: $value\n";} $foundxml = 1; $prefs_xmllib_path = decode("UTF-16LE", decode_base64($value)); print "XML Library location is $prefs_xmllib_path\n"; } $i++; } } } if (! $foundxml) { $shell->Popup("Could not find your XML Library location in file\n$file!", undef, "$0 error", 0); exit; } if ($folder =~ /default/i) { if (not $foundlib) { print "you specified default but it looks like it is already default!\n"; } else { &replace($folder); } } else { if ($foundlib && ($folder eq $prefs_lib_path) ) { # Do nothing, prefs already match file print "Library already set to $folder\n"; } else { &replace($folder); } } # Now open iTunes $shell->Run("iTunes.exe", 1, "false"); exit; sub replace { my $folder = shift; my $prefs_xmllib_path; if ($folder =~ /default/i) { $prefs_xmllib_path = $ENV{USERPROFILE} . "\\My Documents\\My Music\\iTunes\\$xmlfile"; if (! -f $prefs_xmllib_path) { # Try alternate $prefs_xmllib_path = $ENV{USERPROFILE} . "\\My Documents\\My Music\\iTunes\\$xmlfile2"; if ( ! -f $prefs_xmllib_path ) { $shell->Popup("Was going to set your XML Library location to file\n$prefs_xmllib_path\nbut it does not exist!", undef, "$0 error", 0); exit; } } } else { $prefs_xmllib_path = "$folder\\$xmlfile" ; } print "New Library location is $folder\\iTunes Library.itl\n"; print "New XML Location is $prefs_xmllib_path\n"; # Base-64 and UTF16-LE encode the folder path my $encoded = encode_base64(encode("UTF-16LE",$folder)); my $xml_encoded = encode_base64(encode("UTF-16LE",$prefs_xmllib_path)); # print "encoded data is\n--------\n$encoded\n--------\n"; undef($/); open (IN, $file) or die "could not open $file : $!"; my $data = ; close(IN); my $hex = $encoded; $hex =~ s#\s+##gs ; # print "encoded data is\n--------\n$hex\n--------\n"; my $outhex; # Replace newlines with newlines plus two tabs for (my $offset = 0; $offset < length($hex) ; $offset += 60) { $outhex .= "\t\t" . substr($hex, $offset, 60) . "\n"; } # print "outhex data is\n--------\n$outhex\n--------\n"; if ($folder =~ /default/i) { print "Removing iTunes Library location prefs\n(iTunes uses default location)...\n"; $data =~ s#\s+${lib_key}\s+\s+(.*?)##s ; } else { if ($foundlib) { # Replace existing key $data =~ s#${lib_key}\s+\s+(.*?)#${lib_key}\n\t\t\n$outhex\t\t#s ; } else { # Add key before $data =~ s#${libxml_key}#${lib_key}\n\t\t\n$outhex\t\t\n\t\t${libxml_key}#s ; } } #print "data is:\n$data\n"; my $xmlhex = $xml_encoded; $xmlhex =~ s#\s+##gs ; # print "encoded data is\n--------\n$xmlhex\n--------\n"; my $xmlouthex; # Replace newlines with newlines plus two tabs for (my $offset = 0; $offset < length($xmlhex) ; $offset += 60) { $xmlouthex .= "\t\t" . substr($xmlhex, $offset, 60) . "\n"; } # print "xmlouthex data is\n--------\n$xmlouthex\n--------\n"; $data =~ s#${libxml_key}\s+\s+(.*?)#${libxml_key}\n\t\t\n$xmlouthex\t\t#s ; if ($DEBUG) {print "data is:\n$data\n";} my $bak = $file . $$ . ".bak"; if ($opt_b) { print "Your old preferences file saved as $bak\n"; rename($file, $bak) or die "Could not rename current prefs: $!"; } open NEW, ">$file"; print NEW $data; close NEW; }