events: start moving towards a more control-handle based task architecture
This commit is contained in:
+22
-22
@@ -13,7 +13,7 @@ use futures::{StreamExt, future::FutureExt};
|
||||
use ratatui::prelude::*;
|
||||
use tui_skeleton::{AnimationMode, SkeletonText};
|
||||
|
||||
use crate::{events::AudioRecordRequest, prediction::{BandcampResult, PossibleResponse}, scene::{ConversationEntry, Scene, StageActions, StageDirection}, tts::start_tts};
|
||||
use crate::{prediction::{BandcampResult, PossibleResponse}, scene::{ConversationEntry, Scene, StageActions, StageDirection}, transcription::{AudioInputControl, TranscriptionControl, start_audio_input}, tts::{TtsControl, start_tts}};
|
||||
|
||||
mod scene;
|
||||
mod events;
|
||||
@@ -79,9 +79,10 @@ struct App {
|
||||
recording_audio: bool,
|
||||
focus_state: FocusState,
|
||||
|
||||
audio_control_sink: watch::Sender<AudioRecordRequest>,
|
||||
transcription: TranscriptionControl,
|
||||
prediction_request_sink: watch::Sender<StageActions>,
|
||||
tts_request_sink: mpsc::Sender<String>,
|
||||
audio: AudioInputControl,
|
||||
tts: TtsControl,
|
||||
sys_message_sink: mpsc::Sender<String>
|
||||
}
|
||||
|
||||
@@ -110,7 +111,7 @@ impl From<bandcamp::Error> for BandcampError {
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn new(prediction_request_sink: watch::Sender<StageActions>, audio_control_sink: watch::Sender<AudioRecordRequest>, tts_request_sink: mpsc::Sender<String>, sys_message_sink: mpsc::Sender<String>, initial_direction: StageDirection) -> Self {
|
||||
fn new(prediction_request_sink: watch::Sender<StageActions>, audio: AudioInputControl, transcription: TranscriptionControl, tts: TtsControl, sys_message_sink: mpsc::Sender<String>, initial_direction: StageDirection) -> Self {
|
||||
Self {
|
||||
scene: Default::default(),
|
||||
direction: initial_direction,
|
||||
@@ -123,10 +124,11 @@ impl App {
|
||||
prediction_request_sink,
|
||||
is_requesting: false,
|
||||
audio_level: -60.,
|
||||
audio,
|
||||
recording_audio: false,
|
||||
audio_control_sink,
|
||||
transcription,
|
||||
focus_state: FocusState::UserInput,
|
||||
tts_request_sink,
|
||||
tts,
|
||||
sys_message_sink
|
||||
}
|
||||
}
|
||||
@@ -392,7 +394,7 @@ impl App {
|
||||
self.next_actions.push(ConversationEntry::StageDirection(direction.clone()));
|
||||
}
|
||||
self.next_actions.push(ConversationEntry::Eva(selected.text.clone()));
|
||||
self.speak(selected.text.clone()).await;
|
||||
self.tts.speak(selected.text.clone()).await;
|
||||
self.regenerate_responses();
|
||||
}
|
||||
|
||||
@@ -476,7 +478,7 @@ impl App {
|
||||
KeyCode::Enter => {
|
||||
let row_num = self.conversation_state.selected().unwrap();
|
||||
if let ConversationEntry::Eva(text) = &self.scene.conversation()[self.scene.conversation().len() - 1 - row_num] {
|
||||
self.speak(text.clone()).await;
|
||||
self.tts.speak(text.clone()).await;
|
||||
self.focus_state = FocusState::UserInput;
|
||||
self.conversation_state.select(None);
|
||||
}
|
||||
@@ -494,11 +496,11 @@ impl App {
|
||||
KeyCode::Char('x') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
if self.recording_audio {
|
||||
self.recording_audio = false;
|
||||
self.audio_control_sink.send_replace(AudioRecordRequest::Finish);
|
||||
self.transcription.stop();
|
||||
self.is_requesting = true;
|
||||
} else {
|
||||
self.recording_audio = true;
|
||||
self.audio_control_sink.send_replace(AudioRecordRequest::Start);
|
||||
self.transcription.start();
|
||||
}
|
||||
},
|
||||
KeyCode::Down => self.reply_state.select_next(),
|
||||
@@ -536,10 +538,6 @@ impl App {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn speak(&mut self, text: String) {
|
||||
self.tts_request_sink.send(text).await.unwrap();
|
||||
}
|
||||
|
||||
fn regenerate_responses(&mut self) {
|
||||
let actions = StageActions {
|
||||
direction: self.direction.clone(),
|
||||
@@ -610,11 +608,13 @@ async fn main() {
|
||||
SaveData::default()
|
||||
};
|
||||
|
||||
let tts_request_sender = start_tts().await;
|
||||
let (prediction_request_in, mut prediction_out) = prediction::start_prediction(sys_message_src, saved_session.messages).await;
|
||||
let (mut audio_state_receiver, audio_control_in, mut transcription_out) = transcription::start_transcription(sys_message_sink.clone()).await;
|
||||
let (audio_ctrl, mic_stream) = start_audio_input(&sys_message_sink).await;
|
||||
|
||||
let mut app = App::new(prediction_request_in, audio_control_in, tts_request_sender, sys_message_sink, saved_session.direction);
|
||||
let tts_ctrl = start_tts().await;
|
||||
let (prediction_request_in, mut prediction_out) = prediction::start_prediction(sys_message_src, saved_session.messages).await;
|
||||
let transcription_ctrl = transcription::start_transcription(mic_stream).await;
|
||||
|
||||
let mut app = App::new(prediction_request_in, audio_ctrl, transcription_ctrl, tts_ctrl, sys_message_sink, saved_session.direction);
|
||||
|
||||
let mut events = EventStream::new();
|
||||
let mut last_tick = Instant::now();
|
||||
@@ -637,11 +637,11 @@ async fn main() {
|
||||
app.reply_state.select_first();
|
||||
app.is_requesting = false;
|
||||
},
|
||||
_ = audio_state_receiver.changed() => {
|
||||
app.audio_level = *audio_state_receiver.borrow();
|
||||
next_volume = app.audio.next() => {
|
||||
app.audio_level = next_volume
|
||||
},
|
||||
maybe_transcription = transcription_out.recv() => {
|
||||
app.next_actions.push(ConversationEntry::User(maybe_transcription.unwrap()));
|
||||
transcription_result = app.transcription.next() => {
|
||||
app.next_actions.push(ConversationEntry::User(transcription_result));
|
||||
app.regenerate_responses();
|
||||
}
|
||||
maybe_event = event => {
|
||||
|
||||
Reference in New Issue
Block a user