1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
"""detect() — the BackendStatus report for the hub's backend menu."""
from typing import List, Tuple
from backends import (BackendStatus, ServerSpec, format_launch_hint,
probe, servers)
from converter import config
from . import build as _build
from . import models as _models
def detect() -> BackendStatus:
"""Detect how far audio.cpp is set up, plus the command to start it."""
checkout = _build.find_local_checkout()
details: List[str] = []
launch = ""
if checkout is None:
# No local checkout: only a remote server can make this usable.
remote = _detect_remote()
return BackendStatus("audiocpp", "audio.cpp", installed=False,
configured=False, running=remote[0],
remote=remote[0], remote_urls=remote[1],
details=["not cloned — run setup to clone "
"./app/audio.cpp"])
details.append(f"checkout: {checkout}")
binary = _build.find_audiocpp_server_bin(checkout)
built = binary is not None
if built:
details.append(f"built: {binary}")
else:
details.append("not built — run setup to build audiocpp_server")
server_json = checkout / "server.json"
configured = server_json.exists()
specs: List[ServerSpec] = []
missing = _models.missing_model_entries(server_json) if configured else []
if configured:
details.append(f"config: {server_json}")
if missing:
# The config references model files that are not on disk; a
# conversion would fail at model-load time, so say so now.
details.extend(_models.model_install_hints(checkout, missing))
if built:
# Spawned from the checkout: audiocpp_server discovers
# model_specs/<family>.json relative to its working directory.
specs = [ServerSpec(
"audiocpp", config.AUDIOCPP_API_URL,
[str(binary), "--config", str(server_json)],
cwd=checkout, identity=probe.IDENTITY_AUDIOCPP)]
else:
launch = (f"cd {checkout} && ./build/<platform>-<backend>-release"
f"/bin/audiocpp_server --config {server_json}")
else:
details.append("no server.json — run setup to configure models")
if specs:
launch = format_launch_hint(specs)
managed = servers.manages(specs)
remote_running, remote_urls = _detect_remote(managed)
# A more specific "part-way set up" label than unavailable/installed:
# cloned but never built, or built but not configured.
partial = ""
if not built:
partial = "downloaded (not built)"
elif not configured:
partial = "built (not configured)"
return BackendStatus("audiocpp", "audio.cpp", installed=built,
configured=configured,
running=managed or remote_running,
details=details, launch_hint=launch,
servers=specs, managed=managed,
remote=remote_running, remote_urls=remote_urls,
models_missing=bool(missing), partial=partial)
def _detect_remote(managed: bool = False) -> Tuple[bool, dict]:
"""Detect an externally-run audiocpp_server at the remote URL.
Returns ``(running, {spec_name: url})``. The remote URL is probed only
when configured (non-empty); a server answering there is ignored when it
is this tool's own managed server (remote URL == local URL and our pid is
still alive) — that instance is already reported as "[local]".
"""
url = (config.AUDIOCPP_REMOTE_URL or "").strip()
if not url:
return False, {}
if managed and probe.same_endpoint(url, config.AUDIOCPP_API_URL):
return False, {}
if probe.identify_server(url) == probe.IDENTITY_AUDIOCPP:
return True, {"audiocpp": url}
return False, {}
|