//
// YouMeVoiceEngineImp.cpp
// TalkCppSample
//
// Created by on 2017/3/21.
//
//
#include "YouMeVoiceEngineImp.hpp"
#include <iostream>
#include <string>
#include "IYouMeVoiceEngine.h"
#include "./common/Common.h"
#include "cocostudio/CocoStudio.h"
#include "common/MShare.h"
#include "ui/ChatRoomUI.h"
#include "manager/UIManagerEx.h"
#include "manager/DollyTextManager.h"
using namespace std;
#include "cocos2d.h"
USING_NS_CC;
extern bool g_voiceInited;
//进入的房间ID
string g_chatRoomName = "";
//登录的频道ID
string g_userID = "";
//进入频道的模式
YouMeUserRole g_roleType = YOUME_USER_NONE;
std::vector<string> g_rolesInChatRoom;
std::map<string, int> g_roleMicInChatRoom;
std::map<string, int> g_roleSpkInChatRoom;
std::string g_YM_AppKey = "";// "YOUME07FE20BE276A57B5E4C8CE6C06D312FF4F7705FF";
std::string g_YM_ApiKey = "";// "1b96380f1a9f2bcbbd88397d78f863cc";
std::string g_YM_SecKey = "";// "t8IKpTDliAHmLPfTgN7vqcjUjCGg2k8MzEU+IHNqGSHRQvmFNuEfvlbZ7GtE+vStD8+0VmwqkaewGP6zAwgjzAres9xdROXmO0aHKwFh16tTVOotWCfUbt6hDDxIFZuvMBrJetAZ/uUCFqR20nXkxs1CH9iXIUoTtKai18BlnzsBAAE=";
YouMeVoiceEngineImp* YouMeVoiceEngineImp::getInstance() {
static YouMeVoiceEngineImp imp;
return &imp;
}
void YouMeVoiceEngineImp::init()
{
if (g_YM_AppKey.empty() || g_YM_SecKey.empty())
{
return;
}
//显示来自声音引擎的信息
static cocos2d::EventListener* g_eventListener = nullptr;
if (!g_eventListener)
{
g_eventListener = EventListenerCustom::create("YouMeEvent", [=](EventCustom* event) {
std::vector<std::vector<std::string> >* pData = (std::vector<std::vector<std::string> >*)event->getUserData();
std::vector<std::vector<std::string> >& data = *pData;
if (data.size() == 1)
{
DollyTextManager::GetInstance()->AddText(data[0][0]);
}
else if (data.size() == 2)
{
g_chatRoomName = data[1][0];
ChatRoomUI* pChatRoomUI = (ChatRoomUI*)UIManagerEx::GetInstance()->GetUI(UI_CHATROOM);
if (pChatRoomUI)
{
pChatRoomUI->OnEnterRoom();
}
}
else if (data.size() == 3)//麦克风扬声器控制
{
int eventType = atoi(data[1][0].c_str());
std::string userId = data[2][0];
ChatRoomUI* pChatRoomUI = (ChatRoomUI*)UIManagerEx::GetInstance()->GetUI(UI_CHATROOM);
if (pChatRoomUI)
{
pChatRoomUI->onOtherEvent(eventType, userId);
}
}
else if (data.size() == 4)
{
ChatRoomUI* pChatRoomUI = (ChatRoomUI*)UIManagerEx::GetInstance()->GetUI(UI_CHATROOM);
if (pChatRoomUI)
{
pChatRoomUI->onMemberChange(data);
}
}
delete pData;
});
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(g_eventListener, 1);
}
YouMeErrorCode errorcode = IYouMeVoiceEngine::getInstance()->init(YouMeVoiceEngineImp::getInstance(), g_YM_AppKey.c_str(), g_YM_SecKey.c_str(), RTC_CN_SERVER, "");
if (YOUME_SUCCESS == errorcode)
{
g_voiceInited = true;
YouMe_Log("YouMe: 调用初始化成功\n");
}
else
{
YouMe_Log("YouMe: 调用初始化失败,错误码:%d\n", errorcode);
}
}
void YouMeVoiceEngineImp::unInit()
{
g_voiceInited = false;
YouMeErrorCode errorcode = IYouMeVoiceEngine::getInstance()->unInit();
if (YOUME_SUCCESS == errorcode)
{
YouMe_Log("YouMe: 反初始化引擎\n");
}
else
{
YouMe_Log("YouMe: 反初始化引擎,错误码:%d\n", errorcode);
}
}
//向场景发送提示消息用于显示
void addTips(string strTips) {
std::vector<std::vector<std::string> >* evtData = new std::vector<std::vector<std::string> >();
std::vector<std::vector<std::string> >& data = *evtData;
data.resize(1);
data[0].push_back(strTips);
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=] {
EventCustom evtEnter("YouMeEvent");
evtEnter.setUserData(evtData);
Director::getInstance()->getEventDispatcher()->dispatchEvent(&evtEnter);
});
}
void YouMeVoiceEngineImp::onEvent(const YouMeEvent event, const YouMeErrorCode error, const char* channel, const char* param) {
YouMe_Log("YouMe: 事件回调:%d, err:%d, 频道id:%s, param:%s\n", event, error, channel, param);
stringstream ssTips;
switch (event) {
case YOUME_EVENT_INIT_OK:
YouMe_Log("YouMe: Talk 语音初始化成功\n");
addTips("语音初始化成功");
break;
case YOUME_EVENT_INIT_FAILED:
YouMe_Log("YouMe: Talk 语音初始化失败\n");
addTips("语音初始化失败");
break;
case YOUME_EVENT_JOIN_OK:
{
YouMe_Log("YouMe: %s\n", (string("进入房间成功") + channel).c_str());
addTips("进入房间成功");
IYouMeVoiceEngine::getInstance()->setMemberChangeCallback(YouMeVoiceEngineImp::getInstance());
std::vector<std::vector<std::string> >* evtData = new std::vector<std::vector<std::string> >();
std::vector<std::vector<std::string> >& data = *evtData;
data.resize(2);
data[0].push_back("EnterRoom");
data[1].push_back(channel);
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=] {
EventCustom evtEnter("YouMeEvent");
evtEnter.setUserData(evtData);
Director::getInstance()->getEventDispatcher()->dispatchEvent(&evtEnter);
});
}
break;
case YOUME_EVENT_JOIN_FAILED:
YouMe_Log("YouMe: %s\n", (string("进入房间失败,ID:") + channel).c_str());
addTips("进入房间失败");
break;
case YOUME_EVENT_LEAVED_ONE:
YouMe_Log("YouMe: Talk 离开单个房间\n");
addTips("离开单个房间");
break;
case YOUME_EVENT_LEAVED_ALL:
YouMe_Log("YouMe: Talk 离开所有房间\n");
addTips("离开房间");
break;
case YOUME_EVENT_PAUSED:
YouMe_Log("YouMe: Talk 语音暂停\n");
addTips("语音暂停");
break;
case YOUME_EVENT_RESUMED:
YouMe_Log("YouMe: Talk 语音恢复\n");
addTips("语音恢复");
break;
case YOUME_EVENT_SPEAK_SUCCESS:///< 切换对指定频道讲话成功(适用于多频道模式)
break;
case YOUME_EVENT_SPEAK_FAILED:///< 切换对指定频道讲话失败(适用于多频道模式)
break;
case YOUME_EVENT_RECONNECTING:///< 断网了,正在重连
YouMe_Log("YouMe: Talk 正在重连\n");
break;
case YOUME_EVENT_BGM_STOPPED:///< 通知背景音乐播放结束
YouMe_Log("YouMe: 背景音乐播放结束,%s\n", param);
addTips("背景音乐播放结束");
break;
case YOUME_EVENT_BGM_FAILED:///< 通知背景音乐播放失败
YouMe_Log("YouMe: 背景音乐播放失败,%s\n", param);
addTips("背景音乐播放失败");
break;
case YOUME_EVENT_SEND_MESSAGE_RESULT:///< sendMessage成功与否的通知,param为回传的requestID
case YOUME_EVENT_MESSAGE_NOTIFY:///< 收到Message, param为message内容
case YOUME_EVENT_RECONNECTED:///< 断网重连成功
case YOUME_EVENT_KICK_RESULT:///< 踢人的应答
case YOUME_EVENT_KICK_NOTIFY:///< 被踢通知 ,param: (踢人者ID,被踢原因,被禁时间)
case YOUME_EVENT_OTHERS_MIC_ON:///< 其他用户麦克风打开
case YOUME_EVENT_OTHERS_MIC_OFF:///< 其他用户麦克风关闭
case YOUME_EVENT_OTHERS_SPEAKER_ON:///< 其他用户扬声器打开
case YOUME_EVENT_OTHERS_SPEAKER_OFF: ///< 其他用户扬声器关闭
case YOUME_EVENT_LOCAL_MIC_ON:///< 自己麦克风打开
case YOUME_EVENT_LOCAL_MIC_OFF:///< 自己麦克风关闭
case YOUME_EVENT_LOCAL_SPEAKER_ON:///< 自己扬声器打开
case YOUME_EVENT_LOCAL_SPEAKER_OFF: ///< 自己扬声器关闭
case YOUME_EVENT_MIC_CTR_ON:///< 麦克风被其他用户打开
case YOUME_EVENT_MIC_CTR_OFF:///< 麦克风被其他用户关闭
case YOUME_EVENT_SPEAKER_CTR_ON:///< 扬声器被其他用户打开
case YOUME_EVENT_SPEAKER_CTR_OFF:///< 扬声器被其他用户关闭
{
std::vector<std::vector<std::string> >* evtData = new std::vector<std::vector<std::string> >();
std::vector<std::vector<std::string> >& data = *evtData;
data.resize(3);
data[0].push_back("OtherEvent");
data[1].push_back(Itoa((int)event));
data[2].push_back(param);
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=] {
EventCustom evtEnter("YouMeEvent");
evtEnter.setUserData(evtData);
Director::getInstance()->getEventDispatcher()->dispatchEvent(&evtEnter);
});
}
break;
case YOUME_EVENT_MY_MIC_LEVEL: ///< 我的讲话音量
YouMe_Log("YouMe: 我的讲话音量:%d\n", error);
break;
default:
break;
}
}
void YouMeVoiceEngineImp::onRequestRestAPI(int requestID, const YouMeErrorCode& iErrorCode, const char* strQuery, const char* strResult)
{
// strQuery:
// {"command":"query_talk_channel_user_count","query":"{\"ChannelID\":\"123456\",\"AreaID\":0}"}
//strResult:
// {"ActionStatus":"OK","ChannelID":"123456","ErrorCode":0,"ErrorInfo":"","UserCount":0}
}
//IYouMeMemberChangeCallback
// channel:频道ID
// memberChangeJsonStr:查询获得的用户列表,或变更列表
// isUpdate: false为第一次查询,true为增量通知
void YouMeVoiceEngineImp::onMemberChange(const char* channel, const char* memberChangeJsonStr, bool bUpdate) {
// memberChangeJsonStr 数据格式:
// {"channelid":"123","memchange":[{"isJoin":true,"userid":"u541"},{"isJoin":true,"userid":"u948"}]}
YouMe_Log("YouMe: 成员变化通知channel");
std::string load_str = memberChangeJsonStr;
rapidjson::Document _doc;
_doc.Parse<0>(load_str.c_str());
if (_doc.HasParseError())
return;
if (!_doc.IsObject())
return;
//是否有此成员
if (!_doc.HasMember("channelid"))
return;
const rapidjson::Value& channelid = _doc["channelid"];
const char* pAttr = channelid.GetString();
if (!pAttr)
return;
//是否有此成员
if (!_doc.HasMember("memchange"))
return;
std::vector<std::vector<std::string> >* evtData = new std::vector<std::vector<std::string> >();
std::vector<std::vector<std::string> >& data = *evtData;
data.resize(4);
data[0].push_back(channel);
data[3].push_back(Itoa(bUpdate));
const rapidjson::Value& pArray = _doc["memchange"];
for (rapidjson::SizeType i = 0; i < pArray.Size(); i++)
{
const rapidjson::Value& p = pArray[i];
if (!p.HasMember("isJoin"))
continue;
if (!p.HasMember("userid"))
continue;
const rapidjson::Value& isJoin = p["isJoin"];
const rapidjson::Value& userid = p["userid"];
pAttr = userid.GetString();
if (!pAttr)
continue;
std::string strUserInfo = str2bin(pAttr);
vector<string> tmp;
fastsplit(tmp, strUserInfo, '|');
if (tmp.size() != 2)
{
continue;
}
if (isJoin.GetBool())
{
data[1].push_back(tmp[1]);
}
else
{
data[2].push_back(tmp[1]);
}
}
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=] {
EventCustom evtEnter("YouMeEvent");
evtEnter.setUserData(evtData);
Director::getInstance()->getEventDispatcher()->dispatchEvent(&evtEnter);
});
}