@ldelia/react-media 0.2.8 → 0.4.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/.storybook/main.js +25 -2
- package/README.md +1 -4
- package/config/env.js +104 -0
- package/config/getHttpsConfig.js +66 -0
- package/config/jest/babelTransform.js +29 -0
- package/config/jest/cssTransform.js +14 -0
- package/config/jest/fileTransform.js +40 -0
- package/config/modules.js +134 -0
- package/config/paths.js +77 -0
- package/config/webpack/persistentCache/createEnvironmentHash.js +9 -0
- package/config/webpack.config.js +755 -0
- package/config/webpackDevServer.config.js +127 -0
- package/dist/stories/timeline.stories.d.ts +6 -6
- package/package.json +127 -18
- package/scripts/build.js +217 -0
- package/scripts/start.js +154 -0
- package/scripts/test.js +52 -0
- package/src/components/__tests__/timeline/timeline.test.js +22 -0
- package/src/components/index.js +1 -0
- package/src/components/reproduction-widget/README.md +27 -0
- package/src/components/reproduction-widget/ReproductionWidget.js +29 -0
- package/src/components/reproduction-widget/ReproductionWidget.tsx +68 -0
- package/src/components/reproduction-widget/index.js +1 -0
- package/src/components/reproduction-widget/index.tsx +1 -0
- package/src/components/reproduction-widget/inner-players/PlayAlongInnerPlayer.js +5 -0
- package/src/components/reproduction-widget/inner-players/PlayAlongInnerPlayer.tsx +10 -0
- package/src/components/reproduction-widget/inner-players/YouTubeInnerPlayer.js +21 -0
- package/src/components/reproduction-widget/inner-players/YouTubeInnerPlayer.tsx +36 -0
- package/src/components/reproduction-widget/models/Player/PlayAlongPlayer.js +97 -0
- package/src/components/reproduction-widget/models/Player/PlayAlongPlayer.ts +129 -0
- package/src/components/reproduction-widget/models/Player/PlayerEvents.js +4 -0
- package/src/components/reproduction-widget/models/Player/PlayerEvents.ts +4 -0
- package/src/components/reproduction-widget/models/Player/YouTubePlayer.js +126 -0
- package/src/components/reproduction-widget/models/Player/YouTubePlayer.ts +171 -0
- package/src/components/reproduction-widget/models/Reproduction.js +214 -0
- package/src/components/reproduction-widget/models/Reproduction.ts +272 -0
- package/src/components/reproduction-widget/models/ReproductionBuilder.js +51 -0
- package/src/components/reproduction-widget/models/ReproductionBuilder.ts +70 -0
- package/{dist/components/timeline → src/components/timeline/RangeSelectorCanvas}/RangeSelectorCanvas.js +16 -22
- package/src/components/timeline/Timeline.js +77 -0
- package/src/components/timeline/TimelineCanvas/TickTime.js +26 -0
- package/src/components/timeline/TimelineCanvas/TickTimeCollectionDisplay.js +19 -0
- package/src/components/timeline/TimelineCanvas/TimelineCanvas.js +44 -0
- package/src/components/timeline/TimelineCanvas/drawTimeBlocksOnCanvas.js +28 -0
- package/src/components/timeline/TimelineValue/TimelineValue.js +50 -0
- package/src/components/timeline/ZoomContext/ZoomContext.js +2 -0
- package/src/components/timeline/constants.js +13 -0
- package/src/components/timeline/index.js +1 -0
- package/src/components/timeline/utils/utils.js +28 -0
- package/src/index.js +1 -0
- package/src/react-app-env.d.ts +71 -1
- package/src/react-docgen-types.d.ts +37 -0
- package/src/setupTests.js +5 -0
- package/src/stories/reproduction-widget.stories.js +16 -0
- package/src/stories/reproduction-widget.stories.tsx +23 -0
- package/src/stories/timeline.stories.js +54 -0
- package/storybook-static/favicon.svg +1 -0
- package/storybook-static/index.html +173 -0
- package/storybook-static/index.json +1 -0
- package/storybook-static/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/project.json +1 -0
- package/storybook-static/sb-addons/essentials-actions-3/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-actions-3/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-backgrounds-4/manager-bundle.js +12 -0
- package/storybook-static/sb-addons/essentials-backgrounds-4/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-controls-2/manager-bundle.js +412 -0
- package/storybook-static/sb-addons/essentials-controls-2/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-measure-7/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-measure-7/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-outline-8/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-outline-8/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-toolbars-6/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-toolbars-6/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/essentials-viewport-5/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/essentials-viewport-5/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/links-1/manager-bundle.js +3 -0
- package/storybook-static/sb-addons/links-1/manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js +3 -0
- package/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js.LEGAL.txt +0 -0
- package/storybook-static/sb-common-assets/favicon.svg +1 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
- package/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
- package/storybook-static/sb-manager/globals-module-info.js +995 -0
- package/storybook-static/sb-manager/globals-runtime.js +53527 -0
- package/storybook-static/sb-manager/globals.js +48 -0
- package/storybook-static/sb-manager/runtime.js +11885 -0
- package/storybook-static/sb-preview/globals.js +33 -0
- package/storybook-static/sb-preview/runtime.js +9483 -0
- package/tsconfig.json +8 -7
- package/.storybook/main.ts +0 -18
- package/.storybook/preview.ts +0 -14
- package/dist/components/timeline/RangeSelectorCanvas.d.ts +0 -8
- package/dist/components/timeline/TickTime.d.ts +0 -7
- package/dist/components/timeline/TickTime.js +0 -31
- package/dist/components/timeline/TickTimeCollectionDisplay.d.ts +0 -6
- package/dist/components/timeline/TickTimeCollectionDisplay.js +0 -24
- package/dist/components/timeline/VaLueLineCanvas.d.ts +0 -7
- package/dist/components/timeline/VaLueLineCanvas.js +0 -111
- package/dist/reportWebVitals.d.ts +0 -3
- package/dist/reportWebVitals.js +0 -37
- package/src/reportWebVitals.ts +0 -15
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { PlayAlongPlayer } from './PlayAlongPlayer';
|
|
2
|
+
import { PLAYER_EVENTS } from './PlayerEvents';
|
|
3
|
+
// https://developers.google.com/youtube/iframe_api_reference
|
|
4
|
+
var INNER_YOUTUBE_PLAYER_EVENTS;
|
|
5
|
+
(function (INNER_YOUTUBE_PLAYER_EVENTS) {
|
|
6
|
+
INNER_YOUTUBE_PLAYER_EVENTS[INNER_YOUTUBE_PLAYER_EVENTS["VIDEO_UNSTARTED"] = -1] = "VIDEO_UNSTARTED";
|
|
7
|
+
INNER_YOUTUBE_PLAYER_EVENTS[INNER_YOUTUBE_PLAYER_EVENTS["VIDEO_ENDED"] = 0] = "VIDEO_ENDED";
|
|
8
|
+
INNER_YOUTUBE_PLAYER_EVENTS[INNER_YOUTUBE_PLAYER_EVENTS["VIDEO_PLAYING"] = 1] = "VIDEO_PLAYING";
|
|
9
|
+
INNER_YOUTUBE_PLAYER_EVENTS[INNER_YOUTUBE_PLAYER_EVENTS["VIDEO_PAUSED"] = 2] = "VIDEO_PAUSED";
|
|
10
|
+
INNER_YOUTUBE_PLAYER_EVENTS[INNER_YOUTUBE_PLAYER_EVENTS["VIDEO_BUFFERING"] = 3] = "VIDEO_BUFFERING";
|
|
11
|
+
INNER_YOUTUBE_PLAYER_EVENTS[INNER_YOUTUBE_PLAYER_EVENTS["VIDEO_CUED"] = 5] = "VIDEO_CUED";
|
|
12
|
+
})(INNER_YOUTUBE_PLAYER_EVENTS || (INNER_YOUTUBE_PLAYER_EVENTS = {}));
|
|
13
|
+
const dispatchOnReadyHandlers = Symbol();
|
|
14
|
+
const dispatchOnFinishHandlers = Symbol();
|
|
15
|
+
export class YouTubePlayer {
|
|
16
|
+
static get EVENTS() {
|
|
17
|
+
return PLAYER_EVENTS;
|
|
18
|
+
}
|
|
19
|
+
constructor(innerPlayer) {
|
|
20
|
+
this[dispatchOnFinishHandlers] = [];
|
|
21
|
+
this[dispatchOnReadyHandlers] = [];
|
|
22
|
+
this.currentTime = 0;
|
|
23
|
+
this.isRunning = false;
|
|
24
|
+
this.setInnerPlayer(innerPlayer);
|
|
25
|
+
}
|
|
26
|
+
setInnerPlayer(innerPlayer) {
|
|
27
|
+
this.innerPlayer = innerPlayer;
|
|
28
|
+
this.dispatch(YouTubePlayer.EVENTS.READY);
|
|
29
|
+
// this is necessary for avoiding the state video cued.
|
|
30
|
+
// When a video is in this state, when user seek to X, the song is played
|
|
31
|
+
this.innerPlayer.playVideo();
|
|
32
|
+
this.innerPlayer.pauseVideo();
|
|
33
|
+
this.innerPlayer.addEventListener('onStateChange', (videoState) => {
|
|
34
|
+
switch (videoState.data) {
|
|
35
|
+
case INNER_YOUTUBE_PLAYER_EVENTS.VIDEO_ENDED:
|
|
36
|
+
this.dispatch(YouTubePlayer.EVENTS.FINISH);
|
|
37
|
+
this.isRunning = false;
|
|
38
|
+
this.currentTime = 0;
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
getInnerPlayer() {
|
|
46
|
+
return this.innerPlayer;
|
|
47
|
+
}
|
|
48
|
+
play() {
|
|
49
|
+
const videoPlayer = this.getInnerPlayer();
|
|
50
|
+
videoPlayer.playVideo();
|
|
51
|
+
this.isRunning = true;
|
|
52
|
+
}
|
|
53
|
+
pause() {
|
|
54
|
+
this.isRunning = false;
|
|
55
|
+
this.getInnerPlayer().pauseVideo();
|
|
56
|
+
this.currentTime = this.getInnerPlayer().getCurrentTime();
|
|
57
|
+
}
|
|
58
|
+
stop() {
|
|
59
|
+
this.isRunning = false;
|
|
60
|
+
/**
|
|
61
|
+
* Hay un issue al llamar a getDuration del video luego de reanudar una canción pausada (devuelve siempre 0)
|
|
62
|
+
* Para evitar que se pierda la información y tener que cargarla de nuevo, se simula un stop pausando y llevando al comienzo
|
|
63
|
+
* videoPlayer.stopVideo();
|
|
64
|
+
*/
|
|
65
|
+
this.getInnerPlayer().pauseVideo();
|
|
66
|
+
this.seekTo(0);
|
|
67
|
+
}
|
|
68
|
+
seekTo(seconds) {
|
|
69
|
+
const videoPlayer = this.getInnerPlayer();
|
|
70
|
+
this.currentTime = seconds;
|
|
71
|
+
videoPlayer.seekTo(this.currentTime);
|
|
72
|
+
if (this.isRunning) {
|
|
73
|
+
this.play();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
getCurrentTime() {
|
|
77
|
+
return this.isRunning
|
|
78
|
+
? this.getInnerPlayer().getCurrentTime()
|
|
79
|
+
: this.currentTime;
|
|
80
|
+
}
|
|
81
|
+
getDuration() {
|
|
82
|
+
if (this.isAvailable()) {
|
|
83
|
+
return this.getInnerPlayer().getDuration();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
getAvailablePlaybackRates() {
|
|
87
|
+
return this.getInnerPlayer().getAvailablePlaybackRates();
|
|
88
|
+
}
|
|
89
|
+
setPlaybackRate(playbackRate) {
|
|
90
|
+
if (!this.getAvailablePlaybackRates().includes(playbackRate)) {
|
|
91
|
+
throw new Error(`The PlayAlongPlayer doesn't support a playbackRate with value ${playbackRate}`);
|
|
92
|
+
}
|
|
93
|
+
this.getInnerPlayer().setPlaybackRate(playbackRate);
|
|
94
|
+
}
|
|
95
|
+
isAvailable() {
|
|
96
|
+
return this.getInnerPlayer() !== null;
|
|
97
|
+
}
|
|
98
|
+
on(eventName, handler) {
|
|
99
|
+
switch (eventName) {
|
|
100
|
+
case PlayAlongPlayer.EVENTS.READY:
|
|
101
|
+
return this[dispatchOnReadyHandlers].push(handler);
|
|
102
|
+
case PlayAlongPlayer.EVENTS.FINISH:
|
|
103
|
+
return this[dispatchOnFinishHandlers].push(handler);
|
|
104
|
+
default:
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
dispatch(eventName) {
|
|
109
|
+
let handler, i, len;
|
|
110
|
+
let ref = [];
|
|
111
|
+
switch (eventName) {
|
|
112
|
+
case YouTubePlayer.EVENTS.READY:
|
|
113
|
+
ref = this[dispatchOnReadyHandlers];
|
|
114
|
+
break;
|
|
115
|
+
case YouTubePlayer.EVENTS.FINISH:
|
|
116
|
+
ref = this[dispatchOnFinishHandlers];
|
|
117
|
+
break;
|
|
118
|
+
default:
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
|
122
|
+
handler = ref[i];
|
|
123
|
+
setTimeout(handler, 0);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { YouTubePlayer as InnerYouTubePlayer } from 'react-youtube';
|
|
2
|
+
import { PlayAlongPlayer } from './PlayAlongPlayer';
|
|
3
|
+
import { PLAYER_EVENTS } from './PlayerEvents';
|
|
4
|
+
|
|
5
|
+
// https://developers.google.com/youtube/iframe_api_reference
|
|
6
|
+
enum INNER_YOUTUBE_PLAYER_EVENTS {
|
|
7
|
+
VIDEO_UNSTARTED = -1,
|
|
8
|
+
VIDEO_ENDED = 0,
|
|
9
|
+
VIDEO_PLAYING = 1,
|
|
10
|
+
VIDEO_PAUSED = 2,
|
|
11
|
+
VIDEO_BUFFERING = 3,
|
|
12
|
+
VIDEO_CUED = 5,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface INNER_YOUTUBE_PLAYER_StateChangeEvent {
|
|
16
|
+
data: INNER_YOUTUBE_PLAYER_EVENTS;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const dispatchOnReadyHandlers = Symbol();
|
|
20
|
+
const dispatchOnFinishHandlers = Symbol();
|
|
21
|
+
|
|
22
|
+
export class YouTubePlayer {
|
|
23
|
+
private currentTime: number;
|
|
24
|
+
private isRunning: boolean;
|
|
25
|
+
private innerPlayer: InnerYouTubePlayer | number;
|
|
26
|
+
private [dispatchOnReadyHandlers]: (() => void)[];
|
|
27
|
+
private [dispatchOnFinishHandlers]: (() => void)[];
|
|
28
|
+
|
|
29
|
+
static get EVENTS() {
|
|
30
|
+
return PLAYER_EVENTS;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
constructor(innerPlayer: InnerYouTubePlayer) {
|
|
34
|
+
this[dispatchOnFinishHandlers] = [];
|
|
35
|
+
this[dispatchOnReadyHandlers] = [];
|
|
36
|
+
|
|
37
|
+
this.currentTime = 0;
|
|
38
|
+
this.isRunning = false;
|
|
39
|
+
|
|
40
|
+
this.setInnerPlayer(innerPlayer);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private setInnerPlayer(innerPlayer: InnerYouTubePlayer) {
|
|
44
|
+
this.innerPlayer = innerPlayer;
|
|
45
|
+
this.dispatch(YouTubePlayer.EVENTS.READY);
|
|
46
|
+
|
|
47
|
+
// this is necessary for avoiding the state video cued.
|
|
48
|
+
// When a video is in this state, when user seek to X, the song is played
|
|
49
|
+
this.innerPlayer.playVideo();
|
|
50
|
+
this.innerPlayer.pauseVideo();
|
|
51
|
+
|
|
52
|
+
this.innerPlayer.addEventListener(
|
|
53
|
+
'onStateChange',
|
|
54
|
+
(videoState: INNER_YOUTUBE_PLAYER_StateChangeEvent) => {
|
|
55
|
+
switch (videoState.data) {
|
|
56
|
+
case INNER_YOUTUBE_PLAYER_EVENTS.VIDEO_ENDED:
|
|
57
|
+
this.dispatch(YouTubePlayer.EVENTS.FINISH);
|
|
58
|
+
this.isRunning = false;
|
|
59
|
+
this.currentTime = 0;
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
getInnerPlayer() {
|
|
69
|
+
return this.innerPlayer;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
play() {
|
|
73
|
+
const videoPlayer = this.getInnerPlayer();
|
|
74
|
+
videoPlayer.playVideo();
|
|
75
|
+
|
|
76
|
+
this.isRunning = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
pause() {
|
|
80
|
+
this.isRunning = false;
|
|
81
|
+
|
|
82
|
+
this.getInnerPlayer().pauseVideo();
|
|
83
|
+
|
|
84
|
+
this.currentTime = this.getInnerPlayer().getCurrentTime();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
stop() {
|
|
88
|
+
this.isRunning = false;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Hay un issue al llamar a getDuration del video luego de reanudar una canción pausada (devuelve siempre 0)
|
|
92
|
+
* Para evitar que se pierda la información y tener que cargarla de nuevo, se simula un stop pausando y llevando al comienzo
|
|
93
|
+
* videoPlayer.stopVideo();
|
|
94
|
+
*/
|
|
95
|
+
this.getInnerPlayer().pauseVideo();
|
|
96
|
+
|
|
97
|
+
this.seekTo(0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
seekTo(seconds: number) {
|
|
101
|
+
const videoPlayer = this.getInnerPlayer();
|
|
102
|
+
this.currentTime = seconds;
|
|
103
|
+
|
|
104
|
+
videoPlayer.seekTo(this.currentTime);
|
|
105
|
+
|
|
106
|
+
if (this.isRunning) {
|
|
107
|
+
this.play();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getCurrentTime() {
|
|
112
|
+
return this.isRunning
|
|
113
|
+
? this.getInnerPlayer().getCurrentTime()
|
|
114
|
+
: this.currentTime;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
getDuration() {
|
|
118
|
+
if (this.isAvailable()) {
|
|
119
|
+
return this.getInnerPlayer().getDuration();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
getAvailablePlaybackRates() {
|
|
124
|
+
return this.getInnerPlayer().getAvailablePlaybackRates();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
setPlaybackRate(playbackRate: number) {
|
|
128
|
+
if (!this.getAvailablePlaybackRates().includes(playbackRate)) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`The PlayAlongPlayer doesn't support a playbackRate with value ${playbackRate}`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
this.getInnerPlayer().setPlaybackRate(playbackRate);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
isAvailable() {
|
|
137
|
+
return this.getInnerPlayer() !== null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
on(eventName: keyof typeof PlayAlongPlayer.EVENTS, handler: () => void) {
|
|
141
|
+
switch (eventName) {
|
|
142
|
+
case PlayAlongPlayer.EVENTS.READY:
|
|
143
|
+
return this[dispatchOnReadyHandlers].push(handler);
|
|
144
|
+
case PlayAlongPlayer.EVENTS.FINISH:
|
|
145
|
+
return this[dispatchOnFinishHandlers].push(handler);
|
|
146
|
+
default:
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
dispatch(eventName: keyof typeof PlayAlongPlayer.EVENTS) {
|
|
152
|
+
let handler, i, len;
|
|
153
|
+
let ref: (() => void)[] = [];
|
|
154
|
+
|
|
155
|
+
switch (eventName) {
|
|
156
|
+
case YouTubePlayer.EVENTS.READY:
|
|
157
|
+
ref = this[dispatchOnReadyHandlers];
|
|
158
|
+
break;
|
|
159
|
+
case YouTubePlayer.EVENTS.FINISH:
|
|
160
|
+
ref = this[dispatchOnFinishHandlers];
|
|
161
|
+
break;
|
|
162
|
+
default:
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
|
167
|
+
handler = ref[i];
|
|
168
|
+
setTimeout(handler, 0);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { PLAYER_EVENTS } from './Player/PlayerEvents';
|
|
2
|
+
import { ReproductionBuilder } from './ReproductionBuilder';
|
|
3
|
+
const STATES = {
|
|
4
|
+
STOPPED: 0,
|
|
5
|
+
COUNTING_IN: 1,
|
|
6
|
+
PLAYING: 2,
|
|
7
|
+
PAUSED: 3,
|
|
8
|
+
};
|
|
9
|
+
const EVENTS = {
|
|
10
|
+
READY: 'READY',
|
|
11
|
+
START: 'START',
|
|
12
|
+
COUNTING_IN: 'COUNTING_IN',
|
|
13
|
+
PLAY: 'PLAY',
|
|
14
|
+
PLAYING: 'PLAYING',
|
|
15
|
+
PAUSED: 'PAUSED',
|
|
16
|
+
FINISH: 'FINISH',
|
|
17
|
+
};
|
|
18
|
+
const dispatchOnReadyHandlers = Symbol();
|
|
19
|
+
const dispatchOnSongStartHandlers = Symbol();
|
|
20
|
+
const dispatchOnCountingInHandlers = Symbol();
|
|
21
|
+
const dispatchOnPlayHandlers = Symbol();
|
|
22
|
+
const dispatchOnPlayingHandlers = Symbol();
|
|
23
|
+
const dispatchOnPausedHandlers = Symbol();
|
|
24
|
+
const dispatchOnFinishHandlers = Symbol();
|
|
25
|
+
export class Reproduction {
|
|
26
|
+
static get EVENTS() {
|
|
27
|
+
return EVENTS;
|
|
28
|
+
}
|
|
29
|
+
static get STATES() {
|
|
30
|
+
return STATES;
|
|
31
|
+
}
|
|
32
|
+
constructor(player, requiresCountingIn, songTempo) {
|
|
33
|
+
this[dispatchOnReadyHandlers] = [];
|
|
34
|
+
this[dispatchOnSongStartHandlers] = [];
|
|
35
|
+
this[dispatchOnCountingInHandlers] = [];
|
|
36
|
+
this[dispatchOnPlayHandlers] = [];
|
|
37
|
+
this[dispatchOnPlayingHandlers] = [];
|
|
38
|
+
this[dispatchOnPausedHandlers] = [];
|
|
39
|
+
this[dispatchOnFinishHandlers] = [];
|
|
40
|
+
this.songTempo = songTempo;
|
|
41
|
+
this.player = player;
|
|
42
|
+
this.ready = false;
|
|
43
|
+
this.state = Reproduction.STATES.STOPPED;
|
|
44
|
+
this.interval = null;
|
|
45
|
+
this.requiresCountingIn = requiresCountingIn;
|
|
46
|
+
this.countingInCounter = 0;
|
|
47
|
+
this.player.on(PLAYER_EVENTS.READY, () => {
|
|
48
|
+
this.ready = true;
|
|
49
|
+
this.dispatch(Reproduction.EVENTS.READY);
|
|
50
|
+
});
|
|
51
|
+
this.player.on(PLAYER_EVENTS.FINISH, () => {
|
|
52
|
+
this.state = Reproduction.STATES.STOPPED;
|
|
53
|
+
clearInterval(this.interval);
|
|
54
|
+
this.dispatch(Reproduction.EVENTS.FINISH);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
on(eventName, handler) {
|
|
58
|
+
switch (eventName) {
|
|
59
|
+
case Reproduction.EVENTS.READY:
|
|
60
|
+
return this[dispatchOnReadyHandlers].push(handler);
|
|
61
|
+
case Reproduction.EVENTS.START:
|
|
62
|
+
return this[dispatchOnSongStartHandlers].push(handler);
|
|
63
|
+
case Reproduction.EVENTS.COUNTING_IN:
|
|
64
|
+
return this[dispatchOnCountingInHandlers].push(handler);
|
|
65
|
+
case Reproduction.EVENTS.PLAY:
|
|
66
|
+
return this[dispatchOnPlayHandlers].push(handler);
|
|
67
|
+
case Reproduction.EVENTS.PLAYING:
|
|
68
|
+
return this[dispatchOnPlayingHandlers].push(handler);
|
|
69
|
+
case Reproduction.EVENTS.PAUSED:
|
|
70
|
+
return this[dispatchOnPausedHandlers].push(handler);
|
|
71
|
+
case Reproduction.EVENTS.FINISH:
|
|
72
|
+
return this[dispatchOnFinishHandlers].push(handler);
|
|
73
|
+
default:
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
dispatch(eventName) {
|
|
78
|
+
let handler, i, len;
|
|
79
|
+
let ref = [];
|
|
80
|
+
switch (eventName) {
|
|
81
|
+
case Reproduction.EVENTS.READY:
|
|
82
|
+
ref = this[dispatchOnReadyHandlers];
|
|
83
|
+
break;
|
|
84
|
+
case Reproduction.EVENTS.START:
|
|
85
|
+
ref = this[dispatchOnSongStartHandlers];
|
|
86
|
+
break;
|
|
87
|
+
case Reproduction.EVENTS.COUNTING_IN:
|
|
88
|
+
ref = this[dispatchOnCountingInHandlers];
|
|
89
|
+
break;
|
|
90
|
+
case Reproduction.EVENTS.PLAY:
|
|
91
|
+
ref = this[dispatchOnPlayHandlers];
|
|
92
|
+
break;
|
|
93
|
+
case Reproduction.EVENTS.PLAYING:
|
|
94
|
+
ref = this[dispatchOnPlayingHandlers];
|
|
95
|
+
break;
|
|
96
|
+
case Reproduction.EVENTS.PAUSED:
|
|
97
|
+
ref = this[dispatchOnPausedHandlers];
|
|
98
|
+
break;
|
|
99
|
+
case Reproduction.EVENTS.FINISH:
|
|
100
|
+
ref = this[dispatchOnFinishHandlers];
|
|
101
|
+
break;
|
|
102
|
+
default:
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
|
106
|
+
handler = ref[i];
|
|
107
|
+
handler();
|
|
108
|
+
// setTimeout(handler, 0);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
countIn(timeout, limit) {
|
|
112
|
+
// the initial count starts instantly, no waiting
|
|
113
|
+
this.countingInCounter++;
|
|
114
|
+
this.dispatch(Reproduction.EVENTS.COUNTING_IN);
|
|
115
|
+
const interval = setInterval(() => {
|
|
116
|
+
this.countingInCounter++;
|
|
117
|
+
if (this.countingInCounter === limit) {
|
|
118
|
+
clearInterval(interval);
|
|
119
|
+
this.countingInCounter = 0;
|
|
120
|
+
if (limit !== 5) {
|
|
121
|
+
this.countIn(this.getBPMInterval(), 5);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
this.play();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
this.dispatch(Reproduction.EVENTS.COUNTING_IN);
|
|
129
|
+
}
|
|
130
|
+
}, timeout);
|
|
131
|
+
}
|
|
132
|
+
start() {
|
|
133
|
+
if (this.state === Reproduction.STATES.STOPPED) {
|
|
134
|
+
this.dispatch(Reproduction.EVENTS.START);
|
|
135
|
+
}
|
|
136
|
+
if (this.requiresCountingIn && this.getCurrentTime() === 0) {
|
|
137
|
+
this.state = Reproduction.STATES.COUNTING_IN;
|
|
138
|
+
this.countIn(this.getBPMInterval() * 2, 3);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
this.play();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
play() {
|
|
145
|
+
this.state = Reproduction.STATES.PLAYING;
|
|
146
|
+
this.dispatch(Reproduction.EVENTS.PLAY);
|
|
147
|
+
this.player.play();
|
|
148
|
+
const intervalTimeout = 200;
|
|
149
|
+
this.interval = setInterval(() => {
|
|
150
|
+
if (this.isPlaying()) {
|
|
151
|
+
this.dispatch(Reproduction.EVENTS.PLAYING);
|
|
152
|
+
}
|
|
153
|
+
}, intervalTimeout);
|
|
154
|
+
}
|
|
155
|
+
pause() {
|
|
156
|
+
this.state = Reproduction.STATES.PAUSED;
|
|
157
|
+
this.player.pause();
|
|
158
|
+
clearInterval(this.interval);
|
|
159
|
+
this.dispatch(Reproduction.EVENTS.PAUSED);
|
|
160
|
+
}
|
|
161
|
+
stop() {
|
|
162
|
+
this.state = Reproduction.STATES.STOPPED;
|
|
163
|
+
this.player.stop();
|
|
164
|
+
clearInterval(this.interval);
|
|
165
|
+
this.dispatch(Reproduction.EVENTS.FINISH);
|
|
166
|
+
}
|
|
167
|
+
isReady() {
|
|
168
|
+
// It's necessary to avoid play the reproduction-widget when the player is not ready
|
|
169
|
+
return this.ready;
|
|
170
|
+
}
|
|
171
|
+
isPlaying() {
|
|
172
|
+
return this.state === Reproduction.STATES.PLAYING;
|
|
173
|
+
}
|
|
174
|
+
isStopped() {
|
|
175
|
+
return this.state === Reproduction.STATES.STOPPED;
|
|
176
|
+
}
|
|
177
|
+
isPaused() {
|
|
178
|
+
return this.state === Reproduction.STATES.PAUSED;
|
|
179
|
+
}
|
|
180
|
+
isCountingIn() {
|
|
181
|
+
return this.state === Reproduction.STATES.COUNTING_IN;
|
|
182
|
+
}
|
|
183
|
+
getPlayer() {
|
|
184
|
+
return this.player;
|
|
185
|
+
}
|
|
186
|
+
getTempo() {
|
|
187
|
+
return this.songTempo;
|
|
188
|
+
}
|
|
189
|
+
getCurrentTime() {
|
|
190
|
+
// in seconds with milliseconds.
|
|
191
|
+
return this.player.getCurrentTime();
|
|
192
|
+
}
|
|
193
|
+
getDuration() {
|
|
194
|
+
return this.player.getDuration();
|
|
195
|
+
}
|
|
196
|
+
seekTo(seconds) {
|
|
197
|
+
this.player.seekTo(seconds);
|
|
198
|
+
}
|
|
199
|
+
getAvailablePlaybackRates() {
|
|
200
|
+
return this.player.getAvailablePlaybackRates();
|
|
201
|
+
}
|
|
202
|
+
setPlaybackRate(playbackRate) {
|
|
203
|
+
this.player.setPlaybackRate(playbackRate);
|
|
204
|
+
}
|
|
205
|
+
isAvailable() {
|
|
206
|
+
return this.player.isAvailable();
|
|
207
|
+
}
|
|
208
|
+
getBPMInterval() {
|
|
209
|
+
return 60000 / this.getTempo();
|
|
210
|
+
}
|
|
211
|
+
static newBuilder() {
|
|
212
|
+
return new ReproductionBuilder();
|
|
213
|
+
}
|
|
214
|
+
}
|