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