⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filters.cpp

📁 DVD工具dvdsynth的源码
💻 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 + -