refactor: fix application → infrastructure import violations

Move HBP constants to domain, abstract TTS behind VoiceProvider port.
pull/4/head
Rodrigo Pérez 6 months ago
parent 93b0debf83
commit bb771a744e

@ -39,8 +39,7 @@ from dmr_utils3 import bptc
from dmr_utils3 import decode
from dmr_utils3.const import LC_OPT
from ..domain import int_id, bytes_3, bytes_4
from ..infrastructure.hbp_constants import HBPF_DATA_SYNC, HBPF_SLT_VHEAD, HBPF_SLT_VTERM, STREAM_TO
from ..domain import int_id, bytes_3, bytes_4, HBPF_DATA_SYNC, HBPF_SLT_VHEAD, HBPF_SLT_VTERM, STREAM_TO
from .ports import BridgeRouter
logger = logging.getLogger(__name__)

@ -30,8 +30,7 @@ import re
import time
from typing import Any, Callable
from ..domain import bytes_3, int_id
from ..infrastructure.hbp_constants import HBPF_SLT_VTERM
from ..domain import bytes_3, int_id, HBPF_SLT_VTERM
logger = logging.getLogger(__name__)

@ -30,8 +30,7 @@ from random import randint
from time import sleep, time
from typing import Any
from ..domain import int_id, bytes_4
from ..infrastructure.hbp_constants import HBPF_DATA_SYNC, HBPF_SLT_VTERM
from ..domain import int_id, bytes_4, HBPF_DATA_SYNC, HBPF_SLT_VTERM
logger = logging.getLogger(__name__)

@ -139,7 +139,7 @@ class VoiceProvider(ABC):
...
@abstractmethod
def ensure_tts_ambe(self, text: str, lang: str, out_path: str, config: dict[str, Any]) -> str | None:
def ensure_tts_ambe(self, config: dict[str, Any], item: dict[str, Any], audio_path: str) -> str | None:
"""TTS to AMBE file; return path or None. Legacy tts_engine.ensure_tts_ambe."""
...

@ -32,9 +32,7 @@ import time
from datetime import datetime
from typing import Any, Callable
from ..domain import bytes_3
from ..infrastructure.hbp_constants import HBPF_SLT_VHEAD, HBPF_SLT_VTERM
from ..infrastructure.voice.tts_engine import ensure_tts_ambe as tts_ensure_tts_ambe
from ..domain import bytes_3, HBPF_SLT_VHEAD, HBPF_SLT_VTERM
from .ports import VoiceProvider
logger = logging.getLogger(__name__)
@ -448,12 +446,12 @@ class VoiceUseCases:
self._tts_running[tts_idx] = True
logger.info("(%s) Starting TTS conversion in background thread for %s", label, _file)
if self._defer_to_thread:
d = self._defer_to_thread(tts_ensure_tts_ambe, self._config, item, self._audio_path)
d = self._defer_to_thread(self._voice.ensure_tts_ambe, self._config, item, self._audio_path)
d.addCallback(self._tts_conversion_done, tts_idx, _file, _tg, _lang, mode, label)
d.addErrback(self._tts_conversion_error, tts_idx, label)
else:
try:
ambe_path = tts_ensure_tts_ambe(self._config, item, self._audio_path)
ambe_path = self._voice.ensure_tts_ambe(self._config, item, self._audio_path)
self._tts_conversion_done(ambe_path, tts_idx, _file, _tg, _lang, mode, label)
except Exception as e:
self._tts_conversion_error(e, tts_idx, label)

@ -25,6 +25,11 @@ from .entities import BridgeEntry, StreamState, SystemConfig
from .value_objects import DmrId, TgId, Slot, CallType, bytes_3, bytes_4, int_id, ID_MIN, ID_MAX, PEER_MAX
from .errors import DomainError, ConfigError, ACLError
from .result import Result, Success, Fail, is_fail, is_ok, unwrap_or
from .hbp_protocol import (
HBPF_VOICE, HBPF_VOICE_SYNC, HBPF_DATA_SYNC,
HBPF_SLT_VHEAD, HBPF_SLT_VTERM,
VER, PROTO_VER, STREAM_TO,
)
__all__ = [
"BridgeEntry",
@ -49,4 +54,12 @@ __all__ = [
"is_fail",
"is_ok",
"unwrap_or",
"HBPF_VOICE",
"HBPF_VOICE_SYNC",
"HBPF_DATA_SYNC",
"HBPF_SLT_VHEAD",
"HBPF_SLT_VTERM",
"VER",
"PROTO_VER",
"STREAM_TO",
]

@ -0,0 +1,43 @@
# ADN DMR Peer Server - HBP protocol constants (domain)
# Copyright (C) 2026 Rodrigo Pérez, CE5RPY <ce5rpy@qmd.cl>
#
# Derived from ADN DMR Server / FreeDMR / HBlink. Original license:
###############################################################################
# Copyright (C) 2020 Simon Adlem, G7RZU <g7rzu@gb7fr.org.uk>
# Copyright (C) 2016-2019 Cortney T. Buffington, N0MJS <n0mjs@me.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
###############################################################################
"""HBP frame types and protocol-level constants used across layers.
These are pure protocol vocabulary (no Twisted, no I/O dependencies) and
belong in the domain layer so application use cases can reference them
without importing infrastructure.
"""
# Frame types (bits)
HBPF_VOICE = 0x0
HBPF_VOICE_SYNC = 0x1
HBPF_DATA_SYNC = 0x2
HBPF_SLT_VHEAD = 0x1
HBPF_SLT_VTERM = 0x2
# Protocol version
VER = 5
PROTO_VER = 5
# Stream timeout (seconds) for contention (legacy const.py)
STREAM_TO = 0.36

@ -21,7 +21,23 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
###############################################################################
"""Homebrew protocol opcodes and frame types (legacy const.py)."""
"""Homebrew protocol opcodes and frame types (legacy const.py).
Frame types and protocol-level constants live in domain.hbp_protocol (the
canonical source); they are re-exported here so existing infrastructure
imports keep working.
"""
from ..domain.hbp_protocol import ( # noqa: F401 — re-export
HBPF_VOICE,
HBPF_VOICE_SYNC,
HBPF_DATA_SYNC,
HBPF_SLT_VHEAD,
HBPF_SLT_VTERM,
VER,
PROTO_VER,
STREAM_TO,
)
# DMR
DMR = b"DMR"
@ -58,16 +74,3 @@ BCVE = b"BCVE"
# Proxy
PRIN = b"PRIN"
PRBL = b"PRBL"
# Frame types (bits)
HBPF_VOICE = 0x0
HBPF_VOICE_SYNC = 0x1
HBPF_DATA_SYNC = 0x2
HBPF_SLT_VHEAD = 0x1
HBPF_SLT_VTERM = 0x2
VER = 5
PROTO_VER = 5
# Legacy const.py: stream timeout (seconds) for contention
STREAM_TO = 0.36

@ -36,6 +36,7 @@ from bitarray import bitarray
from ...application.ports import VoiceProvider
from .pkt_gen import pkt_gen as _pkt_gen
from .tts_engine import ensure_tts_ambe as _tts_ensure_tts_ambe
from .voice_map import VOICE_MAP
logger = logging.getLogger(__name__)
@ -178,11 +179,9 @@ class DefaultVoiceProvider(VoiceProvider):
"""Generate HBP voice packets for phrase. Legacy mk_voice.pkt_gen."""
return _pkt_gen(rf_src, dst_id, peer, slot, phrase)
def ensure_tts_ambe(self, text: str, lang: str, out_path: str, config: dict[str, Any]) -> str | None:
"""Return out_path if .ambe file exists (cached). Full TTS conversion is in tts_engine.ensure_tts_ambe."""
if out_path and os.path.isfile(out_path):
return out_path
return None
def ensure_tts_ambe(self, config: dict[str, Any], item: dict[str, Any], audio_path: str) -> str | None:
"""Delegate to tts_engine.ensure_tts_ambe (full TTS pipeline)."""
return _tts_ensure_tts_ambe(config, item, audio_path)
class StubVoiceProvider(VoiceProvider):
@ -196,7 +195,7 @@ class StubVoiceProvider(VoiceProvider):
) -> Iterator[bytes]:
return iter([])
def ensure_tts_ambe(self, text: str, lang: str, out_path: str, config: dict[str, Any]) -> str | None:
def ensure_tts_ambe(self, config: dict[str, Any], item: dict[str, Any], audio_path: str) -> str | None:
return None
def read_single_file(self, audio_path: str, lang: str, file_number: str) -> list:

Loading…
Cancel
Save

Powered by TurnKey Linux.