videofilt_vdxframe_addingconfigurability - shekh/VirtualDub2 GitHub Wiki
VirtualDub Plugin SDK 1.2
Adding configurability
Once the basic structure is in place, interesting filters need some sort of configurability. VDXFrame also has wrappers to make this easier. As usual, these are optional and you can use another UI library with the filter base class.
One of the side effects of making it easier to add instance data to a filter is that the filter class itself is likely to contain fields that are not related to configuration parameters. To make writing the configuration UI easier, it's recommended that the configuration data be split off into a separate structure:
struct MyFilterConfig {
int mBrightness;
int mContrast;
MyFilterConfig()
: mBrightness(0)
, mContrast(100)
{
}
};
Doing this makes it more likely that either the structure can be copied as-is, or that it is easier to write the copy constructor and assignment operators.
Once the configuration structure is lifted out into a separate class,
the dialog class can be created. This is done by deriving from
VDXVideoFilterDialog
:
class MyFilterDialog : public VDXVideoFilterDialog {
public:
MyFilterDialog(MyFilterConfig& config, IVDXFilterPreview *ifp) : mConfig(config), mpPreview(ifp) {}
bool Show(VDXHWND parent) {
return 0 != VDXVideoFilterDialog::Show(NULL, MAKEINTRESOURCE(IDD_FILTER_CONFIG), (HWND)parent);
}
virtual INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam);
protected:
MyFilterConfig& mConfig;
IVDXFilterPreview *mpPreview;
};
INT_PTR MyFilterDialog::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) {
return FALSE;
}
Sadly, this is as much as VDXVideoFilterDialog will for you, as you will still have to write Win32 dialog code. However, the base class takes care of wrapping and unwrapping the this pointer, making the rest easier. You can extend the base class with additional methods to add common message handlers.
Now that the dialog is created, the Configure()
method can be added to
the filter class:
bool MyFilter::Configure(VDXHWND hwnd) {
MyFilterConfig oldConfig(mConfig);
MyFilterDialog dlg(mConfig, fa->ifp);
if (dlg.Show(hwnd))
return true;
mConfig = oldConfig;
return false;
}
The copying of the configuration object in and out may seem unnecessary, but this allows the dialog and the filter to share the same configuration structure so that the dialog can update the filter for live previews. It also means that the dialog class doesn't have to worry about rolling back the changes to the configuration object.
An additional advantage of this split structure between the filter,
dialog, and configuration objects is that it allows the
platform-dependent dialog code to be isolated in a different module, if
desired. The VDXHWND
type makes this easier.
Note that there is a gotcha involved with the VDXFrame implementation of
the Configure()
method: the VDXVideoFilterDefinition
template uses
an overload trick to determine if the filter class overloads
Configure()
. Therefore, a filter cannot "unimplement" the
Configure()
method by calling the base VDXVideoFilter::Configure()
method.
The stringProc and
stringProc2 methods of a filter
generate a short blurb for filter list UI. VDXVideoFilter consolidates
both of these into one method and provides a SafePrintf()
helper to
simplify its implementation:
void EmptyFilter::GetSettingString(char *buf, int maxlen) {
SafePrintf(buf, maxlen, " (%d)", mConfig.mBrightness);
}
Copyright (C) 2007-2012 Avery Lee.