Skip to content

Commit

Permalink
Performance: allow to fallback to default Player
Browse files Browse the repository at this point in the history
  • Loading branch information
tsionyx committed Feb 9, 2024
1 parent 794a564 commit d780452
Showing 1 changed file with 39 additions and 14 deletions.
53 changes: 39 additions & 14 deletions src/music/performance.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -23,7 +23,10 @@ pub struct Performance {
repr: Vec<Event>,
}

impl<P> Music<P> {
impl<P> Music<P>
where
Player<P>: Default,
{
pub fn perform<'p>(&self, players: &'p PlayerMap<P>, ctx: Context<'p, P>) -> Performance {
self.perf(players, ctx).0
}
Expand All @@ -36,7 +39,7 @@ impl<P> Music<P> {
match self {
Music::Prim(Primitive::Note(d, p)) => {

Check failure on line 40 in src/music/performance.rs

View workflow job for this annotation

GitHub Actions / Clippy on rust 'stable'

unnecessary structure name repetition

Check failure on line 40 in src/music/performance.rs

View workflow job for this annotation

GitHub Actions / Clippy on rust 'beta'

unnecessary structure name repetition
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)) => (

Check failure on line 44 in src/music/performance.rs

View workflow job for this annotation

GitHub Actions / Clippy on rust 'stable'

unnecessary structure name repetition

Check failure on line 44 in src/music/performance.rs

View workflow job for this annotation

GitHub Actions / Clippy on rust 'beta'

unnecessary structure name repetition
Performance { repr: vec![] },
Expand Down Expand Up @@ -77,11 +80,12 @@ impl<P> Music<P> {
m.perf(players, ctx)
}
Music::Modify(Control::Phrase(phrases), m) => {

Check failure on line 82 in src/music/performance.rs

View workflow job for this annotation

GitHub Actions / Clippy on rust 'stable'

unnecessary structure name repetition

Check failure on line 82 in src/music/performance.rs

View workflow job for this annotation

GitHub Actions / Clippy on rust 'beta'

unnecessary structure name repetition
(ctx.player.interpret_phrase)(m, players, ctx, phrases)
(ctx.player.interpret_phrase.clone())(m, players, ctx, phrases)
}
Music::Modify(Control::Player(p), m) => {

Check failure on line 85 in src/music/performance.rs

View workflow job for this annotation

GitHub Actions / Clippy on rust 'stable'

unnecessary structure name repetition

Check failure on line 85 in src/music/performance.rs

View workflow job for this annotation

GitHub Actions / Clippy on rust 'beta'

unnecessary structure name repetition
// 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)
}
Expand Down Expand Up @@ -122,7 +126,7 @@ pub type Duration = Ratio<u32>;
/// as we go through the interpretation.
pub struct Context<'p, P> {
start_time: TimePoint,
player: &'p Player<P>,
player: Cow<'p, Player<P>>,
instrument: InstrumentName,
whole_note: Duration,
pitch: AbsPitch,
Expand All @@ -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,
Expand Down Expand Up @@ -175,14 +179,25 @@ pub struct Player<P> {
notate_player: NotateFun<P>,
}

impl<P> Clone for Player<P> {
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<P> fmt::Debug for Player<P> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Player {}", self.name)
}
}

type NoteFun<P> = Box<dyn Fn(Context<P>, Dur, &P) -> Performance>;
type PhraseFun<P> = Box<
type NoteFun<P> = Arc<dyn Fn(Context<P>, Dur, &P) -> Performance>;
type PhraseFun<P> = Arc<
dyn Fn(&Music<P>, &PlayerMap<P>, Context<P>, &[PhraseAttribute]) -> (Performance, Duration),
>;
// TODO: producing a properly notated score is not defined yet
Expand All @@ -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,
Expand Down Expand Up @@ -260,7 +275,7 @@ mod defaults {
Player<P>: 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)
Expand Down Expand Up @@ -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<P>) -> Self {
pub fn with_player(player: Cow<'p, Player<P>>) -> Self {
Self {
start_time: TimePoint::from_integer(0),
player,
Expand All @@ -489,4 +504,14 @@ mod defaults {
}
}
}

impl<P> Default for Context<'_, P>
where
P: 'static,
Player<P>: Default,
{
fn default() -> Self {
Self::with_player(Cow::Owned(Player::fancy()))
}
}
}

0 comments on commit d780452

Please sign in to comment.