src/cdrom/macosx/AudioFilePlayer.c
changeset 1487 dc6b59e925a2
parent 1402 d910939febfa
child 1659 14717b52abc0
equal deleted inserted replaced
1486:9d77fc9d0ace 1487:dc6b59e925a2
    22     This file based on Apple sample code. We haven't changed the file name, 
    22     This file based on Apple sample code. We haven't changed the file name, 
    23     so if you want to see the original search for it on apple.com/developer
    23     so if you want to see the original search for it on apple.com/developer
    24 */
    24 */
    25 #include "SDL_config.h"
    25 #include "SDL_config.h"
    26 
    26 
    27 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    27 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    28 //  AudioFilePlayer.cpp
    28     AudioFilePlayer.cpp
    29 //
    29 */
    30 #include "AudioFilePlayer.h"
    30 #include "AudioFilePlayer.h"
    31 
    31 
    32 /*
    32 /*
    33 void ThrowResult (OSStatus result, const char* str)
    33 void ThrowResult (OSStatus result, const char* str)
    34 {
    34 {
    59 #endif
    59 #endif
    60 
    60 
    61 
    61 
    62 static int AudioFilePlayer_SetDestination (AudioFilePlayer *afp, AudioUnit  *inDestUnit)
    62 static int AudioFilePlayer_SetDestination (AudioFilePlayer *afp, AudioUnit  *inDestUnit)
    63 {
    63 {
    64     //if (afp->mConnected) throw static_cast<OSStatus>(-1); //can't set dest if already engaged
    64     /*if (afp->mConnected) throw static_cast<OSStatus>(-1);*/ /* can't set dest if already engaged */
    65     if (afp->mConnected)
    65     if (afp->mConnected)
    66         return 0 ;
    66         return 0 ;
    67 
    67 
    68     SDL_memcpy(&afp->mPlayUnit, inDestUnit, sizeof (afp->mPlayUnit));
    68     SDL_memcpy(&afp->mPlayUnit, inDestUnit, sizeof (afp->mPlayUnit));
    69 
    69 
    70     OSStatus result = noErr;
    70     OSStatus result = noErr;
    71     
    71     
    72 
    72 
    73         //we can "down" cast a component instance to a component
    73         /* we can "down" cast a component instance to a component */
    74     ComponentDescription desc;
    74     ComponentDescription desc;
    75     result = GetComponentInfo ((Component)*inDestUnit, &desc, 0, 0, 0);
    75     result = GetComponentInfo ((Component)*inDestUnit, &desc, 0, 0, 0);
    76     if (result) return 0; //THROW_RESULT("GetComponentInfo")
    76     if (result) return 0; /*THROW_RESULT("GetComponentInfo")*/
    77         
    77         
    78         // we're going to use this to know which convert routine to call
    78         /* we're going to use this to know which convert routine to call
    79         // a v1 audio unit will have a type of 'aunt'
    79            a v1 audio unit will have a type of 'aunt'
    80         // a v2 audio unit will have one of several different types.
    80            a v2 audio unit will have one of several different types. */
    81     if (desc.componentType != kAudioUnitComponentType) {
    81     if (desc.componentType != kAudioUnitComponentType) {
    82         result = badComponentInstance;
    82         result = badComponentInstance;
    83         //THROW_RESULT("BAD COMPONENT")
    83         /*THROW_RESULT("BAD COMPONENT")*/
    84         if (result) return 0;
    84         if (result) return 0;
    85     }
    85     }
    86 
    86 
    87     /* Set the input format of the audio unit. */
    87     /* Set the input format of the audio unit. */
    88     result = AudioUnitSetProperty (*inDestUnit,
    88     result = AudioUnitSetProperty (*inDestUnit,
    89                                kAudioUnitProperty_StreamFormat,
    89                                kAudioUnitProperty_StreamFormat,
    90                                kAudioUnitScope_Input,
    90                                kAudioUnitScope_Input,
    91                                0,
    91                                0,
    92                                &afp->mFileDescription,
    92                                &afp->mFileDescription,
    93                                sizeof (afp->mFileDescription));
    93                                sizeof (afp->mFileDescription));
    94         //THROW_RESULT("AudioUnitSetProperty")
    94         /*THROW_RESULT("AudioUnitSetProperty")*/
    95     if (result) return 0;
    95     if (result) return 0;
    96     return 1;
    96     return 1;
    97 }
    97 }
    98 
    98 
    99 static void AudioFilePlayer_SetNotifier(AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon)
    99 static void AudioFilePlayer_SetNotifier(AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon)
   168     if (!afp->mConnected)
   168     if (!afp->mConnected)
   169     {           
   169     {           
   170         if (!afp->mAudioFileManager->DoConnect(afp->mAudioFileManager))
   170         if (!afp->mAudioFileManager->DoConnect(afp->mAudioFileManager))
   171             return 0;
   171             return 0;
   172 
   172 
   173         // set the render callback for the file data to be supplied to the sound converter AU
   173         /* set the render callback for the file data to be supplied to the sound converter AU */
   174         afp->mInputCallback.inputProc = afp->mAudioFileManager->FileInputProc;
   174         afp->mInputCallback.inputProc = afp->mAudioFileManager->FileInputProc;
   175         afp->mInputCallback.inputProcRefCon = afp->mAudioFileManager;
   175         afp->mInputCallback.inputProcRefCon = afp->mAudioFileManager;
   176 
   176 
   177         OSStatus result = AudioUnitSetProperty (afp->mPlayUnit, 
   177         OSStatus result = AudioUnitSetProperty (afp->mPlayUnit, 
   178                             kAudioUnitProperty_SetInputCallback, 
   178                             kAudioUnitProperty_SetInputCallback, 
   179                             kAudioUnitScope_Input, 
   179                             kAudioUnitScope_Input, 
   180                             0,
   180                             0,
   181                             &afp->mInputCallback, 
   181                             &afp->mInputCallback, 
   182                             sizeof(afp->mInputCallback));
   182                             sizeof(afp->mInputCallback));
   183         if (result) return 0;  //THROW_RESULT("AudioUnitSetProperty")
   183         if (result) return 0;  /*THROW_RESULT("AudioUnitSetProperty")*/
   184         afp->mConnected = 1;
   184         afp->mConnected = 1;
   185     }
   185     }
   186 
   186 
   187     return 1;
   187     return 1;
   188 }
   188 }
   189 
   189 
   190 // warning noted, now please go away ;-)
   190 /* warning noted, now please go away ;-) */
   191 // #warning This should redirect the calling of notification code to some other thread
   191 /* #warning This should redirect the calling of notification code to some other thread */
   192 static void    AudioFilePlayer_DoNotification (AudioFilePlayer *afp, OSStatus inStatus)
   192 static void    AudioFilePlayer_DoNotification (AudioFilePlayer *afp, OSStatus inStatus)
   193 {
   193 {
   194     if (afp->mNotifier) {
   194     if (afp->mNotifier) {
   195         (*afp->mNotifier) (afp->mRefCon, inStatus);
   195         (*afp->mNotifier) (afp->mRefCon, inStatus);
   196     } else {
   196     } else {
   241     OSErr result;
   241     OSErr result;
   242     HFSUniStr255 dfName;
   242     HFSUniStr255 dfName;
   243     ByteCount actual;
   243     ByteCount actual;
   244     SInt64 offset;
   244     SInt64 offset;
   245 
   245 
   246     // Open the data fork of the input file
   246     /* Open the data fork of the input file */
   247     result = FSGetDataForkName(&dfName);
   247     result = FSGetDataForkName(&dfName);
   248        if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName")
   248        if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName")*/
   249 
   249 
   250     result = FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm, &afp->mForkRefNum);
   250     result = FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm, &afp->mForkRefNum);
   251        if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork")
   251        if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork")*/
   252  
   252  
   253     // Read the file header, and check if it's indeed an AIFC file
   253     /* Read the file header, and check if it's indeed an AIFC file */
   254     result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(chunkHeader), &chunkHeader, &actual);
   254     result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(chunkHeader), &chunkHeader, &actual);
   255        if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")
   255        if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/
   256 
   256 
   257     if (chunkHeader.ckID != 'FORM') {
   257     if (chunkHeader.ckID != 'FORM') {
   258         result = -1;
   258         result = -1;
   259         if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'");
   259         if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'");*/
   260     }
   260     }
   261 
   261 
   262     if (chunkHeader.formType != 'AIFC') {
   262     if (chunkHeader.formType != 'AIFC') {
   263         result = -1;
   263         result = -1;
   264         if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): file format is not 'AIFC'");
   264         if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): file format is not 'AIFC'");*/
   265     }
   265     }
   266 
   266 
   267     // Search for the SSND chunk. We ignore all compression etc. information
   267     /* Search for the SSND chunk. We ignore all compression etc. information
   268     // in other chunks. Of course that is kind of evil, but for now we are lazy
   268        in other chunks. Of course that is kind of evil, but for now we are lazy
   269     // and rely on the cdfs to always give us the same fixed format.
   269        and rely on the cdfs to always give us the same fixed format.
   270     // TODO: Parse the COMM chunk we currently skip to fill in mFileDescription.
   270        TODO: Parse the COMM chunk we currently skip to fill in mFileDescription.
       
   271     */
   271     offset = 0;
   272     offset = 0;
   272     do {
   273     do {
   273         result = FSReadFork(afp->mForkRefNum, fsFromMark, offset, sizeof(chunk), &chunk, &actual);
   274         result = FSReadFork(afp->mForkRefNum, fsFromMark, offset, sizeof(chunk), &chunk, &actual);
   274            if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")
   275            if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/
   275             
   276             
   276         // Skip the chunk data
   277         /* Skip the chunk data */
   277         offset = chunk.ckSize;
   278         offset = chunk.ckSize;
   278     } while (chunk.ckID != 'SSND');
   279     } while (chunk.ckID != 'SSND');
   279 
   280 
   280     // Read the header of the SSND chunk. After this, we are positioned right
   281     /* Read the header of the SSND chunk. After this, we are positioned right
   281     // at the start of the audio data.
   282        at the start of the audio data. */
   282     result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(ssndData), &ssndData, &actual);
   283     result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(ssndData), &ssndData, &actual);
   283        if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")
   284        if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/
   284 
   285 
   285     result = FSSetForkPosition(afp->mForkRefNum, fsFromMark, ssndData.offset);
   286     result = FSSetForkPosition(afp->mForkRefNum, fsFromMark, ssndData.offset);
   286        if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSSetForkPosition")
   287        if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSSetForkPosition")*/
   287 
   288 
   288     // Data size
   289     /* Data size */
   289     *outFileDataSize = chunk.ckSize - ssndData.offset - 8;
   290     *outFileDataSize = chunk.ckSize - ssndData.offset - 8;
   290 
   291 
   291     // File format
   292     /* File format */
   292     afp->mFileDescription.mSampleRate = 44100;
   293     afp->mFileDescription.mSampleRate = 44100;
   293     afp->mFileDescription.mFormatID = kAudioFormatLinearPCM;
   294     afp->mFileDescription.mFormatID = kAudioFormatLinearPCM;
   294     afp->mFileDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger;
   295     afp->mFileDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger;
   295     afp->mFileDescription.mBytesPerPacket = 4;
   296     afp->mFileDescription.mBytesPerPacket = 4;
   296     afp->mFileDescription.mFramesPerPacket = 1;
   297     afp->mFileDescription.mFramesPerPacket = 1;
   329     {
   330     {
   330         SDL_free(afp);
   331         SDL_free(afp);
   331         return NULL;
   332         return NULL;
   332     }
   333     }
   333         
   334         
   334     // we want about 4 seconds worth of data for the buffer
   335     /* we want about 4 seconds worth of data for the buffer */
   335     int bytesPerSecond = (UInt32) (4 * afp->mFileDescription.mSampleRate * afp->mFileDescription.mBytesPerFrame);
   336     int bytesPerSecond = (UInt32) (4 * afp->mFileDescription.mSampleRate * afp->mFileDescription.mBytesPerFrame);
   336     
   337     
   337 #if DEBUG
   338 #if DEBUG
   338     printf("File format:\n");
   339     printf("File format:\n");
   339     PrintStreamDesc (&afp->mFileDescription);
   340     PrintStreamDesc (&afp->mFileDescription);