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)
|
runner = web.AppRunner(app)
|
||||||
self._loop.run_until_complete(runner.setup())
|
self._loop.run_until_complete(runner.setup())
|
||||||
try:
|
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", HTTPS_PORT, ssl_context=ctx, reuse_address=True).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", HTTP_PORT, reuse_address=True).start()) # solo CA e reindirizzo
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.error = str(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
|
return
|
||||||
self.log(f"SYS: Accesso remoto pronto su https://{self.ip}:{HTTPS_PORT} (CA: http://{self.ip}:{HTTP_PORT}/ca.crt)")
|
self.log(f"SYS: Accesso remoto pronto su https://{self.ip}:{HTTPS_PORT} (CA: http://{self.ip}:{HTTP_PORT}/ca.crt)")
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -271,6 +271,9 @@ def _query() -> dict[str, list[str]]:
|
|||||||
apis = []
|
apis = []
|
||||||
|
|
||||||
preferred = _PREFERRED_APIS.get(platform.system(), ())
|
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]]:
|
def _collect(api_filter, kind) -> list[tuple[int, str]]:
|
||||||
"""(index, name) for named, non-pseudo devices on one side that can
|
"""(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 ""
|
api = apis[dev["hostapi"]].lower() if dev.get("hostapi", -1) < len(apis) else ""
|
||||||
if api_filter not in api:
|
if api_filter not in api:
|
||||||
continue
|
continue
|
||||||
if not _usable(idx, kind):
|
if not fast and not _usable(idx, kind):
|
||||||
continue
|
continue
|
||||||
seen.add(name)
|
seen.add(name)
|
||||||
found.append((idx, name))
|
found.append((idx, name))
|
||||||
@@ -303,7 +306,7 @@ def _query() -> dict[str, list[str]]:
|
|||||||
if not found:
|
if not found:
|
||||||
continue
|
continue
|
||||||
# One probe per API per direction, cached, on this thread.
|
# 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
|
continue
|
||||||
_chosen_api[kind] = api_filter
|
_chosen_api[kind] = api_filter
|
||||||
out[kind] = [_display_name(n, devices) for _i, n in found]
|
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")
|
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:
|
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()
|
ensure_identity_file()
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
try:
|
try:
|
||||||
@@ -57,6 +80,11 @@ def main() -> None:
|
|||||||
ui.on_wake_toggle = assistant.on_wake_toggle
|
ui.on_wake_toggle = assistant.on_wake_toggle
|
||||||
ui.on_wake_manual = assistant.on_wake_manual
|
ui.on_wake_manual = assistant.on_wake_manual
|
||||||
ui.wake_get_state = assistant.wake_get_state
|
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 avatar.plugins import registry
|
||||||
from core import confirm
|
from core import confirm
|
||||||
confirm.bind(ui.show_confirm, ui.hide_confirm, ui.write_log)
|
confirm.bind(ui.show_confirm, ui.hide_confirm, ui.write_log)
|
||||||
|
|||||||
@@ -4691,8 +4691,9 @@ class MainWindow(QMainWindow):
|
|||||||
'<plist version="1.0"><dict>\n'
|
'<plist version="1.0"><dict>\n'
|
||||||
' <key>Label</key><string>it.luza.assistente</string>\n'
|
' <key>Label</key><string>it.luza.assistente</string>\n'
|
||||||
' <key>ProgramArguments</key><array>\n'
|
' <key>ProgramArguments</key><array>\n'
|
||||||
f' <string>{sys.executable}</string>\n'
|
+ (' <string>/usr/bin/open</string>\n <string>-a</string>\n <string>/Applications/LuZa.app</string>\n'
|
||||||
f' <string>{script}</string>\n'
|
if Path("/Applications/LuZa.app").exists() else
|
||||||
|
f' <string>{sys.executable}</string>\n <string>{script}</string>\n') +
|
||||||
' </array>\n'
|
' </array>\n'
|
||||||
' <key>RunAtLoad</key><true/>\n'
|
' <key>RunAtLoad</key><true/>\n'
|
||||||
'</dict></plist>\n'
|
'</dict></plist>\n'
|
||||||
|
|||||||
Reference in new issue
Block a user