Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <fcntl.h>
- #include <pthread.h>
- #include <pulse/error.h>
- #include <pulse/channelmap.h>
- #include <pulse/stream.h>
- #include <pulse/context.h>
- #include <pulse/mainloop.h>
- // thank you https://gist.github.com/toroidal-code/8798775
- static char * argv0;
- static pa_context * pa_ctx;
- static pthread_t p1;
- static pthread_t p2;
- static int fd1 = -1;
- static int fd2 = -1;
- /* A simple routine calling UNIX write() in a loop */
- static ssize_t loop_write(int fd, const void*data, size_t size) {
- ssize_t ret = 0;
- while (size > 0) {
- ssize_t r;
- if ((r = write(fd, data, size)) < 0)
- return r;
- if (r == 0)
- break;
- ret += r;
- data = (const uint8_t*) data + r;
- size -= (size_t) r;
- }
- return ret;
- }
- static void pa_die(char const * nam, int e) {
- if (e) {
- fprintf(stderr,"%s() failed: %s\n", nam, pa_strerror(e));
- _exit(1);
- }
- }
- static void on_read(pa_stream *p, size_t len, void *user_data) {
- int fd = *(int*)user_data;
- void const * buf;
- // it seems that incoming len is pointless.
- pa_die("pa_stream_peek", pa_stream_peek(p, &buf, &len));
- if (len) {
- if (buf) {
- loop_write(fd, buf, len);
- } else {
- // hole
- unsigned char buf2[len];
- memset(buf2, 0, len);
- loop_write(fd, buf2, len);
- }
- pa_die("pa_stream_drop", pa_stream_drop(p));
- }
- }
- static void start_stream(char const * file, int * fd) {
- static const pa_sample_spec ss = {
- .format = PA_SAMPLE_S16LE,
- .rate = 44100,
- .channels = 2
- };
- pa_stream * s;
- pa_channel_map cm;
- pa_channel_map_init_stereo(&cm);
- if (!pa_channel_map_valid(&cm)) {
- printf("channel map not valid\n");
- _exit(1);
- }
- if (!(s = pa_stream_new(pa_ctx, file, &ss, &cm))) {
- printf("no new stream\n");
- _exit(1);
- }
- *fd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0644);
- if (*fd < 0) {
- perror("create");
- _exit(1);
- }
- pa_stream_set_read_callback(s, on_read, fd);
- pa_die("pa_stream_connect_record", pa_stream_connect_record(s, NULL, NULL, PA_STREAM_NOFLAGS));
- }
- static void on_state(pa_context *c, void *userdata) {
- pa_context_state_t st = pa_context_get_state(c);
- printf("context state %d\n", (int)st);
- if (st == PA_CONTEXT_READY) {
- start_stream("1", &fd1);
- start_stream("2", &fd2);
- }
- }
- int main(int argc, char*argv[]) {
- /* The sample type to use */
- pa_mainloop * pa_lp = pa_mainloop_new();
- if (!pa_lp) {
- printf("no main loop\n");
- return 1;
- }
- pa_mainloop_api * pa_lp_api = pa_mainloop_get_api(pa_lp);
- pa_ctx = pa_context_new(pa_lp_api, "two");
- if (!pa_ctx) {
- printf("no context\n");
- return 1;
- }
- pa_context_set_state_callback(pa_ctx, on_state, NULL);
- pa_die("pa_context_connect", pa_context_connect(pa_ctx, NULL, PA_CONTEXT_NOFLAGS, NULL));
- int dummy;
- pa_mainloop_run(pa_lp, &dummy);
- return 0;
- }
Add Comment
Please, Sign In to add comment