NumberofLoops for Audio - iphone

When repeat button is hit for the first time then it should run infinite times and when it is hit for second time then it should not repeat audio rather it should stop looping. . Below is the code it works very well for the first time but when it is pressed again it is not stopping looping.
BOOL isFirstTime;
#interface English : UIViewController <UITextViewDelegate, ADBannerViewDelegate, UIScrollViewDelegate,
-(void) RepeatAction:(id)sender{
if(isFirstTime == YES){
player.numberOfLoops = -1;
} else {
player.numberOfLoops = 0;
}
}
- (void)playAction:(id)sender
{
if([player isPlaying])
{
[sender setImage:[UIImage imageNamed:#"1play.png"] forState:UIControlStateSelected];
[player pause];
}else{
[sender setImage:[UIImage imageNamed:#"audiopause.png"] forState:UIControlStateNormal];
[player play];
slidertimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:#selector(updateProgressBar:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:slidertimer forMode:NSRunLoopCommonModes];
timer = slidertimer;
}}
Thanks for help.

-(void) RepeatAction:(id)sender{
if(isFirstTime){ // even here you need not to compare with == YES
player.numberOfLoops = -1;
isFirstTime = NO;
} else {
player.numberOfLoops = 0;
isFirstTime = YES;
}
}

Related

update UISlider progress bar currenttime and duration when audio plays

Have a UISlider ProgressBar on UIToolbar when audio plays wants UISlider ProgressBar to display the duration of the audio file and currenttime of the audio file.
- (void)playAction:(id)sender
{
if([player isPlaying])
{
[sender setImage:[UIImage imageNamed:#"1play.png"] forState:UIControlStateSelected];
[player pause];
//[self pauseTimer];
}else{
[sender setImage:[UIImage imageNamed:#"audiopause.png"] forState:UIControlStateNormal];
[player play];
//[self resumeTimer];
}
[self updateProgressBar:timer];
}
- (void)updateProgressBar:(NSTimer *)timer
{
NSTimeInterval playTime = [self.player currentTime];
NSTimeInterval duration = [self.player duration];
float progress = playTime/duration;
[_progressBar setProgress:progress];
}
But it is not working.
Thanks for help.
You're probably going to want to call the updateProgressBar method using a timer, rather than what you're doing right now (calling it in the playAction method). Instead, you can use the playAction method to create the timer that calls updateProgressBar, or pause/stop existing timers.
Looks like you already have an instance variable to keep track of the timer, which is good. Here is how you would create a new timer:
[timer invalidate]; // stop the old timer
// this timer runs once per second, perhaps you want to make it something shorter which would look less choppy
NSTimer *progressTimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:#selector(updateProgressBar:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:progressTimer forMode:NSRunLoopCommonModes];
timer = progressTimer;
If you have a method to pause the audio, you can invalidate the timer there too.
[timer invalidate];
timer = nil;
Altogether, in your code, this would look something like:
- (void)playAction:(id)sender
{
if([player isPlaying])
{
[sender setImage:[UIImage imageNamed:#"1play.png"] forState:UIControlStateSelected];
[player pause];
[timer invalidate];
timer = nil;
} else {
[sender setImage:[UIImage imageNamed:#"audiopause.png"] forState:UIControlStateNormal];
[player play];
[timer invalidate];
NSTimer *progressTimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:#selector(updateProgressBar:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:progressTimer forMode:NSRunLoopCommonModes];
timer = progressTimer;
}
}
- (void)updateProgressBar:(NSTimer *)timer
{
NSTimeInterval playTime = [self.player currentTime];
NSTimeInterval duration = [self.player duration];
float progress = playTime/duration;
[_progressBar setProgress:progress];
}
Try this:
This is for the update slider..
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateSlider) userInfo:nil repeats:YES];
slider.maximumValue = avAudioPlayer.duration;
[slider addTarget:self action:#selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
- (void)updateSlider {
slider.value = avAudioPlayer.currentTime;
}
- (IBAction)sliderChanged:(UISlider *)sender {
[avAudioPlayer stop];
[avAudioPlayer setCurrentTime:slider.value];
[avAudioPlayer prepareToPlay];
[avAudioPlayer play];
}

increase a value while uibutton is kept pressing in iphone

I am trying to increase a variable's value while uibutton is kept pressing. But when user leaves button, increasing of variable's value will be stopped.
i have tried using threads with touch down and touchupinside but couldn't make it work.
-(void) changeValueOfDepthFields:(UIButton *)sender {
if (pressing)
pressing = NO;
else
pressing = YES;
pressingTag = 0;
while (pressing) {
[NSThread detachNewThreadSelector:#selector(increaseValue) toTarget:self withObject:nil];
}
}
- (void) stopValueChange:(UIButton *)sender {
pressing = NO;
}
[fStopUp addTarget:self action:#selector(changeValueOfDepthFields:) forControlEvents:UIControlEventTouchDown];
[fStopUp addTarget:self action:#selector(stopValueChange:) forControlEvents:UIControlEventTouchUpInside];
- (void) increaseValue {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
fstopVal = fstopVal + 0.1;
[self performSelectorOnMainThread:#selector(changeTextOfValues) withObject:nil waitUntilDone:YES];
[pool release];
}
- (void) changeTextOfValues {
fStopField.text = [NSString stringWithFormat:#"%.02f", fstopVal];
}
I wonder if there is an alternative way to do this or not. It seems very simple but couldn't think of any other solution than this one.
It is much easier to use an NSTimer.
- (void)changeValueOfDepthFields:(UIButton *)sender
{
if (!self.timer) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(increaseValue) userInfo:nil repeats:YES];
}
}
- (void)stopValueChange:(UIButton *)sender
{
if (self.timer) {
[self.timer invalidate];
self.timer = nil;
}
}
- (void)increaseValue
{
fstopVal = fstopVal + 0.1;
fStopField.text = [NSString stringWithFormat:#"%.02f", fstopVal];
}
Note: The previous code is just for reference, I didn't do any memory management for example.

How to check if audioplayer is paused while loading multiple viewcontrollers

In playpauseAction Method execution it will play audio file as well as load multiple viewcontrollers
-(void)playpauseAction:(id)sender
{
if
([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateSelected];
[audioPlayer pause];
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
self.timer = [NSTimer scheduledTimerWithTimeInterval:11 target:self selector:#selector(displayviewsAction:) userInfo:nil repeats:NO];
}
}
While loading these view controllers just want to check in every viewcontroller that if audioplayer is paused then invalidate timer if not then continue loading of viewcontroller with NSTimer
- (void)displayviewsAction:(id)sender
{
FirstViewController *viewController = [[FirstViewController alloc] init];
viewController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:viewController.view];
[self.view addSubview:toolbar];
if
([audioPlayer pause]){
[timer invalidate];
} else {
self.timer = [NSTimer scheduledTimerWithTimeInterval:23 target:self selector:#selector(secondViewController) userInfo:nil repeats:NO];
}
[viewController release];
}
My problem is when i add if statement in displayviewAction method it gives me red warning message that statement requires expression of scalar type (void invalid).
But if statement in the playpauseAction works fine.
Why the if statement of displayviewAction is giving red warning message.
AVAudioPlayer's pause is defined as:
-(void)pause
so writing:
if([audioPlayer pause]) {...}
corresponds to write:
if(void) {...}
and void is not a scalar type, exactly what the error message tells you.
Probably your intention was to check if the audio player was paused, that is it is not playing :
if([audioPlayer isPlaying]==NO) {...}

How to resume updating views when resumed AVAudioplayer

I m struggling with this issue for so long but not able to find any solution for this
The issue i have is when i pause the audioplayer i want views to be paused from updating so i used timer invalidate to pause the views from loading but when i resume play only Audioplayer is resumed not the views cause i invalidated the timer.
Now i how i can resume updating views from that point where view was paused. By starting the timer again i can start updating views again but how program will know that at what view it was paused and it should resume updating views from that point. There are multiple views involved displayed code for only two.
-(void)playpauseAction:(id)sender
{
if
([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[timer invalidate];
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
self.timer = [NSTimer scheduledTimerWithTimeInterval:11 target:self selector:#selector(displayviewsAction:) userInfo:nil repeats:NO];
}
}
- (void)displayviewsAction:(id)sender
FirstViewController *viewController = [[FirstViewController alloc] init];
viewController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:viewController.view];
[self.view addSubview:toolbar];
[viewController release];
self.timer = [NSTimer scheduledTimerWithTimeInterval:23 target:self selector:#selector(secondViewController) userInfo:nil repeats:NO];
-(void)secondViewController {
SecondViewController *secondController = [[SecondViewController alloc] init];
secondController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:secondController.view];
[self.view addSubview:toolbar];
[secondController release];
self.timer = [NSTimer scheduledTimerWithTimeInterval:27 target:self selector:#selector(ThirdviewController) userInfo:nil repeats:NO];
}
Thanks and appreciate for your answers and helping me out with this issue.
Use a background thread to basically bind the view to the player, something like this:
UIImageView* imageView; //the view that gets updated
int current_selected_image_index = 0;
float time_for_next_image = 0.0;
AVAudioPlayer* audioPlayer;
NSArray* image_times; //an array of float values representing each
//time when the view should update
NSArray* image_names; //an array of the image file names
-(void)update_view
{
UIImage* next_image_to_play = [image_names objectAtIndex:current_selected_image_index];
imageView.image = next_image_to_play;
}
-(void)bind_view_to_audioplayer
{
while(audioPlayer.isPlaying)
{
float currentPlayingTime = (float)audioPlayer.currentTime;
if(currentPlayingTime >= time_for_next_image)
{
current_selected_image_index++;
[self performSelectorOnMainThread:#selector(update_view) withObject:nil waitUntilDone:NO];
time_for_next_image = [image_times objectAtIndex:[current_selected_image_index+1)];
}
[NSThread sleep:0.2];
}
}
-(void)init_audio
{
current_selected_image_index = 0;
time_for_next_image = [image_times objectAtIndex:1];
}
-(void)play_audio
{
[audioPlayer play];
[self performSelectorInBackground:#selector(bind_view_to_audioplayer) withObject:nil];
}
-(void)pause_audio
{
[audioPlayer pause];
//that's all, the background thread exits because audioPlayer.isPlaying == NO
//the value of current_selected_image_index stays where it is, so [self play_audio] picks up
//where it left off.
}
also, add self as observer for the audioPlayerDidFinishPlaying:successfully: notification to reset when the audioplayer finishes playing.

Gesture recognizer in ios

I have this code in LongTapGestureRecognizer for autoscrolling a view:
-(void) longPressDetectedgesture:
(UILongPressGestureRecognizer*)recognizer
{
_btnautoscrollstop.hidden = NO;
_btnautoscroll.hidden = YES;
// if (autoscrollTimer == nil) {
autoscrollTimer = [NSTimer
scheduledTimerWithTimeInterval:(55.0/1000.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:nil
repeats:YES];
}
- (void)autoscrollTimerFired:(NSTimer*)timer {
CGPoint scrollPoint = self.table.contentOffset;
scrollPoint = CGPointMake(scrollPoint.x, scrollPoint.y + 1);
[self.table setContentOffset:scrollPoint animated:NO];
}
It works perfect for me, but my need is, the autoscrooling must stop when the user taps the screen for Longgesture for the second time and vise versa. How to stop this, when the user taps for a second time.
It looks like you're almost there. You probably want something like this:
if (recogniser.state == UIGestureRecognizerStateBegan) {
if (autoscrollTimer == nil) {
autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:(55.0/1000.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:nil
repeats:YES];
} else {
[autoscrollTimer invalidate];
autoscrollTimer = nil;
}
}
What i usually do is declare a global BOOL Alter; and initialize it Alter = NO; in viewDidLoad (or any other method) then
-(void) longPressDetectedgesture:(UILongPressGestureRecognizer*)recognizer
{
if(Alter)
{
Alter = NO;
[autoscrollTimer inValidate];
}
else
{
Alter = YES;
_btnautoscrollstop.hidden = NO;
_btnautoscroll.hidden = YES;
// if (autoscrollTimer == nil) {
autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:(55.0/1000.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:nil
repeats:YES];
}
}
create a BOOL called shouldFireTimer in viewDidLoad or similar and update it's value each time you detect a longpress
-(void) longPressDetectedgesture: (UILongPressGestureRecognizer*)recognizer {
_btnautoscrollstop.hidden = NO;
_btnautoscroll.hidden = YES;
if ( shouldFireTimer ) {
[autoscrollTimer invalidate];
autoscrollTimer = nil;
} else {
autoscrollTimer = [NSTimer
scheduledTimerWithTimeInterval:(55.0/1000.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:nil
repeats:YES];
}
shouldFireTimer = !shouldFireTimer;
}
- (void)autoscrollTimerFired:(NSTimer*)timer {
CGPoint scrollPoint = self.table.contentOffset;
scrollPoint = CGPointMake(scrollPoint.x, scrollPoint.y + 1);
[self.table setContentOffset:scrollPoint animated:NO];
}
or like Matt says above maybe just check nil status instead of using a BOOL. I suggest using a BOOL as you maybe firing autoscrollTimerFired in other circumstances too (from a button for example) i.e. it might not be nil when you want to call it.