Skip to main content

ass_editor/core/fluent/
karaoke_builders.rs

1//! Karaoke splitter, adjuster, and applicator builders.
2//!
3//! These builders are constructed by [`super::KaraokeOps`], so their fields are
4//! `pub(super)` to remain reachable from the karaoke operations entry point in the
5//! sibling [`super::karaoke`] module.
6
7use crate::commands::{
8    AdjustKaraokeCommand, ApplyKaraokeCommand, EditorCommand, KaraokeType, SplitKaraokeCommand,
9};
10use crate::core::{EditorDocument, Range, Result};
11
12#[cfg(not(feature = "std"))]
13use alloc::vec::Vec;
14
15/// Karaoke splitter builder
16pub struct KaraokeSplitter<'a> {
17    pub(super) document: &'a mut EditorDocument,
18    pub(super) range: Range,
19    pub(super) split_positions: Vec<usize>,
20    pub(super) new_duration: Option<u32>,
21}
22
23impl<'a> KaraokeSplitter<'a> {
24    /// Set new duration for split segments
25    #[must_use]
26    pub fn duration(mut self, duration: u32) -> Self {
27        self.new_duration = Some(duration);
28        self
29    }
30
31    /// Execute the split
32    pub fn execute(self) -> Result<&'a mut EditorDocument> {
33        let mut command = SplitKaraokeCommand::new(self.range, self.split_positions);
34
35        if let Some(duration) = self.new_duration {
36            command = command.duration(duration);
37        }
38
39        command.execute(self.document)?;
40        Ok(self.document)
41    }
42}
43
44/// Karaoke adjuster builder
45pub struct KaraokeAdjuster<'a> {
46    pub(super) document: &'a mut EditorDocument,
47    pub(super) range: Range,
48}
49
50impl<'a> KaraokeAdjuster<'a> {
51    /// Scale timing by factor
52    pub fn scale(self, factor: f32) -> Result<&'a mut EditorDocument> {
53        let command = AdjustKaraokeCommand::scale(self.range, factor);
54        command.execute(self.document)?;
55        Ok(self.document)
56    }
57
58    /// Offset timing by centiseconds
59    pub fn offset(self, offset: i32) -> Result<&'a mut EditorDocument> {
60        let command = AdjustKaraokeCommand::offset(self.range, offset);
61        command.execute(self.document)?;
62        Ok(self.document)
63    }
64
65    /// Set all timing to specific duration
66    pub fn set_all(self, duration: u32) -> Result<&'a mut EditorDocument> {
67        let command = AdjustKaraokeCommand::set_all(self.range, duration);
68        command.execute(self.document)?;
69        Ok(self.document)
70    }
71
72    /// Apply custom timing to each syllable
73    pub fn custom(self, timings: Vec<u32>) -> Result<&'a mut EditorDocument> {
74        let command = AdjustKaraokeCommand::custom(self.range, timings);
75        command.execute(self.document)?;
76        Ok(self.document)
77    }
78}
79
80/// Karaoke applicator builder
81pub struct KaraokeApplicator<'a> {
82    pub(super) document: &'a mut EditorDocument,
83    pub(super) range: Range,
84}
85
86impl<'a> KaraokeApplicator<'a> {
87    /// Apply equal timing
88    pub fn equal(self, duration: u32, karaoke_type: KaraokeType) -> Result<&'a mut EditorDocument> {
89        let command = ApplyKaraokeCommand::equal(self.range, duration, karaoke_type);
90        command.execute(self.document)?;
91        Ok(self.document)
92    }
93
94    /// Apply beat-based timing
95    pub fn beat(
96        self,
97        bpm: u32,
98        beats_per_syllable: f32,
99        karaoke_type: KaraokeType,
100    ) -> Result<&'a mut EditorDocument> {
101        let command = ApplyKaraokeCommand::beat(self.range, bpm, beats_per_syllable, karaoke_type);
102        command.execute(self.document)?;
103        Ok(self.document)
104    }
105
106    /// Apply pattern-based timing
107    pub fn pattern(
108        self,
109        durations: Vec<u32>,
110        karaoke_type: KaraokeType,
111    ) -> Result<&'a mut EditorDocument> {
112        let command = ApplyKaraokeCommand::pattern(self.range, durations, karaoke_type);
113        command.execute(self.document)?;
114        Ok(self.document)
115    }
116
117    /// Import timing from another event
118    pub fn import_from(self, source_event_index: usize) -> Result<&'a mut EditorDocument> {
119        let command = ApplyKaraokeCommand::import_from(self.range, source_event_index);
120        command.execute(self.document)?;
121        Ok(self.document)
122    }
123}