- Make remote playlist
Select shared tracks and create a new playlist for them on the remote iTunes.
Using the get_login_info() handler it is now very easy to send a variety of AppleScript commands to a particular remote user's iTunes application using osascript via ssh.
In this section, I'll create a script that enables me to copy a batch of selected shared tracks to a newly created playlist on the remote machine. This might be too invasive if the remote user doesn't like the idea of new playlists suddenly showing up. However, if the local machine and the remote machine are both yours, you probably won't care. (If you need to cover your tracks--no pun intended--the next section will describe a script to delete remote playlists.)
The script will get the selected shared tracks locally, create a new playlist on the remote iTunes, and then locate the selected tracks on the remote iTunes and duplicate them to the playlist just created.
The script starts with the usual declared property and globals; add a new playPID global. And then the "get selected tracks/get name of shared library" routine we have used previously:
property defaultsDomain : "com.dougscripts.copyshared" -- no spaces global remUserName, remHostIPAddr, remAddr global sel, sharedLibName, playlistName, playPid tell application "iTunes" set sel to selection if sel is {} then display dialog "No tracks selected." buttons {"Cancel"} default button 1 with icon 0 return else set t1 to item 1 of sel if (get class of t1 is shared track) then set sharedLibName to (get name of container of container of t1) else display dialog "No shared tracks selected." buttons {"Cancel"} default button 1 with icon 0 return end if end if my get_login_info() end tell -- == end run -- == handlers = == == == to get_login_info() try set {remUserName, remHostIPAddr} to my read_defaults(sharedLibName) on error m number n if n is in {1, -1728} then -- get username for sharedLibName set remUserName to text returned of (display dialog ¬ "Enter the username associated with the shared library \"" & ¬ sharedLibName & "\":" default answer "") -- get ip address for sharedLibName set remHostIPAddr to text returned of (display dialog ¬ "Enter the IP address associated with the shared library \"" & ¬ sharedLibName & "\":" default answer "") my write_defaults(sharedLibName, {remUserName, remHostIPAddr}) else -- some other error; abort log m log n error number -128 end if end try set remAddr to (remUserName & "@" & remHostIPAddr) as text end get_login_info on write_defaults(k, l) do shell script "defaults write " & defaultsDomain & space & ¬ quoted form of k & " -array " & (("'") & my list_to_text(l, "' '") & ("'")) end write_defaults on read_defaults(k) return paragraphs of (do shell script (("defaults read " & defaultsDomain & space & ¬ quoted form of k) & space & "| grep ' '|sed -e 's/ //g' -e's/\"//g' -e's/\\,//g'")) end read_defaults to escape_single_quotes(x) return my replace_chars(x, "'", "'\\''") as text end escape_single_quotes on replace_chars(txt, srch, repl) set AppleScript's text item delimiters to the srch set the item_list to every text item of txt set AppleScript's text item delimiters to the repl set txt to the item_list as string set AppleScript's text item delimiters to "" return txt end replace_chars on list_to_text(theList, delim) set saveD to AppleScript's text item delimiters try set AppleScript's text item delimiters to {delim} set txt to theList as text on error errStr number errNum set AppleScript's text item delimiters to saveD error errStr number errNum end try set AppleScript's text item delimiters to saveD return (txt) end list_to_text
This much of the script will give us a list of selected tracks and establish the login stuff we need for ssh.
Note that I will use the same .plist file for the defaults commands as I used in the previous project. If you didn't create that file with that project it will be created when you run the final version of this script the first time. You can change the defaultsDomain string to something more generic if you like, eg: "com.myusername.sshhandshake".
Now, we need to ask for a name for the new playlist we will create on the remote iTunes. This routine is similar to the one used in the previous project. It goes right after the call to get_login_info() within the iTunes tell block so that the display dialog displays in iTunes:
-- == get a name for the new playlist set playlistName to "" set defAns to (t1's artist & " - " & t1's album) as text set ddResult to (display dialog "Put new tracks in playlist named:" default answer defAns ¬ buttons {"Cancel", "OK"} default button 2) if text returned of ddResult is not "" and button returned of ddResult is "OK" then set playlistName to my escape_single_quotes(text returned of ddResult) else -- (will cancel on empty string returned) return end if
Be sure to include the escape_single_quotes() handler. Any single-quotes in the playlist name entered have to be escaped for the "make user playlist" osascript that will be ssh'd in this handler:
to make_rem_playlist() try set osaCom to quoted form of ¬ ("osascript -e 'tell application \"iTunes\"' -e 'return persistent id of (make user playlist with properties {name:\"" & playlistName & "\"})' -e 'end tell'") set playPid to (do shell script ("ssh " & remAddr & space & osaCom)) return true on error return false end try end make_rem_playlist
Ultimately, this handler creates a new playlist on the remote user's iTunes with the supplied name and sets the playPID global variable with the persistent ID of the new playlist. If this process works without error then the handler returns true, otherwise it returns false; when we call this handler we will proceed with the rest of the script if true is returned. The full listing will show the context.
Now, why do we need the persistent ID of the new playlist?
I do not always recommend referencing a playlist by name. It can change. Or, there could be several playlists with the same name. I know this is unlikely. But the fact is a playlist's persistent ID is the only way to consistently identify it correctly. (An instance when we can't use the persistent ID is in the next section on deleting a remote playlist.)
Once the new playlist is created on the remote side, this handler will copy a track to it; pid is the persistent ID of a track:
to dupe_to_new_playlist(pid) try with timeout of (1 * days) seconds set osaCom to quoted form of ¬ ("osascript -e 'tell application \"iTunes\"' -e 'duplicate (some track of library playlist 1 whose persistent id is \"" & pid & "\") to some playlist whose persistent id is \"" & playPid & "\"' -e 'end tell'") do shell script ("ssh " & remAddr & space & osaCom) end timeout on error m number n log m log n end try end dupe_to_new_playlist
We'll call this handler within a repeat loop that iterates through each of the selected tracks. The complete listing is on the next page.
Just one thing:
The remote user's iTunes must be set to allow all playlists to be shared (iTunes > Preferences > Shared), otherwise a new one won't show up in the local SHARED playlists.