Created
March 12, 2017 03:54
-
-
Save takaswie/a498329f0a09b1f715b562cb1942638f to your computer and use it in GitHub Desktop.
Poll(2) blocking test of PCM dmix plugin.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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