# The command line

`duet` is the terminal build, `duet-gui` the window; both take the
same files and options. Files are told apart by extension and may come
in any order. With no options DUET opens the files and waits — a
tracker loads stopped, `F5` plays — and with a headless option it does
the job and quits, without opening a window or an audio device.

The option list below is `duet --help`, generated by
`tools/docgen.py` so it cannot fall behind the binary.

## Recipes

Open things:

```sh
duet                               # a fresh duet
duet song.it                       # an Impulse Tracker module
duet tune.swm                      # a SID-Wizard module (.sws/.swt/.swq too)
duet song.it tune.swm              # the two together: a co-play
duet project.zon                   # a project, with everything it holds
duet --play song.it                # ... and start playing at once
duet --keys docs/keymaps/sidwizard.zon song.it   # another key layout
```

Render to a file — no window, no audio device:

```sh
duet --render out.wav project.zon                     # the mix, as you hear it
duet --render out.wav --stems song.it                 # + one wav per strip in out-stems/
duet --render out.wav --seconds 2:30 --fade 3 song.it # cap the length, fade the end
duet --render out.wav --bare song.it                  # the engines alone: no mixer
duet --render blk.wav --bounce-block 00:00-0F:1-2 --tail 1 project.zon
                                   # pattern 00, rows 00-0F (hex), channels 1-2
                                   # (decimal), then one second of ring-out
```

The same render from a program of your own — `zig-out/bin/cplay -o
out.wav project.zon`, byte for byte — is [libduet](dev/libduet.md)'s.

Convert and round-trip:

```sh
duet --resave out.it song.it       # load and write back (an .it, .swm, .swi or .zon)
duet --export-swm out.swm project.zon   # the SID columns as a real SID-Wizard module
duet --save-project jam.zon kick.wav bass.swi   # a new project from loose files
```

Look inside:

```sh
duet --dump song.it                # header, samples, instruments
duet --dump-pat 3 song.it          # one pattern as text
duet --swi-dump bass.swi           # a SID-Wizard instrument's header and tables
duet --dump-screen --page mixer project.zon     # any page, as text
duet --dump-help                   # the key help, every page
duet-gui --gui-shot 60 shot.bmp --gui-keys "f4 down" project.zon
                                   # the window after those keys, as a picture
```

## Every option

<!-- docgen:cli-help -->
```text
  IMPULSE // SID TERMINAL TRACKER  ·  v0.1.0-alpha

usage: duet [files...] [options]
       duet-gui [files...] [options]     the same app in a window

files, by extension, in any order:
  song.it              Impulse Tracker module (IT is the only sample format)
  tune.swm             SID-Wizard module — alone, or co-playing beside an .it
                       (.sws/.swt/.swq, the 2/3/4-chip variants, load alike)
  inst.swi             SID-Wizard instrument (repeatable): COPIED into the S##
                       pool — beside an .swm, IMPORTED into its bank; either
                       way nothing stays linked to the file
  project.zon          a DUET project: its own song file plus every SID
                       instrument, chord table and synth patch, inside

  bare `duet` (no files) opens an empty song behind the DUET splash.

interactive:
  --play               start playback on launch (a tracker loads stopped)
  --page <p>           start screen. Pages: pattern|ins|swi|smp|chords|seed|
                       import|osc|proj|song|swmsong|tempo|mixer|mixfx|mixfx2|
                       viz|help|logo (swi/smp = the instrument/sample editor
                       focused; seed = the +I## picker; import = the
                       instrument lists, --import-src opens the picker over
                       them; osc = the scope band; tempo = the SWM SONG page
                       with the TEMPO pane focused; mixfx = the SENDS page,
                       mixfx2 = the FX units and their return strips).
                       Popups over a page, mostly for --dump-screen:
                       open|ptnlen|undo|export|bounce|pcm|newsw|savereport|
                       fxreport|clip|fx (fx = THE FX PICKER; --fx-list picks
                       which; clip = the SYSTEM CLIPBOARD list)
  --view <g>           co-play pattern grid: it|unity|poly|swm (^V cycles;
                       --swm-view = --view swm)
  --chan-view <c>      channel width: full|ins|note (^W cycles) — the narrow
                       views drop the volume/effect fields and fit more
                       channels on the screen
  --split / --no-split boot with the SID columns pinned / unpinned to the
                       right edge of the grid (pinned is the default; ^T
                       toggles)
  --ins-page <p>       boot inside the I## editor's sub-page:
                       gen|map|vol|pan|pit (implies --page ins)
  --dust-face <f>      boot inside a D## (DUST) patch's page:
                       voice|tables|mod|macro (implies --page ins; needs an
                       armed DUST slot)
  --dusk-face <f>      boot inside a K## (DUSK) patch's page:
                       voice|tables|mod|macro (implies --page ins; needs an
                       armed DUSK slot)
  --fx-list <l>        boot with THE FX PICKER up (implies --page fx):
                       letters|s|vol (a channel) · sw|swnote|swins|swvib
                       (a SID column or track) · duet (the four sends, a-d) ·
                       dust|dusts (a DUST column) · dusk|dusks (a DUSK
                       column) · modsrc|moddst (DUST's mod matrix, over the
                       D## editor) · dusksrc|duskdst (DUSK's, over the K##)
  --import-src <m>     boot with THE IMPORT's picker up over that
                       .swm/.sws/.swt/.swq's bank — or an .it's samples,
                       or a .zon's patches (implies --page ins)
  --viz <m>            visualizer mode, implies --page viz:
                       vu|spectrum|duo|scope|copper|plasma
  --bars <s>           VU/SPECTRUM bar style: normal|scanlines|gap
  --keys <file.zon>    key layout (default: the Impulse Tracker layout;
                       ~/.config/duet/keys.zon loads on its own; ^K reloads)
  --sid-channels <a[,b[,c]]>
                       bind pattern channels (1-based) to SID voices; the
                       instrument column there picks a loaded .swi by its
                       number (1-based)
  --swi-dir <path>     load every .swi in a directory (name-sorted)
  --sid-model <m>      force every chip's model: 6581|8580 (default: what
                       the file says; a DUST slot keeps its own)
  --sid-quality <q>    reSID sampling: fast|interpolate|resample
                       (default interpolate; a .zon may name one)
  --subtune <n>        SWM subtune to play, 0-based

headless:
  --render <out.wav>   offline render of .it / .swm / .zon (no audio device)
  --seconds <n|mm:ss>  length cap for --render and traces (default 600)
  --fade <n>           cos^2 fade over the render's last n seconds
  --bare               render the engines alone: no mixer, no saved SID mutes
  --stems              also write every mixer strip -> <out>-stems/
  --bounce-block <P:R0-R1[:C0-C1]>
                       render one block only: pattern and rows in HEX (the
                       grid's numbers), channels DECIMAL, 1-based (the
                       mixer's), all channels when omitted. Channels left
                       out are silent, as if muted.
  --tail <secs>        with --bounce-block: a note-off (===) on every
                       column at the block's end, then this much release
                       and effect ring-out (0 = exact cut)
  --swm-trace <out>    dump the SID-Wizard player's SID-register stream
  --dust-trace <out>   DUST's register stream, every write attributed to
                       its source (alone, or beside --render)
  --dusk-trace <out>   DUSK's note-engine event stream, attributed the
                       same way (alone, or beside --render)
  --resave <out.it>    load the .it, write it back through the saver
  --resave <out.swm>   same for a .swm (byte-identical for files SID-Wizard
                       saved)
  --resave <out.swi>   same for a .swi instrument
  --resave <out.zon>   same for a project (an old file comes out upgraded)
  --export-swm <out.swm>
                       the SID columns as a real SID-Wizard module
                       (instrument and effect bytes travel verbatim; the
                       number of chips picks .swm/.sws/.swt/.swq)
  --save-project <out.zon>
                       write the session as <out>.zon + <out>.it (bare, or
                       with .wav/.swi args = one-command project creation)
  --shot <n> <o.png>   render pixel/glow frame n to PNG (the visualizer
                       and the scope draw a synthesized signal here)
  --dump-screen        print the full UI text layer, then quit
  --dump-help          print every page of the in-app key help as text
                       (the built-in layout, or the --keys file)
  --bounce-state <s>   with --page bounce: running|preview|failed
  --export-state <s>   with --page export: setup|running|done
  --pcm-state <s>      with --page pcm: fresh|edited
  --clipboard-file <f> the system clipboard as a file: ALT+V's COPY writes
                       it, PASTE reads it (a test's clipboard; the machine's
                       own is untouched)
  --osc-state <s>      with --page osc: keys|chan|sid|dust|dusk (the source)
  --dump               print .it header / samples / instruments
  --dump-pat <n>       print pattern n as text
  --swi-dump           print parsed .swi headers + tables
  --sid-test [o.wav]   SID engine check (1x/2x/4x clock lanes)
  --dust-test [o.wav]  DUST: the default patch through a real slot
  --dusk-test [o.wav]  DUSK: the built-in patch through the built-in table
  --swi-test [o.wav]   SID-Wizard instruments through the player
  --audio-test         audio device + callback stats
  --bench              times each mix stage offline, in multiples of
                       real time, on one core
  -h, --help           this help

duet-gui only (the window, headless):
  --gui-shot <n> <out.bmp>
                       run the real session in a hidden window, save
                       frame n as a BMP — text colors included — and quit
  --gui-keys "<tokens>"
                       keys to feed first, through the real SDL translate
                       (tools/ptydrive.py's names: down cdown tab f5 ...;
                       zin/zout/zdef are the font-zoom chords)
  --gui-log            print every translated key

exit status:
  0 done · 1 a file could not be read, loaded, written or rendered
  · 2 a bad or missing argument (the first line says which)
```
<!-- /docgen -->
