Files
just-music-premium/docs/DEV.md
Barış Keser 751b85a807 v1.0.4: playlist toplu indirme + arayuz duzeltmeleri + Dependabot + belgeler
Ozellikler:
- Playlist toplu indirme (onizle-ve-sec): YouTube playlist URL'si yapistir ->
  tum parcalar arama sonucu gibi listelenir (SearchThread playlist modu,
  noplaylist=False + extract_flat), checkbox'la sec, toplu indir. Yeni bridge
  slotu importPlaylist(url). Indirme pill'i "X/Y" sayaci gosterir (download_total).
- Geri/Ileri gezinme: ust bardaki oklar artik gercek gorunum-gecmisi yiginiyla
  calisir (recordHistory/navBack/navFwd, wireEvents'te baglandi).

Duzeltmeler (alt-ajan taramasindan):
- Komut paletinden karaoke menusu flash-kapaniyordu -> palet ogesi onclick'i
  stopPropagation (global tikla-kapat menuyu silmesin).
- Arama/akilli-liste gorunumunde surukle-sirala gercek listeyi bozup
  kaydediyordu -> trackRow(reorderable): yalniz gercek tam-liste suruklenebilir.
- dl-pill/sep-pill/mini-klip ayni sag-alt kosede biniyordu -> pill'ler sol-alta,
  sepPill dl'nin ustune; ayrica sepPill .show sinifi eksikti (gorunmuyordu) -> fix.
- trackChanged JSON.parse guard'siz -> try/catch.
- repeat_mode trackChanged payload'inda yoktu -> eklendi + okundu (3 durumlu
  tekrar dugmesi parca degisince dogru).
- Eski YouTube sonuclari sorgu degisince temizleniyor.

Altyapi:
- Dependabot (.github/dependabot.yml): pip + github-actions haftalik.
- docs/: ARCHITECTURE, BRIDGE-SIGNALS, KNOWN-ISSUES, DEV (+ TR->EN sozluk) —
  proje kendini belgeliyor. graphify grafigi guncellendi.
- README + GitHub about + Pages: banner (OpenRouter/Nano Banana Pro ile uretildi),
  rozetler, v1.0.4 notlari.
2026-09-19 21:50:15 +03:00

10 KiB
Raw Permalink Blame History

Just Music Premium — Developer Quickstart

A Windows desktop music player: Python + PyQt6 QtWebEngine. The UI is a local web app (justmusic/web/, HTML/CSS/JS) served over a custom app:// scheme and wired to Python through a QWebChannel bridge. Audio DSP is Python (numpy/scipy/sounddevice); downloads use the yt-dlp Python library; studio karaoke (vocal/instrument separation) uses demucs on CPU.

This is the get-started guide. For design rationale and non-obvious decisions see the companion docs listed in Docs index.

Windows-only project. All commands below are for a Windows shell (PowerShell). Paths use \.


1. Run from source (dev)

Interpreter. Python 3.13 family (C:\Python313). CI builds on 3.12, so both are fine.

Trap on this machine: python3 is the Microsoft Store stub — use python (i.e. C:\Python313\python.exe), not python3.

Create the venv and install deps (from the project root):

python -m venv .venv
.venv\Scripts\python.exe -m pip install --upgrade pip
.venv\Scripts\python.exe -m pip install -r requirements.txt

requirements.txt pulls PyQt6 + PyQt6-WebEngine, numpy/scipy/sounddevice, yt-dlp, demucs (drags in torch — CPU wheel, ~490 MB), and pyinstaller.

Embedded binaries — bin/ must exist. The app calls three bundled executables that are NOT in the repo tree by default; CI downloads them fresh each build. For a source run they must be present in bin/:

File Purpose
bin\ffmpeg.exe transcode / decode to mp3
bin\yt-dlp.exe (the in-process yt-dlp library does the work; exe is the fallback)
bin\deno.exe required for YouTube nsig / JS signature solving — see ARCHITECTURE.md

justmusic/config.py resolves each from bin/ first, falls back to PATH, and prepends bin/ to the process PATH so the in-process yt-dlp finds deno.exe. Without deno.exe, YouTube downloads break. (bin/ currently has all three checked in on this machine.)

Launch:

.venv\Scripts\python.exe main.py

main.py registers the app:// URL scheme, spins up the QMainWindow + QWebEngineView, registers the Bridge on the web channel, and loads app://app/index.html.

User data lives outside the repo — in ~\Music\JustMusic\ (writable even if the app is installed read-only):

  • library.json — the library/playlist database (config.DATA_FILE)
  • downloads\ — downloaded tracks
  • covers\ — cover-art cache
  • stems\ — demucs vocal/instrument separation output (studio karaoke)

config.ensure_dirs() creates the base, downloads\, and covers\ on startup. Your own ~\Music is also scanned for the auto playlist.


2. Build the exe locally

python build.py

Output: dist\JustMusic\JustMusic.exe (PyInstaller onedir — fast startup, recommended). build.py --onefile produces a single dist\JustMusic.exe instead (portable but slow to start).

The build --collect-alls torch + demucs and their friends (julius, einops, lameenc, safetensors, sphn, huggingface_hub) plus PyQt6 WebEngine, and --add-binarys the three bin/ exes and the web UI. Consequence: the build is large (~1.4 GB dist\) and slow.

Before rebuilding, dist\ and build\ will be locked if the app is running. Kill any running JustMusic.exe and its QtWebEngineProcess children, then delete dist\ and build\:

taskkill /IM JustMusic.exe /F 2>$null; taskkill /IM QtWebEngineProcess.exe /F 2>$null
Remove-Item -Recurse -Force dist, build -ErrorAction SilentlyContinue

3. Release a new version (the important one)

Shipping is just tag + push — CI builds the .msi and publishes the GitHub Release, and the app auto-updates itself in the field.

  1. Bump the version to match the tag. Edit APP_VERSION in justmusic\config.py (currently "1.0.3") so it equals the tag you're about to push, e.g. 1.0.4.

  2. Tag and push:

    git tag v1.0.4
    git push origin v1.0.4
    

    The v* tag triggers .github/workflows/build.yml on windows-latest, which:

    • re-stamps config.APP_VERSION from the tag (so the exe always knows its own version — you still bump it in step 1 so source and tag agree);
    • pip install -r requirements.txt;
    • downloads fresh ffmpeg.exe, yt-dlp.exe, deno.exe into bin/;
    • runs python build.py;
    • packages a .msi with WiX 3.14 (heat → candle → light, installer\Product.wxs) — perUser install, no UAC / admin;
    • publishes a GitHub Release on the tag with JustMusic-Setup.msi attached.

    You can also run it without a tag via workflow_dispatch (manual run) with a version input.

  3. In-app auto-update — justmusic\updater.py. On launch, a background UpdateCheckThread asks the GitHub "latest release" API (config.UPDATE_API). If the release tag is newer than APP_VERSION, it downloads JustMusic-Setup.msi silently to %TEMP%\JustMusic-update\ and stages it. On app close (Bridge.shutdown), a detached .cmd waits for the app to exit, runs msiexec /i ... /qn (silent, perUser → no UAC), and relaunches the exe.

    • Only frozen (PyInstaller) builds download; a source run just compares versions and does nothing. No network → it gives up silently.

    Net effect: to ship, you only tag + push. Users get it on their next launch/close cycle.

  4. GitHub Pages landing page — .github/workflows/pages.yml deploys site/ to Pages on push to main (when site/** or the workflow file changes). Independent of the release flow.


4. Common maintenance

yt-dlp goes stale. YouTube changes its player/signature often; an old yt-dlp starts failing downloads (e.g. HTTP 403). Fix:

  1. bump the floor in requirements.txt — the yt-dlp>=YYYY.MM.DD line;
  2. bump APP_VERSION, tag a patch, push.

CI always fetches the newest yt-dlp, so a fresh release usually clears it. This is exactly what v1.0.3 was (yt-dlp>=2026.8.19, fixing the 403 that 2026.07.04 caused).


5. The knowledge graph (graphify)

graphify-out/ holds a graphify code graph (god nodes, community structure, cross-file relationships). Per the repo CLAUDE.md:

  • For codebase questions, prefer the scoped subgraph over raw grep:
    graphify query "<question>"
    graphify path "<A>" "<B>"      # relationships between two things
    graphify explain "<concept>"   # focused concept
    
  • graphify-out/wiki/index.md (if present) is good for broad navigation; read graphify-out/GRAPH_REPORT.md only for wide architecture review.
  • After editing code, refresh the graph (AST-only, no API cost):
    graphify update .
    

6. Docs index

Doc What's in it
docs/ARCHITECTURE.md Design overview + non-obvious decisions (why deno, the app:// scheme, DSP pipeline, clip mode)
docs/BRIDGE-SIGNALS.md The QWebChannel contracts — Python Bridge methods and Qt signals the web UI calls/listens to
docs/KNOWN-ISSUES.md Known defects and traps
docs/DEV.md This file

7. Turkish → English glossary

The code, comments, community/playlist labels, and UI strings are Turkish. Common terms a non-Turkish reader will hit:

Turkish English
Kütüphanem My Library (default playlist)
Beğenilen Şarkılar Liked Songs (favorites)
İndirilenler Downloads (playlist)
Çalma listesi Playlist
Şarkı Song / Track
Sanatçı Artist
Ara / Arama Search
İndir Download
Efektler Effects
Ekolayzır Equalizer
Kuyruk / Sıradaki Queue / Up next
Sözler / Şarkı Sözleri Lyrics
Karaoke / Vokal Vocal (karaoke)
Enstrümantal Instrumental
Ayır Separate (stems)
Kapak Cover art
Tema Theme
Ayarlar Settings
Sürükle Drag
Klip / Klip izle Video clip / Watch clip
Ses Volume / Audio
Hız Speed
Tara Scan (music folder)
Yedek / Yedek al Backup / Back up
Güncelleme Update
Ruh Hali Mood
Akıllı Listeler Smart Playlists
Ana Sayfa Home
Oynat / Duraklat Play / Pause
Önceki / Sonraki Previous / Next
Karıştır Shuffle
Tekrarla Repeat
Beğen Like
Görselleştirici Visualizer
Uyku zamanlayıcı Sleep timer
Sessize al Mute
Ambiyans ışığı Ambient light
Kompakt mod Compact mode
İstatistikler Statistics
Ekle Add (import)
Tam ekran Fullscreen
Bas / Orta / Tiz Bass / Mid / Treble (EQ bands)
Yankı / Reverb Reverb / Echo
Oda Room (reverb preset)
Düzenle Edit
Sil / Kaldır Delete / Remove
Bilinmeyen Unknown (missing metadata)