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

📄 mcuendpoint.cpp

📁 一个简单的视频会议VC++MFC工程文件
💻 CPP
字号:
// MCUEndPoint.cpp: implementation of the CMCUEndPoint class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "VISMCU.h"
#include "MCUEndPoint.h"
#include "MainFrm.h"
#include "Shlwapi.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMCUEndPoint::CMCUEndPoint(CMainFrame &mainFrm):CH323EndPoint(FALSE),m_mainFrm(mainFrm)
{
	m_findingGK=FALSE;
}

CMCUEndPoint::~CMCUEndPoint()
{
	for(int i=0;i<m_roomList.GetSize();i++)
	{
		CRoom *p=m_roomList.GetAt(i);
		if(p)
			delete p;
	}
}

void CMCUEndPoint::OnAnswerCall(DWORD connID,const char *RoomID)
{//有终端呼入
	m_mainFrm.Output(IDS_LOG_INCOMING_CALL,connID,RoomID);

	if(AddMember(connID,RoomID))
	{
		
		AnswerCall(connID,TRUE);
	}
	else
	{
		AnswerCall(connID,FALSE);
	}
}

void CMCUEndPoint::OnWaitForAnswer(DWORD connID)
{
}

void CMCUEndPoint::OnConnectionCleared(DWORD connID, DWORD duration,enum CallEndReason reason)
{
	CRoom *room=(CRoom*)GetConnectionData(connID);
	if(room->GetMemberCount()==1)//最后一个人离开会议,不必发送成员离开消息
		room=NULL;
	RemoveMember(connID);
	
	m_mainFrm.Output(IDS_LOG_CALLEND,connID,duration,reason);

	if(room)
	{
		//发送成员离开消息
		
		CString str;
		str.Format("MDEL %d",connID);
		for(DWORD i=0;i<room->GetMemberCount();i++)
		{
			DWORD id=room->GetMembers()[i];
			SendNonStandardMsg(id,str);
		}
	}
}

void CMCUEndPoint::OnConnectionEstablished(DWORD connID)
{
	CString roomID;
	char IP[256]="";
	char appName[256]="";
	CRoom *room=(CRoom*)GetConnectionData(connID);
	roomID=room->GetName();
	GetRemoteAddress(connID,IP,256);
	GetRemoteApplication(connID,appName,256);
	m_mainFrm.Output(IDS_LOG_ESTABLISHED,connID,roomID,GetRemoteName(connID),IP,appName);

	//通知所在会议名称
	CString str;
	str.Format("ROOM %s",roomID);
	SendNonStandardMsg(connID,str);
	//通知会议中其他成员,有人加入
	str.Format("MADD %d %s",connID,GetRemoteName(connID));
	for(DWORD i=0;i<room->GetMemberCount();i++)
	{
		DWORD id=room->GetMembers()[i];
		if(id!=connID)
			SendNonStandardMsg(id,str);
	}
}

void CMCUEndPoint::OnReceiveUserInput(DWORD connID,const char* value)
{
}

//VIS MCU和VIS EP示例程序中利用nonstandard message来实现简单的会议控制
//开发者可以利用nonstandard message实现符合自己需求的会议控制,以及电子
//白板、文件共享等功能
//
//VIS MCU\VIS EP中使用的简单的控制命令如下
//  [前缀]                  含义
//  "MADD"     由MCU发给EP,告诉EP有人加入会议
//  "MDEL"     由MCU发给EP,告诉EP有人离开会议
//  "LIST"     由EP发给MCU,向MCU索取会议成员列表
//  "ROOM"     由MCU发给EP,告诉EP当前所在会议名
//  "ANNO"     通知信息,由MCU发给所有EP
//  "MSGA"     某个EP向所有人发话,由MCU发给EP
//  "MSGP"     某个EP发话给另一个EP,由MCU发给EP
//  "SMSG"     EP发话给另一个EP,由EP发给MCU,MCU然后转发成"MSGA"或者"MSGP"
//  "SETA"     EP发给MCU,告诉MCU要切换音频
//  "SETV"     EP发给MCU,告诉MCU要切换视频

void CMCUEndPoint::OnReceiveNonStandardMsg(DWORD connID,const char* value)
{
	CString v=value;
	CString prefix=v.Left(4);
	if(prefix=="LIST")
	{//终端请求成员列表
		CRoom *room=(CRoom*)GetConnectionData(connID);
		if(room)
		{
			CString str;
			for(DWORD i=0;i<room->GetMemberCount();i++)
			{
				DWORD id=room->GetMembers()[i];
				if(id!=connID)
				{					
					str.Format("MADD %d %s",id,GetRemoteName(id));
					SendNonStandardMsg(connID,str);
				}
			}
		}
	}
	else if(prefix=="SMSG")
	{//终端向其他终端发送文本信息
		CString content=v.Right(v.GetLength()-4-1);
		int index=content.Find(' ');
		DWORD id=StrToInt(content.Left(index));
		CString body=content.Right(content.GetLength()-index-1);
		CString str;
		if(id==0)//跟所有人说
		{
			str.Format("MSGA %d %s",connID,body);
			CRoom *room=(CRoom*)GetConnectionData(connID);
			if(room)
			{			
				for(DWORD i=0;i<room->GetMemberCount();i++)
				{
					DWORD id=room->GetMembers()[i];
					if(id!=connID)
					{					
						SendNonStandardMsg(id,str);
					}
				}
			}
			
		}
		else
		{
			str.Format("MSGP %d %s",connID,body);
			SendNonStandardMsg(id,str);
		}
	}
	else if(prefix=="SETV")
	{//终端要求切换视频
		CString content=v.Right(v.GetLength()-4-1);
		DWORD id=StrToInt(content);
		CRoom *room=(CRoom*)GetConnectionData(connID);
		if(room)
		{
			if(id==0)//终端要求切换到"所有人"
				room->GetVideoMixer().SetMixerMode(connID,TRUE);
			else//终端要求切换到某一个人
			{
				room->GetVideoMixer().SetMixerMode(connID,FALSE);
				room->GetVideoMixer().SetOutgoingVideo(connID,1,&id);
			}
		}
	}
	else if(prefix=="SETA")
	{//终端要求切换音频
		CString content=v.Right(v.GetLength()-4-1);
		DWORD id=StrToInt(content);
		CRoom *room=(CRoom*)GetConnectionData(connID);
		if(room)
		{
			if(id==0)//终端要求切换到"所有人"
				room->GetAudioMixer().SetMixerMode(connID,TRUE);
			else//终端要求切换到某一个人
			{
				room->GetAudioMixer().SetMixerMode(connID,FALSE);
				room->GetAudioMixer().SetOutgoingAudio(connID,1,&id);
			}
		}
	}
}

BOOL CMCUEndPoint::OnRenderAudioFrame(DWORD connID,BYTE* frame,int len)
{
	CRoom *room=(CRoom*)GetConnectionData(connID);
	ASSERT(room!=NULL);
	return room->GetAudioMixer().Write(connID,frame,len);
}

BOOL CMCUEndPoint::OnReadAudioFrame(DWORD connID,BYTE* frame,int len)
{
	CRoom *room=(CRoom*)GetConnectionData(connID);
	ASSERT(room!=NULL);
	return room->GetAudioMixer().Read(connID,frame,len);
}
	
BOOL CMCUEndPoint::OnAudioStop(DWORD connID, BOOL outgoing,const char *CodecName)
{
	m_mainFrm.Output(IDS_LOG_AUDIO_STOP,connID,outgoing?"发送":"接收",CodecName);
	CRoom *room=(CRoom*)GetConnectionData(connID);
	ASSERT(room!=NULL);
	return room->GetAudioMixer().RemoveChannel(connID,outgoing);
}

BOOL CMCUEndPoint::OnAudioStart(DWORD connID,BOOL outgoing,const char *CodecName)
{
	CRoom *room=(CRoom*)GetConnectionData(connID);
	ASSERT(room!=NULL);
	BOOL ret=room->GetAudioMixer().AddChannel(connID,outgoing);
	if(ret)
		m_mainFrm.Output(IDS_LOG_AUDIO_START,connID,outgoing?"发送":"接收",CodecName);

	return 	ret;
}

BOOL CMCUEndPoint::OnRenderVideoFrame(DWORD connID,BYTE *frame, int width, int height)
{
	CRoom *room=(CRoom*)GetConnectionData(connID);
	ASSERT(room!=NULL);
	return room->GetVideoMixer().Write(connID,frame,width,height,FALSE);//不需要delay
}

BOOL CMCUEndPoint::OnReadVideoFrame(DWORD connID,BYTE* frame,int width,int height)
{
	CRoom *room=(CRoom*)GetConnectionData(connID);
	ASSERT(room!=NULL);
	return room->GetVideoMixer().Read(connID,frame,width,height);
}
	
BOOL CMCUEndPoint::OnVideoStop(DWORD connID,BOOL outgoing,const char *CodecName)
{
	m_mainFrm.Output(IDS_LOG_VIDEO_STOP,connID,outgoing?"发送":"接收",CodecName);
	CRoom *room=(CRoom*)GetConnectionData(connID);
	ASSERT(room!=NULL);
	return room->GetVideoMixer().RemoveChannel(connID,outgoing);
}

BOOL CMCUEndPoint::OnVideoStart(DWORD connID,BOOL outgoing,const char* CodecName)
{	
	CRoom *room=(CRoom*)GetConnectionData(connID);
	ASSERT(room!=NULL);
	BOOL ret= room->GetVideoMixer().AddChannel(connID,outgoing,
		AfxGetApp()->GetProfileInt("",KEY_VIDEO_FPS,10),
		AfxGetApp()->GetProfileInt("",KEY_VIDEO_BKCOLOR,0x00ff0000));
	if(ret)
		m_mainFrm.Output(IDS_LOG_VIDEO_START,connID,outgoing?"发送":"接收",CodecName);
	return ret;
}

void CMCUEndPoint::OnUseGatekeeper(enum UseGKResult result,const char* name_GK)
{
	m_findingGK=FALSE;
}

CRoom* CMCUEndPoint::AddRoom(CString name)
{//增加指定名称的会议
	if(name.GetLength()==0)//default room
		name=AfxGetApp()->GetProfileString("",KEY_DEFAULT_ROOM,DEFAULT_ROOM);
	//查找会议列表,看会议是否已经存在
	for(int i=0;i<m_roomList.GetSize();i++)
	{
		CRoom *p=m_roomList.GetAt(i);
		if(p&&p->GetName().CompareNoCase(name)==0)
			return p;
	}
	
	//新建会议
	CRoom * room=new CRoom;
	room->SetName(name);
	m_roomList.Add(room);
	CListCtrl &listCtrl=m_mainFrm.GetRoomListCtrl();
	int index=listCtrl.InsertItem(listCtrl.GetItemCount(),name);
	listCtrl.SetItemData(index,(DWORD)room);
	listCtrl.SetItemText(index,1,"0");

	m_mainFrm.Output(IDS_LOG_ADDROOM,room->GetName());
	return room;
}

BOOL CMCUEndPoint::RemoveRoom(LPCTSTR name)
{//删除会议
	for(int i=0;i<m_roomList.GetSize();i++)
	{
		CRoom *p=m_roomList.GetAt(i);
		if(p&&p->GetName().CompareNoCase(name)==0)
		{
			if(p->GetMemberCount()==0)
			{				
			
				m_roomList.RemoveAt(i);
				CListCtrl &listCtrl=m_mainFrm.GetRoomListCtrl();
				for(int j=0;j<listCtrl.GetItemCount();j++)
					if(listCtrl.GetItemData(j)==((DWORD)p))
						listCtrl.DeleteItem(j);
				delete p;
				m_mainFrm.Output(IDS_LOG_REMOVEROOM,name);
				return TRUE;
			}
			break;
		}
	}
	return FALSE;
}

BOOL CMCUEndPoint::AddMember(DWORD connID, LPCTSTR RoomID)
{//把终端加入指定名称的会议

	//尝试新建会议
	CRoom *room=AddRoom(RoomID);
	if(room==NULL)
	{		
		return FALSE;
	}
	if(room->GetMemberCount()>=AfxGetApp()->GetProfileInt("",KEY_ROOM_SIZE,DEFAULT_ROOM_SIZE))
	{//会议已满
		m_mainFrm.Output(IDS_LOG_ROOMFULL,room->GetName(),AfxGetApp()->GetProfileInt("",KEY_ROOM_SIZE,DEFAULT_ROOM_SIZE),connID);
		
		return FALSE;
	}
	CDWordArray& members=room->GetMembers();
	members.Add(connID);
	SetConnectionData(connID,(DWORD)room);
	//更新成员列表
	CListCtrl& roomListCtrl=m_mainFrm.GetRoomListCtrl();
	for(int i=0;i<roomListCtrl.GetItemCount();i++)
	{
		if(roomListCtrl.GetItemText(i,0).CompareNoCase(room->GetName())==0)
		{
			CString num;
			num.Format("%d",room->GetMemberCount());
			roomListCtrl.SetItemText(i,1,num);
			break;
		}
	}
	int index=roomListCtrl.GetNextItem(-1,LVNI_SELECTED);
	if(index>=0&&roomListCtrl.GetItemData(index)==((DWORD)room))
	{
		CListCtrl& memberListCtrl=m_mainFrm.GetMemberListCtrl();
		int index=memberListCtrl.InsertItem(memberListCtrl.GetItemCount(),GetRemoteName(connID));
		if(index>=0)
		{
			memberListCtrl.SetItemData(index,connID);
			char str[256]="";
			GetRemoteAddress(connID,str,256);
			memberListCtrl.SetItemText(index,1,str);
			GetRemoteApplication(connID,str,256);
			memberListCtrl.SetItemText(index,2,str);
			memberListCtrl.SetItemData(index,connID);
		}
	}
	m_mainFrm.Output(IDS_LOG_ADDTOROOM,connID,room->GetName());
	return TRUE;
}

CString CMCUEndPoint::GetRemoteName(DWORD connID)
{
	CString ret;
	char name[256]="";
	GetRemotePartyName(connID,name,256);
	ret=name;
	int i=ret.ReverseFind('[');
	if(i>=0)
	{
		ret.Delete(i,ret.GetLength()-i);
		ret.TrimRight(' ');
	}
	return ret;

}

BOOL CMCUEndPoint::RemoveMember(DWORD connID)
{//成员离开会议
	CRoom *room=(CRoom*)GetConnectionData(connID);
	if(room==NULL)
		return FALSE;
	room->RemoveMember(connID);
	
	CListCtrl &roomListCtrl=m_mainFrm.GetRoomListCtrl();

	int index=roomListCtrl.GetNextItem(-1,LVNI_SELECTED);
	if(index>=0&&roomListCtrl.GetItemText(index,0).CompareNoCase(room->GetName())==0)
	{
		CListCtrl& memberListCtrl=m_mainFrm.GetMemberListCtrl();
		for(int i=0;i<memberListCtrl.GetItemCount();i++)
		{
			if(memberListCtrl.GetItemData(i)==connID)
			{
				memberListCtrl.DeleteItem(i);
				break;
			}
		}
	}
	m_mainFrm.Output(IDS_LOG_LEAVE_ROOM,connID,room->GetName());
	for(int i=0;i<roomListCtrl.GetItemCount();i++)
	{
		if(roomListCtrl.GetItemData(i)==((DWORD)room))
		{
			if(room->GetMemberCount()==0)
			{
				RemoveRoom(room->GetName());
			}
			else
			{				
				CString num;
				num.Format("%d",room->GetMemberCount());
				roomListCtrl.SetItemText(i,1,num);
				break;
			}
		}
	}

	return TRUE;
}

⌨️ 快捷键说明

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