dougscripts.com

    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.

Site contents © 2001 - 2019 (that's right: 2001) Doug Adams and weblished by Doug Adams. Contact support AT dougscripts DOT com. About.
All rights reserved. Privacy.
AppleScript, iTunes, iPod, iPad, and iPhone are registered trademarks of Apple Inc. This site has no direct affiliation with Apple, Inc.
The one who says "it cannot be done" should not interrupt the one doing it.