UIButton is dead after I change views and switch back - iphone

So I created a program where a sound occurs when the device is shaken. Theres a button, that when tapped stops the sound from being played at any time (This is the "reset" method). There's another button, that when pushed displays another view (This is the "infoView" method). The problem occurs when I go the "infoView" then go back to the first view. The sound still play when the device is shaken but the "reset" button becomes unresponsive. Here's what I have so far, any help would be appreciated.
PS. I'm wondering if it has anything to do with FirstResponders? I'm still trying to wrap my head around FirstResponders.
The .h
#import <UIKit/UIKit.h>
#import "AVfoundation/AVfoundation.h"
#interface OldTvViewController : UIViewController{
AVAudioPlayer *audioPlayer;
}
-(IBAction)reset;
-(IBAction)infoView:(id)sender;
#end
the .m
#import "OldTvViewController.h"
#import "AudioToolBox/AudioToolBox.h"
#import "infoViewController.h"
#implementation OldTvViewController
-(IBAction)infoView:(id)sender{
infoViewController *second = [[infoViewController alloc] initWithNibName:Nil bundle:Nil];
[self presentModalViewController:second animated:YES];
[second release];
}
-(BOOL) canBecomeFirstResponder{
return YES;
}
-(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{
if (event.subtype == UIEventSubtypeMotionShake) {
//Play throw sound
if(audioPlayer.playing){
[audioPlayer stop];
} else{
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/bomb.mp3",[[NSBundle mainBundle] resourcePath]]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.numberOfLoops = 0;
[audioPlayer play];
}
}
}
-(IBAction)reset{
[audioPlayer stop];
}
-(void)viewDidAppear:(BOOL)animated{
[self becomeFirstResponder];
[super viewDidAppear:animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
#end

when You go to info view then where your all button available in that class you try this code.
-(void)viewWillDisapeers
{
[audioPlayer stop];
}
or add in this method
-(IBAction)infoView:(id)sender
{
infoViewController *second = [[infoViewController alloc] initWithNibName:Nil bundle:Nil];
[self presentModalViewController:second animated:YES];
[audioPlayer stop];
[second release];
}

Related

App crashing on playing a sound on button click method

I used uibuttons to create a grid view, now need to select and deselect the button on its click.
All is working fine but when I try to play a sound on a button click, app get crashed by printing the below message in console:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIButton prepareToPlay]: unrecognized selector sent to instance 0x7526a20'
To play the sound,I have taken the object of AVAudioPlayer claas in .h file and initializing it in view did load method and playing it on button click, here is my code
.h file
#import <UIKit/UIKit.h>
#import <AVFoundation/AVAudioPlayer.h>
#import <AudioUnit/AudioUnit.h>
#interface PlayViewController : UIViewController<AVAudioPlayerDelegate>
{
IBOutlet UIButton *resetBtn;
UIButton *btn[25];
AVAudioPlayer *tapSound;
}
-(IBAction)reserBtnClkd;
#property(nonatomic,retain) AVAudioPlayer *tapSound;
#end
in .m file
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *path=[[NSBundle mainBundle] pathForResource:#"button-3" ofType:#"wav"];
AVAudioPlayer *Tapsound=[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
self.tapSound=Tapsound;
[Tapsound release];
[pool release];
[self setTheIcons];
resetBtn.layer.cornerRadius=6.0;
resetBtn.backgroundColor=[UIColor colorWithRed:90/255.00 green:33.00/255.00 blue:179.00/255.00 alpha:1];
resetBtn.titleLabel.font=[UIFont fontWithName:#"Helvetica" size:22];
[resetBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
}
#pragma mark
#pragma mark<Creating The Grid View Of Icons>
#pragma mark
-(void) setTheIcons
{
int x=11;
int y=55;
for(int i=1;i<=25;i++)
{
btn[i]=[UIButton buttonWithType:UIButtonTypeCustom];
btn[i].frame=CGRectMake(x, y, 58,58);
[btn[i] addTarget:self action:#selector(btnClkd:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn[i]];
if(i%5==0)
{
x=11;
y=y+60;
}
else
{
x=x+60;
}
}
[self reserBtnClkd];
}
-(void)btnClkd:(UIButton*)sender
{
sender.selected=!sender.selected;
if(sender.selected)
{
// UIView *tempView=[[UIView alloc]initWithFrame:CGRectMake(12, 12, 34, 34)];
UIView *tempView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 58, 58)];
tempView.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"hover-effectNew.png"]];
tempView.userInteractionEnabled=NO;
[sender addSubview:tempView];
[tempView release];
}
else
{
NSArray *subviewToRemove=[sender subviews];
int i=1;
for(UIView *view in subviewToRemove)
{
if(i==2)
{
[view removeFromSuperview];
}
i++;
}
}
[self.tapSound prepareToPlay];
[self.tapSound setDelegate:self];
[self.tapSound play];
}
And the strange thing is that App crashed only when I play the sound on button click method, otherwise if I play it in view did load then it works without any issue, Scratching my head for two days but could not find any solution, please help me
I think that the problem is that your self.tapSound is an UIButton(you can see it in the crash log: '-[UIButton prepareToPlay]: unrecognized selector sent to instance 0x7526a20'.
Try debugging it step by step and see what happens
I think because self.tapSoundis referencing Tapsound, when you call [Tapsound release] it releases the property as well. I would recommend instantiating the property directly, like this:
/*note that you have declared tapSound in your .h
as a class variable in addition to being a property.
This means you can access it as both.
Wherever you would type self.tapSound, instead use simply tapSound
*/
tapSound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];

Can avplayer play music from mpmusicplayercontroller

is this possible AVPlayer fetch music from ipodlibrary from MPMusicPlayerController and play ,since avplayer cannot access iPodMusicPlayer from MPMusicPlayerController , since AVPlayer support background playing and access to remoteEvents.
The code shown below is from addMusic project. so any help would be appreciated .Thank you
void audioRouteChangeListenerCallback (
void *inUserData,
AudioSessionPropertyID inPropertyID,
UInt32 inPropertyValueSize,
const void *inPropertyValue
) {
// ensure that this callback was invoked for a route change
if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return;
// This callback, being outside the implementation block, needs a reference to the
// MainViewController object, which it receives in the inUserData parameter.
// You provide this reference when registering this callback (see the call to
// AudioSessionAddPropertyListener).
MainViewController *controller = (MainViewController *) inUserData;
// if application sound is not playing, there's nothing to do, so return.
if (controller.appSoundPlayer.playing == 0 ) {
NSLog (#"Audio route change while application audio is stopped.");
return;
} else {
// Determines the reason for the route change, to ensure that it is not
// because of a category change.
CFDictionaryRef routeChangeDictionary = inPropertyValue;
CFNumberRef routeChangeReasonRef =
CFDictionaryGetValue (
routeChangeDictionary,
CFSTR (kAudioSession_AudioRouteChangeKey_Reason)
);
SInt32 routeChangeReason;
CFNumberGetValue (
routeChangeReasonRef,
kCFNumberSInt32Type,
&routeChangeReason
);
// "Old device unavailable" indicates that a headset was unplugged, or that the
// device was removed from a dock connector that supports audio output. This is
// the recommended test for when to pause audio.
if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) {
[controller.appSoundPlayer pause];
NSLog (#"Output device removed, so application audio was paused.");
UIAlertView *routeChangeAlertView =
[[UIAlertView alloc] initWithTitle: NSLocalizedString (#"Playback Paused", #"Title for audio hardware route-changed alert view")
message: NSLocalizedString (#"Audio output was changed", #"Explanation for route-changed alert view")
delegate: controller
cancelButtonTitle: NSLocalizedString (#"StopPlaybackAfterRouteChange", #"Stop button title")
otherButtonTitles: NSLocalizedString (#"ResumePlaybackAfterRouteChange", #"Play button title"), nil];
[routeChangeAlertView show];
// release takes place in alertView:clickedButtonAtIndex: method
} else {
NSLog (#"A route change occurred that does not require pausing of application audio.");
}
}
}
#implementation MainViewController
#synthesize artworkItem;
#synthesize userMediaItemCollection;
#synthesize playBarButton;
#synthesize pauseBarButton;
#synthesize musicPlayer;
#synthesize navigationBar;
#synthesize noArtworkImage; item has no associated artwork
#synthesize backgroundColorTimer;
#synthesize nowPlayingLabel;
#synthesize appSoundButton;
#synthesize addOrShowMusicButton;
#synthesize appSoundPlayer;
#synthesize soundFileURL;
#synthesize interruptedOnPlayback;
#synthesize playedMusicOnce;
#synthesize playing;
#implementation MainViewController
#synthesize artworkItem; // the now-playing media item's artwork image, displayed in the Navigation bar
#synthesize userMediaItemCollection; // the media item collection created by the user, using the media item picker
#synthesize playBarButton; // the button for invoking Play on the music player
#synthesize pauseBarButton; // the button for invoking Pause on the music player
#synthesize musicPlayer; // the music player, which plays media items from the iPod library
#synthesize navigationBar; // the application's Navigation bar
#synthesize noArtworkImage; // an image to display when a media item has no associated artwork
#synthesize backgroundColorTimer; // a timer for changing the background color -- represents an application that is
// doing something else while iPod music is playing
#synthesize nowPlayingLabel; // descriptive text shown on the main screen about the now-playing media item
#synthesize appSoundButton; // the button to invoke playback for the application sound
#synthesize addOrShowMusicButton; // the button for invoking the media item picker. if the user has already
// specified a media item collection, the title changes to "Show Music" and
// the button invokes a table view that shows the specified collection
#synthesize appSoundPlayer; // An AVAudioPlayer object for playing application sound
#synthesize soundFileURL; // The path to the application sound
#synthesize interruptedOnPlayback; // A flag indicating whether or not the application was interrupted during
// application audio playback
#synthesize playedMusicOnce; // A flag indicating if the user has played iPod library music at least one time
// since application launch.
#synthesize playing; // An application that responds to interruptions must keep track of its playing/
// not-playing state.
#pragma mark Music control
- (IBAction) AddMusicOrShowMusic: (id) sender {
// if the user has already chosen some music, display that list
if (userMediaItemCollection) {
MusicTableViewController *controller = [[MusicTableViewController alloc] initWithNibName: #"MusicTableView" bundle: nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController: controller animated: YES];
[controller release];
} else {
MPMediaPickerController *picker =
[[MPMediaPickerController alloc] initWithMediaTypes: MPMediaTypeMusic];
picker.delegate = self;
picker.allowsPickingMultipleItems = YES;
picker.prompt = NSLocalizedString (#"Add songs to play", "Prompt in media item picker");
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleDefault animated: YES];
[self presentModalViewController: picker animated: YES];
[picker release];
}
}
- (void) updatePlayerQueueWithMediaCollection: (MPMediaItemCollection *) mediaItemCollection {
// Configure the music player, but only if the user chose at least one song to play
if (mediaItemCollection) {
if (userMediaItemCollection == nil) {
[self setUserMediaItemCollection: mediaItemCollection];
[musicPlayer setQueueWithItemCollection: userMediaItemCollection];
[self setPlayedMusicOnce: YES];
[musicPlayer play];
} else {
BOOL wasPlaying = NO;
if (musicPlayer.playbackState == MPMusicPlaybackStatePlaying) {
wasPlaying = YES;
}
MPMediaItem *nowPlayingItem = musicPlayer.nowPlayingItem;
NSTimeInterval currentPlaybackTime = musicPlayer.currentPlaybackTime;
NSMutableArray *combinedMediaItems = [[userMediaItemCollection items] mutableCopy];
NSArray *newMediaItems = [mediaItemCollection items];
[combinedMediaItems addObjectsFromArray: newMediaItems];
[self setUserMediaItemCollection: [MPMediaItemCollection collectionWithItems: (NSArray *) combinedMediaItems]];
[combinedMediaItems release];
[musicPlayer setQueueWithItemCollection: userMediaItemCollection];
musicPlayer.nowPlayingItem = nowPlayingItem;
musicPlayer.currentPlaybackTime = currentPlaybackTime;
if (wasPlaying) {
[musicPlayer play];
}
}
navigationBar.topItem.leftBarButtonItem.enabled = YES;
[addOrShowMusicButton setTitle: NSLocalizedString (#"Show Music", #"Alternate title for 'Add Music' button, after user has chosen some music")
forState: UIControlStateNormal];
}
}
- (void) restorePlaybackState {
if (musicPlayer.playbackState == MPMusicPlaybackStateStopped && userMediaItemCollection) {
[addOrShowMusicButton setTitle: NSLocalizedString (#"Show Music", #"Alternate title for 'Add Music' button, after user has chosen some music")
forState: UIControlStateNormal];
if (playedMusicOnce == NO) {
[self setPlayedMusicOnce: YES];
[musicPlayer play];
}
}
}
#pragma mark Media item picker delegate methods________
- (void) mediaPicker: (MPMediaPickerController *) mediaPicker didPickMediaItems: (MPMediaItemCollection *) mediaItemCollection {
[self dismissModalViewControllerAnimated: YES];
[self updatePlayerQueueWithMediaCollection: mediaItemCollection];
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque animated: YES];
}
- (void) mediaPickerDidCancel: (MPMediaPickerController *) mediaPicker {
[self dismissModalViewControllerAnimated: YES];
[[UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleBlackOpaque animated: YES];
}
#pragma mark Music notification handlers__________________
- (void) handle_NowPlayingItemChanged: (id) notification {
MPMediaItem *currentItem = [musicPlayer nowPlayingItem];
UIImage *artworkImage = noArtworkImage;
MPMediaItemArtwork *artwork = [currentItem valueForProperty: MPMediaItemPropertyArtwork];
// Obtain a UIImage object from the MPMediaItemArtwork object
if (artwork) {
artworkImage = [artwork imageWithSize: CGSizeMake (30, 30)];
}
// Obtain a UIButton object and set its background to the UIImage object
UIButton *artworkView = [[UIButton alloc] initWithFrame: CGRectMake (0, 0, 30, 30)];
[artworkView setBackgroundImage: artworkImage forState: UIControlStateNormal];
// Obtain a UIBarButtonItem object and initialize it with the UIButton object
UIBarButtonItem *newArtworkItem = [[UIBarButtonItem alloc] initWithCustomView: artworkView];
[self setArtworkItem: newArtworkItem];
[newArtworkItem release];
[artworkItem setEnabled: NO];
[navigationBar.topItem setRightBarButtonItem: artworkItem animated: YES];
[nowPlayingLabel setText: [
NSString stringWithFormat: #"%# %# %# %#",
NSLocalizedString (#"Now Playing:", #"Label for introducing the now-playing song title and artist"),
[currentItem valueForProperty: MPMediaItemPropertyTitle],
NSLocalizedString (#"by", #"Article between song name and artist name"),
[currentItem valueForProperty: MPMediaItemPropertyArtist]]];
if (musicPlayer.playbackState == MPMusicPlaybackStateStopped) {
[nowPlayingLabel setText: [
NSString stringWithFormat: #"%#",
NSLocalizedString (#"Music-ended Instructions", #"Label for prompting user to play music again after it has stopped")]];
}
}
- (void) handle_PlaybackStateChanged: (id) notification {
MPMusicPlaybackState playbackState = [musicPlayer playbackState];
if (playbackState == MPMusicPlaybackStatePaused) {
navigationBar.topItem.leftBarButtonItem = playBarButton;
} else if (playbackState == MPMusicPlaybackStatePlaying) {
navigationBar.topItem.leftBarButtonItem = pauseBarButton;
} else if (playbackState == MPMusicPlaybackStateStopped) {
navigationBar.topItem.leftBarButtonItem = playBarButton;
// Even though stopped, invoking 'stop' ensures that the music player will play
// its queue from the start.
[musicPlayer stop];
}
}
- (void) handle_iPodLibraryChanged: (id) notification {
]
}
#pragma mark Application playback control_________________
- (IBAction) playAppSound: (id) sender {
[appSoundPlayer play];
playing = YES;
[appSoundButton setEnabled: NO];
}
- (void) alertView: routeChangeAlertView clickedButtonAtIndex: buttonIndex {
if ((NSInteger) buttonIndex == 1) {
[appSoundPlayer play];
} else {
[appSoundPlayer setCurrentTime: 0];
[appSoundButton setEnabled: YES];
}
[routeChangeAlertView release];
}
#pragma mark AV Foundation delegate methods____________
- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) appSoundPlayer successfully: (BOOL) flag {
playing = NO;
[appSoundButton setEnabled: YES];
}
- (void) audioPlayerBeginInterruption: player {
NSLog (#"Interrupted. The system has paused audio playback.");
if (playing) {
playing = NO;
interruptedOnPlayback = YES;
}
}
- (void) audioPlayerEndInterruption: player {
NSLog (#"Interruption ended. Resuming audio playback.");
[[AVAudioSession sharedInstance] setActive: YES error: nil];
if (interruptedOnPlayback) {
[appSoundPlayer prepareToPlay];
[appSoundPlayer play];
playing = YES;
interruptedOnPlayback = NO;
}
}
#pragma mark Table view delegate methods
- (void) musicTableViewControllerDidFinish: (MusicTableViewController *) controller {
[self dismissModalViewControllerAnimated: YES];
[self restorePlaybackState];
}
#pragma mark Application setup
- (void) setupApplicationAudio {
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: #"sound"
ofType: #"caf"];
NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
self.soundFileURL = newURL;
[newURL release];
[[AVAudioSession sharedInstance] setDelegate: self];
// [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil];
UInt32 doSetProperty = 0;
AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryMixWithOthers,
sizeof (doSetProperty),
&doSetProperty
);
// Registers the audio route change listener callback function
AudioSessionAddPropertyListener (
kAudioSessionProperty_AudioRouteChange,
audioRouteChangeListenerCallback,
self
);
// Activates the audio session.
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive: YES error: &activationError];
// Instantiates the AVAudioPlayer object, initializing it with the sound
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil];
self.appSoundPlayer = newPlayer;
[newPlayer release];
[appSoundPlayer prepareToPlay];
[appSoundPlayer setVolume: 1.0];
[appSoundPlayer setDelegate: self];
}
- (void) registerForMediaPlayerNotifications {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver: self
selector: #selector (handle_NowPlayingItemChanged:)
name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification
object: musicPlayer];
[notificationCenter addObserver: self
selector: #selector (handle_PlaybackStateChanged:)
name: MPMusicPlayerControllerPlaybackStateDidChangeNotification
object: musicPlayer];
[musicPlayer beginGeneratingPlaybackNotifications];
}
- (BOOL) useiPodPlayer {
if ([[NSUserDefaults standardUserDefaults] boolForKey: PLAYER_TYPE_PREF_KEY]) {
return YES;
} else {
return NO;
}
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
}
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void) remoteControlReceivedWithEvent: (UIEvent *) receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
switch (receivedEvent.subtype) {
case UIEventSubtypeRemoteControlTogglePlayPause:
[self togglePlayPause];
break;
case UIEventSubtypeRemoteControlPlay:
[self playAudio];
break;
case UIEventSubtypeRemoteControlPause:
[self pauseAudio];
break;
default:
break;
}
}
}
- (IBAction) playOrPauseMusic: (id)sender {
[self togglePlayPause];
}
- (void)playAudio {
[musicPlayer play];
}
- (void)pauseAudio {
[musicPlayer pause];
}
- (void)togglePlayPause {
MPMusicPlaybackState playbackState = [musicPlayer playbackState];
if (playbackState == MPMusicPlaybackStateStopped || playbackState == MPMusicPlaybackStatePaused) {
[musicPlayer play];
} else if (playbackState == MPMusicPlaybackStatePlaying) {
[musicPlayer pause];
}
}
// Configure the application.
- (void) viewDidLoad {
[super viewDidLoad];
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self setupApplicationAudio];
[self setPlayedMusicOnce: NO];
[self setNoArtworkImage: [UIImage imageNamed: #"no_artwork.png"]];
[self setPlayBarButton: [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemPlay
target: self
action: #selector (playOrPauseMusic:)]];
[self setPauseBarButton: [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemPause
target: self
action: #selector (playOrPauseMusic:)]];
[addOrShowMusicButton setTitle: NSLocalizedString (#"Add Music", #"Title for 'Add Music' button, before user has chosen some music")
forState: UIControlStateNormal];
[appSoundButton setTitle: NSLocalizedString (#"Play App Sound", #"Title for 'Play App Sound' button")
forState: UIControlStateNormal];
[nowPlayingLabel setText: NSLocalizedString (#"Instructions", #"Brief instructions to user, shown at launch")];
if ([self useiPodPlayer]) {
[self setMusicPlayer: [MPMusicPlayerController iPodMusicPlayer]];
if ([musicPlayer nowPlayingItem]) {
navigationBar.topItem.leftBarButtonItem.enabled = YES;
[self handle_NowPlayingItemChanged: nil];
if ([musicPlayer playbackState] == MPMusicPlaybackStatePaused) {
navigationBar.topItem.leftBarButtonItem = playBarButton;
}
}
} else {
[self setMusicPlayer: [MPMusicPlayerController applicationMusicPlayer]];
[musicPlayer setShuffleMode: MPMusicShuffleModeOff];
[musicPlayer setRepeatMode: MPMusicRepeatModeNone];
}
[self registerForMediaPlayerNotifications];
[self setBackgroundColorTimer: [NSTimer scheduledTimerWithTimeInterval: 3.5
target: self
selector: #selector (updateBackgroundColor)
userInfo: nil
repeats: YES]];
}
// Invoked by the backgroundColorTimer.
- (void) updateBackgroundColor {
[UIView beginAnimations: nil context: nil];
[UIView setAnimationDuration: 3.0];
CGFloat redLevel = rand() / (float) RAND_MAX;
CGFloat greenLevel = rand() / (float) RAND_MAX;
CGFloat blueLevel = rand() / (float) RAND_MAX;
self.view.backgroundColor = [UIColor colorWithRed: redLevel
green: greenLevel
blue: blueLevel
alpha: 1.0];
[UIView commitAnimations];
}
#pragma mark Application state management_____________
- (void) didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void) viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver: self
name: MPMusicPlayerControllerNowPlayingItemDidChangeNotification
object: musicPlayer];
[[NSNotificationCenter defaultCenter] removeObserver: self
name: MPMusicPlayerControllerPlaybackStateDidChangeNotification
object: musicPlayer];
[musicPlayer endGeneratingPlaybackNotifications];
[musicPlayer release];
[artworkItem release];
[backgroundColorTimer invalidate];
[backgroundColorTimer release];
[navigationBar release];
[noArtworkImage release];
[nowPlayingLabel release];
[pauseBarButton release];
[playBarButton release];
[soundFileURL release];
[userMediaItemCollection release];
[super dealloc];
}
#end
These four lines should get you started :)
MPMediaItem *nowPlayingItem = musicPlayer.nowPlayingItem;
NSURL * mediaURL = [nowPlayingItem valueForProperty:MPMediaItemPropertyAssetURL];
AVPlayerItem * myAVPlayerItem = [AVPlayerItem playerItemWithURL:mediaURL];
AVPlayer * myAvPlayer = [AVPlayer playerWithPlayerItem:myAVPlayerItem];

iOS SDK : playing music on the background and switching views

I am trying to play music in my application. The music works fine but after switching viewControllers and returning to the main menu, my music plays again! It means several identical sounds play together! How can I solve this? Here is my code :
- (void)viewDidLoad {
NSString *music = [[NSBundle mainBundle] pathForResource:#"1music" ofType:#"mp3"];
myMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:music] error:NULL];
myMusic.delegate = self;
myMusic.numberOfLoops = -1;
[myMusic play];
}
- (IBAction) scoreView {
ScoreViewController *scoreView = [[ScoreViewController alloc] initWithNibName:#"ScoreViewController" bundle:nil];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
[self.view addSubview: scoreView.view];
[UIView commitAnimations];
}
EDITED CODE :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
NSString * musicSonati = [[NSBundle mainBundle] pathForResource:#"music" ofType:#"mp3"];
myMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicSonati] error:NULL];
myMusic.delegate = self;
myMusic.numberOfLoops = -1;
[myMusic play];
}
return self;
}
//toggle button
- (IBAction)MusicPlaying:(id)sender {
if ((isPlay = !isPlay))
{
UIImage *buttonImageNormal = [UIImage imageNamed:#"play.png"];
UIImage *stretchableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:0 topCapHeight:0];
[MusicButton setBackgroundImage:stretchableButtonImageNormal forState:UIControlStateNormal];
[myMusic pause];
}else {
UIImage *buttonImageNormal = [UIImage imageNamed:#"pause.png"];
UIImage *stretchableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:0 topCapHeight:0];
[MusicButton setBackgroundImage:stretchableButtonImageNormal forState:UIControlStateNormal];
NSLog(#"Music play");
[myMusic play];
}
}
If you have audio to play on multiple places then one simple way to achieve this is declare AVAudioPlayer instance in delegate with property synthesized.If you want to play this anywhere do this:-
MyAppDelegate *app_delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
if(app_delegate.audioPlayer)
{
[app_delegate.audioPlayer release];
app_delegate.audioPlayer = nil;
}
app_delegate.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
and if you want to stop sound do this:-
if(app_delegate.audioPlayer)
{
if([app_delegate.audioPlayer isPlaying])
{
[app_delegate.audioPlayer stop];
[app_delegate.audioPlayer setCurrentTime:0];
}
}
and to play new sound file release and nil same player if already allocated or alloc it again with new sound file url.
Make sure myMusic is correctly declared as a retained property and synthesized then try something like this:
-(void) commonInit {
NSString * musicSonati = [[NSBundle mainBundle] pathForResource:#"music" ofType:#"mp3"];
self.myMusic = [[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicSonati] error:NULL] autorelease];
self.myMusic.delegate = self;
self.myMusic.numberOfLoops = -1;
//You probably don't want to play music on init, rather defer to viewDidLoad.
// [self.myMusic play];
}
- (id)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self commonInit];
}
return self;
}
- (id)init {
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
[self commonInit];
}
return self;
}
Then try this in your viewDidLoad:
- (void)viewDidLoad {
...
if (!self.myMusic.playing) {
[self.myMusic play];
}
...
}
Also, don't forget to release your player in dealloc!
First, viewDidLoad probably isn't a good place to be initializing your AVAudioPlayer, as the system may need to unload some of your components to reclaim memory (in viewDidUnload). You should probably be creating the AVAudioPlayer in your init method or similar.
So what's happening is you end up creating a second AVAudioPlayer when the focus comes back to your application, and you're actually losing the reference to your first one. (Thus, also leaking memory.)
If you want to start playing music when the view loads, you should additionally check its status before doing so:
- (void)viewDidLoad {
...
if (!myMusic.playing) {
[myMusic play];
}
...
}
Its seems you are developing game (from your function name After viewLoad (ScoreView). ;) )
Well, According to me, AvAudioplayer is not Good Option if you want to implement with Game.
Use cocosdenshion, Download the latest cocos2d folder, find the these 9 files, put it in your resource folder,
And You are done.. !!!
#import "SimpleAudioEngine.h" // wherever you want to call in head part of the file.
Step1 call short file.!
[[SimpleAudioEngine sharedEngine] playEffect:#"blast.mp3"];
step2 call background loop.
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:#"background.mp3" loop:YES];
NOTE: There are list of available function http://www.cocos2d-iphone.org/api-ref/0.99.5/interface_simple_audio_engine.html , Its very easy and simple !
Whole implementation will take, 20 minutes max !
Initialize your player in app delegate file and play your background music. Only set one variable in app delegate which checks music play true or false...and enjoy your app without restarting music......
In your code you initialize you player in view did load and init method... that's why you music restart.....just call it only once in app delegate applicationdidfinshLaunching() method....

Dismiss MPMoviePlayerController on screen touch

I followed this tutorial, and included a video player in my app.
But the problem is that i want to hide the controls, and be able to dismiss the video on screen touch.
I tried putting a big transparent button in front of the video that triggers the dismiss function, but with no luck. the video will always be over the button and the function will never be called.
Is there another way of doing it?
ty
**Hi I think AVPlayer is become more suitable to you,You can use it as below and then add subview if you want to play and if you want to stop remove it from super view
** #import"AVFoundation/AVFoundation.h"
**For creating Player List:
NSString *path1 = [[NSBundle mainBundle] pathForResource:#"hello" ofType:#"mp4"];
AVPlayerItem *first = [AVPlayerItem playerItemWithURL:[NSURL fileURLWithPath:path1]];
player= [AVPlayer playerWithPlayerItem:first];
[self.playerView setPlayer:player];
[player play];
** You have to make uiview for playerview in it :
(id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];
if (self) {
// Initialization code.
}
return self;
}
+ (Class)layerClass {
return [AVPlayerLayer class];
}
-(AVPlayer*)player {
return [(AVPlayerLayer *)[self layer] player];
}
-(void)setPlayer:(AVPlayer *)player {
[(AVPlayerLayer *)[self layer] setPlayer:player];
}
PlayerViewControll .H
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface PlayerView : UIView UILabel *pageNumberLabel;
int pageNumber;
}
#property (nonatomic, retain) AVPlayer *player;
- (id)initWithPageNumber:(int)page;
PlayerView .M
#import "PlayerView.h"
#implementation PlayerView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {}
return self;
}
+ (Class)layerClass {
return [AVPlayerLayer class];
}
- (AVPlayer*)player {
return [(AVPlayerLayer *)[self layer] player];
}
- (void)setPlayer:(AVPlayer *)player {
[(AVPlayerLayer *)[self layer] setPlayer:player];
}
MainViewControll .H
#import <AVFoundation/AVFoundation.h>
#import "PlayerView.h"
#interface MainViewController : UIViewController {
IBOutlet PlayerView *playerView;
NSString *url;
AVPlayer *player;
NSMutableArray *arrIteam;
}
#property(nonatomic,retain) NSMutableArray *arrIteam;
#property (nonatomic, retain) AVPlayer *player;
#property(nonatomic ,retain)IBOutlet PlayerView *playerView;
PlayerView.M
#import "MainViewController.h"
#import <QuartzCore/QuartzCore.h>
#implementation MainViewController
#synthesize player,playerView,arrIteam;
- (void)viewDidLoad {
NSString *path1 = [[NSBundle mainBundle] pathForResource:#"hello" ofType:#"mp4"];
AVPlayerItem *first = [AVPlayerItem playerItemWithURL:[NSURL fileURLWithPath:path1]];
arrIteam = [[NSMutableArray alloc] initWithObjects:first,second, third,fourth,nil];
player=[AVPlayer playerWithPlayerItem:[arrIteam objectAtIndex:i]];
[self.playerView setPlayer:player];
[player play];
[super viewDidLoad];
}
You should use UIGestureRecognizer class. See manual for details. Or read this tutorial.
Use this code.
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(stopPlayer)];
[self.view addGestureRecognizer:gestureRecognizer];
gestureRecognizer.cancelsTouchesInView = NO;
[gestureRecognizer release];
in view didload;
And in
- (void) stopPlayer
stop the player and release this player from view.
Hope it helps you.
i just found the solution to my problem in another question asked here. after some minor modifications, the code worked as expected. thank you all.

Allocation of several sounds

I'm not sure if I wrote this code well (get clicks on touching buttons rapidly):
#import "iEngineRoomAppDelegate.h"
#import "iEngineRoomViewController.h"
#import "SoundEffect.h"
#implementation iEngineRoomAppDelegate
#synthesize window;
#synthesize viewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
[self setupSounds];
}
- (void)setupSounds {
NSBundle *mainBundle = [NSBundle mainBundle];
timbal_big_Sound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:#"timbal_big" ofType:#"caf"]];
timbal_sm_Sound = [[SoundEffect alloc] initWithContentsOfFile:[mainBundle pathForResource:#"timbal_sm" ofType:#"caf"]];
}
- (IBAction)timbal_big: (id)sender {
SoundEffect *currentSoundEffect= timbal_big_Sound;
[currentSoundEffect play];
}
- (IBAction)timbal_sm: (id)sender {
SoundEffect *currentSoundEffect= timbal_sm_Sound;
[currentSoundEffect play];
}
- (void)dealloc {
[timbal_big_Sound release];
[timbal_sm_Sound release];
[viewController release];
[window release];
[super dealloc];
}
#end
Memory management of the SoundEffect objects is right, if you meant that.