introduce -audio as a replacement for -soundhw

-audio is used like "-audio pa,model=sb16".  It is almost as simple as
-soundhw, but it reuses the -audiodev parsing machinery and attaches an
audiodev to the newly-created device.  The main 'feature' is that
it knows about adding the codec device for model=intel-hda, and adding
the audiodev to the codec device.

In the future, it could be extended to support default models or
builtin devices, just like -nic, or even a default backend.  For now,
keep it simple.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2022-04-27 12:27:46 +02:00
parent 67aaa96ae4
commit 039a68373c
9 changed files with 76 additions and 49 deletions

View File

@ -2099,13 +2099,19 @@ static void audio_validate_opts(Audiodev *dev, Error **errp)
void audio_parse_option(const char *opt) void audio_parse_option(const char *opt)
{ {
AudiodevListEntry *e;
Audiodev *dev = NULL; Audiodev *dev = NULL;
Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal); Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal);
visit_type_Audiodev(v, NULL, &dev, &error_fatal); visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v); visit_free(v);
audio_define(dev);
}
void audio_define(Audiodev *dev)
{
AudiodevListEntry *e;
audio_validate_opts(dev, &error_fatal); audio_validate_opts(dev, &error_fatal);
e = g_new0(AudiodevListEntry, 1); e = g_new0(AudiodevListEntry, 1);

View File

@ -168,6 +168,7 @@ void audio_sample_to_uint64(const void *samples, int pos,
void audio_sample_from_uint64(void *samples, int pos, void audio_sample_from_uint64(void *samples, int pos,
uint64_t left, uint64_t right); uint64_t left, uint64_t right);
void audio_define(Audiodev *audio);
void audio_parse_option(const char *opt); void audio_parse_option(const char *opt);
void audio_init_audiodevs(void); void audio_init_audiodevs(void);
void audio_legacy_help(void); void audio_legacy_help(void);

View File

@ -39,15 +39,6 @@ should specify an ``audiodev=`` property. Additionally, when using
vnc, you should specify an ``audiodev=`` property if you plan to vnc, you should specify an ``audiodev=`` property if you plan to
transmit audio through the VNC protocol. transmit audio through the VNC protocol.
Creating sound card devices using ``-soundhw`` (since 5.1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sound card devices should be created using ``-device`` instead. The
names are the same for most devices. The exceptions are ``hda`` which
needs two devices (``-device intel-hda -device hda-duplex``) and
``pcspk`` which can be activated using ``-machine
pcspk-audiodev=<name>``.
``-chardev`` backend aliases ``tty`` and ``parport`` (since 6.0) ``-chardev`` backend aliases ``tty`` and ``parport`` (since 6.0)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

View File

@ -654,6 +654,13 @@ tripped up the CI testing and was suspected to be quite broken. For that
reason the maintainers strongly suspected no one actually used it. reason the maintainers strongly suspected no one actually used it.
Creating sound card devices using ``-soundhw`` (removed in 7.1)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sound card devices should be created using ``-device`` or ``-audio``.
The exception is ``pcspk`` which can be activated using ``-machine
pcspk-audiodev=<name>``.
TCG introspection features TCG introspection features
-------------------------- --------------------------

View File

@ -1311,17 +1311,16 @@ static const TypeInfo hda_codec_device_type_info = {
* create intel hda controller with codec attached to it, * create intel hda controller with codec attached to it,
* so '-soundhw hda' works. * so '-soundhw hda' works.
*/ */
static int intel_hda_and_codec_init(PCIBus *bus) static int intel_hda_and_codec_init(PCIBus *bus, const char *audiodev)
{ {
DeviceState *controller; DeviceState *controller;
BusState *hdabus; BusState *hdabus;
DeviceState *codec; DeviceState *codec;
warn_report("'-soundhw hda' is deprecated, "
"please use '-device intel-hda -device hda-duplex' instead");
controller = DEVICE(pci_create_simple(bus, -1, "intel-hda")); controller = DEVICE(pci_create_simple(bus, -1, "intel-hda"));
hdabus = QLIST_FIRST(&controller->child_bus); hdabus = QLIST_FIRST(&controller->child_bus);
codec = qdev_new("hda-duplex"); codec = qdev_new("hda-duplex");
qdev_prop_set_string(codec, "audiodev", audiodev);
qdev_realize_and_unref(codec, hdabus, &error_fatal); qdev_realize_and_unref(codec, hdabus, &error_fatal);
return 0; return 0;
} }

View File

@ -27,6 +27,7 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qom/object.h" #include "qom/object.h"
#include "hw/qdev-properties.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "hw/audio/soundhw.h" #include "hw/audio/soundhw.h"
@ -36,14 +37,14 @@ struct soundhw {
const char *descr; const char *descr;
const char *typename; const char *typename;
int isa; int isa;
int (*init_pci) (PCIBus *bus); int (*init_pci) (PCIBus *bus, const char *audiodev);
}; };
static struct soundhw soundhw[9]; static struct soundhw soundhw[9];
static int soundhw_count; static int soundhw_count;
void pci_register_soundhw(const char *name, const char *descr, void pci_register_soundhw(const char *name, const char *descr,
int (*init_pci)(PCIBus *bus)) int (*init_pci)(PCIBus *bus, const char *audiodev))
{ {
assert(soundhw_count < ARRAY_SIZE(soundhw) - 1); assert(soundhw_count < ARRAY_SIZE(soundhw) - 1);
soundhw[soundhw_count].name = name; soundhw[soundhw_count].name = name;
@ -80,8 +81,9 @@ void show_valid_soundhw(void)
} }
static struct soundhw *selected = NULL; static struct soundhw *selected = NULL;
static const char *audiodev_id;
void select_soundhw(const char *optarg) void select_soundhw(const char *optarg, const char *audiodev)
{ {
struct soundhw *c; struct soundhw *c;
@ -92,6 +94,7 @@ void select_soundhw(const char *optarg)
for (c = soundhw; c->name; ++c) { for (c = soundhw; c->name; ++c) {
if (g_str_equal(c->name, optarg)) { if (g_str_equal(c->name, optarg)) {
selected = c; selected = c;
audiodev_id = audiodev;
break; break;
} }
} }
@ -129,10 +132,11 @@ void soundhw_init(void)
if (c->typename) { if (c->typename) {
DeviceState *dev = qdev_new(c->typename); DeviceState *dev = qdev_new(c->typename);
qdev_prop_set_string(dev, "audiodev", audiodev_id);
qdev_realize_and_unref(dev, bus, &error_fatal); qdev_realize_and_unref(dev, bus, &error_fatal);
} else { } else {
assert(!c->isa); assert(!c->isa);
c->init_pci(pci_bus); c->init_pci(pci_bus, audiodev_id);
} }
} }

View File

@ -2,12 +2,12 @@
#define HW_SOUNDHW_H #define HW_SOUNDHW_H
void pci_register_soundhw(const char *name, const char *descr, void pci_register_soundhw(const char *name, const char *descr,
int (*init_pci)(PCIBus *bus)); int (*init_pci)(PCIBus *bus, const char *audiodev));
void deprecated_register_soundhw(const char *name, const char *descr, void deprecated_register_soundhw(const char *name, const char *descr,
int isa, const char *typename); int isa, const char *typename);
void soundhw_init(void); void soundhw_init(void);
void show_valid_soundhw(void); void show_valid_soundhw(void);
void select_soundhw(const char *optarg); void select_soundhw(const char *optarg, const char *audiodev);
#endif #endif

View File

@ -661,6 +661,30 @@ SRST
(deprecated) environment variables. (deprecated) environment variables.
ERST ERST
DEF("audio", HAS_ARG, QEMU_OPTION_audio,
"-audio [driver=]driver,model=value[,prop[=value][,...]]\n"
" specifies the audio backend and device to use;\n"
" apart from 'model', options are the same as for -audiodev.\n"
" use '-audio model=help' to show possible devices.\n",
QEMU_ARCH_ALL)
SRST
``-audio [driver=]driver,model=value[,prop[=value][,...]]``
This option is a shortcut for configuring both the guest audio
hardware and the host audio backend in one go.
The host backend options are the same as with the corresponding
``-audiodev`` options below. The guest hardware model can be set with
``model=modelname``. Use ``model=help`` to list the available device
types.
The following two example do exactly the same, to show how ``-audio``
can be used to shorten the command line length:
.. parsed-literal::
|qemu_system| -audiodev pa,id=pa -device sb16,audiodev=pa
|qemu_system| -audio pa,model=sb16
ERST
DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
"-audiodev [driver=]driver,id=id[,prop[=value][,...]]\n" "-audiodev [driver=]driver,id=id[,prop[=value][,...]]\n"
" specifies the audio backend to use\n" " specifies the audio backend to use\n"
@ -892,33 +916,6 @@ SRST
``qemu.wav``. ``qemu.wav``.
ERST ERST
DEF("soundhw", HAS_ARG, QEMU_OPTION_soundhw,
"-soundhw c1,... enable audio support\n"
" and only specified sound cards (comma separated list)\n"
" use '-soundhw help' to get the list of supported cards\n"
" use '-soundhw all' to enable all of them\n", QEMU_ARCH_ALL)
SRST
``-soundhw card1[,card2,...] or -soundhw all``
Enable audio and selected sound hardware. Use 'help' to print all
available sound hardware. For example:
.. parsed-literal::
|qemu_system_x86| -soundhw sb16,adlib disk.img
|qemu_system_x86| -soundhw es1370 disk.img
|qemu_system_x86| -soundhw ac97 disk.img
|qemu_system_x86| -soundhw hda disk.img
|qemu_system_x86| -soundhw all disk.img
|qemu_system_x86| -soundhw help
Note that Linux's i810\_audio OSS kernel (for AC97) module might
require manually specifying clocking.
::
modprobe i810_audio clocking=48000
ERST
DEF("device", HAS_ARG, QEMU_OPTION_device, DEF("device", HAS_ARG, QEMU_OPTION_device,
"-device driver[,prop[=value][,...]]\n" "-device driver[,prop[=value][,...]]\n"
" add device (based on driver)\n" " add device (based on driver)\n"

View File

@ -116,6 +116,8 @@
#include "crypto/init.h" #include "crypto/init.h"
#include "sysemu/replay.h" #include "sysemu/replay.h"
#include "qapi/qapi-events-run-state.h" #include "qapi/qapi-events-run-state.h"
#include "qapi/qapi-types-audio.h"
#include "qapi/qapi-visit-audio.h"
#include "qapi/qapi-visit-block-core.h" #include "qapi/qapi-visit-block-core.h"
#include "qapi/qapi-visit-compat.h" #include "qapi/qapi-visit-compat.h"
#include "qapi/qapi-visit-ui.h" #include "qapi/qapi-visit-ui.h"
@ -2930,13 +2932,33 @@ void qemu_init(int argc, char **argv, char **envp)
case QEMU_OPTION_audiodev: case QEMU_OPTION_audiodev:
audio_parse_option(optarg); audio_parse_option(optarg);
break; break;
case QEMU_OPTION_soundhw: case QEMU_OPTION_audio: {
if (is_help_option(optarg)) { QDict *dict = keyval_parse(optarg, "driver", NULL, &error_fatal);
char *model;
Audiodev *dev = NULL;
Visitor *v;
if (!qdict_haskey(dict, "id")) {
qdict_put_str(dict, "id", "audiodev0");
}
if (!qdict_haskey(dict, "model")) {
error_setg(&error_fatal, "Parameter 'model' is missing");
}
model = g_strdup(qdict_get_str(dict, "model"));
qdict_del(dict, "model");
if (is_help_option(model)) {
show_valid_soundhw(); show_valid_soundhw();
exit(0); exit(0);
} }
select_soundhw (optarg); v = qobject_input_visitor_new_keyval(QOBJECT(dict));
qobject_unref(dict);
visit_type_Audiodev(v, NULL, &dev, &error_fatal);
visit_free(v);
audio_define(dev);
select_soundhw(model, dev->id);
g_free(model);
break; break;
}
case QEMU_OPTION_h: case QEMU_OPTION_h:
help(0); help(0);
break; break;