1#![deny(missing_docs, missing_debug_implementations)]
2extern crate self as redact_composer_core;
6
7pub mod error;
9
10pub mod render;
12
13pub mod timing;
15pub mod util;
17
18#[cfg(test)]
19mod test;
20
21use rand::{thread_rng, RngCore, SeedableRng};
22use rand_chacha::ChaCha12Rng;
23use std::any::TypeId;
24use std::collections::{Bound, HashSet};
25use std::fmt::Debug;
26use std::hash::{Hash, Hasher};
27use std::iter::successors;
28use std::ops::{Range, RangeBounds};
29use twox_hash::XxHash64;
30
31#[cfg(feature = "serde")]
32use serde::{Deserialize, Serialize};
33
34use crate::error::ConversionError;
35use crate::render::context::CompositionContext;
36use crate::render::{tree::Tree, RenderEngine, RenderSegment};
37use crate::timing::{Timing, STANDARD_BEAT_LENGTH};
38
39pub mod derive {
42 pub use redact_composer_derive::ElementCore as Element;
43}
44
45use std::any::Any;
46
47const LOG: &str = "redact_composer";
48
49#[cfg_attr(feature = "serde", typetag::serde)]
69pub trait Element: Debug + AsAny + 'static {
70 fn wrapped_element(&self) -> Option<&dyn Element> {
72 None
73 }
74}
75
76pub trait AsAny {
78 fn as_any(&self) -> &dyn Any;
80}
81
82impl<T: Element> AsAny for T {
83 fn as_any(&self) -> &dyn Any {
84 self
85 }
86}
87
88#[derive(Debug)]
90#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
91pub struct Segment {
92 pub element: Box<dyn Element>,
94 #[cfg_attr(feature = "serde", serde(flatten))]
96 pub timing: Timing,
97 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
100 pub name: Option<String>,
101}
102
103impl Segment {
104 pub fn new(composition_type: impl Element, timing: impl Into<Timing>) -> Segment {
107 Segment {
108 element: Box::new(composition_type),
109 timing: timing.into(),
110 name: Option::default(),
111 }
112 }
113
114 pub fn named(mut self, name: String) -> Self {
117 self.name = Some(name);
118
119 self
120 }
121
122 pub fn unnamed(mut self) -> Self {
124 self.name = None;
125
126 self
127 }
128
129 pub fn element_as<Element: crate::Element>(&self) -> Option<&Element> {
132 successors(Some(&*self.element), |s| s.wrapped_element())
133 .find_map(|s| s.as_any().downcast_ref::<Element>())
134 }
135}
136
137impl RangeBounds<i32> for Segment {
138 fn start_bound(&self) -> Bound<&i32> {
139 self.timing.start_bound()
140 }
141
142 fn end_bound(&self) -> Bound<&i32> {
143 self.timing.end_bound()
144 }
145}
146
147impl RangeBounds<i32> for &Segment {
148 fn start_bound(&self) -> Bound<&i32> {
149 self.timing.start_bound()
150 }
151
152 fn end_bound(&self) -> Bound<&i32> {
153 self.timing.end_bound()
154 }
155}
156
157#[derive(Debug)]
159pub struct SegmentRef<'a, T: Element> {
160 pub element: &'a T,
162 pub timing: &'a Timing,
164 pub name: &'a Option<String>,
166}
167
168impl<'a, T: Element> Clone for SegmentRef<'a, T> {
169 fn clone(&self) -> Self {
170 *self
171 }
172}
173
174impl<'a, T: Element> Copy for SegmentRef<'a, T> {}
175
176impl<'a, T: Element> TryFrom<&'a Segment> for SegmentRef<'a, T> {
177 type Error = ConversionError;
178
179 fn try_from(value: &'a Segment) -> std::result::Result<Self, Self::Error> {
180 if let Some(casted_ref) = value.element_as::<T>() {
181 Ok(SegmentRef {
182 element: casted_ref,
183 timing: &value.timing,
184 name: &value.name,
185 })
186 } else {
187 Err(ConversionError::TypeMismatch)
188 }
189 }
190}
191
192impl<'a, T> IntoSegment for SegmentRef<'a, T>
193where
194 T: Element + Clone,
195{
196 fn into_segment(self, timing: impl Into<Timing>) -> Segment {
211 if let Some(name) = self.name {
212 self.element
213 .clone()
214 .into_segment(timing)
215 .named(name.clone())
216 } else {
217 self.element.clone().into_segment(timing)
218 }
219 }
220
221 fn over(self, timing: impl Into<Timing>) -> Segment {
222 self.into_segment(timing)
223 }
224}
225
226impl<'a, T: Element> RangeBounds<i32> for SegmentRef<'a, T> {
227 fn start_bound(&self) -> Bound<&i32> {
228 self.timing.start_bound()
229 }
230
231 fn end_bound(&self) -> Bound<&i32> {
232 self.timing.end_bound()
233 }
234}
235
236impl<'a, T: Element> From<SegmentRef<'a, T>> for Timing {
237 fn from(value: SegmentRef<'a, T>) -> Self {
238 *value.timing
239 }
240}
241
242impl<'a, T: Element> From<&SegmentRef<'a, T>> for Timing {
243 fn from(value: &SegmentRef<'a, T>) -> Self {
244 *value.timing
245 }
246}
247
248impl<'a, T: Element> From<SegmentRef<'a, T>> for Range<i32> {
249 fn from(value: SegmentRef<'a, T>) -> Self {
250 value.timing.into()
251 }
252}
253
254impl<'a, T: Element> From<&SegmentRef<'a, T>> for Range<i32> {
255 fn from(value: &SegmentRef<'a, T>) -> Self {
256 value.timing.into()
257 }
258}
259
260pub trait IntoSegment: private::Sealed {
262 fn into_segment(self, timing: impl Into<Timing>) -> Segment;
264
265 fn over(self, timing: impl Into<Timing>) -> Segment;
267}
268
269impl<T: Element> IntoSegment for T {
270 fn into_segment(self, timing: impl Into<Timing>) -> Segment {
272 Segment::new(self, timing)
273 }
274
275 fn over(self, timing: impl Into<Timing>) -> Segment {
277 self.into_segment(timing)
278 }
279}
280
281pub mod elements {
283 use super::PartType;
284 use crate::derive::Element;
285 use crate::Element;
286
287 #[cfg(feature = "serde")]
288 use serde::{Deserialize, Serialize};
289
290 #[derive(Element, Clone, Copy, Debug, Eq, PartialEq)]
292 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
293 pub struct PlayNote {
294 pub note: u8,
296 pub velocity: u8,
298 }
299
300 #[derive(Element, Debug)]
303 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
304 #[element(wrapped_element = self.wrapped_element())]
305 pub struct Part(pub(super) Box<dyn Element>, pub(super) PartType);
306}
307use elements::Part;
308use log::{debug, info, log_enabled, trace, warn, Level};
309
310#[derive(Debug, Clone, Copy)]
312#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
313pub enum PartType {
314 Instrument,
316 Percussion,
318}
319
320impl Part {
321 pub fn instrument(wrapped_element: impl Element) -> crate::elements::Part {
323 Part(Box::new(wrapped_element), PartType::Instrument)
324 }
325
326 pub fn percussion(wrapped_element: impl Element) -> crate::elements::Part {
328 Part(Box::new(wrapped_element), PartType::Percussion)
329 }
330
331 pub fn wrapped_element(&self) -> Option<&dyn Element> {
333 Some(&*self.0)
334 }
335
336 pub fn part_type(&self) -> &PartType {
338 &self.1
339 }
340}
341
342#[derive(Debug, Copy, Clone, Eq, PartialEq)]
344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
345pub struct ComposerOptions {
346 pub ticks_per_beat: i32,
348}
349
350impl Default for ComposerOptions {
351 fn default() -> Self {
352 Self {
353 ticks_per_beat: STANDARD_BEAT_LENGTH,
354 }
355 }
356}
357
358#[derive(Debug, Default)]
361pub struct Composer {
362 pub engine: RenderEngine,
364 pub options: ComposerOptions,
366}
367
368impl From<RenderEngine> for Composer {
369 fn from(value: RenderEngine) -> Self {
370 Composer {
371 engine: value,
372 ..Default::default()
373 }
374 }
375}
376
377#[derive(Debug, Copy, Clone, Eq, PartialEq)]
379#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
380pub struct CompositionOptions {
381 pub ticks_per_beat: i32,
383}
384
385impl Default for CompositionOptions {
386 fn default() -> Self {
387 Self {
388 ticks_per_beat: STANDARD_BEAT_LENGTH,
389 }
390 }
391}
392
393impl From<ComposerOptions> for CompositionOptions {
394 fn from(value: ComposerOptions) -> Self {
395 Self {
396 ticks_per_beat: value.ticks_per_beat,
397 }
398 }
399}
400
401#[derive(Debug)]
402#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
403pub struct Composition {
406 pub options: CompositionOptions,
408 pub tree: Tree<RenderSegment>,
410}
411
412impl Composer {
413 pub fn compose(&self, seg: Segment) -> Composition {
415 let mut hasher = XxHash64::with_seed(0);
416 thread_rng().next_u64().hash(&mut hasher);
417 self.compose_with_seed(seg, hasher.finish())
418 }
419 pub fn compose_with_seed(&self, seg: Segment, seed: u64) -> Composition {
422 info!(target: LOG, "Composing {:?} with seed {:?}.", seg, seed);
423 debug!(target: LOG, "{:?}", self.options);
424 let start_time = std::time::Instant::now();
425 let options: CompositionOptions = self.options.into();
426 let mut render_tree = Tree::new();
427 let mut type_cache: Vec<HashSet<TypeId>> = Vec::new();
428 let node_id = render_tree.insert(
429 RenderSegment {
430 rendered: false,
431 seed,
432 segment: seg,
433 error: None,
434 },
435 None,
436 );
437 type_cache.insert(node_id, HashSet::default());
438
439 let mut render_stack = vec![0];
446 loop {
447 let mut added_node_count = 0;
448
449 for render_stack_idx in (0_usize..render_stack.len()).rev() {
450 let node_idx = render_stack[render_stack_idx];
451 let is_top_of_render_stack = render_stack_idx + 1 == render_stack.len();
452
453 if render_tree[node_idx].value.rendered {
455 if is_top_of_render_stack {
456 render_stack.pop();
457 }
458 continue;
459 }
460
461 let composition_context = CompositionContext::new(
462 &options,
463 &render_tree,
464 &render_tree[node_idx],
465 Some(&type_cache),
466 );
467
468 trace!(target: LOG, "Rendering: {:?}", &render_tree[node_idx]);
469 let result = self
470 .engine
471 .render(&render_tree[node_idx].value.segment, composition_context);
472
473 if let Some(render_res) = result {
474 match render_res {
475 crate::render::Result::Err(err) => {
478 trace!(target: LOG, "Rendering (Node idx: {:?}) was unsuccessful: {:?}",
479 &render_tree[node_idx].idx, err);
480 render_tree[node_idx].value.error = Some(err);
481 }
482 crate::render::Result::Ok(segments) => {
484 trace!(target: LOG, "Rendering (Node idx: {:?}) succeeded, producing \
485 {:?} children.", &render_tree[node_idx].idx, segments.len());
486
487 let mut hasher = XxHash64::default();
489 render_tree[node_idx].value.seed.hash(&mut hasher);
490 let mut rng = ChaCha12Rng::seed_from_u64(hasher.finish());
491
492 let children: Vec<RenderSegment> = segments
493 .into_iter()
494 .map(|s| RenderSegment {
495 rendered: !self.engine.can_render(&*s.element),
496 seed: match &s.name {
497 None => {
498 let mut hasher = XxHash64::default();
499 rng.next_u64().hash(&mut hasher);
500 hasher.finish()
501 }
502 Some(name) => {
503 let mut hasher = XxHash64::default();
504 render_tree[node_idx].value.seed.hash(&mut hasher);
505 name.hash(&mut hasher);
506 hasher.finish()
507 }
508 },
509 segment: s,
510 error: None,
511 })
512 .collect();
513
514 added_node_count += children.len();
515 let mut added_node_ids = vec![];
516
517 for child in children {
518 let type_ids = successors(Some(&*child.segment.element), |s| {
520 s.wrapped_element()
521 })
522 .map(|s| s.as_any().type_id())
523 .collect::<HashSet<_>>();
524 for ancestor_idx in
525 successors(Some(node_idx), |p_idx| render_tree[*p_idx].parent)
526 .collect::<Vec<_>>()
527 {
528 type_cache[ancestor_idx].extend(type_ids.iter().copied());
529 }
530
531 let node_id = render_tree.insert(child, Some(node_idx));
532 type_cache.insert(node_id, HashSet::default());
533 added_node_ids.push(node_id);
534 }
535
536 render_tree[node_idx].value.rendered = true;
537 render_tree[node_idx].value.error = None;
538
539 if is_top_of_render_stack {
543 render_stack.pop();
544 }
545 render_stack
548 .append(&mut added_node_ids.into_iter().rev().collect::<Vec<_>>());
549
550 if added_node_count > 0 {
553 break;
554 }
555 }
556 }
557 }
558 }
559
560 if added_node_count == 0 {
562 break;
563 }
564 }
565
566 let duration = std::time::Instant::now().duration_since(start_time);
567 info!(target: LOG, "Finished composing. ({:?})", duration);
568
569 if log_enabled!(target: LOG, Level::Warn) {
570 render_tree
571 .iter()
572 .filter(|n| !n.value.rendered)
573 .for_each(|n| warn!(target: LOG, "Unrendered: {:?}", n));
574 }
575
576 Composition {
577 options: self.options.into(),
578 tree: render_tree,
579 }
580 }
581}
582
583mod private {
584 use crate::SegmentRef;
585
586 pub trait Sealed {}
587
588 impl<T: super::Element> Sealed for T {}
589 impl<T: super::Element> Sealed for SegmentRef<'_, T> {}
590}