| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | /* Copyright 2011 David Henningsson, Canonical Ltd.
 | 
					
						
							|  |  |  |    License: GPLv2+  | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <gtk/gtk.h>
 | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  | #include <stdbool.h>
 | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "sysfs-pin-configs.h"
 | 
					
						
							|  |  |  | #include "apply-changes.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  | typedef struct ui_data_t ui_data_t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | typedef struct pin_ui_data_t { | 
					
						
							|  |  |  |     pin_configs_t* pin_config; | 
					
						
							|  |  |  |     typical_pins_t pins_info[32]; | 
					
						
							|  |  |  |     GtkWidget *frame, *override, *jacktype; | 
					
						
							|  |  |  |     GtkWidget* free_override_cb[FREE_OVERRIDES_COUNT]; | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     ui_data_t* owner; | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | } pin_ui_data_t; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  | struct ui_data_t { | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |     GList* pin_ui_data; | 
					
						
							|  |  |  |     GtkWidget *main_window; | 
					
						
							|  |  |  |     GtkWidget *content_scroll_widget; | 
					
						
							|  |  |  |     GtkWidget *content_inner_box; | 
					
						
							|  |  |  |     GtkWidget *codec_selection_combo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     codec_name_t* current_codec; | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     int sysfs_pincount; | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |     codec_name_t sysfs_codec_names[128]; | 
					
						
							|  |  |  |     pin_configs_t sysfs_pins[32]; | 
					
						
							|  |  |  |     gboolean free_overrides; | 
					
						
							|  |  |  |     gboolean trust_codec; | 
					
						
							|  |  |  |     gboolean trust_defcfg; | 
					
						
							|  |  |  |     gboolean model_auto; | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  | static void update_user_pin_config(ui_data_t* ui, pin_configs_t* cfg); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void update_override_sensitive(GtkWidget* sender, pin_ui_data_t* data) | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     gboolean checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sender)); | 
					
						
							|  |  |  |     gtk_widget_set_sensitive(data->jacktype, checked);  | 
					
						
							|  |  |  |     for (i = 0; i < FREE_OVERRIDES_COUNT; i++) | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |         gtk_widget_set_sensitive(data->free_override_cb[i], checked); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void override_toggled(GtkWidget* sender, pin_ui_data_t* data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     update_override_sensitive(sender, data); | 
					
						
							|  |  |  |     update_user_pin_config(data->owner, data->pin_config); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void jacktype_changed(GtkWidget* sender, pin_ui_data_t* data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     update_user_pin_config(data->owner, data->pin_config); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static GtkWidget* create_pin_ui(ui_data_t* ui, pin_configs_t* pin_cfg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GtkWidget* result; | 
					
						
							|  |  |  |     GtkContainer* box; | 
					
						
							|  |  |  |     pin_ui_data_t* data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int port_conn = get_port_conn(pin_cfg->init_pin_config); | 
					
						
							|  |  |  |     /* Do not show unconnected pins */ | 
					
						
							|  |  |  |     if (ui->trust_defcfg && port_conn == 1)  | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     data = calloc(1, sizeof(pin_ui_data_t)); | 
					
						
							|  |  |  |     data->pin_config = pin_cfg; | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     data->owner = ui; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |     { /* Frame */ | 
					
						
							|  |  |  |         gchar* d = get_config_description(pin_cfg->init_pin_config); | 
					
						
							|  |  |  |         gchar* c = g_strdup_printf("Pin ID: 0x%02x", pin_cfg->nid); | 
					
						
							|  |  |  |         GtkWidget* label = gtk_label_new(c); | 
					
						
							|  |  |  |         result = gtk_frame_new(d); | 
					
						
							|  |  |  |         data->frame = result; | 
					
						
							|  |  |  |         box = GTK_CONTAINER(gtk_box_new(GTK_ORIENTATION_VERTICAL, 2)); | 
					
						
							|  |  |  |         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | 
					
						
							|  |  |  |         gtk_container_add(box, label); | 
					
						
							|  |  |  |         g_free(d); | 
					
						
							|  |  |  |         g_free(c); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { /* Capabilities 
 | 
					
						
							|  |  |  |         gchar* s = get_caps_description(pin_cfg->pin_caps); | 
					
						
							|  |  |  |         gchar* s2 = g_strdup_printf("Capabilities: %s", strlen(s) > 2 ? s+2 : ""); // Hack for initial comma
 | 
					
						
							|  |  |  |         GtkWidget* label = gtk_label_new(s2); | 
					
						
							|  |  |  |         gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); | 
					
						
							|  |  |  |         gtk_container_add(box, label); | 
					
						
							|  |  |  |         g_free(s); | 
					
						
							|  |  |  |         g_free(s2); */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { /* Override */ | 
					
						
							|  |  |  |         GtkWidget* override = data->override = gtk_check_button_new_with_label("Override"); | 
					
						
							|  |  |  |         GtkWidget* jacktype = data->jacktype = gtk_combo_box_text_new(); | 
					
						
							|  |  |  |         GtkWidget* jacktype_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2); | 
					
						
							|  |  |  |         int index = get_typical_pins(data->pins_info, 32, pin_cfg, ui->trust_codec); | 
					
						
							|  |  |  |         typical_pins_t* current = data->pins_info; | 
					
						
							|  |  |  |         while (current->name) { | 
					
						
							|  |  |  |             gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(jacktype), current->name); | 
					
						
							|  |  |  |             current++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         gtk_combo_box_set_active(GTK_COMBO_BOX(jacktype), index); | 
					
						
							|  |  |  |         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(override), pin_cfg->user_override); | 
					
						
							|  |  |  |         g_signal_connect(override, "toggled", G_CALLBACK(override_toggled), data); | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |         g_signal_connect(jacktype, "changed", G_CALLBACK(jacktype_changed), data); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         gtk_container_add(box, override); | 
					
						
							|  |  |  |         gtk_container_add(GTK_CONTAINER(jacktype_box), jacktype); | 
					
						
							|  |  |  |         if (!ui->free_overrides) | 
					
						
							|  |  |  |             gtk_container_add(box, jacktype_box); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Advanced override */ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int i; | 
					
						
							|  |  |  |         GtkGrid* grid = GTK_GRID(gtk_grid_new()); | 
					
						
							|  |  |  |         gtk_grid_set_row_spacing(grid, 2); | 
					
						
							|  |  |  |         gtk_grid_set_column_spacing(grid, 4); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (i = 0; i < FREE_OVERRIDES_COUNT; i++) { | 
					
						
							|  |  |  |             int index = -1; | 
					
						
							|  |  |  |             int j = 0; | 
					
						
							|  |  |  |             unsigned long act_pincfg = actual_pin_config(pin_cfg); | 
					
						
							|  |  |  |             unsigned long mask = get_free_override_mask(i); | 
					
						
							|  |  |  |             free_override_t* values = get_free_override_list(i); | 
					
						
							|  |  |  |             data->free_override_cb[i] = gtk_combo_box_text_new(); | 
					
						
							|  |  |  |             if (!values) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             while (values->name) { | 
					
						
							|  |  |  |                 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(data->free_override_cb[i]), values->name); | 
					
						
							|  |  |  |                 if ((act_pincfg & mask) == values->value) | 
					
						
							|  |  |  |                     index = j; | 
					
						
							|  |  |  |                 values++; | 
					
						
							|  |  |  |                 j++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (index >= 0) | 
					
						
							|  |  |  |                 gtk_combo_box_set_active(GTK_COMBO_BOX(data->free_override_cb[i]), index); | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |             g_signal_connect(data->free_override_cb[i], "changed", G_CALLBACK(jacktype_changed), data); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         gtk_grid_attach(grid, gtk_label_new("Connectivity"), 0, 0, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, data->free_override_cb[0], 0, 1, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, gtk_label_new("Location"), 1, 0, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, data->free_override_cb[1], 1, 1, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, gtk_label_new("Device"), 2, 0, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, data->free_override_cb[2], 2, 1, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, gtk_label_new("Jack"), 3, 0, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, data->free_override_cb[3], 3, 1, 1, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         gtk_grid_attach(grid, gtk_label_new("Color"), 0, 2, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, data->free_override_cb[4], 0, 3, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, gtk_label_new("Jack detection"), 1, 2, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, data->free_override_cb[5], 1, 3, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, gtk_label_new("Channel group"), 2, 2, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, data->free_override_cb[6], 2, 3, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, gtk_label_new("Channel (in group)"), 3, 2, 1, 1); | 
					
						
							|  |  |  |         gtk_grid_attach(grid, data->free_override_cb[7], 3, 3, 1, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ui->free_overrides) | 
					
						
							|  |  |  |             gtk_container_add(box, GTK_WIDGET(grid)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     update_override_sensitive(data->override, data); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     gtk_container_add(GTK_CONTAINER(result), GTK_WIDGET(box)); | 
					
						
							|  |  |  |     ui->pin_ui_data = g_list_prepend(ui->pin_ui_data, data); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void free_pin_ui_data(pin_ui_data_t* data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!data) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     if (data->frame) | 
					
						
							|  |  |  |         gtk_widget_destroy(data->frame); | 
					
						
							|  |  |  |     free(data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gint pin_config_find(pin_ui_data_t* pin_ui, pin_configs_t* cfg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     return pin_ui->pin_config == cfg ? 0 : 1; | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  | static void update_user_pin_config(ui_data_t* ui, pin_configs_t* cfg) | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     pin_ui_data_t* pin_ui; | 
					
						
							|  |  |  |     GList *pos = g_list_find_custom(ui->pin_ui_data, cfg, (GCompareFunc) pin_config_find); | 
					
						
							|  |  |  |     cfg->user_override = FALSE; | 
					
						
							|  |  |  |     if (!pos) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     pin_ui = pos->data; | 
					
						
							|  |  |  |     if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pin_ui->override))) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     if (ui->free_overrides) { | 
					
						
							|  |  |  |         int j; | 
					
						
							|  |  |  |         int index; | 
					
						
							|  |  |  |         unsigned long val = 0; | 
					
						
							|  |  |  |         for (j = 0; j < FREE_OVERRIDES_COUNT; j++) { | 
					
						
							|  |  |  |             index = gtk_combo_box_get_active(GTK_COMBO_BOX(pin_ui->free_override_cb[j])); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |             if (index < 0) | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             val += get_free_override_list(j)[index].value; | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |         if (index < 0) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         cfg->user_pin_config = val; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         int index; | 
					
						
							|  |  |  |         index = gtk_combo_box_get_active(GTK_COMBO_BOX(pin_ui->jacktype)); | 
					
						
							|  |  |  |         if (index < 0) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         cfg->user_pin_config = pin_ui->pins_info[index].pin_set; | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     cfg->user_override = TRUE; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  | static void update_all_user_pin_config(ui_data_t* ui) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  |     for (i = 0; i < ui->sysfs_pincount; i++) | 
					
						
							|  |  |  |         update_user_pin_config(ui, &ui->sysfs_pins[i]); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean validate_user_pin_config(ui_data_t* ui, GError** err) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!ui->current_codec) { | 
					
						
							|  |  |  |         g_set_error(err, 0, 0, "You must first select a codec!"); | 
					
						
							|  |  |  |         return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     update_all_user_pin_config(ui); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |     if (ui->free_overrides) | 
					
						
							|  |  |  |         return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check surround configs */ | 
					
						
							|  |  |  |     for (i = 0; i < ui->sysfs_pincount; i++) { | 
					
						
							|  |  |  |         unsigned long v = ui->sysfs_pins[i].user_pin_config; | 
					
						
							|  |  |  |         if (!ui->sysfs_pins[i].user_override) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         if ((v & 0xf0) != 0x10) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         if (((v & 0xf) != 0) && !find_pin_channel_match(ui->sysfs_pins, ui->sysfs_pincount, v & 0xf0)) { | 
					
						
							|  |  |  |             g_set_error(err, 0, 0, "This surround setup also requires a \"front\" channel override."); | 
					
						
							|  |  |  |             return FALSE; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (((v & 0xf) >= 3) && !find_pin_channel_match(ui->sysfs_pins, ui->sysfs_pincount, 2 + (v & 0xf0))) { | 
					
						
							|  |  |  |             g_set_error(err, 0, 0, "This surround setup also requires a \"back\" channel override."); | 
					
						
							|  |  |  |             return FALSE; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ((v & 0xf) >= 3 && !find_pin_channel_match(ui->sysfs_pins, ui->sysfs_pincount, 1 + (v & 0xf0))) { | 
					
						
							|  |  |  |             g_set_error(err, 0, 0, "This surround setup also requires a \"Center/LFE\" channel override."); | 
					
						
							|  |  |  |             return FALSE; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void show_action_result(ui_data_t* ui, GError* err, const gchar* ok_msg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GtkWidget* dialog; | 
					
						
							|  |  |  |     const gchar* msg = err ? err->message : ok_msg; | 
					
						
							|  |  |  |     dialog = gtk_message_dialog_new (GTK_WINDOW(ui->main_window), | 
					
						
							|  |  |  |         GTK_DIALOG_DESTROY_WITH_PARENT, err ? GTK_MESSAGE_ERROR : GTK_MESSAGE_INFO,  | 
					
						
							|  |  |  |         GTK_BUTTONS_CLOSE, "%s", msg); | 
					
						
							|  |  |  |     gtk_dialog_run (GTK_DIALOG (dialog)); | 
					
						
							|  |  |  |     gtk_widget_destroy (dialog); | 
					
						
							|  |  |  |     if (err) | 
					
						
							|  |  |  |         g_error_free(err); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void apply_now_clicked(GtkButton* button, gpointer user_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GError* err = NULL; | 
					
						
							|  |  |  |     ui_data_t* ui = user_data; | 
					
						
							|  |  |  |     gboolean ok = validate_user_pin_config(ui, &err); | 
					
						
							|  |  |  |     if (ok) | 
					
						
							|  |  |  |         apply_changes_reconfig(ui->sysfs_pins, ui->sysfs_pincount,  | 
					
						
							|  |  |  |             ui->current_codec->card, ui->current_codec->device,  | 
					
						
							|  |  |  |             ui->model_auto ? "auto" : NULL, &err);  | 
					
						
							|  |  |  |     show_action_result(ui, err,  | 
					
						
							|  |  |  |         "Ok, now go ahead and test to see if it actually worked!\n" | 
					
						
							|  |  |  |         "(Remember, this stuff is still experimental.)"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void apply_boot_clicked(GtkButton* button, gpointer user_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GError* err = NULL; | 
					
						
							|  |  |  |     ui_data_t* ui = user_data; | 
					
						
							|  |  |  |     gboolean ok = validate_user_pin_config(ui, &err); | 
					
						
							|  |  |  |     if (ok)  | 
					
						
							|  |  |  |         apply_changes_boot(ui->sysfs_pins, ui->sysfs_pincount,  | 
					
						
							|  |  |  |             ui->current_codec->card, ui->current_codec->device,  | 
					
						
							|  |  |  |             ui->model_auto ? "auto" : NULL, &err);  | 
					
						
							|  |  |  |     show_action_result(ui, err,  | 
					
						
							|  |  |  |         "Ok, now reboot to test to see if it actually worked!\n" | 
					
						
							|  |  |  |         "(Remember, this stuff is still experimental.)"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void reset_boot_clicked(GtkButton* button, gpointer user_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GError* err = NULL; | 
					
						
							|  |  |  |     ui_data_t* ui = user_data; | 
					
						
							|  |  |  |     reset_changes_boot(&err); | 
					
						
							|  |  |  |     show_action_result(ui, err,  | 
					
						
							|  |  |  |         "The previous installed files (if any) of this program have been removed.\n" | 
					
						
							|  |  |  |         "Reboot to finish the uninstallation."); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void resize_main_window(ui_data_t* ui) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GtkAllocation a; | 
					
						
							|  |  |  |     GtkRequisition r; | 
					
						
							|  |  |  |     gint oldw, oldh, neww, newh, maxw, maxh; | 
					
						
							|  |  |  |     GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(ui->main_window)); | 
					
						
							|  |  |  |     gtk_widget_size_request(GTK_WIDGET(ui->content_inner_box), &r); | 
					
						
							|  |  |  |     gtk_widget_get_allocation(ui->content_scroll_widget, &a); | 
					
						
							|  |  |  | //    fprintf(stderr, "W: %d, H: %d, W: %d, H: %d\n", a.width, a.height, r.width, r.height);
 | 
					
						
							|  |  |  |     gtk_window_get_size(GTK_WINDOW(ui->main_window), &oldw, &oldh); | 
					
						
							|  |  |  |     maxw = screen ? (gdk_screen_get_width(screen)*3)/4 : INT_MAX / 4; | 
					
						
							|  |  |  |     maxh = screen ? (gdk_screen_get_height(screen)*3)/4 : INT_MAX / 4; | 
					
						
							|  |  |  | //    fprintf(stderr, "Before: W: %d, H: %d\n", oldw, oldh);
 | 
					
						
							|  |  |  |     neww = oldw; | 
					
						
							|  |  |  |     newh = oldh; | 
					
						
							|  |  |  |     if (a.width < r.width) { | 
					
						
							|  |  |  |         neww += 8 + r.width - a.width; | 
					
						
							|  |  |  |         if (neww > maxw) | 
					
						
							|  |  |  |             neww = maxw; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (a.height < r.height) { | 
					
						
							|  |  |  |         newh += 8 + r.height - a.height; | 
					
						
							|  |  |  |         if (newh > maxh) | 
					
						
							|  |  |  |             newh = maxh; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (neww != oldw || newh != oldh) { | 
					
						
							|  |  |  |         gtk_window_resize(GTK_WINDOW(ui->main_window), neww, newh); | 
					
						
							|  |  |  | //        fprintf(stderr, "After: W: %d, H: %d\n", neww, newh);   
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  | static void update_codec_ui(ui_data_t* ui, bool codec_change) | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     int codec_index = gtk_combo_box_get_active(GTK_COMBO_BOX(ui->codec_selection_combo)); | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_list_free_full(ui->pin_ui_data, (GDestroyNotify) free_pin_ui_data); | 
					
						
							|  |  |  |     ui->pin_ui_data = NULL; | 
					
						
							|  |  |  |     ui->current_codec = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (codec_index < 0) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     ui->current_codec = &ui->sysfs_codec_names[codec_index]; | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     if (codec_change) | 
					
						
							|  |  |  |         ui->sysfs_pincount = get_pin_configs_list(ui->sysfs_pins, 32, ui->current_codec->card, ui->current_codec->device); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |     for (i = 0; i < ui->sysfs_pincount; i++) { | 
					
						
							|  |  |  |         GtkWidget *w = create_pin_ui(ui, &ui->sysfs_pins[i]); | 
					
						
							|  |  |  |         if (w) | 
					
						
							|  |  |  |             gtk_container_add(GTK_CONTAINER(ui->content_inner_box), w); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     gtk_widget_show_all(GTK_WIDGET(ui->content_inner_box)); | 
					
						
							|  |  |  |     resize_main_window(ui); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void codec_selected(GtkComboBox* combo, gpointer user_data)  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     update_codec_ui(user_data, true); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void showallpins_toggled(GtkWidget* sender, ui_data_t* ui_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     gboolean checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sender)); | 
					
						
							|  |  |  |     ui_data->trust_defcfg = !checked; | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     update_codec_ui(ui_data, false); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void automodel_toggled(GtkWidget* sender, ui_data_t* ui_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ui_data->model_auto = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sender)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void free_override_toggled(GtkWidget* sender, ui_data_t* ui_data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ui_data->free_overrides = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sender)); | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |     update_codec_ui(ui_data, false); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char* readme_text =  | 
					
						
							|  |  |  | #include "README.generated.h"
 | 
					
						
							|  |  |  | ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void documentation_clicked(GtkWidget* sender, ui_data_t* ui) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GtkDialog* dlg = GTK_DIALOG(gtk_dialog_new_with_buttons("Jack retasking documentation",  | 
					
						
							|  |  |  |         GTK_WINDOW(ui->main_window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, | 
					
						
							|  |  |  |         GTK_STOCK_CLOSE, GTK_RESPONSE_NONE, NULL)); | 
					
						
							|  |  |  |     GtkTextView* textview = GTK_TEXT_VIEW(gtk_text_view_new()); | 
					
						
							|  |  |  |     GtkContainer* content_area = GTK_CONTAINER(gtk_dialog_get_content_area(dlg)); | 
					
						
							|  |  |  |     GtkScrolledWindow* content_scroll = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gtk_text_buffer_set_text(gtk_text_view_get_buffer(textview), readme_text, -1); | 
					
						
							|  |  |  |     gtk_text_view_set_editable(textview, FALSE); | 
					
						
							|  |  |  |     gtk_text_view_set_wrap_mode(textview, GTK_WRAP_WORD); | 
					
						
							|  |  |  |     gtk_text_view_set_cursor_visible(textview, FALSE); | 
					
						
							|  |  |  |     gtk_scrolled_window_add_with_viewport(content_scroll, GTK_WIDGET(textview)); | 
					
						
							|  |  |  |     gtk_container_add(content_area, GTK_WIDGET(content_scroll)); | 
					
						
							|  |  |  |     gtk_box_set_child_packing(GTK_BOX(content_area), GTK_WIDGET(content_scroll), TRUE, TRUE, 2, GTK_PACK_START); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gtk_widget_show_all(GTK_WIDGET(content_area)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { /* Resize to fit screen */ | 
					
						
							|  |  |  |         GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(ui->main_window)); | 
					
						
							|  |  |  |         int neww = screen ? (gdk_screen_get_width(screen)*3)/4 : 800; | 
					
						
							|  |  |  |         int newh = screen ? (gdk_screen_get_height(screen)*3)/4 : 600; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         gtk_window_set_default_size(GTK_WINDOW(dlg), neww, newh); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gtk_dialog_run(dlg); | 
					
						
							|  |  |  |     gtk_widget_destroy(GTK_WIDGET(dlg)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ui_data_t* create_ui() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ui_data_t* ui = calloc(sizeof(ui_data_t), 1); | 
					
						
							|  |  |  |     GtkContainer* toplevel_box = GTK_CONTAINER(gtk_box_new(GTK_ORIENTATION_VERTICAL, 2)); | 
					
						
							|  |  |  |     GtkContainer* toplevel_2ndbox = GTK_CONTAINER(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2)); | 
					
						
							|  |  |  |     ui->content_inner_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2); | 
					
						
							|  |  |  |     GtkContainer* rightside_box = GTK_CONTAINER(gtk_box_new(GTK_ORIENTATION_VERTICAL, 2)); | 
					
						
							|  |  |  |     ui->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | 
					
						
							|  |  |  |     gtk_window_set_title(GTK_WINDOW(ui->main_window), "Jack retasking for HDA Intel sound cards"); | 
					
						
							|  |  |  |     g_signal_connect (ui->main_window, "destroy", G_CALLBACK (gtk_main_quit), NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ui->trust_codec = TRUE; | 
					
						
							|  |  |  |     ui->trust_defcfg = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Select codec to work with */ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         GtkWidget* combo = ui->codec_selection_combo = gtk_combo_box_text_new(); | 
					
						
							|  |  |  |         GtkWidget* box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2); | 
					
						
							|  |  |  |         codec_name_t *n = ui->sysfs_codec_names; | 
					
						
							|  |  |  |         get_codec_name_list(ui->sysfs_codec_names, 128); | 
					
						
							|  |  |  |         while (n->card != -1) { | 
					
						
							|  |  |  |             gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), n->name); | 
					
						
							|  |  |  |             n++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* Select the first codec */ | 
					
						
							|  |  |  |         if (ui->sysfs_codec_names->card != -1) { | 
					
						
							|  |  |  |             gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); | 
					
						
							|  |  |  |             g_signal_connect(combo, "changed", G_CALLBACK(codec_selected), ui); | 
					
						
							|  |  |  |             gtk_container_add(GTK_CONTAINER(box), gtk_label_new("Select a codec:")); | 
					
						
							|  |  |  |             gtk_container_add(GTK_CONTAINER(box), combo); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             gtk_container_add(GTK_CONTAINER(box), gtk_label_new("No codecs found. Sorry.")); | 
					
						
							|  |  |  |             gtk_widget_destroy(combo); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         gtk_container_add(toplevel_box, box); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Add pin content area */ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         GtkWidget* frame = gtk_frame_new("Pin configuration"); | 
					
						
							|  |  |  |         GtkScrolledWindow* content_scroll = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL)); | 
					
						
							|  |  |  |         ui->content_scroll_widget = GTK_WIDGET(content_scroll); | 
					
						
							|  |  |  |         gtk_frame_set_label_align(GTK_FRAME(frame), 0.5, 0.5); | 
					
						
							|  |  |  |         gtk_scrolled_window_add_with_viewport(content_scroll, ui->content_inner_box); | 
					
						
							|  |  |  |         gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(content_scroll)); | 
					
						
							|  |  |  |         gtk_container_add(toplevel_2ndbox, frame); | 
					
						
							|  |  |  |         gtk_box_set_child_packing(GTK_BOX(toplevel_2ndbox), frame, TRUE, TRUE, 2, GTK_PACK_START); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Create settings */ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         GtkWidget* frame = gtk_frame_new("Options"); | 
					
						
							|  |  |  |         GtkContainer* box = GTK_CONTAINER(gtk_button_box_new(GTK_ORIENTATION_VERTICAL)); | 
					
						
							|  |  |  |         GtkWidget* check; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         check = gtk_check_button_new_with_label("Show unconnected pins"); | 
					
						
							|  |  |  |         g_signal_connect(check, "toggled", G_CALLBACK(showallpins_toggled), ui); | 
					
						
							|  |  |  |         gtk_container_add(box, check); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         check = gtk_check_button_new_with_label("Set model=auto"); | 
					
						
							|  |  |  |         g_signal_connect(check, "toggled", G_CALLBACK(automodel_toggled), ui); | 
					
						
							|  |  |  |         gtk_container_add(box, check); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         check = gtk_check_button_new_with_label("Advanced override"); | 
					
						
							|  |  |  |         g_signal_connect(check, "toggled", G_CALLBACK(free_override_toggled), ui); | 
					
						
							|  |  |  |         gtk_container_add(box, check); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(box)); | 
					
						
							|  |  |  |         gtk_container_add(rightside_box, frame); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Create bottom right buttons */ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         GtkWidget* button; | 
					
						
							|  |  |  |         GtkWidget* box = gtk_button_box_new(GTK_ORIENTATION_VERTICAL); | 
					
						
							|  |  |  |         button = gtk_button_new_with_label("Read documentation"); | 
					
						
							|  |  |  |         g_signal_connect(button, "clicked", G_CALLBACK(documentation_clicked), ui); | 
					
						
							|  |  |  |         gtk_container_add(GTK_CONTAINER(box), button); | 
					
						
							|  |  |  |         button = gtk_button_new_with_label("Apply now"); | 
					
						
							|  |  |  |         g_signal_connect(button, "clicked", G_CALLBACK(apply_now_clicked), ui); | 
					
						
							|  |  |  |         gtk_container_add(GTK_CONTAINER(box), button); | 
					
						
							|  |  |  |         button = gtk_button_new_with_label("Install boot override"); | 
					
						
							|  |  |  |         g_signal_connect(button, "clicked", G_CALLBACK(apply_boot_clicked), ui); | 
					
						
							|  |  |  |         gtk_container_add(GTK_CONTAINER(box), button); | 
					
						
							|  |  |  |         button = gtk_button_new_with_label("Remove boot override"); | 
					
						
							|  |  |  |         g_signal_connect(button, "clicked", G_CALLBACK(reset_boot_clicked), ui); | 
					
						
							|  |  |  |         gtk_container_add(GTK_CONTAINER(box), button); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         gtk_container_add(rightside_box, box); | 
					
						
							|  |  |  |         gtk_box_set_child_packing(GTK_BOX(rightside_box), box, FALSE, FALSE, 2, GTK_PACK_END); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     gtk_container_add(toplevel_2ndbox, GTK_WIDGET(rightside_box)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gtk_container_add(GTK_CONTAINER(toplevel_box), GTK_WIDGET(toplevel_2ndbox)); | 
					
						
							|  |  |  |     gtk_box_set_child_packing(GTK_BOX(toplevel_box), GTK_WIDGET(toplevel_2ndbox), TRUE, TRUE, 2, GTK_PACK_END); | 
					
						
							|  |  |  |     gtk_container_add(GTK_CONTAINER(ui->main_window), GTK_WIDGET(toplevel_box)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ui; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int main(int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ui_data_t* ui; | 
					
						
							|  |  |  |     gtk_init(&argc, &argv); | 
					
						
							|  |  |  |     ui = create_ui(); | 
					
						
							|  |  |  |     gtk_widget_show_all(ui->main_window); | 
					
						
							|  |  |  |     if (ui->codec_selection_combo) | 
					
						
							| 
									
										
										
										
											2013-03-04 15:10:48 +01:00
										 |  |  |         update_codec_ui(ui, true); | 
					
						
							| 
									
										
										
										
											2012-03-22 17:47:02 +01:00
										 |  |  |     gtk_main(); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } |