0

In my AppDelegate I have this method which will run when the play button is clicked:

- (IBAction)actionPlayTrack:(id)sender {
    NSSound *currentSong = [[NSSound alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"03 Bazel" ofType:@"mp3"] byReference:YES];
    if([currentSong isPlaying] == NO){
        [currentSong play];
    } else {
        [currentSong stop];
        [currentSong release];
    }
}

However the if statement to check if the song is currently playing will not work and will always play regardless if there is already a sound playing. Any idea's on why it would be doing this? Perhaps the currentSong object is being reset every time the button is clicked would be my first guess...

[currentSong isPlaying] 

Will always return null.

Scott Nicol
  • 11,458
  • 3
  • 15
  • 8

3 Answers3

3

I believe the problem is that you are creating a new NSSound instance every time you call this method. So the old NSSound instance may be playing, but this one is not. This probably results in a memory leak because you allocate a new instance, but never release the old one.

To overcome this issue, you may want to add a NSSound *currentSong to your class, and then you can use that NSSound object when you want to check if its playing. Then when you switch track you may want to stop the existing NSSound object and release it before making a new NSSound instance.

So your code should look something like:

- (IBAction)actionPlayTrack:(id)sender {
    if (!currentSong) {
        currentSong = [[NSSound alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"03 Bazel" ofType:@"mp3"] byReference:YES];
    }

    if ([currentSong isPlaying]){
        [currentSong stop];
        [currentSong release];
        currentSong = nil;
    } else {
        [currentSong play];
    }
}

- (void)dealloc {
    [currentSong release];
    currentSong = nil;
}

Then add NSSound* currentSong to your header.

kylef
  • 1,066
  • 1
  • 8
  • 11
0

This tip may not solve your problem, but never compare anything against YES or NO. Your test should be:

if (![currentSong isPlaying])

The reason is that NO and YES are single values, whereas the possible values that would count as true are infinite.

matt
  • 515,959
  • 87
  • 875
  • 1,141
0

It will always return NO, as you're asking if the sound you just created is playing, and of course it's not.

You may need to use the AudioSession functions in order to check if the device is already playing something else:

UInt32 otherAudioIsPlaying;
UInt32 propertySize = sizeof( UInt32 );

AudioSessionGetProperty
(
    kAudioSessionProperty_OtherAudioIsPlaying,
    &propertySize,
    &otherAudioIsPlaying
);

Check the Audio Session Programming Guide.

Macmade
  • 52,708
  • 13
  • 106
  • 123