iTunes list indexer

This script will ask for a list name in iTunes and then set a complete list of every artist, each of his/hers/it’s albums and each song for each album
and “paste” it in “TextEdit”
it takes care of ‘blank’ albums and sort of takes care of ‘blank’ artists, but (and I think this is not a possibility) it doesn’t take care of ‘blank’ track names.
I couldn’t make it to index the library, you’d have to make a list and just copy every track into it, sorry… (but I’m working on it)
One more thing, watch it, it takes a while if the list is big (500 songs = 3:30 minutes) - have fun!!

OS version: OS X

-- It might be a bit messy, and, sorry, the coments are in spanish!
-- But feel free to ask

display dialog "" buttons {"Español", "English"} default button 1 -- this is just fancy, nothing important
set el_idioma to the button returned of the result
if el_idioma is equal to "Español" then
	set advertencia to "¡¡Cuidado, indexar 500 canciones toma 3 minutos y medio aprox. asique sea paciente y deje trabajar a la PC!!"
	set pregunta_inicio to "Que lista desea indexar?" & return & "(el orden es alfabético)"
	set falta_el_album to "Falta el album - "
	set index_de to "Index de \""
	set texto_artistas to " artistas, "
	set texto_albums to " albums (sin contar los que faltan), "
	set texto_canciones to " canciones:"
	set indexado_por_nikel to "Indexado por Nikel"
else
	set advertencia to "¡¡Warning, it takes about 3 and a half minutes to index 500 songs, so be patient and let the machine work!!"
	set pregunta_inicio to "Choose list to index" & return & "(order is alphabetic)"
	set falta_el_album to "Album missing - "
	set index_de to "Index of \""
	set texto_artistas to " artists, "
	set texto_albums to " albums (not counting the missing ones), "
	set texto_canciones to " songs:"
	set indexado_por_nikel to "Indexed by Nikel"
end if

display dialog advertencia buttons {"?"} default button 1 giving up after 8 with icon caution
set el_resultado to ""
tell application "iTunes"
	set eleccion to (the name of every user playlist) as list -- busca todas las listas que el usuario tenga en iTunes
	set eleccion to my alfabetico(eleccion) -- luego la ordena alfabéticamente
	set la_lista to (choose from list eleccion with prompt pregunta_inicio) as string -- y le pide al usuario cual quiere indexar
	if la_lista is not equal to "false" then -- si no apretó "cancel" entonces indexa la lista elegida
		set artistas to artist of (every track) in user playlist la_lista -- arma una lista con todos los artistas de la lista
		set artistas to my achicar(artistas) -- saca todos los artistas repetidos (que van a ser muchos, uno por cada cancion de la lista)
		repeat with i from 1 to (count of artistas) -- este repeat es el que toma artista por artista (segun i) y luego busca los albums de cada uno
			set el_resultado to el_resultado & return & (item i of artistas) -- agrego el primer artista
			set los_albums to album of (every track whose artist is (item i of artistas)) in user playlist la_lista -- defino una lista con todos los albums del artista "i"
			repeat with k from 1 to count of los_albums -- si deja el vacio, después hay problemas al agrupar, habrá canciones de diferentes artistas con el mismo album
				if (item k of los_albums) is equal to "" then set (item k of los_albums) to falta_el_album & (item i of artistas) -- esto diferencia cada album que no este definido
			end repeat
			set los_albums to reverse of my achicar(los_albums) -- saco todos los albums que estén repetidos (que también pueden ser cientos)
			repeat with j from 1 to (count of los_albums)
				if (item j of los_albums) contains falta_el_album then -- aca redefino temporalmente el album para que cuando lo busque efectivamente lo encuentre
					set el_item to "" -- pero sin cambiar el item j de los_albums, que lo necesito como está más tarde (entonces uso el_item)
				else
					set el_item to (item j of los_albums) -- si no era "" entonces no lo cambié por "Falta el album" y entonces lo dejo como es
				end if
				set este_album to name of (every track whose album is el_item and artist is (item i of artistas)) in user playlist la_lista -- define una lista con todos los temas del album
				set este_album_como_texto to "" -- lo anterior es una lista, aca lo transformo en el texto que luego voy a mostrar
				repeat with k from 1 to (count of este_album) -- tomo cada canción y la separo ordenandolas en columna
					set este_album_como_texto to este_album_como_texto & "    " & k & " - " & (item k of este_album) & return
				end repeat
				set el_resultado to el_resultado & return & j & " - " & (item j of los_albums) & return & este_album_como_texto -- agrego a el_resultado los albums y las sus canciones de cada uno
			end repeat
		end repeat
		(* lo que sigue son solo número que voy a usar al final, cuando muestre el resultado. Son solo estadísticas *)
		set cantidad_de_artistas to (count of artistas)
		set todos_los_albums to (album of (every track in user playlist la_lista))
		set todos_los_albums to my achicar(todos_los_albums)
		set cantidad_de_albums to (count of todos_los_albums)
		set cantidad_de_canciones to (count of tracks in user playlist la_lista)
		(* esto está acá porque usa funciones de iTunes, que debo incluir en un Tell. Este me pareció bien *)
	else
		return
	end if
end tell

launch application "TextEdit" -- no es estrictamente necesario, pero si lo abro así, no abre el archivo sin título en blanco que abre normalmente
tell application "TextEdit"
	make new document at the beginning of documents with properties {name:index_de & la_lista & "\""}
	set the name of window 1 to index_de & la_lista & "\""
	set zoomed of the front window to false
	set visible of the front window to true
	set the text of the front document to (cantidad_de_artistas as string) & texto_artistas & (cantidad_de_albums as string) ¬
		& texto_albums & (cantidad_de_canciones & texto_canciones & return as string) & el_resultado & return & indexado_por_nikel
end tell


to achicar(albums) -- esta rutina toma una lista y se fija si tiene elementos repetidos. Si los hay, los saca y devuelve una lista más chica, más rápida de procesar.
	set achicado to {item 1 of albums}
	repeat with i from 2 to (count of albums)
		if (item i of albums) is not in (contents of achicado) then set achicado to (achicado & (item i of albums))
	end repeat
	return achicado as list
end achicar

to alfabetico(lista) -- esta rutina recibe una lista y la ordena alfabéticamente según el orden de caracteres ASCII  (por eso las MAYUSCULAS vienen primero)
	set numero to {}
	set nueva_lista to {}
	repeat with i from 1 to (count of lista)
		set numero to (numero & (ASCII number of (item i of lista))) as list -- solo toma el primer caracter de cada elemento
	end repeat
	repeat with i from 32 to 255 -- del 32 al 255 es el rango de caracteres "útiles" para nombres
		repeat with j from 1 to (count of numero)
			if (item j of numero) is equal to i then
				set nueva_lista to nueva_lista & (item j of lista)
			end if
		end repeat
	end repeat
	return nueva_lista as list
end alfabetico


(*
tiempos tardados/times taken:
477 canciones/songs = 03:20 minutos/minutes
339 canciones = 02:05 minutos
139 canciones = 00:20 minutos

parece ser exponencial / seems exponential
*)