@webex/plugin-meetings 3.0.0-beta.145 → 3.0.0-beta.147
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/annotation.types.js.map +1 -1
- package/dist/annotation/constants.js +6 -5
- package/dist/annotation/constants.js.map +1 -1
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/common/errors/webex-errors.js +3 -2
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/config.js +1 -7
- package/dist/config.js.map +1 -1
- package/dist/constants.js +7 -15
- package/dist/constants.js.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/media/index.js +5 -56
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +15 -93
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/index.js +1106 -1876
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +88 -184
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +2 -2
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +1 -23
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +1 -2
- package/dist/meetings/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +153 -134
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/roap/index.js +8 -7
- package/dist/roap/index.js.map +1 -1
- package/dist/types/annotation/annotation.types.d.ts +9 -1
- package/dist/types/annotation/constants.d.ts +5 -5
- package/dist/types/common/errors/webex-errors.d.ts +1 -1
- package/dist/types/config.d.ts +0 -6
- package/dist/types/constants.d.ts +1 -18
- package/dist/types/index.d.ts +1 -1
- package/dist/types/media/properties.d.ts +16 -38
- package/dist/types/meeting/index.d.ts +92 -352
- package/dist/types/meeting/muteState.d.ts +36 -38
- package/dist/types/meeting/request.d.ts +2 -1
- package/dist/types/meeting/util.d.ts +2 -4
- package/package.json +19 -19
- package/src/annotation/annotation.types.ts +10 -1
- package/src/annotation/constants.ts +5 -5
- package/src/common/errors/webex-errors.ts +6 -2
- package/src/config.ts +0 -6
- package/src/constants.ts +1 -14
- package/src/index.ts +1 -0
- package/src/media/index.ts +10 -53
- package/src/media/properties.ts +32 -92
- package/src/meeting/index.ts +532 -1564
- package/src/meeting/muteState.ts +87 -178
- package/src/meeting/request.ts +4 -3
- package/src/meeting/util.ts +3 -24
- package/src/meetings/index.ts +0 -1
- package/src/reconnection-manager/index.ts +4 -9
- package/src/roap/index.ts +13 -14
- package/test/integration/spec/converged-space-meetings.js +59 -3
- package/test/integration/spec/journey.js +330 -256
- package/test/integration/spec/space-meeting.js +75 -3
- package/test/unit/spec/meeting/index.js +776 -1344
- package/test/unit/spec/meeting/muteState.js +238 -394
- package/test/unit/spec/meeting/request.js +4 -4
- package/test/unit/spec/meeting/utils.js +2 -9
- package/test/unit/spec/multistream/receiveSlot.ts +1 -1
- package/test/unit/spec/roap/index.ts +2 -2
- package/test/utils/integrationTestUtils.js +5 -23
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ServerMuteReason } from '@webex/media-helpers';
|
|
2
|
-
export declare const createMuteState: (type: any, meeting: any,
|
|
2
|
+
export declare const createMuteState: (type: any, meeting: any, enabled: boolean) => MuteState;
|
|
3
3
|
/** The purpose of this class is to manage the local and remote mute state and make sure that the server state always matches
|
|
4
4
|
the last requested state by the client.
|
|
5
5
|
|
|
@@ -8,20 +8,28 @@ export declare const createMuteState: (type: any, meeting: any, mediaDirection:
|
|
|
8
8
|
This class is exported only for unit tests. It should never be instantiated directly with new MuteState(), instead createMuteState() should be called
|
|
9
9
|
*/
|
|
10
10
|
export declare class MuteState {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
state: {
|
|
12
|
+
client: {
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
localMute: boolean;
|
|
15
|
+
};
|
|
16
|
+
server: {
|
|
17
|
+
localMute: boolean;
|
|
18
|
+
remoteMute: boolean;
|
|
19
|
+
unmuteAllowed: boolean;
|
|
20
|
+
};
|
|
21
|
+
syncToServerInProgress: boolean;
|
|
22
|
+
};
|
|
14
23
|
type: any;
|
|
15
|
-
sdkOwnsLocalTrack: boolean;
|
|
16
24
|
ignoreMuteStateChange: boolean;
|
|
17
25
|
/**
|
|
18
26
|
* Constructor
|
|
19
27
|
*
|
|
20
28
|
* @param {String} type - audio or video
|
|
21
29
|
* @param {Object} meeting - the meeting object (used for reading current remote mute status)
|
|
22
|
-
* @param {boolean}
|
|
30
|
+
* @param {boolean} enabled - whether the client audio/video is enabled at all
|
|
23
31
|
*/
|
|
24
|
-
constructor(type: string, meeting: any,
|
|
32
|
+
constructor(type: string, meeting: any, enabled: boolean);
|
|
25
33
|
/**
|
|
26
34
|
* Starts the mute state machine. Needs to be called after a new MuteState instance is created.
|
|
27
35
|
*
|
|
@@ -39,6 +47,14 @@ export declare class MuteState {
|
|
|
39
47
|
* @returns {void}
|
|
40
48
|
*/
|
|
41
49
|
handleLocalTrackChange(meeting: any): void;
|
|
50
|
+
/**
|
|
51
|
+
* Enables/disables audio/video
|
|
52
|
+
*
|
|
53
|
+
* @param {Object} meeting - the meeting object
|
|
54
|
+
* @param {boolean} enable
|
|
55
|
+
* @returns {void}
|
|
56
|
+
*/
|
|
57
|
+
enable(meeting: any, enable: boolean): void;
|
|
42
58
|
/**
|
|
43
59
|
* Mutes/unmutes local track
|
|
44
60
|
*
|
|
@@ -48,21 +64,6 @@ export declare class MuteState {
|
|
|
48
64
|
* @returns {void}
|
|
49
65
|
*/
|
|
50
66
|
private muteLocalTrack;
|
|
51
|
-
/**
|
|
52
|
-
* Handles mute/unmute request from the client/user. Returns a promise that's resolved once the server update is completed or
|
|
53
|
-
* at the point that this request becomese superseded by another client request.
|
|
54
|
-
*
|
|
55
|
-
* The client doesn't have to wait for the returned promise to resolve before calling handleClientRequest() again. If
|
|
56
|
-
* handleClientRequest() is called again before the previous one resolved, the MuteState class will make sure that eventually
|
|
57
|
-
* the server state will match the last requested state from the client.
|
|
58
|
-
*
|
|
59
|
-
* @public
|
|
60
|
-
* @memberof MuteState
|
|
61
|
-
* @param {Object} [meeting] the meeting object
|
|
62
|
-
* @param {Boolean} [mute] true for muting, false for unmuting request
|
|
63
|
-
* @returns {Promise}
|
|
64
|
-
*/
|
|
65
|
-
handleClientRequest(meeting: object, mute?: boolean): Promise<unknown>;
|
|
66
67
|
/**
|
|
67
68
|
* This method should be called when the local track mute state is changed
|
|
68
69
|
* @public
|
|
@@ -82,6 +83,12 @@ export declare class MuteState {
|
|
|
82
83
|
* @returns {void}
|
|
83
84
|
*/
|
|
84
85
|
applyClientStateLocally(meeting?: any, reason?: ServerMuteReason): void;
|
|
86
|
+
/** Returns true if client is locally muted - it takes into account not just the client local mute state,
|
|
87
|
+
* but also whether audio/video is enabled at all
|
|
88
|
+
*
|
|
89
|
+
* @returns {boolean}
|
|
90
|
+
*/
|
|
91
|
+
private getClientLocalMuteState;
|
|
85
92
|
/**
|
|
86
93
|
* Updates the server local and remote mute values so that they match the current client desired state.
|
|
87
94
|
*
|
|
@@ -142,13 +149,14 @@ export declare class MuteState {
|
|
|
142
149
|
*/
|
|
143
150
|
handleServerLocalUnmuteRequired(meeting?: object): void;
|
|
144
151
|
/**
|
|
145
|
-
* Returns true if the user is locally or remotely muted
|
|
152
|
+
* Returns true if the user is locally or remotely muted.
|
|
153
|
+
* It only checks the mute status, ignoring the fact whether audio/video is enabled.
|
|
146
154
|
*
|
|
147
155
|
* @public
|
|
148
156
|
* @memberof MuteState
|
|
149
157
|
* @returns {Boolean}
|
|
150
158
|
*/
|
|
151
|
-
isMuted():
|
|
159
|
+
isMuted(): boolean;
|
|
152
160
|
/**
|
|
153
161
|
* Returns true if the user is remotely muted
|
|
154
162
|
*
|
|
@@ -156,7 +164,7 @@ export declare class MuteState {
|
|
|
156
164
|
* @memberof MuteState
|
|
157
165
|
* @returns {Boolean}
|
|
158
166
|
*/
|
|
159
|
-
isRemotelyMuted():
|
|
167
|
+
isRemotelyMuted(): boolean;
|
|
160
168
|
/**
|
|
161
169
|
* Returns true if unmute is allowed
|
|
162
170
|
*
|
|
@@ -164,23 +172,13 @@ export declare class MuteState {
|
|
|
164
172
|
* @memberof MuteState
|
|
165
173
|
* @returns {Boolean}
|
|
166
174
|
*/
|
|
167
|
-
isUnmuteAllowed():
|
|
168
|
-
/**
|
|
169
|
-
* Returns true if the user is locally muted
|
|
170
|
-
*
|
|
171
|
-
* @public
|
|
172
|
-
* @memberof MuteState
|
|
173
|
-
* @returns {Boolean}
|
|
174
|
-
*/
|
|
175
|
-
isLocallyMuted(): any;
|
|
175
|
+
isUnmuteAllowed(): boolean;
|
|
176
176
|
/**
|
|
177
|
-
* Returns true if the user is muted
|
|
177
|
+
* Returns true if the user is locally muted or audio/video is disabled
|
|
178
178
|
*
|
|
179
179
|
* @public
|
|
180
180
|
* @memberof MuteState
|
|
181
181
|
* @returns {Boolean}
|
|
182
182
|
*/
|
|
183
|
-
|
|
184
|
-
get muted(): any;
|
|
185
|
-
get self(): boolean;
|
|
183
|
+
isLocallyMuted(): boolean;
|
|
186
184
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StatelessWebexPlugin } from '@webex/webex-core';
|
|
2
2
|
import { SendReactionOptions, ToggleReactionsOptions } from './request.type';
|
|
3
|
+
import { AnnotationInfo } from '../annotation/annotation.types';
|
|
3
4
|
/**
|
|
4
5
|
* @class MeetingRequest
|
|
5
6
|
*/
|
|
@@ -189,7 +190,7 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
|
189
190
|
deviceUrl: string;
|
|
190
191
|
resourceId: string;
|
|
191
192
|
uri: string;
|
|
192
|
-
|
|
193
|
+
annotationInfo: AnnotationInfo;
|
|
193
194
|
} | any): any;
|
|
194
195
|
/**
|
|
195
196
|
* Sends a request to the DTMF endpoint to send tones
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { LocalCameraTrack, LocalMicrophoneTrack } from '@webex/media-helpers';
|
|
2
1
|
declare const MeetingUtil: {
|
|
3
2
|
parseLocusJoin: (response: any) => any;
|
|
4
3
|
remoteUpdateAudioVideo: (meeting: any, audioMuted?: boolean, videoMuted?: boolean) => any;
|
|
@@ -15,7 +14,6 @@ declare const MeetingUtil: {
|
|
|
15
14
|
isUserInJoinedState: (locusInfo: any) => boolean;
|
|
16
15
|
isMediaEstablished: (currentMediaStatus: any) => any;
|
|
17
16
|
joinMeetingOptions: (meeting: any, options?: any) => any;
|
|
18
|
-
validateOptions: (options: any) => Promise<void>;
|
|
19
17
|
getTrack: (stream: any) => {
|
|
20
18
|
audioTrack: any;
|
|
21
19
|
videoTrack: any;
|
|
@@ -39,8 +37,8 @@ declare const MeetingUtil: {
|
|
|
39
37
|
canUserAskForHelp: (displayHints: any) => boolean;
|
|
40
38
|
lockMeeting: (actions: any, request: any, locusUrl: any) => any;
|
|
41
39
|
unlockMeeting: (actions: any, request: any, locusUrl: any) => any;
|
|
42
|
-
handleAudioLogging: (audioTrack
|
|
43
|
-
handleVideoLogging: (videoTrack
|
|
40
|
+
handleAudioLogging: (audioTrack?: LocalMicrophoneTrack) => void;
|
|
41
|
+
handleVideoLogging: (videoTrack?: LocalCameraTrack) => void;
|
|
44
42
|
handleDeviceLogging: (devices?: any[]) => void;
|
|
45
43
|
endMeetingForAll: (meeting: any) => any;
|
|
46
44
|
canEnableClosedCaption: (displayHints: any) => any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.147",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
36
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
37
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
35
|
+
"@webex/plugin-meetings": "3.0.0-beta.147",
|
|
36
|
+
"@webex/test-helper-chai": "3.0.0-beta.147",
|
|
37
|
+
"@webex/test-helper-mocha": "3.0.0-beta.147",
|
|
38
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.147",
|
|
39
|
+
"@webex/test-helper-retry": "3.0.0-beta.147",
|
|
40
|
+
"@webex/test-helper-test-users": "3.0.0-beta.147",
|
|
41
41
|
"chai": "^4.3.4",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
43
|
"jsdom-global": "3.0.2",
|
|
@@ -46,19 +46,19 @@
|
|
|
46
46
|
"typescript": "^4.7.4"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@webex/common": "3.0.0-beta.
|
|
49
|
+
"@webex/common": "3.0.0-beta.147",
|
|
50
50
|
"@webex/internal-media-core": "1.38.3",
|
|
51
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
52
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
53
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
58
|
-
"@webex/media-helpers": "3.0.0-beta.
|
|
59
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
60
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
61
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
51
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.147",
|
|
52
|
+
"@webex/internal-plugin-device": "3.0.0-beta.147",
|
|
53
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.147",
|
|
54
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.147",
|
|
55
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.147",
|
|
56
|
+
"@webex/internal-plugin-support": "3.0.0-beta.147",
|
|
57
|
+
"@webex/internal-plugin-user": "3.0.0-beta.147",
|
|
58
|
+
"@webex/media-helpers": "3.0.0-beta.147",
|
|
59
|
+
"@webex/plugin-people": "3.0.0-beta.147",
|
|
60
|
+
"@webex/plugin-rooms": "3.0.0-beta.147",
|
|
61
|
+
"@webex/webex-core": "3.0.0-beta.147",
|
|
62
62
|
"ampersand-collection": "^2.0.2",
|
|
63
63
|
"bowser": "^2.11.0",
|
|
64
64
|
"btoa": "^1.2.1",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import {ANNOTATION_POLICY} from './constants';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Type for an StrokeData Object
|
|
3
5
|
*/
|
|
@@ -23,6 +25,13 @@ type CommandRequestBody = {
|
|
|
23
25
|
shareInstanceId: string;
|
|
24
26
|
receivers?: any[];
|
|
25
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* Type for an annotation Object include annotation version and privilege
|
|
30
|
+
*/
|
|
31
|
+
type AnnotationInfo = {
|
|
32
|
+
version: string;
|
|
33
|
+
policy: ANNOTATION_POLICY;
|
|
34
|
+
};
|
|
26
35
|
|
|
27
36
|
interface IAnnotationChannel {
|
|
28
37
|
// === below is for presenter
|
|
@@ -40,4 +49,4 @@ interface IAnnotationChannel {
|
|
|
40
49
|
locusUrlUpdate: (locusUrl: string) => void;
|
|
41
50
|
}
|
|
42
51
|
|
|
43
|
-
export type {StrokeData, RequestData, CommandRequestBody, IAnnotationChannel};
|
|
52
|
+
export type {StrokeData, RequestData, CommandRequestBody, IAnnotationChannel, AnnotationInfo};
|
|
@@ -12,11 +12,11 @@ export const ANNOTATION_STATUS = {
|
|
|
12
12
|
RUNNING_ANNOTATION: 'RUNNING_ANNOTATION',
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
export
|
|
16
|
-
ANYONE_CAN_ANNOTATE
|
|
17
|
-
APPROVAL
|
|
18
|
-
ANNOTATION_NOT_ALLOWED
|
|
19
|
-
}
|
|
15
|
+
export enum ANNOTATION_POLICY {
|
|
16
|
+
ANYONE_CAN_ANNOTATE = 'AnyoneCanAnnotate',
|
|
17
|
+
APPROVAL = 'Approval',
|
|
18
|
+
ANNOTATION_NOT_ALLOWED = 'AnnotationNotAllowed',
|
|
19
|
+
}
|
|
20
20
|
|
|
21
21
|
export const ANNOTATION_REQUEST_TYPE = {
|
|
22
22
|
ANNOTATION_MESSAGE: 'annotation_message',
|
|
@@ -72,13 +72,17 @@ WebExMeetingsErrors[UserNotJoinedError.CODE] = UserNotJoinedError;
|
|
|
72
72
|
* @classdesc Raised whenever the user has not established media yet.
|
|
73
73
|
* @extends WebexMeetingsError
|
|
74
74
|
* @property {number} code - 30103
|
|
75
|
-
* @property {string} message -
|
|
75
|
+
* @property {string} message - error message
|
|
76
76
|
*/
|
|
77
77
|
class NoMediaEstablishedYetError extends WebexMeetingsError {
|
|
78
78
|
static CODE = 30103;
|
|
79
79
|
|
|
80
|
+
// eslint-disable-next-line require-jsdoc
|
|
80
81
|
constructor() {
|
|
81
|
-
super(
|
|
82
|
+
super(
|
|
83
|
+
NoMediaEstablishedYetError.CODE,
|
|
84
|
+
'Webrtc media connection is missing, call addMedia() first'
|
|
85
|
+
);
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
|
package/src/config.ts
CHANGED
|
@@ -10,13 +10,7 @@ export default {
|
|
|
10
10
|
meetings: {
|
|
11
11
|
deviceType: deviceType.WEB,
|
|
12
12
|
mediaSettings: {
|
|
13
|
-
sendAudio: true,
|
|
14
|
-
sendVideo: true,
|
|
15
|
-
receiveAudio: true,
|
|
16
|
-
receiveVideo: true,
|
|
17
13
|
pstn: false,
|
|
18
|
-
sendShare: false,
|
|
19
|
-
receiveShare: false,
|
|
20
14
|
},
|
|
21
15
|
reconnection: {
|
|
22
16
|
enabled: false,
|
package/src/constants.ts
CHANGED
|
@@ -4,7 +4,6 @@ import {hydraTypes} from '@webex/common';
|
|
|
4
4
|
// *********** LOWERCASE / CAMELCASE STRINGS ************
|
|
5
5
|
|
|
6
6
|
export const AUDIO = 'audio';
|
|
7
|
-
export const AUDIO_INPUT = 'audioinput';
|
|
8
7
|
export const AUDIO_STATUS = 'audioStatus';
|
|
9
8
|
export const ALERT = 'alert';
|
|
10
9
|
export const ALIAS = 'alias';
|
|
@@ -67,7 +66,6 @@ export const SHARE = 'share';
|
|
|
67
66
|
export const TYPE = 'type';
|
|
68
67
|
|
|
69
68
|
export const VIDEO = 'video';
|
|
70
|
-
export const VIDEO_INPUT = 'videoinput';
|
|
71
69
|
export const VIDEO_STATUS = 'videoStatus';
|
|
72
70
|
|
|
73
71
|
// *********** UPPERCASE ONLY STRINGS ************
|
|
@@ -363,12 +361,10 @@ export const EVENT_TRIGGERS = {
|
|
|
363
361
|
export const EVENT_TYPES = {
|
|
364
362
|
SELF: 'self',
|
|
365
363
|
OTHER: 'other',
|
|
366
|
-
LOCAL: 'local',
|
|
367
364
|
REMOTE: 'remote',
|
|
368
365
|
REMOTE_AUDIO: 'remoteAudio',
|
|
369
366
|
REMOTE_VIDEO: 'remoteVideo',
|
|
370
367
|
REMOTE_SHARE: 'remoteShare',
|
|
371
|
-
LOCAL_SHARE: 'localShare',
|
|
372
368
|
ERROR: 'error',
|
|
373
369
|
};
|
|
374
370
|
|
|
@@ -400,6 +396,7 @@ export const SHARE_STOPPED_REASON = {
|
|
|
400
396
|
SELF_STOPPED: 'SELF_STOPPED',
|
|
401
397
|
MEETING_REJOIN: 'MEETING_REJOIN',
|
|
402
398
|
MEDIA_RECONNECTION: 'MEDIA_RECONNECTION',
|
|
399
|
+
TRACK_ENDED: 'TRACK_ENDED',
|
|
403
400
|
};
|
|
404
401
|
|
|
405
402
|
export const EVENTS = {
|
|
@@ -1138,16 +1135,6 @@ export const AVAILABLE_RESOLUTIONS = {
|
|
|
1138
1135
|
},
|
|
1139
1136
|
};
|
|
1140
1137
|
|
|
1141
|
-
export const VIDEO_RESOLUTIONS = {
|
|
1142
|
-
[QUALITY_LEVELS.LOW]: AVAILABLE_RESOLUTIONS['480p'],
|
|
1143
|
-
[QUALITY_LEVELS.MEDIUM]: AVAILABLE_RESOLUTIONS['720p'],
|
|
1144
|
-
[QUALITY_LEVELS.HIGH]: AVAILABLE_RESOLUTIONS['1080p'],
|
|
1145
|
-
[QUALITY_LEVELS['360p']]: AVAILABLE_RESOLUTIONS['360p'],
|
|
1146
|
-
[QUALITY_LEVELS['480p']]: AVAILABLE_RESOLUTIONS['480p'],
|
|
1147
|
-
[QUALITY_LEVELS['720p']]: AVAILABLE_RESOLUTIONS['720p'],
|
|
1148
|
-
[QUALITY_LEVELS['1080p']]: AVAILABLE_RESOLUTIONS['1080p'],
|
|
1149
|
-
};
|
|
1150
|
-
|
|
1151
1138
|
/*
|
|
1152
1139
|
* mqa Interval for sending stats metrics
|
|
1153
1140
|
*/
|
package/src/index.ts
CHANGED
package/src/media/index.ts
CHANGED
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
import {RoapMediaConnection, MultistreamRoapMediaConnection} from '@webex/internal-media-core';
|
|
7
7
|
import {LocalCameraTrack, LocalDisplayTrack, LocalMicrophoneTrack} from '@webex/media-helpers';
|
|
8
8
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
9
|
-
import {
|
|
9
|
+
import {MEDIA_TRACK_CONSTRAINT} from '../constants';
|
|
10
10
|
import Config from '../config';
|
|
11
11
|
import StaticConfig from '../common/config';
|
|
12
|
-
import MediaError from '../common/errors/media';
|
|
13
12
|
import BrowserDetection from '../common/browser-detection';
|
|
14
13
|
|
|
15
14
|
const {isBrowser} = BrowserDetection();
|
|
@@ -77,12 +76,12 @@ Media.getLocalMedia = (options: any, config: object) => {
|
|
|
77
76
|
return Promise.resolve(undefined);
|
|
78
77
|
};
|
|
79
78
|
|
|
80
|
-
Media.getDirection = (receive: boolean, send: boolean) => {
|
|
79
|
+
Media.getDirection = (forceSendRecv: boolean, receive: boolean, send: boolean) => {
|
|
81
80
|
if (!receive && !send) {
|
|
82
81
|
return 'inactive';
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
if (receive && send) {
|
|
84
|
+
if (forceSendRecv || (receive && send)) {
|
|
86
85
|
return 'sendrecv';
|
|
87
86
|
}
|
|
88
87
|
|
|
@@ -202,9 +201,13 @@ Media.createMediaConnection = (
|
|
|
202
201
|
screenShareVideo: shareTrack?.underlyingTrack,
|
|
203
202
|
},
|
|
204
203
|
direction: {
|
|
205
|
-
audio: Media.getDirection(mediaDirection.receiveAudio, mediaDirection.sendAudio),
|
|
206
|
-
video: Media.getDirection(mediaDirection.receiveVideo, mediaDirection.sendVideo),
|
|
207
|
-
screenShareVideo: Media.getDirection(
|
|
204
|
+
audio: Media.getDirection(true, mediaDirection.receiveAudio, mediaDirection.sendAudio),
|
|
205
|
+
video: Media.getDirection(true, mediaDirection.receiveVideo, mediaDirection.sendVideo),
|
|
206
|
+
screenShareVideo: Media.getDirection(
|
|
207
|
+
false,
|
|
208
|
+
mediaDirection.receiveShare,
|
|
209
|
+
mediaDirection.sendShare
|
|
210
|
+
),
|
|
208
211
|
},
|
|
209
212
|
remoteQualityLevel,
|
|
210
213
|
},
|
|
@@ -351,52 +354,6 @@ Media.getMedia = (audio: any | boolean, video: any | boolean, config: any) => {
|
|
|
351
354
|
});
|
|
352
355
|
};
|
|
353
356
|
|
|
354
|
-
/**
|
|
355
|
-
* Checks if the machine has at least one audio or video device (Dont use this for screen share)
|
|
356
|
-
* @param {object} [options]
|
|
357
|
-
* {
|
|
358
|
-
* sendAudio: true/false,
|
|
359
|
-
* sendVideo: true/false
|
|
360
|
-
* }
|
|
361
|
-
* @returns {Object} {
|
|
362
|
-
* sendAudio: true/false,
|
|
363
|
-
* sendVideo: true/false
|
|
364
|
-
*}
|
|
365
|
-
*/
|
|
366
|
-
Media.getSupportedDevice = ({sendAudio, sendVideo}: {sendAudio: boolean; sendVideo: boolean}) =>
|
|
367
|
-
Promise.resolve().then(() => {
|
|
368
|
-
if (!navigator.mediaDevices || navigator.mediaDevices.enumerateDevices === undefined) {
|
|
369
|
-
return {
|
|
370
|
-
sendAudio: false,
|
|
371
|
-
sendVideo: false,
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return navigator.mediaDevices.enumerateDevices().then((devices) => {
|
|
376
|
-
const supported = {
|
|
377
|
-
audio: devices.filter((device) => device.kind === AUDIO_INPUT).length > 0,
|
|
378
|
-
video: devices.filter((device) => device.kind === VIDEO_INPUT).length > 0,
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
return {
|
|
382
|
-
sendAudio: supported.audio && sendAudio,
|
|
383
|
-
sendVideo: supported.video && sendVideo,
|
|
384
|
-
};
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* proxy to browser navigator.mediaDevices.enumerateDevices()
|
|
390
|
-
* @returns {Promise}
|
|
391
|
-
*/
|
|
392
|
-
Media.getDevices = () => {
|
|
393
|
-
if (navigator && navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
|
|
394
|
-
return navigator.mediaDevices.enumerateDevices();
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
return Promise.reject(new MediaError('enumerateDevices not supported.'));
|
|
398
|
-
};
|
|
399
|
-
|
|
400
357
|
/**
|
|
401
358
|
*
|
|
402
359
|
* Toggle a specific stream
|
package/src/media/properties.ts
CHANGED
|
@@ -5,39 +5,53 @@ import {LocalCameraTrack, LocalMicrophoneTrack, LocalDisplayTrack} from '@webex/
|
|
|
5
5
|
import {MEETINGS, PC_BAIL_TIMEOUT, QUALITY_LEVELS} from '../constants';
|
|
6
6
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
7
7
|
|
|
8
|
+
export type MediaDirection = {
|
|
9
|
+
sendAudio: boolean;
|
|
10
|
+
sendVideo: boolean;
|
|
11
|
+
sendShare: boolean;
|
|
12
|
+
receiveAudio: boolean;
|
|
13
|
+
receiveVideo: boolean;
|
|
14
|
+
receiveShare: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
8
17
|
/**
|
|
9
18
|
* @class MediaProperties
|
|
10
19
|
*/
|
|
11
20
|
export default class MediaProperties {
|
|
12
|
-
audioTrack
|
|
13
|
-
|
|
14
|
-
mediaDirection: any;
|
|
21
|
+
audioTrack?: LocalMicrophoneTrack;
|
|
22
|
+
mediaDirection: MediaDirection;
|
|
15
23
|
mediaSettings: any;
|
|
16
24
|
webrtcMediaConnection: any;
|
|
17
25
|
remoteAudioTrack: any;
|
|
18
26
|
remoteQualityLevel: any;
|
|
19
27
|
remoteShare: any;
|
|
20
28
|
remoteVideoTrack: any;
|
|
21
|
-
shareTrack
|
|
29
|
+
shareTrack?: LocalDisplayTrack;
|
|
22
30
|
videoDeviceId: any;
|
|
23
|
-
videoTrack
|
|
31
|
+
videoTrack?: LocalCameraTrack;
|
|
24
32
|
namespace = MEETINGS;
|
|
25
33
|
|
|
26
34
|
/**
|
|
27
35
|
* @param {Object} [options] -- to auto construct
|
|
28
36
|
* @returns {MediaProperties}
|
|
29
37
|
*/
|
|
30
|
-
constructor(
|
|
38
|
+
constructor() {
|
|
31
39
|
this.webrtcMediaConnection = null;
|
|
32
|
-
this.mediaDirection =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
this.
|
|
40
|
+
this.mediaDirection = {
|
|
41
|
+
receiveAudio: false,
|
|
42
|
+
receiveVideo: false,
|
|
43
|
+
receiveShare: false,
|
|
44
|
+
sendAudio: false,
|
|
45
|
+
sendVideo: false,
|
|
46
|
+
sendShare: false,
|
|
47
|
+
};
|
|
48
|
+
this.videoTrack = null;
|
|
49
|
+
this.audioTrack = null;
|
|
50
|
+
this.shareTrack = null;
|
|
51
|
+
this.remoteShare = undefined;
|
|
52
|
+
this.remoteAudioTrack = undefined;
|
|
53
|
+
this.remoteVideoTrack = undefined;
|
|
54
|
+
this.remoteQualityLevel = QUALITY_LEVELS.HIGH;
|
|
41
55
|
this.mediaSettings = {};
|
|
42
56
|
this.videoDeviceId = null;
|
|
43
57
|
}
|
|
@@ -62,19 +76,15 @@ export default class MediaProperties {
|
|
|
62
76
|
this.webrtcMediaConnection = mediaPeerConnection;
|
|
63
77
|
}
|
|
64
78
|
|
|
65
|
-
setLocalVideoTrack(videoTrack
|
|
79
|
+
setLocalVideoTrack(videoTrack?: LocalCameraTrack) {
|
|
66
80
|
this.videoTrack = videoTrack;
|
|
67
81
|
}
|
|
68
82
|
|
|
69
|
-
setLocalAudioTrack(audioTrack
|
|
83
|
+
setLocalAudioTrack(audioTrack?: LocalMicrophoneTrack) {
|
|
70
84
|
this.audioTrack = audioTrack;
|
|
71
85
|
}
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
this.localQualityLevel = localQualityLevel;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
setLocalShareTrack(shareTrack: LocalDisplayTrack | null) {
|
|
87
|
+
setLocalShareTrack(shareTrack?: LocalDisplayTrack) {
|
|
78
88
|
this.shareTrack = shareTrack;
|
|
79
89
|
}
|
|
80
90
|
|
|
@@ -117,31 +127,6 @@ export default class MediaProperties {
|
|
|
117
127
|
this.webrtcMediaConnection = null;
|
|
118
128
|
}
|
|
119
129
|
|
|
120
|
-
unsetLocalVideoTrack() {
|
|
121
|
-
this.videoTrack = null;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
unsetLocalShareTrack() {
|
|
125
|
-
this.shareTrack = null;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
unsetLocalAudioTrack() {
|
|
129
|
-
this.audioTrack = null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Removes remote stream from class instance
|
|
134
|
-
* @deprecated after v1.89.3
|
|
135
|
-
* @returns {void}
|
|
136
|
-
*/
|
|
137
|
-
unsetRemoteStream() {
|
|
138
|
-
LoggerProxy.logger.warn(
|
|
139
|
-
'Media:properties#unsetRemoteStream --> [DEPRECATION WARNING]: unsetRemoteStream has been deprecated after v1.89.3 (use unsetRemoteTracks instead)'
|
|
140
|
-
);
|
|
141
|
-
// unsets audio and video only
|
|
142
|
-
this.unsetRemoteMedia();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
130
|
/**
|
|
146
131
|
* Removes both remote audio and video from class instance
|
|
147
132
|
* @returns {void}
|
|
@@ -155,24 +140,6 @@ export default class MediaProperties {
|
|
|
155
140
|
this.remoteShare = null;
|
|
156
141
|
}
|
|
157
142
|
|
|
158
|
-
unsetLocalVideoTracks() {
|
|
159
|
-
this.unsetLocalVideoTrack();
|
|
160
|
-
this.unsetLocalShareTrack();
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Removes remote stream and remote share from class instance
|
|
165
|
-
* @deprecated after v1.89.3
|
|
166
|
-
* @returns {void}
|
|
167
|
-
*/
|
|
168
|
-
unsetRemoteStreams() {
|
|
169
|
-
LoggerProxy.logger.warn(
|
|
170
|
-
'Media:properties#unsetRemoteStreams --> [DEPRECATION WARNING]: unsetRemoteStreams has been deprecated after v1.89.3 (use unsetRemoteTracks instead)'
|
|
171
|
-
);
|
|
172
|
-
this.unsetRemoteStream();
|
|
173
|
-
this.unsetRemoteShare();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
143
|
/**
|
|
177
144
|
* Unsets all remote tracks
|
|
178
145
|
* @returns {void}
|
|
@@ -182,33 +149,6 @@ export default class MediaProperties {
|
|
|
182
149
|
this.unsetRemoteShare();
|
|
183
150
|
}
|
|
184
151
|
|
|
185
|
-
unsetShareStreams() {
|
|
186
|
-
this.unsetLocalShareTrack();
|
|
187
|
-
this.unsetRemoteShare();
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Removes both local and remote video stream from class instance
|
|
192
|
-
* @deprecated after v1.89.3
|
|
193
|
-
* @returns {void}
|
|
194
|
-
*/
|
|
195
|
-
unsetMediaStreams() {
|
|
196
|
-
LoggerProxy.logger.warn(
|
|
197
|
-
'Media:properties#unsetMediaStreams --> [DEPRECATION WARNING]: unsetMediaStreams has been deprecated after v1.89.3 (use unsetMediaTracks instead)'
|
|
198
|
-
);
|
|
199
|
-
this.unsetLocalVideoTrack();
|
|
200
|
-
this.unsetRemoteStream();
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Removes both local and remote video stream from class instance
|
|
205
|
-
* @returns {void}
|
|
206
|
-
*/
|
|
207
|
-
unsetMediaTracks() {
|
|
208
|
-
this.unsetLocalVideoTrack();
|
|
209
|
-
this.unsetRemoteMedia();
|
|
210
|
-
}
|
|
211
|
-
|
|
212
152
|
/**
|
|
213
153
|
* Waits for the webrtc media connection to be connected.
|
|
214
154
|
*
|