@webex/plugin-meetings 3.3.1-next.12 → 3.3.1-next.14

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.
@@ -5233,8 +5233,13 @@ export default class Meeting extends StatelessWebexPlugin {
5233
5233
 
5234
5234
  // @ts-ignore - Fix type
5235
5235
  if (this.webex.internal.llm.isConnected()) {
5236
- // @ts-ignore - Fix type
5237
- if (url === this.webex.internal.llm.getLocusUrl() && isJoined) {
5236
+ if (
5237
+ // @ts-ignore - Fix type
5238
+ url === this.webex.internal.llm.getLocusUrl() &&
5239
+ // @ts-ignore - Fix type
5240
+ datachannelUrl === this.webex.internal.llm.getDatachannelUrl() &&
5241
+ isJoined
5242
+ ) {
5238
5243
  return undefined;
5239
5244
  }
5240
5245
  // @ts-ignore - Fix type
@@ -7897,6 +7902,7 @@ export default class Meeting extends StatelessWebexPlugin {
7897
7902
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE, {
7898
7903
  correlationId: this.correlationId,
7899
7904
  muted,
7905
+ encoderImplementation: this.statsAnalyzer?.shareVideoEncoderImplementation,
7900
7906
  });
7901
7907
  };
7902
7908
 
@@ -91,6 +91,7 @@ export class StatsAnalyzer extends EventsScope {
91
91
  statsStarted: any;
92
92
  successfulCandidatePair: any;
93
93
  localIpAddress: string; // Returns the local IP address for diagnostics. this is the local IP of the interface used for the current media connection a host can have many local Ip Addresses
94
+ shareVideoEncoderImplementation?: string;
94
95
  receiveSlotCallback: ReceiveSlotCallback;
95
96
  isMultistream: boolean;
96
97
 
@@ -613,6 +614,9 @@ export class StatsAnalyzer extends EventsScope {
613
614
  this.statsResults[newType].direction = statsItem.currentDirection;
614
615
  this.statsResults[newType].trackLabel = statsItem.localTrackLabel;
615
616
  this.statsResults[newType].csi = statsItem.csi;
617
+ } else if (type === 'video-share-send' && result.type === 'outbound-rtp') {
618
+ this.shareVideoEncoderImplementation = result.encoderImplementation;
619
+ this.parseGetStatsResult(result, type, isSender);
616
620
  } else {
617
621
  this.parseGetStatsResult(result, type, isSender);
618
622
  }
@@ -87,6 +87,7 @@ describe('plugin-meetings', () => {
87
87
  // @ts-ignore
88
88
  webex = new MockWebex({});
89
89
  webex.internal.llm.on = sinon.stub();
90
+ webex.internal.llm.isConnected = sinon.stub();
90
91
  webex.internal.mercury.on = sinon.stub();
91
92
  breakouts = new Breakouts({}, {parent: webex});
92
93
  breakouts.groupId = 'groupId';
@@ -225,38 +226,6 @@ describe('plugin-meetings', () => {
225
226
  });
226
227
  });
227
228
 
228
- describe('#listenToBroadcastMessages', () => {
229
- it('triggers message event when a message received', () => {
230
- const call = webex.internal.llm.on.getCall(0);
231
- const callback = call.args[1];
232
-
233
- assert.equal(call.args[0], 'event:breakout.message');
234
-
235
- let message;
236
-
237
- breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.MESSAGE, (event) => {
238
- message = event;
239
- });
240
-
241
- breakouts.currentBreakoutSession.sessionId = 'sessionId';
242
-
243
- callback({
244
- data: {
245
- senderUserId: 'senderUserId',
246
- sentTime: 'sentTime',
247
- message: 'message',
248
- },
249
- });
250
-
251
- assert.deepEqual(message, {
252
- senderUserId: 'senderUserId',
253
- sentTime: 'sentTime',
254
- message: 'message',
255
- sessionId: 'sessionId',
256
- });
257
- });
258
- });
259
-
260
229
  describe('#listenToBreakoutRosters', () => {
261
230
  it('triggers member update event when a roster received', () => {
262
231
  const call = webex.internal.mercury.on.getCall(0);
@@ -496,8 +465,58 @@ describe('plugin-meetings', () => {
496
465
  describe('#locusUrlUpdate', () => {
497
466
  it('sets the locus url', () => {
498
467
  breakouts.locusUrlUpdate('newUrl');
468
+ assert.equal(breakouts.locusUrl, 'newUrl');
469
+ });
470
+ });
471
+
472
+ describe('#listenToBroadcastMessages', () => {
473
+ it('do not subscribe message if llm not connected', () => {
474
+ webex.internal.llm.isConnected = sinon.stub().returns(false);
475
+ breakouts.listenTo = sinon.stub();
476
+ breakouts.locusUrlUpdate('newUrl');
477
+ assert.equal(breakouts.locusUrl, 'newUrl');
478
+ assert.notCalled(breakouts.listenTo);
479
+ });
499
480
 
481
+ it('do not subscribe message if already done', () => {
482
+ webex.internal.llm.isConnected = sinon.stub().returns(true);
483
+ breakouts.hasSubscribedToMessage = true;
484
+ breakouts.listenTo = sinon.stub();
485
+ breakouts.locusUrlUpdate('newUrl');
500
486
  assert.equal(breakouts.locusUrl, 'newUrl');
487
+ assert.notCalled(breakouts.listenTo);
488
+ });
489
+
490
+ it('triggers message event when a message received', () => {
491
+ webex.internal.llm.isConnected = sinon.stub().returns(true);
492
+ breakouts.locusUrlUpdate('newUrl');
493
+ const call = webex.internal.llm.on.getCall(0);
494
+ const callback = call.args[1];
495
+
496
+ assert.equal(call.args[0], 'event:breakout.message');
497
+
498
+ let message;
499
+
500
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.MESSAGE, (event) => {
501
+ message = event;
502
+ });
503
+
504
+ breakouts.currentBreakoutSession.sessionId = 'sessionId';
505
+
506
+ callback({
507
+ data: {
508
+ senderUserId: 'senderUserId',
509
+ sentTime: 'sentTime',
510
+ message: 'message',
511
+ },
512
+ });
513
+
514
+ assert.deepEqual(message, {
515
+ senderUserId: 'senderUserId',
516
+ sentTime: 'sentTime',
517
+ message: 'message',
518
+ sessionId: 'sessionId',
519
+ });
501
520
  });
502
521
  });
503
522
 
@@ -6275,7 +6275,7 @@ describe('plugin-meetings', () => {
6275
6275
  },
6276
6276
  'SELF_OBSERVING'
6277
6277
  );
6278
-
6278
+
6279
6279
 
6280
6280
  // Verify that the event handler behaves as expected
6281
6281
  expect(meeting.statsAnalyzer.stopAnalyzer.calledOnce).to.be.true;
@@ -9781,6 +9781,7 @@ describe('plugin-meetings', () => {
9781
9781
  beforeEach(() => {
9782
9782
  webex.internal.llm.isConnected = sinon.stub().returns(false);
9783
9783
  webex.internal.llm.getLocusUrl = sinon.stub();
9784
+ webex.internal.llm.getDatachannelUrl = sinon.stub();
9784
9785
  webex.internal.llm.registerAndConnect = sinon
9785
9786
  .stub()
9786
9787
  .returns(Promise.resolve('something'));
@@ -9808,6 +9809,7 @@ describe('plugin-meetings', () => {
9808
9809
  meeting.joinedWith = {state: 'JOINED'};
9809
9810
  webex.internal.llm.isConnected.returns(true);
9810
9811
  webex.internal.llm.getLocusUrl.returns('a url');
9812
+ webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
9811
9813
 
9812
9814
  meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
9813
9815
 
@@ -9844,6 +9846,7 @@ describe('plugin-meetings', () => {
9844
9846
  meeting.joinedWith = {state: 'JOINED'};
9845
9847
  webex.internal.llm.isConnected.returns(true);
9846
9848
  webex.internal.llm.getLocusUrl.returns('a url');
9849
+ webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
9847
9850
 
9848
9851
  meeting.locusInfo = {url: 'a different url', info: {datachannelUrl: 'a datachannel url'}};
9849
9852
 
@@ -9869,6 +9872,36 @@ describe('plugin-meetings', () => {
9869
9872
  );
9870
9873
  });
9871
9874
 
9875
+ it('disconnects if first if the data channel url has changed', async () => {
9876
+ meeting.joinedWith = {state: 'JOINED'};
9877
+ webex.internal.llm.isConnected.returns(true);
9878
+ webex.internal.llm.getLocusUrl.returns('a url');
9879
+ webex.internal.llm.getDatachannelUrl.returns('a datachannel url');
9880
+
9881
+ meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a different datachannel url'}};
9882
+
9883
+ const result = await meeting.updateLLMConnection();
9884
+
9885
+ assert.calledWith(webex.internal.llm.disconnectLLM);
9886
+ assert.calledWith(
9887
+ webex.internal.llm.registerAndConnect,
9888
+ 'a url',
9889
+ 'a different datachannel url'
9890
+ );
9891
+ assert.equal(result, 'something');
9892
+ assert.calledWithExactly(
9893
+ meeting.webex.internal.llm.off,
9894
+ 'event:relay.event',
9895
+ meeting.processRelayEvent
9896
+ );
9897
+ assert.calledTwice(meeting.webex.internal.llm.off);
9898
+ assert.calledOnceWithExactly(
9899
+ meeting.webex.internal.llm.on,
9900
+ 'event:relay.event',
9901
+ meeting.processRelayEvent
9902
+ );
9903
+ });
9904
+
9872
9905
  it('disconnects when the state is not JOINED', async () => {
9873
9906
  meeting.joinedWith = {state: 'any other state'};
9874
9907
  webex.internal.llm.isConnected.returns(true);
@@ -579,6 +579,7 @@ describe('plugin-meetings', () => {
579
579
  packetsSent: 0,
580
580
  isRequested: true,
581
581
  lastRequestedUpdateTimestamp: 0,
582
+ encoderImplementation: 'fake-encoder',
582
583
  },
583
584
  {
584
585
  type: 'remote-inbound-rtp',
@@ -1169,6 +1170,13 @@ describe('plugin-meetings', () => {
1169
1170
  assert.strictEqual(statsAnalyzer.getLocalIpAddress(), '');
1170
1171
  });
1171
1172
 
1173
+ it('has the correct share video encoder implementation as provided by the stats', async () => {
1174
+ await startStatsAnalyzer({pc, statsAnalyzer});
1175
+
1176
+ await progressTime();
1177
+ assert.strictEqual(statsAnalyzer.shareVideoEncoderImplementation, 'fake-encoder');
1178
+ });
1179
+
1172
1180
  it('logs a message when audio send packets do not increase', async () => {
1173
1181
  await startStatsAnalyzer(
1174
1182
  {