Merge remote-tracking branch 'remotes/kraxel/tags/audio-20190318-pull-request' into staging

audio: pulseaudio fixes for 4.0

# gpg: Signature made Mon 18 Mar 2019 12:08:50 GMT
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/audio-20190318-pull-request:
  audio/paaudio: fix microphone input being unusable
  audio/paaudio: prolong and make latency configurable
  audio/paaudio: fix ignored buffer_length setting

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/audio/paaudio.c b/audio/paaudio.c
index 5d410ed..45295b4 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -549,12 +549,8 @@
     ss.channels = as->nchannels;
     ss.rate = as->freq;
 
-    /*
-     * qemu audio tick runs at 100 Hz (by default), so processing
-     * data chunks worth 10 ms of sound should be a good fit.
-     */
-    ba.tlength = pa_usec_to_bytes (10 * 1000, &ss);
-    ba.minreq = pa_usec_to_bytes (5 * 1000, &ss);
+    ba.tlength = pa_usec_to_bytes(ppdo->latency, &ss);
+    ba.minreq = -1;
     ba.maxlength = -1;
     ba.prebuf = -1;
 
@@ -577,7 +573,8 @@
 
     audio_pcm_init_info (&hw->info, &obt_as);
     hw->samples = pa->samples = audio_buffer_samples(
-        qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, 46440);
+        qapi_AudiodevPaPerDirectionOptions_base(ppdo),
+        &obt_as, ppdo->buffer_length);
     pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
     pa->rpos = hw->rpos;
     if (!pa->pcm_buf) {
@@ -608,6 +605,7 @@
 {
     int error;
     pa_sample_spec ss;
+    pa_buffer_attr ba;
     struct audsettings obt_as = *as;
     PAVoiceIn *pa = (PAVoiceIn *) hw;
     paaudio *g = pa->g = drv_opaque;
@@ -618,6 +616,11 @@
     ss.channels = as->nchannels;
     ss.rate = as->freq;
 
+    ba.fragsize = pa_usec_to_bytes(ppdo->latency, &ss);
+    ba.maxlength = -1;
+    ba.minreq = -1;
+    ba.prebuf = -1;
+
     obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
 
     pa->stream = qpa_simple_new (
@@ -627,7 +630,7 @@
         ppdo->has_name ? ppdo->name : NULL,
         &ss,
         NULL,                   /* channel map */
-        NULL,                   /* buffering attributes */
+        &ba,                    /* buffering attributes */
         &error
         );
     if (!pa->stream) {
@@ -637,7 +640,8 @@
 
     audio_pcm_init_info (&hw->info, &obt_as);
     hw->samples = pa->samples = audio_buffer_samples(
-        qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, 46440);
+        qapi_AudiodevPaPerDirectionOptions_base(ppdo),
+        &obt_as, ppdo->buffer_length);
     pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
     pa->wpos = hw->wpos;
     if (!pa->pcm_buf) {
@@ -809,7 +813,20 @@
     return 0;
 }
 
-/* common */
+static int qpa_validate_per_direction_opts(Audiodev *dev,
+                                           AudiodevPaPerDirectionOptions *pdo)
+{
+    if (!pdo->has_buffer_length) {
+        pdo->has_buffer_length = true;
+        pdo->buffer_length = 46440;
+    }
+    if (!pdo->has_latency) {
+        pdo->has_latency = true;
+        pdo->latency = 15000;
+    }
+    return 1;
+}
+
 static void *qpa_audio_init(Audiodev *dev)
 {
     paaudio *g;
@@ -836,6 +853,13 @@
     g = g_malloc(sizeof(paaudio));
     server = popts->has_server ? popts->server : NULL;
 
+    if (!qpa_validate_per_direction_opts(dev, popts->in)) {
+        goto fail;
+    }
+    if (!qpa_validate_per_direction_opts(dev, popts->out)) {
+        goto fail;
+    }
+
     g->dev = dev;
     g->mainloop = NULL;
     g->context = NULL;
diff --git a/qapi/audio.json b/qapi/audio.json
index 97aee37..9fefdf5 100644
--- a/qapi/audio.json
+++ b/qapi/audio.json
@@ -206,12 +206,16 @@
 #
 # @name: name of the sink/source to use
 #
+# @latency: latency you want PulseAudio to achieve in microseconds
+#           (default 15000)
+#
 # Since: 4.0
 ##
 { 'struct': 'AudiodevPaPerDirectionOptions',
   'base': 'AudiodevPerDirectionOptions',
   'data': {
-    '*name': 'str' } }
+    '*name': 'str',
+    '*latency': 'uint32' } }
 
 ##
 # @AudiodevPaOptions: