From 22f703cab05b7cd368f4de9e03991b7664dc5022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 1 Sep 2014 13:56:46 +0200 Subject: Initial import of argyll version 1.5.1-8 --- spectro/instappsup.c | 556 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 556 insertions(+) create mode 100644 spectro/instappsup.c (limited to 'spectro/instappsup.c') diff --git a/spectro/instappsup.c b/spectro/instappsup.c new file mode 100644 index 0000000..67849c7 --- /dev/null +++ b/spectro/instappsup.c @@ -0,0 +1,556 @@ + + /* Instrument command line application support functions */ + +/* + * Argyll Color Correction System + * + * Author: Graeme W. Gill + * Date: 10/3/2001 + * + * Copyright 2001 - 2013 Graeme W. Gill + * All rights reserved. + * + * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :- + * see the License2.txt file for licencing details. + */ + +#include +#include +#include +#include +#include +#include +#ifndef SALONEINSTLIB +#include "copyright.h" +#include "aconfig.h" +#else +#include "sa_config.h" +#endif /* !SALONEINSTLIB */ +#include "numsup.h" +#include "xspect.h" +#include "conv.h" +#include "insttypes.h" + +#include "icoms.h" +#include "inst.h" +#include "insttypeinst.h" +#include "instappsup.h" + +/* ================================================================= */ +/* a default user interaction handler */ + +typedef struct _uicontext { + int emit_ret; /* Emit \n on inst_triggered */ + int cut; /* The character that caused the termination */ + int uih[256]; /* User interrupt handling key table. Value can be: */ + /* DUIH_OK, DUIH_ABORT, DUIH_TERM, DUIH_TRIG, DUIH_CMND */ +} uicontext; + +static uicontext def_uicntx = { 1, 0, { 0 } }; + +static inst_code def_uicallback(void *cntx, inst_ui_purp purp) { + uicontext *p = (uicontext *)cntx; + + if (purp == inst_triggered) { + if (p->emit_ret) + printf("\n"); + return inst_ok; + + } else if (purp == inst_negcoms + || purp == inst_armed + || purp == inst_measuring) { + int c; + + c = poll_con_char(); + if (c != 0) { + p->cut = c; + c = p->uih[c]; + if (c & (DUIH_ABORT | DUIH_TERM | DUIH_CMND)) + return inst_user_abort; + if (c & DUIH_TRIG) + return inst_user_trig; + } + + /* Change in measurement configuration */ + } else if (purp == inst_measuring) { + return inst_ok; + } + return inst_ok; +} + +/* Return the default uicallback function */ +inst_code (*inst_get_uicallback())(void *, inst_ui_purp) { + return &def_uicallback; +} + +/* Return the default uicallback context */ +void *inst_get_uicontext() { + return (void *)&def_uicntx; +} + +/* Install the default uicallback function in the given inst */ +void inst_set_uicallback(inst *p) { + p->set_uicallback(p, def_uicallback, (void *)&def_uicntx); +} + +/* Set the return on trigger to true or false */ +void inst_set_uicb_trigret(int set) { + uicontext *p = &def_uicntx; + p->emit_ret = set; +} + +/* Reset user interaction handling to default (Esc, ^C, q or 'Q' = Abort) */ +void inst_reset_uih() { + uicontext *p = &def_uicntx; + int i; + + for (i = 0; i < 255; i++) + p->uih[i] = DUIH_NONE; + + p->uih[0x1b] = DUIH_ABORT; /* Escape */ + p->uih['q'] = DUIH_ABORT; /* q */ + p->uih['Q'] = DUIH_ABORT; /* Q */ + p->uih[0x03] = DUIH_ABORT; /* ^C */ +} + +/* Set a key range to the given handling type */ +/* min & max are between 0 and 255, status is one of */ +/* DUIH_OK, DUIH_USER, DUIH_TERM, DUIH_TRIG, DUIH_CMND */ +void inst_set_uih( +int min, /* Start key code */ +int max, /* End key code (inclusive) */ +int status /* ICOM_OK, ICOM_USER, ICOM_TERM, ICOM_TRIG, ICOM_CMND */ +) { + uicontext *p = &def_uicntx; + int i; + + if (min < 0) + min = 0; + else if (min > 255) + min = 255; + if (max < 0) + max = 0; + else if (max > 255) + max = 255; + + if (status != DUIH_NONE + && status != DUIH_ABORT + && status != DUIH_TERM + && status != DUIH_CMND + && status != DUIH_TRIG) + status = DUIH_NONE; + + for (i = min; i <= max; i++) { + p->uih[i] = status; + } +} + +/* Get the character that caused the user interrupt */ +/* + its key type in the upper 8 bits. */ +/* Clear it to 0x00 after reading it. */ +int inst_get_uih_char() { + uicontext *p = &def_uicntx; + int c = p->cut; + c |= p->uih[c]; + p->cut = 0; + return c; +} + +/* ================================================================= */ + +/* A default calibration user interaction handler using the console. */ +/* This handles both normal and display based calibration interaction */ +/* with the instrument, if a disp_setup function and pointer to disp_win_info */ +/* is provided. */ +inst_code inst_handle_calibrate( + inst *p, + inst_cal_type calt, /* Calibration type to do */ + inst_cal_cond calc, /* Current current condition */ + inst_code (*disp_setup) (inst *p,inst_cal_cond calc, disp_win_info *dwi), + /* Callback for handling a display calibration - May be NULL */ + disp_win_info *dwi /* Information to be able to open a display test patch - May be NULL */ +) { + inst_code rv = inst_ok, ev; + int usermes = 0; /* User was given a message */ + char id[200]; /* Condition identifier */ + int ch; + + a1logd(p->log,1,"inst_handle_calibrate called\n"); + + /* Untill we're done with the calibration */ + for (;;) { + + a1logd(p->log,1,"About to call calibrate at top of loop\n"); + ev = p->calibrate(p, &calt, &calc, id); + a1logd(p->log,1,"Calibrate returned calt 0x%x, calc 0x%x, ev 0x%x\n",calt,calc,ev); + + /* We're done */ + if ((ev & inst_mask) == inst_ok) { + if (calc == inst_calc_message) + printf("%s\n",id); + if (usermes) + printf("Calibration complete\n"); + fflush(stdout); + a1logd(p->log,1,"inst_handle_calibrate done 0x%x\n",ev); + return ev; + } + + /* User aborted */ + if ((ev & inst_mask) == inst_user_abort) { + a1logd(p->log,1,"inst_handle_calibrate user aborted 0x%x\n",ev); + return ev; + } + + /* Retry on an error */ + if ((ev & inst_mask) != inst_cal_setup) { + if ((ev & inst_mask) == inst_unsupported) { + a1logd(p->log,1,"inst_handle_calibrate err 0x%x, calibration type 0x%x not supported\n",ev, calt); + return inst_unsupported; + } + + printf("Calibration failed with '%s' (%s)\n", + p->inst_interp_error(p, ev), p->interp_error(p, ev)); + printf("Hit any key to retry, or Esc or Q to abort:\n"); + + empty_con_chars(); + ch = next_con_char(); + printf("\n"); + if (ch == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') { + a1logd(p->log,1,"inst_handle_calibrate user aborted 0x%x\n",inst_user_abort); + fflush(stdout); + return inst_user_abort; + } + + /* Get user to do/setup calibration */ + } else { + + switch (calc) { + case inst_calc_uop_ref_white: + printf("Do a reflective white calibration,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_uop_trans_white: + printf("Do a transmissive white calibration,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_uop_trans_dark: + printf("Do a transmissive dark calibration,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_man_ref_white: + printf("Place the instrument on its reflective white reference %s,\n",id); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_man_ref_whitek: + printf("Click the instrument on its reflective white reference %s,\n",id); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_man_ref_dark: + printf("Place the instrument in the dark, not in contact with any surface,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_man_em_dark: + printf("Place cap on the instrument, or place on a dark surface,\n"); + printf("or place on the white calibration reference,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_man_am_dark: + printf("Place ambient adapter and cap on the instrument,\n"); + printf("or place on the white calibration reference,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_man_cal_smode: + printf("Set instrument sensor to calibration position,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_man_trans_white: + printf("Place the instrument on its transmissive white source,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_man_trans_dark: + printf("Use the appropriate tramissive blocking to block the transmission path,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_change_filter: + printf("Change filter on instrument to %s,\n",id); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_message: + printf("%s\n",id); + printf(" Hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + break; + + case inst_calc_emis_white: + if (disp_setup == NULL || dwi == NULL) { /* No way of creating a test window */ + printf("Place the instrument on a 100%% white test patch,\n"); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + } else { + /* We need to display a 100% white patch to proceed with this */ + /* type of calibration */ + if ((rv = disp_setup(p, calc, dwi)) != inst_ok) + return rv; + } + break; + + case inst_calc_emis_grey: + case inst_calc_emis_grey_darker: + case inst_calc_emis_grey_ligher: + if (dwi == NULL) { /* No way of creating a test window */ + if (calc == inst_calc_emis_grey) { + p->cal_gy_level = 0.6; + p->cal_gy_count = 0; + } else if (calc == inst_calc_emis_grey_darker) { + p->cal_gy_level *= 0.7; + p->cal_gy_count++; + } else if (calc == inst_calc_emis_grey_ligher) { + p->cal_gy_level *= 1.4; + if (p->cal_gy_level > 1.0) + p->cal_gy_level = 1.0; + p->cal_gy_count++; + } + if (p->cal_gy_count > 4) { + printf("Cell ratio calibration failed - too many tries at setting grey level.\n"); + a1logd(p->log,1,"inst_handle_calibrate too many tries at setting grey level 0x%x\n",inst_internal_error); + return inst_internal_error; + } else { + printf("Place the instrument on a %d%% white test patch,\n", (int)(p->cal_gy_level * 100.0 + 0.5)); + printf(" and then hit any key to continue,\n"); + printf(" or hit Esc or Q to abort: "); + } + } else { + + /* We need to display a test patch to proceed with this + * type of calibration. Typically this will be: + * + * inst_calc_xxxx_grey: + * set p->cal_gy_level = 0.6 + * set p->cal_gy_count = 0; + * + * inst_calc_xxxx_grey_darker: + * set p->cal_gy_level *= 0.7 + * set p->cal_gy_count++ + * + * inst_calc_xxxx_grey_ligher: + * set p->cal_gy_level *= 1.4 + * set p->cal_gy_count++ + * + * and return failure if p->cal_gy_count > 4 + */ + + if ((rv = disp_setup(p, calc, dwi)) != inst_ok) + return rv; + } + break; + + default: + /* Something isn't being handled */ + a1logd(p->log,1,"inst_handle_calibrate unhandled calc case 0x%x, err 0x%x\n",calc,inst_internal_error); + return inst_internal_error; + } + fflush(stdout); + + usermes = 1; + + if (calc != inst_calc_man_ref_whitek) { + empty_con_chars(); + ch = next_con_char(); + printf("\n"); + if (ch == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') { + a1logd(p->log,1,"inst_handle_calibrate user aborted 0x%x\n",inst_user_abort); + return inst_user_abort; + } + } + } + } +} + +/* ============================================================================= */ + +/* A helper function to display -y flag usage for each instrument type available */ +/* Return accumulated capabilities2 of all the instruments */ +/* Return all possible capabilities if there are no instruments */ +/* If docbib is nz, then only display the base calibration display types */ +inst2_capability inst_show_disptype_options(FILE *fp, char *oline, icompaths *icmps, int docbib) { + int i, j; + char buf[200], *bp; + char extra[40]; + int olen, pstart; + int notall = 0; /* Not all instruments are USB */ + int gotone = 0; /* Found at least one USB instrument */ + inst2_capability acap = 0; /* Accumulate capabilities */ + + if (icmps == NULL) + return 0; + + /* Locate the end of the option */ + for (bp = oline; *bp != '\000' && *bp == ' '; bp++) + ; + for (; *bp != '\000' && *bp != ' '; bp++) + ; + pstart = bp - oline; + if (pstart > 10) + pstart = 10; + strncpy(buf, oline, pstart); + buf[pstart++] = ' '; + + olen = strlen(oline); /* lenth of option part of line */ + + for (i = 0; icmps != NULL && i < icmps->npaths; i++) { + inst *it; + inst2_capability cap; + int k; + + if ((it = new_inst(icmps->paths[i], 1, g_log, NULL, NULL)) == NULL) { + notall = 1; + continue; + } + gotone = 1; + + it->capabilities(it, NULL, &cap, NULL); + acap |= cap; + + if (cap & inst2_disptype) { + int nsel; + inst_disptypesel *sels; + + if (it->get_disptypesel(it, &nsel, &sels, 1, 0) != inst_ok) { + it->del(it); + continue; + } + for (j = 0; j < nsel; j++) { + int m; + + if (docbib && sels[j].cbid == 0) + continue; /* Skip non cbid type */ + + m = pstart; + for (k = 0; k < (INST_DTYPE_SEL_LEN-1); k++) { + if (sels[j].sel[k] == '\000') + break; + if (m > pstart) + buf[m++] = '|'; + buf[m++] = sels[j].sel[k]; + } + while (m < (olen+1)) /* Indent it by 1 */ + buf[m++] = ' '; + buf[m++] = '\000'; + + extra[0] = '\000'; + if ((sels[j].flags & inst_dtflags_default) || sels[j].cbid != 0) { + strcat(extra, " ["); + if (sels[j].flags & inst_dtflags_default) { + strcat(extra, "Default"); + if (sels[j].cbid != 0) + strcat(extra, ","); + } + if (sels[j].cbid != 0) { + sprintf(extra + strlen(extra), "CB%d",sels[j].cbid); + } + strcat(extra, "]"); + } + + fprintf(fp, "%s%s: %s%s\n",buf, inst_sname(it->itype), sels[j].desc, extra); + + if (j == 0) { + for (m = 0; m < pstart; m++) + buf[m] = ' '; + } + } + } + it->del(it); + } + /* Output a default desciption if not all instruments are USB */ + if (notall) { + int m = pstart; + buf[m++] = 'l'; + buf[m++] = '|'; + buf[m++] = 'c'; + while (m < olen) + buf[m++] = ' '; + buf[m++] = '\000'; + fprintf(fp, "%s%s\n",buf, " Other: l = LCD, c = CRT"); + } + if (!gotone) + acap = ~0; + + return acap; +} + +/* A helper function to turn a -y flag into a selection index */ +/* If docbib is nz, then only allow base calibration display types */ +/* Return -1 on error */ +int inst_get_disptype_index(inst *it, int c, int docbib) { + inst2_capability cap; + int j, k; + + it->capabilities(it, NULL, &cap, NULL); + + if (cap & inst2_disptype) { + int nsel; + inst_disptypesel *sels; + + if (it->get_disptypesel(it, &nsel, &sels, 1, 0) != inst_ok) { + return -1; + } + for (j = 0; j < nsel; j++) { + if (docbib && sels[j].cbid == 0) + continue; /* Skip non cbid type */ + + for (k = 0; k < (INST_DTYPE_SEL_LEN-1); k++) { + if (sels[j].sel[k] == '\000') + break; + if (sels[j].sel[k] == c) { + return j; + } + } + } + } + return -1; +} + +/* ================================================================= */ + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3