⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macaudio.cp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CP
📖 第 1 页 / 共 3 页
字号:
		timeEnd = timeEndArg;

		waveOut->StartedPlaying (cbPlaying);
		
		cmd.cmd = callBackCmd;
		cmd.param1 = kCallBackRelease;
		cmd.param2 = (long) this;
		if (noErr != (e = ::SndDoCommand (waveOut->chan, &cmd, TRUE))) goto CleanUp;
		
		waveOut->m_bAudioCallbacksAreAlive = TRUE;
		
	CleanUp:
	
		return (e);
		
	} /* end PlayBuffer */
	
/*--------------------------------------------------------------------------
|	NewChannel
--------------------------------------------------------------------------*/
SndChannelPtr CWaveHeader::NewChannel (void)

	{ /* begin NewChannel */
		
		SndChannelPtr		chan = nil;
#if defined( _CARBON ) || defined( _MAC_UNIX )
		SndCallBackUPP		userProc = NewSndCallBackUPP (Callback);
#else
		SndCallBackUPP		userProc = NewSndCallBackProc (Callback);
#endif
		
//		if (noErr != ::SndNewChannel (&chan, sampledSynth, initStereo + initNoDrop + initNoInterp, userProc))
		if (noErr != ::SndNewChannel (&chan, sampledSynth, initStereo, userProc))
			chan = nil;
		
		return chan;
		
	} /* end NewChannel */

/*--------------------------------------------------------------------------
|	DisposeChannel
--------------------------------------------------------------------------*/
OSErr CWaveHeader::DisposeChannel (
	
	SndChannelPtr	chan)
	
	{ /* begin DisposeChannel */
	OSErr e;
	
		if(chan)
		{
			SndCallBackUPP		userProc = chan->callBack;
#if defined( _CARBON ) || defined( _MAC_UNIX )
			if (userProc) DisposeSndCallBackUPP (userProc);
#else
			if (userProc) DisposeRoutineDescriptor (userProc);
#endif
		
			e = ::SndDisposeChannel (chan, TRUE);
		
		}
		return e;
		
	} /* end DisposeChannel */

/*--------------------------------------------------------------------------
|	Callback
--------------------------------------------------------------------------*/

pascal void CWaveHeader::Callback (

	SndChannelPtr	chan,
	SndCommand		*cmd)
	
	{ /* begin Callback */
		
#ifndef _MAC_UNIX
		HXMM_INTERRUPTON();
#endif
	
//    if (HXMM_RAHUL_CHECK())
//    {
//        DebugStr("\pCWaveHeader Deferred Task ENTER;g");
//    }
    
		DeferredTask*	dtrec = NULL;
		CWaveHeader*    wh    = NULL;
                SndCommand*	  newCommand;
                
		if (cmd)
		{
			wh = (CWaveHeader *) cmd->param2;
			
			if ( wh )
			{
			    CAudioOutMac* theWaveOut = wh->waveOut;
			    
			    if ( theWaveOut )
			    {
				CMacWaveFormat wf = theWaveOut->wf;
				
				UINT32 ulBytesPerSecond = 
					wf.numChannels *
					( (ULONG32)wf.sampleRate >> 16 ) *
					( wf.sampleSize / 8 );
				
				theWaveOut->m_millisecondsIntoClip +=
					(double)wh->cbPlaying * 1000.0 / (double)ulBytesPerSecond;
			    }
			}
			
			dtrec=wh->waveOut->mDeferredTaskRec;
		}
		
		if (!dtrec)
		{
			goto CleanUp;
		}
		
		newCommand=new SndCommand;
		HX_ASSERT(newCommand);
		
		if (!newCommand)
		{
			delete dtrec;
			goto CleanUp;
		}
		
		if (cmd)
		{
			*newCommand=*cmd;
		}
		else
		{
			delete newCommand;
			delete dtrec;
			goto CleanUp;
		}
		
		wh->waveOut->AddToThePendingList(newCommand);
	
		if (!wh->waveOut->m_bDeferredTaskPending)
		{
		    wh->waveOut->m_bDeferredTaskPending = TRUE;
		    
		    short err = 0;
		    
		    if ( wh->waveOut->m_bIsQuitting )
		    {
			err = -1; // just so it's nonzero
		    }
		    else
		    {
			err = DTInstall(dtrec);
		    }
		    if ( err != noErr )
		    {
			wh->waveOut->m_bDeferredTaskPending = FALSE;
			wh->waveOut->m_bAudioCallbacksAreAlive = FALSE;
			delete dtrec;
			delete newCommand;
			goto CleanUp;
		    }
		}
		
	/*	
		if (wh) {
			long	saveA5 = SetA5 (wh->soundA5);
			wh->Release (cmd->param1);
			SetA5 (saveA5);
			} 
	*/
	
	
	CleanUp:
		
#ifndef _MAC_UNIX
		HXMM_INTERRUPTOFF();
#endif
		
//    if (HXMM_RAHUL_CHECK())
//    {
//        DebugStr("\pCWaveHeader Deferred Task LEAVE;g");
//    }
		return;
		
	} /* end Callback */
	

pascal void CAudioOutMac::DeferredTaskCallback(long param)
{
    if (!param)
    {
        return;
    }
    
#ifndef _MAC_UNIX
	HXMM_INTERRUPTON();
#endif
	
	CAudioOutMac* pAudioOut = (CAudioOutMac*) param;
	
	pAudioOut->m_bAudioCallbacksAreAlive = FALSE;
	
#ifdef THREADS_SUPPORTED
	if (zm_pMutex)
	{
	    zm_pMutex->Lock();
	}
#endif

#if defined(_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
	    if ( !pAudioOut->m_bAudioCallbacksAreAlive )
	    {
		DebugStr( "\pDeferredTaskCallback -- m_bAudioCallbacksAreAlive not true!;g" );
	    }

#endif
	while (gActiveAudioDevice &&
	       pAudioOut->m_pPendingCallbackList && 
	      !pAudioOut->m_pPendingCallbackList->IsEmpty())
	{
		SndCommand*	cmd = (SndCommand*) pAudioOut->m_pPendingCallbackList->RemoveHead();
		BOOL bIsEmpty = pAudioOut->m_pPendingCallbackList->IsEmpty();
		
#ifdef THREADS_SUPPORTED
		// we used to deadlock here; we'd grab the audio mutex before the core mutex,
		// which is not how the rest of this class operates
		if (zm_pMutex)
		{
		    zm_pMutex->Unlock();
		}
#endif
		/* Send time sync for ONLY the last pending audio callback */
		pAudioOut->ProcessCmd(cmd, bIsEmpty);
				
     	delete cmd;
#ifdef THREADS_SUPPORTED
		if (zm_pMutex)
		{
		    zm_pMutex->Lock();
		}
#endif
	}
	
	/* It is possible that on a timesync, a renderer may issue a hyper navigate request.
	 * This may result in leaving the currently active page (thereby unloading 
	 * the embedded player and the core. We would have destructed the CMacAudio class
	 * in this case.
	 */ 
	if (!gActiveAudioDevice)
	{
	    goto cleanup;
	}
	
	pAudioOut->m_bDeferredTaskPending = FALSE;
	
cleanup:	

#ifdef THREADS_SUPPORTED
	if (zm_pMutex)
	{
	    zm_pMutex->Unlock();
	}
#endif

#ifndef _MAC_UNIX
	HXMM_INTERRUPTOFF();
#endif
}

void
CAudioOutMac::ProcessCmd(SndCommand* cmd, BOOL bSendTimeSync /*= TRUE*/)
{
	CWaveHeader	*wh = (CWaveHeader *) cmd->param2;
	if (wh)
	{
		wh->Release(cmd->param1, bSendTimeSync);
	}
}

	
/*--------------------------------------------------------------------------
|	CAudioOutMac
--------------------------------------------------------------------------*/
UINT16 CAudioOutMac::NUM_WAVEHDRS = 12;	// was 30

CAudioOutMac::CAudioOutMac ()
	: chan (nil)
	, mlpWaveHdrs (NULL)
	, mcbPlaying (0)
	, mPaused (TRUE)
	, m_uNumBlocksInDevice(0)
	, m_bFirstPacket(TRUE)
	, m_ulTimeOfFirstPacket(0L)
	, m_pPendingCallbackList(NULL)
	, m_bDeferredTaskPending(FALSE)
	, m_bAudioCallbacksAreAlive(FALSE)
	, m_bIsQuitting(FALSE)
	, m_millisecondsIntoClip(0.0)
	, m_pCallback(NULL)
	, m_pInterruptState(NULL)
{ /* begin CAudioOutMac */
	mDeferredTaskRec=(DeferredTask*)NewPtrClear(sizeof(DeferredTask));
	
	mDeferredTaskRec->qType=dtQType;
	mDeferredTaskRec->dtAddr=CAudioOutMac::gDeferredTask;
    mDeferredTaskRec->dtParam= (long) this;
    
	// Gestalt-based code that remembers potential deferred tasks for emergency removal
	
#ifndef _MAC_UNIX
	Handle dtGestaltHandle = nil;
	OSErr err = Gestalt( kLetInterruptsFinishBeforeQuittingGestalt, (long*)&dtGestaltHandle );
	if ( err != noErr )
	{
#if defined( _CARBON )
	    MacAudioInitInterfaceLibProcPtrs();
	    if (gMacAudioNewHandleSysProc)
	    {
		dtGestaltHandle = (*gMacAudioNewHandleSysProc)( 0 );
	    }
	    if (!dtGestaltHandle)
	    {
		dtGestaltHandle = NewHandle( 0 );
	    }
#else
	    dtGestaltHandle = NewHandleSys( 0 );
#endif
	    if ( dtGestaltHandle )
	    {
		NewGestaltValue( kLetInterruptsFinishBeforeQuittingGestalt, (long)dtGestaltHandle );
	    }
	}

	if ( dtGestaltHandle )
	{
	    GestaltDeferredStruct gds;
	    gds.quitting = &m_bIsQuitting;
	    gds.pending = &m_bAudioCallbacksAreAlive;
	    GetCurrentProcess(&(gds.psn));
	    PtrAndHand( &gds, dtGestaltHandle, sizeof(gds) );
	}
#endif
	

#ifdef THREADS_SUPPORTED
	if (!zm_pMutex)
	{
	    HXMutex::MakeMutex(zm_pMutex);
	}
#endif
    gActiveAudioDevice = this;
} /* end CAudioOutMac */


/*--------------------------------------------------------------------------
|	~CAudioOutMac
--------------------------------------------------------------------------*/
CAudioOutMac::~CAudioOutMac ()

{ /* begin ~CAudioOutMac */ 
	
	Abort ();

#if defined(_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
	BOOL bWaitedForPending = FALSE;
	if ( m_bAudioCallbacksAreAlive )
	{
	    DebugStr( "\pCAudioOutMac dtor -- m_bAudioCallbacksAreAlive still true!;g" );
	    bWaitedForPending = TRUE;
	}
#endif
    
    m_bIsQuitting = TRUE;
    // sit-n-spin awaiting interrupts to finish.
    for ( int i = 0; i < 10; i++ )
    {
	unsigned long dummyTix;
	Delay( 6, &dummyTix );
	if ( !m_bAudioCallbacksAreAlive )
	{
	    i = 10;
	}
    }
    
#if defined(_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
	if ( bWaitedForPending )
	{
	    if ( m_bAudioCallbacksAreAlive )
	    {
		DebugStr( "\ptasks STILL pending! This is gonna hurt...;g" );
	    }
	    else
	    {
		DebugStr( "\pSuccessfully purged pending callbacks;g" );
	    }
	}
#endif

	if (mDeferredTaskRec)
	{


	// first ensure that the Gestalt handle doesn't think it's
	// here any more.
	
#ifndef _MAC_UNIX
	Handle dtGestaltHandle = nil;
	Gestalt( kLetInterruptsFinishBeforeQuittingGestalt, (long*)&dtGestaltHandle );
	if ( dtGestaltHandle )
	{
	    // XXXNH: only look at tasks for this process
	    ProcessSerialNumber psn;
	    GetCurrentProcess(&psn);
	
	    // zip through and if an entry equals this deferred task,
	    // simply zero it out. We won't worry about shuffling
	    // the handle size at this juncture.
	    long hSize = GetHandleSize( dtGestaltHandle );
	    GestaltDeferredStruct* currentPtr = (GestaltDeferredStruct*)*dtGestaltHandle;
	    for ( int i = 0; i < hSize / sizeof(GestaltDeferredStruct); i++ )
	    {
	        unsigned char bSameProcess = FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -