blob: 0f5c5c506fbcf4c826ec053d3b21009e99f45dcd [file] [log] [blame]
/*
* 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::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);
}