Compare commits

...
2 Commits
Author SHA1 Message Date
luzadev b74a0a53ec v1.7.11: fix definitivo BlackHole — ad-hoc codesign del bundle
Causa root: MusicTools.app ha il permesso TCC microfono, ma quando
lancia ffmpeg come subprocess macOS tratta ffmpeg come binario non
firmato distinto -> AVFoundation apre il device senza errore ma
restituisce solo silenzio.

Fix in build_macos.py: dopo PyInstaller + Info.plist, applico
`codesign --force --deep --sign -` ad-hoc su tutto il bundle.
La firma e' "free" (no Developer ID) ma rende l'app un singolo
team coerente per TCC, quindi il permesso del main si propaga
anche a ffmpeg/ffprobe/yt-dlp.
2026-06-09 21:29:30 +02:00
luzadev 415175ec4d v1.7.10: fix registrazione BlackHole muta (device by name)
QuickTime registrava da BlackHole, MusicTools no: il bug era che
list_input_devices passava al record l'index AVFoundation, ma
l'index puo' rinumerarsi tra l'elenco e l'apertura (iPhone in
continuita', Multi-Output Device, hot-plug). Quando ffmpeg apriva
:<index> col numero sbagliato, registrava silenzio dal device
"vero" mappato a quel numero.

Fix: in _list_macos uso il NOME del device come id (es.
"BlackHole 2ch"). ffmpeg AVFoundation accetta sia :<index> sia
:<name> ed il nome e' stabile. Aggiunto campo 'index' solo per
log/diagnostica. Nessun cambio Windows (gia' faceva by-name).
2026-06-09 20:58:51 +02:00
3 changed files with 62 additions and 3 deletions

No files matched your search

+47
View File
@@ -239,6 +239,7 @@ def run_pyinstaller():
if app_path.exists():
log(f"Build completata: {app_path}")
patch_info_plist(app_path)
adhoc_codesign(app_path)
# Mostra dimensione
size = sum(f.stat().st_size for f in app_path.rglob("*") if f.is_file())
log(f"Dimensione: {size / 1024 / 1024:.0f} MB")
@@ -292,6 +293,52 @@ def patch_info_plist(app_path):
log("Info.plist aggiornato.")
def adhoc_codesign(app_path):
"""Ad-hoc codesign dell'intero bundle .app.
Senza una firma coerente, macOS tratta ffmpeg (subprocess bundled)
come binario separato dal main MusicTools per TCC: ffmpeg apre il
dispositivo audio senza errore ma riceve solo silenzio perche' il
sistema non gli concede il permesso microfono ereditato.
`codesign --force --deep --sign -` applica una firma ad-hoc (gratis,
senza Developer ID) a tutti i binari nested. Per macOS questo rende
l'app un singolo "team" coerente, e il permesso TCC concesso al
main si propaga anche a ffmpeg/ffprobe/yt-dlp.
"""
log("Ad-hoc codesign del bundle (per TCC microfono ereditato)...")
try:
# Rimuovi vecchie firme che potrebbero confondere codesign --deep
subprocess.run(
["xattr", "-cr", str(app_path)],
capture_output=True,
)
subprocess.run(
["codesign", "--remove-signature", "--deep", str(app_path)],
capture_output=True,
)
result = subprocess.run(
["codesign", "--force", "--deep", "--sign", "-",
"--timestamp=none", str(app_path)],
capture_output=True, text=True,
)
if result.returncode != 0:
log(f"ATTENZIONE: codesign fallito: {result.stderr.strip()}")
else:
log("Codesign ad-hoc completato.")
# Verifica
verify = subprocess.run(
["codesign", "--verify", "--deep", "--strict", str(app_path)],
capture_output=True, text=True,
)
if verify.returncode == 0:
log("Verifica firma OK.")
else:
log(f"NOTA: verifica firma con warning: {verify.stderr.strip()}")
except FileNotFoundError:
log("ATTENZIONE: 'codesign' non trovato nel PATH, skip ad-hoc signing")
# =========================================================================
# Main
# =========================================================================
+1 -1
View File
@@ -5,7 +5,7 @@ import os
import sys
from pathlib import Path
VERSION = "v1.7.9"
VERSION = "v1.7.11"
APP_NAME = "MusicTools"
+14 -2
View File
@@ -73,7 +73,14 @@ def _is_virtual(name: str) -> bool:
def _list_macos(ffmpeg: str) -> list[dict]:
"""Parsa l'output di `ffmpeg -f avfoundation -list_devices true -i ""`.
L'output va su stderr."""
L'output va su stderr.
IMPORTANTE: come 'id' usiamo il NOME del device (non l'index numerico).
AVFoundation rinumera silenziosamente i device quando cambia il set di
hardware collegato (es. iPhone in continuita', Multi-Output Device, ecc).
Il nome e' invece stabile; ffmpeg AVFoundation accetta sia ':<index>'
sia ':<name>' come specifica del device input.
"""
try:
proc = subprocess.run(
[ffmpeg, "-hide_banner", "-f", "avfoundation",
@@ -105,7 +112,12 @@ def _list_macos(ffmpeg: str) -> list[dict]:
if not m:
continue
idx, name = m.group(1), m.group(2).strip()
devices.append({"id": idx, "name": name, "is_virtual": _is_virtual(name)})
devices.append({
"id": name, # nome stabile (vedi docstring)
"index": idx, # solo informativo per debug
"name": name,
"is_virtual": _is_virtual(name),
})
return devices