Skip to content

Instantly share code, notes, and snippets.

@takaswie
Created March 12, 2017 03:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takaswie/a498329f0a09b1f715b562cb1942638f to your computer and use it in GitHub Desktop.
Save takaswie/a498329f0a09b1f715b562cb1942638f to your computer and use it in GitHub Desktop.
Poll(2) blocking test of PCM dmix plugin.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <stdbool.h>
#include <alsa/asoundlib.h>
#define CHANNELS 2
#define RATE 48000
#define FRAMES 480
/* Equal to 32bit sample * 2 ch * 480 frames. */
static unsigned char buffer[4 * CHANNELS * FRAMES];
static pthread_t thread;
static bool thread_running;
static void *listener_run(void *arg)
{
snd_pcm_t *handle = arg;
snd_pcm_status_t *status;
int err;
snd_pcm_status_alloca(&status);
thread_running = true;
while (thread_running) {
err = snd_pcm_status(handle, status);
if (err < 0) {
printf("snd_pcm_status(): %s\n", strerror(-err));
break;
}
}
printf("listener exit.\n");
return NULL;
}
int main(int argc, const char *const argv[])
{
snd_pcm_t *handle;
snd_pcm_sframes_t frames;
unsigned int i;
int err;
/* Open PCM character device with dmix plugin. */
err = snd_pcm_open(&handle, "pcm.dmix:0,0", SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
printf("snd_pcm_open(2): %s\n", strerror(-errno));
return EXIT_FAILURE;
}
/*
* Set parameters for PCM substream. Keep 500 msec buffer so that dmix
* plugin can work well.
*/
err = snd_pcm_set_params(handle, SND_PCM_FORMAT_S32,
SND_PCM_ACCESS_RW_INTERLEAVED, CHANNELS, RATE,
1, 500 * 1000);
if (err < 0) {
printf("snd_pcm_set_params(): %s\n", strerror(-err));
snd_pcm_close(handle);
return EXIT_FAILURE;
}
/* Start listener for the PCM substream. */
err = pthread_create(&thread, NULL, listener_run, (void *)handle);
if (err < 0) {
printf("pthread_create(2): %s\n", strerror(err));
snd_pcm_close(handle);
return EXIT_FAILURE;
}
/* Write as much frames as 1 sec. */
for (i = 0; i < RATE / FRAMES; ++i) {
frames = snd_pcm_writei(handle, buffer, FRAMES);
if (frames < 0) {
printf("snd_pcm_writei(): %s\n", strerror(-frames));
snd_pcm_close(handle);
return EXIT_FAILURE;
}
if (frames != FRAMES) {
printf("Blocking mode actually works against our "
"expectation: %ld\n",
frames);
break;
}
}
/*
* Let's drain frames in the PCM substream. In this thread, execution
* is sometimes blocked at poll(2). In this case, this program will not
* finish unless receiving any signal.
*/
snd_pcm_drain(handle);
/* Finish a thread for listener. */
thread_running = false;
snd_pcm_close(handle);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment