📄 mcuendpoint.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 + -