Istanza unica (lock), avvio automatico tramite LuZa.app, elenco dispositivi audio immediato su macOS, riuso delle porte del server remoto
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
094807ffe8
commit
bea863e011
4 files changed
+39
-7
No files matched your search
+3
-3
@@ -175,11 +175,11 @@ class RemoteServer:
|
||||
runner = web.AppRunner(app)
|
||||
self._loop.run_until_complete(runner.setup())
|
||||
try:
|
||||
self._loop.run_until_complete(web.TCPSite(runner, "0.0.0.0", HTTPS_PORT, ssl_context=ctx).start())
|
||||
self._loop.run_until_complete(web.TCPSite(runner, "0.0.0.0", HTTP_PORT).start()) # solo CA e reindirizzo
|
||||
self._loop.run_until_complete(web.TCPSite(runner, "0.0.0.0", HTTPS_PORT, ssl_context=ctx, reuse_address=True).start())
|
||||
self._loop.run_until_complete(web.TCPSite(runner, "0.0.0.0", HTTP_PORT, reuse_address=True).start()) # solo CA e reindirizzo
|
||||
except Exception as err:
|
||||
self.error = str(err)
|
||||
self.log(f"ERR: Accesso remoto — porta occupata? {err}")
|
||||
self.log(f"ERR: Accesso remoto non avviato: porta {HTTPS_PORT} occupata (c'è un'altra LuZa aperta?). {err}")
|
||||
return
|
||||
self.log(f"SYS: Accesso remoto pronto su https://{self.ip}:{HTTPS_PORT} (CA: http://{self.ip}:{HTTP_PORT}/ca.crt)")
|
||||
try:
|
||||
|
||||
@@ -271,6 +271,9 @@ def _query() -> dict[str, list[str]]:
|
||||
apis = []
|
||||
|
||||
preferred = _PREFERRED_APIS.get(platform.system(), ())
|
||||
# Su macOS Core Audio non mente: aprire un flusso di prova su ogni dispositivo (Bluetooth, AirPlay, schermi)
|
||||
# costa secondi ciascuno e blocca l'interfaccia. Le prove servono solo per le API fasulle di Windows/Linux.
|
||||
fast = platform.system() == "Darwin"
|
||||
|
||||
def _collect(api_filter, kind) -> list[tuple[int, str]]:
|
||||
"""(index, name) for named, non-pseudo devices on one side that can
|
||||
@@ -287,7 +290,7 @@ def _query() -> dict[str, list[str]]:
|
||||
api = apis[dev["hostapi"]].lower() if dev.get("hostapi", -1) < len(apis) else ""
|
||||
if api_filter not in api:
|
||||
continue
|
||||
if not _usable(idx, kind):
|
||||
if not fast and not _usable(idx, kind):
|
||||
continue
|
||||
seen.add(name)
|
||||
found.append((idx, name))
|
||||
@@ -303,7 +306,7 @@ def _query() -> dict[str, list[str]]:
|
||||
if not found:
|
||||
continue
|
||||
# One probe per API per direction, cached, on this thread.
|
||||
if not _transport_works(found[0][0], kind, (api_filter, kind)):
|
||||
if not fast and not _transport_works(found[0][0], kind, (api_filter, kind)):
|
||||
continue
|
||||
_chosen_api[kind] = api_filter
|
||||
out[kind] = [_display_name(n, devices) for _i, n in found]
|
||||
|
||||
@@ -33,7 +33,30 @@ def ensure_identity_file() -> None:
|
||||
f.write_text(json.dumps(data, indent=4, ensure_ascii=False), encoding="utf-8")
|
||||
|
||||
|
||||
def _single_instance() -> bool:
|
||||
"""Blocco esclusivo su data/luza.lock: una seconda LuZa (avvio automatico + avvio manuale) esce subito."""
|
||||
import fcntl
|
||||
from avatar.settings import DATA_DIR
|
||||
DATA_DIR.mkdir(parents=True, exist_ok=True)
|
||||
global _lock_file
|
||||
_lock_file = open(DATA_DIR / "luza.lock", "w")
|
||||
try:
|
||||
fcntl.flock(_lock_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
_lock_file.write(str(__import__("os").getpid())); _lock_file.flush()
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if "--smoke" not in sys.argv and not _single_instance():
|
||||
print("LuZa è già in esecuzione: questa seconda istanza si chiude.")
|
||||
try:
|
||||
import subprocess
|
||||
subprocess.run(["osascript", "-e", 'display notification "LuZa è già aperta." with title "LuZa"'], timeout=5)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
ensure_identity_file()
|
||||
settings = Settings()
|
||||
try:
|
||||
@@ -57,6 +80,11 @@ def main() -> None:
|
||||
ui.on_wake_toggle = assistant.on_wake_toggle
|
||||
ui.on_wake_manual = assistant.on_wake_manual
|
||||
ui.wake_get_state = assistant.wake_get_state
|
||||
try:
|
||||
from core import audio_devices
|
||||
audio_devices.prefetch() # elenco dispositivi audio pronto prima che si apra la finestra
|
||||
except Exception:
|
||||
pass
|
||||
from avatar.plugins import registry
|
||||
from core import confirm
|
||||
confirm.bind(ui.show_confirm, ui.hide_confirm, ui.write_log)
|
||||
|
||||
@@ -4691,8 +4691,9 @@ class MainWindow(QMainWindow):
|
||||
'<plist version="1.0"><dict>\n'
|
||||
' <key>Label</key><string>it.luza.assistente</string>\n'
|
||||
' <key>ProgramArguments</key><array>\n'
|
||||
f' <string>{sys.executable}</string>\n'
|
||||
f' <string>{script}</string>\n'
|
||||
+ (' <string>/usr/bin/open</string>\n <string>-a</string>\n <string>/Applications/LuZa.app</string>\n'
|
||||
if Path("/Applications/LuZa.app").exists() else
|
||||
f' <string>{sys.executable}</string>\n <string>{script}</string>\n') +
|
||||
' </array>\n'
|
||||
' <key>RunAtLoad</key><true/>\n'
|
||||
'</dict></plist>\n'
|
||||
|
||||
Reference in new issue
Block a user