⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mainframe.cpp

📁 三汇CTI示例程序源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

#include "StdAfx.h"
#include "App.h"

#include "MainFrame.h"

IMPLEMENT_DYNAMIC(MainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd)
	ON_WM_CREATE()
	ON_WM_TIMER() 
	ON_WM_DESTROY()
END_MESSAGE_MAP()


typedef struct ConInfo 
{
	int recNum;
};

struct ConInfo conInfo[50] = {0};

// ENG: Channel list
// CHS: 通道列表
Channel *channels;

BOOL IsStartCti;

// ENG: Conference_id - master_channel pair
// CHS: 会议号-主持人通道 对
map<int, int> cm_pair;

int total_ch;
int	recNumber = 0;

// ENG:	Master Channel Configure
// CHS:	主持人通道

// ENG: Reserved channels
// CHS: 保留通道
int master[] = {0, 1, 2, 3};
const int master_num = sizeof(master) / sizeof(int);


// ENG:	Add files to playlist by num. 
//		Example: if num = 12, it will add 1.wav and 2.wav to the playlist of ch. 
// CHS:	根据参数 num 将需要的文件加到播放列表。
//		例如:如果 num = 12,那么本函数将添加 1.wav 和 2.wav 到 ch 通道的播放列表。
void add_list(int ch, long num)
{
	int a = log10(num);
	int d;
	char s[2];
	char file[100];

	while (a >= 0)
	{
		// ENG:	Get first bit (10-based)
		// CHS:	取第一位
		d = num / pow(10, a);
		num -= d * pow(10, a--);
		itoa(d, s, 10);

		// ENG: Cat a filename
		// CHS: 拼接文件名
		strcpy(file, ".\\wav\\");
		strcat(file, s);
		strcat(file, ".wav");

		// ENG: Add to the playlist
		// CHS: 添加到文件列表
		CHECK_RETURN SsmAddToFileList(ch, file, -1, 0, -1);
	}
}

// ENG: Get its master channel of the parameter 'conf'
// CHS: 返回会议号 conf 的主持人通道号。 
int get_master(int conf)
{
	return cm_pair.find(conf)->second;
}

// ENG: Get master channel of the conf that parameter 'channel' joined.
// CHS: 返回通道 channel 加入的会议的主持人通道号。
int get_chs_master(int channel)
{
	int GrpId, MmbrId;
	DWORD SilenceTime;
	WORD JoinMode, IsSpeaking;
	CHECK_RETURN SsmGetConfChInfo(channel, &GrpId, &MmbrId, &JoinMode, &IsSpeaking, &SilenceTime);

	return get_master(GrpId);
}

// ENG: get an idle channel for the master from the array master
// CHS: 从数组 master 中返回一个空闲的通道给主持人使用。
int get_idle()
{
	for (int i = 0; i < total_ch; i++)
	{ 
		if (channels[i].master == MASTER_IDLE)
			return i;
	}
	return -1;
}

// ENG: check whether the two channel are in the same conference
// CHS: 检查这两个通道是否是在同一个会议中。
bool is_same_group(int ch1, int ch2)
{
	int group1, group2;
	int tmp;
	WORD tmp2;
	DWORD tmp3;
	if (SsmGetConfChInfo(ch1, &group1, &tmp, &tmp2, &tmp2, &tmp3) == -1)
		return false;
	if (SsmGetConfChInfo(ch2, &group2, &tmp, &tmp2, &tmp2, &tmp3) == -1)
		return false;

	return (group1 == group2);

}

// ENG: UI and something unimportant
// CHS: 用户界面和一些不重要的东西
int MainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	CFrameWnd::OnCreate(lpCreateStruct);
	EVENT_SET_INFO EventSet;
	int i;

	// ENG: CTI Board initalizes
	// CHS: CTI 板卡初始化
	IsStartCti = FALSE;
	if (SsmStartCti(".\\shconfig.ini", ".\\shindex.ini") != 0)
	{
		CString sdfs = SsmGetLastErrMsgA();
		MessageBox(SsmGetLastErrMsgA(), _T("Conference Demo"), MB_OK | MB_ICONWARNING);
		DestroyWindow();
	}
	else if (SsmGetMaxUsableBoard() != SsmGetMaxCfgBoard())
	{
		MessageBox(SsmGetLastErrMsgA(), _T("Conference Demo"), MB_OK | MB_ICONWARNING);
		DestroyWindow();
	}
	else
	{
		IsStartCti = TRUE;
		
		EventSet.dwWorkMode = EVENT_MESSAGE;
		EventSet.lpHandlerParam = this->GetSafeHwnd();
		CHECK_RETURN SsmSetEvent(-1, -1, TRUE, &EventSet);

		total_ch = SsmGetMaxCh();
		if (total_ch >= master_num)
		{
			channels = new Channel[total_ch];
			for (i = 0; i < total_ch; i++)
			{
				channels[i].state_channel = CH_IDLE;
				channels[i].state_conference = CO_IDLE;
				channels[i].type = SsmGetChType(i);
				channels[i].master = NOT;
				channels[i].BgSoundEnabled = false;
				channels[i].IsPlayingBgSound = false;
				channels[i].BgSoundVolume = 0;
				channels[i].ch_to_talk_securely = -1;
			}
			for(i = 0; i < master_num; i++)
			{
				if (master[i] < total_ch)
				{
					channels[master[i]].master = MASTER_IDLE;
				}
			}
		}
		else
		{
			MessageBox("Can not get enough channels.", _T("Conference Demo"), MB_OK | MB_ICONWARNING);
			DestroyWindow();
		}
		SetTimer(0, 100, NULL);

	}

	return 0;
}

BOOL MainFrame::DestroyWindow()
{
	CFrameWnd::DestroyWindow();
	return TRUE;
}

void MainFrame::OnDestroy()
{
	if (IsStartCti)
	{
		delete[] channels;
		SsmCloseCti();
	}

	return;
}

BOOL MainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
	wndSplitter.CreateStatic(this, 1, 2);
	wndSplitter.CreateView(0, 0, RUNTIME_CLASS(LeftView), CSize(400, 100), pContext);
	wndSplitter.CreateView(0, 1, RUNTIME_CLASS(ChildView), CSize(400, 100), pContext);

	wndStatusBar.Create(this);

	return TRUE;
}

BOOL MainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	CFrameWnd::PreCreateWindow(cs);

	return TRUE;
}

BOOL MainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
	if (wndSplitter.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;
	else
		return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

// ENG: Deal with Synway messages.
//		It is important for the demo and you may refer here.
// CHS: 处理三汇的用户消息。
//		这一部分对本程序很重要,您可能需要作参考。
LRESULT MainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	int new_state;
	int ch;
	char dtmf;

	if (message >= WM_USER)
	{
		ch = wParam;
		switch (message - WM_USER)
		{
			// ENG: Here is about the channel state, it will send unitive messages to the conference.
			//		For more details, please see Channel flowchart.
			// CHS: 这里是关于通道状态的代码,它将发送统一的消息给会议。
			//		欲了解详情,请参考通道状态转移图。
			case E_CHG_ChState:
				new_state = lParam & 0x00FF;
					// ENG: Trunk and digital
					// CHS: 外线和数字
				if (channels[ch].type == 0 ||
					channels[ch].type == 4 ||
					channels[ch].type == 6 ||
					channels[ch].type == 7 ||
					channels[ch].type == 8 ||
					channels[ch].type == 11 ||
					channels[ch].type == 16 ||
					channels[ch].type == 17
					)
				{

					if( channels[ch].state_channel == CH_INVITEUSER)
					{
						if( new_state == 3)
						{
							channels[ch].state_channel = CH_TALK;
							channels[ch].creater = false;
							channels[ch].dtmf_str.erase(channels[ch].dtmf_str.begin(), channels[ch].dtmf_str.end());
							CHECK_RETURN SsmPlayFile(ch, ".\\wav\\c.wav", -1, 0, -1);
							SsmSetDtmfStopPlay(ch, TRUE);
							channels[ch].state_conference = CO_HOW_TO_JOIN;
						}
						else if(new_state = S_CALL_STANDBY || new_state == S_CALL_PENDING)
						{
							CHECK_RETURN SsmHangup(ch);
							channels[ch].state_channel = CH_IDLE;
						}

					}

					else if (new_state == 2 && channels[ch].state_channel == CH_IDLE)
					{
						CHECK_RETURN SsmPickup(ch);
						channels[ch].state_channel = CH_WAIT_TALK;
					}
					else if (new_state == 3 && channels[ch].state_channel == CH_WAIT_TALK)
					{
						PostMessage(TO_START, ch);
						channels[ch].state_channel = CH_TALK;
					}
					else if (channels[ch].state_channel == CH_WAIT_TALK && (channels[ch].type != 16 && channels[ch].type != 17))
					{
						CHECK_RETURN SsmHangup(ch);
						channels[ch].state_channel = CH_IDLE;
					}
					else if (channels[ch].state_channel == CH_TALK || S_CALL_PENDING == SsmGetChState(ch))
					{
						CHECK_RETURN SsmHangup(ch);
						PostMessage(TO_END, ch);
						channels[ch].state_channel = CH_IDLE;
					}
				}
				// ENG: Station
				// CHS: 坐席
				else if (channels[ch].type == 2) 
				{
					if (new_state == 1 && channels[ch].state_channel == CH_IDLE)
					{
						PostMessage(TO_START, ch);
						channels[ch].state_channel = CH_TALK;
					}
					else if (new_state == 0 && channels[ch].state_channel == CH_TALK)
					{
						PostMessage(TO_END, ch);
						channels[ch].state_channel = CH_IDLE;
					}
				}
				break; 

			// ENG: Here is about dtmf for each choice.
			// CHS: 用于选择的 DTMF 音。
			case E_CHG_RcvDTMF:
				// Arc 4
				if (channels[ch].state_conference == CO_CREATE_OR_JOIN)
				{
					dtmf = lParam & 0x00FF;
					if (dtmf == '*')
					{
						if (channels[ch].dtmf_str.length() != 0)
						{
							char szRecFile[MAX_PATH];

							strcpy(szRecFile, ".\\rec\\");
							strcat(szRecFile, channels[ch].dtmf_str.c_str());
							strcat(szRecFile, ".wav");
							CHECK_RETURN SsmSetDtmfStopPlay(ch, TRUE);
							CHECK_RETURN SsmAddToFileList(ch, szRecFile, -1, 0, -1);
							CHECK_RETURN SsmPlayFileList(ch);
							channels[ch].dtmf_str.erase(channels[ch].dtmf_str.begin(), channels[ch].dtmf_str.end());
							break;
						}
						break;

					}
					if (dtmf == '#')
					{
						// ENG: To create
						// CHS: 创建
						if (channels[ch].dtmf_str.length() == 0)
						{
							// ENG: Create a conference.
							// CHS: 创建一个会议。
							int conf_id = SsmCreateConfGroup(8, 8, 6, -1);
							channels[ch].creater = true;
							if (conf_id >= 0)
							{
								channels[ch].conf_to_join = conf_id;
								int master_ch = get_idle();
								if (master_ch >= 0)
								{
									// ENG: Add master
									// CHS: 添加主持人
									channels[master_ch].master = MASTER_BUSY;
									cm_pair.insert(make_pair(conf_id, master_ch));
									if(master_ch != ch)
									{	
										CHECK_RETURN SsmJoinConfGroup(conf_id, master_ch, 0, 0, FALSE, FALSE);
									}
								
									// ENG: Play "The id of the conference created is ..." .
									// CHS: 播放“您创建的会议的编号的是……”。
									CHECK_RETURN SsmClearFileList(ch);
									CHECK_RETURN SsmAddToFileList(ch, ".\\wav\\d.wav", -1, 0, -1);
									add_list(ch, conf_id);

									// ENG: Play "Choose join-mode ...".
									// CHS: 播放“请选择加入模式……”。
									 CHECK_RETURN SsmAddToFileList(ch, ".\\wav\\c.wav", -1, 0, -1);
									 CHECK_RETURN SsmPlayFileList(ch);
									// ENG: Change state.
									// CHS: 改变状态。
									 char fileName[MAX_PATH];
									 wsprintf(fileName, ".\\rec\\%d.wav", recNumber);
									 conInfo[conf_id].recNum = recNumber;
									 
									 CHECK_RETURN SsmRecToFile(master_ch, fileName, -1, 0, -1, 0, 0);
									 recNumber++;

									 channels[ch].state_conference = CO_HOW_TO_JOIN;
								}
								else // ENG: No more master channels
									 // CHS: 没有更多的主持人通道
								{
									CHECK_RETURN SsmFreeConfGroup(conf_id);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -