hotkeys_missing_lines writes the shipped default of an action the file does not mention, but that
save records the hash of what it wrote, so the file was not reloaded and the action stayed unbound
until the file next changed. The bindings installed at startup and on reload now include those
defaults (hotkeys_with_missing_defaults), as in Ex4 1.47.2; a file of an older version still gets
"none". A logger test covers it.
The search box takes the keyboard on the next frame, its window brought to the front and its text
selected, so typing replaces the query. It is focus_search in [hotkeys] (Cmd-F on macOS), and it
acts while typing in another field, such as the Import window's. View mode has no search box.
mcap.exe FILE, with FILE first (as Explorer's Open with passes it), opens an .mcap, image, video or
.snagx (app/open_file.jai). With no mcap running, the app starts as usual: an .mcap in the library
opens in the Capture window, anything else in the Opened File window, which says where the library
has it already (by its hash in .import-index) or imports it into the library folder typed or chosen.
With mcap running, a second window opens in view mode: the file alone, with Import, and Open in mcap
/ Show in mcap, which hand it to the running copy (a new Open_File message) and close the view. The
library is not loaded or watched, no model loads, and it has no tray icon, no global hotkeys, and
writes no settings or layout.
Import takes a single file as its source too (and -import FILE DEST); an .mcap is copied in as it is,
while a folder's import still skips them. -open-import DEST imports the opened file as its Import
button does, then exits.
-h and --help open a Command Line window listing the options, also toggled from the Debug Panel; with
mcap running, that one comes forward with it (a Show_Help message).
Thumbnails: the "First preview shown" log line, put between creating a preview's texture and its
else, had every preview after the first marked failed. Once its texture was released (scrolled far
away, or the switch from WARP to the GPU at startup) it was never decoded again and showed "Cannot
read".
The selected capture is the one outlined in the grid and shown in the Capture window. Its image is
copied as the Capture window shows it, decoded on a thread of its own and put on the clipboard as
screen captures are (Windows only so far); its path is copied as the system writes paths. Both are
actions in [hotkeys] (copy_image, copy_path), which do not act while typing in the search box.
Settings files at the current version get their default bindings at the next start; the comment
saying to raise APP_USER_SETTINGS_VERSION for a new action had it backwards.
- System sound: on / off (red while on) turns what the computer plays on and off while
recording, as Mic does the microphone; its state is saved as system_audio in [video].
- modules/Screen_Record: the microphone's switch is now one for either source:
record_set_audio, record_audio_on and record_audio_failed take an Audio_Source_Kind, and the
audio thread opens and closes each as it is turned on and off.
- record-probe -system-toggle. With -sync-test, system sound on at 3 s and off at 7 s keeps only
the beeps at 3 and 5 s (8-12 ms from their flashes), and the track runs the whole recording.
- The toolbar's Mic: on / off (red while on) turns the microphone on and off while recording;
its state is saved as microphone in [video] for the next recording. A microphone that cannot
be opened turns it off again, with a toast saying why.
- modules/Screen_Record: record_set_microphone, record_microphone, record_microphone_failed. The
audio thread opens the microphone only while it is on (so Windows shows it in use only then)
and closes it when turned off. Record_Options.audio_track gives the MP4 a sound track whatever
is on at the start, silent while nothing is, as one cannot be added once the header is
written; the app always asks for it. The sources heard and the failures are kept as they
happen, not only at the start.
- record-probe -mic-toggle: the microphone on at 3 s and off at 7 s. With system sound and with
nothing else on, the track runs the whole recording without a break.
- modules/Screen_Record/audio_source.jai: WASAPI, in loopback from the default output device
(what the computer plays) and from the default input device (the microphone), asked for as
48 kHz stereo float, which Windows converts any device to; a device that will not convert is
taken as it is when it gives 48 kHz float. Packets carry the time they were heard. A device
lost (unplugged, default changed) is opened again from the new default once a second.
- An audio thread mixes them onto the video's own timeline: the same time 0, less the same
pauses (record_pause now keeps one account of time paused for both threads). A packet within
30 ms of where its source left off follows on exactly; a source that sends nothing is silence,
passed 200 ms late. Each 1024 samples every source has covered become an AAC frame.
- encoder.jai: an AAC stream (FFmpeg's aac, 160 kb/s) beside the video, written from the audio
thread; both threads' packets meet in the file under a lock. The remux keeps it.
- [video] system_audio (true) and microphone (false). capture.json: Audio, AudioSources. A toast
when a source asked for could not be opened.
- record-probe: -audio system|mic|both, the sound read back (length, level), and -sync-test,
which flashes a white square and beeps together every 2 s, then finds both in the file.
- Measured: 20 s, beeps 0-21 ms from their flashes, no drift; both sources mixed, 5-18 ms;
a 6 s pause cuts the same 6 s from sound and video; 3 min, 85 of 90 beeps within 3-24 ms and
-14 ms from first to last, with 5 outliers (53-147 ms) where two beeps went missing. Tests:
an MP4 with sound keeps its AAC stream through the remux into the library (30 checks).
- src/app/screen_record_win32.jai: while recording, a red frame just outside the region (one
window shaped by a window region, clicks let through) and a toolbar beside it (below the
region at its right, else above, else inside a whole screen's top right): a blinking dot,
the time less time paused, the size, frames dropped and screen losses, and Pause/Resume,
Stop, and Discard, confirmed in the toolbar itself ("Yes, discard / No"). GDI windows that
never take the focus, kept out of every capture (WDA_EXCLUDEFROMCAPTURE). Buttons only ask;
screen_record_frame acts on the next frame. On the shutdown thread they are hidden, not
destroyed.
- modules/Screen_Record: record_pause; while paused the source is drained but nothing is sent,
and frames' times leave the pause out, so the video has no gap. Record_Stats.paused_seconds;
Record_Testing.LOSE_DUPLICATION loses Desktop Duplication every 3 s.
- Recordings left in %TEMP%/mcap by a crash are offered at startup: into the library (no window
known; size from its frames, date from its name), deleted, or later.
- [video] in settings.config: fps (1-120, 30), cursor (true), capture (auto, dxgi, wgc); written
into existing files on the next launch.
- The Win32 GDI bindings move to src/base/platform/win32_gdi_bindings.jai, shared by the overlay
and the toolbar.
- -record-region X Y W H and -record-ui-visible for -record; -pause SECONDS and -lose for
record-probe. capture.json's Paused.
- Checked: the toolbar is not in a whole-screen recording's frame; a 10 s pause leaves a 6.2 s
video of a 16 s run at a steady 30 fps (DXGI and WGC); 3 simulated losses in 10 s recover with
no gap. Tests: a leftover's date and its write (22 checks in the recording group); all pass.
- Fixed on the way: a recording's path repeated the temporary folder ("%1" is the first argument).
- record_region, a new [global_hotkeys] action on Ctrl-PrintScreen (Windows only; none on
macOS): starts a recording, or stops the one running.
- The overlay's video mode (screen_capture_win32.jai): red outline and magnifier; the drag held
to the screen it began on; under 240 x 180 (record_size_allowed, in Screen_Record) the outline
is dashed, the label gives the minimum, and letting go takes nothing; a click or Enter takes
the whole screen; no pixels copied. With immediate, no overlay at all: the screen under the
cursor, for PrintScreen while recording.
- src/app/screen_record.jai: records with modules/Screen_Record to %TEMP%/mcap at 30 fps; a
recording that stops by itself keeps what it has, as does quitting (the shutdown step stops it).
The MP4 goes into the library through the stills' jobs: a video .mcap in Screen Captures, the
MP4 its original, a frame of it its rendered image, metadata.json as a still's, capture.json
with Duration, FrameRate, VideoCodec, PosterTime, Encoder, Capture and DroppedFrames; the MP4 is
deleted once it is in. The catalog reads a video's keys from capture.json too.
- The capture thread makes itself aware of each monitor's DPI: ImGui makes only the main thread
aware, and Desktop Duplication refused the app's capture thread with DXGI_ERROR_UNSUPPORTED
(the fallback recorded with Windows.Graphics.Capture, and the log said so).
- -record SECONDS records the screen under the cursor, puts it in the library and exits;
-record-quit quits while recording instead. Both pass on a scratch library.
- Tests: a "screen recording" group (the size rule; an MP4 from the module's encoder written as a
recording reads back, and the catalog takes it as a video). The segment overlay test no longer
depends on the colours chosen in the app's own data folder.
- README, the format's README and the plan describe it.
- capture_region, a new [global_hotkeys] action, on PrintScreen by default (Windows only; none on
macOS). Existing settings files get the line appended on the next launch. When the key cannot be
registered, the log names Snagit and Windows' "Print screen opens screen capture" setting.
- app/screen_capture_win32.jai: every screen copied the moment the key fires (BitBlt with
CAPTUREBLT over the virtual desktop), shown darkened in a topmost GDI window in a modal loop of its
own, so it works with mcap hidden in the tray. Dragging shows the region bright and outlined; a
magnifier shows the pixels under the cursor with its position or the selection's size; arrow keys
move a pixel (ten with Shift). A click or Enter takes the whole screen under the cursor; Escape,
a right click or losing the focus cancels. Only the parts that change are redrawn.
- app/screen_capture.jai: the region goes on the clipboard (CF_DIB) at once, then a thread writes it
into the library's "Screen Captures" folder as a PNG .mcap: metadata.json with the window under
the region's middle (its title as WindowName, its program's description as AppName) and
capture.json (where on the desktop, the program's path, the hash). mcap then comes to the front
showing it, and OCR, labels and segmentation read it as they read an import.
- A "screen capture" group in the import tests: the file written, its pixels, preview and Capture
Text read back. README and the format's README describe it.
- The exit overlay says which step of shutdown is running and what it waits on ("Stopping the OCR
scan: finishing the text lines it is reading.", the import, the viewer, the models), and how long
that step has taken once it passes 2 s. It said "Saving..." for all of it.
- OCR stops mid-batch: ocr_process takes a cancel flag (Ocr_Engine.cancel), checked by its workers
before each piece of work; a scan sets it to its own cancel. A cut-short batch stores nothing and
counts no failures. Closing during a scan took minutes when a batch held large images; now well
under a second.
- Once shutdown starts, the main thread stops running the app's frames (the viewer, search, import,
OCR, Stats) and draws only the overlay: background_frame read the search thread group while the
shutdown thread was tearing it down, an access violation on exit.