diff --git a/doc/MinorTools.html b/doc/MinorTools.html index 5e9a5c4..93c6b01 100755 --- a/doc/MinorTools.html +++ b/doc/MinorTools.html @@ -52,6 +52,7 @@ Test 1D Brent solver
xicc/xcolorantslu.exe
xicc/xfbview.exe
spectro/dispwin.exe +
spectro/instlist.exe
target/ifarp.exe
target/ppoint.exe
target/qrand.exe diff --git a/doc/instlist.html b/doc/instlist.html new file mode 100644 index 0000000..59de379 --- /dev/null +++ b/doc/instlist.html @@ -0,0 +1,39 @@ + + + + instlist + + + + +

spectro/instlist

+
+ Enumerate connected instrument communication ports (USB and Serial) and output the list in JSON format.
+

Usage

+  instlist [-options]
+  -h, -?, --help  Show help information
+  -v              Verbose diagnostics to stderr
+  -D [level]      Print debug diagnostics to stderr
+

+

Output

+ The output is emitted to stdout as a JSON object containing an array of discovered device objects:
+
+{
+  "event": "instruments",
+  "devices": [
+    {
+      "port": 1,
+      "name": "usb:/bus0/dev1 (X-Rite i1Pro)",
+      "type": "i1Pro"
+    }
+  ]
+}
+    
+

Comments

+ This tool is designed to allow graphical user interfaces and external automation scripts to discover available spectrophotometers and colorimeters across Windows, macOS, and Linux without needing to parse interactive usage output.
+
+ The port number directly corresponds to the -c parameter accepted by tools such as chartread, spotread, and dispread.
+
+ + diff --git a/imdi/Jamfile b/imdi/Jamfile index 79b27fb..2c0ec65 100755 --- a/imdi/Jamfile +++ b/imdi/Jamfile @@ -42,6 +42,7 @@ LINKLIBS = ../numlib/libnum ; # GenFile source.c : program args ; make custom file # Generate all the kernel files GenFileND imdi_k.h : imdi_make $(IMDI_MAKE_OPT) -d [ NormPaths $(DOT) ] ; +Clean clean : imdi_k.c ; # imdi library Library libimdi : imdi.c imdi_tab.c ; diff --git a/spectro/Jamfile b/spectro/Jamfile index d4788ff..38323d0 100755 --- a/spectro/Jamfile +++ b/spectro/Jamfile @@ -51,7 +51,7 @@ if $(UNIX) { #Products Libraries = libinsttypes libdisptechs libinst libdisp libconv libinstapp ; Executables = dispwin synthcal dispread dispcal fakeread synthread - chartread spotread illumread ccxxmake average oeminst ; + chartread spotread instlist illumread ccxxmake average oeminst ; Headers = inst.h ; Samples = SOtele.sp linear.cal strange.cal ccxx.ti1 ; @@ -198,6 +198,10 @@ Main illumread : illumread.c : : : ../target : : ; # Printed target spot reader utility Main spotread : spotread.c : : : : : ; +# Connected instrument enumeration utility +Main instlist : instlist.c : : : : : ; +Clean clean : instlist$(SUFEXE) instlist.o ; + echo "HOME = " $(HOME) ; echo "PWD = " $(PWD) ; diff --git a/spectro/instlist.c b/spectro/instlist.c new file mode 100644 index 0000000..2b59b03 --- /dev/null +++ b/spectro/instlist.c @@ -0,0 +1,134 @@ +/* + * Argyll Color Management System + * USB & Serial Instrument Enumeration Utility. + * Outputs connected instruments in structured JSON format. + * + * Author: Graeme W. Gill / Gordon + * + * Copyright 2026 Graeme W. Gill / Gordon + * All rights reserved. + * + * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :- + * see the License.txt file for licencing details. + */ + +#include +#include +#include +#include +#include "copyright.h" +#include "aconfig.h" +#include "numlib.h" +#include "cgats.h" +#include "conv.h" +#include "xicc.h" +#include "insttypes.h" +#include "icoms.h" +#include "inst.h" + +static void usage(char *diag, ...) { + fprintf(stderr,"Enumerate Instrument Ports, Version %s\n",ARGYLL_VERSION_STR); + if (diag != NULL) { + va_list args; + fprintf(stderr," Diagnostic: "); + va_start(args, diag); + vfprintf(stderr, diag, args); + va_end(args); + fprintf(stderr,"\n"); + } + fprintf(stderr,"Author: Graeme W. Gill / Gordon, licensed under the AGPL Version 3\n"); + fprintf(stderr,"usage: instlist [-options]\n"); + fprintf(stderr," -h, -?, --help Show this help information\n"); + fprintf(stderr," -v Verbose diagnostics to stderr\n"); + fprintf(stderr," -D [level] Print debug diagnostics to stderr\n"); + exit(1); +} + +int main(int argc, char *argv[]) { + int fa, nfa; + int verb = 0; + int debug = 0; + icompaths *icmps = NULL; + icompath **paths = NULL; + int i; + int count = 0; + + /* Set executable path for logger */ + set_exe_path(argv[0]); + + /* Process command-line options */ + for (fa = 1; fa < argc; fa++) { + nfa = fa + 1; + if (argv[fa][0] == '-') { + char *na = NULL; + if (nfa < argc && argv[nfa][0] != '-') + na = argv[nfa]; + + if (strcmp(argv[fa], "-h") == 0 || strcmp(argv[fa], "-?") == 0 || + strcmp(argv[fa], "--help") == 0 || strcmp(argv[fa], "-help") == 0) { + usage(NULL); + } else if (argv[fa][1] == 'v') { + verb = 1; + g_log->verb = verb; + } else if (argv[fa][1] == 'D') { + debug = 1; + if (na != NULL && na[0] >= '0' && na[0] <= '9') { + debug = atoi(na); + fa = nfa; + } + g_log->debug = debug; + } else { + usage("Unknown option '%s'", argv[fa]); + } + } else { + usage("Unexpected argument '%s'", argv[fa]); + } + } + + if ((icmps = new_icompaths(g_log)) == NULL) { + printf("{\n \"event\": \"instruments\",\n \"devices\": []\n}\n"); + fflush(stdout); + return 1; + } + + paths = icmps->paths; + + printf("{\n \"event\": \"instruments\",\n \"devices\": [\n"); + + if (paths != NULL) { + for (i = 0; paths[i] != NULL; i++) { + char *tname = inst_name(paths[i]->dtype); + char *name = paths[i]->name ? paths[i]->name : "Unknown"; + + if (count > 0) { + printf(",\n"); + } + + printf(" {\n"); + printf(" \"port\": %d,\n", i + 1); + printf(" \"name\": \""); + /* Escape quotes and backslashes in name */ + { + char *p; + for (p = name; *p != '\0'; p++) { + if (*p == '"' || *p == '\\') { + putchar('\\'); + } + putchar(*p); + } + } + printf("\",\n"); + printf(" \"type\": \"%s\"\n", (tname != NULL && tname[0] != '\0') ? tname : "Unknown"); + printf(" }"); + count++; + } + } + + printf("\n ]\n}\n"); + fflush(stdout); + + if (icmps != NULL) + icmps->del(icmps); + + return 0; +}