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

#include <vcl.h>
#include "AppGlobalF.h"
#include "ITSSkinF.h"
#include "ITSUtilF.h"
#include "ITSLangTransF.h"
#include "ITS_OPLibF.h"
#pragma hdrstop

#include "WCAM020MF.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "cxButtons"
#pragma link "cxCalc"
#pragma link "cxCheckBox"
#pragma link "cxClasses"
#pragma link "cxContainer"
#pragma link "cxControls"
#pragma link "cxCustomData"
#pragma link "cxData"
#pragma link "cxDataStorage"
#pragma link "cxEdit"
#pragma link "cxFilter"
#pragma link "cxGraphics"
#pragma link "cxGrid"
#pragma link "cxGridBandedTableView"
#pragma link "cxGridCustomTableView"
#pragma link "cxGridCustomView"
#pragma link "cxGridLevel"
#pragma link "cxGridTableView"
#pragma link "cxGroupBox"
#pragma link "cxLabel"
#pragma link "cxLookAndFeelPainters"
#pragma link "cxLookAndFeels"
#pragma link "cxMaskEdit"
#pragma link "cxPC"
#pragma link "cxPCdxBarPopupMenu"
#pragma link "cxSpinEdit"
#pragma link "cxStyles"
#pragma link "cxTextEdit"
#pragma link "dxSkinBlue"
#pragma link "dxSkinsCore"
#pragma link "dxSkinscxPCPainter"
#pragma link "FFBaseComponent"
#pragma link "FFBasePlay"
#pragma link "FFPlay"
#pragma link "FRAME_WCamStateListF"
#pragma link "IdBaseComponent"
#pragma link "IdComponent"
#pragma link "IdIcmpClient"
#pragma link "IdRawBase"
#pragma link "IdRawClient"
#pragma link "ImageBtn"
#pragma link "XNVTViewerCtrlLib_OCX"
#pragma link "dxSkinBlack"
#pragma link "dxSkinMcSkin"
#pragma resource "*.dfm"
TWCAM020M *WCAM020M = NULL;

//{*      Information Bar    *}
#define CAP_CAMERA_NAME				0x01
#define CAP_TIME					0x02
#define CAP_CHANNEL					0x04
#define CAP_SIZE					0x08
#define CAP_EVENT					0x10
#define CAP_FPSCHANGED				0x20

//{*  Pan/tilt/Zoom and Transparent controls *}
#define CTL_FOCUS_CONT				0x2001
#define CTL_PTZ_CONT				0x2002
#define CTL_TRANSPARENT				0x7000
#define CTL_TRANSPARENT_RS232		0x7001

//{*      OCXState for NVSMPEG4OCX    *}
#define GRAPH_NONE					0x00000000
#define GRAPH_PREVIEW				0x00000001
#define GRAPH_CAPTURE				0x00000002
#define GRAPH_PREVIEWCAPTURE		0x00000003
#define GRAPH_AUDIO_LISTEN			0x00000100
#define GRAPH_AUDIO_CAPTURE			0x00000200
#define GRAPH_AUDIO_LISTENCAPTURE	0x00000400
#define GRAPH_STATE_RUNNING			0x80000000


#define SB_PAN_LEFT					0x000000C4
#define SB_PAN_RIGHT				0x0000003C
#define SB_TILT_UP					0x00003C00
#define SB_TILT_DOWN				0x0000C400
#define SB_ZOOM_IN					0x003C0000
#define SB_ZOOM_OUT					0x00C40000
#define SB_FOCUS_IN					0x3C
#define SB_FOCUS_OUT				0xC4

enum { E_MJPG=0, E_MP4S, E_DX50, E_MPEG2, E_MPEG1, E_H264 };
enum { BR_32K=0, BR_64K, BR_128K, BR_256K, BR_384K, BR_500K, BR_750K, BR_1M, BR_1_5M, BR_2M, BR_4M, BR_5M, BR_6M, BR_7M, BR_8M };
enum { S_1080P=0, S_720P, S_D1, S_4CIF, S_VGA, S_HD1, S_H4CIF, S_HVGA, S_CIF, S_QVGA, S_QCIF, S_QQVGA };

#define PRESET_SET                  0x1020 // Unsigned 1 byte
#define PRESET_MOVE                 0x1021 // Unsigned 1 byte
#define PRESET_CLEAR                0x1022 // Unsigned 1 byte

#define LICENSE_KEY "FSXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX"

//---------------------------------------------------------------------------
__fastcall TWCAM020M::TWCAM020M(TComponent* Owner)
    : TForm(Owner)
{
    //::CoInitialize(NULL);
    LangTrans->Translate(this, ITSDb_GetConnection());
    ITSSkin_Load(this);
    LoadLocalSkin();

    CMM_LoadForm(g_sFormsDir, this);

    FSelCtlr = NULL;

    FRAMEWCamStateList1->PnlTop->Visible    = false;
    FRAMEWCamStateList1->PnlBottom->Visible = false;
    FRAMEWCamStateList1->TvList->OptionsView->Footer = false;
    FRAMEWCamStateList1->Col04->Visible = false;
    FRAMEWCamStateList1->Col05->Visible = false;
    FRAMEWCamStateList1->Col06->Visible = true;
    FRAMEWCamStateList1->ColumnSel->Visible = false;

    PgControl->ActivePageIndex = 0;

    FSelIds = new TStringList();

    FTitle = Caption;

    //TabPreset->Visible = false;
    //TabPreset->TabVisible = false;

    FStrmPlay = false;
    String sAVILibDir = g_sAppDir + "LibAV";
    FFPlayer1->SetLicenseKey(LICENSE_KEY);
    FFPlayer1->DisableFPUExceptions();
    if (!FFPlayer1->LoadAVLib(sAVILibDir))
    {
        reMsg->Lines->Add("영상표출 라이브러리 초기화 실패.");
#if 0
        if (g_sLang!= "kr") Application->MessageBox(L"Stream display library load failed.", L"Stream display fail", MB_OK|MB_ICONERROR|MB_APPLMODAL);
        else                Application->MessageBox(L"영상표출 라이브러리를 로드하지 못하였습니다.", L"영상표출 오류", MB_OK|MB_ICONERROR|MB_APPLMODAL);
#endif
    }

    PgCam->Properties->HideTabs = true;

    PnlCamera->ParentColor = false;
    FTmrShow = true;
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::CommClose()
{
    try
    {
        SAFE_DELETE(FSelIds);
        CMM_SaveForm(g_sFormsDir, this);

        CloseWebCamera();
        CloseRtsp();

        //::CoUninitialize();
    }
    catch(...)
    {
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::FormShow(TObject *Sender)
{
    Refresh();
    TmrShow->Enabled = FTmrShow;
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::FormActivate(TObject *Sender)
{
    ActivateForm(true);
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::FormDeactivate(TObject *Sender)
{
    ActivateForm(false);
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::LoadLocalSkin()
{
    PnlCamera->ParentColor = false;
    PnlCamera->Color = clBlack;
    //XNVTViewerCtrl1->Visible = false;
    Refresh();
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::TmrShowTimer(TObject *Sender)
{
    TmrShow->Enabled = false;

    FRAMEWCamStateList1->UpdateList();
    FRAMEWCamStateList1->CxList->Enabled = false;
    UpdatePingList();
    FRAMEWCamStateList1->CxList->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::FormClose(TObject *Sender, TCloseAction &Action)
{
    try {
        CommClose();

        WCAM020M = NULL;
        Action = caFree;
    } catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::OnMainFormMessage(TMessage &Msg)
{
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::OnCctvStateRefreshMessage(TMessage &Msg)
{
    FRAMEWCamStateList1->RefreshStatus();
    RefreshPingList();
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::ActivateForm(bool AActivate)
{
    if (AActivate) FRAMEWCamStateList1->RefreshStatus();
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::DisplayInfo()
{
    ClearPreset();

    FSelCtlr = NULL;
    PnlCctv->Caption = " " + lblSelCctv->Caption + " -";//" Select CCTV: -";

    TcxGridBandedTableView *TvList = FRAMEWCamStateList1->TvList;
    TcxDataController *pGDC = TvList->DataController;
    int nSelIdx = CMM_GetRecordIndex(TvList);
	if (nSelIdx < 0) return;

    String CTLR_NMBR = VarToStr(pGDC->Values[nSelIdx][FRAMEWCamStateList1->Col01->Index]);

    int nMemPtr = (int)pGDC->Values[nSelIdx][FRAMEWCamStateList1->Col99->Index];
    FSelCtlr = (TWCamCtlr*)nMemPtr;
    if (!FSelCtlr) return;

    PnlCctv->Caption = " " + lblSelCctv->Caption + " [" + FSelCtlr->WCAM_CTLR_ID + "] " + FSelCtlr->WCAM_NM;

    PnlCamConrtol->Enabled = false;
    PnlPreset->Enabled = false;
    try
    {
        if (FSelCtlr->WCAM_TYPE_CD == "WEB")
        {
            CloseRtsp();

            if (OpenWebCamera())
            {
                InitPreset();

                PnlCamConrtol->Enabled = true;
                PnlPreset->Enabled = true;
            }
        }
        else
        {
            CloseWebCamera();

            if (XNVTViewerCtrl1->Visible) XNVTViewerCtrl1->Visible = false;
            OpenRtsp();
        }
    }
    catch(Exception &e)
    {
    }

    BtnWebCamUrl->Enabled = true;
}
//---------------------------------------------------------------------------
bool __fastcall TWCAM020M::OpenRtsp()
{
    if (!FSelCtlr) return false;

    try
    {
        reMsg->Lines->Clear();

        CloseRtsp();

        FStrmAddr = FSelCtlr->STRM_SESN_NM.Trim();
        if (FStrmAddr != "")
        {
            FFPlayer1->AspectRatio = -1;//ChkFullScreen->Checked ? -1 : 0;
            FFPlayer1->TryOpen(FStrmAddr, PnlCamera->Handle);
            FStrmPlay = true;
        }
    }
    catch(Exception &e)
    {
    }
    return true;
}
//---------------------------------------------------------------------------
void __fastcall TWCAM020M::CloseRtsp()
{
    if (!FStrmPlay) return;

    try
    {
        if (FFPlayer1->ScreenHandle != NULL)
        {
            FFPlayer1->Stop(true);
            PostMessage(FFPlayer1->ScreenHandle, CM_INVALIDATE, 0, 0);
            UpdateWindow(FFPlayer1->ScreenHandle);
            //FFPlayer1->ScreenHandle = NULL;
        }
    }
    catch(Exception &e)
    {
    }
    FStrmPlay = false;
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnAllSelectClick(TObject *Sender)
{
    TcxButton *pBtn = (TcxButton*)Sender;
    if (PgControl->Properties->ActivePage != TabPing)
        CMM_CheckAllListItem(FRAMEWCamStateList1->TvList, FRAMEWCamStateList1->ColumnSel->Index, pBtn->Tag);
    else
        CMM_CheckAllListItem(TvPing, ColumnSel->Index, pBtn->Tag);
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::ClearCheckList()
{
#if 0
    TcxGridBandedTableView *TvList = FRAMEWCamStateList1->TvList;
    TcxDataController *pGDC = TvList->DataController;
    try
    {
        TvList->BeginUpdate();
        pGDC->BeginUpdate();
        int nRows = pGDC->RecordCount;
        for (int ii = 0; ii < nRows; ii++)
        {
            pGDC->Values[ii][FRAMEWCamStateList1->ColumnSel->Index] = false;
        }
    }
    __finally
    {
        pGDC->EndUpdate();
        TvList->EndUpdate();
    }
#endif
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::FRAMEWCamStateList1TvListCellDblClick(TcxCustomGridTableView *Sender,
          TcxGridTableDataCellViewInfo *ACellViewInfo, TMouseButton AButton,
          TShiftState AShift, bool &AHandled)
{
	if (!ACellViewInfo) return;

    ClearCheckList();

    TcxGridBandedTableView *TvList = FRAMEWCamStateList1->TvList;
    TcxDataController *pGDC = TvList->DataController;
    int nSelIdx = CMM_GetRecordIndex(TvList);
	if (nSelIdx < 0) return;
    pGDC->Values[nSelIdx][FRAMEWCamStateList1->ColumnSel->Index] = true;

    DisplayInfo();
}
//---------------------------------------------------------------------------


int __fastcall TWCAM020M::GetSelListItems(bool ACommCheck/*=true*/)
{
    TcxGridBandedTableView *TvList = FRAMEWCamStateList1->TvList;
    TcxDataController      *pGDC   = TvList->DataController;

    FSelIds->Clear();
    try
    {
        bool bSelected;

        int nRows = TvList->ViewData->RecordCount;
        TvList->BeginUpdate();

        for (int ii = 0; ii < nRows; ii++)
        {
            TcxCustomGridRow* ARow = TvList->ViewData->Rows[ii];
            int nMemPtr = (int)ARow->Values[FRAMEWCamStateList1->Col99->Index];
            TWCamCtlr *pCctv = (TWCamCtlr*)nMemPtr;
            if (!pCctv) continue;

            bSelected = (bool)ARow->Values[FRAMEWCamStateList1->ColumnSel->Index];
            if (bSelected)
            {
                String CTLR_NMBR = ARow->Values[FRAMEWCamStateList1->Col01->Index];
                if (ACommCheck)
                {
                    if (pCctv->STATE.Comm == wcam_normal)
                    {
                        FSelIds->Add(CTLR_NMBR);
                    }
                }
                else
                {
                    FSelIds->Add(CTLR_NMBR);
                }
            }
        }
    }
    __finally
    {
        TvList->EndUpdate();
    }

    return FSelIds->Count;
}
//---------------------------------------------------------------------------



void __fastcall TWCAM020M::BtnWebCamUrlClick(TObject *Sender)
{
    if (FSelCtlr)
    {
        if (FSelCtlr->WCAM_CTLR_IP.Trim() != "")
        {
            String sUrl = "http://" + FSelCtlr->WCAM_CTLR_IP.Trim();
            ShellExecute(NULL, NULL, sUrl.c_str(), NULL, NULL, 0);
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::PgControlPageChanging(TObject *Sender, TcxTabSheet *NewPage,
          bool &AllowChange)
{
    if (NewPage == TabPing)
    {
        BtnAllSelect->Visible = false;
        BtnAllClear->Visible = false;
        BtnReverse->Visible = false;
    }
    else
    {
#if 0
        if (BtnAllSelect->Visible == false) BtnAllSelect->Visible = true;;
        if (BtnAllClear->Visible  == false) BtnAllClear->Visible = true;;
        if (BtnReverse->Visible   == false) BtnReverse->Visible = true;;
#endif
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::UpdatePingList()
{
    CMM_ClearGridTableView(TvPing);

    int ii, jj;
    int nCols = 0;

    TcxDataController *pGDC = TvPing->DataController;

    WCamCtlrManager->FLists.Lock();
    try
    {
        int nRow;
        TvPing->BeginUpdate();
        pGDC->BeginUpdate();

        FOR_STL(TWCamCtlr*, pObj, WCamCtlrManager->FLists)
        {
            if (pObj->DEL_YN == "Y") continue;

            nRow = pGDC->AppendRecord();

            if (pObj->STATE.Comm == wcam_normal) pGDC->Values[nRow][ColumnSel->Index] = false;
            else                                 pGDC->Values[nRow][ColumnSel->Index] = true;

            pGDC->Values[nRow][Col01->Index] = String(pObj->WCAM_CTLR_NMBR);
            pGDC->Values[nRow][Col02->Index] = pObj->WCAM_CTLR_ID;
            pGDC->Values[nRow][Col03->Index] = pObj->WCAM_NM;

            pGDC->Values[nRow][Col04->Index] = pObj->STATE.Comm == wcam_normal ? FrmLang->lblComm0->Caption : FrmLang->lblComm1->Caption;

            pGDC->Values[nRow][Col05->Index] = pObj->WCAM_CTLR_IP;
            pGDC->Values[nRow][Col06->Index] = "-";
            pGDC->Values[nRow][Col07->Index] = "-";
            pGDC->Values[nRow][Col08->Index] = "-";

            pGDC->Values[nRow][Col09->Index] = pObj->WCAM_CTLR_IP;
            pGDC->Values[nRow][Col10->Index] = "-";
            pGDC->Values[nRow][Col11->Index] = "-";
            pGDC->Values[nRow][Col12->Index] = "-";

            pGDC->Values[nRow][Col99->Index] = (int)pObj;
        }
    }
    __finally
    {
        WCamCtlrManager->FLists.UnLock();

        pGDC->EndUpdate();
        TvPing->EndUpdate();
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::RefreshPingList(bool AInit/*=false*/)
{
    TcxDataController *pGDC = TvPing->DataController;
    try
    {
        TvPing->BeginUpdate();
        pGDC->BeginUpdate();

        int nRows = pGDC->RecordCount;
        for(int nRow = 0; nRow < nRows; nRow++)
        {
            int nMemPtr = TvPing->DataController->Values[nRow][Col99->Index];
            TWCamCtlr *pObj = (TWCamCtlr*)nMemPtr;
            if (!pObj) continue;

            if (AInit == false && PgControl->Properties->ActivePage != TabPing)
            {
                if (pObj->STATE.Comm == cctv_normal) pGDC->Values[nRow][ColumnSel->Index] = false;
                else                                 pGDC->Values[nRow][ColumnSel->Index] = true;
            }

            if (AInit)
            {
                pGDC->Values[nRow][Col06->Index] = "-";
                pGDC->Values[nRow][Col07->Index] = "-";
                pGDC->Values[nRow][Col08->Index] = "-";

                pGDC->Values[nRow][Col10->Index] = "-";
                pGDC->Values[nRow][Col11->Index] = "-";
                pGDC->Values[nRow][Col12->Index] = "-";
            }

            pGDC->Values[nRow][Col04->Index] = pObj->STATE.Comm == wcam_normal ? FrmLang->lblComm0->Caption : FrmLang->lblComm1->Caption;
        }
    }
    __finally
    {
        pGDC->EndUpdate();
        TvPing->EndUpdate();
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::PingNetwork(String AIp, int APort)
{
    try
    {
        IdIcmpClient1->Host = AIp;
        IdIcmpClient1->Port = EdPingPort->Value/*512*/;
        IdIcmpClient1->ReceiveTimeout = EdPingTimeout->Value;
        IdIcmpClient1->Ping(IdIcmpClient1->Host, IdIcmpClient1->Port);
    }
	catch (Exception &e)
	{
		Application->ShowException(&e);
	}
    catch(...)
    {
        ShowMessage("Ping error[Unknown]");
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnNwkPingClick(TObject *Sender)
{
    TWaitCursor waitCrs;
	TcxDataController *pGDC = TvPing->DataController;
	int nRows  = pGDC->RecordCount;

    String sMsg;
    int nSelCnt = CMM_GetCheckCount(TvPing, ColumnSel->Index);
    if (0 == nSelCnt)
    {
        sMsg = cxLabel14->Caption;
        Application->MessageBox(sMsg.c_str(), L"Web Camera Network Ping Test", MB_OK|MB_ICONERROR|MB_APPLMODAL);
        CxPing->SetFocus();
        return;
    }

    RefreshPingList(true);

    PnlPing->Enabled = false;

    String sSvrIp;
    int    nSvrPort;
    bool   bPing;

    for (int ii = 0; ii < nRows; ii++)
    {
        bPing = pGDC->Values[ii][ColumnSel->Index];
        if (!bPing) continue;

        //pGDC->Values[ii][ColPingMon->Index] = Now().FormatString("yyyy-mm-dd hh:mm:ss");

        FPingType = 1;

        sSvrIp = pGDC->Values[ii][Col05->Index];
        if (sSvrIp == NULL || sSvrIp.IsEmpty())
        {
            continue;
        }
        pGDC->Values[ii][Col06->Index] = "?";
        pGDC->Values[ii][Col07->Index] = "?";
        pGDC->Values[ii][Col08->Index] = "?";

        nSvrPort = 0;

        FPingTimeout = false;
        PingNetwork(sSvrIp.Trim(), nSvrPort);
        if (FPingTimeout)
        {
            pGDC->Values[ii][Col08->Index] = "Time out";
        }

        Application->ProcessMessages();

        FPingType = 2;

        sSvrIp = pGDC->Values[ii][Col09->Index];
        if (sSvrIp == NULL || sSvrIp.IsEmpty())
        {
            continue;
        }
        pGDC->Values[ii][Col10->Index] = "?";
        pGDC->Values[ii][Col11->Index] = "?";
        pGDC->Values[ii][Col12->Index] = "?";

        nSvrPort = 0;

        FPingTimeout = false;
        PingNetwork(sSvrIp.Trim(), nSvrPort);
        if (FPingTimeout)
        {
            pGDC->Values[ii][Col12->Index] = "Time out";
        }

        Application->ProcessMessages();
    }
    PnlPing->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnNwkPingClearClick(TObject *Sender)
{
    RefreshPingList(true);
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::Col04CustomDrawCell(TcxCustomGridTableView *Sender, TcxCanvas *ACanvas,
          TcxGridTableDataCellViewInfo *AViewInfo, bool &ADone)
{
    try
    {
        TColor tColor;
        String sStatus = AViewInfo->GridRecord->DisplayTexts[AViewInfo->Item->Index];
        tColor = ACanvas->Brush->Color;

        if      (sStatus.Pos("-"))                                tColor = clGray;
        else if (sStatus.Pos(FrmLang->lblComm1->Caption.Trim()))  tColor = clRed;
        else                                                      tColor = clLime;

        ACanvas->SetBrushColor(tColor);
        ACanvas->Font->Color  = clBlack;
    }
    catch(Exception &e)
    {
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::IdIcmpClient1Reply(TComponent *ASender, const TReplyStatus *AReplyStatus)
{
    try
	{
        String sRcvIp = AReplyStatus->FromIpAddress;
        int    nRcvPort= IdIcmpClient1->Port;
        if (rsTimeOut == AReplyStatus->ReplyStatusType || sRcvIp == "0.0.0.0")
        {
            FPingTimeout = true;
            return;
        }

        TcxDataController *pGDC = TvPing->DataController;
        int nRows  = pGDC->RecordCount;

        String sSvrIp;
		for (int ii = 0; ii < nRows; ii++)
        {
			if (FPingType == 1)
                sSvrIp = pGDC->Values[ii][Col05->Index];
            else
                sSvrIp = pGDC->Values[ii][Col09->Index];

			int nSvrPort = 0;

            if (sSvrIp.Trim() == sRcvIp && nRcvPort == nSvrPort)
            {
                if (FPingType == 1)
                {
                    if (AReplyStatus->MsRoundTripTime > 100)
                    {
                        pGDC->Values[ii][Col08->Index] = "Delayed";
                    }
                    else
                    {
                        pGDC->Values[ii][Col08->Index] = "Normal";
                    }

                    pGDC->Values[ii][Col06->Index] = String(AReplyStatus->MsRoundTripTime) + " ";
                    pGDC->Values[ii][Col07->Index] = String(AReplyStatus->TimeToLive) + " ";
                }
                else
                {
                    if (AReplyStatus->MsRoundTripTime > 100)
                    {
                        pGDC->Values[ii][Col12->Index] = "Delayed";
                    }
                    else
                    {
                        pGDC->Values[ii][Col12->Index] = "Normal";
                    }

                    pGDC->Values[ii][Col10->Index] = String(AReplyStatus->MsRoundTripTime) + " ";
                    pGDC->Values[ii][Col11->Index] = String(AReplyStatus->TimeToLive) + " ";
                }

                break;
            }

        }
	}
	catch(Exception &e)
    {
	}
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::Col08CustomDrawCell(TcxCustomGridTableView *Sender, TcxCanvas *ACanvas,
          TcxGridTableDataCellViewInfo *AViewInfo, bool &ADone)
{
    try
    {
        int iIndex = AViewInfo->Item->Index;

        ACanvas->Canvas->Brush->Style = bsSolid;
        String val  = AViewInfo->GridRecord->DisplayTexts[iIndex];

        ACanvas->Canvas->Font->Color = clBlack;
        if (val == "Normal")        ACanvas->Canvas->Brush->Color = clLime;
        else if (val == "Delayed")  ACanvas->Canvas->Brush->Color = clRed;
        else if (val == "Time out") ACanvas->Canvas->Brush->Color = clRed;
        else                        ACanvas->Canvas->Brush->Color = clSilver;

    } catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::TvPingCellDblClick(TcxCustomGridTableView *Sender, TcxGridTableDataCellViewInfo *ACellViewInfo,
          TMouseButton AButton, TShiftState AShift,
          bool &AHandled)
{
	if (!ACellViewInfo) return;

	TcxGridDataController *pGDC = TvPing->DataController;
	int nRow = pGDC->FocusedRecordIndex;
	if( nRow <= -1 )
		return;

    if (ACellViewInfo->Item->Index == Col05->Index ||
        ACellViewInfo->Item->Index == Col09->Index)
	{
        String sSvrIp = pGDC->Values[nRow][ACellViewInfo->Item->Index];
        ITSUtil_NetworkPing(sSvrIp);
    }
}
//---------------------------------------------------------------------------

bool __fastcall TWCAM020M::OpenWebCamera()
{
    if (!FSelCtlr) return false;

    try
    {
        reMsg->Lines->Clear();

        CloseWebCamera();
        if (!XNVTViewerCtrl1->Visible) XNVTViewerCtrl1->Visible = true;

        XNVTViewerCtrl1->IPAddress = FSelCtlr->WCAM_CTLR_IP;
        XNVTViewerCtrl1->Port      = FSelCtlr->CMRA_PORT;
        XNVTViewerCtrl1->ID        = FSelCtlr->CMRA_ID;
        XNVTViewerCtrl1->Password  = FSelCtlr->CMRA_PSWD;
        XNVTViewerCtrl1->Channel   = FSelCtlr->CMRA_CHNL;
        XNVTViewerCtrl1->EnableBackChannelAudio = false;

        if (XNVTViewerCtrl1->Preview())
        {
            BtnSaveImgFile->Enabled = true;
            return true;
        }
        BtnSaveImgFile->Enabled = false;
    }
    catch(...)
    {
    }
    return false;
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::CloseWebCamera()
{
    try
    {
    	XNVTViewerCtrl1->Stop();
    }
    catch(...)
    {
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnZoomInOutMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
    try
    {
        TImageBtn *pBtn = (TImageBtn*)Sender;
        if (pBtn->Tag == 0)
        {
            XNVTViewerCtrl1->PutCamCtl(CTL_PTZ_CONT, SB_ZOOM_IN, 3);
        }
        else
        {
            XNVTViewerCtrl1->PutCamCtl(CTL_PTZ_CONT, SB_ZOOM_OUT, 3);
        }
    }
    catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnZoomInOutMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
    try
    {
        TImageBtn *pBtn = (TImageBtn*)Sender;
        XNVTViewerCtrl1->PutCamCtl(CTL_PTZ_CONT, 0x000000, 3);
    }
    catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnFocusInOutMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
    try
    {
        TImageBtn *pBtn = (TImageBtn*)Sender;
        if (pBtn->Tag == 0)
        {
            XNVTViewerCtrl1->PutCamCtl(CTL_FOCUS_CONT, SB_FOCUS_IN, 1);
        }
        else
        {
            XNVTViewerCtrl1->PutCamCtl(CTL_FOCUS_CONT, SB_FOCUS_OUT, 1);
        }
    }
    catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnFocusInOutMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
    try
    {
        TImageBtn *pBtn = (TImageBtn*)Sender;
        XNVTViewerCtrl1->PutCamCtl(CTL_FOCUS_CONT, 0x000000, 3);
    }
    catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnPanTileMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
    try
    {
        TImageBtn *pBtn = (TImageBtn*)Sender;
        switch(pBtn->Tag)
        {
        case 0: XNVTViewerCtrl1->PutCamCtl(CTL_PTZ_CONT, SB_TILT_UP,   3); break; // Up
        case 1: XNVTViewerCtrl1->PutCamCtl(CTL_PTZ_CONT, SB_TILT_DOWN, 3); break; // Down
        case 2: XNVTViewerCtrl1->PutCamCtl(CTL_PTZ_CONT, SB_PAN_LEFT,  3); break; // Left
        case 3: XNVTViewerCtrl1->PutCamCtl(CTL_PTZ_CONT, SB_PAN_RIGHT, 3); break; // Right
        }
    }
    catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnPanTileMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
    // Zoom In/Out MouseUp Event 와 동일
    try
    {
        TImageBtn *pBtn = (TImageBtn*)Sender;
        XNVTViewerCtrl1->PutCamCtl(CTL_PTZ_CONT, 0x000000, 3);
    }
    catch(...) {}
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnSaveImgFileClick(TObject *Sender)
{
	String sSaveFileName;

	if (!FSelCtlr || XNVTViewerCtrl1->OCXState == GRAPH_NONE)
	{
        String sMsg = cxLabel1->Caption;
        Application->MessageBox(sMsg.c_str(), L"Save Snap Shot", MB_OK|MB_ICONERROR|MB_APPLMODAL);
		return;
	}

	sSaveFileName.printf(L"%s\\%d_%s.bmp", g_sTempDir.c_str(), FSelCtlr->WCAM_CTLR_NMBR, Now().FormatString("yyyymmddhhnnss").c_str());

	if (XNVTViewerCtrl1->FileSnapShot(sSaveFileName.c_str()))
    {
        Application->MessageBox(sSaveFileName.c_str(), L"Save Snap Shot Success", MB_OK|MB_ICONINFORMATION|MB_APPLMODAL);
	}
    else
    {
        Application->MessageBox(cxLabel2->Caption.c_str(), L"Save Snap Shot Fail", MB_OK|MB_ICONERROR|MB_APPLMODAL);
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::ClearPreset()
{
    CMM_ClearGridTableView(TvPreset);
    SePresetNo->Value = 1;
    EdPresetName->Text = "";
    ChkCctvPresetDef->Checked = false;
    //PnlPreset->Enabled = false;
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::InitPreset()
{
    if (!FSelCtlr) return;

    ClearPreset();

    TcxDataController*  pGDC = TvPreset->DataController;

    TvPreset->BeginUpdate();

    try
    {
        FSelCtlr->FLists.Lock();
        try
        {
            FOR_STL(TWCamPset*, pObj, FSelCtlr->FLists)
            {
                if (pObj->DEL_YN == "Y") continue;

                int nRow = pGDC->AppendRecord();

                pGDC->Values[nRow][ColPresetNo->Index]      = String(pObj->PSET_NMBR);
                pGDC->Values[nRow][ColPresetName->Index]    = pObj->PSET_NM;
                pGDC->Values[nRow][ColPresetPan->Index]     = String(pObj->PAN);
                pGDC->Values[nRow][ColPresetTilt->Index]    = String(pObj->TILT);
                pGDC->Values[nRow][ColPresetZoom->Index]    = String(pObj->ZOOM);
                pGDC->Values[nRow][ColPresetFocus->Index]   = String(pObj->FOCS);
                pGDC->Values[nRow][ColPresetAngle->Index]   = "";
                pGDC->Values[nRow][ColPresetDefault->Index] = pObj->DFLT_YN;
            }
        }
        __finally
        {
            FSelCtlr->FLists.UnLock();
        }
    }
    __finally
    {
        TvPreset->EndUpdate();
        PnlPreset->Enabled = true;
        BtnCctvPresetDel->Enabled = false;
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnCctvPresetClick(TObject *Sender)
{
    //프리셋 이동
    if (FSelCtlr)
    {
        int nPresetNo = SePresetNo->Value;
        if (XNVTViewerCtrl1->PutCamCtl(PRESET_MOVE, nPresetNo, 1))
        {
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnCctvPresetSetClick(TObject *Sender)
{
    //프리셋 설정
    if (FSelCtlr)
    {
        int    nPresetNo = SePresetNo->Value;
        String sPresetNm = EdPresetName->Text.Trim();
        String sDefault  = ChkCctvPresetDef->Checked ? "Y" : "N";

        if (sPresetNm == "")
        {
            String sMsg;
            sMsg = cxLabel3->Caption;//"프리셋 명을 입력하세요..";
            Application->MessageBox(sMsg.c_str(), cxLabel4->Caption.c_str(), MB_OK|MB_ICONERROR|MB_APPLMODAL);
            EdPresetName->SetFocus();
        }

        if (XNVTViewerCtrl1->PutCamCtl(PRESET_SET, nPresetNo, 1))
        {
            TWCamPset *pSet = FSelCtlr->FLists.Find(nPresetNo);
            if (!pSet)
            {
                pSet = new TWCamPset();
                pSet->WCAM_CTLR_NMBR = FSelCtlr->WCAM_CTLR_NMBR;
                pSet->PSET_NMBR = nPresetNo;
                FSelCtlr->FLists.Push(pSet->PSET_NMBR, pSet);
            }
            pSet->PSET_NM = sPresetNm;
            pSet->DFLT_YN = sDefault;
            pSet->DEL_YN  = "N";
            WCamCtlrManager->SavePreSet(FSelCtlr);

            InitPreset();

            SePresetNo->Value  = nPresetNo;
            EdPresetName->Text = sPresetNm;
            ChkCctvPresetDef->Checked = sDefault == "Y" ? true : false;

            BtnCctvPresetDel->Enabled = true;
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::BtnCctvPresetDelClick(TObject *Sender)
{
    //프리셋 삭제
    if (FSelCtlr)
    {
        int nPresetNo = SePresetNo->Value;
        if (XNVTViewerCtrl1->PutCamCtl(PRESET_CLEAR, nPresetNo, 1))
        {
            TWCamPset *pSet = FSelCtlr->FLists.Find(nPresetNo);
            if (!pSet)
            {
                return;
            }
            pSet->PSET_NM = "";
            pSet->DEL_YN  = "Y";
            WCamCtlrManager->SavePreSet(FSelCtlr);

            InitPreset();
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::TvPresetCellDblClick(TcxCustomGridTableView *Sender, TcxGridTableDataCellViewInfo *ACellViewInfo,
          TMouseButton AButton, TShiftState AShift, bool &AHandled)
{
	if (!ACellViewInfo) return;
	int nRow = TvPreset->DataController->FocusedRecordIndex;
	if( nRow <= -1 )
		return;

    String sPresetNo = TvPreset->DataController->Values[nRow][ColPresetNo->Index];
    String sPresetNm = TvPreset->DataController->Values[nRow][ColPresetName->Index];
    String sDefault  = TvPreset->DataController->Values[nRow][ColPresetDefault->Index];

    ChkCctvPresetDef->Checked = sDefault == "Y" ? true : false;
    SePresetNo->Value  = sPresetNo.ToIntDef(1);
    EdPresetName->Text = sPresetNm;

    BtnCctvPresetDel->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::SePresetNoPropertiesEditValueChanged(TObject *Sender)
{
    if (FSelCtlr)
    {
        int nPresetNo = SePresetNo->Value;
        TWCamPset* pSet = FSelCtlr->FLists.Find(nPresetNo);
        if (pSet) BtnCctvPresetDel->Enabled = true;
        else      BtnCctvPresetDel->Enabled = false;
    }
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::reMsgDblClick(TObject *Sender)
{
    reMsg->Lines->Clear();
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::XNVTViewerCtrl1EventNotify(TObject *Sender, BSTR message, long message_size)
{
    reMsg->Lines->Add(message);
}
//---------------------------------------------------------------------------

void __fastcall TWCAM020M::FFPlayer1State(TObject *Sender, TPlayState APlayState)
{
    switch(APlayState)
    {
    case Ffbasecomponent::psPlay:   reMsg->Lines->Add("Play..."); break;
    case Ffbasecomponent::psResume: reMsg->Lines->Add("Resume."); break;
    case Ffbasecomponent::psPause:  reMsg->Lines->Add("Pause.."); break;
    case Ffbasecomponent::psStep:   reMsg->Lines->Add("Step..."); break;
    case Ffbasecomponent::psStop:
        if (FFPlayer1->ScreenHandle != NULL)
        {
            PostMessage(FFPlayer1->ScreenHandle, CM_INVALIDATE, 0, 0);
            UpdateWindow(FFPlayer1->ScreenHandle);
            //FFPlayer1->ScreenHandle = NULL;
        }
        reMsg->Lines->Add("Stop...");
        break;
    case Ffbasecomponent::psEnd:
        {
            FFPlayer1->Stop(true);
            PostMessage(FFPlayer1->ScreenHandle, CM_INVALIDATE, 0, 0);
            UpdateWindow(FFPlayer1->ScreenHandle);
            //FFPlayer1->ScreenHandle = NULL;
            FStrmPlay = false;
        }
        reMsg->Lines->Add("End...");
        break;
    }
}
//---------------------------------------------------------------------------

