From patchwork Fri Aug 21 15:37:36 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: 509575 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 61BCD1402C8 for ; Sat, 22 Aug 2015 02:11:30 +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=PRZ1l8EV; dkim-atps=neutral Received: from localhost ([::1]:42492 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZSoue-0001iF-69 for incoming@patchwork.ozlabs.org; Fri, 21 Aug 2015 12:11:28 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51042) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZSoOT-0002sm-VZ for qemu-devel@nongnu.org; Fri, 21 Aug 2015 11:38:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZSoOS-0002Cq-A4 for qemu-devel@nongnu.org; Fri, 21 Aug 2015 11:38:13 -0400 Received: from mail-wi0-x234.google.com ([2a00:1450:400c:c05::234]:37639) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZSoOS-0002Ca-0d for qemu-devel@nongnu.org; Fri, 21 Aug 2015 11:38:12 -0400 Received: by widdq5 with SMTP id dq5so19221509wid.0 for ; Fri, 21 Aug 2015 08:38:11 -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=/K+9A7ci2pNIhk4hlAi46qLTHbVMpq/Zoaa2ZOAabi0=; b=PRZ1l8EVxmviW0pyTaBFXo2eFWvo1n4w3Or9QUq3l4rgvMc+LXTgbotq5CthN8T2Nn HisihZtRc/t/mPNvK+NiUmDKdiyUJ2t8NtFwZk8xUAZ3KO8jhK3fljkdQociC//bZMPK bm6hc+eciSNN32gVM4QQMyNFLDFqoPh6+URgHrZKv+Yg12/YtofxadCaiVMFTx8ZoxJq pW1VxCxpfijCGzr5lMRY1FPJlFrEHrlLTNk3ZluGsYFrCpqyG/Ief8BVD0FYUjJj9KiQ gzTyqL41eqm1/c98cAJyTVBkUOOl9fDsoQraOU3H97wXmB33dSb2UIxWfPkNFxY46TVJ XppA== X-Received: by 10.194.122.97 with SMTP id lr1mr16722857wjb.26.1440171491454; Fri, 21 Aug 2015 08:38:11 -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.10 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 21 Aug 2015 08:38:11 -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:36 +0200 Message-Id: <42e842c87781ca306f77b605caa0cb01c808dec6.1440171025.git.DirtY.iCE.hu@gmail.com> 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::234 Cc: Gerd Hoffmann Subject: [Qemu-devel] [PATCH v2 40/49] ossaudio: 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/ossaudio.c | 289 ++++++++++++++++++++----------------------------------- 1 file changed, 104 insertions(+), 185 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index a4a9a5a..420f984 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -42,19 +42,15 @@ typedef struct OSSVoiceOut { HWVoiceOut hw; - void *pcm_buf; int fd; - int wpos; int nfrags; int fragsize; int mmapped; - int pending; Audiodev *dev; } OSSVoiceOut; typedef struct OSSVoiceIn { HWVoiceIn hw; - void *pcm_buf; int fd; int nfrags; int fragsize; @@ -373,97 +369,87 @@ static int oss_open(int in, struct oss_params *req, audsettings *as, return -1; } -static void oss_write_pending (OSSVoiceOut *oss) +static size_t oss_get_available_bytes(OSSVoiceOut *oss) { - HWVoiceOut *hw = &oss->hw; + int err; + struct count_info cntinfo; + assert(oss->mmapped); + err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); + if (err < 0) { + oss_logerr(errno, "SNDCTL_DSP_GETOPTR failed\n"); + return 0; + } + + return audio_ring_dist(cntinfo.ptr, oss->hw.pos_emul, oss->hw.size_emul); +} + +static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size) +{ + OSSVoiceOut *oss = (OSSVoiceOut *) hw; + if (oss->mmapped) { + *size = MIN(oss_get_available_bytes(oss), hw->size_emul - hw->pos_emul); + return hw->buf_emul + hw->pos_emul; + } else { + return audio_generic_get_buffer_out(hw, size); + } +} + +static size_t oss_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) +{ + OSSVoiceOut *oss = (OSSVoiceOut *) hw; if (oss->mmapped) { - return; + assert(buf == hw->buf_emul + hw->pos_emul && size < hw->size_emul); + + hw->pos_emul = (hw->pos_emul + size) % hw->size_emul; + return size; + } else { + return audio_generic_put_buffer_out(hw, buf, size); + } +} + +static size_t oss_write(HWVoiceOut *hw, void *buf, size_t len) +{ + OSSVoiceOut *oss = (OSSVoiceOut *) hw; + size_t pos; + + if (oss->mmapped) { + size_t total_len; + len = MIN(len, oss_get_available_bytes(oss)); + + total_len = len; + while (len) { + size_t to_copy = MIN(len, hw->size_emul - hw->pos_emul); + memcpy(hw->buf_emul + hw->pos_emul, buf, to_copy); + + hw->pos_emul = (hw->pos_emul + to_copy) % hw->pos_emul; + buf += to_copy; + len -= to_copy; + } + return total_len; } - while (oss->pending) { - int samples_written; + pos = 0; + while (len) { ssize_t bytes_written; - int samples_till_end = hw->samples - oss->wpos; - int samples_to_write = MIN (oss->pending, samples_till_end); - int bytes_to_write = samples_to_write << hw->info.shift; - void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift); + void *pcm = advance(buf, pos); - bytes_written = write (oss->fd, pcm, bytes_to_write); + bytes_written = write(oss->fd, pcm, len); if (bytes_written < 0) { if (errno != EAGAIN) { - oss_logerr (errno, "failed to write %d bytes\n", - bytes_to_write); + oss_logerr(errno, "failed to write %zu bytes\n", + len); } - break; - } - - if (bytes_written & hw->info.align) { - dolog ("misaligned write asked for %d, but got %zd\n", - bytes_to_write, bytes_written); - return; + return pos; } - samples_written = bytes_written >> hw->info.shift; - oss->pending -= samples_written; - oss->wpos = (oss->wpos + samples_written) % hw->samples; - if (bytes_written - bytes_to_write) { + pos += bytes_written; + if (bytes_written < len) { break; } + len -= bytes_written; } -} - -static int oss_run_out (HWVoiceOut *hw, int live) -{ - OSSVoiceOut *oss = (OSSVoiceOut *) hw; - int err, decr; - struct audio_buf_info abinfo; - struct count_info cntinfo; - int bufsize; - - bufsize = hw->samples << hw->info.shift; - - if (oss->mmapped) { - int bytes, pos; - - err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); - if (err < 0) { - oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); - return 0; - } - - pos = hw->rpos << hw->info.shift; - bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize); - decr = MIN (bytes >> hw->info.shift, live); - } - else { - err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo); - if (err < 0) { - oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); - return 0; - } - - if (abinfo.bytes > bufsize) { - trace_oss_invalid_available_size(abinfo.bytes, bufsize); - abinfo.bytes = bufsize; - } - - if (abinfo.bytes < 0) { - trace_oss_invalid_available_size(abinfo.bytes, bufsize); - return 0; - } - - decr = MIN (abinfo.bytes >> hw->info.shift, live); - if (!decr) { - return 0; - } - } - - decr = audio_pcm_hw_clip_out (hw, oss->pcm_buf, decr, oss->pending); - oss->pending += decr; - oss_write_pending (oss); - - return decr; + return pos; } static void oss_fini_out (HWVoiceOut *hw) @@ -474,18 +460,13 @@ static void oss_fini_out (HWVoiceOut *hw) ldebug ("oss_fini\n"); oss_anal_close (&oss->fd); - if (oss->pcm_buf) { - if (oss->mmapped) { - err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); - if (err) { - oss_logerr(errno, "Failed to unmap buffer %p, size %zu\n", - oss->pcm_buf, hw->samples << hw->info.shift); - } + if (oss->mmapped && hw->buf_emul) { + err = munmap(hw->buf_emul, hw->size_emul); + if (err) { + oss_logerr(errno, "Failed to unmap buffer %p, size %zu\n", + hw->buf_emul, hw->size_emul); } - else { - g_free (oss->pcm_buf); - } - oss->pcm_buf = NULL; + hw->buf_emul = NULL; } } @@ -536,19 +517,20 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, oss->mmapped = 0; if (oopts->has_try_mmap && oopts->try_mmap) { - oss->pcm_buf = mmap ( + hw->size_emul = hw->samples << hw->info.shift; + hw->buf_emul = mmap ( NULL, - hw->samples << hw->info.shift, + hw->size_emul, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); - if (oss->pcm_buf == MAP_FAILED) { + if (hw->buf_emul == MAP_FAILED) { oss_logerr(errno, "Failed to map %zu bytes of DAC\n", - hw->samples << hw->info.shift); - } - else { + hw->size_emul); + hw->buf_emul = NULL; + } else { int err; int trig = 0; if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { @@ -568,32 +550,16 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, } if (!oss->mmapped) { - err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); + err = munmap(hw->buf_emul, hw->size_emul); if (err) { oss_logerr(errno, "Failed to unmap buffer %p size %zu\n", - oss->pcm_buf, hw->samples << hw->info.shift); + hw->buf_emul, hw->size_emul); } + hw->buf_emul = NULL; } } } - if (!oss->mmapped) { - oss->pcm_buf = audio_calloc ( - AUDIO_FUNC, - hw->samples, - 1 << hw->info.shift - ); - if (!oss->pcm_buf) { - dolog ( - "Could not allocate DAC buffer (%zu samples, each %d bytes)\n", - hw->samples, - 1 << hw->info.shift - ); - oss_anal_close (&fd); - return -1; - } - } - oss->fd = fd; oss->dev = dev; return 0; @@ -621,7 +587,7 @@ static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } - audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples); + audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->samples); trig = PCM_ENABLE_OUTPUT; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr ( @@ -695,13 +661,6 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) } hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; - oss->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); - if (!oss->pcm_buf) { - dolog("Could not allocate ADC buffer (%zu samples, each %d bytes)\n", - hw->samples, 1 << hw->info.shift); - oss_anal_close (&fd); - return -1; - } oss->fd = fd; oss->dev = dev; @@ -713,78 +672,36 @@ static void oss_fini_in (HWVoiceIn *hw) OSSVoiceIn *oss = (OSSVoiceIn *) hw; oss_anal_close (&oss->fd); - - g_free(oss->pcm_buf); - oss->pcm_buf = NULL; } -static int oss_run_in (HWVoiceIn *hw) +static size_t oss_read(HWVoiceIn *hw, void *buf, size_t len) { OSSVoiceIn *oss = (OSSVoiceIn *) hw; - int hwshift = hw->info.shift; - int i; - int live = audio_pcm_hw_get_live_in (hw); - int dead = hw->samples - live; - size_t read_samples = 0; - struct { - int add; - int len; - } bufs[2] = { - { .add = hw->wpos, .len = 0 }, - { .add = 0, .len = 0 } - }; + size_t pos = 0; - if (!dead) { - return 0; - } - - if (hw->wpos + dead > hw->samples) { - bufs[0].len = (hw->samples - hw->wpos) << hwshift; - bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift; - } - else { - bufs[0].len = dead << hwshift; - } - - for (i = 0; i < 2; ++i) { + while (len) { ssize_t nread; - if (bufs[i].len) { - void *p = advance (oss->pcm_buf, bufs[i].add << hwshift); - nread = read (oss->fd, p, bufs[i].len); + void *dst = advance(buf, pos); + nread = read(oss->fd, dst, len); - if (nread > 0) { - if (nread & hw->info.align) { - dolog ("warning: Misaligned read %zd (requested %d), " - "alignment %d\n", nread, bufs[i].add << hwshift, - hw->info.align + 1); - } - read_samples += nread >> hwshift; - hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift); - } - - if (bufs[i].len - nread) { - if (nread == -1) { - switch (errno) { - case EINTR: - case EAGAIN: - break; - default: - oss_logerr ( - errno, - "Failed to read %d bytes of audio (to %p)\n", - bufs[i].len, p - ); - break; - } - } + if (nread == -1) { + switch (errno) { + case EINTR: + case EAGAIN: + break; + default: + oss_logerr(errno, "Failed to read %zu bytes of audio (to %p)\n", + len, dst); break; } } + + pos += nread; + len -= nread; } - hw->wpos = (hw->wpos + read_samples) % hw->samples; - return read_samples; + return pos; } static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -837,12 +754,14 @@ static void oss_audio_fini (void *opaque) static struct audio_pcm_ops oss_pcm_ops = { .init_out = oss_init_out, .fini_out = oss_fini_out, - .run_out = oss_run_out, + .write = oss_write, + .get_buffer_out = oss_get_buffer_out, + .put_buffer_out = oss_put_buffer_out, .ctl_out = oss_ctl_out, .init_in = oss_init_in, .fini_in = oss_fini_in, - .run_in = oss_run_in, + .read = oss_read, .ctl_in = oss_ctl_in };