123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- import Event from "../utils/event";
- import User from "../model/user";
- import Stream from "../model/stream";
- import { EVENT } from "../common/constants";
- const TAG_NAME = 'UserController';
- /**
- * 通讯成员管理
- */
- class UserController {
- constructor(componentContext) {
- // userMap 用于存储完整的数据结构
- this.userMap = new Map(); // userList 用于存储简化的用户数据 Object,包括 {userID hasMainAudio hasMainVideo hasAuxAudio hasAuxVideo}
- this.userList = []; // streamList 存储steam 对象列表,用于trtc-room 渲染 player
- this.streamList = [];
- this._emitter = new Event();
- this.componentContext = componentContext;
- this.isNewVersion = componentContext.isNewVersion;
- }
- userEventHandler(event) {
- const code = event.detail.code;
- let data;
- if (event.detail.message && typeof event.detail.message === 'string') {
- try {
- data = JSON.parse(event.detail.message);
- } catch (exception) {
- console.warn(TAG_NAME, 'userEventHandler 数据格式错误', exception);
- return false;
- }
- } else {
- console.warn(TAG_NAME, 'userEventHandler 数据格式错误');
- return false;
- }
- switch (code) {
- case 1020:
- // console.log(TAG_NAME, '远端用户全量列表更新:', code)
- if (!this.isNewVersion) {// TODO 旧版SDK处理逻辑,返回全量的用户列表,需要对userList 进行前后对比,筛选出新增用户,暂不实现
- }
- break;
- case 1031:
- // console.log(TAG_NAME, '远端用户进房通知:', code)
- // 1031 有新用户
- // {
- // "userlist":[
- // {
- // "userid":"webrtc11"
- // }
- // ]
- // }
- this.addUser(data);
- break;
- case 1032:
- // console.log(TAG_NAME, '远端用户退房通知:', code)
- // 1032 有用户退出
- this.removeUser(data);
- break;
- case 1033:
- // console.log(TAG_NAME, '远端用户视频状态位变化通知:', code)
- // 1033 用户视频状态变化,新增stream或者更新stream 状态
- // {
- // "userlist":[
- // {
- // "userid":"webrtc11",
- // "playurl":" room://rtc.tencent.com?userid=xxx&streamtype=main",
- // "streamtype":"main",
- // "hasvideo":true
- // }
- // ]
- // }
- this.updateUserVideo(data);
- break;
- case 1034:
- // console.log(TAG_NAME, '远端用户音频状态位变化通知:', code)
- // 1034 用户音频状态变化
- // {
- // "userlist":[
- // {
- // "userid":"webrtc11",
- // "playurl":" room://rtc.tencent.com?userid=xxx&streamtype=main",
- // "hasaudio":false
- // }
- // ]
- // }
- this.updateUserAudio(data);
- break;
- }
- }
- /**
- * 处理用户进房事件
- * @param {Object} data pusher 下发的数据
- */
- addUser(data) {
- // console.log(TAG_NAME, 'addUser', data)
- const incomingUserList = data.userlist;
- const userMap = this.userMap;
- if (Array.isArray(incomingUserList) && incomingUserList.length > 0) {
- incomingUserList.forEach(item => {
- const userID = item.userid; // 已经在 map 中的用户
- let user = this.getUser(userID);
- if (!user) {
- // 新增用户
- user = new User({
- userID: userID
- });
- this.userList.push({
- userID: userID
- });
- }
- userMap.set(userID, user);
- this._emitter.emit(EVENT.REMOTE_USER_JOIN, {
- userID: userID,
- userList: this.userList
- }); // console.log(TAG_NAME, 'addUser', item, userMap.get(userID), this.userMap)
- });
- }
- }
- /**
- * 处理用户退房事件
- * @param {Object} data pusher 下发的数据 {userlist}
- */
- removeUser(data) {
- // console.log(TAG_NAME, 'removeUser', data)
- const incomingUserList = data.userlist;
- if (Array.isArray(incomingUserList) && incomingUserList.length > 0) {
- incomingUserList.forEach(item => {
- const userID = item.userid;
- let user = this.getUser(userID); // 从userList 里删除指定的用户和 stream
- this._removeUserAndStream(userID); // 重置
- user.streams['main'] && user.streams['main'].reset();
- user.streams['aux'] && user.streams['aux'].reset(); // 用户退出,释放引用,外部调用该 user 所有stream 的 playerContext.stop() 方法停止播放
- // TODO 触发时机提前了,方便外部用户做出处理,时机仍需进一步验证
- this._emitter.emit(EVENT.REMOTE_USER_LEAVE, {
- userID: userID,
- userList: this.userList,
- streamList: this.streamList
- });
- user = undefined;
- this.userMap.delete(userID); // console.log(TAG_NAME, 'removeUser', this.userMap)
- });
- }
- }
- /**
- * 处理用户视频通知事件
- * @param {Object} data pusher 下发的数据 {userlist}
- */
- updateUserVideo(data) {
- // console.log(TAG_NAME, 'updateUserVideo', data)
- const incomingUserList = data.userlist;
- if (Array.isArray(incomingUserList) && incomingUserList.length > 0) {
- incomingUserList.forEach(item => {
- // 修改现有用户属性
- const userID = item.userid;
- const streamType = item.streamtype;
- const hasVideo = item.hasvideo;
- const src = item.playurl;
- const user = this.getUser(userID); // 如果找到该用户,则更新用户的信息和相关的stream 信息
- if (user) {
- let stream = user.streams[streamType]; // console.log(TAG_NAME, 'updateUserVideo', user, streamType, stream)
- // 更新指定的stream
- if (!stream) {
- user.streams[streamType] = stream = new Stream({
- streamType: streamType
- }); // 更新streamList
- this.streamList.push(stream);
- }
- if (hasVideo && streamType === 'aux') {
- stream.objectFit = 'contain';
- }
- if (!hasVideo && streamType === 'aux') {
- // TODO 如果是辅流可能要移除该 stream
- this._removeStream(stream);
- } else {
- stream.userID = userID;
- stream.streamID = userID + '_' + streamType;
- stream.hasVideo = hasVideo;
- stream.src = src;
- } // 更新所属user 的 hasXxx 值
- this.userList.find(item => {
- if (item.userID === userID) {
- item[`has${streamType.replace(/^\S/, s => s.toUpperCase())}Video`] = hasVideo;
- return true;
- }
- });
- const eventName = hasVideo ? EVENT.REMOTE_VIDEO_ADD : EVENT.REMOTE_VIDEO_REMOVE;
- this._emitter.emit(eventName, {
- stream: stream,
- streamList: this.streamList,
- userList: this.userList
- }); // console.log(TAG_NAME, 'updateUserVideo', user, stream, this.userMap)
- }
- });
- }
- }
- /**
- * 处理用户音频通知事件
- * @param {Object} data pusher 下发的数据 {userlist}
- */
- updateUserAudio(data) {
- // console.log(TAG_NAME, 'updateUserAudio', data)
- const incomingUserList = data.userlist;
- if (Array.isArray(incomingUserList) && incomingUserList.length > 0) {
- incomingUserList.forEach(item => {
- const userID = item.userid; // 音频只跟着 stream main ,这里只修改 main
- const streamType = 'main';
- const hasAudio = item.hasaudio;
- const src = item.playurl;
- const user = this.getUser(userID);
- if (user) {
- let stream = user.streams[streamType];
- if (!stream) {
- user.streams[streamType] = stream = new Stream({
- streamType: streamType
- }); // 更新streamList
- this.streamList.push(stream);
- }
- stream.userID = userID;
- stream.streamID = userID + '_' + streamType;
- stream.hasAudio = hasAudio;
- stream.src = src; // 更新所属 user 的 hasXxx 值
- this.userList.find(item => {
- if (item.userID === userID) {
- item[`has${streamType.replace(/^\S/, s => s.toUpperCase())}Audio`] = hasAudio;
- return true;
- }
- });
- const eventName = hasAudio ? EVENT.REMOTE_AUDIO_ADD : EVENT.REMOTE_AUDIO_REMOVE;
- this._emitter.emit(eventName, {
- stream: stream,
- streamList: this.streamList,
- userList: this.userList
- }); // console.log(TAG_NAME, 'updateUserAudio', user, stream, this.userMap)
- }
- });
- }
- }
- /**
- *
- * @param {String} userID 用户ID
- * @returns {Object}
- */
- getUser(userID) {
- return this.userMap.get(userID);
- }
- getStream({
- userID,
- streamType
- }) {
- const user = this.userMap.get(userID);
- if (user) {
- return user.streams[streamType];
- }
- return undefined;
- }
- getUserList() {
- return this.userList;
- }
- getStreamList() {
- return this.streamList;
- }
- /**
- * 重置所有user 和 steam
- * @returns {Object}
- */
- reset() {
- this.streamList.forEach(item => {
- item.reset();
- });
- this.streamList = [];
- this.userList = [];
- this.userMap.clear();
- return {
- userList: this.userList,
- streamList: this.streamList
- };
- }
- on(eventCode, handler, context) {
- this._emitter.on(eventCode, handler, context);
- }
- off(eventCode, handler) {
- this._emitter.off(eventCode, handler);
- }
- /**
- * 删除用户和所有的 stream
- * @param {String} userID 用户ID
- */
- _removeUserAndStream(userID) {
- this.streamList = this.streamList.filter(item => {
- return item.userID !== userID && item.userID !== '';
- });
- this.userList = this.userList.filter(item => {
- return item.userID !== userID;
- });
- }
- _removeStream(stream) {
- this.streamList = this.streamList.filter(item => {
- if (item.userID === stream.userID && item.streamType === stream.streamType) {
- return false;
- }
- return true;
- });
- }
- }
- export default UserController;
|