@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.
Files changed (83) hide show
  1. package/dist/wazo-sdk.js +6 -6
  2. package/esm/__tests__/__voice__/call.test.js +44 -2
  3. package/esm/__tests__/api-client.test.js +20 -1
  4. package/esm/api/auth.js +13 -2
  5. package/esm/domain/Phone/WebRTCPhone.js +6 -7
  6. package/esm/index.js +2 -0
  7. package/esm/simple/Auth.js +6 -12
  8. package/esm/simple/Phone.js +1 -0
  9. package/esm/simple/__tests__/Auth.test.js +8 -64
  10. package/esm/state-machine/call-state-machine.js +1 -1
  11. package/esm/types/api/auth.d.ts.map +1 -1
  12. package/esm/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  13. package/esm/types/index.d.ts +2 -0
  14. package/esm/types/index.d.ts.map +1 -1
  15. package/esm/types/simple/Auth.d.ts.map +1 -1
  16. package/esm/types/simple/Phone.d.ts.map +1 -1
  17. package/esm/types/state-machine/utils.d.ts +1 -1
  18. package/esm/types/state-machine/utils.d.ts.map +1 -1
  19. package/esm/types/utils/api-requester.d.ts.map +1 -1
  20. package/esm/types/utils/sdp.d.ts +2 -0
  21. package/esm/types/utils/sdp.d.ts.map +1 -1
  22. package/esm/types/utils/webrtc.d.ts +1 -0
  23. package/esm/types/utils/webrtc.d.ts.map +1 -1
  24. package/esm/types/voice/call.d.ts +19 -11
  25. package/esm/types/voice/call.d.ts.map +1 -1
  26. package/esm/types/voice/softphone.d.ts +18 -13
  27. package/esm/types/voice/softphone.d.ts.map +1 -1
  28. package/esm/utils/__tests__/api-requester.test.js +17 -0
  29. package/esm/utils/api-requester.js +9 -1
  30. package/esm/utils/sdp.js +13 -0
  31. package/esm/utils/webrtc.js +21 -1
  32. package/esm/voice/call.js +90 -30
  33. package/esm/voice/softphone.js +94 -23
  34. package/lib/__tests__/__voice__/call.test.js +43 -1
  35. package/lib/__tests__/api-client.test.js +20 -1
  36. package/lib/api/auth.js +13 -2
  37. package/lib/domain/Phone/WebRTCPhone.js +5 -6
  38. package/lib/index.js +6 -2
  39. package/lib/simple/Auth.js +6 -12
  40. package/lib/simple/Phone.js +1 -0
  41. package/lib/simple/__tests__/Auth.test.js +11 -64
  42. package/lib/state-machine/call-state-machine.js +1 -1
  43. package/lib/types/api/auth.d.ts.map +1 -1
  44. package/lib/types/domain/Phone/WebRTCPhone.d.ts.map +1 -1
  45. package/lib/types/index.d.ts +2 -0
  46. package/lib/types/index.d.ts.map +1 -1
  47. package/lib/types/simple/Auth.d.ts.map +1 -1
  48. package/lib/types/simple/Phone.d.ts.map +1 -1
  49. package/lib/types/state-machine/utils.d.ts +1 -1
  50. package/lib/types/state-machine/utils.d.ts.map +1 -1
  51. package/lib/types/utils/api-requester.d.ts.map +1 -1
  52. package/lib/types/utils/sdp.d.ts +2 -0
  53. package/lib/types/utils/sdp.d.ts.map +1 -1
  54. package/lib/types/utils/webrtc.d.ts +1 -0
  55. package/lib/types/utils/webrtc.d.ts.map +1 -1
  56. package/lib/types/voice/call.d.ts +19 -11
  57. package/lib/types/voice/call.d.ts.map +1 -1
  58. package/lib/types/voice/softphone.d.ts +18 -13
  59. package/lib/types/voice/softphone.d.ts.map +1 -1
  60. package/lib/utils/__tests__/api-requester.test.js +17 -0
  61. package/lib/utils/api-requester.js +9 -1
  62. package/lib/utils/sdp.js +16 -1
  63. package/lib/utils/webrtc.js +23 -2
  64. package/lib/voice/call.js +87 -28
  65. package/lib/voice/softphone.js +95 -23
  66. package/package.json +1 -1
  67. package/src/__tests__/__voice__/call.test.ts +47 -2
  68. package/src/__tests__/api-client.test.ts +22 -1
  69. package/src/api/auth.ts +25 -3
  70. package/src/domain/Phone/WebRTCPhone.ts +9 -9
  71. package/src/index.ts +2 -0
  72. package/src/simple/Auth.ts +6 -13
  73. package/src/simple/Phone.ts +1 -0
  74. package/src/simple/__tests__/Auth.test.ts +9 -87
  75. package/src/state-machine/call-state-machine.ts +1 -1
  76. package/src/state-machine/utils.ts +2 -2
  77. package/src/utils/__tests__/api-requester.test.ts +20 -0
  78. package/src/utils/api-requester.ts +9 -1
  79. package/src/utils/sdp.ts +16 -0
  80. package/src/utils/webrtc.ts +24 -2
  81. package/src/voice/call.ts +118 -40
  82. package/src/voice/softphone.ts +116 -30
  83. 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 ActionTypes, type EstablishedActionTypes, type CallActorRef } from '../state-machine/call-state-machine';
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(withCalls: Call[]): void;
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 number(): any;
102
- _bindEvents(): void;
103
- _downgradeToAudio(withMessage?: boolean): boolean;
104
- _upgradeToVideo(options?: ReinviteOptions): Promise<boolean>;
105
- _sendReinviteMessage(isUpgrade: boolean): void;
106
- _onScreenSharing(screenStream: MediaStream, hadVideo: boolean, desktop?: boolean | null | undefined): void;
107
- _sendAction(action: ActionTypes | EstablishedActionTypes): void;
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":"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"}
1
+ {"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../../../src/voice/call.ts"],"names":[],"mappings":"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"}
@@ -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, ActionTypes } from '../state-machine/softphone-state-machine';
7
- import { WebRtcConfig, SipCall } from '../domain/types';
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
- getState(): StateTypes;
70
+ getIncomingCalls(): Call[];
71
+ get state(): StateTypes;
65
72
  getUserAgent(): string;
73
+ isRegistered(): boolean;
66
74
  _bindEvents(): void;
67
- _sendAction(action: ActionTypes): void;
68
- _getCall(sipCall: SipCall): Call | undefined;
69
- _onCallEvent(sipCall: SipCall, eventName: string, ...args: any[]): void;
70
- _onMessage(message: Message & {
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":"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"}
1
+ {"version":3,"file":"softphone.d.ts","sourceRoot":"","sources":["../../../src/voice/softphone.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAKtC,OAAO,KAAK,OAAO,MAAM,mBAAmB,CAAC;AAC7C,OAAO,KAAK,OAAO,MAAM,mBAAmB,CAAC;AAI7C,OAA8B,EAAE,KAAK,iBAAiB,EAAW,KAAK,UAAU,EAAuB,MAAM,0CAA0C,CAAC;AACxJ,OAAO,EAAE,YAAY,EAAW,MAAM,iBAAiB,CAAC;AACxD,OAAO,gBAAgB,MAAM,mBAAmB,CAAC;AAGjD,OAAO,IAAI,MAAM,QAAQ,CAAC;AAG1B,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,uBAAuB,qBAAqB,CAAC;AAC1D,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAC7C,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AACjD,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AACjD,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAC3D,eAAO,MAAM,qBAAqB,mBAAmB,CAAC;AACtD,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AACzD,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AACrD,eAAO,MAAM,6BAA6B,yBAAyB,CAAC;AACpE,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAC1C,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAC7C,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAEjD,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAEzD,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;IACF,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAIF,qBAAa,SAAU,SAAQ,YAAY;IACzC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,iBAAiB,EAAE,MAAM,CAAC;IAE1B,eAAe,EAAE,MAAM,CAAC;IAExB,KAAK,EAAE,IAAI,EAAE,CAAC;IAEd,MAAM,EAAE,gBAAgB,CAAC;IAEzB,OAAO,EAAE,OAAO,CAAC;IAEjB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAExB,cAAc,EAAE,iBAAiB,CAAC;IAElC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAE/B,kBAAkB,EAAE,OAAO,CAAC;IAE5B,cAAc,UAAQ;;IAWtB,OAAO,CAAC,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM;IAyBrC,UAAU;IAYhB,oBAAoB,IAAI,OAAO,GAAG,IAAI;IAIhC,sBAAsB,CAC1B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,EACnB,UAAU,GAAE,OAAO,CAAC,YAAY,CAAM,GACrC,OAAO,CAAC,IAAI,CAAC;IAqChB,SAAS;IASH,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAqCtD,UAAU,CAAC,YAAY,EAAE,IAAI;IAI7B,gBAAgB,CAAC,IAAI,EAAE,IAAI;IAqD3B,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAKrC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAKtC,YAAY,CAAC,UAAU,GAAE,IAAI,GAAG,IAAW;IAI3C,cAAc;IASd,aAAa;IASb,mBAAmB,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI;IAIxD,uBAAuB,CAAC,EAAE,EAAE,MAAM;IAOlC,sBAAsB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;IAOlD,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IAOlF,gBAAgB,CAAC,EAAE,EAAE,MAAM;IAK3B,MAAM,IAAI,OAAO;IAKjB,iBAAiB,CAAC,MAAM,EAAE,MAAM;IAOhC,gBAAgB,CAAC,MAAM,EAAE,MAAM;IAK/B,cAAc,IAAI,IAAI,GAAG,SAAS;IAIlC,gBAAgB,IAAI,IAAI,EAAE;IAI1B,IAAI,KAAK,IAAI,UAAU,CAEtB;IAED,YAAY;IAIZ,YAAY;IAIZ,WAAW,IAAI,IAAI;IAiJnB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,UAAU;CAiCnB;;AAED,wBAA+B"}
@@ -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
- return typeof btoa !== 'undefined' ? btoa(str) : Base64.encode(str);
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
+ };
@@ -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 : constraints?.audio,
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 { getSipSessionId } from '../utils/sdp';
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.eventEmitter.emit(EVENT_TERMINATE_SOUND, 'call rejected locally');
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.removeCall(this);
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.eventEmitter.emit(EVENT_CALL_MUTED);
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.eventEmitter.emit(EVENT_CALL_UN_MUTED);
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.eventEmitter.emit(EVENT_CALL_HELD);
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.eventEmitter.emit(EVENT_CALL_RESUMED);
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.eventEmitter.emit(EVENT_CAMERA_RESUMED);
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.eventEmitter.emit(EVENT_CAMERA_DISABLED);
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 getState(this.callActor) === EstablishedStates.HELD;
244
+ return this._hasEstablishedState(EstablishedStates.HELD);
193
245
  }
194
246
  isEstablished() {
195
- return getState(this.callActor) === States.ESTABLISHED;
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.eventEmitter.emit(EVENT_SHARE_SCREEN_ENDED);
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.removeCall(this);
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 number() {
387
- const identity = this.sipCall.remoteIdentity || this.sipCall.assertedIdentity;
388
- // @ts-ignore: private
389
- return identity ? identity.uri._normal.user : null;
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.eventEmitter.emit(EVENT_CALL_CANCELED, elsewhere);
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.eventEmitter.emit(EVENT_CALL_TERMINATING);
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
- return this.eventEmitter.emit(EVENT_CALL_ENDED);
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.eventEmitter.emit(EVENT_AUDIO_STREAM, stream);
501
+ return this.emit(EVENT_AUDIO_STREAM, stream);
441
502
  }
442
- return this.eventEmitter.emit(EVENT_VIDEO_STREAM, stream, event.track.id, event);
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.eventEmitter.emit(EVENT_REMOVE_STREAM, event.stream);
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.eventEmitter.emit(EVENT_SHARE_SCREEN_ENDING);
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.eventEmitter.emit(EVENT_SHARE_SCREEN_STARTED, screenStream);
581
+ this.emit(EVENT_SHARE_SCREEN_STARTED, screenStream);
522
582
  }
523
583
  _sendAction(action) {
524
584
  this.callActor.send({ type: action });