(************************************************************************* vStrip_gui: Graphical User Interface for vStrip-DLL Copyright (C) 2001 [maven] (maven@maven.de) 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 0.8f: - added dvd2avi support to gui 0.8e: - fixed SetStart/-End LBA not always working on Cell-Level 0.8d: - rearranged output screen to show dependency of outputs - added chapters - added video info (IFO) - changed flags/type - fixed incorrect fio_BUFFERSIZE - better popup menu in ifo selection - ask before adding menu vobs - eta/throughput 0.8c: - not much new on this side really... :) 0.8b: - incorporated changed prototype/defines from command-line 0.8b (maybe 1gb size is now detected correctly) - fixed Key conversion (hex) when giving a Key 0.8a: - udf file-selecter, new fileexit and filesize routines w/ udf support 0.8: - incorporated console changes (different structures, udf, aspi) 0.7c: - added audio & subp lang-support - fixed swapped cell & vob id when saving settings (.vsc) 0.7b: - added CELL LBA display - renamed # of Sectors to End LBA (because that's what it was) - added drag & drop support for files (ifo, vsc, lst, everything else -> added) - added popup-menu to ifo-tree (to set start & end lba) - improved Percentage/ProgressBar display when using start- and/or end-lba 0.7: - added support for multiple outputs - revised .vsc format (and loading & saving) - reorganised things a bit to make room - removed maximise button (hi alex!) 0.6ß: - command-line support for files (.vsc loaded, others added) - icon (could someone draw me a nice one, please?) *************************************************************************) unit MainForm; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, ExtCtrls, CheckLst, Math, vStrip, vStrip_Thread, Registry, IniFiles, ShellApi, Menus, Grids; const vStripRegistryPath = '\Software\[maven]\vStrip_GUI'; type TStreamInfo = record save : Byte; remap_to : Byte; end; TAStreamInfo = array[0..511] of TStreamInfo; // 0..255 streams, 256..511 substreams TIFOProgramChain = record NumCells : Integer; Length : t_vs_time; Cells : TPAVobCellID; end; TOutputInfo = record FileName : string; FileSize : Cardinal; // split Flags : Cardinal; end; TvStripForm = class(TForm) Input: TTabSheet; IFO: TTabSheet; Output: TTabSheet; ButtonOpenVOB: TButton; OpenVOBDialog: TOpenDialog; ButtonRemoveVOB: TButton; ButtonSortVOB: TButton; ButtonDownVOB: TButton; ButtonUpVOB: TButton; OpenIFODialog: TOpenDialog; ListViewFiles: TListView; TreeViewIFO: TTreeView; CheckListBoxStreams: TCheckListBox; ListBoxRemap: TListBox; ButtonClearVOB: TButton; CheckBoxSubstreams: TCheckBox; GroupBoxStreams: TGroupBox; ButtonAllStreams: TButton; ButtonNoStreams: TButton; LabelRemap: TLabel; GroupBoxOutputOptions: TGroupBox; CheckBoxDemux: TCheckBox; CheckBoxKeepGOPs: TCheckBox; RadioGroupSplit: TRadioGroup; CheckBoxAppend: TCheckBox; CheckBoxAC3Header: TCheckBox; CheckBoxPCMHeader: TCheckBox; GroupBoxSplitSize: TGroupBox; GroupBoxFileName: TGroupBox; ButtonOutput: TButton; EditFileName: TEdit; SaveOutputDialog: TSaveDialog; ButtonRun: TButton; ProgressBar1: TProgressBar; GroupBoxInputOptions: TGroupBox; Label2: TLabel; Label3: TLabel; Label4: TLabel; EditStartLBA: TEdit; EditEndLBA: TEdit; EditMaxSync: TEdit; GroupBoxDecrypt: TGroupBox; EditPadGuess: TEdit; EditSameGuess: TEdit; EditPercentageGuess: TEdit; EditKey: TEdit; Label10: TLabel; Label12: TLabel; GroupBox1: TGroupBox; EditIFOName: TEdit; ButtonOpenIFO: TButton; RadioGroupAngles: TRadioGroup; GroupBoxCells: TGroupBox; ListBoxVOBID: TListBox; CheckListBoxCELLID: TCheckListBox; ButtonIFOReset: TButton; Label1: TLabel; Label6: TLabel; ListViewInfo: TListView; SaveSettingsDialog: TSaveDialog; OpenSettingsDialog: TOpenDialog; GroupBox2: TGroupBox; ButtonLoadSettings: TButton; ButtonSaveSettings: TButton; ComboBoxKeySearch: TComboBox; Label7: TLabel; GroupBox3: TGroupBox; ComboBoxFrameRate: TComboBox; Label5: TLabel; Label8: TLabel; ComboBoxAspectRatio: TComboBox; RadioGroupOutputs: TRadioGroup; ComboBoxFileSize: TComboBox; PopupMenuIFO: TPopupMenu; SetStartLBA: TMenuItem; SetEndLBA: TMenuItem; GroupBoxIFOAudio: TGroupBox; ListBoxIFOAudio: TListBox; GroupBoxIFOSub: TGroupBox; ListBoxIFOSub: TListBox; CheckBoxIsVOB: TCheckBox; ComboBoxASPI: TComboBox; ButtonUDF: TButton; CheckBoxDemacro: TCheckBox; GroupBoxIFOVideo: TGroupBox; EditIFOVideo: TEdit; SetStartEndLBA: TMenuItem; ETA: TTabSheet; GroupBoxETA: TGroupBox; EditETA: TEdit; GroupBoxSpeed: TGroupBox; EditKS: TEdit; Sheets: TPageControl; CheckBoxDVD2AVI: TCheckBox; procedure ButtonOpenVOBClick(Sender: TObject); procedure ButtonRemoveVOBClick(Sender: TObject); procedure ButtonSortVOBClick(Sender: TObject); procedure ButtonUpVOBClick(Sender: TObject); procedure ButtonDownVOBClick(Sender: TObject); procedure ButtonOpenIFOClick(Sender: TObject); procedure ListViewFilesCompare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer); procedure FormCreate(Sender: TObject); procedure ButtonRunClick(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure ButtonClearVOBClick(Sender: TObject); procedure ListBoxRemapClick(Sender: TObject); procedure CheckBoxSubstreamsClick(Sender: TObject); procedure ButtonAllStreamsClick(Sender: TObject); procedure ButtonNoStreamsClick(Sender: TObject); procedure CheckBoxDemuxClick(Sender: TObject); procedure EditFileSizeKeyPress(Sender: TObject; var Key: Char); procedure ButtonOutputClick(Sender: TObject); procedure EditKeyKeyPress(Sender: TObject; var Key: Char); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure ButtonIFOResetClick(Sender: TObject); procedure ListBoxVOBIDClick(Sender: TObject); procedure CheckListBoxCELLIDClickCheck(Sender: TObject); procedure TreeViewIFOChange(Sender: TObject; Node: TTreeNode); procedure CheckListBoxStreamsClick(Sender: TObject); procedure ButtonSaveSettingsClick(Sender: TObject); procedure ButtonLoadSettingsClick(Sender: TObject); procedure EditFileNameChange(Sender: TObject); procedure RadioGroupOutputsClick(Sender: TObject); procedure TreeViewIFOContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); procedure SetStartLBAClick(Sender: TObject); procedure SetEndLBAClick(Sender: TObject); procedure ButtonUDFClick(Sender: TObject); procedure SetStartEndLBAClick(Sender: TObject); procedure CheckBoxKeepGOPsClick(Sender: TObject); private data: t_vs_data; streams, substreams: ta_vs_streamflags; stream_ofs: Integer; output_mask: Byte; outputs: array[0..inb_MAX_OUTPUT - 1] of TOutputInfo; num_output, cur_output: Integer; stream_info: TAStreamInfo; cell_list: TPAVobCellID; num_cell: Integer; KeepCells: array[0..255, 0..255, 0..1] of Boolean; // 0 display, 1 keep ResetKeepCells: Boolean; NumIFOChains: Integer; IFOChainIdx: Integer; IFOChains: array of TIFOProgramChain; PopupMenuItem: TTreeNode; VSThread: TVSThread; VSThreadActive: Boolean; procedure ParseCardinal(s: String; initial_value: Cardinal; var target: Cardinal); procedure LoadInitialDirectory(dlg: TOpenDialog; regname: String); procedure SaveInitialDirectory(dlg: TOpenDialog; regname: String; FileName: String); procedure LoadSettings(FName: String); procedure SaveSettings(FName: String); procedure AddTime(var sum: array of Byte; b: array of Byte); procedure ParseIFO(FileName: String); procedure UpdateFileName(Name: String; OP: TRadioGroup; cur: Integer; var num: Integer); procedure GetOutputSettings(var op: TOutputInfo); procedure PutOutputSettings(op: TOutputInfo); function AddFile(Name: String): Boolean; procedure OnVSThreadTerminate(Sender: TObject); procedure WMDropFiles(var m: TMessage); message WM_DROPFILES; public { Public-Deklarationen } function GetStreamDescription(Idx: Byte; SubStream: Boolean): String; end; var vStripForm: TvStripForm; implementation uses UDFSel; {$R *.DFM} procedure TvStripForm.ParseCardinal(s: String; initial_value: Cardinal; var target: Cardinal); var i: Cardinal; j: Integer; begin target := initial_value; if (s <> '') then begin Val(s, i, j); if (j = 0) then target := i; end; end; procedure TvStripForm.LoadInitialDirectory(dlg: TOpenDialog; regname: String); var reg: TRegistry; begin reg := TRegistry.Create(KEY_READ); try if (reg.OpenKey(regname, False)) then begin if (reg.ValueExists(dlg.Name)) then dlg.InitialDir := reg.ReadString(dlg.Name); reg.CloseKey(); end; finally reg.Free(); end; end; procedure TvStripForm.SaveInitialDirectory(dlg: TOpenDialog; regname: String; FileName: String); var reg: TRegistry; begin reg := TRegistry.Create(KEY_WRITE); try if (reg.OpenKey(regname, True)) then begin reg.WriteString(dlg.Name, ExtractFileDir(FileName)); reg.CloseKey(); end; finally reg.Free(); end; end; procedure TvStripForm.LoadSettings(FName: String); var ini: TMemIniFile; i, j, k, l, m: Integer; SaveSaveStreams: Boolean; OrMask, AndMask: Byte; begin ini := TMemIniFile.Create(FName); // input ListViewFiles.Items.Clear(); k := ini.ReadInteger('Input', 'NumFiles', 0); for i := 0 to k - 1 do AddFile(ini.ReadString('Input', 'F' + IntToStr(i), '')); EditStartLBA.Text := ini.ReadString('Input', 'OfsPackets', ''); EditEndLBA.Text := ini.ReadString('Input', 'NumPackets', ''); EditMaxSync.Text := ini.ReadString('Input', 'MaxSync', '2048'); {$IFDEF vs_DECRYPT} EditPadGuess.Text := ini.ReadString('Input', 'PadGuess', '2'); EditSameGuess.Text := ini.ReadString('Input', 'SameGuess', '2'); EditPercentageGuess.Text := ini.ReadString('Input', 'PercentageGuess', '75'); EditKey.Text := ini.ReadString('Input', 'Key', ''); ComboBoxKeySearch.ItemIndex := ini.ReadInteger('Input', 'KeySearch', 0); {$ENDIF} ComboBoxASPI.ItemIndex := ini.ReadInteger('Input', 'ASPIMode', 0); CheckBoxIsVOB.Checked := ini.ReadBool('Input', 'IsVOB', true); // ifo ButtonIFOResetClick(nil); EditIFOName.Text := ini.ReadString('IFO', 'IFOName', ''); if (EditIFOName.Text <> '') then ParseIFO(EditIFOName.Text); k := ini.ReadInteger('IFO', 'NumKeepCells', 0); if (k = 65536) then begin for i := 0 to 255 do for j := 0 to 255 do KeepCells[i, j, 1] := True end else begin for i := 0 to 255 do for j := 0 to 255 do KeepCells[i, j, 1] := False; for i := 0 to k - 1 do begin j := ini.ReadInteger('IFO', 'K' + IntToStr(i), -1); if (j <> -1) then KeepCells[j and $ff, j shr 8, 1] := True; end; end; k := ini.ReadInteger('IFO', 'IFOChainIdx', -1); if (k <> -1) then begin // select IFOChainIdx if (k < NumIFOChains) then begin for i := 0 to TreeViewIFO.Items.Count - 1 do with TreeViewIFO.Items[i] do if ((Parent = nil) and (Integer(Data) = k)) then begin IFOChainIdx := -1; ResetKeepCells := False; TreeViewIFO.Selected := TreeViewIFO.Items[i]; ResetKeepCells := True; break; end; end; end; if (RadioGroupAngles.Enabled) then begin i := ini.ReadInteger('IFO', 'Angles', -1); if ((i <> -1) and (i < RadioGroupAngles.Items.Count)) then RadioGroupAngles.ItemIndex := i; end; // output CheckBoxDemacro.Checked := ini.ReadBool('Output', 'Demacro', True); ComboBoxFrameRate.ItemIndex := ini.ReadInteger('Output', 'FrameRate', 0); ComboBoxAspectRatio.ItemIndex := ini.ReadInteger('Output', 'AspectRatio', 0); RadioGroupOutputs.Items.Clear(); num_output := ini.ReadInteger('Output', 'NumOutputs', 0); k := 0; for i := 0 to num_output do begin RadioGroupOutputs.Items.Append('Output ' + IntToStr(k)); outputs[i].FileName := ini.ReadString('Output' + IntToStr(i), 'FileName', ''); j := ini.ReadInteger('Output' + IntToStr(i), 'FileSize', 0); outputs[i].FileSize := j * ((1 shl 20) div fio_BUFFER_SIZE); with outputs[i] do begin flags := 0; if (ini.ReadBool('Output' + IntToStr(i), 'Append', False)) then flags := flags or vso_APPEND; if (ini.ReadBool('Output' + IntToStr(i), 'Demux', False)) then flags := flags or vso_DEMUX; if (ini.ReadBool('Output' + IntToStr(i), 'AC3Header', False)) then flags := flags or vso_KEEP_AC3_IDENT_BYTES; if (ini.ReadBool('Output' + IntToStr(i), 'PCMHeader', False)) then flags := flags or vso_KEEP_PCM_IDENT_BYTES; if (ini.ReadBool('Output' + IntToStr(i), 'KeepGOPs', False)) then flags := flags or vso_ONLY_KEEP_GOPS; if (ini.ReadBool('Output' + IntToStr(i), 'DVD2AVI', False)) then flags := flags or vso_DVD2AVI; j := ini.ReadInteger('Output' + IntToStr(i), 'Split', 0); case j of 1: flags := flags or vso_SPLIT_VOBID; 2: flags := flags or vso_SPLIT_CELLID; end; end; SaveSaveStreams := ini.ReadBool('Output' + IntToStr(i), 'SaveSaveStreams', False); // init masks if (SaveSaveStreams) then begin OrMask := $00; AndMask := Byte(not (1 shl i)); end else begin OrMask := 1 shl i; AndMask := $ff; end; for l := 0 to 511 do stream_info[l].save := (stream_info[l].save or OrMask) and AndMask; // saved masks if (not SaveSaveStreams) then begin OrMask := $00; AndMask := Byte(not (1 shl i)); end else begin OrMask := 1 shl i; AndMask := $ff; end; j := ini.ReadInteger('Output' + IntToStr(i), 'NumSaveStreams', 0); for l := 0 to j - 1 do begin m := ini.ReadInteger('Output' + IntToStr(i), 'S' + IntToStr(l), 0); stream_info[m].save := (stream_info[m].save or OrMask) and AndMask; end; Inc(k); end; cur_output := 0; PutOutputSettings(outputs[0]); // these will be copied on the next line RadioGroupOutputs.ItemIndex := 0; UpdateFileName(outputs[0].FileName, RadioGroupOutputs, 0, num_output); // empty one to RadioGroup if neccessary j := ini.ReadInteger('Output', 'NumRemaps', 0); for i := 0 to j - 1 do begin k := ini.ReadInteger('Output', 'R' + IntToStr(i), 0); stream_info[k and $1ff].remap_to := k shr 9; end; CheckBoxSubStreams.Checked := False; for i := 0 to 255 do begin CheckListBoxStreams.Checked[i] := (stream_info[i].save and output_mask) <> 0; CheckListBoxStreams.Items.Strings[i] := GetStreamDescription(i, False); end; CheckListBoxStreams.ItemIndex := -1; ListBoxRemap.ItemIndex := -1; stream_ofs := 0; RadioGroupOutputsClick(nil); ini.Free(); end; procedure TvStripForm.SaveSettings(FName: String); var ini: TMemIniFile; i, j, k, l: Integer; SaveSaveStreams: Boolean; Mask, MaxMask: Byte; begin ini := TMemIniFile.Create(FName); ini.Clear(); // input ini.WriteInteger('Input', 'NumFiles', ListViewFiles.Items.Count); for i := 0 to ListViewFiles.Items.Count - 1 do ini.WriteString('Input', 'F' + IntToStr(i), ListViewFiles.Items[i].Caption); if (EditStartLBA.Text <> '') then ini.WriteString('Input', 'OfsPackets', EditStartLBA.Text); if (EditEndLBA.Text <> '') then ini.WriteString('Input', 'NumPackets', EditEndLBA.Text); if (EditMaxSync.Text <> '') then ini.WriteString('Input', 'MaxSync', EditMaxSync.Text); {$IFDEF vs_DECRYPT} if (EditPadGuess.Text <> '') then ini.WriteString('Input', 'PadGuess', EditPadGuess.Text); if (EditSameGuess.Text <> '') then ini.WriteString('Input', 'SameGuess', EditSameGuess.Text); if (EditPercentageGuess.Text <> '') then ini.WriteString('Input', 'PercentageGuess', EditPercentageGuess.Text); if (EditKey.Text <> '') then ini.WriteString('Input', 'Key', EditKey.Text); ini.WriteInteger('Input', 'KeySearch', ComboBoxKeySearch.ItemIndex); {$ENDIF} ini.WriteInteger('Input', 'ASPIMode', ComboBoxASPI.ItemIndex); ini.WriteBool('Input', 'IsVOB', CheckBoxIsVOB.Checked); // ifo ini.WriteString('IFO', 'IFOName', EditIFOName.Text); if (IFOChainIdx <> -1) then ini.WriteInteger('IFO', 'IFOChainIdx', IFOChainIdx); k := 0; for i := 0 to 255 do for j := 0 to 255 do if (KeepCells[i, j, 1]) then Inc(k); ini.WriteInteger('IFO', 'NumKeepCells', k); if ((k <> 0) and (k <> 256 * 256)) then begin k := 0; for i := 0 to 255 do for j := 0 to 255 do if (KeepCells[i, j, 1]) then begin ini.WriteInteger('IFO', 'K' + IntToStr(k), i or (j shl 8)); // vob_id upper byte Inc(k); end; end; if (RadioGroupAngles.Enabled) then ini.WriteInteger('IFO', 'Angles', RadioGroupAngles.ItemIndex); // output ini.WriteBool('Output', 'Demacro', CheckBoxDemacro.Checked); ini.WriteInteger('Output', 'FrameRate', ComboBoxFrameRate.ItemIndex); ini.WriteInteger('Output', 'AspectRatio', ComboBoxAspectRatio.ItemIndex); GetOutputSettings(outputs[cur_output]); j := 0; for i := 0 to num_output do if (outputs[i].FileName <> '') then Inc(j); ini.WriteInteger('Output', 'NumOutputs', j); j := 0; MaxMask := 0; for i := 0 to num_output do if (outputs[i].FileName <> '') then with outputs[i] do begin MaxMask := MaxMask or (1 shl i); ini.WriteString('Output' + IntToStr(j), 'FileName', FileName); ini.WriteInteger('Output' + IntToStr(j), 'FileSize', FileSize div ((1 shl 20) div fio_BUFFER_SIZE)); k := 0; if ((flags and vso_SPLIT_VOBID) <> 0) then k := 1 else if ((flags and vso_SPLIT_CELLID) <> 0) then k := 2; ini.WriteInteger('Output' + IntToStr(j), 'Split', k); ini.WriteBool('Output' + IntToStr(j), 'Append', (flags and vso_APPEND) <> 0); ini.WriteBool('Output' + IntToStr(j), 'Demux', (flags and vso_DEMUX) <> 0); ini.WriteBool('Output' + IntToStr(j), 'AC3Header', (flags and vso_KEEP_AC3_IDENT_BYTES) <> 0); ini.WriteBool('Output' + IntToStr(j), 'PCMHeader', (flags and vso_KEEP_PCM_IDENT_BYTES) <> 0); ini.WriteBool('Output' + IntToStr(j), 'KeepGOPs', (flags and vso_ONLY_KEEP_GOPS) <> 0); ini.WriteBool('Output' + IntToStr(j), 'DVD2AVI', (flags and vso_DVD2AVI) <> 0); Mask := 1 shl i; k := 0; for l := 0 to 511 do if ((stream_info[l].save and Mask) <> 0) then Inc(k); SaveSaveStreams := k < 256; ini.WriteBool('Output' + IntToStr(j), 'SaveSaveStreams', SaveSaveStreams); if (not SaveSaveStreams) then begin ini.WriteInteger('Output' + IntToStr(j), 'NumSaveStreams', 512 - k); k := 0; for l := 0 to 511 do with stream_info[l] do if ((save and Mask) = 0) then begin ini.WriteInteger('Output' + IntToStr(j), 'S' + IntToStr(k), l); Inc(k); end; end else begin ini.WriteInteger('Output' + IntToStr(j), 'NumSaveStreams', k); k := 0; for l := 0 to 511 do with stream_info[l] do if ((save and Mask) <> 0) then begin ini.WriteInteger('Output' + IntToStr(j), 'S' + IntToStr(k), l); Inc(k); end; end; Inc(j); end; j := 0; for i := 0 to 511 do with stream_info[i] do if (((save and MaxMask) <> 0) and (remap_to <> (i and 255))) then Inc(j); ini.WriteInteger('Output', 'NumRemaps', j); j := 0; for i := 0 to 511 do with stream_info[i] do if (((save and MaxMask) <> 0) and (remap_to <> (i and 255))) then begin ini.WriteInteger('Output', 'R' + IntToStr(j), i + (Ord(remap_to) shl 9)); Inc(j); end; ini.UpdateFile(); ini.Free(); end; procedure TvStripForm.AddTime(var sum: array of Byte; b: array of Byte); var i: Integer; max_f: Integer; begin for i := Low(sum) to High(sum) do Inc(sum[i], (b[i] and DVD_TIME_AND)); max_f := 25; if ((b[3] and (not DVD_TIME_AND)) = 192) then max_f := 30; if (sum[3] >= max_f) then begin Dec(sum[3], max_f); Inc(sum[2]); end; if (sum[2] >= 60) then begin // seconds Dec(sum[2], 60); Inc(sum[1]); end; if (sum[1] >= 60) then begin // minutes Dec(sum[1], 60); Inc(sum[0]); end; end; procedure TvStripForm.ParseIFO(FileName: String); var i, j, k: Integer; LastChapter: Integer; ifo_handle, ifo_flags: Cardinal; it, ch: TTreeNode; ctime: array[0..3] of Byte; s: String; begin TreeViewIFO.Items.Clear(); IFOChainIdx := -1; RadioGroupAngles.Items.Clear(); RadioGroupAngles.Enabled := False; ListBoxIFOAudio.Items.Clear(); ListBoxIFOSub.Items.Clear(); for i := 0 to NumIFOChains - 1 do if (IFOChains[i].Cells <> Nil) then begin FreeMem(IFOChains[i].Cells); IFOChains[i].Cells := Nil; end; SetLength(IFOChains, 0); NumIFOChains := 0; it := nil; ifo_flags := 0; case ComboBoxASPI.ItemIndex of 0: ifo_flags := ifo_flags + fio_USE_ASPI; 1: ifo_flags := ifo_flags + fio_USE_ASPI + vs_PREFER_ASPI; end; ifo_handle := ifoOpen(PChar(EditIFOName.Text), ifo_flags); if (ifo_handle <> 0) then begin EditIFOVideo.Text := ifoGetVideoDesc(ifo_handle); j := ifoGetNumAudio(ifo_handle); for i := 0 to j - 1 do ListBoxIFOAudio.Items.Add(Format('%d. %s', [i, ifoGetAudioDesc(ifo_handle, i)])); j := ifoGetNumSubPic(ifo_handle); for i := 0 to j - 1 do ListBoxIFOSub.Items.Add(Format('%d. %s', [i, ifoGetSubPicDesc(ifo_handle, i)])); with TreeViewIFO.Items do begin BeginUpdate(); NumIFOChains := ifoGetNumPGCI(ifo_handle); SetLength(IFOChains, NumIFOChains); for i := 0 to NumIFOChains - 1 do with IFOChains[i] do begin NumCells := ifoGetPGCIInfo(ifo_handle, i, Length); it := AddObject(nil, Format('%u. Length: %u:%.2u:%.2u:%.2u in %d cell(s)', [i, Length[0], Length[1], Length[2], Length[3], NumCells]), Pointer(i)); GetMem(Cells, NumCells * SizeOf(t_vs_vobcellid)); ifoGetPGCICells(ifo_handle, i, @Cells^[0]); ch := it; LastChapter := -1; for j := 0 to NumCells - 1 do with Cells[j] do begin if (chapter <> LastChapter) then begin ctime[0] := 0; ctime[1] := 0; ctime[2] := 0; ctime[3] := 0; k := j; while ((k < NumCells) and (Cells[k].chapter = chapter)) do begin AddTime(ctime, Cells[k].time); Inc(k); end; ch := AddChildObject(it, Format('%u. Chapter (%u:%.2u:%.2u:%.2u)', [chapter, ctime[0], ctime[1], ctime[2], ctime[3]]), Pointer(j)); LastChapter := chapter; end; s := Format('%u. V: %.3u/C: %.3u', [j, vob_id, cell_id]); if (angle <> $11) then s := s + Format(' (%u/%u)', [angle and $f, angle shr 4]); s := s + Format(' [@LBA %u - %u]', [start_lba, end_lba]); AddChildObject(ch, s, Pointer(j)); end; end; if ((it <> nil) and (NumIFOChains = 1)) then TreeViewIFO.Selected := it; EndUpdate(); end; ifoClose(ifo_handle); end else MessageDlg('vStrip could not read/parse the IFO-File', mtError, [mbOK], 0); end; procedure TvStripForm.UpdateFileName(Name: String; OP: TRadioGroup; cur: Integer; var num: Integer); var i: Integer; f: Boolean; begin if (Name <> '') then begin // add if not one free outputs[cur].FileName := Name; f := False; for i := 0 to num do if (outputs[i].FileName = '') then f := True; if ((not f) and (num < inb_MAX_OUTPUT - 1)) then begin Inc(num); OP.Items.Append('Output ' + IntToStr(num)); end; end else begin // remove if last if ((num > 1) and ((cur = num) or (outputs[num].FileName = ''))) then begin OP.Items.Delete(OP.Items.Count - 1); Dec(Num); end; end; end; procedure TvStripForm.GetOutputSettings(var op: TOutputInfo); begin op.FileName := EditFileName.Text; if (ComboBoxFileSize.Text = '') then op.FileSize := 0 else begin ParseCardinal(ComboBoxFileSize.Text, 0, op.FileSize); op.FileSize := op.FileSize * ((1 shl 20) div fio_BUFFER_SIZE); end; op.flags := 0; case RadioGroupSplit.ItemIndex of 1: op.flags := op.flags + vso_SPLIT_VOBID; 2: op.flags := op.flags + vso_SPLIT_CELLID; end; if (CheckBoxDemux.Checked) then begin op.flags := op.flags + vso_DEMUX; if (CheckBoxAC3Header.Checked) then op.flags := op.flags + vso_KEEP_AC3_IDENT_BYTES; if (CheckBoxPCMHeader.Checked) then op.flags := op.flags + vso_KEEP_PCM_IDENT_BYTES; end; if (CheckBoxKeepGOPs.Checked) then op.flags := op.flags + vso_ONLY_KEEP_GOPS; if (CheckBoxDVD2AVI.Checked) then op.flags := op.flags + vso_DVD2AVI; if (CheckBoxAppend.Checked) then op.flags := op.flags + vso_APPEND; end; procedure TvStripForm.PutOutputSettings(op: TOutputInfo); begin EditFileName.Text := op.FileName; if (op.FileSize = 0) then ComboBoxFileSize.Text := '' else ComboBoxFileSize.Text := IntToStr(op.FileSize div ((1 shl 20) div fio_BUFFER_SIZE)); if ((op.flags and vso_SPLIT_VOBID) <> 0) then RadioGroupSplit.ItemIndex := 1 else if ((op.flags and vso_SPLIT_CELLID) <> 0) then RadioGroupSplit.ItemIndex := 2 else RadioGroupSplit.ItemIndex := 0; CheckBoxDemux.Checked := (op.flags and vso_DEMUX) <> 0; CheckBoxAC3Header.Checked := (op.flags and vso_KEEP_AC3_IDENT_BYTES) <> 0; CheckBoxAC3Header.Enabled := CheckBoxDemux.Checked; CheckBoxPCMHeader.Checked := (op.flags and vso_KEEP_PCM_IDENT_BYTES) <> 0; CheckBoxPCMHeader.Enabled := CheckBoxDemux.Checked; CheckBoxKeepGOPs.Checked := (op.flags and vso_ONLY_KEEP_GOPS) <> 0; CheckBoxDVD2AVI.Checked := (op.flags and vso_DVD2AVI) <> 0; CheckBoxAppend.Checked := (op.flags and vso_APPEND) <> 0; end; function TvStripForm.AddFile(Name: String): Boolean; var it: TListItem; s: String; sl: TextFile; ignore: Boolean; begin Result := False; if ((Name <> '') and uFileExists(Name)) then begin if (AnsiCompareFileName(ExtractFileExt(Name), '.VSC') = 0) then begin LoadSettings(Name); end else if (AnsiCompareFileName(ExtractFileExt(Name), '.IFO') = 0) then begin EditIFOName.Text := Name; ParseIFO(Name); end else if (AnsiCompareFileName(ExtractFileExt(Name), '.LST') = 0) then begin AssignFile(sl, Name); Reset(sl); while (not EoF(sl)) do begin ReadLn(sl, s); if ((s <> '') and (s <> Name) and uFileExists(s)) then AddFile(s); end; CloseFile(sl); Result := True; end else begin ignore := False; s := Name; while (Pos('\', s) > 0) do Delete(s, 1, Pos('\', s)); if (Length(s) = 12) then begin s[5] := 'X'; s[6] := 'X'; if (AnsiCompareFileName(s, 'VTS_XX_0.VOB') = 0) then ignore := MessageDlg(Format('%s seems to be a Menu VOB...' + #13 + #13 + 'Really add it to the List?', [Name]), mtConfirmation, [mbYes, mbNo], 0) <> mrYes; end; if (not ignore) then begin it := ListViewFiles.Items.Add(); it.Caption := Name; it.SubItems.Add(IntToStr(((uGetSize(it.Caption) + (1 shl 19)) shr 20))); end; end; end; end; procedure TvStripForm.OnVSThreadTerminate(Sender: TObject); begin // these are *not* needed anymore, as vs_done was definitely called! if (data.infile <> nil) then begin FreeMem(data.infile); data.infile := nil; end; if (cell_list <> nil) then begin FreeMem(cell_list); cell_list := nil; num_cell := 0; end; VSThread := nil; VSThreadActive := False; ETA.TabVisible := False; ButtonRun.Caption := '&Run'; ButtonRun.Hint := 'Start Processing'; end; procedure TvStripForm.WMDropFiles(var m: TMessage); var i, j: Cardinal; buf: array[0..511] of Char; was_empty, did_list : Boolean; begin was_empty := ListViewFiles.Items.Count <= 0; did_list := False; j := DragQueryFile(m.WParam, $ffffffff, Nil, 0); for i := 1 to j do begin DragQueryFile(m.WParam, i - 1, @buf, SizeOf(buf)); if (AddFile(buf)) then did_list := True; end; if (was_empty and not did_list) then ListViewFiles.CustomSort(nil, 0); DragFinish(m.WParam); end; function TvStripForm.GetStreamDescription(Idx: Byte; SubStream: Boolean): String; var s: String; begin s := Format('0x%.2x', [Idx]); if (SubStream) then case Idx of $20..$3f: s := s + ' (Subtitle Stream ' + IntToStr(Idx - $20) + ')'; $80..$87: s := s + ' (AC3 Audio Stream ' + IntToStr(Idx - $80) + ')'; $a0..$a7: s := s + ' (PCM Audio Stream ' + IntToStr(Idx - $a0) + ')'; end else case Idx of $bd: s := s + ' (Private Stream 1)'; $be: s := s + ' (Padding Stream)'; $bf: s := s + ' (Private Stream 2)'; $c0..$c7: s := s + ' (Audio Stream ' + IntToStr(Idx - $c0) + ')'; $e0..$e7: s := s + ' (Video Stream ' + IntToStr(Idx - $e0) + ')'; end; Result := s; end; procedure TvStripForm.ButtonOpenVOBClick(Sender: TObject); var i: Integer; was_empty, did_list: Boolean; begin OpenVOBDialog.FileName := ''; if (OpenVOBDialog.Execute()) then with ListViewFiles.Items do begin SaveInitialDirectory(OpenVOBDialog, vStripRegistryPath, OpenVOBDialog.FileName); was_empty := Count = 0; did_list := False; BeginUpdate(); for i := 0 to OpenVOBDialog.Files.Count - 1 do if (AddFile(OpenVOBDialog.Files[i])) then did_list := True; if (was_empty and not did_list) then ListViewFiles.CustomSort(nil, 0); EndUpdate(); end; end; procedure TvStripForm.ButtonRemoveVOBClick(Sender: TObject); var i: Integer; begin ListViewFiles.Items.BeginUpdate(); while (ListViewFiles.SelCount > 0) do for i := 0 to ListViewFiles.Items.Count - 1 do if (ListViewFiles.Items[i].Selected) then begin ListViewFiles.Items.Delete(i); break; end; ListViewFiles.Items.EndUpdate(); end; procedure TvStripForm.ButtonSortVOBClick(Sender: TObject); begin ListViewFiles.CustomSort(nil, 0); end; procedure TvStripForm.ButtonUpVOBClick(Sender: TObject); var i: Integer; it: TListItem; begin if ((ListViewFiles.SelCount > 0) and not ListViewFiles.Items[0].Selected) then with ListViewFiles.Items do begin BeginUpdate(); for i := 1 to Count - 1 do if (ListViewFiles.Items[i].Selected) then begin it := Insert(i - 1); it.Caption := ListViewFiles.Items[i + 1].Caption; it.Selected := ListViewFiles.Items[i + 1].Selected; it.SubItems.Add(ListViewFiles.Items[i + 1].SubItems[0]); Delete(i + 1); end; EndUpdate(); end; end; procedure TvStripForm.ButtonDownVOBClick(Sender: TObject); var i: Integer; it: TListItem; begin if ((ListViewFiles.SelCount > 0) and not ListViewFiles.Items[ListViewFiles.Items.Count - 1].Selected) then with ListViewFiles.Items do begin BeginUpdate(); for i := Count - 2 downto 0 do if (ListViewFiles.Items[i].Selected) then begin it := Insert(i + 2); it.Caption := ListViewFiles.Items[i].Caption; it.Selected := ListViewFiles.Items[i].Selected; it.SubItems.Add(ListViewFiles.Items[i].SubItems[0]); Delete(i); end; EndUpdate(); end; end; procedure TvStripForm.ButtonOpenIFOClick(Sender: TObject); begin OpenIFODialog.FileName := EditIFOName.Text; if (OpenIFODialog.Execute()) then begin SaveInitialDirectory(OpenIFODialog, vStripRegistryPath, OpenIFODialog.FileName); EditIFOName.Text := OpenIFODialog.FileName; ParseIFO(OpenIFODialog.FileName); end; end; procedure TvStripForm.ListViewFilesCompare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer); begin Compare := AnsiCompareFileName(Item1.Caption, Item2.Caption); end; procedure TvStripForm.FormCreate(Sender: TObject); var i: Integer; vv, fl: Cardinal; vv_str: String; dec_mismatch: Boolean; begin // Parse Version Info From DLL vv := vs_get_version(fl); vv_str := Format('%u.%u%s', [(vv shr 24) and $ff, (vv shr 16) and $ff, Chr((vv shr 8) and $ff)]); if ((vv and $ff) > 1) then vv_str := vv_str + IntToStr(vv and $ff); if ((fl and vsv_DECRYPT) <> 0) then vv_str := vv_str + '_css'; vv_str := vv_str + ' by ' + vs_get_author(); Caption := Caption + ' ' + vv_str; {$IFDEF vs_DECRYPT} dec_mismatch := True; {$ELSE} dec_mismatch := False; {$ENDIF} if (dec_mismatch <> ((fl and vsv_DECRYPT) <> 0)) then begin MessageDlg('Feature/Version Mismatch in ' + vs_DllName + ' and GUI!', mtError, [mbOK], 0); Application.Terminate(); end; // Fill the streams in for i := 0 to 255 do begin stream_info[i].save := $ff; stream_info[i].remap_to := i; stream_info[i + 256].save := $ff; stream_info[i + 256].remap_to := i; CheckListBoxStreams.Checked[CheckListBoxStreams.Items.Add(GetStreamDescription(i, False))] := True; ListBoxRemap.Items.Add(Format('0x%.2x', [i])); end; NumIFOChains := 0; IFOChainIdx := -1; stream_ofs := 0; output_mask := $01; num_cell := 0; cell_list := nil; ResetKeepCells := True; VSThread := nil; VSThreadActive := False; ButtonIFOResetClick(nil); // init the cell-list to everything LoadInitialDirectory(OpenVOBDialog, vStripRegistryPath); LoadInitialDirectory(OpenIFODialog, vStripRegistryPath); LoadInitialDirectory(OpenSettingsDialog, vStripRegistryPath); LoadInitialDirectory(SaveOutputDialog, vStripRegistryPath); LoadInitialDirectory(SaveSettingsDialog, vStripRegistryPath); ComboBoxFrameRate.ItemIndex := 0; ComboBoxAspectRatio.ItemIndex := 0; ComboBoxASPI.ItemIndex := 0; {$IFDEF vs_DECRYPT} ComboBoxKeySearch.ItemIndex := 0; GroupBoxDecrypt.Visible := True; {$ENDIF} num_output := 0; cur_output := 0; for i := 0 to inb_MAX_OUTPUT - 1 do begin outputs[i].FileName := ''; outputs[i].FileSize := 0; outputs[i].Flags := 0; end; PopupMenuItem := Nil; if (FileExists('vStrip_gui.vsc')) then LoadSettings('vStrip_gui.vsc'); ButtonUDF.Enabled := aspi_ok; // parse command-line parameters for i := 1 to ParamCount() do AddFile(ParamStr(i)); DragAcceptFiles(Handle, True); end; procedure TvStripForm.ButtonRunClick(Sender: TObject); var i, j, k, ai: Integer; total_lba: Int64; {$IFDEF vs_DECRYPT} key: Int64; {$ENDIF} begin if ((not VSThreadActive) and (VSThread = nil) and (ListViewFiles.Items.Count > 0)) then begin VSThreadActive := True; ETA.TabVisible := True; data.infile := CreateStreamList(ListViewFiles, total_lba); GetOutputSettings(outputs[cur_output]); j := 0; for i := 0 to num_output do begin StrLCopy(data.outputs[i].outfile, PChar(outputs[i].FileName), SizeOf(data.outputs[i].outfile)); data.outputs[i].split_output := outputs[i].FileSize; data.outputs[i].flags := outputs[i].flags; if (outputs[i].FileName <> '') then Inc(j); end; data.num_outputs := j; data.flags := vs_SUPPORT_1GB; data.framerate := $ffffffff; if (ComboBoxFrameRate.ItemIndex > 0) then data.framerate := ComboBoxFrameRate.ItemIndex; data.aspectratio := $ffffffff; if (ComboBoxAspectRatio.ItemIndex > 0) then data.aspectratio := ComboBoxAspectRatio.ItemIndex; if (not CheckBoxISVOB.Checked) then data.flags := data.flags + vs_NO_VOB; if (CheckBoxDemacro.Checked) then data.flags := data.flags + vs_DEMACRO; case ComboBoxASPI.ItemIndex of 0: data.flags := data.flags + vs_USE_ASPI; 1: data.flags := data.flags + vs_USE_ASPI + vs_PREFER_ASPI; end; ParseCardinal(EditMaxSync.Text, 2048, data.max_sync_bytes); ParseCardinal(EditStartLBA.Text, 0, data.start_lba); ParseCardinal(EditEndLBA.Text, $ffffffff, data.end_lba); {$IFDEF vs_DECRYPT} ParseCardinal(EditSameGuess.Text, 2, data.same_guess); ParseCardinal(EditPadGuess.Text, 2, data.pad_guess); ParseCardinal(EditPercentageGuess.Text, 75, data.pc_guess); data.key[0] := 0; data.key[1] := 0; data.key[2] := 0; data.key[3] := 0; data.key[4] := 0; if ((EditKey.Text <> '') and (Length(EditKey.Text) = 10)) then begin key := StrToInt64('$' + EditKey.Text); data.key[0] := key shr 32; data.key[1] := (key shr 24) and $ff; data.key[2] := (key shr 16) and $ff; data.key[3] := (key shr 8) and $ff; data.key[4] := key and $ff; end; case ComboBoxKeySearch.ItemIndex of 1: data.flags := data.flags + vs_CRACK_EACH_VOB_ID; 2: data.flags := data.flags + vs_CRACK_EACH_CELL_ID; 3: data.flags := data.flags + vs_CRACK_EACH_VOB_ID + vs_CRACK_EACH_CELL_ID; 4: data.flags := data.flags + vs_DONT_CRACK; end; {$ENDIF} ai := 1; if (IFOChainIdx <> -1) then begin if (RadioGroupAngles.Enabled) then begin if (RadioGroupAngles.ItemIndex = RadioGroupAngles.Items.Count - 1) then ai := 0 // all angles else ai := 1 + RadioGroupAngles.ItemIndex; end; end; k := 0; for i := 0 to 255 do for j := 0 to 255 do if (KeepCells[i, j, 0] and KeepCells[i, j, 1]) then Inc(k); if ((k <> 256 * 256) and (k <> 0)) then begin num_cell := k; GetMem(cell_list, num_cell * SizeOf(t_vs_vobcellid)); k := 0; if (IFOChainIdx <> -1) then begin for i := 0 to IFOChains[IFOChainIdx].NumCells - 1 do with IFOChains[IFOChainIdx].Cells[i] do if (KeepCells[vob_id and $ff, cell_id, 0] and KeepCells[vob_id and $ff, cell_id, 1]) then begin cell_list^[k].vob_id := vob_id; cell_list^[k].cell_id := cell_id; cell_list^[k].angle := angle; Inc(k); end; num_cell := k; if (ai <> 0) then for i := 0 to num_cell - 1 do if (((cell_list^[i].angle shr 4) >= ai) and ((cell_list^[i].angle and $f) <> ai)) then begin cell_list^[i].vob_id := 0; cell_list^[i].cell_id := 0; end; end else begin for i := 0 to 255 do for j := 0 to 255 do if (KeepCells[i, j, 0] and KeepCells[i, j, 1]) then begin cell_list^[k].vob_id := i; cell_list^[k].cell_id := j; Inc(k); end; end; end; for i := 0 to 255 do begin streams[i].remap_to := stream_info[i].remap_to; streams[i].user_func := 0; streams[i].save := stream_info[i].save; substreams[i].remap_to := stream_info[i + 256].remap_to; substreams[i].user_func := 0; substreams[i].save := stream_info[i + 256].save; end; ButtonRun.Caption := '&Abort'; ButtonRun.Hint := 'Abort Processing'; VSThread := TVSThread.CreateVS(@data, @streams, @substreams, total_lba, num_cell, cell_list, ProgressBar1, ListViewInfo, ListViewFiles); VSThread.OnTerminate := OnVSThreadTerminate; VSThread.Suspended := False; end else if ((VSThread <> nil) and VSThreadActive) then VSThread.Terminate(); end; procedure TvStripForm.FormDestroy(Sender: TObject); var i: Integer; begin if ((VSThread <> nil) and VSThreadActive) then begin VSThread.Terminate(); VSThread.WaitFor(); end; for i := 0 to NumIFOChains - 1 do if (IFOChains[i].Cells <> NiL) then begin FreeMem(IFOChains[i].Cells); IFOChains[i].Cells := Nil; end; SetLength(IFOChains, 0); NumIFOChains := 0; end; procedure TvStripForm.ButtonClearVOBClick(Sender: TObject); begin ListViewFiles.Items.Clear(); EditStartLBA.Text := ''; EditEndLBA.Text := ''; EditKey.Text := ''; end; procedure TvStripForm.ListBoxRemapClick(Sender: TObject); begin if ((ListBoxRemap.ItemIndex <> -1) and (CheckListBoxStreams.ItemIndex <> -1)) then stream_info[stream_ofs + CheckListBoxStreams.ItemIndex].remap_to := ListBoxRemap.ItemIndex; end; procedure TvStripForm.CheckBoxSubstreamsClick(Sender: TObject); var i: Integer; new_ofs: Integer; begin if (CheckBoxSubstreams.Checked) then begin new_ofs := 256; GroupBoxStreams.Caption := 'SubStreams:' end else begin new_ofs := 0; GroupBoxStreams.Caption := 'Streams:' end; if (new_ofs <> stream_ofs) then begin for i := 0 to 255 do begin CheckListBoxStreams.Checked[i] := (stream_info[i + new_ofs].save and output_mask) <> 0; CheckListBoxStreams.Items.Strings[i] := GetStreamDescription(i, CheckBoxSubstreams.Checked); end; CheckListBoxStreams.ItemIndex := -1; ListBoxRemap.ItemIndex := -1; stream_ofs := new_ofs; end; end; procedure TvStripForm.ButtonAllStreamsClick(Sender: TObject); var i: Integer; begin for i := 0 to 255 do begin stream_info[i].save := stream_info[i].save or output_mask; stream_info[i + 256].save := stream_info[i + 256].save or output_mask; CheckListBoxStreams.Checked[i] := True; end; end; procedure TvStripForm.ButtonNoStreamsClick(Sender: TObject); var i: Integer; begin for i := 0 to 255 do begin stream_info[i].save := stream_info[i].save and (not output_mask); stream_info[i + 256].save := stream_info[i + 256].save and (not output_mask); CheckListBoxStreams.Checked[i] := False; end; end; procedure TvStripForm.CheckBoxDemuxClick(Sender: TObject); var i, j: Integer; begin CheckBoxAC3Header.Enabled := CheckBoxDemux.Checked; CheckBoxPCMHeader.Enabled := CheckBoxDemux.Checked; ListBoxRemap.Enabled := not CheckBoxDemux.Checked and (RadioGroupOutputs.ItemIndex = 0); LabelRemap.Enabled := not CheckBoxDemux.Checked and (RadioGroupOutputs.ItemIndex = 0); ButtonAllStreams.Enabled := not CheckBoxDemux.Checked and (RadioGroupOutputs.ItemIndex = 0); j := 0; if (CheckBoxDemux.Checked) then begin for i := 0 to 511 do if ((stream_info[i].save and output_mask) <> 0) then Inc(j); if (j > 1) then ButtonNoStreamsClick(Sender); // select none, if more than 1 selected end; end; procedure TvStripForm.EditFileSizeKeyPress(Sender: TObject; var Key: Char); begin if ((Key > #31) and not (Key in ['0'..'9'])) then Key := #0; end; procedure TvStripForm.ButtonOutputClick(Sender: TObject); begin SaveOutputDialog.FileName := EditFileName.Text; if (SaveOutputDialog.Execute()) then begin EditFileName.Text := SaveOutputDialog.FileName; UpdateFileName(EditFileName.Text, RadioGroupOutputs, cur_output, num_output); SaveInitialDirectory(SaveOutputDialog, vStripRegistryPath, SaveOutputDialog.FileName); end; end; procedure TvStripForm.EditKeyKeyPress(Sender: TObject; var Key: Char); begin if ((Key > #31) and not (UpCase(Key) in ['0'..'9','A'..'F'])) then Key := #0; end; procedure TvStripForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin if ((VSThread <> nil) and VSThreadActive) then begin if (MessageDlg('Operation in Progress...' + #13 + #13 + 'Quit?', mtConfirmation, [mbYes, mbNo], 0) <> mrYes) then CanClose := False; end; end; procedure TvStripForm.ButtonIFOResetClick(Sender: TObject); var i, j: Integer; begin for i := 0 to NumIFOChains - 1 do if (IFOChains[i].Cells <> Nil) then begin FreeMem(IFOChains[i].Cells); IFOChains[i].Cells := Nil; end; SetLength(IFOChains, 0); IFOChainIdx := -1; NumIFOChains := 0; RadioGroupAngles.Items.Clear(); TreeViewIFO.Items.Clear(); ListBoxIFOAudio.Items.Clear(); ListBoxIFOSub.Items.Clear(); ListBoxVOBID.Items.Clear(); CheckListBoxCellID.Items.Clear(); for i := 0 to 255 do begin for j := 0 to 255 do begin KeepCells[i, j, 0] := True; KeepCells[i, j, 1] := True; end; ListBoxVOBID.Items.Add(Format('%.3u', [i])); CheckListBoxCellID.Items.Add(Format('%.3u', [i])); CheckListBoxCellID.Checked[i] := True; end; ListBoxVOBID.ItemIndex := 0; end; procedure TvStripForm.ListBoxVOBIDClick(Sender: TObject); var idx, i, j: Integer; begin if (ListBoxVobID.ItemIndex <> -1) then begin Val(ListBoxVobID.Items[ListBoxVobID.ItemIndex], idx, i); if (i = 0) then begin CheckListBoxCellID.Items.Clear(); j := 0; for i := 0 to 255 do if (KeepCells[idx, i, 0]) then begin CheckListBoxCellID.Items.Add(Format('%.3u', [i])); CheckListBoxCellID.Checked[j] := KeepCells[idx, i, 1]; Inc(j); end; end; end; end; procedure TvStripForm.CheckListBoxCELLIDClickCheck(Sender: TObject); var i, j, k: Integer; begin if ((CheckListBoxCellID.ItemIndex <> -1) and (ListBoxVobID.ItemIndex <> -1)) then begin Val(ListBoxVobID.Items[ListBoxVobID.ItemIndex], i, k); if (k = 0) then begin Val(CheckListBoxCellID.Items[CheckListBoxCellID.ItemIndex], j, k); if (k = 0) then KeepCells[i, j, 1] := CheckListBoxCellID.Checked[CheckListBoxCellID.ItemIndex]; end; end; end; procedure TvStripForm.TreeViewIFOChange(Sender: TObject; Node: TTreeNode); var it: TTreeNode; i, j, k, max_a: Integer; arr: array[0..255] of Boolean; begin if (NumIFOChains > 0) then begin it := Node; while (it.Parent <> nil) do it := it.Parent; if (IFOChainIdx <> Integer(it.Data)) then begin IFOChainIdx := Integer(it.Data); max_a := 0; for i := 0 to IFOChains[IFOChainIdx].NumCells - 1 do with IFOChains[IFOChainIdx].Cells[i] do max_a := Max(max_a, angle and $f); RadioGroupAngles.Enabled := max_a > 1; RadioGroupAngles.Items.Clear(); for i := 0 to max_a - 1 do RadioGroupAngles.Items.Add('Angle ' + IntToStr(i + 1)); RadioGroupAngles.ItemIndex := 0; RadioGroupAngles.Items.Add('All'); // Update VOB/CELL-Lists ListBoxVOBID.Items.Clear(); for i := 0 to 255 do arr[i] := False; for i := 0 to IFOChains[IFOChainIdx].NumCells - 1 do with IFOChains[IFOChainIdx].Cells[i] do arr[vob_id and $ff] := True; for i := 0 to 255 do if (arr[i]) then ListBoxVobID.Items.Add(Format('%.3u', [i])); for i := 0 to 255 do for j := 0 to 255 do begin KeepCells[i, j, 0] := False; if (ResetKeepCells) then KeepCells[i, j, 1] := False; end; for i := 0 to IFOChains[IFOChainIdx].NumCells - 1 do with IFOChains[IFOChainIdx].Cells[i] do begin KeepCells[vob_id and $ff, cell_id, 0] := True; if (ResetKeepCells) then KeepCells[vob_id and $ff, cell_id, 1] := True; end; if (Node.Parent = nil) then begin ListBoxVobID.ItemIndex := 0; ListBoxVOBIDClick(nil); end; end; if (Node.Parent <> nil) then begin // follow idx i := Integer(Node.Data); with IFOChains[IFOChainIdx].Cells[i] do begin for j := 0 to ListBoxVobID.Items.Count - 1 do begin Val(ListBoxVobID.Items[j], k, max_a); if ((max_a = 0) and (vob_id = k)) then if (ListBoxVobID.ItemIndex <> j) then begin ListBoxVobID.ItemIndex := j; ListBoxVOBIDClick(nil); break; end; end; for j := 0 to CheckListBoxCellID.Items.Count - 1 do begin Val(CheckListBoxCellID.Items[j], k, max_a); if ((max_a = 0) and (cell_id = k)) then begin CheckListBoxCellID.ItemIndex := j; break; end; end; end; end; end; end; procedure TvStripForm.CheckListBoxStreamsClick(Sender: TObject); begin if (CheckListBoxStreams.ItemIndex <> -1) then begin ListBoxRemap.ItemIndex := stream_info[stream_ofs + CheckListBoxStreams.ItemIndex].remap_to; if (CheckListBoxStreams.Checked[CheckListBoxStreams.ItemIndex]) then stream_info[stream_ofs + CheckListBoxStreams.ItemIndex].save := stream_info[stream_ofs + CheckListBoxStreams.ItemIndex].save or output_mask else stream_info[stream_ofs + CheckListBoxStreams.ItemIndex].save := stream_info[stream_ofs + CheckListBoxStreams.ItemIndex].save and (not output_mask); end; end; procedure TvStripForm.ButtonSaveSettingsClick(Sender: TObject); begin if (SaveSettingsDialog.Execute()) then begin SaveInitialDirectory(SaveSettingsDialog, vStripRegistryPath, SaveSettingsDialog.FileName); SaveSettings(SaveSettingsDialog.FileName); end; end; procedure TvStripForm.ButtonLoadSettingsClick(Sender: TObject); begin if (OpenSettingsDialog.Execute()) then begin SaveInitialDirectory(OpenSettingsDialog, vStripRegistryPath, OpenSettingsDialog.FileName); LoadSettings(OpenSettingsDialog.FileName); end; end; procedure TvStripForm.EditFileNameChange(Sender: TObject); begin if (EditFileName.Modified) then UpdateFileName(EditFileName.Text, RadioGroupOutputs, cur_output, num_output); end; procedure TvStripForm.RadioGroupOutputsClick(Sender: TObject); var i: Integer; begin GetOutputSettings(outputs[cur_output]); cur_output := RadioGroupOutputs.ItemIndex; PutOutputSettings(outputs[cur_output]); output_mask := 1 shl RadioGroupOutputs.ItemIndex; if (output_mask = $01) then begin LabelRemap.Enabled := not CheckBoxDemux.Checked; ListBoxRemap.Enabled := not CheckBoxDemux.Checked; end else begin LabelRemap.Enabled := False; ListBoxRemap.Enabled := False; end; for i := 0 to 255 do CheckListBoxStreams.Checked[i] := (stream_info[i + stream_ofs].save and output_mask) <> 0; end; procedure TvStripForm.TreeViewIFOContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); var it: TTreeNode; begin if ((MousePos.x <> -1) and (MousePos.y <> - 1)) then it := TreeViewIFO.GetNodeAt(MousePos.x, MousePos.y) else it := TreeViewIFO.Selected; if (it <> Nil) then begin PopupMenuIFO.Items[0].Enabled := True; PopupMenuIFO.Items[1].Enabled := True; PopupMenuIFO.Items[2].Enabled := True; PopupMenuItem := it; end else begin PopupMenuIFO.Items[0].Enabled := False; PopupMenuIFO.Items[1].Enabled := False; PopupMenuIFO.Items[2].Enabled := False; PopupMenuItem := Nil; end; end; procedure TvStripForm.SetStartLBAClick(Sender: TObject); var i, j: Integer; Top: TTreeNode; begin if (PopupMenuItem <> Nil) then begin if (PopupMenuItem.Parent <> Nil) then begin Top := PopupMenuItem.Parent; while (Top.Parent <> Nil) do Top := Top.Parent; i := Integer(Top.Data); j := Integer(PopupMenuItem.Data); if ((i < NumIFOChains) and (j < IFOChains[i].NumCells)) then EditStartLBA.Text := IntToStr(IFOChains[i].Cells[j].start_lba); end else begin i := Integer(PopupMenuItem.Data); if ((i < NumIFOChains) and (IFOChains[i].NumCells > 0)) then EditStartLBA.Text := IntToStr(IFOChains[i].Cells[0].start_lba); end; end; end; procedure TvStripForm.SetEndLBAClick(Sender: TObject); var i, j, k: Integer; Top: TTreeNode; begin if (PopupMenuItem <> Nil) then begin if (PopupMenuItem.Parent <> Nil) then begin Top := PopupMenuItem.Parent; while (Top.Parent <> Nil) do Top := Top.Parent; i := Integer(Top.Data); j := Integer(PopupMenuItem.Data); if ((i < NumIFOChains) and (j < IFOChains[i].NumCells)) then begin if (PopupMenuItem.Parent.Parent = Nil) then begin // Chapter k := j; while ((k < IFOChains[i].NumCells) and (IFOChains[i].Cells[j].chapter = IFOChains[i].Cells[k].chapter)) do Inc(k); EditEndLBA.Text := IntToStr(IFOChains[i].Cells[k - 1].end_lba); // Chapter End end else EditEndLBA.Text := IntToStr(IFOChains[i].Cells[j].end_lba); // Cell end; end else begin i := Integer(PopupMenuItem.Data); if ((i < NumIFOChains) and (IFOChains[i].NumCells > 0)) then EditEndLBA.Text := IntToStr(IFOChains[i].Cells[IFOChains[i].NumCells - 1].end_lba); end; end; end; procedure TvStripForm.ButtonUDFClick(Sender: TObject); var udf_sel: TUDFSelector; i: Integer; begin udf_sel := TUDFSelector.Create(vStripForm); udf_sel.ShowModal(); if (udf_sel.ModalResult > 0) then begin for i := 0 to udf_sel.ListBoxFiles.Items.Count - 1 do AddFile(udf_sel.ListBoxFiles.Items[i]); end; udf_sel.Free(); end; procedure TvStripForm.SetStartEndLBAClick(Sender: TObject); begin SetStartLBAClick(Sender); SetEndLBAClick(Sender); end; procedure TvStripForm.CheckBoxKeepGOPsClick(Sender: TObject); begin CheckBoxDVD2AVI.Enabled := not CheckBoxKeepGOPs.Checked; end; end.