NikkeDoy daf9c5739c
All checks were successful
SonarQube Code Quality Scan / SonarQube Scan (push) Successful in 1m43s
🐛 | Code quality fixes
- config.py: move 'import shutil' to module level
- player.py: unify type hints, narrow except, add debug log
- discord_rpc.py: replace broad except Exception with specific types
- gui.py: remove unused import; replace lambda closures with method refs; fix closure scope bug; extract _populate_list_page() to remove duplicate code; add public accessors; make flush_volume public; add AudioVisualizer.reset_activity()
- tests: replace unused _f variable with Path.touch()
2026-06-04 18:27:44 +03:00
2026-06-03 18:53:24 +03:00
2026-05-31 23:38:45 +03:00
2026-06-04 18:27:44 +03:00
2026-06-03 18:53:24 +03:00
2026-06-04 18:27:44 +03:00
2026-06-04 18:27:44 +03:00
2026-06-04 18:27:44 +03:00
2026-05-31 22:57:28 +03:00
2026-05-31 23:03:55 +03:00
2026-06-04 18:27:44 +03:00
2026-06-03 19:05:17 +03:00
2026-06-03 18:53:24 +03:00
2026-05-31 23:03:55 +03:00
2026-06-03 18:53:24 +03:00

Tunetti 🎵

Quality Gate Status

A desktop YouTube Music player — search, play, and manage your music without opening a browser. 🖥️

Tunetti screenshot

🤖 A note about this project

This project is approximately 99% AI-generated code. It was created by prompting large language models — not by hand. The code works, but it may not follow every best practice you'd expect from hand-written software. Contributions, bug reports, and suggestions are very welcome! 🙏


What can it do?

  • 🎶 YouTube Music search & playback — Find songs, albums, and artists right from the app.
  • 🎧 Play music in the background — Keep listening while you work.
  • 🎨 Good-looking interface — Dark theme with a modern, clean design.
  • 🎤 Discord Rich Presence — Show your friends what you're listening to.
  • 📊 Play history & stats — See your most-played tracks, listening trends, and daily counts.
  • Favourites — Save songs you love and find them again instantly.
  • 📈 Audio visualizer — A colorful spectrum display that moves with the music.
  • ⏯️ Full playback controls — Play, pause, skip, seek, volume, loop, shuffle, and queue.
  • ⚙️ Configurable — Toggle Discord RPC, visualizer, and more in settings.
  • 💾 Lightweight — Streams audio on demand; no big music library to store.

📋 What you'll need

  • Python 3.10 or newer
  • Linux with PulseAudio or PipeWire for sound
  • FFmpeg installed and on your PATH

🚀 Getting started

# Download the code
git clone https://git.huitsinnevada.fi/NikkeDoy/Tunetti.git
cd Tunetti

# Set up a virtual environment
python -m venv .venv
source .venv/bin/activate

# Install everything
pip install -r requirements.txt

⚠️ You might also need system packages like libegl1 or libxkbcommon0 — your package manager will tell you what's missing.

▶️ Running Tunetti

# Normal mode
python main.py

# Debug mode (see what's happening under the hood)
TUNETTI_VERBOSE=1 python main.py

On first launch, Tunetti creates ~/.config/tunetti/ and sets everything up for you.

🔧 Environment variables

Variable What it does
TUNETTI_VERBOSE Set to 1, true, or yes to see detailed debug logs.

📁 How the code is organized

Tunetti/
├── main.py                # App start & logging
├── gui.py                 # All the visual stuff (window, search bar, visualizer, stats, settings)
├── player.py              # Audio playback, downloads, queue
├── config.py              # Settings loader
├── music_db.py            # History, favourites, stats database
├── discord_rpc.py         # Discord integration
├── requirements.txt       # List of Python packages needed
├── sonar-project.properties
└── .gitea/
    └── workflows/
        └── sonar.yaml     # Automated code checks

⚙️ Settings

Tunetti stores its settings in ~/.config/tunetti/config.json. Here's what you can change:

Setting Default What it does
volume 50 Playback volume (0100)
max_history 5000 Max number of plays to remember
discord_rpc_enabled true Show what you're listening to on Discord
visualizer_enabled true Show the audio spectrum visualizer
db_path ~/.config/tunetti/music_history.db Where the database is stored

📦 What's under the hood

Package What it's used for
yt-dlp Downloads audio from YouTube
ytmusicapi Searches YouTube Music
PySide6 The graphical interface (Qt6)
pypresence Discord Rich Presence

🧪 Testing

Tests use pytest with coverage and are designed to run both locally and in CI (SonarQube picks up the coverage report automatically).

# Install test dependencies
pip install -r requirements-dev.txt

# Run all tests
.venv/bin/python -m pytest tests/ -v

# Run with coverage (generates coverage.xml for SonarQube)
.venv/bin/coverage run -m pytest tests/
.venv/bin/coverage xml
Module Coverage What's covered
music_db.py 100% All DB operations: record, favourites, history, stats, edge cases
config.py 87% Load, save, migrate, volume clamping, get/set settings
discord_rpc.py 84% _safe_artists edge cases, DiscordRPC lifecycle, mocked pypresence
player.py 32% Helpers: _best_thumbnail, _build_song_dict, _generate_test_wav, _stale_files, _build_resolved_dict
gui.py 12% Helpers: _fmt_ms, _artists_str, _norm_artists, _artists_from_json

The Qt GUI/player classes require a display server and PulseAudio — they can't run in headless CI. Guarded imports (in player.py and gui.py) ensure pure helper functions are still testable anywhere.

📄 License

See LICENSE.

Description
No description provided
Readme MIT 664 KiB
Languages
Python 100%