Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
imagej-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
imagej-elphel
Commits
31fcc689
Commit
31fcc689
authored
Jan 29, 2026
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implementing quasi-parallel processing using GUI and MCP
parent
30b9d3f9
Changes
9
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
232 additions
and
445 deletions
+232
-445
CLTParameters.java
src/main/java/com/elphel/imagej/cameras/CLTParameters.java
+7
-1
EyesisCorrectionParameters.java
...com/elphel/imagej/cameras/EyesisCorrectionParameters.java
+25
-13
GenericJTabbedDialogMcp.java
...ava/com/elphel/imagej/common/GenericJTabbedDialogMcp.java
+36
-2
Eyesis_Correction.java
.../java/com/elphel/imagej/correction/Eyesis_Correction.java
+44
-419
SyncCommand.java
src/main/java/com/elphel/imagej/correction/SyncCommand.java
+1
-0
McpDialogRegistry.java
src/main/java/com/elphel/imagej/mcp/McpDialogRegistry.java
+42
-3
McpDialogSession.java
src/main/java/com/elphel/imagej/mcp/McpDialogSession.java
+38
-0
McpFsAccess.java
src/main/java/com/elphel/imagej/mcp/McpFsAccess.java
+3
-3
McpServer.java
src/main/java/com/elphel/imagej/mcp/McpServer.java
+36
-4
No files found.
src/main/java/com/elphel/imagej/cameras/CLTParameters.java
View file @
31fcc689
...
...
@@ -3407,13 +3407,19 @@ public class CLTParameters {
}
public
boolean
showJDialog
()
{
return
showJDialog
(
false
);
return
showJDialog
(
false
,
GenericJTabbedDialogMcp
.
isDefaultMcpMode
()
);
}
// codex 2026-01-27: optional modeless dialog for MCP/GUI co-use
public
boolean
showJDialog
(
boolean
nonBlocking
)
{
return
showJDialog
(
nonBlocking
,
GenericJTabbedDialogMcp
.
isDefaultMcpMode
());
}
// codex 2026-01-28: allow forcing GUI vs MCP mode per call
public
boolean
showJDialog
(
boolean
nonBlocking
,
boolean
useMcp
)
{
// GenericDialog gd = new GenericDialog("Set CLT parameters");
GenericJTabbedDialogMcp
gd
=
new
GenericJTabbedDialogMcp
(
"Set CLT parameters"
,
1090
,
900
,
!
nonBlocking
);
// codex 2026-01-25
gd
.
setMcpMode
(
useMcp
);
gd
.
addTab
(
"General"
,
"General parameters"
);
gd
.
addNumericField
(
"Nominal (rectilinear) disparity between side of square cameras (pix)"
,
this
.
disparity
,
3
,
7
,
"pix"
,
"Used when rendering 4 images"
);
...
...
src/main/java/com/elphel/imagej/cameras/EyesisCorrectionParameters.java
View file @
31fcc689
...
...
@@ -1197,14 +1197,23 @@ public class EyesisCorrectionParameters {
public
boolean
showCLTBatchDialog
(
String
title
,
CLTParameters
clt_parameters
)
{
return
showCLTBatchDialog
(
title
,
clt_parameters
,
false
);
return
showCLTBatchDialog
(
title
,
clt_parameters
,
false
,
GenericJTabbedDialogMcp
.
isDefaultMcpMode
()
);
}
// codex 2026-01-27: optional modeless dialog for MCP/GUI co-use
public
boolean
showCLTBatchDialog
(
String
title
,
CLTParameters
clt_parameters
,
boolean
nonBlocking
)
{
return
showCLTBatchDialog
(
title
,
clt_parameters
,
nonBlocking
,
GenericJTabbedDialogMcp
.
isDefaultMcpMode
());
}
// codex 2026-01-28: allow forcing GUI vs MCP mode per call
public
boolean
showCLTBatchDialog
(
String
title
,
CLTParameters
clt_parameters
,
boolean
nonBlocking
,
boolean
useMcp
)
{
GenericJTabbedDialogMcp
gd
=
new
GenericJTabbedDialogMcp
(
title
,
1000
,
1000
,
!
nonBlocking
);
// codex 2026-01-25
gd
.
setMcpMode
(
useMcp
);
updateAuxFromMain
();
...
...
@@ -1792,7 +1801,8 @@ public class EyesisCorrectionParameters {
base_path
=
base_path
.
resolve
(
Paths
.
get
(
dir_map
.
get
(
"rootDirectory"
)));
File
base_dir
=
new
File
(
base_path
.
toString
());
if
(!
base_dir
.
exists
())
{
base_dir
.
mkdirs
();
// codex 2026-01-28: mkdirs side-effect (consider guarding)
System
.
out
.
println
(
"Root directory "
+
base_path
.
toString
()+
" does not exist, ignoring "
+
seq_str
);
return
null
;
}
}
// set sourceDirectory:
...
...
@@ -1808,7 +1818,8 @@ public class EyesisCorrectionParameters {
Path
source_path
=
Paths
.
get
(
this
.
sourceDirectory
);
File
source_dir
=
new
File
(
source_path
.
toString
());
if
(!
source_dir
.
exists
())
{
source_dir
.
mkdirs
();
// codex 2026-01-28: mkdirs side-effect (consider guarding)
System
.
out
.
println
(
"Source directory "
+
source_path
.
toString
()+
" does not exist, ignoring "
+
seq_str
);
return
null
;
}
useCuasSeedDir
=
false
;
...
...
@@ -1821,7 +1832,8 @@ public class EyesisCorrectionParameters {
File
dir_file
=
new
File
(
dir_path
.
toString
());
if
((
i
!=
KEY_INDEX_UAS_LOGS
)
&&
(
i
!=
KEY_INDEX_SKY_MASK
))
{
// cuasUasLogs, cuasSkyMask are files, not directories
if
(!
dir_file
.
exists
())
{
dir_file
.
mkdirs
();
// codex 2026-01-28: mkdirs side-effect (consider guarding)
System
.
out
.
println
(
KEY_DIRS
[
i
]+
" directory "
+
dir_path
.
toString
()+
" does not exist, ignoring "
+
seq_str
);
return
null
;
}
}
dir_string
=
dir_path
.
toString
();
...
...
src/main/java/com/elphel/imagej/common/GenericJTabbedDialogMcp.java
View file @
31fcc689
...
...
@@ -12,7 +12,9 @@ import ij.IJ;
public
class
GenericJTabbedDialogMcp
extends
GenericJTabbedDialog
{
// codex 2026-01-25: MCP dialog capture state
private
static
boolean
defaultMcpMode
=
false
;
private
static
long
dialogTimeoutMs
=
30000L
;
public
boolean
mcp_mode
=
false
;
private
boolean
mcpCanceled
=
false
;
private
final
List
<
McpDialogField
>
mcpFields
=
new
ArrayList
<
McpDialogField
>();
private
final
String
dialogTitle
;
private
String
currentTab
=
""
;
...
...
@@ -42,6 +44,14 @@ public class GenericJTabbedDialogMcp extends GenericJTabbedDialog{
public
static
boolean
isDefaultMcpMode
()
{
return
defaultMcpMode
;
}
// codex 2026-01-28: configurable MCP dialog submit timeout (0 = wait forever)
public
static
void
setDialogTimeoutMs
(
long
timeoutMs
)
{
dialogTimeoutMs
=
timeoutMs
;
}
// codex 2026-01-28: override MCP mode per dialog instance
public
void
setMcpMode
(
boolean
enabled
)
{
this
.
mcp_mode
=
enabled
;
}
private
void
addMcpField
(
McpDialogField
field
)
{
mcpFields
.
add
(
field
);
...
...
@@ -121,6 +131,16 @@ public class GenericJTabbedDialogMcp extends GenericJTabbedDialog{
else
super
.
addChoice
(
label
,
items
,
defaultItem
,
tooltip
,
count
);
}
@Override
public
void
addChoice
(
String
label
,
String
[]
items
,
String
defaultItem
)
{
addChoice
(
label
,
items
,
defaultItem
,
null
,
0
);
}
@Override
public
void
addChoice
(
String
label
,
String
[]
items
,
String
defaultItem
,
String
tooltip
)
{
addChoice
(
label
,
items
,
defaultItem
,
tooltip
,
0
);
}
@Override
public
void
addDefaultButtons
()
{
// not used
if
(
mcp_mode
)
{
...
...
@@ -149,7 +169,10 @@ public class GenericJTabbedDialogMcp extends GenericJTabbedDialog{
if
(
mcp_mode
)
{
// codex 2026-01-25: publish dialog schema to MCP registry
readIndex
=
0
;
McpDialogRegistry
.
setCurrent
(
new
McpDialogSession
(
dialogTitle
,
mcpFields
));
boolean
applied
=
McpDialogRegistry
.
setCurrent
(
new
McpDialogSession
(
dialogTitle
,
mcpFields
));
if
(!
applied
)
{
System
.
out
.
println
(
"MCP: dialog already active, ignoring \""
+
dialogTitle
+
"\""
);
}
}
else
super
.
buildDialog
();
}
...
...
@@ -253,6 +276,17 @@ public class GenericJTabbedDialogMcp extends GenericJTabbedDialog{
public
boolean
showDialog
()
{
if
(
mcp_mode
)
{
buildDialog
();
McpDialogSession
session
=
McpDialogRegistry
.
getCurrent
();
if
(
session
!=
null
)
{
long
timeout
=
dialogTimeoutMs
;
Boolean
ok
=
(
timeout
<=
0
)
?
session
.
awaitSubmit
(
Long
.
MAX_VALUE
)
:
session
.
awaitSubmit
(
timeout
);
if
(
ok
!=
null
&&
!
ok
.
booleanValue
())
{
mcpCanceled
=
true
;
}
else
{
mcpCanceled
=
false
;
}
}
McpDialogRegistry
.
setCurrent
(
null
);
return
true
;
}
else
return
super
.
showDialog
();
...
...
@@ -279,7 +313,7 @@ public class GenericJTabbedDialogMcp extends GenericJTabbedDialog{
@Override
public
boolean
wasCanceled
()
{
if
(
mcp_mode
)
{
return
false
;
return
mcpCanceled
;
}
else
return
super
.
wasCanceled
();
}
...
...
src/main/java/com/elphel/imagej/correction/Eyesis_Correction.java
View file @
31fcc689
This diff is collapsed.
Click to expand it.
src/main/java/com/elphel/imagej/correction/SyncCommand.java
View file @
31fcc689
...
...
@@ -12,6 +12,7 @@ public class SyncCommand {
public
AtomicInteger
stopRequested
=
new
AtomicInteger
(
0
);
// 0 - not requested, 1 - ASAP, 2 - gracefully
public
String
buttonLabel
=
""
;
public
boolean
confirm
=
true
;
public
boolean
fromMcp
=
false
;
// codex 2026-01-27: MCP-controlled pause/confirm
private
boolean
mcpMode
=
false
;
private
boolean
confirmPending
=
false
;
...
...
src/main/java/com/elphel/imagej/mcp/McpDialogRegistry.java
View file @
31fcc689
...
...
@@ -8,19 +8,58 @@ public class McpDialogRegistry {
private
McpDialogRegistry
()
{
}
public
static
void
setCurrent
(
McpDialogSession
session
)
{
public
static
boolean
setCurrent
(
McpDialogSession
session
)
{
if
(
session
==
null
)
{
CURRENT
.
set
(
null
);
return
true
;
}
McpDialogSession
existing
=
CURRENT
.
get
();
if
(
existing
!=
null
)
{
return
false
;
}
CURRENT
.
set
(
session
);
return
true
;
}
public
static
McpDialogSession
getCurrent
()
{
return
CURRENT
.
get
();
}
public
static
void
setValue
(
String
label
,
String
value
)
{
public
static
boolean
setValue
(
String
label
,
String
value
)
{
McpDialogSession
session
=
CURRENT
.
get
();
if
(
session
==
null
)
{
return
;
return
false
;
}
session
.
setValue
(
label
,
value
);
return
true
;
}
public
static
boolean
setValueForId
(
String
id
,
String
label
,
String
value
)
{
McpDialogSession
session
=
CURRENT
.
get
();
if
(
session
==
null
||
id
==
null
||
!
id
.
equals
(
session
.
getId
()))
{
return
false
;
}
session
.
setValue
(
label
,
value
);
return
true
;
}
public
static
boolean
submitCurrent
(
boolean
ok
)
{
McpDialogSession
session
=
CURRENT
.
get
();
if
(
session
==
null
)
{
return
false
;
}
session
.
submit
(
ok
);
CURRENT
.
set
(
null
);
return
true
;
}
public
static
boolean
submitForId
(
String
id
,
boolean
ok
)
{
McpDialogSession
session
=
CURRENT
.
get
();
if
(
session
==
null
||
id
==
null
||
!
id
.
equals
(
session
.
getId
()))
{
return
false
;
}
session
.
submit
(
ok
);
CURRENT
.
set
(
null
);
return
true
;
}
}
src/main/java/com/elphel/imagej/mcp/McpDialogSession.java
View file @
31fcc689
...
...
@@ -8,10 +8,13 @@ import java.util.Map;
import
java.util.UUID
;
public
class
McpDialogSession
{
public
static
final
int
debugLevel
=
-
1
;
// name in the same case in most other places. Compares if (debugLevel >-3)
private
final
String
id
;
private
final
String
title
;
private
final
List
<
McpDialogField
>
fields
;
private
final
Map
<
String
,
String
>
valuesByLabel
;
private
final
Object
submitLock
=
new
Object
();
private
Boolean
submittedOk
=
null
;
public
McpDialogSession
(
String
title
,
List
<
McpDialogField
>
fields
)
{
this
.
id
=
UUID
.
randomUUID
().
toString
();
...
...
@@ -37,6 +40,41 @@ public class McpDialogSession {
return
;
}
valuesByLabel
.
put
(
label
,
value
);
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"setValue("
+
label
+
","
+
value
+
")"
);
}
}
public
void
submit
(
boolean
ok
)
{
synchronized
(
submitLock
)
{
submittedOk
=
Boolean
.
valueOf
(
ok
);
submitLock
.
notifyAll
();
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"submit("
+
ok
+
")"
);
}
}
}
public
Boolean
awaitSubmit
(
long
timeoutMs
)
{
synchronized
(
submitLock
)
{
if
(
submittedOk
!=
null
)
{
return
submittedOk
;
}
long
deadline
=
System
.
currentTimeMillis
()
+
timeoutMs
;
while
(
submittedOk
==
null
)
{
long
remaining
=
deadline
-
System
.
currentTimeMillis
();
if
(
remaining
<=
0
)
{
break
;
}
try
{
submitLock
.
wait
(
remaining
);
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
break
;
}
}
return
submittedOk
;
}
}
public
String
getValue
(
String
label
)
{
...
...
src/main/java/com/elphel/imagej/mcp/McpFsAccess.java
View file @
31fcc689
...
...
@@ -72,9 +72,9 @@ public class McpFsAccess {
if
(
configPath
!=
null
&&
!
configPath
.
trim
().
isEmpty
())
{
Path
configFile
=
Paths
.
get
(
configPath
).
toAbsolutePath
().
normalize
();
roots
.
add
(
configFile
);
Path
configDir
=
configFile
.
getParent
();
if
(
configDir
!=
null
)
{
roots
.
add
(
configDir
);
Path
configDir
FileParent
=
configFile
.
getParent
();
if
(
configDir
FileParent
!=
null
)
{
roots
.
add
(
configDir
FileParent
);
}
addRootsFromConfig
(
configFile
,
roots
);
}
...
...
src/main/java/com/elphel/imagej/mcp/McpServer.java
View file @
31fcc689
...
...
@@ -51,6 +51,7 @@ public class McpServer {
server
.
createContext
(
"/mcp/status"
,
new
StatusHandler
());
server
.
createContext
(
"/mcp/dialog"
,
new
DialogHandler
());
server
.
createContext
(
"/mcp/dialog/values"
,
new
DialogValuesHandler
());
server
.
createContext
(
"/mcp/dialog/submit"
,
new
DialogSubmitHandler
());
server
.
createContext
(
"/mcp/button"
,
new
ButtonHandler
());
server
.
createContext
(
"/mcp/interrupt"
,
new
InterruptHandler
());
server
.
createContext
(
"/mcp/interrupt/confirm"
,
new
InterruptConfirmHandler
());
...
...
@@ -62,8 +63,10 @@ public class McpServer {
server
.
createContext
(
"/mcp/fs/glob"
,
new
FsGlobHandler
());
server
.
setExecutor
(
null
);
server
.
start
();
if
(
Eyesis_Correction
.
MCP_DEBUG_LEVEL
>=
Eyesis_Correction
.
MINIMAL_DEBUG_MCP
)
{
System
.
out
.
println
(
"MCP: server started on http://127.0.0.1:"
+
port
);
}
}
private
class
StatusHandler
implements
HttpHandler
{
@Override
...
...
@@ -89,14 +92,40 @@ public class McpServer {
return
;
}
Map
<
String
,
String
>
params
=
parseParams
(
exchange
);
String
id
=
params
.
get
(
"id"
);
String
label
=
params
.
get
(
"label"
);
String
value
=
params
.
get
(
"value"
);
if
(
label
==
null
)
{
sendJson
(
exchange
,
400
,
"{\"ok\":false,\"error\":\"Missing label\"}"
);
return
;
}
McpDialogRegistry
.
setValue
(
label
,
value
);
boolean
applied
=
(
id
==
null
)
?
McpDialogRegistry
.
setValue
(
label
,
value
)
:
McpDialogRegistry
.
setValueForId
(
id
,
label
,
value
);
if
(
applied
)
{
if
(
Eyesis_Correction
.
MCP_DEBUG_LEVEL
>=
Eyesis_Correction
.
MINIMAL_DEBUG_MCP
)
{
System
.
out
.
println
(
"MCP: dialog value label=\""
+
label
+
"\""
);
}
sendJson
(
exchange
,
200
,
"{\"ok\":true}"
);
}
else
{
sendJson
(
exchange
,
409
,
"{\"ok\":false,\"error\":\"No active dialog or id mismatch\"}"
);
}
}
}
private
class
DialogSubmitHandler
implements
HttpHandler
{
@Override
public
void
handle
(
HttpExchange
exchange
)
throws
IOException
{
if
(!
"POST"
.
equalsIgnoreCase
(
exchange
.
getRequestMethod
()))
{
sendJson
(
exchange
,
405
,
"{\"ok\":false,\"error\":\"POST required\"}"
);
return
;
}
Map
<
String
,
String
>
params
=
parseParams
(
exchange
);
String
id
=
params
.
get
(
"id"
);
boolean
ok
=
parseBool
(
params
.
get
(
"ok"
),
true
);
boolean
applied
=
(
id
==
null
)
?
McpDialogRegistry
.
submitCurrent
(
ok
)
:
McpDialogRegistry
.
submitForId
(
id
,
ok
);
if
(
applied
&&
Eyesis_Correction
.
MCP_DEBUG_LEVEL
>=
Eyesis_Correction
.
MINIMAL_DEBUG_MCP
)
{
System
.
out
.
println
(
"MCP: dialog submit ok="
+
ok
);
}
sendJson
(
exchange
,
200
,
applied
?
"{\"ok\":true}"
:
"{\"ok\":false,\"error\":\"No active dialog\"}"
);
}
}
...
...
@@ -113,7 +142,10 @@ public class McpServer {
sendJson
(
exchange
,
400
,
"{\"ok\":false,\"error\":\"Missing label\"}"
);
return
;
}
owner
.
triggerCommand
(
label
);
owner
.
triggerCommand
(
label
,
true
);
if
(
Eyesis_Correction
.
MCP_DEBUG_LEVEL
>=
Eyesis_Correction
.
MINIMAL_DEBUG_MCP
)
{
System
.
out
.
println
(
"MCP: button \""
+
label
+
"\""
);
}
sendJson
(
exchange
,
200
,
"{\"ok\":true}"
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment