unsigned int __stdcall SpkrThread(LPVOID Unused) { int i; DWORD bufLen = ((N_SAMPLES * BITS_PER_SAMPLE) / 8); WAVEHDR* pWH; MMRESULT ret; int played; OsMsg *pMsg = NULL; OsIntPtrMsg *pSpeakerMsg = NULL; BOOL bGotMsg ; int n; bool bDone ; static bool sLastRingerEnabled = false; OsStatus res; static bool bRunning = false ; HWAVEOUT hOut = NULL; UINT timerId=0; // Verify that only 1 instance of the MicThread is running if (bRunning) { ResumeThread(hMicThread); return 1 ; } else { bRunning = true ; } ResumeThread(hMicThread); #ifdef OHISTORY /* [ */ WAVEHDR* lastWH[OHISTORY]; int lastInd[OHISTORY]; int last = 0; for (i=0;i<OHISTORY;i++) { lastWH[i] = 0; lastInd[i] = 0; } memset(histOut, 0xff, sizeof(histOut)); lastOut = 0; #endif /* OHISTORY ] */ // Initialize headers for (i=0; i<N_OUT_BUFFERS; i++) { hOutHdr[i] = hOutBuf[i] = NULL; pOutHdr[i] = NULL; } if (openSpeakerDevices(pWH, hOut)) { // NOT using a sound card // Set up a 10ms timer to call back to this routine timerId = timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC); } played = 0; bDone = false ; while (!bDone) { bGotMsg = (gSpeakerStatusQueue->receive(pMsg) == OS_SUCCESS); // when switching devices, ringer to in-call we need to make // sure any outstanding buffers are flushed if (sLastRingerEnabled != DmaTask::isRingerEnabled()) { if (audioOutH) { ret = waveOutReset(audioOutH); } if (audioOutCallH) { ret = waveOutReset(audioOutCallH); } if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutReset", ret, -1, __LINE__); } else { waitForDeviceResetCompletion(); } } if (bGotMsg && pMsg) { pSpeakerMsg = (OsIntPtrMsg*)pMsg; intptr_t msgType = pSpeakerMsg->getData1(); intptr_t data2 = pSpeakerMsg->getData2(); pSpeakerMsg->releaseMsg(); pSpeakerMsg = NULL; pMsg = NULL; switch (msgType) { case WM_ALT_HEARTBEAT: OsSysLog::add(FAC_MP, PRI_DEBUG, "SpeakerThreadWnt invoking MpMediaTask::signalFrameStart from timer message"); res = MpMediaTask::signalFrameStart(); switch (res) { case OS_SUCCESS: frameCount++; break; #ifdef DEBUG_WINDOZE /* [ */ case OS_LIMIT_REACHED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_LIMIT_REACHED\n", frameCount); break; case OS_WAIT_TIMEOUT: // Should bump missed frame statistic osPrintf(" Frame %d: OS_WAIT_TIMEOUT\n", frameCount); break; case OS_ALREADY_SIGNALED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_ALREADY_SIGNALED\n", frameCount); break; default: osPrintf("Frame %d, signalFrameStart() returned %d\n", frameCount, res); break; #else /* DEBUG_WINDOZE ] [ */ case OS_LIMIT_REACHED: case OS_WAIT_TIMEOUT: case OS_ALREADY_SIGNALED: default: // Should bump missed frame statistic break; #endif /* DEBUG_WINDOZE ] */ } // Check for a changed speaker device if (DmaTask::isOutputDeviceChanged()) { DmaTask::clearOutputDeviceChanged() ; closeSpeakerDevices() ; if (audioOutH) { ret = waveOutReset(audioOutH); } if (audioOutCallH) { ret = waveOutReset(audioOutCallH); } if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutReset", ret, -1, __LINE__); } else { waitForDeviceResetCompletion(); } // Kill the hearbeat timer if it exists if (timerId>0) timeKillEvent(timerId); if (openSpeakerDevices(pWH, hOut)) { // Open failed - so start the heartbeat timer timerId = timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC); } continue ; } break ; case WOM_DONE: pWH = (WAVEHDR *) data2; n = (pWH->dwUser) & USER_BUFFER_MASK; #ifdef OHISTORY /* [ */ lastWH[last] = pWH; lastInd[last] = n; last = (last + 1) % OHISTORY; if (N_OUT_BUFFERS == played) { osPrintf("after first %d buffers:", played + 1); osPrintf("\nCall Backs:"); for (i=0; i<OHISTORY; i++) { osPrintf("%c%3d", (0 == (i % 20)) ? '\n' : ' ', histOut[i]); } osPrintf("\n\nMessages:"); for (i=0; i<OHISTORY; i++) { osPrintf("%c%3d", (0 == (i % 20)) ? '\n' : ' ', lastInd[i]); } osPrintf("\n"); } #endif /* OHISTORY ] */ if (DmaTask::isOutputDeviceChanged()) { DmaTask::clearOutputDeviceChanged() ; closeSpeakerDevices() ; if (openSpeakerDevices(pWH, hOut)) { if (timerId>0) timeKillEvent(timerId); timerId = timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC); } continue ; } hOut = selectSpeakerDevice() ; if (hOut) { ret = waveOutUnprepareHeader(hOut, pWH, sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutUnprepareHeader", ret, played, __LINE__); } outPostUnprep(n, false); pWH = outPrePrep(n, bufLen); ret = waveOutPrepareHeader(hOut, pWH, sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutPrepareHeader", ret, played, __LINE__); } ret = waveOutWrite(hOut, pWH, sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutWrite", ret, played, __LINE__); } played++; } OsSysLog::add(FAC_MP, PRI_DEBUG, "SpeakerThreadWnt invoking MpMediaTask::signalFrameStart from WOM_DONE message"); res = MpMediaTask::signalFrameStart(); switch (res) { #ifdef DEBUG_WINDOZE /* [ */ case OS_SUCCESS: frameCount++; osPrintf(" Frame %d: OS_SUCCESSFUL\n", frameCount); break; case OS_LIMIT_REACHED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_LIMIT_REACHED\n", frameCount); break; case OS_WAIT_TIMEOUT: // Should bump missed frame statistic osPrintf(" Frame %d: OS_WAIT_TIMEOUT\n", frameCount); break; case OS_ALREADY_SIGNALED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_ALREADY_SIGNALED\n", frameCount); break; default: osPrintf("Frame %d, signalFrameStart() returned %d\n", frameCount, res); break; #else /* DEBUG_WINDOZE ] [ */ case OS_SUCCESS: frameCount++; break; case OS_LIMIT_REACHED: case OS_WAIT_TIMEOUT: case OS_ALREADY_SIGNALED: default: // Should bump missed frame statistic break; #endif /* DEBUG_WINDOZE ] */ } break; case WOM_CLOSE: // Audio device was closed on us (doesn't happen as far as I // know) bDone = true ; break; default: break; } } else { // Sky is falling, kick out so that we don't spin a high priority // thread. bDone = true ; } // record our last ringer state sLastRingerEnabled = DmaTask::isRingerEnabled(); } // Stop heartbeat timer if it exist if (timerId>0) timeKillEvent(timerId); closeSpeakerDevices() ; bRunning = false ; return 0; }
unsigned int __stdcall SpkrThread(LPVOID Unused) { int i; DWORD bufLen = ((N_SAMPLES * BITS_PER_SAMPLE) / 8); WAVEHDR* pWH; MMRESULT ret; int played; MSG tMsg; BOOL bGotMsg ; int n; bool bDone ; static bool sLastRingerEnabled = false; OsStatus res; static bool bRunning = false ; HWAVEOUT hOut = NULL; // Verify that only 1 instance of the MicThread is running if (bRunning) { ResumeThread(hMicThread); return 1 ; } else { bRunning = true ; } ResumeThread(hMicThread); #ifdef OHISTORY /* [ */ WAVEHDR* lastWH[OHISTORY]; int lastInd[OHISTORY]; int last = 0; for (i=0;i<OHISTORY;i++) { lastWH[i] = 0; lastInd[i] = 0; } memset(histOut, 0xff, sizeof(histOut)); lastOut = 0; #endif /* OHISTORY ] */ // Initialize headers for (i=0; i<N_OUT_BUFFERS; i++) { hOutHdr[i] = hOutBuf[i] = NULL; pOutHdr[i] = NULL; } if (openSpeakerDevices(pWH, hOut)) { // NOT using a sound card // Set up a 10ms timer to call back to this routine timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC); } played = 0; bDone = false ; while (!bDone) { bGotMsg = GetMessage(&tMsg, NULL, 0, 0); // when switching devices, ringer to in-call we need to make // sure any outstanding buffers are flushed if (sLastRingerEnabled != DmaTask::isRingerEnabled()) { if (audioOutH) { waveOutReset(audioOutH); } if (audioOutCallH) { waveOutReset(audioOutCallH); } } if (bGotMsg) { switch (tMsg.message) { case WM_ALT_HEARTBEAT: res = MpMediaTask::signalFrameStart(); switch (res) { case OS_SUCCESS: frameCount++; break; case OS_LIMIT_REACHED: case OS_WAIT_TIMEOUT: case OS_ALREADY_SIGNALED: default: // Should bump missed frame statistic break; } break ; case WOM_DONE: pWH = (WAVEHDR *) tMsg.wParam; n = (pWH->dwUser) & USER_BUFFER_MASK; #ifdef OHISTORY /* [ */ lastWH[last] = pWH; lastInd[last] = n; last = (last + 1) % OHISTORY; if (N_OUT_BUFFERS == played) { osPrintf("after first %d buffers:", played + 1); osPrintf("\nCall Backs:"); for (i=0; i<OHISTORY; i++) { osPrintf("%c%3d", (0 == (i % 20)) ? '\n' : ' ', histOut[i]); } osPrintf("\n\nMessages:"); for (i=0; i<OHISTORY; i++) { osPrintf("%c%3d", (0 == (i % 20)) ? '\n' : ' ', lastInd[i]); } osPrintf("\n"); } #endif /* OHISTORY ] */ if (DmaTask::isOutputDeviceChanged()) { DmaTask::clearOutputDeviceChanged() ; closeSpeakerDevices() ; if (openSpeakerDevices(pWH, hOut)) { timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC); } continue ; } hOut = selectSpeakerDevice() ; if (hOut) { ret = waveOutUnprepareHeader(hOut, pWH, sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutUnprepareHeader", ret, played, __LINE__); } outPostUnprep(n, false); pWH = outPrePrep(n, bufLen); ret = waveOutPrepareHeader(hOut, pWH, sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutPrepareHeader", ret, played, __LINE__); } ret = waveOutWrite(hOut, pWH, sizeof(WAVEHDR)); if (ret != MMSYSERR_NOERROR) { showWaveError("waveOutWrite", ret, played, __LINE__); /* RL < */ if (ret == MMSYSERR_NODRIVER) { closeSpeakerDevices() ; if (openSpeakerDevices(pWH, hOut)) { timeSetEvent(10, 0, TimerCallbackProc, GetCurrentThreadId(), TIME_PERIODIC); } continue; } /* RL > */ } played++; } res = MpMediaTask::signalFrameStart(); switch (res) { case OS_SUCCESS: frameCount++; break; #ifdef DEBUG_WINDOZE /* [ */ case OS_LIMIT_REACHED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_LIMIT_REACHED\n", frameCount); break; case OS_WAIT_TIMEOUT: // Should bump missed frame statistic osPrintf(" Frame %d: OS_WAIT_TIMEOUT\n", frameCount); break; case OS_ALREADY_SIGNALED: // Should bump missed frame statistic osPrintf(" Frame %d: OS_ALREADY_SIGNALED\n", frameCount); break; default: osPrintf("Frame %d, signalFrameStart() returned %d\n", frameCount, res); break; #else /* DEBUG_WINDOZE ] [ */ case OS_LIMIT_REACHED: case OS_WAIT_TIMEOUT: case OS_ALREADY_SIGNALED: default: // Should bump missed frame statistic break; #endif /* DEBUG_WINDOZE ] */ } break; case WOM_CLOSE: // Audio device was closed on us (doesn't happen as far as I // know) bDone = true ; break; default: break; } } else { // Sky is falling, kick out so that we don't spin a high priority // thread. bDone = true ; } // record our last ringer state sLastRingerEnabled = DmaTask::isRingerEnabled(); } closeSpeakerDevices() ; bRunning = false ; return 0; }