#include "stdafx.h"
#include "NZSDK_Sample.h"
#include "DlgLiveSample.h"
#include "CMyString.h"
#include <algorithm>
#import <msxml3.dll> named_guids


static LPCTSTR stream_no = _T("2");

IMPLEMENT_DYNAMIC(CDlgLiveSample, CDialog)

CDlgLiveSample::CDlgLiveSample( NZ_SDK_KIND eSdkKind, CWnd* pParent )	: CDialog(CDlgLiveSample::IDD, pParent)
{
	::CoInitialize(NULL);
	InitializeCriticalSectionEx(&m_csCaptureStreams, 0, CRITICAL_SECTION_NO_DEBUG_INFO);
	m_stop_capture = FALSE;
	m_eSdkKind = eSdkKind;
}

CDlgLiveSample::~CDlgLiveSample()
{
	DeleteCriticalSection(&m_csCaptureStreams);
	::CoUninitialize();
}

void CDlgLiveSample::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_PTZ_CB_SPEED, m_cb_ptz_speed);
	DDX_Control(pDX, IDC_CB_MODEL, m_cb_model);
	DDX_Control(pDX, IDC_PB_DATETIMEPICKER1, m_dtp);
	DDX_Control(pDX, IDC_COMBO_DATA_CATEGORY, m_cb_data_category);
	DDX_Control(pDX, IDC_DATA_FROM_DATE, m_export_from_date);
	DDX_Control(pDX, IDC_DATA_FROM_TIME, m_export_from_time);
	DDX_Control(pDX, IDC_DATA_TO_DATE, m_export_to_date);
	DDX_Control(pDX, IDC_DATA_TO_TIME, m_export_to_time);
	DDX_Control(pDX, IDC_COMBO_DATA_IMAGE, m_cb_data_image);
}


BEGIN_MESSAGE_MAP(CDlgLiveSample, CDialog)
	ON_BN_CLICKED(IDC_NRS_BTN_CONNECT, &CDlgLiveSample::OnBnClickedNrsBtnConnect)
	ON_BN_CLICKED(IDC_NRS_BTN_DISCONNECT, &CDlgLiveSample::OnBnClickedNrsBtnDisconnect)
	ON_BN_CLICKED(IDC_VIDEO_BTN_OPEN, &CDlgLiveSample::OnBnClickedVideoBtnOpen)
	ON_BN_CLICKED(IDC_VIDEO_BTN_CLOSE, &CDlgLiveSample::OnBnClickedVideoBtnClose)
	ON_WM_CLOSE()
	ON_BN_CLICKED(IDC_PRESET_BTN_SET, &CDlgLiveSample::OnBnClickedPresetBtnSet)
	ON_BN_CLICKED(IDC_PRESET_BTN_MOVE, &CDlgLiveSample::OnBnClickedPresetBtnMove)
	ON_BN_CLICKED(IDC_AUDIO_BTN_OPEN, &CDlgLiveSample::OnBnClickedAudioBtnOpen)
	ON_BN_CLICKED(IDC_AUDIO_BTN_CLOSE, &CDlgLiveSample::OnBnClickedAudioBtnClose)
	ON_BN_CLICKED(IDC_EVENT_BTN_OPEN, &CDlgLiveSample::OnBnClickedEventBtnOpen)
	ON_BN_CLICKED(IDC_EVENT_BTN_CLOSE, &CDlgLiveSample::OnBnClickedEventBtnClose)
	ON_CBN_SELCHANGE(IDC_CB_MODEL, &CDlgLiveSample::OnCbnSelchangeCbModel)
	ON_BN_CLICKED(IDC_BTN_TOUR_START, &CDlgLiveSample::OnBnClickedBtnTourStart)
	ON_BN_CLICKED(IDC_BTN_TOUR_STOP, &CDlgLiveSample::OnBnClickedBtnTourStop)
	ON_BN_CLICKED(IDC_TALK_BTN_START, &CDlgLiveSample::OnBnClickedTalkBtnStart)
	ON_BN_CLICKED(IDC_TALK_BTN_STOP, &CDlgLiveSample::OnBnClickedTalkBtnStop)
	ON_BN_CLICKED(IDC_PB_VIDEO_BTN_OPEN, &CDlgLiveSample::OnBnClickedPbVideoBtnOpen)
	ON_BN_CLICKED(IDC_PB_VIDEO_BTN_CLOSE, &CDlgLiveSample::OnBnClickedPbVideoBtnClose)
	ON_BN_CLICKED(IDC_PB_PLAY, &CDlgLiveSample::OnBnClickedPbPlay)
	ON_BN_CLICKED(IDC_PB_PAUSE, &CDlgLiveSample::OnBnClickedPbPause)
	ON_BN_CLICKED(IDC_BUTTON_GET_DATAS, &CDlgLiveSample::OnBnClickedGetDatas)
	ON_BN_CLICKED(IDC_BUTTON_EXPORT_VIDEO, &CDlgLiveSample::OnBnClickedExportVideo)
	ON_BN_CLICKED(IDC_BUTTON_CANCEL_EXPORT, &CDlgLiveSample::OnBnClickedCancelExport)
	ON_BN_CLICKED(IDC_BUTTON_EXPORT_IMAGE, &CDlgLiveSample::OnBnClickedExportImage)
	ON_BN_CLICKED(IDC_PTZ_GET_SPECIFICATION, &CDlgLiveSample::OnBnClickedGetPtzSpecification)
	ON_BN_CLICKED(IDC_PTZ_GET_POSITION, &CDlgLiveSample::OnBnClickedGetPtzPosition)
	ON_BN_CLICKED(IDC_PTZ_SET_POSITION, &CDlgLiveSample::OnBnClickedSetPtzPosition)
	ON_WM_DESTROY()
	ON_MESSAGE(CDlgScreen::LUM_SCREEN_CLOSED, &CDlgLiveSample::OnScreenClosed)
END_MESSAGE_MAP()


// CDlgLiveSample 메시지 처리기입니다.

static UINT __stdcall g_on_capture( void *arg )
{
	return ( (CDlgLiveSample*)arg )->OnCapture( ) ? 0 : -1;
}

BOOL CDlgLiveSample::OnInitDialog()
{
	CDialog::OnInitDialog();


	GetDlgItem( IDC_VIDEO_EDIT_CHANNEL )->SetWindowText( _T("1") );
	GetDlgItem( IDC_AUDIO_EDIT_CHANNEL )->SetWindowText( _T("1") );
	GetDlgItem( IDC_EVENT_EDIT_CHANNEL )->SetWindowText( _T("1,3,4") );
	GetDlgItem( IDC_PTZ_EDIT_CHANNEL )->SetWindowText( _T("1") );
	GetDlgItem( IDC_TALK_EDIT_CHANNEL )->SetWindowText( _T("1") );
	GetDlgItem( IDC_PB_VIDEO_EDIT_CHANNEL )->SetWindowText( _T("1") );

	SYSTEMTIME st;
	GetLocalTime( &st );
	st.wMinute = 0;
	st.wSecond = 0;
	m_dtp.SetFormat( _T("yyyy-MM-dd  HH':'mm':'ss") );
	m_dtp.SetTime( &st );

	EnableVideo( FALSE );
	EnableAudio( FALSE );
	EnableEvent( FALSE );
	EnableTalk( FALSE );
	EnableBackup( FALSE );
	EnablePTZ( FALSE );
	EnableData( FALSE );
	GetDlgItem( IDC_NRS_BTN_DISCONNECT )->EnableWindow( FALSE );
	( (CButton*)GetDlgItem(IDC_VIDEO_CHECK_AUTO_PLAY) )->SetCheck( BST_CHECKED );
	( (CButton*)GetDlgItem(IDC_PB_VIDEO_CHECK_AUTO_PLAY) )->SetCheck( BST_CHECKED );

	for( int i=0; i<10; i++ )
	{
		CString strTemp;
		strTemp.Format(_T("%d"), i+1);
		m_cb_ptz_speed.InsertString( i, strTemp );
	}
	m_cb_ptz_speed.SetCurSel( 4 );

	m_cb_model.InsertString( 0, _T("Rhino") );
	m_cb_model.InsertString( 1, _T("Leopard") );
	m_cb_model.SetCurSel( 1 );
	OnCbnSelchangeCbModel( );

	GetDlgItem( IDC_PTZ_EDIT_PRESET )->SetWindowText( _T("1") );

	m_cb_data_category.InsertString(0, _T("Camera"));
	m_cb_data_category.InsertString(1, _T("Nrs"));
	m_cb_data_category.InsertString(2, _T("RecordSchedule"));
	m_cb_data_category.InsertString(3, _T("User"));
	m_cb_data_category.InsertString(4, _T("Client"));
	m_cb_data_category.InsertString(5, _T("Facility"));
	m_cb_data_category.SetCurSel(0);

	m_cb_data_image.InsertString(0, _T("Bitmap"));
	m_cb_data_image.InsertString(1, _T("Png"));
	m_cb_data_image.InsertString(2, _T("Jpeg"));
	m_cb_data_image.InsertString(3, _T("Tiff"));
	m_cb_data_image.SetCurSel(0);

	GetDlgItem(IDC_DATA_EDIT_PATH)->SetWindowText( _T("C:\\"));

	switch(m_eSdkKind)
	{
	case NZ_SDK_VMS:
		{
			m_cb_model.EnableWindow(FALSE);
			GetDlgItem(IDC_NRS_EDIT_HTTP_PORT)->SetWindowText(_T("8001"));
			GetDlgItem(IDC_NRS_EDIT_RTSP_PORT)->EnableWindow(FALSE);
			CString strDeviceID = _T("DeviceID");
			GetDlgItem(IDC_VIDEO_TXT_CHANNEL)->SetWindowText(strDeviceID);
			GetDlgItem(IDC_AUDIO_TXT_CHANNEL)->SetWindowText(strDeviceID);
			GetDlgItem(IDC_PTZ_TXT_CHANNEL)->SetWindowText(strDeviceID);
			GetDlgItem(IDC_DATA_TXT_CHANNEL)->SetWindowText(strDeviceID);
			GetDlgItem(IDC_EVENT_TXT_CHANNEL)->SetWindowText(strDeviceID);
			GetDlgItem(IDC_TALK_TXT_CHANNEL)->SetWindowText(strDeviceID);
			GetDlgItem(IDC_PB_VIDEO_TXT_CHANNEL)->SetWindowText(strDeviceID);
		}
		break;
	}

	return TRUE;  // return TRUE unless you set the focus to a control
	// 예외: OCX 속성 페이지는 FALSE를 반환해야 합니다.
}

void CDlgLiveSample::OnDestroy()
{
	OnBnClickedNrsBtnDisconnect();
	CDialog::OnDestroy();
}

BOOL CDlgLiveSample::OnCapture( )
{
	NZ_STREAM stream = { (NZ_STREAM_TYPE)0, };
	BOOL bResult = FALSE;

	while( !m_stop_capture )
	{
		EnterCriticalSection(&m_csCaptureStreams);
		std::vector<STREAM_INFO> vStreams = m_vCaptureStreams;
		LeaveCriticalSection(&m_csCaptureStreams);

		std::vector<STREAM_INFO>::iterator pos = vStreams.begin();
		for (; pos != vStreams.end(); pos++)
		{
			if (m_eSdkKind == NZ_SDK_VMS)
				bResult = m_sdk.Command(NZ_CMD_GET_STREAM, (DWORD_PTR)pos->nNrsID, (DWORD_PTR)pos->nSessionType, (DWORD_PTR)&stream);
			else
				bResult = m_sdk.Command(NZ_CMD_GET_STREAM, (DWORD_PTR)&stream);

			if( bResult )
			{
				// TODO:
				// ...
				// Do anything with the video, audio or event stream if needed.
				// ...
				if( stream.type == NZ_STREAM_TYPE_EVENT )
					TRACE( _T("stream_type: %d, channel:%d, stream_no:%d\n"), stream.type, stream.channel, stream.stream_no );
				else if( stream.type == NZ_STREAM_TYPE_CAMERA_DISCONNECTED )
					TRACE( _T("%d Channel, %d Stream Camera Disconnected.\n"), stream.channel, stream.stream_no );
				else if( stream.type == NZ_STREAM_TYPE_VIDEO )
				{
					TRACE( _T("%04d%02d%02d%02d%02d%02d.%03d %d Channel, %d Stream, %d.\n"), 
						stream.time.wYear, stream.time.wMonth, stream.time.wDay, stream.time.wHour, stream.time.wMinute, stream.time.wSecond, stream.time.wMilliseconds,
						stream.channel, stream.stream_no, stream.DATA.video.codec );
				}
				m_sdk.Command( NZ_CMD_RELEASE_STREAM, (DWORD_PTR)&stream );
			}
		}

		Sleep( 1 );
	}
	return TRUE;
}

void CDlgLiveSample::OnBnClickedNrsBtnConnect()
{
	NZ_MODEL model = ( NZ_MODEL )( m_cb_model.GetCurSel()+1 );

	m_sdk.SetSdkKind(m_eSdkKind);
	switch(m_eSdkKind)
	{
	case NZ_SDK_NRS:
		{
			m_sdk.SetNrsSessionType(NZ_SESSION_TYPE_LIVE);
			m_sdk.SetNrsModel(model);
		}
		break;
	}

	if( !m_sdk.Open(_T(".")) )
		return;


	CMyString addr( GetDlgItem(IDC_NRS_EDIT_ADDRESS) );
	CMyString http_port( GetDlgItem(IDC_NRS_EDIT_HTTP_PORT) );
	CMyString rtsp_port( GetDlgItem(IDC_NRS_EDIT_RTSP_PORT) );
	CMyString id( GetDlgItem(IDC_NRS_EDIT_ID) );
	CMyString pw( GetDlgItem(IDC_NRS_EDIT_PASSWORD) );

	if( !m_sdk.Command(NZ_CMD_CONNECT, 
		(DWORD_PTR)(LPCTSTR)addr, 
		(m_eSdkKind == NZ_SDK_NRS) ? (DWORD_PTR)(LPCTSTR)CMyString(_T("http=%s&rtsp=%s"), http_port, rtsp_port) : (DWORD_PTR)_tstoi(http_port), 
		(DWORD_PTR)(LPCTSTR)id, 
		(DWORD_PTR)(LPCTSTR)pw) )
	{
		CString strMessage;
		switch(m_eSdkKind)
		{
		case NZ_SDK_VMS:
			strMessage.Format(_T("Failed to connect.(%u)"), m_sdk.GetLastError());
			break;
		default:
			strMessage = _T("Failed to connect.");
			break;
		}
		AfxMessageBox( strMessage );
		m_stop_capture = TRUE;
		m_sdk.Close( );
	}
	else
	{
			// If you need to handle video, audio or event stream, create the below capture thread.
		m_stop_capture = FALSE;
		m_capture_thread = (HANDLE)_beginthreadex( NULL, 0, &g_on_capture, this, 0, &m_id_capture );
		m_cb_model.EnableWindow( FALSE );
		GetDlgItem( IDC_NRS_BTN_DISCONNECT )->EnableWindow( TRUE );
		GetDlgItem( IDC_NRS_BTN_CONNECT )->EnableWindow( FALSE );
		EnableVideo( TRUE );
		EnablePTZ( TRUE );


		EnableData( m_eSdkKind == NZ_SDK_VMS );

		if( model == NZ_MODEL_RHINO )
		{
			EnableTalk( TRUE );
			EnableBackup( TRUE );
		}

		if( model == NZ_MODEL_LEOPARD )
		{
			EnableEvent( TRUE );
			EnableAudio( TRUE );
			EnableTalk( TRUE );
			EnableBackup( TRUE );
		}
	}
}

void CDlgLiveSample::OnBnClickedNrsBtnDisconnect()
{
	if (!m_stop_capture)
	{
		m_stop_capture = TRUE;
		WaitForSingleObject(m_capture_thread, INFINITE);
	}
	m_sdk.Command( NZ_CMD_DISCONNECT );
	GetDlgItem( IDC_NRS_BTN_DISCONNECT )->EnableWindow( FALSE );
	GetDlgItem( IDC_NRS_BTN_CONNECT )->EnableWindow( TRUE );
	EnableVideo( FALSE );
	EnableAudio( FALSE );
	EnableEvent( FALSE );
	EnableTalk( FALSE );
	EnableBackup( FALSE );
	EnablePTZ( FALSE );
	EnableData( FALSE );
	if (m_eSdkKind == NZ_SDK_NRS)
		m_cb_model.EnableWindow( TRUE );
	Sleep( 100 );
	m_sdk.Close( );
}

NZ_VMS_DATA_TYPE CDlgLiveSample::GetDataCategory()
{
	return (NZ_VMS_DATA_TYPE)(m_cb_data_category.GetCurSel() + 1);
}

CString CDlgLiveSample::GetDataCategoryName()
{
	switch(GetDataCategory())
	{
	case NZ_DATA_TYPE_CAMERA:
		return _T("Camera");
	case NZ_DATA_TYPE_NRS:
		return _T("Nrs");
	case NZ_DATA_TYPE_RECORD_SCHEDULE:
		return _T("RecordSchedule");
	case NZ_DATA_TYPE_USER:
		return _T("User");
	case NZ_DATA_TYPE_CLIENT:
		return _T("Client");
	case NZ_DATA_TYPE_FACILITY:
		return _T("Facility");
	default:
		return _T("");
	}
}

void CDlgLiveSample::OnBnClickedGetDatas()
{
	LPSTR pBuffer = NULL;
	int nBufferSize = 0;
	if (!m_sdk.Command(NZ_CMD_GET_DATAS, GetDataCategory(), (DWORD_PTR)&pBuffer, (DWORD_PTR)&nBufferSize))
		return;

	do 
	{
		TCHAR tszPath[MAX_PATH] = {0};
		GetModuleFileName(NULL, tszPath, MAX_PATH);
		PathRemoveFileSpec(tszPath);
		CString strFilePath;
		strFilePath.Format(_T("%s\\%s.xml"), tszPath, GetDataCategoryName());

		HANDLE hFile = CreateFile(strFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		if (hFile == INVALID_HANDLE_VALUE)
			break;

		DWORD dwWritten = 0;
		if (!WriteFile(hFile, pBuffer, (DWORD)nBufferSize, &dwWritten, NULL))
		{
			CloseHandle(hFile);
			break;
		}

		FlushFileBuffers(hFile);
		CloseHandle(hFile);

		ShellExecute(GetSafeHwnd(), _T("open"), _T("notepad.exe"), strFilePath, NULL, SW_SHOW);

	} while(FALSE);

	m_sdk.ReleaseData(pBuffer);
}

void CDlgLiveSample::OnBnClickedVideoBtnOpen()
{
	CMyString channel( GetDlgItem(IDC_VIDEO_EDIT_CHANNEL) );
	int nNrsID = GetNrsIDByDeviceID(_tstoi(channel));
	STREAM_INFO stStream(NZ_SESSION_TYPE_LIVE, nNrsID, _tstoi(channel), _tstoi(stream_no));
	
	EnterCriticalSection(&m_csCaptureStreams);

	if (std::find(m_vCaptureStreams.begin(), m_vCaptureStreams.end(), stStream) != m_vCaptureStreams.end())
	{
		LeaveCriticalSection(&m_csCaptureStreams);
		TRACE(_T("Already stream opened.\r\n"));
		return;
	}

	LeaveCriticalSection(&m_csCaptureStreams);

	CDlgScreen *screen = NULL;
	if( ((CButton*)GetDlgItem(IDC_VIDEO_CHECK_AUTO_PLAY))->GetCheck() == BST_CHECKED )
	{
		screen = new CDlgScreen( );
		screen->m_sdk = &m_sdk;
		screen->m_nSessionType = stStream.nSessionType;
		screen->m_nNrsID = nNrsID;
		screen->m_channel = stStream.nDeviceKey;
		screen->m_stream_no = stStream.nStreamNo;
		screen->Create( IDD_SCREEN, this );
	}


	BOOL bNeedDecodingData = FALSE;
	if( !m_sdk.Command(NZ_CMD_OPEN_VIDEO, stStream.nDeviceKey, stStream.nStreamNo, screen ? TRUE : FALSE, screen ? (DWORD_PTR)screen->GetSafeHwnd() : (bNeedDecodingData ? 0 : 1)) )
	{
		delete screen;
		return;
	}

	if( screen )
	{
		screen->ShowWindow( SW_SHOW );
		m_mapScreens[stStream] = SHARED_PTR<CDlgScreen>(screen);

		m_sdk.Command( NZ_CMD_VIEW_RESIZE, stStream.nDeviceKey, stStream.nStreamNo );
		m_sdk.Command( NZ_CMD_VIEW_SHOW_SELECTION, stStream.nDeviceKey, stStream.nStreamNo, 0 );

		//POINT pt[5] = { {30,30}, {100,30}, {200, 50}, {30,200}, {30,30} };
		//CMyString str_arg4( "index=1&pt_count=5&image_width=1920&image_height=1080" );
		//m_sdk.Command( NZ_CMD_VIEW_SHOW_ZONE, stStream.nDeviceKey, stStream.nStreamNo, (DWORD_PTR)pt, (DWORD_PTR)(LPCTSTR)str_arg4 );

		//POINT pt2[5] = { {130,130}, {200,130}, {300, 150}, {130,300}, {130,130} };
		//str_arg4.Format( "index=2&pt_count=5&image_width=1920&image_height=1080" );
		//m_sdk.Command( NZ_CMD_VIEW_SHOW_ZONE, stStream.nDeviceKey, stStream.nStreamNo, (DWORD_PTR)pt2, (DWORD_PTR)(LPCTSTR)str_arg4 );

		//RECT rc_detect = { 100,100,400,200 };
		//str_arg4.Format( "show=1&image_width=1920&image_height=1080" );
		//m_sdk.Command( NZ_CMD_VIEW_SHOW_DETECT, stStream.nDeviceKey, stStream.nStreamNo, (DWORD_PTR)&rc_detect, (DWORD_PTR)(LPCTSTR)str_arg4 );

		CString strTitle;
		strTitle.Format(_T("Live Device : %d"), stStream.nDeviceKey);
		m_sdk.Command( NZ_CMD_VIEW_SHOW_NAME, stStream.nDeviceKey, stStream.nStreamNo, (DWORD_PTR)strTitle.GetBuffer(), (DWORD_PTR)20 );
	}

	EnterCriticalSection(&m_csCaptureStreams);

	m_vCaptureStreams.push_back(stStream);

	LeaveCriticalSection(&m_csCaptureStreams);
}

void CDlgLiveSample::OnBnClickedVideoBtnClose()
{
	CMyString channel( GetDlgItem(IDC_VIDEO_EDIT_CHANNEL) );
	int nNrsID = GetNrsIDByDeviceID(_tstoi(channel));
	STREAM_INFO stStream(NZ_SESSION_TYPE_LIVE, nNrsID, _tstoi(channel), _tstoi(stream_no));

	EnterCriticalSection(&m_csCaptureStreams);

	std::vector<STREAM_INFO>::iterator posStream = std::find(m_vCaptureStreams.begin(), m_vCaptureStreams.end(), stStream);
	if (posStream == m_vCaptureStreams.end())
	{
		LeaveCriticalSection(&m_csCaptureStreams);
		return;
	}

	m_vCaptureStreams.erase(posStream);
	LeaveCriticalSection(&m_csCaptureStreams);

	m_sdk.Command( NZ_CMD_CLOSE_VIDEO, stStream.nDeviceKey, stStream.nStreamNo );
	if (m_mapScreens.find(stStream) != m_mapScreens.end())
	{
		m_mapScreens[stStream]->PostMessage(WM_CLOSE);
		m_mapScreens.erase(stStream);
	}
}

void CDlgLiveSample::OnClose()
{
	m_stop_capture = TRUE;
	std::map<STREAM_INFO, SHARED_PTR<CDlgScreen>>::iterator posScreen = m_mapScreens.begin();
	for (; posScreen != m_mapScreens.end(); posScreen++)
	{
		if (posScreen->first.nSessionType == NZ_SESSION_TYPE_LIVE)
			m_sdk.Command( NZ_CMD_CLOSE_VIDEO, posScreen->first.nDeviceKey, posScreen->first.nStreamNo );
		else
			m_sdk.Command( NZ_CMD_PB_CLOSE_VIDEO, posScreen->first.nDeviceKey, (DWORD_PTR)"Playback" );
	}

	m_mapScreens.clear();

	m_sdk.Command( NZ_CMD_DISCONNECT );
	Sleep( 100 );
	m_sdk.Close( );

	CDialog::OnClose();
}

LRESULT CDlgLiveSample::OnScreenClosed(WPARAM wParam, LPARAM lParam)
{
	CDlgScreen* pScreen = reinterpret_cast<CDlgScreen*>(wParam);
	STREAM_INFO stStream(pScreen->m_nSessionType, pScreen->m_nNrsID, pScreen->m_channel, pScreen->m_stream_no);

	EnterCriticalSection(&m_csCaptureStreams);

	std::vector<STREAM_INFO>::iterator posStream = std::find(m_vCaptureStreams.begin(), m_vCaptureStreams.end(), stStream);
	if (posStream == m_vCaptureStreams.end())
	{
		LeaveCriticalSection(&m_csCaptureStreams);
		return 0;
	}

	m_vCaptureStreams.erase(posStream);

	LeaveCriticalSection(&m_csCaptureStreams);

	if (pScreen->m_nSessionType == NZ_SESSION_TYPE_LIVE)
		m_sdk.Command( NZ_CMD_CLOSE_VIDEO, stStream.nDeviceKey, stStream.nStreamNo );
	else
		m_sdk.Command( NZ_CMD_PB_CLOSE_VIDEO, stStream.nDeviceKey, (DWORD_PTR)"Playback" );


	if (m_mapScreens.find(stStream) != m_mapScreens.end())
		m_mapScreens.erase(stStream);

	return 0;
}

void CDlgLiveSample::EnableVideo( BOOL enable )
{
	GetDlgItem( IDC_VIDEO_GRP )->EnableWindow( enable );
	GetDlgItem( IDC_VIDEO_TXT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_VIDEO_EDIT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_VIDEO_BTN_OPEN )->EnableWindow( enable );
	GetDlgItem( IDC_VIDEO_BTN_CLOSE )->EnableWindow( enable );
	GetDlgItem( IDC_VIDEO_CHECK_AUTO_PLAY )->EnableWindow( enable );
}

void CDlgLiveSample::EnableAudio( BOOL enable )
{
	GetDlgItem( IDC_AUDIO_GRP )->EnableWindow( enable );
	GetDlgItem( IDC_AUDIO_TXT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_AUDIO_EDIT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_AUDIO_BTN_OPEN )->EnableWindow( enable );
	GetDlgItem( IDC_AUDIO_BTN_CLOSE )->EnableWindow( enable );
	//GetDlgItem( IDC_AUDIO_CHECK_AUTO_PLAY )->EnableWindow( enable );
	( (CButton*)GetDlgItem(IDC_AUDIO_CHECK_AUTO_PLAY) )->SetCheck( BST_CHECKED );
	GetDlgItem( IDC_AUDIO_CHECK_AUTO_PLAY )->EnableWindow( FALSE );
}

void CDlgLiveSample::EnableEvent( BOOL enable )
{
	GetDlgItem( IDC_EVENT_GRP )->EnableWindow( enable );
	GetDlgItem( IDC_EVENT_TXT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_EVENT_EDIT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_EVENT_BTN_OPEN )->EnableWindow( enable );
	GetDlgItem( IDC_EVENT_BTN_CLOSE )->EnableWindow( enable );
}

void CDlgLiveSample::EnableTalk( BOOL enable )
{
	GetDlgItem( IDC_TALK_GRP )->EnableWindow( enable );
	GetDlgItem( IDC_TALK_TXT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_TALK_EDIT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_TALK_BTN_START )->EnableWindow( enable );
	GetDlgItem( IDC_TALK_BTN_STOP )->EnableWindow( enable );
	//GetDlgItem( IDC_TALK_BTN_LOAD_WAVE_PATH )->EnableWindow( enable );
	//GetDlgItem( IDC_TALK_EDIT_WAVE_PATH )->EnableWindow( enable );
	//GetDlgItem( IDC_TALK_BTN_SEND_WAVE )->EnableWindow( enable );
}

void CDlgLiveSample::EnableBackup( BOOL enable )
{
	GetDlgItem( IDC_BACKUP_GRP )->EnableWindow( enable );
	GetDlgItem( IDC_PB_VIDEO_TXT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_PB_VIDEO_EDIT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_PB_VIDEO_BTN_OPEN )->EnableWindow( enable );
	GetDlgItem( IDC_PB_VIDEO_BTN_CLOSE )->EnableWindow( enable );
	GetDlgItem( IDC_PB_VIDEO_CHECK_AUTO_PLAY )->EnableWindow( enable );
	GetDlgItem( IDC_PB_DATETIMEPICKER1 )->EnableWindow( enable );
	GetDlgItem( IDC_PB_PLAY )->EnableWindow( enable );
	GetDlgItem( IDC_PB_PAUSE )->EnableWindow( enable );
}

void CDlgLiveSample::EnableData( BOOL enable )
{
	GetDlgItem(IDC_DATA_GRP)->EnableWindow(enable);
	GetDlgItem(IDC_DATA_TXT_CATEGORY)->EnableWindow(enable);
	GetDlgItem(IDC_COMBO_DATA_CATEGORY)->EnableWindow(enable);
	GetDlgItem(IDC_BUTTON_GET_DATAS)->EnableWindow(enable);

	GetDlgItem(IDC_DATA_TXT_CHANNEL)->EnableWindow(enable);
	GetDlgItem(IDC_DATA_EDIT_CHANNEL)->EnableWindow(enable);
	GetDlgItem(IDC_DATA_TXT_RANGE)->EnableWindow(enable);
	GetDlgItem(IDC_DATA_FROM_DATE)->EnableWindow(enable);
	GetDlgItem(IDC_DATA_FROM_TIME)->EnableWindow(enable);
	GetDlgItem(IDC_DATA_TO_DATE)->EnableWindow(enable);
	GetDlgItem(IDC_DATA_TO_TIME)->EnableWindow(enable);

	GetDlgItem(IDC_DATA_TXT_PATH)->EnableWindow(enable);
	GetDlgItem(IDC_DATA_EDIT_PATH)->EnableWindow(enable);

	GetDlgItem(IDC_BUTTON_EXPORT_VIDEO)->EnableWindow(enable);
	GetDlgItem(IDC_BUTTON_CANCEL_EXPORT)->EnableWindow(enable);
	GetDlgItem(IDC_BUTTON_EXPORT_IMAGE)->EnableWindow(enable);
	GetDlgItem(IDC_DATA_TXT_IMAGE_FORMAT)->EnableWindow(enable);
	GetDlgItem(IDC_COMBO_DATA_IMAGE)->EnableWindow(enable);
}

void CDlgLiveSample::EnablePTZ( BOOL enable )
{
	GetDlgItem( IDC_PTZ_GRP )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_TXT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_EDIT_CHANNEL )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_GRP_PTZ )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_LEFT )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_RIGHT )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_UP )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_DOWN )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_LU )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_LD )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_RU )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_RD )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_TELE )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_BTN_WIDE )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_TXT_SPEED )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_CB_SPEED )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_GRP_PRESET )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_TXT_CHANNEL2 )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_EDIT_PRESET )->EnableWindow( enable );
	GetDlgItem( IDC_PRESET_BTN_SET )->EnableWindow( enable );
	GetDlgItem( IDC_PRESET_BTN_MOVE )->EnableWindow( enable );

	if( !enable || ((NZ_MODEL)(m_cb_model.GetCurSel()+1) == NZ_MODEL_LEOPARD) )
	{
		GetDlgItem( IDC_PTZ_GRP_TOUR )->EnableWindow( enable );
		GetDlgItem( IDC_BTN_TOUR_START )->EnableWindow( enable );
		GetDlgItem( IDC_BTN_TOUR_STOP )->EnableWindow( enable );
	}

	GetDlgItem( IDC_PTZ_GET_SPECIFICATION )->EnableWindow( enable );
	GetDlgItem( IDC_EDIT_PTZ_POSITION_SPECIFICATION )->EnableWindow( enable );
	GetDlgItem( IDC_STATIC_PTZ_PAN_POSITION )->EnableWindow( enable );
	GetDlgItem( IDC_STATIC_PTZ_TILT_POSITION )->EnableWindow( enable );
	GetDlgItem( IDC_STATIC_PTZ_ZOOM_POSITION )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_GET_POSITION )->EnableWindow( enable );
	GetDlgItem( IDC_EDIT_PTZ_PAN_RPOSITION )->EnableWindow( enable );
	GetDlgItem( IDC_EDIT_PTZ_TILT_RPOSITION )->EnableWindow( enable );
	GetDlgItem( IDC_EDIT_PTZ_ZOOM_RPOSITION )->EnableWindow( enable );
	GetDlgItem( IDC_PTZ_SET_POSITION )->EnableWindow( enable );
	GetDlgItem( IDC_EDIT_PTZ_PAN_WPOSITION )->EnableWindow( enable );
	GetDlgItem( IDC_EDIT_PTZ_TILT_WPOSITION )->EnableWindow( enable );
	GetDlgItem( IDC_EDIT_PTZ_ZOOM_WPOSITION )->EnableWindow( enable );
}

void CDlgLiveSample::OnBnClickedPresetBtnSet()
{
	CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
	CMyString preset( GetDlgItem(IDC_PTZ_EDIT_PRESET) );
	m_sdk.Command( NZ_CMD_PTZ_PRESET_SET, _tstoi(channel), 1, _tstoi(preset) );
}

void CDlgLiveSample::OnBnClickedPresetBtnMove()
{
	CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
	CMyString preset( GetDlgItem(IDC_PTZ_EDIT_PRESET) );
	m_sdk.Command( NZ_CMD_PTZ_PRESET_MOVE, _tstoi(channel), 1, _tstoi(preset) );
}

BOOL CDlgLiveSample::PreTranslateMessage(MSG* pMsg)
{
	if( pMsg->message == WM_LBUTTONDOWN )
	{
		for( int i=0; i<8; i++ )
		{
			CRect rc;
			GetDlgItem( IDC_PTZ_BTN_LEFT+i )->GetWindowRect( &rc );
			if( rc.PtInRect(pMsg->pt) )
			{
				CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
				m_sdk.Command( (NZ_CMD)(NZ_CMD_PTZ_MOVE_LEFT+i), _tstoi(channel), 1, m_cb_ptz_speed.GetCurSel()+1, 0 );
				return CDialog::PreTranslateMessage(pMsg);
			}
		}
		for( int i=0; i<2; i++ )
		{
			CRect rc;
			GetDlgItem( IDC_PTZ_BTN_TELE+i )->GetWindowRect( &rc );
			if( rc.PtInRect(pMsg->pt) )
			{
				CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
				m_sdk.Command( (NZ_CMD)(NZ_CMD_PTZ_ZOOM_TELE+i), _tstoi(channel), 1, m_cb_ptz_speed.GetCurSel()+1, 0 );
				return CDialog::PreTranslateMessage(pMsg);
			}
		}
	}
	if( pMsg->message == WM_LBUTTONUP )
	{
		for( int i=0; i<8; i++ )
		{
			CRect rc;
			GetDlgItem( IDC_PTZ_BTN_LEFT+i )->GetWindowRect( &rc );
			if( rc.PtInRect(pMsg->pt) )
			{
				CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
				m_sdk.Command( (NZ_CMD)(NZ_CMD_PTZ_MOVE_LEFT+i), _tstoi(channel), 1, 0, 1 );
				return CDialog::PreTranslateMessage(pMsg);
			}
		}
		for( int i=0; i<2; i++ )
		{
			CRect rc;
			GetDlgItem( IDC_PTZ_BTN_TELE+i )->GetWindowRect( &rc );
			if( rc.PtInRect(pMsg->pt) )
			{
				CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
				m_sdk.Command( (NZ_CMD)(NZ_CMD_PTZ_ZOOM_TELE+i), _tstoi(channel), 1, 0, 1 );
				return CDialog::PreTranslateMessage(pMsg);
			}
		}
	}
	return CDialog::PreTranslateMessage(pMsg);
}

void CDlgLiveSample::OnBnClickedAudioBtnOpen()
{
	CMyString channel( GetDlgItem(IDC_AUDIO_EDIT_CHANNEL) );
	BOOL auto_play = ( (CButton*)GetDlgItem(IDC_AUDIO_CHECK_AUTO_PLAY) )->GetCheck( ) == BST_CHECKED;
	if( !m_sdk.Command(NZ_CMD_OPEN_AUDIO, _tstoi(channel), _tstoi(stream_no), auto_play) )
		AfxMessageBox( _T("Open Audio failed.") );
}

void CDlgLiveSample::OnBnClickedAudioBtnClose()
{
	CMyString channel( GetDlgItem(IDC_AUDIO_EDIT_CHANNEL) );
	m_sdk.Command( NZ_CMD_CLOSE_AUDIO, _tstoi(channel), _tstoi(stream_no) );
}

void CDlgLiveSample::OnBnClickedEventBtnOpen()
{
	CMyString channel_list( GetDlgItem(IDC_EVENT_EDIT_CHANNEL) );
	m_sdk.Command( NZ_CMD_OPEN_EVENT, (DWORD_PTR)(LPCTSTR)channel_list );
	GetDlgItem( IDC_EVENT_EDIT_CHANNEL )->EnableWindow( FALSE );
	GetDlgItem( IDC_EVENT_BTN_OPEN )->EnableWindow( FALSE );
}

void CDlgLiveSample::OnBnClickedEventBtnClose()
{
	m_sdk.Command( NZ_CMD_CLOSE_EVENT );
	GetDlgItem( IDC_EVENT_EDIT_CHANNEL )->EnableWindow( TRUE );
	GetDlgItem( IDC_EVENT_BTN_OPEN )->EnableWindow( TRUE );
}

void CDlgLiveSample::OnCbnSelchangeCbModel()
{
	NZ_MODEL model = ( NZ_MODEL )( m_cb_model.GetCurSel()+1 );

	switch( model )
	{
	case NZ_MODEL_RHINO:
		GetDlgItem( IDC_NRS_EDIT_ADDRESS )->SetWindowText( _T("naiz.re.kr") );
		GetDlgItem( IDC_NRS_EDIT_HTTP_PORT )->SetWindowText( _T("10000") );
		GetDlgItem( IDC_NRS_EDIT_RTSP_PORT )->SetWindowText( _T("1554") );
		GetDlgItem( IDC_NRS_EDIT_ID )->SetWindowText( _T("Admin") );
		GetDlgItem( IDC_NRS_EDIT_PASSWORD )->SetWindowText( _T("") );
		break;
	case NZ_MODEL_LEOPARD:
		GetDlgItem( IDC_NRS_EDIT_ADDRESS )->SetWindowText( _T("naiz.re.kr") );
		GetDlgItem( IDC_NRS_EDIT_HTTP_PORT )->SetWindowText( _T("8002") );
		GetDlgItem( IDC_NRS_EDIT_RTSP_PORT )->SetWindowText( _T("8002") );
		GetDlgItem( IDC_NRS_EDIT_ID )->SetWindowText( _T("admin") );
		GetDlgItem( IDC_NRS_EDIT_PASSWORD )->SetWindowText( _T("admin") );
		break;
	}
}

void CDlgLiveSample::OnBnClickedBtnTourStart()
{
	CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
	m_sdk.Command( NZ_CMD_PTZ_TOUR_START, _tstoi(channel), _tstoi(stream_no) );
}

void CDlgLiveSample::OnBnClickedBtnTourStop()
{
	CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
	m_sdk.Command( NZ_CMD_PTZ_TOUR_STOP, _tstoi(channel), _tstoi(stream_no) );
}

void CDlgLiveSample::OnBnClickedGetPtzSpecification()
{
	NZ_PTZ_POSITION_SPECIFICATION stSpecification;
	CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
	if (!m_sdk.Command( NZ_CMD_GET_PTZ_POSITION_SPECIFICATION, _tstoi(channel), _tstoi(stream_no), (DWORD_PTR)&stSpecification))
		return;
	CString strTemp;
	strTemp.Format(_T("SupportPanTilt=%d, SupportZoom=%d, Pan=%.9g~%.9g, Tilt=%.9g~%.9g, Zoom=%.9g~%.9g"), 
		stSpecification.bSupportPanTiltPosition,
		stSpecification.bSupportZoomPosition,
		stSpecification.dMinPanPosition, stSpecification.dMaxPanPosition,
		stSpecification.dMinTiltPosition, stSpecification.dMaxTiltPosition,
		stSpecification.dMinZoomPosition, stSpecification.dMaxZoomPosition);
	GetDlgItem(IDC_EDIT_PTZ_POSITION_SPECIFICATION)->SetWindowText(strTemp);
}

void CDlgLiveSample::OnBnClickedGetPtzPosition()
{
	NZ_PTZ_POSITION stPosition;
	CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
	if (!m_sdk.Command( NZ_CMD_GET_PTZ_POSITION, _tstoi(channel), _tstoi(stream_no), (DWORD_PTR)&stPosition))
		return;
	GetDlgItem(IDC_EDIT_PTZ_PAN_RPOSITION)->SetWindowText(CMyString(_T("%.9g"), stPosition.dPanPosition));
	GetDlgItem(IDC_EDIT_PTZ_TILT_RPOSITION)->SetWindowText(CMyString(_T("%.9g"), stPosition.dTiltPosition));
	GetDlgItem(IDC_EDIT_PTZ_ZOOM_RPOSITION)->SetWindowText(CMyString(_T("%.9g"), stPosition.dZoomPosition));
}

void CDlgLiveSample::OnBnClickedSetPtzPosition()
{
	NZ_PTZ_POSITION stPosition;
	CMyString channel( GetDlgItem(IDC_PTZ_EDIT_CHANNEL) );
	CString strTemp;
	GetDlgItem(IDC_EDIT_PTZ_PAN_WPOSITION)->GetWindowText(strTemp);
	stPosition.dPanPosition = _tstof(strTemp);
	GetDlgItem(IDC_EDIT_PTZ_TILT_WPOSITION)->GetWindowText(strTemp);
	stPosition.dTiltPosition = _tstof(strTemp);
	GetDlgItem(IDC_EDIT_PTZ_ZOOM_WPOSITION)->GetWindowText(strTemp);
	stPosition.dZoomPosition = _tstof(strTemp);
	m_sdk.Command( NZ_CMD_SET_PTZ_POSITION, _tstoi(channel), _tstoi(stream_no), (DWORD_PTR)&stPosition);
}

void CDlgLiveSample::OnBnClickedTalkBtnStart()
{
	CMyString channel( GetDlgItem(IDC_TALK_EDIT_CHANNEL) );
	if( !m_sdk.Command(NZ_CMD_START_TALK, _tstoi(channel), _tstoi(stream_no)) )
	{
		AfxMessageBox( _T("Failed to start talk.") );
		return;
	}
	GetDlgItem( IDC_TALK_EDIT_CHANNEL )->EnableWindow( FALSE );
	GetDlgItem( IDC_TALK_BTN_START )->EnableWindow( FALSE );
}

void CDlgLiveSample::OnBnClickedTalkBtnStop()
{
	CMyString channel( GetDlgItem(IDC_TALK_EDIT_CHANNEL) );
	m_sdk.Command( NZ_CMD_STOP_TALK, _tstoi(channel), _tstoi(stream_no) );
	GetDlgItem( IDC_TALK_EDIT_CHANNEL )->EnableWindow( TRUE );
	GetDlgItem( IDC_TALK_BTN_START )->EnableWindow( TRUE );
}

void CDlgLiveSample::OnBnClickedPbVideoBtnOpen()
{
	CMyString channel( GetDlgItem(IDC_PB_VIDEO_EDIT_CHANNEL) );
	int nNrsID = GetNrsIDByDeviceID(_tstoi(channel));
	STREAM_INFO stStream(NZ_SESSION_TYPE_PB, nNrsID, _tstoi(channel), 0);

	EnterCriticalSection(&m_csCaptureStreams);

	if (std::find(m_vCaptureStreams.begin(), m_vCaptureStreams.end(), stStream) != m_vCaptureStreams.end())
	{
		LeaveCriticalSection(&m_csCaptureStreams);
		TRACE(_T("Already stream opened.\r\n"));
		return;
	}

	LeaveCriticalSection(&m_csCaptureStreams);

	CDlgScreen *screen = NULL;
	if( ((CButton*)GetDlgItem(IDC_PB_VIDEO_CHECK_AUTO_PLAY))->GetCheck() == BST_CHECKED )
	{
		screen = new CDlgScreen( );
		screen->m_sdk = &m_sdk;
		screen->m_channel = stStream.nDeviceKey;
		screen->m_stream_no = stStream.nStreamNo;
		screen->m_pb = TRUE;
		screen->Create( IDD_SCREEN, this );
	}


	BOOL bNeedDecodingData = FALSE;
	if( !m_sdk.Command(NZ_CMD_PB_OPEN_VIDEO, stStream.nDeviceKey, stStream.nStreamNo, screen ? TRUE : FALSE, screen ? (DWORD_PTR)screen->GetSafeHwnd() : (bNeedDecodingData ? 0 : 1), (DWORD_PTR)"Playback") )
	{
		delete screen;
		return;
	}


	if( screen )
	{
		screen->ShowWindow( SW_SHOW );
		m_mapScreens[stStream] = SHARED_PTR<CDlgScreen>(screen);

		m_sdk.Command( NZ_CMD_VIEW_RESIZE, stStream.nDeviceKey, stStream.nStreamNo, (DWORD_PTR)"Playback" );
		m_sdk.Command( NZ_CMD_VIEW_SHOW_SELECTION, stStream.nDeviceKey, _tstoi(stream_no), stStream.nStreamNo, (DWORD_PTR)"Playback" );
	}

	EnterCriticalSection(&m_csCaptureStreams);

	m_vCaptureStreams.push_back(stStream);

	LeaveCriticalSection(&m_csCaptureStreams);
}


void CDlgLiveSample::OnBnClickedPbVideoBtnClose()
{
	CMyString channel( GetDlgItem(IDC_PB_VIDEO_EDIT_CHANNEL) );
	int nNrsID = GetNrsIDByDeviceID(_tstoi(channel));
	STREAM_INFO stStream(NZ_SESSION_TYPE_PB, nNrsID, _tstoi(channel), 0);

	EnterCriticalSection(&m_csCaptureStreams);

	std::vector<STREAM_INFO>::iterator posStream = std::find(m_vCaptureStreams.begin(), m_vCaptureStreams.end(), stStream);
	if (posStream == m_vCaptureStreams.end())
	{
		LeaveCriticalSection(&m_csCaptureStreams);
		return;
	}

	m_vCaptureStreams.erase(posStream);
	LeaveCriticalSection(&m_csCaptureStreams);

	m_sdk.Command( NZ_CMD_PB_CLOSE_VIDEO, stStream.nDeviceKey, (DWORD_PTR)"Playback" );
	if (m_mapScreens.find(stStream) != m_mapScreens.end())
	{
		m_mapScreens[stStream]->PostMessage(WM_CLOSE);
		m_mapScreens.erase(stStream);
	}
}

int CDlgLiveSample::GetNrsIDByDeviceID(int nDeviceID)
{
	if (m_eSdkKind != NZ_SDK_VMS)
		return 1;

	LPSTR pBuffer = NULL;
	int nBufferSize = 0;
	if (!m_sdk.Command( NZ_CMD_GET_DATA, (DWORD_PTR)NZ_DATA_TYPE_CAMERA, (DWORD_PTR)nDeviceID, (DWORD_PTR)&pBuffer, (DWORD_PTR)&nBufferSize ))
		return 0;

	int nNrsID = 0;
	MSXML2::IXMLDOMDocumentPtr pDoc;
	pDoc.CreateInstance(MSXML2::CLSID_DOMDocument);
	_bstr_t bstrXML(pBuffer);
	_variant_t vResult = pDoc->loadXML(bstrXML);
	if (vResult.boolVal)
	{
		_bstr_t node(_T("//nrs_no"));
		MSXML2::IXMLDOMNodePtr pNode = pDoc->selectSingleNode(node);
		if (pNode != NULL)
		{
			CString strTemp = pNode->Gettext();
			nNrsID = _tstoi(strTemp);
		}

		pDoc->documentElement.Release();
	}
	pDoc.Release();

	m_sdk.ReleaseData(pBuffer);
	return nNrsID;
}


void CDlgLiveSample::OnBnClickedPbPlay()
{
	SYSTEMTIME st = { 0, };
	m_dtp.GetTime( &st );
	CMyString arg( _T("refresh=1&speed=1&method=forward&date=%04d-%02d-%02d&time=%02d-%02d-%02d"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond );
	CMyString channel( GetDlgItem(IDC_PB_VIDEO_EDIT_CHANNEL) );
	m_sdk.Command( NZ_CMD_PB_PLAY, _tstoi(channel), 0, (DWORD_PTR)(LPCTSTR)arg, (DWORD_PTR)"Playback" );
	//m_sdk.Command( NZ_CMD_VIEW_RESIZE, _tstoi(channel), 0 );
}

void CDlgLiveSample::OnBnClickedPbPause()
{
	CMyString channel( GetDlgItem(IDC_PB_VIDEO_EDIT_CHANNEL) );
	m_sdk.Command( NZ_CMD_PB_PAUSE, _tstoi(channel), (DWORD_PTR)"Playback" );
}


void CDlgLiveSample::OnBnClickedExportVideo()
{
	CString strTemp;
	CString strOption = _T("<Export>\r\n");
	// 0 : Avi, 1 : Exe
	strOption += _T("\t<ExportKind>0</ExportKind>\r\n");
	CTime clsDate, clsTime;
	m_export_from_date.GetTime(clsDate);
	m_export_from_time.GetTime(clsTime);
	strTemp.Format(_T("\t<FromTime>%04d%02d%02d%02d%02d%02d</FromTime>\r\n"), clsDate.GetYear(), clsDate.GetMonth(), clsDate.GetDay(), clsTime.GetHour(), clsTime.GetMinute(), clsTime.GetSecond());
	strOption += strTemp;
	m_export_to_date.GetTime(clsDate);
	m_export_to_time.GetTime(clsTime);
	strTemp.Format(_T("\t<ToTime>%04d%02d%02d%02d%02d%02d</ToTime>\r\n"), clsDate.GetYear(), clsDate.GetMonth(), clsDate.GetDay(), clsTime.GetHour(), clsTime.GetMinute(), clsTime.GetSecond());
	strOption += strTemp;

	CString strPath;
	GetDlgItem(IDC_DATA_EDIT_PATH)->GetWindowText(strPath);
	strTemp.Format(_T("\t<Path>%s</Path>\r\n"), strPath);
	strOption += strTemp;
	//strOption += _T("\t<MaxSize>1073741824</MaxSize>\r\n");			// Limit Size (Byte)
	strOption += _T("\t<MaxSize>2104533975</MaxSize>\r\n");			// Limit Size (Byte)
	strOption += _T("\t<Timeout>60</Timeout>\r\n");
	CString strChannel;
	GetDlgItem(IDC_DATA_EDIT_CHANNEL)->GetWindowText(strChannel);
	strTemp.Format(_T("\t<Cameras><Camera><CameraID>%s</CameraID><FileName>Camera_%s</FileName></Camera></Cameras>\r\n"), strChannel, strChannel);
	strOption += strTemp;
	strOption += _T("</Export>\r\n");

	if (!m_sdk.Command(NZ_CMD_EXPORT_VIDEO, (DWORD_PTR)(LPCTSTR)strOption, (DWORD_PTR)OnExportMessage, (DWORD_PTR)this))
		TRACE(_T("ERROR - Error raised when export video. the error is %u\r\n"), m_sdk.GetLastError());
}

void CALLBACK CDlgLiveSample::OnExportMessage(NZ_EXPORT_MESSAGE eMessage, LONG_PTR pParam1, LONG_PTR pParam2, LONG_PTR pUserParam)
{
	CDlgLiveSample* pDlg = reinterpret_cast<CDlgLiveSample*>(pUserParam);
	switch(eMessage)
	{
	case NZ_EXPORT_MESSAGE_STARTED:
		TRACE(_T("INFO - Export started (%d)\r\n"), (int)pParam1);
		break;
	case NZ_EXPORT_MESSAGE_FINISHED:
		TRACE(_T("INFO - Export finished (%d, %d, %u)\r\n"), (int)pParam1, (int)pParam2, pDlg->m_sdk.GetLastError());
		break;
	case NZ_EXPORT_MESSAGE_UPDATED:
		TRACE(_T("INFO - Export updated (%d)\r\n"), (int)pParam1);
		break;
	}
}


void CDlgLiveSample::OnBnClickedCancelExport()
{
	m_sdk.Command(NZ_CMD_CANCEL_EXPORT_VIDEO);
}


void CDlgLiveSample::OnBnClickedExportImage()
{
	CString strTemp;
	CString strOption = _T("<Export>\r\n");
	CTime clsDate, clsTime;
	m_export_from_date.GetTime(clsDate);
	m_export_from_time.GetTime(clsTime);
	strTemp.Format(_T("\t<FromTime>%04d%02d%02d%02d%02d%02d</FromTime>\r\n"), clsDate.GetYear(), clsDate.GetMonth(), clsDate.GetDay(), clsTime.GetHour(), clsTime.GetMinute(), clsTime.GetSecond());
	strOption += strTemp;
	m_export_to_date.GetTime(clsDate);
	m_export_to_time.GetTime(clsTime);
	strTemp.Format(_T("\t<ToTime>%04d%02d%02d%02d%02d%02d</ToTime>\r\n"), clsDate.GetYear(), clsDate.GetMonth(), clsDate.GetDay(), clsTime.GetHour(), clsTime.GetMinute(), clsTime.GetSecond());
	strOption += strTemp;

	CString strPath;
	GetDlgItem(IDC_DATA_EDIT_PATH)->GetWindowText(strPath);
	strTemp.Format(_T("\t<Path>%s</Path>\r\n"), strPath);
	strOption += strTemp;
	strTemp.Format(_T("\t<ImageFormat>%s</ImageFormat>\r\n"), GetImageFormat());
	strOption += strTemp;
	CString strChannel;
	GetDlgItem(IDC_DATA_EDIT_CHANNEL)->GetWindowText(strChannel);
	strTemp.Format(_T("\t<Cameras><Camera><CameraID>%s</CameraID><FileName>%04d%02d%02d%02d%02d%02d</FileName></Camera></Cameras>\r\n"), strChannel, 
		clsDate.GetYear(), clsDate.GetMonth(), clsDate.GetDay(), clsTime.GetHour(), clsTime.GetMinute(), clsTime.GetSecond());
	strOption += strTemp;
	strOption += _T("</Export>\r\n");

	if (!m_sdk.Command(NZ_CMD_EXPORT_IMAGE, (DWORD_PTR)(LPCTSTR)strOption, (DWORD_PTR)OnExportMessage, (DWORD_PTR)this))
		TRACE(_T("ERROR - Error raised when export image. the error is %u\r\n"), m_sdk.GetLastError());
}

CString CDlgLiveSample::GetImageFormat()
{
	switch(m_cb_data_image.GetCurSel())
	{
	case 0:
		return _T("bmp");
	case 1:
		return _T("png");
	case 2:
		return _T("jpg");
	case 3:
		return _T("tif");
	}
	return _T("");
}