agora-edu-core
Version:
Core APIs for building an online classroom
869 lines (843 loc) • 40.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.StreamStore = void 0;
require("core-js/modules/esnext.set.add-all.js");
require("core-js/modules/esnext.set.delete-all.js");
require("core-js/modules/esnext.set.difference.js");
require("core-js/modules/esnext.set.every.js");
require("core-js/modules/esnext.set.filter.js");
require("core-js/modules/esnext.set.find.js");
require("core-js/modules/esnext.set.intersection.js");
require("core-js/modules/esnext.set.is-disjoint-from.js");
require("core-js/modules/esnext.set.is-subset-of.js");
require("core-js/modules/esnext.set.is-superset-of.js");
require("core-js/modules/esnext.set.join.js");
require("core-js/modules/esnext.set.map.js");
require("core-js/modules/esnext.set.reduce.js");
require("core-js/modules/esnext.set.some.js");
require("core-js/modules/esnext.set.symmetric-difference.js");
require("core-js/modules/esnext.set.union.js");
require("core-js/modules/esnext.map.delete-all.js");
require("core-js/modules/esnext.map.every.js");
require("core-js/modules/esnext.map.filter.js");
require("core-js/modules/esnext.map.find.js");
require("core-js/modules/esnext.map.find-key.js");
require("core-js/modules/esnext.map.includes.js");
require("core-js/modules/esnext.map.key-of.js");
require("core-js/modules/esnext.map.map-keys.js");
require("core-js/modules/esnext.map.map-values.js");
require("core-js/modules/esnext.map.merge.js");
require("core-js/modules/esnext.map.reduce.js");
require("core-js/modules/esnext.map.some.js");
require("core-js/modules/esnext.map.update.js");
var _agoraRteSdk = require("agora-rte-sdk");
var _mobx = require("mobx");
var _type = require("../../../../type");
var _configs = require("../../../../configs");
var _utils = require("../../../../utils");
var _error = require("../../../../utils/error");
var _base = require("../base");
var _struct = require("./struct");
var _eventCenter = require("../../../../event-center");
var _ = require("../../../..");
var _class, _descriptor, _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _class2, _descriptor2, _SceneEventHandler;
function _initializerDefineProperty(e, i, r, l) { r && Object.defineProperty(e, i, { enumerable: r.enumerable, configurable: r.configurable, writable: r.writable, value: r.initializer ? r.initializer.call(l) : void 0 }); }
function _applyDecoratedDescriptor(i, e, r, n, l) { var a = {}; return Object.keys(n).forEach(function (i) { a[i] = n[i]; }), a.enumerable = !!a.enumerable, a.configurable = !!a.configurable, ("value" in a || a.initializer) && (a.writable = !0), a = r.slice().reverse().reduce(function (r, n) { return n(i, e, r) || r; }, a), l && void 0 !== a.initializer && (a.value = a.initializer ? a.initializer.call(l) : void 0, a.initializer = void 0), void 0 === a.initializer ? (Object.defineProperty(i, e, a), null) : a; }
function _initializerWarningHelper(r, e) { throw Error("Decorating class property failed. Please ensure that transform-class-properties is enabled and runs after the decorators transform."); }
/**
* `StreamStore` 类用于管理媒体流。
*/
/** @en
* The `StreamStore` class is used for managing media streams.
*/
let StreamStore = exports.StreamStore = (_class = class StreamStore extends _base.EduStoreBase {
constructor(...args) {
super(...args);
this._disposers = [];
this._streamMessageListeners = new Set();
this._streamMessageScene = void 0;
this._handleSceneStreamMessage = (streamId, message) => {
this._streamMessageListeners.forEach(listener => listener(streamId, message));
};
_initializerDefineProperty(this, "_dataStore", _descriptor, this);
}
/**
* @internal
*
* 主房间数据信息
*/
/** @en
* @internal
*
* main store datastore
*/
get mainRoomDataStore() {
const scene = this.classroomStore.connectionStore.mainRoomScene;
const handler = SceneEventHandler.getEventHandler(scene);
return handler.dataStore;
}
/**
* @internal
*
* 分组房间数据信息
*/
/** @en
* @internal
*
* sub store datastore
*/
get subRoomDataStore() {
const scene = this.classroomStore.connectionStore.subRoomScene;
const handler = SceneEventHandler.getEventHandler(scene);
return handler.dataStore;
}
/**
* 本地屏幕共享流信息
* streamUuid: 流 UUID
* shareStreamToken: 流 Token
*/
/** @en
* Local screen stream info
* streamUuid: Stream UUID
* shareStreamToken: Stream token
*/
get _screenShareTokenAccessor() {
return {
streamUuid: this.localShareStreamUuid,
shareStreamToken: this.shareStreamToken
};
}
/**
* 房间内流信息列表
* key: 流 UUID
* value: 流对象
*/
/** @en
* Streams in the room
* key: Stream UUID
* value: Stream object
*/
get streamByStreamUuid() {
return this._dataStore.streamByStreamUuid;
}
/**
* 房间内用户流信息列表
* key: 用户 UUID
* value: 流 UUID 集合
*/
/** @en
* Stream UUID set indexed by User UUID
* key: User UUID
* value: Set of stream UUID
*/
get streamByUserUuid() {
return this._dataStore.streamByUserUuid;
}
/**
* 音量列表
* key: 流 UUID
* value: 音量值,范围:0 ~ 1
*/
/** @en
* Volume list indexed by stream UUID
* key: Stream UUID
* value: volume value, range by: 0 ~ 1
*/
get streamVolumes() {
return this._dataStore.streamVolumes;
}
/**
* 屏幕共享 Tokens
* key: 流 UUID
* value: RTC Token
*/
/** @en
* Screen share tokens
* key: Stream UUID
* value: RTC token
*/
get shareStreamTokens() {
return this._dataStore.shareStreamTokens;
}
/**
* 本地屏幕共享 Token
*/
/** @en
* Local screen share token
*/
get shareStreamToken() {
const streamUuid = this.localShareStreamUuid;
if (!streamUuid) {
return undefined;
}
return this.shareStreamTokens.get(streamUuid);
}
/**
* 本地摄像头视频流 UUID
*/
/** @en
* Loal camera stream UUID
*/
get localCameraStreamUuid() {
const {
sessionInfo: {
userUuid
}
} = _configs.EduClassroomConfig.shared;
const streamUuids = this.streamByUserUuid.get(userUuid) || new Set();
for (const streamUuid of streamUuids) {
const stream = this.streamByStreamUuid.get(streamUuid);
if (stream && stream.videoSourceType === _agoraRteSdk.AgoraRteVideoSourceType.Camera) {
return stream.streamUuid;
}
}
return undefined;
}
/**
* 本地麦克风音频流 UUID
*/
/** @en
* Local microphone stream UUID
*/
get localMicStreamUuid() {
const {
sessionInfo: {
userUuid
}
} = _configs.EduClassroomConfig.shared;
const streamUuids = this.streamByUserUuid.get(userUuid) || new Set();
for (const streamUuid of streamUuids) {
const stream = this.streamByStreamUuid.get(streamUuid);
if (stream && stream.audioSourceType === _agoraRteSdk.AgoraRteAudioSourceType.Mic) {
return stream.streamUuid;
}
}
return undefined;
}
/**
* 本地屏幕共享视频流 UUID
**/
/** @en
* Local screen stream UUID
*/
get localShareStreamUuid() {
const {
sessionInfo: {
userUuid
}
} = _configs.EduClassroomConfig.shared;
const streamUuids = this.streamByUserUuid.get(userUuid) || new Set();
for (const streamUuid of streamUuids) {
const stream = this.streamByStreamUuid.get(streamUuid);
if (stream && stream.videoSourceType === _agoraRteSdk.AgoraRteVideoSourceType.ScreenShare) {
return stream.streamUuid;
}
}
return undefined;
}
/**
* 初始化屏幕共享流
* @param scene 房间对象
* @param streamUuid 流 UUID
* @param rtcToken RTC Token
*/
/** @en
* Initializes the screen stream
* @param scene Room object
* @param streamUuid Stream UUID
* @param rtcToken RTC Token
*/
initializeScreenShareStream(scene, streamUuid, rtcToken) {
SceneEventHandler.getEventHandler(scene).dataStore.shareStreamTokens.set(streamUuid, rtcToken);
}
/**
* 销毁屏幕共享流
* @param scene 房间对象
*/
/** @en
* Destroys the screen stream
* @param scene Room object
*/
destroyScreenShareStream(scene) {
SceneEventHandler.getEventHandler(scene).dataStore.shareStreamTokens.clear();
}
/**
* 设置远端视频质量
* @param streamUuid 要设置的流的 UUID
* @param remoteVideoStreamType 要设置的流类型
* @param fromScene 流所在的房间对象,不传默认为当前房间
**/
/** @en
* Sets the remote video stream quality type
* @param streamUuid The UUID of the stream to be set
* @param remoteVideoStreamType The stream type to set
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
async setRemoteVideoStreamType(streamUuid, remoteVideoStreamType, fromScene) {
try {
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
await scene.setRemoteVideoStreamType(streamUuid, remoteVideoStreamType);
}
} catch (e) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_SET_REMOTE_VIDEO_STREAM_TYPE_FAIL, new Error(`failed to set remote video stream type, streamId is ${streamUuid}`));
}
}
/**
* 渲染远端视频
* @param stream 流对象
* @param dom 渲染节点
* @param mirror 是否镜像
* @param renderMode 填充方式
* @param fromScene 流所在的房间对象,不传默认为当前房间
**/
/** @en
* Renders the remote video
* @param stream Stream object
* @param dom DOM node
* @param mirror Whether to apply mirror
* @param renderMode Mode of rendering video
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
setupRemoteVideo(stream, dom, mirror, renderMode, fromScene) {
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
var _scene$localUser;
const canvas = new _agoraRteSdk.AgoraRtcVideoCanvas(stream.streamUuid, scene.sceneId, dom, {
mirror,
renderMode
});
(_scene$localUser = scene.localUser) === null || _scene$localUser === void 0 ? void 0 : _scene$localUser.setupRemoteVideo(canvas);
}
}
/**
* 订阅/取消远端视频流
* @param stream 流对象
* @param muted 是否订阅
* @param fromScene 流所在的房间对象,不传默认为当前房间
*/
/** @en
* Subscribes/Unsubscribes the remote video stream
* @param stream Stream object
* @param muted Whether to subscribe
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
muteRemoteVideoStream(stream, muted, fromScene) {
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
scene.muteRemoteVideoStream(stream.streamUuid, muted);
}
}
/**
* 订阅/取消远端音频流
* @param stream 流对象
* @param muted 是否订阅
* @param fromScene 流所在的房间对象,不传默认为当前房间
*/
/** @en
* Subscribes/Unsubscribes the remote audio stream
* @param stream Stream object
* @param muted Whether to subscribe
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
muteRemoteAudioStream(stream, muted, fromScene) {
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
scene.muteRemoteAudioStream(stream.streamUuid, muted);
}
}
/**
* 批量订阅
* @param streams 流对象列表
* @param muted 是否订阅
* @param fromScene 流所在的房间对象,不传默认为当前房间
*/
/** @en
* Subscribes a batch of streams
* @param streams Set of stream object
* @param muted Whether to subscribe
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
muteRemoteVideoStreamMass(streams, muted, fromScene) {
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
const streamUuids = streams.map(({
streamUuid
}) => streamUuid);
return scene.muteRemoteVideoStreamMass(streamUuids, muted);
}
}
/**
* 更新本地音频和视频发布状态
* @param state 音频和视频发布状态
* @param fromScene 流所在的房间对象,不传默认为当前房间
*
**/
/** @en
* Updates the local audio ad video publishing states
* @param state The audio ad video publishing state
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
async updateLocalPublishState(state, fromScene) {
try {
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
var _scene$localUser2;
await ((_scene$localUser2 = scene.localUser) === null || _scene$localUser2 === void 0 ? void 0 : _scene$localUser2.updateLocalMediaStream({
publishVideo: state.videoState,
publishAudio: state.audioState
}));
}
} catch (e) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_MEDIA_LOCAL_PUBLISH_STATE_UPDATE_FAIL, e);
}
}
/**
* 更新远端音频和视频发布状态
* @param userUuid 用户 ID
* @param streamUuid 流 ID
* @param state 音频和视频发布状态
* @param fromScene 流所在的房间对象,不传默认为当前房间
**/
/** @en
* Updates the remote audio ad video publishing states
* @param userUuid The user ID
* @param streamUuid The stream ID
* @param state The audio ad video publishing state
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
async updateRemotePublishState(userUuid, streamUuid, state, fromScene) {
try {
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
var _scene$localUser3;
await ((_scene$localUser3 = scene.localUser) === null || _scene$localUser3 === void 0 ? void 0 : _scene$localUser3.updateRemoteMediaStream(userUuid, streamUuid, {
publishVideo: state.videoState,
publishAudio: state.audioState
}));
}
} catch (e) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_MEDIA_REMOTE_PUBLISH_STATE_UPDATE_FAIL, e);
}
}
/**
* 批量更新远端音频和视频发布状态
* @param streams 流列表
**/
/** @en
* Batch updates the remote audio ad video publishing states
* @param streams list of stream
*/
async updateRemotePublishStateBatch(streams, fromScene) {
try {
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
await scene.updateRemoteMediaStreamBatch(streams);
}
} catch (e) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_MEDIA_REMOTE_PUBLISH_STATE_UPDATE_FAIL, e);
}
}
/**
* 旁路推流,将当前已发布的流推送到CDN
* @param fromScene 流所在的房间对象,不传默认为当前房间
*/
/** @en
* Bypass push, pushs the currently published stream to CDN
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
async publishStreamToCdn(fromScene) {
try {
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
var _scene$localUser4;
await ((_scene$localUser4 = scene.localUser) === null || _scene$localUser4 === void 0 ? void 0 : _scene$localUser4.publishStreamToCdn());
}
} catch (e) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_MEDIA_REMOTE_PUBLISH_CDN_STREAM_FAIL, e);
}
}
/**
* 更新视频墙开关状态和发流用户列表
* @param state 1 开启视频墙 0 关闭视频墙
* @param data userUuids 发流用户列表
*/
/** @en
* Updates the status and users of the video gallery
* @param state 1 open 0 close
* @param data userUuids users who publish streams
*/
async updateExpandedScopeAndStreams(state, data) {
const roomUuid = _configs.EduClassroomConfig.shared.sessionInfo.roomUuid;
try {
await this.api.updateExpandedScopeAndStreams(roomUuid, state, data);
} catch (err) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_ULTRA_VIDEO_WALL_UPDATE_STREAMS_FAIL, err);
}
}
/**
* 为本地用户创建一条屏幕共享流,返回已创建的流ID与Token。
* 此方法只允许房间内创建一路屏幕共享流,若房间内需要同时存在多路屏幕流,请使用 publishScreenShareStateless
* @param fromScene 流所在的房间对象,不传默认为当前房间
* @param streamOptions 发流选项
*/
/** @en
* Creates a screen share stream for the local user, returns the stream id and the token of the created stream.
* This method only allows creating one screen share stream in the room, if multiple streams are needed, please use publishScreenShareStateless
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
* @param streamOptions Options for publishing stream
*/
async publishScreenShare(fromScene, streamOptions) {
try {
const userUuid = _configs.EduClassroomConfig.shared.sessionInfo.userUuid;
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
const res = await this.classroomStore.api.startShareScreen(scene.sceneId, userUuid, streamOptions);
return res;
}
} catch (e) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_MEDIA_START_SCREENSHARE_FAIL, e);
}
}
/**
* 取消发布屏幕共享流
* @param fromScene 流所在的房间对象,不传默认为当前房间
*/
/** @en
* Removes the screen share stream that is created for the local user before
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
async unpublishScreenShare(fromScene) {
try {
const userUuid = _configs.EduClassroomConfig.shared.sessionInfo.userUuid;
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
await this.classroomStore.api.stopShareScreen(scene.sceneId, userUuid);
}
} catch (e) {
if (!_agoraRteSdk.AGError.isOf(e, _.AGServiceErrorCode.SERV_SCREEN_NOT_SHARED)) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_MEDIA_STOP_SCREENSHARE_FAIL, e);
}
}
}
/**
* 为本地用户创建一条屏幕共享流,返回已创建的流ID与Token。
* 此方法允许房间内创建多路屏幕共享流
* @param fromScene 流所在的房间对象,不传默认为当前房间
*/
/** @en
* Creates a screen share stream for the local user, returns the stream id and the token of the created stream.
* This method allows creating multiple screen share streams in the room
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
async publishScreenShareStateless(fromScene) {
try {
const userUuid = _configs.EduClassroomConfig.shared.sessionInfo.userUuid;
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
const res = await this.classroomStore.api.startShareScreenStateless(scene.sceneId, userUuid);
return res;
}
} catch (e) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_MEDIA_START_SCREENSHARE_FAIL, e);
}
}
/**
* 取消发布屏幕共享流
* @param fromScene 流所在的房间对象,不传默认为当前房间
*/
/** @en
* Removes the screen share stream that is created for the local user before
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
async unpublishScreenShareStateless(fromScene) {
try {
const userUuid = _configs.EduClassroomConfig.shared.sessionInfo.userUuid;
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : this.classroomStore.connectionStore.scene;
if (scene) {
await this.classroomStore.api.stopShareScreenStateless(scene.sceneId, userUuid);
}
} catch (e) {
if (!_agoraRteSdk.AGError.isOf(e, _.AGServiceErrorCode.SERV_SCREEN_NOT_SHARED)) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_MEDIA_STOP_SCREENSHARE_FAIL, e);
}
}
}
/**
* 设置延时等级(仅可在当前端没有发布音视频流的情况下使用)
* @param level 流的延时等级
* @param fromScene 流所在的房间对象,不传默认为当前房间
*/
/** @en
* Sets the delay level (only available if the current user has no audio and video streams published)
* @param level Level of streaming delay
* @param fromScene The room object in which the stream resides, if not passed, defaults to the current room
*/
async setLatencyLevel(level, fromScene) {
var _this$classroomStore$;
const cameraStream = this.streamByStreamUuid.get(this.localCameraStreamUuid);
const micStream = this.streamByStreamUuid.get(this.localMicStreamUuid);
const screenStream = this.streamByStreamUuid.get(this.localShareStreamUuid);
const anyStreamPublished = (cameraStream === null || cameraStream === void 0 ? void 0 : cameraStream.videoState) === _agoraRteSdk.AgoraRteMediaPublishState.Published || (micStream === null || micStream === void 0 ? void 0 : micStream.audioState) === _agoraRteSdk.AgoraRteMediaPublishState.Published || (screenStream === null || screenStream === void 0 ? void 0 : screenStream.videoState) === _agoraRteSdk.AgoraRteMediaPublishState.Published;
if (anyStreamPublished) {
_error.EduErrorCenter.shared.handleThrowableError(_error.AGEduErrorCode.EDU_ERR_SET_LATENCY_LEVEL_FAIL, new Error("failed to set latency level as there're streams published"));
}
const scene = fromScene !== null && fromScene !== void 0 ? fromScene : (_this$classroomStore$ = this.classroomStore.connectionStore.scene) === null || _this$classroomStore$ === void 0 ? void 0 : _this$classroomStore$.rtcChannel.setLatencyLevel(level);
if (scene) {
scene;
}
}
_setEventHandler(scene) {
if (this.classroomStore.connectionStore.mainRoomScene === scene) {
let handler = SceneEventHandler.getEventHandler(scene);
if (!handler) {
handler = SceneEventHandler.createEventHandler(scene, this.classroomStore);
}
this._dataStore = handler.dataStore;
} else {
const handler = SceneEventHandler.createEventHandler(scene, this.classroomStore);
this._dataStore = handler.dataStore;
}
this._attachStreamMessageListener(scene);
}
/**
* @internal
*/
/** @en
* @internal
*/
onInstall() {
this._disposers.push((0, _mobx.computed)(() => this.classroomStore.connectionStore.scene).observe(({
newValue,
oldValue
}) => {
if (newValue) {
this._setEventHandler(newValue);
}
}));
//this reaction is responsible to join/leave rtc when screenshare info is ready
this._disposers.push((0, _mobx.reaction)(() => this._screenShareTokenAccessor, value => {
const {
streamUuid,
shareStreamToken
} = value;
if (streamUuid && shareStreamToken) {
if (this.classroomStore.connectionStore.rtcSubState === _agoraRteSdk.AGRtcState.Idle) {
this.classroomStore.connectionStore.joinRTC({
connectionType: _agoraRteSdk.AGRtcConnectionType.sub,
streamUuid,
token: shareStreamToken
});
}
} else {
// leave rtc if share StreamUuid is no longer in the room
if (this.classroomStore.connectionStore.rtcSubState !== _agoraRteSdk.AGRtcState.Idle) {
this.classroomStore.connectionStore.leaveRTC(_agoraRteSdk.AGRtcConnectionType.sub);
}
}
}));
}
/**
* @internal
*/
/** @en
* @internal
*/
onDestroy() {
SceneEventHandler.cleanup();
this._detachStreamMessageListener();
this._disposers.forEach(d => d());
this._disposers = [];
}
addStreamMessageListener(listener) {
this._streamMessageListeners.add(listener);
return () => this.removeStreamMessageListener(listener);
}
removeStreamMessageListener(listener) {
this._streamMessageListeners.delete(listener);
}
_attachStreamMessageListener(scene) {
if (!scene || this._streamMessageScene === scene) {
return;
}
this._detachStreamMessageListener();
this._streamMessageScene = scene;
scene.on(_agoraRteSdk.AgoraRteEventType.StreamMessage, this._handleSceneStreamMessage);
}
_detachStreamMessageListener() {
if (this._streamMessageScene) {
this._streamMessageScene.off(_agoraRteSdk.AgoraRteEventType.StreamMessage, this._handleSceneStreamMessage);
this._streamMessageScene = undefined;
}
}
}, _descriptor = _applyDecoratedDescriptor(_class.prototype, "_dataStore", [_mobx.observable], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return {
streamByStreamUuid: new Map(),
streamByUserUuid: new Map(),
streamVolumes: new Map(),
shareStreamTokens: new Map()
};
}
}), _applyDecoratedDescriptor(_class.prototype, "mainRoomDataStore", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "mainRoomDataStore"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "subRoomDataStore", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "subRoomDataStore"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_screenShareTokenAccessor", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "_screenShareTokenAccessor"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "streamByStreamUuid", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "streamByStreamUuid"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "streamByUserUuid", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "streamByUserUuid"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "streamVolumes", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "streamVolumes"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "shareStreamTokens", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "shareStreamTokens"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "shareStreamToken", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "shareStreamToken"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "localCameraStreamUuid", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "localCameraStreamUuid"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "localMicStreamUuid", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "localMicStreamUuid"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "localShareStreamUuid", [_mobx.computed], Object.getOwnPropertyDescriptor(_class.prototype, "localShareStreamUuid"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "initializeScreenShareStream", [_mobx.action], Object.getOwnPropertyDescriptor(_class.prototype, "initializeScreenShareStream"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "destroyScreenShareStream", [_mobx.action], Object.getOwnPropertyDescriptor(_class.prototype, "destroyScreenShareStream"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "setRemoteVideoStreamType", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "setRemoteVideoStreamType"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "setupRemoteVideo", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "setupRemoteVideo"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "muteRemoteVideoStream", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "muteRemoteVideoStream"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "muteRemoteAudioStream", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "muteRemoteAudioStream"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "muteRemoteVideoStreamMass", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "muteRemoteVideoStreamMass"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateLocalPublishState", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "updateLocalPublishState"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateRemotePublishState", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "updateRemotePublishState"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateRemotePublishStateBatch", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "updateRemotePublishStateBatch"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "publishStreamToCdn", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "publishStreamToCdn"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateExpandedScopeAndStreams", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "updateExpandedScopeAndStreams"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "publishScreenShare", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "publishScreenShare"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "unpublishScreenShare", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "unpublishScreenShare"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "publishScreenShareStateless", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "publishScreenShareStateless"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "unpublishScreenShareStateless", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "unpublishScreenShareStateless"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "setLatencyLevel", [_agoraRteSdk.bound], Object.getOwnPropertyDescriptor(_class.prototype, "setLatencyLevel"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_setEventHandler", [_mobx.action], Object.getOwnPropertyDescriptor(_class.prototype, "_setEventHandler"), _class.prototype), _class);
let SceneEventHandler = (_dec = _mobx.action.bound, _dec2 = _mobx.action.bound, _dec3 = _mobx.action.bound, _dec4 = _mobx.action.bound, _dec5 = _mobx.action.bound, _dec6 = _mobx.action.bound, _dec7 = _mobx.action.bound, _class2 = (_SceneEventHandler = class SceneEventHandler {
static createEventHandler(scene, classroomStore) {
if (SceneEventHandler._handlers[scene.sceneId]) {
SceneEventHandler._handlers[scene.sceneId].removeEventHandlers();
}
const handler = new SceneEventHandler(scene, classroomStore);
handler.addEventHandlers();
handler._checkLocalScreenShareState();
SceneEventHandler._handlers[scene.sceneId] = handler;
return SceneEventHandler._handlers[scene.sceneId];
}
static getEventHandler(scene) {
return SceneEventHandler._handlers[scene.sceneId];
}
static cleanup() {
Object.keys(SceneEventHandler._handlers).forEach(k => {
SceneEventHandler._handlers[k].removeEventHandlers();
});
SceneEventHandler._handlers = {};
}
constructor(_scene, _classroomStore) {
this._scene = _scene;
this._classroomStore = _classroomStore;
_initializerDefineProperty(this, "dataStore", _descriptor2, this);
}
addEventHandlers() {
this._scene.on(_agoraRteSdk.AgoraRteEventType.AudioVolumes, this._updateStreamVolumes);
this._scene.on(_agoraRteSdk.AgoraRteEventType.LocalStreamAdded, this._addLocalStream);
this._scene.on(_agoraRteSdk.AgoraRteEventType.LocalStreamRemove, this._removeLocalStream);
this._scene.on(_agoraRteSdk.AgoraRteEventType.LocalStreamUpdate, this._updateLocalStream);
this._scene.on(_agoraRteSdk.AgoraRteEventType.RemoteStreamAdded, this._addRemoteStream);
this._scene.on(_agoraRteSdk.AgoraRteEventType.RemoteStreamRemove, this._removeRemoteStream);
this._scene.on(_agoraRteSdk.AgoraRteEventType.RemoteStreamUpdate, this._updateRemoteStream);
}
removeEventHandlers() {
this._scene.off(_agoraRteSdk.AgoraRteEventType.AudioVolumes, this._updateStreamVolumes);
this._scene.off(_agoraRteSdk.AgoraRteEventType.LocalStreamAdded, this._addLocalStream);
this._scene.off(_agoraRteSdk.AgoraRteEventType.LocalStreamRemove, this._removeLocalStream);
this._scene.off(_agoraRteSdk.AgoraRteEventType.LocalStreamUpdate, this._updateLocalStream);
this._scene.off(_agoraRteSdk.AgoraRteEventType.RemoteStreamAdded, this._addRemoteStream);
this._scene.off(_agoraRteSdk.AgoraRteEventType.RemoteStreamRemove, this._removeRemoteStream);
this._scene.off(_agoraRteSdk.AgoraRteEventType.RemoteStreamUpdate, this._updateRemoteStream);
}
async _checkLocalScreenShareState() {
if (this._classroomStore.connectionStore._subRoomScene) {
await (0, _mobx.when)(() => this._classroomStore.connectionStore.subRoomState === _type.ClassroomState.Connected);
} else {
await (0, _mobx.when)(() => this._classroomStore.connectionStore.classroomState === _type.ClassroomState.Connected);
}
//当初始化时有自己的屏幕共享流,取消发布屏幕共享流
const userUuid = _configs.EduClassroomConfig.shared.sessionInfo.userUuid;
if (this._classroomStore.roomStore.screenShareStreamUuid && this._classroomStore.roomStore.screenShareUserUuid === userUuid) {
await this._classroomStore.streamStore.unpublishScreenShare(this._scene);
}
}
_addStream2UserSet(stream, userUuid) {
let streamUuidSet = this.dataStore.streamByUserUuid.get(userUuid);
if (!streamUuidSet) {
streamUuidSet = new Set();
}
streamUuidSet.add(stream.streamUuid);
this.dataStore.streamByUserUuid.set(userUuid, streamUuidSet);
}
_removeStreamFromUserSet(streamUuid, userUuid) {
const streamUuidSet = this.dataStore.streamByUserUuid.get(userUuid);
if (!streamUuidSet) {
return;
}
streamUuidSet.delete(streamUuid);
if (streamUuidSet.size === 0) {
// delete entry if no more stream
this.dataStore.streamByUserUuid.delete(userUuid);
}
}
_updateStreamVolumes(volumes) {
this.dataStore.streamVolumes = volumes;
}
_addLocalStream(streams) {
_agoraRteSdk.Logger.info('Scene Id:', this._scene.sceneId, 'Add localStreams', streams);
streams.forEach(stream => {
const eduStream = new _struct.EduStream(stream);
this.dataStore.streamByStreamUuid.set(stream.streamUuid, eduStream);
this._addStream2UserSet(eduStream, stream.fromUser.userUuid);
});
}
_removeLocalStream(streams) {
streams.forEach(stream => {
this.dataStore.streamByStreamUuid.delete(stream.streamUuid);
this._removeStreamFromUserSet(stream.streamUuid, stream.fromUser.userUuid);
});
}
_updateLocalStream(streams, operator) {
_agoraRteSdk.Logger.info('Scene Id:', this._scene.sceneId, 'Update localStreams', streams);
streams.forEach(stream => {
if (operator) {
const {
sessionInfo
} = _configs.EduClassroomConfig.shared;
const {
role,
userUuid
} = operator;
const eduRole = (0, _utils.RteRole2EduRole)(sessionInfo.roomType, role);
// do not process if it's myself
if (userUuid !== sessionInfo.userUuid && eduRole === _type.EduRoleTypeEnum.teacher) {
const oldStream = this.dataStore.streamByStreamUuid.get(stream.streamUuid);
if (!oldStream) {
_agoraRteSdk.Logger.warn(`stream ${stream.streamUuid} not found when updating local stream`);
} else {
if (oldStream.audioState !== stream.audioState) {
_eventCenter.EduEventCenter.shared.emitClasroomEvents(stream.audioState === _agoraRteSdk.AgoraRteMediaPublishState.Published ? _type.AgoraEduClassroomEvent.TeacherTurnOnMyMic : _type.AgoraEduClassroomEvent.TeacherTurnOffMyMic, this._scene.sceneId);
}
if (oldStream.videoState !== stream.videoState) {
_eventCenter.EduEventCenter.shared.emitClasroomEvents(stream.videoState === _agoraRteSdk.AgoraRteMediaPublishState.Published ? _type.AgoraEduClassroomEvent.TeacherTurnOnMyCam : _type.AgoraEduClassroomEvent.TeacherTurnOffMyCam, this._scene.sceneId);
}
}
}
}
const eduStream = new _struct.EduStream(stream);
this.dataStore.streamByStreamUuid.set(stream.streamUuid, eduStream);
this._addStream2UserSet(eduStream, stream.fromUser.userUuid);
});
}
_addRemoteStream(streams) {
streams.forEach(stream => {
const eduStream = new _struct.EduStream(stream);
this.dataStore.streamByStreamUuid.set(stream.streamUuid, eduStream);
this._addStream2UserSet(eduStream, stream.fromUser.userUuid);
});
}
_removeRemoteStream(streams) {
streams.forEach(stream => {
this.dataStore.streamByStreamUuid.delete(stream.streamUuid);
this._removeStreamFromUserSet(stream.streamUuid, stream.fromUser.userUuid);
});
}
_updateRemoteStream(streams) {
streams.forEach(stream => {
const eduStream = new _struct.EduStream(stream);
this.dataStore.streamByStreamUuid.set(stream.streamUuid, eduStream);
this._addStream2UserSet(eduStream, stream.fromUser.userUuid);
});
}
}, _SceneEventHandler._handlers = {}, _SceneEventHandler), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, "dataStore", [_mobx.observable], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return {
streamByStreamUuid: new Map(),
streamByUserUuid: new Map(),
streamVolumes: new Map(),
shareStreamTokens: new Map()
};
}
}), _applyDecoratedDescriptor(_class2.prototype, "_updateStreamVolumes", [_dec], Object.getOwnPropertyDescriptor(_class2.prototype, "_updateStreamVolumes"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "_addLocalStream", [_dec2], Object.getOwnPropertyDescriptor(_class2.prototype, "_addLocalStream"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "_removeLocalStream", [_dec3], Object.getOwnPropertyDescriptor(_class2.prototype, "_removeLocalStream"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "_updateLocalStream", [_dec4], Object.getOwnPropertyDescriptor(_class2.prototype, "_updateLocalStream"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "_addRemoteStream", [_dec5], Object.getOwnPropertyDescriptor(_class2.prototype, "_addRemoteStream"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "_removeRemoteStream", [_dec6], Object.getOwnPropertyDescriptor(_class2.prototype, "_removeRemoteStream"), _class2.prototype), _applyDecoratedDescriptor(_class2.prototype, "_updateRemoteStream", [_dec7], Object.getOwnPropertyDescriptor(_class2.prototype, "_updateRemoteStream"), _class2.prototype), _class2);