timingsrc 1.2.6 → 1.2.8
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/build/es2019/factories/compute-velocity.d.ts +2 -0
- package/build/es2019/factories/compute-velocity.d.ts.map +1 -0
- package/build/es2019/factories/compute-velocity.js +2 -0
- package/build/es2019/factories/compute-velocity.js.map +1 -0
- package/build/es2019/factories/default-set-timingsrc.d.ts +9 -2
- package/build/es2019/factories/default-set-timingsrc.d.ts.map +1 -1
- package/build/es2019/factories/default-set-timingsrc.js +6 -3
- package/build/es2019/factories/default-set-timingsrc.js.map +1 -1
- package/build/es2019/factories/set-current-time.d.ts +1 -2
- package/build/es2019/factories/set-current-time.d.ts.map +1 -1
- package/build/es2019/factories/set-current-time.js.map +1 -1
- package/build/es2019/factories/set-playback-rate.d.ts +1 -2
- package/build/es2019/factories/set-playback-rate.d.ts.map +1 -1
- package/build/es2019/factories/set-playback-rate.js.map +1 -1
- package/build/es2019/factories/set-timingsrc-with-custom-update-function.d.ts +6 -2
- package/build/es2019/factories/set-timingsrc-with-custom-update-function.d.ts.map +1 -1
- package/build/es2019/factories/set-timingsrc-with-custom-update-function.js +30 -10
- package/build/es2019/factories/set-timingsrc-with-custom-update-function.js.map +1 -1
- package/build/es2019/factories/set-timingsrc.d.ts +5 -2
- package/build/es2019/factories/set-timingsrc.d.ts.map +1 -1
- package/build/es2019/factories/set-timingsrc.js +1 -3
- package/build/es2019/factories/set-timingsrc.js.map +1 -1
- package/build/es2019/factories/update-gradually.d.ts +7 -2
- package/build/es2019/factories/update-gradually.d.ts.map +1 -1
- package/build/es2019/factories/update-gradually.js +18 -7
- package/build/es2019/factories/update-gradually.js.map +1 -1
- package/build/es2019/factories/update-media-element.d.ts +5 -2
- package/build/es2019/factories/update-media-element.d.ts.map +1 -1
- package/build/es2019/factories/update-media-element.js.map +1 -1
- package/build/es2019/factories/update-stepwise-factory.d.ts +12 -2
- package/build/es2019/factories/update-stepwise-factory.d.ts.map +1 -1
- package/build/es2019/factories/update-stepwise-factory.js +98 -25
- package/build/es2019/factories/update-stepwise-factory.js.map +1 -1
- package/build/es2019/factories/window.d.ts +1 -2
- package/build/es2019/factories/window.d.ts.map +1 -1
- package/build/es2019/factories/window.js.map +1 -1
- package/build/es2019/functions/determine-supported-playback-rate-values.d.ts +2 -1
- package/build/es2019/functions/determine-supported-playback-rate-values.d.ts.map +1 -1
- package/build/es2019/functions/determine-supported-playback-rate-values.js.map +1 -1
- package/build/es2019/functions/update-vector-with-new-position.d.ts +6 -0
- package/build/es2019/functions/update-vector-with-new-position.d.ts.map +1 -0
- package/build/es2019/functions/update-vector-with-new-position.js +5 -0
- package/build/es2019/functions/update-vector-with-new-position.js.map +1 -0
- package/build/es2019/module.d.ts +11 -3
- package/build/es2019/module.d.ts.map +1 -1
- package/build/es2019/module.js +3 -1
- package/build/es2019/module.js.map +1 -1
- package/build/es2019/types/index.d.ts +1 -17
- package/build/es2019/types/index.d.ts.map +1 -1
- package/build/es2019/types/index.js +1 -17
- package/build/es2019/types/index.js.map +1 -1
- package/build/es2019/types/update-function.d.ts +1 -1
- package/build/es2019/types/update-function.d.ts.map +1 -1
- package/build/es2019/types/update-vector-with-custom-state.d.ts +3 -0
- package/build/es2019/types/update-vector-with-custom-state.d.ts.map +1 -0
- package/build/es2019/types/update-vector-with-custom-state.js +2 -0
- package/build/es2019/types/update-vector-with-custom-state.js.map +1 -0
- package/build/es5/bundle.js +202 -72
- package/package.json +8 -8
- package/src/factories/compute-velocity.ts +2 -0
- package/src/factories/default-set-timingsrc.ts +30 -19
- package/src/factories/set-current-time.ts +2 -4
- package/src/factories/set-playback-rate.ts +2 -4
- package/src/factories/set-timingsrc-with-custom-update-function.ts +59 -16
- package/src/factories/set-timingsrc.ts +14 -4
- package/src/factories/update-gradually.ts +37 -8
- package/src/factories/update-media-element.ts +18 -3
- package/src/factories/update-stepwise-factory.ts +133 -38
- package/src/factories/window.ts +1 -3
- package/src/functions/determine-supported-playback-rate-values.ts +3 -1
- package/src/functions/update-vector-with-new-position.ts +9 -0
- package/src/module.ts +4 -0
- package/src/types/index.ts +1 -17
- package/src/types/update-function.ts +5 -1
- package/src/types/update-vector-with-custom-state.ts +5 -0
- package/build/es2019/types/default-timingsrc-factory.d.ts +0 -8
- package/build/es2019/types/default-timingsrc-factory.d.ts.map +0 -1
- package/build/es2019/types/default-timingsrc-factory.js +0 -2
- package/build/es2019/types/default-timingsrc-factory.js.map +0 -1
- package/build/es2019/types/determine-supported-playback-rate-values-function.d.ts +0 -2
- package/build/es2019/types/determine-supported-playback-rate-values-function.d.ts.map +0 -1
- package/build/es2019/types/determine-supported-playback-rate-values-function.js +0 -2
- package/build/es2019/types/determine-supported-playback-rate-values-function.js.map +0 -1
- package/build/es2019/types/pause-function.d.ts +0 -2
- package/build/es2019/types/pause-function.d.ts.map +0 -1
- package/build/es2019/types/pause-function.js +0 -2
- package/build/es2019/types/pause-function.js.map +0 -1
- package/build/es2019/types/play-function.d.ts +0 -2
- package/build/es2019/types/play-function.d.ts.map +0 -1
- package/build/es2019/types/play-function.js +0 -2
- package/build/es2019/types/play-function.js.map +0 -1
- package/build/es2019/types/set-current-time-factory.d.ts +0 -3
- package/build/es2019/types/set-current-time-factory.d.ts.map +0 -1
- package/build/es2019/types/set-current-time-factory.js +0 -2
- package/build/es2019/types/set-current-time-factory.js.map +0 -1
- package/build/es2019/types/set-current-time-function.d.ts +0 -2
- package/build/es2019/types/set-current-time-function.d.ts.map +0 -1
- package/build/es2019/types/set-current-time-function.js +0 -2
- package/build/es2019/types/set-current-time-function.js.map +0 -1
- package/build/es2019/types/set-playback-rate-factory.d.ts +0 -3
- package/build/es2019/types/set-playback-rate-factory.d.ts.map +0 -1
- package/build/es2019/types/set-playback-rate-factory.js +0 -2
- package/build/es2019/types/set-playback-rate-factory.js.map +0 -1
- package/build/es2019/types/set-playback-rate-function.d.ts +0 -2
- package/build/es2019/types/set-playback-rate-function.d.ts.map +0 -1
- package/build/es2019/types/set-playback-rate-function.js +0 -2
- package/build/es2019/types/set-playback-rate-function.js.map +0 -1
- package/build/es2019/types/set-timingsrc-factory.d.ts +0 -5
- package/build/es2019/types/set-timingsrc-factory.d.ts.map +0 -1
- package/build/es2019/types/set-timingsrc-factory.js +0 -2
- package/build/es2019/types/set-timingsrc-factory.js.map +0 -1
- package/build/es2019/types/set-timingsrc-function.d.ts +0 -4
- package/build/es2019/types/set-timingsrc-function.d.ts.map +0 -1
- package/build/es2019/types/set-timingsrc-function.js +0 -2
- package/build/es2019/types/set-timingsrc-function.js.map +0 -1
- package/build/es2019/types/set-timingsrc-with-custom-update-function-factory.d.ts +0 -5
- package/build/es2019/types/set-timingsrc-with-custom-update-function-factory.d.ts.map +0 -1
- package/build/es2019/types/set-timingsrc-with-custom-update-function-factory.js +0 -2
- package/build/es2019/types/set-timingsrc-with-custom-update-function-factory.js.map +0 -1
- package/build/es2019/types/set-timingsrc-with-custom-update-function-function.d.ts +0 -5
- package/build/es2019/types/set-timingsrc-with-custom-update-function-function.d.ts.map +0 -1
- package/build/es2019/types/set-timingsrc-with-custom-update-function-function.js +0 -2
- package/build/es2019/types/set-timingsrc-with-custom-update-function-function.js.map +0 -1
- package/build/es2019/types/update-gradually-factory.d.ts +0 -4
- package/build/es2019/types/update-gradually-factory.d.ts.map +0 -1
- package/build/es2019/types/update-gradually-factory.js +0 -2
- package/build/es2019/types/update-gradually-factory.js.map +0 -1
- package/build/es2019/types/update-media-element-factory.d.ts +0 -7
- package/build/es2019/types/update-media-element-factory.d.ts.map +0 -1
- package/build/es2019/types/update-media-element-factory.js +0 -2
- package/build/es2019/types/update-media-element-factory.js.map +0 -1
- package/build/es2019/types/update-media-element-function.d.ts +0 -2
- package/build/es2019/types/update-media-element-function.d.ts.map +0 -1
- package/build/es2019/types/update-media-element-function.js +0 -2
- package/build/es2019/types/update-media-element-function.js.map +0 -1
- package/build/es2019/types/update-stepwise-factory-factory.d.ts +0 -4
- package/build/es2019/types/update-stepwise-factory-factory.d.ts.map +0 -1
- package/build/es2019/types/update-stepwise-factory-factory.js +0 -2
- package/build/es2019/types/update-stepwise-factory-factory.js.map +0 -1
- package/build/es2019/types/update-stepwise-factory.d.ts +0 -3
- package/build/es2019/types/update-stepwise-factory.d.ts.map +0 -1
- package/build/es2019/types/update-stepwise-factory.js +0 -2
- package/build/es2019/types/update-stepwise-factory.js.map +0 -1
- package/build/es2019/types/window-factory.d.ts +0 -2
- package/build/es2019/types/window-factory.d.ts.map +0 -1
- package/build/es2019/types/window-factory.js +0 -2
- package/build/es2019/types/window-factory.js.map +0 -1
- package/src/types/default-timingsrc-factory.ts +0 -15
- package/src/types/determine-supported-playback-rate-values-function.ts +0 -1
- package/src/types/pause-function.ts +0 -1
- package/src/types/play-function.ts +0 -1
- package/src/types/set-current-time-factory.ts +0 -3
- package/src/types/set-current-time-function.ts +0 -1
- package/src/types/set-playback-rate-factory.ts +0 -3
- package/src/types/set-playback-rate-function.ts +0 -1
- package/src/types/set-timingsrc-factory.ts +0 -8
- package/src/types/set-timingsrc-function.ts +0 -8
- package/src/types/set-timingsrc-with-custom-update-function-factory.ts +0 -10
- package/src/types/set-timingsrc-with-custom-update-function-function.ts +0 -10
- package/src/types/update-gradually-factory.ts +0 -9
- package/src/types/update-media-element-factory.ts +0 -12
- package/src/types/update-media-element-function.ts +0 -8
- package/src/types/update-stepwise-factory-factory.ts +0 -4
- package/src/types/update-stepwise-factory.ts +0 -3
- package/src/types/window-factory.ts +0 -1
|
@@ -1,36 +1,79 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { TAnimationFrameFunction, TOnFunction } from 'subscribable-things';
|
|
2
|
+
import type { ITimingObject } from 'timing-object';
|
|
3
|
+
import { IUpdateVector } from '../interfaces';
|
|
4
|
+
import { TPrepareTimingStateVectorFunction, TUpdateFunction } from '../types';
|
|
5
|
+
import type { createUpdateMediaElement } from './update-media-element';
|
|
2
6
|
|
|
3
|
-
export const createSetTimingsrcWithCustomUpdateFunction
|
|
4
|
-
animationFrame,
|
|
5
|
-
document,
|
|
6
|
-
on,
|
|
7
|
-
updateMediaElement
|
|
7
|
+
export const createSetTimingsrcWithCustomUpdateFunction = (
|
|
8
|
+
animationFrame: TAnimationFrameFunction,
|
|
9
|
+
document: Document,
|
|
10
|
+
on: TOnFunction,
|
|
11
|
+
updateMediaElement: ReturnType<typeof createUpdateMediaElement>
|
|
8
12
|
) => {
|
|
9
|
-
return
|
|
13
|
+
return <UpdateVectorWithCustomState extends IUpdateVector>(
|
|
14
|
+
mediaElement: HTMLMediaElement,
|
|
15
|
+
timingObject: ITimingObject,
|
|
16
|
+
updateFunction: TUpdateFunction<UpdateVectorWithCustomState>,
|
|
17
|
+
prepareTimingStateVector: null | TPrepareTimingStateVectorFunction = null
|
|
18
|
+
) => {
|
|
19
|
+
let previousUpdateVectorWithCustomState: null | UpdateVectorWithCustomState = null;
|
|
20
|
+
|
|
10
21
|
const update = () => {
|
|
11
22
|
const { currentTime, duration, playbackRate } = mediaElement;
|
|
12
23
|
const timingStateVector = timingObject.query();
|
|
13
|
-
|
|
24
|
+
|
|
25
|
+
previousUpdateVectorWithCustomState = updateFunction(
|
|
14
26
|
prepareTimingStateVector === null ? timingStateVector : prepareTimingStateVector(timingStateVector),
|
|
15
|
-
currentTime
|
|
27
|
+
currentTime,
|
|
28
|
+
previousUpdateVectorWithCustomState
|
|
16
29
|
);
|
|
30
|
+
|
|
17
31
|
const sanitizedDuration = typeof duration === 'number' && !isNaN(duration) ? duration : 0;
|
|
32
|
+
const { position, velocity } = previousUpdateVectorWithCustomState;
|
|
18
33
|
|
|
19
34
|
updateMediaElement(currentTime, sanitizedDuration, mediaElement, playbackRate, position, velocity);
|
|
35
|
+
|
|
36
|
+
return velocity !== 0;
|
|
20
37
|
};
|
|
21
38
|
|
|
22
|
-
|
|
23
|
-
|
|
39
|
+
let unsubscribe: () => void;
|
|
40
|
+
|
|
41
|
+
const updateOnce = () => {
|
|
42
|
+
if (!update()) {
|
|
43
|
+
unsubscribe();
|
|
44
|
+
|
|
45
|
+
unsubscribe = updateReactively();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const updateConsistently = () => {
|
|
49
|
+
const unsubscribeFunctions = [
|
|
50
|
+
animationFrame()(() => updateOnce()),
|
|
51
|
+
on(
|
|
52
|
+
timingObject,
|
|
53
|
+
'change'
|
|
54
|
+
)(() => {
|
|
55
|
+
if (document.visibilityState === 'hidden') {
|
|
56
|
+
updateOnce();
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
return () => unsubscribeFunctions.forEach((unsubscribeFunction) => unsubscribeFunction());
|
|
62
|
+
};
|
|
63
|
+
const updateReactively = () =>
|
|
24
64
|
on(
|
|
25
65
|
timingObject,
|
|
26
66
|
'change'
|
|
27
67
|
)(() => {
|
|
28
|
-
if (
|
|
29
|
-
|
|
68
|
+
if (update()) {
|
|
69
|
+
unsubscribe();
|
|
70
|
+
|
|
71
|
+
unsubscribe = updateConsistently();
|
|
30
72
|
}
|
|
31
|
-
})
|
|
32
|
-
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
unsubscribe = update() ? updateConsistently() : updateReactively();
|
|
33
76
|
|
|
34
|
-
return () =>
|
|
77
|
+
return () => unsubscribe();
|
|
35
78
|
};
|
|
36
79
|
};
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ITimingObject } from 'timing-object';
|
|
2
|
+
import type { createSetTimingsrcWithCustomUpdateFunction } from '../factories/set-timingsrc-with-custom-update-function';
|
|
3
|
+
import { IUpdateVector } from '../interfaces';
|
|
4
|
+
import { TPrepareTimingStateVectorFunction, TUpdateFunction } from '../types';
|
|
2
5
|
|
|
3
|
-
export const createSetTimingsrc
|
|
4
|
-
|
|
6
|
+
export const createSetTimingsrc =
|
|
7
|
+
<UpdateVectorWithCustomState extends IUpdateVector>(
|
|
8
|
+
setTimingsrcWithCustomUpdateFunction: ReturnType<typeof createSetTimingsrcWithCustomUpdateFunction>,
|
|
9
|
+
update: TUpdateFunction<UpdateVectorWithCustomState>
|
|
10
|
+
) =>
|
|
11
|
+
(
|
|
12
|
+
mediaElement: HTMLMediaElement,
|
|
13
|
+
timingObject: ITimingObject,
|
|
14
|
+
prepareTimingStateVector: null | TPrepareTimingStateVectorFunction = null
|
|
15
|
+
) =>
|
|
5
16
|
setTimingsrcWithCustomUpdateFunction(mediaElement, timingObject, update, prepareTimingStateVector);
|
|
6
|
-
};
|
|
@@ -1,29 +1,58 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { determineSupportedPlaybackRateValues } from '../functions/determine-supported-playback-rate-values';
|
|
2
|
+
import type { updateVectorWithNewPosition as updateVectorWithNewPositionFunction } from '../functions/update-vector-with-new-position';
|
|
3
|
+
import { IUpdateVector } from '../interfaces';
|
|
4
|
+
import { TUpdateFunction } from '../types';
|
|
5
|
+
import type { createComputeVelocity } from './compute-velocity';
|
|
6
|
+
|
|
7
|
+
export const createUpdateGradually = (
|
|
8
|
+
computeVelocity: ReturnType<typeof createComputeVelocity>,
|
|
9
|
+
[minValue, maxValue]: ReturnType<typeof determineSupportedPlaybackRateValues>,
|
|
10
|
+
threshold: number,
|
|
11
|
+
tolerance: number,
|
|
12
|
+
updateVectorWithNewPosition: typeof updateVectorWithNewPositionFunction
|
|
13
|
+
): TUpdateFunction<IUpdateVector & { mediaElementDelay: number }> => {
|
|
14
|
+
return ({ position, velocity }, currentTime, previousUpdateVectorWithCustomState) => {
|
|
15
|
+
let { mediaElementDelay } = previousUpdateVectorWithCustomState ?? { mediaElementDelay: 0 };
|
|
2
16
|
|
|
3
|
-
export const createUpdateGradually: TUpdateGraduallyFactory = ([minValue, maxValue], timeConstant, threshold, tolerance) => {
|
|
4
|
-
return ({ position, velocity }, currentTime) => {
|
|
5
17
|
if (velocity < minValue || velocity > maxValue) {
|
|
6
|
-
return { position, velocity: 0 };
|
|
18
|
+
return { mediaElementDelay, position, velocity: 0 };
|
|
7
19
|
}
|
|
8
20
|
|
|
9
21
|
if (position < 0 || velocity === 0) {
|
|
10
|
-
return { position, velocity };
|
|
22
|
+
return { mediaElementDelay, position, velocity };
|
|
11
23
|
}
|
|
12
24
|
|
|
13
25
|
const positionDifference = currentTime - position;
|
|
14
26
|
const absolutePositionDifference = Math.abs(positionDifference);
|
|
15
27
|
|
|
16
28
|
if (absolutePositionDifference > threshold) {
|
|
17
|
-
|
|
29
|
+
const { position: lastPosition } = previousUpdateVectorWithCustomState ?? { position: null };
|
|
30
|
+
|
|
31
|
+
if (positionDifference < 0 || positionDifference > mediaElementDelay) {
|
|
32
|
+
if (lastPosition === currentTime) {
|
|
33
|
+
mediaElementDelay += absolutePositionDifference;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return updateVectorWithNewPosition(mediaElementDelay, position, (nextPosition) =>
|
|
37
|
+
computeVelocity(nextPosition - position, minValue, maxValue, velocity)
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (lastPosition !== currentTime) {
|
|
42
|
+
return updateVectorWithNewPosition(mediaElementDelay - absolutePositionDifference, position, (nextPosition) =>
|
|
43
|
+
computeVelocity(nextPosition - position, minValue, maxValue, velocity)
|
|
44
|
+
);
|
|
45
|
+
}
|
|
18
46
|
}
|
|
19
47
|
|
|
20
48
|
if (absolutePositionDifference > tolerance) {
|
|
21
49
|
return {
|
|
50
|
+
mediaElementDelay,
|
|
22
51
|
position: currentTime,
|
|
23
|
-
velocity:
|
|
52
|
+
velocity: computeVelocity(positionDifference, minValue, maxValue, velocity)
|
|
24
53
|
};
|
|
25
54
|
}
|
|
26
55
|
|
|
27
|
-
return { position: currentTime, velocity };
|
|
56
|
+
return { mediaElementDelay, position: currentTime, velocity };
|
|
28
57
|
};
|
|
29
58
|
};
|
|
@@ -1,7 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { pause as pauseFunction } from '../functions/pause';
|
|
2
|
+
import type { play as playFunction } from '../functions/play';
|
|
3
|
+
import type { createSetCurrentTime } from './set-current-time';
|
|
4
|
+
import type { createSetPlaybackRate } from './set-playback-rate';
|
|
2
5
|
|
|
3
|
-
export const createUpdateMediaElement
|
|
4
|
-
|
|
6
|
+
export const createUpdateMediaElement = (
|
|
7
|
+
pause: typeof pauseFunction,
|
|
8
|
+
play: typeof playFunction,
|
|
9
|
+
setCurrentTime: ReturnType<typeof createSetCurrentTime>,
|
|
10
|
+
setPlaybackRate: ReturnType<typeof createSetPlaybackRate>
|
|
11
|
+
) => {
|
|
12
|
+
return (
|
|
13
|
+
currentTime: number,
|
|
14
|
+
duration: number,
|
|
15
|
+
mediaElement: HTMLMediaElement,
|
|
16
|
+
playbackRate: number,
|
|
17
|
+
position: number,
|
|
18
|
+
velocity: number
|
|
19
|
+
) => {
|
|
5
20
|
if (position < 0) {
|
|
6
21
|
if (currentTime > 0) {
|
|
7
22
|
setCurrentTime(mediaElement, currentTime, 0);
|
|
@@ -1,57 +1,152 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { TTranslateTimingStateVectorFunction } from 'timing-object';
|
|
2
|
+
import { IUpdateVector } from '../interfaces';
|
|
3
|
+
import { TUpdateFunction } from '../types';
|
|
4
|
+
|
|
5
|
+
const MAXIMUM_PLAYHEAD_DIFFERENCE = 0.5;
|
|
6
|
+
|
|
7
|
+
export const createUpdateStepwiseFactory = (translateTimingStateVector: TTranslateTimingStateVectorFunction) => {
|
|
8
|
+
return (
|
|
9
|
+
tolerance: number
|
|
10
|
+
): TUpdateFunction<
|
|
11
|
+
IUpdateVector & {
|
|
12
|
+
lastAppliedPostion: number;
|
|
13
|
+
lastAppliedTimestamp: number;
|
|
14
|
+
lastAppliedVelocity: number;
|
|
15
|
+
lastPlayheadDifference: number;
|
|
16
|
+
mediaElementDelay: number;
|
|
17
|
+
numberOfDetectedResets: number;
|
|
18
|
+
numberOfExpectedResets: number;
|
|
19
|
+
}
|
|
20
|
+
> => {
|
|
21
|
+
return (timingStateVector, currentTime, previousUpdateVectorWithCustomState) => {
|
|
22
|
+
let {
|
|
23
|
+
lastAppliedPostion,
|
|
24
|
+
lastAppliedTimestamp,
|
|
25
|
+
lastAppliedVelocity,
|
|
26
|
+
lastPlayheadDifference,
|
|
27
|
+
mediaElementDelay,
|
|
28
|
+
numberOfDetectedResets,
|
|
29
|
+
numberOfExpectedResets
|
|
30
|
+
} = previousUpdateVectorWithCustomState ?? {
|
|
31
|
+
lastAppliedPostion: 0,
|
|
32
|
+
lastAppliedTimestamp: 0,
|
|
33
|
+
lastAppliedVelocity: 0,
|
|
34
|
+
lastPlayheadDifference: 0,
|
|
35
|
+
mediaElementDelay: 0,
|
|
36
|
+
numberOfDetectedResets: 0,
|
|
37
|
+
numberOfExpectedResets: 1
|
|
38
|
+
};
|
|
2
39
|
|
|
3
|
-
export const createUpdateStepwiseFactory: TUpdateStepwiseFactoryFactory = (translateTimingStateVector) => {
|
|
4
|
-
return (tolerance) => {
|
|
5
|
-
let lastMotionUpdate: null | { position: number; timestamp: number; velocity: number } = null;
|
|
6
|
-
let lastPlayheadDifference = 0;
|
|
7
|
-
let mediaElementDelay = 0;
|
|
8
|
-
|
|
9
|
-
return (timingStateVector, currentTime) => {
|
|
10
40
|
if (timingStateVector.position < 0 || timingStateVector.velocity === 0) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
41
|
+
lastAppliedPostion = timingStateVector.position;
|
|
42
|
+
lastAppliedVelocity = timingStateVector.velocity;
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
lastAppliedPostion,
|
|
46
|
+
lastAppliedTimestamp: 0,
|
|
47
|
+
lastAppliedVelocity,
|
|
48
|
+
lastPlayheadDifference,
|
|
49
|
+
mediaElementDelay,
|
|
50
|
+
numberOfDetectedResets,
|
|
51
|
+
numberOfExpectedResets,
|
|
52
|
+
position: lastAppliedPostion,
|
|
53
|
+
velocity: lastAppliedVelocity
|
|
54
|
+
};
|
|
14
55
|
}
|
|
15
56
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (
|
|
57
|
+
// Bug #4: Safari decreases currentTime after playing for about 200 milliseconds.
|
|
58
|
+
if (lastAppliedVelocity === timingStateVector.velocity && lastPlayheadDifference < MAXIMUM_PLAYHEAD_DIFFERENCE) {
|
|
59
|
+
const playheadDifference = Math.abs(currentTime - lastAppliedPostion) * lastAppliedVelocity;
|
|
60
|
+
|
|
61
|
+
if (playheadDifference < MAXIMUM_PLAYHEAD_DIFFERENCE) {
|
|
62
|
+
if (playheadDifference + 0.001 > lastPlayheadDifference) {
|
|
63
|
+
lastPlayheadDifference = playheadDifference;
|
|
64
|
+
|
|
65
|
+
if (numberOfDetectedResets < numberOfExpectedResets) {
|
|
66
|
+
return {
|
|
67
|
+
lastAppliedPostion,
|
|
68
|
+
lastAppliedTimestamp,
|
|
69
|
+
lastAppliedVelocity,
|
|
70
|
+
lastPlayheadDifference,
|
|
71
|
+
mediaElementDelay,
|
|
72
|
+
numberOfDetectedResets,
|
|
73
|
+
numberOfExpectedResets,
|
|
74
|
+
position: currentTime,
|
|
75
|
+
velocity: lastAppliedVelocity
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
lastPlayheadDifference = playheadDifference;
|
|
80
|
+
numberOfDetectedResets += 1;
|
|
81
|
+
|
|
82
|
+
if (numberOfDetectedResets <= numberOfExpectedResets) {
|
|
83
|
+
return {
|
|
84
|
+
lastAppliedPostion,
|
|
85
|
+
lastAppliedTimestamp,
|
|
86
|
+
lastAppliedVelocity,
|
|
87
|
+
lastPlayheadDifference,
|
|
88
|
+
mediaElementDelay,
|
|
89
|
+
numberOfDetectedResets,
|
|
90
|
+
numberOfExpectedResets,
|
|
91
|
+
position: currentTime,
|
|
92
|
+
velocity: lastAppliedVelocity
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
numberOfExpectedResets += 1;
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
21
99
|
lastPlayheadDifference = playheadDifference;
|
|
22
|
-
|
|
23
|
-
return { position: currentTime, velocity: lastMotionUpdate.velocity };
|
|
100
|
+
numberOfExpectedResets = Math.max(numberOfDetectedResets, 1);
|
|
24
101
|
}
|
|
25
|
-
|
|
26
|
-
|
|
102
|
+
} else {
|
|
103
|
+
lastAppliedTimestamp = 0;
|
|
27
104
|
}
|
|
28
105
|
|
|
29
106
|
const positionDifference = Math.abs(currentTime - timingStateVector.position);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
107
|
+
const velocityHasChanged =
|
|
108
|
+
lastAppliedVelocity === 0 ||
|
|
109
|
+
(lastAppliedVelocity < 0 && timingStateVector.velocity > 0) ||
|
|
110
|
+
(lastAppliedVelocity > 0 && timingStateVector.velocity < 0);
|
|
111
|
+
|
|
112
|
+
if (positionDifference > tolerance || velocityHasChanged) {
|
|
113
|
+
if (lastAppliedTimestamp > 0) {
|
|
114
|
+
const elapsedTime = timingStateVector.timestamp - lastAppliedTimestamp;
|
|
115
|
+
const { position } = translateTimingStateVector(
|
|
116
|
+
{ acceleration: 0, position: lastAppliedPostion, timestamp: lastAppliedTimestamp, velocity: lastAppliedVelocity },
|
|
117
|
+
elapsedTime
|
|
118
|
+
);
|
|
36
119
|
|
|
37
120
|
mediaElementDelay = position - currentTime;
|
|
38
121
|
}
|
|
39
122
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
123
|
+
lastAppliedPostion = timingStateVector.position + mediaElementDelay;
|
|
124
|
+
lastAppliedVelocity = timingStateVector.velocity;
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
lastAppliedPostion,
|
|
128
|
+
lastAppliedTimestamp: timingStateVector.timestamp,
|
|
129
|
+
lastAppliedVelocity,
|
|
130
|
+
lastPlayheadDifference: 0,
|
|
131
|
+
mediaElementDelay,
|
|
132
|
+
numberOfDetectedResets: 0,
|
|
133
|
+
numberOfExpectedResets,
|
|
134
|
+
position: lastAppliedPostion,
|
|
135
|
+
velocity: lastAppliedVelocity
|
|
46
136
|
};
|
|
47
|
-
lastPlayheadDifference = 0;
|
|
48
|
-
|
|
49
|
-
return { position: positioWithDelay, velocity: timingStateVector.velocity };
|
|
50
137
|
}
|
|
51
138
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
139
|
+
return {
|
|
140
|
+
lastAppliedPostion,
|
|
141
|
+
lastAppliedTimestamp,
|
|
142
|
+
lastAppliedVelocity,
|
|
143
|
+
lastPlayheadDifference,
|
|
144
|
+
mediaElementDelay,
|
|
145
|
+
numberOfDetectedResets,
|
|
146
|
+
numberOfExpectedResets,
|
|
147
|
+
position: currentTime,
|
|
148
|
+
velocity: timingStateVector.velocity
|
|
149
|
+
};
|
|
55
150
|
};
|
|
56
151
|
};
|
|
57
152
|
};
|
package/src/factories/window.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { createWindow } from '../factories/window';
|
|
2
|
+
|
|
1
3
|
const DEFAULT_VALUES = [Number.MIN_VALUE, Number.MAX_VALUE] as const;
|
|
2
4
|
|
|
3
|
-
export const determineSupportedPlaybackRateValues = (window:
|
|
5
|
+
export const determineSupportedPlaybackRateValues = (window: ReturnType<typeof createWindow>): readonly [number, number] => {
|
|
4
6
|
if (window === null) {
|
|
5
7
|
return DEFAULT_VALUES;
|
|
6
8
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const updateVectorWithNewPosition = (
|
|
2
|
+
mediaElementDelay: number,
|
|
3
|
+
position: number,
|
|
4
|
+
updateVelocity: (nextPosition: number) => number
|
|
5
|
+
) => {
|
|
6
|
+
const nextPosition = position + mediaElementDelay;
|
|
7
|
+
|
|
8
|
+
return { mediaElementDelay, position: nextPosition, velocity: updateVelocity(nextPosition) };
|
|
9
|
+
};
|
package/src/module.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { animationFrame, on } from 'subscribable-things';
|
|
2
2
|
import { translateTimingStateVector } from 'timing-object';
|
|
3
|
+
import { createComputeVelocity } from './factories/compute-velocity';
|
|
3
4
|
import { createDefaultSetTimingsrc } from './factories/default-set-timingsrc';
|
|
4
5
|
import { createSetCurrentTime } from './factories/set-current-time';
|
|
5
6
|
import { createSetPlaybackRate } from './factories/set-playback-rate';
|
|
@@ -12,6 +13,7 @@ import { createWindow } from './factories/window';
|
|
|
12
13
|
import { determineSupportedPlaybackRateValues } from './functions/determine-supported-playback-rate-values';
|
|
13
14
|
import { pause } from './functions/pause';
|
|
14
15
|
import { play } from './functions/play';
|
|
16
|
+
import { updateVectorWithNewPosition } from './functions/update-vector-with-new-position';
|
|
15
17
|
|
|
16
18
|
export { createSetTimingsrc };
|
|
17
19
|
|
|
@@ -29,10 +31,12 @@ export const setTimingsrcWithCustomUpdateFunction = createSetTimingsrcWithCustom
|
|
|
29
31
|
);
|
|
30
32
|
|
|
31
33
|
export const setTimingsrc = createDefaultSetTimingsrc(
|
|
34
|
+
createComputeVelocity,
|
|
32
35
|
createSetTimingsrc,
|
|
33
36
|
createUpdateGradually,
|
|
34
37
|
createUpdateStepwise,
|
|
35
38
|
determineSupportedPlaybackRateValues,
|
|
36
39
|
setTimingsrcWithCustomUpdateFunction,
|
|
40
|
+
updateVectorWithNewPosition,
|
|
37
41
|
createWindow()
|
|
38
42
|
);
|
package/src/types/index.ts
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
export * from './default-timingsrc-factory';
|
|
2
|
-
export * from './determine-supported-playback-rate-values-function';
|
|
3
|
-
export * from './pause-function';
|
|
4
|
-
export * from './play-function';
|
|
5
1
|
export * from './prepare-timing-state-vector-function';
|
|
6
|
-
export * from './set-current-time-factory';
|
|
7
|
-
export * from './set-current-time-function';
|
|
8
|
-
export * from './set-playback-rate-factory';
|
|
9
|
-
export * from './set-playback-rate-function';
|
|
10
|
-
export * from './set-timingsrc-factory';
|
|
11
|
-
export * from './set-timingsrc-function';
|
|
12
|
-
export * from './set-timingsrc-with-custom-update-function-factory';
|
|
13
|
-
export * from './set-timingsrc-with-custom-update-function-function';
|
|
14
2
|
export * from './update-function';
|
|
15
|
-
export * from './update-
|
|
16
|
-
export * from './update-media-element-factory';
|
|
17
|
-
export * from './update-stepwise-factory';
|
|
18
|
-
export * from './update-stepwise-factory-factory';
|
|
19
|
-
export * from './window-factory';
|
|
3
|
+
export * from './update-vector-with-custom-state';
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { ITimingStateVector } from 'timing-object';
|
|
2
2
|
import { IUpdateVector } from '../interfaces';
|
|
3
3
|
|
|
4
|
-
export type TUpdateFunction = (
|
|
4
|
+
export type TUpdateFunction<UpdateVectorWithCustomState extends IUpdateVector> = (
|
|
5
|
+
timingStateVector: ITimingStateVector,
|
|
6
|
+
currentTime: number,
|
|
7
|
+
previousUpdateVectorWithCustomState: null | UpdateVectorWithCustomState
|
|
8
|
+
) => UpdateVectorWithCustomState;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { TDetermineSupportedPlaybackRateValuesFunction } from './determine-supported-playback-rate-values-function';
|
|
2
|
-
import { TSetTimingsrcFactory } from './set-timingsrc-factory';
|
|
3
|
-
import { TSetTimingsrcFunction } from './set-timingsrc-function';
|
|
4
|
-
import { TSetTimingsrcWithCustomUpdateFunctionFunction } from './set-timingsrc-with-custom-update-function-function';
|
|
5
|
-
import { TUpdateGraduallyFactory } from './update-gradually-factory';
|
|
6
|
-
import { TUpdateStepwiseFactory } from './update-stepwise-factory';
|
|
7
|
-
export declare type TDefaultSetTimingsrcFactory = (createSetTimingsrc: TSetTimingsrcFactory, createUpdateGradually: TUpdateGraduallyFactory, createUpdateStepwise: TUpdateStepwiseFactory, determineSupportedPlaybackRateValues: TDetermineSupportedPlaybackRateValuesFunction, setTimingsrcWithCustomUpdateFunction: TSetTimingsrcWithCustomUpdateFunctionFunction, window: null | (Window & typeof globalThis)) => TSetTimingsrcFunction;
|
|
8
|
-
//# sourceMappingURL=default-timingsrc-factory.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"default-timingsrc-factory.d.ts","sourceRoot":"","sources":["../../../src/types/default-timingsrc-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6CAA6C,EAAE,MAAM,qDAAqD,CAAC;AACpH,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,6CAA6C,EAAE,MAAM,sDAAsD,CAAC;AACrH,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,oBAAY,2BAA2B,GAAG,CACtC,kBAAkB,EAAE,oBAAoB,EACxC,qBAAqB,EAAE,uBAAuB,EAC9C,oBAAoB,EAAE,sBAAsB,EAC5C,oCAAoC,EAAE,6CAA6C,EACnF,oCAAoC,EAAE,6CAA6C,EACnF,MAAM,EAAE,IAAI,GAAG,CAAC,MAAM,GAAG,OAAO,UAAU,CAAC,KAC1C,qBAAqB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"default-timingsrc-factory.js","sourceRoot":"","sources":["../../../src/types/default-timingsrc-factory.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"determine-supported-playback-rate-values-function.d.ts","sourceRoot":"","sources":["../../../src/types/determine-supported-playback-rate-values-function.ts"],"names":[],"mappings":"AAAA,oBAAY,6CAA6C,GAAG,CAAC,MAAM,EAAE,IAAI,GAAG,CAAC,MAAM,GAAG,OAAO,UAAU,CAAC,KAAK,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"determine-supported-playback-rate-values-function.js","sourceRoot":"","sources":["../../../src/types/determine-supported-playback-rate-values-function.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pause-function.d.ts","sourceRoot":"","sources":["../../../src/types/pause-function.ts"],"names":[],"mappings":"AAAA,oBAAY,cAAc,GAAG,CAAC,YAAY,EAAE,gBAAgB,KAAK,IAAI,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pause-function.js","sourceRoot":"","sources":["../../../src/types/pause-function.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"play-function.d.ts","sourceRoot":"","sources":["../../../src/types/play-function.ts"],"names":[],"mappings":"AAAA,oBAAY,aAAa,GAAG,CAAC,YAAY,EAAE,gBAAgB,KAAK,IAAI,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"play-function.js","sourceRoot":"","sources":["../../../src/types/play-function.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set-current-time-factory.d.ts","sourceRoot":"","sources":["../../../src/types/set-current-time-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,oBAAY,sBAAsB,GAAG,CAAC,sBAAsB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,uBAAuB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set-current-time-factory.js","sourceRoot":"","sources":["../../../src/types/set-current-time-factory.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set-current-time-function.d.ts","sourceRoot":"","sources":["../../../src/types/set-current-time-function.ts"],"names":[],"mappings":"AAAA,oBAAY,uBAAuB,GAAG,CAAC,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set-current-time-function.js","sourceRoot":"","sources":["../../../src/types/set-current-time-function.ts"],"names":[],"mappings":""}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import { TSetPlaybackRateFunction } from './set-playback-rate-function';
|
|
2
|
-
export declare type TSetPlaybackRateFactory = (playbackRateAssignments: WeakMap<HTMLMediaElement, [number, number]>) => TSetPlaybackRateFunction;
|
|
3
|
-
//# sourceMappingURL=set-playback-rate-factory.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set-playback-rate-factory.d.ts","sourceRoot":"","sources":["../../../src/types/set-playback-rate-factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAExE,oBAAY,uBAAuB,GAAG,CAAC,uBAAuB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,wBAAwB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set-playback-rate-factory.js","sourceRoot":"","sources":["../../../src/types/set-playback-rate-factory.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"set-playback-rate-function.d.ts","sourceRoot":"","sources":["../../../src/types/set-playback-rate-function.ts"],"names":[],"mappings":"AAAA,oBAAY,wBAAwB,GAAG,CAAC,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC"}
|