initial import
This commit is contained in:
2
qemu-legacy/65-kvm.rules
Normal file
2
qemu-legacy/65-kvm.rules
Normal file
@@ -0,0 +1,2 @@
|
||||
KERNEL=="kvm", GROUP="kvm", MODE="0660"
|
||||
KERNEL=="vhost-net", GROUP="kvm", MODE="0660", TAG+="uaccess", OPTIONS+="static_node=vhost-net"
|
||||
248
qemu-legacy/PKGBUILD
Normal file
248
qemu-legacy/PKGBUILD
Normal file
@@ -0,0 +1,248 @@
|
||||
# Maintainer: Jesus E. <heckyel@riseup.net>
|
||||
|
||||
pkgbase=qemu-legacy
|
||||
pkgname=(qemu-legacy qemu-headless-legacy qemu-arch-extra-legacy qemu-headless-arch-extra-legacy
|
||||
qemu-block-iscsi-legacy qemu-guest-agent-legacy)
|
||||
pkgdesc="A generic and free machine emulator and virtualizer (legacy version)"
|
||||
pkgver=5.2.0
|
||||
_debver=5.2
|
||||
_debrel=11
|
||||
pkgrel=1
|
||||
arch=(i686 x86_64)
|
||||
license=(GPL-2 LGPL-2.1)
|
||||
url='https://wiki.qemu.org/'
|
||||
_headlessdeps=(seabios gnutls libpng libaio numactl libnfs
|
||||
lzo snappy curl vde2 libcap-ng spice usbredir libslirp
|
||||
libssh dtc libseccomp libsndio sdl2 virglrenderer)
|
||||
depends=(vte "${_headlessdeps[@]}")
|
||||
makedepends=(spice-protocol python libiscsi python-sphinx xfsprogs ninja quilt)
|
||||
source=("https://wiki.qemu.org/download/qemu-${pkgver}.tar.bz2"
|
||||
"https://deb.debian.org/debian/pool/main/q/qemu/qemu_${_debver}+dfsg-${_debrel}+deb11u3.debian.tar.xz"
|
||||
"65-kvm.rules"
|
||||
"sndio.patch"
|
||||
"qemu-ga.initd"
|
||||
"qemu-ga.conf"
|
||||
"qemu-ga.run")
|
||||
sha512sums=('f0c450a2a4723c33473e5af5a51b0c006fe04685758863b076f2cf11352c08a0693650579811667f6411f7e572c92892624390a0f26878b08419d79c15ff0e86'
|
||||
'295be9761eb6c1aa9f2dd86eb81b53791010af41da89adf062011724b6c5ea5bcc4c5a9c7f968472e7c7d6a582e2f485663b357c0013309bd7d618165ba94ad1'
|
||||
'13a097ee0ac9f740ad3de8d24c71bdb9a655dc18e3afc1bac990643a120a3ec9de45be887a89ef840e5a88c2f4dc8e3a3a435fd3185b1884d57d6c292864e7c5'
|
||||
'a42221d80b89020d0067d80908a62de0fa3ef0f012a8497b275d1bde055b4caf215b4afc17c8d8ace37a02742694a1c89873d18678e0d16e69e47840c169ace9'
|
||||
'2ca4d73b79871d5f25d4630e09341847df7ed86867a0340af5d4deb88a7d653f694767acdb95a336aadd722b109f39b93e59bc268bf476748d65175c55010afb'
|
||||
'00b4f6774fd6f864344bc087ff0fafdd485293527db2a4bef0ca2ba37639383f56977c794687c345b705462c2ad442062205938ec9e5e79647aeba2f9f530537'
|
||||
'70654a9f14c6fec9b8a07ba26a2b0405ad560a405f4c86607e5d08a39a0395bc8f03c1d463d42bc42dca2cc95e4f0cbf34d0e4eb74717740b2679ff6cf0985f6')
|
||||
|
||||
case $CARCH in
|
||||
i?86) _corearch=i386 ;;
|
||||
x86_64) _corearch=x86_64 ;;
|
||||
esac
|
||||
|
||||
prepare() {
|
||||
mkdir build-{full,headless}
|
||||
mkdir -p extra-arch-{full,headless}/usr/{bin,share/qemu}
|
||||
|
||||
cd qemu-${pkgver}
|
||||
|
||||
if [[ ${pkgver%.*} = ${_debver%+*} ]]; then
|
||||
# Debian patches
|
||||
export QUILT_PATCHES=debian/patches
|
||||
export QUILT_REFRESH_ARGS='-p ab --no-timestamps --no-index'
|
||||
export QUILT_DIFF_ARGS='--no-timestamps'
|
||||
|
||||
mv "$srcdir"/debian .
|
||||
|
||||
# Doesn't apply
|
||||
rm -v debian/patches/skip-meson-pc-bios.diff || true
|
||||
|
||||
quilt push -av
|
||||
fi
|
||||
|
||||
patch -p1 < $srcdir/sndio.patch
|
||||
}
|
||||
|
||||
build() {
|
||||
_build full \
|
||||
--audio-drv-list="sndio alsa sdl"
|
||||
|
||||
_build headless \
|
||||
--audio-drv-list="sndio alsa sdl" \
|
||||
--disable-gtk \
|
||||
--disable-vte
|
||||
}
|
||||
|
||||
_build() (
|
||||
cd build-$1
|
||||
|
||||
../qemu-${pkgver}/configure \
|
||||
--prefix=/usr \
|
||||
--sysconfdir=/etc \
|
||||
--localstatedir=/var \
|
||||
--libexecdir=/usr/libexec/qemu \
|
||||
--smbd=/usr/sbin/smbd \
|
||||
--enable-modules \
|
||||
--enable-sdl \
|
||||
--enable-slirp=system \
|
||||
--enable-xfsctl \
|
||||
--disable-smartcard \
|
||||
"${@:2}"
|
||||
|
||||
ninja
|
||||
)
|
||||
|
||||
package_qemu-legacy() {
|
||||
optdepends=('qemu-arch-extra-legacy: extra architectures support'
|
||||
'sndio: audio and MIDI server support')
|
||||
provides=(qemu-headless-legacy)
|
||||
conflicts=(qemu-headless-legacy)
|
||||
replaces=(qemu-kvm)
|
||||
|
||||
_package full
|
||||
|
||||
for i in COPYING{,.LIB} LICENSE; do
|
||||
install -Dm644 "$srcdir/qemu-$pkgver/$i" "$pkgdir/usr/share/licenses/$pkgname/$i"
|
||||
done
|
||||
}
|
||||
|
||||
package_qemu-headless-legacy() {
|
||||
pkgdesc="QEMU without GUI (legacy version)"
|
||||
depends=("${_headlessdeps[@]}")
|
||||
optdepends=('qemu-headless-arch-extra-legacy: extra architectures support'
|
||||
'sndio: audio and MIDI server support')
|
||||
|
||||
_package headless
|
||||
|
||||
for i in COPYING{,.LIB} LICENSE; do
|
||||
install -Dm644 "$srcdir/qemu-$pkgver/$i" "$pkgdir/usr/share/licenses/$pkgname/$i"
|
||||
done
|
||||
}
|
||||
|
||||
_package() {
|
||||
optdepends+=('samba: SMB/CIFS server support'
|
||||
'qemu-block-iscsi-legacy: iSCSI block support')
|
||||
install=qemu.install
|
||||
options=(!strip !emptydirs)
|
||||
|
||||
DESTDIR="$pkgdir" ninja -C build-$1 install "${@:2}"
|
||||
|
||||
# udev rules
|
||||
install -Dm644 65-kvm.rules "$pkgdir/lib/udev/rules.d/65-kvm.rules"
|
||||
|
||||
# remove conflicting /var/run directory
|
||||
cd "$pkgdir"
|
||||
rm -r var
|
||||
|
||||
cd usr/lib
|
||||
|
||||
# bridge_helper needs suid
|
||||
# https://bugs.archlinux.org/task/32565
|
||||
chmod u+s ../libexec/qemu/qemu-bridge-helper
|
||||
|
||||
# remove split block modules
|
||||
rm qemu/block-iscsi.so
|
||||
|
||||
cd ../bin
|
||||
|
||||
# remove extra arch
|
||||
for _bin in qemu-*; do
|
||||
[[ -f $_bin ]] || continue
|
||||
|
||||
case ${_bin#qemu-} in
|
||||
# guest agent
|
||||
ga) rm "$_bin"; continue ;;
|
||||
|
||||
# tools
|
||||
edid|img|io|keymap|nbd|pr-helper|storage-daemon) continue ;;
|
||||
|
||||
# core emu
|
||||
system-${_corearch}) continue ;;
|
||||
esac
|
||||
|
||||
mv "$_bin" "$srcdir/extra-arch-$1/usr/bin"
|
||||
done
|
||||
|
||||
cd ../share/qemu
|
||||
for _blob in *; do
|
||||
[[ -f $_blob ]] || continue
|
||||
|
||||
case $_blob in
|
||||
# provided by seabios package
|
||||
bios.bin|bios-256k.bin|vgabios-cirrus.bin|vgabios-qxl.bin|\
|
||||
vgabios-stdvga.bin|vgabios-vmware.bin|vgabios-virtio.bin|vgabios-bochs-display.bin|\
|
||||
vgabios-ramfb.bin) rm "$_blob"; continue ;;
|
||||
|
||||
# provided by edk2-ovmf package
|
||||
edk2-*) rm "$_blob"; continue ;;
|
||||
|
||||
# iPXE ROMs
|
||||
efi-*|pxe-*) continue ;;
|
||||
|
||||
# core blobs
|
||||
bios-microvm.bin|kvmvapic.bin|linuxboot*|multiboot.bin|sgabios.bin|vgabios*) continue ;;
|
||||
|
||||
# Trace events definitions
|
||||
trace-events*) continue ;;
|
||||
esac
|
||||
|
||||
mv "$_blob" "$srcdir/extra-arch-$1/usr/share/qemu"
|
||||
done
|
||||
|
||||
# provided by edk2-ovmf package
|
||||
rm -r firmware
|
||||
|
||||
cd ..
|
||||
if [ "$1" = headless ]; then rm -r {applications,icons}; fi
|
||||
}
|
||||
|
||||
package_qemu-arch-extra-legacy() {
|
||||
pkgdesc="QEMU for foreign architectures (legacy version)"
|
||||
depends=(qemu-legacy)
|
||||
provides=(qemu-headless-arch-extra-legacy)
|
||||
conflicts=(qemu-headless-arch-extra-legacy)
|
||||
options=(!strip)
|
||||
|
||||
mv extra-arch-full/usr "$pkgdir"
|
||||
|
||||
for i in COPYING{,.LIB} LICENSE; do
|
||||
install -Dm644 "$srcdir/qemu-$pkgver/$i" "$pkgdir/usr/share/licenses/$pkgname/$i"
|
||||
done
|
||||
}
|
||||
|
||||
package_qemu-headless-arch-extra-legacy() {
|
||||
pkgdesc="QEMU without GUI, for foreign architectures (legacy version)"
|
||||
depends=(qemu-headless-legacy)
|
||||
options=(!strip)
|
||||
|
||||
mv extra-arch-headless/usr "$pkgdir"
|
||||
|
||||
for i in COPYING{,.LIB} LICENSE; do
|
||||
install -Dm644 "$srcdir/qemu-$pkgver/$i" "$pkgdir/usr/share/licenses/$pkgname/$i"
|
||||
done
|
||||
}
|
||||
|
||||
package_qemu-block-iscsi-legacy() {
|
||||
pkgdesc="QEMU iSCSI block module (legacy version)"
|
||||
depends=(glib2 libiscsi)
|
||||
|
||||
install -D build-full/block-iscsi.so "$pkgdir/usr/lib/qemu/block-iscsi.so"
|
||||
|
||||
for i in COPYING{,.LIB} LICENSE; do
|
||||
install -Dm644 "$srcdir/qemu-$pkgver/$i" "$pkgdir/usr/share/licenses/$pkgname/$i"
|
||||
done
|
||||
}
|
||||
|
||||
package_qemu-guest-agent-legacy() {
|
||||
pkgdesc="QEMU Guest Agent (legacy version)"
|
||||
depends=(gcc-libs glib2 libeudev)
|
||||
backup=(etc/sv/qemu-ga/conf)
|
||||
|
||||
install -D build-full/qga/qemu-ga "$pkgdir/usr/sbin/qemu-ga"
|
||||
install -Dm755 "$srcdir/qemu-$pkgver/scripts/qemu-guest-agent/fsfreeze-hook" "$pkgdir/etc/qemu/fsfreeze-hook"
|
||||
|
||||
install -Dm755 "$srcdir/qemu-ga.initd" "$pkgdir/etc/init.d/qemu-ga"
|
||||
|
||||
install -Dm644 "$srcdir/qemu-ga.conf" "$pkgdir/etc/sv/qemu-ga/conf"
|
||||
install -Dm755 "$srcdir/qemu-ga.run" "$pkgdir/etc/sv/qemu-ga/run"
|
||||
|
||||
for i in COPYING{,.LIB} LICENSE; do
|
||||
install -Dm644 "$srcdir/qemu-$pkgver/$i" "$pkgdir/usr/share/licenses/$pkgname/$i"
|
||||
done
|
||||
}
|
||||
1
qemu-legacy/qemu-ga.conf
Normal file
1
qemu-legacy/qemu-ga.conf
Normal file
@@ -0,0 +1 @@
|
||||
OPTS=""
|
||||
13
qemu-legacy/qemu-ga.initd
Normal file
13
qemu-legacy/qemu-ga.initd
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/sbin/openrc-run
|
||||
# Copyright 2017-2019 Hyperbola Project
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
|
||||
description="QEMU Guest Agent service"
|
||||
|
||||
command="/usr/sbin/qemu-ga"
|
||||
command_args="-d"
|
||||
pidfile="/var/run/qemu-ga.pid"
|
||||
|
||||
depend() {
|
||||
need localmount
|
||||
}
|
||||
3
qemu-legacy/qemu-ga.run
Normal file
3
qemu-legacy/qemu-ga.run
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
[ -r conf ] && . ./conf
|
||||
exec qemu-ga ${OPTS}
|
||||
21
qemu-legacy/qemu.install
Normal file
21
qemu-legacy/qemu.install
Normal file
@@ -0,0 +1,21 @@
|
||||
post_install() {
|
||||
if ! getent group kvm &>/dev/null; then
|
||||
groupadd kvm -f -g 78 >/dev/null
|
||||
fi
|
||||
|
||||
# trigger events on modules files when already loaded
|
||||
for _f in /sys/devices/virtual/misc/{kvm,vhost-net}; do
|
||||
[[ -e "$_f" ]] && udevadm trigger "$_f"
|
||||
done
|
||||
:
|
||||
}
|
||||
|
||||
post_upgrade() {
|
||||
post_install
|
||||
}
|
||||
|
||||
post_remove() {
|
||||
if getent group kvm &>/dev/null; then
|
||||
groupdel kvm >/dev/null
|
||||
fi
|
||||
}
|
||||
781
qemu-legacy/sndio.patch
Normal file
781
qemu-legacy/sndio.patch
Normal file
@@ -0,0 +1,781 @@
|
||||
diff --git a/audio/audio.c b/audio/audio.c
|
||||
index 46578e4..dd38f4b 100644
|
||||
--- a/audio/audio.c
|
||||
+++ b/audio/audio.c
|
||||
@@ -2027,6 +2027,7 @@ void audio_create_pdos(Audiodev *dev)
|
||||
CASE(OSS, oss, Oss);
|
||||
CASE(PA, pa, Pa);
|
||||
CASE(SDL, sdl, );
|
||||
+ CASE(SNDIO, sndio, );
|
||||
CASE(SPICE, spice, );
|
||||
CASE(WAV, wav, );
|
||||
|
||||
diff --git a/audio/audio_template.h b/audio/audio_template.h
|
||||
index 8dd48ce..f2dd279 100644
|
||||
--- a/audio/audio_template.h
|
||||
+++ b/audio/audio_template.h
|
||||
@@ -338,6 +338,8 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev)
|
||||
return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE);
|
||||
case AUDIODEV_DRIVER_SDL:
|
||||
return dev->u.sdl.TYPE;
|
||||
+ case AUDIODEV_DRIVER_SNDIO:
|
||||
+ return dev->u.sndio.TYPE;
|
||||
case AUDIODEV_DRIVER_SPICE:
|
||||
return dev->u.spice.TYPE;
|
||||
case AUDIODEV_DRIVER_WAV:
|
||||
diff --git a/audio/meson.build b/audio/meson.build
|
||||
index 7d53b0f..c992d8a 100644
|
||||
--- a/audio/meson.build
|
||||
+++ b/audio/meson.build
|
||||
@@ -17,6 +17,7 @@ foreach m : [
|
||||
['CONFIG_AUDIO_OSS', 'oss', oss, 'ossaudio.c'],
|
||||
['CONFIG_AUDIO_PA', 'pa', pulse, 'paaudio.c'],
|
||||
['CONFIG_AUDIO_SDL', 'sdl', sdl, 'sdlaudio.c'],
|
||||
+ ['CONFIG_AUDIO_SNDIO', 'sndio', sndio, 'sndioaudio.c'],
|
||||
['CONFIG_AUDIO_JACK', 'jack', jack, 'jackaudio.c'],
|
||||
['CONFIG_SPICE', 'spice', spice, 'spiceaudio.c']
|
||||
]
|
||||
diff --git b/audio/sndioaudio.c b/audio/sndioaudio.c
|
||||
new file mode 100644
|
||||
index 0000000..204af07
|
||||
--- /dev/null
|
||||
+++ b/audio/sndioaudio.c
|
||||
@@ -0,0 +1,555 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2019 Alexandre Ratchov <alex@caoua.org>
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * TODO :
|
||||
+ *
|
||||
+ * Use a single device and open it in full-duplex rather than
|
||||
+ * opening it twice (once for playback once for recording).
|
||||
+ *
|
||||
+ * This is the only way to ensure that playback doesn't drift with respect
|
||||
+ * to recording, which is what guest systems expect.
|
||||
+ */
|
||||
+
|
||||
+#include <poll.h>
|
||||
+#include <sndio.h>
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "qemu-common.h"
|
||||
+#include "qemu/main-loop.h"
|
||||
+#include "audio.h"
|
||||
+#include "trace.h"
|
||||
+
|
||||
+#define AUDIO_CAP "sndio"
|
||||
+#include "audio_int.h"
|
||||
+
|
||||
+/* default latency in ms if no option is set */
|
||||
+#define SNDIO_LATENCY_US 50000
|
||||
+
|
||||
+typedef struct SndioVoice {
|
||||
+ union {
|
||||
+ HWVoiceOut out;
|
||||
+ HWVoiceIn in;
|
||||
+ } hw;
|
||||
+ struct sio_par par;
|
||||
+ struct sio_hdl *hdl;
|
||||
+ struct pollfd *pfds;
|
||||
+ struct pollindex {
|
||||
+ struct SndioVoice *self;
|
||||
+ int index;
|
||||
+ } *pindexes;
|
||||
+ unsigned char *buf;
|
||||
+ size_t buf_size;
|
||||
+ size_t sndio_pos;
|
||||
+ size_t qemu_pos;
|
||||
+ unsigned int mode;
|
||||
+ unsigned int nfds;
|
||||
+} SndioVoice;
|
||||
+
|
||||
+typedef struct SndioConf {
|
||||
+ const char *devname;
|
||||
+ unsigned int latency;
|
||||
+} SndioConf;
|
||||
+
|
||||
+/* needed for forward reference */
|
||||
+static void sndio_poll_in(void *arg);
|
||||
+static void sndio_poll_out(void *arg);
|
||||
+
|
||||
+/*
|
||||
+ * stop polling descriptors
|
||||
+ */
|
||||
+static void sndio_poll_clear(SndioVoice *self)
|
||||
+{
|
||||
+ struct pollfd *pfd;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < self->nfds; i++) {
|
||||
+ pfd = &self->pfds[i];
|
||||
+ qemu_set_fd_handler (pfd->fd, NULL, NULL, NULL);
|
||||
+ }
|
||||
+
|
||||
+ self->nfds = 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * write data to the device until it blocks or
|
||||
+ * all of our buffered data is written
|
||||
+ */
|
||||
+static void sndio_write(SndioVoice *self)
|
||||
+{
|
||||
+ size_t todo, n;
|
||||
+
|
||||
+ todo = self->qemu_pos - self->sndio_pos;
|
||||
+
|
||||
+ /*
|
||||
+ * transfer data to device, until it blocks
|
||||
+ */
|
||||
+ while (todo > 0) {
|
||||
+ n = sio_write(self->hdl, self->buf + self->sndio_pos, todo);
|
||||
+ if (n == 0) {
|
||||
+ break;
|
||||
+ }
|
||||
+ self->sndio_pos += n;
|
||||
+ todo -= n;
|
||||
+ }
|
||||
+
|
||||
+ if (self->sndio_pos == self->buf_size) {
|
||||
+ /*
|
||||
+ * we complete the block
|
||||
+ */
|
||||
+ self->sndio_pos = 0;
|
||||
+ self->qemu_pos = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * read data from the device until it blocks or
|
||||
+ * there no room any longer
|
||||
+ */
|
||||
+static void sndio_read(SndioVoice *self)
|
||||
+{
|
||||
+ size_t todo, n;
|
||||
+
|
||||
+ todo = self->buf_size - self->sndio_pos;
|
||||
+
|
||||
+ /*
|
||||
+ * transfer data from the device, until it blocks
|
||||
+ */
|
||||
+ while (todo > 0) {
|
||||
+ n = sio_read(self->hdl, self->buf + self->sndio_pos, todo);
|
||||
+ if (n == 0) {
|
||||
+ break;
|
||||
+ }
|
||||
+ self->sndio_pos += n;
|
||||
+ todo -= n;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Set handlers for all descriptors libsndio needs to
|
||||
+ * poll
|
||||
+ */
|
||||
+static void sndio_poll_wait(SndioVoice *self)
|
||||
+{
|
||||
+ struct pollfd *pfd;
|
||||
+ int events, i;
|
||||
+
|
||||
+ events = 0;
|
||||
+ if (self->mode == SIO_PLAY) {
|
||||
+ if (self->sndio_pos < self->qemu_pos) {
|
||||
+ events |= POLLOUT;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (self->sndio_pos < self->buf_size) {
|
||||
+ events |= POLLIN;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * fill the given array of descriptors with the events sndio
|
||||
+ * wants, they are different from our 'event' variable because
|
||||
+ * sndio may use descriptors internally.
|
||||
+ */
|
||||
+ self->nfds = sio_pollfd(self->hdl, self->pfds, events);
|
||||
+
|
||||
+ for (i = 0; i < self->nfds; i++) {
|
||||
+ pfd = &self->pfds[i];
|
||||
+ if (pfd->fd < 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ qemu_set_fd_handler(pfd->fd,
|
||||
+ (pfd->events & POLLIN) ? sndio_poll_in : NULL,
|
||||
+ (pfd->events & POLLOUT) ? sndio_poll_out : NULL,
|
||||
+ &self->pindexes[i]);
|
||||
+ pfd->revents = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * call-back called when one of the descriptors
|
||||
+ * became readable or writable
|
||||
+ */
|
||||
+static void sndio_poll_event(SndioVoice *self, int index, int event)
|
||||
+{
|
||||
+ int revents;
|
||||
+
|
||||
+ /*
|
||||
+ * ensure we're not called twice this cycle
|
||||
+ */
|
||||
+ sndio_poll_clear(self);
|
||||
+
|
||||
+ /*
|
||||
+ * make self->pfds[] look as we're returning from poll syscal,
|
||||
+ * this is how sio_revents expects events to be.
|
||||
+ */
|
||||
+ self->pfds[index].revents = event;
|
||||
+
|
||||
+ /*
|
||||
+ * tell sndio to handle events and return whether we can read or
|
||||
+ * write without blocking.
|
||||
+ */
|
||||
+ revents = sio_revents(self->hdl, self->pfds);
|
||||
+ if (self->mode == SIO_PLAY) {
|
||||
+ if (revents & POLLOUT) {
|
||||
+ sndio_write(self);
|
||||
+ }
|
||||
+
|
||||
+ if (self->qemu_pos < self->buf_size) {
|
||||
+ audio_run(self->hw.out.s, "sndio_out");
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (revents & POLLIN) {
|
||||
+ sndio_read(self);
|
||||
+ }
|
||||
+
|
||||
+ if (self->qemu_pos < self->sndio_pos) {
|
||||
+ audio_run(self->hw.in.s, "sndio_in");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ sndio_poll_wait(self);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * return a buffer where data to play can be stored,
|
||||
+ * its size is stored in the location pointed by the size argument.
|
||||
+ */
|
||||
+static void *sndio_get_buffer_out(HWVoiceOut *hw, size_t *size)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ /* size is not set by the caller */
|
||||
+ *size = self->buf_size - self->qemu_pos;
|
||||
+ return self->buf + self->qemu_pos;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * return a buffer where data to play can be stored
|
||||
+ */
|
||||
+static size_t sndio_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ self->qemu_pos += size;
|
||||
+ sndio_poll_wait(self);
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * return a buffer from where recorded data is available,
|
||||
+ * its size is stored in the location pointed by the size argument.
|
||||
+ * it may not exceed the initial value of "*size".
|
||||
+ */
|
||||
+static void *sndio_get_buffer_in(HWVoiceIn *hw, size_t *size)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+ size_t todo, max_todo;
|
||||
+
|
||||
+ /*
|
||||
+ * unlike the get_buffer_out() method, get_buffer_in()
|
||||
+ * must return a buffer of at most the given size, see audio.c
|
||||
+ */
|
||||
+ max_todo = *size;
|
||||
+
|
||||
+ todo = self->sndio_pos - self->qemu_pos;
|
||||
+ if (todo > max_todo) {
|
||||
+ todo = max_todo;
|
||||
+ }
|
||||
+
|
||||
+ *size = todo;
|
||||
+ return self->buf + self->qemu_pos;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * discard the given amount of recorded data
|
||||
+ */
|
||||
+static void sndio_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ self->qemu_pos += size;
|
||||
+ if (self->qemu_pos == self->buf_size) {
|
||||
+ self->qemu_pos = 0;
|
||||
+ self->sndio_pos = 0;
|
||||
+ }
|
||||
+ sndio_poll_wait(self);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * call-back called when one of our descriptors becomes writable
|
||||
+ */
|
||||
+static void sndio_poll_out(void *arg)
|
||||
+{
|
||||
+ struct pollindex *pindex = (struct pollindex *) arg;
|
||||
+
|
||||
+ sndio_poll_event(pindex->self, pindex->index, POLLOUT);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * call-back called when one of our descriptors becomes readable
|
||||
+ */
|
||||
+static void sndio_poll_in(void *arg)
|
||||
+{
|
||||
+ struct pollindex *pindex = (struct pollindex *) arg;
|
||||
+
|
||||
+ sndio_poll_event(pindex->self, pindex->index, POLLIN);
|
||||
+}
|
||||
+
|
||||
+static void sndio_fini(SndioVoice *self)
|
||||
+{
|
||||
+ if (self->hdl) {
|
||||
+ sio_close(self->hdl);
|
||||
+ self->hdl = NULL;
|
||||
+ }
|
||||
+
|
||||
+ g_free(self->pfds);
|
||||
+ g_free(self->pindexes);
|
||||
+ g_free(self->buf);
|
||||
+}
|
||||
+
|
||||
+static int sndio_init(SndioVoice *self,
|
||||
+ struct audsettings *as, int mode, Audiodev *dev)
|
||||
+{
|
||||
+ AudiodevSndioOptions *opts = &dev->u.sndio;
|
||||
+ unsigned long long latency;
|
||||
+ const char *dev_name;
|
||||
+ struct sio_par req;
|
||||
+ unsigned int nch;
|
||||
+ int i, nfds;
|
||||
+
|
||||
+ dev_name = opts->has_dev ? opts->dev : SIO_DEVANY;
|
||||
+ latency = opts->has_latency ? opts->latency : SNDIO_LATENCY_US;
|
||||
+
|
||||
+ /* open the device in non-blocking mode */
|
||||
+ self->hdl = sio_open(dev_name, mode, 1);
|
||||
+ if (self->hdl == NULL) {
|
||||
+ dolog("failed to open device\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ self->mode = mode;
|
||||
+
|
||||
+ sio_initpar(&req);
|
||||
+
|
||||
+ switch (as->fmt) {
|
||||
+ case AUDIO_FORMAT_S8:
|
||||
+ req.bits = 8;
|
||||
+ req.sig = 1;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_U8:
|
||||
+ req.bits = 8;
|
||||
+ req.sig = 0;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_S16:
|
||||
+ req.bits = 16;
|
||||
+ req.sig = 1;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_U16:
|
||||
+ req.bits = 16;
|
||||
+ req.sig = 0;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_S32:
|
||||
+ req.bits = 32;
|
||||
+ req.sig = 1;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_U32:
|
||||
+ req.bits = 32;
|
||||
+ req.sig = 0;
|
||||
+ default:
|
||||
+ dolog("unknown audio sample format\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (req.bits > 8) {
|
||||
+ req.le = as->endianness ? 0 : 1;
|
||||
+ }
|
||||
+
|
||||
+ req.rate = as->freq;
|
||||
+ if (mode == SIO_PLAY) {
|
||||
+ req.pchan = as->nchannels;
|
||||
+ } else {
|
||||
+ req.rchan = as->nchannels;
|
||||
+ }
|
||||
+
|
||||
+ /* set on-device buffer size */
|
||||
+ req.appbufsz = req.rate * latency / 1000000;
|
||||
+
|
||||
+ if (!sio_setpar(self->hdl, &req)) {
|
||||
+ dolog("failed set audio params\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (!sio_getpar(self->hdl, &self->par)) {
|
||||
+ dolog("failed get audio params\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ nch = (mode == SIO_PLAY) ? self->par.pchan : self->par.rchan;
|
||||
+
|
||||
+ /*
|
||||
+ * With the default setup, sndio supports any combination of parameters
|
||||
+ * so these checks are mostly to catch configuration errors.
|
||||
+ */
|
||||
+ if (self->par.bits != req.bits || self->par.bps != req.bits / 8 ||
|
||||
+ self->par.sig != req.sig || (req.bits > 8 && self->par.le != req.le) ||
|
||||
+ self->par.rate != as->freq || nch != as->nchannels) {
|
||||
+ dolog("unsupported audio params\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * we use one block as buffer size; this is how
|
||||
+ * transfers get well aligned
|
||||
+ */
|
||||
+ self->buf_size = self->par.round * self->par.bps * nch;
|
||||
+
|
||||
+ self->buf = g_malloc(self->buf_size);
|
||||
+ if (self->buf == NULL) {
|
||||
+ dolog("failed to allocate audio buffer\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ nfds = sio_nfds(self->hdl);
|
||||
+
|
||||
+ self->pfds = g_malloc_n(nfds, sizeof(struct pollfd));
|
||||
+ if (self->pfds == NULL) {
|
||||
+ dolog("failed to allocate pollfd structures\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ self->pindexes = g_malloc_n(nfds, sizeof(struct pollindex));
|
||||
+ if (self->pindexes == NULL) {
|
||||
+ dolog("failed to allocate pollindex structures\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < nfds; i++) {
|
||||
+ self->pindexes[i].self = self;
|
||||
+ self->pindexes[i].index = i;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+fail:
|
||||
+ sndio_fini(self);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static void sndio_enable(SndioVoice *self, bool enable)
|
||||
+{
|
||||
+ if (enable) {
|
||||
+ sio_start(self->hdl);
|
||||
+ sndio_poll_wait(self);
|
||||
+ } else {
|
||||
+ sndio_poll_clear(self);
|
||||
+ sio_stop(self->hdl);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void sndio_enable_out(HWVoiceOut *hw, bool enable)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ return sndio_enable(self, enable);
|
||||
+}
|
||||
+
|
||||
+static void sndio_enable_in(HWVoiceIn *hw, bool enable)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ return sndio_enable(self, enable);
|
||||
+}
|
||||
+
|
||||
+static int sndio_init_out(HWVoiceOut *hw, struct audsettings *as, void *opaque)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ if (sndio_init(self, as, SIO_PLAY, opaque) == -1) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ audio_pcm_init_info(&hw->info, as);
|
||||
+ hw->samples = self->par.round;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int sndio_init_in(HWVoiceIn *hw, struct audsettings *as, void *opaque)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ if (sndio_init(self, as, SIO_REC, opaque) == -1) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ audio_pcm_init_info(&hw->info, as);
|
||||
+ hw->samples = self->par.round;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void sndio_fini_out(HWVoiceOut *hw)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ return sndio_fini(self);
|
||||
+}
|
||||
+
|
||||
+static void sndio_fini_in(HWVoiceIn *hw)
|
||||
+{
|
||||
+ SndioVoice *self = (SndioVoice *) hw;
|
||||
+
|
||||
+ return sndio_fini(self);
|
||||
+}
|
||||
+
|
||||
+static void *sndio_audio_init(Audiodev *dev)
|
||||
+{
|
||||
+ assert(dev->driver == AUDIODEV_DRIVER_SNDIO);
|
||||
+ return dev;
|
||||
+}
|
||||
+
|
||||
+static void sndio_audio_fini(void *opaque)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static struct audio_pcm_ops sndio_pcm_ops = {
|
||||
+ .init_out = sndio_init_out,
|
||||
+ .fini_out = sndio_fini_out,
|
||||
+ .enable_out = sndio_enable_out,
|
||||
+ .get_buffer_out = sndio_get_buffer_out,
|
||||
+ .put_buffer_out = sndio_put_buffer_out,
|
||||
+ .init_in = sndio_init_in,
|
||||
+ .fini_in = sndio_fini_in,
|
||||
+ .enable_in = sndio_enable_in,
|
||||
+ .get_buffer_in = sndio_get_buffer_in,
|
||||
+ .put_buffer_in = sndio_put_buffer_in,
|
||||
+};
|
||||
+
|
||||
+static struct audio_driver sndio_audio_driver = {
|
||||
+ .name = "sndio",
|
||||
+ .descr = "https://man.openbsd.org/sndio",
|
||||
+ .init = sndio_audio_init,
|
||||
+ .fini = sndio_audio_fini,
|
||||
+ .pcm_ops = &sndio_pcm_ops,
|
||||
+ .can_be_default = 1,
|
||||
+ .max_voices_out = INT_MAX,
|
||||
+ .max_voices_in = INT_MAX,
|
||||
+ .voice_size_out = sizeof(SndioVoice),
|
||||
+ .voice_size_in = sizeof(SndioVoice)
|
||||
+};
|
||||
+
|
||||
+static void register_audio_sndio(void)
|
||||
+{
|
||||
+ audio_driver_register(&sndio_audio_driver);
|
||||
+}
|
||||
+
|
||||
+type_init(register_audio_sndio);
|
||||
diff --git a/configure b/configure
|
||||
index 18c26e0..a06f64a 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -756,8 +756,8 @@ NetBSD)
|
||||
OpenBSD)
|
||||
bsd="yes"
|
||||
make="${MAKE-gmake}"
|
||||
- audio_drv_list="try-sdl"
|
||||
- audio_possible_drivers="sdl"
|
||||
+ audio_drv_list="sndio"
|
||||
+ audio_possible_drivers="sndio"
|
||||
;;
|
||||
Darwin)
|
||||
bsd="yes"
|
||||
@@ -792,8 +792,8 @@ Haiku)
|
||||
QEMU_CFLAGS="-DB_USE_POSITIVE_POSIX_ERRORS -D_BSD_SOURCE $QEMU_CFLAGS"
|
||||
;;
|
||||
Linux)
|
||||
- audio_drv_list="try-pa oss"
|
||||
- audio_possible_drivers="oss alsa sdl pa"
|
||||
+ audio_drv_list="try-sndio oss"
|
||||
+ audio_possible_drivers="oss alsa sdl sndio pa"
|
||||
linux="yes"
|
||||
linux_user="yes"
|
||||
vhost_user="yes"
|
||||
@@ -3381,6 +3381,24 @@ for drv in $audio_drv_list; do
|
||||
fi
|
||||
;;
|
||||
|
||||
+ sndio | try-sndio)
|
||||
+ if $pkg_config sndio --exists; then
|
||||
+ sndio=yes
|
||||
+ sndio_libs=$($pkg_config sndio --libs)
|
||||
+ sndio_cflags=$($pkg_config sndio --cflags)
|
||||
+ if test "$drv" = "try-sndio"; then
|
||||
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-sndio/sndio/')
|
||||
+ fi
|
||||
+ else
|
||||
+ if test "$drv" = "try-sndio"; then
|
||||
+ audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/try-sndio//')
|
||||
+ else
|
||||
+ error_exit "$drv check failed" \
|
||||
+ "Make sure to have the $drv libs and headers installed."
|
||||
+ fi
|
||||
+ fi
|
||||
+ ;;
|
||||
+
|
||||
coreaudio)
|
||||
coreaudio_libs="-framework CoreAudio"
|
||||
;;
|
||||
@@ -5667,7 +5685,6 @@ write_c_skeleton
|
||||
if test "$gcov" = "yes" ; then
|
||||
:
|
||||
elif test "$fortify_source" = "yes" ; then
|
||||
- QEMU_CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $QEMU_CFLAGS"
|
||||
debug=no
|
||||
fi
|
||||
|
||||
@@ -6028,6 +6045,11 @@ echo "PULSE_CFLAGS=$pulse_cflags" >> $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 "$sndio" = "yes" ; then
|
||||
+ echo "CONFIG_SNDIO=y" >> $config_host_mak
|
||||
+fi
|
||||
+echo "SNDIO_LIBS=$sndio_libs" >> $config_host_mak
|
||||
+echo "SNDIO_CFLAGS=$sndio_cflags" >> $config_host_mak
|
||||
if test "$libjack" = "yes" ; then
|
||||
echo "CONFIG_LIBJACK=y" >> $config_host_mak
|
||||
fi
|
||||
diff --git a/meson.build b/meson.build
|
||||
index e338619..68c1320 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -359,6 +359,11 @@ jack = not_found
|
||||
if 'CONFIG_LIBJACK' in config_host
|
||||
jack = declare_dependency(link_args: config_host['JACK_LIBS'].split())
|
||||
endif
|
||||
+sndio = not_found
|
||||
+if 'CONFIG_SNDIO' in config_host
|
||||
+ sndio = declare_dependency(compile_args: config_host['SNDIO_CFLAGS'].split(),
|
||||
+ link_args: config_host['SNDIO_LIBS'].split())
|
||||
+endif
|
||||
spice = not_found
|
||||
spice_headers = not_found
|
||||
if 'CONFIG_SPICE' in config_host
|
||||
@@ -509,7 +514,7 @@ if have_system and not get_option('curses').disabled()
|
||||
endif
|
||||
endif
|
||||
if not curses.found()
|
||||
- curses_compile_args = ['-DNCURSES_WIDECHAR']
|
||||
+ curses_compile_args = ['-D_XOPEN_SOURCE_EXTENDED -DNCURSES_WIDECHAR']
|
||||
has_curses_h = cc.has_header('curses.h', args: curses_compile_args)
|
||||
if targetos != 'windows' and not has_curses_h
|
||||
message('Trying with /usr/include/ncursesw')
|
||||
@@ -2011,11 +2016,9 @@ if targetos == 'darwin'
|
||||
endif
|
||||
summary_info += {'ARFLAGS': config_host['ARFLAGS']}
|
||||
summary_info += {'CFLAGS': ' '.join(get_option('c_args')
|
||||
- + ['-O' + get_option('optimization')]
|
||||
+ (get_option('debug') ? ['-g'] : []))}
|
||||
if link_language == 'cpp'
|
||||
summary_info += {'CXXFLAGS': ' '.join(get_option('cpp_args')
|
||||
- + ['-O' + get_option('optimization')]
|
||||
+ (get_option('debug') ? ['-g'] : []))}
|
||||
endif
|
||||
link_args = get_option(link_language + '_link_args')
|
||||
diff --git a/qapi/audio.json b/qapi/audio.json
|
||||
index 072ed79..0b3d6f3 100644
|
||||
--- a/qapi/audio.json
|
||||
+++ b/qapi/audio.json
|
||||
@@ -106,6 +106,28 @@
|
||||
'*threshold': 'uint32' } }
|
||||
|
||||
##
|
||||
+# @AudiodevSndioOptions:
|
||||
+#
|
||||
+# Options of the sndio audio backend.
|
||||
+#
|
||||
+# @in: options of the capture stream
|
||||
+#
|
||||
+# @out: options of the playback stream
|
||||
+#
|
||||
+# @dev: the name of the sndio device to use (default 'default')
|
||||
+#
|
||||
+# @latency: play buffer size (in microseconds)
|
||||
+#
|
||||
+# Since: 5.0
|
||||
+##
|
||||
+{ 'struct': 'AudiodevSndioOptions',
|
||||
+ 'data': {
|
||||
+ '*in': 'AudiodevPerDirectionOptions',
|
||||
+ '*out': 'AudiodevPerDirectionOptions',
|
||||
+ '*dev': 'str',
|
||||
+ '*latency': 'uint32'} }
|
||||
+
|
||||
+##
|
||||
# @AudiodevCoreaudioPerDirectionOptions:
|
||||
#
|
||||
# Options of the Core Audio backend that are used for both playback and
|
||||
@@ -356,7 +378,7 @@
|
||||
##
|
||||
{ 'enum': 'AudiodevDriver',
|
||||
'data': [ 'none', 'alsa', 'coreaudio', 'dsound', 'jack', 'oss', 'pa',
|
||||
- 'sdl', 'spice', 'wav' ] }
|
||||
+ 'sdl', 'sndio', 'spice', 'wav' ] }
|
||||
|
||||
##
|
||||
# @Audiodev:
|
||||
@@ -386,5 +408,6 @@
|
||||
'oss': 'AudiodevOssOptions',
|
||||
'pa': 'AudiodevPaOptions',
|
||||
'sdl': 'AudiodevGenericOptions',
|
||||
+ 'sndio': 'AudiodevSndioOptions',
|
||||
'spice': 'AudiodevGenericOptions',
|
||||
'wav': 'AudiodevWavOptions' } }
|
||||
diff --git a/qemu-options.hx b/qemu-options.hx
|
||||
index 104632e..a611956 100644
|
||||
--- a/qemu-options.hx
|
||||
+++ b/qemu-options.hx
|
||||
@@ -582,6 +582,9 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
|
||||
#ifdef CONFIG_AUDIO_SDL
|
||||
"-audiodev sdl,id=id[,prop[=value][,...]]\n"
|
||||
#endif
|
||||
+#ifdef CONFIG_AUDIO_SNDIO
|
||||
+ "-audiodev sndio,id=id[,prop[=value][,...]]\n"
|
||||
+#endif
|
||||
#ifdef CONFIG_SPICE
|
||||
"-audiodev spice,id=id[,prop[=value][,...]]\n"
|
||||
#endif
|
||||
@@ -703,6 +706,11 @@ SRST
|
||||
``in|out.buffer-count=count``
|
||||
Sets the count of the buffers.
|
||||
|
||||
+``-audiodev sndio,id=id[,prop[=value][,...]]``
|
||||
+ Creates a backend using SNDIO. This backend is available on
|
||||
+ OpenBSD and most other Unix-like systems. This backend has no
|
||||
+ backend specific properties.
|
||||
+
|
||||
``in|out.try-poll=on|of``
|
||||
Attempt to use poll mode with the device. Default is on.
|
||||
|
||||
Reference in New Issue
Block a user