Newer
Older
voice / src / voice_tts / session / state.py
"""Per-session state: buffers, queues, stop control, voice/emotion settings."""

import asyncio
from dataclasses import dataclass, field
from pathlib import Path


@dataclass
class VoiceProfile:
    """Reference audio paths per emotion for a single speaker."""

    default_ref: Path | None = None
    emotion_refs: dict[str, Path] = field(default_factory=dict)

    def ref_for(self, emotion: str) -> Path | None:
        return self.emotion_refs.get(emotion) or self.default_ref


@dataclass
class SessionState:
    """Mutable state for one WebSocket connection."""

    session_id: str
    language: str = "ru"
    speed: float = 1.0
    emotion: str = "neutral"
    voice: VoiceProfile = field(default_factory=VoiceProfile)

    # Text buffer
    text_buffer: str = ""

    # Stop / interrupt control
    stop_event: asyncio.Event = field(default_factory=asyncio.Event)

    # Audio output queue (filled by TTS worker, drained by WebSocket sender)
    audio_queue: asyncio.Queue[bytes] = field(default_factory=asyncio.Queue)

    # Sequence counter for outgoing messages
    out_seq: int = 0
    segment_seq: int = 0

    def next_out_seq(self) -> int:
        self.out_seq += 1
        return self.out_seq

    def next_segment_seq(self) -> int:
        self.segment_seq += 1
        return self.segment_seq

    def reset_stop(self) -> None:
        self.stop_event.clear()

    def stop(self) -> None:
        self.stop_event.set()

    def is_stopped(self) -> bool:
        return self.stop_event.is_set()

    def clear_buffer(self) -> None:
        self.text_buffer = ""