diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 153 |
1 files changed, 153 insertions, 0 deletions
@@ -0,0 +1,153 @@ +#include <gtk/gtk.h> +#include <cairo/cairo.h> +#include <portaudio.h> + +int device = -1; + +typedef struct { + float left; + float right; +} AudioData; + +AudioData audiodata; + +struct data { + int device_num; +}; + +PaStream *stream = NULL; +GtkWidget *drawing_area; + +#define FRAMES_PER_BUFFER 256 + +int patestCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) +{ + AudioData *data = (AudioData *)userData; + float *in = (float *)inputBuffer; + + if (data->left > 0) { + data->left -= 0.005; + } + + if (data->right > 0) { + data->right -= 0.005; + } + + for (unsigned long i = 0; i < framesPerBuffer * 2; i += 2) { + data->left = MAX(data->left, fabs(in[i])); + data->right = MAX(data->right, fabs(in[i + 1])); + } + + if (drawing_area) { + gtk_widget_queue_draw(GTK_WIDGET(drawing_area)); + } + + return 0; +} + +static void select_device(GtkWidget *widget, gpointer data) +{ + struct data *d = (struct data *)data; + device = d->device_num; + printf("Device %d selected\n", d->device_num); + + PaStreamParameters inputParameters; + memset(&inputParameters, 0, sizeof(inputParameters)); + inputParameters.channelCount = 2; + inputParameters.device = device; + inputParameters.hostApiSpecificStreamInfo = NULL; + inputParameters.sampleFormat = paFloat32; + inputParameters.suggestedLatency = Pa_GetDeviceInfo(device)->defaultLowInputLatency; + + Pa_OpenStream(&stream, &inputParameters, NULL, Pa_GetDeviceInfo(device)->defaultSampleRate, FRAMES_PER_BUFFER, paNoFlag, patestCallback, &audiodata); + Pa_StartStream(stream); +} + +static void draw(cairo_t *cr, GtkWidget *area) +{ + cairo_set_source_rgba(cr, 1, 0, 0, 1); + cairo_arc(cr, 250, 250, audiodata.left * 250, 0, 2 * M_PI); + cairo_arc(cr, 800, 250, audiodata.right * 250, 0, 2 * M_PI); + cairo_fill(cr); + + gtk_widget_queue_draw(area); +} + +static void draw_cb(GtkDrawingArea *drawing_area, cairo_t *cr, int width, int height, gpointer data) +{ + cairo_paint(cr); + draw(cr, data); +} + +static void refresh() +{ +} + +static void activate(GtkApplication *app, gpointer user_data) +{ + GtkWidget *window; + GtkWidget *grid; + GtkWidget *button; + + // init window + window = gtk_application_window_new(app); + gtk_window_set_title(GTK_WINDOW(window), "Directional Audio Visualizer"); + + // init grid + grid = gtk_grid_new(); + gtk_window_set_child(GTK_WINDOW(window), grid); + + // init drawing_area + drawing_area = gtk_drawing_area_new(); + gtk_widget_set_size_request(drawing_area, 1050, 500); + gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(drawing_area), draw_cb, drawing_area, NULL); + gtk_grid_attach(GTK_GRID(grid), drawing_area, 1, 2, 100, 100); + + // init audio devices + Pa_Initialize(); + int numDevices = Pa_GetDeviceCount(); + + if (numDevices < 0) { + printf("Error getting device count.\n"); + exit(EXIT_FAILURE); + } else if (numDevices == 0) { + printf("There are no available audio devices on this machine.\n"); + exit(EXIT_SUCCESS); + } + + // init button for every audio device + for (int i = 0; i < numDevices; i++) { + const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i); + struct data *d = malloc(sizeof(struct data)); + d->device_num = i; + button = gtk_button_new_with_label(deviceInfo->name); + g_signal_connect(button, "clicked", G_CALLBACK(select_device), d); + gtk_grid_attach(GTK_GRID(grid), button, 0, numDevices - i - 1, 1, 1); + } + + // init button for refresh + button = gtk_button_new_with_label("Refresh"); + g_signal_connect_swapped(button, "clicked", G_CALLBACK(refresh), window); + gtk_grid_attach(GTK_GRID(grid), button, 1, 0, 1, 1); + + // init button for quit + button = gtk_button_new_with_label("Quit"); + g_signal_connect_swapped(button, "clicked", G_CALLBACK(gtk_window_destroy), window); + gtk_grid_attach(GTK_GRID(grid), button, 1, 1, 1, 1); + + // set window + gtk_window_present(GTK_WINDOW(window)); +} + +int main(int argc, char **argv) +{ + GtkApplication *app; + int status; + + app = gtk_application_new("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS); + g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); + status = g_application_run(G_APPLICATION(app), argc, argv); + g_object_unref(app); + + return status; +} |
