@microsoft/live-share-media 0.5.1 → 1.0.0-preview.10
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/.nycrc.json +10 -10
- package/LICENSE +86 -86
- package/README.md +141 -137
- package/bin/IMediaPlayer.d.ts.map +1 -1
- package/bin/LiveMediaSession.d.ts +95 -0
- package/bin/LiveMediaSession.d.ts.map +1 -0
- package/bin/LiveMediaSession.js +232 -0
- package/bin/LiveMediaSession.js.map +1 -0
- package/bin/LiveMediaSessionCoordinator.d.ts +228 -0
- package/bin/LiveMediaSessionCoordinator.d.ts.map +1 -0
- package/bin/LiveMediaSessionCoordinator.js +408 -0
- package/bin/LiveMediaSessionCoordinator.js.map +1 -0
- package/bin/LiveMediaSessionCoordinatorSuspension.d.ts +20 -0
- package/bin/LiveMediaSessionCoordinatorSuspension.d.ts.map +1 -0
- package/bin/LiveMediaSessionCoordinatorSuspension.js +28 -0
- package/bin/LiveMediaSessionCoordinatorSuspension.js.map +1 -0
- package/bin/MediaPlayerSynchronizer.d.ts +11 -11
- package/bin/MediaPlayerSynchronizer.d.ts.map +1 -1
- package/bin/MediaPlayerSynchronizer.js +136 -76
- package/bin/MediaPlayerSynchronizer.js.map +1 -1
- package/bin/MediaSessionActionThrottler.d.ts +1 -1
- package/bin/MediaSessionActionThrottler.d.ts.map +1 -1
- package/bin/MediaSessionActionThrottler.js.map +1 -1
- package/bin/MediaSessionExtensions.d.ts.map +1 -1
- package/bin/RepeatedActionThrottler.d.ts +2 -2
- package/bin/RepeatedActionThrottler.d.ts.map +1 -1
- package/bin/RepeatedActionThrottler.js +9 -3
- package/bin/RepeatedActionThrottler.js.map +1 -1
- package/bin/VolumeManager.d.ts +84 -0
- package/bin/VolumeManager.d.ts.map +1 -0
- package/bin/VolumeManager.js +175 -0
- package/bin/VolumeManager.js.map +1 -0
- package/bin/index.d.ts +9 -9
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +4 -4
- package/bin/index.js.map +1 -1
- package/bin/internals/GroupCoordinatorState.d.ts +12 -12
- package/bin/internals/GroupCoordinatorState.d.ts.map +1 -1
- package/bin/internals/GroupCoordinatorState.js +94 -56
- package/bin/internals/GroupCoordinatorState.js.map +1 -1
- package/bin/internals/GroupPlaybackPosition.d.ts +3 -3
- package/bin/internals/GroupPlaybackPosition.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackPosition.js +24 -15
- package/bin/internals/GroupPlaybackPosition.js.map +1 -1
- package/bin/internals/GroupPlaybackTrack.d.ts +4 -4
- package/bin/internals/GroupPlaybackTrack.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackTrack.js +14 -4
- package/bin/internals/GroupPlaybackTrack.js.map +1 -1
- package/bin/internals/GroupPlaybackTrackData.d.ts +3 -3
- package/bin/internals/GroupPlaybackTrackData.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackTrackData.js +8 -4
- package/bin/internals/GroupPlaybackTrackData.js.map +1 -1
- package/bin/internals/GroupTransportState.d.ts +5 -5
- package/bin/internals/GroupTransportState.d.ts.map +1 -1
- package/bin/internals/GroupTransportState.js +28 -13
- package/bin/internals/GroupTransportState.js.map +1 -1
- package/bin/internals/consts.d.ts.map +1 -1
- package/bin/internals/consts.js +54 -54
- package/bin/internals/consts.js.map +1 -1
- package/bin/internals/index.d.ts +6 -6
- package/package.json +38 -38
- package/src/IMediaPlayer.ts +29 -21
- package/src/LiveMediaSession.ts +305 -0
- package/src/LiveMediaSessionCoordinator.ts +621 -0
- package/src/{EphemeralMediaSessionCoordinatorSuspension.ts → LiveMediaSessionCoordinatorSuspension.ts} +39 -31
- package/src/MediaPlayerSynchronizer.ts +636 -450
- package/src/MediaSessionActionThrottler.ts +16 -14
- package/src/MediaSessionExtensions.ts +52 -42
- package/src/RepeatedActionThrottler.ts +74 -56
- package/src/VolumeManager.ts +197 -0
- package/src/index.ts +14 -15
- package/src/internals/GroupCoordinatorState.ts +606 -446
- package/src/internals/GroupPlaybackPosition.ts +227 -193
- package/src/internals/GroupPlaybackTrack.ts +176 -147
- package/src/internals/GroupPlaybackTrackData.ts +98 -90
- package/src/internals/GroupTransportState.ts +157 -127
- package/src/internals/consts.ts +98 -80
- package/src/internals/index.ts +11 -11
- package/src/test/GroupPlaybackPosition.spec.ts +600 -340
- package/src/test/GroupPlaybackTrack.spec.ts +122 -66
- package/src/test/SharedMediaSession.spec.ts +149 -113
- package/src/test/SharedMediaSessionCoordinator.spec.ts +271 -231
- package/src/test/VolumeManager.spec.ts +219 -0
- package/tsconfig.build.json +8 -8
- package/tsconfig.json +76 -75
- package/src/EphemeralMediaSession.ts +0 -248
- package/src/EphemeralMediaSessionCoordinator.ts +0 -461
- package/src/VolumeLimiter.ts +0 -182
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ExtendedMediaSessionActionDetails } from
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Base class for action throttlers.
|
|
10
|
-
*/
|
|
11
|
-
export abstract class MediaSessionActionThrottler {
|
|
12
|
-
public abstract throttled(
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ExtendedMediaSessionActionDetails } from "./MediaSessionExtensions";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Base class for action throttlers.
|
|
10
|
+
*/
|
|
11
|
+
export abstract class MediaSessionActionThrottler {
|
|
12
|
+
public abstract throttled(
|
|
13
|
+
details: ExtendedMediaSessionActionDetails,
|
|
14
|
+
handler?: MediaSessionActionHandler
|
|
15
|
+
): void;
|
|
16
|
+
}
|
|
@@ -1,42 +1,52 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface MediaSessionCoordinatorSuspension {
|
|
7
|
-
waitPoint?: CoordinationWaitPoint;
|
|
8
|
-
end(seekTo?: number): void;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export type MediaSessionCoordinatorState = "closed" | "waiting" | "joined";
|
|
12
|
-
|
|
13
|
-
export enum MediaSessionCoordinatorEvents {
|
|
14
|
-
coordinatorstatechange =
|
|
15
|
-
triggeraction =
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export type ExtendedMediaSessionAction =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface MediaSessionCoordinatorSuspension {
|
|
7
|
+
waitPoint?: CoordinationWaitPoint;
|
|
8
|
+
end(seekTo?: number): void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type MediaSessionCoordinatorState = "closed" | "waiting" | "joined";
|
|
12
|
+
|
|
13
|
+
export enum MediaSessionCoordinatorEvents {
|
|
14
|
+
coordinatorstatechange = "coordinatorstatechange",
|
|
15
|
+
triggeraction = "triggeraction",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type ExtendedMediaSessionAction =
|
|
19
|
+
| MediaSessionAction
|
|
20
|
+
| "settrack"
|
|
21
|
+
| "wait"
|
|
22
|
+
| "catchup"
|
|
23
|
+
| "datachange"
|
|
24
|
+
| "blocked";
|
|
25
|
+
|
|
26
|
+
export type ExtendedMediaSessionPlaybackState =
|
|
27
|
+
| MediaSessionPlaybackState
|
|
28
|
+
| "suspended"
|
|
29
|
+
| "waiting"
|
|
30
|
+
| "ended";
|
|
31
|
+
|
|
32
|
+
export interface ExtendedMediaMetadata extends MediaMetadata {
|
|
33
|
+
trackIdentifier: string;
|
|
34
|
+
liveStream: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface CoordinationWaitPoint {
|
|
38
|
+
position: number;
|
|
39
|
+
reason?: string;
|
|
40
|
+
maxClients?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface ExtendedMediaSessionActionDetails {
|
|
44
|
+
action: ExtendedMediaSessionAction;
|
|
45
|
+
fastSeek?: boolean | null;
|
|
46
|
+
seekOffset?: number | null;
|
|
47
|
+
seekTime?: number | null;
|
|
48
|
+
metadata?: ExtendedMediaMetadata | null;
|
|
49
|
+
suspension?: MediaSessionCoordinatorSuspension | null;
|
|
50
|
+
data?: object | null;
|
|
51
|
+
blocked?: ExtendedMediaSessionAction | null;
|
|
52
|
+
}
|
|
@@ -1,56 +1,74 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { TimeInterval } from
|
|
7
|
-
import { MediaSessionActionThrottler } from
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
private
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
public
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { TimeInterval } from "@microsoft/live-share";
|
|
7
|
+
import { MediaSessionActionThrottler } from "./MediaSessionActionThrottler";
|
|
8
|
+
import {
|
|
9
|
+
ExtendedMediaSessionActionDetails,
|
|
10
|
+
ExtendedMediaSessionAction,
|
|
11
|
+
} from "./MediaSessionExtensions";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A Throttler that passes through all actions but will only let an action be repeated once every 2 seconds.
|
|
15
|
+
*/
|
|
16
|
+
export class RepeatedActionThrottler extends MediaSessionActionThrottler {
|
|
17
|
+
private static FILTERED_ACTIONS: ExtendedMediaSessionAction[] = [
|
|
18
|
+
"play",
|
|
19
|
+
"pause",
|
|
20
|
+
"seekto",
|
|
21
|
+
"catchup",
|
|
22
|
+
];
|
|
23
|
+
private _repeatInterval = new TimeInterval(2000);
|
|
24
|
+
private _lastActionSentTime?: number;
|
|
25
|
+
private _lastActionSent?: string;
|
|
26
|
+
|
|
27
|
+
public get repeatInterval(): number {
|
|
28
|
+
return this._repeatInterval.seconds;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public set repeatInterval(value: number) {
|
|
32
|
+
this._repeatInterval.seconds = value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public throttled(
|
|
36
|
+
details: ExtendedMediaSessionActionDetails,
|
|
37
|
+
handler?: MediaSessionActionHandler
|
|
38
|
+
): void {
|
|
39
|
+
if (handler) {
|
|
40
|
+
if (
|
|
41
|
+
RepeatedActionThrottler.FILTERED_ACTIONS.indexOf(
|
|
42
|
+
details.action
|
|
43
|
+
) >= 0
|
|
44
|
+
) {
|
|
45
|
+
const changeKey = this.getChangeKey(details);
|
|
46
|
+
const now = new Date().getTime();
|
|
47
|
+
if (this._lastActionSent && changeKey == this._lastActionSent) {
|
|
48
|
+
if (
|
|
49
|
+
now - this._lastActionSentTime! >=
|
|
50
|
+
this._repeatInterval.milliseconds
|
|
51
|
+
) {
|
|
52
|
+
handler(details as MediaSessionActionDetails);
|
|
53
|
+
this._lastActionSentTime = now;
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
handler(details as MediaSessionActionDetails);
|
|
57
|
+
this._lastActionSent = changeKey;
|
|
58
|
+
this._lastActionSentTime = now;
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
handler(details as MediaSessionActionDetails);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private getChangeKey(details: ExtendedMediaSessionActionDetails): string {
|
|
67
|
+
switch (details.action) {
|
|
68
|
+
case "seekto":
|
|
69
|
+
return `seekto:${details.seekTime}`;
|
|
70
|
+
default:
|
|
71
|
+
return details.action;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { TimeInterval } from "@microsoft/live-share";
|
|
7
|
+
import { IMediaPlayer } from "./IMediaPlayer";
|
|
8
|
+
|
|
9
|
+
export enum LimitLevelType {
|
|
10
|
+
fixed,
|
|
11
|
+
percentage,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Smooth audio level changes when volume is modified, or if volume limiting has started/ended.
|
|
16
|
+
*/
|
|
17
|
+
export class VolumeManager {
|
|
18
|
+
private readonly _player: IMediaPlayer;
|
|
19
|
+
private readonly _volumeChangeDuration = new TimeInterval(500);
|
|
20
|
+
|
|
21
|
+
// defaults to player volume
|
|
22
|
+
private _volume = 0.0;
|
|
23
|
+
private _isLimiting = false;
|
|
24
|
+
private _limitLevel = 0.1;
|
|
25
|
+
private _limitLevelType: LimitLevelType = LimitLevelType.fixed;
|
|
26
|
+
private _startTime = 0;
|
|
27
|
+
private _startVolume = 0;
|
|
28
|
+
private _running = false;
|
|
29
|
+
|
|
30
|
+
constructor(player: IMediaPlayer) {
|
|
31
|
+
this._player = player;
|
|
32
|
+
this._volume = this._player.volume;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The selected volume.
|
|
37
|
+
*
|
|
38
|
+
* @remarks
|
|
39
|
+
* Expressed as a value between 0.0 and 1.0. The default value is 1.0.
|
|
40
|
+
* Can be used for things like volume sliders.
|
|
41
|
+
*
|
|
42
|
+
* Does not return the current volume if limiting is enabled, but the desired volume.
|
|
43
|
+
*/
|
|
44
|
+
public get volume(): number {
|
|
45
|
+
return this._volume;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public set volume(value: number) {
|
|
49
|
+
if (value < 0 || value > 1.0) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
`VolumeManager: cannot set volume to ${value}. Level must be between 0.0 and 1.0.`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this._volume = value;
|
|
56
|
+
this.startAdjusting();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Target level to lower volume to.
|
|
61
|
+
*
|
|
62
|
+
* @remarks
|
|
63
|
+
* Expressed as a value between 0.0 and 1.0. The value is applied based upon the configured
|
|
64
|
+
* `levelType`. The default value is 0.1.
|
|
65
|
+
*
|
|
66
|
+
* For a level type of `LevelType.fixed` the value is the exact level the volume will be
|
|
67
|
+
* lowered to. The default value of 0.1 would cause the volume to be lowered to 0.1.
|
|
68
|
+
*
|
|
69
|
+
* For a level type of `LevelType.percentage` the value is the percentage by which the volume
|
|
70
|
+
* level should be lowered to. The default value of 0.1 would cause the volume to be lowered
|
|
71
|
+
* to 10% of its starting value.
|
|
72
|
+
*/
|
|
73
|
+
public get limitLevel(): number {
|
|
74
|
+
return this._limitLevel;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public set limitLevel(value: number) {
|
|
78
|
+
if (value < 0 || value > 1.0) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
`VolumeManager: cannot set level to ${value}. Level must be between 0.0 and 1.0.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this._limitLevel = value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The type of level represented by the `limitLevel` property.
|
|
89
|
+
*/
|
|
90
|
+
public get limitLevelType(): LimitLevelType {
|
|
91
|
+
return this._limitLevelType;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public set limitLevelType(value: LimitLevelType) {
|
|
95
|
+
this._limitLevelType = value;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Amount of time, in seconds, it should take to change the volume up or down to the desired level.
|
|
100
|
+
*
|
|
101
|
+
* @remarks
|
|
102
|
+
* Default `volumeChangeDuration` is 0.5 seconds.
|
|
103
|
+
*/
|
|
104
|
+
public get volumeChangeDuration(): number {
|
|
105
|
+
return this._volumeChangeDuration.seconds;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public set volumeChangeDuration(value: number) {
|
|
109
|
+
this._volumeChangeDuration.seconds = Math.abs(value);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Whether or not volume limiting is currently enabled.
|
|
114
|
+
*/
|
|
115
|
+
public get isLimiting(): boolean {
|
|
116
|
+
return this._isLimiting;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Limits volume based on `limitLevel` and `limitLevelType` properties.
|
|
121
|
+
* @see `limitLevel`
|
|
122
|
+
* @see `limitLevelType`
|
|
123
|
+
*/
|
|
124
|
+
public startLimiting(): void {
|
|
125
|
+
this._isLimiting = true;
|
|
126
|
+
this.startAdjusting();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Disables volume limit.
|
|
131
|
+
*/
|
|
132
|
+
public stopLimiting(): void {
|
|
133
|
+
this._isLimiting = false;
|
|
134
|
+
this.startAdjusting();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private startAdjusting() {
|
|
138
|
+
const adjustVolume = () => {
|
|
139
|
+
// Schedule next animation frame if volume change not finished
|
|
140
|
+
if (
|
|
141
|
+
this.millisSinceVolumeChangeStart() <=
|
|
142
|
+
this._volumeChangeDuration.milliseconds
|
|
143
|
+
) {
|
|
144
|
+
this._player.volume = this.computeInterpolatedVolume();
|
|
145
|
+
this.scheduleAnimationFrame(adjustVolume);
|
|
146
|
+
} else {
|
|
147
|
+
this._player.volume = this.computeTargetVolume();
|
|
148
|
+
this._running = false;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
this._startTime = new Date().getTime();
|
|
153
|
+
this._startVolume = this._player.volume;
|
|
154
|
+
if (!this._running) {
|
|
155
|
+
this._running = true;
|
|
156
|
+
this.scheduleAnimationFrame(adjustVolume);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private scheduleAnimationFrame(callback: FrameRequestCallback): void {
|
|
161
|
+
if (typeof requestAnimationFrame == "function") {
|
|
162
|
+
requestAnimationFrame(callback);
|
|
163
|
+
} else {
|
|
164
|
+
setTimeout(callback, 20);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private computeInterpolatedVolume(): number {
|
|
169
|
+
const volumeChangeMillis = this._volumeChangeDuration.milliseconds;
|
|
170
|
+
const volumeDifference = this.computeTargetVolume() - this._startVolume;
|
|
171
|
+
const adjustmentFromStart =
|
|
172
|
+
(volumeDifference / volumeChangeMillis) *
|
|
173
|
+
this.millisSinceVolumeChangeStart();
|
|
174
|
+
return this._startVolume + adjustmentFromStart;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private computeTargetVolume(): number {
|
|
178
|
+
if (this._limitLevelType == LimitLevelType.percentage) {
|
|
179
|
+
if (this._isLimiting) {
|
|
180
|
+
return this._volume * this._limitLevel;
|
|
181
|
+
} else {
|
|
182
|
+
return this._volume;
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
if (this._isLimiting && this._volume > this._limitLevel) {
|
|
186
|
+
return this._limitLevel;
|
|
187
|
+
} else {
|
|
188
|
+
return this._volume;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private millisSinceVolumeChangeStart(): number {
|
|
194
|
+
const now = new Date().getTime();
|
|
195
|
+
return now - this._startTime;
|
|
196
|
+
}
|
|
197
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
9
|
-
export * from
|
|
10
|
-
export * from
|
|
11
|
-
export * from
|
|
12
|
-
export * from
|
|
13
|
-
export * from
|
|
14
|
-
export * from
|
|
15
|
-
export * from './VolumeLimiter';
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export * from "./LiveMediaSession";
|
|
7
|
+
export * from "./LiveMediaSessionCoordinator";
|
|
8
|
+
export * from "./LiveMediaSessionCoordinatorSuspension";
|
|
9
|
+
export * from "./IMediaPlayer";
|
|
10
|
+
export * from "./MediaPlayerSynchronizer";
|
|
11
|
+
export * from "./MediaSessionActionThrottler";
|
|
12
|
+
export * from "./MediaSessionExtensions";
|
|
13
|
+
export * from "./RepeatedActionThrottler";
|
|
14
|
+
export * from "./VolumeManager";
|