[gnome-color-manager] Add some initial code to support calibration of devices. It's pretty raw at the moment



commit aa4f26f96d0fcb47f2647c7a3bee00cfad48de53
Author: Richard Hughes <richard hughsie com>
Date:   Thu Oct 29 22:39:16 2009 +0000

    Add some initial code to support calibration of devices. It's pretty raw at the moment

 data/Makefile.am    |    1 +
 data/gcm-import.ui  |  181 ++++++++++++++++++++++
 data/gcm-prefs.ui   |    1 -
 src/gcm-calibrate.c |  419 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/gcm-calibrate.h |    5 +-
 src/gcm-prefs.c     |   67 ++++++++-
 6 files changed, 667 insertions(+), 7 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index deaa1bc..2719f88 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -15,6 +15,7 @@ desktop_in_files =					\
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 
 pkgdata_DATA =						\
+	gcm-import.ui					\
 	gcm-prefs.ui
 
 EXTRA_DIST =						\
diff --git a/data/gcm-import.ui b/data/gcm-import.ui
new file mode 100644
index 0000000..38dcef8
--- /dev/null
+++ b/data/gcm-import.ui
@@ -0,0 +1,181 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkDialog" id="dialog_calibrate">
+    <property name="border_width">5</property>
+    <property name="type_hint">normal</property>
+    <property name="has_separator">False</property>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="spacing">12</property>
+            <child>
+              <object class="GtkVBox" id="vbox2">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkImage" id="image1">
+                    <property name="visible">True</property>
+                    <property name="stock">gtk-dialog-info</property>
+                    <property name="icon-size">6</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="vbox1">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">9</property>
+                <child>
+                  <object class="GtkHBox" id="hbox2">
+                    <property name="visible">True</property>
+                    <child>
+                      <object class="GtkLabel" id="label_title">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">&lt;big&gt;&lt;b&gt;Title&lt;/b&gt;&lt;/big&gt;</property>
+                        <property name="use_markup">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkVBox" id="vbox_contents">
+                    <property name="visible">True</property>
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <object class="GtkHBox" id="hbox3">
+                        <property name="visible">True</property>
+                        <child>
+                          <object class="GtkLabel" id="label_message">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">Message</property>
+                            <property name="wrap">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkExpander" id="expander_details">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <child>
+                          <object class="GtkVBox" id="vbox_details">
+                            <property name="visible">True</property>
+                            <property name="orientation">vertical</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                        </child>
+                        <child type="label">
+                          <object class="GtkLabel" id="label1">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">&lt;b&gt;Details&lt;/b&gt;</property>
+                            <property name="use_markup">True</property>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="button_cancel">
+                <property name="label">gtk-cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button_ok">
+                <property name="label">gtk-ok</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">button_cancel</action-widget>
+      <action-widget response="0">button_ok</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/data/gcm-prefs.ui b/data/gcm-prefs.ui
index 2f07161..234f1c8 100644
--- a/data/gcm-prefs.ui
+++ b/data/gcm-prefs.ui
@@ -295,7 +295,6 @@
                       <object class="GtkButton" id="button_calibrate">
                         <property name="label" translatable="yes">_Calibrate</property>
                         <property name="visible">True</property>
-                        <property name="sensitive">False</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">True</property>
                         <property name="use_underline">True</property>
diff --git a/src/gcm-calibrate.c b/src/gcm-calibrate.c
index 7dd5cf5..d0aedb0 100644
--- a/src/gcm-calibrate.c
+++ b/src/gcm-calibrate.c
@@ -28,9 +28,13 @@
 
 #include "config.h"
 
-#include <glib-object.h>
+#include <glib/gi18n.h>
 #include <math.h>
+#include <string.h>
 #include <gio/gio.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <vte/vte.h>
 
 #include "gcm-calibrate.h"
 
@@ -49,7 +53,14 @@ struct _GcmCalibratePrivate
 {
 	gboolean			 is_lcd;
 	gboolean			 is_crt;
+	guint				 display;
 	gchar				*output_name;
+	gchar				*basename;
+	GMainLoop			*loop;
+	GtkWidget			*terminal;
+	GtkBuilder			*builder;
+	pid_t				 child_pid;
+	GtkResponseType			 response;
 };
 
 enum {
@@ -63,19 +74,367 @@ enum {
 G_DEFINE_TYPE (GcmCalibrate, gcm_calibrate, G_TYPE_OBJECT)
 
 /**
- * gcm_calibrate_run_task:
+ * gcm_calibrate_get_display:
+ **/
+static guint
+gcm_calibrate_get_display (const gchar *output_name, GError **error)
+{
+	gboolean ret;
+	gchar *data = NULL;
+	gchar **split = NULL;
+	gint exit_status;
+	guint display = G_MAXUINT;
+	guint i;
+	gchar *name;
+
+	/* execute it and capture stderr */
+	ret = g_spawn_command_line_sync ("dispcal", NULL, &data, &exit_status, error);
+	if (!ret)
+		goto out;
+
+	/* split it into lines */
+	split = g_strsplit (data, "\n", -1);
+	for (i=0; split[i] != NULL; i++) {
+		name = g_strdup (split[i]);
+		g_strdelimit (name, " ", '\0');
+		if (g_strcmp0 (output_name, &name[26]) == 0) {
+			display = atoi (&name[4]);
+			egg_debug ("found %s mapped to %i", output_name, display);
+		}
+		g_free (name);
+	}
+
+	/* nothing found */
+	if (display == G_MAXUINT) {
+		if (error != NULL)
+			*error = g_error_new (1, 0, "failed to match display");
+	}
+out:
+	g_free (data);
+	g_strfreev (split);
+	return display;
+}
+
+/**
+ * gcm_calibrate_get_display_type:
+ **/
+static gchar
+gcm_calibrate_get_display_type (GcmCalibrate *calibrate)
+{
+	GcmCalibratePrivate *priv = calibrate->priv;
+	if (priv->is_lcd)
+		return 'l';
+	if (priv->is_crt)
+		return 'c';
+	return '\0';
+}
+
+/**
+ * gcm_calibrate_set_title:
+ **/
+static void
+gcm_calibrate_set_title (GcmCalibrate *calibrate, const gchar *title)
+{
+	GcmCalibratePrivate *priv = calibrate->priv;
+	GtkWidget *widget;
+	gchar *text;
+
+	/* set the text */
+	text = g_strdup_printf ("<big><b>%s</b></big>", title);
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_title"));
+	gtk_label_set_markup (GTK_LABEL(widget), text);
+	g_free (text);
+}
+
+/**
+ * gcm_calibrate_set_message:
+ **/
+static void
+gcm_calibrate_set_message (GcmCalibrate *calibrate, const gchar *title)
+{
+	GcmCalibratePrivate *priv = calibrate->priv;
+	GtkWidget *widget;
+	gchar *text;
+
+	/* set the text */
+	text = g_strdup_printf ("%s", title);
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "label_message"));
+	gtk_label_set_markup (GTK_LABEL(widget), text);
+	g_free (text);
+}
+
+/**
+ * gcm_calibrate_setup:
  **/
 gboolean
-gcm_calibrate_run_task (GcmCalibrate *calibrate, GcmCalibrateTask task, GError **error)
+gcm_calibrate_setup (GcmCalibrate *calibrate, GtkWindow *window, GError **error)
+{
+	GtkWidget *widget;
+	GcmCalibratePrivate *priv = calibrate->priv;
+	GtkWidget *dialog;
+	GtkResponseType response;
+	gboolean ret = TRUE;
+
+	/* show main UI */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_calibrate"));
+	gtk_widget_show_all (widget);
+	if (window != NULL)
+		gdk_window_set_transient_for (gtk_widget_get_window (widget), gtk_widget_get_window (GTK_WIDGET(window)));
+
+	/* setup GUI */
+	gcm_calibrate_set_title (calibrate, _("Setup hardware"));
+	gcm_calibrate_set_message (calibrate, _("Setting up hardware device for use..."));
+
+	/* this wasn't previously set */
+	if (!priv->is_lcd && !priv->is_crt) {
+		dialog = gtk_message_dialog_new (GTK_WINDOW(widget), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_CANCEL,
+						 _("Could not auto-detect CRT or LCD"));
+		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("Please indicate if the screen you are trying to profile is a CRT (old type) or a LCD (digital flat panel)."));
+		gtk_dialog_add_button (GTK_DIALOG (dialog), _("LCD"), GTK_RESPONSE_YES);
+		gtk_dialog_add_button (GTK_DIALOG (dialog), _("CRT"), GTK_RESPONSE_NO);
+		response = gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+		if (response == GTK_RESPONSE_YES) {
+			g_object_set (calibrate,
+				      "is-lcd", TRUE,
+				      NULL);
+		} else if (response == GTK_RESPONSE_NO) {
+			g_object_set (calibrate,
+				      "is-crt", TRUE,
+				      NULL);
+		} else {
+			if (error != NULL)
+				*error = g_error_new (1, 0, "user did not choose crt or lcd");
+			ret = FALSE;
+			goto out;
+		}
+	}
+out:
+	return ret;
+}
+
+/**
+ * gcm_calibrate_task_neutralise:
+ **/
+static gboolean
+gcm_calibrate_task_neutralise (GcmCalibrate *calibrate, GError **error)
+{
+	gboolean ret = TRUE;
+	GcmCalibratePrivate *priv = calibrate->priv;
+	gchar type;
+	gchar *cmd = NULL;
+	gchar **argc = NULL;
+	GtkWidget *widget;
+	GtkWidget *dialog;
+	GtkResponseType response;
+
+	/* match up the output name with the device number defined by dispcal */
+	priv->display = gcm_calibrate_get_display (priv->output_name, error);
+	if (priv->display == G_MAXUINT)
+		goto out;
+
+	/* get l-cd or c-rt */
+	type = gcm_calibrate_get_display_type (calibrate);
+
+	/* TODO: choose a better filename, maybe based on the monitor serial number */
+	priv->basename = g_strdup ("basename");
+
+	/* setup the command */
+	cmd = g_strdup_printf ("dispcal -v -ql -m -d%i -y%c %s", priv->display, type, priv->basename);
+	argc = g_strsplit (cmd, " ", -1);
+	egg_debug ("running %s", cmd);
+
+	/* start up the command */
+	priv->child_pid = vte_terminal_fork_command (VTE_TERMINAL(priv->terminal), argc[0], &argc[1], NULL, "/tmp", FALSE, FALSE, FALSE);
+
+	/* ask user to attach device */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_calibrate"));
+	dialog = gtk_message_dialog_new (GTK_WINDOW(widget), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK_CANCEL,
+					 _("Please attach device"));
+	gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("Please attach the hardware device to the center of the screen on the grey square."));
+	response = gtk_dialog_run (GTK_DIALOG (dialog));
+	gtk_widget_destroy (dialog);
+	if (response != GTK_RESPONSE_OK) {
+		vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), "Q", 1);
+		if (error != NULL)
+			*error = g_error_new (1, 0, "user did not attach hardware device");
+		ret = FALSE;
+		goto out;
+	}
+
+	/* send the terminal an okay */
+	vte_terminal_feed_child (VTE_TERMINAL(priv->terminal), " ", 1);
+
+	/* setup GUI */
+	gcm_calibrate_set_title (calibrate, _("Resetting screen to neutral state"));
+	gcm_calibrate_set_message (calibrate, _("This brings the screen to a neutral state by sending colored and gray patches to your screen and measuring them with the hardware device."));
+
+	/* wait until finished */
+	g_main_loop_run (priv->loop);
+out:
+	g_strfreev (argc);
+	g_free (cmd);
+	return ret;
+}
+
+/**
+ * gcm_calibrate_timeout_cb:
+ **/
+static gboolean
+gcm_calibrate_timeout_cb (GcmCalibrate *calibrate)
+{
+	vte_terminal_feed_child (VTE_TERMINAL(calibrate->priv->terminal), " ", 1);
+	return FALSE;
+}
+
+/**
+ * gcm_calibrate_task_generate_patches:
+ **/
+static gboolean
+gcm_calibrate_task_generate_patches (GcmCalibrate *calibrate, GError **error)
 {
 	gboolean ret = TRUE;
+	GcmCalibratePrivate *priv = calibrate->priv;
+	gchar type;
+	gchar *cmd = NULL;
+	gchar **argc = NULL;
+
+	/* get l-cd or c-rt */
+	type = gcm_calibrate_get_display_type (calibrate);
+
+	/* setup the command */
+	cmd = g_strdup_printf ("targen -v -d3 -f250 %s", priv->basename);
+	argc = g_strsplit (cmd, " ", -1);
+	egg_debug ("running %s", cmd);
+
+	/* start up the command */
+	priv->child_pid = vte_terminal_fork_command (VTE_TERMINAL(priv->terminal), argc[0], &argc[1], NULL, "/tmp", FALSE, FALSE, FALSE);
+	g_timeout_add_seconds (3, (GSourceFunc) gcm_calibrate_timeout_cb, calibrate);
+
+	/* setup GUI */
+	gcm_calibrate_set_title (calibrate, _("Generating the patches"));
+	gcm_calibrate_set_message (calibrate, _("Generating the patches that will be measured with the hardware device."));
+
+	/* wait until finished */
+	g_main_loop_run (priv->loop);
+
+	g_strfreev (argc);
+	g_free (cmd);
+	return ret;
+}
+
+/**
+ * gcm_calibrate_task_draw_and_measure:
+ **/
+static gboolean
+gcm_calibrate_task_draw_and_measure (GcmCalibrate *calibrate, GError **error)
+{
+	gboolean ret = TRUE;
+	GcmCalibratePrivate *priv = calibrate->priv;
+	gchar type;
+	gchar *cmd = NULL;
+	gchar **argc = NULL;
+
+	/* get l-cd or c-rt */
+	type = gcm_calibrate_get_display_type (calibrate);
+
+	/* setup the command */
+	cmd = g_strdup_printf ("dispread -v -d%i -y%c -k %s.cal %s", priv->display, type, priv->basename, priv->basename);
+	argc = g_strsplit (cmd, " ", -1);
+	egg_debug ("running %s", cmd);
+
+	/* start up the command */
+	priv->child_pid = vte_terminal_fork_command (VTE_TERMINAL(priv->terminal), argc[0], &argc[1], NULL, "/tmp", FALSE, FALSE, FALSE);
+
+	/* setup GUI */
+	gcm_calibrate_set_title (calibrate, _("Drawing the patches"));
+	gcm_calibrate_set_message (calibrate, _("Drawing the generated patches to the screen, which will then be measured by the hardware device."));
+
+	/* wait until finished */
+	g_main_loop_run (priv->loop);
+
+	g_strfreev (argc);
+	g_free (cmd);
+	return ret;
+}
+
+/**
+ * gcm_calibrate_task_generate_profile:
+ **/
+static gboolean
+gcm_calibrate_task_generate_profile (GcmCalibrate *calibrate, GError **error)
+{
+	gboolean ret = TRUE;
+	GcmCalibratePrivate *priv = calibrate->priv;
+	gchar type;
+	gchar *cmd = NULL;
+	gchar **argc = NULL;
+
+	/* get l-cd or c-rt */
+	type = gcm_calibrate_get_display_type (calibrate);
+
+	/* setup the command */
+	cmd = g_strdup_printf ("colprof -A \"LG\" -M \"LG Flatpanel\" -D \"October 29 2009\" -q m -as %s", priv->basename);
+
+	argc = g_strsplit (cmd, " ", -1);
+	egg_debug ("running %s", cmd);
+
+	/* start up the command */
+	priv->child_pid = vte_terminal_fork_command (VTE_TERMINAL(priv->terminal), argc[0], &argc[1], NULL, "/tmp", FALSE, FALSE, FALSE);
+
+	/* setup GUI */
+	gcm_calibrate_set_title (calibrate, _("Generating the profile"));
+	gcm_calibrate_set_message (calibrate, _("Generating the ICC color profile that can be used with this screen."));
+
+	/* wait until finished */
+	g_main_loop_run (priv->loop);
+
+	g_strfreev (argc);
+	g_free (cmd);
+	return ret;
+}
+
+/**
+ * gcm_calibrate_task:
+ **/
+gboolean
+gcm_calibrate_task (GcmCalibrate *calibrate, GcmCalibrateTask task, GError **error)
+{
+	gboolean ret = FALSE;
 
 	g_return_val_if_fail (GCM_IS_CALIBRATE (calibrate), FALSE);
 
+	/* each option */
+	if (task == GCM_CALIBRATE_TASK_NEUTRALISE) {
+		ret = gcm_calibrate_task_neutralise (calibrate, error);
+		goto out;
+	}
+	if (task == GCM_CALIBRATE_TASK_GENERATE_PATCHES) {
+		ret = gcm_calibrate_task_generate_patches (calibrate, error);
+		goto out;
+	}
+	if (task == GCM_CALIBRATE_TASK_DRAW_AND_MEASURE) {
+		ret = gcm_calibrate_task_draw_and_measure (calibrate, error);
+		goto out;
+	}
+	if (task == GCM_CALIBRATE_TASK_GENERATE_PROFILE) {
+		ret = gcm_calibrate_task_generate_profile (calibrate, error);
+		goto out;
+	}
+out:
 	return ret;
 }
 
 /**
+ * gcm_calibrate_exit_cb:
+ **/
+static void
+gcm_calibrate_exit_cb (VteTerminal *terminal, GcmCalibrate *calibrate)
+{
+	g_main_loop_quit (calibrate->priv->loop);
+}
+
+/**
  * gcm_calibrate_get_property:
  **/
 static void
@@ -101,6 +460,25 @@ gcm_calibrate_get_property (GObject *object, guint prop_id, GValue *value, GPara
 }
 
 /**
+ * gcm_calibrate_guess_type:
+ **/
+static void
+gcm_calibrate_guess_type (GcmCalibrate *calibrate)
+{
+	GcmCalibratePrivate *priv = calibrate->priv;
+
+	/* guess based on the output name */
+	if (strstr (priv->output_name, "DVI") != NULL ||
+	    strstr (priv->output_name, "LVDS") != NULL) {
+		priv->is_lcd = TRUE;
+		priv->is_crt = FALSE;
+	} else {
+		priv->is_lcd = FALSE;
+		priv->is_crt = FALSE;
+	}
+}
+
+/**
  * gcm_calibrate_set_property:
  **/
 static void
@@ -119,6 +497,7 @@ gcm_calibrate_set_property (GObject *object, guint prop_id, const GValue *value,
 	case PROP_OUTPUT_NAME:
 		g_free (priv->output_name);
 		priv->output_name = g_strdup (g_value_get_string (value));
+		gcm_calibrate_guess_type (calibrate);
 		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -171,8 +550,30 @@ gcm_calibrate_class_init (GcmCalibrateClass *klass)
 static void
 gcm_calibrate_init (GcmCalibrate *calibrate)
 {
+	gint retval;
+	GError *error = NULL;
+	GtkWidget *widget;
+
 	calibrate->priv = GCM_CALIBRATE_GET_PRIVATE (calibrate);
 	calibrate->priv->output_name = NULL;
+	calibrate->priv->basename = NULL;
+	calibrate->priv->loop = g_main_loop_new (NULL, FALSE);
+
+	/* get UI */
+	calibrate->priv->builder = gtk_builder_new ();
+	retval = gtk_builder_add_from_file (calibrate->priv->builder, GCM_DATA "/gcm-import.ui", &error);
+	if (retval == 0) {
+		egg_warning ("failed to load ui: %s", error->message);
+		g_error_free (error);
+	}
+
+	/* add vte widget */
+	calibrate->priv->terminal = vte_terminal_new ();
+	vte_terminal_set_size (VTE_TERMINAL(calibrate->priv->terminal), 40, 10);
+	g_signal_connect (calibrate->priv->terminal, "child-exited",
+			  G_CALLBACK (gcm_calibrate_exit_cb), calibrate);
+	widget = GTK_WIDGET (gtk_builder_get_object (calibrate->priv->builder, "vbox_details"));
+	gtk_box_pack_end (GTK_BOX(widget), calibrate->priv->terminal, TRUE, TRUE, 6);
 }
 
 /**
@@ -181,10 +582,22 @@ gcm_calibrate_init (GcmCalibrate *calibrate)
 static void
 gcm_calibrate_finalize (GObject *object)
 {
+	GtkWidget *widget;
 	GcmCalibrate *calibrate = GCM_CALIBRATE (object);
 	GcmCalibratePrivate *priv = calibrate->priv;
 
+	/* wait until finished */
+	if (g_main_loop_is_running (priv->loop))
+		g_main_loop_quit (priv->loop);
+
+	/* hide window */
+	widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "dialog_calibrate"));
+	gtk_widget_hide (widget);
+
 	g_free (priv->output_name);
+	g_free (priv->basename);
+	g_main_loop_unref (priv->loop);
+	g_object_unref (priv->builder);
 
 	G_OBJECT_CLASS (gcm_calibrate_parent_class)->finalize (object);
 }
diff --git a/src/gcm-calibrate.h b/src/gcm-calibrate.h
index 091d4a1..1b8f6d4 100644
--- a/src/gcm-calibrate.h
+++ b/src/gcm-calibrate.h
@@ -64,7 +64,10 @@ typedef enum {
 
 GType		 gcm_calibrate_get_type		  	(void);
 GcmCalibrate	*gcm_calibrate_new			(void);
-gboolean	 gcm_calibrate_run_task			(GcmCalibrate		*calibrate,
+gboolean	 gcm_calibrate_setup			(GcmCalibrate		*calibrate,
+							 GtkWindow		*window,
+							 GError			**error);
+gboolean	 gcm_calibrate_task			(GcmCalibrate		*calibrate,
 							 GcmCalibrateTask	 task,
 							 GError			**error);
 
diff --git a/src/gcm-prefs.c b/src/gcm-prefs.c
index a83f28a..4ff52b3 100644
--- a/src/gcm-prefs.c
+++ b/src/gcm-prefs.c
@@ -28,6 +28,7 @@
 
 #include "gcm-utils.h"
 #include "gcm-profile.h"
+#include "gcm-calibrate.h"
 
 static GtkBuilder *builder = NULL;
 static GtkListStore *list_store_devices = NULL;
@@ -74,6 +75,67 @@ gcm_prefs_help_cb (GtkWidget *widget, gpointer data)
 }
 
 /**
+ * gcm_prefs_calibrate_cb:
+ **/
+static void
+gcm_prefs_calibrate_cb (GtkWidget *widget, gpointer data)
+{
+	GcmCalibrate *calib;
+	gboolean ret;
+	GError *error = NULL;
+	GtkWindow *window;
+
+	calib = gcm_calibrate_new ();
+	g_object_set (calib,
+		      "output-name", "LVDS1",
+	//	      "output-name", "DVI1",
+		      NULL);
+
+	/* run each task in order */
+	window = GTK_WINDOW(gtk_builder_get_object (builder, "dialog_prefs"));
+	ret = gcm_calibrate_setup (calib, window, &error);
+	if (!ret) {
+		egg_warning ("failed to setup: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* step 1 */
+	ret = gcm_calibrate_task (calib, GCM_CALIBRATE_TASK_NEUTRALISE, &error);
+	if (!ret) {
+		egg_warning ("failed to calibrate: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* step 2 */
+	ret = gcm_calibrate_task (calib, GCM_CALIBRATE_TASK_GENERATE_PATCHES, &error);
+	if (!ret) {
+		egg_warning ("failed to calibrate: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* step 3 */
+	ret = gcm_calibrate_task (calib, GCM_CALIBRATE_TASK_DRAW_AND_MEASURE, &error);
+	if (!ret) {
+		egg_warning ("failed to calibrate: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* step 4 */
+	ret = gcm_calibrate_task (calib, GCM_CALIBRATE_TASK_GENERATE_PROFILE, &error);
+	if (!ret) {
+		egg_warning ("failed to calibrate: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+out:
+	g_object_unref (calib);
+}
+
+/**
  * gcm_prefs_reset_cb:
  **/
 static void
@@ -461,10 +523,8 @@ out:
 int
 main (int argc, char **argv)
 {
-//	gboolean ret;
 	gboolean verbose = FALSE;
 	guint retval = 0;
-//	GError *error = NULL;
 	GOptionContext *context;
 	GtkWidget *main_window;
 	GtkWidget *widget;
@@ -550,6 +610,9 @@ main (int argc, char **argv)
 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_reset"));
 	g_signal_connect (widget, "clicked",
 			  G_CALLBACK (gcm_prefs_reset_cb), NULL);
+	widget = GTK_WIDGET (gtk_builder_get_object (builder, "button_calibrate"));
+	g_signal_connect (widget, "clicked",
+			  G_CALLBACK (gcm_prefs_calibrate_cb), NULL);
 
 	/* setup icc profiles list */
 	widget = GTK_WIDGET (gtk_builder_get_object (builder, "combobox_profile"));



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]