3

I am playing songs by using AVPlayer. I am able to play it in background as well. There is a UIButton called showPlaylist. When I tap on it I need to display list of songs which I have selected from ipodLibrary in UITableView and I should be able to display artwork, number of mins remaining in the song and the artist's name if it is available in the song.

I have play and pause buttons: when I click the pause button, the song is paused but when I tap on the play button again, it goes to the ipodLibrary. How to resume play when I tap on the play button?

And when there are multiple songs in that UITableView, I want it to continue to the next track as soon as the first track completes. I was wondering how to do that.

-(IBAction)playButtonPressed:(UIButton *)sender {
  // Create picker view
  MPMediaPickerController* picker = [[MPMediaPickerController alloc] init];
  picker.delegate = self;
  if (userMediaItemCollection) {
    MusicTableViewController *controller = [[MusicTableViewController alloc]
     initWithNibName: @"MusicTableView" bundle: nil];
    controller.delegate = self;
    controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [self presentModalViewController: controller animated: YES];
  } else {
    MPMediaPickerController *picker = [[MPMediaPickerController alloc]
      initWithMediaTypes: MPMediaTypeMusic];
    picker.delegate  = self;
    picker.allowsPickingMultipleItems = YES;
    picker.prompt = NSLocalizedString
      (@"Add songs to play", "Prompt in media item picker");
    [[UIApplication sharedApplication] setStatusBarStyle:
      UIStatusBarStyleDefault animated: YES];
    [self presentModalViewController: picker animated: YES];
  }
}

-(IBAction)pauseButtonPressed:(UIButton *)sender {
  [myPlayer pause];
}

-(void) mediaPickerDidCancel:(MPMediaPickerController *)mediaPicker {
  [self dismissViewControllerAnimated:YES completion:nil];
}

-(void) mediaPicker:(MPMediaPickerController *)mediaPicker didPickMediaItems:
  (MPMediaItemCollection *)mediaItemCollection {
  [self dismissViewControllerAnimated:YES completion:nil];
  NSURL* assetUrl = [mediaItemCollection.representativeItem
    valueForProperty:MPMediaItemPropertyAssetURL];
  AVURLAsset* asset = [AVURLAsset URLAssetWithURL:assetUrl options:nil];
  AVPlayerItem* playerItem = [AVPlayerItem playerItemWithAsset:asset];
  myPlayer = [AVPlayer playerWithPlayerItem:playerItem];
  [myPlayer play];
}

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
  [self becomeFirstResponder];
}

- (BOOL)canBecomeFirstResponder {
  return YES;
}

- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
  [self resignFirstResponder];
}

-(void)remoteControlReceivedWithEvent:(UIEvent *)event {
  switch (event.subtype) {
    case UIEventSubtypeRemoteControlTogglePlayPause:
      if (myPlayer.rate == 0.0) {
        [myPlayer play];
      } else {
        [myPlayer pause];
      }
      break;
    case UIEventSubtypeRemoteControlPlay:
      [myPlayer play];
      break;
    case UIEventSubtypeRemoteControlPause:
      [myPlayer pause];
      break;
    default:
      break;
  }
}
dda
  • 6,030
  • 2
  • 25
  • 34
coded
  • 113
  • 1
  • 1
  • 9
  • You might want to look at this question with regards to your question about remote events http://stackoverflow.com/questions/11566512/how-to-choose-next-song-in-remotecontrolledevents/11567222#11567222 – Dustin Jul 19 '12 at 18:42

2 Answers2

3

I would look into Apple's sample code "Add Music" which clearly demonstrated how to do everything you've described.

This sample application runs you through the ins and outs of populating a UITableView with the contents of a mutable copy of selected songs from the iPod library saved into a MPMediaItemCollection. It also shows how using MPMediaItems and MPMediaItemCollections you can display track specific attributes as the cells title label, etc.

  1. For populating the table view, you could set it up something like this:

    MPMediaItem *mediaItem = (MPMediaItem *)[collectionMutableCopy objectAtIndex:row];

    MPMediaItemArtwork *artwork = [mediaItem valueForProperty:MPMediaItemPropertyArtwork];

    if (mediaItem) {
        cell.textLabel.text = [mediaItem valueForProperty:MPMediaItemPropertyTitle];
        cell.detailTextLabel.text = [mediaItem valueForProperty:MPMediaItemPropertyArtist];
        if (artwork != nil) {
            cell.imageView.image = [artwork imageWithSize:CGSizeMake (40, 40)];
        }else{
            cell.imageView.image = [UIImage imageNamed:@"no_artwork.png"];
        }
    }
    
  2. Rename the button linked to the play button as "Select Music" and make a new button called "Play" with its action set to:

    - (IBAction)playMusic { [myPlayer play]; }

EDIT: Creating array from contents of MPMediaItemCollection:

NSMutableArray *collectionMutableCopy = [[NSMutableArray alloc] initWithArray:myMediaItemCollection.items];

EDIT 2: Uncomment the following lines in the project:

In - (void) registerForMediaPlayerNotifications

/*
 // This sample doesn't use libray change notifications; this code is here to show how
 //     it's done if you need it.
 [[NSNotificationCenter defaultCenter] removeObserver: self
 name: MPMediaLibraryDidChangeNotification
 object: musicPlayer];

 [[MPMediaLibrary defaultMediaLibrary] endGeneratingLibraryChangeNotifications];

 */

In - (void)dealloc

/*
 // This sample doesn't use libray change notifications; this code is here to show how
 //     it's done if you need it.
 [notificationCenter addObserver: self
 selector: @selector (handle_iPodLibraryChanged:)
 name: MPMediaLibraryDidChangeNotification
 object: musicPlayer];

 [[MPMediaLibrary defaultMediaLibrary] beginGeneratingLibraryChangeNotifications];
 */

Replace this line:

[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil];

With this

 [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];

 UInt32 doSetProperty = 0;
 AudioSessionSetProperty (
 kAudioSessionProperty_OverrideCategoryMixWithOthers,
 sizeof (doSetProperty),
 &doSetProperty
 );

Then add the following to your projects info.plist file

enter image description here

Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
  • ^^ I apologize for the mal-formatted response... Syntax highlighting doesn't seem to be working properly. – Mick MacCallum Jul 19 '12 at 16:55
  • can i use the same cell to display title name , artist name as well artwork cause i have increased the tableviewcell height so that it can occupy all of these . correct me if i am wrong the above code will be implemented in cellForRowAtIndexPath . – coded Jul 19 '12 at 17:02
  • i have only one view where i have placed buttons on top so when i click showMusic Button the UITableview will get displayed below the buttons so that it can occupy the bottom part of the screen – coded Jul 19 '12 at 17:06
  • @coded Yes, you can. Each cell has a textLabel, and a detailTextLabel property but in order to use both of these textLabels you will need to change the cells style to UITableViewCellStyleValue1, UITableViewCellStyleValue2, or UITableViewCellStyleSubtitle. Yes this will go in cellForRowAtIndexPath, and I'm don't understand what you mean in your second comment. – Mick MacCallum Jul 19 '12 at 17:09
  • ah ok .when i run my app i have playbutton , pausebutton , addMusicButton,showPlaylistButton . all of these buttons are placed on the top so when i tap on showPlaylistButton the UITableView will get displaced along with the details of the song , so how much ever songs i select from ipodLibary all these details will get displayed right,i was wondering how artwork will get displayed like for artist there is MPMediaItemPropertyArtist – coded Jul 19 '12 at 17:18
  • @coded Well considering that MPMediaItemCollections are immutable, you will need to create a mutable copy of the collection then delete that object from the copy in UITableView's commitEditingStyle method, then basically refresh the media collection to the contents of the altered copy. – Mick MacCallum Jul 19 '12 at 17:24
  • @coded Sorry to say, I can not. I'm currently working on a similar project to you, and am still in the process of writing it all out my self. The information I've already given you is basically a summary of what I have already learned that I will need to do to complete my goal. – Mick MacCallum Jul 19 '12 at 17:27
  • Just one last is there a way where i can retrieve the list of songs of Songs Library in array ,if i have to implement this in which method should i implement it – coded Jul 20 '12 at 03:44
  • @coded This link should help you, http://stevetranby.com/blog/2010/09/background-music-queue-with-avplayer-and-ios4/ – Mick MacCallum Jul 23 '12 at 12:05
  • i tried to add selected songs into my new UITableView when i run the app it didnt call cellForRowAtIndexPath .. i was referring to Add Music project by apple they have used updatePlayerQueueWithMediaCollection but since i am using AVPlayer nowPlayingItem property is not available in AVPlayer. I am not able to fetch the list of selected songs from the ipodLibrary onto my tableView how to add media item collection as a playback queue for avplayer so that it displays the selected songs from ipodLibrary – coded Jul 23 '12 at 12:31
  • @coded I don't understand what the problem is, all the functionality you are describing is part of that sample project and works out of the box. – Mick MacCallum Jul 23 '12 at 22:16
  • the functionality which they are using works since they r using mpmusicplayercontroller since i am using avplayer i am not able to do it idk if i am correct – coded Jul 24 '12 at 03:14
  • @coded can you elaborate on why you are using AVPlayer instead? – Mick MacCallum Jul 24 '12 at 03:19
  • i am using avplayer since it supports background play and airplay – coded Jul 24 '12 at 03:39
  • @coded MPMusicPlayerController supports airplay, and lock screen playback simply by initializing the correct audio session. – Mick MacCallum Jul 24 '12 at 14:49
  • I tried to get it working but the music was getting stopped as soon as the app goes to background ..i have read in most of the forums where ppl say MPMusicPlayerController stops the song as soon as the app goes to background .. were u able to go thro my code which i have posted in pastebin ... i can send u my project so that u will have an idea – coded Jul 24 '12 at 16:35
  • @coded Apple already included lock screen playback in the project, it's just commented out. – Mick MacCallum Jul 24 '12 at 16:53
  • even after i un commented it ,the music was getting stopped – coded Jul 24 '12 at 17:05
  • can u help me out in this problem – coded Jul 25 '12 at 02:53
  • the artwork isnt showing up when i add songs from ipod Library its available in the song ... the artist song is getting cut like for ex Agressive Expans.... its showing like this .. can i add CGRect for artist , song label . – coded Jul 25 '12 at 14:16
  • @coded Did this solve the problem and you're asking me how to solve another one? – Mick MacCallum Jul 25 '12 at 14:46
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/14411/discussion-between-nspostwhenidle-and-coded) – Mick MacCallum Jul 25 '12 at 15:00
1

Your problem is that your play button is doing something other than just telling the music player to play. You need one that just calls [myPlayer play]; Do all your setup somewhere other than the play button.

It's not really good coding practice to have your play button also pick songs (it's better to keep to the idea of one button -> one function). So have a button that does what's in your play button right now and then have your play button just call [myPlayer play]

As for your other question, you should look at this: Play multiple audio files using AVAudioPlayer

Just so you know, you're not really supposed to ask multiple questions in the same post. It makes it harder to give a concise, useful answer and can make the site harder to find things on.

I'm not sure if you're asking how to display song information, but I guess it's in your title. For this one, iPhone sdk - accessing current song information through an app.

Community
  • 1
  • 1
Dustin
  • 6,783
  • 4
  • 36
  • 53
  • so i would add another UIButton where it allows me to choose songs and another UIButton to play the song. – coded Jul 19 '12 at 17:04
  • 1
    That would be a good idea, although technically you could use some variable to keep track of what's going on and change your button's behavior accordingly. – Dustin Jul 19 '12 at 17:05
  • Thanks , one more the article about multiple audio files which u have mentioned its for AVAudioPlayer i am using AVPlayer ,as soon as the say for ex 1st song gets over if there is another song in the selected playlist it should start playing .I have read somewhere to use NSNotification ,whats ur take on it – coded Jul 19 '12 at 17:10
  • Not a bad way to do it, kind of a pain if you haven't done it before. If you want the easiest way, try `audioPlayerDidFinishPlaying`. All you have to do is set up `AVAudioPlayerDelegate` (you add `` in you .h file and set `myPlayer.delegate = self` in your .m). – Dustin Jul 19 '12 at 17:15
  • i have set AVAudioPlayerDelegate in my h.file if i set myPlayer.delegate = self ,how its going to play the second song ,i am just curious to ask question as it is very interesting – coded Jul 19 '12 at 17:22
  • You implement `audioPlayerDidFinishPlaying` and tell `myPlayer` to play the next song (if a song exists). – Dustin Jul 19 '12 at 17:29
  • Thanks Dustin , how to do this for remoteControlledEvents ? – coded Jul 19 '12 at 17:37
  • That's a whole other question... Try and see if you can do it; if you can't post another question and I'm sure people will be happy to help. – Dustin Jul 19 '12 at 17:41