Skip to content

Instantly share code, notes, and snippets.

@ford-prefect
Created April 4, 2018 13:30
Show Gist options
  • Save ford-prefect/e6e07007fd35d7503995ab36466d4ed3 to your computer and use it in GitHub Desktop.
Save ford-prefect/e6e07007fd35d7503995ab36466d4ed3 to your computer and use it in GitHub Desktop.
Loopback test
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <pulse/pulseaudio.h>
typedef struct {
pa_threaded_mainloop *loop;
pa_context *context;
pa_stream *play, *rec;
} App;
void write_cb(pa_stream *s, size_t nbytes, void *userdata)
{
uint8_t data[nbytes];
memset(data, 0, nbytes);
pa_stream_write(s, data, nbytes, NULL, 0, PA_SEEK_RELATIVE);
printf("Wrote %lu bytes\n", nbytes);
}
void read_cb(pa_stream *s, size_t nbytes, void *userdata)
{
uint8_t data[nbytes];
size_t n = nbytes;
pa_stream_peek(s, (const void **) &data, &n);
pa_stream_drop(s);
printf("Read %lu (of %lu) bytes\n", n, nbytes);
}
static void context_cb_t(pa_context *c, void *userdata)
{
App *app = (App *) userdata;
pa_mainloop_api *mainloop_api = pa_threaded_mainloop_get_api(app->loop);
switch (pa_context_get_state(c)) {
case PA_CONTEXT_READY: {
pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 2,
};
pa_buffer_attr play_attr = {
.tlength = pa_usec_to_bytes(50 * PA_USEC_PER_MSEC, &ss),
.minreq = -1,
.maxlength = -1,
};
pa_buffer_attr rec_attr = {
.tlength = -1,
.minreq = -1,
.maxlength = -1,
.fragsize = pa_usec_to_bytes(50 * PA_USEC_PER_MSEC, &ss),
};
app->play = pa_stream_new(c, "loopback-play", &ss, NULL);
pa_stream_set_write_callback(app->play, write_cb, NULL);
pa_stream_connect_playback(app->play, NULL, &play_attr, PA_STREAM_ADJUST_LATENCY, NULL, NULL);
app->rec = pa_stream_new(c, "loopback-rec", &ss, NULL);
pa_stream_set_read_callback(app->rec, read_cb, NULL);
pa_stream_connect_record(app->rec, NULL, &rec_attr, PA_STREAM_ADJUST_LATENCY);
break;
}
case PA_CONTEXT_FAILED:
mainloop_api->quit(mainloop_api, -1);
break;
default:
break;
}
}
int main(void)
{
App app = { 0, };
app.loop = pa_threaded_mainloop_new();
app.context = pa_context_new(pa_threaded_mainloop_get_api(app.loop), "loopback-test");
pa_context_set_state_callback(app.context, context_cb_t, &app);
pa_context_connect(app.context, NULL, PA_CONTEXT_NOFLAGS, NULL);
pa_threaded_mainloop_start(app.loop);
sleep(300);
pa_threaded_mainloop_stop(app.loop);
if (app.play) {
pa_stream_disconnect(app.play);
pa_stream_unref(app.play);
}
if (app.rec) {
pa_stream_disconnect(app.rec);
pa_stream_unref(app.rec);
}
pa_context_disconnect(app.context);
pa_context_unref(app.context);
pa_threaded_mainloop_free(app.loop);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment