1
1
// beatmap downloader
2
2
3
- function startpreview ( box ) {
4
- let volume = 1 ;
5
- if ( window . gamesettings ) {
6
- volume = ( window . gamesettings . mastervolume / 100 ) * ( window . gamesettings . musicvolume / 100 ) ;
7
- volume = Math . min ( 1 , Math . max ( 0 , volume ) ) ;
8
- }
9
- let audios = document . getElementsByTagName ( "audio" ) ;
10
- for ( let i = 0 ; i < audios . length ; ++ i )
11
- audios [ i ] . softstop ( ) ;
12
- let a = document . createElement ( "audio" ) ;
13
- let s = document . createElement ( "source" ) ;
14
- s . src = "https://cdn.sayobot.cn:25225/preview/" + box . sid + ".mp3" ;
15
- s . type = "audio/mpeg" ;
16
- a . appendChild ( s ) ;
17
- a . volume = 0 ;
18
- a . play ( ) ;
19
- document . body . appendChild ( a ) ;
20
- let fadeIn = setInterval ( function ( ) {
21
- if ( a . volume < volume )
22
- a . volume = Math . min ( volume , a . volume + 0.05 * volume ) ;
23
- else
24
- clearInterval ( fadeIn ) ;
25
- } , 30 ) ;
26
- let fadeOut = setInterval ( function ( ) {
27
- if ( a . currentTime > 9.3 ) // assume it's 10s long
28
- a . volume = Math . max ( 0 , a . volume - 0.05 * volume ) ;
29
- if ( a . volume == 0 )
30
- clearInterval ( fadeOut ) ;
31
- } , 30 ) ;
32
- a . softstop = function ( ) {
33
- let fadeOut = setInterval ( function ( ) {
34
- a . volume = Math . max ( 0 , a . volume - 0.05 * volume ) ;
35
- if ( a . volume == 0 ) {
36
- clearInterval ( fadeOut ) ;
37
- a . remove ( ) ;
3
+ ( ( ) => {
4
+
5
+ /**
6
+ * Preview Audio
7
+ */
8
+ class PreviewAudio {
9
+ /**
10
+ * Build a PreviewAudio object
11
+ * @param {string | number } sid Beatmap's sid
12
+ * @param {number } volume Volume of preview audio
13
+ */
14
+ constructor ( sid , volume = 1 ) {
15
+ const audioContext = new Audio ( "https://cdn.sayobot.cn:25225/preview/" + sid + ".mp3" ) ;
16
+ this . _sid = sid ;
17
+ this . _volume = volume ;
18
+ this . _audioContext = audioContext ;
19
+ this . _playing = false ;
20
+ this . _ready = false ;
21
+ this . _fadeTimer = 0 ;
22
+ this . _playTimer = 0 ;
23
+ audioContext . load ( ) ;
24
+ audioContext . volume = 0 ;
25
+ audioContext . addEventListener ( 'canplay' , ( ) => {
26
+ this . _ready = true
27
+ if ( this . _playing === true ) {
28
+ this . play ( ) ;
29
+ }
30
+ } , { once : true } )
31
+ }
32
+ play ( ) {
33
+ this . _playing = true ;
34
+ if ( this . _ready ) {
35
+ this . _playing = true
36
+ this . _audioContext . volume = 0 ;
37
+ this . _audioContext . currentTime = 0 ;
38
+ this . _audioContext . play ( ) ;
39
+ clearInterval ( this . _fadeTimer ) ;
40
+ clearTimeout ( this . _playTimer ) ;
41
+ this . _fadeTimer = setInterval ( ( ) => {
42
+ if ( this . _audioContext . volume < this . _volume )
43
+ this . _audioContext . volume = Math . min ( this . _volume , this . _audioContext . volume + 0.05 * this . _volume ) ;
44
+ else
45
+ clearInterval ( this . _fadeTimer ) ;
46
+ clearTimeout ( this . _playTimer ) ;
47
+ } , 30 ) ;
48
+ this . _playTimer = setTimeout ( ( ) => {
49
+ this . _audioContext . volume = this . _volume ;
50
+ clearInterval ( this . _fadeTimer ) ;
51
+ clearTimeout ( this . _playTimer ) ;
52
+ } , 600 ) ;
38
53
}
39
- } , 10 ) ;
54
+ }
55
+ stop ( ) {
56
+ this . _playing = false
57
+ clearInterval ( this . _fadeTimer ) ;
58
+ clearTimeout ( this . _playTimer ) ;
59
+ this . _fadeTimer = setInterval ( ( ) => {
60
+ this . _audioContext . volume = Math . max ( 0 , this . _audioContext . volume - 0.05 * this . _volume ) ;
61
+ if ( this . _audioContext . volume === 0 ) {
62
+ this . _audioContext . pause ( ) ;
63
+ clearInterval ( this . _fadeTimer ) ;
64
+ clearTimeout ( this . _playTimer ) ;
65
+ }
66
+ } , 10 ) ;
67
+ this . _playTimer = setTimeout ( ( ) => {
68
+ this . _audioContext . pause ( ) ;
69
+ clearInterval ( this . _fadeTimer ) ;
70
+ clearTimeout ( this . _playTimer ) ;
71
+ } , 200 ) ;
72
+ }
73
+ set volume ( value ) {
74
+ this . _volume = value ;
75
+ }
76
+ get volume ( ) {
77
+ return this . _volume ;
78
+ }
40
79
}
41
- }
42
80
43
- function startdownload ( box ) {
44
- startpreview ( box ) ;
45
- if ( box . downloading ) {
46
- return ;
47
- }
48
- let url = "https://dl.sayobot.cn/beatmaps/download/novideo/" + box . sid ;
49
- box . downloading = true ;
50
- box . classList . add ( "downloading" ) ;
51
- let xhr = new XMLHttpRequest ( ) ;
52
- xhr . responseType = 'arraybuffer' ;
53
- xhr . open ( "GET" , url ) ;
54
- // create download progress bar
55
- let container = document . createElement ( "div" ) ;
56
- let title = document . createElement ( "div" ) ;
57
- let bar = document . createElement ( "progress" ) ;
58
- container . className = "download-progress" ;
59
- title . className = "title" ;
60
- title . innerText = box . setdata . title ;
61
- container . appendChild ( title ) ;
62
- container . appendChild ( bar ) ;
63
- // insert so that download list from recent to old
64
- let statuslines = document . getElementById ( "statuslines" ) ;
65
- statuslines . insertBefore ( container , statuslines . children [ 3 ] ) ;
66
- bar . max = 1 ;
67
- bar . value = 0 ;
68
- // async part
69
- xhr . onload = function ( ) {
70
- box . oszblob = new Blob ( [ xhr . response ] ) ;
71
- bar . className = "finished" ;
72
- box . classList . remove ( "downloading" ) ;
81
+ class PreviewAudioManager {
82
+ /**
83
+ * Create a preview audio manager
84
+ * @param {object } [settings] Preview audio manager settings
85
+ * @param {number } [settings.volume] Audio's volume
86
+ */
87
+ constructor ( settings = { } ) {
88
+ const { volume} = settings
89
+ /**
90
+ * @type {PreviewAudio }
91
+ */
92
+ this . _active = null ;
93
+ this . _volume = volume ;
94
+ }
95
+ /**
96
+ * Play preview audio
97
+ * @param {string | number } sid Beatmap's sid
98
+ */
99
+ play ( sid ) {
100
+ if ( this . _active ) {
101
+ this . _active . stop ( ) ;
102
+ }
103
+ this . _active = new PreviewAudio ( sid , this . _volume ) ;
104
+ this . _active . play ( )
105
+ }
106
+ stop ( ) {
107
+ if ( this . _active ) {
108
+ this . _active . stop ( ) ;
109
+ }
110
+ }
111
+ set volume ( value ) {
112
+ if ( value > 1 ) {
113
+ value = 1 ;
114
+ }
115
+ this . _volume = value ;
116
+ if ( this . _active ) {
117
+ this . _active . volume = value ;
118
+ }
119
+ }
120
+ get volume ( ) {
121
+ return this . _volume ;
122
+ }
73
123
}
74
- xhr . onprogress = function ( e ) {
75
- bar . value = e . loaded / e . total ;
124
+
125
+ const previewAudioMgr = new PreviewAudioManager ( )
126
+
127
+ function startpreview ( box ) {
128
+ let volume = 1 ;
129
+ if ( window . gamesettings ) {
130
+ volume = ( window . gamesettings . mastervolume / 100 ) * ( window . gamesettings . musicvolume / 100 ) ;
131
+ volume = Math . min ( 1 , Math . max ( 0 , volume ) ) ;
132
+ }
133
+ previewAudioMgr . volume = volume
134
+ previewAudioMgr . play ( box . sid )
76
135
}
77
- xhr . onerror = function ( ) {
78
- console . error ( "download failed" ) ;
79
- alert ( "Beatmap download failed. Please retry later." )
80
- box . downloading = false ;
81
- box . classList . remove ( "downloading" ) ;
136
+
137
+ function startdownload ( box ) {
138
+ startpreview ( box ) ;
139
+ if ( box . downloading ) {
140
+ return ;
141
+ }
142
+ let url = "https://txy1.sayobot.cn/beatmaps/download/mini/" + box . sid ;
143
+ box . downloading = true ;
144
+ box . classList . add ( "downloading" ) ;
145
+ let xhr = new XMLHttpRequest ( ) ;
146
+ xhr . responseType = 'arraybuffer' ;
147
+ xhr . open ( "GET" , url ) ;
148
+ // create download progress bar
149
+ let container = document . createElement ( "div" ) ;
150
+ let title = document . createElement ( "div" ) ;
151
+ let bar = document . createElement ( "progress" ) ;
152
+ container . className = "download-progress" ;
153
+ title . className = "title" ;
154
+ title . innerText = box . setdata . title ;
155
+ container . appendChild ( title ) ;
156
+ container . appendChild ( bar ) ;
157
+ // insert so that download list from recent to old
158
+ let statuslines = document . getElementById ( "statuslines" ) ;
159
+ statuslines . insertBefore ( container , statuslines . children [ 3 ] ) ;
160
+ bar . max = 1 ;
161
+ bar . value = 0 ;
162
+ // async part
163
+ xhr . onload = function ( ) {
164
+ box . oszblob = new Blob ( [ xhr . response ] ) ;
165
+ bar . className = "finished" ;
166
+ box . classList . remove ( "downloading" ) ;
167
+ }
168
+ xhr . onprogress = function ( e ) {
169
+ bar . value = e . loaded / e . total ;
170
+ }
171
+ xhr . onerror = function ( ) {
172
+ console . error ( "download failed" ) ;
173
+ alert ( "Beatmap download failed. Please retry later." )
174
+ box . downloading = false ;
175
+ box . classList . remove ( "downloading" ) ;
176
+ }
177
+ xhr . send ( ) ;
82
178
}
83
- xhr . send ( ) ;
84
- }
179
+
180
+ window . startdownload = startdownload
181
+ window . previewAudioMgr = previewAudioMgr
182
+ } ) ( )
0 commit comments