asynchronous sound 再生 サブルーチン群

/*** globals ***/ #define kSoundComplete 1 // sound is done playing SndChannelPtr gSndChan; Boolean gCallbackPerformed = false; /* Prototypes (private) */ SndChannelPtr MyCreateSndChannel( SndCallBackUPP userRoutine ); //OSErr MyDisposeSndChannel( SndChannelPtr sndChan, Boolean quietNow ); OSErr MyInstallCallback( SndChannelPtr mySndChan ); pascal void MyCallback( SndChannelPtr channel, SndCommand * theCmd ); /***************************** MyCreateSndChannel ******************************/ SndChannelPtr MyCreateSndChannel( SndCallBackUPP userRoutine ) { OSErr myErr; SndChannelPtr mySndChan = nil; // System will allocate memory myErr = SndNewChannel( &mySndChan, 0, 0, userRoutine ); if( myErr == noErr ) mySndChan->userInfo = 0; // reset userInfo field else mySndChan = nil; // return nil return( mySndChan ); } /*************************** MyInstallCallback ******************************************/ OSErr MyInstallCallback( SndChannelPtr mySndChan ) { const Boolean kWait = false; // by Jim Reekes ( SoundApp in Ultimate Mac Prog'mng ) SndCommand mySndCmd; // a sound command mySndCmd.cmd = callBackCmd; // install the callback command mySndCmd.param1 = kSoundComplete; // last command for this channel mySndCmd.param2 = (long)(&gCallbackPerformed); return( SndDoCommand( mySndChan, &mySndCmd, kWait ) ); } /**************************** MyCallback ****************************************/ pascal void MyCallback( SndChannelPtr channel, SndCommand * theCmd ) //Carbon { if( theCmd->param1 == kSoundComplete ) //Carbon *( (Boolean *)(theCmd->param2) ) = true; // set a global flag // same as gCallbackPerformed = true; } /**************************** MyCheckSndChan ****************************************/ void MyCheckSndChan( void ) { OSErr err; Handle mySndHandle; if( gCallbackPerformed ) // check global flag { // channel is done gCallbackPerformed = false; // reset global flag mySndHandle = (Handle)(gSndChan->userInfo); //save handle before DisposeChannel if( gSndChan != nil ) { err = SndDisposeChannel( gSndChan, true ); //quietNow if( err != noErr ) DoError( err, "\pSndDisposeChannel failed", false ); gSndChan = nil; // set pointer to nil } if( mySndHandle != nil ) { HUnlock( mySndHandle ); //HPurge( mySndHandle ); DisposeHandle( mySndHandle ); } } } /**************************** MyStopPlaying ****************************************/ void MyStopPlaying( void ) { if ( gSndChan != nil ) // is sound really playing gCallbackPerformed = true; // set global flag MyCheckSndChan(); // call routine to do disposing } /***************************** MyStartPlaying ****************************************/ void MyStartPlaying( short mySndID ) { const Boolean kAsync = true; // play is asynchronous Handle mySndHandle; // handle to an 'snd ' resource OSErr myErr; SndCallBackUPP myBack; //for PPC if( gSndChan != nil ) // check if channel is active MyStopPlaying(); myBack = NewSndCallBackUPP( MyCallback ); gSndChan = MyCreateSndChannel( myBack ); mySndHandle = GetResource( 'snd ', mySndID ); if( mySndHandle != nil && gSndChan != nil ) { // start sound playing DetachResource( mySndHandle ); // detach resource from file // remember to release sound handle gSndChan->userInfo = (long)mySndHandle; HLock( mySndHandle ); // lock the resource data myErr = SndPlay( gSndChan, (SndListResource **)mySndHandle, kAsync ); if( myErr == noErr ) myErr = MyInstallCallback( gSndChan ); if( myErr != noErr ) DoError( myErr, "\pMyStartPlaying() failed.", false ); } DisposeSndCallBackUPP( myBack ); }

戻る