@microsoft/live-share-media 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.nycrc.json +10 -10
- package/LICENSE +90 -90
- package/README.md +135 -135
- package/bin/LiveMediaSession.d.ts.map +1 -1
- package/bin/LiveMediaSession.js +1 -1
- package/bin/LiveMediaSession.js.map +1 -1
- package/bin/LiveMediaSessionCoordinator.d.ts +3 -2
- package/bin/LiveMediaSessionCoordinator.d.ts.map +1 -1
- package/bin/LiveMediaSessionCoordinator.js +27 -13
- package/bin/LiveMediaSessionCoordinator.js.map +1 -1
- package/bin/MediaSessionExtensions.d.ts +0 -4
- package/bin/MediaSessionExtensions.d.ts.map +1 -1
- package/bin/MediaSessionExtensions.js.map +1 -1
- package/bin/internals/consts.d.ts +2 -2
- package/bin/internals/consts.d.ts.map +1 -1
- package/bin/internals/consts.js +2 -2
- package/bin/internals/consts.js.map +1 -1
- package/package.json +45 -45
- package/src/IMediaPlayer.ts +29 -29
- package/src/LiveMediaSession.ts +337 -336
- package/src/LiveMediaSessionCoordinator.ts +711 -678
- package/src/LiveMediaSessionCoordinatorSuspension.ts +39 -39
- package/src/MediaPlayerSynchronizer.ts +714 -714
- package/src/MediaSessionActionThrottler.ts +19 -19
- package/src/MediaSessionExtensions.ts +182 -187
- package/src/RepeatedActionThrottler.ts +76 -76
- package/src/VolumeManager.ts +200 -200
- package/src/index.ts +14 -14
- package/src/internals/GroupCoordinatorState.ts +685 -685
- package/src/internals/GroupPlaybackPosition.ts +228 -228
- package/src/internals/GroupPlaybackTrack.ts +182 -182
- package/src/internals/GroupPlaybackTrackData.ts +104 -104
- package/src/internals/GroupTransportState.ts +170 -170
- package/src/internals/consts.ts +103 -102
- package/src/internals/errors.ts +42 -42
- package/src/internals/index.ts +12 -12
- package/tsconfig.build.json +8 -8
- package/tsconfig.json +76 -76
- package/typedoc.json +10 -10
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
ExtendedMediaSessionActionDetails,
|
|
8
|
-
ExtendedMediaSessionActionHandler,
|
|
9
|
-
} from "./MediaSessionExtensions";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Base class for action throttlers.
|
|
13
|
-
*/
|
|
14
|
-
export abstract class MediaSessionActionThrottler {
|
|
15
|
-
public abstract throttled(
|
|
16
|
-
details: MediaSessionActionDetails | ExtendedMediaSessionActionDetails,
|
|
17
|
-
handler?: MediaSessionActionHandler | ExtendedMediaSessionActionHandler
|
|
18
|
-
): void;
|
|
19
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
ExtendedMediaSessionActionDetails,
|
|
8
|
+
ExtendedMediaSessionActionHandler,
|
|
9
|
+
} from "./MediaSessionExtensions";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base class for action throttlers.
|
|
13
|
+
*/
|
|
14
|
+
export abstract class MediaSessionActionThrottler {
|
|
15
|
+
public abstract throttled(
|
|
16
|
+
details: MediaSessionActionDetails | ExtendedMediaSessionActionDetails,
|
|
17
|
+
handler?: MediaSessionActionHandler | ExtendedMediaSessionActionHandler
|
|
18
|
+
): void;
|
|
19
|
+
}
|
|
@@ -1,187 +1,182 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Suspension object for when group synchronization is suspended for the local user.
|
|
8
|
-
*/
|
|
9
|
-
export interface MediaSessionCoordinatorSuspension {
|
|
10
|
-
/**
|
|
11
|
-
* The wait point that the suspension was created with.
|
|
12
|
-
*
|
|
13
|
-
* @remarks
|
|
14
|
-
* If undefined, the suspension was not created with a wait point.
|
|
15
|
-
*/
|
|
16
|
-
waitPoint?: CoordinationWaitPoint;
|
|
17
|
-
/**
|
|
18
|
-
* Ends the suspension.
|
|
19
|
-
*
|
|
20
|
-
* @param seekTo the timestamp to seek to after the suspension ends.
|
|
21
|
-
* If no value is provided, the local user will return to the group playback position.
|
|
22
|
-
*
|
|
23
|
-
* @remarks
|
|
24
|
-
* If there are other suspensions active, all other suspensions must be ended before group synchronization can resume.
|
|
25
|
-
*/
|
|
26
|
-
end(seekTo?: number): void;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Wait point interface for a suspension.
|
|
31
|
-
*
|
|
32
|
-
* @remarks
|
|
33
|
-
* Used by {@link MediaSessionCoordinatorSuspension} to schedule a suspension at a specific media position.
|
|
34
|
-
*/
|
|
35
|
-
export interface CoordinationWaitPoint {
|
|
36
|
-
/**
|
|
37
|
-
* The position in milliseconds that the suspension should begin.
|
|
38
|
-
*/
|
|
39
|
-
position: number;
|
|
40
|
-
/**
|
|
41
|
-
* Optional. The reason for the suspension.
|
|
42
|
-
*/
|
|
43
|
-
reason?: string;
|
|
44
|
-
/**
|
|
45
|
-
* Optional. The max clients to wait for before a suspension ends.
|
|
46
|
-
*/
|
|
47
|
-
maxClients?: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
*
|
|
52
|
-
*/
|
|
53
|
-
export
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
*
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
*
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
*
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
* Handler for `LiveMediaSession` actions.
|
|
184
|
-
*/
|
|
185
|
-
export interface ExtendedMediaSessionActionHandler {
|
|
186
|
-
(details: ExtendedMediaSessionActionDetails): void;
|
|
187
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
* Licensed under the Microsoft Live Share SDK License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Suspension object for when group synchronization is suspended for the local user.
|
|
8
|
+
*/
|
|
9
|
+
export interface MediaSessionCoordinatorSuspension {
|
|
10
|
+
/**
|
|
11
|
+
* The wait point that the suspension was created with.
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* If undefined, the suspension was not created with a wait point.
|
|
15
|
+
*/
|
|
16
|
+
waitPoint?: CoordinationWaitPoint;
|
|
17
|
+
/**
|
|
18
|
+
* Ends the suspension.
|
|
19
|
+
*
|
|
20
|
+
* @param seekTo the timestamp to seek to after the suspension ends.
|
|
21
|
+
* If no value is provided, the local user will return to the group playback position.
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* If there are other suspensions active, all other suspensions must be ended before group synchronization can resume.
|
|
25
|
+
*/
|
|
26
|
+
end(seekTo?: number): void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Wait point interface for a suspension.
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* Used by {@link MediaSessionCoordinatorSuspension} to schedule a suspension at a specific media position.
|
|
34
|
+
*/
|
|
35
|
+
export interface CoordinationWaitPoint {
|
|
36
|
+
/**
|
|
37
|
+
* The position in milliseconds that the suspension should begin.
|
|
38
|
+
*/
|
|
39
|
+
position: number;
|
|
40
|
+
/**
|
|
41
|
+
* Optional. The reason for the suspension.
|
|
42
|
+
*/
|
|
43
|
+
reason?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Optional. The max clients to wait for before a suspension ends.
|
|
46
|
+
*/
|
|
47
|
+
maxClients?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Event types of `LiveMediaSessionCoordinator`.
|
|
52
|
+
*/
|
|
53
|
+
export enum MediaSessionCoordinatorEvents {
|
|
54
|
+
/**
|
|
55
|
+
* Event emitted after the coordinator's state changed
|
|
56
|
+
*/
|
|
57
|
+
coordinatorstatechange = "coordinatorstatechange",
|
|
58
|
+
/**
|
|
59
|
+
* Event emitted when an action was triggered.
|
|
60
|
+
*/
|
|
61
|
+
triggeraction = "triggeraction",
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Action types supported for `LiveMediaSession`.
|
|
66
|
+
*
|
|
67
|
+
* @remarks
|
|
68
|
+
* These types extend the default actions supported by the `MediaSession` specification in browsers.
|
|
69
|
+
* These additional actions help with group synchronization.
|
|
70
|
+
*/
|
|
71
|
+
export type ExtendedMediaSessionAction =
|
|
72
|
+
| MediaSessionAction
|
|
73
|
+
| "settrack"
|
|
74
|
+
| "wait"
|
|
75
|
+
| "catchup"
|
|
76
|
+
| "datachange"
|
|
77
|
+
| "blocked";
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Extended playback state for `LiveMediaSession`.
|
|
81
|
+
*
|
|
82
|
+
* @remarks
|
|
83
|
+
* These types extend the default state types supported by the `MediaSession` specification in browsers.
|
|
84
|
+
* These additional types help with group synchronization.
|
|
85
|
+
*/
|
|
86
|
+
export type ExtendedMediaSessionPlaybackState =
|
|
87
|
+
| MediaSessionPlaybackState
|
|
88
|
+
| "suspended"
|
|
89
|
+
| "waiting"
|
|
90
|
+
| "ended";
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The source of the action for `LiveMediaSession`.
|
|
94
|
+
*
|
|
95
|
+
* @remarks
|
|
96
|
+
* Is `user` when the action was explicitly invoked via the `LiveMediaSessionCoordinator`.
|
|
97
|
+
* Is `system` when the action was invoked via `GroupCoordinatorState` when the local client is out of sync.
|
|
98
|
+
*/
|
|
99
|
+
export type ExtendedMediaSessionActionSource = "user" | "system";
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Metadata for `LiveMediaSession`.
|
|
103
|
+
*
|
|
104
|
+
* @remarks
|
|
105
|
+
* These types extend the default session metadata supported by the `MediaSession` specification in browsers.
|
|
106
|
+
* These additional types help with group synchronization.
|
|
107
|
+
*/
|
|
108
|
+
export interface ExtendedMediaMetadata extends MediaMetadata {
|
|
109
|
+
/**
|
|
110
|
+
* A unique identifier for the track (e.g., UUID, URL, etc.)
|
|
111
|
+
*/
|
|
112
|
+
trackIdentifier: string;
|
|
113
|
+
/**
|
|
114
|
+
* Flag indicating whether or not the stream is a live broadcast.
|
|
115
|
+
*/
|
|
116
|
+
liveStream?: boolean;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Details for emitted actions from `LiveMediaSession`.
|
|
121
|
+
*
|
|
122
|
+
* @remarks
|
|
123
|
+
* These types extend the default event details supported by the `MediaSession` specification in browsers.
|
|
124
|
+
* These additional types help with group synchronization.
|
|
125
|
+
*/
|
|
126
|
+
export interface ExtendedMediaSessionActionDetails {
|
|
127
|
+
/**
|
|
128
|
+
* The action type of this event.
|
|
129
|
+
*/
|
|
130
|
+
action: ExtendedMediaSessionAction;
|
|
131
|
+
/**
|
|
132
|
+
* The source of the action.
|
|
133
|
+
*
|
|
134
|
+
* @remarks
|
|
135
|
+
* Is `user` when the action was explicitly invoked via the `LiveMediaSessionCoordinator`.
|
|
136
|
+
* Is `system` when the action was invoked via `GroupCoordinatorState` when the local client is out of sync.
|
|
137
|
+
*/
|
|
138
|
+
source: ExtendedMediaSessionActionSource;
|
|
139
|
+
/**
|
|
140
|
+
* Unique identifier of the client that triggered this action.
|
|
141
|
+
*/
|
|
142
|
+
clientId: string;
|
|
143
|
+
/**
|
|
144
|
+
* Flag indicating whether or not the action was triggered by the local client.
|
|
145
|
+
*/
|
|
146
|
+
local: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Flag indicating whether or not this was a fast seek action.
|
|
149
|
+
*/
|
|
150
|
+
fastSeek?: boolean | null;
|
|
151
|
+
/**
|
|
152
|
+
* The offset of the seek.
|
|
153
|
+
*/
|
|
154
|
+
seekOffset?: number | null;
|
|
155
|
+
/**
|
|
156
|
+
* Timestamp of the seek event.
|
|
157
|
+
*/
|
|
158
|
+
seekTime?: number | null;
|
|
159
|
+
/**
|
|
160
|
+
* Updated session metadata that was changed via this action.
|
|
161
|
+
*/
|
|
162
|
+
metadata?: ExtendedMediaMetadata | null;
|
|
163
|
+
/**
|
|
164
|
+
* Suspension associated with this action.
|
|
165
|
+
*/
|
|
166
|
+
suspension?: MediaSessionCoordinatorSuspension | null;
|
|
167
|
+
/**
|
|
168
|
+
* Custom data associated with this action.
|
|
169
|
+
*/
|
|
170
|
+
data?: object | null;
|
|
171
|
+
/**
|
|
172
|
+
* Action type that was blocked.
|
|
173
|
+
*/
|
|
174
|
+
blocked?: ExtendedMediaSessionAction | null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Handler for `LiveMediaSession` actions.
|
|
179
|
+
*/
|
|
180
|
+
export interface ExtendedMediaSessionActionHandler {
|
|
181
|
+
(details: ExtendedMediaSessionActionDetails): void;
|
|
182
|
+
}
|
|
@@ -1,76 +1,76 @@
|
|
|
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: MediaSessionActionDetails | 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(
|
|
67
|
-
details: MediaSessionActionDetails | ExtendedMediaSessionActionDetails
|
|
68
|
-
): string {
|
|
69
|
-
switch (details.action) {
|
|
70
|
-
case "seekto":
|
|
71
|
-
return `seekto:${details.seekTime}`;
|
|
72
|
-
default:
|
|
73
|
-
return details.action;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
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: MediaSessionActionDetails | 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(
|
|
67
|
+
details: MediaSessionActionDetails | ExtendedMediaSessionActionDetails
|
|
68
|
+
): string {
|
|
69
|
+
switch (details.action) {
|
|
70
|
+
case "seekto":
|
|
71
|
+
return `seekto:${details.seekTime}`;
|
|
72
|
+
default:
|
|
73
|
+
return details.action;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|