207 lines
6.5 KiB
Rust
207 lines
6.5 KiB
Rust
use super::*;
|
|
use std::time::{Duration,Instant};
|
|
|
|
pub struct TheApplication{
|
|
pub(super) plugins:Vec<PluginType>,
|
|
pub(super) state:ApplicationState,
|
|
}
|
|
|
|
|
|
pub struct ApplicationState{
|
|
// This is separate so that I can use the address
|
|
// of a PluginType to find its index inside of plugins.
|
|
pub(super) plugin_ids:Vec<PluginId>,
|
|
pub(super) id_map:HashMap<RString,PluginModAndIndices>,
|
|
pub(super) delayed_commands:VecDeque<DelayedCommand>,
|
|
pub(super) responses:VecDeque<DelayedResponse>,
|
|
pub(super) sender:RSender<AsyncCommand>,
|
|
pub(super) receiver:RReceiver<AsyncCommand>,
|
|
pub(super) last_run_at:Instant,
|
|
}
|
|
|
|
|
|
|
|
fn print_response(
|
|
plugin_id:&PluginId,
|
|
response:&str,
|
|
){
|
|
println!(
|
|
"reponse:\n{}\nfrom:\n {:?}\n\n",
|
|
response.left_pad(4),
|
|
plugin_id,
|
|
);
|
|
}
|
|
|
|
impl TheApplication{
|
|
/// Runs a command,
|
|
pub fn run_command(&mut self,which_plugin:WhichPlugin,command:RStr<'_>)->Result<(),AppError>{
|
|
let list=self.state.expand_which_plugin(which_plugin)?;
|
|
for index in list {
|
|
let state=Application_TO::from_ptr(&mut self.state,TU_Opaque);
|
|
let plugin=&mut self.plugins[index as usize];
|
|
println!("command:\n{}", command.left_pad(4));
|
|
let resp=plugin.json_command(command,state).into_result()?;
|
|
self.state.register_command_run();
|
|
print_response(&self.state.plugin_ids[index],&resp);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn tick(&mut self) -> Result<(), AppError>{
|
|
if let Ok(ac)=self.state.receiver.try_recv() {
|
|
self.state.send_command_to_plugin(&ac.from,ac.which_plugin,ac.command).into_result()?;
|
|
}
|
|
|
|
if let Some(dc)=self.state.delayed_commands.pop_front() {
|
|
self.run_command_(&dc.from,dc.plugin_index,&dc.command)?;
|
|
}
|
|
|
|
let mut responses=mem::replace(&mut self.state.responses, VecDeque::new());
|
|
for DelayedResponse{to,from,response} in responses.drain(..) {
|
|
let response=PluginResponse::owned_response(from,response);
|
|
let state=Application_TO::from_ptr(&mut self.state,TU_Opaque);
|
|
if let RSome(res)=self.plugins[to]
|
|
.handle_response(response, state)
|
|
.into_result()?
|
|
{
|
|
print_response(&res.plugin_id, &res.response);
|
|
}
|
|
}
|
|
self.state.responses=responses;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn is_finished(&self)->bool{
|
|
self.state.last_run_at.elapsed()>=Duration::from_secs(5)
|
|
}
|
|
|
|
fn run_command_(&mut self,from:&PluginId, to:usize, command:&str) -> Result<(), AppError> {
|
|
let state=Application_TO::from_ptr(&mut self.state,TU_Opaque);
|
|
let response=self.plugins[to].json_command(command.into(),state).into_result()?;
|
|
let to=self.state.index_for_plugin_id(from)?;
|
|
|
|
self.state.register_command_run();
|
|
|
|
let response = DelayedResponse {
|
|
from:self.state.plugin_ids[to].clone(),
|
|
to,
|
|
response,
|
|
};
|
|
|
|
self.state.responses.push_back(response);
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
|
|
impl ApplicationState{
|
|
pub(crate) fn new() -> Self {
|
|
let (sender,receiver)=crossbeam_channel::unbounded();
|
|
|
|
Self{
|
|
plugin_ids:Vec::new(),
|
|
id_map:HashMap::new(),
|
|
delayed_commands:VecDeque::new(),
|
|
responses:VecDeque::new(),
|
|
sender,
|
|
receiver,
|
|
last_run_at:Instant::now(),
|
|
}
|
|
}
|
|
|
|
fn register_command_run(&mut self) {
|
|
self.last_run_at=Instant::now();
|
|
}
|
|
|
|
fn index_for_plugin_id(&self, id:&PluginId) -> Result<usize,AppError> {
|
|
self.id_map.get(&*id.named)
|
|
.and_then(|x| x.indices.get(id.instance as usize).cloned())
|
|
.ok_or_else(|| AppError::InvalidPlugin(WhichPlugin::Id(id.clone())))
|
|
}
|
|
|
|
fn expand_which_plugin(&self, which_plugin:WhichPlugin) -> Result<PluginIndices, AppError> {
|
|
match which_plugin {
|
|
WhichPlugin::Id(id)=>{
|
|
self.index_for_plugin_id(&id)
|
|
.map(|i| PluginIndices::from([i]) )
|
|
},
|
|
WhichPlugin::First{ref named}
|
|
| WhichPlugin::Last{ref named}
|
|
| WhichPlugin::Every{ref named} => {
|
|
self.id_map.get(&**named).and_then(|x| {
|
|
let list=&x.indices;
|
|
match which_plugin {
|
|
WhichPlugin::First{..} => {
|
|
PluginIndices::from([*list.first()?])
|
|
},
|
|
WhichPlugin::Last{..} => {
|
|
PluginIndices::from([*list.last()?])
|
|
},
|
|
WhichPlugin::Every{..} => {
|
|
PluginIndices::from(&**list)
|
|
},
|
|
_=>unreachable!(),
|
|
}.piped(Some)
|
|
})
|
|
.ok_or_else(|| AppError::InvalidPlugin(which_plugin.clone()))
|
|
},
|
|
WhichPlugin::Many(list) => {
|
|
let mut plugin_indices=PluginIndices::new();
|
|
for elem in list {
|
|
plugin_indices.extend(self.expand_which_plugin(elem)?);
|
|
}
|
|
Ok(plugin_indices)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl Application for ApplicationState {
|
|
fn send_command_to_plugin(
|
|
&mut self,
|
|
from:&PluginId,
|
|
which_plugin:WhichPlugin,
|
|
command:RString,
|
|
) -> RResult<(),AppError> {
|
|
self.expand_which_plugin(which_plugin).map(|plugin_indices|{
|
|
let command=Arc::new(command);
|
|
for plugin_index in plugin_indices {
|
|
let from=from.clone();
|
|
self.delayed_commands.push_back(DelayedCommand {
|
|
from,
|
|
plugin_index,
|
|
command:command.clone(),
|
|
});
|
|
}
|
|
}).into()
|
|
}
|
|
|
|
fn get_plugin_id(&self, which_plugin:WhichPlugin) -> RResult<RVec<PluginId>, AppError> {
|
|
self.expand_which_plugin(which_plugin)
|
|
.map(|list|{
|
|
list.into_iter()
|
|
.map(|i| self.plugin_ids[i].clone() )
|
|
.collect::<RVec<PluginId>>()
|
|
})
|
|
.into()
|
|
}
|
|
|
|
fn sender(&self) -> RSender<AsyncCommand> {
|
|
self.sender.clone()
|
|
}
|
|
|
|
fn loaded_plugins(&self) -> RVec<PluginId> {
|
|
self.plugin_ids.clone().into()
|
|
}
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|