Skip to content

Support launching DIVE Desktop on a dataset from the command line#1754

Open
mattdawkins wants to merge 3 commits into
mainfrom
dev/desktop-cli-open
Open

Support launching DIVE Desktop on a dataset from the command line#1754
mattdawkins wants to merge 3 commits into
mainfrom
dev/desktop-cli-open

Conversation

@mattdawkins

Copy link
Copy Markdown
Member

Summary

Adds --import / --annotations / --name so DIVE Desktop can be started directly on media plus an annotation file, skipping the import wizard:

dive-desktop --import input_list.txt --annotations detections.csv --name "Sea Lions"

--import accepts anything the wizard does (an image-sequence directory, an image-list text file, or a video); --annotations accepts a VIAME CSV or DIVE JSON.

This came out of wanting to review detector output over an image list without clicking through the import wizard each time.

Behavior

The import runs through the same backend calls as the wizard (beginMediaImportfinalizeMediaImportdataFileImport), so the result is an ordinary dataset — it lands in the recents list and can be reopened later, exactly as if it had been imported by hand. Media that needs transcoding is converted first, and the viewer opens when the conversion job completes.

Two things worth a look in review

Renderer pulls, main process does not push. The renderer asks for the pending dataset (desktop:cli-open-pending) once it is mounted. Settings are owned by the renderer and handed to the background process at startup, and the import needs them (for dataPath), so the request waits on that handoff — otherwise the backend throws settings has not been initialized. Pulling also avoids racing the listener registration against an import that finishes before the window is ready.

Second-instance forwarding. A second launch carrying --import now opens that dataset in the running window instead of being dropped by the single-instance lock. The args are parsed from the raw process.argv and handed over via requestSingleInstanceLock(additionalData), because the argv Chromium forwards to second-instance hoists switches ahead of positionals and thereby detaches --import from its value:

["dive-desktop","--import","--annotations","--name", ...switches..., "/path/list.txt","/path/x.csv","Sea Lions"]

Window creation is now guarded on actually holding the lock. Previously a losing instance raced its own app.quit(), and with the "already running" dialog no longer blocking that race it would build a window mid-teardown and report a spurious "application failed to start".

Testing

  • New unit tests for the argument parser (6 cases, including = syntax, short flags, relative-path resolution, and not swallowing a following flag as a value).
  • Built with build:electron:dir and exercised end to end on a 3-image list with a VIAME CSV of 570 polygon detections: dataset imports, viewer opens, annotations and polygons render, dataset appears in recents. Second-instance forwarding verified with a separate CSV opening into the already-running window.
  • platform/ suite passes apart from two web-girder/multicamFileRegistry.spec.ts failures that reproduce on a clean main and are unrelated to this change.

🤖 Generated with Claude Code

mattdawkins and others added 3 commits July 13, 2026 12:08
Add --import / --annotations / --name so the app can be started directly on
media plus an annotation file, skipping the import wizard:

  dive-desktop --import input_list.txt --annotations detections.csv

--import accepts anything the wizard does (image directory, image-list text
file, or video) and --annotations accepts a VIAME CSV or DIVE JSON. The import
runs through the same backend calls as the wizard (beginMediaImport ->
finalizeMediaImport -> dataFileImport), so the result is an ordinary dataset:
it lands in the recents list and can be reopened later. Media needing
transcoding is converted first and opens when the job completes.

Two things worth calling out:

- The renderer pulls the pending dataset (desktop:cli-open-pending) once it is
  mounted, rather than the main process pushing it. Settings are owned by the
  renderer and handed to the background process at startup, and the import
  needs them, so the request waits on that handoff. It also avoids racing an
  import that finishes before the window is ready.

- A second launch carrying --import forwards to the running instance instead of
  being dropped by the single-instance lock. The args are parsed from the raw
  process.argv and passed via requestSingleInstanceLock(additionalData),
  because the argv Chromium forwards to second-instance hoists switches ahead
  of positionals and so detaches --import from its value. Window creation is
  now guarded on holding the lock; a losing instance previously raced its own
  app.quit() and could report a spurious startup failure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The launch flags only handled single-camera datasets, since they went
straight to beginMediaImport. Name each camera instead to import a
multi-camera or stereo dataset:

  dive-desktop --camera left=/data/left --camera right=/data/right \
               --annotations left=/data/left.csv --annotations right=/data/right.csv \
               --calibration /data/calibration_matrices.npz

--camera is repeatable and takes <name>=<media>, splitting on the first =
so Windows paths survive; flag order is the display order. --annotations
becomes <camera>=<file> in this mode, since each camera carries its own
track file. --calibration takes a stereo calibration (.npz or .json), and
--default-display picks the camera shown on open (default: left when
present, else the first camera).

Stereo is not a separate flag: as elsewhere in DIVE, cameras named exactly
left and right are typed stereo by the importer, anything else multicam.

Multi-camera launches route through beginMultiCamImport rather than
beginMediaImport, which takes the per-camera track files in its sourceList
and hands the calibration to finalizeMediaImport to copy and normalize, so
annotations must not also be imported via dataFileImport.

Also fixed along the way:

- second-instance forwarding gated on cliArgs.importPath, which a
  multi-camera launch does not set, so forwarding a multi-camera dataset to
  a running instance was silently dropped.
- parseCliArgs can now reject bad usage (mixing --import with --camera, a
  lone camera, annotations naming an unknown camera, mismatched media
  kinds). It is called at module scope, so a throw there would have taken
  the process down with no message; the error is now held and reported once
  the app is ready.
- a failed CLI import only raised a modal dialog, which is invisible to
  anyone driving the app from a script; it is logged as well now, and the
  message no longer says "Failed to open undefined" for multi-camera.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Opening a dataset while the viewer already shows another one keeps
ViewerLoader mounted and only changes the :id route param. Vue Router calls
beforeRouteUpdate for that, not beforeRouteLeave, so the unsaved-changes
guard never ran -- and the id watcher in Viewer reloads by way of
discardChanges(), silently throwing away unsaved edits.

Guard beforeRouteUpdate with the same navigateAwayGuard.

Previously unreachable, since navigation into the viewer always came from
another route. The CLI launch flags made it reachable: forwarding a dataset
to a running instance navigates viewer -> viewer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mattdawkins added a commit to VIAME/VIAME that referenced this pull request Jul 13, 2026
Points the dive submodule at viame/master f1fe0b2a, which adds
--import / --annotations / --name to dive-desktop so it can be started
directly on media plus an annotation file (VIAME CSV or DIVE JSON),
skipping the import wizard:

  dive-desktop --import input_list.txt --annotations detections.csv

Upstream PR against dive main: Kitware/dive#1754

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mattdawkins added a commit to VIAME/VIAME that referenced this pull request Jul 13, 2026
Points the dive submodule at viame/master d622e3a2, which extends the
dive-desktop launch flags to multi-camera and stereo datasets:

  dive-desktop --camera left=<media> --camera right=<media> \
               --annotations left=<file> --annotations right=<file> \
               --calibration <file>

Cameras named exactly left/right import as stereo, anything else as
multicam, matching how DIVE types these datasets elsewhere.

Upstream PR against dive main: Kitware/dive#1754

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mattdawkins added a commit to VIAME/VIAME that referenced this pull request Jul 13, 2026
Opening a dataset from the command line while the viewer already shows
another one navigates viewer -> viewer, which fires beforeRouteUpdate rather
than beforeRouteLeave, so DIVE's unsaved-changes guard was skipped and the
reload silently discarded unsaved edits.

Upstream PR against dive main: Kitware/dive#1754

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mattdawkins mattdawkins requested a review from BryonLewis July 13, 2026 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant