AppleScript使用文本文件作为源将iTunes中的多个曲目添加到播放列表中

时间:2016-09-11 06:13:21

标签: applescript itunes playlist property-list

我有一个iTunes播放列表,我以前备份到一个文本文件中,格式如下:

"标题","艺术家","曲目编号","专辑"

我使用其中四首曲目创建了一个示例文件:

" Ritual"," Chick Corea Elektric Band II"," 9"," Paint The World"
"风险"," Deftones"," 9"," Diamond Eyes"
" Risveglio酒店""精"" 10"" Zombi"
" Ritual"," Ashes Divide"," 8","继续告诉自己它好吧"

此播放列表中的所有曲目目前都在iTunes中。我想使用AppleScript将这些曲目中的每一个添加到播放列表中。我已经能够使用以下AppleScript对单个项目(例如:标题)进行此操作:

-- set variables
set srcFile to "/Users/kjesso/Documents/=Scripting=/AppleScript/ipod_gym_playlist_track_names_sample.txt"
set allRecords to paragraphs of (read srcFile as «class utf8»)
set myPlaylist to "Test"
property okflag : false

-- check if iTunes is running
tell application "Finder"
    if (get name of every process) contains "iTunes" then ¬
        set okflag to true
end tell
if okflag then
    -- if iTunes is running then do this
    tell application "iTunes"
        repeat with aRecord in allRecords
            set results to (every file track of playlist "Library" whose name is aRecord)
            repeat with aTrack in results
                duplicate aTrack to playlist myPlaylist
            end repeat
        end repeat
    end tell
else
    -- if iTunes is not running do this
    return "Unable to execute because iTunes is not running"
end if

然而,如果从不同的艺术家找到重复的曲目标题,它将只采取第一首曲目,因为该剧本不能区分不同的艺术家,只有"标题"作为内容。数组是否在AppleScript中原生存在?

我认为这需要使用Property List文件完成?在进一步在线阅读,试图创建一个阵列来做我想做的事情(捕捉曲目标题,艺术家,专辑等),我遇到了各种线程like this,说明最好使用一个属性列表?我试图实现与here类似的功能,但不是将输出发送到CSV文件,而是将其发送到iTunes中的播放列表。

如果我需要使用属性列表来实现我的目标,我创建了以下示例属性列表文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>title</key>
    <string>"Ritual"</string>
    <key>artist</key>
    <string>"Chick Corea Elektric Band II"</string>
    <key>album</key>
    <string>"Paint The World"</string>
</dict>
<dict>
    <key>title</key>
    <string>"Risk"</string>
    <key>artist</key>
    <string>"Deftones"</string>
    <key>album</key>
    <string>"Diamond Eyes"</string>
</dict>
<dict>
    <key>title</key>
    <string>"Risveglio"</string>
    <key>artist</key>
    <string>"Goblin"</string>
    <key>album</key>
    <string>"Zombi"</string>
</dict>
<dict>
    <key>title</key>
    <string>"Ritual"</string>
    <key>artist</key>
    <string>"Ashes Divide"</string>
    <key>album</key>
    <string>"Keep Telling Myself It's Alright"</string>
</dict>
</plist>

任何人对如何使其发挥作用有任何想法?

3 个答案:

答案 0 :(得分:1)

如果您希望选择不仅基于名称,还要基于艺术家,专辑...只需添加过滤器,如下例所示。

此外,您可能无需检查iTunes是否已打开。当脚本运行时,如果未启动iTunes,脚本将直接启动它。所以除非你真的不想让它自动打开iTunes,否则什么都不做。

通常,您无需参考特定的播放列表“库”。这是默认值。

set myPlaylist to "Test"
set {theTitle, theAlbum, theArtist} to {"Ritual", "Paint The World", "Chick Corea Elektric Band II"}

tell application "iTunes"
set myTracks to (tracks whose (name is theTitle) and (album is theAlbum) and (artist is theArtist))
duplicate (item 1 of myTracks) to playlist myPlaylist
end tell

我假设只有1个曲目匹配标题,专辑和艺术家(然后我拿到了第一个也找到了唯一的项目)。如果您不确定它是否足够,您可以在过滤器中添加其他内容(年份,持续时间......)。

关于plist或文本文件或记录列表,请记住,关键是您使用相同的方法来编写和读取文件。所以正确的问题是:你是怎么写这个文件的? (我猜不是手动!)

如果您正在使用其他脚本构建文件,则可以更轻松地保存和读取记录(一条记录= {title,album,artist})。除了在脚本中读取和写入之外,您将无需做任何事情。唯一的缺点是你将无法使用文本编辑器读取文件......但这是必需的吗?

在下面的示例中,脚本从txt文件读取(与您的示例相同),每行1个轨道,每个值用','分隔:

set textFile to choose file "Select your text file"
set myText to (paragraphs of (read textFile))
set AppleScript's text item delimiters to {","}
set myRecords to {}
repeat with aParagraph in myText
set MS to aParagraph as string
if (count of (text items of MS)) is 4 then
    set the end of myRecords to {text item 1 of MS, text item 2 of MS, text item 3 of MS, text item 4 of MS}
else
    -- skipt the record : invalid number of text item !
end if
end repeat

结果是myRecords列表,每条记录都是4个值的列表{title,artist,trackNo,album}

答案 1 :(得分:0)

我最终在this post的帮助下使用一维数组(列表)找到了解决方案。这是最终结果:

set srcFile to "/Users/kjesso/Documents/=Scripting=/AppleScript/ipod_mp3s_sample.csv"
set allRecords to paragraphs of (read srcFile as «class utf8»)
set myPlaylist to "Test"

tell application "iTunes"
    repeat with aRecord in allRecords
        set AppleScript's text item delimiters to ","
        set arrayVar to text items of aRecord
        set results to (every file track of playlist "Library" whose name is (item 1 of arrayVar) and artist is (item 2 of arrayVar) and track number is (item 3 of arrayVar) and album is (item 4 of arrayVar))
        repeat with aTrack in results
            duplicate aTrack to playlist myPlaylist
        end repeat
    end repeat
end tell

这里是源文件“ipod_mp3s_sample.csv”内容:

Ritual,Ashes Divide,8,Keep Telling Myself It's Alright
Ritual,Chick Corea Elektric Band II,9,Paint The World
Risk,Deftones,9,Diamond Eyes
Risveglio,Goblin,10,Zombi

答案 2 :(得分:0)

这是我写的一个脚本,它采用带有Track / Artist TAB分隔的CSV文件。 我用它从我在Spotify上找到的播放列表中搜索我自己的iTunes资料库 我使用了一个在线导出器将Spotify播放列表导出为CSV。 我不得不首先清理excel中的播放列表。

这也会创建单独的日志文件:

1)它找到的轨道 2)它没有找到的轨道      (我使用此列表作为单独的脚本,我有那个 然后会为我在soulSeek上搜索那些歌曲。

这里是代码:

-- Choose a file
set CSVstr to "Please locate your CSV file..."
set CSV_File to (choose file with prompt CSVstr) as text
set posixfilepath to (the POSIX path of CSV_File)
set posixfilepathLIST to emptylist(stringtolist(posixfilepath, "/"))
--set thename to item 1 of stringtolist(last item of posixfilepathLIST, ".")
set thename to (ListToString((reverse of (rest of (reverse of (stringtolist(last item of posixfilepathLIST, "."))))), "."))
set posixfilepathLISTCLEANED to reverse of (rest of (reverse of posixfilepathLIST))
set posixfilepathSTRINGCLEANED to ListToString(posixfilepathLISTCLEANED, ":")

--creates log file
set log_file_found to posixfilepathSTRINGCLEANED & ":" & (thename) & "_Matched_in_iTunes.txt"
global log_file_found
ClearLog(log_file_found)
WriteLog("Program Started....")
set log_file_notfound to posixfilepathSTRINGCLEANED & ":" & (thename) & "_NotFound_in_iTunes.txt"
global log_file_notfound
ClearLog(log_file_notfound)
WriteLog2("Program Started....")
property dialog_timeout : 3 -- set the amount of time before dialogs auto-answer.

-- Reading your file to memory
set CSV_Lines to every paragraph of (read file CSV_File from 1)
set AppleScript's text item delimiters to {""}
set Line_Values to {}
set {tids, text item delimiters} to {text item delimiters, "    "}
set trackCount to (count CSV_Lines)
set foundCount to 0
set NotfoundCount to 0
set gov to 1


tell application "iTunes"
    try
        set opt to (display dialog "Enter Name for Playlist" default answer {thename} default button 2 with title " Spotify Recreate from CSV " with icon 1)
        set newName to (text returned of opt)
        set maxfind to (button returned of opt)
        if newName is "" then error
    on error
        return
    end try

    try
        set newnom to ("_WrangledFrom_" & newName)
        if exists playlist newnom then delete playlist newnom
        set newP to (make new playlist with properties {name:newnom})
        set thePlaylist to view of the front browser window
        set view of front window to newP
        set listOfNames to {}
        set listOfNamesNotFound to {}
    end try
end tell



-- moves through the list one item at a time
repeat with i from 1 to trackCount
    set savedTIDS to AppleScript's text item delimiters
    set searchName to text item 1 of item i of CSV_Lines
    set searchArtist to text item 2 of item i of CSV_Lines
    set searchAll to (searchName & " - " & searchArtist) as text
    set searchAll2 to (searchName & " " & searchArtist) as text
    set tid to AppleScript's text item delimiters

    #insert routine here:
    tell application "iTunes"


        --ignoring diacriticals and punctuation
        --set big_list to (every file track whose name contains {searchName} and artist contains {searchArtist})
        --set big_list to (every file track of playlist "Library" whose name contains searchName and artist contains searchArtist)
        set big_list to (search library playlist 1 for {searchAll2} only songs)
        --set search_results to (search library playlist 1 for searchAll2)
        --set results to (every file track of playlist "Library" whose name contains searchName and artist contains searchArtist)
        --end ignoring

        set foundtracks to (count of items of big_list)
        if (count of items of big_list) is greater than or equal to gov then
            set foundCount to foundCount + 1
            set foundtrackinfo to ("Found " & foundtracks & " For | " & searchAll)
            delay 0.2
            my WriteLog(foundtrackinfo)
            copy foundtrackinfo to the end of listOfNames

            repeat with a in big_list
                duplicate a to newP
            end repeat
        else
            set NotfoundCount to NotfoundCount + 1
            set foundtrackinfo to ("Not Found | " & searchAll) as text
            delay 0.1
            my WriteLog2(foundtrackinfo)
            copy foundtrackinfo to the end of listOfNamesNotFound
        end if
    end tell
end repeat
delay 2
tell application "iTunes"
    set view of front window to newP
end tell
delay 2
try
    tell application "System Events"
        tell process "iTunes"
            set frontmost to true
        end tell

        keystroke "a" using {control down, option down, command down}
        delay 1
        keystroke "a" using {option down, command down}
        delay 1
    end tell
end try

set AppleScript's text item delimiters to savedTIDS
set AppleScript's text item delimiters to {""}

display dialog ("Spotify CSV Wrangle Complete") buttons {"OK"} default button 1
my WriteLog("Program Ended...")
my WriteLog2("Program Ended...")

on WriteLog(text4Log)
    set wri to open for access file log_file_found with write permission
    write (text4Log & return) to wri starting at eof
    close access wri
end WriteLog

on WriteLog2(text4Log)
    set wri to open for access file log_file_notfound with write permission
    write (text4Log & return) to wri starting at eof
    close access wri
end WriteLog2

on ClearLog(clear_log_file)
    set clearLF to open for access file clear_log_file with write permission
    set eof of clearLF to 0
    close access clearLF
end ClearLog (*
    --Progress Bar Subroutine

    --my SetupProgress([[linked-template:text]], 0, "Processing Data...", "Preparing to process.")

    on SetupProgress(SPTotalCount, SPCompletedSteps, SPDescription, SPAdditionalDescription)
        set progress total steps to {SPTotalCount}
        set progress completed steps to {SPCompletedSteps}
        set progress description to {SPDescription}
        set progress additional description to {SPAdditionalDescription}
    end SetupProgress

*)

on emptylist(klist)
    set nlist to {}
    set dataLength to length of klist
    repeat with i from 1 to dataLength
        if item i of klist is not "" then
            set end of nlist to (item i of klist)
        end if
    end repeat
    return nlist
end emptylist

on ListToString(theList, delim)
    set oldelim to AppleScript's text item delimiters
    set AppleScript's text item delimiters to delim
    set alist to theList as string
    set AppleScript's text item delimiters to oldelim
    return alist
end ListToString

on stringtolist(theString, delim)
    set oldelim to AppleScript's text item delimiters
    set AppleScript's text item delimiters to delim
    set dlist to (every text item of theString)
    set AppleScript's text item delimiters to oldelim
    return dlist
end stringtolist