I am creating a custom object, it is currently very simple. Below you will find my .h for the object.
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#interface LAZMessagePlayer : NSObject <AVAudioPlayerDelegate>
- (void)play:(UIView*)viewThatWasPressed;
- (void)pause;
- (BOOL)isPlaying;
#end
and the corresponding .m for the object
#import "LAZMessagePlayer.h"
#implementation LAZMessagePlayer {
AVAudioPlayer* myPlayer;
UIView* currentViewPlaying;
}
-(id)init{
NSLog(#"init audio");
NSURL* src = [NSURL fileURLWithPath:[NSString stringWithFormat:#"/Users/Developer/Downloads/317.mp3", [[NSBundle mainBundle] resourcePath]]];
NSError* error;
myPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:src error:&error];
}
-(void)play:(UIView*)viewThatWasPressed {
NSLog(#"play");
currentViewPlaying = viewThatWasPressed;
currentViewPlaying.hidden = YES;
[myPlayer play];
}
-(void)pause {
NSLog(#"pause");
currentViewPlaying.hidden = NO;
[myPlayer pause];
}
-(void)audioPlayerDidFinishPlaying:
(AVAudioPlayer *)player successfully:(BOOL)flag
{
NSLog(#"done");
currentViewPlaying.hidden = NO;
}
-(BOOL)isPlaying {
return myPlayer.playing;
}
#end
Inside of my ViewController i have declared a private variable at the top of my Controller.m like so,
#import "LAZMessagesViewController.h"
#interface LAZMessagesViewController () {
LAZMessagePlayer* myPlayer;
}
Inside my viewDidLoad I alloc/init myPlayer.
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationBarExtensionViewDelegate = self;
// Do any additional setup after loading the view.
myPlayer = [[LAZMessagePlayer alloc] init];
}
Later inside my Tap handler I receive a BAD ACCESS code = 1 the first time I try to reference myPlayer, here is the first line that breaks
if([myPlayer isPlaying])...
I am familiar with c++ memory management, but new to Objective-C entirely. Can somebody please point out my glaringly obvious miss.
Thank you.
Solved it myself. Inside of Object.h I needed:
self = [super init];
.
.
.
return self;
Related
I currently have a SettingsViewController which handles starting/stopping music and adjusting the musics volume.
Is it possible to make the music stay on after unwinding the SettingsViewController? And after turning on the music and switching ViewControllers, can I re-open the SettingsViewController and turn off the music as well? Please let me know the limitations.
Here is the code for my SettingsViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface SettingsViewController : UIViewController <AVAudioPlayerDelegate>
{
AVAudioPlayer *audioPlayer;
IBOutlet UISwitch *Switch;
IBOutlet UISlider *Slider;
}
-(IBAction)Switch:(UISwitch *)sender;
-(IBAction)Slider:(UISlider *)sender;
#end
And here is the code for my SettingsViewController.m
#import "SettingsViewController.h"
#interface SettingsViewController ()
#end
#implementation SettingsViewController
-(IBAction)Switch:(UISwitch *)sender{
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
if(sender.tag == 0){
if(sender.on){
[standardDefaults setObject:#"On" forKey:#"keyName"];
//choosing and setting the music file
NSString *music = [[NSBundle mainBundle]pathForResource:#"bgmusic1" ofType:#"mp3"];
audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:music] error:NULL];
audioPlayer.delegate = self;
audioPlayer.numberOfLoops= -1; //sets the music to loop infinitely
[audioPlayer play]; //plays the music
} else if (sender.on == 0){
[standardDefaults setObject:#"Off" forKey:#"keyName"];
[audioPlayer stop]; //stops the music
}
}
[standardDefaults synchronize];
}
-(IBAction)Slider:(UISlider *)sender{
audioPlayer.volume = sender.value / 100.0; //will adjust the volume of the music according the slider value
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
Let me know what needs to be modified!
Do that in your AppDelegate.
To access it from anywhere, import it's .h file in your ViewControllers .m file and access it with
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
Make the audioplayer to a property in your AppDelegate.h to allow public access (for e.g. your other viewControllers)
#interface AppDelegate: NSAppDelegate
{
IBOutlet UISwitch *Switch;
IBOutlet UISlider *Slider;
}
#property AVAudioPlayer *audioPlayer; // <------
-(IBAction)Switch:(UISwitch *)sender;
-(IBAction)Slider:(UISlider *)sender;
#end
Then adjust each call of your audioplayer in the m file to adopt the change in your h file.
//Instead of [audioplayer doSomething] write...
[self.audioplayer doSomething];
// in modern objective-c you can use also
[_audioplayer doSomething];
To call your audioplayer from other ViewControllers then implement the first mentioned code and call your player like so
[appDelegate.audioplayer doSomething]
Because your audioPlayer will be release when its parent SettingsViewController released.
So you should add it to global and you can make it with Singleton Pattern.
Create BackgroundPlayer.h
#interface BackgroundPlayer: NSObject {
AVAudioPlayer *audioPlayer;
}
+ (id)sharedManager;
#end
and BackgroundPlayer.m
#implementation BackgroundPlayer
static BackgroundPlayer* sharedInstance = nil;
+ (BackgroundPlayer*) sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[super allocWithZone:NULL] init];
}
return sharedInstance;
}
- (id)init
{
self = [super init];
return self;
}
-(void)playAudio:(NSString *) audioPath
{
audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:audioPath] error:NULL];
audioPlayer.delegate = self;
audioPlayer.numberOfLoops= -1; //sets the music to loop infinitely
[audioPlayer play]; //plays the music
}
-(void)setVolum:(float) volum {
if (audioPlayer) {
audioPlayer.volume = sender.value / 100.0;
}
}
Then you just call
NSString *music = [[NSBundle mainBundle]pathForResource:#"bgmusic1" ofType:#"mp3"];
[[BackgroundPlayersharedInstance] playAudio:music];
i am trying to make a simple audio board application, i am following the Apple documentation on the AVFoundationPlayer, but i keep getting this error (no visible #interface for 'NSBundle' declares the selector 'pathForRescource:ofType:' ) and i have searched for an hour, with no result.
my .h file
#import <UIKit/UIKit.h>
#import <AVFoundation/AVAudioPlayer.h>
#interface ViewController : UIViewController <AVAudioPlayerDelegate> {
}
//actions
-(IBAction)playSound1;
-(IBAction)playSound2;
-(IBAction)playSound3;
-(IBAction)playSound4;
#property (nonatomic, strong) AVAudioPlayer *player;
#end
my .m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize player;
- (void)viewDidLoad
{
NSString *soundFilePath1 =
[[NSBundle mainBundle] pathForRescource: #"trumpet"
ofType: #"mp3"];
NSURL *fileURL1 = [[NSURL alloc] initFileURLWithPath: soundFilePath1];
AVAudioPlayer *newPlayer =
[[AVAudioPlayer alloc] initWithContentsOfURL:fileURL1 error:nil];
[fileURL1 release];
self.player= newPlayer;
[newPlayer release];
[player prepareToPlay];
[player setDelegate: self];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
If i can provide any other details i would be happy to help and thank you for reading.
It's a typo. You have written pathForRescource: and it is pathForResource:ofType:.
- (NSString *)pathForResource:(NSString *)name ofType:(NSString *)extension
I am an amateur developer making an ios app which includes a sound file (mp3) being played when a button impressed. However, the sound is not playing (tested on a mobile device, not ios simulator). I already have the sound file in bundle resources and have added AVFoundation to link binary with libraries. I have xcode 4.6 and have mac osx 10.8.4. Here is my code for viewcontroller.h:
#import <UIKit/UIKit.h>
#import <RevMobAds/RevMobAds.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController : UIViewController
- (IBAction)playButton:(id)sender;
- (IBAction)stopButton:(id)sender;
#property (nonatomic, strong) AVAudioPlayer *avPlayer;
- (void)revmob;
#end
Viewcontroller.m:
#import "ViewController.h"
#import <RevMobAds/RevMobAds.h>
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[[RevMobAds session] showBanner];
// Do any additional setup after loading the view, typically from a nib.
NSString *stringPath = [[NSBundle mainBundle] pathForResource:#"98648__dobroide__20100606-mosquito" ofType:#"mp3"];
if (stringPath)
{
NSURL *url = [NSURL fileURLWithPath:stringPath];
NSError *error;
_avPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
if (!error)
{
[_avPlayer setNumberOfLoops:-1];
}
else
{
NSLog(#"Error occurred: %#", [error localizedDescription]);
}
}
else
{
NSLog(#"Resource not found");
}
[self performSelector:#selector(revmob) withObject:nil afterDelay:10.0];
}
- (void)revmob
{
[[RevMobAds session] showFullscreen];
}
- (IBAction)playButton:(id)sender
{
[_avPlayer play];
NSLog(#"Sound playing");
}
- (IBAction)stopButton:(id)sender
{
[_avPlayer pause];
NSLog(#"Sound Stopped");
}
#end
In ViewController.h import the AVFoundation header file:
#import
Go the ViewController.m and add the following outlet properties and IBAction method definitions in the interface section:
#interface ViewController ()
#property (nonatomic, strong) IBOutlet UILabel *trackTitle;
#property (nonatomic, strong) IBOutlet UILabel *playedTime;
- (IBAction)stopSound:(id)sender;
- (IBAction)playOrPauseSound:(id)sender;
#end
Go back to ViewController.xib and make the following connections:
top label -> trackTitle outlet
middle label -> playedTime outlet
left button -> IBAction playOrPauseSound
right button -> IBAction stopSound
Now the connections are made we can finish our code in ViewController.m. In the interface section add the following properties
#property (nonatomic, strong) AVAudioPlayer *audioPlayer;
#property (nonatomic) BOOL isPlaying;
#property (nonatomic, strong) NSTimer *timer;
Go the ViewController.m and add the following outlet properties and IBAction method definitions in the interface section.
#interface ViewController ()
#property (nonatomic, strong) IBOutlet UILabel *trackTitle;
#property (nonatomic, strong) IBOutlet UILabel *playedTime;
- (IBAction)stopSound:(id)sender;
- (IBAction)playOrPauseSound:(id)sender;
#end
Change the viewDidLoad method in :
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.isPlaying = NO;
self.trackTitle.text = #"The Stone Foxes - EveryBody Knows";
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [mainBundle pathForResource:#"thestonefoxes-everybodyknows" ofType:#"mp3"];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
NSError *error = nil;
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:fileData error:&error]
[self.audioPlayer prepareToPlay];
}
- (IBAction)playOrPauseSound:(id)sender;
{
if (self.isPlaying)
{
// Music is currently playing
[self.audioPlayer pause];
self.isPlaying = NO;
}
else
{
// Music is currenty paused/stopped
[self.audioPlayer play];
self.isPlaying = YES;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateTime) userInfo:nil repeats:YES];
}
}
- (void)updateTime
{
NSTimeInterval currentTime = self.audioPlayer.currentTime;
NSInteger minutes = floor(currentTime/60);
NSInteger seconds = trunc(currentTime - minutes * 60);
// update your UI with currentTime;
self.playedTime.text = [NSString stringWithFormat:#"%d:%02d", minutes, seconds];
}
- (IBAction)stopSound:(id)sender
{
[self.audioPlayer stop];
self.audioPlayer.currentTime = 0;
self.isPlaying = NO;
}
I've tested your code on my Mac and it seems to work just fine. It could be that the cause for your problem is that while your mp3 is visible in Xcode, it's not being added to the bundle during compilation. Like in this question.
To fix it, click the mp3 in Xcode, look at the File Inspector and check the Target Membership box next to your target (in the screenshot mine is SOTest).
Here is my code:
MainViewConroller.h
#import <UIKit/UIKit.h>
#import "FlipsideViewController.h"
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate> {
AVAudioPlayer *audioPlayer;
NSArray *soundsArray;
}
#property(nonatomic, retain) AVAudioPlayer *audioPlayer;
#property(nonatomic, retain) NSArray *soundsArray;
-(void)prepareSounds;
- (IBAction)playSound:(UIButton *)sender;
#end
Here is my MainViewController.m:
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
#synthesize audioPlayer;
#synthesize soundsArray;
-(void)prepareSounds
{
NSString *filepath= [[NSBundle mainBundle] pathForResource:#"Sound" ofType:#"plist"];
self.soundsArray = [[NSArray alloc] initWithContentsOfFile:filepath];
}
- (void)stopAudio
{
if (audioPlayer!= nil) {
[audioPlayer stop];
//do some task for changing the Image i.e setting the default image
}
}
- (IBAction)playSound:(UIButton *)sender
{
UIButton *btn = (UIButton*)sender;
NSString *soundName = [soundsArray objectAtIndex:(btn.tag - 1)];
NSString *path = [[NSBundle mainBundle] pathForResource:soundName ofType:#"mp3"];
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:nil];
self.audioPlayer = p;
if([audioPlayer isPlaying])
{
[self stopAudio];
}
[self.audioPlayer play];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Flipside View
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)showInfo:(id)sender
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:controller animated:YES completion:nil];
}
#end
I have 3 buttons. In the 'Supporting Files' folder I have an array of strings with the name of the sound files I want to play, named 'Sound.plist', and in the 'Supporting Files' folder I have a folder named 'Sounds', which contains the sound files.
All of my buttons play the same sound, even when I delete the .plist file. It seems to always play the sound that is first in the 'Sounds' folder. Can someone please provide some insight, I feel like I have tried everything. Thanks!
I'm trying to get a short audio file (mp3) to play in my app. Here is the code i'm using:
AVAudioPlayer *AudioPlayer;
NSError *error;
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
pathForResource:#"filename"
ofType:#"mp3"]];
AudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
AudioPlayer.delegate = self;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
if (error)
{
NSLog(#"Error: %#",
[error localizedDescription]);
}
else
{
[AudioPlayer play];
}
I don't really know what i'm missing, the examples i've followed seem to match what i'm doing.
edit: I should also mention that the code runs without error, there is a try catch around this.
I had a similar problem due to ARC. Instead of defining the AVAudioPlayer in the same method you are using it, you should should have an instance variable somewhere else, such as the UIViewController. This way ARC doesn't auto release this object and audio can play.
I've made some additions and got it work:
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface FirstViewController : UIViewController <AVAudioPlayerDelegate> {
AVAudioPlayer *data;
UIButton *playButton_;
}
#property(nonatomic, retain) IBOutlet UIButton *playButton;
-(IBAction)musicPlayButtonClicked:(id)sender;
#end
#import "ViewController.h"
#implementation FirstViewController
#synthesize playButton=playButton_;
- (IBAction)musicPlayButtonClicked:(id)sender {
NSString *name = [[NSString alloc] initWithFormat:#"09 No Money"];
NSString *source = [[NSBundle mainBundle] pathForResource:name ofType:#"mp3"];
if (data) {
[data stop];
data = nil;
}
data=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath: source] error:NULL];
data.delegate = self;
[data play];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
In Interface Builder I've added a button and connected it with IBOutlet and musicPlayButtonClicked IBAction.
And don't forget to add AVFoundation framework to your project.
ps
I'm really sorry for my english, please, be indulgent.
I had this problem myself, until I found out that the sound was not coming through the speakers (instead - it was redirected to the calls speaker). Try adding this to redirect the sound through the speakers:
UInt32 doChangeDefaultRoute = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
sizeof (doChangeDefaultRoute),
&doChangeDefaultRoute);