@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.
Files changed (96) hide show
  1. package/README.md +2 -1
  2. package/bin/IMediaPlayer.d.ts.map +1 -1
  3. package/bin/LiveMediaSession.d.ts +7 -7
  4. package/bin/LiveMediaSession.d.ts.map +1 -1
  5. package/bin/LiveMediaSession.js +28 -17
  6. package/bin/LiveMediaSession.js.map +1 -1
  7. package/bin/LiveMediaSessionCoordinator.d.ts +2 -2
  8. package/bin/LiveMediaSessionCoordinator.d.ts.map +1 -1
  9. package/bin/LiveMediaSessionCoordinator.js +34 -22
  10. package/bin/LiveMediaSessionCoordinator.js.map +1 -1
  11. package/bin/LiveMediaSessionCoordinatorSuspension.d.ts +1 -1
  12. package/bin/LiveMediaSessionCoordinatorSuspension.d.ts.map +1 -1
  13. package/bin/LiveMediaSessionCoordinatorSuspension.js.map +1 -1
  14. package/bin/MediaPlayerSynchronizer.d.ts +7 -7
  15. package/bin/MediaPlayerSynchronizer.d.ts.map +1 -1
  16. package/bin/MediaPlayerSynchronizer.js +127 -72
  17. package/bin/MediaPlayerSynchronizer.js.map +1 -1
  18. package/bin/MediaSessionActionThrottler.d.ts +1 -1
  19. package/bin/MediaSessionActionThrottler.d.ts.map +1 -1
  20. package/bin/MediaSessionActionThrottler.js.map +1 -1
  21. package/bin/MediaSessionExtensions.d.ts.map +1 -1
  22. package/bin/RepeatedActionThrottler.d.ts +2 -2
  23. package/bin/RepeatedActionThrottler.d.ts.map +1 -1
  24. package/bin/RepeatedActionThrottler.js +9 -3
  25. package/bin/RepeatedActionThrottler.js.map +1 -1
  26. package/bin/VolumeManager.d.ts +1 -1
  27. package/bin/VolumeManager.d.ts.map +1 -1
  28. package/bin/VolumeManager.js +4 -2
  29. package/bin/VolumeManager.js.map +1 -1
  30. package/bin/index.d.ts +9 -9
  31. package/bin/index.d.ts.map +1 -1
  32. package/bin/index.js.map +1 -1
  33. package/bin/internals/GroupCoordinatorState.d.ts +8 -8
  34. package/bin/internals/GroupCoordinatorState.d.ts.map +1 -1
  35. package/bin/internals/GroupCoordinatorState.js +91 -53
  36. package/bin/internals/GroupCoordinatorState.js.map +1 -1
  37. package/bin/internals/GroupPlaybackPosition.d.ts +3 -3
  38. package/bin/internals/GroupPlaybackPosition.d.ts.map +1 -1
  39. package/bin/internals/GroupPlaybackPosition.js +22 -13
  40. package/bin/internals/GroupPlaybackPosition.js.map +1 -1
  41. package/bin/internals/GroupPlaybackTrack.d.ts +4 -4
  42. package/bin/internals/GroupPlaybackTrack.d.ts.map +1 -1
  43. package/bin/internals/GroupPlaybackTrack.js +14 -4
  44. package/bin/internals/GroupPlaybackTrack.js.map +1 -1
  45. package/bin/internals/GroupPlaybackTrackData.d.ts +3 -3
  46. package/bin/internals/GroupPlaybackTrackData.d.ts.map +1 -1
  47. package/bin/internals/GroupPlaybackTrackData.js +8 -4
  48. package/bin/internals/GroupPlaybackTrackData.js.map +1 -1
  49. package/bin/internals/GroupTransportState.d.ts +5 -5
  50. package/bin/internals/GroupTransportState.d.ts.map +1 -1
  51. package/bin/internals/GroupTransportState.js +27 -12
  52. package/bin/internals/GroupTransportState.js.map +1 -1
  53. package/bin/internals/consts.d.ts.map +1 -1
  54. package/bin/internals/consts.js +54 -54
  55. package/bin/internals/consts.js.map +1 -1
  56. package/bin/internals/index.d.ts +6 -6
  57. package/package.json +3 -3
  58. package/src/IMediaPlayer.ts +10 -2
  59. package/src/LiveMediaSession.ts +133 -71
  60. package/src/LiveMediaSessionCoordinator.ts +302 -142
  61. package/src/LiveMediaSessionCoordinatorSuspension.ts +13 -5
  62. package/src/MediaPlayerSynchronizer.ts +329 -149
  63. package/src/MediaSessionActionThrottler.ts +5 -3
  64. package/src/MediaSessionExtensions.ts +15 -5
  65. package/src/RepeatedActionThrottler.ts +27 -9
  66. package/src/VolumeManager.ts +24 -12
  67. package/src/index.ts +9 -10
  68. package/src/internals/GroupCoordinatorState.ts +274 -114
  69. package/src/internals/GroupPlaybackPosition.ts +61 -27
  70. package/src/internals/GroupPlaybackTrack.ts +51 -22
  71. package/src/internals/GroupPlaybackTrackData.ts +24 -16
  72. package/src/internals/GroupTransportState.ts +53 -23
  73. package/src/internals/consts.ts +73 -55
  74. package/src/internals/index.ts +6 -6
  75. package/src/test/GroupPlaybackPosition.spec.ts +371 -111
  76. package/src/test/GroupPlaybackTrack.spec.ts +91 -35
  77. package/src/test/SharedMediaSession.spec.ts +64 -28
  78. package/src/test/SharedMediaSessionCoordinator.spec.ts +86 -46
  79. package/src/test/VolumeManager.spec.ts +38 -31
  80. package/tsconfig.json +1 -0
  81. package/bin/EphemeralMediaSession.d.ts +0 -102
  82. package/bin/EphemeralMediaSession.d.ts.map +0 -1
  83. package/bin/EphemeralMediaSession.js +0 -226
  84. package/bin/EphemeralMediaSession.js.map +0 -1
  85. package/bin/EphemeralMediaSessionCoordinator.d.ts +0 -228
  86. package/bin/EphemeralMediaSessionCoordinator.d.ts.map +0 -1
  87. package/bin/EphemeralMediaSessionCoordinator.js +0 -396
  88. package/bin/EphemeralMediaSessionCoordinator.js.map +0 -1
  89. package/bin/EphemeralMediaSessionCoordinatorSuspension.d.ts +0 -20
  90. package/bin/EphemeralMediaSessionCoordinatorSuspension.d.ts.map +0 -1
  91. package/bin/EphemeralMediaSessionCoordinatorSuspension.js +0 -28
  92. package/bin/EphemeralMediaSessionCoordinatorSuspension.js.map +0 -1
  93. package/bin/VolumeLimiter.d.ts +0 -70
  94. package/bin/VolumeLimiter.d.ts.map +0 -1
  95. package/bin/VolumeLimiter.js +0 -170
  96. package/bin/VolumeLimiter.js.map +0 -1
@@ -3,10 +3,17 @@
3
3
  * Licensed under the Microsoft Live Share SDK License.
4
4
  */
5
5
 
6
- import { LiveEvent, IRuntimeSignaler, TimeInterval } from '@microsoft/live-share';
7
- import { GroupTransportState } from './GroupTransportState';
8
- import { GroupPlaybackTrackEvents } from './GroupPlaybackTrack';
9
- import { CoordinationWaitPoint, ExtendedMediaSessionPlaybackState } from '../MediaSessionExtensions';
6
+ import {
7
+ LiveEvent,
8
+ IRuntimeSignaler,
9
+ TimeInterval,
10
+ } from "@microsoft/live-share";
11
+ import { GroupTransportState } from "./GroupTransportState";
12
+ import { GroupPlaybackTrackEvents } from "./GroupPlaybackTrack";
13
+ import {
14
+ CoordinationWaitPoint,
15
+ ExtendedMediaSessionPlaybackState,
16
+ } from "../MediaSessionExtensions";
10
17
 
11
18
  /**
12
19
  *Per client position
@@ -14,7 +21,7 @@ import { CoordinationWaitPoint, ExtendedMediaSessionPlaybackState } from '../Med
14
21
  */
15
22
  export interface ICurrentPlaybackPosition {
16
23
  playbackState: ExtendedMediaSessionPlaybackState;
17
- waitPoint?: CoordinationWaitPoint
24
+ waitPoint?: CoordinationWaitPoint;
18
25
  position: number;
19
26
  duration?: number;
20
27
  timestamp: number;
@@ -30,25 +37,31 @@ export class GroupPlaybackPosition {
30
37
  private _updateInterval: TimeInterval;
31
38
  private _positions: Map<string, ICurrentPlaybackPosition>;
32
39
 
33
-
34
- constructor(transportState: GroupTransportState, runtime: IRuntimeSignaler, updateInterval: TimeInterval) {
40
+ constructor(
41
+ transportState: GroupTransportState,
42
+ runtime: IRuntimeSignaler,
43
+ updateInterval: TimeInterval
44
+ ) {
35
45
  this._transportState = transportState;
36
46
  this._runtime = runtime;
37
47
  this._updateInterval = updateInterval;
38
48
  this._positions = new Map();
39
49
 
40
50
  // Listen for track change
41
- this._transportState.track.on(GroupPlaybackTrackEvents.trackChange, _ => {
42
- // Reset position tracking and duration
43
- this._positions = new Map();
44
- this.mediaDuration = undefined;
45
- });
51
+ this._transportState.track.on(
52
+ GroupPlaybackTrackEvents.trackChange,
53
+ (_) => {
54
+ // Reset position tracking and duration
55
+ this._positions = new Map();
56
+ this.mediaDuration = undefined;
57
+ }
58
+ );
46
59
  }
47
60
 
48
61
  /**
49
62
  * Returns the latest position info for the local client.
50
63
  */
51
- public get localPosition(): ICurrentPlaybackPosition|undefined {
64
+ public get localPosition(): ICurrentPlaybackPosition | undefined {
52
65
  return this._positions.get(this._runtime.clientId!);
53
66
  }
54
67
 
@@ -57,7 +70,7 @@ export class GroupPlaybackPosition {
57
70
  */
58
71
  public get totalClients(): number {
59
72
  let cnt = 0;
60
- this.forEach(_ => cnt++);
73
+ this.forEach((_) => cnt++);
61
74
  return cnt;
62
75
  }
63
76
 
@@ -69,8 +82,8 @@ export class GroupPlaybackPosition {
69
82
  let playing = 0;
70
83
  this.forEach((position, projectedPosition) => {
71
84
  switch (position.playbackState) {
72
- case 'none':
73
- case 'ended':
85
+ case "none":
86
+ case "ended":
74
87
  // not playing.
75
88
  break;
76
89
  default:
@@ -88,9 +101,16 @@ export class GroupPlaybackPosition {
88
101
  public get clientsWaiting(): number {
89
102
  let cnt = 0;
90
103
  const waitPoint = this.localPosition?.waitPoint;
91
- if (waitPoint && (waitPoint.maxClients == undefined || this.totalClients <= waitPoint.maxClients)) {
104
+ if (
105
+ waitPoint &&
106
+ (waitPoint.maxClients == undefined ||
107
+ this.totalClients <= waitPoint.maxClients)
108
+ ) {
92
109
  this.forEach((position, projectedPosition) => {
93
- if (position.playbackState == 'suspended' && position.waitPoint) {
110
+ if (
111
+ position.playbackState == "suspended" &&
112
+ position.waitPoint
113
+ ) {
94
114
  cnt++;
95
115
  } else if (position.position < waitPoint.position) {
96
116
  cnt++;
@@ -108,9 +128,11 @@ export class GroupPlaybackPosition {
108
128
  * This is called when calculating the current seekTo position.
109
129
  */
110
130
  public get maxPosition(): number {
111
- if (this._transportState.playbackState == 'playing') {
131
+ if (this._transportState.playbackState == "playing") {
112
132
  const now = LiveEvent.getTimestamp();
113
- const projected = this._transportState.startPosition + ((now - this._transportState.timestamp) / 1000);
133
+ const projected =
134
+ this._transportState.startPosition +
135
+ (now - this._transportState.timestamp) / 1000;
114
136
  return this.limitProjectedPosition(projected);
115
137
  } else {
116
138
  return this._transportState.startPosition;
@@ -123,21 +145,25 @@ export class GroupPlaybackPosition {
123
145
  public mediaDuration?: number;
124
146
 
125
147
  public get targetPosition(): number {
126
- if (this._transportState.playbackState == 'playing') {
148
+ if (this._transportState.playbackState == "playing") {
127
149
  return this.getMostProgressedPosition();
128
150
  } else {
129
151
  return this._transportState.startPosition;
130
152
  }
131
153
  }
132
154
 
133
-
134
155
  /**
135
156
  * Enumerates every reported playback position.
136
157
  * @param callbackFn Function applied to each position,
137
158
  */
138
- public forEach(callbackFn: (position: ICurrentPlaybackPosition, projectedPosition: number) => void): void {
159
+ public forEach(
160
+ callbackFn: (
161
+ position: ICurrentPlaybackPosition,
162
+ projectedPosition: number
163
+ ) => void
164
+ ): void {
139
165
  const now = LiveEvent.getTimestamp();
140
- const ignoreBefore = now - (this._updateInterval.milliseconds * 2);
166
+ const ignoreBefore = now - this._updateInterval.milliseconds * 2;
141
167
  const shouldProject = !this._transportState.track.metadata?.liveStream;
142
168
  this._positions.forEach((value, key) => {
143
169
  const position = this._positions.get(key)!;
@@ -146,7 +172,10 @@ export class GroupPlaybackPosition {
146
172
  if (position.timestamp > ignoreBefore) {
147
173
  // Compute projected playback position
148
174
  // - This computation does not take into account future wait points.
149
- const projected = position.playbackState == 'playing' && shouldProject ? position.position + ((now - position.timestamp) / 1000) : position.position;
175
+ const projected =
176
+ position.playbackState == "playing" && shouldProject
177
+ ? position.position + (now - position.timestamp) / 1000
178
+ : position.position;
150
179
  callbackFn(position, this.limitProjectedPosition(projected));
151
180
  }
152
181
  });
@@ -179,7 +208,10 @@ export class GroupPlaybackPosition {
179
208
  // Compute max progress
180
209
  let progress = -1;
181
210
  this.forEach((position, projectedPosition) => {
182
- if (projectedPosition <= maxPosition && projectedPosition > progress) {
211
+ if (
212
+ projectedPosition <= maxPosition &&
213
+ projectedPosition > progress
214
+ ) {
183
215
  progress = projectedPosition;
184
216
  }
185
217
  });
@@ -188,6 +220,8 @@ export class GroupPlaybackPosition {
188
220
  }
189
221
 
190
222
  private limitProjectedPosition(position: number): number {
191
- return this.mediaDuration != undefined ? Math.min(position, this.mediaDuration) : position;
223
+ return this.mediaDuration != undefined
224
+ ? Math.min(position, this.mediaDuration)
225
+ : position;
192
226
  }
193
227
  }
@@ -3,46 +3,53 @@
3
3
  * Licensed under the Microsoft Live Share SDK License.
4
4
  */
5
5
 
6
- import { IEvent } from '@microsoft/live-share';
7
- import EventEmitter from 'events';
8
- import { IMediaPlayerState } from '../LiveMediaSessionCoordinator';
9
- import { CoordinationWaitPoint, ExtendedMediaMetadata } from '../MediaSessionExtensions';
6
+ import { IEvent } from "@microsoft/live-share";
7
+ import EventEmitter from "events";
8
+ import { IMediaPlayerState } from "../LiveMediaSessionCoordinator";
9
+ import {
10
+ CoordinationWaitPoint,
11
+ ExtendedMediaMetadata,
12
+ } from "../MediaSessionExtensions";
10
13
 
11
14
  /**
12
15
  * @hidden
13
16
  */
14
- export interface IPlaybackTrack {
15
- metadata: ExtendedMediaMetadata|null;
17
+ export interface IPlaybackTrack {
18
+ metadata: ExtendedMediaMetadata | null;
16
19
  waitPoints: CoordinationWaitPoint[];
17
20
  timestamp: number;
18
21
  clientId: string;
19
22
  }
20
23
 
21
-
22
24
  /**
23
25
  * @hidden
24
26
  */
25
- export enum GroupPlaybackTrackEvents {
26
- trackChange = 'trackChange'
27
+ export enum GroupPlaybackTrackEvents {
28
+ trackChange = "trackChange",
27
29
  }
28
30
 
29
31
  /**
30
32
  * @hidden
31
33
  */
32
- export interface IPlaybackTrackChangeEvent extends IEvent {
33
- metadata: ExtendedMediaMetadata|null;
34
+ export interface IPlaybackTrackChangeEvent extends IEvent {
35
+ metadata: ExtendedMediaMetadata | null;
34
36
  }
35
37
 
36
38
  /**
37
39
  * @hidden
38
40
  */
39
- export class GroupPlaybackTrack extends EventEmitter {
41
+ export class GroupPlaybackTrack extends EventEmitter {
40
42
  private readonly _getMediaPlayerState: () => IMediaPlayerState;
41
43
  private _current: IPlaybackTrack;
42
44
 
43
45
  constructor(getMediaPlayerState: () => IMediaPlayerState) {
44
46
  super();
45
- this._current = { metadata: null, waitPoints: [], timestamp: 0, clientId: '' };
47
+ this._current = {
48
+ metadata: null,
49
+ waitPoints: [],
50
+ timestamp: 0,
51
+ clientId: "",
52
+ };
46
53
  this._getMediaPlayerState = getMediaPlayerState;
47
54
  }
48
55
 
@@ -55,7 +62,7 @@ import { CoordinationWaitPoint, ExtendedMediaMetadata } from '../MediaSessionExt
55
62
  return this._current;
56
63
  }
57
64
 
58
- public get metadata(): ExtendedMediaMetadata|null {
65
+ public get metadata(): ExtendedMediaMetadata | null {
59
66
  return this.current.metadata;
60
67
  }
61
68
 
@@ -77,7 +84,9 @@ import { CoordinationWaitPoint, ExtendedMediaMetadata } from '../MediaSessionExt
77
84
  return true;
78
85
  }
79
86
 
80
- public findNextWaitPoint(lastWaitPoint: CoordinationWaitPoint|undefined): CoordinationWaitPoint|undefined {
87
+ public findNextWaitPoint(
88
+ lastWaitPoint: CoordinationWaitPoint | undefined
89
+ ): CoordinationWaitPoint | undefined {
81
90
  const waitPoints = this._current.waitPoints || [];
82
91
  for (const waitPoint of waitPoints) {
83
92
  if (lastWaitPoint && waitPoint.position <= lastWaitPoint.position) {
@@ -98,14 +107,22 @@ import { CoordinationWaitPoint, ExtendedMediaMetadata } from '../MediaSessionExt
98
107
 
99
108
  // Is this the same track?
100
109
  const current = this.current;
101
- if (GroupPlaybackTrack.compareMetadata(this.current.metadata, track.metadata)) {
110
+ if (
111
+ GroupPlaybackTrack.compareMetadata(
112
+ this.current.metadata,
113
+ track.metadata
114
+ )
115
+ ) {
102
116
  // Add any dynamic wait points.
103
117
  track.waitPoints.forEach((waitPoint) => {
104
118
  this.addWaitPoint(waitPoint);
105
119
  });
106
120
 
107
121
  // Ignore if same playback state
108
- if (track.timestamp == current.timestamp && track.clientId == current.clientId) {
122
+ if (
123
+ track.timestamp == current.timestamp &&
124
+ track.clientId == current.clientId
125
+ ) {
109
126
  return false;
110
127
  }
111
128
  }
@@ -117,7 +134,10 @@ import { CoordinationWaitPoint, ExtendedMediaMetadata } from '../MediaSessionExt
117
134
 
118
135
  // Ignore state changes that are from a clientId that sorts higher then the current one.
119
136
  // - current.clientId should not be empty if current.timestamp != 0
120
- if (track.timestamp == current.timestamp && track.clientId.localeCompare(current.clientId) > 0) {
137
+ if (
138
+ track.timestamp == current.timestamp &&
139
+ track.clientId.localeCompare(current.clientId) > 0
140
+ ) {
121
141
  return false;
122
142
  }
123
143
 
@@ -125,16 +145,25 @@ import { CoordinationWaitPoint, ExtendedMediaMetadata } from '../MediaSessionExt
125
145
  this._current = track;
126
146
 
127
147
  // Notify listeners
128
- this.emit(GroupPlaybackTrackEvents.trackChange, { name: GroupPlaybackTrackEvents.trackChange, metadata: track.metadata });
148
+ this.emit(GroupPlaybackTrackEvents.trackChange, {
149
+ name: GroupPlaybackTrackEvents.trackChange,
150
+ metadata: track.metadata,
151
+ });
129
152
 
130
153
  return true;
131
154
  }
132
155
 
133
- public compare(metadata: ExtendedMediaMetadata|null): boolean {
134
- return GroupPlaybackTrack.compareMetadata(this.current.metadata, metadata);
156
+ public compare(metadata: ExtendedMediaMetadata | null): boolean {
157
+ return GroupPlaybackTrack.compareMetadata(
158
+ this.current.metadata,
159
+ metadata
160
+ );
135
161
  }
136
162
 
137
- public static compareMetadata(current: ExtendedMediaMetadata|null, metadata: ExtendedMediaMetadata|null): boolean {
163
+ public static compareMetadata(
164
+ current: ExtendedMediaMetadata | null,
165
+ metadata: ExtendedMediaMetadata | null
166
+ ): boolean {
138
167
  // Only compare when we have two metadata instances
139
168
  if (current && metadata) {
140
169
  return JSON.stringify(current) == JSON.stringify(metadata);
@@ -3,16 +3,18 @@
3
3
  * Licensed under the Microsoft Live Share SDK License.
4
4
  */
5
5
 
6
- import { IEvent } from '@microsoft/live-share';
7
- import EventEmitter from 'events';
8
- import { GroupPlaybackTrack, GroupPlaybackTrackEvents } from './GroupPlaybackTrack';
9
-
6
+ import { IEvent } from "@microsoft/live-share";
7
+ import EventEmitter from "events";
8
+ import {
9
+ GroupPlaybackTrack,
10
+ GroupPlaybackTrackEvents,
11
+ } from "./GroupPlaybackTrack";
10
12
 
11
13
  /**
12
14
  * @hidden
13
15
  */
14
- export interface IPlaybackTrackData {
15
- data: object|null;
16
+ export interface IPlaybackTrackData {
17
+ data: object | null;
16
18
  timestamp: number;
17
19
  clientId: string;
18
20
  }
@@ -20,28 +22,28 @@ import { GroupPlaybackTrack, GroupPlaybackTrackEvents } from './GroupPlaybackTra
20
22
  /**
21
23
  * @hidden
22
24
  */
23
- export enum PlaybackTrackDataEvents {
24
- dataChange = 'dataChange'
25
+ export enum PlaybackTrackDataEvents {
26
+ dataChange = "dataChange",
25
27
  }
26
28
 
27
29
  /**
28
30
  * @hidden
29
31
  */
30
32
  export interface IPlaybackTrackDataChangeEvent extends IEvent {
31
- data: object|null;
33
+ data: object | null;
32
34
  }
33
35
 
34
36
  /**
35
37
  * @hidden
36
38
  */
37
- export class GroupPlaybackTrackData extends EventEmitter {
39
+ export class GroupPlaybackTrackData extends EventEmitter {
38
40
  private _track: GroupPlaybackTrack;
39
41
  private _current: IPlaybackTrackData;
40
42
 
41
43
  constructor(track: GroupPlaybackTrack) {
42
44
  super();
43
45
  this._track = track;
44
- this._current = { data: null, timestamp: 0, clientId: '' };
46
+ this._current = { data: null, timestamp: 0, clientId: "" };
45
47
 
46
48
  // Listen for track changes
47
49
  this._track.on(GroupPlaybackTrackEvents.trackChange, () => {
@@ -49,8 +51,8 @@ export interface IPlaybackTrackDataChangeEvent extends IEvent {
49
51
  this._current = {
50
52
  data: null,
51
53
  timestamp: this._track.current.timestamp,
52
- clientId: this._track.current.clientId
53
- }
54
+ clientId: this._track.current.clientId,
55
+ };
54
56
  });
55
57
  }
56
58
 
@@ -58,7 +60,7 @@ export interface IPlaybackTrackDataChangeEvent extends IEvent {
58
60
  return this._current;
59
61
  }
60
62
 
61
- public get data(): object|null {
63
+ public get data(): object | null {
62
64
  return this.current.data;
63
65
  }
64
66
 
@@ -70,7 +72,10 @@ export interface IPlaybackTrackDataChangeEvent extends IEvent {
70
72
  }
71
73
 
72
74
  // Ignore state changes that have the same timestamp and the clientId sorts higher.
73
- if (event.timestamp == current.timestamp && event.clientId.localeCompare(current.clientId) > 0) {
75
+ if (
76
+ event.timestamp == current.timestamp &&
77
+ event.clientId.localeCompare(current.clientId) > 0
78
+ ) {
74
79
  return false;
75
80
  }
76
81
 
@@ -83,7 +88,10 @@ export interface IPlaybackTrackDataChangeEvent extends IEvent {
83
88
  this._current = event;
84
89
 
85
90
  // Notify listeners
86
- this.emit(PlaybackTrackDataEvents.dataChange, { type: PlaybackTrackDataEvents.dataChange, data: event.data });
91
+ this.emit(PlaybackTrackDataEvents.dataChange, {
92
+ type: PlaybackTrackDataEvents.dataChange,
93
+ data: event.data,
94
+ });
87
95
 
88
96
  return true;
89
97
  }
@@ -3,17 +3,22 @@
3
3
  * Licensed under the Microsoft Live Share SDK License.
4
4
  */
5
5
 
6
- import { IEvent, LiveEvent } from '@microsoft/live-share';
7
- import EventEmitter from 'events';
8
- import { IMediaPlayerState } from '../LiveMediaSessionCoordinator';
9
- import { ExtendedMediaSessionPlaybackState, ExtendedMediaSessionAction } from '../MediaSessionExtensions';
10
- import { GroupPlaybackTrack, GroupPlaybackTrackEvents } from './GroupPlaybackTrack';
11
-
6
+ import { IEvent, LiveEvent } from "@microsoft/live-share";
7
+ import EventEmitter from "events";
8
+ import { IMediaPlayerState } from "../LiveMediaSessionCoordinator";
9
+ import {
10
+ ExtendedMediaSessionPlaybackState,
11
+ ExtendedMediaSessionAction,
12
+ } from "../MediaSessionExtensions";
13
+ import {
14
+ GroupPlaybackTrack,
15
+ GroupPlaybackTrackEvents,
16
+ } from "./GroupPlaybackTrack";
12
17
 
13
18
  /**
14
19
  * @hidden
15
20
  */
16
- export interface ITransportState {
21
+ export interface ITransportState {
17
22
  playbackState: ExtendedMediaSessionPlaybackState;
18
23
  startPosition: number;
19
24
  timestamp: number;
@@ -24,7 +29,7 @@ import { GroupPlaybackTrack, GroupPlaybackTrackEvents } from './GroupPlaybackTra
24
29
  * @hidden
25
30
  */
26
31
  export enum GroupTransportStateEvents {
27
- transportStateChange = 'transportStateChange'
32
+ transportStateChange = "transportStateChange",
28
33
  }
29
34
 
30
35
  /**
@@ -38,31 +43,34 @@ export interface ITransportStateChangeEvent extends IEvent {
38
43
  /**
39
44
  * @hidden
40
45
  */
41
- export class GroupTransportState extends EventEmitter {
46
+ export class GroupTransportState extends EventEmitter {
42
47
  private readonly _getMediaPlayerState: () => IMediaPlayerState;
43
48
  private _track: GroupPlaybackTrack;
44
49
  private _current: ITransportState;
45
50
 
46
- constructor(track: GroupPlaybackTrack, getMediaPlayerState: () => IMediaPlayerState) {
51
+ constructor(
52
+ track: GroupPlaybackTrack,
53
+ getMediaPlayerState: () => IMediaPlayerState
54
+ ) {
47
55
  super();
48
56
  this._getMediaPlayerState = getMediaPlayerState;
49
57
  this._track = track;
50
58
  this._current = {
51
- playbackState: 'none',
59
+ playbackState: "none",
52
60
  startPosition: 0.0,
53
61
  timestamp: 0,
54
- clientId: ''
62
+ clientId: "",
55
63
  };
56
64
 
57
65
  // Listen for track changes
58
66
  this._track.on(GroupPlaybackTrackEvents.trackChange, () => {
59
67
  // Track changed so reset state to stopped ad position 0.0
60
68
  this._current = {
61
- playbackState: 'none',
69
+ playbackState: "none",
62
70
  startPosition: 0.0,
63
71
  timestamp: this._track.current.timestamp,
64
- clientId: this._track.current.clientId
65
- }
72
+ clientId: this._track.current.clientId,
73
+ };
66
74
  });
67
75
  }
68
76
 
@@ -87,7 +95,10 @@ export interface ITransportStateChangeEvent extends IEvent {
87
95
  }
88
96
 
89
97
  public compare(state: ITransportState): boolean {
90
- return this.current.playbackState == state.playbackState && this.current.startPosition == state.startPosition;
98
+ return (
99
+ this.current.playbackState == state.playbackState &&
100
+ this.current.startPosition == state.startPosition
101
+ );
91
102
  }
92
103
 
93
104
  public updateState(state: ITransportState): boolean {
@@ -103,7 +114,10 @@ export interface ITransportStateChangeEvent extends IEvent {
103
114
  }
104
115
 
105
116
  // Ignore state changes that have the same timestamp and the clientId sorts higher.
106
- if (state.timestamp == originalState.timestamp && state.clientId.localeCompare(originalState.clientId) > 0) {
117
+ if (
118
+ state.timestamp == originalState.timestamp &&
119
+ state.clientId.localeCompare(originalState.clientId) > 0
120
+ ) {
107
121
  return false;
108
122
  }
109
123
 
@@ -112,14 +126,30 @@ export interface ITransportStateChangeEvent extends IEvent {
112
126
 
113
127
  // Trigger transport change
114
128
  const playerState = this._getMediaPlayerState().playbackState;
115
- if (originalState.playbackState == state.playbackState && playerState != 'ended') {
116
- this.emit(GroupTransportStateEvents.transportStateChange, { type: GroupTransportStateEvents.transportStateChange, action: 'seekto', seekTime: state.startPosition });
117
- } else if (state.playbackState == 'playing') {
129
+ if (
130
+ originalState.playbackState == state.playbackState &&
131
+ playerState != "ended"
132
+ ) {
133
+ this.emit(GroupTransportStateEvents.transportStateChange, {
134
+ type: GroupTransportStateEvents.transportStateChange,
135
+ action: "seekto",
136
+ seekTime: state.startPosition,
137
+ });
138
+ } else if (state.playbackState == "playing") {
118
139
  const now = LiveEvent.getTimestamp();
119
- const projectedPosition = state.startPosition + ((now - state.timestamp) / 1000);
120
- this.emit(GroupTransportStateEvents.transportStateChange, { type: GroupTransportStateEvents.transportStateChange, action: 'play', seekTime: projectedPosition});
140
+ const projectedPosition =
141
+ state.startPosition + (now - state.timestamp) / 1000;
142
+ this.emit(GroupTransportStateEvents.transportStateChange, {
143
+ type: GroupTransportStateEvents.transportStateChange,
144
+ action: "play",
145
+ seekTime: projectedPosition,
146
+ });
121
147
  } else {
122
- this.emit(GroupTransportStateEvents.transportStateChange, { type: GroupTransportStateEvents.transportStateChange, action: 'pause', seekTime: state.startPosition});
148
+ this.emit(GroupTransportStateEvents.transportStateChange, {
149
+ type: GroupTransportStateEvents.transportStateChange,
150
+ action: "pause",
151
+ seekTime: state.startPosition,
152
+ });
123
153
  }
124
154
 
125
155
  return true;