Disable the audio feature in VNC when QEMU is configured with
`--disable-audio`. Do not compile the corresponding audio-related
code.
The audio feature is disabled in a way that makes a QEMU server behave
like a non-QEMU server (as far as audio is concerned). The client sends
the audio pseudo-encoding, but the server does not respond with
confirmation, because send_ext_audio_ack is now behind an #ifdef.
A well-behaved client should handle this accordingly and continue
using VNC without sending any audio-related messages to the server.
If a client misbehaves and sends VNC_MSG_CLIENT_QEMU_AUDIO while
the audio feature is disabled, the server will close the connection with
an error.
The behaviour described above is already present when there is no audiodev
(`vs->vd->audio_be` is NULL).
Signed-off-by: Sergei Heifetz <heifetz@yandex-team.com>
---
qemu-options.hx | 3 +++
ui/vnc.c | 27 +++++++++++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/qemu-options.hx b/qemu-options.hx
index 890c4f1d230..04ea2239296 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2723,6 +2723,9 @@ SRST
must be omitted, otherwise is must be present and specify a
valid audiodev.
+ If QEMU is configured with ``--disable-audio``, this parameter
+ is not present and audio is not transmitted over VNC.
+
``power-control=on|off``
Permit the remote client to issue shutdown, reboot or reset power
control requests.
diff --git a/ui/vnc.c b/ui/vnc.c
index 952976e9649..0ee5502d1e6 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1072,6 +1072,7 @@ static void vnc_update_throttle_offset(VncState *vs)
size_t offset =
vs->client_width * vs->client_height * vs->client_pf.bytes_per_pixel;
+#ifdef CONFIG_AUDIO
if (vs->audio_cap) {
int bps;
switch (vs->as.fmt) {
@@ -1091,6 +1092,7 @@ static void vnc_update_throttle_offset(VncState *vs)
}
offset += vs->as.freq * bps * vs->as.nchannels;
}
+#endif
/* Put a floor of 1MB on offset, so that if we have a large pending
* buffer and the display is resized to a small size & back again
@@ -1214,6 +1216,7 @@ static int vnc_update_client(VncState *vs, int has_dirty)
return n;
}
+#ifdef CONFIG_AUDIO
/* audio */
static void audio_capture_notify(void *opaque, audcnotification_e cmd)
{
@@ -1293,6 +1296,7 @@ static void audio_del(VncState *vs)
vs->audio_cap = NULL;
}
}
+#endif
static void vnc_disconnect_start(VncState *vs)
{
@@ -1332,7 +1336,9 @@ void vnc_disconnect_finish(VncState *vs)
#ifdef CONFIG_VNC_SASL
vnc_sasl_client_cleanup(vs);
#endif /* CONFIG_VNC_SASL */
+#ifdef CONFIG_AUDIO
audio_del(vs);
+#endif
qkbd_state_lift_all_keys(vs->vd->kbd);
if (vs->mouse_mode_notifier.notify != NULL) {
@@ -2097,6 +2103,7 @@ static void send_ext_key_event_ack(VncState *vs)
vnc_flush(vs);
}
+#ifdef CONFIG_AUDIO
static void send_ext_audio_ack(VncState *vs)
{
vnc_lock_output(vs);
@@ -2110,6 +2117,7 @@ static void send_ext_audio_ack(VncState *vs)
vnc_unlock_output(vs);
vnc_flush(vs);
}
+#endif
static void send_xvp_message(VncState *vs, int code)
{
@@ -2197,10 +2205,15 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
send_ext_key_event_ack(vs);
break;
case VNC_ENCODING_AUDIO:
+#ifdef CONFIG_AUDIO
if (vs->vd->audio_be) {
vnc_set_feature(vs, VNC_FEATURE_AUDIO);
send_ext_audio_ack(vs);
}
+#else
+ VNC_DEBUG("Audio encoding received with audio subsystem "
+ "disabled\n");
+#endif
break;
case VNC_ENCODING_WMVi:
vnc_set_feature(vs, VNC_FEATURE_WMVI);
@@ -2394,7 +2407,9 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
{
int i;
uint16_t limit;
+#ifdef CONFIG_AUDIO
uint32_t freq;
+#endif
VncDisplay *vd = vs->vd;
if (data[0] > 3) {
@@ -2572,6 +2587,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
break;
}
+#ifdef CONFIG_AUDIO
if (len == 2)
return 4;
@@ -2626,6 +2642,9 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
break;
}
break;
+#else
+ abort();
+#endif
default:
VNC_DEBUG("Msg: %d\n", read_u16(data, 0));
@@ -3369,10 +3388,12 @@ static void vnc_connect(VncDisplay *vd, QIOChannelSocket *sioc,
vs->last_x = -1;
vs->last_y = -1;
+#ifdef CONFIG_AUDIO
vs->as.freq = 44100;
vs->as.nchannels = 2;
vs->as.fmt = AUDIO_FORMAT_S16;
vs->as.big_endian = false;
+#endif
qemu_mutex_init(&vs->output_mutex);
vs->bh = qemu_bh_new(vnc_jobs_bh, vs);
@@ -3649,9 +3670,11 @@ static QemuOptsList qemu_vnc_opts = {
},{
.name = "non-adaptive",
.type = QEMU_OPT_BOOL,
+#ifdef CONFIG_AUDIO
},{
.name = "audiodev",
.type = QEMU_OPT_STRING,
+#endif
},{
.name = "power-control",
.type = QEMU_OPT_BOOL,
@@ -4084,7 +4107,9 @@ void vnc_display_open(const char *id, Error **errp)
const char *saslauthz;
int lock_key_sync = 1;
int key_delay_ms;
+#ifdef CONFIG_AUDIO
const char *audiodev;
+#endif
const char *passwordSecret;
if (!vd) {
@@ -4242,6 +4267,7 @@ void vnc_display_open(const char *id, Error **errp)
}
vd->ledstate = 0;
+#ifdef CONFIG_AUDIO
audiodev = qemu_opt_get(opts, "audiodev");
if (audiodev) {
vd->audio_be = audio_be_by_name(audiodev, errp);
@@ -4251,6 +4277,7 @@ void vnc_display_open(const char *id, Error **errp)
} else {
vd->audio_be = audio_get_default_audio_be(NULL);
}
+#endif
device_id = qemu_opt_get(opts, "display");
if (device_id) {
--
2.34.1