会捷通客户端 SDK (Windows 版) 开发文档

会捷通客户端 SDK (Windows 版) 开发文档

1. 概述

gallery-view

会捷通客户端 SDK 是⼀款视频会议软终端开发套件,开发者可以利⽤本 SDK 开发出具有清晰流畅的⾳视频体验和⾼清内容协作的⾳视频会议终端应用。会捷通客户端 SDK 具备强⼤的⽹络适应性,和独特的⾳视频抗⽹络丢包算法,配合会捷通云视讯平台使⽤,可以保证在 30% ⽹络丢包环境下视频依然清晰流畅,即使⽹络丢包⾼达 50%,依然可以保证⾳频通畅。 会捷通客户端 SDK 提供了丰富,⽽且简单易⽤的 API 接⼝。开发者不需要掌握丰富的⾳视频和信令相关知识,也可以使⽤本 SDK 开发出专业的视频会议软终端应用。 本⽂档详细介绍了 SDK 的各项功能,以及它们的使⽤⽅法。

本文档对应 SDK 版本为 1.3

1.1 系统要求

  • Windows 7 SP1 及以上

1.2 开发环境

  • Visual Studio 2015
  • Visual Studio 2013

注意

部分较老版本 Windows 7 SP1 系统可能没有安装 Windows 7 更新程序 KB2999226 (update for Universal C Runtime (CRT) ),这可能导致应用无法正常启动,解决办法是下载并安装 KB2999226

官网下载地址 - https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=49077 (opens new window)

另外,微软官方建议应用打包时,包含 UCRT dll 文件。

App-local deployment of the Universal CRT is supported. To obtain the binaries for app-local deployment, install the Windows Software Development Kit (SDK) for Windows 10 (opens new window). The binaries will be installed to C:\Program Files (x86)\Windows Kits\10\Redist\ucrt. You will need to copy all of the DLLs with your app (note that the set of DLLs are necessary is different on different versions of Windows, so you must include all of the DLLs in order for your program to run on all supported versions of Windows).

1.3 示例代码

  • 示例代码下载地址 GitHub (opens new window)

  • 示例应用下载地址 示例应用 (opens new window)

  • 代码构成

    • 工程根目录

      • EasyVideoWin.sln - C# solution

      • EasyVideoWin - Demo 工程目录

        • EasyVideoWin.csproj - C# project
        • CustomControls - 该目录下包含工程中用到的自定义控件
        • Helpers - 该目录下包含工程中用到的通用工具程序
        • Model - 该目录下包含工程中用到的SDK相关的逻辑处理程序
        • Properties - 工程属性目录
        • Resources - 资源目录
        • Rest - 该目录包含与其他服务器通讯的 rest api 相应类的定义
        • View - 该目录包含UI组件的定义
        • ViewModel - 该目录下包含与View对应的绑定数据的程序。
        • WinForms - 该目录下包含相关window forms程序
      • ManagedEVSdk - 对EVSDK进行封装的托管C++程序工程目录。

        • ManagedEVSdk.sln - C++ solution
        • ManagedEVSdk.vcxproj - C++ project
        • Include - 头文件目录
        • Source - 源文件目录
      • sdk_libs

        • files - 该目录下包含EVSDK里用到的文件
        • include - EVSDK库应用开发用到的头文件
        • lib - EVSDK库文件

1.4 编译示例工程

  • 首先用 Visual Studio 2013 打开解决方案 EasyVideoWinSdk\EasyVideoWinSdk.sln,将编译 Configuration 修改为 Release,然后重新编译解决方案,生成的库文件和需要的 EVSDK 的相关文件将会一并输出到项目根目录下的 EasyVideoWin\bin\ 目录下
  • 然后用 Visual Studio 2015 打开项目根目录下的 EasyVideoWin.sln,然后重新编译解决方案,编译成功即可运行

编译过程帮助视频

帮助视频 (opens new window)

开发工具

注意:开发工具分别为 Visual Studio 2013 和 Visual Studio 2015,并非 Blend for Visual Stuido 2013 和 Blend for Visual Studio 2015

2. 快速定制化

如果我们的示例工程满足您的产品需要,但是需要更换应用 Logo 以及公司版权信息,仅需进行非常少量的图片替换,以及本地化语言文件的修改,即可构建出符合您需要的专属定制化客户端应用。

2.1 替换 logo 等图片资源文件

开发者可以根据实际需要对EasyVideoWin\Resources\Icons下的图片资源文件进行替换,比如 APP logo,屏蔽视频的背景图片等。

2.2 修改 APP 名字、公司名称、版权信息等文本内容

开发者可以通过修改 EasyVideoWin\Properties\AssemblyInfo.cs 中的内容,实现 APP 名称、公司名称、版权信息的替换。另外,还需要对 EasyVideoWin\Resources\Languages下的en-US.xaml和zh-CN.xaml 中的其他文字内容进行替换。

[assembly: AssemblyTitle("HexMeetHJT")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("HexMeet")]
[assembly: AssemblyProduct("HexMeetHJT")]
[assembly: AssemblyCopyright("Copyright © HexMeet 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

2.3 修改程序的默认配置文件

开发者可以通过修改 EasyVideoWin\Properties\Settings.settings 中的内容,实现对公有云服务器地址、软件升级服务器地址等的默认配置。

<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="EasyVideoWin.Properties" GeneratedClassName="Settings">
  <Profiles />
  <Settings>
    <Setting Name="Language" Type="System.String" Scope="User">
      <Value Profile="(Default)" />
    </Setting>
    <Setting Name="ConfInfoAddress" Type="System.String" Scope="User">
      <Value Profile="(Default)" />
    </Setting>
    <Setting Name="ConfManagementAddress" Type="System.String" Scope="User">
      <Value Profile="(Default)" />
    </Setting>
    <Setting Name="URLProtocol" Type="System.String" Scope="User">
      <Value Profile="(Default)">hexmeethjt</Value>
    </Setting>
    <Setting Name="CloudServerAddress" Type="System.String" Scope="User">
      <Value Profile="(Default)">cloud.hexmeet.com</Value>
    </Setting>
    <Setting Name="CloudLocationServerAddress" Type="System.String" Scope="User">
      <Value Profile="(Default)">https://cloudcenter.hexmeet.com</Value>
    </Setting>
    <Setting Name="SoftwareUpdateAddress" Type="System.String" Scope="User">
      <Value Profile="(Default)">http://swinfo.cninnovatel.com</Value>
    </Setting>
    <Setting Name="SoftwareUpdateFlag" Type="System.String" Scope="User">
      <Value Profile="(Default)">windows</Value>
    </Setting>
    <Setting Name="SoftwareUpdateBundleId" Type="System.String" Scope="User">
      <Value Profile="(Default)">com.hexmeet.hjt</Value>
    </Setting>
    <Setting Name="SoftwareUpdateAppInfo" Type="System.String" Scope="User">
      <Value Profile="(Default)">appinfo.json</Value>
    </Setting>
    <Setting Name="SoftwareUpdateAppInfoPrefix" Type="System.String" Scope="User">
      <Value Profile="(Default)" />
    </Setting>
  </Settings>
</SettingsFile>

3. 开发入门

3.1 封装SDK - ManagedEVSdk

由于 EVSDK 库是 C++ 代码编写的,接口也是c++格式的。为了更方便的在 C# 中应用该库,该例程对 EVSDK 库用托管 C++ 代码进行了二次封装,封装后的 ManagedEVSdk 能够非常便利的应用在C#程序中,下面说到的关于 SDK 的应用和说明都是针对ManagedEVSdk来说的。

3.1.1 SDK 功能

SDK主要提供了下面的功能:

1)登录认证

2)登录用户的用户名和密码的修改

3)音频设备和视频设备的设置

4)加入会议

5)静音、屏蔽本地视频、发送双流等操作

3.1.2 SDK 调用方式

SDK中的方法调用有同步调用和异步调用两种方式。对于异步方法调用,要注册监听相应的回调事件,同时也要对通用出错回调事件EventError进行处理。

3.1.3 SDK 包装接口类 EVSdkWrapper

SDK对外提供的调用接口函数和监听事件都包装在类 EVSdkWrapper 中。

3.2 创建实例和初始化 SDK

首先编译工程 ManagedEVSdk,生成 ManagedEVSdk.dll,然后在工程 EasyVideoWin 中引用 ManagedEVSdk.dll,接下来就可以应用 SDK了。

3.2.1 创建 EVSdkWrapper 实例

在使用SDK前,首先要生成类EVSdkWrapper的一个实例,通过调用类 EVSdkWrapper 中的静态函数 CreateInstance() 生成

/**
 创建 EVSdkWrapper 实例
 */
public static EVSdkWrapper CreateInstance();

3.2.2 初始化 SDK

在调用SDK前,先要对SDK做相应的初始化,下面是本例程对SDK的相应初始化操作。

在程序 LoginWindow.xaml.cs 中初始化SDK:

private void InitEVSdk()
{
    try
    {
        log.Info("Begin to init evsdk");
        bool first_run = false;
        string appDataFolder = Utils.GetConfigDataPath();
        if (!Directory.Exists(appDataFolder))
        {
            // Try to create the directory.
            Directory.CreateDirectory(appDataFolder);
        }

        if (!File.Exists(System.IO.Path.Combine(appDataFolder, "hexmeetrc")))
        {
            log.Info("SDK Configuration doesn't exist. It must be the 1st run after installation.");
            first_run = true;
        }

        EVSdkManager.Instance.CreateEVEngine();
        EVSdkManager.Instance.SetLog(ManagedEVSdk.Structs.EV_LOG_LEVEL_CLI.EV_LOG_LEVEL_MESSAGE, appDataFolder, "evsdk", 20 * 1024 * 1024);
        EVSdkManager.Instance.EnableLog(true);
        EVSdkManager.Instance.Initialize(appDataFolder, "hexmeetrc");
        string rootCAPath = Utils.GetRootCAPath();
        EVSdkManager.Instance.SetRootCA(rootCAPath);
        EVSdkManager.Instance.EnableWhiteBoard(true);
        CallController.Instance.SetMaxRecvVideo(MAX_RECV_VIDEO_NUMBER);
        CallController.Instance.SetPeopleHighFrameRate(Helpers.Utils.GetOpenHighFrameRateVideo());

        if (first_run)
        {
            // Set the default call rate to 2M 
            EVSdkManager.Instance.SetBandwidth(2048);
            log.Info("Set Default Call Rate to 2M at 1st run");
        }

        string userAgentName = "HexMeet EasyVideo Win";
        // get correct product version for user agent.
        string version = System.Windows.Forms.Application.ProductVersion;
        EVSdkManager.Instance.SetUserAgent(userAgentName, version);
        log.Info("Init sdk end.");
    }
    catch(Exception e)
    {
        log.ErrorFormat("Failed to init ev sdk, exception:{0}", e.Message);
        System.Environment.Exit(1);
    }
}

下面是对初始化SDK用到的SDK的api的描述说明。

3.2.2.1 创建SDK引擎

首先创建SDK引擎,才能使用对SDK的调用

/**
 创建SDK引擎
 */
public void CreateEVEngine();

3.2.2.2 日志输出配置

设置SDK日志输出的相关参数配置

/**
 用于设置sdk日志相关参数配置

 @param level 日志等级
 @param logPath 日志存放位置
 @param logFileName 日志名称
 @param maxFileSize 日志大小
 */
void EVEngineSetLog(EV_LOG_LEVEL_CLI level, string logPath, string logFileName, uint maxFileSize);

3.2.2.3 启用/禁用输出日志

是否启用SDK输出日志

/**
 是否启用SDK输出日志

 @param enable 是否输出日志
 */
public void EVEngineEnableLog(bool enable);

3.2.2.4 初始化

使用相关配置对SDK进行初始化,如果配置文件内容为空则使用默认配置

/**
 使用配置文件初始化SDK

 @param configPath sdk配置文件的路径
 @param configFileName sdk配置文件名称
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineInitialize(string configPath, string configFileName);

3.2.2.5 设置证书文件

设置加密传输时的证书文件,在登录或匿名入会前可以根据需要设置该项的值,该调用在呼叫过程设置不会立即生效

/**
 设置证书文件

 @param rootCaPath 证书文件路径名
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetRootCA(string rootCaPath);

3.2.2.6 启用/禁用白板

设置是否启用白板,该调用在程序启动时设置一次即可,在使用过程中不要设置

/**
 是否启用白板

 @param enable 是否启用白板
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineEnableWhiteBoard(bool enable);

3.2.2.7 设置用户代理

设置用户代理信息

/**
 设置用户代理信息

 @param company 终端类型的有关信息
 @param version 版本信息
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetUserAgent(string company, string version);

3.2.2.8 启用加密

设置是否启用加密通信,在登录或匿名入会前可以根据需要设置该项的值,该调用在呼叫过程设置不会立即生效。当启用加密时,要调用 EVEngineSetRootCA 设置证书

/**
 设置是否启用加密通信

 @param enable 是否启用加密通信
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineEnableSecure(bool enable);

在完成上面相关的初始化操作后,就可以匿名加入会议或者登录到服务器进行有关的操作了。

3.2.3 注册监听事件

在创建EVSdkWrapper的实例后,同时要注册监听下面的SDK回调事件以便做出相应的处理

3.2.3.1 错误回调事件

当SDK监测到有错误发生的时候,会触发回调事件 EventError

/**
 错误回调事件
 @param   EVErrorCli 类型变量
 */
public event Action<EVErrorCli> EventError;

3.2.3.2 警告回调事件

当SDK监测到有警告发生的时候,会触发回调事件 EventWarn

/**
 警告回调事件
 @param   EVWarnCli 类型变量
 */
public event Action<EVWarnCli> EventWarn;

3.2.3.3 网络状态回调事件

当SDK网络状态发生的时候,会触发回调事件 EventNetworkState

/**
 警告回调事件
 @param   bool 类型变量,表示网络是否可用
 */
public event Action<bool> EventNetworkState;

3.3 用户登录及相关操作

用户通过用户名和密码登录到服务器,能够获取用户信息、修改有关信息,接收入会邀请等操作。

3.3.1 登录

用户正常登录会执行:定位->登录->注册视频服务(其中注册视频服务由 SDK 处理)

/**
 用户定位登录(包含定位跟登录)

 @param locationServer 定位服务器
 @param port 端口号
 @param username 用户名
 @param password 密码
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineLoginWithLocation(string locationServer, uint port, string username, string password);

/** 登录后会收到SDK以下回调 */
1)出现错误会回调 
public event Action<EVErrorCli> EventError;

2)成功会回调
/**
 登录成功回调事件
 
 @param EVUserInfoCli类型的变量, 用户信息
*/
public event Action<EVUserInfoCli> EventLoginSucceed;

/**
 注册信息回调事件
 
 @param bool类型的变量, 是否注册成功,只有注册成功才能进行呼叫
*/
public event Action<bool> EventRegister;
uml diagram

登录成功后,就可以下载当前用户的头像、修改头像、修改用户名、修改密码、加入会议等相关操作。

3.3.1 下载用户头像

下载用户保存在服务器上的头像,该头像可以设置在呼叫中,当屏蔽本地视频时,可以让接收方看到该头像

/**
 下载用户头像

 @param path 头像保存在本地的路径
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public void DownloadUserImage(string path);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调 
public event Action<EVErrorCli> EventError;

2)成功会回调
/**
 @param string类型的变量, 头像保存在本地的路径
*/
public event Action<string> EventDownloadUserImageComplete;

3.3.2 修改用户头像

修改用户保存在服务器上的头像

/**
 下载用户头像

 @param path 头像保存在本地的路径
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineUploadUserImage(string path);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调, EVErrorCli.action 的值为 uploadUserImage
public event Action<EVErrorCli> EventError;

2)成功会回调
/**
 @param string类型的变量, 头像保存在本地的路径
*/
public event Action<string> EventUploadUserImageComplete;

3.3.3 修改密码

修改用户保存在服务器上的头像

/**
 修改密码
 
 @param oldPassword 原密码
        newPassword 新密码
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineChangePassword(string oldPassword, string newPassword);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.3.4 修改用户显示名称

修改用户的显示名称,当加入会议时,如果没有设置在会议中的显示名称,则显示该名称

/**
 修改密码
 
 @param displayName 新名称
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineChangeDisplayName(string displayName);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调, EVErrorCli.action 的值为 changeDisplayName
public event Action<EVErrorCli> EventError;

3.3.5 获取用户信息

获取用户信息,包括部门,显示名称等

/**
 获取用户信息
 
 @param userInfo 类EVUserInfoCli的引用
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineGetUserInfo(ref EVUserInfoCli userInfo);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.3.6 入会邀请回调事件

用户登录后,注册监听入会邀请回调事件,将会入会邀请的信息,用户可以选择调用加入会议API "EVEngineJoinConference"入会或者拒绝入会

/**
 入会邀请回调事件
        
 @param EVCallInfoCli类型变量,呼叫信息
 */
public event Action<EVCallInfoCli> EventJoinConferenceIndication;

3.3.7 登出

用户登录完成相应的操作后,需要调用登出api

/**
 登出
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineLogout();

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.3.8 获取用户显示名称

获取用户显示名称

/**
 获取用户显示名称
 
 @return 返回用户显示名称
 */
public string EVEngineGetDisplayName();

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.4 设备管理

SDK提供了对本地音视频设备的获取,设置等接口。

3.4.1 获取设备列表

根据设备类型,获取当前可用的设备列表

/**
 获取设备列表
 
 @param type 设备类型
        
 @return 当前可用的设备列表
 */
public EVDeviceCli[] EVEngineGetDevices(EV_DEVICE_TYPE_CLI type);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.4.2 获取当前使用设备

根据设备类型,获取当前正在使用的设备

/**
 获取当前使用设备
 
 @param type 设备类型
        
 @return 当前正在使用可用设备
 */
EVDeviceCli EVEngineGetDevice(EV_DEVICE_TYPE_CLI type);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.4.3 设置使用设备

根据设备类型,设置APP要使用的设备。

/**
 设置要使用的设备
 
 @param type 设备类型
        id 要使用的设备id
        
 @return 无
 */
void EVEngineSetDevice(EV_DEVICE_TYPE_CLI type, uint id);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.4.4 启用获取麦克音量值

启用或禁用获取麦克的音量值,只有启用后,才能调用获取麦克音量值的大小

/**
 启用或禁用获取麦克的音量大小值
 
 @param enale 启用或禁用获取麦克音量值
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineEnableMicMeter(bool enable);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.4.5 获取麦克输入音量值

获取当前使用的麦克的音量值

/**
 获取麦克输入的音量值
 
 @param 无
        
 @return 音量值
 */
public float EVEngineGetMicVolume();

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.5 视频及内容窗口设置

通过设置本地视频、远端视频、接收内容的窗口,就能在相应的窗口显示对应的视频画面。

3.5.1 设置本地视频窗口

设置本地视频窗口句柄,本地摄像头采集到的视频流将显示在该窗口

/**
 设置本地视频窗口
 
 @param id 窗口句柄
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetLocalVideoWindow(IntPtr id);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.5.2 设置远端视频窗口

设置远端视频窗口句柄,接收到的远端视频流将显示在这些窗口

/**
 设置本地视频窗口
 
 @param ids 窗口句柄数组
        size 窗口句柄数组长度
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetRemoteVideoWindow(IntPtr[] ids, uint size);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.5.3 设置接收内容窗口

设置接收内容窗口句柄,接收到的内容视频流将显示在该窗口

/**
 设置接收内容视频窗口
 
 @param id 窗口句柄
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetRemoteContentWindow(IntPtr id);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.5.4 设置发送内容窗口

设置发送内容窗口句柄,该窗口的内容将被发送到远端

/**
 设置发送内容窗口
 
 @param id 窗口句柄
        mode 内容模式
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetLocalContentWindow(IntPtr id, EV_CONTENT_MODE_CLI mode);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.5.5 预览本地视频

如果在会议中,设置本地视频窗口后就可以在对应的窗口看到本地的视频流了。如果没有在呼叫中,要预览本地视频流就调用预览本地视频接口来打开摄像头,在使用完毕需要关闭。

/**
 预览本地视频
 
 @param enable 是否预览本地视频
        
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineEnablePreview(bool enable);

/** 调用该API后会收到SDK以下回调 */
1)出现错误会回调
public event Action<EVErrorCli> EventError;

3.6 呼叫参数设置

在进行呼叫前,可以设置呼叫的相关参数

3.6.1 最大视频流接收路数

设置视频流的最大接收路数,该调用在呼叫过程设置不会立即生效

/**
 设置视频流的最大接收路数

 @param num 视频流的最大接收路数
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetMaxRecvVideo(uint num);

3.6.2 主流高帧率

获取主流是否启用高帧率

/**
 获取主流是否启用高帧率
 
 @return 是否启用了高帧率
 */
public bool EVEngineHighFPSEnabled();

设置主流是否启用高帧率,该调用在呼叫过程设置不会立即生效

/**
 设置主流是否启用高帧率

 @param enable 主流是否启用高帧率
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineEnableHighFPS(bool enable);

3.6.3 呼叫带宽

获取当前呼叫带宽

/**
 获取当前呼叫带宽
 
 @return 带宽值
 */
public uint EVEngineGetBandwidth();

设置呼叫过程中带宽的值,该调用在呼叫过程设置不会立即生效

/**
 设置呼叫过程中带宽的值

 @param kbps 带宽值,一般取值384,512,768,1024,1536,2048
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetBandwidth(uint kbps);

3.6.4 主流高清

获取主流是否启用高清

/**
 获取主流是否启用高清
 
 @return 是否启用了高清
 */
public bool EVEngineHDEnabled();

设置主流是否启用高清,该调用在呼叫过程设置不会立即生效

/**
 设置主流是否启用高清

 @param enable 主流是否启用高清
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineEnableHD(bool enable);

3.6.5 设置分屏能力集

设置分屏的能力集,该调用在呼叫过程设置不会立即生效

/**
 设置分屏的能力集

 @param mode 分屏模式
 @param types 能力集合
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetLayoutCapacity(EV_LAYOUT_MODE_CLI mode, EV_LAYOUT_TYPE_CLI[] types);

3.7 加入会议

做完相应的准备工作后就可以进行呼叫加入会议了。加入会议的方式有以下几种:

3.7.1 定位匿名方式入会

用户匿名方式入会的时候会执行:定位到会议管理服务器->匿名登录->注册视频服务->呼叫 (其中匿名登录以及注册视频服务均由SDK 处理)。该方式不用用户进行登录。

定位服务、匿名登录、注册视频服务统一都由SDK处理只需要调用以下 API

/**
 用户执行定位匿名登录入会

 @param locationServer 定位服务器
 @param port 端口号
 @param conferenceNumber 会议号码
 @param displayName 用户在会议中的名称
 @param password 会议密码
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
int EVEngineJoinConferenceWithLocation(string locationServer, uint port, string conferenceNumber, string displayName, string password);

当调用了匿名入会的 API 后,会收到 SDK 回调:入会成功或者入会失败。需要做出处理

1)出现错误会回调
public event Action<EVErrorCli> EventError;

2)登录成功回调
public event Action<EVUserInfoCli> EventLoginSucceed;

3) 入会成功会回调
/**
 入会成功回调事件

 @param EVCallInfoCli类型变量,表示当前呼叫信息
 */
public event Action<EVCallInfoCli> EventCallConnected;

4) 入会失败会回调
/**
 入会结束回调事件

 @param EVCallInfoCli类型变量,表示当前呼叫信息
        如果该变量的 err字段不为空,并且 err.type == ManagedEVSdk.ErrorInfo.EV_ERROR_TYPE_CLI.EV_ERROR_TYPE_CALL && err.code == (int)ManagedEVSdk.ErrorInfo.EV_CALL_ERROR_CLI.EV_CALL_INVALID_PASSWORD, 则表示加入该会议时的密码不正确,需要重新输入密码加入会或者直接结束呼叫
 */
public event Action<EVCallInfoCli> EventCallEnd;

uml diagram

3.7.2 直接匿名方式入会

相对于定位匿名方式入会,直接匿名方式入会直接连接到会议管理服务器,其他的步骤和定位匿名入会方式一样

/**
 用户执行直接匿名登录入会

 @param server 会议管理服务器
 @param port 端口号
 @param conferenceNumber 会议号码
 @param displayName 用户在会议中的名称
 @param password 会议密码
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineJoinConference(string server, uint port, string conferenceNumber, string displayName, string password);


3.7.3 登录入会

用户登录后, 可以直接呼入当前服务器上的会议。调用该函数之后的后续处理操作同匿名入会方式。

/**
 用户执行登录入会

 @param conferenceNumber 会议号码
 @param displayName 用户在会议中的名称
 @param password 会议密码
 @param type svc呼叫类型,此处设为 EV_SVC_CALL_CONF
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineJoinConference(string number, string displayName, string password, EV_SVC_CALL_TYPE_CLI type);

3.7.4 入会回调事件

在调用加入会议的API前,需要监听以下回调事件,在入会成功后,会触发下面的回调事件

3.7.4.1 网络质量状态

当成功入会后,SDK 会监测当前的网络质量状态,当发生变化时,会触发该事件

/**
 网络质量状态事件
 @param float型的变量,表示网络质量的值,取值为 1-5,数值越大网络质量越好
 
 @return 带宽值
 */
public event Action<float> EventNetworkQuality;
3.7.4.2 内容接收事件

当发送内容成功或者接收到其他终端发送的内容后,SDK 会触发回调事件

/**
 发送或接收内容回调事件

 @param EVContentInfoCli类型的变量,表示内容信息
 */
public event Action<EVContentInfoCli> EventContent;
3.7.4.3 分屏信息事件

当成功入会后,SDK 会触发分屏信息回调事件

/**
 分屏信息回调事件

 @param EVLayoutIndicationCli类型的变量,表示分屏信息
 */
public event Action<EVLayoutIndicationCli> EventLayoutIndication;
3.7.4.4 分屏中终端信息事件

当成功入会后,SDK 会触发分屏中的终端信息回调事件

/**
 分屏中的终端信息回调事件

 @param EVSiteCli类型的变量,表示终端信息
 */
public event Action<EVSiteCli> EventLayoutSiteIndication;
3.7.4.5 分屏中发言者信息事件

当成功入会后,SDK 会触发分屏中的发言者信息回调事件

/**
 分屏中的发言者信息回调事件

 @param EVLayoutSpeakerIndicationCli类型的变量,表示发言者信息
 */
public event Action<EVLayoutSpeakerIndicationCli> EventLayoutSpeakerIndication;
3.7.4.6 录制信息事件

当会议进行录制的时候,SDK 会触发录制信息回调事件

/**
 录制信息回调事件

 @param EVRecordingInfoCli类型的变量,表示录制信息
 */
public event Action<EVRecordingInfoCli> EventRecordingIndication;
3.7.4.7 字幕信息事件

当会议的字幕信息发生变化时候,SDK 会触发字幕信息回调事件

/**
 字幕信息回调事件

 @param EVMessageOverlayCli类型的变量,表示字幕信息
 */
public event Action<EVMessageOverlayCli> EventMessageOverlay;
3.7.4.7 白板信息事件

当会议的白板信息发生变化时候,SDK 会触发白板信息回调事件

/**
 白板信息回调事件

 @param EVWhiteBoardInfoCli类型的变量,表示白板信息
 */
public event Action<EVWhiteBoardInfoCli> EventWhiteBoardIndication;
3.7.4.8 麦克风已静音事件

当有人说话,但是当前麦克风已静音,SDK 会触发该回调事件

/**
 麦克风已静音回调事件
 */
public event Action EventMuteSpeakingDetected;
3.7.4.9 在线终端数量事件

当会议中的在线终端数量发生变化时,SDK 会触发该回调事件

/**
 在线终端数量事件
 
 @param int类型的变量,表示在线终端数量
 */
public event Action<int> EventParticipant;
3.7.4.10 远端静音提示

当会议中发生远端对该终端进行静音或者解除静音时,SDK 会触发该回调事件

/**
 远端静音提示
 
 @param int, 当取值为0时,表示远端静音,否则为远端解除静音
 */
public event Action<int> EventMicMutedShow;
3.7.4.11 P2P 呼叫的对端头像 URL

当接收到 P2P 呼叫时,收到主叫端的图像 URL 时,SDK 会触发该回调事件

/**
 P2P呼叫的对端头像 URL
 
 @param string, P2P 呼叫的对端头像 URL
 */
public event Action<string> EventPeerImageUrl;

3.7.5 P2P 呼叫

P2P 呼叫的基本流程如下图所示

uml diagram

用户登录后,本端A 可以从通讯录选择一个联系人对端B 进行 P2P 呼叫。

/**
 用户执行P2P呼叫

 @param number 用户 UID
 @param displayName 用户在会议中的名称
 @param password 会议密码
 @param type SVC 呼叫类型,此处设为 EV_SVC_CALL_P2P
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk. ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineJoinConference(string number, string displayName, string password, EV_SVC_CALL_TYPE_CLI type);

当本端A 执行 P2P 呼叫成功后会收到 EventCallConnected 回调事件,此时 EVCallInfoCli.svcCallType == EV_SVC_CALL_P2P 表示本端A 执行 P2P 连接成功,但是对端B 还没有做出响应
public event Action<EVCallInfoCli> EventCallConnected;

当对端 B 收到 P2P 呼叫后,会收到下面的回调事件

/**
 对端 B 收到 P2P 呼叫的回调

 @param EVCallInfoCli 类型变量,表示当前呼叫信息
 a. 当 EVCallInfoCli.svcCallAction == EV_SVC_INCOMING_CALL_RING && EVCallInfoCli.svcCallType == EV_SVC_CALL_P2P 时表示对端 B 正在接收到 P2P 呼叫,需要对端做出处理
 b. 当 EVCallInfoCli.svcCallAction == EV_SVC_INCOMING_CALL_CANCEL 时:
    1) 当(EVCallInfoCli.err.type == EV_ERROR_TYPE_CLI.EV_ERROR_TYPE_SDK && EVCallInfoCli.err.code == EV_ERROR_CLI.EV_CALL_TIMEOUT)时表示超时对端 B 没有接收呼叫;
    2) 其他情况表示本端 A 取消了呼叫
 */

public event Action<EVCallInfoCli> EventJoinConferenceIndication;

当对端B 收到P2P 呼叫后,可以做出下列的响应之一

1)调用 EVEngineJoinConference 加入P2P 呼叫
  /**
 用户执行P2P呼叫

 @param number 会议号码
 @param displayName 用户在会议中的名称
 @param password 会议密码
 @param type svc呼叫类型,此处设为 EV_SVC_CALL_P2P
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineJoinConference(string number, string displayName, string password, EV_SVC_CALL_TYPE_CLI type);

之后本端A 会收到回调事件 OnCallPeerConnected,表示对端B 成功加入
public void OnCallPeerConnected(EVCallInfo* info);

2)调用 EVEngineDeclineIncommingCall 拒绝呼叫
/**
 拒绝呼叫

 @param conferenceNumber 会议号码
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineDeclineIncommingCall(string conferenceNumber);

之后本端A 会收到EventCallEnd回调事件
/**
 入会结束回调事件

 @param EVCallInfoCli类型变量,表示当前呼叫信息
 当 EVCallInfoCli.err.type == EV_ERROR_TYPE_SDK 时:
 a. 如果此时 EVCallInfoCli.err.code == EV_CALL_TIMEOUT 表示呼叫超时自己结束呼叫
 b. 如果此时 EVCallInfoCli.err.code == EV_CALL_DECLINED 表示对端拒绝呼叫
 */
public event Action<EVCallInfoCli> EventCallEnd;

3) 对端 B 没有对呼叫做出相应,本端A 会收到 EventCallEnd 回调事件
/**
 入会结束回调事件

 @param EVCallInfoCli类型变量,表示当前呼叫信息
 此时 EVCallInfoCli.err.type == EV_ERROR_TYPE_SDK && EVCallInfoCli.err.code == EV_CALL_TIMEOUT 表示呼叫超时自己结束呼叫
 */
public event Action<EVCallInfoCli> EventCallEnd;

3.8 呼叫中操作

在成功入会后,可以对当前呼叫进行下面的操作:

3.8.1 本地视频设置

获取是否启用本地视频

/**
 获取是否启用本地视频
 
 @return 是否启用本地视频
 */
public bool EVEngineCameraEnabled();

设置本地视频是否可用

/**
 设置本地视频是否可用

 @param enable 是否启用本地视频
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineEnableCamera(bool enable);

3.8.2 静音设置

获取当前是否静音

/**
 获取是否静音
 
 @return 是否静音
 */
public bool EVEngineMicEnabled();

设置是否静音

/**
 设置是否静音

 @param enable 是否静音
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineEnableMic(bool enable);

3.8.3 申请发言

当本地被远端静音后,调用申请发言请求远端解除静音

/**
 请求远端解除静音

 @param val 请求远端是否解除静音
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineRequestRemoteUnmute(bool val);

3.8.4 分屏设置

设置呼叫过程中的分屏设置

/**
 设置分屏

 @param layout 分屏设置的参数值
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetLayout(EVLayoutRequestCli layout);

通过该调用可以将分屏设置为主讲模式和画廊模式

  • 主讲视图

主讲视图

设置主讲视图模式

/**
 设置视频模式(主讲模式、画廊模式)

 @param layout EVLayoutRequestCli
 @return API调用结果
 */
public int EVEngineSetLayout(EVLayoutRequestCli layout);
//示例代码里主讲视图模式下 主视频窗口可以显示为1x5的窗口模式
ManagedEVSdk.Structs.EVLayoutRequestCli layoutRequest = new ManagedEVSdk.Structs.EVLayoutRequestCli();
layoutRequest.mode = ManagedEVSdk.Structs.EV_LAYOUT_MODE_CLI.EV_LAYOUT_SPEAKER_MODE;
layoutRequest.max_type = ManagedEVSdk.Structs.EV_LAYOUT_TYPE_CLI.EV_LAYOUT_TYPE_5_4T_1B;
layoutRequest.page = EV_LAYOUT_PAGE_CLI.EV_LAYOUT_CURRENT_PAGE;
layoutRequest.max_resolution = new ManagedEVSdk.Structs.EVVideoSizeCli() { width = 0, height = 0 };
layoutRequest.windows_size = IntPtr.Zero == focusVideoWindow ? 0u : 1u;
layoutRequest.windows = new IntPtr[layoutRequest.windows_size];
if (layoutRequest.windows_size > 0)
{
    layoutRequest.windows[0] = focusVideoWindow;
}
for (int i = 1; i < layoutRequest.windows_size; ++i)
{
    layoutRequest.windows[i] = IntPtr.Zero;
}
EVEngineSetLayout(layoutRequest);

  • 画廊视图

画廊视图

设置画廊视图模式

/**
 设置视频模式(主讲模式、画廊模式)

 @param layout EVLayoutRequest对象
 @return API调用结果
 */
public int EVEngineSetLayout(EVLayoutRequestCli layout);
//示例代码里画廊视图模式下 主视频窗口可以显示为1x1、1x2、2x2、2x3、3x3的窗口模式(可根据需要调整窗口位置)
ManagedEVSdk.Structs.EVLayoutRequestCli layoutRequest = new ManagedEVSdk.Structs.EVLayoutRequestCli();
layoutRequest.mode = ManagedEVSdk.Structs.EV_LAYOUT_MODE_CLI.EV_LAYOUT_GALLERY_MODE;
layoutRequest.max_type = ManagedEVSdk.Structs.EV_LAYOUT_TYPE_CLI.EV_LAYOUT_TYPE_9;
layoutRequest.page = EV_LAYOUT_PAGE_CLI.EV_LAYOUT_CURRENT_PAGE;
layoutRequest.max_resolution = new ManagedEVSdk.Structs.EVVideoSizeCli() { width = 0, height = 0 };
layoutRequest.windows_size = IntPtr.Zero == focusVideoWindow ? 0u : 1u;
layoutRequest.windows = new IntPtr[layoutRequest.windows_size];
if (layoutRequest.windows_size > 0)
{
    layoutRequest.windows[0] = focusVideoWindow;
}
for (int i = 1; i < layoutRequest.windows_size; ++i)
{
    layoutRequest.windows[i] = IntPtr.Zero;
}
EVEngineSetLayout(layoutRequest);

3.8.5 呼叫状态

获取呼叫过程中的音频、视频、内容的相关参数值

/**
 设置呼叫过程中带宽的值

 @param stats 呼叫状态的引用
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineGetStats(ref EVStatsCli stats);

3.8.6 退出会议

使用完当前会议后,结束会议

/**
 结束会议
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineLeaveConference();

3.8.7 视频和纯语音设置

获取当前是否视频模式

/**
 获取是否视频模式
 
 @return int, 0 表示纯语音模式,1 为视频模式
 */
public int EVEngineVideoActive();

设置是否视频模式

/**
 设置是否视频模式

 @param int, 0 表示纯语音模式,1 为视频模式
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetVideoActive(int active);

3.8.8 改名

在呼叫过程中修改显示名称

/**
 在呼叫过程中修改显示名称

 @param string 修改后的显示名称
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSetInConfDisplayName(string displayName);

3.9 内容共享

3.9.1 发送内容

开始发送内容

/**
 发送内容
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSendContent();

当调用了发送内容的 API 后,会收到 SDK 回调:发送成功或者发送失败。需要做出处理

1)失败会回调
public event Action<EVErrorCli> EventError;

2)发送成功会回调
public event Action<EVContentInfoCli> EventContent;
uml diagram

在收到发送成功的回调消息后,需要调用API "EVEngineSetLocalContentWindow" 设置发送内容的窗口句柄

uml diagram

3.9.2 发送白板

发送白板

/**
 发送白板
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineSendWhiteBoard();

当调用了发送内容的 API 后,会收到 SDK 回调:发送成功或者发送失败。需要做出处理

1)失败会回调
public event Action<EVErrorCli> EventError;

2)发送成功会回调
public event Action<EVContentInfoCli> EventContent;
uml diagram

在收到发送成功的回调消息后,需要调用API "EVEngineSetLocalContentWindow" 设置发送内容的窗口句柄

uml diagram

3.9.3 结束发送内容

当完成发送内容或白板,调用该API停止发送

/**
 停止发送内容
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineStopContent();

当调用了结束发送内容的 API 后,会收到 SDK 回调:结束成功或者结束失败。需要做出处理

1)失败会回调
public event Action<EVErrorCli> EventError;

2)结束成功会回调
public event Action<EVContentInfoCli> EventContent;

3.9.4 共享内容声音

获取是否启用共享内容声音

/**
 获取是否启用共享内容声音
 
 @return 是否启用共享内容声音
 */
public bool EVEngineContentAudioEnabled();

设置是否启用共享内容声音

/**
 设置是否启用共享内容声音

 @param enable 是否启用共享内容声音
 
 @return 返回 SDK 处理结果,参考enum ManagedEVSdk.ErrorInfo.EV_ERROR_CLI
 */
public int EVEngineEnableContentAudio(bool enable);

4. 数据类和枚举类型

// 呼叫类型
public enum EV_CALL_TYPE_CLI
{
    EV_CALL_UNKNOWN = 0,	// 未知类型
    EV_CALL_SIP = 1,		// SIP呼叫
    EV_CALL_H323 = 2,		// H.323 呼叫
    EV_CALL_SVC = 3			// SVC 呼叫
}

// SVC 呼叫类型
public enum EV_SVC_CALL_TYPE_CLI
{
    EV_SVC_CALL_CONF = 0,	// 会议邀请呼叫
    EV_SVC_CALL_P2P = 1		// p2p 呼叫
}

// svc 呼叫动作
public enum EV_SVC_CALL_ACTION_CLI
{
    EV_SVC_NO_ACTION = 0,			// 没有呼叫动作
    EV_SVC_INCOMING_CALL_RING = 1,	// 呼入振铃
    EV_SVC_INCOMING_CALL_CANCEL = 2	// 呼入超时,取消呼叫
}

// 呼叫方向
public enum EV_CALL_DIR_CLI
{
    EV_CALL_OUTGOING = 0,	// 呼出
    EV_CALL_INCOMING = 1	// 呼入
}

// 呼叫状态
public enum EV_CALL_STATUS_CLI
{
    EV_CALL_STATUS_SUCCESS = 0,		// 呼叫成功
    EV_CALL_STATUS_ABORTED = 1,		// 呼叫中止
    EV_CALL_STATUS_MISSED = 2,		// 呼叫未接听
    EV_CALL_STATUS_DECLINED = 3		// 呼叫拒绝
}

// 媒体流类型枚举
public enum EV_STREAM_TYPE_CLI
{
    EV_STREAM_AUDIO = 0,//音频流
    EV_STREAM_VIDEO = 1,//视频流
    EV_STREAM_CONTENT = 2,//分享内容
    EV_STREAM_WHITE_BOARD = 3//白板
}

// 媒体流传输方向枚举
public enum EV_STREAM_DIR_CLI
{
    EV_STREAM_UPLOAD = 0,// 发送
    EV_STREAM_DOWNLOAD = 1//接收
}

// 接收或发送内容的状态
public enum EV_CONTENT_STATUS_CLI {
    EV_CONTENT_UNKNOWN      = 0 // 未知
    , EV_CONTENT_GRANTED    = 1 // 授予
    , EV_CONTENT_RELEASED   = 2 // 释放
    , EV_CONTENT_DENIED     = 3 // 拒绝
    , EV_CONTENT_REVOKED    = 4 // 撤回
}

//内容模式:
public enum EV_CONTENT_MODE_CLI
{
    EV_CONTENT_FULL_MODE = 0,   	// 当前窗口所在屏幕的内容都被发送出去
    EV_CONTENT_APPLICATION_MODE = 1 // 只有当前窗口的内容被发送出去
}

// 白板类型(目前仅支持 ACS 白板)
public enum class EV_WHITE_BOARD_TYPE_CLI
{
    EV_ACS_WHITE_BOARD = 0,		// ACS 白板
    EV_BELUGA_WHITE_BOARD = 1	// beluga 白板
};

/**
 错误信息类
 在触发EventError的回调后,首先根据 type 的值判断出是哪个类型的错误发生了,然后再根据错误码code定位具体的错误(参考下面的“错误码以及枚举类型”)。
 action 表示哪个调用触发了本次错误,具体的action的值请见EVSDK的头文件IEVEngine.h中的class EV_CLASS_API IEVEngine : public IEVCommon包含的函数名
 args 表示错误的包含的可能的参数
*/
public class EVErrorCli
{
    public EV_ERROR_TYPE_CLI type;  // 当前分为 sdk,location server,dorado server,call几类错误
	public string action;			// 表示哪个调用触发了本次错误
    public int code;				// 错误码
    public string msg;				// 错误消息描述
    public string[] args;			// 错误参数
    
    public EVErrorCli();

    public void Unmanaged2ManagedStruct(EVError* evErr);
}

// 警告类型
public enum EV_WARN_CLI {
    EV_WARN_NETWORK_POOR = 0					// 网络连接不稳定
    , EV_WARN_NETWORK_VERY_POOR = 1				// 网络连接很差
    , EV_WARN_BANDWIDTH_INSUFFICIENT = 2		// 网络带宽不足
    , EV_WARN_BANDWIDTH_VERY_INSUFFICIENT = 3	// 网络带宽严重不足
    , EV_WARN_NO_AUDIO_CAPTURE_CARD = 4			// 没有音频输入设备
    , EV_WARN_UNMUTE_AUDIO_NOT_ALLOWED = 5		// 当前会议禁止解除静音
    , EV_WARN_UNMUTE_AUDIO_INDICATION = 6		// 远端解除静音提示
}

// 警告信息类
public class EVWarnCli
{
    public EV_WARN_CLI code;	// 警告码
    public string msg;			// 警告信息描述

    public EVWarnCli();

    public void Unmanaged2ManagedStruct(EVWarn* evWarn);
}

// 视频分辨率
public class EVVideoSizeCli
{
    public int height;	// 视频高度
    public int width;	// 视频宽度

    public EVVideoSizeCli();

    public void Unmanaged2ManagedStruct(EVVideoSize* evVideoSize);
}

// 日志级别类型
public enum class EV_LOG_LEVEL_CLI
{
    EV_LOG_LEVEL_DEBUG = 0,		// 调试
    EV_LOG_LEVEL_MESSAGE = 1,	// 消息
    EV_LOG_LEVEL_WARNING = 2,	// 警告
    EV_LOG_LEVEL_ERROR = 3,		// 一般错误
    EV_LOG_LEVEL_FATAL = 4		// 严重错误
};

// 设备类型
public enum EV_DEVICE_TYPE_CLI
{
    EV_DEVICE_AUDIO_CAPTURE = 0, 	// 音频输入设备
    EV_DEVICE_AUDIO_PLAYBACK = 1, 	// 音频输出设备
    EV_DEVICE_VIDEO_CAPTURE = 2 	// 视频输入设备
}

// 设备信息类
public class EVDeviceCli
{
    public uint id;					// 设备 id
    public byte[] name;				// 设备名称
    public EV_DEVICE_TYPE_CLI type;	// 设备类型
    public string desc;				// 描述信息

    public EVDeviceCli();

    public void Unmanaged2ManagedStruct(EVDevice* evDevice);
}

// 分屏模式类型
public enum EV_LAYOUT_MODE_CLI {
    EV_LAYOUT_AUTO_MODE = 0,		// 自动分屏
    EV_LAYOUT_GALLERY_MODE = 1,		// 画廊模式
    EV_LAYOUT_SPEAKER_MODE = 2,		// 主讲模式
    EV_LAYOUT_SPECIFIED_MODE = 3	// 指定模式
};

// 分屏类型
public enum EV_LAYOUT_TYPE_CLI {
    EV_LAYOUT_TYPE_AUTO = -1,		// 自动分屏
    EV_LAYOUT_TYPE_1 = 101,			// 1分屏
    EV_LAYOUT_TYPE_2H = 201,		// 2个水平分屏(分屏大小按比例)
    EV_LAYOUT_TYPE_2V = 202,		// 2个竖直分屏(分屏大小按比例)
    EV_LAYOUT_TYPE_2H_2 = 203,		// 2个水平分屏(充满屏幕)
    EV_LAYOUT_TYPE_2V_2 = 204,		// 2个竖直分屏(充满屏幕)
    EV_LAYOUT_TYPE_2_1IN1 = 205,	// 2分屏(画中画)
    EV_LAYOUT_TYPE_2_1L_1RS = 207,	// 2分屏(左边1个大右边1小)
    EV_LAYOUT_TYPE_3_1T_2B = 301,	// 1上2下
    EV_LAYOUT_TYPE_3_2T_1B = 302, 	// 2上1下
    EV_LAYOUT_TYPE_3_1L_2R = 303,	// 1左2右边
    EV_LAYOUT_TYPE_3_2IN1 = 304,	// 3分屏,2个小分屏在1个大分屏中的画中画模式
    EV_LAYOUT_TYPE_1P2W = 305,		// 1上2下全屏
    EV_LAYOUT_TYPE_4 = 401,			// 2x2分屏
    EV_LAYOUT_TYPE_4_3T_1B = 402,	// 3上1下
    EV_LAYOUT_TYPE_4_1L_3R = 403,	// 1左3右
    EV_LAYOUT_TYPE_4_1T_3B = 404,	// 1上3下
    EV_LAYOUT_TYPE_4_3IN1 = 405,	// 3个小分屏在1个大分屏中的画中画模式
    EV_LAYOUT_TYPE_5_1L_4R = 501,	// 1左4右
    EV_LAYOUT_TYPE_5_4T_1B = 502,	// 4上1下
    EV_LAYOUT_TYPE_5_1T_4B = 503,	// 1上4下
    EV_LAYOUT_TYPE_6 = 601,			// 2x3按比例分屏
    EV_LAYOUT_TYPE_6W = 602,		// 2x3全屏
    EV_LAYOUT_TYPE_2P4W = 603,		// 2上4下全屏
    EV_LAYOUT_TYPE_6CP = 604,		// 1个大分屏,4个小分屏在右和下
    EV_LAYOUT_TYPE_8 = 801,			// 1个大分屏,7个小分屏在右和下
    EV_LAYOUT_TYPE_9 = 901,			// 3x3分屏
    EV_LAYOUT_TYPE_9_1IN_8OUT = 902,// 1个大分屏在中,4个小分屏在上,4个小分屏在下
    EV_LAYOUT_TYPE_9_8T_1B = 903,	// 1个大分屏在下,8个小分屏分2行在上
    EV_LAYOUT_TYPE_9_1T_8B = 904,	// 1个大分屏在上,8个小分屏分2行在下
    EV_LAYOUT_TYPE_10 = 1001,		// 2个大分屏在中,4个小分屏在上,4个小分屏在下
    EV_LAYOUT_TYPE_2TP8B = 1002,	// 2个大分屏在上,8个小分屏分2行在下
    EV_LAYOUT_TYPE_2CP4L4R = 1003,	// 2个大分屏在中,4个小分屏在左,4个小分屏在右
    EV_LAYOUT_TYPE_12W = 1201,		// 3x4全屏
    EV_LAYOUT_TYPE_13 = 1301,		// 1个大分屏居中,12个小分屏均匀分布在四周
    EV_LAYOUT_TYPE_1LTP12 = 1302,	// 1个大分屏在左上,12个小分屏均匀分布在右下
    EV_LAYOUT_TYPE_16 = 1601,		// 4x4分屏
    EV_LAYOUT_TYPE_1TLP16 = 1701,	// 当前不支持
    EV_LAYOUT_TYPE_1CP16 = 1702,	// 当前不支持
    EV_LAYOUT_TYPE_20 = 2001,		// 当前不支持
    EV_LAYOUT_TYPE_20_SQUARE = 2002,// 当前不支持
    EV_LAYOUT_TYPE_1TLP20 = 2101,	// 当前不支持
    EV_LAYOUT_TYPE_1CP20 = 2102,	// 当前不支持
    EV_LAYOUT_TYPE_25 = 2501,		// 当前不支持
    EV_LAYOUT_TYPE_30 = 3001,		// 当前不支持
    EV_LAYOUT_TYPE_30_SQUARE = 3002,// 当前不支持
    EV_LAYOUT_TYPE_36 = 3601		// 当前不支持
};

// 分屏的分页类型
public enum EV_LAYOUT_PAGE_CLI {
    EV_LAYOUT_CURRENT_PAGE = 0,	// 当前页
    EV_LAYOUT_PREV_PAGE = 1,	// 前一页
    EV_LAYOUT_NEXT_PAGE = 2		// 后一页
};

// 设置分屏请求
public class EVLayoutRequestCli
{
    public EVVideoSizeCli max_resolution;	// 最大分辨率,0表示不限制
    public EV_LAYOUT_TYPE_CLI max_type;		// 最大分屏类型,即最多支持分屏的个数
    public EV_LAYOUT_MODE_CLI mode;			// 分屏模式
    public EV_LAYOUT_PAGE_CLI page;			// 页数,每页的长度为5个分屏
    public IntPtr[] windows;				// 限制哪些分屏还在请求的分屏里面
    public uint windows_size;				// 限制的分屏数

    public EVLayoutRequestCli();

    public void Managed2UnmanagedStruct(EVLayoutRequest* evLayoutRequest);
}

// 分屏终端信息
public class EVSiteCli
{
    public ulong device_id;		// 终端设备id
    public bool is_local;		// 是否当前终端
    public bool mic_muted;		// 麦克是否被静音
    public string name;			// 终端名称
    public bool remote_muted;	// 是否被远端静音
    public IntPtr window;		// 对应的窗口句柄

    public EVSiteCli();

    public void Unmanaged2ManagedStruct(EVSite* site);
}

// 分屏信息
public class EVLayoutIndicationCli
{
    public EV_LAYOUT_MODE_CLI mode;			// 当前展示的分屏模式
    public bool mode_settable;				// 是否可以修改分屏模式
    public EV_LAYOUT_MODE_CLI setting_mode;	// 当前设置的分屏模式
    public EVSiteCli[] sites;				// 分屏终端列表
    public uint sites_size;					// 分屏终端列表的个数
    public int speaker_index;				// 发言者在分屏终端列表中的索引
    public string speaker_name;				// 发言者名称
    public EV_LAYOUT_TYPE_CLI type;			// 分屏类型

    public EVLayoutIndicationCli();

    public void Unmanaged2ManagedStruct(EVLayoutIndication* indication);
}

// 发言者信息
public class EVLayoutSpeakerIndicationCli
{
    public int speaker_index;			// 发言者在分屏终端列表中的索引
    public string speaker_name;			// 发言者名称

    public EVLayoutSpeakerIndicationCli();

    public void Unmanaged2ManagedStruct(EVLayoutSpeakerIndication* indication);
}

// 媒体统计信息
public class EVStreamStatsCli
{
    public ulong cum_packet;			// 累计丢包数
    public ulong cum_packet_loss;		// 累计丢包率
    public EV_STREAM_DIR_CLI dir;		// 媒体方向
    public float fps;					// 帧率
    public bool is_encrypted;			// 是否加密
    public string name;					// 名称
    public float nego_bandwidth;		// 协商速率
    public float packet_loss_rate;		// 丢包率
    public string payload_type;			// 编解码器
    public float real_bandwidth;		// 实际速率
    public EVVideoSizeCli resolution;	// 分辨率
    public uint ssrc;					// 该字段当前不用
    public EV_STREAM_TYPE_CLI type;		// 媒体类型

    public EVStreamStatsCli();

    public void Unmanaged2ManagedStruct(EVStreamStats* evStreamStats);
}

// 媒体统计信息列表
public class EVStatsCli
{
    public uint size;					// 媒体统计列表长度
    public EVStreamStatsCli[] stats;	// 媒体统计列表

    public EVStatsCli();

    public void Unmanaged2ManagedStruct(EVStats* evStats);
}

// 当前登录的服务器支持的功能
public class EVFeatureSupportCli
{
    public bool chatInConference;			// 是否支持聊天功能
    public bool contactWebPage;				// 是否支持联系人
    public bool p2pCall;					// 是否支持p2p呼叫
    public bool sitenameIsChangeable;		// 是否支持改名
    public bool switchingToAudioConference;	// 是否支持切换到纯语音模式

    public EVFeatureSupportCli();

    public void Unmanaged2ManagedStruct(EVFeatureSupport* evFeatureSupport);
}

// 用户信息
public class EVUserInfoCli
{
    public string cellphone;				// 手机号码
    public string customizedH5UrlPrefix;	// html url 前缀
    public string dept;						// 部门
    public ulong deviceId;					// 设备 id
    public string displayName;				// 显示名称
    public string email;					// 电子邮件
    public bool everChangedPasswd;			// 是否曾经修改过密码
    public string org;						// 组织名
    public string orgPortAllocMode;			// 组织端口分配模式
    public ulong orgPortCount;				// 组织端口数
    public string telephone;				// 电话号码
    public string token;					// 当前token
    public ulong userId;					// 用户 id
    public string username;					// 用户名称
	public EVFeatureSupportCli featureSupport;	// 当前登录的服务器支持的功能
    
    public EVUserInfoCli();

    public void Unmanaged2ManagedStruct(EVUserInfo* evUserInfo);
}

// 呼叫信息
public class EVCallInfoCli
{
    public string conference_number;	// 会议号码
    public bool contentEnabled;			// 当前会议是否支持内容发送或接收
    public EVErrorCli err;				// 错误信息
    public bool isAudioOnly;			// 是否仅音频
    public bool isBigConference;		// 是否大会
    public bool isRemoteMuted;			// 是否远端静音
    public string password;				// 会议密码
    public string peer;					// 呼叫的对端
    public EV_SVC_CALL_ACTION_CLI svcCallAction;	// svc 呼叫动作
    public EV_SVC_CALL_TYPE_CLI svcCallType;	// svc 呼叫类型

    public EVCallInfoCli();

    public void Unmanaged2ManagedStruct(EVCallInfo* evCallInfo);
}

// 内容信息
public class EVContentInfoCli
{
    public EV_STREAM_DIR_CLI dir;			// 媒体流方向
    public bool enabled;					// 是否启用
    public EV_CONTENT_STATUS_CLI status;	// 内容状态
    public EV_STREAM_TYPE_CLI type;			// 媒体流类型

    public EVContentInfoCli();

    public void Unmanaged2ManagedStruct(EVContentInfo* info);
}

// 录制状态
public enum EV_RECORDING_STATE_CLI
{
    EV_RECORDING_STATE_NONE = 0,	// 没有录制
    EV_RECORDING_STATE_ON = 1,		// 录制开始
    EV_RECORDING_STATE_PAUSE = 2	// 录制暂停
}

// 录制信息
public class EVRecordingInfoCli
{
    public bool live;						// 是否直播
    public EV_RECORDING_STATE_CLI state;	// 录制状态

    public EVRecordingInfoCli();

    public void Unmanaged2ManagedStruct(EVRecordingInfo* info);
}

// 字幕信息
public class EVMessageOverlayCli
{
    public string backgroundColor;			// 背景颜色
    public string content;					// 字幕内容
    public int displayRepetitions;			// 显示次数
    public int displaySpeed;				// 显示速度
    public bool enable;						// 是否启用字幕
    public int fontSize;					// 字体大小
    public string foregroundColor;			// 字体颜色
    public int transparency;				// 透明度
    public int verticalBorder;				// 垂直边距

    public EVMessageOverlayCli();

    public void Unmanaged2ManagedStruct(EVMessageOverlay* messageOverlay);
}

// 白板信息
public class EVWhiteBoardInfoCli
{
    public string authServer;				// 认证服务器
    public string server;					// 白板服务器
    public EV_WHITE_BOARD_TYPE_CLI type;	// 白板类型

    public EVWhiteBoardInfoCli();

    public void Unmanaged2ManagedStruct(EVWhiteBoardInfo* whiteBoardInfo);
}

5. 错误码

// SDK 类型错误码
public enum EV_ERROR_CLI
{
    EV_OK = 0,
    EV_NG = 1,
    EV_UNINITIALIZED = 2,
    EV_BAD_FORMAT = 3,
    EV_NOT_IN_CONF = 4,
    EV_BAD_PARAM = 5,
    EV_REGISTER_FAILED = 6,
    EV_INTERNAL_ERROR = 7,
    EV_SERVER_UNREACHABLE = 8,
    EV_SERVER_INVALID = 9,
    EV_CALL_DECLINED = 10,
    EV_CALL_BUSY = 11,
    EV_CALL_IO_ERROR = 12,
    EV_NOT_LOGIN = 13,
    EV_CALL_TIMEOUT = 14
}

// 服务器类型错误码
public enum EV_SERVER_ERROR_CLI
{
    EV_SERVER_API_VERSION_NOT_SUPPORTED = 1000,
    EV_SERVER_INVALID_TOKEN = 1001,
    EV_SERVER_INVALID_PARAMETER = 1002,
    EV_SERVER_INVALID_DEVICESN = 1003,
    EV_SERVER_INVALID_MEDIA_TYPE = 1004,
    EV_SERVER_PERMISSION_DENIED = 1005,
    EV_SERVER_WRONG_FIELD_NAME = 1006,
    EV_SERVER_INTERNAL_SYSTEM_ERROR = 1007,
    EV_SERVER_OPERATION_FAILED = 1008,
    EV_SERVER_GET_FAILED = 1009,
    EV_SERVER_NOT_SUPPORTED = 1010,
    EV_SERVER_REDIS_LOCK_TIMEOUT = 1011,
    EV_SERVER_INVALID_USER_NAME_PASSWORD = 1100,
    EV_SERVER_LOGIN_FAILED_MORE_THAN_5_TIMES = 1101,
    EV_SERVER_ACCOUNT_TEMPORARILY_LOCKED = 1102,
    EV_SERVER_ACCOUNT_DISABLED = 1103,
    EV_SERVER_NO_USERNAME = 1104,
    EV_SERVER_EMAIL_MISMATCH = 1105,
    EV_SERVER_COMPANY_ADMINISTRATOR_NOT_IN_ANY_COMPANY = 1106,
    EV_SERVER_NOT_AVAILABLE_FOR_ADMINISTRATORS = 1112,
    EV_SERVER_FILE_UPLOAD_FAILED = 1200,
    EV_SERVER_INVALID_LICENSE = 1201,
    EV_SERVER_INVALID_IMPORT_USER_FILE = 1202,
    EV_SERVER_INVALID_TIME_SERVICE_ADDRESS = 1300,
    EV_SERVER_FAILED_UPDATE_SYSTEM_PROPERTIES = 1301,
    EV_SERVER_CONF_NOT_EXISTS = 1400,
    EV_SERVER_NUMERICID_CONFLICTS = 1401,
    EV_SERVER_CONF_UPDATING_IN_PROGRESS = 1402,
    EV_SERVER_CONF_DELETING_IN_PROGRESS = 1403,
    EV_SERVER_CONF_TERMINATING_IN_PROGRESS = 1404,
    EV_SERVER_CONF_LAUNCHING_IN_PROGRESS = 1405,
    EV_SERVER_CONF_NOT_IN_APPROVED_STATUS = 1406,
    EV_SERVER_CONF_NUMERICID_ONGOING = 1407,
    EV_SERVER_CONF_NOT_APPROVED_OR_ONGOING = 1409,
    EV_SERVER_PARTICIPANT_NOT_EXISTS_IN_CONF = 1410,
    EV_SERVER_NUMERICID_ALREADY_IN_USE = 1412,
    EV_SERVER_INVALID_CONF_TIME = 1415,
    EV_SERVER_INVALID_CONF_ID = 1418,
    EV_SERVER_NOT_FOUND_SUITABLE_MRU = 1421,
    EV_SERVER_NOT_FOUND_SUITABLE_GATEWAY = 1422,
    EV_SERVER_FAILED_TO_CONNECT_MRU = 1424,
    EV_SERVER_NOT_ALLOW_DUPLICATED_NAME = 1427,
    EV_SERVER_NOT_FOUND_CONF_IN_REDIS = 1430,
    EV_SERVER_NOT_IN_LECTURER_MODE = 1431,
    EV_SERVER_FAILED_TO_MUTE_ALL_PARTICIPANTS = 1433,
    EV_SERVER_FAILED_TO_CONNECT_PARTICIPANT = 1436,
    EV_SERVER_FAILED_TO_DISCONNECT_PARTICIPANT = 1439,
    EV_SERVER_FAILED_TO_CHANGE_LAYOUT = 1442,
    EV_SERVER_FAILED_TO_SET_SUBTITLE = 1445,
    EV_SERVER_FAILED_TO_MUTE_PARTICIPANT_AUDIO = 1448,
    EV_SERVER_FAILED_TO_DELETE_PARTICIPANT = 1451,
    EV_SERVER_FAILED_TO_INVITE_AVC_ENDPOINT = 1454,
    EV_SERVER_FAILED_TO_INVITE_SVC_ENDPOINTS = 1455,
    EV_SERVER_CONF_ROOM_COMPLETELY_FULL = 1456,
    EV_SERVER_TIMEOUT_TO_GENERATE_NUMERICID = 1457,
    EV_SERVER_NOT_FOUND_PROFILE_NAMED_SVC = 1460,
    EV_SERVER_FAILED_TO_PROLONG_CONF = 1463,
    EV_SERVER_INVALID_MEETING_CONTROL_REQUEST = 1500,
    EV_SERVER_NAME_IN_USE = 1600,
    EV_SERVER_EMPTY_ENDPOINT_NAME = 1601,
    EV_SERVER_EMPTY_ENDPOINT_CALL_MODE = 1602,
    EV_SERVER_EMPTY_ENDPOINT_SIP_USERNAME = 1603,
    EV_SERVER_EMPTY_ENDPOINT_SIP_PASSWORD = 1604,
    EV_SERVER_EMPTY_ENDPOINT_ADDRESS = 1605,
    EV_SERVER_INVALID_SIP_USERNAME = 1606,
    EV_SERVER_INVALID_IP_ADDRESS = 1607,
    EV_SERVER_ENDPOINT_NOT_EXIST = 1608,
    EV_SERVER_E164_IN_USE = 1609,
    EV_SERVER_ENDPOINT_DEVICE_SN_EXIST = 1610,
    EV_SERVER_SIP_USERNAME_REGISTERED = 1611,
    EV_SERVER_ENDPOINT_E164_INVALID = 1612,
    EV_SERVER_NOT_FOUND_ENDPOINT_DEVICE_SN = 1613,
    EV_SERVER_NOT_FOUND_ENDPOINT_PROVISION_TEMPLATE = 1614,
    EV_SERVER_DEVICE_SN_EXISTS = 1615,
    EV_SERVER_CAN_NOT_DELETE_USER_IN_RESERVED_MEETING = 1700,
    EV_SERVER_EMPTY_USER_PASSWORD = 1701,
    EV_SERVER_EMPTY_USERNAME = 1702,
    EV_SERVER_EMPTY_USER_DISPLAY_NAME = 1703,
    EV_SERVER_INVALID_USER_EMAIL = 1704,
    EV_SERVER_INVALID_CELLPHONE_NUMBER = 1705,
    EV_SERVER_ORIGINAL_PASSWORD_WRONG = 1706,
    EV_SERVER_DUPLICATE_EMAIL_NAME = 1707,
    EV_SERVER_DUPLICATE_CELLPHONE_NUMBER = 1708,
    EV_SERVER_DUPLICATE_USERNAME = 1709,
    EV_SERVER_INVALID_CONF_ROOM_MAX_CAPACITY = 1710,
    EV_SERVER_SHOULD_ASSIGN_DEPARTMENT_TO_DEPARTMENT_ADMINISTRATOR = 1711,
    EV_SERVER_EMPTY_USER_EMAIL = 1712,
    EV_SERVER_EMPTY_USER_CELLPHONE_NUMBER = 1713,
    EV_SERVER_NOT_ORGANIZATION_ADMINISTRATOR = 1714,
    EV_SERVER_COMPANY_NOT_EXIST = 1800,
    EV_SERVER_SHORT_NAME_OF_COMPANY_USED = 1801,
    EV_SERVER_FULL_NAME_OF_COMPANY_USED = 1802,
    EV_SERVER_COMPANY_NOT_EMPTY = 1803,
    EV_SERVER_EMPTY_COMPANY_SHORT_NAME = 1804,
    EV_SERVER_AGENT_IN_USE = 1900,
    EV_SERVER_SHORT_NAME_IN_USE = 1901,
    EV_SERVER_FULL_NAME_IN_USE = 1902,
    EV_SERVER_AGENT_NOT_EXIST = 1903,
    EV_SERVER_AGENT_NOT_EMPTY = 1904,
    EV_SERVER_CONF_ROOM_EXPIRED = 2000,

    EV_SERVER_NOT_ACTIVED = 2001,

    EV_SERVER_NOT_FOUND_SUITABLE_ROOM = 2003,
    EV_SERVER_NOT_FOUND_TEMPLATE_OR_ROOM = 2005,
    EV_SERVER_CONF_ROOM_IN_USE = 2006,
    EV_SERVER_CONF_ROOM_NUMBER_IN_USE = 2009,
    EV_SERVER_CONF_ROOM_CAPACITY_EXCEEDS_LIMIT = 2012,
    EV_SERVER_INVALID_CONF_ROOM_CAPACITY = 2015, //PASSWORD REQUIRED
    EV_SERVER_INVALID_CONF_ROOM_NUMBER = 2018,
    EV_SERVER_ROOM_NOT_EXISTS = 2021,

    EV_SERVER_ROOM_NOT_ALLOW_ANONYMOUS_CALL = 2031,
    EV_SERVER_ROOM_ONLY_ALLOW_OWNER_ACTIVE = 2033,
    EV_SERVER_TRIAL_PERIOD_EXPIRED = 2035,

    EV_SERVER_CAN_NOT_DELETE_DEPARTMENT_WITH_SUBORDINATE_DEPARTMENT = 2100,
    EV_SERVER_CAN_NOT_DELETE_DEPARTMENT_WITH_USERS_OR_ENDPOINTS = 2101,
    EV_SERVER_INVALID_ACS_CONFIGURATION = 2200,
    TRIAL_EXPIRED = 2035
}

// 定位类型错误码
public enum EV_LOCATE_ERROR_CLI
{
    EV_LOCATE_FAILED_TO_READ_BODY = 10000,
    EV_LOCATE_FAILED_TO_PARSE_BODY = 10001,
    EV_LOCATE_LOCATION_TIMEOUT = 10002,
    EV_LOCATE_ERROR_INFO_GENERAL = 10003,
    EV_LOCATE_ERROR_INFO_BAD_FORMAT = 10004,
    EV_LOCATE_UNEXPECTED = 10005,
    EV_LOCATE_FAILED_TO_LOCATE_CLIENT = 10006,
    EV_LOCATE_FAILED_TO_LOCATE_ZONE = 10007,
    EV_LOCATE_NO_LOCATION_DOMAIN = 10008,
    EV_LOCATE_ERROR_LOCATION_REQUEST = 10009
}

// 呼叫类型错误码
public enum EV_CALL_ERROR_CLI
{
    EV_CALL_INVALID_NUMERICID = 1001,
    EV_CALL_INVALID_USERNAME = 1003,
    EV_CALL_INVALID_USERID = 1005,
    EV_CALL_INVALID_DEVICEID = 1007,
    EV_CALL_INVALID_ENDPOINT = 1009,

    EV_CALL_SERVER_UNLICENSED = 2001,
    SERVER_LICENSE_EXPIRED = 2002,
    EV_CALL_NOT_FOUND_SUITABLE_MRU = 2003,
    EV_CALL_NEITHER_TEMPLATE_NOR_ONGOING_NOR_BINDED_ROOM = 2005,
    EV_CALL_LOCK_TIMEOUT = 2007,
    EV_CALL_TEMPLATE_CONF_WITHOUT_CONFROOM = 2009,
    EV_CALL_ROOM_EXPIRED = 2011,
    ROOM_COMPLETELY_FULL = 2013,
    EV_CALL_INVALID_PASSWORD = 2015,
    EV_CALL_NO_TIME_SPACE_TO_ACTIVATE_ROOM = 2017,
    NOT_FOUND_SIGNALING_IP = 2019,
    MIXED_MRU_COMPLETELY_FULL = 2021,
    EV_CALL_CONF_PORT_COUNT_USED_UP = 2023,
    EV_CALL_ORG_PORT_COUNT_USED_UP = 2024,
    EV_CALL_HAISHEN_PORT_COUNT_USED_UP = 2025,
    EV_CALL_HAISHEN_GATEWAY_AUDIO_PORT_COUNT_USED_UP = 2027,
    EV_CALL_HAISHEN_GATEWAY_VIDEO_PORT_COUNT_USED_UP = 2029,
    EV_CALL_ONLY_ROOM_OWNER_CAN_ACTIVATE_ROOM = 2031,
    EV_CALL_NOT_ALLOW_ANONYMOUS_PARTY = 2033,
    EV_CALL_TRIAL_ORG_EXPIRED = 2035,
    CALL_FAILED_FOR_PARTY_IN_CALL = 4049,
    PARTY_OFFLINE = 4051,
    SERVICE_EXCEPTION = 2999
}

6. 安装包中需要包含的文件

以下部分是 EVSDK 的 dll 文件及其依赖的其他文件,在安装包中需要包含以下文件,并且安装到和应用程序执行文件相同的目录中。

  • evsdk.dll - EVSDK 库文件
  • rootca.pem - 根 CA 文件,SDK 需要使用该文件,否则当平台端开启 HTTPS 后,可能导致无法注册
  • msvcr120.dll - C++ 运行时库文件
  • msvcp120.dll - C++ 运行时库文件
  • msvcp140.dll - C++ 运行时库文件
  • vcruntime140.dll - C++ 运行时库文件

以下文件是 UI 部分需要的文件(开发者在开发过程中如果引入了其他依赖,则需要根据实际情况在安装包中包含其他依赖文件。)

  • HexMeetHJT.exe - 应用程序可执行文件
  • HexMeetHJT.exe.config
  • ManagedEVSdk.dll - EVSDK 的 C# 接口 DLL
  • Resources/Icons/background.jpg - 屏蔽摄像头时的背景图片
  • Resources/Icons/default_user_header.jpg - 默认头像图片
  • Resources/sounds/camera.wav - 快门音
  • Resources/sounds/ringtone.wav - 来电铃音
  • Resources/sounds/speaker.wav - sperker 测试音
  • locales/en-GB.pak
  • locales/en-US.pak
  • locales/zh-CN.pak
  • locales/zh-TW.pak
  • cef.pak
  • cef_100_percent.pak
  • cef_200_percent.pak
  • cef_extension.pak
  • CefSharp.BrowserSubprocess.Core.dll
  • CefSharp.BrowserSubprocess.exe
  • CefSharp.Core.dll
  • CefSharp.dll
  • CefSharp.WinForms.dll
  • CefSharp.Wpf.dll
  • chrome_elf.dll
  • d3dcompiler_47.dll
  • icudtl.dat
  • Ionic.Zip.Reduced.dll
  • libcef.dll
  • libEGL.dll
  • libGLESv2.dll
  • log4net.dll
  • Microsoft.WindowsAPICodePack.dll
  • Microsoft.WindowsAPICodePack.Shell.dll
  • NAudio.dll
  • Newtonsoft.Json.dll
  • System.Net.Http.dll
  • System.Windows.dll
  • System.Windows.Interactivity.dll
  • XamlAnimatedGif.dll
  • native_blob.bin
  • snapshot_blob.bin
  • v8_context_snapshot.bin
上次更新: 6/22/2022, 3:38:06 PM