aboutsummaryrefslogtreecommitdiffstats
path: root/audio/audio.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/audio.c')
-rw-r--r--audio/audio.c214
1 files changed, 109 insertions, 105 deletions
diff --git a/audio/audio.c b/audio/audio.c
index 5a77dac..fbc8431 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -24,7 +24,7 @@
*/
#include "hw/hw.h"
#include "audio.h"
-#include "console.h"
+#include "monitor.h"
#include "qemu-timer.h"
#include "sysemu.h"
@@ -146,14 +146,14 @@ struct fixed_settings {
int enabled;
int nb_voices;
int greedy;
- audsettings_t settings;
+ struct audsettings settings;
};
static struct {
struct fixed_settings fixed_out;
struct fixed_settings fixed_in;
union {
- int hz;
+ int hertz;
int64_t ticks;
} period;
int plive;
@@ -183,14 +183,14 @@ static struct {
}
},
- { 0 }, /* period */
+ { 250 }, /* period */
0, /* plive */
0 /* log_to_monitor */
};
-AudioState glob_audio_state;
+static AudioState glob_audio_state;
-volume_t nominal_volume = {
+struct mixeng_volume nominal_volume = {
0,
#ifdef FLOAT_MIXENG
1.0,
@@ -296,8 +296,8 @@ void *audio_calloc (const char *funcname, int nmemb, size_t size)
static char *audio_alloc_prefix (const char *s)
{
const char qemu_prefix[] = "QEMU_";
- size_t len;
- char *r;
+ size_t len, i;
+ char *r, *u;
if (!s) {
return NULL;
@@ -306,17 +306,15 @@ static char *audio_alloc_prefix (const char *s)
len = strlen (s);
r = qemu_malloc (len + sizeof (qemu_prefix));
- if (r) {
- size_t i;
- char *u = r + sizeof (qemu_prefix) - 1;
+ u = r + sizeof (qemu_prefix) - 1;
- strcpy (r, qemu_prefix);
- strcat (r, s);
+ pstrcpy (r, len + sizeof (qemu_prefix), qemu_prefix);
+ pstrcat (r, len + sizeof (qemu_prefix), s);
- for (i = 0; i < len; ++i) {
- u[i] = toupper (u[i]);
- }
+ for (i = 0; i < len; ++i) {
+ u[i] = qemu_toupper(u[i]);
}
+
return r;
}
@@ -433,10 +431,10 @@ void AUD_vlog (const char *cap, const char *fmt, va_list ap)
{
if (conf.log_to_monitor) {
if (cap) {
- term_printf ("%s: ", cap);
+ monitor_printf(cur_mon, "%s: ", cap);
}
- term_vprintf (fmt, ap);
+ monitor_vprintf(cur_mon, fmt, ap);
}
else {
if (!VERBOSE_CHECK(audio))
@@ -536,7 +534,7 @@ static void audio_process_options (const char *prefix,
{
char *optname;
const char qemu_prefix[] = "QEMU_";
- size_t preflen;
+ size_t preflen, optlen;
if (audio_bug (AUDIO_FUNC, !prefix)) {
dolog ("prefix = NULL\n");
@@ -564,21 +562,17 @@ static void audio_process_options (const char *prefix,
/* len of opt->name + len of prefix + size of qemu_prefix
* (includes trailing zero) + zero + underscore (on behalf of
* sizeof) */
- optname = qemu_malloc (len + preflen + sizeof (qemu_prefix) + 1);
- if (!optname) {
- dolog ("Could not allocate memory for option name `%s'\n",
- opt->name);
- continue;
- }
+ optlen = len + preflen + sizeof (qemu_prefix) + 1;
+ optname = qemu_malloc (optlen);
- strcpy (optname, qemu_prefix);
+ pstrcpy (optname, optlen, qemu_prefix);
/* copy while upper-casing, including trailing zero */
for (i = 0; i <= preflen; ++i) {
- optname[i + sizeof (qemu_prefix) - 1] = toupper (prefix[i]);
+ optname[i + sizeof (qemu_prefix) - 1] = qemu_toupper(prefix[i]);
}
- strcat (optname, "_");
- strcat (optname, opt->name);
+ pstrcat (optname, optlen, "_");
+ pstrcat (optname, optlen, opt->name);
def = 1;
switch (opt->tag) {
@@ -618,7 +612,7 @@ static void audio_process_options (const char *prefix,
}
}
-static void audio_print_settings (audsettings_t *as)
+static void audio_print_settings (struct audsettings *as)
{
dolog ("frequency=%d nchannels=%d fmt=", as->freq, as->nchannels);
@@ -635,6 +629,12 @@ static void audio_print_settings (audsettings_t *as)
case AUD_FMT_U16:
AUD_log (NULL, "U16");
break;
+ case AUD_FMT_S32:
+ AUD_log (NULL, "S32");
+ break;
+ case AUD_FMT_U32:
+ AUD_log (NULL, "U32");
+ break;
default:
AUD_log (NULL, "invalid(%d)", as->fmt);
break;
@@ -655,7 +655,7 @@ static void audio_print_settings (audsettings_t *as)
AUD_log (NULL, "\n");
}
-static int audio_validate_settings (audsettings_t *as)
+static int audio_validate_settings (struct audsettings *as)
{
int invalid;
@@ -679,7 +679,7 @@ static int audio_validate_settings (audsettings_t *as)
return invalid ? -1 : 0;
}
-static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
+static int audio_pcm_info_eq (struct audio_pcm_info *info, struct audsettings *as)
{
int bits = 8, sign = 0;
@@ -694,6 +694,7 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
case AUD_FMT_U16:
bits = 16;
break;
+
case AUD_FMT_S32:
sign = 1;
case AUD_FMT_U32:
@@ -707,7 +708,7 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
&& info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS);
}
-void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
+void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
{
int bits = 8, sign = 0, shift = 0;
@@ -802,8 +803,8 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
/*
* Capture
*/
-static void noop_conv (st_sample_t *dst, const void *src,
- int samples, volume_t *vol)
+static void noop_conv (struct st_sample *dst, const void *src,
+ int samples, struct mixeng_volume *vol)
{
(void) src;
(void) dst;
@@ -812,11 +813,11 @@ static void noop_conv (st_sample_t *dst, const void *src,
}
static CaptureVoiceOut *audio_pcm_capture_find_specific (
- AudioState *s,
- audsettings_t *as
+ struct audsettings *as
)
{
CaptureVoiceOut *cap;
+ AudioState *s = &glob_audio_state;
for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
if (audio_pcm_info_eq (&cap->hw.info, as)) {
@@ -891,8 +892,9 @@ static void audio_detach_capture (HWVoiceOut *hw)
}
}
-static int audio_attach_capture (AudioState *s, HWVoiceOut *hw)
+static int audio_attach_capture (HWVoiceOut *hw)
{
+ AudioState *s = &glob_audio_state;
CaptureVoiceOut *cap;
audio_detach_capture (hw);
@@ -989,7 +991,7 @@ int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
{
HWVoiceIn *hw = sw->hw;
int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
- st_sample_t *src, *dst = sw->buf;
+ struct st_sample *src, *dst = sw->buf;
rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;
@@ -1236,6 +1238,7 @@ void AUD_set_active_out (SWVoiceOut *sw, int on)
hw = sw->hw;
if (sw->active != on) {
+ AudioState *s = &glob_audio_state;
SWVoiceOut *temp_sw;
SWVoiceCap *sc;
@@ -1243,9 +1246,11 @@ void AUD_set_active_out (SWVoiceOut *sw, int on)
hw->pending_disable = 0;
if (!hw->enabled) {
hw->enabled = 1;
+ if (s->vm_running) {
BEGIN_NOSIGALRM
hw->pcm_ops->ctl_out (hw, VOICE_ENABLE);
END_NOSIGALRM
+ }
}
}
else {
@@ -1281,14 +1286,17 @@ void AUD_set_active_in (SWVoiceIn *sw, int on)
hw = sw->hw;
if (sw->active != on) {
+ AudioState *s = &glob_audio_state;
SWVoiceIn *temp_sw;
if (on) {
if (!hw->enabled) {
hw->enabled = 1;
+ if (s->vm_running) {
BEGIN_NOSIGALRM
hw->pcm_ops->ctl_in (hw, VOICE_ENABLE);
END_NOSIGALRM
+ }
}
sw->total_hw_samples_acquired = hw->total_samples_captured;
}
@@ -1404,7 +1412,7 @@ static void audio_run_out (AudioState *s)
HWVoiceOut *hw = NULL;
SWVoiceOut *sw;
- while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) {
+ while ((hw = audio_pcm_hw_find_any_enabled_out (hw))) {
int played;
int live, free, nb_live, cleanup_required, prev_rpos;
@@ -1503,7 +1511,7 @@ static void audio_run_out (AudioState *s)
#ifdef DEBUG_PLIVE
dolog ("Finishing with old voice\n");
#endif
- audio_close_out (s, sw);
+ audio_close_out (sw);
}
sw = sw1;
}
@@ -1515,7 +1523,7 @@ static void audio_run_in (AudioState *s)
{
HWVoiceIn *hw = NULL;
- while ((hw = audio_pcm_hw_find_any_enabled_in (s, hw))) {
+ while ((hw = audio_pcm_hw_find_any_enabled_in (hw))) {
SWVoiceIn *sw;
int captured, min;
@@ -1556,7 +1564,7 @@ static void audio_run_capture (AudioState *s)
while (live) {
int left = hw->samples - rpos;
int to_capture = audio_MIN (live, left);
- st_sample_t *src;
+ struct st_sample *src;
struct capture_callback *cb;
src = hw->mix_buf + rpos;
@@ -1591,7 +1599,7 @@ static void audio_run_capture (AudioState *s)
static void audio_timer (void *opaque)
{
- AudioState* s = opaque;
+ AudioState *s = opaque;
#if 0
#define MAX_DIFFS 1000
int64_t now = qemu_get_clock(vm_clock);
@@ -1662,7 +1670,7 @@ static struct audio_option audio_options[] = {
"Number of voices for ADC", NULL, 0},
/* Misc */
- {"TIMER_PERIOD", AUD_OPT_INT, &conf.period.hz,
+ {"TIMER_PERIOD", AUD_OPT_INT, &conf.period.hertz,
"Timer period in HZ (0 - use lowest possible)", NULL, 0},
{"PLIVE", AUD_OPT_BOOL, &conf.plive,
@@ -1698,7 +1706,7 @@ void AUD_help (void)
size_t i;
audio_process_options ("AUDIO", audio_options);
- for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE (drvtab); i++) {
struct audio_driver *d = drvtab[i];
if (d->options) {
audio_process_options (d->name, d->options);
@@ -1711,7 +1719,7 @@ void AUD_help (void)
printf ("Available drivers:\n");
- for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
+ for (i = 0; i < ARRAY_SIZE (drvtab); i++) {
struct audio_driver *d = drvtab[i];
printf ("Name: %s\n", d->name);
@@ -1773,8 +1781,8 @@ static int audio_driver_init (AudioState *s, struct audio_driver *drv, int out)
END_NOSIGALRM
if (opaque != NULL) {
- audio_init_nb_voices_out (s, drv);
- audio_init_nb_voices_in (s, drv);
+ audio_init_nb_voices_out (drv);
+ audio_init_nb_voices_in (drv);
if (out) {
s->drv_out = drv;
s->drv_out_opaque = opaque;
@@ -1790,19 +1798,21 @@ static int audio_driver_init (AudioState *s, struct audio_driver *drv, int out)
}
}
-static void audio_vm_change_state_handler (void *opaque, int running)
+static void audio_vm_change_state_handler (void *opaque, int running,
+ int reason)
{
AudioState *s = opaque;
HWVoiceOut *hwo = NULL;
HWVoiceIn *hwi = NULL;
int op = running ? VOICE_ENABLE : VOICE_DISABLE;
+ s->vm_running = running;
BEGIN_NOSIGALRM
- while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
+ while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) {
hwo->pcm_ops->ctl_out (hwo, op);
}
- while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
+ while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) {
hwi->pcm_ops->ctl_in (hwi, op);
}
END_NOSIGALRM
@@ -1821,7 +1831,7 @@ static void audio_atexit (void)
initialized = 0;
BEGIN_NOSIGALRM
- while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
+ while ((hwo = audio_pcm_hw_find_any_enabled_out (hwo))) {
SWVoiceCap *sc;
hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
@@ -1837,7 +1847,7 @@ static void audio_atexit (void)
}
}
- while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
+ while ((hwi = audio_pcm_hw_find_any_enabled_in (hwi))) {
hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
hwi->pcm_ops->fini_in (hwi);
}
@@ -1869,21 +1879,6 @@ static int audio_load (QEMUFile *f, void *opaque, int version_id)
return 0;
}
-void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card)
-{
- card->audio = s;
- card->name = qemu_strdup (name);
- memset (&card->entries, 0, sizeof (card->entries));
- LIST_INSERT_HEAD (&s->card_head, card, entries);
-}
-
-void AUD_remove_card (QEMUSoundCard *card)
-{
- LIST_REMOVE (card, entries);
- card->audio = NULL;
- qemu_free (card->name);
-}
-
static int
find_audio_driver( AudioState* s, int out )
{
@@ -1946,10 +1941,14 @@ find_audio_driver( AudioState* s, int out )
}
-AudioState *AUD_init (void)
+static void audio_init (void)
{
AudioState *s = &glob_audio_state;
+ if (s->drv_out && s->drv_in) {
+ return;
+ }
+
LIST_INIT (&s->hw_head_out);
LIST_INIT (&s->hw_head_in);
LIST_INIT (&s->cap_head);
@@ -1958,7 +1957,7 @@ AudioState *AUD_init (void)
s->ts = qemu_new_timer (vm_clock, audio_timer, s);
if (!s->ts) {
dolog ("Could not create audio timer\n");
- return NULL;
+ return;
}
audio_process_options ("AUDIO", audio_options);
@@ -1978,32 +1977,29 @@ AudioState *AUD_init (void)
s->nb_hw_voices_in = 0;
}
- if ( find_audio_driver (s, 0) == 0 &&
- find_audio_driver (s, 1) == 0 )
- {
- VMChangeStateEntry *e;
+ if ( find_audio_driver (s, 0) != 0 ||
+ find_audio_driver (s, 1) != 0 ) {
+ qemu_del_timer (s->ts);
+ return;
+ }
- if (conf.period.hz <= 0) {
- if (conf.period.hz < 0) {
- dolog ("warning: Timer period is negative - %d "
- "treating as zero\n",
- conf.period.hz);
- }
- conf.period.ticks = 1;
- }
- else {
- conf.period.ticks = ticks_per_sec / conf.period.hz;
- }
+ VMChangeStateEntry *e;
- e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
- if (!e) {
- dolog ("warning: Could not register change state handler\n"
- "(Audio can continue looping even after stopping the VM)\n");
+ if (conf.period.hertz <= 0) {
+ if (conf.period.hertz < 0) {
+ dolog ("warning: Timer period is negative - %d "
+ "treating as zero\n",
+ conf.period.hertz);
}
+ conf.period.ticks = 1;
+ } else {
+ conf.period.ticks = ticks_per_sec / conf.period.hertz;
}
- else {
- qemu_del_timer (s->ts);
- return NULL;
+
+ e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
+ if (!e) {
+ dolog ("warning: Could not register change state handler\n"
+ "(Audio can continue looping even after stopping the VM)\n");
}
initialized = 1;
@@ -2011,7 +2007,20 @@ AudioState *AUD_init (void)
LIST_INIT (&s->card_head);
register_savevm ("audio", 0, 1, audio_save, audio_load, s);
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
- return s;
+}
+
+void AUD_register_card (const char *name, QEMUSoundCard *card)
+{
+ audio_init ();
+ card->name = qemu_strdup (name);
+ memset (&card->entries, 0, sizeof (card->entries));
+ LIST_INSERT_HEAD (&glob_audio_state.card_head, card, entries);
+}
+
+void AUD_remove_card (QEMUSoundCard *card)
+{
+ LIST_REMOVE (card, entries);
+ qemu_free (card->name);
}
// this was added to work around a deadlock in SDL when quitting
@@ -2021,20 +2030,15 @@ void AUD_cleanup()
}
CaptureVoiceOut *AUD_add_capture (
- AudioState *s,
- audsettings_t *as,
+ struct audsettings *as,
struct audio_capture_ops *ops,
void *cb_opaque
)
{
+ AudioState *s = &glob_audio_state;
CaptureVoiceOut *cap;
struct capture_callback *cb;
- if (!s) {
- /* XXX suppress */
- s = &glob_audio_state;
- }
-
if (audio_validate_settings (as)) {
dolog ("Invalid settings were passed when trying to add capture\n");
audio_print_settings (as);
@@ -2050,7 +2054,7 @@ CaptureVoiceOut *AUD_add_capture (
cb->ops = *ops;
cb->opaque = cb_opaque;
- cap = audio_pcm_capture_find_specific (s, as);
+ cap = audio_pcm_capture_find_specific (as);
if (cap) {
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
return cap;
@@ -2073,7 +2077,7 @@ CaptureVoiceOut *AUD_add_capture (
/* XXX find a more elegant way */
hw->samples = 4096 * 4;
hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples,
- sizeof (st_sample_t));
+ sizeof (struct st_sample));
if (!hw->mix_buf) {
dolog ("Could not allocate capture mix buffer (%d samples)\n",
hw->samples);
@@ -2100,8 +2104,8 @@ CaptureVoiceOut *AUD_add_capture (
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
hw = NULL;
- while ((hw = audio_pcm_hw_find_any_out (s, hw))) {
- audio_attach_capture (s, hw);
+ while ((hw = audio_pcm_hw_find_any_out (hw))) {
+ audio_attach_capture (hw);
}
return cap;