You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
5.0 KiB
175 lines
5.0 KiB
#include <stdio.h> |
|
#include <unistd.h> |
|
#include <string.h> |
|
#include <errno.h> |
|
#include <pulse/simple.h> |
|
#include <pulse/error.h> |
|
#include <pulse/pulseaudio.h> |
|
#define BUFSIZE 1024 |
|
|
|
pa_mainloop *m_pulseaudio_mainloop; |
|
|
|
void cb(__attribute__((unused)) pa_context *pulseaudio_context, const pa_server_info *i, void *userdata){ |
|
|
|
//getting default sink name |
|
struct audio_data *audio = (struct audio_data *)userdata; |
|
audio->source = malloc(sizeof(char) * 1024); |
|
|
|
strcpy(audio->source,i->default_sink_name); |
|
|
|
//appending .monitor suufix |
|
audio->source = strcat(audio->source, ".monitor"); |
|
|
|
//quiting mainloop |
|
pa_context_disconnect(pulseaudio_context); |
|
pa_context_unref(pulseaudio_context); |
|
pa_mainloop_quit(m_pulseaudio_mainloop, 0); |
|
pa_mainloop_free(m_pulseaudio_mainloop); |
|
} |
|
|
|
|
|
void pulseaudio_context_state_callback(pa_context *pulseaudio_context, |
|
void *userdata) { |
|
|
|
//make sure loop is ready |
|
switch (pa_context_get_state(pulseaudio_context)) |
|
{ |
|
case PA_CONTEXT_UNCONNECTED: |
|
//printf("UNCONNECTED\n"); |
|
break; |
|
case PA_CONTEXT_CONNECTING: |
|
//printf("CONNECTING\n"); |
|
break; |
|
case PA_CONTEXT_AUTHORIZING: |
|
//printf("AUTHORIZING\n"); |
|
break; |
|
case PA_CONTEXT_SETTING_NAME: |
|
//printf("SETTING_NAME\n"); |
|
break; |
|
case PA_CONTEXT_READY://extract default sink name |
|
//printf("READY\n"); |
|
pa_operation_unref(pa_context_get_server_info( |
|
pulseaudio_context, cb, userdata)); |
|
break; |
|
case PA_CONTEXT_FAILED: |
|
printf("failed to coennect to pulseaudio server\n"); |
|
exit(EXIT_FAILURE); |
|
break; |
|
case PA_CONTEXT_TERMINATED: |
|
printf("TERMINATED\n"); |
|
pa_mainloop_quit(m_pulseaudio_mainloop, 0); |
|
break; |
|
} |
|
} |
|
|
|
|
|
void getPulseDefaultSink(void* data) { |
|
|
|
|
|
struct audio_data *audio = (struct audio_data *)data; |
|
pa_mainloop_api *mainloop_api; |
|
pa_context *pulseaudio_context; |
|
int ret; |
|
|
|
// Create a mainloop API and connection to the default server |
|
m_pulseaudio_mainloop = pa_mainloop_new(); |
|
|
|
mainloop_api = pa_mainloop_get_api(m_pulseaudio_mainloop); |
|
pulseaudio_context = pa_context_new(mainloop_api, "cava device list"); |
|
|
|
|
|
// This function connects to the pulse server |
|
pa_context_connect(pulseaudio_context, NULL, PA_CONTEXT_NOFLAGS, |
|
NULL); |
|
|
|
|
|
// printf("connecting to server\n"); |
|
|
|
//This function defines a callback so the server will tell us its state. |
|
pa_context_set_state_callback(pulseaudio_context, |
|
pulseaudio_context_state_callback, |
|
(void*)audio); |
|
|
|
|
|
|
|
//starting a mainloop to get default sink |
|
|
|
//starting with one nonblokng iteration in case pulseaudio is not able to run |
|
if (!(ret = pa_mainloop_iterate(m_pulseaudio_mainloop, 0, &ret))){ |
|
printf("Could not open pulseaudio mainloop to " |
|
"find default device name: %d\n" |
|
"check if pulseaudio is running\n", |
|
ret); |
|
|
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
pa_mainloop_run(m_pulseaudio_mainloop, &ret); |
|
|
|
|
|
} |
|
|
|
void* input_pulse(void* data) |
|
{ |
|
|
|
struct audio_data *audio = (struct audio_data *)data; |
|
int i, n; |
|
int16_t buf[BUFSIZE / 2]; |
|
|
|
/* The sample type to use */ |
|
static const pa_sample_spec ss = { |
|
.format = PA_SAMPLE_S16LE, |
|
.rate = 44100, |
|
.channels = 2 |
|
}; |
|
static const pa_buffer_attr pb = { |
|
.maxlength = BUFSIZE * 2, |
|
.fragsize = BUFSIZE |
|
}; |
|
|
|
pa_simple *s = NULL; |
|
int error; |
|
|
|
if (!(s = pa_simple_new(NULL, "cava", PA_STREAM_RECORD, audio->source, "audio for cava", &ss, NULL, &pb, &error))) { |
|
//fprintf(stderr, __FILE__": Could not open pulseaudio source: %s, %s. To find a list of your pulseaudio sources run 'pacmd list-sources'\n",audio->source, pa_strerror(error)); |
|
sprintf(audio->error_message, __FILE__": Could not open pulseaudio source: %s, %s. To find a list of your pulseaudio sources run 'pacmd list-sources'\n",audio->source, pa_strerror(error)); |
|
audio->terminate = 1; |
|
pthread_exit(NULL); |
|
} |
|
|
|
n = 0; |
|
|
|
while (1) { |
|
/* Record some data ... */ |
|
if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) { |
|
//fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error)); |
|
//exit(EXIT_FAILURE); |
|
sprintf(audio->error_message, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error)); |
|
audio->terminate = 1; |
|
pthread_exit(NULL); |
|
} |
|
|
|
//sorting out channels |
|
|
|
for (i = 0; i < BUFSIZE / 2; i += 2) { |
|
|
|
if (audio->channels == 1) audio->audio_out_l[n] = (buf[i] + buf[i + 1]) / 2; |
|
|
|
//stereo storing channels in buffer |
|
if (audio->channels == 2) { |
|
audio->audio_out_l[n] = buf[i]; |
|
audio->audio_out_r[n] = buf[i + 1]; |
|
} |
|
|
|
n++; |
|
if (n == 2048 - 1)n = 0; |
|
} |
|
|
|
if (audio->terminate == 1) { |
|
pa_simple_free(s); |
|
break; |
|
} |
|
} |
|
|
|
return 0; |
|
}
|
|
|