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:
commit
bae31bfa48
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user