cocoa playing an mp3

#import <Cocoa/Cocoa.h>
#import <QTKit/QTKit.h>

@interface SoundPlayer : NSObject {
  NSSound *sound;
  IBOutlet NSWindow *window;
  IBOutlet NSSlider *progress;
  BOOL loop;
}
- (IBAction)open: (id)sender;
- (IBAction)setLoop: (id)sender;
- (IBAction)play: (id)sender;
- (IBAction)stop: (id)sender;
- (IBAction)takeCurrentTimeFrom: (id)sender;
@end

#import "SoundPlayer.h"

@implementation SoundPlayer
- (IBAction)open: (id)sender
{
    NSOpenPanel *openPanel = [NSOpenPanel openPanel];
    [openPanel runModalForTypes: [NSArray arrayWithObjects: @"aiff", @"mp3", @"m4a", nil]];
    [sound release];
    sound = [[QTMovie movieWithFile: [openPanel filename]
                              error: NULL] retain];
    [sound setAttribute: [NSNumber numberWithBool: loop]
                 forKey: QTMovieLoopsAttribute];
    [window setTitle: [[openPanel filename] lastPathComponent]];
}
- (IBAction)setLoop: (id)sender
{
    loop = ([sender state] == NSOnState);
    [sound setAttribute: [NSNumber numberWithBool: loop]
                 forKey: QTMovieLoopsAttribute];
}
- (IBAction)play: (id)sender
{
    NSTimeInterval duration;
    QTGetTimeInterval([sound duration], &duration);
    [progress setMaxValue: duration];
    [NSTimer scheduledTimerWithTimeInterval: 0.1
                                     target: self
                                   selector: @selector(updateIndicator:)
                                   userInfo: sound
                                    repeats: YES];
    [sound play];
}
- (void)updateIndicator: (NSTimer*)aTimer
{
    QTMovie *playingSound = [aTimer userInfo];
    if (!(sound == playingSound && ([sound rate] != 0)))
    {
        [aTimer invalidate];
        return;
    }
    NSTimeInterval currentTime;
    QTGetTimeInterval([sound currentTime], &currentTime);
    [progress setDoubleValue: currentTime];
}
- (IBAction)stop: (id)sender
{
    [sound stop];
}
- (IBAction)takeCurrentTimeFrom: (id)sender
{
    [sound setCurrentTime: QTMakeTimeWithTimeInterval([sender doubleValue])];
}
@end

I've written a framework in C++ that might help: http://github.com/sbooth/SFBAudioEngine

It supports multiple audio formats and has a fairly benign API and comes with a Cocoa sample.

If you're not interested in third-party frameworks, your bet would probably be to use an AudioQueue to take care of the playback. To do this, you'd probably use AudioFile to decode the MP3 and AudioQueue for the playback. Apple has an example at http://developer.apple.com/mac/library/samplecode/AudioQueueTools/Introduction/Intro.html


Use AVFoundation! According to apple, it has been integrated with Mac OS X Lion (I think), so.. Here is how to play mp3 painlessly:

1- link the AVFoundation Framework.

2- import it wherever you want to play your awesome mp3

#import <AVFoundation/AVFoundation.h>

3- Add an audioPlayer instance variable to play the sound (That's how I like to do it, at least)

@interface WCMainWindow : ... {
    ...
    AVAudioPlayer* audioPlayer;
}

4- In you init, make sure you initialize your audioPlayer:

NSString* path = [[NSBundle mainBundle] pathForResource:@"myFile" ofType:@"mp3"];
NSURL* file = [NSURL fileURLWithPath:path];
// thanks @gebirgsbaerbel
    
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:file error:nil];
[audioPlayer prepareToPlay];

5- Play your awesome Mp3!!

if ([audioPlayer isPlaying]) {
    [audioPlayer pause];
} else {
    [audioPlayer play];
}

Finally, credit goes to this guy.


Use NSSound.

You didn't specify what you mean by “lots of limitations”, so I don't know why this won't work for you. Note that it has a lot fewer limitations since Leopard; you can now play to any device, for example.