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 );
}
戻る