Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

nullx86

macrumors 6502a
Original poster
Jun 26, 2009
884
1
Wilmington/Jacksonville, NC
I know it can be done, because of Adium and Windows Live Messengers ability to report what song is playing, so my question, is there a way to have iTunes dump whatever is played to a text document? I want to do this to keep track of what songs I listen to over a radio stream. If anyone has any ideas, please post them, I have no clue how to make this happen. Thanks.
 
I don't have something ready-made, but it seems like AppleScript is the way to go. My suggestion would be to have an AppleScript that is always running when you are wanting this task performed. You can get the current track's artist and title, store this in a property, then sleep some amount of time. I would say the length of the shortest possible song minus 15 seconds, etc. Then wake up and check again. If the track is different, record the saved values to your file. If not, sleep again.

I am very unskilled at AppleScript, but I think this could be done in a dozen lines or so.

-Lee
 
I don't have something ready-made, but it seems like AppleScript is the way to go. My suggestion would be to have an AppleScript that is always running when you are wanting this task performed. You can get the current track's artist and title, store this in a property, then sleep some amount of time. I would say the length of the shortest possible song minus 15 seconds, etc. Then wake up and check again. If the track is different, record the saved values to your file. If not, sleep again.

I am very unskilled at AppleScript, but I think this could be done in a dozen lines or so.

-Lee


yeah exactly what i want, i just know jack about how to do it
 
Code:
set saveTrack to ""
repeat
	tell application "iTunes"
		set trackName to artist of current track & " - " & name of current track
	end tell
	if trackName is not equal to saveTrack then
		if saveTrack is not equal to "" then
			do shell script "echo \"" & saveTrack & "\" >>~/SongList.txt"
		end if
		set saveTrack to trackName
	end if
	do shell script "sleep 5"
end repeat

13. That's about a dozen.

Code:
set saveTrack to ""
repeat
	tell application "iTunes"
		set trackName to artist of current track & " - " & name of current track
	end tell
	if trackName is not equal to saveTrack then
		if saveTrack is not equal to "" then do shell script "echo \"" & saveTrack & "\" >>~/SongList.txt"
		set saveTrack to trackName
	end if
	do shell script "sleep 5"
end repeat

Down to 11! a little more difficult to extend in the future, though.

The things you might want to tweak:
What is actually getting set for trackname. Now it's artist - title, but you can get any of these things that are a property of a track:
album (text) : the album name of the track
album artist (text) : the album artist of the track
album rating (integer) : the rating of the album for this track (0 to 100)
album rating kind (user/computed, r/o) : the rating kind of the album rating for this track
artist (text) : the artist/source of the track
bit rate (integer, r/o) : the bit rate of the track (in kbps)
bookmark (real) : the bookmark time of the track in seconds
bookmarkable (boolean) : is the playback position for this track remembered?
bpm (integer) : the tempo of this track in beats per minute
category (text) : the category of the track
comment (text) : freeform notes about the track
compilation (boolean) : is this track from a compilation album?
composer (text) : the composer of the track
database ID (integer, r/o) : the common, unique ID for this track. If two tracks in different playlists have the same database ID, they are sharing the same data.
date added (date, r/o) : the date the track was added to the playlist
description (text) : the description of the track
disc count (integer) : the total number of discs in the source album
disc number (integer) : the index of the disc containing this track on the source album
duration (real, r/o) : the length of the track in seconds
enabled (boolean) : is this track checked for playback?
episode ID (text) : the episode ID of the track
episode number (integer) : the episode number of the track
EQ (text) : the name of the EQ preset of the track
finish (real) : the stop time of the track in seconds
gapless (boolean) : is this track from a gapless album?
genre (text) : the music/audio genre (category) of the track
grouping (text) : the grouping (piece) of the track. Generally used to denote movements within a classical work.
kind (text, r/o) : a text description of the track
long description (text)
lyrics (text) : the lyrics of the track
modification date (date, r/o) : the modification date of the content of this track
played count (integer) : number of times this track has been played
played date (date) : the date and time this track was last played
podcast (boolean, r/o) : is this track a podcast episode?
rating (integer) : the rating of this track (0 to 100)
rating kind (user/computed, r/o) : the rating kind of this track
release date (date, r/o) : the release date of this track
sample rate (integer, r/o) : the sample rate of the track (in Hz)
season number (integer) : the season number of the track
shufflable (boolean) : is this track included when shuffling?
skipped count (integer) : number of times this track has been skipped
skipped date (date) : the date and time this track was last skipped
show (text) : the show name of the track
sort album (text) : override string to use for the track when sorting by album
sort artist (text) : override string to use for the track when sorting by artist
sort album artist (text) : override string to use for the track when sorting by album artist
sort name (text) : override string to use for the track when sorting by name
sort composer (text) : override string to use for the track when sorting by composer
sort show (text) : override string to use for the track when sorting by show name
size (integer, r/o) : the size of the track (in bytes)
start (real) : the start time of the track in seconds
time (text, r/o) : the length of the track in MM:SS format
track count (integer) : the total number of tracks on the source album
track number (integer) : the index of the track on the source album
unplayed (boolean) : is this track unplayed?
video kind (none/movie/music video/TV show) : kind of video track
volume adjustment (integer) : relative volume adjustment of the track (-100% to 100%)
year (integer) : the year the track was recorded/released

Otherwise, the sleep of 5 is way low, i did that for testing. 1 minute seems to be reasonable, but you'll need to tweak this to the "right" value for you.

Also, i have it logging in my home directory to SongList.txt. You can tweak this in the "do shell script" line.

-Lee
 
iTunes posts a notification with player status changes as of version 4.7, so if you've got Xcode tools installed you can make an cocoa application to do this for you (without having to poll).

Using the standard application template you need to add to the ApplicationDelegate this:

Code:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
	NSDistributedNotificationCenter *notificationCenter = [NSDistributedNotificationCenter defaultCenter];
	
	[notificationCenter addObserver:self
			selector:@selector(log:)
				name:@"com.apple.iTunes.playerInfo"
			  object:nil];
	
	[NSApp hide:nil];
}

Which simply registers the application to be given status updates, and this:

Code:
- (void)log:(id)sender
{
	NSAppleScript *script = [[NSAppleScript alloc] initWithSource:@"tell application \"iTunes\" \n\
							 if player state is playing then \n\
							 set trackName to name of current track\n\
							 set trackArtist to artist of current track\n\
							 end if\n\
							 end tell\n\
							 \n\
							 return trackName & \" – \" & trackArtist "];
	
	NSAppleEventDescriptor *eventDesc = [script executeAndReturnError:nil];
		
	NSString *filePath = NSHomeDirectory();
	filePath = [filePath stringByAppendingPathComponent:@"songLog.txt"];
	
	NSFileManager *dfm = [NSFileManager defaultManager];
	
	if (![dfm fileExistsAtPath:filePath]) {
		[@"" writeToFile:filePath
			  atomically:NO
				encoding:NSUTF8StringEncoding
				   error:nil];
	}
	
	NSString *trackname = [eventDesc stringValue];
	
	if (trackname) {
		trackname = [trackname stringByAppendingString:@"\n"];
		NSFileHandle *newHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
		[newHandle seekToEndOfFile];
		[newHandle writeData:[trackname dataUsingEncoding:NSUTF8StringEncoding]];
	}	

	[script release];
}

Which queries iTunes for it's currently playing song (as per previously discussed) and writes it to the end of the file "songLog.txt" in your home directory.

You can then add this application to your login items to have it run when you log in.

EDIT: attaching a zip for the application if you can't be bothered with all that...
 

Attachments

  • iTunesListener.zip
    30.3 KB · Views: 134
iTunes posts a notification with player status changes as of version 4.7, so if you've got Xcode tools installed you can make an cocoa application to do this for you (without having to poll).

Using the standard application template you need to add to the ApplicationDelegate this:

Code:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    NSDistributedNotificationCenter *notificationCenter = [NSDistributedNotificationCenter defaultCenter];
    
    [notificationCenter addObserver:self
            selector:@selector(log:)
                name:@"com.apple.iTunes.playerInfo"
              object:nil];
    
    [NSApp hide:nil];
}
Which simply registers the application to be given status updates, and this:

Code:
- (void)log:(id)sender
{
    NSAppleScript *script = [[NSAppleScript alloc] initWithSource:@"tell application \"iTunes\" \n\
                             if player state is playing then \n\
                             set trackName to name of current track\n\
                             set trackArtist to artist of current track\n\
                             end if\n\
                             end tell\n\
                             \n\
                             return trackName & \" – \" & trackArtist "];
    
    NSAppleEventDescriptor *eventDesc = [script executeAndReturnError:nil];
        
    NSString *filePath = NSHomeDirectory();
    filePath = [filePath stringByAppendingPathComponent:@"songLog.txt"];
    
    NSFileManager *dfm = [NSFileManager defaultManager];
    
    if (![dfm fileExistsAtPath:filePath]) {
        [@"" writeToFile:filePath
              atomically:NO
                encoding:NSUTF8StringEncoding
                   error:nil];
    }
    
    NSString *trackname = [eventDesc stringValue];
    
    if (trackname) {
        trackname = [trackname stringByAppendingString:@"\n"];
        NSFileHandle *newHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
        [newHandle seekToEndOfFile];
        [newHandle writeData:[trackname dataUsingEncoding:NSUTF8StringEncoding]];
    }    

    [script release];
}
Which queries iTunes for it's currently playing song (as per previously discussed) and writes it to the end of the file "songLog.txt" in your home directory.

You can then add this application to your login items to have it run when you log in.

EDIT: attaching a zip for the application if you can't be bothered with all that...

thanks for the zip, i just tried that, il try to compile something in xcode later, im a total noob with this...

uhh, the zipped app you attached. the code said it would save in home, i checked, and sure enough, the file is there, but it isnt getting stream vaules correctly. Also, the stream connects are duplicated. Any ideas on this?

Code:
Distortion Radio – missing value
Distortion Radio – missing value
THE EDGE 103.9 – missing value
THE EDGE 103.9 – missing value
Rescue Me – Buckcherry
THE EDGE 103.9 – missing value
THE EDGE 103.9 – missing value

Rescue Me was a local file on my iMac, just as a test. The two images below show that the song title is shown, and the radio title is shown as well. I tried this on Distortion Radio as well, which only has a static display of the song/artist name. Thanks guys.
 

Attachments

  • Screen shot 2009-12-29 at 2.42.58 AM.png
    Screen shot 2009-12-29 at 2.42.58 AM.png
    20.8 KB · Views: 93
  • Screen shot 2009-12-29 at 2.43.03 AM.png
    Screen shot 2009-12-29 at 2.43.03 AM.png
    23.3 KB · Views: 101
thanks for the zip, i just tried that, il try to compile something in xcode later, im a total noob with this...

uhh, the zipped app you attached. the code said it would save in home, i checked, and sure enough, the file is there, but it isnt getting stream vaules correctly. Also, the stream connects are duplicated. Any ideas on this?

Not sure about the duplicate entries, but the 'missing value' issue is because the radio station doesn't provide a value iTunes interprets as an artist. You'll need to find out what value the radiostation uses as it's description ("KILLERS - SOMEBODY TOLD ME" on the screen shot you posted) and modify the code appropriately. I can't find what this value is, lee posted all the possible ones, so it could be that you can't get this information through applescript.
 
Another (possible) problem here is that the stream may show up as a single "track". That's to say, song to song, DJ to commercials, etc. it may not "change tracks". Hopefully if you can find the "banner message" they send, that's enough to tell when things change. What field those things in, though, is a mystery. I'd try description and comment next to see if that's where itunes is sticking that extra info.

-Lee
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.