📄 filters.cpp
字号:
/***********************************************************************
Copyright 2002 Ben Rudiak-Gould.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
or visit <http://www.gnu.org/copyleft/gpl.html>.
***********************************************************************/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include "../include/dvdsynth-filter.h"
#include "resource.h"
HINSTANCE g_hinstance;
DvsDockingBayGlobal* g_callbacks;
struct Filter {
DvsFilterGlobal* funcs;
Filter* next;
};
Filter* all_filters;
struct FilterInstance {
DvsDeviceUser* dev;
FilterInstance* next;
};
struct FilterDialog {
Filter* active_filters;
Filter* all_filters;
void Init(HWND hwnd);
void Add(HWND hwnd);
void Remove(HWND hwnd);
void MoveUpDown(HWND hwnd, bool down);
Filter** GetSelectedActiveFilter(HWND hwnd, bool one_prev);
};
bool Includes(Filter* list, DvsFilterGlobal* filter) {
for (Filter* f = list; f; f = f->next)
if (f->funcs == filter)
return true;
return false;
}
void FilterDialog::Init(HWND hwnd) {
Filter* f;
HWND active_list = GetDlgItem(hwnd, IDC_ACTIVELIST);
for (f = active_filters; f; f = f->next) {
int index = ListBox_InsertString(active_list, 0, f->funcs->visible_name);
ListBox_SetItemData(active_list, index, f->funcs);
}
ListBox_InsertString(active_list, 0, "(raw device)");
HWND avail_list = GetDlgItem(hwnd, IDC_AVAILLIST);
for (f = all_filters; f; f = f->next) {
if ((f->funcs->flags & DVDSYNTH_FILTER_ONLY_ONE) && Includes(active_filters, f->funcs)) {
// filter already in list; no action
} else {
int index = ListBox_AddString(avail_list, f->funcs->visible_name);
ListBox_SetItemData(avail_list, index, f->funcs);
}
}
}
void FilterDialog::Add(HWND hwnd) {
HWND active_list = GetDlgItem(hwnd, IDC_ACTIVELIST);
HWND avail_list = GetDlgItem(hwnd, IDC_AVAILLIST);
int avail_index = ListBox_GetCurSel(avail_list);
if (avail_index == LB_ERR) return;
DvsFilterGlobal* filter = (DvsFilterGlobal*)ListBox_GetItemData(avail_list, avail_index);
if (filter->flags & DVDSYNTH_FILTER_ONLY_ONE)
ListBox_DeleteString(avail_list, avail_index);
int active_index = ListBox_AddString(active_list, filter->visible_name);
ListBox_SetItemData(active_list, active_index, filter);
Filter* f = new Filter;
f->funcs = filter;
f->next = active_filters;
active_filters = f;
}
void FilterDialog::Remove(HWND hwnd) {
HWND active_list = GetDlgItem(hwnd, IDC_ACTIVELIST);
HWND avail_list = GetDlgItem(hwnd, IDC_AVAILLIST);
int active_index = ListBox_GetCurSel(active_list);
if (active_index == LB_ERR || active_index == 0) return;
int pos = ListBox_GetCount(active_list) - 1;
Filter** pf = &active_filters;
while (pos > active_index && *pf != 0) {
pf = &(*pf)->next;
--pos;
}
Filter* f = *pf;
DvsFilterGlobal* filter = (DvsFilterGlobal*)ListBox_GetItemData(active_list, active_index);
if (f == 0 || f->funcs != filter)
return;
ListBox_DeleteString(active_list, active_index);
*pf = f->next;
delete f;
if (filter->flags & DVDSYNTH_FILTER_ONLY_ONE) {
int avail_index = ListBox_AddString(avail_list, filter->visible_name);
ListBox_SetItemData(avail_list, avail_index, filter);
}
}
Filter** FilterDialog::GetSelectedActiveFilter(HWND hwnd, bool one_prev) {
HWND active_list = GetDlgItem(hwnd, IDC_ACTIVELIST);
int active_index = ListBox_GetCurSel(active_list);
if (active_index <= 0) return 0;
active_index += one_prev;
int pos = ListBox_GetCount(active_list) - 1;
if (active_index > pos) return 0;
Filter** pf = &active_filters;
while (pos > active_index && *pf != 0) {
pf = &(*pf)->next;
--pos;
}
Filter* f = *pf;
DvsFilterGlobal* filter = (DvsFilterGlobal*)ListBox_GetItemData(active_list, active_index);
if (f == 0 || f->funcs != filter)
return 0;
return pf;
}
void FilterDialog::MoveUpDown(HWND hwnd, bool down) {
Filter** pplower = GetSelectedActiveFilter(hwnd, down);
if (!pplower) return;
Filter* plower = *pplower;
Filter* pupper = plower->next;
if (!pupper) return;
HWND active_list = GetDlgItem(hwnd, IDC_ACTIVELIST);
int active_index = ListBox_GetCurSel(active_list);
int inactive_index = active_index + (down ? +1 : -1);
DvsFilterGlobal* other_filter = (DvsFilterGlobal*)ListBox_GetItemData(active_list, inactive_index);
ListBox_DeleteString(active_list, inactive_index);
ListBox_InsertString(active_list, active_index, other_filter->visible_name);
ListBox_SetItemData(active_list, active_index, other_filter);
*pplower = pupper;
plower->next = pupper->next;
pupper->next = plower;
}
BOOL CALLBACK FilterSelectDialogProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
if (msg == WM_INITDIALOG) {
SetWindowLong(hwnd, DWL_USER, (LONG)lparam);
((FilterDialog*)lparam)->Init(hwnd);
return TRUE;
} else if (msg == WM_COMMAND) {
FilterDialog* fd = (FilterDialog*)GetWindowLong(hwnd, DWL_USER);
switch (LOWORD(wparam)) {
case IDOK:
EndDialog(hwnd, 0);
return TRUE;
case IDC_ADD:
fd->Add(hwnd);
return TRUE;
case IDC_REMOVE:
fd->Remove(hwnd);
return TRUE;
case IDC_MOVEUP:
fd->MoveUpDown(hwnd, false);
return TRUE;
case IDC_MOVEDOWN:
fd->MoveUpDown(hwnd, true);
return TRUE;
}
}
return FALSE;
}
void FilterSelectDialog(Filter** currently_selected, Filter* all_filters) {
FilterDialog fd = { *currently_selected, all_filters };
DialogBoxParam(g_hinstance, MAKEINTRESOURCE(IDD_FILTERS), NULL, FilterSelectDialogProc, (LPARAM)&fd);
*currently_selected = fd.active_filters;
}
class MyDevice : public DvsDeviceUser {
FilterInstance* filter_instances; // last in list is actual device
static Filter* active_filters;
void Hook(Filter* f, DvsDeviceUser* user, DvsDeviceKernel** pkernel, DvsDockingBay* bay);
static void StaticAddDeviceMenuItems(DvsDeviceUser* self, DvsMenu* menu);
static int StaticQueryUnplug(DvsDeviceUser* self);
static void StaticDelete(DvsDeviceUser* self);
public:
MyDevice(DvsDeviceUser* user, DvsDeviceKernel** pkernel, DvsDockingBay* bay);
};
Filter* MyDevice::active_filters = 0;
void AddDeviceMenuItems(FilterInstance* i, DvsMenu* menu) {
if (i->next)
AddDeviceMenuItems(i->next, menu);
if (i->dev->vtable->AddDeviceMenuItems)
i->dev->vtable->AddDeviceMenuItems(i->dev, menu);
}
void MyDevice::StaticAddDeviceMenuItems(DvsDeviceUser* self, DvsMenu* menu) {
AddDeviceMenuItems(((MyDevice*)self)->filter_instances, menu);
}
int MyDevice::StaticQueryUnplug(DvsDeviceUser* self) {
int result = 0;
for (FilterInstance* i = ((MyDevice*)self)->filter_instances; i; i = i->next) {
if (i->dev->vtable->QueryUnplug) {
result = i->dev->vtable->QueryUnplug(i->dev);
if (result < 0)
break;
}
}
return result;
}
void MyDevice::StaticDelete(DvsDeviceUser* self) {
FilterInstance* i = ((MyDevice*)self)->filter_instances;
while (i) {
if (i->dev->vtable->Delete)
i->dev->vtable->Delete(i->dev);
FilterInstance* j = i->next;
delete i;
i = j;
}
delete ((MyDevice*)self);
}
void MyDevice::Hook(Filter* f, DvsDeviceUser* user, DvsDeviceKernel** pkernel, DvsDockingBay* bay) {
if (!f)
return;
Hook(f->next, user, pkernel, bay);
DvsDeviceUser* old_user_device = filter_instances->dev;
DvsDeviceUser* new_user_device = f->funcs->HookDevice(pkernel, bay);
if (new_user_device != 0 && new_user_device != old_user_device) {
FilterInstance* fi = new FilterInstance;
fi->next = filter_instances;
fi->dev = new_user_device;
filter_instances = fi;
}
}
MyDevice::MyDevice(DvsDeviceUser* user, DvsDeviceKernel** pkernel, DvsDockingBay* bay) {
static DvsDeviceUser_vtable vt = {
StaticAddDeviceMenuItems,
StaticQueryUnplug,
StaticDelete
};
vtable = &vt;
FilterSelectDialog(&active_filters, all_filters);
filter_instances = new FilterInstance;
filter_instances->next = 0;
filter_instances->dev = user;
Hook(active_filters, user, pkernel, bay);
}
class MyDockingBay : public DvsDockingBay {
DvsDockingBay* child;
public:
MyDockingBay(DvsDockingBay* _child) {
child = _child;
static DvsDockingBay_vtable vt = {
StaticSetHandlers,
StaticRequestUnplug,
StaticSharedPool_Alloc,
StaticGetScsiID,
StaticGetDriveLetters
};
vtable = &vt;
}
void SetHandlers(DvsDeviceUser* user_handler, DvsDeviceKernel* kernel_handler) {
DvsDeviceUser* my_user_handler = new MyDevice(user_handler, &kernel_handler, child);
child->vtable->SetHandlers(child, my_user_handler, kernel_handler);
}
void RequestUnplug() {
child->vtable->RequestUnplug(child);
}
void* SharedPool_Alloc(unsigned len) {
return child->vtable->SharedPool_Alloc(child, len);
}
int GetScsiID() {
return child->vtable->GetScsiID(child);
}
unsigned GetDriveLetters() {
return child->vtable->GetDriveLetters(child);
}
static void StaticSetHandlers(DvsDockingBay* self, DvsDeviceUser* user_handler, DvsDeviceKernel* kernel_handler) {
((MyDockingBay*)self)->SetHandlers(user_handler, kernel_handler);
}
static void StaticRequestUnplug(DvsDockingBay* self) {
((MyDockingBay*)self)->RequestUnplug();
}
static void* StaticSharedPool_Alloc(DvsDockingBay* self, unsigned len) {
return ((MyDockingBay*)self)->SharedPool_Alloc(len);
}
static int StaticGetScsiID(DvsDockingBay* self) {
return ((MyDockingBay*)self)->GetScsiID();
}
static unsigned StaticGetDriveLetters(DvsDockingBay* self) {
return ((MyDockingBay*)self)->GetDriveLetters();
}
};
struct DvsDockingBay* HookDockingBay(DvsDockingBay* original_docking_bay) {
return new MyDockingBay(original_docking_bay);
}
void LoadPlugins() {
WIN32_FIND_DATA wfd;
HANDLE h = FindFirstFile("*.dll", &wfd);
if (h != INVALID_HANDLE_VALUE) {
do {
HMODULE hmod = LoadLibrary(wfd.cFileName);
if (hmod != NULL) {
typedef DvsFilterGlobal* __cdecl DFPE_func(DvsDockingBayGlobal*);
DFPE_func* DvdsynthFilterPluginEntry = (DFPE_func*)GetProcAddress(hmod, "DvdsynthFilterPluginEntry");
if (DvdsynthFilterPluginEntry) {
DvsFilterGlobal* plugin = DvdsynthFilterPluginEntry(g_callbacks);
for (; plugin; plugin = plugin->next) {
Filter* f = new Filter;
f->next = all_filters;
f->funcs = plugin;
all_filters = f;
}
} else {
FreeLibrary(hmod);
}
}
} while (FindNextFile(h, &wfd));
FindClose(h);
}
}
DvsDeviceGlobal plugin_functions = {
0,
0,
0,
HookDockingBay
};
extern "C"
DvsDeviceGlobal* __cdecl DvdsynthDevicePluginEntry(DvsDockingBayGlobal* callbacks) {
if (g_callbacks == 0) {
g_callbacks = callbacks;
LoadPlugins();
}
return &plugin_functions;
}
extern "C"
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD, LPVOID) {
g_hinstance = hinst;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -