I’m experimenting with NSDictionary in hope I can optimise code and clean up thousands of tags in Music.app. Mostly Ive been using NSArray in the past.
The end goal is to have a persistent ID as the key with each track property so I can focus on cleaning up that mp3 tag.
I’ve created a master NSDictionary which I want to iterate and create further NSDictionary’s from the key/values within it. You’ll see I can achieve this one way, but need to understand why I’m not able to achieve it in an iterative loop.
Also, Is there anything else I’m forgetting here as far as missing value goes? Was wondering about the potential of the persistent ID becoming mismatched with the values. Let me know if there’s a better way
use AppleScript version "2.5"
use framework "Foundation"
use scripting additions
tell application "Music"
set theID to (get persistent ID of every file track of library playlist 1)
set nsDict to current application's NSDictionary's dictionaryWithObjects:{"name", "artist", "album"} forKeys:{"theName", "theArtist", "theAlbum"}
(* ----- An example of what I am trying to achieve in a loop --------
set theName to (current application's NSDictionary's dictionaryWithObjects:(get name of every file track of library playlist 1) forKeys:theID)
set theArtist to (current application's NSDictionary's dictionaryWithObjects:(get artist of every file track of library playlist 1) forKeys:theID)
set theAlbum to (current application's NSDictionary's dictionaryWithObjects:(get album of every file track of library playlist 1) forKeys:theID)
*)
set theKeys to nsDict's allKeys()
repeat with thisKey in theKeys
set thisObject to (nsDict's valueForKey:thisKey)
set thisKey to (current application's NSDictionary's dictionaryWithObjects:(get thisObject of every file track of library playlist 1) forKeys:theID)
end repeat
end tell
I’ve done lots of ITunes scripting working with tab clean up.
Ultimately what is going to be your purpose
And your workflow?
I’ve found it’s going to be slow and potentially dangerous to
Operate on all of your files in your music library.
I’ve found it much better to work with a playlist or selected tracks.
You can then build up your own personal “model” from
There. And process and iterate thru those easier.
Really rethink your code.
I see your trying to create your own dictionary of every
Track getting the persistentID, Name, Artist, Album.
But why?
ITunes already has all of this done for you.
You should consider how your accessing this data.
In your code I was confused by the variable
trackID, you should name it as trackIDs since it
Is a list of IDs.
(same with trackName, trackArtist etc)
I would also rethink the concept of Dictionaries and Arrays.
A Dictionary is usually a record of info/detail about a object.
A Array is a list of objects (which can be a list of Dictionaries)
(use an analogy of sticking things in a folder)
I would approach each track as having it’s own dictionary.
And store these tracks in a Array.
You can then use that Array as a object for a key in a dictionary.
Like a playlist would. A playlist Dict would have keys for “playlistName”, “persistentID”
and “playlistTracks”.
I get that your trying to get 4 lists (Arrays)
trackIDs
trackNames
trackArtists
trackAlbums
and then trying to create a dictionary from that by iterating over them.
But while those lists (remember at this point from your code they are lists and
not NSArrays). are just like folders.
your hoping that each of those 4 lists has in order this info for each track.
But this may not be so. Say your 14th track doesn’t have an Artist…
and your 27th track doesn’t have an album. No all of a sudden your 4
lists are not “linked”.
You can’t use a repeat with I from 1 to (count of trackIDs)
set aID to item I of trackIDs
set aName to item I of trackNames
etc
set theKeys to nsDict's allKeys()
repeat with thisKey in theKeys
set thisObject to (nsDict's valueForKey:thisKey)
set thisKey to (current application's NSDictionary's dictionaryWithObjects:(get thisObject of every file track of library playlist 1) forKeys:theID)
end repeat
this is all very confusing.
your repeating with thisKey which is NSString
then your trying to set thisKey as a NSDictionary?
even if you change that to a variable like foundItems
set foundItems to (current application's NSDictionary's dictionaryWithObjects:(get thisObject of every file track of library playlist 1) forKeys:theID)
your not storing it anyplace.
I think what your wanting to do is change your nsDict.
You want to be doing
nsDict’s setObjects:forKeys:
(You’ll need to change to NSMutableDictionary)
And I think you may want to create an intermediate NSDictionary (foundItems)
And then
nsDict’s setValue:foundItems forKey:thisKey
why not just create a list of your keys theKeys
repeat with thisKey
get theItems first
then create a dictionary.
I would also look into NSMutableDictionay which seems I think a bit more what your after.
And also NSMutableArray
use AppleScript version "2.4"
use framework "Foundation"
-- classes, constants, and enums used
property NSMutableDictionary : a reference to current application's NSMutableDictionary
property NSMutableArray : a reference to current application's NSMutableArray
property processedItems : missing value
on run {}
set selTracks to my getSelectedTracks()
set my processedItems to my processTracks:selTracks
end run
-- MAIN FUNCTIONS
on getSelectedTracks()
set selectedTracks to {}
try
tell application "iTunes"
set sel to selection
if sel is not {} then
-- log {"selection is Tracks"}
repeat with aTrack in sel
copy aTrack to the end of selectedTracks
end repeat
else
-- log {"selection is Playlist"}
set thePlaylist to view of the front browser window
repeat with i from 1 to (index of last track of thePlaylist)
set aTrack to track i of thePlaylist
copy aTrack to the end of selectedTracks
end repeat
end if
end tell
end try
return selectedTracks
end getSelectedTracks
on processTracks:tracksToProcess
set theProcessedList to {}
set theProcessedTracks to NSMutableArray's new()
repeat with i from 1 to (count of tracksToProcess)
set aTrack to item i of tracksToProcess
set theResults to (my processTrack:aTrack)
set the end of theProcessedList to theResults
(theProcessedTracks's addObject:theResults)
end repeat
-- return theProcessedList
return theProcessedTracks
end processTracks:
on processTrack:aTrack
-- do further subFunctions / Processing
--set theResults to missing value
set theResults to my createTrackDict:aTrack
return theResults
end processTrack:
on createTrackDict:aTrack
set aTrackDict to NSMutableDictionary's dictionary()
tell application "iTunes"
set aTrackID to persistent ID of aTrack
set aTrackName to name of aTrack
set aTrackArtist to artist of aTrack
set aTrackAlbum to album of aTrack
end tell
if aTrackName is "" then set aTrackName to "Missing Name"
if aTrackArtist is "" then set aTrackArtist to "Missing Artist"
if aTrackAlbum is "" then set aTrackAlbum to "Missing Album"
aTrackDict's setValue:aTrackID forKey:"trackPersistentID"
aTrackDict's setValue:aTrackName forKey:"trackName"
aTrackDict's setValue:aTrackArtist forKey:"trackArtist"
aTrackDict's setValue:aTrackAlbum forKey:"trackAlbum"
return aTrackDict
end createTrackDict: