@microsoft/live-share-media 1.0.0-preview.1 → 1.0.0-preview.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/bin/IMediaPlayer.d.ts.map +1 -1
- package/bin/LiveMediaSession.d.ts +7 -7
- package/bin/LiveMediaSession.d.ts.map +1 -1
- package/bin/LiveMediaSession.js +28 -17
- package/bin/LiveMediaSession.js.map +1 -1
- package/bin/LiveMediaSessionCoordinator.d.ts +2 -2
- package/bin/LiveMediaSessionCoordinator.d.ts.map +1 -1
- package/bin/LiveMediaSessionCoordinator.js +34 -22
- package/bin/LiveMediaSessionCoordinator.js.map +1 -1
- package/bin/LiveMediaSessionCoordinatorSuspension.d.ts +1 -1
- package/bin/LiveMediaSessionCoordinatorSuspension.d.ts.map +1 -1
- package/bin/LiveMediaSessionCoordinatorSuspension.js.map +1 -1
- package/bin/MediaPlayerSynchronizer.d.ts +7 -7
- package/bin/MediaPlayerSynchronizer.d.ts.map +1 -1
- package/bin/MediaPlayerSynchronizer.js +127 -72
- 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 +1 -1
- package/bin/VolumeManager.d.ts.map +1 -1
- package/bin/VolumeManager.js +4 -2
- package/bin/VolumeManager.js.map +1 -1
- package/bin/index.d.ts +9 -9
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js.map +1 -1
- package/bin/internals/GroupCoordinatorState.d.ts +8 -8
- package/bin/internals/GroupCoordinatorState.d.ts.map +1 -1
- package/bin/internals/GroupCoordinatorState.js +91 -53
- 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 +22 -13
- 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 +27 -12
- 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 +3 -3
- package/src/IMediaPlayer.ts +10 -2
- package/src/LiveMediaSession.ts +133 -71
- package/src/LiveMediaSessionCoordinator.ts +302 -142
- package/src/LiveMediaSessionCoordinatorSuspension.ts +13 -5
- package/src/MediaPlayerSynchronizer.ts +329 -149
- package/src/MediaSessionActionThrottler.ts +5 -3
- package/src/MediaSessionExtensions.ts +15 -5
- package/src/RepeatedActionThrottler.ts +27 -9
- package/src/VolumeManager.ts +24 -12
- package/src/index.ts +9 -10
- package/src/internals/GroupCoordinatorState.ts +274 -114
- package/src/internals/GroupPlaybackPosition.ts +61 -27
- package/src/internals/GroupPlaybackTrack.ts +51 -22
- package/src/internals/GroupPlaybackTrackData.ts +24 -16
- package/src/internals/GroupTransportState.ts +53 -23
- package/src/internals/consts.ts +73 -55
- package/src/internals/index.ts +6 -6
- package/src/test/GroupPlaybackPosition.spec.ts +371 -111
- package/src/test/GroupPlaybackTrack.spec.ts +91 -35
- package/src/test/SharedMediaSession.spec.ts +64 -28
- package/src/test/SharedMediaSessionCoordinator.spec.ts +86 -46
- package/src/test/VolumeManager.spec.ts +38 -31
- package/tsconfig.json +1 -0
- package/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
|
@@ -3,168 +3,281 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
import { strict as assert } from
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
import "mocha";
|
|
7
|
+
import { strict as assert } from "assert";
|
|
8
|
+
import {
|
|
9
|
+
IParticipant,
|
|
10
|
+
ParticipantRole,
|
|
11
|
+
SimulatedBroadcastHub,
|
|
12
|
+
SimulatedCollaborationSpace,
|
|
13
|
+
} from "@microsoft/teams-collaboration";
|
|
14
|
+
import { GroupPlaybackTrack } from "./GroupPlaybackTrack";
|
|
15
|
+
import { GroupTransportState, ITransportState } from "./GroupTransportState";
|
|
16
|
+
import {
|
|
17
|
+
GroupPlaybackPosition,
|
|
18
|
+
ICurrentPlaybackPosition,
|
|
19
|
+
} from "./GroupPlaybackPosition";
|
|
20
|
+
import {
|
|
21
|
+
CoordinationWaitPoint,
|
|
22
|
+
ExtendedMediaMetadata,
|
|
23
|
+
ExtendedMediaSessionPlaybackState,
|
|
24
|
+
} from "../MediaSessionExtensions";
|
|
25
|
+
import { TimeInterval } from "../internals";
|
|
26
|
+
|
|
27
|
+
function createTransportUpdate(
|
|
28
|
+
space: SimulatedCollaborationSpace,
|
|
29
|
+
playbackState: ExtendedMediaSessionPlaybackState,
|
|
30
|
+
startPosition: number
|
|
31
|
+
): ITransportState {
|
|
16
32
|
return {
|
|
17
33
|
playbackState: playbackState,
|
|
18
34
|
startPosition: startPosition,
|
|
19
35
|
timestamp: space.clock.getTime(),
|
|
20
|
-
socketId: space.socket.id
|
|
36
|
+
socketId: space.socket.id,
|
|
21
37
|
};
|
|
22
38
|
}
|
|
23
39
|
|
|
24
|
-
function createPositionUpdate(
|
|
40
|
+
function createPositionUpdate(
|
|
41
|
+
space: SimulatedCollaborationSpace,
|
|
42
|
+
playbackState: ExtendedMediaSessionPlaybackState,
|
|
43
|
+
position: number,
|
|
44
|
+
waitPoint?: CoordinationWaitPoint,
|
|
45
|
+
duration?: number
|
|
46
|
+
): ICurrentPlaybackPosition {
|
|
25
47
|
return {
|
|
26
48
|
playbackState: playbackState,
|
|
27
49
|
waitPoint: waitPoint,
|
|
28
50
|
position: position,
|
|
29
51
|
duration: duration,
|
|
30
52
|
timestamp: space.clock.getTime(),
|
|
31
|
-
socketId: space.socket.id
|
|
53
|
+
socketId: space.socket.id,
|
|
32
54
|
};
|
|
33
55
|
}
|
|
34
56
|
|
|
35
|
-
function subtractSeconds<T extends { timestamp: number
|
|
36
|
-
|
|
57
|
+
function subtractSeconds<T extends { timestamp: number }>(
|
|
58
|
+
seconds: number,
|
|
59
|
+
update: T
|
|
60
|
+
): T {
|
|
61
|
+
update.timestamp -= seconds * 1000;
|
|
37
62
|
return update;
|
|
38
|
-
}
|
|
63
|
+
}
|
|
39
64
|
|
|
40
|
-
function addSeconds<T extends { timestamp: number
|
|
41
|
-
|
|
65
|
+
function addSeconds<T extends { timestamp: number }>(
|
|
66
|
+
seconds: number,
|
|
67
|
+
update: T
|
|
68
|
+
): T {
|
|
69
|
+
update.timestamp += seconds * 1000;
|
|
42
70
|
return update;
|
|
43
|
-
}
|
|
71
|
+
}
|
|
44
72
|
|
|
45
|
-
describe(
|
|
73
|
+
describe("GroupPlaybackPosition", () => {
|
|
46
74
|
const hub = new SimulatedBroadcastHub();
|
|
47
75
|
|
|
48
|
-
const user1: IParticipant = {
|
|
76
|
+
const user1: IParticipant = {
|
|
77
|
+
participantId: "user1",
|
|
78
|
+
role: ParticipantRole.organizer,
|
|
79
|
+
};
|
|
49
80
|
const space1 = new SimulatedCollaborationSpace(user1, hub);
|
|
50
|
-
const user2: IParticipant = {
|
|
81
|
+
const user2: IParticipant = {
|
|
82
|
+
participantId: "user2",
|
|
83
|
+
role: ParticipantRole.participant,
|
|
84
|
+
};
|
|
51
85
|
const space2 = new SimulatedCollaborationSpace(user2, hub);
|
|
52
86
|
|
|
53
|
-
const track1 = {
|
|
54
|
-
|
|
87
|
+
const track1 = {
|
|
88
|
+
trackIdentifier: "track1",
|
|
89
|
+
title: "Test Track 1",
|
|
90
|
+
} as ExtendedMediaMetadata;
|
|
91
|
+
const track2 = {
|
|
92
|
+
trackIdentifier: "track2",
|
|
93
|
+
title: "Test Track 2",
|
|
94
|
+
} as ExtendedMediaMetadata;
|
|
55
95
|
|
|
56
96
|
const updateInterval = new TimeInterval(10);
|
|
57
97
|
|
|
58
|
-
it(
|
|
98
|
+
it("should start with 0 clients", async () => {
|
|
59
99
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
60
100
|
const transportState = new GroupTransportState(playbackTrack);
|
|
61
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
101
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
102
|
+
transportState,
|
|
103
|
+
space1,
|
|
104
|
+
updateInterval
|
|
105
|
+
);
|
|
62
106
|
|
|
63
107
|
await space1.join();
|
|
64
108
|
try {
|
|
65
109
|
assert(playbackPosition.totalClients == 0, `wrong client count`);
|
|
66
|
-
assert(
|
|
110
|
+
assert(
|
|
111
|
+
playbackPosition.localPosition == undefined,
|
|
112
|
+
`wrong position`
|
|
113
|
+
);
|
|
67
114
|
} finally {
|
|
68
115
|
await space1.leave();
|
|
69
116
|
}
|
|
70
117
|
});
|
|
71
118
|
|
|
72
|
-
it(
|
|
119
|
+
it("should find local position", async () => {
|
|
73
120
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
74
121
|
const transportState = new GroupTransportState(playbackTrack);
|
|
75
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
122
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
123
|
+
transportState,
|
|
124
|
+
space1,
|
|
125
|
+
updateInterval
|
|
126
|
+
);
|
|
76
127
|
|
|
77
128
|
await space1.join();
|
|
78
129
|
try {
|
|
79
|
-
await playbackPosition.UpdatePlaybackPosition(
|
|
130
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
131
|
+
createPositionUpdate(space1, "none", 0.0)
|
|
132
|
+
);
|
|
80
133
|
|
|
81
134
|
assert(playbackPosition.totalClients == 1, `wrong client count`);
|
|
82
|
-
assert(
|
|
135
|
+
assert(
|
|
136
|
+
playbackPosition.localPosition != undefined,
|
|
137
|
+
`local position not found`
|
|
138
|
+
);
|
|
83
139
|
} finally {
|
|
84
140
|
await space1.leave();
|
|
85
141
|
}
|
|
86
142
|
});
|
|
87
143
|
|
|
88
|
-
it(
|
|
144
|
+
it("should update local position", async () => {
|
|
89
145
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
90
146
|
const transportState = new GroupTransportState(playbackTrack);
|
|
91
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
147
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
148
|
+
transportState,
|
|
149
|
+
space1,
|
|
150
|
+
updateInterval
|
|
151
|
+
);
|
|
92
152
|
|
|
93
153
|
await space1.join();
|
|
94
154
|
try {
|
|
95
|
-
const position = createPositionUpdate(space1,
|
|
155
|
+
const position = createPositionUpdate(space1, "none", 0.0);
|
|
96
156
|
await playbackPosition.UpdatePlaybackPosition(position);
|
|
97
157
|
|
|
98
|
-
const newPosition = addSeconds(
|
|
158
|
+
const newPosition = addSeconds(
|
|
159
|
+
1.0,
|
|
160
|
+
createPositionUpdate(space1, "none", 0.0)
|
|
161
|
+
);
|
|
99
162
|
await playbackPosition.UpdatePlaybackPosition(newPosition);
|
|
100
163
|
|
|
101
164
|
assert(playbackPosition.totalClients == 1, `wrong client count`);
|
|
102
|
-
assert(
|
|
103
|
-
|
|
165
|
+
assert(
|
|
166
|
+
playbackPosition.localPosition != undefined,
|
|
167
|
+
`local position not found`
|
|
168
|
+
);
|
|
169
|
+
assert(
|
|
170
|
+
playbackPosition.localPosition.timestamp ==
|
|
171
|
+
newPosition.timestamp,
|
|
172
|
+
`position not updated`
|
|
173
|
+
);
|
|
104
174
|
} finally {
|
|
105
175
|
await space1.leave();
|
|
106
176
|
}
|
|
107
177
|
});
|
|
108
178
|
|
|
109
|
-
it(
|
|
179
|
+
it("should ignore older position updates", async () => {
|
|
110
180
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
111
181
|
const transportState = new GroupTransportState(playbackTrack);
|
|
112
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
182
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
183
|
+
transportState,
|
|
184
|
+
space1,
|
|
185
|
+
updateInterval
|
|
186
|
+
);
|
|
113
187
|
|
|
114
188
|
await space1.join();
|
|
115
189
|
try {
|
|
116
|
-
const position = createPositionUpdate(space1,
|
|
190
|
+
const position = createPositionUpdate(space1, "none", 0.0);
|
|
117
191
|
await playbackPosition.UpdatePlaybackPosition(position);
|
|
118
192
|
|
|
119
|
-
const newPosition = subtractSeconds(
|
|
193
|
+
const newPosition = subtractSeconds(
|
|
194
|
+
1.0,
|
|
195
|
+
createPositionUpdate(space1, "none", 0.0)
|
|
196
|
+
);
|
|
120
197
|
await playbackPosition.UpdatePlaybackPosition(newPosition);
|
|
121
198
|
|
|
122
199
|
assert(playbackPosition.totalClients == 1, `wrong client count`);
|
|
123
|
-
assert(
|
|
124
|
-
|
|
200
|
+
assert(
|
|
201
|
+
playbackPosition.localPosition != undefined,
|
|
202
|
+
`local position not found`
|
|
203
|
+
);
|
|
204
|
+
assert(
|
|
205
|
+
playbackPosition.localPosition.timestamp == position.timestamp,
|
|
206
|
+
`position not updated`
|
|
207
|
+
);
|
|
125
208
|
} finally {
|
|
126
209
|
await space1.leave();
|
|
127
210
|
}
|
|
128
211
|
});
|
|
129
212
|
|
|
130
|
-
it(
|
|
213
|
+
it("should track other client positions", async () => {
|
|
131
214
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
132
215
|
const transportState = new GroupTransportState(playbackTrack);
|
|
133
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
216
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
217
|
+
transportState,
|
|
218
|
+
space1,
|
|
219
|
+
updateInterval
|
|
220
|
+
);
|
|
134
221
|
|
|
135
222
|
await space1.join();
|
|
136
223
|
await space2.join();
|
|
137
224
|
try {
|
|
138
|
-
const position1 = createPositionUpdate(space1,
|
|
225
|
+
const position1 = createPositionUpdate(space1, "none", 0.0);
|
|
139
226
|
await playbackPosition.UpdatePlaybackPosition(position1);
|
|
140
227
|
|
|
141
|
-
const position2 = addSeconds(
|
|
228
|
+
const position2 = addSeconds(
|
|
229
|
+
1.0,
|
|
230
|
+
createPositionUpdate(space2, "none", 0.0)
|
|
231
|
+
);
|
|
142
232
|
await playbackPosition.UpdatePlaybackPosition(position2);
|
|
143
233
|
|
|
144
234
|
assert(playbackPosition.totalClients == 2, `wrong client count`);
|
|
145
|
-
assert(
|
|
146
|
-
|
|
235
|
+
assert(
|
|
236
|
+
playbackPosition.localPosition != undefined,
|
|
237
|
+
`local position not found`
|
|
238
|
+
);
|
|
239
|
+
assert(
|
|
240
|
+
playbackPosition.localPosition.timestamp == position1.timestamp,
|
|
241
|
+
`position not updated`
|
|
242
|
+
);
|
|
147
243
|
} finally {
|
|
148
244
|
await space1.leave();
|
|
149
245
|
await space2.leave();
|
|
150
246
|
}
|
|
151
247
|
});
|
|
152
248
|
|
|
153
|
-
it(
|
|
249
|
+
it("should enumerate client positions", async () => {
|
|
154
250
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
155
251
|
const transportState = new GroupTransportState(playbackTrack);
|
|
156
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
252
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
253
|
+
transportState,
|
|
254
|
+
space1,
|
|
255
|
+
updateInterval
|
|
256
|
+
);
|
|
157
257
|
|
|
158
258
|
await space1.join();
|
|
159
259
|
await space2.join();
|
|
160
260
|
try {
|
|
161
|
-
await playbackPosition.UpdatePlaybackPosition(
|
|
162
|
-
|
|
261
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
262
|
+
createPositionUpdate(space1, "none", 0.0)
|
|
263
|
+
);
|
|
264
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
265
|
+
subtractSeconds(
|
|
266
|
+
updateInterval.seconds,
|
|
267
|
+
createPositionUpdate(space2, "none", 0.0)
|
|
268
|
+
)
|
|
269
|
+
);
|
|
163
270
|
|
|
164
271
|
let cnt = 0;
|
|
165
272
|
playbackPosition.forEach((position, projectedPosition) => {
|
|
166
|
-
assert(
|
|
167
|
-
|
|
273
|
+
assert(
|
|
274
|
+
position.position == 0.0,
|
|
275
|
+
`wrong position ${position.position}`
|
|
276
|
+
);
|
|
277
|
+
assert(
|
|
278
|
+
projectedPosition == 0.0,
|
|
279
|
+
`wrong projected position ${projectedPosition}`
|
|
280
|
+
);
|
|
168
281
|
cnt++;
|
|
169
282
|
});
|
|
170
283
|
|
|
@@ -175,21 +288,38 @@ describe('GroupPlaybackPosition', () => {
|
|
|
175
288
|
}
|
|
176
289
|
});
|
|
177
290
|
|
|
178
|
-
it(
|
|
291
|
+
it("should ignore stale positions", async () => {
|
|
179
292
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
180
293
|
const transportState = new GroupTransportState(playbackTrack);
|
|
181
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
294
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
295
|
+
transportState,
|
|
296
|
+
space1,
|
|
297
|
+
updateInterval
|
|
298
|
+
);
|
|
182
299
|
|
|
183
300
|
await space1.join();
|
|
184
301
|
await space2.join();
|
|
185
302
|
try {
|
|
186
|
-
await playbackPosition.UpdatePlaybackPosition(
|
|
187
|
-
|
|
303
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
304
|
+
createPositionUpdate(space1, "none", 0.0)
|
|
305
|
+
);
|
|
306
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
307
|
+
subtractSeconds(
|
|
308
|
+
updateInterval.seconds * 3,
|
|
309
|
+
createPositionUpdate(space2, "none", 0.0)
|
|
310
|
+
)
|
|
311
|
+
);
|
|
188
312
|
|
|
189
313
|
let cnt = 0;
|
|
190
314
|
playbackPosition.forEach((position, projectedPosition) => {
|
|
191
|
-
assert(
|
|
192
|
-
|
|
315
|
+
assert(
|
|
316
|
+
position.position == 0.0,
|
|
317
|
+
`wrong position ${position.position}`
|
|
318
|
+
);
|
|
319
|
+
assert(
|
|
320
|
+
projectedPosition == 0.0,
|
|
321
|
+
`wrong projected position ${projectedPosition}`
|
|
322
|
+
);
|
|
193
323
|
cnt++;
|
|
194
324
|
});
|
|
195
325
|
|
|
@@ -200,19 +330,34 @@ describe('GroupPlaybackPosition', () => {
|
|
|
200
330
|
}
|
|
201
331
|
});
|
|
202
332
|
|
|
203
|
-
it(
|
|
333
|
+
it("should project position when playing", async () => {
|
|
204
334
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
205
335
|
const transportState = new GroupTransportState(playbackTrack);
|
|
206
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
336
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
337
|
+
transportState,
|
|
338
|
+
space1,
|
|
339
|
+
new TimeInterval(1000)
|
|
340
|
+
);
|
|
207
341
|
|
|
208
342
|
await space1.join();
|
|
209
343
|
try {
|
|
210
|
-
await playbackPosition.UpdatePlaybackPosition(
|
|
344
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
345
|
+
subtractSeconds(
|
|
346
|
+
1.0,
|
|
347
|
+
createPositionUpdate(space1, "playing", 0.0)
|
|
348
|
+
)
|
|
349
|
+
);
|
|
211
350
|
|
|
212
351
|
let cnt = 0;
|
|
213
352
|
playbackPosition.forEach((position, projectedPosition) => {
|
|
214
|
-
assert(
|
|
215
|
-
|
|
353
|
+
assert(
|
|
354
|
+
position.position == 0.0,
|
|
355
|
+
`wrong position ${position.position}`
|
|
356
|
+
);
|
|
357
|
+
assert(
|
|
358
|
+
projectedPosition >= 1.0,
|
|
359
|
+
`wrong projected position ${projectedPosition}`
|
|
360
|
+
);
|
|
216
361
|
cnt++;
|
|
217
362
|
});
|
|
218
363
|
|
|
@@ -222,119 +367,234 @@ describe('GroupPlaybackPosition', () => {
|
|
|
222
367
|
}
|
|
223
368
|
});
|
|
224
369
|
|
|
225
|
-
it(
|
|
370
|
+
it("should compute max playback position relative to transport state", async () => {
|
|
226
371
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
227
372
|
const transportState = new GroupTransportState(playbackTrack);
|
|
228
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
373
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
374
|
+
transportState,
|
|
375
|
+
space1,
|
|
376
|
+
new TimeInterval(1000)
|
|
377
|
+
);
|
|
229
378
|
|
|
230
379
|
await space1.join();
|
|
231
380
|
try {
|
|
232
|
-
assert(
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
381
|
+
assert(
|
|
382
|
+
playbackPosition.maxPosition == 0.0,
|
|
383
|
+
`wrong starting position of ${playbackPosition.maxPosition}`
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
await transportState.updateState(
|
|
387
|
+
subtractSeconds(
|
|
388
|
+
2.0,
|
|
389
|
+
createTransportUpdate(space1, "playing", 0.0)
|
|
390
|
+
)
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
assert(
|
|
394
|
+
playbackPosition.maxPosition >= 2.0,
|
|
395
|
+
`wrong projected position of ${playbackPosition.maxPosition}`
|
|
396
|
+
);
|
|
237
397
|
} finally {
|
|
238
398
|
await space1.leave();
|
|
239
399
|
}
|
|
240
400
|
});
|
|
241
401
|
|
|
242
|
-
it(
|
|
402
|
+
it("should compute target position relative to other client positions", async () => {
|
|
243
403
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
244
404
|
const transportState = new GroupTransportState(playbackTrack);
|
|
245
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
405
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
406
|
+
transportState,
|
|
407
|
+
space1,
|
|
408
|
+
new TimeInterval(1000)
|
|
409
|
+
);
|
|
246
410
|
|
|
247
411
|
await space1.join();
|
|
248
412
|
await space2.join();
|
|
249
413
|
try {
|
|
250
|
-
assert(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
414
|
+
assert(
|
|
415
|
+
playbackPosition.targetPosition == 0.0,
|
|
416
|
+
`wrong starting position of ${playbackPosition.targetPosition}`
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
await transportState.updateState(
|
|
420
|
+
subtractSeconds(
|
|
421
|
+
2.0,
|
|
422
|
+
createTransportUpdate(space1, "playing", 0.0)
|
|
423
|
+
)
|
|
424
|
+
);
|
|
425
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
426
|
+
createPositionUpdate(space1, "playing", 0.0)
|
|
427
|
+
);
|
|
428
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
429
|
+
subtractSeconds(
|
|
430
|
+
1.0,
|
|
431
|
+
createPositionUpdate(space2, "playing", 0.0)
|
|
432
|
+
)
|
|
433
|
+
);
|
|
255
434
|
|
|
256
435
|
// We're sometimes getting back a target position of 0.999 instead of 1.0 (some sort of rounding error)
|
|
257
|
-
assert(
|
|
436
|
+
assert(
|
|
437
|
+
playbackPosition.targetPosition > 0.9 &&
|
|
438
|
+
playbackPosition.targetPosition < 2.0,
|
|
439
|
+
`wrong target position of ${playbackPosition.targetPosition}`
|
|
440
|
+
);
|
|
258
441
|
} finally {
|
|
259
442
|
await space1.leave();
|
|
260
443
|
await space2.leave();
|
|
261
444
|
}
|
|
262
445
|
});
|
|
263
446
|
|
|
264
|
-
it(
|
|
447
|
+
it("should limit max and target position by media duration", async () => {
|
|
265
448
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
266
449
|
const transportState = new GroupTransportState(playbackTrack);
|
|
267
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
450
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
451
|
+
transportState,
|
|
452
|
+
space1,
|
|
453
|
+
new TimeInterval(1000)
|
|
454
|
+
);
|
|
268
455
|
|
|
269
456
|
await space1.join();
|
|
270
457
|
await space2.join();
|
|
271
458
|
try {
|
|
272
|
-
await transportState.updateState(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
459
|
+
await transportState.updateState(
|
|
460
|
+
subtractSeconds(
|
|
461
|
+
2.0,
|
|
462
|
+
createTransportUpdate(space1, "playing", 0.0)
|
|
463
|
+
)
|
|
464
|
+
);
|
|
465
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
466
|
+
createPositionUpdate(space1, "playing", 0.0, undefined, 0.5)
|
|
467
|
+
);
|
|
468
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
469
|
+
subtractSeconds(
|
|
470
|
+
1.0,
|
|
471
|
+
createPositionUpdate(space2, "playing", 0.0, undefined, 0.5)
|
|
472
|
+
)
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
assert(
|
|
476
|
+
playbackPosition.maxPosition == 0.5,
|
|
477
|
+
`wrong max position ${playbackPosition.maxPosition}`
|
|
478
|
+
);
|
|
479
|
+
assert(
|
|
480
|
+
playbackPosition.targetPosition == 0.5,
|
|
481
|
+
`wrong target position ${playbackPosition.targetPosition}`
|
|
482
|
+
);
|
|
278
483
|
} finally {
|
|
279
484
|
await space1.leave();
|
|
280
485
|
await space2.leave();
|
|
281
486
|
}
|
|
282
487
|
});
|
|
283
488
|
|
|
284
|
-
it(
|
|
489
|
+
it("should count number of waiting clients", async () => {
|
|
285
490
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
286
491
|
const transportState = new GroupTransportState(playbackTrack);
|
|
287
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
492
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
493
|
+
transportState,
|
|
494
|
+
space1,
|
|
495
|
+
new TimeInterval(1000)
|
|
496
|
+
);
|
|
288
497
|
|
|
289
498
|
await space1.join();
|
|
290
499
|
await space2.join();
|
|
291
500
|
try {
|
|
292
|
-
await transportState.updateState(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
501
|
+
await transportState.updateState(
|
|
502
|
+
subtractSeconds(
|
|
503
|
+
2.0,
|
|
504
|
+
createTransportUpdate(space1, "playing", 0.0)
|
|
505
|
+
)
|
|
506
|
+
);
|
|
507
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
508
|
+
createPositionUpdate(space1, "suspended", 2.0, {
|
|
509
|
+
position: 2.0,
|
|
510
|
+
})
|
|
511
|
+
);
|
|
512
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
513
|
+
subtractSeconds(
|
|
514
|
+
1.0,
|
|
515
|
+
createPositionUpdate(space2, "playing", 0.0, undefined)
|
|
516
|
+
)
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
assert(
|
|
520
|
+
playbackPosition.clientsWaiting == 2,
|
|
521
|
+
`wrong count ${playbackPosition.clientsWaiting}`
|
|
522
|
+
);
|
|
297
523
|
} finally {
|
|
298
524
|
await space1.leave();
|
|
299
525
|
await space2.leave();
|
|
300
526
|
}
|
|
301
527
|
});
|
|
302
528
|
|
|
303
|
-
it(
|
|
529
|
+
it("should drop waiting count after suspension ends", async () => {
|
|
304
530
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
305
531
|
const transportState = new GroupTransportState(playbackTrack);
|
|
306
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
532
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
533
|
+
transportState,
|
|
534
|
+
space1,
|
|
535
|
+
new TimeInterval(1000)
|
|
536
|
+
);
|
|
307
537
|
|
|
308
538
|
await space1.join();
|
|
309
539
|
await space2.join();
|
|
310
540
|
try {
|
|
311
|
-
await transportState.updateState(
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
541
|
+
await transportState.updateState(
|
|
542
|
+
subtractSeconds(
|
|
543
|
+
2.0,
|
|
544
|
+
createTransportUpdate(space1, "playing", 0.0)
|
|
545
|
+
)
|
|
546
|
+
);
|
|
547
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
548
|
+
createPositionUpdate(space1, "waiting", 2.0, { position: 2.0 })
|
|
549
|
+
);
|
|
550
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
551
|
+
createPositionUpdate(space2, "suspended", 2.0, {
|
|
552
|
+
position: 2.0,
|
|
553
|
+
})
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
assert(
|
|
557
|
+
playbackPosition.clientsWaiting == 1,
|
|
558
|
+
`wrong count ${playbackPosition.clientsWaiting}`
|
|
559
|
+
);
|
|
316
560
|
} finally {
|
|
317
561
|
await space1.leave();
|
|
318
562
|
await space2.leave();
|
|
319
563
|
}
|
|
320
564
|
});
|
|
321
565
|
|
|
322
|
-
it(
|
|
566
|
+
it("should drop waiting count to 0 after all clients reach wait point", async () => {
|
|
323
567
|
const playbackTrack = new GroupPlaybackTrack(() => track1);
|
|
324
568
|
const transportState = new GroupTransportState(playbackTrack);
|
|
325
|
-
const playbackPosition = new GroupPlaybackPosition(
|
|
569
|
+
const playbackPosition = new GroupPlaybackPosition(
|
|
570
|
+
transportState,
|
|
571
|
+
space1,
|
|
572
|
+
new TimeInterval(1000)
|
|
573
|
+
);
|
|
326
574
|
|
|
327
575
|
await space1.join();
|
|
328
576
|
await space2.join();
|
|
329
577
|
try {
|
|
330
|
-
await transportState.updateState(
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
578
|
+
await transportState.updateState(
|
|
579
|
+
subtractSeconds(
|
|
580
|
+
2.0,
|
|
581
|
+
createTransportUpdate(space1, "playing", 0.0)
|
|
582
|
+
)
|
|
583
|
+
);
|
|
584
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
585
|
+
createPositionUpdate(space1, "waiting", 2.0, { position: 2.0 })
|
|
586
|
+
);
|
|
587
|
+
await playbackPosition.UpdatePlaybackPosition(
|
|
588
|
+
createPositionUpdate(space2, "waiting", 2.0, { position: 2.0 })
|
|
589
|
+
);
|
|
590
|
+
|
|
591
|
+
assert(
|
|
592
|
+
playbackPosition.clientsWaiting == 0,
|
|
593
|
+
`wrong count ${playbackPosition.clientsWaiting}`
|
|
594
|
+
);
|
|
335
595
|
} finally {
|
|
336
596
|
await space1.leave();
|
|
337
597
|
await space2.leave();
|
|
338
598
|
}
|
|
339
599
|
});
|
|
340
|
-
});
|
|
600
|
+
});
|