//---------------------------------------------------------------------------
//	DVCapture
//  2002 - 2005 Stanislav Sumec <sumec@fit.vutbr.cz>
//
//	UnitMain.cpp
//  main form
//---------------------------------------------------------------------------
#include "dshow_hack.h"
#include <SysUtils.hpp>
#include <IniFiles.hpp>
#include <StrUtils.hpp>
#include <vcl.h>
#include <math.h>
//---------------------------------------------------------------------------
#pragma hdrstop
#include "DSTools.h"
#include "UnitMain.h"
#include "UnitSources.h"
#include "UnitSampleRate.h"
#include "UnitPreview.h"
#include "UnitAudioPreview.h"
#include "UnitVideoPreview.h"
#include "UnitRecording.h"
#include "fuuids.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TFormMain *FormMain;

const AnsiString SectionMain = "Main";
const AnsiString KeyChannelA = "Channel A";
const AnsiString KeyChannelV = "Channel V";
const MinDiskFree = 200;
//---------------------------------------------------------------------------

__fastcall TFormMain::TFormMain(TComponent* Owner): TForm(Owner) {
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::FormCreate(TObject *Sender) {
	ChangePos = true;
	WindowProc = NewWndProc;
	if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) {
  	ShowMessage("CoInitialize Failed!");
    exit(1);
  }

  ChangeVideo = ChangeAudio = true;
  ChangeFileName = true;
  pGraph = NULL;
  pBuild = NULL;
  pMC = NULL;
  pMS = NULL;

  if (InitCaptureGraphBuilder(&pGraph, &pBuild, &pMC) != S_OK) {
  	ShowMessage("CreateGraph Failed!");
    exit(1);
  }
  pGraph->QueryInterface(IID_IMediaSeeking,(LPVOID *) &pMS);

  g_dwGraphRegister = 0;
  AddGraphToRot(pGraph, &g_dwGraphRegister);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::FormDestroy(TObject *Sender) {
	ChangePos = false;
  pMC->Stop();
	if (g_dwGraphRegister != 0)
  	RemoveGraphFromRot(g_dwGraphRegister);

  ListViewSources->Items->Clear();
  SAFE_RELEASE(pMC);
  SAFE_RELEASE(pMS);
	SAFE_RELEASE(pGraph);
  SAFE_RELEASE(pBuild);

	CoUninitialize();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::FormShow(TObject *Sender) {
  ListViewSources->OnSelectItem(NULL, NULL, true);
  LoadINI(ExtractFileDir(Application->ExeName) + "\\DVCapture.ini");
  if (ListViewSources->Items->Count > 0)
    CheckBoxPreview->Checked = true;
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::Open1Click(TObject *Sender) {
  if (OpenDialog1->Execute()) {
    LoadINI(OpenDialog1->FileName);
    if (ListViewSources->Items->Count > 0)
    	CheckBoxPreview->Checked = true;
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::Save1Click(TObject *Sender) {
  if (SaveDialog1->Execute()) {
    SaveINI(SaveDialog1->FileName);
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::Exit1Click(TObject *Sender) {
	Close();
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::About1Click(TObject *Sender) {
  ShowMessage("DVCapture (Compiled: " + AnsiString(__DATE__) + ")\n2002 - 2005 Stanislav Sumec\nBrno University of Technology\nFaculty of Information Technology");
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// Aux DS methods -----------------------------------------------------------
//---------------------------------------------------------------------------

void TFormMain::AddFilterToGraph(REFCLSID rclsid, IBaseFilter **ppv, const char *Name) {
  *ppv = NULL;
  int hr;
  LPVOID pv;
  hr = CoCreateInstance(rclsid, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)(&pv));
  if (SUCCEEDED(hr)) {
    AnsiString n = Name;
    wchar_t wn[1024];
    n.WideChar(wn, 1024);
    hr = pGraph->AddFilter((IBaseFilter*)pv, wn);
    if (SUCCEEDED(hr)) {
      *ppv = (IBaseFilter*)pv;
    } else {
      ((IBaseFilter*)pv)->Release();
    }
  }
  if (*ppv == NULL)
    ShowMessage(AnsiString("Could not add filter!\n") + Name);
}
//---------------------------------------------------------------------------

bool TFormMain::ConnectF2F(const GUID *pType, IBaseFilter *fin, IBaseFilter *fout, bool ShowError) {
  bool b = (SUCCEEDED(pBuild->RenderStream(0, pType, fin, 0, fout)));
  if (!b && ShowError) {
    AnsiString Message = "Could not connect filters!";
    FILTER_INFO Info;
    if (fin->QueryFilterInfo(&Info) == S_OK) {
    	Message = Message + "\n" + Info.achName;
      if (Info.pGraph != NULL)
      	Info.pGraph->Release();
    }
    if (fout->QueryFilterInfo(&Info) == S_OK) {
    	Message = Message + "\n" + Info.achName;
      if (Info.pGraph != NULL)
      	Info.pGraph->Release();
    }
    ShowMessage(Message);
  }
  return b;
}
//---------------------------------------------------------------------------

bool TFormMain::SetFileName(IBaseFilter *f, const char *Name) {
  IFileSinkFilter *pSink;
  int hr = f->QueryInterface(IID_IFileSinkFilter, (void**)(&pSink));
  if (SUCCEEDED(hr)) {
    AnsiString n  = Name;
    int bs = n.WideCharBufSize();
    wchar_t *wn = new wchar_t[bs];
    n.WideChar(wn, bs);
    pSink->SetFileName(wn, NULL);
    pSink->Release();
    delete[] wn;
    return true;
  }
  ShowMessage(AnsiString("Could not set file name: ") + Name);
  return false;
}
//---------------------------------------------------------------------------

void TFormMain::StartPreview() {
  for (int i = 0; i < ListViewSources->Items->Count; i++) {
    TAVSource *s = ((TAVSource*)(ListViewSources->Items->Item[i]->Data));
    if (s->VideoPreview || s->AudioPreview || CheckBoxPreview->Checked) {
      pMC->Run();
      return;
    }
  }
}
//---------------------------------------------------------------------------

void TFormMain::RunStopGraph() {
  pMC->Run();
  Sleep(1000);
  pMC->Stop();
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

bool TFormMain::AddVideoSource(AnsiString Name) {
	int IDLength = FormSources->GetVideoSourceID().Length();
	AnsiString DName = Name.SubString(1 + IDLength, Name.Length() - IDLength);

  ICreateDevEnum *pDevEnum = NULL;
  IEnumMoniker *pEnum = NULL;

  // Create the System Device Enumerator.
  HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)(&pDevEnum));
  if (SUCCEEDED(hr)) {
    // Create an enumerator for the video capture category.
    hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);

    if (pEnum != NULL) {
      IMoniker *pMoniker = NULL;
      while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
        IPropertyBag *pPropBag;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
        if (FAILED(hr)) {
        	pMoniker->Release();
          continue;  // Skip this one, maybe the next one will work.
        }
        // Find the description or friendly name.
        VARIANT varName;
        VariantInit(&varName);
        hr = pPropBag->Read(L"Description", &varName, 0);
        if (FAILED(hr)) {
        	hr = pPropBag->Read(L"FriendlyName", &varName, 0);
        }

        if (SUCCEEDED(hr)) {
          if (AnsiString(varName.bstrVal) == DName) {
            VariantClear(&varName);

            TAVSource AVSource;
            AVSource.Type = 0;
            AVSource.VideoFormat = 0;
            AVSource.File = "";
            AVSource.VideoPreview = false;
            AVSource.AudioPreview = false;
            AVSource.Init();

            hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&AVSource.pCap);
            if (SUCCEEDED(hr)) {
                hr = pGraph->AddFilter(AVSource.pCap, L"Capture Filter");

        				pPropBag->Release();
                pMoniker->Release();

                pEnum->Release();
                pDevEnum->Release();

                AddFilterToGraph(CLSID_DVSplitter, &AVSource.pDVSplit, "DV Splitter");
                AddFilterToGraph(CLSID_InfTee, &AVSource.pInfTee, "Video Infinite Pin Tee Filter");
                AddFilterToGraph(CLSID_InfTee, &AVSource.pInfTeeAudio, "Audio Infinite Pin Tee Filter");

                if (AVSource.pDVSplit != NULL && AVSource.pInfTee != NULL && AVSource.pInfTeeAudio != NULL) {
                  if (ConnectF2F(&MEDIATYPE_Interleaved, AVSource.pCap, AVSource.pDVSplit, false) &&
                      ConnectF2F(&MEDIATYPE_Video, AVSource.pDVSplit, AVSource.pInfTee, false) &&
                      ConnectF2F(&MEDIATYPE_Audio, AVSource.pDVSplit, AVSource.pInfTeeAudio, false)) {

                    TListItem *li = ListViewSources->Items->Add();
                    li->Caption = Name;
                    li->Data = new TAVSource;
                    (*((TAVSource*)(li->Data))) = AVSource;
                    ListViewSources->Selected = li;
                    return true;
                  } else {
                  	SAFE_REMOVE(pGraph, AVSource.pDVSplit);
                    SAFE_REMOVE(pGraph, AVSource.pInfTeeAudio);
                    if (ConnectF2F(NULL, AVSource.pCap, AVSource.pInfTee, false)) {
                    	AVSource.VideoFormat = 2;
                      TListItem *li = ListViewSources->Items->Add();
                      li->Caption = Name;
                      li->Data = new TAVSource;
                      (*((TAVSource*)(li->Data))) = AVSource;
                      ListViewSources->Selected = li;
                      return true;
                    }
                  }
                }

                ShowMessage("Could not add source: " + Name);
                AVSource.Release(pGraph);
                return false;
            }
          } else
            VariantClear(&varName);
        }
        pPropBag->Release();
        pMoniker->Release();
      }
    }
    SAFE_RELEASE(pEnum);
    SAFE_RELEASE(pDevEnum);
	}
  return false;
}
//---------------------------------------------------------------------------

bool TFormMain::AddAudioSource(AnsiString Name) {
	int IDLength = FormSources->GetAudioSourceID().Length();
	AnsiString DName = Name.SubString(1 + IDLength, Name.Length() - IDLength);

  ICreateDevEnum *pDevEnum = NULL;
  IEnumMoniker *pEnum = NULL;

  // Create the System Device Enumerator.
  HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)(&pDevEnum));
  if (SUCCEEDED(hr)) {
    // Create an enumerator for the audio capture category.
    hr = pDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEnum, 0);

    if (pEnum != NULL) {
      IMoniker *pMoniker = NULL;
      while (pEnum->Next(1, &pMoniker, NULL) == S_OK) {
        IPropertyBag *pPropBag;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
        if (FAILED(hr)) {
          pMoniker->Release();
          continue;  // Skip this one, maybe the next one will work.
        }
        // Find the description or friendly name.
        VARIANT varName;
        VariantInit(&varName);
        hr = pPropBag->Read(L"Description", &varName, 0);
        if (FAILED(hr)) {
          hr = pPropBag->Read(L"FriendlyName", &varName, 0);
        }

        if (SUCCEEDED(hr)) {
          if (AnsiString(varName.bstrVal) == DName) {
            VariantClear(&varName);

            TAVSource AVSource;
            AVSource.Type = 1;
            AVSource.VideoFormat = 0;
            AVSource.File = "";
            AVSource.VideoPreview = false;
            AVSource.AudioPreview = false;
            AVSource.Init();

            hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&AVSource.pCap);
            if (SUCCEEDED(hr)) {
                hr = pGraph->AddFilter(AVSource.pCap, L"Capture Filter");

        				pPropBag->Release();
                pMoniker->Release();

                pEnum->Release();
                pDevEnum->Release();

                AddFilterToGraph(CLSID_InfTee, &AVSource.pInfTee, "Infinite Pin Tee Filter");
                if (AVSource.pInfTee != NULL) {
                  if (ConnectF2F(&MEDIATYPE_Audio, AVSource.pCap, AVSource.pInfTee)) {
                    TListItem *li = ListViewSources->Items->Add();
                    li->Caption = Name;
                    li->Data = new TAVSource;
                    (*((TAVSource*)(li->Data))) = AVSource;
                    ListViewSources->Selected = li;
                    return true;
                  }
                }

                ShowMessage("Could not add source: " + Name);
                AVSource.Release(pGraph);
                return false;
            }

          } else
            VariantClear(&varName);
        }
        pPropBag->Release();
        pMoniker->Release();
      }
    }
    SAFE_RELEASE(pEnum);
    SAFE_RELEASE(pDevEnum);
	}
  return false;
}
//---------------------------------------------------------------------------

void TFormMain::RemoveOutputFilters() {
  for (int i = 0; i < ListViewSources->Items->Count; i++) {
    TAVSource *s = ((TAVSource*)(ListViewSources->Items->Item[i]->Data));
    SAFE_REMOVE(pGraph, s->pAVIMux);
    SAFE_REMOVE(pGraph, s->pFileWriter);
    SAFE_REMOVE(pGraph, s->pMPEG2TSOutputDemux);
    SAFE_REMOVE(pGraph, s->pWAVEDst);
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ButtonAddClick(TObject *Sender) {
	if (FormSources->ShowModal() == mrOk) {
  	bool PreviewAll = CheckBoxPreview->Checked;
    if (PreviewAll)
    	CheckBoxPreview->Checked = false;
  	for (int i = 0; i < FormSources->ListBoxSources->Items->Count; i++) {
    	if (FormSources->ListBoxSources->Selected[i]) {
        AnsiString Name = FormSources->ListBoxSources->Items->Strings[i];
        if (FormSources->IsVideoSource(Name))
          AddVideoSource(Name);
        else if (FormSources->IsAudioSource(Name))
          AddAudioSource(Name);
        ListViewSources->OnSelectItem(ListViewSources, ListViewSources->Selected, true);
      }
    }
    if (PreviewAll)
    	CheckBoxPreview->Checked = true;
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ButtonRemoveClick(TObject *Sender) {
  if (ListViewSources->Selected != NULL) {
	  TAVSource *s = ((TAVSource*)(ListViewSources->Selected->Data));
    CheckBoxVideoPreview->Checked = false;
    CheckBoxAudioPreview->Checked = false;
    bool PreviewAll = CheckBoxPreview->Checked;
    if (PreviewAll)
    	CheckBoxPreview->Checked = false;
    ListViewSources->Selected->Delete();
    ListViewSources->OnSelectItem(ListViewSources, ListViewSources->Selected, true);
    if (PreviewAll)
    	CheckBoxPreview->Checked = true;
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ButtonPropertiesClick(TObject *Sender) {
  if (ListViewSources->Selected != NULL) {
    TAVSource *s = ((TAVSource*)(ListViewSources->Selected->Data));
    ShowFilterProperties(Handle, s->pCap);
  }
  ListViewSources->OnSelectItem(ListViewSources, ListViewSources->Selected, true);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ButtonRecordClick(TObject *Sender) {
  if (ListViewSources->Items->Count == 0)
    return;

  pMC->Stop();
  RemoveOutputFilters();

  AnsiString DateTime = EditDirectoryName->Text;
  if (CheckBoxDateTime->Checked) {
    DateTime += "D" + FormatDateTime("yyyy-mm-dd", Now());
    DateTime += "-T" + FormatDateTime("hh-nn-ss", Now());
  }

  for (int i = 0; i < ListViewSources->Items->Count; i++) {
    TAVSource *s = ((TAVSource*)(ListViewSources->Items->Item[i]->Data));
    if (s->File == "") {
      ShowMessage(ListViewSources->Items->Item[i]->Caption + ": File name is missing!");
      RemoveOutputFilters();
      StartPreview();
      return;
    }

    AnsiString FileName = GetIndexName(DateTime + "\\" + s->File);
    if (!ForceDirectories(ExtractFileDir(FileName))) {
      ShowMessage(ListViewSources->Items->Item[i]->Caption + ": Could not create directory!");
      RemoveOutputFilters();
      StartPreview();
      return;
    }

    if (s->Type == 0) {
	    if (s->pDVSplit != NULL) {
      	// DV
        AddFilterToGraph(CLSID_AviDest, &s->pAVIMux, "AVI Mux");
	      AddFilterToGraph(CLSID_FileWriter, &s->pFileWriter, "AVI File Writer");

        if (s->pAVIMux == NULL ||
            s->pFileWriter == NULL ||
            !ConnectF2F(&MEDIATYPE_Video, s->pInfTee, s->pAVIMux) ||
            !ConnectF2F(&MEDIATYPE_Audio, s->pInfTeeAudio, s->pAVIMux) ||
            !ConnectF2F(&MEDIATYPE_Stream, s->pAVIMux, s->pFileWriter) ||
            !SetFileName(s->pFileWriter, ExchangeExt(FileName, ".avi").c_str())) {
          RemoveOutputFilters();
          StartPreview();
          return;
        }
      } else {
      	// HDV
        if (s->VideoFormat == 1) {
          AddFilterToGraph(CLSID_CineFormDumper, &s->pFileWriter, "MPEG2TS File Writer");

          if (s->pFileWriter == NULL ||
              !ConnectF2F(NULL, s->pInfTee, s->pFileWriter) ||
              !SetFileName(s->pFileWriter, ExchangeExt(FileName, ".m2t").c_str())) {
            RemoveOutputFilters();
            StartPreview();
            return;
          }

          TimerHack->Enabled = true;
          ShowFilterProperties(Handle, s->pFileWriter);
          TimerHack->Enabled = false;
        } else {
	        AddFilterToGraph(CLSID_MoonlightDemuxer, &s->pMPEG2TSOutputDemux, "MPEG2TS Demuxer");
          AddFilterToGraph(CLSID_MoonlightMultiplex, &s->pAVIMux, "MPEG2PS Muxer");
        	AddFilterToGraph(CLSID_Dump, &s->pFileWriter, "MPEG2PS File Writer");

          if (s->pMPEG2TSOutputDemux != NULL) {
          	if (ConnectF2F(NULL, s->pInfTee, s->pMPEG2TSOutputDemux))
		          RunStopGraph();
          }

          if (s->pMPEG2TSOutputDemux == NULL ||
	          	s->pAVIMux == NULL ||
              s->pFileWriter == NULL ||
              !ConnectF2F(&MEDIATYPE_Video, s->pMPEG2TSOutputDemux, s->pAVIMux) ||
              !ConnectF2F(&MEDIATYPE_Audio, s->pMPEG2TSOutputDemux, s->pAVIMux) ||
              !ConnectF2F(&MEDIATYPE_Stream, s->pAVIMux, s->pFileWriter) ||
              !SetFileName(s->pFileWriter, ExchangeExt(FileName, ".mpg").c_str())) {
            RemoveOutputFilters();
            StartPreview();
            return;
          }
        }
      }
    } else {
      AddFilterToGraph(CLSID_WavDest, &s->pWAVEDst, "WAVE Dst");
      AddFilterToGraph(CLSID_FileWriter, &s->pFileWriter, "Wave File Writer");

      if (s->pWAVEDst == NULL ||
          s->pFileWriter == NULL ||
          !ConnectF2F(&MEDIATYPE_Audio, s->pInfTee, s->pWAVEDst) ||
          !ConnectF2F(&MEDIATYPE_Stream, s->pWAVEDst, s->pFileWriter) ||
          !SetFileName(s->pFileWriter, ExchangeExt(FileName, ".wav").c_str())) {
        RemoveOutputFilters();
        StartPreview();
        return;
      }
    }
  }

  bool PreviewAll = CheckBoxPreview->Checked;
  if (PreviewAll)
    CheckBoxPreview->Checked = false;

  SaveINI(DateTime + "\\Description.ini");

	pMC->Run();
  Caption = Application->Title + " (Recording)";

	StartDiskFree = -1;
  StartTime = -1;
	TimerRecord->Enabled = true;
  TimerRecord->OnTimer(TimerRecord);
  int mr = FormRecording->ShowModal();
  TimerRecord->Enabled = false;

  LONGLONG Duration;
  if (pMS != NULL && pMS->GetCurrentPosition(&Duration) == S_OK) {
    int t = Round(Duration / 10000000.0);
    AnsiString Text;
    Text.printf("%.2d:%.2d:%.2d", (t / 60) / 60, (t / 60) % 60, t % 60);
    Caption = Application->Title + " (Recorded " + Text + ")";
  } else
  	Caption = Application->Title;

  pMC->Stop();
  RemoveOutputFilters();

  StartPreview();
  if (PreviewAll)
    CheckBoxPreview->Checked = true;

  if (mr == mrAbort) {
  	Beep();
  	ShowMessage("Less than " + IntToStr(MinDiskFree) + "MB free!");
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ListViewSourcesDeletion(TObject *Sender, TListItem *Item) {
  TAVSource *av = ((TAVSource*)(Item->Data));
  RemoveFilters(pGraph, av->VideoPreviewFilters);
  RemoveFilters(pGraph, av->VideoPreviewFilters2);
  RemoveFilters(pGraph, av->AudioPreviewFilters);
  av->Release(pGraph);
  delete av;
}
//---------------------------------------------------------------------------

void TFormMain::SelectComboBoxItem(TComboBox *ComboBox, AnsiString Value) {
  ComboBox->ItemIndex = ComboBox->Items->IndexOf(Value);
  if (ComboBox->ItemIndex < 0)
    ComboBox->ItemIndex = ComboBox->Items->Add(Value);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ListViewSourcesSelectItem(TObject *Sender, TListItem *Item, bool Selected) {
  if (Selected) {
    ChangeVideo = ChangeAudio = false;

    bool e = Item != NULL;
    ChangeFileName = false;
    EditFileName->Enabled = e;
    ButtonFileName->Enabled = e;
    ButtonRate->Enabled = e;
    CheckBoxVideoPreview->Enabled = e;
    CheckBoxAudioPreview->Enabled = e;
    TrackBarVolume->Enabled = e;
    TrackBarBalance->Enabled = e;

    ComboBoxChannels->Items->Clear();
    ComboBoxBits->Items->Clear();
    ComboBoxRate->Items->Clear();
    ComboBoxInput->Items->Clear();

    ComboBoxWidth->Items->Clear();
    ComboBoxHeight->Items->Clear();

    ComboBoxChannels->Enabled = e;
    ComboBoxBits->Enabled = e;
    ComboBoxRate->Enabled = e;
    ComboBoxInput->Enabled = e;

    ComboBoxWidth->Enabled = e;
    ComboBoxHeight->Enabled = e;

    RadioButtonVFAVI->Enabled = false;
    RadioButtonVFMPEG2TS->Enabled = false;
    RadioButtonVFMPEG2PS->Enabled = false;
    RadioButtonVFAVI->Checked = false;
    RadioButtonVFMPEG2TS->Checked = false;
    RadioButtonVFMPEG2PS->Checked = false;

    int hr;
    if (e) {
      TAVSource *av = ((TAVSource*)(Item->Data));

      EditFileName->Text = av->File;
      CheckBoxVideoPreview->Checked = av->VideoPreview;
      CheckBoxAudioPreview->Checked = av->AudioPreview;

      if (av->Type == 0) {
	      PageControl->ActivePageIndex = 1;
        TrackBarVolume->Position = 0;
        TrackBarBalance->Position = 0;
        LabelVolume->Caption = "";
        LabelBalance->Caption = "";

        int width, height, frames;
        VIDEO_STREAM_CONFIG_CAPS scc;

        SetVideoParams(pBuild, av->pCap, 360, 288, 25);
        GetVideoParams(pBuild, av->pCap, width, height, frames, scc);

        for (unsigned int i = scc.MinCroppingSize.cx; i <= scc.MaxCroppingSize.cx; i += scc.CropGranularityX)
          ComboBoxWidth->Items->Add(IntToStr(i));

        for (unsigned int i = scc.MinCroppingSize.cy; i <= scc.MaxCroppingSize.cy; i += scc.CropGranularityY)
          ComboBoxHeight->Items->Add(IntToStr(i));

        SelectComboBoxItem(ComboBoxWidth, width);
        SelectComboBoxItem(ComboBoxHeight, height);

        if (av->pDVSplit != NULL) {
        	RadioButtonVFAVI->Enabled = true;
          RadioButtonVFAVI->Checked = true;
          av->VideoFormat = 0;
        } else {
        	RadioButtonVFMPEG2TS->Enabled = true;
    			RadioButtonVFMPEG2PS->Enabled = true;
          if (av->VideoFormat == 1)
          	RadioButtonVFMPEG2TS->Checked = true;
          else {
          	RadioButtonVFMPEG2PS->Checked = true;
            av->VideoFormat = 2;
          }
        }
      } else {
      	CheckBoxVideoPreview->Enabled = false;
      	PageControl->ActivePageIndex = 0;
        int rate, bits, chn;
        AUDIO_STREAM_CONFIG_CAPS scc;
        GetAudioParams(pBuild, av->pCap, rate, bits, chn, scc);

        for (unsigned int i = scc.MinimumChannels; i <= scc.MaximumChannels; i += scc.ChannelsGranularity)
          ComboBoxChannels->Items->Add(IntToStr(i));
        for (unsigned int i = scc.MinimumBitsPerSample; i <= scc.MaximumBitsPerSample; i += scc.BitsPerSampleGranularity)
          ComboBoxBits->Items->Add(IntToStr(i));
        for (unsigned int i = scc.MinimumSampleFrequency; i <= scc.MaximumSampleFrequency; i += scc.SampleFrequencyGranularity)
          ComboBoxRate->Items->Add(IntToStr(i));

        SelectComboBoxItem(ComboBoxChannels, chn);
        SelectComboBoxItem(ComboBoxBits, bits);
        SelectComboBoxItem(ComboBoxRate, rate);

        Pins pins = GetPins(av->pCap, PINDIR_INPUT);

        for (int i = 0; i < pins.size(); i++)
          ComboBoxInput->Items->Add(GetPinName(pins[i]));

        ComboBoxInput->ItemIndex = FindSelectedPin(pins);
        if (ComboBoxInput->ItemIndex >= 0) {
          double level, pan;
          bool enabled;
          GetPinParams(pins[ComboBoxInput->ItemIndex], level, pan, enabled);
          TrackBarVolume->Position = Round(100.0 * level);
          TrackBarBalance->Position = Round(50.0 * pan);

          LabelVolume->Caption = FloatToStr(level);
          LabelBalance->Caption = FloatToStr(pan);
        }

        ReleasePins(pins);
      }
    } else {
      EditFileName->Text = "";
      CheckBoxVideoPreview->Checked = false;
      CheckBoxAudioPreview->Checked = false;
      TrackBarVolume->Position = 0;
      TrackBarBalance->Position = 0;
      LabelVolume->Caption = "";
      LabelBalance->Caption = "";
      PageControl->ActivePageIndex = 0;
    }

    ChangeVideo = ChangeAudio = true;
    ChangeFileName = true;
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ButtonFileNameClick(TObject *Sender) {
  if (SaveDialog->Execute())
    EditDirectoryName->Text = SaveDialog->FileName;
}
//---------------------------------------------------------------------------

void TFormMain::SaveINI(AnsiString FileName) {
  TIniFile *ini = new TIniFile(FileName);

  TStringList *Sections = new TStringList();
  try {
    ini->ReadSections(Sections);
    for (int i = 0; i < Sections->Count; i++)
      ini->EraseSection(Sections->Strings[i]);
  } __finally {
    delete Sections;
  }

  ini->WriteString(SectionMain, "Directory", EditDirectoryName->Text);
  ini->WriteBool(SectionMain, "Add date time", CheckBoxDateTime->Checked);
  for (int i = 0; i < ListViewSources->Items->Count; i++) {
    AnsiString n = ListViewSources->Items->Item[i]->Caption;
    TAVSource *s = ((TAVSource*)(ListViewSources->Items->Item[i]->Data));
    if (s->File != NULL) {
      ini->WriteString(n, "File", s->File);
      ini->WriteBool(n, "Video preview", s->VideoPreview);
      ini->WriteBool(n, "Audio preview", s->AudioPreview);
      ini->WriteInteger(n, "Video format", s->VideoFormat);

      for (int j = 0; j < s->AudioChannels.size(); j++)
        ini->WriteString(n, KeyChannelA + IntToStr(j + 1), s->AudioChannels[j]);
      for (int j = 0; j < s->VideoChannels.size(); j++)
        ini->WriteString(n, KeyChannelV + IntToStr(j + 1), s->VideoChannels[j]);

      if (s->Type == 0) {
      } else {
        int rate, bits, chn;
        GetAudioParams(pBuild, s->pCap, rate, bits, chn);
        ini->WriteInteger(n, "Rate", rate);
        ini->WriteInteger(n, "Bits", bits);
        ini->WriteInteger(n, "Channels", chn);

        Pins pins = GetPins(s->pCap, PINDIR_INPUT);

        int Pin = FindSelectedPin(pins);
        if (Pin >= 0) {
          double level, pan;
          bool enabled;
          GetPinParams(pins[Pin], level, pan, enabled);

          ini->WriteString(n, "Input", GetPinName(pins[Pin]));
          ini->WriteFloat(n, "Volume", level);
          ini->WriteFloat(n, "Balance", pan);
        }
        ReleasePins(pins);
      }
    }
  }
  delete ini;
}
//---------------------------------------------------------------------------

void TFormMain::LoadINI(AnsiString FileName) {
  ListViewSources->Items->Clear();
  TIniFile *ini = new TIniFile(FileName);
  EditDirectoryName->Text = ini->ReadString(SectionMain, "Directory", "");
  CheckBoxDateTime->Checked = ini->ReadBool(SectionMain, "Add date time", true);

  TStringList *nl = new TStringList();
  ini->ReadSections(nl);
  for (int i = 0; i < nl->Count; i++) {
    AnsiString n = nl->Strings[i];
    if (n != SectionMain) {
      bool ok;
      if (FormSources->IsVideoSource(n)) {
        ok = AddVideoSource(n);
      } else if (FormSources->IsAudioSource(n)) {
        ok = AddAudioSource(n);
      } else
      	ok = false;

      if (ok) {
        TAVSource *s = ((TAVSource*)(ListViewSources->Items->Item[ListViewSources->Items->Count - 1]->Data));

        TStringList *Values = new TStringList();
        try {
          ini->ReadSection(n, Values);
          for (int j = 0; j < Values->Count; j++) {
            if (AnsiStartsText(KeyChannelA, Values->Strings[j])) {
              int Number = StrToIntDef(Values->Strings[j].SubString(KeyChannelA.Length() + 1, Values->Strings[j].Length() - KeyChannelA.Length()), 0) - 1;
              if (Number >= 0) {
                if (Number >= s->AudioChannels.size())
                  s->AudioChannels.resize(Number + 1);
                s->AudioChannels[Number] = ini->ReadString(n, Values->Strings[j], "");
              }
            }

            if (AnsiStartsText(KeyChannelV, Values->Strings[j])) {
              int Number = StrToIntDef(Values->Strings[j].SubString(KeyChannelV.Length() + 1, Values->Strings[j].Length() - KeyChannelV.Length()), 0) - 1;
              if (Number >= 0) {
                if (Number >= s->VideoChannels.size())
                  s->VideoChannels.resize(Number + 1);
                s->VideoChannels[Number] = ini->ReadString(n, Values->Strings[j], "");
              }
            }
          }
        } __finally {
          delete Values;
        }

        s->File = ini->ReadString(n, "File", "");
        s->VideoPreview = ini->ReadBool(n, "Video preview", false);
        s->AudioPreview = ini->ReadBool(n, "Audio preview", false);
        s->VideoFormat = ini->ReadInteger(n, "Video format", 0);

        if (s->Type == 0) {
        } else {
          SetAudioParams(pBuild, s->pCap, ini->ReadInteger(n, "Rate", 44100), ini->ReadInteger(n, "Bits", 16), ini->ReadInteger(n, "Channels", 2));

          Pins pins = GetPins(s->pCap, PINDIR_INPUT);
          AnsiString Input = ini->ReadString(n, "Input", "unknown");
          if (Input != "unknown") {
            int Pin = FindPin(pins, Input);
            if (Pin < 0)
              ShowMessage("Could not find input: " + Input);
            else
              for (int i = 0; i < pins.size(); i++) {
                double level, pan;
                bool enabled;
                GetPinParams(pins[Pin], level, pan, enabled);
                enabled = i == Pin;
                if (enabled) {
                  level = ini->ReadFloat(n, "Volume", 1);
                  pan = ini->ReadFloat(n, "Balance", 0);
                }
                SetPinParams(pins[Pin], level, pan, enabled);
              }
          }
          ReleasePins(pins);
        }
      }
    }
  }
  delete nl;
  delete ini;

  ListViewSources->OnSelectItem(ListViewSources, ListViewSources->Selected, true);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::CheckBoxVideoPreviewClick(TObject *Sender) {
  if (ListViewSources->Selected != NULL) {
    TAVSource *s = ((TAVSource*)(ListViewSources->Selected->Data));
    if (s->VideoPreview != CheckBoxVideoPreview->Checked) {
	    pMC->Stop();
      if (s->Type == 0) {
        if (CheckBoxVideoPreview->Checked) {
          TIBaseFilters OldFilters = GetFilters(pGraph);

          if (s->pDVSplit != NULL) {
            // DV
            AddFilterToGraph(CLSID_DVVideoCodec, &s->pDVDecoder, "DV Decoder");
            AddFilterToGraph(CLSID_VideoRenderer, &s->pVideoRenderer, "Video Renderer");
            if (s->pDVDecoder != NULL && s->pVideoRenderer != NULL) {
              if (!(ConnectF2F(&MEDIATYPE_Video, s->pInfTee, s->pDVDecoder) &&
                    ConnectF2F(&MEDIATYPE_Video, s->pDVDecoder, s->pVideoRenderer))) {
                SAFE_REMOVE(pGraph, s->pDVDecoder);
                SAFE_REMOVE(pGraph, s->pVideoRenderer);
              }
            } else {
              SAFE_REMOVE(pGraph, s->pDVDecoder);
              SAFE_REMOVE(pGraph, s->pVideoRenderer);
            }
          } else {
            // HDV
            AddFilterToGraph(CLSID_MoonlightDemuxer, &s->pMPEG2TSDemux, "MPEG2TS Demuxer");
            AddFilterToGraph(CLSID_VideoRenderer, &s->pVideoRenderer, "Video Renderer");
            if (s->pMPEG2TSDemux != NULL && s->pVideoRenderer != NULL) {
              if (ConnectF2F(NULL, s->pInfTee, s->pMPEG2TSDemux)) {
                RunStopGraph();
                if (!ConnectF2F(&MEDIATYPE_Video, s->pMPEG2TSDemux, s->pVideoRenderer)) {
                  SAFE_REMOVE(pGraph, s->pDVDecoder);
                  SAFE_REMOVE(pGraph, s->pVideoRenderer);
                }
              } else {
                SAFE_REMOVE(pGraph, s->pDVDecoder);
                SAFE_REMOVE(pGraph, s->pVideoRenderer);
              }
            } else {
              SAFE_REMOVE(pGraph, s->pVideoRenderer);
              SAFE_REMOVE(pGraph, s->pVideoRenderer);
            }
          }

          s->VideoPreviewFilters = GetNewFilters(pGraph, OldFilters);
          ReleaseFilters(OldFilters);
        } else {
          RemoveFilters(pGraph, s->VideoPreviewFilters);
          SAFE_RELEASE(s->pVideoRenderer);
          SAFE_RELEASE(s->pDVDecoder);
          SAFE_RELEASE(s->pMPEG2TSDemux);
        }
      }
      s->VideoPreview = CheckBoxVideoPreview->Checked;
      StartPreview();
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::CheckBoxAudioPreviewClick(TObject *Sender) {
  if (ListViewSources->Selected != NULL) {
    TAVSource *s = ((TAVSource*)(ListViewSources->Selected->Data));
    if (s->AudioPreview != CheckBoxAudioPreview->Checked) {
      pMC->Stop();
      if (s->Type == 0) {
        if (CheckBoxAudioPreview->Checked) {
          TIBaseFilters OldFilters = GetFilters(pGraph);

          if (s->pDVSplit == NULL) {
            // HDV
            AddFilterToGraph(CLSID_InfTee, &s->pInfTeeAudio, "Audio Infinite Pin Tee Filter");
            AddFilterToGraph(CLSID_MoonlightDemuxer, &s->pMPEG2TSDemux3, "MPEG2TS Demuxer3");

            if (s->pMPEG2TSDemux3 != NULL && s->pInfTeeAudio != NULL) {
              if (ConnectF2F(NULL, s->pInfTee, s->pMPEG2TSDemux3)) {
                RunStopGraph();
                if (!ConnectF2F(&MEDIATYPE_Audio, s->pMPEG2TSDemux3, s->pInfTeeAudio)) {
                  SAFE_REMOVE(pGraph, s->pMPEG2TSDemux3);
                  SAFE_REMOVE(pGraph, s->pInfTeeAudio);
                }
              } else {
                SAFE_REMOVE(pGraph, s->pMPEG2TSDemux3);
                SAFE_REMOVE(pGraph, s->pInfTeeAudio);
              }
            } else {
              SAFE_REMOVE(pGraph, s->pMPEG2TSDemux3);
              SAFE_REMOVE(pGraph, s->pInfTeeAudio);
            }
          }

          if (s->pInfTeeAudio != NULL) {
            AddFilterToGraph(CLSID_Scope, &s->pScope, "Scope");
            if (s->pScope != NULL) {
              if (!(ConnectF2F(&MEDIATYPE_Audio, s->pInfTeeAudio, s->pScope)))
                SAFE_REMOVE(pGraph, s->pScope);
            }

            AddFilterToGraph(CLSID_AudioRender, &s->pAudioRenderer, "Audio Renderer");
            if (s->pAudioRenderer != NULL) {
              if (!(ConnectF2F(&MEDIATYPE_Audio, s->pInfTeeAudio, s->pAudioRenderer)))
                SAFE_REMOVE(pGraph, s->pAudioRenderer);
            }
          }

          s->AudioPreviewFilters = GetNewFilters(pGraph, OldFilters);
          ReleaseFilters(OldFilters);
        } else {
          RemoveFilters(pGraph, s->AudioPreviewFilters);
          SAFE_RELEASE(s->pScope);
          SAFE_RELEASE(s->pAudioRenderer);
          if (s->pDVSplit == NULL) {
            // HDV
            SAFE_RELEASE(s->pInfTeeAudio);
          }
        }
      } else {
        if (CheckBoxAudioPreview->Checked) {
          AddFilterToGraph(CLSID_Scope, &s->pScope, "Scope");
          if (s->pScope != NULL) {
            if (!(ConnectF2F(&MEDIATYPE_Audio, s->pInfTee, s->pScope)))
              SAFE_REMOVE(pGraph, s->pScope);
          }

          AddFilterToGraph(CLSID_AudioRender, &s->pAudioRenderer, "Audio Renderer");
          if (s->pAudioRenderer != NULL) {
            if (!(ConnectF2F(&MEDIATYPE_Audio, s->pInfTee, s->pAudioRenderer)))
              SAFE_REMOVE(pGraph, s->pAudioRenderer);
          }
        } else {
          SAFE_REMOVE(pGraph, s->pScope);
          SAFE_REMOVE(pGraph, s->pAudioRenderer);
        }
      }
      s->AudioPreview = CheckBoxAudioPreview->Checked;
      StartPreview();
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ComboBoxAudioChange(TObject *Sender) {
  if (!ChangeAudio)
    return;

  if (ListViewSources->Selected == NULL)
    return;
    
  TAVSource *av = (TAVSource*)ListViewSources->Selected->Data;
  if (av == NULL)
    return;

  if (av->Type == 0) {
  } else {
    int rate, bits, chn;
    if (TryStrToInt(ComboBoxRate->Text, rate) &&
        TryStrToInt(ComboBoxBits->Text, bits) &&
        TryStrToInt(ComboBoxChannels->Text, chn))
      SetAudioParams(pBuild, av->pCap, rate, bits, chn);
  }

  ListViewSources->OnSelectItem(ListViewSources, ListViewSources->Selected, true);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ButtonRateClick(TObject *Sender) {
  if (ListViewSources->Selected == NULL)
    return;

  TAVSource *av = (TAVSource*)ListViewSources->Selected->Data;
  if (av == NULL)
    return;

  if (FormSampleRate->ShowModal() == mrOk) {
    if (av->Type == 0) {
    }
    else {
      int rate, bits, chn;
      if (TryStrToInt(ComboBoxBits->Text, bits) &&
          TryStrToInt(ComboBoxChannels->Text, chn))
        SetAudioParams(pBuild, av->pCap, FormSampleRate->SampleRate, bits, chn);
    }

    ListViewSources->OnSelectItem(ListViewSources, ListViewSources->Selected, true);
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::ComboBoxInputChange(TObject *Sender) {
  if (!ChangeAudio)
    return;

  if (ListViewSources->Selected == NULL)
    return;

  TAVSource *av = (TAVSource*)ListViewSources->Selected->Data;
  if (av == NULL)
    return;

  Pins pins = GetPins(av->pCap, PINDIR_INPUT);

  double level, pan;
  bool enabled;

  for (int i = 0; i < pins.size(); i++) {
    GetPinParams(pins[i], level, pan, enabled);
    enabled = i == ComboBoxInput->ItemIndex;
    SetPinParams(pins[i], level, pan, enabled);
  }

  ReleasePins(pins);

  ListViewSources->OnSelectItem(ListViewSources, ListViewSources->Selected, true);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::TrackBarVolumeChange(TObject *Sender) {
  if (!ChangeAudio)
    return;

  if (ListViewSources->Selected == NULL)
    return;

  TAVSource *av = (TAVSource*)ListViewSources->Selected->Data;
  if (av == NULL)
    return;

  Pins pins = GetPins(av->pCap, PINDIR_INPUT);

  double level, pan;
  bool enabled;

  for (int i = 0; i < pins.size(); i++) {
    if (i == ComboBoxInput->ItemIndex) {
      GetPinParams(pins[i], level, pan, enabled);
      if (Sender == TrackBarVolume)
        level = TrackBarVolume->Position / 100.0;
      else if (Sender == TrackBarBalance)
        pan = TrackBarBalance->Position / 50.0;
      SetPinParams(pins[i], level, pan, enabled);
      break;
    }
  }

  ReleasePins(pins);

  ListViewSources->OnSelectItem(ListViewSources, ListViewSources->Selected, true);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::CheckBoxPreviewClick(TObject *Sender) {
  pMC->Stop();
  int FrameCounter = 0;
  for (int i = 0; i < ListViewSources->Items->Count; i++) {
    TAVSource *s = (TAVSource*)ListViewSources->Items->Item[i]->Data;
    s->PreviewFrames.clear();
    if (s->Type == 1) {
      bool Remove = true;
      if (CheckBoxPreview->Checked && s->pSampleGrabber == NULL) {
        AddFilterToGraph(CLSID_SampleGrabber, &s->pSampleGrabber, "SampleGrabber");
        AddFilterToGraph(CLSID_NullRenderer, &s->pNullRenderer, "NullRenderer");
        if (s->pSampleGrabber != NULL && s->pNullRenderer != NULL) {
          if (ConnectF2F(&MEDIATYPE_Audio, s->pInfTee, s->pSampleGrabber) && ConnectF2F(&MEDIATYPE_Audio, s->pSampleGrabber, s->pNullRenderer)) {
            CComQIPtr<ISampleGrabber, &IID_ISampleGrabber> pGrabber(s->pSampleGrabber);
            if (pGrabber) {
              if (pGrabber->SetBufferSamples(TRUE) ==  S_OK && pGrabber->SetOneShot(FALSE) ==  S_OK) {
                AM_MEDIA_TYPE Type;
                if (pGrabber->GetConnectedMediaType(&Type) == S_OK) {
                  if (Type.formattype == FORMAT_WaveFormatEx) {
                    WAVEFORMATEX *Format = (WAVEFORMATEX*)Type.pbFormat;
                    if (Format->wFormatTag == WAVE_FORMAT_PCM && Format->wBitsPerSample == 16) {
                      Remove = false;
                      for (int n = 0; n < Format->nChannels; n++) {
                        int Top = FormPreview->GetMaxControlHeight();
                        TFrameAudioPreview *FramePreview = new TFrameAudioPreview(FormPreview);
                        FramePreview->Name = "FramePreview" + IntToStr(FrameCounter++);
                        FramePreview->LabelNazev->Caption = ListViewSources->Items->Item[i]->Caption + " / Channel " + IntToStr(n + 1);
                        FramePreview->Top = Top;
                        FramePreview->Parent = FormPreview;
                        s->PreviewFrames.push_back(FramePreview);
                        if (s->AudioChannels.size() > n)
                          FramePreview->EditPopis->Text = s->AudioChannels[n];
                        else
                          FramePreview->EditPopis->Text = "";
                        FramePreview->EditPopis->OnChange = EditPopisChange;
                      }
                    }
                  }
                  FreeMediaType(Type);
                }
              }
            }
          }
        }
      }
      if (Remove) {
        SAFE_REMOVE(pGraph, s->pSampleGrabber);
        SAFE_REMOVE(pGraph, s->pNullRenderer);
      }
    } else if (s->Type == 0) {
      bool Remove = true;
      if (CheckBoxPreview->Checked && s->pVideoRenderer2 == NULL) {
      	TIBaseFilters OldFilters = GetFilters(pGraph);

	      if (s->pDVSplit != NULL) {
        	// DV
  	      AddFilterToGraph(CLSID_DVVideoCodec, &s->pDVDecoder2, "DV Decoder2");
        } else {
        	// HDV
          AddFilterToGraph(CLSID_MoonlightDemuxer, &s->pMPEG2TSDemux2, "MPEG2TS Demuxer2");
        }
        AddFilterToGraph(CLSID_VideoRenderer, &s->pVideoRenderer2, "Video Renderer2");

        if (s->pVideoRenderer2 != NULL && (s->pDVDecoder2 != NULL || s->pMPEG2TSDemux2 != NULL)) {
					if (s->pDVSplit == NULL)
          	if (ConnectF2F(NULL, s->pInfTee, s->pMPEG2TSDemux2))
	            RunStopGraph();

          if ((s->pDVSplit != NULL &&
	 	           ConnectF2F(&MEDIATYPE_Video, s->pInfTee, s->pDVDecoder2) &&
               ConnectF2F(&MEDIATYPE_Video, s->pDVDecoder2, s->pVideoRenderer2)) ||
               (s->pDVSplit == NULL &&
	 	           /*ConnectF2F(NULL, s->pInfTee, s->pMPEG2TSDemux2) &&*/
               ConnectF2F(&MEDIATYPE_Video, s->pMPEG2TSDemux2, s->pVideoRenderer2))
              ) {

            int Top = FormPreview->GetMaxControlHeight();
            TFrameVideoPreview *FramePreview = new TFrameVideoPreview(FormPreview);
            FramePreview->Name = "FramePreview" + IntToStr(FrameCounter++);
            FramePreview->LabelNazev->Caption = ListViewSources->Items->Item[i]->Caption;
            FramePreview->Top = Top;
            FramePreview->Parent = FormPreview;
            if (s->VideoChannels.size() > 0)
              FramePreview->EditPopis->Text = s->VideoChannels[0];
            else
              FramePreview->EditPopis->Text = "";
            FramePreview->EditPopis->OnChange = EditPopisChange;

            CComQIPtr<IVideoWindow> pVideoWindow(s->pVideoRenderer2);
            if (pVideoWindow) {
              HRESULT hr = pVideoWindow->put_Owner((long)FramePreview->PanelVideo->Handle);
              if (hr == S_OK) {
                hr = pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN);
                if (hr == S_OK) {
                  hr = pVideoWindow->SetWindowPosition(0, 0, FramePreview->PanelVideo->Width, FramePreview->PanelVideo->Height);
                  Remove = false;
                }
              }
            }

            if (!Remove)
              s->PreviewFrames.push_back(FramePreview);
            else
              delete FramePreview;
          }
        }
        s->VideoPreviewFilters2 = GetNewFilters(pGraph, OldFilters);
        ReleaseFilters(OldFilters);
      }
      if (Remove) {
      	RemoveFilters(pGraph, s->VideoPreviewFilters2);
      	SAFE_RELEASE(s->pDVDecoder2);
        SAFE_RELEASE(s->pMPEG2TSDemux2);
        SAFE_RELEASE(s->pVideoRenderer2);
      }
    }
  }

  StartPreview();
  FormPreview->Visible = CheckBoxPreview->Checked;
  if (FormPreview->Visible) {
    FormPreview->ClientHeight = FormPreview->GetMaxControlHeight();
    FormPreview->Left = Left + Width;
    FormPreview->Top = Top;
  } else {
    while (FormPreview->ControlCount > 0)
	    delete FormPreview->Controls[0];
  }
  TimerAudioPreview->Enabled = CheckBoxPreview->Checked;
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::TimerAudioPreviewTimer(TObject *Sender) {
  for (int i = 0; i < ListViewSources->Items->Count; i++) {
    TAVSource *s = (TAVSource*)ListViewSources->Items->Item[i]->Data;
    if (s->Type == 1) {
      int nChannels = s->PreviewFrames.size();
      if (nChannels > 0) {
        CComQIPtr<ISampleGrabber, &IID_ISampleGrabber> pGrabber(s->pSampleGrabber);
        if (pGrabber) {
          long BufferSize = 0;
          long *Buffer = NULL;
          pGrabber->GetCurrentBuffer(&BufferSize, Buffer);
          Buffer = (long*)malloc(BufferSize);
          if (Buffer) {
            pGrabber->GetCurrentBuffer(&BufferSize, Buffer);
            long Samples = BufferSize / nChannels / 2;
            for (int n = 0; n < nChannels; n++) {
              TFrameAudioPreview *Preview = (TFrameAudioPreview*)s->PreviewFrames[n];
              Graphics::TBitmap *Bitmap = Preview->ImageWave->Picture->Bitmap;
              Bitmap->PixelFormat = pf24bit;
              Bitmap->Width = Preview->ImageWave->Width;
              Bitmap->Height = Preview->ImageWave->Height;
              Bitmap->Canvas->Brush->Color = clWhite;
              Bitmap->Canvas->Brush->Style = bsSolid;
              Bitmap->Canvas->FillRect(Bitmap->Canvas->ClipRect);
              short *b = (short*)Buffer + n;
              for (int p = 0; p < Samples; p++) {
                float f = (float)b[0] / (float)MAXSHORT;
                b += nChannels;
                if (f < -1.0)
                  f = -1.0;
                else if (f > 1.0)
                  f = 1.0;
                int x = Bitmap->Width * ((float)p / (float)Samples);
                int y = (Bitmap->Height - 1) * (0.5 + f / 2.0);
                char *z = (((char*)Bitmap->ScanLine[y]) + x * 3);
                z[0] = 0;
                z[1] = 0;
                z[2] = 0;
              }
            }
            free(Buffer);
          }
        }
      }
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::EditFileNameChange(TObject *Sender) {
  if (ChangeFileName && ListViewSources->Selected != NULL) {
    TAVSource *s = ((TAVSource*)(ListViewSources->Selected->Data));
    s->File = EditFileName->Text;
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::EditPopisChange(TObject *Sender) {
  for (int i = 0; i < ListViewSources->Items->Count; i++) {
    TAVSource *s = (TAVSource*)ListViewSources->Items->Item[i]->Data;
    int nChannels = s->PreviewFrames.size();
    if (s->Type == 0) {
      s->VideoChannels.resize(nChannels);
      for (int n = 0; n < nChannels; n++)
        s->VideoChannels[n] = ((TFrameVideoPreview*)s->PreviewFrames[n])->EditPopis->Text;
    } else if (s->Type == 1) {
      s->AudioChannels.resize(nChannels);
      for (int n = 0; n < nChannels; n++)
        s->AudioChannels[n] = ((TFrameAudioPreview*)s->PreviewFrames[n])->EditPopis->Text;
    }
  }
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::NewWndProc(Messages::TMessage &Message) {
	if (Message.Msg == WM_MOVE) {
  	if (ChangePos) {
    	FormPreview->ChangePos = false;
	    FormPreview->Top = Top;
  	  FormPreview->Left = Left + Width;
      FormPreview->ChangePos = true;
    }
  }
	WndProc(Message);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::TimerRecordTimer(TObject *Sender) {
  LONGLONG Duration;
  AnsiString Text;
  if (pMS != NULL && pMS->GetCurrentPosition(&Duration) == S_OK) {
    int t = Round(Duration / 10000000.0);
    Text.printf("%.2d:%.2d:%.2d", (t / 60) / 60, (t / 60) % 60, t % 60);
  } else
    Text = "?";
  FormRecording->LabelTime->Caption = Text;

  __int64 Free;
  AnsiString Drive = ExtractFileDrive(EditDirectoryName->Text);
  if (Drive == "")
    Free = DiskFree(0);
  else
    Free = DiskFree(UpperCase(Drive)[1] - 'A' + 1);

  if (StartDiskFree < 0) {
    StartDiskFree = Free;
    StartTime = clock();
    Text = "?";
  } else {
  	clock_t Length = clock() - (__int64)StartTime;
    __int64 Bytes = StartDiskFree - Free;
    if (Length > 0 && Bytes >0) {
	    __int64 t = Free / ((__int64)CLK_TCK * (Bytes) / ((__int64)Length));
  	  Text.printf("%.2d:%.2d:%.2d", int((t / 60) / 60), int((t / 60) % 60), int(t % 60));
    } else
    	Text = "?";
  }
  FormRecording->LabelRemainingTime->Caption = Text;

  Free /= 1024 * 1024;
  FormRecording->LabelDiskFree->Caption = IntToStr(Free) + "MB";
  if (Free < MinDiskFree)
    FormRecording->ModalResult = mrAbort;
}
//---------------------------------------------------------------------------

AnsiString TFormMain::GetIndexName(AnsiString Name) {
  if (FileExists(Name)) {
    AnsiString Ext = ExtractFileExt(Name);
    AnsiString File = Name.SubString(1, Name.Length() - Ext.Length());
    int i = 0;
    do {
      Name = File + "." + IntToStr(i++) + Ext;
    } while (FileExists(Name));
    return Name;
  } else
    return Name;
}
//---------------------------------------------------------------------------

AnsiString TFormMain::ExchangeExt(AnsiString FileName, AnsiString Ext) {
  return FileName.SubString(1, FileName.Length() - ExtractFileExt(FileName).Length()) + Ext;
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::Button1Click(TObject *Sender)
{
	IBaseFilter *pFileWriter;
	AddFilterToGraph(CLSID_CineFormDumper, &pFileWriter, "MPEG2TS File Writer");
  if (pFileWriter) {
  	TimerHack->Enabled = true;
  	ShowFilterProperties(Handle, pFileWriter);
		TimerHack->Enabled = false;

    ShowMessage("Kontrola");
    ShowFilterProperties(Handle, pFileWriter);
  	SAFE_REMOVE(pGraph, pFileWriter);
  }
}
//---------------------------------------------------------------------------

BOOL CALLBACK EnumChildProcCheckBox(HWND hwnd, LPARAM lParam) {
	char *Name = "Detect and split files on scene breaks.";
	char Caption[1000];
  if (GetWindowText(hwnd, Caption, sizeof(Caption)) > 0 && strcmp(Caption, Name) == 0) {
    PostMessage(hwnd, WM_KEYDOWN, 0x20, 0x00390001);
    PostMessage(hwnd, WM_CHAR, 0x20, 0x00390001);
    PostMessage(hwnd, 15, 0, 0);
    PostMessage(hwnd, WM_KEYUP, 0x20, 0xC0390001);
    Beep();
    FormMain->TimerHack->Enabled = false;
    return FALSE;
  }
 	return TRUE;
}
//---------------------------------------------------------------------------

BOOL CALLBACK EnumChildProcDialog(HWND hwnd, LPARAM lParam) {
	char *Name = "MPEG2TS File Writer";
	char Caption[1000];
  if (GetWindowText(hwnd, Caption, sizeof(Caption)) > 0 && strncmp(Caption, Name, strlen(Name)) == 0) {
    EnumChildWindows(hwnd, (WNDENUMPROC)EnumChildProcCheckBox, 0);
    PostMessage(hwnd, WM_KEYDOWN, 0x0D, 0x001C0001);
    PostMessage(hwnd, 15, 0, 0);
    PostMessage(hwnd, WM_KEYUP, 0x0D, 0xC01C0001);
    return FALSE;
  }
  return TRUE;
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::TimerHackTimer(TObject *Sender) {
	EnumWindows((WNDENUMPROC)EnumChildProcDialog, 0);
}
//---------------------------------------------------------------------------

void __fastcall TFormMain::RadioButtonVFAVIClick(TObject *Sender) {
  if (!ChangeVideo)
    return;

  if (ListViewSources->Selected == NULL)
    return;

  TAVSource *av = (TAVSource*)ListViewSources->Selected->Data;
  if (av == NULL)
    return;

  if (RadioButtonVFMPEG2TS->Checked)
  	av->VideoFormat = 1;
  else if (RadioButtonVFMPEG2PS->Checked)
  	av->VideoFormat = 2;
  else
  	av->VideoFormat = 0;
}
//---------------------------------------------------------------------------


