summaryrefslogtreecommitdiffstats
path: root/src/multimedia
diff options
context:
space:
mode:
authoraxis <qt-info@nokia.com>2010-02-26 09:05:39 (GMT)
committeraxis <qt-info@nokia.com>2010-02-26 09:05:39 (GMT)
commit5e9382c018e231c5e2ef49dd8a38eaff535b9837 (patch)
tree89f13d31d5804c38999fdefd0e2aca39d305f91c /src/multimedia
parent11e54877f87ff97039452f117d40ec17eefbcbff (diff)
parent53e7dda038e9251ca7380d3717709764c580192e (diff)
downloadQt-5e9382c018e231c5e2ef49dd8a38eaff535b9837.zip
Qt-5e9382c018e231c5e2ef49dd8a38eaff535b9837.tar.gz
Qt-5e9382c018e231c5e2ef49dd8a38eaff535b9837.tar.bz2
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/qt-s60-public into master-s60
Conflicts: qmake/generators/symbian/initprojectdeploy_symbian.cpp qmake/generators/symbian/symmake_abld.h
Diffstat (limited to 'src/multimedia')
-rw-r--r--src/multimedia/audio/qaudioinput.cpp74
-rw-r--r--src/multimedia/audio/qaudioinput_alsa_p.cpp121
-rw-r--r--src/multimedia/audio/qaudioinput_win32_p.cpp42
-rw-r--r--src/multimedia/audio/qaudiooutput.cpp78
-rw-r--r--src/multimedia/audio/qaudiooutput_alsa_p.cpp64
-rw-r--r--src/multimedia/audio/qaudiooutput_win32_p.cpp62
6 files changed, 211 insertions, 230 deletions
diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp
index 45cafc1..fd892dd 100644
--- a/src/multimedia/audio/qaudioinput.cpp
+++ b/src/multimedia/audio/qaudioinput.cpp
@@ -190,18 +190,18 @@ QAudioInput::~QAudioInput()
Passing a QIODevice allows the data to be transfered without any extra code.
All that is required is to open the QIODevice.
+ If able to successfully get audio data from the systems audio device the
+ state() is set to either QAudio::ActiveState or QAudio::IdleState,
+ error() is set to QAudio::NoError and the stateChanged() signal is emitted.
+
+ If a problem occurs during this process the error() is set to QAudio::OpenError,
+ state() is set to QAudio::StoppedState and stateChanged() signal is emitted.
+
\sa QIODevice
*/
void QAudioInput::start(QIODevice* device)
{
- /*
- -If currently not StoppedState, stop
- -If previous start was push mode, delete internal QIODevice.
- -open audio input.
- If ok, NoError and ActiveState, else OpenError and StoppedState.
- -emit stateChanged()
- */
d->start(device);
}
@@ -210,19 +210,18 @@ void QAudioInput::start(QIODevice* device)
transfer. This QIODevice can be used to read() audio data
directly.
+ If able to access the systems audio device the state() is set to
+ QAudio::IdleState, error() is set to QAudio::NoError
+ and the stateChanged() signal is emitted.
+
+ If a problem occurs during this process the error() is set to QAudio::OpenError,
+ state() is set to QAudio::StoppedState and stateChanged() signal is emitted.
+
\sa QIODevice
*/
QIODevice* QAudioInput::start()
{
- /*
- -If currently not StoppedState, stop
- -If no internal QIODevice, create one.
- -open audio input.
- -If ok, NoError and IdleState, else OpenError and StoppedState
- -emit stateChanged()
- -return internal QIODevice
- */
return d->start(0);
}
@@ -236,17 +235,14 @@ QAudioFormat QAudioInput::format() const
}
/*!
- Stops the audio input.
+ Stops the audio input, detaching from the system resource.
+
+ Sets error() to QAudio::NoError, state() to QAudio::StoppedState and
+ emit stateChanged() signal.
*/
void QAudioInput::stop()
{
- /*
- -If StoppedState, return
- -set to StoppedState
- -detach from audio device
- -emit stateChanged()
- */
d->stop();
}
@@ -256,42 +252,32 @@ void QAudioInput::stop()
void QAudioInput::reset()
{
- /*
- -drop all buffered audio, set buffers to zero.
- -call stop()
- */
d->reset();
}
/*!
Stops processing audio data, preserving buffered audio data.
+
+ Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and
+ emit stateChanged() signal.
*/
void QAudioInput::suspend()
{
- /*
- -If not ActiveState|IdleState, return
- -stop processing audio, saving all buffered audio data
- -set NoError and SuspendedState
- -emit stateChanged()
- */
d->suspend();
}
/*!
Resumes processing audio data after a suspend().
+
+ Sets error() to QAudio::NoError.
+ Sets state() to QAudio::ActiveState if you previously called start(QIODevice*).
+ Sets state() to QAudio::IdleState if you previously called start().
+ emits stateChanged() signal.
*/
void QAudioInput::resume()
{
- /*
- -If SuspendedState, return
- -resume audio
- -(PULL MODE): set ActiveState, NoError
- -(PUSH MODE): set IdleState, NoError
- -kick start audio if needed
- -emit stateChanged()
- */
d->resume();
}
@@ -327,6 +313,9 @@ int QAudioInput::bufferSize() const
/*!
Returns the amount of audio data available to read in bytes.
+
+ NOTE: returned value is only valid while in QAudio::ActiveState or QAudio::IdleState
+ state, otherwise returns zero.
*/
int QAudioInput::bytesReady() const
@@ -352,7 +341,10 @@ int QAudioInput::periodSize() const
/*!
Sets the interval for notify() signal to be emitted.
This is based on the \a ms of audio data processed
- not on actual real-time. The resolution of the timer is platform specific.
+ not on actual real-time.
+ The minimum resolution of the timer is platform specific and values
+ should be checked with notifyInterval() to confirm actual value
+ being used.
*/
void QAudioInput::setNotifyInterval(int ms)
diff --git a/src/multimedia/audio/qaudioinput_alsa_p.cpp b/src/multimedia/audio/qaudioinput_alsa_p.cpp
index 26e46b3..6010f3c 100644
--- a/src/multimedia/audio/qaudioinput_alsa_p.cpp
+++ b/src/multimedia/audio/qaudioinput_alsa_p.cpp
@@ -217,9 +217,11 @@ QIODevice* QAudioInputPrivate::start(QIODevice* device)
//set to pull mode
pullMode = true;
audioSource = device;
+ deviceState = QAudio::ActiveState;
} else {
//set to push mode
pullMode = false;
+ deviceState = QAudio::IdleState;
audioSource = new InputPrivate(this);
audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
}
@@ -413,7 +415,6 @@ bool QAudioInputPrivate::open()
timer->start(period_time*chunks/2000);
errorState = QAudio::NoError;
- deviceState = QAudio::ActiveState;
totalTimeValue = 0;
@@ -439,7 +440,7 @@ int QAudioInputPrivate::bytesReady() const
if(resuming)
return period_size;
- if(deviceState != QAudio::ActiveState)
+ if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
return 0;
int frames = snd_pcm_avail_update(handle);
if((int)frames > (int)buffer_frames)
@@ -450,8 +451,8 @@ int QAudioInputPrivate::bytesReady() const
qint64 QAudioInputPrivate::read(char* data, qint64 len)
{
- Q_UNUSED(data)
Q_UNUSED(len)
+
// Read in some audio data and write it to QIODevice, pull mode
if ( !handle )
return 0;
@@ -468,7 +469,7 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len)
if (readFrames >= 0) {
err = snd_pcm_frames_to_bytes(handle, readFrames);
#ifdef DEBUG_AUDIO
- qDebug()<<QString::fromLatin1("PULL: read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData();
+ qDebug()<<QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData();
#endif
break;
} else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) {
@@ -489,28 +490,46 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len)
if(err > 0) {
// got some send it onward
#ifdef DEBUG_AUDIO
- qDebug()<<"PULL: frames to write to QIODevice = "<<
+ qDebug()<<"frames to write to QIODevice = "<<
snd_pcm_bytes_to_frames( handle, (int)err )<<" ("<<err<<") bytes";
#endif
- if(deviceState != QAudio::ActiveState)
+ if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
return 0;
+ if (pullMode) {
+ qint64 l = audioSource->write(audioBuffer,err);
+ if(l < 0) {
+ close();
+ errorState = QAudio::IOError;
+ deviceState = QAudio::StoppedState;
+ emit stateChanged(deviceState);
+ } else if(l == 0) {
+ if (deviceState != QAudio::IdleState) {
+ errorState = QAudio::NoError;
+ deviceState = QAudio::IdleState;
+ emit stateChanged(deviceState);
+ }
+ } else {
+ totalTimeValue += err;
+ resuming = false;
+ if (deviceState != QAudio::ActiveState) {
+ errorState = QAudio::NoError;
+ deviceState = QAudio::ActiveState;
+ emit stateChanged(deviceState);
+ }
+ }
+ return l;
- qint64 l = audioSource->write(audioBuffer,err);
- if(l < 0) {
- close();
- errorState = QAudio::IOError;
- deviceState = QAudio::StoppedState;
- emit stateChanged(deviceState);
- } else if(l == 0) {
- errorState = QAudio::NoError;
- deviceState = QAudio::IdleState;
} else {
- totalTimeValue += snd_pcm_bytes_to_frames(handle, err)*1000000/settings.frequency();
+ memcpy(data,audioBuffer,err);
+ totalTimeValue += err;
resuming = false;
- errorState = QAudio::NoError;
- deviceState = QAudio::ActiveState;
+ if (deviceState != QAudio::ActiveState) {
+ errorState = QAudio::NoError;
+ deviceState = QAudio::ActiveState;
+ emit stateChanged(deviceState);
+ }
+ return err;
}
- return l;
}
return 0;
}
@@ -569,7 +588,7 @@ int QAudioInputPrivate::notifyInterval() const
qint64 QAudioInputPrivate::processedUSecs() const
{
- return totalTimeValue;
+ return qint64(1000000) * totalTimeValue / settings.frequency();
}
void QAudioInputPrivate::suspend()
@@ -617,34 +636,10 @@ bool QAudioInputPrivate::deviceReady()
qint64 QAudioInputPrivate::elapsedUSecs() const
{
- if(!handle)
- return 0;
-
if (deviceState == QAudio::StoppedState)
return 0;
-#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
- snd_pcm_status_t* status;
- snd_pcm_status_alloca(&status);
-
- snd_timestamp_t t1,t2;
- if( snd_pcm_status(handle, status) >= 0) {
- snd_pcm_status_get_tstamp(status,&t1);
- snd_pcm_status_get_trigger_tstamp(status,&t2);
- t1.tv_sec-=t2.tv_sec;
-
- signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec;
- if(l < 0) {
- t1.tv_sec--;
- l = -l;
- l %= 1000000;
- }
- return ((t1.tv_sec * 1000000)+l);
- } else
- return 0;
-#else
return clockStamp.elapsed()*1000;
-#endif
}
void QAudioInputPrivate::reset()
@@ -670,43 +665,7 @@ InputPrivate::~InputPrivate()
qint64 InputPrivate::readData( char* data, qint64 len)
{
- // push mode, user read() called
- if((audioDevice->state() != QAudio::ActiveState) && !audioDevice->resuming)
- return 0;
-
- int readFrames;
- int count=0, err = 0;
-
- while(count < 5) {
- int frames = snd_pcm_bytes_to_frames(audioDevice->handle, len);
- readFrames = snd_pcm_readi(audioDevice->handle, data, frames);
- if (readFrames >= 0) {
- err = snd_pcm_frames_to_bytes(audioDevice->handle, readFrames);
-#ifdef DEBUG_AUDIO
- qDebug()<<QString::fromLatin1("PUSH: read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData();
-#endif
- break;
- } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) {
- audioDevice->errorState = QAudio::IOError;
- err = 0;
- break;
- } else {
- if(readFrames == -EPIPE) {
- audioDevice->errorState = QAudio::UnderrunError;
- err = snd_pcm_prepare(audioDevice->handle);
- } else if(readFrames == -ESTRPIPE) {
- err = snd_pcm_prepare(audioDevice->handle);
- }
- if(err != 0) break;
- }
- count++;
- }
- if(err > 0 && readFrames > 0) {
- audioDevice->totalTimeValue += readFrames*1000/audioDevice->settings.frequency()*1000;
- audioDevice->deviceState = QAudio::ActiveState;
- return err;
- }
- return 0;
+ return audioDevice->read(data,len);
}
qint64 InputPrivate::writeData(const char* data, qint64 len)
diff --git a/src/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/audio/qaudioinput_win32_p.cpp
index cc4fdee..594f6ca 100644
--- a/src/multimedia/audio/qaudioinput_win32_p.cpp
+++ b/src/multimedia/audio/qaudioinput_win32_p.cpp
@@ -192,9 +192,11 @@ QIODevice* QAudioInputPrivate::start(QIODevice* device)
//set to pull mode
pullMode = true;
audioSource = device;
+ deviceState = QAudio::ActiveState;
} else {
//set to push mode
pullMode = false;
+ deviceState = QAudio::IdleState;
audioSource = new InputPrivate(this);
audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
}
@@ -311,7 +313,6 @@ bool QAudioInputPrivate::open()
elapsedTimeOffset = 0;
totalTimeValue = 0;
errorState = QAudio::NoError;
- deviceState = QAudio::ActiveState;
return true;
}
@@ -320,9 +321,9 @@ void QAudioInputPrivate::close()
if(deviceState == QAudio::StoppedState)
return;
+ deviceState = QAudio::StoppedState;
waveInReset(hWaveIn);
waveInClose(hWaveIn);
- deviceState = QAudio::StoppedState;
int count = 0;
while(!finished && count < 500) {
@@ -357,7 +358,6 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len)
char* p = data;
qint64 l = 0;
qint64 written = 0;
-
while(!done) {
// Read in some audio data
if(waveBlocks[header].dwBytesRecorded > 0 && waveBlocks[header].dwFlags & WHDR_DONE) {
@@ -378,11 +378,12 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len)
errorState = QAudio::IOError;
} else {
- totalTimeValue += waveBlocks[header].dwBytesRecorded
- /((settings.channels()*settings.sampleSize()/8))
- *10000/settings.frequency()*100;
+ totalTimeValue += waveBlocks[header].dwBytesRecorded;
errorState = QAudio::NoError;
- deviceState = QAudio::ActiveState;
+ if (deviceState != QAudio::ActiveState) {
+ deviceState = QAudio::ActiveState;
+ emit stateChanged(deviceState);
+ }
resuming = false;
}
} else {
@@ -392,16 +393,17 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len)
#ifdef DEBUG_AUDIO
qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l;
#endif
- totalTimeValue += waveBlocks[header].dwBytesRecorded
- /((settings.channels()*settings.sampleSize()/8))
- *10000/settings.frequency()*100;
+ totalTimeValue += waveBlocks[header].dwBytesRecorded;
errorState = QAudio::NoError;
- deviceState = QAudio::ActiveState;
+ if (deviceState != QAudio::ActiveState) {
+ deviceState = QAudio::ActiveState;
+ emit stateChanged(deviceState);
+ }
resuming = false;
}
} else {
//no data, not ready yet, next time
- return 0;
+ break;
}
waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR));
@@ -510,7 +512,13 @@ int QAudioInputPrivate::notifyInterval() const
qint64 QAudioInputPrivate::processedUSecs() const
{
- return totalTimeValue;
+ if (deviceState == QAudio::StoppedState)
+ return 0;
+ qint64 result = qint64(1000000) * totalTimeValue /
+ (settings.channels()*(settings.sampleSize()/8)) /
+ settings.frequency();
+
+ return result;
}
void QAudioInputPrivate::suspend()
@@ -540,6 +548,9 @@ bool QAudioInputPrivate::deviceReady()
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT";
#endif
+ if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
+ return true;
+
if(pullMode) {
// reads some audio data and writes it to QIODevice
read(0,0);
@@ -548,8 +559,6 @@ bool QAudioInputPrivate::deviceReady()
InputPrivate* a = qobject_cast<InputPrivate*>(audioSource);
a->trigger();
}
- if(deviceState != QAudio::ActiveState)
- return true;
if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
emit notify();
@@ -582,7 +591,8 @@ InputPrivate::~InputPrivate() {}
qint64 InputPrivate::readData( char* data, qint64 len)
{
// push mode, user read() called
- if(audioDevice->deviceState != QAudio::ActiveState)
+ if(audioDevice->deviceState != QAudio::ActiveState &&
+ audioDevice->deviceState != QAudio::IdleState)
return 0;
// Read in some audio data
return audioDevice->read(data,len);
diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp
index afd8a84..b0b5244 100644
--- a/src/multimedia/audio/qaudiooutput.cpp
+++ b/src/multimedia/audio/qaudiooutput.cpp
@@ -202,18 +202,18 @@ QAudioFormat QAudioOutput::format() const
Passing a QIODevice allows the data to be transfered without any extra code.
All that is required is to open the QIODevice.
+ If able to successfully output audio data to the systems audio device the
+ state() is set to QAudio::ActiveState, error() is set to QAudio::NoError
+ and the stateChanged() signal is emitted.
+
+ If a problem occurs during this process the error() is set to QAudio::OpenError,
+ state() is set to QAudio::StoppedState and stateChanged() signal is emitted.
+
\sa QIODevice
*/
void QAudioOutput::start(QIODevice* device)
{
- /*
- -If currently not StoppedState, stop.
- -If previous start was push mode, delete internal QIODevice.
- -open audio output.
- -If ok, NoError and ActiveState, else OpenError and StoppedState
- -emit stateChanged()
- */
d->start(device);
}
@@ -221,34 +221,30 @@ void QAudioOutput::start(QIODevice* device)
Returns a pointer to the QIODevice being used to handle the data
transfer. This QIODevice can be used to write() audio data directly.
+ If able to access the systems audio device the state() is set to
+ QAudio::IdleState, error() is set to QAudio::NoError
+ and the stateChanged() signal is emitted.
+
+ If a problem occurs during this process the error() is set to QAudio::OpenError,
+ state() is set to QAudio::StoppedState and stateChanged() signal is emitted.
+
\sa QIODevice
*/
QIODevice* QAudioOutput::start()
{
- /*
- -If currently not StoppedState, stop.
- -If no internal QIODevice, create one.
- -open audio output.
- -If ok, NoError and IdleState, else OpenError and StoppedState
- -emit stateChanged()
- -return internal QIODevice
- */
return d->start(0);
}
/*!
- Stops the audio output.
+ Stops the audio output, detaching from the system resource.
+
+ Sets error() to QAudio::NoError, state() to QAudio::StoppedState and
+ emit stateChanged() signal.
*/
void QAudioOutput::stop()
{
- /*
- -If StoppedState, return
- -set to StoppedState
- -detach from audio device
- -emit stateChanged()
- */
d->stop();
}
@@ -258,55 +254,44 @@ void QAudioOutput::stop()
void QAudioOutput::reset()
{
- /*
- -drop all buffered audio, set buffers to zero.
- -call stop()
- */
d->reset();
}
/*!
Stops processing audio data, preserving buffered audio data.
+
+ Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and
+ emit stateChanged() signal.
*/
void QAudioOutput::suspend()
{
- /*
- -If not ActiveState|IdleState, return
- -stop processing audio, saving all buffered audio data
- -set NoError and SuspendedState
- -emit stateChanged()
- */
d->suspend();
}
/*!
Resumes processing audio data after a suspend().
+
+ Sets error() to QAudio::NoError.
+ Sets state() to QAudio::ActiveState if you previously called start(QIODevice*).
+ Sets state() to QAudio::IdleState if you previously called start().
+ emits stateChanged() signal.
*/
void QAudioOutput::resume()
{
- /*
- -If SuspendedState, return
- -resume audio
- -(PULL MODE): set ActiveState, NoError
- -(PUSH MODE): set IdleState, NoError
- -kick start audio if needed
- -emit stateChanged()
- */
d->resume();
}
/*!
Returns the free space available in bytes in the audio buffer.
+
+ NOTE: returned value is only valid while in QAudio::ActiveState or QAudio::IdleState
+ state, otherwise returns zero.
*/
int QAudioOutput::bytesFree() const
{
- /*
- -If not ActiveState|IdleState, return 0
- -return space available in audio buffer in bytes
- */
return d->bytesFree();
}
@@ -353,7 +338,10 @@ int QAudioOutput::bufferSize() const
/*!
Sets the interval for notify() signal to be emitted.
This is based on the \a ms of audio data processed
- not on actual real-time. The resolution of the timer is platform specific.
+ not on actual real-time.
+ The minimum resolution of the timer is platform specific and values
+ should be checked with notifyInterval() to confirm actual value
+ being used.
*/
void QAudioOutput::setNotifyInterval(int ms)
diff --git a/src/multimedia/audio/qaudiooutput_alsa_p.cpp b/src/multimedia/audio/qaudiooutput_alsa_p.cpp
index 7b89cef..b127103 100644
--- a/src/multimedia/audio/qaudiooutput_alsa_p.cpp
+++ b/src/multimedia/audio/qaudiooutput_alsa_p.cpp
@@ -259,6 +259,7 @@ void QAudioOutputPrivate::stop()
{
if(deviceState == QAudio::StoppedState)
return;
+ errorState = QAudio::NoError;
deviceState = QAudio::StoppedState;
close();
emit stateChanged(deviceState);
@@ -494,10 +495,13 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len )
err = snd_pcm_writei( handle, data, frames );
}
if(err > 0) {
- totalTimeValue += err*1000000/settings.frequency();
+ totalTimeValue += err;
resuming = false;
errorState = QAudio::NoError;
- deviceState = QAudio::ActiveState;
+ if (deviceState != QAudio::ActiveState) {
+ deviceState = QAudio::ActiveState;
+ emit stateChanged(deviceState);
+ }
return snd_pcm_frames_to_bytes( handle, err );
} else
err = xrun_recovery(err);
@@ -542,7 +546,7 @@ int QAudioOutputPrivate::notifyInterval() const
qint64 QAudioOutputPrivate::processedUSecs() const
{
- return totalTimeValue;
+ return qint64(1000000) * totalTimeValue / settings.frequency();
}
void QAudioOutputPrivate::resume()
@@ -562,10 +566,8 @@ void QAudioOutputPrivate::resume()
bytesAvailable = (int)snd_pcm_frames_to_bytes(handle, buffer_frames);
}
resuming = true;
- if(pullMode)
- deviceState = QAudio::ActiveState;
- else
- deviceState = QAudio::IdleState;
+
+ deviceState = QAudio::ActiveState;
errorState = QAudio::NoError;
timer->start(period_time/1000);
@@ -637,7 +639,9 @@ bool QAudioOutputPrivate::deviceReady()
// Got some data to output
if(deviceState != QAudio::ActiveState)
return true;
- write(audioBuffer,l);
+ qint64 bytesWritten = write(audioBuffer,l);
+ if (bytesWritten != l)
+ audioSource->seek(audioSource->pos()-(l-bytesWritten));
bytesAvailable = bytesFree();
} else if(l == 0) {
@@ -645,9 +649,11 @@ bool QAudioOutputPrivate::deviceReady()
bytesAvailable = bytesFree();
if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) {
// Underrun
- errorState = QAudio::UnderrunError;
- deviceState = QAudio::IdleState;
- emit stateChanged(deviceState);
+ if (deviceState != QAudio::IdleState) {
+ errorState = QAudio::UnderrunError;
+ deviceState = QAudio::IdleState;
+ emit stateChanged(deviceState);
+ }
}
} else if(l < 0) {
@@ -655,8 +661,17 @@ bool QAudioOutputPrivate::deviceReady()
errorState = QAudio::IOError;
emit stateChanged(deviceState);
}
- } else
+ } else {
bytesAvailable = bytesFree();
+ if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) {
+ // Underrun
+ if (deviceState != QAudio::IdleState) {
+ errorState = QAudio::UnderrunError;
+ deviceState = QAudio::IdleState;
+ emit stateChanged(deviceState);
+ }
+ }
+ }
if(deviceState != QAudio::ActiveState)
return true;
@@ -671,35 +686,10 @@ bool QAudioOutputPrivate::deviceReady()
qint64 QAudioOutputPrivate::elapsedUSecs() const
{
- if(!handle)
- return 0;
-
if (deviceState == QAudio::StoppedState)
return 0;
-#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
- snd_pcm_status_t* status;
- snd_pcm_status_alloca(&status);
-
- snd_timestamp_t t1,t2;
- if( snd_pcm_status(handle, status) >= 0) {
- snd_pcm_status_get_tstamp(status,&t1);
- snd_pcm_status_get_trigger_tstamp(status,&t2);
- t1.tv_sec-=t2.tv_sec;
-
- signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec;
- if(l < 0) {
- t1.tv_sec--;
- l = -l;
- l %= 1000000;
- }
- return ((t1.tv_sec * 1000000)+l);
- } else
- return 0;
-#else
return clockStamp.elapsed()*1000;
-#endif
- return 0;
}
void QAudioOutputPrivate::reset()
diff --git a/src/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/audio/qaudiooutput_win32_p.cpp
index bce45c1..6200160 100644
--- a/src/multimedia/audio/qaudiooutput_win32_p.cpp
+++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp
@@ -211,6 +211,13 @@ bool QAudioOutputPrivate::open()
QTime now(QTime::currentTime());
qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
#endif
+ if (!(settings.frequency() >= 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 @@ void QAudioOutputPrivate::close()
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 @@ int QAudioOutputPrivate::notifyInterval() const
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 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len )
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::resume()
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);
@@ -465,8 +487,16 @@ bool QAudioOutputPrivate::deviceReady()
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 +508,28 @@ bool QAudioOutputPrivate::deviceReady()
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) {