Skip to content

InstaZDLL/WaveFlow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

34 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

WaveFlow logo

WaveFlow

Local music player for desktop β€” built with Tauri 2, React 19 & Rust

Version Tauri 2 React 19 Rust License Platform


WaveFlow is a local music player desktop app with a Spotify-inspired 3-panel UI. It scans your local audio folders, organizes tracks by album/artist/genre, and plays them with a real-time audio engine β€” no streaming, no cloud, your music stays on your machine.

Features

  • Audio playback β€” symphonia decoder + cpal output, supports MP3, FLAC, WAV, OGG Vorbis, AAC, ALAC (M4A)
  • Real-time engine β€” lock-free 3-thread architecture (decoder, ring buffer, cpal callback), zero allocations in the hot path
  • Library scanning β€” point to any folder, metadata extraction via lofty, embedded artwork extraction
  • Multi-artist β€” automatic split of "Artist A, Artist B" into individual, independently-linkable artists
  • Album & artist detail pages β€” clickable album/artist cards open a dedicated view with tracklist, discography, and stats
  • Now Playing panel β€” Spotify-style right-edge panel with large artwork, clickable artists, and artist biography
  • Metadata enrichment β€” Deezer public API (artist images, album covers, labels) + Last.fm (artist biographies) cached 30 days locally; artwork is downloaded into a hash-addressed on-disk cache so it renders offline on re-visits
  • Playlists β€” create, edit, delete, add tracks from folders/albums/artists in bulk
  • Likes β€” heart any track, dedicated "Liked tracks" view
  • Search β€” instant full-text search (FTS5 contentless) across titles, artists, albums with prefix matching
  • Queue β€” persistent queue with shuffle (Fisher-Yates), repeat (off/all/one), auto-advance
  • Resume β€” remembers last track + position across app restarts
  • Audio settings β€” volume normalization (-3 dB), mono downmix, crossfade slider (UI ready)
  • Virtual scroll β€” handles 6000+ tracks without UI freeze (@tanstack/react-virtual)
  • Dark mode β€” animated radial transition via View Transitions API
  • i18n β€” French & English, auto-detected, switchable in settings
  • Accessibility β€” keyboard navigation, ARIA roles, focus rings, prefers-reduced-motion
  • Profiles β€” isolated per-profile database (libraries, playlists, settings, play history)

Tech Stack

Layer Technologies
Desktop shell Tauri 2.10
Frontend React 19, TypeScript, Vite 8, Tailwind CSS 4, Lucide icons
Backend Rust, SQLite (sqlx), FTS5 contentless full-text search
Audio symphonia 0.5 (decode), cpal 0.15 (output), rubato 0.15 (resample), rtrb 0.3 (SPSC ring)
External metadata Deezer public API (no auth) + Last.fm (user-provided API key) via reqwest 0.12 with rustls
Package manager Bun

Getting Started

# Install dependencies
bun install

# Run the desktop app in development mode
bun run tauri dev

# Build for production
bun run tauri build

Development Commands

bun run dev          # Vite dev server only (no Tauri shell)
bun run typecheck    # TypeScript check
bun run lint         # ESLint
bun run lint:fix     # ESLint with auto-fix
bun run format       # Prettier

Project Structure

waveflow/
β”œβ”€β”€ src/                              # React frontend
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ common/                   # Reusable UI (NavItem, Artwork, ArtistLink, modals, EmptyState)
β”‚   β”‚   β”œβ”€β”€ layout/                   # Sidebar, TopBar, AppLayout, QueuePanel, NowPlayingPanel
β”‚   β”‚   β”œβ”€β”€ player/                   # PlayerBar, PlaybackControls, VolumeControl, ProgressBar
β”‚   β”‚   └── views/                    # Home, Library, Playlist, AlbumDetail, ArtistDetail, Liked, Recent, Settings, etc.
β”‚   β”œβ”€β”€ contexts/                     # ThemeContext, PlayerContext, LibraryContext, PlaylistContext, ProfileContext
β”‚   β”œβ”€β”€ hooks/                        # useTheme, usePlayer, useLibrary, usePlaylist, useProfile
β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   β”œβ”€β”€ tauri/                    # Typed invoke() wrappers (track, browse, player, playlist, detail, integration)
β”‚   β”‚   β”œβ”€β”€ playlistVisuals.ts        # Shared color/icon constants for playlists
β”‚   β”‚   └── PlaylistIcon.tsx          # Icon dispatcher component
β”‚   β”œβ”€β”€ i18n/locales/                 # fr.json, en.json
β”‚   β”œβ”€β”€ types/                        # ViewId, LibraryTab, NavItemProps, etc.
β”‚   β”œβ”€β”€ App.tsx                       # Provider tree
β”‚   └── main.tsx                      # Entry point
β”œβ”€β”€ src-tauri/                        # Rust backend
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ audio/                    # Audio engine (engine, decoder, output, resampler, state, analytics)
β”‚   β”‚   β”œβ”€β”€ commands/                 # Tauri commands (library, playlist, track, browse, player, scan, profile, deezer, integration)
β”‚   β”‚   β”œβ”€β”€ db/                       # Database open/migrate helpers (app.db + per-profile data.db)
β”‚   β”‚   β”œβ”€β”€ deezer.rs                 # Deezer public API client (search/get artist & album)
β”‚   β”‚   β”œβ”€β”€ lastfm.rs                 # Last.fm API client (artist.getInfo with HTML strip)
β”‚   β”‚   β”œβ”€β”€ lrclib.rs                 # LRCLIB API client (synchronized lyrics)
β”‚   β”‚   β”œβ”€β”€ metadata_artwork.rs       # Shared on-disk cache for remote artwork (blake3-hashed)
β”‚   β”‚   β”œβ”€β”€ queue.rs                  # Persistent queue operations (fill, advance, shuffle, restore)
β”‚   β”‚   β”œβ”€β”€ state.rs                  # AppState (profile pool, paths, global app_db)
β”‚   β”‚   β”œβ”€β”€ paths.rs                  # Filesystem layout
β”‚   β”‚   β”œβ”€β”€ error.rs                  # AppError + AppResult
β”‚   β”‚   └── lib.rs                    # Tauri setup, command registration, shutdown hook
β”‚   β”œβ”€β”€ migrations/
β”‚   β”‚   β”œβ”€β”€ app/                      # Global app.db schema (profile list, app_setting, deezer cache tables)
β”‚   β”‚   └── profile/                  # Per-profile SQLite schema (FTS5 contentless, triggers, indexes, lyrics)
β”‚   β”œβ”€β”€ Cargo.toml
β”‚   └── tauri.conf.json
└── package.json

Audio Architecture

β”Œβ”€ Tauri commands (tokio)     β”Œβ”€ Decoder thread (std)        β”Œβ”€ cpal callback (real-time)
β”‚  player_play, pause, seek   β”‚  symphonia FormatReader +     β”‚  pop f32 from SPSC ring
β”‚  β†’ crossbeam::Sender ──────►│  Decoder + rubato Resampler   β”‚  Γ— volume Γ— normalization
β”‚                              β”‚  push f32 β†’ rtrb::Producer ──►│  mono downmix (if enabled)
β”‚                              β”‚  emit position/state events   β”‚  β†’ device native format
└──────────────────────────────┴───────────────────────────────┴──────────────────────────

Rules: the cpal callback never allocates, never locks, never logs. It only touches rtrb::Consumer and Atomic* fields in SharedPlayback.

i18n

Strings are externalized in src/i18n/locales/. To add a language:

  1. Create src/i18n/locales/xx.json (same structure as fr.json)
  2. Import it in src/i18n/index.ts and add to SUPPORTED_LANGUAGES
  3. It will appear in the Settings language selector automatically

License

GPL-3.0 β€” see LICENSE

About

🌊 WaveFlow is a modern local music player with a clean, Spotify-like interface. Manage and listen to your own audio library directly from your browser. Built with React & Tailwind CSS.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages