diff -r dee5afe5301f -r 3f74d0d4af4c src/multimedia/audio/qaudiooutput_win32_p.cpp --- a/src/multimedia/audio/qaudiooutput_win32_p.cpp Mon Mar 15 12:43:09 2010 +0200 +++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp Thu Apr 08 14:19:33 2010 +0300 @@ -211,6 +211,13 @@ QTime now(QTime::currentTime()); qDebug()<= 8000 && settings.frequency() <= 48000)) { + errorState = QAudio::OpenError; + deviceState = QAudio::StoppedState; + emit stateChanged(deviceState); + qWarning("QAudioOutput: open error, frequency out of range."); + return false; + } if(buffer_size == 0) { // Default buffer size, 200ms, default period size is 40ms buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2; @@ -289,6 +296,7 @@ return; deviceState = QAudio::StoppedState; + errorState = QAudio::NoError; int delay = (buffer_size-bytesFree())*1000/(settings.frequency() *settings.channels()*(settings.sampleSize()/8)); waveOutReset(hWaveOut); @@ -340,12 +348,20 @@ qint64 QAudioOutputPrivate::processedUSecs() const { - return totalTimeValue; + if (deviceState == QAudio::StoppedState) + return 0; + qint64 result = qint64(1000000) * totalTimeValue / + (settings.channels()*(settings.sampleSize()/8)) / + settings.frequency(); + + return result; } qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) { // Write out some audio data + if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) + return 0; char* p = (char*)data; int l = (int)len; @@ -385,13 +401,16 @@ current->dwBufferLength,waveFreeBlockCount); LeaveCriticalSection(&waveOutCriticalSection); #endif - totalTimeValue += current->dwBufferLength - /(settings.channels()*(settings.sampleSize()/8)) - *1000000/settings.frequency();; + totalTimeValue += current->dwBufferLength; waveCurrentBlock++; waveCurrentBlock %= buffer_size/period_size; current = &waveBlocks[waveCurrentBlock]; current->dwUser = 0; + errorState = QAudio::NoError; + if (deviceState != QAudio::ActiveState) { + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } } return (len-l); } @@ -409,8 +428,11 @@ void QAudioOutputPrivate::suspend() { - if(deviceState == QAudio::ActiveState) { + if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState) { + int delay = (buffer_size-bytesFree())*1000/(settings.frequency() + *settings.channels()*(settings.sampleSize()/8)); waveOutPause(hWaveOut); + Sleep(delay+10); deviceState = QAudio::SuspendedState; errorState = QAudio::NoError; emit stateChanged(deviceState); @@ -433,6 +455,9 @@ bool QAudioOutputPrivate::deviceReady() { + if(deviceState == QAudio::StoppedState) + return false; + if(pullMode) { int chunks = bytesAvailable/period_size; #ifdef DEBUG_AUDIO @@ -465,8 +490,16 @@ int l = audioSource->read(audioBuffer,input); if(l > 0) { int out= write(audioBuffer,l); - if(out > 0) - deviceState = QAudio::ActiveState; + if(out > 0) { + if (deviceState != QAudio::ActiveState) { + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } + } + if ( out < l) { + // Didnt write all data + audioSource->seek(audioSource->pos()-(l-out)); + } if(startup) waveOutRestart(hWaveOut); } else if(l == 0) { @@ -478,16 +511,28 @@ LeaveCriticalSection(&waveOutCriticalSection); if(check == buffer_size/period_size) { errorState = QAudio::UnderrunError; - deviceState = QAudio::IdleState; - emit stateChanged(deviceState); + if (deviceState != QAudio::IdleState) { + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } } } else if(l < 0) { bytesAvailable = bytesFree(); errorState = QAudio::IOError; } + } else { + int buffered; + EnterCriticalSection(&waveOutCriticalSection); + buffered = waveFreeBlockCount; + LeaveCriticalSection(&waveOutCriticalSection); + errorState = QAudio::UnderrunError; + if (buffered >= buffer_size/period_size && deviceState == QAudio::ActiveState) { + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } } - if(deviceState != QAudio::ActiveState) + if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return true; if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {