[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.

Add visualizer toggling

Kasper (Oct 2, 2025, 11:46 PM +0200) f9704318 e2d1df8c

+65 -2
+15 -2
src/App.svelte
··· 66 66 ipc_renderer.removeListener('Show Queue', toggle_queue) 67 67 }) 68 68 69 + function toggle_visualizer() { 70 + show_visualizer = !show_visualizer 71 + } 72 + ipc_renderer.on('Toggle Visualizer', toggle_visualizer) 73 + onDestroy(() => { 74 + ipc_renderer.removeListener('Toggle Visualizer', toggle_visualizer) 75 + }) 76 + 69 77 let droppable = false 70 78 const allowed_mimes = ['audio/mpeg', 'audio/x-m4a', 'audio/ogg'] // mp3, m4a 71 79 function get_file_paths(e: DragEvent): string[] { ··· 136 144 } 137 145 }), 138 146 ) 147 + 148 + let show_visualizer = false 139 149 140 150 let playlist_info: PlaylistInfo | null = null 141 151 onDestroy( ··· 275 285 <Queue /> 276 286 {/if} 277 287 </div> 278 - <Player /> 288 + <Player on_show_visualizer={toggle_visualizer} /> 279 289 {#if droppable} 280 290 <!-- if the overlay is always visible, it's not possible to scroll while dragging tracks --> 281 291 <div class="drag-overlay" transition:fade={{ duration: 100 }}> ··· 293 303 ></div> 294 304 {/if} 295 305 </main> 296 - <Visualizer /> 306 + 307 + {#if show_visualizer} 308 + <Visualizer on_close={toggle_visualizer} /> 309 + {/if} 297 310 298 311 <QuickNav /> 299 312 {#if track_info_state.instance}
+29
src/components/Player.svelte
··· 21 21 import { ipc_renderer } from '$lib/window' 22 22 import { tracks_page_item_ids } from './TrackList.svelte' 23 23 24 + export let on_show_visualizer: () => void 25 + 24 26 async function playing_context_menu() { 25 27 const playing = queue.getCurrent() 26 28 if (playing) { ··· 229 231 </div> 230 232 </div> 231 233 <div class="right"> 234 + <button 235 + type="button" 236 + class="mr-2" 237 + aria-label="Show visualizer" 238 + tabindex="-1" 239 + on:click={() => { 240 + on_show_visualizer() 241 + }} 242 + > 243 + <div class="parent-active-zoom"> 244 + <svg 245 + xmlns="http://www.w3.org/2000/svg" 246 + width="24" 247 + height="24" 248 + viewBox="-2 -2 26 26" 249 + fill="none" 250 + stroke="currentColor" 251 + stroke-width="2" 252 + stroke-linecap="round" 253 + stroke-linejoin="round" 254 + class="lucide lucide-audio-lines-icon lucide-audio-lines" 255 + ><path d="M2 10v3" /><path d="M6 6v11" /><path d="M10 3v18" /><path d="M14 8v7" /><path 256 + d="M18 5v13" 257 + /><path d="M22 10v3" /></svg 258 + > 259 + </div> 260 + </button> 232 261 <button type="button" class="volume-icon" tabindex="-1" on:click={volume.toggle}> 233 262 {#if $volume > 0.5} 234 263 <svg
+8
src/electron/menubar.ts
··· 178 178 }, 179 179 }, 180 180 { 181 + label: 'Toggle Visualizer', 182 + type: 'checkbox', 183 + accelerator: 'CmdOrCtrl+T', 184 + click() { 185 + web_contents.send('Toggle Visualizer') 186 + }, 187 + }, 188 + { 181 189 label: 'Toggle Quick Nav', 182 190 type: 'checkbox', 183 191 accelerator: 'CmdOrCtrl+K',
+1
src/electron/typed_ipc.ts
··· 117 117 volumeUp: () => void 118 118 volumeDown: () => void 119 119 'Show Queue': () => void 120 + 'Toggle Visualizer': () => void 120 121 ToggleQuickNav: () => void 121 122 'Group Album Tracks': (checked: boolean) => void 122 123
+12
src/lib/visualizer/Visualizer.svelte
··· 3 3 import { ShaderToyLite } from './ShaderToyLite.js' 4 4 import { onMount } from 'svelte' 5 5 import { audioContext, mediaElementSource } from '$lib/player' 6 + import { check_shortcut } from '$lib/helpers' 7 + 8 + export let on_close: () => void 6 9 7 10 const canvas_id = 'visualizer' 8 11 ··· 65 68 }) 66 69 </script> 67 70 71 + <svelte:window 72 + on:keydown={(e) => { 73 + if (check_shortcut(e, 'Escape')) { 74 + on_close() 75 + } 76 + }} 77 + /> 78 + 79 + <!-- svelte-ignore a11y_no_static_element_interactions --> 68 80 <div class="fixed top-0 left-0 flex h-screen w-screen items-center justify-center"> 69 81 <canvas id={canvas_id} width="840" height="472"></canvas> 70 82 </div>