Sunday, July 3, 2022

#1 2022-01-06 02:44:28 am

MrCee
Member
Registered: 2016-07-01
Posts: 15

Iterate NSDictionary to create further NSDictionary's in Music.app

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 :)

Applescript:

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

Last edited by MrCee (2022-01-06 02:48:19 am)

Offline

 

#2 2022-01-06 05:36:16 pm

technomorph
Member
Registered: 2017-12-14
Posts: 254

Re: Iterate NSDictionary to create further NSDictionary's in Music.app

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.

Offline

 

#3 2022-01-06 05:40:33 pm

technomorph
Member
Registered: 2017-12-14
Posts: 254

Re: Iterate NSDictionary to create further NSDictionary's in Music.app

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

and hope that those are going to match up.

Last edited by technomorph (2022-01-06 05:51:19 pm)

Offline

 

#4 2022-01-06 06:04:22 pm

technomorph
Member
Registered: 2017-12-14
Posts: 254

Re: Iterate NSDictionary to create further NSDictionary's in Music.app

a few other things about your code:

Applescript:

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

Applescript:

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
---------------

Last edited by technomorph (2022-01-06 06:13:08 pm)

Offline

 

#5 2022-01-06 11:02:28 pm

technomorph
Member
Registered: 2017-12-14
Posts: 254

Re: Iterate NSDictionary to create further NSDictionary's in Music.app

Substitute Music for iTunes ....

Applescript:

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:

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)