@webex/plugin-meetings 3.7.0 → 3.8.0-next.10
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/dist/annotation/index.js +17 -0
- package/dist/annotation/index.js.map +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/join-forbidden-error.js +52 -0
- package/dist/common/errors/join-forbidden-error.js.map +1 -0
- package/dist/common/errors/{webinar-registration-error.js → join-webinar-error.js} +12 -12
- package/dist/common/errors/join-webinar-error.js.map +1 -0
- package/dist/common/errors/multistream-not-supported-error.js +53 -0
- package/dist/common/errors/multistream-not-supported-error.js.map +1 -0
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +69 -6
- package/dist/constants.js.map +1 -1
- package/dist/index.js +16 -11
- package/dist/index.js.map +1 -1
- package/dist/interpretation/index.js +4 -4
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +14 -3
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +35 -17
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +1 -0
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/properties.js +30 -16
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/brbState.js +167 -0
- package/dist/meeting/brbState.js.map +1 -0
- package/dist/meeting/in-meeting-actions.js +13 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1373 -1052
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +32 -11
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +1 -6
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +51 -29
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +103 -67
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +115 -45
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/utilv2.js +6 -2
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/index.js +107 -55
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +2 -0
- package/dist/meetings/meetings.types.js.map +1 -1
- package/dist/meetings/util.js +1 -1
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +9 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js.map +1 -1
- package/dist/member/util.js +39 -28
- package/dist/member/util.js.map +1 -1
- package/dist/members/util.js +4 -2
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +6 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/remoteMedia.js +30 -15
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +40 -8
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +24 -0
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/reachability/clusterReachability.js +12 -15
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +471 -140
- package/dist/reachability/index.js.map +1 -1
- package/dist/{rtcMetrics/constants.js → reachability/reachability.types.js} +1 -5
- package/dist/reachability/reachability.types.js.map +1 -0
- package/dist/reachability/request.js +21 -8
- package/dist/reachability/request.js.map +1 -1
- package/dist/recording-controller/enums.js +8 -4
- package/dist/recording-controller/enums.js.map +1 -1
- package/dist/recording-controller/index.js +18 -9
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +13 -9
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +15 -15
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +45 -79
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +3 -6
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/types/annotation/index.d.ts +5 -0
- package/dist/types/common/errors/join-forbidden-error.d.ts +15 -0
- package/dist/types/common/errors/{webinar-registration-error.d.ts → join-webinar-error.d.ts} +2 -2
- package/dist/types/common/errors/multistream-not-supported-error.d.ts +17 -0
- package/dist/types/config.d.ts +2 -0
- package/dist/types/constants.d.ts +54 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/locus-info/index.d.ts +2 -1
- package/dist/types/meeting/brbState.d.ts +54 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +12 -0
- package/dist/types/meeting/index.d.ts +86 -14
- package/dist/types/meeting/locusMediaRequest.d.ts +6 -3
- package/dist/types/meeting/request.d.ts +14 -3
- package/dist/types/meeting/request.type.d.ts +6 -0
- package/dist/types/meeting/util.d.ts +3 -3
- package/dist/types/meeting-info/meeting-info-v2.d.ts +30 -5
- package/dist/types/meetings/index.d.ts +20 -2
- package/dist/types/meetings/meetings.types.d.ts +8 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/types.d.ts +7 -0
- package/dist/types/members/util.d.ts +2 -0
- package/dist/types/metrics/constants.d.ts +6 -1
- package/dist/types/multistream/remoteMediaManager.d.ts +10 -1
- package/dist/types/multistream/sendSlotManager.d.ts +8 -1
- package/dist/types/reachability/clusterReachability.d.ts +1 -10
- package/dist/types/reachability/index.d.ts +83 -36
- package/dist/types/reachability/reachability.types.d.ts +64 -0
- package/dist/types/reachability/request.d.ts +5 -1
- package/dist/types/recording-controller/enums.d.ts +5 -2
- package/dist/types/recording-controller/index.d.ts +1 -0
- package/dist/types/recording-controller/util.d.ts +2 -1
- package/dist/types/roap/request.d.ts +1 -13
- package/dist/webinar/index.js +390 -7
- package/dist/webinar/index.js.map +1 -1
- package/package.json +23 -22
- package/src/annotation/index.ts +16 -0
- package/src/common/errors/join-forbidden-error.ts +26 -0
- package/src/common/errors/join-webinar-error.ts +24 -0
- package/src/common/errors/multistream-not-supported-error.ts +30 -0
- package/src/config.ts +2 -0
- package/src/constants.ts +62 -3
- package/src/index.ts +5 -3
- package/src/interpretation/index.ts +3 -3
- package/src/locus-info/index.ts +20 -3
- package/src/locus-info/selfUtils.ts +24 -6
- package/src/media/MediaConnectionAwaiter.ts +2 -0
- package/src/media/properties.ts +34 -13
- package/src/meeting/brbState.ts +169 -0
- package/src/meeting/in-meeting-actions.ts +25 -0
- package/src/meeting/index.ts +485 -88
- package/src/meeting/locusMediaRequest.ts +38 -12
- package/src/meeting/muteState.ts +1 -6
- package/src/meeting/request.ts +30 -12
- package/src/meeting/request.type.ts +7 -0
- package/src/meeting/util.ts +32 -13
- package/src/meeting-info/meeting-info-v2.ts +83 -12
- package/src/meeting-info/utilv2.ts +17 -3
- package/src/meetings/index.ts +79 -20
- package/src/meetings/meetings.types.ts +10 -0
- package/src/meetings/util.ts +2 -1
- package/src/member/index.ts +9 -0
- package/src/member/types.ts +8 -0
- package/src/member/util.ts +34 -24
- package/src/members/util.ts +1 -0
- package/src/metrics/constants.ts +6 -1
- package/src/multistream/remoteMedia.ts +28 -15
- package/src/multistream/remoteMediaManager.ts +32 -10
- package/src/multistream/sendSlotManager.ts +31 -0
- package/src/reachability/clusterReachability.ts +5 -15
- package/src/reachability/index.ts +315 -75
- package/src/reachability/reachability.types.ts +85 -0
- package/src/reachability/request.ts +55 -31
- package/src/recording-controller/enums.ts +5 -2
- package/src/recording-controller/index.ts +17 -4
- package/src/recording-controller/util.ts +28 -9
- package/src/roap/index.ts +14 -13
- package/src/roap/request.ts +30 -44
- package/src/roap/turnDiscovery.ts +2 -4
- package/src/webinar/index.ts +235 -9
- package/test/unit/spec/annotation/index.ts +46 -1
- package/test/unit/spec/interpretation/index.ts +39 -1
- package/test/unit/spec/locus-info/index.js +292 -60
- package/test/unit/spec/locus-info/selfConstant.js +7 -0
- package/test/unit/spec/locus-info/selfUtils.js +101 -1
- package/test/unit/spec/media/properties.ts +15 -0
- package/test/unit/spec/meeting/brbState.ts +114 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +15 -1
- package/test/unit/spec/meeting/index.js +908 -124
- package/test/unit/spec/meeting/locusMediaRequest.ts +111 -66
- package/test/unit/spec/meeting/muteState.js +0 -24
- package/test/unit/spec/meeting/request.js +3 -26
- package/test/unit/spec/meeting/utils.js +73 -28
- package/test/unit/spec/meeting-info/meetinginfov2.js +46 -4
- package/test/unit/spec/meeting-info/utilv2.js +26 -0
- package/test/unit/spec/meetings/index.js +172 -18
- package/test/unit/spec/meetings/utils.js +10 -0
- package/test/unit/spec/member/util.js +52 -11
- package/test/unit/spec/members/utils.js +95 -0
- package/test/unit/spec/multistream/remoteMedia.ts +11 -7
- package/test/unit/spec/multistream/remoteMediaManager.ts +397 -118
- package/test/unit/spec/reachability/clusterReachability.ts +7 -0
- package/test/unit/spec/reachability/index.ts +391 -9
- package/test/unit/spec/reachability/request.js +48 -12
- package/test/unit/spec/recording-controller/index.js +61 -5
- package/test/unit/spec/recording-controller/util.js +39 -3
- package/test/unit/spec/roap/index.ts +48 -1
- package/test/unit/spec/roap/request.ts +51 -109
- package/test/unit/spec/roap/turnDiscovery.ts +202 -147
- package/test/unit/spec/webinar/index.ts +509 -0
- package/dist/common/errors/webinar-registration-error.js.map +0 -1
- package/dist/networkQualityMonitor/index.js +0 -227
- package/dist/networkQualityMonitor/index.js.map +0 -1
- package/dist/rtcMetrics/constants.js.map +0 -1
- package/dist/rtcMetrics/index.js +0 -197
- package/dist/rtcMetrics/index.js.map +0 -1
- package/dist/types/networkQualityMonitor/index.d.ts +0 -70
- package/dist/types/rtcMetrics/constants.d.ts +0 -4
- package/dist/types/rtcMetrics/index.d.ts +0 -71
- package/src/common/errors/webinar-registration-error.ts +0 -27
package/src/meetings/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint no-shadow: ["error", { "allow": ["eventType"] }] */
|
|
2
|
-
import {cloneDeep} from 'lodash';
|
|
2
|
+
import {cloneDeep, clone} from 'lodash';
|
|
3
3
|
import '@webex/internal-plugin-mercury';
|
|
4
4
|
import '@webex/internal-plugin-conversation';
|
|
5
5
|
import '@webex/internal-plugin-metrics';
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
_ON_HOLD_LOBBY_,
|
|
43
43
|
_WAIT_,
|
|
44
44
|
DESTINATION_TYPE,
|
|
45
|
+
INITIAL_REGISTRATION_STATUS,
|
|
45
46
|
} from '../constants';
|
|
46
47
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
47
48
|
import MeetingInfo from '../meeting-info';
|
|
@@ -53,12 +54,18 @@ import Request from './request';
|
|
|
53
54
|
import PasswordError from '../common/errors/password-error';
|
|
54
55
|
import CaptchaError from '../common/errors/captcha-error';
|
|
55
56
|
import MeetingCollection from './collection';
|
|
56
|
-
import {
|
|
57
|
+
import {
|
|
58
|
+
MEETING_KEY,
|
|
59
|
+
INoiseReductionEffect,
|
|
60
|
+
IVirtualBackgroundEffect,
|
|
61
|
+
MeetingRegistrationStatus,
|
|
62
|
+
} from './meetings.types';
|
|
57
63
|
import MeetingsUtil from './util';
|
|
58
64
|
import PermissionError from '../common/errors/permission';
|
|
59
|
-
import
|
|
65
|
+
import JoinWebinarError from '../common/errors/join-webinar-error';
|
|
60
66
|
import {SpaceIDDeprecatedError} from '../common/errors/webex-errors';
|
|
61
67
|
import NoMeetingInfoError from '../common/errors/no-meeting-info';
|
|
68
|
+
import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
|
62
69
|
|
|
63
70
|
let mediaLogger;
|
|
64
71
|
|
|
@@ -155,6 +162,9 @@ export type BasicMeetingInformation = {
|
|
|
155
162
|
};
|
|
156
163
|
meetingInfo: any;
|
|
157
164
|
sessionCorrelationId: string;
|
|
165
|
+
roles: string[];
|
|
166
|
+
getCurUserType: () => string | null;
|
|
167
|
+
callStateForMetrics: CallStateForMetrics;
|
|
158
168
|
};
|
|
159
169
|
|
|
160
170
|
/**
|
|
@@ -176,6 +186,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
176
186
|
mediaHelpers: any;
|
|
177
187
|
breakoutLocusForHandleLater: any;
|
|
178
188
|
namespace = MEETINGS;
|
|
189
|
+
registrationStatus: MeetingRegistrationStatus;
|
|
179
190
|
|
|
180
191
|
/**
|
|
181
192
|
* Initializes the Meetings Plugin
|
|
@@ -689,6 +700,20 @@ export default class Meetings extends WebexPlugin {
|
|
|
689
700
|
});
|
|
690
701
|
}
|
|
691
702
|
|
|
703
|
+
/**
|
|
704
|
+
* API to change log upload interval. Setting the factor to 0 will disable periodic log uploads.
|
|
705
|
+
*
|
|
706
|
+
* @param {number} factor new factor value
|
|
707
|
+
* @returns {void}
|
|
708
|
+
*/
|
|
709
|
+
private _setLogUploadIntervalMultiplicationFactor(factor: number) {
|
|
710
|
+
if (typeof factor !== 'number') {
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
// @ts-ignore
|
|
714
|
+
this.config.logUploadIntervalMultiplicationFactor = factor;
|
|
715
|
+
}
|
|
716
|
+
|
|
692
717
|
/**
|
|
693
718
|
* API to toggle unified meetings
|
|
694
719
|
* @param {Boolean} changeState
|
|
@@ -782,6 +807,18 @@ export default class Meetings extends WebexPlugin {
|
|
|
782
807
|
}
|
|
783
808
|
}
|
|
784
809
|
|
|
810
|
+
/**
|
|
811
|
+
* Executes a registration step and updates the registration status.
|
|
812
|
+
* @param {Function} step - The registration step to execute.
|
|
813
|
+
* @param {string} stepName - The name of the registration step.
|
|
814
|
+
* @returns {Promise} A promise that resolves when the step is completed.
|
|
815
|
+
*/
|
|
816
|
+
executeRegistrationStep(step: () => Promise<any>, stepName: string) {
|
|
817
|
+
return step().then(() => {
|
|
818
|
+
this.registrationStatus[stepName] = true;
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
|
|
785
822
|
/**
|
|
786
823
|
* Explicitly sets up the meetings plugin by registering
|
|
787
824
|
* the device, connecting to mercury, and listening for locus events.
|
|
@@ -792,6 +829,8 @@ export default class Meetings extends WebexPlugin {
|
|
|
792
829
|
* @memberof Meetings
|
|
793
830
|
*/
|
|
794
831
|
public register(deviceRegistrationOptions?: DeviceRegistrationOptions): Promise<any> {
|
|
832
|
+
this.registrationStatus = clone(INITIAL_REGISTRATION_STATUS);
|
|
833
|
+
|
|
795
834
|
// @ts-ignore
|
|
796
835
|
if (!this.webex.canAuthorize) {
|
|
797
836
|
LoggerProxy.logger.error(
|
|
@@ -810,24 +849,39 @@ export default class Meetings extends WebexPlugin {
|
|
|
810
849
|
}
|
|
811
850
|
|
|
812
851
|
return Promise.all([
|
|
813
|
-
this.fetchUserPreferredWebexSite(),
|
|
814
|
-
this.getGeoHint(),
|
|
815
|
-
this.
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
852
|
+
this.executeRegistrationStep(() => this.fetchUserPreferredWebexSite(), 'fetchWebexSite'),
|
|
853
|
+
this.executeRegistrationStep(() => this.getGeoHint(), 'getGeoHint'),
|
|
854
|
+
this.executeRegistrationStep(
|
|
855
|
+
() =>
|
|
856
|
+
this.startReachability('registration').catch((error) => {
|
|
857
|
+
LoggerProxy.logger.warn(`Meetings:index#register --> startReachability failed:`, error);
|
|
858
|
+
}),
|
|
859
|
+
'startReachability'
|
|
860
|
+
),
|
|
861
|
+
this.executeRegistrationStep(
|
|
862
|
+
() =>
|
|
863
|
+
// @ts-ignore
|
|
864
|
+
this.webex.internal.device
|
|
865
|
+
.register(deviceRegistrationOptions)
|
|
824
866
|
// @ts-ignore
|
|
825
|
-
|
|
826
|
-
|
|
867
|
+
.then(() => {
|
|
868
|
+
LoggerProxy.logger.info(
|
|
869
|
+
// @ts-ignore
|
|
870
|
+
`Meetings:index#register --> INFO, Device registered ${this.webex.internal.device.url}`
|
|
871
|
+
);
|
|
872
|
+
}),
|
|
873
|
+
'deviceRegister'
|
|
874
|
+
).then(() =>
|
|
875
|
+
this.executeRegistrationStep(
|
|
876
|
+
// @ts-ignore
|
|
877
|
+
() => this.webex.internal.mercury.connect(),
|
|
878
|
+
'mercuryConnect'
|
|
827
879
|
)
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
880
|
+
),
|
|
881
|
+
this.executeRegistrationStep(
|
|
882
|
+
() => Promise.resolve(MeetingsUtil.checkH264Support.call(this)),
|
|
883
|
+
'checkH264Support'
|
|
884
|
+
),
|
|
831
885
|
])
|
|
832
886
|
.then(() => {
|
|
833
887
|
this.listenForEvents();
|
|
@@ -891,6 +945,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
891
945
|
EVENT_TRIGGERS.MEETINGS_UNREGISTERED
|
|
892
946
|
);
|
|
893
947
|
this.registered = false;
|
|
948
|
+
this.registrationStatus = clone(INITIAL_REGISTRATION_STATUS);
|
|
894
949
|
})
|
|
895
950
|
);
|
|
896
951
|
}
|
|
@@ -1143,6 +1198,9 @@ export default class Meetings extends WebexPlugin {
|
|
|
1143
1198
|
sessionId: meeting.locusInfo?.fullState?.sessionId,
|
|
1144
1199
|
},
|
|
1145
1200
|
},
|
|
1201
|
+
roles: meeting.roles,
|
|
1202
|
+
callStateForMetrics: meeting.callStateForMetrics,
|
|
1203
|
+
getCurUserType: meeting.getCurUserType,
|
|
1146
1204
|
});
|
|
1147
1205
|
this.meetingCollection.delete(meeting.id);
|
|
1148
1206
|
Trigger.trigger(
|
|
@@ -1406,7 +1464,8 @@ export default class Meetings extends WebexPlugin {
|
|
|
1406
1464
|
!(err instanceof CaptchaError) &&
|
|
1407
1465
|
!(err instanceof PasswordError) &&
|
|
1408
1466
|
!(err instanceof PermissionError) &&
|
|
1409
|
-
!(err instanceof
|
|
1467
|
+
!(err instanceof JoinWebinarError) &&
|
|
1468
|
+
!(err instanceof JoinForbiddenError)
|
|
1410
1469
|
) {
|
|
1411
1470
|
LoggerProxy.logger.info(
|
|
1412
1471
|
`Meetings:index#createMeeting --> Info Unable to fetch meeting info for ${destination}.`
|
|
@@ -21,3 +21,13 @@ export const MEETING_KEY = {
|
|
|
21
21
|
} as const;
|
|
22
22
|
|
|
23
23
|
export type MEETING_KEY = Enum<typeof MEETING_KEY>;
|
|
24
|
+
|
|
25
|
+
// finer grained status for registration steps
|
|
26
|
+
export type MeetingRegistrationStatus = {
|
|
27
|
+
fetchWebexSite: boolean;
|
|
28
|
+
getGeoHint: boolean;
|
|
29
|
+
startReachability: boolean;
|
|
30
|
+
deviceRegister: boolean;
|
|
31
|
+
mercuryConnect: boolean;
|
|
32
|
+
checkH264Support: boolean;
|
|
33
|
+
};
|
package/src/meetings/util.ts
CHANGED
package/src/member/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ export default class Member {
|
|
|
28
28
|
isRecording: any;
|
|
29
29
|
isRemovable: any;
|
|
30
30
|
isSelf: any;
|
|
31
|
+
isBrb: boolean;
|
|
31
32
|
isUser: any;
|
|
32
33
|
isVideoMuted: any;
|
|
33
34
|
roles: IExternalRoles;
|
|
@@ -227,6 +228,13 @@ export default class Member {
|
|
|
227
228
|
* @memberof Member
|
|
228
229
|
*/
|
|
229
230
|
this.isRemovable = null;
|
|
231
|
+
/**
|
|
232
|
+
* @instance
|
|
233
|
+
* @type {Boolean}
|
|
234
|
+
* @public
|
|
235
|
+
* @memberof Member
|
|
236
|
+
*/
|
|
237
|
+
this.isBrb = false;
|
|
230
238
|
/**
|
|
231
239
|
* @instance
|
|
232
240
|
* @type {String}
|
|
@@ -295,6 +303,7 @@ export default class Member {
|
|
|
295
303
|
this.supportsInterpretation = MemberUtil.isInterpretationSupported(participant);
|
|
296
304
|
this.supportLiveAnnotation = MemberUtil.isLiveAnnotationSupported(participant);
|
|
297
305
|
this.isGuest = MemberUtil.isGuest(participant);
|
|
306
|
+
this.isBrb = MemberUtil.isBrb(participant);
|
|
298
307
|
this.isUser = MemberUtil.isUser(participant);
|
|
299
308
|
this.isDevice = MemberUtil.isDevice(participant);
|
|
300
309
|
this.isModerator = MemberUtil.isModerator(participant);
|
package/src/member/types.ts
CHANGED
|
@@ -23,6 +23,14 @@ export type ParticipantWithRoles = {
|
|
|
23
23
|
};
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
export type ParticipantWithBrb = {
|
|
27
|
+
controls: {
|
|
28
|
+
brb?: {
|
|
29
|
+
enabled: boolean;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
26
34
|
// values are inherited from locus so don't update these
|
|
27
35
|
export enum MediaStatus {
|
|
28
36
|
RECVONLY = 'RECVONLY', // participant only receiving and not sending
|
package/src/member/util.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ServerRoles,
|
|
5
5
|
ServerRoleShape,
|
|
6
6
|
IMediaStatus,
|
|
7
|
+
ParticipantWithBrb,
|
|
7
8
|
} from './types';
|
|
8
9
|
import {
|
|
9
10
|
_USER_,
|
|
@@ -29,7 +30,7 @@ import ParameterError from '../common/errors/parameter';
|
|
|
29
30
|
const MemberUtil: any = {};
|
|
30
31
|
|
|
31
32
|
/**
|
|
32
|
-
* @param {Object} participant
|
|
33
|
+
* @param {Object} participant - The locus participant object.
|
|
33
34
|
* @returns {Boolean}
|
|
34
35
|
*/
|
|
35
36
|
MemberUtil.canReclaimHost = (participant) => {
|
|
@@ -43,14 +44,23 @@ MemberUtil.canReclaimHost = (participant) => {
|
|
|
43
44
|
};
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
|
-
* @param {Object} participant
|
|
47
|
+
* @param {Object} participant - The locus participant object.
|
|
47
48
|
* @returns {[ServerRoleShape]}
|
|
48
49
|
*/
|
|
49
50
|
MemberUtil.getControlsRoles = (participant: ParticipantWithRoles): Array<ServerRoleShape> =>
|
|
50
51
|
participant?.controls?.role?.roles;
|
|
51
52
|
|
|
52
53
|
/**
|
|
53
|
-
*
|
|
54
|
+
* Checks if the participant has the brb status enabled.
|
|
55
|
+
*
|
|
56
|
+
* @param {ParticipantWithBrb} participant - The locus participant object.
|
|
57
|
+
* @returns {boolean} - True if the participant has brb enabled, false otherwise.
|
|
58
|
+
*/
|
|
59
|
+
MemberUtil.isBrb = (participant: ParticipantWithBrb): boolean =>
|
|
60
|
+
participant.controls?.brb?.enabled || false;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {Object} participant - The locus participant object.
|
|
54
64
|
* @param {ServerRoles} controlRole the search role
|
|
55
65
|
* @returns {Boolean}
|
|
56
66
|
*/
|
|
@@ -60,28 +70,28 @@ MemberUtil.hasRole = (participant: any, controlRole: ServerRoles): boolean =>
|
|
|
60
70
|
);
|
|
61
71
|
|
|
62
72
|
/**
|
|
63
|
-
* @param {Object} participant
|
|
73
|
+
* @param {Object} participant - The locus participant object.
|
|
64
74
|
* @returns {Boolean}
|
|
65
75
|
*/
|
|
66
76
|
MemberUtil.hasCohost = (participant: ParticipantWithRoles): boolean =>
|
|
67
77
|
MemberUtil.hasRole(participant, ServerRoles.Cohost) || false;
|
|
68
78
|
|
|
69
79
|
/**
|
|
70
|
-
* @param {Object} participant
|
|
80
|
+
* @param {Object} participant - The locus participant object.
|
|
71
81
|
* @returns {Boolean}
|
|
72
82
|
*/
|
|
73
83
|
MemberUtil.hasModerator = (participant: ParticipantWithRoles): boolean =>
|
|
74
84
|
MemberUtil.hasRole(participant, ServerRoles.Moderator) || false;
|
|
75
85
|
|
|
76
86
|
/**
|
|
77
|
-
* @param {Object} participant
|
|
87
|
+
* @param {Object} participant - The locus participant object.
|
|
78
88
|
* @returns {Boolean}
|
|
79
89
|
*/
|
|
80
90
|
MemberUtil.hasPresenter = (participant: ParticipantWithRoles): boolean =>
|
|
81
91
|
MemberUtil.hasRole(participant, ServerRoles.Presenter) || false;
|
|
82
92
|
|
|
83
93
|
/**
|
|
84
|
-
* @param {Object} participant
|
|
94
|
+
* @param {Object} participant - The locus participant object.
|
|
85
95
|
* @returns {IExternalRoles}
|
|
86
96
|
*/
|
|
87
97
|
MemberUtil.extractControlRoles = (participant: ParticipantWithRoles): IExternalRoles => {
|
|
@@ -95,7 +105,7 @@ MemberUtil.extractControlRoles = (participant: ParticipantWithRoles): IExternalR
|
|
|
95
105
|
};
|
|
96
106
|
|
|
97
107
|
/**
|
|
98
|
-
* @param {Object} participant
|
|
108
|
+
* @param {Object} participant - The locus participant object.
|
|
99
109
|
* @returns {Boolean}
|
|
100
110
|
*/
|
|
101
111
|
MemberUtil.isUser = (participant: any) => participant && participant.type === _USER_;
|
|
@@ -103,13 +113,13 @@ MemberUtil.isUser = (participant: any) => participant && participant.type === _U
|
|
|
103
113
|
MemberUtil.isModerator = (participant) => participant && participant.moderator;
|
|
104
114
|
|
|
105
115
|
/**
|
|
106
|
-
* @param {Object} participant
|
|
116
|
+
* @param {Object} participant - The locus participant object.
|
|
107
117
|
* @returns {Boolean}
|
|
108
118
|
*/
|
|
109
119
|
MemberUtil.isGuest = (participant: any) => participant && participant.guest;
|
|
110
120
|
|
|
111
121
|
/**
|
|
112
|
-
* @param {Object} participant
|
|
122
|
+
* @param {Object} participant - The locus participant object.
|
|
113
123
|
* @returns {Boolean}
|
|
114
124
|
*/
|
|
115
125
|
MemberUtil.isDevice = (participant: any) => participant && participant.type === _RESOURCE_ROOM_;
|
|
@@ -120,7 +130,7 @@ MemberUtil.isModeratorAssignmentProhibited = (participant) =>
|
|
|
120
130
|
/**
|
|
121
131
|
* checks to see if the participant id is the same as the passed id
|
|
122
132
|
* there are multiple ids that can be used
|
|
123
|
-
* @param {Object} participant
|
|
133
|
+
* @param {Object} participant - The locus participant object.
|
|
124
134
|
* @param {String} id
|
|
125
135
|
* @returns {Boolean}
|
|
126
136
|
*/
|
|
@@ -130,7 +140,7 @@ MemberUtil.isSame = (participant: any, id: string) =>
|
|
|
130
140
|
/**
|
|
131
141
|
* checks to see if the participant id is the same as the passed id for associated devices
|
|
132
142
|
* there are multiple ids that can be used
|
|
133
|
-
* @param {Object} participant
|
|
143
|
+
* @param {Object} participant - The locus participant object.
|
|
134
144
|
* @param {String} id
|
|
135
145
|
* @returns {Boolean}
|
|
136
146
|
*/
|
|
@@ -142,7 +152,7 @@ MemberUtil.isAssociatedSame = (participant: any, id: string) =>
|
|
|
142
152
|
);
|
|
143
153
|
|
|
144
154
|
/**
|
|
145
|
-
* @param {Object} participant
|
|
155
|
+
* @param {Object} participant - The locus participant object.
|
|
146
156
|
* @param {Boolean} isGuest
|
|
147
157
|
* @param {String} status
|
|
148
158
|
* @returns {Boolean}
|
|
@@ -161,7 +171,7 @@ MemberUtil.isNotAdmitted = (participant: any, isGuest: boolean, status: string):
|
|
|
161
171
|
!status === _IN_MEETING_);
|
|
162
172
|
|
|
163
173
|
/**
|
|
164
|
-
* @param {Object} participant
|
|
174
|
+
* @param {Object} participant - The locus participant object.
|
|
165
175
|
* @returns {Boolean}
|
|
166
176
|
*/
|
|
167
177
|
MemberUtil.isAudioMuted = (participant: any) => {
|
|
@@ -173,7 +183,7 @@ MemberUtil.isAudioMuted = (participant: any) => {
|
|
|
173
183
|
};
|
|
174
184
|
|
|
175
185
|
/**
|
|
176
|
-
* @param {Object} participant
|
|
186
|
+
* @param {Object} participant - The locus participant object.
|
|
177
187
|
* @returns {Boolean}
|
|
178
188
|
*/
|
|
179
189
|
MemberUtil.isVideoMuted = (participant: any): boolean => {
|
|
@@ -185,7 +195,7 @@ MemberUtil.isVideoMuted = (participant: any): boolean => {
|
|
|
185
195
|
};
|
|
186
196
|
|
|
187
197
|
/**
|
|
188
|
-
* @param {Object} participant
|
|
198
|
+
* @param {Object} participant - The locus participant object.
|
|
189
199
|
* @returns {Boolean}
|
|
190
200
|
*/
|
|
191
201
|
MemberUtil.isHandRaised = (participant: any) => {
|
|
@@ -197,7 +207,7 @@ MemberUtil.isHandRaised = (participant: any) => {
|
|
|
197
207
|
};
|
|
198
208
|
|
|
199
209
|
/**
|
|
200
|
-
* @param {Object} participant
|
|
210
|
+
* @param {Object} participant - The locus participant object.
|
|
201
211
|
* @returns {Boolean}
|
|
202
212
|
*/
|
|
203
213
|
MemberUtil.isBreakoutsSupported = (participant) => {
|
|
@@ -209,7 +219,7 @@ MemberUtil.isBreakoutsSupported = (participant) => {
|
|
|
209
219
|
};
|
|
210
220
|
|
|
211
221
|
/**
|
|
212
|
-
* @param {Object} participant
|
|
222
|
+
* @param {Object} participant - The locus participant object.
|
|
213
223
|
* @returns {Boolean}
|
|
214
224
|
*/
|
|
215
225
|
MemberUtil.isInterpretationSupported = (participant) => {
|
|
@@ -223,7 +233,7 @@ MemberUtil.isInterpretationSupported = (participant) => {
|
|
|
223
233
|
};
|
|
224
234
|
|
|
225
235
|
/**
|
|
226
|
-
* @param {Object} participant
|
|
236
|
+
* @param {Object} participant - The locus participant object.
|
|
227
237
|
* @returns {Boolean}
|
|
228
238
|
*/
|
|
229
239
|
MemberUtil.isLiveAnnotationSupported = (participant) => {
|
|
@@ -279,7 +289,7 @@ MemberUtil.getRecordingMember = (controls: any) => {
|
|
|
279
289
|
};
|
|
280
290
|
|
|
281
291
|
/**
|
|
282
|
-
* @param {Object} participant
|
|
292
|
+
* @param {Object} participant - The locus participant object.
|
|
283
293
|
* @returns {Boolean}
|
|
284
294
|
*/
|
|
285
295
|
MemberUtil.isRecording = (participant: any) => {
|
|
@@ -325,7 +335,7 @@ MemberUtil.isMutable = (isSelf, isDevice, isInMeeting, isMuted, type) => {
|
|
|
325
335
|
};
|
|
326
336
|
|
|
327
337
|
/**
|
|
328
|
-
* @param {Object} participant
|
|
338
|
+
* @param {Object} participant - The locus participant object.
|
|
329
339
|
* @returns {String}
|
|
330
340
|
*/
|
|
331
341
|
MemberUtil.extractStatus = (participant: any) => {
|
|
@@ -355,7 +365,7 @@ MemberUtil.extractStatus = (participant: any) => {
|
|
|
355
365
|
};
|
|
356
366
|
|
|
357
367
|
/**
|
|
358
|
-
* @param {Object} participant
|
|
368
|
+
* @param {Object} participant - The locus participant object.
|
|
359
369
|
* @returns {String}
|
|
360
370
|
*/
|
|
361
371
|
MemberUtil.extractId = (participant: any) => {
|
|
@@ -368,7 +378,7 @@ MemberUtil.extractId = (participant: any) => {
|
|
|
368
378
|
|
|
369
379
|
/**
|
|
370
380
|
* extracts the media status from nested participant object
|
|
371
|
-
* @param {Object} participant
|
|
381
|
+
* @param {Object} participant - The locus participant object.
|
|
372
382
|
* @returns {Object}
|
|
373
383
|
*/
|
|
374
384
|
MemberUtil.extractMediaStatus = (participant: any): IMediaStatus => {
|
|
@@ -383,7 +393,7 @@ MemberUtil.extractMediaStatus = (participant: any): IMediaStatus => {
|
|
|
383
393
|
};
|
|
384
394
|
|
|
385
395
|
/**
|
|
386
|
-
* @param {Object} participant
|
|
396
|
+
* @param {Object} participant - The locus participant object.
|
|
387
397
|
* @returns {String}
|
|
388
398
|
*/
|
|
389
399
|
MemberUtil.extractName = (participant: any) => {
|
package/src/members/util.ts
CHANGED
package/src/metrics/constants.ts
CHANGED
|
@@ -70,7 +70,12 @@ const BEHAVIORAL_METRICS = {
|
|
|
70
70
|
ROAP_HTTP_RESPONSE_MISSING: 'js_sdk_roap_http_response_missing',
|
|
71
71
|
TURN_DISCOVERY_REQUIRES_OK: 'js_sdk_turn_discovery_requires_ok',
|
|
72
72
|
REACHABILITY_COMPLETED: 'js_sdk_reachability_completed',
|
|
73
|
-
|
|
73
|
+
JOIN_WEBINAR_ERROR: 'js_sdk_join_webinar_error',
|
|
74
|
+
GUEST_ENTERED_LOBBY: 'js_sdk_guest_entered_lobby',
|
|
75
|
+
GUEST_EXITED_LOBBY: 'js_sdk_guest_exited_lobby',
|
|
76
|
+
VERIFY_REGISTRATION_ID_SUCCESS: 'js_sdk_verify_registrationId_success',
|
|
77
|
+
VERIFY_REGISTRATION_ID_ERROR: 'js_sdk_verify_registrationId_error',
|
|
78
|
+
JOIN_FORBIDDEN_ERROR: 'js_sdk_join_forbidden_error',
|
|
74
79
|
};
|
|
75
80
|
|
|
76
81
|
export {BEHAVIORAL_METRICS as default};
|
|
@@ -19,6 +19,14 @@ export type RemoteVideoResolution =
|
|
|
19
19
|
| 'large' // 1080p or less
|
|
20
20
|
| 'best'; // highest possible resolution
|
|
21
21
|
|
|
22
|
+
const MAX_FS_VALUES = {
|
|
23
|
+
'90p': 60,
|
|
24
|
+
'180p': 240,
|
|
25
|
+
'360p': 920,
|
|
26
|
+
'720p': 3600,
|
|
27
|
+
'1080p': 8192,
|
|
28
|
+
};
|
|
29
|
+
|
|
22
30
|
/**
|
|
23
31
|
* Converts pane size into h264 maxFs
|
|
24
32
|
* @param {PaneSize} paneSize
|
|
@@ -29,28 +37,28 @@ export function getMaxFs(paneSize: RemoteVideoResolution): number {
|
|
|
29
37
|
|
|
30
38
|
switch (paneSize) {
|
|
31
39
|
case 'thumbnail':
|
|
32
|
-
maxFs =
|
|
40
|
+
maxFs = MAX_FS_VALUES['90p'];
|
|
33
41
|
break;
|
|
34
42
|
case 'very small':
|
|
35
|
-
maxFs =
|
|
43
|
+
maxFs = MAX_FS_VALUES['180p'];
|
|
36
44
|
break;
|
|
37
45
|
case 'small':
|
|
38
|
-
maxFs =
|
|
46
|
+
maxFs = MAX_FS_VALUES['360p'];
|
|
39
47
|
break;
|
|
40
48
|
case 'medium':
|
|
41
|
-
maxFs =
|
|
49
|
+
maxFs = MAX_FS_VALUES['720p'];
|
|
42
50
|
break;
|
|
43
51
|
case 'large':
|
|
44
|
-
maxFs =
|
|
52
|
+
maxFs = MAX_FS_VALUES['1080p'];
|
|
45
53
|
break;
|
|
46
54
|
case 'best':
|
|
47
|
-
maxFs =
|
|
55
|
+
maxFs = MAX_FS_VALUES['1080p']; // for now 'best' is 1080p, so same as 'large'
|
|
48
56
|
break;
|
|
49
57
|
default:
|
|
50
58
|
LoggerProxy.logger.warn(
|
|
51
59
|
`RemoteMedia#getMaxFs --> unsupported paneSize: ${paneSize}, using "medium" instead`
|
|
52
60
|
);
|
|
53
|
-
maxFs =
|
|
61
|
+
maxFs = MAX_FS_VALUES['720p'];
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
return maxFs;
|
|
@@ -117,16 +125,21 @@ export class RemoteMedia extends EventsScope {
|
|
|
117
125
|
return;
|
|
118
126
|
}
|
|
119
127
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
128
|
+
// we switch to the next resolution level when the height is 10% more than the current resolution height
|
|
129
|
+
// except for 1080p - we switch to it immediately when the height is more than 720p
|
|
130
|
+
const threshold = 1.1;
|
|
131
|
+
const getThresholdHeight = (h: number) => Math.round(h * threshold);
|
|
132
|
+
|
|
133
|
+
if (height < getThresholdHeight(90)) {
|
|
134
|
+
fs = MAX_FS_VALUES['90p'];
|
|
135
|
+
} else if (height < getThresholdHeight(180)) {
|
|
136
|
+
fs = MAX_FS_VALUES['180p'];
|
|
137
|
+
} else if (height < getThresholdHeight(360)) {
|
|
138
|
+
fs = MAX_FS_VALUES['360p'];
|
|
126
139
|
} else if (height <= 720) {
|
|
127
|
-
fs =
|
|
140
|
+
fs = MAX_FS_VALUES['720p'];
|
|
128
141
|
} else {
|
|
129
|
-
fs =
|
|
142
|
+
fs = MAX_FS_VALUES['1080p'];
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
this.receiveSlot?.setMaxFs(fs);
|
|
@@ -1054,22 +1054,44 @@ export class RemoteMediaManager extends EventsScope {
|
|
|
1054
1054
|
);
|
|
1055
1055
|
}
|
|
1056
1056
|
|
|
1057
|
+
/**
|
|
1058
|
+
* Set multiple remote video CSIs at once
|
|
1059
|
+
* @param remoteMediaCsis The remote medias and CSIs to set them to
|
|
1060
|
+
* @returns {void}
|
|
1061
|
+
*/
|
|
1062
|
+
public setRemoteVideoCsis(remoteMediaCsis: {remoteMedia: RemoteMedia; csi?: CSI | null}[]) {
|
|
1063
|
+
if (!remoteMediaCsis.length) {
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// Check all remote medias are known
|
|
1068
|
+
remoteMediaCsis.forEach(({remoteMedia}) => {
|
|
1069
|
+
if (!Object.values(this.media.video.memberPanes).includes(remoteMedia)) {
|
|
1070
|
+
throw new Error(`remoteMedia ${remoteMedia.id} not found`);
|
|
1071
|
+
}
|
|
1072
|
+
});
|
|
1073
|
+
|
|
1074
|
+
// Set remote video CSIs
|
|
1075
|
+
remoteMediaCsis.forEach(({remoteMedia, csi}) => {
|
|
1076
|
+
if (csi) {
|
|
1077
|
+
remoteMedia.sendMediaRequest(csi, false);
|
|
1078
|
+
} else {
|
|
1079
|
+
remoteMedia.cancelMediaRequest(false);
|
|
1080
|
+
}
|
|
1081
|
+
});
|
|
1082
|
+
|
|
1083
|
+
// Commit the changes
|
|
1084
|
+
this.mediaRequestManagers.video.commit();
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1057
1087
|
/**
|
|
1058
1088
|
* Sets a new CSI on a given remote media object
|
|
1059
1089
|
*
|
|
1060
1090
|
* @param {RemoteMedia} remoteMedia remote Media object to modify
|
|
1061
1091
|
* @param {CSI} csi new CSI value, can be null if we want to stop receiving media
|
|
1062
1092
|
*/
|
|
1063
|
-
public setRemoteVideoCsi(remoteMedia: RemoteMedia, csi
|
|
1064
|
-
|
|
1065
|
-
throw new Error('remoteMedia not found');
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
if (csi) {
|
|
1069
|
-
remoteMedia.sendMediaRequest(csi, true);
|
|
1070
|
-
} else {
|
|
1071
|
-
remoteMedia.cancelMediaRequest(true);
|
|
1072
|
-
}
|
|
1093
|
+
public setRemoteVideoCsi(remoteMedia: RemoteMedia, csi?: CSI | null) {
|
|
1094
|
+
this.setRemoteVideoCsis([{remoteMedia, csi}]);
|
|
1073
1095
|
}
|
|
1074
1096
|
|
|
1075
1097
|
/**
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
LocalStream,
|
|
5
5
|
MultistreamRoapMediaConnection,
|
|
6
6
|
NamedMediaGroup,
|
|
7
|
+
StreamState,
|
|
7
8
|
} from '@webex/internal-media-core';
|
|
8
9
|
|
|
9
10
|
export default class SendSlotManager {
|
|
@@ -83,6 +84,36 @@ export default class SendSlotManager {
|
|
|
83
84
|
);
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Sets the source state override for the given media type.
|
|
89
|
+
* @param {MediaType} mediaType - The type of media (must be MediaType.VideoMain to apply source state changes).
|
|
90
|
+
* @param {StreamState | null} state - The state to set or null to clear the override value.
|
|
91
|
+
* @returns {void}
|
|
92
|
+
*/
|
|
93
|
+
public setSourceStateOverride(mediaType: MediaType, state: StreamState | null) {
|
|
94
|
+
if (mediaType !== MediaType.VideoMain) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`sendSlotManager cannot set source state override which media type is ${mediaType}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const slot = this.slots.get(mediaType);
|
|
101
|
+
|
|
102
|
+
if (!slot) {
|
|
103
|
+
throw new Error(`Slot for ${mediaType} does not exist`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (state) {
|
|
107
|
+
slot.setSourceStateOverride(state);
|
|
108
|
+
} else {
|
|
109
|
+
slot.clearSourceStateOverride();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
this.LoggerProxy.logger.info(
|
|
113
|
+
`SendSlotsManager->setSourceStateOverride#set source state override for ${mediaType} to ${state}`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
86
117
|
/**
|
|
87
118
|
* This method publishes the given stream to the sendSlot for the given mediaType
|
|
88
119
|
* @param {MediaType} mediaType MediaType of the sendSlot to which a stream needs to be published (AUDIO_MAIN/VIDEO_MAIN/AUDIO_SLIDES/VIDEO_SLIDES)
|