nemesis
nemesis

Reputation: 1351

AVAudioPlayer pausing issue

In my project, I have an AVAudioPlayer which plays a song. After I pause it, and hit play again, it starts over instead of playing where I paused. Why is that happening? Also, when I press play for the first time, it loads the song about 3-4 seconds. I thought I solved it by loading it on the other thread, but it still loads too slow (at least the view doesn't freeze anymore). How can I fix that? Here's the code:

- (IBAction)play:(id)sender {
  songIsCurrentlyPaused = NO;
  if(songIsCurrentlyPaused==YES){
    [self.background play];
  } else {
    playQueue = dispatch_queue_create("volume_change", NULL);
    dispatch_async(playQueue, ^{ NSString *filePath = 
      [[NSBundle mainBundle]pathForResource:@"some_song" ofType:@"mp3"];
      NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
      self.background = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
      self.background.delegate = self;
      [self.background setNumberOfLoops:1];
      [self.background setVolume:0.5];
      [self.background play]; });

      [trackNameLabel setText:@"Currently playing :\n some_song"];
      self.timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(updateProgressBar) userInfo:nil repeats:YES];
    }
}

- (IBAction)pause:(id)sender {
  songIsCurrentlyPaused = YES;
  [self.background pause];
  [trackNameLabel setText:@"Currently playing : some_song (paused)"];
  [self.progressBar setProgress:self.background.currentTime/self.background.duration animated:YES];
}

Thanks!

Upvotes: 1

Views: 2762

Answers (1)

Rok Jarc
Rok Jarc

Reputation: 18865

You're setting songIsCurrentlyPaused to NO at the beginning of play:

Try commenting it out:

- (IBAction)play:(id)sender {
  //songIsCurrentlyPaused = NO;
  if(songIsCurrentlyPaused==YES){
    [self.background play];
  } else {
    playQueue = dispatch_queue_create("volume_change", NULL);
    dispatch_async(playQueue, ^{ NSString *filePath = 
      [[NSBundle mainBundle]pathForResource:@"some_song" ofType:@"mp3"];
      NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
      self.background = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
      self.background.delegate = self;
      [self.background setNumberOfLoops:1];
      [self.background setVolume:0.5];
      [self.background play]; });

      [trackNameLabel setText:@"Currently playing :\n some_song"];
      self.timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(updateProgressBar) userInfo:nil repeats:YES];
    }
}

- (IBAction)pause:(id)sender {
  songIsCurrentlyPaused = YES;
  [self.background pause];
  [trackNameLabel setText:@"Currently playing : some_song (paused)"];
  [self.progressBar setProgress:self.background.currentTime/self.background.duration animated:YES];
}

If you want to get rid of that initial pause you're gonna have to completely reorganize your player setup. Initialize it before user can hit play button and also call:

[self.background prepareToPlay];

which will preload the song. Also move songIsCurrentlyPaused = NO; to some earlier place in code.

EDIT:

To get rid of initial delay you should move your initializing code to somewhere like loadView or viweDidLoad.

   //initialization code
   NSString *filePath = [[NSBundle mainBundle]pathForResource:@"some_song" ofType:@"mp3"];
   NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
   self.background = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
   self.background.delegate = self;
   [self.background setNumberOfLoops:1];
   [self.background setVolume:0.5];
   [self.background prepareToPlay];

Now this may cause a lag in UI display so you might wan't to consider preloading data in background thread.

Your IBAction methods should then be modified:

- (IBAction)play:(id)sender
{

   if (songIsCurrentlyPaused==YES) 
   { 
      [self.background play];
   }
   else
   {
      playQueue = dispatch_queue_create("volume_change", NULL);
      dispatch_async(playQueue, ^{
         [self.background setCurrentTime: 0.0];
         [self.background play];
      });

      [self.progressBar setProgress:0.0 animated:YES];
      [trackNameLabel setText:@"Currently playing :\n some_song"];
      self.timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(updateProgressBar) userInfo:nil repeats:YES];

  }
  songIsCurrentlyPaused = NO;
}

- (IBAction)pause:(id)sender
{
  songIsCurrentlyPaused = YES;
  [self.background pause];
  [trackNameLabel setText:@"Currently playing : some_song (paused)"];
  [self.progressBar setProgress:self.background.currentTime/self.background.duration animated:YES];
}

Upvotes: 1

Related Questions