[READ-ONLY] Mirror of https://github.com/probablykasper/ferrum. Music library app for Mac, Linux and Windows ferrum.kasper.space
electron linux macos music music-library music-player napi windows
0

Configure Feed

Select the types of activity you want to include in your feed.

Speed up auto transitions when doing manual transition

+83 -27
+83 -27
src/lib/visualizer/Visualizer.svelte
··· 127 127 let next_vis = visualisers[1] 128 128 129 129 let current_shader_index = 0 130 - let next_shader_index: number | null = null 130 + let transition: { 131 + next_shader_index: number 132 + pending_shader_index: number | null 133 + auto: boolean 134 + duration: number 135 + start_time: number 136 + animation_old: Animation 137 + animation_new: Animation 138 + cancelled?: boolean 139 + } | null = null 131 140 let auto_transition_timeout: ReturnType<typeof setTimeout> | undefined 132 141 133 142 const visualizer = start_visualizer(audio_context, media_element_source, (info) => { ··· 138 147 next_vis.toy?.set_volume(info.volume) 139 148 }) 140 149 141 - let pending_transition: number | null = null 150 + async function transition_to_shader(new_shader_index: number, auto: boolean) { 151 + if (!main_vis.canvas || !next_vis.canvas) { 152 + return console.error('Missing canvas') 153 + } 154 + 155 + if (transition) { 156 + const auto_to_manual = !auto && transition.auto 157 + const passed_half = Date.now() - transition.start_time > transition.duration * 0.5 158 + 159 + if (auto_to_manual) { 160 + // User wants to transition manually, but we're in a slow auto transition, so speed it up 161 + transition.auto = false 162 + transition.animation_new.updatePlaybackRate(4) 163 + transition.animation_old.updatePlaybackRate(4) 164 + } 165 + 166 + if (new_shader_index === transition.next_shader_index) { 167 + if (auto_to_manual && !passed_half) { 168 + // Auto transition already started here, but it's not halfway done, so we just speed it up 169 + transition.pending_shader_index = null 170 + return 171 + } 172 + } 173 + 174 + if (new_shader_index === current_shader_index) { 175 + if (!transition.cancelled) { 176 + transition.animation_new.reverse() 177 + transition.animation_old.reverse() 178 + } 179 + transition.cancelled = true 180 + } 142 181 143 - async function transition_to_shader(new_shader_index: number, duration = 2000) { 144 - if (next_shader_index !== null) { 145 - pending_transition = new_shader_index 182 + // Schedule the shader for later 183 + transition.pending_shader_index = new_shader_index 184 + // ...unless we're already transitioning to it 185 + if (transition.pending_shader_index === transition.next_shader_index) { 186 + transition.pending_shader_index = null 187 + } 146 188 return 147 189 } 148 - if (current_shader_index === new_shader_index) return 149 190 150 - if (!main_vis.canvas || !next_vis.canvas) { 151 - return console.error('Missing canvas') 191 + if (new_shader_index === current_shader_index) { 192 + return 152 193 } 153 194 154 - next_shader_index = new_shader_index 155 195 clearTimeout(auto_transition_timeout) 156 196 157 197 // Start transition visualizer ··· 173 213 next_vis.toy.set_buffer_a({ source: shaders[new_shader_index].shader }) 174 214 next_vis.toy.play() 175 215 216 + const duration = auto ? 2000 : 300 217 + 176 218 const animation_new = next_vis.canvas.animate( 177 219 { opacity: [0, 1] }, 178 220 { ··· 190 232 fill: 'forwards', 191 233 }, 192 234 ) 235 + transition = { 236 + next_shader_index: new_shader_index, 237 + pending_shader_index: null, 238 + auto, 239 + duration, 240 + start_time: Date.now(), 241 + animation_new, 242 + animation_old, 243 + } 193 244 await animation_new.finished 194 245 await animation_old.finished 195 246 196 - await new Promise((resolve) => setTimeout(resolve, duration)) 247 + if (transition.cancelled) { 248 + transition = null 249 + next_vis.toy?.pause() // Keep the instance for later use 250 + schedule_auto_transition() 251 + return 252 + } 197 253 198 - next_vis.is_main = true 199 - main_vis.is_main = false 200 254 // Swap 201 255 ;[main_vis, next_vis] = [next_vis, main_vis] 256 + main_vis.is_main = true 257 + next_vis.is_main = false 202 258 203 259 next_vis.toy?.pause() // Keep the instance for later use 204 260 205 - current_shader_index = new_shader_index 206 - next_shader_index = null 261 + current_shader_index = transition?.next_shader_index 207 262 208 - schedule_auto_transition() 209 - 210 - if (pending_transition !== null) { 211 - const next_index = pending_transition 212 - pending_transition = null 213 - transition_to_shader(next_index) 263 + if (transition.pending_shader_index !== null) { 264 + const new_index = transition.pending_shader_index 265 + transition = null 266 + transition_to_shader(new_index, false) 267 + } else { 268 + transition = null 269 + schedule_auto_transition() 214 270 } 215 271 } 216 272 217 273 function schedule_auto_transition() { 218 274 clearTimeout(auto_transition_timeout) 219 275 auto_transition_timeout = setTimeout(() => { 220 - if (next_shader_index === null) { 276 + if (!transition) { 221 277 const next_index = (current_shader_index + 1) % shaders.length 222 - transition_to_shader(next_index) 278 + transition_to_shader(next_index, true) 223 279 } 224 280 }, 10000) 225 281 } ··· 237 293 } 238 294 239 295 function schedule_resize(vis: Vis) { 240 - if (next_shader_index === null && !vis.is_main) { 296 + if (!transition && !vis.is_main) { 241 297 vis.should_resize = true 242 298 return 243 299 } ··· 274 330 }} 275 331 onkeydown={(e) => { 276 332 if (check_modifiers(e, {})) { 277 - let shader_index = next_shader_index ?? current_shader_index 333 + let shader_index = transition?.next_shader_index ?? current_shader_index 278 334 if (e.key === 'ArrowLeft') { 279 - transition_to_shader((shader_index - 1 + shaders.length) % shaders.length, 500) 335 + transition_to_shader((shader_index - 1 + shaders.length) % shaders.length, false) 280 336 } else if (e.key === 'ArrowRight') { 281 - transition_to_shader((shader_index + 1) % shaders.length, 500) 337 + transition_to_shader((shader_index + 1) % shaders.length, false) 282 338 } else if (/^[1-9]$/.test(e.key)) { 283 - transition_to_shader(Math.min(parseInt(e.key) - 1, shaders.length - 1), 500) 339 + transition_to_shader(Math.min(parseInt(e.key) - 1, shaders.length - 1), false) 284 340 } else { 285 341 show_player_temporarily() 286 342 }