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

📄 dvdsubber.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
   ++numerator;
   if ((numerator & 31) == (denominator & 31))
      compile_dialog->SetProgress(numerator, denominator);
}


inline int ScaledPixelClip(int x) {
   x = (x + 0x8000) >> 16;
   return (x<=0 ? 0 : x>=255 ? 255 : x);
}


int RGB2YVU(int rgb) {
   const int cyb = int(0.114*219/255*65536+0.5);
   const int cyg = int(0.587*219/255*65536+0.5);
   const int cyr = int(0.299*219/255*65536+0.5);
   // y can't overflow
   int y = (cyb*(rgb&255) + cyg*((rgb>>8)&255) + cyr*((rgb>>16)&255) + 0x108000) >> 16;
   int scaled_y = (y - 16) * int(255.0/219.0*65536+0.5);
   int b_y = ((rgb&255) << 16) - scaled_y;
   int u = ScaledPixelClip((b_y >> 10) * int(1/2.018*1024+0.5) + 0x800000);
   int r_y = (rgb & 0xFF0000) - scaled_y;
   int v = ScaledPixelClip((r_y >> 10) * int(1/1.596*1024+0.5) + 0x800000);
   return (y*256+v)*256+u;
}


int  SubpictureReceiver::ColorLookup(unsigned rgb) {
   unsigned yvu = RGB2YVU(rgb);
   int i;
   for (i = 0; i < k->palette_size; ++i) {
      if (k->palette[i] == yvu)
         break;
   }
   if (i >= k->palette_size) {
      if (i >= 16) {
         return -1;
      }
      k->palette[k->palette_size++] = yvu;
   }
   return 15 - i;
}

void SubpictureReceiver::SetVTSNumber(int vts_number) {
   if (got_title)
      throw "Only one <vts> command allowed";
   got_title = true;
   if (vts_number < 1 || vts_number > int(k->disc_info->num_title_sets))
      throw "VTS number out of range";
   k->title = vts_number - 1;
}

void SubpictureReceiver::SetAngle(int _angle) {
   if (got_angle)
      throw "Only one <angle> command allowed";
   got_angle = true;
   angle = _angle;
}


bool SubpictureReceiver::ReadSector(unsigned lba, unsigned char* buf) {
   static unsigned char cdb[10] = { 0x28, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
   for (int i=0; i<4; ++i) {
      cdb[5-i] = lba >> (i*8);
   }
   unsigned long buflen = 2048;
   SenseData sense;
   return SCSIRESULT_SUCCESS == g_bays->KernelScsiCommand(k->child, cdb, 10, buf, &buflen, 1, &sense);
}

void SubpictureReceiver::GrowMap() {
   map_len *= 2;
   unsigned char* new_map = new unsigned char[map_len];
   memcpy(new_map, map_data, map_pos);
   delete[] map_data;
   map_data = new_map;
}

void SubpictureReceiver::AddVOBU(unsigned lba, unsigned vobu_number, unsigned num_fields, unsigned num_data_blocks) {
   if (num_fields < 60 && num_data_blocks < 0x400) {
      if (map_pos > map_len - 2) {
         GrowMap();
      }
      map_data[map_pos] = (num_fields<<2) + (num_data_blocks>>8);
      map_data[map_pos+1] = num_data_blocks;
      map_pos += 2;
   } else {
      if (num_fields >= 0x10000 || num_data_blocks >= 0x10000) {
         ErrorAtLBA("Unexpectedly long VOBU", lba);
         throw 0;
      }
      if (map_pos > map_len - 5) {
         GrowMap();
      }
      map_data[map_pos] = 0xFE;
      map_data[map_pos+1] = num_fields >> 8;
      map_data[map_pos+2] = num_fields;
      map_data[map_pos+3] = num_data_blocks >> 8;
      map_data[map_pos+4] = num_data_blocks;
      map_pos += 5;
   }
   compile_dialog->SetProgress(vobu_number, num_vobus);
}

void SubpictureReceiver::ChangePTM(unsigned new_ptm) {
   if (map_pos > map_len - 5) {
      GrowMap();
   }
   map_data[map_pos] = 0xFF;
   for (int i=0; i<4; ++i) {
      map_data[map_pos+i+1] = new_ptm >> (24-i*8);
   }
   map_pos += 5;
}

void SubpictureReceiver::ChangeAngle(unsigned new_angle) {
   if (map_pos >= map_len) {
      GrowMap();
   }
   map_data[map_pos++] = 0xF0 + new_angle;
}


void SubpictureReceiver::Note(const char* msg) {
   compile_dialog->AddMessage(msg);
}

void SubpictureReceiver::Warning(const char* msg) {
   compile_dialog->AddMessage(msg);
   got_warning = true;
}

void SubpictureReceiver::Error(const char* msg, const char* fmt, int value) {
   compile_dialog->AddMessage("*** ERROR:");
   compile_dialog->AddMessage(msg);
   char buf[1024];
   sprintf(buf, fmt, value);
   compile_dialog->AddMessage(buf);
}

void SubpictureReceiver::ErrorAtLBA(const char* msg, unsigned lba) {
   Error(msg, "(at logical block address %X)", lba);
}

void SubpictureReceiver::ErrorAtLine(const char* msg, int line) {
   Error(msg, "(at script file line %d)", line);
}

void SubpictureReceiver::ErrorAtTime(const char* msg, unsigned field) {
   Error(msg, "(at video field %d)", field);
}


bool ChooseFile(char* filename, const char* title, const char* filters) {
   OPENFILENAME ofn;
   ofn.lStructSize = 76;
   ofn.hwndOwner = NULL;
   ofn.hInstance = g_hinstance;
   ofn.lpstrFilter = filters;
   ofn.lpstrCustomFilter = NULL;
   ofn.nMaxCustFilter = 0;
   ofn.nFilterIndex = 2;
   ofn.lpstrFile = filename;
   ofn.nMaxFile = MAX_PATH;
   ofn.lpstrFileTitle = NULL;
   ofn.nMaxFileTitle = 0;
   ofn.lpstrInitialDir = NULL;
   ofn.lpstrTitle = title;
   ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
   ofn.lpstrDefExt = NULL;
   ofn.lpfnHook = NULL;
   ofn.lpTemplateName = NULL;
   return !!GetOpenFileName(&ofn);
}


bool CreateTempFile(HANDLE* puserhandle, dvs_file_handle* pkernelhandle) {
   char temp_path[MAX_PATH];
   if (!GetTempPath(MAX_PATH, temp_path)) {
      MessageBox(NULL, "Could not get temporary directory.", "DVDSubber", MB_OK);
      return false;
   }

   char temp_name[MAX_PATH];
   if (!GetTempFileName(temp_path, "DVS", 0, temp_name)) {
      MessageBox(NULL, "Could not get temporary file name.", "DVDSubber", MB_OK);
      return false;
   }

   HANDLE htemp = CreateFile(temp_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, TRUNCATE_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL);
   if (htemp == INVALID_HANDLE_VALUE) {
      MessageBox(NULL, "Could not create temporary file.", "DVDSubber", MB_OK);
      return false;
   }

   dvs_file_handle temphandle;
   if (0 != g_bays->OpenFileRO(&temphandle, temp_name)) {
      MessageBox(NULL, "Could not create temporary file (in kernel mode).", "DVDSubber", MB_OK);
      CloseHandle(htemp);
      return false;
   }

   *puserhandle = htemp;
   *pkernelhandle = temphandle;
   return true;
}


class FileLRU {
   enum { max_files = 12 };
   char* ptrs[max_files];
   int num_files;
   char buf[max_files][MAX_PATH];
public:
   FileLRU() {
      for (int i=0; i<max_files; ++i) {
         ptrs[i] = buf[i];
      }
      num_files = 0;
   }
   const char* Get(int index) {
      return index >= 0 && index < num_files ? ptrs[index] : 0;
   }
   void Promote(const char* entry) {
      int i;
      for (i=0; i<num_files-1; ++i) {
         if (ptrs[i] == entry) {
            break;
         }
      }
      char* t = ptrs[i];
      while (i>0) {
         ptrs[i] = ptrs[i-1];
         --i;
      }
      ptrs[0] = t;
      if (ptrs[0] != entry) {
         lstrcpy(ptrs[0], entry);
      }
   }
   void Demote(const char* entry) {
      int i;
      for (i=0; i<num_files; ++i) {
         if (ptrs[i] == entry) {
            char* t = ptrs[i];
            while (i<num_files-1) {
               ptrs[i] = ptrs[i+1];
               ++i;
            }
            ptrs[num_files-1] = t;
            break;
         }
      }
   }
};


FileLRU file_lru;


bool CompileSubtitlesCatch(FILE* out, ICompilerCallbacks* compiler_callbacks) {
   try {
      return CompileSubtitles(out, compiler_callbacks);
   }
   catch (...) {
      return false;
   }
}


void ApplySubtitles(void* _self, int _subtitle_filename) {
   // put subtitle filename at top of LRU
   const char* subtitle_filename = (char*)_subtitle_filename;
   file_lru.Promote(subtitle_filename);

   DVDSubberUser* self = (DVDSubberUser*)_self;
   DVDSubberKernel* k = self->k;

   // make temp. file for compiled subtitles
   if (k->data_file_handle == 0) {
      if (!CreateTempFile(&self->data_file_handle, &k->data_file_handle))
         return;
   }

   // make drive appear empty while we update the disc
   g_bays->Driver_Call(self->driver_handle, "SetState", "pi", k, int(stateUpdating));

   // remove old subtitles
   k->num_subpics = 0;

   // remove old subpicture data
   SetFilePointer(self->data_file_handle, 0, NULL, FILE_BEGIN);
   SetEndOfFile(self->data_file_handle);

   if (subtitle_filename) {

      FILE* fsub = fopen(subtitle_filename, "r");
      if (!fsub) {
         MessageBox(NULL, "Could not open the subtitle file.", "DVDSubber", MB_OK);
      } else {

         scsi_result_t scsi_error = 0;
         try {
            k->disc_info = GetDiscInfo(k->child, self->bay);
         }
         catch (scsi_result_t result) {
            scsi_error = result;
            k->disc_info = 0;
         }
         if (scsi_error) {
            char buf[128];
            wsprintf(buf, "Failed to get disc info: SCSI error %X.", scsi_error);
            MessageBox(NULL, buf, "DVDSubber", MB_OK);
         } else if (!k->disc_info) {
            MessageBox(NULL, "Failed to get disc info. (Maybe there is not a DVD-Video disc in the drive?)", "DVDSubber", MB_OK);
         } else {
            PrintDiscInfo(k->disc_info);

            CompileDialog* compile_dialog = new CompileDialog;

            SubpictureReceiver subpic_receiver(compile_dialog, k, self->bay, self->data_file_handle);

            if (CompileSubtitlesCatch(fsub, &subpic_receiver)) {
               if (subpic_receiver.GotWarning()) {
                  subpic_receiver.Note("Compilation was successful, but there were warnings.");
                  compile_dialog->SetButtonAutoclose("OK");
               } else {
                  compile_dialog->Destroy();
               }
            } else {
               if (subpic_receiver.UserAborted()) {
                  compile_dialog->Destroy();
               } else {
                  subpic_receiver.Note("Compilation was not successful.");
                  compile_dialog->SetButtonAutoclose("OK");
               }
               k->num_subpics = 0;
            }

            k->saved_scr_lba = 0xFFFFFFF0;
         }
         fclose(fsub);
      }
   }

   g_bays->Driver_Call(self->driver_handle, "SetState", "pi", k, int(stateUpdated));
}


void OpenSubtitles(void* _self, int) {
   static char subtitle_filename[MAX_PATH];
   if (ChooseFile(subtitle_filename, "Choose subtitle file", "DVD subber scripts (*.dvdsub)\0*.dvdsub\0")) {
      ApplySubtitles(_self, (int)subtitle_filename);
   }
}


void AddDeviceMenuItems(DvsDeviceUser* _self, DvsMenu* menu) {
   menu->vtable->BeginSubmenu(menu, "DVD subber", false);
   menu->vtable->AddItem(menu, "&Open...", false, OpenSubtitles, _self, 0);
   DVDSubberUser* self = (DVDSubberUser*)_self;
   if (self->k->num_subpics != 0) {
      menu->vtable->AddItem(menu, "&Remove current subtitles", false, ApplySubtitles, _self, 0);
   }
//   menu->vtable->AddItem(menu, "Scan disc", false, ScanDisc, _self, 0);
   menu->vtable->AddSeparator(menu);
   for (int i = 0; ; ++i) {
      const char* name = file_lru.Get(i);
      if (name==0) break;
      menu->vtable->AddItem(menu, name, false, ApplySubtitles, _self, int(name));
   }
   menu->vtable->EndSubmenu(menu);
}

void Delete(DvsDeviceUser* _self) {
   DVDSubberUser* self = (DVDSubberUser*)_self;
   if (self->k->data_file_handle != 0) {
      g_bays->CloseFile(self->k->data_file_handle);
   }
   if (self->data_file_handle) {
      CloseHandle(self->data_file_handle);
   }
   g_bays->Driver_Unload(self->driver_handle);
   delete self;
}


DvsDeviceUser_vtable DVDSubberUser_vtable = {
   AddDeviceMenuItems,
   0,
   Delete
};


DvsDeviceUser* HookDevice(DvsDeviceKernel** pkernel, DvsDockingBay* bay) {
   DVDSubberUser* u = new DVDSubberUser;
   u->vtable = &DVDSubberUser_vtable;
   u->bay = bay;
   u->driver_handle = g_bays->Driver_Load("DVDSubber.kll");
   if (!u->driver_handle)
      return 0;
   u->data_file_handle = NULL;
   DVDSubberKernel* k = u->k = (DVDSubberKernel*)bay->vtable->SharedPool_Alloc(bay, sizeof(DVDSubberKernel));
   k->ScsiCommand = (dvs_scsi_func*)g_bays->Driver_Call(u->driver_handle, "GetDispatchFunc", "");
   k->child = *pkernel;
   k->state = stateActive;
   k->subpic_inf = 0;
   k->num_subpics = 0;
   k->data_file_handle = 0;
   *pkernel = k;
   return u;
}


DvsFilterGlobal filter_global = {
   0,
   "DVD Subtitler",
   DVDSYNTH_FILTER_ONLY_ONE,
   HookDevice,
   0
};


extern "C"
DvsFilterGlobal* __cdecl DvdsynthFilterPluginEntry(DvsDockingBayGlobal* bays) {
   g_bays = bays;
   return &filter_global;
}


extern "C"
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID) {
   g_hinstance = hinst;
   return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -