diff options
Diffstat (limited to 'src/capture.c')
-rw-r--r-- | src/capture.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/src/capture.c b/src/capture.c new file mode 100644 index 0000000..e8ca2fd --- /dev/null +++ b/src/capture.c @@ -0,0 +1,203 @@ +#include "capture.h" +#include <pulse/pulseaudio.h> +#include <gtk/gtk.h> + +#define APP_TITLE "Test 5 lpo" +#define BUFSIZE 1024 + +extern void my_process(float *data, size_t nsamples, size_t nchan); + +capture_sound_level_cb_t *capture_sound_level_cb=NULL; + +int capture_init(pa_mainloop **m, pa_context **c); +void context_state_callback(pa_context *c, void *userdata); +void context_get_server_info_callback(pa_context *c, const pa_server_info*si, void *userdata); +void context_get_source_info_callback(pa_context *c, const pa_source_info *si, int is_last, void *userdata); +pa_stream * create_stream(pa_context *c, const pa_source_info *si); +void stream_state_callback(pa_stream *s, void *userdata); +void stream_read_callback(pa_stream *s, size_t nbytes, void *userdata); + +char *device_name=NULL; + +// Main procedure of this thread +void audio_thread(void *args) { + pa_context *c; + pa_mainloop *m; + int res, retval; + + capture_sound_level_cb=(capture_sound_level_cb_t *)args; + + //printf("debug : args==%p capture_sound_level_cb==%p\n", args, capture_sound_level_cb); + + res=capture_init(&m, &c); + g_assert(res==0); + + res=pa_mainloop_run(m,&retval); + g_assert(res==0); + g_assert(retval==0); + +// pa_context_disconnect(pa_ct); + pa_mainloop_free(m); +} + +int capture_init(pa_mainloop **m, pa_context **c) { + int res=0; + + *m=pa_mainloop_new(); + g_assert(*m); + + *c = pa_context_new(pa_mainloop_get_api(*m), APP_TITLE); + g_assert(*c); + + pa_context_set_state_callback(*c, context_state_callback, NULL); + res=pa_context_connect(*c, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL); + + return res; +} + +void context_state_callback(pa_context *c, void *userdata) { + switch (pa_context_get_state(c)) { + case PA_CONTEXT_UNCONNECTED: + printf("PA_CONTEXT_UNCONNECTED\n"); + break; + case PA_CONTEXT_CONNECTING: + printf("PA_CONTEXT_CONNECTING\n"); + break; + case PA_CONTEXT_AUTHORIZING: + printf("PA_CONTEXT_AUTHORIZING\n"); + break; + case PA_CONTEXT_SETTING_NAME: + printf("PA_CONTEXT_SETTING_NAME\n"); + break; + case PA_CONTEXT_READY: + printf("PA_CONTEXT_READY\n"); +// if (!device_name) { + pa_operation_unref(pa_context_get_server_info(c, context_get_server_info_callback, NULL)); +/* } else { + pa_operation_unref(pa_context_get_source_info_by_name(c, device_name, context_get_source_info_callback, NULL)); + } +*/ + break; + + case PA_CONTEXT_FAILED: + printf("PA_CONTEXT_FAILED\n"); + break; + + case PA_CONTEXT_TERMINATED: + printf("PA_CONTEXT_TERMINATED\n"); + break; + } +} + +void context_get_server_info_callback(pa_context *c, const pa_server_info*si, void *userdata) { + if (!si) { + printf("Failed to get server information\n"); + return; + } + + if (!si->default_source_name) { + printf("No default source set\n"); + return; + } + + pa_operation_unref(pa_context_get_source_info_by_name(c, si->default_source_name, context_get_source_info_callback, NULL)); + +} + +void context_get_source_info_callback(pa_context *c, const pa_source_info *si, int is_last, void *userdata) { + + if (is_last < 0) { + printf("Failed to get sink information\n"); + return; + } + + if (!si) { + return; + } + + create_stream(c,si); +} + +pa_stream *create_stream(pa_context *c, const pa_source_info *si) { + static const pa_buffer_attr ba={ + .maxlength=-1, + .tlength=1024, + .prebuf=-1, + .minreq=-1, + // .minreq=256, //For FFT calculus + .fragsize=512 + }; + + pa_sample_spec nss = { + .format = PA_SAMPLE_FLOAT32LE, + .rate = si->sample_spec.rate, + .channels = si->sample_spec.channels + }; + + pa_stream *stream=NULL; + //pa_proplist *pl=NULL; + char t[256]; + +/* + pa_channel_map cmap; + pa_channel_map_init_mono(&cmap); + //pa_channel_map_init_stereo(&cmap); +*/ + + printf("Source : %s (%s)\n", si->name, si->description); + printf("Using sample format: %s\n", pa_sample_spec_snprint(t, sizeof(t), &nss)); + printf("Using channel map: %s\n", pa_channel_map_snprint(t, sizeof(t), &(si->channel_map))); +/* + pl=pa_proplist_new(); + pa_proplist_set(pl, "maxlength", &pl_maxlength, sizeof(pl_maxlength)); + pa_proplist_set(pl, "tlength", &pl_tlength, sizeof(pl_tlength)); + pa_proplist_set(pl, "fragsize", &pl_fragsize, sizeof(pl_fragsize)); +*/ + stream=pa_stream_new(c, APP_TITLE, &nss, &(si->channel_map)); + //stream=pa_stream_new_with_proplist(c, APP_TITLE, &(si->sample_spec), &(si->channel_map), pl); + pa_stream_set_state_callback(stream, stream_state_callback, NULL); + pa_stream_set_read_callback(stream, stream_read_callback, NULL); + //pa_stream_connect_record(stream, APP_TITLE, NULL, (enum pa_stream_flags) 0); + pa_stream_connect_record(stream, si->name, &ba, PA_STREAM_ADJUST_LATENCY); + + return stream; +} + +void stream_state_callback(pa_stream *s, void *userdata) { + switch (pa_stream_get_state(s)) { + case PA_STREAM_UNCONNECTED: + printf("PA_STREAM_UNCONNECTED\n"); + break; + case PA_STREAM_CREATING: + printf("PA_STREAM_CREATING\n"); + break; + case PA_STREAM_READY: + printf("PA_STREAM_READY\n"); + //g_timeout_add(100, latency_func, NULL); + //pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_info_callback, NULL)); + break; + case PA_STREAM_FAILED: + printf("PA_STREAM_FAILED\n"); + break; + case PA_STREAM_TERMINATED: + printf("PA_STREAM_TERMINATED\n"); + break; + } +} + +void stream_read_callback(pa_stream *s, size_t nbytes, void *userdata) { + const void *p; + //printf("stream_read_callback %i\n", nbytes); + + if (pa_stream_peek(s, &p, &nbytes) < 0) { + printf("pa_stream_peek() failed\n");//: %s", pa_strerror(pa_context_errno(context))); + return; + } + +//printf("debug : before call capture_sound_level_cb==%p\n", capture_sound_level_cb); + my_process((float *)p,nbytes/sizeof(float), pa_stream_get_sample_spec(s)->channels); +//printf("debug : after call capture_sound_level_cb==%p\n", capture_sound_level_cb); + + pa_stream_drop(s); +} + |