Retrieving the currently being played music track
One question I keep hearing is “Can you find out what music track a user is listening to? as I want to use it for …”, where the reason usually revolves around posting it to a social network network site, or using it as IM status. Thankfully retrieving the currently being played music track is very easy thanks to the MediaPlayer Framework.
Each application has its own MPMusicPlayerController, but it also has access to the iPod’s MPMusicPlayerController, using the class method iPodMusicPlayer.
MPMusicPlayerController *iPodMusicPlayerController = [MPMusicPlayerController iPodMusicPlayer];
After you have got the iPod music player, you can then get the now playing item
MPMediaItem *nowPlayingItem = [iPodMusicPlayerController nowPlayingItem];
If the now playing item is nil, you know that the user is not playing a music track on their iPod.
Unlike many of the other APIs in iOS, you can’t access information such as the track name, via a simple string property. You have to use one of the following keys:
NSString *const MPMediaItemPropertyPersistentID; NSString *const MPMediaItemPropertyMediaType; NSString *const MPMediaItemPropertyTitle; NSString *const MPMediaItemPropertyAlbumTitle; NSString *const MPMediaItemPropertyArtist; NSString *const MPMediaItemPropertyAlbumArtist; NSString *const MPMediaItemPropertyGenre; NSString *const MPMediaItemPropertyComposer; NSString *const MPMediaItemPropertyPlaybackDuration; NSString *const MPMediaItemPropertyAlbumTrackNumber; NSString *const MPMediaItemPropertyAlbumTrackCount; NSString *const MPMediaItemPropertyDiscNumber; NSString *const MPMediaItemPropertyDiscCount; NSString *const MPMediaItemPropertyArtwork; NSString *const MPMediaItemPropertyLyrics; NSString *const MPMediaItemPropertyIsCompilation; NSString *const MPMediaItemPropertyReleaseDate; NSString *const MPMediaItemPropertyBeatsPerMinute; NSString *const MPMediaItemPropertyComments; NSString *const MPMediaItemPropertyAssetURL;
And then query the Media Player Item, using the instance method valueForProperty:.
NSString *itemTitle = [nowPlayingItem valueForProperty:MPMediaItemPropertyTitle];
And thus you will end up with a code snippet like this:
MPMusicPlayerController *iPodMusicPlayerController = [MPMusicPlayerController iPodMusicPlayer]; MPMediaItem *nowPlayingItem = [iPodMusicPlayerController nowPlayingItem]; if(nowPlayingItem) { NSString *itemTitle = [nowPlayingItem valueForProperty:MPMediaItemPropertyTitle]; NSLog(@"User is playing the following song: %@",itemTitle); }else { NSLog(@"User is not playing a song"); }
As always this is just a small code snippet to get you started. There are situations for instance, where the user can have a now playing item that has no title (strange I know). So as always you will have to handle these edge cases appropriately.
Does retrieving nowPlayingItem work with non-iPod media players that are playing music in the background? (ie Pandora)
No unfortunately it wouldn’t, as they would (more than likely) be using their own audio player within their applications.
If another application used the iPod to play music, that would work.
Is there a way to use MPMediaItemPropertyPersistentID to actually play a song? I tried this and it doesn’t seem to work:
self.musicPlayer = [MPMusicPlayerController applicationMusicPlayer];
MPMediaQuery *everything = [[MPMediaQuery alloc] init];
NSArray *itemsFromGenericQuery = [everything items];
SongName = [[NSMutableArray alloc] init];
SongItem = [[NSMutableArray alloc] init];
NSString *songTitle;
NSString *songID;
//Collect names & ID for entire music library & put into arrays
for (MPMediaItem *song in itemsFromGenericQuery) {
songTitle = [song valueForProperty: MPMediaItemPropertyTitle];
[SongName addObject:songTitle];
songID = [song valueForProperty: MPMediaItemPropertyPersistentID];
[SongItem addObject:songID];
}
NSLog (@”%@”, [SongName objectAtIndex:1]);
NSLog (@”%@”, [SongItem objectAtIndex:1]);
// Play the second song in the list
MPMediaItemCollection *collection = [MPMediaItemCollection collectionWithItems:[NSArray arrayWithObject:[SongItem objectAtIndex:1]]];
[self.musicPlayer setQueueWithItemCollection:collection];
[self.musicPlayer play];
Your problem is:
MPMediaItemCollection *collection = [MPMediaItemCollection collectionWithItems:[NSArray arrayWithObject:[SongItem objectAtIndex:1]]];
collectionWithItems: expects an array of MPMediaItems, not an array of MPMediaItemPropertyPersistentIDs.
Thanks for the response! I’m pretty much a newb programmer. Are you saying I need to use a something other than collectionWithItems to use the array of MPMediaItemPropertyPersistentIDs ? If so, what would I use?
Any code example you you could provide would be deeply helpful.
Thanks ahead of time!
Take this bit of code:
for (MPMediaItem *song in itemsFromGenericQuery) {
songTitle = [song valueForProperty: MPMediaItemPropertyTitle];
[SongName addObject:songTitle];
songID = [song valueForProperty: MPMediaItemPropertyPersistentID];
[SongItem addObject:songID];
}
You are looping through an array of MPMediaItems (what you need to pass to the player), and you are then storing an array of song titles and an array of song IDs.
So you have two options:
1) Keep an array of the MPMediaItems
2) Use the MPMediaItemPropertyPersistentID of the MPMediaItems, to retrieve it at a later point. MPMediaPropertyPredicate should do that for you.
Got it! Here is my implementation:
MPMediaPropertyPredicate *predicate = [MPMediaPropertyPredicate predicateWithValue:[SongItem objectAtIndex:1] forProperty:MPMediaItemPropertyPersistentID];
MPMediaQuery *mySongQuery = [[MPMediaQuery alloc] init];
[mySongQuery addFilterPredicate: predicate];
[musicPlayer setQueueWithQuery:mySongQuery];
[musicPlayer play];
Works like a charm! Thanks for your input!!!!
Glad I could help
If you make an application, let me know what it is.