Пример #1
0
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;
}
Пример #2
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;
}