now we can parse an entire presentation to a list of slides

This commit is contained in:
Chris Cochrun 2024-12-06 11:15:41 -06:00
parent 6779b0c77c
commit 87a26642fa
5 changed files with 193 additions and 19 deletions

View file

@ -9,6 +9,8 @@ use std::{
};
use tracing::error;
use super::songs::Song;
#[derive(
Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize,
)]
@ -174,6 +176,7 @@ pub struct Slide {
font: String,
font_size: i32,
text_alignment: TextAlignment,
audio: Option<PathBuf>,
video_loop: bool,
video_start_time: f32,
video_end_time: f32,
@ -199,10 +202,42 @@ impl Slide {
pub fn video_loop(&self) -> bool {
self.video_loop
}
pub fn song_slides(song: &Song) -> Result<Vec<Self>> {
let lyrics = song.get_lyrics()?;
let slides: Vec<Slide> = lyrics
.iter()
.map(|l| {
let song = song.clone();
SlideBuilder::new()
.background(song.background.unwrap_or_default())
.font(song.font.unwrap_or_default())
.font_size(song.font_size.unwrap_or_default())
.text_alignment(
song.text_alignment.unwrap_or_default(),
)
.audio(song.audio.unwrap_or_default())
.video_loop(true)
.video_start_time(0.0)
.video_end_time(0.0)
.text(l)
.build()
.unwrap_or_default()
})
.collect();
Ok(slides)
}
}
impl From<Value> for Slide {
fn from(value: Value) -> Self {
Self::from(&value)
}
}
impl From<&Value> for Slide {
fn from(value: &Value) -> Self {
match value {
Value::List(list) => lisp_to_slide(list),
_ => Slide::default(),
@ -210,7 +245,7 @@ impl From<Value> for Slide {
}
}
fn lisp_to_slide(lisp: Vec<Value>) -> Slide {
fn lisp_to_slide(lisp: &Vec<Value>) -> Slide {
const DEFAULT_BACKGROUND_LOCATION: usize = 1;
const DEFAULT_TEXT_LOCATION: usize = 0;
@ -327,11 +362,9 @@ pub fn lisp_to_background(lisp: &Value) -> Background {
home.push_str("/");
let s = s.replace("./", &home);
dbg!(&s);
match Background::try_from(s.as_str()) {
Ok(background) => background,
Err(e) => {
dbg!(&e);
error!(
"Couldn't load background: {e}"
);
@ -368,6 +401,7 @@ pub struct SlideBuilder {
text: Option<String>,
font: Option<String>,
font_size: Option<i32>,
audio: Option<PathBuf>,
text_alignment: Option<TextAlignment>,
video_loop: Option<bool>,
video_start_time: Option<f32>,
@ -401,6 +435,11 @@ impl SlideBuilder {
self
}
pub(crate) fn audio(mut self, audio: impl Into<PathBuf>) -> Self {
let _ = self.audio.insert(audio.into());
self
}
pub(crate) fn font(mut self, font: impl Into<String>) -> Self {
let _ = self.font.insert(font.into());
self
@ -471,6 +510,7 @@ impl SlideBuilder {
font,
font_size,
text_alignment,
audio: self.audio,
video_loop,
video_start_time,
video_end_time,

View file

@ -103,7 +103,7 @@ impl From<Value> for Song {
}
}
fn lisp_to_song(list: Vec<Value>) -> Song {
pub fn lisp_to_song(list: Vec<Value>) -> Song {
const DEFAULT_SONG_ID: i32 = 0;
const DEFAULT_SONG_LOCATION: usize = 0;
@ -273,7 +273,6 @@ fn lisp_to_song(list: Vec<Value>) -> Song {
};
let lyric = format!("{verse_title}{lyric}");
println!("lyric_final: {lyric}");
let lyric = lyric.replace(
"\\n", r#"
"#,
@ -592,8 +591,6 @@ You saved my soul"
let value = test_lisp_song();
let lisp_song = Song::from(value);
let test_song = test_song();
println!("test_song: {}", test_song.lyrics.clone().unwrap());
println!("lisp_song: {}", lisp_song.lyrics.clone().unwrap());
assert_eq!(test_song, lisp_song);
}
}

View file

@ -1,6 +1,7 @@
use crisp::types::{Symbol, Value};
use tracing::error;
use crate::Slide;
use crate::{core::songs::lisp_to_song, Slide};
pub fn parse_lisp(value: Value) -> Vec<Slide> {
match &value {
@ -10,7 +11,14 @@ pub fn parse_lisp(value: Value) -> Vec<Slide> {
vec![slide]
}
Value::Symbol(Symbol(s)) if s == "song" => {
vec![Slide::default()]
let song = lisp_to_song(vec.clone());
match Slide::song_slides(&song) {
Ok(s) => s,
Err(e) => {
error!("Couldn't load song: {e}");
vec![Slide::default()]
}
}
}
Value::Symbol(Symbol(s)) if s == "load" => {
vec![Slide::default()]
@ -23,7 +31,7 @@ pub fn parse_lisp(value: Value) -> Vec<Slide> {
#[cfg(test)]
mod test {
use std::fs::read_to_string;
use std::{fs::read_to_string, path::PathBuf};
use crate::{Background, SlideBuilder, TextAlignment};
@ -49,6 +57,31 @@ mod test {
}
}
#[test]
fn test_parsing_lisp_presentation() {
let lisp =
read_to_string("./test_presentation.lisp").expect("oops");
let lisp_value = crisp::reader::read(&lisp);
let test_vec =
vec![test_slide(), test_second_slide(), song_slide()];
match lisp_value {
Value::List(value) => {
let mut slide_vec = vec![];
for value in value {
let mut vec = parse_lisp(value);
slide_vec.append(&mut vec);
}
let first_lisp_slide = &slide_vec[0];
let second_lisp_slide = &slide_vec[1];
let third_lisp_slide = &slide_vec[2];
assert_eq!(first_lisp_slide, &test_vec[0]);
assert_eq!(second_lisp_slide, &test_vec[1]);
assert_eq!(third_lisp_slide, &test_vec[2]);
}
_ => panic!("this should be a lisp"),
}
}
fn test_slide() -> Slide {
SlideBuilder::new()
.text("This is frodo")
@ -81,4 +114,22 @@ mod test {
.build()
.unwrap()
}
fn song_slide() -> Slide {
SlideBuilder::new()
.text("Death Was Arrested\nNorth Point Worship")
.background(
Background::try_from("~/nc/tfc/openlp/CMG - Bright Mountains 01.jpg")
.unwrap(),
)
.font("Quicksand Bold")
.font_size(60)
.text_alignment(TextAlignment::MiddleCenter)
.audio(PathBuf::from("file:///home/chris/music/North Point InsideOut/Nothing Ordinary, Pt. 1 (Live)/05 Death Was Arrested (feat. Seth Condrey).mp3"))
.video_loop(true)
.video_start_time(0.0)
.video_end_time(0.0)
.build()
.unwrap()
}
}

View file

@ -1,13 +1,100 @@
(slide :background (image :source "~/pics/frodo.jpg" :fit fill)
(text "This is frodo" :font-size 70))
(slide (video :source "~/vids/test/camprules2024.mp4" :fit contain))
(song :author "Jordan Feliz" :ccli 97987
:font "Quicksand" :font-size 80
:title "The River"
:background (image :source "./coolbg.jpg")
(text "I'm going down to the river")
(text "Down to the river")
(text "Down to the river to pray ay ay!"))
(song :id 7 :author "North Point Worship"
:font "Quicksand Bold" :font-size 60
:title "Death Was Arrested"
:background (image :source "file:///home/chris/nc/tfc/openlp/CMG - Bright Mountains 01.jpg" :fit cover)
:text-alignment center
:audio "file:///home/chris/music/North Point InsideOut/Nothing Ordinary, Pt. 1 (Live)/05 Death Was Arrested (feat. Seth Condrey).mp3"
:verse-order (i1 v1 v2 c1 v3 c1 v4 c1 b1 b1 e1 e2)
(i1 "Death Was Arrested\nNorth Point Worship")
(v1 "Alone in my sorrow
And dead in my sin
Lost without hope
With no place to begin
Your love made a way
To let mercy come in
When death was arrested
And my life began")
(v2 "Ash was redeemed
Only beauty remains
My orphan heart
Was given a name
My mourning grew quiet,
My feet rose to dance
When death was arrested
And my life began")
(c1 "Oh, Your grace so free,
Washes over me
You have made me new,
Now life begins with You
It's Your endless love,
Pouring down on us
You have made us new,
Now life begins with You")
(v3 "Released from my chains,
I'm a prisoner no more
My shame was a ransom
He faithfully bore
He cancelled my debt and
He called me His friend
When death was arrested
And my life began")
(v4 "Our Savior displayed
On a criminal's cross
Darkness rejoiced as though
Heaven had lost
But then Jesus arose
With our freedom in hand
That's when death was arrested
And my life began
That's when death was arrested
And my life began")
(b1 "Oh, we're free, free,
Forever we're free
Come join the song
Of all the redeemed
Yes, we're free, free,
Forever amen
When death was arrested
And my life began
Oh, we're free, free,
Forever we're free
Come join the song
Of all the redeemed
Yes, we're free, free,
Forever amen
When death was arrested
And my life began")
(e1 "When death was arrested
And my life began
That's when death was arrested
And my life began"))
(song :author "Jordan Feliz" :ccli 97987
:font "Quicksand" :font-size 80
:title "The River"

View file

@ -91,5 +91,4 @@ And my life began")
And my life began
That's when death was arrested
And my life began")
)
And my life began"))