I want to get the ISRC code for Local itunes songs. I can get the metaData by the following codes:
MPMusicPlayerController *mp= mp = [MPMusicPlayerController applicationMusicPlayer];
NSURL *assetURL = [mp.nowPlayingItem valueForProperty:MPMediaItemPropertyAssetURL];
AVAsset *asset = [AVAsset assetWithURL:assetURL];
NSArray *metadata = [asset commonMetadata];
for ( AVMetadataItem* item in metadata ) {
NSString *key = [item commonKey];
NSString *value = [item stringValue];
NSLog(#"extra iptions %#",[item extraAttributes]);
NSLog(#"key = %#, value = %#", key, value);
NSLog(#"keyspace and Local %# %#",[item keySpace],[item key]);
}
But I am really wondering about how to get ISRC(International Standard Record Coding).
Try this (warning: typed into browser)
NSArray *metadata = [asset metadataForFormat:AVMetadataFormatID3Metadata];
if (metadata == nil) {
NSLog(#"No ID3 metadata for asset: %#", asset);
}
// From https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVFoundation_ID3Constants/Reference/reference.html
NSArray *filteredMetadata = [AVMetadataItem metadataItemsFromArray:metadata withKey:AVMetadataID3MetadataKeyInternationalStandardRecordingCode keySpace:nil];
AVMetadataItem *item = [filteredMetadata firstObject];
if (item != nil) {
NSLog(#"ISRC: %#", item.stringValue);
} else {
NSLog(#"No ISRC found for: %#", asset);
}
EDIT: I should mention, the reason your original code didn't print the value of the ISRC is because the ISRC is not part of the common metadata space, and won't be included in the array returned by [asset commonMetadata]. The ISRC key is specific to ID3 metadata, so if your asset does not have ID3 metadata associated with it, you will be unable to retrieve that information.
Related
I am trying to load an asset from a local identifier. The local identifier seems to be correct but the asset is null and I can't figure out why. I have a similar code in another part of my app that works fine.
Queue *queue = [NSEntityDescription insertNewObjectForEntityForName:#"Queue" inManagedObjectContext:self.context];
for (int reyrt = 0; reyrt < self.storeGIF.count; reyrt++) {
queue.queuetextimagePath = [self.storeGIF objectAtIndex:reyrt];
}
__block float fileSize;
NSArray *identifiers = #[queue.queuetextimagePath];
PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:identifiers options:nil];
PHAsset *asset = [assetsFetchResult firstObject];
NSLog (#"identifiers: %#", identifiers);
NSLog (#"assetsFetchResult: %#", assetsFetchResult);
NSLog (#"asset: %#", asset);
if (!asset) {
NSLog(#"can't retrieve PHAsset from localIdentifier:%#",identifiers);
}
Here is the NSLog file result when using the above code.
019-07-19 09:26:36.366739-0400 myApp[1440:328144] identifiers: (
"857AC3DA-C047-4D88-911B-C5FE227E2B96/L0/001"
)
2019-07-19 09:26:36.366945-0400 myApp[1440:328144] assetsFetchResult PHFetchResult: 0x281129900 count=0
2019-07-19 09:26:36.366982-0400 myApp[1440:328144] asset: (null)
2019-07-19 09:26:36.367061-0400 myApp[1440:328144] can't retrieve PHAsset from localIdentifier:(
"857AC3DA-C047-4D88-911B-C5FE227E2B96/L0/001"
)
The problem is that you should drop /L0/001 part before requesting the object. I don't understand why uuid strings contain these suffixes, but it works if you drop it and use only normal UUID part.
I am working with an iOS application in which i upload images on Picasa web albums from my iOS application.When i create album firstly i check whether any album with the same name exist or not so i fetch all the albums with their name and album id with the below code.
for (GDataEntryPhotoAlbum *albumEntry in feed)
{
NSString *title = [[albumEntry title] stringValue];
NSString *title1 = [albumEntry GPhotoID];
NSLog(#"File Title: %# | ID: %#",title,title1);
}
i get all the album name and albumid .
now i check with the current album name given by the user.
if ([title isEqual:albumName]){
//do not create new album
// return the album id
}
else{
//create new album
}
Everything working fine ,but now the problem is how can i send the albumid to the uploading method which is below mentioned:
- (void)_startUpload:(UIImage *)image:(NSString *)filePath{
NSLog(#"album feed is %#",albfeed);
// user/11106615845/albumid/6029121 gphotoID:60291215413
//GDataFeedPhotoAlbum *albumFeedOfPhotos = [self photoFeed];
//https://photos.googleapis.com/data/upload/resumable/media/create-session/feed/api/user/114789383162963173862/albumid/6025392474120084449
//https://photos.googleapis.com/data/entry/user/1082642086705/albumid/60254095886065
NSURL *uploadURL1 = [[[albfeed uploadLink] URL] retain];
NSString *photoPath = [[NSBundle mainBundle] pathForResource:#"red_bull" ofType:#"jpg"];
NSString *photoName = [photoPath lastPathComponent];
NSLog(#"uploadURL1 : %#",uploadURL1 );
NSLog(#"photoPath : %#",photoPath);
NSLog(#"photoName : %#",photoName);
NSData *photoData = [NSData dataWithContentsOfFile:filePath];
if (photoData) {
GDataEntryPhoto *newEntry = [GDataEntryPhoto photoEntry];
[newEntry setTitleWithString:photoName];
[newEntry setPhotoDescriptionWithString:filePath];
[newEntry setTimestamp:[GDataPhotoTimestamp timestampWithDate:[NSDate date]]];
[newEntry setPhotoData:photoData];
NSString *mimeType = [GDataUtilities MIMETypeForFileAtPath:filePath
defaultMIMEType:#"image/jpeg"];
[newEntry setPhotoMIMEType:mimeType];
[newEntry setUploadSlug:photoName];
GDataServiceGooglePhotos *service = [self googlePhotosService];
SEL progressSel = #selector(ticket:hasDeliveredByteCount:ofTotalByteCount:);
service.authToken = authTokens;
[service setServiceUploadProgressSelector:progressSel];
GDataServiceTicket *ticket;
ticket = [service fetchEntryByInsertingEntry:newEntry
forFeedURL:uploadURL1
delegate:self
didFinishSelector:#selector(addPhotoTicket:finishedWithEntry:error:)];
[service setServiceUploadProgressSelector:nil];
}else {
NSLog(#"### Image not loaded");
}
i don't know how will i send the specific albumid so that i don't need to create a new album ,if that album is already found in my account.
How can i achieve that??
I don't want to create another album with the same name,,get the albumid and upload images on the previous album.
please help me out.
Thank you for your precious time.
I am exporting a Quicktime video using AVExporterSession and setting the metadata on it as follows:
AVMutableMetadataItem *newMetaDataCommentItem = [[AVMutableMetadataItem alloc] init];
[newMetaDataCommentItem setKeySpace:AVMetadataKeySpaceQuickTimeMetadata];
[newMetaDataCommentItem setKey:AVMetadataQuickTimeMetadataKeyComment];
[newMetaDataCommentItem setValue:#"Test metadata value"];
NSMutableArray *metaData = [NSMutableArray array];
[metaData addObject:newMetaDataCommentItem];
exporter = [[AVAssetExportSession alloc] initWithAsset:mutableComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL=[[SNMovieManager instance] urlForFinalMovie];
exporter.metadata = metaData;
exporter.outputFileType = AVFileTypeQuickTimeMovie;
exporter.shouldOptimizeForNetworkUse = YES;
exporter.videoComposition = video;
I then import the file video to my Mac and run mdls on it and see the value has been set correctly: kMDItemComment = "Test metadata value"
The bit I can't do is read that value back. I am using the following to read the file. The asset is correct but the metadata property is always an empty dictionary.
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if([[result valueForProperty:#"ALAssetPropertyType"] isEqualToString:#"ALAssetTypeVideo"])
{
ALAssetRepresentation *rep = result.defaultRepresentation;
NSDictionary *metadata = rep.metadata;
[images addObject:(id)rep.fullScreenImage];
}
Does anyone know if I am taking the correct approach here and if not let me know what the correct approach to read this comment back out is?
Thanks
Simon
I would be highly appreciated if you can provide more code base related to the PhotoLibrary save process.
Otherwise only one answer, Metadata will return nil if the representation is one that the system cannot interpret.
The returned dictionary holds the properties of the video at a specified location in an file source.
I'think your problem is on getting metadata script
You should get an AVURLAsset first and get metadata from it ALAssetRepresentation metadata is different
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
if([[result valueForProperty:#"ALAssetPropertyType"] isEqualToString:#"ALAssetTypeVideo"])
{
AVURLAsset *videoAset = [AVURLAsset assetWithURL:[[asset defaultRepresentation] url]];
if ([[videoAset metadataForFormat:AVMetadataFormatQuickTimeMetadata] count]) {
AVMutableMetadataItem *meta = [[videoAset metadataForFormat:AVMetadataFormatQuickTimeUserData] objectAtIndex:0];
NSLog(#"%#",meta);
NSLog(#"%lu",(unsigned long)[[videoAset metadataForFormat:AVMetadataFormatQuickTimeMetadata] count]);
}
}
I'm trying to play a song in my application. When the the code to play a song is put right away in the controller it runs good.
But when i put the code in a class, call the class then call the method to play the song, nothing happens ? If someone have a clue please feel free to help.
here is the code to play a song
-(void)randomSound{
NSLog(#"sound");
NSString * path;
NSError * err;
NSString *name;
NSArray *names = [[NSArray alloc] initWithObjects:#"1up.wav", #"mario02.dsp.wav", #"mario04.dsp.wav", #"mario06.dsp.wav", #"mrf.dsp.wav", nil];
name = [names randomObject];
path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:name];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSURL * url = [NSURL fileURLWithPath:path];
self.snd = [[AVAudioPlayer alloc] initWithContentsOfURL:url
error:&err] ;
if (! self.snd) {
NSLog(#"data named '%#' had error %#", name, [err localizedDescription]);
} else {
NSLog(#"playing");
[self.snd prepareToPlay];
[self.snd play];
}
} else {
NSLog(#"data file '%#' doesn't exist at '%#'", name, path);
}
}
The way i call the method
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"YAHOO"])
{
YahooViewController *YH = [[YahooViewController alloc] init];
[YH randomSound];
}
The random method in case someone would like to know whats in it
-(id)randomObject {
NSUInteger myCount = [self count];
if (myCount)
return [self objectAtIndex:arc4random_uniform(myCount)];
else
return nil;
}
After discussion in comments it was identified the issue was URL encoding.
Check out this question / answer which will show you how to URLEncode a string:
How do I URL encode a string
I'm trying to fetch iTunes library in ios.
And trying to retrieve top 10 playcount song in 5days.
Could you tell me how to do? Here's my code.
MPMediaPropertyPredicate is not right answer...I guess.
MPMediaQuery *everything = [[MPMediaQuery alloc] init];
NSLog(#"Logging items from a generic query...");
NSArray *itemsFromGenericQuery = [everything items];
for (MPMediaItem *song in itemsFromGenericQuery) {
NSString *songTitle = [song valueForProperty: MPMediaItemPropertyTitle];
NSString *artistName = [song valueForProperty:MPMediaItemPropertyArtist];
NSString *lastPlayeddate = [song valueForProperty:MPMediaItemPropertyLastPlayedDate];
NSString *playCount = [song valueForProperty:MPMediaItemPropertyPlayCount];
NSLog (#"%#", songTitle);
text.text = [NSString stringWithFormat:#"%#\n%# %# %# %#", text.text, songTitle, artistName, lastPlayeddate, playCount];
}
All the best.
Apparently, play count is considered a "user defined" key, and therefore cannot be used in MPMediaPropertyPredicate
See http://developer.apple.com/library/ios/documentation/mediaplayer/reference/MPMediaItem_ClassReference/Reference/Reference.html#//apple_ref/doc/uid/TP40008211-CH1-SW38
You will have to iterate the songs and retrieve these properties manually.
enumerateValuesForProperties:usingBlock: is probably your most efficient option here.
http://developer.apple.com/library/ios/documentation/mediaplayer/reference/MPMediaEntity_ClassReference/Reference/Reference.html#//apple_ref/occ/instm/MPMediaEntity/enumerateValuesForProperties:usingBlock: