mirror of https://github.com/xemu-project/xemu.git
pci: cleanup virtio ids.
audio: bugfixes and latency improvements. misc fixes for hw/display and ui -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmNHtYsACgkQTLbY7tPo cTjHhg//RDkHbqVSExe+Odw5ISuLu/EXZSHAVjo3KOCUvaj7O2cXi8N7DVfEy5a5 T3+WSv0v4X6TYSV0PoMb36a11rCuOKzeLZrtEOQeYfG3D1WCVc9gIWMt6omzBC7A YQ59P+u19qHD7xD2PP3WRtdcqmsceg1RG+47adX2EnsRZmmu/yJxD72w/Q1kXMuB jIzuJU2ZVorYX9y11hnIU3M5pvoX/vjFA+Ib2UGZZdlE3KlUKtJeAtLiZkHfoyd1 5janU+PtSU6Z1yVirE7RVz3+IBbfqqEFTkDtMXJucJW/Eod0NHCyo4Q6D64HoiZe +JZKkHmuvn8ZUgXMtIOZdH+aOHlaIJzA5SoA2IFxCBVuxn7p4NtPbCRoHHg7gkDh BDsq+p/wsdOY06u1txFw9dYy+4tKvWS7+Dxhyme7GT2YUQHrEEG3pzGFmk3PE0Vi tEAhmfNRxWzUgIcynQiN/3SnShAI8lANq0SEiiTvqcX7h1TK+cjEYjOTMsjK43nL 2W/pgQxJpEPcSs3jgFLnBLk9rUHRNRC+GtMBlwN+Wdc1y17leZHiIinqhHjXuts3 cJTdv4veeGuJENPIl2rk5JOdvpVtzduDkz+Rzx0mGb+LnAYdK2lBUV5LY9FfdwaK 2Bgg02ZYNBz7K2zzFeeV+7b7K/LYOuWkGdzGvKbpqjbefopZmTM= =6d/F -----END PGP SIGNATURE----- Merge tag 'kraxel-20221013-pull-request' of https://gitlab.com/kraxel/qemu into staging pci: cleanup virtio ids. audio: bugfixes and latency improvements. misc fixes for hw/display and ui # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmNHtYsACgkQTLbY7tPo # cTjHhg//RDkHbqVSExe+Odw5ISuLu/EXZSHAVjo3KOCUvaj7O2cXi8N7DVfEy5a5 # T3+WSv0v4X6TYSV0PoMb36a11rCuOKzeLZrtEOQeYfG3D1WCVc9gIWMt6omzBC7A # YQ59P+u19qHD7xD2PP3WRtdcqmsceg1RG+47adX2EnsRZmmu/yJxD72w/Q1kXMuB # jIzuJU2ZVorYX9y11hnIU3M5pvoX/vjFA+Ib2UGZZdlE3KlUKtJeAtLiZkHfoyd1 # 5janU+PtSU6Z1yVirE7RVz3+IBbfqqEFTkDtMXJucJW/Eod0NHCyo4Q6D64HoiZe # +JZKkHmuvn8ZUgXMtIOZdH+aOHlaIJzA5SoA2IFxCBVuxn7p4NtPbCRoHHg7gkDh # BDsq+p/wsdOY06u1txFw9dYy+4tKvWS7+Dxhyme7GT2YUQHrEEG3pzGFmk3PE0Vi # tEAhmfNRxWzUgIcynQiN/3SnShAI8lANq0SEiiTvqcX7h1TK+cjEYjOTMsjK43nL # 2W/pgQxJpEPcSs3jgFLnBLk9rUHRNRC+GtMBlwN+Wdc1y17leZHiIinqhHjXuts3 # cJTdv4veeGuJENPIl2rk5JOdvpVtzduDkz+Rzx0mGb+LnAYdK2lBUV5LY9FfdwaK # 2Bgg02ZYNBz7K2zzFeeV+7b7K/LYOuWkGdzGvKbpqjbefopZmTM= # =6d/F # -----END PGP SIGNATURE----- # gpg: Signature made Thu 13 Oct 2022 02:51:55 EDT # gpg: using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * tag 'kraxel-20221013-pull-request' of https://gitlab.com/kraxel/qemu: (26 commits) audio: improve out.voices test audio: fix in.voices test gtk: Add show_menubar=on|off command line option. qemu-edid: Restrict input parameter -d to avoid division by zero ui/gtk: Fix the implicit mouse ungrabbing logic pci-ids: document modern virtio-pci ids in pci.h too pci-ids: drop list of modern virtio devices pci-ids: drop PCI_DEVICE_ID_VIRTIO_PMEM pci-ids: drop PCI_DEVICE_ID_VIRTIO_MEM pci-ids: drop PCI_DEVICE_ID_VIRTIO_IOMMU docs: add firmware feature flags cirrus_vga: fix potential memory overflow ui/gtk-egl: egl context needs to be unbound in the end of gd_egl_switch ui/vnc-clipboard: fix integer underflow in vnc_client_cut_text_ext audio: prevent an integer overflow in resampling code audio: fix sw->buf size for audio recording audio: refactor audio_get_avail() audio: rename audio_sw_bytes_free() audio: swap audio_rate_get_bytes() function parameters spiceaudio: update comment ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
2ba341b369
|
@ -602,6 +602,42 @@ static int alsa_open(bool in, struct alsa_params_req *req,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t alsa_buffer_get_free(HWVoiceOut *hw)
|
||||||
|
{
|
||||||
|
ALSAVoiceOut *alsa = (ALSAVoiceOut *)hw;
|
||||||
|
snd_pcm_sframes_t avail;
|
||||||
|
size_t alsa_free, generic_free, generic_in_use;
|
||||||
|
|
||||||
|
avail = snd_pcm_avail_update(alsa->handle);
|
||||||
|
if (avail < 0) {
|
||||||
|
if (avail == -EPIPE) {
|
||||||
|
if (!alsa_recover(alsa->handle)) {
|
||||||
|
avail = snd_pcm_avail_update(alsa->handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (avail < 0) {
|
||||||
|
alsa_logerr(avail,
|
||||||
|
"Could not obtain number of available frames\n");
|
||||||
|
avail = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alsa_free = avail * hw->info.bytes_per_frame;
|
||||||
|
generic_free = audio_generic_buffer_get_free(hw);
|
||||||
|
generic_in_use = hw->samples * hw->info.bytes_per_frame - generic_free;
|
||||||
|
if (generic_in_use) {
|
||||||
|
/*
|
||||||
|
* This code can only be reached in the unlikely case that
|
||||||
|
* snd_pcm_avail_update() returned a larger number of frames
|
||||||
|
* than snd_pcm_writei() could write. Make sure that all
|
||||||
|
* remaining bytes in the generic buffer can be written.
|
||||||
|
*/
|
||||||
|
alsa_free = alsa_free > generic_in_use ? alsa_free - generic_in_use : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return alsa_free;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
|
static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
|
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
|
||||||
|
@ -916,7 +952,7 @@ static struct audio_pcm_ops alsa_pcm_ops = {
|
||||||
.init_out = alsa_init_out,
|
.init_out = alsa_init_out,
|
||||||
.fini_out = alsa_fini_out,
|
.fini_out = alsa_fini_out,
|
||||||
.write = alsa_write,
|
.write = alsa_write,
|
||||||
.buffer_get_free = audio_generic_buffer_get_free,
|
.buffer_get_free = alsa_buffer_get_free,
|
||||||
.run_buffer_out = audio_generic_run_buffer_out,
|
.run_buffer_out = audio_generic_run_buffer_out,
|
||||||
.enable_out = alsa_enable_out,
|
.enable_out = alsa_enable_out,
|
||||||
|
|
||||||
|
|
111
audio/audio.c
111
audio/audio.c
|
@ -986,6 +986,18 @@ void AUD_set_active_in (SWVoiceIn *sw, int on)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* audio_frontend_frames_in() - returns the number of frames the resampling
|
||||||
|
* code generates from frames_in frames
|
||||||
|
*
|
||||||
|
* @sw: audio recording frontend
|
||||||
|
* @frames_in: number of frames
|
||||||
|
*/
|
||||||
|
static size_t audio_frontend_frames_in(SWVoiceIn *sw, size_t frames_in)
|
||||||
|
{
|
||||||
|
return (int64_t)frames_in * sw->ratio >> 32;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t audio_get_avail (SWVoiceIn *sw)
|
static size_t audio_get_avail (SWVoiceIn *sw)
|
||||||
{
|
{
|
||||||
size_t live;
|
size_t live;
|
||||||
|
@ -1002,17 +1014,24 @@ static size_t audio_get_avail (SWVoiceIn *sw)
|
||||||
}
|
}
|
||||||
|
|
||||||
ldebug (
|
ldebug (
|
||||||
"%s: get_avail live %zu ret %" PRId64 "\n",
|
"%s: get_avail live %zu frontend frames %zu\n",
|
||||||
SW_NAME (sw),
|
SW_NAME (sw),
|
||||||
live, (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame
|
live, audio_frontend_frames_in(sw, live)
|
||||||
);
|
);
|
||||||
|
|
||||||
return (((int64_t) live << 32) / sw->ratio) * sw->info.bytes_per_frame;
|
return live;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t audio_sw_bytes_free(SWVoiceOut *sw, size_t free)
|
/**
|
||||||
|
* audio_frontend_frames_out() - returns the number of frames needed to
|
||||||
|
* get frames_out frames after resampling
|
||||||
|
*
|
||||||
|
* @sw: audio playback frontend
|
||||||
|
* @frames_out: number of frames
|
||||||
|
*/
|
||||||
|
static size_t audio_frontend_frames_out(SWVoiceOut *sw, size_t frames_out)
|
||||||
{
|
{
|
||||||
return (((int64_t)free << 32) / sw->ratio) * sw->info.bytes_per_frame;
|
return ((int64_t)frames_out << 32) / sw->ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t audio_get_free(SWVoiceOut *sw)
|
static size_t audio_get_free(SWVoiceOut *sw)
|
||||||
|
@ -1034,8 +1053,8 @@ static size_t audio_get_free(SWVoiceOut *sw)
|
||||||
dead = sw->hw->mix_buf->size - live;
|
dead = sw->hw->mix_buf->size - live;
|
||||||
|
|
||||||
#ifdef DEBUG_OUT
|
#ifdef DEBUG_OUT
|
||||||
dolog("%s: get_free live %zu dead %zu sw_bytes %zu\n",
|
dolog("%s: get_free live %zu dead %zu frontend frames %zu\n",
|
||||||
SW_NAME(sw), live, dead, audio_sw_bytes_free(sw, dead));
|
SW_NAME(sw), live, dead, audio_frontend_frames_out(sw, dead));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return dead;
|
return dead;
|
||||||
|
@ -1121,8 +1140,12 @@ static void audio_run_out (AudioState *s)
|
||||||
HWVoiceOut *hw = NULL;
|
HWVoiceOut *hw = NULL;
|
||||||
SWVoiceOut *sw;
|
SWVoiceOut *sw;
|
||||||
|
|
||||||
if (!audio_get_pdo_out(s->dev)->mixing_engine) {
|
while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
|
||||||
while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
|
size_t played, live, prev_rpos;
|
||||||
|
size_t hw_free = audio_pcm_hw_get_free(hw);
|
||||||
|
int nb_live;
|
||||||
|
|
||||||
|
if (!audio_get_pdo_out(s->dev)->mixing_engine) {
|
||||||
/* there is exactly 1 sw for each hw with no mixeng */
|
/* there is exactly 1 sw for each hw with no mixeng */
|
||||||
sw = hw->sw_head.lh_first;
|
sw = hw->sw_head.lh_first;
|
||||||
|
|
||||||
|
@ -1135,16 +1158,16 @@ static void audio_run_out (AudioState *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sw->active) {
|
if (sw->active) {
|
||||||
sw->callback.fn(sw->callback.opaque, INT_MAX);
|
sw->callback.fn(sw->callback.opaque,
|
||||||
|
hw_free * sw->info.bytes_per_frame);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
|
if (hw->pcm_ops->run_buffer_out) {
|
||||||
size_t played, live, prev_rpos;
|
hw->pcm_ops->run_buffer_out(hw);
|
||||||
size_t hw_free = audio_pcm_hw_get_free(hw);
|
}
|
||||||
int nb_live;
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
|
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
|
||||||
if (sw->active) {
|
if (sw->active) {
|
||||||
|
@ -1152,13 +1175,14 @@ static void audio_run_out (AudioState *s)
|
||||||
size_t free;
|
size_t free;
|
||||||
|
|
||||||
if (hw_free > sw->total_hw_samples_mixed) {
|
if (hw_free > sw->total_hw_samples_mixed) {
|
||||||
free = audio_sw_bytes_free(sw,
|
free = audio_frontend_frames_out(sw,
|
||||||
MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
|
MIN(sw_free, hw_free - sw->total_hw_samples_mixed));
|
||||||
} else {
|
} else {
|
||||||
free = 0;
|
free = 0;
|
||||||
}
|
}
|
||||||
if (free > 0) {
|
if (free > 0) {
|
||||||
sw->callback.fn(sw->callback.opaque, free);
|
sw->callback.fn(sw->callback.opaque,
|
||||||
|
free * sw->info.bytes_per_frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1297,11 +1321,13 @@ static void audio_run_in (AudioState *s)
|
||||||
sw->total_hw_samples_acquired -= min;
|
sw->total_hw_samples_acquired -= min;
|
||||||
|
|
||||||
if (sw->active) {
|
if (sw->active) {
|
||||||
|
size_t sw_avail = audio_get_avail(sw);
|
||||||
size_t avail;
|
size_t avail;
|
||||||
|
|
||||||
avail = audio_get_avail (sw);
|
avail = audio_frontend_frames_in(sw, sw_avail);
|
||||||
if (avail > 0) {
|
if (avail > 0) {
|
||||||
sw->callback.fn (sw->callback.opaque, avail);
|
sw->callback.fn(sw->callback.opaque,
|
||||||
|
avail * sw->info.bytes_per_frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1501,10 +1527,6 @@ size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hw->pcm_ops->run_buffer_out) {
|
|
||||||
hw->pcm_ops->run_buffer_out(hw);
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1750,13 +1772,13 @@ static AudioState *audio_init(Audiodev *dev, const char *name)
|
||||||
s->nb_hw_voices_out = audio_get_pdo_out(dev)->voices;
|
s->nb_hw_voices_out = audio_get_pdo_out(dev)->voices;
|
||||||
s->nb_hw_voices_in = audio_get_pdo_in(dev)->voices;
|
s->nb_hw_voices_in = audio_get_pdo_in(dev)->voices;
|
||||||
|
|
||||||
if (s->nb_hw_voices_out <= 0) {
|
if (s->nb_hw_voices_out < 1) {
|
||||||
dolog ("Bogus number of playback voices %d, setting to 1\n",
|
dolog ("Bogus number of playback voices %d, setting to 1\n",
|
||||||
s->nb_hw_voices_out);
|
s->nb_hw_voices_out);
|
||||||
s->nb_hw_voices_out = 1;
|
s->nb_hw_voices_out = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->nb_hw_voices_in <= 0) {
|
if (s->nb_hw_voices_in < 0) {
|
||||||
dolog ("Bogus number of capture voices %d, setting to 0\n",
|
dolog ("Bogus number of capture voices %d, setting to 0\n",
|
||||||
s->nb_hw_voices_in);
|
s->nb_hw_voices_in);
|
||||||
s->nb_hw_voices_in = 0;
|
s->nb_hw_voices_in = 0;
|
||||||
|
@ -2251,26 +2273,39 @@ void audio_rate_start(RateCtl *rate)
|
||||||
rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
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 audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info)
|
||||||
size_t bytes_avail)
|
|
||||||
{
|
{
|
||||||
int64_t now;
|
int64_t now;
|
||||||
int64_t ticks;
|
int64_t ticks;
|
||||||
int64_t bytes;
|
int64_t bytes;
|
||||||
int64_t samples;
|
int64_t frames;
|
||||||
size_t ret;
|
|
||||||
|
|
||||||
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
ticks = now - rate->start_ticks;
|
ticks = now - rate->start_ticks;
|
||||||
bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
|
bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
|
||||||
samples = (bytes - rate->bytes_sent) / info->bytes_per_frame;
|
frames = (bytes - rate->bytes_sent) / info->bytes_per_frame;
|
||||||
if (samples < 0 || samples > 65536) {
|
if (frames < 0 || frames > 65536) {
|
||||||
AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)\n", samples);
|
AUD_log(NULL, "Resetting rate control (%" PRId64 " frames)\n", frames);
|
||||||
audio_rate_start(rate);
|
audio_rate_start(rate);
|
||||||
samples = 0;
|
frames = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = MIN(samples * info->bytes_per_frame, bytes_avail);
|
return frames * info->bytes_per_frame;
|
||||||
rate->bytes_sent += ret;
|
}
|
||||||
return ret;
|
|
||||||
|
void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used)
|
||||||
|
{
|
||||||
|
rate->bytes_sent += bytes_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info,
|
||||||
|
size_t bytes_avail)
|
||||||
|
{
|
||||||
|
size_t bytes;
|
||||||
|
|
||||||
|
bytes = audio_rate_peek_bytes(rate, info);
|
||||||
|
bytes = MIN(bytes, bytes_avail);
|
||||||
|
audio_rate_add_bytes(rate, bytes);
|
||||||
|
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,7 +263,9 @@ typedef struct RateCtl {
|
||||||
} RateCtl;
|
} RateCtl;
|
||||||
|
|
||||||
void audio_rate_start(RateCtl *rate);
|
void audio_rate_start(RateCtl *rate);
|
||||||
size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
|
size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info);
|
||||||
|
void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used);
|
||||||
|
size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info,
|
||||||
size_t bytes_avail);
|
size_t bytes_avail);
|
||||||
|
|
||||||
static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len)
|
static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len)
|
||||||
|
|
|
@ -110,7 +110,11 @@ static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DAC
|
||||||
samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;
|
samples = ((int64_t) sw->HWBUF->size << 32) / sw->ratio;
|
||||||
|
#else
|
||||||
|
samples = (int64_t)sw->HWBUF->size * sw->ratio >> 32;
|
||||||
|
#endif
|
||||||
|
|
||||||
sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
|
sw->buf = audio_calloc(__func__, samples, sizeof(struct st_sample));
|
||||||
if (!sw->buf) {
|
if (!sw->buf) {
|
||||||
|
|
|
@ -82,7 +82,7 @@ static void *dbus_get_buffer_out(HWVoiceOut *hw, size_t *size)
|
||||||
}
|
}
|
||||||
|
|
||||||
*size = MIN(vo->buf_size - vo->buf_pos, *size);
|
*size = MIN(vo->buf_size - vo->buf_pos, *size);
|
||||||
*size = audio_rate_get_bytes(&hw->info, &vo->rate, *size);
|
*size = audio_rate_get_bytes(&vo->rate, &hw->info, *size);
|
||||||
|
|
||||||
return vo->buf + vo->buf_pos;
|
return vo->buf + vo->buf_pos;
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ dbus_read(HWVoiceIn *hw, void *buf, size_t size)
|
||||||
|
|
||||||
trace_dbus_audio_read(size);
|
trace_dbus_audio_read(size);
|
||||||
|
|
||||||
/* size = audio_rate_get_bytes(&hw->info, &vo->rate, size); */
|
/* size = audio_rate_get_bytes(&vo->rate, &hw->info, size); */
|
||||||
|
|
||||||
g_hash_table_iter_init(&iter, da->in_listeners);
|
g_hash_table_iter_init(&iter, da->in_listeners);
|
||||||
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) {
|
||||||
|
|
|
@ -44,7 +44,7 @@ typedef struct NoVoiceIn {
|
||||||
static size_t no_write(HWVoiceOut *hw, void *buf, size_t len)
|
static size_t no_write(HWVoiceOut *hw, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
NoVoiceOut *no = (NoVoiceOut *) hw;
|
NoVoiceOut *no = (NoVoiceOut *) hw;
|
||||||
return audio_rate_get_bytes(&hw->info, &no->rate, len);
|
return audio_rate_get_bytes(&no->rate, &hw->info, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
|
static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
|
||||||
|
@ -89,7 +89,7 @@ static void no_fini_in (HWVoiceIn *hw)
|
||||||
static size_t no_read(HWVoiceIn *hw, void *buf, size_t size)
|
static size_t no_read(HWVoiceIn *hw, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
NoVoiceIn *no = (NoVoiceIn *) hw;
|
NoVoiceIn *no = (NoVoiceIn *) hw;
|
||||||
int64_t bytes = audio_rate_get_bytes(&hw->info, &no->rate, size);
|
int64_t bytes = audio_rate_get_bytes(&no->rate, &hw->info, size);
|
||||||
|
|
||||||
audio_pcm_info_clear_buf(&hw->info, buf, bytes / hw->info.bytes_per_frame);
|
audio_pcm_info_clear_buf(&hw->info, buf, bytes / hw->info.bytes_per_frame);
|
||||||
return bytes;
|
return bytes;
|
||||||
|
|
|
@ -72,11 +72,6 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
|
||||||
ilast = *ibuf++;
|
ilast = *ibuf++;
|
||||||
rate->ipos++;
|
rate->ipos++;
|
||||||
|
|
||||||
/* if ipos overflow, there is a infinite loop */
|
|
||||||
if (rate->ipos == 0xffffffff) {
|
|
||||||
rate->ipos = 1;
|
|
||||||
rate->opos = rate->opos & 0xffffffff;
|
|
||||||
}
|
|
||||||
/* See if we finished the input buffer yet */
|
/* See if we finished the input buffer yet */
|
||||||
if (ibuf >= iend) {
|
if (ibuf >= iend) {
|
||||||
goto the_end;
|
goto the_end;
|
||||||
|
@ -85,6 +80,12 @@ void NAME (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
|
||||||
|
|
||||||
icur = *ibuf;
|
icur = *ibuf;
|
||||||
|
|
||||||
|
/* wrap ipos and opos around long before they overflow */
|
||||||
|
if (rate->ipos >= 0x10001) {
|
||||||
|
rate->ipos = 1;
|
||||||
|
rate->opos &= 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
/* interpolate */
|
/* interpolate */
|
||||||
#ifdef FLOAT_MIXENG
|
#ifdef FLOAT_MIXENG
|
||||||
#ifdef RECIPROCAL
|
#ifdef RECIPROCAL
|
||||||
|
|
|
@ -120,6 +120,13 @@ static void line_out_fini (HWVoiceOut *hw)
|
||||||
spice_server_remove_interface (&out->sin.base);
|
spice_server_remove_interface (&out->sin.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t line_out_get_free(HWVoiceOut *hw)
|
||||||
|
{
|
||||||
|
SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||||
|
|
||||||
|
return audio_rate_peek_bytes(&out->rate, &hw->info);
|
||||||
|
}
|
||||||
|
|
||||||
static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size)
|
static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size)
|
||||||
{
|
{
|
||||||
SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||||
|
@ -133,8 +140,6 @@ static void *line_out_get_buffer(HWVoiceOut *hw, size_t *size)
|
||||||
*size = MIN((out->fsize - out->fpos) << 2, *size);
|
*size = MIN((out->fsize - out->fpos) << 2, *size);
|
||||||
}
|
}
|
||||||
|
|
||||||
*size = audio_rate_get_bytes(&hw->info, &out->rate, *size);
|
|
||||||
|
|
||||||
return out->frame + out->fpos;
|
return out->frame + out->fpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +147,8 @@ static size_t line_out_put_buffer(HWVoiceOut *hw, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
SpiceVoiceOut *out = container_of(hw, SpiceVoiceOut, hw);
|
||||||
|
|
||||||
|
audio_rate_add_bytes(&out->rate, size);
|
||||||
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
assert(buf == out->frame + out->fpos && out->fpos <= out->fsize);
|
assert(buf == out->frame + out->fpos && out->fpos <= out->fsize);
|
||||||
out->fpos += size >> 2;
|
out->fpos += size >> 2;
|
||||||
|
@ -232,10 +239,13 @@ static void line_in_fini (HWVoiceIn *hw)
|
||||||
static size_t line_in_read(HWVoiceIn *hw, void *buf, size_t len)
|
static size_t line_in_read(HWVoiceIn *hw, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw);
|
SpiceVoiceIn *in = container_of (hw, SpiceVoiceIn, hw);
|
||||||
uint64_t to_read = audio_rate_get_bytes(&hw->info, &in->rate, len) >> 2;
|
uint64_t to_read = audio_rate_get_bytes(&in->rate, &hw->info, len) >> 2;
|
||||||
size_t ready = spice_server_record_get_samples(&in->sin, buf, to_read);
|
size_t ready = spice_server_record_get_samples(&in->sin, buf, to_read);
|
||||||
|
|
||||||
/* XXX: do we need this? */
|
/*
|
||||||
|
* If the client didn't send new frames, it most likely disconnected.
|
||||||
|
* Generate silence in this case to avoid a stalled audio stream.
|
||||||
|
*/
|
||||||
if (ready == 0) {
|
if (ready == 0) {
|
||||||
memset(buf, 0, to_read << 2);
|
memset(buf, 0, to_read << 2);
|
||||||
ready = to_read;
|
ready = to_read;
|
||||||
|
@ -282,6 +292,7 @@ static struct audio_pcm_ops audio_callbacks = {
|
||||||
.init_out = line_out_init,
|
.init_out = line_out_init,
|
||||||
.fini_out = line_out_fini,
|
.fini_out = line_out_fini,
|
||||||
.write = audio_generic_write,
|
.write = audio_generic_write,
|
||||||
|
.buffer_get_free = line_out_get_free,
|
||||||
.get_buffer_out = line_out_get_buffer,
|
.get_buffer_out = line_out_get_buffer,
|
||||||
.put_buffer_out = line_out_put_buffer,
|
.put_buffer_out = line_out_put_buffer,
|
||||||
.enable_out = line_out_enable,
|
.enable_out = line_out_enable,
|
||||||
|
|
|
@ -42,7 +42,7 @@ typedef struct WAVVoiceOut {
|
||||||
static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len)
|
static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len)
|
||||||
{
|
{
|
||||||
WAVVoiceOut *wav = (WAVVoiceOut *) hw;
|
WAVVoiceOut *wav = (WAVVoiceOut *) hw;
|
||||||
int64_t bytes = audio_rate_get_bytes(&hw->info, &wav->rate, len);
|
int64_t bytes = audio_rate_get_bytes(&wav->rate, &hw->info, len);
|
||||||
assert(bytes % hw->info.bytes_per_frame == 0);
|
assert(bytes % hw->info.bytes_per_frame == 0);
|
||||||
|
|
||||||
if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) {
|
if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) {
|
||||||
|
|
|
@ -113,13 +113,22 @@
|
||||||
# Virtualization, as specified in the AMD64 Architecture
|
# Virtualization, as specified in the AMD64 Architecture
|
||||||
# Programmer's Manual. QEMU command line options related to
|
# Programmer's Manual. QEMU command line options related to
|
||||||
# this feature are documented in
|
# this feature are documented in
|
||||||
# "docs/amd-memory-encryption.txt".
|
# "docs/system/i386/amd-memory-encryption.rst".
|
||||||
#
|
#
|
||||||
# @amd-sev-es: The firmware supports running under AMD Secure Encrypted
|
# @amd-sev-es: The firmware supports running under AMD Secure Encrypted
|
||||||
# Virtualization - Encrypted State, as specified in the AMD64
|
# Virtualization - Encrypted State, as specified in the AMD64
|
||||||
# Architecture Programmer's Manual. QEMU command line options
|
# Architecture Programmer's Manual. QEMU command line options
|
||||||
# related to this feature are documented in
|
# related to this feature are documented in
|
||||||
# "docs/amd-memory-encryption.txt".
|
# "docs/system/i386/amd-memory-encryption.rst".
|
||||||
|
#
|
||||||
|
# @amd-sev-snp: The firmware supports running under AMD Secure Encrypted
|
||||||
|
# Virtualization - Secure Nested Paging, as specified in the
|
||||||
|
# AMD64 Architecture Programmer's Manual. QEMU command line
|
||||||
|
# options related to this feature are documented in
|
||||||
|
# "docs/system/i386/amd-memory-encryption.rst".
|
||||||
|
#
|
||||||
|
# @intel-tdx: The firmware supports running under Intel Trust Domain
|
||||||
|
# Extensions (TDX).
|
||||||
#
|
#
|
||||||
# @enrolled-keys: The variable store (NVRAM) template associated with
|
# @enrolled-keys: The variable store (NVRAM) template associated with
|
||||||
# the firmware binary has the UEFI Secure Boot
|
# the firmware binary has the UEFI Secure Boot
|
||||||
|
@ -185,9 +194,11 @@
|
||||||
# Since: 3.0
|
# Since: 3.0
|
||||||
##
|
##
|
||||||
{ 'enum' : 'FirmwareFeature',
|
{ 'enum' : 'FirmwareFeature',
|
||||||
'data' : [ 'acpi-s3', 'acpi-s4', 'amd-sev', 'amd-sev-es', 'enrolled-keys',
|
'data' : [ 'acpi-s3', 'acpi-s4',
|
||||||
'requires-smm', 'secure-boot', 'verbose-dynamic',
|
'amd-sev', 'amd-sev-es', 'amd-sev-snp',
|
||||||
'verbose-static' ] }
|
'intel-tdx',
|
||||||
|
'enrolled-keys', 'requires-smm', 'secure-boot',
|
||||||
|
'verbose-dynamic', 'verbose-static' ] }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @FirmwareFlashFile:
|
# @FirmwareFlashFile:
|
||||||
|
|
|
@ -22,16 +22,14 @@ maintained as part of the virtio specification.
|
||||||
1af4:1004 SCSI host bus adapter device (legacy)
|
1af4:1004 SCSI host bus adapter device (legacy)
|
||||||
1af4:1005 entropy generator device (legacy)
|
1af4:1005 entropy generator device (legacy)
|
||||||
1af4:1009 9p filesystem device (legacy)
|
1af4:1009 9p filesystem device (legacy)
|
||||||
|
1af4:1012 vsock device (bug compatibility)
|
||||||
|
|
||||||
1af4:1041 network device (modern)
|
1af4:1040 Start of ID range for modern virtio devices. The PCI device
|
||||||
1af4:1042 block device (modern)
|
to ID is calculated from the virtio device ID by adding the
|
||||||
1af4:1043 console device (modern)
|
1af4:10ef 0x1040 offset. The virtio IDs are defined in the virtio
|
||||||
1af4:1044 entropy generator device (modern)
|
specification. The Linux kernel has a header file with
|
||||||
1af4:1045 balloon device (modern)
|
defines for all virtio IDs (linux/virtio_ids.h), qemu has a
|
||||||
1af4:1048 SCSI host bus adapter device (modern)
|
copy in include/standard-headers/.
|
||||||
1af4:1049 9p filesystem device (modern)
|
|
||||||
1af4:1050 virtio gpu device (modern)
|
|
||||||
1af4:1052 virtio input device (modern)
|
|
||||||
|
|
||||||
1af4:10f0 Available for experimental usage without registration. Must get
|
1af4:10f0 Available for experimental usage without registration. Must get
|
||||||
to official ID when the code leaves the test lab (i.e. when seeking
|
to official ID when the code leaves the test lab (i.e. when seeking
|
||||||
|
|
|
@ -834,7 +834,7 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
|
||||||
word alignment, so we keep them for the next line */
|
word alignment, so we keep them for the next line */
|
||||||
/* XXX: keep alignment to speed up transfer */
|
/* XXX: keep alignment to speed up transfer */
|
||||||
end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
|
end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
|
||||||
copy_count = s->cirrus_srcptr_end - end_ptr;
|
copy_count = MIN(s->cirrus_srcptr_end - end_ptr, CIRRUS_BLTBUFSIZE);
|
||||||
memmove(s->cirrus_bltbuf, end_ptr, copy_count);
|
memmove(s->cirrus_bltbuf, end_ptr, copy_count);
|
||||||
s->cirrus_srcptr = s->cirrus_bltbuf + copy_count;
|
s->cirrus_srcptr = s->cirrus_bltbuf + copy_count;
|
||||||
s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
|
s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
|
||||||
|
|
|
@ -74,8 +74,6 @@ static void virtio_iommu_pci_class_init(ObjectClass *klass, void *data)
|
||||||
k->realize = virtio_iommu_pci_realize;
|
k->realize = virtio_iommu_pci_realize;
|
||||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||||
device_class_set_props(dc, virtio_iommu_pci_properties);
|
device_class_set_props(dc, virtio_iommu_pci_properties);
|
||||||
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
|
|
||||||
pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_IOMMU;
|
|
||||||
pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
|
pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
|
||||||
pcidev_k->class_id = PCI_CLASS_OTHERS;
|
pcidev_k->class_id = PCI_CLASS_OTHERS;
|
||||||
dc->hotpluggable = false;
|
dc->hotpluggable = false;
|
||||||
|
@ -90,7 +88,7 @@ static void virtio_iommu_pci_instance_init(Object *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VirtioPCIDeviceTypeInfo virtio_iommu_pci_info = {
|
static const VirtioPCIDeviceTypeInfo virtio_iommu_pci_info = {
|
||||||
.generic_name = TYPE_VIRTIO_IOMMU_PCI,
|
.generic_name = TYPE_VIRTIO_IOMMU_PCI,
|
||||||
.instance_size = sizeof(VirtIOIOMMUPCI),
|
.instance_size = sizeof(VirtIOIOMMUPCI),
|
||||||
.instance_init = virtio_iommu_pci_instance_init,
|
.instance_init = virtio_iommu_pci_instance_init,
|
||||||
.class_init = virtio_iommu_pci_class_init,
|
.class_init = virtio_iommu_pci_class_init,
|
||||||
|
|
|
@ -104,8 +104,6 @@ static void virtio_mem_pci_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
||||||
k->realize = virtio_mem_pci_realize;
|
k->realize = virtio_mem_pci_realize;
|
||||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||||
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
|
|
||||||
pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_MEM;
|
|
||||||
pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
|
pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
|
||||||
pcidev_k->class_id = PCI_CLASS_OTHERS;
|
pcidev_k->class_id = PCI_CLASS_OTHERS;
|
||||||
|
|
||||||
|
|
|
@ -1688,7 +1688,7 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
|
||||||
pci_set_word(config + PCI_VENDOR_ID,
|
pci_set_word(config + PCI_VENDOR_ID,
|
||||||
PCI_VENDOR_ID_REDHAT_QUMRANET);
|
PCI_VENDOR_ID_REDHAT_QUMRANET);
|
||||||
pci_set_word(config + PCI_DEVICE_ID,
|
pci_set_word(config + PCI_DEVICE_ID,
|
||||||
0x1040 + virtio_bus_get_vdev_id(bus));
|
PCI_DEVICE_ID_VIRTIO_10_BASE + virtio_bus_get_vdev_id(bus));
|
||||||
pci_config_set_revision(config, 1);
|
pci_config_set_revision(config, 1);
|
||||||
}
|
}
|
||||||
config[PCI_INTERRUPT_PIN] = 1;
|
config[PCI_INTERRUPT_PIN] = 1;
|
||||||
|
|
|
@ -90,8 +90,6 @@ static void virtio_pmem_pci_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
||||||
k->realize = virtio_pmem_pci_realize;
|
k->realize = virtio_pmem_pci_realize;
|
||||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||||
pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
|
|
||||||
pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_PMEM;
|
|
||||||
pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
|
pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
|
||||||
pcidev_k->class_id = PCI_CLASS_OTHERS;
|
pcidev_k->class_id = PCI_CLASS_OTHERS;
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ extern bool pci_available;
|
||||||
#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4
|
#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4
|
||||||
#define PCI_SUBDEVICE_ID_QEMU 0x1100
|
#define PCI_SUBDEVICE_ID_QEMU 0x1100
|
||||||
|
|
||||||
|
/* legacy virtio-pci devices */
|
||||||
#define PCI_DEVICE_ID_VIRTIO_NET 0x1000
|
#define PCI_DEVICE_ID_VIRTIO_NET 0x1000
|
||||||
#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001
|
#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001
|
||||||
#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
|
#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002
|
||||||
|
@ -84,9 +85,15 @@ extern bool pci_available;
|
||||||
#define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
|
#define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
|
||||||
#define PCI_DEVICE_ID_VIRTIO_9P 0x1009
|
#define PCI_DEVICE_ID_VIRTIO_9P 0x1009
|
||||||
#define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012
|
#define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012
|
||||||
#define PCI_DEVICE_ID_VIRTIO_PMEM 0x1013
|
|
||||||
#define PCI_DEVICE_ID_VIRTIO_IOMMU 0x1014
|
/*
|
||||||
#define PCI_DEVICE_ID_VIRTIO_MEM 0x1015
|
* modern virtio-pci devices get their id assigned automatically,
|
||||||
|
* there is no need to add #defines here. It gets calculated as
|
||||||
|
*
|
||||||
|
* PCI_DEVICE_ID = PCI_DEVICE_ID_VIRTIO_10_BASE +
|
||||||
|
* virtio_bus_get_vdev_id(bus)
|
||||||
|
*/
|
||||||
|
#define PCI_DEVICE_ID_VIRTIO_10_BASE 0x1040
|
||||||
|
|
||||||
#define PCI_VENDOR_ID_REDHAT 0x1b36
|
#define PCI_VENDOR_ID_REDHAT 0x1b36
|
||||||
#define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001
|
#define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001
|
||||||
|
|
|
@ -1199,13 +1199,16 @@
|
||||||
# interfaces (e.g. VGA and virtual console character devices)
|
# interfaces (e.g. VGA and virtual console character devices)
|
||||||
# by default.
|
# by default.
|
||||||
# Since 7.1
|
# Since 7.1
|
||||||
|
# @show-menubar: Display the main window menubar. Defaults to "on".
|
||||||
|
# Since 8.0
|
||||||
#
|
#
|
||||||
# Since: 2.12
|
# Since: 2.12
|
||||||
##
|
##
|
||||||
{ 'struct' : 'DisplayGTK',
|
{ 'struct' : 'DisplayGTK',
|
||||||
'data' : { '*grab-on-hover' : 'bool',
|
'data' : { '*grab-on-hover' : 'bool',
|
||||||
'*zoom-to-fit' : 'bool',
|
'*zoom-to-fit' : 'bool',
|
||||||
'*show-tabs' : 'bool' } }
|
'*show-tabs' : 'bool',
|
||||||
|
'*show-menubar' : 'bool' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @DisplayEGLHeadless:
|
# @DisplayEGLHeadless:
|
||||||
|
|
|
@ -92,6 +92,10 @@ int main(int argc, char *argv[])
|
||||||
fprintf(stderr, "not a number: %s\n", optarg);
|
fprintf(stderr, "not a number: %s\n", optarg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
if (dpi == 0) {
|
||||||
|
fprintf(stderr, "cannot be zero: %s\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
info.vendor = optarg;
|
info.vendor = optarg;
|
||||||
|
|
|
@ -1980,6 +1980,7 @@ DEF("display", HAS_ARG, QEMU_OPTION_display,
|
||||||
#if defined(CONFIG_GTK)
|
#if defined(CONFIG_GTK)
|
||||||
"-display gtk[,full-screen=on|off][,gl=on|off][,grab-on-hover=on|off]\n"
|
"-display gtk[,full-screen=on|off][,gl=on|off][,grab-on-hover=on|off]\n"
|
||||||
" [,show-tabs=on|off][,show-cursor=on|off][,window-close=on|off]\n"
|
" [,show-tabs=on|off][,show-cursor=on|off][,window-close=on|off]\n"
|
||||||
|
" [,show-menubar=on|off]\n"
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_VNC)
|
#if defined(CONFIG_VNC)
|
||||||
"-display vnc=<display>[,<optargs>]\n"
|
"-display vnc=<display>[,<optargs>]\n"
|
||||||
|
@ -2072,6 +2073,8 @@ SRST
|
||||||
|
|
||||||
``window-close=on|off`` : Allow to quit qemu with window close button
|
``window-close=on|off`` : Allow to quit qemu with window close button
|
||||||
|
|
||||||
|
``show-menubar=on|off`` : Display the main window menubar, defaults to "on"
|
||||||
|
|
||||||
``curses[,charset=<encoding>]``
|
``curses[,charset=<encoding>]``
|
||||||
Display video output via curses. For graphics device models
|
Display video output via curses. For graphics device models
|
||||||
which support a text mode, QEMU can display this output using a
|
which support a text mode, QEMU can display this output using a
|
||||||
|
|
|
@ -195,6 +195,9 @@ void gd_egl_switch(DisplayChangeListener *dcl,
|
||||||
if (resized) {
|
if (resized) {
|
||||||
gd_update_windowsize(vc);
|
gd_update_windowsize(vc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||||
|
EGL_NO_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc,
|
QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc,
|
||||||
|
|
25
ui/gtk.c
25
ui/gtk.c
|
@ -681,9 +681,13 @@ static void gd_mouse_mode_change(Notifier *notify, void *data)
|
||||||
|
|
||||||
s = container_of(notify, GtkDisplayState, mouse_mode_notifier);
|
s = container_of(notify, GtkDisplayState, mouse_mode_notifier);
|
||||||
/* release the grab at switching to absolute mode */
|
/* release the grab at switching to absolute mode */
|
||||||
if (qemu_input_is_absolute() && gd_is_grab_active(s)) {
|
if (qemu_input_is_absolute() && s->ptr_owner) {
|
||||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
|
if (!s->ptr_owner->window) {
|
||||||
FALSE);
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->grab_item),
|
||||||
|
FALSE);
|
||||||
|
} else {
|
||||||
|
gd_ungrab_pointer(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < s->nb_vcs; i++) {
|
for (i = 0; i < s->nb_vcs; i++) {
|
||||||
VirtualConsole *vc = &s->vc[i];
|
VirtualConsole *vc = &s->vc[i];
|
||||||
|
@ -2167,7 +2171,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkWidget *gd_create_menu_view(GtkDisplayState *s)
|
static GtkWidget *gd_create_menu_view(GtkDisplayState *s, DisplayOptions *opts)
|
||||||
{
|
{
|
||||||
GSList *group = NULL;
|
GSList *group = NULL;
|
||||||
GtkWidget *view_menu;
|
GtkWidget *view_menu;
|
||||||
|
@ -2265,7 +2269,8 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s)
|
||||||
s->show_menubar_item = gtk_check_menu_item_new_with_mnemonic(
|
s->show_menubar_item = gtk_check_menu_item_new_with_mnemonic(
|
||||||
_("Show Menubar"));
|
_("Show Menubar"));
|
||||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->show_menubar_item),
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(s->show_menubar_item),
|
||||||
TRUE);
|
!opts->u.gtk.has_show_menubar ||
|
||||||
|
opts->u.gtk.show_menubar);
|
||||||
gtk_accel_group_connect(s->accel_group, GDK_KEY_m, HOTKEY_MODIFIERS, 0,
|
gtk_accel_group_connect(s->accel_group, GDK_KEY_m, HOTKEY_MODIFIERS, 0,
|
||||||
g_cclosure_new_swap(G_CALLBACK(gd_accel_show_menubar), s, NULL));
|
g_cclosure_new_swap(G_CALLBACK(gd_accel_show_menubar), s, NULL));
|
||||||
gtk_accel_label_set_accel(
|
gtk_accel_label_set_accel(
|
||||||
|
@ -2276,13 +2281,13 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s)
|
||||||
return view_menu;
|
return view_menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gd_create_menus(GtkDisplayState *s)
|
static void gd_create_menus(GtkDisplayState *s, DisplayOptions *opts)
|
||||||
{
|
{
|
||||||
GtkSettings *settings;
|
GtkSettings *settings;
|
||||||
|
|
||||||
s->accel_group = gtk_accel_group_new();
|
s->accel_group = gtk_accel_group_new();
|
||||||
s->machine_menu = gd_create_menu_machine(s);
|
s->machine_menu = gd_create_menu_machine(s);
|
||||||
s->view_menu = gd_create_menu_view(s);
|
s->view_menu = gd_create_menu_view(s, opts);
|
||||||
|
|
||||||
s->machine_menu_item = gtk_menu_item_new_with_mnemonic(_("_Machine"));
|
s->machine_menu_item = gtk_menu_item_new_with_mnemonic(_("_Machine"));
|
||||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(s->machine_menu_item),
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(s->machine_menu_item),
|
||||||
|
@ -2359,7 +2364,7 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
|
||||||
|
|
||||||
gtk_window_set_icon_name(GTK_WINDOW(s->window), "qemu");
|
gtk_window_set_icon_name(GTK_WINDOW(s->window), "qemu");
|
||||||
|
|
||||||
gd_create_menus(s);
|
gd_create_menus(s, opts);
|
||||||
|
|
||||||
gd_connect_signals(s);
|
gd_connect_signals(s);
|
||||||
|
|
||||||
|
@ -2374,6 +2379,10 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts)
|
||||||
gtk_container_add(GTK_CONTAINER(s->window), s->vbox);
|
gtk_container_add(GTK_CONTAINER(s->window), s->vbox);
|
||||||
|
|
||||||
gtk_widget_show_all(s->window);
|
gtk_widget_show_all(s->window);
|
||||||
|
if (opts->u.gtk.has_show_menubar &&
|
||||||
|
!opts->u.gtk.show_menubar) {
|
||||||
|
gtk_widget_hide(s->menu_bar);
|
||||||
|
}
|
||||||
|
|
||||||
vc = gd_vc_find_current(s);
|
vc = gd_vc_find_current(s);
|
||||||
gtk_widget_set_sensitive(s->view_menu, vc != NULL);
|
gtk_widget_set_sensitive(s->view_menu, vc != NULL);
|
||||||
|
|
11
ui/vnc.c
11
ui/vnc.c
|
@ -2442,8 +2442,8 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
|
uint32_t dlen = abs(read_s32(data, 4));
|
||||||
if (len == 8) {
|
if (len == 8) {
|
||||||
uint32_t dlen = abs(read_s32(data, 4));
|
|
||||||
if (dlen > (1 << 20)) {
|
if (dlen > (1 << 20)) {
|
||||||
error_report("vnc: client_cut_text msg payload has %u bytes"
|
error_report("vnc: client_cut_text msg payload has %u bytes"
|
||||||
" which exceeds our limit of 1MB.", dlen);
|
" which exceeds our limit of 1MB.", dlen);
|
||||||
|
@ -2456,8 +2456,13 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_s32(data, 4) < 0) {
|
if (read_s32(data, 4) < 0) {
|
||||||
vnc_client_cut_text_ext(vs, abs(read_s32(data, 4)),
|
if (dlen < 4) {
|
||||||
read_u32(data, 8), data + 12);
|
error_report("vnc: malformed payload (header less than 4 bytes)"
|
||||||
|
" in extended clipboard pseudo-encoding.");
|
||||||
|
vnc_client_error(vs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vnc_client_cut_text_ext(vs, dlen, read_u32(data, 8), data + 12);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vnc_client_cut_text(vs, read_u32(data, 4), data + 8);
|
vnc_client_cut_text(vs, read_u32(data, 4), data + 8);
|
||||||
|
|
Loading…
Reference in New Issue