pub struct VoiceService {
loader: Arc<dyn Fn() -> Result<Arc<dyn Engine>, String> + Send + Sync>,
engine: Arc<Mutex<Option<Arc<dyn Engine>>>>,
settings: VoiceSettings,
sink: Arc<dyn AudioSink>,
notes: Arc<dyn NoteDispatch>,
seats: Arc<Mutex<HashMap<SessionSlot, Seat>>>,
previews: Arc<Mutex<HashMap<SessionSlot, PreviewSlot>>>,
}Expand description
The per-seat voice service. One render queue per seat, so a second say
waits behind the first, and one engine for the whole process, loaded at
boot and kept for the process’s life; a failed warm is retried by the
first say.
Fields§
§loader: Arc<dyn Fn() -> Result<Arc<dyn Engine>, String> + Send + Sync>§engine: Arc<Mutex<Option<Arc<dyn Engine>>>>§settings: VoiceSettings§sink: Arc<dyn AudioSink>§notes: Arc<dyn NoteDispatch>§seats: Arc<Mutex<HashMap<SessionSlot, Seat>>>§previews: Arc<Mutex<HashMap<SessionSlot, PreviewSlot>>>The previews one seat may have in flight: a held key updates the newest voice instead of queueing one render per press.
Implementations§
Source§impl VoiceService
impl VoiceService
pub fn new( loader: Arc<dyn Fn() -> Result<Arc<dyn Engine>, String> + Send + Sync>, settings: VoiceSettings, sink: Arc<dyn AudioSink>, notes: Arc<dyn NoteDispatch>, ) -> Self
Sourcepub async fn say(
&self,
seat: &SessionSlot,
text: String,
) -> Result<(), SayError>
pub async fn say( &self, seat: &SessionSlot, text: String, ) -> Result<(), SayError>
Queue one utterance for seat. Answers once the first audio is
rendered, so a named engine failure reaches the caller rather than
disappearing into a playback queue.
Sourcepub async fn preview(
&self,
seat: &SessionSlot,
voice: String,
) -> Result<(), SayError>
pub async fn preview( &self, seat: &SessionSlot, voice: String, ) -> Result<(), SayError>
Render one fixed line in voice on seat’s own stream, so a voice is
heard before it is chosen. The seat’s speaker switch is the playback
gate: nobody listening means nowhere to play.
One render loop per seat. While a preview renders, a second press replaces the pending voice instead of queueing another render, so the newest press is the one heard and a held key costs one render.
Sourcefn settle_previews(&self, seat: &SessionSlot, generation: u64) -> Option<String>
fn settle_previews(&self, seat: &SessionSlot, generation: u64) -> Option<String>
End the loop generation owns and hand back the voice a later press
left waiting. A newer loop’s flag and voice are its own, and neither
is touched.
Sourcefn restart_previews(&self, seat: &SessionSlot, voice: String) -> Option<u64>
fn restart_previews(&self, seat: &SessionSlot, voice: String) -> Option<u64>
Claim the seat for a waiting voice. None when a newer loop already
holds it: that loop carries the newest press, so an older voice is the
one to drop.
Sourceasync fn render_previews(&self, seat: &SessionSlot) -> Result<(), SayError>
async fn render_previews(&self, seat: &SessionSlot) -> Result<(), SayError>
Drain the seat’s pending previews, newest last.
Sourcefn listening_queue(
&self,
seat: &SessionSlot,
) -> Result<UnboundedSender<Job>, SayError>
fn listening_queue( &self, seat: &SessionSlot, ) -> Result<UnboundedSender<Job>, SayError>
The queue of a seat that still has a listener. A say reads it again
after a load, because the seat can empty while the engine loads.
Sourcepub fn set_listening(
&self,
seat: &SessionSlot,
client: u64,
on: bool,
explicit: bool,
)
pub fn set_listening( &self, seat: &SessionSlot, client: u64, on: bool, explicit: bool, )
Turn one client’s voice on or off for seat. The session is told on
the first client in, and on the last client out only when the reader
turned it off themselves: a move to another seat pauses the seat
without toggling the agent.
Sourcepub async fn replace_engine(&self, engine: Arc<dyn Engine>)
pub async fn replace_engine(&self, engine: Arc<dyn Engine>)
Swap the loaded engine for one already built, so a model change keeps serving until the new engine is up.
pub fn listeners(&self, seat: &SessionSlot) -> usize
Sourcepub fn release(&self, client: u64) -> Vec<SessionSlot>
pub fn release(&self, client: u64) -> Vec<SessionSlot>
A connection has gone: take it off every seat it was listening to, and answer the seats whose count changed. A socket that dies says no goodbye, so this teardown is what lowers the count.
Sourcepub fn enabled(&self) -> bool
pub fn enabled(&self) -> bool
Whether [tts] enabled is set. A disabled service registers no tool
and refuses every say.
Sourcepub fn occupant_changed(&self, seat: &SessionSlot)
pub fn occupant_changed(&self, seat: &SessionSlot)
The seat’s occupant changed under a listening client: tell the new
session it is heard, because the note fires on the listener set’s
transitions and a /new or /resume leaves that set alone.
Sourcepub(crate) async fn warm(&self) -> Result<(), SayError>
pub(crate) async fn warm(&self) -> Result<(), SayError>
Load the engine ahead of the first say. A failed load leaves the
slot empty, so the first say retries it.
Sourceasync fn engine(&self) -> Result<Arc<dyn Engine>, SayError>
async fn engine(&self) -> Result<Arc<dyn Engine>, SayError>
The engine, loading it on the first caller. The mutex is held across
the load, so a second say waits for it instead of racing it.
Sourcefn spawn_queue(
&self,
seat: &SessionSlot,
live: Arc<AtomicUsize>,
) -> UnboundedSender<Job>
fn spawn_queue( &self, seat: &SessionSlot, live: Arc<AtomicUsize>, ) -> UnboundedSender<Job>
The seat’s render loop. It stops the moment the last listener leaves, so a queued utterance is not rendered into a seat nobody hears.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for VoiceService
impl !UnwindSafe for VoiceService
impl Freeze for VoiceService
impl Send for VoiceService
impl Sync for VoiceService
impl Unpin for VoiceService
impl UnsafeUnpin for VoiceService
Blanket Implementations§
§impl<T> AnySync for T
impl<T> AnySync for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more