src/multimedia/audio/qaudioinput_alsa_p.cpp
changeset 33 3e2da88830cd
parent 23 89e065397ea6
--- a/src/multimedia/audio/qaudioinput_alsa_p.cpp	Tue Jul 06 15:10:48 2010 +0300
+++ b/src/multimedia/audio/qaudioinput_alsa_p.cpp	Wed Aug 18 10:37:55 2010 +0300
@@ -120,7 +120,7 @@
         if(err < 0)
             reset = true;
         else {
-            bytesAvailable = bytesReady();
+            bytesAvailable = checkBytesReady();
             if (bytesAvailable <= 0)
                 reset = true;
         }
@@ -408,7 +408,7 @@
     snd_pcm_start(handle);
 
     // Step 5: Setup timer
-    bytesAvailable = bytesReady();
+    bytesAvailable = checkBytesReady();
 
     if(pullMode)
         connect(audioSource,SIGNAL(readyRead()),this,SLOT(userFeed()));
@@ -437,19 +437,29 @@
     }
 }
 
-int QAudioInputPrivate::bytesReady() const
+int QAudioInputPrivate::checkBytesReady()
 {
     if(resuming)
-        return period_size;
+        bytesAvailable = period_size;
+    else if(deviceState != QAudio::ActiveState
+            && deviceState != QAudio::IdleState)
+        bytesAvailable = 0;
+    else {
+        int frames = snd_pcm_avail_update(handle);
+        if (frames < 0) {
+            bytesAvailable = frames;
+        } else {
+            if((int)frames > (int)buffer_frames)
+                frames = buffer_frames;
+            bytesAvailable = snd_pcm_frames_to_bytes(handle, frames);
+        }
+    }
+    return bytesAvailable;
+}
 
-    if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
-        return 0;
-    int frames = snd_pcm_avail_update(handle);
-    if (frames < 0) return frames;
-    if((int)frames > (int)buffer_frames)
-        frames = buffer_frames;
-
-    return snd_pcm_frames_to_bytes(handle, frames);
+int QAudioInputPrivate::bytesReady() const
+{
+    return qMax(bytesAvailable, 0);
 }
 
 qint64 QAudioInputPrivate::read(char* data, qint64 len)
@@ -460,12 +470,12 @@
     if ( !handle )
         return 0;
 
-    bytesAvailable = bytesReady();
+    bytesAvailable = checkBytesReady();
 
     if (bytesAvailable < 0) {
         // bytesAvailable as negative is error code, try to recover from it.
         xrun_recovery(bytesAvailable);
-        bytesAvailable = bytesReady();
+        bytesAvailable = checkBytesReady();
         if (bytesAvailable < 0) {
             // recovery failed must stop and set error.
             close();
@@ -639,11 +649,25 @@
         InputPrivate* a = qobject_cast<InputPrivate*>(audioSource);
         a->trigger();
     }
-    bytesAvailable = bytesReady();
+    bytesAvailable = checkBytesReady();
 
     if(deviceState != QAudio::ActiveState)
         return true;
 
+    if (bytesAvailable < 0) {
+        // bytesAvailable as negative is error code, try to recover from it.
+        xrun_recovery(bytesAvailable);
+        bytesAvailable = checkBytesReady();
+        if (bytesAvailable < 0) {
+            // recovery failed must stop and set error.
+            close();
+            errorState = QAudio::IOError;
+            deviceState = QAudio::StoppedState;
+            emit stateChanged(deviceState);
+            return 0;
+        }
+    }
+
     if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
         emit notify();
         elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;