diff options
Diffstat (limited to 'spectro')
-rwxr-xr-x[-rw-r--r--] | spectro/IntsLib_Readme.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/Jamfile | 34 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/License.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/License2.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/License3.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/LzmaDec.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/LzmaDec.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/LzmaTypes.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/Makefile.OSX | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/Makefile.SA | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/Makefile.UNIX | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/Makefile.WNT | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/Readme.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/SOtele.sp | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/afiles | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/aglob.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/aglob.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/average.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/base64.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/base64.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ccwin.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ccwin.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ccxx.ti1 | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ccxxmake.c | 48 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/chartread.c | 34 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/colorhug.c | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/colorhug.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/conv.c | 41 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/conv.h | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/cubecal.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dev.h | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dispcal.c | 217 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dispread.c | 39 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dispsup.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dispsup.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/disptechs.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/disptechs.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dispwin.c | 580 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dispwin.h | 14 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp20.c | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp20.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp22.c | 15 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp22.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp41.c | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp41.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp51.c | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp51.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp92.c | 37 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/dtp92.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ex1.c | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ex1.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/fakeread.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/hcfr.c | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/hcfr.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/hidio.c | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/hidio.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/huey.c | 28 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/huey.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/i1d3.c | 81 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/i1d3.h | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/i1disp.c | 81 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/i1disp.h | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/i1pro.c | 11 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/i1pro.h | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/i1pro_imp.c | 117 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/i1pro_imp.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/icoms.c | 179 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/icoms.h | 32 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/icoms_nt.c | 26 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/icoms_ux.c | 62 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ifiles | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/illumread.c | 8 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/inflate.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/inst.c | 365 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/inst.h | 37 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/instappsup.c | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/instappsup.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/instlib.ksh | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/instlib.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/insttypeinst.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/insttypes.c | 90 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/insttypes.h | 30 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/iusb.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/kleink10.c | 11 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/kleink10.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/linear.sp | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/madvrwin.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/madvrwin.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/mongoose.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/mongoose.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/munki.c | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/munki.h | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/munki_imp.c | 12 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/munki_imp.h | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/oemarch.c | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/oemarch.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/oeminst.c | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/pollem.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/pollem.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/rspec.c | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/rspec.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/sa_conv.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/sa_conv.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/smcube.c | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/smcube.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/spec2cie.c | 159 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/specbos.c | 260 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/specbos.h | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/spotread.c | 153 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/spyd2.c | 72 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/spyd2.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ss.c | 71 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ss.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ss_imp.c | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/ss_imp.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/synthcal.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/synthread.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/usbio.c | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/usbio.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/usbio_bsd.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/usbio_lx.c | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/usbio_nt.c | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/usbio_ox.c | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/vinflate.c | 0 | ||||
-rwxr-xr-x | spectro/vtpglut.c | 570 | ||||
-rwxr-xr-x | spectro/vtpglut.h | 243 | ||||
-rwxr-xr-x | spectro/vtpgluttypes.h | 44 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/webwin.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/webwin.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/xdg_bds.c | 52 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/xdg_bds.h | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/xrga.c | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | spectro/xrga.h | 0 |
133 files changed, 3038 insertions, 951 deletions
diff --git a/spectro/IntsLib_Readme.txt b/spectro/IntsLib_Readme.txt index c8df3d3..c8df3d3 100644..100755 --- a/spectro/IntsLib_Readme.txt +++ b/spectro/IntsLib_Readme.txt diff --git a/spectro/Jamfile b/spectro/Jamfile index 94a2f70..f40ef19 100644..100755 --- a/spectro/Jamfile +++ b/spectro/Jamfile @@ -11,6 +11,11 @@ if $(OS) = MACOSX { ObjectCcFlags dispwin_dispwin : -ObjC ; } +if $(USE_CMFM) = true { + echo "CMF Measurement device support is enabled" ; + DEFINES += ENABLE_CMFM ; +} + if [ GLOB [ NormPaths . ] : fastserio.c ] { # echo "!!!!!!!!! fastserio.c is enabled !!!!!!!!!" ; # DEFINES += ENABLE_FTDI ; @@ -127,6 +132,24 @@ if $(USE_DEMOINST) = true && [ GLOB [ NormPaths . ] : demoinst.c ] { INST_SRCS += demoinst.c ; } +if $(USE_VTPGLUT) = true && [ GLOB [ NormPaths . ] : vtpglut.c ] { + echo "Compiling Video Test Pattern Generator and 3DLUT support" ; + DEFINES += ENABLE_VTPGLUT ; + INST_SRCS += vtpglut.c ; +} + +if $(USE_PRINTERS) = true && [ GLOB [ NormPaths . ] : printers.c ] { + echo "Compiling Printer support" ; + DEFINES += ENABLE_DEMOINST ; + INST_SRCS += printers.c ; +} + +if $(USE_CMFM) = true && [ GLOB [ NormPaths . ] : colvis.c ] { + echo "Compiling ColVis support" ; + DEFINES += ENABLE_CMFM ; + INST_SRCS += colvis.c ; +} + Library libinst : inst.c insttypes.c icoms.c disptechs.c rspec.c xrga.c $(INST_SRCS) ; # Display access library @@ -138,7 +161,8 @@ Library libdisp : dispsup.c dispwin.c webwin.c ccwin.c # applications need to know about different instrument or display types, but not access them. */ # (Note we're working around a bug in Jam caused by objects shared between libraries) Object insttypes2 : insttypes.c ; -LibraryFromObjects libinsttypes : insttypes2 ; +Object xrga2 : xrga.c ; +LibraryFromObjects libinsttypes : insttypes2 xrga2 ; Object disptechs2 : disptechs.c ; LibraryFromObjects libdisptechs : disptechs2 ; @@ -171,6 +195,8 @@ if $(LIBUSB_IS_DLL) = true { LINKLIBS += $(LIBUSBDIR)/$(LIBUSB) ; } +LINKFLAGS += $(GUILINKFLAGS) ; + # General target reader program Main chartread : chartread.c ../target/alphix.c : : : ../target : : ; @@ -180,10 +206,8 @@ Main illumread : illumread.c : : : ../target : : ; # Printed target spot reader utility Main spotread : spotread.c : : : : : ; -# Test code -if $(HOME) = "d:\\usr\\graeme" && $(PWD) = "/src/argyll/spectro" { - Main setoem : setoem.c : : : : : ../numlib/libui ; -} +echo "HOME = " $(HOME) ; +echo "PWD = " $(PWD) ; # CCMX and CCSStool Main ccxxmake : ccxxmake.c : : : : : libdisp ; diff --git a/spectro/License.txt b/spectro/License.txt index a871fcf..a871fcf 100644..100755 --- a/spectro/License.txt +++ b/spectro/License.txt diff --git a/spectro/License2.txt b/spectro/License2.txt index 05ca889..05ca889 100644..100755 --- a/spectro/License2.txt +++ b/spectro/License2.txt diff --git a/spectro/License3.txt b/spectro/License3.txt index 94a9ed0..94a9ed0 100644..100755 --- a/spectro/License3.txt +++ b/spectro/License3.txt diff --git a/spectro/LzmaDec.c b/spectro/LzmaDec.c index 8c1a148..8c1a148 100644..100755 --- a/spectro/LzmaDec.c +++ b/spectro/LzmaDec.c diff --git a/spectro/LzmaDec.h b/spectro/LzmaDec.h index 6045fae..6045fae 100644..100755 --- a/spectro/LzmaDec.h +++ b/spectro/LzmaDec.h diff --git a/spectro/LzmaTypes.h b/spectro/LzmaTypes.h index 7732c24..7732c24 100644..100755 --- a/spectro/LzmaTypes.h +++ b/spectro/LzmaTypes.h diff --git a/spectro/Makefile.OSX b/spectro/Makefile.OSX index 485cbf4..485cbf4 100644..100755 --- a/spectro/Makefile.OSX +++ b/spectro/Makefile.OSX diff --git a/spectro/Makefile.SA b/spectro/Makefile.SA index 5913126..5913126 100644..100755 --- a/spectro/Makefile.SA +++ b/spectro/Makefile.SA diff --git a/spectro/Makefile.UNIX b/spectro/Makefile.UNIX index adafa67..adafa67 100644..100755 --- a/spectro/Makefile.UNIX +++ b/spectro/Makefile.UNIX diff --git a/spectro/Makefile.WNT b/spectro/Makefile.WNT index 83eef28..83eef28 100644..100755 --- a/spectro/Makefile.WNT +++ b/spectro/Makefile.WNT diff --git a/spectro/Readme.txt b/spectro/Readme.txt index b9fe0aa..b9fe0aa 100644..100755 --- a/spectro/Readme.txt +++ b/spectro/Readme.txt diff --git a/spectro/SOtele.sp b/spectro/SOtele.sp index f63d90e..f63d90e 100644..100755 --- a/spectro/SOtele.sp +++ b/spectro/SOtele.sp diff --git a/spectro/afiles b/spectro/afiles index 8891ce7..9c14a9b 100644..100755 --- a/spectro/afiles +++ b/spectro/afiles @@ -111,6 +111,9 @@ usbio_lx.c usbio_bsd.c hidio.h hidio.c +vtpglut.h +vtpglut.c +vtpgluttypes.h pollem.h pollem.c dispwin.c diff --git a/spectro/aglob.c b/spectro/aglob.c index dbf9157..dbf9157 100644..100755 --- a/spectro/aglob.c +++ b/spectro/aglob.c diff --git a/spectro/aglob.h b/spectro/aglob.h index dbb5025..dbb5025 100644..100755 --- a/spectro/aglob.h +++ b/spectro/aglob.h diff --git a/spectro/average.c b/spectro/average.c index e961262..e961262 100644..100755 --- a/spectro/average.c +++ b/spectro/average.c diff --git a/spectro/base64.c b/spectro/base64.c index 8e07967..8e07967 100644..100755 --- a/spectro/base64.c +++ b/spectro/base64.c diff --git a/spectro/base64.h b/spectro/base64.h index 29ca140..29ca140 100644..100755 --- a/spectro/base64.h +++ b/spectro/base64.h diff --git a/spectro/ccwin.c b/spectro/ccwin.c index a89bc65..a89bc65 100644..100755 --- a/spectro/ccwin.c +++ b/spectro/ccwin.c diff --git a/spectro/ccwin.h b/spectro/ccwin.h index 9fb902d..9fb902d 100644..100755 --- a/spectro/ccwin.h +++ b/spectro/ccwin.h diff --git a/spectro/ccxx.ti1 b/spectro/ccxx.ti1 index 47f2b13..47f2b13 100644..100755 --- a/spectro/ccxx.ti1 +++ b/spectro/ccxx.ti1 diff --git a/spectro/ccxxmake.c b/spectro/ccxxmake.c index 740eb0a..4d8c057 100644..100755 --- a/spectro/ccxxmake.c +++ b/spectro/ccxxmake.c @@ -179,7 +179,7 @@ usage(int flag, char *diag, ...) { // fprintf(stderr," -V Use adaptive measurement mode (if available)\n"); fprintf(stderr," -C \"command\" Invoke shell \"command\" each time a color is set\n"); fprintf(stderr," -o observ Choose CIE Observer for CCMX spectrometer data:\n"); - fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2\n"); + fprintf(stderr," 1931_2 (def), 1964_10, 2012_2, 2012_10, S&B 1955_2, shaw, J&V 1978_2 or file.cmf\n"); fprintf(stderr," -s steps Override default patch sequence combination steps (default %d)\n",DEFAULT_MSTEPS); fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n"); fprintf(stderr," -D [level] Print debug diagnostics to stderr\n"); @@ -221,7 +221,8 @@ int main(int argc, char *argv[]) { int faketoggle = 0; /* Toggle fake between "colorimeter" and "spectro" */ int fakeseq = 0; /* Fake auto CCMX sequence */ int spec = 0; /* Need spectral data to implement option */ - icxObserverType observ = icxOT_CIE_1931_2; + icxObserverType obType = icxOT_CIE_1931_2; + xspect custObserver[3]; /* If obType = icxOT_custom */ int override = 1; /* Override redirect on X11 */ icompaths *icmps = NULL; /* Ports to choose from */ int comno = COMPORT; /* COM port used */ @@ -466,21 +467,30 @@ int main(int argc, char *argv[]) { if (na == NULL) usage(0,"Parameter expecte after -o"); if (strcmp(na, "1931_2") == 0) { /* Classic 2 degree */ spec = 2; - observ = icxOT_CIE_1931_2; + obType = icxOT_CIE_1931_2; } else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */ spec = 2; - observ = icxOT_CIE_1964_10; + obType = icxOT_CIE_1964_10; + } else if (strcmp(na, "2012_2") == 0) { /* Latest 2 degree */ + spec = 2; + obType = icxOT_CIE_2012_2; + } else if (strcmp(na, "2012_10") == 0) { /* Latest 10 degree */ + spec = 2; + obType = icxOT_CIE_2012_10; } else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */ spec = 2; - observ = icxOT_Stiles_Burch_2; + obType = icxOT_Stiles_Burch_2; } else if (strcmp(na, "1978_2") == 0) { /* Judd and Voss 1978 2 degree */ spec = 2; - observ = icxOT_Judd_Voss_2; + obType = icxOT_Judd_Voss_2; } else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */ spec = 2; - observ = icxOT_Shaw_Fairchild_2; - } else - usage(0,"-o parameter '%s' not recognised",na); + obType = icxOT_Shaw_Fairchild_2; + } else { /* Assume it's a filename */ + obType = icxOT_custom; + if (read_cmf(custObserver, na) != 0) + usage(0,"Failed to read custom observer CMF from -o file '%s'",na); + } } else if (argv[fa][1] == 's') { fa = nfa; @@ -874,7 +884,7 @@ int main(int argc, char *argv[]) { } /* Create a spectral conversion object */ - if ((sp2cie = new_xsp2cie(icxIT_none, NULL, observ, NULL, icSigXYZData, icxClamp)) == NULL) + if ((sp2cie = new_xsp2cie(icxIT_none, NULL, obType, custObserver, icSigXYZData, icxClamp)) == NULL) error("Creation of spectral conversion object failed"); for (i = 0; i < npat; i++) { @@ -938,8 +948,8 @@ int main(int argc, char *argv[]) { cgf = NULL; } - if (spec != 0 && observ != icxOT_CIE_1931_2) - oname = standardObserverDescription(observ); + if (spec != 0 && obType != icxOT_CIE_1931_2) + oname = standardObserverDescription(obType); if (oname != NULL) { char *tt = colname; @@ -1211,8 +1221,8 @@ int main(int argc, char *argv[]) { for (i = 0; ; i++) { if (paths[i] == NULL) break; - if ((paths[i]->itype == instSpyder1 && setup_spyd2(0) == 0) - || (paths[i]->itype == instSpyder2 && setup_spyd2(1) == 0)) + if ((paths[i]->dtype == instSpyder1 && setup_spyd2(0) == 0) + || (paths[i]->dtype == instSpyder2 && setup_spyd2(1) == 0)) fprintf(stderr," %d = '%s' !! Disabled - no firmware !!\n",i+1,paths[i]->name); else fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name); @@ -1308,7 +1318,7 @@ int main(int argc, char *argv[]) { if (spec) { /* Create a spectral conversion object */ - if ((sp2cie = new_xsp2cie(icxIT_none, NULL, observ, NULL, icSigXYZData, icxClamp)) == NULL) + if ((sp2cie = new_xsp2cie(icxIT_none, NULL, obType, custObserver, icSigXYZData, icxClamp)) == NULL) error("Creation of spectral conversion object failed"); } for (i = 0; i < npat; i++) { /* For all grid points */ @@ -1327,7 +1337,7 @@ int main(int argc, char *argv[]) { if (fake) refname = "fake spectrometer"; else - refname = inst_name(it->itype); + refname = inst_name(it->dtype); gotref = 1; if (sp2cie != NULL) sp2cie->del(sp2cie); @@ -1342,7 +1352,7 @@ int main(int argc, char *argv[]) { if (fake) colname = "fake colorimeter"; else - colname = inst_name(it->itype); + colname = inst_name(it->dtype); gotcol = 1; } } @@ -1427,8 +1437,8 @@ int main(int argc, char *argv[]) { continue; } - if (spec != 0 && observ != icxOT_CIE_1931_2) - oname = standardObserverDescription(observ); + if (spec != 0 && obType != icxOT_CIE_1931_2) + oname = standardObserverDescription(obType); if (oname != NULL) { /* Incorporate observer name in colname */ char *tt = colname; diff --git a/spectro/chartread.c b/spectro/chartread.c index e1624e1..6a9db39 100644..100755 --- a/spectro/chartread.c +++ b/spectro/chartread.c @@ -265,6 +265,7 @@ int disbidi, /* Disable automatic bi-directional strip recognition */ int highres, /* Use high res spectral mode */ char *ccxxname, /* Colorimeter Correction/Colorimeter Calibration name */ icxObserverType obType, /* ccss observer */ +xspect custObserver[3], /* If obType = icxOT_custom */ double scan_tol, /* Modify patch consistency tolerance */ int pbypatch, /* Patch by patch measurement */ int xtern, /* Use external (user supplied) values rather than instument read */ @@ -468,7 +469,7 @@ a1log *log /* verb, debug & error log */ it->del(it); return -1; } - if ((rv = it->get_set_opt(it, inst_opt_set_ccss_obs, obType, NULL)) != inst_ok) { + if ((rv = it->get_set_opt(it, inst_opt_set_ccss_obs, obType, custObserver)) != inst_ok) { printf("\nSetting CCSS observer failed with error :'%s' (%s)\n", it->inst_interp_error(it, rv), it->interp_error(it, rv)); cs->del(cs); @@ -489,7 +490,7 @@ a1log *log /* verb, debug & error log */ /* If non-standard observer wasn't set by a CCSS file above */ if (obType != icxOT_default && (cap2 & inst2_ccss) && ccssset == 0) { - if ((rv = it->get_set_opt(it, inst_opt_set_ccss_obs, obType, NULL)) != inst_ok) { + if ((rv = it->get_set_opt(it, inst_opt_set_ccss_obs, obType, custObserver)) != inst_ok) { printf("\nSetting CCSS observer failed with error :'%s' (%s)\n", it->inst_interp_error(it, rv), it->interp_error(it, rv)); it->del(it); @@ -552,12 +553,10 @@ a1log *log /* verb, debug & error log */ rmode = 0; } } else if (displ) { -printf("~1 using displ mode\n"); /* We assume a display mode will always be spot by spot */ mode = inst_mode_emis_spot; rmode = 0; } else if (emis) { -printf("~1 using emis mode\n"); if (pbypatch && it->check_mode(it, inst_mode_emis_spot) == inst_ok) { mode = inst_mode_emis_spot; @@ -1466,7 +1465,7 @@ printf("~1 using emis mode\n"); /* DTP51 has a nasty habit of misaligning test squares by +/- 1 */ /* See if this might have happened */ - if (it->itype == instDTP51) { + if (it->dtype == instDTP51) { loff = -1; hoff = 1; } @@ -2155,9 +2154,9 @@ usage() { fprintf(stderr," -X file.ccss Use Colorimeter Calibration Spectral Samples for calibration\n"); fprintf(stderr," -Q observ Choose CIE Observer for CCSS instrument:\n"); #ifdef SALONEINSTLIB - fprintf(stderr," 1931_2 (def), 1964_10\n"); + fprintf(stderr," 1931_2 (def), 1964_10, 2012_2, 2012_10\n"); #else /* !SALONEINSTLIB */ - fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2\n"); + fprintf(stderr," 1931_2 (def), 1964_10, 2012_2, 2012_10, S&B 1955_2, shaw, J&V 1978_2 or file.cmf\n"); #endif /* !SALONEINSTLIB */ } fprintf(stderr," -T ratio Modify strip patch consistency tolerance by ratio\n"); @@ -2208,6 +2207,7 @@ int main(int argc, char *argv[]) { int doplot = 0; /* Plot spectral of patch by patch */ char ccxxname[MAXNAMEL+1] = "\000"; /* Colorimeter Correction/Colorimeter Calibration name */ icxObserverType obType = icxOT_default; /* ccss observer */ + xspect custObserver[3]; /* If obType = icxOT_custom */ static char inname[MAXNAMEL+1] = { 0 }; /* Input cgats file base name */ static char outname[MAXNAMEL+1] = { 0 }; /* Output cgats file base name */ cgats *icg; /* input cgats structure */ @@ -2300,6 +2300,10 @@ int main(int argc, char *argv[]) { obType = icxOT_CIE_1931_2; } else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */ obType = icxOT_CIE_1964_10; + } else if (strcmp(na, "2012_2") == 0) { /* Latest 2 degree */ + obType = icxOT_CIE_2012_2; + } else if (strcmp(na, "2012_10") == 0) { /* Latest 10 degree */ + obType = icxOT_CIE_2012_10; #ifndef SALONEINSTLIB } else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */ obType = icxOT_Stiles_Burch_2; @@ -2308,8 +2312,11 @@ int main(int argc, char *argv[]) { } else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */ obType = icxOT_Shaw_Fairchild_2; #endif /* !SALONEINSTLIB */ - } else - usage(); + } else { /* Assume it's a filename */ + obType = icxOT_custom; + if (read_cmf(custObserver, na) != 0) + usage(); + } } /* Scan tolerance ratio */ @@ -2992,7 +2999,7 @@ int main(int argc, char *argv[]) { if (read_strips(itype, scols, &atype, npat, totpa, stipa, pis, paix, saix, ixord, rstart, rand, hex, ipath, fc, plen, glen, tlen, trans, emis, displ, dtype, fe, scalstd, &ucalstd, nocal, disbidi, highres, - ccxxname, obType, + ccxxname, obType, custObserver, scan_tol, pbypatch, xtern, spectral, uvmode, accurate_expd, emit_warnings, doplot, g_log) == 0) { /* And save the result */ @@ -3009,6 +3016,13 @@ int main(int argc, char *argv[]) { if (displ == 0 && trans == 0 && ucalstd != xcalstd_none) ocg->add_kword(ocg, 0, "DEVCALSTD",xcalstd2str(ucalstd), NULL); + if (fe == inst_opt_filter_pol) + ocg->add_kword(ocg, 0, "INSTRUMENT_FILTER", "POLARIZED", NULL); + else if (fe == inst_opt_filter_D65) + ocg->add_kword(ocg, 0, "INSTRUMENT_FILTER", "D65", NULL); + else if (fe == inst_opt_filter_UVCut) + ocg->add_kword(ocg, 0, "INSTRUMENT_FILTER", "UVCUT", NULL); + /* Count patches actually read */ for (nrpat = i = 0; i < npat; i++) { if (cols[i].rr) { diff --git a/spectro/colorhug.c b/spectro/colorhug.c index fefe766..aa8ba21 100644..100755 --- a/spectro/colorhug.c +++ b/spectro/colorhug.c @@ -33,6 +33,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -1197,7 +1198,7 @@ colorhug_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern colorhug *new_colorhug(icoms *icom, instType itype) { +extern colorhug *new_colorhug(icoms *icom, instType dtype) { colorhug *p; int i; @@ -1223,9 +1224,9 @@ extern colorhug *new_colorhug(icoms *icom, instType itype) { p->del = colorhug_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; - if (itype == instColorHug2) + if (dtype == instColorHug2) p->stype = ch_two; icmSetUnity3x3(p->ccmat); diff --git a/spectro/colorhug.h b/spectro/colorhug.h index 8617705..8617705 100644..100755 --- a/spectro/colorhug.h +++ b/spectro/colorhug.h diff --git a/spectro/conv.c b/spectro/conv.c index 284a30c..a728566 100644..100755 --- a/spectro/conv.c +++ b/spectro/conv.c @@ -41,6 +41,9 @@ #include <stdarg.h> #include <errno.h> #include <string.h> +#include <sys/time.h> +#include <sys/types.h> +#include <pwd.h> /* select() defined, but not poll(), so emulate poll() */ #if defined(FD_CLR) && !defined(POLLIN) @@ -59,6 +62,7 @@ #include "sa_config.h" #endif #include "numsup.h" +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -241,6 +245,12 @@ void empty_con_chars(void) { if ((stdinh = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) return; for (;;) { + /* Wait for 1msec */ + + /* Do dummy read, as stdin seems to be signalled on startup */ + if (WaitForSingleObject(stdinh, 1) == WAIT_OBJECT_0) + ReadFile(stdinh, buf, 0, &bread, NULL); + if (WaitForSingleObject(stdinh, 1) == WAIT_OBJECT_0) { ReadFile(stdinh, buf, 100, &bread, NULL); } else { @@ -423,6 +433,13 @@ athread *new_athread( /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Return the login $HOME directory. */ +/* (Useful if we might be running sudo) */ +/* No NT equivalent ?? */ +char *login_HOME() { + return getenv("HOME"); +} + /* Delete a file */ void delete_file(char *fname) { _unlink(fname); @@ -789,6 +806,7 @@ static void *threadproc( athread *p = (athread *)param; /* Register this thread with the Objective-C garbage collector */ + /* (Hmm. Done by default in latter versions though, hence deprecated in them ?) */ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 objc_registerThreadWithCollector(); #endif @@ -833,6 +851,29 @@ athread *new_athread( /* - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Return the login $HOME directory. */ +/* (Useful if we might be running sudo) */ +char *login_HOME() { + + if (getuid() == 0) { /* If we are running as root */ + char *uids; + + if ((uids = getenv("SUDO_UID")) != NULL) { /* And we sudo's to get it */ + int uid; + struct passwd *pwd; + + uid = atoi(uids); + + if ((pwd = getpwuid(uid)) != NULL) { + return pwd->pw_dir; + } + } + } + + return getenv("HOME"); +} + + /* Delete a file */ void delete_file(char *fname) { unlink(fname); diff --git a/spectro/conv.h b/spectro/conv.h index a6adcbf..14e5636 100644..100755 --- a/spectro/conv.h +++ b/spectro/conv.h @@ -168,6 +168,10 @@ athread *new_athread(int (*function)(void *context), void *context); /* - - - - - - - - - - - - - - - - - - -- */ +/* Return the login $HOME directory. */ +/* (Useful if we might be running sudo) */ +char *login_HOME(); + /* Delete a file */ void delete_file(char *fname); diff --git a/spectro/cubecal.h b/spectro/cubecal.h index 93f1ada..93f1ada 100644..100755 --- a/spectro/cubecal.h +++ b/spectro/cubecal.h diff --git a/spectro/dev.h b/spectro/dev.h index 0b62de3..004c20f 100644..100755 --- a/spectro/dev.h +++ b/spectro/dev.h @@ -29,13 +29,15 @@ /* Device base object. */ #define DEV_OBJ_BASE \ a1log *log; /* Pointer to debug & error logging class */ \ + devType dtype; /* Device type determined by driver */ \ icoms *icom; /* Device coms object */ \ - instType itype; /* Device type determined by driver */ \ + int gotcoms; /* Coms established flag */ \ + int inited; /* Device open and initialized flag */ \ /* The base object type */ struct _dev { DEV_OBJ_BASE - }; typedef struct _dev dev; +}; typedef struct _dev dev; #define DEV_H #endif /* DEV_H */ diff --git a/spectro/dispcal.c b/spectro/dispcal.c index 65e2f10..a4798af 100644..100755 --- a/spectro/dispcal.c +++ b/spectro/dispcal.c @@ -151,6 +151,8 @@ #undef CHECK_MODEL /* Do readings to check the accuracy of our model */ #undef SHOW_WINDOW_ONFAKE /* Display a test window up for a fake device */ +#undef DEBUG_MEAS_RES /* Debug just VideoLUT resolution code */ + /* Invoke with -dfake for testing with a fake device. */ /* Will use a fake.icm/.icc profile if present, or a built in fake */ /* device behaviour if not. */ @@ -178,18 +180,19 @@ #define RDAC_SMOOTH 0.3 /* RAMDAC curve fitting smoothness */ #define MEAS_RES /* Measure the RAMNDAC entry size */ -#ifdef DEBUG_PLOT +#if defined(DEBUG_PLOT) || defined(DEBUG) || defined(DEBUG_MEAS_RES) #include "plot.h" #endif #if defined(DEBUG) - -#define DBG(xxx) fprintf xxx ; -#define dbgo stderr +# define DBG(xxx) fprintf xxx ; +# define DEBUG_MEAS_RES #else -#define DBG(xxx) +# define DBG(xxx) #endif /* DEBUG */ +#define dbgo stderr + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Sample points used in initial device model optimisation */ @@ -1242,6 +1245,7 @@ static double comp_ct( int plank, /* NZ if Plankian locus, 0 if Daylight locus */ int dovct, /* NZ if visual match, 0 if traditional correlation */ icxObserverType obType, /* If not default, set a custom observer */ + xspect custObserver[3], /* If obType = icxOT_custom */ double xyz[3] /* Color to match */ ) { double ct_xyz[3]; /* XYZ on locus */ @@ -1254,7 +1258,7 @@ static double comp_ct( obType = icxOT_CIE_1931_2; if ((ct = icx_XYZ2ill_ct(ct_xyz, plank != 0 ? icxIT_Ptemp : icxIT_Dtemp, - obType, NULL, xyz, NULL, dovct)) < 0) + obType, custObserver, xyz, NULL, dovct)) < 0) error("Got bad color temperature conversion\n"); if (de != NULL) { @@ -1317,7 +1321,7 @@ static int comp_ramdac_prec( val[i] = (double)i; meas[i] = ttt[i].XYZ[1]; } -#ifdef DEBUG +#ifdef DEBUG_MEAS_RES fprintf(dbgo,"raw measurements:\n"); do_plot(val, meas, NULL, NULL, 17); #endif @@ -1337,67 +1341,85 @@ static int comp_ramdac_prec( /* Create score for each hypothesis */ scale = 1.0; - for (j = 0; j < 5; j++) { + for (j = 0; j < 5; j++) { /* Res 8, 9, 10, 11, 12 bits */ int k; - int step = 1 << (4 - j); + int step = 1 << (4 - j); /* Step 16, 8, 4, 2, 1 */ double v = 0.0; double merr; + int off; + double oscore; /* Offset score */ bits[j] = 8.0 + j; + score[j] = 1e38; - /* Create the target response */ - for (i = 0; i < 17;) { - for (k = 0; k < step && (i+k) < 17; k++) { - targ[i + k] = v; + /* Try possible offsets */ + for (off = 0; off < step; off++) { + int ik = off; /* Initial k */ + + /* Create the target response */ + for (i = 0; i < 17;) { + int ii; /* Actual count of loop */ + for (ii = 0, k = ik; k < step && (i+k) < 17; k++, ii++) { + targ[i + ii] = v; //printf("j %d: targ[%d] = %f\n",j,i+k,v); + } + v += step/16.0; + i += ii; + ik = 0; } - v += step/16.0; - i += k; - } - /* Tweak it for typical display non-linearity */ - min = 1e9, max = -1e9; - for (i = 0; i < 17; i++) { - targ[i] = pow((NVAL + targ[i]/16.0)/255.0, 2.2); - if (targ[i] < min) - min = targ[i]; - if (targ[i] > max) - max = targ[i]; - } - for (i = 0; i < 17; i++) - targ[i] = (targ[i] - min)/(max - min); + /* Tweak it for typical display non-linearity */ + min = 1e9, max = -1e9; + for (i = 0; i < 17; i++) { + targ[i] = pow((NVAL + targ[i]/16.0)/255.0, 2.2); + if (targ[i] < min) + min = targ[i]; + if (targ[i] > max) + max = targ[i]; + } + for (i = 0; i < 17; i++) + targ[i] = (targ[i] - min)/(max - min); + + /* Try and make fit a little better */ + /* with a crude optimisation */ + for (k = 0; k < 50; k++) { + + merr = 0.0; + for (i = 0; i < 17; i++) + merr += targ[i] - meas[i]; + merr /= 17.0; - /* Try and make fit a little better */ - /* with a crude optimisation */ - for (k = 0; k < 50; k++) { + for (i = 0; i < 17; i++) { + targ[i] *= (1.0 + 0.5 * merr); + targ[i] -= 0.5 * merr; +// targ[i] -= merr; + } + } - merr = 0.0; - for (i = 0; i < 17; i++) - merr += targ[i] - meas[i]; - merr /= 17.0; - + oscore = 0.0; for (i = 0; i < 17; i++) { - targ[i] *= (1.0 + 0.5 * merr); - targ[i] -= 0.5 * merr; -// targ[i] -= merr; + double tt = targ[i] - meas[i]; + tt *= tt; + oscore += tt; } - } - score[j] = 0.0; - for (i = 0; i < 17; i++) { - double tt = targ[i] - meas[i]; - score[j] += tt * tt; +#ifdef DEBUG_MEAS_RES + printf("%d bits %d offset score %f\n",8+j,off,oscore); + do_plot(val, meas, targ, NULL, 17); +#endif + /* keep best score from offsets */ + if (oscore < score[j]) + score[j] = oscore; } + score[j] *= scale; - scale *= 1.1; + scale *= 1.7; /* De-weight higher bit depth slightly */ + /* Correct if overall graph is symetrical */ + /* around minimum value ? */ -#ifdef DEBUG - printf("%d bits score %f\n",8+j,score[j]); - do_plot(val, meas, targ, NULL, 17); -#endif } - /* Pick the best score */ + /* Locate the best and second best scores */ bcor = bcor2 = 1e8; bbits = 0; @@ -1415,9 +1437,15 @@ static int comp_ramdac_prec( /* Don't pick anything if it's not reasonably certain */ if (bcor2/bcor < 1.3 || (bcor2/bcor < 2.1 && bcor > 0.15) - ) rbits = 0; + ) { +#ifdef DEBUG_MEAS_RES + printf("bcor2/bcor < 1.3 %d\n",bcor2/bcor < 1.3); + printf("bcor2/bcor < 2.1 %d && bcor > 0.15 %d -> %d\n", bcor2/bcor < 2.1, bcor > 0.15, bcor2/bcor < 2.1 && bcor > 0.15); +#endif + rbits = 0; + } -#ifdef DEBUG +#ifdef DEBUG_MEAS_RES printf("Win score %f by cor %f, ratio %f\n",bcor, bcor2 - bcor, bcor2/bcor); printf("Best %d, returning %d bits\n",bbits,rbits); do_plot10(bits, score, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 5, 1); @@ -1489,7 +1517,7 @@ double g_def_gamma = 2.4; */ /* Flag = 0x0000 = default */ -/* Flag & 0x0001 = list ChromCast's */ +/* Flag & 0x0001 = list ChromeCast's */ void usage(int flag, char *diag, ...) { int i; disppath **dp; @@ -1532,10 +1560,10 @@ void usage(int flag, char *diag, ...) { if (flag & 0x001) { ccast_id **ids; if ((ids = get_ccids()) == NULL) { - fprintf(stderr," ** Error discovering ChromCasts **\n"); + fprintf(stderr," ** Error discovering ChromeCasts **\n"); } else { if (ids[0] == NULL) - fprintf(stderr," ** No ChromCasts found **\n"); + fprintf(stderr," ** No ChromeCasts found **\n"); else { int i; for (i = 0; ids[i] != NULL; i++) @@ -1548,7 +1576,7 @@ void usage(int flag, char *diag, ...) { fprintf(stderr," -dmadvr Display via MadVR Video Renderer\n"); #endif // fprintf(stderr," -d fake Use a fake display device for testing, fake%s if present\n",ICC_FILE_EXT); - fprintf(stderr," -c listno Set communication port from the following list (default %d)\n",COMPORT); + fprintf(stderr," -c listno Choose instrument from the following list (default %d)\n",COMPORT); if ((icmps = new_icompaths(g_log)) != NULL) { icompath **paths; if ((paths = icmps->paths) != NULL) { @@ -1556,8 +1584,8 @@ void usage(int flag, char *diag, ...) { for (i = 0; ; i++) { if (paths[i] == NULL) break; - if ((paths[i]->itype == instSpyder1 && setup_spyd2(0) == 0) - || (paths[i]->itype == instSpyder2 && setup_spyd2(1) == 0)) + if ((paths[i]->dtype == instSpyder1 && setup_spyd2(0) == 0) + || (paths[i]->dtype == instSpyder2 && setup_spyd2(1) == 0)) fprintf(stderr," %d = '%s' !! Disabled - no firmware !!\n",i+1,paths[i]->name); else fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name); @@ -1614,7 +1642,7 @@ void usage(int flag, char *diag, ...) { if (cap2 & inst2_ccss) { fprintf(stderr," -X file.ccss Use Colorimeter Calibration Spectral Samples for calibration\n"); fprintf(stderr," -Q observ Choose CIE Observer for spectrometer or CCSS colorimeter data:\n"); - fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2, 1964_10c\n"); + fprintf(stderr," 1931_2 (def), 1964_10, 2012_2, 2012_10, S&B 1955_2, shaw, J&V 1978_2, 1964_10c or file.cmf\n"); } fprintf(stderr," -I b|w Drift compensation, Black: -Ib, White: -Iw, Both: -Ibw\n"); fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n"); @@ -1702,6 +1730,8 @@ int main(int argc, char *argv[]) { ccss *ccs = NULL; /* Colorimeter Calibration Spectral Samples */ int spec = 0; /* Want spectral data from instrument */ icxObserverType obType = icxOT_default; + xspect custObserver[3]; /* If obType = icxOT_custom */ + disprd *dr = NULL; /* Display patch read object */ csamp asgrey; /* Main calibration loop test points */ double dispLum = 0.0; /* Display luminence reading */ @@ -1733,12 +1763,18 @@ int main(int argc, char *argv[]) { /* causes warning messages in 10.10. */ /* OS X 10.6+ uses a nominal gamma of 2.2 */ - if (Gestalt(gestaltSystemVersionMajor, &MacMajVers) == noErr + if ( +#ifdef NEVER + Gestalt(gestaltSystemVersionMajor, &MacMajVers) == noErr && Gestalt(gestaltSystemVersionMinor, &MacMinVers) == noErr - && Gestalt(gestaltSystemVersionBugFix, &MacBFVers) == noErr) { - if (MacMajVers >= 10 && MacMinVers >= 6) { + && Gestalt(gestaltSystemVersionBugFix, &MacBFVers) == noErr + && MacMajVers >= 10 && MacMinVers >= 6 +#else + floor(kCFCoreFoundationVersionNumber) >= kCFCoreFoundationVersionNumber10_6 +#endif + + ) { g_def_gamma = 2.4; - } } #endif /* >= 1040 */ } @@ -1818,7 +1854,7 @@ int main(int argc, char *argv[]) { ccdisp = atoi(na+3); if (ccdisp <= 0) - usage(0,"ChromCast number must be in range 1..N"); + usage(0,"ChromeCast number must be in range 1..N"); } fa = nfa; #ifdef NT @@ -1916,6 +1952,10 @@ int main(int argc, char *argv[]) { obType = icxOT_CIE_1931_2; } else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */ obType = icxOT_CIE_1964_10; + } else if (strcmp(na, "2012_2") == 0) { /* Latest 2 degree */ + obType = icxOT_CIE_2012_2; + } else if (strcmp(na, "2012_10") == 0) { /* Latest 10 degree */ + obType = icxOT_CIE_2012_10; } else if (strcmp(na, "1964_10c") == 0) { /* 10 degree corrected */ obType = icxOT_CIE_1964_10c; } else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */ @@ -1924,8 +1964,11 @@ int main(int argc, char *argv[]) { obType = icxOT_Judd_Voss_2; } else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */ obType = icxOT_Shaw_Fairchild_2; - } else - usage(0,"-Q parameter '%s' not recognised",na); + } else { /* Assume it's a filename */ + obType = icxOT_custom; + if (read_cmf(custObserver, na) != 0) + usage(0,"Failed to read custom observer CMF from -Q file '%s'",na); + } /* Change color callout */ } else if (argv[fa][1] == 'C') { @@ -2288,13 +2331,13 @@ int main(int argc, char *argv[]) { /* If we've requested ChromeCast, look it up */ if (ccdisp) { if ((ccids = get_ccids()) == NULL) - error("discovering ChromCasts failed"); + error("discovering ChromeCasts failed"); if (ccids[0] == NULL) - error("There are no ChromCasts to use\n"); + error("There are no ChromeCasts to use\n"); for (i = 0; ccids[i] != NULL; i++) ; if (ccdisp < 1 || ccdisp > i) - error("Chosen ChromCasts (%d) is outside list (1..%d)\n",ccdisp,i); + error("Chosen ChromeCasts (%d) is outside list (1..%d)\n",ccdisp,i); ccid = ccids[ccdisp-1]; } @@ -2353,7 +2396,7 @@ int main(int argc, char *argv[]) { cmx != NULL ? cmx->cc_cbid : 0, cmx != NULL ? cmx->matrix : NULL, ccs != NULL ? ccs->samples : NULL, ccs != NULL ? ccs->no_samp : 0, - spec, obType, NULL, bdrift, wdrift, + spec, obType, custObserver, bdrift, wdrift, "fake" ICC_FILE_EXT, g_log)) == NULL) error("new_disprd() failed with '%s'\n",disprd_err(errc)); @@ -2409,10 +2452,10 @@ int main(int argc, char *argv[]) { wp[0] = w[0]/(w[0] + w[1] + w[2]); wp[1] = w[1]/(w[0] + w[1] + w[2]); - cct = comp_ct(&cct_de, NULL, 1, 0, obType, w); /* Compute CCT */ - cdt = comp_ct(&cdt_de, NULL, 0, 0, obType, w); /* Compute CDT */ - vct = comp_ct(&vct_de, NULL, 1, 1, obType, w); /* Compute VCT */ - vdt = comp_ct(&vdt_de, NULL, 0, 1, obType, w); /* Compute VDT */ + cct = comp_ct(&cct_de, NULL, 1, 0, obType, custObserver, w); /* Compute CCT */ + cdt = comp_ct(&cdt_de, NULL, 0, 0, obType, custObserver, w); /* Compute CDT */ + vct = comp_ct(&vct_de, NULL, 1, 1, obType, custObserver, w); /* Compute VCT */ + vdt = comp_ct(&vdt_de, NULL, 0, 1, obType, custObserver, w); /* Compute VDT */ /* Compute advertised current gamma - use the gross curve shape for robustness */ cgamma = pop_gamma(tcols[0].XYZ[1], tcols[1].XYZ[1], tcols[2].XYZ[1]); @@ -3193,9 +3236,9 @@ int main(int argc, char *argv[]) { } else if (temp > 0.0) { /* Daylight color temperature */ double XYZ[3]; if (planckian) - rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL); + rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL, 0); else - rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL); + rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL, 0); if (rv != 0) error("Failed to compute XYZ of target color temperature %f\n",temp); icmXYZ2Yxy(tYxy, XYZ); @@ -3222,7 +3265,7 @@ int main(int argc, char *argv[]) { } else { /* Target is native white */ printf("\nAdjust R,G & B gain to desired white point. Press space when done.\n"); /* Compute the CT and delta E to white locus of target */ - ct = comp_ct(&ct_de, NULL, planckian, dovct, obType, tcols[0].XYZ); + ct = comp_ct(&ct_de, NULL, planckian, dovct, obType, custObserver, tcols[0].XYZ); printf(" Initial Br %.2f, x %.4f , y %.4f , %c%cT %4.0fK DE 2K %4.1f\n", tarw, tYxy[1],tYxy[2], dovct ? 'V' : 'C', planckian ? 'C' : 'D', ct,ct_de); @@ -3264,7 +3307,7 @@ int main(int argc, char *argv[]) { } else { /* Target is native white */ double lxyz[3]; /* Locus XYZ */ - ct = comp_ct(&ct_de, lxyz, planckian, dovct, obType, tcols[0].XYZ); + ct = comp_ct(&ct_de, lxyz, planckian, dovct, obType, custObserver, tcols[0].XYZ); icmXYZ2Yxy(tYxy, lxyz); /* lxyz is already normalised */ @@ -3476,9 +3519,9 @@ int main(int argc, char *argv[]) { } else if (temp > 0.0) { /* Daylight color temperature */ double XYZ[3]; if (planckian) - rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL); + rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL, 0); else - rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL); + rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL, 0); if (rv != 0) error("Failed to compute XYZ of target color temperature %f\n",temp); icmXYZ2Yxy(tYxy, XYZ); @@ -3652,9 +3695,9 @@ int main(int argc, char *argv[]) { } else if (temp > 0.0) { /* Daylight color temperature */ double XYZ[3]; if (planckian) - rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL); + rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Ptemp, temp, NULL, 0); else - rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL); + rv = icx_ill_sp2XYZ(XYZ, icxOT_default, NULL, icxIT_Dtemp, temp, NULL, 0); if (rv != 0) error("Failed to compute XYZ of target color temperature %f\n",temp); icmXYZ2Yxy(tYxy, XYZ); @@ -3695,7 +3738,7 @@ int main(int argc, char *argv[]) { icmXYZ2Lab(&tXYZ, bLab, bLab); /* And color temperature */ - ct = comp_ct(&ct_de, NULL, planckian, dovct, obType, tcols[2].XYZ); + ct = comp_ct(&ct_de, NULL, planckian, dovct, obType, custObserver, tcols[2].XYZ); printf("\n"); @@ -4187,9 +4230,9 @@ int main(int argc, char *argv[]) { } else if (temp > 0.0) { /* Daylight color temperature */ if (planckian) - rv = icx_ill_sp2XYZ(x.twh, icxOT_default, NULL, icxIT_Ptemp, temp, NULL); + rv = icx_ill_sp2XYZ(x.twh, icxOT_default, NULL, icxIT_Ptemp, temp, NULL, 0); else - rv = icx_ill_sp2XYZ(x.twh, icxOT_default, NULL, icxIT_Dtemp, temp, NULL); + rv = icx_ill_sp2XYZ(x.twh, icxOT_default, NULL, icxIT_Dtemp, temp, NULL, 0); if (rv != 0) error("Failed to compute XYZ of target color temperature %f\n",temp); //printf("~1 Raw target from temp %f XYZ = %f %f %f\n",temp,x.twh[0],x.twh[1],x.twh[2]); @@ -4360,7 +4403,7 @@ int main(int argc, char *argv[]) { 0.2, /* Background relative to reference white */ 80.0, /* Display is 80 cd/m^2 */ 0.0, 0.01, x.nwh, /* 0% flare and 1% glare same white point */ - 0, 1.0); + 0, 1.0, 0.0, NULL); break; case gt_Rec709: @@ -4371,7 +4414,7 @@ int main(int argc, char *argv[]) { 0.2, /* Background relative to reference white */ 1000.0/3.1415, /* Luminance of white in the Image field (cd/m^2) */ 0.0, 0.01, x.nwh, /* 0% flare and 1% glare same white point */ - 0, 1.0); + 0, 1.0, 0.0, NULL); break; default: @@ -4384,7 +4427,7 @@ int main(int argc, char *argv[]) { 0.2, /* Background relative to reference white */ x.twh[1], /* Target white level (cd/m^2) */ 0.0, 0.01, x.nwh, /* 0% flare and 1% glare same white point */ - 0, 1.0); + 0, 1.0, 0.0, NULL); /* Compute the normalisation values */ x.svc->XYZ_to_cam(x.svc, Jab, x.nwh); /* Relative white point */ diff --git a/spectro/dispread.c b/spectro/dispread.c index 4c96b76..5e332cc 100644..100755 --- a/spectro/dispread.c +++ b/spectro/dispread.c @@ -53,8 +53,8 @@ #include "copyright.h" #include "aconfig.h" #include "numlib.h" -#include "xspect.h" #include "cgats.h" +#include "xspect.h" #include "insttypes.h" #include "conv.h" #include "icoms.h" @@ -98,7 +98,7 @@ static int gcc_bug_fix(int i) { */ /* Flag = 0x0000 = default */ -/* Flag & 0x0001 = list ChromCast's */ +/* Flag & 0x0001 = list ChromeCast's */ void usage(int flag, char *diag, ...) { int i; disppath **dp; @@ -141,10 +141,10 @@ void usage(int flag, char *diag, ...) { if (flag & 0x001) { ccast_id **ids; if ((ids = get_ccids()) == NULL) { - fprintf(stderr," ** Error discovering ChromCasts **\n"); + fprintf(stderr," ** Error discovering ChromeCasts **\n"); } else { if (ids[0] == NULL) - fprintf(stderr," ** No ChromCasts found **\n"); + fprintf(stderr," ** No ChromeCasts found **\n"); else { int i; for (i = 0; ids[i] != NULL; i++) @@ -165,8 +165,8 @@ void usage(int flag, char *diag, ...) { for (i = 0; ; i++) { if (paths[i] == NULL) break; - if ((paths[i]->itype == instSpyder1 && setup_spyd2(0) == 0) - || (paths[i]->itype == instSpyder2 && setup_spyd2(1) == 0)) + if ((paths[i]->dtype == instSpyder1 && setup_spyd2(0) == 0) + || (paths[i]->dtype == instSpyder2 && setup_spyd2(1) == 0)) fprintf(stderr," %d = '%s' !! Disabled - no firmware !!\n",i+1,paths[i]->name); else fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name); @@ -201,7 +201,7 @@ void usage(int flag, char *diag, ...) { if (cap2 & inst2_ccss) { fprintf(stderr," -X file.ccss Use Colorimeter Calibration Spectral Samples for calibration\n"); fprintf(stderr," -Q observ Choose CIE Observer for spectrometer or CCSS colorimeter data:\n"); - fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2, 1964_10c\n"); + fprintf(stderr," 1931_2 (def), 1964_10, 2012_2, 2012_10, S&B 1955_2, shaw, J&V 1978_2, 1964_10c or file.cmf\n"); } fprintf(stderr," -I b|w Drift compensation, Black: -Ib, White: -Iw, Both: -Ibw\n"); fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n"); @@ -252,6 +252,7 @@ int main(int argc, char *argv[]) { ccss *ccs = NULL; /* Colorimeter Calibration Spectral Samples */ int spec = 0; /* Don't save spectral information */ icxObserverType obType = icxOT_default; + xspect custObserver[3]; /* If obType = icxOT_custom */ int webdisp = 0; /* NZ for web display, == port number */ int ccdisp = 0; /* NZ for ChromeCast, == list index */ ccast_id **ccids = NULL; @@ -356,7 +357,7 @@ int main(int argc, char *argv[]) { ccdisp = atoi(na+3); if (ccdisp <= 0) - usage(0,"ChromCast number must be in range 1..N"); + usage(0,"ChromeCast number must be in range 1..N"); } fa = nfa; #ifdef NT @@ -531,6 +532,10 @@ int main(int argc, char *argv[]) { obType = icxOT_CIE_1931_2; } else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */ obType = icxOT_CIE_1964_10; + } else if (strcmp(na, "2012_2") == 0) { /* Latest 2 degree */ + obType = icxOT_CIE_2012_2; + } else if (strcmp(na, "2012_10") == 0) { /* Latest 10 degree */ + obType = icxOT_CIE_2012_10; } else if (strcmp(na, "1964_10c") == 0) { /* 10 degree corrected */ obType = icxOT_CIE_1964_10c; } else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */ @@ -539,9 +544,11 @@ int main(int argc, char *argv[]) { obType = icxOT_Judd_Voss_2; } else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */ obType = icxOT_Shaw_Fairchild_2; - } else - usage(0,"-Q parameter '%s' not recognised",na); - + } else { /* Assume it's a filename */ + obType = icxOT_custom; + if (read_cmf(custObserver, na) != 0) + usage(0,"Failed to read custom observer CMF from -Q file '%s'",na); + } /* Change color callout */ } else if (argv[fa][1] == 'C') { @@ -683,13 +690,13 @@ int main(int argc, char *argv[]) { /* If we've requested ChromeCast, look it up */ if (ccdisp) { if ((ccids = get_ccids()) == NULL) - error("discovering ChromCasts failed"); + error("discovering ChromeCasts failed"); if (ccids[0] == NULL) - error("There are no ChromCasts to use\n"); + error("There are no ChromeCasts to use\n"); for (i = 0; ccids[i] != NULL; i++) ; if (ccdisp < 1 || ccdisp > i) - error("Chosen ChromCasts (%d) is outside list (1..%d)\n",ccdisp,i); + error("Chosen ChromeCasts (%d) is outside list (1..%d)\n",ccdisp,i); ccid = ccids[ccdisp-1]; } @@ -924,7 +931,7 @@ int main(int argc, char *argv[]) { cmx != NULL ? cmx->cc_cbid : 0, cmx != NULL ? cmx->matrix : NULL, ccs != NULL ? ccs->samples : NULL, ccs != NULL ? ccs->no_samp : 0, - spec, obType, NULL, bdrift, wdrift, + spec, obType, custObserver, bdrift, wdrift, "fake" ICC_FILE_EXT, g_log)) == NULL) error("new_disprd failed with '%s'\n",disprd_err(errc)); @@ -1083,7 +1090,7 @@ int main(int argc, char *argv[]) { ocg->add_kword(ocg, 0, "NORMALIZED_TO_Y_100","NO", NULL); /* Write out the calibration if we have it */ - if (cal != NULL && cal[0][0] >= 0.0) { + if (cal[0][0] >= 0.0) { ocg->add_other(ocg, "CAL"); /* our special type is Calibration file */ ocg->add_table(ocg, tt_other, 1); /* Add another table for RAMDAC values */ ocg->add_kword(ocg, 1, "DESCRIPTOR", "Argyll Device Calibration State",NULL); diff --git a/spectro/dispsup.c b/spectro/dispsup.c index 281912d..21e847f 100644..100755 --- a/spectro/dispsup.c +++ b/spectro/dispsup.c @@ -32,9 +32,11 @@ #include <sys/types.h> #include <time.h> #include <string.h> +#include <ctype.h> #include "copyright.h" #include "aconfig.h" #include "numlib.h" +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" diff --git a/spectro/dispsup.h b/spectro/dispsup.h index 07a66e2..07a66e2 100644..100755 --- a/spectro/dispsup.h +++ b/spectro/dispsup.h diff --git a/spectro/disptechs.c b/spectro/disptechs.c index bade777..bade777 100644..100755 --- a/spectro/disptechs.c +++ b/spectro/disptechs.c diff --git a/spectro/disptechs.h b/spectro/disptechs.h index 9860eac..9860eac 100644..100755 --- a/spectro/disptechs.h +++ b/spectro/disptechs.h diff --git a/spectro/dispwin.c b/spectro/dispwin.c index 368f707..7761db1 100644..100755 --- a/spectro/dispwin.c +++ b/spectro/dispwin.c @@ -17,6 +17,15 @@ /* TTBD * + * Should add support for XRandR 1.5 MST support, so that a Monitor driven + * by multiple CRTCs gets treated as a single item. (How does Xinerama emulation + * handle this though ?) - i.e. might have to duplicate profile atoms, + * set both VideoLUTs when one is set, deal with EDID/ucmm confusion etc. + * Note that XRandR Xinerama emulation changes with v1.5 and MST. + * + * Should look at MSWin & OS X uninstall profile function, and see if + * requirement of supplying profile name can be removed (just like X11 case). + * * Should probably check the display attributes (like visual depth) * and complain if we aren't using 24 bit color or better. * @@ -56,7 +65,7 @@ #include "numlib.h" #include "cgats.h" #include "conv.h" -#include "xicc.h" +# include "xicc.h" #include "disptechs.h" #include "dispwin.h" #include "ui.h" @@ -66,6 +75,9 @@ #ifdef NT # include "madvrwin.h" #endif +#include "insttypes.h" +#include "inst.h" +#include "icoms.h" #if defined(UNIX_X11) # include <dlfcn.h> # if defined(USE_UCMM) @@ -92,6 +104,7 @@ */ #include <Foundation/Foundation.h> +#include <CoreFoundation/CoreFoundation.h> #include <AppKit/AppKit.h> @@ -153,8 +166,9 @@ CFUUIDRef CGDisplayCreateUUIDFromDisplayID (uint32_t displayID); #endif -/* ----------------------------------------------- */ -/* Dealing with locating displays */ +/* ===================================================================== */ +/* Display enumeration code */ +/* ===================================================================== */ int callback_ddebug = 0; /* Diagnostic global for get_displays() and get_a_display() */ /* and events */ @@ -597,11 +611,16 @@ disppath **get_displays() { } #if RANDR_MAJOR == 1 && RANDR_MINOR >= 2 && !defined(DISABLE_RANDR) - /* Use Xrandr 1.2 if it's available, and if it's not disabled */ + /* Use Xrandr 1.2 if it's available, and if it's not disabled. */ if (getenv("ARGYLL_IGNORE_XRANDR1_2") == NULL && XRRQueryExtension(mydisplay, &evb, &erb) != 0 && XRRQueryVersion(mydisplay, &majv, &minv) && majv == 1 && minv >= 2) { + static void *xrr_found = NULL; /* .so handle */ + static XRRScreenResources *(*_XRRGetScreenResourcesCurrent) + (Display *dpy, Window window) = NULL; + static RROutput (*_XRRGetOutputPrimary)(Display *dpy, Window window) = NULL; + int defsix; /* Default Screen index */ if (XSetErrorHandler(null_error_handler) == 0) { debugrr("get_displays failed on XSetErrorHandler\n"); @@ -610,20 +629,38 @@ disppath **get_displays() { return NULL; } + /* Get functions available in Xrandr V1.3 */ + if (minv >= 3 && xrr_found == NULL) { + if ((xrr_found = dlopen("libXrandr.so", RTLD_LAZY)) != NULL) { + _XRRGetScreenResourcesCurrent = dlsym(xrr_found, "XRRGetScreenResourcesCurrent"); + _XRRGetOutputPrimary = dlsym(xrr_found, "XRRGetOutputPrimary"); + } + } + + /* Hmm. Do Xrandr systems alway have only one Screen, */ + /* just like Xinerama ? */ dcount = ScreenCount(mydisplay); - /* Go through all the screens */ + debugrr2((errout,"get_displays using %d XRandR Screens\n",dcount)); + + /* Not sure what to do with this. */ + /* Should we go through X11 screens with this first ? */ + /* (How does Xrandr translate Screen 1..n to Xinerama ?????) */ + defsix = DefaultScreen(mydisplay); + + /* In order to be in sync with an application using Xinerama, */ + /* we need to generate our screen indexes in the same */ + /* order as Xinerama. */ + + /* Go through all the X11 screens */ for (i = 0; i < dcount; i++) { - static void *xrr_found = NULL; /* .so handle */ - static XRRScreenResources *(*_XRRGetScreenResourcesCurrent) - (Display *dpy, Window window) = NULL; XRRScreenResources *scrnres; - int jj; /* Screen index */ - - if (minv >= 3 && xrr_found == NULL) { - if ((xrr_found = dlopen("libXrandr.so", RTLD_LAZY)) != NULL) - _XRRGetScreenResourcesCurrent = dlsym(xrr_found, "XRRGetScreenResourcesCurrent"); - } + int has_primary = 0; + int pix = -1; /* CRTC index containing primary */ + int pop = -1; /* Output index containing primary */ + int jj; /* Xinerama screen ix */ + int xj; /* working crtc index */ + int xk; /* working output index */ if (minv >= 3 && _XRRGetScreenResourcesCurrent != NULL) { scrnres = _XRRGetScreenResourcesCurrent(mydisplay, RootWindow(mydisplay,i)); @@ -637,70 +674,150 @@ disppath **get_displays() { free_disppaths(disps); return NULL; } + /* We have to scan through CRTC's & outputs in the same order */ + /* as the XRANDR XInerama implementation in the X server. */ + /* This is a little tricky, as we need to do the primary output, */ + /* first, while keeping the rest in order. */ + + /* Locate the crtc index that contains the primary (if any) */ + if (minv >= 3 && _XRRGetOutputPrimary != NULL) { + XID primary; /* Primary output ID */ + + primary = _XRRGetOutputPrimary(mydisplay, RootWindow(mydisplay,i)); + debugrr2((errout,"XRRGetOutputPrimary returned XID %x\n",primary)); + + if (primary != None) { + for (j = 0; j < scrnres->ncrtc; j++) { + XRRCrtcInfo *crtci = NULL; + + if ((crtci = XRRGetCrtcInfo(mydisplay, scrnres, scrnres->crtcs[j])) == NULL) + continue; + + if (crtci->mode == None || crtci->noutput == 0) { + XRRFreeCrtcInfo(crtci); + continue; + } + + for (k = 0; k < crtci->noutput; k++) { + if (crtci->outputs[k] == primary) { + pix = j; + pop = k; + } + } + XRRFreeCrtcInfo(crtci); + } + if (pix < 0) { /* Didn't locate primary */ + debugrr2((errout,"Couldn't locate primary CRTC!\n")); + } else { + debugrr2((errout,"Primary is at CRTC %d Output %d\n",pix,pop)); + has_primary = 1; + } + } + } - /* Look at all the screens outputs */ - for (jj = j = 0; j < scrnres->noutput; j++) { - XRROutputInfo *outi = NULL; + /* Look through all the Screens CRTC's */ + for (jj = xj = j = 0; j < scrnres->ncrtc; j++, xj++) { + char *pp; XRRCrtcInfo *crtci = NULL; - - if ((outi = XRRGetOutputInfo(mydisplay, scrnres, scrnres->outputs[j])) == NULL) { - debugrr("XRRGetOutputInfo failed\n"); - XRRFreeScreenResources(scrnres); - XCloseDisplay(mydisplay); - free_disppaths(disps); - return NULL; + XRROutputInfo *outi0 = NULL; + + if (has_primary) { + if (j == 0) + xj = pix; /* Start with crtc containing primary */ + + else if (xj == pix) /* We've up to primary that we've alread done */ + xj++; /* Skip it */ } - - if (outi->connection == RR_Disconnected || - outi->crtc == None) { - XRRFreeOutputInfo(outi); + + if ((crtci = XRRGetCrtcInfo(mydisplay, scrnres, scrnres->crtcs[xj])) == NULL) { + debugrr2((errout,"XRRGetCrtcInfo of Screen %d CRTC %d failed\n",i,xj)); + if (has_primary && j == 0) + xj = -1; /* Start at beginning */ continue; } - /* Check that the VideoLUT's are accessible */ - { - XRRCrtcGamma *crtcgam = NULL; - - debugrr("Checking XRandR 1.2 VideoLUT access\n"); - if ((crtcgam = XRRGetCrtcGamma(mydisplay, outi->crtc)) == NULL - || crtcgam->size == 0) { - fprintf(stderr,"XRandR 1.2 is faulty - falling back to older extensions\n"); + debugrr2((errout,"XRRGetCrtcInfo of Screen %d CRTC %d has %d Outputs %s Mode\n",i,xj,crtci->noutput,crtci->mode == None ? "No" : "Valid")); + + if (crtci->mode == None || crtci->noutput == 0) { + debugrr2((errout,"CRTC skipped as it has no mode or no outputs\n",i,xj,crtci->noutput)); + XRRFreeCrtcInfo(crtci); + if (has_primary && j == 0) + xj = -1; /* Start at beginning */ + continue; + } + + /* This CRTC will now be counted as an Xinerama screen */ + /* For each output of Crtc */ + for (xk = k = 0; k < crtci->noutput; k++, xk++) { + XRROutputInfo *outi = NULL; + + if (has_primary && xj == pix) { + if (k == 0) + xk = pop; /* Start with primary output */ + else if (xk == pop) /* We've up to primary that we've alread done */ + xk++; /* Skip it */ + } + + if ((outi = XRRGetOutputInfo(mydisplay, scrnres, crtci->outputs[xk])) == NULL) { + debugrr2((errout,"XRRGetOutputInfo failed for Screen %d CRTC %d Output %d\n",i,xj,xk)); + goto next_output; + } + if (k == 0) /* Save this so we can label any clones */ + outi0 = outi; + + if (outi->connection == RR_Disconnected) { + debugrr2((errout,"Screen %d CRTC %d Output %d is disconnected\n",i,xj,xk)); + goto next_output; + } + + /* Check that the VideoLUT's are accessible */ + { + XRRCrtcGamma *crtcgam = NULL; + + debugrr("Checking XRandR 1.2 VideoLUT access\n"); + if ((crtcgam = XRRGetCrtcGamma(mydisplay, scrnres->crtcs[xj])) == NULL + || crtcgam->size == 0) { + fprintf(stderr,"XRRGetCrtcGamma failed - falling back to older extensions\n"); + if (crtcgam != NULL) + XRRFreeGamma(crtcgam); + if (outi != NULL && outi != outi0) + XRRFreeOutputInfo(outi); + if (outi0 != NULL) + XRRFreeOutputInfo(outi0); + XRRFreeCrtcInfo(crtci); + XRRFreeScreenResources(scrnres); + free_disppaths(disps); + disps = NULL; + goto done_xrandr; + } if (crtcgam != NULL) XRRFreeGamma(crtcgam); - free_disppaths(disps); - disps = NULL; - j = scrnres->noutput; - i = dcount; - XRRFreeOutputInfo(outi); - continue; /* Abort XRandR 1.2 */ } - if (crtcgam != NULL) - XRRFreeGamma(crtcgam); - } #ifdef NEVER - { - Atom *oprops; - int noprop; + { + Atom *oprops; + int noprop; - /* Get a list of the properties of the output */ - oprops = XRRListOutputProperties(mydisplay, scrnres->outputs[j], &noprop); + /* Get a list of the properties of the output */ + oprops = XRRListOutputProperties(mydisplay, crtci->outputs[xk], &noprop); - printf("num props = %d\n", noprop); - for (k = 0; k < noprop; k++) { - printf("%d: atom 0x%x, name = '%s'\n", k, oprops[k], XGetAtomName(mydisplay, oprops[k])); + printf("num props = %d\n", noprop); + for (k = 0; k < noprop; k++) { + printf("%d: atom 0x%x, name = '%s'\n", k, oprops[k], XGetAtomName(mydisplay, oprops[k])); + } } - } #endif /* NEVER */ - if ((crtci = XRRGetCrtcInfo(mydisplay, scrnres, outi->crtc)) != NULL) { - char *pp; - /* Add the output to the list */ + debugrr2((errout,"Adding Screen %d CRTC %d Output %d\n",i,xj,xk)); if (disps == NULL) { if ((disps = (disppath **)calloc(sizeof(disppath *), 1 + 1)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); - XRRFreeOutputInfo(outi); + if (outi != NULL && outi != outi0) + XRRFreeOutputInfo(outi); + if (outi0 != NULL) + XRRFreeOutputInfo(outi0); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); return NULL; @@ -710,7 +827,10 @@ disppath **get_displays() { sizeof(disppath *) * (ndisps + 2))) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); - XRRFreeOutputInfo(outi); + if (outi != NULL && outi != outi0) + XRRFreeOutputInfo(outi); + if (outi0 != NULL) + XRRFreeOutputInfo(outi0); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); return NULL; @@ -721,44 +841,49 @@ disppath **get_displays() { if ((disps[ndisps] = calloc(sizeof(disppath),1)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); - XRRFreeOutputInfo(outi); + if (outi != NULL && outi != outi0) + XRRFreeOutputInfo(outi); + if (outi0 != NULL) + XRRFreeOutputInfo(outi0); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); free_disppaths(disps); return NULL; } - disps[ndisps]->screen = i; - disps[ndisps]->uscreen = i; - disps[ndisps]->rscreen = i; + disps[ndisps]->screen = i; /* X11 (virtual) Screen */ + disps[ndisps]->uscreen = jj; /* Xinerama/Xrandr screen */ + disps[ndisps]->rscreen = jj; disps[ndisps]->sx = crtci->x; disps[ndisps]->sy = crtci->y; disps[ndisps]->sw = crtci->width; disps[ndisps]->sh = crtci->height; - disps[ndisps]->crtc = outi->crtc; /* XID of crtc */ - disps[ndisps]->output = scrnres->outputs[j]; /* XID of output */ + disps[ndisps]->crtc = scrnres->crtcs[xj]; /* XID of CRTC */ + disps[ndisps]->output = crtci->outputs[xk]; /* XID of output */ - sprintf(desc1,"Screen %d, Output %s",ndisps+1,outi->name); + sprintf(desc1,"Monitor %d, Output %s",ndisps+1,outi->name); sprintf(desc2,"%s at %d, %d, width %d, height %d",desc1, disps[ndisps]->sx, disps[ndisps]->sy, disps[ndisps]->sw, disps[ndisps]->sh); - /* See if it is a clone */ - for (k = 0; k < ndisps; k++) { - if (disps[k]->crtc == disps[ndisps]->crtc) { - sprintf(desc1, "[ Clone of %d ]",k+1); - strcat(desc2, desc1); - } + /* If it is a clone */ + if (k > 0 & outi0 != NULL) { + sprintf(desc1, "[ Clone of %s ]",outi0->name); + strcat(desc2, desc1); } + if ((disps[ndisps]->description = strdup(desc2)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); - XRRFreeOutputInfo(outi); + if (outi != NULL && outi != outi0) + XRRFreeOutputInfo(outi); + if (outi0 != NULL) + XRRFreeOutputInfo(outi0); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); free_disppaths(disps); return NULL; } - + /* Form the display name */ if ((pp = strrchr(dnbuf, ':')) != NULL) { if ((pp = strchr(pp, '.')) != NULL) { @@ -768,27 +893,29 @@ disppath **get_displays() { if ((disps[ndisps]->name = strdup(dnbuf)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); - XRRFreeOutputInfo(outi); + if (outi != NULL && outi != outi0) + XRRFreeOutputInfo(outi); + if (outi0 != NULL) + XRRFreeOutputInfo(outi0); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); free_disppaths(disps); return NULL; } debugrr2((errout, "Display %d name = '%s'\n",ndisps,disps[ndisps]->name)); - + /* Create the X11 root atom of the default screen */ - /* that may contain the associated ICC profile */ - /* (The _%d variant will probably break with non-Xrandr */ - /* aware software if Xrandr is configured to have more than */ - /* a single virtual screen.) */ + /* that may contain the associated ICC profile. */ if (jj == 0) strcpy(desc1, "_ICC_PROFILE"); else - sprintf(desc1, "_ICC_PROFILE_%d",jj); + sprintf(desc1, "_ICC_PROFILE_%d",disps[ndisps]->uscreen); if ((disps[ndisps]->icc_atom = XInternAtom(mydisplay, desc1, False)) == None) error("Unable to intern atom '%s'",desc1); + debugrr2((errout,"Root atom '%s'\n",desc1)); + /* Create the atom of the output that may contain the associated ICC profile */ if ((disps[ndisps]->icc_out_atom = XInternAtom(mydisplay, "_ICC_PROFILE", False)) == None) error("Unable to intern atom '%s'","_ICC_PROFILE"); @@ -810,19 +937,22 @@ disppath **get_displays() { for (ii = 0; keys[ii][0] != '\000'; ii++) { /* Get the atom for the EDID data */ if ((edid_atom = XInternAtom(mydisplay, keys[ii], True)) == None) { - debugrr2((errout, "Unable to intern atom '%s'\n",keys[ii])); + // debugrr2((errout, "Unable to intern atom '%s'\n",keys[ii])); /* Try the next key */ - } else { - /* Get the EDID_DATA */ - if (XRRGetOutputProperty(mydisplay, scrnres->outputs[j], edid_atom, + /* Get the EDID_DATA */ + } else { + if (XRRGetOutputProperty(mydisplay, crtci->outputs[xk], edid_atom, 0, 0x7ffffff, False, False, XA_INTEGER, &ret_type, &ret_format, &ret_len, &ret_togo, &atomv) == Success && (ret_len == 128 || ret_len == 256)) { if ((disps[ndisps]->edid = malloc(sizeof(unsigned char) * ret_len)) == NULL) { debugrr("get_displays failed on malloc\n"); XRRFreeCrtcInfo(crtci); - XRRFreeOutputInfo(outi); + if (outi != NULL && outi != outi0) + XRRFreeOutputInfo(outi); + if (outi0 != NULL) + XRRFreeOutputInfo(outi0); XRRFreeScreenResources(scrnres); XCloseDisplay(mydisplay); free_disppaths(disps); @@ -840,22 +970,30 @@ disppath **get_displays() { if (keys[ii][0] == '\000') debugrr2((errout, "Failed to get EDID for display\n")); } - - jj++; /* Next enabled index */ ndisps++; /* Now it's number of displays */ - XRRFreeCrtcInfo(crtci); + + next_output:; + if (outi != NULL && outi != outi0) + XRRFreeOutputInfo(outi); + if (has_primary && xj == pix && k == 0) + xk = -1; /* Go to first output */ } - XRRFreeOutputInfo(outi); + next_screen:; + if (outi0 != NULL) + XRRFreeOutputInfo(outi0); + XRRFreeCrtcInfo(crtci); + jj++; /* Next Xinerama screen index */ + if (has_primary && j == 0) + xj = -1; /* Go to first screen */ } XRRFreeScreenResources(scrnres); } + done_xrandr:; XSetErrorHandler(NULL); - defsix = DefaultScreen(mydisplay); } #endif /* randr >= V 1.2 */ if (disps == NULL) { /* Use Older style identification */ - debugrr("get_displays checking for Xinerama\n"); if (XSetErrorHandler(null_error_handler) == 0) { debugrr("get_displays failed on XSetErrorHandler\n"); @@ -863,7 +1001,8 @@ disppath **get_displays() { return NULL; } - if (XineramaQueryExtension(mydisplay, &evb, &erb) != 0 + if (getenv("ARGYLL_IGNORE_XINERAMA") == NULL + && XineramaQueryExtension(mydisplay, &evb, &erb) != 0 && XineramaIsActive(mydisplay)) { xai = XineramaQueryScreens(mydisplay, &dcount); @@ -873,10 +1012,10 @@ disppath **get_displays() { XCloseDisplay(mydisplay); return NULL; } - defsix = 0; + debugrr2((errout,"get_displays using %d Xinerama Screens\n",dcount)); } else { dcount = ScreenCount(mydisplay); - defsix = DefaultScreen(mydisplay); + debugrr2((errout,"get_displays using %d X11 Screens\n",dcount)); } /* Allocate our list */ @@ -903,7 +1042,10 @@ disppath **get_displays() { /* Form the display name */ if ((pp = strrchr(dnbuf, ':')) != NULL) { if ((pp = strchr(pp, '.')) != NULL) { - sprintf(pp,".%d",i); + if (xai != NULL) /* Xinerama */ + sprintf(pp,".%d",0); + else + sprintf(pp,".%d",i); } } if ((disps[i]->name = strdup(dnbuf)) == NULL) { @@ -915,14 +1057,15 @@ disppath **get_displays() { debugrr2((errout, "Display %d name = '%s'\n",i,disps[i]->name)); if (xai != NULL) { /* Xinerama */ - disps[i]->screen = 0; /* We are asuming Xinerame creates a single virtual screen */ - disps[i]->uscreen = i; /* We are assuming xinerama lists screens in the same order */ + /* xai[i].screen_number should be == i */ + disps[i]->screen = 0; /* Assume Xinerame creates a single virtual X11 screen */ + disps[i]->uscreen = i; /* Underlying Xinerma screen */ disps[i]->rscreen = i; disps[i]->sx = xai[i].x_org; disps[i]->sy = xai[i].y_org; disps[i]->sw = xai[i].width; disps[i]->sh = xai[i].height; - } else { + } else { /* Plain X11 Screens */ disps[i]->screen = i; disps[i]->uscreen = i; disps[i]->rscreen = i; @@ -992,9 +1135,9 @@ disppath **get_displays() { && monitor.model != NULL && monitor.model[0] != '\000') sprintf(desc1, "%s",monitor.model); else - sprintf(desc1,"Screen %d",i+1); + sprintf(desc1,"Monitor %d",i+1); } else - sprintf(desc1,"Screen %d",i+1); + sprintf(desc1,"Monitor %d",i+1); sprintf(desc2,"%s at %d, %d, width %d, height %d",desc1, disps[i]->sx, disps[i]->sy, disps[i]->sw, disps[i]->sh); @@ -1006,14 +1149,15 @@ disppath **get_displays() { } } XSetErrorHandler(NULL); - } - /* Put the screen given by the display name at the top */ - { - disppath *tdispp; - tdispp = disps[defsix]; - disps[defsix] = disps[0]; - disps[0] = tdispp; + /* Put the default Screen the top of the list */ + if (xai == NULL) { + int defsix = DefaultScreen(mydisplay); + disppath *tdispp; + tdispp = disps[defsix]; + disps[defsix] = disps[0]; + disps[0] = tdispp; + } } if (xai != NULL) @@ -1087,6 +1231,8 @@ disppath *get_a_display(int ix) { disppath **paths, *rv = NULL; int i; + debugrr2((errout, "get_a_display called with ix %d\n",ix)); + if ((paths = get_displays()) == NULL) return NULL; @@ -1095,8 +1241,9 @@ disppath *get_a_display(int ix) { free_disppaths(paths); return NULL; } - if (i == ix) + if (i == ix) { break; + } } if ((rv = malloc(sizeof(disppath))) == NULL) { debugrr("get_a_display failed malloc\n"); @@ -1129,6 +1276,8 @@ disppath *get_a_display(int ix) { memmove(rv->edid, paths[i]->edid, rv->edid_len ); } #endif + debugrr2((errout, " Selected ix %d '%s' %s'\n",i,rv->name,rv->description)); + free_disppaths(paths); return rv; } @@ -1147,7 +1296,9 @@ void free_a_disppath(disppath *path) { } } -/* ----------------------------------------------- */ +/* ===================================================================== */ +/* RAMDAC access code */ +/* ===================================================================== */ /* For VideoLUT/RAMDAC use, we assume that the frame buffer */ /* may map through some intermediate hardware or lookup */ @@ -1465,7 +1616,7 @@ static char *iprof_path(p_scope scope, char *fname) { dirname = COLORSYNC_DIR_LOCAL; else { dirname = COLORSYNC_DIR_USER; - if ((home = getenv("HOME")) == NULL){ + if ((home = login_HOME()) == NULL){ return NULL; } } @@ -2273,7 +2424,10 @@ void dispwin_del_ramdac(ramdac *r) { free(r); } -/* ----------------------------------------------- */ +/* ===================================================================== */ +/* Profile install code */ +/* ===================================================================== */ + /* Useful function for X11 profile atom settings */ #if defined(UNIX_X11) @@ -2283,7 +2437,10 @@ static int set_X11_atom(dispwin *p, char *fname) { unsigned long psize, bread; unsigned char *atomv; - debugr("Setting _ICC_PROFILE property\n"); + if (p->myuscreen == 0) + debugr("Setting _ICC_PROFILE property\n"); + else + debugr2((errout,"Setting _ICC_PROFILE_%d property\n",p->myuscreen)); /* Read in the ICC profile, then set the X11 atom value */ #if !defined(O_CREAT) && !defined(_O_CREAT) @@ -2323,11 +2480,13 @@ static int set_X11_atom(dispwin *p, char *fname) { fclose(fp); - XChangeProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom, + if (p->icc_atom != None) { + XChangeProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom, XA_CARDINAL, 8, PropModeReplace, atomv, psize); + } #if RANDR_MAJOR == 1 && RANDR_MINOR >= 2 && !defined(DISABLE_RANDR) - if (p->icc_out_atom != 0) { + if (p->icc_out_atom != None) { /* If Xrandr 1.2, set property on output */ /* This seems to fail on some servers. Ignore the error ? */ if (XSetErrorHandler(null_error_handler) == 0) { @@ -2351,7 +2510,8 @@ static int set_X11_atom(dispwin *p, char *fname) { } #endif /* UNXI X11 */ -/* ----------------------------------------------- */ +/* ---------------------------------------------- */ + /* See if colord is available */ #if defined(UNIX_X11) && defined(USE_UCMM) @@ -2373,7 +2533,8 @@ int dispwin_checkfor_colord() { cd_found = NULL; - if ((cd_found = dlopen("libcolordcompat.so", RTLD_LAZY)) != NULL) { + if (getenv("ARGYLL_USE_COLORD") != NULL + && (cd_found = dlopen("libcolordcompat.so", RTLD_LAZY)) != NULL) { cd_edid_install_profile = dlsym(cd_found, "cd_edid_install_profile"); cd_edid_remove_profile = dlsym(cd_found, "cd_edid_remove_profile"); @@ -2394,7 +2555,6 @@ int dispwin_checkfor_colord() { #endif - /* ----------------------------------------------- */ /* Install a display profile and make */ /* it the default for this display. */ @@ -2630,7 +2790,7 @@ int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) { return 0; } -#else /* 10.6 and prior */ +#else /* OS X 10.6 and prior */ // Switch to using iprof_path() to simplify ? { CMError ev; @@ -2766,8 +2926,9 @@ int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) { /* Un-Install a display profile */ /* Return nz if failed, */ -/* 1 if not sucessfully deleted */ +/* 1 if not successfully deleted */ /* 2 if profile not found */ +/* NT and OS X need fname, *NIX does not. */ int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) { debugr2((errout,"dispwin_uninstall_profile '%s'\n", fname)); #ifdef NT @@ -2883,7 +3044,7 @@ int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) { } debug2((errout,"Set euid %d and egid %d\n",uid,gid)); } - /* If setting local system proile and not effective root, but sudo */ + /* If setting local system profile and not effective root, but sudo */ } else if (scope != p_scope_user && getuid() == 0 && geteuid() != 0) { if (getenv("SUDO_UID") != NULL && getenv("SUDO_GID") != NULL) { @@ -3029,14 +3190,15 @@ int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) { if (cd_found) ev = cd_edid_remove_profile(p->edid, p->edid_len, fname); else - ev = ucmm_uninstall_monitor_profile(sc, p->edid, p->edid_len, p->name, fname); + ev = ucmm_uninstall_monitor_profile(sc, p->edid, p->edid_len, p->name); if (ev != ucmm_ok) { debugr2((errout,"Installing profile '%s' failed with error %d '%s'\n",fname,ev,ucmm_error_string(ev))); return 1; } - XDeleteProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom); + if (p->icc_atom != None) + XDeleteProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom); #if RANDR_MAJOR == 1 && RANDR_MINOR >= 2 && !defined(DISABLE_RANDR) /* If Xrandr 1.2, set property on output */ @@ -3254,6 +3416,7 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) { debugr2((errout,"Setting X11 atom to profile '%s' failed",profile)); /* Hmm. We ignore this error */ } + free(profile); return rd_fp; } if (ev != ucmm_no_profile) { @@ -3291,9 +3454,14 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) { #endif /* randr >= V 1.2 */ if (atomv == NULL) { + if (p->icc_atom == None) { + debugr("Second or subsequent Output doesn't have ICC_PROFILE property\n"); + return NULL; + } + if (p->myuscreen != 0) sprintf(aname, "_ICC_PROFILE_%d",p->myuscreen); - + /* Get the ICC profile property */ if (XGetWindowProperty(p->mydisplay, RootWindow(p->mydisplay, 0), p->icc_atom, 0, 0x7ffffff, False, XA_CARDINAL, @@ -3336,7 +3504,7 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) { return NULL; } -/* ----------------------------------------------- */ +/* ===================================================================== */ /* Restore the display state and free ramdacs */ static void restore_display(dispwin *p) { @@ -3416,6 +3584,8 @@ static void dispwin_sighandler(int arg) { static amutex_static(lock); dispwin *pp, *np; + debugrr("dispwin_sighandler called\n"); + /* Make sure we don't re-enter */ if (amutex_trylock(lock)) { return; @@ -3483,7 +3653,10 @@ static void dispwin_uninstall_signal_handlers(dispwin *p) { p->next = NULL; } -/* ----------------------------------------------- */ +/* ===================================================================== */ +/* Test patch window code */ +/* ===================================================================== */ + /* Test patch window specific declarations */ #ifdef UNIX_APPLE @@ -3531,6 +3704,7 @@ unsigned char emptyCursor[43] = { * the mouse enters the window. This needs the main thread * to be dedicated to running the event loop, so would involve * some trickiness after main() in every program. + * - we have done this with numlib/ui.c, so this is possible. */ - (void)resetCursorRects { [super resetCursorRects]; @@ -3671,8 +3845,7 @@ static void create_my_win(void *cntx) { /* Moves the window to the front of the screen list within its level, */ /* and show the window (i.e. make it "key") */ - /* Trigger warning on OS X 10.11 El Capitan ? */ - /* (Doesn't happen using 1.6.3 which ran everything in the main thread.) */ + /* Trigger warning on OS X 10.11 El Capitan if not run in the main thread. */ [cx->window makeKeyAndOrderFront: nil]; /* Use a null color transform to ensure device values */ @@ -3720,17 +3893,23 @@ static void create_my_win(void *cntx) { #endif /* >= 10.6 */ #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 - /* >= 10.6+ device colors don't work on secondary display, need null transform. */ - /* < 10.6 null transform doesn't work. */ + /* >= 10.6+ device colors don't work on secondary displays and need a null transform. */ + /* < 10.6 null transform doesn't work, but isn't needed. */ - if (Gestalt(gestaltSystemVersionMajor, &MacMajVers) == noErr + if ( +#ifdef NEVER + Gestalt(gestaltSystemVersionMajor, &MacMajVers) == noErr && Gestalt(gestaltSystemVersionMinor, &MacMinVers) == noErr && Gestalt(gestaltSystemVersionBugFix, &MacBFVers) == noErr && MacMajVers >= 10 && MacMinVers >= 6 +#else + floor(kCFCoreFoundationVersionNumber) >= kCFCoreFoundationVersionNumber10_6 +#endif + && cx->nscs == NULL) { warning("Unable to create null color transform - test colors may be wrong!"); } -#endif +#endif /* >= 1040 */ cx->err = 0; } @@ -3750,7 +3929,7 @@ double r, double g, double b /* Color values 0.0 - 1.0 */ double kr, kf; int update_delay = 0; - debugr("dispwin_set_color called\n"); + debugrr2((errout, "dispwin_set_color called on disp '%s'\n",p->name)); if (p->nowin) { return 1; @@ -3941,8 +4120,15 @@ double r, double g, double b /* Color values 0.0 - 1.0 */ /* Stop the system going to sleep */ UpdateSystemActivity(OverallAct); +/* + replacement ? + IOPMAssertionID assertionID; + IOPMAssertionDeclareUserActivity(CFSTR(""), kIOPMUserActiveLocal, &assertionID); +*/ + /* Make sure our window is brought to the front at least once, */ /* but not every time, in case the user wants to kill the application. */ + /* is orderFrontRegardless a replacement ?? */ if (p->btf == 0){ OSStatus stat; ProcessSerialNumber cpsn; @@ -4748,6 +4934,11 @@ int ddebug /* >0 to print debug statements to stderr */ dispwin_del(p); return NULL; } + if ((p->description = strdup(disp->description)) == NULL) { + debugr2((errout,"new_dispwin: Malloc failed\n")); + dispwin_del(p); + return NULL; + } p->ddid = disp->ddid; /* Display we're working on */ #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 @@ -4816,7 +5007,7 @@ int ddebug /* >0 to print debug statements to stderr */ if (p->rdepth != p->ndepth) { if (!p->warned) { - warning("new_dispwin: Frame buffer depth %d doesn't matcv VideoLUT %d",p->rdepth, p->ndepth); + warning("new_dispwin: Frame buffer depth %d doesn't match VideoLUT %d",p->rdepth, p->ndepth); p->warned = 1; } } @@ -4975,20 +5166,25 @@ int ddebug /* >0 to print debug statements to stderr */ /* open the display */ p->mydisplay = XOpenDisplay(bname); - if(!p->mydisplay) { - debugr2((errout,"new_dispwin: Unable to open display '%s'\n",bname)); + if (!p->mydisplay) { + debugrr2((errout,"new_dispwin: Unable to open display '%s'\n",bname)); dispwin_del(p); free(bname); return NULL; } + debugrr2((errout,"new_dispwin: Opened display '%s' OK\n",bname)); free(bname); - debugr("new_dispwin: Opened display OK\n"); if ((p->name = strdup(disp->name)) == NULL) { debugr2((errout,"new_dispwin: Malloc failed\n")); dispwin_del(p); return NULL; } + if ((p->description = strdup(disp->description)) == NULL) { + debugr2((errout,"new_dispwin: Malloc failed\n")); + dispwin_del(p); + return NULL; + } p->myscreen = disp->screen; p->myuscreen = disp->uscreen; p->myrscreen = disp->rscreen; @@ -5181,7 +5377,7 @@ int ddebug /* >0 to print debug statements to stderr */ } } - debugr2((errout,"new_dispwin: %s fdepth %d, rdepth %d, ndepth %d, edepth %d, r/g/b shifts %d %d %d\n", vinfo->class != TrueColor ? "TreuColor" : "DirectColor", p->fdepth,p->rdepth,p->ndepth,p->edepth, p->shift[0], p->shift[1], p->shift[2])); + debugrr2((errout,"new_dispwin: %s fdepth %d, rdepth %d, ndepth %d, edepth %d, r/g/b shifts %d %d %d\n", vinfo->class != TrueColor ? "TreuColor" : "DirectColor", p->fdepth,p->rdepth,p->ndepth,p->edepth, p->shift[0], p->shift[1], p->shift[2])); if (nowin == 0) { /* Create a window */ unsigned long attrmask = 0; @@ -5228,6 +5424,8 @@ int ddebug /* >0 to print debug statements to stderr */ p->ww = wi; p->wh = he; + debugrr2((errout,"new_dispwin: at %d, %d size %d, %d\n",p->tx,p->ty,p->ww,p->wh)); + /* Setup Size Hints */ mysizehints.flags = PPosition | USSize; mysizehints.x = xo; @@ -5630,7 +5828,7 @@ int ddebug /* >0 to print debug statements to stderr */ p->native = native &= ~2; } - debugr("new_dispwin: return sucessfully\n"); + debugr("new_dispwin: return successfully\n"); return p; } @@ -5887,7 +6085,8 @@ static int gcc_bug_fix(int i) { #include "numlib.h" /* Flag = 0x0000 = default */ -/* Flag & 0x0001 = list ChromCast's */ +/* Flag & 0x0001 = list ChromeCast's */ +/* Flag & 0x0002 = list VTPG's's */ static void usage(int flag, char *diag, ...) { disppath **dp; fprintf(stderr,"Test display patch window, Set Video LUTs, Install profiles, Version %s\n",ARGYLL_VERSION_STR); @@ -5923,13 +6122,13 @@ static void usage(int flag, char *diag, ...) { free_disppaths(dp); fprintf(stderr," -dweb[:port] Display via web server at port (default 8080)\n"); fprintf(stderr," -dcc[:n] Display via n'th ChromeCast (default 1, ? for list)\n"); - if (flag & 0x001) { + if (flag & 0x0001) { ccast_id **ids; if ((ids = get_ccids()) == NULL) { - fprintf(stderr," ** Error discovering ChromCasts **\n"); + fprintf(stderr," ** Error discovering ChromeCasts **\n"); } else { if (ids[0] == NULL) - fprintf(stderr," ** No ChromCasts found **\n"); + fprintf(stderr," ** No ChromeCasts found **\n"); else { int i; for (i = 0; ids[i] != NULL; i++) @@ -5942,8 +6141,28 @@ static void usage(int flag, char *diag, ...) { fprintf(stderr," -dmadvr Display via MadVR Video Renderer\n"); #endif +#ifdef ENABLE_VTPGLUT + fprintf(stderr," -dvtpg[:n] Display via n'th Video Test Patch Generator (default 1, ? for list)\n"); + if (flag & 0x0002) { + icompaths *icmps; + if ((icmps = new_icompaths_sel(g_log, icomt_vtpg | icomt_portattr_all)) != NULL) { + icompath **paths; + if ((paths = icmps->dpaths[dtix_vtpg]) != NULL) { + int i; + for (i = 0; ; i++) { + if (paths[i] == NULL) + break; + fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name); + } + } else + fprintf(stderr," ** No VTPG's found **\n"); + } + } +#endif + fprintf(stderr," -P ho,vo,ss[,vs] Position test window and scale it\n"); fprintf(stderr," -F Fill whole screen with black background\n"); + fprintf(stderr," -E Video encode output as (16-235)/255 \"TV\" levels\n"); fprintf(stderr," -i Run forever with random values\n"); fprintf(stderr," -G filename Display RGB colors from CGATS (ie .ti1) file\n"); fprintf(stderr," -C r.rr,g.gg,b.bb Add this RGB color to list to be displayed\n"); @@ -5954,7 +6173,7 @@ static void usage(int flag, char *diag, ...) { fprintf(stderr," -s filename Save the currently loaded Video LUT to 'filename'\n"); fprintf(stderr," -c Load a linear display calibration\n"); fprintf(stderr," -V Verify that calfile/profile cal. is currently loaded in LUT\n"); - fprintf(stderr," -I Install profile for display and use it's calibration\n"); + fprintf(stderr," -I Install profile for display and use its calibration\n"); fprintf(stderr," -U Un-install profile for display\n"); fprintf(stderr," -S d Specify the install/uninstall scope for OS X [nlu] or X11/Vista [lu]\n"); fprintf(stderr," d is one of: n = network, l = local system, u = user (default)\n"); @@ -5981,6 +6200,9 @@ main(int argc, char *argv[]) { #ifdef NT int madvrdisp = 0; /* NZ for MadVR display */ #endif +#ifdef ENABLE_VTPGLUT + int vtpgdisp = 0; /* NZ for Video Test Pattern Generator, == list index */ +#endif disppath *disp = NULL; /* Display being used */ double hpatscale = 1.0, vpatscale = 1.0; /* scale factor for test patch size */ double ho = 0.0, vo = 0.0; /* Test window offsets, -1.0 to 1.0 */ @@ -6073,7 +6295,7 @@ main(int argc, char *argv[]) { ccdisp = atoi(na+3); if (ccdisp <= 0) - usage(0,"ChromCast number must be in range 1..N"); + usage(0,"ChromeCast number must be in range 1..N"); } fa = nfa; #ifdef NT @@ -6082,6 +6304,20 @@ main(int argc, char *argv[]) { madvrdisp = 1; fa = nfa; #endif +#ifdef ENABLE_VTPGLUT + } else if (strncmp(na,"vtpg",4) == 0 + || strncmp(na,"VTPG",4) == 0) { + vtpgdisp = 1; + if (na[4] == ':') { + if (na[3] < '0' || na[3] > '9') + usage(0x0002,"Available VTPG's"); + + vtpgdisp = atoi(na+3); + if (vtpgdisp <= 0) + usage(0,"VTPG number must be in range 1..N"); + } + fa = nfa; +#endif /* ENABLE_VTPGLUT */ } else { #if defined(UNIX_X11) int ix, iv; @@ -6259,8 +6495,13 @@ main(int argc, char *argv[]) { #endif /* Bomb on bad combinations (not all are being detected) */ - if (installprofile && calname[0] == '\000') - error("Can't install or uninstall a displays profile without profile argument"); + if (installprofile == 1 && calname[0] == '\000') + error("Can't install a displays profile without profile argument"); + +#if !defined(UNIX) + if (installprofile == 2 && calname[0] == '\000') + error("Can't uninstall a displays profile without profile argument"); +#endif if (verify && calname[0] == '\000' && loadprofile == 0) error("No calibration/profile provided to verify against"); @@ -6285,17 +6526,17 @@ main(int argc, char *argv[]) { } else if (ccdisp != 0) { ccast_id **ids; if ((ids = get_ccids()) == NULL) { - printf("Error - discovering ChromCasts failed\n"); + printf("Error - discovering ChromeCasts failed\n"); return -1; } if (ids[0] == NULL) { - printf("Error - there are no ChromCasts to use\n"); + printf("Error - there are no ChromeCasts to use\n"); return -1; } for (i = 0; ids[i] != NULL; i++) ; if (ccdisp < 1 || ccdisp > i) { - printf("Error - chosen ChromCasts (%d) is outside list (1..%d)\n",ccdisp,i); + printf("Error - chosen ChromeCasts (%d) is outside list (1..%d)\n",ccdisp,i); return -1; } @@ -6427,10 +6668,10 @@ main(int argc, char *argv[]) { if (rv == 2) warning("Profile '%s' not found to uninstall!",calname); else - error("Error trying to uninstall profile '%s'!",calname); + error("Error trying to uninstall profile for display '%s'!",dw->description); } if (verb) { - printf("Un-Installed '%s'\n",calname); + printf("Un-Installed profile for display '%s'\n",dw->description); } } @@ -6582,25 +6823,28 @@ main(int argc, char *argv[]) { dw->r->v[j][i] = val + w * (cal[j][ix+1] - val); } } - /* If the calibration was created with a restricted range video encoding, */ - /* ensure that the installed calibration applies this encoding. */ - if (out_tvenc) { - for (i = 0; i < dw->r->nent; i++) { - for (j = 0; j < 3; j++) { - dw->r->v[j][i] = (dw->r->v[j][i] * (235.0-16.0) + 16.0)/255.0; - - /* For video encoding the extra bits of precision are created by bit */ - /* shifting rather than scaling, so we need to scale the fp value to */ - /* account for this. */ - if (dw->edepth > 8) - dw->r->v[j][i] = (dw->r->v[j][i] * 255 * (1 << (dw->edepth - 8))) - /((1 << dw->edepth) - 1.0); - } + debug("Got cal file calibration\n"); + } + + /* If the calibration was created with a restricted range video encoding, */ + /* ensure that the installed calibration applies this encoding. */ + if (out_tvenc) { + if (verb) + printf("Using output TV encoding range of (16-235)/255\n"); + for (i = 0; i < dw->r->nent; i++) { + for (j = 0; j < 3; j++) { + dw->r->v[j][i] = (dw->r->v[j][i] * (235.0-16.0) + 16.0)/255.0; + + /* For video encoding the extra bits of precision are created by bit */ + /* shifting rather than scaling, so we need to scale the fp value to */ + /* account for this. */ + if (dw->edepth > 8) + dw->r->v[j][i] = (dw->r->v[j][i] * 255 * (1 << (dw->edepth - 8))) + /((1 << dw->edepth) - 1.0); } } - - debug("Got cal file calibration\n"); } + if (ccg != NULL) ccg->del(ccg); if (icco != NULL) diff --git a/spectro/dispwin.h b/spectro/dispwin.h index 47fd256..8130d5f 100644..100755 --- a/spectro/dispwin.h +++ b/spectro/dispwin.h @@ -118,10 +118,10 @@ typedef struct { CGDirectDisplayID ddid; #endif /* UNIX_APPLE */ #if defined(UNIX_X11) - int screen; /* Screen to select */ - int uscreen; /* Underlying screen */ - int rscreen; /* Underlying RAMDAC screen */ - Atom icc_atom; /* ICC profile root atom for this display */ + int screen; /* X11 (possibly virtual) Screen */ + int uscreen; /* Underlying Xinerma/XRandr screen */ + int rscreen; /* Underlying RAMDAC screen (user override) */ + Atom icc_atom; /* ICC profile root/output atom for this display */ unsigned char *edid; /* 128 or 256 bytes of monitor EDID, NULL if none */ int edid_len; /* 128 or 256 */ @@ -272,9 +272,9 @@ struct _dispwin { #if defined(UNIX_X11) Display *mydisplay; - int myscreen; /* Usual or virtual screen with Xinerama */ - int myuscreen; /* Underlying screen */ - int myrscreen; /* Underlying RAMDAC screen */ + int myscreen; /* Overall X11 (possibly virtual) Screen */ + int myuscreen; /* Underlying Xinerma/Xrandr screen */ + int myrscreen; /* Underlying RAMDAC screen (user override) */ Atom icc_atom; /* ICC profile root atom for this display */ unsigned char *edid; /* 128 or 256 bytes of monitor EDID, NULL if none */ int edid_len; /* 128 or 256 */ diff --git a/spectro/dtp20.c b/spectro/dtp20.c index a125a53..c33dc3d 100644..100755 --- a/spectro/dtp20.c +++ b/spectro/dtp20.c @@ -67,6 +67,7 @@ #include "sa_config.h" #endif /* SALONEINSTLIB */ #include "numsup.h" +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -1737,7 +1738,7 @@ inst_opt_type m, /* Requested status type */ } /* Constructor */ -extern dtp20 *new_dtp20(icoms *icom, instType itype) { +extern dtp20 *new_dtp20(icoms *icom, instType dtype) { dtp20 *p; if ((p = (dtp20 *)calloc(sizeof(dtp20),1)) == NULL) { a1loge(icom->log, 1, "new_dtp20: malloc failed!\n"); @@ -1761,7 +1762,7 @@ extern dtp20 *new_dtp20(icoms *icom, instType itype) { p->del = dtp20_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; p->cap = inst_mode_none; /* Unknown until set */ p->mode = inst_mode_none; /* Not in a known mode yet */ diff --git a/spectro/dtp20.h b/spectro/dtp20.h index a8b6862..a8b6862 100644..100755 --- a/spectro/dtp20.h +++ b/spectro/dtp20.h diff --git a/spectro/dtp22.c b/spectro/dtp22.c index 37249f0..34a8506 100644..100755 --- a/spectro/dtp22.c +++ b/spectro/dtp22.c @@ -51,6 +51,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* !SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -97,9 +98,7 @@ extract_ec(char *s) { if (*p == '>') break; } - if ( (p-3) < s - || p[0] != '>' - || p[-3] != '<') + if ((p-3) < s || p[0] != '>' || p[-3] != '<') return -1; tt[0] = p[-2]; tt[1] = p[-1]; @@ -517,8 +516,8 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ } } } else { /* Inst error or switch activated */ - if (strlen(buf) >= 4 - && buf[0] == '<' && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>') { + if ((strlen(buf) >= 4 + && buf[0] == '<' && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>')) { if ((ev = dtp22_interp_code((inst *)p, extract_ec(buf))) != inst_ok) { dtp22_command(p, "CE\r", buf, MAX_MES_SIZE, 0.5); dtp22_command(p, "2PB\r", buf, MAX_MES_SIZE, 0.5); @@ -747,8 +746,8 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ } } } else { /* Inst error or switch activated */ - if (strlen(buf) >= 4 - && buf[0] == '<' && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>') { + if ((strlen(buf) >= 4 + && buf[0] == '<' && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>')) { if ((ev = dtp22_interp_code((inst *)p, extract_ec(buf))) != inst_ok) { dtp22_command(p, "CE\r", buf, MAX_MES_SIZE, 0.5); if (ev != inst_ok) @@ -1145,7 +1144,7 @@ extern dtp22 *new_dtp22(icoms *icom, instType itype) { p->del = dtp22_del; p->icom = icom; - p->itype = itype; + p->dtype = itype; p->mode = inst_mode_none; p->need_cal = 1; /* Do a white calibration each time we open the device */ diff --git a/spectro/dtp22.h b/spectro/dtp22.h index af565e8..af565e8 100644..100755 --- a/spectro/dtp22.h +++ b/spectro/dtp22.h diff --git a/spectro/dtp41.c b/spectro/dtp41.c index 97a3db1..e536cfc 100644..100755 --- a/spectro/dtp41.c +++ b/spectro/dtp41.c @@ -48,6 +48,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* !SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -1331,7 +1332,7 @@ dtp41_get_set_opt(inst *pp, inst_opt_type m, ...) } /* Constructor */ -extern dtp41 *new_dtp41(icoms *icom, instType itype) { +extern dtp41 *new_dtp41(icoms *icom, instType dtype) { dtp41 *p; if ((p = (dtp41 *)calloc(sizeof(dtp41),1)) == NULL) { a1loge(icom->log, 1, "new_dtp41: malloc failed!\n"); @@ -1354,7 +1355,7 @@ extern dtp41 *new_dtp41(icoms *icom, instType itype) { p->del = dtp41_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; p->cap = inst_mode_none; /* Unknown until set */ p->mode = inst_mode_none; /* Not in a known mode yet */ p->nstaticr = 5; /* Number of static readings */ diff --git a/spectro/dtp41.h b/spectro/dtp41.h index 018ed5c..018ed5c 100644..100755 --- a/spectro/dtp41.h +++ b/spectro/dtp41.h diff --git a/spectro/dtp51.c b/spectro/dtp51.c index 0b2ecab..70932e5 100644..100755 --- a/spectro/dtp51.c +++ b/spectro/dtp51.c @@ -51,6 +51,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* !SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -896,7 +897,7 @@ dtp51_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern dtp51 *new_dtp51(icoms *icom, instType itype) { +extern dtp51 *new_dtp51(icoms *icom, instType dtype) { dtp51 *p; if ((p = (dtp51 *)calloc(sizeof(dtp51),1)) == NULL) { a1loge(icom->log, 1, "new_dtp51: malloc failed!\n"); @@ -918,7 +919,7 @@ extern dtp51 *new_dtp51(icoms *icom, instType itype) { p->del = dtp51_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; p->native_calstd = xcalstd_xrdi; /* Not alterable */ diff --git a/spectro/dtp51.h b/spectro/dtp51.h index 804b8ae..804b8ae 100644..100755 --- a/spectro/dtp51.h +++ b/spectro/dtp51.h diff --git a/spectro/dtp92.c b/spectro/dtp92.c index 33b8fa0..fbcbd7e 100644..100755 --- a/spectro/dtp92.c +++ b/spectro/dtp92.c @@ -51,6 +51,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* !SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -179,7 +180,7 @@ dtp92_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { char *brc[5] = { "30BR\r", "60BR\r", "18BR\r", "0CBR\r", "06BR\r" }; char *fcc; unsigned int etime; - instType itype = pp->itype; + instType dtype = pp->dtype; int ci, bi, i, se; inst_code ev = inst_ok; @@ -202,7 +203,7 @@ dtp92_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { /* */ /* Set config, interface, write end point, read end point, read quanta */ - if (itype == instDTP94) { + if (dtype == instDTP94) { wr_ep = 0x02; rd_ep = 0x81; } else { @@ -407,17 +408,17 @@ dtp92_init_inst(inst *pp) { return inst_unknown_model; if (strncmp(buf,"X-Rite DTP94",12) == 0) - p->itype = instDTP94; + p->dtype = instDTP94; else - p->itype = instDTP92; + p->dtype = instDTP92; - if (p->itype == instDTP92) { + if (p->dtype == instDTP92) { /* Turn echoing of characters off */ if ((ev = dtp92_command(p, "DEC\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) return ev; } - if (p->itype == instDTP92) { + if (p->dtype == instDTP92) { /* Set decimal point on */ if ((ev = dtp92_command(p, "0106CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) return ev; @@ -435,7 +436,7 @@ dtp92_init_inst(inst *pp) { if ((ev = dtp92_command(p, "010ACF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) return ev; - if (p->itype == instDTP92) { + if (p->dtype == instDTP92) { /* Set absolute (luminance) calibration */ if ((ev = dtp92_command(p, "0118CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) return ev; @@ -449,13 +450,13 @@ dtp92_init_inst(inst *pp) { if ((ev = dtp92_command(p, "EFC\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) return ev; - if (p->itype == instDTP94) { + if (p->dtype == instDTP94) { /* Compensate for offset drift */ if ((ev = dtp92_command(p, "0117CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) return ev; } - if (p->itype == instDTP92) { + if (p->dtype == instDTP92) { /* Enable ABS mode (in case firmware doesn't default to this after EFC) */ if ((ev = dtp92_command(p, "0118CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) return ev; @@ -505,7 +506,7 @@ dtp92_init_inst(inst *pp) { /* ??? Need to set CTYP appropriately ??? */ #ifdef NEVER /* Debug code */ - if (p->itype == instDTP94) { + if (p->dtype == instDTP94) { int i, val; char tb[50]; @@ -571,7 +572,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ /* Could change SS to suite level expected. */ #ifdef NEVER - if (p->itype == instDTP92) { + if (p->dtype == instDTP92) { /* Set sample size to 31 (default is 16) for low level readings */ if ((rv = dtp92_command(p, "1fSS\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) return rv; @@ -652,7 +653,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ } #ifdef NEVER - if (p->itype == instDTP92) { + if (p->dtype == instDTP92) { /* Set sample size back to 16 */ if ((rv = dtp92_command(p, "10SS\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) return rv; @@ -759,7 +760,7 @@ static inst_code dtp92_get_n_a_cals(inst *pp, inst_cal_type *pn_cals, inst_cal_t inst_cal_type n_cals = inst_calt_none; inst_cal_type a_cals = inst_calt_none; - if (p->itype == instDTP92) { + if (p->dtype == instDTP92) { if (p->need_ratio_cal) n_cals |= inst_calt_emis_ratio; a_cals |= inst_calt_emis_ratio; @@ -1058,7 +1059,7 @@ inst3_capability *pcap3) { | inst2_ccmx ; /* The '92 does have a switch, but we're not currently supporting it */ - if (p->itype == instDTP94) { + if (p->dtype == instDTP94) { cap2 |= inst2_disptype; } else { cap2 |= inst2_get_refresh_rate; @@ -1167,7 +1168,7 @@ static inst_disptypesel dtp94_disptypesel[4] = { }; static void set_base_disptype_list(dtp92 *p) { - if (p->itype == instDTP94) { + if (p->dtype == instDTP94) { p->_dtlist = dtp94_disptypesel; } else { p->_dtlist = dtp92_disptypesel; @@ -1218,7 +1219,7 @@ static inst_code set_disp_type(dtp92 *p, inst_disptypesel *dentry) { p->cbid = dentry->cbid; p->ucbid = dentry->cbid; /* is underying base if dentry is base selection */ - if (p->itype == instDTP92) { + if (p->dtype == instDTP92) { if (p->icx != 0) return inst_unsupported; @@ -1395,7 +1396,7 @@ dtp92_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern dtp92 *new_dtp92(icoms *icom, instType itype) { +extern dtp92 *new_dtp92(icoms *icom, instType dtype) { dtp92 *p; if ((p = (dtp92 *)calloc(sizeof(dtp92),1)) == NULL) { a1loge(icom->log, 1, "new_dtp92: malloc failed!\n"); @@ -1423,7 +1424,7 @@ extern dtp92 *new_dtp92(icoms *icom, instType itype) { p->del = dtp92_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; icmSetUnity3x3(p->ccmat); /* Set the colorimeter correction matrix to do nothing */ set_base_disptype_list(p); diff --git a/spectro/dtp92.h b/spectro/dtp92.h index 8a6885e..8a6885e 100644..100755 --- a/spectro/dtp92.h +++ b/spectro/dtp92.h diff --git a/spectro/ex1.c b/spectro/ex1.c index 5f4eae2..929af3d 100644..100755 --- a/spectro/ex1.c +++ b/spectro/ex1.c @@ -54,6 +54,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* !SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -158,7 +159,7 @@ static int ex1_touch_calibration(ex1 *p); static inst_code ex1_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { ex1 *p = (ex1 *) pp; - instType itype = pp->itype; + instType dtype = pp->dtype; int se; inst_code ev = inst_ok; @@ -1210,7 +1211,7 @@ ex1_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern ex1 *new_ex1(icoms *icom, instType itype) { +extern ex1 *new_ex1(icoms *icom, instType dtype) { ex1 *p; if ((p = (ex1 *)calloc(sizeof(ex1),1)) == NULL) { a1loge(icom->log, 1, "new_ex1: malloc failed!\n"); @@ -1241,7 +1242,7 @@ extern ex1 *new_ex1(icoms *icom, instType itype) { p->del = ex1_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; p->want_dcalib = 1; /* Always do an initial dark calibration */ diff --git a/spectro/ex1.h b/spectro/ex1.h index a278777..a278777 100644..100755 --- a/spectro/ex1.h +++ b/spectro/ex1.h diff --git a/spectro/fakeread.c b/spectro/fakeread.c index 3cad93a..3cad93a 100644..100755 --- a/spectro/fakeread.c +++ b/spectro/fakeread.c diff --git a/spectro/hcfr.c b/spectro/hcfr.c index 22b5170..568c69f 100644..100755 --- a/spectro/hcfr.c +++ b/spectro/hcfr.c @@ -53,6 +53,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -125,7 +126,7 @@ hcfr_flush( int rv; for (rv = ICOM_OK;;) { - rv = c->read(c, buf, MAX_MES_SIZE, NULL, '\000', 100000, 0.05); + rv = c->read(c, buf, MAX_MES_SIZE, NULL, NULL, 100000, 0.05); if (rv != ICOM_OK) break; /* Expect timeout with nothing to read */ } @@ -933,7 +934,7 @@ hcfr_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern hcfr *new_hcfr(icoms *icom, instType itype) { +extern hcfr *new_hcfr(icoms *icom, instType dtype) { hcfr *p; if ((p = (hcfr *)calloc(sizeof(hcfr),1)) == NULL) { a1loge(icom->log, 1, "new_hcfr: malloc failed!\n"); @@ -957,7 +958,7 @@ extern hcfr *new_hcfr(icoms *icom, instType itype) { p->del = hcfr_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; icmSetUnity3x3(p->ccmat); /* Set the colorimeter correction matrix to do nothing */ p->dtech = disptech_unknown; diff --git a/spectro/hcfr.h b/spectro/hcfr.h index 2420fdf..2420fdf 100644..100755 --- a/spectro/hcfr.h +++ b/spectro/hcfr.h diff --git a/spectro/hidio.c b/spectro/hidio.c index 2d8649f..e78fb98 100644..100755 --- a/spectro/hidio.c +++ b/spectro/hidio.c @@ -73,6 +73,7 @@ #include "sa_config.h" #endif #include "numsup.h" +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -419,6 +420,8 @@ int hid_get_paths(icompaths *p) { /* Add the path to the list */ p->add_hid(p, pname, vid, pid, 0, hidd, itype); + } else { + a1logd(p->log, 4, "skipping HID device VID 0x%x PID 0x%x lid 0x%x that we don't want\n",vid, pid, lid); } if (ioob != 0) /* If we haven't kept it */ IOObjectRelease(ioob); /* Release found object */ diff --git a/spectro/hidio.h b/spectro/hidio.h index 87edd43..87edd43 100644..100755 --- a/spectro/hidio.h +++ b/spectro/hidio.h diff --git a/spectro/huey.c b/spectro/huey.c index 2c82b4c..7739f96 100644..100755 --- a/spectro/huey.c +++ b/spectro/huey.c @@ -49,6 +49,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -885,25 +886,38 @@ huey_check_unlock( if ((ev = huey_command(p, i1d_status, buf, buf, 1.0,1.0)) != inst_ok) return ev; - /* Hmm. Some Lenovo Huey's say they are unlocked, even when they are not. */ + /* Hmm. Some Lenovo Huey's (the HueyColors ?) aren't locked, */ + /* so the unlock command fails. */ if (p->lenovo || strncmp((char *)buf, "Locked", 6) == 0) { memset(buf, 0, 7); + + /* Set unlock codes */ if (p->lenovo) strcpy((char *)buf,"huyL"); else strcpy((char *)buf,"GrMb"); - if ((ev = huey_command(p, i1d_unlock, buf, buf, 1.0,1.0)) != inst_ok) - return ev; + if ((ev = huey_command(p, i1d_unlock, buf, buf, 1.0,1.0)) != inst_ok) { + a1logd(p->log,2,"huey_check_unlock: warning, unlock command returned error\n"); + /* Perhaps the error code is for wrong unlock code, so ignore this */ + /* and try a status command */ + } memset(buf, 0, 7); if ((ev = huey_command(p, i1d_status, buf, buf, 1.0,1.0)) != inst_ok) return ev; } + /* + Apparently the "ECCM3" is a "hueyCOLOR", which is actually + a monochrome sensor! It uses different instructions to the Huey, + and wouldn't be terribly useful to ArgyllCMS. + See <https://github.com/hughsie/colord/tree/master/src/sensors/huey2> + */ + if (strncmp((char *)buf, "huL002", 6) != 0 /* Lenovo Huey ? */ - && strncmp((char *)buf, "ECCM2 ", 6) != 0 /* Lenovo Thinkpad W530 Huey ? */ - && strncmp((char *)buf, "ECCM3 ", 6) != 0 /* Lenovo Thinkpad W530 Huey ? */ + && strncmp((char *)buf, "ECCM2 ", 6) != 0 /* Lenovo Thinkpad W530 HueyPro ? */ +// && strncmp((char *)buf, "ECCM3 ", 6) != 0 /* Lenovo Thinkpad P70 HueyColor ? */ && strncmp((char *)buf, "Cir001", 6) != 0) { /* Huey */ a1logd(p->log,1,"huey_check_unlock: unknown model '%s'\n",buf); return huey_interp_code((inst *)p, HUEY_UNKNOWN_MODEL); @@ -1732,7 +1746,7 @@ huey_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern huey *new_huey(icoms *icom, instType itype) { +extern huey *new_huey(icoms *icom, instType dtype) { huey *p; if ((p = (huey *)calloc(sizeof(huey),1)) == NULL) { a1loge(icom->log, 1, "new_huey: malloc failed!\n"); @@ -1756,7 +1770,7 @@ extern huey *new_huey(icoms *icom, instType itype) { p->del = huey_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; icmSetUnity3x3(p->ccmat); /* Set the colorimeter correction matrix to do nothing */ p->dtech = disptech_unknown; diff --git a/spectro/huey.h b/spectro/huey.h index f13056b..f13056b 100644..100755 --- a/spectro/huey.h +++ b/spectro/huey.h diff --git a/spectro/i1d3.c b/spectro/i1d3.c index 4562a52..7e5c396 100644..100755 --- a/spectro/i1d3.c +++ b/spectro/i1d3.c @@ -53,6 +53,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -125,8 +126,8 @@ typedef enum { i1d3_firmver = 0x0012, /* Firmware version string */ i1d3_firmdate = 0x0013, /* Firmware date string */ i1d3_locked = 0x0020, /* Get locked status */ - i1d3_measure1 = 0x0100, /* Used by all measure */ - i1d3_measure2 = 0x0200, /* Used by all measure except ambient */ + i1d3_freqmeas = 0x0100, /* Measure transition over given time */ + i1d3_periodmeas = 0x0200, /* Measure time between transition count */ i1d3_readintee = 0x0800, /* Read internal EEPROM */ i1d3_readextee = 0x1200, /* Read external EEPROM */ i1d3_setled = 0x2100, /* Set the LED state */ @@ -155,10 +156,10 @@ static char *inst_desc(i1Disp3CC cc) { return "GetFirmwareDate"; case i1d3_locked: return "GetLockedStatus"; - case i1d3_measure1: - return "Measure1"; - case i1d3_measure2: - return "Measure2"; + case i1d3_freqmeas: + return "Frequency Measure"; + case i1d3_periodmeas: + return "Period Measure"; case i1d3_readintee: return "ReadInternalEEPROM"; case i1d3_readextee: @@ -278,9 +279,9 @@ i1d3_command( } /* Hmm. Not sure about this bug workaround. Is this a rev B thing ? */ - /* May get status 0x83 on i1d3_measure2 when there are no transitions ? */ + /* May get status 0x83 on i1d3_periodmeas when there are no transitions ? */ /* If so, ignore the error. */ - if (rv == inst_ok && cc == i1d3_measure2 && recv[1] == 0x02 && recv[0] == 0x83) { + if (rv == inst_ok && cc == i1d3_periodmeas && recv[1] == 0x02 && recv[0] == 0x83) { int i; for (i = 2; i < 14; i++) { if (recv[i] != 0) @@ -587,7 +588,7 @@ i1d3_unlock( struct { char *pname; /* Product name */ unsigned int key[2]; /* Unlock code */ - i1d3_dtype dtype; /* Base type enumerator */ + i1d3_dtype btype; /* Base type enumerator */ i1d3_dtype stype; /* Sub type enumerator */ } codes[] = { { "i1Display3 ", { 0xe9622e9f, 0x8d63e133 }, i1d3_disppro, i1d3_disppro }, @@ -597,6 +598,7 @@ i1d3_unlock( { "i1Display3 ", { 0x160eb6ae, 0x14440e70 }, i1d3_disppro, i1d3_quato_sh3 }, { "i1Display3 ", { 0x291e41d7, 0x51937bdd }, i1d3_disppro, i1d3_hp_dreamc }, { "i1Display3 ", { 0xc9bfafe0, 0x02871166 }, i1d3_disppro, i1d3_sc_c6 }, + { "i1Display3 ", { 0x1abfae03, 0xf25ac8e8 }, i1d3_disppro, i1d3_wacom_dc }, { NULL } }; inst_code ev; @@ -630,7 +632,7 @@ i1d3_unlock( // codes[ix].key[0], codes[ix].key[1]); a1logd(p->log, 3, "i1d3_unlock: Trying unlock key %d/%d\n", ix+1, nix); - p->dtype = codes[ix].dtype; + p->btype = codes[ix].btype; p->stype = codes[ix].stype; /* Attempt unlock */ @@ -778,7 +780,7 @@ i1d3_read_external_eeprom( /* Take a raw measurement using a given integration time. */ /* The measurent is the count of (both) edges from the L2V */ -/* over the integration time */ +/* over the integration time. */ static inst_code i1d3_freq_measure( i1d3 *p, /* Object */ @@ -804,21 +806,31 @@ i1d3_freq_measure( todev[23] = 0; /* Unknown parameter, always 0 */ - if ((ev = i1d3_command(p, i1d3_measure1, todev, fromdev, I1D3_MEAS_TIMEOUT, 0)) != inst_ok) + if ((ev = i1d3_command(p, i1d3_freqmeas, todev, fromdev, I1D3_MEAS_TIMEOUT, 0)) != inst_ok) return ev; rgb[0] = (double)buf2uint(fromdev + 2); rgb[1] = (double)buf2uint(fromdev + 6); rgb[2] = (double)buf2uint(fromdev + 10); + /* The HW holds the L2F *OE high (disabled) until the start of the measurement period, */ + /* and this has the effect of holding the internal integrator in a reset state. */ + /* This then synchronizes the frequency output to the start of */ + /* the measurement, which has the effect of rounding down the count output. */ + /* To compensate, we have to add 0.5 to the count. */ + rgb[0] += 0.5; + rgb[1] += 0.5; + rgb[2] += 0.5; + return inst_ok; } /* Take a raw measurement that returns the number of clocks */ -/* between and initial edge and edgec[] subsequent edges of the L2F. */ -/* The edge count must be between 1 and 65535 inclusive. */ -/* Both edges are counted. It's advisable to use an even edgec[], */ -/* because the L2F output may not be symetric. */ +/* between and initial edge at the start of the period (triggered by */ +/* the *OE going low and the integrator being started) and edgec[] */ +/* subsequent edges of the L2F. The edge count must be between */ +/* 1 and 65535 inclusive. Both edges are counted. It's advisable */ +/* to use an even edgec[], because the L2F output may not be symetric. */ /* If there are no edges within 10 seconds, return a count of 0 */ static inst_code i1d3_period_measure( @@ -841,7 +853,7 @@ i1d3_period_measure( todev[7] = (unsigned char)mask; todev[8] = 0; /* Unknown parameter, always 0 */ - if ((ev = i1d3_command(p, i1d3_measure2, todev, fromdev, I1D3_MEAS_TIMEOUT, 0)) != inst_ok) + if ((ev = i1d3_command(p, i1d3_periodmeas, todev, fromdev, I1D3_MEAS_TIMEOUT, 0)) != inst_ok) return ev; rgb[0] = (double)buf2uint(fromdev + 2); @@ -932,6 +944,9 @@ i1d3_set_LEDs( To break up the USB synchronization, the integration time is randomized slightly. + + NOTE :- we should really switch to using period measurement mode here, + since it is more accurate ? */ #ifndef PSRAND32L @@ -1577,7 +1592,8 @@ i1d3_take_emis_measurement( isth = p->th_en; p->th_en = 0; - /* If we should take a frequency measurement first */ + /* If we should take a frequency measurement first, */ + /* since it is done in a predictable duration */ if (mode == i1d3_adaptive || mode == i1d3_frequency) { /* Typically this is 200msec for non-refresh, 400msec for refresh. */ @@ -1635,7 +1651,7 @@ i1d3_take_emis_measurement( continue; if (rmeas[i] < 10.0 - || (p->dtype != i1d3_munkdisp && rmeas[i] < 20.0)) { + || (p->btype != i1d3_munkdisp && rmeas[i] < 20.0)) { a1logd(p->log,3,"chan %d needs pre-measurement\n",i); mask2 |= 1 << i; } else { @@ -1667,7 +1683,7 @@ i1d3_take_emis_measurement( /* Transfer updated counts from 1st initial measurement */ for (i = 0; i < 3; i++) { if ((mask2 & (1 << i)) != 0) { - rmeas[i] = rmeas2[i]; + rmeas[i] = rmeas2[i]; /* Compute trial RGB in case we need it later */ if (rmeas[i] >= 0.5) { @@ -1680,7 +1696,7 @@ i1d3_take_emis_measurement( /* we are measuring a CRT with a refresh rate which adds innacuracy, */ /* and could result in a unecessarily long re-reading. */ /* Don't do this for Munki Display, because of its slow measurements. */ - if (p->dtype != i1d3_munkdisp) { + if (p->btype != i1d3_munkdisp) { for (i = 0; i < 3; i++) { if ((mask2 & (1 << i)) == 0) continue; @@ -2465,9 +2481,12 @@ i1d3_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { /* something to do with detaching the default HID driver ?? */ #if defined(UNIX_X11) usbflags |= icomuf_detach; - usbflags |= icomuf_no_open_clear; usbflags |= icomuf_reset_before_close; #endif + + /* On MSWin it doesn't like clearing on open when running direct (i.e not HID) */ + usbflags |= icomuf_no_open_clear; + /* Open as an HID if available */ if (p->icom->port_type(p->icom) == icomt_hid) { @@ -2579,7 +2598,7 @@ i1d3_init_inst(inst *pp) { return ev; if (p->prod_type == 0x0002) { /* If ColorMunki Display */ /* Set this in case it doesn't need unlocking */ - p->dtype = p->stype = i1d3_munkdisp; + p->btype = p->stype = i1d3_munkdisp; } if ((ev = i1d3_get_firmver(p, p->firm_ver)) != inst_ok) return ev; @@ -2731,7 +2750,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ } /* Attempt a refresh display frame rate calibration if needed */ - if (p->dtype != i1d3_munkdisp && p->refrmode != 0 && p->rrset == 0) { + if (p->btype != i1d3_munkdisp && p->refrmode != 0 && p->rrset == 0) { inst_code ev = inst_ok; p->mininttime = 2.0 * p->dinttime; @@ -2804,7 +2823,7 @@ double *ref_rate) { if (!p->inited) return inst_no_init; - if (p->dtype == i1d3_munkdisp) + if (p->btype == i1d3_munkdisp) return inst_unsupported; if (ref_rate != NULL) @@ -2928,7 +2947,7 @@ static inst_code i1d3_get_n_a_cals(inst *pp, inst_cal_type *pn_cals, inst_cal_ty inst_cal_type n_cals = inst_calt_none; inst_cal_type a_cals = inst_calt_none; - if (p->dtype != i1d3_munkdisp && p->refrmode != 0) { + if (p->btype != i1d3_munkdisp && p->refrmode != 0) { if (p->rrset == 0) n_cals |= inst_calt_ref_freq; a_cals |= inst_calt_ref_freq; @@ -2988,7 +3007,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ return inst_unsupported; } - if ((*calt & inst_calt_ref_freq) && p->dtype != i1d3_munkdisp && p->refrmode != 0) { + if ((*calt & inst_calt_ref_freq) && p->btype != i1d3_munkdisp && p->refrmode != 0) { inst_code ev = inst_ok; p->mininttime = 2.0 * p->dinttime; @@ -3498,7 +3517,7 @@ inst3_capability *pcap3) { | inst2_set_min_int_time ; - if (p->dtype != i1d3_munkdisp) { + if (p->btype != i1d3_munkdisp) { cap2 |= inst2_meas_disp_update; cap2 |= inst2_get_refresh_rate; cap2 |= inst2_set_refresh_rate; @@ -3865,7 +3884,7 @@ i1d3_get_set_opt(inst *pp, inst_opt_type m, ...) { p->omininttime = dval; /* Hmm. This code is duplicated a lot.. */ - if (p->dtype != i1d3_munkdisp && p->refrmode != 0) { + if (p->btype != i1d3_munkdisp && p->refrmode != 0) { inst_code ev = inst_ok; p->mininttime = 2.0 * p->dinttime; @@ -4038,7 +4057,7 @@ i1d3_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern i1d3 *new_i1d3(icoms *icom, instType itype) { +extern i1d3 *new_i1d3(icoms *icom, instType dtype) { i1d3 *p; if ((p = (i1d3 *)calloc(sizeof(i1d3),1)) == NULL) { @@ -4073,7 +4092,7 @@ extern i1d3 *new_i1d3(icoms *icom, instType itype) { p->del = i1d3_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; amutex_init(p->lock); icmSetUnity3x3(p->ccmat); diff --git a/spectro/i1d3.h b/spectro/i1d3.h index a7c3b24..6152a00 100644..100755 --- a/spectro/i1d3.h +++ b/spectro/i1d3.h @@ -87,7 +87,8 @@ typedef enum { i1d3_nec_ssp = 3, /* NEC SpectraSensor Pro */ i1d3_quato_sh3 = 4, /* Quato Silver Haze 3 */ i1d3_hp_dreamc = 5, /* HP DreameColor */ - i1d3_sc_c6 = 6 /* SpectraCal C6 */ + i1d3_sc_c6 = 6, /* SpectraCal C6 */ + i1d3_wacom_dc = 7 /* Wacom DC */ } i1d3_dtype; /* Measurement mode */ @@ -108,7 +109,7 @@ struct _i1d3 { inst_opt_type trig; /* Reading trigger mode */ /* Information and EEPROM values */ - i1d3_dtype dtype; /* Base type of instrument, ie i1d3_disppro or i1d3_munkdisp */ + i1d3_dtype btype; /* Base type of instrument, ie i1d3_disppro or i1d3_munkdisp */ i1d3_dtype stype; /* Sub type of instrument, ie. any of i1d3_dtype. */ /* (Only accurate if it needed unlocking). */ int status; /* 0 if status is ok (not sure what this is) */ diff --git a/spectro/i1disp.c b/spectro/i1disp.c index 9e4b01f..dfe4a60 100644..100755 --- a/spectro/i1disp.c +++ b/spectro/i1disp.c @@ -47,6 +47,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* !SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -276,7 +277,7 @@ i1disp_rdreg_byte( int rsize; inst_code ev; - if (p->dtype == 0) { + if (p->btype == 0) { if (addr < 0 || addr > 127) return i1disp_interp_code((inst *)p, I1DISP_BAD_REG_ADDRESS); } else { @@ -484,7 +485,7 @@ i1disp_rdexreg_bytes( int ooff, rsize; inst_code ev; - if (p->dtype != 2) /* Only ColorMunki Smile ? */ + if (p->btype != 2) /* Only ColorMunki Smile ? */ return i1disp_interp_code((inst *)p, I1DISP_WRONG_DEVICE); if (addr < 0 || addr > 0x0200) @@ -649,7 +650,7 @@ i1d1_take_measurement( if (p->inited == 0) return i1disp_interp_code((inst *)p, I1DISP_NOT_INITED); - if (p->dtype != 0) + if (p->btype != 0) return i1disp_interp_code((inst *)p, I1DISP_WRONG_DEVICE); /* Do an initial measurement with minimum edge count of 1 */ @@ -858,13 +859,13 @@ i1d2_take_measurement( if (p->inited == 0) return i1disp_interp_code((inst *)p, I1DISP_NOT_INITED); - if (p->dtype == 0) + if (p->btype == 0) return i1disp_interp_code((inst *)p, I1DISP_WRONG_DEVICE); a1logd(p->log, 3, "i1d2_take_measurement called with refreshm = %d\n",refreshm); /* Do refresh period measurement */ - if (p->dtype == 1 && refreshm && p->rrset == 0) { + if (p->btype == 1 && refreshm && p->rrset == 0) { if ((ev = i1disp_do_fcal_setit(p)) != inst_ok) return ev; @@ -1040,13 +1041,13 @@ i1d2_take_measurement( if (p->inited == 0) return i1disp_interp_code((inst *)p, I1DISP_NOT_INITED); - if (p->dtype == 0) + if (p->btype == 0) return i1disp_interp_code((inst *)p, I1DISP_WRONG_DEVICE); a1logd(p->log, 3, "i1d2_take_measurement called with refreshm = %d\n",refreshm); /* Do refresh period measurement */ - if (p->dtype == 1 && refreshm && p->rrset == 0) { + if (p->btype == 1 && refreshm && p->rrset == 0) { if ((ev = i1disp_do_fcal_setit(p)) != inst_ok) return ev; @@ -1238,7 +1239,7 @@ i1disp_take_XYZ_measurement( inst_code ev; double *mat; /* Pointer to matrix */ - if (p->dtype == 0) { /* i1 disp 1 */ + if (p->btype == 0) { /* i1 disp 1 */ if ((ev = i1d1_take_measurement(p, 0, rgb)) != inst_ok) return ev; } else { /* i1 disp 2 or ColorMunki Smile */ @@ -1289,7 +1290,7 @@ i1disp_do_black_cal( double rgb1[3], rgb2[3]; /* RGB Readings */ inst_code ev; - if (p->dtype != 0) + if (p->btype != 0) return i1disp_interp_code((inst *)p, I1DISP_CANT_BLACK_CALIB); /* Do a couple of readings without subtracting the black */ @@ -1331,7 +1332,7 @@ i1disp_read_refrate( a1logd(p->log, 3, "Frequency calibration called\n"); - if (p->dtype != 1) + if (p->btype != 1) return inst_unsupported; if (ref_rate != NULL) @@ -1376,7 +1377,7 @@ i1disp_do_fcal_setit( a1logd(p->log, 3, "Frequency calibration called\n"); - if (p->dtype != 1) + if (p->btype != 1) return i1disp_interp_code((inst *)p, I1DISP_CANT_MEASP_CALIB); if ((ev = i1disp_read_refrate((inst *)p, &p->refrate)) != inst_ok @@ -1410,7 +1411,7 @@ i1disp_check_unlock( struct { unsigned char code[4]; - i1d2_dtype stype; + i1d2_stype stype; } codes[] = { { { 'G','r','M','b' }, i1d2_norm }, /* "GrMb" i1 Display */ { { 'L','i','t','e' }, i1d2_lite }, /* "Lite" i1 Display LT */ @@ -1429,7 +1430,7 @@ i1disp_check_unlock( { { 0x0e,0x0e,0x0e,0x0e }, i1d2_norm }, /* */ { { 0x11,0x02,0xde,0xf0 }, i1d2_norm }, /* Barco Chroma 5 ? */ // { { 0xff,0xff,0xff,0xff }, i1d2_norm }, /* Chroma 5 isn't locked ? */ - { { ' ',' ',' ',' ' }, -1 } + { { ' ',' ',' ',' ' }, i1d2_unkn } }; a1logd(p->log, 3, "i1disp: about to check response and unlock instrument if needed\n"); @@ -1444,7 +1445,7 @@ i1disp_check_unlock( /* Try each code in turn */ for (i = 0; ;i++) { - if (codes[i].stype == -1) { + if (codes[i].stype == i1d2_unkn) { a1logd(p->log, 3, "Failed to find correct unlock code\n"); return i1disp_interp_code((inst *)p, I1DISP_UNKNOWN_MODEL); } @@ -1489,37 +1490,37 @@ i1disp_check_unlock( /* Barco Chroma 5 with ver = 5.01 vv = '5' */ if (ver >= 4.0 && ver < 5.1 && vv == '5') { - p->dtype = 0; /* Sequel Chroma 4 ?? */ + p->btype = 0; /* Sequel Chroma 4 ?? */ p->stype = i1d1_chroma4; /* Treat like an Eye-One Display 1 */ /* Sequel Chroma 4 with vv == 0xff ???? */ /* Sencore ColorPro III with ver = 5.01 and vv = 0xff */ } else if (ver >= 4.0 && ver < 5.1 && vv == 0xff) { - p->dtype = 0; /* Eye-One Display 1 */ + p->btype = 0; /* Eye-One Display 1 */ p->stype = i1d1_sencoreIII; /* Sencore ColorPro IV with ver = 5.01 and vv = 'L' */ } else if (ver >= 4.0 && ver < 5.1 && vv == 'L') { - p->dtype = 0; /* Eye-One Display 1 */ + p->btype = 0; /* Eye-One Display 1 */ p->stype = i1d1_sencoreIV; /* Treat like an Eye-One Display 1 */ /* Sencore ColorPro V with ver = 5.01 and vv = 'B' */ } else if (ver >= 4.0 && ver < 5.1 && vv == 'B') { - p->dtype = 0; /* Eye-One Display 1 */ + p->btype = 0; /* Eye-One Display 1 */ p->stype = i1d1_sencoreV; /* Treat like an Eye-One Display 1 */ } else if (ver >= 5.1 && ver <= 5.3 && vv == 'L') { - p->dtype = 0; /* Eye-One Display 1 */ + p->btype = 0; /* Eye-One Display 1 */ } else if (ver >= 6.0 && ver <= 6.29 && vv == 'L') { - p->dtype = 1; /* Eye-One Display 2 */ + p->btype = 1; /* Eye-One Display 2 */ } else if (ver >= 6.0 && ver <= 6.29 && (vv = 0xff || vv == 'M')) { // Faulty Smile's have vv = 0xff /* ColorMunki Create ? */ /* ColorMunki Smile */ - if (p->dtype == 0) /* Not sure if this is set by Create */ - p->dtype = 1; + if (p->btype == 0) /* Not sure if this is set by Create */ + p->btype = 1; } else { /* Reject any version or model we don't know about */ @@ -1642,7 +1643,7 @@ i1disp_read_all_regs( p->serno[0] = '\000'; /* Read extra registers */ - if (p->dtype == 1) { + if (p->btype == 1) { #ifdef NEVER /* Not used, so don't bother */ for (i = 0; i < 3; i++) { @@ -1668,7 +1669,7 @@ i1disp_read_all_regs( /* ColorMunki Smile extra information */ /* (Colormunki Create too ????) */ - } else if (p->dtype == 2) { + } else if (p->btype == 2) { int i, v; /* Smile doesn't have ambient - reg144 seems to contain LCD cal type, */ @@ -1813,12 +1814,12 @@ i1disp_init_inst(inst *pp) { if (p->log->debug >= 3) { /* Dump all the register space */ - if (p->dtype < 2) { + if (p->btype < 2) { unsigned char buf[0x200]; int i, len; len = 128; - if (p->dtype != 0) + if (p->btype != 0) len = 160; for (i = 0; i < len; i++) { @@ -1985,11 +1986,11 @@ static inst_code i1disp_get_n_a_cals(inst *pp, inst_cal_type *pn_cals, inst_cal_ inst_cal_type n_cals = inst_calt_none; inst_cal_type a_cals = inst_calt_none; - if (p->dtype == 0) { /* Eye-One Display 1 */ + if (p->btype == 0) { /* Eye-One Display 1 */ a_cals |= inst_calt_emis_offset; } - if (p->dtype == 1 && p->refrmode != 0) { + if (p->btype == 1 && p->refrmode != 0) { if (p->rrset == 0) n_cals |= inst_calt_ref_freq; a_cals |= inst_calt_ref_freq; @@ -2015,7 +2016,7 @@ inst_code i1disp_calibrate( inst *pp, inst_cal_type *calt, /* Calibration type to do/remaining */ inst_cal_cond *calc, /* Current condition/desired condition */ -inst_calc_id_type *idtype, /* Condition identifier type */ +inst_calc_id_type *btype, /* Condition identifier type */ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ ) { i1disp *p = (i1disp *)pp; @@ -2027,7 +2028,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ if (!p->inited) return inst_no_init; - *idtype = inst_calc_id_none; + *btype = inst_calc_id_none; id[0] = '\000'; if ((ev = i1disp_get_n_a_cals((inst *)p, &needed, &available)) != inst_ok) @@ -2056,7 +2057,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ } /* Do the appropriate calibration */ - if (p->dtype == 0) { /* Eye-One Display 1 */ + if (p->btype == 0) { /* Eye-One Display 1 */ if (*calt & inst_calt_emis_offset) { if ((*calc & inst_calc_cond_mask) != inst_calc_man_ref_dark) { @@ -2284,7 +2285,7 @@ inst3_capability *pcap3) { /* i1D2 has refresh display & ambient capability */ /* but i1D1 & ColorMunki Smile don't */ - if (p->dtype == 1) { + if (p->btype == 1) { cap1 |= inst_mode_emis_ambient | inst_mode_emis_refresh_ovd | inst_mode_emis_norefresh_ovd @@ -2322,7 +2323,7 @@ static inst_code i1disp_check_mode(inst *pp, inst_mode m) { /* Only display emission mode supported */ if (!IMODETST(m, inst_mode_emis_spot) - && !(p->dtype == 1 && IMODETST(m, inst_mode_emis_ambient))) { + && !(p->btype == 1 && IMODETST(m, inst_mode_emis_ambient))) { return inst_unsupported; } @@ -2410,7 +2411,7 @@ static inst_disptypesel smile_disptypesel[3] = { static void set_base_disptype_list(i1disp *p) { /* set the base display type list */ - if (p->itype == instSmile) { + if (p->dtype == instSmile) { p->_dtlist = smile_disptypesel; } else { p->_dtlist = i1disp_disptypesel; @@ -2632,7 +2633,7 @@ i1disp_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern i1disp *new_i1disp(icoms *icom, instType itype) { +extern i1disp *new_i1disp(icoms *icom, instType dtype) { i1disp *p; @@ -2663,13 +2664,13 @@ extern i1disp *new_i1disp(icoms *icom, instType itype) { p->del = i1disp_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; - if (p->itype == instI1Disp2) - p->dtype = 1; /* i1Display2 */ + if (p->dtype == instI1Disp2) + p->btype = 1; /* i1Display2 */ - else if (p->itype == instSmile) { - p->dtype = 2; /* Smile */ + else if (p->btype == instSmile) { + p->btype = 2; /* Smile */ } icmSetUnity3x3(p->ccmat); /* Set the colorimeter correction matrix to do nothing */ diff --git a/spectro/i1disp.h b/spectro/i1disp.h index eada827..61423b7 100644..100755 --- a/spectro/i1disp.h +++ b/spectro/i1disp.h @@ -78,6 +78,7 @@ /* Sub-type of instrument (i.e. based on vers, char code, unlock code) */ typedef enum { + i1d2_unkn = -1, i1d2_norm = 0, /* Normal (i1d1, i1d2, Smile) */ i1d2_lite = 1, /* "Lite" */ i1d2_munki = 2, /* "Munk" */ @@ -88,15 +89,15 @@ typedef enum { i1d1_sencoreIII = 7, /* Sencore ColorPro III */ i1d1_sencoreIV = 8, /* Sencore ColorPro IV */ i1d1_sencoreV = 9 /* Sencore ColorPro V */ -} i1d2_dtype; +} i1d2_stype; /* I1DISP communication object */ struct _i1disp { INST_OBJ_BASE - int dtype; /* Device type: 0 = i1D1, 1 = i1D2, 2 = Smile */ - i1d2_dtype stype; /* Sub type */ + int btype; /* Device type: 0 = i1D1, 1 = i1D2, 2 = Smile */ + i1d2_stype stype; /* Sub type */ inst_mode mode; /* Currently selected mode */ diff --git a/spectro/i1pro.c b/spectro/i1pro.c index 44614d2..4399c57 100644..100755 --- a/spectro/i1pro.c +++ b/spectro/i1pro.c @@ -64,6 +64,7 @@ #include "numsup.h" #include "rspl1.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -140,15 +141,15 @@ i1pro_determine_capabilities(i1pro *p) { ; /* Set the Pro capabilities mask */ - if (p->itype == instI1Pro - || p->itype == instI1Pro2) { + if (p->dtype == instI1Pro + || p->dtype == instI1Pro2) { p->cap |= inst_mode_ref_spot | inst_mode_ref_strip ; } /* Set the Pro2 capabilities mask */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { p->cap |= inst_mode_ref_uv ; } @@ -911,7 +912,7 @@ i1pro_del(inst *pp) { } /* Constructor */ -extern i1pro *new_i1pro(icoms *icom, instType itype) { +extern i1pro *new_i1pro(icoms *icom, instType dtype) { i1pro *p; int rv; if ((p = (i1pro *)calloc(sizeof(i1pro),1)) == NULL) { @@ -940,7 +941,7 @@ extern i1pro *new_i1pro(icoms *icom, instType itype) { p->del = i1pro_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; i1pro_determine_capabilities(p); diff --git a/spectro/i1pro.h b/spectro/i1pro.h index e449f2c..378dc30 100644..100755 --- a/spectro/i1pro.h +++ b/spectro/i1pro.h @@ -45,7 +45,7 @@ struct _i1pro { INST_OBJ_BASE - int dtype; /* Device type: 0 = ?? */ + int idtype; /* Device type: 0 = ?? */ /* *** i1pro private data **** */ inst_mode cap; /* Instrument mode capability */ diff --git a/spectro/i1pro_imp.c b/spectro/i1pro_imp.c index a8cb9e0..03f0a0d 100644..100755 --- a/spectro/i1pro_imp.c +++ b/spectro/i1pro_imp.c @@ -92,6 +92,7 @@ #include "numsup.h" #include "rspl1.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -372,7 +373,7 @@ void del_i1proimp(i1pro *p) { i1pro_state *s; i1pro_code ev; - if (p->itype != instI1Pro2 && (ev = i1pro_update_log(p)) != I1PRO_OK) { + if (p->dtype != instI1Pro2 && (ev = i1pro_update_log(p)) != I1PRO_OK) { a1logd(p->log,2,"i1pro_update_log: Updating the cal and log parameters to" " EEProm failed failed\n"); } @@ -458,7 +459,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { a1logd(p->log,5,"i1pro_init:\n"); m->native_calstd = xcalstd_gmdi; /* Rev A-D */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { m->native_calstd = xcalstd_xrga; /* Rev E */ } m->target_calstd = xcalstd_native; /* Default to native calibration */ @@ -474,17 +475,17 @@ i1pro_code i1pro_imp_init(i1pro *p) { } /* Revert to i1pro if i1pro2 driver is not enabled */ - if (p->itype == instI1Pro2 + if (p->dtype == instI1Pro2 #ifdef ENABLE_2 && getenv("ARGYLL_DISABLE_I1PRO2_DRIVER") != NULL /* Disabled by environment */ #endif ) { - p->itype = instI1Pro; + p->dtype = instI1Pro; } - if (p->itype != instI1Monitor - && p->itype != instI1Pro - && p->itype != instI1Pro2) + if (p->dtype != instI1Monitor + && p->dtype != instI1Pro + && p->dtype != instI1Pro2) return I1PRO_UNKNOWN_MODEL; m->trig = inst_opt_trig_user; @@ -513,14 +514,14 @@ i1pro_code i1pro_imp_init(i1pro *p) { return ev; a1logd(p->log,2,"Firmware rev = %d, max +ve value = 0x%x\n",m->fwrev, m->maxpve); - if (p->itype == instI1Pro2 && m->fwrev < 600) { /* Hmm */ + if (p->dtype == instI1Pro2 && m->fwrev < 600) { /* Hmm */ a1logd(p->log,2, "Strange, firmware isn't up to i1pro2 but has extra pipe..revert to i1pro driver\n",m->fwrev); - p->itype = instI1Pro; + p->dtype = instI1Pro; } /* Get the EEProm size */ m->eesize = 8192; /* Rev A..D */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { #ifdef NEVER // ~~99 Hmm. makes it worse. Why ??? // /* Make sure LED sequence is finished, because it interferes with EEProm read! */ @@ -550,7 +551,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { return ev; } - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { /* Get the Chip ID (This doesn't work until after reading the EEProm !) */ if ((ev = i1pro2_getchipid(p, m->chipid)) != I1PRO_OK) { free(eeprom); @@ -565,7 +566,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { } /* Parse the i1pro2 extra data */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { if ((ev = m->data->parse_eeprom(m->data, eeprom, m->eesize, 1)) != I1PRO_OK) { free(eeprom); return ev; @@ -624,7 +625,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { m->nsen = 128; m->nraw = 128; - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { int clkusec, subdiv, xraw, nraw; if ((ev = i1pro2_getmeaschar(p, &clkusec, &xraw, &nraw, &subdiv)) != I1PRO_OK) return ev; @@ -685,7 +686,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { m->min_int_time = dp[0]; /* And then override it */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { m->min_int_time = m->subclkdiv2 * m->intclkp2; /* 0.004896 */ } else { if (m->fwrev >= 301) @@ -716,7 +717,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { if ((m->white_ref[0] = m->data->get_doubles(m->data, &count, key_white_ref)) == NULL || count != m->nwav[0]) { - if (p->itype != instI1Monitor) + if (p->dtype != instI1Monitor) return I1PRO_HW_CALIBINFO; m->white_ref[0] = NULL; } @@ -727,7 +728,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { if ((m->amb_coef[0] = m->data->get_doubles(m->data, &count, key_amb_coef)) == NULL || count != m->nwav[0]) { - if (p->itype != instI1Monitor + if (p->dtype != instI1Monitor && m->capabilities & 0x6000) /* Expect ambient calibration */ return I1PRO_HW_CALIBINFO; m->amb_coef[0] = NULL; @@ -799,7 +800,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { } /* Read Rev E specific keys */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { int i, j; double *dp; int *sip; @@ -1001,7 +1002,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { s->dark_int_time4 = DISP_INTT4; /* 0.1 */ s->idark_int_time[0] = s->idark_int_time[2] = m->min_int_time; - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { s->idark_int_time[1] = s->idark_int_time[3] = ADARKINT_MAX2; /* 4.0 */ } else { #ifdef USE_HIGH_GAIN_MODE @@ -1242,8 +1243,8 @@ i1pro_code i1pro_imp_init(i1pro *p) { } } - if (p->itype != instI1Monitor /* Monitor doesn't have reflective cal */ - && p->itype != instI1Pro2) { /* Rev E mode has different calibration */ + if (p->dtype != instI1Monitor /* Monitor doesn't have reflective cal */ + && p->dtype != instI1Pro2) { /* Rev E mode has different calibration */ /* Restore the previous reflective spot calibration from the EEProm */ /* Get ready to operate the instrument */ if ((ev = i1pro_restore_refspot_cal(p)) != I1PRO_OK) @@ -1266,11 +1267,11 @@ i1pro_code i1pro_imp_init(i1pro *p) { return ev; if (p->log->verb >= 1) { - a1logv(p->log,1,"Instrument Type: %s\n",inst_name(p->itype)); + a1logv(p->log,1,"Instrument Type: %s\n",inst_name(p->dtype)); a1logv(p->log,1,"Serial Number: %d\n",m->serno); a1logv(p->log,1,"Firmware version: %d\n",m->fwrev); a1logv(p->log,1,"CPLD version: %d\n",m->cpldrev); - if (p->itype == instI1Pro2) + if (p->dtype == instI1Pro2) a1logv(p->log,1,"Chip ID: %02x-%02x%02x%02x%02x%02x%02x%02x\n", m->chipid[0], m->chipid[1], m->chipid[2], m->chipid[3], m->chipid[4], m->chipid[5], m->chipid[6], m->chipid[7]); @@ -1290,7 +1291,7 @@ i1pro_code i1pro_imp_init(i1pro *p) { #ifdef NEVER // ~~99 play with LED settings - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { /* Makes it white */ unsigned char b2[] = { @@ -1355,7 +1356,7 @@ i1pro_code i1pro_imp_set_mode( switch(mmode) { case i1p_refl_spot: case i1p_refl_scan: - if (p->itype == instI1Monitor) + if (p->dtype == instI1Monitor) return I1PRO_INT_ILLEGALMODE; /* i1Monitor can't do reflection */ break; case i1p_emiss_spot_na: @@ -1414,11 +1415,11 @@ i1pro_code i1pro_imp_get_n_a_cals(i1pro *p, inst_cal_type *pn_cals, inst_cal_typ wl_valid = 0; } } - if ((curtime - cs->iddate) > ((p->itype == instI1Pro2) ? DCALTOUT2 : DCALTOUT)) { + if ((curtime - cs->iddate) > ((p->dtype == instI1Pro2) ? DCALTOUT2 : DCALTOUT)) { a1logd(p->log,2,"Invalidating adaptive dark cal as %d secs from last cal\n",curtime - cs->iddate); idark_valid = 0; } - if ((curtime - cs->ddate) > ((p->itype == instI1Pro2) ? DCALTOUT2 : DCALTOUT)) { + if ((curtime - cs->ddate) > ((p->dtype == instI1Pro2) ? DCALTOUT2 : DCALTOUT)) { a1logd(p->log,2,"Invalidating dark cal as %d secs from last cal\n",curtime - cs->ddate); dark_valid = 0; } @@ -1486,7 +1487,7 @@ i1pro_code i1pro_imp_get_n_a_cals(i1pro *p, inst_cal_type *pn_cals, inst_cal_typ && m->hr_inited /* and hi-res has been setup */ && (!m->emis_hr_cal || (n_cals & inst_calt_em_dark)) /* and the emis cal hasn't been */ /* fine tuned or we will be doing a dark cal */ - && p->itype != instI1Monitor) { /* i1Monitor doesn't have reflective cal capability */ + && p->dtype != instI1Monitor) { /* i1Monitor doesn't have reflective cal capability */ n_cals |= inst_calt_ref_white; /* Need a reflective white calibration */ a_cals |= inst_calt_ref_white; } @@ -1833,7 +1834,7 @@ i1pro_code i1pro_imp_calibrate( } #ifdef USE_HIGH_GAIN_MODE - if (p->itype != instI1Pro2) { /* Rev E doesn't have high gain mode */ + if (p->dtype != instI1Pro2) { /* Rev E doesn't have high gain mode */ nummeas = i1pro_comp_nummeas(p, s->dcaltime, s->idark_int_time[2]); a1logd(p->log,2,"Doing adaptive interpolated black calibration, dcaltime %f, idark_int_time[2] %f, nummeas %d, gainmode %d\n", s->dcaltime, s->idark_int_time[2], nummeas, 1); if ((ev = i1pro_dark_measure(p, s->idark_data[2], @@ -1883,7 +1884,7 @@ i1pro_code i1pro_imp_calibrate( ss->dark_int_time = s->dark_int_time; ss->dark_gain_mode = s->dark_gain_mode; #ifdef USE_HIGH_GAIN_MODE - for (j = 0; j < (p->itype != instI1Pro2) ? 4 : 2; j++) + for (j = 0; j < (p->dtype != instI1Pro2) ? 4 : 2; j++) #else for (j = 0; j < 2; j++) #endif @@ -1933,7 +1934,7 @@ i1pro_code i1pro_imp_calibrate( #endif #ifdef USE_HIGH_GAIN_MODE - if (p->itype != instI1Pro2) { /* Rev E doesn't have high gain mode */ + if (p->dtype != instI1Pro2) { /* Rev E doesn't have high gain mode */ // fprintf(stderr,"High gain offsets:\n"); // plot_raw(s->idark_data[2]); // fprintf(stderr,"High gain multiplier:\n"); @@ -1993,7 +1994,7 @@ i1pro_code i1pro_imp_calibrate( } #ifdef USE_HIGH_GAIN_MODE - if (p->itype != instI1Pro2) { /* Rev E doesn't have high gain mode */ + if (p->dtype != instI1Pro2) { /* Rev E doesn't have high gain mode */ s->idark_int_time[2] = s->inttime; nummeas = i1pro_comp_nummeas(p, s->dcaltime, s->idark_int_time[2]); a1logd(p->log,2,"Doing adaptive scan black calibration, dcaltime %f, idark_int_time[2] %f, nummeas %d, gainmode %d\n", s->dcaltime, s->idark_int_time[2], nummeas, s->gainmode); @@ -2043,7 +2044,7 @@ i1pro_code i1pro_imp_calibrate( ss->dark_int_time = s->dark_int_time; ss->dark_gain_mode = s->dark_gain_mode; #ifdef USE_HIGH_GAIN_MODE - for (j = 0; j < (p->itype != instI1Pro2) ? 4 : 2; j += 2) + for (j = 0; j < (p->dtype != instI1Pro2) ? 4 : 2; j += 2) #else for (j = 0; j < 2; j += 2) #endif @@ -2207,7 +2208,7 @@ i1pro_code i1pro_imp_calibrate( m->mmode = mmode; /* Restore actual mode */ return ev; } - } else if (p->itype != instI1Pro2 && s->gainmode == 0 && scale > m->highgain) { + } else if (p->dtype != instI1Pro2 && s->gainmode == 0 && scale > m->highgain) { #ifdef USE_HIGH_GAIN_MODE a1logd(p->log,3,"Scan signal is so low we're switching to high gain mode\n"); s->gainmode = 1; @@ -4218,7 +4219,7 @@ i1pro_code i1pro_save_calibration(i1pro *p) { i1pnonv x; int ss; int argyllversion = ARGYLL_VERSION; - int isRevE = p->itype == instI1Pro2 ? 1 : 0; + int isRevE = p->dtype == instI1Pro2 ? 1 : 0; strcpy(nmode, "w"); #if !defined(O_CREAT) && !defined(_O_CREAT) @@ -4230,7 +4231,8 @@ i1pro_code i1pro_save_calibration(i1pro *p) { /* Create the file name */ sprintf(cal_name, "ArgyllCMS/.i1p_%d.cal", m->serno); - if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_write, xdg_user, cal_name)) < 1) { + if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_write, xdg_user, xdg_none, + cal_name)) < 1) { a1logd(p->log,1,"i1pro_save_calibration xdg_bds returned no paths\n"); return I1PRO_INT_CAL_SAVE; } @@ -4353,7 +4355,8 @@ i1pro_code i1pro_restore_calibration(i1pro *p) { #endif /* Create the file name */ sprintf(cal_name, "ArgyllCMS/.i1p_%d.cal" SSEPS "color/.i1p_%d.cal", m->serno, m->serno); - if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, cal_name)) < 1) { + if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, xdg_none, + cal_name)) < 1) { a1logd(p->log,2,"i1pro_restore_calibration xdg_bds failed to locate file'\n"); return I1PRO_INT_CAL_RESTORE; } @@ -4394,7 +4397,7 @@ i1pro_code i1pro_restore_calibration(i1pro *p) { || argyllversion != ARGYLL_VERSION || ss != (sizeof(i1pro_state) + sizeof(i1proimp)) || serno != m->serno - || isRevE != (p->itype == instI1Pro2 ? 1 : 0) + || isRevE != (p->dtype == instI1Pro2 ? 1 : 0) || nraw != m->nraw || nwav0 != m->nwav[0] || nwav1 != m->nwav[1]) { @@ -4675,7 +4678,8 @@ i1pro_code i1pro_touch_calibration(i1pro *p) { /* Locate the file name */ sprintf(cal_name, "ArgyllCMS/.i1p_%d.cal" SSEPS "color/.i1p_%d.cal", m->serno, m->serno); - if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, cal_name)) < 1) { + if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, xdg_none, + cal_name)) < 1) { a1logd(p->log,2,"i1pro_restore_calibration xdg_bds failed to locate file'\n"); return I1PRO_INT_CAL_TOUCH; } @@ -5822,7 +5826,7 @@ i1pro_trigger_one_measure( *inttime = m->min_int_time; /* The Rev E measure mode has it's own settings */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { m->intclkp = m->intclkp2; /* From i1pro2_getmeaschar() ? */ m->subclkdiv = m->subclkdiv2; m->subtmode = 0; @@ -5892,7 +5896,7 @@ i1pro_trigger_one_measure( /* Compute integration clocks */ dintclocks = floor(*inttime/m->intclkp + 0.5); - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { if (dintclocks > 4294967296.0) /* This is probably not the actual limit */ return I1PRO_INT_INTTOOBIG; } else { @@ -5926,7 +5930,7 @@ i1pro_trigger_one_measure( if (gainmode == 0) measmodeflags |= I1PRO_MMF_LOWGAIN; /* Normal gain mode */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { measmodeflags2 = 0; if (s->scan && !(mmodif & 0x20)) /* Never scan on a calibration */ measmodeflags2 |= I1PRO2_MMF_SCAN; @@ -5958,7 +5962,7 @@ i1pro_trigger_one_measure( #endif /* NEVER */ { - if (p->itype != instI1Pro2) { /* Rev E sets the params in the measure command */ + if (p->dtype != instI1Pro2) { /* Rev E sets the params in the measure command */ /* Set the hardware for measurement */ if ((ev = i1pro_setmeasparams(p, intclocks, lampclocks, nummeas, measmodeflags)) != I1PRO_OK) return ev; @@ -5988,7 +5992,7 @@ i1pro_trigger_one_measure( /* Trigger a measurement */ usb_reinit_cancel(&m->rd_sync); /* Prepare to sync rd and trigger */ - if (p->itype != instI1Pro2) { + if (p->dtype != instI1Pro2) { if ((ev = i1pro_triggermeasure(p, TRIG_DELAY)) != I1PRO_OK) return ev; } else { @@ -7396,7 +7400,7 @@ void i1pro_sub_absraw( /* black. It's not clear why it works best this way, or how */ /* dependent on the particular instrument the magic numbers are, */ /* but it reduces the black level error from over 10% to about 0.3% */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { // double xx[NSEN_MAX], in[NSEN_MAX], res[NSEN_MAX]; double asub[NSEN_MAX]; double avgscell, zero; @@ -7516,7 +7520,7 @@ void i1pro_absraw_to_abswav( abswav[i][j] = tm[j] = oval; } - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { /* Now apply stray light compensation */ /* For each output wavelength */ for (j = 0; j < m->nwav[highres]; j++) { @@ -7613,7 +7617,7 @@ static double i1pro_raw2wav_uncal(i1pro *p, double raw) { double ov; int k; - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { raw = 128.0 - raw; /* Quadratic expects +ve correlation */ /* Compute polinomial */ @@ -7641,7 +7645,7 @@ static double i1pro_raw2wav(i1pro *p, int refl, double raw) { double ov; int k; - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { i1pro_state *s = &m->ms[m->mmode]; /* Correct for CCD offset and scale back to reference */ @@ -7980,6 +7984,7 @@ i1pro_code i1pro2_match_wl_meas(i1pro *p, double *pled_off, double *wlraw) { /* at 550 nm. (see above), which amounts to about +0.026, leaving 0.2528 */ /* unexplained. It appears the CCD wavelength has a dependence on the */ /* angle that the light enters the optics ?? */ + /* (- is it just a change in the spectrum shape ??) */ led_off += 0.2528; /* Hack to make ambient cap correction == white tile correction */ @@ -8813,7 +8818,7 @@ i1pro_code i1pro_create_hr(i1pro *p) { /* use the orginal filters to figure this out. */ if (m->raw2wav == NULL #ifndef ANALIZE_EXISTING - && p->itype != instI1Pro2 + && p->dtype != instI1Pro2 #endif ) { i1pro_fc coeff[100][16]; /* Existing filter cooefficients */ @@ -9418,7 +9423,7 @@ i1pro_code i1pro_create_hr(i1pro *p) { trspl->del(trspl); /* Upsample stray light */ - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { #ifdef ONEDSTRAYLIGHTUS double **slp; /* 2D Array of stray light values */ @@ -10727,7 +10732,7 @@ i1pro_code i1pro_optimise_sensor( /* expected level is < target_level/gain */ /* Hmm. It may not be a good idea to use high gain mode if it compromises */ /* the longer integration time which reduces noise. */ - if (p->itype != instI1Pro2 && new_int_time > m->max_int_time && permithg) { + if (p->dtype != instI1Pro2 && new_int_time > m->max_int_time && permithg) { new_int_time /= m->highgain; new_gain_mode = 1; a1logd(p->log,3,"Switching to high gain mode\n"); @@ -10810,7 +10815,7 @@ i1pro_prepare_idark( /* Compute base */ s->idark_data[i+0][j] = d01 - s->idark_data[i+1][j] * s->idark_int_time[i+0]; } - if (p->itype == instI1Pro2) /* Rev E doesn't have high gain mode */ + if (p->dtype == instI1Pro2) /* Rev E doesn't have high gain mode */ break; } } @@ -10928,7 +10933,7 @@ i1pro_reset( pbuf[0] = mask; - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { pbuf[1] = 0; /* Not known what i1pro2 second byte is for */ len = 2; } @@ -10978,7 +10983,7 @@ i1pro_readEEProm( short2buf(&pbuf[4], size); pbuf[6] = pbuf[7] = 0; /* Ignored */ - if (p->itype == instI1Pro2) + if (p->dtype == instI1Pro2) len = 6; se = p->icom->usb_control(p->icom, @@ -11066,7 +11071,7 @@ i1pro_writeEEProm( short2buf(&pbuf[4], size); short2buf(&pbuf[6], 0x100); /* Might be accidental, left over from getmisc.. */ - if (p->itype == instI1Pro2) + if (p->dtype == instI1Pro2) len = 6; se = p->icom->usb_control(p->icom, @@ -12112,7 +12117,7 @@ i1pro2_indLEDoff(void *pp) { #ifdef NEVER // ~~99 play with LED settings - if (p->itype == instI1Pro2) { + if (p->dtype == instI1Pro2) { // LED is capable of white and red @@ -12927,7 +12932,7 @@ static i1_dtype i1data_det_type(i1data *d, i1key key) { if (key < 0x100) return i1_dtype_section; - switch(key) { + switch((int)key) { /* Log keys */ case key_meascount: case key_meascount + 1000: diff --git a/spectro/i1pro_imp.h b/spectro/i1pro_imp.h index 582cc98..582cc98 100644..100755 --- a/spectro/i1pro_imp.h +++ b/spectro/i1pro_imp.h diff --git a/spectro/icoms.c b/spectro/icoms.c index eadecc9..875f3b6 100644..100755 --- a/spectro/icoms.c +++ b/spectro/icoms.c @@ -35,12 +35,16 @@ #include "sa_config.h" #endif #include "numsup.h" +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" #include "icoms.h" +icom_type dev_category(instType itype); +int serial_get_paths(icompaths *p, icom_type mask); + /* ----------------------------------------------------- */ /* Fake display & instrument device */ @@ -118,24 +122,32 @@ static icompath *icompaths_get_path( /* Return the device path corresponding to the port number, or NULL if out of range */ static icompath *icompaths_get_path_sel( icompaths *p, - icom_type dctype, /* Device type list */ + icom_dtix dtix, /* Device type list */ int port /* Enumerated port number, 1..n */ ) { /* Check it is an enumeration */ - if (dctype != dtix_combined - && dctype != dtix_inst - && dctype != dtix_3dlut - && dctype != dtix_vtpg - && dctype != dtix_printer) + if (dtix != dtix_combined + && dtix != dtix_inst + && dtix != dtix_3dlut + && dtix != dtix_vtpg + && dtix != dtix_printer + && dtix != dtix_cmfm) { +//printf("~1 unrec index\n"); return NULL; + } - if (dctype == dtix_inst) + if (dtix == dtix_inst) { +//printf("~1 inst\n"); return icompaths_get_path(p, port); + } - if (port <= 0 || port > p->ndpaths[dctype]) + if (port <= 0 || port > p->ndpaths[dtix]) { +//printf("~1 port %d out of range %d - %d\n", port,0, p->ndpaths[dtix]); return NULL; + } - return p->dpaths[dctype][port-1]; +//printf("~1 OK index for port %d\n",port); + return p->dpaths[dtix][port-1]; } /* Clear a single device paths list */ @@ -172,6 +184,7 @@ static void icompaths_clear_all(icompaths *p) { icompaths_clear(p, dtix_3dlut); icompaths_clear(p, dtix_vtpg); icompaths_clear(p, dtix_printer); + icompaths_clear(p, dtix_cmfm); icompaths_clear(p, dtix_combined); } @@ -183,7 +196,7 @@ static int icompaths_add_path(icompaths *p, int ix, icompath *xp) { if (xp == NULL) ix = dtix_combined; if (p->dpaths[ix] == NULL) { - if ((p->dpaths[ix] = (icompath **)calloc(sizeof(icompath *), 1 + 1)) == NULL) { + if ((p->dpaths[ix] = (icompath **)calloc(1 + 1, sizeof(icompath *))) == NULL) { a1loge(p->log, ICOM_SYS, "icompaths: calloc failed!\n"); return ICOM_SYS; } @@ -198,7 +211,7 @@ static int icompaths_add_path(icompaths *p, int ix, icompath *xp) { p->dpaths[ix][p->ndpaths[ix]+1] = NULL; } if (xp == NULL) { - if ((xp = calloc(sizeof(icompath), 1)) == NULL) { + if ((xp = calloc(1, sizeof(icompath))) == NULL) { a1loge(p->log, ICOM_SYS, "icompaths: malloc failed!\n"); return ICOM_SYS; } @@ -227,7 +240,7 @@ int icompaths_make_dslists(icompaths *p) { if ((rv = icompaths_add_path(p, dtix_inst, xp)) != ICOM_OK) return rv; } - if (xp->dctype & icomt_3dlut) { + if (xp->dctype & icomt_v3dlut) { if ((rv = icompaths_add_path(p, dtix_3dlut, xp)) != ICOM_OK) return rv; } @@ -239,6 +252,10 @@ int icompaths_make_dslists(icompaths *p) { if ((rv = icompaths_add_path(p, dtix_printer, xp)) != ICOM_OK) return rv; } + if (xp->dctype & icomt_cmfm) { + if ((rv = icompaths_add_path(p, dtix_cmfm, xp)) != ICOM_OK) + return rv; + } } /* Maintain backwards compatible instrument list alias */ @@ -289,9 +306,9 @@ int icompaths_set_serial_itype(icompath *p, devType itype) { char pname[400], *cp; /* Convert device type to category */ - p->dctype = (p->dctype & ~icomt_cat_mask) | inst_category(itype); + p->dctype = (p->dctype & ~icomt_cat_mask) | dev_category(itype); - p->itype = itype; + p->dtype = itype; /* Strip any existing description in brackets */ if ((cp = strchr(p->name, '(')) != NULL && cp > p->name) @@ -330,13 +347,13 @@ int icompath_set_usb(a1log *log, icompath *p, char *name, unsigned int vid, unsi a1logd(g_log, 8, "icompath_set_usb '%s' got dctype 0x%x\n",p->name,p->dctype); p->dctype |= icomt_usb; - p->dctype = (p->dctype & ~icomt_cat_mask) | inst_category(itype); + p->dctype = (p->dctype & ~icomt_cat_mask) | dev_category(itype); p->nep = nep; p->vid = vid; p->pid = pid; p->usbd = usbd; - p->itype = itype; + p->dtype = itype; a1logd(g_log, 8, "icompath_set_usb '%s' returning dctype 0x%x\n",p->name,p->dctype); @@ -375,7 +392,7 @@ static int icompaths_add_hid(icompaths *p, char *name, unsigned int vid, unsigne a1logd(g_log, 8, "icompaths_add_hid '%s' got dctype 0x%x\n",xp->name,xp->dctype); xp->dctype |= icomt_hid; - xp->dctype = (xp->dctype & ~icomt_cat_mask) | inst_category(itype); + xp->dctype = (xp->dctype & ~icomt_cat_mask) | dev_category(itype); if ((xp->name = strdup(name)) == NULL) { a1loge(p->log, ICOM_SYS, "icompaths: strdup failed!\n"); @@ -386,7 +403,7 @@ static int icompaths_add_hid(icompaths *p, char *name, unsigned int vid, unsigne xp->vid = vid; xp->pid = pid; xp->hidd = hidd; - xp->itype = itype; + xp->dtype = itype; a1logd(g_log, 8, "icompath_set_usb '%s' returning dctype 0x%x\n",xp->name,xp->dctype); @@ -398,20 +415,26 @@ static void icompaths_del(icompaths *p) { if (p != NULL) { icompaths_clear_all(p); + if (p->exlist != NULL) { + int i; + for (i = 0; i < p->exno; i++) { + if (p->exlist[i] != NULL) + free(p->exlist[i]); + } + free(p->exlist); + } p->log = del_a1log(p->log); /* Unreference it and set to NULL */ free(p); } } /* Create and return a list of available serial ports or USB devices for this system. */ -/* We look at the registry key "HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM" */ -/* to determine serial ports, and use libusb to discover USB devices. */ -/* return icom error */ +/* Return icom error */ int icompaths_refresh_paths_sel(icompaths *p, icom_type mask) { int rv, usbend = 0; int i, j; - a1logd(p->log, 7, "icoms_refresh_paths: called with mask = %d\n",mask); + a1logd(p->log, 7, "icoms_refresh_paths: called with mask = 0x%x\n",mask); /* Clear any existing device paths */ p->clear(p); @@ -451,9 +474,9 @@ int icompaths_refresh_paths_sel(icompaths *p, icom_type mask) { for (i = usbend; i < (np-1); i++) { for (j = i+1; j < np; j++) { - if ((pl[i]->itype == instUnknown && pl[j]->itype != instUnknown) - || (((pl[i]->itype == instUnknown && pl[j]->itype == instUnknown) - || (pl[i]->itype != instUnknown && pl[j]->itype != instUnknown)) + if ((pl[i]->dtype == instUnknown && pl[j]->dtype != instUnknown) + || (((pl[i]->dtype == instUnknown && pl[j]->dtype == instUnknown) + || (pl[i]->dtype != instUnknown && pl[j]->dtype != instUnknown)) && strcmp(pl[i]->name, pl[j]->name) > 0)) { icompath *tt = pl[i]; pl[i] = pl[j]; @@ -501,12 +524,91 @@ int icompaths_refresh_paths(icompaths *p) { return icompaths_refresh_paths_sel(p, icomt_instrument | icomt_portattr_all); } +static int create_fserexcl(icompaths *p) { + char *envv; + + p->exno = 0; + + /* Get the exclusion list */ + if ((envv = getenv("ARGYLL_EXCLUDE_SERIAL_SCAN")) != NULL) { + char *cp, *pcp; + + /* Count the number of strings */ + for (cp = envv;; cp++) { + if (*cp == ';' + || *cp == ',' + || *cp == '\000') + p->exno++; + if (*cp == '\000') + break; + } + + if ((p->exlist = (char **)calloc(p->exno, sizeof(char *))) == NULL) { + a1logd(p->log, 1, "create_fserexcl: calloc failed!\n"); + return 1; + } + + /* Copy strings to array */ + p->exno = 0; + for (pcp = cp = envv;; cp++) { + if (*cp == ';' + || *cp == ',' + || *cp == '\000') { + + if (cp - pcp > 0) { + if ((p->exlist[p->exno] = (char *)calloc(cp - pcp +1, sizeof(char))) == NULL) { + a1logd(p->log, 1, "create_fserexcl: calloc failed!\n"); + return 1; + } + memmove(p->exlist[p->exno], pcp, cp - pcp); + p->exlist[p->exno][cp - pcp] = '\000'; + p->exno++; + } + pcp = cp + 1; + } + if (*cp == '\000') + break; + } + +#ifdef NEVER + printf("Exclusion list len %d =\n",p->exno); + for (i = 0; i < p->exno; i++) + printf(" '%s'\n",p->exlist[i]); +#endif + } + return 0; +} + +/* Return nz if the given path is on the fast serial scan */ +/* exclusion list */ +static int icompaths_fs_excluded(icompaths *p, icompath *path) { + + a1logd(p->log, 5, "fs_excluded check '%s'\n",path->spath); + +#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL) + if (p->exlist != NULL) { + int i; + + for (i = 0; i < p->exno; i++) { + if (strcmp(p->exlist[i], path->spath) == 0) { + a1logd(p->log, 5, "excluding '%s' from fast scan\n",path->spath); + return 1; + } + } + } +#endif + return 0; +} + /* Allocate an icom paths and set it to the list of available devices */ /* that match the icom_type mask. */ /* Return NULL on error */ icompaths *new_icompaths_sel(a1log *log, icom_type mask) { icompaths *p; - if ((p = (icompaths *)calloc(sizeof(icompaths), 1)) == NULL) { + + a1logd(log, 3, "new_icompath: called with mask 0x%x\n",mask); + + if ((p = (icompaths *)calloc(1, sizeof(icompaths))) == NULL) { a1loge(log, ICOM_SYS, "new_icompath: calloc failed!\n"); return NULL; } @@ -521,7 +623,9 @@ icompaths *new_icompaths_sel(a1log *log, icom_type mask) { p->del = icompaths_del; /* ====== internal implementation ======= */ + #if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL) + p->fs_excluded = icompaths_fs_excluded; p->add_serial = icompaths_add_serial; #endif /* ENABLE_SERIAL */ #ifdef ENABLE_USB @@ -532,6 +636,9 @@ icompaths *new_icompaths_sel(a1log *log, icom_type mask) { p->get_last_path = icompaths_get_last_path; /* ====================================== */ + /* Get list of fast scan exclusion devices */ + create_fserexcl(p); + if (icompaths_refresh_paths_sel(p, mask)) { a1loge(log, ICOM_SYS, "new_icompaths: icompaths_refresh_paths failed!\n"); free(p); @@ -581,7 +688,7 @@ static int icom_copy_path_to_icom(icoms *p, icompath *pp) { return rv; #endif p->dctype = pp->dctype; - p->itype = pp->itype; + p->dtype = pp->dtype; a1logd(g_log, 8, "icom_copy_path_to_icom '%s' returning dctype 0x%x\n",p->name,p->dctype); @@ -671,14 +778,20 @@ int frbw /* nz to Flush Read Before Write */ /* Return error if coms */ if (rv != ICOM_OK) { - a1logd(p->log, 8, "icoms_write_read: failed - returning 0x%x\n",rv); + if (rv & ICOM_TO) + a1logd(p->log, 8, "icoms_write_read: write T.O. %f sec. returning 0x%x\n",tout, rv); + else + a1logd(p->log, 8, "icoms_write_read: write failed - returning 0x%x\n",rv); return rv; } /* Read response */ rv = p->read(p, rbuf, bsize, bread, tc, ntc, tout); - a1logd(p->log, 8, "icoms_write_read: returning 0x%x\n",rv); + if (rv & ICOM_TO) + a1logd(p->log, 8, "icoms_write_read: read T.O. %f sec. returning 0x%x\n",tout, rv); + else + a1logd(p->log, 8, "icoms_write_read: read returning 0x%x\n",rv); return rv; } @@ -739,9 +852,9 @@ icoms *new_icoms( ) { icoms *p; - a1logd(log, 2, "new_icoms '%s' itype '%s' dctype 0x%x\n",ipath->name,inst_sname(ipath->itype),ipath->dctype); + a1logd(log, 2, "new_icoms '%s' itype '%s' dctype 0x%x\n",ipath->name,inst_sname(ipath->dtype),ipath->dctype); - if ((p = (icoms *)calloc(sizeof(icoms), 1)) == NULL) { + if ((p = (icoms *)calloc(1, sizeof(icoms))) == NULL) { a1loge(log, ICOM_SYS, "new_icoms: calloc failed!\n"); return NULL; } @@ -750,7 +863,7 @@ icoms *new_icoms( a1loge(log, ICOM_SYS, "new_icoms: strdup failed!\n"); return NULL; } - p->itype = ipath->itype; + p->dtype = ipath->dtype; /* Copy ipath info to this icoms */ if (icom_copy_path_to_icom(p, ipath)) { @@ -857,6 +970,8 @@ char *baud_rate_to_str(baud_rate br) { return "57600"; case baud_115200: return "115200"; + case baud_230400: + return "230400"; case baud_921600: return "921600"; } diff --git a/spectro/icoms.h b/spectro/icoms.h index be36cac..4e18b62 100644..100755 --- a/spectro/icoms.h +++ b/spectro/icoms.h @@ -55,11 +55,12 @@ typedef enum { /* Category of device */ icomt_instrument = 0x010000, /* Color measurement instrument (default) */ - icomt_3dlut = 0x020000, /* A 3D cLUT box */ - icomt_vtpg = 0x040000, /* A video test patern generator box */ + icomt_v3dlut = 0x020000, /* A Video 3D cLUT box */ + icomt_vtpg = 0x040000, /* A Video test patern generator box */ icomt_printer = 0x080000, /* A printing device */ + icomt_cmfm = 0x100000, /* A CMF Measuring device */ - icomt_cat_any = 0x0f0000, /* Could be any device category */ + icomt_cat_any = 0x1f0000, /* Could be any device category */ icomt_cat_mask = 0xff0000, /* Mask for device category */ /* Type of underlying communication port */ @@ -68,6 +69,7 @@ typedef enum { icomt_usb = 0x000002, /* USB port */ icomt_hid = 0x000004, /* HID USB port */ icomt_bt = 0x000008, /* Bluetooth (non-serial) */ +// icomt_net = 0x000010, /* Network Connected */ icomt_port_mask = 0x0000ff, /* Mask for port type */ @@ -83,7 +85,6 @@ typedef enum { icomt_portattr_all = icomt_portattr_mask /* Scan for all port types */ - } icom_type; /* Status bits/return values */ @@ -145,9 +146,9 @@ typedef struct { /* - - - - - - - - - - - - - - - - - - - - */ /* Store information about a possible instrument communication path */ -/* (Note a path doesn't have a reference to icompaths or its' log) */ +/* (Note a path doesn't have a reference to icompaths or its log) */ struct _icompath { - devType itype; /* Type of device if known */ + devType dtype; /* Type of device if known */ char *name; /* instance description */ icom_type dctype; /* Device and com. type */ @@ -171,6 +172,7 @@ typedef enum { dtix_3dlut, dtix_vtpg, dtix_printer, + dtix_cmfm, dtix_number /* Number of entries */ } icom_dtix; @@ -209,7 +211,7 @@ struct _icompaths { /* Return the device path corresponding to the port number, or NULL if out of range */ icompath *(*get_path_sel)( struct _icompaths *p, - icom_type dctype, /* Device type list */ + icom_dtix dtix, /* Device type list */ int port); /* Enumerated port number, 1..n */ /* Clear all the device paths */ @@ -220,7 +222,14 @@ struct _icompaths { /* ====== internal implementation ======= */ + /* Fast serial scan exclusion list - from ARGYLL_EXCLUDE_SERIAL_SCAN env. var. */ + int exno; + char **exlist; + #if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL) + /* Return nz if the serial port is on the fast serial scan exclusion list */ + int (*fs_excluded)(struct _icompaths *p, struct _icompath *path); + /* Add a serial path to combined. path is copied. Return icom error */ int (*add_serial)(struct _icompaths *p, char *name, char *spath, icom_type dctype); #endif /* ENABLE_SERIAL */ @@ -228,11 +237,11 @@ struct _icompaths { #ifdef ENABLE_USB /* Add a usb path to combined. usbd is taken, others are copied. Return icom error */ int (*add_usb)(struct _icompaths *p, char *name, unsigned int vid, unsigned int pid, - int nep, struct usb_idevice *usbd, devType itype); + int nep, struct usb_idevice *usbd, devType dtype); /* Add an hid path to combined. hidd is taken, others are copied. Return icom error */ int (*add_hid)(struct _icompaths *p, char *name, unsigned int vid, unsigned int pid, - int nep, struct hid_idevice *hidd, devType itype); + int nep, struct hid_idevice *hidd, devType dtype); #endif /* ENABLE_USB */ /* Delete the last combined path */ @@ -279,7 +288,8 @@ typedef enum { baud_38400 = 10, baud_57600 = 11, baud_115200 = 12, - baud_921600 = 13 + baud_230400 = 13, + baud_921600 = 14 } baud_rate; char *baud_rate_to_str(baud_rate br); @@ -327,7 +337,7 @@ struct _icoms { /* Copy of some of icompath contents: */ icom_type dctype; /* Device cat. and com. type */ - devType itype; /* Type of device if known */ + devType dtype; /* Type of device if known */ char *name; /* Device description */ diff --git a/spectro/icoms_nt.c b/spectro/icoms_nt.c index b9e0d0c..39ff6f0 100644..100755 --- a/spectro/icoms_nt.c +++ b/spectro/icoms_nt.c @@ -18,7 +18,7 @@ #include <conio.h> -instType fast_ser_inst_type(icoms *p, int tryhard, void *, void *); +devType fast_ser_dev_type(icoms *p, int tryhard, void *, void *); /* Add paths to serial connected device. */ /* Return an icom error */ @@ -128,12 +128,14 @@ int serial_get_paths(icompaths *p, icom_type mask) { icoms *icom; if ((path = p->get_last_path(p)) != NULL && (icom = new_icoms(path, p->log)) != NULL) { - devType itype = fast_ser_inst_type(icom, 0, NULL, NULL); - if (itype != instUnknown) - icompaths_set_serial_itype(path, itype); /* And set category */ + if (!p->fs_excluded(p, path)) { + devType itype = fast_ser_dev_type(icom, 0, NULL, NULL); + if (itype != instUnknown) + icompaths_set_serial_itype(path, itype); /* And set category */ + } icom->del(icom); } - a1logd(p->log, 8, "serial_get_paths: Identified '%s' dctype 0x%x\n",inst_sname(path->itype),path->dctype); + a1logd(p->log, 8, "serial_get_paths: Identified '%s' dctype 0x%x\n",inst_sname(path->dtype),path->dctype); } } if ((stat = RegCloseKey(sch)) != ERROR_SUCCESS) { @@ -163,6 +165,15 @@ void serial_close_port(icoms *p) { /* -------------------------------------------------------------------- */ +#ifndef CBR_230400 +# define CBR_230400 230400 +#endif +#ifndef CBR_460800 +# define CBR_460800 460800 +#endif +#ifndef CBR_512000 +# define CBR_512000 512000 +#endif #ifndef CBR_921600 # define CBR_921600 921600 #endif @@ -190,10 +201,12 @@ int delayms) { /* Delay after open in msec */ " Open delay = %d ms\n" ,p->name ,fc ,baud_rate_to_str(baud) ,parity ,stop ,word, delayms); +#ifdef NEVER /* Is this needed ? */ if (p->is_open) { a1logd(p->log, 8, "icoms_set_ser_port: closing port '%s'\n",p->name); p->close_port(p); } +#endif if (p->port_type(p) == icomt_serial) { DCB dcb; @@ -386,6 +399,9 @@ int delayms) { /* Delay after open in msec */ case baud_115200: dcb.BaudRate = CBR_115200; break; + case baud_230400: + dcb.BaudRate = CBR_230400; + break; case baud_921600: dcb.BaudRate = CBR_921600; break; diff --git a/spectro/icoms_ux.c b/spectro/icoms_ux.c index 9e79d7f..2ee19bd 100644..100755 --- a/spectro/icoms_ux.c +++ b/spectro/icoms_ux.c @@ -1,5 +1,6 @@ /* Unix icoms and serial I/O class */ +/* This is #includeed in icom.c */ /* * Argyll Color Correction System @@ -49,7 +50,7 @@ #endif /* UNIX_APPLE */ -instType fast_ser_inst_type(icoms *p, int tryhard, void *, void *); +devType fast_ser_dev_type(icoms *p, int tryhard, void *, void *); /* Add paths to serial connected device. */ /* Return an icom error */ @@ -142,12 +143,14 @@ int serial_get_paths(icompaths *p, icom_type mask) { icoms *icom; if ((path = p->get_last_path(p)) != NULL && (icom = new_icoms(path, p->log)) != NULL) { - instType itype = fast_ser_inst_type(icom, 0, NULL, NULL); - if (itype != instUnknown) - icompaths_set_serial_itype(path, itype); /* And set category */ + if (!p->fs_excluded(p, path)) { + instType itype = fast_ser_dev_type(icom, 0, NULL, NULL); + if (itype != instUnknown) + icompaths_set_serial_itype(path, itype); /* And set category */ + } icom->del(icom); } - a1logd(p->log, 8, "serial_get_paths: Identified '%s' dctype 0x%x\n",inst_sname(path->itype),path->dctype); + a1logd(p->log, 8, "serial_get_paths: Identified '%s' dctype 0x%x\n",inst_sname(path->dtype),path->dctype); } continue2: CFRelease(dfp); @@ -258,7 +261,7 @@ int serial_get_paths(icompaths *p, icom_type mask) { strcpy(dpath, dirn); strcat(dpath, de->d_name); - /* See if the serial port is real */ + /* See if the (not fast) serial port is real */ if (strncmp(de->d_name, "ttyUSB", 6) != 0 && strncmp(de->d_name, "ttyHS", 5) != 0 && strncmp(de->d_name, "rfcomm", 6) != 0) { @@ -320,12 +323,14 @@ int serial_get_paths(icompaths *p, icom_type mask) { icoms *icom; if ((path = p->get_last_path(p)) != NULL && (icom = new_icoms(path, p->log)) != NULL) { - instType itype = fast_ser_inst_type(icom, 0, NULL, NULL); - if (itype != instUnknown) - icompaths_set_serial_itype(path, itype); /* And set category */ + if (!p->fs_excluded(p, path)) { + instType itype = fast_ser_dev_type(icom, 0, NULL, NULL); + if (itype != instUnknown) + icompaths_set_serial_itype(path, itype); /* And set category */ + } icom->del(icom); } - a1logd(p->log, 8, "serial_get_paths: Identified '%s' dctype 0x%x\n",inst_sname(path->itype),path->dctype); + a1logd(p->log, 8, "serial_get_paths: Identified '%s' dctype 0x%x\n",inst_sname(path->dtype),path->dctype); } } closedir(dd); @@ -361,6 +366,15 @@ void serial_close_port(icoms *p) { #endif #if defined(UNIX_APPLE) || defined(__OpenBSD__) +# ifndef B230400 +# define B230400 230400 +# endif +# ifndef B460800 +# define B460800 460800 +# endif +# ifndef B512000 +# define B512000 512000 +# endif # ifndef B921600 # define B921600 921600 # endif @@ -393,10 +407,12 @@ int delayms) { /* Delay after open in msec */ ,p->name ,fc ,baud_rate_to_str(baud) ,parity ,stop ,word, delayms); +#ifdef NEVER /* This is too slow on OS X */ if (p->is_open) { /* Close it and re-open it */ a1logd(p->log, 8, "icoms_set_ser_port: closing port\n"); p->close_port(p); } +#endif if (p->port_type(p) == icomt_serial) { @@ -418,13 +434,27 @@ int delayms) { /* Delay after open in msec */ a1logd(p->log, 8, "icoms_set_ser_port: about to open serial port '%s'\n",p->spath); + /* Hmm. Recent OS X to FTDI can take 1500 msec to open. Why ? */ + /* O_NONBLOCK O_SYNC */ if ((p->fd = open(p->spath, O_RDWR | O_NOCTTY )) < 0) { - a1logd(p->log, 1, "icoms_set_ser_port: open port '%s' r/w failed with %d (%s)\n",p->spath,p->fd,strerror(errno)); + a1logd(p->log, 1, "icoms_set_ser_port: open port '%s' r/w failed with %d (%s)\n", + p->spath,p->fd,strerror(errno)); + return ICOM_SYS; + } if (delayms < 160) /* Seems to need at least 80 msec for many drivers */ delayms = 160; - msec_sleep(delayms); /* For Bluetooth */ + msec_sleep(delayms); /* For Bluetooth and other drivers */ + +#ifdef NEVER + /* If we used O_NONBLOCK */ + if (fcntl(p->fd, F_SETFL, 0) == -1) { + a1logd(p->log, 1, "icoms_set_ser_port: clearing O_NONBLOCK failed with %d (%s)\n", + p->spath,p->fd,strerror(errno)); + return ICOM_SYS; + } +#endif #ifdef NEVER /* See what supplementary groups we are a member of */ { @@ -460,11 +490,6 @@ int delayms) { /* Delay after open in msec */ fail:; } #endif - return ICOM_SYS; - } - - /* O_NONBLOCK O_SYNC */ - p->is_open = 1; } @@ -622,6 +647,9 @@ int delayms) { /* Delay after open in msec */ case baud_115200: speed = B115200; break; + case baud_230400: + speed = B230400; + break; case baud_921600: speed = B921600; break; diff --git a/spectro/ifiles b/spectro/ifiles index 706d0b7..706d0b7 100644..100755 --- a/spectro/ifiles +++ b/spectro/ifiles diff --git a/spectro/illumread.c b/spectro/illumread.c index 58569e3..28ecbca 100644..100755 --- a/spectro/illumread.c +++ b/spectro/illumread.c @@ -253,8 +253,8 @@ usage(char *diag, ...) { for (i = 0; ; i++) { if (paths[i] == NULL) break; - if ((paths[i]->itype == instSpyder1 && setup_spyd2(0) == 0) - || (paths[i]->itype == instSpyder2 && setup_spyd2(1) == 0)) + if ((paths[i]->dtype == instSpyder1 && setup_spyd2(0) == 0) + || (paths[i]->dtype == instSpyder2 && setup_spyd2(1) == 0)) fprintf(stderr," %d = '%s' !! Disabled - no firmware !!\n",i+1,paths[i]->name); else fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name); @@ -999,8 +999,8 @@ int main(int argc, char *argv[]) for (i = 0; ; i++) { if (paths[i] == NULL) break; - if ((paths[i]->itype == instSpyder1 && setup_spyd2(0) == 0) - || (paths[i]->itype == instSpyder2 && setup_spyd2(1) == 0)) + if ((paths[i]->dtype == instSpyder1 && setup_spyd2(0) == 0) + || (paths[i]->dtype == instSpyder2 && setup_spyd2(1) == 0)) fprintf(stderr," %d = '%s' !! Disabled - no firmware !!\n",i+1,paths[i]->name); else fprintf(stderr," %d = '%s'\n",i+1,paths[i]->name); diff --git a/spectro/inflate.c b/spectro/inflate.c index 55d8e65..55d8e65 100644..100755 --- a/spectro/inflate.c +++ b/spectro/inflate.c diff --git a/spectro/inst.c b/spectro/inst.c index 681ef0a..07ace6e 100644..100755 --- a/spectro/inst.c +++ b/spectro/inst.c @@ -45,6 +45,8 @@ #include "sa_config.h" #endif /* !SALONEINSTLIB */ #include "numsup.h" +#include "rand.h" +#include "cgats.h" #include "xspect.h" #include "conv.h" @@ -58,7 +60,7 @@ #include "sort.h" #if defined(ENABLE_FAST_SERIAL) -instType fast_ser_inst_type(icoms *p, int tryhard, +devType fast_ser_dev_type(icoms *p, int tryhard, inst_code (*uicallback)(void *cntx, inst_ui_purp purp), void *cntx); # if defined(ENABLE_SERIAL) static instType ser_inst_type(icoms *p, @@ -66,6 +68,8 @@ static instType ser_inst_type(icoms *p, # endif /* ENABLE_SERIAL */ #endif /* ENABLE_FAST_SERIAL */ +icom_type dev_category(instType itype); + /* ------------------------------------ */ /* Default methods for instrument class */ @@ -89,7 +93,7 @@ inst *p) { /* Return the instrument type */ static instType get_itype(inst *p) { if (p != NULL) - return p->itype; + return p->dtype; return instUnknown; } @@ -523,6 +527,8 @@ static char *inst_interp_error(inst *p, inst_code ec) { return "Internal error - communications needed but not established"; case inst_no_init: return "Internal error - initialisation needed but not done"; + case inst_unsupported: + return "Unsupported function"; case inst_internal_error: return "Internal software error"; case inst_coms_fail: @@ -545,8 +551,6 @@ static char *inst_interp_error(inst *p, inst_code ec) { return "Instrument needs calibration"; case inst_cal_setup: return "Instrument needs to be setup for calibration"; - case inst_unsupported: - return "Unsupported function"; case inst_unexpected_reply: return "Unexpected Reply"; case inst_wrong_config: @@ -613,7 +617,7 @@ void *cntx /* Context for callback */ return NULL; } - a1logd(log, 2, "new_inst: called with path '%s' type '%s'\n",path->name,inst_sname(path->itype)); + a1logd(log, 2, "new_inst: called with path '%s' type '%s'\n",path->name,inst_sname(path->dtype)); if ((icom = new_icoms(path, log)) == NULL) { a1logd(log, 2, "new_inst: new_icoms failed to open it\n"); @@ -623,12 +627,12 @@ void *cntx /* Context for callback */ /* Set instrument type from USB port, if not specified */ - itype = icom->itype; /* Instrument type if its known from usb/hid */ + itype = icom->dtype; /* Instrument type if its known from usb/hid */ #if defined(ENABLE_FAST_SERIAL) if (itype == instUnknown && !nocoms && (icom->dctype & icomt_fastserial)) { - itype = fast_ser_inst_type(icom, 1, uicallback, cntx); /* Else type from serial */ - icom->dctype = (icom->dctype & ~icomt_cat_mask) | inst_category(itype); + itype = fast_ser_dev_type(icom, 1, uicallback, cntx); /* Else type from serial */ + icom->dctype = (icom->dctype & ~icomt_cat_mask) | dev_category(itype); a1logd(log, 8, "new_inst: fast set '%s' dctype 0x%x\n",icom->name,icom->dctype); } #endif /* ENABLE_FAST_SERIAL */ @@ -636,7 +640,7 @@ void *cntx /* Context for callback */ #if defined(ENABLE_SERIAL) if (itype == instUnknown && !nocoms) { itype = ser_inst_type(icom, uicallback, cntx); /* Else type from serial */ - icom->dctype = (icom->dctype & ~icomt_cat_mask) | inst_category(itype); + icom->dctype = (icom->dctype & ~icomt_cat_mask) | dev_category(itype); a1logd(log, 8, "new_inst: set '%s' dctype 0x%x\n",icom->name,icom->dctype); } #endif /* ENABLE_SERIAL */ @@ -957,7 +961,7 @@ int doccmx /* Add matching installed ccmx files */ iccmx *ss_list; /* Just ccmx's for this instrument */ - if ((ss_list = list_iccmx(p->itype, NULL)) == NULL) { + if ((ss_list = list_iccmx(p->dtype, NULL)) == NULL) { free(list); return inst_internal_error; } @@ -1111,7 +1115,7 @@ iccmx *list_iccmx(instType itype, int *no) { int npaths = 0; - npaths = xdg_bds(NULL, &paths, xdg_data, xdg_read, xdg_user, + npaths = xdg_bds(NULL, &paths, xdg_data, xdg_read, xdg_user, xdg_none, "ArgyllCMS/\052.ccmx" XDG_FUDGE "color/\052.ccmx" ); @@ -1251,7 +1255,7 @@ iccss *list_iccss(int *no) { int npaths = 0; - npaths = xdg_bds(NULL, &paths, xdg_data, xdg_read, xdg_user, + npaths = xdg_bds(NULL, &paths, xdg_data, xdg_read, xdg_user, xdg_none, "ArgyllCMS/\052.ccss" XDG_FUDGE "color/\052.ccss" ); @@ -1375,15 +1379,18 @@ void free_iccss(iccss *list) { /* Detect fast serial instruments */ #ifdef ENABLE_FAST_SERIAL + +static void radiance_delimiters(icoms *p, int lgchsum); +static void radiance_random(icoms *p, int lgchsum); static void hex2bin(char *buf, int len); /* Heuristicly determine the instrument type for */ /* a fast serial connection, and instUnknown if not serial. */ /* Set it in icoms and also return it. */ -instType fast_ser_inst_type( +devType fast_ser_dev_type( icoms *p, int tryhard, - inst_code (*uicallback)(void *cntx, inst_ui_purp purp), /* optional uicallback */ + inst_code (*uicallback)(void *cntx, inst_ui_purp purp), /* optional uicallback for abort */ void *cntx /* Context for callback */ ) { instType rv = instUnknown; @@ -1400,16 +1407,20 @@ instType fast_ser_inst_type( int se, len; double tryto = 0.1; /* [0.1] Communication timout */ // double tryto = 0.9; /* Communication timout (test) */ - - a1logd(p->log, 8, "fast_ser_inst_type: on '%s' dctype 0x%x\n",p->name,p->dctype); + + a1logd(p->log, 8, "fast_ser_dev_type: on '%s' dctype 0x%x\n",p->name,p->dctype); if (!(p->dctype & icomt_seriallike) && !(p->dctype & icomt_fastserial)) { - return p->itype; + return p->dtype; } /* The tick to give up on */ +#if defined(__APPLE__) + etime = msec_time() + (long)(2500.0 + 0.5); /* OS X open() is really slow (1500msec) */ +#else etime = msec_time() + (long)(2000.0 + 0.5); +#endif // etime = msec_time() + (long)(20000.0 + 0.5); /* (test) */ a1logd(p->log, 1, "fser_inst_type: Trying different baud rates (%u msec to go) Path %s%s\n", @@ -1427,7 +1438,7 @@ instType fast_ser_inst_type( if (!tryhard) break; /* try only once */ } - a1logd(p->log, 5, "Trying %s baud\n",baud_rate_to_str(brt[i])); + a1logd(p->log, 5, "Trying %s baud, %d msec to go\n",baud_rate_to_str(brt[i]),etime - msec_time()); if ((se = p->set_ser_port_ex(p, fc_None, brt[i], parity_none, stop_1, length_8, delayms)) != ICOM_OK) { @@ -1437,76 +1448,148 @@ instType fast_ser_inst_type( /* Assume Klein K10 only uses 9600. */ /* We need to also assume that we might be talking to a Spectrolino, */ - /* and avoid upsetting it. */ + /* and avoid upsetting it, or some other serial instrument that */ + /* is set to 9600 baud. */ if ((p->dctype & icomt_btserial) == 0 && brt[i] == baud_9600) { double sto = 0.2; /* Give 9600 a little more time */ int bread, len; + int lgchsum = 0; /* Try a spectrolino/spectroscan command first */ if (tryto > sto) sto = tryto; - p->write_read_ex(p, ";D024\r\n", 0, buf, BUFSZ-1, &bread, "\r", 1, sto, 1); + + /* Do first character only and see if there is an echo */ + p->write_read_ex(p, ";", 1, buf, BUFSZ-1, &bread, "\r", 1, 0.2, 1); + if (bread == 1 && buf[0] == ';') +#ifdef ENABLE_VTPGLUT + goto check_lumagen; +#else + goto continue_looking; +#endif + + /* Send the rest of the spectrolino command */ + p->write_read_ex(p, "D024\r\n", 0, buf, BUFSZ-1, &bread, "\r", 1, 0.2, 1); if (bread == 0) { - a1logd(p->log, 5, "fser_inst_type: Spectroino command returned nothing\n"); - goto not_k10; + char *bp; + a1logd(p->log, 5, "fser_inst_type: Spectrolino command returned nothing\n"); + +#ifdef ENABLE_VTPGLUT + /* It could be a Lumagen Radiance with echo off, */ + /* so poke it and see if it responds. */ + /* (Unfortunately the Lumagen delimeters modes aren't */ + /* backwards compatible, so we may have to poke it twice...) */ + /* Send "X" first, to get it out of menu mode ? */ + p->write_read_ex(p, "X", 1, buf, BUFSZ, NULL, "\n", 1, 0.1, 1); // Menu off + a1logd(p->log, 5, "fser_inst_type: Checking for Lumagen Radiance\n"); + p->write_read_ex(p, "#ZQS00\r", 0, buf, BUFSZ, &bread, "\n", 1, sto, 1); + if (bread == 0) { + p->write_read_ex(p, "#0ZQS008E\r", 0, buf, BUFSZ, &bread, "\n", 1, sto, 1); + lgchsum = 1; + } + + if (bread > 0 + && (bp = strrchr(buf, '!')) != NULL + && strlen(bp) >= 4 + && strncmp(bp,"!S00",4) == 0) { + goto check_lumagen; + } +#endif /* ENABLE_VTPGLUT */ + + /* Nope - look for something at a different baud rate */ + goto continue_looking; } + buf[bread] = '\000'; len = strlen(buf); a1logd(p->log, 5, "fser_inst_type: got %d bytes\n",len); - if (len < 4) { - a1logd(p->log, 5, "fser_inst_type: Reply was too short\n"); - goto not_k10; /* Not K10, X-Rite or Spectrolino */ - } - /* Is this a Spectrolino or Spectroscan error resonse ? */ - if (len >= 5 && strncmp(buf, ":26", 3) == 0 - || len >= 7 && strncmp(buf, ":D183", 5) == 0) { + if ((len >= 5 && strncmp(buf, ":26", 3) == 0) + || (len >= 7 && strncmp(buf, ":D183", 5) == 0)) { a1logd(p->log, 5, "fser_inst_type: Ignore Spectrolino\n"); return instUnknown; /* Not doing Spectrolino detection here */ } /* Is this an X-Rite error value such as "<01>" ? */ - if (buf[0] == '<' && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>') { + if ((buf[0] == '<' && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>') + || (isdigit(buf[0]) && isdigit(buf[1]) && buf[2] == '>')) { a1logd(p->log, 5, "fser_inst_type: Ignore X-Rite\n"); return instUnknown; /* Not doing X-Rite detection here */ } /* The Klein K10 seems to respond with it's calibration list, preceeded by "D4" ? */ - if (buf[0] != 'D' || buf[1] != '4') { - a1logd(p->log, 5, "fser_inst_type: Not Klein response\n"); - goto not_k10;; + if (buf[0] == 'D' && buf[1] == '4') { + a1logd(p->log, 5, "fser_inst_type: Looks like it may be a Klein\n"); + + /* Confirm this is a Klein instrument */ + + /* The first response is the calibration list, and it may need flushing. */ + /* (write_read_ex doesn't cope with time it takes to dump this.) */ + for (;;) { + bread = 0; + p->read(p, buf, BUFSZ, &bread, NULL, BUFSZ, 0.1); + if (bread == 0) + break; + } + + if ((se = p->write_read_ex(p, "P0\r", 0, buf, BUFSZ, NULL, ">", 1, tryto, 1)) == inst_ok) { + + /* Is this a Klein K1/K8/K10 response ? */ + if (strncmp(buf, "P0K-1 ", 6) == 0 + || strncmp(buf, "P0K-8 ", 6) == 0 + || strncmp(buf, "P0K-10", 6) == 0 + || strncmp(buf, "P0KV-10", 7) == 0) { + a1logd(p->log, 5, "fser_inst_type: found Klein K1/K8/K10\n"); + rv = instKleinK10; + break; + } + } } - a1logd(p->log, 5, "fser_inst_type: Looks like it may be a Klein\n"); +#ifdef ENABLE_VTPGLUT + /* Is this a Lumagen Radiance with echo on, it responds with ";D024..." */ + if ((len >= 4 && strncmp(buf, ";D024", 4) == 0) + || (len >= 4 && strncmp(buf, "!N\n\r", 4) == 0)) { + char *bp; - /* Confirm this is a Klein instrument */ + check_lumagen:; - /* The first response is the calibration list, and it may need flushing. */ - /* (write_read_ex doesn't cope with time it takes to dump this.) */ - for (;;) { - bread = 0; - p->read(p, buf, BUFSZ, &bread, NULL, BUFSZ, 0.1); - if (bread == 0) - break; - } + /* Send "X" first, to get it out of menu mode ? */ + p->write_read_ex(p, "X", 1, buf, BUFSZ, NULL, "\n", 1, 0.1, 1); // Menu off - if ((se = p->write_read_ex(p, "P0\r", 0, buf, BUFSZ, NULL, ">", 1, tryto, 1)) == inst_ok) { + /* Get the Lumagen device information */ + p->write_read_ex(p, lgchsum ? "#0ZQS018F\r" : "#ZQS01\r", + 0, buf, BUFSZ, &bread, "\n", 1, sto, 1); - /* Is this a Klein K1/K8/K10 response ? */ - if (strncmp(buf, "P0K-1 ", 6) == 0 - || strncmp(buf, "P0K-8 ", 6) == 0 - || strncmp(buf, "P0K-10", 6) == 0 - || strncmp(buf, "P0KV-10", 7) == 0) { - a1logd(p->log, 5, "fser_inst_type: found Klein K1/K8/K10\n"); - rv = instKleinK10; - break; + /* Might have echo with checksum, so lgchsum not set correctly */ + if (!lgchsum && bread > 0 && strstr(buf, "!N") != NULL) { + p->write_read_ex(p, "#0ZQS018F\r", 0, buf, BUFSZ, &bread, "\n", 1, sto, 1); + if (bread >= 11 && strncmp(buf, "#0ZQS018F!Y", 11) == 0) + lgchsum = 1; + } + + /* returns something like "ZQS01!S01,Radiance2020,030115,1016,001309\r\m" */ + if ((bp = strrchr(buf, '!')) != NULL && strlen(bp) >= 13) { + if (strncmp(bp,"!S01,Radiance",13) == 0) { + a1logd(p->log, 5, "fser_inst_type: Found Lumagen Radiance\n"); + +#ifdef NEVER /* Test various Lumagen com. settings */ + radiance_random(p, lgchsum); +// radiance_delimiters(p, lgchsum); +#endif + radiance_delimiters(p, lgchsum); + return devRadiance; + } } + a1logd(p->log, 5, "fser_inst_type: Not Lumagen Radiance\n"); + return instUnknown; } +#endif /* ENABLE_VTPGLUT */ - not_k10:; + continue_looking:; /* Check for user abort */ if (uicallback != NULL) { @@ -1516,7 +1599,7 @@ instType fast_ser_inst_type( return instUnknown; } } - } + } /* 9600 baud */ /* SwatchMate Cube only uses 38400 */ if ((p->dctype & icomt_btserial) == 0 && brt[i] == baud_38400) { @@ -1549,7 +1632,7 @@ instType fast_ser_inst_type( } /* JETI specbos or spectraval. */ - /* We are fudging the baud rate selection here - */ + /* We are not allowing for all possible baud rate selections here - */ /* the 1211 RS and BT can't handle 921600, */ /* while the 15x1 can handle 230400 & 3000000, which we don't test for... */ // if ((p->dctype & icomt_btserial) == 0 || brt[i] == baud_115200) @@ -1610,16 +1693,116 @@ instType fast_ser_inst_type( if (rv == instUnknown && msec_time() >= etime) { /* We haven't established comms */ a1logd(p->log, 5, "fser_inst_type: Failed to establish coms\n"); - p->itype = rv; + p->dtype = rv; return instUnknown; } a1logd(p->log, 5, "fser_inst_type: Instrument type is '%s'\n", inst_name(rv)); - p->itype = rv; + p->dtype = rv; return rv; } + +#ifdef ENABLE_VTPGLUT + + +/* + Lumagen uses following sequence to setup coms: + + Sent Recieved Comments + ---- -------- -------- + M0931 M0931 use %M0931 to ensure it's on + f Ok if on, else echo's 'f' + B009600 then close & re-open port at 9600 baud. +20x e 20x Ok Some sort of exit menu command ? + e Ok + I 030115.14.051d...... + g Ok5b28 + L000100NQ ..... + lots more + + These sequences seem to not honour the Delimeters etc., but + work all the time ?? + + Needs 'X' to exit M0931 to respond to normal "Z" sequences. + +*/ + +/* Switch Lumagen Radiance to Echo + Delimiters mode */ +static void radiance_delimiters(icoms *p, int lgchsum) { + time_t clk = time(0); + char *com, *chcom; + char buf[BUFSZ]; + + // Echo On + p->write_read_ex(p, lgchsum ? "#0ZE100\r" : "#ZE1\r", + 0, buf, BUFSZ, NULL, "\n", 1, 0.1, 1); + +#ifndef NEVER + // Delimeters off + com = "#ZD0\r"; + chcom = "#0ZD0FE\r"; +#else + // Delimiters on + com = "#ZD1\r"; + chcom = "#0ZD1FF\r"; +#endif + + p->write_read_ex(p, lgchsum ? chcom : com, 0, buf, BUFSZ, NULL, "\n", 1, 0.1, 1); + +#ifdef NEVER + // ~~~999 see if delimiters works +// p->write_read_ex(p, "%", 1, buf, BUFSZ, NULL, "\n", 1, 0.2, 1); // Doesn't work ! +// msec_sleep(1000); + p->write_read_ex(p, "M0931", 5, buf, BUFSZ, NULL, "\n", 1, 0.2, 1); + p->write_read_ex(p, "f", 1, buf, BUFSZ, NULL, "\n", 1, 0.2, 1); + p->write_read_ex(p, "X", 1, buf, BUFSZ, NULL, "\n", 1, 0.2, 1); // Menu off +// p->write_read_ex(p, "eeeeeeeeeeeeeeeeeeee", 20, buf, BUFSZ, NULL, "\n", 1, 0.2, 1); +#endif +} + +/* Test code for Lumagen com. settings; */ +/* - set a random echo and delimeters. */ +static void radiance_random(icoms *p, int lgchsum) { + time_t clk = time(0); + int ech, del; + char *com, *chcom; + char buf[BUFSZ]; + + rand32(clk); + + del = i_rand(0, 3); + ech = i_rand(0, 1); + + fprintf(stderr, "echo %d, del %d\n",ech, del); + // Random Echo: + if (ech == 1) { + p->write_read_ex(p, lgchsum ? "#0ZE100\r" : "#ZE1\r", + 0, buf, BUFSZ, NULL, "\n", 1, 0.1, 1); + } else { + p->write_read_ex(p, lgchsum ? "#0ZE0FF\r" : "#ZE0\r", + 0, buf, BUFSZ, NULL, "\n", 1, 0.1, 1); + } + + // Random Delimeters: + if (del == 0) { + com = "#ZD0\r"; + chcom = "#0ZD0FE\r"; + } else if (del == 1) { + com = "#ZD1\r"; + chcom = "#0ZD1FF\r"; + } else if (del == 2) { + com = "#ZD2\r"; + chcom = "#0ZD200\r"; + } else { + com = "#ZD3\r"; + chcom = "#0ZD301\r"; + } + p->write_read_ex(p, lgchsum ? chcom : com, 0, buf, BUFSZ, NULL, "\n", 1, 0.1, 1); +} +#endif /* ENABLE_VTPGLUT */ + #undef BUFSZ #endif /* ENABLE_FAST_SERIAL */ @@ -1654,7 +1837,7 @@ static instType ser_inst_type( #ifdef ENABLE_USB if (p->usbd != NULL || p->hidd != NULL) - return p->itype; + return p->dtype; #endif /* ENABLE_USB */ bi = 0; @@ -1677,38 +1860,35 @@ static instType ser_inst_type( a1logd(p->log, 5, "Trying %s baud\n",baud_rate_to_str(brt[i])); bread = 0; - /* Try a spectrolino/spectroscan command first */ - p->write_read_ex(p, ";D024\r\n", 0, buf, BUFSZ-1, &bread, "\r", 1, 0.5, 1); + /* Try a spectrolino/spectroscan command first, */ + /* but do first character only and see if there is an echo */ + p->write_read_ex(p, ";", 1, buf, BUFSZ-1, &bread, "\r", 1, 0.2, 1); + if (bread == 1 && buf[0] == ';') + goto continue_looking; /* It may be a Lumagen, so skip it. */ + + /* Send the rest of the spectrolino command */ + p->write_read_ex(p, "D024\r\n", 0, buf, BUFSZ-1, &bread, "\r", 1, 0.5, 1); if (bread == 0) { - /* Check for user abort */ - if (uicallback != NULL) { - inst_code ev; - if ((ev = uicallback(cntx, inst_negcoms)) == inst_user_abort) { - a1logd(p->log, 5, "ser_inst_type: User aborted\n"); - return instUnknown; - } - } - continue; + goto continue_looking; } buf[bread] = '\000'; len = strlen(buf); // a1logd(p->log, 5, "len = %d\n",len); - if (len < 4) - continue; /* The Klein K10 seems to respond with it's calibration list, preceeded by "D4" ? */ /* - don't know how reliable this is though. Another way may be to look for a */ /* response len > 100 characters ?? */ - if (buf[0] == 'D' && buf[1] == '4') { + if (len >= 3 && buf[0] == 'D' && buf[1] == '4') { // a1logd(p->log, 5, "klein\n"); klein = 1; break; } /* Is this an X-Rite error value such as "<01>" ? */ - if (buf[0] == '<' && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>') { + if ((len >= 4 && buf[0] == '<' && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>') + || (len >= 3 && isdigit(buf[0]) && isdigit(buf[1]) && buf[2] == '>')) { // a1logd(p->log, 5, "xrite\n"); xrite = 1; break; @@ -1726,9 +1906,24 @@ static instType ser_inst_type( ss = 1; break; } + + continue_looking:; + + /* Check for user abort */ + if (uicallback != NULL) { + inst_code ev; + if ((ev = uicallback(cntx, inst_negcoms)) == inst_user_abort) { + a1logd(p->log, 5, "ser_inst_type: User aborted\n"); + return instUnknown; + } + } } if (rv == instUnknown + && klein == 0 + && xrite == 0 + && ss == 0 + && so == 0 && msec_time() >= etime) { /* We haven't established comms */ a1logd(p->log, 5, "ser_inst_type: Failed to establish coms\n"); return instUnknown; @@ -1806,7 +2001,7 @@ static instType ser_inst_type( p->close_port(p); /* Or should we leave it open ?? */ - p->itype = rv; + p->dtype = rv; return rv; } @@ -1921,28 +2116,6 @@ int sym_to_inst_mode(inst_mode *mode, const char *sym) { return rv; } -/* ============================================================= */ -/* Utilities */ - -/* Return a string for the xcalstd enum */ -char *xcalstd2str(xcalstd std) { - switch(std) { - case xcalstd_native: - return "NATIVE"; - case xcalstd_xrdi: - return "XRDI"; - case xcalstd_gmdi: - return "GMDI"; - case xcalstd_xrga: - return "XRGA"; - default: - break; - } - return "None"; -} - - - diff --git a/spectro/inst.h b/spectro/inst.h index 01f579d..04e02d6 100644..100755 --- a/spectro/inst.h +++ b/spectro/inst.h @@ -43,6 +43,7 @@ and agreed to support. */ +#include "dev.h" /* Base device class */ #include "insttypes.h" /* libinst Includes this functionality */ #include "disptechs.h" /* libinst Includes this functionality */ #include "icoms.h" /* libinst Includes this functionality */ @@ -101,20 +102,6 @@ struct _ipatch { }; typedef struct _ipatch ipatch; -/* ------------------------------------------------------ */ -/* Gretag/X-Rite specific reflective measurement standard */ - -typedef enum { - xcalstd_none = -2, /* Not set */ - xcalstd_native = -1, /* No conversion */ - xcalstd_xrdi = 0, /* Historical X-Rite */ - xcalstd_gmdi = 1, /* Historical Gretag-Macbeth */ - xcalstd_xrga = 2, /* Current X-Rite */ -} xcalstd; - -/* Return a string for the xcalstd enum */ -char *xcalstd2str(xcalstd std); - /* ---------------------------------------- */ /* Instrument interface abstract base class */ @@ -301,7 +288,7 @@ typedef enum { /* Return a string with a symbolic encoding of the mode flags */ void inst_mode_to_sym(char sym[MAX_INST_MODE_SYM_SZ], inst_mode mode); -/* Return a set of mode flags that correspondf to the symbolic encoding */ +/* Return a set of mode flags that correspond to the symbolic encoding */ /* Return nz if a symbol wasn't recognized */ int sym_to_inst_mode(inst_mode *mode, const char *sym); @@ -363,6 +350,9 @@ typedef enum { typedef enum { inst3_none = 0x00000000, /* No capabilities */ + inst3_average = 0x00000001 /* Can set to average multiple measurements into 1 */ + /* See inst_opt_set_averages */ + } inst3_capability; /* - - - - - - - - - - - - - - - - - - - */ @@ -511,7 +501,10 @@ typedef enum { /* [xcalstd standard] */ inst_opt_get_xcalstd = 0x0023, /* Get the effective X-Rite ref. cal. standard */ /* [xcalstd *standard] */ - inst_opt_lamp_remediate = 0x0024 /* Remediate i1Pro lamp [double seconds] */ + inst_opt_lamp_remediate = 0x0024, /* Remediate i1Pro lamp [double seconds] */ + + inst_opt_set_averages = 0x0025 /* Set the number of measurements to average [int] */ + /* 0 for default */ } inst_opt_type; @@ -680,7 +673,7 @@ typedef enum { inst_conf_ambient } inst_config; -# define EXRA_INST_OBJ +# define EXTRA_INST_OBJ /* Off-line pending readings available (status) */ #define CALIDLEN 200 /* Maxumum length of calibration tile ID string */ @@ -692,12 +685,10 @@ typedef enum { /* after initialisation. */ #define INST_OBJ_BASE \ \ - EXRA_INST_OBJ \ - a1log *log; /* Pointer to debug & error logging class */ \ - instType itype; /* Instrument type determined by driver */ \ - icoms *icom; /* Instrument coms object */ \ - int gotcoms; /* Coms established flag */ \ - int inited; /* Instrument open and initialized flag */ \ + DEV_OBJ_BASE \ + \ + EXTRA_INST_OBJ \ + \ double cal_gy_level; /* Display calibration test window state */ \ int cal_gy_count; /* Display calibration test window state */ \ inst_code (*uicallback)(void *cntx, inst_ui_purp purp); \ diff --git a/spectro/instappsup.c b/spectro/instappsup.c index fc550b4..6c3dd68 100644..100755 --- a/spectro/instappsup.c +++ b/spectro/instappsup.c @@ -27,6 +27,7 @@ #include "sa_config.h" #endif /* !SALONEINSTLIB */ #include "numsup.h" +#include "cgats.h" #include "xspect.h" #include "conv.h" #include "insttypes.h" @@ -504,7 +505,7 @@ inst2_capability inst_show_disptype_options(FILE *fp, char *oline, icompaths *ic strcat(extra, "]"); } - fprintf(fp, "%s%s: %s%s\n",buf, inst_sname(it->itype), sels[j].desc, extra); + fprintf(fp, "%s%s: %s%s\n",buf, inst_sname(it->dtype), sels[j].desc, extra); if (j == 0) { for (m = 0; m < pstart; m++) diff --git a/spectro/instappsup.h b/spectro/instappsup.h index 8da4325..8da4325 100644..100755 --- a/spectro/instappsup.h +++ b/spectro/instappsup.h diff --git a/spectro/instlib.ksh b/spectro/instlib.ksh index 8b0303f..8b0303f 100644..100755 --- a/spectro/instlib.ksh +++ b/spectro/instlib.ksh diff --git a/spectro/instlib.txt b/spectro/instlib.txt index 661584d..661584d 100644..100755 --- a/spectro/instlib.txt +++ b/spectro/instlib.txt diff --git a/spectro/insttypeinst.h b/spectro/insttypeinst.h index 081d130..081d130 100644..100755 --- a/spectro/insttypeinst.h +++ b/spectro/insttypeinst.h diff --git a/spectro/insttypes.c b/spectro/insttypes.c index 760d678..2a61d21 100644..100755 --- a/spectro/insttypes.c +++ b/spectro/insttypes.c @@ -26,6 +26,7 @@ #include "sa_config.h" #endif /* !SALONEINSTLIB */ #include "numsup.h" +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -39,8 +40,8 @@ /* Given a device type, return the corrsponding */ /* category */ -extern icom_type inst_category(instType itype) { - switch (itype) { +extern icom_type dev_category(devType dtype) { + switch (dtype) { /* Color measurement instruments */ case instDTP22: @@ -80,19 +81,26 @@ extern icom_type inst_category(instType itype) { return icomt_instrument; +#ifdef ENABLE_VTPGLUT /* 3D cLUT box */ + case devRadiance: + return icomt_v3dlut | icomt_vtpg; + case devPrisma: + return icomt_v3dlut; /* Video test patern generator box */ - /* Printers */ - case devEpsonR1800: - return icomt_printer; +#endif + + case instFakeDisp: return icomt_unknown; // ??? - } + case devUnknown: + return icomt_unknown; // ??? + } return icomt_cat_any; } @@ -166,6 +174,16 @@ char *inst_sname(instType itype) { case instColorHug2: return "ColorHug2"; + +#ifdef ENABLE_VTPGLUT + case devRadiance: + return "Radiance"; + case devPrisma: + return "Prisma"; +#endif + + + default: break; } @@ -242,6 +260,16 @@ char *inst_name(instType itype) { case instColorHug2: return "Hughski ColorHug2"; + +#ifdef ENABLE_VTPGLUT + case devRadiance: + return "Lumagen Radiance"; + case devPrisma: + return "Q, Inc Prisma"; +#endif + + + default: break; } @@ -337,6 +365,16 @@ instType inst_enum(char *name) { return instColorHug2; +#ifdef ENABLE_VTPGLUT + if (strcmp(name, "Lumagen Radiance") == 0) + return devRadiance; + + if (strcmp(name, "Q, Inc Prisma") == 0) + return devPrisma; +#endif + + + return instUnknown; } @@ -371,6 +409,8 @@ int nep) { /* Number of end points */ return instI1Disp3; if (idProduct == 0x6003) /* ColorMinki Smile (aka. ColorMunki Display Lite) */ return instSmile; + if (idProduct == 0x6008) /* ColorMunki i1Studio */ + return instColorMunki; if (idProduct == 0xD020) /* DTP20 */ return instDTP20; if (idProduct == 0xD092) /* DTP92Q */ @@ -427,6 +467,8 @@ int nep) { /* Number of end points */ + + return instUnknown; } @@ -536,4 +578,40 @@ int inst_illuminant(xspect *sp, instType itype) { return 1; } +/* ============================================================= */ +/* XRGA support */ + +/* Return a string for the xcalstd enum */ +char *xcalstd2str(xcalstd std) { + switch(std) { + case xcalstd_native: + return "NATIVE"; + case xcalstd_xrdi: + return "XRDI"; + case xcalstd_gmdi: + return "GMDI"; + case xcalstd_xrga: + return "XRGA"; + default: + break; + } + return "None"; +} + +/* Parse a string to xcalstd, */ +/* return xcalstd_none if not recognized */ +xcalstd str2xcalstd(char *str) { + if (strcmp(str, "NATIVE") == 0) + return xcalstd_native; + if (strcmp(str, "XRDI") == 0) + return xcalstd_xrdi; + if (strcmp(str, "GMDI") == 0) + return xcalstd_gmdi; + if (strcmp(str, "XRGA") == 0) + return xcalstd_xrga; + + return xcalstd_none; +} + + diff --git a/spectro/insttypes.h b/spectro/insttypes.h index 8306bc8..104b25d 100644..100755 --- a/spectro/insttypes.h +++ b/spectro/insttypes.h @@ -65,21 +65,23 @@ typedef enum { instFakeDisp = 9998, /* Fake display & instrument device id */ +#ifdef ENABLE_VTPGLUT /* 3D cLUT box */ - // 20000 + devRadiance = 20000, /* Lumagen Radiance v3dlut & vtpg */ + devPrisma, /* Q, Inc Prisma v3dlut */ /* Video test patern generator box */ // 30000 +#endif + - /* Printers */ - devEpsonR1800 = 40000 /* Epson R1800 printer */ } devType; /* Aliases for backwards compatibility */ #define instUnknown devUnknown typedef devType instType; -typedef devType cLUTType; +typedef devType vcLUTType; typedef devType vtpgType; typedef devType printerType; @@ -90,7 +92,7 @@ enum _icom_type; /* Given a device type, return the corrsponding */ /* category */ -//extern _icom_type inst_category(instType itype); +//extern _icom_type dev_category(instType itype); /* Given its instrument type, return the matching */ /* short instrument name (static string), */ @@ -127,6 +129,24 @@ int nep); /* Number of end points (0 for prelim match) */ extern int inst_illuminant(xspect *sp, instType itype); +/* ------------------------------------------------------ */ +/* Gretag/X-Rite specific reflective measurement standard */ + +typedef enum { + xcalstd_none = -2, /* Not set */ + xcalstd_native = -1, /* No conversion */ + xcalstd_xrdi = 0, /* Historical X-Rite */ + xcalstd_gmdi = 1, /* Historical Gretag-Macbeth */ + xcalstd_xrga = 2, /* Current X-Rite */ +} xcalstd; + +/* Return a string for the xcalstd enum */ +char *xcalstd2str(xcalstd std); + +/* Parse a string to xcalstd, */ +/* return xcalstd_none if not recognized */ +xcalstd str2xcalstd(char *str); + #ifdef __cplusplus } #endif diff --git a/spectro/iusb.h b/spectro/iusb.h index 94047cf..94047cf 100644..100755 --- a/spectro/iusb.h +++ b/spectro/iusb.h diff --git a/spectro/kleink10.c b/spectro/kleink10.c index 3d67b6c..d169156 100644..100755 --- a/spectro/kleink10.c +++ b/spectro/kleink10.c @@ -54,6 +54,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* !SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -354,7 +355,7 @@ k10_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { baud_rate brt[] = { baud_9600, baud_nc }; unsigned int etime; unsigned int i; - instType itype = pp->itype; + instType dtype = pp->dtype; int se; char *cp; @@ -1486,8 +1487,8 @@ static inst_code k10_imp_measure_refresh( /* Locate the smallest values and maximum time */ maxt = -1e6; - minv = minv = minv = 1e20; - maxv = maxv = maxv = -11e20; + minv = 1e20; + maxv = -11e20; for (i = nfsamps-1; i >= 0; i--) { if (samp[i] < minv) minv = samp[i]; @@ -2842,7 +2843,7 @@ k10_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern kleink10 *new_kleink10(icoms *icom, instType itype) { +extern kleink10 *new_kleink10(icoms *icom, instType dtype) { kleink10 *p; if ((p = (kleink10 *)calloc(sizeof(kleink10),1)) == NULL) { a1loge(icom->log, 1, "new_kleink10: malloc failed!\n"); @@ -2871,7 +2872,7 @@ extern kleink10 *new_kleink10(icoms *icom, instType itype) { p->del = k10_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; p->dtech = disptech_unknown; amutex_init(p->lock); diff --git a/spectro/kleink10.h b/spectro/kleink10.h index 136476a..136476a 100644..100755 --- a/spectro/kleink10.h +++ b/spectro/kleink10.h diff --git a/spectro/linear.sp b/spectro/linear.sp index 8851462..8851462 100644..100755 --- a/spectro/linear.sp +++ b/spectro/linear.sp diff --git a/spectro/madvrwin.c b/spectro/madvrwin.c index 305a240..305a240 100644..100755 --- a/spectro/madvrwin.c +++ b/spectro/madvrwin.c diff --git a/spectro/madvrwin.h b/spectro/madvrwin.h index bbaf32e..bbaf32e 100644..100755 --- a/spectro/madvrwin.h +++ b/spectro/madvrwin.h diff --git a/spectro/mongoose.c b/spectro/mongoose.c index 019101e..019101e 100644..100755 --- a/spectro/mongoose.c +++ b/spectro/mongoose.c diff --git a/spectro/mongoose.h b/spectro/mongoose.h index 1ee0c47..1ee0c47 100644..100755 --- a/spectro/mongoose.h +++ b/spectro/mongoose.h diff --git a/spectro/munki.c b/spectro/munki.c index 16cd863..306f1dc 100644..100755 --- a/spectro/munki.c +++ b/spectro/munki.c @@ -49,6 +49,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -1012,7 +1013,7 @@ munki_del(inst *pp) { } /* Constructor */ -extern munki *new_munki(icoms *icom, instType itype) { +extern munki *new_munki(icoms *icom, instType dtype) { munki *p; int rv; if ((p = (munki *)calloc(sizeof(munki),1)) == NULL) { @@ -1043,7 +1044,7 @@ extern munki *new_munki(icoms *icom, instType itype) { p->del = munki_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; /* Preliminary capabilities */ munki_determine_capabilities(p); diff --git a/spectro/munki.h b/spectro/munki.h index 01eda29..cb4d917 100644..100755 --- a/spectro/munki.h +++ b/spectro/munki.h @@ -46,7 +46,7 @@ struct _munki { INST_OBJ_BASE - int dtype; /* Device type: 0 = ?? */ + int idtype; /* Device type: 0 = ?? */ /* *** munki private data **** */ inst_mode cap; /* Instrument mode capability */ diff --git a/spectro/munki_imp.c b/spectro/munki_imp.c index eae2837..d8690e8 100644..100755 --- a/spectro/munki_imp.c +++ b/spectro/munki_imp.c @@ -60,6 +60,7 @@ #include "numsup.h" #include "rspl1.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -483,7 +484,7 @@ munki_code munki_imp_init(munki *p) { a1logd(p->log,2,"munki_init:\n"); - if (p->itype != instColorMunki) + if (p->dtype != instColorMunki) return MUNKI_UNKNOWN_MODEL; @@ -3183,7 +3184,8 @@ munki_code munki_save_calibration(munki *p) { #endif sprintf(cal_name, "ArgyllCMS/.mk_%s.cal", m->serno); - if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_write, xdg_user, cal_name)) < 1) { + if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_write, xdg_user, xdg_none, + cal_name)) < 1) { a1logd(p->log,1,"munki_save_calibration xdg_bds returned no paths\n"); return MUNKI_INT_CAL_SAVE; } @@ -3299,7 +3301,8 @@ munki_code munki_restore_calibration(munki *p) { #endif sprintf(cal_name, "ArgyllCMS/.mk_%s.cal" SSEPS "color/.mk_%s.cal", m->serno, m->serno); - if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, cal_name)) < 1) { + if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, xdg_none, + cal_name)) < 1) { a1logd(p->log,1,"munki_restore_calibration xdg_bds returned no paths\n"); return MUNKI_INT_CAL_RESTORE; } @@ -3616,7 +3619,8 @@ munki_code munki_touch_calibration(munki *p) { int rv; sprintf(cal_name, "ArgyllCMS/.mk_%s.cal" SSEPS "color/.mk_%s.cal", m->serno, m->serno); - if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, cal_name)) < 1) + if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, xdg_none, + cal_name)) < 1) return MUNKI_INT_CAL_TOUCH; a1logd(p->log,2,"munki_touch_calibration touching file '%s'\n",cal_paths[0]); diff --git a/spectro/munki_imp.h b/spectro/munki_imp.h index f639395..fca4c5f 100644..100755 --- a/spectro/munki_imp.h +++ b/spectro/munki_imp.h @@ -186,7 +186,8 @@ struct _munkiimp { /* Information from the HW */ int fwrev; /* int - Firmware revision number, from getfirm() */ - /* Typically 0120 = V1.32 */ + /* Typically 0120 = V1.32 (Build 1303) */ + /* i1Studio 0200 = V2.00 (Build 1310) */ unsigned char chipid[8]; /* HW serial number */ char vstring[37]; /* Asciiz version string */ int tickdur; /* Tick duration (usec, converted to intclkp) */ diff --git a/spectro/oemarch.c b/spectro/oemarch.c index c8775bf..1837e63 100644..100755 --- a/spectro/oemarch.c +++ b/spectro/oemarch.c @@ -51,6 +51,7 @@ #include "numsup.h" #endif /* SALONEINSTLIB */ #include "xdg_bds.h" +#include "cgats.h" #include "xspect.h" #include "conv.h" #include "aglob.h" diff --git a/spectro/oemarch.h b/spectro/oemarch.h index b0b1a65..b0b1a65 100644..100755 --- a/spectro/oemarch.h +++ b/spectro/oemarch.h diff --git a/spectro/oeminst.c b/spectro/oeminst.c index 726a54c..3a4b03b 100644..100755 --- a/spectro/oeminst.c +++ b/spectro/oeminst.c @@ -30,6 +30,7 @@ #include "conv.h" #include "aglob.h" #include "oemarch.h" +#include "cgats.h" #include "xspect.h" #include "disptechs.h" #include "ccmx.h" @@ -260,7 +261,8 @@ main(int argc, char *argv[]) { int npaths = 0; /* Get destination path. This may drop uid/gid if we are su */ - if ((npaths = xdg_bds(NULL, &paths, xdg_data, xdg_write, scope, install_name)) < 1) { + if ((npaths = xdg_bds(NULL, &paths, xdg_data, xdg_write, scope, xdg_none, + install_name)) < 1) { error("Failed to find/create XDG_DATA path '%s'",install_name); } if (install) diff --git a/spectro/pollem.c b/spectro/pollem.c index 855702b..855702b 100644..100755 --- a/spectro/pollem.c +++ b/spectro/pollem.c diff --git a/spectro/pollem.h b/spectro/pollem.h index bd879e1..bd879e1 100644..100755 --- a/spectro/pollem.h +++ b/spectro/pollem.h diff --git a/spectro/rspec.c b/spectro/rspec.c index 6a7f8c7..c50cd83 100644..100755 --- a/spectro/rspec.c +++ b/spectro/rspec.c @@ -47,6 +47,7 @@ #ifndef SALONEINSTLIB # include "plot.h" #endif +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -928,7 +929,8 @@ int calf_open(calf *x, a1log *log, char *fname, int wr) { sprintf(cal_name, "ArgyllCMS/%s", fname); else sprintf(cal_name, "ArgyllCMS/%s" SSEPS "color/%s", fname, fname); - if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_write, xdg_user, cal_name)) < 1) { + if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_write, xdg_user, xdg_none, + cal_name)) < 1) { a1logd(x->log,1,"calf_open: xdg_bds returned no paths\n"); return 1; } @@ -971,7 +973,8 @@ int calf_touch(a1log *log, char *fname) { /* Locate the file name */ sprintf(cal_name, "ArgyllCMS/%s" SSEPS "color/%s", fname, fname); - if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, cal_name)) < 1) { + if ((no_paths = xdg_bds(NULL, &cal_paths, xdg_cache, xdg_read, xdg_user, xdg_none, + cal_name)) < 1) { a1logd(log,2,"calf_touch: xdg_bds failed to locate file'\n"); return 1; } diff --git a/spectro/rspec.h b/spectro/rspec.h index 0cbee58..0cbee58 100644..100755 --- a/spectro/rspec.h +++ b/spectro/rspec.h diff --git a/spectro/sa_conv.c b/spectro/sa_conv.c index 84286ba..84286ba 100644..100755 --- a/spectro/sa_conv.c +++ b/spectro/sa_conv.c diff --git a/spectro/sa_conv.h b/spectro/sa_conv.h index 0f7e635..0f7e635 100644..100755 --- a/spectro/sa_conv.h +++ b/spectro/sa_conv.h diff --git a/spectro/smcube.c b/spectro/smcube.c index c450d48..9f6947d 100644..100755 --- a/spectro/smcube.c +++ b/spectro/smcube.c @@ -73,6 +73,7 @@ #include "numsup.h" #include "sa_conv.h" #endif /* !SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -203,7 +204,7 @@ smcube_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { baud_rate brt[] = { baud_38400, baud_nc }; unsigned int etime; unsigned int i; - instType itype = pp->itype; + instType dtype = pp->dtype; int se; inst_code ev = inst_ok; @@ -1133,7 +1134,7 @@ smcube_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern smcube *new_smcube(icoms *icom, instType itype) { +extern smcube *new_smcube(icoms *icom, instType dtype) { smcube *p; if ((p = (smcube *)calloc(sizeof(smcube),1)) == NULL) { a1loge(icom->log, 1, "new_smcube: malloc failed!\n"); @@ -1158,7 +1159,7 @@ extern smcube *new_smcube(icoms *icom, instType itype) { p->icom = icom; icom->icntx = (void *)p; /* Allow us to get instrument from icom */ - p->itype = itype; + p->dtype = dtype; amutex_init(p->lock); diff --git a/spectro/smcube.h b/spectro/smcube.h index 06aee9d..06aee9d 100644..100755 --- a/spectro/smcube.h +++ b/spectro/smcube.h diff --git a/spectro/spec2cie.c b/spectro/spec2cie.c index d77c334..6c56e67 100644..100755 --- a/spectro/spec2cie.c +++ b/spectro/spec2cie.c @@ -73,6 +73,7 @@ #include "conv.h" #include "icoms.h" #include "inst.h" +#include "xrga.h" #ifdef ALLOW_PLOT #include "plot.h" #include "ui.h" @@ -87,6 +88,7 @@ usage (void) fprintf (stderr, "\n"); fprintf (stderr, "Usage: spec2cie [options] input.[ti3|sp] output.[ti3|sp]\n"); fprintf (stderr, " -v Verbose mode\n"); + fprintf (stderr, " -A NN|AX|AG|XA|XG|GA|GX XRGA conversion (default NN)\n"); fprintf (stderr, " -I illum Override actual instrument illuminant in .ti3 or .sp file:\n"); fprintf (stderr, " A, C, D50, D50M2, D65, F5, F8, F10 or file.sp\n"); fprintf (stderr, " (only used in conjunction with -f)\n"); @@ -95,7 +97,7 @@ usage (void) fprintf (stderr, " -i illum Choose illuminant for computation of CIE XYZ from spectral data & FWA:\n"); fprintf (stderr, " A, C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp\n"); fprintf (stderr, " -o observ Choose CIE Observer for spectral data:\n"); - fprintf (stderr, " 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2 or file.cmf\n"); + fprintf (stderr, " 1931_2 (def), 1964_10, 2012_2, 2012_10, S&B 1955_2, shaw, J&V 1978_2 or file.cmf\n"); fprintf (stderr, " -n Don't output spectral values\n"); #ifdef ALLOW_PLOT fprintf (stderr, " -p Plot each values spectrum\n"); @@ -110,6 +112,10 @@ main(int argc, char *argv[]) { int fa, nfa; /* current argument we're looking at */ int verb = 0; + xcalstd calstd = xcalstd_none; /* X-Rite calibration standard of .ti3 file */ + xcalpol calpol = xcalstd_nonpol; /* If measurement is polarized */ + xcalstd calstdi = xcalstd_none; /* X-Rite calibration standard conversion in */ + xcalstd calstdo = xcalstd_none; /* X-Rite calibration standard conversion out */ int nospec = 0; /* NZ if not to output spectral values */ char *in_ti3_name; char *out_ti3_name; @@ -117,7 +123,7 @@ main(int argc, char *argv[]) cgats *ocg; /* output cgats structure */ cgats_set_elem *elems; - int isspect = 0; /* nz if SPECT file rathe than TI3 */ + int isspect = 0; /* nz if SPECT file rather than TI3 */ int isemis = 0; /* nz if this is an emissive reference */ int isdisp = 0; /* nz if this is a display device */ int isdnormed = 0; /* Has display data been normalised to 100 ? */ @@ -140,11 +146,11 @@ main(int argc, char *argv[]) xspect inst_cust_illum; /* Custom actual instrument illumination spectrum */ /* if inst_illum == icxIT_custom */ - icxObserverType observ = icxOT_none; - xspect cust_observ[3]; /* Custom observer CMF's */ + icxObserverType obType = icxOT_none; + xspect custObserver[3]; /* Custom observer CMF's */ int npat; /* Number of patches */ - int dti; /* Device Type index */ + int ti; /* Field index */ char *kw; int i, j, jj, k; @@ -175,12 +181,43 @@ main(int argc, char *argv[]) } if (argv[fa][1] == '?') - usage (); + usage(); /* Verbose */ else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') verb = 1; + /* XRGA conversion */ + else if (argv[fa][1] == 'A') { + fa = nfa; + if (na == NULL) usage(); + if (na[0] == 'N' && na[1] == 'N') { + calstdi = xcalstd_none; + calstdo = xcalstd_none; + } else if (na[0] == 'A' && na[1] == 'X') { + calstdi = xcalstd_xrga; + calstdo = xcalstd_xrdi; + } else if (na[0] == 'A' && na[1] == 'G') { + calstdi = xcalstd_xrga; + calstdo = xcalstd_gmdi; + } else if (na[0] == 'X' && na[1] == 'A') { + calstdi = xcalstd_xrdi; + calstdo = xcalstd_xrga; + } else if (na[0] == 'X' && na[1] == 'G') { + calstdi = xcalstd_xrdi; + calstdo = xcalstd_gmdi; + } else if (na[0] == 'G' && na[1] == 'A') { + calstdi = xcalstd_gmdi; + calstdo = xcalstd_xrga; + } else if (na[0] == 'G' && na[1] == 'X') { + calstdi = xcalstd_gmdi; + calstdo = xcalstd_xrdi; + } else { + //usage("Paramater after -A '%c%c' not recognized",na[0],na[1]); + usage(); + } + } + /* Don't output spectral */ else if (argv[fa][1] == 'n' || argv[fa][1] == 'N') nospec = 1; @@ -327,25 +364,25 @@ main(int argc, char *argv[]) else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') { fa = nfa; if (na == NULL) - usage (); + usage(); if (strcmp (na, "1931_2") == 0) { /* Classic 2 degree */ - observ = icxOT_CIE_1931_2; + obType = icxOT_CIE_1931_2; } else if (strcmp (na, "1964_10") == 0) { /* Classic 10 degree */ - observ = icxOT_CIE_1964_10; - } - else if (strcmp (na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */ - observ = icxOT_Stiles_Burch_2; - } - else if (strcmp (na, "1978_2") == 0) { /* Judd and Voss 1978 2 degree */ - observ = icxOT_Judd_Voss_2; - } - else if (strcmp (na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */ - observ = icxOT_Shaw_Fairchild_2; - } - else { /* Assume it's a filename */ - observ = icxOT_custom; - if (read_cmf (cust_observ, na) != 0) + obType = icxOT_CIE_1964_10; + } else if (strcmp(na, "2012_2") == 0) { /* Latest 2 degree */ + obType = icxOT_CIE_2012_2; + } else if (strcmp(na, "2012_10") == 0) { /* Latest 10 degree */ + obType = icxOT_CIE_2012_10; + } else if (strcmp (na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */ + obType = icxOT_Stiles_Burch_2; + } else if (strcmp (na, "1978_2") == 0) { /* Judd and Voss 1978 2 degree */ + obType = icxOT_Judd_Voss_2; + } else if (strcmp (na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */ + obType = icxOT_Shaw_Fairchild_2; + } else { /* Assume it's a filename */ + obType = icxOT_custom; + if (read_cmf (custObserver, na) != 0) usage (); } } @@ -376,21 +413,21 @@ main(int argc, char *argv[]) ocg = new_cgats (); /* Create a CGATS structure */ ocg->add_other (ocg, "CTI3"); /* Calibration Target Information 3 */ - icg->add_other (ocg, "SPECT"); /* Spectral file */ + ocg->add_other (ocg, "SPECT"); /* Spectral file */ if (icg->read_name (icg, in_ti3_name)) error ("CGATS file read error: %s", icg->err); + if (icg->ntables < 1) + error ("Input file doesn't contain at least one table"); + if (icg->ntables == 0 || icg->t[0].tt != tt_other || (icg->t[0].oi != 0 && icg->t[0].oi != 1)) error ("Input file isn't a CTI3 or SPECT format file"); - if (icg->t[0].oi == 1) + if (icg->t[0].oi == 1) /* SPECT type */ isspect = 1; - if (icg->ntables < 1) - error ("Input file doesn't contain at least one table"); - /* add table to output file */ if (isspect) ocg->add_table(ocg, tt_other, 1); @@ -416,14 +453,14 @@ main(int argc, char *argv[]) } if (isspect) { - if ((dti = icg->find_kword (icg, 0, "MEAS_TYPE")) < 0) + if ((ti = icg->find_kword (icg, 0, "MEAS_TYPE")) < 0) error ("Input file doesn't contain keyword MEAS_TYPE"); /* Reflective options when not a reflective profile type */ - if (strcmp(icg->t[0].kdata[dti],"EMISSION") == 0 - || strcmp(icg->t[0].kdata[dti],"AMBIENT") == 0 - || strcmp(icg->t[0].kdata[dti],"EMISSION_FLASH") == 0 - || strcmp(icg->t[0].kdata[dti],"AMBIENT_FLASH") == 0) { + if (strcmp(icg->t[0].kdata[ti],"EMISSION") == 0 + || strcmp(icg->t[0].kdata[ti],"AMBIENT") == 0 + || strcmp(icg->t[0].kdata[ti],"EMISSION_FLASH") == 0 + || strcmp(icg->t[0].kdata[ti],"AMBIENT_FLASH") == 0) { isemis = 1; if (illum != icxIT_none) error("-i illuminant can't be used for emissive reference type"); @@ -434,12 +471,12 @@ main(int argc, char *argv[]) } } else { - if ((dti = icg->find_kword (icg, 0, "DEVICE_CLASS")) < 0) + if ((ti = icg->find_kword (icg, 0, "DEVICE_CLASS")) < 0) error ("Input file doesn't contain keyword DEVICE_CLASS"); /* Reflective options when not a reflective profile type */ - if (strcmp(icg->t[0].kdata[dti],"DISPLAY") == 0 - || strcmp(icg->t[0].kdata[dti],"EMISINPUT") == 0) { + if (strcmp(icg->t[0].kdata[ti],"DISPLAY") == 0 + || strcmp(icg->t[0].kdata[ti],"EMISINPUT") == 0) { isemis = 1; if (illum != icxIT_none) error("-i illuminant can't be used for emissive reference type"); @@ -454,8 +491,38 @@ main(int argc, char *argv[]) if (illum == icxIT_none) illum = icxIT_D50; - if (observ == icxOT_none) - observ = icxOT_CIE_1931_2; + if (obType == icxOT_none) + obType = icxOT_CIE_1931_2; + + /* See if the measurements were polarized */ + if ((ti = icg->find_kword(icg, 0, "INSTRUMENT_FILTER")) >= 0 + && strcmp(icg->t[0].kdata[ti], "POLARIZED") == 0) { + calpol = xcalstd_pol; /* If measurement is polarized */ + } + + /* See if there is an XRGA anotation in the incoming file */ + if ((ti = icg->find_kword(icg, 0, "DEVCALSTD")) >= 0) { + calstd = str2xcalstd(icg->t[0].kdata[ti]); + } + + /* Check XRGA conversion */ + if (calstdo != xcalstd_none) { + + if (isemis || isdisp) + error("XRGA conversion only applies to reflective measurements"); + + if (calstd != xcalstd_none + && calstd != calstdi) { + warning("Input file calibration standard '%s' doesn't match -A parameter '%s'", + xcalstd2str(calstd), xcalstd2str(calstdi)); + } + + /* Anotate output file */ + if ((ti = ocg->find_kword (ocg, 0, "DEVCALSTD")) >= 0) + ocg->add_kword_at(ocg, 0, ti, "DEVCALSTD",xcalstd2str(calstdo), NULL); + else + ocg->add_kword(ocg, 0, "DEVCALSTD",xcalstd2str(calstdo), NULL); + } /* See if the display CIE data has been normalised to Y = 100 */ { @@ -477,7 +544,7 @@ main(int argc, char *argv[]) if ((ti = icg->find_kword(icg, 0, "COLOR_REP")) < 0) error("Input file doesn't contain keyword COLOR_REP"); - if (strcmp (icg->t[0].kdata[dti], "DISPLAY") == 0) { + if (strcmp (icg->t[0].kdata[ti], "DISPLAY") == 0) { isdisp = 1; } @@ -700,16 +767,16 @@ main(int argc, char *argv[]) } /* If CIE calculation illuminant is not standard, compute it's white point */ - if (illum != icxIT_D50) { + if (illum != icxIT_D50 && illum != icxIT_none) { ill_wp = _ill_wp; - /* Compute XYZ of illuminant */ - if (icx_ill_sp2XYZ(ill_wp, observ, cust_observ, illum, 0.0, &cust_illum) != 0) + /* Compute normalised XYZ of illuminant */ + if (icx_ill_sp2XYZ(ill_wp, obType, custObserver, illum, 0.0, &cust_illum, 0) != 0) error("icx_ill_sp2XYZ returned error"); } /* Create a spectral conversion object */ - if ((sp2cie = new_xsp2cie(illum, &cust_illum, observ, cust_observ, + if ((sp2cie = new_xsp2cie(illum, &cust_illum, obType, custObserver, icSigXYZData, icxClamp)) == NULL) { error ("Creation of spectral conversion object failed"); @@ -789,6 +856,10 @@ main(int argc, char *argv[]) for (j = 0; j < rmwsp.spec_n; j++) { rmwsp.spec[j] /= nw; /* Compute average */ } + + if (calstdo != xcalstd_none) + xspec_convert_xrga(&rmwsp, &rmwsp, calpol, calstdo, calstdi); + mwsp = rmwsp; /* Structure copy */ } @@ -838,7 +909,7 @@ main(int argc, char *argv[]) printf("FWA content = %f\n",FWAc); } - /* Create an FWA compensated white spectrum and XYZ value */ + /* Create an FWA compensated white spectrum and XYZ value */ sp2cie->sconvert (sp2cie, &rmwsp, mwXYZ, &mwsp); } @@ -895,6 +966,8 @@ main(int argc, char *argv[]) for (j = 0; j < sp.spec_n; j++) { sp.spec[j] = *((double *)icg->t[0].fdata[i][spi[j]]); } + if (calstdo != xcalstd_none) + xspec_convert_xrga(&sp, &sp, calpol, calstdo, calstdi); if (fwacomp) { corr_sp = sp; /* Copy spectrum */ diff --git a/spectro/specbos.c b/spectro/specbos.c index 4c5e4ba..136fb34 100644..100755 --- a/spectro/specbos.c +++ b/spectro/specbos.c @@ -63,6 +63,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* !SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -74,6 +75,9 @@ static inst_code specbos_interp_code(inst *pp, int ec); #define MAX_MES_SIZE 500 /* Maximum normal message reply size */ #define MAX_RD_SIZE 8000 /* Maximum reading message reply size */ +#define DEFAULT_TRANS_NAV 10 /* Default transmission mode number of averages */ +#define DEFAULT_NAV 1 /* Default other mode number of averages */ + /* Interpret an icoms error into a SPECBOS error */ static int icoms2specbos_err(int se) { if (se != ICOM_OK) { @@ -132,13 +136,18 @@ int nd /* nz to disable debug messages */ return icoms2specbos_err(se); } - /* Over Bluetooth, we get an erronious string "AT+JSCR\r\n" mixed in our output. */ + /* Over Bluetooth, we get an erroneous string "AT+JSCR\r\n" mixed in our output. */ /* This would appear to be from the eBMU Bluetooth adapter AT command set. */ if (bread > 9 && strncmp(out, "AT+JSCR\r\n", 9) == 0) { a1logd(p->log, 8, "specbos: ignored 'AT+JSCR\\r\\n' response\n"); memmove(out, out+9, bsize-9); bread -= 9; } + if (bread > 8 && strncmp(out, "AT+JSCR\r", 8) == 0) { + a1logd(p->log, 8, "specbos: ignored 'AT+JSCR\\r' response\n"); + memmove(out, out+8, bsize-8); + bread -= 8; + } /* See if there was an error, and remove any enquire codes */ for (dp = cp = out; *cp != '\000' && (dp - out) < bsize; cp++) { @@ -221,7 +230,7 @@ specbos_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { unsigned int etime; unsigned int len, i; - instType itype = pp->itype; + instType dtype = pp->dtype; int se; inst_code ev = inst_ok; @@ -250,6 +259,8 @@ specbos_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { return ev; } + msec_sleep(600); + /* We need to setup communications */ } else { int delayms = 0; @@ -261,7 +272,7 @@ specbos_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { a1logd(p->log, 1, "specbos_init_coms: Trying different baud rates (%u msec to go)\n",etime - msec_time()); /* Spectraval Bluetooth serial doesn't seem to actuall function */ - /* until 600msec after it is opened. We get arroneos "AT+JSCR\r\n" reply */ + /* until 600msec after it is opened. We get an erroneous "AT+JSCR\r\n" reply */ /* within that time, and it won't re-open after closing. */ if (p->icom->dctype & icomt_btserial) delayms = 600; @@ -321,8 +332,8 @@ specbos_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { p->model = 1201; } else if ((len >= 10 && strncmp(buf, "JETI_SDCM3", 10) == 0) || (len >= 9 && strncmp(buf, "DCM3_JETI", 9) == 0) - || (len >= 17 && strncmp(buf, "PECFIRM_JETI_1501", 18) == 0) - || (len >= 18 && strncmp(buf, "SPECFIRM_JETI_1501", 17) == 0)) { + || (len >= 17 && strncmp(buf, "PECFIRM_JETI_1501", 17) == 0) + || (len >= 18 && strncmp(buf, "SPECFIRM_JETI_1501", 18) == 0)) { p->model = 1501; } else { if (len < 11 @@ -342,22 +353,32 @@ specbos_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { } a1logd(p->log, 2, "specbos_init_coms: init coms has suceeded\n"); - p->gotcoms = 1; - /* See if it's a 1501 or 1511 */ if (p->model == 1501) { + int i; int dispen = 0; - if ((ev = specbos_command(p, "*conf:dispen?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) { - amutex_unlock(p->lock); - a1logd(p->log, 2, "specbos_init_coms: failed to get display status\n"); - return inst_protocol_error; - } - if (sscanf(buf, "%d ",&dispen) != 1) { - amutex_unlock(p->lock); - a1loge(p->log, 1, "specbos_init_inst: failed to parse display status\n"); - return ev; + /* Try a few times because of BT misbehaviour */ + for (i = 0; i < 3; i++) { + if ((ev = specbos_command(p, "*conf:dispen?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) { + if (i < 3) + continue; + amutex_unlock(p->lock); + a1logd(p->log, 2, "specbos_init_coms: failed to get display status\n"); + return inst_protocol_error; + } + + if (sscanf(buf, "%d ",&dispen) != 1) { + if (i < 3) + continue; + amutex_unlock(p->lock); + a1loge(p->log, 1, "specbos_init_inst: failed to parse display status\n"); + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); + } else { + break; + } } + a1logd(p->log, 1, " spectraval %s display\n",dispen ? "has" : "doesn't have"); if (dispen) { p->model = 1511; @@ -393,6 +414,8 @@ specbos_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { } #endif + p->gotcoms = 1; + amutex_unlock(p->lock); return inst_ok; } @@ -559,25 +582,33 @@ specbos_init_inst(inst *pp) { p->measto = 20.0; /* Set default. Specbos default is 60.0 */ if (p->model == 1211) - p->measto = 6.0; /* Same overall time as i1d3 ?? */ + p->measto = 6.0 + 3.6; /* Aprox. Same overall time as i1d3 ?? */ else if (p->model == 1201) - p->measto = 16.0; + p->measto = 16.0 + 3.6; else if (p->model == 1501 || p->model == 1511) - p->measto = 6.0; + p->measto = 6.0 + 3.6; /* Implement max auto int. time, to speed up display measurement */ if (p->model == 1501 || p->model == 1511) { +#ifdef NEVER /* Bound auto by integration time (worse for inttime > 1.0) */ int maxaver = 2; /* Maximum averages for auto int time */ double dmaxtint; int maxtint; /* Actual time taken depends on maxtint, autoavc & fudge factor. */ - dmaxtint = p->measto/(maxaver + 3.5); + dmaxtint = (p->measto - 3.6)/(2.0 * maxaver); + + //printf("dmaxtint %f\n",dmaxtint); maxtint = (int)(dmaxtint * 1000.0+0.5); - if (maxtint < 1000 || maxtint > 64999) - error("specbos: assert, maxtint %d out of range",maxtint); + if (maxtint < 1000 || maxtint > 64999) { + warning("specbos: assert, maxtint %d out of range",maxtint); + if (maxtint < 1000) + maxtint = 1000; + else if (maxtint > 64999) + maxtint = 64999; + } /* Set maximum integration time */ sprintf(mes, "*para:maxtint %d\r", maxtint); @@ -592,6 +623,45 @@ specbos_init_inst(inst *pp) { amutex_unlock(p->lock); return ev; } +#else /* Bound auto by no. averages (better - limit maxint to 1.0) */ + double dmaxtint = 1.0; /* Recommended maximum */ + int maxtint; + int maxaver; /* Maximum averages for auto int time */ + + maxtint = (int)(dmaxtint * 1000.0+0.5); + + if (maxtint < 1000 || maxtint > 64999) { + warning("specbos: assert, maxtint %d out of range",maxtint); + if (maxtint < 1000) + maxtint = 1000; + else if (maxtint > 64999) + maxtint = 64999; + } + + /* Set maximum integration time */ + sprintf(mes, "*para:maxtint %d\r", maxtint); + if ((ev = specbos_command(p, mes, buf, MAX_MES_SIZE, 1.0)) != inst_ok) { + amutex_unlock(p->lock); + return ev; + } + + /* Total time = overhead + initial sample + 2 * int time per measure */ + maxaver = (int)ceil((p->measto - 3.6)/(2.0 * dmaxtint)); + + //printf("maxaver %d\n",maxaver); + + if (maxaver < 2) { + warning("specbos: assert, maxaver %d out of range",maxaver); + maxaver = 2; + } + + /* Set maximum number of auto averages. Min value is 2 */ + sprintf(mes, "*para:maxaver %d\r", maxaver); + if ((ev = specbos_command(p, mes, buf, MAX_MES_SIZE, 1.0)) != inst_ok) { + amutex_unlock(p->lock); + return ev; + } +#endif /* spectraval doesn't support *fetch:XYZ command */ p->noXYZ = 1; @@ -600,38 +670,69 @@ specbos_init_inst(inst *pp) { double dmaxtin; int maxtin; - dmaxtin = p->measto/2.5; /* Fudge factor */ + /* Total time = overhead + initial sample + 2 * int time per measure */ + dmaxtin = (p->measto - 3.6)/2.0; /* Fudge factor */ + maxtin = (int)(dmaxtin * 1000.0+0.5); - if (maxtin < 1000 || maxtin > 64999) - error("specbos: assert, maxtin %d out of range",maxtin); + if (maxtin < 1000 || maxtin > 64999) { + warning("specbos: assert, maxtint %d out of range",maxtin); + if (maxtin < 1000) + maxtin = 1000; + else if (maxtin > 64999) + maxtin = 64999; + } /* Set maximum integration time */ - sprintf(mes, "*para:maxtint %d\r", maxtin); + /* (1201 *para:maxtint doesn't work !!) */ + sprintf(mes, "*conf:maxtin %d\r", maxtin); + if ((ev = specbos_command(p, mes, buf, MAX_MES_SIZE, 1.0)) != inst_ok) { + amutex_unlock(p->lock); + return ev; + } + +#ifdef NEVER /* Use default */ + /* Set split time to limit dark current error for long integration times */ + sprintf(mes, "*para:splitt %d\r", 1000); if ((ev = specbos_command(p, mes, buf, MAX_MES_SIZE, 1.0)) != inst_ok) { amutex_unlock(p->lock); return ev; } +#endif + } if (p->model == 1501 || p->model == 1511) { + int i; int wstart, wend, wstep; - /* Set the measurement format to None. We will read measurement manually. */ - /* (0 = None, 1 = Binary, 2 = ASCII) */ - if ((ev = specbos_command(p, "*para:form 0\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) { - amutex_unlock(p->lock); - return ev; - } + /* Try several times due to BT problems */ + for (i = 0; i < 3; i++) { + /* Set the measurement format to None. We will read measurement manually. */ + /* (0 = None, 1 = Binary, 2 = ASCII) */ + if ((ev = specbos_command(p, "*para:form 0\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) { + if (i < 3) + continue; + amutex_unlock(p->lock); + return ev; + } - if ((ev = specbos_command(p, "*para:wran?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) { - amutex_unlock(p->lock); - return ev; - } - if (sscanf(buf, "%d %d %d",&wstart,&wend,&wstep) != 3) { - amutex_unlock(p->lock); - a1loge(p->log, 1, "specbos_init_inst: failed to parse wavelength range\n"); - return ev; + if ((ev = specbos_command(p, "*para:wran?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) { + if (i < 3) + continue; + amutex_unlock(p->lock); + return ev; + } + if (sscanf(buf, "%d %d %d",&wstart,&wend,&wstep) != 3) { + if (i < 3) + continue; + amutex_unlock(p->lock); + a1loge(p->log, 1, "specbos_init_inst: failed to parse wavelength range\n"); + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); + + } else { + break; + } } p->wl_short = (double)wstart; @@ -679,7 +780,7 @@ specbos_init_inst(inst *pp) { if (sscanf(buf, "Predefined start wave: %lf ",&p->wl_short) != 1) { amutex_unlock(p->lock); a1loge(p->log, 1, "specbos_init_inst: failed to parse start wave\n"); - return ev; + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); } a1logd(p->log, 1, " Short wl range %f\n",p->wl_short); @@ -690,7 +791,7 @@ specbos_init_inst(inst *pp) { if (sscanf(buf, "Predefined end wave: %lf ",&p->wl_long) != 1) { amutex_unlock(p->lock); a1loge(p->log, 1, "specbos_init_inst: failed to parse end wave\n"); - return ev; + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); } if (p->wl_long > 830.0) /* Could go to 1000 with 1211 */ p->wl_long = 830.0; /* Limit it to useful visual range */ @@ -807,13 +908,13 @@ specbos_get_target_laser( } if (p->model == 1501 || p->model == 1511) { if (sscanf(buf, "%d ",&lstate) != 1) { - a1loge(p->log, 2, "specbos_get_target_laser: failed to parse laser state\n"); - return inst_protocol_error; + a1logd(p->log, 1, "specbos_get_target_laser: failed to parse laser state\n"); + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); } } else { if (sscanf(buf, "laser: %d ",&lstate) != 1) { - a1loge(p->log, 2, "specbos_get_target_laser: failed to parse laser state\n"); - return inst_protocol_error; + a1logd(p->log, 1, "specbos_get_target_laser: failed to parse laser state\n"); + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); } } *laser = lstate; @@ -956,9 +1057,18 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ } } + /* If we have a requested number of averages */ + if (p->noaverage != 0) { + if ((rv = set_average(p, p->noaverage, 0)) != inst_ok) + return rv; + /* Set to average 10 readings for transmission */ - if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission) { - if ((rv = set_average(p, 10, 0)) != inst_ok) + } else if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission) { + if ((rv = set_average(p, DEFAULT_TRANS_NAV, 0)) != inst_ok) + return rv; + /* Or default 1 otherwise */ + } else { + if ((rv = set_average(p, DEFAULT_NAV, 0)) != inst_ok) return rv; } @@ -1037,7 +1147,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ &val->XYZ[0], &val->XYZ[1], &val->XYZ[2]) != 3) { amutex_unlock(p->lock); a1logd(p->log, 1, "specbos_read_sample: failed to parse '%s'\n",buf); - return inst_protocol_error; + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); } /* Hmm. Some older firmware versions are reported to not support the */ @@ -1048,7 +1158,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ p->noXYZ = 1; if (p->model == 1501 || p->model == 1511) { - if ((ec = specbos_fcommand(p, "*calc:PHOTOmetric\r", buf, MAX_RD_SIZE, 0.5, 1, tnorm, 0)) + if ((ec = specbos_fcommand(p, "*calc:PHOTOmetric\r", buf, MAX_RD_SIZE, 1.0, 1, tnorm, 0)) != SPECBOS_OK) { amutex_unlock(p->lock); return specbos_interp_code((inst *)p, ec); @@ -1056,7 +1166,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ if (sscanf(buf, "%lf ", &Yxy[0]) != 1) { amutex_unlock(p->lock); a1logd(p->log, 1, "specbos_read_sample: failed to parse '%s'\n",buf); - return inst_protocol_error; + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); } } else { if ((ec = specbos_fcommand(p, "*fetch:PHOTOmetric\r", buf, MAX_RD_SIZE, 0.5, 1, tnorm, 0)) @@ -1067,7 +1177,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ if (sscanf(buf, "Luminance[cd/m^2]: %lf ", &Yxy[0]) != 1) { amutex_unlock(p->lock); a1logd(p->log, 1, "specbos_read_sample: failed to parse '%s'\n",buf); - return inst_protocol_error; + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); } } @@ -1080,7 +1190,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ if (sscanf(buf, " %lf %lf ", &Yxy[1], &Yxy[2]) != 2) { amutex_unlock(p->lock); a1logd(p->log, 1, "specbos_read_sample: failed to parse '%s'\n",buf); - return inst_protocol_error; + return specbos_interp_code((inst *)p, SPECBOS_DATA_PARSE_ERROR); } } else { if ((ec = specbos_fcommand(p, "*fetch:CHROMXY\r", buf, MAX_RD_SIZE, 0.5, 1, tnorm, 0)) @@ -1147,10 +1257,10 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ /* Fetch the spectral readings */ if (p->model == 1501 || p->model == 1511) - ec = specbos_fcommand(p, "*calc:sprad\r", buf, MAX_RD_SIZE, 4.0, + ec = specbos_fcommand(p, "*calc:sprad\r", buf, MAX_RD_SIZE, 6.0, 1, tspec, 0); else - ec = specbos_fcommand(p, "*fetch:sprad\r", buf, MAX_RD_SIZE, 4.0, + ec = specbos_fcommand(p, "*fetch:sprad\r", buf, MAX_RD_SIZE, 6.0, 2+p->nbands+1, tnorm, 0); if (ec != SPECBOS_OK) { a1logd(p->log, 1, "specbos_fcommand: failed with 0x%x\n",ec); @@ -1196,7 +1306,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ try_again:; } if (tries >= maxtries) { - a1logd(p->log, 1, "specbos_fcommand: ran out of retries\n"); + a1logd(p->log, 1, "specbos_fcommand: ran out of retries - parsing error ?\n"); amutex_unlock(p->lock); return inst_protocol_error; } @@ -1616,7 +1726,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ p->mode = inst_mode_emis_tele | inst_mode_spectral; p->doing_cal = 1; - /* Set to average 50 readings */ + /* Set to average 50 readings for calibration */ if ((ev = set_average(p, 50, 1)) != inst_ok) return ev; @@ -1982,9 +2092,9 @@ specbos_del(inst *pp) { if (p->th != NULL) { /* Terminate diffuser monitor thread */ int i; p->th_term = 1; /* Tell thread to exit on error */ - for (i = 0; p->th_termed == 0 && i < 5; i++) + for (i = 0; p->th_termed == 0 && i < 50; i++) msec_sleep(100); /* Wait for thread to terminate */ - if (i >= 5) { + if (i >= 50) { a1logd(p->log,3,"specbos diffuser thread termination failed\n"); } p->th->del(p->th); @@ -2007,6 +2117,7 @@ inst3_capability *pcap3) { specbos *p = (specbos *)pp; inst_mode cap1 = 0; inst2_capability cap2 = 0; + inst3_capability cap3 = 0; cap1 |= inst_mode_emis_tele | inst_mode_trans_spot /* Emulated transmission mode diffuse/90 */ @@ -2034,12 +2145,15 @@ inst3_capability *pcap3) { cap2 |= inst2_get_refresh_rate; } + /* Can average multiple measurements */ + cap3 |= inst3_average; + if (pcap1 != NULL) *pcap1 = cap1; if (pcap2 != NULL) *pcap2 = cap2; if (pcap3 != NULL) - *pcap3 = inst3_none; + *pcap3 = cap3; } /* Return current or given configuration available measurement modes. */ @@ -2368,6 +2482,24 @@ specbos_get_set_opt(inst *pp, inst_opt_type m, ...) { if (!p->inited) return inst_no_init; + if (m == inst_opt_set_averages) { + va_list args; + int nav = 1; + + va_start(args, m); + nav = va_arg(args, int); + va_end(args); + + if (nav < 0) + return inst_bad_parameter; + + p->noaverage = nav; + + /* Averages will get set before each measurement */ + + return inst_ok; + } + /* Use default implementation of other inst_opt_type's */ { inst_code rv; @@ -2382,7 +2514,7 @@ specbos_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern specbos *new_specbos(icoms *icom, instType itype) { +extern specbos *new_specbos(icoms *icom, instType dtype) { specbos *p; if ((p = (specbos *)calloc(sizeof(specbos),1)) == NULL) { a1loge(icom->log, 1, "new_specbos: malloc failed!\n"); @@ -2410,12 +2542,14 @@ extern specbos *new_specbos(icoms *icom, instType itype) { p->del = specbos_del; p->icom = icom; - p->itype = itype; - if (p->itype == instSpecbos1201) + p->dtype = dtype; + if (p->dtype == instSpecbos1201) p->model = 1201; amutex_init(p->lock); + p->noaverage = 1; + return p; } diff --git a/spectro/specbos.h b/spectro/specbos.h index 5c89fd5..ef6fc2f 100644..100755 --- a/spectro/specbos.h +++ b/spectro/specbos.h @@ -160,6 +160,9 @@ struct _specbos { int doing_cal; /* Flag - doing internal calibration measure */ /* Other state */ + int noaverage; /* Current setting of number of measurements to average */ + /* 0 for default */ + athread *th; /* Diffuser position monitoring thread */ volatile int th_term; /* nz to terminate thread */ volatile int th_termed; /* nz when thread terminated */ diff --git a/spectro/spotread.c b/spectro/spotread.c index c5ac955..16f6f2d 100644..100755 --- a/spectro/spotread.c +++ b/spectro/spotread.c @@ -277,7 +277,7 @@ usage(char *diag, ...) { #ifndef SALONEINSTLIB fprintf(stderr," -S Plot spectrum for each reading\n"); #endif /* !SALONEINSTLIB */ - fprintf(stderr," -c listno Set communication port from the following list (default %d)\n",COMPORT); + fprintf(stderr," -c listno Set instrument port from the following list (default %d)\n",COMPORT); if ((icmps = new_icompaths(g_log)) != NULL) { icompath **paths; if ((paths = icmps->paths) != NULL) { @@ -286,8 +286,8 @@ usage(char *diag, ...) { if (paths[i] == NULL) break; #if !defined(NOT_ALLINSTS) || defined(EN_SPYD2) - if ((paths[i]->itype == instSpyder1 && setup_spyd2(0) == 0) - || (paths[i]->itype == instSpyder2 && setup_spyd2(1) == 0)) + if ((paths[i]->dtype == instSpyder1 && setup_spyd2(0) == 0) + || (paths[i]->dtype == instSpyder2 && setup_spyd2(1) == 0)) fprintf(stderr," %d = '%s' !! Disabled - no firmware !!\n",i+1,paths[i]->name); else #endif @@ -318,9 +318,9 @@ usage(char *diag, ...) { #endif fprintf(stderr," -Q observ Choose CIE Observer for spectral data or CCSS instrument:\n"); #ifndef SALONEINSTLIB - fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2\n"); + fprintf(stderr," 1931_2 (def), 1964_10, 2012_2, 2012_10, S&B 1955_2, shaw, J&V 1978_2 or file.cmf\n"); #else - fprintf(stderr," 1931_2 (def), 1964_10\n"); + fprintf(stderr," 1931_2 (def), 1964_10, 2012_2, 2012_10 or file.cmf\n"); #endif #ifndef SALONEINSTLIB fprintf(stderr," (Choose FWA during operation)\n"); @@ -334,6 +334,9 @@ usage(char *diag, ...) { fprintf(stderr," -A N|A|X|G XRGA conversion (default N)\n"); fprintf(stderr," -x Display Yxy instead of Lab\n"); fprintf(stderr," -h Display LCh instead of Lab\n"); +#ifndef SALONEINSTLIB + fprintf(stderr," -u Display Yuv instead of Lab\n"); +#endif fprintf(stderr," -V Show running average and std. devation from ref.\n"); #ifndef SALONEINSTLIB fprintf(stderr," -T Display correlated color temperatures, CRI and TLCI\n"); @@ -354,6 +357,7 @@ usage(char *diag, ...) { fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n"); fprintf(stderr," -Y A Use non-adaptive integration time mode (if available).\n"); fprintf(stderr," -Y l|L Test for i1Pro Lamp Drift (l), and remediate it (L)\n"); + fprintf(stderr," -Y a Use Averaging mode (if available).\n"); // fprintf(stderr," -Y U Test i1pro2 UV measurement mode\n"); #ifndef SALONEINSTLIB fprintf(stderr," -Y W:fname.sp Save white tile ref. spectrum to file\n"); @@ -389,8 +393,12 @@ int main(int argc, char *argv[]) { int refrmode = -1; /* -1 = default, 0 = non-refresh mode, 1 = refresh mode */ double refrate = 0.0; /* 0.0 = default, > 0.0 = override refresh rate */ int nadaptive = 0; /* Use non-apative mode if available */ + int averagemode = 0; /* Use averaging mode if available */ int doYxy= 0; /* Display Yxy instead of Lab */ int doLCh= 0; /* Display LCh instead of Lab */ +#ifndef SALONEINSTLIB + int doYuv= 0; /* Display Yuv instead of Lab */ +#endif int doCCT= 0; /* Display correlated color temperatures */ inst_mode mode = 0, smode = 0; /* Normal mode and saved readings mode */ inst_opt_type trigmode = inst_opt_unknown; /* Chosen trigger mode */ @@ -423,6 +431,7 @@ int main(int argc, char *argv[]) { icxIllumeType illum = icxIT_D50; /* Spectral defaults */ xspect cust_illum; /* Custom illumination spectrum */ icxObserverType obType = icxOT_default; + xspect custObserver[3]; /* If obType = icxOT_custom */ xspect sp; /* Last spectrum read */ xspect rsp; /* Reference spectrum */ xsp2cie *sp2cie = NULL; /* default conversion */ @@ -435,6 +444,9 @@ int main(int argc, char *argv[]) { double rLab[3] = { -10.0, 0, 0}; /* Reference Lab */ double Yxy[3] = { 0.0, 0, 0}; /* Yxy value */ double LCh[3] = { 0.0, 0, 0}; /* LCh value */ +#ifndef SALONEINSTLIB + double Yuv[3] = { 0.0, 0, 0}; /* Yuv value */ +#endif double refstats = 0; /* Print running avg & stddev against ref */ double rstat_n; /* Stats N */ double rstat_XYZ[3]; /* Stats sum of XYZ's */ @@ -616,6 +628,10 @@ int main(int argc, char *argv[]) { obType = icxOT_CIE_1931_2; } else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */ obType = icxOT_CIE_1964_10; + } else if (strcmp(na, "2012_2") == 0) { /* Latest 2 degree */ + obType = icxOT_CIE_2012_2; + } else if (strcmp(na, "2012_10") == 0) { /* Latest 10 degree */ + obType = icxOT_CIE_2012_10; #ifndef SALONEINSTLIB } else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */ obType = icxOT_Stiles_Burch_2; @@ -624,8 +640,11 @@ int main(int argc, char *argv[]) { } else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */ obType = icxOT_Shaw_Fairchild_2; #endif /* !SALONEINSTLIB */ - } else - usage("Spectral observer type '%s' not recognised",na); + } else { + obType = icxOT_custom; + if (read_cmf(custObserver, na) != 0) + usage(0,"Failed to read custom observer CMF from -Q file '%s'",na); + } /* Request transmission measurement */ } else if (argv[fa][1] == 't') { @@ -730,11 +749,25 @@ int main(int argc, char *argv[]) { } else if (argv[fa][1] == 'x') { doYxy = 1; doLCh = 0; +#ifndef SALONEINSTLIB + doYuv = 0; +#endif /* Show LCh */ } else if (argv[fa][1] == 'h') { doYxy = 0; doLCh = 1; +#ifndef SALONEINSTLIB + doYuv = 0; +#endif + +#ifndef SALONEINSTLIB + /* Show Yuv */ + } else if (argv[fa][1] == 'u') { + doYxy = 0; + doLCh = 0; + doYuv = 1; +#endif /* Compute running average and standard deviation from ref. */ /* Also turns off clamping */ @@ -792,6 +825,8 @@ int main(int argc, char *argv[]) { if (na[0] == 'A') { nadaptive = 1; + } else if (na[0] == 'a') { + averagemode = 1; } else if (na[0] == 'r') { refrmode = 1; } else if (na[0] == 'n') { @@ -936,8 +971,8 @@ int main(int argc, char *argv[]) { double remtime = 0.0; int cooltime = 30; - if (it->itype != instI1Pro - && it->itype != instI1Pro2) { + if (it->dtype != instI1Pro + && it->dtype != instI1Pro2) { printf("LampDrift is only applicable to i1Pro instrument"); } @@ -1289,6 +1324,18 @@ int main(int argc, char *argv[]) { } it->capabilities(it, &cap, &cap2, &cap3); + /* If requested, average several readings (i.e. JETI 1211) */ + if (averagemode) { + if (!IMODETST(cap3, inst3_average)) { + if (verb) + printf("Requested averaging mode and instrument doesn't support it (ignored)\n"); + averagemode = 0; + } else if ((rv = it->get_set_opt(it, inst_opt_set_averages, 10)) != inst_ok) { + printf("Setting no of averages to 10 failed with '%s' (%s) !!!\n", + it->inst_interp_error(it, rv), it->interp_error(it, rv)); + } + } + /* Apply Extra filter compensation */ if (filtername[0] != '\000') { if ((rv = it->comp_filter(it, filtername)) != inst_ok) { @@ -1356,7 +1403,7 @@ int main(int argc, char *argv[]) { it->del(it); return -1; } - if ((rv = it->get_set_opt(it, inst_opt_set_ccss_obs, obType, NULL)) != inst_ok) { + if ((rv = it->get_set_opt(it, inst_opt_set_ccss_obs, obType, custObserver)) != inst_ok) { printf("\nSetting CCS Observer failed with error :'%s' (%s)\n", it->inst_interp_error(it, rv), it->interp_error(it, rv)); cs->del(cs); @@ -1392,7 +1439,7 @@ int main(int argc, char *argv[]) { /* If non-standard observer wasn't set by a CCSS file above */ if (obType != icxOT_default && (cap2 & inst2_ccss) && ccssset == 0) { - if ((rv = it->get_set_opt(it, inst_opt_set_ccss_obs, obType, 0)) != inst_ok) { + if ((rv = it->get_set_opt(it, inst_opt_set_ccss_obs, obType, custObserver)) != inst_ok) { printf("\nSetting CCSS Observer failed with error :'%s' (%s)\n", it->inst_interp_error(it, rv), it->interp_error(it, rv)); it->del(it); @@ -1500,7 +1547,7 @@ int main(int argc, char *argv[]) { illum = icxIT_none; /* Create a spectral conversion object */ - if ((sp2cie = new_xsp2cie(illum, &cust_illum, obType, NULL, icSigXYZData, + if ((sp2cie = new_xsp2cie(illum, &cust_illum, obType, custObserver, icSigXYZData, refstats ? icxNoClamp : icxClamp)) == NULL) error("Creation of spectral conversion object failed"); @@ -1573,6 +1620,7 @@ int main(int argc, char *argv[]) { #ifndef SALONEINSTLIB double cct, vct, vdt; double cct_de, vct_de, vdt_de; + double cct_sn, vct_sn, vdt_sn; /* Sign: 1 + above, -1 = below */ #endif /* !SALONEINSTLIB */ int ch = '0'; /* Character */ int sufwa = 0; /* Setup for FWA compensation */ @@ -2087,6 +2135,9 @@ int main(int argc, char *argv[]) { if (ch == 'K' || ch == 'k') { /* Do a calibration */ inst_code ev; + /* Should we do a get_n_a_cals() first, so we can abort */ + /* if no calibrations are available ?? */ + printf("\nDoing a calibration\n"); /* save current location */ @@ -2265,7 +2316,7 @@ int main(int argc, char *argv[]) { /* Creat the base conversion object */ if (sp2cief[fidx] == NULL) { if ((sp2cief[fidx] = new_xsp2cie(illum, &cust_illum, obType, - NULL, icSigXYZData, refstats ? icxNoClamp : icxClamp)) == NULL) + custObserver, icSigXYZData, refstats ? icxNoClamp : icxClamp)) == NULL) error("Creation of spectral conversion object failed"); } @@ -2404,24 +2455,36 @@ int main(int argc, char *argv[]) { icmXYZNumber wp; double nxyz[3], axyz[3]; double lab[3], alab[3]; + double yxy[3], ayxy[3]; + /* Y normalized sample */ nxyz[0] = XYZ[0] / XYZ[1]; nxyz[2] = XYZ[2] / XYZ[1]; nxyz[1] = XYZ[1] / XYZ[1]; /* Compute CCT */ - if ((cct = icx_XYZ2ill_ct(axyz, icxIT_Ptemp, obType, NULL, XYZ, NULL, 0)) < 0) + if ((cct = icx_XYZ2ill_ct(axyz, icxIT_Ptemp, obType, custObserver, nxyz, NULL, 0)) < 0) error ("Got bad cct\n"); axyz[0] /= axyz[1]; axyz[2] /= axyz[1]; axyz[1] /= axyz[1]; - icmAry2XYZ(wp, axyz); - icmXYZ2Lab(&wp, lab, nxyz); - icmXYZ2Lab(&wp, alab, axyz); - cct_de = icmLabDE(lab, alab); + icmXYZ21960UCS(lab, nxyz); + icmXYZ21960UCS(alab, axyz); + cct_de = sqrt((lab[1] - alab[1]) * (lab[1] - alab[1]) + + (lab[2] - alab[2]) * (lab[2] - alab[2])); + + + cct_sn = 1.0; + icmXYZ2Yxy(yxy, nxyz); + icmXYZ2Yxy(ayxy, axyz); + /* Dot product of vector from aprox. locus curve "center" */ + /* xy 0.5, 0.25 with vector from */ + if ((yxy[1] - ayxy[1]) * (ayxy[1] - 0.5) + + (yxy[2] - ayxy[2]) * (ayxy[2] - 0.25) < 0.0) + cct_sn = -1.0; /* Compute VCT */ - if ((vct = icx_XYZ2ill_ct(axyz, icxIT_Ptemp, obType, NULL, XYZ, NULL, 1)) < 0) + if ((vct = icx_XYZ2ill_ct(axyz, icxIT_Ptemp, obType, custObserver, nxyz, NULL, 1)) < 0) error ("Got bad vct\n"); axyz[0] /= axyz[1]; axyz[2] /= axyz[1]; @@ -2429,10 +2492,17 @@ int main(int argc, char *argv[]) { icmAry2XYZ(wp, axyz); icmXYZ2Lab(&wp, lab, nxyz); icmXYZ2Lab(&wp, alab, axyz); - vct_de = icmLabDE(lab, alab); - + vct_de = icmCIE2K(lab, alab); + + vct_sn = 1.0; + icmXYZ2Yxy(yxy, nxyz); + icmXYZ2Yxy(ayxy, axyz); + if ((yxy[1] - ayxy[1]) * (ayxy[1] - 0.5) + + (yxy[2] - ayxy[2]) * (ayxy[2] - 0.25) < 0.0) + vct_sn = -1.0; + /* Compute VDT */ - if ((vdt = icx_XYZ2ill_ct(axyz, icxIT_Dtemp, obType, NULL, XYZ, NULL, 1)) < 0) + if ((vdt = icx_XYZ2ill_ct(axyz, icxIT_Dtemp, obType, custObserver, nxyz, NULL, 1)) < 0) error ("Got bad vct\n"); axyz[0] /= axyz[1]; axyz[2] /= axyz[1]; @@ -2440,7 +2510,14 @@ int main(int argc, char *argv[]) { icmAry2XYZ(wp, axyz); icmXYZ2Lab(&wp, lab, nxyz); icmXYZ2Lab(&wp, alab, axyz); - vdt_de = icmLabDE(lab, alab); + vdt_de = icmCIE2K(lab, alab); + + vdt_sn = 1.0; + icmXYZ2Yxy(yxy, nxyz); + icmXYZ2Yxy(ayxy, axyz); + if ((yxy[1] - ayxy[1]) * (ayxy[1] - 0.5) + + (yxy[2] - ayxy[2]) * (ayxy[2] - 0.25) < 0.0) + vdt_sn = -1.0; } /* Compute D50 Lab from XYZ */ @@ -2452,6 +2529,9 @@ int main(int argc, char *argv[]) { /* Compute LCh from Lab */ icmLab2LCh(LCh, Lab); + /* Compute D50 Yuv from XYZ */ + icmXYZ21976UCS(Yuv, XYZ); + #else /* SALONEINSTLIB */ /* Compute D50 Lab from XYZ */ XYZ2Lab(Lab, XYZ); @@ -2503,6 +2583,9 @@ int main(int argc, char *argv[]) { /* recompute LCh from Lab */ icmLab2LCh(LCh, Lab); + + /* recompute Yuv */ + icmXYZ21976UCS(Yuv, XYZ); #else /* SALONEINSTLIB */ else { @@ -2534,6 +2617,12 @@ int main(int argc, char *argv[]) { /* Print out the XYZ and LCh */ printf("\n Result is XYZ: %f %f %f, LCh: %f %f %f\n", XYZ[0], XYZ[1], XYZ[2], LCh[0], LCh[1], LCh[2]); +#ifndef SALONEINSTLIB + } else if (doYuv) { + /* Print out the XYZ and Yuv */ + printf("\n Result is XYZ: %f %f %f, Yuv: %f %f %f\n", + XYZ[0], XYZ[1], XYZ[2], Yuv[0], Yuv[1], Yuv[2]); +#endif } else { /* Print out the XYZ and Lab */ printf("\n Result is XYZ: %f %f %f, D50 Lab: %f %f %f\n", @@ -2588,15 +2677,15 @@ int main(int argc, char *argv[]) { log(XYZ[1]/2.5)/log(2.0)); } else { #ifndef SALONEINSTLIB - printf(" Ambient = %.1f Lux%s, CCT = %.0fK (Delta E %f)\n", + printf(" Ambient = %.1f Lux%s, CCT = %.0fK (Duv %.4f)\n", XYZ[1], ambient == 2 ? "-Seconds" : "", - cct, cct_de); + cct, cct_sn * cct_de); if (ambient != 2) printf(" Suggested EV @ ISO100 for %.1f Lux incident light = %.1f\n", XYZ[1], log(XYZ[1]/2.5)/log(2.0)); - printf(" Closest Planckian temperature = %.0fK (Delta E %f)\n",vct, vct_de); - printf(" Closest Daylight temperature = %.0fK (Delta E %f)\n",vdt, vdt_de); + printf(" Closest Planckian temperature = %.0fK (DE2K %.1f)\n",vct, vct_sn * vct_de); + printf(" Closest Daylight temperature = %.0fK (DE2K %.1f)\n",vdt, vdt_sn * vdt_de); #else /* SALONEINSTLIB */ printf(" Ambient = %.1f Lux%s\n", XYZ[1], ambient == 2 ? "-Seconds" : ""); @@ -2604,9 +2693,9 @@ int main(int argc, char *argv[]) { } #ifndef SALONEINSTLIB } else if (doCCT) { - printf(" CCT = %.0fK (Delta E %f)\n",cct, cct_de); - printf(" Closest Planckian temperature = %.0fK (Delta E %f)\n",vct, vct_de); - printf(" Closest Daylight temperature = %.0fK (Delta E %f)\n",vdt, vdt_de); + printf(" CCT = %.0fK (Duv %.4f)\n",cct, cct_sn * cct_de); + printf(" Closest Planckian temperature = %.0fK (DE2K %.1f)\n",vct, vct_sn * vct_de); + printf(" Closest Daylight temperature = %.0fK (DE2K %.1f)\n",vdt, vdt_sn * vdt_de); #endif } #ifndef SALONEINSTLIB @@ -2616,7 +2705,7 @@ int main(int argc, char *argv[]) { double cri; cri = icx_CIE1995_CRI(&invalid, RR, &sp); printf(" Color Rendering Index (Ra) = %.1f [ R9 = %.1f ]%s\n", - cri, RR[9-1], invalid ? " (Invalid)" : ""); + cri, RR[9-1], invalid ? " (Caution)" : ""); for (i = 0; i < 14; i++) { printf(" R%d%s = %.1f", i+1, i < 9 ? " " : "", RR[i]); if (i == 6) @@ -2628,7 +2717,7 @@ int main(int argc, char *argv[]) { int invalid = 0; double tlci; tlci = icx_EBU2012_TLCI(&invalid, &sp); - printf(" Television Lighting Consistency Index 2012 (Qa) = %.1f%s\n",tlci,invalid ? " (Invalid)" : ""); + printf(" Television Lighting Consistency Index 2012 (Qa) = %.1f%s\n",tlci,invalid ? " (Caution)" : ""); } #endif diff --git a/spectro/spyd2.c b/spectro/spyd2.c index 85a2d7f..28051f3 100644..100755 --- a/spectro/spyd2.c +++ b/spectro/spyd2.c @@ -95,6 +95,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -2677,7 +2678,7 @@ spyd2_download_pld( int i; int id; - if (p->itype == instSpyder1) + if (p->dtype == instSpyder1) id = 0; else id = 1; @@ -2748,7 +2749,7 @@ spyd4_load_cal(spyd2 *p) { for (;;) { /* So we can break */ - if ((no_paths = xdg_bds(NULL, &bin_paths, xdg_data, xdg_read, xdg_user, + if ((no_paths = xdg_bds(NULL, &bin_paths, xdg_data, xdg_read, xdg_user, xdg_none, "ArgyllCMS/spyd4cal.bin" XDG_FUDGE "color/spyd4cal.bin" )) < 1) break; @@ -2884,15 +2885,15 @@ spyd2_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { /* it needs icomuf_resetep_before_read to work at all, and */ /* gets retries anyway. So we use the libusb-win32 driver for it. */ #if defined(NT) - if (p->itype == instSpyder3) { + if (p->dtype == instSpyder3) { usbflags |= icomuf_resetep_before_read; /* The spyder USB is buggy ? */ } #endif /* On OS X the Spyder 2 can't close properly */ #if defined(UNIX_APPLE) /* OS X*/ - if (p->itype == instSpyder1 - || p->itype == instSpyder2) { + if (p->dtype == instSpyder1 + || p->dtype == instSpyder2) { usbflags |= icomuf_reset_before_close; /* The spyder 2 USB is buggy ? */ } #endif @@ -2901,8 +2902,8 @@ spyd2_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { #if defined(UNIX_X11) /* Linux*/ /* On Linux the Spyder 2 doesn't work reliably unless each */ /* read is preceeded by a reset endpoint. */ - if (p->itype == instSpyder1 - || p->itype == instSpyder2) { + if (p->dtype == instSpyder1 + || p->dtype == instSpyder2) { usbflags |= icomuf_resetep_before_read; /* The spyder USB is buggy ? */ } #endif @@ -2937,11 +2938,11 @@ spyd2_init_inst(inst *pp) { if (p->gotcoms == 0) /* Must establish coms before calling init */ return spyd2_interp_code((inst *)p, SPYD2_NO_COMS); - if (p->itype != instSpyder1 - && p->itype != instSpyder2 - && p->itype != instSpyder3 - && p->itype != instSpyder4 - && p->itype != instSpyder5) + if (p->dtype != instSpyder1 + && p->dtype != instSpyder2 + && p->dtype != instSpyder3 + && p->dtype != instSpyder4 + && p->dtype != instSpyder5) return spyd2_interp_code((inst *)p, SPYD2_UNKNOWN_MODEL); p->refrate = DEFRRATE; @@ -2950,9 +2951,9 @@ spyd2_init_inst(inst *pp) { p->prevrawinv = 0; /* prevraw is valid */ /* For Spyder 1 & 2, reset the hardware and wait for it to become ready. */ - if (p->itype != instSpyder3 - && p->itype != instSpyder4 - && p->itype != instSpyder5) { + if (p->dtype != instSpyder3 + && p->dtype != instSpyder4 + && p->dtype != instSpyder5) { /* Reset the instrument */ if ((ev = spyd2_reset(p)) != inst_ok) @@ -3038,7 +3039,7 @@ spyd2_init_inst(inst *pp) { a1logv(p->log, 1, "Instrument Type: %s\n" "Serial Number: %s\n" "Hardware version: 0x%02x%02x\n" - ,inst_name(p->itype) ,p->serno ,p->hwver,p->fbits); + ,inst_name(p->dtype) ,p->serno ,p->hwver,p->fbits); return inst_ok; } @@ -3504,9 +3505,9 @@ inst3_capability *pcap3) { /* We don't seem to have a way of detecting the lack */ /* of ambinent capability, short of doing a read */ /* and noticing the result is zero. */ - if (p->itype == instSpyder3 - || p->itype == instSpyder4 - || p->itype == instSpyder5) { + if (p->dtype == instSpyder3 + || p->dtype == instSpyder4 + || p->dtype == instSpyder5) { cap1 |= inst_mode_emis_ambient; } @@ -3518,9 +3519,9 @@ inst3_capability *pcap3) { | inst2_emis_refr_meas ; - if (p->itype == instSpyder3 - || p->itype == instSpyder4 - || p->itype == instSpyder5) { + if (p->dtype == instSpyder3 + || p->dtype == instSpyder4 + || p->dtype == instSpyder5) { cap2 |= inst2_disptype; cap2 |= inst2_has_leds; cap2 |= inst2_ambient_mono; @@ -3528,8 +3529,8 @@ inst3_capability *pcap3) { cap2 |= inst2_disptype; } - if (p->itype == instSpyder4 - || p->itype == instSpyder5) + if (p->dtype == instSpyder4 + || p->dtype == instSpyder5) cap2 |= inst2_ccss; /* Spyder4 & 5 has spectral sensivities */ if (pcap1 != NULL) @@ -3747,8 +3748,8 @@ static inst_disptypesel spyd4_disptypesel[8] = { static void set_base_disptype_list(spyd2 *p) { /* set the base display type list */ - if (p->itype == instSpyder4 - || p->itype == instSpyder5) { + if (p->dtype == instSpyder4 + || p->dtype == instSpyder5) { if (spyd4_nocals <= 1) { p->_dtlist = spyd4_disptypesel_1; } else { /* spyd4_nocals == 6 or 7, Spyder 4 or 5. */ @@ -3757,7 +3758,7 @@ static void set_base_disptype_list(spyd2 *p) { /* So use the spyder 4 list */ p->_dtlist = spyd4_disptypesel; } - } else if (p->itype == instSpyder3) { + } else if (p->dtype == instSpyder3) { p->_dtlist = spyd3_disptypesel; } else { p->_dtlist = spyd2_disptypesel; @@ -4079,7 +4080,7 @@ spyd2_get_set_opt(inst *pp, inst_opt_type m, ...) { } /* Constructor */ -extern spyd2 *new_spyd2(icoms *icom, instType itype) { +extern spyd2 *new_spyd2(icoms *icom, instType dtype) { spyd2 *p; if ((p = (spyd2 *)calloc(sizeof(spyd2),1)) == NULL) { a1loge(icom->log, 1, "new_spyd2: malloc failed!\n"); @@ -4109,11 +4110,11 @@ extern spyd2 *new_spyd2(icoms *icom, instType itype) { p->del = spyd2_del; p->icom = icom; - p->itype = itype; + p->dtype = dtype; /* Load manufacturers Spyder4 calibrations */ - if (itype == instSpyder4 - || itype == instSpyder5) { + if (dtype == instSpyder4 + || dtype == instSpyder5) { int rv; p->hwver = 7; /* Set preliminary version */ if ((rv = spyd4_load_cal(p)) != SPYD2_OK) @@ -4121,11 +4122,11 @@ extern spyd2 *new_spyd2(icoms *icom, instType itype) { if (spyd4_nocals < 1) a1logd(p->log, 1, "Spyder4 choice of calibrations not available\n"); } - if (itype == instSpyder3) { + if (dtype == instSpyder3) { p->hwver = 4; /* Set preliminary version */ } - if (itype == instSpyder1 // ???? - || itype == instSpyder2) { + if (dtype == instSpyder1 // ???? + || dtype == instSpyder2) { p->hwver = 3; /* Set preliminary version */ } @@ -4164,7 +4165,8 @@ int setup_spyd2(int id) { else p1 = "ArgyllCMS/spyd2PLD.bin" XDG_FUDGE "color/spyd2PLD.bin"; - if ((no_paths = xdg_bds(NULL, &bin_paths, xdg_data, xdg_read, xdg_user, p1)) < 1) { + if ((no_paths = xdg_bds(NULL, &bin_paths, xdg_data, xdg_read, xdg_user, xdg_none, + p1)) < 1) { a1logd(g_log, 1, "setup_spyd2: failed to find PLD file on path '%s'\n",p1); break; } diff --git a/spectro/spyd2.h b/spectro/spyd2.h index 318ed7c..318ed7c 100644..100755 --- a/spectro/spyd2.h +++ b/spectro/spyd2.h diff --git a/spectro/ss.c b/spectro/ss.c index 260df4a..4f95fdb 100644..100755 --- a/spectro/ss.c +++ b/spectro/ss.c @@ -76,6 +76,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" @@ -223,7 +224,7 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { ss_command(p, SH_TMO); if (ss_sub_1(p) == ss_AnsPFX) { /* Got comms */ - p->itype = instSpectroScan; /* Preliminary */ + p->dtype = instSpectroScan; /* Preliminary */ break; } @@ -233,7 +234,7 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { ss_command(p, SH_TMO); if (ss_sub_1(p) == ss_ParameterAnswer) { /* Got comms */ - p->itype = instSpectrolino; + p->dtype = instSpectrolino; break; } @@ -259,7 +260,7 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { a1logd(p->log, 4, "ss_init_coms: got basic communications\n"); /* Finalise the communications */ - if (p->itype == instSpectrolino) { + if (p->dtype == instSpectrolino) { if ((ev = so_do_MeasControlDownload(p, fcc1)) != inst_ok) return ev; @@ -326,7 +327,7 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { a1logd(p->log, 4, "ss_init_coms: establish communications\n"); /* See if we have a Spectroscan or SpectroscanT, and get other details */ - p->itype = instUnknown; + p->dtype = instUnknown; { char devn[19]; @@ -335,9 +336,9 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { if (ev == inst_ok) { a1logd(p->log, 5, "ss_init_coms: got device name '%s'\n",devn); if (strncmp(devn, "SpectroScanT",12) == 0) { - p->itype = instSpectroScanT; + p->dtype = instSpectroScanT; } else if (strncmp(devn, "SpectroScan",11) == 0) { - p->itype = instSpectroScan; + p->dtype = instSpectroScan; } } } @@ -363,8 +364,8 @@ ss_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) { || strncmp(devn, "Spectrolino",11) != 0) return inst_unknown_model; - if (p->itype == instUnknown) /* No SpectroScan */ - p->itype = instSpectrolino; + if (p->dtype == instUnknown) /* No SpectroScan */ + p->dtype = instSpectrolino; } } @@ -390,15 +391,15 @@ static void ss_determine_capabilities(ss *p) { | inst_mode_spectral ; - if (p->itype == instSpectrolino) { + if (p->dtype == instSpectrolino) { p->cap |= inst_mode_trans_spot; /* Support this manually using a light table */ } - if (p->itype == instSpectroScan - || p->itype == instSpectroScanT) /* Only in reflective mode */ + if (p->dtype == instSpectroScan + || p->dtype == instSpectroScanT) /* Only in reflective mode */ p->cap |= inst_mode_ref_xy; - if (p->itype == instSpectroScanT) { + if (p->dtype == instSpectroScanT) { p->cap |= inst_mode_trans_spot; } @@ -408,8 +409,8 @@ static void ss_determine_capabilities(ss *p) { | inst2_user_switch_trig ; - if (p->itype == instSpectroScan - || p->itype == instSpectroScanT) { + if (p->dtype == instSpectroScan + || p->dtype == instSpectroScanT) { /* These are not available in transmission mode */ if ((p->mode & inst_mode_illum_mask) != inst_mode_transmission) { p->cap2 |= inst2_xy_holdrel @@ -451,10 +452,10 @@ ss_init_inst(inst *pp) { } /* Reset the instrument to a known state */ - if (p->itype != instSpectrolino) { + if (p->dtype != instSpectrolino) { /* Initialise the device without resetting the baud rate */ - if (p->itype == instSpectroScanT) { + if (p->dtype == instSpectroScanT) { if ((rv = ss_do_SetTableMode(p, ss_tmt_Reflectance)) != inst_ok) return rv; } @@ -726,8 +727,8 @@ ipatch *vals) { /* Pointer to array of values */ if (!p->inited) return inst_no_init; - if (p->itype != instSpectroScan - && p->itype != instSpectroScanT) + if (p->dtype != instSpectroScan + && p->dtype != instSpectroScanT) return inst_unsupported; /* Move quickest in X direction to minimise noise, */ @@ -1044,7 +1045,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ break; } /* If SpectroScanT transmission, poll the enter key */ - if (p->itype == instSpectroScanT + if (p->dtype == instSpectroScanT && (p->mode & inst_mode_illum_mask) == inst_mode_transmission) { ss_sks sk; ss_ptt pt; @@ -1117,14 +1118,14 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ /* For the spectroscan, make sure the instrument is on line, */ /* since it may be off line to allow the user to position it. */ - if (p->itype != instSpectrolino && p->offline) { + if (p->dtype != instSpectrolino && p->offline) { if ((rv = p->xy_locate_end((inst *)p)) != inst_ok) return rv; } /* For reflection spot mode on a SpectroScan, lower the head. */ /* (A SpectroScanT in transmission will position automatically) */ - if (p->itype != instSpectrolino + if (p->dtype != instSpectrolino && (p->mode & inst_mode_illum_mask) != inst_mode_transmission) { if ((rv = ss_do_MoveDown(p)) != inst_ok) return rv; @@ -1139,7 +1140,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ /* For reflection spot mode on a SpectroScan, raise the head. */ /* (A SpectroScanT in transmission will position automatically) */ - if (p->itype != instSpectrolino + if (p->dtype != instSpectrolino && (p->mode & inst_mode_illum_mask) != inst_mode_transmission) { if ((rv = ss_do_MoveUp(p)) != inst_ok) return rv; @@ -1153,7 +1154,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */ /* Emulated spot transmission mode: */ if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission - && p->itype == instSpectrolino) { + && p->dtype == instSpectrolino) { ss_st rst; /* Return Spectrum Type (Reflectance/Density) */ ss_rvt rvf; /* Return Reference Valid Flag */ ss_aft af; /* Return filter being used (None/Pol/D65/UV/custom */ @@ -1376,7 +1377,7 @@ static inst_code ss_get_n_a_cals(inst *pp, inst_cal_type *pn_cals, inst_cal_type inst_cal_type a_cals = inst_calt_none; if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission) { - if (p->itype == instSpectrolino) { /* Emulated transmission */ + if (p->dtype == instSpectrolino) { /* Emulated transmission */ if (p->need_wd_cal && p->noinitcalib == 0) n_cals |= inst_calt_ref_white; a_cals |= inst_calt_ref_white; @@ -1464,7 +1465,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ p->filt = ss_aft_NoFilter; /* Need no filter for emission */ /* Set mode to reflection as a default for calibration */ - if (p->itype == instSpectroScanT) { + if (p->dtype == instSpectroScanT) { if ((rv = ss_do_SetTableMode(p, ss_tmt_Reflectance)) != inst_ok) return rv; } else { @@ -1484,7 +1485,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ if (p->noinitcalib == 0) { /* Make sure we're in a condition to do the calibration */ - if (p->itype == instSpectrolino + if (p->dtype == instSpectrolino && (*calc & inst_calc_cond_mask) != inst_calc_man_ref_white) { *calc = inst_calc_man_ref_white; a1logd(p->log, 3, "ss cal need cond. inst_calc_man_ref_white and haven't got it\n"); @@ -1496,7 +1497,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ a1logd(p->log, 3, "ss cal doing white reflective cal\n"); /* For SpectroScan, move to the white reference in slot 1 and lower */ - if (p->itype != instSpectrolino) { + if (p->dtype != instSpectrolino) { if ((rv = ss_do_MoveToWhiteRefPos(p, ss_wrpt_RefTile1)) != inst_ok) return rv; if ((rv = ss_do_MoveDown(p)) != inst_ok) @@ -1510,7 +1511,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ rv = inst_ok; /* For SpectroScan, raise */ - if (p->itype != instSpectrolino) { + if (p->dtype != instSpectrolino) { if ((rv = ss_do_MoveUp(p)) != inst_ok) return rv; } @@ -1541,7 +1542,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ /* Emission or spot transmission mode, dark calibration. */ if ((p->mode & inst_mode_illum_mask) == inst_mode_emission || ((p->mode & inst_mode_illum_mask) == inst_mode_transmission - && p->itype == instSpectrolino)) { + && p->dtype == instSpectrolino)) { a1logd(p->log, 3, "emmission/transmission dark calibration:\n"); /* Set emission mode */ if ((rv = so_do_MeasControlDownload(p, ss_ctt_EmissionMeas)) != inst_ok) @@ -1563,7 +1564,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ /* Restore the instrument to the desired mode */ /* SpectroScanT - Transmission mode, set transmission mode. */ if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission - && p->itype == instSpectroScanT) { + && p->dtype == instSpectroScanT) { if ((p->mode & inst_mode_illum_mask) == inst_mode_transmission) { if ((rv = ss_do_SetTableMode(p, ss_tmt_Transmission)) != inst_ok) @@ -1584,7 +1585,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ a1logd(p->log, 3, "ss cal need trans with calt = trans_white\n"); /* Emulated spot transmission using spectrolino */ - if ((*calt & inst_calt_trans_vwhite) && p->itype == instSpectrolino) { + if ((*calt & inst_calt_trans_vwhite) && p->dtype == instSpectrolino) { ss_st rst; /* Return Spectrum Type (Reflectance/Density) */ ss_rvt rvf; /* Return Reference Valid Flag */ ss_aft af; /* Return filter being used (None/Pol/D65/UV/custom */ @@ -1631,7 +1632,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */ a1logd(p->log, 3, "transmission lino cal done\n"); /* SpectroScanT */ - } else if ((*calt & inst_calt_trans_white) && p->itype != instSpectrolino) { + } else if ((*calt & inst_calt_trans_white) && p->dtype != instSpectrolino) { /* Hmm. Should we really return a message and resume somehow, */ /* rather than communicating directly with the user... */ @@ -2154,7 +2155,7 @@ ss_del(inst *pp) { ss *p = (ss *)pp; if (p->inited - && p->itype == instSpectroScanT + && p->dtype == instSpectroScanT && (p->mode & inst_mode_illum_mask) == inst_mode_transmission) { ss_do_SetDeviceOnline(p); ss_do_SetTableMode(p, ss_tmt_Reflectance); @@ -2175,7 +2176,7 @@ ss_del(inst *pp) { } /* Constructor */ -extern ss *new_ss(icoms *icom, instType itype) { +extern ss *new_ss(icoms *icom, instType dtype) { ss *p; if ((p = (ss *)calloc(sizeof(ss),1)) == NULL) { a1loge(icom->log, 1, "new_ss: malloc failed!\n"); @@ -2209,7 +2210,7 @@ extern ss *new_ss(icoms *icom, instType itype) { /* Init state */ p->icom = icom; - p->itype = itype; + p->dtype = dtype; p->cap = inst_mode_none; /* Unknown until initialised */ p->mode = inst_mode_none; /* Not in a known mode yet */ p->nextmode = inst_mode_none; /* Not in a known mode yet */ diff --git a/spectro/ss.h b/spectro/ss.h index bc816e7..bc816e7 100644..100755 --- a/spectro/ss.h +++ b/spectro/ss.h diff --git a/spectro/ss_imp.c b/spectro/ss_imp.c index 05f0602..0de14ea 100644..100755 --- a/spectro/ss_imp.c +++ b/spectro/ss_imp.c @@ -50,6 +50,7 @@ #include "sa_config.h" #include "numsup.h" #endif /* SALONEINSTLIB */ +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" diff --git a/spectro/ss_imp.h b/spectro/ss_imp.h index ccd9ce3..ccd9ce3 100644..100755 --- a/spectro/ss_imp.h +++ b/spectro/ss_imp.h diff --git a/spectro/synthcal.c b/spectro/synthcal.c index 14471f6..14471f6 100644..100755 --- a/spectro/synthcal.c +++ b/spectro/synthcal.c diff --git a/spectro/synthread.c b/spectro/synthread.c index 3a23c31..3a23c31 100644..100755 --- a/spectro/synthread.c +++ b/spectro/synthread.c diff --git a/spectro/usbio.c b/spectro/usbio.c index fca997d..efd0dc8 100644..100755 --- a/spectro/usbio.c +++ b/spectro/usbio.c @@ -33,6 +33,7 @@ #include "sa_config.h" #endif #include "numsup.h" +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" diff --git a/spectro/usbio.h b/spectro/usbio.h index 2a01ea3..2a01ea3 100644..100755 --- a/spectro/usbio.h +++ b/spectro/usbio.h diff --git a/spectro/usbio_bsd.c b/spectro/usbio_bsd.c index 4b3e038..4b3e038 100644..100755 --- a/spectro/usbio_bsd.c +++ b/spectro/usbio_bsd.c diff --git a/spectro/usbio_lx.c b/spectro/usbio_lx.c index 6edcb29..135f8eb 100644..100755 --- a/spectro/usbio_lx.c +++ b/spectro/usbio_lx.c @@ -22,6 +22,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> +#include <sys/time.h> #include <linux/usbdevice_fs.h> /* select() defined, but not poll(), so emulate poll() */ @@ -785,6 +786,9 @@ static int icoms_usb_transaction( in_usb_rw++; a1logd(p->log, 8, "icoms_usb_transaction: req type 0x%x ep 0x%x size %d to %d\n",ttype,endpoint,length, timeout); + if (transferred != NULL) + *transferred = 0; + if (!p->usbd->running) { in_usb_rw--; a1logv(p->log, 1, "icoms_usb_transaction: reaper thread is not running\n"); diff --git a/spectro/usbio_nt.c b/spectro/usbio_nt.c index 34426fd..f3748bb 100644..100755 --- a/spectro/usbio_nt.c +++ b/spectro/usbio_nt.c @@ -589,6 +589,9 @@ static int icoms_usb_transaction( a1logd(p->log, 8, "icoms_usb_transaction: req type 0x%x ep 0x%x size %d\n",ttype,endpoint,length); + if (transferred != NULL) + *transferred = 0; + if (ttype != icom_usb_trantype_interrutpt && ttype != icom_usb_trantype_bulk) { /* We only handle interrupt & bulk, not control */ @@ -692,6 +695,9 @@ int timeout) { a1logd(p->log, 8, "icoms_usb_control_msg: type 0x%x req 0x%x size %d\n",requesttype,request,size); + if (transferred != NULL) + *transferred = 0; + memset(&req, 0, sizeof(libusb_request)); req.timeout = timeout; diff --git a/spectro/usbio_ox.c b/spectro/usbio_ox.c index 2b09955..3923d6d 100644..100755 --- a/spectro/usbio_ox.c +++ b/spectro/usbio_ox.c @@ -457,12 +457,20 @@ char **pnames /* List of process names to try and kill before opening */ (*pluginref)->Stop(pluginref); IODestroyPlugInInterface(pluginref); // this stops IOServices though ?? + /* This can fail if the device has multiple interfaces, and */ + /* one of them is grabbed by a system interface (i.e. debug serial port) */ + /* So soft fail, and rely on ep use to fail for invalid interface */ if ((rv = (*(p->usbd->interfaces[i]))->USBInterfaceOpen( p->usbd->interfaces[i])) != kIOReturnSuccess) { - a1loge(p->log, rv, "usb_open_port: USBInterfaceOpen failed with 0x%x\n",rv); +#ifdef NEVER + a1loge(p->log, rv, "usb_open_port: USBInterfaceOpen %d failed with 0x%x\n",i, rv); IOObjectRelease(ioit); cleanup_device(p); return ICOM_SYS; +#else + a1logw(p->log, "usb_open_port: USBInterfaceOpen %d failed with 0x%x\n",i,rv); + continue; +#endif } /* Get the end point details, and set reference to pipe no and interfece ix */ @@ -580,6 +588,9 @@ static int icoms_usb_transaction( a1logd(p->log, 8, "icoms_usb_transaction: req type 0x%x ep 0x%x size %d\n",ttype,endpoint,length); + if (transferred != NULL) + *transferred = 0; + if (ttype != icom_usb_trantype_interrutpt && ttype != icom_usb_trantype_bulk) { /* We only handle interrupt & bulk, not control */ diff --git a/spectro/vinflate.c b/spectro/vinflate.c index 847fa28..847fa28 100644..100755 --- a/spectro/vinflate.c +++ b/spectro/vinflate.c diff --git a/spectro/vtpglut.c b/spectro/vtpglut.c new file mode 100755 index 0000000..2308466 --- /dev/null +++ b/spectro/vtpglut.c @@ -0,0 +1,570 @@ + +/* Abstract Video Test Patch Generator and/or 3dLUT class implemenation */ + +/* + * 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 <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifndef SALONEINSTLIB +#include "copyright.h" +#include "aconfig.h" +#else +#include "sa_config.h" +#endif /* !SALONEINSTLIB */ +#include "numsup.h" +#include "cgats.h" +#include "xspect.h" +#include "conv.h" + +#include "insttypes.h" +#include "icoms.h" +#include "vtpglut.h" +#include "rspec.h" +#include "vtpgluttypes.h" +#include "sort.h" + +icom_type dev_category(instType itype); + +/* --------------------------------------------------------- */ + +#if defined(ENABLE_FAST_SERIAL) +extern devType fast_ser_dev_type(icoms *p, int tryhard, + inst_code (*uicallback)(void *cntx, inst_ui_purp purp), void *cntx); +# if defined(ENABLE_SERIAL) +static devType ser_vtpglut_type(icoms *p, + vtpglut_code (*uicallback)(void *cntx, vtpglut_ui_purp purp), void *cntx); + +/* Translate vtpglut uicallback into inst callback */ +typedef struct { + void *cntx; + vtpglut_code (*uicallback)(void *cntx, vtpglut_ui_purp purp); +} vtpglut_callback_cntx; + +static inst_code ser_uicallback(void *cntx, inst_ui_purp purp) { + vtpglut_callback_cntx *p = (vtpglut_callback_cntx *)cntx; + vtpglut_ui_purp ser_purp; + + if (purp == vtpglut_negcoms) + ser_purp = inst_negcoms; + else + return inst_internal_error; + return p->uicallback(p->cntx, ser_purp); +} + +# endif /* ENABLE_SERIAL */ +#endif /* ENABLE_FAST_SERIAL */ + + +/* ------------------------------------ */ +/* Default methods for instrument class */ + +/* Establish communications at the indicated baud rate. */ +/* Timout in to seconds, and return non-zero error code */ +static vtpglut_code init_coms( +vtpglut *p) { /* Timeout */ + return vtpglut_unsupported; +} + +/* Initialise or re-initialise the INST */ +/* return non-zero on an error, with inst error code */ +static vtpglut_code init_vtpglut( +vtpglut *p) { + return vtpglut_unsupported; +} + +/* Return the device type */ +static devType get_dtype(vtpglut *p) { + if (p != NULL) + return p->dtype; + return devUnknown; +} + +/* Return the device serial number. */ +/* (This will be an empty string if there is no serial no) */ +static char *get_serial_no(vtpglut *p) { + return ""; +} + +/* Return the device mode/capabilities */ +static void capabilities(vtpglut *p, vtpglut_mode *cap1, + vtpglut_capability *cap2) { + if (cap1 != NULL) + *cap1 = vtpglut_mode_none; + if (cap2 != NULL) + *cap2 = vtpglut2_none; +} + +/* Check the device mode */ +static vtpglut_code check_mode( +vtpglut *p, +vtpglut_mode m) { /* Requested mode */ + return vtpglut_unsupported; +} + +/* Set the device mode */ +static vtpglut_code set_mode( +vtpglut *p, +vtpglut_mode m) { /* Requested mode */ + return vtpglut_unsupported; +} + +/* Get a status or set or get an option (default implementation) */ +vtpglut_code vtpglut_get_set_opt_def( +vtpglut *p, +vtpglut_opt_type m, /* Requested option type */ +va_list args) { /* Option parameters */ + return vtpglut_unsupported; +} + +/* Get a status or set or get an option */ +static vtpglut_code get_set_opt( +vtpglut *p, +vtpglut_opt_type m, /* Requested status type */ +...) { /* Status parameters */ + vtpglut_code rv; + va_list args; + + va_start(args, m); + rv = vtpglut_get_set_opt_def(p, m, args); /* Call the above */ + va_end(args); + + return rv; +} + +/* Supply a user interaction callback function. */ +static void set_uicallback( +vtpglut *pp, +vtpglut_code (*uicallback)(void *cntx, vtpglut_ui_purp purp), +void *cntx) { + pp->uicallback = uicallback; + pp->uic_cntx = cntx; +} + +/* Supply an asynchronous event callback function. */ +static void set_event_callback( +vtpglut *pp, +void (*eventcallback)(void *cntx, vtpglut_event_type event), +void *cntx) { + pp->eventcallback = eventcallback; + pp->event_cntx = cntx; +} + +/* Generic inst error codes interpretation */ +static char *vtpglut_interp_error(vtpglut *p, vtpglut_code ec) { + switch(ec & vtpglut_mask) { + case vtpglut_ok: + return "No error"; + case vtpglut_notify: + return "Notification"; + case vtpglut_warning: + return "Warning"; + case vtpglut_no_coms: + return "Internal error - communications needed but not established"; + case vtpglut_no_init: + return "Internal error - initialisation needed but not done"; + case vtpglut_unsupported: + return "Unsupported function"; + case vtpglut_internal_error: + return "Internal software error"; + case vtpglut_coms_fail: + return "Communications failure"; + case vtpglut_unknown_model: + return "Not expected device model"; + case vtpglut_protocol_error: + return "Communication protocol breakdown"; + case vtpglut_user_abort: + return "User hit Abort Key"; + case vtpglut_user_trig: + return "User hit Trigger Key"; + case vtpglut_unexpected_reply: + return "Unexpected Reply"; + case vtpglut_wrong_setup: + return "Wrong or conflicting setup"; + case vtpglut_hardware_fail: + return "Hardware Failure"; + case vtpglut_system_error: + return "Operating System Error"; + case vtpglut_bad_parameter: + return "Bad Parameter Value"; + case vtpglut_other_error: + return "Non-specific error"; + } + return "Unknown inst error code"; +} + +/* Instrument specific error codes interpretation */ +static char *interp_error(vtpglut *p, int ec) { + return "interp_error is uninplemented in base class!"; +} + +/* Return the last serial communication error code */ +/* (This is used for deciding fallback/retry strategies) */ +static int last_scomerr(vtpglut *p) { + return p->icom->lserr; +} + +/* ---------------------------------------------- */ + +/* Delete things set/done by new_vtpglut() */ +static vtpglut_code virtual_del(vtpglut *p) { + +#if defined(UNIX_APPLE) + osx_latencycritical_end(); +#endif + + return vtpglut_ok; +} + + +/* Virtual constructor. */ +/* Return NULL for unknown instrument, */ +/* or serial instrument if nocoms == 0. */ +extern vtpglut *new_vtpglut( +icompath *path, /* Device path to instrument */ +int nocoms, /* Don't open if communications are needed to establish inst type */ +a1log *log, /* log to use */ +vtpglut_code (*uicallback)(void *cntx, vtpglut_ui_purp purp), /* optional uicallback for abort */ +void *cntx /* Context for callback */ +) { + devType itype = devUnknown; /* Actual type */ + icoms *icom; + vtpglut *p = NULL; + + if (path == NULL) { + a1logd(log, 2, "new_vtpglut: got NULL path\n"); + return NULL; + } + + a1logd(log, 2, "new_vtpglut: called with path '%s' type '%s'\n",path->name,inst_sname(path->itype)); + + if ((icom = new_icoms(path, log)) == NULL) { + a1logd(log, 2, "new_vtpglut: new_icoms failed to open it\n"); + return NULL; + } + + + + /* Set device type from USB port, if not specified */ + itype = icom->itype; /* Instrument type if its known from usb/hid */ + +#if defined(ENABLE_FAST_SERIAL) + if (itype == instUnknown && !nocoms && (icom->dctype & icomt_fastserial)) { + vtpglut_callback_cntx wcntx; + + /* Wrap vtpglut callback in inst callback */ + wcntx.cntx = cntx; + wcntx.uicallback = uicallback; + + itype = fast_ser_dev_type(icom, 1, ser_uicallback, &wcntx); /* Else type from serial */ + icom->dctype = (icom->dctype & ~icomt_cat_mask) | dev_category(itype); + a1logd(log, 8, "new_vtpglut: fast set '%s' dctype 0x%x\n",icom->name,icom->dctype); + } +#endif /* ENABLE_FAST_SERIAL */ + +#if defined(ENABLE_SERIAL) + if (itype == instUnknown && !nocoms) { + itype = ser_vtpglut_type(icom, uicallback, cntx); /* Else type from serial */ + icom->dctype = (icom->dctype & ~icomt_cat_mask) | dev_category(itype); + a1logd(log, 8, "new_vtpglut: set '%s' dctype 0x%x\n",icom->name,icom->dctype); + } +#endif /* ENABLE_SERIAL */ + + +#ifdef ENABLE_SERIAL +// if (itype == devRadiance) +// p = (vtpglut *)new_radiance(icom, itype); +#endif /* ENABLE_SERIAL */ + +#ifdef ENABLE_USB +// if (itype == instXXXX) +// p = (vtpglut *)new_XXXX(icom, itype); +#endif /* ENABLE_USB */ + + + /* Nothing matched */ + if (p == NULL) { + a1logd(log, 2, "new_vtpglut: device type not recognised\n"); + icom->del(icom); + return NULL; + } + + p->vdel = virtual_del; + + /* Add default methods if constructor did not supply them */ + if (p->init_coms == NULL) + p->init_coms = init_coms; + if (p->init_vtpglut == NULL) + p->init_vtpglut = init_vtpglut; + if (p->get_dtype == NULL) + p->get_dtype = get_dtype; + if (p->get_serial_no == NULL) + p->get_serial_no = get_serial_no; + if (p->capabilities == NULL) + p->capabilities = capabilities; + if (p->check_mode == NULL) + p->check_mode = check_mode; + if (p->set_mode == NULL) + p->set_mode = set_mode; + if (p->get_set_opt == NULL) + p->get_set_opt = get_set_opt; + if (p->set_uicallback == NULL) + p->set_uicallback = set_uicallback; + if (p->set_event_callback == NULL) + p->set_event_callback = set_event_callback; + if (p->vtpglut_interp_error == NULL) + p->vtpglut_interp_error = vtpglut_interp_error; + if (p->interp_error == NULL) + p->interp_error = interp_error; + if (p->last_scomerr == NULL) + p->last_scomerr = last_scomerr; + + /* Set the provided user interaction callback */ + p->set_uicallback(p, uicallback, cntx); + +#if defined(UNIX_APPLE) + osx_latencycritical_start(); +#endif + + return p; +} + +/* ============================================================= */ +/* Detect serial device */ + +#ifdef ENABLE_SERIAL +static void hex2bin(char *buf, int len); + +/* Heuristicly determine the device type for */ +/* a serial connection, and devUnknown if not serial. */ +/* Set it in icoms and also return it. */ +static devType ser_vtpglut_type( + icoms *p, + vtpglut_code (*uicallback)(void *cntx, vtpglut_ui_purp purp), /* optional uicallback */ + void *cntx /* Context for callback */ +) { + devType rv = instUnknown; +#define BUFSZ (128 + 10) + char buf[BUFSZ]; + baud_rate brt[] = { baud_9600, baud_57600, baud_115200, baud_230400, baud_nc }; + unsigned int etime; + unsigned int bi, i; + int se, len, bread; + int lumagen = 0, lgchsum = 0; + +#ifdef ENABLE_USB + if (p->usbd != NULL || p->hidd != NULL) + return p->itype; +#endif /* ENABLE_USB */ + + bi = 0; + + /* The tick to give up on */ + etime = msec_time() + (long)(20.0 * 1000.0 + 0.5); + + a1logd(p->log, 1, "ser_vtpglut_type: Trying different baud rates (%u msec to go)\n",etime - msec_time()); + + /* Until we time out, find the correct baud rate */ + for (i = bi; msec_time() < etime; i++) { + lgchsum = 0; + + if (brt[i] == baud_nc) + i = 0; + if ((se = p->set_ser_port(p, fc_None, brt[i], parity_none, + stop_1, length_8)) != ICOM_OK) { + a1logd(p->log, 5, "ser_vtpglut_type: set_ser_port failed with 0x%x\n",se); + return instUnknown; /* Give up */ + } + + a1logd(p->log, 5, "Trying %s baud\n",baud_rate_to_str(brt[i])); + bread = 0; + + /* If Lumagen baud rate */ + if (brt[i] == baud_9600 + || brt[i] == baud_57600 + || brt[i] == baud_115200 + || brt[i] == baud_230400) { + + /* Try a spectrolino/spectroscan command first, so as not to upset it, */ + /* but do first character only and see if there is an echo */ + p->write_read_ex(p, ";", 1, buf, BUFSZ-1, &bread, "\r", 1, 0.2, 1); + if (bread == 1 && buf[0] == ';') + goto check_lumagen; /* It may be a Lumagen, so skip it. */ + + /* Send the rest of the spectrolino command */ + p->write_read_ex(p, "D024\r\n", 0, buf, BUFSZ-1, &bread, "\r", 1, 0.5, 1); + + + if (bread == 0) { + char *bp; + a1logd(p->log, 5, "ser_vtpglut_type: Spectrolino command returned nothing\n"); + + /* It could be a Lumagen Radiance with echo off, */ + /* so poke it and see if it responds. */ + /* (Unfortunately the Lumagen delimeters modes aren't */ + /* backwards compatible, so we may have to poke it twice...) */ + + /* Send "X" first, to get it out of menu mode ? */ + p->write_read_ex(p, "X", 1, buf, BUFSZ, NULL, "\n", 1, 0.1, 1); // Menu off + + a1logd(p->log, 5, "ser_vtpglut_type: Checking for Lumagen Radiance\n"); + p->write_read_ex(p, "#ZQS00\r", 0, buf, BUFSZ, &bread, "\n", 1, 0.5, 1); + if (bread == 0) { + p->write_read_ex(p, "#0ZQS008E\r", 0, buf, BUFSZ, &bread, "\n", 1, 0.5, 1); + lgchsum = 1; + } + + if (bread > 0 + && (bp = strrchr(buf, '!')) != NULL + && strlen(bp) >= 4 + && strncmp(bp,"!S00",4) == 0) { + goto check_lumagen; + } + + /* Nope - look for something at a different baud rate */ + goto continue_looking; + } + buf[bread] = '\000'; + len = strlen(buf); + + /* Is this a Lumagen Radiance with echo on, it responds with ";D024..." */ + if ((len >= 4 && strncmp(buf, ";D024", 4) == 0) + || (len >= 4 && strncmp(buf, "!N\n\r", 4) == 0)) { + char *bp; + + check_lumagen:; + + /* Get the Lumagen device information */ + p->write_read_ex(p, lgchsum ? "#0ZQS018F\r" : "#ZQS01\r", + 0, buf, BUFSZ, &bread, "\n", 1, 0.5, 1); + + /* Might have echo with checksum, so lgchsum not set correctly */ + if (!lgchsum && bread > 0 && strstr(buf, "!N") != NULL) { + p->write_read_ex(p, "#0ZQS018F\r", 0, buf, BUFSZ, &bread, "\n", 1, 0.5, 1); + if (bread >= 11 && strncmp(buf, "#0ZQS018F!Y", 11) == 0) + lgchsum = 1; + } + + /* returns something like "ZQS01!S01,Radiance2020,030115,1016,001309\r\m" */ + if ((bp = strrchr(buf, '!')) != NULL && strlen(bp) >= 13) { + if (strncmp(bp,"!S01,Radiance",13) == 0) { + a1logd(p->log, 5, "ser_vtpglut_type: Found Lumagen Radiance\n"); + lumagen = 1; + break; + } + } + a1logd(p->log, 5, "ser_vtpglut_type: Not Lumagen Radiance\n"); + goto continue_looking; + } + } /* Possibly Lumagen */ + + continue_looking:; + + /* Check for user abort */ + if (uicallback != NULL) { + vtpglut_code ev; + if ((ev = uicallback(cntx, vtpglut_negcoms)) == vtpglut_user_abort) { + a1logd(p->log, 5, "ser_vtpglut_type: User aborted\n"); + return instUnknown; + } + } + } /* next baud */ + + if (rv == instUnknown + && lumagen == 0 + && msec_time() >= etime) { /* We haven't established comms */ + a1logd(p->log, 5, "ser_vtpglut_type: Failed to establish coms\n"); + return instUnknown; + } + + a1logd(p->log, 5, "ser_vtpglut_type: Got coms with device\n"); + + if (lumagen) { + char *bp; + + /* Get the Lumagen device information */ + if ((se = p->write_read_ex(p, "ZQS01", 0, buf, BUFSZ, NULL, "\n", 1, 2.5, 1)) != 0) + return instUnknown; + + /* returns something like "ZQS01!S01,Radiance2020,030115,1016,001309\r\m" */ + if ((bp = strstr(buf, "!")) != NULL && strlen(bp) >= 13) { + if (strncmp(bp,"!S01,Radiance",13) == 0) { + rv = devRadiance; + } + } + } + + a1logd(p->log, 5, "ser_vtpglut_type: Device type is '%s'\n", inst_name(rv)); + + p->close_port(p); /* Or should we leave it open ?? */ + + p->itype = rv; + + return rv; +} +#undef BUFSZ + +#endif /* ENABLE_SERIAL */ + +#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL) + +/* Convert an ASCII Hex character to an integer. */ +static int h2b(char c) { + if (c >= '0' && c <= '9') + return (c-(int)'0'); + if (c >= 'A' && c <= 'F') + return (10 + c-(int)'A'); + if (c >= 'a' && c <= 'f') + return (10 + c-(int)'a'); + return 0; +} + +/* Convert a Hex encoded buffer into binary. */ +/* len is number of bytes out */ +static void hex2bin(char *buf, int len) { + int i; + + for (i = 0; i < len; i++) { + buf[i] = (char)((h2b(buf[2 * i + 0]) << 4) + | (h2b(buf[2 * i + 1]) << 0)); + } +} + +#endif /* ENABLE_SERIAL */ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spectro/vtpglut.h b/spectro/vtpglut.h new file mode 100755 index 0000000..c461887 --- /dev/null +++ b/spectro/vtpglut.h @@ -0,0 +1,243 @@ + +#ifndef VTPGLUT_H + +/* + * v3dlut/vtpg API definition. + * + * Abstract base class for common color Video Test Pattern Generator interface + * and Video 3DLut devices. + */ + +/* + * Argyll Color Correction System + * + * Author: Graeme W. Gill + * Date: 15/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 "dev.h" /* Device base class */ +#include "insttypes.h" /* libinst Includes this functionality */ +#include "icoms.h" /* libinst Includes this functionality */ +#include "conv.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* ------------------------------------------------- */ +/* aprox. debug level guide: + + 1,2 Applications, internal errors + 2,3 High level instrument drivers + 4,5 High level instrument communications + 6,7 High level serial/USB communications + 8,9 Low level serial/USB communications + +*/ + +/* ---------------------------------------- */ +/* Device interface abstract base class. */ + +/* This is used for all device types except color instruments */ + +/* Abstract return codes in ms 8bits. */ +/* Device dependant codes in ls 16 bits. */ +/* Note :- update vtpglut_interp_error() in other.c if anything here is changed. */ +/* and also check all the device specific XXX_interp_code() routines too. */ +typedef enum { + vtpglut_ok = 0x000000, + vtpglut_notify = 0x010000, /* A Notification */ + vtpglut_warning = 0x020000, /* A Warning */ + vtpglut_no_coms = 0x030000, /* init_coms() hasn't been called yet */ + vtpglut_no_init = 0x040000, /* init_dev() hasn't been called yet */ + vtpglut_unsupported = 0x050000, /* Unsupported function */ + vtpglut_internal_error = 0x060000, /* Internal software error */ + vtpglut_coms_fail = 0x070000, /* Communication failure */ + vtpglut_unknown_model = 0x080000, /* Not the expected device */ + vtpglut_protocol_error = 0x090000, /* Read or Write protocol error */ + vtpglut_user_abort = 0x0A0000, /* User hit escape */ + vtpglut_user_trig = 0x0C0000, /* User hit trigger key */ + vtpglut_unexpected_reply = 0x140000, /* Unexpected Reply */ + vtpglut_wrong_setup = 0x150000, /* Setup is wrong or conflicting */ + vtpglut_hardware_fail = 0x160000, /* Hardware failure */ + vtpglut_system_error = 0x170000, /* System call (ie malloc) fail */ + vtpglut_bad_parameter = 0x180000, /* Bad parameter value */ + vtpglut_other_error = 0x190000, /* Some other error */ + vtpglut_mask = 0xff0000, /* vtpglut_code mask value */ + vtpglut_dmask = 0x00ffff /* device specific mask value */ +} vtpglut_code; + +/* Device capabilities & modes */ +/* Note that due to the binary combinations, capabilities is not definititive */ +/* as to valid modes. check_mode() is definitive. */ +/* #defines are for saving modes in a version independent way. */ +/* Note :- update vtpglut_mode_sym[] table in vtpglut.c if anything here is changed. */ +typedef enum { + vtpglut_mode_none = 0x00000000, /* No capability/mode */ +} vtpglut_mode; + +typedef enum { + vtpglut2_none = 0x00000000, /* No capability */ +} vtpglut_capability; + + +/* Device options for get_set_opt() */ +typedef enum { + vtpglut_opt_unknown = 0x0000, /* Option not specified */ +} vtpglut_opt_type; + +/* User interaction callback (uicallback()) function purpose */ +/* (Make sure vtpglut.c inst_code ser_uicallbac() is updated if this changes. */ +typedef enum { + vtpglut_negcoms /* Negotiating communications - can abort */ +} vtpglut_ui_purp; + +/* Asynchronous event callback type */ +typedef enum { + inst_event_none /* (Placeholder) */ +} vtpglut_event_type; + +/* ---------------------------------------- */ +/* Device interface abstract base class */ + +# define EXTRA_VTPGLUT_OBJ + +/* vtpg/v3dlut interface base object */ +/* Note that some methods work after creation, while many */ +/* will return an error if communications hasn't been established and */ +/* the device initialised. Some may change their response before and */ +/* after initialisation. */ +#define VTPGLUT_OBJ_BASE \ + \ + DEV_OBJ_BASE \ + \ + EXTRA_VTPGLUT_OBJ \ + \ + vtpglut_code (*uicallback)(void *cntx, vtpglut_ui_purp purp); \ + void *uic_cntx; /* User interaction callback function */ \ + void (*eventcallback)(void *cntx, vtpglut_event_type event); \ + void *event_cntx; /* Asynchronous event callback function */ \ + \ + /* Virtual delete. Cleans up things done by new_vtpglut(). */ \ + vtpglut_code (*vdel)( \ + struct _vtpglut *p); \ + \ + /* Establish communications at the indicated baud rate. */ \ + /* (Serial parameters are ignored for USB/Network device) */ \ + /* Timout in to seconds, and return non-zero error code */ \ + vtpglut_code (*init_coms)( \ + struct _vtpglut *p); \ + \ + /* Initialise or re-initialise the vtpglut. */ \ + /* return non-zero on an error, with dev error code */ \ + vtpglut_code (*init_vtpglut)( \ + struct _vtpglut *p); \ + \ + /* Return the device type */ \ + /* (this could concievably change after init_vtpglut()) */ \ + /* Can be called before init */ \ + devType (*get_dtype)( \ + struct _vtpglut *p); \ + \ + /* Return the device serial number. */ \ + /* (This will be an empty string if there is no serial no) */ \ + char *(*get_serial_no)( \ + struct _vtpglut *p); \ + \ + /* Return the avilable devices modes and capabilities. */ \ + /* Can be called before init, but may be different to */ \ + /* what's returned after initilisation. */ \ + /* Note that these may change with the mode. */ \ + /* Arguments may be NULL */ \ + void (*capabilities)(struct _vtpglut *p, \ + vtpglut_mode *cap1, \ + vtpglut_capability *cap2); \ + \ + /* Check that the particular device measurement mode is valid, */ \ + /* since it's not possible to be 100% sure from capabilities */ \ + vtpglut_code (*check_mode)( \ + struct _vtpglut *p, \ + vtpglut_mode m); /* Requested mode */ \ + \ + /* Set the device mode */ \ + /* Note that this may change the capabilities. */ \ + vtpglut_code (*set_mode)( \ + struct _vtpglut *p, \ + vtpglut_mode m); /* Requested mode */ \ + \ + /* Get a status or get or set an option */ \ + /* option state. */ \ + /* Some options can be set before init */ \ + /* See vtpglut_opt_type typedef for list of mode types */ \ + vtpglut_code (*get_set_opt)( \ + struct _vtpglut *p, \ + vtpglut_opt_type m, /* Requested option mode */ \ + ...); /* Option parameters */ \ + \ + /* Supply a user interaction callback function. \ + * (Nothing currentlt defined) \ + * \ + * NULL can be set to disable the callback. \ + */ \ + void (*set_uicallback)(struct _vtpglut *p, \ + vtpglut_code (*uicallback)(void *cntx, vtpglut_ui_purp purp), \ + void *cntx); \ + \ + /* Supply an aynchronous event callback function. \ + * This is called from a different thread with the following possible events: \ + * \ + * inst_event_XXX: (placeholder) \ + * \ + * NULL can be set to disable the callback. \ + */ \ + void (*set_event_callback)(struct _vtpglut *p, \ + void (*eventcallback)(void *cntx, vtpglut_event_type event), \ + void *cntx); \ + \ + /* Generic device error codes interpretation */ \ + char * (*vtpglut_interp_error)(struct _vtpglut *p, vtpglut_code ec); \ + \ + /* Instrument specific error codes interpretation */ \ + char * (*interp_error)(struct _vtpglut *p, int ec); \ + \ + /* Return the last serial communication error code */ \ + /* (This is used for deciding fallback/retry strategies) */ \ + int (*last_scomerr)(struct _vtpglut *p); \ + \ + /* Destroy ourselves */ \ + void (*del)(struct _vtpglut *p); \ + + +/* The base object type */ +struct _vtpglut { + VTPGLUT_OBJ_BASE + }; typedef struct _vtpglut vtpglut; + +/* Virtual constructor. */ +/* Return NULL for unknown device, */ +/* or serial device if nocoms == 0. */ +/* (Doesn't copy icompaths log!) */ +extern vtpglut *new_vtpglut( + icompath *path, /* Device path for this device */ + int nocoms, /* Don't open if communications are needed to establish device type */ + a1log *log, /* Log to use */ + vtpglut_code (*uicallback)(void *cntx, vtpglut_ui_purp purp), + /* optional uicallback for abort */ + void *cntx /* Context for callback */ +); + +/* - - - - - - - - - - - - - - - - - - -- */ + +#ifdef __cplusplus + } +#endif + +#define VTPGLUT_H +#endif /* VTPGLUT_H */ diff --git a/spectro/vtpgluttypes.h b/spectro/vtpgluttypes.h new file mode 100755 index 0000000..081d130 --- /dev/null +++ b/spectro/vtpgluttypes.h @@ -0,0 +1,44 @@ + +/* Add instrument instance headers here */ + +/* + * 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. + */ + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef ENABLE_SERIAL +# include "dtp22.h" +# include "dtp41.h" +# include "dtp51.h" +# include "ss.h" +#endif + +#ifdef ENABLE_FAST_SERIAL +# include "specbos.h" +# include "kleink10.h" +# include "smcube.h" +#endif + +#ifdef ENABLE_USB +# include "dtp20.h" +# include "dtp92.h" +# include "i1disp.h" +# include "i1d3.h" +# include "i1pro.h" +# include "munki.h" +# include "spyd2.h" +# include "huey.h" +# include "ex1.h" +# include "hcfr.h" +# include "colorhug.h" +#endif + + diff --git a/spectro/webwin.c b/spectro/webwin.c index 1d5f713..1d5f713 100644..100755 --- a/spectro/webwin.c +++ b/spectro/webwin.c diff --git a/spectro/webwin.h b/spectro/webwin.h index 1f4412a..1f4412a 100644..100755 --- a/spectro/webwin.h +++ b/spectro/webwin.h diff --git a/spectro/xdg_bds.c b/spectro/xdg_bds.c index 03f7561..73e3edd 100644..100755 --- a/spectro/xdg_bds.c +++ b/spectro/xdg_bds.c @@ -263,7 +263,10 @@ void xdg_free(char **paths, int nopaths) { /* type of storage and access required. Return 0 if there is an error. */ /* The files are always unique (ie. the first match to a given filename */ /* in the possible XDG list of directories is returned, and files with */ -/* the same name in other XDG directories are ignored) */ +/* the same name in other XDG directories are ignored), unless the */ +/* xdg_all_matches flag is set. */ +/* If xdg_read, then first user then local scope are searched. */ +/* If xdf_write, then only the specified scope is used. */ /* Wildcards should not be used for xdg_write. */ /* The list should be free'd using xdg_free() after use. */ /* XDG environment variables and the subpath are assumed to be using */ @@ -279,6 +282,7 @@ int xdg_bds( xdg_storage_type st, /* Specify the storage type */ xdg_op_type op, /* Operation type */ xdg_scope sc, /* Scope if write */ + xdg_options opt, /* Options flags */ char *pfname /* Sub-path and file name(s) */ ) { char *path = NULL; /* Directory paths to search, separated by ':' or ';' */ @@ -315,7 +319,7 @@ int xdg_bds( return 0; } #ifdef NT - } else if (getenv("HOME") == NULL && (xdg = getenv("APPDATA")) != NULL) { + } else if (login_HOME() == NULL && (xdg = getenv("APPDATA")) != NULL) { if ((path = cappend(path, xdg)) == NULL) { if (er != NULL) *er = xdg_alloc; a1loge(g_log, 1, "xdg_bds: malloc failed\n"); @@ -323,7 +327,7 @@ int xdg_bds( } #endif } else { - if ((home = getenv("HOME")) == NULL + if ((home = login_HOME()) == NULL #ifdef NT && (home = getenv("APPDATA")) == NULL #endif @@ -339,7 +343,7 @@ int xdg_bds( return 0; } #ifdef NT - if (getenv("HOME") != NULL) + if (login_HOME() != NULL) path = dappend(path, ".local/share"); #else #ifdef UNIX_APPLE @@ -363,7 +367,7 @@ int xdg_bds( return 0; } #ifdef NT - } else if (getenv("HOME") == NULL && (xdg = getenv("APPDATA")) != NULL) { + } else if (login_HOME() == NULL && (xdg = getenv("APPDATA")) != NULL) { if ((path = cappend(path, xdg)) == NULL) { if (er != NULL) *er = xdg_alloc; a1loge(g_log, 1, "xdg_bds: malloc failed\n"); @@ -371,7 +375,7 @@ int xdg_bds( } #endif } else { - if ((home = getenv("HOME")) == NULL + if ((home = login_HOME()) == NULL #ifdef NT && (home = getenv("APPDATA")) == NULL #endif @@ -387,7 +391,7 @@ int xdg_bds( return 0; } #ifdef NT - if (getenv("HOME") != NULL) + if (login_HOME() != NULL) path = dappend(path, ".config"); #else #ifdef UNIX_APPLE @@ -411,7 +415,7 @@ int xdg_bds( return 0; } #ifdef NT - } else if (getenv("HOME") == NULL && (xdg = getenv("APPDATA")) != NULL) { + } else if (login_HOME() == NULL && (xdg = getenv("APPDATA")) != NULL) { if ((path = cappend(path, xdg)) == NULL) { if (er != NULL) *er = xdg_alloc; a1loge(g_log, 1, "xdg_bds: malloc failed\n"); @@ -424,7 +428,7 @@ int xdg_bds( } #endif } else { - if ((home = getenv("HOME")) == NULL + if ((home = login_HOME()) == NULL #ifdef NT && (home = getenv("APPDATA")) == NULL #endif @@ -440,7 +444,7 @@ int xdg_bds( return 0; } #ifdef NT - if (getenv("HOME") != NULL) + if (login_HOME() != NULL) path = dappend(path, ".cache"); else path = dappend(path, "Cache"); @@ -662,18 +666,20 @@ int xdg_bds( } DBG((DBGA,"Found match with '%s'\n",fpath)) - /* Check that this one hasn't already been found */ - /* in a different search directory */ - for (i = 0; i < npaths; i++) { - if (strcmp(fpath + rlen, fnames[i]) == 0) { - /* Already been found earlier - ignore it */ - break; + if (opt != xdg_all_matches) { + /* Check that this one hasn't already been found */ + /* in a different search directory */ + for (i = 0; i < npaths; i++) { + if (strcmp(fpath + rlen, fnames[i]) == 0) { + /* Already been found earlier - ignore it */ + break; + } + } + if (i < npaths) { + free(fpath); + DBG((DBGA,"Ignoring it because it's already in list\n")) + continue; /* Ignore it */ } - } - if (i < npaths) { - free(fpath); - DBG((DBGA,"Ignoring it because it's already in list\n")) - continue; /* Ignore it */ } /* Found a file, so append it to the list */ @@ -969,7 +975,7 @@ static int runtest( } printf("\nTesting Variable %s\n",env); - if ((nopaths = xdg_bds(&er, &paths, st, xdg_write, sc, pfname)) == 0) { + if ((nopaths = xdg_bds(&er, &paths, st, xdg_write, sc, xdg_none, pfname)) == 0) { printf("Write test failed with %s\n",xdg_errstr(er)); return 1; } @@ -996,7 +1002,7 @@ static int runtest( } xdg_free(paths, nopaths); - if ((nopaths = xdg_bds(&er, &paths, st, xdg_read, sc, pfname)) < 1) { + if ((nopaths = xdg_bds(&er, &paths, st, xdg_read, sc, xdg_none, pfname)) < 1) { printf("Read test failed with %s\n",xdg_errstr(er)); return 1; } diff --git a/spectro/xdg_bds.h b/spectro/xdg_bds.h index 18101b0..9eb6651 100644..100755 --- a/spectro/xdg_bds.h +++ b/spectro/xdg_bds.h @@ -51,6 +51,12 @@ typedef enum { xdg_local /* Local System wide context */ } xdg_scope; +/* Optional flags */ +typedef enum { + xdg_none = 0x0000, /* No options */ + xdg_all_matches = 0x0001 /* Return all matching files */ +} xdg_options; + /* An error code */ typedef enum { xdg_ok = 0, @@ -96,6 +102,7 @@ int xdg_bds( xdg_storage_type st, /* Specify the storage type */ xdg_op_type op, /* Operation type */ xdg_scope sc, /* Scope if write */ + xdg_options opt, /* Options flags */ char *spath /* Sub-path and file name or file pattern */ ); diff --git a/spectro/xrga.c b/spectro/xrga.c index 0bf22fa..7318fce 100644..100755 --- a/spectro/xrga.c +++ b/spectro/xrga.c @@ -42,6 +42,7 @@ #ifndef SALONEINSTLIB # include "plot.h" #endif +#include "cgats.h" #include "xspect.h" #include "insttypes.h" #include "conv.h" diff --git a/spectro/xrga.h b/spectro/xrga.h index 0605fc8..0605fc8 100644..100755 --- a/spectro/xrga.h +++ b/spectro/xrga.h |