Getting the most played track out of the iPod library (MPMediaQuery) - iphone

I need to get out the 25 most Played Songs out from my iPod Library with my iPhone app. i am using a MPMediaQuery.
One solutions would be to loop through all tracks and them comparing by MPMediaItemPropertyAlbumTrackCount. But i think thats a bit unefficient. Is there a way to directly get the Most Played items playlist?

I think you are looking for MPMediaItemPropertyPlayCount not MPMediaItemPropertyAlbumTrackCount. MPMediaItemPropertyAlbumTrackCount is the track number of the song as it appears in its album.
MPMediaItemPropertyPlayCount unfortunately cannot be used for making queries with MPMediaQuery since it is a user-defined property.
Your best option is to store all the play counts in a database like Core Data when your app is opened for the first time and update it by registering for notifications when the user's library changes.

you can use NSSortDescriptor to sort the most played songs
MPMediaQuery *everything = [[MPMediaQuery alloc] init];
NSSortDescriptor *sorter = [NSSortDescriptor sortDescriptorWithKey:MPMediaItemPropertyPlayCount ascending:NO];
NSArray *sortedSongsArray = [[everything items] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]];

Related

Which method to use to extract frames from the video in iphone?

I am working on app where I am supposed to extract the frames of video.So after doing lot of R&D i found following methods.
1)Using iFrameExtractor which uses ffmpeg framework https://github.com/lajos/iFrameExtractor.
2)Using built in property of MPMoviePlayerController
MPMoviePlayerController *movie = [[MPMoviePlayerController alloc] initWithContentURL: [NSURL URLWithString:#"Video.mp4"]];
NSNumber t1 = 10;
NSNumber t2 = 11;
NSArray *TimeStamp = [NSArray arrayWithObjects:t1,t2,nil];
[movie requestThumbnailImagesAtTimes:TimeStamp timeOption:MPMovieTimeOptionExact];
3)Using AVAssetImageGenerator
So I am confused of using which method to choose.Any one please tell me the right method by listing demerits of other methods.
I have extract all the frames of video(which can be of maximum 2 minutes)
Thanks in Advance. :)
You are going to have some legal issues to deal with attempting to use ffmpeg compiled into an iOS application, see compatibility-between-the-iphone-app-store-and-the-lgpl for more on that. I had not heard of AVAssetImageGenerator before, but that copyCGImageAtTime method seems like exactly what you would want for small thumbnails, it should be easy to create a UIImage and pass in the returned CGImageRef and then save the result as a PNG. The requestThumbnailImagesAtTimes API likely just calls AVAssetImageGenerator anyway.

MPMediaPickerController.showsCloudItems seems to do nothing

Posted this on Apple with no luck, but now that the iOS 6 NDA is up, hoping more eyes will see it here.
I am attempting to modify an app to only allow a user to select music that has been downloaded locally. I have the following code under iOS 6 GM:
MPMediaPickerController* mpc = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeAnyAudio];
mpc.allowsPickingMultipleItems = YES;
mpc.modalPresentationStyle = UIModalPresentationCurrentContext;
mpc.showsCloudItems = NO;
[self presentViewController:mpc animated:YES completion:nil];
From the documentation:
The default behavior for a media item picker is YES, which means the
the picker shows available iCloud items. A media item is considered an
iCloud item if it is available via iTunes Match and is not already
stored on the device.
I take this to mean that if iTunes Match is enabled, only items that have been downloaded to the device will show in the picker, however I always see the entire iTunes Match library. I filed a radar for this, because it seems like a serious bug. If anyone can tell me otherwise, I'd love to know what I'm missing here.
This seems to be an OS problem.
Using picker.showsCloudItems = NO; correctly shows fewer songs, instead of the whole list... The songs listed there are songs that either were manually downloaded in the Music app or songs that were streamed and therefore cached.
The problem, at least in my case, is dealing with the cached ones.
If I select a song that was manually downloaded the value of MPMediaItemPropertyIsCloudItem is NO, which is correct. I can also access the asset's URL through the MPMediaItemPropertyAssetURL property.
On the other hand, selecting a song that was cached returns YES on MPMediaItemPropertyIsCloudItem and nil on MPMediaItemPropertyAssetURL, making the song virtually useless to me.
Sorry I don't have an actual answer but I don't have enough reputation to simply comment.
Hope my 2 cents help somehow, but it truly seems to me that this issue can only be resolved by Apple in a future update.
A better solution to test if an item comes from iCloud in the didPickMediaItems delegate:
MPMediaItem *selectedItem = [selectedItems objectAtIndex:0];
if (![[selectedItem valueForProperty:MPMediaItemPropertyIsCloudItem] boolValue])
You don't really need to play it, it is more efficient to use the embedded property in the MPMediaItem.
I had this same problem. Although I was unable to hide the items, here's a good workaround that I used to prevent people from being able to select them. Inside didPickMediaItems, you should temporarily load it into an AVPlayerItem and then just check the validity of that item like so:
- (void)mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
MPMediaItem *selectedItem = [[mediaItemCollection items]objectAtIndex:0];
NSURL *tempURL = [selectedItem valueForProperty:MPMediaItemPropertyAssetURL];
AVPlayerItem *playerItem = [[AVPlayerItem alloc]initWithURL:tempURL];
if(playerItem.loadedTimeRanges==NULL)
{
UIAlertView *alert=[[[UIAlertView alloc]initWithTitle:NSLocalizedString(#"Invalid Song Choice",NULL) message:NSLocalizedString(#"Please choose a song that is local to your phone.",NULL) delegate:self cancelButtonTitle:NSLocalizedString(#"Okay",NULL) otherButtonTitles:nil]autorelease];
[alert show];
[playerItem release];
}
else
{
NSLog(#"Your good to go...do whatever you want with the local song");
}
}
It appears to be fixed in iOS 7.
The following code works; iCloud items are not showing:
MPMediaPickerController *picker = [[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
picker.delegate = self;
picker.allowsPickingMultipleItems = NO;
picker.showsCloudItems = NO;

iOS: Displaying currently played track info in LockScreen?

As of iOS 5 we have access to MPNowPlayingInfoCenter to display info in the lockscreen and in the multimedia controls on the multitasking bar. I have an app that plays local audio files. I want to display info like the artist's name, the album and the artwork on the lockscreen with MPNowPlayingInfoCenter, but the only way to do this (As far as I know) is to use MPMusicPlayerController and get nowPlayingItem... The problem is that MPMusicPlayerController is used to play iPod Music only, and not locally stored files. Is there a way around this in iOS 5?
You can create your own NSDictionary and supply that to the MPNowPlayingInfoCenter.
NSArray *keys = [NSArray arrayWithObjects:MPMediaItemPropertyAlbumTitle, MPMediaItemPropertyArtist, ..., nil];
NSArray *values = [NSArray arrayWithObjects:#"Album", #"Artist", ..., nil];
NSDictionary *mediaInfo = [NSDictionary dictionaryWithObjects:values forKeys:keys];
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:mediaInfo];

Sort List Based On Custom User Settings

I'm working on an app where a user can upload and download information. The information is downloaded in such a way that when it's downloaded, it's ordered according to when it was submitted.
What I'd like is for the user to be able to reorganize the table view, save the order to a preference file (all ready working) and from now on, whenever data is request, the order now conforms to the users re-organized list.
Maybe my brains just fried, but is there an array function that can accomplish this, or am I on my own? Any suggestions how to go about writing something like this?
Thanks
What about NSSortDescriptor:
NSArray *sortedArray = [originalArray sortedArrayUsingDescriptors:
[NSArray arrayWithObject:
[[[NSSortDescriptor alloc] initWithKey:#"keyToBeSorted"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)] autorelease]]];

Load songs from iPod Library right after sync

I'm developing an iPhone application that uses the iPod library to play some songs. I load the songs with the code below. The problem is, when running this code right after the device has been synced with iTunes, there is a problem. Apparently the iPod Library needs to be updated, and it takes some time. If I go to the iPod Application right after a sync I seen a message saying "Updating Library..". If i call "[query items]" from my application while that is happening, I get an empty array indicating there is no songs in the library. Everything works perfect when the update is over. Is there any way to solve this problem? Maybe a way to detect when the update is over. I have tried to listen to alle NSNotifications, but none were called when the update finished.
MPMediaQuery *query = [MPMediaQuery songsQuery];
// convert all items to abstracted media item
NSArray *items = [query items];
NSMutableArray *convertedItems = [[NSMutableArray alloc] initWithCapacity:[items count]];
for (MPMediaItem *item in items) {
REMediaItem *mediaItem = [[REMediaItem alloc] initWithMediaItem:item];
[convertedItems addObject:mediaItem];
[mediaItem release];
}
I hope someone can help.
Peter
I discovered that there actually is a way to see when the update is complete. The device will post a notification when the update is over.
[[MPMediaLibrary defaultMediaLibrary] beginGeneratingLibraryChangeNotifications]
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:#selector(iPodLibraryDidChange)
name: MPMediaLibraryDidChangeNotification
object:nil];
The only problem is that I can't find a way to determinate if the device is updating the iPod Library and I should wait for it to finish or the device simply doesnt have any songs in the library. [query items] will return an empty array in both cases.
#Peter is right - and actually I found a walkaround for his problem.
At first I found that MPMediaPickerController returns nil when allocated and initiated while syncing - at first I thought it will work to check if there's an access to the library but sometimes it doesn't work.
The only way for now I found is to check lastModificationDate of MPMediaLibrary - as long as it's changing you won't get results using MPMediaQuery - delay your changes to a moment when that property stops changing (by any way you like) and you should be fine.
Already sent a bug report on that - the documentation says you should reload your cached objects from library when the notification fires but you clearly can't do it if MPMediaQuery returns nil for every object you try to find.