Skip to main content

ass_editor/core/fluent/
karaoke.rs

1//! Fluent API for ASS karaoke operations and the karaoke generator builder.
2
3use super::karaoke_builders::{KaraokeAdjuster, KaraokeApplicator, KaraokeSplitter};
4use crate::commands::{EditorCommand, GenerateKaraokeCommand, KaraokeType};
5use crate::core::{EditorDocument, Position, Range, Result};
6
7#[cfg(not(feature = "std"))]
8use alloc::vec::Vec;
9
10/// Fluent API for ASS karaoke operations
11pub struct KaraokeOps<'a> {
12    document: &'a mut EditorDocument,
13    range: Option<Range>,
14}
15
16impl<'a> KaraokeOps<'a> {
17    /// Create new karaoke operations
18    pub(super) fn new(document: &'a mut EditorDocument) -> Self {
19        Self {
20            document,
21            range: None,
22        }
23    }
24
25    /// Set range for karaoke operations
26    #[must_use]
27    pub fn in_range(mut self, range: Range) -> Self {
28        self.range = Some(range);
29        self
30    }
31
32    /// Generate karaoke timing for text
33    pub fn generate(self, default_duration: u32) -> KaraokeGenerator<'a> {
34        let default_range = if self.range.is_none() {
35            let doc_len = self.document.text().len();
36            Range::new(Position::new(0), Position::new(doc_len))
37        } else {
38            Range::new(Position::new(0), Position::new(0)) // Placeholder, won't be used
39        };
40
41        KaraokeGenerator {
42            document: self.document,
43            range: self.range.unwrap_or(default_range),
44            default_duration,
45            karaoke_type: KaraokeType::Standard,
46            auto_detect_syllables: true,
47        }
48    }
49
50    /// Split existing karaoke timing
51    pub fn split(self, split_positions: Vec<usize>) -> KaraokeSplitter<'a> {
52        let default_range = if self.range.is_none() {
53            let doc_len = self.document.text().len();
54            Range::new(Position::new(0), Position::new(doc_len))
55        } else {
56            Range::new(Position::new(0), Position::new(0)) // Placeholder
57        };
58
59        KaraokeSplitter {
60            document: self.document,
61            range: self.range.unwrap_or(default_range),
62            split_positions,
63            new_duration: None,
64        }
65    }
66
67    /// Adjust existing karaoke timing
68    pub fn adjust(self) -> KaraokeAdjuster<'a> {
69        let default_range = if self.range.is_none() {
70            let doc_len = self.document.text().len();
71            Range::new(Position::new(0), Position::new(doc_len))
72        } else {
73            Range::new(Position::new(0), Position::new(0)) // Placeholder
74        };
75
76        KaraokeAdjuster {
77            document: self.document,
78            range: self.range.unwrap_or(default_range),
79        }
80    }
81
82    /// Apply karaoke template
83    pub fn apply(self) -> KaraokeApplicator<'a> {
84        let default_range = if self.range.is_none() {
85            let doc_len = self.document.text().len();
86            Range::new(Position::new(0), Position::new(doc_len))
87        } else {
88            Range::new(Position::new(0), Position::new(0)) // Placeholder
89        };
90
91        KaraokeApplicator {
92            document: self.document,
93            range: self.range.unwrap_or(default_range),
94        }
95    }
96}
97
98/// Karaoke generator builder
99pub struct KaraokeGenerator<'a> {
100    document: &'a mut EditorDocument,
101    range: Range,
102    default_duration: u32,
103    karaoke_type: KaraokeType,
104    auto_detect_syllables: bool,
105}
106
107impl<'a> KaraokeGenerator<'a> {
108    /// Set karaoke type
109    #[must_use]
110    pub fn karaoke_type(mut self, karaoke_type: KaraokeType) -> Self {
111        self.karaoke_type = karaoke_type;
112        self
113    }
114
115    /// Use manual syllable splitting
116    #[must_use]
117    pub fn manual_syllables(mut self) -> Self {
118        self.auto_detect_syllables = false;
119        self
120    }
121
122    /// Execute the generation
123    pub fn execute(self) -> Result<&'a mut EditorDocument> {
124        let mut command = GenerateKaraokeCommand::new(self.range, self.default_duration)
125            .karaoke_type(self.karaoke_type);
126
127        if !self.auto_detect_syllables {
128            command = command.manual_syllables();
129        }
130
131        command.execute(self.document)?;
132        Ok(self.document)
133    }
134}