From patchwork Tue Sep 24 06:19:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157941 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2A9731668 for ; Tue, 24 Sep 2019 06:21:51 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0BDD120673 for ; Tue, 24 Sep 2019 06:21:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0BDD120673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41282 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeCr-0005Nd-9u for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:21:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59157) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeB5-0003Z7-UZ for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB4-0000qN-Pz for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:19:59 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49292) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB4-0000pz-KF for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:19:58 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F0024315C02C for ; Tue, 24 Sep 2019 06:19:57 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id 708D45D71C; Tue, 24 Sep 2019 06:19:52 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 886119D6A; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 01/16] audio: fix buffer-length typo in documentation Date: Tue, 24 Sep 2019 08:19:36 +0200 Message-Id: <20190924061951.27916-2-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Tue, 24 Sep 2019 06:19:57 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann , Stefan Hajnoczi Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Stefan Hajnoczi Fixes: f0b3d811529 ("audio: -audiodev command line option: documentation") Signed-off-by: Stefan Hajnoczi Message-Id: <20190918095335.7646-2-stefanha@redhat.com> Signed-off-by: Gerd Hoffmann --- qemu-options.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index 80c16fa317e5..569958fc0c77 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -439,7 +439,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, " in|out.format= sample format to use with fixed settings\n" " valid values: s8, s16, s32, u8, u16, u32\n" " in|out.voices= number of voices to use\n" - " in|out.buffer-len= length of buffer in microseconds\n" + " in|out.buffer-length= length of buffer in microseconds\n" "-audiodev none,id=id,[,prop[=value][,...]]\n" " dummy driver that discards all output\n" #ifdef CONFIG_AUDIO_ALSA @@ -524,7 +524,7 @@ Valid values are: @code{s8}, @code{s16}, @code{s32}, @code{u8}, @item in|out.voices=@var{voices} Specify the number of @var{voices} to use. Default is 1. -@item in|out.buffer=@var{usecs} +@item in|out.buffer-length=@var{usecs} Sets the size of the buffer in microseconds. @end table From patchwork Tue Sep 24 06:19:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157939 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 436791709 for ; Tue, 24 Sep 2019 06:21:50 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 23EDC20673 for ; Tue, 24 Sep 2019 06:21:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 23EDC20673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41280 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeCq-0005M3-A2 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:21:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59159) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeB6-0003Z8-2R for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB4-0000qc-Un for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:19:59 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56308) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB4-0000q8-PC for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:19:58 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1BD921DC5 for ; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id 70C7B19C58; Tue, 24 Sep 2019 06:19:52 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 910459D70; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 02/16] audio: fix ALSA period-length typo in documentation Date: Tue, 24 Sep 2019 08:19:37 +0200 Message-Id: <20190924061951.27916-3-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.71]); Tue, 24 Sep 2019 06:19:58 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gerd Hoffmann , Stefan Hajnoczi Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Stefan Hajnoczi Fixes: f0b3d811529 ("audio: -audiodev command line option: documentation") Signed-off-by: Stefan Hajnoczi Message-Id: <20190918095335.7646-4-stefanha@redhat.com> Signed-off-by: Gerd Hoffmann --- qemu-options.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index 569958fc0c77..565d7af8c208 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -445,7 +445,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, #ifdef CONFIG_AUDIO_ALSA "-audiodev alsa,id=id[,prop[=value][,...]]\n" " in|out.dev= name of the audio device to use\n" - " in|out.period-len= length of period in microseconds\n" + " in|out.period-length= length of period in microseconds\n" " in|out.try-poll= attempt to use poll mode\n" " threshold= threshold (in microseconds) when playback starts\n" #endif @@ -545,7 +545,7 @@ ALSA specific options are: Specify the ALSA @var{device} to use for input and/or output. Default is @code{default}. -@item in|out.period-len=@var{usecs} +@item in|out.period-length=@var{usecs} Sets the period length in microseconds. @item in|out.try-poll=on|off From patchwork Tue Sep 24 06:19:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157953 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 55E7C1709 for ; Tue, 24 Sep 2019 06:25:03 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 26B2F20673 for ; Tue, 24 Sep 2019 06:25:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 26B2F20673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41314 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeFx-0000hK-WB for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:25:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59197) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeB7-0003ZU-Pw for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB5-0000ql-0h for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49294) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB4-0000q5-O8 for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:19:58 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 11D72315C000; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id 65B2A5C1B2; Tue, 24 Sep 2019 06:19:52 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 9D0A89D75; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 03/16] audio: api for mixeng code free backends Date: Tue, 24 Sep 2019 08:19:38 +0200 Message-Id: <20190924061951.27916-4-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Tue, 24 Sep 2019 06:19:58 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán This will make it possible to skip mixeng with audio playback and recording, allowing us to free ourselves from the limitations of the current mixeng (stereo, int64 samples only). In this case, HW and SW voices will be essentially the same, for every SW voice we will create a HW voice, since we can no longer mix multiple voices together. Some backends expect us to call a function when we have data ready write()/read() style, while others provide a buffer and expects us to directly write/read it, so for optimal performance audio_pcm_ops provide methods for both cases. Previously backends asked mixeng for more data in run_out/run_it, now instead mixeng or the frontends will call the backends, so that's why two sets of functions required. audio.c contains glue code between the two styles, so backends only ever have to implement one style and frontends are free to call whichever is more convenient for them. Signed-off-by: Kővágó, Zoltán Message-id: 15a33c03a62228922d851f7324c52f73cb8d2414.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/audio_int.h | 41 ++++++-- audio/audio_template.h | 1 + audio/audio.c | 216 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 250 insertions(+), 8 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index a674c5374a06..8fb1ca8a8d0f 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -65,6 +65,8 @@ typedef struct HWVoiceOut { uint64_t ts_helper; struct st_sample *mix_buf; + void *buf_emul; + size_t pos_emul, pending_emul, size_emul; size_t samples; QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; @@ -87,6 +89,8 @@ typedef struct HWVoiceIn { uint64_t ts_helper; struct st_sample *conv_buf; + void *buf_emul; + size_t pos_emul, pending_emul, size_emul; size_t samples; QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; @@ -147,17 +151,42 @@ struct audio_driver { }; struct audio_pcm_ops { - int (*init_out)(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque); - void (*fini_out)(HWVoiceOut *hw); + int (*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque); + void (*fini_out)(HWVoiceOut *hw); size_t (*run_out)(HWVoiceOut *hw, size_t live); - int (*ctl_out) (HWVoiceOut *hw, int cmd, ...); + size_t (*write) (HWVoiceOut *hw, void *buf, size_t size); + /* + * get a buffer that after later can be passed to put_buffer_out; optional + * returns the buffer, and writes it's size to size (in bytes) + * this is unrelated to the above buffer_size_out function + */ + void *(*get_buffer_out)(HWVoiceOut *hw, size_t *size); + /* + * put back the buffer returned by get_buffer_out; optional + * buf must be equal the pointer returned by get_buffer_out, + * size may be smaller + */ + size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size); + int (*ctl_out) (HWVoiceOut *hw, int cmd, ...); - int (*init_in) (HWVoiceIn *hw, struct audsettings *as, void *drv_opaque); - void (*fini_in) (HWVoiceIn *hw); + int (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); + void (*fini_in) (HWVoiceIn *hw); size_t (*run_in)(HWVoiceIn *hw); - int (*ctl_in) (HWVoiceIn *hw, int cmd, ...); + size_t (*read) (HWVoiceIn *hw, void *buf, size_t size); + void *(*get_buffer_in)(HWVoiceIn *hw, size_t *size); + void (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size); + int (*ctl_in) (HWVoiceIn *hw, int cmd, ...); }; +void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size); +void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size); +void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size); +size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size); +size_t audio_generic_put_buffer_out_nowrite(HWVoiceOut *hw, void *buf, + size_t size); +size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size); +size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size); + struct capture_callback { struct audio_capture_ops ops; void *opaque; diff --git a/audio/audio_template.h b/audio/audio_template.h index 2562bf5f0062..ff4a173f1810 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -71,6 +71,7 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s, static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) { + g_free(hw->buf_emul); g_free (HWBUF); HWBUF = NULL; } diff --git a/audio/audio.c b/audio/audio.c index e99fcd0694e9..e29a1e15eb30 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -573,6 +573,25 @@ size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, return clipped; } +static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t len) +{ + size_t clipped = 0; + size_t pos = hw->rpos; + + while (len) { + st_sample *src = hw->mix_buf + pos; + uint8_t *dst = advance(pcm_buf, clipped << hw->info.shift); + size_t samples_till_end_of_buf = hw->samples - pos; + size_t samples_to_clip = MIN(len, samples_till_end_of_buf); + + hw->clip(dst, src, samples_to_clip); + + pos = (pos + samples_to_clip) % hw->samples; + len -= samples_to_clip; + clipped += samples_to_clip; + } +} + /* * Soft voice (capture) */ @@ -1050,6 +1069,36 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos, mixeng_clear(hw->mix_buf, samples - n); } +static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) +{ + size_t clipped = 0; + + while (live) { + size_t size, decr, proc; + void *buf = hw->pcm_ops->get_buffer_out(hw, &size); + if (!buf) { + /* retrying will likely won't help, drop everything. */ + hw->rpos = (hw->rpos + live) % hw->samples; + return clipped + live; + } + + decr = MIN(size >> hw->info.shift, live); + audio_pcm_hw_clip_out2(hw, buf, decr); + proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >> + hw->info.shift; + + live -= proc; + clipped += proc; + hw->rpos = (hw->rpos + proc) % hw->samples; + + if (proc == 0 || proc < decr) { + break; + } + } + + return clipped; +} + static void audio_run_out (AudioState *s) { HWVoiceOut *hw = NULL; @@ -1097,7 +1146,11 @@ static void audio_run_out (AudioState *s) } prev_rpos = hw->rpos; - played = hw->pcm_ops->run_out (hw, live); + if (hw->pcm_ops->run_out) { + played = hw->pcm_ops->run_out(hw, live); + } else { + played = audio_pcm_hw_run_out(hw, live); + } replay_audio_out(&played); if (audio_bug(__func__, hw->rpos >= hw->samples)) { dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n", @@ -1156,6 +1209,35 @@ static void audio_run_out (AudioState *s) } } +static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) +{ + size_t conv = 0; + + while (samples) { + size_t proc; + size_t size = samples << hw->info.shift; + void *buf = hw->pcm_ops->get_buffer_in(hw, &size); + + assert((size & hw->info.align) == 0); + if (size == 0) { + hw->pcm_ops->put_buffer_in(hw, buf, size); + break; + } + + proc = MIN(size >> hw->info.shift, + hw->samples - hw->wpos); + + hw->conv(hw->conv_buf + hw->wpos, buf, proc); + hw->wpos = (hw->wpos + proc) % hw->samples; + + samples -= proc; + conv += proc; + hw->pcm_ops->put_buffer_in(hw, buf, proc << hw->info.shift); + } + + return conv; +} + static void audio_run_in (AudioState *s) { HWVoiceIn *hw = NULL; @@ -1165,7 +1247,12 @@ static void audio_run_in (AudioState *s) size_t captured = 0, min; if (replay_mode != REPLAY_MODE_PLAY) { - captured = hw->pcm_ops->run_in(hw); + if (hw->pcm_ops->run_in) { + captured = hw->pcm_ops->run_in(hw); + } else { + captured = audio_pcm_hw_run_in( + hw, hw->samples - audio_pcm_hw_get_live_in(hw)); + } } replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples); @@ -1259,12 +1346,137 @@ void audio_run(AudioState *s, const char *msg) #endif } +void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size) +{ + ssize_t start; + + if (unlikely(!hw->buf_emul)) { + size_t calc_size = hw->samples << hw->info.shift; + hw->buf_emul = g_malloc(calc_size); + hw->size_emul = calc_size; + hw->pos_emul = hw->pending_emul = 0; + } + + while (hw->pending_emul < hw->size_emul) { + size_t read_len = MIN(hw->size_emul - hw->pos_emul, + hw->size_emul - hw->pending_emul); + size_t read = hw->pcm_ops->read(hw, hw->buf_emul + hw->pos_emul, + read_len); + hw->pending_emul += read; + if (read < read_len) { + break; + } + } + + start = ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start += hw->size_emul; + } + assert(start >= 0 && start < hw->size_emul); + + *size = MIN(hw->pending_emul, hw->size_emul - start); + return hw->buf_emul + start; +} + +void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size) +{ + assert(size <= hw->pending_emul); + hw->pending_emul -= size; +} + +void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size) +{ + if (unlikely(!hw->buf_emul)) { + size_t calc_size = hw->samples << hw->info.shift; + + hw->buf_emul = g_malloc(calc_size); + hw->size_emul = calc_size; + hw->pos_emul = hw->pending_emul = 0; + } + + *size = MIN(hw->size_emul - hw->pending_emul, + hw->size_emul - hw->pos_emul); + return hw->buf_emul + hw->pos_emul; +} + +size_t audio_generic_put_buffer_out_nowrite(HWVoiceOut *hw, void *buf, + size_t size) +{ + assert(buf == hw->buf_emul + hw->pos_emul && + size + hw->pending_emul <= hw->size_emul); + + hw->pending_emul += size; + hw->pos_emul = (hw->pos_emul + size) % hw->size_emul; + + return size; +} + +size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) +{ + audio_generic_put_buffer_out_nowrite(hw, buf, size); + + while (hw->pending_emul) { + size_t write_len, written; + ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start += hw->size_emul; + } + assert(start >= 0 && start < hw->size_emul); + + write_len = MIN(hw->pending_emul, hw->size_emul - start); + + written = hw->pcm_ops->write(hw, hw->buf_emul + start, write_len); + hw->pending_emul -= written; + + if (written < write_len) { + break; + } + } + + /* + * fake we have written everything. non-written data remain in pending_emul, + * so we do not have to clip them multiple times + */ + return size; +} + +size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size) +{ + size_t dst_size, copy_size; + void *dst = hw->pcm_ops->get_buffer_out(hw, &dst_size); + copy_size = MIN(size, dst_size); + + memcpy(dst, buf, copy_size); + return hw->pcm_ops->put_buffer_out(hw, buf, copy_size); +} + +size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size) +{ + size_t dst_size, copy_size; + void *dst = hw->pcm_ops->get_buffer_in(hw, &dst_size); + copy_size = MIN(size, dst_size); + + memcpy(dst, buf, copy_size); + hw->pcm_ops->put_buffer_in(hw, buf, copy_size); + return copy_size; +} + + static int audio_driver_init(AudioState *s, struct audio_driver *drv, bool msg, Audiodev *dev) { s->drv_opaque = drv->init(dev); if (s->drv_opaque) { + if (!drv->pcm_ops->get_buffer_in) { + drv->pcm_ops->get_buffer_in = audio_generic_get_buffer_in; + drv->pcm_ops->put_buffer_in = audio_generic_put_buffer_in; + } + if (!drv->pcm_ops->get_buffer_out) { + drv->pcm_ops->get_buffer_out = audio_generic_get_buffer_out; + drv->pcm_ops->put_buffer_out = audio_generic_put_buffer_out; + } + audio_init_nb_voices_out(s, drv); audio_init_nb_voices_in(s, drv); s->drv = drv; From patchwork Tue Sep 24 06:19:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157947 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0004E1668 for ; Tue, 24 Sep 2019 06:24:57 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C389A20673 for ; Tue, 24 Sep 2019 06:24:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C389A20673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41308 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeFs-0000aS-3y for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:24:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59200) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeB7-0003ZV-SL for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB5-0000qs-2u for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45974) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB4-0000qC-QD for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:19:59 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 258E318CB8E8; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id 62E281001947; Tue, 24 Sep 2019 06:19:52 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id A643A9C84; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 04/16] alsaaudio: port to the new audio backend api Date: Tue, 24 Sep 2019 08:19:39 +0200 Message-Id: <20190924061951.27916-5-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.63]); Tue, 24 Sep 2019 06:19:58 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: ab9768e73dfe7b7305bd6a51629846e0d77622a5.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/alsaaudio.c | 308 +++++++++++++--------------------------------- 1 file changed, 83 insertions(+), 225 deletions(-) diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 591344dccd1f..19124d09d845 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -44,9 +44,6 @@ struct pollhlp { typedef struct ALSAVoiceOut { HWVoiceOut hw; - int wpos; - int pending; - void *pcm_buf; snd_pcm_t *handle; struct pollhlp pollhlp; Audiodev *dev; @@ -55,7 +52,6 @@ typedef struct ALSAVoiceOut { typedef struct ALSAVoiceIn { HWVoiceIn hw; snd_pcm_t *handle; - void *pcm_buf; struct pollhlp pollhlp; Audiodev *dev; } ALSAVoiceIn; @@ -602,102 +598,64 @@ 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 size_t alsa_run_out(HWVoiceOut *hw, size_t live) +static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len) { ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; - size_t 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) @@ -706,9 +664,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, @@ -737,14 +692,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(__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; @@ -839,14 +786,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(__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; @@ -858,129 +797,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 size_t 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; - size_t live = audio_pcm_hw_get_live_in (hw); - size_t dead = hw->samples - live; - size_t decr; - struct { - size_t add; - size_t 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, ...) @@ -1065,12 +923,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, }; From patchwork Tue Sep 24 06:19:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157951 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A60A21668 for ; Tue, 24 Sep 2019 06:25:02 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 84BE120673 for ; Tue, 24 Sep 2019 06:25:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 84BE120673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41312 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeFw-0000gk-Lq for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:25:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59210) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeB8-0003ZY-DD for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB6-0000rW-9U for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:02 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58334) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB5-0000qx-Sy for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:00 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1E8CD308FBAC; Tue, 24 Sep 2019 06:19:59 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id F0CC0600C8; Tue, 24 Sep 2019 06:19:55 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id AF2AB9C86; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 05/16] coreaudio: port to the new audio backend api Date: Tue, 24 Sep 2019 08:19:40 +0200 Message-Id: <20190924061951.27916-6-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.43]); Tue, 24 Sep 2019 06:19:59 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: 586a1e66de5cbc6c5234f9ae556d24befb6afada.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/coreaudio.c | 130 ++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 61 deletions(-) diff --git a/audio/coreaudio.c b/audio/coreaudio.c index d1be58b40aa8..5cde42f9826c 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -43,9 +43,6 @@ typedef struct coreaudioVoiceOut { UInt32 audioDevicePropertyBufferFrameSize; AudioStreamBasicDescription outputStreamBasicDescription; AudioDeviceIOProcID ioprocid; - size_t live; - size_t decr; - size_t rpos; } coreaudioVoiceOut; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 @@ -397,31 +394,29 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name) return 0; } -static size_t coreaudio_run_out(HWVoiceOut *hw, size_t live) -{ - size_t decr; - coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; - - if (coreaudio_lock (core, "coreaudio_run_out")) { - return 0; +#define COREAUDIO_WRAPPER_FUNC(name, ret_type, args_decl, args) \ + static ret_type glue(coreaudio_, name)args_decl \ + { \ + coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; \ + ret_type ret; \ + \ + if (coreaudio_lock(core, "coreaudio_" #name)) { \ + return 0; \ + } \ + \ + ret = glue(audio_generic_, name)args; \ + \ + coreaudio_unlock(core, "coreaudio_" #name); \ + return ret; \ } - - if (core->decr > live) { - ldebug ("core->decr %d live %d core->live %d\n", - core->decr, - live, - core->live); - } - - decr = MIN (core->decr, live); - core->decr -= decr; - - core->live = live - decr; - hw->rpos = core->rpos; - - coreaudio_unlock (core, "coreaudio_run_out"); - return decr; -} +COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size), + (hw, size)) +COREAUDIO_WRAPPER_FUNC(put_buffer_out_nowrite, size_t, + (HWVoiceOut *hw, void *buf, size_t size), + (hw, buf, size)) +COREAUDIO_WRAPPER_FUNC(write, size_t, (HWVoiceOut *hw, void *buf, size_t size), + (hw, buf, size)) +#undef COREAUDIO_WRAPPER_FUNC /* callback to feed audiooutput buffer */ static OSStatus audioDeviceIOProc( @@ -433,19 +428,11 @@ static OSStatus audioDeviceIOProc( const AudioTimeStamp* inOutputTime, void* hwptr) { - UInt32 frame, frameCount; - float *out = outOutputData->mBuffers[0].mData; + UInt32 frameCount, pending_frames; + void *out = outOutputData->mBuffers[0].mData; HWVoiceOut *hw = hwptr; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr; - int rpos, live; - struct st_sample *src; -#ifndef FLOAT_MIXENG -#ifdef RECIPROCAL - const float scale = 1.f / UINT_MAX; -#else - const float scale = UINT_MAX; -#endif -#endif + size_t len; if (coreaudio_lock (core, "audioDeviceIOProc")) { inInputTime = 0; @@ -453,42 +440,51 @@ static OSStatus audioDeviceIOProc( } frameCount = core->audioDevicePropertyBufferFrameSize; - live = core->live; + pending_frames = hw->pending_emul >> hw->info.shift; /* if there are not enough samples, set signal and return */ - if (live < frameCount) { + if (pending_frames < frameCount) { inInputTime = 0; coreaudio_unlock (core, "audioDeviceIOProc(empty)"); return 0; } - rpos = core->rpos; - src = hw->mix_buf + rpos; + len = frameCount << hw->info.shift; + while (len) { + size_t write_len; + ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start += hw->size_emul; + } + assert(start >= 0 && start < hw->size_emul); - /* fill buffer */ - for (frame = 0; frame < frameCount; frame++) { -#ifdef FLOAT_MIXENG - *out++ = src[frame].l; /* left channel */ - *out++ = src[frame].r; /* right channel */ -#else -#ifdef RECIPROCAL - *out++ = src[frame].l * scale; /* left channel */ - *out++ = src[frame].r * scale; /* right channel */ -#else - *out++ = src[frame].l / scale; /* left channel */ - *out++ = src[frame].r / scale; /* right channel */ -#endif -#endif + write_len = MIN(MIN(hw->pending_emul, len), + hw->size_emul - start); + + memcpy(out, hw->buf_emul + start, write_len); + hw->pending_emul -= write_len; + len -= write_len; + out += write_len; } - rpos = (rpos + frameCount) % hw->samples; - core->decr += frameCount; - core->rpos = rpos; - coreaudio_unlock (core, "audioDeviceIOProc"); return 0; } +static UInt32 coreaudio_get_flags(struct audio_pcm_info *info, + struct audsettings *as) +{ + UInt32 flags = info->sign ? kAudioFormatFlagIsSignedInteger : 0; + if (as->endianness) { /* 0 = little, 1 = big */ + flags |= kAudioFormatFlagIsBigEndian; + } + + if (flags == 0) { /* must not be 0 */ + flags = kAudioFormatFlagsAreAllClear; + } + return flags; +} + static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) { @@ -576,6 +572,16 @@ static int coreaudio_init_out(HWVoiceOut *hw, struct audsettings *as, /* set Samplerate */ core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq; + core->outputStreamBasicDescription.mFormatID = kAudioFormatLinearPCM; + core->outputStreamBasicDescription.mFormatFlags = + coreaudio_get_flags(&hw->info, as); + core->outputStreamBasicDescription.mBytesPerPacket = + core->outputStreamBasicDescription.mBytesPerFrame = + hw->info.nchannels * hw->info.bits / 8; + core->outputStreamBasicDescription.mFramesPerPacket = 1; + core->outputStreamBasicDescription.mChannelsPerFrame = hw->info.nchannels; + core->outputStreamBasicDescription.mBitsPerChannel = hw->info.bits; + status = coreaudio_set_streamformat(core->outputDeviceID, &core->outputStreamBasicDescription); if (status != kAudioHardwareNoError) { @@ -686,7 +692,9 @@ static void coreaudio_audio_fini (void *opaque) static struct audio_pcm_ops coreaudio_pcm_ops = { .init_out = coreaudio_init_out, .fini_out = coreaudio_fini_out, - .run_out = coreaudio_run_out, + .write = coreaudio_write, + .get_buffer_out = coreaudio_get_buffer_out, + .put_buffer_out = coreaudio_put_buffer_out_nowrite, .ctl_out = coreaudio_ctl_out }; From patchwork Tue Sep 24 06:19:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157959 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 458361668 for ; Tue, 24 Sep 2019 06:29:05 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 167AE20673 for ; Tue, 24 Sep 2019 06:29:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 167AE20673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41336 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeJs-0004UK-5I for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:29:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59203) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeB7-0003ZW-VI for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB4-0000qU-RG for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54260) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB4-0000pu-I6 for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:19:58 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CDAE7368DA; Tue, 24 Sep 2019 06:19:57 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id EE1815C1B5; Tue, 24 Sep 2019 06:19:55 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id B9F459C87; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 06/16] dsoundaudio: port to the new audio backend api Date: Tue, 24 Sep 2019 08:19:41 +0200 Message-Id: <20190924061951.27916-7-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Tue, 24 Sep 2019 06:19:57 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: 2ca925ab551ea832c930fc2db213a9e73d8dab7f.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/dsound_template.h | 47 +++--- audio/dsoundaudio.c | 329 ++++++++++------------------------------ 2 files changed, 103 insertions(+), 273 deletions(-) diff --git a/audio/dsound_template.h b/audio/dsound_template.h index 8ece870c9ef7..9f10b688df57 100644 --- a/audio/dsound_template.h +++ b/audio/dsound_template.h @@ -29,6 +29,8 @@ #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER #define FIELD dsound_capture_buffer #define FIELD2 dsound_capture +#define HWVOICE HWVoiceIn +#define DSOUNDVOICE DSoundVoiceIn #else #define NAME "playback buffer" #define NAME2 "DirectSound" @@ -37,6 +39,8 @@ #define BUFPTR LPDIRECTSOUNDBUFFER #define FIELD dsound_buffer #define FIELD2 dsound +#define HWVOICE HWVoiceOut +#define DSOUNDVOICE DSoundVoiceOut #endif static int glue (dsound_unlock_, TYPE) ( @@ -72,8 +76,6 @@ static int glue (dsound_lock_, TYPE) ( ) { HRESULT hr; - LPVOID p1 = NULL, p2 = NULL; - DWORD blen1 = 0, blen2 = 0; DWORD flag; #ifdef DSBTYPE_IN @@ -81,7 +83,7 @@ static int glue (dsound_lock_, TYPE) ( #else flag = entire ? DSBLOCK_ENTIREBUFFER : 0; #endif - hr = glue(IFACE, _Lock)(buf, pos, len, &p1, &blen1, &p2, &blen2, flag); + hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag); if (FAILED (hr)) { #ifndef DSBTYPE_IN @@ -96,34 +98,34 @@ static int glue (dsound_lock_, TYPE) ( goto fail; } - if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) { - dolog ("DirectSound returned misaligned buffer %ld %ld\n", - blen1, blen2); - glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2); + if ((p1p && *p1p && (*blen1p & info->align)) || + (p2p && *p2p && (*blen2p & info->align))) { + dolog("DirectSound returned misaligned buffer %ld %ld\n", + *blen1p, *blen2p); + glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p, + blen2p ? *blen2p : 0); goto fail; } - if (!p1 && blen1) { - dolog ("warning: !p1 && blen1=%ld\n", blen1); - blen1 = 0; + if (p1p && !*p1p && *blen1p) { + dolog("warning: !p1 && blen1=%ld\n", *blen1p); + *blen1p = 0; } - if (!p2 && blen2) { - dolog ("warning: !p2 && blen2=%ld\n", blen2); - blen2 = 0; + if (p2p && !*p2p && *blen2p) { + dolog("warning: !p2 && blen2=%ld\n", *blen2p); + *blen2p = 0; } - *p1p = p1; - *p2p = p2; - *blen1p = blen1; - *blen2p = blen2; return 0; fail: *p1p = NULL - 1; - *p2p = NULL - 1; *blen1p = -1; - *blen2p = -1; + if (p2p) { + *p2p = NULL - 1; + *blen2p = -1; + } return -1; } @@ -242,7 +244,6 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, goto fail0; } - ds->first_time = 1; obt_as.endianness = 0; audio_pcm_init_info (&hw->info, &obt_as); @@ -252,15 +253,13 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, bc.dwBufferBytes, hw->info.align + 1 ); } + hw->size_emul = bc.dwBufferBytes; hw->samples = bc.dwBufferBytes >> hw->info.shift; ds->s = s; #ifdef DEBUG_DSOUND dolog ("caps %ld, desc %ld\n", bc.dwBufferBytes, bd.dwBufferBytes); - - dolog ("bufsize %d, freq %d, chan %d, fmt %d\n", - hw->bufsize, settings.freq, settings.nchannels, settings.fmt); #endif return 0; @@ -276,3 +275,5 @@ static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as, #undef BUFPTR #undef FIELD #undef FIELD2 +#undef HWVOICE +#undef DSOUNDVOICE diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 2fc118b795d0..9960247814c7 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -53,19 +53,11 @@ typedef struct { typedef struct { HWVoiceOut hw; LPDIRECTSOUNDBUFFER dsound_buffer; - DWORD old_pos; - int first_time; dsound *s; -#ifdef DEBUG_DSOUND - DWORD old_ppos; - DWORD played; - DWORD mixed; -#endif } DSoundVoiceOut; typedef struct { HWVoiceIn hw; - int first_time; LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer; dsound *s; } DSoundVoiceIn; @@ -243,11 +235,6 @@ static void GCC_FMT_ATTR (3, 4) dsound_logerr2 ( dsound_log_hresult (hr); } -static uint64_t usecs_to_bytes(struct audio_pcm_info *info, uint32_t usecs) -{ - return muldiv64(usecs, info->bytes_per_second, 1000000); -} - #ifdef DEBUG_DSOUND static void print_wave_format (WAVEFORMATEX *wfx) { @@ -312,33 +299,6 @@ static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb, return 0; } -static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len) -{ - int src_len1 = dst_len; - int src_len2 = 0; - int pos = hw->rpos + dst_len; - struct st_sample *src1 = hw->mix_buf + hw->rpos; - struct st_sample *src2 = NULL; - - if (pos > hw->samples) { - src_len1 = hw->samples - hw->rpos; - src2 = hw->mix_buf; - src_len2 = dst_len - src_len1; - pos = src_len2; - } - - if (src_len1) { - hw->clip (dst, src1, src_len1); - } - - if (src_len2) { - dst = advance (dst, src_len1 << hw->info.shift); - hw->clip (dst, src2, src_len2); - } - - hw->rpos = pos % hw->samples; -} - static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb, dsound *s) { @@ -350,7 +310,7 @@ static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb, dsb, &hw->info, 0, - hw->samples << hw->info.shift, + hw->size_emul, &p1, &p2, &blen1, &blen2, 1, @@ -454,139 +414,51 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } -static size_t dsound_run_out(HWVoiceOut *hw, size_t live) +static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size) { - int err; + DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; + LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer; HRESULT hr; + DWORD ppos, act_size; + size_t req_size; + int err; + void *ret; + + hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, NULL); + if (FAILED(hr)) { + dsound_logerr(hr, "Could not get playback buffer position\n"); + *size = 0; + return NULL; + } + + req_size = audio_ring_dist(ppos, hw->pos_emul, hw->size_emul); + req_size = MIN(req_size, hw->size_emul - hw->pos_emul); + + err = dsound_lock_out(dsb, &hw->info, hw->pos_emul, req_size, &ret, NULL, + &act_size, NULL, false, ds->s); + if (err) { + dolog("Failed to lock buffer\n"); + *size = 0; + return NULL; + } + + *size = act_size; + return ret; +} + +static size_t dsound_put_buffer_out(HWVoiceOut *hw, void *buf, size_t len) +{ DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer; - size_t len; - int hwshift; - DWORD blen1, blen2; - DWORD len1, len2; - DWORD decr; - DWORD wpos, ppos, old_pos; - LPVOID p1, p2; - size_t bufsize; - dsound *s = ds->s; - AudiodevDsoundOptions *dso = &s->dev->u.dsound; + int err = dsound_unlock_out(dsb, buf, NULL, len, 0); - if (!dsb) { - dolog ("Attempt to run empty with playback buffer\n"); - return 0; - } - - hwshift = hw->info.shift; - bufsize = hw->samples << hwshift; - - hr = IDirectSoundBuffer_GetCurrentPosition ( - dsb, - &ppos, - ds->first_time ? &wpos : NULL - ); - if (FAILED (hr)) { - dsound_logerr (hr, "Could not get playback buffer position\n"); - return 0; - } - - len = live << hwshift; - - if (ds->first_time) { - if (dso->latency) { - DWORD cur_blat; - - cur_blat = audio_ring_dist (wpos, ppos, bufsize); - ds->first_time = 0; - old_pos = wpos; - old_pos += - usecs_to_bytes(&hw->info, dso->latency) - cur_blat; - old_pos %= bufsize; - old_pos &= ~hw->info.align; - } - else { - old_pos = wpos; - } -#ifdef DEBUG_DSOUND - ds->played = 0; - ds->mixed = 0; -#endif - } - else { - if (ds->old_pos == ppos) { -#ifdef DEBUG_DSOUND - dolog ("old_pos == ppos\n"); -#endif - return 0; - } - -#ifdef DEBUG_DSOUND - ds->played += audio_ring_dist (ds->old_pos, ppos, hw->bufsize); -#endif - old_pos = ds->old_pos; - } - - if ((old_pos < ppos) && ((old_pos + len) > ppos)) { - len = ppos - old_pos; - } - else { - if ((old_pos > ppos) && ((old_pos + len) > (ppos + bufsize))) { - len = bufsize - old_pos + ppos; - } - } - - if (audio_bug(__func__, len > bufsize)) { - dolog("len=%zu bufsize=%zu old_pos=%ld ppos=%ld\n", - len, bufsize, old_pos, ppos); - return 0; - } - - len &= ~hw->info.align; - if (!len) { - return 0; - } - -#ifdef DEBUG_DSOUND - ds->old_ppos = ppos; -#endif - err = dsound_lock_out ( - dsb, - &hw->info, - old_pos, - len, - &p1, &p2, - &blen1, &blen2, - 0, - s - ); if (err) { + dolog("Failed to unlock buffer!!\n"); return 0; } + hw->pos_emul = (hw->pos_emul + len) % hw->size_emul; - len1 = blen1 >> hwshift; - len2 = blen2 >> hwshift; - decr = len1 + len2; - - if (p1 && len1) { - dsound_write_sample (hw, p1, len1); - } - - if (p2 && len2) { - dsound_write_sample (hw, p2, len2); - } - - dsound_unlock_out (dsb, p1, p2, blen1, blen2); - ds->old_pos = (old_pos + (decr << hwshift)) % bufsize; - -#ifdef DEBUG_DSOUND - ds->mixed += decr << hwshift; - - dolog ("played %lu mixed %lu diff %ld sec %f\n", - ds->played, - ds->mixed, - ds->mixed - ds->played, - abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second); -#endif - return decr; + return len; } static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -641,96 +513,49 @@ static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) return 0; } -static size_t dsound_run_in(HWVoiceIn *hw) +static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size) { - int err; + DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; + LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; HRESULT hr; + DWORD cpos, act_size; + size_t req_size; + int err; + void *ret; + + hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, &cpos, NULL); + if (FAILED(hr)) { + dsound_logerr(hr, "Could not get capture buffer position\n"); + *size = 0; + return NULL; + } + + req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul); + req_size = MIN(req_size, hw->size_emul - hw->pos_emul); + + err = dsound_lock_in(dscb, &hw->info, hw->pos_emul, req_size, &ret, NULL, + &act_size, NULL, false, ds->s); + if (err) { + dolog("Failed to lock buffer\n"); + *size = 0; + return NULL; + } + + *size = act_size; + return ret; +} + +static void dsound_put_buffer_in(HWVoiceIn *hw, void *buf, size_t len) +{ DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; - size_t live, len, dead; - DWORD blen1, blen2; - DWORD len1, len2; - DWORD decr; - DWORD cpos, rpos; - LPVOID p1, p2; - int hwshift; - dsound *s = ds->s; + int err = dsound_unlock_in(dscb, buf, NULL, len, 0); - if (!dscb) { - dolog ("Attempt to run without capture buffer\n"); - return 0; - } - - hwshift = hw->info.shift; - - live = audio_pcm_hw_get_live_in (hw); - dead = hw->samples - live; - if (!dead) { - return 0; - } - - hr = IDirectSoundCaptureBuffer_GetCurrentPosition ( - dscb, - &cpos, - ds->first_time ? &rpos : NULL - ); - if (FAILED (hr)) { - dsound_logerr (hr, "Could not get capture buffer position\n"); - return 0; - } - - if (ds->first_time) { - ds->first_time = 0; - if (rpos & hw->info.align) { - ldebug ("warning: Misaligned capture read position %ld(%d)\n", - rpos, hw->info.align); - } - hw->wpos = rpos >> hwshift; - } - - if (cpos & hw->info.align) { - ldebug ("warning: Misaligned capture position %ld(%d)\n", - cpos, hw->info.align); - } - cpos >>= hwshift; - - len = audio_ring_dist (cpos, hw->wpos, hw->samples); - if (!len) { - return 0; - } - len = MIN (len, dead); - - err = dsound_lock_in ( - dscb, - &hw->info, - hw->wpos << hwshift, - len << hwshift, - &p1, - &p2, - &blen1, - &blen2, - 0, - s - ); if (err) { - return 0; + dolog("Failed to unlock buffer!!\n"); + return; } - - len1 = blen1 >> hwshift; - len2 = blen2 >> hwshift; - decr = len1 + len2; - - if (p1 && len1) { - hw->conv (hw->conv_buf + hw->wpos, p1, len1); - } - - if (p2 && len2) { - hw->conv (hw->conv_buf, p2, len2); - } - - dsound_unlock_in (dscb, p1, p2, blen1, blen2); - hw->wpos = (hw->wpos + decr) % hw->samples; - return decr; + hw->pos_emul = (hw->pos_emul + len) % hw->size_emul; } static void dsound_audio_fini (void *opaque) @@ -846,12 +671,16 @@ static void *dsound_audio_init(Audiodev *dev) static struct audio_pcm_ops dsound_pcm_ops = { .init_out = dsound_init_out, .fini_out = dsound_fini_out, - .run_out = dsound_run_out, + .write = audio_generic_write, + .get_buffer_out = dsound_get_buffer_out, + .put_buffer_out = dsound_put_buffer_out, .ctl_out = dsound_ctl_out, .init_in = dsound_init_in, .fini_in = dsound_fini_in, - .run_in = dsound_run_in, + .read = audio_generic_read, + .get_buffer_in = dsound_get_buffer_in, + .put_buffer_in = dsound_put_buffer_in, .ctl_in = dsound_ctl_in }; From patchwork Tue Sep 24 06:19:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157945 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3ED0517D4 for ; Tue, 24 Sep 2019 06:21:55 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 201B120673 for ; Tue, 24 Sep 2019 06:21:55 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 201B120673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41286 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeCv-0005Tr-T6 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:21:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59186) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeB7-0003ZA-1n for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB5-0000r1-Ho for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53124) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB5-0000qK-9l for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:19:59 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9E3D9806A5E; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5091A5C1B2; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id C27199C90; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 07/16] noaudio: port to the new audio backend api Date: Tue, 24 Sep 2019 08:19:42 +0200 Message-Id: <20190924061951.27916-8-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.67]); Tue, 24 Sep 2019 06:19:58 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: 10eebdd2e1529c2bd403ef98dd9d346c6d4ca3d1.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/noaudio.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/audio/noaudio.c b/audio/noaudio.c index 0fb2629cf283..b054fd225b66 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -41,10 +41,9 @@ typedef struct NoVoiceIn { int64_t old_ticks; } NoVoiceIn; -static size_t no_run_out(HWVoiceOut *hw, size_t live) +static size_t no_write(HWVoiceOut *hw, void *buf, size_t len) { NoVoiceOut *no = (NoVoiceOut *) hw; - size_t decr, samples; int64_t now; int64_t ticks; int64_t bytes; @@ -52,13 +51,9 @@ static size_t no_run_out(HWVoiceOut *hw, size_t live) now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); ticks = now - no->old_ticks; bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - bytes = MIN(bytes, SIZE_MAX); - samples = bytes >> hw->info.shift; no->old_ticks = now; - decr = MIN (live, samples); - hw->rpos = (hw->rpos + decr) % hw->samples; - return decr; + return MIN(len, bytes); } static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) @@ -92,25 +87,21 @@ static void no_fini_in (HWVoiceIn *hw) (void) hw; } -static size_t no_run_in(HWVoiceIn *hw) +static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) { + size_t to_clear; NoVoiceIn *no = (NoVoiceIn *) hw; - size_t live = audio_pcm_hw_get_live_in(hw); - size_t dead = hw->samples - live; - size_t samples = 0; - if (dead) { - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t ticks = now - no->old_ticks; - int64_t bytes = - muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); + int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + int64_t ticks = now - no->old_ticks; + int64_t bytes = + muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - no->old_ticks = now; - bytes = MIN (bytes, SIZE_MAX); - samples = bytes >> hw->info.shift; - samples = MIN (samples, dead); - } - return samples; + no->old_ticks = now; + to_clear = MIN(bytes, size); + + audio_pcm_info_clear_buf(&hw->info, buf, to_clear >> hw->info.shift); + return to_clear; } static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) @@ -133,12 +124,12 @@ static void no_audio_fini (void *opaque) static struct audio_pcm_ops no_pcm_ops = { .init_out = no_init_out, .fini_out = no_fini_out, - .run_out = no_run_out, + .write = no_write, .ctl_out = no_ctl_out, .init_in = no_init_in, .fini_in = no_fini_in, - .run_in = no_run_in, + .read = no_read, .ctl_in = no_ctl_in }; From patchwork Tue Sep 24 06:19:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157969 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C534F14E5 for ; Tue, 24 Sep 2019 06:38:09 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9528A20665 for ; Tue, 24 Sep 2019 06:38:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9528A20665 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41404 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeSe-00039v-Qe for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:38:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59339) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeBK-0003kz-8R for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeBF-0000vh-A9 for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:13 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45998) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeBE-0000ug-UR for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:09 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DC0D318CB8E9; Tue, 24 Sep 2019 06:20:06 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id AD30B60852; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id CBB139CA3; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 08/16] ossaudio: port to the new audio backend api Date: Tue, 24 Sep 2019 08:19:43 +0200 Message-Id: <20190924061951.27916-9-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.63]); Tue, 24 Sep 2019 06:20:06 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: 22ab335146acd8099779583edcf6ed46de836bd6.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/ossaudio.c | 288 +++++++++++++++++------------------------------ 1 file changed, 104 insertions(+), 184 deletions(-) diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 169693368886..278251270691 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -40,19 +40,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; @@ -371,98 +367,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 size_t oss_run_out(HWVoiceOut *hw, size_t live) -{ - OSSVoiceOut *oss = (OSSVoiceOut *) hw; - int err; - size_t decr; - struct audio_buf_info abinfo; - struct count_info cntinfo; - size_t 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) @@ -473,18 +458,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; } } @@ -535,19 +515,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) { @@ -567,30 +548,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(__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; @@ -618,7 +585,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 ( @@ -692,13 +659,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(__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; @@ -710,78 +670,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 size_t 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; - size_t live = audio_pcm_hw_get_live_in (hw); - size_t dead = hw->samples - live; - size_t read_samples = 0; - struct { - size_t add; - size_t 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 %zu), " - "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 %zu 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, ...) @@ -845,12 +763,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 }; From patchwork Tue Sep 24 06:19:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157967 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3017C1599 for ; Tue, 24 Sep 2019 06:37:00 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id EBD4C20665 for ; Tue, 24 Sep 2019 06:36:59 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EBD4C20665 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41390 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeRX-00024m-0x for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:36:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59264) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeBC-0003eY-7h for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB7-0000sX-Th for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52576) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB7-0000re-5k for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:01 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4A6248535C; Tue, 24 Sep 2019 06:20:00 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id B2689601A5; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id D97D79CA5; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 09/16] paaudio: port to the new audio backend api Date: Tue, 24 Sep 2019 08:19:44 +0200 Message-Id: <20190924061951.27916-10-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 24 Sep 2019 06:20:00 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: 21fe8f2cf949039c8c40a0352590c593b104917d.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- configure | 5 - audio/audio_pt_int.h | 22 --- audio/audio_pt_int.c | 173 -------------------- audio/paaudio.c | 372 ++++++------------------------------------- audio/Makefile.objs | 1 - 5 files changed, 45 insertions(+), 528 deletions(-) delete mode 100644 audio/audio_pt_int.h delete mode 100644 audio/audio_pt_int.c diff --git a/configure b/configure index 30544f52e630..397bb476e196 100755 --- a/configure +++ b/configure @@ -297,7 +297,6 @@ host_cc="cc" libs_cpu="" libs_softmmu="" libs_tools="" -audio_pt_int="" audio_win_int="" libs_qga="" debug_info="yes" @@ -3388,7 +3387,6 @@ for drv in $audio_drv_list; do pa | try-pa) if $pkg_config libpulse --exists; then pulse_libs=$($pkg_config libpulse --libs) - audio_pt_int="yes" if test "$drv" = "try-pa"; then audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-pa/pa/') fi @@ -6611,9 +6609,6 @@ echo "PULSE_LIBS=$pulse_libs" >> $config_host_mak echo "COREAUDIO_LIBS=$coreaudio_libs" >> $config_host_mak echo "DSOUND_LIBS=$dsound_libs" >> $config_host_mak echo "OSS_LIBS=$oss_libs" >> $config_host_mak -if test "$audio_pt_int" = "yes" ; then - echo "CONFIG_AUDIO_PT_INT=y" >> $config_host_mak -fi if test "$audio_win_int" = "yes" ; then echo "CONFIG_AUDIO_WIN_INT=y" >> $config_host_mak fi diff --git a/audio/audio_pt_int.h b/audio/audio_pt_int.h deleted file mode 100644 index 4c0c15b9af94..000000000000 --- a/audio/audio_pt_int.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef QEMU_AUDIO_PT_INT_H -#define QEMU_AUDIO_PT_INT_H - -#include - -struct audio_pt { - const char *drv; - pthread_t thread; - pthread_cond_t cond; - pthread_mutex_t mutex; -}; - -int audio_pt_init (struct audio_pt *, void *(*) (void *), void *, - const char *, const char *); -int audio_pt_fini (struct audio_pt *, const char *); -int audio_pt_lock (struct audio_pt *, const char *); -int audio_pt_unlock (struct audio_pt *, const char *); -int audio_pt_wait (struct audio_pt *, const char *); -int audio_pt_unlock_and_signal (struct audio_pt *, const char *); -int audio_pt_join (struct audio_pt *, void **, const char *); - -#endif /* QEMU_AUDIO_PT_INT_H */ diff --git a/audio/audio_pt_int.c b/audio/audio_pt_int.c deleted file mode 100644 index 9f9d44ad4a63..000000000000 --- a/audio/audio_pt_int.c +++ /dev/null @@ -1,173 +0,0 @@ -#include "qemu/osdep.h" -#include "audio.h" - -#define AUDIO_CAP "audio-pt" - -#include "audio_int.h" -#include "audio_pt_int.h" - -static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err, - const char *fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - AUD_vlog (pt->drv, fmt, ap); - va_end (ap); - - AUD_log (NULL, "\n"); - AUD_log (pt->drv, "Reason: %s\n", strerror (err)); -} - -int audio_pt_init (struct audio_pt *p, void *(*func) (void *), - void *opaque, const char *drv, const char *cap) -{ - int err, err2; - const char *efunc; - sigset_t set, old_set; - - p->drv = drv; - - err = sigfillset (&set); - if (err) { - logerr(p, errno, "%s(%s): sigfillset failed", cap, __func__); - return -1; - } - - err = pthread_mutex_init (&p->mutex, NULL); - if (err) { - efunc = "pthread_mutex_init"; - goto err0; - } - - err = pthread_cond_init (&p->cond, NULL); - if (err) { - efunc = "pthread_cond_init"; - goto err1; - } - - err = pthread_sigmask (SIG_BLOCK, &set, &old_set); - if (err) { - efunc = "pthread_sigmask"; - goto err2; - } - - err = pthread_create (&p->thread, NULL, func, opaque); - - err2 = pthread_sigmask (SIG_SETMASK, &old_set, NULL); - if (err2) { - logerr(p, err2, "%s(%s): pthread_sigmask (restore) failed", - cap, __func__); - /* We have failed to restore original signal mask, all bets are off, - so terminate the process */ - exit (EXIT_FAILURE); - } - - if (err) { - efunc = "pthread_create"; - goto err2; - } - - return 0; - - err2: - err2 = pthread_cond_destroy (&p->cond); - if (err2) { - logerr(p, err2, "%s(%s): pthread_cond_destroy failed", cap, __func__); - } - - err1: - err2 = pthread_mutex_destroy (&p->mutex); - if (err2) { - logerr(p, err2, "%s(%s): pthread_mutex_destroy failed", cap, __func__); - } - - err0: - logerr(p, err, "%s(%s): %s failed", cap, __func__, efunc); - return -1; -} - -int audio_pt_fini (struct audio_pt *p, const char *cap) -{ - int err, ret = 0; - - err = pthread_cond_destroy (&p->cond); - if (err) { - logerr(p, err, "%s(%s): pthread_cond_destroy failed", cap, __func__); - ret = -1; - } - - err = pthread_mutex_destroy (&p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_mutex_destroy failed", cap, __func__); - ret = -1; - } - return ret; -} - -int audio_pt_lock (struct audio_pt *p, const char *cap) -{ - int err; - - err = pthread_mutex_lock (&p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_mutex_lock failed", cap, __func__); - return -1; - } - return 0; -} - -int audio_pt_unlock (struct audio_pt *p, const char *cap) -{ - int err; - - err = pthread_mutex_unlock (&p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_mutex_unlock failed", cap, __func__); - return -1; - } - return 0; -} - -int audio_pt_wait (struct audio_pt *p, const char *cap) -{ - int err; - - err = pthread_cond_wait (&p->cond, &p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_cond_wait failed", cap, __func__); - return -1; - } - return 0; -} - -int audio_pt_unlock_and_signal (struct audio_pt *p, const char *cap) -{ - int err; - - err = pthread_mutex_unlock (&p->mutex); - if (err) { - logerr(p, err, "%s(%s): pthread_mutex_unlock failed", cap, __func__); - return -1; - } - err = pthread_cond_signal (&p->cond); - if (err) { - logerr(p, err, "%s(%s): pthread_cond_signal failed", cap, __func__); - return -1; - } - return 0; -} - -int audio_pt_join (struct audio_pt *p, void **arg, const char *cap) -{ - int err; - void *ret; - - err = pthread_join (p->thread, &ret); - if (err) { - logerr(p, err, "%s(%s): pthread_join failed", cap, __func__); - return -1; - } - *arg = ret; - return 0; -} diff --git a/audio/paaudio.c b/audio/paaudio.c index bfef9acaadd0..75fce5320269 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -9,7 +9,6 @@ #define AUDIO_CAP "pulseaudio" #include "audio_int.h" -#include "audio_pt_int.h" typedef struct PAConnection { char *server; @@ -30,28 +29,16 @@ typedef struct { typedef struct { HWVoiceOut hw; - size_t done; - size_t live; - size_t decr; - size_t rpos; pa_stream *stream; - void *pcm_buf; - struct audio_pt pt; paaudio *g; size_t samples; } PAVoiceOut; typedef struct { HWVoiceIn hw; - size_t done; - size_t dead; - size_t incr; - size_t wpos; pa_stream *stream; - void *pcm_buf; - struct audio_pt pt; const void *read_data; - size_t read_index, read_length; + size_t read_length; paaudio *g; size_t samples; } PAVoiceIn; @@ -89,298 +76,96 @@ static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) } #endif -#define CHECK_SUCCESS_GOTO(c, rerror, expression, label) \ +#define CHECK_SUCCESS_GOTO(c, expression, label, msg) \ do { \ if (!(expression)) { \ - if (rerror) { \ - *(rerror) = pa_context_errno ((c)->context); \ - } \ + qpa_logerr(pa_context_errno((c)->context), msg); \ goto label; \ } \ } while (0) -#define CHECK_DEAD_GOTO(c, stream, rerror, label) \ +#define CHECK_DEAD_GOTO(c, stream, label, msg) \ do { \ if (!(c)->context || !PA_CONTEXT_IS_GOOD (pa_context_get_state((c)->context)) || \ !(stream) || !PA_STREAM_IS_GOOD (pa_stream_get_state ((stream)))) { \ if (((c)->context && pa_context_get_state ((c)->context) == PA_CONTEXT_FAILED) || \ ((stream) && pa_stream_get_state ((stream)) == PA_STREAM_FAILED)) { \ - if (rerror) { \ - *(rerror) = pa_context_errno ((c)->context); \ - } \ + qpa_logerr(pa_context_errno((c)->context), msg); \ } else { \ - if (rerror) { \ - *(rerror) = PA_ERR_BADSTATE; \ - } \ + qpa_logerr(PA_ERR_BADSTATE, msg); \ } \ goto label; \ } \ } while (0) -static int qpa_simple_read (PAVoiceIn *p, void *data, size_t length, int *rerror) +static size_t qpa_read(HWVoiceIn *hw, void *data, size_t length) { + PAVoiceIn *p = (PAVoiceIn *) hw; PAConnection *c = p->g->conn; + size_t l; + int r; pa_threaded_mainloop_lock(c->mainloop); - CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); + CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail, + "pa_threaded_mainloop_lock failed\n"); - while (length > 0) { - size_t l; - - while (!p->read_data) { - int r; - - r = pa_stream_peek (p->stream, &p->read_data, &p->read_length); - CHECK_SUCCESS_GOTO(c, rerror, r == 0, unlock_and_fail); - - if (!p->read_data) { - pa_threaded_mainloop_wait(c->mainloop); - CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); - } else { - p->read_index = 0; - } - } - - l = p->read_length < length ? p->read_length : length; - memcpy (data, (const uint8_t *) p->read_data+p->read_index, l); - - data = (uint8_t *) data + l; - length -= l; - - p->read_index += l; - p->read_length -= l; + if (!p->read_length) { + r = pa_stream_peek(p->stream, &p->read_data, &p->read_length); + CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail, + "pa_stream_peek failed\n"); + } - if (!p->read_length) { - int r; + l = MIN(p->read_length, length); + memcpy(data, p->read_data, l); - r = pa_stream_drop (p->stream); - p->read_data = NULL; - p->read_length = 0; - p->read_index = 0; + p->read_data += l; + p->read_length -= l; - CHECK_SUCCESS_GOTO(c, rerror, r == 0, unlock_and_fail); - } + if (!p->read_length) { + r = pa_stream_drop(p->stream); + CHECK_SUCCESS_GOTO(c, r == 0, unlock_and_fail, + "pa_stream_drop failed\n"); } pa_threaded_mainloop_unlock(c->mainloop); - return 0; + return l; unlock_and_fail: pa_threaded_mainloop_unlock(c->mainloop); - return -1; + return 0; } -static int qpa_simple_write (PAVoiceOut *p, const void *data, size_t length, int *rerror) +static size_t qpa_write(HWVoiceOut *hw, void *data, size_t length) { + PAVoiceOut *p = (PAVoiceOut *) hw; PAConnection *c = p->g->conn; + size_t l; + int r; pa_threaded_mainloop_lock(c->mainloop); - CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); + CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail, + "pa_threaded_mainloop_lock failed\n"); - while (length > 0) { - size_t l; - int r; + l = pa_stream_writable_size(p->stream); - while (!(l = pa_stream_writable_size (p->stream))) { - pa_threaded_mainloop_wait(c->mainloop); - CHECK_DEAD_GOTO(c, p->stream, rerror, unlock_and_fail); - } + CHECK_SUCCESS_GOTO(c, l != (size_t) -1, unlock_and_fail, + "pa_stream_writable_size failed\n"); - CHECK_SUCCESS_GOTO(c, rerror, l != (size_t) -1, unlock_and_fail); - - if (l > length) { - l = length; - } - - r = pa_stream_write (p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); - CHECK_SUCCESS_GOTO(c, rerror, r >= 0, unlock_and_fail); - - data = (const uint8_t *) data + l; - length -= l; + if (l > length) { + l = length; } + r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE); + CHECK_SUCCESS_GOTO(c, r >= 0, unlock_and_fail, "pa_stream_write failed\n"); + pa_threaded_mainloop_unlock(c->mainloop); - return 0; + return l; unlock_and_fail: pa_threaded_mainloop_unlock(c->mainloop); - return -1; -} - -static void *qpa_thread_out (void *arg) -{ - PAVoiceOut *pa = arg; - HWVoiceOut *hw = &pa->hw; - - if (audio_pt_lock(&pa->pt, __func__)) { - return NULL; - } - - for (;;) { - size_t decr, to_mix, rpos; - - for (;;) { - if (pa->done) { - goto exit; - } - - if (pa->live > 0) { - break; - } - - if (audio_pt_wait(&pa->pt, __func__)) { - goto exit; - } - } - - decr = to_mix = MIN(pa->live, pa->samples >> 5); - rpos = pa->rpos; - - if (audio_pt_unlock(&pa->pt, __func__)) { - return NULL; - } - - while (to_mix) { - int error; - size_t chunk = MIN (to_mix, hw->samples - rpos); - struct st_sample *src = hw->mix_buf + rpos; - - hw->clip (pa->pcm_buf, src, chunk); - - if (qpa_simple_write (pa, pa->pcm_buf, - chunk << hw->info.shift, &error) < 0) { - qpa_logerr (error, "pa_simple_write failed\n"); - return NULL; - } - - rpos = (rpos + chunk) % hw->samples; - to_mix -= chunk; - } - - if (audio_pt_lock(&pa->pt, __func__)) { - return NULL; - } - - pa->rpos = rpos; - pa->live -= decr; - pa->decr += decr; - } - - exit: - audio_pt_unlock(&pa->pt, __func__); - return NULL; -} - -static size_t qpa_run_out(HWVoiceOut *hw, size_t live) -{ - size_t decr; - PAVoiceOut *pa = (PAVoiceOut *) hw; - - if (audio_pt_lock(&pa->pt, __func__)) { - return 0; - } - - decr = MIN (live, pa->decr); - pa->decr -= decr; - pa->live = live - decr; - hw->rpos = pa->rpos; - if (pa->live > 0) { - audio_pt_unlock_and_signal(&pa->pt, __func__); - } - else { - audio_pt_unlock(&pa->pt, __func__); - } - return decr; -} - -/* capture */ -static void *qpa_thread_in (void *arg) -{ - PAVoiceIn *pa = arg; - HWVoiceIn *hw = &pa->hw; - - if (audio_pt_lock(&pa->pt, __func__)) { - return NULL; - } - - for (;;) { - size_t incr, to_grab, wpos; - - for (;;) { - if (pa->done) { - goto exit; - } - - if (pa->dead > 0) { - break; - } - - if (audio_pt_wait(&pa->pt, __func__)) { - goto exit; - } - } - - incr = to_grab = MIN(pa->dead, pa->samples >> 5); - wpos = pa->wpos; - - if (audio_pt_unlock(&pa->pt, __func__)) { - return NULL; - } - - while (to_grab) { - int error; - size_t chunk = MIN (to_grab, hw->samples - wpos); - void *buf = advance (pa->pcm_buf, wpos); - - if (qpa_simple_read (pa, buf, - chunk << hw->info.shift, &error) < 0) { - qpa_logerr (error, "pa_simple_read failed\n"); - return NULL; - } - - hw->conv (hw->conv_buf + wpos, buf, chunk); - wpos = (wpos + chunk) % hw->samples; - to_grab -= chunk; - } - - if (audio_pt_lock(&pa->pt, __func__)) { - return NULL; - } - - pa->wpos = wpos; - pa->dead -= incr; - pa->incr += incr; - } - - exit: - audio_pt_unlock(&pa->pt, __func__); - return NULL; -} - -static size_t qpa_run_in(HWVoiceIn *hw) -{ - size_t live, incr, dead; - PAVoiceIn *pa = (PAVoiceIn *) hw; - - if (audio_pt_lock(&pa->pt, __func__)) { - return 0; - } - - live = audio_pcm_hw_get_live_in (hw); - dead = hw->samples - live; - incr = MIN (dead, pa->incr); - pa->incr -= incr; - pa->dead = dead - incr; - hw->wpos = pa->wpos; - if (pa->dead > 0) { - audio_pt_unlock_and_signal(&pa->pt, __func__); - } - else { - audio_pt_unlock(&pa->pt, __func__); - } - return incr; + return 0; } static pa_sample_format_t audfmt_to_pa (AudioFormat afmt, int endianness) @@ -468,13 +253,6 @@ static void stream_state_cb (pa_stream *s, void * userdata) } } -static void stream_request_cb (pa_stream *s, size_t length, void *userdata) -{ - PAConnection *c = userdata; - - pa_threaded_mainloop_signal(c->mainloop, 0); -} - static pa_stream *qpa_simple_new ( PAConnection *c, const char *name, @@ -497,8 +275,6 @@ static pa_stream *qpa_simple_new ( } pa_stream_set_state_callback(stream, stream_state_cb, c); - pa_stream_set_read_callback(stream, stream_request_cb, c); - pa_stream_set_write_callback(stream, stream_request_cb, c); flags = PA_STREAM_INTERPOLATE_TIMING @@ -579,28 +355,9 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as, hw->samples = pa->samples = audio_buffer_samples( 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) { - dolog("Could not allocate buffer (%zu bytes)\n", - hw->samples << hw->info.shift); - goto fail2; - } - - if (audio_pt_init(&pa->pt, qpa_thread_out, hw, AUDIO_CAP, __func__)) { - goto fail3; - } return 0; - fail3: - g_free (pa->pcm_buf); - pa->pcm_buf = NULL; - fail2: - if (pa->stream) { - pa_stream_unref (pa->stream); - pa->stream = NULL; - } fail1: return -1; } @@ -647,28 +404,9 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) hw->samples = pa->samples = audio_buffer_samples( 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) { - dolog("Could not allocate buffer (%zu bytes)\n", - hw->samples << hw->info.shift); - goto fail2; - } - - if (audio_pt_init(&pa->pt, qpa_thread_in, hw, AUDIO_CAP, __func__)) { - goto fail3; - } return 0; - fail3: - g_free (pa->pcm_buf); - pa->pcm_buf = NULL; - fail2: - if (pa->stream) { - pa_stream_unref (pa->stream); - pa->stream = NULL; - } fail1: return -1; } @@ -696,42 +434,22 @@ static void qpa_simple_disconnect(PAConnection *c, pa_stream *stream) static void qpa_fini_out (HWVoiceOut *hw) { - void *ret; PAVoiceOut *pa = (PAVoiceOut *) hw; - audio_pt_lock(&pa->pt, __func__); - pa->done = 1; - audio_pt_unlock_and_signal(&pa->pt, __func__); - audio_pt_join(&pa->pt, &ret, __func__); - if (pa->stream) { qpa_simple_disconnect(pa->g->conn, pa->stream); pa->stream = NULL; } - - audio_pt_fini(&pa->pt, __func__); - g_free (pa->pcm_buf); - pa->pcm_buf = NULL; } static void qpa_fini_in (HWVoiceIn *hw) { - void *ret; PAVoiceIn *pa = (PAVoiceIn *) hw; - audio_pt_lock(&pa->pt, __func__); - pa->done = 1; - audio_pt_unlock_and_signal(&pa->pt, __func__); - audio_pt_join(&pa->pt, &ret, __func__); - if (pa->stream) { qpa_simple_disconnect(pa->g->conn, pa->stream); pa->stream = NULL; } - - audio_pt_fini(&pa->pt, __func__); - g_free (pa->pcm_buf); - pa->pcm_buf = NULL; } static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) @@ -1005,12 +723,12 @@ static void qpa_audio_fini (void *opaque) static struct audio_pcm_ops qpa_pcm_ops = { .init_out = qpa_init_out, .fini_out = qpa_fini_out, - .run_out = qpa_run_out, + .write = qpa_write, .ctl_out = qpa_ctl_out, .init_in = qpa_init_in, .fini_in = qpa_fini_in, - .run_in = qpa_run_in, + .read = qpa_read, .ctl_in = qpa_ctl_in }; diff --git a/audio/Makefile.objs b/audio/Makefile.objs index dca87f63470d..d7490a379f3e 100644 --- a/audio/Makefile.objs +++ b/audio/Makefile.objs @@ -2,7 +2,6 @@ common-obj-y = audio.o audio_legacy.o noaudio.o wavaudio.o mixeng.o common-obj-$(CONFIG_SPICE) += spiceaudio.o common-obj-$(CONFIG_AUDIO_COREAUDIO) += coreaudio.o common-obj-$(CONFIG_AUDIO_DSOUND) += dsoundaudio.o -common-obj-$(CONFIG_AUDIO_PT_INT) += audio_pt_int.o common-obj-$(CONFIG_AUDIO_WIN_INT) += audio_win_int.o common-obj-y += wavcapture.o From patchwork Tue Sep 24 06:19:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157957 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D3DF51668 for ; Tue, 24 Sep 2019 06:29:00 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B39BB20673 for ; Tue, 24 Sep 2019 06:29:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B39BB20673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41334 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeJn-0004Sn-Pz for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:28:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59282) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeBE-0003hY-I2 for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeBC-0000uD-68 for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37908) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeBB-0000tx-UB for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:06 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3B51E811DC; Tue, 24 Sep 2019 06:20:05 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id CA9DD5D6A5; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id E1F4F9CA6; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 10/16] sdlaudio: port to the new audio backend api Date: Tue, 24 Sep 2019 08:19:45 +0200 Message-Id: <20190924061951.27916-11-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 24 Sep 2019 06:20:05 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: ac1722a03fb1b530c2081f46585ce7fa80ebef6c.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/sdlaudio.c | 87 +++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index 14b11f033521..f7ac8cd10188 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -41,8 +41,6 @@ typedef struct SDLVoiceOut { HWVoiceOut hw; - size_t live; - size_t decr; } SDLVoiceOut; static struct SDLAudioState { @@ -184,62 +182,59 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len) SDLVoiceOut *sdl = opaque; SDLAudioState *s = &glob_sdl; HWVoiceOut *hw = &sdl->hw; - size_t samples = len >> hw->info.shift; - size_t to_mix, decr; - if (s->exit || !sdl->live) { + if (s->exit) { return; } /* dolog ("in callback samples=%zu live=%zu\n", samples, sdl->live); */ - to_mix = MIN(samples, sdl->live); - decr = to_mix; - while (to_mix) { - size_t chunk = MIN(to_mix, hw->samples - hw->rpos); - struct st_sample *src = hw->mix_buf + hw->rpos; - - /* dolog ("in callback to_mix %zu, chunk %zu\n", to_mix, chunk); */ - hw->clip(buf, src, chunk); - hw->rpos = (hw->rpos + chunk) % hw->samples; - to_mix -= chunk; - buf += chunk << hw->info.shift; + while (hw->pending_emul && len) { + size_t write_len; + ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul; + if (start < 0) { + start += hw->size_emul; + } + assert(start >= 0 && start < hw->size_emul); + + write_len = MIN(MIN(hw->pending_emul, len), + hw->size_emul - start); + + memcpy(buf, hw->buf_emul + start, write_len); + hw->pending_emul -= write_len; + len -= write_len; + buf += write_len; } - samples -= decr; - sdl->live -= decr; - sdl->decr += decr; - - /* dolog ("done len=%zu\n", len); */ - /* SDL2 does not clear the remaining buffer for us, so do it on our own */ - if (samples) { - memset(buf, 0, samples << hw->info.shift); + /* clear remaining buffer that we couldn't fill with data */ + if (len) { + memset(buf, 0, len); } } -static size_t sdl_run_out(HWVoiceOut *hw, size_t live) -{ - size_t decr; - SDLVoiceOut *sdl = (SDLVoiceOut *) hw; - - SDL_LockAudio(); - - if (sdl->decr > live) { - ldebug ("sdl->decr %d live %d sdl->live %d\n", - sdl->decr, - live, - sdl->live); +#define SDL_WRAPPER_FUNC(name, ret_type, args_decl, args, fail, unlock) \ + static ret_type glue(sdl_, name)args_decl \ + { \ + ret_type ret; \ + \ + SDL_LockAudio(); \ + \ + ret = glue(audio_generic_, name)args; \ + \ + SDL_UnlockAudio(); \ + return ret; \ } - decr = MIN (sdl->decr, live); - sdl->decr -= decr; +SDL_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size), + (hw, size), *size = 0, sdl_unlock) +SDL_WRAPPER_FUNC(put_buffer_out_nowrite, size_t, + (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size), + /*nothing*/, sdl_unlock_and_post) +SDL_WRAPPER_FUNC(write, size_t, + (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size), + /*nothing*/, sdl_unlock_and_post) - sdl->live = live; - - SDL_UnlockAudio(); - - return decr; -} +#undef SDL_WRAPPER_FUNC static void sdl_fini_out (HWVoiceOut *hw) { @@ -336,7 +331,9 @@ static void sdl_audio_fini (void *opaque) static struct audio_pcm_ops sdl_pcm_ops = { .init_out = sdl_init_out, .fini_out = sdl_fini_out, - .run_out = sdl_run_out, + .write = sdl_write, + .get_buffer_out = sdl_get_buffer_out, + .put_buffer_out = sdl_put_buffer_out_nowrite, .ctl_out = sdl_ctl_out, }; From patchwork Tue Sep 24 06:19:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157961 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8F33017EE for ; Tue, 24 Sep 2019 06:34:14 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6E03120665 for ; Tue, 24 Sep 2019 06:34:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6E03120665 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41362 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeOr-0007kC-4s for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:34:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59231) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeBA-0003bo-2H for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB7-0000s3-68 for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39282) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB6-0000rK-Ms for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:00 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D2A0013A82; Tue, 24 Sep 2019 06:19:59 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id CD79910018F8; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id EAFC79CA7; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 11/16] spiceaudio: port to the new audio backend api Date: Tue, 24 Sep 2019 08:19:46 +0200 Message-Id: <20190924061951.27916-12-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Tue, 24 Sep 2019 06:19:59 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: 4d3356df9ccbffee2f710b93d456443c81e3f011.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/spiceaudio.c | 116 ++++++++++++++++----------------------------- 1 file changed, 42 insertions(+), 74 deletions(-) diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 26873c7f22a5..ff4e4dcbb022 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -51,7 +51,7 @@ typedef struct SpiceVoiceOut { SpiceRateCtl rate; int active; uint32_t *frame; - uint32_t *fpos; + uint32_t fpos; uint32_t fsize; } SpiceVoiceOut; @@ -60,7 +60,6 @@ typedef struct SpiceVoiceIn { SpiceRecordInstance sin; SpiceRateCtl rate; int active; - uint32_t samples[LINE_IN_SAMPLES]; } SpiceVoiceIn; static const SpicePlaybackInterface playback_sif = { @@ -152,44 +151,40 @@ static void line_out_fini (HWVoiceOut *hw) spice_server_remove_interface (&out->sin.base); } -static size_t line_out_run (HWVoiceOut *hw, size_t live) +static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size) { - SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); - size_t rpos, decr; - size_t samples; + SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); + size_t decr; - if (!live) { - return 0; + if (!out->frame) { + spice_server_playback_get_buffer(&out->sin, &out->frame, &out->fsize); + out->fpos = 0; } - decr = rate_get_samples (&hw->info, &out->rate); - decr = MIN (live, decr); + if (out->frame) { + decr = rate_get_samples(&hw->info, &out->rate); + decr = MIN(out->fsize - out->fpos, decr); - samples = decr; - rpos = hw->rpos; - while (samples) { - int left_till_end_samples = hw->samples - rpos; - int len = MIN (samples, left_till_end_samples); + *size = decr << hw->info.shift; + } else { + rate_start(&out->rate); + } + return out->frame + out->fpos; +} + +static size_t line_out_put_buffer(HWVoiceOut *hw, void *buf, size_t size) +{ + SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); - if (!out->frame) { - spice_server_playback_get_buffer (&out->sin, &out->frame, &out->fsize); - out->fpos = out->frame; - } - if (out->frame) { - len = MIN (len, out->fsize); - hw->clip (out->fpos, hw->mix_buf + rpos, len); - out->fsize -= len; - out->fpos += len; - if (out->fsize == 0) { - spice_server_playback_put_samples (&out->sin, out->frame); - out->frame = out->fpos = NULL; - } - } - rpos = (rpos + len) % hw->samples; - samples -= len; + assert(buf == out->frame + out->fpos && out->fpos <= out->fsize); + out->fpos += size >> 2; + + if (out->fpos == out->fsize) { /* buffer full */ + spice_server_playback_put_samples(&out->sin, out->frame); + out->frame = NULL; } - hw->rpos = rpos; - return decr; + + return size; } static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) @@ -211,9 +206,9 @@ static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) } out->active = 0; if (out->frame) { - memset (out->fpos, 0, out->fsize << 2); + memset(out->frame + out->fpos, 0, (out->fsize - out->fpos) << 2); spice_server_playback_put_samples (&out->sin, out->frame); - out->frame = out->fpos = NULL; + out->frame = NULL; } spice_server_playback_stop (&out->sin); break; @@ -275,49 +270,20 @@ static void line_in_fini (HWVoiceIn *hw) spice_server_remove_interface (&in->sin.base); } -static size_t line_in_run(HWVoiceIn *hw) +static size_t line_in_read(HWVoiceIn *hw, void *buf, size_t len) { SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); - size_t num_samples; - int ready; - size_t len[2]; - uint64_t delta_samp; - const uint32_t *samples; + uint64_t delta_samp = rate_get_samples(&hw->info, &in->rate); + uint64_t to_read = MIN(len >> 2, delta_samp); + size_t ready = spice_server_record_get_samples(&in->sin, buf, to_read); - if (!(num_samples = hw->samples - audio_pcm_hw_get_live_in (hw))) { - return 0; - } - - delta_samp = rate_get_samples (&hw->info, &in->rate); - num_samples = MIN (num_samples, delta_samp); - - ready = spice_server_record_get_samples (&in->sin, in->samples, num_samples); - samples = in->samples; + /* XXX: do we need this? */ if (ready == 0) { - static const uint32_t silence[LINE_IN_SAMPLES]; - samples = silence; - ready = LINE_IN_SAMPLES; + memset(buf, 0, to_read << 2); + ready = to_read; } - num_samples = MIN (ready, num_samples); - - if (hw->wpos + num_samples > hw->samples) { - len[0] = hw->samples - hw->wpos; - len[1] = num_samples - len[0]; - } else { - len[0] = num_samples; - len[1] = 0; - } - - hw->conv (hw->conv_buf + hw->wpos, samples, len[0]); - - if (len[1]) { - hw->conv (hw->conv_buf, samples + len[0], len[1]); - } - - hw->wpos = (hw->wpos + num_samples) % hw->samples; - - return num_samples; + return ready << 2; } static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) @@ -366,12 +332,14 @@ static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) static struct audio_pcm_ops audio_callbacks = { .init_out = line_out_init, .fini_out = line_out_fini, - .run_out = line_out_run, + .write = audio_generic_write, + .get_buffer_out = line_out_get_buffer, + .put_buffer_out = line_out_put_buffer, .ctl_out = line_out_ctl, .init_in = line_in_init, .fini_in = line_in_fini, - .run_in = line_in_run, + .read = line_in_read, .ctl_in = line_in_ctl, }; From patchwork Tue Sep 24 06:19:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157955 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BEF261709 for ; Tue, 24 Sep 2019 06:28:53 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 971F120673 for ; Tue, 24 Sep 2019 06:28:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 971F120673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41332 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeJg-0004QS-9S for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:28:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59224) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeB9-0003au-Fq for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeB7-0000rv-5C for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45978) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeB6-0000rL-Me for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:00 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D3C4C18CB8E9; Tue, 24 Sep 2019 06:19:59 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id D1D1A1001947; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id F3AFF9CBB; Tue, 24 Sep 2019 08:19:51 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 12/16] wavaudio: port to the new audio backend api Date: Tue, 24 Sep 2019 08:19:47 +0200 Message-Id: <20190924061951.27916-13-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.63]); Tue, 24 Sep 2019 06:19:59 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: eede77aeb9c17b379948b0b6d2ac10f45d74fa62.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/wavaudio.c | 54 ++++++++---------------------------------------- 1 file changed, 9 insertions(+), 45 deletions(-) diff --git a/audio/wavaudio.c b/audio/wavaudio.c index b6eeeb4e26ef..78af2f1338d2 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -36,52 +36,28 @@ typedef struct WAVVoiceOut { HWVoiceOut hw; FILE *f; int64_t old_ticks; - void *pcm_buf; int total_samples; } WAVVoiceOut; -static size_t wav_run_out(HWVoiceOut *hw, size_t live) +static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len) { WAVVoiceOut *wav = (WAVVoiceOut *) hw; - size_t rpos, decr, samples; - uint8_t *dst; - struct st_sample *src; int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); int64_t ticks = now - wav->old_ticks; int64_t bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - if (bytes > INT_MAX) { - samples = INT_MAX >> hw->info.shift; - } - else { - samples = bytes >> hw->info.shift; - } - + bytes = MIN(bytes, len); + bytes = bytes >> hw->info.shift << hw->info.shift; wav->old_ticks = now; - decr = MIN (live, samples); - samples = decr; - rpos = hw->rpos; - while (samples) { - int left_till_end_samples = hw->samples - rpos; - int convert_samples = MIN (samples, left_till_end_samples); - src = hw->mix_buf + rpos; - dst = advance (wav->pcm_buf, rpos << hw->info.shift); - - hw->clip (dst, src, convert_samples); - if (fwrite (dst, convert_samples << hw->info.shift, 1, wav->f) != 1) { - dolog ("wav_run_out: fwrite of %d bytes failed\nReaons: %s\n", - convert_samples << hw->info.shift, strerror (errno)); - } - - rpos = (rpos + convert_samples) % hw->samples; - samples -= convert_samples; - wav->total_samples += convert_samples; + if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) { + dolog("wav_write_out: fwrite of %" PRId64 " bytes failed\nReason: %s\n", + bytes, strerror(errno)); } - hw->rpos = rpos; - return decr; + wav->total_samples += bytes >> hw->info.shift; + return bytes; } /* VICE code: Store number as little endian. */ @@ -137,13 +113,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, audio_pcm_init_info (&hw->info, &wav_as); hw->samples = 1024; - wav->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); - if (!wav->pcm_buf) { - dolog("Could not allocate buffer (%zu bytes)\n", - hw->samples << hw->info.shift); - return -1; - } - le_store (hdr + 22, hw->info.nchannels, 2); le_store (hdr + 24, hw->info.freq, 4); le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4); @@ -153,8 +122,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, if (!wav->f) { dolog ("Failed to open wave file `%s'\nReason: %s\n", wav_path, strerror(errno)); - g_free (wav->pcm_buf); - wav->pcm_buf = NULL; return -1; } @@ -208,9 +175,6 @@ static void wav_fini_out (HWVoiceOut *hw) wav->f, strerror (errno)); } wav->f = NULL; - - g_free (wav->pcm_buf); - wav->pcm_buf = NULL; } static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) @@ -234,7 +198,7 @@ static void wav_audio_fini (void *opaque) static struct audio_pcm_ops wav_pcm_ops = { .init_out = wav_init_out, .fini_out = wav_fini_out, - .run_out = wav_run_out, + .write = wav_write_out, .ctl_out = wav_ctl_out, }; From patchwork Tue Sep 24 06:19:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157963 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0BEF21850 for ; Tue, 24 Sep 2019 06:34:15 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E120720665 for ; Tue, 24 Sep 2019 06:34:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E120720665 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41364 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeOr-0007ko-Pp for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:34:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59292) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeBF-0003iT-7n for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeBD-0000um-Md for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58978) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeBD-0000uZ-Cb for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:07 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A68CF10DCC8A; Tue, 24 Sep 2019 06:20:06 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id D474D5D9CA; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 097F69CBC; Tue, 24 Sep 2019 08:19:52 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 13/16] audio: remove remains of the old backend api Date: Tue, 24 Sep 2019 08:19:48 +0200 Message-Id: <20190924061951.27916-14-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.64]); Tue, 24 Sep 2019 06:20:06 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Signed-off-by: Kővágó, Zoltán Message-id: 497decab6d0f0fb9529bea63ec7ce0bd7b553038.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/audio_int.h | 7 ------- audio/audio.c | 42 ++++++------------------------------------ 2 files changed, 6 insertions(+), 43 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index 8fb1ca8a8d0f..c76d7c39e84c 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -153,7 +153,6 @@ struct audio_driver { struct audio_pcm_ops { int (*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque); void (*fini_out)(HWVoiceOut *hw); - size_t (*run_out)(HWVoiceOut *hw, size_t live); size_t (*write) (HWVoiceOut *hw, void *buf, size_t size); /* * get a buffer that after later can be passed to put_buffer_out; optional @@ -171,7 +170,6 @@ struct audio_pcm_ops { int (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); void (*fini_in) (HWVoiceIn *hw); - size_t (*run_in)(HWVoiceIn *hw); size_t (*read) (HWVoiceIn *hw, void *buf, size_t size); void *(*get_buffer_in)(HWVoiceIn *hw, size_t *size); void (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size); @@ -237,11 +235,6 @@ audio_driver *audio_driver_lookup(const char *name); void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as); void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); -size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw); - -size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, - size_t live, size_t pending); - int audio_bug (const char *funcname, int cond); void *audio_calloc (const char *funcname, int nmemb, size_t size); diff --git a/audio/audio.c b/audio/audio.c index e29a1e15eb30..435bcf20c139 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -541,7 +541,7 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw) return m; } -size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) +static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) { size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); if (audio_bug(__func__, live > hw->samples)) { @@ -551,29 +551,7 @@ size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) return live; } -size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, - size_t live, size_t pending) -{ - size_t left = hw->samples - pending; - size_t len = MIN (left, live); - size_t clipped = 0; - - while (len) { - struct st_sample *src = hw->mix_buf + hw->rpos; - uint8_t *dst = advance (pcm_buf, hw->rpos << hw->info.shift); - size_t samples_till_end_of_buf = hw->samples - hw->rpos; - size_t samples_to_clip = MIN (len, samples_till_end_of_buf); - - hw->clip (dst, src, samples_to_clip); - - hw->rpos = (hw->rpos + samples_to_clip) % hw->samples; - len -= samples_to_clip; - clipped += samples_to_clip; - } - return clipped; -} - -static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t len) +static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len) { size_t clipped = 0; size_t pos = hw->rpos; @@ -1083,7 +1061,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) } decr = MIN(size >> hw->info.shift, live); - audio_pcm_hw_clip_out2(hw, buf, decr); + audio_pcm_hw_clip_out(hw, buf, decr); proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >> hw->info.shift; @@ -1146,11 +1124,7 @@ static void audio_run_out (AudioState *s) } prev_rpos = hw->rpos; - if (hw->pcm_ops->run_out) { - played = hw->pcm_ops->run_out(hw, live); - } else { - played = audio_pcm_hw_run_out(hw, live); - } + played = audio_pcm_hw_run_out(hw, live); replay_audio_out(&played); if (audio_bug(__func__, hw->rpos >= hw->samples)) { dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n", @@ -1247,12 +1221,8 @@ static void audio_run_in (AudioState *s) size_t captured = 0, min; if (replay_mode != REPLAY_MODE_PLAY) { - if (hw->pcm_ops->run_in) { - captured = hw->pcm_ops->run_in(hw); - } else { - captured = audio_pcm_hw_run_in( - hw, hw->samples - audio_pcm_hw_get_live_in(hw)); - } + captured = audio_pcm_hw_run_in( + hw, hw->samples - audio_pcm_hw_get_live_in(hw)); } replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples); From patchwork Tue Sep 24 06:19:49 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157949 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3DBC21668 for ; Tue, 24 Sep 2019 06:25:00 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0E6DE20673 for ; Tue, 24 Sep 2019 06:25:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0E6DE20673 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41310 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeFu-0000dy-Bb for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:24:58 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59319) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeBG-0003jn-Q7 for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeBD-0000uu-SO for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59768) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeBD-0000uc-IV for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:07 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D31A08BA2DA; Tue, 24 Sep 2019 06:20:06 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id D81B660925; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 16B189C74; Tue, 24 Sep 2019 08:19:52 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 14/16] audio: unify input and output mixeng buffer management Date: Tue, 24 Sep 2019 08:19:49 +0200 Message-Id: <20190924061951.27916-15-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.68]); Tue, 24 Sep 2019 06:20:06 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán Usage notes: hw->samples became hw->{mix,conv}_buf->size, except before initialization (audio_pcm_hw_alloc_resources_*), hw->samples gives the initial size of the STSampleBuffer. The next commit tries to fix this inconsistency. Signed-off-by: Kővágó, Zoltán Message-id: a78caeb2eeb6348ecb45bb2c81709570ef8ac5b3.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/audio_int.h | 12 ++-- audio/audio_template.h | 19 +++---- audio/audio.c | 122 +++++++++++++++++++++-------------------- audio/ossaudio.c | 3 +- 4 files changed, 80 insertions(+), 76 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index c76d7c39e84c..20021df9e8be 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -52,6 +52,11 @@ struct audio_pcm_info { typedef struct AudioState AudioState; typedef struct SWVoiceCap SWVoiceCap; +typedef struct STSampleBuffer { + size_t pos, size; + st_sample samples[]; +} STSampleBuffer; + typedef struct HWVoiceOut { AudioState *s; int enabled; @@ -60,11 +65,9 @@ typedef struct HWVoiceOut { struct audio_pcm_info info; f_sample *clip; - - size_t rpos; uint64_t ts_helper; - struct st_sample *mix_buf; + STSampleBuffer *mix_buf; void *buf_emul; size_t pos_emul, pending_emul, size_emul; @@ -84,11 +87,10 @@ typedef struct HWVoiceIn { t_sample *conv; - size_t wpos; size_t total_samples_captured; uint64_t ts_helper; - struct st_sample *conv_buf; + STSampleBuffer *conv_buf; void *buf_emul; size_t pos_emul, pending_emul, size_emul; diff --git a/audio/audio_template.h b/audio/audio_template.h index ff4a173f1810..87c6d2d27102 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -76,16 +76,15 @@ static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) HWBUF = NULL; } -static bool glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw) +static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw) { - HWBUF = audio_calloc(__func__, hw->samples, sizeof(struct st_sample)); - if (!HWBUF) { - dolog("Could not allocate " NAME " buffer (%zu samples)\n", - hw->samples); - return false; + size_t samples = hw->samples; + if (audio_bug(__func__, samples == 0)) { + dolog("Attempted to allocate empty buffer\n"); } - return true; + HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples); + HWBUF->size = samples; } static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw) @@ -104,7 +103,7 @@ static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw) { int samples; - samples = ((int64_t) sw->hw->samples << 32) / sw->ratio; + samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio; sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample)); if (!sw->buf) { @@ -280,9 +279,7 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, [hw->info.swap_endianness] [audio_bits_to_index (hw->info.bits)]; - if (!glue(audio_pcm_hw_alloc_resources_, TYPE)(hw)) { - goto err1; - } + glue(audio_pcm_hw_alloc_resources_, TYPE)(hw); QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries); glue (s->nb_hw_voices_, TYPE) -= 1; diff --git a/audio/audio.c b/audio/audio.c index 435bcf20c139..ba07fb77dd4f 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -544,8 +544,8 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw) static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) { size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); - if (audio_bug(__func__, live > hw->samples)) { - dolog("live=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live > hw->conv_buf->size)) { + dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); return 0; } return live; @@ -554,17 +554,17 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len) { size_t clipped = 0; - size_t pos = hw->rpos; + size_t pos = hw->mix_buf->pos; while (len) { - st_sample *src = hw->mix_buf + pos; + st_sample *src = hw->mix_buf->samples + pos; uint8_t *dst = advance(pcm_buf, clipped << hw->info.shift); - size_t samples_till_end_of_buf = hw->samples - pos; + size_t samples_till_end_of_buf = hw->mix_buf->size - pos; size_t samples_to_clip = MIN(len, samples_till_end_of_buf); hw->clip(dst, src, samples_to_clip); - pos = (pos + samples_to_clip) % hw->samples; + pos = (pos + samples_to_clip) % hw->mix_buf->size; len -= samples_to_clip; clipped += samples_to_clip; } @@ -579,17 +579,17 @@ static size_t audio_pcm_sw_get_rpos_in(SWVoiceIn *sw) ssize_t live = hw->total_samples_captured - sw->total_hw_samples_acquired; ssize_t rpos; - if (audio_bug(__func__, live < 0 || live > hw->samples)) { - dolog("live=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live < 0 || live > hw->conv_buf->size)) { + dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); return 0; } - rpos = hw->wpos - live; + rpos = hw->conv_buf->pos - live; if (rpos >= 0) { return rpos; } else { - return hw->samples + rpos; + return hw->conv_buf->size + rpos; } } @@ -599,11 +599,11 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0; struct st_sample *src, *dst = sw->buf; - rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples; + rpos = audio_pcm_sw_get_rpos_in(sw) % hw->conv_buf->size; live = hw->total_samples_captured - sw->total_hw_samples_acquired; - if (audio_bug(__func__, live > hw->samples)) { - dolog("live_in=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live > hw->conv_buf->size)) { + dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); return 0; } @@ -616,11 +616,11 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) swlim = MIN (swlim, samples); while (swlim) { - src = hw->conv_buf + rpos; - if (hw->wpos > rpos) { - isamp = hw->wpos - rpos; + src = hw->conv_buf->samples + rpos; + if (hw->conv_buf->pos > rpos) { + isamp = hw->conv_buf->pos - rpos; } else { - isamp = hw->samples - rpos; + isamp = hw->conv_buf->size - rpos; } if (!isamp) { @@ -630,7 +630,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) st_rate_flow (sw->rate, src, dst, &isamp, &osamp); swlim -= osamp; - rpos = (rpos + isamp) % hw->samples; + rpos = (rpos + isamp) % hw->conv_buf->size; dst += osamp; ret += osamp; total += isamp; @@ -678,8 +678,8 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live) if (nb_live1) { size_t live = smin; - if (audio_bug(__func__, live > hw->samples)) { - dolog("live=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live > hw->mix_buf->size)) { + dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size); return 0; } return live; @@ -699,11 +699,11 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) return size; } - hwsamples = sw->hw->samples; + hwsamples = sw->hw->mix_buf->size; live = sw->total_hw_samples_mixed; if (audio_bug(__func__, live > hwsamples)) { - dolog("live=%zu hw->samples=%zu\n", live, hwsamples); + dolog("live=%zu hw->mix_buf->size=%zu\n", live, hwsamples); return 0; } @@ -714,7 +714,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) return 0; } - wpos = (sw->hw->rpos + live) % hwsamples; + wpos = (sw->hw->mix_buf->pos + live) % hwsamples; samples = size >> sw->info.shift; dead = hwsamples - live; @@ -740,7 +740,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) st_rate_flow_mix ( sw->rate, sw->buf + pos, - sw->hw->mix_buf + wpos, + sw->hw->mix_buf->samples + wpos, &isamp, &osamp ); @@ -868,7 +868,7 @@ size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size) int AUD_get_buffer_size_out (SWVoiceOut *sw) { - return sw->hw->samples << sw->hw->info.shift; + return sw->hw->mix_buf->size << sw->hw->info.shift; } void AUD_set_active_out (SWVoiceOut *sw, int on) @@ -969,8 +969,9 @@ static size_t audio_get_avail (SWVoiceIn *sw) } live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired; - if (audio_bug(__func__, live > sw->hw->samples)) { - dolog("live=%zu sw->hw->samples=%zu\n", live, sw->hw->samples); + if (audio_bug(__func__, live > sw->hw->conv_buf->size)) { + dolog("live=%zu sw->hw->conv_buf->size=%zu\n", live, + sw->hw->conv_buf->size); return 0; } @@ -993,12 +994,13 @@ static size_t audio_get_free(SWVoiceOut *sw) live = sw->total_hw_samples_mixed; - if (audio_bug(__func__, live > sw->hw->samples)) { - dolog("live=%zu sw->hw->samples=%zu\n", live, sw->hw->samples); + if (audio_bug(__func__, live > sw->hw->mix_buf->size)) { + dolog("live=%zu sw->hw->mix_buf->size=%zu\n", live, + sw->hw->mix_buf->size); return 0; } - dead = sw->hw->samples - live; + dead = sw->hw->mix_buf->size - live; #ifdef DEBUG_OUT dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n", @@ -1023,12 +1025,12 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos, n = samples; while (n) { - size_t till_end_of_hw = hw->samples - rpos2; + size_t till_end_of_hw = hw->mix_buf->size - rpos2; size_t to_write = MIN(till_end_of_hw, n); size_t bytes = to_write << hw->info.shift; size_t written; - sw->buf = hw->mix_buf + rpos2; + sw->buf = hw->mix_buf->samples + rpos2; written = audio_pcm_sw_write (sw, NULL, bytes); if (written - bytes) { dolog("Could not mix %zu bytes into a capture " @@ -1037,14 +1039,14 @@ static void audio_capture_mix_and_clear(HWVoiceOut *hw, size_t rpos, break; } n -= to_write; - rpos2 = (rpos2 + to_write) % hw->samples; + rpos2 = (rpos2 + to_write) % hw->mix_buf->size; } } } - n = MIN(samples, hw->samples - rpos); - mixeng_clear(hw->mix_buf + rpos, n); - mixeng_clear(hw->mix_buf, samples - n); + n = MIN(samples, hw->mix_buf->size - rpos); + mixeng_clear(hw->mix_buf->samples + rpos, n); + mixeng_clear(hw->mix_buf->samples, samples - n); } static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) @@ -1056,7 +1058,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) void *buf = hw->pcm_ops->get_buffer_out(hw, &size); if (!buf) { /* retrying will likely won't help, drop everything. */ - hw->rpos = (hw->rpos + live) % hw->samples; + hw->mix_buf->pos = (hw->mix_buf->pos + live) % hw->mix_buf->size; return clipped + live; } @@ -1067,7 +1069,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t live) live -= proc; clipped += proc; - hw->rpos = (hw->rpos + proc) % hw->samples; + hw->mix_buf->pos = (hw->mix_buf->pos + proc) % hw->mix_buf->size; if (proc == 0 || proc < decr) { break; @@ -1091,8 +1093,8 @@ static void audio_run_out (AudioState *s) live = 0; } - if (audio_bug(__func__, live > hw->samples)) { - dolog ("live=%zu hw->samples=%zu\n", live, hw->samples); + if (audio_bug(__func__, live > hw->mix_buf->size)) { + dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size); continue; } @@ -1123,13 +1125,13 @@ static void audio_run_out (AudioState *s) continue; } - prev_rpos = hw->rpos; + prev_rpos = hw->mix_buf->pos; played = audio_pcm_hw_run_out(hw, live); replay_audio_out(&played); - if (audio_bug(__func__, hw->rpos >= hw->samples)) { - dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n", - hw->rpos, hw->samples, played); - hw->rpos = 0; + if (audio_bug(__func__, hw->mix_buf->pos >= hw->mix_buf->size)) { + dolog("hw->mix_buf->pos=%zu hw->mix_buf->size=%zu played=%zu\n", + hw->mix_buf->pos, hw->mix_buf->size, played); + hw->mix_buf->pos = 0; } #ifdef DEBUG_OUT @@ -1186,6 +1188,7 @@ static void audio_run_out (AudioState *s) static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) { size_t conv = 0; + STSampleBuffer *conv_buf = hw->conv_buf; while (samples) { size_t proc; @@ -1199,10 +1202,10 @@ static size_t audio_pcm_hw_run_in(HWVoiceIn *hw, size_t samples) } proc = MIN(size >> hw->info.shift, - hw->samples - hw->wpos); + conv_buf->size - conv_buf->pos); - hw->conv(hw->conv_buf + hw->wpos, buf, proc); - hw->wpos = (hw->wpos + proc) % hw->samples; + hw->conv(conv_buf->samples + conv_buf->pos, buf, proc); + conv_buf->pos = (conv_buf->pos + proc) % conv_buf->size; samples -= proc; conv += proc; @@ -1222,9 +1225,10 @@ static void audio_run_in (AudioState *s) if (replay_mode != REPLAY_MODE_PLAY) { captured = audio_pcm_hw_run_in( - hw, hw->samples - audio_pcm_hw_get_live_in(hw)); + hw, hw->conv_buf->size - audio_pcm_hw_get_live_in(hw)); } - replay_audio_in(&captured, hw->conv_buf, &hw->wpos, hw->samples); + replay_audio_in(&captured, hw->conv_buf->samples, &hw->conv_buf->pos, + hw->conv_buf->size); min = audio_pcm_hw_find_min_in (hw); hw->total_samples_captured += captured - min; @@ -1255,14 +1259,14 @@ static void audio_run_capture (AudioState *s) SWVoiceOut *sw; captured = live = audio_pcm_hw_get_live_out (hw, NULL); - rpos = hw->rpos; + rpos = hw->mix_buf->pos; while (live) { - size_t left = hw->samples - rpos; + size_t left = hw->mix_buf->size - rpos; size_t to_capture = MIN(live, left); struct st_sample *src; struct capture_callback *cb; - src = hw->mix_buf + rpos; + src = hw->mix_buf->samples + rpos; hw->clip (cap->buf, src, to_capture); mixeng_clear (src, to_capture); @@ -1270,10 +1274,10 @@ static void audio_run_capture (AudioState *s) cb->ops.capture (cb->opaque, cap->buf, to_capture << hw->info.shift); } - rpos = (rpos + to_capture) % hw->samples; + rpos = (rpos + to_capture) % hw->mix_buf->size; live -= to_capture; } - hw->rpos = rpos; + hw->mix_buf->pos = rpos; for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { if (!sw->active && sw->empty) { @@ -1321,7 +1325,7 @@ void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size) ssize_t start; if (unlikely(!hw->buf_emul)) { - size_t calc_size = hw->samples << hw->info.shift; + size_t calc_size = hw->conv_buf->size << hw->info.shift; hw->buf_emul = g_malloc(calc_size); hw->size_emul = calc_size; hw->pos_emul = hw->pending_emul = 0; @@ -1357,7 +1361,7 @@ void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size) void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size) { if (unlikely(!hw->buf_emul)) { - size_t calc_size = hw->samples << hw->info.shift; + size_t calc_size = hw->mix_buf->size << hw->info.shift; hw->buf_emul = g_malloc(calc_size); hw->size_emul = calc_size; @@ -1764,11 +1768,11 @@ CaptureVoiceOut *AUD_add_capture( /* XXX find a more elegant way */ hw->samples = 4096 * 4; - hw->mix_buf = g_new0(struct st_sample, hw->samples); + audio_pcm_hw_alloc_resources_out(hw); audio_pcm_init_info (&hw->info, as); - cap->buf = g_malloc0_n(hw->samples, 1 << hw->info.shift); + cap->buf = g_malloc0_n(hw->mix_buf->size, 1 << hw->info.shift); hw->clip = mixeng_clip [hw->info.nchannels == 2] diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 278251270691..76c082d5e2a5 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -585,7 +585,8 @@ static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } - audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->samples); + audio_pcm_info_clear_buf( + &hw->info, hw->buf_emul, hw->mix_buf->size); trig = PCM_ENABLE_OUTPUT; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr ( From patchwork Tue Sep 24 06:19:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157965 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E883314E5 for ; Tue, 24 Sep 2019 06:35:15 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B660820665 for ; Tue, 24 Sep 2019 06:35:15 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B660820665 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41368 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCePq-0000Hk-IO for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:35:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59286) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeBE-0003hh-NA for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeBC-0000uP-LK for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45990) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeBC-0000u7-8S for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:06 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 84F7D18CB8E9; Tue, 24 Sep 2019 06:20:05 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id DD2505D71C; Tue, 24 Sep 2019 06:19:58 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 24EDB9C75; Tue, 24 Sep 2019 08:19:52 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 15/16] audio: common rate control code for timer based outputs Date: Tue, 24 Sep 2019 08:19:50 +0200 Message-Id: <20190924061951.27916-16-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.63]); Tue, 24 Sep 2019 06:20:05 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán This commit removes the ad-hoc rate-limiting code from noaudio and wavaudio, and replaces them with a (slightly modified) code from spiceaudio. This way multiple write calls (for example when the circular buffer wraps around) do not cause problems. Signed-off-by: Kővágó, Zoltán Message-id: fd0fe5b95b13fa26d09ae77a72f99d0ea411de14.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/audio_int.h | 9 ++++++++ audio/audio.c | 30 +++++++++++++++++++++++++++ audio/noaudio.c | 49 ++++++++++++++++++++------------------------ audio/spiceaudio.c | 51 ++++++++-------------------------------------- audio/wavaudio.c | 21 +++++++++---------- 5 files changed, 79 insertions(+), 81 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index 20021df9e8be..778615ccafa4 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -242,6 +242,15 @@ void *audio_calloc (const char *funcname, int nmemb, size_t size); void audio_run(AudioState *s, const char *msg); +typedef struct RateCtl { + int64_t start_ticks; + int64_t bytes_sent; +} RateCtl; + +void audio_rate_start(RateCtl *rate); +size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate, + size_t bytes_avail); + #define VOICE_ENABLE 1 #define VOICE_DISABLE 2 #define VOICE_VOLUME 3 diff --git a/audio/audio.c b/audio/audio.c index ba07fb77dd4f..fab1e3571838 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -2051,3 +2051,33 @@ const char *audio_get_id(QEMUSoundCard *card) return ""; } } + +void audio_rate_start(RateCtl *rate) +{ + memset(rate, 0, sizeof(RateCtl)); + rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + +size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate, + size_t bytes_avail) +{ + int64_t now; + int64_t ticks; + int64_t bytes; + int64_t samples; + size_t ret; + + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + ticks = now - rate->start_ticks; + bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND); + samples = (bytes - rate->bytes_sent) >> info->shift; + if (samples < 0 || samples > 65536) { + AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)\n", samples); + audio_rate_start(rate); + samples = 0; + } + + ret = MIN(samples << info->shift, bytes_avail); + rate->bytes_sent += ret; + return ret; +} diff --git a/audio/noaudio.c b/audio/noaudio.c index b054fd225b66..9f1cc67df942 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -33,33 +33,27 @@ typedef struct NoVoiceOut { HWVoiceOut hw; - int64_t old_ticks; + RateCtl rate; } NoVoiceOut; typedef struct NoVoiceIn { HWVoiceIn hw; - int64_t old_ticks; + RateCtl rate; } NoVoiceIn; static size_t no_write(HWVoiceOut *hw, void *buf, size_t len) { NoVoiceOut *no = (NoVoiceOut *) hw; - int64_t now; - int64_t ticks; - int64_t bytes; - - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - ticks = now - no->old_ticks; - bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - - no->old_ticks = now; - return MIN(len, bytes); + return audio_rate_get_bytes(&hw->info, &no->rate, len); } static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) { + NoVoiceOut *no = (NoVoiceOut *) hw; + audio_pcm_init_info (&hw->info, as); hw->samples = 1024; + audio_rate_start(&no->rate); return 0; } @@ -70,15 +64,21 @@ static void no_fini_out (HWVoiceOut *hw) static int no_ctl_out (HWVoiceOut *hw, int cmd, ...) { - (void) hw; - (void) cmd; + NoVoiceOut *no = (NoVoiceOut *) hw; + + if (cmd == VOICE_ENABLE) { + audio_rate_start(&no->rate); + } return 0; } static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) { + NoVoiceIn *no = (NoVoiceIn *) hw; + audio_pcm_init_info (&hw->info, as); hw->samples = 1024; + audio_rate_start(&no->rate); return 0; } @@ -89,25 +89,20 @@ static void no_fini_in (HWVoiceIn *hw) static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) { - size_t to_clear; NoVoiceIn *no = (NoVoiceIn *) hw; + int64_t bytes = audio_rate_get_bytes(&hw->info, &no->rate, size); - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t ticks = now - no->old_ticks; - int64_t bytes = - muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - - no->old_ticks = now; - to_clear = MIN(bytes, size); - - audio_pcm_info_clear_buf(&hw->info, buf, to_clear >> hw->info.shift); - return to_clear; + audio_pcm_info_clear_buf(&hw->info, buf, bytes >> hw->info.shift); + return bytes; } static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) { - (void) hw; - (void) cmd; + NoVoiceIn *no = (NoVoiceIn *) hw; + + if (cmd == VOICE_ENABLE) { + audio_rate_start(&no->rate); + } return 0; } diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index ff4e4dcbb022..4ce4f94c6dca 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -40,15 +40,10 @@ #define LINE_IN_SAMPLES (256 * 4) #endif -typedef struct SpiceRateCtl { - int64_t start_ticks; - int64_t bytes_sent; -} SpiceRateCtl; - typedef struct SpiceVoiceOut { HWVoiceOut hw; SpicePlaybackInstance sin; - SpiceRateCtl rate; + RateCtl rate; int active; uint32_t *frame; uint32_t fpos; @@ -58,7 +53,7 @@ typedef struct SpiceVoiceOut { typedef struct SpiceVoiceIn { HWVoiceIn hw; SpiceRecordInstance sin; - SpiceRateCtl rate; + RateCtl rate; int active; } SpiceVoiceIn; @@ -89,32 +84,6 @@ static void spice_audio_fini (void *opaque) /* nothing */ } -static void rate_start (SpiceRateCtl *rate) -{ - memset (rate, 0, sizeof (*rate)); - rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); -} - -static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate) -{ - int64_t now; - int64_t ticks; - int64_t bytes; - int64_t samples; - - now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - ticks = now - rate->start_ticks; - bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND); - samples = (bytes - rate->bytes_sent) >> info->shift; - if (samples < 0 || samples > 65536) { - error_report("Resetting rate control (%" PRId64 " samples)", samples); - rate_start(rate); - samples = 0; - } - rate->bytes_sent += samples << info->shift; - return samples; -} - /* playback */ static int line_out_init(HWVoiceOut *hw, struct audsettings *as, @@ -154,7 +123,6 @@ static void line_out_fini (HWVoiceOut *hw) static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size) { SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); - size_t decr; if (!out->frame) { spice_server_playback_get_buffer(&out->sin, &out->frame, &out->fsize); @@ -162,12 +130,10 @@ static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size) } if (out->frame) { - decr = rate_get_samples(&hw->info, &out->rate); - decr = MIN(out->fsize - out->fpos, decr); - - *size = decr << hw->info.shift; + *size = audio_rate_get_bytes( + &hw->info, &out->rate, (out->fsize - out->fpos) << hw->info.shift); } else { - rate_start(&out->rate); + audio_rate_start(&out->rate); } return out->frame + out->fpos; } @@ -197,7 +163,7 @@ static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) break; } out->active = 1; - rate_start (&out->rate); + audio_rate_start(&out->rate); spice_server_playback_start (&out->sin); break; case VOICE_DISABLE: @@ -273,8 +239,7 @@ static void line_in_fini (HWVoiceIn *hw) static size_t line_in_read(HWVoiceIn *hw, void *buf, size_t len) { SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); - uint64_t delta_samp = rate_get_samples(&hw->info, &in->rate); - uint64_t to_read = MIN(len >> 2, delta_samp); + uint64_t to_read = audio_rate_get_bytes(&hw->info, &in->rate, len) >> 2; size_t ready = spice_server_record_get_samples(&in->sin, buf, to_read); /* XXX: do we need this? */ @@ -296,7 +261,7 @@ static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) break; } in->active = 1; - rate_start (&in->rate); + audio_rate_start(&in->rate); spice_server_record_start (&in->sin); break; case VOICE_DISABLE: diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 78af2f1338d2..85f5ff9c28bc 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -35,21 +35,15 @@ typedef struct WAVVoiceOut { HWVoiceOut hw; FILE *f; - int64_t old_ticks; + RateCtl rate; int total_samples; } WAVVoiceOut; static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len) { WAVVoiceOut *wav = (WAVVoiceOut *) hw; - int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - int64_t ticks = now - wav->old_ticks; - int64_t bytes = - muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND); - - bytes = MIN(bytes, len); - bytes = bytes >> hw->info.shift << hw->info.shift; - wav->old_ticks = now; + int64_t bytes = audio_rate_get_bytes(&hw->info, &wav->rate, len); + assert(bytes >> hw->info.shift << hw->info.shift == bytes); if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) { dolog("wav_write_out: fwrite of %" PRId64 " bytes failed\nReason: %s\n", @@ -130,6 +124,8 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings *as, strerror(errno)); return -1; } + + audio_rate_start(&wav->rate); return 0; } @@ -179,8 +175,11 @@ static void wav_fini_out (HWVoiceOut *hw) static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) { - (void) hw; - (void) cmd; + WAVVoiceOut *wav = (WAVVoiceOut *) hw; + + if (cmd == VOICE_ENABLE) { + audio_rate_start(&wav->rate); + } return 0; } From patchwork Tue Sep 24 06:19:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 11157973 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1D12414E5 for ; Tue, 24 Sep 2019 06:39:30 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D7E5D20665 for ; Tue, 24 Sep 2019 06:39:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D7E5D20665 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:41412 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeTx-0004JK-2S for patchwork-qemu-devel@patchwork.kernel.org; Tue, 24 Sep 2019 02:39:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:59342) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCeBK-0003l0-FP for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCeBF-0000vr-D3 for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60706) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCeBE-0000uf-Tm for qemu-devel@nongnu.org; Tue, 24 Sep 2019 02:20:09 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E10893082133; Tue, 24 Sep 2019 06:20:06 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-116-47.ams2.redhat.com [10.36.116.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id 19CDA5D9DC; Tue, 24 Sep 2019 06:19:59 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 3E7629C7F; Tue, 24 Sep 2019 08:19:52 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PULL 16/16] audio: split ctl_* functions into enable_* and volume_* Date: Tue, 24 Sep 2019 08:19:51 +0200 Message-Id: <20190924061951.27916-17-kraxel@redhat.com> In-Reply-To: <20190924061951.27916-1-kraxel@redhat.com> References: <20190924061951.27916-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Tue, 24 Sep 2019 06:20:06 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?unknown-8bit?b?S8WRdsOhZ8OzQHJlZGhhdC5jb20sIEdlcmQgSG9mZm1hbm4gPGty?= =?unknown-8bit?b?YXhlbEByZWRoYXQuY29tPiwgPT9VVEYtOD9xP1pvbHQ9QzM9QTFuPz0g?= =?unknown-8bit?b?PERpcnRZLmlDRS5odUBnbWFpbC5jb20+?= Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" From: Kővágó, Zoltán This way we no longer need vararg functions, improving compile time error detection. Also now it's possible to check actually what commands are supported, without needing to manually update ctl_caps. Signed-off-by: Kővágó, Zoltán Message-id: 2b08b3773569c5be055d0a0fb2f29ff64e79f0f4.1568927990.git.DirtY.iCE.hu@gmail.com Signed-off-by: Gerd Hoffmann --- audio/audio_int.h | 15 ++--- audio/audio_template.h | 1 - audio/alsaaudio.c | 62 ++++++++------------ audio/audio.c | 45 +++++++++------ audio/coreaudio.c | 13 ++--- audio/dsoundaudio.c | 50 +++++++--------- audio/noaudio.c | 14 ++--- audio/ossaudio.c | 79 ++++++++++--------------- audio/paaudio.c | 127 ++++++++++++++++------------------------- audio/sdlaudio.c | 17 +----- audio/spiceaudio.c | 102 ++++++++++++++------------------- audio/wavaudio.c | 7 +-- 12 files changed, 217 insertions(+), 315 deletions(-) diff --git a/audio/audio_int.h b/audio/audio_int.h index 778615ccafa4..22a703c13e1c 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -74,7 +74,6 @@ typedef struct HWVoiceOut { size_t samples; QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; QLIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head; - int ctl_caps; struct audio_pcm_ops *pcm_ops; QLIST_ENTRY (HWVoiceOut) entries; } HWVoiceOut; @@ -96,7 +95,6 @@ typedef struct HWVoiceIn { size_t samples; QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; - int ctl_caps; struct audio_pcm_ops *pcm_ops; QLIST_ENTRY (HWVoiceIn) entries; } HWVoiceIn; @@ -148,7 +146,6 @@ struct audio_driver { int max_voices_in; int voice_size_out; int voice_size_in; - int ctl_caps; QLIST_ENTRY(audio_driver) next; }; @@ -168,14 +165,16 @@ struct audio_pcm_ops { * size may be smaller */ size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size); - int (*ctl_out) (HWVoiceOut *hw, int cmd, ...); + void (*enable_out)(HWVoiceOut *hw, bool enable); + void (*volume_out)(HWVoiceOut *hw, struct mixeng_volume *vol); int (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); void (*fini_in) (HWVoiceIn *hw); size_t (*read) (HWVoiceIn *hw, void *buf, size_t size); void *(*get_buffer_in)(HWVoiceIn *hw, size_t *size); void (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size); - int (*ctl_in) (HWVoiceIn *hw, int cmd, ...); + void (*enable_in)(HWVoiceIn *hw, bool enable); + void (*volume_in)(HWVoiceIn *hw, struct mixeng_volume *vol); }; void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size); @@ -251,12 +250,6 @@ void audio_rate_start(RateCtl *rate); size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate, size_t bytes_avail); -#define VOICE_ENABLE 1 -#define VOICE_DISABLE 2 -#define VOICE_VOLUME 3 - -#define VOICE_VOLUME_CAP (1 << VOICE_VOLUME) - static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len) { return (dst >= src) ? (dst - src) : (len - src + dst); diff --git a/audio/audio_template.h b/audio/audio_template.h index 87c6d2d27102..235d1acbbebb 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -254,7 +254,6 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, hw->s = s; hw->pcm_ops = drv->pcm_ops; - hw->ctl_caps = drv->ctl_caps; QLIST_INIT (&hw->sw_head); #ifdef DAC diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c index 19124d09d845..cfe42284a6aa 100644 --- a/audio/alsaaudio.c +++ b/audio/alsaaudio.c @@ -731,34 +731,28 @@ static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl) return 0; } -static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void alsa_enable_out(HWVoiceOut *hw, bool enable) { ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw; AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.out; - switch (cmd) { - case VOICE_ENABLE: - { - bool poll_mode = apdo->try_poll; + if (enable) { + bool poll_mode = apdo->try_poll; - ldebug ("enabling voice\n"); - if (poll_mode && alsa_poll_out (hw)) { - poll_mode = 0; - } - hw->poll_mode = poll_mode; - return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PREPARE); + ldebug("enabling voice\n"); + if (poll_mode && alsa_poll_out(hw)) { + poll_mode = 0; } - - case VOICE_DISABLE: - ldebug ("disabling voice\n"); + hw->poll_mode = poll_mode; + alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PREPARE); + } else { + ldebug("disabling voice\n"); if (hw->poll_mode) { hw->poll_mode = 0; - alsa_fini_poll (&alsa->pollhlp); + alsa_fini_poll(&alsa->pollhlp); } - return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PAUSE); + alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PAUSE); } - - return -1; } static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) @@ -841,35 +835,29 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t len) return pos; } -static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void alsa_enable_in(HWVoiceIn *hw, bool enable) { ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw; AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.in; - switch (cmd) { - case VOICE_ENABLE: - { - bool poll_mode = apdo->try_poll; + if (enable) { + bool poll_mode = apdo->try_poll; - ldebug ("enabling voice\n"); - if (poll_mode && alsa_poll_in (hw)) { - poll_mode = 0; - } - hw->poll_mode = poll_mode; - - return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_START); + ldebug("enabling voice\n"); + if (poll_mode && alsa_poll_in(hw)) { + poll_mode = 0; } + hw->poll_mode = poll_mode; - case VOICE_DISABLE: + alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_START); + } else { ldebug ("disabling voice\n"); if (hw->poll_mode) { hw->poll_mode = 0; - alsa_fini_poll (&alsa->pollhlp); + alsa_fini_poll(&alsa->pollhlp); } - return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_PAUSE); + alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_PAUSE); } - - return -1; } static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo) @@ -924,12 +912,12 @@ static struct audio_pcm_ops alsa_pcm_ops = { .init_out = alsa_init_out, .fini_out = alsa_fini_out, .write = alsa_write, - .ctl_out = alsa_ctl_out, + .enable_out = alsa_enable_out, .init_in = alsa_init_in, .fini_in = alsa_fini_in, .read = alsa_read, - .ctl_in = alsa_ctl_in, + .enable_in = alsa_enable_in, }; static struct audio_driver alsa_audio_driver = { diff --git a/audio/audio.c b/audio/audio.c index fab1e3571838..7128ee98dc97 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -636,7 +636,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) total += isamp; } - if (!(hw->ctl_caps & VOICE_VOLUME_CAP)) { + if (!hw->pcm_ops->volume_in) { mixeng_volume (sw->buf, ret, &sw->vol); } @@ -723,7 +723,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) if (swlim) { sw->conv (sw->buf, buf, swlim); - if (!(sw->hw->ctl_caps & VOICE_VOLUME_CAP)) { + if (!sw->hw->pcm_ops->volume_out) { mixeng_volume (sw->buf, swlim, &sw->vol); } } @@ -890,7 +890,9 @@ void AUD_set_active_out (SWVoiceOut *sw, int on) if (!hw->enabled) { hw->enabled = 1; if (s->vm_running) { - hw->pcm_ops->ctl_out(hw, VOICE_ENABLE); + if (hw->pcm_ops->enable_out) { + hw->pcm_ops->enable_out(hw, true); + } audio_reset_timer (s); } } @@ -935,7 +937,9 @@ void AUD_set_active_in (SWVoiceIn *sw, int on) if (!hw->enabled) { hw->enabled = 1; if (s->vm_running) { - hw->pcm_ops->ctl_in(hw, VOICE_ENABLE); + if (hw->pcm_ops->enable_in) { + hw->pcm_ops->enable_in(hw, true); + } audio_reset_timer (s); } } @@ -952,7 +956,9 @@ void AUD_set_active_in (SWVoiceIn *sw, int on) if (nb_active == 1) { hw->enabled = 0; - hw->pcm_ops->ctl_in (hw, VOICE_DISABLE); + if (hw->pcm_ops->enable_in) { + hw->pcm_ops->enable_in(hw, false); + } } } } @@ -1105,7 +1111,9 @@ static void audio_run_out (AudioState *s) #endif hw->enabled = 0; hw->pending_disable = 0; - hw->pcm_ops->ctl_out (hw, VOICE_DISABLE); + if (hw->pcm_ops->enable_out) { + hw->pcm_ops->enable_out(hw, false); + } for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) { sc->sw.active = 0; audio_recalc_and_notify_capture (sc->cap); @@ -1470,15 +1478,18 @@ static void audio_vm_change_state_handler (void *opaque, int running, AudioState *s = opaque; HWVoiceOut *hwo = NULL; HWVoiceIn *hwi = NULL; - int op = running ? VOICE_ENABLE : VOICE_DISABLE; s->vm_running = running; while ((hwo = audio_pcm_hw_find_any_enabled_out(s, hwo))) { - hwo->pcm_ops->ctl_out(hwo, op); + if (hwo->pcm_ops->enable_out) { + hwo->pcm_ops->enable_out(hwo, running); + } } while ((hwi = audio_pcm_hw_find_any_enabled_in(s, hwi))) { - hwi->pcm_ops->ctl_in(hwi, op); + if (hwi->pcm_ops->enable_in) { + hwi->pcm_ops->enable_in(hwi, running); + } } audio_reset_timer (s); } @@ -1498,8 +1509,8 @@ static void free_audio_state(AudioState *s) QLIST_FOREACH_SAFE(hwo, &s->hw_head_out, entries, hwon) { SWVoiceCap *sc; - if (hwo->enabled) { - hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE); + if (hwo->enabled && hwo->pcm_ops->enable_out) { + hwo->pcm_ops->enable_out(hwo, false); } hwo->pcm_ops->fini_out (hwo); @@ -1515,8 +1526,8 @@ static void free_audio_state(AudioState *s) } QLIST_FOREACH_SAFE(hwi, &s->hw_head_in, entries, hwin) { - if (hwi->enabled) { - hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE); + if (hwi->enabled && hwi->pcm_ops->enable_in) { + hwi->pcm_ops->enable_in(hwi, false); } hwi->pcm_ops->fini_in (hwi); QLIST_REMOVE(hwi, entries); @@ -1838,8 +1849,8 @@ void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol) sw->vol.l = nominal_volume.l * lvol / 255; sw->vol.r = nominal_volume.r * rvol / 255; - if (hw->pcm_ops->ctl_out) { - hw->pcm_ops->ctl_out (hw, VOICE_VOLUME, sw); + if (hw->pcm_ops->volume_out) { + hw->pcm_ops->volume_out(hw, &sw->vol); } } } @@ -1853,8 +1864,8 @@ void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol) sw->vol.l = nominal_volume.l * lvol / 255; sw->vol.r = nominal_volume.r * rvol / 255; - if (hw->pcm_ops->ctl_in) { - hw->pcm_ops->ctl_in (hw, VOICE_VOLUME, sw); + if (hw->pcm_ops->volume_in) { + hw->pcm_ops->volume_in(hw, &sw->vol); } } } diff --git a/audio/coreaudio.c b/audio/coreaudio.c index 5cde42f9826c..1427c9f622d9 100644 --- a/audio/coreaudio.c +++ b/audio/coreaudio.c @@ -648,13 +648,12 @@ static void coreaudio_fini_out (HWVoiceOut *hw) } } -static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void coreaudio_enable_out(HWVoiceOut *hw, bool enable) { OSStatus status; coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; - switch (cmd) { - case VOICE_ENABLE: + if (enable) { /* start playback */ if (!isPlaying(core->outputDeviceID)) { status = AudioDeviceStart(core->outputDeviceID, core->ioprocid); @@ -662,9 +661,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) coreaudio_logerr (status, "Could not resume playback\n"); } } - break; - - case VOICE_DISABLE: + } else { /* stop playback */ if (!audio_is_cleaning_up()) { if (isPlaying(core->outputDeviceID)) { @@ -675,9 +672,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) } } } - break; } - return 0; } static void *coreaudio_audio_init(Audiodev *dev) @@ -695,7 +690,7 @@ static struct audio_pcm_ops coreaudio_pcm_ops = { .write = coreaudio_write, .get_buffer_out = coreaudio_get_buffer_out, .put_buffer_out = coreaudio_put_buffer_out_nowrite, - .ctl_out = coreaudio_ctl_out + .enable_out = coreaudio_enable_out }; static struct audio_driver coreaudio_audio_driver = { diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index 9960247814c7..d4a4757445b0 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -361,7 +361,7 @@ static int dsound_open (dsound *s) return 0; } -static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void dsound_enable_out(HWVoiceOut *hw, bool enable) { HRESULT hr; DWORD status; @@ -371,18 +371,17 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) if (!dsb) { dolog ("Attempt to control voice without a buffer\n"); - return 0; + return; } - switch (cmd) { - case VOICE_ENABLE: + if (enable) { if (dsound_get_status_out (dsb, &status, s)) { - return -1; + return; } if (status & DSBSTATUS_PLAYING) { dolog ("warning: Voice is already playing\n"); - return 0; + return; } dsound_clear_sample (hw, dsb, s); @@ -390,28 +389,24 @@ static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING); if (FAILED (hr)) { dsound_logerr (hr, "Could not start playing buffer\n"); - return -1; + return; } - break; - - case VOICE_DISABLE: + } else { if (dsound_get_status_out (dsb, &status, s)) { - return -1; + return; } if (status & DSBSTATUS_PLAYING) { hr = IDirectSoundBuffer_Stop (dsb); if (FAILED (hr)) { dsound_logerr (hr, "Could not stop playing buffer\n"); - return -1; + return; } } else { dolog ("warning: Voice is not playing\n"); } - break; } - return 0; } static void *dsound_get_buffer_out(HWVoiceOut *hw, size_t *size) @@ -461,7 +456,7 @@ static size_t dsound_put_buffer_out(HWVoiceOut *hw, void *buf, size_t len) return len; } -static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void dsound_enable_in(HWVoiceIn *hw, bool enable) { HRESULT hr; DWORD status; @@ -470,18 +465,17 @@ static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) if (!dscb) { dolog ("Attempt to control capture voice without a buffer\n"); - return -1; + return; } - switch (cmd) { - case VOICE_ENABLE: + if (enable) { if (dsound_get_status_in (dscb, &status)) { - return -1; + return; } if (status & DSCBSTATUS_CAPTURING) { dolog ("warning: Voice is already capturing\n"); - return 0; + return; } /* clear ?? */ @@ -489,28 +483,24 @@ static int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...) hr = IDirectSoundCaptureBuffer_Start (dscb, DSCBSTART_LOOPING); if (FAILED (hr)) { dsound_logerr (hr, "Could not start capturing\n"); - return -1; + return; } - break; - - case VOICE_DISABLE: + } else { if (dsound_get_status_in (dscb, &status)) { - return -1; + return; } if (status & DSCBSTATUS_CAPTURING) { hr = IDirectSoundCaptureBuffer_Stop (dscb); if (FAILED (hr)) { dsound_logerr (hr, "Could not stop capturing\n"); - return -1; + return; } } else { dolog ("warning: Voice is not capturing\n"); } - break; } - return 0; } static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size) @@ -674,14 +664,14 @@ static struct audio_pcm_ops dsound_pcm_ops = { .write = audio_generic_write, .get_buffer_out = dsound_get_buffer_out, .put_buffer_out = dsound_put_buffer_out, - .ctl_out = dsound_ctl_out, + .enable_out = dsound_enable_out, .init_in = dsound_init_in, .fini_in = dsound_fini_in, .read = audio_generic_read, .get_buffer_in = dsound_get_buffer_in, .put_buffer_in = dsound_put_buffer_in, - .ctl_in = dsound_ctl_in + .enable_in = dsound_enable_in, }; static struct audio_driver dsound_audio_driver = { diff --git a/audio/noaudio.c b/audio/noaudio.c index 9f1cc67df942..ec8a287f3689 100644 --- a/audio/noaudio.c +++ b/audio/noaudio.c @@ -62,14 +62,13 @@ static void no_fini_out (HWVoiceOut *hw) (void) hw; } -static int no_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void no_enable_out(HWVoiceOut *hw, bool enable) { NoVoiceOut *no = (NoVoiceOut *) hw; - if (cmd == VOICE_ENABLE) { + if (enable) { audio_rate_start(&no->rate); } - return 0; } static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) @@ -96,14 +95,13 @@ static size_t no_read(HWVoiceIn *hw, void *buf, size_t size) return bytes; } -static int no_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void no_enable_in(HWVoiceIn *hw, bool enable) { NoVoiceIn *no = (NoVoiceIn *) hw; - if (cmd == VOICE_ENABLE) { + if (enable) { audio_rate_start(&no->rate); } - return 0; } static void *no_audio_init(Audiodev *dev) @@ -120,12 +118,12 @@ static struct audio_pcm_ops no_pcm_ops = { .init_out = no_init_out, .fini_out = no_fini_out, .write = no_write, - .ctl_out = no_ctl_out, + .enable_out = no_enable_out, .init_in = no_init_in, .fini_in = no_fini_in, .read = no_read, - .ctl_in = no_ctl_in + .enable_in = no_enable_in }; static struct audio_driver no_audio_driver = { diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 76c082d5e2a5..0c4451e972de 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -563,60 +563,50 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, return 0; } -static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void oss_enable_out(HWVoiceOut *hw, bool enable) { int trig; OSSVoiceOut *oss = (OSSVoiceOut *) hw; AudiodevOssPerDirectionOptions *opdo = oss->dev->u.oss.out; - switch (cmd) { - case VOICE_ENABLE: - { - bool poll_mode = opdo->try_poll; + if (enable) { + bool poll_mode = opdo->try_poll; - ldebug ("enabling voice\n"); - if (poll_mode) { - oss_poll_out (hw); - poll_mode = 0; - } - hw->poll_mode = poll_mode; - - if (!oss->mmapped) { - return 0; - } + ldebug("enabling voice\n"); + if (poll_mode) { + oss_poll_out(hw); + poll_mode = 0; + } + hw->poll_mode = poll_mode; - audio_pcm_info_clear_buf( - &hw->info, hw->buf_emul, hw->mix_buf->size); - trig = PCM_ENABLE_OUTPUT; - if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { - oss_logerr ( - errno, - "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n" - ); - return -1; - } + if (!oss->mmapped) { + return; } - break; - case VOICE_DISABLE: + audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->mix_buf->size); + trig = PCM_ENABLE_OUTPUT; + if (ioctl(oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { + oss_logerr(errno, + "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"); + return; + } + } else { if (hw->poll_mode) { qemu_set_fd_handler (oss->fd, NULL, NULL, NULL); hw->poll_mode = 0; } if (!oss->mmapped) { - return 0; + return; } ldebug ("disabling voice\n"); trig = 0; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n"); - return -1; + return; } - break; } - return 0; } static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) @@ -703,32 +693,25 @@ static size_t oss_read(HWVoiceIn *hw, void *buf, size_t len) return pos; } -static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void oss_enable_in(HWVoiceIn *hw, bool enable) { OSSVoiceIn *oss = (OSSVoiceIn *) hw; AudiodevOssPerDirectionOptions *opdo = oss->dev->u.oss.out; - switch (cmd) { - case VOICE_ENABLE: - { - bool poll_mode = opdo->try_poll; + if (enable) { + bool poll_mode = opdo->try_poll; - if (poll_mode) { - oss_poll_in (hw); - poll_mode = 0; - } - hw->poll_mode = poll_mode; + if (poll_mode) { + oss_poll_in(hw); + poll_mode = 0; } - break; - - case VOICE_DISABLE: + hw->poll_mode = poll_mode; + } else { if (hw->poll_mode) { hw->poll_mode = 0; qemu_set_fd_handler (oss->fd, NULL, NULL, NULL); } - break; } - return 0; } static void oss_init_per_direction(AudiodevOssPerDirectionOptions *opdo) @@ -767,12 +750,12 @@ static struct audio_pcm_ops oss_pcm_ops = { .write = oss_write, .get_buffer_out = oss_get_buffer_out, .put_buffer_out = oss_put_buffer_out, - .ctl_out = oss_ctl_out, + .enable_out = oss_enable_out, .init_in = oss_init_in, .fini_in = oss_fini_in, .read = oss_read, - .ctl_in = oss_ctl_in + .enable_in = oss_enable_in }; static struct audio_driver oss_audio_driver = { diff --git a/audio/paaudio.c b/audio/paaudio.c index 75fce5320269..ed31f863f7fe 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -452,7 +452,7 @@ static void qpa_fini_in (HWVoiceIn *hw) } } -static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void qpa_volume_out(HWVoiceOut *hw, struct mixeng_volume *vol) { PAVoiceOut *pa = (PAVoiceOut *) hw; pa_operation *op; @@ -463,49 +463,36 @@ static int qpa_ctl_out (HWVoiceOut *hw, int cmd, ...) pa_cvolume_init (&v); /* function is present in 0.9.13+ */ #endif - switch (cmd) { - case VOICE_VOLUME: - { - SWVoiceOut *sw; - va_list ap; + v.channels = 2; + v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->l) / UINT32_MAX; + v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->r) / UINT32_MAX; - va_start (ap, cmd); - sw = va_arg (ap, SWVoiceOut *); - va_end (ap); + pa_threaded_mainloop_lock(c->mainloop); - v.channels = 2; - v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX; - v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX; - - pa_threaded_mainloop_lock(c->mainloop); - - op = pa_context_set_sink_input_volume(c->context, - pa_stream_get_index (pa->stream), - &v, NULL, NULL); - if (!op) { - qpa_logerr(pa_context_errno(c->context), - "set_sink_input_volume() failed\n"); - } else { - pa_operation_unref(op); - } - - op = pa_context_set_sink_input_mute(c->context, - pa_stream_get_index (pa->stream), - sw->vol.mute, NULL, NULL); - if (!op) { - qpa_logerr(pa_context_errno(c->context), - "set_sink_input_mute() failed\n"); - } else { - pa_operation_unref(op); - } + op = pa_context_set_sink_input_volume(c->context, + pa_stream_get_index(pa->stream), + &v, NULL, NULL); + if (!op) { + qpa_logerr(pa_context_errno(c->context), + "set_sink_input_volume() failed\n"); + } else { + pa_operation_unref(op); + } - pa_threaded_mainloop_unlock(c->mainloop); - } + op = pa_context_set_sink_input_mute(c->context, + pa_stream_get_index(pa->stream), + vol->mute, NULL, NULL); + if (!op) { + qpa_logerr(pa_context_errno(c->context), + "set_sink_input_mute() failed\n"); + } else { + pa_operation_unref(op); } - return 0; + + pa_threaded_mainloop_unlock(c->mainloop); } -static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...) +static void qpa_volume_in(HWVoiceIn *hw, struct mixeng_volume *vol) { PAVoiceIn *pa = (PAVoiceIn *) hw; pa_operation *op; @@ -516,46 +503,33 @@ static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...) pa_cvolume_init (&v); #endif - switch (cmd) { - case VOICE_VOLUME: - { - SWVoiceIn *sw; - va_list ap; + v.channels = 2; + v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->l) / UINT32_MAX; + v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->r) / UINT32_MAX; - va_start (ap, cmd); - sw = va_arg (ap, SWVoiceIn *); - va_end (ap); + pa_threaded_mainloop_lock(c->mainloop); - v.channels = 2; - v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.l) / UINT32_MAX; - v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * sw->vol.r) / UINT32_MAX; - - pa_threaded_mainloop_lock(c->mainloop); - - op = pa_context_set_source_output_volume(c->context, - pa_stream_get_index(pa->stream), - &v, NULL, NULL); - if (!op) { - qpa_logerr(pa_context_errno(c->context), - "set_source_output_volume() failed\n"); - } else { - pa_operation_unref(op); - } - - op = pa_context_set_source_output_mute(c->context, - pa_stream_get_index (pa->stream), - sw->vol.mute, NULL, NULL); - if (!op) { - qpa_logerr(pa_context_errno(c->context), - "set_source_output_mute() failed\n"); - } else { - pa_operation_unref (op); - } + op = pa_context_set_source_output_volume(c->context, + pa_stream_get_index(pa->stream), + &v, NULL, NULL); + if (!op) { + qpa_logerr(pa_context_errno(c->context), + "set_source_output_volume() failed\n"); + } else { + pa_operation_unref(op); + } - pa_threaded_mainloop_unlock(c->mainloop); - } + op = pa_context_set_source_output_mute(c->context, + pa_stream_get_index(pa->stream), + vol->mute, NULL, NULL); + if (!op) { + qpa_logerr(pa_context_errno(c->context), + "set_source_output_mute() failed\n"); + } else { + pa_operation_unref(op); } - return 0; + + pa_threaded_mainloop_unlock(c->mainloop); } static int qpa_validate_per_direction_opts(Audiodev *dev, @@ -724,12 +698,12 @@ static struct audio_pcm_ops qpa_pcm_ops = { .init_out = qpa_init_out, .fini_out = qpa_fini_out, .write = qpa_write, - .ctl_out = qpa_ctl_out, + .volume_out = qpa_volume_out, .init_in = qpa_init_in, .fini_in = qpa_fini_in, .read = qpa_read, - .ctl_in = qpa_ctl_in + .volume_in = qpa_volume_in }; static struct audio_driver pa_audio_driver = { @@ -743,7 +717,6 @@ static struct audio_driver pa_audio_driver = { .max_voices_in = INT_MAX, .voice_size_out = sizeof (PAVoiceOut), .voice_size_in = sizeof (PAVoiceIn), - .ctl_caps = VOICE_VOLUME_CAP }; static void register_audio_pa(void) diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c index f7ac8cd10188..5c6bcfcb3e9d 100644 --- a/audio/sdlaudio.c +++ b/audio/sdlaudio.c @@ -285,20 +285,9 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as, return 0; } -static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void sdl_enable_out(HWVoiceOut *hw, bool enable) { - (void) hw; - - switch (cmd) { - case VOICE_ENABLE: - SDL_PauseAudio (0); - break; - - case VOICE_DISABLE: - SDL_PauseAudio (1); - break; - } - return 0; + SDL_PauseAudio(!enable); } static void *sdl_audio_init(Audiodev *dev) @@ -334,7 +323,7 @@ static struct audio_pcm_ops sdl_pcm_ops = { .write = sdl_write, .get_buffer_out = sdl_get_buffer_out, .put_buffer_out = sdl_put_buffer_out_nowrite, - .ctl_out = sdl_ctl_out, + .enable_out = sdl_enable_out, }; static struct audio_driver sdl_audio_driver = { diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c index 4ce4f94c6dca..9860f9c5e16c 100644 --- a/audio/spiceaudio.c +++ b/audio/spiceaudio.c @@ -153,22 +153,20 @@ static size_t line_out_put_buffer(HWVoiceOut *hw, void *buf, size_t size) return size; } -static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) +static void line_out_enable(HWVoiceOut *hw, bool enable) { SpiceVoiceOut *out = container_of (hw, SpiceVoiceOut, hw); - switch (cmd) { - case VOICE_ENABLE: + if (enable) { if (out->active) { - break; + return; } out->active = 1; audio_rate_start(&out->rate); spice_server_playback_start (&out->sin); - break; - case VOICE_DISABLE: + } else { if (!out->active) { - break; + return; } out->active = 0; if (out->frame) { @@ -177,29 +175,21 @@ static int line_out_ctl (HWVoiceOut *hw, int cmd, ...) out->frame = NULL; } spice_server_playback_stop (&out->sin); - break; - case VOICE_VOLUME: - { + } +} + #if ((SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && (SPICE_INTERFACE_PLAYBACK_MINOR >= 2)) - SWVoiceOut *sw; - va_list ap; - uint16_t vol[2]; +static void line_out_volume(HWVoiceOut *hw, struct mixeng_volume *vol) +{ + SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw); + uint16_t svol[2]; - va_start (ap, cmd); - sw = va_arg (ap, SWVoiceOut *); - va_end (ap); - - vol[0] = sw->vol.l / ((1ULL << 16) + 1); - vol[1] = sw->vol.r / ((1ULL << 16) + 1); - spice_server_playback_set_volume (&out->sin, 2, vol); - spice_server_playback_set_mute (&out->sin, sw->vol.mute); + svol[0] = vol->l / ((1ULL << 16) + 1); + svol[1] = vol->r / ((1ULL << 16) + 1); + spice_server_playback_set_volume(&out->sin, 2, svol); + spice_server_playback_set_mute(&out->sin, vol->mute); +} #endif - break; - } - } - - return 0; -} /* record */ @@ -251,48 +241,38 @@ static size_t line_in_read(HWVoiceIn *hw, void *buf, size_t len) return ready << 2; } -static int line_in_ctl (HWVoiceIn *hw, int cmd, ...) +static void line_in_enable(HWVoiceIn *hw, bool enable) { SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw); - switch (cmd) { - case VOICE_ENABLE: + if (enable) { if (in->active) { - break; + return; } in->active = 1; audio_rate_start(&in->rate); spice_server_record_start (&in->sin); - break; - case VOICE_DISABLE: + } else { if (!in->active) { - break; + return; } in->active = 0; spice_server_record_stop (&in->sin); - break; - case VOICE_VOLUME: - { + } +} + #if ((SPICE_INTERFACE_RECORD_MAJOR >= 2) && (SPICE_INTERFACE_RECORD_MINOR >= 2)) - SWVoiceIn *sw; - va_list ap; - uint16_t vol[2]; +static void line_in_volume(HWVoiceIn *hw, struct mixeng_volume *vol) +{ + SpiceVoiceIn *in = container_of(hw, SpiceVoiceIn, hw); + uint16_t svol[2]; - va_start (ap, cmd); - sw = va_arg (ap, SWVoiceIn *); - va_end (ap); - - vol[0] = sw->vol.l / ((1ULL << 16) + 1); - vol[1] = sw->vol.r / ((1ULL << 16) + 1); - spice_server_record_set_volume (&in->sin, 2, vol); - spice_server_record_set_mute (&in->sin, sw->vol.mute); + svol[0] = vol->l / ((1ULL << 16) + 1); + svol[1] = vol->r / ((1ULL << 16) + 1); + spice_server_record_set_volume(&in->sin, 2, svol); + spice_server_record_set_mute(&in->sin, vol->mute); +} #endif - break; - } - } - - return 0; -} static struct audio_pcm_ops audio_callbacks = { .init_out = line_out_init, @@ -300,12 +280,19 @@ static struct audio_pcm_ops audio_callbacks = { .write = audio_generic_write, .get_buffer_out = line_out_get_buffer, .put_buffer_out = line_out_put_buffer, - .ctl_out = line_out_ctl, + .enable_out = line_out_enable, +#if (SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && \ + (SPICE_INTERFACE_PLAYBACK_MINOR >= 2) + .volume_out = line_out_volume, +#endif .init_in = line_in_init, .fini_in = line_in_fini, .read = line_in_read, - .ctl_in = line_in_ctl, + .enable_in = line_in_enable, +#if ((SPICE_INTERFACE_RECORD_MAJOR >= 2) && (SPICE_INTERFACE_RECORD_MINOR >= 2)) + .volume_in = line_in_volume, +#endif }; static struct audio_driver spice_audio_driver = { @@ -318,9 +305,6 @@ static struct audio_driver spice_audio_driver = { .max_voices_in = 1, .voice_size_out = sizeof (SpiceVoiceOut), .voice_size_in = sizeof (SpiceVoiceIn), -#if ((SPICE_INTERFACE_PLAYBACK_MAJOR >= 1) && (SPICE_INTERFACE_PLAYBACK_MINOR >= 2)) - .ctl_caps = VOICE_VOLUME_CAP -#endif }; void qemu_spice_audio_init (void) diff --git a/audio/wavaudio.c b/audio/wavaudio.c index 85f5ff9c28bc..47efdc1b1eab 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -173,14 +173,13 @@ static void wav_fini_out (HWVoiceOut *hw) wav->f = NULL; } -static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...) +static void wav_enable_out(HWVoiceOut *hw, bool enable) { WAVVoiceOut *wav = (WAVVoiceOut *) hw; - if (cmd == VOICE_ENABLE) { + if (enable) { audio_rate_start(&wav->rate); } - return 0; } static void *wav_audio_init(Audiodev *dev) @@ -198,7 +197,7 @@ static struct audio_pcm_ops wav_pcm_ops = { .init_out = wav_init_out, .fini_out = wav_fini_out, .write = wav_write_out, - .ctl_out = wav_ctl_out, + .enable_out = wav_enable_out, }; static struct audio_driver wav_audio_driver = {