1pub mod audio;
8pub mod code;
9pub mod schedule;
10pub mod text;
11pub mod visual;
12
13pub use audio::{AudioAdapter, AudioFormat};
14pub use code::{CodeAdapter, CodeLang};
15pub use schedule::{schedule, Hap};
16pub use text::{TextAdapter, TextStyle};
17pub use visual::VisualAdapter;
18
19use refrain_core::Refrain;
20use thiserror::Error;
21
22#[derive(Debug, Error)]
23pub enum AdapterErr {
24 #[error("adapter not implemented yet: {0}")]
25 NotImplemented(String),
26 #[error("encoding error: {0}")]
27 Encoding(String),
28}
29
30#[derive(Debug, Clone, Default)]
31pub struct AdapterCaps {
32 pub realtime: bool,
33 pub differentiable: bool,
34}
35
36#[derive(Debug, Clone, Default)]
37pub struct EmitCtx {
38 pub sample_rate: Option<u32>,
39 pub frame_count: Option<u32>,
40}
41
42pub struct ExtractedRefrain<'a> {
43 pub refrain: &'a Refrain,
44}
45
46pub trait RefrainAdapter: Send + Sync {
47 fn name(&self) -> &str;
48 fn emit(&self, refrain: &ExtractedRefrain, ctx: &EmitCtx) -> Result<Vec<u8>, AdapterErr>;
49 fn capabilities(&self) -> AdapterCaps;
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 struct DummyAdapter;
57 impl RefrainAdapter for DummyAdapter {
58 fn name(&self) -> &str {
59 "dummy"
60 }
61 fn emit(&self, _r: &ExtractedRefrain, _ctx: &EmitCtx) -> Result<Vec<u8>, AdapterErr> {
62 Ok(vec![])
63 }
64 fn capabilities(&self) -> AdapterCaps {
65 AdapterCaps::default()
66 }
67 }
68
69 #[test]
70 fn dummy_adapter_emits_empty() {
71 let r = Refrain::new("dummy-host");
72 let ex = ExtractedRefrain { refrain: &r };
73 let bytes = DummyAdapter.emit(&ex, &EmitCtx::default()).unwrap();
74 assert!(bytes.is_empty());
75 assert_eq!(DummyAdapter.name(), "dummy");
76 }
77}