From patchwork Fri Aug 21 15:37:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?UTF-8?B?Wm9sdMOhbiBLxZF2w6Fnw7M=?= X-Patchwork-Id: 509576 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 944E21402C8 for ; Sat, 22 Aug 2015 02:13:25 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=GJ9ECguP; dkim-atps=neutral Received: from localhost ([::1]:42546 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZSowV-0004dQ-CO for incoming@patchwork.ozlabs.org; Fri, 21 Aug 2015 12:13:23 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51055) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZSoOU-0002u3-Ki for qemu-devel@nongnu.org; Fri, 21 Aug 2015 11:38:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZSoOP-0002BR-IE for qemu-devel@nongnu.org; Fri, 21 Aug 2015 11:38:14 -0400 Received: from mail-wi0-x22a.google.com ([2a00:1450:400c:c05::22a]:33823) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZSoOP-0002BF-8l for qemu-devel@nongnu.org; Fri, 21 Aug 2015 11:38:09 -0400 Received: by wicne3 with SMTP id ne3so23100450wic.1 for ; Fri, 21 Aug 2015 08:38:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=zlyosED+Sh/B0cPkbekAOIRV/hVJmVwVvYp0TtGUc60=; b=GJ9ECguPhtwPb0lXqQzbgPKSJiOTXP46Pg2GXEvIJBkXAgFBUawYuq7J2IJFYKzAPZ lyArMpvo9LqkAQUnRyGIrw+LR8TVPxu6Okwi/A/lqbEEAU5+JmtUASP5QFDMbDkXX0Ue IBlRQjI1qW42mLVkWsrknHoPyMClFa8dlcSUKMeaiXRWhXPDn7lOUDBqXufKhd8KFfkI nKjOykkayrYdC8Oh9/E12CmOtyONTQcU6Chw7G50gCahk17VG0TqMqllZpsEGDNwpgkA EwTiF5RCugcIIi+lAM0/neyAwdyp1oe2yFDuPD1xuI5IexHiNDBJrwmFYtXqtrvFzA0g AmuQ== X-Received: by 10.180.74.141 with SMTP id t13mr6636284wiv.71.1440171488671; Fri, 21 Aug 2015 08:38:08 -0700 (PDT) Received: from nullptr.home.dirty-ice.org (178-164-172-216.pool.digikabel.hu. [178.164.172.216]) by smtp.gmail.com with ESMTPSA id v8sm10479895wjr.15.2015.08.21.08.38.08 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 21 Aug 2015 08:38:08 -0700 (PDT) From: "=?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?=" X-Google-Original-From: =?UTF-8?q?K=C5=91v=C3=A1g=C3=B3=2C=20Zolt=C3=A1n?= To: qemu-devel@nongnu.org Date: Fri, 21 Aug 2015 17:37:32 +0200 Message-Id: X-Mailer: git-send-email 2.5.0 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:400c:c05::22a Cc: Gerd Hoffmann Subject: [Qemu-devel] [PATCH v2 36/49] alsaaudio: port to the new audio backend api X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Kővágó, Zoltán --- audio/alsaaudio.c | 306 +++++++++++++++--------------------------------------- 1 file changed, 81 insertions(+), 225 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 8199b71..c64bbc6 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -45,9 +45,6 @@ struct pollhlp { typedef struct ALSAVoiceOut { HWVoiceOut hw; - int wpos; - int pending; - void *pcm_buf; snd_pcm_t *handle; struct pollhlp pollhlp; Audiodev *dev; @@ -56,7 +53,6 @@ typedef struct ALSAVoiceOut { typedef struct ALSAVoiceIn { HWVoiceIn hw; snd_pcm_t *handle; - void *pcm_buf; struct pollhlp pollhlp; Audiodev *dev; } ALSAVoiceIn; @@ -611,102 +607,62 @@ static int alsa_open(bool in, struct alsa_params_req *req, return -1; } -static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle) -{ - snd_pcm_sframes_t avail; - - avail = snd_pcm_avail_update (handle); - if (avail < 0) { - if (avail == -EPIPE) { - if (!alsa_recover (handle)) { - avail = snd_pcm_avail_update (handle); - } - } - - if (avail < 0) { - alsa_logerr (avail, - "Could not obtain number of available frames\n"); - return -1; - } - } - - return avail; -} - -static void alsa_write_pending (ALSAVoiceOut *alsa) -{ - HWVoiceOut *hw = &alsa->hw; - - while (alsa->pending) { - int left_till_end_samples = hw->samples - alsa->wpos; - int len = MIN (alsa->pending, left_till_end_samples); - char *src = advance (alsa->pcm_buf, alsa->wpos << hw->info.shift); - - while (len) { - snd_pcm_sframes_t written; - - written = snd_pcm_writei (alsa->handle, src, len); - - if (written <= 0) { - switch (written) { - case 0: - trace_alsa_wrote_zero(len); - return; - - case -EPIPE: - if (alsa_recover (alsa->handle)) { - alsa_logerr (written, "Failed to write %d frames\n", - len); - return; - } - trace_alsa_xrun_out(); - continue; - - case -ESTRPIPE: - /* stream is suspended and waiting for an - application recovery */ - if (alsa_resume (alsa->handle)) { - alsa_logerr (written, "Failed to write %d frames\n", - len); - return; - } - trace_alsa_resume_out(); - continue; - - case -EAGAIN: - return; - - default: - alsa_logerr (written, "Failed to write %d frames from %p\n", - len, src); - return; - } - } - - alsa->wpos = (alsa->wpos + written) % hw->samples; - alsa->pending -= written; - len -= written; - } - } -} - -static int alsa_run_out (HWVoiceOut *hw, int live) +static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len) { ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; - int decr; - snd_pcm_sframes_t avail; + size_t pos = 0; + size_t len_frames = len >> hw->info.shift; - avail = alsa_get_avail (alsa->handle); - if (avail < 0) { - dolog ("Could not get number of available playback frames\n"); - return 0; + while (len_frames) { + char *src = advance(buf, pos); + snd_pcm_sframes_t written; + + written = snd_pcm_writei(alsa->handle, src, len_frames); + + if (written <= 0) { + switch (written) { + case 0: + trace_alsa_wrote_zero(len_frames); + return pos; + + case -EPIPE: + if (alsa_recover(alsa->handle)) { + alsa_logerr(written, "Failed to write %zu frames\n", + len_frames); + return pos; + } + trace_alsa_xrun_out(); + continue; + + case -ESTRPIPE: + /* stream is suspended and waiting for an + application recovery */ + if (alsa_resume(alsa->handle)) { + alsa_logerr(written, "Failed to write %zu frames\n", + len_frames); + return pos; + } + trace_alsa_resume_out(); + continue; + + case -EAGAIN: + return pos; + + default: + alsa_logerr(written, "Failed to write %zu frames from %p\n", + len, src); + return pos; + } + } + + pos += written << hw->info.shift; + if (written < len_frames) { + break; + } + len_frames -= written; } - decr = MIN (live, avail); - decr = audio_pcm_hw_clip_out (hw, alsa->pcm_buf, decr, alsa->pending); - alsa->pending += decr; - alsa_write_pending (alsa); - return decr; + return pos; } static void alsa_fini_out (HWVoiceOut *hw) @@ -715,9 +671,6 @@ static void alsa_fini_out (HWVoiceOut *hw) ldebug ("alsa_fini\n"); alsa_anal_close (&alsa->handle, &alsa->pollhlp); - - g_free(alsa->pcm_buf); - alsa->pcm_buf = NULL; } static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, @@ -746,14 +699,6 @@ static int alsa_init_out(HWVoiceOut *hw, struct audsettings *as, audio_pcm_init_info (&hw->info, &obt_as); hw->samples = obt.samples; - alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift); - if (!alsa->pcm_buf) { - dolog("Could not allocate DAC buffer (%zu samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); - alsa_anal_close1 (&handle); - return -1; - } - alsa->pollhlp.s = hw->s; alsa->handle = handle; alsa->dev = dev; @@ -848,14 +793,6 @@ static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) audio_pcm_init_info (&hw->info, &obt_as); hw->samples = obt.samples; - alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); - if (!alsa->pcm_buf) { - dolog("Could not allocate ADC buffer (%zu samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); - alsa_anal_close1 (&handle); - return -1; - } - alsa->pollhlp.s = hw->s; alsa->handle = handle; alsa->dev = dev; @@ -867,129 +804,48 @@ static void alsa_fini_in (HWVoiceIn *hw) ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; alsa_anal_close (&alsa->handle, &alsa->pollhlp); - - g_free(alsa->pcm_buf); - alsa->pcm_buf = NULL; } -static int alsa_run_in (HWVoiceIn *hw) +static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len) { ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; - int hwshift = hw->info.shift; - int i; - int live = audio_pcm_hw_get_live_in (hw); - int dead = hw->samples - live; - int decr; - struct { - int add; - int len; - } bufs[2] = { - { .add = hw->wpos, .len = 0 }, - { .add = 0, .len = 0 } - }; - snd_pcm_sframes_t avail; - snd_pcm_uframes_t read_samples = 0; + size_t pos = 0; - if (!dead) { - return 0; - } - - avail = alsa_get_avail (alsa->handle); - if (avail < 0) { - dolog ("Could not get number of captured frames\n"); - return 0; - } - - if (!avail) { - snd_pcm_state_t state; - - state = snd_pcm_state (alsa->handle); - switch (state) { - case SND_PCM_STATE_PREPARED: - avail = hw->samples; - break; - case SND_PCM_STATE_SUSPENDED: - /* stream is suspended and waiting for an application recovery */ - if (alsa_resume (alsa->handle)) { - dolog ("Failed to resume suspended input stream\n"); - return 0; - } - trace_alsa_resume_in(); - break; - default: - trace_alsa_no_frames(state); - return 0; - } - } - - decr = MIN (dead, avail); - if (!decr) { - return 0; - } - - if (hw->wpos + decr > hw->samples) { - bufs[0].len = (hw->samples - hw->wpos); - bufs[1].len = (decr - (hw->samples - hw->wpos)); - } - else { - bufs[0].len = decr; - } - - for (i = 0; i < 2; ++i) { - void *src; - struct st_sample *dst; + while (len) { + void *dst = advance(buf, pos); snd_pcm_sframes_t nread; - snd_pcm_uframes_t len; - len = bufs[i].len; + nread = snd_pcm_readi(alsa->handle, dst, len >> hw->info.shift); - src = advance (alsa->pcm_buf, bufs[i].add << hwshift); - dst = hw->conv_buf + bufs[i].add; + if (nread <= 0) { + switch (nread) { + case 0: + trace_alsa_read_zero(len); + return pos;; - while (len) { - nread = snd_pcm_readi (alsa->handle, src, len); - - if (nread <= 0) { - switch (nread) { - case 0: - trace_alsa_read_zero(len); - goto exit; - - case -EPIPE: - if (alsa_recover (alsa->handle)) { - alsa_logerr (nread, "Failed to read %ld frames\n", len); - goto exit; - } - trace_alsa_xrun_in(); - continue; - - case -EAGAIN: - goto exit; - - default: - alsa_logerr ( - nread, - "Failed to read %ld frames from %p\n", - len, - src - ); - goto exit; + case -EPIPE: + if (alsa_recover(alsa->handle)) { + alsa_logerr(nread, "Failed to read %zu frames\n", len); + return pos; } + trace_alsa_xrun_in(); + continue; + + case -EAGAIN: + return pos; + + default: + alsa_logerr(nread, "Failed to read %zu frames to %p\n", + len, dst); + return pos;; } - - hw->conv (dst, src, nread); - - src = advance (src, nread << hwshift); - dst += nread; - - read_samples += nread; - len -= nread; } + + pos += nread << hw->info.shift; + len -= nread << hw->info.shift; } - exit: - hw->wpos = (hw->wpos + read_samples) % hw->samples; - return read_samples; + return pos; } static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -1056,12 +912,12 @@ static void alsa_audio_fini (void *opaque) static struct audio_pcm_ops alsa_pcm_ops = { .init_out = alsa_init_out, .fini_out = alsa_fini_out, - .run_out = alsa_run_out, + .write = alsa_write, .ctl_out = alsa_ctl_out, .init_in = alsa_init_in, .fini_in = alsa_fini_in, - .run_in = alsa_run_in, + .read = alsa_read, .ctl_in = alsa_ctl_in, };