如何通过 AppleScript 更改 iTunes 播放列表中歌曲的顺序

发布于 2024-09-30 05:08:13 字数 185 浏览 4 评论 0原文

如何使用 AppleScript 命令将播放列表中的歌曲移动到列表中的不同位置?

我已经有了歌曲和播放列表,并且其中一个已经在另一个中了;我只需要改变立场。

我的目标是对用户选择的曲目进行排序;理想情况下,我希望将按顺序排列的轨道移动到第一个选择的轨道的位置,并在按顺序排列的轨道之后立即按顺序对所有其他选定的轨道进行排序。

How can I move a song that's in a playlist to a different position within the list with an AppleScript command?

I already have the song and the playlist, and the one is already in the other; I need only to change the position.

My goal is to sort the tracks that the user has selected; ideally, I'd want to move the first-by-order track to the position of the first-in-selection track, and order all the other selected tracks immediately and sequentially after the first-by-order one.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

太阳公公是暖光 2024-10-07 05:08:14

move 命令看起来确实有很多错误。在我的实验中,似乎无论您将曲目移动到哪个位置,它都会将其移动到播放列表的末尾。尽管效率有点低,但这应该仍然是可以管理的。其语法如下所示:

tell application "iTunes"
move first track of playlist "foo" to end of playlist "foo"
end tell

您应该可以使用其他几种结构来代替“结束”,包括“播放列表“foo”的开始”、“播放列表“foo”的第 5 轨之后”之类的内容,以及“在播放列表“foo”的第 5 首曲目之前”,但这些似乎都没有按预期工作。但是,如果您基本上按照您想要的方式将曲目排序在列表中,您应该能够迭代该列表,告诉 iTunes 将每个曲目连续移动到播放列表的末尾,最后您会得到全部完成后排序。

The move command does appear to be pretty buggy. In my experimenting, it appears that no matter what location you give it to move a track to, it moves it to the end of the playlist. This should still be manageable though, if a bit inefficient. The syntax for this looks like:

tell application "iTunes"
move first track of playlist "foo" to end of playlist "foo"
end tell

There are several other constructions you're supposed to be able to use instead of "end of", including things like 'beginning of playlist "foo"', 'after track 5 of playlist "foo"', and 'before track 5 of playlist "foo"', but none of those appear to work as expected. But, if you basically get your tracks in a list sorted the way you want, you should be able to just iterate the list, tell iTunes to move each track in succession to the end of the playlist, and you'd end up with the sorted order after it's all done.

孤独陪着我 2024-10-07 05:08:14

这是一个解决方案,但它是间接的,因为它导入 XML 文件。

该脚本创建一个 XML 文件,例如从 iTunes 导出播放列表。
当脚本完成创建 XML 文件后,它会在 iTunes 中导入该文件,iTunes 创建另一个同名的智能播放列表,脚本切换到新的播放列表并删除原始播放列表。
它也适用于非连续选择。

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 的 grep 而不是 GNU 的 grep,FreeBSD 的 grep 在 Mountain Lion 上非常慢(根据数据,慢了 30 到 100 倍)我读过的内容),所以这个脚本也会很慢。

Tunes 11 打破了在播放列表中歌曲重复的 AppleScript 命令。 song Repeat 的值仍然可以用 get 读取,只是无法设置,所以在脚本中注释掉该行。

Here is a solution, but it's indirect, because it imports an XML file.

The script creates an XML file, such as export a playlist from iTunes.
When the script has finished creating the XML file, it imports the file in iTunes, iTunes creates another Smart Playlist with the same name, the script switch to the new playlist and delete the original.
It work also on non-contiguous selection.

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

This script run on (Mac OS X 10.4 ... 10.7) , (iTunes 7.5 ... 10.6.3).

The script doesn't work on older versions, I don't know about newer versions.


I know :

Mountain Lion use FreeBSD's grep instead of GNU's grep, FreeBSD's grep is extremely slow on Mountain Lion (30 to 100 times slower according to what I read), so this script will also be slow.

Tunes 11 breaks the AppleScript command to song repeat a playlist. The value of song repeat can still be read with get, it just can’t be set, so comments the line in the script.

断爱 2024-10-07 05:08:14

这是一个使用 GUI 脚本 的脚本。

但这种脚本很容易被破坏,具体取决于iTunes的版本或操作系统的版本。
用户必须调整延迟(取决于机器的速度)。
用户还必须更改脚本中的本地化标题。

该脚本适用于 iTunes 10.6.3Mac OS X 10.5.8,我不知道它是否适用于其他版本。

您必须通过单击通用访问系统首选项窗格中标有“启用辅助设备访问”的复选框来启用辅助功能框架

-- this script work on smart and user playlist
property selPlaylist : missing value
set b to false
tell application "iTunes"
    set oldV to (get version) as string < "11"
    activate
    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
        if oldV and class of front window is not in {browser window, playlist window} then --- no  playlist window on iTunes 11
            return my displayAlert("The front window is not a browser or a playlist window")
        else if class of front window is not browser window then
            return my displayAlert("The front window is not a browser window")
        end if
        tell selPlaylist
            set b to special kind is none
            set tShuffle to shuffle
            set isSmart to smart
        end tell
    end try
    if not b then return my displayAlert("This script will not work on special playlist")
    if tShuffle then return my displayAlert("This script will not work when shuffle is ON")

    set {sortOK, gridView, liveUpd} to my checkSortCol()
    if gridView then return my displayAlert("This script will not work on Grid View")
    if not sortOK then return my displayAlert("This script will not work when the sort column is not the 'status' column")
    if isSmart and liveUpd then return my displayAlert("You must uncheck the \"Live updating\" case, (Edit your Smart playlist)")

    --**** do something with these selections  **********
    set sortedTracks to reverse of selTracks -- ***** This example reverses the order. ********

    set dataID to database ID of item 1 of sortedTracks
    my moveSelectedTracks(item 1 of selTracks, sortedTracks, (count sortedTracks))
    reveal (track 1 of selPlaylist whose database ID is dataID)
end tell

on moveSelectedTracks(firstTrack, sortedT, n)
    tell application "System Events"
        tell process "iTunes"
            repeat with i from 1 to n
                my selectRow(item i of sortedT)
                keystroke "c" using command down --  copy track
                my selectRow(firstTrack)
                keystroke "v" using command down -- paste track
                delay 0.1
                tell front window to if subrole is "AXDialog" then click last button -- close dialog
            end repeat
            my selectRow(firstTrack)
            repeat with i from 1 to n
                keystroke "x" using command down -- cut track
                delay 0.1
                tell front window to if subrole is "AXDialog" then click last button -- close dialog
                delay 0.1
            end repeat
        end tell
    end tell
end moveSelectedTracks

on selectRow(i)
    tell application "iTunes" to reveal i
end selectRow

on checkSortCol() -- ****** "status" is the localized title, you need to change it according to your system language ******
    tell application "System Events"
        tell process "iTunes"
            if (exists radio group 2 of window 1) then return {true, true, true} -- grid view without outline
            set s to value of attribute "AXSortDirection" of (button "status" of group 1 of outline 1 of (last scroll area of window 1 whose group 1 of outline 1 is not missing value))

            set x to value of attribute "AXMenuItemMarkChar" of menu item 3 of menu of menu bar item 5 of menu bar 1 -- menu "as Grid"          
            set y to not (enabled of menu item 4 of menu of menu bar item 4 of menu bar 1) -- menu "Cut"
        end tell
    end tell
    return {s is not "AXUnknownSortDirection", x is not {"�"}, y}
end checkSortCol

on displayAlert(t)
    activate
    display alert t
end displayAlert

您必须取消选中智能播放列表上的“实时更新”,否则脚本将无法工作,因为“剪切”菜单项被禁用。
完成后您可以重新检查。

Here is a script that uses the GUI Scripting.

But this kind of script is easily broken depending on the version of iTunes or the version of the OS.
The user must adjust the delay (depending on the speed of the machine).
The user must also change the localized title in the script.

This script works on iTunes 10.6.3 and Mac OS X 10.5.8, I don't know if it works on other versions.

You must enable the Accessibility Frameworks by clicking the checkbox labeled "Enable access for assistive devices" in the Universal Access System Preference pane.

-- this script work on smart and user playlist
property selPlaylist : missing value
set b to false
tell application "iTunes"
    set oldV to (get version) as string < "11"
    activate
    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
        if oldV and class of front window is not in {browser window, playlist window} then --- no  playlist window on iTunes 11
            return my displayAlert("The front window is not a browser or a playlist window")
        else if class of front window is not browser window then
            return my displayAlert("The front window is not a browser window")
        end if
        tell selPlaylist
            set b to special kind is none
            set tShuffle to shuffle
            set isSmart to smart
        end tell
    end try
    if not b then return my displayAlert("This script will not work on special playlist")
    if tShuffle then return my displayAlert("This script will not work when shuffle is ON")

    set {sortOK, gridView, liveUpd} to my checkSortCol()
    if gridView then return my displayAlert("This script will not work on Grid View")
    if not sortOK then return my displayAlert("This script will not work when the sort column is not the 'status' column")
    if isSmart and liveUpd then return my displayAlert("You must uncheck the \"Live updating\" case, (Edit your Smart playlist)")

    --**** do something with these selections  **********
    set sortedTracks to reverse of selTracks -- ***** This example reverses the order. ********

    set dataID to database ID of item 1 of sortedTracks
    my moveSelectedTracks(item 1 of selTracks, sortedTracks, (count sortedTracks))
    reveal (track 1 of selPlaylist whose database ID is dataID)
end tell

on moveSelectedTracks(firstTrack, sortedT, n)
    tell application "System Events"
        tell process "iTunes"
            repeat with i from 1 to n
                my selectRow(item i of sortedT)
                keystroke "c" using command down --  copy track
                my selectRow(firstTrack)
                keystroke "v" using command down -- paste track
                delay 0.1
                tell front window to if subrole is "AXDialog" then click last button -- close dialog
            end repeat
            my selectRow(firstTrack)
            repeat with i from 1 to n
                keystroke "x" using command down -- cut track
                delay 0.1
                tell front window to if subrole is "AXDialog" then click last button -- close dialog
                delay 0.1
            end repeat
        end tell
    end tell
end moveSelectedTracks

on selectRow(i)
    tell application "iTunes" to reveal i
end selectRow

on checkSortCol() -- ****** "status" is the localized title, you need to change it according to your system language ******
    tell application "System Events"
        tell process "iTunes"
            if (exists radio group 2 of window 1) then return {true, true, true} -- grid view without outline
            set s to value of attribute "AXSortDirection" of (button "status" of group 1 of outline 1 of (last scroll area of window 1 whose group 1 of outline 1 is not missing value))

            set x to value of attribute "AXMenuItemMarkChar" of menu item 3 of menu of menu bar item 5 of menu bar 1 -- menu "as Grid"          
            set y to not (enabled of menu item 4 of menu of menu bar item 4 of menu bar 1) -- menu "Cut"
        end tell
    end tell
    return {s is not "AXUnknownSortDirection", x is not {"�"}, y}
end checkSortCol

on displayAlert(t)
    activate
    display alert t
end displayAlert

You must uncheck "Live updating" on the Smart Playlist, otherwise the script will not work because the "Cut" menu item is disabled.
You can recheck it after you have finished.

瀟灑尐姊 2024-10-07 05:08:14

由于您对 Philip Regan 的帖子的评论,我查看了 iTunes 中的移动命令,它说它用于移动播放列表,所以它对您没有帮助。但是,您可以执行此操作,这基本上将在当前播放列表中按照您想要的方式重新创建播放列表顺序。

我在这里假设选择是连续的。如果不是,则必须调整此代码,但您可以使用这些想法来实现这一点。

注意:您必须输入一些代码来对选择进行排序,因为我无法真正从您的描述中得知您想要如何对选择进行排序。将该代码放在我标记为“在此进行排序”的区域中。其余代码应该按原样工作。

我希望这会有所帮助...祝你好运。

-- this is only tested on music tracks, not apps or books etc.
-- do not use this code on your main music library

-- this will sort the selected tracks
-- insert sorting code here: DO YOUR SORTING HERE
-- now the sorting code just reverses the order of the selection

-- it works by getting references of the songs in your playlist from the main library, sorting that,
-- then deleting the tracks from the current playlist and recreating the playlist from the references

tell application "iTunes"
    -- get the selection
    set selectedTracks to the selection
    set selectionCount to count of selectedTracks
    if selectionCount is 0 then
        error "Error: Nothing is selected!"
    else if selectionCount is 1 then
        error "Error: There is nothing to sort because only 1 item is selected!"
    end if

    -- store the player state
    try
        set currentPlaylist to current playlist
    on error
        play
        pause
        set currentPlaylist to current playlist
    end try
    try
        set currentTrack to current track
        set currentTrackID to persistent ID of currentTrack
        set currentTime to player position
        set currentState to player state
    on error
        set currentState to false
    end try

    -- are we in the right type of playlist?
    if (special kind of currentPlaylist is not none) or (smart of currentPlaylist) then
        error ("Error: we cannot use this code on playlist " & name of currentPlaylist & "!")
    end if

    -- is the selection in the current playlist?
    set firstSelectedTrack to item 1 of selectedTracks
    set firstSelectedTrackID to persistent ID of firstSelectedTrack
    try
        first track of currentPlaylist whose persistent ID is firstSelectedTrackID
    on error
        error "Error: the selected tracks are not in the current playlist, so this code won't work!"
    end try

    -- are we dealing with music tracks?
    if class of firstSelectedTrack is not file track then error "Error: this code is only tested on music file tracks!"

    (****** DO YOUR SORTING HERE *********)
    -- sort your selected tracks in a list however you need
    -- in this case I'm just reversing the order for simplicity
    set sortedSelection to reverse of selectedTracks
    (*************************************)

    -- figure out the index of the first selected track out of the entire playlist
    set playlistTracks to tracks of currentPlaylist
    repeat with i from 1 to count of playlistTracks
        if (item i of playlistTracks) is firstSelectedTrack then exit repeat
    end repeat

    -- now we make one big list of the sorted playlist
    set tracksBeforeSelection to {}
    set tracksAfterSelection to {}
    try
        set tracksBeforeSelection to items 1 thru (i - 1) of playlistTracks
    end try
    try
        set tracksAfterSelection to items (i + selectionCount) thru end of playlistTracks
    end try
    set finalTrackList to tracksBeforeSelection & sortedSelection & tracksAfterSelection

    -- now we get references to all these tracks from the main library so we can delete the playlist and reorganize it
    set finalTrackListRefs to {}
    repeat with aTrack in finalTrackList
        set trackID to persistent ID of aTrack
        set refTrack to (first track of library playlist 1 whose persistent ID is trackID)
        set end of finalTrackListRefs to refTrack
    end repeat

    -- remove all the tracks from the playlist
    delete tracks of currentPlaylist

    -- put the playlist back in the new order
    repeat with aTrack in finalTrackListRefs
        duplicate aTrack to currentPlaylist
    end repeat

    -- restore the player state
    if currentState is playing then
        play (first track of currentPlaylist whose persistent ID is currentTrackID)
        set player position to currentTime
    end if
end tell

Because of your comment to Philip Regan's post, I looked at the move command in iTunes and it says it's for moving playlists, so it won't help you. However you can do this which will basically recreate the playlist order how you want in the current playlist.

I assume here that the selection is sequential. If it's not this code will have to be adjusted but you can use these ideas to accomplish that.

NOTE: you have to put in some code to do your sorting of the selection because I can't really tell how you want to sort the selection from your description. Put that code in the area I have marked "DO YOUR SORTING HERE". The rest of the code should work as-is.

I hope this helps... good luck.

-- this is only tested on music tracks, not apps or books etc.
-- do not use this code on your main music library

-- this will sort the selected tracks
-- insert sorting code here: DO YOUR SORTING HERE
-- now the sorting code just reverses the order of the selection

-- it works by getting references of the songs in your playlist from the main library, sorting that,
-- then deleting the tracks from the current playlist and recreating the playlist from the references

tell application "iTunes"
    -- get the selection
    set selectedTracks to the selection
    set selectionCount to count of selectedTracks
    if selectionCount is 0 then
        error "Error: Nothing is selected!"
    else if selectionCount is 1 then
        error "Error: There is nothing to sort because only 1 item is selected!"
    end if

    -- store the player state
    try
        set currentPlaylist to current playlist
    on error
        play
        pause
        set currentPlaylist to current playlist
    end try
    try
        set currentTrack to current track
        set currentTrackID to persistent ID of currentTrack
        set currentTime to player position
        set currentState to player state
    on error
        set currentState to false
    end try

    -- are we in the right type of playlist?
    if (special kind of currentPlaylist is not none) or (smart of currentPlaylist) then
        error ("Error: we cannot use this code on playlist " & name of currentPlaylist & "!")
    end if

    -- is the selection in the current playlist?
    set firstSelectedTrack to item 1 of selectedTracks
    set firstSelectedTrackID to persistent ID of firstSelectedTrack
    try
        first track of currentPlaylist whose persistent ID is firstSelectedTrackID
    on error
        error "Error: the selected tracks are not in the current playlist, so this code won't work!"
    end try

    -- are we dealing with music tracks?
    if class of firstSelectedTrack is not file track then error "Error: this code is only tested on music file tracks!"

    (****** DO YOUR SORTING HERE *********)
    -- sort your selected tracks in a list however you need
    -- in this case I'm just reversing the order for simplicity
    set sortedSelection to reverse of selectedTracks
    (*************************************)

    -- figure out the index of the first selected track out of the entire playlist
    set playlistTracks to tracks of currentPlaylist
    repeat with i from 1 to count of playlistTracks
        if (item i of playlistTracks) is firstSelectedTrack then exit repeat
    end repeat

    -- now we make one big list of the sorted playlist
    set tracksBeforeSelection to {}
    set tracksAfterSelection to {}
    try
        set tracksBeforeSelection to items 1 thru (i - 1) of playlistTracks
    end try
    try
        set tracksAfterSelection to items (i + selectionCount) thru end of playlistTracks
    end try
    set finalTrackList to tracksBeforeSelection & sortedSelection & tracksAfterSelection

    -- now we get references to all these tracks from the main library so we can delete the playlist and reorganize it
    set finalTrackListRefs to {}
    repeat with aTrack in finalTrackList
        set trackID to persistent ID of aTrack
        set refTrack to (first track of library playlist 1 whose persistent ID is trackID)
        set end of finalTrackListRefs to refTrack
    end repeat

    -- remove all the tracks from the playlist
    delete tracks of currentPlaylist

    -- put the playlist back in the new order
    repeat with aTrack in finalTrackListRefs
        duplicate aTrack to currentPlaylist
    end repeat

    -- restore the player state
    if currentState is playing then
        play (first track of currentPlaylist whose persistent ID is currentTrackID)
        set player position to currentTime
    end if
end tell
萌面超妹 2024-10-07 05:08:14

您不能直接执行此操作,因为字典显示播放列表中曲目的 index 属性是仅获取的,而不是获取/设置的。

我看到的解决这个问题的唯一方法是创建一个新的播放列表,按照您希望的顺序将曲目移动到新的播放列表中,然后丢弃旧的播放列表。

You can't do that directly because the Dictionary shows the index property of a track in a playlist is get-only, not get/set.

The only way I see around this would be to create a new playlist, move the tracks into the new one in the order you want them to be in, then trash the old one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文