Capture and Record
WinDV’s main interface is a single resizable dialog with a tab control that switches between Capture and Record modes.
Dialog Layout
CDVToolsDlg is the application’s only top-level window, derived from
CDialog.
There is no document/view pattern and no frame window.
The dialog is resizable; the initial size sets the minimum size constraint.
The dialog contains one instance of CDV (the m_video member) mapped
to the IDC_VIDEO picture control.
CDV inherits CStatic, so it is a legitimate child window that can host
the preview renderer as a grandchild window.
Key Controls
| Control ID | Type | Purpose |
|---|---|---|
IDC_VIDEO |
CDV (CStatic) |
Preview window host |
IDC_TOOL_TAB |
CToolTab |
Owner-draw tab control |
IDC_VSRC |
Static text | Current capture source device name |
IDC_VSRC_SEL |
Button | Opens device selection dialog |
IDC_FDST |
CDropFilesEdit |
Capture destination filename base |
IDC_FDST_SEL |
Button | Opens file browse dialog |
IDC_FSRC |
CDropFilesEdit |
Record source file list |
IDC_FSRC_SEL |
Button | Opens multi-file browse dialog |
IDC_VDST |
Static text | Current record destination device name |
IDC_VDST_SEL |
Button | Opens device selection dialog |
IDC_CAPTURE |
Button | Toggle capture start/pause |
IDC_RECORD |
Button | Toggle record start/pause |
IDCANCEL |
Button | Cancel / reset to idle |
IDC_CONFIG |
Button | Opens configuration property sheet |
IDC_DVCTRL |
Checkbox | Enable/disable tape transport control |
IDC_STATUS |
Static text | Primary status message |
IDC_STATUS2 |
Static text | DV recording timestamp display |
IDC_STATUS3 |
Static text | Queue fill level display |
IDC_COUNTER |
Static text | Elapsed capture/record time |
IDC_PICTURE |
Button | Logo (clicking opens About dialog) |
CDropFilesEdit is a CEdit subclass that accepts file-drop events.
For IDC_FSRC (multi-file record source) a " | " separator is used
between filenames.
For IDC_FDST (single-file capture destination) a transform callback
CaptureFilenameExtractBase() strips the extension so the field always
shows only the base name.
Tab Control and Mode Switching
IDC_TOOL_TAB is a CToolTab (owner-draw) with two items:
| Tab index | Label | Mode |
|---|---|---|
| 0 | “Video Capture” | Capture (FireWire to AVI) |
| 1 | “Video Recording” | Record (AVI to FireWire) |
Tab-change Mechanics
TCN_SELCHANGE on the tab control routes to OnSelchangeToolTab(), which:
- Reads
m_toolTab.GetCurSel(). - For each control in
ctrlProperties[], callsShowWindow(SW_SHOW or SW_HIDE)based on whether(1 << sel) & tabMaskis non-zero. - Calls
InitVideo()to rebuild the pipeline for the newly active tab.
InitVideo() for tab 0 calls CDV::BuildCapturing() (live preview begins
immediately).
InitVideo() for tab 1 calls CDV::Destroy() and displays a prompt.
Pressing the Cancel button or Escape also calls InitVideo(), which resets
the pipeline to the idle/paused state for the active tab rather than
closing the dialog.
The default CDialog::OnCancel() behaviour (close dialog) is suppressed.
Tab Item Sizing
SetToolTabItemSize() recalculates the width of each tab item so that
all items together fill the tab control width with a half-item gutter on
each side:
itemWidth = tabControlWidth * 2 / (itemCount * 2 + 1)
This is called from both OnInitDialog() and OnSize() so the tabs
resize with the dialog.
Proportional Resize System
All controls in the dialog resize proportionally as the user drags the
window borders.
The system uses a static array of CtrlProperties structures defined at
the top of DVToolsDlg.cpp:
static struct CtrlProperties {
int id; // control resource ID
int dx, dw; // horizontal left-edge and right-edge percentage anchors
int dy, dh; // vertical top-edge and bottom-edge percentage anchors
int tabMask; // which tabs show this control
} ctrlProperties[] = { ... };
How the Percentages Work
When OnSize(cx, cy) fires:
deltaX = cx - m_originalRect.right (change from initial width)
deltaY = cy - m_originalRect.bottom (change from initial height)
For each control, the new position is computed as:
new_left = originalLeft + (dx * deltaX) / 100
new_top = originalTop + (dy * deltaY) / 100
new_width = originalWidth + ((dw - dx) * deltaX) / 100
new_height = originalHeight + ((dh - dy) * deltaY) / 100
dx and dy anchor the control’s leading edges;
dw and dh anchor the trailing edges.
-
dx = 0: left edge is fixed (left-anchored). -
dx = 100: left edge tracks the right side (right-anchored, fixed width). -
dw = 100, dx = 0: control stretches full width. -
dy = 100, dh = 100: control is anchored to the bottom.
Two named percentage constants are defined to describe the layout zones:
#define XL 25 // left zone boundary (25% from left)
#define XR 75 // right zone boundary (75% from left, or 25% from right)
Layout Table (Selected Controls)
| Control | dx | dw | Behaviour |
|---|---|---|---|
IDC_VIDEO |
0 | 100 | Fills entire client area width |
IDC_TOOL_TAB |
XL=25 | XR=75 | Centred band; narrows as dialog widens |
| Device/file labels | XL | XL | Fixed-width, pinned to 25% mark |
| Device/file edits | XL | XR | Stretch between 25% and 75% marks |
| Buttons (sel, cfg, action) | XR | XR | Pinned to 75% mark, fixed width |
IDC_STATUS |
XL | XR | Full-width status stretches with dialog |
IDC_COUNTER, status2/3 |
XR | XR | Pinned to right |
All controls use dy = 100, dh = 100 so their vertical positions track
100% of the height change, keeping them pinned to the bottom of the dialog.
Status Display and Timer Updates
A 200 ms WM_TIMER (timer ID 1) is started by SetTimer(1, 200, NULL)
when the pipeline becomes active and stopped by KillTimer(1) in
InitVideo().
OnTimer() performs two jobs:
Auto-exit check:
If m_exitOnFinish is set (from the -exit command-line flag) and the
pipeline has reached CDV::Finished, OnClose() is called immediately.
Status label updates (only when the text changes to avoid repaints):
| Label | Content |
|---|---|
m_status (IDC_STATUS) |
Pipeline state; appends dropped-frame count |
m_status2 (IDC_STATUS2) |
DV timestamp as DD.MM.'YY HH:MM:SS |
m_counter (IDC_COUNTER) |
Elapsed time as H:MM:SS.t |
m_status3 (IDC_STATUS3) |
Queue fill level; during capture also shows DV error count and percentage |
During active capture (CDV::Capturing), m_status3 shows the queue
load together with the current DV error statistics:
Q:N E:N/X.X%
where N (first) is the queue slot count, N (second) is the number of
frames with at least one video error, and X.X% is the error rate.
The error portion is omitted when no errors have been detected yet.
The elapsed time conversion:
REFERENCE_TIME t = m_video.GetTime(); // 100-ns units
t /= 1000000; // -> tenths of a second
int ss = (int)(t % 10); t /= 10;
int s = (int)(t % 60); t /= 60;
int m = (int)(t % 60); t /= 60;
txt2.Format("%d:%02d:%02d.%01d", (int)t, m, s, ss);
SetThreadExecutionState(ES_DISPLAY_REQUIRED) is called in OnTimer() to
prevent the monitor from blanking during active capture or recording
sessions.
Custom Window Messages
WinDV defines several WM_USER-based messages for cross-thread
notification.
All are declared in DShow.h and routed via ON_MESSAGE entries in
CDVToolsDlg’s message map.
| Message | Value | Sender | Handler |
|---|---|---|---|
WM_DV_TIMECHANGE |
+201 |
Capturing | OnDVTimeChange |
WM_DV_LOWDISKSPACE |
+202 |
Capturing | OnDVLowDiskSpace |
WM_DV_SIGNALLOST |
+203 |
Capturing | OnDVSignalLost |
WM_DV_CHECK_COMPLETE |
+204 |
Capturing (post-capture) | OnDVCheckComplete |
OnDVTimeChange
Reads lParam as a time_t DV recording timestamp and updates
the m_status2 label.
OnDVLowDiskSpace (v1.2.6)
Posted by CapturingThread when GetDiskFreeSpaceEx() reports fewer
than 500 MB free on the capture destination drive.
lParam carries the remaining free space in megabytes.
The handler:
- Formats the string
"WARNING: Low disk space! X MB remaining"intom_status. - Calls
MessageBeep(MB_ICONEXCLAMATION)to produce an audible alert.
Capture continues; the handler does not stop or pause the pipeline. The warning is informational, allowing the user to decide whether to stop early.
OnDVSignalLost (v1.2.7)
Posted by CapturingThread when CDVQueue::GetWithTimeout() times
out without receiving a frame or an EOS marker, indicating the
FireWire signal was lost.
The handler:
- Sets
m_statusto"Signal lost - capture stopped.". - Calls
MessageBeep(MB_ICONEXCLAMATION).
The thread has already set the pipeline state to Finished before
posting the message, so no additional stop call is required from the
dialog.
OnDVCheckComplete (v1.6.0)
Posted by CapturingThread after the post-capture phase (AVI integrity
check + SHA-256 + CSV log) completes.
wParam is non-zero if the AVI check passed, zero if problems were found.
The handler reads CDV::GetLastCheckResult() and CDV::GetErrorStats()
to build an extended status bar message:
AVI OK: N frames, PAL | DV: error-free
AVI OK: N frames, NTSC | DV errors: M frames (X.X%), worst: #F (N STA),
audio: A frames [C CRITICAL]
AVI problem: <reason> | DV errors: ...
If the AVI check failed, MessageBeep(MB_ICONWARNING) is called.
The full check result is available via CDV::GetLastCheckResult() for
programmatic access (e.g., from the CLI check command).
Configuration Dialogs
The configuration button (IDC_CONFIG) opens a CPropertySheet with
two pages:
CCaptureCfg
Exposes:
- AVI type radio button (Type 1 / Type 2)
- Discontinuity threshold (seconds)
- Maximum frames per file
- Frame decimation factor (
EveryNth) - Date/time format string (with history combo)
- Sequence digit count
- Auto-stop on signal loss (
IDC_CHK_AUTOSTOP, timeout in seconds) -
SHA-256 checksum (
IDC_CHK_SHA256) – when checked, asha256sum-compatible sidecar file (.sha256) is written next to each captured AVI file after the post-capture phase completes. ControlsCDV::m_enableSHA256.
CRecordCfg
Exposes:
- AVI prefix list (pipe-delimited paths played before main file list)
- AVI suffix list (pipe-delimited paths played after main file list)
- Preview checkbox (enable/disable preview during recording)
The property sheet is created with PSH_NOAPPLYNOW because settings
take effect only when a new pipeline is built.
Live application would require a graph rebuild, which is not implemented.
Changes made in the dialog are copied back to CDV and the CDVToolsDlg
member variables only when the user confirms with OK.
Supporting Controls
CToolTab
CToolTab is a CTabCtrl subclass that overrides DrawItem() to draw
tab items using the owner-draw style.
It provides consistent styling across Windows versions without requiring
visual styles.
CDropFilesEdit
CDropFilesEdit is a CEdit subclass that registers as a drop target
and handles WM_DROPFILES.
It accepts a separator string (for multi-file mode) and an optional
transform callback.
For IDC_FSRC (Record source):
- Separator:
" | " - Transform: none
- Multiple files dropped are joined with the separator.
For IDC_FDST (Capture destination):
- Separator:
""(single file) - Transform:
CaptureFilenameExtractBasestrips the extension so only the base path is stored.
CVideoDeviceSel
A simple CDialog subclass that shows a list box populated with device
friendly names returned by GetVideoSrcList() or GetVideoDstList().
Returns the selected index via GetSelection().