Rustify est un lecteur de musique local performant et moderne construit avec Tauri 2, Rust (moteur audio rodio, métadonnées lofty, base de données rusqlite) et du TypeScript natif sans framework lourd.
- Importation récursive : Scan de dossier avec détection automatique (
.mp3,.flac,.wav,.ogg,.m4a,.aac,.opus). - Métadonnées complètes : Extraction via
lofty(Titre, Artiste, Album, Genre, Année, Numéro de piste, Durée). - Pochettes d'album réelles : Extraction native et mise en cache performante via IPC
read_cover. - Moteur Audio Rust (
rodio) : Play, pause, reprise, stop, seek temporel précis, contrôle du volume et sélection du périphérique de sortie audio. - Gestion de la file de lecture : Queue dynamique, modes répétition (repeat) et lecture aléatoire (shuffle).
- Favoris : Marquage des pistes, albums et artistes préférés.
- Statistiques détaillées : Suivi des lectures (play count), skips (skip count), réactions (likes / dislikes) et durée totale / moyenne d'écoute par morceau.
- Historique de lecture : Traçabilité des dernières pistes jouées avec horodatage.
- Playlists : Création, gestion et lecture de listes personnalisées.
- Instance unique (Single Instance) : Prévention des lancements multiples simultanés.
- Interface réactive : Sidebar de navigation, animations (lecteur vinyle), barre de recherche instantanée et thématisation sombre aux accents ambre.
rustify/
├── src/ # Frontend (Vite + TypeScript native — pas de framework)
│ ├── main.ts # Logique UI, gestion d'état, IPC invoke()
│ └── style.css # Thème sombre, accent ambre, animation vinyle
├── index.html # Structure HTML5 sémantique
├── src-tauri/
│ ├── src/
│ │ ├── main.rs # Point d'entrée Tauri, plugins & enregistrement des commandes
│ │ ├── state.rs # AppState (Mutex<Connection>, Mutex<Player>)
│ │ ├── db.rs # Schéma SQLite + CRUD (tracks, playlists, favorites, stats)
│ │ ├── scanner.rs # Exploration de dossiers & extraction de tags (lofty)
│ │ ├── player.rs # Moteur audio (rodio) sur thread dédié (Queue, seek, volume)
│ │ ├── commands.rs # Interface IPC (Tauri commands)
│ │ └── models.rs # Structures de données partagées (Serialize/Deserialize)
│ ├── capabilities/ # Configuration des permissions Tauri 2
│ ├── tauri.conf.json # Configuration de l'application Tauri
│ └── Cargo.toml # Dépendances Rust (rodio, lofty, rusqlite, tauri-plugin-single-instance...)
Frontend (TS) ➔ invoke() ➔ commands.rs ➔ AppState ➔ db.rs (SQLite) / player.rs (rodio thread) ➔ Result<T, String>
- Rust (
winget install Rustlang.Rustup) - Node.js LTS (
winget install OpenJS.NodeJS.LTS) - Visual Studio Build Tools (Workload "Desktop development with C++" pour Windows MSVC)
# Cloner le dépôt et se placer dans le projet
cd rustify
# Installer les dépendances frontend
npm install
# Démarrer l'application en mode développement
npm run tauri devnpm run tauri build- Scan et import récursif de la bibliothèque musicale.
- Extraction des tags audio (
lofty). - Base de données locale SQLite (
rusqliteWAL mode). - Moteur audio Rust via thread dédié (
rodio). - Extraction et affichage des pochettes d'albums (
read_cover). - Système de favoris (Pistes, Albums, Artistes).
- Statistiques d'écoute avancées & Historique.
- Prévention multi-instances (Single Instance).
- Sélection dynamique des périphériques audio.
- Auto-enchaînement via callbacks
sinkau lieu du polling. - Synchronization bidirectionnelle du scan (détection/purge des fichiers supprimés avec confirmation).
- Surveillance multi-dossiers incrémentale (
mtime). - Reconstitution / Réordonnancement par Drag & Drop des playlists et de la queue.
- Raccourcis clavier globaux (Media Keys de l'OS).
- Égaliseur logiciel / Normalisation du volume (ReplayGain).
- Problème :
rodio::OutputStreamutilisecpal::platform::Streamqui est!Send. Le placer directement dansMutex<Player>bloquait la compilation Tauri (E0277). - Solution : Le moteur audio est exécuté dans son propre thread dédié créé via
player::spawn_player_thread(). Les commandes frontend communiquent viaSender<PlayerCommand>et lisent un état partagéArc<Mutex<PlayerState>>.
- Problème : Chokidar (Vite) bloquait les DLLs verrouillées par Cargo dans
src-tauri/target/. - Solution : Ajout de
server.watch.ignored: ['**/src-tauri/**']dansvite.config.ts.
Synchronisé automatiquement avec Auto-Github


