@microsoft/live-share-media 1.0.0-preview.1 → 1.0.0-preview.11

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 (111) hide show
  1. package/README.md +15 -13
  2. package/package.json +11 -9
  3. package/src/IMediaPlayer.ts +10 -2
  4. package/src/LiveMediaSession.ts +138 -71
  5. package/src/LiveMediaSessionCoordinator.ts +302 -142
  6. package/src/LiveMediaSessionCoordinatorSuspension.ts +13 -5
  7. package/src/MediaPlayerSynchronizer.ts +329 -149
  8. package/src/MediaSessionActionThrottler.ts +5 -3
  9. package/src/MediaSessionExtensions.ts +15 -5
  10. package/src/RepeatedActionThrottler.ts +27 -9
  11. package/src/VolumeManager.ts +24 -12
  12. package/src/index.ts +9 -10
  13. package/src/internals/GroupCoordinatorState.ts +275 -114
  14. package/src/internals/GroupPlaybackPosition.ts +63 -29
  15. package/src/internals/GroupPlaybackTrack.ts +51 -22
  16. package/src/internals/GroupPlaybackTrackData.ts +24 -16
  17. package/src/internals/GroupTransportState.ts +54 -24
  18. package/src/internals/consts.ts +73 -55
  19. package/src/internals/index.ts +6 -6
  20. package/src/test/GroupPlaybackPosition.spec.ts +371 -111
  21. package/src/test/GroupPlaybackTrack.spec.ts +91 -35
  22. package/src/test/SharedMediaSession.spec.ts +64 -28
  23. package/src/test/SharedMediaSessionCoordinator.spec.ts +86 -46
  24. package/src/test/VolumeManager.spec.ts +38 -31
  25. package/tsconfig.json +1 -0
  26. package/.vscode/launch.json +0 -29
  27. package/.vscode/settings.json +0 -2
  28. package/bin/EphemeralMediaSession.d.ts +0 -102
  29. package/bin/EphemeralMediaSession.d.ts.map +0 -1
  30. package/bin/EphemeralMediaSession.js +0 -226
  31. package/bin/EphemeralMediaSession.js.map +0 -1
  32. package/bin/EphemeralMediaSessionCoordinator.d.ts +0 -228
  33. package/bin/EphemeralMediaSessionCoordinator.d.ts.map +0 -1
  34. package/bin/EphemeralMediaSessionCoordinator.js +0 -396
  35. package/bin/EphemeralMediaSessionCoordinator.js.map +0 -1
  36. package/bin/EphemeralMediaSessionCoordinatorSuspension.d.ts +0 -20
  37. package/bin/EphemeralMediaSessionCoordinatorSuspension.d.ts.map +0 -1
  38. package/bin/EphemeralMediaSessionCoordinatorSuspension.js +0 -28
  39. package/bin/EphemeralMediaSessionCoordinatorSuspension.js.map +0 -1
  40. package/bin/IMediaPlayer.d.ts +0 -21
  41. package/bin/IMediaPlayer.d.ts.map +0 -1
  42. package/bin/IMediaPlayer.js +0 -7
  43. package/bin/IMediaPlayer.js.map +0 -1
  44. package/bin/LiveMediaSession.d.ts +0 -95
  45. package/bin/LiveMediaSession.d.ts.map +0 -1
  46. package/bin/LiveMediaSession.js +0 -217
  47. package/bin/LiveMediaSession.js.map +0 -1
  48. package/bin/LiveMediaSessionCoordinator.d.ts +0 -228
  49. package/bin/LiveMediaSessionCoordinator.d.ts.map +0 -1
  50. package/bin/LiveMediaSessionCoordinator.js +0 -396
  51. package/bin/LiveMediaSessionCoordinator.js.map +0 -1
  52. package/bin/LiveMediaSessionCoordinatorSuspension.d.ts +0 -20
  53. package/bin/LiveMediaSessionCoordinatorSuspension.d.ts.map +0 -1
  54. package/bin/LiveMediaSessionCoordinatorSuspension.js +0 -28
  55. package/bin/LiveMediaSessionCoordinatorSuspension.js.map +0 -1
  56. package/bin/MediaPlayerSynchronizer.d.ts +0 -164
  57. package/bin/MediaPlayerSynchronizer.d.ts.map +0 -1
  58. package/bin/MediaPlayerSynchronizer.js +0 -414
  59. package/bin/MediaPlayerSynchronizer.js.map +0 -1
  60. package/bin/MediaSessionActionThrottler.d.ts +0 -12
  61. package/bin/MediaSessionActionThrottler.d.ts.map +0 -1
  62. package/bin/MediaSessionActionThrottler.js +0 -14
  63. package/bin/MediaSessionActionThrottler.js.map +0 -1
  64. package/bin/MediaSessionExtensions.d.ts +0 -35
  65. package/bin/MediaSessionExtensions.d.ts.map +0 -1
  66. package/bin/MediaSessionExtensions.js +0 -13
  67. package/bin/MediaSessionExtensions.js.map +0 -1
  68. package/bin/RepeatedActionThrottler.d.ts +0 -20
  69. package/bin/RepeatedActionThrottler.d.ts.map +0 -1
  70. package/bin/RepeatedActionThrottler.js +0 -57
  71. package/bin/RepeatedActionThrottler.js.map +0 -1
  72. package/bin/VolumeLimiter.d.ts +0 -70
  73. package/bin/VolumeLimiter.d.ts.map +0 -1
  74. package/bin/VolumeLimiter.js +0 -170
  75. package/bin/VolumeLimiter.js.map +0 -1
  76. package/bin/VolumeManager.d.ts +0 -84
  77. package/bin/VolumeManager.d.ts.map +0 -1
  78. package/bin/VolumeManager.js +0 -173
  79. package/bin/VolumeManager.js.map +0 -1
  80. package/bin/index.d.ts +0 -14
  81. package/bin/index.d.ts.map +0 -1
  82. package/bin/index.js +0 -30
  83. package/bin/index.js.map +0 -1
  84. package/bin/internals/GroupCoordinatorState.d.ts +0 -93
  85. package/bin/internals/GroupCoordinatorState.d.ts.map +0 -1
  86. package/bin/internals/GroupCoordinatorState.js +0 -367
  87. package/bin/internals/GroupCoordinatorState.js.map +0 -1
  88. package/bin/internals/GroupPlaybackPosition.d.ts +0 -67
  89. package/bin/internals/GroupPlaybackPosition.d.ts.map +0 -1
  90. package/bin/internals/GroupPlaybackPosition.js +0 -158
  91. package/bin/internals/GroupPlaybackPosition.js.map +0 -1
  92. package/bin/internals/GroupPlaybackTrack.d.ts +0 -46
  93. package/bin/internals/GroupPlaybackTrack.d.ts.map +0 -1
  94. package/bin/internals/GroupPlaybackTrack.js +0 -112
  95. package/bin/internals/GroupPlaybackTrack.js.map +0 -1
  96. package/bin/internals/GroupPlaybackTrackData.d.ts +0 -40
  97. package/bin/internals/GroupPlaybackTrackData.d.ts.map +0 -1
  98. package/bin/internals/GroupPlaybackTrackData.js +0 -66
  99. package/bin/internals/GroupPlaybackTrackData.js.map +0 -1
  100. package/bin/internals/GroupTransportState.d.ts +0 -49
  101. package/bin/internals/GroupTransportState.d.ts.map +0 -1
  102. package/bin/internals/GroupTransportState.js +0 -97
  103. package/bin/internals/GroupTransportState.js.map +0 -1
  104. package/bin/internals/consts.d.ts +0 -73
  105. package/bin/internals/consts.d.ts.map +0 -1
  106. package/bin/internals/consts.js +0 -82
  107. package/bin/internals/consts.js.map +0 -1
  108. package/bin/internals/index.d.ts +0 -11
  109. package/bin/internals/index.d.ts.map +0 -1
  110. package/bin/internals/index.js +0 -27
  111. package/bin/internals/index.js.map +0 -1
package/README.md CHANGED
@@ -11,15 +11,13 @@ You can find our API reference documentation at [aka.ms/livesharedocs](https://a
11
11
  To add the latest version of the SDK to your application using NPM:
12
12
 
13
13
  ```bash
14
- npm install @microsoft/live-share --save
15
- npm install @microsoft/live-share-media --save
14
+ npm install fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-media --save
16
15
  ```
17
16
 
18
17
  or using [Yarn](https://yarnpkg.com/):
19
18
 
20
19
  ```bash
21
- yarn add @microsoft/live-share
22
- yarn add @microsoft/live-share-media
20
+ yarn add fluid-framework @fluidframework/azure-client @microsoft/live-share @microsoft/live-share-media
23
21
  ```
24
22
 
25
23
  ## Building package
@@ -50,15 +48,16 @@ This will use lerna to hoist and build all dependencies.
50
48
  ```
51
49
 
52
50
  ```javascript
53
- import * as microsoftTeams from "@microsoft/teams-js";
54
- import { TeamsFluidClient } from "@microsoft/live-share";
51
+ import { app, LiveShareHost } from "@microsoft/teams-js";
52
+ import { LiveShareClient } from "@microsoft/live-share";
55
53
  import { LiveMediaSession } from "@microsoft/live-share-media";
56
54
 
57
55
  // Initialize the Teams Client SDK
58
56
  await microsoftTeams.app.initialize();
59
57
 
60
58
  // Setup the Fluid container
61
- const client = new TeamsFluidClient();
59
+ const host = LiveShareHost.create();
60
+ const client = new LiveShareClient(host);
62
61
  const schema = {
63
62
  initialObjects: {
64
63
  mediaSession: LiveMediaSession,
@@ -112,11 +111,14 @@ The Live Share SDK contains dependencies for [@microsoft/teams-js](https://www.n
112
111
 
113
112
  **It is critical that your app use the package dependencies listed in the table below.** Lookup the version of the `@microsoft/live-share` you're using and set any other dependencies in your package.json file to match:
114
113
 
115
- | @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-(media or canvas) | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react |
116
- | --------------------- | -------------------- | --------------- | --------------------------- | ---------------------------- | ------------------------------- | ------------------------------- |
117
- | 1.0.0-preview.1 | 2.0.0-experimental.1 | ~1.2.3 | 1.0.0-preview.1 (optional) | ~1.0.2 (optional) | 2.0.0-experimental.0 (optional) | 2.0.0-experimental.0 (optional) |
118
- | ~0.5.1 | 2.0.0-experimental.1 | ~1.2.3 | ~0.5.1 (optional) | ~1.0.2 (optional) | 2.0.0-experimental.0 (optional) | 2.0.0-experimental.0 (optional) |
119
- | ~0.3.1 | 2.0.0-experimental.0 | ~0.59.0 | ~0.3.1 (optional) | ~0.59.0 (optional) | 2.0.0-experimental.0 (optional) | 2.0.0-experimental.0 (optional) |
114
+ | @microsoft/live-share | @microsoft/teams-js | fluid-framework | @microsoft/live-share-\* | @fluidframework/azure-client | @microsoft/TeamsFx | @microsoft/TeamsFx-react |
115
+ | --------------------- | -------------------- | --------------- | -------------------------- | ---------------------------- | ------------------------------- | ------------------------------- |
116
+ | 1.0.0-preview.11 | ^2.11.0 | ^1.2.3 | 1.0.0-preview.11 (optional) | ^1.0.0 (optional) | ^2.5.0 (optional) | ^2.5.0 (optional) |
117
+ | 1.0.0-preview.10 | ^2.10.1 | ~1.2.3 | 1.0.0-preview.10 (optional) | ~1.0.2 (optional) | ^2.5.0 (optional) | ^2.5.0 (optional) |
118
+ | 1.0.0-preview.8 | ^2.5.0 | ~1.2.3 | 1.0.0-preview.10 (optional) | ~1.0.2 (optional) | ^2.5.0 (optional) | ^2.5.0 (optional) |
119
+ | 1.0.0-preview.3 | 2.0.0-experimental.1 | ~1.2.3 | 1.0.0-preview.3 (optional) | ~1.0.2 (optional) | 2.0.0-experimental.0 (optional) | 2.0.0-experimental.0 (optional) |
120
+ | ~0.5.1 | 2.0.0-experimental.1 | ~1.2.3 | ~0.5.1 (optional) | ~1.0.2 (optional) | 2.0.0-experimental.0 (optional) | 2.0.0-experimental.0 (optional) |
121
+ | ~0.3.1 | 2.0.0-experimental.0 | ~0.59.0 | ~0.3.1 (optional) | ~0.59.0 (optional) | 2.0.0-experimental.0 (optional) | 2.0.0-experimental.0 (optional) |
120
122
 
121
123
  ## Contributing
122
124
 
@@ -131,7 +133,7 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
131
133
 
132
134
  ## Reporting Security Issues
133
135
 
134
- Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the [MSRC PGP](https://technet.microsoft.com/en-us/security/dn606155) key, can be found in the [Security TechCenter](https://technet.microsoft.com/en-us/security/default).
136
+ Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the [MSRC PGP](https://technet.microsoft.com/security/dn606155) key, can be found in the [Security TechCenter](https://technet.microsoft.com/security/default).
135
137
 
136
138
  Copyright (c) Microsoft Corporation. All rights reserved.
137
139
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/live-share-media",
3
- "version": "1.0.0-preview.1",
3
+ "version": "1.0.0-preview.11",
4
4
  "description": "Live Share classes that synchronize media playback across clients.",
5
5
  "author": "Microsoft",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -13,19 +13,21 @@
13
13
  "test:debug": "ts-mocha src/**/*.spec.ts --inspect-brk",
14
14
  "test:coverage": "nyc --reporter=html --reporter=text --reporter=text-summary npm test"
15
15
  },
16
- "dependencies": {
17
- "fluid-framework": "~1.2.3",
18
- "@microsoft/live-share": "1.0.0-preview.1"
19
- },
20
16
  "devDependencies": {
17
+ "@microsoft/live-share": "1.0.0-preview.11",
21
18
  "@types/assert": "^1.5.6",
22
- "@types/mocha": "^9.0.0",
23
- "@types/node": "^10.12.24",
24
- "mocha": "^9.1.1",
19
+ "@types/mocha": "^10.0.1",
20
+ "@types/node": "^18.11.18",
21
+ "fluid-framework": "^1.3.6",
22
+ "mocha": "^10.2.0",
25
23
  "nyc": "^15.1.0",
26
- "ts-mocha": "^9.0.2",
24
+ "ts-mocha": "^10.0.0",
27
25
  "typescript": "^4.6.4"
28
26
  },
27
+ "peerDependencies": {
28
+ "@microsoft/live-share": "1.0.0-preview.11",
29
+ "fluid-framework": "^1.2.3"
30
+ },
29
31
  "repository": {
30
32
  "directory": "packages/live-share-media",
31
33
  "type": "git",
@@ -16,6 +16,14 @@ export interface IMediaPlayer {
16
16
  load(): void;
17
17
  pause(): void;
18
18
  play(): Promise<void>;
19
- addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
20
- removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
19
+ addEventListener(
20
+ type: string,
21
+ listener: EventListenerOrEventListenerObject,
22
+ options?: boolean | AddEventListenerOptions
23
+ ): void;
24
+ removeEventListener(
25
+ type: string,
26
+ listener: EventListenerOrEventListenerObject,
27
+ options?: boolean | EventListenerOptions
28
+ ): void;
21
29
  }
@@ -3,40 +3,49 @@
3
3
  * Licensed under the Microsoft Live Share SDK License.
4
4
  */
5
5
 
6
- import { DataObject, DataObjectFactory } from '@fluidframework/aqueduct';
7
- import { LiveTelemetryLogger, UserMeetingRole } from '@microsoft/live-share';
8
- import { MediaPlayerSynchronizer } from './MediaPlayerSynchronizer';
9
- import { ITriggerActionEvent, TelemetryEvents } from './internals';
10
- import { MediaSessionCoordinatorEvents, ExtendedMediaSessionAction, ExtendedMediaSessionActionDetails } from './MediaSessionExtensions';
11
- import { LiveMediaSessionCoordinator, IMediaPlayerState } from './LiveMediaSessionCoordinator';
12
- import { MediaSessionActionThrottler } from './MediaSessionActionThrottler';
13
- import { RepeatedActionThrottler } from './RepeatedActionThrottler';
14
- import { IMediaPlayer } from './IMediaPlayer';
6
+ import { DataObject, DataObjectFactory } from "@fluidframework/aqueduct";
7
+ import { DynamicObjectRegistry, LiveTelemetryLogger, UserMeetingRole } from "@microsoft/live-share";
8
+ import { MediaPlayerSynchronizer } from "./MediaPlayerSynchronizer";
9
+ import { ITriggerActionEvent, TelemetryEvents } from "./internals";
10
+ import {
11
+ MediaSessionCoordinatorEvents,
12
+ ExtendedMediaSessionAction,
13
+ ExtendedMediaSessionActionDetails,
14
+ } from "./MediaSessionExtensions";
15
+ import {
16
+ LiveMediaSessionCoordinator,
17
+ IMediaPlayerState,
18
+ } from "./LiveMediaSessionCoordinator";
19
+ import { MediaSessionActionThrottler } from "./MediaSessionActionThrottler";
20
+ import { RepeatedActionThrottler } from "./RepeatedActionThrottler";
21
+ import { IMediaPlayer } from "./IMediaPlayer";
15
22
 
16
23
  /**
17
24
  * Live fluid object that synchronizes media playback across multiple clients.
18
25
  */
19
- export class LiveMediaSession extends DataObject {
20
- private _actionThrottler: MediaSessionActionThrottler = new RepeatedActionThrottler();
26
+ export class LiveMediaSession extends DataObject {
27
+ private _actionThrottler: MediaSessionActionThrottler =
28
+ new RepeatedActionThrottler();
21
29
  private _logger?: LiveTelemetryLogger;
22
30
  private _requestPlayerStateHandler?: () => IMediaPlayerState;
23
31
  private _coordinator?: LiveMediaSessionCoordinator;
24
- private readonly _actionHandlers: Map<string, MediaSessionActionHandler> = new Map();
32
+ private readonly _actionHandlers: Map<string, MediaSessionActionHandler> =
33
+ new Map();
25
34
  private _synchronizing?: MediaPlayerSynchronizer;
26
35
 
27
36
  // Position update timer
28
37
  private _updateTimer: any;
29
38
  private _lastUpdateTime: number = 0;
30
-
39
+
31
40
  /**
32
41
  * The objects fluid type name.
33
42
  */
34
- public static readonly TypeName = `@microsoft/fluid-media:SharedMediaSession`;
43
+ public static readonly TypeName = `@microsoft/fluid-media:SharedMediaSession`;
35
44
 
36
45
  /**
37
46
  * The objects fluid type factory.
38
47
  */
39
- public static readonly factory = new DataObjectFactory(
48
+ public static readonly factory = new DataObjectFactory(
40
49
  LiveMediaSession.TypeName,
41
50
  LiveMediaSession,
42
51
  [],
@@ -46,15 +55,15 @@ import { IMediaPlayer } from './IMediaPlayer';
46
55
  /**
47
56
  * Extension point that lets applications replace the default logic for throttling the sessions
48
57
  * local sync behavior.
49
- *
58
+ *
50
59
  * @remarks
51
- * The `LiveMediaCoordinator` is fairly aggressive at wanting to keep the local media player
52
- * in sync with the rest of the group. This aggressiveness can result in the coordinator sending
53
- * new sync actions before the local player has finished responding to the previous sync action.
60
+ * The `LiveMediaCoordinator` is fairly aggressive at wanting to keep the local media player
61
+ * in sync with the rest of the group. This aggressiveness can result in the coordinator sending
62
+ * new sync actions before the local player has finished responding to the previous sync action.
54
63
  * The `ActionThrottler` gives apps fine grain control over how aggressive they want sync to be.
55
- *
56
- * By default, a `RepeatedAction` throttler is used which prevents the same sync action from
57
- * being sent within an adjustable time period.
64
+ *
65
+ * By default, a `RepeatedAction` throttler is used which prevents the same sync action from
66
+ * being sent within an adjustable time period.
58
67
  */
59
68
  public get actionThrottler(): MediaSessionActionThrottler {
60
69
  return this._actionThrottler;
@@ -76,7 +85,7 @@ import { IMediaPlayer } from './IMediaPlayer';
76
85
  * Returns true if the object has been initialized.
77
86
  */
78
87
  public get isStarted(): boolean {
79
- return this.isInitialized
88
+ return this.isInitialized;
80
89
  }
81
90
 
82
91
  /**
@@ -88,7 +97,7 @@ import { IMediaPlayer } from './IMediaPlayer';
88
97
 
89
98
  /**
90
99
  * Returns the logger used by the session and coordinator.
91
- *
100
+ *
92
101
  * @remarks
93
102
  * This is used by the `MediaPlayerSynchronizer` to log events.
94
103
  */
@@ -98,10 +107,12 @@ import { IMediaPlayer } from './IMediaPlayer';
98
107
 
99
108
  /**
100
109
  * initialize the object.
101
- * @param acceptTransportChangesFrom Optional. List of roles allowed to group transport
110
+ * @param acceptTransportChangesFrom Optional. List of roles allowed to group transport
102
111
  * operations like play/pause/seek/setTrack.
103
112
  */
104
- public initialize(acceptTransportChangesFrom?: UserMeetingRole[]): Promise<void> {
113
+ public initialize(
114
+ acceptTransportChangesFrom?: UserMeetingRole[]
115
+ ): Promise<void> {
105
116
  return this.coordinator.initialize(acceptTransportChangesFrom);
106
117
  }
107
118
 
@@ -110,11 +121,13 @@ import { IMediaPlayer } from './IMediaPlayer';
110
121
  * @param action Name of the action to register a handler for.
111
122
  * @param handler Function called when the action is triggered.
112
123
  */
113
- public setActionHandler(action: ExtendedMediaSessionAction, handler: MediaSessionActionHandler | null): void {
124
+ public setActionHandler(
125
+ action: ExtendedMediaSessionAction,
126
+ handler: MediaSessionActionHandler | null
127
+ ): void {
114
128
  if (handler) {
115
129
  // add handler
116
130
  this._actionHandlers.set(action, handler);
117
-
118
131
  } else if (this._actionHandlers.has(action)) {
119
132
  // remove handler
120
133
  this._actionHandlers.delete(action);
@@ -122,8 +135,8 @@ import { IMediaPlayer } from './IMediaPlayer';
122
135
  }
123
136
 
124
137
  /**
125
- * Registers a handler that will be queried anytime the group coordinate needs to know the
126
- * local players transport state and position.
138
+ * Registers a handler that will be queried anytime the group coordinate needs to know the
139
+ * local players transport state and position.
127
140
  */
128
141
  public setRequestPlayerStateHandler(handler: () => IMediaPlayerState) {
129
142
  this._requestPlayerStateHandler = handler;
@@ -142,7 +155,9 @@ import { IMediaPlayer } from './IMediaPlayer';
142
155
 
143
156
  // Start position update timer
144
157
  if (!this._updateTimer) {
145
- this.logger.sendTelemetryEvent(TelemetryEvents.MediaSession.BeginPositionUpdateTimer);
158
+ this.logger.sendTelemetryEvent(
159
+ TelemetryEvents.MediaSession.BeginPositionUpdateTimer
160
+ );
146
161
  this._updateTimer = setInterval(() => {
147
162
  // Get current state
148
163
  const state = this.getCurrentPlayerState();
@@ -153,7 +168,10 @@ import { IMediaPlayer } from './IMediaPlayer';
153
168
  // Send position update if interval hit
154
169
  const now = new Date().getTime();
155
170
  const delta = (now - this._lastUpdateTime) / 1000;
156
- if (this.coordinator.isInitialized && delta >= this.coordinator.positionUpdateInterval) {
171
+ if (
172
+ this.coordinator.isInitialized &&
173
+ delta >= this.coordinator.positionUpdateInterval
174
+ ) {
157
175
  this._lastUpdateTime = now;
158
176
  this.coordinator.sendPositionUpdate(state);
159
177
  }
@@ -166,73 +184,122 @@ import { IMediaPlayer } from './IMediaPlayer';
166
184
  }
167
185
 
168
186
  protected async hasInitialized(): Promise<void> {
169
- this. _logger = new LiveTelemetryLogger(this.runtime);
187
+ this._logger = new LiveTelemetryLogger(this.runtime);
170
188
 
171
189
  // Create coordinator and listen for triggered actions
172
- this._coordinator = new LiveMediaSessionCoordinator(this.runtime, () => this.getCurrentPlayerState());
173
- this._coordinator.on(MediaSessionCoordinatorEvents.triggeraction, (event: ITriggerActionEvent) => {
174
- // Pre-process actions
175
- const details = event.details;
176
- const seekTime = typeof details.seekTime == 'number' ? details.seekTime : -1;
177
- switch (details.action) {
178
- case 'play':
179
- this.logger.sendTelemetryEvent(TelemetryEvents.MediaSession.PlayAction, null, {position: seekTime});
180
- break;
181
- case 'pause':
182
- this.logger.sendTelemetryEvent(TelemetryEvents.MediaSession.PauseAction, null, {position: seekTime});
183
- break;
184
- case 'seekto':
185
- this.logger.sendTelemetryEvent(TelemetryEvents.MediaSession.SeekToAction, null, {position: seekTime});
186
- break;
187
- case 'settrack':
188
- this.logger.sendTelemetryEvent(TelemetryEvents.MediaSession.SetTrackAction);
189
- break;
190
- case 'datachange':
191
- this.logger.sendTelemetryEvent(TelemetryEvents.MediaSession.DataChangeAction);
192
- break;
193
- case 'catchup':
194
- // Default to seekto if catchup not implemented
195
- this.logger.sendTelemetryEvent(TelemetryEvents.MediaSession.CatchUpAction, null, {position: seekTime});
196
- if (!this._actionHandlers.has('catchup')) {
197
- details.action = 'seekto';
198
- }
199
- break;
200
- }
190
+ this._coordinator = new LiveMediaSessionCoordinator(this.runtime, () =>
191
+ this.getCurrentPlayerState()
192
+ );
193
+ this._coordinator.on(
194
+ MediaSessionCoordinatorEvents.triggeraction,
195
+ (event: ITriggerActionEvent) => {
196
+ // Pre-process actions
197
+ const details = event.details;
198
+ const seekTime =
199
+ typeof details.seekTime == "number" ? details.seekTime : -1;
200
+ switch (details.action) {
201
+ case "play":
202
+ this.logger.sendTelemetryEvent(
203
+ TelemetryEvents.MediaSession.PlayAction,
204
+ null,
205
+ {
206
+ position: seekTime,
207
+ }
208
+ );
209
+ break;
210
+ case "pause":
211
+ this.logger.sendTelemetryEvent(
212
+ TelemetryEvents.MediaSession.PauseAction,
213
+ null,
214
+ {
215
+ position: seekTime,
216
+ }
217
+ );
218
+ break;
219
+ case "seekto":
220
+ this.logger.sendTelemetryEvent(
221
+ TelemetryEvents.MediaSession.SeekToAction,
222
+ null,
223
+ {
224
+ position: seekTime,
225
+ }
226
+ );
227
+ break;
228
+ case "settrack":
229
+ this.logger.sendTelemetryEvent(
230
+ TelemetryEvents.MediaSession.SetTrackAction
231
+ );
232
+ break;
233
+ case "datachange":
234
+ this.logger.sendTelemetryEvent(
235
+ TelemetryEvents.MediaSession.DataChangeAction
236
+ );
237
+ break;
238
+ case "catchup":
239
+ // Default to seekto if catchup not implemented
240
+ this.logger.sendTelemetryEvent(
241
+ TelemetryEvents.MediaSession.CatchUpAction,
242
+ null,
243
+ {
244
+ position: seekTime,
245
+ }
246
+ );
247
+ if (!this._actionHandlers.has("catchup")) {
248
+ details.action = "seekto";
249
+ }
250
+ break;
251
+ }
201
252
 
202
- // Dispatch action
203
- this.dispatchAction(details);
204
- });
253
+ // Dispatch action
254
+ this.dispatchAction(details);
255
+ }
256
+ );
205
257
  }
206
258
 
207
259
  private checkWaitPointHit(state: IMediaPlayerState): void {
208
260
  // Was a wait point hit?
209
261
  if (state.positionState && this.coordinator.isInitialized) {
210
262
  const waitPoint = this.coordinator.findNextWaitPoint();
211
- if (waitPoint && state.positionState.position != undefined && state.positionState.position >= waitPoint.position) {
263
+ if (
264
+ waitPoint &&
265
+ state.positionState.position != undefined &&
266
+ state.positionState.position >= waitPoint.position
267
+ ) {
212
268
  // Ensure handler registered
213
- if (!this._actionHandlers.has('wait')) {
214
- throw new Error(`SharedMediaSession: wait point hit but no 'wait' action registered.`);
269
+ if (!this._actionHandlers.has("wait")) {
270
+ throw new Error(
271
+ `SharedMediaSession: wait point hit but no 'wait' action registered.`
272
+ );
215
273
  }
216
274
 
217
275
  // Begin suspension for wait point
218
276
  const suspension = this.coordinator.beginSuspension(waitPoint);
219
- this.dispatchAction({action: 'wait', suspension: suspension});
277
+ this.dispatchAction({ action: "wait", suspension: suspension });
220
278
  }
221
279
  }
222
280
  }
223
281
 
224
282
  private getCurrentPlayerState(): IMediaPlayerState {
225
283
  if (!this._requestPlayerStateHandler) {
226
- throw new Error(`SharedMediaSession: no getPlayerState callback configured.`);
284
+ throw new Error(
285
+ `SharedMediaSession: no getPlayerState callback configured.`
286
+ );
227
287
  }
228
288
 
229
289
  return this._requestPlayerStateHandler();
230
290
  }
231
291
 
232
- private dispatchAction(details: MediaSessionActionDetails|ExtendedMediaSessionActionDetails): void {
292
+ private dispatchAction(
293
+ details: MediaSessionActionDetails | ExtendedMediaSessionActionDetails
294
+ ): void {
233
295
  if (this._actionHandlers.has(details.action)) {
234
296
  const handler = this._actionHandlers.get(details.action);
235
297
  this._actionThrottler.throttled(details, handler);
236
298
  }
237
299
  }
238
300
  }
301
+
302
+ /**
303
+ * Register `LiveMediaSession` as an available `LoadableObjectClass` for use in packages that support dynamic object loading, such as `@microsoft/live-share-turbo`.
304
+ */
305
+ DynamicObjectRegistry.registerObjectClass(LiveMediaSession, LiveMediaSession.TypeName);