@defcomm/meetingsdk 0.3.1 → 0.3.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/index.d.mts CHANGED
@@ -219,7 +219,7 @@ declare class VideoSDKCore {
219
219
  rejectJoinRequest(requestId: string, reason?: string): Promise<void>;
220
220
  toggleMic(): void;
221
221
  toggleCam(): void;
222
- startScreenShare(): Promise<MediaStream>;
222
+ startScreenShare(): Promise<MediaStream | null>;
223
223
  stopScreenShare(): Promise<void>;
224
224
  startRecording(): Promise<void>;
225
225
  stopRecording(): Promise<void>;
@@ -436,7 +436,7 @@ declare class SFUClient {
436
436
  video?: boolean | undefined;
437
437
  }): Promise<MediaStream>;
438
438
  private publishExistingTracks;
439
- shareScreen(): Promise<MediaStream>;
439
+ shareScreen(): Promise<MediaStream | null>;
440
440
  stopScreenShare(): Promise<void>;
441
441
  muteAudio(muted: boolean): void;
442
442
  muteVideo(muted: boolean): void;
package/dist/index.d.ts CHANGED
@@ -219,7 +219,7 @@ declare class VideoSDKCore {
219
219
  rejectJoinRequest(requestId: string, reason?: string): Promise<void>;
220
220
  toggleMic(): void;
221
221
  toggleCam(): void;
222
- startScreenShare(): Promise<MediaStream>;
222
+ startScreenShare(): Promise<MediaStream | null>;
223
223
  stopScreenShare(): Promise<void>;
224
224
  startRecording(): Promise<void>;
225
225
  stopRecording(): Promise<void>;
@@ -436,7 +436,7 @@ declare class SFUClient {
436
436
  video?: boolean | undefined;
437
437
  }): Promise<MediaStream>;
438
438
  private publishExistingTracks;
439
- shareScreen(): Promise<MediaStream>;
439
+ shareScreen(): Promise<MediaStream | null>;
440
440
  stopScreenShare(): Promise<void>;
441
441
  muteAudio(muted: boolean): void;
442
442
  muteVideo(muted: boolean): void;
package/dist/index.js CHANGED
@@ -1362,11 +1362,14 @@ var SFUClient = class {
1362
1362
  sdp: answer.sdp
1363
1363
  }
1364
1364
  });
1365
- const waiters = this.subscriptionWaiters.splice(0);
1366
- waiters.forEach((w) => w.resolve());
1365
+ const waiter = this.subscriptionWaiters.shift();
1366
+ waiter?.resolve();
1367
1367
  } catch (error) {
1368
- const waiters = this.subscriptionWaiters.splice(0);
1369
- waiters.forEach((w) => w.reject(error));
1368
+ const waiter = this.subscriptionWaiters.shift();
1369
+ if (waiter) {
1370
+ waiter.trackIds.forEach((id) => this.subscribedTracks.delete(id));
1371
+ waiter.reject(error);
1372
+ }
1370
1373
  this.onError(
1371
1374
  new Error(`Failed to process subscriber offer: ${String(error)}`)
1372
1375
  );
@@ -1388,11 +1391,20 @@ var SFUClient = class {
1388
1391
  if (!uniqueIds.length || !this.isSocketOpen()) return;
1389
1392
  uniqueIds.forEach((id) => this.subscribedTracks.add(id));
1390
1393
  return new Promise((resolve, reject) => {
1391
- this.subscriptionWaiters.push({ resolve, reject });
1392
- this.send({
1394
+ const sent = this.send({
1393
1395
  type: "subscribe",
1394
1396
  payload: { track_ids: uniqueIds }
1395
1397
  });
1398
+ if (!sent) {
1399
+ uniqueIds.forEach((id) => this.subscribedTracks.delete(id));
1400
+ reject(new Error("Signaling socket is not open"));
1401
+ return;
1402
+ }
1403
+ this.subscriptionWaiters.push({
1404
+ trackIds: uniqueIds,
1405
+ resolve,
1406
+ reject
1407
+ });
1396
1408
  });
1397
1409
  }
1398
1410
  async processSubscriptionQueue() {
@@ -1405,11 +1417,20 @@ var SFUClient = class {
1405
1417
  continue;
1406
1418
  }
1407
1419
  await new Promise((resolve, reject) => {
1408
- this.subscriptionWaiters.push({ resolve, reject });
1409
- this.send({
1420
+ const sent = this.send({
1410
1421
  type: "subscribe",
1411
1422
  payload: { track_ids: [trackId] }
1412
1423
  });
1424
+ if (!sent) {
1425
+ this.subscribedTracks.delete(trackId);
1426
+ reject(new Error("Signaling socket is not open"));
1427
+ return;
1428
+ }
1429
+ this.subscriptionWaiters.push({
1430
+ trackIds: [trackId],
1431
+ resolve,
1432
+ reject
1433
+ });
1413
1434
  });
1414
1435
  }
1415
1436
  } finally {
@@ -1467,9 +1488,16 @@ var SFUClient = class {
1467
1488
  if (!this.screenTransceiver || !this.screenSender) {
1468
1489
  throw new Error("Screen transceiver is not initialized");
1469
1490
  }
1470
- if (this.screenStream) {
1471
- return this.screenStream;
1491
+ const existing = this.screenStream;
1492
+ const existingTrack = this.screenSender.track;
1493
+ if (existing || existingTrack && existingTrack.readyState === "live") {
1494
+ return existing;
1472
1495
  }
1496
+ try {
1497
+ await this.screenSender.replaceTrack(null);
1498
+ } catch {
1499
+ }
1500
+ this.screenTransceiver.direction = "inactive";
1473
1501
  const screenStream = await navigator.mediaDevices.getDisplayMedia({
1474
1502
  video: true,
1475
1503
  audio: false
@@ -1479,29 +1507,33 @@ var SFUClient = class {
1479
1507
  screenStream.getTracks().forEach((track) => track.stop());
1480
1508
  throw new Error("Screen share returned no video track");
1481
1509
  }
1510
+ const generation = ++this.screenShareGeneration;
1482
1511
  this.screenStream = screenStream;
1483
1512
  try {
1484
1513
  await this.screenSender.replaceTrack(screenTrack);
1485
1514
  this.screenTransceiver.direction = "sendonly";
1515
+ this.send({
1516
+ type: "start_screen_share"
1517
+ });
1486
1518
  const offer = await this.publisher.createOffer();
1487
1519
  await this.publisher.setLocalDescription(offer);
1520
+ const localDescription = this.publisher.localDescription;
1521
+ if (!localDescription?.sdp) {
1522
+ throw new Error("Publisher did not produce a valid screen-share SDP");
1523
+ }
1488
1524
  this.send({
1489
1525
  type: "publish_offer",
1490
1526
  payload: {
1491
1527
  revision: ++this.publisherRevision,
1492
- sdp: offer.sdp
1528
+ sdp: localDescription.sdp
1493
1529
  }
1494
1530
  });
1495
- this.send({ type: "start_screen_share" });
1496
1531
  screenTrack.onended = () => {
1532
+ if (generation !== this.screenShareGeneration) {
1533
+ return;
1534
+ }
1497
1535
  void this.stopScreenShare();
1498
1536
  };
1499
- console.info("[publisher] Screen track attached", {
1500
- screenTrackId: screenTrack.id,
1501
- cameraTrackId: this.videoSender?.track?.id,
1502
- screenMid: this.screenTransceiver.mid,
1503
- cameraMid: this.cameraTransceiver?.mid
1504
- });
1505
1537
  return this.screenStream;
1506
1538
  } catch (error) {
1507
1539
  try {
@@ -1509,19 +1541,33 @@ var SFUClient = class {
1509
1541
  } catch {
1510
1542
  }
1511
1543
  this.screenTransceiver.direction = "inactive";
1512
- screenStream.getTracks().forEach((track) => track.stop());
1544
+ screenTrack.onended = null;
1545
+ screenStream.getTracks().forEach((track) => {
1546
+ try {
1547
+ track.stop();
1548
+ } catch {
1549
+ }
1550
+ });
1513
1551
  this.screenStream = null;
1514
1552
  try {
1515
- this.send({ type: "stop_screen_share" });
1553
+ this.send({
1554
+ type: "stop_screen_share"
1555
+ });
1516
1556
  } catch {
1517
1557
  }
1518
1558
  throw error;
1519
1559
  }
1520
1560
  }
1521
1561
  async stopScreenShare() {
1522
- if (!this.screenStream && !this.screenSender?.track) return;
1523
- const screenTrack = this.screenSender?.track || null;
1524
- if (screenTrack) screenTrack.onended = null;
1562
+ const stream = this.screenStream;
1563
+ const senderTrack = this.screenSender?.track || null;
1564
+ if (!stream && !senderTrack) {
1565
+ return;
1566
+ }
1567
+ ++this.screenShareGeneration;
1568
+ if (senderTrack) {
1569
+ senderTrack.onended = null;
1570
+ }
1525
1571
  try {
1526
1572
  await this.screenSender?.replaceTrack(null);
1527
1573
  } catch (error) {
@@ -1530,23 +1576,33 @@ var SFUClient = class {
1530
1576
  if (this.screenTransceiver) {
1531
1577
  this.screenTransceiver.direction = "inactive";
1532
1578
  }
1533
- this.send({ type: "stop_screen_share" });
1534
1579
  try {
1535
- const offer = await this.publisher?.createOffer();
1536
- if (offer && this.publisher) {
1580
+ if (this.publisher) {
1581
+ const offer = await this.publisher.createOffer();
1537
1582
  await this.publisher.setLocalDescription(offer);
1538
- this.send({
1539
- type: "publish_offer",
1540
- payload: {
1541
- revision: ++this.publisherRevision,
1542
- sdp: offer.sdp
1543
- }
1544
- });
1583
+ const localDescription = this.publisher.localDescription;
1584
+ if (localDescription?.sdp) {
1585
+ this.send({
1586
+ type: "publish_offer",
1587
+ payload: {
1588
+ revision: ++this.publisherRevision,
1589
+ sdp: localDescription.sdp
1590
+ }
1591
+ });
1592
+ }
1545
1593
  }
1546
1594
  } catch (error) {
1547
1595
  this.onError(error);
1548
1596
  }
1549
- this.screenStream?.getTracks().forEach((track) => track.stop());
1597
+ this.send({
1598
+ type: "stop_screen_share"
1599
+ });
1600
+ stream?.getTracks().forEach((track) => {
1601
+ try {
1602
+ track.stop();
1603
+ } catch {
1604
+ }
1605
+ });
1550
1606
  this.screenStream = null;
1551
1607
  if (this.currentParticipantId) {
1552
1608
  this.onScreenShareStopped(this.currentParticipantId);