@microsoft/live-share-media 2.0.0-internal.7 → 2.0.0-internal.9
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/cjs/LiveMediaSession.d.ts +2 -2
- package/bin/cjs/LiveMediaSession.d.ts.map +1 -1
- package/bin/cjs/LiveMediaSession.js +6 -6
- package/bin/cjs/LiveMediaSession.js.map +1 -1
- package/bin/cjs/LiveMediaSessionCoordinator.d.ts +38 -7
- package/bin/cjs/LiveMediaSessionCoordinator.d.ts.map +1 -1
- package/bin/cjs/LiveMediaSessionCoordinator.js +90 -9
- package/bin/cjs/LiveMediaSessionCoordinator.js.map +1 -1
- package/bin/cjs/internals/GroupCoordinatorState.d.ts +2 -1
- package/bin/cjs/internals/GroupCoordinatorState.d.ts.map +1 -1
- package/bin/cjs/internals/GroupCoordinatorState.js.map +1 -1
- package/bin/cjs/internals/GroupPlaybackPosition.d.ts +2 -2
- package/bin/cjs/internals/GroupPlaybackPosition.d.ts.map +1 -1
- package/bin/cjs/internals/GroupPlaybackPosition.js +1 -1
- package/bin/cjs/internals/GroupPlaybackPosition.js.map +1 -1
- package/bin/esm/LiveMediaSession.d.ts +2 -2
- package/bin/esm/LiveMediaSession.d.ts.map +1 -1
- package/bin/esm/LiveMediaSession.js +2 -2
- package/bin/esm/LiveMediaSession.js.map +1 -1
- package/bin/esm/LiveMediaSessionCoordinator.d.ts +38 -7
- package/bin/esm/LiveMediaSessionCoordinator.d.ts.map +1 -1
- package/bin/esm/LiveMediaSessionCoordinator.js +91 -10
- package/bin/esm/LiveMediaSessionCoordinator.js.map +1 -1
- package/bin/esm/internals/GroupCoordinatorState.d.ts +2 -1
- package/bin/esm/internals/GroupCoordinatorState.d.ts.map +1 -1
- package/bin/esm/internals/GroupCoordinatorState.js.map +1 -1
- package/bin/esm/internals/GroupPlaybackPosition.d.ts +2 -2
- package/bin/esm/internals/GroupPlaybackPosition.d.ts.map +1 -1
- package/bin/esm/internals/GroupPlaybackPosition.js +1 -1
- package/bin/esm/internals/GroupPlaybackPosition.js.map +1 -1
- package/package.json +3 -3
- package/src/LiveMediaSession.ts +2 -5
- package/src/LiveMediaSessionCoordinator.ts +96 -10
- package/src/internals/GroupCoordinatorState.ts +2 -1
- package/src/internals/GroupPlaybackPosition.ts +4 -4
- package/src/internals/PriorityTimeInterval.ts +76 -0
- package/.mocharc.cjs +0 -12
- package/.nycrc.json +0 -11
- package/bin/test/IMediaPlayer.d.ts +0 -21
- package/bin/test/IMediaPlayer.d.ts.map +0 -1
- package/bin/test/IMediaPlayer.js +0 -7
- package/bin/test/IMediaPlayer.js.map +0 -1
- package/bin/test/LiveMediaSession.d.ts +0 -97
- package/bin/test/LiveMediaSession.d.ts.map +0 -1
- package/bin/test/LiveMediaSession.js +0 -261
- package/bin/test/LiveMediaSession.js.map +0 -1
- package/bin/test/LiveMediaSessionCoordinator.d.ts +0 -296
- package/bin/test/LiveMediaSessionCoordinator.d.ts.map +0 -1
- package/bin/test/LiveMediaSessionCoordinator.js +0 -552
- package/bin/test/LiveMediaSessionCoordinator.js.map +0 -1
- package/bin/test/LiveMediaSessionCoordinatorSuspension.d.ts +0 -20
- package/bin/test/LiveMediaSessionCoordinatorSuspension.d.ts.map +0 -1
- package/bin/test/LiveMediaSessionCoordinatorSuspension.js +0 -28
- package/bin/test/LiveMediaSessionCoordinatorSuspension.js.map +0 -1
- package/bin/test/MediaPlayerSynchronizer.d.ts +0 -204
- package/bin/test/MediaPlayerSynchronizer.d.ts.map +0 -1
- package/bin/test/MediaPlayerSynchronizer.js +0 -574
- package/bin/test/MediaPlayerSynchronizer.js.map +0 -1
- package/bin/test/MediaSessionActionThrottler.d.ts +0 -12
- package/bin/test/MediaSessionActionThrottler.d.ts.map +0 -1
- package/bin/test/MediaSessionActionThrottler.js +0 -14
- package/bin/test/MediaSessionActionThrottler.js.map +0 -1
- package/bin/test/MediaSessionExtensions.d.ts +0 -177
- package/bin/test/MediaSessionExtensions.d.ts.map +0 -1
- package/bin/test/MediaSessionExtensions.js +0 -26
- package/bin/test/MediaSessionExtensions.js.map +0 -1
- package/bin/test/RepeatedActionThrottler.d.ts +0 -20
- package/bin/test/RepeatedActionThrottler.d.ts.map +0 -1
- package/bin/test/RepeatedActionThrottler.js +0 -63
- package/bin/test/RepeatedActionThrottler.js.map +0 -1
- package/bin/test/VolumeManager.d.ts +0 -84
- package/bin/test/VolumeManager.d.ts.map +0 -1
- package/bin/test/VolumeManager.js +0 -175
- package/bin/test/VolumeManager.js.map +0 -1
- package/bin/test/index.d.ts +0 -14
- package/bin/test/index.d.ts.map +0 -1
- package/bin/test/index.js +0 -30
- package/bin/test/index.js.map +0 -1
- package/bin/test/internals/GroupCoordinatorState.d.ts +0 -110
- package/bin/test/internals/GroupCoordinatorState.d.ts.map +0 -1
- package/bin/test/internals/GroupCoordinatorState.js +0 -516
- package/bin/test/internals/GroupCoordinatorState.js.map +0 -1
- package/bin/test/internals/GroupPlaybackPosition.d.ts +0 -71
- package/bin/test/internals/GroupPlaybackPosition.d.ts.map +0 -1
- package/bin/test/internals/GroupPlaybackPosition.js +0 -170
- package/bin/test/internals/GroupPlaybackPosition.js.map +0 -1
- package/bin/test/internals/GroupPlaybackRate.d.ts +0 -38
- package/bin/test/internals/GroupPlaybackRate.d.ts.map +0 -1
- package/bin/test/internals/GroupPlaybackRate.js +0 -59
- package/bin/test/internals/GroupPlaybackRate.js.map +0 -1
- package/bin/test/internals/GroupPlaybackTrack.d.ts +0 -45
- package/bin/test/internals/GroupPlaybackTrack.d.ts.map +0 -1
- package/bin/test/internals/GroupPlaybackTrack.js +0 -122
- package/bin/test/internals/GroupPlaybackTrack.js.map +0 -1
- package/bin/test/internals/GroupPlaybackTrackData.d.ts +0 -40
- package/bin/test/internals/GroupPlaybackTrackData.d.ts.map +0 -1
- package/bin/test/internals/GroupPlaybackTrackData.js +0 -70
- package/bin/test/internals/GroupPlaybackTrackData.js.map +0 -1
- package/bin/test/internals/GroupTransportState.d.ts +0 -52
- package/bin/test/internals/GroupTransportState.d.ts.map +0 -1
- package/bin/test/internals/GroupTransportState.js +0 -120
- package/bin/test/internals/GroupTransportState.js.map +0 -1
- package/bin/test/internals/PriorityTimeInterval.d.ts +0 -33
- package/bin/test/internals/PriorityTimeInterval.d.ts.map +0 -1
- package/bin/test/internals/PriorityTimeInterval.js +0 -45
- package/bin/test/internals/PriorityTimeInterval.js.map +0 -1
- package/bin/test/internals/consts.d.ts +0 -83
- package/bin/test/internals/consts.d.ts.map +0 -1
- package/bin/test/internals/consts.js +0 -92
- package/bin/test/internals/consts.js.map +0 -1
- package/bin/test/internals/errors.d.ts +0 -17
- package/bin/test/internals/errors.d.ts.map +0 -1
- package/bin/test/internals/errors.js +0 -34
- package/bin/test/internals/errors.js.map +0 -1
- package/bin/test/internals/interfaces.d.ts +0 -23
- package/bin/test/internals/interfaces.d.ts.map +0 -1
- package/bin/test/internals/interfaces.js +0 -3
- package/bin/test/internals/interfaces.js.map +0 -1
- package/bin/test/package.json +0 -1
- package/bin/test/test/GroupPlaybackPosition.spec.d.ts +0 -6
- package/bin/test/test/GroupPlaybackPosition.spec.d.ts.map +0 -1
- package/bin/test/test/GroupPlaybackPosition.spec.js +0 -315
- package/bin/test/test/GroupPlaybackPosition.spec.js.map +0 -1
- package/bin/test/test/GroupPlaybackRate.spec.d.ts +0 -6
- package/bin/test/test/GroupPlaybackRate.spec.d.ts.map +0 -1
- package/bin/test/test/GroupPlaybackRate.spec.js +0 -47
- package/bin/test/test/GroupPlaybackRate.spec.js.map +0 -1
- package/bin/test/test/GroupPlaybackTrack.spec.d.ts +0 -6
- package/bin/test/test/GroupPlaybackTrack.spec.d.ts.map +0 -1
- package/bin/test/test/GroupPlaybackTrack.spec.js +0 -171
- package/bin/test/test/GroupPlaybackTrack.spec.js.map +0 -1
- package/bin/test/test/GroupPlaybackTrackData.spec.d.ts +0 -6
- package/bin/test/test/GroupPlaybackTrackData.spec.d.ts.map +0 -1
- package/bin/test/test/GroupPlaybackTrackData.spec.js +0 -63
- package/bin/test/test/GroupPlaybackTrackData.spec.js.map +0 -1
- package/bin/test/test/LiveMediaSession_ManualActionHandler.spec.d.ts +0 -6
- package/bin/test/test/LiveMediaSession_ManualActionHandler.spec.d.ts.map +0 -1
- package/bin/test/test/LiveMediaSession_ManualActionHandler.spec.js +0 -324
- package/bin/test/test/LiveMediaSession_ManualActionHandler.spec.js.map +0 -1
- package/bin/test/test/LiveMediaSession_Synchronizer.spec.d.ts +0 -6
- package/bin/test/test/LiveMediaSession_Synchronizer.spec.d.ts.map +0 -1
- package/bin/test/test/LiveMediaSession_Synchronizer.spec.js +0 -669
- package/bin/test/test/LiveMediaSession_Synchronizer.spec.js.map +0 -1
- package/bin/test/test/PriorityTimeInterval.spec.d.ts +0 -6
- package/bin/test/test/PriorityTimeInterval.spec.d.ts.map +0 -1
- package/bin/test/test/PriorityTimeInterval.spec.js +0 -67
- package/bin/test/test/PriorityTimeInterval.spec.js.map +0 -1
- package/bin/test/test/TestUtils.d.ts +0 -44
- package/bin/test/test/TestUtils.d.ts.map +0 -1
- package/bin/test/test/TestUtils.js +0 -116
- package/bin/test/test/TestUtils.js.map +0 -1
- package/bin/test/test/VolumeManager.spec.d.ts +0 -2
- package/bin/test/test/VolumeManager.spec.d.ts.map +0 -1
- package/bin/test/test/VolumeManager.spec.js +0 -163
- package/bin/test/test/VolumeManager.spec.js.map +0 -1
- package/nyc/junit-report.json +0 -930
- package/nyc/junit-report.xml +0 -59
- package/tsconfig.test.json +0 -9
- package/typedoc.json +0 -10
package/src/LiveMediaSession.ts
CHANGED
|
@@ -3,10 +3,7 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
DataObjectFactory,
|
|
8
|
-
createDataObjectKind,
|
|
9
|
-
} from "@fluidframework/aqueduct/internal";
|
|
6
|
+
import { DataObjectFactory } from "@fluidframework/aqueduct/legacy";
|
|
10
7
|
import {
|
|
11
8
|
LiveDataObjectInitializeNotNeededError,
|
|
12
9
|
LiveDataObjectInitializeState,
|
|
@@ -354,7 +351,7 @@ export type LiveMediaSession = LiveMediaSessionClass;
|
|
|
354
351
|
|
|
355
352
|
// eslint-disable-next-line no-redeclare
|
|
356
353
|
export const LiveMediaSession = (() => {
|
|
357
|
-
const kind =
|
|
354
|
+
const kind = LiveMediaSessionClass;
|
|
358
355
|
return kind as typeof kind & SharedObjectKind<LiveMediaSessionClass>;
|
|
359
356
|
})();
|
|
360
357
|
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
TrackMetadataNotSetError,
|
|
41
41
|
ActionBlockedError,
|
|
42
42
|
} from "./internals/errors.js";
|
|
43
|
-
|
|
43
|
+
import { PriorityTimeInterval } from "./internals/PriorityTimeInterval.js";
|
|
44
44
|
import { LiveMediaSessionCoordinatorSuspension } from "./LiveMediaSessionCoordinatorSuspension.js";
|
|
45
45
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
46
46
|
import { IEvent } from "@fluidframework/core-interfaces";
|
|
@@ -97,8 +97,27 @@ export class LiveMediaSessionCoordinator extends TypedEventEmitter<ILiveMediaSes
|
|
|
97
97
|
private readonly _liveRuntime: LiveShareRuntime;
|
|
98
98
|
private readonly _logger: LiveTelemetryLogger;
|
|
99
99
|
private readonly _getPlayerState: () => IMediaPlayerState;
|
|
100
|
-
private _positionUpdateInterval = new
|
|
101
|
-
|
|
100
|
+
private _positionUpdateInterval = new PriorityTimeInterval(
|
|
101
|
+
2000,
|
|
102
|
+
// Scale by function
|
|
103
|
+
() => {
|
|
104
|
+
const audience = this._liveRuntime.audience;
|
|
105
|
+
if (!audience) return 1;
|
|
106
|
+
// As the audience size gets bigger, we relax the update interval, since more variance is expected
|
|
107
|
+
const count = audience.getMembers().size;
|
|
108
|
+
return 1 + count / 5;
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
private _maxPlaybackDrift = new PriorityTimeInterval(
|
|
112
|
+
1500, // Scale by function
|
|
113
|
+
() => {
|
|
114
|
+
const audience = this._liveRuntime.audience;
|
|
115
|
+
if (!audience) return 1;
|
|
116
|
+
// As the audience size gets bigger, we relax the playback drift, since more variance is expected
|
|
117
|
+
const count = audience.getMembers().size;
|
|
118
|
+
return 1 + count / 25;
|
|
119
|
+
}
|
|
120
|
+
);
|
|
102
121
|
private _lastWaitPoint?: CoordinationWaitPoint;
|
|
103
122
|
private initializeState: LiveDataObjectInitializeState =
|
|
104
123
|
LiveDataObjectInitializeState.needed;
|
|
@@ -222,13 +241,29 @@ export class LiveMediaSessionCoordinator extends TypedEventEmitter<ILiveMediaSes
|
|
|
222
241
|
}
|
|
223
242
|
|
|
224
243
|
/**
|
|
225
|
-
*
|
|
244
|
+
* Controls whether or not to scale {@link maxPlaybackDrift} by the number of users in the session.
|
|
226
245
|
*
|
|
227
246
|
* @remarks
|
|
228
|
-
*
|
|
229
|
-
*
|
|
247
|
+
* As more clients join a session, it is more likely that some users will fall behind the presenter.
|
|
248
|
+
* It is also less likely that users will notice drift as more clients are added.
|
|
249
|
+
* It is usually helpful to be more lenient as more clients are added so everyone can watch all the content.
|
|
250
|
+
* Default value is true.
|
|
251
|
+
*/
|
|
252
|
+
public get shouldScaleMaxPlaybackDrift(): boolean {
|
|
253
|
+
return this._maxPlaybackDrift.shouldPrioritize;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
public set shouldScaleMaxPlaybackDrift(value: boolean) {
|
|
257
|
+
this._maxPlaybackDrift.shouldPrioritize = value;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Max amount of playback drift allowed in seconds.
|
|
262
|
+
* This will scale automatically according to the number of participants in the session when {@link shouldScaleMaxPlaybackDrift} is true.
|
|
230
263
|
*
|
|
231
|
-
*
|
|
264
|
+
* @remarks
|
|
265
|
+
* Should the local clients playback position lag by more than the specified value, the coordinator will trigger a `catchup` action.
|
|
266
|
+
* Default value is `1.5` seconds.
|
|
232
267
|
*/
|
|
233
268
|
public get maxPlaybackDrift(): number {
|
|
234
269
|
return this._maxPlaybackDrift.seconds;
|
|
@@ -239,11 +274,30 @@ export class LiveMediaSessionCoordinator extends TypedEventEmitter<ILiveMediaSes
|
|
|
239
274
|
}
|
|
240
275
|
|
|
241
276
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
277
|
+
* Controls whether or not to compute {@link positionUpdateInterval} based on whether user has initiated a playback command.
|
|
278
|
+
* Default value is true.
|
|
244
279
|
*
|
|
245
280
|
* @remarks
|
|
246
|
-
*
|
|
281
|
+
* When true, users that are simply watching but not controlling playback will report their positions less frequently.
|
|
282
|
+
* When a user has sent a transport command, they will begin sending position updates more frequently.
|
|
283
|
+
* Most Live Share apps have a concept of a primary presenter, and don't allow anyone to pause/play for the group.
|
|
284
|
+
* By ensuring only one/few users broadcast updates frequently, the server load is reduced considerably.
|
|
285
|
+
*/
|
|
286
|
+
public get shouldScalePositionUpdateInterval(): boolean {
|
|
287
|
+
return this._positionUpdateInterval.shouldPrioritize;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
public set shouldScalePositionUpdateInterval(value: boolean) {
|
|
291
|
+
this._positionUpdateInterval.shouldPrioritize = value;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Frequency with which position updates are broadcast to the rest of the group in seconds.
|
|
296
|
+
* When {@link shouldScalePositionUpdateInterval} is set to `true`, the value set is the minimum value.
|
|
297
|
+
* The value returned is the actual value used to send updates by the local user, which may be larger than the value set.
|
|
298
|
+
*
|
|
299
|
+
* @remarks
|
|
300
|
+
* Defaults to a minimum value of `2` seconds.
|
|
247
301
|
*/
|
|
248
302
|
public get positionUpdateInterval(): number {
|
|
249
303
|
return this._positionUpdateInterval.seconds;
|
|
@@ -293,6 +347,10 @@ export class LiveMediaSessionCoordinator extends TypedEventEmitter<ILiveMediaSes
|
|
|
293
347
|
track: this._groupState.playbackTrack.current,
|
|
294
348
|
position: position,
|
|
295
349
|
});
|
|
350
|
+
if (this.canSendPositionUpdates) {
|
|
351
|
+
// User has taken initiative to send event, give priority for sending position updates
|
|
352
|
+
this._positionUpdateInterval.hasPriority = true;
|
|
353
|
+
}
|
|
296
354
|
}
|
|
297
355
|
|
|
298
356
|
/**
|
|
@@ -335,6 +393,10 @@ export class LiveMediaSessionCoordinator extends TypedEventEmitter<ILiveMediaSes
|
|
|
335
393
|
track: this._groupState.playbackTrack.current,
|
|
336
394
|
position: position,
|
|
337
395
|
});
|
|
396
|
+
if (this.canSendPositionUpdates) {
|
|
397
|
+
// User has taken initiative to send event, give priority for sending position updates
|
|
398
|
+
this._positionUpdateInterval.hasPriority = true;
|
|
399
|
+
}
|
|
338
400
|
}
|
|
339
401
|
|
|
340
402
|
/**
|
|
@@ -375,12 +437,24 @@ export class LiveMediaSessionCoordinator extends TypedEventEmitter<ILiveMediaSes
|
|
|
375
437
|
track: this._groupState.playbackTrack.current,
|
|
376
438
|
position: time,
|
|
377
439
|
});
|
|
440
|
+
if (this.canSendPositionUpdates) {
|
|
441
|
+
// User has taken initiative to send event, give priority for sending position updates
|
|
442
|
+
this._positionUpdateInterval.hasPriority = true;
|
|
443
|
+
}
|
|
378
444
|
} catch (err) {
|
|
379
445
|
await this._groupState!.syncLocalMediaSession();
|
|
380
446
|
throw err;
|
|
381
447
|
}
|
|
382
448
|
}
|
|
383
449
|
|
|
450
|
+
/**
|
|
451
|
+
* Sets the playback rate for everyone in the session.
|
|
452
|
+
*
|
|
453
|
+
* @param playbackRate the playback rate to set.
|
|
454
|
+
*
|
|
455
|
+
* @throws
|
|
456
|
+
* Throws an exception if the session/coordinator hasn't been initialized or {@link canSetPlaybackRate} is false.
|
|
457
|
+
*/
|
|
384
458
|
public async setPlaybackRate(playbackRate: number): Promise<void> {
|
|
385
459
|
LiveDataObjectNotInitializedError.assert(
|
|
386
460
|
"LiveMediaSessionCoordinator:setPlaybackRate",
|
|
@@ -400,6 +474,10 @@ export class LiveMediaSessionCoordinator extends TypedEventEmitter<ILiveMediaSes
|
|
|
400
474
|
{ playbackRate }
|
|
401
475
|
);
|
|
402
476
|
await this._rateChangeEvent!.sendEvent({ playbackRate });
|
|
477
|
+
if (this.canSendPositionUpdates) {
|
|
478
|
+
// User has taken initiative to send event, give priority for sending position updates
|
|
479
|
+
this._positionUpdateInterval.hasPriority = true;
|
|
480
|
+
}
|
|
403
481
|
}
|
|
404
482
|
|
|
405
483
|
/**
|
|
@@ -436,6 +514,10 @@ export class LiveMediaSessionCoordinator extends TypedEventEmitter<ILiveMediaSes
|
|
|
436
514
|
metadata: metadata,
|
|
437
515
|
waitPoints: waitPoints || [],
|
|
438
516
|
});
|
|
517
|
+
if (this.canSendPositionUpdates) {
|
|
518
|
+
// User has taken initiative to send event, give priority for sending position updates
|
|
519
|
+
this._positionUpdateInterval.hasPriority = true;
|
|
520
|
+
}
|
|
439
521
|
}
|
|
440
522
|
|
|
441
523
|
/**
|
|
@@ -470,6 +552,10 @@ export class LiveMediaSessionCoordinator extends TypedEventEmitter<ILiveMediaSes
|
|
|
470
552
|
await this._setTrackDataEvent!.sendEvent({
|
|
471
553
|
data: data,
|
|
472
554
|
});
|
|
555
|
+
if (this.canSendPositionUpdates) {
|
|
556
|
+
// User has taken initiative to send event, give priority for sending position updates
|
|
557
|
+
this._positionUpdateInterval.hasPriority = true;
|
|
558
|
+
}
|
|
473
559
|
}
|
|
474
560
|
|
|
475
561
|
/**
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
} from "./GroupPlaybackRate.js";
|
|
54
54
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
55
55
|
import { IGenericTypedEvents } from "./interfaces.js";
|
|
56
|
+
import { PriorityTimeInterval } from "./PriorityTimeInterval.js";
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
59
|
* @hidden
|
|
@@ -145,7 +146,7 @@ export class GroupCoordinatorState extends TypedEventEmitter<IGenericTypedEvents
|
|
|
145
146
|
runtime: IRuntimeSignaler,
|
|
146
147
|
liveRuntime: LiveShareRuntime,
|
|
147
148
|
maxPlaybackDrift: TimeInterval,
|
|
148
|
-
positionUpdateInterval:
|
|
149
|
+
positionUpdateInterval: PriorityTimeInterval,
|
|
149
150
|
getMediaPlayerState: () => IMediaPlayerState
|
|
150
151
|
) {
|
|
151
152
|
super();
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { TimeInterval } from "@microsoft/live-share";
|
|
7
6
|
import {
|
|
8
7
|
IRuntimeSignaler,
|
|
9
8
|
LiveShareRuntime,
|
|
@@ -15,6 +14,7 @@ import {
|
|
|
15
14
|
ExtendedMediaSessionPlaybackState,
|
|
16
15
|
} from "../MediaSessionExtensions.js";
|
|
17
16
|
import { GroupPlaybackRate } from "./GroupPlaybackRate.js";
|
|
17
|
+
import { PriorityTimeInterval } from "./PriorityTimeInterval.js";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Per client position
|
|
@@ -37,7 +37,7 @@ export class GroupPlaybackPosition {
|
|
|
37
37
|
private _playbackRate: GroupPlaybackRate;
|
|
38
38
|
private _runtime: IRuntimeSignaler;
|
|
39
39
|
private _liveRuntime: LiveShareRuntime;
|
|
40
|
-
private _updateInterval:
|
|
40
|
+
private _updateInterval: PriorityTimeInterval;
|
|
41
41
|
private _positions: Map<string, ICurrentPlaybackPosition>;
|
|
42
42
|
|
|
43
43
|
constructor(
|
|
@@ -45,7 +45,7 @@ export class GroupPlaybackPosition {
|
|
|
45
45
|
playbackRate: GroupPlaybackRate,
|
|
46
46
|
runtime: IRuntimeSignaler,
|
|
47
47
|
liveRuntime: LiveShareRuntime,
|
|
48
|
-
updateInterval:
|
|
48
|
+
updateInterval: PriorityTimeInterval
|
|
49
49
|
) {
|
|
50
50
|
this._transportState = transportState;
|
|
51
51
|
this._playbackRate = playbackRate;
|
|
@@ -171,7 +171,7 @@ export class GroupPlaybackPosition {
|
|
|
171
171
|
) => void
|
|
172
172
|
): void {
|
|
173
173
|
const now = this._liveRuntime.getTimestamp();
|
|
174
|
-
const ignoreBefore = now - this._updateInterval.
|
|
174
|
+
const ignoreBefore = now - this._updateInterval.maxMilliseconds * 2;
|
|
175
175
|
const shouldProject = !this._transportState.track.metadata?.liveStream;
|
|
176
176
|
this._positions.forEach((position, _) => {
|
|
177
177
|
// Ignore any old updates
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { TimeInterval } from "@microsoft/live-share";
|
|
2
|
+
|
|
3
|
+
function getScaledPriorityTimeMs(
|
|
4
|
+
minMilliseconds: number,
|
|
5
|
+
hasPriority: boolean,
|
|
6
|
+
shouldPrioritize: boolean,
|
|
7
|
+
scaleBy: number
|
|
8
|
+
): number {
|
|
9
|
+
if (!shouldPrioritize) return minMilliseconds;
|
|
10
|
+
if (hasPriority) return minMilliseconds;
|
|
11
|
+
return minMilliseconds * scaleBy;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @hidden
|
|
16
|
+
* Time interval that can scale based on a scaling function.
|
|
17
|
+
*/
|
|
18
|
+
export class PriorityTimeInterval extends TimeInterval {
|
|
19
|
+
/**
|
|
20
|
+
* If true, local user has priority and will have the lowest possible millesecond value.
|
|
21
|
+
*/
|
|
22
|
+
public hasPriority: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* If true, milliseconds will be scaled when {@link hasPriority} is false.
|
|
25
|
+
*/
|
|
26
|
+
public shouldPrioritize: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Function to get the scale ratio.
|
|
29
|
+
*/
|
|
30
|
+
private getScaleBy: () => number;
|
|
31
|
+
/**
|
|
32
|
+
* Time interval that can scale based on a scaling function.
|
|
33
|
+
*
|
|
34
|
+
* @param defaultMilliseconds the default minimum milliseconds
|
|
35
|
+
* @param getScaleByFn a function to scale the milliseconds by when {@link hasPriority} is false and {@link shouldPrioritize} is true.
|
|
36
|
+
* @param defaultHasPriority the default {@link hasPriority} value
|
|
37
|
+
* @param defaultShouldPrioritize the default {@link shouldPrioritize} value
|
|
38
|
+
*/
|
|
39
|
+
constructor(
|
|
40
|
+
defaultMilliseconds: number,
|
|
41
|
+
getScaleByFn: () => number,
|
|
42
|
+
defaultHasPriority: boolean = false,
|
|
43
|
+
defaultShouldPrioritize: boolean = true
|
|
44
|
+
) {
|
|
45
|
+
super(defaultMilliseconds);
|
|
46
|
+
this.hasPriority = defaultHasPriority;
|
|
47
|
+
this.shouldPrioritize = defaultShouldPrioritize;
|
|
48
|
+
this.getScaleBy = getScaleByFn;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public get milliseconds(): number {
|
|
52
|
+
return getScaledPriorityTimeMs(
|
|
53
|
+
this._milliseconds,
|
|
54
|
+
this.hasPriority,
|
|
55
|
+
this.shouldPrioritize,
|
|
56
|
+
this.getScaleBy()
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public set milliseconds(value: number) {
|
|
61
|
+
this._milliseconds = value;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public get minMilliseconds(): number {
|
|
65
|
+
return this._milliseconds;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public get maxMilliseconds(): number {
|
|
69
|
+
return getScaledPriorityTimeMs(
|
|
70
|
+
this._milliseconds,
|
|
71
|
+
false,
|
|
72
|
+
this.shouldPrioritize,
|
|
73
|
+
this.getScaleBy()
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
package/.mocharc.cjs
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
"use strict";
|
|
7
|
-
|
|
8
|
-
const packageDir = `${__dirname}/../..`;
|
|
9
|
-
|
|
10
|
-
const getFluidTestMochaConfig = require("@fluidframework/mocha-test-setup/mocharc-common.js");
|
|
11
|
-
const config = getFluidTestMochaConfig(packageDir);
|
|
12
|
-
module.exports = config;
|
package/.nycrc.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
export interface IMediaPlayer {
|
|
6
|
-
readonly currentSrc: string;
|
|
7
|
-
currentTime: number;
|
|
8
|
-
readonly duration: number;
|
|
9
|
-
readonly ended: boolean;
|
|
10
|
-
muted: boolean;
|
|
11
|
-
readonly paused: boolean;
|
|
12
|
-
playbackRate: number;
|
|
13
|
-
src: string;
|
|
14
|
-
volume: number;
|
|
15
|
-
load(): void;
|
|
16
|
-
pause(): void;
|
|
17
|
-
play(): Promise<void>;
|
|
18
|
-
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
|
19
|
-
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=IMediaPlayer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IMediaPlayer.d.ts","sourceRoot":"","sources":["../../src/IMediaPlayer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,IAAI,IAAI,CAAC;IACb,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,gBAAgB,CACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC5C,IAAI,CAAC;IACR,mBAAmB,CACf,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACzC,IAAI,CAAC;CACX"}
|
package/bin/test/IMediaPlayer.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IMediaPlayer.js","sourceRoot":"","sources":["../../src/IMediaPlayer.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
import { DataObjectFactory } from "@fluidframework/aqueduct/internal";
|
|
6
|
-
import { LiveTelemetryLogger, UserMeetingRole } from "@microsoft/live-share";
|
|
7
|
-
import { LiveDataObject } from "@microsoft/live-share/internal";
|
|
8
|
-
import { MediaPlayerSynchronizer } from "./MediaPlayerSynchronizer.js";
|
|
9
|
-
import { ExtendedMediaSessionAction, ExtendedMediaSessionActionHandler } from "./MediaSessionExtensions.js";
|
|
10
|
-
import { LiveMediaSessionCoordinator, IMediaPlayerState } from "./LiveMediaSessionCoordinator.js";
|
|
11
|
-
import { MediaSessionActionThrottler } from "./MediaSessionActionThrottler.js";
|
|
12
|
-
import { IMediaPlayer } from "./IMediaPlayer.js";
|
|
13
|
-
import { SharedObjectKind } from "fluid-framework";
|
|
14
|
-
/**
|
|
15
|
-
* Live fluid object that synchronizes media playback across multiple clients.
|
|
16
|
-
*/
|
|
17
|
-
export declare class LiveMediaSessionClass extends LiveDataObject {
|
|
18
|
-
private _actionThrottler;
|
|
19
|
-
private _logger?;
|
|
20
|
-
private _requestPlayerStateHandler?;
|
|
21
|
-
private _coordinator?;
|
|
22
|
-
private readonly _actionHandlers;
|
|
23
|
-
private _synchronizing?;
|
|
24
|
-
private _updateTimer;
|
|
25
|
-
private _lastUpdateTime;
|
|
26
|
-
/**
|
|
27
|
-
* The objects fluid type name.
|
|
28
|
-
*/
|
|
29
|
-
static readonly TypeName = "@microsoft/fluid-media:SharedMediaSession";
|
|
30
|
-
/**
|
|
31
|
-
* The objects fluid type factory.
|
|
32
|
-
*/
|
|
33
|
-
static readonly factory: DataObjectFactory<LiveMediaSessionClass, import("@fluidframework/aqueduct/internal").DataObjectTypes>;
|
|
34
|
-
/**
|
|
35
|
-
* Extension point that lets applications replace the default logic for throttling the sessions
|
|
36
|
-
* local sync behavior.
|
|
37
|
-
*
|
|
38
|
-
* @remarks
|
|
39
|
-
* The `LiveMediaCoordinator` is fairly aggressive at wanting to keep the local media player
|
|
40
|
-
* in sync with the rest of the group. This aggressiveness can result in the coordinator sending
|
|
41
|
-
* new sync actions before the local player has finished responding to the previous sync action.
|
|
42
|
-
* The `ActionThrottler` gives apps fine grain control over how aggressive they want sync to be.
|
|
43
|
-
*
|
|
44
|
-
* By default, a `RepeatedAction` throttler is used which prevents the same sync action from
|
|
45
|
-
* being sent within an adjustable time period.
|
|
46
|
-
*/
|
|
47
|
-
get actionThrottler(): MediaSessionActionThrottler;
|
|
48
|
-
set actionThrottler(value: MediaSessionActionThrottler);
|
|
49
|
-
/**
|
|
50
|
-
* The group coordinator for the session.
|
|
51
|
-
*/
|
|
52
|
-
get coordinator(): LiveMediaSessionCoordinator;
|
|
53
|
-
/**
|
|
54
|
-
* Returns the logger used by the session and coordinator.
|
|
55
|
-
*
|
|
56
|
-
* @remarks
|
|
57
|
-
* This is used by the `MediaPlayerSynchronizer` to log events.
|
|
58
|
-
*/
|
|
59
|
-
get logger(): LiveTelemetryLogger;
|
|
60
|
-
/**
|
|
61
|
-
* Initialize the object to begin sending/receiving group playback updates through this DDS.
|
|
62
|
-
*
|
|
63
|
-
* @param allowedRoles Optional. List of roles allowed to group transport operations like play/pause/seek/setTrack.
|
|
64
|
-
*
|
|
65
|
-
* @returns a void promise that resolves once complete.
|
|
66
|
-
*
|
|
67
|
-
* @throws error when `.initialize()` has already been called for this class instance.
|
|
68
|
-
*/
|
|
69
|
-
initialize(allowedRoles?: UserMeetingRole[]): Promise<void>;
|
|
70
|
-
/**
|
|
71
|
-
* Registers an action handler with the session.
|
|
72
|
-
* @param action Name of the action to register a handler for.
|
|
73
|
-
* @param handler Function called when the action is triggered.
|
|
74
|
-
*/
|
|
75
|
-
setActionHandler(action: ExtendedMediaSessionAction, handler: ExtendedMediaSessionActionHandler | MediaSessionActionHandler | null): void;
|
|
76
|
-
/**
|
|
77
|
-
* Registers a handler that will be queried anytime the group coordinate needs to know the
|
|
78
|
-
* local players transport state and position.
|
|
79
|
-
*/
|
|
80
|
-
setRequestPlayerStateHandler(handler: () => IMediaPlayerState): void;
|
|
81
|
-
/**
|
|
82
|
-
* Begins synchronizing the playback of a media element.
|
|
83
|
-
* @param player Something that "looks like" and HTML Media Element.
|
|
84
|
-
* @returns A new synchronizer instance. Call `synchronizer.end()` to stop synchronizing the elements playback.
|
|
85
|
-
*/
|
|
86
|
-
synchronize(player: IMediaPlayer): MediaPlayerSynchronizer;
|
|
87
|
-
protected hasInitialized(): Promise<void>;
|
|
88
|
-
private checkWaitPointHit;
|
|
89
|
-
private getCurrentPlayerState;
|
|
90
|
-
private dispatchAction;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Live fluid object that synchronizes media playback across multiple clients.
|
|
94
|
-
*/
|
|
95
|
-
export type LiveMediaSession = LiveMediaSessionClass;
|
|
96
|
-
export declare const LiveMediaSession: typeof LiveMediaSessionClass & SharedObjectKind<LiveMediaSessionClass>;
|
|
97
|
-
//# sourceMappingURL=LiveMediaSession.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LiveMediaSession.d.ts","sourceRoot":"","sources":["../../src/LiveMediaSession.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACH,iBAAiB,EAEpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAGH,mBAAmB,EACnB,eAAe,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEH,cAAc,EACjB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAEH,0BAA0B,EAE1B,iCAAiC,EACpC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACH,2BAA2B,EAC3B,iBAAiB,EACpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAE/E,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGnD;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,cAAc;IACrD,OAAO,CAAC,gBAAgB,CACU;IAClC,OAAO,CAAC,OAAO,CAAC,CAAsB;IACtC,OAAO,CAAC,0BAA0B,CAAC,CAA0B;IAC7D,OAAO,CAAC,YAAY,CAAC,CAA8B;IACnD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAGlB;IACd,OAAO,CAAC,cAAc,CAAC,CAA0B;IAGjD,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,eAAe,CAAa;IAEpC;;OAEG;IACH,gBAAuB,QAAQ,+CAA+C;IAE9E;;OAEG;IACH,gBAAuB,OAAO,wGAK5B;IAEF;;;;;;;;;;;;OAYG;IACH,IAAW,eAAe,IAAI,2BAA2B,CAExD;IAED,IAAW,eAAe,CAAC,KAAK,EAAE,2BAA2B,EAE5D;IAED;;OAEG;IACH,IAAW,WAAW,IAAI,2BAA2B,CAEpD;IAED;;;;;OAKG;IACH,IAAW,MAAM,IAAI,mBAAmB,CAEvC;IAED;;;;;;;;OAQG;IACU,UAAU,CAAC,YAAY,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBxE;;;;OAIG;IACI,gBAAgB,CACnB,MAAM,EAAE,0BAA0B,EAClC,OAAO,EACD,iCAAiC,GACjC,yBAAyB,GACzB,IAAI,GACX,IAAI;IAUP;;;OAGG;IACI,4BAA4B,CAAC,OAAO,EAAE,MAAM,iBAAiB;IAIpE;;;;OAIG;IACI,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,uBAAuB;cAoCjD,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAwF/C,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,cAAc;CAQzB;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,qBAAqB,CAAC;AAGrD,eAAO,MAAM,gBAAgB,wEAGzB,CAAC"}
|