use ff_filter::FilterStep;
use crate::clip::Clip;
use crate::ids::TrackId;
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Track {
pub id: TrackId,
pub name: String,
pub mute: bool,
pub solo: bool,
pub enabled: bool,
pub lock: bool,
pub clips: Vec<Clip>,
#[cfg_attr(feature = "serde", serde(skip))]
pub audio_effects: Vec<FilterStep>,
}
impl Track {
#[must_use]
pub fn new(clips: Vec<Clip>) -> Self {
Self {
id: TrackId::UNSET,
name: String::new(),
mute: false,
solo: false,
enabled: true,
lock: false,
clips,
audio_effects: Vec::new(),
}
}
#[must_use]
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = name.into();
self
}
#[must_use]
pub fn muted(mut self, mute: bool) -> Self {
self.mute = mute;
self
}
#[must_use]
pub fn soloed(mut self, solo: bool) -> Self {
self.solo = solo;
self
}
#[must_use]
pub fn enabled(mut self, enabled: bool) -> Self {
self.enabled = enabled;
self
}
#[must_use]
pub fn locked(mut self, lock: bool) -> Self {
self.lock = lock;
self
}
#[must_use]
pub fn audio_effects(mut self, steps: Vec<FilterStep>) -> Self {
self.audio_effects = steps;
self
}
pub(crate) fn is_active(&self, any_solo_in_list: bool) -> bool {
self.enabled && !self.mute && (!any_solo_in_list || self.solo)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_active_should_reflect_enabled_mute_solo() {
assert!(Track::new(vec![]).is_active(false));
assert!(!Track::new(vec![]).enabled(false).is_active(false));
assert!(!Track::new(vec![]).muted(true).is_active(false));
assert!(!Track::new(vec![]).is_active(true));
assert!(Track::new(vec![]).soloed(true).is_active(true));
assert!(
!Track::new(vec![])
.soloed(true)
.enabled(false)
.is_active(true)
);
}
#[test]
fn new_track_should_have_empty_audio_effects() {
assert!(Track::new(vec![]).audio_effects.is_empty());
}
#[test]
fn audio_effects_builder_should_set_chain() {
let track = Track::new(vec![]).audio_effects(vec![FilterStep::Volume(-6.0)]);
assert_eq!(track.audio_effects.len(), 1);
assert!(matches!(
track.audio_effects[0],
FilterStep::Volume(v) if (v - (-6.0)).abs() < 1e-9
));
}
}