1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
use chrono::{DateTime, Utc};
use scene::{Scene, SceneTracks};
use time::MediaTime;
use crate::placement::MAIN_TRACK_NAME;
use crate::placement::track_factory::build_empty_track;
use crate::types::TrackType;
pub fn get_main_scene(scenes: &[Scene]) -> Option<&Scene> {
scenes.iter().find(|scene| scene.is_main)
}
pub fn ensure_main_scene(scenes: &[Scene], next_id: &mut dyn FnMut() -> String, now: DateTime<Utc>) -> Vec<Scene> {
if scenes.iter().any(|scene| scene.is_main) {
return scenes.to_vec();
}
let main_scene = build_default_scene(
next_id(),
next_id(),
"Main scene".to_string(),
true,
now,
);
let mut next = Vec::with_capacity(scenes.len() + 1);
next.push(main_scene);
next.extend(scenes.iter().cloned());
next
}
pub fn build_default_scene(
id: impl Into<String>,
main_track_id: impl Into<String>,
name: String,
is_main: bool,
now: DateTime<Utc>,
) -> Scene {
Scene {
id: id.into(),
name,
is_main,
tracks: SceneTracks {
overlay: Vec::new(),
main: build_empty_track(
main_track_id,
TrackType::Video,
Some(MAIN_TRACK_NAME.to_string()),
),
audio: Vec::new(),
},
bookmarks: Vec::new(),
created_at: now,
updated_at: now,
}
}
pub struct SceneDeleteCheck {
pub can_delete: bool,
pub reason: Option<String>,
}
pub fn can_delete_scene(scene: &Scene) -> SceneDeleteCheck {
if scene.is_main {
return SceneDeleteCheck {
can_delete: false,
reason: Some("Cannot delete main scene".to_string()),
};
}
SceneDeleteCheck {
can_delete: true,
reason: None,
}
}
pub fn get_fallback_scene_after_delete<'a>(
scenes: &'a [Scene],
deleted_scene_id: &str,
current_scene_id: Option<&str>,
) -> Option<&'a Scene> {
if current_scene_id != Some(deleted_scene_id) {
return scenes.iter().find(|scene| Some(scene.id.as_str()) == current_scene_id);
}
get_main_scene(scenes)
}
pub fn find_current_scene<'a>(
scenes: &'a [Scene],
current_scene_id: &str,
) -> Option<&'a Scene> {
scenes
.iter()
.find(|scene| scene.id == current_scene_id)
.or_else(|| get_main_scene(scenes))
.or_else(|| scenes.first())
}
pub fn get_project_duration_from_scenes(scenes: &[Scene]) -> MediaTime {
let Some(main_scene) = get_main_scene(scenes).or_else(|| scenes.first()) else {
return MediaTime::ZERO;
};
crate::calculate_total_duration(&main_scene.tracks)
}
pub fn update_scene_in_array(
scenes: &[Scene],
scene_id: &str,
update: impl Fn(&Scene) -> Scene,
) -> Vec<Scene> {
scenes
.iter()
.map(|scene| {
if scene.id == scene_id {
update(scene)
} else {
scene.clone()
}
})
.collect()
}
|