@microsoft/live-share-media 1.2.0 → 1.2.1

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 (33) hide show
  1. package/bin/LiveMediaSession.d.ts.map +1 -1
  2. package/bin/LiveMediaSession.js +2 -0
  3. package/bin/LiveMediaSession.js.map +1 -1
  4. package/bin/MediaPlayerSynchronizer.d.ts.map +1 -1
  5. package/bin/MediaPlayerSynchronizer.js +12 -0
  6. package/bin/MediaPlayerSynchronizer.js.map +1 -1
  7. package/bin/MediaSessionExtensions.d.ts +135 -6
  8. package/bin/MediaSessionExtensions.d.ts.map +1 -1
  9. package/bin/MediaSessionExtensions.js +9 -0
  10. package/bin/MediaSessionExtensions.js.map +1 -1
  11. package/bin/internals/GroupCoordinatorState.d.ts.map +1 -1
  12. package/bin/internals/GroupCoordinatorState.js +49 -21
  13. package/bin/internals/GroupCoordinatorState.js.map +1 -1
  14. package/bin/internals/GroupPlaybackTrack.d.ts +2 -2
  15. package/bin/internals/GroupPlaybackTrack.d.ts.map +1 -1
  16. package/bin/internals/GroupPlaybackTrack.js +2 -1
  17. package/bin/internals/GroupPlaybackTrack.js.map +1 -1
  18. package/bin/internals/GroupPlaybackTrackData.d.ts +2 -1
  19. package/bin/internals/GroupPlaybackTrackData.d.ts.map +1 -1
  20. package/bin/internals/GroupPlaybackTrackData.js +2 -1
  21. package/bin/internals/GroupPlaybackTrackData.js.map +1 -1
  22. package/bin/internals/GroupTransportState.d.ts +2 -2
  23. package/bin/internals/GroupTransportState.d.ts.map +1 -1
  24. package/bin/internals/GroupTransportState.js +4 -1
  25. package/bin/internals/GroupTransportState.js.map +1 -1
  26. package/package.json +3 -3
  27. package/src/LiveMediaSession.ts +2 -0
  28. package/src/MediaPlayerSynchronizer.ts +12 -0
  29. package/src/MediaSessionExtensions.ts +137 -7
  30. package/src/internals/GroupCoordinatorState.ts +62 -23
  31. package/src/internals/GroupPlaybackTrack.ts +6 -1
  32. package/src/internals/GroupPlaybackTrackData.ts +6 -1
  33. package/src/internals/GroupTransportState.ts +8 -1
@@ -17,6 +17,7 @@ import {
17
17
  CoordinationWaitPoint,
18
18
  ExtendedMediaSessionPlaybackState,
19
19
  ExtendedMediaSessionActionDetails,
20
+ ExtendedMediaSessionActionSource,
20
21
  } from "../MediaSessionExtensions";
21
22
  import {
22
23
  GroupPlaybackTrack,
@@ -150,7 +151,7 @@ export class GroupCoordinatorState extends EventEmitter {
150
151
  this._logger.sendTelemetryEvent(
151
152
  TelemetryEvents.GroupCoordinator.TrackChanged
152
153
  );
153
- this.emitSetTrack(evt.clientId, evt.metadata!);
154
+ this.emitSetTrack(evt.clientId, evt.metadata!, evt.source);
154
155
  } else {
155
156
  this._logger.sendTelemetryEvent(
156
157
  TelemetryEvents.GroupCoordinator.TrackChangeDelayed
@@ -161,15 +162,18 @@ export class GroupCoordinatorState extends EventEmitter {
161
162
  // Listen for track data changes
162
163
  this._playbackTrackData.on(
163
164
  PlaybackTrackDataEvents.dataChange,
164
- (evt) => {
165
+ async (evt) => {
165
166
  if (!this.isSuspended && !this.isWaiting) {
166
167
  this._logger.sendTelemetryEvent(
167
168
  TelemetryEvents.GroupCoordinator.TrackDataChanged
168
169
  );
170
+ const clientId = await waitUntilConnected(this._runtime);
169
171
  this.emitTriggerAction({
170
172
  action: "datachange",
173
+ source: evt.source,
171
174
  data: evt.data,
172
175
  clientId: evt.clientId,
176
+ local: evt.clientId === clientId,
173
177
  });
174
178
  } else {
175
179
  this._logger.sendTelemetryEvent(
@@ -182,7 +186,7 @@ export class GroupCoordinatorState extends EventEmitter {
182
186
  // Listen to transport related events
183
187
  this._transportState.on(
184
188
  GroupTransportStateEvents.transportStateChange,
185
- (evt) => {
189
+ async (evt) => {
186
190
  if (!this.isSuspended && !this.isWaiting) {
187
191
  this._logger.sendTelemetryEvent(
188
192
  TelemetryEvents.GroupCoordinator.TransportStateChanged,
@@ -193,12 +197,18 @@ export class GroupCoordinatorState extends EventEmitter {
193
197
  }
194
198
  );
195
199
 
200
+ const localClientId = await waitUntilConnected(
201
+ this._runtime
202
+ );
203
+ const local = evt.clientId === localClientId;
196
204
  // Trigger action
197
205
  switch (evt.action) {
198
206
  case "play":
199
207
  this.emitTriggerAction({
200
208
  action: "play",
209
+ source: evt.source,
201
210
  clientId: evt.clientId,
211
+ local,
202
212
  seekTime: evt.seekTime,
203
213
  });
204
214
  break;
@@ -206,7 +216,9 @@ export class GroupCoordinatorState extends EventEmitter {
206
216
  case "pause":
207
217
  this.emitTriggerAction({
208
218
  action: "pause",
219
+ source: evt.source,
209
220
  clientId: evt.clientId,
221
+ local,
210
222
  seekTime: evt.seekTime,
211
223
  });
212
224
  break;
@@ -214,7 +226,9 @@ export class GroupCoordinatorState extends EventEmitter {
214
226
  case "seekto":
215
227
  this.emitTriggerAction({
216
228
  action: "seekto",
229
+ source: evt.source,
217
230
  clientId: evt.clientId,
231
+ local,
218
232
  seekTime: evt.seekTime,
219
233
  });
220
234
  break;
@@ -319,12 +333,15 @@ export class GroupCoordinatorState extends EventEmitter {
319
333
  ): void {
320
334
  // Update shared track
321
335
  // - Will trigger 'trackChange' event to update media session
322
- const updated = this.playbackTrack.updateTrack({
323
- metadata: event.data.metadata,
324
- waitPoints: event.data.waitPoints,
325
- timestamp: event.timestamp,
326
- clientId: event.clientId || "",
327
- });
336
+ const updated = this.playbackTrack.updateTrack(
337
+ {
338
+ metadata: event.data.metadata,
339
+ waitPoints: event.data.waitPoints,
340
+ timestamp: event.timestamp,
341
+ clientId: event.clientId || "",
342
+ },
343
+ "user"
344
+ );
328
345
 
329
346
  if (updated) {
330
347
  this._logger.sendTelemetryEvent(
@@ -346,11 +363,14 @@ export class GroupCoordinatorState extends EventEmitter {
346
363
  ): void {
347
364
  // Update shared track data
348
365
  // - Will trigger 'dataChange' event to update media session
349
- const updated = this.playbackTrackData.updateData({
350
- data: event.data.data,
351
- timestamp: event.timestamp,
352
- clientId: event.clientId || "",
353
- });
366
+ const updated = this.playbackTrackData.updateData(
367
+ {
368
+ data: event.data.data,
369
+ timestamp: event.timestamp,
370
+ clientId: event.clientId || "",
371
+ },
372
+ "user"
373
+ );
354
374
 
355
375
  if (updated) {
356
376
  this._logger.sendTelemetryEvent(
@@ -372,7 +392,7 @@ export class GroupCoordinatorState extends EventEmitter {
372
392
  ): void {
373
393
  // Ensure change is for current track
374
394
  // - Will trigger a 'trackChange' event if newer track.
375
- this.playbackTrack.updateTrack(event.data.track);
395
+ this.playbackTrack.updateTrack(event.data.track, "system");
376
396
  if (this.playbackTrack.compare(event.data.track.metadata)) {
377
397
  // Update playback state
378
398
  let playbackState = this.transportState.playbackState;
@@ -392,7 +412,7 @@ export class GroupCoordinatorState extends EventEmitter {
392
412
  timestamp: event.timestamp,
393
413
  clientId: event.clientId || "",
394
414
  };
395
- const updated = this.transportState.updateState(newState);
415
+ const updated = this.transportState.updateState(newState, "user");
396
416
 
397
417
  if (updated) {
398
418
  const correlationId = LiveTelemetryLogger.formatCorrelationId(
@@ -441,16 +461,16 @@ export class GroupCoordinatorState extends EventEmitter {
441
461
  ): void {
442
462
  // Ensure change is for current track
443
463
  // - Will trigger a 'trackChange' event if newer track.
444
- this.playbackTrack.updateTrack(event.data.track);
464
+ this.playbackTrack.updateTrack(event.data.track, "system");
445
465
  if (this.playbackTrack.compare(event.data.track.metadata)) {
446
466
  // Ensure we have the latest track data
447
- this.playbackTrackData.updateData(event.data.trackData);
467
+ this.playbackTrackData.updateData(event.data.trackData, "system");
448
468
 
449
469
  // Update transport state if needed
450
470
  // - Ignore transport state changes if the client has ended as this will cause the local
451
471
  // player to start playback even though the video may have ended for everyone.
452
472
  if (event.data.playbackState != "ended") {
453
- this.transportState.updateState(event.data.transport);
473
+ this.transportState.updateState(event.data.transport, "system");
454
474
  }
455
475
 
456
476
  // Ensure change is for current transport state
@@ -529,7 +549,8 @@ export class GroupCoordinatorState extends EventEmitter {
529
549
  );
530
550
  this.emitSetTrack(
531
551
  this.playbackTrack.current.clientId,
532
- this.playbackTrack.metadata!
552
+ this.playbackTrack.metadata!,
553
+ "system"
533
554
  );
534
555
  return;
535
556
  }
@@ -568,11 +589,14 @@ export class GroupCoordinatorState extends EventEmitter {
568
589
  );
569
590
  await this.emitTriggerAction({
570
591
  action: "catchup",
592
+ source: "system",
571
593
  clientId: await waitUntilConnected(this._runtime),
594
+ local: true,
572
595
  seekTime: target,
573
596
  });
574
597
  }
575
598
 
599
+ const localClientId = await waitUntilConnected(this._runtime);
576
600
  // Sync transport state
577
601
  if (this.transportState.playbackState != playbackState) {
578
602
  this._logger.sendTelemetryEvent(
@@ -583,17 +607,23 @@ export class GroupCoordinatorState extends EventEmitter {
583
607
  target: this.transportState.playbackState,
584
608
  }
585
609
  );
610
+ const local =
611
+ localClientId === this.transportState.current.clientId;
586
612
  switch (this.transportState.playbackState) {
587
613
  case "playing":
588
614
  await this.emitTriggerAction({
589
615
  action: "play",
616
+ source: "system",
590
617
  clientId: this.transportState.current.clientId,
618
+ local,
591
619
  });
592
620
  break;
593
621
  case "paused":
594
622
  await this.emitTriggerAction({
595
623
  action: "pause",
624
+ source: "system",
596
625
  clientId: this.transportState.current.clientId,
626
+ local,
597
627
  });
598
628
  break;
599
629
  }
@@ -607,9 +637,14 @@ export class GroupCoordinatorState extends EventEmitter {
607
637
  this._logger.sendTelemetryEvent(
608
638
  TelemetryEvents.GroupCoordinator.TrackDataOutOfSync
609
639
  );
640
+ const local =
641
+ localClientId ===
642
+ this.playbackTrackData.current.clientId;
610
643
  await this.emitTriggerAction({
611
644
  action: "datachange",
645
+ source: "system",
612
646
  clientId: this.playbackTrackData.current.clientId,
647
+ local,
613
648
  data: this.playbackTrackData.data,
614
649
  });
615
650
  }
@@ -617,17 +652,21 @@ export class GroupCoordinatorState extends EventEmitter {
617
652
  }
618
653
  }
619
654
 
620
- private emitSetTrack(
655
+ private async emitSetTrack(
621
656
  clientId: string,
622
- metadata: ExtendedMediaMetadata
623
- ): void {
657
+ metadata: ExtendedMediaMetadata,
658
+ source: ExtendedMediaSessionActionSource
659
+ ): Promise<void> {
624
660
  // Reset tracking states
625
661
  this._waitPoint = undefined;
626
662
 
663
+ const localClientId = await waitUntilConnected(this._runtime);
627
664
  // Trigger settrack action
628
665
  this.emitTriggerAction({
629
666
  action: "settrack",
667
+ source,
630
668
  clientId,
669
+ local: localClientId === clientId,
631
670
  metadata,
632
671
  });
633
672
  }
@@ -9,6 +9,7 @@ import { IMediaPlayerState } from "../LiveMediaSessionCoordinator";
9
9
  import {
10
10
  CoordinationWaitPoint,
11
11
  ExtendedMediaMetadata,
12
+ ExtendedMediaSessionActionSource,
12
13
  } from "../MediaSessionExtensions";
13
14
 
14
15
  /**
@@ -99,7 +100,10 @@ export class GroupPlaybackTrack extends EventEmitter {
99
100
  return undefined;
100
101
  }
101
102
 
102
- public updateTrack(track: IPlaybackTrack): boolean {
103
+ public updateTrack(
104
+ track: IPlaybackTrack,
105
+ source: ExtendedMediaSessionActionSource
106
+ ): boolean {
103
107
  // Guard against missing waitPoints collection
104
108
  if (!Array.isArray(track.waitPoints)) {
105
109
  track.waitPoints = [];
@@ -149,6 +153,7 @@ export class GroupPlaybackTrack extends EventEmitter {
149
153
  name: GroupPlaybackTrackEvents.trackChange,
150
154
  clientId: track.clientId,
151
155
  metadata: track.metadata,
156
+ source,
152
157
  });
153
158
 
154
159
  return true;
@@ -9,6 +9,7 @@ import {
9
9
  GroupPlaybackTrack,
10
10
  GroupPlaybackTrackEvents,
11
11
  } from "./GroupPlaybackTrack";
12
+ import { ExtendedMediaSessionActionSource } from "../MediaSessionExtensions";
12
13
 
13
14
  /**
14
15
  * @hidden
@@ -64,7 +65,10 @@ export class GroupPlaybackTrackData extends EventEmitter {
64
65
  return this.current.data;
65
66
  }
66
67
 
67
- public updateData(event: IPlaybackTrackData): boolean {
68
+ public updateData(
69
+ event: IPlaybackTrackData,
70
+ source: ExtendedMediaSessionActionSource
71
+ ): boolean {
68
72
  // Ignore state changes that are older
69
73
  const current = this.current;
70
74
  if (event.timestamp < current.timestamp) {
@@ -92,6 +96,7 @@ export class GroupPlaybackTrackData extends EventEmitter {
92
96
  type: PlaybackTrackDataEvents.dataChange,
93
97
  clientId: event.clientId,
94
98
  data: event.data,
99
+ source,
95
100
  });
96
101
 
97
102
  return true;
@@ -9,6 +9,7 @@ import { IMediaPlayerState } from "../LiveMediaSessionCoordinator";
9
9
  import {
10
10
  ExtendedMediaSessionPlaybackState,
11
11
  ExtendedMediaSessionAction,
12
+ ExtendedMediaSessionActionSource,
12
13
  } from "../MediaSessionExtensions";
13
14
  import {
14
15
  GroupPlaybackTrack,
@@ -104,7 +105,10 @@ export class GroupTransportState extends EventEmitter {
104
105
  );
105
106
  }
106
107
 
107
- public updateState(state: ITransportState): boolean {
108
+ public updateState(
109
+ state: ITransportState,
110
+ source: ExtendedMediaSessionActionSource
111
+ ): boolean {
108
112
  // Ignore if same playback state and start position
109
113
  if (this.compare(state)) {
110
114
  return false;
@@ -138,6 +142,7 @@ export class GroupTransportState extends EventEmitter {
138
142
  action: "seekto",
139
143
  clientId: state.clientId,
140
144
  seekTime: state.startPosition,
145
+ source,
141
146
  });
142
147
  } else if (state.playbackState == "playing") {
143
148
  const now = this._liveRuntime.getTimestamp();
@@ -148,6 +153,7 @@ export class GroupTransportState extends EventEmitter {
148
153
  action: "play",
149
154
  clientId: state.clientId,
150
155
  seekTime: projectedPosition,
156
+ source,
151
157
  });
152
158
  } else {
153
159
  this.emit(GroupTransportStateEvents.transportStateChange, {
@@ -155,6 +161,7 @@ export class GroupTransportState extends EventEmitter {
155
161
  action: "pause",
156
162
  clientId: state.clientId,
157
163
  seekTime: state.startPosition,
164
+ source,
158
165
  });
159
166
  }
160
167