Get album year for item in iPod library? - iphone

Trying the following code:
// Per albums
MPMediaQuery *albumsQuery = [MPMediaQuery albumsQuery];
NSArray *collections = [albumsQuery collections];
for (MPMediaItemCollection *collection in collections)
{
NSDate *collectionReleaseDate = [collection valueForProperty: MPMediaItemPropertyReleaseDate];
NSLog(#"collection release date: %#", collectionReleaseDate);
MPMediaItem *representativeItem = [collection representativeItem];
NSDate *representativeItemReleaseDate = [representativeItem valueForProperty: MPMediaItemPropertyReleaseDate];
NSLog(#"representativeItem release date: %#", representativeItemReleaseDate);
}
// Just per item
MPMediaQuery *query = [[MPMediaQuery alloc] init];
NSArray *items = [query items];
for (MPMediaItem *item in items)
{
NSDate *date = [item valueForProperty: MPMediaItemPropertyReleaseDate];
NSLog(#"release date: %#", date);
}
In all cases I get nil's for NSDates...
But in the iPod library I can see dates, so the information must be available.
What is the correct way to obtain it?

Well, I think I've figured it out. I was thinking that 'Year' column in iTunes corresponds to MPMediaItemPropertyReleaseDate in API - but it's wrong. My items actually weren't having release date info.
I also found how to obtain 'Year' information (which I needed), but unfortunately in undocumented way:
MPMediaItem *item = ...;
NSNumber *yearNumber = [item valueForProperty:#"year"];
if (yearNumber && [yearNumber isKindOfClass:[NSNumber class]])
{
int year = [yearNumber intValue];
if (year != 0)
{
// do something with year
}
}

Related

iPhone - How to import native calendar events to my iphone app?

I am doing one simple application using iPhone calendar, where I need to import the iPhone native calendar events into my iPhone app. How can I do this. I have a piece of code but it doesn't seems to be working. I have added some events into my iPhone native calendar. But when i retrieve it's not fetching anything. Here is the piece of code.
-(IBAction)importCalEvents:(id)sender
{
NSArray *caleandarsArray = [[NSArray alloc] init];
caleandarsArray = [[eventStore calendars] retain];
NSLog(#"Calendars from Array : %#", caleandarsArray);
for (EKCalendar *CalendarEK in caleandarsArray)
{
NSLog(#"Calendar Title : %#", CalendarEK.title);
}
}
you can fetch all the calendar events like this.
import these 2 framworks (add if not exists into your project).
1 EventKit/EventKit.h
2) EventKitUI/EventKitUI.h
call this function on button click
-(void)EventList{
EKEventStore *eventStore = [[EKEventStore alloc] init];
NSDate *startDate = [[NSDate alloc] init];
NSDate *endDate = [[NSDate alloc] initWithTimeInterval:3600 sinceDate:startDate];
NSArray *calendars = [eventStore calendars];
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:startDate
endDate:endDate calendars:calendars];
NSArray *matchingEvents = [eventStore eventsMatchingPredicate:predicate];
EKEvent *anEvent;
NSLog(#"Total Events >> %d",[matchingEvents count]);
for (int j=0; j < [ matchingEvents count]; j++) {
anEvent = [matchingEvents objectAtIndex:j];
NSLog(#"Title >>>%#",anEvent.title);
NSLog(#"start date is %# \n End Date is >>> %#",anEvent.startDate,anEvent.endDate);
}
}
And set the startDate and EndDate as per your Requirement.
so you can get all the detatils you want.
Best Luck..

parsing calender events

In my application I am retrieving all calender events using eventkit framework. Now I have parse it in to json to upload it to server. what is the best way to do this, kindly give me an idea if there are any parser libraries or framework which can parse calendar events. Below is the code i used to retrieve events
- (NSMutableArray *)fetchallevents {
NSDate *start = [NSDate distantPast];
NSLog(#"start date is : %#",start);
NSDate *finish = [NSDate distantFuture];
NSLog(#"start date is : %#",finish);
// use Dictionary for remove duplicates produced by events covered more one year segment
NSMutableDictionary *eventsDict = [NSMutableDictionary dictionaryWithCapacity:1024];
NSDate* currentStart = [NSDate dateWithTimeInterval:0 sinceDate:start];
int seconds_in_year = 60*60*24*365;
// enumerate events by one year segment because iOS do not support predicate longer than 4 year !
while ([currentStart compare:finish] == NSOrderedAscending) {
NSDate* currentFinish = [NSDate dateWithTimeInterval:seconds_in_year sinceDate:currentStart];
if ([currentFinish compare:finish] == NSOrderedDescending) {
currentFinish = [NSDate dateWithTimeInterval:0 sinceDate:finish];
}
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:currentStart endDate:currentFinish calendars:nil];
[eventStore enumerateEventsMatchingPredicate:predicate
usingBlock:^(EKEvent *event, BOOL *stop) {
if (event) {
[eventsDict setObject:event forKey:event.eventIdentifier]; } }];
currentStart = [NSDate dateWithTimeInterval:(seconds_in_year + 1) sinceDate:currentStart];
}
NSMutableArray *events =[[eventsDict allValues]mutableCopy];
//NSLog(#"the evenets for the day is : %#", events);
return events;
}

How to play songs (only songs) from a playlist on iOS?

I'm trying to play songs from an iPod playlist. As far as playlist may have videos too, I want to play only songs in them.
MPMusicPlayerController *mp = [MPMusicPlayerController applicationMusicPlayer];
MPMediaQuery *query = [MPMediaQuery songsQuery];
query.groupingType = MPMediaGroupingPlaylist;
NSArray *playlists = [query collections];
BOOL found = NO;
for(MPMediaPlaylist *playlist in playlists)
{
NSString *name = [playlist valueForProperty:MPMediaPlaylistPropertyName];
if([name caseInsensitiveCompare:#"MyPlaylist"] == NSOrderedSame && [playlist count] > 0)
{
MPMediaItemCollection *collection = [MPMediaItemCollection collectionWithItems:playlist.items];
[mp setQueueWithItemCollection:collection];
found = YES;
NSLog(#"items count %d", [playlist count]);
for (MPMediaItem *item in [collection items]){
NSLog(#"%#", [item valueForKey:MPMediaItemPropertyMediaType]);
}
break;
}
}
After I load a playlist with 1 song a 2 videos, the output is:
items count 3
256
256
1
I don't understand why I'm getting videos too, if the query is intended to retrieve songs, and media items have media type MPMediaTypeMovie (256 or 1 << 8).
Any suggestion?
One possible workaround would be to create a custom query using predicates. This can be implemented by using the MPMediaQuery items array rather than the collections array. The collections array is an array of MPMediaItemCollections. The items array is an array of MPMediaItems, so you can filter the query by MPMediaItemPropertyMediaType. MPMediaItemPropertyMediaType is only applicable to a MPMediaItem and not a MPMediaItemCollection.
Initialize the query with a set of predicates based on the playlist title and media type. This will select your playlist and filter out any videos from the query:
NSString *playlistName = #"MyPlaylist";
MPMediaPropertyPredicate *playlistPredicate = [MPMediaPropertyPredicate predicateWithValue:playlistName
forProperty:MPMediaPlaylistPropertyName];
NSNumber *mediaTypeNumber = [NSNumber numberWithInteger:MPMediaTypeMusic]; // == 1
MPMediaPropertyPredicate *mediaTypePredicate = [MPMediaPropertyPredicate predicateWithValue:mediaTypeNumber
forProperty:MPMediaItemPropertyMediaType];
NSSet *predicateSet = [NSSet setWithObjects:playlistPredicate, mediaTypePredicate, nil];
MPMediaQuery *mediaTypeQuery = [[MPMediaQuery alloc] initWithFilterPredicates:predicateSet];
[mediaTypeQuery setGroupingType:MPMediaGroupingPlaylist];
These MPMediaPropertyPredicates will NOT filter if you return your array from the MPMediaQuery collections array. You should see media item types other than 1 in the log statements:
NSArray *playlistCollections = [mediaTypeQuery collections];
[playlistCollections enumerateObjectsUsingBlock:^(MPMediaPlaylist *playlist, NSUInteger idx, BOOL *stop) {
NSLog (#"Playlist title: %#", [playlist valueForProperty:MPMediaPlaylistPropertyName]);
NSArray *songs = [playlist items];
[songs enumerateObjectsUsingBlock:^(MPMediaItem *song, NSUInteger idx, BOOL *stop) {
NSString *songTitle = [song valueForProperty:MPMediaItemPropertyTitle];
NSInteger mediaValue = [[song valueForProperty:MPMediaItemPropertyMediaType] integerValue];
if (mediaValue != 1)
NSLog(#"title: %# - media type value: %d", songTitle, mediaValue);
}]; // Should return other media types here.
}];
The MPMediaPropertyPredicates WILL filter if you return your array from MPMediaQuery items:
NSArray *playlistItems = [mediaTypeQuery items];
[playlistItems enumerateObjectsUsingBlock:^(MPMediaItem *song, NSUInteger idx, BOOL *stop) {
NSString *songTitle = [song valueForProperty: MPMediaItemPropertyTitle];
NSInteger mediaValue = [[song valueForProperty:MPMediaItemPropertyMediaType] integerValue];
if (mediaValue != 1)
NSLog(#"title: %# - media type value: %d", songTitle, mediaValue);
}]; // Should return nothing here.
You could also apply a media type filter to your entire library by using only the mediaTypePredicate on the songsQuery:
MPMediaQuery *query = [MPMediaQuery songsQuery];
[query setGroupingType:MPMediaGroupingPlaylist];
[mediaTypeQuery addFilterPredicate:mediaTypePredicate];
NSArray *playlists = [query items];

Extracting specific data from a Mutable Dictionary

I have a Mutable Dictionary which allows people to choose a selection of days of the week. Once a day has been selected the state is updated using numberWithBool.
When I NSLog the output it looks something like this:
{
day = Monday;
isSelected = 1;
},
{
day = Tuesday;
isSelected = 0;
},
{
day = Wednesday;
isSelected = 0;
},
{
day = Thursday;
isSelected = 0;
},
{
day = Friday;
isSelected = 0;
},
{
day = Saturday;
isSelected = 0;
},
{
day = Sunday;
isSelected = 1;
}
I would like to be able to extract the chosen days and produce the output in the form of a string. So in this example the output would be: Monday, Sunday
How can I do this?
My code for creating the dictionary is below:
NSMutableArray * tempSource = [[NSMutableArray alloc] init];
NSArray *daysOfWeek = [NSArray arrayWithObjects:#"Monday", #"Tuesday", #"Wednesday", #"Thursday", #"Friday", #"Saturday", #"Sunday",nil];
for (int i = 0; i < 7; i++)
{
NSString *dayOfWeek = [daysOfWeek objectAtIndex:i];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:dayOfWeek, #"day", [NSNumber numberWithBool:NO], #"isSelected",nil];
[tempSource addObject:dict];
}
[self setSourceArray:tempSource];
[tempSource release];
You can loop thru all of your items in the array and build a side-array only containing names of the day (1), or you can use a predicate and then KVC to extract the days directly (2).
Then join the components of the filtered array into a string.
Solution 1:
NSMutableArray selectedDays = [[NSMutableArray alloc] init];
for(NSDictionary* entry in sourceArray)
{
if (([entry objectForKey:#"isSelected"] boolValue]) {
[selectedDays addObject:[entry objectForKey:#"day"]];
}
}
NSString days = [selectedDays componentsJoinedByString:#", "];
[selectedDays release];
Solution 2:
NSPredicate* filter = [NSPredicate predicateWithFormat:#"SELF.isSelected == 1"]; // not sure about the exact format (no mac here to test right now so you may adapt a bit if it does not work directly)
// get the array of dictionaries but only the ones that have isSelected==1
NSArray selectedEntries = [sourceArray filteredArrayUsingPredicate:filter];
NSArray selectedDays = [selectedEntries valueForKey:#"day"]; // extract the "days" keys of the dictionaries. We have a NSArray of strings then.
NSString days = [selectedDays componentsJoinedByString:#", "];
As a side note, your way of doing this is quite strange. Why having an NSArray of NSDictionaries for this? As this is simple and a static-size array containing only BOOL, you may instead for this particular case simply use C array BOOL selected[7] and nothing more.
Then to have the name of the weekdays you should instead use the methods of NSCalendar/NSDateFormatter/NSDateComponents to get the standard names of the weekdays (automatically in the right language/locale of the user): create an NSDate using a NSDateComponent for which you simply define the weekday component, then use an NSDateFormatter to convert this to a string, choosing a string format that only display the weekday name.
-(void)tableView:(UITableView*)tv didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
// selectedDays is an instance variable in .h declared as
// BOOL selectedDays[7];
selectedDays[indexPath.row] = ! selectedDays[indexPath.row];
[tv reloadData];
}
-(UITableViewCell*)tableView:(UITableView*)tv cellForRowAtIndexPath:(NSIndexPath*)indexPath {
static NSString* kCellIdentifier = #"DayCell";
UITableViewCell* cell = [tv dequeueReusableCellWithIdentifier:kCellIdentifier];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:... identifier:kCellIdentifier]; autorelease];
// configure here every property that is common to all for your cells (text color, etc)
}
// configure here things that will change from cell to cell
cell.accessoryType = selectedDays[indexPath.row] ? UITableViewCellAccessoryTypeCheckmarck : UITableViewCellAccessoryTypeNone;
cell.textLabel.text = weekdayName(indexPath.row);
return cell;
}
// Simple C function to return the name of a given weekday
NSString* weekdayName(int weekday)
{
#if WAY_1
/**** Solution 1 ****/
// Optimization note: You may compute this once for all instead of recomputing it each time
NSDateComponents* comp = [[[NSDateComponents alloc] init] autorelease];
[comp setWeekday:weekday+1]; // weekdays start at 1 for NSDateComponents
NSDate* d = [[NSCalendar currentCalendar] dateFromComponents:comp];
NSDateFormatter* df = [[[NSDateFormatter alloc] init] autorelease];
[df setDateFormat:#"EEEE"]; // format for the weekday
return [[df stringFromDate:d] capitalizedString];
#else
/**** Solution 2 ****/
NSDateFormatter* df = [[[NSDateFormatter alloc] init] autorelease];
NSArray* weekdayNames = [df weekdaySymbols]; // or maybe one of its sibling methods? check what is returned here to be sure
return [weekdayNames objectAtIndex:weekday];
#endif
}
Is there a reason that you avoid NSMutableIndexSet?
It may simplify your code to:
NSArray *daysOfWeek = ...;
NSMutableIndexSet *indexesOfSelectedDays = ...;
NSArray *selectedDays = [daysOfWeek objectsAtIndexes:indexesOfSelectedDays];
Use NSPredicate to create a predicate that selects the items in the array where isSelected is true, and use that to filter the array using NSArray's -filteredArrayUsingPredicate: method. (#Miraaj posted a good example of using a predicate faster than I could type it.) Then take that filtered array and pick out the days, like this:
NSArray *selectedItems = [sourceArray filteredArrayUsingPredicate:somePredicate];
NSArray *days = [selectedItems valueForKey:#"day"];
NSString *daysString = [days componentsJoinedByString#", "];

How do I get all songs from the iPhone music library from a specific year?

Hi Stack Overflowers, I'm hoping you might be able to help me.
I'm trying to get a collection of all songs in a users iPhone music library from a specific year i.e 2002.
I'm then looking to play the songs through a MPMusicPlayerController.
It seems that you can't set up a MPMediaPropertyPredicate to filter by release date which I think rules that out. What I don't really want to do is have to get a full array of all track release dates and then iterate all the NSDates as I (perhaps wrongly) expect this could be quite slow for large libraries.
What is the best way of achieving this task?
Thanks in advance.
here is what you are looking for.
allMedia = [MPMediaQuery songsQuery];
//MPMediaPropertyPredicate *mpp1 = [MPMediaPropertyPredicate predicateWithValue:#"2" forProperty:MPMediaItemPropertyRating comparisonType:MPMediaPredicateComparisonEqualTo];
//MPMediaPropertyPredicate *mpp2 = [MPMediaPropertyPredicate predicateWithValue:#"Pop" forProperty:MPMediaItemPropertyGenre comparisonType:MPMediaPredicateComparisonContains];
//[allMedia addFilterPredicate:mpp1];
//[allMedia addFilterPredicate:mpp2];
//[myPlayer setQueueWithQuery:allMedia];
NSArray *itemsFromGenericQuery = [allMedia items];
NSMutableArray *mArray = [[NSMutableArray alloc] init];
int i = 0;
int j=0;
NSLog(#"itemCount: %d",[itemsFromGenericQuery count]);
float playsQuery = sliderPlays.value;
if(playsQuery == 20){playsQuery = 10000;}
NSLog(#"sliderRating.value %f sliderPlays.value %.1f", [sliderRating value], playsQuery);
while(i++ < 1000){
int trackNumber = arc4random() % [itemsFromGenericQuery count];
MPMediaItem *song = [itemsFromGenericQuery objectAtIndex:trackNumber];
NSString *artistName = [song valueForProperty: MPMediaItemPropertyArtist];
NSString *title = [song valueForProperty: MPMediaItemPropertyTitle];
NSString *rating = [song valueForKey:MPMediaItemPropertyRating];
double length = [[song valueForProperty:MPMediaItemPropertyPlaybackDuration] doubleValue];
NSNumber *year = [song valueForProperty:MPMediaItemPropertyYear];
if ([year intValue] >= [def intValue] <= {
if(j++ > 50){break;}
NSLog (#"tracknumber: %d j: %d artistName: %# title: %# length: %# year: %# playcount: %d",trackNumber, j, artistName, title, length, rating, [playCount intValue]);
[mArray addObject:song];
}
if(i++ > 1000)break;
}
MPMediaItemCollection *itemCol = [[MPMediaItemCollection alloc] initWithItems:mArray];
[myPlayer setQueueWithItemCollection:itemCol];
[myPlayer setShuffleMode: MPMusicShuffleModeSongs];
[myPlayer setRepeatMode: MPMusicRepeatModeNone];