Rename: l'app si chiama MusicTools (non piu MusicDownload)
- main.py: titolo finestra pywebview -> 'MusicTools' - core/config.py: APP_NAME='MusicTools', cartella config bundled ora ~/Library/Application Support/MusicTools/ e %APPDATA%/MusicTools/. Migrazione one-shot: se non esiste la nuova ma esiste la legacy 'MusicDownload', il config.json viene copiato cosi' le impostazioni non vanno perse dopo l'aggiornamento - core/recorder.py: messaggio errore permesso microfono - api/bridge.py: User-Agent update check + guida Spotify menzionano MusicTools - build_macos.py / build_windows.py / .github/workflows/build.yml: prodotti rinominati (MusicTools.app, MusicTools.exe, MusicTools-macOS.zip, MusicTools-Windows.zip, Release 'Build MusicTools') - webui: <title>, brand-name sidebar, intestazioni commenti - README: tutti i riferimenti aggiornati + nota che il repo Git conserva il nome storico 'musicdownload' (URL stabili per release gia' pubblicate) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1 parent
6f5c32165a
commit
850d3f4b6c
11 files changed
+77
-57
No files matched your search
+14
-14
@@ -1,4 +1,4 @@
|
||||
name: Build MusicDownload
|
||||
name: Build MusicTools
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -36,14 +36,14 @@ jobs:
|
||||
- name: Package .app -> zip
|
||||
run: |
|
||||
cd dist
|
||||
ditto -c -k --sequesterRsrc --keepParent MusicDownload.app ../MusicDownload-macOS.zip
|
||||
ls -lh ../MusicDownload-macOS.zip
|
||||
ditto -c -k --sequesterRsrc --keepParent MusicTools.app ../MusicTools-macOS.zip
|
||||
ls -lh ../MusicTools-macOS.zip
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MusicDownload-macOS
|
||||
path: MusicDownload-macOS.zip
|
||||
name: MusicTools-macOS
|
||||
path: MusicTools-macOS.zip
|
||||
retention-days: 14
|
||||
|
||||
# =========================================================
|
||||
@@ -69,14 +69,14 @@ jobs:
|
||||
- name: Package -> zip
|
||||
shell: pwsh
|
||||
run: |
|
||||
Compress-Archive -Path dist/MusicDownload/* -DestinationPath MusicDownload-Windows.zip -CompressionLevel Optimal
|
||||
Get-Item MusicDownload-Windows.zip
|
||||
Compress-Archive -Path dist/MusicTools/* -DestinationPath MusicTools-Windows.zip -CompressionLevel Optimal
|
||||
Get-Item MusicTools-Windows.zip
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MusicDownload-Windows
|
||||
path: MusicDownload-Windows.zip
|
||||
name: MusicTools-Windows
|
||||
path: MusicTools-Windows.zip
|
||||
retention-days: 14
|
||||
|
||||
# =========================================================
|
||||
@@ -90,22 +90,22 @@ jobs:
|
||||
- name: Download macOS artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: MusicDownload-macOS
|
||||
name: MusicTools-macOS
|
||||
path: artifacts/macos
|
||||
|
||||
- name: Download Windows artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: MusicDownload-Windows
|
||||
name: MusicTools-Windows
|
||||
path: artifacts/windows
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: MusicDownload ${{ github.ref_name }}
|
||||
name: MusicTools ${{ github.ref_name }}
|
||||
tag_name: ${{ github.ref_name }}
|
||||
generate_release_notes: true
|
||||
fail_on_unmatched_files: true
|
||||
files: |
|
||||
artifacts/macos/MusicDownload-macOS.zip
|
||||
artifacts/windows/MusicDownload-Windows.zip
|
||||
artifacts/macos/MusicTools-macOS.zip
|
||||
artifacts/windows/MusicTools-Windows.zip
|
||||
@@ -1,4 +1,4 @@
|
||||
# MusicDownload
|
||||
# MusicTools
|
||||
|
||||
Applicazione desktop per **scaricare musica e video**, **modificare i metadati** dei file audio e **registrare l'audio** da qualsiasi ingresso del computer.
|
||||
|
||||
@@ -8,6 +8,8 @@ Sviluppata da **LuZa**.
|
||||
|
||||
Repo: <https://github.com/luzadev/musicdownload>
|
||||
|
||||
> ℹ️ Il repo Git conserva il nome storico **`musicdownload`** (l'app prima si chiamava così); URL stabili per release già pubblicate e installazioni esistenti.
|
||||
|
||||
## Funzionalità
|
||||
|
||||
| Tab | Cosa fa |
|
||||
@@ -91,14 +93,14 @@ brew install blackhole-2ch
|
||||
|
||||
Anche se non è un microfono fisico, macOS richiede il permesso "Microfono" per leggere da BlackHole via AVFoundation.
|
||||
|
||||
Vai su **Preferenze di Sistema → Privacy e sicurezza → Microfono** e abilita l'app da cui lanci MusicDownload (Terminal/iTerm in sviluppo, oppure MusicDownload.app per la build distribuita). Se non vedi nessuna voce, comparirà un popup la prima volta che premi REC — accetta.
|
||||
Vai su **Preferenze di Sistema → Privacy e sicurezza → Microfono** e abilita l'app da cui lanci MusicTools (Terminal/iTerm in sviluppo, oppure MusicTools.app per la build distribuita). Se non vedi nessuna voce, comparirà un popup la prima volta che premi REC — accetta.
|
||||
|
||||
### 3. Setup A — minimo (registri ma non senti l'audio durante)
|
||||
|
||||
1. Click sull'icona altoparlante nella barra menu → **Output → BlackHole 2ch**
|
||||
*Oppure: Preferenze di Sistema → Audio → Uscita → BlackHole 2ch*
|
||||
2. Fai partire lo stream (Spotify/YouTube): non sentirai nulla — è normale, l'audio va a BlackHole
|
||||
3. App MusicDownload → tab **● Registra** → dispositivo **🔄 BlackHole 2ch (loopback)** → **REC**
|
||||
3. App MusicTools → tab **● Registra** → dispositivo **🔄 BlackHole 2ch (loopback)** → **REC**
|
||||
4. **Stop** e riascolta il file MP3 generato
|
||||
|
||||
### 4. Setup B — completo (registri E senti l'audio contemporaneamente, consigliato)
|
||||
@@ -119,7 +121,7 @@ Adesso ogni audio del sistema viene riprodotto sugli speaker (lo senti) e contem
|
||||
| Sintomo | Causa probabile | Fix |
|
||||
|---|---|---|
|
||||
| BlackHole non compare nel dropdown | CoreAudio non l'ha ancora caricato dopo l'install | `sudo killall coreaudiod` poi premi **↻ Aggiorna** |
|
||||
| Errore `ffmpeg exit -6` o `permesso Microfono mancante` | macOS nega l'accesso al device | Privacy e sicurezza → Microfono → abilita Terminal/MusicDownload |
|
||||
| Errore `ffmpeg exit -6` o `permesso Microfono mancante` | macOS nega l'accesso al device | Privacy e sicurezza → Microfono → abilita Terminal/MusicTools |
|
||||
| File MP3 muto | Output di sistema non passa per BlackHole | Cambia output su BlackHole o Multi-Output Device (vedi Setup A/B) |
|
||||
| Audio doppio/eco nel file | Stai registrando da BlackHole *e* da microfono fisico simultaneamente | Verifica che nel dropdown ci sia solo `BlackHole 2ch` |
|
||||
| Audio crackly/distorto | Sample rate non allineato | In Audio MIDI Setup, BlackHole + altoparlanti tutti a 48 kHz |
|
||||
@@ -127,7 +129,7 @@ Adesso ogni audio del sistema viene riprodotto sugli speaker (lo senti) e contem
|
||||
## Struttura progetto
|
||||
|
||||
```
|
||||
MusicDownload/
|
||||
MusicTools/
|
||||
├── main.py # Entry point — bootstrap pywebview
|
||||
├── requirements.txt
|
||||
├── build_macos.py # Script build macOS (.app)
|
||||
@@ -169,8 +171,8 @@ Il file `config.json` viene creato automaticamente al primo avvio:
|
||||
|
||||
Posizione:
|
||||
- **Sviluppo**: directory del progetto
|
||||
- **macOS bundle**: `~/Library/Application Support/MusicDownload/`
|
||||
- **Windows bundle**: `%APPDATA%/MusicDownload/`
|
||||
- **macOS bundle**: `~/Library/Application Support/MusicTools/`
|
||||
- **Windows bundle**: `%APPDATA%/MusicTools/`
|
||||
|
||||
## Build locale
|
||||
|
||||
@@ -182,7 +184,7 @@ pip install pyinstaller
|
||||
python3 build_macos.py
|
||||
```
|
||||
|
||||
Produce `dist/MusicDownload.app` con yt-dlp, ffmpeg, ffprobe e tutte le dylib bundled (rpath patchati con `install_name_tool`).
|
||||
Produce `dist/MusicTools.app` con yt-dlp, ffmpeg, ffprobe e tutte le dylib bundled (rpath patchati con `install_name_tool`).
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -191,14 +193,14 @@ pip install pyinstaller
|
||||
python build_windows.py
|
||||
```
|
||||
|
||||
Produce `dist/MusicDownload/MusicDownload.exe`. Lo script scarica automaticamente `yt-dlp.exe` e `ffmpeg.exe`/`ffprobe.exe` static build.
|
||||
Produce `dist/MusicTools/MusicTools.exe`. Lo script scarica automaticamente `yt-dlp.exe` e `ffmpeg.exe`/`ffprobe.exe` static build.
|
||||
|
||||
## Build & Release automatiche (GitHub Actions)
|
||||
|
||||
Ogni push di un tag `v*` triggera la pipeline `.github/workflows/build.yml`:
|
||||
|
||||
1. **`build-macos`** (runner `macos-latest`) → `MusicDownload-macOS.zip` (la `.app` zippata con `ditto`)
|
||||
2. **`build-windows`** (runner `windows-latest`) → `MusicDownload-Windows.zip`
|
||||
1. **`build-macos`** (runner `macos-latest`) → `MusicTools-macOS.zip` (la `.app` zippata con `ditto`)
|
||||
2. **`build-windows`** (runner `windows-latest`) → `MusicTools-Windows.zip`
|
||||
3. **`release`** → crea automaticamente una GitHub Release con entrambi gli asset allegati
|
||||
|
||||
Per pubblicare una nuova versione:
|
||||
@@ -211,10 +213,10 @@ git push origin v1.3.0
|
||||
Per fare solo una build di test (senza release):
|
||||
|
||||
```bash
|
||||
gh workflow run "Build MusicDownload" --ref main
|
||||
gh workflow run "Build MusicTools" --ref main
|
||||
```
|
||||
|
||||
oppure dalla UI: **Actions → Build MusicDownload → Run workflow**.
|
||||
oppure dalla UI: **Actions → Build MusicTools → Run workflow**.
|
||||
|
||||
Le release ufficiali sono disponibili su <https://github.com/luzadev/musicdownload/releases>.
|
||||
|
||||
|
||||
+2
-2
@@ -38,7 +38,7 @@ SPOTIFY_GUIDE_TEXT = """\
|
||||
1) Vai su https://developer.spotify.com/dashboard e accedi (anche con account free).
|
||||
2) Clicca "Create app".
|
||||
3) Compila:
|
||||
- App name: MusicDownload (o quello che vuoi)
|
||||
- App name: MusicTools (o quello che vuoi)
|
||||
- Description: a piacere
|
||||
- Redirect URI: http://localhost:8888/callback (obbligatorio ma non usato)
|
||||
- Seleziona "Web API"
|
||||
@@ -148,7 +148,7 @@ class Api:
|
||||
API_URL = "https://api.github.com/repos/luzadev/musicdownload/releases/latest"
|
||||
try:
|
||||
resp = requests.get(API_URL, headers={
|
||||
"User-Agent": "MusicDownload",
|
||||
"User-Agent": "MusicTools",
|
||||
"Accept": "application/vnd.github+json",
|
||||
}, timeout=10)
|
||||
resp.raise_for_status()
|
||||
|
||||
+9
-9
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Build script per creare MusicDownload.app su macOS.
|
||||
Build script per creare MusicTools.app su macOS.
|
||||
|
||||
Uso:
|
||||
python3 build_macos.py
|
||||
@@ -8,7 +8,7 @@ Uso:
|
||||
Cosa fa:
|
||||
1. Scarica il binario standalone di yt-dlp per macOS
|
||||
2. Raccoglie ffmpeg + ffprobe + tutte le loro dylib da Homebrew
|
||||
3. Esegue PyInstaller per creare MusicDownload.app
|
||||
3. Esegue PyInstaller per creare MusicTools.app
|
||||
|
||||
Requisiti:
|
||||
pip3 install pyinstaller
|
||||
@@ -210,7 +210,7 @@ def run_pyinstaller():
|
||||
|
||||
cmd = [
|
||||
sys.executable, "-m", "PyInstaller",
|
||||
"--name", "MusicDownload",
|
||||
"--name", "MusicTools",
|
||||
"--windowed",
|
||||
"--onedir",
|
||||
"--noconfirm",
|
||||
@@ -230,7 +230,7 @@ def run_pyinstaller():
|
||||
log(f"Comando: {' '.join(cmd[:10])}...")
|
||||
subprocess.run(cmd, check=True, cwd=str(ROOT))
|
||||
|
||||
app_path = DIST_DIR / "MusicDownload.app"
|
||||
app_path = DIST_DIR / "MusicTools.app"
|
||||
if app_path.exists():
|
||||
log(f"Build completata: {app_path}")
|
||||
# Mostra dimensione
|
||||
@@ -238,8 +238,8 @@ def run_pyinstaller():
|
||||
log(f"Dimensione: {size / 1024 / 1024:.0f} MB")
|
||||
else:
|
||||
log("ATTENZIONE: .app non trovata, controlla l'output di PyInstaller")
|
||||
# Potrebbe essere in dist/MusicDownload/ (non .app)
|
||||
alt = DIST_DIR / "MusicDownload"
|
||||
# Potrebbe essere in dist/MusicTools/ (non .app)
|
||||
alt = DIST_DIR / "MusicTools"
|
||||
if alt.exists():
|
||||
log(f"Trovata directory: {alt}")
|
||||
|
||||
@@ -249,7 +249,7 @@ def run_pyinstaller():
|
||||
# =========================================================================
|
||||
def main():
|
||||
print("=" * 50)
|
||||
print(" MusicDownload — Build macOS")
|
||||
print(" MusicTools — Build macOS")
|
||||
print("=" * 50)
|
||||
|
||||
# Verifica pyinstaller
|
||||
@@ -272,12 +272,12 @@ def main():
|
||||
print("\n" + "=" * 50)
|
||||
print(" DONE!")
|
||||
print("=" * 50)
|
||||
app = DIST_DIR / "MusicDownload.app"
|
||||
app = DIST_DIR / "MusicTools.app"
|
||||
if app.exists():
|
||||
print(f"\n L'app e in: {app}")
|
||||
print(f" Per testarla: open '{app}'")
|
||||
print(f"\n Per distribuirla, comprimi la cartella:")
|
||||
print(f" zip -r MusicDownload.zip dist/MusicDownload.app")
|
||||
print(f" zip -r MusicTools.zip dist/MusicTools.app")
|
||||
print()
|
||||
|
||||
|
||||
|
||||
+9
-9
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Build script per creare MusicDownload.exe su Windows.
|
||||
Build script per creare MusicTools.exe su Windows.
|
||||
|
||||
Uso:
|
||||
python build_windows.py
|
||||
@@ -7,7 +7,7 @@ Uso:
|
||||
Cosa fa:
|
||||
1. Scarica il binario standalone di yt-dlp per Windows
|
||||
2. Scarica ffmpeg static build per Windows
|
||||
3. Esegue PyInstaller per creare MusicDownload.exe
|
||||
3. Esegue PyInstaller per creare MusicTools.exe
|
||||
|
||||
Requisiti:
|
||||
pip install pyinstaller
|
||||
@@ -101,7 +101,7 @@ def run_pyinstaller():
|
||||
|
||||
cmd = [
|
||||
sys.executable, "-m", "PyInstaller",
|
||||
"--name", "MusicDownload",
|
||||
"--name", "MusicTools",
|
||||
"--windowed",
|
||||
"--onedir",
|
||||
"--noconfirm",
|
||||
@@ -126,11 +126,11 @@ def run_pyinstaller():
|
||||
log(f"Comando: {' '.join(cmd[:10])}...")
|
||||
subprocess.run(cmd, check=True, cwd=str(ROOT))
|
||||
|
||||
exe_path = DIST_DIR / "MusicDownload" / "MusicDownload.exe"
|
||||
exe_path = DIST_DIR / "MusicTools" / "MusicTools.exe"
|
||||
if exe_path.exists():
|
||||
log(f"Build completata: {exe_path}")
|
||||
else:
|
||||
log("ATTENZIONE: MusicDownload.exe non trovato, controlla l'output")
|
||||
log("ATTENZIONE: MusicTools.exe non trovato, controlla l'output")
|
||||
|
||||
|
||||
# =========================================================================
|
||||
@@ -138,7 +138,7 @@ def run_pyinstaller():
|
||||
# =========================================================================
|
||||
def main():
|
||||
print("=" * 50)
|
||||
print(" MusicDownload - Build Windows")
|
||||
print(" MusicTools - Build Windows")
|
||||
print("=" * 50)
|
||||
|
||||
if sys.platform != "win32":
|
||||
@@ -167,12 +167,12 @@ def main():
|
||||
print("\n" + "=" * 50)
|
||||
print(" DONE!")
|
||||
print("=" * 50)
|
||||
dist = DIST_DIR / "MusicDownload"
|
||||
dist = DIST_DIR / "MusicTools"
|
||||
if dist.exists():
|
||||
print(f"\n L'app e in: {dist}")
|
||||
print(f" Eseguibile: {dist / 'MusicDownload.exe'}")
|
||||
print(f" Eseguibile: {dist / 'MusicTools.exe'}")
|
||||
print(f"\n Per distribuirla, comprimi la cartella:")
|
||||
print(f" Comprimi {dist} -> MusicDownload_Windows.zip")
|
||||
print(f" Comprimi {dist} -> MusicTools_Windows.zip")
|
||||
print()
|
||||
|
||||
|
||||
|
||||
+21
-3
@@ -8,21 +8,39 @@ from pathlib import Path
|
||||
VERSION = "v1.2.2"
|
||||
|
||||
|
||||
APP_NAME = "MusicTools"
|
||||
_LEGACY_NAME = "MusicDownload"
|
||||
|
||||
|
||||
def _get_config_dir() -> Path:
|
||||
"""Ritorna la directory per config.json.
|
||||
|
||||
Frozen (bundle PyInstaller):
|
||||
- macOS: ~/Library/Application Support/MusicDownload/
|
||||
- Windows: %APPDATA%/MusicDownload/
|
||||
- macOS: ~/Library/Application Support/MusicTools/
|
||||
- Windows: %APPDATA%/MusicTools/
|
||||
Dev (non frozen):
|
||||
- directory del progetto
|
||||
|
||||
Se la cartella nuova non esiste ma quella legacy 'MusicDownload' si',
|
||||
viene migrata (copia di config.json) cosi' l'utente non perde le
|
||||
impostazioni dopo il rename.
|
||||
"""
|
||||
if getattr(sys, "frozen", False):
|
||||
if sys.platform == "win32":
|
||||
base = Path(os.environ.get("APPDATA", Path.home()))
|
||||
else:
|
||||
base = Path.home() / "Library" / "Application Support"
|
||||
config_dir = base / "MusicDownload"
|
||||
config_dir = base / APP_NAME
|
||||
legacy_dir = base / _LEGACY_NAME
|
||||
# Migrazione one-shot: se non esiste la nuova ma esiste la vecchia
|
||||
if not config_dir.exists() and legacy_dir.exists():
|
||||
try:
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
legacy_cfg = legacy_dir / "config.json"
|
||||
if legacy_cfg.exists():
|
||||
(config_dir / "config.json").write_bytes(legacy_cfg.read_bytes())
|
||||
except OSError:
|
||||
pass
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
return config_dir
|
||||
return Path(__file__).resolve().parent.parent
|
||||
|
||||
+1
-1
@@ -350,7 +350,7 @@ def _extract_friendly_error(rc: int) -> str:
|
||||
return "Dispositivo non disponibile (riavvia il servizio audio o ricontrolla la selezione)."
|
||||
|
||||
if "permission" in text or "not authorized" in text or "not permitted" in text:
|
||||
return "Permesso microfono negato da macOS. Abilita Python/MusicDownload in Privacy → Microfono."
|
||||
return "Permesso microfono negato da macOS. Abilita Python/MusicTools in Privacy → Microfono."
|
||||
|
||||
if "no such device" in text or "no such audio device" in text:
|
||||
return "Dispositivo non trovato. Premi '↻ Aggiorna' e riseleziona."
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""MusicDownload — Entry point (pywebview + WebKit/EdgeChromium)."""
|
||||
"""MusicTools — Entry point (pywebview + WebKit/EdgeChromium)."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
@@ -23,7 +23,7 @@ def main():
|
||||
index_path = _resource_path("webui", "index.html")
|
||||
|
||||
window = webview.create_window(
|
||||
title="MusicDownload",
|
||||
title="MusicTools",
|
||||
url=index_path,
|
||||
js_api=api,
|
||||
width=1080,
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/* ===============================
|
||||
MusicDownload — Spotify-like UI
|
||||
MusicTools — Spotify-like UI
|
||||
=============================== */
|
||||
|
||||
:root {
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>MusicDownload</title>
|
||||
<title>MusicTools</title>
|
||||
<link rel="stylesheet" href="css/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
@@ -15,7 +15,7 @@
|
||||
<div class="brand-logo">
|
||||
<span>♫</span>
|
||||
</div>
|
||||
<div class="brand-name">MusicDownload</div>
|
||||
<div class="brand-name">MusicTools</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/* ======================================================
|
||||
MusicDownload — Frontend (vanilla JS)
|
||||
MusicTools — Frontend (vanilla JS)
|
||||
====================================================== */
|
||||
|
||||
const $ = (sel) => document.querySelector(sel);
|
||||
|
||||
Reference in new issue
Block a user