UISwitch with AVAudioPlayer - iphone

Have problem in playsound section.When i turn switch off - soundchecker change his value to NO,but audioplayer not stopping.What's wrong guys?
-(IBAction)Settings {
if(settingsview==nil) {
settingsview=[[UIView alloc] initWithFrame:CGRectMake(10, 130, 300, 80)];
[settingsview setBackgroundColor:[UIColor clearColor]];
UILabel *labelforSound = [[UILabel alloc]initWithFrame:CGRectMake(15, 25, 70, 20)];
[labelforSound setFont:[UIFont systemFontOfSize:18]];
[labelforSound setBackgroundColor:[UIColor clearColor]];
[labelforSound setText:#"Sound"];
SoundSwitch = [[UISwitch alloc]initWithFrame:CGRectMake(10, 50, 20, 20)];
SoundSwitch.userInteractionEnabled = YES;
if(soundchecker == YES) [SoundSwitch setOn:YES];
else [SoundSwitch setOn:NO];
[SoundSwitch addTarget:self action:#selector(playsound:) forControlEvents:UIControlEventValueChanged];
[settingsview addSubview:labelforSound];
[settingsview addSubview:SoundSwitch];
[self.view addSubview:settingsview];
}
else {
[settingsview removeFromSuperview];
[settingsview release];
settingsview=nil;
}
}
//-------Playsound------------------//
-(void)playsound:(id) sender {
NSString *pathtosong = [[NSBundle mainBundle]pathForResource:#"Teachme" ofType:#"mp3"];
AVAudioPlayer* audioplayer = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathtosong] error:NULL];
if(SoundSwitch.on) {
[audioplayer play];
soundchecker = YES;
}
if(!SoundSwitch.on) {
[audioplayer stop];
soundchecker = NO;
}
}

It's not stopping because every time that playsound is called you are creating a NEW AVAudioPlayer. So when you call [audioplayer stop], you are not calling it on the AVAudioPlayer that is currently playing, you are calling it on a new one you just created.
You could add the AVAudioPlayer variable to the header of your class (as a property if you want). Then you could do this:
-(void)playsound:(id) sender
{
if(SoundSwitch.on)
{
if(!audioPlayer) {
NSString *pathtosong = [[NSBundle mainBundle]pathForResource:#"Teachme" ofType:#"mp3"];
audioplayer = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:pathtosong] error:nil];
}
[audioplayer play];
soundchecker = YES;
} else {
if(audioPlayer && audioPlayer.isPlaying) {
[audioplayer stop];
}
soundchecker = NO;
}
}

Related

Record and Play using AVAudioRecorder and AVAudioPlayer

I am creating an app in which user can record and play the recorded file.
I am able to record and play as well, but the problem I am facing is that while playing(listening) the recording, if user presses the record button it will start recording and pressing on the stop resumes the previous recording where it was left.
What I want is when user is listening to the recording and in the mean while he presses the record button, then the last recording (which he was playing) should get destroyed.
In short,I do not want to resume the last recording, I want to play the recent recording.
Here is my code for recording and playback.
-(void)showStopbutton
{
if (flag_for_mic_button == 0)
{
// All in vain the following condition not making any effect palyer is resuming back
if ([audioPlayer isPlaying])
{
[audioPlayer stop];
audioPlayer = nil;
audioPlayer = NO;
}
//
[btn_Mic setImage:[UIImage imageNamed:#"stop.png"] forState:UIControlStateNormal];
lbl_Press.hidden = TRUE;
lbl_updateTime.hidden = FALSE;
[self startRecording];
flag_for_mic_button = 1;
}
else if (flag_for_mic_button ==1)
{
[self stopRecording];
// All in vain the following condition not making any effect palyer is resuming back
if ([audioPlayer isPlaying])
{
audioPlayer = NO;
[audioPlayer stop];
audioPlayer = nil;
}
//
[btn_Mic setImage:[UIImage imageNamed:#"mic.png"] forState:UIControlStateNormal];
lbl_Press.hidden = FALSE;
lbl_updateTime.hidden = TRUE;
flag_for_mic_button = 0;
}
}
-(void)startRecording
{
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *err = nil;
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);
if(err){
NSLog(#"audioSession: %# %d %#", [err domain], [err code], [[err userInfo] description]);
return;
}
[audioSession setActive:YES error:&err];
err = nil;
if(err){
NSLog(#"audioSession: %# %d %#", [err domain], [err code], [[err userInfo] description]);
return;
}
recordSetting = [[NSMutableDictionary alloc]init];
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithInt:44100.0f] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
[recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0];
caldate =[now description];
recorderFilePath = [NSString stringWithFormat:#"%#/%# MyRecording.caf",DOCUMENTS_FOLDER,caldate];
NSURL *url = [NSURL fileURLWithPath:recorderFilePath];
err=nil;
audioRecorder = [[AVAudioRecorder alloc]initWithURL:url settings:recordSetting error:&err];
[audioRecorder setDelegate:self];
[audioRecorder prepareToRecord];
audioRecorder.meteringEnabled = YES;
[audioRecorder record];
[self setTimer];
[self hidePlaybackView];
}
-(void)stopRecording
{
[audioRecorder stop];
[start_Timer invalidate];
[self showPlaybackView];
}
-(void)playSound
{
// [self playBackTimer];
if (!recorderFilePath)
{
recorderFilePath = [NSString stringWithFormat:#"%#/%# MyRecording.caf",DOCUMENTS_FOLDER,caldate];
}
if(soundID)
{
AudioServicesDisposeSystemSoundID(soundID);
}
//Get a URL for the sound file
NSURL *filePath = [NSURL fileURLWithPath:recorderFilePath isDirectory:NO];
//Use audio sevices to create the sound
AudioServicesCreateSystemSoundID((CFURLRef)CFBridgingRetain(filePath), &soundID);
//Use audio services to play the sound
AudioServicesPlaySystemSound(soundID);
audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:filePath error:nil];
[audioPlayer play];
audioPlayer.delegate = self;
}
EDIT:
-(void)showPlaybackView
{
view_playback = [[UIView alloc]initWithFrame:CGRectMake(0, 600, 320, 80)];
view_playback.backgroundColor = [UIColor grayColor];
[self.view addSubview:view_playback];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];
view_playback.frame = CGRectMake(0, 325, 320, 55);
[UIView commitAnimations];
btn_Playback = [UIButton buttonWithType:UIButtonTypeCustom];
[btn_Playback setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
btn_Playback.frame = CGRectMake(10, 10, 35, 35);
[view_playback addSubview:btn_Playback];
[btn_Playback addTarget:self action:#selector(playSound) forControlEvents:UIControlEventTouchUpInside];
btn_done = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn_done setTitle:#"Done" forState:UIControlStateNormal];
btn_done.frame = CGRectMake(265, 15, 45, 30);
btn_done.titleLabel.font = [UIFont systemFontOfSize:14.0f];
[view_playback addSubview:btn_done];
[view_playback addSubview:playback_slider];
[btn_done addTarget:self action:#selector(Done) forControlEvents:UIControlEventTouchUpInside];
}
Any help would be appreciable.
Thanks
Try this approach :
-(void)showStopbutton
{
if (![audioPlayer isPlaying])
{
[audioPlayer start];
// other stuff
}
if ([audioPlayer isPlaying])
{
[audioPlayer stop];
// Delete the previous recording in the delegate method of audio player
}
}
I stopped the Audio Player and do not let it resume back by using the following code.
if([audioPlayer isPlaying])
{
audioPlayer.currentTime=0;
}
Happy Coding!

Repeat (Loop) UIButton besides Play button

Basically in app have a play button for audio file, want to add another UIButton Besides Play button so that whenever it is pressed it will repeat audio file for some number of times or may be infinite until it is pressed again to stop repetition of playing audio file. How can this be achieved.
Below is the code for play/pause toggle button
_playButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_playButton addTarget:self action:#selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
_playButton.frame = CGRectMake(80, 40, 25, 25);
[_playButton setImage:[UIImage imageNamed:#"1play.png"] forState:UIControlStateNormal];
[_playButton setImage:[UIImage imageNamed:#"audiopause.png"] forState:UIControlStateSelected];
UIBarButtonItem *play = [[UIBarButtonItem alloc] initWithCustomView:_playButton];
// Get the file path to the song to play.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Theme"ofType:#"mp3"];
// Convert the file path to a URL.
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
//Initialize the AVAudioPlayer.
player = [[AVAudioPlayer alloc]
initWithContentsOfURL:fileURL error:nil];
player.delegate = self;
- (void)playAction:(id)sender
{
if([player isPlaying])
{
[sender setImage:[UIImage imageNamed:#"1play.png"] forState:UIControlStateSelected];
[player pause];
//[timer invalidate];
//timer = nil;
//[self pauseTimer];
}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;
}
}
It looks like all you need is to execute an action every x number of seconds. You can move the code the UIButton is executing to a method, and then have a NSTimer looping that executes that method for n number of times, then invalidate the NSTimer when you are done.
I have finally worked it out like this
-(void) RepeatAction:(id)sender{
if (player && player.playing) {
[player stop];
player = nil;
[_playButton setImage:[UIImage imageNamed:#"1play.png"] forState:UIControlStateNormal];
return;
}
// Get the file path to the song to play.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Theme"ofType:#"mp3"];
// Convert the file path to a URL.
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
//Initialize the AVAudioPlayer.
player = [[AVAudioPlayer alloc]
initWithContentsOfURL:fileURL error:nil];
player.delegate = self;
player.numberOfLoops = -1;
[player play];
}
Now only problem i m facing is that play/pause toggle button is disturbed with this. How to fix that.

Toggling play/pause not working

Getting red warnings for {[audioPlayer pause];}saying Expected']' and getting another red warning message for [[audioPlayer play];] saying Expected expression.
UIButton *playpauseButton = [UIButton buttonWithType:UIButtonTypeCustom];
[playpauseButton addTarget:self action:#selector(playpauseAction:) forControlEvents:UIControlEventTouchUpInside];
playpauseButton.frame = CGRectMake(0, 0, 50, 50);
[playpauseButton setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
[playpauseButton setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateSelected];
UIBarButtonItem *playpause = [[UIBarButtonItem alloc] initWithCustomView:playpauseButton];
The action code:
-(void)playpauseAction:(UIButton *)sender
{
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"theme"
ofType:#"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:fileURL error:nil];
[fileURL release];
[audioPlayer prepareToPlay];
audioPlayer.currentTime = 0;
//[audioPlayer play];
if
([audioPlayer isPlaying]){
Image:[UIImage imageNamed:#"play.png"] forState:UIControlStateSelected
setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal
{[audioPlayer pause];}
} else {
setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateSelected
Image:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal
[[audioPlayer play]; ]
}
}
I need help in fixing this code.
Thanks for help.
The entire play/pause part of your method is completely invalid Objective-C. Try this instead:
if ([audioPlayer isPlaying])
{
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
[audioPlayer pause];
}
else
{
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
}
Also, you really don’t need to be recreating your audioPlayer in that method. Put it (where by “it” I mean “everything in that method between the first line and the ‘if’”) in your -viewDidLoad or something.
try setting the delegate and checking for error:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"theme" ofType:#"mp3"];
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: [NSURL fileURLWithPath:filePath] error:&err];
if( err ){
NSLog(#"Failed with reason: %#", [err localizedDescription]);
} else{
//set our delegate and begin playback
audioPlayer.delegate = self;
[audioPlayer play];
}
btw, you definitely don't want to be allocing the audioPlayer every time the button is pressed, unless you check if it's nil first (for the first run through).

UIButton view unrecognized selector sent to instance

Basically i have a UIToolbar on the main window and when i hit the infobutton to open a modal view application is crashing with output message that UIButton view unrecognized selector sent to instance. Can someone please help me to solve this output message.
UIButton *infoItem = [[UIButton buttonWithType:UIButtonTypeInfoLight] retain];
infoItem.frame = CGRectMake(250.0, 8.0, 25.0, 25.0);
infoItem.backgroundColor = [UIColor clearColor];
[infoItem addTarget:self action:#selector(displayModalViewaction:) forControlEvents:UIControlEventTouchUpInside];
infoItem.backgroundColor = [UIColor grayColor];
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
NSArray *toolbarItems = [NSArray arrayWithObjects: settingsButton, flexItem, systemItem, flexItem, systemItem1,flexItem, systemItem2, flexItem, systemItem3, flexItem, infoItem, nil];
[toolbar setItems:toolbarItems];
[settingsButton release];
[systemItem release];
[systemItem1 release];
[systemItem2 release];
[systemItem3 release];
[infoItem release];
[flexItem release];
[super viewDidLoad];
- (void) playaudio: (id) sender {
// Get the file path to the song to play.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"theme"
ofType:#"mp3"];
// Convert the file path to a URL.
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:filePath];
//Initialize the AVAudioPlayer.
self.audioPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:fileURL error:nil];
// Making sure the audio is at the start of the stream.
self.audioPlayer.currentTime = 0;
[self.audioPlayer play];
}
- (void)pause: (id)sender {
if
([audioPlayer isPlaying])
{[audioPlayer pause];}
else
{[audioPlayer play];}
}
- (void)stop: (id) sender
{
[audioPlayer stop];
}
- (void)displayModalViewaction
{
self.viewController = [[Infoviewcontroller alloc] init];
UINavigationController *navigationController=[[UINavigationController alloc] init];
navigationController.navigationBar.tintColor = [UIColor brownColor];
[navigationController pushViewController:_viewController animated:YES];
[self.view addSubview:navigationController.view];
}
Appreciate help to solve this.
Thanks in advance.
[infoItem addTarget:self action:#selector(displayModalViewaction:) forControlEvents:UIControlEventTouchUpInside];
infoItem.backgroundColor = [UIColor grayColor];
should be
[infoItem addTarget:self action:#selector(displayModalViewaction) forControlEvents:UIControlEventTouchUpInside];
infoItem.backgroundColor = [UIColor grayColor];
because displayModalViewaction do not receive any parameters.
use #selector(displayModalViewaction) to add event;
or change method define with: -(void)displayModalViewaction:(id)sender;

Temporary release memory

I am creating a quiz app in iPhone.
So that i have so many labels and buttons in use at a time.
If i release them right after one question then application stops.
If i am not doing that and releasing them at dealloc function then it shows memory warning and app crashes.
I am using this Code
received memory warning. level 1
If i set around 20 questions then application is not crashing but if i add more questions then it crashes..
I think it is allocating memory and not releasing right after one question.
Please help me out this:(
Edited :
I am using this code after selecting answer
-(void)checkAnswer:(int)theAnswerValue
{
[AVback stop];
[scrollview scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[Challengetext setHidden:YES];
[theScore setHidden:YES];
[theQuestion setHidden:NO];
[Question setHidden:YES];
if(rightAnswer == theAnswerValue)
{
NSString *AVpath = [[NSBundle mainBundle] pathForResource:#"Winner_1" ofType:#"m4a"];
AVAudioPlayer *AVbtn1 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:AVpath] error:NULL];
[img1 setHidden:NO];
[img2 setHidden:YES];
[theQuestion setFont:[UIFont fontWithName:#"Futura" size:30]];
theQuestion.textColor = [UIColor purpleColor];
theQuestion.text = #"\n\nCorrect Answer!!";
[rightans setHidden:NO];
[Description setHidden:NO];
[ContainerView setHidden:NO];
myScore = myScore + 50;
}
else
{
NSString *AVpath = [[NSBundle mainBundle] pathForResource:#"incorrect2" ofType:#"m4a"];
AVAudioPlayer *AVbtn1 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:AVpath] error:NULL];
QuizAppUniversalAppDelegate *appDelegate = (QuizAppUniversalAppDelegate *) [[UIApplication sharedApplication] delegate];
if(appDelegate.soundIndicator == 0){
[AVbtn1 play];
}
else{
[AVback stop];
[AVstart stop];
[AVbtn1 stop];
}
[img2 setHidden:NO];
[img1 setHidden:YES];
[theQuestion setFont:[UIFont fontWithName:#"Futura" size:30]];
theQuestion.textColor = [UIColor redColor];
theQuestion.text = #"\nIncorrect Answer!!\nRight answer is : \n ";
[rightans setHidden:NO];
[Description setHidden:NO];
[ContainerView setHidden:NO];
myScore = myScore ;
}
Thanks.. Any help will be appreciated.. !!
You don't appear to be releasing your avBtn1 object anywhere, and you are allocating a new one every time checkAnswer is called. Is that dealt with somewhere else in the code?