@microsoft/live-share-media 1.0.0-preview.8 → 1.0.0
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/LICENSE +64 -61
- package/README.md +11 -15
- package/bin/IMediaPlayer.d.ts +20 -20
- package/bin/IMediaPlayer.js +6 -6
- package/bin/LiveMediaSession.d.ts +90 -94
- package/bin/LiveMediaSession.d.ts.map +1 -1
- package/bin/LiveMediaSession.js +228 -231
- package/bin/LiveMediaSession.js.map +1 -1
- package/bin/LiveMediaSessionCoordinator.d.ts +238 -227
- package/bin/LiveMediaSessionCoordinator.d.ts.map +1 -1
- package/bin/LiveMediaSessionCoordinator.js +476 -407
- package/bin/LiveMediaSessionCoordinator.js.map +1 -1
- package/bin/LiveMediaSessionCoordinatorSuspension.d.ts +19 -19
- package/bin/LiveMediaSessionCoordinatorSuspension.js +27 -27
- package/bin/MediaPlayerSynchronizer.d.ts +173 -163
- package/bin/MediaPlayerSynchronizer.d.ts.map +1 -1
- package/bin/MediaPlayerSynchronizer.js +491 -468
- package/bin/MediaPlayerSynchronizer.js.map +1 -1
- package/bin/MediaSessionActionThrottler.d.ts +11 -11
- package/bin/MediaSessionActionThrottler.js +13 -13
- package/bin/MediaSessionExtensions.d.ts +34 -34
- package/bin/MediaSessionExtensions.d.ts.map +1 -1
- package/bin/MediaSessionExtensions.js +12 -12
- package/bin/RepeatedActionThrottler.d.ts +19 -19
- package/bin/RepeatedActionThrottler.js +62 -62
- package/bin/RepeatedActionThrottler.js.map +1 -1
- package/bin/VolumeManager.d.ts +83 -83
- package/bin/VolumeManager.js +174 -174
- package/bin/index.d.ts +13 -13
- package/bin/index.js +29 -29
- package/bin/internals/GroupCoordinatorState.d.ts +93 -92
- package/bin/internals/GroupCoordinatorState.d.ts.map +1 -1
- package/bin/internals/GroupCoordinatorState.js +407 -404
- package/bin/internals/GroupCoordinatorState.js.map +1 -1
- package/bin/internals/GroupPlaybackPosition.d.ts +67 -66
- package/bin/internals/GroupPlaybackPosition.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackPosition.js +166 -166
- package/bin/internals/GroupPlaybackPosition.js.map +1 -1
- package/bin/internals/GroupPlaybackTrack.d.ts +45 -45
- package/bin/internals/GroupPlaybackTrack.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackTrack.js +121 -121
- package/bin/internals/GroupPlaybackTrackData.d.ts +39 -39
- package/bin/internals/GroupPlaybackTrackData.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackTrackData.js +69 -69
- package/bin/internals/GroupTransportState.d.ts +49 -48
- package/bin/internals/GroupTransportState.d.ts.map +1 -1
- package/bin/internals/GroupTransportState.js +111 -111
- package/bin/internals/GroupTransportState.js.map +1 -1
- package/bin/internals/consts.d.ts +75 -72
- package/bin/internals/consts.d.ts.map +1 -1
- package/bin/internals/consts.js +84 -81
- package/bin/internals/consts.js.map +1 -1
- package/bin/internals/index.d.ts +10 -10
- package/bin/internals/index.js +26 -26
- package/package.json +9 -7
- package/src/LiveMediaSession.ts +24 -20
- package/src/LiveMediaSessionCoordinator.ts +101 -29
- package/src/MediaPlayerSynchronizer.ts +30 -14
- package/src/internals/GroupCoordinatorState.ts +49 -34
- package/src/internals/GroupPlaybackPosition.ts +7 -3
- package/src/internals/GroupPlaybackTrack.ts +2 -2
- package/src/internals/GroupPlaybackTrackData.ts +2 -2
- package/src/internals/GroupTransportState.ts +11 -4
- package/src/internals/consts.ts +4 -0
- package/typedoc.json +10 -0
- 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/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/src/test/GroupPlaybackPosition.spec.ts +0 -600
- package/src/test/GroupPlaybackTrack.spec.ts +0 -122
- package/src/test/SharedMediaSession.spec.ts +0 -149
- package/src/test/SharedMediaSessionCoordinator.spec.ts +0 -271
- package/src/test/VolumeManager.spec.ts +0 -219
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
IEvent,
|
|
8
7
|
ILiveEvent,
|
|
9
|
-
LiveEvent,
|
|
10
8
|
TimeInterval,
|
|
11
9
|
IRuntimeSignaler,
|
|
12
10
|
LiveTelemetryLogger,
|
|
11
|
+
LiveShareRuntime,
|
|
12
|
+
IEvent,
|
|
13
13
|
} from "@microsoft/live-share";
|
|
14
14
|
import EventEmitter from "events";
|
|
15
15
|
import {
|
|
@@ -40,7 +40,7 @@ import { TelemetryEvents } from "./consts";
|
|
|
40
40
|
/**
|
|
41
41
|
* @hidden
|
|
42
42
|
*/
|
|
43
|
-
export interface IPositionUpdateEvent
|
|
43
|
+
export interface IPositionUpdateEvent {
|
|
44
44
|
track: IPlaybackTrack;
|
|
45
45
|
trackData: IPlaybackTrackData;
|
|
46
46
|
transport: ITransportState;
|
|
@@ -52,7 +52,7 @@ export interface IPositionUpdateEvent extends ILiveEvent {
|
|
|
52
52
|
/**
|
|
53
53
|
* @hidden
|
|
54
54
|
*/
|
|
55
|
-
export interface ITransportCommandEvent
|
|
55
|
+
export interface ITransportCommandEvent {
|
|
56
56
|
track: IPlaybackTrack;
|
|
57
57
|
position: number;
|
|
58
58
|
}
|
|
@@ -60,7 +60,7 @@ export interface ITransportCommandEvent extends ILiveEvent {
|
|
|
60
60
|
/**
|
|
61
61
|
* @hidden
|
|
62
62
|
*/
|
|
63
|
-
export interface ISetTrackEvent
|
|
63
|
+
export interface ISetTrackEvent {
|
|
64
64
|
metadata: ExtendedMediaMetadata | null;
|
|
65
65
|
waitPoints: CoordinationWaitPoint[];
|
|
66
66
|
}
|
|
@@ -68,7 +68,7 @@ export interface ISetTrackEvent extends ILiveEvent {
|
|
|
68
68
|
/**
|
|
69
69
|
* @hidden
|
|
70
70
|
*/
|
|
71
|
-
export interface ISetTrackDataEvent
|
|
71
|
+
export interface ISetTrackDataEvent {
|
|
72
72
|
data: object | null;
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -92,6 +92,7 @@ export enum GroupCoordinatorStateEvents {
|
|
|
92
92
|
*/
|
|
93
93
|
export class GroupCoordinatorState extends EventEmitter {
|
|
94
94
|
private readonly _runtime: IRuntimeSignaler;
|
|
95
|
+
private readonly _liveRuntime: LiveShareRuntime;
|
|
95
96
|
private readonly _logger: LiveTelemetryLogger;
|
|
96
97
|
private readonly _maxPlaybackDrift: TimeInterval;
|
|
97
98
|
private _getMediaPlayerState: () => IMediaPlayerState;
|
|
@@ -115,13 +116,15 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
115
116
|
|
|
116
117
|
constructor(
|
|
117
118
|
runtime: IRuntimeSignaler,
|
|
119
|
+
liveRuntime: LiveShareRuntime,
|
|
118
120
|
maxPlaybackDrift: TimeInterval,
|
|
119
121
|
positionUpdateInterval: TimeInterval,
|
|
120
122
|
getMediaPlayerState: () => IMediaPlayerState
|
|
121
123
|
) {
|
|
122
124
|
super();
|
|
123
125
|
this._runtime = runtime;
|
|
124
|
-
this.
|
|
126
|
+
this._liveRuntime = liveRuntime;
|
|
127
|
+
this._logger = new LiveTelemetryLogger(runtime, liveRuntime);
|
|
125
128
|
this._maxPlaybackDrift = maxPlaybackDrift;
|
|
126
129
|
this._playbackTrack = new GroupPlaybackTrack(getMediaPlayerState);
|
|
127
130
|
this._playbackTrackData = new GroupPlaybackTrackData(
|
|
@@ -129,11 +132,13 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
129
132
|
);
|
|
130
133
|
this._transportState = new GroupTransportState(
|
|
131
134
|
this._playbackTrack,
|
|
132
|
-
getMediaPlayerState
|
|
135
|
+
getMediaPlayerState,
|
|
136
|
+
this._liveRuntime
|
|
133
137
|
);
|
|
134
138
|
this._playbackPosition = new GroupPlaybackPosition(
|
|
135
139
|
this._transportState,
|
|
136
140
|
this._runtime,
|
|
141
|
+
this._liveRuntime,
|
|
137
142
|
positionUpdateInterval
|
|
138
143
|
);
|
|
139
144
|
this._getMediaPlayerState = getMediaPlayerState;
|
|
@@ -278,7 +283,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
278
283
|
|
|
279
284
|
public createPositionUpdateEvent(
|
|
280
285
|
state: IMediaPlayerState
|
|
281
|
-
):
|
|
286
|
+
): IPositionUpdateEvent {
|
|
282
287
|
const { positionState, playbackState } = state;
|
|
283
288
|
if (this.isSuspended) {
|
|
284
289
|
// Report suspension state
|
|
@@ -303,12 +308,15 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
303
308
|
}
|
|
304
309
|
}
|
|
305
310
|
|
|
306
|
-
public handleSetTrack(
|
|
311
|
+
public handleSetTrack(
|
|
312
|
+
event: ILiveEvent<ISetTrackEvent>,
|
|
313
|
+
local: boolean
|
|
314
|
+
): void {
|
|
307
315
|
// Update shared track
|
|
308
316
|
// - Will trigger 'trackChange' event to update media session
|
|
309
317
|
const updated = this.playbackTrack.updateTrack({
|
|
310
|
-
metadata: event.metadata,
|
|
311
|
-
waitPoints: event.waitPoints,
|
|
318
|
+
metadata: event.data.metadata,
|
|
319
|
+
waitPoints: event.data.waitPoints,
|
|
312
320
|
timestamp: event.timestamp,
|
|
313
321
|
clientId: event.clientId || "",
|
|
314
322
|
});
|
|
@@ -327,11 +335,14 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
327
335
|
}
|
|
328
336
|
}
|
|
329
337
|
|
|
330
|
-
public handleSetTrackData(
|
|
338
|
+
public handleSetTrackData(
|
|
339
|
+
event: ILiveEvent<ISetTrackDataEvent>,
|
|
340
|
+
local: boolean
|
|
341
|
+
): void {
|
|
331
342
|
// Update shared track data
|
|
332
343
|
// - Will trigger 'dataChange' event to update media session
|
|
333
344
|
const updated = this.playbackTrackData.updateData({
|
|
334
|
-
data: event.data,
|
|
345
|
+
data: event.data.data,
|
|
335
346
|
timestamp: event.timestamp,
|
|
336
347
|
clientId: event.clientId || "",
|
|
337
348
|
});
|
|
@@ -351,13 +362,13 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
351
362
|
}
|
|
352
363
|
|
|
353
364
|
public handleTransportCommand(
|
|
354
|
-
event: ITransportCommandEvent
|
|
365
|
+
event: ILiveEvent<ITransportCommandEvent>,
|
|
355
366
|
local: boolean
|
|
356
367
|
): void {
|
|
357
368
|
// Ensure change is for current track
|
|
358
369
|
// - Will trigger a 'trackChange' event if newer track.
|
|
359
|
-
this.playbackTrack.updateTrack(event.track);
|
|
360
|
-
if (this.playbackTrack.compare(event.track.metadata)) {
|
|
370
|
+
this.playbackTrack.updateTrack(event.data.track);
|
|
371
|
+
if (this.playbackTrack.compare(event.data.track.metadata)) {
|
|
361
372
|
// Update playback state
|
|
362
373
|
let playbackState = this.transportState.playbackState;
|
|
363
374
|
switch (event.name) {
|
|
@@ -372,7 +383,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
372
383
|
// Try to update playback state
|
|
373
384
|
const newState: ITransportState = {
|
|
374
385
|
playbackState: playbackState,
|
|
375
|
-
startPosition: event.position,
|
|
386
|
+
startPosition: event.data.position,
|
|
376
387
|
timestamp: event.timestamp,
|
|
377
388
|
clientId: event.clientId || "",
|
|
378
389
|
};
|
|
@@ -420,30 +431,30 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
420
431
|
}
|
|
421
432
|
|
|
422
433
|
public handlePositionUpdate(
|
|
423
|
-
event: IPositionUpdateEvent
|
|
434
|
+
event: Omit<ILiveEvent<IPositionUpdateEvent>, "name">,
|
|
424
435
|
local: boolean
|
|
425
436
|
): void {
|
|
426
437
|
// Ensure change is for current track
|
|
427
438
|
// - Will trigger a 'trackChange' event if newer track.
|
|
428
|
-
this.playbackTrack.updateTrack(event.track);
|
|
429
|
-
if (this.playbackTrack.compare(event.track.metadata)) {
|
|
439
|
+
this.playbackTrack.updateTrack(event.data.track);
|
|
440
|
+
if (this.playbackTrack.compare(event.data.track.metadata)) {
|
|
430
441
|
// Ensure we have the latest track data
|
|
431
|
-
this.playbackTrackData.updateData(event.trackData);
|
|
442
|
+
this.playbackTrackData.updateData(event.data.trackData);
|
|
432
443
|
|
|
433
444
|
// Update transport state if needed
|
|
434
445
|
// - Ignore transport state changes if the client has ended as this will cause the local
|
|
435
446
|
// player to start playback even though the video may have ended for everyone.
|
|
436
|
-
if (event.playbackState != "ended") {
|
|
437
|
-
this.transportState.updateState(event.transport);
|
|
447
|
+
if (event.data.playbackState != "ended") {
|
|
448
|
+
this.transportState.updateState(event.data.transport);
|
|
438
449
|
}
|
|
439
450
|
|
|
440
451
|
// Ensure change is for current transport state
|
|
441
|
-
if (this.transportState.compare(event.transport)) {
|
|
452
|
+
if (this.transportState.compare(event.data.transport)) {
|
|
442
453
|
// Update playback position
|
|
443
454
|
const position: ICurrentPlaybackPosition = {
|
|
444
|
-
playbackState: event.playbackState,
|
|
445
|
-
waitPoint: event.waitPoint,
|
|
446
|
-
position: event.position,
|
|
455
|
+
playbackState: event.data.playbackState,
|
|
456
|
+
waitPoint: event.data.waitPoint,
|
|
457
|
+
position: event.data.position,
|
|
447
458
|
timestamp: event.timestamp,
|
|
448
459
|
clientId: event.clientId || "",
|
|
449
460
|
};
|
|
@@ -455,20 +466,24 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
455
466
|
// - This is needed because the catchup logic can try to sink the client with
|
|
456
467
|
// the rest of the group while the local player is trying to to seek to a
|
|
457
468
|
// new position.
|
|
458
|
-
switch (event.playbackState) {
|
|
469
|
+
switch (event.data.playbackState) {
|
|
459
470
|
case "none":
|
|
460
471
|
case "paused":
|
|
461
472
|
case "playing":
|
|
462
|
-
if (
|
|
473
|
+
if (
|
|
474
|
+
event.data.playbackState !=
|
|
475
|
+
this._lastStateChange
|
|
476
|
+
) {
|
|
463
477
|
this._logger.sendTelemetryEvent(
|
|
464
478
|
TelemetryEvents.GroupCoordinator
|
|
465
479
|
.BeginSoftSuspension,
|
|
466
480
|
null,
|
|
467
|
-
{ playbackState: event.playbackState }
|
|
481
|
+
{ playbackState: event.data.playbackState }
|
|
468
482
|
);
|
|
469
|
-
this._lastStateChange =
|
|
483
|
+
this._lastStateChange =
|
|
484
|
+
event.data.playbackState;
|
|
470
485
|
this._lastStateChangeTime =
|
|
471
|
-
|
|
486
|
+
this._liveRuntime.getTimestamp();
|
|
472
487
|
}
|
|
473
488
|
break;
|
|
474
489
|
}
|
|
@@ -494,7 +509,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
494
509
|
public async syncLocalMediaSession(): Promise<void> {
|
|
495
510
|
// Skip further syncs if we're waiting or in a "soft suspension".
|
|
496
511
|
const softSuspensionDelta =
|
|
497
|
-
|
|
512
|
+
this._liveRuntime.getTimestamp() - this._lastStateChangeTime;
|
|
498
513
|
if (!this.isWaiting && softSuspensionDelta >= 1000) {
|
|
499
514
|
let { metadata, trackData, positionState, playbackState } =
|
|
500
515
|
this._getMediaPlayerState();
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
LiveEvent,
|
|
8
7
|
IRuntimeSignaler,
|
|
9
8
|
TimeInterval,
|
|
9
|
+
LiveShareClient,
|
|
10
|
+
LiveShareRuntime,
|
|
10
11
|
} from "@microsoft/live-share";
|
|
11
12
|
import { GroupTransportState } from "./GroupTransportState";
|
|
12
13
|
import { GroupPlaybackTrackEvents } from "./GroupPlaybackTrack";
|
|
@@ -34,16 +35,19 @@ export interface ICurrentPlaybackPosition {
|
|
|
34
35
|
export class GroupPlaybackPosition {
|
|
35
36
|
private _transportState: GroupTransportState;
|
|
36
37
|
private _runtime: IRuntimeSignaler;
|
|
38
|
+
private _liveRuntime: LiveShareRuntime;
|
|
37
39
|
private _updateInterval: TimeInterval;
|
|
38
40
|
private _positions: Map<string, ICurrentPlaybackPosition>;
|
|
39
41
|
|
|
40
42
|
constructor(
|
|
41
43
|
transportState: GroupTransportState,
|
|
42
44
|
runtime: IRuntimeSignaler,
|
|
45
|
+
liveRuntime: LiveShareRuntime,
|
|
43
46
|
updateInterval: TimeInterval
|
|
44
47
|
) {
|
|
45
48
|
this._transportState = transportState;
|
|
46
49
|
this._runtime = runtime;
|
|
50
|
+
this._liveRuntime = liveRuntime;
|
|
47
51
|
this._updateInterval = updateInterval;
|
|
48
52
|
this._positions = new Map();
|
|
49
53
|
|
|
@@ -129,7 +133,7 @@ export class GroupPlaybackPosition {
|
|
|
129
133
|
*/
|
|
130
134
|
public get maxPosition(): number {
|
|
131
135
|
if (this._transportState.playbackState == "playing") {
|
|
132
|
-
const now =
|
|
136
|
+
const now = this._liveRuntime.getTimestamp();
|
|
133
137
|
const projected =
|
|
134
138
|
this._transportState.startPosition +
|
|
135
139
|
(now - this._transportState.timestamp) / 1000;
|
|
@@ -162,7 +166,7 @@ export class GroupPlaybackPosition {
|
|
|
162
166
|
projectedPosition: number
|
|
163
167
|
) => void
|
|
164
168
|
): void {
|
|
165
|
-
const now =
|
|
169
|
+
const now = this._liveRuntime.getTimestamp();
|
|
166
170
|
const ignoreBefore = now - this._updateInterval.milliseconds * 2;
|
|
167
171
|
const shouldProject = !this._transportState.track.metadata?.liveStream;
|
|
168
172
|
this._positions.forEach((value, key) => {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { ILiveEvent } from "@microsoft/live-share";
|
|
7
7
|
import EventEmitter from "events";
|
|
8
8
|
import { IMediaPlayerState } from "../LiveMediaSessionCoordinator";
|
|
9
9
|
import {
|
|
@@ -31,7 +31,7 @@ export enum GroupPlaybackTrackEvents {
|
|
|
31
31
|
/**
|
|
32
32
|
* @hidden
|
|
33
33
|
*/
|
|
34
|
-
export interface IPlaybackTrackChangeEvent extends
|
|
34
|
+
export interface IPlaybackTrackChangeEvent extends ILiveEvent {
|
|
35
35
|
metadata: ExtendedMediaMetadata | null;
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { ILiveEvent } from "@microsoft/live-share";
|
|
7
7
|
import EventEmitter from "events";
|
|
8
8
|
import {
|
|
9
9
|
GroupPlaybackTrack,
|
|
@@ -29,7 +29,7 @@ export enum PlaybackTrackDataEvents {
|
|
|
29
29
|
/**
|
|
30
30
|
* @hidden
|
|
31
31
|
*/
|
|
32
|
-
export interface IPlaybackTrackDataChangeEvent extends
|
|
32
|
+
export interface IPlaybackTrackDataChangeEvent extends ILiveEvent {
|
|
33
33
|
data: object | null;
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ILiveEvent,
|
|
8
|
+
LiveShareRuntime,
|
|
9
|
+
LiveShareClient,
|
|
10
|
+
} from "@microsoft/live-share";
|
|
7
11
|
import EventEmitter from "events";
|
|
8
12
|
import { IMediaPlayerState } from "../LiveMediaSessionCoordinator";
|
|
9
13
|
import {
|
|
@@ -35,7 +39,7 @@ export enum GroupTransportStateEvents {
|
|
|
35
39
|
/**
|
|
36
40
|
* @hidden
|
|
37
41
|
*/
|
|
38
|
-
export interface ITransportStateChangeEvent extends
|
|
42
|
+
export interface ITransportStateChangeEvent extends ILiveEvent {
|
|
39
43
|
action: ExtendedMediaSessionAction;
|
|
40
44
|
seekTime?: number;
|
|
41
45
|
}
|
|
@@ -46,13 +50,16 @@ export interface ITransportStateChangeEvent extends IEvent {
|
|
|
46
50
|
export class GroupTransportState extends EventEmitter {
|
|
47
51
|
private readonly _getMediaPlayerState: () => IMediaPlayerState;
|
|
48
52
|
private _track: GroupPlaybackTrack;
|
|
53
|
+
private readonly _liveRuntime: LiveShareRuntime;
|
|
49
54
|
private _current: ITransportState;
|
|
50
55
|
|
|
51
56
|
constructor(
|
|
52
57
|
track: GroupPlaybackTrack,
|
|
53
|
-
getMediaPlayerState: () => IMediaPlayerState
|
|
58
|
+
getMediaPlayerState: () => IMediaPlayerState,
|
|
59
|
+
liveRuntime: LiveShareRuntime
|
|
54
60
|
) {
|
|
55
61
|
super();
|
|
62
|
+
this._liveRuntime = liveRuntime;
|
|
56
63
|
this._getMediaPlayerState = getMediaPlayerState;
|
|
57
64
|
this._track = track;
|
|
58
65
|
this._current = {
|
|
@@ -136,7 +143,7 @@ export class GroupTransportState extends EventEmitter {
|
|
|
136
143
|
seekTime: state.startPosition,
|
|
137
144
|
});
|
|
138
145
|
} else if (state.playbackState == "playing") {
|
|
139
|
-
const now =
|
|
146
|
+
const now = this._liveRuntime.getTimestamp();
|
|
140
147
|
const projectedPosition =
|
|
141
148
|
state.startPosition + (now - state.timestamp) / 1000;
|
|
142
149
|
this.emit(GroupTransportStateEvents.transportStateChange, {
|
package/src/internals/consts.ts
CHANGED
|
@@ -22,6 +22,8 @@ export const TelemetryEvents = {
|
|
|
22
22
|
UserTappedVideoToPlay: transmit(
|
|
23
23
|
"MediaPlayerSynchronizer:UserTappedVideoToPlay"
|
|
24
24
|
),
|
|
25
|
+
UserTappedVideoToPlayError:
|
|
26
|
+
"MediaPlayerSynchronizer:UserTappedVideoToPlayError",
|
|
25
27
|
PlaybackRateChangeBlocked:
|
|
26
28
|
"MediaPlayerSynchronizer:PlaybackRateChangeBlocked",
|
|
27
29
|
PlayerBlockedOperation: transmit(
|
|
@@ -72,6 +74,8 @@ export const TelemetryEvents = {
|
|
|
72
74
|
RemoteSeekToReceived: transmit(
|
|
73
75
|
"SessionCoordinator:RemoteSeekToReceived"
|
|
74
76
|
),
|
|
77
|
+
PositionUpdateEventError: "SessionCoordinator:PositionUpdateEventError",
|
|
78
|
+
SendJoinedEventError: "SessionCoordinator:SendJoinedEventError",
|
|
75
79
|
},
|
|
76
80
|
GroupCoordinator: {
|
|
77
81
|
TrackChanged: "GroupCoordinator:TrackChanged",
|
package/typedoc.json
ADDED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
import { DataObject, DataObjectFactory } from '@fluidframework/aqueduct';
|
|
6
|
-
import { EphemeralTelemetryLogger, UserMeetingRole } from '@microsoft/live-share';
|
|
7
|
-
import { MediaPlayerSynchronizer } from './MediaPlayerSynchronizer';
|
|
8
|
-
import { ExtendedMediaSessionAction } from './MediaSessionExtensions';
|
|
9
|
-
import { EphemeralMediaSessionCoordinator, IMediaPlayerState } from './EphemeralMediaSessionCoordinator';
|
|
10
|
-
import { MediaSessionActionThrottler } from './MediaSessionActionThrottler';
|
|
11
|
-
import { IMediaPlayer } from './IMediaPlayer';
|
|
12
|
-
/**
|
|
13
|
-
* Ephemeral fluid object that synchronizes media playback across multiple clients.
|
|
14
|
-
*/
|
|
15
|
-
export declare class EphemeralMediaSession extends DataObject {
|
|
16
|
-
private _actionThrottler;
|
|
17
|
-
private _logger?;
|
|
18
|
-
private _requestPlayerStateHandler?;
|
|
19
|
-
private _coordinator?;
|
|
20
|
-
private readonly _actionHandlers;
|
|
21
|
-
private _synchronizing?;
|
|
22
|
-
private _updateTimer;
|
|
23
|
-
private _lastUpdateTime;
|
|
24
|
-
/**
|
|
25
|
-
* The objects fluid type name.
|
|
26
|
-
*/
|
|
27
|
-
static readonly TypeName = "@microsoft/fluid-media:SharedMediaSession";
|
|
28
|
-
/**
|
|
29
|
-
* The objects fluid type factory.
|
|
30
|
-
*/
|
|
31
|
-
static readonly factory: DataObjectFactory<EphemeralMediaSession, import("@fluidframework/aqueduct").DataObjectTypes>;
|
|
32
|
-
/**
|
|
33
|
-
* Extension point that lets applications replace the default logic for throttling the sessions
|
|
34
|
-
* local sync behavior.
|
|
35
|
-
*
|
|
36
|
-
* @remarks
|
|
37
|
-
* The `EphemeralMediaCoordinator` is fairly aggressive at wanting to keep the local media player
|
|
38
|
-
* in sync with the rest of the group. This aggressiveness can result in the coordinator sending
|
|
39
|
-
* new sync actions before the local player has finished responding to the previous sync action.
|
|
40
|
-
* The `ActionThrottler` gives apps fine grain control over how aggressive they want sync to be.
|
|
41
|
-
*
|
|
42
|
-
* By default, a `RepeatedAction` throttler is used which prevents the same sync action from
|
|
43
|
-
* being sent within an adjustable time period.
|
|
44
|
-
*/
|
|
45
|
-
get actionThrottler(): MediaSessionActionThrottler;
|
|
46
|
-
set actionThrottler(value: MediaSessionActionThrottler);
|
|
47
|
-
/**
|
|
48
|
-
* Returns true if the object has been initialized.
|
|
49
|
-
*/
|
|
50
|
-
get isInitialized(): boolean;
|
|
51
|
-
/**
|
|
52
|
-
* @deprecated isInitialized should be used instead
|
|
53
|
-
* Returns true if the object has been initialized.
|
|
54
|
-
*/
|
|
55
|
-
get isStarted(): boolean;
|
|
56
|
-
/**
|
|
57
|
-
* The group coordinator for the session.
|
|
58
|
-
*/
|
|
59
|
-
get coordinator(): EphemeralMediaSessionCoordinator;
|
|
60
|
-
/**
|
|
61
|
-
* Returns the logger used by the session and coordinator.
|
|
62
|
-
*
|
|
63
|
-
* @remarks
|
|
64
|
-
* This is used by the `MediaPlayerSynchronizer` to log events.
|
|
65
|
-
*/
|
|
66
|
-
get logger(): EphemeralTelemetryLogger;
|
|
67
|
-
/**
|
|
68
|
-
* initialize the object.
|
|
69
|
-
* @param acceptTransportChangesFrom Optional. List of roles allowed to group transport
|
|
70
|
-
* operations like play/pause/seek/setTrack.
|
|
71
|
-
*/
|
|
72
|
-
initialize(acceptTransportChangesFrom?: UserMeetingRole[]): Promise<void>;
|
|
73
|
-
/**
|
|
74
|
-
* @deprecated initialize should be used instead
|
|
75
|
-
* initialize the object.
|
|
76
|
-
* @param acceptTransportChangesFrom Optional. List of roles allowed to group transport
|
|
77
|
-
* operations like play/pause/seek/setTrack.
|
|
78
|
-
*/
|
|
79
|
-
start(acceptTransportChangesFrom?: UserMeetingRole[]): Promise<void>;
|
|
80
|
-
/**
|
|
81
|
-
* Registers an action handler with the session.
|
|
82
|
-
* @param action Name of the action to register a handler for.
|
|
83
|
-
* @param handler Function called when the action is triggered.
|
|
84
|
-
*/
|
|
85
|
-
setActionHandler(action: ExtendedMediaSessionAction, handler: MediaSessionActionHandler | null): void;
|
|
86
|
-
/**
|
|
87
|
-
* Registers a handler that will be queried anytime the group coordinate needs to know the
|
|
88
|
-
* local players transport state and position.
|
|
89
|
-
*/
|
|
90
|
-
setRequestPlayerStateHandler(handler: () => IMediaPlayerState): void;
|
|
91
|
-
/**
|
|
92
|
-
* Begins synchronizing the playback of a media element.
|
|
93
|
-
* @param player Something that "looks like" and HTML Media Element.
|
|
94
|
-
* @returns A new synchronizer instance. Call `synchronizer.end()` to stop synchronizing the elements playback.
|
|
95
|
-
*/
|
|
96
|
-
synchronize(player: IMediaPlayer): MediaPlayerSynchronizer;
|
|
97
|
-
protected hasInitialized(): Promise<void>;
|
|
98
|
-
private checkWaitPointHit;
|
|
99
|
-
private getCurrentPlayerState;
|
|
100
|
-
private dispatchAction;
|
|
101
|
-
}
|
|
102
|
-
//# sourceMappingURL=EphemeralMediaSession.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EphemeralMediaSession.d.ts","sourceRoot":"","sources":["../src/EphemeralMediaSession.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,OAAO,EAAiC,0BAA0B,EAAqC,MAAM,0BAA0B,CAAC;AACxI,OAAO,EAAE,gCAAgC,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACzG,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;GAEG;AACF,qBAAa,qBAAsB,SAAQ,UAAU;IAClD,OAAO,CAAC,gBAAgB,CAA8D;IACtF,OAAO,CAAC,OAAO,CAAC,CAA2B;IAC3C,OAAO,CAAC,0BAA0B,CAAC,CAA0B;IAC7D,OAAO,CAAC,YAAY,CAAC,CAAmC;IACxD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqD;IACrF,OAAO,CAAC,cAAc,CAAC,CAA0B;IAGjD,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,eAAe,CAAa;IAEpC;;OAEG;IACF,gBAAuB,QAAQ,+CAA+C;IAE/E;;OAEG;IACF,gBAAuB,OAAO,+FAK7B;IAEF;;;;;;;;;;;;OAYG;IACH,IAAW,eAAe,IAAI,2BAA2B,CAExD;IAED,IAAW,eAAe,CAAC,KAAK,EAAE,2BAA2B,EAE5D;IAED;;OAEG;IACH,IAAW,aAAa,IAAI,OAAO,CAElC;IAED;;;OAGG;IACH,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED;;OAEG;IACH,IAAW,WAAW,IAAI,gCAAgC,CAEzD;IAED;;;;;OAKG;IACH,IAAW,MAAM,IAAI,wBAAwB,CAE5C;IAED;;;;OAIG;IACK,UAAU,CAAC,0BAA0B,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjF;;;;;OAKG;IACI,KAAK,CAAC,0BAA0B,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E;;;;OAIG;IACI,gBAAgB,CAAC,MAAM,EAAE,0BAA0B,EAAE,OAAO,EAAE,yBAAyB,GAAG,IAAI,GAAG,IAAI;IAW5G;;;OAGG;IACI,4BAA4B,CAAC,OAAO,EAAE,MAAM,iBAAiB;IAIpE;;;;OAIG;IACI,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,uBAAuB;cA+BjD,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAuC/C,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,cAAc;CAMzB"}
|