2
/* Instrument command line application support functions */
5
* Argyll Color Correction System
7
* Author: Graeme W. Gill
10
* Copyright 2001 - 2013 Graeme W. Gill
11
* All rights reserved.
13
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
14
* see the License2.txt file for licencing details.
24
#include "copyright.h"
27
#include "sa_config.h"
28
#endif /* !SALONEINSTLIB */
32
#include "insttypes.h"
36
#include "insttypeinst.h"
37
#include "instappsup.h"
39
/* ================================================================= */
40
/* a default user interaction handler */
42
typedef struct _uicontext {
43
int emit_ret; /* Emit \n on inst_triggered */
44
int cut; /* The character that caused the termination */
45
int uih[256]; /* User interrupt handling key table. Value can be: */
46
/* DUIH_OK, DUIH_ABORT, DUIH_TERM, DUIH_TRIG, DUIH_CMND */
49
static uicontext def_uicntx = { 1, 0, { 0 } };
51
static inst_code def_uicallback(void *cntx, inst_ui_purp purp) {
52
uicontext *p = (uicontext *)cntx;
54
if (purp == inst_triggered) {
59
} else if (purp == inst_negcoms
61
|| purp == inst_measuring) {
68
if (c & (DUIH_ABORT | DUIH_TERM | DUIH_CMND))
69
return inst_user_abort;
71
return inst_user_trig;
74
/* Change in measurement configuration */
75
} else if (purp == inst_measuring) {
81
/* Return the default uicallback function */
82
inst_code (*inst_get_uicallback())(void *, inst_ui_purp) {
83
return &def_uicallback;
86
/* Return the default uicallback context */
87
void *inst_get_uicontext() {
88
return (void *)&def_uicntx;
91
/* Install the default uicallback function in the given inst */
92
void inst_set_uicallback(inst *p) {
93
p->set_uicallback(p, def_uicallback, (void *)&def_uicntx);
96
/* Set the return on trigger to true or false */
97
void inst_set_uicb_trigret(int set) {
98
uicontext *p = &def_uicntx;
102
/* Reset user interaction handling to default (Esc, ^C, q or 'Q' = Abort) */
103
void inst_reset_uih() {
104
uicontext *p = &def_uicntx;
107
for (i = 0; i < 255; i++)
108
p->uih[i] = DUIH_NONE;
110
p->uih[0x1b] = DUIH_ABORT; /* Escape */
111
p->uih['q'] = DUIH_ABORT; /* q */
112
p->uih['Q'] = DUIH_ABORT; /* Q */
113
p->uih[0x03] = DUIH_ABORT; /* ^C */
116
/* Set a key range to the given handling type */
117
/* min & max are between 0 and 255, status is one of */
118
/* DUIH_OK, DUIH_USER, DUIH_TERM, DUIH_TRIG, DUIH_CMND */
120
int min, /* Start key code */
121
int max, /* End key code (inclusive) */
122
int status /* ICOM_OK, ICOM_USER, ICOM_TERM, ICOM_TRIG, ICOM_CMND */
124
uicontext *p = &def_uicntx;
136
if (status != DUIH_NONE
137
&& status != DUIH_ABORT
138
&& status != DUIH_TERM
139
&& status != DUIH_CMND
140
&& status != DUIH_TRIG)
143
for (i = min; i <= max; i++) {
148
/* Get the character that caused the user interrupt */
149
/* + its key type in the upper 8 bits. */
150
/* Clear it to 0x00 after reading it. */
151
int inst_get_uih_char() {
152
uicontext *p = &def_uicntx;
159
/* ================================================================= */
161
/* A default calibration user interaction handler using the console. */
162
/* This handles both normal and display based calibration interaction */
163
/* with the instrument, if a disp_setup function and pointer to disp_win_info */
165
inst_code inst_handle_calibrate(
167
inst_cal_type calt, /* Calibration type to do */
168
inst_cal_cond calc, /* Current current condition */
169
inst_code (*disp_setup) (inst *p,inst_cal_cond calc, disp_win_info *dwi),
170
/* Callback for handling a display calibration - May be NULL */
171
disp_win_info *dwi /* Information to be able to open a display test patch - May be NULL */
173
inst_code rv = inst_ok, ev;
174
int usermes = 0; /* User was given a message */
175
char id[200]; /* Condition identifier */
178
a1logd(p->log,1,"inst_handle_calibrate called\n");
180
/* Untill we're done with the calibration */
183
a1logd(p->log,1,"About to call calibrate at top of loop\n");
184
ev = p->calibrate(p, &calt, &calc, id);
185
a1logd(p->log,1,"Calibrate returned calt 0x%x, calc 0x%x, ev 0x%x\n",calt,calc,ev);
188
if ((ev & inst_mask) == inst_ok) {
189
if (calc == inst_calc_message)
192
printf("Calibration complete\n");
194
a1logd(p->log,1,"inst_handle_calibrate done 0x%x\n",ev);
199
if ((ev & inst_mask) == inst_user_abort) {
200
a1logd(p->log,1,"inst_handle_calibrate user aborted 0x%x\n",ev);
204
/* Retry on an error */
205
if ((ev & inst_mask) != inst_cal_setup) {
206
if ((ev & inst_mask) == inst_unsupported) {
207
a1logd(p->log,1,"inst_handle_calibrate err 0x%x, calibration type 0x%x not supported\n",ev, calt);
208
return inst_unsupported;
211
printf("Calibration failed with '%s' (%s)\n",
212
p->inst_interp_error(p, ev), p->interp_error(p, ev));
213
printf("Hit any key to retry, or Esc or Q to abort:\n");
216
ch = next_con_char();
218
if (ch == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
219
a1logd(p->log,1,"inst_handle_calibrate user aborted 0x%x\n",inst_user_abort);
221
return inst_user_abort;
224
/* Get user to do/setup calibration */
228
case inst_calc_uop_ref_white:
229
printf("Do a reflective white calibration,\n");
230
printf(" and then hit any key to continue,\n");
231
printf(" or hit Esc or Q to abort: ");
234
case inst_calc_uop_trans_white:
235
printf("Do a transmissive white calibration,\n");
236
printf(" and then hit any key to continue,\n");
237
printf(" or hit Esc or Q to abort: ");
240
case inst_calc_uop_trans_dark:
241
printf("Do a transmissive dark calibration,\n");
242
printf(" and then hit any key to continue,\n");
243
printf(" or hit Esc or Q to abort: ");
246
case inst_calc_man_ref_white:
247
printf("Place the instrument on its reflective white reference %s,\n",id);
248
printf(" and then hit any key to continue,\n");
249
printf(" or hit Esc or Q to abort: ");
252
case inst_calc_man_ref_whitek:
253
printf("Click the instrument on its reflective white reference %s,\n",id);
254
printf(" or hit Esc or Q to abort: ");
257
case inst_calc_man_ref_dark:
258
printf("Place the instrument in the dark, not in contact with any surface,\n");
259
printf(" and then hit any key to continue,\n");
260
printf(" or hit Esc or Q to abort: ");
263
case inst_calc_man_em_dark:
264
printf("Place cap on the instrument, or place on a dark surface,\n");
265
printf("or place on the white calibration reference,\n");
266
printf(" and then hit any key to continue,\n");
267
printf(" or hit Esc or Q to abort: ");
270
case inst_calc_man_am_dark:
271
printf("Place ambient adapter and cap on the instrument,\n");
272
printf("or place on the white calibration reference,\n");
273
printf(" and then hit any key to continue,\n");
274
printf(" or hit Esc or Q to abort: ");
277
case inst_calc_man_cal_smode:
278
printf("Set instrument sensor to calibration position,\n");
279
printf(" and then hit any key to continue,\n");
280
printf(" or hit Esc or Q to abort: ");
283
case inst_calc_man_trans_white:
284
printf("Place the instrument on its transmissive white source,\n");
285
printf(" and then hit any key to continue,\n");
286
printf(" or hit Esc or Q to abort: ");
289
case inst_calc_man_trans_dark:
290
printf("Use the appropriate tramissive blocking to block the transmission path,\n");
291
printf(" and then hit any key to continue,\n");
292
printf(" or hit Esc or Q to abort: ");
295
case inst_calc_change_filter:
296
printf("Change filter on instrument to %s,\n",id);
297
printf(" and then hit any key to continue,\n");
298
printf(" or hit Esc or Q to abort: ");
301
case inst_calc_message:
303
printf(" Hit any key to continue,\n");
304
printf(" or hit Esc or Q to abort: ");
307
case inst_calc_emis_white:
308
if (disp_setup == NULL || dwi == NULL) { /* No way of creating a test window */
309
printf("Place the instrument on a 100%% white test patch,\n");
310
printf(" and then hit any key to continue,\n");
311
printf(" or hit Esc or Q to abort: ");
313
/* We need to display a 100% white patch to proceed with this */
314
/* type of calibration */
315
if ((rv = disp_setup(p, calc, dwi)) != inst_ok)
320
case inst_calc_emis_grey:
321
case inst_calc_emis_grey_darker:
322
case inst_calc_emis_grey_ligher:
323
if (dwi == NULL) { /* No way of creating a test window */
324
if (calc == inst_calc_emis_grey) {
325
p->cal_gy_level = 0.6;
327
} else if (calc == inst_calc_emis_grey_darker) {
328
p->cal_gy_level *= 0.7;
330
} else if (calc == inst_calc_emis_grey_ligher) {
331
p->cal_gy_level *= 1.4;
332
if (p->cal_gy_level > 1.0)
333
p->cal_gy_level = 1.0;
336
if (p->cal_gy_count > 4) {
337
printf("Cell ratio calibration failed - too many tries at setting grey level.\n");
338
a1logd(p->log,1,"inst_handle_calibrate too many tries at setting grey level 0x%x\n",inst_internal_error);
339
return inst_internal_error;
341
printf("Place the instrument on a %d%% white test patch,\n", (int)(p->cal_gy_level * 100.0 + 0.5));
342
printf(" and then hit any key to continue,\n");
343
printf(" or hit Esc or Q to abort: ");
347
/* We need to display a test patch to proceed with this
348
* type of calibration. Typically this will be:
350
* inst_calc_xxxx_grey:
351
* set p->cal_gy_level = 0.6
352
* set p->cal_gy_count = 0;
354
* inst_calc_xxxx_grey_darker:
355
* set p->cal_gy_level *= 0.7
356
* set p->cal_gy_count++
358
* inst_calc_xxxx_grey_ligher:
359
* set p->cal_gy_level *= 1.4
360
* set p->cal_gy_count++
362
* and return failure if p->cal_gy_count > 4
365
if ((rv = disp_setup(p, calc, dwi)) != inst_ok)
371
/* Something isn't being handled */
372
a1logd(p->log,1,"inst_handle_calibrate unhandled calc case 0x%x, err 0x%x\n",calc,inst_internal_error);
373
return inst_internal_error;
379
if (calc != inst_calc_man_ref_whitek) {
381
ch = next_con_char();
383
if (ch == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
384
a1logd(p->log,1,"inst_handle_calibrate user aborted 0x%x\n",inst_user_abort);
385
return inst_user_abort;
392
/* ============================================================================= */
394
/* A helper function to display -y flag usage for each instrument type available */
395
/* Return accumulated capabilities2 of all the instruments */
396
/* Return all possible capabilities if there are no instruments */
397
/* If docbib is nz, then only display the base calibration display types */
398
inst2_capability inst_show_disptype_options(FILE *fp, char *oline, icompaths *icmps, int docbib) {
403
int notall = 0; /* Not all instruments are USB */
404
int gotone = 0; /* Found at least one USB instrument */
405
inst2_capability acap = 0; /* Accumulate capabilities */
410
/* Locate the end of the option */
411
for (bp = oline; *bp != '\000' && *bp == ' '; bp++)
413
for (; *bp != '\000' && *bp != ' '; bp++)
418
strncpy(buf, oline, pstart);
421
olen = strlen(oline); /* lenth of option part of line */
423
for (i = 0; icmps != NULL && i < icmps->npaths; i++) {
425
inst2_capability cap;
428
if ((it = new_inst(icmps->paths[i], 1, g_log, NULL, NULL)) == NULL) {
434
it->capabilities(it, NULL, &cap, NULL);
437
if (cap & inst2_disptype) {
439
inst_disptypesel *sels;
441
if (it->get_disptypesel(it, &nsel, &sels, 1, 0) != inst_ok) {
445
for (j = 0; j < nsel; j++) {
448
if (docbib && sels[j].cbid == 0)
449
continue; /* Skip non cbid type */
452
for (k = 0; k < (INST_DTYPE_SEL_LEN-1); k++) {
453
if (sels[j].sel[k] == '\000')
457
buf[m++] = sels[j].sel[k];
459
while (m < (olen+1)) /* Indent it by 1 */
464
if ((sels[j].flags & inst_dtflags_default) || sels[j].cbid != 0) {
466
if (sels[j].flags & inst_dtflags_default) {
467
strcat(extra, "Default");
468
if (sels[j].cbid != 0)
471
if (sels[j].cbid != 0) {
472
sprintf(extra + strlen(extra), "CB%d",sels[j].cbid);
477
fprintf(fp, "%s%s: %s%s\n",buf, inst_sname(it->itype), sels[j].desc, extra);
480
for (m = 0; m < pstart; m++)
487
/* Output a default desciption if not all instruments are USB */
496
fprintf(fp, "%s%s\n",buf, " Other: l = LCD, c = CRT");
504
/* A helper function to turn a -y flag into a selection index */
505
/* If docbib is nz, then only allow base calibration display types */
506
/* Return -1 on error */
507
int inst_get_disptype_index(inst *it, int c, int docbib) {
508
inst2_capability cap;
511
it->capabilities(it, NULL, &cap, NULL);
513
if (cap & inst2_disptype) {
515
inst_disptypesel *sels;
517
if (it->get_disptypesel(it, &nsel, &sels, 1, 0) != inst_ok) {
520
for (j = 0; j < nsel; j++) {
521
if (docbib && sels[j].cbid == 0)
522
continue; /* Skip non cbid type */
524
for (k = 0; k < (INST_DTYPE_SEL_LEN-1); k++) {
525
if (sels[j].sel[k] == '\000')
527
if (sels[j].sel[k] == c) {
536
/* ================================================================= */