/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "ChannelDlg.h"
#include "VideoSize.h"
#include "CaptureDevicePool.h"
#include "ChannelPool.h"

#include <Mmsystem.h>
#include <dbt.h>


#include "assert.h"


#include <process.h> // threads.

#if defined _WIN32
    #define SLEEP_10_SEC ::Sleep(10000)
    #define GET_TIME_IN_MS timeGetTime
#endif

// Hack to convert char to TCHAR, using two buffers to be able to
// call twice in the same statement
TCHAR convertTemp1[256] = {0};
TCHAR convertTemp2[256] = {0};
bool convertBufferSwitch(false);
TCHAR* CharToTchar(const char* str, int len)
{
#ifdef _UNICODE
  TCHAR* temp = convertBufferSwitch ? convertTemp1 : convertTemp2;
  convertBufferSwitch = !convertBufferSwitch;
  memset(temp, 0, sizeof(convertTemp1));
  MultiByteToWideChar(CP_UTF8, 0, str, len, temp, 256);
  return temp;
#else
  return str;
#endif
}

// Hack to convert TCHAR to char
char convertTemp3[256] = {0};
char* TcharToChar(TCHAR* str, int len)
{
#ifdef _UNICODE
  memset(convertTemp3, 0, sizeof(convertTemp3));
  WideCharToMultiByte(CP_UTF8, 0, str, len, convertTemp3, 256, 0, 0);
  return convertTemp3;
#else
  return str;
#endif
}

/////////////////////////////////////////////////////////////////////////////
// CDXChannelDlg dialog

CDXChannelDlg::CDXChannelDlg(VideoEngine* videoEngine,
                             CaptureDevicePool& captureDevicePool,
                             ChannelPool& channelPool,
    void* voiceEngine
    ,CWnd* pParent,CDXChannelDlgObserver* observer,
    int parentChannel/*=-1*/)
	: CDialog(CDXChannelDlg::IDD, pParent),
    _canAddLog(true),
    _dialogObserver(observer),
    _videoEngine(videoEngine),
    _captureDevicePool(captureDevicePool),
    _channelPool(channelPool),
    _parentChannel(parentChannel),
#ifndef NO_VOICE_ENGINE
    _voiceEngine((VoiceEngine*) voiceEngine),
#endif
    _callbackEvent(::CreateEvent( NULL, FALSE, FALSE, NULL)),
    _externalTransport(NULL)
{
    strcpy(_logMsg,"");
	_channelId = -1;
    _audioChannel=-1;
    _captureId=-1;

	//_transport = NULL;


	//{{AFX_DATA_INIT(CDXChannelDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32	

    InitializeCriticalSection(&_critCallback);
    unsigned int threadID;
    _callbackThread=(HANDLE)_beginthreadex(NULL,1024*1024,CallbackThread,(void*)this,0, &threadID);


}

void CDXChannelDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDXChannelDlg)
	DDX_Control(pDX, IDC_DEVICE, m_ctrlDevice);
	DDX_Control(pDX, IDC_CODEC_LIST, m_ctrlCodec);
	DDX_Control(pDX, IDC_CAPTURE, m_ctrlLiveRemoteVideo);
	DDX_Control(pDX, IDC_LIVEVIDEO, m_ctrlLiveVideo);
	DDX_Control(pDX, IDC_LOCAL_PORT1, m_localPort1);
	DDX_Control(pDX, IDC_REMOTE_PORT1, m_remotePort1);
	DDX_Control(pDX, IDC_IPADDRESS1, m_remoteIp1);
    DDX_Control(pDX, IDC_CODEC_SIZE, m_ctrlCodecSize);
    DDX_Control(pDX, IDC_RTCPMODE, m_ctrlRtcpMode);
    DDX_Control(pDX, IDC_PACKETBURST, m_ctrlPacketBurst);
	DDX_Control(pDX, IDC_BITRATE, m_ctrlBitrate);
	DDX_Control(pDX, IDC_MIN_FRAME_RATE, m_ctrlMinFrameRate);
    DDX_Control(pDX, IDC_TMMBR,m_cbTmmbr);
    DDX_Control(pDX, IDC_EXTTRANSPORT,m_cbExternalTransport);
    DDX_Control(pDX, IDC_PACKETLOSS,m_ctrlPacketLoss);
    DDX_Control(pDX, IDC_DELAY,m_ctrlDelay);
    DDX_Control(pDX, IDC_FREEZELOG,m_cbFreezeLog);
    DDX_Control(pDX,IDC_INFORMATION,m_ctrlInfo);
	//}}AFX_DATA_MAP
}

// ON_WM_SYSKEYDOWN			ALT+key

BEGIN_MESSAGE_MAP(CDXChannelDlg, CDialog)
	//{{AFX_MSG_MAP(CDXChannelDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_RBUTTONUP()
	//ON_WM_DEVICECHANGE()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_STARTSEND, OnStartSend)
	ON_BN_CLICKED(IDC_STOPSend, OnStopSend)
	//ON_WM_TIMER()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
	ON_CBN_SELCHANGE(IDC_CODEC_LIST, OnCbnSelchangeCodecList)
	ON_CBN_SELCHANGE(IDC_DEVICE, OnCbnSelchangeDevice)
	ON_CBN_SELCHANGE(IDC_CODEC_SIZE, OnCbnSelchangeSize)
	ON_CBN_SELCHANGE(IDC_BITRATE, OnCbnSelchangeBitrate)
	//ON_MESSAGE(WM_DISPLAYCHANGE, OnDisplayChange)
	ON_CBN_SELCHANGE(IDC_MIN_FRAME_RATE, OnCbnSelchangeMinFrameRate)	
    ON_BN_CLICKED(IDC_STARTLISTEN, OnBnClickedStartlisten)
    ON_BN_CLICKED(IDC_STOPLISTEN, OnBnClickedStoplisten)
    ON_BN_CLICKED(IDC_TMMBR, &CDXChannelDlg::OnBnClickedTmmbr)
    ON_CBN_SELCHANGE(IDC_RTCPMODE, &CDXChannelDlg::OnCbnSelchangeRtcpmode)
    ON_BN_CLICKED(IDC_PROT_NACK, &CDXChannelDlg::OnBnClickedProtNack)
    ON_BN_CLICKED(IDC_PROT_NONE, &CDXChannelDlg::OnBnClickedProtNone)
    ON_BN_CLICKED(IDC_PROT_FEC, &CDXChannelDlg::OnBnClickedProtFec)    
    ON_BN_CLICKED(IDC_FREEZELOG, &CDXChannelDlg::OnBnClickedFreezelog)
    ON_BN_CLICKED(IDC_VERSION, &CDXChannelDlg::OnBnClickedVersion)
    ON_BN_CLICKED(IDC_EXTTRANSPORT, &CDXChannelDlg::OnBnClickedExttransport)
    ON_CBN_SELCHANGE(IDC_PACKETLOSS, &CDXChannelDlg::OnCbnSelchangePacketloss)
    ON_CBN_SELCHANGE(IDC_DELAY, &CDXChannelDlg::OnCbnSelchangeDelay)
    ON_BN_CLICKED(IDC_BTN_RECORD_INCOMING, &CDXChannelDlg::OnBnClickedBtnRecordIncoming)
    ON_BN_CLICKED(IDC_BTN_RECORD_OUTGOING, &CDXChannelDlg::OnBnClickedBtnRecordOutgoing)
    ON_BN_CLICKED(IDC_BTN_CREATE_SLAVE, &CDXChannelDlg::OnBnClickedBtnCreateSlave)
    ON_BN_CLICKED(IDC_PROT_NACKFEC, &CDXChannelDlg::OnBnClickedProtNackFec)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDXChannelDlg message handlers


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

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon


	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("5"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("6"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("7"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("8"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("9"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("10"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("11"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("12"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("13"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("14"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("15"));
    ::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("16"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("17"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("18"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("19"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("20"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("21"));
    ::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("22"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("23"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("24"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("25"));
	::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("26"));
    ::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("27"));
    ::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("28"));
    ::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("29"));
    ::SendMessage(m_ctrlMinFrameRate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("30"));
    m_ctrlMinFrameRate.SetCurSel(25);

    // Codec sizes
    for(VideoSize i=VideoSize::UNDEFINED;i<VideoSize::NUMBER_OF_VIDEO_SIZE;i=VideoSize(i+1))
    {
        char sizeStr[64];
        int width=0;
        int height=0;
        GetWidthHeight(i,width,height);
        sprintf(sizeStr,"%d x %d",width,height);
        ::SendMessage(m_ctrlCodecSize.m_hWnd, CB_ADDSTRING, 0,(LPARAM) CharToTchar(sizeStr,-1));
    }
    m_ctrlCodecSize.SetCurSel(8);

    // RTCP mode
    /*
    kRtcpNone     = 0,
    kRtcpCompound_RFC4585     = 1,
    kRtcpNonCompound_RFC5506 = 2 */
    ::SendMessage(m_ctrlRtcpMode.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("RTCP_NONE"));
    ::SendMessage(m_ctrlRtcpMode.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("RTCP_COMPOUND_RFC4585"));
    ::SendMessage(m_ctrlRtcpMode.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("RTCP_NON_COMPOUND_RFC5506"));
    m_ctrlRtcpMode.SetCurSel(2);


    //Packet Burst
    ::SendMessage(m_ctrlPacketBurst.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("0"));
    ::SendMessage(m_ctrlPacketBurst.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("10"));
    ::SendMessage(m_ctrlPacketBurst.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("20"));
    ::SendMessage(m_ctrlPacketBurst.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("30"));
    m_ctrlPacketBurst.SetCurSel(0);


    //Send Bitrate
	::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("50"));
	::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("100"));
	::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("200"));
	::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("300"));
	::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("500"));
	::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("1000"));
	::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("2000"));
    ::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("3000"));
	::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("4000"));
    ::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("5000"));
    ::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("6000"));
    ::SendMessage(m_ctrlBitrate.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("7000"));

    m_ctrlBitrate.SetCurSel(3);

    // External transport packet loss
    ::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("0"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("2"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("4"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("6"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("8"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("10"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("12"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("14"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("16"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("18"));
	::SendMessage(m_ctrlPacketLoss.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("20"));
    m_ctrlPacketLoss.SetCurSel(0);

    // External transport delay
    ::SendMessage(m_ctrlDelay.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("0"));
	::SendMessage(m_ctrlDelay.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("30"));
	::SendMessage(m_ctrlDelay.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("60"));
	::SendMessage(m_ctrlDelay.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("90"));
	::SendMessage(m_ctrlDelay.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("120"));
	::SendMessage(m_ctrlDelay.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("150"));
	::SendMessage(m_ctrlDelay.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("180"));
	::SendMessage(m_ctrlDelay.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("210"));
    m_ctrlDelay.SetCurSel(0);


    _vieBase=ViEBase::GetInterface(_videoEngine);
    TEST_MUSTPASS(_vieBase==0,-5);

    _vieCapture=ViECapture::GetInterface(_videoEngine);
    TEST_MUSTPASS(_vieCapture==0,-5);

    _vieRTPRTCP=ViERTP_RTCP::GetInterface(_videoEngine);
    TEST_MUSTPASS(_vieRTPRTCP==0,-5);

    _vieRender=ViERender::GetInterface(_videoEngine);
    TEST_MUSTPASS(_vieRender==0,-5);

    _vieCodec=ViECodec::GetInterface(_videoEngine);
    TEST_MUSTPASS(_vieCodec==0,-5);
    _vieNetwork=ViENetwork::GetInterface(_videoEngine);
    TEST_MUSTPASS(_vieNetwork==0,-5);

    _vieFile=ViEFile::GetInterface(_videoEngine);
    TEST_MUSTPASS(_vieFile==0,-5);

#ifndef NO_VOICE_ENGINE

    _veBase = VoEBase::GetInterface(_voiceEngine);
    _veNetwork = VoENetwork::GetInterface(_voiceEngine);
    _veCodec = VoECodec::GetInterface(_voiceEngine);
    _veRTCP = VoERTP_RTCP::GetInterface(_voiceEngine);
    TEST_MUSTPASS(_vieBase->SetVoiceEngine(_voiceEngine),-5);
#endif

	int err = 0;

	char str[64];
	bool found = false;


	int captureIdx = 0;
	while (-1 !=_vieCapture->GetCaptureDevice(captureIdx,str,sizeof(str),NULL,0))
	{
		char* tmp = strstr(str,"(VFW)");
		if (!tmp)
		{
            ::SendMessage(m_ctrlDevice.m_hWnd, CB_ADDSTRING, 0,(LPARAM)CharToTchar(str,-1));
			found = true;
		}
		captureIdx++;
		memset(str, 0, 64);
	}
    WIN32_FIND_DATA FindFileData;
    HANDLE hFind;
    //char fileSearch[256];
    //strcpy(fileSearch,_T("*.avi"));
    hFind = FindFirstFile(_T("*.avi"), &FindFileData);
    if (hFind != INVALID_HANDLE_VALUE)
    {

      ::SendMessage(m_ctrlDevice.m_hWnd, CB_ADDSTRING, 0,(LPARAM)(FindFileData.cFileName));
      while(FindNextFile(hFind,&FindFileData))
      {
        ::SendMessage(m_ctrlDevice.m_hWnd, CB_ADDSTRING, 0,(LPARAM)(FindFileData.cFileName));
      }
      FindClose(hFind);
    }



    ::SendMessage(m_ctrlDevice.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("Conference"));
    ::SendMessage(m_ctrlDevice.m_hWnd, CB_ADDSTRING, 0,(LPARAM)_T("None"));

	if (!found)
	{
		strncpy(str,"N/A",64);
		::SendMessage(m_ctrlDevice.m_hWnd, CB_ADDSTRING, 0,(LPARAM)CharToTchar(str,-1));
	}
    m_ctrlDevice.SetCurSel(0);

    //Codecs
    int numOfCodecs = _vieCodec->NumberOfCodecs();
	for(int i=0; i<numOfCodecs;++i)
	{
		VideoCodec codec;
        if(-1 !=_vieCodec->GetCodec(i,codec))
        {
            ::SendMessage(m_ctrlCodec.m_hWnd, CB_ADDSTRING, 0,(LPARAM)CharToTchar(codec.plName,-1));
        }
	}
    m_ctrlCodec.SetCurSel(0);

#ifndef NO_VOICE_ENGINE
	CodecInst voiceCodec;
    int numOfVeCodecs = _veCodec->NumOfCodecs();
	for(int i=0; i<numOfVeCodecs;++i)
	{
        if(_veCodec->GetCodec(i,voiceCodec)!=-1)
        {
            if(strncmp(voiceCodec.plname,"ISAC",4)==0)
            break;


        }
	}

	_audioChannel = _veBase->CreateChannel();


    TEST_MUSTPASS(_veRTCP->SetRTCPStatus(_audioChannel, true),-5);
    TEST_MUSTPASS(_veCodec->SetSendCodec(_audioChannel, voiceCodec),-5);
    TEST_MUSTPASS(_veBase->StartPlayout(_audioChannel),-5);

#endif  //NO_VOICE_ENGINE

	if(_parentChannel==-1)
    {
        TEST_MUSTPASS(_vieBase->CreateChannel(_channelId),-5);
    }
    else // This is a slave channel
    {
        TEST_MUSTPASS(_vieBase->CreateChannel(_channelId,_parentChannel),-5);
    }
#ifndef NO_VOICE_ENGINE
    TEST_MUSTPASS(_vieBase->ConnectAudioChannel(_channelId,_audioChannel),-5);
#endif

    _channelPool.AddChannel(_channelId);	

    //Set Receive codec
    {
    VideoCodec codec;
    int numOfCodecs = _vieCodec->NumberOfCodecs();;
	for(int i=0; i<numOfCodecs;++i)
	{
		if(-1 !=_vieCodec->GetCodec(i,codec))
        {
				if(codec.codecType == webrtc::kVideoCodecVP8)
				{
					codec.codecSpecific.VP8.feedbackModeOn = true;
					codec.codecSpecific.VP8.pictureLossIndicationOn = true;
				}
            TEST_MUSTPASS(_vieCodec->SetReceiveCodec(_channelId,codec),-5);
        }
	}
    }

    //TMMBR
    m_cbTmmbr.SetCheck(BST_CHECKED);
    OnBnClickedTmmbr();

    //Packet Burst
    m_ctrlPacketBurst.SetCurSel(0);


    //Protection method none
    CButton *opProtection = (CButton *) GetDlgItem(IDC_PROT_NONE);
    opProtection->SetCheck(BST_CHECKED);
    OnBnClickedProtNone();


    // Configure the renderer
    ConfigureRender();

    TEST_MUSTPASS(_vieCodec->RegisterEncoderObserver(_channelId,*this),kViECodecObserverAlreadyRegistered);
    TEST_MUSTPASS(_vieCodec->RegisterDecoderObserver(_channelId,*this),-5);

    TEST_MUSTPASS(_vieBase->RegisterObserver(*this),kViEBaseObserverAlreadyRegistered);




    //Set captions based on channel id
    m_remoteIp1.SetAddress(127,0,0,1);
    CString port;	
	port.AppendFormat(_T("%d"),11111+_channelId*4);       
	m_remotePort1.SetWindowText(port);
	m_localPort1.SetWindowText(port);

    CString title;
    this->GetWindowText(title);
    if(_parentChannel==-1)
    {        
        title.AppendFormat(_T("%s - channel %d"),title,_channelId);
    }
    else
    {
        title.AppendFormat(_T("%s - slave channel %d - parent %d"),title,_channelId,_parentChannel);
    }
    this->SetWindowText(title);

    if(_parentChannel!=-1)
       m_ctrlDevice.EnableWindow(FALSE); //Prevent from changing capture device

	return TRUE;  // return TRUE  unless you set the focus to a control
}



void CDXChannelDlg::OnTimer(UINT nIDEvent)
{
	CDialog::OnTimer(nIDEvent);
}

void CDXChannelDlg::SetSendCodec()
{
    // Get the codec stucture
    int codecSel= m_ctrlCodec.GetCurSel();
    VideoCodec codec;
    TEST_MUSTPASS(_vieCodec->GetCodec(codecSel,codec),-5);


    // Set Codec Size
    VideoSize sizeSel=VideoSize(m_ctrlCodecSize.GetCurSel());
    int width, height;
    GetWidthHeight(sizeSel, width, height);
    codec.width=width;
    codec.height=height;

    //Set the codec bitrate
    CString bitrateStr;
	m_ctrlBitrate.GetLBText(m_ctrlBitrate.GetCurSel(), bitrateStr);
    int bitrate = _ttoi(bitrateStr.GetBuffer(0));
    if(codec.codecType!=kVideoCodecI420)
    {
        codec.startBitrate=bitrate;
        codec.maxBitrate=bitrate*4;
    }


    //Set the codec frame rate
    codec.maxFramerate = m_ctrlMinFrameRate.GetCurSel() +5;

    if(strncmp(codec.plName, "VP8", 5) == 0)
    {
		codec.codecSpecific.VP8.feedbackModeOn = true;
		codec.codecSpecific.VP8.pictureLossIndicationOn = true;
        TEST_MUSTPASS(_vieRTPRTCP->SetKeyFrameRequestMethod(_channelId, kViEKeyFrameRequestPliRtcp),-5);
    }else
    {
        TEST_MUSTPASS(_vieRTPRTCP->SetKeyFrameRequestMethod(_channelId, kViEKeyFrameRequestPliRtcp),-5);
    }
    TEST_MUSTPASS(_vieCodec->SetSendCodec(_channelId, codec),-5);

    if (codec.codecType == webrtc::kVideoCodecMPEG4)
    {
        unsigned char configParameterSize = 0;
        _vieCodec->GetCodecConfigParameters(_channelId, codec.codecSpecific.MPEG4.configParameters, configParameterSize);
        codec.codecSpecific.MPEG4.configParametersSize = configParameterSize;
        _vieCodec->SetReceiveCodec(_channelId, codec);
    }
    if (codec.codecType == webrtc::kVideoCodecI420)
    {        // Need to set the receive codec size
        _vieCodec->SetReceiveCodec(_channelId, codec);
    }
}

void CDXChannelDlg::SetSendDestination()
{
    if(_externalTransport)
        return;

    BYTE part1, part2, part3, part4;
	char sendIP1[16];
	m_remoteIp1.GetAddress(part1, part2, part3, part4);
	sprintf(sendIP1,"%d.%d.%d.%d",part1,part2,part3,part4);

    CString strPort;
    m_remotePort1.GetWindowText(strPort);
	int remotePort1 = _ttoi(strPort.GetString());

#ifdef IPV6
	char* recIP = "::0";
#else
	char* recIP = "0.0.0.0";
#endif //IPV6

    TEST_MUSTPASS(_vieNetwork->SetSendDestination(_channelId,sendIP1,remotePort1),kViENetworkAlreadySending);

    #ifndef NO_VOICE_ENGINE
	    m_localPort1.GetWindowText(strPort);
	    int localPort1 = _ttoi(strPort.GetString());
        int res=_veBase->SetLocalReceiver(_audioChannel,localPort1+2);

        TEST_MUSTPASS(_veBase->SetSendDestination(_audioChannel, remotePort1+2, sendIP1),-5)
    #endif

}

void CDXChannelDlg::SetLocalReceiver()
{
    if(_externalTransport)
        return;

    CString strPort;
	m_localPort1.GetWindowText(strPort);
	int localPort1 = _ttoi(strPort.GetString());



    // May fail because we are sending
    TEST_MUSTPASS(_vieNetwork->SetLocalReceiver(_channelId, localPort1),-5);

    #ifndef NO_VOICE_ENGINE
        int res=_veBase->SetLocalReceiver(_audioChannel,localPort1+2);
    #endif



}

void CDXChannelDlg::SetCaptureDevice()
{
    if(_parentChannel!=-1) // don't accept changing input on slave channels.
        return;

    int camSel=-1;
    camSel=m_ctrlDevice.GetCurSel();

	CString captureStr;
    //captureStr.Compare
	m_ctrlDevice.GetLBText(camSel, captureStr);
	if(captureStr!=_T("N/A") != 0)
	{

        TEST_MUSTPASS(_vieFile->StopPlayFile(_captureId),kViEFileNotPlaying);
        TEST_MUSTPASS(_vieCapture->DisconnectCaptureDevice(_channelId),kViECaptureDeviceNotConnected);
        TEST_MUSTPASS(_vieRender->RemoveRenderer(_captureId),kViERenderInvalidRenderId);

        if(_captureId>=0x1001 && _captureId<0x10FF)// ID is a capture device
        {
            TEST_MUSTPASS(_captureDevicePool.ReturnCaptureDevice(_captureId),-5);
        }

        if(captureStr!=_T("None")==0)
        {
            _captureId=-1;
        }
        else if(_tcsstr(captureStr,_T(".avi"))!=NULL ) // Selected an AVI file
        {
            TEST_MUSTPASS(_vieFile->StartPlayFile(TcharToChar(captureStr.GetBuffer(),-1),_captureId,false,webrtc::kFileFormatAviFile),-5);
            TEST_MUSTPASS(_vieRender->AddRenderer(_captureId,m_ctrlLiveVideo.m_hWnd, 0, 0.0f, 0.0f,1.0f,1.0f),-5);
            TEST_MUSTPASS(_vieRender->StartRender(_captureId),-5);
            TEST_MUSTPASS(_vieFile->SendFileOnChannel(_captureId,_channelId),-5);
            TEST_MUSTPASS(_vieFile->StartPlayFileAsMicrophone(_captureId,_channelId,true),-5);
            //TEST_MUSTPASS(_vieFile->StartPlayAudioLocally(_captureId,_channelId),-5);
        }
        else
        {

            char captureName[256];
            char uniqueCaptureName[256];

            TEST_MUSTPASS(_vieCapture->GetCaptureDevice(camSel,captureName,256,uniqueCaptureName,256),-5);

            TEST_MUSTPASS(_captureDevicePool.GetCaptureDevice(_captureId,uniqueCaptureName),-5);
            TEST_MUSTPASS(_vieCapture->StartCapture(_captureId),kViECaptureDeviceAlreadyStarted);
            TEST_MUSTPASS(_vieCapture->RegisterObserver(_captureId,*this),kViECaptureObserverAlreadyRegistered);

            TEST_MUSTPASS(_vieRender->AddRenderer(_captureId,m_ctrlLiveVideo.m_hWnd, 0, 0.0f, 0.0f,1.0f,1.0f),-5);
            TEST_MUSTPASS(_vieCapture->ConnectCaptureDevice(_captureId,_channelId),-5);
            TEST_MUSTPASS(_vieRender->StartRender(_captureId),-5);            
        }
    }

}



void CDXChannelDlg::OnBnClickedStartlisten()
{


    // Configure the local ports
    SetLocalReceiver();

    //Configure the remote destination- needed in order to be able to respond to RTCP messages
    SetSendDestination();


    #ifndef NO_VOICE_ENGINE
        TEST_MUSTPASS(_veBase->StartReceive(_audioChannel),-5);
    #endif
    TEST_MUSTPASS(_vieBase->StartReceive(_channelId),-5);


}

void CDXChannelDlg::OnStartSend()
{

    // Set the send destination
    SetSendDestination();

    // Configure the local ports (Needed to be able to receive RTCP
    //SetLocalReceiver();


    // Set the send codec
    SetSendCodec();

    if(_captureId==-1) // If no capture device has been set.
	    SetCaptureDevice(); //Set the capture device



    //TEST_MUSTPASS(_vieRTPRTCP->SetStartSequenceNumber(_channelId,1),-5);

    // Start sending
    TEST_MUSTPASS(_vieBase->StartSend(_channelId),-5);


    #ifndef NO_VOICE_ENGINE
        TEST_MUSTPASS(_veBase->StartSend(_audioChannel),-5);
    #endif


}

void CDXChannelDlg::ConfigureRender()
{
    TEST_MUSTPASS(_vieRender->AddRenderer(_channelId,m_ctrlLiveRemoteVideo.m_hWnd, 0, 0.0f, 0.0f,1.0f,1.0f),-5);

    TEST_MUSTPASS(_vieFile->SetRenderStartImage(_channelId,"renderStartImage.jpg"),-5);
    TEST_MUSTPASS(_vieRender->StartRender(_channelId),-5);
    TEST_MUSTPASS(_vieFile->SetRenderTimeoutImage(_channelId,"renderTimeoutImage.jpg"),-5);


}


void CDXChannelDlg::OnStopSend()
{

    #ifndef NO_VOICE_ENGINE
        TEST_MUSTPASS(_veBase->StopSend(_audioChannel),-5);
    #endif


    TEST_MUSTPASS(_vieBase->StopSend(_channelId),kViEBaseNotSending);   // Accept error Not sending


}
void CDXChannelDlg::OnBnClickedStoplisten()
{


    #ifndef NO_VOICE_ENGINE
        TEST_MUSTPASS(_veBase->StopReceive(_audioChannel),-5);
    #endif
    TEST_MUSTPASS(_vieBase->StopReceive(_channelId),-5);
}


void CDXChannelDlg::OnDestroy()
{

    OnStopSend();
    OnBnClickedStoplisten();

    if(_vieCapture && _parentChannel==-1)
    {
        _vieCapture->DisconnectCaptureDevice(_channelId);
        _captureDevicePool.ReturnCaptureDevice(_captureId);
    }
    if(_vieFile && _parentChannel!=-1)
    {
        TEST_MUSTPASS(_vieFile->StopPlayFile(_captureId),kViEFileNotPlaying);
    }




    if(_videoEngine)
	{
        if(_parentChannel==-1)
        {
            _vieCodec->DeregisterEncoderObserver(_channelId);
        }
        _vieBase->DeleteChannel(_channelId);
        _channelPool.RemoveChannel(_channelId);
	}

	_videoEngine = NULL;
#ifndef NO_VOICE_ENGINE

    if (_voiceEngine)
	{
        _veBase->DeleteChannel(_audioChannel);
        _veBase->Release();
        _veNetwork->Release();
        _veCodec->Release();
        _veRTCP->Release();
	}
#endif


    strcpy(_logMsg,"");
    SetEvent(_callbackEvent);
    MSG msg; // Wait until the callback thread exits. Need to handle messages since the callback thread can call SendMessage when updating UI
    while(WaitForSingleObject(_callbackThread,10)==WAIT_TIMEOUT)
    {
        DWORD ret = PeekMessage( &msg, NULL, 0, 0,PM_REMOVE );
        if (ret >0)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    CloseHandle(_callbackThread);
    CloseHandle(_callbackEvent);
    DeleteCriticalSection(&_critCallback);

    TEST_MUSTPASS(_vieCapture->Release()<0,-5);
    TEST_MUSTPASS(_vieRTPRTCP->Release()<0,-5);
    TEST_MUSTPASS(_vieRender->Release()<0,-5);
    TEST_MUSTPASS(_vieCodec->Release()<0,-5);
    TEST_MUSTPASS(_vieNetwork->Release()<0,-5);
    TEST_MUSTPASS(_vieFile->Release()<0,-5);
    TEST_MUSTPASS(_vieBase->Release()<0,-5);



#ifdef TEST_EXTERNAL_TRANSPORT
	if(_transport)
		delete _transport;
	_transport = NULL;
#endif

    delete _externalTransport;

	CDialog::OnDestroy();
    if(_dialogObserver)
    {
        _dialogObserver->ChannelDialogEnded(this);
    }
}

void CDXChannelDlg::OnCancel()
{
    DestroyWindow();
}
// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDXChannelDlg::OnPaint()
{
    if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

BOOL CDXChannelDlg::OnDeviceChange( UINT nID, DWORD lParam)
{
	if(nID ==  DBT_DEVNODES_CHANGED)
	{
	  //  SetCaptureDevice();
	}
	return CDialog::OnDeviceChange(nID, lParam);
}


void CDXChannelDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if(SC_MAXIMIZE == nID)
	{}
	CDialog::OnSysCommand(nID, lParam);
}


static bool fullScreen = false;
void CDXChannelDlg::OnRButtonUp( UINT nFlags, CPoint point)
{
	CDialog::OnRButtonUp( nFlags,  point);
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDXChannelDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CDXChannelDlg::OnCbnSelchangeCodecList()
{
    SetSendCodec();
}


void CDXChannelDlg::OnCbnSelchangeSize()
{
    SetSendCodec();
}

void CDXChannelDlg::OnCbnSelchangeDevice()
{


    SetCaptureDevice();

}


void CDXChannelDlg::OnCbnSelchangeBitrate()
{

    SetSendCodec();

}

void CDXChannelDlg::OnCbnSelchangeMinFrameRate()
{

    SetSendCodec();

}


void CDXChannelDlg::OnBnClickedTmmbr()
{

    TEST_MUSTPASS(_vieRTPRTCP->SetTMMBRStatus(_channelId,m_cbTmmbr.GetCheck()==BST_CHECKED),-5);

}

void CDXChannelDlg::OnCbnSelchangeRtcpmode()
{

 /*
 kRtcpNone     = 0,
 kRtcpCompound_RFC4585     = 1,
 kRtcpNonCompound_RFC5506 = 2 */
    ViERTCPMode mode=ViERTCPMode(m_ctrlRtcpMode.GetCurSel());
    TEST_MUSTPASS(_vieRTPRTCP->SetRTCPStatus(_channelId,mode),-5);

}

void CDXChannelDlg::OnBnClickedFreezelog()
{
    _canAddLog=m_cbFreezeLog.GetCheck()!=BST_CHECKED;
}

void CDXChannelDlg::OnBnClickedProtNack()
{

    TEST_MUSTPASS(_vieRTPRTCP->SetNACKStatus(_channelId,true),-5);

}

void CDXChannelDlg::OnBnClickedProtNone()
{

    TEST_MUSTPASS(_vieRTPRTCP->SetNACKStatus(_channelId,false),-5);
    TEST_MUSTPASS(_vieRTPRTCP->SetFECStatus(_channelId,false,0,0),-5);
    TEST_MUSTPASS(_vieRTPRTCP->SetHybridNACKFECStatus(_channelId,false,0,0),-5);
}

void CDXChannelDlg::OnBnClickedProtFec()
{
    int noCodec=_vieCodec->NumberOfCodecs();
    int redPayloadType=0;
    int fecPayloadType=0;
    for(unsigned char i=0;i<noCodec;++i)
    {
        VideoCodec codec;
        _vieCodec->GetCodec(i,codec);
        if(codec.codecType==webrtc::kVideoCodecRED)
        {
            redPayloadType=codec.plType;
        }
        if(codec.codecType==webrtc::kVideoCodecULPFEC)
        {
            fecPayloadType=codec.plType;
        }
    }
    TEST_MUSTPASS(_vieRTPRTCP->SetFECStatus(_channelId,true,redPayloadType,fecPayloadType),-5);
}

void CDXChannelDlg::OnBnClickedProtNackFec()
{
    int noCodec=_vieCodec->NumberOfCodecs();
    int redPayloadType=0;
    int fecPayloadType=0;
    for(unsigned char i=0;i<noCodec;++i)
    {
        VideoCodec codec;
        _vieCodec->GetCodec(i,codec);
        if(codec.codecType==webrtc::kVideoCodecRED)
        {
            redPayloadType=codec.plType;
        }
        if(codec.codecType==webrtc::kVideoCodecULPFEC)
        {
            fecPayloadType=codec.plType;
        }
    }
    TEST_MUSTPASS(_vieRTPRTCP->SetHybridNACKFECStatus(_channelId,true,
                                                      redPayloadType,
                                                      fecPayloadType),-5);

}

void CDXChannelDlg::OnBnClickedVersion()
{
    char version[1024];
    _vieBase->GetVersion(version);
    MessageBox(CharToTchar(version,-1));
    int p=strlen(version);
#ifndef NO_VOICE_ENGINE
    _veBase->GetVersion(version);
    MessageBox(CharToTchar(version,-1));
#endif
}

unsigned int WINAPI CDXChannelDlg::CallbackThread(LPVOID lpParameter)
{
    static_cast<CDXChannelDlg*>(lpParameter)->CallbackThreadProcess();
    return 0;
}

void CDXChannelDlg::CallbackThreadProcess()
{
    while(1)
    {
        if(WAIT_OBJECT_0==WaitForSingleObject(_callbackEvent,INFINITE))
        {
            char smsg[512];
            EnterCriticalSection(&_critCallback);
            strncpy(smsg,_logMsg,strlen(_logMsg)+1);
            strcpy(_logMsg,"");


            LeaveCriticalSection(&_critCallback);
            if(strstr(smsg,"Send")!=NULL)
            {
                unsigned short fractionLost=0;
                unsigned int cumulativeLost=0;
                unsigned int extendedMax=0;
                unsigned int jitter=0;
                int rttMs=0;



                _vieRTPRTCP->GetReceivedRTCPStatistics(_channelId,
                                                  fractionLost,
                                                  cumulativeLost,
                                                  extendedMax,
                                                  jitter,
                                                  rttMs);

                //int bw=0;
                //if(_vieCodec->GetAvailableBandwidth(_channelId,bw)==0)
                //{
                //    sprintf(smsg,"%s, rtt %d, loss %d,bw %d", smsg,rttMs,fractionLost,bw);
                //}
                //else
                //{
                //    _vieBase->LastError(); // Reset last error.
                //}



            }
            if(strlen(smsg))
            {
                m_ctrlInfo.InsertString(0,(LPCTSTR) CharToTchar(smsg,-1));
                while(m_ctrlInfo.GetCount()==151)
                    m_ctrlInfo.DeleteString(150);
            }
            else
            {
                break; // End the callback thread
            }
        }
    }

}
void CDXChannelDlg::AddToInfo(const char* msg)
{
    if(!_canAddLog)
        return;
    EnterCriticalSection(&_critCallback);

    SYSTEMTIME systemTime;
    GetSystemTime(&systemTime);

    if(strlen(_logMsg)==0)
    {
        SetEvent(_callbackEvent); // Notify of new
    }

    sprintf (_logMsg, "(%2u:%2u:%2u:%3u) %s", systemTime.wHour,
                                                           systemTime.wMinute,
                                                           systemTime.wSecond,
                                                           systemTime.wMilliseconds,
                                                           msg
                                                           );



    LeaveCriticalSection(&_critCallback);


}

void CDXChannelDlg::IncomingRate(const int videoChannel,
                              unsigned int framerate,
                              unsigned int bitrate)
{
	char str[64];
	sprintf(str,"Incoming Fr:%d br %d\n", framerate, bitrate);
    AddToInfo(str);
}

void CDXChannelDlg::RequestNewKeyFrame(int channel)
{
    assert(!"(RequestNewKeyFrame why is it called");
}
void CDXChannelDlg::PerformanceAlarm(unsigned int cpuLoad)
{
    char str[64];
    sprintf(str,"Performance alarm %d",cpuLoad);    
    AddToInfo(str);
}
void CDXChannelDlg::OutgoingRate(const int videoChannel,
                              unsigned int framerate,
                              unsigned int bitrate)
	{
		char str[64];
        sprintf(str,"Send Fr:%d br %d", framerate, bitrate);
        AddToInfo(str);
	}
void CDXChannelDlg::IncomingCodecChanged(const int  videoChannel,
                                      const VideoCodec& videoCodec)
	{
		char str[128];
        sprintf(str,"Incoming codec channel:%d pltype:%d width:%d height:%d\n", videoChannel, videoCodec.plType, videoCodec.width,videoCodec.height);        
        AddToInfo(str);
	}
void CDXChannelDlg::BrightnessAlarm(const int captureId,
                                 const Brightness brightness)
{

    switch(brightness)
    {
    case Normal:        
        AddToInfo("BrightnessAlarm - image ok.\n");
        break;
    case Bright:        
        AddToInfo("BrightnessAlarm - light image.\n");
        break;
    case Dark:        
        AddToInfo("BrightnessAlarm - dark image.\n");
        break;
    }
}

void CDXChannelDlg::CapturedFrameRate(const int captureId,
                                   const unsigned char frameRate)
{
   char str[64];
   sprintf(str,"Local Camera Frame rate:%d \n", frameRate);
   AddToInfo(str);
}

void CDXChannelDlg::NoPictureAlarm(const int captureId,
                                const CaptureAlarm alarm)
{
   char str[64];
   sprintf(str,"No Picture alarm\n");   
   AddToInfo(str);

}


void CDXChannelDlg::OnBnClickedExttransport()
{
    if(m_cbExternalTransport.GetCheck()==BST_CHECKED)
    {
        m_localPort1.EnableWindow(FALSE);
        m_remotePort1.EnableWindow(FALSE);
        m_remoteIp1.EnableWindow(FALSE);
        m_ctrlPacketLoss.EnableWindow(TRUE);
        m_ctrlDelay.EnableWindow(TRUE);
        _externalTransport= new TbExternalTransport(*_vieNetwork);
        _vieNetwork->RegisterSendTransport(_channelId,*_externalTransport);
    }
    else
    {
        _vieNetwork->DeregisterSendTransport(_channelId);

        delete _externalTransport;
        _externalTransport=NULL;
        m_localPort1.EnableWindow(TRUE);
        m_remotePort1.EnableWindow(TRUE);
        m_remoteIp1.EnableWindow(TRUE);
        m_ctrlPacketLoss.EnableWindow(FALSE);
        m_ctrlDelay.EnableWindow(FALSE);
    }
}


void CDXChannelDlg::OnCbnSelchangePacketloss()
{
    if(_externalTransport)
    {
        _externalTransport->SetPacketLoss(m_ctrlPacketLoss.GetCurSel()*2);
    }
}


void CDXChannelDlg::OnCbnSelchangeDelay()
{
    if(_externalTransport)
    {
        _externalTransport->SetNetworkDelay(m_ctrlDelay.GetCurSel()*30);
    }

}

void CDXChannelDlg::OnBnClickedBtnRecordIncoming()
{

    CButton *recordBtn = (CButton *) GetDlgItem(IDC_BTN_RECORD_INCOMING);
    
    CString text;
    recordBtn->GetWindowText(text);
    if(text!=_T("Stop Rec Inc")!=0)
    {
        recordBtn->SetWindowText(_T("Stop Rec Inc"));
        SYSTEMTIME time;
        GetSystemTime(&time);
        sprintf(_fileName,"IncomingChannel%d_%4d%2d%2d%2d%2d.avi",_channelId,time.wYear,time.wMonth,time.wDay,time.wHour,time.wMinute);

        AudioSource audioSource=PLAYOUT;
        webrtc::CodecInst audioCodec;
        strcpy(audioCodec.plname,"L16");
        audioCodec.rate     = 256000;
        audioCodec.plfreq   = 16000;
        audioCodec.pacsize  = 160;

        webrtc::VideoCodec videoCodec;
        memset(&videoCodec,0,sizeof(videoCodec));

        strcpy(videoCodec.plName,"VP8");
        videoCodec.maxBitrate=1000;
        videoCodec.startBitrate=1000;
        videoCodec.width=352;
        videoCodec.height=288;
        videoCodec.codecType=webrtc::kVideoCodecVP8;
        videoCodec.maxFramerate=30;        
        TEST_MUSTPASS(_vieFile->StartRecordIncomingVideo(_channelId,_fileName,audioSource,audioCodec, videoCodec),-5);		
    }
    else
    {
        recordBtn->SetWindowText(_T("Record Incoming"));
        TEST_MUSTPASS(_vieFile->StopRecordIncomingVideo(_channelId),-5);
        CString msg;
        msg.AppendFormat(_T("Recorded file %s"),_fileName);
        MessageBox(msg);
    }
}

void CDXChannelDlg::OnBnClickedBtnRecordOutgoing()
{

    CButton *recordBtn = (CButton *) GetDlgItem(IDC_BTN_RECORD_OUTGOING);
    CString text;
    recordBtn->GetWindowText(text);
    if(text!=_T("Stop Rec Out"))
    {
        recordBtn->SetWindowText(_T("Stop Rec Out"));
        SYSTEMTIME time;
        GetSystemTime(&time);
        sprintf(_fileName,"OutgoingChannel%d_%4d%2d%2d%2d%2d.avi",_channelId,time.wYear,time.wMonth,time.wDay,time.wHour,time.wMinute);

        AudioSource audioSource=MICROPHONE;
        webrtc::CodecInst audioCodec;
        strcpy(audioCodec.plname,"L16");
        audioCodec.rate     = 256000;
        audioCodec.plfreq   = 16000;
        audioCodec.pacsize  = 160;

        webrtc::VideoCodec videoCodec;
        memset(&videoCodec,0,sizeof(videoCodec));

        strcpy(videoCodec.plName,"VP8");
        videoCodec.maxBitrate=1000;
        videoCodec.startBitrate=1000;
        videoCodec.width=352;
        videoCodec.height=288;
        videoCodec.codecType=webrtc::kVideoCodecVP8;
        videoCodec.maxFramerate=30;        
        TEST_MUSTPASS(_vieFile->StartRecordOutgoingVideo(_channelId,_fileName,audioSource,audioCodec,videoCodec),-5);		
    }
    else
    {
        recordBtn->SetWindowText(_T("Record Outgoing"));
        TEST_MUSTPASS(_vieFile->StopRecordOutgoingVideo(_channelId),-5);
        CString msg;
        msg.AppendFormat(_T("Recorded file %s"),_fileName);
        MessageBox(msg);
    }
}

void CDXChannelDlg::OnBnClickedBtnCreateSlave()
{
    CDXChannelDlg* newSlave =new CDXChannelDlg(_videoEngine,_captureDevicePool,_channelPool,_voiceEngine,NULL,_dialogObserver,_channelId);
    newSlave->Create(CDXChannelDlg::IDD,NULL);
}
