Passing data to my custom NSObject? - ios

I have attempted to create my first custom class "AudioPlayer". I want to pass data (the audio title) from a tableview to my "AudioPlayer" and load the AudioPlayer with initWithContentsOfURL:[NSURL fileURLWithPath:path] but when I alloc the "AudioPlayer" in my "MainViewController" i get the error "Incompatible pointer types initializing 'Audio Player*___strong' with and expression of type AVAudioPLayer*". My question is, How would i initialize my custom audio player with the selected audio's title as the URL? It works fine when I created a variable of AVAudioPlayer, but I don't know how to pass it to my custom class.
Here is my custom class Header..
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#interface AudioPlayer : NSObject{
AVAudioPlayer *audioPlayer;
//Volume slider
NSTimer *volumeTimer;
IBOutlet UISlider *volumeSlider;
}
-(bool) isPlaying;
-(bool) isPaused;
-(void)playPause:(id)sender;
#property (nonatomic, retain) AVAudioPlayer *audioPlayer;
#end
Here is my custom class implementation file...
#import "AudioPlayer.h"
#implementation AudioPlayer
#synthesize audioPlayer;
-(void)playPause{
if ([audioPlayer isPlaying]) {
[audioPlayer pause];
} else {
[audioPlayer play];
}
}
-(void)volumeSlider
{
//Setup the volume slider
volumeTimer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:#selector(updateVolumeSlider) userInfo:nil repeats:YES];
[audioPlayer setVolume:volumeSlider.value];
}
#end
Here is the MainView implementation...
- (void)viewDidLoad
{
[super viewDidLoad];
//Instantiate performanceArray
performanceArray = [[NSMutableArray alloc]initWithObjects:#"Centering", nil];
//Instantiate recoveryArray
recoveryArray = [[NSMutableArray alloc]initWithObjects:#"Power Nap", nil];
//Instantiate the AudioPlayer
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
NSString *path = [[NSBundle mainBundle] pathForResource:cell.textLabel.text ofType:#"m4a"];
AudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[audioPlayer.audioPlayer prepareToPlay];
}

I think you are confusing your custom class with AVAudioPlayer class.
If you are trying to add more methods and options to the default class of AVAudioPlayer, you should subclass AVAudioPlayer rather than NSObject.
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#interface AudioPlayer : AVAudioPlayer
// the rest of your code
and then as deanandreakis answered, you need to alloc/init your class rather than AVAudioPlayer.
meaning:
AudioPlayer *audioPlayer = [[AudioPlayer alloc] init];
Or you can use categories to add your custom methods added to AVAudioPlayer.

Your AudioPlayer object that you created is not of type AVAudioPlayer so I think the following line:
AudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
should be something like : AudioPlayer *audioPlayer = [[AudioPlayer alloc] init];
which would create an object of your custom class. You have at least a couple of options to then pass the NSURL information such as adding params to your custom classes init method or creating another property in your custom class that you set just after you create your object.
In your custom class AudioPlayer you could add a new my URL attribute:
#interface AudioPlayer : NSObject{
AVAudioPlayer *audioPlayer;
//Volume slider
NSTimer *volumeTimer;
IBOutlet UISlider *volumeSlider;
NSURL* myURL;
}
Then in your implementation file for AudioPlayer add the following init method:
-(id)initWithURL:(NSURL)theURL
{
self = [super init];
if (self) {
// perform initialization of object here
myURL = theURL;
}
return self;
}
And then in your MainView you could do something like:
NSURL* theURL = [NSURL fileURLWithPath:path];
AudioPlayer *audioPlayer = [[AudioPlayer alloc] initWithURL:theURL];

Related

How to play .caf audio file from server url in ios

I try to play audio from server url but nothing play, But i try to play audio from document directory path url and it play fine.
NSData *songData=[NSData dataWithContentsOfURL:[NSURL URLWithString:
[NSString stringWithFormat:#"%#",aSongURL]]];
AVAudioPlayer *abc = [[AVAudioPlayer alloc] initWithData:songData error:nil];
abc.numberOfLoops=0;
[abc prepareToPlay];
[abc play];
You can try this. Hope it helps.
AVPlayer *objAVPlayer = [[AVPlayer alloc] initWithURL:url];
[objAVPlayer play];
My answer is below
ViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface ViewController : UIViewController
#property (nonatomic,strong)AVAudioPlayer *player;
- (IBAction)actionPlayAudio:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize player;
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)actionPlayAudio:(id)sender {
NSString *strAudioFileURL = #"dev.epixelsoft.co/love_app/audio/img_14957068361.caf";
NSURL *soundFileURL = [NSURL fileURLWithPath:strAudioFileURL];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
[player play];
}

How can I keep background music playing when switching ViewControllers?

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];

playing a mp3 file in iOS app [duplicate]

This question already has answers here:
How do I programmatically play an MP3 on an iPhone?
(4 answers)
Closed 4 years ago.
I can't figure out how to play a music file in an iPhone game.
Im creating a Game and I am trying to figure out how to play music whenever the app is launched.
I tried this:
- (void)awakeFromNib {
NSString *path = [[NSBundle mainBundle] pathForResource:#"musicamenu" ofType:#"mp3"];
AVAudioPlayer *theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
[theAudio play];
}
This is how you do it. In your v1AppDelegate.h file add
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#interface v1AppDelegate : UIResponder <UIApplicationDelegate>
{
AVAudioPlayer *myAudioPlayer;
}
#property (nonatomic, retain) AVAudioPlayer *myAudioPlayer;
#property (strong, nonatomic) UIWindow *window;
#end
Now in your v1AppDelegate.m file add this
#import "v1AppDelegate.h"
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#implementation v1AppDelegate
#synthesize window = _window;
#synthesize myAudioPlayer;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//start a background sound
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"Soothing_Music2_Long" ofType: #"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath ];
myAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
myAudioPlayer.numberOfLoops = -1; //infinite loop
[myAudioPlayer play];
// Override point for customization after application launch.
return YES;
}
If you wish to stop or start this music from anywhere else in your code then simply add this
#import "v1AppDelegate.h"
- (IBAction)stopMusic
{
v1AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate.myAudioPlayer stop];
}
- (IBAction)startMusic
{
v1AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate.myAudioPlayer play];
}
I recommend to add the play music method in applicationDidBecomeActive: method. Because you want the music played every time the app is launched. Note you should hold a reference to the player. Else the music will not be played.
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Play music on another queue so that the main queue is not blocked.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self playMusic];
});
}
- (void)playMusic
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"done" ofType:#"mp3"];
NSError *error = nil;
NSURL *url = [NSURL fileURLWithPath:path];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
[self.player play];
}
For Swift 3.1 :
Use this two imports :
import AVFoundation
import AudioToolbox
Create a reference for your AVAudioPlayer :
private var mAudioPlayer : AVAudioPlayer?
Use this function for play a sound you are storing in your app :
func onTapSound(){
let soundFile = Bundle.main.path(forResource: "slap_placeholder.wav", ofType: nil)
let url = URL(fileURLWithPath: soundFile!)
self.mAudioPlayer = try! AVAudioPlayer(contentsOf: url as URL)
self.mAudioPlayer?.play()
}

AVAudioPlayer not playing my mp3

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);

AVAudioPlayer delegate wont get called in a class method?

i am using the AVAudioPlayer and setting its delegate but its delegate is not getting called
+ (void) playflip
{
NSString *path;
path = [[NSBundle mainBundle] pathForResource:#"flip" ofType:#"mp3"];
AVAudioPlayer *flip;
flip = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:Nil];
flip.delegate = self;
[flip play];
}
My class where i am implementing is the sound class
#interface SoundClass : NSObject <AVAudioPlayerDelegate>
I am calling this delegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
NSLog(#"delegate called");
[player release];
player = nil;
}
It looks like maybe your flip object is going out of scope, because the rest of your code looks fine. Here's what I do:
// controller.h
#interface SoundClass : NSObject <AVAudioPlayerDelegate> {}
// #property(nonatomic,retain) NSMutableDictionary *sounds;
// I have lots of sounds, pre-loaded in a dictionary so that I can reference by name
// With one player, you can just use:
#property(nonatomic,retain) AVAudioPlayer *player;
Then allocate and load the sound in your .m
player = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:Nil];
[player prepareToPlay];
player.delegate = self;
[player play];
Now you should get your DidFinishPlaying notification.

Resources