Tag Archives: iTunes

Mac workflow: iTunes playlist tagger

A probléma

Elég régóta használok tageket OS X alatt – a gyári óperenciás rendszerben még nem léteztek, már gyártottam őket valami toollal, ami openmeta kompatibilis volt. Amióta a Finderrel is lehet taggelni, azóta nem értem, hogy az iTunes médiaszörnyeteg miért nincs ugyanerre felkészítve. Számtalan alkalommal került már elő, hogy mondjuk hangulat alapján hallgatnék zenét, vagy mondjuk csak egy szál vékony női énekhangot akarok hallani – ilyesfajta keresésre pedig semmi nem képes.

Léteznek mindenféle toolok, amik ezt próbálják segíteni valahogyan: a Tangerine pl. ütemet próbál számolni, a Moody pedig egy 4×4 osztású 2D sebesség vs. hangulat mátrixba soroltatná veled a trackeket.

A megoldás

Mindkét fent említett játékos a trackekbe irkálna valami custom metaadatot, én viszont kitaláltam valami sokkal ügyesebbet! Egy track tetszőleges számú playlistben szerepelhet – legyen hát a playlist neve a tag, amit a trackre akasztunk! Már csak egy olyan eszköz kell, ami az aktuálisan játszott tracket gyorsan bedobálja ezekbe a “tag” playlistekbe anélkül, hogy ehhez egerezni kellene meló közben.
Szerencsére a platformon létezik Alfred, a csodás productivity tool, ami szénné scriptelhető, az iTunes meg nagy haverja az AppleScriptnek, úgyhogy már csak össze kell engedni őket.

Azt találtam ki, hogy ezek a speciális, tag-ként funkcionáló playlistek egy közös, “Tags” nevű playlist folderben fognak lakni és a nevük @ prefixxel kezdődik majd, így különböztetve meg őket a többi listától. Az Alfred workflow-nak pedig a következőket kell szolgáltatnia:

  • mondja meg, hogy épp mi szól
  • lássam egy listában az éppen lejátszott trackra összes releváns és irreleváns taget
  • egyszerre akárhány taget rápakolhassak az aktuális trackre

Nos, ilyen lett:

iTunes playlist tagger

Keyword vagy shortcut indítja. A listában zöld + ikonnal szerepelnek az aktuális trackre még nem ráakasztott, de egyébként létező tag-ek, piros – ikonnal pedig azok, amelyek már hozzá vannak rendelve. Értelemszerűen a pirosak törlik az adott tag-et, a zöldek hozzáadják.

Ez azonban a rendes power usernek még kevés lenne, mert mi van, ha több új tag-re van szükségünk? Ilyenkor jön az, hogy a “plst ” kulcsszó után space-szel elválasztva irkálhatjuk a tageket. Ha a tag neve – prefixszel kezdődik, akkor az a tag törlődni fog, ha + karakterrel (a + nem kötelező, a nem mínusz első karakter automatikusan +-at jelent), akkor pedig hozzácsapjuk az adott tracket. Így akármennyi taget írhatunk egymás után, a tagger script szép sorban feldolgozza őket egyesével.

Na de nem lennék rendes kocka, ha nem néznénk meg a forrást. Itt van a script filter rész, ami felépíti a kiválasztó listát:

on run argv
	set q to argv as text

(*
	if not (itunes_is_running()) then 
		set xml to xml & linefeed & "" & linefeed
		set xml to xml & "iTunes is not running" & linefeed
		set xml to xml & "Start iTunes and retry" & linefeed
		set xml to xml & "now_paused.png" & linefeed
		set xml to xml & "" & linefeed

		return xml & "" & linefeed
	end if
*)

	-- pick up info from iTunes
	tell application "iTunes"
		set dbid to the database ID of the current track
		set artist_name to (get artist of the current track)
		set track_name to the name of the current track
		set pls to (get name of user playlists)
	end tell

	-- xml header
	set xml to "" & linefeed
	set xml to xml & "" & linefeed

	-- track info list item
	set xml to xml & linefeed & "" & linefeed
	set xml to xml & "" & track_name & "" & linefeed
	set xml to xml & "" & artist_name & "" & linefeed
	set xml to xml & "now_playing.png" & linefeed
	set xml to xml & "" & linefeed

	-- add new tag list item
	set xml to xml & linefeed & "" & linefeed
	set xml to xml & "New Playlist Tag" & linefeed
	if q is equal to "" then 
		set xml to xml & "To remove tags use - prefix, e.g: slow -fast" & linefeed
	else
		set xml to xml & "" & q & "" & linefeed
	end if
	set xml to xml & "playlist_new.png" & linefeed
	set xml to xml & "" & linefeed

	return xml & getTags(dbid) & ""
end run

on getTags(dbid)
	-- assemble tag list

	set tags to ""
	tell application "iTunes"
		set artist_name to (get artist of the current track)
		set track_name to the name of the current track
		set pls to (get name of user playlists)
	end tell
	
	set tagsToRemove to {}
	set tagsToAdd to {}
	
	-- collect used/unused tags into lists
	repeat with pl in pls
		if pl starts with "@" then
			tell application "iTunes"
				set results to (every file track of user playlist pl whose database id is dbid)
			end tell
			
			if (count of results) > 0 then
				set end of tagsToRemove to pl
			else
				set end of tagsToAdd to pl
			end if
		end if
	end repeat
	
	repeat with pl in tagsToRemove
		set tags to tags & getItem("-", pl, dbid)
	end repeat
	
	repeat with pl in tagsToAdd
		set tags to tags & getItem("+", pl, dbid)
	end repeat
	
	return tags
	
end getTags

on getItem(prefix, myID, dbid)
	-- create tag list item

	set myIcon to ""
	tell application "iTunes"
		set track_name to the name of the current track
		set results to (every file track of playlist myID whose database id is dbid)
	end tell
	if (count of results) > 0 then
		set icon to "playlist_remove.png"
	else
		set icon to "playlist_add.png"
	end if
	
	set AppleScript's text item delimiters to "@"
	set myID to (text item 2 of myID)
	
	set myItem to ""
	set myItem to myItem & linefeed & "" & linefeed
	set myItem to myItem & "" & myID & "" & linefeed
	if prefix is equal to "+" then 
		set myItem to myItem & "Add this tag" & linefeed
	else
		set myItem to myItem & "Remove this tag" & linefeed
	end if
	set myItem to myItem & "" & icon & "" & linefeed
	set myItem to myItem & "" & linefeed
	
	return myItem
	
end getItem

on itunes_is_running()
	-- iTunes detect - too slow to use
	tell application "System Events" to return (exists process "iTunes")
end itunes_is_running

Ez pedig a tagger, ami a playlist managementet csinálja:

on run argv
	set q to argv as text

	-- create folder playlist for tags
	tell application "iTunes"
		if not (exists folder playlist "Tags") then make folder playlist with properties {name:"Tags"}
	end tell

	set tid to AppleScript's text item delimiters

	-- separate dbid and tags
	set AppleScript's text item delimiters to "|"
	set dbid to (item 1 of (text items of q))
	set tags to (item 2 of (text items of q))
	set AppleScript's text item delimiters to tid

	-- get list of tags
	set AppleScript's text item delimiters to " "
	set qList to text items of tags -- not text of, text items of
	set AppleScript's text item delimiters to tid

	-- collect add/remove tags
	set addTags to {}
	set removeTags to {}

	repeat with qItem in qList
		set prefix to (character 1 of qItem)
		if (prefix is not equal to "+") and (prefix is not equal to "-") then
			set qItem to "+" & qItem
		end if
		
		if character 1 of qItem is equal to "-" then
			set end of removeTags to getToken(qItem)
		else
			set end of addTags to getToken(qItem)
		end if
		
	end repeat

	-- add tags
	repeat with addTag in addTags
		tell application "iTunes"
			set tagFolder to folder playlist "Tags"
			if (exists playlist addTag) then
				set newTag to (playlist addTag)
			else
				set newTag to (make playlist at tagFolder with properties {name:addTag})
			end if
			
			
			set results to (every file track of playlist addTag whose database ID is dbid)
			if (count of results) = 0 then
				duplicate (current track) to newTag
			end if
		end tell
	end repeat

	-- remove tags
	repeat with removeTag in removeTags
		tell application "iTunes"
			set tagFolder to folder playlist "Tags"
			if not (exists playlist removeTag) then exit repeat
			
			set results to (every file track of playlist removeTag whose database ID is dbid)
			if (count of results) > 0 then
				delete (some track of playlist (removeTag as text) whose database ID is dbid)
			end if
		end tell
	end repeat
end run

on getToken(the_string)
	return "@" & text 2 thru length of the_string
end getToken

Ha idáig eljutsz, be kell írjak egy pirosat, annyira száraz az egész. Azonban ha hozzám hasonlóan dolgozol és neked is hiányzik az iTunes-ből a tagging funkcionalitás, akkor szeretnéd a toolt! Ha tetszik és használnád, innen vagy a packal.org-ról vihető a komplett workflow.