I have no idea what the cause of the problem is, the moment it the player tries to play the test audio file it crashes, but only in simulator. On real device it runs fine. I have pasted the code bellow if you want to have a look, including the little debug information it gives me... If I do not find the origin of this crash, will it pass Apple´s QA procedures as long as it runs fine on the device itself?
could possible this isa -> unknown class be the problem?
It crashes on [p play]
in this method:
-(void)startPlaybackForPlayer:(AVAudioPlayer*)p
{
if ([p play])
{
[self updateViewForPlayerState:p];
}
else
NSLog(@"Could not play %@\n", p.url);
}
-
#import "AudioPlayerViewController.h"
@interface AudioPlayerViewController ()
{
//AVAudioPlayer *player;
}
@property (nonatomic,strong) AVAudioPlayer *player;
@end
@implementation AudioPlayerViewController
-(void)updateCurrentTimeForPlayer:(AVAudioPlayer *)p
{
self.currentTime.text = [NSString stringWithFormat:@"%d:%02d", (int)p.currentTime / 60, (int)p.currentTime % 60, nil];
self.progressBar.value = p.currentTime;
}
- (void)updateCurrentTime
{
[self updateCurrentTimeForPlayer:self.player];
}
- (void)updateViewForPlayerState:(AVAudioPlayer *)p
{
[self updateCurrentTimeForPlayer:p];
if (self.updateTimer)
[self.updateTimer invalidate];
if (p.playing)
{
[self.playButton setImage:((p.playing == YES) ? pauseBtnBG : playBtnBG) forState:UIControlStateNormal];
//[lvlMeter_in setPlayer:p];
self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:@selector(updateCurrentTime) userInfo:p repeats:YES];
}
else
{
[self.playButton setImage:((p.playing == YES) ? pauseBtnBG : playBtnBG) forState:UIControlStateNormal];
//[lvlMeter_in setPlayer:nil];
self.updateTimer = nil;
}
}
- (void)updateViewForPlayerStateInBackground:(AVAudioPlayer *)p
{
[self updateCurrentTimeForPlayer:p];
if (p.playing)
{
[self.playButton setImage:((p.playing == YES) ? pauseBtnBG : playBtnBG) forState:UIControlStateNormal];
}
else
{
[self.playButton setImage:((p.playing == YES) ? pauseBtnBG : playBtnBG) forState:UIControlStateNormal];
}
}
-(void)updateViewForPlayerInfo:(AVAudioPlayer*)p
{
self.duration.text = [NSString stringWithFormat:@"%d:%02d", (int)p.duration / 60, (int)p.duration % 60, nil];
self.progressBar.maximumValue = p.duration;
self.volumeSlider.value = p.volume;
}
- (void)rewind
{
//AVAudioPlayer *p = rewTimer.userInfo;
//p.currentTime-= SKIP_TIME;
//[self updateCurrentTimeForPlayer:p];
}
- (void)ffwd
{
//AVAudioPlayer *p = ffwTimer.userInfo;
//p.currentTime+= SKIP_TIME;
//[self updateCurrentTimeForPlayer:p];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"### AudioPlayerViewController Initiallized");
playBtnBG = [UIImage imageNamed:@"play.png"]; // Retain, maybe make strong
pauseBtnBG = [UIImage imageNamed:@"pause.png"];
[self.playButton setImage:playBtnBG forState:UIControlStateNormal];
[self registerForBackgroundNotifications];
self.updateTimer = nil;
//rewTimer = nil;
//ffwTimer = nil;
self.duration.adjustsFontSizeToFitWidth = YES;
self.currentTime.adjustsFontSizeToFitWidth = YES;
self.progressBar.minimumValue = 0.0;
// Load the the sample file, use mono or stero sample
#warning samplefile does not exist
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: [[NSBundle mainBundle] pathForResource:@"bubbles" ofType:@"m4a"]];
//NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: [[NSBundle mainBundle] pathForResource:@"sample2ch" ofType:@"m4a"]];
self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
if (self.player)
{
self.fileName.text = [NSString stringWithFormat: @"%@ (%d ch.)", [[self.player.url relativePath] lastPathComponent], self.player.numberOfChannels, nil];
[self updateViewForPlayerInfo:self.player];
[self updateViewForPlayerState:self.player];
self.player.numberOfLoops = 1;
self.player.delegate = self;
}
OSStatus result = AudioSessionInitialize(NULL, NULL, NULL, NULL);
if (result)
NSLog(@"Error initializing audio session! %ld", result);
[[AVAudioSession sharedInstance] setDelegate: self];
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryError];
if (setCategoryError)
NSLog(@"Error setting category! %@", setCategoryError);
#warning did change here - migth cause bug
//result = AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, RouteChangeListener, (__bridge void *)(self));
if (result)
NSLog(@"Could not add property listener! %ld", result);
/*
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
self.player.delegate = self;
[self.player prepareToPlay];
[self playAudio];
*/
}
-(void)pausePlaybackForPlayer:(AVAudioPlayer*)p
{
[p pause];
[self updateViewForPlayerState:p];
}
-(void)startPlaybackForPlayer:(AVAudioPlayer*)p
{
if ([p play])
{
[self updateViewForPlayerState:p];
}
else
NSLog(@"Could not play %@\n", p.url);
}
- (IBAction)playButtonPressed:(UIButton *)sender
{
if (self.player.playing == YES)
[self pausePlaybackForPlayer: self.player];
else
[self startPlaybackForPlayer: self.player];
}
- (IBAction)rewButtonPressed:(UIButton *)sender
{
/*
if (rewTimer) [rewTimer invalidate];
rewTimer = [NSTimer scheduledTimerWithTimeInterval:SKIP_INTERVAL target:self selector:@selector(rewind) userInfo:player repeats:YES];
*/
}
- (IBAction)rewButtonReleased:(UIButton *)sender
{
/*
if (rewTimer) [rewTimer invalidate];
rewTimer = nil;
*/
}
- (IBAction)ffwButtonPressed:(UIButton *)sender
{
/*
if (ffwTimer) [ffwTimer invalidate];
ffwTimer = [NSTimer scheduledTimerWithTimeInterval:SKIP_INTERVAL target:self selector:@selector(ffwd) userInfo:player repeats:YES];
*/
}
- (IBAction)ffwButtonReleased:(UIButton *)sender
{
/*
if (ffwTimer) [ffwTimer invalidate];
ffwTimer = nil;
*/
}
- (IBAction)volumeSliderMoved:(UISlider *)sender
{
self.player.volume = [sender value];
}
- (IBAction)progressSliderMoved:(UISlider *)sender
{
self.player.currentTime = sender.value;
[self updateCurrentTimeForPlayer:self.player];
}
#pragma mark AudioSession handlers
/**
void RouteChangeListener( void * inClientData,
AudioSessionPropertyID inID,
UInt32 inDataSize,
const void * inData)
{
avTouchController* This = (avTouchController*)inClientData;
if (inID == kAudioSessionProperty_AudioRouteChange) {
CFDictionaryRef routeDict = (CFDictionaryRef)inData;
NSNumber* reasonValue = (NSNumber*)CFDictionaryGetValue(routeDict, CFSTR(kAudioSession_AudioRouteChangeKey_Reason));
int reason = [reasonValue intValue];
if (reason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) {
[This pausePlaybackForPlayer:This.player];
}
}
}*/
#pragma mark AVAudioPlayer delegate methods
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)p successfully:(BOOL)flag
{
if (flag == NO)
NSLog(@"Playback finished unsuccessfully");
[p setCurrentTime:0.];
if (self.inBackground)
{
[self updateViewForPlayerStateInBackground:p];
}
else
{
[self updateViewForPlayerState:p];
}
}
- (void)playerDecodeErrorDidOccur:(AVAudioPlayer *)p error:(NSError *)error
{
NSLog(@"ERROR IN DECODE: %@\n", error);
}
// we will only get these notifications if playback was interrupted
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)p
{
NSLog(@"Interruption begin. Updating UI for new state");
// the object has already been paused, we just need to update UI
if (self.inBackground)
{
[self updateViewForPlayerStateInBackground:p];
}
else
{
[self updateViewForPlayerState:p];
}
}
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)p
{
NSLog(@"Interruption ended. Resuming playback");
[self startPlaybackForPlayer:p];
}
#pragma mark background notifications
- (void)registerForBackgroundNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(setInBackgroundFlag)
name:UIApplicationWillResignActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(clearInBackgroundFlag)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
- (void)setInBackgroundFlag
{
self.inBackground = true;
}
- (void)clearInBackgroundFlag
{
self.inBackground = false;
}
- (void)playAudio
{
// Move operation to new thread
dispatch_queue_t playAudiofile = dispatch_queue_create("play audiofile", NULL);
dispatch_async(playAudiofile, ^{
NSLog(@"Playing audiofile in new thread: %@", self.audiofile);
NSAssert(![self.audiofile isEqualToString:@""], @"audiofile must be specified.");
NSError *audioError;
NSString *soundFilePath = [[NSBundle mainBundle]pathForResource:self.audiofile ofType:@"mp3"];
NSAssert(soundFilePath != NULL, @"Sound File Not found");
NSURL *soundFileURL = [NSURL URLWithString:soundFilePath];
self.player = [[AVAudioPlayer alloc]initWithContentsOfURL:soundFileURL error:&audioError];
[self.player play];
});
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
frame #0: 0x020b4b54 libc++abi.dylib`__cxa_throw
frame #1: 0x0e215a41 AudioCodecs`ACBaseCodec::GetProperty(unsigned long, unsigned long&, void*) + 757
frame #2: 0x0e237618 AudioCodecs`ACMP4AACBaseDecoder::GetProperty(unsigned long, unsigned long&, void*) + 2458
frame #3: 0x0e235b83 AudioCodecs`ACMP4AACLowComplexityDecoder::GetProperty(unsigned long, unsigned long&, void*) + 565
frame #4: 0x0e28d4b4 AudioCodecs`GetProperty(void*, unsigned long, unsigned long*, void*) + 47
frame #5: 0x001347a8 AudioToolbox`AudioCodecGetProperty + 88
frame #6: 0x000392db AudioToolbox`CodecConverter::CheckInitialize(void const*, unsigned long) + 523
frame #7: 0x00038f34 AudioToolbox`CodecConverter::CodecConverter(OpaqueAudioComponent*&, OpaqueAudioComponentInstance*, StreamDescPair const&, StreamDescPair const&, bool, AudioConverterPrimeInfo const&) + 676
frame #8: 0x00038c7e AudioToolbox`CodecConverter::CodecConverter(OpaqueAudioComponent*&, OpaqueAudioComponentInstance*, StreamDescPair const&, StreamDescPair const&, bool, AudioConverterPrimeInfo const&) + 62
frame #9: 0x0003ddf7 AudioToolbox`CodecDecoderFactory::BuildCodecConverterChain(StreamDescPair const&, ChainBuildSettings const&, AudioConverterChain*, PCMConverterFactory*) + 631
frame #10: 0x0002647c AudioToolbox`ConverterRegistry::CreateConverter(StreamDescPair const&, AudioConverterChain**, unsigned long, AudioClassDescription const*) + 204
frame #11: 0x00019ba0 AudioToolbox`_AudioConverterNewInternal + 352
frame #12: 0x00060a00 AudioToolbox`AudioQueueObject::ConverterConnection::BuildConverter() + 416
frame #13: 0x000607e2 AudioToolbox`AudioQueueObject::ConverterConnection::ConverterConnection(AudioQueueObject&, long&) + 130
frame #14: 0x000620bc AudioToolbox`AudioQueueObject::IONodeConnection::GetConverterConnection_Init(long&) + 60
frame #15: 0x00065803 AudioToolbox`AudioQueueObject::SetProperty(unsigned long, CADeserializer&) + 1123
frame #16: 0x0008c44a AudioToolbox`AQServer_SetProperty + 106
frame #17: 0x00092276 AudioToolbox`AudioQueueSetProperty + 374
frame #18: 0x004c1d2b AVFoundation`AVAudioPlayerCpp::allocAudioQueue() + 683
frame #19: 0x004c13be AVFoundation`AVAudioPlayerCpp::prepareToPlayQueue() + 26
frame #20: 0x004bfebe AVFoundation`AVAudioPlayerCpp::prepareToPlay() + 84
frame #21: 0x004129f7 AVFoundation`-[AVAudioPlayer prepareToPlay] + 59
frame #22: 0x00006b7e SteinerAudio`-[AudioPlayerViewController viewDidLoad](self=0x07ad3cf0, _cmd=0x00b98a77) + 3694 at AudioPlayerViewController.mm:160
frame #23: 0x006c71c7 UIKit`-[UIViewController loadViewIfRequired] + 536
frame #24: 0x006c7232 UIKit`-[UIViewController view] + 33
frame #25: 0x006c74da UIKit`-[UIViewController contentScrollView] + 36
frame #26: 0x006de8e5 UIKit`-[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] + 36
frame #27: 0x006de9cb UIKit`-[UINavigationController _layoutViewController:] + 43
frame #28: 0x006dec76 UIKit`-[UINavigationController _updateScrollViewFromViewController:toViewController:] + 254
frame #29: 0x006ded71 UIKit`-[UINavigationController _startTransition:fromViewController:toViewController:] + 72
frame #30: 0x006df89b UIKit`-[UINavigationController _startDeferredTransitionIfNeeded:] + 386
frame #31: 0x006dfe93 UIKit`-[UINavigationController pushViewController:transition:forceImmediate:] + 1030
frame #32: 0x006dfa88 UIKit`-[UINavigationController pushViewController:animated:] + 62
frame #33: 0x00a3be63 UIKit`-[UIStoryboardPushSegue perform] + 1111
frame #34: 0x00a2db99 UIKit`-[UIStoryboardSegueTemplate _perform:] + 174
frame #35: 0x00a2dc14 UIKit`-[UIStoryboardSegueTemplate perform:] + 115
frame #36: 0x00695249 UIKit`-[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1134
frame #37: 0x006954ed UIKit`-[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 201
frame #38: 0x0109f5b3 Foundation`__NSFireDelayedPerform + 380
frame #39: 0x0199f376 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
frame #40: 0x0199ee06 CoreFoundation`__CFRunLoopDoTimer + 534
frame #41: 0x01986a82 CoreFoundation`__CFRunLoopRun + 1810
frame #42: 0x01985f44 CoreFoundation`CFRunLoopRunSpecific + 276
frame #43: 0x01985e1b CoreFoundation`CFRunLoopRunInMode + 123
frame #44: 0x028557e3 GraphicsServices`GSEventRunModal + 88
frame #45: 0x02855668 GraphicsServices`GSEventRun + 104
frame #46: 0x005e5ffc UIKit`UIApplicationMain + 1211
frame #47: 0x0000237d SteinerAudio`main(argc=1, argv=0xbffff3a0) + 141 at main.m:16
Disable C++/All exception break points in XCode. Or edit the breakpoint and set it to just objectiveC.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With