📄 macaudio.cp
字号:
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 + -