This sample app is written C++.
The key code for the sample application is in the AgoraTutorial
folder. The following steps identify the code most relevant to using the Agora SDK.
- Create the AgoraTutorialDlg Class
- Create the AgoraObject Class
- Create the AGEngineEventHandler Class
For details about the APIs used to develop this sample, see the Agora.io Documentation version 2.2.
The AgoraTutorialDlg
class manages UI element interactions with the application and Agora SDK.
- Add the OnInitDialog() Method
- Add the OnBnClickedBtnjoin() Method
- Add the OnBnClickedBtnleave() Method
- Add the OnBnClickedBtnmutelocaud() Method
- Add the OnBnClickedBtndisvid() Method
- Add the OnFirstRemoteVideoDecoded() Callback
The OnInitDialog()
method initializes the sample application.
Retrieve the system menu using GetSystemMenu()
. Verify that pSysMenu
is not NULL
and perform the following actions:
- Declare a boolean
bNameValid
variable and a stringstrAboutMenu
variable. - Obtain the value of
bNameValid
by passingIDS_ABOUTBOX
intostrAboutMenu.LoadString()
. - Validate
bNameValid
and ensurestrAboutMenu
is not empty before appending the menu items usingpSysMenu->AppendMenu()
.
The remaining code in this section is within the OnInitDialog()
method.
BOOL CAgoraTutorialDlg::OnInitDialog()
{
...
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
...
}
Set the application icons using SetIcon()
. If APP_ID
is not set, use MessageBox()
to display a message telling the user to apply the App ID to the application, and exit the application using ExitProcess()
.
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
if (_tcslen(APP_ID) == 0) {
MessageBox(_T("Please apply your own App ID to macro APP_ID"), _T("Notice"), MB_OK | MB_ICONERROR);
ExitProcess(0);
}
Begin the Agora engine initialization process.
- Create and set
m_lpAgoraObject
withAPP_ID
usingGetAgoraObject()
. - Set the message handler using
m_lpAgoraObject->SetMsgHandlerWnd()
. - Enable video for the Agora engine using
m_lpAgoraObject->GetEngine()->enableVideo()
. - Set the default video canvas, user ID, view, and render mode properties
vc.uid
,vc.view
, andvc.renderMode
. - Set up local video with
vc
usingm_lpAgoraObject->GetEngine()->setupLocalVideo()
.
m_lpAgoraObject = CAgoraObject::GetAgoraObject(APP_ID);
m_lpAgoraObject->SetMsgHandlerWnd(GetSafeHwnd());
m_lpAgoraObject->GetEngine()->enableVideo();
VideoCanvas vc;
vc.uid = 0;
vc.view = m_wndLocal.GetSafeHwnd();
vc.renderMode = RENDER_MODE_FIT;
m_lpAgoraObject->GetEngine()->setupLocalVideo(vc);
return TRUE;
The OnBnClickedBtnjoin()
method triggers when the join UI button is clicked.
Invoke UpdateData()
.
- If
m_strChannelName
is empty, display a prompt explaining that the channel namemust not be empty
. - If
m_strChannelName
is not empty, join the channel specified bym_strChannelName
usingm_lpAgoraObject->JoinChannel()
.
void CAgoraTutorialDlg::OnBnClickedBtnjoin()
{
UpdateData(TRUE);
if (m_strChannelName.IsEmpty())
MessageBox(_T("Channel name must not be empty"), _T("Notice"), MB_OK | MB_ICONERROR);
else
m_lpAgoraObject->JoinChannel(m_strChannelName);
}
The OnBnClickedBtnleave()
method triggers when the leave UI button is clicked. Leave the channel by invoking m_lpAgoraObject->LeaveChannel()
.
void CAgoraTutorialDlg::OnBnClickedBtnleave()
{
m_lpAgoraObject->LeaveChannel();
}
The OnBnClickedBtnmutelocaud()
method triggers when the local audio button is clicked.
Retrieve the current local audio mute status using m_lpAgoraObject->IsLocalAudioMuted()
and apply the reverse value to mute or unmute the local audio using m_lpAgoraObject->MuteLocalAudio()
.
void CAgoraTutorialDlg::OnBnClickedBtnmutelocaud()
{
BOOL bStatValue = !m_lpAgoraObject->IsLocalAudioMuted();
m_lpAgoraObject->MuteLocalAudio(bStatValue);
}
The OnBnClickedBtndisvid()
method triggers when the enable or disable video button is clicked.
Retrieve the current video enable or disable status using m_lpAgoraObject->IsVideoEnabled()
and apply the reverse value to enable or disable the video using m_lpAgoraObject->MuteLocalVideo()
.
void CAgoraTutorialDlg::OnBnClickedBtndisvid()
{
BOOL bStatValue = !m_lpAgoraObject->IsVideoEnabled();
m_lpAgoraObject->MuteLocalVideo(bStatValue);
}
The OnFirstRemoteVideoDecoded()
method triggers when the first remote video frame is decoded.
- Convert
wParam
into aLPAGE_FIRST_REMOTE_VIDEO_DECODED
object. - Create a
VideoCanvas
object and set the render mode, user ID, and view properties usingvc.renderMode
,vc.uid
, andvc.view
. - Set up the remote video with
vc
usingm_lpAgoraObject->GetEngine()->setupRemoteVideo()
. - Clear
lpData
from memory usingdelete
and return0
.
LRESULT CAgoraTutorialDlg::OnFirstRemoteVideoDecoded(WPARAM wParam, LPARAM lParam)
{
LPAGE_FIRST_REMOTE_VIDEO_DECODED lpData = (LPAGE_FIRST_REMOTE_VIDEO_DECODED)wParam;
VideoCanvas vc;
vc.renderMode = RENDER_MODE_FIT;
vc.uid = lpData->uid;
vc.view = m_wndRemote.GetSafeHwnd();
m_lpAgoraObject->GetEngine()->setupRemoteVideo(vc);
delete lpData;
return 0;
}
The AgoraObject
class manages communication with the Agora SDK.
- Declare Global Variables and Initialize CAgoraObject
- Create Agora SDK and Engine Methods
- Create Message Handlers
- Create Channel Methods
- Create Video Methods
- Create Audio Methods
Declare the global Agora SDK variables:
Variable | Value | Description |
---|---|---|
m_lpAgoraObject |
NULL |
The Agora object |
m_lpAgoraEngine |
NULL |
The Agora engine |
m_EngineEventHandler |
N/A | The event handler for the Agora engine |
#include "StdAfx.h"
#include <stdio.h>
#include "AgoraObject.h"
CAgoraObject *CAgoraObject::m_lpAgoraObject = NULL;
IRtcEngine *CAgoraObject::m_lpAgoraEngine = NULL;
CAGEngineEventHandler CAgoraObject::m_EngineEventHandler;
When CAgoraObject
is initialized, clear the channel name using m_strChannelName.Empty()
and set m_bLocalVideoMuted
to FALSE
.
CAgoraObject::CAgoraObject(void)
: m_dwEngineFlag(0)
, m_bVideoEnable(FALSE)
, m_bLocalAudioMuted(FALSE)
{
m_strChannelName.Empty();
m_bLocalVideoMuted = FALSE;
}
The methods in this section manage the Agora SDK and engine.
- Add the GetSDKVersion() Method
- Add the GetEngine() Method
- Add the GetAgoraObject() Method
- Add the CloseAgoraObject() Method
The GetSDKVersion()
method retrieves the version number of the Agora SDK used in the sample application.
Initialize nBuildNumber
to 0
and retrieve the Agora RTC engine version number using getAgoraRtcEngineVersion()
.
Convert lpszEngineVer
to a CString
object and return its value.
CString CAgoraObject::GetSDKVersion()
{
int nBuildNumber = 0;
const char *lpszEngineVer = getAgoraRtcEngineVersion(&nBuildNumber);
CString strEngineVer;
#ifdef UNICODE
::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpszEngineVer, -1, strEngineVer.GetBuffer(256), 256);
strEngineVer.ReleaseBuffer();
#endif
return strEngineVer;
}
The GetEngine()
method retrieves the Agora engine object.
If m_lpAgoraEngine
is NULL
, the engine has not been created yet. Create it using createAgoraRtcEngine()
.
Return the engine object m_lpAgoraEngine
.
IRtcEngine *CAgoraObject::GetEngine()
{
if(m_lpAgoraEngine == NULL)
m_lpAgoraEngine = (IRtcEngine *)createAgoraRtcEngine();
return m_lpAgoraEngine;
}
The GetAgoraObject()
method retrieves the Agora SDK object.
- If
m_lpAgoraObject
isNULL
, the Agora object has not been created yet. Create it usingnew CAgoraObject()
. - If
m_lpAgoraEngine
isNULL
, the engine has not been created yet. Create it usingcreateAgoraRtcEngine()
.
If lpAppId
is NULL
, return m_lpAgoraObject
.
Create a RtcEngineContext
object and set the event handler and App ID properties ctx.eventHandler
and ctx.appId
. If unicode is enabled, use szAppId
as the App ID. Otherwise, use lpAppId
.
Initialize the engine with ctx
using m_lpAgoraEngine->initialize()
and return m_lpAgoraObject
.
CAgoraObject *CAgoraObject::GetAgoraObject(LPCTSTR lpAppId)
{
if (m_lpAgoraObject == NULL)
m_lpAgoraObject = new CAgoraObject();
if (m_lpAgoraEngine == NULL)
m_lpAgoraEngine = (IRtcEngine *)createAgoraRtcEngine();
if (lpAppId == NULL)
return m_lpAgoraObject;
RtcEngineContext ctx;
ctx.eventHandler = &m_EngineEventHandler;
#ifdef UNICODE
char szAppId[128];
::WideCharToMultiByte(CP_ACP, 0, lpAppId, -1, szAppId, 128, NULL, NULL);
ctx.appId = szAppId;
#else
ctx.appId = lpAppId;
#endif
m_lpAgoraEngine->initialize(ctx);
return m_lpAgoraObject;
}
The CloseAgoraObject()
method clears the Agora object from memory.
- If
m_lpAgoraEngine
exists, release it from memory usingm_lpAgoraEngine->release()
. - If
m_lpAgoraObject
exists, delete it usingdelete
.
Set m_lpAgoraEngine
and m_lpAgoraObject
to NULL
.
void CAgoraObject::CloseAgoraObject()
{
if(m_lpAgoraEngine != NULL)
m_lpAgoraEngine->release();
if(m_lpAgoraObject != NULL)
delete m_lpAgoraObject;
m_lpAgoraEngine = NULL;
m_lpAgoraObject = NULL;
}
The methods in this section manage the message receiver.
The SetMsgHandlerWnd()
method sends the message hWnd
to the Agora engine's event handler using m_EngineEventHandler.SetMsgReceiver()
.
void CAgoraObject::SetMsgHandlerWnd(HWND hWnd)
{
m_EngineEventHandler.SetMsgReceiver(hWnd);
}
The GetMsgHandlerWnd()
method retrieves the message receiver object from the Agora engine'e event handler using m_EngineEventHandler.GetMsgReceiver()
.
HWND CAgoraObject::GetMsgHandlerWnd()
{
return m_EngineEventHandler.GetMsgReceiver();
}
The methods in this section manage joining or leaving a channel and retrieving the channel name.
The JoinChannel()
method joins the user specified by nUID
to the channel specified by lpChannelName
.
Initialize nRet
with a value of 0
and join the channel using m_lpAgoraEngine->joinChannel()
. Use szChannelName
if unicode is supported, and lpChannelName
otherwise.
Ensure the channel join is successful by checking if nRet
is equal to 0
and set m_strChannelName
to lpChannelName
.
BOOL CAgoraObject::JoinChannel(LPCTSTR lpChannelName, UINT nUID)
{
int nRet = 0;
#ifdef UNICODE
CHAR szChannelName[128];
::WideCharToMultiByte(CP_UTF8, 0, lpChannelName, -1, szChannelName, 128, NULL, NULL);
nRet = m_lpAgoraEngine->joinChannel(NULL, szChannelName, NULL, nUID);
#else
nRet = m_lpAgoraEngine->joinChannel(NULL, lpChannelName, NULL, nUID);
#endif
if (nRet == 0)
m_strChannelName = lpChannelName;
return nRet == 0 ? TRUE : FALSE;
}
The LeaveChannel()
method leaves the channel.
Stop the preview using m_lpAgoraEngine->stopPreview()
, then leave the channel using m_lpAgoraEngine->leaveChannel()
.
If the leave channel action is successful, return TRUE
. Otherwise, return FALSE
.
BOOL CAgoraObject::LeaveChannel()
{
m_lpAgoraEngine->stopPreview();
int nRet = m_lpAgoraEngine->leaveChannel();
return nRet == 0 ? TRUE : FALSE;
}
The GetChanelName()
method retrieves the channel name, returning m_strChannelName
.
CString CAgoraObject::GetChanelName()
{
return m_strChannelName;
}
The methods in this section manage the video.
The EnableVideo()
method enables the video for the sample application.
Initialize nRet
with a value for 0
. If bEnable
is TRUE
, enable the video using m_lpAgoraEngine->enableVideo()
. Otherwise, disable the video using m_lpAgoraEngine->disableVideo()
.
Ensure the enable or disable video action is successful and set m_bVideoEnable
to bEnable
.
BOOL CAgoraObject::EnableVideo(BOOL bEnable)
{
int nRet = 0;
if (bEnable)
nRet = m_lpAgoraEngine->enableVideo();
else
nRet = m_lpAgoraEngine->disableVideo();
if (nRet == 0)
m_bVideoEnable = bEnable;
return nRet == 0 ? TRUE : FALSE;
}
The IsVideoEnabled()
method indicates if video is enabled for the sample application and returns m_bVideoEnable
.
BOOL CAgoraObject::IsVideoEnabled()
{
return m_bVideoEnable;
}
The MuteLocalVideo()
method turns local video on or off.
Ensure m_lpAgoraEngine
is not NULL
before completing the remaining method actions.
Declare a RtcEngineParameters
object and invoke its muteLocalVideoStream()
method with bMuted
.
If the mute or unmute local video is successful, set m_bLocalVideoMuted
to bMuted
.
BOOL CAgoraObject::MuteLocalVideo(BOOL bMuted)
{
ASSERT(m_lpAgoraEngine != NULL);
RtcEngineParameters rep(*m_lpAgoraEngine);
int ret = rep.muteLocalVideoStream((bool)bMuted);
if (ret == 0)
m_bLocalVideoMuted = bMuted;
return ret == 0 ? TRUE : FALSE;
}
The IsLocalVideoMuted()
method indicates if the local video is on or off for the sample application, returning m_bLocalVideoMuted
.
BOOL CAgoraObject::IsLocalVideoMuted()
{
return m_bLocalVideoMuted;
}
The methods in this section manage the audio.
The MuteLocalAudio()
method mutes or unmutes the local audio.
Ensure m_lpAgoraEngine
is not NULL
before completing the remaining method actions.
Declare a RtcEngineParameters
object and invoke its muteLocalAudioStream()
method with bMuted
.
If the mute or unmute local audio is successful, set m_bLocalAudioMuted
to bMuted
.
BOOL CAgoraObject::MuteLocalAudio(BOOL bMuted)
{
ASSERT(m_lpAgoraEngine != NULL);
RtcEngineParameters rep(*m_lpAgoraEngine);
int ret = rep.muteLocalAudioStream((bool)bMuted);
if (ret == 0)
m_bLocalAudioMuted = bMuted;
return ret == 0 ? TRUE : FALSE;
}
The IsLocalAudioMuted()
method indicates if local audio is muted or unmuted for the sample application, returning m_bLocalAudioMuted
.
BOOL CAgoraObject::IsLocalAudioMuted()
{
return m_bLocalAudioMuted;
}
The methods in the AGEngineEventHandler
class manage event listener callbacks.
- Create Channel Callbacks
- Create Engine and API Callbacks
- Create Audio and Video Callbacks
- Create Statistics Callbacks
- Create Device Callbacks
- Create User Callbacks
- Create Connection Callbacks
- Create Recording Callbacks
Changes in the channel trigger the callbacks in this section.
The onJoinChannelSuccess()
callback triggers when a channel is successfully joined.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_JOINCHANNEL_SUCCESS
object and set the channel name, user ID, and time elapsed values using lpData->channel
, lpData->uid
, and lpData->elapsed
.
Note: lpData->channel
requires memory to be allocated prior to setting the channel name using strcpy_s()
.
Complete the method by displaying a join channel success message using PostMessage()
.
void CAGEngineEventHandler::onJoinChannelSuccess(const char* channel, uid_t uid, int elapsed)
{
if (m_hMainWnd == NULL)
return;
LPAGE_JOINCHANNEL_SUCCESS lpData = new AGE_JOINCHANNEL_SUCCESS;
int nChannelLen = strlen(channel) + 1;
lpData->channel = new char[nChannelLen];
lpData->uid = uid;
lpData->elapsed = elapsed;
strcpy_s(lpData->channel, nChannelLen, channel);
::PostMessage(m_hMainWnd, WM_MSGID(EID_JOINCHANNEL_SUCCESS), (WPARAM)lpData, 0);
}
The onRejoinChannelSuccess()
callback triggers when a channel is successfully rejoined.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_REJOINCHANNEL_SUCCESS
object and set the channel name, user ID, and time elapsed values using lpData->channel
, lpData->uid
, and lpData->elapsed
.
Note: lpData->channel
requires memory to be allocated prior to setting the channel name using strcpy_s()
.
Complete the method by displaying a rejoin channel success message using PostMessage()
.
void CAGEngineEventHandler::onRejoinChannelSuccess(const char* channel, uid_t uid, int elapsed)
{
if (m_hMainWnd == NULL)
return;
LPAGE_REJOINCHANNEL_SUCCESS lpData = new AGE_REJOINCHANNEL_SUCCESS;
int nChannelLen = strlen(channel) + 1;
lpData->channel = new char[nChannelLen];
lpData->uid = uid;
lpData->elapsed = elapsed;
strcpy_s(lpData->channel, nChannelLen, channel);
::PostMessage(m_hMainWnd, WM_MSGID(EID_REJOINCHANNEL_SUCCESS), (WPARAM)lpData, 0);
}
The onLeaveChannel()
callback triggers when a leave channel event occurs with statistics.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_LEAVE_CHANNEL
object and set the statistics property lpData->rtcStat
with stat
using memcpy()
.
Complete the method by displaying a leave channel message using PostMessage()
.
void CAGEngineEventHandler::onLeaveChannel(const RtcStats& stat)
{
if (m_hMainWnd == NULL)
return;
LPAGE_LEAVE_CHANNEL lpData = new AGE_LEAVE_CHANNEL;
memcpy(&lpData->rtcStat, &stat, sizeof(RtcStats));
::PostMessage(m_hMainWnd, WM_MSGID(EID_LEAVE_CHANNEL), (WPARAM)lpData, 0);
}
The callbacks in this section trigger when changes to Agora engine or API occur.
- Add the onWarning() Callback
- Add the onError() Callback
- Add the onMediaEngineEvent() Callback
- Add the onApiCallExecuted() Callback
The onWarning()
callback triggers when a warning occurs from the Agora engine.
Declare a CString
object and set its value to _T("onWarning")
.
void CAGEngineEventHandler::onWarning(int warn, const char* msg)
{
CString str;
str = _T("onWarning");
}
The onError()
callback triggers when an error occurs from the Agora engine.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_ERROR
object.
-
If
msg
is notNULL
, setlpData->msg
tomsg
.Note:
lpData->msg
requires memory to be allocated prior to setting the message usingstrcpy_s()
. -
If
msg
isNULL
, setlpData->msg
toNULL
.
Complete the method by displaying an error message using PostMessage()
.
void CAGEngineEventHandler::onError(int err, const char* msg)
{
if (m_hMainWnd == NULL)
return;
LPAGE_ERROR lpData = new AGE_ERROR;
int nMsgLen = 0;
// attention: the pointer of msg maybe NULL!!!
if(msg != NULL) {
nMsgLen = strlen(msg) + 1;
lpData->msg = new char[nMsgLen];
strcpy_s(lpData->msg, nMsgLen, msg);
}
else
lpData->msg = NULL;
lpData->err = err;
::PostMessage(m_hMainWnd, WM_MSGID(EID_ERROR), (WPARAM)lpData, 0);
}
The onMediaEngineEvent()
callback triggers when an event occurs on the Agora media engine.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_MEDIA_ENGINE_EVENT
object and set the event property lpData->evt
with evt
.
Complete the method by displaying a media engine event message using PostMessage()
.
void CAGEngineEventHandler::onMediaEngineEvent(int evt)
{
if (m_hMainWnd == NULL)
return;
LPAGE_MEDIA_ENGINE_EVENT lpData = new AGE_MEDIA_ENGINE_EVENT;
lpData->evt = evt;
::PostMessage(m_hMainWnd, WM_MSGID(EID_MEDIA_ENGINE_EVENT), (WPARAM)lpData, 0);
}
The onApiCallExecuted()
callback triggers when an API call is executed.
Declare a new LPAGE_APICALL_EXECUTED
object and set the api and error properties lpData->api
and lpData->error
.
Note: lpData->api
requires memory allocation prior to setting api
using strcpy_s()
.
Complete the method by displaying an API call execution event message using PostMessage()
.
void CAGEngineEventHandler::onApiCallExecuted(const char* api, int error)
{
if (m_hMainWnd == NULL)
return;
LPAGE_APICALL_EXECUTED lpData = new AGE_APICALL_EXECUTED;
strcpy_s(lpData->api, 128, api);
lpData->error = error;
::PostMessage(m_hMainWnd, WM_MSGID(EID_APICALL_EXECUTED), (WPARAM)lpData, 0);
}
The callbacks in this section trigger when changes to audio or video occur.
- Add the onAudioQuality() Callback
- Add the onAudioVolumeIndication() Callback
- Add the onFirstLocalVideoFrame() Callback
- Add the onFirstRemoteVideoDecoded() Callback
- Add the onFirstRemoteVideoFrame() Callback
- Add the onVideoStopped() Callback
The onAudioQuality()
callback triggers when the audio quality changes for a user specified by uid
.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_AUDIO_QUALITY
object and set the user ID, quality, time delay, and lost properties using lpData->uid
, lpData->quality
, lpData->delay
, and lpData->lost
.
Complete the method by displaying an audio quality change message using PostMessage()
.
void CAGEngineEventHandler::onAudioQuality(uid_t uid, int quality, unsigned short delay, unsigned short lost)
{
if (m_hMainWnd == NULL)
return;
LPAGE_AUDIO_QUALITY lpData = new AGE_AUDIO_QUALITY;
lpData->uid = uid;
lpData->quality = quality;
lpData->delay = delay;
lpData->lost = lost;
::PostMessage(m_hMainWnd, WM_MSGID(EID_AUDIO_QUALITY), (WPARAM)lpData, 0);
}
The onAudioVolumeIndication()
callback triggers when the audio volume indicator changes for a speaker specified by speakerNumber
.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_AUDIO_VOLUME_INDICATION
object and set the speakers, speaker ID, and total volume properties using lpData->speakers
, lpData->speakerNumber
, and lpData->totalVolume
.
Note: lpData->speakers
requires a new AudioVolumeInfo
object to be created with memory allocation, prior to setting speakers
using strcpy_s()
.
Complete the method by displaying an audio indication change message using PostMessage()
.
void CAGEngineEventHandler::onAudioVolumeIndication(const AudioVolumeInfo* speakers, unsigned int speakerNumber, int totalVolume)
{
if (m_hMainWnd == NULL)
return;
LPAGE_AUDIO_VOLUME_INDICATION lpData = new AGE_AUDIO_VOLUME_INDICATION;
lpData->speakers = new AudioVolumeInfo[speakerNumber];
memcpy(lpData->speakers, speakers, speakerNumber*sizeof(AudioVolumeInfo));
lpData->speakerNumber = speakerNumber;
lpData->totalVolume = totalVolume;
::PostMessage(m_hMainWnd, WM_MSGID(EID_AUDIO_VOLUME_INDICATION), (WPARAM)lpData, 0);
}
The onFirstLocalVideoFrame()
callback triggers when the first local video frame has elapsed.
Declare a new LPAGE_FIRST_LOCAL_VIDEO_FRAME
object and set the width, height, and time elapsed properties lpData->width
, lpData->height
, and lpData->elapsed
.
Complete the method by displaying a first local video frame received event message using PostMessage()
.
void CAGEngineEventHandler::onFirstLocalVideoFrame(int width, int height, int elapsed)
{
LPAGE_FIRST_LOCAL_VIDEO_FRAME lpData = new AGE_FIRST_LOCAL_VIDEO_FRAME;
lpData->width = width;
lpData->height = height;
lpData->elapsed = elapsed;
if(m_hMainWnd != NULL)
::PostMessage(m_hMainWnd, WM_MSGID(EID_FIRST_LOCAL_VIDEO_FRAME), (WPARAM)lpData, 0);
}
The onFirstRemoteVideoDecoded()
callback triggers when the first remote video is decoded.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_FIRST_REMOTE_VIDEO_DECODED
object and set the following properties:
Property | Value | Description |
---|---|---|
lpData->uid |
uid |
User ID |
lpData->width |
width |
Width |
lpData->height |
height |
Height |
lpData->elapsed |
elapsed |
Time elapsed |
Complete the method by displaying a first remote video decoded event message using PostMessage()
.
void CAGEngineEventHandler::onFirstRemoteVideoDecoded(uid_t uid, int width, int height, int elapsed)
{
if (m_hMainWnd == NULL)
return;
LPAGE_FIRST_REMOTE_VIDEO_DECODED lpData = new AGE_FIRST_REMOTE_VIDEO_DECODED;
lpData->uid = uid;
lpData->width = width;
lpData->height = height;
lpData->elapsed = elapsed;
::PostMessage(m_hMainWnd, WM_MSGID(EID_FIRST_REMOTE_VIDEO_DECODED), (WPARAM)lpData, 0);
}
The onFirstRemoteVideoFrame()
callback triggers when the first remote video frame is received.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_FIRST_REMOTE_VIDEO_FRAME
object and set the following properties:
Property | Value | Description |
---|---|---|
lpData->uid |
uid |
User ID |
lpData->width |
width |
Width |
lpData->height |
height |
Height |
lpData->elapsed |
elapsed |
Time elapsed |
Complete the method by displaying a first remote video frame received event message using PostMessage()
.
void CAGEngineEventHandler::onFirstRemoteVideoFrame(uid_t uid, int width, int height, int elapsed)
{
if (m_hMainWnd == NULL)
return;
LPAGE_FIRST_REMOTE_VIDEO_FRAME lpData = new AGE_FIRST_REMOTE_VIDEO_FRAME;
lpData->uid = uid;
lpData->width = width;
lpData->height = height;
lpData->elapsed = elapsed;
::PostMessage(m_hMainWnd, WM_MSGID(EID_FIRST_REMOTE_VIDEO_FRAME), (WPARAM)lpData, 0);
}
The onVideoStopped()
callback triggers when the video stops.
If m_hMainWnd
is not NULL
, display a video stopped event message using PostMessage()
.
void CAGEngineEventHandler::onVideoStopped()
{
if (m_hMainWnd != NULL)
::PostMessage(m_hMainWnd, WM_MSGID(EID_VIDEO_STOPPED), 0, 0);
}
The callbacks in this section trigger when statistic changes occur.
The onRtcStats()
callback triggers when an RTC statistic changes.
Declare a CString
variable str
and set the value to _T("stat")
.
void CAGEngineEventHandler::onRtcStats(const RtcStats& stat)
{
CString str;
str = _T("stat");
}
The onLastmileQuality()
callback triggers when the last mile quality test changes.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_LASTMILE_QUALITY
object and set the quality property lpData->quality
.
Complete the method by displaying a last mile quality change event message using PostMessage()
.
void CAGEngineEventHandler::onLastmileQuality(int quality)
{
if (m_hMainWnd == NULL)
return;
LPAGE_LASTMILE_QUALITY lpData = new AGE_LASTMILE_QUALITY;
lpData->quality = quality;
::PostMessage(m_hMainWnd, WM_MSGID(EID_LASTMILE_QUALITY), (WPARAM)lpData, 0);
}
The onLocalVideoStats()
callback triggers when local video statistics are received.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_LOCAL_VIDEO_STAT
object and set the bitrate and framerate properties lpData->sentBitrate
and lpData->sentFrameRate
.
Complete the method by displaying a local video statistics event message using PostMessage()
.
void CAGEngineEventHandler::onLocalVideoStats(const LocalVideoStats& stats)
{
if (m_hMainWnd == NULL)
return;
LPAGE_LOCAL_VIDEO_STAT lpData = new AGE_LOCAL_VIDEO_STAT;
lpData->sentBitrate = stats.sentBitrate;
lpData->sentFrameRate = stats.sentFrameRate;
::PostMessage(m_hMainWnd, WM_MSGID(EID_LOCAL_VIDEO_STAT), (WPARAM)lpData, 0);
}
The onRemoteVideoStats()
callback triggers when remote video statistics are received.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_REMOTE_VIDEO_STAT
object and set:
Property | Value | Description |
---|---|---|
lpData->uid |
stats.uid |
User ID |
lpData->delay |
stats.delay |
Time delay |
lpData->width |
stats.width |
Width |
lpData->height |
stats.height |
Height |
lpData->sentBitrate |
stats.receivedBitrate |
Bit rate |
lpData->sentFrameRate |
stats.receivedFrameRate |
Frame rate |
Complete the method by displaying a remote video statistics event message using PostMessage()
.
void CAGEngineEventHandler::onRemoteVideoStats(const RemoteVideoStats& stats)
{
if (m_hMainWnd == NULL)
return;
LPAGE_REMOTE_VIDEO_STAT lpData = new AGE_REMOTE_VIDEO_STAT;
lpData->uid = stats.uid;
lpData->delay = stats.delay;
lpData->width = stats.width;
lpData->height = stats.height;
lpData->receivedFrameRate = stats.receivedFrameRate;
lpData->receivedBitrate = stats.receivedBitrate;
::PostMessage(m_hMainWnd, WM_MSGID(EID_REMOTE_VIDEO_STAT), (WPARAM)lpData, 0);
}
The callbacks in this section trigger when device changes occur.
The onAudioDeviceStateChanged()
callback triggers when an audio device state changes.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_AUDIO_DEVICE_STATE_CHANGED
object and set the device ID, device type, and device state properties lpData->deviceId
, lpData->deviceType
, and lpData->deviceState
.
Note: lpData->deviceId
requires memory allocation prior to setting deviceId
using strcpy_s()
.
Complete the method by displaying an audio device change event message using PostMessage()
.
void CAGEngineEventHandler::onAudioDeviceStateChanged(const char* deviceId, int deviceType, int deviceState)
{
if (m_hMainWnd == NULL)
return;
LPAGE_AUDIO_DEVICE_STATE_CHANGED lpData = new AGE_AUDIO_DEVICE_STATE_CHANGED;
int nDeviceIDLen = strlen(deviceId) + 1;
lpData->deviceId = new char[nDeviceIDLen];
strcpy_s(lpData->deviceId, nDeviceIDLen, deviceId);
lpData->deviceType = deviceType;
lpData->deviceState = deviceState;
::PostMessage(m_hMainWnd, WM_MSGID(EID_AUDIO_DEVICE_STATE_CHANGED), (WPARAM)lpData, 0);
}
The onVideoDeviceStateChanged()
callback triggers when a video device state changes.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_VIDEO_DEVICE_STATE_CHANGED
object and set the device ID, device type, and device state properties lpData->deviceId
, lpData->deviceType
, and lpData->deviceState
.
Note: lpData->deviceId
requires memory allocation prior to setting deviceId
using strcpy_s()
.
Complete the method by displaying a video device change event message using PostMessage()
.
void CAGEngineEventHandler::onVideoDeviceStateChanged(const char* deviceId, int deviceType, int deviceState)
{
if (m_hMainWnd == NULL)
return;
LPAGE_VIDEO_DEVICE_STATE_CHANGED lpData = new AGE_VIDEO_DEVICE_STATE_CHANGED;
int nDeviceIDLen = strlen(deviceId) + 1;
lpData->deviceId = new char[nDeviceIDLen];
strcpy_s(lpData->deviceId, nDeviceIDLen, deviceId);
lpData->deviceType = deviceType;
lpData->deviceState = deviceState;
::PostMessage(m_hMainWnd, WM_MSGID(EID_VIDEO_DEVICE_STATE_CHANGED), (WPARAM)lpData, 0);
}
The onCameraReady()
callback triggers when the camera is ready for use.
If m_hMainWnd
is not NULL
, displaying a camera ready event message using PostMessage()
.
void CAGEngineEventHandler::onCameraReady()
{
if(m_hMainWnd != NULL)
::PostMessage(m_hMainWnd, WM_MSGID(EID_CAMERA_READY), 0, 0);
}
The callbacks in this section trigger when user changes occur.
- Add the onUserJoined() Callback
- Add the onUserOffline() Callback
- Add the onUserMuteAudio() Callback
- Add the onUserMuteVideo() Callback
- Add the onStreamMessage() Callback
- Add the onUserEnableVideo() Callback
The onUserJoined()
callback triggers when a user specified by uid
joins the channel.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_USER_JOINED
object and set the user ID and time elapsed properties lpData->uid
and lpData->elapsed
.
Complete the method by displaying a user joined event message using PostMessage()
.
void CAGEngineEventHandler::onUserJoined(uid_t uid, int elapsed)
{
if (m_hMainWnd == NULL)
return;
LPAGE_USER_JOINED lpData = new AGE_USER_JOINED;
lpData->uid = uid;
lpData->elapsed = elapsed;
::PostMessage(m_hMainWnd, WM_MSGID(EID_USER_JOINED), (WPARAM)lpData, 0);
}
The onUserOffline()
callback triggers when a user specified by uid
goes offline.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_USER_OFFLINE
object and set the user ID and reason properties lpData->uid
and lpData->reason
.
Complete the method by displaying a user offline event message using PostMessage()
.
void CAGEngineEventHandler::onUserOffline(uid_t uid, USER_OFFLINE_REASON_TYPE reason)
{
if (m_hMainWnd == NULL)
return;
LPAGE_USER_OFFLINE lpData = new AGE_USER_OFFLINE;
lpData->uid = uid;
lpData->reason = reason;
::PostMessage(m_hMainWnd, WM_MSGID(EID_USER_OFFLINE), (WPARAM)lpData, 0);
}
The onUserMuteAudio()
callback triggers when a user specified by uid
mutes their audio.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_USER_MUTE_AUDIO
object and set the user ID and mute properties lpData->uid
and lpData->muted
.
Complete the method by displaying a user muted audio event message using PostMessage()
.
void CAGEngineEventHandler::onUserMuteAudio(uid_t uid, bool muted)
{
if (m_hMainWnd == NULL)
return;
LPAGE_USER_MUTE_AUDIO lpData = new AGE_USER_MUTE_AUDIO;
lpData->uid = uid;
lpData->muted = muted;
::PostMessage(m_hMainWnd, WM_MSGID(EID_USER_MUTE_AUDIO), (WPARAM)lpData, 0);
}
The onUserMuteAudio()
callback triggers when a user specified by uid
turns off their video.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_USER_MUTE_VIDEO
object and set the user ID and on or off properties lpData->uid
and lpData->muted
.
Complete the method by displaying a user turned off video event message using PostMessage()
.
void CAGEngineEventHandler::onUserMuteVideo(uid_t uid, bool muted)
{
if (m_hMainWnd == NULL)
return;
LPAGE_USER_MUTE_VIDEO lpData = new AGE_USER_MUTE_VIDEO;
lpData->uid = uid;
lpData->muted = muted;
::PostMessage(m_hMainWnd, WM_MSGID(EID_USER_MUTE_VIDEO), (WPARAM)lpData, 0);
}
The onStreamMessage()
callback triggers when a user specified by uid
sends a message to the stream.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_STREAM_MESSAGE
object and set the user ID, stream ID, data, and length properties lpData->uid
, lpData->streamId
, lpData->data
, and lpData->length
.
Complete the method by displaying a user sent a stream message using PostMessage()
.
void CAGEngineEventHandler::onStreamMessage(uid_t uid, int streamId, const char* data, size_t length)
{
if (m_hMainWnd == NULL)
return;
LPAGE_STREAM_MESSAGE lpData = new AGE_STREAM_MESSAGE;
lpData->uid = uid;
lpData->streamId = streamId;
lpData->data = new char[length];
lpData->length = length;
memcpy_s(lpData->data, length, data, length);
::PostMessage(m_hMainWnd, WM_MSGID(EID_STREAM_MESSAGE), (WPARAM)lpData, 0);
}
The onUserEnableVideo()
callback triggers when a user specified by uid
enables video. This method is not currently set up, but you may add code to update changes to your application or send a message about the event.
void CAGEngineEventHandler::onUserEnableVideo(uid_t uid, bool enabled)
{
// if (m_hMainWnd != NULL)
// ::PostMessage(m_hMainWnd, WM_MSGID(EID_CONNECTION_LOST), 0, 0);
}
The callbacks in this section trigger when connection changes occur.
The onConnectionLost()
callback triggers when the connection is lost.
If m_hMainWnd
is not NULL
, display a connection lost event message using PostMessage()
.
void CAGEngineEventHandler::onConnectionLost()
{
if(m_hMainWnd != NULL)
::PostMessage(m_hMainWnd, WM_MSGID(EID_CONNECTION_LOST), 0, 0);
}
The onConnectionInterrupted()
callback triggers when the connection is interrupted.
Declare a CString
object and set its value to _T("onConnectionInterrupted")
.
void CAGEngineEventHandler::onConnectionInterrupted()
{
CString str;
str = _T("onConnectionInterrupted");
}
The callbacks in this section trigger when changes occur during the recording service.
The onStartRecordingService()
callback triggers when the recording service starts.
If m_hMainWnd
is not NULL
, display a recording service started event message using PostMessage()
.
void CAGEngineEventHandler::onStartRecordingService(int error)
{
if (m_hMainWnd != NULL)
::PostMessage(m_hMainWnd, WM_MSGID(EID_START_RCDSRV), 0, 0);
}
The onStopRecordingService()
callback triggers when the recording service stops.
If m_hMainWnd
is not NULL
, display a recording service stopped event message using PostMessage()
.
void CAGEngineEventHandler::onStopRecordingService(int error)
{
if (m_hMainWnd != NULL)
::PostMessage(m_hMainWnd, WM_MSGID(EID_STOP_RCDSRV), 0, 0);
}
The onRefreshRecordingServiceStatus()
callback triggers when the recording service refreshes.
If m_hMainWnd
is NULL
, end the method.
Declare a new LPAGE_RCDSRV_STATUS
object and set the status property lpData->status
.
Display a recording service refreshed event message using PostMessage()
.
void CAGEngineEventHandler::onRefreshRecordingServiceStatus(int status)
{
if (m_hMainWnd == NULL)
return;
LPAGE_RCDSRV_STATUS lpData = new AGE_RCDSRV_STATUS;
lpData->status = status;
::PostMessage(m_hMainWnd, WM_MSGID(EID_REFREASH_RCDSRV), (WPARAM)lpData, 0);
}