@microsoft/live-share-media 1.0.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/LiveMediaSession.d.ts +9 -10
- package/bin/LiveMediaSession.d.ts.map +1 -1
- package/bin/LiveMediaSession.js +35 -17
- package/bin/LiveMediaSession.js.map +1 -1
- package/bin/LiveMediaSessionCoordinator.d.ts +8 -3
- package/bin/LiveMediaSessionCoordinator.d.ts.map +1 -1
- package/bin/LiveMediaSessionCoordinator.js +19 -27
- package/bin/LiveMediaSessionCoordinator.js.map +1 -1
- package/bin/MediaPlayerSynchronizer.d.ts +3 -2
- package/bin/MediaPlayerSynchronizer.d.ts.map +1 -1
- package/bin/MediaPlayerSynchronizer.js +46 -36
- package/bin/MediaPlayerSynchronizer.js.map +1 -1
- package/bin/MediaSessionActionThrottler.d.ts +2 -2
- package/bin/MediaSessionActionThrottler.d.ts.map +1 -1
- package/bin/MediaSessionActionThrottler.js.map +1 -1
- package/bin/MediaSessionExtensions.d.ts +4 -0
- package/bin/MediaSessionExtensions.d.ts.map +1 -1
- package/bin/RepeatedActionThrottler.d.ts +1 -1
- package/bin/RepeatedActionThrottler.d.ts.map +1 -1
- package/bin/RepeatedActionThrottler.js.map +1 -1
- package/bin/internals/GroupCoordinatorState.d.ts +1 -1
- package/bin/internals/GroupCoordinatorState.d.ts.map +1 -1
- package/bin/internals/GroupCoordinatorState.js +23 -6
- package/bin/internals/GroupCoordinatorState.js.map +1 -1
- package/bin/internals/GroupPlaybackTrack.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackTrack.js +1 -0
- package/bin/internals/GroupPlaybackTrack.js.map +1 -1
- package/bin/internals/GroupPlaybackTrackData.d.ts.map +1 -1
- package/bin/internals/GroupPlaybackTrackData.js +1 -0
- package/bin/internals/GroupPlaybackTrackData.js.map +1 -1
- package/bin/internals/GroupTransportState.d.ts.map +1 -1
- package/bin/internals/GroupTransportState.js +3 -0
- package/bin/internals/GroupTransportState.js.map +1 -1
- package/package.json +4 -4
- package/src/LiveMediaSession.ts +42 -19
- package/src/LiveMediaSessionCoordinator.ts +22 -34
- package/src/MediaPlayerSynchronizer.ts +51 -43
- package/src/MediaSessionActionThrottler.ts +6 -3
- package/src/MediaSessionExtensions.ts +5 -0
- package/src/RepeatedActionThrottler.ts +4 -2
- package/src/internals/GroupCoordinatorState.ts +30 -7
- package/src/internals/GroupPlaybackTrack.ts +1 -0
- package/src/internals/GroupPlaybackTrackData.ts +1 -0
- package/src/internals/GroupTransportState.ts +4 -5
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
LiveTelemetryLogger,
|
|
7
|
+
ILiveEvent,
|
|
8
|
+
IRuntimeSignaler,
|
|
9
|
+
} from "@microsoft/live-share";
|
|
6
10
|
import EventEmitter from "events";
|
|
7
11
|
import {
|
|
8
12
|
ExtendedMediaSessionAction,
|
|
@@ -17,6 +21,7 @@ import { VolumeManager } from "./VolumeManager";
|
|
|
17
21
|
import { LiveMediaSession } from "./LiveMediaSession";
|
|
18
22
|
import { IMediaPlayer } from "./IMediaPlayer";
|
|
19
23
|
import { TelemetryEvents } from "./internals";
|
|
24
|
+
import { waitUntilConnected } from "@microsoft/live-share/bin/internals";
|
|
20
25
|
|
|
21
26
|
/**
|
|
22
27
|
* Event data returned by `MediaPlayerSynchronizer` object.
|
|
@@ -76,6 +81,7 @@ export class MediaPlayerSynchronizer extends EventEmitter {
|
|
|
76
81
|
private _logger: LiveTelemetryLogger;
|
|
77
82
|
private _player: IMediaPlayer;
|
|
78
83
|
private _mediaSession: LiveMediaSession;
|
|
84
|
+
private _runtime: IRuntimeSignaler;
|
|
79
85
|
private _volumeManager: VolumeManager;
|
|
80
86
|
private _onEnd?: () => void;
|
|
81
87
|
private _onPlayerEvent: EventListener;
|
|
@@ -94,11 +100,13 @@ export class MediaPlayerSynchronizer extends EventEmitter {
|
|
|
94
100
|
constructor(
|
|
95
101
|
player: IMediaPlayer,
|
|
96
102
|
mediaSession: LiveMediaSession,
|
|
103
|
+
runtime: IRuntimeSignaler,
|
|
97
104
|
onEnd: () => void
|
|
98
105
|
) {
|
|
99
106
|
super();
|
|
100
107
|
this._player = player;
|
|
101
108
|
this._mediaSession = mediaSession;
|
|
109
|
+
this._runtime = runtime;
|
|
102
110
|
this._logger = mediaSession.logger;
|
|
103
111
|
this._volumeManager = new VolumeManager(player);
|
|
104
112
|
this._onEnd = onEnd;
|
|
@@ -352,7 +360,7 @@ export class MediaPlayerSynchronizer extends EventEmitter {
|
|
|
352
360
|
}
|
|
353
361
|
}
|
|
354
362
|
|
|
355
|
-
this.dispatchGroupAction(details,
|
|
363
|
+
this.dispatchGroupAction(details, error);
|
|
356
364
|
}
|
|
357
365
|
);
|
|
358
366
|
}
|
|
@@ -513,7 +521,13 @@ export class MediaPlayerSynchronizer extends EventEmitter {
|
|
|
513
521
|
);
|
|
514
522
|
suspension.end(seekTo);
|
|
515
523
|
|
|
516
|
-
this.
|
|
524
|
+
waitUntilConnected(this._runtime).then((clientId: string) => {
|
|
525
|
+
this.dispatchUserAction({
|
|
526
|
+
action: "seekto",
|
|
527
|
+
clientId,
|
|
528
|
+
seekTime: seekTo,
|
|
529
|
+
});
|
|
530
|
+
});
|
|
517
531
|
}
|
|
518
532
|
|
|
519
533
|
/**
|
|
@@ -532,7 +546,10 @@ export class MediaPlayerSynchronizer extends EventEmitter {
|
|
|
532
546
|
this._expectedPlaybackState = "playing";
|
|
533
547
|
await this._mediaSession.coordinator.play();
|
|
534
548
|
|
|
535
|
-
this.dispatchUserAction({
|
|
549
|
+
this.dispatchUserAction({
|
|
550
|
+
action: "play",
|
|
551
|
+
clientId: await waitUntilConnected(this._runtime),
|
|
552
|
+
});
|
|
536
553
|
}
|
|
537
554
|
|
|
538
555
|
/**
|
|
@@ -551,7 +568,10 @@ export class MediaPlayerSynchronizer extends EventEmitter {
|
|
|
551
568
|
this._expectedPlaybackState = "paused";
|
|
552
569
|
await this._mediaSession.coordinator.pause();
|
|
553
570
|
|
|
554
|
-
this.dispatchUserAction({
|
|
571
|
+
this.dispatchUserAction({
|
|
572
|
+
action: "pause",
|
|
573
|
+
clientId: await waitUntilConnected(this._runtime),
|
|
574
|
+
});
|
|
555
575
|
}
|
|
556
576
|
|
|
557
577
|
/**
|
|
@@ -576,7 +596,11 @@ export class MediaPlayerSynchronizer extends EventEmitter {
|
|
|
576
596
|
);
|
|
577
597
|
await this._mediaSession.coordinator.seekTo(time);
|
|
578
598
|
|
|
579
|
-
this.dispatchUserAction({
|
|
599
|
+
this.dispatchUserAction({
|
|
600
|
+
action: "seekto",
|
|
601
|
+
clientId: await waitUntilConnected(this._runtime),
|
|
602
|
+
seekTime: time,
|
|
603
|
+
});
|
|
580
604
|
}
|
|
581
605
|
|
|
582
606
|
/**
|
|
@@ -597,7 +621,11 @@ export class MediaPlayerSynchronizer extends EventEmitter {
|
|
|
597
621
|
);
|
|
598
622
|
await this._mediaSession.coordinator.setTrack(track, waitPoints);
|
|
599
623
|
|
|
600
|
-
this.dispatchUserAction({
|
|
624
|
+
this.dispatchUserAction({
|
|
625
|
+
action: "settrack",
|
|
626
|
+
clientId: await waitUntilConnected(this._runtime),
|
|
627
|
+
metadata: track,
|
|
628
|
+
});
|
|
601
629
|
}
|
|
602
630
|
|
|
603
631
|
/**
|
|
@@ -616,52 +644,32 @@ export class MediaPlayerSynchronizer extends EventEmitter {
|
|
|
616
644
|
this._trackData = data;
|
|
617
645
|
await this._mediaSession.coordinator.setTrackData(data);
|
|
618
646
|
|
|
619
|
-
this.dispatchUserAction({
|
|
647
|
+
this.dispatchUserAction({
|
|
648
|
+
action: "datachange",
|
|
649
|
+
clientId: await waitUntilConnected(this._runtime),
|
|
650
|
+
data: data,
|
|
651
|
+
});
|
|
620
652
|
}
|
|
621
653
|
|
|
654
|
+
// TODO: what is delay useful for? we do not use, delete?
|
|
622
655
|
private dispatchGroupAction(
|
|
623
656
|
details: ExtendedMediaSessionActionDetails,
|
|
624
|
-
delay = false,
|
|
625
657
|
error: Error | undefined
|
|
626
658
|
): void {
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
details: details,
|
|
633
|
-
playerError: error,
|
|
634
|
-
}),
|
|
635
|
-
50
|
|
636
|
-
);
|
|
637
|
-
} else {
|
|
638
|
-
this.emit(MediaPlayerSynchronizerEvents.groupaction, {
|
|
639
|
-
type: MediaPlayerSynchronizerEvents.groupaction,
|
|
640
|
-
details: details,
|
|
641
|
-
error,
|
|
642
|
-
});
|
|
643
|
-
}
|
|
659
|
+
this.emit(MediaPlayerSynchronizerEvents.groupaction, {
|
|
660
|
+
type: MediaPlayerSynchronizerEvents.groupaction,
|
|
661
|
+
details: details,
|
|
662
|
+
error,
|
|
663
|
+
});
|
|
644
664
|
}
|
|
645
665
|
|
|
646
666
|
private dispatchUserAction(
|
|
647
|
-
details: ExtendedMediaSessionActionDetails
|
|
648
|
-
delay = false
|
|
667
|
+
details: ExtendedMediaSessionActionDetails
|
|
649
668
|
): void {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
type: MediaPlayerSynchronizerEvents.useraction,
|
|
655
|
-
details: details,
|
|
656
|
-
}),
|
|
657
|
-
50
|
|
658
|
-
);
|
|
659
|
-
} else {
|
|
660
|
-
this.emit(MediaPlayerSynchronizerEvents.useraction, {
|
|
661
|
-
type: MediaPlayerSynchronizerEvents.useraction,
|
|
662
|
-
details: details,
|
|
663
|
-
});
|
|
664
|
-
}
|
|
669
|
+
this.emit(MediaPlayerSynchronizerEvents.useraction, {
|
|
670
|
+
type: MediaPlayerSynchronizerEvents.useraction,
|
|
671
|
+
details: details,
|
|
672
|
+
});
|
|
665
673
|
}
|
|
666
674
|
|
|
667
675
|
private async catchupPlayer(time: number): Promise<void> {
|
|
@@ -3,14 +3,17 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ExtendedMediaSessionActionDetails,
|
|
8
|
+
ExtendedMediaSessionActionHandler,
|
|
9
|
+
} from "./MediaSessionExtensions";
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Base class for action throttlers.
|
|
10
13
|
*/
|
|
11
14
|
export abstract class MediaSessionActionThrottler {
|
|
12
15
|
public abstract throttled(
|
|
13
|
-
details: ExtendedMediaSessionActionDetails,
|
|
14
|
-
handler?: MediaSessionActionHandler
|
|
16
|
+
details: MediaSessionActionDetails | ExtendedMediaSessionActionDetails,
|
|
17
|
+
handler?: MediaSessionActionHandler | ExtendedMediaSessionActionHandler
|
|
15
18
|
): void;
|
|
16
19
|
}
|
|
@@ -42,6 +42,7 @@ export interface CoordinationWaitPoint {
|
|
|
42
42
|
|
|
43
43
|
export interface ExtendedMediaSessionActionDetails {
|
|
44
44
|
action: ExtendedMediaSessionAction;
|
|
45
|
+
clientId: string;
|
|
45
46
|
fastSeek?: boolean | null;
|
|
46
47
|
seekOffset?: number | null;
|
|
47
48
|
seekTime?: number | null;
|
|
@@ -50,3 +51,7 @@ export interface ExtendedMediaSessionActionDetails {
|
|
|
50
51
|
data?: object | null;
|
|
51
52
|
blocked?: ExtendedMediaSessionAction | null;
|
|
52
53
|
}
|
|
54
|
+
|
|
55
|
+
export interface ExtendedMediaSessionActionHandler {
|
|
56
|
+
(details: ExtendedMediaSessionActionDetails): void;
|
|
57
|
+
}
|
|
@@ -33,7 +33,7 @@ export class RepeatedActionThrottler extends MediaSessionActionThrottler {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
public throttled(
|
|
36
|
-
details: ExtendedMediaSessionActionDetails,
|
|
36
|
+
details: MediaSessionActionDetails | ExtendedMediaSessionActionDetails,
|
|
37
37
|
handler?: MediaSessionActionHandler
|
|
38
38
|
): void {
|
|
39
39
|
if (handler) {
|
|
@@ -63,7 +63,9 @@ export class RepeatedActionThrottler extends MediaSessionActionThrottler {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
private getChangeKey(
|
|
66
|
+
private getChangeKey(
|
|
67
|
+
details: MediaSessionActionDetails | ExtendedMediaSessionActionDetails
|
|
68
|
+
): string {
|
|
67
69
|
switch (details.action) {
|
|
68
70
|
case "seekto":
|
|
69
71
|
return `seekto:${details.seekTime}`;
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
IPlaybackTrackData,
|
|
37
37
|
} from "./GroupPlaybackTrackData";
|
|
38
38
|
import { TelemetryEvents } from "./consts";
|
|
39
|
+
import { waitUntilConnected } from "@microsoft/live-share/bin/internals";
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* @hidden
|
|
@@ -149,7 +150,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
149
150
|
this._logger.sendTelemetryEvent(
|
|
150
151
|
TelemetryEvents.GroupCoordinator.TrackChanged
|
|
151
152
|
);
|
|
152
|
-
this.emitSetTrack(evt.metadata!);
|
|
153
|
+
this.emitSetTrack(evt.clientId, evt.metadata!);
|
|
153
154
|
} else {
|
|
154
155
|
this._logger.sendTelemetryEvent(
|
|
155
156
|
TelemetryEvents.GroupCoordinator.TrackChangeDelayed
|
|
@@ -168,6 +169,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
168
169
|
this.emitTriggerAction({
|
|
169
170
|
action: "datachange",
|
|
170
171
|
data: evt.data,
|
|
172
|
+
clientId: evt.clientId,
|
|
171
173
|
});
|
|
172
174
|
} else {
|
|
173
175
|
this._logger.sendTelemetryEvent(
|
|
@@ -196,6 +198,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
196
198
|
case "play":
|
|
197
199
|
this.emitTriggerAction({
|
|
198
200
|
action: "play",
|
|
201
|
+
clientId: evt.clientId,
|
|
199
202
|
seekTime: evt.seekTime,
|
|
200
203
|
});
|
|
201
204
|
break;
|
|
@@ -203,6 +206,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
203
206
|
case "pause":
|
|
204
207
|
this.emitTriggerAction({
|
|
205
208
|
action: "pause",
|
|
209
|
+
clientId: evt.clientId,
|
|
206
210
|
seekTime: evt.seekTime,
|
|
207
211
|
});
|
|
208
212
|
break;
|
|
@@ -210,6 +214,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
210
214
|
case "seekto":
|
|
211
215
|
this.emitTriggerAction({
|
|
212
216
|
action: "seekto",
|
|
217
|
+
clientId: evt.clientId,
|
|
213
218
|
seekTime: evt.seekTime,
|
|
214
219
|
});
|
|
215
220
|
break;
|
|
@@ -431,7 +436,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
431
436
|
}
|
|
432
437
|
|
|
433
438
|
public handlePositionUpdate(
|
|
434
|
-
event:
|
|
439
|
+
event: ILiveEvent<IPositionUpdateEvent>,
|
|
435
440
|
local: boolean
|
|
436
441
|
): void {
|
|
437
442
|
// Ensure change is for current track
|
|
@@ -522,7 +527,10 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
522
527
|
this._logger.sendTelemetryEvent(
|
|
523
528
|
TelemetryEvents.GroupCoordinator.TrackOutOfSync
|
|
524
529
|
);
|
|
525
|
-
this.emitSetTrack(
|
|
530
|
+
this.emitSetTrack(
|
|
531
|
+
this.playbackTrack.current.clientId,
|
|
532
|
+
this.playbackTrack.metadata!
|
|
533
|
+
);
|
|
526
534
|
return;
|
|
527
535
|
}
|
|
528
536
|
|
|
@@ -560,6 +568,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
560
568
|
);
|
|
561
569
|
await this.emitTriggerAction({
|
|
562
570
|
action: "catchup",
|
|
571
|
+
clientId: await waitUntilConnected(this._runtime),
|
|
563
572
|
seekTime: target,
|
|
564
573
|
});
|
|
565
574
|
}
|
|
@@ -576,10 +585,16 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
576
585
|
);
|
|
577
586
|
switch (this.transportState.playbackState) {
|
|
578
587
|
case "playing":
|
|
579
|
-
await this.emitTriggerAction({
|
|
588
|
+
await this.emitTriggerAction({
|
|
589
|
+
action: "play",
|
|
590
|
+
clientId: this.transportState.current.clientId,
|
|
591
|
+
});
|
|
580
592
|
break;
|
|
581
593
|
case "paused":
|
|
582
|
-
await this.emitTriggerAction({
|
|
594
|
+
await this.emitTriggerAction({
|
|
595
|
+
action: "pause",
|
|
596
|
+
clientId: this.transportState.current.clientId,
|
|
597
|
+
});
|
|
583
598
|
break;
|
|
584
599
|
}
|
|
585
600
|
}
|
|
@@ -594,6 +609,7 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
594
609
|
);
|
|
595
610
|
await this.emitTriggerAction({
|
|
596
611
|
action: "datachange",
|
|
612
|
+
clientId: this.playbackTrackData.current.clientId,
|
|
597
613
|
data: this.playbackTrackData.data,
|
|
598
614
|
});
|
|
599
615
|
}
|
|
@@ -601,12 +617,19 @@ export class GroupCoordinatorState extends EventEmitter {
|
|
|
601
617
|
}
|
|
602
618
|
}
|
|
603
619
|
|
|
604
|
-
private emitSetTrack(
|
|
620
|
+
private emitSetTrack(
|
|
621
|
+
clientId: string,
|
|
622
|
+
metadata: ExtendedMediaMetadata
|
|
623
|
+
): void {
|
|
605
624
|
// Reset tracking states
|
|
606
625
|
this._waitPoint = undefined;
|
|
607
626
|
|
|
608
627
|
// Trigger settrack action
|
|
609
|
-
this.emitTriggerAction({
|
|
628
|
+
this.emitTriggerAction({
|
|
629
|
+
action: "settrack",
|
|
630
|
+
clientId,
|
|
631
|
+
metadata,
|
|
632
|
+
});
|
|
610
633
|
}
|
|
611
634
|
|
|
612
635
|
private emitTriggerAction(
|
|
@@ -3,11 +3,7 @@
|
|
|
3
3
|
* Licensed under the Microsoft Live Share SDK License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
ILiveEvent,
|
|
8
|
-
LiveShareRuntime,
|
|
9
|
-
LiveShareClient,
|
|
10
|
-
} from "@microsoft/live-share";
|
|
6
|
+
import { ILiveEvent, LiveShareRuntime } from "@microsoft/live-share";
|
|
11
7
|
import EventEmitter from "events";
|
|
12
8
|
import { IMediaPlayerState } from "../LiveMediaSessionCoordinator";
|
|
13
9
|
import {
|
|
@@ -140,6 +136,7 @@ export class GroupTransportState extends EventEmitter {
|
|
|
140
136
|
this.emit(GroupTransportStateEvents.transportStateChange, {
|
|
141
137
|
type: GroupTransportStateEvents.transportStateChange,
|
|
142
138
|
action: "seekto",
|
|
139
|
+
clientId: state.clientId,
|
|
143
140
|
seekTime: state.startPosition,
|
|
144
141
|
});
|
|
145
142
|
} else if (state.playbackState == "playing") {
|
|
@@ -149,12 +146,14 @@ export class GroupTransportState extends EventEmitter {
|
|
|
149
146
|
this.emit(GroupTransportStateEvents.transportStateChange, {
|
|
150
147
|
type: GroupTransportStateEvents.transportStateChange,
|
|
151
148
|
action: "play",
|
|
149
|
+
clientId: state.clientId,
|
|
152
150
|
seekTime: projectedPosition,
|
|
153
151
|
});
|
|
154
152
|
} else {
|
|
155
153
|
this.emit(GroupTransportStateEvents.transportStateChange, {
|
|
156
154
|
type: GroupTransportStateEvents.transportStateChange,
|
|
157
155
|
action: "pause",
|
|
156
|
+
clientId: state.clientId,
|
|
158
157
|
seekTime: state.startPosition,
|
|
159
158
|
});
|
|
160
159
|
}
|