I am looking at ways to store song information and then play a specific song. I've seen this post:
How do you use MPMediaItemPropertyPersistentID to play music in iPhone Music Player Framework?
If I have a MPMediaItemPropertyPersistentID already, can I directly play that song without looping every single song until I find a matching id?
You don't have to do this by looping through all the items in the library. It can be done via MPMediaQuery, something like this:
NSNumber *persistentIDNumber = [NSNumber numberWithInteger:4238475234];
MPMusicPlayerController *player = [MPMusicPlayerController applicationMusicPlayer];
MPMediaPropertyPredicate *predicate = [MPMediaPropertyPredicate predicateWithValue:persistentIDNumber forProperty:MPMediaEntityPropertyPersistentID];
MPMediaQuery *query = [[MPMediaQuery alloc] init];
[query addFilterPredicate: predicate];
[player setQueueWithQuery:query];
[player prepareToPlay];
[player play];
Related
I have an AVQueuePlayer that is used to play a list of MP3 songs from the internet (http). I need to also know which song is currently playing. The current problem is that loading the song causes a delay that blocks the main thread while waiting for the song to load (first song as well as sequential songs after the first has completed playback).
The following code blocks the main thread:
queuePlayer = [[AVQueuePlayer alloc] init];
[queuePlayer insertItem: [AVPlayerItem playerItemWithURL:url] afterItem: nil]; // etc.
[queuePlayer play]
I am looking for a way to create a playlist of MP3s where the next file to be played back is preloaded in the background.
I tried the following code:
NSArray* tracks = [NSArray arrayWithObjects:#"http://example.com/song1.mp3", #"http://example.com/song2.mp3", #"http://example.com/song3.mp3", nil];
for (NSString* trackName in tracks)
{
AVURLAsset* audioAsset = [[AVURLAsset alloc]initWithURL:[NSURL URLWithString:trackName]
options:nil];
AVMutableCompositionTrack* audioTrack = [_composition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
NSError* error;
[audioTrack insertTimeRange:CMTimeRangeMake([_composition duration], audioAsset.duration)
ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio]objectAtIndex:0]
atTime:kCMTimeZero
error:&error];
if (error)
{
NSLog(#"%#", [error localizedDescription]);
}
// Store the track IDs as track name -> track ID
[_audioMixTrackIDs setValue:[NSNumber numberWithInteger:audioTrack.trackID]
forKey:trackName];
}
_player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
[_player play];
The issue with this is that I am not sure how to detect when the next song starts playing. Also, the docs don't specify whether or not this will pre-load MP3 files or not.
I am looking for a solution that:
Plays MP3s by pre-loading them in the background prior to playback (ideally start loading the next song before the current song finishes, so it is ready for immediate playback once the current song finishes)
Allow me to view the current song playing.
AVFoundation has some classes designed to do exactly what you're looking for.
It looks like your current solution is to build a single AVPlayerItem that concatenates all of the MP3 files that you want to play. A better solution is to create an AVQueuePlayer with an array of the AVPlayerItem objects that you want to play.
NSArray* tracks = [NSArray arrayWithObjects:#"http://example.com/song1.mp3", #"http://example.com/song2.mp3", #"http://example.com/song3.mp3", nil];
NSMutableArray *playerItems = [[NSMutableArray alloc] init];
for (NSString* trackName in tracks)
{
NSURL *assetURL = [NSURL URLWithString:trackName];
if (!assetURL) {
continue;
}
AVURLAsset* audioAsset = [[AVURLAsset alloc] initWithURL:assetURL
options:nil];
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithAsset:audioAsset];
[playerItems addObject:playerItem];
}
_player = [[AVQueuePlayer alloc] initWithItems:playerItems];
[_player play];
In answer to your final wrap-up questions:
Yes, AVQueuePlayer DOES preload the next item in the playlist while it's playing the current one.
You can access the currentItem property to determine which AVPlayerItem is currently playing.
i'm developing a music player app.I have a tableView that contains the songs names of the ipod library.My problem is that when i select a cell it plays a specific song but when that song is completed it doesn't skip to the next item automatically.
This is my code when i select a cell:
MPMediaQuery *mq = [MPMediaQuery songsQuery];
MPMediaPropertyPredicate *songNamePredicate = [MPMediaPropertyPredicate
predicateWithValue:[songsTitle objectAtIndex:indexPath.row]
forProperty:MPMediaItemPropertyTitle];
[mq addFilterPredicate:songNamePredicate];
[mp setQueueWithQuery:mq];
[mp play];
i really need your help.Thanks.
It doesn't skip to the next song because the playback queue only has one item. At launch, set the playback queue to the entire songs query. Also create an array of MPMediaItems using the items property of MPMediaQuery:
MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
self.songs = songsQuery.items;
[self.musicPlayer setQueueWithQuery:songsQuery];
In tableView:didSelectRowAtIndexPath:, have the music player play the selected item using MPMusicPlayerController's setNowPlayingItem: method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MPMediaItem *song = self.songs[indexPath.row];
[self.musicPlayer setNowPlayingItem:song];
[self.musicPlayer play];
}
Here is a sample project that demonstrates this:
https://dl.dropboxusercontent.com/u/1990969/SongsPlayerTableView.zip
I am trying to play MPMedaiItem in MPMusicPlayerController in iOS.
In my case , i have a UITableView that show songs from playlist.
When i tap cell on UITableView , i want to play that song with MPMusicPlayerController.
And i also want to skip next songs from playlist when i tap Next Button.
How can i play it?
Here is some of my codes that write in didSelected Method of UITableView.
That doesn't play anything.
MPMediaItemCollection *songs = [self.arrayOfSongs objectAtIndex:indexPath.row ];
MPMediaItem *item = [songs representativeItem ];
NSLog(#"%#",[item valueForProperty:MPMediaItemPropertyTitle ]);
[self.player setNowPlayingItem:[item valueForProperty:MPMediaItemPropertyAssetURL]];
[self.player play ];
I know this is a little late, but your problem is that MPMusicPlayerController's nowPlayingItem property expects a MPMediaItem object, and you're passing it an NSString containing the URL of the asset. Here's an example of how this could be accomplished.
MPMusicPlayerController *controller = [MPMusicPlayerController iPodMusicPlayer];
MPMediaItemCollection *collection = [[MPMediaItemCollection alloc] initWithItems:arrayOfMediaItems];
MPMediaItem *item = [collection representativeItem];
[controller setQueueWithItemCollection:collection];
[controller setNowPlayingItem:item];
[controller prepareToPlay];
[controller play];
I find it easier to use AVPlayer in an instance like this.
in your header file declare the AVPlayer object;
AVPlayer *audioPlayer;
Then in your method file use something like:
if(!audioPlayer){
audioPlayer = [[AVPlayer alloc] initWithURL:[item valueForProperty:MPMediaItemPropertyAssetURL]];
} else {
[audioPlayer replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithURL:itemURL]];
}
[audioPlayer play];
I am trying to start playing music from within my application. I have iOs 6 but I need it to run in 5.1 as I need to support iPad 1 which goes up to that version.
I imported both CoreMedia and MediaPlayer frameworks and I am playing via the MPMusicPlayerController. I am able to get the list of songs, but playing doesn't work. I am testing in a real device, not the simulator.
Any thoughts into what is wrong?
__strong NSArray * _myMusic;
__strong MPMusicPlayerController * _player;
// Specify a media query
MPMediaQuery *query = [MPMediaQuery songsQuery];
// Obtain the media item collections from the query
_myMusic = [query collections];
_player = [MPMusicPlayerController applicationMusicPlayer]; //also tried iPodMusicPlayer
MPMediaItemCollection *currentQueue = [[MPMediaItemCollection alloc] initWithItems:_myMusic];
[_player setQueueWithItemCollection:currentQueue];
[_player setShuffleMode: MPMusicShuffleModeOff];
[_player setRepeatMode: MPMusicRepeatModeNone];
[_player setVolume:1];
[_player play];
SETUP
I put a mp3 into my bundle just for testing, i will have them download into the documents directory. But for now i am going to work off the bundle.
I have found a couple tutorials, but not anything for what i need. The below is definitely a mix of a couple solutions and probably not the best approach.
Problem
How do i pull a song out of my bundle and play within the app?
//Create an instance of MPMusicPlayerController
MPMusicPlayerController* myPlayer = [MPMusicPlayerController applicationMusicPlayer];
//Read the song off the bundle.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"LittleMoments" ofType:#"mp3"];
NSData *myData = [NSData dataWithContentsOfFile:filePath];
if (myData) {
//This wont work for me because i don't want to query songs from the iPod,
i want to play songs out of the Bundle.
//Create a query that will return all songs by The Beatles grouped by album
MPMediaQuery* query = [MPMediaQuery songsQuery];
[query addFilterPredicate:[MPMediaPropertyPredicate predicateWithValue:#"The Beatles" forProperty:MPMediaItemPropertyArtist comparisonType:MPMediaPredicateComparisonEqualTo]];
[query setGroupingType:MPMediaGroupingAlbum];
//Pass the query to the player
[myPlayer setQueueWithQuery:query];
/////**** how can i get nsdata into MyPlayer?*****//////
//Start playing and set a label text to the name and image to the cover art of the song that is playing
[myPlayer play];
}
Try playing the file with AVAudioPlayer
AVAudioPlayer *audioPlayer = [(AVAudioPlayer*)[AVAudioPlayer alloc] initWithData:myData error:nil];
audioPlayer.delegate = self;
[audioPlayer play];