Access iTunes On A Remote Machine
If you've got the name, password, and IP of a remote machine on your network, accessing its copy of iTunes and music files is pretty easy.
Step 1: Setting Up the Remote Machine
The remote machine must have "Remote Apple Events" checked in the Sharing Pane of its System Preferences. This permits remote machines to send it commands. It isn't neccessary for the local machine to be set this way (but it does seem only fair).
The iTunes application on the remote machine must already be activated in order for an AppleScript on the local machine to control it. I couldn't get it to activate via a remote script. Also, you can't have the remote machine going to sleep otherwise the connection will be cut off. Screen Effects are OK, however.
Start iTunes and then scurry back to the local machine and we can get started. (Make sure you turn the volume up on the remote machine. Once you get the upcoming script going you will know you're actually making the remote iTunes do something. If your spouse is using the remote machine, then you will know from their irritable calls of "Knock it off!" that you have succeeded. That's how it works at my house.)
Step 2: The AppleScript
This first basic script will contain everything you need to access control of the remote iTunes. First, you must know the remote machine's administrator's username and user password and the IP address or Rendezvous name (somename.local) of the remote machine. You can get the IP address from the Sharing pane of the remote machine's System Preferences. Select the File Sharing Service, put a check in its "On" checkbox, and it will display the IP address; it will look something like "192.168.2.1". You don't have to leave File Sharing turned On once you get the IP address unless you want to.
Supply the appropriate info to the first line of the code below and you've got a remote iTunes player:
-- change this to your info:
set remMachine to "eppc://username:userpass@remote_ip"
using terms from application "iTunes"
try
tell application "iTunes" of machine remMachine
playpause
end tell
on error errM number errN
display dialog (errM & space & errN)
end try
end using terms from
Pretty basic. I put everything in a try-error block because you Just Never Know What Can Happen.
Here's one that displays a menu of remote playlists and lets you select and play one—this will definitely annoy the Spouse by stealth:
global allRemPlaylists, remMachine
-- change this to your info:
set remMachine to "eppc://username:userpass@remote_ip"
-- get list of remote iTunes playlists...
tell me to getRemPlaylists()
-- select one to play...
set thisPlaylist to (choose from list allRemPlaylists with prompt "Select a playlist...")
-- play it!
if thisPlaylist is not false then
set thisPlaylist to thisPlaylist as string
tell me to playRemPlaylist(thisPlaylist)
end if -- done
--
to getRemPlaylists()
using terms from application "iTunes"
try
tell application "iTunes" of machine remMachine
set allRemPlaylists to (get name of user playlists)
end tell
on error errM number errN
display dialog (errM & space & errN)
end try
end using terms from
end getRemPlaylists
to playRemPlaylist(thisPlaylist)
using terms from application "iTunes"
try
tell application "iTunes" of machine remMachine
play playlist thisPlaylist
end tell
on error errM number errN
display dialog (errM & space & errN)
end try
end using terms from
end playRemPlaylist
The script above uses subroutines so that the action happening with the remote iTunes is kept isolated from what's going on on the local machine. Particularly, the choose from list command in the run handler is performed on the local machine, the subroutines are performed on the remote machine.
Now of course, the biggie: can you access files on the remote machine? Sure.
The location property contains the filepath of a track. Apple has removed the location property from the shared track class. But you can still identify a remote track by matching the name, artist, album, and size of the shared track (properties available from the shared track on the local machine) with a track on the remote machine. Then get the remote track's location—it's a file track on the remote machine. Send that filepath back to the local machine and you're in business.
This script will add the currently playing shared track to your iTunes. It will also copy the file to your iTunes Music folder (again, you must fill in the required info):
global remMachine, theAFP, covetedTrack
-- change this to your info:
set remMachine to "eppc://username:userpass@remote_ip"
set theAFP to "afp://username:userpass@remote_ip"
set remStartDisk to my getRemStartDisk()
mount volume (theAFP & remStartDisk)
tell application "iTunes"
if player state is not stopped and class of current track is shared track then
tell current track to set {nom, alb, art, siz} to {name, album, artist, size}
try
with timeout of 300 seconds
tell me to getLocationOfSharedTrack(nom, alb, art, siz)
display dialog "Copy \"" & nom & "\" by " & art & " from " & alb & " to this computer?" default button 2
add alias covetedTrack
end timeout
end try
end if
end tell
--
to getRemStartDisk()
using terms from application "Finder"
tell application "Finder" of machine remMachine
return (get name of startup disk)
end tell
end using terms from
end getRemStartDisk
to getLocationOfSharedTrack(nom, alb, art, siz)
using terms from application "iTunes"
try
tell application "iTunes" of machine remMachine
if exists (some file track of library playlist 1 whose name is nom and album is alb and artist is art and size is siz) then
set covetedTrack to (get location of (some file track of library playlist 1 whose name is nom and album is alb and artist is art and size is siz)) as string
end if
end tell
on error errM number errN
display dialog (errM & space & errN)
end try
end using terms from
end getLocationOfSharedTrack
This should run as a compiled script. And a couple of caveats. First, this script makes the assumption that the remote iTunes keeps its Music folder on its startup disk. In order to copy files from the remote computer, the volume those files are on has to be mounted on the local machine. You may have to hardcode the location and mount the correct volume. Also this script has hardly any error checking. Some tweaking may be in order.
It is a simple next step to move the selected shared tracks from the remote machine to the local machine. You can use the two subroutines from the script above and we'll add a new run handler that works with the selected tracks. Select some shared tracks listed on the local machine's iTunes and run this script:
global remMachine, covetedTrack
-- change this to your info:
set remMachine to "eppc://username:userpass@remote_ip"
set theAFP to "afp://username:userpass@remote_ip"
set remStartDisk to my getRemStartDisk()
mount volume (theAFP & remStartDisk)
tell application "iTunes"
if selection is not {} then
set sel to a reference to selection
repeat with s from 1 to count sel
set theST to item s of sel
if (get class of theST) is shared track then
try
with timeout of 300 seconds
tell theST to set {nom, alb, art, siz} to {name, album, artist, size}
tell me to getLocationOfSharedTrack(nom, alb, art, siz)
add alias covetedTrack
end timeout
end try
end if
end repeat
end if
end tell
--
to getRemStartDisk()
using terms from application "Finder"
tell application "Finder" of machine remMachine
return (get name of startup disk)
end tell
end using terms from
end getRemStartDisk
to getLocationOfSharedTrack(nom, alb, art, siz)
using terms from application "iTunes"
try
tell application "iTunes" of machine remMachine
if exists (some file track of library playlist 1 whose name is nom and album is alb and artist is art and size is siz) then
set covetedTrack to (get location of (some file track of library playlist 1 whose name is nom and album is alb and artist is art and size is siz)) as string
end if
end tell
on error errM number errN
display dialog (errM & space & errN)
end try
end using terms from
end getLocationOfSharedTrack
But wait, there's more.
If you know that iTunes is running on a remote machine, you can see what track is playing (it might even be one of yours being shared from the local machine):
global remMachine, myTrack, myPlaylist
-- change this to your info:
set remMachine to "eppc://username:userpass@remote_ip"
set myTrack to {}
set myPlaylist to ""
tell me to see_shared_info()
if myTrack is not {} then
set {nom, art, alb, siz} to myTrack
if myPlaylist is not "" then set myPlaylist to ("in playlist \"" & myPlaylist & "\"")
try
with timeout of 30 seconds
display dialog ("\"" & remMachine & "\" is listening to" & return & return & nom & return & "by " & art & return & "from " & alb & return & myPlaylist) buttons {"Thanks"} default button 1 giving up after 30
end timeout
end try
end if
to see_shared_info()
using terms from application "iTunes"
try
tell application "iTunes" of machine remMachine
if player state is not stopped then
set myPlaylist to (get name of current playlist)
tell current track
set myTrack to {name, artist, album, size}
end tell
end if
end tell
on error errM number errN
display dialog (errM & space & errN)
end try
end using terms from
end see_shared_info
I left the size/siz variable available so that a future version of this script could determine if/which track on the local machine (ie, my machine) is being played on the other machine (see the next example). WIth that info I can determine its location (filepath) and/or database id. For example, a Stay-Open app version of the script above could monitor a specific remote machine's iTunes and update the play count locally.
An iPodlounge correspondent asked how to raise/lower the rating of a shared track (he's listening on his laptop as the local machine, a desktop is the remote machine):
global remMachine
-- change this to your info:
set remMachine to "eppc://username:userpass@remote_ip"
tell application "iTunes"
if player state is not stopped and class of current track is shared track then
tell current track to set {nom, alb, art, siz} to {name, album, artist, size}
set rate to button returned of (display dialog "Add or Subtract a Rating star to \"" & nom & "\"" buttons {"Cancel", "Subtract", "Add"})
try
with timeout of 300 seconds
tell me to getSharedTrack(nom, alb, art, siz, rate)
end timeout
end try
end if
end tell
--
to getSharedTrack(nom, alb, art, siz, rate)
using terms from application "iTunes"
try
tell application "iTunes" of machine remMachine
if exists (some file track of library playlist 1 whose name is nom and album is alb and artist is art and size is siz) then
set theTrack to (some file track of library playlist 1 whose name is nom and album is alb and artist is art and size is siz)
tell theTrack
if rate is "Subtract" then
if rating is not 0 then set rating to (get rating - 20)
else if rating is not 100 then
set rating to (get rating + 20)
end if
end tell
end if
end tell
on error errM number errN
display dialog (errM & space & errN)
end try
end using terms from
end getSharedTrack
Notice that this script identifies the current shared track—theTrack in the subroutine—so that you can perform commands on it.
For more, visit the Network category of scripts, and remember: Don't Steal Music. The presumption here is that you can only access a remote machine if you have access to the administrative priviledges; Q.E.D., you are the administrator and the files are yours. These scripts are provided for private use and the edification of AppleScript users and are not intended as a means of illegal file sharing or circumventing copyright laws.
ADDENDA - A couple of correspondents have pointed out that the lines which check for the existence of a remote track before actually performing tasks with the remote track are superfluous. True enough; if the track exists in the shared playlist then it must already exist, right? One correspondent chopped the processing time in half by removing those lines and moving right to the task required.
November 16, 2003
updated November 19, 2003
updated November 21, 2003
updated December 17, 2003