/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2010-2011 Richard Hughes * * Licensed under the GNU General Public License Version 2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include "cd-client-sync.h" #include "cd-device-sync.h" #include "cd-enum.h" #include "cd-profile-sync.h" #include "cd-sensor-sync.h" typedef struct { CdClient *client; GOptionContext *context; GPtrArray *cmd_array; } CdUtilPrivate; typedef gboolean (*CdUtilPrivateCb) (CdUtilPrivate *util, gchar **values, GError **error); typedef struct { gchar *name; gchar *description; CdUtilPrivateCb callback; } CdUtilItem; /** * cd_util_print_field: **/ static void cd_util_print_field (const gchar *title, const gchar *message) { const guint padding = 15; guint i; guint len = 0; /* nothing useful to print */ if (message == NULL || message[0] == '\0') return; if (title != NULL) { g_print ("%s:", title); len = strlen (title) + 1; } for (i = len; i < padding; i++) g_print (" "); g_print ("%s\n", message); } /** * cd_util_print_field_time: **/ static void cd_util_print_field_time (const gchar *title, gint64 usecs) { gchar *str; GDateTime *datetime; datetime = g_date_time_new_from_unix_utc (usecs / G_USEC_PER_SEC); /* TRANSLATORS: this is the profile creation date strftime format */ str = g_date_time_format (datetime, _("%B %e %Y, %I:%M:%S %p")); cd_util_print_field (title, str); g_date_time_unref (datetime); g_free (str); } /** * cd_util_show_owner: **/ static void cd_util_show_owner (guint uid) { struct passwd *pw; pw = getpwuid (uid); /* TRANSLATORS: profile owner */ cd_util_print_field (_("Owner"), pw->pw_name); } /** * cd_util_show_profile: **/ static void cd_util_show_profile (CdProfile *profile) { CdColorspace colorspace; CdObjectScope scope; CdProfileKind kind; const gchar *tmp; gchar *str_tmp; GHashTable *metadata; GList *list, *l; /* TRANSLATORS: the internal DBus path */ cd_util_print_field (_("Object Path"), cd_profile_get_object_path (profile)); cd_util_show_owner (cd_profile_get_owner (profile)); tmp = cd_profile_get_format (profile); if (tmp != NULL && tmp[0] != '\0') { /* TRANSLATORS: the profile format, e.g. * ColorModel.OutputMode.OutputResolution */ cd_util_print_field (_("Format"), tmp); } tmp = cd_profile_get_title (profile); if (tmp != NULL && tmp[0] != '\0') { /* TRANSLATORS: the profile title, e.g. * "ColorMunki, HP Deskjet d1300 Series" */ cd_util_print_field (_("Title"), tmp); } tmp = cd_profile_get_qualifier (profile); if (tmp != NULL && tmp[0] != '\0') { /* TRANSLATORS: the profile qualifier, e.g. RGB.Plain.300dpi */ cd_util_print_field (_("Qualifier"), tmp); } kind = cd_profile_get_kind (profile); if (kind != CD_PROFILE_KIND_UNKNOWN) { /* TRANSLATORS: the profile type, e.g. 'output' */ cd_util_print_field (_("Type"), cd_profile_kind_to_string (kind)); } colorspace = cd_profile_get_colorspace (profile); if (colorspace != CD_COLORSPACE_UNKNOWN) { /* TRANSLATORS: the profile colorspace, e.g. 'rgb' */ cd_util_print_field (_("Colorspace"), cd_colorspace_to_string (colorspace)); } scope = cd_profile_get_scope (profile); if (scope != CD_OBJECT_SCOPE_UNKNOWN) { /* TRANSLATORS: the object scope, e.g. temp, disk, etc */ cd_util_print_field (_("Scope"), cd_object_scope_to_string (scope)); } /* TRANSLATORS: if the profile has a Video Card Gamma Table lookup */ cd_util_print_field (_("Gamma Table"), cd_profile_get_has_vcgt (profile) ? "Yes" : "No"); /* TRANSLATORS: profile filename */ cd_util_print_field (_("Filename"), cd_profile_get_filename (profile)); /* TRANSLATORS: profile identifier */ cd_util_print_field (_("Profile ID"), cd_profile_get_id (profile)); /* list all the items of metadata */ metadata = cd_profile_get_metadata (profile); list = g_hash_table_get_keys (metadata); for (l = list; l != NULL; l = l->next) { if (g_strcmp0 (l->data, "CMS") == 0) continue; tmp = (const gchar *) g_hash_table_lookup (metadata, l->data); str_tmp = g_strdup_printf ("%s=%s", (const gchar *) l->data, tmp); /* TRANSLATORS: the metadata for the device */ cd_util_print_field (_("Metadata"), str_tmp); g_free (str_tmp); } g_list_free (list); g_hash_table_unref (metadata); } /** * cd_util_show_device: **/ static void cd_util_show_device (CdDevice *device) { CdObjectScope scope; CdProfile *profile_tmp; const gchar *tmp; gboolean ret; gchar *str_tmp; GError *error = NULL; GHashTable *metadata; GList *list, *l; GPtrArray *profiles; guint i; /* TRANSLATORS: the internal DBus path */ cd_util_print_field (_("Object Path"), cd_device_get_object_path (device)); cd_util_show_owner (cd_device_get_owner (device)); /* TRANSLATORS: this is the time the device was registered * with colord, and probably is the same as the system startup * unless the device has been explicitly saved in the database */ cd_util_print_field_time (_("Created"), cd_device_get_created (device)); /* TRANSLATORS: this is the time of the last calibration or when * the manufacturer-provided profile was assigned by the user */ cd_util_print_field_time (_("Modified"), cd_device_get_modified (device)); /* TRANSLATORS: the device type, e.g. "printer" */ cd_util_print_field (_("Type"), cd_device_kind_to_string (cd_device_get_kind (device))); /* TRANSLATORS: the device model */ cd_util_print_field (_("Model"), cd_device_get_model (device)); /* TRANSLATORS: the device vendor */ cd_util_print_field (_("Vendor"), cd_device_get_vendor (device)); /* TRANSLATORS: the device inhibitors */ str_tmp = g_strjoinv (", ", (gchar **) cd_device_get_profiling_inhibitors (device)); cd_util_print_field (_("Inhibitors"), str_tmp); g_free (str_tmp); /* TRANSLATORS: the device serial number */ cd_util_print_field (_("Serial"), cd_device_get_serial (device)); tmp = cd_device_get_format (device); if (tmp != NULL && tmp[0] != '\0') { /* TRANSLATORS: the device format, e.g. * ColorModel.OutputMode.OutputResolution */ cd_util_print_field (_("Format"), tmp); } scope = cd_device_get_scope (device); if (scope != CD_OBJECT_SCOPE_UNKNOWN) { /* TRANSLATORS: the object scope, e.g. temp, disk, etc */ cd_util_print_field (_("Scope"), cd_object_scope_to_string (scope)); } /* TRANSLATORS: the device colorspace, e.g. "rgb" */ cd_util_print_field (_("Colorspace"), cd_colorspace_to_string (cd_device_get_colorspace (device))); /* TRANSLATORS: the device identifier */ cd_util_print_field (_("Device ID"), cd_device_get_id (device)); /* print profiles */ profiles = cd_device_get_profiles (device); for (i=0; ilen; i++) { profile_tmp = g_ptr_array_index (profiles, i); /* TRANSLATORS: the profile for the device */ str_tmp = g_strdup_printf ("%s %i", _("Profile"), i+1); ret = cd_profile_connect_sync (profile_tmp, NULL, &error); if (!ret) { cd_util_print_field (str_tmp, cd_profile_get_object_path (profile_tmp)); cd_util_print_field (NULL, error->message); g_clear_error (&error); } else { cd_util_print_field (str_tmp, cd_profile_get_id (profile_tmp)); cd_util_print_field (NULL, cd_profile_get_filename(profile_tmp)); } g_free (str_tmp); } /* list all the items of metadata */ metadata = cd_device_get_metadata (device); list = g_hash_table_get_keys (metadata); for (l = list; l != NULL; l = l->next) { tmp = (const gchar *) g_hash_table_lookup (metadata, l->data); str_tmp = g_strdup_printf ("%s=%s", (const gchar *) l->data, tmp); /* TRANSLATORS: the metadata for the device */ cd_util_print_field (_("Metadata"), str_tmp); g_free (str_tmp); } g_list_free (list); g_hash_table_unref (metadata); } /** * cd_util_idle_loop_quit_cb: **/ static gboolean cd_util_idle_loop_quit_cb (gpointer user_data) { GMainLoop *loop = (GMainLoop *) user_data; g_main_loop_quit (loop); return FALSE; } /** * cd_util_show_sensor: **/ static void cd_util_show_sensor (CdSensor *sensor) { CdSensorKind kind; CdSensorState state; const gchar *tmp; gboolean ret; gchar *str_tmp; GError *error = NULL; GHashTable *options = NULL; GList *l; GList *list = NULL; GMainLoop *loop = NULL; GVariant *value_tmp; /* TRANSLATORS: the internal DBus path */ cd_util_print_field (_("Object Path"), cd_sensor_get_object_path (sensor)); /* lock */ ret = cd_sensor_lock_sync (sensor, NULL, &error); if (!ret) { g_warning ("Failed to lock sensor: %s", error->message); g_error_free (error); goto out; } /* wait for updates */ loop = g_main_loop_new (NULL, FALSE); g_idle_add (cd_util_idle_loop_quit_cb, loop); g_main_loop_run (loop); kind = cd_sensor_get_kind (sensor); if (kind != CD_SENSOR_KIND_UNKNOWN) { /* TRANSLATORS: the sensor type, e.g. 'output' */ cd_util_print_field (_("Type"), cd_sensor_kind_to_string (kind)); } state = cd_sensor_get_state (sensor); if (state != CD_SENSOR_STATE_UNKNOWN) { /* TRANSLATORS: the sensor state, e.g. 'idle' */ cd_util_print_field (_("State"), cd_sensor_state_to_string (state)); } tmp = cd_sensor_get_serial (sensor); if (tmp != NULL) { /* TRANSLATORS: sensor serial */ cd_util_print_field (_("Serial number"), tmp); } tmp = cd_sensor_get_model (sensor); if (tmp != NULL) { /* TRANSLATORS: sensor model */ cd_util_print_field (_("Model"), tmp); } tmp = cd_sensor_get_vendor (sensor); if (tmp != NULL) { /* TRANSLATORS: sensor vendor */ cd_util_print_field (_("Vendor"), tmp); } /* print sensor options */ options = cd_sensor_get_options (sensor); list = g_hash_table_get_keys (options); for (l = list; l != NULL; l = l->next) { value_tmp = (GVariant *) g_hash_table_lookup (options, l->data); if (g_variant_is_of_type (value_tmp, G_VARIANT_TYPE_STRING)) { str_tmp = g_strdup_printf ("%s=%s", (const gchar *) l->data, g_variant_get_string (value_tmp, NULL)); } else { str_tmp = g_strdup_printf ("%s=*unknown*", (const gchar *) l->data); } /* TRANSLATORS: the options for the sensor */ cd_util_print_field (_("Options"), str_tmp); g_free (str_tmp); } /* TRANSLATORS: if the sensor has a colord native driver */ cd_util_print_field (_("Native"), cd_sensor_get_native (sensor) ? "Yes" : "No"); /* TRANSLATORS: if the sensor is locked */ cd_util_print_field (_("Locked"), cd_sensor_get_locked (sensor) ? "Yes" : "No"); /* TRANSLATORS: if the sensor supports calibrating an LCD display */ cd_util_print_field (_("LCD"), cd_sensor_has_cap (sensor, CD_SENSOR_CAP_LCD) ? "Yes" : "No"); /* TRANSLATORS: if the sensor supports calibrating a CRT display */ cd_util_print_field (_("CRT"), cd_sensor_has_cap (sensor, CD_SENSOR_CAP_CRT) ? "Yes" : "No"); /* TRANSLATORS: if the sensor supports calibrating a printer */ cd_util_print_field (_("Printer"), cd_sensor_has_cap (sensor, CD_SENSOR_CAP_PRINTER) ? "Yes" : "No"); /* TRANSLATORS: if the sensor supports spot measurements */ cd_util_print_field (_("Spot"), cd_sensor_has_cap (sensor, CD_SENSOR_CAP_SPOT) ? "Yes" : "No"); /* TRANSLATORS: if the sensor supports calibrating a projector */ cd_util_print_field (_("Projector"), cd_sensor_has_cap (sensor, CD_SENSOR_CAP_PROJECTOR) ? "Yes" : "No"); /* TRANSLATORS: if the sensor supports getting the ambient light level */ cd_util_print_field (_("Ambient"), cd_sensor_has_cap (sensor, CD_SENSOR_CAP_AMBIENT) ? "Yes" : "No"); /* unlock */ ret = cd_sensor_unlock_sync (sensor, NULL, &error); if (!ret) { g_warning ("Failed to unlock sensor: %s", error->message); g_error_free (error); goto out; } out: g_list_free (list); if (options != NULL) g_hash_table_unref (options); if (loop != NULL) g_main_loop_unref (loop); } /** * cd_util_item_free: **/ static void cd_util_item_free (CdUtilItem *item) { g_free (item->name); g_free (item->description); g_free (item); } /* * cd_sort_command_name_cb: */ static gint cd_sort_command_name_cb (CdUtilItem **item1, CdUtilItem **item2) { return g_strcmp0 ((*item1)->name, (*item2)->name); } /** * cd_util_add: **/ static void cd_util_add (GPtrArray *array, const gchar *name, const gchar *description, CdUtilPrivateCb callback) { gchar **names; guint i; CdUtilItem *item; /* add each one */ names = g_strsplit (name, ",", -1); for (i=0; names[i] != NULL; i++) { item = g_new0 (CdUtilItem, 1); item->name = g_strdup (names[i]); if (i == 0) { item->description = g_strdup (description); } else { /* TRANSLATORS: this is a command alias */ item->description = g_strdup_printf (_("Alias to %s"), names[0]); } item->callback = callback; g_ptr_array_add (array, item); } g_strfreev (names); } /** * cd_util_get_descriptions: **/ static gchar * cd_util_get_descriptions (GPtrArray *array) { guint i; guint j; guint len; guint max_len = 0; CdUtilItem *item; GString *string; /* get maximum command length */ for (i=0; ilen; i++) { item = g_ptr_array_index (array, i); len = strlen (item->name); if (len > max_len) max_len = len; } /* ensure we're spaced by at least this */ if (max_len < 19) max_len = 19; /* print each command */ string = g_string_new (""); for (i=0; ilen; i++) { item = g_ptr_array_index (array, i); g_string_append (string, " "); g_string_append (string, item->name); len = strlen (item->name); for (j=len; jdescription); g_string_append_c (string, '\n'); } /* remove trailing newline */ if (string->len > 0) g_string_set_size (string, string->len - 1); return g_string_free (string, FALSE); } /** * cd_util_run: **/ static gboolean cd_util_run (CdUtilPrivate *priv, const gchar *command, gchar **values, GError **error) { gboolean ret = FALSE; guint i; CdUtilItem *item; GString *string; /* find command */ for (i=0; icmd_array->len; i++) { item = g_ptr_array_index (priv->cmd_array, i); if (g_strcmp0 (item->name, command) == 0) { ret = item->callback (priv, values, error); goto out; } } /* not found */ string = g_string_new (""); /* TRANSLATORS: error message */ g_string_append_printf (string, "%s\n", _("Command not found, valid commands are:")); for (i=0; icmd_array->len; i++) { item = g_ptr_array_index (priv->cmd_array, i); g_string_append_printf (string, " * %s\n", item->name); } g_set_error_literal (error, 1, 0, string->str); g_string_free (string, TRUE); out: return ret; } /** * cd_util_get_devices: **/ static gboolean cd_util_get_devices (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device; gboolean ret = TRUE; GPtrArray *array = NULL; guint i; /* execute sync method */ array = cd_client_get_devices_sync (priv->client, NULL, error); if (array == NULL) { ret = FALSE; goto out; } for (i=0; i < array->len; i++) { device = g_ptr_array_index (array, i); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; cd_util_show_device (device); } out: if (array != NULL) g_ptr_array_unref (array); return ret; } /** * cd_util_get_devices_by_kind: **/ static gboolean cd_util_get_devices_by_kind (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device; gboolean ret = TRUE; GPtrArray *array = NULL; guint i; if (g_strv_length (values) < 1) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device kind " "e.g. 'printer'"); goto out; } /* execute sync method */ array = cd_client_get_devices_by_kind_sync (priv->client, cd_device_kind_from_string (values[0]), NULL, error); if (array == NULL) { ret = FALSE; goto out; } for (i=0; i < array->len; i++) { device = g_ptr_array_index (array, i); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; cd_util_show_device (device); } out: if (array != NULL) g_ptr_array_unref (array); return ret; } /** * cd_util_get_profiles: **/ static gboolean cd_util_get_profiles (CdUtilPrivate *priv, gchar **values, GError **error) { CdProfile *profile; gboolean ret = TRUE; GPtrArray *array = NULL; guint i; /* execute sync method */ array = cd_client_get_profiles_sync (priv->client, NULL, error); if (array == NULL) { ret = FALSE; goto out; } for (i=0; i < array->len; i++) { profile = g_ptr_array_index (array, i); ret = cd_profile_connect_sync (profile, NULL, error); if (!ret) goto out; cd_util_show_profile (profile); } out: if (array != NULL) g_ptr_array_unref (array); return ret; } /** * cd_util_get_sensors: **/ static gboolean cd_util_get_sensors (CdUtilPrivate *priv, gchar **values, GError **error) { CdSensor *sensor; gboolean ret = TRUE; GPtrArray *array = NULL; guint i; /* execute sync method */ array = cd_client_get_sensors_sync (priv->client, NULL, error); if (array == NULL) { ret = FALSE; goto out; } if (array->len == 0) { ret = FALSE; /* TRANSLATORS: the user does not have a colorimeter attached */ g_set_error_literal (error, 1, 0, _("There are no supported sensors attached")); goto out; } for (i=0; i < array->len; i++) { sensor = g_ptr_array_index (array, i); ret = cd_sensor_connect_sync (sensor, NULL, error); if (!ret) goto out; cd_util_show_sensor (sensor); } out: if (array != NULL) g_ptr_array_unref (array); return ret; } /** * cd_util_sensor_lock: **/ static gboolean cd_util_sensor_lock (CdUtilPrivate *priv, gchar **values, GError **error) { CdSensor *sensor; gboolean ret = TRUE; GMainLoop *loop = NULL; GPtrArray *array = NULL; guint i; /* execute sync method */ array = cd_client_get_sensors_sync (priv->client, NULL, error); if (array == NULL) { ret = FALSE; goto out; } if (array->len == 0) { ret = FALSE; /* TRANSLATORS: the user does not have a colorimeter attached */ g_set_error_literal (error, 1, 0, _("There are no supported sensors attached")); goto out; } for (i=0; i < array->len; i++) { sensor = g_ptr_array_index (array, i); ret = cd_sensor_connect_sync (sensor, NULL, error); if (!ret) goto out; /* lock */ ret = cd_sensor_lock_sync (sensor, NULL, error); if (!ret) goto out; } /* spin */ loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (loop); out: if (loop != NULL) g_main_loop_unref (loop); if (array != NULL) g_ptr_array_unref (array); return ret; } /** * cd_util_get_sensor_reading: **/ static gboolean cd_util_get_sensor_reading (CdUtilPrivate *priv, gchar **values, GError **error) { CdColorXYZ *xyz; CdSensorCap cap; CdSensor *sensor; gboolean ret = TRUE; // gdouble ambient; GPtrArray *array = NULL; guint i; if (g_strv_length (values) < 1) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device type " "e.g. 'lcd'"); goto out; } /* execute sync method */ array = cd_client_get_sensors_sync (priv->client, NULL, error); if (array == NULL) { ret = FALSE; goto out; } if (array->len == 0) { ret = FALSE; /* TRANSLATORS: the user does not have a colorimeter attached */ g_set_error_literal (error, 1, 0, _("There are no supported sensors attached")); goto out; } cap = cd_sensor_cap_from_string (values[0]); for (i=0; i < array->len; i++) { sensor = g_ptr_array_index (array, i); ret = cd_sensor_connect_sync (sensor, NULL, error); if (!ret) goto out; /* lock */ ret = cd_sensor_lock_sync (sensor, NULL, error); if (!ret) goto out; /* get a sample sync */ xyz = cd_sensor_get_sample_sync (sensor, cap, NULL, error); if (xyz == NULL) { ret = FALSE; goto out; } /* unlock */ ret = cd_sensor_unlock_sync (sensor, NULL, error); if (!ret) goto out; /* TRANSLATORS: this is the sensor title */ g_print ("%s: %s - %s\n", _("Sensor"), cd_sensor_get_vendor (sensor), cd_sensor_get_model (sensor)); /* TRANSLATORS: this is the ambient light level in Lux */ // g_print ("%s: %f Lux\n", // _("Ambient"), // ambient); /* TRANSLATORS: this is the XYZ color value */ g_print ("%s XYZ : %f, %f, %f\n", _("Color"), xyz->X, xyz->Y, xyz->Z); cd_color_xyz_free (xyz); } out: if (array != NULL) g_ptr_array_unref (array); return ret; } /** * cd_util_sensor_set_options: **/ static gboolean cd_util_sensor_set_options (CdUtilPrivate *priv, gchar **values, GError **error) { CdSensor *sensor; gboolean ret = TRUE; GHashTable *options = NULL; GPtrArray *array = NULL; guint i; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected key value " "e.g. 'remote-profile-hash' 'deadbeef'"); goto out; } /* execute sync method */ array = cd_client_get_sensors_sync (priv->client, NULL, error); if (array == NULL) { ret = FALSE; goto out; } if (array->len == 0) { ret = FALSE; /* TRANSLATORS: the user does not have a colorimeter attached */ g_set_error_literal (error, 1, 0, _("There are no supported sensors attached")); goto out; } /* prepare options for each sensor */ options = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (options, values[0], g_variant_new_string (values[1])); for (i=0; i < array->len; i++) { sensor = g_ptr_array_index (array, i); ret = cd_sensor_connect_sync (sensor, NULL, error); if (!ret) goto out; /* lock */ ret = cd_sensor_lock_sync (sensor, NULL, error); if (!ret) goto out; /* TRANSLATORS: this is the sensor title */ g_print ("%s: %s - %s\n", _("Sensor"), cd_sensor_get_vendor (sensor), cd_sensor_get_model (sensor)); /* set the options set */ ret = cd_sensor_set_options_sync (sensor, options, NULL, error); if (!ret) goto out; /* unlock */ ret = cd_sensor_unlock_sync (sensor, NULL, error); if (!ret) goto out; } out: if (options != NULL) g_hash_table_unref (options); if (array != NULL) g_ptr_array_unref (array); return ret; } /** * cd_util_create_device: **/ static gboolean cd_util_create_device (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; gboolean ret = TRUE; guint mask; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device id, scope " "e.g. 'epson-stylus-800 disk'"); goto out; } /* execute sync method */ mask = cd_object_scope_from_string (values[1]); device = cd_client_create_device_sync (priv->client, values[0], mask, NULL, NULL, error); if (device == NULL) { ret = FALSE; goto out; } g_print ("Created device:\n"); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; cd_util_show_device (device); out: if (device != NULL) g_object_unref (device); return ret; } /** * cd_util_find_device: **/ static gboolean cd_util_find_device (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 1) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device id " "e.g. 'epson-stylus-800'"); goto out; } /* execute sync method */ device = cd_client_find_device_sync (priv->client, values[0], NULL, error); if (device == NULL) { ret = FALSE; goto out; } ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; cd_util_show_device (device); out: if (device != NULL) g_object_unref (device); return ret; } /** * cd_util_find_device_by_property: **/ static gboolean cd_util_find_device_by_property (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected key value " "e.g. 'XRANDR_name' 'lvds'"); goto out; } /* execute sync method */ device = cd_client_find_device_by_property_sync (priv->client, values[0], values[1], NULL, error); if (device == NULL) { ret = FALSE; goto out; } ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; cd_util_show_device (device); out: if (device != NULL) g_object_unref (device); return ret; } /** * cd_util_find_profile: **/ static gboolean cd_util_find_profile (CdUtilPrivate *priv, gchar **values, GError **error) { CdProfile *profile = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 1) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected profile id " "e.g. 'epson-rgb'"); goto out; } /* execute sync method */ profile = cd_client_find_profile_sync (priv->client, values[0], NULL, error); if (profile == NULL) { ret = FALSE; goto out; } ret = cd_profile_connect_sync (profile, NULL, error); if (!ret) goto out; cd_util_show_profile (profile); out: if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_find_profile_by_filename: **/ static gboolean cd_util_find_profile_by_filename (CdUtilPrivate *priv, gchar **values, GError **error) { CdProfile *profile = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 1) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected profile filename"); goto out; } /* execute sync method */ profile = cd_client_find_profile_by_filename_sync (priv->client, values[0], NULL, error); if (profile == NULL) { ret = FALSE; goto out; } ret = cd_profile_connect_sync (profile, NULL, error); if (!ret) goto out; cd_util_show_profile (profile); out: if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_get_standard_space: **/ static gboolean cd_util_get_standard_space (CdUtilPrivate *priv, gchar **values, GError **error) { CdProfile *profile = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 1) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected standard space " "e.g. 'adobe-rgb'"); goto out; } /* execute sync method */ profile = cd_client_get_standard_space_sync (priv->client, cd_standard_space_from_string (values[0]), NULL, error); if (profile == NULL) { ret = FALSE; goto out; } ret = cd_profile_connect_sync (profile, NULL, error); if (!ret) goto out; cd_util_show_profile (profile); out: if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_create_profile: **/ static gboolean cd_util_create_profile (CdUtilPrivate *priv, gchar **values, GError **error) { CdProfile *profile = NULL; gboolean ret = TRUE; guint mask; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected profile id, scope " "e.g. 'epson-rgb disk'"); goto out; } /* execute sync method */ mask = cd_object_scope_from_string (values[1]); profile = cd_client_create_profile_sync (priv->client, values[0], mask, NULL, NULL, error); if (profile == NULL) { ret = FALSE; goto out; } ret = cd_profile_connect_sync (profile, NULL, error); if (!ret) goto out; g_print ("Created profile:\n"); cd_util_show_profile (profile); out: if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_device_add_profile: **/ static gboolean cd_util_device_add_profile (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; CdProfile *profile = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path, profile path " "e.g. '/org/device/foo /org/profile/bar'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[1])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[1]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; profile = cd_profile_new_with_object_path (values[1]); ret = cd_device_add_profile_sync (device, CD_DEVICE_RELATION_HARD, profile, NULL, error); if (!ret) goto out; out: if (device != NULL) g_object_unref (device); if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_device_make_profile_default: **/ static gboolean cd_util_device_make_profile_default (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; CdProfile *profile = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path, profile path " "e.g. '/org/device/foo /org/profile/bar'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[1])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[1]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; profile = cd_profile_new_with_object_path (values[1]); ret = cd_device_make_profile_default_sync (device, profile, NULL, error); if (!ret) goto out; out: if (device != NULL) g_object_unref (device); if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_delete_device: **/ static gboolean cd_util_delete_device (CdUtilPrivate *priv, gchar **values, GError **error) { gboolean ret = TRUE; CdDevice *device = NULL; if (g_strv_length (values) < 1) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path " "e.g. '/org/devices/foo'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_client_delete_device_sync (priv->client, device, NULL, error); if (!ret) goto out; out: if (device != NULL) g_object_unref (device); return ret; } /** * cd_util_delete_profile: **/ static gboolean cd_util_delete_profile (CdUtilPrivate *priv, gchar **values, GError **error) { gboolean ret = TRUE; CdProfile *profile = NULL; if (g_strv_length (values) < 1) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected profile path " "e.g. '/org/profiles/bar'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } profile = cd_profile_new_with_object_path (values[0]); ret = cd_client_delete_profile_sync (priv->client, profile, NULL, error); if (!ret) goto out; out: if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_profile_set_qualifier: **/ static gboolean cd_util_profile_set_qualifier (CdUtilPrivate *priv, gchar **values, GError **error) { CdProfile *profile = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected profile path, qualifier " "e.g. '/org/profile/foo epson.rgb.300dpi'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } profile = cd_profile_new_with_object_path (values[0]); ret = cd_profile_set_qualifier_sync (profile, values[1], NULL, error); if (!ret) goto out; out: if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_profile_set_filename: **/ static gboolean cd_util_profile_set_filename (CdUtilPrivate *priv, gchar **values, GError **error) { CdProfile *profile = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected profile path, filename " "e.g. '/org/profile/foo bar.icc'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } profile = cd_profile_new_with_object_path (values[0]); ret = cd_profile_connect_sync (profile, NULL, error); if (!ret) goto out; ret = cd_profile_set_filename_sync (profile, values[1], NULL, error); if (!ret) goto out; out: if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_device_set_model: **/ static gboolean cd_util_device_set_model (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path, model " "e.g. '/org/devices/bar \"Stylus 800\"'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; ret = cd_device_set_model_sync (device, values[1], NULL, error); if (!ret) goto out; out: if (device != NULL) g_object_unref (device); return ret; } /** * cd_util_device_get_default_profile: **/ static gboolean cd_util_device_get_default_profile (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; CdProfile *profile = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 1) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path " "e.g. '/org/devices/bar'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; profile = cd_device_get_default_profile (device); if (profile == NULL) { ret = FALSE; g_set_error (error, 1, 0, "There is no assigned profile for %s", values[0]); goto out; } ret = cd_profile_connect_sync (profile, NULL, error); if (!ret) goto out; cd_util_show_profile (profile); out: if (device != NULL) g_object_unref (device); if (profile != NULL) g_object_unref (profile); return ret; } /** * cd_util_device_set_vendor: **/ static gboolean cd_util_device_set_vendor (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path, vendor " "e.g. '/org/devices/bar Epson'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; ret = cd_device_set_vendor_sync (device, values[1], NULL, error); if (!ret) goto out; out: if (device != NULL) g_object_unref (device); return ret; } /** * cd_util_device_set_serial: **/ static gboolean cd_util_device_set_serial (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path, serial " "e.g. '/org/devices/bar 00001234'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; ret = cd_device_set_serial_sync (device, values[1], NULL, error); if (!ret) goto out; out: if (device != NULL) g_object_unref (device); return ret; } /** * cd_util_device_set_kind: **/ static gboolean cd_util_device_set_kind (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path, kind " "e.g. '/org/devices/bar printer'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; ret = cd_device_set_kind_sync (device, cd_device_kind_from_string (values[1]), NULL, error); if (!ret) goto out; out: if (device != NULL) g_object_unref (device); return ret; } /** * cd_util_device_inhibit: **/ static gboolean cd_util_device_inhibit (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; gboolean ret = TRUE; GMainLoop *loop = NULL; gint timeout; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path timeout (use 0 for 'never') " "e.g. '/org/devices/epson-800' 60"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } /* check timeout is valid */ timeout = atoi (values[1]); if (timeout < 0) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid timeout: %s", values[1]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; ret = cd_device_profiling_inhibit_sync (device, NULL, error); if (!ret) goto out; /* wait for ctrl-c, as inhibit will be destroyed when the * colormgr tool is finished */ loop = g_main_loop_new (NULL, FALSE); if (timeout > 0) { g_timeout_add_seconds (timeout, cd_util_idle_loop_quit_cb, loop); } g_main_loop_run (loop); out: if (loop != NULL) g_main_loop_unref (loop); if (device != NULL) g_object_unref (device); return ret; } /** * cd_util_device_get_profile_for_qualifiers: **/ static gboolean cd_util_device_get_profile_for_qualifiers (CdUtilPrivate *priv, gchar **values, GError **error) { CdDevice *device = NULL; CdProfile *profile = NULL; gboolean ret = TRUE; if (g_strv_length (values) < 2) { ret = FALSE; g_set_error_literal (error, 1, 0, "Not enough arguments, " "expected device path, qualifier " "e.g. '/org/devices/bar *.*.300dpi'"); goto out; } /* check is valid object path */ if (!g_variant_is_object_path (values[0])) { ret = FALSE; g_set_error (error, 1, 0, "Not a valid object path: %s", values[0]); goto out; } device = cd_device_new_with_object_path (values[0]); ret = cd_device_connect_sync (device, NULL, error); if (!ret) goto out; profile = cd_device_get_profile_for_qualifiers_sync (device, (const gchar **) values, NULL, error); if (profile == NULL) { ret = FALSE; goto out; } cd_util_show_profile (profile); out: if (device != NULL) g_object_unref (device); if (profile != NULL) g_object_unref (profile); return ret; } /** * main: **/ int main (int argc, char *argv[]) { gboolean ret; GError *error = NULL; guint retval = 1; CdUtilPrivate *priv; gchar *cmd_descriptions = NULL; setlocale (LC_ALL, ""); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); g_type_init (); /* create helper object */ priv = g_new0 (CdUtilPrivate, 1); /* add commands */ priv->cmd_array = g_ptr_array_new_with_free_func ((GDestroyNotify) cd_util_item_free); cd_util_add (priv->cmd_array, "get-devices", /* TRANSLATORS: command description */ _("Gets all the color managed devices"), cd_util_get_devices); cd_util_add (priv->cmd_array, "get-devices-by-kind", /* TRANSLATORS: command description */ _("Gets all the color managed devices of a specific kind"), cd_util_get_devices_by_kind); cd_util_add (priv->cmd_array, "get-profiles", /* TRANSLATORS: command description */ _("Gets all the available color profiles"), cd_util_get_profiles); cd_util_add (priv->cmd_array, "get-sensors", /* TRANSLATORS: command description */ _("Gets all the available color sensors"), cd_util_get_sensors); cd_util_add (priv->cmd_array, "get-sensor-reading", /* TRANSLATORS: command description */ _("Gets a reading from a sensor"), cd_util_get_sensor_reading); cd_util_add (priv->cmd_array, "sensor-lock", /* TRANSLATORS: command description */ _("Locks the color sensor"), cd_util_sensor_lock); cd_util_add (priv->cmd_array, "sensor-set-options", /* TRANSLATORS: command description */ _("Sets one or more sensor options"), cd_util_sensor_set_options); cd_util_add (priv->cmd_array, "create-device", /* TRANSLATORS: command description */ _("Create a device"), cd_util_create_device); cd_util_add (priv->cmd_array, "find-device", /* TRANSLATORS: command description */ _("Find a device"), cd_util_find_device); cd_util_add (priv->cmd_array, "find-device-by-property", /* TRANSLATORS: command description */ _("Find a device that has a specific property"), cd_util_find_device_by_property); cd_util_add (priv->cmd_array, "find-profile", /* TRANSLATORS: command description */ _("Find a profile"), cd_util_find_profile); cd_util_add (priv->cmd_array, "find-profile-by-filename", /* TRANSLATORS: command description */ _("Find a profile by filename"), cd_util_find_profile_by_filename); cd_util_add (priv->cmd_array, "get-standard-space", /* TRANSLATORS: command description */ _("Get a standard colorspace"), cd_util_get_standard_space); cd_util_add (priv->cmd_array, "create-profile", /* TRANSLATORS: command description */ _("Create a profile"), cd_util_create_profile); cd_util_add (priv->cmd_array, "device-add-profile", /* TRANSLATORS: command description */ _("Add a profile to a device"), cd_util_device_add_profile); cd_util_add (priv->cmd_array, "device-make-profile-default", /* TRANSLATORS: command description */ _("Makes a profile default for a device"), cd_util_device_make_profile_default); cd_util_add (priv->cmd_array, "delete-device", /* TRANSLATORS: command description */ _("Deletes a device"), cd_util_delete_device); cd_util_add (priv->cmd_array, "delete-profile", /* TRANSLATORS: command description */ _("Deletes a profile"), cd_util_delete_profile); cd_util_add (priv->cmd_array, "profile-set-qualifier", /* TRANSLATORS: command description */ _("Sets the profile qualifier"), cd_util_profile_set_qualifier); cd_util_add (priv->cmd_array, "profile-set-filename", /* TRANSLATORS: command description */ _("Sets the profile filename"), cd_util_profile_set_filename); cd_util_add (priv->cmd_array, "device-set-model", /* TRANSLATORS: command description */ _("Sets the device model"), cd_util_device_set_model); cd_util_add (priv->cmd_array, "device-get-default-profile", /* TRANSLATORS: command description */ _("Gets the default profile for a device"), cd_util_device_get_default_profile); cd_util_add (priv->cmd_array, "device-set-vendor", /* TRANSLATORS: command description */ _("Sets the device vendor"), cd_util_device_set_vendor); cd_util_add (priv->cmd_array, "device-set-serial", /* TRANSLATORS: command description */ _("Sets the device serial"), cd_util_device_set_serial); cd_util_add (priv->cmd_array, "device-set-kind", /* TRANSLATORS: command description */ _("Sets the device kind"), cd_util_device_set_kind); cd_util_add (priv->cmd_array, "device-inhibit", /* TRANSLATORS: command description */ _("Inhibits color profiles for this device"), cd_util_device_inhibit); cd_util_add (priv->cmd_array, "device-get-profile-for-qualifier", /* TRANSLATORS: command description */ _("Returns all the profiles that match a qualifier"), cd_util_device_get_profile_for_qualifiers); /* sort by command name */ g_ptr_array_sort (priv->cmd_array, (GCompareFunc) cd_sort_command_name_cb); /* get a list of the commands */ priv->context = g_option_context_new (NULL); cmd_descriptions = cd_util_get_descriptions (priv->cmd_array); g_option_context_set_summary (priv->context, cmd_descriptions); /* TRANSLATORS: program name */ g_set_application_name (_("Color Management")); g_option_context_parse (priv->context, &argc, &argv, NULL); /* get connection to colord */ priv->client = cd_client_new (); ret = cd_client_connect_sync (priv->client, NULL, &error); if (!ret) { /* TRANSLATORS: no colord available */ g_print ("%s %s\n", _("No connection to colord:"), error->message); g_error_free (error); goto out; } /* run the specified command */ ret = cd_util_run (priv, argv[1], (gchar**) &argv[2], &error); if (!ret) { g_print ("%s\n", error->message); g_error_free (error); goto out; } /* success */ retval = 0; out: if (priv != NULL) { g_object_unref (priv->client); if (priv->cmd_array != NULL) g_ptr_array_unref (priv->cmd_array); g_option_context_free (priv->context); g_free (priv); } g_free (cmd_descriptions); return retval; }