audio: bugfixes for jack backend and gus emulation.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABCgAGBQJe7LriAAoJEEy22O7T6HE4TPgP+gOkwKib+yZMh+p5Eyhfl8F8
 sZvu2ukl7/SDusJOoFLDqgyj6Evxog7OXCjsmiurTR+fawaKif/4UG8c+JXtL3XU
 g7cv0meJMf/Q9+K/PAX7brnkj7GrMEtVL6G/dGFXgGeyzAfdtPLGdFIEvXwfDgEY
 BeqJNuppit6ENicuse1k1nXITJSOsTUnosBL+aj6aUAX5FfGIFxHQUwgX0Ds3EZF
 jk5HVKP+48qt5JjHCms+iPM3gCREmeySQXZG/0pF3F3kQUWJMP34Ng6B9QsrLr1a
 qIDxFEYpRuiGG8Ay3IG3y/GGZK/+9uDVkz3JhVM/3D5xRa808Ft7NS2CaMApjHNA
 VuURSIu3AIqa4E0zAxRwpFTw7zPfLRtzVMme8ZVd1E40I+RKYsR4o5vrAcvgRfBI
 07OoXpwSO2girwYC3uvQ9eNC8s7gg/eqzNtEEdg47abRzwaD87QWNnVdv2wr+p5E
 kLI2bZylEMCJ0br+t/eMjp7S45u+RLSU0YlGdfknGDaU1jOMI11WPpaNcgXKGzKB
 jLSN5PI6EugU5pYVsKYut0D99nZeexG8vOJscN33ub/N3VHxAvimGwW2uTYhGVyU
 GZz88e4uqm/wsthPZCfE0nqyO/ZGJ9TrZuE1qkyWqH+/bXxxBwmbqLrsjsVgeIuQ
 rlSsCcQHa/g+AISudicM
 =Triq
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/audio-20200619-pull-request' into staging

audio: bugfixes for jack backend and gus emulation.

# gpg: Signature made Fri 19 Jun 2020 14:17:22 BST
# gpg:                using RSA key 4CB6D8EED3E87138
# 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

* remotes/kraxel/tags/audio-20200619-pull-request:
  hw/audio/gus: Fix registers 32-bit access
  audio/jack: simplify the re-init code path
  audio/jack: honour the enable state of the audio device
  audio/jack: do not remove ports when finishing
  audio/jack: remove invalid set of input support bool
  audio/jack: remove unused stopped state
  audio/jack: fix invalid minimum buffer size check

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-06-19 22:56:59 +01:00
commit bae31bfa48
3 changed files with 40 additions and 37 deletions

View File

@ -38,7 +38,6 @@ struct QJack;
typedef enum QJackState { typedef enum QJackState {
QJACK_STATE_DISCONNECTED, QJACK_STATE_DISCONNECTED,
QJACK_STATE_STOPPED,
QJACK_STATE_RUNNING, QJACK_STATE_RUNNING,
QJACK_STATE_SHUTDOWN QJACK_STATE_SHUTDOWN
} }
@ -57,7 +56,7 @@ typedef struct QJackClient {
AudiodevJackPerDirectionOptions *opt; AudiodevJackPerDirectionOptions *opt;
bool out; bool out;
bool finished; bool enabled;
bool connect_ports; bool connect_ports;
int packets; int packets;
@ -272,9 +271,17 @@ static int qjack_process(jack_nframes_t nframes, void *arg)
} }
if (c->out) { if (c->out) {
qjack_buffer_read_l(&c->fifo, buffers, nframes); if (likely(c->enabled)) {
qjack_buffer_read_l(&c->fifo, buffers, nframes);
} else {
for(int i = 0; i < c->nchannels; ++i) {
memset(buffers[i], 0, nframes * sizeof(float));
}
}
} else { } else {
qjack_buffer_write_l(&c->fifo, buffers, nframes); if (likely(c->enabled)) {
qjack_buffer_write_l(&c->fifo, buffers, nframes);
}
} }
return 0; return 0;
@ -315,8 +322,8 @@ static void qjack_client_recover(QJackClient *c)
if (c->state == QJACK_STATE_DISCONNECTED && if (c->state == QJACK_STATE_DISCONNECTED &&
c->packets % 100 == 0) { c->packets % 100 == 0) {
/* if not finished then attempt to recover */ /* if enabled then attempt to recover */
if (!c->finished) { if (c->enabled) {
dolog("attempting to reconnect to server\n"); dolog("attempting to reconnect to server\n");
qjack_client_init(c); qjack_client_init(c);
} }
@ -388,7 +395,10 @@ static int qjack_client_init(QJackClient *c)
char client_name[jack_client_name_size()]; char client_name[jack_client_name_size()];
jack_options_t options = JackNullOption; jack_options_t options = JackNullOption;
c->finished = false; if (c->state == QJACK_STATE_RUNNING) {
return 0;
}
c->connect_ports = true; c->connect_ports = true;
snprintf(client_name, sizeof(client_name), "%s-%s", snprintf(client_name, sizeof(client_name), "%s-%s",
@ -434,17 +444,6 @@ static int qjack_client_init(QJackClient *c)
jack_set_xrun_callback(c->client, qjack_xrun, c); jack_set_xrun_callback(c->client, qjack_xrun, c);
jack_on_shutdown(c->client, qjack_shutdown, c); jack_on_shutdown(c->client, qjack_shutdown, c);
/*
* ensure the buffersize is no smaller then 512 samples, some (all?) qemu
* virtual devices do not work correctly otherwise
*/
if (c->buffersize < 512) {
c->buffersize = 512;
}
/* create a 2 period buffer */
qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 2);
/* allocate and register the ports */ /* allocate and register the ports */
c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels); c->port = g_malloc(sizeof(jack_port_t *) * c->nchannels);
for (int i = 0; i < c->nchannels; ++i) { for (int i = 0; i < c->nchannels; ++i) {
@ -468,6 +467,17 @@ static int qjack_client_init(QJackClient *c)
jack_activate(c->client); jack_activate(c->client);
c->buffersize = jack_get_buffer_size(c->client); c->buffersize = jack_get_buffer_size(c->client);
/*
* ensure the buffersize is no smaller then 512 samples, some (all?) qemu
* virtual devices do not work correctly otherwise
*/
if (c->buffersize < 512) {
c->buffersize = 512;
}
/* create a 2 period buffer */
qjack_buffer_create(&c->fifo, c->nchannels, c->buffersize * 2);
qjack_client_connect_ports(c); qjack_client_connect_ports(c);
c->state = QJACK_STATE_RUNNING; c->state = QJACK_STATE_RUNNING;
return 0; return 0;
@ -479,13 +489,13 @@ static int qjack_init_out(HWVoiceOut *hw, struct audsettings *as,
QJackOut *jo = (QJackOut *)hw; QJackOut *jo = (QJackOut *)hw;
Audiodev *dev = (Audiodev *)drv_opaque; Audiodev *dev = (Audiodev *)drv_opaque;
if (jo->c.state != QJACK_STATE_DISCONNECTED) { qjack_client_fini(&jo->c);
return 0;
}
jo->c.out = true; jo->c.out = true;
jo->c.enabled = false;
jo->c.nchannels = as->nchannels; jo->c.nchannels = as->nchannels;
jo->c.opt = dev->u.jack.out; jo->c.opt = dev->u.jack.out;
int ret = qjack_client_init(&jo->c); int ret = qjack_client_init(&jo->c);
if (ret != 0) { if (ret != 0) {
return ret; return ret;
@ -515,13 +525,13 @@ static int qjack_init_in(HWVoiceIn *hw, struct audsettings *as,
QJackIn *ji = (QJackIn *)hw; QJackIn *ji = (QJackIn *)hw;
Audiodev *dev = (Audiodev *)drv_opaque; Audiodev *dev = (Audiodev *)drv_opaque;
if (ji->c.state != QJACK_STATE_DISCONNECTED) { qjack_client_fini(&ji->c);
return 0;
}
ji->c.out = false; ji->c.out = false;
ji->c.enabled = false;
ji->c.nchannels = as->nchannels; ji->c.nchannels = as->nchannels;
ji->c.opt = dev->u.jack.in; ji->c.opt = dev->u.jack.in;
int ret = qjack_client_init(&ji->c); int ret = qjack_client_init(&ji->c);
if (ret != 0) { if (ret != 0) {
return ret; return ret;
@ -549,12 +559,6 @@ static void qjack_client_fini(QJackClient *c)
{ {
switch (c->state) { switch (c->state) {
case QJACK_STATE_RUNNING: case QJACK_STATE_RUNNING:
/* fallthrough */
case QJACK_STATE_STOPPED:
for (int i = 0; i < c->nchannels; ++i) {
jack_port_unregister(c->client, c->port[i]);
}
jack_deactivate(c->client); jack_deactivate(c->client);
/* fallthrough */ /* fallthrough */
@ -575,23 +579,25 @@ static void qjack_client_fini(QJackClient *c)
static void qjack_fini_out(HWVoiceOut *hw) static void qjack_fini_out(HWVoiceOut *hw)
{ {
QJackOut *jo = (QJackOut *)hw; QJackOut *jo = (QJackOut *)hw;
jo->c.finished = true;
qjack_client_fini(&jo->c); qjack_client_fini(&jo->c);
} }
static void qjack_fini_in(HWVoiceIn *hw) static void qjack_fini_in(HWVoiceIn *hw)
{ {
QJackIn *ji = (QJackIn *)hw; QJackIn *ji = (QJackIn *)hw;
ji->c.finished = true;
qjack_client_fini(&ji->c); qjack_client_fini(&ji->c);
} }
static void qjack_enable_out(HWVoiceOut *hw, bool enable) static void qjack_enable_out(HWVoiceOut *hw, bool enable)
{ {
QJackOut *jo = (QJackOut *)hw;
jo->c.enabled = enable;
} }
static void qjack_enable_in(HWVoiceIn *hw, bool enable) static void qjack_enable_in(HWVoiceIn *hw, bool enable)
{ {
QJackIn *ji = (QJackIn *)hw;
ji->c.enabled = enable;
} }
static int qjack_thread_creator(jack_native_thread_t *thread, static int qjack_thread_creator(jack_native_thread_t *thread,
@ -611,9 +617,6 @@ static int qjack_thread_creator(jack_native_thread_t *thread,
static void *qjack_init(Audiodev *dev) static void *qjack_init(Audiodev *dev)
{ {
assert(dev->driver == AUDIODEV_DRIVER_JACK); assert(dev->driver == AUDIODEV_DRIVER_JACK);
dev->u.jack.has_in = false;
return dev; return dev;
} }

View File

@ -32,7 +32,7 @@
#define GUSregb(position) (* (gusptr+(position))) #define GUSregb(position) (* (gusptr+(position)))
#define GUSregw(position) (*(uint16_t *) (gusptr+(position))) #define GUSregw(position) (*(uint16_t *) (gusptr+(position)))
#define GUSregd(position) (*(uint16_t *)(gusptr+(position))) #define GUSregd(position) (*(uint32_t *)(gusptr + (position)))
/* size given in bytes */ /* size given in bytes */
unsigned int gus_read(GUSEmuState * state, int port, int size) unsigned int gus_read(GUSEmuState * state, int port, int size)

View File

@ -28,7 +28,7 @@
#define GUSregb(position) (* (gusptr+(position))) #define GUSregb(position) (* (gusptr+(position)))
#define GUSregw(position) (*(uint16_t *) (gusptr+(position))) #define GUSregw(position) (*(uint16_t *) (gusptr+(position)))
#define GUSregd(position) (*(uint16_t *)(gusptr+(position))) #define GUSregd(position) (*(uint32_t *)(gusptr + (position)))
#define GUSvoice(position) (*(uint16_t *)(voiceptr+(position))) #define GUSvoice(position) (*(uint16_t *)(voiceptr+(position)))