~ubuntu-branches/ubuntu/quantal/colord/quantal-proposed

« back to all changes in this revision

Viewing changes to client/cd-fix-profile.c

  • Committer: Package Import Robot
  • Author(s): Christopher James Halse Rogers
  • Date: 2012-03-01 17:33:00 UTC
  • mto: (1.1.4) (2.1.7 sid)
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: package-import@ubuntu.com-20120301173300-q1s2bs8yubnybln8
ImportĀ upstreamĀ versionĀ 0.1.18

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2
2
 *
3
 
 * Copyright (C) 2009-2011 Richard Hughes <richard@hughsie.com>
 
3
 * Copyright (C) 2009-2012 Richard Hughes <richard@hughsie.com>
4
4
 *
5
5
 * Licensed under the GNU General Public License Version 2
6
6
 *
22
22
#include "config.h"
23
23
 
24
24
#include <glib/gi18n.h>
 
25
#include <gio/gio.h>
25
26
#include <locale.h>
26
27
#include <lcms2.h>
27
28
#include <stdlib.h>
28
29
 
 
30
#include "cd-client-sync.h"
29
31
#include "cd-common.h"
 
32
#include "cd-enum.h"
30
33
#include "cd-lcms-helpers.h"
31
 
 
32
 
static gint lcms_error_code = 0;
 
34
#include "cd-profile-sync.h"
 
35
 
 
36
typedef struct {
 
37
        GOptionContext          *context;
 
38
        GPtrArray               *cmd_array;
 
39
        CdClient                *client;
 
40
} CdUtilPrivate;
 
41
 
 
42
typedef gboolean (*CdUtilPrivateCb)     (CdUtilPrivate  *util,
 
43
                                         gchar          **values,
 
44
                                         GError         **error);
 
45
 
 
46
typedef struct {
 
47
        gchar           *name;
 
48
        gchar           *description;
 
49
        CdUtilPrivateCb  callback;
 
50
} CdUtilItem;
 
51
 
 
52
/**
 
53
 * cd_util_item_free:
 
54
 **/
 
55
static void
 
56
cd_util_item_free (CdUtilItem *item)
 
57
{
 
58
        g_free (item->name);
 
59
        g_free (item->description);
 
60
        g_free (item);
 
61
}
33
62
 
34
63
/*
35
 
 * cd_fix_profile_filename:
 
64
 * cd_sort_command_name_cb:
36
65
 */
 
66
static gint
 
67
cd_sort_command_name_cb (CdUtilItem **item1, CdUtilItem **item2)
 
68
{
 
69
        return g_strcmp0 ((*item1)->name, (*item2)->name);
 
70
}
 
71
 
 
72
/**
 
73
 * cd_util_add:
 
74
 **/
 
75
static void
 
76
cd_util_add (GPtrArray *array, const gchar *name, const gchar *description, CdUtilPrivateCb callback)
 
77
{
 
78
        CdUtilItem *item;
 
79
        gchar **names;
 
80
        guint i;
 
81
 
 
82
        /* add each one */
 
83
        names = g_strsplit (name, ",", -1);
 
84
        for (i=0; names[i] != NULL; i++) {
 
85
                item = g_new0 (CdUtilItem, 1);
 
86
                item->name = g_strdup (names[i]);
 
87
                if (i == 0) {
 
88
                        item->description = g_strdup (description);
 
89
                } else {
 
90
                        /* TRANSLATORS: this is a command alias */
 
91
                        item->description = g_strdup_printf (_("Alias to %s"),
 
92
                                                             names[0]);
 
93
                }
 
94
                item->callback = callback;
 
95
                g_ptr_array_add (array, item);
 
96
        }
 
97
        g_strfreev (names);
 
98
}
 
99
 
 
100
/**
 
101
 * cd_util_get_descriptions:
 
102
 **/
 
103
static gchar *
 
104
cd_util_get_descriptions (GPtrArray *array)
 
105
{
 
106
        CdUtilItem *item;
 
107
        GString *string;
 
108
        guint i;
 
109
        guint j;
 
110
        guint len;
 
111
        guint max_len = 0;
 
112
 
 
113
        /* get maximum command length */
 
114
        for (i=0; i<array->len; i++) {
 
115
                item = g_ptr_array_index (array, i);
 
116
                len = strlen (item->name);
 
117
                if (len > max_len)
 
118
                        max_len = len;
 
119
        }
 
120
 
 
121
        /* ensure we're spaced by at least this */
 
122
        if (max_len < 19)
 
123
                max_len = 19;
 
124
 
 
125
        /* print each command */
 
126
        string = g_string_new ("");
 
127
        for (i=0; i<array->len; i++) {
 
128
                item = g_ptr_array_index (array, i);
 
129
                g_string_append (string, "  ");
 
130
                g_string_append (string, item->name);
 
131
                len = strlen (item->name);
 
132
                for (j=len; j<max_len+3; j++)
 
133
                        g_string_append_c (string, ' ');
 
134
                g_string_append (string, item->description);
 
135
                g_string_append_c (string, '\n');
 
136
        }
 
137
 
 
138
        /* remove trailing newline */
 
139
        if (string->len > 0)
 
140
                g_string_set_size (string, string->len - 1);
 
141
 
 
142
        return g_string_free (string, FALSE);
 
143
}
 
144
 
 
145
/**
 
146
 * cd_util_run:
 
147
 **/
37
148
static gboolean
38
 
cd_fix_profile_filename (const gchar *filename,
39
 
                         const gchar *description,
40
 
                         const gchar *copyright,
41
 
                         const gchar *model,
42
 
                         const gchar *manufacturer,
43
 
                         const gchar *metadata,
44
 
                         gboolean clear_metadata)
45
 
{
46
 
        gboolean ret = TRUE;
 
149
cd_util_run (CdUtilPrivate *priv, const gchar *command, gchar **values, GError **error)
 
150
{
 
151
        CdUtilItem *item;
 
152
        gboolean ret = FALSE;
 
153
        GString *string;
 
154
        guint i;
 
155
 
 
156
        /* find command */
 
157
        for (i=0; i<priv->cmd_array->len; i++) {
 
158
                item = g_ptr_array_index (priv->cmd_array, i);
 
159
                if (g_strcmp0 (item->name, command) == 0) {
 
160
                        ret = item->callback (priv, values, error);
 
161
                        goto out;
 
162
                }
 
163
        }
 
164
 
 
165
        /* not found */
 
166
        string = g_string_new ("");
 
167
        /* TRANSLATORS: error message */
 
168
        g_string_append_printf (string, "%s\n",
 
169
                                _("Command not found, valid commands are:"));
 
170
        for (i=0; i<priv->cmd_array->len; i++) {
 
171
                item = g_ptr_array_index (priv->cmd_array, i);
 
172
                g_string_append_printf (string, " * %s\n", item->name);
 
173
        }
 
174
        g_set_error_literal (error, 1, 0, string->str);
 
175
        g_string_free (string, TRUE);
 
176
out:
 
177
        return ret;
 
178
}
 
179
 
 
180
/**
 
181
 * cd_util_profile_read:
 
182
 **/
 
183
static cmsHPROFILE
 
184
cd_util_profile_read (const gchar *filename, GError **error)
 
185
{
47
186
        cmsHPROFILE lcms_profile = NULL;
 
187
        gboolean ret;
48
188
        gchar *data = NULL;
49
189
        gsize len;
50
 
        GError *error = NULL;
51
190
 
52
 
        ret = g_file_get_contents (filename, &data, &len, &error);
53
 
        if (!ret) {
54
 
                g_warning ("failed to open profile: %s",
55
 
                           error->message);
56
 
                g_error_free (error);
 
191
        ret = g_file_get_contents (filename, &data, &len, error);
 
192
        if (!ret)
57
193
                goto out;
58
 
        }
59
194
 
60
195
        lcms_profile = cmsOpenProfileFromMem (data, len);
61
 
        if (lcms_profile == NULL || lcms_error_code != 0) {
62
 
                g_warning ("failed to open profile");
63
 
                ret = FALSE;
 
196
        if (lcms_profile == NULL) {
 
197
                g_set_error (error, 1, 0,
 
198
                             "failed to open profile %s",
 
199
                             filename);
64
200
                goto out;
65
201
        }
 
202
out:
 
203
        g_free (data);
 
204
        return lcms_profile;
 
205
}
66
206
 
67
 
        /* profile version to write */
68
 
        cmsSetProfileVersion (lcms_profile, 3.4);
69
 
        if (description != NULL) {
70
 
                ret = _cmsWriteTagTextAscii (lcms_profile,
71
 
                                             cmsSigProfileDescriptionTag,
72
 
                                             description);
73
 
                if (!ret || lcms_error_code != 0) {
74
 
                        g_warning ("failed to write description");
75
 
                        goto out;
76
 
                }
77
 
        }
78
 
        if (copyright != NULL) {
79
 
                ret = _cmsWriteTagTextAscii (lcms_profile,
80
 
                                             cmsSigCopyrightTag,
81
 
                                             copyright);
82
 
                if (!ret || lcms_error_code != 0) {
83
 
                        g_warning ("failed to write copyright");
84
 
                        goto out;
85
 
                }
86
 
        }
87
 
        if (model != NULL) {
88
 
                ret = _cmsWriteTagTextAscii (lcms_profile,
89
 
                                             cmsSigDeviceModelDescTag,
90
 
                                             model);
91
 
                if (!ret || lcms_error_code != 0) {
92
 
                        g_warning ("failed to write model");
93
 
                        goto out;
94
 
                }
95
 
        }
96
 
        if (manufacturer != NULL) {
97
 
                ret = _cmsWriteTagTextAscii (lcms_profile,
98
 
                                             cmsSigDeviceMfgDescTag,
99
 
                                             manufacturer);
100
 
                if (!ret || lcms_error_code != 0) {
101
 
                        g_warning ("failed to write manufacturer");
102
 
                        goto out;
103
 
                }
104
 
        }
105
 
        if (metadata != NULL) {
106
 
                ret = cd_profile_write_metadata_string (lcms_profile,
107
 
                                                        metadata,
108
 
                                                        clear_metadata,
109
 
                                                        "cd-fix-profile",
110
 
                                                        &error);
111
 
                if (!ret) {
112
 
                        g_warning ("failed to write metadata: %s",
113
 
                                   error->message);
114
 
                        g_error_free (error);
115
 
                        goto out;
116
 
                }
117
 
        }
 
207
/**
 
208
 * cd_util_profile_write:
 
209
 **/
 
210
static gboolean
 
211
cd_util_profile_write (cmsHPROFILE lcms_profile, const gchar *filename, GError **error)
 
212
{
 
213
        gboolean ret;
118
214
 
119
215
        /* write profile id */
120
216
        ret = cmsMD5computeID (lcms_profile);
121
 
        if (!ret || lcms_error_code != 0) {
122
 
                g_warning ("failed to write profile id");
123
 
                goto out;
124
 
        }
125
 
 
126
 
        cmsSaveProfileToFile (lcms_profile, filename);
127
 
out:
128
 
        if (lcms_profile != NULL)
129
 
                cmsCloseProfile (lcms_profile);
 
217
        if (!ret) {
 
218
                g_set_error (error, 1, 0,
 
219
                             "failed to compute profile id for %s",
 
220
                             filename);
 
221
                goto out;
 
222
        }
 
223
 
 
224
        /* save file */
 
225
        ret = cmsSaveProfileToFile (lcms_profile, filename);
 
226
        if (!ret) {
 
227
                g_set_error (error, 1, 0,
 
228
                             "failed to save profile to %s",
 
229
                             filename);
 
230
                goto out;
 
231
        }
 
232
out:
 
233
        return ret;
 
234
}
 
235
 
 
236
/**
 
237
 * cd_util_profile_set_text_acsii:
 
238
 **/
 
239
static gboolean
 
240
cd_util_profile_set_text_acsii (cmsHPROFILE lcms_profile,
 
241
                                cmsTagSignature sig,
 
242
                                const gchar *value,
 
243
                                GError **error)
 
244
{
 
245
        gboolean ret;
 
246
 
 
247
        ret = _cmsWriteTagTextAscii (lcms_profile, sig, value);
 
248
        if (!ret) {
 
249
                g_set_error (error, 1, 0,
 
250
                             "failed to write '%s'",
 
251
                             value);
 
252
                goto out;
 
253
        }
 
254
out:
 
255
        return ret;
 
256
}
 
257
 
 
258
/**
 
259
 * cd_util_set_info_text:
 
260
 **/
 
261
static gboolean
 
262
cd_util_set_info_text (CdUtilPrivate *priv, cmsTagSignature sig, gchar **values, GError **error)
 
263
{
 
264
        cmsHPROFILE lcms_profile = NULL;
 
265
        gboolean ret = TRUE;
 
266
 
 
267
        /* check arguments */
 
268
        if (g_strv_length (values) != 2) {
 
269
                ret = FALSE;
 
270
                g_set_error_literal (error, 1, 0,
 
271
                                     "invalid input, expect 'value' 'filename'");
 
272
                goto out;
 
273
        }
 
274
 
 
275
        /* open profile */
 
276
        lcms_profile = cd_util_profile_read (values[1], error);
 
277
        if (lcms_profile == NULL) {
 
278
                ret = FALSE;
 
279
                goto out;
 
280
        }
 
281
 
 
282
        /* update value */
 
283
        ret = cd_util_profile_set_text_acsii (lcms_profile,
 
284
                                              sig,
 
285
                                              values[0],
 
286
                                              error);
 
287
        if (!ret)
 
288
                goto out;
 
289
 
 
290
        /* write new file */
 
291
        ret = cd_util_profile_write (lcms_profile, values[1], error);
 
292
        if (!ret)
 
293
                goto out;
 
294
out:
 
295
        if (lcms_profile != NULL)
 
296
                cmsCloseProfile (lcms_profile);
 
297
        return ret;
 
298
}
 
299
 
 
300
/**
 
301
 * cd_util_set_copyright:
 
302
 **/
 
303
static gboolean
 
304
cd_util_set_copyright (CdUtilPrivate *priv, gchar **values, GError **error)
 
305
{
 
306
        return cd_util_set_info_text (priv, cmsInfoCopyright, values, error);
 
307
}
 
308
 
 
309
/**
 
310
 * cd_util_set_description:
 
311
 **/
 
312
static gboolean
 
313
cd_util_set_description (CdUtilPrivate *priv, gchar **values, GError **error)
 
314
{
 
315
        return cd_util_set_info_text (priv, cmsInfoDescription, values, error);
 
316
}
 
317
 
 
318
/**
 
319
 * cd_util_set_manufacturer:
 
320
 **/
 
321
static gboolean
 
322
cd_util_set_manufacturer (CdUtilPrivate *priv, gchar **values, GError **error)
 
323
{
 
324
        return cd_util_set_info_text (priv, cmsInfoManufacturer, values, error);
 
325
}
 
326
 
 
327
/**
 
328
 * cd_util_set_model:
 
329
 **/
 
330
static gboolean
 
331
cd_util_set_model (CdUtilPrivate *priv, gchar **values, GError **error)
 
332
{
 
333
        return cd_util_set_info_text (priv, cmsInfoModel, values, error);
 
334
}
 
335
 
 
336
/**
 
337
 * cd_util_clear_metadata:
 
338
 **/
 
339
static gboolean
 
340
cd_util_clear_metadata (CdUtilPrivate *priv, gchar **values, GError **error)
 
341
{
 
342
        cmsHANDLE dict = NULL;
 
343
        cmsHPROFILE lcms_profile = NULL;
 
344
        gboolean ret = TRUE;
 
345
 
 
346
        /* check arguments */
 
347
        if (g_strv_length (values) != 1) {
 
348
                ret = FALSE;
 
349
                g_set_error_literal (error, 1, 0,
 
350
                                     "invalid input, expect 'filename'");
 
351
                goto out;
 
352
        }
 
353
 
 
354
        /* open profile */
 
355
        lcms_profile = cd_util_profile_read (values[0], error);
 
356
        if (lcms_profile == NULL) {
 
357
                ret = FALSE;
 
358
                goto out;
 
359
        }
 
360
 
 
361
        /* clear dict */
 
362
        ret = cmsWriteTag (lcms_profile, cmsSigMetaTag, dict);
 
363
        if (!ret) {
 
364
                g_set_error_literal (error, 1, 0,
 
365
                                     "cannot write empty dict tag");
 
366
                goto out;
 
367
        }
 
368
 
 
369
        /* write new file */
 
370
        ret = cd_util_profile_write (lcms_profile, values[0], error);
 
371
        if (!ret)
 
372
                goto out;
 
373
out:
 
374
        if (lcms_profile != NULL)
 
375
                cmsCloseProfile (lcms_profile);
 
376
        return ret;
 
377
}
 
378
 
 
379
/**
 
380
 * cd_util_get_standard_space_filename:
 
381
 **/
 
382
static gchar *
 
383
cd_util_get_standard_space_filename (CdUtilPrivate *priv,
 
384
                                     CdStandardSpace standard_space,
 
385
                                     GError **error)
 
386
{
 
387
        CdProfile *profile_tmp;
 
388
        gboolean ret;
 
389
        gchar *filename = NULL;
 
390
 
 
391
        /* try to find */
 
392
        profile_tmp = cd_client_get_standard_space_sync (priv->client,
 
393
                                                         standard_space,
 
394
                                                         NULL,
 
395
                                                         error);
 
396
        if (profile_tmp == NULL)
 
397
                goto out;
 
398
 
 
399
        /* get filename */
 
400
        ret = cd_profile_connect_sync (profile_tmp, NULL, error);
 
401
        if (!ret)
 
402
                goto out;
 
403
        filename = g_strdup (cd_profile_get_filename (profile_tmp));
 
404
out:
 
405
        if (profile_tmp != NULL)
 
406
                g_object_unref (profile_tmp);
 
407
        return filename;
 
408
}
 
409
 
 
410
typedef struct {
 
411
        guint                    idx;
 
412
        cmsFloat32Number        *data;
 
413
} CdUtilGamutCdeckHelper;
 
414
 
 
415
/**
 
416
 * cd_util_get_coverage_sample_cb:
 
417
 **/
 
418
static cmsInt32Number
 
419
cd_util_get_coverage_sample_cb (const cmsFloat32Number in[],
 
420
                                cmsFloat32Number out[],
 
421
                                void *user_data)
 
422
{
 
423
        CdUtilGamutCdeckHelper *helper = (CdUtilGamutCdeckHelper *) user_data;
 
424
        helper->data[helper->idx++] = in[0];
 
425
        helper->data[helper->idx++] = in[1];
 
426
        helper->data[helper->idx++] = in[2];
 
427
        return 1;
 
428
}
 
429
 
 
430
/**
 
431
 * cd_util_get_coverage:
 
432
 * @profile: A valid #CdUtil
 
433
 * @filename_in: A filename to proof against
 
434
 * @error: A #GError, or %NULL
 
435
 *
 
436
 * Gets the gamut coverage of two profiles
 
437
 *
 
438
 * Return value: A positive value for success, or -1.0 for error.
 
439
 **/
 
440
static gdouble
 
441
cd_util_get_coverage (cmsHPROFILE profile_proof,
 
442
                      const gchar *filename_in,
 
443
                      GError **error)
 
444
{
 
445
        const guint cube_size = 33;
 
446
        cmsFloat32Number *data = NULL;
 
447
        cmsHPROFILE profile_in = NULL;
 
448
        cmsHPROFILE profile_null = NULL;
 
449
        cmsHTRANSFORM transform = NULL;
 
450
        cmsUInt16Number *alarm_codes = NULL;
 
451
        cmsUInt32Number dimensions[] = { cube_size, cube_size, cube_size };
 
452
        CdUtilGamutCdeckHelper helper;
 
453
        gboolean ret;
 
454
        gdouble coverage = -1.0;
 
455
        guint cnt = 0;
 
456
        guint data_len = cube_size * cube_size * cube_size;
 
457
        guint i;
 
458
 
 
459
        /* load profiles into lcms */
 
460
        profile_null = cmsCreateNULLProfile ();
 
461
        profile_in = cmsOpenProfileFromFile (filename_in, "r");
 
462
        if (profile_in == NULL) {
 
463
                g_set_error (error, 1, 0, "Failed to open %s", filename_in);
 
464
                goto out;
 
465
        }
 
466
 
 
467
        /* create a proofing transform with gamut check */
 
468
        transform = cmsCreateProofingTransform (profile_in,
 
469
                                                TYPE_RGB_FLT,
 
470
                                                profile_null,
 
471
                                                TYPE_GRAY_FLT,
 
472
                                                profile_proof,
 
473
                                                INTENT_ABSOLUTE_COLORIMETRIC,
 
474
                                                INTENT_ABSOLUTE_COLORIMETRIC,
 
475
                                                cmsFLAGS_GAMUTCHECK |
 
476
                                                cmsFLAGS_SOFTPROOFING);
 
477
        if (transform == NULL) {
 
478
                g_set_error (error, 1, 0,
 
479
                             "Failed to setup transform for %s",
 
480
                             filename_in);
 
481
                goto out;
 
482
        }
 
483
 
 
484
        /* set gamut alarm to 0xffff */
 
485
        alarm_codes = g_new0 (cmsUInt16Number, cmsMAXCHANNELS);
 
486
        alarm_codes[0] = 0xffff;
 
487
        cmsSetAlarmCodes (alarm_codes);
 
488
 
 
489
        /* slice profile in regular intevals */
 
490
        data = g_new0 (cmsFloat32Number, data_len * 3);
 
491
        helper.data = data;
 
492
        helper.idx = 0;
 
493
        ret = cmsSliceSpaceFloat (3, dimensions,
 
494
                                  cd_util_get_coverage_sample_cb,
 
495
                                  &helper);
 
496
        if (!ret) {
 
497
                g_set_error_literal (error, 1, 0, "Failed to slice data");
 
498
                goto out;
 
499
        }
 
500
 
 
501
        /* transform each one of those nodes across the proofing transform */
 
502
        cmsDoTransform (transform, helper.data, helper.data, data_len);
 
503
 
 
504
        /* count the nodes that gives you zero and divide by total number */
 
505
        for (i = 0; i < data_len; i++) {
 
506
                if (helper.data[i] == 0.0)
 
507
                        cnt++;
 
508
        }
 
509
 
 
510
        /* success */
 
511
        coverage = (gdouble) cnt / (gdouble) data_len;
 
512
        g_assert (coverage >= 0.0);
 
513
out:
130
514
        g_free (data);
131
 
        return ret;
132
 
}
133
 
 
134
 
/**
135
 
 * cd_fix_profile_error_cb:
136
 
 **/
137
 
static void
138
 
cd_fix_profile_error_cb (cmsContext ContextID,
139
 
                         cmsUInt32Number errorcode,
140
 
                         const char *text)
 
515
        if (transform != NULL)
 
516
                cmsDeleteTransform (transform);
 
517
        if (profile_null != NULL)
 
518
                cmsCloseProfile (profile_null);
 
519
        if (profile_in != NULL)
 
520
                cmsCloseProfile (profile_in);
 
521
        return coverage;
 
522
}
 
523
 
 
524
/**
 
525
 * cd_util_get_profile_coverage:
 
526
 **/
 
527
static gdouble
 
528
cd_util_get_profile_coverage (CdUtilPrivate *priv,
 
529
                              cmsHPROFILE profile,
 
530
                              CdStandardSpace standard_space,
 
531
                              GError **error)
 
532
{
 
533
        gchar *filename = NULL;
 
534
        gdouble coverage = -1.0f;
 
535
 
 
536
        /* get the correct standard space */
 
537
        filename = cd_util_get_standard_space_filename (priv,
 
538
                                                        standard_space,
 
539
                                                        error);
 
540
        if (filename == NULL)
 
541
                goto out;
 
542
 
 
543
        /* work out the coverage */
 
544
        coverage = cd_util_get_coverage (profile, filename, error);
 
545
        if (coverage < 0.0f)
 
546
                goto out;
 
547
out:
 
548
        g_free (filename);
 
549
        return coverage;
 
550
}
 
551
 
 
552
/**
 
553
 * cd_util_set_fix_metadata:
 
554
 **/
 
555
static gboolean
 
556
cd_util_set_fix_metadata (CdUtilPrivate *priv, gchar **values, GError **error)
 
557
{
 
558
        cmsHANDLE dict_new = NULL;
 
559
        cmsHANDLE dict_old = NULL;
 
560
        cmsHPROFILE lcms_profile = NULL;
 
561
        const cmsDICTentry *entry;
 
562
        gboolean ret = TRUE;
 
563
        gchar name[1024];
 
564
        gdouble coverage;
 
565
        gchar *coverage_tmp;
 
566
 
 
567
        /* check arguments */
 
568
        if (g_strv_length (values) != 1) {
 
569
                ret = FALSE;
 
570
                g_set_error_literal (error, 1, 0,
 
571
                                     "invalid input, expect 'filename'");
 
572
                goto out;
 
573
        }
 
574
 
 
575
        /* open profile */
 
576
        lcms_profile = cd_util_profile_read (values[0], error);
 
577
        if (lcms_profile == NULL) {
 
578
                ret = FALSE;
 
579
                goto out;
 
580
        }
 
581
 
 
582
        /* copy everything except the CMF keys */
 
583
        dict_old = cmsReadTag (lcms_profile, cmsSigMetaTag);
 
584
        if (dict_old == NULL) {
 
585
                ret = FALSE;
 
586
                g_set_error_literal (error, 1, 0,
 
587
                                     "no metadata present");
 
588
                goto out;
 
589
        }
 
590
 
 
591
        /* copy, but ignore the gamut keys */
 
592
        dict_new = cmsDictAlloc (NULL);
 
593
        for (entry = cmsDictGetEntryList (dict_old);
 
594
             entry != NULL;
 
595
             entry = cmsDictNextEntry (entry)) {
 
596
                wcstombs (name, entry->Name, sizeof (name));
 
597
                if (g_str_has_prefix (name, "GAMUT_volume") == 0)
 
598
                        continue;
 
599
                cmsDictAddEntry (dict_new,
 
600
                                 entry->Name,
 
601
                                 entry->Value,
 
602
                                 NULL,
 
603
                                 NULL);
 
604
        }
 
605
 
 
606
        /* get coverages of common spaces */
 
607
        if (cmsGetColorSpace (lcms_profile) == cmsSigRgbData) {
 
608
 
 
609
                /* get the gamut coverage for sRGB */
 
610
                coverage = cd_util_get_profile_coverage (priv,
 
611
                                                          lcms_profile,
 
612
                                                          CD_STANDARD_SPACE_ADOBE_RGB,
 
613
                                                          error);
 
614
                if (coverage < 0.0) {
 
615
                        ret = FALSE;
 
616
                        goto out;
 
617
                }
 
618
                coverage_tmp = g_strdup_printf ("%f", coverage);
 
619
                _cmsDictAddEntryAscii (dict_new,
 
620
                                       "GAMUT_coverage(adobe-rgb)",
 
621
                                       coverage_tmp);
 
622
                g_free (coverage_tmp);
 
623
                g_debug ("coverage of AdobeRGB: %f%%", coverage * 100.0f);
 
624
 
 
625
                /* get the gamut coverage for AdobeRGB */
 
626
                coverage = cd_util_get_profile_coverage (priv,
 
627
                                                         lcms_profile,
 
628
                                                         CD_STANDARD_SPACE_SRGB,
 
629
                                                         error);
 
630
                if (coverage < 0.0) {
 
631
                        ret = FALSE;
 
632
                        goto out;
 
633
                }
 
634
                coverage_tmp = g_strdup_printf ("%f", coverage);
 
635
                _cmsDictAddEntryAscii (dict_new,
 
636
                                       "GAMUT_coverage(srgb)",
 
637
                                       coverage_tmp);
 
638
                g_free (coverage_tmp);
 
639
                g_debug ("coverage of sRGB: %f%%", coverage * 100.0f);
 
640
        }
 
641
 
 
642
        /* add CMS defines */
 
643
        _cmsDictAddEntryAscii (dict_new,
 
644
                               CD_PROFILE_METADATA_CMF_VERSION,
 
645
                               PACKAGE_VERSION);
 
646
        ret = cmsWriteTag (lcms_profile, cmsSigMetaTag, dict_new);
 
647
        if (!ret) {
 
648
                g_set_error_literal (error, 1, 0,
 
649
                                     "cannot initialize dict tag");
 
650
                goto out;
 
651
        }
 
652
 
 
653
        /* write new file */
 
654
        ret = cd_util_profile_write (lcms_profile, values[0], error);
 
655
        if (!ret)
 
656
                goto out;
 
657
out:
 
658
        if (dict_new != NULL)
 
659
                cmsDictFree (dict_new);
 
660
        if (lcms_profile != NULL)
 
661
                cmsCloseProfile (lcms_profile);
 
662
        return ret;
 
663
}
 
664
 
 
665
/**
 
666
 * cd_util_init_metadata:
 
667
 **/
 
668
static gboolean
 
669
cd_util_init_metadata (CdUtilPrivate *priv, gchar **values, GError **error)
 
670
{
 
671
        cmsHANDLE dict_new = NULL;
 
672
        cmsHANDLE dict_old = NULL;
 
673
        cmsHPROFILE lcms_profile = NULL;
 
674
        const cmsDICTentry *entry;
 
675
        gboolean ret = TRUE;
 
676
        gchar name[1024];
 
677
 
 
678
        /* check arguments */
 
679
        if (g_strv_length (values) != 1) {
 
680
                ret = FALSE;
 
681
                g_set_error_literal (error, 1, 0,
 
682
                                     "invalid input, expect 'filename'");
 
683
                goto out;
 
684
        }
 
685
 
 
686
        /* open profile */
 
687
        lcms_profile = cd_util_profile_read (values[0], error);
 
688
        if (lcms_profile == NULL) {
 
689
                ret = FALSE;
 
690
                goto out;
 
691
        }
 
692
 
 
693
        /* copy everything except the CMF keys */
 
694
        dict_old = cmsReadTag (lcms_profile, cmsSigMetaTag);
 
695
        if (dict_old == NULL) {
 
696
                ret = FALSE;
 
697
                g_set_error_literal (error, 1, 0,
 
698
                                     "no metadata present");
 
699
                goto out;
 
700
        }
 
701
 
 
702
        /* copy, but ignore the key */
 
703
        dict_new = cmsDictAlloc (NULL);
 
704
        for (entry = cmsDictGetEntryList (dict_old);
 
705
             entry != NULL;
 
706
             entry = cmsDictNextEntry (entry)) {
 
707
                wcstombs (name, entry->Name, sizeof (name));
 
708
                if (g_strcmp0 (name, CD_PROFILE_METADATA_CMF_PRODUCT) == 0)
 
709
                        continue;
 
710
                if (g_strcmp0 (name, CD_PROFILE_METADATA_CMF_BINARY) == 0)
 
711
                        continue;
 
712
                if (g_strcmp0 (name, CD_PROFILE_METADATA_CMF_VERSION) == 0)
 
713
                        continue;
 
714
                cmsDictAddEntry (dict_new,
 
715
                                 entry->Name,
 
716
                                 entry->Value,
 
717
                                 NULL,
 
718
                                 NULL);
 
719
        }
 
720
 
 
721
        /* add CMS defines */
 
722
        _cmsDictAddEntryAscii (dict_new,
 
723
                               CD_PROFILE_METADATA_CMF_PRODUCT,
 
724
                               PACKAGE_NAME);
 
725
        _cmsDictAddEntryAscii (dict_new,
 
726
                               CD_PROFILE_METADATA_CMF_BINARY,
 
727
                               "cd-fix-profile");
 
728
        _cmsDictAddEntryAscii (dict_new,
 
729
                               CD_PROFILE_METADATA_CMF_VERSION,
 
730
                               PACKAGE_VERSION);
 
731
        ret = cmsWriteTag (lcms_profile, cmsSigMetaTag, dict_new);
 
732
        if (!ret) {
 
733
                g_set_error_literal (error, 1, 0,
 
734
                                     "cannot initialize dict tag");
 
735
                goto out;
 
736
        }
 
737
 
 
738
        /* write new file */
 
739
        ret = cd_util_profile_write (lcms_profile, values[0], error);
 
740
        if (!ret)
 
741
                goto out;
 
742
out:
 
743
        if (dict_new != NULL)
 
744
                cmsDictFree (dict_new);
 
745
        if (lcms_profile != NULL)
 
746
                cmsCloseProfile (lcms_profile);
 
747
        return ret;
 
748
}
 
749
 
 
750
/**
 
751
 * cd_util_remove_metadata:
 
752
 **/
 
753
static gboolean
 
754
cd_util_remove_metadata (CdUtilPrivate *priv, gchar **values, GError **error)
 
755
{
 
756
        cmsHANDLE dict_new = NULL;
 
757
        cmsHANDLE dict_old = NULL;
 
758
        cmsHPROFILE lcms_profile = NULL;
 
759
        const cmsDICTentry *entry;
 
760
        gboolean ret = TRUE;
 
761
        gchar name[1024];
 
762
 
 
763
        /* check arguments */
 
764
        if (g_strv_length (values) != 2) {
 
765
                ret = FALSE;
 
766
                g_set_error_literal (error, 1, 0,
 
767
                                     "invalid input, expect 'key' 'filename'");
 
768
                goto out;
 
769
        }
 
770
 
 
771
        /* open profile */
 
772
        lcms_profile = cd_util_profile_read (values[1], error);
 
773
        if (lcms_profile == NULL) {
 
774
                ret = FALSE;
 
775
                goto out;
 
776
        }
 
777
 
 
778
        /* copy everything except the key */
 
779
        dict_old = cmsReadTag (lcms_profile, cmsSigMetaTag);
 
780
        if (dict_old == NULL) {
 
781
                ret = FALSE;
 
782
                g_set_error_literal (error, 1, 0,
 
783
                                     "no metadata present");
 
784
                goto out;
 
785
        }
 
786
 
 
787
        /* copy, but ignore the key */
 
788
        dict_new = cmsDictAlloc (NULL);
 
789
        for (entry = cmsDictGetEntryList (dict_old);
 
790
             entry != NULL;
 
791
             entry = cmsDictNextEntry (entry)) {
 
792
                wcstombs (name, entry->Name, sizeof (name));
 
793
                if (g_strcmp0 (name, values[0]) == 0)
 
794
                        continue;
 
795
                cmsDictAddEntry (dict_new,
 
796
                                 entry->Name,
 
797
                                 entry->Value,
 
798
                                 NULL,
 
799
                                 NULL);
 
800
        }
 
801
 
 
802
        /* write the new dict */
 
803
        ret = cmsWriteTag (lcms_profile, cmsSigMetaTag, dict_new);
 
804
        if (!ret) {
 
805
                g_set_error_literal (error, 1, 0,
 
806
                                     "cannot initialize dict tag");
 
807
                goto out;
 
808
        }
 
809
 
 
810
        /* write new file */
 
811
        ret = cd_util_profile_write (lcms_profile, values[1], error);
 
812
        if (!ret)
 
813
                goto out;
 
814
out:
 
815
        if (dict_new != NULL)
 
816
                cmsDictFree (dict_new);
 
817
        if (lcms_profile != NULL)
 
818
                cmsCloseProfile (lcms_profile);
 
819
        return ret;
 
820
}
 
821
 
 
822
/**
 
823
 * cd_util_add_metadata:
 
824
 **/
 
825
static gboolean
 
826
cd_util_add_metadata (CdUtilPrivate *priv, gchar **values, GError **error)
 
827
{
 
828
        cmsHANDLE dict_new = NULL;
 
829
        cmsHANDLE dict_old = NULL;
 
830
        cmsHPROFILE lcms_profile = NULL;
 
831
        const cmsDICTentry *entry;
 
832
        gboolean ret = TRUE;
 
833
        gchar name[1024];
 
834
 
 
835
        /* check arguments */
 
836
        if (g_strv_length (values) != 3) {
 
837
                ret = FALSE;
 
838
                g_set_error_literal (error, 1, 0,
 
839
                                     "invalid input, expect 'key' 'value' 'filename'");
 
840
                goto out;
 
841
        }
 
842
 
 
843
        /* open profile */
 
844
        lcms_profile = cd_util_profile_read (values[2], error);
 
845
        if (lcms_profile == NULL) {
 
846
                ret = FALSE;
 
847
                goto out;
 
848
        }
 
849
 
 
850
        /* add CMS defines */
 
851
        dict_old = cmsReadTag (lcms_profile, cmsSigMetaTag);
 
852
        if (dict_old == NULL)
 
853
                dict_old = cmsDictAlloc (NULL);
 
854
 
 
855
        /* copy, but ignore the key */
 
856
        dict_new = cmsDictAlloc (NULL);
 
857
        for (entry = cmsDictGetEntryList (dict_old);
 
858
             entry != NULL;
 
859
             entry = cmsDictNextEntry (entry)) {
 
860
                wcstombs (name, entry->Name, sizeof (name));
 
861
                if (g_strcmp0 (name, values[0]) == 0)
 
862
                        continue;
 
863
                cmsDictAddEntry (dict_new,
 
864
                                 entry->Name,
 
865
                                 entry->Value,
 
866
                                 NULL,
 
867
                                 NULL);
 
868
        }
 
869
 
 
870
        /* add new entry */
 
871
        _cmsDictAddEntryAscii (dict_new,
 
872
                               values[0],
 
873
                               values[1]);
 
874
        ret = cmsWriteTag (lcms_profile, cmsSigMetaTag, dict_new);
 
875
        if (!ret) {
 
876
                g_set_error_literal (error, 1, 0,
 
877
                                     "cannot write new dict tag");
 
878
                goto out;
 
879
        }
 
880
 
 
881
        /* write new file */
 
882
        ret = cd_util_profile_write (lcms_profile, values[2], error);
 
883
        if (!ret)
 
884
                goto out;
 
885
out:
 
886
        if (dict_new != NULL)
 
887
                cmsDictFree (dict_new);
 
888
        if (lcms_profile != NULL)
 
889
                cmsCloseProfile (lcms_profile);
 
890
        return ret;
 
891
}
 
892
 
 
893
/**
 
894
 * cd_util_dump:
 
895
 **/
 
896
static gboolean
 
897
cd_util_dump (CdUtilPrivate *priv, gchar **values, GError **error)
 
898
{
 
899
        cmsHANDLE dict;
 
900
        cmsHPROFILE lcms_profile = NULL;
 
901
        const cmsDICTentry* entry;
 
902
        gboolean ret = TRUE;
 
903
        gchar ascii_name[1024];
 
904
        gchar ascii_value[1024];
 
905
 
 
906
        /* check arguments */
 
907
        if (g_strv_length (values) != 1) {
 
908
                ret = FALSE;
 
909
                g_set_error_literal (error, 1, 0,
 
910
                                     "invalid input, expect 'filename'");
 
911
                goto out;
 
912
        }
 
913
 
 
914
        /* set value */
 
915
        g_print ("Using filename %s\n", values[0]);
 
916
        lcms_profile = cmsOpenProfileFromFile (values[0], "r");
 
917
        if (lcms_profile == NULL) {
 
918
                g_warning ("failed to open profile %s", values[0]);
 
919
                ret = FALSE;
 
920
                goto out;
 
921
        }
 
922
        ret = cmsGetProfileInfoASCII (lcms_profile, cmsInfoDescription, "en", "US", ascii_name, 1024);
 
923
        if (ret)
 
924
                g_print ("%s\t%s\n", _("Description"), ascii_name);
 
925
        ret = cmsGetProfileInfoASCII (lcms_profile, cmsInfoManufacturer, "en", "US", ascii_name, 1024);
 
926
        if (ret)
 
927
                g_print ("%s\t%s\n", _("Manufacturer"), ascii_name);
 
928
        ret = cmsGetProfileInfoASCII (lcms_profile, cmsInfoModel, "en", "US", ascii_name, 1024);
 
929
        if (ret)
 
930
                g_print ("%s\t%s\n", _("Model"), ascii_name);
 
931
        ret = cmsGetProfileInfoASCII (lcms_profile, cmsInfoCopyright, "en", "US", ascii_name, 1024);
 
932
        if (ret)
 
933
                g_print ("%s\t%s\n", _("Copyright"), ascii_name);
 
934
 
 
935
        /* does profile have metadata? */
 
936
        dict = cmsReadTag (lcms_profile, cmsSigMetaTag);
 
937
        if (dict == NULL) {
 
938
                g_print ("%s\n", _("No metadata"));
 
939
        } else {
 
940
                for (entry = cmsDictGetEntryList (dict);
 
941
                     entry != NULL;
 
942
                     entry = cmsDictNextEntry (entry)) {
 
943
 
 
944
                        /* convert from wchar_t to char */
 
945
                        wcstombs (ascii_name, entry->Name, sizeof (ascii_name));
 
946
                        wcstombs (ascii_value, entry->Value, sizeof (ascii_value));
 
947
                        g_print ("%s %s\t=\t%s\n",
 
948
                                 _("Metadata"), ascii_name, ascii_value);
 
949
                }
 
950
        }
 
951
 
 
952
        /* success */
 
953
        ret = TRUE;
 
954
out:
 
955
        if (lcms_profile != NULL)
 
956
                cmsCloseProfile (lcms_profile);
 
957
        return ret;
 
958
}
 
959
 
 
960
/**
 
961
 * cd_util_ignore_cb:
 
962
 **/
 
963
static void
 
964
cd_util_ignore_cb (const gchar *log_domain, GLogLevelFlags log_level,
 
965
                   const gchar *message, gpointer user_data)
 
966
{
 
967
}
 
968
 
 
969
/**
 
970
 * cd_util_lcms_error_cb:
 
971
 **/
 
972
static void
 
973
cd_util_lcms_error_cb (cmsContext ContextID,
 
974
                       cmsUInt32Number errorcode,
 
975
                       const char *text)
141
976
{
142
977
        g_warning ("LCMS error %i: %s", errorcode, text);
143
 
 
144
 
        /* copy this sytemwide */
145
 
        lcms_error_code = errorcode;
146
978
}
147
979
 
148
 
/*
 
980
/**
149
981
 * main:
150
 
 */
 
982
 **/
151
983
int
152
 
main (int argc, char **argv)
 
984
main (int argc, char *argv[])
153
985
{
154
 
        guint i;
155
 
        guint retval = 0;
 
986
        CdUtilPrivate *priv;
156
987
        gboolean ret;
157
 
        GOptionContext *context;
158
 
        gchar **files = NULL;
159
 
        gchar *description = NULL;
160
 
        gchar *copyright = NULL;
161
 
        gchar *model = NULL;
162
 
        gchar *manufacturer = NULL;
163
 
        gchar *metadata = NULL;
164
 
        gboolean clear_metadata = FALSE;
165
 
 
 
988
        gboolean verbose = FALSE;
 
989
        gchar *cmd_descriptions = NULL;
 
990
        GError *error = NULL;
 
991
        guint retval = 1;
166
992
        const GOptionEntry options[] = {
167
 
                { "description", 'd', 0, G_OPTION_ARG_STRING, &description,
168
 
                /* TRANSLATORS: command line option */
169
 
                  _("The profile description"), NULL },
170
 
                { "copyright", 'c', 0, G_OPTION_ARG_STRING, &copyright,
171
 
                /* TRANSLATORS: command line option */
172
 
                  _("The profile copyright"), NULL },
173
 
                { "model", 'm', 0, G_OPTION_ARG_STRING, &model,
174
 
                /* TRANSLATORS: command line option */
175
 
                  _("The device model"), NULL },
176
 
                { "manufacturer", 'n', 0, G_OPTION_ARG_STRING, &manufacturer,
177
 
                /* TRANSLATORS: command line option */
178
 
                  _("The device manufacturer"), NULL },
179
 
                { "clear-metadata", '\0', 0, G_OPTION_ARG_NONE, &clear_metadata,
180
 
                /* TRANSLATORS: command line option */
181
 
                  _("Clear existing metadata in the profile"), NULL },
182
 
                { "metadata", 'n', 0, G_OPTION_ARG_STRING, &metadata,
183
 
                /* TRANSLATORS: command line option */
184
 
                  _("Extra metadata in 'key1=value1,key2=value2' format"), NULL },
185
 
                { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &files,
186
 
                /* TRANSLATORS: command line option */
187
 
                  _("Profiles to fix"), NULL },
 
993
                { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
 
994
                        /* TRANSLATORS: command line option */
 
995
                        _("Show extra debugging information"), NULL },
188
996
                { NULL}
189
997
        };
190
998
 
193
1001
        bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
194
1002
        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
195
1003
        textdomain (GETTEXT_PACKAGE);
196
 
 
197
 
        /* TRANSLATORS: command line tool */
198
 
        context = g_option_context_new (_("ICC profile fix program"));
199
 
        g_option_context_add_main_entries (context, options, NULL);
200
 
        g_option_context_parse (context, &argc, &argv, NULL);
201
 
        g_option_context_free (context);
202
 
 
203
 
        /* nothing specified */
204
 
        if (files == NULL)
205
 
                goto out;
206
 
 
207
 
        /* setup LCMS */
208
 
        cmsSetLogErrorHandler (cd_fix_profile_error_cb);
209
 
 
210
 
        /* fix each profile */
211
 
        for (i=0; files[i] != NULL; i++) {
212
 
                ret = cd_fix_profile_filename (files[i],
213
 
                                               description,
214
 
                                               copyright,
215
 
                                               model,
216
 
                                               manufacturer,
217
 
                                               metadata,
218
 
                                               clear_metadata);
219
 
                if (!ret) {
220
 
                        retval = 1;
221
 
                        goto out;
222
 
                }
223
 
        }
 
1004
        cmsSetLogErrorHandler (cd_util_lcms_error_cb);
 
1005
 
 
1006
        g_type_init ();
 
1007
 
 
1008
        /* create helper object */
 
1009
        priv = g_new0 (CdUtilPrivate, 1);
 
1010
        priv->client = cd_client_new ();
 
1011
        ret = cd_client_connect_sync (priv->client, NULL, &error);
 
1012
        if (!ret) {
 
1013
                g_print ("%s\n", error->message);
 
1014
                g_error_free (error);
 
1015
                goto out;
 
1016
        }
 
1017
 
 
1018
        /* add commands */
 
1019
        priv->cmd_array = g_ptr_array_new_with_free_func ((GDestroyNotify) cd_util_item_free);
 
1020
        cd_util_add (priv->cmd_array,
 
1021
                     "dump",
 
1022
                     /* TRANSLATORS: command description */
 
1023
                     _("Show all the details about the profile"),
 
1024
                     cd_util_dump);
 
1025
        cd_util_add (priv->cmd_array,
 
1026
                     "md-clear",
 
1027
                     /* TRANSLATORS: command description */
 
1028
                     _("Clear any metadata in the profile"),
 
1029
                     cd_util_clear_metadata);
 
1030
        cd_util_add (priv->cmd_array,
 
1031
                     "md-init",
 
1032
                     /* TRANSLATORS: command description */
 
1033
                     _("Initialize any metadata for the profile"),
 
1034
                     cd_util_init_metadata);
 
1035
        cd_util_add (priv->cmd_array,
 
1036
                     "md-add",
 
1037
                     /* TRANSLATORS: command description */
 
1038
                     _("Add a metadata item to the profile"),
 
1039
                     cd_util_add_metadata);
 
1040
        cd_util_add (priv->cmd_array,
 
1041
                     "md-remove",
 
1042
                     /* TRANSLATORS: command description */
 
1043
                     _("Remove a metadata item from the profile"),
 
1044
                     cd_util_remove_metadata);
 
1045
        cd_util_add (priv->cmd_array,
 
1046
                     "set-copyright",
 
1047
                     /* TRANSLATORS: command description */
 
1048
                     _("Sets the copyright string"),
 
1049
                     cd_util_set_copyright);
 
1050
        cd_util_add (priv->cmd_array,
 
1051
                     "set-description",
 
1052
                     /* TRANSLATORS: command description */
 
1053
                     _("Sets the description string"),
 
1054
                     cd_util_set_description);
 
1055
        cd_util_add (priv->cmd_array,
 
1056
                     "set-manufacturer",
 
1057
                     /* TRANSLATORS: command description */
 
1058
                     _("Sets the manufacturer string"),
 
1059
                     cd_util_set_manufacturer);
 
1060
        cd_util_add (priv->cmd_array,
 
1061
                     "set-model",
 
1062
                     /* TRANSLATORS: command description */
 
1063
                     _("Sets the model string"),
 
1064
                     cd_util_set_model);
 
1065
        cd_util_add (priv->cmd_array,
 
1066
                     "md-fix",
 
1067
                     /* TRANSLATORS: command description */
 
1068
                     _("Automatically fix metadata in the profile"),
 
1069
                     cd_util_set_fix_metadata);
 
1070
 
 
1071
        /* sort by command name */
 
1072
        g_ptr_array_sort (priv->cmd_array,
 
1073
                          (GCompareFunc) cd_sort_command_name_cb);
 
1074
 
 
1075
        /* get a list of the commands */
 
1076
        priv->context = g_option_context_new (NULL);
 
1077
        cmd_descriptions = cd_util_get_descriptions (priv->cmd_array);
 
1078
        g_option_context_set_summary (priv->context, cmd_descriptions);
 
1079
 
 
1080
        /* TRANSLATORS: program name */
 
1081
        g_set_application_name (_("Color Management"));
 
1082
        g_option_context_add_main_entries (priv->context, options, NULL);
 
1083
        g_option_context_parse (priv->context, &argc, &argv, NULL);
 
1084
 
 
1085
        /* set verbose? */
 
1086
        if (verbose) {
 
1087
                g_setenv ("COLORD_VERBOSE", "1", FALSE);
 
1088
        } else {
 
1089
                g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
 
1090
                                   cd_util_ignore_cb, NULL);
 
1091
        }
 
1092
 
 
1093
        /* get connection to colord */
 
1094
 
 
1095
        /* run the specified command */
 
1096
        ret = cd_util_run (priv, argv[1], (gchar**) &argv[2], &error);
 
1097
        if (!ret) {
 
1098
                g_print ("%s\n", error->message);
 
1099
                g_error_free (error);
 
1100
                goto out;
 
1101
        }
 
1102
 
 
1103
        /* success */
 
1104
        retval = 0;
224
1105
out:
225
 
        g_free (description);
226
 
        g_free (copyright);
227
 
        g_free (model);
228
 
        g_free (manufacturer);
229
 
        g_strfreev (files);
 
1106
        if (priv != NULL) {
 
1107
                if (priv->cmd_array != NULL)
 
1108
                        g_ptr_array_unref (priv->cmd_array);
 
1109
                g_option_context_free (priv->context);
 
1110
                g_object_unref (priv->client);
 
1111
                g_free (priv);
 
1112
        }
 
1113
        g_free (cmd_descriptions);
230
1114
        return retval;
231
1115
}
232
1116