#include #include "ui.hpp" using namespace std; void GTKUI::draw(cairo_t* cr, GtkWidget* drawing_area, gpointer user_data) { GTKUI* gtk = (GTKUI*)user_data; AudioData* audiodata = gtk->audiodata; float window_width = 900; float window_height = 900; float radius = 200; float space = 50; float delta, x, y; delta = 2 * M_PI / audiodata->get_channel_cnt(); cairo_set_source_rgba(cr, 1, 1, 1, 1); cairo_arc(cr, window_width / 2, window_height / 2, space, 0, 2 * M_PI); cairo_fill(cr); cairo_set_source_rgba(cr, 1, 0, 0, 1); for (int i = 0; i < audiodata->get_channel_cnt(); i += 2) { x = (radius + space) * cos(i * delta / 2); y = (radius + space) * sin(i * delta / 2); cairo_arc(cr, window_width / 2 - x, window_height / 2 - y, audiodata->get_channels()[i] * radius, 0, 2 * M_PI); cairo_arc(cr, window_width / 2 + x, window_height / 2 + y, audiodata->get_channels()[i + 1] * radius, 0, 2 * M_PI); } cairo_fill(cr); gtk_widget_queue_draw(drawing_area); } void GTKUI::draw_cb(GtkDrawingArea* drawing_area, cairo_t* cr, int width, int height, gpointer user_data) { GTKUI* gtk = (GTKUI*)user_data; AudioData* audiodata = gtk->audiodata; if (audiodata->get_channel_cnt() == 0) return; cairo_paint(cr); draw(cr, GTK_WIDGET(drawing_area), user_data); } struct ButtonData { GTKUI* gtk; int select_device; }; void GTKUI::select_device(GtkWidget* widget, gpointer user_data) { ButtonData* buttond = (ButtonData*)user_data; GTKUI* gtk = buttond->gtk; AudioData* audiodata = gtk->audiodata; audiodata->set_device_num(buttond->select_device); audiodata->start_stream(); gtk_widget_add_tick_callback(gtk->drawing_area, gtk->drawCallback, user_data, NULL); } void GTKUI::refresh(GtkWidget* widget, gpointer user_data) { GTKUI* gtk = (GTKUI*)user_data; AudioData* audiodata = gtk->audiodata; Pa_Terminate(); 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); } GtkWidget* button; for (int i = 0; i < numDevices; i++) { const PaDeviceInfo* deviceInfo = Pa_GetDeviceInfo(i); ButtonData* buttond = new ButtonData; buttond->gtk = gtk; buttond->select_device = i; button = gtk_button_new_with_label(deviceInfo->name); gtk->buttons.push_back(button); g_signal_connect(button, "clicked", G_CALLBACK(select_device), buttond); gtk_grid_attach(GTK_GRID(gtk->grid), button, 0, numDevices - i - 1, 1, 1); } gtk_widget_queue_draw(gtk->grid); } void GTKUI::close_window(GtkWidget* widget, gpointer user_data) { GTKUI* gtk = (GTKUI*)user_data; AudioData* audiodata = gtk->audiodata; audiodata->close_stream(); gtk_window_destroy(GTK_WINDOW(gtk->window)); } gboolean GTKUI::drawCallback(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer user_data) { if (widget) { gtk_widget_queue_draw(GTK_WIDGET(widget)); } return true; } void GTKUI::activate(GtkApplication* app, gpointer user_data) { GTKUI* gtk = (GTKUI*)user_data; // init window gtk->window = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(gtk->window), "Directional Audio Visualizer"); // init grid gtk->grid = gtk_grid_new(); gtk_window_set_child(GTK_WINDOW(gtk->window), gtk->grid); // init drawing_area gtk->drawing_area = gtk_drawing_area_new(); gtk_widget_set_size_request(gtk->drawing_area, 900, 900); gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(gtk->drawing_area), draw_cb, user_data, NULL); gtk_grid_attach(GTK_GRID(gtk->grid), gtk->drawing_area, 1, 2, 100, 100); // init audio devices Pa_Initialize(); refresh(gtk->window, user_data); // init button for refresh gtk->refresh_button = gtk_button_new_with_label("Refresh"); g_signal_connect(gtk->refresh_button, "clicked", G_CALLBACK(gtk->refresh), gtk); gtk_grid_attach(GTK_GRID(gtk->grid), gtk->refresh_button, 1, 0, 1, 1); // init button for quit gtk->quit_button = gtk_button_new_with_label("Quit"); g_signal_connect(gtk->quit_button, "clicked", G_CALLBACK(gtk->close_window), gtk); gtk_grid_attach(GTK_GRID(gtk->grid), gtk->quit_button, 1, 1, 1, 1); // set window gtk_window_present(GTK_WINDOW(gtk->window)); } GTKUI::GTKUI(int argc, char* argv[]) { this->audiodata = new AudioData; app = gtk_application_new("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS); g_signal_connect(app, "activate", G_CALLBACK(activate), this); status = g_application_run(G_APPLICATION(app), argc, argv); g_object_unref(app); }