audio: clean up before monitor clean up
Since aa5cb7f5e
, the chardevs are being cleaned up when leaving qemu,
before the atexit() handlers. audio_cleanup() may use the monitor to
notify of changes. For compatibility reasons, let's clean up audio
before the monitor so it keeps emitting monitor events.
The audio_atexit() function is made idempotent (so it can be called
multiple times), and renamed to audio_cleanup(). Since coreaudio
backend is using a 'isAtexit' code path, change it to check
audio_is_cleaning_up() instead, so the path is taken during normal
exit.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20160801112343.29082-3-marcandre.lureau@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
This commit is contained in:
parent
2ef45716e1
commit
a384c205ac
@ -1739,13 +1739,21 @@ static void audio_vm_change_state_handler (void *opaque, int running,
|
|||||||
audio_reset_timer (s);
|
audio_reset_timer (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void audio_atexit (void)
|
static bool is_cleaning_up;
|
||||||
|
|
||||||
|
bool audio_is_cleaning_up(void)
|
||||||
|
{
|
||||||
|
return is_cleaning_up;
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio_cleanup(void)
|
||||||
{
|
{
|
||||||
AudioState *s = &glob_audio_state;
|
AudioState *s = &glob_audio_state;
|
||||||
HWVoiceOut *hwo = NULL;
|
HWVoiceOut *hwo, *hwon;
|
||||||
HWVoiceIn *hwi = NULL;
|
HWVoiceIn *hwi, *hwin;
|
||||||
|
|
||||||
while ((hwo = audio_pcm_hw_find_any_out (hwo))) {
|
is_cleaning_up = true;
|
||||||
|
QLIST_FOREACH_SAFE(hwo, &glob_audio_state.hw_head_out, entries, hwon) {
|
||||||
SWVoiceCap *sc;
|
SWVoiceCap *sc;
|
||||||
|
|
||||||
if (hwo->enabled) {
|
if (hwo->enabled) {
|
||||||
@ -1761,17 +1769,20 @@ static void audio_atexit (void)
|
|||||||
cb->ops.destroy (cb->opaque);
|
cb->ops.destroy (cb->opaque);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QLIST_REMOVE(hwo, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((hwi = audio_pcm_hw_find_any_in (hwi))) {
|
QLIST_FOREACH_SAFE(hwi, &glob_audio_state.hw_head_in, entries, hwin) {
|
||||||
if (hwi->enabled) {
|
if (hwi->enabled) {
|
||||||
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
|
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
|
||||||
}
|
}
|
||||||
hwi->pcm_ops->fini_in (hwi);
|
hwi->pcm_ops->fini_in (hwi);
|
||||||
|
QLIST_REMOVE(hwi, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->drv) {
|
if (s->drv) {
|
||||||
s->drv->fini (s->drv_opaque);
|
s->drv->fini (s->drv_opaque);
|
||||||
|
s->drv = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1799,7 +1810,7 @@ static void audio_init (void)
|
|||||||
QLIST_INIT (&s->hw_head_out);
|
QLIST_INIT (&s->hw_head_out);
|
||||||
QLIST_INIT (&s->hw_head_in);
|
QLIST_INIT (&s->hw_head_in);
|
||||||
QLIST_INIT (&s->cap_head);
|
QLIST_INIT (&s->cap_head);
|
||||||
atexit (audio_atexit);
|
atexit(audio_cleanup);
|
||||||
|
|
||||||
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
|
s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s);
|
||||||
|
|
||||||
@ -1966,8 +1977,7 @@ CaptureVoiceOut *AUD_add_capture (
|
|||||||
QLIST_INSERT_HEAD (&s->cap_head, cap, entries);
|
QLIST_INSERT_HEAD (&s->cap_head, cap, entries);
|
||||||
QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
|
QLIST_INSERT_HEAD (&cap->cb_head, cb, entries);
|
||||||
|
|
||||||
hw = NULL;
|
QLIST_FOREACH(hw, &glob_audio_state.hw_head_out, entries) {
|
||||||
while ((hw = audio_pcm_hw_find_any_out (hw))) {
|
|
||||||
audio_attach_capture (hw);
|
audio_attach_capture (hw);
|
||||||
}
|
}
|
||||||
return cap;
|
return cap;
|
||||||
|
@ -163,4 +163,7 @@ static inline void *advance (void *p, int incr)
|
|||||||
int wav_start_capture (CaptureState *s, const char *path, int freq,
|
int wav_start_capture (CaptureState *s, const char *path, int freq,
|
||||||
int bits, int nchannels);
|
int bits, int nchannels);
|
||||||
|
|
||||||
|
bool audio_is_cleaning_up(void);
|
||||||
|
void audio_cleanup(void);
|
||||||
|
|
||||||
#endif /* QEMU_AUDIO_H */
|
#endif /* QEMU_AUDIO_H */
|
||||||
|
@ -36,8 +36,6 @@
|
|||||||
#define MAC_OS_X_VERSION_10_6 1060
|
#define MAC_OS_X_VERSION_10_6 1060
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int isAtexit;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int buffer_frames;
|
int buffer_frames;
|
||||||
int nbuffers;
|
int nbuffers;
|
||||||
@ -378,11 +376,6 @@ static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void coreaudio_atexit (void)
|
|
||||||
{
|
|
||||||
isAtexit = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
|
static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
@ -630,7 +623,7 @@ static void coreaudio_fini_out (HWVoiceOut *hw)
|
|||||||
int err;
|
int err;
|
||||||
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
|
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
|
||||||
|
|
||||||
if (!isAtexit) {
|
if (!audio_is_cleaning_up()) {
|
||||||
/* stop playback */
|
/* stop playback */
|
||||||
if (isPlaying(core->outputDeviceID)) {
|
if (isPlaying(core->outputDeviceID)) {
|
||||||
status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
|
status = AudioDeviceStop(core->outputDeviceID, core->ioprocid);
|
||||||
@ -673,7 +666,7 @@ static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
|
|||||||
|
|
||||||
case VOICE_DISABLE:
|
case VOICE_DISABLE:
|
||||||
/* stop playback */
|
/* stop playback */
|
||||||
if (!isAtexit) {
|
if (!audio_is_cleaning_up()) {
|
||||||
if (isPlaying(core->outputDeviceID)) {
|
if (isPlaying(core->outputDeviceID)) {
|
||||||
status = AudioDeviceStop(core->outputDeviceID,
|
status = AudioDeviceStop(core->outputDeviceID,
|
||||||
core->ioprocid);
|
core->ioprocid);
|
||||||
@ -697,7 +690,6 @@ static void *coreaudio_audio_init (void)
|
|||||||
CoreaudioConf *conf = g_malloc(sizeof(CoreaudioConf));
|
CoreaudioConf *conf = g_malloc(sizeof(CoreaudioConf));
|
||||||
*conf = glob_conf;
|
*conf = glob_conf;
|
||||||
|
|
||||||
atexit(coreaudio_atexit);
|
|
||||||
return conf;
|
return conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
vl.c
1
vl.c
@ -4612,6 +4612,7 @@ int main(int argc, char **argv, char **envp)
|
|||||||
|
|
||||||
/* vhost-user must be cleaned up before chardevs. */
|
/* vhost-user must be cleaned up before chardevs. */
|
||||||
net_cleanup();
|
net_cleanup();
|
||||||
|
audio_cleanup();
|
||||||
monitor_cleanup();
|
monitor_cleanup();
|
||||||
qemu_chr_cleanup();
|
qemu_chr_cleanup();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user