@wazo/sdk 1.0.0-alpha.0 → 1.0.0-alpha.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/dist/wazo-sdk.js +6 -6
- package/esm/__tests__/__voice__/call.test.js +44 -2
- package/esm/__tests__/api-client.test.js +20 -1
- package/esm/api/auth.js +13 -2
- package/esm/domain/Phone/WebRTCPhone.js +6 -7
- package/esm/index.js +2 -0
- package/esm/simple/Auth.js +6 -12
- package/esm/simple/Phone.js +1 -0
- package/esm/simple/__tests__/Auth.test.js +8 -64
- package/esm/state-machine/call-state-machine.js +1 -1
- package/esm/types/api/auth.d.ts.map +1 -1
- package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/esm/types/index.d.ts +2 -0
- package/esm/types/index.d.ts.map +1 -1
- package/esm/types/simple/Auth.d.ts.map +1 -1
- package/esm/types/simple/Phone.d.ts.map +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/api-requester.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 +19 -11
- package/esm/types/voice/call.d.ts.map +1 -1
- package/esm/types/voice/softphone.d.ts +18 -13
- package/esm/types/voice/softphone.d.ts.map +1 -1
- package/esm/utils/__tests__/api-requester.test.js +17 -0
- package/esm/utils/api-requester.js +9 -1
- package/esm/utils/sdp.js +13 -0
- package/esm/utils/webrtc.js +21 -1
- package/esm/voice/call.js +90 -30
- package/esm/voice/softphone.js +94 -23
- package/lib/__tests__/__voice__/call.test.js +43 -1
- package/lib/__tests__/api-client.test.js +20 -1
- package/lib/api/auth.js +13 -2
- package/lib/domain/Phone/WebRTCPhone.js +5 -6
- package/lib/index.js +6 -2
- package/lib/simple/Auth.js +6 -12
- package/lib/simple/Phone.js +1 -0
- package/lib/simple/__tests__/Auth.test.js +11 -64
- package/lib/state-machine/call-state-machine.js +1 -1
- package/lib/types/api/auth.d.ts.map +1 -1
- package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/simple/Auth.d.ts.map +1 -1
- package/lib/types/simple/Phone.d.ts.map +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/api-requester.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 +19 -11
- package/lib/types/voice/call.d.ts.map +1 -1
- package/lib/types/voice/softphone.d.ts +18 -13
- package/lib/types/voice/softphone.d.ts.map +1 -1
- package/lib/utils/__tests__/api-requester.test.js +17 -0
- package/lib/utils/api-requester.js +9 -1
- package/lib/utils/sdp.js +16 -1
- package/lib/utils/webrtc.js +23 -2
- package/lib/voice/call.js +87 -28
- package/lib/voice/softphone.js +95 -23
- package/package.json +1 -1
- package/src/__tests__/__voice__/call.test.ts +47 -2
- package/src/__tests__/api-client.test.ts +22 -1
- package/src/api/auth.ts +25 -3
- package/src/domain/Phone/WebRTCPhone.ts +9 -9
- package/src/index.ts +2 -0
- package/src/simple/Auth.ts +6 -13
- package/src/simple/Phone.ts +1 -0
- package/src/simple/__tests__/Auth.test.ts +9 -87
- package/src/state-machine/call-state-machine.ts +1 -1
- package/src/state-machine/utils.ts +2 -2
- package/src/utils/__tests__/api-requester.test.ts +20 -0
- package/src/utils/api-requester.ts +9 -1
- package/src/utils/sdp.ts +16 -0
- package/src/utils/webrtc.ts +24 -2
- package/src/voice/call.ts +118 -40
- package/src/voice/softphone.ts +116 -30
- package/src/web-rtc-client.ts +1 -1
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import { OutgoingInviteRequest } from 'sip.js/lib/core';
|
|
4
4
|
import type { IncomingRequestMessage } from 'sip.js/lib/core/messages/incoming-request-message';
|
|
5
|
-
import { type
|
|
5
|
+
import { type StateTypes, type EstablishedStateTypes, type CallActorRef } from '../state-machine/call-state-machine';
|
|
6
6
|
import { SipCall } from '../domain/types';
|
|
7
|
+
import ApiCall from '../domain/Call';
|
|
7
8
|
import { Softphone } from './softphone';
|
|
8
9
|
export type AcceptOptions = {
|
|
9
10
|
withCamera?: boolean;
|
|
@@ -37,12 +38,10 @@ export declare const EVENT_SHARE_SCREEN_ENDED = "onScreenShareEnded";
|
|
|
37
38
|
export declare const EVENT_WEB_RTC_STATS = "webRtcStats";
|
|
38
39
|
export declare const EVENT_CAMERA_RESUMED = "onCameraResumed";
|
|
39
40
|
export declare const EVENT_CAMERA_DISABLED = "onCameraDisabled";
|
|
40
|
-
export declare const EVENT_TERMINATE_SOUND = "terminateSound";
|
|
41
41
|
export declare const MESSAGE_TYPE_CHAT = "message/TYPE_CHAT";
|
|
42
42
|
export declare const MESSAGE_TYPE_SIGNAL = "message/TYPE_SIGNAL";
|
|
43
43
|
export declare const MESSAGE_TRACK_UPDATED = "onTrackUpdated";
|
|
44
44
|
declare class Call extends EventEmitter {
|
|
45
|
-
eventEmitter: EventEmitter;
|
|
46
45
|
callActor: CallActorRef;
|
|
47
46
|
apiId?: string;
|
|
48
47
|
sipCall: SipCall;
|
|
@@ -52,19 +51,25 @@ declare class Call extends EventEmitter {
|
|
|
52
51
|
endTime: Date;
|
|
53
52
|
phone: Softphone;
|
|
54
53
|
shouldSendReinvite: boolean;
|
|
54
|
+
recording: boolean;
|
|
55
|
+
displayName: string | null;
|
|
56
|
+
number: string | null;
|
|
55
57
|
currentScreenShare: Record<string, any> | null;
|
|
58
|
+
static parseCall(apiCall: ApiCall): Call;
|
|
56
59
|
constructor(sipCall: SipCall, phone: Softphone);
|
|
57
60
|
accept(options?: AcceptOptions): Promise<string | null>;
|
|
58
61
|
reject(): Promise<boolean>;
|
|
59
62
|
hangup(): Promise<boolean>;
|
|
60
63
|
forceCancel(): void;
|
|
61
|
-
startConference(
|
|
64
|
+
startConference(): void;
|
|
62
65
|
mute(): void;
|
|
63
66
|
unMute(): void;
|
|
64
67
|
hold(): Promise<void | OutgoingInviteRequest>;
|
|
65
68
|
resume(): Promise<MediaStream | null | undefined>;
|
|
66
69
|
turnCameraOn(): void;
|
|
67
70
|
turnCameraOff(): void;
|
|
71
|
+
isMuted(): boolean;
|
|
72
|
+
isCameraMuted(): boolean;
|
|
68
73
|
isHeld(): boolean;
|
|
69
74
|
isEstablished(): boolean;
|
|
70
75
|
isConference(): boolean;
|
|
@@ -86,6 +91,7 @@ declare class Call extends EventEmitter {
|
|
|
86
91
|
onEarlyMedia(): void;
|
|
87
92
|
onTrack(event: RTCTrackEvent | MediaStreamTrackEvent): void;
|
|
88
93
|
onError(error: Error): void;
|
|
94
|
+
onCallIncoming(): void;
|
|
89
95
|
onRejected(): void;
|
|
90
96
|
onNetworkStats(stats: Record<string, any>, previousStats: Record<string, any>): void;
|
|
91
97
|
getRemoteStream(): MediaStream | null;
|
|
@@ -96,15 +102,17 @@ declare class Call extends EventEmitter {
|
|
|
96
102
|
getLocalVideoStream(): MediaStream | null | undefined;
|
|
97
103
|
hasALocalVideoTrack(): boolean;
|
|
98
104
|
isVideoRemotelyHeld(): boolean;
|
|
105
|
+
isRinging(): boolean;
|
|
99
106
|
onReinvite(request: IncomingRequestMessage, updatedCalleeName: string, updatedNumber: string, hadRemoteVideo: boolean): void;
|
|
100
107
|
get id(): string;
|
|
101
|
-
get
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
get state(): StateTypes | Record<StateTypes, EstablishedStateTypes>;
|
|
109
|
+
private _hasEstablishedState;
|
|
110
|
+
private _bindEvents;
|
|
111
|
+
private _downgradeToAudio;
|
|
112
|
+
private _upgradeToVideo;
|
|
113
|
+
private _sendReinviteMessage;
|
|
114
|
+
private _onScreenSharing;
|
|
115
|
+
private _sendAction;
|
|
108
116
|
}
|
|
109
117
|
export default Call;
|
|
110
118
|
//# sourceMappingURL=call.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../../../src/voice/call.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mDAAmD,CAAC;AAEhG,OAAyB,
|
|
1
|
+
{"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../../../src/voice/call.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mDAAmD,CAAC;AAEhG,OAAyB,EAAsF,KAAK,UAAU,EAAqB,KAAK,qBAAqB,EAAE,KAAK,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAC9O,OAAO,EAAE,OAAO,EAAkB,MAAM,iBAAiB,CAAC;AAC1D,OAAO,OAAO,MAAM,gBAAgB,CAAC;AAGrC,OAAkB,EAAyB,SAAS,EAAE,MAAM,aAAa,CAAC;AAO1E,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAGF,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,iBAAiB,eAAe,CAAC;AAC9C,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,eAAO,MAAM,mBAAmB,aAAa,CAAC;AAC9C,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AACpD,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,eAAO,MAAM,mBAAmB,YAAY,CAAC;AAC7C,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAC5C,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAClD,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AACpD,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAC/D,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AACjE,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAC7D,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AACjD,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AACtD,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AACzD,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AAEtD,cAAM,IAAK,SAAQ,YAAY;IAC7B,SAAS,EAAE,YAAY,CAAC;IAGxB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,OAAO,EAAE,OAAO,CAAC;IAEjB,YAAY,EAAE,MAAM,EAAE,CAAC;IAEvB,YAAY,EAAE,IAAI,CAAC;IAEnB,UAAU,EAAE,IAAI,CAAC;IAEjB,OAAO,EAAE,IAAI,CAAC;IAEd,KAAK,EAAE,SAAS,CAAC;IAEjB,kBAAkB,UAAS;IAE3B,SAAS,UAAS;IAElB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtB,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IAE/C,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;gBAmD5B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;IAiBxC,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAsB3D,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAW1B,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAYhC,WAAW,IAAI,IAAI;IASnB,eAAe;IAef,IAAI;IAWJ,MAAM;IAWA,IAAI;IAyBJ,MAAM;IA2CZ,YAAY,IAAI,IAAI;IAQpB,aAAa,IAAI,IAAI;IAQrB,OAAO;IAIP,aAAa;IAIb,MAAM;IAIN,aAAa;IAIb,YAAY,IAAI,OAAO;IAIvB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAO9B,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,SAAS;IAOhD,UAAU,CAAC,MAAM,EAAE,MAAM;IAQzB,sBAAsB,CAAC,QAAQ,SAAO;IAOtC,qBAAqB;IAOf,QAAQ,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,GAAG,SAAS,CAAC;IAItD,YAAY,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IA0BxF,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,SAAe,GAAG,IAAI;IAO3D,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO/B,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAOxB,kBAAkB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAoC1E,iBAAiB,CAAC,kBAAkB,UAAO,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAAC;IA6ChG,qBAAqB,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO;IAOrD,UAAU;IAKV,UAAU;IAIV,YAAY;IAIZ,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,qBAAqB;IAIpD,OAAO,CAAC,KAAK,EAAE,KAAK;IAIpB,cAAc;IAId,UAAU;IAQV,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAI7E,eAAe;IAIf,oBAAoB;IAIpB,cAAc;IAId,aAAa;IAIb,cAAc;IAId,mBAAmB;IAInB,mBAAmB;IAInB,mBAAmB;IAInB,SAAS;IAIT,UAAU,CAAC,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO;IAIrH,IAAI,EAAE,WAEL;IAED,IAAI,KAAK,IAAI,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAElE;IAED,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,WAAW;IA8EnB,OAAO,CAAC,iBAAiB;YAcX,eAAe;IA8B7B,OAAO,CAAC,oBAAoB;IAmB5B,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,WAAW;CAGpB;AAED,eAAe,IAAI,CAAC"}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
|
-
import type { Message } from 'sip.js/lib/api/message';
|
|
4
3
|
import type Session from '../domain/Session';
|
|
5
4
|
import type SipLine from '../domain/SipLine';
|
|
6
|
-
import { type SoftphoneActorRef, type StateTypes
|
|
7
|
-
import { WebRtcConfig
|
|
5
|
+
import { type SoftphoneActorRef, type StateTypes } from '../state-machine/softphone-state-machine';
|
|
6
|
+
import { WebRtcConfig } from '../domain/types';
|
|
8
7
|
import WazoWebRTCClient from '../web-rtc-client';
|
|
9
8
|
import Call from './call';
|
|
10
9
|
export declare const EVENT_INCOMING = "incoming";
|
|
10
|
+
export declare const EVENT_OUTGOING = "outgoing";
|
|
11
11
|
export declare const EVENT_HEARTBEAT = "heartbeat";
|
|
12
12
|
export declare const EVENT_HEARTBEAT_TIMEOUT = "heartbeatTimeout";
|
|
13
13
|
export declare const EVENT_REGISTERED = "registered";
|
|
14
14
|
export declare const EVENT_UNREGISTERED = "unregistered";
|
|
15
15
|
export declare const EVENT_DISCONNECTED = "disconnected";
|
|
16
16
|
export declare const EVENT_VIDEO_INPUT_CHANGE = "videoInputChange";
|
|
17
|
+
export declare const EVENT_TERMINATE_SOUND = "terminateSound";
|
|
18
|
+
export declare const EVENT_PLAY_HANGUP_SOUND = "playHangupSound";
|
|
19
|
+
export declare const EVENT_PLAY_RING_SOUND = "playRingSound";
|
|
20
|
+
export declare const EVENT_PLAY_INBOUND_CALL_SOUND = "playInboundCallSound";
|
|
17
21
|
export declare const EVENT_ON_MESSAGE = "message";
|
|
18
22
|
export declare const EVENT_ON_CHAT = "phone/ON_CHAT";
|
|
19
23
|
export declare const EVENT_ON_SIGNAL = "phone/ON_SIGNAL";
|
|
@@ -32,7 +36,6 @@ export declare class Softphone extends EventEmitter {
|
|
|
32
36
|
audioRingDeviceId?: string;
|
|
33
37
|
audioOutputVolume: number;
|
|
34
38
|
audioRingVolume: number;
|
|
35
|
-
eventEmitter: EventEmitter;
|
|
36
39
|
calls: Call[];
|
|
37
40
|
client: WazoWebRTCClient;
|
|
38
41
|
session: Session;
|
|
@@ -40,6 +43,7 @@ export declare class Softphone extends EventEmitter {
|
|
|
40
43
|
softphoneActor: SoftphoneActorRef;
|
|
41
44
|
options: Partial<WebRtcConfig>;
|
|
42
45
|
shouldSendReinvite: boolean;
|
|
46
|
+
ringingEnabled: boolean;
|
|
43
47
|
constructor();
|
|
44
48
|
connect(options?: Partial<WebRtcConfig>): Promise<void>;
|
|
45
49
|
disconnect(): Promise<void | null>;
|
|
@@ -48,6 +52,9 @@ export declare class Softphone extends EventEmitter {
|
|
|
48
52
|
reconnect(): void;
|
|
49
53
|
call(options: CallOptions): Promise<Call | null>;
|
|
50
54
|
removeCall(callToRemove: Call): void;
|
|
55
|
+
onCallTerminated(call: Call): void;
|
|
56
|
+
enableRinging(): Promise<void> | void;
|
|
57
|
+
disableRinging(): Promise<void> | void;
|
|
51
58
|
holdAllCalls(exceptCall?: Call | null): void;
|
|
52
59
|
startHeartbeat(): void;
|
|
53
60
|
stopHeartbeat(): void;
|
|
@@ -59,18 +66,16 @@ export declare class Softphone extends EventEmitter {
|
|
|
59
66
|
hasSfu(): boolean;
|
|
60
67
|
changeAudioVolume(volume: number): void;
|
|
61
68
|
changeRingVolume(volume: number): void;
|
|
62
|
-
getCalls(): Call[];
|
|
63
69
|
getCurrentCall(): Call | undefined;
|
|
64
|
-
|
|
70
|
+
getIncomingCalls(): Call[];
|
|
71
|
+
get state(): StateTypes;
|
|
65
72
|
getUserAgent(): string;
|
|
73
|
+
isRegistered(): boolean;
|
|
66
74
|
_bindEvents(): void;
|
|
67
|
-
_sendAction
|
|
68
|
-
_getCall
|
|
69
|
-
_onCallEvent
|
|
70
|
-
_onMessage
|
|
71
|
-
method?: string;
|
|
72
|
-
body?: string;
|
|
73
|
-
}): void;
|
|
75
|
+
private _sendAction;
|
|
76
|
+
private _getCall;
|
|
77
|
+
private _onCallEvent;
|
|
78
|
+
private _onMessage;
|
|
74
79
|
}
|
|
75
80
|
declare const _default: Softphone;
|
|
76
81
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"softphone.d.ts","sourceRoot":"","sources":["../../../src/voice/softphone.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"softphone.d.ts","sourceRoot":"","sources":["../../../src/voice/softphone.ts"],"names":[],"mappings":"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"}
|
|
@@ -147,3 +147,20 @@ describe('With a refresh token', () => {
|
|
|
147
147
|
});
|
|
148
148
|
});
|
|
149
149
|
});
|
|
150
|
+
describe('base64Encode', () => {
|
|
151
|
+
it('should encode a string using base64', () => {
|
|
152
|
+
const input = 'Hello World!';
|
|
153
|
+
const expectedOutput = 'SGVsbG8gV29ybGQh';
|
|
154
|
+
expect(ApiRequester.base64Encode(input)).toBe(expectedOutput);
|
|
155
|
+
});
|
|
156
|
+
it('should handle special characters', () => {
|
|
157
|
+
const input = 'éà$@€';
|
|
158
|
+
const expectedOutput = 'w6nDoCRA4oKs';
|
|
159
|
+
expect(ApiRequester.base64Encode(input)).toBe(expectedOutput);
|
|
160
|
+
});
|
|
161
|
+
it('should handle empty string', () => {
|
|
162
|
+
const input = '';
|
|
163
|
+
const expectedOutput = '';
|
|
164
|
+
expect(ApiRequester.base64Encode(input)).toBe(expectedOutput);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
@@ -32,7 +32,15 @@ export default class ApiRequester {
|
|
|
32
32
|
return Object.keys(obj).filter(key => obj[key]).map(key => `${key}=${encodeURIComponent(obj[key])}`).join('&');
|
|
33
33
|
}
|
|
34
34
|
static base64Encode(str) {
|
|
35
|
-
|
|
35
|
+
if (typeof btoa !== 'undefined') {
|
|
36
|
+
try {
|
|
37
|
+
return btoa(str);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
// fall back to Base64.encode if btoa fails
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return Base64.encode(str);
|
|
36
44
|
}
|
|
37
45
|
// @see https://github.com/facebook/flow/issues/183#issuecomment-358607052
|
|
38
46
|
constructor({ server, refreshTokenCallback, clientId, agent = null, token = null, fetchOptions, requestTimeout = REQUEST_TIMEOUT_MS, }) {
|
package/esm/utils/sdp.js
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';
|
|
@@ -128,3 +129,15 @@ export const replaceLocalIpModifier = (description) => Promise.resolve({
|
|
|
128
129
|
sdp: description.sdp.replace('c=IN IP4 0.0.0.0', 'c=IN IP4 127.0.0.1'),
|
|
129
130
|
});
|
|
130
131
|
export const makeURI = (target, host) => UserAgent.makeURI(`sip:${target}@${host}`);
|
|
132
|
+
export const getCallNumber = (sipCall) => {
|
|
133
|
+
// eslint-disable-next-line
|
|
134
|
+
const identity = sipCall ? sipCall.remoteIdentity || sipCall.assertedIdentity : null;
|
|
135
|
+
// @ts-ignore: private
|
|
136
|
+
return identity ? identity.uri._normal.user : null;
|
|
137
|
+
};
|
|
138
|
+
export const getCallDisplayName = (sipCall) => {
|
|
139
|
+
// eslint-disable-next-line
|
|
140
|
+
const identity = sipCall ? sipCall.remoteIdentity || sipCall.assertedIdentity : null;
|
|
141
|
+
const number = getCallNumber(sipCall);
|
|
142
|
+
return identity ? identity.displayName || number : number;
|
|
143
|
+
};
|
package/esm/utils/webrtc.js
CHANGED
|
@@ -173,6 +173,26 @@ export const toggleVideo = (sipCall, muteCamera) => {
|
|
|
173
173
|
});
|
|
174
174
|
}
|
|
175
175
|
};
|
|
176
|
+
export const isVideoMuted = (sipCall) => {
|
|
177
|
+
const sdh = sipCall.sessionDescriptionHandler;
|
|
178
|
+
const pc = sdh?.peerConnection;
|
|
179
|
+
if (pc?.getSenders) {
|
|
180
|
+
for (const sender of pc.getSenders()) {
|
|
181
|
+
if (sender && sender.track && sender.track.kind === 'video') {
|
|
182
|
+
return !sender.track.enabled;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
for (const stream of pc.getLocalStreams()) {
|
|
188
|
+
// eslint-disable-next-line no-unreachable-loop
|
|
189
|
+
for (const track of stream.getVideoTracks()) {
|
|
190
|
+
return !track.enabled;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return true;
|
|
195
|
+
};
|
|
176
196
|
export const cleanupStream = (stream) => {
|
|
177
197
|
stream.getTracks().filter(track => track.enabled).forEach(track => track.stop());
|
|
178
198
|
};
|
|
@@ -241,7 +261,7 @@ export const getMediaConfiguration = (enableVideo, conference = false, constrain
|
|
|
241
261
|
return {
|
|
242
262
|
constraints: {
|
|
243
263
|
// Exact constraint are not supported with `getDisplayMedia` and we must have a video=false in desktop screenshare
|
|
244
|
-
audio: screenSharing ? !isDesktop :
|
|
264
|
+
audio: screenSharing ? !isDesktop : withAudio ? getAudioConstraints(true) : false,
|
|
245
265
|
video: screenSharing ? isDesktop ? {
|
|
246
266
|
mandatory: {
|
|
247
267
|
chromeMediaSource: 'desktop',
|
package/esm/voice/call.js
CHANGED
|
@@ -5,9 +5,10 @@ import { Invitation } from 'sip.js/lib/api/invitation';
|
|
|
5
5
|
import { SessionState } from 'sip.js/lib/api/session-state';
|
|
6
6
|
import callStateMachine, { Actions, EstablishedActions, States, EstablishedStates } from '../state-machine/call-state-machine';
|
|
7
7
|
import IssueReporter from '../service/IssueReporter';
|
|
8
|
-
import {
|
|
8
|
+
import softphone, { EVENT_TERMINATE_SOUND } from './softphone';
|
|
9
|
+
import { getCallDisplayName, getCallNumber, getSipSessionId } from '../utils/sdp';
|
|
9
10
|
import { assertCan, assertState, getState } from '../state-machine/utils';
|
|
10
|
-
import { downgradeToAudio, getLocalStream, getLocalVideoStream, getPeerConnection, getRemoteStream, getRemoteVideoStream, getStreamFromConstraints, getWebRtcStats, hasALocalVideoTrack, hasLocalVideo, hasRemoteVideo, isVideoRemotelyHeld, setLocalMediaStream, toggleVideo, upgradeToVideo } from '../utils/webrtc';
|
|
11
|
+
import { downgradeToAudio, getLocalStream, getLocalVideoStream, getPeerConnection, getRemoteStream, getRemoteVideoStream, getStreamFromConstraints, getWebRtcStats, hasALocalVideoTrack, hasLocalVideo, hasRemoteVideo, isVideoMuted, isVideoRemotelyHeld, setLocalMediaStream, toggleVideo, upgradeToVideo } from '../utils/webrtc';
|
|
11
12
|
const logger = IssueReporter.loggerFor('call');
|
|
12
13
|
// Events
|
|
13
14
|
export const EVENT_CALL_ACCEPTED = 'accepted';
|
|
@@ -33,12 +34,10 @@ export const EVENT_SHARE_SCREEN_ENDED = 'onScreenShareEnded';
|
|
|
33
34
|
export const EVENT_WEB_RTC_STATS = 'webRtcStats';
|
|
34
35
|
export const EVENT_CAMERA_RESUMED = 'onCameraResumed';
|
|
35
36
|
export const EVENT_CAMERA_DISABLED = 'onCameraDisabled';
|
|
36
|
-
export const EVENT_TERMINATE_SOUND = 'terminateSound';
|
|
37
37
|
export const MESSAGE_TYPE_CHAT = 'message/TYPE_CHAT';
|
|
38
38
|
export const MESSAGE_TYPE_SIGNAL = 'message/TYPE_SIGNAL';
|
|
39
39
|
export const MESSAGE_TRACK_UPDATED = 'onTrackUpdated';
|
|
40
40
|
class Call extends EventEmitter {
|
|
41
|
-
eventEmitter;
|
|
42
41
|
callActor;
|
|
43
42
|
// Wazo call id, used in Wazo Websocket and API
|
|
44
43
|
apiId;
|
|
@@ -49,7 +48,52 @@ class Call extends EventEmitter {
|
|
|
49
48
|
endTime;
|
|
50
49
|
phone;
|
|
51
50
|
shouldSendReinvite = false;
|
|
51
|
+
recording = false;
|
|
52
|
+
displayName;
|
|
53
|
+
number;
|
|
52
54
|
currentScreenShare;
|
|
55
|
+
static parseCall(apiCall) {
|
|
56
|
+
const sipCall = {
|
|
57
|
+
id: apiCall.sipCallId,
|
|
58
|
+
stateChange: {
|
|
59
|
+
addListener: () => { },
|
|
60
|
+
},
|
|
61
|
+
remoteIdentity: {
|
|
62
|
+
uri: {
|
|
63
|
+
_normal: {
|
|
64
|
+
user: apiCall.calleeNumber,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
// Mock sdk so `hasLocalVideo` will return true.
|
|
69
|
+
sessionDescriptionHandler: {
|
|
70
|
+
localMediaStream: {
|
|
71
|
+
getTracks: () => (apiCall.isVideo ? [{ kind: 'video', readyState: 'live' }] : []),
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
const call = new Call(sipCall, softphone);
|
|
76
|
+
// call._sendAction(Actions.ES);
|
|
77
|
+
call.apiId = apiCall.id;
|
|
78
|
+
call.answerTime = new Date(+apiCall.startingTime);
|
|
79
|
+
// Update call state
|
|
80
|
+
const snapshot = call.callActor.getSnapshot();
|
|
81
|
+
if (apiCall.isUp()) {
|
|
82
|
+
snapshot.value = { [States.ESTABLISHED]: EstablishedStates.ONGOING };
|
|
83
|
+
}
|
|
84
|
+
if (apiCall.muted) {
|
|
85
|
+
snapshot.value = { [States.ESTABLISHED]: EstablishedStates.MUTED };
|
|
86
|
+
}
|
|
87
|
+
if (apiCall.isRinging()) {
|
|
88
|
+
snapshot.value = States.RINGING;
|
|
89
|
+
}
|
|
90
|
+
if (apiCall.isRecording()) {
|
|
91
|
+
call.recording = true;
|
|
92
|
+
}
|
|
93
|
+
// @ts-ignore
|
|
94
|
+
call.callActor.update(snapshot);
|
|
95
|
+
return call;
|
|
96
|
+
}
|
|
53
97
|
constructor(sipCall, phone) {
|
|
54
98
|
super();
|
|
55
99
|
this.callActor = createActor(callStateMachine);
|
|
@@ -57,6 +101,8 @@ class Call extends EventEmitter {
|
|
|
57
101
|
this.creationTime = new Date();
|
|
58
102
|
this.phone = phone;
|
|
59
103
|
this.sipCall = sipCall;
|
|
104
|
+
this.number = getCallNumber(sipCall);
|
|
105
|
+
this.displayName = getCallDisplayName(sipCall);
|
|
60
106
|
this._bindEvents();
|
|
61
107
|
}
|
|
62
108
|
async accept(options = {}) {
|
|
@@ -78,7 +124,7 @@ class Call extends EventEmitter {
|
|
|
78
124
|
async reject() {
|
|
79
125
|
assertCan(this.callActor, Actions.REJECT);
|
|
80
126
|
logger.info('call - reject', { id: this.id });
|
|
81
|
-
this.
|
|
127
|
+
this.phone.emit(EVENT_TERMINATE_SOUND, 'call rejected locally');
|
|
82
128
|
this.shouldSendReinvite = false;
|
|
83
129
|
return this.hangup();
|
|
84
130
|
}
|
|
@@ -87,7 +133,7 @@ class Call extends EventEmitter {
|
|
|
87
133
|
logger.info('call - hangup', { id: this.id });
|
|
88
134
|
await this.phone.client.hangup(this.sipCall);
|
|
89
135
|
// Remove this call from softphone's calls
|
|
90
|
-
this.phone.
|
|
136
|
+
this.phone.onCallTerminated(this);
|
|
91
137
|
return true;
|
|
92
138
|
}
|
|
93
139
|
forceCancel() {
|
|
@@ -99,7 +145,7 @@ class Call extends EventEmitter {
|
|
|
99
145
|
logger.info('call - force cancel, error', e);
|
|
100
146
|
}
|
|
101
147
|
}
|
|
102
|
-
startConference(withCalls) {
|
|
148
|
+
startConference( /* withCalls: Call[] */) {
|
|
103
149
|
// @TODO
|
|
104
150
|
// const participants = [this, ...withCalls].reduce((acc: Record<string, any>, call: Call) => {
|
|
105
151
|
// acc[call.talkingToIds[0]] = call;
|
|
@@ -117,14 +163,14 @@ class Call extends EventEmitter {
|
|
|
117
163
|
logger.info('call - mute', { id: this.id });
|
|
118
164
|
this._sendAction(EstablishedActions.MUTE);
|
|
119
165
|
this.phone.client.mute(this.sipCall);
|
|
120
|
-
this.
|
|
166
|
+
this.emit(EVENT_CALL_MUTED);
|
|
121
167
|
}
|
|
122
168
|
unMute() {
|
|
123
169
|
assertCan(this.callActor, EstablishedActions.UN_MUTE);
|
|
124
170
|
logger.info('call - un-mute', { id: this.id });
|
|
125
171
|
this._sendAction(EstablishedActions.UN_MUTE);
|
|
126
172
|
this.phone.client.unmute(this.sipCall);
|
|
127
|
-
this.
|
|
173
|
+
this.emit(EVENT_CALL_UN_MUTED);
|
|
128
174
|
}
|
|
129
175
|
async hold() {
|
|
130
176
|
assertCan(this.callActor, EstablishedActions.HOLD);
|
|
@@ -140,7 +186,7 @@ class Call extends EventEmitter {
|
|
|
140
186
|
await downgradeToAudio(this.sipCall);
|
|
141
187
|
}
|
|
142
188
|
const promise = this.phone.client.hold(this.sipCall, this.isConference(), hasVideo);
|
|
143
|
-
this.
|
|
189
|
+
this.emit(EVENT_CALL_HELD);
|
|
144
190
|
return promise;
|
|
145
191
|
}
|
|
146
192
|
async resume() {
|
|
@@ -167,7 +213,7 @@ class Call extends EventEmitter {
|
|
|
167
213
|
this._onScreenSharing(stream, hadVideo, wasDesktop);
|
|
168
214
|
}
|
|
169
215
|
};
|
|
170
|
-
this.
|
|
216
|
+
this.emit(EVENT_CALL_RESUMED);
|
|
171
217
|
return promise.then(() => {
|
|
172
218
|
const stream = this.getLocalVideoStream();
|
|
173
219
|
if (wasScreensharing) {
|
|
@@ -180,19 +226,25 @@ class Call extends EventEmitter {
|
|
|
180
226
|
assertState(this.callActor, States.ESTABLISHED);
|
|
181
227
|
logger.info('call - turn camera on', { id: this.id });
|
|
182
228
|
toggleVideo(this.sipCall, true);
|
|
183
|
-
this.
|
|
229
|
+
this.emit(EVENT_CAMERA_RESUMED);
|
|
184
230
|
}
|
|
185
231
|
turnCameraOff() {
|
|
186
232
|
assertState(this.callActor, States.ESTABLISHED);
|
|
187
233
|
logger.info('call - turn camera off', { id: this.id });
|
|
188
234
|
toggleVideo(this.sipCall, false);
|
|
189
|
-
this.
|
|
235
|
+
this.emit(EVENT_CAMERA_DISABLED);
|
|
236
|
+
}
|
|
237
|
+
isMuted() {
|
|
238
|
+
return this._hasEstablishedState(EstablishedStates.MUTED);
|
|
239
|
+
}
|
|
240
|
+
isCameraMuted() {
|
|
241
|
+
return isVideoMuted(this.sipCall);
|
|
190
242
|
}
|
|
191
243
|
isHeld() {
|
|
192
|
-
return
|
|
244
|
+
return this._hasEstablishedState(EstablishedStates.HELD);
|
|
193
245
|
}
|
|
194
246
|
isEstablished() {
|
|
195
|
-
return
|
|
247
|
+
return States.ESTABLISHED in this.state;
|
|
196
248
|
}
|
|
197
249
|
isConference() {
|
|
198
250
|
return getPeerConnection(this.sipCall)?.sfu;
|
|
@@ -320,7 +372,7 @@ class Call extends EventEmitter {
|
|
|
320
372
|
catch (e) {
|
|
321
373
|
console.warn(e);
|
|
322
374
|
}
|
|
323
|
-
this.
|
|
375
|
+
this.emit(EVENT_SHARE_SCREEN_ENDED);
|
|
324
376
|
this.currentScreenShare = null;
|
|
325
377
|
return reinvited;
|
|
326
378
|
}
|
|
@@ -345,10 +397,13 @@ class Call extends EventEmitter {
|
|
|
345
397
|
onError(error) {
|
|
346
398
|
this.emit(EVENT_CALL_ERROR, error);
|
|
347
399
|
}
|
|
400
|
+
onCallIncoming() {
|
|
401
|
+
this._sendAction(Actions.INCOMING_CALL);
|
|
402
|
+
}
|
|
348
403
|
onRejected() {
|
|
349
404
|
this.endTime = new Date();
|
|
350
405
|
this.emit(EVENT_CALL_REJECTED);
|
|
351
|
-
this.phone.
|
|
406
|
+
this.phone.onCallTerminated(this);
|
|
352
407
|
}
|
|
353
408
|
onNetworkStats(stats, previousStats) {
|
|
354
409
|
this.emit(EVENT_WEB_RTC_STATS, stats, previousStats);
|
|
@@ -377,16 +432,21 @@ class Call extends EventEmitter {
|
|
|
377
432
|
isVideoRemotelyHeld() {
|
|
378
433
|
return isVideoRemotelyHeld(this.sipCall);
|
|
379
434
|
}
|
|
435
|
+
isRinging() {
|
|
436
|
+
return this.state === States.RINGING;
|
|
437
|
+
}
|
|
380
438
|
onReinvite(request, updatedCalleeName, updatedNumber, hadRemoteVideo) {
|
|
381
439
|
this.emit(EVENT_REINVITE, request, updatedCalleeName, updatedNumber, hadRemoteVideo);
|
|
382
440
|
}
|
|
383
441
|
get id() {
|
|
384
442
|
return getSipSessionId(this.sipCall);
|
|
385
443
|
}
|
|
386
|
-
get
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
444
|
+
get state() {
|
|
445
|
+
return getState(this.callActor);
|
|
446
|
+
}
|
|
447
|
+
_hasEstablishedState(establishedState) {
|
|
448
|
+
const state = this.state;
|
|
449
|
+
return States.ESTABLISHED in state && state[States.ESTABLISHED] === establishedState;
|
|
390
450
|
}
|
|
391
451
|
_bindEvents() {
|
|
392
452
|
if (this.sipCall instanceof Invitation) {
|
|
@@ -396,21 +456,22 @@ class Call extends EventEmitter {
|
|
|
396
456
|
logger.trace('call - on sip session canceled', { callId: message.callId, id: this.id });
|
|
397
457
|
onCancel(message);
|
|
398
458
|
const elsewhere = message.data.indexOf('cause=26') !== -1 && message.data.indexOf('completed elsewhere') !== -1;
|
|
399
|
-
this.
|
|
459
|
+
this.emit(EVENT_CALL_CANCELED, elsewhere);
|
|
400
460
|
};
|
|
401
461
|
}
|
|
402
462
|
this.sipCall.stateChange.addListener((newState) => {
|
|
403
463
|
switch (newState) {
|
|
404
464
|
case SessionState.Terminating:
|
|
405
465
|
logger.info('call - terminating', { id: this.id });
|
|
406
|
-
this.
|
|
466
|
+
this.emit(EVENT_CALL_TERMINATING);
|
|
407
467
|
break;
|
|
408
468
|
case SessionState.Terminated:
|
|
409
469
|
{
|
|
410
470
|
logger.info('call - terminated', { id: this.id });
|
|
411
471
|
// Should be called before `_onCallTerminated` or the callCount will not decrement...
|
|
412
472
|
this.endTime = new Date();
|
|
413
|
-
|
|
473
|
+
this.emit(EVENT_CALL_ENDED);
|
|
474
|
+
return this.phone.onCallTerminated(this);
|
|
414
475
|
}
|
|
415
476
|
default:
|
|
416
477
|
break;
|
|
@@ -437,18 +498,17 @@ class Call extends EventEmitter {
|
|
|
437
498
|
kind,
|
|
438
499
|
});
|
|
439
500
|
if (kind === 'audio') {
|
|
440
|
-
return this.
|
|
501
|
+
return this.emit(EVENT_AUDIO_STREAM, stream);
|
|
441
502
|
}
|
|
442
|
-
return this.
|
|
503
|
+
return this.emit(EVENT_VIDEO_STREAM, stream, event.track.id, event);
|
|
443
504
|
};
|
|
444
505
|
peerConnection.onremovestream = (event) => {
|
|
445
506
|
logger.info('call - on remove stream called on the peer connection', {
|
|
446
507
|
id: event.stream.id,
|
|
447
508
|
tracks: event.stream.getTracks(),
|
|
448
509
|
});
|
|
449
|
-
this.
|
|
510
|
+
this.emit(EVENT_REMOVE_STREAM, event.stream);
|
|
450
511
|
};
|
|
451
|
-
// Client events
|
|
452
512
|
}
|
|
453
513
|
_downgradeToAudio(withMessage = true) {
|
|
454
514
|
assertState(this.callActor, States.ESTABLISHED);
|
|
@@ -508,7 +568,7 @@ class Call extends EventEmitter {
|
|
|
508
568
|
if (screenTrack) {
|
|
509
569
|
screenTrack.onended = () => {
|
|
510
570
|
logger.info('call - on screenshare ended', { hadVideo, id: this.id, screenTrack });
|
|
511
|
-
this.
|
|
571
|
+
this.emit(EVENT_SHARE_SCREEN_ENDING);
|
|
512
572
|
};
|
|
513
573
|
}
|
|
514
574
|
this.currentScreenShare = {
|
|
@@ -518,7 +578,7 @@ class Call extends EventEmitter {
|
|
|
518
578
|
desktop,
|
|
519
579
|
};
|
|
520
580
|
setLocalMediaStream(this.sipCall, screenStream);
|
|
521
|
-
this.
|
|
581
|
+
this.emit(EVENT_SHARE_SCREEN_STARTED, screenStream);
|
|
522
582
|
}
|
|
523
583
|
_sendAction(action) {
|
|
524
584
|
this.callActor.send({ type: action });
|