Reputation: 790
I am developing an Music player App. And using Play/Pause button and a Progress bar while playing an audio. and I am calling a method with NSTimer to update progress bar. What I need is to pause the progress bar and resume it where it was left off.
I can pause the timer as well the progress bar with the code referred from the links: 1. How to pause a NSTimer? 2. How to Pause/Play NSTimer?
But I am struggling in resuming it where ii was left off. I also need to update progress bar based on the audio.
My code is as below:
AVAudioPlayer *audioPlayer;
NSTimer *audioTimer;
BOOL play;
BOOL ispaused;
int seconds1;
int minutes1;
int hours1;
NSDate *pauseStart, *previousFireDate;
Play/Pause Button action:
- (IBAction)playSoundTapped:(id)sender
{
songUrl = [NSURL URLWithString:@"http://www.stephaniequinn.com/Music/Allegro%20from%20Duet%20in%20C%20Major.mp3"];
self.playerItem = [AVPlayerItem playerItemWithURL:songUrl];
self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
self.player = [AVPlayer playerWithURL:songUrl];
if (play==YES)
{
if (ispaused == YES)
{
float pauseTime = -1*[pauseStart timeIntervalSinceNow];
[audioTimer setFireDate:[NSDate dateWithTimeInterval:pauseTime sinceDate:previousFireDate]];
audioTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateProgress) userInfo:nil repeats:YES];
[self.player play];
ispaused = NO;
}
else
{
audioTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateProgress) userInfo:nil repeats:YES];
[self.player play];
ispaused = NO;
}
_playImg.image=[UIImage imageNamed:@"Pause.png"];
play=NO;
}
else
{
[self.player pause];
ispaused = YES;
pauseStart = [NSDate dateWithTimeIntervalSinceNow:0];
previousFireDate = [audioTimer fireDate];
[audioTimer setFireDate:[NSDate distantFuture]];
_playImg.image=[UIImage imageNamed:@"Play.png"];
play=YES;
}
}
Updates ProgressBar:
- (void)updateProgress
{
if (ispaused == NO)
{
seconds1 += 1;
if (seconds1 == 60)
{
seconds1 = 0;
minutes1++;
if (minutes1 == 60)
{
minutes1 = 0;
hours1++;
}
}
float duration = CMTimeGetSeconds([_playerItem duration]);
float actDuration = duration/100;
float currentTime = CMTimeGetSeconds([_player currentTime]);
float minutes = currentTime/60;
//float seconds = (currentTime - minutes) * 60;
NSLog(@"Duration: %.2f",actDuration);
NSLog(@"Current Time: %.2f",minutes);
NSString *durStr = [NSString stringWithFormat: @"%f",duration];
if ([durStr isEqual: @"nan"])
{
NSLog(@"Nan");
}
else
{
[self setProgress:minutes animated:YES];
}
}
else
{
NSLog(@“Paused”);
}
}
It is restarting the audio instead of resuming. As I am a beginner to iOS I don’t know where I'm doing mistake. Can Anyone help me please….?
Upvotes: 3
Views: 1278
Reputation: 790
I got it!
i just add the below in pause function
rate = CMTimeGetSeconds([_player currentTime])/60;
and setting it as a current time to the audio player with the reference from ketan Parmer's Answer
[audioPlayer setCurrentTime:rate];
and when stoping
rate = 0.0;
and rate is a float which is globally declared. Thanks to Ketan..!
Upvotes: 1
Reputation: 27448
What i am doing in my one of project,
- (void)playPauseAudio : (UIButton*)sender{
if (!playPause.selected) {
[audioPlayer play];
sliderTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateSlider) userInfo:nil repeats:YES];
[mySlider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
mySlider.maximumValue = audioPlayer.duration;
}
else{
[audioPlayer pause];
[sliderTimer invalidate];
}
playPause.selected = !playPause.selected;
}
I have common button for play and pause, it just change it's title on normal state
and selected state
to play
and pause
respectively.
So in my method, playPause
is button, audioPlayer
is AVAudioPlayer
object, sliderTimer
is NSTimer
object, mySlider
is UISlider
object to show progress. That's it. You can manage your case some how as i mentioned.
And updateSlider
and sliderChanged
method is something like below,
- (void)updateSlider{
mySlider.value = audioPlayer.currentTime;
timerLabel.text = [self timeFormatted:audioPlayer.duration - audioPlayer.currentTime];
NSLog(@"update slider call");
}
- (void)sliderChanged : (UISlider*) sender{
[audioPlayer setCurrentTime:mySlider.value];
timerLabel.text = [self timeFormatted:audioPlayer.duration - mySlider.value];
}
So, If user manually change UISlider
then sliderChanged
will get called and your player will reach at that point.
Upvotes: 2