@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.
- package/bin/LiveMediaSession.d.ts.map +1 -1
- package/bin/LiveMediaSession.js +2 -0
- package/bin/LiveMediaSession.js.map +1 -1
- package/bin/MediaPlayerSynchronizer.d.ts.map +1 -1
- package/bin/MediaPlayerSynchronizer.js +12 -0
- package/bin/MediaPlayerSynchronizer.js.map +1 -1
- package/bin/MediaSessionExtensions.d.ts +135 -6
- package/bin/MediaSessionExtensions.d.ts.map +1 -1
- package/bin/MediaSessionExtensions.js +9 -0
- package/bin/MediaSessionExtensions.js.map +1 -1
- package/bin/internals/GroupCoordinatorState.d.ts.map +1 -1
- package/bin/internals/GroupCoordinatorState.js +49 -21
- package/bin/internals/GroupCoordinatorState.js.map +1 -1
- package/bin/internals/GroupPlaybackTrack.d.ts +2 -2
- package/bin/internals/GroupPlaybackTrack.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackTrack.js +2 -1
- package/bin/internals/GroupPlaybackTrack.js.map +1 -1
- package/bin/internals/GroupPlaybackTrackData.d.ts +2 -1
- package/bin/internals/GroupPlaybackTrackData.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackTrackData.js +2 -1
- package/bin/internals/GroupPlaybackTrackData.js.map +1 -1
- package/bin/internals/GroupTransportState.d.ts +2 -2
- package/bin/internals/GroupTransportState.d.ts.map +1 -1
- package/bin/internals/GroupTransportState.js +4 -1
- package/bin/internals/GroupTransportState.js.map +1 -1
- package/package.json +3 -3
- package/src/LiveMediaSession.ts +2 -0
- package/src/MediaPlayerSynchronizer.ts +12 -0
- package/src/MediaSessionExtensions.ts +137 -7
- package/src/internals/GroupCoordinatorState.ts +62 -23
- package/src/internals/GroupPlaybackTrack.ts +6 -1
- package/src/internals/GroupPlaybackTrackData.ts +6 -1
- 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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|