Skip to content

Commit

Permalink
Make PCM writable before IO thread starts
Browse files Browse the repository at this point in the history
Is seems, that Firefox requires the PCM to be writable before it calls
the snd_pcm_start() ALSA function. Otherwise, audio thread will hang
forever in the poll system call.
  • Loading branch information
arkq committed Dec 10, 2016
1 parent d91ec18 commit 03d799c
Showing 1 changed file with 17 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/asound/bluealsa-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <fcntl.h>
#include <poll.h>
#include <pthread.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/eventfd.h>
#include <sys/ioctl.h>
Expand Down Expand Up @@ -50,7 +51,7 @@ struct bluealsa_pcm {
/* virtual hardware - ring buffer */
snd_pcm_uframes_t io_ptr;
pthread_t io_thread;
int io_started;
bool io_started;

/* ALSA operates on frames, we on bytes */
size_t frame_size;
Expand Down Expand Up @@ -316,10 +317,16 @@ static int bluealsa_start(snd_pcm_ioplug_t *io) {
struct bluealsa_pcm *pcm = io->private_data;
debug("Starting");

pcm->io_started = 1;
/* If the IO thread is already started, skip thread creation. Otherwise,
* we might end up with a bunch of IO threads reading or writing to the
* same FIFO simultaneously. */
if (pcm->io_started)
return 0;

pcm->io_started = true;
if ((errno = pthread_create(&pcm->io_thread, NULL, io_thread, io)) != 0) {
debug("Couldn't create IO thread: %s", strerror(errno));
pcm->io_started = 0;
pcm->io_started = false;
return -errno;
}

Expand All @@ -331,7 +338,7 @@ static int bluealsa_stop(snd_pcm_ioplug_t *io) {
struct bluealsa_pcm *pcm = io->private_data;
debug("Stopping");
if (pcm->io_started) {
pcm->io_started = 0;
pcm->io_started = false;
pthread_cancel(pcm->io_thread);
pthread_join(pcm->io_thread, NULL);
}
Expand Down Expand Up @@ -364,6 +371,12 @@ static int bluealsa_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params)
return -errno;
}

/* Indicate that our PCM is ready for writing, even though is is not 100%
* true - IO thread is not running yet. Some weird implementations might
* require PCM to be writable before the snd_pcm_start() call. */
if (io->stream == SND_PCM_STREAM_PLAYBACK)
eventfd_write(pcm->event_fd, 1);

if (pcm->io.stream == SND_PCM_STREAM_PLAYBACK) {
/* By default, the size of the pipe buffer is set to a too large value for
* our purpose. On modern Linux system it is 65536 bytes. Large buffer in
Expand Down

0 comments on commit 03d799c

Please sign in to comment.