//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#include <stdio.h>
#include <ctype.h>
#include <StrUtils.hpp>
#include <IniFiles.hpp>
#pragma hdrstop
#include "UnitMainDemo.h"
#include "avfile.h"
#include "WindowsMM.h"
#include "avfile_utils.h"
#include "PrologSources.h"
#include "UnitInputDevices.h"
#include "DetectorESF.h"
#include "Logging.h"
#include "CameraDllHandler.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormMainDemo *FormMainDemo;

//---------------------------------------------------------------------------
const AnsiString SectionSources = "Sources";
const AnsiString SectionForm = "Form - ";
const AnsiString SectionMain = "Main";
const AnsiString SectionImages = "Images";
const AnsiString KeyLeft = "Left";
const AnsiString KeyTop = "Top";
const AnsiString KeyWidth = "Width";
const AnsiString KeyHeight = "Height";
const AnsiString KeyQueue1 = "Queue1";
const AnsiString KeyQueue2 = "Queue2";
const AnsiString KeyMode = "Mode";
const AnsiString KeyQuality = "Quality";
const AnsiString KeyInputSize = "Input size";
const AnsiString KeyOutputSize = "Output size";
const AnsiString KeyControl = "Control";
const AnsiString KeyOutputAspectRatio = "Output aspect ratio";
const AnsiString KeyStep = "Step";
const AnsiString KeySlideCount = "Slide count";
const AnsiString KeyImageWidth = "Width";
const AnsiString KeyImageInterval = "Interval";
const AnsiString KeyImage = "Image";

//---------------------------------------------------------------------------
static int GlobalMode = 0;

//---------------------------------------------------------------------------
void GlobalModeWorking()
{
	Screen->Cursor = crHourGlass;
	GlobalMode++;
}

//---------------------------------------------------------------------------
void GlobalModeIdle()
{
	if (GlobalMode > 0)
	{
		GlobalMode--;
	}
	if (GlobalMode == 0)
	{
		Screen->Cursor = crDefault;
	}
}

//---------------------------------------------------------------------------
AnsiString ParamStrFromName(AnsiString Name)
{
	for (int i = 1; i < ParamCount(); i++)
	{
		if (AnsiSameText(Name, ParamStr(i)))
		{
			return ParamStr(i + 1);
		}
	}
	return "";
}

//---------------------------------------------------------------------------
__fastcall TFormMainDemo::TFormMainDemo(TComponent* Owner): TForm(Owner)
{
	TImg::MemoryManager = new TWindowsMM();
	TDetectorESF::SetupSlides(&Slides);

	InitLog();
	RTEditor = NULL;
	AudioPlayer.SetWindow(Handle);
	WindowProc = NewWndProc;
	FAudio = NULL;
	FormVideo = NULL;
	Initiallized = false;

	INIFileName = ChangeFileExt(Application->ExeName, ".ini");
	AnsiString CustomINIFileName = ParamStrFromName("-config");

	if (CustomINIFileName != "")
	{
		CustomINIFileName = ExpandFileName(CustomINIFileName);
		if (FileExists(CustomINIFileName))
		{
			INIFileName = CustomINIFileName;
		}
		else
		{
			ShowMessage("Config file " + CustomINIFileName + " not found!\nUsing standard config file " + INIFileName + ".");
		}
	}

	FDefaulCaption = Caption;
	LoadSources();
	LoadMain();
	FromParam = false;
	Init();
}

//---------------------------------------------------------------------------
__fastcall TFormMainDemo::~TFormMainDemo()
{
	if (FormVideo)
	{
		SaveForm(FormVideo);
		delete FormVideo;
	}
	FreeFormControls();
	FreeFormVideoInput();
	AudioPlayer.Stop();
	if (FAudio)
	{
		delete FAudio;
	}
	if (RTEditor)
	{
		delete RTEditor;
	}

	Slides.clear();
	if (TImg::MemoryManager)
	{
		delete TImg::MemoryManager;
		TImg::MemoryManager = NULL;
	}
	SaveMain();
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::FormCreate(TObject *Sender)
{
	LoadForm(this);
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::FormDestroy(TObject *Sender)
{
	SaveForm(this);
}

//---------------------------------------------------------------------------
// Zakladni operace
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::ButtonOpenClick(TObject *Sender)
{
	if (OpenDialog1->Execute())
	{
		OpenFile(OpenDialog1->FileName.c_str());
		if (RTEditor != NULL)
		{
			chbOnline->Enabled = true;
		}
	}
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::ButtonOpenHubClick(TObject *Sender)
{
	if (OpenDialog1->Execute())
	{
		OpenFile((AnsiString("*HUB*") + OpenDialog1->FileName).c_str());
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::OpenFile(const char *FileName)
{
	GlobalModeWorking();
	try
	{
		Caption = FDefaulCaption;
		FreeFormControls();
		FreeFormVideoInput();
		Initiallized = false;
		if (RTEditor)
		{
			delete RTEditor;
			RTEditor = NULL;
		}
		UpdateOutputWindow();
		ListBox1->Items->Clear();
		RTEditor = new TRTEditor();
		RTEditor->SetTexts(ListBox1->Items);
		RTEditor->SetPrologSources(ListBox2->Items);
		RTEditor->Load(FileName, NULL);
		Caption = FDefaulCaption + " - " + FileName;
	}
	__finally
	{
		GlobalModeIdle();
	}
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::ButtonInitClick(TObject *Sender)
{
	if (!RTEditor)
	{
		return;
	}

	GlobalModeWorking();
	try
	{
		RTEditor->Init(RadioGroupMode->ItemIndex, StrToInt(EditStep->Text), StrToInt(EditDelay->Text), StrToInt(Edit1->Text), true, true, RadioGroupInput->ItemIndex, RadioGroupOutput->ItemIndex);
		RadioGroupQuality->OnClick(RadioGroupQuality);

		Init();
		Initiallized = true;
		CreateFormControls();
		UpdateOutputWindow();
		UpdateInputWindow();
	}
	__finally
	{
		GlobalModeIdle();
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::Init()
{
	ListBox1->Items->Clear();

	Slides.clear();
	SkipProlog = 0;
	FPS = 0;
	TotalFrameCount = 0;
	TotalSkippedFrames = 0;
	UpdateStatus();

	if (RTEditor)
	{
		TrackBar1->Max = RTEditor->Sources.GetLength();
	}
	else
	{
		TrackBar1->Max = 0;
	}
	TrackBar1->Position = 0;
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::ButtonStartClick(TObject *Sender)
{
	if (!RTEditor || Repeat)
	{
		return;
	}

	if (!Initiallized)
	{
		ButtonInit->Click();
	}

	RTEditor->ClearQueues();
	FrameCount = 0;
	LastFrameTime = clock();
	SkipFrames = 0;
	SkipProlog = 0;
	Repeat = true;

	// start all cameras, if exist
	CameraDll->StartAll();
	Sleep(1000);

	if (CheckBoxAudio->Checked)
	{
		Prepering = true;
//		RTEditor->GetAudio();
		AudioPlayer.Stop();
		TAVFile::TAudioInfo ai = RTEditor->GetAudioInfo();
		int i = AudioPlayer.Init(ai.SamplesPerSec, ai.Channels, 16, this);
		if (i >= 0)
		{
			AudioPlayer.Prepare();
		}
		SkipFrames = 0;
		Prepering = false;
		AudioPlayer.Start();
	}
	else if (CheckBoxSync->Checked)
	{
		SkipFrames = 0;
		Prepering = false;
		TimerSync->Interval = RTEditor->GetStep();
		TimerSync->Enabled = true;
	}
	else
	{
		do
		{
			RTEditor->Do(false, false, false);
			RTEditor->SkipAudio();
			TImg *Frame = RTEditor->GetVideo();
			if (Frame)
			{
				if (CheckBoxShow->Checked)
				{
					DisplayOutput(Frame);
				}
				delete Frame;
				DisplayInput();
			}

			clock_t Diff = clock() - LastFrameTime;
			if (Diff >= CLK_TCK)
			{
				FPS = float(FrameCount) / (float(Diff) / float(CLK_TCK));
				FrameCount = 0;
				LastFrameTime = clock();
			}
			UpdateStatus();
			FrameCount++;
			TotalFrameCount++;
			TrackBar1->Position = RTEditor->GetTime() - RTEditor->GetVideoQueueLength() * RTEditor->GetStep();
			Application->ProcessMessages();
		}
		while (Repeat && !RTEditor->Sources.Eof());
	}
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::TimerSyncTimer(TObject *Sender)
{
#if 1
	unsigned int Len;
	GetData(Len);
	if (RTEditor->Sources.Eof())
	{
		ButtonStop->Click();
	}
#else
	TimerSync->Enabled = false;
	clock_t Begin = clock();
	unsigned int Len;
	GetData(Len);
	clock_t End = clock();
	int Interval = RTEditor->GetStep();
	Interval = Interval - 1000 * (End - Begin) / CLK_TCK;
	if (Interval < 1)
	{
		Interval = 1;
	}
	TimerSync->Interval = Interval;
	TimerSync->Enabled = true;
	if (RTEditor->Sources.Eof())
	{
		ButtonStop->Click();
	}
#endif
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::ButtonStopClick(TObject *Sender)
{
	CameraDll->StopAll();
	Repeat = false;
	AudioPlayer.Stop();
	TimerSync->Enabled = false;
	if (FromParam)
	{
		Close();
	}
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::ButtonResetClick(TObject *Sender)
{
	if (!RTEditor)
	{
		return;
	}

	ButtonStop->Click();
	RTEditor->Reset(StrToInt(EditDelay->Text), StrToInt(Edit1->Text));
	Init();
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::RadioGroupQualityClick(TObject *Sender)
{
	if (!RTEditor)
	{
		return;
	}
	RTEditor->SetupQuality(RadioGroupQuality->ItemIndex - 1);
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::Button3Click(TObject *Sender)
{
	CreateFormControls();
}

//---------------------------------------------------------------------------
// Obsluha TAudioSource
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::NewWndProc(Messages::TMessage &Message)
{
	if (!AudioPlayer.WndProc(Message))
	{
		WndProc(Message);
	}
}

//---------------------------------------------------------------------------
unsigned int TFormMainDemo::GetPos()
{
	return 0;
}

//---------------------------------------------------------------------------
unsigned int TFormMainDemo::GetLen()
{
	return 1;
}

//---------------------------------------------------------------------------
BYTE* TFormMainDemo::GetData(unsigned int &Len)
{
	if (FAudio)
	{
		delete FAudio;
		FAudio = NULL;
	}

	if (Prepering)
	{
		RTEditor->Do(false, false);
	}
	else
	{
		clock_t Begin = clock();

		SkipProlog = 0;
		bool b = (SkipProlog > 0) ? (TotalFrameCount % (SkipProlog + 1)) != 0 : false;

		if (SkipFrames > 0)
		{
			RTEditor->Do(true, false, true);
			SkipFrames--;
			FrameCount++;
			TotalSkippedFrames++;
		}
		else
		{
			RTEditor->Do(false, false, b);
			if (SkipProlog > 0)
			{
				SkipProlog--;
			}
		}

		TImg *Frame = RTEditor->GetVideo();
		if (Frame)
		{
			if (CheckBoxShow->Checked)
			{
				DisplayOutput(Frame);
			}
			delete Frame;
			DisplayInput();
		}
		clock_t End = clock();

		TrackBar1->Max = RTEditor->Sources.GetLength();
		TrackBar1->Position = RTEditor->GetTime() - RTEditor->GetVideoQueueLength() * RTEditor->GetStep();

		TAVFile::TFrameRate FrameRate = RTEditor->GetFrameInfo().FrameRate;
		double FrameTime = 1000.0 / (double(FrameRate.Rate) / double(FrameRate.Scale));
		double Time = double(1000) * double(End - Begin) / double(CLK_TCK);

		unsigned int Drop = (Time + 0.025 * FrameTime) / FrameTime;
		if (Drop > 0)
		{
			SkipProlog++;
		}
		SkipFrames += Drop;

		clock_t Diff = clock() - LastFrameTime;
		if (Diff >= CLK_TCK)
		{
			FPS = 1000.0 / (float)RTEditor->GetStep() - float(FrameCount) / (float(Diff) / float(CLK_TCK));
			FrameCount = 0;
			LastFrameTime = clock();
		}
		UpdateStatus();
		TotalFrameCount++;
	}

	FAudio = RTEditor->GetAudio();
	if (FAudio)
	{
		Len = FAudio->Size;
		return FAudio->Wave;
	}
	else
	{
		Len = 0;
		return NULL;
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::UpdateStatus()
{
	if (RTEditor)
	{
		LabelTime->Caption = IntToStr(RTEditor->GetTime()) + " (" + IntToStr(TotalFrameCount) + ")";
		TRTEditor::TStatistics Statistics = RTEditor->GetStatistics();
		AnsiString s;
		s.printf("%d %d %d %d %d", Statistics.Sources, Statistics.Import, Statistics.Prolog, Statistics.Editing, Statistics.Total);
		LabelStatistics->Caption = s;
		Log("Demo", "%d %d %d %d %d", Statistics.Sources, Statistics.Import, Statistics.Prolog, Statistics.Editing, Statistics.Total);

		if (AudioPlayer.GetCount() > 0)
		{
			LabelAudioBufOut->Caption = IntToStr(AudioPlayer.GetAudioBufOut(0));
			LabelAudioBufOut->Refresh();
		}
		else
		{
			LabelAudioBufOut->Caption = "";
		}
	}
	else
	{
		LabelTime->Caption = IntToStr(0);
		LabelStatistics->Caption = "";
		LabelAudioBufOut->Caption = "";
	}
	LabelSkipped->Caption = IntToStr(TotalSkippedFrames);
	LabelFPS->Caption = FloatToStrF(FPS, ffFixed, 18, 2);
	LabelSkipProlog->Caption = IntToStr(SkipProlog);
}

//---------------------------------------------------------------------------
// Zobrazeni vstupu a vystupu
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
void TFormMainDemo::DisplayOutput(TImg *Frame)
{
	if (FormVideo)
	{
		FormVideo->Display(Frame);
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::UpdateOutputWindow()
{
	if (CheckBoxShow->Checked && Initiallized)
	{
		if (!FormVideo)
		{
			FormVideo = new TFormVideoDemo(this);
			LoadForm(FormVideo);
			FormVideo->SetupSlides(&Slides);

			TIniFile *INI = new TIniFile(INIFileName);
			try
			{
				AnsiString Section = SectionImages;
				FormVideo->SetOutputAspectRatio(INI->ReadFloat(Section, KeyOutputAspectRatio, 0));
				FormVideo->SetSlideCount(INI->ReadInteger(Section, KeySlideCount, 3));
				FormVideo->PanelRight->Width = INI->ReadInteger(Section, KeyImageWidth, 256);
				FormVideo->TimerImages->Interval = INI->ReadInteger(Section, KeyImageInterval, 1000);

				for (int i = 1; INI->ValueExists(Section, KeyImage + IntToStr(i)); i++)
				{
					FormVideo->Images.push_back(INI->ReadString(Section, KeyImage + IntToStr(i), ""));
				}
			}
			__finally
			{
				delete INI;
			}
		}
		if (FromParam)
		{
			FormVideo->SetFullScreen(true);
		}
		FormVideo->Show();
	}
	else
	{
		if (FormVideo)
		{
			SaveForm(FormVideo);
			delete FormVideo;
			FormVideo = NULL;
		}
	}
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::CheckBoxShowClick(TObject *Sender)
{
	UpdateOutputWindow();
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::FormShow(TObject *Sender)
{
	UpdateOutputWindow();
	UpdateInputWindow();

	AnsiString Input = ParamStrFromName("-input");
	if (Input != "")
	{
		OpenFile(Input.c_str());
		FromParam = true;
		ButtonStart->Click();
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::FreeFormVideoInput()
{
	for (unsigned i = 0; i < FormVideoInput.size(); i++)
	{
		SaveForm(FormVideoInput[i]);
		delete FormVideoInput[i];
	}
	FormVideoInput.clear();
}

//---------------------------------------------------------------------------
void TFormMainDemo::UpdateInputWindow()
{
	if (CheckBoxInput->Checked && Initiallized)
	{
		FreeFormVideoInput();
		for (unsigned int i = 0; i < RTEditor->Sources.size(); i++)
		{
			int Camera = RTEditor->Sources.Sources[i]->Camera;
			if (Camera >= 0)
			{
				TFormVideoDemo *FormVideo = new TFormVideoDemo(this, "Input " + IntToStr(Camera));
				LoadForm(FormVideo);
				FormVideo->Show();
				FormVideoInput.push_back(FormVideo);
			}
		}
	}
	else
	{
		FreeFormVideoInput();
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::DisplayInput()
{
	if (!CheckBoxInput->Checked)
	{
		return;
	}

	for (unsigned int i = 0; i < RTEditor->Sources.size() && i < FormVideoInput.size(); i++)
	{
		int Camera = RTEditor->Sources.Sources[i]->Camera;
		if (Camera >= 0)
		{
			TImg *Frame = RTEditor->Sources.GetFrame(Camera);
			if (Frame)
			{
				FormVideoInput[i]->Display(Frame);
			}
		}
	}
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::CheckBoxInputClick(TObject *Sender)
{
	UpdateInputWindow();
}

//---------------------------------------------------------------------------
// Ovladaci prvky
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
void TFormMainDemo::FreeFormControls()
{
	for (unsigned i = 0; i < FormControls.size(); i++)
	{
		SaveForm(FormControls[i]);
		delete FormControls[i];
	}
	FormControls.clear();
}

//---------------------------------------------------------------------------
void TFormMainDemo::AddFormControls(AnsiString Caption, TRTEditor::TControlType Type)
{
	if (!RTEditor)
	{
		return;
	}

	TRTEditor::TFloatControls Controls = RTEditor->GetControls(Type);
	if (Controls.empty())
	{
		return;
	}

	TFormFloatControls *Form = new TFormFloatControls(this, Caption, Type, Controls);
	Form->OnControlChange = OnControlChange;
	LoadForm(Form);
	Form->Show();
	FormControls.push_back(Form);
}

//---------------------------------------------------------------------------
void TFormMainDemo::CreateFormControls()
{
	FreeFormControls();
	AddFormControls("c_const", TRTEditor::ctCConst);
	AddFormControls("p_const", TRTEditor::ctPConst);
	AddFormControls("s_person_mult", TRTEditor::ctPMult);
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::OnControlChange(System::TObject* Sender, TRTEditor::TControlType Type, TRTEditor::TFloatControl Control)
{
	RTEditor->SetControl(Type, Control);
}

//---------------------------------------------------------------------------
// Nastaveni konfigurace pro Prolog
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::Button1Click(TObject *Sender)
{
	if (ListBox2->Items->Count > 0)
	{
		AnsiString Path = ExtractFilePath(ListBox2->Items->Strings[ListBox2->ItemIndex < 0 ? 0 : ListBox2->ItemIndex]);
		if (Path != "")
		{
			OpenDialog2->InitialDir = Path;
		}
	}

	if (OpenDialog2->Execute())
	{
		ListBox2->Items->Add(OpenDialog2->FileName);
		SaveSources();
	}
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::Button5Click(TObject *Sender)
{
	int Index = 0;
	ListBox2->Items->Add(TPrologSources::GetBuiltInPrefix() + IntToStr(Index));
	SaveSources();
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::Button2Click(TObject *Sender)
{
	if (ListBox2->ItemIndex >= 0)
	{
		ListBox2->Items->Delete(ListBox2->ItemIndex);
		SaveSources();
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::LoadSources()
{
	TIniFile *INI = new TIniFile(INIFileName);
	try
	{
		ListBox2->Items->Clear();
		for (int i = 0; INI->ValueExists(SectionSources, IntToStr(i)); i++)
		{
			ListBox2->Items->Add(INI->ReadString(SectionSources, IntToStr(i), ""));
		}
	}
	__finally
	{
		delete INI;
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::SaveSources()
{
	TIniFile *INI = new TIniFile(INIFileName);
	try
	{
		INI->EraseSection(SectionSources);
		for (int i = 0; i < ListBox2->Items->Count; i++)
		{
			INI->WriteString(SectionSources, IntToStr(i), ListBox2->Items->Strings[i]);
		}
	}
	__finally
	{
		delete INI;
	}
}

//---------------------------------------------------------------------------
// Ukladani pozice oken
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
AnsiString GetFormSection(TForm *Form)
{
	AnsiString Section;
	int p = AnsiPos(" - ", Form->Caption);
	if (p > 0)
	{
		Section = Form->Caption.SubString(1, p - 1);
	}
	else
	{
		Section = Form->Caption;
	}
	return Section;
}

//---------------------------------------------------------------------------
void TFormMainDemo::LoadForm(TForm *Form)
{
	const MinBorder = 50;

	TIniFile *INI = new TIniFile(INIFileName);
	try
	{
		AnsiString Section = SectionForm + GetFormSection(Form);
		if (INI->SectionExists(Section))
		{
			Form->Left = INI->ReadInteger(Section, KeyLeft, Form->Left);
			Form->Top = INI->ReadInteger(Section, KeyTop, Form->Top);
			if (Form->BorderStyle != bsDialog)
			{
				Form->Width = INI->ReadInteger(Section, KeyWidth, Form->Width);
				Form->Height = INI->ReadInteger(Section, KeyHeight, Form->Height);
			}

			if (Form->Left + Form->Width < MinBorder)
			{
				Form->Left = MinBorder - Form->Width;
			}
			if (Form->Top + Form->Height < MinBorder)
			{
				Form->Top = MinBorder - Form->Height;
			}
			if (Screen->Width - Form->Left < MinBorder)
			{
				Form->Left = Screen->Width - MinBorder;
			}
			if (Screen->Height - Form->Top < MinBorder)
			{
				Form->Top = Screen->Height - MinBorder;
			}
		}
	}
	__finally
	{
		delete INI;
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::SaveForm(TForm *Form)
{
	TIniFile *INI = new TIniFile(INIFileName);
	try
	{
		AnsiString Section = SectionForm + GetFormSection(Form);
		INI->WriteInteger(Section, KeyLeft, Form->Left);
		INI->WriteInteger(Section, KeyTop, Form->Top);
		INI->WriteInteger(Section, KeyWidth, Form->Width);
		INI->WriteInteger(Section, KeyHeight, Form->Height);
	}
	__finally
	{
		delete INI;
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::LoadMain()
{
	TIniFile *INI = new TIniFile(INIFileName);
	try
	{
		AnsiString Section = SectionMain;
		EditDelay->Text = INI->ReadString(Section, KeyQueue1, "0");
		Edit1->Text = INI->ReadString(Section, KeyQueue2, "0");
		RadioGroupMode->ItemIndex = INI->ReadInteger(Section, KeyMode, 0);
		RadioGroupQuality->ItemIndex = INI->ReadInteger(Section, KeyQuality, 1);
		RadioGroupInput->ItemIndex = INI->ReadInteger(Section, KeyInputSize, 0);
		RadioGroupOutput->ItemIndex = INI->ReadInteger(Section, KeyOutputSize, 0);
		switch (INI->ReadInteger(Section, KeyControl, 0))
		{
		case 1:
			CheckBoxSync->Checked = true;
			break;
		case 2:
			CheckBoxAudio->Checked = true;
			break;
		default:
			RadioButton1->Checked = true;
			break;
		}

		TAVFileDeviceList List = AVFileGetDeviceList();
		for (unsigned int i = 0; i < List.size(); i++)
		{
			if (INI->ValueExists("InputDevices", IntToStr(List[i].Device)))
			{
				AVFileSetDevicePriority(List[i].Device, INI->ReadInteger("InputDevices", IntToStr(List[i].Device), -1));
			}
		}
		EditStep->Text = INI->ReadString(Section, KeyStep, "40");
	}
	__finally
	{
		delete INI;
	}
}

//---------------------------------------------------------------------------
void TFormMainDemo::SaveMain()
{
	TIniFile *INI = new TIniFile(INIFileName);
	try
	{
		AnsiString Section = SectionMain;
		INI->WriteString(Section, KeyQueue1, EditDelay->Text);
		INI->WriteString(Section, KeyQueue2, Edit1->Text);
		INI->WriteInteger(Section, KeyMode, RadioGroupMode->ItemIndex);
		INI->WriteInteger(Section, KeyQuality, RadioGroupQuality->ItemIndex);
		INI->WriteInteger(Section, KeyInputSize, RadioGroupInput->ItemIndex);
		INI->WriteInteger(Section, KeyOutputSize, RadioGroupOutput->ItemIndex);
		int Control;
		if (CheckBoxSync->Checked)
		{
			Control = 1;
		}
		else if (CheckBoxAudio->Checked)
		{
			Control = 2;
		}
		else
		{
			Control = 0;
		}
		INI->WriteInteger(Section, KeyControl, Control);
		INI->WriteString(Section, KeyStep, EditStep->Text);
	}
	__finally
	{
		delete INI;
	}
}

//---------------------------------------------------------------------------
// Bordel
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::Button4Click(TObject *Sender)
{
	if (SaveDialog1->Execute())
	{
		ListBox1->Items->SaveToFile(SaveDialog1->FileName);
	}
}

//---------------------------------------------------------------------------
void __fastcall TFormMainDemo::Button6Click(TObject *Sender)
{
	TFormInputDevices *Form = new TFormInputDevices(this);
	try
	{
		if (Form->ShowModal() == mrOk)
		{
			TIniFile *f = new TIniFile(INIFileName);
			try
			{
				TAVFileDeviceList List = AVFileGetDeviceList();
				for (unsigned int i = 0; i < List.size(); i++)
				{
					f->WriteInteger("InputDevices", IntToStr(List[i].Device), AVFileGetDevicePriority(List[i].Device));
				}
			}
			__finally
			{
				delete f;
			}
		}
	}
	__finally
	{
		delete Form;
	}
}

void __fastcall TFormMainDemo::chbOnlineClick(TObject *Sender)
{
	if (RTEditor != NULL)
	{
		RTEditor->SetUseOnlineCameras(((TCheckBox*)Sender)->Checked);
	}
}
//---------------------------------------------------------------------------

