/* Compiling: * gcc test.c -o test -lpulse */ #include #include static pa_mainloop *mainloop = NULL; static pa_stream *stream = NULL; pa_usec_t started_at = 0; static void stream_state_cb(pa_stream *p, void *userdata) { pa_context *context; pa_stream_state_t state; printf("stream_state_cb()\n"); context = pa_stream_get_context(stream); state = pa_stream_get_state(stream); switch (state) { case PA_STREAM_UNCONNECTED: case PA_STREAM_CREATING: break; case PA_STREAM_READY: { const pa_format_info *info; char buf[PA_FORMAT_INFO_SNPRINT_MAX]; printf("Stream ready.\n"); info = pa_stream_get_format_info(stream); if (!info) { printf("pa_stream_get_format_info() failed: %s\n", pa_strerror(pa_context_errno(context))); goto fail; } printf("Negotiated format: %s\n", pa_format_info_snprint(buf, sizeof(buf), info)); break; } case PA_STREAM_FAILED: { printf("Stream failed: %s\n", pa_strerror(pa_context_errno(context))); goto fail; } case PA_STREAM_TERMINATED: { printf("Stream terminated.\n"); pa_mainloop_quit(mainloop, 0); break; } } return; fail: pa_mainloop_quit(mainloop, -1); } static void stream_write_cb(pa_stream *p, size_t nbytes, void *userdata) { pa_context *context; void *buf; int r; struct timeval timeval; pa_usec_t now; unsigned seconds_passed; pa_usec_t stream_usec; unsigned stream_time; unsigned rate; printf("stream_write_cb()\n"); context = pa_stream_get_context(stream); buf = pa_xnew0(uint8_t, nbytes); r = pa_stream_write(stream, buf, nbytes, NULL, 0, PA_SEEK_RELATIVE); pa_xfree(buf); if (r < 0) { printf("pa_stream_write() failed: %s", pa_strerror(pa_context_errno(context))); goto fail; } now = pa_timeval_load(pa_gettimeofday(&timeval)); seconds_passed = (now - started_at) / PA_USEC_PER_SEC; printf("seconds_passed = %u\n", seconds_passed); if (pa_stream_get_time(p, &stream_usec) >= 0) { stream_time = stream_usec / PA_USEC_PER_SEC; printf("stream_time = %u\n", stream_time); } else printf("pa_stream_get_time() failed.\n"); return; fail: pa_mainloop_quit(mainloop, -1); } static void context_state_cb(pa_context *context, void *userdata) { pa_context_state_t state; printf("context_state_cb()\n"); state = pa_context_get_state(context); switch (state) { case PA_CONTEXT_UNCONNECTED: case PA_CONTEXT_CONNECTING: case PA_CONTEXT_AUTHORIZING: case PA_CONTEXT_SETTING_NAME: break; case PA_CONTEXT_READY: { pa_sample_spec spec; pa_channel_map map; pa_format_info *formats[1]; pa_buffer_attr attr; int r; struct timeval timeval; spec.format = PA_SAMPLE_S16LE; spec.rate = 22050; spec.channels = 2; map.channels = 2; map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; formats[0] = pa_format_info_new(); formats[0]->encoding = PA_ENCODING_PCM; pa_format_info_set_sample_format(formats[0], spec.format); pa_format_info_set_channels(formats[0], spec.channels); pa_format_info_set_channel_map(formats[0], &map); attr.maxlength = -1; attr.tlength = pa_usec_to_bytes(100 * PA_USEC_PER_MSEC, &spec); attr.prebuf = -1; attr.minreq = -1; stream = pa_stream_new(context, "Nile", &spec, &map); pa_format_info_free(formats[0]); if (!stream) { printf("pa_stream_new_extended() failed: %s\n", pa_strerror(pa_context_errno(context))); goto fail; } pa_stream_set_state_callback(stream, stream_state_cb, NULL); pa_stream_set_write_callback(stream, stream_write_cb, NULL); r = pa_stream_connect_playback(stream, NULL, &attr, PA_STREAM_FIX_RATE | PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); if (r < 0) { printf("pa_stream_connect_playback() failed: %s\n", pa_strerror(r)); goto fail; } started_at = pa_timeval_load(pa_gettimeofday(&timeval)); break; } case PA_CONTEXT_FAILED: { printf("Context terminated.\n"); pa_mainloop_quit(mainloop, 0); break; } case PA_CONTEXT_TERMINATED: { printf("Context failed: %s\n", pa_strerror(pa_context_errno(context))); goto fail; } } return; fail: pa_mainloop_quit(mainloop, -1); } int main() { pa_context *context; int r; printf("main()\n"); mainloop = pa_mainloop_new(); context = pa_context_new(pa_mainloop_get_api(mainloop), "Super Solution"); if (!context) { printf("pa_context_new() failed.\n"); return EXIT_FAILURE; } pa_context_set_state_callback(context, context_state_cb, NULL); r = pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); if (r < 0) { printf("pa_context_connect() failed: %s\n", pa_strerror(pa_context_errno(context))); goto fail; } pa_mainloop_run(mainloop, NULL); if (stream) { pa_stream_disconnect(stream); pa_stream_unref(stream); } pa_context_disconnect(context); pa_context_unref(context); pa_mainloop_free(mainloop); return EXIT_SUCCESS; fail: if (stream) { pa_stream_disconnect(stream); pa_stream_unref(stream); } if (context) { pa_context_disconnect(context); pa_context_unref(context); } if (mainloop) pa_mainloop_free(mainloop); return EXIT_FAILURE; }