Commit Graph
1638 Commits
Author SHA1 Message Date
vicrodh b8cfcfb34a Add audio visualizer backend infrastructure
- Add spectrum-analyzer crate for FFT processing
- Create visualizer module with:
  - RingBuffer: lockless SPSC buffer for audio samples
  - FFT processor: dedicated thread for spectrum analysis
  - TappedSource: rodio Source wrapper for sample capture
  - VisualizerTap: shared state for audio thread integration
- Add Tauri commands: set_visualizer_enabled, is_visualizer_enabled
- Register visualizer in AppState and lib.rs

Backend compiles. Next: integrate with audio thread to capture samples.
2026-02-01 15:07:21 -06:00
vicrodh 5a93ac509d Fix volume spam: deduplicate set_volume calls in backend
- Skip setting volume if already at same value (0.001 tolerance)
- Skip logging when volume unchanged
- Prevents MPRIS/PipeWire feedback loop spam
2026-02-01 14:33:56 -06:00
vicrodh 43444951ba Hypersensitive sleeve parallax: ±120px H, ±35px V with power curve
- Doubled horizontal range to ±120px
- Doubled vertical range to ±35px
- Added power curve (0.7) for hypersensitivity near center
- Small mouse movements now produce dramatic response
2026-02-01 14:27:57 -06:00
vicrodh 33dc0ccafb Increase sleeve parallax range: 120px horizontal, 35px vertical 2026-02-01 14:26:16 -06:00
vicrodh 1a4fa3cc78 Remove all parallax from vinyl - only sleeve moves
- Vinyl stays perfectly centered, only rotates
- Removed X and Y parallax from vinyl position
- Removed parallax uniform from shader
- Only the cover art (sleeve) responds to mouse movement
2026-02-01 14:24:36 -06:00
vicrodh 2fe0efc3d4 Fix vinyl rotation: 33⅓ RPM, concentric, no Y-axis movement
- Set rotation speed to 33.333 RPM (0.0582 rad/frame at 60fps)
- Remove Y-axis parallax from vinyl position (stays centered)
- Remove Y parallax from shader for perfectly concentric rotation
- Add mipmaps and trilinear filtering for anti-aliasing
- Enable anisotropic filtering when available
2026-02-01 14:22:56 -06:00
vicrodh 81232457d1 Fix parallax values to prevent artifacts 2026-02-01 14:15:37 -06:00
vicrodh 68b863ea64 Extreme horizontal parallax and use PNG texture
- Use PNG instead of SVG for better WebGL compatibility
- Extreme horizontal parallax: cover 200px, vinyl 120px
- Reduced vertical parallax for subtle depth
- Shader parallax: 0.15 horizontal, 0.05 vertical
- Disc appears to slide out of sleeve with minimal mouse movement
2026-02-01 14:14:02 -06:00
vicrodh fc85d66f5c Fix VinylPanel: add padding and aggressive parallax
- Add padding around vinyl (scale UV by 1.15x)
- Discard pixels outside bounds to avoid edge artifacts
- Much more aggressive parallax: cover 80/50px, vinyl 50/35px
- Shader parallax offset increased to 0.08
- Vinyl size reduced to 85% for more breathing room
2026-02-01 14:10:55 -06:00
vicrodh 6265e685ea Update logo and regenerate all app icons
- Updated qbz-logo.svg and qbz-logo.png
- Added qbz-vinyl-v3.svg for VinylPanel
- Regenerated all Tauri icons from new logo
- Updated Android icons and favicon
2026-02-01 14:09:57 -06:00
vicrodh b068426e9f Rewrite VinylPanel with WebGL2 for performance
- Use WebGL2 canvas for vinyl rendering instead of CSS
- Load qbz-vinyl-v3.svg as texture
- Shader-based rotation when playing
- Parallax effect via uniforms (no DOM updates)
- Album cover slides left to reveal vinyl
- Much lower CPU usage than CSS animation
2026-02-01 14:08:57 -06:00
vicrodh 20b9aa2c86 Improve VinylPanel parallax sensitivity and alignment
- Double parallax sensitivity (30/20px cover, 18/12px disc)
- Cover and disc now vertically centered together
- Cover slides 15% left when playing to reveal disc
- Simplified transform calculations
2026-02-01 13:55:05 -06:00
vicrodh fcb81dad2b Fix VinylPanel layout and styling to match Figma design
- Correct z-ordering: cover in front (z-10), disc behind
- Cover slides left when playing to reveal disc
- Add mouse parallax effect for depth
- More visible grooves with alternating brightness
- Neutral gray colors instead of amber vintage
- Use system typography instead of Oswald
- Radial gradient on disc for realistic shading
2026-02-01 13:52:26 -06:00
vicrodh d79fdf58b6 Add Vinyl panel to Focus mode and fix MPRIS volume feedback loop
- Add VinylPanel.svelte with spinning vinyl disc animation
- Album cover slides left when playing to reveal disc
- CSS-based grooves (40 rings) and amber center label
- Vintage typography with "33 1/3 RPM" badge
- Add 'vinyl' as new Focus tab option in ImmersiveHeader
- Fix MPRIS/PipeWire volume feedback loop by checking if volume
  actually changed before calling setVolume
2026-02-01 13:51:19 -06:00
vicrodh 319150920b Enhance immersive ambient animation vibrancy and speed
- Increase animation speed to 1.8x for more dynamic movement
- Add per-channel histogram normalization to expand color range
- Boost saturation to 2.5x and brightness to 0.85
- Add 12% red channel boost for warmer tones
- Target color range 30-240 to lift shadows and preserve highlights
2026-02-01 13:42:41 -06:00
vicrodh d4cfd14fc6 fix(immersive): prevent black from dominating in B&W artwork
Problem: brightness(0.5) made whites gray while blacks stayed black,
causing dark areas to dominate even in mostly-white artwork.

Solution:
- Increased brightness from 0.5 to 0.7
- Added shadow lift: maps 0-255 to 25-255
- Black now becomes dark gray (~10% brightness floor)
- Whites remain visible and balanced

Result: 'Panda/cow' effect - both light and dark areas visible.
2026-02-01 13:32:52 -06:00
vicrodh edca4d0bec feat(immersive): dramatically increase ambient animation
New effects added:
- Layer rotation: each layer rotates slowly (1-2° range)
- Scale breathing: zoom levels pulse in/out per layer
- Pulsing vignette: edge darkening varies over time
- Increased drift amplitudes: far ±0.20, mid ±0.14, near ±0.08
- Stronger brightness breathing: ±12% (was ±8%)

All effects are decorrelated (different speeds/phases) for organic feel.
Default intensity now 1.0 for maximum visibility.
2026-02-01 13:28:48 -06:00
vicrodh cec7a799d5 feat(immersive): increase ambient animation visibility
Shader changes:
- Removed 0.5x time multiplier (was making motion too slow)
- Increased drift amplitudes ~3x (far: 0.15, mid: 0.10, near: 0.06)
- Faster drift speeds (~12-17 sec cycles instead of ~40-80 sec)
- Breathing effect doubled (0.08 vs 0.04)

Config changes:
- Default ambientIntensity: 0.8 (was 0.5)

Purpose: Keep pixels active (OLED), make motion perceptible
while maintaining ambient character (no sudden movements).
2026-02-01 13:25:47 -06:00
vicrodh 8bb38ccdda perf(lyrics): remove karaoke animation, plain white text only
Even GPU-accelerated animation was too expensive.
Immersive mode now uses simple bright white text with no animation.
2026-02-01 13:15:39 -06:00
vicrodh dbd706fc64 perf(lyrics): GPU-accelerated underline animation
Replace expensive properties with GPU-accelerated ones:
- transform: scaleX() instead of width (no layout recalc)
- Solid color instead of gradient
- Removed box-shadow blur (very expensive)
- Added will-change: transform hint

This runs entirely on GPU compositor thread.
2026-02-01 13:14:43 -06:00
vicrodh 06469aeaa3 fix(lyrics): use QBZ blue underline for karaoke effect
Revert to glowing underline approach with QBZ brand blue (#5281ff):
- Text stays bright white (no background-clip: text)
- Underline sweeps from left to right during line duration
- Blue glow effect with box-shadow
- Much better readability than gradient text
2026-02-01 13:13:36 -06:00
vicrodh fc382a2237 feat(lyrics): metallic shimmer effect for karaoke
Replace underline with metallic shimmer that sweeps across text:
- Mostly white (40% each side) with purple highlight band in center
- Gradient moves from right to left during line duration
- Uses ease-in-out for natural feel
- GPU-accelerated, single element, no JS polling
2026-02-01 13:11:01 -06:00
vicrodh c1a7a5977a fix(lyrics): use glowing underline instead of gradient text for karaoke
The background-clip: text technique made white appear gray.
New approach uses a pseudo-element underline that:
- Sweeps from left to right with the line duration
- Has purple glow effect (#a78bfa)
- Keeps text bright white and readable
- No impact on text color/brightness
2026-02-01 13:09:54 -06:00
vicrodh db2419fcb0 feat(lyrics): CSS-only karaoke animation for immersive mode
Replace JS-polled karaoke with pure CSS animation:
- Calculate line duration from timing data (timeMs)
- Use CSS animation with background-position sweep
- Animation runs once per line change, no polling needed
- Uses purple (#c4b5fd) to white gradient for visibility

Data flow: Pass full LyricsLine objects (with timeMs) through
component chain instead of stripping timing data.
2026-02-01 13:08:43 -06:00
vicrodh 562f73f350 perf(lyrics): reduce CPU usage in immersive mode by ~90%
Problem: Lyrics split view consumed more CPU than coverflow due to:
- Polling every 80-200ms for karaoke progress updates
- Inline styles on ALL ~50+ lines recalculated on every render
- Transitions tracked on all lines (4 properties each)

Solution:
1. lyricsStore: Add setProgressTrackingEnabled() to skip progress
   updates in immersive mode (only track line index changes)
2. LyricsLines: Use CSS classes for opacity instead of inline styles
   in immersive mode (distance-1, distance-2, distance-3, distance-far)
3. LyricsLines: Add CSS containment (contain: layout style) to isolate
   paint/layout recalculations
4. LyricsLines: Reduce transitions on non-active lines (2 vs 4 props)
5. ImmersivePlayer: Disable progress tracking on mount, re-enable on exit

Result: Immersive lyrics now updates only on line changes (~10-20/min)
instead of continuous progress updates (~300-750/min)
2026-02-01 13:04:13 -06:00
vicrodh f43ecb495f Add book-style collage and custom tooltip styles to SuggestionsPanel
- Book collage: 3 album covers with left/center/right positioning
- Rotated side covers (-12deg/+12deg) with hover animation
- Custom tooltip: opens bottom-right with high z-index (1000)
- Info trigger: 24px with dark background for visibility
- Fade-in animation for tooltip appearance
2026-02-01 12:55:52 -06:00
vicrodh c968beefa0 feat(immersive): merge History into Queue tab + add background transition
Queue/History:
- Removed History as separate tab from header
- Added History as sub-tab within QueuePanel
- Sub-tabs: Queue | History with counts
- Removed history-focus from focus mode tabs
- Removed keyboard shortcut 'H' and '5' for history

Background transition:
- Added 400ms crossfade when artwork changes
- Works for both WebGL and CSS fallback renderers
- Fades out, loads new texture, fades back in
2026-02-01 12:51:31 -06:00
vicrodh 780557efff fix(suggestions): remove book collage, fix badges and tooltip
- Removed book collage (playlist.images are same image at different sizes)
- Using medium quality image (images[1]) for playlist cards
- Fixed z-index on Qobuz/QBZ badges (z-index: 10, above overlay)
- Increased badge icons by 2pt (Qobuz: 22px, QBZ: 19px)
- Replaced native title tooltip with Tooltip component for radio info
2026-02-01 12:42:03 -06:00
vicrodh b20a2edf74 feat(suggestions): book-style collage for playlist cards
- Shows 3 covers like album spines when available
- Center cover fully visible, left/right at -15% offset
- Falls back to medium-quality single image if < 3 images
- Uses images[1] (medium) instead of images[0] (largest)
2026-02-01 12:33:04 -06:00
vicrodh 79672c4afb fix(suggestions): use highest quality playlist artwork
Changed from last (smallest) to first (largest) image in array
2026-02-01 12:30:35 -06:00
vicrodh 5c6ecc6a93 feat(immersive): implement Heavy Immersion shader
Three mandatory mechanisms for depth illusion:

1. Multi-scale texture sampling:
   - Far layer (0.7x zoom) - feels distant
   - Mid layer (0.9x zoom) - transition
   - Near layer (1.3x zoom) - feels close

2. Scale-dependent UV drift:
   - Far: slowest drift (0.03, 0.025)
   - Mid: medium drift (0.05, 0.04)
   - Near: fastest drift (0.07, 0.06)
   - Creates parallax-like depth perception

3. Spatial weighting:
   - Near layer dominant at screen center
   - Far layer dominant at screen edges
   - Mid layer fills the ring between
   - Vignette for additional depth

Result: Background feels spatially enveloping,
not like a zoomed/cropped image.
2026-02-01 12:21:03 -06:00
vicrodh dd0bd1e170 checkpoint: solid immersive baseline before heavy immersion upgrade
Working state:
- Atmospheric background (no recognizable artwork)
- Multi-sample blur in shader
- Gradient tint (cool top, warm bottom)
- Oswald font for lyrics (28px/30px)
- Lyrics panel 700px wide
- Text shadow for contrast
- Karaoke effect disabled in immersive

Ready for Heavy Immersion shader upgrade.
2026-02-01 12:19:52 -06:00
vicrodh 0f6c24f4f9 fix(lyrics): disable karaoke gradient in immersive, increase font +2pt
- Font size: 28px inactive, 30px active
- Disabled background-clip karaoke effect in immersive mode
- Active line now pure white (#ffffff)
- Past lines dimmed to 35% opacity
2026-02-01 12:06:18 -06:00
vicrodh 9d3f05025a fix(immersive): preserve blue colors and improve lyrics readability
Shader:
- Fixed luminance formula that was killing blue (30% blend instead of 100%)

Lyrics:
- Added Oswald font for immersive lyrics
- Increased font size by 2pt (26px inactive, 28px active)
- Active lines now pure white with higher weight for clarity
2026-02-01 11:58:47 -06:00
vicrodh 01adbb7ab4 feat(immersive): enhance shader and widen lyrics panel
Shader improvements:
- Multi-sample blur (4 corners averaged)
- Luminance preservation over saturation
- Gradient tint (cool top, warm bottom) for anti-flat look

Layout:
- Lyrics panel width increased from 560px to 700px (+140px)
- Responsive breakpoint adjusted (480px → 620px)
2026-02-01 11:50:16 -06:00
vicrodh 7535fdb8cc fix(lyrics): add text shadow for contrast against any background
Immersive lyrics now have dark shadow behind text for readability
on light/warm backgrounds like Powerslave's golden tones.
2026-02-01 11:43:41 -06:00
vicrodh 240ca09c6a fix(immersive): sample 90-100% of image for complete color representation
Rely on extreme blur to destroy details, not cropping.
This ensures all dominant colors (like blue sky) are captured.
2026-02-01 11:39:32 -06:00
vicrodh 8917049b00 fix(immersive): increase crop sample size for more relevant colors
Zoom factor changed from 1.5-3x to 1.1-1.6x
Now samples 62-90% of image instead of 33-66%
2026-02-01 11:34:36 -06:00
vicrodh 0bdd83dc08 fix(immersive): destroy artwork structure, preserve only mood
Implement proper atmospheric background pipeline:
- Random NON-CENTERED crop (150-300% zoom) to break composition
- Extreme blur at small size (destroys all semantic detail)
- Scale up with smoothing for additional blur
- Color adjustments (saturation 1.4x, brightness 0.5x)
- Vignette overlay

The background is now an unrecognizable color field derived from
artwork colors. Acceptance test: "Can I identify the album from
the background alone?" must be NO.

Applies to both WebGL and CSS fallback renderers.
2026-02-01 11:32:29 -06:00
vicrodh e4a108dc16 refactor(immersive): separate blur and motion concerns
- texture-loader.ts: Multi-pass blur (4×15px) at 256x256 for CSS-equivalent quality
- ambient.frag: Simplified to UV drift, zoom breathing, and color breathing only
- Blur computed ONCE at load time, shader only does motion effects
- No per-frame blur, image processing, or texture uploads
2026-02-01 11:24:24 -06:00
vicrodh b110516965 feat(immersive): increase source quality to 256x256
- Source canvas now 256x256 (was 64x64)
- Light pre-blur (8px), GPU shader does main blur
- Increased shader blur radius and samples (16 samples)
- Should produce much smoother results
2026-02-01 10:53:13 -06:00
vicrodh add1cf3cc0 feat(immersive): add GPU blur + noise distortion in shader
- Multi-sample blur: 12 samples in circular pattern
- Noise-based UV distortion to break up pixelation
- Random sample offsets for organic blur effect
- All blur computation is GPU-side (no CPU cost)
2026-02-01 10:50:14 -06:00
vicrodh 6fc1156b93 fix(immersive): match original blur quality with triple-pass blur
- Canvas size back to 64x64 (like original)
- Blur radius 20px applied 3 times (20 + 20 + 10 = ~50px total)
- Expanded canvas for blur overflow, then crop to final
- Brightness 0.55, saturation 1.3 (matching original)
2026-02-01 10:46:43 -06:00
vicrodh 7795fa159e fix(immersive): increase animation visibility + more blur + debug logs
- Animation params increased: 8% UV drift, 5% zoom, 12% brightness
- Canvas reduced to 8x8 for maximum blur effect
- Added debug logs to verify animation is running
2026-02-01 10:31:18 -06:00
vicrodh 606fb43853 fix(immersive): proper two-canvas blur technique + reduce to 15fps
Blur fix:
- Use three separate canvases (source, blur, final)
- Apply blur filter when drawing BETWEEN canvases (not to self)
- Canvas size reduced to 16x16 for extreme blur when scaled
- Double blur pass for extra smoothness

CPU fix:
- Reduce animation from 30fps to 15fps
- Slow ambient motion doesn't need high frame rate
2026-02-01 10:27:12 -06:00
vicrodh 3a93651122 fix(immersive): increase blur intensity for proper background effect
- Reduce canvas to 32x32 (was 128) for more natural scaling blur
- Apply triple-pass blur technique:
  1. Scale down (interpolation blur)
  2. Apply blur filter and redraw
  3. Third pass for extra smoothness
- Adjust brightness to 0.45 (darker) and saturation to 1.3
- Lower JPEG quality to 0.7 (blur hides artifacts anyway)
2026-02-01 10:19:11 -06:00
vicrodh 34710e92e1 feat(immersive): integrate WebGL2 renderer into ImmersiveBackground
- ImmersiveBackground now checks WebGL2 availability on mount
- Dynamically imports ImmersiveAmbientCanvas when WebGL2 available
- Falls back to CSS blur when WebGL2 unavailable
- New props: enableAmbient (default true), ambientIntensity

Automatic renderer selection:
1. Check BUILD_IMMERSIVE_ENABLED (compile-time)
2. Check isRuntimeEnabled() (user preference)
3. Check isWebGL2Available() (browser capability)
4. If all pass: use WebGL2 with ambient motion
5. Otherwise: use CSS fallback (original behavior)
2026-02-01 10:13:50 -06:00
vicrodh c94857fc87 feat(immersive): add Phase 3 ambient motion shader
- Add shaders/ambient.frag with:
  - UV drift (slow wandering motion)
  - Zoom oscillation (breathing effect)
  - Color breathing (subtle brightness pulsing)
  - Configurable intensity via u_intensity uniform

- Update ImmersiveAmbientCanvas.svelte:
  - Use ambient shader instead of static
  - Add animation loop with requestAnimationFrame
  - Frame throttling at 30fps for power efficiency
  - Visibility-aware: pauses when tab hidden
  - Props: enableMotion, intensity
  - Responds to enableMotion changes dynamically

All motion computation is GPU-side. No CPU per-frame work
except uniform updates (3 floats).
2026-02-01 10:12:09 -06:00
vicrodh 350352afb9 feat(immersive): add Phase 2 texture loader with pre-blur
- Add utils/texture-loader.ts with:
  - Async pre-blur generation using canvas 2D
  - Blur cache (max 20 entries)
  - Request cancellation for rapid track changes
  - Abort signal support throughout

- Update ImmersiveAmbientCanvas.svelte:
  - Use texture-loader for blurred artwork
  - Handle cancellation gracefully
  - Report texture metrics
  - Clean up pending loads on destroy

Pre-blur is computed once per track change (CPU), then uploaded
to GPU texture. No per-frame blur computation.
2026-02-01 10:10:44 -06:00
vicrodh 979326eeba feat(immersive): add Phase 1 minimal WebGL2 renderer
- Add utils/webgl-utils.ts with context creation, shader compilation,
  texture loading, and cleanup utilities
- Add shaders/fullscreen.vert for fullscreen quad rendering
- Add shaders/static.frag for basic texture display
- Add shaders/index.ts for Vite ?raw shader imports
- Add ImmersiveAmbientCanvas.svelte component with:
  - WebGL2 context management
  - Context loss/restore handling
  - Automatic resize handling
  - Performance metrics reporting
- Update app.d.ts with shader file type declarations

This is a static renderer only - no animation yet.
Phase 2 will connect to real artwork with pre-blur.
2026-02-01 10:09:13 -06:00