@microsoft/live-share-media 1.0.0-preview.1 → 1.0.0-preview.11
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/README.md +15 -13
- package/package.json +11 -9
- package/src/IMediaPlayer.ts +10 -2
- package/src/LiveMediaSession.ts +138 -71
- package/src/LiveMediaSessionCoordinator.ts +302 -142
- package/src/LiveMediaSessionCoordinatorSuspension.ts +13 -5
- package/src/MediaPlayerSynchronizer.ts +329 -149
- package/src/MediaSessionActionThrottler.ts +5 -3
- package/src/MediaSessionExtensions.ts +15 -5
- package/src/RepeatedActionThrottler.ts +27 -9
- package/src/VolumeManager.ts +24 -12
- package/src/index.ts +9 -10
- package/src/internals/GroupCoordinatorState.ts +275 -114
- package/src/internals/GroupPlaybackPosition.ts +63 -29
- package/src/internals/GroupPlaybackTrack.ts +51 -22
- package/src/internals/GroupPlaybackTrackData.ts +24 -16
- package/src/internals/GroupTransportState.ts +54 -24
- package/src/internals/consts.ts +73 -55
- package/src/internals/index.ts +6 -6
- package/src/test/GroupPlaybackPosition.spec.ts +371 -111
- package/src/test/GroupPlaybackTrack.spec.ts +91 -35
- package/src/test/SharedMediaSession.spec.ts +64 -28
- package/src/test/SharedMediaSessionCoordinator.spec.ts +86 -46
- package/src/test/VolumeManager.spec.ts +38 -31
- package/tsconfig.json +1 -0
- package/.vscode/launch.json +0 -29
- package/.vscode/settings.json +0 -2
- package/bin/EphemeralMediaSession.d.ts +0 -102
- package/bin/EphemeralMediaSession.d.ts.map +0 -1
- package/bin/EphemeralMediaSession.js +0 -226
- package/bin/EphemeralMediaSession.js.map +0 -1
- package/bin/EphemeralMediaSessionCoordinator.d.ts +0 -228
- package/bin/EphemeralMediaSessionCoordinator.d.ts.map +0 -1
- package/bin/EphemeralMediaSessionCoordinator.js +0 -396
- package/bin/EphemeralMediaSessionCoordinator.js.map +0 -1
- package/bin/EphemeralMediaSessionCoordinatorSuspension.d.ts +0 -20
- package/bin/EphemeralMediaSessionCoordinatorSuspension.d.ts.map +0 -1
- package/bin/EphemeralMediaSessionCoordinatorSuspension.js +0 -28
- package/bin/EphemeralMediaSessionCoordinatorSuspension.js.map +0 -1
- package/bin/IMediaPlayer.d.ts +0 -21
- package/bin/IMediaPlayer.d.ts.map +0 -1
- package/bin/IMediaPlayer.js +0 -7
- package/bin/IMediaPlayer.js.map +0 -1
- package/bin/LiveMediaSession.d.ts +0 -95
- package/bin/LiveMediaSession.d.ts.map +0 -1
- package/bin/LiveMediaSession.js +0 -217
- package/bin/LiveMediaSession.js.map +0 -1
- package/bin/LiveMediaSessionCoordinator.d.ts +0 -228
- package/bin/LiveMediaSessionCoordinator.d.ts.map +0 -1
- package/bin/LiveMediaSessionCoordinator.js +0 -396
- package/bin/LiveMediaSessionCoordinator.js.map +0 -1
- package/bin/LiveMediaSessionCoordinatorSuspension.d.ts +0 -20
- package/bin/LiveMediaSessionCoordinatorSuspension.d.ts.map +0 -1
- package/bin/LiveMediaSessionCoordinatorSuspension.js +0 -28
- package/bin/LiveMediaSessionCoordinatorSuspension.js.map +0 -1
- package/bin/MediaPlayerSynchronizer.d.ts +0 -164
- package/bin/MediaPlayerSynchronizer.d.ts.map +0 -1
- package/bin/MediaPlayerSynchronizer.js +0 -414
- package/bin/MediaPlayerSynchronizer.js.map +0 -1
- package/bin/MediaSessionActionThrottler.d.ts +0 -12
- package/bin/MediaSessionActionThrottler.d.ts.map +0 -1
- package/bin/MediaSessionActionThrottler.js +0 -14
- package/bin/MediaSessionActionThrottler.js.map +0 -1
- package/bin/MediaSessionExtensions.d.ts +0 -35
- package/bin/MediaSessionExtensions.d.ts.map +0 -1
- package/bin/MediaSessionExtensions.js +0 -13
- package/bin/MediaSessionExtensions.js.map +0 -1
- package/bin/RepeatedActionThrottler.d.ts +0 -20
- package/bin/RepeatedActionThrottler.d.ts.map +0 -1
- package/bin/RepeatedActionThrottler.js +0 -57
- package/bin/RepeatedActionThrottler.js.map +0 -1
- package/bin/VolumeLimiter.d.ts +0 -70
- package/bin/VolumeLimiter.d.ts.map +0 -1
- package/bin/VolumeLimiter.js +0 -170
- package/bin/VolumeLimiter.js.map +0 -1
- package/bin/VolumeManager.d.ts +0 -84
- package/bin/VolumeManager.d.ts.map +0 -1
- package/bin/VolumeManager.js +0 -173
- package/bin/VolumeManager.js.map +0 -1
- package/bin/index.d.ts +0 -14
- package/bin/index.d.ts.map +0 -1
- package/bin/index.js +0 -30
- package/bin/index.js.map +0 -1
- package/bin/internals/GroupCoordinatorState.d.ts +0 -93
- package/bin/internals/GroupCoordinatorState.d.ts.map +0 -1
- package/bin/internals/GroupCoordinatorState.js +0 -367
- package/bin/internals/GroupCoordinatorState.js.map +0 -1
- package/bin/internals/GroupPlaybackPosition.d.ts +0 -67
- package/bin/internals/GroupPlaybackPosition.d.ts.map +0 -1
- package/bin/internals/GroupPlaybackPosition.js +0 -158
- package/bin/internals/GroupPlaybackPosition.js.map +0 -1
- package/bin/internals/GroupPlaybackTrack.d.ts +0 -46
- package/bin/internals/GroupPlaybackTrack.d.ts.map +0 -1
- package/bin/internals/GroupPlaybackTrack.js +0 -112
- package/bin/internals/GroupPlaybackTrack.js.map +0 -1
- package/bin/internals/GroupPlaybackTrackData.d.ts +0 -40
- package/bin/internals/GroupPlaybackTrackData.d.ts.map +0 -1
- package/bin/internals/GroupPlaybackTrackData.js +0 -66
- package/bin/internals/GroupPlaybackTrackData.js.map +0 -1
- package/bin/internals/GroupTransportState.d.ts +0 -49
- package/bin/internals/GroupTransportState.d.ts.map +0 -1
- package/bin/internals/GroupTransportState.js +0 -97
- package/bin/internals/GroupTransportState.js.map +0 -1
- package/bin/internals/consts.d.ts +0 -73
- package/bin/internals/consts.d.ts.map +0 -1
- package/bin/internals/consts.js +0 -82
- package/bin/internals/consts.js.map +0 -1
- package/bin/internals/index.d.ts +0 -11
- package/bin/internals/index.d.ts.map +0 -1
- package/bin/internals/index.js +0 -27
- package/bin/internals/index.js.map +0 -1
|
@@ -3,16 +3,40 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import
|
|
6
|
+
import {
|
|
7
|
+
IEvent,
|
|
8
|
+
ILiveEvent,
|
|
9
|
+
LiveEvent,
|
|
10
|
+
TimeInterval,
|
|
11
|
+
IRuntimeSignaler,
|
|
12
|
+
LiveTelemetryLogger,
|
|
13
|
+
LiveShareClient,
|
|
14
|
+
} from "@microsoft/live-share";
|
|
15
|
+
import EventEmitter from "events";
|
|
16
|
+
import {
|
|
17
|
+
ExtendedMediaMetadata,
|
|
18
|
+
CoordinationWaitPoint,
|
|
19
|
+
ExtendedMediaSessionPlaybackState,
|
|
20
|
+
ExtendedMediaSessionActionDetails,
|
|
21
|
+
} from "../MediaSessionExtensions";
|
|
22
|
+
import {
|
|
23
|
+
GroupPlaybackTrack,
|
|
24
|
+
GroupPlaybackTrackEvents,
|
|
25
|
+
IPlaybackTrack,
|
|
26
|
+
} from "./GroupPlaybackTrack";
|
|
27
|
+
import { GroupTransportState, ITransportState } from "./GroupTransportState";
|
|
28
|
+
import {
|
|
29
|
+
GroupPlaybackPosition,
|
|
30
|
+
ICurrentPlaybackPosition,
|
|
31
|
+
} from "./GroupPlaybackPosition";
|
|
32
|
+
import { IMediaPlayerState } from "../LiveMediaSessionCoordinator";
|
|
33
|
+
import { GroupTransportStateEvents } from "./GroupTransportState";
|
|
34
|
+
import {
|
|
35
|
+
GroupPlaybackTrackData,
|
|
36
|
+
PlaybackTrackDataEvents,
|
|
37
|
+
IPlaybackTrackData,
|
|
38
|
+
} from "./GroupPlaybackTrackData";
|
|
39
|
+
import { TelemetryEvents } from "./consts";
|
|
16
40
|
|
|
17
41
|
/**
|
|
18
42
|
* @hidden
|
|
@@ -38,7 +62,7 @@ export interface ITransportCommandEvent extends ILiveEvent {
|
|
|
38
62
|
* @hidden
|
|
39
63
|
*/
|
|
40
64
|
export interface ISetTrackEvent extends ILiveEvent {
|
|
41
|
-
metadata: ExtendedMediaMetadata|null;
|
|
65
|
+
metadata: ExtendedMediaMetadata | null;
|
|
42
66
|
waitPoints: CoordinationWaitPoint[];
|
|
43
67
|
}
|
|
44
68
|
|
|
@@ -46,13 +70,13 @@ export interface ISetTrackEvent extends ILiveEvent {
|
|
|
46
70
|
* @hidden
|
|
47
71
|
*/
|
|
48
72
|
export interface ISetTrackDataEvent extends ILiveEvent {
|
|
49
|
-
data: object|null;
|
|
73
|
+
data: object | null;
|
|
50
74
|
}
|
|
51
75
|
|
|
52
76
|
/**
|
|
53
77
|
* @hidden
|
|
54
78
|
*/
|
|
55
|
-
|
|
79
|
+
export interface ITriggerActionEvent extends IEvent {
|
|
56
80
|
details: ExtendedMediaSessionActionDetails;
|
|
57
81
|
}
|
|
58
82
|
|
|
@@ -60,14 +84,14 @@ export interface ISetTrackDataEvent extends ILiveEvent {
|
|
|
60
84
|
* @hidden
|
|
61
85
|
*/
|
|
62
86
|
export enum GroupCoordinatorStateEvents {
|
|
63
|
-
newwaitpoint =
|
|
64
|
-
triggeraction =
|
|
87
|
+
newwaitpoint = "newwaitpoint",
|
|
88
|
+
triggeraction = "triggeraction",
|
|
65
89
|
}
|
|
66
90
|
|
|
67
91
|
/**
|
|
68
92
|
* @hidden
|
|
69
93
|
*/
|
|
70
|
-
|
|
94
|
+
export class GroupCoordinatorState extends EventEmitter {
|
|
71
95
|
private readonly _runtime: IRuntimeSignaler;
|
|
72
96
|
private readonly _logger: LiveTelemetryLogger;
|
|
73
97
|
private readonly _maxPlaybackDrift: TimeInterval;
|
|
@@ -87,69 +111,118 @@ export enum GroupCoordinatorStateEvents {
|
|
|
87
111
|
// - Soft suspensions temporarily disconnect the local media session when transitioning between
|
|
88
112
|
// paused, playing, and none states. This is to give the local client time to finish any inprogress
|
|
89
113
|
// operations like sending a transport command or ending a suspension.
|
|
90
|
-
private _lastStateChange: ExtendedMediaSessionPlaybackState =
|
|
114
|
+
private _lastStateChange: ExtendedMediaSessionPlaybackState = "none";
|
|
91
115
|
private _lastStateChangeTime: number = 0;
|
|
92
116
|
|
|
93
|
-
constructor
|
|
117
|
+
constructor(
|
|
118
|
+
runtime: IRuntimeSignaler,
|
|
119
|
+
maxPlaybackDrift: TimeInterval,
|
|
120
|
+
positionUpdateInterval: TimeInterval,
|
|
121
|
+
getMediaPlayerState: () => IMediaPlayerState
|
|
122
|
+
) {
|
|
94
123
|
super();
|
|
95
124
|
this._runtime = runtime;
|
|
96
125
|
this._logger = new LiveTelemetryLogger(runtime);
|
|
97
126
|
this._maxPlaybackDrift = maxPlaybackDrift;
|
|
98
127
|
this._playbackTrack = new GroupPlaybackTrack(getMediaPlayerState);
|
|
99
|
-
this._playbackTrackData = new GroupPlaybackTrackData(
|
|
100
|
-
|
|
101
|
-
|
|
128
|
+
this._playbackTrackData = new GroupPlaybackTrackData(
|
|
129
|
+
this._playbackTrack
|
|
130
|
+
);
|
|
131
|
+
this._transportState = new GroupTransportState(
|
|
132
|
+
this._playbackTrack,
|
|
133
|
+
getMediaPlayerState
|
|
134
|
+
);
|
|
135
|
+
this._playbackPosition = new GroupPlaybackPosition(
|
|
136
|
+
this._transportState,
|
|
137
|
+
this._runtime,
|
|
138
|
+
positionUpdateInterval
|
|
139
|
+
);
|
|
102
140
|
this._getMediaPlayerState = getMediaPlayerState;
|
|
103
141
|
|
|
104
142
|
// Listen track related events
|
|
105
|
-
this._playbackTrack.on(GroupPlaybackTrackEvents.trackChange, evt => {
|
|
143
|
+
this._playbackTrack.on(GroupPlaybackTrackEvents.trackChange, (evt) => {
|
|
106
144
|
if (!this.isSuspended) {
|
|
107
|
-
this._logger.sendTelemetryEvent(
|
|
145
|
+
this._logger.sendTelemetryEvent(
|
|
146
|
+
TelemetryEvents.GroupCoordinator.TrackChanged
|
|
147
|
+
);
|
|
108
148
|
this.emitSetTrack(evt.metadata!);
|
|
109
149
|
} else {
|
|
110
|
-
this._logger.sendTelemetryEvent(
|
|
150
|
+
this._logger.sendTelemetryEvent(
|
|
151
|
+
TelemetryEvents.GroupCoordinator.TrackChangeDelayed
|
|
152
|
+
);
|
|
111
153
|
}
|
|
112
154
|
});
|
|
113
155
|
|
|
114
156
|
// Listen for track data changes
|
|
115
|
-
this._playbackTrackData.on(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
this.
|
|
119
|
-
|
|
120
|
-
|
|
157
|
+
this._playbackTrackData.on(
|
|
158
|
+
PlaybackTrackDataEvents.dataChange,
|
|
159
|
+
(evt) => {
|
|
160
|
+
if (!this.isSuspended && !this.isWaiting) {
|
|
161
|
+
this._logger.sendTelemetryEvent(
|
|
162
|
+
TelemetryEvents.GroupCoordinator.TrackDataChanged
|
|
163
|
+
);
|
|
164
|
+
this.emitTriggerAction({
|
|
165
|
+
action: "datachange",
|
|
166
|
+
data: evt.data,
|
|
167
|
+
});
|
|
168
|
+
} else {
|
|
169
|
+
this._logger.sendTelemetryEvent(
|
|
170
|
+
TelemetryEvents.GroupCoordinator.TrackDataChangeDelayed
|
|
171
|
+
);
|
|
172
|
+
}
|
|
121
173
|
}
|
|
122
|
-
|
|
174
|
+
);
|
|
123
175
|
|
|
124
176
|
// Listen to transport related events
|
|
125
|
-
this._transportState.on(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
177
|
+
this._transportState.on(
|
|
178
|
+
GroupTransportStateEvents.transportStateChange,
|
|
179
|
+
(evt) => {
|
|
180
|
+
if (!this.isSuspended && !this.isWaiting) {
|
|
181
|
+
this._logger.sendTelemetryEvent(
|
|
182
|
+
TelemetryEvents.GroupCoordinator.TransportStateChanged,
|
|
183
|
+
null,
|
|
184
|
+
{
|
|
185
|
+
action: evt.action,
|
|
186
|
+
seekTime: evt.seekTime,
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// Trigger action
|
|
191
|
+
switch (evt.action) {
|
|
192
|
+
case "play":
|
|
193
|
+
this.emitTriggerAction({
|
|
194
|
+
action: "play",
|
|
195
|
+
seekTime: evt.seekTime,
|
|
196
|
+
});
|
|
197
|
+
break;
|
|
137
198
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
199
|
+
case "pause":
|
|
200
|
+
this.emitTriggerAction({
|
|
201
|
+
action: "pause",
|
|
202
|
+
seekTime: evt.seekTime,
|
|
203
|
+
});
|
|
204
|
+
break;
|
|
141
205
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
206
|
+
case "seekto":
|
|
207
|
+
this.emitTriggerAction({
|
|
208
|
+
action: "seekto",
|
|
209
|
+
seekTime: evt.seekTime,
|
|
210
|
+
});
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
this._logger.sendTelemetryEvent(
|
|
215
|
+
TelemetryEvents.GroupCoordinator
|
|
216
|
+
.TransportStateChangeDelayed,
|
|
217
|
+
null,
|
|
218
|
+
{
|
|
219
|
+
action: evt.action,
|
|
220
|
+
seekTime: evt.seekTime,
|
|
221
|
+
}
|
|
222
|
+
);
|
|
145
223
|
}
|
|
146
|
-
} else {
|
|
147
|
-
this._logger.sendTelemetryEvent(TelemetryEvents.GroupCoordinator.TransportStateChangeDelayed, null, {
|
|
148
|
-
action: evt.action,
|
|
149
|
-
seekTime: evt.seekTime
|
|
150
|
-
});
|
|
151
224
|
}
|
|
152
|
-
|
|
225
|
+
);
|
|
153
226
|
}
|
|
154
227
|
|
|
155
228
|
public get playbackTrack(): GroupPlaybackTrack {
|
|
@@ -168,7 +241,7 @@ export enum GroupCoordinatorStateEvents {
|
|
|
168
241
|
return this._playbackPosition;
|
|
169
242
|
}
|
|
170
243
|
|
|
171
|
-
public get waitingAt(): CoordinationWaitPoint|undefined {
|
|
244
|
+
public get waitingAt(): CoordinationWaitPoint | undefined {
|
|
172
245
|
return this._waitPoint;
|
|
173
246
|
}
|
|
174
247
|
|
|
@@ -204,7 +277,9 @@ export enum GroupCoordinatorStateEvents {
|
|
|
204
277
|
}
|
|
205
278
|
}
|
|
206
279
|
|
|
207
|
-
public createPositionUpdateEvent(
|
|
280
|
+
public createPositionUpdateEvent(
|
|
281
|
+
state: IMediaPlayerState
|
|
282
|
+
): Partial<IPositionUpdateEvent> {
|
|
208
283
|
const { positionState, playbackState } = state;
|
|
209
284
|
if (this.isSuspended) {
|
|
210
285
|
// Report suspension state
|
|
@@ -212,9 +287,9 @@ export enum GroupCoordinatorStateEvents {
|
|
|
212
287
|
track: this.playbackTrack.current,
|
|
213
288
|
trackData: this.playbackTrackData.current,
|
|
214
289
|
transport: this.transportState.current,
|
|
215
|
-
playbackState:
|
|
290
|
+
playbackState: "suspended",
|
|
216
291
|
position: positionState?.position || 0.0,
|
|
217
|
-
waitPoint: this._waitPoint
|
|
292
|
+
waitPoint: this._waitPoint,
|
|
218
293
|
};
|
|
219
294
|
} else {
|
|
220
295
|
// Report current position
|
|
@@ -222,9 +297,9 @@ export enum GroupCoordinatorStateEvents {
|
|
|
222
297
|
track: this.playbackTrack.current,
|
|
223
298
|
trackData: this.playbackTrackData.current,
|
|
224
299
|
transport: this.transportState.current,
|
|
225
|
-
playbackState: this._waitPoint ?
|
|
300
|
+
playbackState: this._waitPoint ? "waiting" : playbackState,
|
|
226
301
|
position: positionState?.position || 0.0,
|
|
227
|
-
waitPoint: this._waitPoint
|
|
302
|
+
waitPoint: this._waitPoint,
|
|
228
303
|
};
|
|
229
304
|
}
|
|
230
305
|
}
|
|
@@ -236,11 +311,20 @@ export enum GroupCoordinatorStateEvents {
|
|
|
236
311
|
metadata: event.metadata,
|
|
237
312
|
waitPoints: event.waitPoints,
|
|
238
313
|
timestamp: event.timestamp,
|
|
239
|
-
clientId: event.clientId ||
|
|
314
|
+
clientId: event.clientId || "",
|
|
240
315
|
});
|
|
241
316
|
|
|
242
317
|
if (updated) {
|
|
243
|
-
this._logger.sendTelemetryEvent(
|
|
318
|
+
this._logger.sendTelemetryEvent(
|
|
319
|
+
TelemetryEvents.SessionCoordinator.RemoteSetTrackReceived,
|
|
320
|
+
null,
|
|
321
|
+
{
|
|
322
|
+
correlationId: LiveTelemetryLogger.formatCorrelationId(
|
|
323
|
+
event.clientId,
|
|
324
|
+
event.timestamp
|
|
325
|
+
),
|
|
326
|
+
}
|
|
327
|
+
);
|
|
244
328
|
}
|
|
245
329
|
}
|
|
246
330
|
|
|
@@ -250,15 +334,27 @@ export enum GroupCoordinatorStateEvents {
|
|
|
250
334
|
const updated = this.playbackTrackData.updateData({
|
|
251
335
|
data: event.data,
|
|
252
336
|
timestamp: event.timestamp,
|
|
253
|
-
clientId: event.clientId ||
|
|
337
|
+
clientId: event.clientId || "",
|
|
254
338
|
});
|
|
255
339
|
|
|
256
340
|
if (updated) {
|
|
257
|
-
this._logger.sendTelemetryEvent(
|
|
341
|
+
this._logger.sendTelemetryEvent(
|
|
342
|
+
TelemetryEvents.SessionCoordinator.RemoteSetTrackReceived,
|
|
343
|
+
null,
|
|
344
|
+
{
|
|
345
|
+
correlationId: LiveTelemetryLogger.formatCorrelationId(
|
|
346
|
+
event.clientId,
|
|
347
|
+
event.timestamp
|
|
348
|
+
),
|
|
349
|
+
}
|
|
350
|
+
);
|
|
258
351
|
}
|
|
259
352
|
}
|
|
260
353
|
|
|
261
|
-
public handleTransportCommand(
|
|
354
|
+
public handleTransportCommand(
|
|
355
|
+
event: ITransportCommandEvent,
|
|
356
|
+
local: boolean
|
|
357
|
+
): void {
|
|
262
358
|
// Ensure change is for current track
|
|
263
359
|
// - Will trigger a 'trackChange' event if newer track.
|
|
264
360
|
this.playbackTrack.updateTrack(event.track);
|
|
@@ -266,11 +362,11 @@ export enum GroupCoordinatorStateEvents {
|
|
|
266
362
|
// Update playback state
|
|
267
363
|
let playbackState = this.transportState.playbackState;
|
|
268
364
|
switch (event.name) {
|
|
269
|
-
case
|
|
270
|
-
playbackState =
|
|
365
|
+
case "play":
|
|
366
|
+
playbackState = "playing";
|
|
271
367
|
break;
|
|
272
|
-
case
|
|
273
|
-
playbackState =
|
|
368
|
+
case "pause":
|
|
369
|
+
playbackState = "paused";
|
|
274
370
|
break;
|
|
275
371
|
}
|
|
276
372
|
|
|
@@ -279,29 +375,55 @@ export enum GroupCoordinatorStateEvents {
|
|
|
279
375
|
playbackState: playbackState,
|
|
280
376
|
startPosition: event.position,
|
|
281
377
|
timestamp: event.timestamp,
|
|
282
|
-
clientId: event.clientId ||
|
|
378
|
+
clientId: event.clientId || "",
|
|
283
379
|
};
|
|
284
380
|
const updated = this.transportState.updateState(newState);
|
|
285
381
|
|
|
286
382
|
if (updated) {
|
|
287
|
-
const correlationId = LiveTelemetryLogger.formatCorrelationId(
|
|
383
|
+
const correlationId = LiveTelemetryLogger.formatCorrelationId(
|
|
384
|
+
event.clientId,
|
|
385
|
+
event.timestamp
|
|
386
|
+
);
|
|
288
387
|
switch (event.name) {
|
|
289
|
-
case
|
|
290
|
-
this._logger.sendTelemetryEvent(
|
|
388
|
+
case "play":
|
|
389
|
+
this._logger.sendTelemetryEvent(
|
|
390
|
+
TelemetryEvents.SessionCoordinator
|
|
391
|
+
.RemotePlayReceived,
|
|
392
|
+
null,
|
|
393
|
+
{
|
|
394
|
+
correlationId: correlationId,
|
|
395
|
+
}
|
|
396
|
+
);
|
|
291
397
|
break;
|
|
292
|
-
case
|
|
293
|
-
this._logger.sendTelemetryEvent(
|
|
398
|
+
case "pause":
|
|
399
|
+
this._logger.sendTelemetryEvent(
|
|
400
|
+
TelemetryEvents.SessionCoordinator
|
|
401
|
+
.RemotePauseReceived,
|
|
402
|
+
null,
|
|
403
|
+
{
|
|
404
|
+
correlationId: correlationId,
|
|
405
|
+
}
|
|
406
|
+
);
|
|
294
407
|
break;
|
|
295
|
-
case
|
|
296
|
-
this._logger.sendTelemetryEvent(
|
|
408
|
+
case "seekTo":
|
|
409
|
+
this._logger.sendTelemetryEvent(
|
|
410
|
+
TelemetryEvents.SessionCoordinator
|
|
411
|
+
.RemoteSeekToReceived,
|
|
412
|
+
null,
|
|
413
|
+
{
|
|
414
|
+
correlationId: correlationId,
|
|
415
|
+
}
|
|
416
|
+
);
|
|
297
417
|
break;
|
|
298
418
|
}
|
|
299
|
-
|
|
300
419
|
}
|
|
301
420
|
}
|
|
302
421
|
}
|
|
303
422
|
|
|
304
|
-
public handlePositionUpdate(
|
|
423
|
+
public handlePositionUpdate(
|
|
424
|
+
event: IPositionUpdateEvent,
|
|
425
|
+
local: boolean
|
|
426
|
+
): void {
|
|
305
427
|
// Ensure change is for current track
|
|
306
428
|
// - Will trigger a 'trackChange' event if newer track.
|
|
307
429
|
this.playbackTrack.updateTrack(event.track);
|
|
@@ -312,7 +434,7 @@ export enum GroupCoordinatorStateEvents {
|
|
|
312
434
|
// Update transport state if needed
|
|
313
435
|
// - Ignore transport state changes if the client has ended as this will cause the local
|
|
314
436
|
// player to start playback even though the video may have ended for everyone.
|
|
315
|
-
if (event.playbackState !=
|
|
437
|
+
if (event.playbackState != "ended") {
|
|
316
438
|
this.transportState.updateState(event.transport);
|
|
317
439
|
}
|
|
318
440
|
|
|
@@ -324,7 +446,7 @@ export enum GroupCoordinatorStateEvents {
|
|
|
324
446
|
waitPoint: event.waitPoint,
|
|
325
447
|
position: event.position,
|
|
326
448
|
timestamp: event.timestamp,
|
|
327
|
-
clientId: event.clientId ||
|
|
449
|
+
clientId: event.clientId || "",
|
|
328
450
|
};
|
|
329
451
|
this.playbackPosition.UpdatePlaybackPosition(position);
|
|
330
452
|
|
|
@@ -335,13 +457,19 @@ export enum GroupCoordinatorStateEvents {
|
|
|
335
457
|
// the rest of the group while the local player is trying to to seek to a
|
|
336
458
|
// new position.
|
|
337
459
|
switch (event.playbackState) {
|
|
338
|
-
case
|
|
339
|
-
case
|
|
340
|
-
case
|
|
460
|
+
case "none":
|
|
461
|
+
case "paused":
|
|
462
|
+
case "playing":
|
|
341
463
|
if (event.playbackState != this._lastStateChange) {
|
|
342
|
-
this._logger.sendTelemetryEvent(
|
|
464
|
+
this._logger.sendTelemetryEvent(
|
|
465
|
+
TelemetryEvents.GroupCoordinator
|
|
466
|
+
.BeginSoftSuspension,
|
|
467
|
+
null,
|
|
468
|
+
{ playbackState: event.playbackState }
|
|
469
|
+
);
|
|
343
470
|
this._lastStateChange = event.playbackState;
|
|
344
|
-
this._lastStateChangeTime =
|
|
471
|
+
this._lastStateChangeTime =
|
|
472
|
+
LiveShareClient.getTimestamp();
|
|
345
473
|
}
|
|
346
474
|
break;
|
|
347
475
|
}
|
|
@@ -366,14 +494,20 @@ export enum GroupCoordinatorStateEvents {
|
|
|
366
494
|
|
|
367
495
|
public async syncLocalMediaSession(): Promise<void> {
|
|
368
496
|
// Skip further syncs if we're waiting or in a "soft suspension".
|
|
369
|
-
const softSuspensionDelta =
|
|
497
|
+
const softSuspensionDelta =
|
|
498
|
+
LiveShareClient.getTimestamp() - this._lastStateChangeTime;
|
|
370
499
|
if (!this.isWaiting && softSuspensionDelta >= 1000) {
|
|
371
|
-
let { metadata, trackData, positionState, playbackState } =
|
|
372
|
-
|
|
500
|
+
let { metadata, trackData, positionState, playbackState } =
|
|
501
|
+
this._getMediaPlayerState();
|
|
502
|
+
this._logger.sendTelemetryEvent(
|
|
503
|
+
TelemetryEvents.GroupCoordinator.CheckingForSyncIssues
|
|
504
|
+
);
|
|
373
505
|
|
|
374
506
|
// Check for track change
|
|
375
507
|
if (!this.playbackTrack.compare(metadata)) {
|
|
376
|
-
this._logger.sendTelemetryEvent(
|
|
508
|
+
this._logger.sendTelemetryEvent(
|
|
509
|
+
TelemetryEvents.GroupCoordinator.TrackOutOfSync
|
|
510
|
+
);
|
|
377
511
|
this.emitSetTrack(this.playbackTrack.metadata!);
|
|
378
512
|
return;
|
|
379
513
|
}
|
|
@@ -384,7 +518,10 @@ export enum GroupCoordinatorStateEvents {
|
|
|
384
518
|
// else has finished the video.
|
|
385
519
|
// - Should another user seek or press play after the video has ended that will cause
|
|
386
520
|
// a transport action to trigger which will take the player out of the ended state.
|
|
387
|
-
if (
|
|
521
|
+
if (
|
|
522
|
+
playbackState != "ended" &&
|
|
523
|
+
!this._playbackPosition.trackEnded
|
|
524
|
+
) {
|
|
388
525
|
// Ensure we have a position
|
|
389
526
|
let position = positionState?.position;
|
|
390
527
|
if (position == undefined) {
|
|
@@ -394,37 +531,59 @@ export enum GroupCoordinatorStateEvents {
|
|
|
394
531
|
// Check for catchup
|
|
395
532
|
// - Target can return -1 in cases where there is no position tracking data
|
|
396
533
|
const target = this.playbackPosition.targetPosition;
|
|
397
|
-
if (
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
534
|
+
if (
|
|
535
|
+
target >= 0.0 &&
|
|
536
|
+
Math.abs(target - position) >=
|
|
537
|
+
this._maxPlaybackDrift.seconds
|
|
538
|
+
) {
|
|
539
|
+
this._logger.sendTelemetryEvent(
|
|
540
|
+
TelemetryEvents.GroupCoordinator.PositionOutOfSync,
|
|
541
|
+
null,
|
|
542
|
+
{
|
|
543
|
+
current: position,
|
|
544
|
+
target: target,
|
|
545
|
+
}
|
|
546
|
+
);
|
|
547
|
+
await this.emitTriggerAction({
|
|
548
|
+
action: "catchup",
|
|
549
|
+
seekTime: target,
|
|
401
550
|
});
|
|
402
|
-
await this.emitTriggerAction({action: 'catchup', seekTime: target});
|
|
403
551
|
}
|
|
404
552
|
|
|
405
553
|
// Sync transport state
|
|
406
554
|
if (this.transportState.playbackState != playbackState) {
|
|
407
|
-
this._logger.sendTelemetryEvent(
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
555
|
+
this._logger.sendTelemetryEvent(
|
|
556
|
+
TelemetryEvents.GroupCoordinator.TransportOutOfSync,
|
|
557
|
+
null,
|
|
558
|
+
{
|
|
559
|
+
current: playbackState,
|
|
560
|
+
target: this.transportState.playbackState,
|
|
561
|
+
}
|
|
562
|
+
);
|
|
411
563
|
switch (this.transportState.playbackState) {
|
|
412
|
-
case
|
|
413
|
-
await this.emitTriggerAction({action:
|
|
564
|
+
case "playing":
|
|
565
|
+
await this.emitTriggerAction({ action: "play" });
|
|
414
566
|
break;
|
|
415
|
-
case
|
|
416
|
-
await this.emitTriggerAction({action:
|
|
567
|
+
case "paused":
|
|
568
|
+
await this.emitTriggerAction({ action: "pause" });
|
|
417
569
|
break;
|
|
418
570
|
}
|
|
419
571
|
}
|
|
420
572
|
|
|
421
573
|
// Sync track data
|
|
422
|
-
if (
|
|
423
|
-
|
|
424
|
-
|
|
574
|
+
if (
|
|
575
|
+
JSON.stringify(this.playbackTrackData.data) !=
|
|
576
|
+
JSON.stringify(trackData)
|
|
577
|
+
) {
|
|
578
|
+
this._logger.sendTelemetryEvent(
|
|
579
|
+
TelemetryEvents.GroupCoordinator.TrackDataOutOfSync
|
|
580
|
+
);
|
|
581
|
+
await this.emitTriggerAction({
|
|
582
|
+
action: "datachange",
|
|
583
|
+
data: this.playbackTrackData.data,
|
|
584
|
+
});
|
|
425
585
|
}
|
|
426
586
|
}
|
|
427
|
-
|
|
428
587
|
}
|
|
429
588
|
}
|
|
430
589
|
|
|
@@ -433,14 +592,16 @@ export enum GroupCoordinatorStateEvents {
|
|
|
433
592
|
this._waitPoint = undefined;
|
|
434
593
|
|
|
435
594
|
// Trigger settrack action
|
|
436
|
-
this.emitTriggerAction({action:
|
|
595
|
+
this.emitTriggerAction({ action: "settrack", metadata: metadata });
|
|
437
596
|
}
|
|
438
597
|
|
|
439
|
-
private emitTriggerAction(
|
|
598
|
+
private emitTriggerAction(
|
|
599
|
+
details: ExtendedMediaSessionActionDetails
|
|
600
|
+
): void {
|
|
440
601
|
const evt: ITriggerActionEvent = {
|
|
441
602
|
name: GroupCoordinatorStateEvents.triggeraction,
|
|
442
|
-
details: details
|
|
603
|
+
details: details,
|
|
443
604
|
};
|
|
444
|
-
|
|
605
|
+
this.emit(GroupCoordinatorStateEvents.triggeraction, evt);
|
|
445
606
|
}
|
|
446
|
-
}
|
|
607
|
+
}
|