// APIDemoDlg.cpp : APIDemo For Y110 Analog Interface Card
// Copyright  Yeastar Technology Co.,Ltd
// First Version : 2006-7-5
// Last Version : 2006-9-15

#include "stdafx.h"
#include "APIDemo.h"
#include "APIDemoDlg.h"

CAPIDemoDlg* pDlg;

class CE1Adapter : public CYsE1
{
	virtual void MsgFromE1(int nPort, YS_E1_MSG_TYPE type, const _e1_msg_t* param /* = NULL */)
	{
		pDlg->DoMsgFromE1(nPort, type, param);
	}

	virtual void AudioFromE1(int nPort, YS_CB_AUDIO_TYPE type, unsigned char* data, int length)
	{
		pDlg->DoAudioFromE1(nPort, type, data, length);
	}
};

CE1Adapter E1Adapter;
class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAPIDemoDlg dialog

int	CAPIDemoDlg::DoMsgFromE1(int nPort, YS_E1_MSG_TYPE type, const _e1_msg_t* param)
{
	_e1_msg_t* _msg = (_e1_msg_t*)param;
	int nItem = nPort - 1;
	CString str;
	switch (type) {
	case YS_E1_MSG_UNKNOW:
		break;
	case YS_E1_STATUS_OK:
		str.Format("Card:%d Pri Connect Success!", nPort);
		SetDlgItemText(IDC_PROMPT, str);
		break;
	case YS_E1_STATUS_FAIL:
		str.Format("Card:%d Pri Connect Fail!", nPort);
		SetDlgItemText(IDC_PROMPT, str);
		break;
	case YS_E1_MSG_DEV_INFO:
		{
			CString str;
			m_nChanNum = _msg->nChannelNum;
			m_nCardNum = _msg->nCardNum;
			for(short i=0; i<m_nChanNum; i++) {
				str.Format("%d", i+1);
				m_Report.InsertItem(i, str);
				if(m_nChanNum % 23 == 0) str="T1";
				else str="E1";
				m_Report.SetItemText(i, 1, str);
			}
			m_sVersion = "";
			for(i=0; i<_msg->nCardNum; i++) {
				str.Format("%02X ", (BYTE)_msg->nCardVer[i]);
				m_sVersion += str;
			}
		}
		break;
	case YS_E1_MSG_CALL_NEW:
		{
			CString str;
			str.Format("%s/%s|%s", _msg->sCallerId, _msg->sCallerName, _msg->sDidNum);
			m_Report.SetItemText(nItem, 2, "Ringing");
			m_Report.SetItemText(nItem, 4, str);
			if (m_bAutoAnswer) {
				if (E1Adapter.CallAnswer(nPort) == 0)
					m_Report.SetItemText(nItem, 2, "Answer");
			}
			m_bCall[nItem] = 1;
		}
		break;
	case YS_E1_MSG_RINGBACK:
		m_Report.SetItemText(nItem, 2, "Ring back");
		m_Report.SetItemText(nItem, 5, "");
		break;
	case YS_E1_MSG_ANSWER:
		m_Report.SetItemText(nItem, 2, "Answer");
		m_Report.SetItemText(nItem, 5, "");
		break;
	case YS_E1_MSG_HANGUP:
		m_Report.SetItemText(nItem, 2, "Hang Up");
		m_Report.SetItemText(nItem, 5, "");
		memset(m_sDtmf[nPort-1], 0, sizeof(m_sDtmf[nPort-1]));
		DelBridgeOfPort(nPort);
		m_bCall[nItem] = 0;
		break;
	case YS_E1_MSG_RCVDTMF:
		{
			CString dtmfstr;
			dtmfstr.Format("%s%s", m_Report.GetItemText(nItem, 5), _msg->sDtmfs);
			m_Report.SetItemText(nItem, 5, dtmfstr);
			FillDtmf(nPort, _msg->sDtmfs[0]);
		}
		break;
	case YS_E1_MSG_CALL_BUSY:
		m_Report.SetItemText(nItem, 2, "Call Busy");
		m_Report.SetItemText(nItem, 5, "");
		m_bCall[nItem] = 0;
		break;
	case YS_E1_MSG_CALL_FAILURE:
		m_Report.SetItemText(nItem, 2, "Call Failure");
		m_Report.SetItemText(nItem, 5, "");
		m_bCall[nItem] = 0;
		break;
	}
	return 0;
}

int CAPIDemoDlg::DoAudioFromE1(int nPort, YS_CB_AUDIO_TYPE type, unsigned char* data, int length)
{
	switch (type) {
	case YS_E1_AUDIO_EMPTY:
		if (!m_bCall[nPort-1])
			break;
		if (m_IsTalking[nPort-1]) {
			int nBridgePort = GetBridgePort(nPort);
			if (0 == nBridgePort)
				break;
			memcpy(data, m_TalkToBuffer[nBridgePort-1], length);
		} else 
			m_Audio[nPort-1].GetData(data, length);
		break;
	case YS_E1_AUDIO_FULL:
		if (!m_bCall[nPort-1])
			break;
		if (m_IsTalking[nPort-1]) {
			int nBridgePort = GetBridgePort(nPort);
			if (0 == nBridgePort)
				break;
			memcpy(m_TalkToBuffer[nPort-1], data, length);
		} else
			m_Audio[nPort-1].PutData(data, length);
		break;
	default:
		break;
	}
	return 0;
}

int CAPIDemoDlg::AddBridgeOfPort(int nPort1, int nPort2)
{
	if (nPort1 <= 0 || nPort1 > m_nChanNum || nPort2 <=0 || nPort2 > m_nChanNum)
		return -1;
	DelBridgeOfPort(nPort1);
	DelBridgeOfPort(nPort2);
	m_IsTalking[nPort1-1] = true;
	m_TalkTo[nPort1-1] = nPort2;
	memset(m_TalkToBuffer[nPort1-1], 0xff, sizeof(m_TalkToBuffer[nPort1-1]));
	m_IsTalking[nPort2-1] = true;
	m_TalkTo[nPort2-1] = nPort1;
	memset(m_TalkToBuffer[nPort2-1], 0xff, sizeof(m_TalkToBuffer[nPort2-1]));
	CString str;
	str.Format("Talk to %d", nPort1);
	m_Report.SetItemText(nPort2-1, 7, str);
	str.Format("Talk to %d", nPort2);
	m_Report.SetItemText(nPort1-1, 7, str);
	return 0;
}

int	CAPIDemoDlg::DelBridgeOfPort(int nPort)
{
	if (nPort <= 0 || nPort > m_nChanNum)
		return -1;
	int nPeerPort = GetBridgePort(nPort);
	m_IsTalking[nPort-1] = false;
	m_TalkTo[nPort-1] = 0;
	m_Report.SetItemText(nPort-1, 7, "");
	if (nPeerPort <= 0 || nPeerPort > m_nChanNum)
		return 0;
	m_IsTalking[nPeerPort-1] = false;
	m_TalkTo[nPeerPort-1] = 0;
	m_Report.SetItemText(nPeerPort-1, 7, "");
	return 0;
}

int	CAPIDemoDlg::GetBridgePort(int nPort)
{
	int nPeerPort = 0;
	if (nPort <= 0 || nPort > m_nChanNum)
		return 0;
	nPeerPort = m_TalkTo[nPort-1];
	if (nPeerPort <= 0 || nPeerPort > m_nChanNum)
		return 0;
	if (m_TalkTo[nPeerPort-1] != nPort)
		return 0;
	return nPeerPort;
}

int	CAPIDemoDlg::FillDtmf(int nPort, unsigned char dtmf)
{
	if (nPort <= 0 || nPort > m_nChanNum)
		return -1;
	if ('#' != dtmf) {
		if (strlen(m_sDtmf[nPort-1]) > 250)
			memset(m_sDtmf[nPort-1], 0, sizeof(m_sDtmf[nPort-1]));
		for (int i = 0; i < sizeof(m_sDtmf[nPort-1]); i++) {
			if ('\0' == m_sDtmf[nPort-1][i]) {
				m_sDtmf[nPort-1][i] = dtmf;
				break;
			}
		}
		return 0;
	}
		
	int nIndex = -1;
	char sTemp[256] = {0};
	for (int i = 0; i < (int)strlen(m_sDtmf[nPort-1]); i++) {
		if ('*' == m_sDtmf[nPort-1][i])
			nIndex = i; 
	}
	if (nIndex < 0)
		return 0;
	sTemp[0] = m_sDtmf[nPort-1][nIndex+1];
	sTemp[1] = m_sDtmf[nPort-1][nIndex+2];
	int nChan = atoi(sTemp);
	if (nChan <= 0 || nChan > m_nChanNum) {
		memset(m_sDtmf[nPort-1], 0, sizeof(m_sDtmf[nPort-1]));
		return 0;
	}
	_snprintf(sTemp, sizeof(sTemp)-1, "%s", &m_sDtmf[nPort-1][nIndex+3]);
	memset(m_sDtmf[nPort-1], 0, sizeof(m_sDtmf[nPort-1]));
	if (E1Adapter.CallOut(nChan, sTemp, m_CallerID, m_CallerName) != 0)
		return -1;
	AddBridgeOfPort(nPort, nChan);
	return 0;
}

CAPIDemoDlg::CAPIDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CAPIDemoDlg::IDD, pParent)
{
	AfxInitRichEdit();
	pDlg = this;
	//{{AFX_DATA_INIT(CAPIDemoDlg)
	m_PlayFile = "";
	m_RecFile = "";
	m_CallerID = AfxGetApp()->GetProfileString("Default", "CallerID", "");
	m_DtmfStr = AfxGetApp()->GetProfileString("Default", "DTMFStr", "");
	m_CallerName = AfxGetApp()->GetProfileString("Default", "CallerName", "");
	m_CalleeID = _T("");
	m_sVersion = _T("");
	m_bLoop = FALSE;
	m_bEchoEnable = FALSE;
	m_nEchoOffset = 0;
	m_bAutoAnswer = FALSE;
	m_bAllPort = FALSE;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDI_YEASTAR);
	m_nCardNum = 0;
	m_nChanNum = 0;
}

void CAPIDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAPIDemoDlg)
	DDX_Control(pDX, IDC_COMBO_BRIDGE_PORT2, m_ComboBridgePort2);
	DDX_Control(pDX, IDC_COMBO_BRIDGE_PORT1, m_ComboBridgePort1);
	DDX_Control(pDX, IDC_COMBO_DTMF_TYPE, m_ComboDtmfType);
	DDX_Control(pDX, IDC_CODEC_TYPE, m_ComboCodecType);
	DDX_Control(pDX, IDC_DCHANSEL, m_DChanSel);
	DDX_Control(pDX, IDC_SWITCHLIST, m_SwitchList);
	DDX_Control(pDX, IDC_MODELIST, m_ModeList);
	DDX_Control(pDX, IDC_LOG, m_log);
	DDX_Control(pDX, IDC_PLAYBAR, m_PlayBar);
	DDX_Control(pDX, IDC_REPORT, m_Report);
	DDX_Text(pDX, IDC_PLAYFILE, m_PlayFile);
	DDX_Text(pDX, IDC_RECFILE, m_RecFile);
	DDX_Text(pDX, IDC_CALLERID, m_CallerID);
	DDX_Text(pDX, IDC_DTMFSTR, m_DtmfStr);
	DDX_Text(pDX, IDC_CALLERNAME, m_CallerName);
	DDX_Text(pDX, IDC_CALLEEID, m_CalleeID);
	DDX_Text(pDX, IDC_VERSION, m_sVersion);
	DDX_Check(pDX, IDC_CHECK_LOOP, m_bLoop);
	DDX_Check(pDX, IDC_CHECK_ECHO, m_bEchoEnable);
	DDX_Text(pDX, IDC_EDIT_ECHO_OFFSET, m_nEchoOffset);
	DDV_MinMaxUInt(pDX, m_nEchoOffset, 80, 480);
	DDX_Check(pDX, IDC_CHECK_AUTOANSWER, m_bAutoAnswer);
	DDX_Check(pDX, IDC_CHECK_ALL_PORT, m_bAllPort);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAPIDemoDlg, CDialog)
	//{{AFX_MSG_MAP(CAPIDemoDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_OPEN, OnOpen)
	ON_BN_CLICKED(IDC_CLOSE, OnClose)
	ON_BN_CLICKED(IDC_HANGUP, OnHangup)
	ON_BN_CLICKED(IDC_PLAYFILESEL, OnPlayfilesel)
	ON_BN_CLICKED(IDC_STARTPLAY, OnStartplay)
	ON_BN_CLICKED(IDC_STOPPLAY, OnStopplay)
	ON_BN_CLICKED(IDC_RECFILESEL, OnRecfilesel)
	ON_BN_CLICKED(IDC_STARTREC, OnStartrec)
	ON_BN_CLICKED(IDC_STOPREC, OnStoprec)
	ON_BN_CLICKED(IDC_STARTLOOP, OnStartloop)
	ON_BN_CLICKED(IDC_STOPLOOP, OnStoploop)
	ON_BN_CLICKED(IDC_SENDDTMF, OnSenddtmf)
	ON_NOTIFY(NM_CLICK, IDC_REPORT, OnClickReport)
	ON_EN_KILLFOCUS(IDC_PLAYFILE, OnKillfocusPlayfile)
	ON_NOTIFY(NM_CUSTOMDRAW, IDC_PLAYBAR, OnCustomdrawPlaybar)
	ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_PLAYBAR, OnReleasedcapturePlaybar)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_PAUSEPLAY, OnPauseplay)
	ON_BN_CLICKED(IDC_LOADPCMRES, OnLoadpcmres)
	ON_BN_CLICKED(IDC_LOADWAVRES, OnLoadwavres)
	ON_BN_CLICKED(IDC_CALLOUT, OnCallout)
	ON_BN_CLICKED(IDC_ANSWER, OnAnswer)
	ON_BN_CLICKED(IDC_CHECK_LOOP, OnCheckLoop)
	ON_BN_CLICKED(IDC_BUT_ECHO_OFFSET, OnButEchoOffset)
	ON_BN_CLICKED(IDC_CHECK_ECHO, OnCheckEcho)
	ON_BN_CLICKED(IDC_BUT_DTMF_SET, OnButDtmfSet)
	ON_BN_CLICKED(IDC_BUT_SET_BRIDGE, OnButSetBridge)
	ON_BN_CLICKED(IDC_CHECK_AUTOANSWER, OnCheckAutoanswer)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAPIDemoDlg message handlers

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

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 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
	
	SetTimer(1, 1000, NULL);

	m_ModeList.ResetContent();
	m_ModeList.AddString("default");
	m_ModeList.AddString("E1");
	m_ModeList.AddString("T1");
	BYTE ModeNo = AfxGetApp()->GetProfileInt("Default", "Mode", 0);
	m_ModeList.SetCurSel(ModeNo);

	m_SwitchList.ResetContent();
	m_SwitchList.AddString("unknow");
	m_SwitchList.AddString("ni2");
	m_SwitchList.AddString("dms100");
	m_SwitchList.AddString("lucent5e");
	m_SwitchList.AddString("att4ess");
	m_SwitchList.AddString("euroisdnE1");
	m_SwitchList.AddString("euroisdnT1");
	m_SwitchList.AddString("ni1");
	m_SwitchList.AddString("gr303eoc");
	m_SwitchList.AddString("gr303tmc");
	BYTE SwitchNo = AfxGetApp()->GetProfileInt("Default", "Switch", 5);
	m_SwitchList.SetCurSel(SwitchNo);

	BYTE DChannelNo = AfxGetApp()->GetProfileInt("Default", "DChannel", 15);
	m_DChanSel.SetCurSel(DChannelNo);

	BYTE CodecType = AfxGetApp()->GetProfileInt("Default", "codec", 1);
	m_ComboCodecType.AddString("U law");
	m_ComboCodecType.AddString("A law");
	m_ComboCodecType.SetCurSel(CodecType);
	BYTE DtmfType = AfxGetApp()->GetProfileInt("Default", "dtmf", 0);
	m_ComboDtmfType.AddString("inband");
	m_ComboDtmfType.AddString("pri_info");
	m_ComboDtmfType.SetCurSel(DtmfType);
	m_nEchoOffset = 220;
	m_bEchoEnable = 1;
	m_Report.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
	CString str;
	static const struct
	{
		UINT nColHdrId;
		int  nFormat;
		int  nWidth;
	} colData[] = {{IDS_NO, LVCFMT_LEFT, 35},
					{IDS_TYPE, LVCFMT_LEFT, 0},
					{IDS_LINESTATUS, LVCFMT_LEFT, 100},
					{IDS_TONEDETECT, LVCFMT_LEFT, 0},
					{IDS_CALLERID, LVCFMT_LEFT, 120},
					{IDS_GETDTMF, LVCFMT_LEFT, 120},
					{IDS_SENDDTMF, LVCFMT_LEFT, 100},
					{IDS_NOTE, LVCFMT_LEFT, 80}};
	const int nColCount = sizeof colData / sizeof colData[0];

	for (int nColumn = 0; nColumn < nColCount; nColumn++) {
		VERIFY(str.LoadString(colData[nColumn].nColHdrId));
		m_Report.InsertColumn(nColumn, str, colData[nColumn].nFormat,colData[nColumn].nWidth);
	}

	for(int i=0; i<YS_E1_MAX_CHANNEL; i++) {
		m_IsTalking[i] = false;
		m_TalkTo[i] = 0;
		m_IntCount[i] = 0;
		m_bCall[i] = 0;
		memset(m_sDtmf[i], 0, sizeof(m_sDtmf[i]));
	}
	m_bAutoAnswer = AfxGetApp()->GetProfileInt("Default", "AutoAnswer", 0);
	UpdateData(FALSE);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CAPIDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 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 CAPIDemoDlg::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();
	}
}

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

void CAPIDemoDlg::OnOK() 
{
	// CDialog::OnOK();
}

void CAPIDemoDlg::OnOpen() 
{
	if(!UpdateData(TRUE)) return;
	m_Report.DeleteAllItems();
	SetDlgItemText(IDC_VERSION, "");
	BYTE ModeNo = (BYTE)m_ModeList.GetCurSel();
	AfxGetApp()->WriteProfileInt("Default", "Mode", ModeNo);
	BYTE SwitchNo = (BYTE)m_SwitchList.GetCurSel();
	AfxGetApp()->WriteProfileInt("Default", "Switch", SwitchNo);
	BYTE DChannelNo = (BYTE)m_DChanSel.GetCurSel();
	AfxGetApp()->WriteProfileInt("Default", "DChannel", DChannelNo);
	BYTE CodecType = (BYTE)m_ComboCodecType.GetCurSel();
	AfxGetApp()->WriteProfileInt("Default", "Codec", CodecType);
	BYTE DtmfType = (BYTE)m_ComboDtmfType.GetCurSel();
	AfxGetApp()->WriteProfileInt("Default", "Dtmf", DtmfType);
	
//	m_CurrAudioCodec = YS_DEFAULT_AUDIO_CODEC;
//	m_CurrAudioLen = YS_DEFAULT_AUDIO_LENGTH;

	CONF_E1_INFO info = {0};
	info.bSaveChanData = 0;
	info.ModeType = ModeNo;
	info.NodeType = IsDlgButtonChecked(IDC_NETWORK) ? NODE_PRI_NETWORK : NODE_PRI_CPE;
	info.SwitchType = SwitchNo;
	info.DChannelNo = DChannelNo;
	info.nCodecType = CodecType;
	info.nDtmfType = DtmfType;
	if (E1Adapter.Open(&info) != 0) {
		SetDlgItemText(IDC_PROMPT, "Unknow Error!");
	} else {
		SetDlgItemText(IDC_PROMPT, "Open Device Success!");
		GetDlgItem(IDC_MODELIST)->EnableWindow(FALSE);
		GetDlgItem(IDC_SWITCHLIST)->EnableWindow(FALSE);
		GetDlgItem(IDC_NETWORK)->EnableWindow(FALSE);
		GetDlgItem(IDC_OPEN)->EnableWindow(FALSE);
		GetDlgItem(IDC_CLOSE)->EnableWindow(TRUE);
		m_ComboBridgePort1.ResetContent();
		m_ComboBridgePort2.ResetContent();
		for (int i = 0; i < m_nChanNum; i++) {
			CString str;
			str.Format("%d", i+1);
			m_ComboBridgePort1.AddString(str);
			m_ComboBridgePort2.AddString(str);
		}
		m_ComboBridgePort1.SetCurSel(0);
		m_ComboBridgePort2.SetCurSel(1);
	}
	UpdateData(FALSE);
}

void CAPIDemoDlg::OnClose() 
{
	for (int i = 0; i < YS_E1_MAX_CHANNEL; i++) {
		m_Audio[i].Close();
	}
	if (E1Adapter.Close() != 0) {
		SetDlgItemText(IDC_PROMPT, "Unknow Error!");
	} else {
		SetDlgItemText(IDC_PROMPT, "Close Device Success!");
		m_Report.DeleteAllItems();
		GetDlgItem(IDC_MODELIST)->EnableWindow(TRUE);
		GetDlgItem(IDC_SWITCHLIST)->EnableWindow(TRUE);
		GetDlgItem(IDC_NETWORK)->EnableWindow(TRUE);
		GetDlgItem(IDC_OPEN)->EnableWindow(TRUE);
		GetDlgItem(IDC_CLOSE)->EnableWindow(FALSE);
	}

}


void CAPIDemoDlg::PostNcDestroy() 
{
//	CloseDevice();
	
	CDialog::PostNcDestroy();
}

int CAPIDemoDlg::CheckChannelType(CString type) 
{
	POSITION pos = m_Report.GetFirstSelectedItemPosition();
	if (pos == NULL) {
		SetDlgItemText(IDC_PROMPT, "No Selected Channel!");
		return -1;
	}
	int		nItem;
	if((nItem = m_Report.GetNextSelectedItem(pos)) != -1) {
		if(!type.IsEmpty() && m_Report.GetItemText(nItem, 1) != type || m_Report.GetItemText(nItem, 1) == "NULL") {
			SetDlgItemText(IDC_PROMPT, "Channel Type Dismatch! " + type);
			return -1;
		}
	}
	return nItem + 1;
}

void CAPIDemoDlg::OnPlayfilesel() 
{
	static char BASED_CODE pcmFilter[]="PCM Raw File (*.pcm)|*.pcm|Wave File (*.wav)|*.wav||";
	CFileDialog dlgOpenBox(TRUE, NULL, NULL, OFN_ENABLESIZING | OFN_FILEMUSTEXIST, pcmFilter, NULL);
	if (dlgOpenBox.DoModal()==IDOK)
	{
		m_PlayFile = dlgOpenBox.GetPathName();
		UpdateData(FALSE);
		OnKillfocusPlayfile();
	}
}

void CAPIDemoDlg::OnStartplay() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		if (m_Audio[ChannelNo-1].IsPlayFinished()) {
			CString filetype = m_PlayFile.Right(4);
			filetype.MakeUpper();
			if(filetype==".WAV")
				m_Audio[ChannelNo-1].LoadWaveFile((char *)(LPCSTR)m_PlayFile);
			else {
				if(!m_Audio[ChannelNo-1].LoadPcmFile((char *)(LPCSTR)m_PlayFile, AUDIO_CODEC_ULAW)) return;
				DWORD len = m_Audio[ChannelNo-1].GetLength();
				DWORD pos = m_Audio[ChannelNo-1].GetCurPos();
				m_PlayBar.SetRange(0, len, TRUE);
				m_PlayBar.SetPos(pos);
				CString str;
				DWORD sec = len/8000;
				str.Format("Len %d:%02d", sec/60, sec%60);
				SetDlgItemText(IDC_PLAYTIME, str);
				sec = pos/8000;
				str.Format("Pos %d:%02d", sec/60, sec%60);
				SetDlgItemText(IDC_PLAYPOS, str);
			}
		}
		CString str;
		str.Format("PlayFile%d", ChannelNo);
		AfxGetApp()->WriteProfileString("Default", str, m_PlayFile);
		m_Audio[ChannelNo-1].Play();
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnPauseplay() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		m_Audio[ChannelNo-1].Pause();
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnStopplay() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		m_Audio[ChannelNo-1].Close();
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnRecfilesel() 
{
	static char BASED_CODE pcmFilter[]="PCM Raw File (*.pcm)|*.pcm|Wave File (*.wav)|*.wav||";
	CFileDialog dlgOpenBox(FALSE, NULL, NULL, OFN_ENABLESIZING, pcmFilter, NULL);
	if (dlgOpenBox.DoModal()==IDOK)
	{
		m_RecFile = dlgOpenBox.GetPathName();
		UpdateData(FALSE);
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnStartrec() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		CString filetype = m_RecFile.Right(4);
		filetype.MakeUpper();
		if(filetype==".WAV")
			m_Audio[ChannelNo-1].SaveToWaveFile((char *)(LPCSTR)m_RecFile);
		else {
			m_Audio[ChannelNo-1].SaveToPcmFile((char *)(LPCSTR)m_RecFile, AUDIO_CODEC_ULAW);
		}
		CString str;
		str.Format("RecFile%d", ChannelNo);
		AfxGetApp()->WriteProfileString("Default", str, m_RecFile);
		m_Audio[ChannelNo-1].RecStart();
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnStoprec() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		m_Audio[ChannelNo-1].RecStop();
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnStartloop() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		//m_Audio[ChannelNo-1].EchoStart();
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnStoploop() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		//m_Audio[ChannelNo-1].EchoStop();
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnCallout() 
{
	if(!UpdateData(TRUE)) return;
	if (m_bAllPort) {
		for (int i = 0; i < m_Report.GetItemCount(); i++) {
			if (E1Adapter.CallOut(i+1, m_CalleeID, m_CallerID, m_CallerName) != 0)
				continue;
			m_Report.SetItemText(i, 2, "calling...");
			m_Report.SetItemText(i, 4, m_CalleeID);
			m_bCall[i] = 1;
			if(!m_Audio[i].LoadPcmResource(AfxGetInstanceHandle(), IDR_PCMGSLS, AUDIO_CODEC_ULAW, "PCM")) 
				continue;
			m_Audio[i].Play();
		}
		return;
	}
	AfxGetApp()->WriteProfileString("Default", "CallerID", m_CallerID);
	AfxGetApp()->WriteProfileString("Default", "CallerName", m_CallerName);
	AfxGetApp()->WriteProfileString("Default", "CalleeID", m_CalleeID);

	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		if (E1Adapter.CallOut(ChannelNo, m_CalleeID, m_CallerID, m_CallerName) != 0) {
			AfxMessageBox("Call Out Failure!");
		} else {
			m_Report.SetItemText(ChannelNo-1, 2, "calling...");
			m_Report.SetItemText(ChannelNo-1, 4, m_CalleeID);
			m_bCall[ChannelNo-1] = 1;
		}
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnSenddtmf() 
{
	UpdateData(TRUE);
	AfxGetApp()->WriteProfileString("Default", "DTMFStr", m_DtmfStr);
	//GetDlgItem(IDC_SENDDTMF)->EnableWindow(FALSE);

	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		for (int i = 0; i < m_DtmfStr.GetLength(); i++)
			E1Adapter.SendDtmf(ChannelNo, m_DtmfStr.GetAt(i));
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnAnswer() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		if (E1Adapter.CallAnswer(ChannelNo) == 0)
			m_Report.SetItemText(ChannelNo-1, 2, "Answer");
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnHangup() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		DelBridgeOfPort(ChannelNo);
		E1Adapter.HangUp(ChannelNo);
		m_bCall[ChannelNo-1] = 0;
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnClickReport(NMHDR* pNMHDR, LRESULT* pResult) 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		SetChannelValue(ChannelNo);
	} 
	*pResult = 0;
}

void CAPIDemoDlg::SetChannelValue(short ChannelNo)
{
	CString str;
	CString newPlayFile;
	UpdateData(TRUE);
	str.Format("PlayFile%d", ChannelNo);
	newPlayFile = AfxGetApp()->GetProfileString("Default", str, "");
	if (newPlayFile != "")
		m_PlayFile = newPlayFile;
	str.Format("RecFile%d", ChannelNo);
	m_RecFile = AfxGetApp()->GetProfileString("Default", str, "");
	m_bLoop = m_Audio[ChannelNo-1].GetPlayLoop();
	str.Format("echo%d", ChannelNo);
	m_bEchoEnable = AfxGetApp()->GetProfileInt("Default", str, 1);
	UpdateData(FALSE);
	if(m_Audio[ChannelNo-1].GetLength()==0) 
		OnKillfocusPlayfile();
}


void CAPIDemoDlg::OnKillfocusPlayfile() 
{
	UpdateData(TRUE);

}

void CAPIDemoDlg::OnCustomdrawPlaybar(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CString str;
	DWORD sec = m_PlayBar.GetPos()/8000;
	str.Format("Pos %d:%02d", sec/60, sec%60);
	SetDlgItemText(IDC_PLAYPOS, str);
	
//	*pResult = 0;
}

void CAPIDemoDlg::OnReleasedcapturePlaybar(NMHDR* pNMHDR, LRESULT* pResult) 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		if(!m_Audio[ChannelNo-1].SeekTo(m_PlayBar.GetPos())) 
			return;
	}
}

void CAPIDemoDlg::OnCheckLoop() 
{
	// TODO: Add your control notification handler code here
	UpdateData(TRUE);
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		if(!m_Audio[ChannelNo-1].SetPlayLoop(m_bLoop)) 
			return;
	}
}

void CAPIDemoDlg::OnTimer(UINT nIDEvent) 
{
	if(nIDEvent == 1) {
		POSITION pos = m_Report.GetFirstSelectedItemPosition();
		int		ChannelNo;
		if (pos != NULL) {
			ChannelNo = m_Report.GetNextSelectedItem(pos);
			if(m_Report.GetItemText(ChannelNo, 1) != "NULL") {
				DWORD len, pos, sec;
				CString str, old;
				len = m_Audio[ChannelNo].GetLength();
				pos = m_Audio[ChannelNo].GetCurPos();
				if(pos==0) {
					BOOL nn = m_Audio[ChannelNo].IsPlayFinished();
				}
				m_PlayBar.SetRange(0, len, TRUE);
				m_PlayBar.SetPos(pos);
				sec = len/8000;
				str.Format("Len %d:%02d", sec/60, sec%60);
				GetDlgItemText(IDC_PLAYTIME, old);
				if(str!=old) SetDlgItemText(IDC_PLAYTIME, str);
				sec = pos/8000;
				str.Format("Pos %d:%02d", sec/60, sec%60);
				GetDlgItemText(IDC_PLAYPOS, old);
				if(str!=old) SetDlgItemText(IDC_PLAYPOS, str);

				len = m_Audio[ChannelNo].GetRecLength();
				sec = len/8000;
				str.Format("Len %d:%02d", sec/60, sec%60);
				GetDlgItemText(IDC_RECTIME, old);
				if(str!=old) SetDlgItemText(IDC_RECTIME, str);
			}
		}
	}
	CDialog::OnTimer(nIDEvent);
}

void CAPIDemoDlg::OnLoadpcmres() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		if(!m_Audio[ChannelNo-1].LoadPcmResource(AfxGetInstanceHandle(), IDR_PCMGSLS, AUDIO_CODEC_ULAW, "PCM")) 
			return;
		m_Audio[ChannelNo-1].Play();
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnLoadwavres() 
{
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		if(!m_Audio[ChannelNo-1].LoadWaveResource(AfxGetInstanceHandle(), IDR_IMA, "WAVE")) 
			return;
		m_Audio[ChannelNo-1].Play();
	} else {
		AfxMessageBox("please select channel!");
	}
}

void CAPIDemoDlg::OnButEchoOffset() 
{
	// TODO: Add your control notification handler code here
	UpdateData(TRUE);
	E1Adapter.SetEchoOffset(m_nEchoOffset);
}

void CAPIDemoDlg::OnCheckEcho() 
{
	// TODO: Add your control notification handler code here
	UpdateData(TRUE);
	int ChannelNo = CheckChannelType("");
	if(ChannelNo != -1) {
		CString str;
		str.Format("echo%d", ChannelNo);
		AfxGetApp()->WriteProfileInt("Default", str, m_bEchoEnable);
		E1Adapter.SetEchoEnable(ChannelNo, m_bEchoEnable);
	}	
}

void CAPIDemoDlg::OnButDtmfSet() 
{
	// TODO: Add your control notification handler code here
	BYTE DtmfType = (BYTE)m_ComboDtmfType.GetCurSel();
	if (E1Adapter.SetDtmfType(DtmfType) != 0)
		return;	
	AfxGetApp()->WriteProfileInt("Default", "Dtmf", DtmfType);
}

void CAPIDemoDlg::OnButSetBridge() 
{
	// TODO: Add your control notification handler code here
	int nPort1 = m_ComboBridgePort1.GetCurSel() + 1;
	int nPort2 = m_ComboBridgePort2.GetCurSel() + 1;
	if (nPort1 == nPort2) {
		AfxMessageBox("Set Audio Bridge Err!");
		return;
	}
	if (AddBridgeOfPort(nPort1, nPort2) != 0){
		AfxMessageBox("Set Audio Bridge Err!");
		return;
	}
}

BOOL CAPIDemoDlg::DestroyWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	E1Adapter.Close();
	return CDialog::DestroyWindow();
}

void CAPIDemoDlg::OnCheckAutoanswer() 
{
	// TODO: Add your control notification handler code here
	UpdateData(TRUE);
	AfxGetApp()->WriteProfileInt("Default", "AutoAnswer", m_bAutoAnswer);
}
