@wazo/sdk 1.0.0-alpha.1 → 1.0.0-alpha.3
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/wazo-sdk.js +6 -6
- package/esm/__tests__/__voice__/call.test.js +45 -2
- package/esm/domain/Phone/CTIPhone.js +2 -2
- package/esm/domain/Phone/WebRTCPhone.js +6 -7
- package/esm/index.js +1 -1
- package/esm/service/CallApi.js +4 -4
- package/esm/simple/Phone.js +1 -0
- package/esm/state-machine/call-state-machine.js +1 -1
- package/esm/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/esm/types/index.d.ts +1 -1
- package/esm/types/index.d.ts.map +1 -1
- package/esm/types/service/CallApi.d.ts +5 -5
- package/esm/types/service/CallApi.d.ts.map +1 -1
- package/esm/types/simple/Phone.d.ts.map +1 -1
- package/esm/types/state-machine/softphone-state-machine.d.ts +1 -1
- package/esm/types/state-machine/utils.d.ts +1 -1
- package/esm/types/state-machine/utils.d.ts.map +1 -1
- package/esm/types/utils/sdp.d.ts +2 -0
- package/esm/types/utils/sdp.d.ts.map +1 -1
- package/esm/types/utils/webrtc.d.ts +1 -0
- package/esm/types/utils/webrtc.d.ts.map +1 -1
- package/esm/types/voice/call.d.ts +27 -12
- package/esm/types/voice/call.d.ts.map +1 -1
- package/esm/types/voice/softphone.d.ts +22 -13
- package/esm/types/voice/softphone.d.ts.map +1 -1
- package/esm/utils/sdp.js +13 -0
- package/esm/utils/webrtc.js +20 -0
- package/esm/voice/call.js +115 -33
- package/esm/voice/softphone.js +105 -25
- package/lib/__tests__/__voice__/call.test.js +44 -1
- package/lib/domain/Phone/CTIPhone.js +2 -2
- package/lib/domain/Phone/WebRTCPhone.js +5 -6
- package/lib/index.js +2 -2
- package/lib/service/CallApi.js +2 -2
- package/lib/simple/Phone.js +1 -0
- package/lib/state-machine/call-state-machine.js +1 -1
- package/lib/types/domain/Phone/CTIPhone.d.ts.map +1 -1
- package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/service/CallApi.d.ts +5 -5
- package/lib/types/service/CallApi.d.ts.map +1 -1
- package/lib/types/simple/Phone.d.ts.map +1 -1
- package/lib/types/state-machine/softphone-state-machine.d.ts +1 -1
- package/lib/types/state-machine/utils.d.ts +1 -1
- package/lib/types/state-machine/utils.d.ts.map +1 -1
- package/lib/types/utils/sdp.d.ts +2 -0
- package/lib/types/utils/sdp.d.ts.map +1 -1
- package/lib/types/utils/webrtc.d.ts +1 -0
- package/lib/types/utils/webrtc.d.ts.map +1 -1
- package/lib/types/voice/call.d.ts +27 -12
- package/lib/types/voice/call.d.ts.map +1 -1
- package/lib/types/voice/softphone.d.ts +22 -13
- package/lib/types/voice/softphone.d.ts.map +1 -1
- package/lib/utils/sdp.js +16 -1
- package/lib/utils/webrtc.js +22 -1
- package/lib/voice/call.js +112 -31
- package/lib/voice/softphone.js +109 -25
- package/package.json +1 -1
- package/src/__tests__/__voice__/call.test.ts +48 -2
- package/src/domain/Phone/CTIPhone.ts +3 -2
- package/src/domain/Phone/WebRTCPhone.ts +9 -9
- package/src/index.ts +1 -1
- package/src/service/CallApi.ts +7 -7
- package/src/simple/Phone.ts +1 -0
- package/src/state-machine/call-state-machine.ts +1 -1
- package/src/state-machine/utils.ts +2 -2
- package/src/utils/sdp.ts +16 -0
- package/src/utils/webrtc.ts +23 -1
- package/src/voice/call.ts +149 -43
- package/src/voice/softphone.ts +130 -31
- package/src/web-rtc-client.ts +1 -1
|
@@ -3,8 +3,9 @@ import { Inviter, UserAgent, type URI } from 'sip.js';
|
|
|
3
3
|
|
|
4
4
|
import softphone from '../../voice/softphone';
|
|
5
5
|
import Call from '../../voice/call';
|
|
6
|
-
import { Actions, States } from '../../state-machine/call-state-machine';
|
|
6
|
+
import { Actions, EstablishedStates, States } from '../../state-machine/call-state-machine';
|
|
7
7
|
import { Actions as SoftphoneActions } from '../../state-machine/softphone-state-machine';
|
|
8
|
+
import ApiCall from '../../domain/Call';
|
|
8
9
|
|
|
9
10
|
import InvalidStateTransition from '../../domain/InvalidStateTransition';
|
|
10
11
|
|
|
@@ -33,6 +34,7 @@ jest.mock('../../web-rtc-client', () => jest.fn().mockImplementation(() => ({
|
|
|
33
34
|
answer: jest.fn(() => Promise.resolve()),
|
|
34
35
|
hangup: jest.fn(() => Promise.resolve()),
|
|
35
36
|
register: jest.fn(() => Promise.resolve()),
|
|
37
|
+
onCallEnded: jest.fn(() => Promise.resolve()),
|
|
36
38
|
setOnHeartbeatTimeout: jest.fn(() => Promise.resolve()),
|
|
37
39
|
setOnHeartbeatCallback: jest.fn(() => Promise.resolve()),
|
|
38
40
|
on: jest.fn(),
|
|
@@ -42,11 +44,45 @@ const ua = new UserAgent(uaOptions);
|
|
|
42
44
|
const sipCall = new Inviter(ua, UserAgent.makeURI('sip:1234@my.stack.io') as URI);
|
|
43
45
|
|
|
44
46
|
softphone.connect();
|
|
47
|
+
// @ts-ignore: private method
|
|
45
48
|
softphone._sendAction(SoftphoneActions.REGISTER_DONE);
|
|
46
49
|
|
|
47
50
|
const invalidStateTransition = (state: string, action: string) => new InvalidStateTransition(`Invalid state transition from ${state} with action ${action}`, state, action);
|
|
48
51
|
|
|
49
52
|
describe('Call', () => {
|
|
53
|
+
describe('parsing an API call', () => {
|
|
54
|
+
it('Should parse an API call and transform it to a Call instance', async () => {
|
|
55
|
+
const apiCall = new ApiCall({
|
|
56
|
+
id: '1234',
|
|
57
|
+
sipCallId: 'abcd',
|
|
58
|
+
isCaller: false,
|
|
59
|
+
isVideo: true,
|
|
60
|
+
recording: true,
|
|
61
|
+
callerName: '',
|
|
62
|
+
callerNumber: '',
|
|
63
|
+
calleeName: '',
|
|
64
|
+
calleeNumber: '0123423223',
|
|
65
|
+
dialedExtension: '',
|
|
66
|
+
lineId: null,
|
|
67
|
+
muted: true,
|
|
68
|
+
onHold: false,
|
|
69
|
+
startingTime: new Date(),
|
|
70
|
+
status: 'Up',
|
|
71
|
+
talkingToIds: [],
|
|
72
|
+
});
|
|
73
|
+
const call = Call.parseCall(apiCall);
|
|
74
|
+
|
|
75
|
+
expect(call.recording).toBeTruthy();
|
|
76
|
+
expect(call.id).toBe(apiCall.sipCallId);
|
|
77
|
+
expect(call.apiId).toBe(apiCall.id);
|
|
78
|
+
expect(call.number).toBe(apiCall.calleeNumber);
|
|
79
|
+
expect(call.answerTime).toStrictEqual(apiCall.startingTime);
|
|
80
|
+
expect(call.isMuted()).toBeTruthy();
|
|
81
|
+
expect(call.state).toStrictEqual({ [States.ESTABLISHED]: EstablishedStates.MUTED });
|
|
82
|
+
expect(call.isEstablished()).toBeTruthy();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
50
86
|
describe('accept', () => {
|
|
51
87
|
it('Should throw an error when accepting a not ringing call', async () => {
|
|
52
88
|
const call = new Call(sipCall, softphone);
|
|
@@ -54,16 +90,24 @@ describe('Call', () => {
|
|
|
54
90
|
await expect(call.accept()).rejects.toThrowError(invalidStateTransition(States.IDLE, Actions.ACCEPT));
|
|
55
91
|
});
|
|
56
92
|
|
|
57
|
-
it
|
|
93
|
+
it('Should throw an error when the softphone is not registered', async () => {
|
|
58
94
|
const call = new Call(sipCall, softphone);
|
|
95
|
+
// @ts-ignore: private method
|
|
59
96
|
call._sendAction(Actions.INCOMING_CALL);
|
|
97
|
+
// @ts-ignore: private method
|
|
60
98
|
softphone._sendAction(SoftphoneActions.TRANSPORT_CLOSED);
|
|
61
99
|
|
|
62
100
|
await expect(call.accept()).rejects.toThrowError(invalidStateTransition(States.RINGING, Actions.ACCEPT));
|
|
101
|
+
|
|
102
|
+
// Revert softphone state
|
|
103
|
+
softphone.connect();
|
|
104
|
+
// @ts-ignore: private method
|
|
105
|
+
softphone._sendAction(SoftphoneActions.REGISTER_DONE);
|
|
63
106
|
});
|
|
64
107
|
|
|
65
108
|
it('Should not throw an error when accepting a not ringing call', async () => {
|
|
66
109
|
const call = new Call(sipCall, softphone);
|
|
110
|
+
// @ts-ignore: private method
|
|
67
111
|
call._sendAction(Actions.INCOMING_CALL);
|
|
68
112
|
|
|
69
113
|
await call.accept();
|
|
@@ -80,7 +124,9 @@ describe('Call', () => {
|
|
|
80
124
|
|
|
81
125
|
it('Should not throw an error when terminating an established call', async () => {
|
|
82
126
|
const call = new Call(sipCall, softphone);
|
|
127
|
+
// @ts-ignore: private method
|
|
83
128
|
call._sendAction(Actions.MAKE_CALL);
|
|
129
|
+
// @ts-ignore: private method
|
|
84
130
|
call._sendAction(Actions.REMOTLY_ACCEPTED);
|
|
85
131
|
|
|
86
132
|
await call.hangup();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Session from '../Session';
|
|
2
2
|
import Call from '../Call';
|
|
3
|
+
import SoftphoneCall from '../../voice/call';
|
|
3
4
|
import Line from '../Line';
|
|
4
5
|
import CallSession from '../CallSession';
|
|
5
6
|
import type { Phone, AvailablePhoneOptions } from './Phone';
|
|
@@ -141,7 +142,7 @@ export default class CTIPhone extends Emitter implements Phone {
|
|
|
141
142
|
});
|
|
142
143
|
|
|
143
144
|
try {
|
|
144
|
-
await CallApi.cancelCall(callSession);
|
|
145
|
+
await CallApi.cancelCall({ apiId: callSession.getId() } as SoftphoneCall);
|
|
145
146
|
|
|
146
147
|
if (this.currentCall && callSession.callId === this.currentCall.id) {
|
|
147
148
|
this.endCurrentCall(callSession);
|
|
@@ -167,7 +168,7 @@ export default class CTIPhone extends Emitter implements Phone {
|
|
|
167
168
|
callId: callSession.getId(),
|
|
168
169
|
number: callSession.number,
|
|
169
170
|
});
|
|
170
|
-
await CallApi.cancelCall(callSession);
|
|
171
|
+
await CallApi.cancelCall({ id: callSession.getId() } as SoftphoneCall);
|
|
171
172
|
this.eventEmitter.emit('onCallEnded', callSession);
|
|
172
173
|
}
|
|
173
174
|
|
|
@@ -12,7 +12,7 @@ import WazoWebRTCClient from '../../web-rtc-client';
|
|
|
12
12
|
import Emitter from '../../utils/Emitter';
|
|
13
13
|
import IssueReporter from '../../service/IssueReporter';
|
|
14
14
|
import { PeerConnection, WazoSession } from '../types';
|
|
15
|
-
import { getSipSessionId } from '../../utils/sdp';
|
|
15
|
+
import { getCallDisplayName, getCallNumber, getSipSessionId } from '../../utils/sdp';
|
|
16
16
|
import { downgradeToAudio, getStreamFromConstraints, getWebRtcStats, setLocalMediaStream, upgradeToVideo } from '../../utils/webrtc';
|
|
17
17
|
|
|
18
18
|
export const ON_USER_AGENT = 'onUserAgent';
|
|
@@ -61,6 +61,8 @@ export const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
|
|
|
61
61
|
export const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
|
|
62
62
|
export const events = [ON_USER_AGENT, ON_REGISTERED, ON_UNREGISTERED, ON_PROGRESS, ON_CALL_ACCEPTED, ON_CALL_ANSWERED, ON_CALL_INCOMING, ON_CALL_OUTGOING, ON_CALL_MUTED, ON_CALL_UNMUTED, ON_CALL_RESUMED, ON_CALL_HELD, ON_CALL_UNHELD, ON_CAMERA_DISABLED, ON_CALL_FAILED, ON_CALL_ENDED, ON_CALL_REJECTED, ON_MESSAGE, ON_REINVITE, ON_TRACK, ON_AUDIO_STREAM, ON_VIDEO_STREAM, ON_REMOVE_STREAM, ON_SHARE_SCREEN_ENDED, ON_TERMINATE_SOUND, ON_PLAY_RING_SOUND, ON_PLAY_INBOUND_CALL_SIGNAL_SOUND, ON_PLAY_HANGUP_SOUND, ON_PLAY_PROGRESS_SOUND, ON_VIDEO_INPUT_CHANGE, ON_SHARE_SCREEN_STARTED, ON_CALL_ERROR, ON_CHAT, ON_SIGNAL, ON_NETWORK_STATS, ON_DISCONNECTED, ON_EARLY_MEDIA];
|
|
63
63
|
const logger = IssueReporter.loggerFor('webrtc-phone');
|
|
64
|
+
|
|
65
|
+
// @deprecated: Use Wazo.Voice.Softphone instead
|
|
64
66
|
export default class WebRTCPhone extends Emitter implements Phone {
|
|
65
67
|
client: WazoWebRTCClient;
|
|
66
68
|
|
|
@@ -1783,20 +1785,17 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1783
1785
|
}
|
|
1784
1786
|
|
|
1785
1787
|
_createCallSession(sipSession: WazoSession, fromSession?: CallSession | null | undefined, extra: Record<string, any> = {}): CallSession {
|
|
1786
|
-
|
|
1787
|
-
const
|
|
1788
|
-
|
|
1789
|
-
const number = identity ? identity.uri._normal.user : null;
|
|
1790
|
-
const {
|
|
1791
|
-
state,
|
|
1792
|
-
} = sipSession || {};
|
|
1788
|
+
const number = getCallNumber(sipSession);
|
|
1789
|
+
const displayName = getCallDisplayName(sipSession);
|
|
1790
|
+
const { state } = sipSession || {};
|
|
1793
1791
|
const sessionId = getSipSessionId(sipSession);
|
|
1792
|
+
|
|
1794
1793
|
fromSession = fromSession || this.callSessions[sessionId];
|
|
1795
1794
|
const callSession = new CallSession({
|
|
1796
1795
|
callId: fromSession && fromSession.callId,
|
|
1797
1796
|
sipCallId: sessionId,
|
|
1798
1797
|
sipStatus: state,
|
|
1799
|
-
displayName
|
|
1798
|
+
displayName,
|
|
1800
1799
|
// @ts-ignore: date / number
|
|
1801
1800
|
startTime: fromSession ? fromSession.startTime : new Date(),
|
|
1802
1801
|
creationTime: fromSession ? fromSession.creationTime : null,
|
|
@@ -1817,6 +1816,7 @@ export default class WebRTCPhone extends Emitter implements Phone {
|
|
|
1817
1816
|
...extra,
|
|
1818
1817
|
});
|
|
1819
1818
|
this.callSessions[sessionId] = callSession;
|
|
1819
|
+
|
|
1820
1820
|
return callSession;
|
|
1821
1821
|
}
|
|
1822
1822
|
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { default as ServerError } from './domain/ServerError';
|
|
|
7
7
|
export { default as InvalidStateTransition } from './domain/InvalidStateTransition';
|
|
8
8
|
export { default as InvalidState } from './domain/InvalidState';
|
|
9
9
|
export { default as SFUNotAvailableError } from './domain/SFUNotAvailableError';
|
|
10
|
-
export { default as
|
|
10
|
+
export { default as ApiCall } from './domain/Call';
|
|
11
11
|
export { default as CallLog } from './domain/CallLog';
|
|
12
12
|
export { default as Recording } from './domain/Recording';
|
|
13
13
|
export { default as ChatMessage } from './domain/ChatMessage';
|
package/src/service/CallApi.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ApiCall from '../domain/Call';
|
|
2
|
+
import Call from '../voice/call';
|
|
2
3
|
import CallLog from '../domain/CallLog';
|
|
3
4
|
import Line from '../domain/Line';
|
|
4
5
|
import Session from '../domain/Session';
|
|
5
6
|
import Relocation from '../domain/Relocation';
|
|
6
|
-
import CallSession from '../domain/CallSession';
|
|
7
7
|
import getApiClient from './getApiClient';
|
|
8
8
|
import Transfer from '../domain/IndirectTransfer';
|
|
9
9
|
|
|
@@ -16,7 +16,7 @@ export default class CallApi {
|
|
|
16
16
|
return getApiClient().callLogd.listDistinctCallLogs(offset, limit, distinct);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
static async fetchActiveCalls(): Promise<
|
|
19
|
+
static async fetchActiveCalls(): Promise<ApiCall[]> {
|
|
20
20
|
return getApiClient().calld.listCalls();
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -37,14 +37,14 @@ export default class CallApi {
|
|
|
37
37
|
return getApiClient().confd.getUserLineSip(session.uuid as string, lineToUse ? <unknown>lineToUse.id as string : '');
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
static async cancelCall(
|
|
41
|
-
return getApiClient().calld.cancelCall(
|
|
40
|
+
static async cancelCall(call: Call): Promise<boolean> {
|
|
41
|
+
return getApiClient().calld.cancelCall(call.apiId || '');
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
static async makeCall(callFromLine: Line, extension: string, isMobile = false, callbackAllLines = false): Promise<
|
|
44
|
+
static async makeCall(callFromLine: Line, extension: string, isMobile = false, callbackAllLines = false): Promise<ApiCall | null | undefined> {
|
|
45
45
|
const lineId = callFromLine ? callFromLine.id : null;
|
|
46
46
|
const response = await getApiClient().calld.makeCall(extension, isMobile, lineId, callbackAllLines);
|
|
47
|
-
return
|
|
47
|
+
return ApiCall.parse(response);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
static async relocateCall(callId: string, line: number, contactIdentifier?: string): Promise<Relocation> {
|
package/src/simple/Phone.ts
CHANGED
|
@@ -19,6 +19,7 @@ const sipLogger = IssueReporter.loggerFor('sip.js');
|
|
|
19
19
|
const protocolLogger = IssueReporter.loggerFor('sip');
|
|
20
20
|
const protocolDebugMessages = ['Received WebSocket text message:', 'Sending WebSocket message:'];
|
|
21
21
|
|
|
22
|
+
// @deprecated: Use Wazo.Voice.Softphone instead
|
|
22
23
|
export class Phone extends Emitter {
|
|
23
24
|
client: WazoWebRTCClient;
|
|
24
25
|
|
|
@@ -43,7 +43,7 @@ export type EstablishedActionTypes = typeof EstablishedActions[keyof typeof Esta
|
|
|
43
43
|
|
|
44
44
|
const callMachine = setup({
|
|
45
45
|
guards: {
|
|
46
|
-
isRegistered: () => softphone.
|
|
46
|
+
isRegistered: () => softphone.state === SoftphoneStates.REGISTERED,
|
|
47
47
|
},
|
|
48
48
|
}).createMachine({
|
|
49
49
|
id: 'call',
|
|
@@ -8,8 +8,8 @@ import IssueReporter from '../service/IssueReporter';
|
|
|
8
8
|
|
|
9
9
|
const logger = IssueReporter.loggerFor('state-machine');
|
|
10
10
|
|
|
11
|
-
export const getState = (actor: SoftphoneActorRef | CallActorRef): SoftphoneStates | CallStates | EstablishedStateTypes => {
|
|
12
|
-
return actor.getSnapshot().value as SoftphoneStates | CallStates | EstablishedStateTypes
|
|
11
|
+
export const getState = (actor: SoftphoneActorRef | CallActorRef): SoftphoneStates | CallStates | EstablishedStateTypes | Record<CallStates, EstablishedStateTypes> => {
|
|
12
|
+
return actor.getSnapshot().value as SoftphoneStates | CallStates | EstablishedStateTypes | Record<CallStates, EstablishedStateTypes>;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export const can = (actor: SoftphoneActorRef | CallActorRef, action: SoftphoneActions | CallActions | EstablishedCallActions): boolean => {
|
package/src/utils/sdp.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
1
2
|
import sdpParser from 'sdp-transform';
|
|
2
3
|
import { UserAgent } from 'sip.js/lib/api/user-agent';
|
|
3
4
|
import { Inviter } from 'sip.js/lib/api';
|
|
@@ -174,3 +175,18 @@ export const replaceLocalIpModifier = (description: Record<string, any>) => Prom
|
|
|
174
175
|
});
|
|
175
176
|
|
|
176
177
|
export const makeURI = (target: string, host: string): URI | undefined => UserAgent.makeURI(`sip:${target}@${host}`);
|
|
178
|
+
|
|
179
|
+
export const getCallNumber = (sipCall: SipCall): string => {
|
|
180
|
+
// eslint-disable-next-line
|
|
181
|
+
const identity = sipCall ? sipCall.remoteIdentity || sipCall.assertedIdentity : null;
|
|
182
|
+
// @ts-ignore: private
|
|
183
|
+
return identity ? identity.uri._normal.user : null;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export const getCallDisplayName = (sipCall: SipCall): string => {
|
|
187
|
+
// eslint-disable-next-line
|
|
188
|
+
const identity = sipCall ? sipCall.remoteIdentity || sipCall.assertedIdentity : null;
|
|
189
|
+
const number = getCallNumber(sipCall);
|
|
190
|
+
|
|
191
|
+
return identity ? identity.displayName || number : number;
|
|
192
|
+
};
|
package/src/utils/webrtc.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* eslint-disable no-underscore-dangle, no-param-reassign */
|
|
1
|
+
/* eslint-disable no-underscore-dangle, no-param-reassign, no-restricted-syntax */
|
|
2
2
|
import type { SessionDescriptionHandler } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler';
|
|
3
3
|
import type { SessionDescriptionHandlerFactoryOptions } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-factory-options';
|
|
4
4
|
import type { SessionDescriptionHandlerConfiguration } from 'sip.js/lib/platform/web/session-description-handler/session-description-handler-configuration';
|
|
@@ -246,6 +246,28 @@ export const toggleVideo = (sipCall: SipCall, muteCamera: boolean): void => {
|
|
|
246
246
|
}
|
|
247
247
|
};
|
|
248
248
|
|
|
249
|
+
export const isVideoMuted = (sipCall: SipCall): boolean => {
|
|
250
|
+
const sdh = sipCall.sessionDescriptionHandler as SessionDescriptionHandler;
|
|
251
|
+
const pc = sdh?.peerConnection as PeerConnection;
|
|
252
|
+
|
|
253
|
+
if (pc?.getSenders) {
|
|
254
|
+
for (const sender of pc.getSenders()) {
|
|
255
|
+
if (sender && sender.track && sender.track.kind === 'video') {
|
|
256
|
+
return !sender.track.enabled;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
for (const stream of pc.getLocalStreams()) {
|
|
261
|
+
// eslint-disable-next-line no-unreachable-loop
|
|
262
|
+
for (const track of stream.getVideoTracks()) {
|
|
263
|
+
return !track.enabled;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return true;
|
|
269
|
+
};
|
|
270
|
+
|
|
249
271
|
export const cleanupStream = (stream: MediaStream): void => {
|
|
250
272
|
stream.getTracks().filter(track => track.enabled).forEach(track => track.stop());
|
|
251
273
|
};
|