Topic : Change star ratings to match another library

Topic Archived This topic has been archived - replies are not allowed.


This question is answered. "Helpful" answers available: 2 . "Solved" answers available: 1 .



            Permlink
            Replies : 16 - Pages : 2 [ 1 2 | Next ] - Last Post : Nov 21, 2007 4:51 AM by: dev_sleidy
Greg DiGenti


Posts: 48
Registered: Jul 18, 2004
Change star ratings to match another library
Posted: Nov 17, 2007 5:41 PM
 

This is something I've been trying to figure out how to do for a while, but haven't been able to come up with a solution.

I rate songs while I'm listening to music at work using an AppleScript I wrote that I keep in the dock which gives me a popup to rate the song, which it then adds to a new playlist called "Newly Rated Songs." The goal is to rate all of the songs in my iTunes library.

The problem comes in when I try to keep the ratings in sync with my home computer and my iPod. My current solution is to drag the songs from my work computer to my iPod (where unrated versions of those songs already exist), then take the iPod home and use Senuti to take them from the iPod into iTunes.

As much as a hassle as this is, it becomes worse since iTunes thinks they're new songs and I end up with duplicates of all the newly rated songs, and I have to sift through them and delete the unrated copies.

What I was curious about, is there a way to make a script that will just take the ratings from the playlist of newly rated songs, put those into some kind of text file, then when I get home, run a script that takes the ratings from the text file and rates the songs in my home iTunes? Rather than moving songs back and forth?

Thanks for any help.

G5   Mac OS X (10.4.8)  
dev_sleidy


Posts: 754
Registered: Jun 13, 2006
Re: Change star ratings to match another library
Posted: Nov 17, 2007 6:45 PM   in response to: Greg DiGenti
 

'is there a way to make a script that will just take the ratings from the playlist of newly rated songs, put those into some kind of text file, then when I get home, run a script that takes the ratings from the text file and rates the songs in my home iTunes? Rather than moving songs back and forth?' - yes.

Below are three (3) code segments.

The first code segment - creates a text file (on the 'Desktop') of 'iTunes' 'Library' playlist tracks with ratings greater than 0.

The second code segment - reads the created text file (when it is dragged onto the second code segments' saved applet) and updates 'iTunes' 'Library' playlist tracks accordingly. This code segment works in 'Leopard'; but, cause an error in 'Tiger'. Details are presented below.

The third code segment - clears out 'iTunes' 'Library' playlist tracks. I used this so I could test the first two code segments on a single Mac.

Code segment 01:

tell application "iTunes"

try
set tNames to name of every track of playlist "Library" whose rating ≠ 0
set tRatings to rating of every track of playlist "Library" whose rating ≠ 0

set tDate to ((path to desktop folder from user domain) as string) & (do shell script "date +%Y%m%d_%H%M%S_")

set fREF to open for access file (tDate & "iTunes_Ratings.txt") with write permission

set tCount to count tNames
repeat with i from 1 to tCount
write ((item i of tNames) & tab & (item i of tRatings)) to fREF
if (i < tCount) then write (ASCII character 10) to fREF
end repeat

close access fREF
end try
end tell

Code segment 02:

on run
display dialog "Drop respective file(S) onto applet for processing." buttons {"OK"} default button "OK"
end run

on open (dragged_Items)

repeat with x in dragged_Items
set tParagraphs to every paragraph of (read x)

tell application "iTunes"
activate

set tNames to name of every track of playlist "Library"

repeat with i in tParagraphs

set {oAStid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, tab}
set tItems to text items of i
set AppleScript's text item delimiters to oAStid

if (tNames contains (item 1 of tItems)) then
repeat with j from 1 to (count tNames)
if ((item j of tNames) is equal to (item 1 of tItems)) then set (rating of track j of playlist "Library") to (item 2 of tItems)
end repeat
end if
end repeat
end tell

end repeat
end open

Code segment 03.

tell application "iTunes" to set rating of (every track of playlist "Library" whose rating ≠ 0) to 0

    • --

Save each code segment as an application (actually, an applet).

One problem, here. Code segment 02 works, as is, in 'Leopard'; but the ...

if ((item j of tNames) is equal to (item 1 of tItems)) then set (rating of track j of playlist "Library") to (item 2 of tItems)

... line, fails in 'Tiger'. For some reason ...

count (item 2 of tItems)

... results in 4 - in 'Tiger'; but 2 - in 'Leopard'.

I may investigate this later.

  Mac OS X (10.4.11)    
dev_sleidy


Posts: 754
Registered: Jun 13, 2006
Re: Change star ratings to match another library
Posted: Nov 17, 2007 7:44 PM   in response to: dev_sleidy
 

Code segment 02, rewritten - that works on 'Tiger', and 'Leopard':

on run
display dialog "Drop respective file(S) onto applet for processing." buttons {"OK"} default button "OK"
end run

on open (dragged_Items)

repeat with x in dragged_Items
set tParagraphs to every paragraph of (read x)

tell application "iTunes"
activate

set tNames to name of every track of playlist "Library"

repeat with i in tParagraphs

set {oAStid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, tab}
set tItems to text items of i
set AppleScript's text item delimiters to oAStid

-- Cheater code
set item02 to (item 2 of tItems)
if ((count item02) > 2) then set item02 to ((character 2 of item02) & (character 4 of item02))

if (tNames contains (item 1 of tItems)) then
repeat with j from 1 to (count tNames)
if ((item j of tNames) is equal to (item 1 of tItems)) then set (rating of track j of playlist "Library") to item02
end repeat
end if

end repeat

end tell

end repeat
end open

  Mac OS X (10.4.11)    
dev_sleidy


Posts: 754
Registered: Jun 13, 2006
Re: Change star ratings to match another library
Posted: Nov 17, 2007 9:38 PM   in response to: dev_sleidy
 

I noted a mistake in my second post.

The code below, was tested (on 'Tiger' and 'Leopard') with tracks of 1, 2, 3, 4, and 5 star rating; and worked.

--- Code starts here ---

on run
display dialog "Drop respective file(S) onto applet for processing." buttons {"OK"} default button "OK"
end run

on open (dragged_Items)

repeat with x in dragged_Items
set tParagraphs to every paragraph of (read x)

tell application "iTunes"
activate

set tNames to name of every track of playlist "Library"

repeat with i in tParagraphs

set {oAStid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, tab}
set tItems to text items of i
set AppleScript's text item delimiters to oAStid

-- Cheater code
set item02 to (item 2 of tItems)

if ((count item02) > 4) then
set item02 to ((character 2 of item02) & (character 4 of item02) & (character 6 of item02))
else if ((count item02) > 3) then
set item02 to ((character 2 of item02) & (character 4 of item02))
end if

if (tNames contains (item 1 of tItems)) then
repeat with j from 1 to (count tNames)
if ((item j of tNames) is equal to (item 1 of tItems)) then set (rating of track j of playlist "Library") to item02
end repeat
end if

end repeat

end tell

end repeat
end open

--- Code ends here ---

  Mac OS X (10.4.11)    
Hiroto


Posts: 828
From: Japan
Registered: Oct 24, 2001
Re: Change star ratings to match another library
Posted: Nov 18, 2007 11:25 AM   in response to: dev_sleidy
 

Hello dev_sleidy,

I think the different behaviours of your original code segment 02 under OSX10.4 and OSX10.5 are caused by the significant change in 'write' and 'read' commands of AppleScript 2.0.

In AS2.0, 'write' and 'read' commands will use system's primary encoding even when Unicode text object is written or read when there's no 'as' parameter is specified.
In pre-AS2.0, 'write' command will use UTF-16BE encoding in writing Unicode text when there's no 'as' parameter is specified, while 'read' command will use system's primary encoding when there's no 'as' parameter is specified.

So the resulting text file of your original code segment 01 is in system's primary encoding under OSX10.5 while it is in UTF-16 under OSX10.4 (because iTunes' track name is Unicode text).

If I'm not much mistaken, a clean remedy would be to specify 'as Unicode text' to both 'write' and 'read' commands in your code segements.


cf. 'Unicode Support' section of AppleScrpt 2.0 release note.
http://developer.apple.com/releasenotes/AppleScript/RN-AppleScript/index.html

All the best,
H

  Mac OS 9.1.x    
Greg DiGenti


Posts: 48
Registered: Jul 18, 2004
Re: Change star ratings to match another library
Posted: Nov 19, 2007 9:29 AM   in response to: dev_sleidy
 

Wow, I appreciate the help on this.

Looking over your script, though, it looks like all it takes into account is the song name. A problem I foresee with this approach is that with an iTunes library of over 8,000 songs, all songs with the same name are not equal. Sometimes they're by two different bands, or sometimes they're by the same band, just different versions on different albums (and some versions may be worse than others).

Is there something besides song name that iTunes uses that's more precise? Or maybe if the first segment of code also checked for the album name, and a cross-check was done in the second segment between the song name and album name?

G5   Mac OS X (10.4.8)  
dev_sleidy


Posts: 754
Registered: Jun 13, 2006
Re: Change star ratings to match another library
Posted: Nov 19, 2007 11:26 AM   in response to: Greg DiGenti
 

'Is there something besides song name that iTunes uses that's more precise?' - yes.

---

'Or maybe if the first segment of code also checked for the album name, and a cross-check was done in the second segment between the song name and album name?' - yes, this too can, and should, be performed.

Study and understand the code provided, and then consult the 'iTunes' Library from within 'Script Editor' (via the 'Window, Library' menu item) with reference to 'album' (of the 'track' class).

Next, simply add a single line to, and modify one line of, each code segment (of 'Code segment 01' and 'Code segment 02'). The 'album' related additions and modifications, to the code segments, should take you no more then one minute total to incorporate.

By coincidence, I just ripped ten (10) of Christmas songs CDs - resulting in the same song from different albums, being added to 'iTunes'. One song was listed under five (5) different album names, so I tested my modified code, against that track name (with each name given a different star rating), and it worked.

Grasshopper, once you have edited your code (to include saving the tracks' album name to the '.txt' file, within 'Code segment 1'; and, extract the tracks' album name from the '.txt' file, within 'Code segment 2') please, post it for all to see.

  Mac OS X (10.4.11)    
dev_sleidy


Posts: 754
Registered: Jun 13, 2006
Re: Change star ratings to match another library
Posted: Nov 19, 2007 11:56 AM   in response to: dev_sleidy
 

Typo correction: The sentence ...

By coincidence, I just ripped ten (10) of Christmas songs CDs - resulting in the same song from different albums, being added to 'iTunes'.

... was meant to be ...

By coincidence, I just ripped ten (10) CDs of Christmas songs - resulting in the same song from different albums, being added to 'iTunes'.

  Mac OS X (10.4.11)    
Greg DiGenti


Posts: 48
Registered: Jul 18, 2004
Re: Change star ratings to match another library
Posted: Nov 19, 2007 1:56 PM   in response to: dev_sleidy
 

I'm not quite adept enough with Applescript to do it in one minute, but I did finally get it working. Quite a brilliant script, thanks so much for your help.

Here's what I ended up with, see what you think. (I added a bit in the beginning of each one to allow the user to choose a playlist, since it's likely going to be a different playlist on each computer for me):


Script 1 starts here

tell application "iTunes"
set thePlaylists to name of every playlist
set thePlaylist to (choose from list thePlaylists) as Unicode text

try
set tNames to name of every track of playlist thePlaylist whose rating ≠ 0
set tAlbum to album of every track of playlist thePlaylist whose rating ≠ 0
set tRatings to rating of every track of playlist thePlaylist whose rating ≠ 0

set tDate to ((path to desktop folder from user domain) as string) & (do shell script "date +%Y%m%d_%H%M%S_")

set fREF to open for access file (tDate & "iTunes_Ratings.txt") with write permission

set tCount to count tNames
repeat with i from 1 to tCount
write ((item i of tNames) & tab & (item i of tAlbum) & tab & (item i of tRatings)) to fREF as Unicode text
if (i < tCount) then write (ASCII character 10) to fREF
end repeat

close access fREF
end try
end tell


Script 2 starts here

display dialog "Drop respective file(S) onto applet for processing." buttons {"OK"} default button "OK"
end run

on open (dragged_Items)

repeat with x in dragged_Items
set tParagraphs to every paragraph of (read x)

tell application "iTunes"
activate
set thePlaylists to name of every playlist
set thePlaylist to (choose from list thePlaylists) as Unicode text

set tNames to name of every track of playlist thePlaylist
set tAlbums to album of every track of playlist thePlaylist

repeat with i in tParagraphs

set {oAStid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, tab}
set tItems to text items of i
set AppleScript's text item delimiters to oAStid

-- Cheater code
set tAlbum to (item 2 of tItems)
set tRating to (item 3 of tItems)

if ((count tRating) > 4) then
set tRating to ((character 2 of tRating) & (character 4 of tRating) & (character 6 of tRating))
else if ((count tRating) > 3) then
set tRating to ((character 2 of tRating) & (character 4 of tRating))
end if

--Only if the rating is greater than 3 stars
if (tNames contains (item 1 of tItems) and tAlbums contains tAlbum) then
repeat with j from 1 to (count tNames)
if ((item j of tNames) is equal to (item 1 of tItems)) and ((item j of tAlbums) is equal to (tAlbum)) then set (rating of track j of playlist thePlaylist) to tRating
end repeat
end if

end repeat

end tell

end repeat
end open

G5   Mac OS X (10.4.8)  
Greg DiGenti


Posts: 48
Registered: Jul 18, 2004
Re: Change star ratings to match another library
Posted: Nov 19, 2007 1:59 PM   in response to: Greg DiGenti
 

BTW, I meant to remove the "--Only if the rating is greater than 3 stars" portion from the second script's code, since it wasn't relevant in my final version.

G5   Mac OS X (10.4.8)  
dev_sleidy


Posts: 754
Registered: Jun 13, 2006
Re: Change star ratings to match another library
Posted: Nov 19, 2007 2:56 PM   in response to: Greg DiGenti
 

Excellent Grasshopper.

You had entered the same code, at the same locations, as I did.

  Mac OS X (10.4.11)    
Greg DiGenti


Posts: 48
Registered: Jul 18, 2004
Re: Change star ratings to match another library
Posted: Nov 20, 2007 8:27 AM   in response to: dev_sleidy
 

Thanks a lot dev. I did a limited trial run last night and it worked like a charm. I'm glad there are smart people out there like yourself willing to help out with things like this. I just wished I had posted this sooner; it would have saved me a lot of trouble!

One question I have, though, is what is this part of the code all about?
if ((count tRating) > 4) then
set tRating to ((character 2 of tRating) & (character 4 of tRating) & (character 6 of tRating))
else if ((count tRating) > 3) then
set tRating to ((character 2 of tRating) & (character 4 of tRating))
end if

It seems to me that at that point in the code, the tRating variable already contains the correct number and it seems as though you should just be able to use that as the rating for the track. But when I tried it, I was told a "descriptor mismatch occurred." I also tried to coerce it into an integer, but it would say something that sounded silly to me: "Can't make '60' into type integer."

What's going on exactly?

G5   Mac OS X (10.4.8)  
Hiroto


Posts: 828
From: Japan
Registered: Oct 24, 2001
Re: Change star ratings to match another library
Posted: Nov 20, 2007 10:00 AM   in response to: Greg DiGenti
 

Hello Greg DiGenti,

As I mentioned earlier, tRating read in the current script is in system's primary encoding, e.g. MacRoman, although it is actually Unicode text (UTF-16).

E.g.
"60" in UTF-16BE has byte sequence as 0x00360030, which is interpreted in MacRoman as a string that consists of 0x00, 0x36, 0x00, 0x30 (i.e. =6=0, where '=' denotes 0x00). [1]


To eliminate the ad-hoc code to adjust tRating value, you may just replace this line in your script (if I'm not mistaken):

set tParagraphs to every paragraph of (read x)

with this line:

set tParagraphs to every paragraph of (read x as Unicode text)


You have already used 'as Unicode text' in write command correctly.
By the way, your tests on album name and track name work even in current script because of AppleScript's peculiar behaviour of text comparison, which I consider as bug. [2]

Regards,
H


Notes.
[1] Try the following TEST-1 which illustartes error in 'as integer' coercion .

-- TEST-1
(* for pre-AppleScript 2.0 *)
set x00 to ASCII character 0
set t to x00 & "6" & x00 & "0"
--set t to «data TEXT00360030» as anything
set u to "60" as Unicode text
--set u to «data utxt00360030» as anything

set rr to {t, u}
try
set end of rr to t as integer -- throws error -1700 errAECoercionFail
on error errs number errn
set end of rr to {errs, errn}
end try
set end of rr to u as integer -- 60
return rr
-- END OF TEST-1


[2] Try the following TEST-2 which illustrates this peculiar behaviour in text comparison.

-- TEST-2
(* for pre-AppleScript 2.0 *)
set x00 to ASCII character 0
set t to x00 & "A" & x00 & "B"
set t1 to x00 & "A" & x00 & x00 & x00 & "B" & x00 & x00
set u to "AB" as Unicode text
return {u = t, u = t1} -- {true , true}
(* I believe this to be considered as bug, for this should return {false, false} *)
-- END OF TEST-2


Message was edited by: Hiroto

  Mac OS 9.1.x    
Greg DiGenti


Posts: 48
Registered: Jul 18, 2004
Re: Change star ratings to match another library
Posted: Nov 20, 2007 12:59 PM   in response to: Hiroto
 

Thank you for your explanation Hiroto. The inability to see that 60=60 sure seems to me like a case of Applescript making something more difficult than it needs to be.

Also, I tried adding your set tParagraphs to every paragraph of (read x as Unicode text) code and got the odd error message Can't make "60??.

But that's fine, I can just leave it as it was before. Thanks again.

G5   Mac OS X (10.4.8)  
Hiroto


Posts: 828
From: Japan
Registered: Oct 24, 2001
Re: Change star ratings to match another library
Posted: Nov 20, 2007 1:23 PM   in response to: Greg DiGenti
 

Ah, I've missed this line in your Script 1:

if (i < tCount) then write (ASCII character 10) to fREF

which should have been:

if (i < tCount) then write (ASCII character 10) as Unicode text to fREF


After this fix, the next line in your Script 2 will work as intended:

set tParagraphs to every paragraph of (read x as Unicode text)

Cheers,
H

Message was edited by: Hiroto

  Mac OS 9.1.x