Вот решение, но оно косвенное, потому что оно импортирует файл XML.
Сценарий создает файл XML, например экспортирует список воспроизведения из iTunes .
Когда сценарий завершает создание файла XML, он импортирует файл в iTunes, iTunes создает другой Smart Playlist с тем же именем, сценарий переключается на новый список воспроизведения и удаляет оригинал.
Работает также на несмежном отборе.
set b to false
tell application "iTunes"
set selTracks to selection
if (count selTracks) < 2 then return my displayAlert("Select 2 or more tracks")
set selPlaylist to container of item 1 of selTracks
try
tell selPlaylist to set b to special kind is none and smart is true
end try
if not b then return my displayAlert("Not a smart playlist")
set {oldFindexing, fixed indexing} to {fixed indexing, false}
set firstIndex to index of item 1 of selTracks
set fixed indexing to oldFindexing
--**** do something with these selections **********
set sortedTracks to reverse of selTracks -- ***** This example reverses the order. ********
end tell
my moveSelectedTracks(sortedTracks, selPlaylist, firstIndex)
on moveSelectedTracks(selT, selP, n)
script o
property tDataIDs : {}
property sTracks : selT
property tArgs2 : {}
end script
set L to {}
set tc to count o's sTracks
tell application "iTunes"
set o's tDataIDs to database ID of tracks of selP -- get id of the tracks in the playlist
set theID to persistent ID of selP
repeat with i from 1 to tc -- get id of the each sorted track
set item i of o's sTracks to "<key>" & (get database ID of (item i of o's sTracks)) & "<"
end repeat
end tell
set tc to count o's tDataIDs
--- make arguments
repeat with i from 1 to tc
if i = n then set o's tArgs2 to o's tArgs2 & o's sTracks
set t to "<key>" & item i of o's tDataIDs & "<"
if t is not in o's sTracks then set end of o's tArgs2 to t
end repeat
set {oTID, text item delimiters} to {text item delimiters, linefeed}
set o's tArgs2 to o's tArgs2 as text --convert a list to text (one argument per line)
set text item delimiters to oTID
set xmlLib to my get_iTunes_Library_xml() -- get path of "iTunes Library.xml"
set tFile to (path to temporary items as string) & "__xzaTemp_Playlist321__"
set tempF to quoted form of POSIX path of tFile
try --- write arguments to a temporary file
set openfile to open for access file (tFile & ".txt") with write permission
set eof of openfile to 0
write (o's tArgs2) to openfile starting at eof
close access openfile
on error err
try
close access file tFile
end try
return my displayAlert("Error when writing to a temporary file.\\n" & err)
end try
-- ** create the XML file, grep write the beginning of the xml File
do shell script "/usr/bin/grep -m1 -B40 ' <dict>' " & xmlLib & " > " & (tempF & ".xml")
(* append to the xmlFile:
grep read each argument and search track info in "iTunes Library.xml", perl clean up the output
grep search the info of the smart playlist and write it
sed change all arguments to array of dicts (this will be the order of each track in the playlist)
echo write the end of the xml File.
*)
do shell script "(tmp=" & tempF & ".txt; /usr/bin/grep -A62 -F -f \"$tmp\" " & xmlLib & " |/usr/bin/perl -pe 'undef $/; s|</dict> ((?:(?!</dict>).)*)\\n--|</dict>|sgx; s:</dict>(?!.*</dict>).*|</dict>\\s*</dict>\\s*<key>Playlists</key>.*:</dict>:sx;'; echo '</dict>\\n<key>Playlists</key><array>' ; /usr/bin/grep -m1 -A42 -B3 '>Playlist Persistent ID</key><string>" & theID & "<' " & xmlLib & " | /usr/bin/grep -m1 -B40 '<array>'; /usr/bin/sed 's:$:/integer></dict>:; s:^<key>:<dict><key>Track ID</key><integer>:' \"$tmp\" ; echo '</array></dict></array></dict></plist>') >> " & (tempF & ".xml")
set tFolder to ""
set b to false
tell application "iTunes"
set {tName, songRepeat} to {name, song repeat} of selP
add ((tFile & ".xml") as alias) -- import the XML file as Smart Playlist
try
set tFolder to parent of selP -- if the smart playlist is in a folder playlist
end try
set selP2 to last user playlist whose name is tName and its smart is true -- get the new smart playlist
if (persistent ID of selP2) is not theID then -- else no importation
if tFolder is not "" then move selP2 to tFolder -- move to the folder playlist
reveal (track n of selP2) -- select the same row in the imported playlist
try
tell current track to set {dataID, b} to {database ID, its container = selP}
end try
if b then -- the current track is in the smart playlist
set {tState, tPos} to {player state, player position}
play (first track of selP2 whose database ID = dataID) -- play the same track
set player position to (tPos + 0.4) -- same position
if tState = paused then
pause
else if tState is stopped then
stop
end if
set song repeat of selP2 to songRepeat -- this line doesn't work on iTunes 11
end if
delete selP -- delete the smart playlist (the original)
end if
end tell
do shell script "/bin/rm -f " & tempF & "{.txt,.xml} > /dev/null 2>&1 &" -- delete the temp files
end moveSelectedTracks
on get_iTunes_Library_xml()
do shell script "/usr/bin/defaults read com.apple.iApps iTunesRecentDatabases |/usr/bin/sed -En 's:^ *\"(.*)\"$:\\1:p' |/usr/bin/perl -MURI -e 'print URI->new(<>)->file;'"
return quoted form of the result
end get_iTunes_Library_xml
on displayAlert(t)
activate
display alert t
end displayAlert
Этот скрипт запускается (Mac OS X 10.4 ... 10.7
), (iTunes 7.5 ... 10.6.3
).
Скрипт не работает на старых версиях, я не знаю о новых версиях.
Я знаю:
Mountain Lion использует FreeBSD's grep
вместо GNU's grep
, grep во FreeBSD чрезвычайно медлен на Mountain Lion (в 30-100 раз медленнее, согласно тому, что я прочитал), поэтому этот скрипт также будет медленным
Tunes 11 разбивает команду AppleScript на song repeat
список воспроизведения. Значение song repeat
все еще можно прочитать с помощью get, его просто нельзя установить, поэтому комментируйте строку в скрипте.