@webex/plugin-meetings 2.37.0 → 2.37.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/UPGRADING.md +9 -9
- package/browsers.js +19 -24
- package/dist/common/browser-detection.js +1 -20
- package/dist/common/browser-detection.js.map +1 -1
- package/dist/common/collection.js +5 -20
- package/dist/common/collection.js.map +1 -1
- package/dist/common/config.js +0 -7
- package/dist/common/config.js.map +1 -1
- package/dist/common/errors/captcha-error.js +5 -26
- package/dist/common/errors/captcha-error.js.map +1 -1
- package/dist/common/errors/intent-to-join.js +5 -26
- package/dist/common/errors/intent-to-join.js.map +1 -1
- package/dist/common/errors/join-meeting.js +6 -27
- package/dist/common/errors/join-meeting.js.map +1 -1
- package/dist/common/errors/media.js +5 -26
- package/dist/common/errors/media.js.map +1 -1
- package/dist/common/errors/parameter.js +5 -33
- package/dist/common/errors/parameter.js.map +1 -1
- package/dist/common/errors/password-error.js +5 -26
- package/dist/common/errors/password-error.js.map +1 -1
- package/dist/common/errors/permission.js +4 -25
- package/dist/common/errors/permission.js.map +1 -1
- package/dist/common/errors/reconnection-in-progress.js +0 -17
- package/dist/common/errors/reconnection-in-progress.js.map +1 -1
- package/dist/common/errors/reconnection.js +5 -26
- package/dist/common/errors/reconnection.js.map +1 -1
- package/dist/common/errors/stats.js +5 -26
- package/dist/common/errors/stats.js.map +1 -1
- package/dist/common/errors/webex-errors.js +7 -46
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/errors/webex-meetings-error.js +1 -24
- package/dist/common/errors/webex-meetings-error.js.map +1 -1
- package/dist/common/events/events-scope.js +0 -22
- package/dist/common/events/events-scope.js.map +1 -1
- package/dist/common/events/events.js +0 -23
- package/dist/common/events/events.js.map +1 -1
- package/dist/common/events/trigger-proxy.js +0 -12
- package/dist/common/events/trigger-proxy.js.map +1 -1
- package/dist/common/events/util.js +0 -15
- package/dist/common/events/util.js.map +1 -1
- package/dist/common/logs/logger-config.js +0 -4
- package/dist/common/logs/logger-config.js.map +1 -1
- package/dist/common/logs/logger-proxy.js +1 -8
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.js +35 -61
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +4 -14
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +1 -5
- package/dist/config.js.map +1 -1
- package/dist/constants.js +46 -42
- package/dist/constants.js.map +1 -1
- package/dist/index.js +1 -17
- package/dist/index.js.map +1 -1
- package/dist/locus-info/controlsUtils.js +10 -28
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/embeddedAppsUtils.js +3 -26
- package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
- package/dist/locus-info/fullState.js +0 -15
- package/dist/locus-info/fullState.js.map +1 -1
- package/dist/locus-info/hostUtils.js +4 -12
- package/dist/locus-info/hostUtils.js.map +1 -1
- package/dist/locus-info/index.js +101 -193
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +0 -37
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +12 -38
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +87 -123
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +16 -81
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +74 -137
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +64 -110
- package/dist/media/properties.js.map +1 -1
- package/dist/media/util.js +3 -17
- package/dist/media/util.js.map +1 -1
- package/dist/mediaQualityMetrics/config.js +10 -12
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/effectsState.js +120 -192
- package/dist/meeting/effectsState.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +0 -13
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +812 -1487
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +31 -78
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +157 -227
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/state.js +21 -31
- package/dist/meeting/state.js.map +1 -1
- package/dist/meeting/util.js +25 -169
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/collection.js +3 -25
- package/dist/meeting-info/collection.js.map +1 -1
- package/dist/meeting-info/index.js +10 -33
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +179 -268
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/request.js +1 -16
- package/dist/meeting-info/request.js.map +1 -1
- package/dist/meeting-info/util.js +98 -183
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +137 -228
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +3 -21
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +451 -570
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/request.js +7 -30
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +94 -148
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +49 -89
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +17 -68
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +2 -12
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +68 -184
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +21 -56
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +9 -38
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/config.js +0 -2
- package/dist/metrics/config.js.map +1 -1
- package/dist/metrics/constants.js +1 -2
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +48 -136
- package/dist/metrics/index.js.map +1 -1
- package/dist/networkQualityMonitor/index.js +28 -57
- package/dist/networkQualityMonitor/index.js.map +1 -1
- package/dist/peer-connection-manager/index.js +60 -190
- package/dist/peer-connection-manager/index.js.map +1 -1
- package/dist/peer-connection-manager/util.js +10 -24
- package/dist/peer-connection-manager/util.js.map +1 -1
- package/dist/personal-meeting-room/index.js +10 -45
- package/dist/personal-meeting-room/index.js.map +1 -1
- package/dist/personal-meeting-room/request.js +2 -33
- package/dist/personal-meeting-room/request.js.map +1 -1
- package/dist/personal-meeting-room/util.js +0 -13
- package/dist/personal-meeting-room/util.js.map +1 -1
- package/dist/reachability/index.js +100 -166
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +2 -18
- package/dist/reachability/request.js.map +1 -1
- package/dist/reactions/reactions.js +0 -2
- package/dist/reactions/reactions.js.map +1 -1
- package/dist/reactions/reactions.type.js +0 -5
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +294 -468
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/collection.js +1 -12
- package/dist/roap/collection.js.map +1 -1
- package/dist/roap/handler.js +15 -85
- package/dist/roap/handler.js.map +1 -1
- package/dist/roap/index.js +42 -94
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +81 -148
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/state.js +2 -39
- package/dist/roap/state.js.map +1 -1
- package/dist/roap/turnDiscovery.js +8 -52
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/util.js +0 -26
- package/dist/roap/util.js.map +1 -1
- package/dist/statsAnalyzer/global.js +0 -2
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/statsAnalyzer/index.js +68 -168
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +54 -53
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/transcription/index.js +13 -45
- package/dist/transcription/index.js.map +1 -1
- package/internal-README.md +7 -6
- package/package.json +17 -17
- package/src/common/browser-detection.ts +9 -6
- package/src/common/collection.ts +3 -1
- package/src/common/errors/captcha-error.ts +6 -6
- package/src/common/errors/intent-to-join.ts +6 -6
- package/src/common/errors/join-meeting.ts +12 -8
- package/src/common/errors/media.ts +6 -6
- package/src/common/errors/parameter.ts +9 -6
- package/src/common/errors/password-error.ts +6 -6
- package/src/common/errors/permission.ts +5 -5
- package/src/common/errors/reconnection.ts +6 -6
- package/src/common/errors/stats.ts +6 -6
- package/src/common/errors/webex-errors.ts +7 -5
- package/src/common/errors/webex-meetings-error.ts +1 -1
- package/src/common/events/events-scope.ts +5 -1
- package/src/common/events/events.ts +5 -1
- package/src/common/events/trigger-proxy.ts +8 -3
- package/src/common/events/util.ts +1 -2
- package/src/common/logs/logger-proxy.ts +21 -10
- package/src/common/logs/request.ts +11 -8
- package/src/config.ts +11 -11
- package/src/constants.ts +138 -119
- package/src/index.js +1 -1
- package/src/locus-info/controlsUtils.ts +34 -24
- package/src/locus-info/fullState.ts +15 -11
- package/src/locus-info/hostUtils.ts +4 -3
- package/src/locus-info/index.ts +25 -34
- package/src/locus-info/infoUtils.ts +12 -4
- package/src/locus-info/mediaSharesUtils.ts +4 -4
- package/src/locus-info/parser.ts +45 -68
- package/src/locus-info/selfUtils.ts +106 -57
- package/src/media/index.ts +118 -109
- package/src/media/properties.ts +26 -20
- package/src/media/util.ts +2 -2
- package/src/mediaQualityMetrics/config.ts +46 -46
- package/src/meeting/effectsState.ts +35 -35
- package/src/meeting/in-meeting-actions.ts +7 -3
- package/src/meeting/index.ts +1435 -1210
- package/src/meeting/muteState.ts +62 -31
- package/src/meeting/request.ts +160 -113
- package/src/meeting/state.ts +45 -30
- package/src/meeting/util.ts +131 -90
- package/src/meeting-info/collection.ts +2 -1
- package/src/meeting-info/index.ts +32 -30
- package/src/meeting-info/meeting-info-v2.ts +106 -108
- package/src/meeting-info/request.ts +9 -3
- package/src/meeting-info/util.ts +54 -46
- package/src/meeting-info/utilv2.ts +59 -53
- package/src/meetings/collection.ts +1 -1
- package/src/meetings/index.ts +513 -441
- package/src/meetings/request.ts +26 -24
- package/src/meetings/util.ts +26 -23
- package/src/member/index.ts +55 -49
- package/src/member/util.ts +26 -13
- package/src/members/collection.ts +0 -1
- package/src/members/index.ts +172 -121
- package/src/members/request.ts +46 -14
- package/src/members/util.ts +44 -42
- package/src/metrics/config.ts +254 -81
- package/src/metrics/constants.ts +0 -2
- package/src/metrics/index.ts +84 -71
- package/src/networkQualityMonitor/index.ts +20 -23
- package/src/peer-connection-manager/index.ts +321 -241
- package/src/peer-connection-manager/util.ts +4 -2
- package/src/personal-meeting-room/index.ts +12 -16
- package/src/personal-meeting-room/request.ts +10 -3
- package/src/personal-meeting-room/util.ts +3 -3
- package/src/reachability/index.ts +61 -59
- package/src/reachability/request.ts +36 -32
- package/src/reactions/reactions.ts +4 -4
- package/src/reactions/reactions.type.ts +2 -3
- package/src/reconnection-manager/index.ts +159 -98
- package/src/roap/collection.ts +2 -4
- package/src/roap/handler.ts +63 -32
- package/src/roap/index.ts +78 -58
- package/src/roap/request.ts +69 -54
- package/src/roap/state.ts +17 -11
- package/src/roap/turnDiscovery.ts +60 -31
- package/src/roap/util.ts +39 -31
- package/src/statsAnalyzer/global.ts +30 -33
- package/src/statsAnalyzer/index.ts +397 -169
- package/src/statsAnalyzer/mqaUtil.ts +178 -72
- package/src/transcription/index.ts +34 -32
- package/test/integration/spec/journey.js +666 -462
- package/test/integration/spec/space-meeting.js +318 -203
- package/test/integration/spec/transcription.js +6 -7
- package/test/unit/spec/common/browser-detection.js +9 -28
- package/test/unit/spec/fixture/locus.js +92 -90
- package/test/unit/spec/locus-info/controlsUtils.js +5 -5
- package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
- package/test/unit/spec/locus-info/index.js +1 -2
- package/test/unit/spec/locus-info/infoUtils.js +24 -31
- package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
- package/test/unit/spec/locus-info/lib/SeqCmp.json +513 -685
- package/test/unit/spec/locus-info/parser.js +3 -9
- package/test/unit/spec/locus-info/selfConstant.js +72 -103
- package/test/unit/spec/locus-info/selfUtils.js +21 -12
- package/test/unit/spec/meeting/effectsState.js +33 -45
- package/test/unit/spec/meeting/in-meeting-actions.ts +2 -3
- package/test/unit/spec/meeting/index.js +1141 -649
- package/test/unit/spec/meeting/muteState.js +42 -33
- package/test/unit/spec/meeting/request.js +56 -45
- package/test/unit/spec/meeting/utils.js +66 -49
- package/test/unit/spec/meeting-info/meetinginfov2.js +100 -73
- package/test/unit/spec/meeting-info/request.js +7 -9
- package/test/unit/spec/meeting-info/util.js +11 -12
- package/test/unit/spec/meeting-info/utilv2.js +110 -74
- package/test/unit/spec/meetings/collection.js +1 -1
- package/test/unit/spec/meetings/index.js +438 -257
- package/test/unit/spec/meetings/utils.js +14 -12
- package/test/unit/spec/member/index.js +0 -1
- package/test/unit/spec/member/util.js +5 -6
- package/test/unit/spec/members/index.js +84 -35
- package/test/unit/spec/members/request.js +29 -20
- package/test/unit/spec/members/utils.js +8 -5
- package/test/unit/spec/metrics/index.js +16 -21
- package/test/unit/spec/networkQualityMonitor/index.js +21 -15
- package/test/unit/spec/peerconnection-manager/index.js +88 -58
- package/test/unit/spec/peerconnection-manager/utils.js +5 -4
- package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +7 -8
- package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
- package/test/unit/spec/reachability/index.ts +9 -11
- package/test/unit/spec/reconnection-manager/index.js +14 -17
- package/test/unit/spec/roap/index.ts +18 -8
- package/test/unit/spec/roap/turnDiscovery.ts +22 -19
- package/test/unit/spec/roap/util.js +3 -3
- package/test/unit/spec/stats-analyzer/index.js +29 -24
- package/test/utils/cmr.js +44 -42
- package/test/utils/testUtils.js +83 -74
- package/test/utils/webex-config.js +18 -18
- package/test/utils/webex-test-users.js +53 -50
package/src/meeting/index.ts
CHANGED
|
@@ -5,8 +5,12 @@ import {StatelessWebexPlugin} from '@webex/webex-core';
|
|
|
5
5
|
import {Media as WebRTCMedia} from '@webex/internal-media-core';
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
MeetingNotActiveError,
|
|
9
|
-
|
|
8
|
+
MeetingNotActiveError,
|
|
9
|
+
createMeetingsError,
|
|
10
|
+
UserInLobbyError,
|
|
11
|
+
NoMediaEstablishedYetError,
|
|
12
|
+
UserNotJoinedError,
|
|
13
|
+
InvalidSdpError,
|
|
10
14
|
} from '../common/errors/webex-errors';
|
|
11
15
|
import {StatsAnalyzer, EVENTS as StatsAnalyzerEvents} from '../statsAnalyzer';
|
|
12
16
|
import NetworkQualityMonitor from '../networkQualityMonitor';
|
|
@@ -15,17 +19,17 @@ import Trigger from '../common/events/trigger-proxy';
|
|
|
15
19
|
import Roap from '../roap/index';
|
|
16
20
|
import Media from '../media';
|
|
17
21
|
import MediaProperties from '../media/properties';
|
|
18
|
-
import MeetingStateMachine from '
|
|
19
|
-
import createMuteState from '
|
|
20
|
-
import createEffectsState from '
|
|
22
|
+
import MeetingStateMachine from './state';
|
|
23
|
+
import createMuteState from './muteState';
|
|
24
|
+
import createEffectsState from './effectsState';
|
|
21
25
|
import LocusInfo from '../locus-info';
|
|
22
26
|
import PeerConnectionManager from '../peer-connection-manager';
|
|
23
27
|
import Metrics from '../metrics';
|
|
24
28
|
import {trigger, mediaType, eventType} from '../metrics/config';
|
|
25
29
|
import ReconnectionManager from '../reconnection-manager';
|
|
26
|
-
import MeetingRequest from '
|
|
30
|
+
import MeetingRequest from './request';
|
|
27
31
|
import Members from '../members/index';
|
|
28
|
-
import MeetingUtil from '
|
|
32
|
+
import MeetingUtil from './util';
|
|
29
33
|
import MediaUtil from '../media/util';
|
|
30
34
|
import Transcription from '../transcription';
|
|
31
35
|
import PasswordError from '../common/errors/password-error';
|
|
@@ -69,12 +73,15 @@ import {
|
|
|
69
73
|
VIDEO_RESOLUTIONS,
|
|
70
74
|
VIDEO,
|
|
71
75
|
BNR_STATUS,
|
|
72
|
-
HTTP_VERBS
|
|
76
|
+
HTTP_VERBS,
|
|
73
77
|
} from '../constants';
|
|
74
78
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
75
79
|
import ParameterError from '../common/errors/parameter';
|
|
76
80
|
import MediaError from '../common/errors/media';
|
|
77
|
-
import {
|
|
81
|
+
import {
|
|
82
|
+
MeetingInfoV2PasswordError,
|
|
83
|
+
MeetingInfoV2CaptchaError,
|
|
84
|
+
} from '../meeting-info/meeting-info-v2';
|
|
78
85
|
import BrowserDetection from '../common/browser-detection';
|
|
79
86
|
import RoapCollection from '../roap/collection';
|
|
80
87
|
import {SkinTones, Reactions} from '../reactions/reactions';
|
|
@@ -82,10 +89,9 @@ import {Reaction, ReactionType, SkinToneType} from '../reactions/reactions.type'
|
|
|
82
89
|
|
|
83
90
|
import InMeetingActions from './in-meeting-actions';
|
|
84
91
|
|
|
85
|
-
|
|
86
92
|
const {isBrowser} = BrowserDetection();
|
|
87
93
|
|
|
88
|
-
const logRequest = (request: any, {
|
|
94
|
+
const logRequest = (request: any, {header = '', success = '', failure = ''}) => {
|
|
89
95
|
LoggerProxy.logger.info(header);
|
|
90
96
|
|
|
91
97
|
return request
|
|
@@ -104,7 +110,7 @@ export const MEDIA_UPDATE_TYPE = {
|
|
|
104
110
|
ALL: 'ALL',
|
|
105
111
|
AUDIO: 'AUDIO',
|
|
106
112
|
VIDEO: 'VIDEO',
|
|
107
|
-
SHARE: 'SHARE'
|
|
113
|
+
SHARE: 'SHARE',
|
|
108
114
|
};
|
|
109
115
|
|
|
110
116
|
/**
|
|
@@ -120,21 +126,21 @@ export const MEDIA_UPDATE_TYPE = {
|
|
|
120
126
|
*/
|
|
121
127
|
|
|
122
128
|
/**
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
* AudioVideo
|
|
130
|
+
* @typedef {Object} AudioVideo
|
|
131
|
+
* @property {Object} audio
|
|
132
|
+
* @property {String} audio.deviceId
|
|
133
|
+
* @property {Object} video
|
|
134
|
+
* @property {String} video.deviceId
|
|
135
|
+
* @property {String} video.localVideoQuality // [240p, 360p, 480p, 720p, 1080p]
|
|
136
|
+
*/
|
|
131
137
|
|
|
132
138
|
/**
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
* SharePreferences
|
|
140
|
+
* @typedef {Object} SharePreferences
|
|
141
|
+
* @property {Object} [shareConstraints]
|
|
142
|
+
* @property {Boolean} [highFrameRate]
|
|
143
|
+
*/
|
|
138
144
|
|
|
139
145
|
/**
|
|
140
146
|
* JoinOptions
|
|
@@ -164,36 +170,36 @@ export const MEDIA_UPDATE_TYPE = {
|
|
|
164
170
|
*/
|
|
165
171
|
|
|
166
172
|
/**
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
* Meeting State Change Event
|
|
174
|
+
* Emitted when ever there is a meeting state change
|
|
175
|
+
* @event meeting:stateChange
|
|
176
|
+
* @instance
|
|
177
|
+
* @type {Object}
|
|
178
|
+
* @property {String} currentState current state of the meeting
|
|
179
|
+
* @property {String} previousState previous state of the meeting
|
|
180
|
+
* @memberof Meeting
|
|
181
|
+
*/
|
|
176
182
|
|
|
177
183
|
/**
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
* Media Ready Event
|
|
185
|
+
* Emitted when a stream is ready to be rendered
|
|
186
|
+
* @event media:ready
|
|
187
|
+
* @instance
|
|
188
|
+
* @type {Object}
|
|
189
|
+
* @property {MediaStream} stream the media stream
|
|
190
|
+
* @property {String} type what type of stream, remote, local
|
|
191
|
+
* @memberof Meeting
|
|
192
|
+
*/
|
|
187
193
|
|
|
188
194
|
/**
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
* Media Stopped Event
|
|
196
|
+
* Emitted when a stream has stopped sending
|
|
197
|
+
* @event media:stopped
|
|
198
|
+
* @instance
|
|
199
|
+
* @type {Object}
|
|
200
|
+
* @property {String} type what type of stream, remote, local
|
|
201
|
+
* @memberof Meeting
|
|
202
|
+
*/
|
|
197
203
|
|
|
198
204
|
/**
|
|
199
205
|
* Meeting Ringing Event
|
|
@@ -320,7 +326,6 @@ export const MEDIA_UPDATE_TYPE = {
|
|
|
320
326
|
* @memberof Meeting
|
|
321
327
|
*/
|
|
322
328
|
|
|
323
|
-
|
|
324
329
|
/**
|
|
325
330
|
* Meeting Self Guest Admitted Event
|
|
326
331
|
* Emitted when a joined user get admitted to the meeting by another member or host
|
|
@@ -352,42 +357,42 @@ export const MEDIA_UPDATE_TYPE = {
|
|
|
352
357
|
*/
|
|
353
358
|
|
|
354
359
|
/**
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
360
|
+
* Reconnection Starting Event
|
|
361
|
+
* Emitted when reconnection of media to the active meeting was successful
|
|
362
|
+
* @event meeting:reconnectionStarting
|
|
363
|
+
* @instance
|
|
364
|
+
* @memberof Meeting
|
|
365
|
+
*/
|
|
361
366
|
|
|
362
367
|
/**
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
368
|
+
* Reconnection Success Event
|
|
369
|
+
* Emitted when reconnection of media to the active meeting was successful
|
|
370
|
+
* @event meeting:reconnectionSuccess
|
|
371
|
+
* @instance
|
|
372
|
+
* @type {Object}
|
|
373
|
+
* @property {Object} reconnect
|
|
374
|
+
* @memberof Meeting
|
|
375
|
+
*/
|
|
371
376
|
|
|
372
377
|
/**
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
378
|
+
* Reconnection Failure Event
|
|
379
|
+
* Emitted when reconnection of media to the active meeting was successful
|
|
380
|
+
* @event meeting:reconnectionFailure
|
|
381
|
+
* @instance
|
|
382
|
+
* @type {Object}
|
|
383
|
+
* @property {Error} error
|
|
384
|
+
* @memberof Meeting
|
|
385
|
+
*/
|
|
381
386
|
|
|
382
387
|
/**
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
388
|
+
* Meeting network quality event
|
|
389
|
+
* Emitted on each interval of retrieving stats Analyzer data
|
|
390
|
+
* @event network:quality
|
|
391
|
+
* @type {Object}
|
|
392
|
+
* @property {string} mediaType {video|audio}
|
|
393
|
+
* @property {number} networkQualityScore - {1|0} 1 indicates acceptable uplink 0 indicates unacceptable uplink based on threshold
|
|
394
|
+
* @memberof Meeting
|
|
395
|
+
*/
|
|
391
396
|
|
|
392
397
|
/**
|
|
393
398
|
* @description Meeting is the crux of the plugin
|
|
@@ -470,6 +475,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
470
475
|
resourceUrl: string;
|
|
471
476
|
selfId: string;
|
|
472
477
|
state: any;
|
|
478
|
+
|
|
473
479
|
namespace = MEETINGS;
|
|
474
480
|
|
|
475
481
|
/**
|
|
@@ -477,7 +483,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
477
483
|
* @param {Object} options
|
|
478
484
|
* @constructor
|
|
479
485
|
* @memberof Meeting
|
|
480
|
-
|
|
486
|
+
*/
|
|
481
487
|
constructor(attrs: any, options: object) {
|
|
482
488
|
super({}, options);
|
|
483
489
|
/**
|
|
@@ -755,7 +761,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
755
761
|
* @type {InMeetingActions}
|
|
756
762
|
* @public
|
|
757
763
|
* @memberof Meeting
|
|
758
|
-
|
|
764
|
+
*/
|
|
759
765
|
this.inMeetingActions = new InMeetingActions();
|
|
760
766
|
/**
|
|
761
767
|
* This is deprecated, please use shareStatus instead.
|
|
@@ -796,7 +802,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
796
802
|
|
|
797
803
|
return false;
|
|
798
804
|
},
|
|
799
|
-
configurable: true
|
|
805
|
+
configurable: true,
|
|
800
806
|
});
|
|
801
807
|
/**
|
|
802
808
|
* @instance
|
|
@@ -992,32 +998,55 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
992
998
|
* @memberof Meeting
|
|
993
999
|
* @returns {Promise}
|
|
994
1000
|
*/
|
|
995
|
-
public async fetchMeetingInfo({
|
|
1001
|
+
public async fetchMeetingInfo({
|
|
1002
|
+
password = null,
|
|
1003
|
+
captchaCode = null,
|
|
1004
|
+
}: {
|
|
1005
|
+
password?: string;
|
|
1006
|
+
captchaCode?: string;
|
|
1007
|
+
}) {
|
|
996
1008
|
// when fetch meeting info is called directly by the client, we want to clear out the random timer for sdk to do it
|
|
997
1009
|
if (this.fetchMeetingInfoTimeoutId) {
|
|
998
1010
|
clearTimeout(this.fetchMeetingInfoTimeoutId);
|
|
999
1011
|
this.fetchMeetingInfoTimeoutId = undefined;
|
|
1000
1012
|
}
|
|
1001
1013
|
if (captchaCode && !this.requiredCaptcha) {
|
|
1002
|
-
return Promise.reject(
|
|
1014
|
+
return Promise.reject(
|
|
1015
|
+
new Error('fetchMeetingInfo() called with captchaCode when captcha was not required')
|
|
1016
|
+
);
|
|
1003
1017
|
}
|
|
1004
|
-
if (
|
|
1005
|
-
|
|
1018
|
+
if (
|
|
1019
|
+
password &&
|
|
1020
|
+
this.passwordStatus !== PASSWORD_STATUS.REQUIRED &&
|
|
1021
|
+
this.passwordStatus !== PASSWORD_STATUS.UNKNOWN
|
|
1022
|
+
) {
|
|
1023
|
+
return Promise.reject(
|
|
1024
|
+
new Error('fetchMeetingInfo() called with password when password was not required')
|
|
1025
|
+
);
|
|
1006
1026
|
}
|
|
1007
1027
|
|
|
1008
1028
|
try {
|
|
1009
|
-
const captchaInfo = captchaCode
|
|
1010
|
-
|
|
1011
|
-
|
|
1029
|
+
const captchaInfo = captchaCode
|
|
1030
|
+
? {code: captchaCode, id: this.requiredCaptcha.captchaId}
|
|
1031
|
+
: null;
|
|
1032
|
+
|
|
1033
|
+
const info = await this.attrs.meetingInfoProvider.fetchMeetingInfo(
|
|
1034
|
+
this.destination,
|
|
1035
|
+
this.destinationType,
|
|
1036
|
+
password,
|
|
1037
|
+
captchaInfo
|
|
1038
|
+
);
|
|
1012
1039
|
|
|
1013
1040
|
this.parseMeetingInfo(info, this.destination);
|
|
1014
1041
|
this.meetingInfo = info ? info.body : null;
|
|
1015
1042
|
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.NONE;
|
|
1016
1043
|
this.requiredCaptcha = null;
|
|
1017
|
-
if (
|
|
1044
|
+
if (
|
|
1045
|
+
this.passwordStatus === PASSWORD_STATUS.REQUIRED ||
|
|
1046
|
+
this.passwordStatus === PASSWORD_STATUS.VERIFIED
|
|
1047
|
+
) {
|
|
1018
1048
|
this.passwordStatus = PASSWORD_STATUS.VERIFIED;
|
|
1019
|
-
}
|
|
1020
|
-
else {
|
|
1049
|
+
} else {
|
|
1021
1050
|
this.passwordStatus = PASSWORD_STATUS.NOT_REQUIRED;
|
|
1022
1051
|
}
|
|
1023
1052
|
|
|
@@ -1025,17 +1054,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1025
1054
|
this,
|
|
1026
1055
|
{
|
|
1027
1056
|
file: 'meetings',
|
|
1028
|
-
function: 'fetchMeetingInfo'
|
|
1057
|
+
function: 'fetchMeetingInfo',
|
|
1029
1058
|
},
|
|
1030
1059
|
EVENT_TRIGGERS.MEETING_INFO_AVAILABLE
|
|
1031
1060
|
);
|
|
1032
1061
|
|
|
1033
1062
|
return Promise.resolve();
|
|
1034
|
-
}
|
|
1035
|
-
catch (err) {
|
|
1063
|
+
} catch (err) {
|
|
1036
1064
|
if (err instanceof MeetingInfoV2PasswordError) {
|
|
1037
1065
|
// @ts-ignore
|
|
1038
|
-
LoggerProxy.logger.info(
|
|
1066
|
+
LoggerProxy.logger.info(
|
|
1067
|
+
`Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - password required (code=${err?.body?.code}).`
|
|
1068
|
+
);
|
|
1039
1069
|
|
|
1040
1070
|
// when wbxappapi requires password it still populates partial meeting info in the response
|
|
1041
1071
|
if (err.meetingInfo) {
|
|
@@ -1050,26 +1080,26 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1050
1080
|
await this.refreshCaptcha();
|
|
1051
1081
|
}
|
|
1052
1082
|
|
|
1053
|
-
throw
|
|
1054
|
-
}
|
|
1055
|
-
else if (err instanceof MeetingInfoV2CaptchaError) {
|
|
1083
|
+
throw new PasswordError();
|
|
1084
|
+
} else if (err instanceof MeetingInfoV2CaptchaError) {
|
|
1056
1085
|
// @ts-ignore
|
|
1057
|
-
LoggerProxy.logger.info(
|
|
1086
|
+
LoggerProxy.logger.info(
|
|
1087
|
+
`Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - captcha required (code=${err?.body?.code}).`
|
|
1088
|
+
);
|
|
1058
1089
|
|
|
1059
|
-
this.meetingInfoFailureReason =
|
|
1060
|
-
MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA
|
|
1061
|
-
MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD;
|
|
1090
|
+
this.meetingInfoFailureReason = this.requiredCaptcha
|
|
1091
|
+
? MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA
|
|
1092
|
+
: MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD;
|
|
1062
1093
|
|
|
1063
1094
|
if (err.isPasswordRequired) {
|
|
1064
1095
|
this.passwordStatus = PASSWORD_STATUS.REQUIRED;
|
|
1065
1096
|
}
|
|
1066
1097
|
|
|
1067
1098
|
this.requiredCaptcha = err.captchaInfo;
|
|
1068
|
-
throw
|
|
1069
|
-
}
|
|
1070
|
-
else {
|
|
1099
|
+
throw new CaptchaError();
|
|
1100
|
+
} else {
|
|
1071
1101
|
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.OTHER;
|
|
1072
|
-
throw
|
|
1102
|
+
throw err;
|
|
1073
1103
|
}
|
|
1074
1104
|
}
|
|
1075
1105
|
}
|
|
@@ -1085,24 +1115,27 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1085
1115
|
*/
|
|
1086
1116
|
public verifyPassword(password: string, captchaCode: string) {
|
|
1087
1117
|
return this.fetchMeetingInfo({
|
|
1088
|
-
password,
|
|
1118
|
+
password,
|
|
1119
|
+
captchaCode,
|
|
1089
1120
|
})
|
|
1090
1121
|
.then(() => {
|
|
1091
|
-
Metrics.sendBehavioralMetric(
|
|
1092
|
-
BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS
|
|
1093
|
-
);
|
|
1122
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS);
|
|
1094
1123
|
|
|
1095
|
-
return {
|
|
1124
|
+
return {
|
|
1125
|
+
isPasswordValid: true,
|
|
1126
|
+
requiredCaptcha: null,
|
|
1127
|
+
failureReason: MEETING_INFO_FAILURE_REASON.NONE,
|
|
1128
|
+
};
|
|
1096
1129
|
})
|
|
1097
1130
|
.catch((error) => {
|
|
1098
1131
|
if (error instanceof PasswordError || error instanceof CaptchaError) {
|
|
1099
1132
|
return {
|
|
1100
1133
|
isPasswordValid: this.passwordStatus === PASSWORD_STATUS.VERIFIED,
|
|
1101
1134
|
requiredCaptcha: this.requiredCaptcha,
|
|
1102
|
-
failureReason: this.meetingInfoFailureReason
|
|
1135
|
+
failureReason: this.meetingInfoFailureReason,
|
|
1103
1136
|
};
|
|
1104
1137
|
}
|
|
1105
|
-
throw
|
|
1138
|
+
throw error;
|
|
1106
1139
|
});
|
|
1107
1140
|
}
|
|
1108
1141
|
|
|
@@ -1122,18 +1155,21 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1122
1155
|
// we have to pass the wbxappapi hostname as the siteFullName parameter
|
|
1123
1156
|
const {hostname} = new URL(this.requiredCaptcha.refreshURL);
|
|
1124
1157
|
|
|
1125
|
-
return this.meetingRequest
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1158
|
+
return this.meetingRequest
|
|
1159
|
+
.refreshCaptcha({
|
|
1160
|
+
captchaRefreshUrl: `${this.requiredCaptcha.refreshURL}&siteFullName=${hostname}`,
|
|
1161
|
+
captchaId: this.requiredCaptcha.captchaId,
|
|
1162
|
+
})
|
|
1129
1163
|
.then((response) => {
|
|
1130
1164
|
this.requiredCaptcha.captchaId = response.body.captchaID;
|
|
1131
1165
|
this.requiredCaptcha.verificationImageURL = response.body.verificationImageURL;
|
|
1132
1166
|
this.requiredCaptcha.verificationAudioURL = response.body.verificationAudioURL;
|
|
1133
1167
|
})
|
|
1134
1168
|
.catch((error) => {
|
|
1135
|
-
LoggerProxy.logger.error(
|
|
1136
|
-
|
|
1169
|
+
LoggerProxy.logger.error(
|
|
1170
|
+
`Meeting:index#refreshCaptcha --> Error Unable to refresh captcha for ${this.destination} - ${error}`
|
|
1171
|
+
);
|
|
1172
|
+
throw error;
|
|
1137
1173
|
});
|
|
1138
1174
|
}
|
|
1139
1175
|
|
|
@@ -1173,13 +1209,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1173
1209
|
// https:// jira-eng-gpk2.cisco.com/jira/browse/SPARK-240520
|
|
1174
1210
|
// TODO: send custom parameter explaining why the inactivity happened
|
|
1175
1211
|
// refresh , no media or network got dsconnected or something else
|
|
1176
|
-
Metrics.sendBehavioralMetric(
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
locus_id: this.locusId
|
|
1181
|
-
}
|
|
1182
|
-
);
|
|
1212
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.DISCONNECT_DUE_TO_INACTIVITY, {
|
|
1213
|
+
correlation_id: this.correlationId,
|
|
1214
|
+
locus_id: this.locusId,
|
|
1215
|
+
});
|
|
1183
1216
|
|
|
1184
1217
|
// Upload logs on media inactivity
|
|
1185
1218
|
// Normally media should not be inactive
|
|
@@ -1187,24 +1220,25 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1187
1220
|
this,
|
|
1188
1221
|
{
|
|
1189
1222
|
file: 'meeting/index',
|
|
1190
|
-
function: 'setUpLocusInfoMediaInactiveListener'
|
|
1223
|
+
function: 'setUpLocusInfoMediaInactiveListener',
|
|
1191
1224
|
},
|
|
1192
1225
|
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
1193
1226
|
this
|
|
1194
1227
|
);
|
|
1195
1228
|
|
|
1196
|
-
LoggerProxy.logger.error(
|
|
1229
|
+
LoggerProxy.logger.error(
|
|
1230
|
+
`Meeting:index#setUpLocusInfoMediaInactiveListener --> Meeting disconnected due to inactivity: ${res.reason}`
|
|
1231
|
+
);
|
|
1197
1232
|
|
|
1198
1233
|
// @ts-ignore - config coming from registerPlugin
|
|
1199
1234
|
if (this.config.reconnection.autoRejoin) {
|
|
1200
1235
|
this.reconnect();
|
|
1201
|
-
}
|
|
1202
|
-
else {
|
|
1236
|
+
} else {
|
|
1203
1237
|
Trigger.trigger(
|
|
1204
1238
|
this,
|
|
1205
1239
|
{
|
|
1206
1240
|
file: 'meeting/index',
|
|
1207
|
-
function: 'setUpLocusInfoMediaInactiveListener'
|
|
1241
|
+
function: 'setUpLocusInfoMediaInactiveListener',
|
|
1208
1242
|
},
|
|
1209
1243
|
EVENT_TRIGGERS.MEETING_SELF_LEFT,
|
|
1210
1244
|
res.reason
|
|
@@ -1230,7 +1264,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1230
1264
|
this,
|
|
1231
1265
|
{
|
|
1232
1266
|
file: 'meeting/index',
|
|
1233
|
-
function: 'setUpLocusInfoAssignHostListener'
|
|
1267
|
+
function: 'setUpLocusInfoAssignHostListener',
|
|
1234
1268
|
},
|
|
1235
1269
|
EVENT_TRIGGERS.MEETING_ACTIONS_UPDATE,
|
|
1236
1270
|
this.inMeetingActions.get()
|
|
@@ -1251,11 +1285,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1251
1285
|
this,
|
|
1252
1286
|
{
|
|
1253
1287
|
file: 'meeting/index',
|
|
1254
|
-
function: 'setUpLocusFullStateListener'
|
|
1288
|
+
function: 'setUpLocusFullStateListener',
|
|
1255
1289
|
},
|
|
1256
1290
|
EVENT_TRIGGERS.MEETING_STATE_CHANGE,
|
|
1257
1291
|
{
|
|
1258
|
-
payload
|
|
1292
|
+
payload,
|
|
1259
1293
|
}
|
|
1260
1294
|
);
|
|
1261
1295
|
});
|
|
@@ -1276,22 +1310,26 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1276
1310
|
* @returns {Object}
|
|
1277
1311
|
* @memberof Meeting
|
|
1278
1312
|
*/
|
|
1279
|
-
getAnalyzerMetricsPrePayload(
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1313
|
+
getAnalyzerMetricsPrePayload(
|
|
1314
|
+
options:
|
|
1315
|
+
| {
|
|
1316
|
+
event: string;
|
|
1317
|
+
trackingId: string;
|
|
1318
|
+
locus: object;
|
|
1319
|
+
mediaConnections: Array<any>;
|
|
1320
|
+
errors: object;
|
|
1321
|
+
}
|
|
1322
|
+
| any
|
|
1323
|
+
) {
|
|
1286
1324
|
if (options) {
|
|
1287
|
-
const {
|
|
1288
|
-
event,
|
|
1289
|
-
trackingId,
|
|
1290
|
-
mediaConnections
|
|
1291
|
-
} = options;
|
|
1325
|
+
const {event, trackingId, mediaConnections} = options;
|
|
1292
1326
|
|
|
1293
1327
|
if (!event) {
|
|
1294
|
-
LoggerProxy.logger.error(
|
|
1328
|
+
LoggerProxy.logger.error(
|
|
1329
|
+
'Meeting:index#getAnalyzerMetricsPrePayload --> Error [Call Analyzer Event',
|
|
1330
|
+
event || '',
|
|
1331
|
+
`]: invalid identifers or event type! ${this.correlationId}`
|
|
1332
|
+
);
|
|
1295
1333
|
|
|
1296
1334
|
return null;
|
|
1297
1335
|
}
|
|
@@ -1302,13 +1340,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1302
1340
|
deviceId: this.deviceUrl,
|
|
1303
1341
|
orgId: this.orgId,
|
|
1304
1342
|
// @ts-ignore fix type
|
|
1305
|
-
locusUrl: this.webex.internal.services.get('locus')
|
|
1343
|
+
locusUrl: this.webex.internal.services.get('locus'),
|
|
1306
1344
|
};
|
|
1307
1345
|
|
|
1308
1346
|
if (this.locusUrl && this.locusInfo.fullState) {
|
|
1309
1347
|
identifiers.locusUrl = this.locusUrl;
|
|
1310
1348
|
identifiers.locusId = this.locusUrl && this.locusUrl.split('/').pop();
|
|
1311
|
-
identifiers.locusStartTime =
|
|
1349
|
+
identifiers.locusStartTime =
|
|
1350
|
+
this.locusInfo.fullState && this.locusInfo.fullState.lastActive;
|
|
1312
1351
|
}
|
|
1313
1352
|
|
|
1314
1353
|
// Check if mediaConnections has been passed in or else use this.mediaConnections
|
|
@@ -1316,8 +1355,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1316
1355
|
identifiers.mediaAgentAlias = mediaConnections?.[0].mediaAgentAlias;
|
|
1317
1356
|
identifiers.mediaAgentGroupId = mediaConnections?.[0].mediaAgentGroupId;
|
|
1318
1357
|
identifiers.mediaAgentCluster = mediaConnections?.[0].mediaAgentCluster;
|
|
1319
|
-
}
|
|
1320
|
-
else if (this.mediaConnections) {
|
|
1358
|
+
} else if (this.mediaConnections) {
|
|
1321
1359
|
identifiers.mediaAgentAlias = this.mediaConnections?.[0].mediaAgentAlias;
|
|
1322
1360
|
identifiers.mediaAgentGroupId = this.mediaConnections?.[0].mediaAgentGroupId;
|
|
1323
1361
|
identifiers.mediaAgentCluster = this.mediaConnections?.[0].mediaAgentCluster;
|
|
@@ -1333,7 +1371,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1333
1371
|
|
|
1334
1372
|
if (joinRespRxStartAudio) {
|
|
1335
1373
|
options.audioSetupDelay = {
|
|
1336
|
-
joinRespRxStart: joinRespRxStartAudio
|
|
1374
|
+
joinRespRxStart: joinRespRxStartAudio,
|
|
1337
1375
|
};
|
|
1338
1376
|
}
|
|
1339
1377
|
|
|
@@ -1341,7 +1379,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1341
1379
|
|
|
1342
1380
|
if (joinRespRxStartAudio) {
|
|
1343
1381
|
options.videoSetupDelay = {
|
|
1344
|
-
joinRespRxStart: joinRespRxStartVideo
|
|
1382
|
+
joinRespRxStart: joinRespRxStartVideo,
|
|
1345
1383
|
};
|
|
1346
1384
|
}
|
|
1347
1385
|
|
|
@@ -1350,7 +1388,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1350
1388
|
if (joinRespTxStartAudio) {
|
|
1351
1389
|
options.audioSetupDelay = {
|
|
1352
1390
|
...options.audioSetupDelay,
|
|
1353
|
-
joinRespTxStart: joinRespTxStartAudio
|
|
1391
|
+
joinRespTxStart: joinRespTxStartAudio,
|
|
1354
1392
|
};
|
|
1355
1393
|
}
|
|
1356
1394
|
|
|
@@ -1359,7 +1397,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1359
1397
|
if (joinRespTxStartVideo) {
|
|
1360
1398
|
options.videoSetupDelay = {
|
|
1361
1399
|
...options.videoSetupDelay,
|
|
1362
|
-
joinRespTxStart: joinRespTxStartVideo
|
|
1400
|
+
joinRespTxStart: joinRespTxStartVideo,
|
|
1363
1401
|
};
|
|
1364
1402
|
}
|
|
1365
1403
|
|
|
@@ -1368,7 +1406,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1368
1406
|
if (localSDPGenRemoteSDPRecv) {
|
|
1369
1407
|
options.joinTimes = {
|
|
1370
1408
|
...options.joinTimes,
|
|
1371
|
-
localSDPGenRemoteSDPRecv
|
|
1409
|
+
localSDPGenRemoteSDPRecv,
|
|
1372
1410
|
};
|
|
1373
1411
|
}
|
|
1374
1412
|
|
|
@@ -1377,7 +1415,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1377
1415
|
if (callInitiateJoinReq) {
|
|
1378
1416
|
options.joinTimes = {
|
|
1379
1417
|
...options.joinTimes,
|
|
1380
|
-
callInitiateJoinReq
|
|
1418
|
+
callInitiateJoinReq,
|
|
1381
1419
|
};
|
|
1382
1420
|
}
|
|
1383
1421
|
|
|
@@ -1386,7 +1424,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1386
1424
|
if (joinReqResp) {
|
|
1387
1425
|
options.joinTimes = {
|
|
1388
1426
|
...options.joinTimes,
|
|
1389
|
-
joinReqResp
|
|
1427
|
+
joinReqResp,
|
|
1390
1428
|
};
|
|
1391
1429
|
}
|
|
1392
1430
|
|
|
@@ -1395,14 +1433,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1395
1433
|
if (getTotalJmt) {
|
|
1396
1434
|
options.joinTimes = {
|
|
1397
1435
|
...options.joinTimes,
|
|
1398
|
-
getTotalJmt
|
|
1436
|
+
getTotalJmt,
|
|
1399
1437
|
};
|
|
1400
1438
|
}
|
|
1401
1439
|
|
|
1402
1440
|
if (options.type === MQA_STATS.CA_TYPE) {
|
|
1403
1441
|
payload = Metrics.initMediaPayload(options.event, identifiers, options);
|
|
1404
|
-
}
|
|
1405
|
-
else {
|
|
1442
|
+
} else {
|
|
1406
1443
|
payload = Metrics.initPayload(options.event, identifiers, options);
|
|
1407
1444
|
}
|
|
1408
1445
|
|
|
@@ -1423,11 +1460,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1423
1460
|
* @private
|
|
1424
1461
|
* @memberof Meeting
|
|
1425
1462
|
*/
|
|
1426
|
-
private sendCallAnalyzerMetrics(options: {
|
|
1463
|
+
private sendCallAnalyzerMetrics(options: {
|
|
1464
|
+
event: string;
|
|
1465
|
+
trackingId: string;
|
|
1466
|
+
locus: object;
|
|
1467
|
+
errors: object;
|
|
1468
|
+
}) {
|
|
1427
1469
|
const payload = this.getAnalyzerMetricsPrePayload({
|
|
1428
1470
|
// @ts-ignore - config coming from registerPlugin
|
|
1429
1471
|
...pick(this.config.metrics, ['clientType', 'subClientType']),
|
|
1430
|
-
...options
|
|
1472
|
+
...options,
|
|
1431
1473
|
});
|
|
1432
1474
|
|
|
1433
1475
|
// @ts-ignore - fix type
|
|
@@ -1444,12 +1486,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1444
1486
|
* @private
|
|
1445
1487
|
* @memberof Meeting
|
|
1446
1488
|
*/
|
|
1447
|
-
private sendMediaQualityAnalyzerMetrics(options: {
|
|
1489
|
+
private sendMediaQualityAnalyzerMetrics(options: {
|
|
1490
|
+
event: string;
|
|
1491
|
+
trackingId: string;
|
|
1492
|
+
locus: object;
|
|
1493
|
+
}) {
|
|
1448
1494
|
const payload = this.getAnalyzerMetricsPrePayload({
|
|
1449
1495
|
type: MQA_STATS.CA_TYPE,
|
|
1450
1496
|
// @ts-ignore - config coming from registerPlugin
|
|
1451
1497
|
...pick(this.config.metrics, ['clientType', 'subClientType']),
|
|
1452
|
-
...options
|
|
1498
|
+
...options,
|
|
1453
1499
|
});
|
|
1454
1500
|
|
|
1455
1501
|
// @ts-ignore
|
|
@@ -1469,19 +1515,21 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1469
1515
|
this,
|
|
1470
1516
|
{
|
|
1471
1517
|
file: 'meeting/index',
|
|
1472
|
-
function: 'setNetworkStatus'
|
|
1518
|
+
function: 'setNetworkStatus',
|
|
1473
1519
|
},
|
|
1474
|
-
EVENT_TRIGGERS.MEETINGS_NETWORK_DISCONNECTED
|
|
1520
|
+
EVENT_TRIGGERS.MEETINGS_NETWORK_DISCONNECTED
|
|
1475
1521
|
);
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1522
|
+
} else if (
|
|
1523
|
+
networkStatus === NETWORK_STATUS.CONNECTED &&
|
|
1524
|
+
this.networkStatus === NETWORK_STATUS.DISCONNECTED
|
|
1525
|
+
) {
|
|
1478
1526
|
Trigger.trigger(
|
|
1479
1527
|
this,
|
|
1480
1528
|
{
|
|
1481
1529
|
file: 'meeting/index',
|
|
1482
|
-
function: 'setNetworkStatus'
|
|
1530
|
+
function: 'setNetworkStatus',
|
|
1483
1531
|
},
|
|
1484
|
-
EVENT_TRIGGERS.MEETINGS_NETWORK_CONNECTED
|
|
1532
|
+
EVENT_TRIGGERS.MEETINGS_NETWORK_CONNECTED
|
|
1485
1533
|
);
|
|
1486
1534
|
}
|
|
1487
1535
|
|
|
@@ -1503,8 +1551,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1503
1551
|
|
|
1504
1552
|
// If user moved to a JOINED state and there is a pending floor grant trigger it
|
|
1505
1553
|
if (this.floorGrantPending && payload.newSelf.state === MEETING_STATE.STATES.JOINED) {
|
|
1506
|
-
this.requestScreenShareFloor()
|
|
1507
|
-
|
|
1554
|
+
this.requestScreenShareFloor().then(() => {
|
|
1555
|
+
this.floorGrantPending = false;
|
|
1556
|
+
});
|
|
1508
1557
|
}
|
|
1509
1558
|
});
|
|
1510
1559
|
}
|
|
@@ -1518,8 +1567,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1518
1567
|
*/
|
|
1519
1568
|
private pstnUpdate(payload: any) {
|
|
1520
1569
|
if (this.locusInfo.self) {
|
|
1521
|
-
const dialInPstnDevice = payload.newSelf?.pstnDevices.find(
|
|
1522
|
-
|
|
1570
|
+
const dialInPstnDevice = payload.newSelf?.pstnDevices.find(
|
|
1571
|
+
(device) => device.url === this.dialInUrl
|
|
1572
|
+
);
|
|
1573
|
+
const dialOutPstnDevice = payload.newSelf?.pstnDevices.find(
|
|
1574
|
+
(device) => device.url === this.dialOutUrl
|
|
1575
|
+
);
|
|
1523
1576
|
let changed = false;
|
|
1524
1577
|
|
|
1525
1578
|
if (dialInPstnDevice) {
|
|
@@ -1545,18 +1598,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1545
1598
|
this,
|
|
1546
1599
|
{
|
|
1547
1600
|
file: 'meeting/index',
|
|
1548
|
-
function: 'setUpLocusSelfListener'
|
|
1601
|
+
function: 'setUpLocusSelfListener',
|
|
1549
1602
|
},
|
|
1550
1603
|
EVENT_TRIGGERS.MEETING_SELF_PHONE_AUDIO_UPDATE,
|
|
1551
1604
|
{
|
|
1552
1605
|
dialIn: {
|
|
1553
1606
|
status: this.dialInDeviceStatus,
|
|
1554
|
-
attendeeId: dialInPstnDevice?.attendeeId
|
|
1607
|
+
attendeeId: dialInPstnDevice?.attendeeId,
|
|
1555
1608
|
},
|
|
1556
1609
|
dialOut: {
|
|
1557
1610
|
status: this.dialOutDeviceStatus,
|
|
1558
|
-
attendeeId: dialOutPstnDevice?.attendeeId
|
|
1559
|
-
}
|
|
1611
|
+
attendeeId: dialOutPstnDevice?.attendeeId,
|
|
1612
|
+
},
|
|
1560
1613
|
}
|
|
1561
1614
|
);
|
|
1562
1615
|
}
|
|
@@ -1609,8 +1662,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1609
1662
|
* @private
|
|
1610
1663
|
* @memberof Meeting
|
|
1611
1664
|
*/
|
|
1612
|
-
|
|
1613
|
-
this.locusInfo.on(
|
|
1665
|
+
private setupLocusControlsListener() {
|
|
1666
|
+
this.locusInfo.on(
|
|
1667
|
+
LOCUSINFO.EVENTS.CONTROLS_RECORDING_UPDATED,
|
|
1614
1668
|
({state, modifiedBy, lastModified}) => {
|
|
1615
1669
|
let event;
|
|
1616
1670
|
|
|
@@ -1636,65 +1690,67 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1636
1690
|
this.recording = {
|
|
1637
1691
|
state: state === RECORDING_STATE.RESUMED ? RECORDING_STATE.RECORDING : state,
|
|
1638
1692
|
modifiedBy,
|
|
1639
|
-
lastModified
|
|
1693
|
+
lastModified,
|
|
1640
1694
|
};
|
|
1641
1695
|
|
|
1642
1696
|
Trigger.trigger(
|
|
1643
1697
|
this,
|
|
1644
1698
|
{
|
|
1645
1699
|
file: 'meeting/index',
|
|
1646
|
-
function: 'setupLocusControlsListener'
|
|
1700
|
+
function: 'setupLocusControlsListener',
|
|
1647
1701
|
},
|
|
1648
1702
|
event,
|
|
1649
1703
|
this.recording
|
|
1650
1704
|
);
|
|
1651
|
-
}
|
|
1705
|
+
}
|
|
1706
|
+
);
|
|
1652
1707
|
|
|
1653
|
-
this.locusInfo.on(
|
|
1708
|
+
this.locusInfo.on(
|
|
1709
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_CONTAINER_UPDATED,
|
|
1654
1710
|
({meetingContainerUrl}) => {
|
|
1655
1711
|
Trigger.trigger(
|
|
1656
1712
|
this,
|
|
1657
1713
|
{
|
|
1658
1714
|
file: 'meeting/index',
|
|
1659
|
-
function: 'setupLocusControlsListener'
|
|
1715
|
+
function: 'setupLocusControlsListener',
|
|
1660
1716
|
},
|
|
1661
1717
|
EVENT_TRIGGERS.MEETING_MEETING_CONTAINER_UPDATE,
|
|
1662
1718
|
{meetingContainerUrl}
|
|
1663
1719
|
);
|
|
1664
|
-
}
|
|
1720
|
+
}
|
|
1721
|
+
);
|
|
1665
1722
|
|
|
1666
|
-
this.locusInfo.on(
|
|
1723
|
+
this.locusInfo.on(
|
|
1724
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIBE_UPDATED,
|
|
1667
1725
|
({caption, transcribing}) => {
|
|
1668
|
-
|
|
1669
1726
|
// @ts-ignore - config coming from registerPlugin
|
|
1670
1727
|
if (transcribing && this.transcription && this.config.receiveTranscription) {
|
|
1671
1728
|
this.receiveTranscription();
|
|
1672
|
-
}
|
|
1673
|
-
else if (!transcribing && this.transcription) {
|
|
1729
|
+
} else if (!transcribing && this.transcription) {
|
|
1674
1730
|
Trigger.trigger(
|
|
1675
1731
|
this,
|
|
1676
1732
|
{
|
|
1677
1733
|
file: 'meeting/index',
|
|
1678
|
-
function: 'setupLocusControlsListener'
|
|
1734
|
+
function: 'setupLocusControlsListener',
|
|
1679
1735
|
},
|
|
1680
1736
|
EVENT_TRIGGERS.MEETING_STOPPED_RECEIVING_TRANSCRIPTION,
|
|
1681
1737
|
{caption, transcribing}
|
|
1682
1738
|
);
|
|
1683
1739
|
}
|
|
1684
|
-
}
|
|
1740
|
+
}
|
|
1741
|
+
);
|
|
1685
1742
|
|
|
1686
|
-
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ENTRY_EXIT_TONE_UPDATED,
|
|
1687
|
-
(
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
});
|
|
1743
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ENTRY_EXIT_TONE_UPDATED, ({entryExitTone}) => {
|
|
1744
|
+
Trigger.trigger(
|
|
1745
|
+
this,
|
|
1746
|
+
{
|
|
1747
|
+
file: 'meeting/index',
|
|
1748
|
+
function: 'setupLocusControlsListener',
|
|
1749
|
+
},
|
|
1750
|
+
EVENT_TRIGGERS.MEETING_ENTRY_EXIT_TONE_UPDATE,
|
|
1751
|
+
{entryExitTone}
|
|
1752
|
+
);
|
|
1753
|
+
});
|
|
1698
1754
|
}
|
|
1699
1755
|
|
|
1700
1756
|
/**
|
|
@@ -1705,7 +1761,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1705
1761
|
* @private
|
|
1706
1762
|
* @memberof Meeting
|
|
1707
1763
|
*/
|
|
1708
|
-
|
|
1764
|
+
private setUpLocusMediaSharesListener() {
|
|
1709
1765
|
// Will get triggered on local and remote share
|
|
1710
1766
|
this.locusInfo.on(EVENTS.LOCUS_INFO_UPDATE_MEDIA_SHARES, (payload) => {
|
|
1711
1767
|
const {content: contentShare, whiteboard: whiteboardShare} = payload.current;
|
|
@@ -1713,11 +1769,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1713
1769
|
const previousWhiteboardShare = payload.previous?.whiteboard;
|
|
1714
1770
|
|
|
1715
1771
|
if (
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1772
|
+
contentShare.beneficiaryId === previousContentShare?.beneficiaryId &&
|
|
1773
|
+
contentShare.disposition === previousContentShare?.disposition &&
|
|
1774
|
+
whiteboardShare.beneficiaryId === previousWhiteboardShare?.beneficiaryId &&
|
|
1775
|
+
whiteboardShare.disposition === previousWhiteboardShare?.disposition &&
|
|
1776
|
+
whiteboardShare.resourceUrl === previousWhiteboardShare?.resourceUrl
|
|
1721
1777
|
) {
|
|
1722
1778
|
// nothing changed, so ignore
|
|
1723
1779
|
// (this happens when we steal presentation from remote)
|
|
@@ -1741,13 +1797,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1741
1797
|
) {
|
|
1742
1798
|
if (this.mediaProperties.shareTrack?.readyState === 'ended') {
|
|
1743
1799
|
this.stopShare({
|
|
1744
|
-
skipSignalingCheck: true
|
|
1745
|
-
})
|
|
1746
|
-
.
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1800
|
+
skipSignalingCheck: true,
|
|
1801
|
+
}).catch((error) => {
|
|
1802
|
+
LoggerProxy.logger.log(
|
|
1803
|
+
'Meeting:index#setUpLocusMediaSharesListener --> Error stopping share: ',
|
|
1804
|
+
error
|
|
1805
|
+
);
|
|
1806
|
+
});
|
|
1807
|
+
} else {
|
|
1751
1808
|
// CONTENT - sharing content local
|
|
1752
1809
|
newShareStatus = SHARE_STATUS.LOCAL_SHARE_ACTIVE;
|
|
1753
1810
|
}
|
|
@@ -1761,10 +1818,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1761
1818
|
}
|
|
1762
1819
|
// or if content share is either released or null and whiteboard share is either released or null, no one is sharing
|
|
1763
1820
|
else if (
|
|
1764
|
-
(previousContentShare &&
|
|
1765
|
-
|
|
1766
|
-
(previousWhiteboardShare &&
|
|
1767
|
-
|
|
1821
|
+
((previousContentShare && contentShare.disposition === FLOOR_ACTION.RELEASED) ||
|
|
1822
|
+
contentShare.disposition === null) &&
|
|
1823
|
+
((previousWhiteboardShare && whiteboardShare.disposition === FLOOR_ACTION.RELEASED) ||
|
|
1824
|
+
whiteboardShare.disposition === null)
|
|
1768
1825
|
) {
|
|
1769
1826
|
newShareStatus = SHARE_STATUS.NO_SHARE;
|
|
1770
1827
|
}
|
|
@@ -1782,7 +1839,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1782
1839
|
this,
|
|
1783
1840
|
{
|
|
1784
1841
|
file: 'meetings/index',
|
|
1785
|
-
function: 'remoteShare'
|
|
1842
|
+
function: 'remoteShare',
|
|
1786
1843
|
},
|
|
1787
1844
|
EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE
|
|
1788
1845
|
);
|
|
@@ -1793,11 +1850,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1793
1850
|
this,
|
|
1794
1851
|
{
|
|
1795
1852
|
file: 'meeting/index',
|
|
1796
|
-
function: '
|
|
1853
|
+
function: 'stopFloorRequest',
|
|
1797
1854
|
},
|
|
1798
1855
|
EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
1799
1856
|
{
|
|
1800
|
-
reason: SHARE_STOPPED_REASON.SELF_STOPPED
|
|
1857
|
+
reason: SHARE_STOPPED_REASON.SELF_STOPPED,
|
|
1801
1858
|
}
|
|
1802
1859
|
);
|
|
1803
1860
|
break;
|
|
@@ -1807,7 +1864,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1807
1864
|
this,
|
|
1808
1865
|
{
|
|
1809
1866
|
file: 'meeting/index',
|
|
1810
|
-
function: 'stopWhiteboardShare'
|
|
1867
|
+
function: 'stopWhiteboardShare',
|
|
1811
1868
|
},
|
|
1812
1869
|
EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD
|
|
1813
1870
|
);
|
|
@@ -1829,27 +1886,28 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1829
1886
|
this,
|
|
1830
1887
|
{
|
|
1831
1888
|
file: 'meetings/index',
|
|
1832
|
-
function: 'remoteShare'
|
|
1889
|
+
function: 'remoteShare',
|
|
1833
1890
|
},
|
|
1834
1891
|
EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
1835
1892
|
{
|
|
1836
|
-
memberId: contentShare.beneficiaryId
|
|
1893
|
+
memberId: contentShare.beneficiaryId,
|
|
1837
1894
|
}
|
|
1838
1895
|
);
|
|
1839
1896
|
};
|
|
1840
1897
|
|
|
1841
1898
|
// if a remote participant is stealing the presentation from us
|
|
1842
|
-
if (
|
|
1899
|
+
if (
|
|
1900
|
+
!this.mediaProperties.mediaDirection?.sendShare ||
|
|
1901
|
+
oldShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE
|
|
1902
|
+
) {
|
|
1843
1903
|
sendStartedSharingRemote();
|
|
1844
|
-
}
|
|
1845
|
-
else {
|
|
1904
|
+
} else {
|
|
1846
1905
|
this.updateShare({
|
|
1847
1906
|
sendShare: false,
|
|
1848
|
-
receiveShare: this.mediaProperties.mediaDirection.receiveShare
|
|
1849
|
-
})
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
});
|
|
1907
|
+
receiveShare: this.mediaProperties.mediaDirection.receiveShare,
|
|
1908
|
+
}).finally(() => {
|
|
1909
|
+
sendStartedSharingRemote();
|
|
1910
|
+
});
|
|
1853
1911
|
}
|
|
1854
1912
|
break;
|
|
1855
1913
|
}
|
|
@@ -1859,9 +1917,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1859
1917
|
this,
|
|
1860
1918
|
{
|
|
1861
1919
|
file: 'meeting/index',
|
|
1862
|
-
function: 'share'
|
|
1920
|
+
function: 'share',
|
|
1863
1921
|
},
|
|
1864
|
-
EVENT_TRIGGERS.MEETING_STARTED_SHARING_LOCAL
|
|
1922
|
+
EVENT_TRIGGERS.MEETING_STARTED_SHARING_LOCAL
|
|
1865
1923
|
);
|
|
1866
1924
|
Metrics.postEvent({event: eventType.LOCAL_SHARE_FLOOR_GRANTED, meeting: this});
|
|
1867
1925
|
break;
|
|
@@ -1871,19 +1929,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1871
1929
|
this,
|
|
1872
1930
|
{
|
|
1873
1931
|
file: 'meeting/index',
|
|
1874
|
-
function: 'startWhiteboardShare'
|
|
1932
|
+
function: 'startWhiteboardShare',
|
|
1875
1933
|
},
|
|
1876
1934
|
EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
1877
1935
|
{
|
|
1878
1936
|
resourceUrl: whiteboardShare.resourceUrl,
|
|
1879
|
-
memberId: whiteboardShare.beneficiaryId
|
|
1937
|
+
memberId: whiteboardShare.beneficiaryId,
|
|
1880
1938
|
}
|
|
1881
1939
|
);
|
|
1882
1940
|
Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_FLOOR_GRANTED, meeting: this});
|
|
1883
1941
|
break;
|
|
1884
1942
|
|
|
1885
1943
|
case SHARE_STATUS.NO_SHARE:
|
|
1886
|
-
|
|
1944
|
+
// nothing to do
|
|
1887
1945
|
break;
|
|
1888
1946
|
|
|
1889
1947
|
default:
|
|
@@ -1891,36 +1949,34 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1891
1949
|
}
|
|
1892
1950
|
|
|
1893
1951
|
this.members.locusMediaSharesUpdate(payload);
|
|
1894
|
-
}
|
|
1895
|
-
else if (newShareStatus === SHARE_STATUS.REMOTE_SHARE_ACTIVE) {
|
|
1952
|
+
} else if (newShareStatus === SHARE_STATUS.REMOTE_SHARE_ACTIVE) {
|
|
1896
1953
|
// if we got here, then some remote participant has stolen
|
|
1897
1954
|
// the presentation from another remote participant
|
|
1898
1955
|
Trigger.trigger(
|
|
1899
1956
|
this,
|
|
1900
1957
|
{
|
|
1901
1958
|
file: 'meetings/index',
|
|
1902
|
-
function: 'remoteShare'
|
|
1959
|
+
function: 'remoteShare',
|
|
1903
1960
|
},
|
|
1904
1961
|
EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
1905
1962
|
{
|
|
1906
|
-
memberId: contentShare.beneficiaryId
|
|
1963
|
+
memberId: contentShare.beneficiaryId,
|
|
1907
1964
|
}
|
|
1908
1965
|
);
|
|
1909
1966
|
this.members.locusMediaSharesUpdate(payload);
|
|
1910
|
-
}
|
|
1911
|
-
else if (newShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE) {
|
|
1967
|
+
} else if (newShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE) {
|
|
1912
1968
|
// if we got here, then some remote participant has stolen
|
|
1913
1969
|
// the presentation from another remote participant
|
|
1914
1970
|
Trigger.trigger(
|
|
1915
1971
|
this,
|
|
1916
1972
|
{
|
|
1917
1973
|
file: 'meeting/index',
|
|
1918
|
-
function: 'startWhiteboardShare'
|
|
1974
|
+
function: 'startWhiteboardShare',
|
|
1919
1975
|
},
|
|
1920
1976
|
EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
1921
1977
|
{
|
|
1922
1978
|
resourceUrl: whiteboardShare.resourceUrl,
|
|
1923
|
-
memberId: whiteboardShare.beneficiaryId
|
|
1979
|
+
memberId: whiteboardShare.beneficiaryId,
|
|
1924
1980
|
}
|
|
1925
1981
|
);
|
|
1926
1982
|
Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_FLOOR_GRANTED, meeting: this});
|
|
@@ -1957,11 +2013,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1957
2013
|
this,
|
|
1958
2014
|
{
|
|
1959
2015
|
file: 'meeting/index',
|
|
1960
|
-
function: 'setUpLocusInfoMeetingInfoListener'
|
|
2016
|
+
function: 'setUpLocusInfoMeetingInfoListener',
|
|
1961
2017
|
},
|
|
1962
2018
|
EVENT_TRIGGERS.MEETING_LOCKED,
|
|
1963
2019
|
{
|
|
1964
|
-
payload
|
|
2020
|
+
payload,
|
|
1965
2021
|
}
|
|
1966
2022
|
);
|
|
1967
2023
|
}
|
|
@@ -1972,11 +2028,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1972
2028
|
this,
|
|
1973
2029
|
{
|
|
1974
2030
|
file: 'meeting/index',
|
|
1975
|
-
function: 'setUpLocusInfoMeetingInfoListener'
|
|
2031
|
+
function: 'setUpLocusInfoMeetingInfoListener',
|
|
1976
2032
|
},
|
|
1977
2033
|
EVENT_TRIGGERS.MEETING_UNLOCKED,
|
|
1978
2034
|
{
|
|
1979
|
-
payload
|
|
2035
|
+
payload,
|
|
1980
2036
|
}
|
|
1981
2037
|
);
|
|
1982
2038
|
}
|
|
@@ -1984,7 +2040,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1984
2040
|
this.locusInfo.on(LOCUSINFO.EVENTS.MEETING_INFO_UPDATED, (payload) => {
|
|
1985
2041
|
if (payload && payload.info) {
|
|
1986
2042
|
const changed = this.inMeetingActions.set({
|
|
1987
|
-
canInviteNewParticipants: MeetingUtil.canInviteNewParticipants(
|
|
2043
|
+
canInviteNewParticipants: MeetingUtil.canInviteNewParticipants(
|
|
2044
|
+
payload.info.userDisplayHints
|
|
2045
|
+
),
|
|
1988
2046
|
canAdmitParticipant: MeetingUtil.canAdmitParticipant(payload.info.userDisplayHints),
|
|
1989
2047
|
canLock: MeetingUtil.canUserLock(payload.info.userDisplayHints),
|
|
1990
2048
|
canUnlock: MeetingUtil.canUserUnlock(payload.info.userDisplayHints),
|
|
@@ -1994,16 +2052,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1994
2052
|
canResumeRecording: MeetingUtil.canUserResume(payload.info.userDisplayHints),
|
|
1995
2053
|
canRaiseHand: MeetingUtil.canUserRaiseHand(payload.info.userDisplayHints),
|
|
1996
2054
|
canLowerAllHands: MeetingUtil.canUserLowerAllHands(payload.info.userDisplayHints),
|
|
1997
|
-
canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(
|
|
1998
|
-
|
|
2055
|
+
canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(
|
|
2056
|
+
payload.info.userDisplayHints
|
|
2057
|
+
),
|
|
2058
|
+
bothLeaveAndEndMeetingAvailable: MeetingUtil.bothLeaveAndEndMeetingAvailable(
|
|
2059
|
+
payload.info.userDisplayHints
|
|
2060
|
+
),
|
|
1999
2061
|
canEnableClosedCaption: MeetingUtil.canEnableClosedCaption(payload.info.userDisplayHints),
|
|
2000
2062
|
canStartTranscribing: MeetingUtil.canStartTranscribing(payload.info.userDisplayHints),
|
|
2001
2063
|
canStopTranscribing: MeetingUtil.canStopTranscribing(payload.info.userDisplayHints),
|
|
2002
2064
|
isClosedCaptionActive: MeetingUtil.isClosedCaptionActive(payload.info.userDisplayHints),
|
|
2003
2065
|
isWebexAssistantActive: MeetingUtil.isWebexAssistantActive(payload.info.userDisplayHints),
|
|
2004
2066
|
canViewCaptionPanel: MeetingUtil.canViewCaptionPanel(payload.info.userDisplayHints),
|
|
2005
|
-
isRealTimeTranslationEnabled: MeetingUtil.isRealTimeTranslationEnabled(
|
|
2006
|
-
|
|
2067
|
+
isRealTimeTranslationEnabled: MeetingUtil.isRealTimeTranslationEnabled(
|
|
2068
|
+
payload.info.userDisplayHints
|
|
2069
|
+
),
|
|
2070
|
+
canSelectSpokenLanguages: MeetingUtil.canSelectSpokenLanguages(
|
|
2071
|
+
payload.info.userDisplayHints
|
|
2072
|
+
),
|
|
2007
2073
|
waitingForOthersToJoin: MeetingUtil.waitingForOthersToJoin(payload.info.userDisplayHints),
|
|
2008
2074
|
});
|
|
2009
2075
|
|
|
@@ -2012,7 +2078,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2012
2078
|
this,
|
|
2013
2079
|
{
|
|
2014
2080
|
file: 'meeting/index',
|
|
2015
|
-
function: 'setUpLocusInfoMeetingInfoListener'
|
|
2081
|
+
function: 'setUpLocusInfoMeetingInfoListener',
|
|
2016
2082
|
},
|
|
2017
2083
|
EVENT_TRIGGERS.MEETING_ACTIONS_UPDATE,
|
|
2018
2084
|
this.inMeetingActions.get()
|
|
@@ -2035,7 +2101,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2035
2101
|
this,
|
|
2036
2102
|
{
|
|
2037
2103
|
file: 'meeting/index',
|
|
2038
|
-
function: 'setUpLocusEmbeddedAppsListener'
|
|
2104
|
+
function: 'setUpLocusEmbeddedAppsListener',
|
|
2039
2105
|
},
|
|
2040
2106
|
EVENT_TRIGGERS.MEETING_EMBEDDED_APPS_UPDATE,
|
|
2041
2107
|
embeddedApps
|
|
@@ -2058,11 +2124,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2058
2124
|
this,
|
|
2059
2125
|
{
|
|
2060
2126
|
file: 'meeting/index',
|
|
2061
|
-
function: 'setUpLocusInfoSelfListener'
|
|
2127
|
+
function: 'setUpLocusInfoSelfListener',
|
|
2062
2128
|
},
|
|
2063
2129
|
EVENT_TRIGGERS.MEETING_SELF_UNMUTED_BY_OTHERS,
|
|
2064
2130
|
{
|
|
2065
|
-
payload
|
|
2131
|
+
payload,
|
|
2066
2132
|
}
|
|
2067
2133
|
);
|
|
2068
2134
|
}
|
|
@@ -2075,17 +2141,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2075
2141
|
// with "mute on entry" server will send us remote mute even if we don't have media configured,
|
|
2076
2142
|
// so if being muted by others, always send the notification,
|
|
2077
2143
|
// but if being unmuted, only send it if we are also locally unmuted
|
|
2078
|
-
if (payload.muted ||
|
|
2144
|
+
if (payload.muted || !this.audio?.isMuted()) {
|
|
2079
2145
|
Trigger.trigger(
|
|
2080
2146
|
this,
|
|
2081
2147
|
{
|
|
2082
2148
|
file: 'meeting/index',
|
|
2083
|
-
function: 'setUpLocusInfoSelfListener'
|
|
2149
|
+
function: 'setUpLocusInfoSelfListener',
|
|
2084
2150
|
},
|
|
2085
|
-
payload.muted
|
|
2151
|
+
payload.muted
|
|
2152
|
+
? EVENT_TRIGGERS.MEETING_SELF_MUTED_BY_OTHERS
|
|
2153
|
+
: EVENT_TRIGGERS.MEETING_SELF_UNMUTED_BY_OTHERS,
|
|
2086
2154
|
{
|
|
2087
|
-
payload
|
|
2088
|
-
}
|
|
2155
|
+
payload,
|
|
2156
|
+
}
|
|
2089
2157
|
);
|
|
2090
2158
|
}
|
|
2091
2159
|
}
|
|
@@ -2095,11 +2163,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2095
2163
|
this,
|
|
2096
2164
|
{
|
|
2097
2165
|
file: 'meeting/index',
|
|
2098
|
-
function: 'setUpLocusInfoSelfListener'
|
|
2166
|
+
function: 'setUpLocusInfoSelfListener',
|
|
2099
2167
|
},
|
|
2100
2168
|
EVENT_TRIGGERS.MEETING_SELF_REQUESTED_TO_UNMUTE,
|
|
2101
2169
|
{
|
|
2102
|
-
payload
|
|
2170
|
+
payload,
|
|
2103
2171
|
}
|
|
2104
2172
|
);
|
|
2105
2173
|
});
|
|
@@ -2111,17 +2179,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2111
2179
|
this,
|
|
2112
2180
|
{
|
|
2113
2181
|
file: 'meeting/index',
|
|
2114
|
-
function: 'setUpLocusInfoSelfListener'
|
|
2182
|
+
function: 'setUpLocusInfoSelfListener',
|
|
2115
2183
|
},
|
|
2116
2184
|
EVENT_TRIGGERS.MEETING_SELF_LOBBY_WAITING,
|
|
2117
2185
|
{
|
|
2118
|
-
payload
|
|
2186
|
+
payload,
|
|
2119
2187
|
}
|
|
2120
2188
|
);
|
|
2121
2189
|
|
|
2122
2190
|
Metrics.postEvent({
|
|
2123
2191
|
event: eventType.LOBBY_ENTERED,
|
|
2124
|
-
meeting: this
|
|
2192
|
+
meeting: this,
|
|
2125
2193
|
});
|
|
2126
2194
|
}
|
|
2127
2195
|
});
|
|
@@ -2133,30 +2201,27 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2133
2201
|
this,
|
|
2134
2202
|
{
|
|
2135
2203
|
file: 'meeting/index',
|
|
2136
|
-
function: 'setUpLocusInfoSelfListener'
|
|
2204
|
+
function: 'setUpLocusInfoSelfListener',
|
|
2137
2205
|
},
|
|
2138
2206
|
EVENT_TRIGGERS.MEETING_SELF_GUEST_ADMITTED,
|
|
2139
2207
|
{
|
|
2140
|
-
payload
|
|
2208
|
+
payload,
|
|
2141
2209
|
}
|
|
2142
2210
|
);
|
|
2143
2211
|
|
|
2144
2212
|
Metrics.postEvent({
|
|
2145
2213
|
event: eventType.LOBBY_EXITED,
|
|
2146
|
-
meeting: this
|
|
2214
|
+
meeting: this,
|
|
2147
2215
|
});
|
|
2148
2216
|
}
|
|
2149
2217
|
});
|
|
2150
2218
|
|
|
2151
2219
|
// @ts-ignore - check if MEDIA_INACTIVITY exists
|
|
2152
2220
|
this.locusInfo.on(LOCUSINFO.EVENTS.MEDIA_INACTIVITY, () => {
|
|
2153
|
-
Metrics.sendBehavioralMetric(
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
locus_id: this.locusId
|
|
2158
|
-
}
|
|
2159
|
-
);
|
|
2221
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_MEDIA_INACTIVE, {
|
|
2222
|
+
correlation_id: this.correlationId,
|
|
2223
|
+
locus_id: this.locusId,
|
|
2224
|
+
});
|
|
2160
2225
|
this.reconnect();
|
|
2161
2226
|
});
|
|
2162
2227
|
|
|
@@ -2174,8 +2239,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2174
2239
|
sendShare: this.mediaProperties.mediaDirection?.sendShare,
|
|
2175
2240
|
receiveAudio: this.mediaProperties.mediaDirection?.receiveAudio,
|
|
2176
2241
|
receiveVideo: this.mediaProperties.mediaDirection?.receiveVideo,
|
|
2177
|
-
receiveShare: this.mediaProperties.mediaDirection?.receiveShare
|
|
2178
|
-
}
|
|
2242
|
+
receiveShare: this.mediaProperties.mediaDirection?.receiveShare,
|
|
2243
|
+
},
|
|
2179
2244
|
});
|
|
2180
2245
|
}
|
|
2181
2246
|
});
|
|
@@ -2185,11 +2250,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2185
2250
|
this,
|
|
2186
2251
|
{
|
|
2187
2252
|
file: 'meeting/index',
|
|
2188
|
-
function: 'setUpLocusInfoSelfListener'
|
|
2253
|
+
function: 'setUpLocusInfoSelfListener',
|
|
2189
2254
|
},
|
|
2190
2255
|
EVENT_TRIGGERS.MEETING_SELF_CANNOT_VIEW_PARTICIPANT_LIST,
|
|
2191
2256
|
{
|
|
2192
|
-
payload
|
|
2257
|
+
payload,
|
|
2193
2258
|
}
|
|
2194
2259
|
);
|
|
2195
2260
|
});
|
|
@@ -2199,11 +2264,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2199
2264
|
this,
|
|
2200
2265
|
{
|
|
2201
2266
|
file: 'meeting/index',
|
|
2202
|
-
function: 'setUpLocusInfoSelfListener'
|
|
2267
|
+
function: 'setUpLocusInfoSelfListener',
|
|
2203
2268
|
},
|
|
2204
2269
|
EVENT_TRIGGERS.MEETING_SELF_IS_SHARING_BLOCKED,
|
|
2205
2270
|
{
|
|
2206
|
-
payload
|
|
2271
|
+
payload,
|
|
2207
2272
|
}
|
|
2208
2273
|
);
|
|
2209
2274
|
});
|
|
@@ -2220,12 +2285,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2220
2285
|
this.meetingFiniteStateMachine.remote(payload);
|
|
2221
2286
|
|
|
2222
2287
|
if (payload.remoteDeclined) {
|
|
2223
|
-
this.leave({reason: payload.reason})
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2288
|
+
this.leave({reason: payload.reason})
|
|
2289
|
+
.then(() => {
|
|
2290
|
+
LoggerProxy.logger.info(
|
|
2291
|
+
'Meeting:index#setUpLocusInfoMeetingListener --> REMOTE_RESPONSE. Attempting to leave meeting.'
|
|
2292
|
+
);
|
|
2293
|
+
})
|
|
2294
|
+
.catch((error) => {
|
|
2295
|
+
// @ts-ignore
|
|
2296
|
+
LoggerProxy.logger.error(
|
|
2297
|
+
`Meeting:index#setUpLocusInfoMeetingListener --> REMOTE_RESPONSE. Issue with leave for meeting, meeting still in collection: ${this.meeting}, error: ${error}`
|
|
2298
|
+
);
|
|
2299
|
+
});
|
|
2229
2300
|
}
|
|
2230
2301
|
});
|
|
2231
2302
|
this.locusInfo.on(EVENTS.DESTROY_MEETING, (payload) => {
|
|
@@ -2249,27 +2320,35 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2249
2320
|
if (payload.shouldLeave) {
|
|
2250
2321
|
// TODO: We should do cleaning of meeting object if the shouldLeave: false because there might be meeting object which we are not cleaning
|
|
2251
2322
|
|
|
2252
|
-
this.leave({reason: payload.reason})
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2323
|
+
this.leave({reason: payload.reason})
|
|
2324
|
+
.then(() => {
|
|
2325
|
+
LoggerProxy.logger.warn(
|
|
2326
|
+
'Meeting:index#setUpLocusInfoMeetingListener --> DESTROY_MEETING. The meeting has been left, but has not been destroyed, you should see a later event for leave.'
|
|
2327
|
+
);
|
|
2328
|
+
})
|
|
2329
|
+
.catch((error) => {
|
|
2330
|
+
// @ts-ignore
|
|
2331
|
+
LoggerProxy.logger.error(
|
|
2332
|
+
`Meeting:index#setUpLocusInfoMeetingListener --> DESTROY_MEETING. Issue with leave for meeting, meeting still in collection: ${this.meeting}, error: ${error}`
|
|
2333
|
+
);
|
|
2334
|
+
});
|
|
2335
|
+
} else {
|
|
2336
|
+
LoggerProxy.logger.info(
|
|
2337
|
+
'Meeting:index#setUpLocusInfoMeetingListener --> MEETING_REMOVED_REASON',
|
|
2338
|
+
payload.reason
|
|
2339
|
+
);
|
|
2261
2340
|
|
|
2262
2341
|
MeetingUtil.cleanUp(this);
|
|
2263
2342
|
Trigger.trigger(
|
|
2264
2343
|
this,
|
|
2265
2344
|
{
|
|
2266
2345
|
file: 'meeting/index',
|
|
2267
|
-
function: 'setUpLocusInfoMeetingListener'
|
|
2346
|
+
function: 'setUpLocusInfoMeetingListener',
|
|
2268
2347
|
},
|
|
2269
2348
|
EVENTS.DESTROY_MEETING,
|
|
2270
2349
|
{
|
|
2271
2350
|
reason: payload.reason,
|
|
2272
|
-
meetingId: this.id
|
|
2351
|
+
meetingId: this.id,
|
|
2273
2352
|
}
|
|
2274
2353
|
);
|
|
2275
2354
|
}
|
|
@@ -2312,7 +2391,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2312
2391
|
email: string;
|
|
2313
2392
|
phoneNumber: string;
|
|
2314
2393
|
},
|
|
2315
|
-
alertIfActive
|
|
2394
|
+
alertIfActive = true
|
|
2316
2395
|
) {
|
|
2317
2396
|
return this.members.addMember(invitee, alertIfActive);
|
|
2318
2397
|
}
|
|
@@ -2325,7 +2404,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2325
2404
|
* @public
|
|
2326
2405
|
* @memberof Meeting
|
|
2327
2406
|
*/
|
|
2328
|
-
public cancelPhoneInvite(invitee: {
|
|
2407
|
+
public cancelPhoneInvite(invitee: {phoneNumber: string}) {
|
|
2329
2408
|
return this.members.cancelPhoneInvite(invitee);
|
|
2330
2409
|
}
|
|
2331
2410
|
|
|
@@ -2359,7 +2438,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2359
2438
|
* @public
|
|
2360
2439
|
* @memberof Meeting
|
|
2361
2440
|
*/
|
|
2362
|
-
public mute(memberId: string, mute
|
|
2441
|
+
public mute(memberId: string, mute = true) {
|
|
2363
2442
|
return this.members.muteMember(memberId, mute);
|
|
2364
2443
|
}
|
|
2365
2444
|
|
|
@@ -2371,7 +2450,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2371
2450
|
* @public
|
|
2372
2451
|
* @memberof Meeting
|
|
2373
2452
|
*/
|
|
2374
|
-
public transfer(memberId: string, moderator
|
|
2453
|
+
public transfer(memberId: string, moderator = true) {
|
|
2375
2454
|
return this.members.transferHostToMember(memberId, moderator);
|
|
2376
2455
|
}
|
|
2377
2456
|
|
|
@@ -2459,14 +2538,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2459
2538
|
* @memberof Meeting
|
|
2460
2539
|
*/
|
|
2461
2540
|
parseMeetingInfo(
|
|
2462
|
-
meetingInfo:
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2541
|
+
meetingInfo:
|
|
2542
|
+
| {
|
|
2543
|
+
body: {
|
|
2544
|
+
conversationUrl: string;
|
|
2545
|
+
locusUrl: string;
|
|
2546
|
+
sipUri: string;
|
|
2547
|
+
owner: object;
|
|
2548
|
+
};
|
|
2549
|
+
}
|
|
2550
|
+
| any,
|
|
2470
2551
|
destination: object | string | null = null
|
|
2471
2552
|
) {
|
|
2472
2553
|
const webexMeetingInfo = meetingInfo?.body;
|
|
@@ -2479,17 +2560,32 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2479
2560
|
}
|
|
2480
2561
|
|
|
2481
2562
|
// MeetingInfo will be undefined for 1:1 calls
|
|
2482
|
-
if (
|
|
2483
|
-
|
|
2563
|
+
if (
|
|
2564
|
+
locusMeetingObject ||
|
|
2565
|
+
(webexMeetingInfo && !(meetingInfo?.errors && meetingInfo?.errors.length > 0))
|
|
2566
|
+
) {
|
|
2567
|
+
this.conversationUrl =
|
|
2568
|
+
locusMeetingObject?.conversationUrl ||
|
|
2569
|
+
webexMeetingInfo?.conversationUrl ||
|
|
2570
|
+
this.conversationUrl;
|
|
2484
2571
|
this.locusUrl = locusMeetingObject?.url || webexMeetingInfo?.locusUrl || this.locusUrl;
|
|
2485
2572
|
// @ts-ignore - config coming from registerPlugin
|
|
2486
|
-
this.setSipUri(
|
|
2573
|
+
this.setSipUri(
|
|
2574
|
+
this.config.experimental.enableUnifiedMeetings
|
|
2575
|
+
? locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipUrl
|
|
2576
|
+
: locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipMeetingUri || this.sipUri
|
|
2577
|
+
);
|
|
2487
2578
|
// @ts-ignore - config coming from registerPlugin
|
|
2488
2579
|
if (this.config.experimental.enableUnifiedMeetings) {
|
|
2489
|
-
this.meetingNumber =
|
|
2580
|
+
this.meetingNumber =
|
|
2581
|
+
locusMeetingObject?.info.webExMeetingId || webexMeetingInfo?.meetingNumber;
|
|
2490
2582
|
this.meetingJoinUrl = webexMeetingInfo?.meetingJoinUrl;
|
|
2491
2583
|
}
|
|
2492
|
-
this.owner =
|
|
2584
|
+
this.owner =
|
|
2585
|
+
locusMeetingObject?.info.owner ||
|
|
2586
|
+
webexMeetingInfo?.owner ||
|
|
2587
|
+
webexMeetingInfo?.hostId ||
|
|
2588
|
+
this.owner;
|
|
2493
2589
|
this.permissionToken = webexMeetingInfo?.permissionToken;
|
|
2494
2590
|
}
|
|
2495
2591
|
}
|
|
@@ -2504,7 +2600,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2504
2600
|
* @private
|
|
2505
2601
|
* @memberof Meeting
|
|
2506
2602
|
*/
|
|
2507
|
-
private parseLocus(locus: {
|
|
2603
|
+
private parseLocus(locus: {url: string; participants: Array<any>; self: object}) {
|
|
2508
2604
|
if (locus) {
|
|
2509
2605
|
this.locusUrl = locus.url;
|
|
2510
2606
|
// TODO: move this to parse participants module
|
|
@@ -2562,13 +2658,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2562
2658
|
* @private
|
|
2563
2659
|
* @memberof Meeting
|
|
2564
2660
|
*/
|
|
2565
|
-
private setLocus(
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2661
|
+
private setLocus(
|
|
2662
|
+
locus:
|
|
2663
|
+
| {
|
|
2664
|
+
mediaConnections: Array<any>;
|
|
2665
|
+
locusUrl: string;
|
|
2666
|
+
locusId: string;
|
|
2667
|
+
mediaId: string;
|
|
2668
|
+
host: object;
|
|
2669
|
+
}
|
|
2670
|
+
| any
|
|
2671
|
+
) {
|
|
2572
2672
|
const mtgLocus: any = locus.locus || locus;
|
|
2573
2673
|
|
|
2574
2674
|
// LocusInfo object saves the locus object
|
|
@@ -2602,13 +2702,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2602
2702
|
// so we might need to either
|
|
2603
2703
|
// A) wait until we have media flowing
|
|
2604
2704
|
// B) trigger a second event when video is flowing
|
|
2605
|
-
LoggerProxy.logger.log(
|
|
2705
|
+
LoggerProxy.logger.log(
|
|
2706
|
+
`Meeting:index#setRemoteStream --> ontrack event received for peerConnection: ${event}`
|
|
2707
|
+
);
|
|
2606
2708
|
|
|
2607
2709
|
const MEDIA_ID = {
|
|
2608
2710
|
AUDIO_TRACK: '0',
|
|
2609
2711
|
VIDEO_TRACK: '1',
|
|
2610
|
-
SHARE_TRACK: '2'
|
|
2712
|
+
SHARE_TRACK: '2',
|
|
2611
2713
|
};
|
|
2714
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
2612
2715
|
let eventType = null;
|
|
2613
2716
|
const mediaTrack = event.track;
|
|
2614
2717
|
let trackMediaID = null;
|
|
@@ -2617,31 +2720,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2617
2720
|
// sdk tries to determine the transceive using the track id present
|
|
2618
2721
|
if (event.transceiver && event.transceiver.mid) {
|
|
2619
2722
|
trackMediaID = event.transceiver.mid;
|
|
2620
|
-
}
|
|
2621
|
-
else {
|
|
2723
|
+
} else {
|
|
2622
2724
|
const {audioTransceiver, videoTransceiver, shareTransceiver} = event.target;
|
|
2623
2725
|
|
|
2624
2726
|
// audio kind indicates its a audio stream
|
|
2625
2727
|
if (mediaTrack.id === audioTransceiver.receiver.track.id) {
|
|
2626
2728
|
trackMediaID = '0';
|
|
2627
|
-
}
|
|
2628
|
-
else
|
|
2629
|
-
if (mediaTrack.id === videoTransceiver.receiver.track.id) {
|
|
2729
|
+
} else if (mediaTrack.id === videoTransceiver.receiver.track.id) {
|
|
2630
2730
|
trackMediaID = '1';
|
|
2631
|
-
}
|
|
2632
|
-
else
|
|
2633
|
-
if (mediaTrack.id === shareTransceiver.receiver.track.id) {
|
|
2731
|
+
} else if (mediaTrack.id === shareTransceiver.receiver.track.id) {
|
|
2634
2732
|
trackMediaID = '2';
|
|
2635
|
-
}
|
|
2636
|
-
else {
|
|
2733
|
+
} else {
|
|
2637
2734
|
trackMediaID = null;
|
|
2638
|
-
Metrics.sendBehavioralMetric(
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
locus_id: this.locusUrl.split('/').pop()
|
|
2643
|
-
}
|
|
2644
|
-
);
|
|
2735
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MUTE_AUDIO_FAILURE, {
|
|
2736
|
+
correlation_id: this.correlationId,
|
|
2737
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
2738
|
+
});
|
|
2645
2739
|
}
|
|
2646
2740
|
}
|
|
2647
2741
|
|
|
@@ -2674,12 +2768,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2674
2768
|
this,
|
|
2675
2769
|
{
|
|
2676
2770
|
file: 'meeting/index',
|
|
2677
|
-
function: 'setRemoteStream:pc.ontrack'
|
|
2771
|
+
function: 'setRemoteStream:pc.ontrack',
|
|
2678
2772
|
},
|
|
2679
2773
|
EVENT_TRIGGERS.MEDIA_READY,
|
|
2680
2774
|
{
|
|
2681
2775
|
type: eventType,
|
|
2682
|
-
stream: MediaUtil.createMediaStream([mediaTrack])
|
|
2776
|
+
stream: MediaUtil.createMediaStream([mediaTrack]),
|
|
2683
2777
|
}
|
|
2684
2778
|
);
|
|
2685
2779
|
}
|
|
@@ -2693,13 +2787,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2693
2787
|
* @public
|
|
2694
2788
|
* @memberof Meeting
|
|
2695
2789
|
*/
|
|
2696
|
-
public uploadLogs(options: object = {
|
|
2697
|
-
Trigger.trigger(
|
|
2698
|
-
this,
|
|
2699
|
-
options,
|
|
2700
|
-
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
2701
|
-
this
|
|
2702
|
-
);
|
|
2790
|
+
public uploadLogs(options: object = {file: 'meeting/index', function: 'uploadLogs'}) {
|
|
2791
|
+
Trigger.trigger(this, options, EVENTS.REQUEST_UPLOAD_LOGS, this);
|
|
2703
2792
|
}
|
|
2704
2793
|
|
|
2705
2794
|
/**
|
|
@@ -2711,7 +2800,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2711
2800
|
* @deprecated after v1.89.3
|
|
2712
2801
|
*/
|
|
2713
2802
|
public unsetRemoteStream() {
|
|
2714
|
-
LoggerProxy.logger.warn(
|
|
2803
|
+
LoggerProxy.logger.warn(
|
|
2804
|
+
'Meeting:index#unsetRemoteStream --> [DEPRECATION WARNING]: unsetRemoteStream has been deprecated after v1.89.3'
|
|
2805
|
+
);
|
|
2715
2806
|
this.mediaProperties.unsetRemoteMedia();
|
|
2716
2807
|
}
|
|
2717
2808
|
|
|
@@ -2732,7 +2823,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2732
2823
|
* @deprecated after v1.89.3
|
|
2733
2824
|
*/
|
|
2734
2825
|
public closeRemoteStream() {
|
|
2735
|
-
LoggerProxy.logger.warn(
|
|
2826
|
+
LoggerProxy.logger.warn(
|
|
2827
|
+
'Meeting:index#closeRemoteStream --> [DEPRECATION WARNING]: closeRemoteStream has been deprecated after v1.89.3'
|
|
2828
|
+
);
|
|
2736
2829
|
this.closeRemoteTracks();
|
|
2737
2830
|
}
|
|
2738
2831
|
|
|
@@ -2743,11 +2836,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2743
2836
|
* @memberof Meeting
|
|
2744
2837
|
*/
|
|
2745
2838
|
closeRemoteTracks() {
|
|
2746
|
-
const {
|
|
2747
|
-
remoteAudioTrack,
|
|
2748
|
-
remoteVideoTrack,
|
|
2749
|
-
remoteShare
|
|
2750
|
-
} = this.mediaProperties;
|
|
2839
|
+
const {remoteAudioTrack, remoteVideoTrack, remoteShare} = this.mediaProperties;
|
|
2751
2840
|
|
|
2752
2841
|
/**
|
|
2753
2842
|
* Triggers an event to the developer
|
|
@@ -2755,16 +2844,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2755
2844
|
* @returns {void}
|
|
2756
2845
|
* @inner
|
|
2757
2846
|
*/
|
|
2847
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
2758
2848
|
const triggerMediaStoppedEvent = (mediaType: string) => {
|
|
2759
2849
|
Trigger.trigger(
|
|
2760
2850
|
this,
|
|
2761
2851
|
{
|
|
2762
2852
|
file: 'meeting/index',
|
|
2763
|
-
function: 'closeRemoteTracks'
|
|
2853
|
+
function: 'closeRemoteTracks',
|
|
2764
2854
|
},
|
|
2765
2855
|
EVENT_TRIGGERS.MEDIA_STOPPED,
|
|
2766
2856
|
{
|
|
2767
|
-
type: mediaType
|
|
2857
|
+
type: mediaType,
|
|
2768
2858
|
}
|
|
2769
2859
|
);
|
|
2770
2860
|
};
|
|
@@ -2778,24 +2868,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2778
2868
|
*/
|
|
2779
2869
|
// eslint-disable-next-line arrow-body-style
|
|
2780
2870
|
const stopTrack = (track: MediaStreamTrack, type: string) => {
|
|
2781
|
-
return Media.stopTracks(track)
|
|
2782
|
-
.
|
|
2783
|
-
|
|
2784
|
-
const isWrongReadyState = track && !isTrackStopped;
|
|
2871
|
+
return Media.stopTracks(track).then(() => {
|
|
2872
|
+
const isTrackStopped = track && track.readyState === ENDED;
|
|
2873
|
+
const isWrongReadyState = track && !isTrackStopped;
|
|
2785
2874
|
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
}
|
|
2875
|
+
if (isTrackStopped) {
|
|
2876
|
+
triggerMediaStoppedEvent(type);
|
|
2877
|
+
} else if (isWrongReadyState) {
|
|
2878
|
+
LoggerProxy.logger.warn(
|
|
2879
|
+
`Meeting:index#closeRemoteTracks --> Error: MediaStreamTrack.readyState is ${track.readyState} for ${type}`
|
|
2880
|
+
);
|
|
2881
|
+
}
|
|
2882
|
+
});
|
|
2793
2883
|
};
|
|
2794
2884
|
|
|
2795
2885
|
return Promise.all([
|
|
2796
2886
|
stopTrack(remoteAudioTrack, EVENT_TYPES.REMOTE_AUDIO),
|
|
2797
2887
|
stopTrack(remoteVideoTrack, EVENT_TYPES.REMOTE_VIDEO),
|
|
2798
|
-
stopTrack(remoteShare, EVENT_TYPES.REMOTE_SHARE)
|
|
2888
|
+
stopTrack(remoteShare, EVENT_TYPES.REMOTE_SHARE),
|
|
2799
2889
|
]);
|
|
2800
2890
|
}
|
|
2801
2891
|
|
|
@@ -2810,12 +2900,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2810
2900
|
this,
|
|
2811
2901
|
{
|
|
2812
2902
|
file: 'meeting/index',
|
|
2813
|
-
function: 'setLocalTracks'
|
|
2903
|
+
function: 'setLocalTracks',
|
|
2814
2904
|
},
|
|
2815
2905
|
EVENT_TRIGGERS.MEDIA_READY,
|
|
2816
2906
|
{
|
|
2817
2907
|
type: EVENT_TYPES.LOCAL,
|
|
2818
|
-
stream: MediaUtil.createMediaStream([
|
|
2908
|
+
stream: MediaUtil.createMediaStream([
|
|
2909
|
+
this.mediaProperties.audioTrack,
|
|
2910
|
+
this.mediaProperties.videoTrack,
|
|
2911
|
+
]),
|
|
2819
2912
|
}
|
|
2820
2913
|
);
|
|
2821
2914
|
}
|
|
@@ -2828,16 +2921,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2828
2921
|
* @private
|
|
2829
2922
|
* @memberof Meeting
|
|
2830
2923
|
*/
|
|
2831
|
-
private setLocalAudioTrack(audioTrack: MediaStreamTrack, emitEvent
|
|
2924
|
+
private setLocalAudioTrack(audioTrack: MediaStreamTrack, emitEvent = true) {
|
|
2832
2925
|
if (audioTrack) {
|
|
2833
2926
|
const settings = audioTrack.getSettings();
|
|
2834
2927
|
|
|
2835
2928
|
this.mediaProperties.setMediaSettings('audio', {
|
|
2836
2929
|
echoCancellation: settings.echoCancellation,
|
|
2837
|
-
noiseSuppression: settings.noiseSuppression
|
|
2930
|
+
noiseSuppression: settings.noiseSuppression,
|
|
2838
2931
|
});
|
|
2839
2932
|
|
|
2840
|
-
LoggerProxy.logger.log(
|
|
2933
|
+
LoggerProxy.logger.log(
|
|
2934
|
+
'Meeting:index#setLocalAudioTrack --> Audio settings.',
|
|
2935
|
+
JSON.stringify(this.mediaProperties.mediaSettings.audio)
|
|
2936
|
+
);
|
|
2841
2937
|
this.mediaProperties.setLocalAudioTrack(audioTrack);
|
|
2842
2938
|
if (this.audio) this.audio.applyClientStateLocally(this);
|
|
2843
2939
|
}
|
|
@@ -2855,16 +2951,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2855
2951
|
* @private
|
|
2856
2952
|
* @memberof Meeting
|
|
2857
2953
|
*/
|
|
2858
|
-
private setLocalVideoTrack(videoTrack: MediaStreamTrack, emitEvent
|
|
2954
|
+
private setLocalVideoTrack(videoTrack: MediaStreamTrack, emitEvent = true) {
|
|
2859
2955
|
if (videoTrack) {
|
|
2860
|
-
const {
|
|
2861
|
-
aspectRatio, frameRate, height, width, deviceId
|
|
2862
|
-
} = videoTrack.getSettings();
|
|
2956
|
+
const {aspectRatio, frameRate, height, width, deviceId} = videoTrack.getSettings();
|
|
2863
2957
|
|
|
2864
2958
|
const {localQualityLevel} = this.mediaProperties;
|
|
2865
2959
|
|
|
2866
2960
|
if (Number(localQualityLevel.slice(0, -1)) > height) {
|
|
2867
|
-
LoggerProxy.logger
|
|
2961
|
+
LoggerProxy.logger
|
|
2962
|
+
.warn(`Meeting:index#setLocalVideoTrack --> Local video quality of ${localQualityLevel} not supported,
|
|
2868
2963
|
downscaling to highest possible resolution of ${height}p`);
|
|
2869
2964
|
|
|
2870
2965
|
this.mediaProperties.setLocalQualityLevel(`${height}p`);
|
|
@@ -2874,13 +2969,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2874
2969
|
if (this.video) this.video.applyClientStateLocally(this);
|
|
2875
2970
|
|
|
2876
2971
|
this.mediaProperties.setMediaSettings('video', {
|
|
2877
|
-
aspectRatio,
|
|
2972
|
+
aspectRatio,
|
|
2973
|
+
frameRate,
|
|
2974
|
+
height,
|
|
2975
|
+
width,
|
|
2878
2976
|
});
|
|
2879
2977
|
// store and save the selected video input device
|
|
2880
2978
|
if (deviceId) {
|
|
2881
2979
|
this.mediaProperties.setVideoDeviceId(deviceId);
|
|
2882
2980
|
}
|
|
2883
|
-
LoggerProxy.logger.log(
|
|
2981
|
+
LoggerProxy.logger.log(
|
|
2982
|
+
'Meeting:index#setLocalVideoTrack --> Video settings.',
|
|
2983
|
+
JSON.stringify(this.mediaProperties.mediaSettings.video)
|
|
2984
|
+
);
|
|
2884
2985
|
}
|
|
2885
2986
|
|
|
2886
2987
|
if (emitEvent) {
|
|
@@ -2928,9 +3029,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2928
3029
|
height: settings.height,
|
|
2929
3030
|
width: settings.width,
|
|
2930
3031
|
displaySurface: settings.displaySurface,
|
|
2931
|
-
cursor: settings.cursor
|
|
3032
|
+
cursor: settings.cursor,
|
|
2932
3033
|
});
|
|
2933
|
-
LoggerProxy.logger.log(
|
|
3034
|
+
LoggerProxy.logger.log(
|
|
3035
|
+
'Meeting:index#setLocalShareTrack --> Screen settings.',
|
|
3036
|
+
JSON.stringify(this.mediaProperties.mediaSettings.screen)
|
|
3037
|
+
);
|
|
2934
3038
|
}
|
|
2935
3039
|
|
|
2936
3040
|
contentTracks.onended = () => this.handleShareTrackEnded(localShare);
|
|
@@ -2939,12 +3043,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2939
3043
|
this,
|
|
2940
3044
|
{
|
|
2941
3045
|
file: 'meeting/index',
|
|
2942
|
-
function: 'setLocalShareTrack'
|
|
3046
|
+
function: 'setLocalShareTrack',
|
|
2943
3047
|
},
|
|
2944
3048
|
EVENT_TRIGGERS.MEDIA_READY,
|
|
2945
3049
|
{
|
|
2946
3050
|
type: EVENT_TYPES.LOCAL_SHARE,
|
|
2947
|
-
stream: localShare
|
|
3051
|
+
stream: localShare,
|
|
2948
3052
|
}
|
|
2949
3053
|
);
|
|
2950
3054
|
}
|
|
@@ -2972,15 +3076,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2972
3076
|
this,
|
|
2973
3077
|
{
|
|
2974
3078
|
file: 'meeting/index',
|
|
2975
|
-
function: 'closeLocalStream'
|
|
3079
|
+
function: 'closeLocalStream',
|
|
2976
3080
|
},
|
|
2977
|
-
EVENT_TRIGGERS.MEDIA_STOPPED,
|
|
2978
|
-
|
|
3081
|
+
EVENT_TRIGGERS.MEDIA_STOPPED,
|
|
3082
|
+
{
|
|
3083
|
+
type: EVENT_TYPES.LOCAL,
|
|
2979
3084
|
}
|
|
2980
3085
|
);
|
|
2981
|
-
}
|
|
2982
|
-
|
|
2983
|
-
|
|
3086
|
+
} else if (audioTrack || videoTrack) {
|
|
3087
|
+
LoggerProxy.logger.warn(
|
|
3088
|
+
'Meeting:index#closeLocalStream --> Warning: track might already been ended or unavaliable.'
|
|
3089
|
+
);
|
|
2984
3090
|
}
|
|
2985
3091
|
});
|
|
2986
3092
|
}
|
|
@@ -3001,16 +3107,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3001
3107
|
this,
|
|
3002
3108
|
{
|
|
3003
3109
|
file: 'meeting/index',
|
|
3004
|
-
function: 'closeLocalShare'
|
|
3110
|
+
function: 'closeLocalShare',
|
|
3005
3111
|
},
|
|
3006
|
-
EVENT_TRIGGERS.MEDIA_STOPPED,
|
|
3007
|
-
|
|
3112
|
+
EVENT_TRIGGERS.MEDIA_STOPPED,
|
|
3113
|
+
{
|
|
3114
|
+
type: EVENT_TYPES.LOCAL_SHARE,
|
|
3008
3115
|
}
|
|
3009
3116
|
);
|
|
3010
|
-
}
|
|
3011
|
-
else if (track) {
|
|
3117
|
+
} else if (track) {
|
|
3012
3118
|
// Track exists but with wrong readyState
|
|
3013
|
-
LoggerProxy.logger.warn(
|
|
3119
|
+
LoggerProxy.logger.warn(
|
|
3120
|
+
`Meeting:index#closeLocalShare --> Error: MediaStreamTrack.readyState is ${track.readyState} for localShare`
|
|
3121
|
+
);
|
|
3014
3122
|
}
|
|
3015
3123
|
});
|
|
3016
3124
|
}
|
|
@@ -3052,14 +3160,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3052
3160
|
if (!this.hasWebsocketConnected) {
|
|
3053
3161
|
Metrics.postEvent({
|
|
3054
3162
|
event: eventType.MERCURY_CONNECTION_RESTORED,
|
|
3055
|
-
meeting: this
|
|
3163
|
+
meeting: this,
|
|
3164
|
+
});
|
|
3165
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MERCURY_CONNECTION_RESTORED, {
|
|
3166
|
+
correlation_id: this.correlationId,
|
|
3056
3167
|
});
|
|
3057
|
-
Metrics.sendBehavioralMetric(
|
|
3058
|
-
BEHAVIORAL_METRICS.MERCURY_CONNECTION_RESTORED,
|
|
3059
|
-
{
|
|
3060
|
-
correlation_id: this.correlationId
|
|
3061
|
-
}
|
|
3062
|
-
);
|
|
3063
3168
|
}
|
|
3064
3169
|
this.hasWebsocketConnected = true;
|
|
3065
3170
|
});
|
|
@@ -3069,14 +3174,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3069
3174
|
LoggerProxy.logger.error('Meeting:index#setMercuryListener --> Web socket offline');
|
|
3070
3175
|
Metrics.postEvent({
|
|
3071
3176
|
event: eventType.MERCURY_CONNECTION_LOST,
|
|
3072
|
-
meeting: this
|
|
3177
|
+
meeting: this,
|
|
3178
|
+
});
|
|
3179
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MERCURY_CONNECTION_FAILURE, {
|
|
3180
|
+
correlation_id: this.correlationId,
|
|
3073
3181
|
});
|
|
3074
|
-
Metrics.sendBehavioralMetric(
|
|
3075
|
-
BEHAVIORAL_METRICS.MERCURY_CONNECTION_FAILURE,
|
|
3076
|
-
{
|
|
3077
|
-
correlation_id: this.correlationId
|
|
3078
|
-
}
|
|
3079
|
-
);
|
|
3080
3182
|
});
|
|
3081
3183
|
}
|
|
3082
3184
|
|
|
@@ -3143,32 +3245,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3143
3245
|
const LOG_HEADER = 'Meeting:index#muteAudio -->';
|
|
3144
3246
|
|
|
3145
3247
|
// First, stop sending the local audio media
|
|
3146
|
-
return logRequest(
|
|
3147
|
-
.
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3248
|
+
return logRequest(
|
|
3249
|
+
this.audio
|
|
3250
|
+
.handleClientRequest(this, true)
|
|
3251
|
+
.then(() => {
|
|
3252
|
+
MeetingUtil.handleAudioLogging(this.mediaProperties.audioTrack);
|
|
3253
|
+
Metrics.postEvent({
|
|
3254
|
+
event: eventType.MUTED,
|
|
3255
|
+
meeting: this,
|
|
3256
|
+
data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.AUDIO},
|
|
3257
|
+
});
|
|
3258
|
+
})
|
|
3259
|
+
.catch((error) => {
|
|
3260
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MUTE_AUDIO_FAILURE, {
|
|
3158
3261
|
correlation_id: this.correlationId,
|
|
3159
3262
|
locus_id: this.locusUrl.split('/').pop(),
|
|
3160
3263
|
reason: error.message,
|
|
3161
|
-
stack: error.stack
|
|
3162
|
-
}
|
|
3163
|
-
);
|
|
3264
|
+
stack: error.stack,
|
|
3265
|
+
});
|
|
3164
3266
|
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3267
|
+
throw error;
|
|
3268
|
+
}),
|
|
3269
|
+
{
|
|
3270
|
+
header: `${LOG_HEADER} muting audio`,
|
|
3271
|
+
success: `${LOG_HEADER} muted audio successfully`,
|
|
3272
|
+
failure: `${LOG_HEADER} muting audio failed, `,
|
|
3273
|
+
}
|
|
3274
|
+
);
|
|
3172
3275
|
}
|
|
3173
3276
|
|
|
3174
3277
|
/**
|
|
@@ -3195,33 +3298,34 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3195
3298
|
const LOG_HEADER = 'Meeting:index#unmuteAudio -->';
|
|
3196
3299
|
|
|
3197
3300
|
// First, send the control to unmute the participant on the server
|
|
3198
|
-
return logRequest(
|
|
3199
|
-
.
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3301
|
+
return logRequest(
|
|
3302
|
+
this.audio
|
|
3303
|
+
.handleClientRequest(this, false)
|
|
3304
|
+
.then(() => {
|
|
3305
|
+
MeetingUtil.handleAudioLogging(this.mediaProperties.audioTrack);
|
|
3306
|
+
Metrics.postEvent({
|
|
3307
|
+
event: eventType.UNMUTED,
|
|
3308
|
+
meeting: this,
|
|
3309
|
+
data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.AUDIO},
|
|
3310
|
+
});
|
|
3311
|
+
})
|
|
3312
|
+
.catch((error) => {
|
|
3313
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UNMUTE_AUDIO_FAILURE, {
|
|
3210
3314
|
correlation_id: this.correlationId,
|
|
3211
3315
|
locus_id: this.locusUrl.split('/').pop(),
|
|
3212
3316
|
reason: error.message,
|
|
3213
|
-
stack: error.stack
|
|
3214
|
-
}
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
}
|
|
3317
|
+
stack: error.stack,
|
|
3318
|
+
});
|
|
3319
|
+
|
|
3320
|
+
throw error;
|
|
3321
|
+
}),
|
|
3322
|
+
{
|
|
3323
|
+
header: `${LOG_HEADER} unmuting audio`,
|
|
3324
|
+
success: `${LOG_HEADER} unmuted audio successfully`,
|
|
3325
|
+
failure: `${LOG_HEADER} unmuting audio failed, `,
|
|
3326
|
+
}
|
|
3327
|
+
);
|
|
3328
|
+
}
|
|
3225
3329
|
|
|
3226
3330
|
/**
|
|
3227
3331
|
* Mute the video for a meeting
|
|
@@ -3246,32 +3350,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3246
3350
|
|
|
3247
3351
|
const LOG_HEADER = 'Meeting:index#muteVideo -->';
|
|
3248
3352
|
|
|
3249
|
-
return logRequest(
|
|
3250
|
-
.
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3353
|
+
return logRequest(
|
|
3354
|
+
this.video
|
|
3355
|
+
.handleClientRequest(this, true)
|
|
3356
|
+
.then(() => {
|
|
3357
|
+
MeetingUtil.handleVideoLogging(this.mediaProperties.videoTrack);
|
|
3358
|
+
Metrics.postEvent({
|
|
3359
|
+
event: eventType.MUTED,
|
|
3360
|
+
meeting: this,
|
|
3361
|
+
data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.VIDEO},
|
|
3362
|
+
});
|
|
3363
|
+
})
|
|
3364
|
+
.catch((error) => {
|
|
3365
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MUTE_VIDEO_FAILURE, {
|
|
3261
3366
|
correlation_id: this.correlationId,
|
|
3262
3367
|
locus_id: this.locusUrl.split('/').pop(),
|
|
3263
3368
|
reason: error.message,
|
|
3264
|
-
stack: error.stack
|
|
3265
|
-
}
|
|
3266
|
-
);
|
|
3369
|
+
stack: error.stack,
|
|
3370
|
+
});
|
|
3267
3371
|
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3372
|
+
throw error;
|
|
3373
|
+
}),
|
|
3374
|
+
{
|
|
3375
|
+
header: `${LOG_HEADER} muting video`,
|
|
3376
|
+
success: `${LOG_HEADER} muted video successfully`,
|
|
3377
|
+
failure: `${LOG_HEADER} muting video failed, `,
|
|
3378
|
+
}
|
|
3379
|
+
);
|
|
3275
3380
|
}
|
|
3276
3381
|
|
|
3277
3382
|
/**
|
|
@@ -3297,32 +3402,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3297
3402
|
|
|
3298
3403
|
const LOG_HEADER = 'Meeting:index#unmuteVideo -->';
|
|
3299
3404
|
|
|
3300
|
-
return logRequest(
|
|
3301
|
-
.
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3405
|
+
return logRequest(
|
|
3406
|
+
this.video
|
|
3407
|
+
.handleClientRequest(this, false)
|
|
3408
|
+
.then(() => {
|
|
3409
|
+
MeetingUtil.handleVideoLogging(this.mediaProperties.videoTrack);
|
|
3410
|
+
Metrics.postEvent({
|
|
3411
|
+
event: eventType.UNMUTED,
|
|
3412
|
+
meeting: this,
|
|
3413
|
+
data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.VIDEO},
|
|
3414
|
+
});
|
|
3415
|
+
})
|
|
3416
|
+
.catch((error) => {
|
|
3417
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UNMUTE_VIDEO_FAILURE, {
|
|
3312
3418
|
correlation_id: this.correlationId,
|
|
3313
3419
|
locus_id: this.locusUrl.split('/').pop(),
|
|
3314
3420
|
reason: error.message,
|
|
3315
|
-
stack: error.stack
|
|
3316
|
-
}
|
|
3317
|
-
);
|
|
3421
|
+
stack: error.stack,
|
|
3422
|
+
});
|
|
3318
3423
|
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3424
|
+
throw error;
|
|
3425
|
+
}),
|
|
3426
|
+
{
|
|
3427
|
+
header: `${LOG_HEADER} unmuting video`,
|
|
3428
|
+
success: `${LOG_HEADER} unmuted video successfully`,
|
|
3429
|
+
failure: `${LOG_HEADER} unmuting video failed, `,
|
|
3430
|
+
}
|
|
3431
|
+
);
|
|
3326
3432
|
}
|
|
3327
3433
|
|
|
3328
3434
|
/**
|
|
@@ -3366,12 +3472,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3366
3472
|
this.addMedia({
|
|
3367
3473
|
mediaSettings,
|
|
3368
3474
|
localShare,
|
|
3369
|
-
localStream
|
|
3475
|
+
localStream,
|
|
3370
3476
|
}).then((mediaResponse) => ({
|
|
3371
3477
|
join: joinResponse,
|
|
3372
3478
|
media: mediaResponse,
|
|
3373
|
-
local: [localStream, localShare]
|
|
3374
|
-
}))
|
|
3479
|
+
local: [localStream, localShare],
|
|
3480
|
+
}))
|
|
3481
|
+
)
|
|
3482
|
+
)
|
|
3375
3483
|
.catch((error) => {
|
|
3376
3484
|
LoggerProxy.logger.error('Meeting:index#joinWithMedia --> ', error);
|
|
3377
3485
|
|
|
@@ -3381,10 +3489,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3381
3489
|
correlation_id: this.correlationId,
|
|
3382
3490
|
locus_id: this.locusUrl.split('/').pop(),
|
|
3383
3491
|
reason: error.message,
|
|
3384
|
-
stack: error.stack
|
|
3492
|
+
stack: error.stack,
|
|
3385
3493
|
},
|
|
3386
3494
|
{
|
|
3387
|
-
type: error.name
|
|
3495
|
+
type: error.name,
|
|
3388
3496
|
}
|
|
3389
3497
|
);
|
|
3390
3498
|
|
|
@@ -3401,28 +3509,34 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3401
3509
|
* @memberof Meeting
|
|
3402
3510
|
*/
|
|
3403
3511
|
public reconnect(options?: object) {
|
|
3404
|
-
LoggerProxy.logger.log(
|
|
3512
|
+
LoggerProxy.logger.log(
|
|
3513
|
+
`Meeting:index#reconnect --> attempting to reconnect meeting ${this.id}`
|
|
3514
|
+
);
|
|
3405
3515
|
|
|
3406
3516
|
if (!this.reconnectionManager || !this.reconnectionManager.reconnect) {
|
|
3407
|
-
return Promise.reject(
|
|
3517
|
+
return Promise.reject(
|
|
3518
|
+
new ParameterError('Cannot reconnect, ReconnectionManager must first be defined.')
|
|
3519
|
+
);
|
|
3408
3520
|
}
|
|
3409
3521
|
|
|
3410
3522
|
// @ts-ignore - currentMediaStatus coming from SelfUtil
|
|
3411
3523
|
if (!MeetingUtil.isMediaEstablished(this.currentMediaStatus)) {
|
|
3412
|
-
return Promise.reject(
|
|
3524
|
+
return Promise.reject(
|
|
3525
|
+
new ParameterError('Cannot reconnect, Media has not established to reconnect')
|
|
3526
|
+
);
|
|
3413
3527
|
}
|
|
3414
3528
|
|
|
3415
3529
|
try {
|
|
3416
3530
|
LoggerProxy.logger.info('Meeting:index#reconnect --> Validating reconnect ability.');
|
|
3417
3531
|
// @ts-ignore
|
|
3418
3532
|
this.reconnectionManager.validate();
|
|
3419
|
-
}
|
|
3420
|
-
catch (error) {
|
|
3533
|
+
} catch (error) {
|
|
3421
3534
|
// Unable to reconnect this call
|
|
3422
3535
|
if (error instanceof ReconnectInProgress) {
|
|
3423
|
-
LoggerProxy.logger.info(
|
|
3424
|
-
|
|
3425
|
-
|
|
3536
|
+
LoggerProxy.logger.info(
|
|
3537
|
+
'Meeting:index#reconnect --> Unable to reconnect, reconnection in progress.'
|
|
3538
|
+
);
|
|
3539
|
+
} else {
|
|
3426
3540
|
LoggerProxy.logger.log('Meeting:index#reconnect --> Unable to reconnect.', error);
|
|
3427
3541
|
}
|
|
3428
3542
|
|
|
@@ -3433,7 +3547,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3433
3547
|
this,
|
|
3434
3548
|
{
|
|
3435
3549
|
file: 'meeting/index',
|
|
3436
|
-
function: 'reconnect'
|
|
3550
|
+
function: 'reconnect',
|
|
3437
3551
|
},
|
|
3438
3552
|
EVENT_TRIGGERS.MEETING_RECONNECTION_STARTING
|
|
3439
3553
|
);
|
|
@@ -3445,7 +3559,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3445
3559
|
this,
|
|
3446
3560
|
{
|
|
3447
3561
|
file: 'meeting/index',
|
|
3448
|
-
function: 'reconnect'
|
|
3562
|
+
function: 'reconnect',
|
|
3449
3563
|
},
|
|
3450
3564
|
EVENT_TRIGGERS.MEETING_RECONNECTION_SUCCESS
|
|
3451
3565
|
);
|
|
@@ -3456,29 +3570,26 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3456
3570
|
this,
|
|
3457
3571
|
{
|
|
3458
3572
|
file: 'meeting/index',
|
|
3459
|
-
function: 'reconnect'
|
|
3573
|
+
function: 'reconnect',
|
|
3460
3574
|
},
|
|
3461
3575
|
EVENT_TRIGGERS.MEETING_RECONNECTION_FAILURE,
|
|
3462
3576
|
{
|
|
3463
|
-
error: new ReconnectionError('Reconnection failure event', error)
|
|
3577
|
+
error: new ReconnectionError('Reconnection failure event', error),
|
|
3464
3578
|
}
|
|
3465
3579
|
);
|
|
3466
3580
|
|
|
3467
3581
|
LoggerProxy.logger.error('Meeting:index#reconnect --> Meeting reconnect failed', error);
|
|
3468
3582
|
|
|
3469
|
-
Metrics.sendBehavioralMetric(
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
stack: error.stack
|
|
3476
|
-
}
|
|
3477
|
-
);
|
|
3583
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_RECONNECT_FAILURE, {
|
|
3584
|
+
correlation_id: this.correlationId,
|
|
3585
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
3586
|
+
reason: error.message,
|
|
3587
|
+
stack: error.stack,
|
|
3588
|
+
});
|
|
3478
3589
|
|
|
3479
3590
|
this.uploadLogs({
|
|
3480
3591
|
file: 'meeting/index',
|
|
3481
|
-
function: 'reconnect'
|
|
3592
|
+
function: 'reconnect',
|
|
3482
3593
|
});
|
|
3483
3594
|
|
|
3484
3595
|
return Promise.reject(new ReconnectionError('Reconnection failure event', error));
|
|
@@ -3532,14 +3643,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3532
3643
|
|
|
3533
3644
|
this.triggerStopReceivingTranscriptionEvent();
|
|
3534
3645
|
|
|
3535
|
-
Metrics.sendBehavioralMetric(
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
event
|
|
3541
|
-
}
|
|
3542
|
-
);
|
|
3646
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_FAILURE, {
|
|
3647
|
+
correlation_id: this.correlationId,
|
|
3648
|
+
reason: 'unexpected error: transcription LLM web socket connection error had occured.',
|
|
3649
|
+
event,
|
|
3650
|
+
});
|
|
3543
3651
|
});
|
|
3544
3652
|
}
|
|
3545
3653
|
|
|
@@ -3557,10 +3665,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3557
3665
|
try {
|
|
3558
3666
|
const {datachannelUrl} = this.locusInfo.info;
|
|
3559
3667
|
// @ts-ignore - fix type
|
|
3560
|
-
const {
|
|
3668
|
+
const {
|
|
3669
|
+
body: {webSocketUrl},
|
|
3670
|
+
} = await this.request({
|
|
3561
3671
|
method: HTTP_VERBS.POST,
|
|
3562
3672
|
uri: datachannelUrl,
|
|
3563
|
-
body: {deviceUrl: this.deviceUrl}
|
|
3673
|
+
body: {deviceUrl: this.deviceUrl},
|
|
3564
3674
|
});
|
|
3565
3675
|
|
|
3566
3676
|
LoggerProxy.logger.info(
|
|
@@ -3572,7 +3682,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3572
3682
|
webSocketUrl,
|
|
3573
3683
|
// @ts-ignore - fix type
|
|
3574
3684
|
this.webex.sessionId,
|
|
3575
|
-
this.members
|
|
3685
|
+
this.members
|
|
3576
3686
|
);
|
|
3577
3687
|
|
|
3578
3688
|
LoggerProxy.logger.info(
|
|
@@ -3586,7 +3696,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3586
3696
|
this,
|
|
3587
3697
|
{
|
|
3588
3698
|
file: 'meeting/index',
|
|
3589
|
-
function: 'join'
|
|
3699
|
+
function: 'join',
|
|
3590
3700
|
},
|
|
3591
3701
|
EVENT_TRIGGERS.MEETING_STARTED_RECEIVING_TRANSCRIPTION,
|
|
3592
3702
|
payload
|
|
@@ -3596,17 +3706,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3596
3706
|
this.monitorTranscriptionSocketConnection();
|
|
3597
3707
|
// @ts-ignore - fix type
|
|
3598
3708
|
this.transcription.connect(this.webex.credentials.supertoken.access_token);
|
|
3599
|
-
}
|
|
3600
|
-
catch (error) {
|
|
3709
|
+
} catch (error) {
|
|
3601
3710
|
LoggerProxy.logger.error(`Meeting:index#receiveTranscription --> ${error}`);
|
|
3602
|
-
Metrics.sendBehavioralMetric(
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
stack: error.stack
|
|
3608
|
-
}
|
|
3609
|
-
);
|
|
3711
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_FAILURE, {
|
|
3712
|
+
correlation_id: this.correlationId,
|
|
3713
|
+
reason: error.message,
|
|
3714
|
+
stack: error.stack,
|
|
3715
|
+
});
|
|
3610
3716
|
}
|
|
3611
3717
|
}
|
|
3612
3718
|
|
|
@@ -3636,7 +3742,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3636
3742
|
this,
|
|
3637
3743
|
{
|
|
3638
3744
|
file: 'meeting',
|
|
3639
|
-
function: 'triggerStopReceivingTranscriptionEvent'
|
|
3745
|
+
function: 'triggerStopReceivingTranscriptionEvent',
|
|
3640
3746
|
},
|
|
3641
3747
|
EVENT_TRIGGERS.MEETING_STOPPED_RECEIVING_TRANSCRIPTION
|
|
3642
3748
|
);
|
|
@@ -3683,10 +3789,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3683
3789
|
|
|
3684
3790
|
if (!this.hasJoinedOnce) {
|
|
3685
3791
|
this.hasJoinedOnce = true;
|
|
3686
|
-
}
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3792
|
+
} else {
|
|
3793
|
+
LoggerProxy.logger.log(
|
|
3794
|
+
`Meeting:index#join --> Generating a new correlation id for meeting ${this.id}`
|
|
3795
|
+
);
|
|
3796
|
+
LoggerProxy.logger.log(
|
|
3797
|
+
`Meeting:index#join --> Previous correlation id ${this.correlationId}`
|
|
3798
|
+
);
|
|
3690
3799
|
this.setCorrelationId(uuid.v4());
|
|
3691
3800
|
LoggerProxy.logger.log(`Meeting:index#join --> New correlation id ${this.correlationId}`);
|
|
3692
3801
|
}
|
|
@@ -3698,7 +3807,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3698
3807
|
Metrics.postEvent({
|
|
3699
3808
|
event: eventType.CALL_INITIATED,
|
|
3700
3809
|
meeting: this,
|
|
3701
|
-
data: {trigger: trigger.USER_INTERACTION, isRoapCallEnabled: true}
|
|
3810
|
+
data: {trigger: trigger.USER_INTERACTION, isRoapCallEnabled: true},
|
|
3702
3811
|
});
|
|
3703
3812
|
|
|
3704
3813
|
LoggerProxy.logger.log('Meeting:index#join --> Joining a meeting');
|
|
@@ -3771,15 +3880,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3771
3880
|
.then((join) => {
|
|
3772
3881
|
joinSuccess(join);
|
|
3773
3882
|
this.deferJoin = undefined;
|
|
3774
|
-
Metrics.sendBehavioralMetric(
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
correlation_id: this.correlationId
|
|
3778
|
-
}
|
|
3779
|
-
);
|
|
3883
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
|
|
3884
|
+
correlation_id: this.correlationId,
|
|
3885
|
+
});
|
|
3780
3886
|
|
|
3781
3887
|
return join;
|
|
3782
|
-
})
|
|
3888
|
+
})
|
|
3889
|
+
.then(async (join) => {
|
|
3783
3890
|
if (isBrowser) {
|
|
3784
3891
|
// @ts-ignore - config coming from registerPlugin
|
|
3785
3892
|
if (this.config.receiveTranscription || options.receiveTranscription) {
|
|
@@ -3788,9 +3895,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3788
3895
|
LoggerProxy.logger.info('Meeting:index#join --> enabled to recieve transcription!');
|
|
3789
3896
|
}
|
|
3790
3897
|
}
|
|
3791
|
-
}
|
|
3792
|
-
|
|
3793
|
-
|
|
3898
|
+
} else {
|
|
3899
|
+
LoggerProxy.logger.error(
|
|
3900
|
+
'Meeting:index#join --> Receving transcription is not supported on this platform'
|
|
3901
|
+
);
|
|
3794
3902
|
}
|
|
3795
3903
|
|
|
3796
3904
|
return join;
|
|
@@ -3804,28 +3912,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3804
3912
|
meeting: this,
|
|
3805
3913
|
meetingId: this.id,
|
|
3806
3914
|
data: {
|
|
3807
|
-
errors: [
|
|
3808
|
-
|
|
3809
|
-
]
|
|
3810
|
-
}
|
|
3915
|
+
errors: [Metrics.parseLocusError(error.error, true)],
|
|
3916
|
+
},
|
|
3811
3917
|
});
|
|
3812
3918
|
|
|
3813
3919
|
// TODO: change this to error codes and pre defined dictionary
|
|
3814
|
-
Metrics.sendBehavioralMetric(
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
stack: error.stack
|
|
3820
|
-
}
|
|
3821
|
-
);
|
|
3920
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_FAILURE, {
|
|
3921
|
+
correlation_id: this.correlationId,
|
|
3922
|
+
reason: error.error?.message,
|
|
3923
|
+
stack: error.stack,
|
|
3924
|
+
});
|
|
3822
3925
|
|
|
3823
3926
|
// Upload logs on join Failure
|
|
3824
3927
|
Trigger.trigger(
|
|
3825
3928
|
this,
|
|
3826
3929
|
{
|
|
3827
3930
|
file: 'meeting/index',
|
|
3828
|
-
function: 'join'
|
|
3931
|
+
function: 'join',
|
|
3829
3932
|
},
|
|
3830
3933
|
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
3831
3934
|
this
|
|
@@ -3877,28 +3980,28 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3877
3980
|
|
|
3878
3981
|
if (!this.dialInUrl) this.dialInUrl = `dialin:///${uuid.v4()}`;
|
|
3879
3982
|
|
|
3880
|
-
return this.meetingRequest
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3983
|
+
return this.meetingRequest
|
|
3984
|
+
.dialIn({
|
|
3985
|
+
correlationId,
|
|
3986
|
+
dialInUrl: this.dialInUrl,
|
|
3987
|
+
locusUrl,
|
|
3988
|
+
clientUrl: this.deviceUrl,
|
|
3989
|
+
})
|
|
3990
|
+
.then((res) => {
|
|
3991
|
+
this.locusInfo.onFullLocus(res.body.locus);
|
|
3992
|
+
})
|
|
3993
|
+
.catch((error) => {
|
|
3994
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE, {
|
|
3891
3995
|
correlation_id: this.correlationId,
|
|
3892
3996
|
dial_in_url: this.dialInUrl,
|
|
3893
3997
|
locus_id: locusUrl.split('/').pop(),
|
|
3894
3998
|
client_url: this.deviceUrl,
|
|
3895
3999
|
reason: error.error?.message,
|
|
3896
|
-
stack: error.stack
|
|
3897
|
-
}
|
|
3898
|
-
);
|
|
4000
|
+
stack: error.stack,
|
|
4001
|
+
});
|
|
3899
4002
|
|
|
3900
|
-
|
|
3901
|
-
|
|
4003
|
+
return Promise.reject(error);
|
|
4004
|
+
});
|
|
3902
4005
|
}
|
|
3903
4006
|
|
|
3904
4007
|
/**
|
|
@@ -3915,29 +4018,29 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3915
4018
|
|
|
3916
4019
|
if (!this.dialOutUrl) this.dialOutUrl = `dialout:///${uuid.v4()}`;
|
|
3917
4020
|
|
|
3918
|
-
return this.meetingRequest
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
4021
|
+
return this.meetingRequest
|
|
4022
|
+
.dialOut({
|
|
4023
|
+
correlationId,
|
|
4024
|
+
dialOutUrl: this.dialOutUrl,
|
|
4025
|
+
phoneNumber,
|
|
4026
|
+
locusUrl,
|
|
4027
|
+
clientUrl: this.deviceUrl,
|
|
4028
|
+
})
|
|
4029
|
+
.then((res) => {
|
|
4030
|
+
this.locusInfo.onFullLocus(res.body.locus);
|
|
4031
|
+
})
|
|
4032
|
+
.catch((error) => {
|
|
4033
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE, {
|
|
3930
4034
|
correlation_id: this.correlationId,
|
|
3931
4035
|
dial_out_url: this.dialOutUrl,
|
|
3932
4036
|
locus_id: locusUrl.split('/').pop(),
|
|
3933
4037
|
client_url: this.deviceUrl,
|
|
3934
4038
|
reason: error.error?.message,
|
|
3935
|
-
stack: error.stack
|
|
3936
|
-
}
|
|
3937
|
-
);
|
|
4039
|
+
stack: error.stack,
|
|
4040
|
+
});
|
|
3938
4041
|
|
|
3939
|
-
|
|
3940
|
-
|
|
4042
|
+
return Promise.reject(error);
|
|
4043
|
+
});
|
|
3941
4044
|
}
|
|
3942
4045
|
|
|
3943
4046
|
/**
|
|
@@ -3949,12 +4052,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3949
4052
|
*/
|
|
3950
4053
|
public disconnectPhoneAudio() {
|
|
3951
4054
|
return Promise.all([
|
|
3952
|
-
this.isPhoneProvisioned(this.dialInDeviceStatus)
|
|
3953
|
-
MeetingUtil.disconnectPhoneAudio(this, this.dialInUrl)
|
|
3954
|
-
Promise.resolve(),
|
|
3955
|
-
this.isPhoneProvisioned(this.dialOutDeviceStatus)
|
|
3956
|
-
MeetingUtil.disconnectPhoneAudio(this, this.dialOutUrl)
|
|
3957
|
-
Promise.resolve()
|
|
4055
|
+
this.isPhoneProvisioned(this.dialInDeviceStatus)
|
|
4056
|
+
? MeetingUtil.disconnectPhoneAudio(this, this.dialInUrl)
|
|
4057
|
+
: Promise.resolve(),
|
|
4058
|
+
this.isPhoneProvisioned(this.dialOutDeviceStatus)
|
|
4059
|
+
? MeetingUtil.disconnectPhoneAudio(this, this.dialOutUrl)
|
|
4060
|
+
: Promise.resolve(),
|
|
3958
4061
|
]);
|
|
3959
4062
|
}
|
|
3960
4063
|
|
|
@@ -3980,17 +4083,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3980
4083
|
share: true,
|
|
3981
4084
|
share_audio: false,
|
|
3982
4085
|
video: false,
|
|
3983
|
-
whiteboard: false
|
|
4086
|
+
whiteboard: false,
|
|
3984
4087
|
},
|
|
3985
4088
|
tx: {
|
|
3986
4089
|
audio: false,
|
|
3987
4090
|
share: false,
|
|
3988
4091
|
share_audio: false,
|
|
3989
4092
|
video: false,
|
|
3990
|
-
whiteboard: false
|
|
3991
|
-
}
|
|
3992
|
-
}
|
|
3993
|
-
}
|
|
4093
|
+
whiteboard: false,
|
|
4094
|
+
},
|
|
4095
|
+
},
|
|
4096
|
+
},
|
|
3994
4097
|
});
|
|
3995
4098
|
|
|
3996
4099
|
Metrics.postEvent({event: eventType.MOVE_MEDIA, meeting: this});
|
|
@@ -4009,8 +4112,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4009
4112
|
sendAudio: false,
|
|
4010
4113
|
receiveAudio: false,
|
|
4011
4114
|
sendShare: false,
|
|
4012
|
-
receiveShare: true
|
|
4013
|
-
}
|
|
4115
|
+
receiveShare: true,
|
|
4116
|
+
},
|
|
4014
4117
|
};
|
|
4015
4118
|
|
|
4016
4119
|
// clean up the local tracks
|
|
@@ -4022,50 +4125,44 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4022
4125
|
|
|
4023
4126
|
this.mediaProperties.unsetMediaTracks();
|
|
4024
4127
|
|
|
4025
|
-
|
|
4026
4128
|
// when a move to is intiated by the client , Locus delets the existing media node from the server as soon the DX answers the meeting
|
|
4027
4129
|
// once the DX answers we establish connection back the media server with only receiveShare enabled
|
|
4028
4130
|
// @ts-ignore - reconnectMedia does not accept any argument
|
|
4029
|
-
await this.reconnectionManager.reconnectMedia(mediaSettings)
|
|
4030
|
-
.
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
);
|
|
4034
|
-
});
|
|
4035
|
-
}
|
|
4036
|
-
catch (error) {
|
|
4131
|
+
await this.reconnectionManager.reconnectMedia(mediaSettings).then(() => {
|
|
4132
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_TO_SUCCESS);
|
|
4133
|
+
});
|
|
4134
|
+
} catch (error) {
|
|
4037
4135
|
LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
|
|
4038
|
-
Metrics.sendBehavioralMetric(
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
stack: error.stack
|
|
4045
|
-
}
|
|
4046
|
-
);
|
|
4136
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_TO_FAILURE, {
|
|
4137
|
+
correlation_id: this.correlationId,
|
|
4138
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
4139
|
+
reason: error.message,
|
|
4140
|
+
stack: error.stack,
|
|
4141
|
+
});
|
|
4047
4142
|
}
|
|
4048
4143
|
});
|
|
4049
4144
|
|
|
4050
|
-
LoggerProxy.logger.info(
|
|
4145
|
+
LoggerProxy.logger.info(
|
|
4146
|
+
'Meeting:index#moveTo --> Initated moved to using resourceId',
|
|
4147
|
+
resourceId
|
|
4148
|
+
);
|
|
4051
4149
|
|
|
4052
|
-
return MeetingUtil.joinMeetingOptions(this, {resourceId, moveToResource: true})
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
{
|
|
4150
|
+
return MeetingUtil.joinMeetingOptions(this, {resourceId, moveToResource: true})
|
|
4151
|
+
.then(() => {
|
|
4152
|
+
this.meetingFiniteStateMachine.join();
|
|
4153
|
+
})
|
|
4154
|
+
.catch((error) => {
|
|
4155
|
+
this.meetingFiniteStateMachine.fail(error);
|
|
4156
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_TO_FAILURE, {
|
|
4059
4157
|
correlation_id: this.correlationId,
|
|
4060
4158
|
locus_id: this.locusUrl.split('/').pop(),
|
|
4061
4159
|
reason: error.message,
|
|
4062
|
-
stack: error.stack
|
|
4063
|
-
}
|
|
4064
|
-
|
|
4065
|
-
LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
|
|
4160
|
+
stack: error.stack,
|
|
4161
|
+
});
|
|
4162
|
+
LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
|
|
4066
4163
|
|
|
4067
|
-
|
|
4068
|
-
|
|
4164
|
+
return Promise.reject(error);
|
|
4165
|
+
});
|
|
4069
4166
|
}
|
|
4070
4167
|
|
|
4071
4168
|
/**
|
|
@@ -4085,26 +4182,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4085
4182
|
Metrics.postEvent({event: eventType.MOVE_MEDIA, meeting: this});
|
|
4086
4183
|
|
|
4087
4184
|
return MeetingUtil.joinMeetingOptions(this)
|
|
4088
|
-
.then(() =>
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS
|
|
4096
|
-
)
|
|
4097
|
-
|
|
4185
|
+
.then(() =>
|
|
4186
|
+
MeetingUtil.leaveMeeting(this, {
|
|
4187
|
+
resourceId,
|
|
4188
|
+
correlationId: oldCorrelationId,
|
|
4189
|
+
moveMeeting: true,
|
|
4190
|
+
}).then(() => {
|
|
4191
|
+
this.resourceId = '';
|
|
4192
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS);
|
|
4193
|
+
})
|
|
4194
|
+
)
|
|
4195
|
+
.catch((error) => {
|
|
4098
4196
|
this.meetingFiniteStateMachine.fail(error);
|
|
4099
|
-
Metrics.sendBehavioralMetric(
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
stack: error.stack
|
|
4106
|
-
}
|
|
4107
|
-
);
|
|
4197
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_FROM_FAILURE, {
|
|
4198
|
+
correlation_id: this.correlationId,
|
|
4199
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
4200
|
+
reason: error.message,
|
|
4201
|
+
stack: error.stack,
|
|
4202
|
+
});
|
|
4108
4203
|
LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
|
|
4109
4204
|
|
|
4110
4205
|
return Promise.reject(error);
|
|
@@ -4124,55 +4219,63 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4124
4219
|
getMediaStreams = (
|
|
4125
4220
|
mediaDirection: any,
|
|
4126
4221
|
// This return an OBJECT {video: {height, widght}}
|
|
4222
|
+
// eslint-disable-next-line default-param-last
|
|
4127
4223
|
audioVideo: any = VIDEO_RESOLUTIONS[this.mediaProperties.localQualityLevel],
|
|
4128
4224
|
sharePreferences?: any
|
|
4129
4225
|
) => {
|
|
4130
4226
|
if (
|
|
4131
4227
|
mediaDirection &&
|
|
4132
|
-
(
|
|
4133
|
-
mediaDirection.sendAudio ||
|
|
4134
|
-
mediaDirection.sendVideo ||
|
|
4135
|
-
mediaDirection.sendShare
|
|
4136
|
-
)
|
|
4228
|
+
(mediaDirection.sendAudio || mediaDirection.sendVideo || mediaDirection.sendShare)
|
|
4137
4229
|
) {
|
|
4138
|
-
if (
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
) &&
|
|
4230
|
+
if (
|
|
4231
|
+
mediaDirection &&
|
|
4232
|
+
mediaDirection.sendAudio &&
|
|
4233
|
+
mediaDirection.sendVideo &&
|
|
4234
|
+
mediaDirection.sendShare &&
|
|
4144
4235
|
isBrowser('safari')
|
|
4145
4236
|
) {
|
|
4146
|
-
LoggerProxy.logger.warn(
|
|
4237
|
+
LoggerProxy.logger.warn(
|
|
4238
|
+
'Meeting:index#getMediaStreams --> Setting `sendShare` to FALSE, due to complications with Safari'
|
|
4239
|
+
);
|
|
4147
4240
|
|
|
4148
4241
|
mediaDirection.sendShare = false;
|
|
4149
4242
|
|
|
4150
|
-
LoggerProxy.logger.warn(
|
|
4151
|
-
|
|
4243
|
+
LoggerProxy.logger.warn(
|
|
4244
|
+
'Meeting:index#getMediaStreams --> Enabling `sendShare` along with `sendAudio` & `sendVideo`, on Safari, causes a failure while setting up a screen share at the same time as the camera+mic stream'
|
|
4245
|
+
);
|
|
4246
|
+
LoggerProxy.logger.warn(
|
|
4247
|
+
'Meeting:index#getMediaStreams --> Please use `meeting.shareScreen()` to manually start the screen share after successfully joining the meeting'
|
|
4248
|
+
);
|
|
4152
4249
|
}
|
|
4153
4250
|
|
|
4154
4251
|
if (audioVideo && isString(audioVideo)) {
|
|
4155
4252
|
if (Object.keys(VIDEO_RESOLUTIONS).includes(audioVideo)) {
|
|
4156
4253
|
this.mediaProperties.setLocalQualityLevel(audioVideo);
|
|
4157
4254
|
audioVideo = {video: VIDEO_RESOLUTIONS[audioVideo].video};
|
|
4158
|
-
}
|
|
4159
|
-
|
|
4160
|
-
|
|
4255
|
+
} else {
|
|
4256
|
+
throw new ParameterError(
|
|
4257
|
+
`${audioVideo} not supported. Either pass level from pre-defined resolutions or pass complete audioVideo object`
|
|
4258
|
+
);
|
|
4161
4259
|
}
|
|
4162
4260
|
}
|
|
4163
4261
|
|
|
4164
4262
|
if (!audioVideo.video) {
|
|
4165
|
-
audioVideo = {
|
|
4263
|
+
audioVideo = {
|
|
4264
|
+
...audioVideo,
|
|
4265
|
+
video: {
|
|
4266
|
+
...audioVideo.video,
|
|
4267
|
+
...VIDEO_RESOLUTIONS[this.mediaProperties.localQualityLevel].video,
|
|
4268
|
+
},
|
|
4269
|
+
};
|
|
4166
4270
|
}
|
|
4167
4271
|
// extract deviceId if exists otherwise default to null.
|
|
4168
|
-
const {deviceId: preferredVideoDevice} = (audioVideo && audioVideo.video || {deviceId: null}
|
|
4272
|
+
const {deviceId: preferredVideoDevice} = (audioVideo && audioVideo.video) || {deviceId: null};
|
|
4169
4273
|
const lastVideoDeviceId = this.mediaProperties.getVideoDeviceId();
|
|
4170
4274
|
|
|
4171
4275
|
if (preferredVideoDevice) {
|
|
4172
4276
|
// Store new preferred video input device
|
|
4173
4277
|
this.mediaProperties.setVideoDeviceId(preferredVideoDevice);
|
|
4174
|
-
}
|
|
4175
|
-
else if (lastVideoDeviceId) {
|
|
4278
|
+
} else if (lastVideoDeviceId) {
|
|
4176
4279
|
// no new video preference specified so use last stored value,
|
|
4177
4280
|
// works with empty object {} or media constraint.
|
|
4178
4281
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -4180,50 +4283,55 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4180
4283
|
...audioVideo,
|
|
4181
4284
|
video: {
|
|
4182
4285
|
...audioVideo.video,
|
|
4183
|
-
deviceId: lastVideoDeviceId
|
|
4184
|
-
}
|
|
4286
|
+
deviceId: lastVideoDeviceId,
|
|
4287
|
+
},
|
|
4185
4288
|
};
|
|
4186
4289
|
}
|
|
4187
4290
|
|
|
4188
4291
|
return Media.getSupportedDevice({
|
|
4189
4292
|
sendAudio: mediaDirection.sendAudio,
|
|
4190
|
-
sendVideo: mediaDirection.sendVideo
|
|
4293
|
+
sendVideo: mediaDirection.sendVideo,
|
|
4191
4294
|
})
|
|
4192
|
-
.catch((error) =>
|
|
4193
|
-
|
|
4194
|
-
|
|
4295
|
+
.catch((error) =>
|
|
4296
|
+
Promise.reject(
|
|
4297
|
+
new MediaError(
|
|
4298
|
+
'Given constraints do not match permission set for either camera or microphone',
|
|
4299
|
+
error
|
|
4300
|
+
)
|
|
4301
|
+
)
|
|
4302
|
+
)
|
|
4195
4303
|
.then((devicePermissions) =>
|
|
4196
4304
|
Media.getUserMedia(
|
|
4197
4305
|
{
|
|
4198
4306
|
...mediaDirection,
|
|
4199
4307
|
sendAudio: devicePermissions.sendAudio,
|
|
4200
4308
|
sendVideo: devicePermissions.sendVideo,
|
|
4201
|
-
isSharing: this.shareStatus === SHARE_STATUS.LOCAL_SHARE_ACTIVE
|
|
4309
|
+
isSharing: this.shareStatus === SHARE_STATUS.LOCAL_SHARE_ACTIVE,
|
|
4202
4310
|
},
|
|
4203
4311
|
audioVideo,
|
|
4204
4312
|
sharePreferences,
|
|
4205
4313
|
// @ts-ignore - config coming from registerPlugin
|
|
4206
4314
|
this.config
|
|
4207
|
-
)
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4315
|
+
).catch((error) => {
|
|
4316
|
+
// Whenever there is a failure when trying to access a user's device
|
|
4317
|
+
// report it as an Behavioral metric
|
|
4318
|
+
// This gives visibility into common errors and can help
|
|
4319
|
+
// with further troubleshooting
|
|
4320
|
+
const metricName = BEHAVIORAL_METRICS.GET_USER_MEDIA_FAILURE;
|
|
4321
|
+
const data = {
|
|
4322
|
+
correlation_id: this.correlationId,
|
|
4323
|
+
locus_id: this.locusUrl?.split('/').pop(),
|
|
4324
|
+
reason: error.message,
|
|
4325
|
+
stack: error.stack,
|
|
4326
|
+
};
|
|
4327
|
+
const metadata = {
|
|
4328
|
+
type: error.name,
|
|
4329
|
+
};
|
|
4330
|
+
|
|
4331
|
+
Metrics.sendBehavioralMetric(metricName, data, metadata);
|
|
4332
|
+
throw new MediaError('Unable to retrieve media streams', error);
|
|
4333
|
+
})
|
|
4334
|
+
);
|
|
4227
4335
|
}
|
|
4228
4336
|
|
|
4229
4337
|
return Promise.reject(
|
|
@@ -4231,7 +4339,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4231
4339
|
);
|
|
4232
4340
|
};
|
|
4233
4341
|
|
|
4234
|
-
|
|
4235
4342
|
/**
|
|
4236
4343
|
* Checks if the machine has at least one audio or video device
|
|
4237
4344
|
* @param {Object} options
|
|
@@ -4240,7 +4347,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4240
4347
|
* @returns {Object}
|
|
4241
4348
|
* @memberof Meetings
|
|
4242
4349
|
*/
|
|
4243
|
-
getSupportedDevices = ({
|
|
4350
|
+
getSupportedDevices = ({
|
|
4351
|
+
sendAudio = true,
|
|
4352
|
+
sendVideo = true,
|
|
4353
|
+
}: {
|
|
4354
|
+
sendAudio: boolean;
|
|
4355
|
+
sendVideo: boolean;
|
|
4356
|
+
}) => Media.getSupportedDevice({sendAudio, sendVideo});
|
|
4244
4357
|
|
|
4245
4358
|
/**
|
|
4246
4359
|
* Get the devices from the Media module
|
|
@@ -4260,15 +4373,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4260
4373
|
// TODO: might have to send the same event to the developer
|
|
4261
4374
|
// Add ip address info if geo hint is present
|
|
4262
4375
|
// @ts-ignore fix type
|
|
4263
|
-
options.data.intervalMetadata.peerReflexiveIP =
|
|
4264
|
-
|
|
4376
|
+
options.data.intervalMetadata.peerReflexiveIP =
|
|
4377
|
+
this.webex.meetings.geoHintInfo?.clientAddress ||
|
|
4378
|
+
options.data.intervalMetadata.peerReflexiveIP ||
|
|
4379
|
+
MQA_STATS.DEFAULT_IP;
|
|
4380
|
+
Metrics.postEvent({
|
|
4381
|
+
event: eventType.MEDIA_QUALITY,
|
|
4382
|
+
meeting: this,
|
|
4383
|
+
data: {intervalData: options.data, networkType: options.networkType},
|
|
4384
|
+
});
|
|
4265
4385
|
});
|
|
4266
4386
|
this.statsAnalyzer.on(StatsAnalyzerEvents.LOCAL_MEDIA_STARTED, (data) => {
|
|
4267
4387
|
Trigger.trigger(
|
|
4268
4388
|
this,
|
|
4269
4389
|
{
|
|
4270
4390
|
file: 'meeting/index',
|
|
4271
|
-
function: 'addMedia'
|
|
4391
|
+
function: 'addMedia',
|
|
4272
4392
|
},
|
|
4273
4393
|
EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
|
|
4274
4394
|
data
|
|
@@ -4277,8 +4397,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4277
4397
|
event: eventType.SENDING_MEDIA_START,
|
|
4278
4398
|
meeting: this,
|
|
4279
4399
|
data: {
|
|
4280
|
-
mediaType: data.type
|
|
4281
|
-
}
|
|
4400
|
+
mediaType: data.type,
|
|
4401
|
+
},
|
|
4282
4402
|
});
|
|
4283
4403
|
});
|
|
4284
4404
|
this.statsAnalyzer.on(StatsAnalyzerEvents.LOCAL_MEDIA_STOPPED, (data) => {
|
|
@@ -4286,8 +4406,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4286
4406
|
event: eventType.SENDING_MEDIA_STOP,
|
|
4287
4407
|
meeting: this,
|
|
4288
4408
|
data: {
|
|
4289
|
-
mediaType: data.type
|
|
4290
|
-
}
|
|
4409
|
+
mediaType: data.type,
|
|
4410
|
+
},
|
|
4291
4411
|
});
|
|
4292
4412
|
});
|
|
4293
4413
|
this.statsAnalyzer.on(StatsAnalyzerEvents.REMOTE_MEDIA_STARTED, (data) => {
|
|
@@ -4295,7 +4415,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4295
4415
|
this,
|
|
4296
4416
|
{
|
|
4297
4417
|
file: 'meeting/index',
|
|
4298
|
-
function: 'addMedia'
|
|
4418
|
+
function: 'addMedia',
|
|
4299
4419
|
},
|
|
4300
4420
|
EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
|
|
4301
4421
|
data
|
|
@@ -4304,8 +4424,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4304
4424
|
event: eventType.RECEIVING_MEDIA_START,
|
|
4305
4425
|
meeting: this,
|
|
4306
4426
|
data: {
|
|
4307
|
-
mediaType: data.type
|
|
4308
|
-
}
|
|
4427
|
+
mediaType: data.type,
|
|
4428
|
+
},
|
|
4309
4429
|
});
|
|
4310
4430
|
});
|
|
4311
4431
|
this.statsAnalyzer.on(StatsAnalyzerEvents.REMOTE_MEDIA_STOPPED, (data) => {
|
|
@@ -4313,8 +4433,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4313
4433
|
event: eventType.RECEIVING_MEDIA_STOP,
|
|
4314
4434
|
meeting: this,
|
|
4315
4435
|
data: {
|
|
4316
|
-
mediaType: data.type
|
|
4317
|
-
}
|
|
4436
|
+
mediaType: data.type,
|
|
4437
|
+
},
|
|
4318
4438
|
});
|
|
4319
4439
|
});
|
|
4320
4440
|
};
|
|
@@ -4363,17 +4483,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4363
4483
|
share: false,
|
|
4364
4484
|
share_audio: false,
|
|
4365
4485
|
video: false,
|
|
4366
|
-
whiteboard: false
|
|
4486
|
+
whiteboard: false,
|
|
4367
4487
|
},
|
|
4368
4488
|
tx: {
|
|
4369
4489
|
audio: false,
|
|
4370
4490
|
share: false,
|
|
4371
4491
|
share_audio: false,
|
|
4372
4492
|
video: false,
|
|
4373
|
-
whiteboard: false
|
|
4374
|
-
}
|
|
4375
|
-
}
|
|
4376
|
-
}
|
|
4493
|
+
whiteboard: false,
|
|
4494
|
+
},
|
|
4495
|
+
},
|
|
4496
|
+
},
|
|
4377
4497
|
});
|
|
4378
4498
|
|
|
4379
4499
|
return MeetingUtil.validateOptions(options)
|
|
@@ -4390,20 +4510,25 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4390
4510
|
|
|
4391
4511
|
return this.preMedia(localStream, localShare, mediaSettings);
|
|
4392
4512
|
})
|
|
4393
|
-
.then(() =>
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4513
|
+
.then(() =>
|
|
4514
|
+
Media.attachMedia(this.mediaProperties, {
|
|
4515
|
+
meetingId: this.id,
|
|
4516
|
+
remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
|
|
4517
|
+
// @ts-ignore - config coming from registerPlugin
|
|
4518
|
+
enableRtx: this.config.enableRtx,
|
|
4519
|
+
// @ts-ignore - config coming from registerPlugin
|
|
4520
|
+
enableExtmap: this.config.enableExtmap,
|
|
4521
|
+
setStartLocalSDPGenRemoteSDPRecvDelay:
|
|
4522
|
+
this.setStartLocalSDPGenRemoteSDPRecvDelay.bind(this),
|
|
4523
|
+
})
|
|
4524
|
+
)
|
|
4525
|
+
.then((peerConnection) =>
|
|
4526
|
+
this.getDevices().then((devices) => {
|
|
4527
|
+
MeetingUtil.handleDeviceLogging(devices);
|
|
4528
|
+
|
|
4529
|
+
return peerConnection;
|
|
4530
|
+
})
|
|
4531
|
+
)
|
|
4407
4532
|
.then((peerConnection) => {
|
|
4408
4533
|
this.handleMediaLogging(this.mediaProperties);
|
|
4409
4534
|
LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection Received from attachMedia `);
|
|
@@ -4417,63 +4542,71 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4417
4542
|
// @ts-ignore - config coming from registerPlugin
|
|
4418
4543
|
this.statsAnalyzer = new StatsAnalyzer(this.config.stats, this.networkQualityMonitor);
|
|
4419
4544
|
this.setupStatsAnalyzerEventHandlers();
|
|
4420
|
-
this.networkQualityMonitor.on(
|
|
4545
|
+
this.networkQualityMonitor.on(
|
|
4546
|
+
EVENT_TRIGGERS.NETWORK_QUALITY,
|
|
4547
|
+
this.sendNetworkQualityEvent.bind(this)
|
|
4548
|
+
);
|
|
4421
4549
|
}
|
|
4422
4550
|
})
|
|
4423
4551
|
.catch((error) => {
|
|
4424
|
-
LoggerProxy.logger.error(
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
|
|
4428
|
-
{
|
|
4429
|
-
correlation_id: this.correlationId,
|
|
4430
|
-
locus_id: this.locusUrl.split('/').pop(),
|
|
4431
|
-
reason: error.message,
|
|
4432
|
-
stack: error.stack,
|
|
4433
|
-
turnDiscoverySkippedReason,
|
|
4434
|
-
turnServerUsed
|
|
4435
|
-
}
|
|
4552
|
+
LoggerProxy.logger.error(
|
|
4553
|
+
`${LOG_HEADER} Error adding media , setting up peerconnection, `,
|
|
4554
|
+
error
|
|
4436
4555
|
);
|
|
4437
4556
|
|
|
4557
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE, {
|
|
4558
|
+
correlation_id: this.correlationId,
|
|
4559
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
4560
|
+
reason: error.message,
|
|
4561
|
+
stack: error.stack,
|
|
4562
|
+
turnDiscoverySkippedReason,
|
|
4563
|
+
turnServerUsed,
|
|
4564
|
+
});
|
|
4565
|
+
|
|
4438
4566
|
throw error;
|
|
4439
4567
|
})
|
|
4440
|
-
.then(
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4568
|
+
.then(
|
|
4569
|
+
() =>
|
|
4570
|
+
new Promise<void>((resolve, reject) => {
|
|
4571
|
+
let timerCount = 0;
|
|
4572
|
+
|
|
4573
|
+
// eslint-disable-next-line func-names
|
|
4574
|
+
// eslint-disable-next-line prefer-arrow-callback
|
|
4575
|
+
if (this.type === _CALL_) {
|
|
4576
|
+
resolve();
|
|
4577
|
+
}
|
|
4578
|
+
const joiningTimer = setInterval(() => {
|
|
4579
|
+
timerCount += 1;
|
|
4580
|
+
if (this.meetingState === FULL_STATE.ACTIVE) {
|
|
4581
|
+
clearInterval(joiningTimer);
|
|
4582
|
+
resolve();
|
|
4583
|
+
}
|
|
4454
4584
|
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4585
|
+
if (timerCount === 4) {
|
|
4586
|
+
clearInterval(joiningTimer);
|
|
4587
|
+
reject(new Error('Meeting is still not active '));
|
|
4588
|
+
}
|
|
4589
|
+
}, 1000);
|
|
4590
|
+
})
|
|
4591
|
+
)
|
|
4461
4592
|
.then(() =>
|
|
4462
|
-
logRequest(
|
|
4463
|
-
.sendRoapMediaRequest({
|
|
4593
|
+
logRequest(
|
|
4594
|
+
this.roap.sendRoapMediaRequest({
|
|
4464
4595
|
sdp: this.mediaProperties.peerConnection.sdp,
|
|
4465
4596
|
roapSeq: this.roapSeq,
|
|
4466
|
-
meeting: this // or can pass meeting ID
|
|
4467
|
-
}),
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4597
|
+
meeting: this, // or can pass meeting ID
|
|
4598
|
+
}),
|
|
4599
|
+
{
|
|
4600
|
+
header: `${LOG_HEADER} Send Roap Media Request.`,
|
|
4601
|
+
success: `${LOG_HEADER} Successfully send roap media request`,
|
|
4602
|
+
failure: `${LOG_HEADER} Error joining the call on send roap media request, `,
|
|
4603
|
+
}
|
|
4604
|
+
)
|
|
4605
|
+
)
|
|
4606
|
+
.then(() =>
|
|
4607
|
+
this.mediaProperties.waitForIceConnectedState().catch(() => {
|
|
4608
|
+
throw createMeetingsError(30202, 'Meeting connection failed');
|
|
4609
|
+
})
|
|
4477
4610
|
)
|
|
4478
4611
|
.then(() => {
|
|
4479
4612
|
LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection CONNECTED`);
|
|
@@ -4491,63 +4624,61 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4491
4624
|
})
|
|
4492
4625
|
.then(() => this.mediaProperties.getCurrentConnectionType())
|
|
4493
4626
|
.then((connectionType) => {
|
|
4494
|
-
Metrics.sendBehavioralMetric(
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
connectionType
|
|
4500
|
-
}
|
|
4501
|
-
);
|
|
4627
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
|
|
4628
|
+
correlation_id: this.correlationId,
|
|
4629
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
4630
|
+
connectionType,
|
|
4631
|
+
});
|
|
4502
4632
|
})
|
|
4503
4633
|
.catch((error) => {
|
|
4504
4634
|
// Clean up stats analyzer, peer connection, and turn off listeners
|
|
4505
|
-
const stopStatsAnalyzer =
|
|
4635
|
+
const stopStatsAnalyzer = this.statsAnalyzer
|
|
4636
|
+
? this.statsAnalyzer.stopAnalyzer()
|
|
4637
|
+
: Promise.resolve();
|
|
4506
4638
|
|
|
4507
|
-
return stopStatsAnalyzer
|
|
4508
|
-
.
|
|
4509
|
-
this.statsAnalyzer = null;
|
|
4639
|
+
return stopStatsAnalyzer.then(() => {
|
|
4640
|
+
this.statsAnalyzer = null;
|
|
4510
4641
|
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4642
|
+
if (this.mediaProperties.peerConnection) {
|
|
4643
|
+
this.closePeerConnections();
|
|
4644
|
+
this.unsetPeerConnections();
|
|
4645
|
+
}
|
|
4515
4646
|
|
|
4516
|
-
|
|
4647
|
+
LoggerProxy.logger.error(
|
|
4648
|
+
`${LOG_HEADER} Error adding media failed to initiate PC and send request, `,
|
|
4649
|
+
error
|
|
4650
|
+
);
|
|
4517
4651
|
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
turnServerUsed
|
|
4528
|
-
}
|
|
4529
|
-
);
|
|
4652
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE, {
|
|
4653
|
+
correlation_id: this.correlationId,
|
|
4654
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
4655
|
+
reason: error.message,
|
|
4656
|
+
stack: error.stack,
|
|
4657
|
+
code: error.code,
|
|
4658
|
+
turnDiscoverySkippedReason,
|
|
4659
|
+
turnServerUsed,
|
|
4660
|
+
});
|
|
4530
4661
|
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4662
|
+
// Upload logs on error while adding media
|
|
4663
|
+
Trigger.trigger(
|
|
4664
|
+
this,
|
|
4665
|
+
{
|
|
4666
|
+
file: 'meeting/index',
|
|
4667
|
+
function: 'addMedia',
|
|
4668
|
+
},
|
|
4669
|
+
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
4670
|
+
this
|
|
4671
|
+
);
|
|
4541
4672
|
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4673
|
+
// If addMedia failes for not establishing connection then
|
|
4674
|
+
// leave the meeting with reson connection failed as meeting anyways will end
|
|
4675
|
+
// and cannot be connected unless network condition is checked for firewall
|
|
4676
|
+
if (error.code === InvalidSdpError.CODE) {
|
|
4677
|
+
this.leave({reason: MEETING_REMOVED_REASON.MEETING_CONNECTION_FAILED});
|
|
4678
|
+
}
|
|
4548
4679
|
|
|
4549
|
-
|
|
4550
|
-
|
|
4680
|
+
throw error;
|
|
4681
|
+
});
|
|
4551
4682
|
});
|
|
4552
4683
|
}
|
|
4553
4684
|
|
|
@@ -4556,7 +4687,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4556
4687
|
* @returns {Boolean}
|
|
4557
4688
|
*/
|
|
4558
4689
|
canUpdateMedia() {
|
|
4559
|
-
return
|
|
4690
|
+
return (
|
|
4691
|
+
this.mediaProperties.peerConnection.signalingState === SDP.STABLE &&
|
|
4692
|
+
!RoapCollection.isBusy(this.correlationId)
|
|
4693
|
+
);
|
|
4560
4694
|
}
|
|
4561
4695
|
|
|
4562
4696
|
/**
|
|
@@ -4570,10 +4704,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4570
4704
|
private enqueueMediaUpdate(mediaUpdateType: string, options: object) {
|
|
4571
4705
|
return new Promise((resolve, reject) => {
|
|
4572
4706
|
const queueItem = {
|
|
4573
|
-
pendingPromiseResolve: resolve,
|
|
4707
|
+
pendingPromiseResolve: resolve,
|
|
4708
|
+
pendingPromiseReject: reject,
|
|
4709
|
+
mediaUpdateType,
|
|
4710
|
+
options,
|
|
4574
4711
|
};
|
|
4575
4712
|
|
|
4576
|
-
LoggerProxy.logger.log(
|
|
4713
|
+
LoggerProxy.logger.log(
|
|
4714
|
+
`Meeting:index#enqueueMediaUpdate --> enqueuing media update type=${mediaUpdateType}`
|
|
4715
|
+
);
|
|
4577
4716
|
this.queuedMediaUpdates.push(queueItem);
|
|
4578
4717
|
});
|
|
4579
4718
|
}
|
|
@@ -4592,9 +4731,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4592
4731
|
this,
|
|
4593
4732
|
{
|
|
4594
4733
|
file: 'meeting/index',
|
|
4595
|
-
function: 'mediaNegotiatedEvent'
|
|
4734
|
+
function: 'mediaNegotiatedEvent',
|
|
4596
4735
|
},
|
|
4597
|
-
EVENT_TRIGGERS.MEDIA_NEGOTIATED
|
|
4736
|
+
EVENT_TRIGGERS.MEDIA_NEGOTIATED
|
|
4598
4737
|
);
|
|
4599
4738
|
}
|
|
4600
4739
|
};
|
|
@@ -4607,12 +4746,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4607
4746
|
* @memberof Meeting
|
|
4608
4747
|
*/
|
|
4609
4748
|
processNextQueuedMediaUpdate = () => {
|
|
4610
|
-
if (this.canUpdateMedia() &&
|
|
4611
|
-
const {
|
|
4612
|
-
|
|
4613
|
-
} = this.queuedMediaUpdates.shift();
|
|
4749
|
+
if (this.canUpdateMedia() && this.queuedMediaUpdates.length > 0) {
|
|
4750
|
+
const {pendingPromiseResolve, pendingPromiseReject, mediaUpdateType, options} =
|
|
4751
|
+
this.queuedMediaUpdates.shift();
|
|
4614
4752
|
|
|
4615
|
-
LoggerProxy.logger.log(
|
|
4753
|
+
LoggerProxy.logger.log(
|
|
4754
|
+
`Meeting:index#processNextQueuedMediaUpdate --> performing delayed media update type=${mediaUpdateType}`
|
|
4755
|
+
);
|
|
4616
4756
|
switch (mediaUpdateType) {
|
|
4617
4757
|
case MEDIA_UPDATE_TYPE.ALL:
|
|
4618
4758
|
this.updateMedia(options).then(pendingPromiseResolve, pendingPromiseReject);
|
|
@@ -4627,7 +4767,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4627
4767
|
this.updateShare(options).then(pendingPromiseResolve, pendingPromiseReject);
|
|
4628
4768
|
break;
|
|
4629
4769
|
default:
|
|
4630
|
-
LoggerProxy.logger.error(
|
|
4770
|
+
LoggerProxy.logger.error(
|
|
4771
|
+
`Peer-connection-manager:index#processNextQueuedMediaUpdate --> unsupported media update type ${mediaUpdateType} found in the queue`
|
|
4772
|
+
);
|
|
4631
4773
|
break;
|
|
4632
4774
|
}
|
|
4633
4775
|
}
|
|
@@ -4657,67 +4799,93 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4657
4799
|
if (!this.canUpdateMedia()) {
|
|
4658
4800
|
return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.ALL, options);
|
|
4659
4801
|
}
|
|
4660
|
-
const {
|
|
4661
|
-
localStream, localShare, mediaSettings
|
|
4662
|
-
} = options;
|
|
4802
|
+
const {localStream, localShare, mediaSettings} = options;
|
|
4663
4803
|
|
|
4664
4804
|
const previousSendShareStatus = this.mediaProperties.mediaDirection.sendShare;
|
|
4665
|
-
|
|
4666
|
-
return MeetingUtil.validateOptions(options)
|
|
4667
|
-
.then(() => this.preMedia(localStream, localShare, mediaSettings))
|
|
4668
|
-
.then(() =>
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
.then((peerConnection) => {
|
|
4677
|
-
LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection received from updateMedia, ${peerConnection}`);
|
|
4678
|
-
this.setRemoteStream(peerConnection);
|
|
4679
|
-
if (mediaSettings.receiveShare || localShare) {
|
|
4680
|
-
PeerConnectionManager.setContentSlides(peerConnection);
|
|
4681
|
-
}
|
|
4805
|
+
|
|
4806
|
+
return MeetingUtil.validateOptions(options)
|
|
4807
|
+
.then(() => this.preMedia(localStream, localShare, mediaSettings))
|
|
4808
|
+
.then(() =>
|
|
4809
|
+
Media.updateMedia(this.mediaProperties, {
|
|
4810
|
+
meetingId: this.id,
|
|
4811
|
+
remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
|
|
4812
|
+
// @ts-ignore - config coming from registerPlugin
|
|
4813
|
+
enableRtx: this.config.enableRtx,
|
|
4814
|
+
// @ts-ignore - config coming from registerPlugin
|
|
4815
|
+
enableExtmap: this.config.enableExtmap,
|
|
4682
4816
|
})
|
|
4683
|
-
|
|
4684
|
-
|
|
4817
|
+
.then((peerConnection) => {
|
|
4818
|
+
LoggerProxy.logger.info(
|
|
4819
|
+
`${LOG_HEADER} PeerConnection received from updateMedia, ${peerConnection}`
|
|
4820
|
+
);
|
|
4821
|
+
this.setRemoteStream(peerConnection);
|
|
4822
|
+
if (mediaSettings.receiveShare || localShare) {
|
|
4823
|
+
PeerConnectionManager.setContentSlides(peerConnection);
|
|
4824
|
+
}
|
|
4825
|
+
})
|
|
4826
|
+
.catch((error) => {
|
|
4827
|
+
LoggerProxy.logger.error(`${LOG_HEADER} Error updatedMedia, `, error);
|
|
4685
4828
|
|
|
4686
|
-
|
|
4687
|
-
BEHAVIORAL_METRICS.UPDATE_MEDIA_FAILURE,
|
|
4688
|
-
{
|
|
4829
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPDATE_MEDIA_FAILURE, {
|
|
4689
4830
|
correlation_id: this.correlationId,
|
|
4690
4831
|
locus_id: this.locusUrl.split('/').pop(),
|
|
4691
4832
|
reason: error.message,
|
|
4692
|
-
stack: error.stack
|
|
4833
|
+
stack: error.stack,
|
|
4834
|
+
});
|
|
4835
|
+
|
|
4836
|
+
throw error;
|
|
4837
|
+
})
|
|
4838
|
+
.then(() =>
|
|
4839
|
+
logRequest(
|
|
4840
|
+
this.roap.sendRoapMediaRequest({
|
|
4841
|
+
sdp: this.mediaProperties.peerConnection.sdp,
|
|
4842
|
+
roapSeq: this.roapSeq,
|
|
4843
|
+
meeting: this, // or can pass meeting ID
|
|
4844
|
+
}),
|
|
4845
|
+
{
|
|
4846
|
+
header: `${LOG_HEADER} sendRoapMediaRequest being sent`,
|
|
4847
|
+
success: `${LOG_HEADER} sendRoadMediaRequest successful`,
|
|
4848
|
+
failure: `${LOG_HEADER} Error updateMedia on send roap media request, `,
|
|
4849
|
+
}
|
|
4850
|
+
)
|
|
4851
|
+
)
|
|
4852
|
+
.then(() => this.checkForStopShare(mediaSettings.sendShare, previousSendShareStatus))
|
|
4853
|
+
.then((startShare) => {
|
|
4854
|
+
// This is a special case if we do an /floor grant followed by /media
|
|
4855
|
+
// we actually get a OFFER from the server and a GLAR condition happens
|
|
4856
|
+
if (startShare) {
|
|
4857
|
+
// We are assuming that the clients are connected when doing an update
|
|
4858
|
+
return this.share();
|
|
4693
4859
|
}
|
|
4694
|
-
);
|
|
4695
4860
|
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
//
|
|
4716
|
-
|
|
4717
|
-
|
|
4861
|
+
throw error;
|
|
4862
|
+
})
|
|
4863
|
+
.then(() =>
|
|
4864
|
+
logRequest(
|
|
4865
|
+
this.roap.sendRoapMediaRequest({
|
|
4866
|
+
sdp: this.mediaProperties.peerConnection.sdp,
|
|
4867
|
+
roapSeq: this.roapSeq,
|
|
4868
|
+
meeting: this, // or can pass meeting ID
|
|
4869
|
+
}),
|
|
4870
|
+
{
|
|
4871
|
+
header: `${LOG_HEADER} sendRoapMediaRequest being sent`,
|
|
4872
|
+
success: `${LOG_HEADER} sendRoadMediaRequest successful`,
|
|
4873
|
+
failure: `${LOG_HEADER} Error updateMedia on send roap media request, `,
|
|
4874
|
+
}
|
|
4875
|
+
)
|
|
4876
|
+
)
|
|
4877
|
+
.then(() => this.checkForStopShare(mediaSettings.sendShare, previousSendShareStatus))
|
|
4878
|
+
.then((startShare) => {
|
|
4879
|
+
// This is a special case if we do an /floor grant followed by /media
|
|
4880
|
+
// we actually get a OFFER from the server and a GLAR condition happens
|
|
4881
|
+
if (startShare) {
|
|
4882
|
+
// We are assuming that the clients are connected when doing an update
|
|
4883
|
+
return this.requestScreenShareFloor();
|
|
4884
|
+
}
|
|
4718
4885
|
|
|
4719
|
-
|
|
4720
|
-
|
|
4886
|
+
return Promise.resolve();
|
|
4887
|
+
})
|
|
4888
|
+
);
|
|
4721
4889
|
}
|
|
4722
4890
|
|
|
4723
4891
|
/**
|
|
@@ -4730,13 +4898,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4730
4898
|
* @public
|
|
4731
4899
|
* @memberof Meeting
|
|
4732
4900
|
*/
|
|
4733
|
-
public async updateAudio(options: {
|
|
4901
|
+
public async updateAudio(options: {
|
|
4902
|
+
sendAudio: boolean;
|
|
4903
|
+
receiveAudio: boolean;
|
|
4904
|
+
stream: MediaStream;
|
|
4905
|
+
}) {
|
|
4734
4906
|
if (!this.canUpdateMedia()) {
|
|
4735
4907
|
return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.AUDIO, options);
|
|
4736
4908
|
}
|
|
4737
|
-
const {
|
|
4738
|
-
sendAudio, receiveAudio, stream
|
|
4739
|
-
} = options;
|
|
4909
|
+
const {sendAudio, receiveAudio, stream} = options;
|
|
4740
4910
|
|
|
4741
4911
|
const {audioTransceiver} = this.mediaProperties.peerConnection;
|
|
4742
4912
|
let track = MeetingUtil.getTrack(stream).audioTrack;
|
|
@@ -4748,7 +4918,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4748
4918
|
if (this.effects && this.effects.state) {
|
|
4749
4919
|
const bnrEnabled = this.effects.state.bnr.enabled;
|
|
4750
4920
|
|
|
4751
|
-
if (
|
|
4921
|
+
if (
|
|
4922
|
+
sendAudio &&
|
|
4923
|
+
!this.isAudioMuted() &&
|
|
4924
|
+
(bnrEnabled === BNR_STATUS.ENABLED || bnrEnabled === BNR_STATUS.SHOULD_ENABLE)
|
|
4925
|
+
) {
|
|
4752
4926
|
LoggerProxy.logger.info('Meeting:index#updateAudio. Calling WebRTC enable bnr method');
|
|
4753
4927
|
track = await this.internal_enableBNR(track);
|
|
4754
4928
|
LoggerProxy.logger.info('Meeting:index#updateAudio. WebRTC enable bnr request completed');
|
|
@@ -4762,10 +4936,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4762
4936
|
if (this.mediaProperties.mediaDirection) {
|
|
4763
4937
|
previousMediaDirection = {
|
|
4764
4938
|
sendTrack: this.mediaProperties.mediaDirection.sendAudio,
|
|
4765
|
-
receiveTrack: this.mediaProperties.mediaDirection.receiveAudio
|
|
4939
|
+
receiveTrack: this.mediaProperties.mediaDirection.receiveAudio,
|
|
4766
4940
|
};
|
|
4767
|
-
}
|
|
4768
|
-
else {
|
|
4941
|
+
} else {
|
|
4769
4942
|
this.mediaProperties.mediaDirection = {};
|
|
4770
4943
|
}
|
|
4771
4944
|
|
|
@@ -4777,12 +4950,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4777
4950
|
track,
|
|
4778
4951
|
transceiver: audioTransceiver,
|
|
4779
4952
|
peerConnection: this.mediaProperties.peerConnection,
|
|
4780
|
-
previousMediaDirection
|
|
4953
|
+
previousMediaDirection,
|
|
4781
4954
|
},
|
|
4782
4955
|
{
|
|
4783
4956
|
mediaProperties: this.mediaProperties,
|
|
4784
4957
|
meeting: this,
|
|
4785
|
-
id: this.id
|
|
4958
|
+
id: this.id,
|
|
4786
4959
|
}
|
|
4787
4960
|
);
|
|
4788
4961
|
})
|
|
@@ -4792,7 +4965,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4792
4965
|
this.mediaProperties.mediaDirection.receiveAudio = receiveAudio;
|
|
4793
4966
|
|
|
4794
4967
|
// audio state could be undefined if you have not sent audio before
|
|
4795
|
-
this.audio =
|
|
4968
|
+
this.audio =
|
|
4969
|
+
this.audio || createMuteState(AUDIO, this, this.mediaProperties.mediaDirection);
|
|
4796
4970
|
});
|
|
4797
4971
|
}
|
|
4798
4972
|
|
|
@@ -4806,7 +4980,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4806
4980
|
* @public
|
|
4807
4981
|
* @memberof Meeting
|
|
4808
4982
|
*/
|
|
4809
|
-
public updateVideo(options: {
|
|
4983
|
+
public updateVideo(options: {sendVideo: boolean; receiveVideo: boolean; stream: MediaStream}) {
|
|
4810
4984
|
if (!this.canUpdateMedia()) {
|
|
4811
4985
|
return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.VIDEO, options);
|
|
4812
4986
|
}
|
|
@@ -4819,30 +4993,35 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4819
4993
|
}
|
|
4820
4994
|
|
|
4821
4995
|
return MeetingUtil.validateOptions({sendVideo, localStream: stream})
|
|
4822
|
-
.then(() =>
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4996
|
+
.then(() =>
|
|
4997
|
+
MeetingUtil.updateTransceiver(
|
|
4998
|
+
{
|
|
4999
|
+
type: 'video',
|
|
5000
|
+
sendTrack: options.sendVideo,
|
|
5001
|
+
receiveTrack: options.receiveVideo,
|
|
5002
|
+
track,
|
|
5003
|
+
transceiver: videoTransceiver,
|
|
5004
|
+
peerConnection: this.mediaProperties.peerConnection,
|
|
5005
|
+
previousMediaDirection: {
|
|
5006
|
+
sendTrack: this.mediaProperties.mediaDirection.sendVideo,
|
|
5007
|
+
receiveTrack: this.mediaProperties.mediaDirection.receiveVideo,
|
|
5008
|
+
},
|
|
5009
|
+
},
|
|
5010
|
+
{
|
|
5011
|
+
mediaProperties: this.mediaProperties,
|
|
5012
|
+
meeting: this,
|
|
5013
|
+
id: this.id,
|
|
5014
|
+
}
|
|
5015
|
+
)
|
|
5016
|
+
)
|
|
4839
5017
|
.then(() => {
|
|
4840
5018
|
this.setLocalVideoTrack(track);
|
|
4841
5019
|
this.mediaProperties.mediaDirection.sendVideo = sendVideo;
|
|
4842
5020
|
this.mediaProperties.mediaDirection.receiveVideo = receiveVideo;
|
|
4843
5021
|
|
|
4844
5022
|
// video state could be undefined if you have not sent video before
|
|
4845
|
-
this.video =
|
|
5023
|
+
this.video =
|
|
5024
|
+
this.video || createMuteState(VIDEO, this, this.mediaProperties.mediaDirection);
|
|
4846
5025
|
});
|
|
4847
5026
|
}
|
|
4848
5027
|
|
|
@@ -4862,8 +5041,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4862
5041
|
|
|
4863
5042
|
if (!sendShare && previousShareStatus) {
|
|
4864
5043
|
// When user stops sharing
|
|
4865
|
-
return this.releaseScreenShareFloor()
|
|
4866
|
-
.then(() => Promise.resolve(false));
|
|
5044
|
+
return this.releaseScreenShareFloor().then(() => Promise.resolve(false));
|
|
4867
5045
|
}
|
|
4868
5046
|
|
|
4869
5047
|
return Promise.resolve();
|
|
@@ -4878,7 +5056,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4878
5056
|
* @public
|
|
4879
5057
|
* @memberof Meeting
|
|
4880
5058
|
*/
|
|
4881
|
-
public updateShare(options: {
|
|
5059
|
+
public updateShare(options: {
|
|
5060
|
+
sendShare?: boolean;
|
|
5061
|
+
receiveShare?: boolean;
|
|
5062
|
+
stream?: any;
|
|
5063
|
+
skipSignalingCheck?: boolean;
|
|
5064
|
+
}) {
|
|
4882
5065
|
if (!options.skipSignalingCheck && !this.canUpdateMedia()) {
|
|
4883
5066
|
return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.SHARE, options);
|
|
4884
5067
|
}
|
|
@@ -4895,30 +5078,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4895
5078
|
|
|
4896
5079
|
return MeetingUtil.validateOptions({sendShare, localShare: stream})
|
|
4897
5080
|
.then(() => this.checkForStopShare(sendShare, previousSendShareStatus))
|
|
4898
|
-
.then((startShare) =>
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
5081
|
+
.then((startShare) =>
|
|
5082
|
+
MeetingUtil.updateTransceiver(
|
|
5083
|
+
{
|
|
5084
|
+
type: 'video',
|
|
5085
|
+
sendTrack: sendShare,
|
|
5086
|
+
receiveTrack: receiveShare,
|
|
5087
|
+
track,
|
|
5088
|
+
transceiver: shareTransceiver,
|
|
5089
|
+
peerConnection: this.mediaProperties.peerConnection,
|
|
5090
|
+
previousMediaDirection: {
|
|
5091
|
+
sendTrack: this.mediaProperties.mediaDirection.sendShare,
|
|
5092
|
+
receiveTrack: this.mediaProperties.mediaDirection.receiveShare,
|
|
5093
|
+
},
|
|
5094
|
+
},
|
|
5095
|
+
{
|
|
5096
|
+
mediaProperties: this.mediaProperties,
|
|
5097
|
+
meeting: this,
|
|
5098
|
+
id: this.id,
|
|
5099
|
+
}
|
|
5100
|
+
).then(() => {
|
|
4916
5101
|
if (startShare) {
|
|
4917
5102
|
return this.requestScreenShareFloor();
|
|
4918
5103
|
}
|
|
4919
5104
|
|
|
4920
5105
|
return Promise.resolve();
|
|
4921
|
-
})
|
|
5106
|
+
})
|
|
5107
|
+
)
|
|
4922
5108
|
.then(() => {
|
|
4923
5109
|
this.mediaProperties.mediaDirection.sendShare = sendShare;
|
|
4924
5110
|
this.mediaProperties.mediaDirection.receiveShare = receiveShare;
|
|
@@ -4930,17 +5116,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4930
5116
|
.finally(() => {
|
|
4931
5117
|
const delay = 1e3;
|
|
4932
5118
|
// Check to see if share was stopped natively before onended was assigned.
|
|
4933
|
-
const sharingModeIsActive =
|
|
5119
|
+
const sharingModeIsActive =
|
|
5120
|
+
this.mediaProperties.peerConnection.shareTransceiver.direction === SENDRECV;
|
|
4934
5121
|
const isSharingOutOfSync = sharingModeIsActive && !this.isLocalShareLive;
|
|
4935
5122
|
|
|
4936
5123
|
if (isSharingOutOfSync) {
|
|
4937
5124
|
// Adding a delay to avoid a 409 from server
|
|
4938
5125
|
// which results in user still appearing as if sharing.
|
|
4939
5126
|
// Also delay give time for changes to peerConnection.
|
|
4940
|
-
setTimeout(
|
|
4941
|
-
() => this.handleShareTrackEnded(stream),
|
|
4942
|
-
delay
|
|
4943
|
-
);
|
|
5127
|
+
setTimeout(() => this.handleShareTrackEnded(stream), delay);
|
|
4944
5128
|
}
|
|
4945
5129
|
});
|
|
4946
5130
|
}
|
|
@@ -4984,7 +5168,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4984
5168
|
.acknowledgeMeeting({
|
|
4985
5169
|
locusUrl: this.locusUrl,
|
|
4986
5170
|
deviceUrl: this.deviceUrl,
|
|
4987
|
-
correlationId: this.correlationId
|
|
5171
|
+
correlationId: this.correlationId,
|
|
4988
5172
|
})
|
|
4989
5173
|
.then((response) => Promise.resolve(response))
|
|
4990
5174
|
.then((response) => {
|
|
@@ -4992,14 +5176,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4992
5176
|
Metrics.postEvent({event: eventType.ALERT_DISPLAYED, meeting: this});
|
|
4993
5177
|
|
|
4994
5178
|
return Promise.resolve({
|
|
4995
|
-
response
|
|
5179
|
+
response,
|
|
4996
5180
|
});
|
|
4997
5181
|
});
|
|
4998
5182
|
}
|
|
4999
5183
|
|
|
5000
5184
|
// TODO: outside of 1:1 incoming, and all outgoing calls
|
|
5001
5185
|
return Promise.resolve({
|
|
5002
|
-
message: 'noop'
|
|
5186
|
+
message: 'noop',
|
|
5003
5187
|
});
|
|
5004
5188
|
}
|
|
5005
5189
|
|
|
@@ -5011,15 +5195,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5011
5195
|
* @memberof Meeting
|
|
5012
5196
|
*/
|
|
5013
5197
|
public decline(reason: string) {
|
|
5014
|
-
return MeetingUtil.declineMeeting(this, reason)
|
|
5015
|
-
|
|
5198
|
+
return MeetingUtil.declineMeeting(this, reason)
|
|
5199
|
+
.then((decline) => {
|
|
5200
|
+
this.meetingFiniteStateMachine.decline();
|
|
5016
5201
|
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5202
|
+
return Promise.resolve(decline);
|
|
5203
|
+
})
|
|
5204
|
+
.catch((error) => {
|
|
5205
|
+
this.meetingFiniteStateMachine.fail(error);
|
|
5020
5206
|
|
|
5021
|
-
|
|
5022
|
-
|
|
5207
|
+
return Promise.reject(error);
|
|
5208
|
+
});
|
|
5023
5209
|
}
|
|
5024
5210
|
|
|
5025
5211
|
/**
|
|
@@ -5030,8 +5216,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5030
5216
|
* @public
|
|
5031
5217
|
* @memberof Meeting
|
|
5032
5218
|
*/
|
|
5033
|
-
public leave(options: {
|
|
5034
|
-
Metrics.postEvent({
|
|
5219
|
+
public leave(options: {resourceId?: string; reason?: any} = {} as any) {
|
|
5220
|
+
Metrics.postEvent({
|
|
5221
|
+
event: eventType.LEAVE,
|
|
5222
|
+
meeting: this,
|
|
5223
|
+
data: {trigger: trigger.USER_INTERACTION, canProceed: false},
|
|
5224
|
+
});
|
|
5035
5225
|
const leaveReason = options.reason || MEETING_REMOVED_REASON.CLIENT_LEAVE_REQUEST;
|
|
5036
5226
|
|
|
5037
5227
|
LoggerProxy.logger.log('Meeting:index#leave --> Leaving a meeting');
|
|
@@ -5046,7 +5236,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5046
5236
|
this,
|
|
5047
5237
|
{
|
|
5048
5238
|
file: 'meeting/index',
|
|
5049
|
-
function: 'leave'
|
|
5239
|
+
function: 'leave',
|
|
5050
5240
|
},
|
|
5051
5241
|
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
5052
5242
|
this
|
|
@@ -5059,19 +5249,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5059
5249
|
this,
|
|
5060
5250
|
{
|
|
5061
5251
|
file: 'meeting/index',
|
|
5062
|
-
function: 'leave'
|
|
5252
|
+
function: 'leave',
|
|
5063
5253
|
},
|
|
5064
5254
|
EVENTS.DESTROY_MEETING,
|
|
5065
5255
|
{
|
|
5066
5256
|
reason: options.reason,
|
|
5067
|
-
meetingId: this.id
|
|
5257
|
+
meetingId: this.id,
|
|
5068
5258
|
}
|
|
5069
5259
|
);
|
|
5070
5260
|
}
|
|
5071
5261
|
LoggerProxy.logger.log('Meeting:index#leave --> LEAVE REASON ', leaveReason);
|
|
5072
5262
|
|
|
5073
5263
|
return leave;
|
|
5074
|
-
})
|
|
5264
|
+
})
|
|
5265
|
+
.catch((error) => {
|
|
5075
5266
|
this.meetingFiniteStateMachine.fail(error);
|
|
5076
5267
|
LoggerProxy.logger.error('Meeting:index#leave --> Failed to leave ', error);
|
|
5077
5268
|
// upload logs on leave irrespective of meeting delete
|
|
@@ -5079,21 +5270,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5079
5270
|
this,
|
|
5080
5271
|
{
|
|
5081
5272
|
file: 'meeting/index',
|
|
5082
|
-
function: 'leave'
|
|
5273
|
+
function: 'leave',
|
|
5083
5274
|
},
|
|
5084
5275
|
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
5085
5276
|
this
|
|
5086
5277
|
);
|
|
5087
|
-
Metrics.sendBehavioralMetric(
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
code: error.code
|
|
5095
|
-
}
|
|
5096
|
-
);
|
|
5278
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_LEAVE_FAILURE, {
|
|
5279
|
+
correlation_id: this.correlationId,
|
|
5280
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
5281
|
+
reason: error.message,
|
|
5282
|
+
stack: error.stack,
|
|
5283
|
+
code: error.code,
|
|
5284
|
+
});
|
|
5097
5285
|
|
|
5098
5286
|
return Promise.reject(error);
|
|
5099
5287
|
});
|
|
@@ -5122,14 +5310,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5122
5310
|
personUrl: this.locusInfo.self.url,
|
|
5123
5311
|
deviceUrl: this.deviceUrl,
|
|
5124
5312
|
uri: whiteboard.url,
|
|
5125
|
-
resourceUrl: channelUrl
|
|
5313
|
+
resourceUrl: channelUrl,
|
|
5126
5314
|
};
|
|
5127
5315
|
|
|
5128
5316
|
if (resourceToken) {
|
|
5129
5317
|
body.resourceToken = resourceToken;
|
|
5130
5318
|
}
|
|
5131
5319
|
|
|
5132
|
-
return this.meetingRequest
|
|
5320
|
+
return this.meetingRequest
|
|
5321
|
+
.changeMeetingFloor(body)
|
|
5133
5322
|
.then(() => {
|
|
5134
5323
|
this.isSharing = false;
|
|
5135
5324
|
|
|
@@ -5138,16 +5327,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5138
5327
|
.catch((error) => {
|
|
5139
5328
|
LoggerProxy.logger.error('Meeting:index#startWhiteboardShare --> Error ', error);
|
|
5140
5329
|
|
|
5141
|
-
Metrics.sendBehavioralMetric(
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
board: {channelUrl}
|
|
5149
|
-
}
|
|
5150
|
-
);
|
|
5330
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_START_WHITEBOARD_SHARE_FAILURE, {
|
|
5331
|
+
correlation_id: this.correlationId,
|
|
5332
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
5333
|
+
reason: error.message,
|
|
5334
|
+
stack: error.stack,
|
|
5335
|
+
board: {channelUrl},
|
|
5336
|
+
});
|
|
5151
5337
|
|
|
5152
5338
|
return Promise.reject(error);
|
|
5153
5339
|
});
|
|
@@ -5169,12 +5355,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5169
5355
|
if (whiteboard) {
|
|
5170
5356
|
Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_STOPPED, meeting: this});
|
|
5171
5357
|
|
|
5172
|
-
return this.meetingRequest
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5358
|
+
return this.meetingRequest
|
|
5359
|
+
.changeMeetingFloor({
|
|
5360
|
+
disposition: FLOOR_ACTION.RELEASED,
|
|
5361
|
+
personUrl: this.locusInfo.self.url,
|
|
5362
|
+
deviceUrl: this.deviceUrl,
|
|
5363
|
+
uri: whiteboard.url,
|
|
5364
|
+
})
|
|
5178
5365
|
.catch((error) => {
|
|
5179
5366
|
LoggerProxy.logger.error('Meeting:index#stopWhiteboardShare --> Error ', error);
|
|
5180
5367
|
|
|
@@ -5186,14 +5373,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5186
5373
|
locus_id: this.locusUrl.split('/').pop(),
|
|
5187
5374
|
reason: error.message,
|
|
5188
5375
|
stack: error.stack,
|
|
5189
|
-
board: {channelUrl}
|
|
5376
|
+
board: {channelUrl},
|
|
5190
5377
|
}
|
|
5191
5378
|
);
|
|
5192
5379
|
|
|
5193
5380
|
return Promise.reject(error);
|
|
5194
5381
|
})
|
|
5195
|
-
.finally(() => {
|
|
5196
|
-
});
|
|
5382
|
+
.finally(() => {});
|
|
5197
5383
|
}
|
|
5198
5384
|
|
|
5199
5385
|
return Promise.reject(new ParameterError('Cannot stop share without whiteboard.'));
|
|
@@ -5208,16 +5394,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5208
5394
|
private requestScreenShareFloor() {
|
|
5209
5395
|
const content = this.locusInfo.mediaShares.find((element) => element.name === CONTENT);
|
|
5210
5396
|
|
|
5211
|
-
if (content &&
|
|
5397
|
+
if (content && this.shareStatus !== SHARE_STATUS.LOCAL_SHARE_ACTIVE) {
|
|
5212
5398
|
Metrics.postEvent({event: eventType.SHARE_INITIATED, meeting: this});
|
|
5213
5399
|
|
|
5214
|
-
return this.meetingRequest
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5400
|
+
return this.meetingRequest
|
|
5401
|
+
.changeMeetingFloor({
|
|
5402
|
+
disposition: FLOOR_ACTION.GRANTED,
|
|
5403
|
+
personUrl: this.locusInfo.self.url,
|
|
5404
|
+
deviceUrl: this.deviceUrl,
|
|
5405
|
+
uri: content.url,
|
|
5406
|
+
resourceUrl: this.resourceUrl,
|
|
5407
|
+
})
|
|
5221
5408
|
.then(() => {
|
|
5222
5409
|
this.isSharing = true;
|
|
5223
5410
|
|
|
@@ -5226,15 +5413,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5226
5413
|
.catch((error) => {
|
|
5227
5414
|
LoggerProxy.logger.error('Meeting:index#share --> Error ', error);
|
|
5228
5415
|
|
|
5229
|
-
Metrics.sendBehavioralMetric(
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
stack: error.stack
|
|
5236
|
-
}
|
|
5237
|
-
);
|
|
5416
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_FAILURE, {
|
|
5417
|
+
correlation_id: this.correlationId,
|
|
5418
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
5419
|
+
reason: error.message,
|
|
5420
|
+
stack: error.stack,
|
|
5421
|
+
});
|
|
5238
5422
|
|
|
5239
5423
|
return Promise.reject(error);
|
|
5240
5424
|
});
|
|
@@ -5255,7 +5439,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5255
5439
|
return this.updateShare({
|
|
5256
5440
|
sendShare: false,
|
|
5257
5441
|
receiveShare: this.mediaProperties.mediaDirection.receiveShare,
|
|
5258
|
-
...options
|
|
5442
|
+
...options,
|
|
5259
5443
|
});
|
|
5260
5444
|
}
|
|
5261
5445
|
|
|
@@ -5268,7 +5452,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5268
5452
|
private releaseScreenShareFloor() {
|
|
5269
5453
|
const content = this.locusInfo.mediaShares.find((element) => element.name === CONTENT);
|
|
5270
5454
|
|
|
5271
|
-
if (content &&
|
|
5455
|
+
if (content && this.mediaProperties.mediaDirection.sendShare) {
|
|
5272
5456
|
Metrics.postEvent({event: eventType.SHARE_STOPPED, meeting: this});
|
|
5273
5457
|
Media.stopTracks(this.mediaProperties.shareTrack);
|
|
5274
5458
|
|
|
@@ -5279,25 +5463,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5279
5463
|
return Promise.resolve();
|
|
5280
5464
|
}
|
|
5281
5465
|
|
|
5282
|
-
return this.meetingRequest
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5466
|
+
return this.meetingRequest
|
|
5467
|
+
.changeMeetingFloor({
|
|
5468
|
+
disposition: FLOOR_ACTION.RELEASED,
|
|
5469
|
+
personUrl: this.locusInfo.self.url,
|
|
5470
|
+
deviceUrl: this.deviceUrl,
|
|
5471
|
+
uri: content.url,
|
|
5472
|
+
resourceUrl: this.resourceUrl,
|
|
5473
|
+
})
|
|
5289
5474
|
.catch((error) => {
|
|
5290
5475
|
LoggerProxy.logger.error('Meeting:index#releaseScreenShareFloor --> Error ', error);
|
|
5291
5476
|
|
|
5292
|
-
Metrics.sendBehavioralMetric(
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
stack: error.stack
|
|
5299
|
-
}
|
|
5300
|
-
);
|
|
5477
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.STOP_FLOOR_REQUEST_FAILURE, {
|
|
5478
|
+
correlation_id: this.correlationId,
|
|
5479
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
5480
|
+
reason: error.message,
|
|
5481
|
+
stack: error.stack,
|
|
5482
|
+
});
|
|
5301
5483
|
|
|
5302
5484
|
return Promise.reject(error);
|
|
5303
5485
|
})
|
|
@@ -5392,18 +5574,21 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5392
5574
|
public sendDTMF(tones: string) {
|
|
5393
5575
|
if (this.locusInfo && this.locusInfo.self) {
|
|
5394
5576
|
if (this.locusInfo.self.enableDTMF) {
|
|
5395
|
-
return this.meetingRequest
|
|
5396
|
-
.
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
});
|
|
5577
|
+
return this.meetingRequest.sendDTMF({
|
|
5578
|
+
locusUrl: this.locusInfo.self.url,
|
|
5579
|
+
deviceUrl: this.deviceUrl,
|
|
5580
|
+
tones,
|
|
5581
|
+
});
|
|
5401
5582
|
}
|
|
5402
5583
|
|
|
5403
|
-
return this.rejectWithErrorLog(
|
|
5584
|
+
return this.rejectWithErrorLog(
|
|
5585
|
+
'Meeting:index#sendDTMF --> cannot send DTMF, meeting does not have DTMF enabled'
|
|
5586
|
+
);
|
|
5404
5587
|
}
|
|
5405
5588
|
|
|
5406
|
-
return this.rejectWithErrorLog(
|
|
5589
|
+
return this.rejectWithErrorLog(
|
|
5590
|
+
'Meeting:index#sendDTMF --> cannot send DTMF, meeting does not have a connection to the "locus" call control service. Have you joined?'
|
|
5591
|
+
);
|
|
5407
5592
|
}
|
|
5408
5593
|
|
|
5409
5594
|
/**
|
|
@@ -5440,12 +5625,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5440
5625
|
|
|
5441
5626
|
// TODO: We need a real time value for Audio, Video and Share send indicator
|
|
5442
5627
|
if (mediaDirection.receiveVideo !== true || !remoteVideoTrack) {
|
|
5443
|
-
return this.rejectWithErrorLog(
|
|
5628
|
+
return this.rejectWithErrorLog(
|
|
5629
|
+
'Meeting:index#changeVideoLayout --> cannot change video layout, you are not recieving any video/share stream'
|
|
5630
|
+
);
|
|
5444
5631
|
}
|
|
5445
5632
|
|
|
5446
5633
|
if (layoutType) {
|
|
5447
5634
|
if (!LAYOUT_TYPES.includes(layoutType)) {
|
|
5448
|
-
this.rejectWithErrorLog(
|
|
5635
|
+
this.rejectWithErrorLog(
|
|
5636
|
+
'Meeting:index#changeVideoLayout --> cannot change video layout, invalid layoutType recieved.'
|
|
5637
|
+
);
|
|
5449
5638
|
}
|
|
5450
5639
|
|
|
5451
5640
|
layoutInfo.layoutType = layoutType;
|
|
@@ -5471,15 +5660,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5471
5660
|
const contentHeight = Math.round(content.height);
|
|
5472
5661
|
|
|
5473
5662
|
// Stop any "twitching" caused by very slight size changes
|
|
5474
|
-
if (
|
|
5663
|
+
if (
|
|
5664
|
+
!this.lastVideoLayoutInfo.content ||
|
|
5475
5665
|
Math.abs(this.lastVideoLayoutInfo.content.height - contentHeight) > 2 ||
|
|
5476
5666
|
Math.abs(this.lastVideoLayoutInfo.content.width - contentWidth) > 2
|
|
5477
5667
|
) {
|
|
5478
5668
|
layoutInfo.content = {width: contentWidth, height: contentHeight};
|
|
5479
5669
|
}
|
|
5480
|
-
}
|
|
5481
|
-
|
|
5482
|
-
|
|
5670
|
+
} else {
|
|
5671
|
+
return this.rejectWithErrorLog(
|
|
5672
|
+
'Meeting:index#changeVideoLayout --> unable to send renderInfo for content, you are not receiving remote share'
|
|
5673
|
+
);
|
|
5483
5674
|
}
|
|
5484
5675
|
}
|
|
5485
5676
|
|
|
@@ -5498,7 +5689,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5498
5689
|
},
|
|
5499
5690
|
EVENT_TRIGGERS.MEETING_CONTROLS_LAYOUT_UPDATE,
|
|
5500
5691
|
{
|
|
5501
|
-
layout: envelope.layout
|
|
5692
|
+
layout: envelope.layout,
|
|
5502
5693
|
}
|
|
5503
5694
|
);
|
|
5504
5695
|
});
|
|
@@ -5509,7 +5700,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5509
5700
|
deviceUrl: this.deviceUrl,
|
|
5510
5701
|
layoutType,
|
|
5511
5702
|
main: layoutInfo.main,
|
|
5512
|
-
content: layoutInfo.content
|
|
5703
|
+
content: layoutInfo.content,
|
|
5513
5704
|
})
|
|
5514
5705
|
.then((response) => {
|
|
5515
5706
|
if (response && response.body && response.body.locus) {
|
|
@@ -5536,12 +5727,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5536
5727
|
}
|
|
5537
5728
|
|
|
5538
5729
|
if (!this.mediaProperties.mediaDirection.sendVideo) {
|
|
5539
|
-
return this.rejectWithErrorLog(
|
|
5730
|
+
return this.rejectWithErrorLog(
|
|
5731
|
+
'Meeting:index#setLocalVideoQuality --> unable to change video quality, sendVideo is disabled'
|
|
5732
|
+
);
|
|
5540
5733
|
}
|
|
5541
5734
|
|
|
5542
5735
|
// If level is already the same, don't do anything
|
|
5543
5736
|
if (level === this.mediaProperties.localQualityLevel) {
|
|
5544
|
-
LoggerProxy.logger.warn(
|
|
5737
|
+
LoggerProxy.logger.warn(
|
|
5738
|
+
`Meeting:index#setLocalQualityLevel --> Quality already set to ${level}`
|
|
5739
|
+
);
|
|
5545
5740
|
|
|
5546
5741
|
return Promise.resolve();
|
|
5547
5742
|
}
|
|
@@ -5552,25 +5747,27 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5552
5747
|
const mediaDirection = {
|
|
5553
5748
|
sendAudio: this.mediaProperties.mediaDirection.sendAudio,
|
|
5554
5749
|
sendVideo: this.mediaProperties.mediaDirection.sendVideo,
|
|
5555
|
-
sendShare: this.mediaProperties.mediaDirection.sendShare
|
|
5750
|
+
sendShare: this.mediaProperties.mediaDirection.sendShare,
|
|
5556
5751
|
};
|
|
5557
5752
|
|
|
5558
5753
|
// When changing local video quality level
|
|
5559
5754
|
// Need to stop current track first as chrome doesn't support resolution upscaling(for eg. changing 480p to 720p)
|
|
5560
5755
|
// Without feeding it a new track
|
|
5561
5756
|
// open bug link: https://bugs.chromium.org/p/chromium/issues/detail?id=943469
|
|
5562
|
-
if (isBrowser('chrome') && this.mediaProperties.videoTrack)
|
|
5757
|
+
if (isBrowser('chrome') && this.mediaProperties.videoTrack)
|
|
5758
|
+
Media.stopTracks(this.mediaProperties.videoTrack);
|
|
5563
5759
|
|
|
5564
|
-
return this.getMediaStreams(mediaDirection, VIDEO_RESOLUTIONS[level])
|
|
5565
|
-
|
|
5760
|
+
return this.getMediaStreams(mediaDirection, VIDEO_RESOLUTIONS[level]).then(
|
|
5761
|
+
async ([localStream]) => {
|
|
5566
5762
|
await this.updateVideo({
|
|
5567
5763
|
sendVideo: true,
|
|
5568
5764
|
receiveVideo: true,
|
|
5569
|
-
stream: localStream
|
|
5765
|
+
stream: localStream,
|
|
5570
5766
|
});
|
|
5571
5767
|
|
|
5572
5768
|
return localStream;
|
|
5573
|
-
}
|
|
5769
|
+
}
|
|
5770
|
+
);
|
|
5574
5771
|
}
|
|
5575
5772
|
|
|
5576
5773
|
/**
|
|
@@ -5582,16 +5779,25 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5582
5779
|
LoggerProxy.logger.log(`Meeting:index#setRemoteQualityLevel --> Setting quality to ${level}`);
|
|
5583
5780
|
|
|
5584
5781
|
if (!QUALITY_LEVELS[level]) {
|
|
5585
|
-
return this.rejectWithErrorLog(
|
|
5782
|
+
return this.rejectWithErrorLog(
|
|
5783
|
+
`Meeting:index#setRemoteQualityLevel --> ${level} not defined`
|
|
5784
|
+
);
|
|
5586
5785
|
}
|
|
5587
5786
|
|
|
5588
|
-
if (
|
|
5589
|
-
|
|
5787
|
+
if (
|
|
5788
|
+
!this.mediaProperties.mediaDirection.receiveAudio &&
|
|
5789
|
+
!this.mediaProperties.mediaDirection.receiveVideo
|
|
5790
|
+
) {
|
|
5791
|
+
return this.rejectWithErrorLog(
|
|
5792
|
+
'Meeting:index#setRemoteQualityLevel --> unable to change remote quality, receiveVideo and receiveAudio is disabled'
|
|
5793
|
+
);
|
|
5590
5794
|
}
|
|
5591
5795
|
|
|
5592
5796
|
// If level is already the same, don't do anything
|
|
5593
5797
|
if (level === this.mediaProperties.remoteQualityLevel) {
|
|
5594
|
-
LoggerProxy.logger.warn(
|
|
5798
|
+
LoggerProxy.logger.warn(
|
|
5799
|
+
`Meeting:index#setRemoteQualityLevel --> Quality already set to ${level}`
|
|
5800
|
+
);
|
|
5595
5801
|
|
|
5596
5802
|
return Promise.resolve();
|
|
5597
5803
|
}
|
|
@@ -5617,7 +5823,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5617
5823
|
|
|
5618
5824
|
const previousLevel = {
|
|
5619
5825
|
local: this.mediaProperties.localQualityLevel,
|
|
5620
|
-
remote: this.mediaProperties.remoteQualityLevel
|
|
5826
|
+
remote: this.mediaProperties.remoteQualityLevel,
|
|
5621
5827
|
};
|
|
5622
5828
|
|
|
5623
5829
|
// If level is already the same, don't do anything
|
|
@@ -5625,7 +5831,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5625
5831
|
level === this.mediaProperties.localQualityLevel &&
|
|
5626
5832
|
level === this.mediaProperties.remoteQualityLevel
|
|
5627
5833
|
) {
|
|
5628
|
-
LoggerProxy.logger.warn(
|
|
5834
|
+
LoggerProxy.logger.warn(
|
|
5835
|
+
`Meeting:index#setMeetingQuality --> Quality already set to ${level}`
|
|
5836
|
+
);
|
|
5629
5837
|
|
|
5630
5838
|
return Promise.resolve();
|
|
5631
5839
|
}
|
|
@@ -5635,9 +5843,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5635
5843
|
|
|
5636
5844
|
return (sendVideo ? this.setLocalVideoQuality(level) : Promise.resolve())
|
|
5637
5845
|
.then(() =>
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
Promise.resolve()))
|
|
5846
|
+
receiveAudio || receiveVideo ? this.setRemoteQualityLevel(level) : Promise.resolve()
|
|
5847
|
+
)
|
|
5641
5848
|
.catch((error) => {
|
|
5642
5849
|
// From troubleshooting it seems that the stream itself doesn't change the max-fs if the peer connection isn't stable
|
|
5643
5850
|
this.mediaProperties.setLocalQualityLevel(previousLevel.local);
|
|
@@ -5651,10 +5858,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5651
5858
|
correlation_id: this.correlationId,
|
|
5652
5859
|
locus_id: this.locusUrl.split('/').pop(),
|
|
5653
5860
|
reason: error.message,
|
|
5654
|
-
stack: error.stack
|
|
5861
|
+
stack: error.stack,
|
|
5655
5862
|
},
|
|
5656
5863
|
{
|
|
5657
|
-
type: error.name
|
|
5864
|
+
type: error.name,
|
|
5658
5865
|
}
|
|
5659
5866
|
);
|
|
5660
5867
|
|
|
@@ -5663,20 +5870,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5663
5870
|
}
|
|
5664
5871
|
|
|
5665
5872
|
/**
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5873
|
+
* @param {Object} options parameter
|
|
5874
|
+
* @param {Boolean} options.sendAudio send audio from the display share
|
|
5875
|
+
* @param {Boolean} options.sendShare send video from the display share
|
|
5876
|
+
* @param {Object} options.sharePreferences
|
|
5877
|
+
* @param {MediaTrackConstraints} options.sharePreferences.shareConstraints constraints to apply to video
|
|
5878
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints}
|
|
5879
|
+
* @param {Boolean} options.sharePreferences.highFrameRate if shareConstraints isn't provided, set default values based off of this boolean
|
|
5880
|
+
* @returns {Promise}
|
|
5881
|
+
*/
|
|
5675
5882
|
shareScreen(
|
|
5676
5883
|
options: {
|
|
5677
5884
|
sendAudio: boolean;
|
|
5678
5885
|
sendShare: boolean;
|
|
5679
|
-
sharePreferences: {
|
|
5886
|
+
sharePreferences: {shareConstraints: MediaTrackConstraints};
|
|
5680
5887
|
} = {} as any
|
|
5681
5888
|
) {
|
|
5682
5889
|
LoggerProxy.logger.log('Meeting:index#shareScreen --> Getting local share');
|
|
@@ -5684,16 +5891,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5684
5891
|
const shareConstraints = {
|
|
5685
5892
|
sendShare: true,
|
|
5686
5893
|
sendAudio: false,
|
|
5687
|
-
...options
|
|
5894
|
+
...options,
|
|
5688
5895
|
};
|
|
5689
5896
|
|
|
5690
5897
|
// @ts-ignore - config coming from registerPlugin
|
|
5691
5898
|
return Media.getDisplayMedia(shareConstraints, this.config)
|
|
5692
|
-
.then((shareStream) =>
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5899
|
+
.then((shareStream) =>
|
|
5900
|
+
this.updateShare({
|
|
5901
|
+
sendShare: true,
|
|
5902
|
+
receiveShare: this.mediaProperties.mediaDirection.receiveShare,
|
|
5903
|
+
stream: shareStream,
|
|
5904
|
+
})
|
|
5905
|
+
)
|
|
5697
5906
|
.catch((error) => {
|
|
5698
5907
|
// Whenever there is a failure when trying to access a user's display
|
|
5699
5908
|
// report it as an Behavioral metric
|
|
@@ -5707,10 +5916,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5707
5916
|
correlation_id: this.correlationId,
|
|
5708
5917
|
locus_id: this.locusUrl.split('/').pop(),
|
|
5709
5918
|
reason: error.message,
|
|
5710
|
-
stack: error.stack
|
|
5919
|
+
stack: error.stack,
|
|
5711
5920
|
};
|
|
5712
5921
|
const metadata = {
|
|
5713
|
-
type: error.name
|
|
5922
|
+
type: error.name,
|
|
5714
5923
|
};
|
|
5715
5924
|
|
|
5716
5925
|
Metrics.sendBehavioralMetric(metricName, data, metadata);
|
|
@@ -5728,28 +5937,29 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5728
5937
|
private handleShareTrackEnded(localShare: MediaStream) {
|
|
5729
5938
|
if (this.wirelessShare) {
|
|
5730
5939
|
this.leave({reason: MEETING_REMOVED_REASON.USER_ENDED_SHARE_STREAMS});
|
|
5731
|
-
}
|
|
5732
|
-
else {
|
|
5940
|
+
} else {
|
|
5733
5941
|
// Skip checking for a stable peerConnection
|
|
5734
5942
|
// to allow immediately stopping screenshare
|
|
5735
5943
|
this.stopShare({
|
|
5736
|
-
skipSignalingCheck: true
|
|
5737
|
-
})
|
|
5738
|
-
.
|
|
5739
|
-
|
|
5740
|
-
|
|
5944
|
+
skipSignalingCheck: true,
|
|
5945
|
+
}).catch((error) => {
|
|
5946
|
+
LoggerProxy.logger.log(
|
|
5947
|
+
'Meeting:index#handleShareTrackEnded --> Error stopping share: ',
|
|
5948
|
+
error
|
|
5949
|
+
);
|
|
5950
|
+
});
|
|
5741
5951
|
}
|
|
5742
5952
|
|
|
5743
5953
|
Trigger.trigger(
|
|
5744
5954
|
this,
|
|
5745
5955
|
{
|
|
5746
5956
|
file: 'meeting/index',
|
|
5747
|
-
function: 'handleShareTrackEnded'
|
|
5957
|
+
function: 'handleShareTrackEnded',
|
|
5748
5958
|
},
|
|
5749
5959
|
EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
5750
5960
|
{
|
|
5751
5961
|
type: EVENT_TYPES.LOCAL_SHARE,
|
|
5752
|
-
stream: localShare
|
|
5962
|
+
stream: localShare,
|
|
5753
5963
|
}
|
|
5754
5964
|
);
|
|
5755
5965
|
}
|
|
@@ -5770,12 +5980,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5770
5980
|
this,
|
|
5771
5981
|
{
|
|
5772
5982
|
file: 'meeting/index',
|
|
5773
|
-
function: 'addMedia'
|
|
5983
|
+
function: 'addMedia',
|
|
5774
5984
|
},
|
|
5775
5985
|
EVENT_TRIGGERS.NETWORK_QUALITY,
|
|
5776
5986
|
{
|
|
5777
5987
|
networkQualityScore: res.networkQualityScore,
|
|
5778
|
-
mediaType: res.mediaType
|
|
5988
|
+
mediaType: res.mediaType,
|
|
5779
5989
|
}
|
|
5780
5990
|
);
|
|
5781
5991
|
}
|
|
@@ -5787,7 +5997,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5787
5997
|
* @private
|
|
5788
5998
|
* @returns {undefined}
|
|
5789
5999
|
*/
|
|
5790
|
-
private handleMediaLogging({
|
|
6000
|
+
private handleMediaLogging({audioTrack, videoTrack}: any) {
|
|
5791
6001
|
MeetingUtil.handleVideoLogging(videoTrack);
|
|
5792
6002
|
MeetingUtil.handleAudioLogging(audioTrack);
|
|
5793
6003
|
}
|
|
@@ -5817,7 +6027,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5817
6027
|
const start = this[`startSetupDelay${typeMedia}`];
|
|
5818
6028
|
const end = this[`endSetupDelay${typeMedia}`];
|
|
5819
6029
|
|
|
5820
|
-
return
|
|
6030
|
+
return start && end ? end - start : undefined;
|
|
5821
6031
|
}
|
|
5822
6032
|
|
|
5823
6033
|
/**
|
|
@@ -5845,14 +6055,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5845
6055
|
const start = this[`startSendingMediaDelay${typeMedia}`];
|
|
5846
6056
|
const end = this[`endSendingMediaDelay${typeMedia}`];
|
|
5847
6057
|
|
|
5848
|
-
return
|
|
6058
|
+
return start && end ? end - start : undefined;
|
|
5849
6059
|
}
|
|
5850
6060
|
|
|
5851
6061
|
/**
|
|
5852
6062
|
*
|
|
5853
6063
|
* @returns {undefined}
|
|
5854
6064
|
*/
|
|
5855
|
-
|
|
6065
|
+
setStartLocalSDPGenRemoteSDPRecvDelay() {
|
|
5856
6066
|
if (!this.startLocalSDPGenRemoteSDPRecvDelay) {
|
|
5857
6067
|
this.startLocalSDPGenRemoteSDPRecvDelay = performance.now();
|
|
5858
6068
|
this.endLocalSDPGenRemoteSDPRecvDelay = undefined;
|
|
@@ -5880,9 +6090,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5880
6090
|
if (start && end) {
|
|
5881
6091
|
const calculatedDelay = end - start;
|
|
5882
6092
|
|
|
5883
|
-
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
|
|
5884
|
-
undefined :
|
|
5885
|
-
calculatedDelay;
|
|
6093
|
+
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ? undefined : calculatedDelay;
|
|
5886
6094
|
}
|
|
5887
6095
|
|
|
5888
6096
|
return undefined;
|
|
@@ -5916,9 +6124,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5916
6124
|
if (start && end) {
|
|
5917
6125
|
const calculatedDelay = end - start;
|
|
5918
6126
|
|
|
5919
|
-
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
|
|
5920
|
-
undefined :
|
|
5921
|
-
calculatedDelay;
|
|
6127
|
+
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ? undefined : calculatedDelay;
|
|
5922
6128
|
}
|
|
5923
6129
|
|
|
5924
6130
|
return undefined;
|
|
@@ -5952,9 +6158,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5952
6158
|
if (start && end) {
|
|
5953
6159
|
const calculatedDelay = end - start;
|
|
5954
6160
|
|
|
5955
|
-
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
|
|
5956
|
-
undefined :
|
|
5957
|
-
calculatedDelay;
|
|
6161
|
+
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ? undefined : calculatedDelay;
|
|
5958
6162
|
}
|
|
5959
6163
|
|
|
5960
6164
|
return undefined;
|
|
@@ -5968,10 +6172,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5968
6172
|
const start = this.startCallInitiateJoinReq;
|
|
5969
6173
|
const end = this.endJoinReqResp;
|
|
5970
6174
|
|
|
5971
|
-
return
|
|
6175
|
+
return start && end ? end - start : undefined;
|
|
5972
6176
|
}
|
|
5973
6177
|
|
|
5974
|
-
|
|
5975
6178
|
/**
|
|
5976
6179
|
* End the current meeting for all
|
|
5977
6180
|
* @returns {Promise}
|
|
@@ -5979,16 +6182,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5979
6182
|
* @memberof Meeting
|
|
5980
6183
|
*/
|
|
5981
6184
|
public endMeetingForAll() {
|
|
5982
|
-
Metrics.postEvent({
|
|
6185
|
+
Metrics.postEvent({
|
|
6186
|
+
event: eventType.LEAVE,
|
|
6187
|
+
meeting: this,
|
|
6188
|
+
data: {trigger: trigger.USER_INTERACTION, canProceed: false},
|
|
6189
|
+
});
|
|
5983
6190
|
|
|
5984
6191
|
LoggerProxy.logger.log('Meeting:index#endMeetingForAll --> End meeting for All');
|
|
5985
|
-
Metrics.sendBehavioralMetric(
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
locus_id: this.locusId
|
|
5990
|
-
}
|
|
5991
|
-
);
|
|
6192
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_END_ALL_INITIATED, {
|
|
6193
|
+
correlation_id: this.correlationId,
|
|
6194
|
+
locus_id: this.locusId,
|
|
6195
|
+
});
|
|
5992
6196
|
|
|
5993
6197
|
return MeetingUtil.endMeetingForAll(this)
|
|
5994
6198
|
.then((end) => {
|
|
@@ -6000,36 +6204,37 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6000
6204
|
this,
|
|
6001
6205
|
{
|
|
6002
6206
|
file: 'meeting/index',
|
|
6003
|
-
function: 'endMeetingForAll'
|
|
6207
|
+
function: 'endMeetingForAll',
|
|
6004
6208
|
},
|
|
6005
6209
|
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
6006
6210
|
this
|
|
6007
6211
|
);
|
|
6008
6212
|
|
|
6009
6213
|
return end;
|
|
6010
|
-
})
|
|
6214
|
+
})
|
|
6215
|
+
.catch((error) => {
|
|
6011
6216
|
this.meetingFiniteStateMachine.fail(error);
|
|
6012
|
-
LoggerProxy.logger.error(
|
|
6217
|
+
LoggerProxy.logger.error(
|
|
6218
|
+
'Meeting:index#endMeetingForAll --> Failed to end meeting ',
|
|
6219
|
+
error
|
|
6220
|
+
);
|
|
6013
6221
|
// upload logs on leave irrespective of meeting delete
|
|
6014
6222
|
Trigger.trigger(
|
|
6015
6223
|
this,
|
|
6016
6224
|
{
|
|
6017
6225
|
file: 'meeting/index',
|
|
6018
|
-
function: 'endMeetingForAll'
|
|
6226
|
+
function: 'endMeetingForAll',
|
|
6019
6227
|
},
|
|
6020
6228
|
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
6021
6229
|
this
|
|
6022
6230
|
);
|
|
6023
|
-
Metrics.sendBehavioralMetric(
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
code: error.code
|
|
6031
|
-
}
|
|
6032
|
-
);
|
|
6231
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_END_ALL_FAILURE, {
|
|
6232
|
+
correlation_id: this.correlationId,
|
|
6233
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
6234
|
+
reason: error.message,
|
|
6235
|
+
stack: error.stack,
|
|
6236
|
+
code: error.code,
|
|
6237
|
+
});
|
|
6033
6238
|
|
|
6034
6239
|
return Promise.reject(error);
|
|
6035
6240
|
});
|
|
@@ -6079,11 +6284,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6079
6284
|
LoggerProxy.logger.info('Meeting:index#internal_enableBNR. Internal enable BNR called');
|
|
6080
6285
|
const bnrAudioTrack = await WebRTCMedia.Effects.BNR.enableBNR(audioTrack);
|
|
6081
6286
|
|
|
6082
|
-
LoggerProxy.logger.info(
|
|
6287
|
+
LoggerProxy.logger.info(
|
|
6288
|
+
'Meeting:index#internal_enableBNR. BNR enabled track obtained from WebRTC & returned as stream'
|
|
6289
|
+
);
|
|
6083
6290
|
|
|
6084
6291
|
return bnrAudioTrack;
|
|
6085
|
-
}
|
|
6086
|
-
catch (error) {
|
|
6292
|
+
} catch (error) {
|
|
6087
6293
|
LoggerProxy.logger.error('Meeting:index#internal_enableBNR.', error);
|
|
6088
6294
|
throw error;
|
|
6089
6295
|
}
|
|
@@ -6096,7 +6302,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6096
6302
|
* @memberof Meeting
|
|
6097
6303
|
*/
|
|
6098
6304
|
public enableBNR() {
|
|
6099
|
-
if (
|
|
6305
|
+
if (
|
|
6306
|
+
typeof this.mediaProperties === 'undefined' ||
|
|
6307
|
+
typeof this.mediaProperties.audioTrack === 'undefined'
|
|
6308
|
+
) {
|
|
6100
6309
|
return Promise.reject(new Error("Meeting doesn't have an audioTrack attached"));
|
|
6101
6310
|
}
|
|
6102
6311
|
|
|
@@ -6108,20 +6317,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6108
6317
|
|
|
6109
6318
|
const LOG_HEADER = 'Meeting:index#enableBNR -->';
|
|
6110
6319
|
|
|
6111
|
-
return logRequest(
|
|
6112
|
-
.
|
|
6113
|
-
|
|
6320
|
+
return logRequest(
|
|
6321
|
+
this.effects
|
|
6322
|
+
.handleClientRequest(true, this)
|
|
6323
|
+
.then((res) => {
|
|
6324
|
+
LoggerProxy.logger.info('Meeting:index#enableBNR. Enable bnr completed');
|
|
6114
6325
|
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6326
|
+
return res;
|
|
6327
|
+
})
|
|
6328
|
+
.catch((error) => {
|
|
6329
|
+
throw error;
|
|
6330
|
+
}),
|
|
6331
|
+
{
|
|
6332
|
+
header: `${LOG_HEADER} enable bnr`,
|
|
6333
|
+
success: `${LOG_HEADER} enable bnr success`,
|
|
6334
|
+
failure: `${LOG_HEADER} enable bnr failure, `,
|
|
6335
|
+
}
|
|
6336
|
+
);
|
|
6125
6337
|
}
|
|
6126
6338
|
|
|
6127
6339
|
/**
|
|
@@ -6131,7 +6343,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6131
6343
|
* @memberof Meeting
|
|
6132
6344
|
*/
|
|
6133
6345
|
public disableBNR() {
|
|
6134
|
-
if (
|
|
6346
|
+
if (
|
|
6347
|
+
typeof this.mediaProperties === 'undefined' ||
|
|
6348
|
+
typeof this.mediaProperties.audioTrack === 'undefined'
|
|
6349
|
+
) {
|
|
6135
6350
|
return Promise.reject(new Error("Meeting doesn't have an audioTrack attached"));
|
|
6136
6351
|
}
|
|
6137
6352
|
|
|
@@ -6143,20 +6358,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6143
6358
|
|
|
6144
6359
|
const LOG_HEADER = 'Meeting:index#disableBNR -->';
|
|
6145
6360
|
|
|
6146
|
-
return logRequest(
|
|
6147
|
-
.
|
|
6148
|
-
|
|
6361
|
+
return logRequest(
|
|
6362
|
+
this.effects
|
|
6363
|
+
.handleClientRequest(false, this)
|
|
6364
|
+
.then((res) => {
|
|
6365
|
+
LoggerProxy.logger.info('Meeting:index#disableBNR. Disable bnr completed');
|
|
6149
6366
|
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6367
|
+
return res;
|
|
6368
|
+
})
|
|
6369
|
+
.catch((error) => {
|
|
6370
|
+
throw error;
|
|
6371
|
+
}),
|
|
6372
|
+
{
|
|
6373
|
+
header: `${LOG_HEADER} disable bnr`,
|
|
6374
|
+
success: `${LOG_HEADER} disable bnr success`,
|
|
6375
|
+
failure: `${LOG_HEADER} disable bnr failure, `,
|
|
6376
|
+
}
|
|
6377
|
+
);
|
|
6160
6378
|
}
|
|
6161
6379
|
|
|
6162
6380
|
/**
|
|
@@ -6167,22 +6385,30 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6167
6385
|
*/
|
|
6168
6386
|
startKeepAlive = () => {
|
|
6169
6387
|
if (this.keepAliveTimerId) {
|
|
6170
|
-
LoggerProxy.logger.warn(
|
|
6388
|
+
LoggerProxy.logger.warn(
|
|
6389
|
+
'Meeting:index#startKeepAlive --> keepAlive not started: keepAliveTimerId already exists'
|
|
6390
|
+
);
|
|
6171
6391
|
|
|
6172
6392
|
return;
|
|
6173
6393
|
}
|
|
6174
6394
|
if (!this.joinedWith?.keepAliveUrl) {
|
|
6175
|
-
LoggerProxy.logger.warn(
|
|
6395
|
+
LoggerProxy.logger.warn(
|
|
6396
|
+
'Meeting:index#startKeepAlive --> keepAlive not started: no keepAliveUrl'
|
|
6397
|
+
);
|
|
6176
6398
|
|
|
6177
6399
|
return;
|
|
6178
6400
|
}
|
|
6179
6401
|
if (!this.joinedWith?.keepAliveSecs) {
|
|
6180
|
-
LoggerProxy.logger.warn(
|
|
6402
|
+
LoggerProxy.logger.warn(
|
|
6403
|
+
'Meeting:index#startKeepAlive --> keepAlive not started: no keepAliveSecs'
|
|
6404
|
+
);
|
|
6181
6405
|
|
|
6182
6406
|
return;
|
|
6183
6407
|
}
|
|
6184
6408
|
if (this.joinedWith.keepAliveSecs <= 1) {
|
|
6185
|
-
LoggerProxy.logger.warn(
|
|
6409
|
+
LoggerProxy.logger.warn(
|
|
6410
|
+
'Meeting:index#startKeepAlive --> keepAlive not started: keepAliveSecs <= 1'
|
|
6411
|
+
);
|
|
6186
6412
|
|
|
6187
6413
|
return;
|
|
6188
6414
|
}
|
|
@@ -6190,13 +6416,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6190
6416
|
const keepAliveInterval = (this.joinedWith.keepAliveSecs - 1) * 750; // taken from UCF
|
|
6191
6417
|
|
|
6192
6418
|
this.keepAliveTimerId = setInterval(() => {
|
|
6193
|
-
this.meetingRequest.keepAlive({keepAliveUrl})
|
|
6194
|
-
.
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
});
|
|
6419
|
+
this.meetingRequest.keepAlive({keepAliveUrl}).catch((error) => {
|
|
6420
|
+
LoggerProxy.logger.warn(
|
|
6421
|
+
`Meeting:index#startKeepAlive --> Stopping sending keepAlives to ${keepAliveUrl} after error ${error}`
|
|
6422
|
+
);
|
|
6423
|
+
this.stopKeepAlive();
|
|
6424
|
+
});
|
|
6200
6425
|
}, keepAliveInterval);
|
|
6201
6426
|
};
|
|
6202
6427
|
|
|
@@ -6235,7 +6460,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6235
6460
|
const skinToneData = SkinTones[skinToneType] || SkinTones.normal;
|
|
6236
6461
|
const reaction: Reaction = {
|
|
6237
6462
|
...reactionData,
|
|
6238
|
-
tone: skinToneData
|
|
6463
|
+
tone: skinToneData,
|
|
6239
6464
|
};
|
|
6240
6465
|
|
|
6241
6466
|
if (reactionChannelUrl) {
|