now we can parse an entire presentation to a list of slides
This commit is contained in:
parent
6779b0c77c
commit
87a26642fa
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
57
src/lisp.rs
57
src/lisp.rs
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"))
|
||||
|
|
Loading…
Reference in a new issue