"""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 = ""