I am creating a meeting bot that records a conference room by referring to the following example.
https://github.com/zoom/meetingsdk-linux-raw-recording-sample
I succeeded in obtaining raw voice data by joining the conference room with the code.
I want to create a bot as an instance unit on one server and connect it to multiple conference rooms at the same time.
For this, I created a ZoomSession and separated the variables as shown in the code below, but the bot failed to join more than one conference room.
class ZoomSDKSession {
public:
IAuthService* authService;
IMeetingService* meetingService;
ISettingService* settingService;
// Audio related members
std::unique_ptr<ZoomSDKAudioRawData> audioSource;
IZoomSDKAudioRawDataHelper* audioHelper;
// Video related members
std::unique_ptr<ZoomSDKRenderer> videoSource;
IZoomSDKRenderer* videoHelper;
ZoomSDKSession(): authService(nullptr), meetingService(nullptr), settingService(nullptr) {} };
...
session->audioSource = std::make_unique<ZoomSDKAudioRawData>(session->meetingService);
session->videoSource = std::make_unique<ZoomSDKRenderer>();
If the bot first joins a meeting room and then tries to join another meeting room, it fails with the following:
Leaving recording token as NULL
join_meeting:error 2 (SDKERR_WRONG_USAGE,///<Incorrect usage of the feature.
)
Incorrect usage of the feature
The action creates a Session before joining a meeting room and creates services, audio_source, audio_helper, etc.
Please help me solve this.
my code is
// C++ Standard Library
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
#include <thread>
#include <map>
#include <algorithm>
#include <numeric>
#include <mutex>
// System Headers
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
// External Libraries
#include <glib.h>
#include <asio/io_service.hpp>
// Zoom SDK Core
#include "zoom_sdk.h"
#include "auth_service_interface.h"
#include "meeting_service_interface.h"
// Zoom Meeting Components
#include "meeting_service_components/meeting_audio_interface.h"
#include "meeting_service_components/meeting_participants_ctrl_interface.h"
#include "meeting_service_components/meeting_video_interface.h"
#include "meeting_service_components/meeting_recording_interface.h"
// Zoom Settings
#include "setting_service_interface.h"
// Custom Services
#include "MeetingJoinTokenService.h"
#include "WebsocketServer.h"
#include "RestServer.h"
#include "ZoomSDKManager.h"
// Event Listeners
#include "MeetingReminderEventListener.h"
#include "MeetingServiceEventListener.h"
#include "AuthServiceEventListener.h"
#include "MeetingParticipantsCtrlEventListener.h"
#include "MeetingRecordingCtrlEventListener.h"
// Raw Data Handlers
#include "ZoomSDKRenderer.h"
#include "ZoomSDKAudioRawData.h"
#include "ZoomSDKVideoSource.h"
#include "ZoomSDKVirtualAudioMicEvent.h"
#include "rawdata/rawdata_renderer_interface.h"
#include "rawdata/zoom_rawdata_api.h"
// Network Handlers
#include "NetworkConnectionHandler.h"
//The port number the WebSocket server listens on
#define PORT_NUMBER 8080
USING_ZOOM_SDK_NAMESPACE
//references for SendAudioRawData
std::string DEFAULT_AUDIO_SOURCE = "yourwavefile.wav";
//references for SendVideoRawData
std::string DEFAULT_VIDEO_SOURCE = "yourmp4file.mp4";
GMainLoop* loop;
//These are needed to readsettingsfromTEXT named config.txt
std::string recording_token;
//this is used to get a userID, there is no specific proper logic here. It just gets the first userID.
//userID is needed for video subscription.
unsigned int userID;
//this will enable or disable logic to get raw video and raw audio
//do note that this will be overwritten by config.txt
bool GetVideoRawData = false;
bool GetAudioRawData = true;
bool SendVideoRawData = false;
bool SendAudioRawData = false;
std::string g_meeting_number;
std::string g_meeting_password;
void printSDKError(SDKError err) {
switch(err) {
case ZOOM_SDK_NAMESPACE::SDKERR_SUCCESS:
std::cout << "Success" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_NO_IMPL:
std::cout << "This feature is currently invalid" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_WRONG_USAGE:
std::cout << "Incorrect usage of the feature" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_INVALID_PARAMETER:
std::cout << "Wrong parameter" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_MODULE_LOAD_FAILED:
std::cout << "Loading module failed" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_MEMORY_FAILED:
std::cout << "No memory is allocated" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_SERVICE_FAILED:
std::cout << "Internal service error" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_UNINITIALIZE:
std::cout << "Not initialized before the usage" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_UNAUTHENTICATION:
std::cout << "Not authorized before the usage" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_NORECORDINGINPROCESS:
std::cout << "No recording in process" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_TRANSCODER_NOFOUND:
std::cout << "Transcoder module is not found" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_VIDEO_NOTREADY:
std::cout << "The video service is not ready" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_NO_PERMISSION:
std::cout << "No permission" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_UNKNOWN:
std::cout << "Unknown error" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_OTHER_SDK_INSTANCE_RUNNING:
std::cout << "The other instance of the SDK is in process" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_INTERNAL_ERROR:
std::cout << "SDK internal error" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_NO_AUDIODEVICE_ISFOUND:
std::cout << "No audio device found" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_NO_VIDEODEVICE_ISFOUND:
std::cout << "No video device found" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_TOO_FREQUENT_CALL:
std::cout << "API calls too frequently" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_FAIL_ASSIGN_USER_PRIVILEGE:
std::cout << "User can't be assigned with new privilege" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_MEETING_DONT_SUPPORT_FEATURE:
std::cout << "The current meeting doesn't support the feature" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_MEETING_NOT_SHARE_SENDER:
std::cout << "The current user is not the presenter" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_MEETING_YOU_HAVE_NO_SHARE:
std::cout << "There is no sharing" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_MEETING_VIEWTYPE_PARAMETER_IS_WRONG:
std::cout << "Incorrect ViewType parameters" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_MEETING_ANNOTATION_IS_OFF:
std::cout << "Annotation is disabled" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_SETTING_OS_DONT_SUPPORT:
std::cout << "Current OS doesn't support the setting" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_EMAIL_LOGIN_IS_DISABLED:
std::cout << "Email login is disabled" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_HARDWARE_NOT_MEET_FOR_VB:
std::cout << "Computer doesn't meet the minimum requirements to use virtual background feature" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_NEED_USER_CONFIRM_RECORD_DISCLAIMER:
std::cout << "Need process disclaimer" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_NO_SHARE_DATA:
std::cout << "There is no raw data of sharing" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_SHARE_CANNOT_SUBSCRIBE_MYSELF:
std::cout << "Cannot subscribe to own share" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_NOT_IN_MEETING:
std::cout << "Not in meeting" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_NOT_JOIN_AUDIO:
std::cout << "Not joined audio" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_HARDWARE_DONT_SUPPORT:
std::cout << "The current device doesn't support the feature" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_DOMAIN_DONT_SUPPORT:
std::cout << "Domain doesn't support" << std::endl;
break;
case ZOOM_SDK_NAMESPACE::SDKERR_MEETING_REMOTE_CONTROL_IS_OFF:
std::cout << "Remote control is disabled" << std::endl;
break;
default:
std::cout << "Other error occurred" << std::endl;
}
}
//this is a helper method to get the first User ID, it is just an arbitary UserID
uint32_t getUserID(std::string meeting_number) {
auto& manager = ZoomSDKManager::getInstance();
auto session = manager.getSession(meeting_number);
auto participantsController = session->meetingService->GetMeetingParticipantsController();
int returnvalue = participantsController->GetParticipantsList()->GetItem(0);
std::cout << "UserID is : " << returnvalue << std::endl;
return returnvalue;
}
IUserInfo* getMyself(std::string meeting_number) {
auto& manager = ZoomSDKManager::getInstance();
auto session = manager.getSession(meeting_number);
auto participantsController = session->meetingService->GetMeetingParticipantsController();
IUserInfo* returnvalue = participantsController->GetMySelfUser();
return returnvalue;
}
//this is a helper method to get the first User Object, it is just an arbitary User Object
IUserInfo* getUserObj(std::string meeting_number) {
auto& manager = ZoomSDKManager::getInstance();
auto session = manager.getSession(meeting_number);
auto participantsController = session->meetingService->GetMeetingParticipantsController();
int userID = participantsController->GetParticipantsList()->GetItem(0);
IUserInfo* returnvalue = participantsController->GetUserByUserID(userID);
std::cout << "UserID is : " << returnvalue << std::endl;
return returnvalue;
}
//check if you have permission to start raw recording
void CheckAndStartRawRecording(bool isVideo, bool isAudio, std::string meeting_number) {
auto& manager = ZoomSDKManager::getInstance();
auto session = manager.getSession(meeting_number);
if (isVideo || isAudio) {
auto recordController = session->meetingService->GetMeetingRecordingController();
SDKError err2 = recordController->CanStartRawRecording();
if (err2 == SDKERR_SUCCESS) {
SDKError err1 = recordController->StartRawRecording();
std::cout << "StartRawRecording : " << err1 << std::endl;
if (err1 != SDKERR_SUCCESS) {
std::cout << "Error occurred starting raw recording" << std::endl;
}
else {
//GetAudioRawData
if (isAudio) {
session->audioHelper = GetAudioRawdataHelper();
if (session->audioHelper && session->audioSource) {
SDKError err = session->audioHelper->subscribe(session->audioSource.get());
if (err != SDKERR_SUCCESS) {
std::cout << "Error occurred subscribing to audio : " << err << std::endl;
}
}
else {
std::cout << "Error getting audioHelper" << std::endl;
}
}
}
}
else {
std::cout << "Cannot start raw recording: no permissions yet, need host, co-host, or recording privilege" << std::endl;
}
}
}
//callback when given host permission
void onIsHost(std::string meeting_number) {
printf("Is host now...\n");
CheckAndStartRawRecording(GetVideoRawData, GetAudioRawData, meeting_number);
}
//callback when given cohost permission
void onIsCoHost(std::string meeting_number) {
printf("Is co-host now...\n");
CheckAndStartRawRecording(GetVideoRawData, GetAudioRawData, meeting_number);
}
//callback when given recording permission
void onIsGivenRecordingPermission(std::string meeting_number) {
printf("Is given recording permissions now...\n");
CheckAndStartRawRecording(GetVideoRawData, GetAudioRawData, meeting_number);
}
//callback when the SDK is inmeeting
void onInMeeting(std::string meeting_number) {
std::cout<<"onInMeeting Invoked : " << meeting_number <<std::endl;
auto& manager = ZoomSDKManager::getInstance();
auto session = manager.getSession(meeting_number);
MeetingStatus status = session->meetingService->GetMeetingStatus();
std::cout<<status<<std::endl;
switch (status)
{
case MEETING_STATUS_IDLE:
printf("No meeting is running.\n");
break;
case MEETING_STATUS_CONNECTING:
printf("Connect to the meeting server status.\n");
break;
case MEETING_STATUS_WAITINGFORHOST:
printf("Waiting for the host to start the meeting.\n");
break;
case MEETING_STATUS_INMEETING:
printf("onMeetingStatusChanged() In Meeting.\n");
// if (onInMeeting_) onInMeeting_(meeting_number_);
break;
case MEETING_STATUS_DISCONNECTING:
printf("Disconnect the meeting server, leave meeting status.\n");
break;
case MEETING_STATUS_RECONNECTING:
printf("Reconnecting meeting server status\n");
break;
case MEETING_STATUS_FAILED:
printf("Failed to connect the meeting server.\n");
break;
case MEETING_STATUS_ENDED:
printf("Meeting ends.\n");
// if (onMeetingEnds_) onMeetingEnds_(meeting_number_);
break;
case MEETING_STATUS_UNKNOW:
printf("Unknown status.\n");
break;
case MEETING_STATUS_LOCKED:
printf("Meeting is locked to prevent the further participants to join the meeting.\n");
break;
case MEETING_STATUS_UNLOCKED:
printf("Meeting is open and participants can join the meeting.\n");
break;
case MEETING_STATUS_IN_WAITING_ROOM:
printf("Participants who join the meeting before the start are in the waiting room.\n");
break;
default:
printf("other");
break;
}
//double check if you are in a meeting
if (status == ZOOM_SDK_NAMESPACE::MEETING_STATUS_INMEETING) {
printf("In Meeting Now...\n");
//print all list of participants
IList<unsigned int>* participants = session->meetingService->GetMeetingParticipantsController()->GetParticipantsList();
for(int i = 0; i < participants->GetCount(); i++){
IUserInfo* user = session->meetingService->GetMeetingParticipantsController()->GetUserByUserID(participants->GetItem(i));
printf("[User %d]\n", i);
printf("id: %d, name: %s\n", user->GetUserID(), user->GetUserName());
}
printf("Participants count: %d\n", participants->GetCount());
// request local recoding
auto recordController = session->meetingService->GetMeetingRecordingController();
recordController->RequestLocalRecordingPrivilege();
}
//first attempt to start raw recording / sending, upon successfully joined and achieved "in-meeting" state.
CheckAndStartRawRecording(GetVideoRawData, GetAudioRawData, meeting_number);
// CheckAndStartRawSending(SendVideoRawData, SendAudioRawData);
}
//on meeting ended, typically by host, do something here. it is possible to reuse this SDK instance
void onMeetingEndsQuitApp(std::string meeting_number) {
// CleanSDK();
//std::exit(0);
}
void onMeetingJoined(std::string meeting_number) {
std::cout << "Joining Meeting("<<meeting_number<<")... "<<std::endl;
}
std::string getMeetingToken(std::string meeting_number)
{
//meeting_number
MeetingJoinTokenService& meetingJoinTokenService = MeetingJoinTokenService::GetInstance();
std::string token = meetingJoinTokenService.getToken(meeting_number);
return token;
}
void CleanSDK()
{
ZOOM_SDK_NAMESPACE::SDKError err(ZOOM_SDK_NAMESPACE::SDKERR_SUCCESS);
ZoomSDKManager::getInstance().cleanup();
//attempt to clean up SDK
err = ZOOM_SDK_NAMESPACE::CleanUPSDK();
if (err != ZOOM_SDK_NAMESPACE::SDKERR_SUCCESS)
{
std::cerr << "CleanSDK meetingSdk:error " << std::endl;
}
else
{
std::cerr << "CleanSDK meetingSdk:success" << std::endl;
}
}
void JoinMeeting(std::string meeting_number, std::string meeting_password)
{
std::cerr << "Joining Meeting" << std::endl;
SDKError err2(SDKError::SDKERR_SUCCESS);
auto& manager = ZoomSDKManager::getInstance();
auto session = manager.getSession(meeting_number);
session->audioSource = std::make_unique<ZoomSDKAudioRawData>(session->meetingService);
session->videoSource = std::make_unique<ZoomSDKRenderer>();
std::cerr << "Settingservice created." << std::endl;
// Set the event listener for meeting status
session->meetingService->SetEvent(new MeetingServiceEventListener(&onMeetingJoined, &onMeetingEndsQuitApp, &onInMeeting, meeting_number));
// Set the event listener for host, co-host
auto participantsController = session->meetingService->GetMeetingParticipantsController();
participantsController->SetEvent(new MeetingParticipantsCtrlEventListener(&onIsHost, &onIsCoHost, meeting_number));
// Set the event listener for recording privilege status
auto recordController = session->meetingService->GetMeetingRecordingController();
recordController->SetEvent(new MeetingRecordingCtrlEventListener(&onIsGivenRecordingPermission, meeting_number));
// set event listnener for prompt handler
IMeetingReminderController* meetingremindercontroller = session->meetingService->GetMeetingReminderController();
MeetingReminderEventListener* meetingremindereventlistener = new MeetingReminderEventListener();
meetingremindercontroller->SetEvent(meetingremindereventlistener);
//prepare params used for joining meeting
ZOOM_SDK_NAMESPACE::JoinParam joinParam;
ZOOM_SDK_NAMESPACE::SDKError err(ZOOM_SDK_NAMESPACE::SDKERR_SERVICE_FAILED);
joinParam.userType = ZOOM_SDK_NAMESPACE::SDK_UT_WITHOUT_LOGIN;
ZOOM_SDK_NAMESPACE::JoinParam4WithoutLogin& withoutloginParam = joinParam.param.withoutloginuserJoin;
// withoutloginParam.meetingNumber = 1231231234;
withoutloginParam.meetingNumber = std::stoull(meeting_number);
withoutloginParam.vanityID = NULL;
withoutloginParam.userName = "Bot";
// withoutloginParam.psw = "1";
withoutloginParam.psw = meeting_password.c_str();
withoutloginParam.customer_key = NULL;
withoutloginParam.webinarToken = NULL;
withoutloginParam.isVideoOff = false;
withoutloginParam.isAudioOff = false;
// std::cerr << "JWT token is " << token << std::endl;
std::cerr << "Recording token is " << recording_token << std::endl;
//automatically set app_privilege token if it is present in config.txt, or retrieved from web service
withoutloginParam.app_privilege_token = NULL;
if (!recording_token.size() == 0)
{
withoutloginParam.app_privilege_token = recording_token.c_str();
std::cerr << "Setting recording token" << std::endl;
}
else
{
withoutloginParam.app_privilege_token = NULL;
std::cerr << "Leaving recording token as NULL" << std::endl;
}
MeetingStatus status = session->meetingService->GetMeetingStatus();
std::cout<<"Meeting status : " << status << std::endl;
if (GetAudioRawData) {
//set join audio to true
ZOOM_SDK_NAMESPACE::IAudioSettingContext* pAudioContext = session->settingService->GetAudioSettings();
if (pAudioContext)
{
//ensure auto join audio
pAudioContext->EnableAutoJoinAudio(true);
}
}
if (SendVideoRawData) {
//ensure video is turned on
withoutloginParam.isVideoOff = false;
//set join video to true
ZOOM_SDK_NAMESPACE::IVideoSettingContext* pVideoContext = session->settingService->GetVideoSettings();
if (pVideoContext)
{
pVideoContext->EnableAutoTurnOffVideoWhenJoinMeeting(false);
}
}
if (SendAudioRawData) {
ZOOM_SDK_NAMESPACE::IAudioSettingContext* pAudioContext = session->settingService->GetAudioSettings();
if (pAudioContext)
{
//ensure auto join audio
pAudioContext->EnableAutoJoinAudio(true);
pAudioContext->EnableAlwaysMuteMicWhenJoinVoip(true);
pAudioContext->SetSuppressBackgroundNoiseLevel(Suppress_BGNoise_Level_None);
}
}
//attempt to join meeting
if (session->meetingService)
{
err = session->meetingService->Join(joinParam);
}
else
{
std::cout << "join_meeting m_pMeetingService:Null" << std::endl;
}
if (ZOOM_SDK_NAMESPACE::SDKERR_SUCCESS == err)
{
std::cout << "join_meeting:success" << std::endl;
}
else
{
std::cout << "join_meeting:error " << err << std::endl;
manager.removeSession(meeting_number);
printSDKError(err);
}
// g_meeting_number = "";
// g_meeting_password = "";
}
//callback when authentication is compeleted
void OnAuthenticationComplete()
{
std::cout << "OnAuthenticationComplete number:" << g_meeting_number << " / password: " << g_meeting_password << std::endl;
JoinMeeting(g_meeting_number, g_meeting_password);
}
void AuthMeetingSDK(std::string meeting_number, std::string meeting_password)
{
auto& manager = ZoomSDKManager::getInstance();
if (!manager.createSession(meeting_number)) {
std::cerr << "Failed to create session for meeting " << meeting_number << std::endl;
return;
}
auto session = manager.getSession(meeting_number);
if (!session) {
std::cerr << "Failed to get session for meeting " << meeting_number << std::endl;
return;
}
SDKError err(SDKError::SDKERR_SUCCESS);
std::string token = getMeetingToken(meeting_number);
//create auth service
// if ((err = CreateAuthService(&m_pAuthService)) != SDKError::SDKERR_SUCCESS) {};
// std::cerr << "AuthService created." << std::endl;
g_meeting_number = meeting_number;
g_meeting_password = meeting_password;
//Create a param to insert jwt token
ZOOM_SDK_NAMESPACE::AuthContext param;
// Origin
if ((err = session->authService->SetEvent(new AuthServiceEventListener(&OnAuthenticationComplete))) != SDKError::SDKERR_SUCCESS) {
std::cerr << "Failed to set event for auth service result callback" << meeting_number << std::endl;
} else {
std::cout<< "Success set event for auth service result callback" <<std::endl;
};
if (!token.size() == 0){
param.jwt_token = token.c_str();
std::cerr << "AuthSDK:token generate : " << param.jwt_token << std::endl;
}
session->authService->SDKAuth(param);
std::cout<< "Success SDKAuth" <<std::endl;
}
void InitMeetingSDK()
{
ZOOM_SDK_NAMESPACE::SDKError err(ZOOM_SDK_NAMESPACE::SDKERR_SUCCESS);
ZOOM_SDK_NAMESPACE::InitParam initParam;
// set domain
initParam.strWebDomain = "https://zoom.us";
initParam.strSupportUrl = "https://zoom.us";
// set language id
initParam.emLanguageID = ZOOM_SDK_NAMESPACE::LANGUAGE_English;
//set logging perferences
initParam.enableLogByDefault = true;
initParam.enableGenerateDump = true;
// attempt to initialize
err = ZOOM_SDK_NAMESPACE::InitSDK(initParam);
if (err != ZOOM_SDK_NAMESPACE::SDKERR_SUCCESS){
std::cerr << "Init meetingSdk:error " << std::endl;
}
else{
std::cerr << "Init meetingSdk:success" << std::endl;
}
}
// Define a struct to hold the response data
struct ResponseData {
std::ostringstream stream;
};
// Callback function to write response data into the stringstream
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t totalSize = size * nmemb;
ResponseData* response = static_cast<ResponseData*>(userp);
response->stream.write(static_cast<const char*>(contents), totalSize);
return totalSize;
}
gboolean timeout_callback(gpointer data)
{
return TRUE;
}
//this catches a break signal, such as Ctrl + C
void my_handler(int s)
{
printf("\nCaught signal %d\n", s);
// LeaveMeeting();
printf("Leaving session.\n");
CleanSDK();
WebsocketServer::getInstance().stop();
RestServer::getInstance().stop();
//InitMeetingSDK();
//AuthMeetingSDK();
std::exit(0);
}
void initAppSettings()
{
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = my_handler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
}
void setupWebsocketServer(WebsocketServer& server, asio::io_service& io_service)
{
server.connect([&io_service, &server](ClientConnection conn)
{
io_service.post([conn, &server]()
{
std::clog << "Connection opened." << std::endl;
std::clog << "There are now " << server.numConnections() << " open connections." << std::endl;
Json::Value jsonData;
jsonData["userName"] = "bot";
jsonData["text"] = "hello";
server.sendMessage(conn, "message", jsonData);
});
});
server.disconnect([&io_service, &server](ClientConnection conn)
{
io_service.post([conn, &server]()
{
std::clog << "Connection closed." << std::endl;
std::clog << "There are now " << server.numConnections() << " open connections." << std::endl;
});
});
server.message("message", [&io_service, &server](ClientConnection conn, const Json::Value& args)
{
io_service.post([conn, args, &server]()
{
std::clog << "message handler on the main thread" << std::endl;
std::clog << "Message payload:" << std::endl;
for (auto key : args.getMemberNames()) {
std::clog << "\t" << key << ": " << args[key].asString() << std::endl;
}
server.sendMessage(conn, "message", args);
std::clog << "numConnections : " << server.numConnections() << std::endl;
});
});
}
void inviteCallback(std::string meeting_number, std::string password) {
std::cout << "Default join meeting callback - Meeting: " << meeting_number << " / password : " << password << std::endl;
AuthMeetingSDK(meeting_number, password);
}
int main(int argc, char* argv[])
{
InitMeetingSDK();
initAppSettings();
asio::io_service io_service;
asio::io_service::work work(io_service);
WebsocketServer& server = WebsocketServer::getInstance();
setupWebsocketServer(server, io_service);
server.run(PORT_NUMBER);
RestServer& restServer = RestServer::getInstance();
restServer.addEndpoints();
restServer.addInviteEndpoint(inviteCallback);
restServer.start();
loop = g_main_loop_new(NULL, FALSE);
g_timeout_add(0, [](gpointer user_data) -> gboolean {
asio::io_service* io = static_cast<asio::io_service*>(user_data);
io->poll();
return G_SOURCE_CONTINUE;
}, &io_service);
g_timeout_add(1000, timeout_callback, loop);
g_main_loop_run(loop);
g_main_loop_unref(loop);
// serverThread.join();
return 0;
}