From d7804528cdd100ed1bc36aa9a64a10bd23530fbe Mon Sep 17 00:00:00 2001 From: Ivan L Date: Thu, 8 Feb 2024 01:46:13 +0400 Subject: [PATCH] Performance: allow to fallback to default Player --- src/music/performance.rs | 53 +++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/music/performance.rs b/src/music/performance.rs index 13d90e8..2e5d8f0 100644 --- a/src/music/performance.rs +++ b/src/music/performance.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fmt}; +use std::{borrow::Cow, collections::HashMap, fmt, sync::Arc}; use itertools::Itertools as _; use num_rational::Ratio; @@ -23,7 +23,10 @@ pub struct Performance { repr: Vec, } -impl

Music

{ +impl

Music

+where + Player

: Default, +{ pub fn perform<'p>(&self, players: &'p PlayerMap

, ctx: Context<'p, P>) -> Performance { self.perf(players, ctx).0 } @@ -36,7 +39,7 @@ impl

Music

{ match self { Music::Prim(Primitive::Note(d, p)) => { let dur = d.into_ratio() * ctx.whole_note; - ((ctx.player.play_note)(ctx, *d, p), dur) + ((ctx.player.play_note.clone())(ctx, *d, p), dur) } Music::Prim(Primitive::Rest(d)) => ( Performance { repr: vec![] }, @@ -77,11 +80,12 @@ impl

Music

{ m.perf(players, ctx) } Music::Modify(Control::Phrase(phrases), m) => { - (ctx.player.interpret_phrase)(m, players, ctx, phrases) + (ctx.player.interpret_phrase.clone())(m, players, ctx, phrases) } Music::Modify(Control::Player(p), m) => { - // TODO - let player = players.get(p).expect("not found player"); + let player = players + .get(p) + .map_or_else(|| Cow::Owned(Player::default()), Cow::Borrowed); ctx.player = player; m.perf(players, ctx) } @@ -122,7 +126,7 @@ pub type Duration = Ratio; /// as we go through the interpretation. pub struct Context<'p, P> { start_time: TimePoint, - player: &'p Player

, + player: Cow<'p, Player

>, instrument: InstrumentName, whole_note: Duration, pitch: AbsPitch, @@ -143,7 +147,7 @@ impl<'p, P> Clone for Context<'p, P> { } = self; Self { start_time: *start_time, - player: *player, + player: player.clone(), instrument: instrument.clone(), whole_note: *whole_note, pitch: *pitch, @@ -175,14 +179,25 @@ pub struct Player

{ notate_player: NotateFun

, } +impl

Clone for Player

{ + fn clone(&self) -> Self { + Self { + name: self.name.clone(), + play_note: self.play_note.clone(), + interpret_phrase: self.interpret_phrase.clone(), + notate_player: self.notate_player, + } + } +} + impl

fmt::Debug for Player

{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Player {}", self.name) } } -type NoteFun

= Box, Dur, &P) -> Performance>; -type PhraseFun

= Box< +type NoteFun

= Arc, Dur, &P) -> Performance>; +type PhraseFun

= Arc< dyn Fn(&Music

, &PlayerMap

, Context

, &[PhraseAttribute]) -> (Performance, Duration), >; // TODO: producing a properly notated score is not defined yet @@ -208,7 +223,7 @@ mod defaults { where Attr: 'static, { - Box::new(move |ctx, dur, (note_pitch, attrs)| { + Arc::new(move |ctx, dur, (note_pitch, attrs)| { let Context { start_time, player: _ignore_player, @@ -260,7 +275,7 @@ mod defaults { Player

: Default, PhraseF: Fn(Performance, &PhraseAttribute) -> Performance + 'static, { - Box::new(move |music, players, ctx, attrs| { + Arc::new(move |music, players, ctx, attrs| { let (perf, dur) = music.perf(players, ctx); let perf = attrs.iter().fold(perf, &attr_modifier); (perf, dur) @@ -470,14 +485,14 @@ mod defaults { /// with changed interpretations of the [phrases][PhraseAttribute]. pub fn fancy() -> Self { Self { - interpret_phrase: Box::new(fancy_interpret_phrase), + interpret_phrase: Arc::new(fancy_interpret_phrase), ..Self::default() } } } impl<'p, P> Context<'p, P> { - pub fn with_player(player: &'p Player

) -> Self { + pub fn with_player(player: Cow<'p, Player

>) -> Self { Self { start_time: TimePoint::from_integer(0), player, @@ -489,4 +504,14 @@ mod defaults { } } } + + impl

Default for Context<'_, P> + where + P: 'static, + Player

: Default, + { + fn default() -> Self { + Self::with_player(Cow::Owned(Player::fancy())) + } + } }