fleshing out the core a bit more
This commit is contained in:
parent
e05815e550
commit
c8bb484a53
13 changed files with 497 additions and 9 deletions
55
src/rust/core/Cargo.toml
Normal file
55
src/rust/core/Cargo.toml
Normal file
|
@ -0,0 +1,55 @@
|
|||
[package]
|
||||
name = "core"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = [
|
||||
"Chris Cochrun <chris@cochrun.xyz>"
|
||||
]
|
||||
license = "GPL-3.0"
|
||||
|
||||
# This will instruct Cargo to create a static
|
||||
# library which CMake can link against
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
path = "lib.rs"
|
||||
|
||||
# [[bin]]
|
||||
# name = "lumina"
|
||||
# path = "src/rust/main.rs"
|
||||
|
||||
[dependencies]
|
||||
configparser = "3.0.2"
|
||||
serde = "1.0.152"
|
||||
serde_derive = "1.0.152"
|
||||
quote = "1.0.27"
|
||||
# cxx = "1.0.83"
|
||||
# cxx-qt = "0.6.1"
|
||||
# cxx-qt-lib = "0.6.1"
|
||||
# home = "0.5.4"
|
||||
dirs = "5.0.0"
|
||||
# libsqlite3-sys = { version = ">=0.17.2", features = ["bundled"] }
|
||||
youtube_dl = "0.8.0"
|
||||
tar = "0.4.40"
|
||||
zstd = "0.12.4"
|
||||
serde_json = "1.0.104"
|
||||
fastrand = "2.0.0"
|
||||
rfd = { version = "0.12.1", features = ["xdg-portal"], default-features = false }
|
||||
sqlx = { version = "0.8.2", features = ["sqlite", "runtime-tokio", "macros"] }
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
tracing-subscriber = { version = "0.3.17", features = ["fmt", "std", "chrono", "time", "local-time", "env-filter"] }
|
||||
tracing = "0.1.37"
|
||||
time = { version = "0.3.29", features = ["formatting", "macros"] }
|
||||
obws = "0.13.0"
|
||||
reqwest = "0.11.23"
|
||||
color-eyre = "0.6.3"
|
||||
# ffmpeg-next = "6.0.0"
|
||||
|
||||
# cxx-qt-build generates C++ code from the `#[cxx_qt::bridge]` module
|
||||
# and compiles it together with the Rust static library
|
||||
# [build-dependencies]
|
||||
# cxx-qt-build = { version = "0.6.1", features = [ "link_qt_object_files" ] }
|
||||
# qt-build-utils = "0.6.1"
|
||||
|
||||
# [dependencies.confy]
|
||||
# features = ["yaml_conf"]
|
||||
# default-features = false
|
11
src/rust/core/images.rs
Normal file
11
src/rust/core/images.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
pub struct Image {
|
||||
title: String
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
pub fn test_image() {
|
||||
assert_eq!(true, true)
|
||||
}
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
use std::{error::Error, fmt::Display};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PresKind {
|
||||
Html,
|
||||
Pdf,
|
||||
Generic,
|
||||
}
|
||||
use crate::presentations::PresKind;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub enum ServiceItemKind {
|
||||
#[default]
|
||||
Song,
|
||||
Video,
|
||||
Image,
|
||||
|
@ -81,3 +77,11 @@ impl Display for ParseError {
|
|||
write!(f, "Error: {message}")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
pub fn test_kinds() {
|
||||
assert_eq!(true, true)
|
||||
}
|
||||
}
|
||||
|
|
7
src/rust/core/lib.rs
Normal file
7
src/rust/core/lib.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
pub mod service_items;
|
||||
pub mod kinds;
|
||||
pub mod slides;
|
||||
pub mod songs;
|
||||
pub mod videos;
|
||||
pub mod presentations;
|
||||
pub mod images;
|
|
@ -1,2 +0,0 @@
|
|||
pub mod service_items;
|
||||
pub mod kinds;
|
38
src/rust/core/presentations.rs
Normal file
38
src/rust/core/presentations.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub enum PresKind {
|
||||
Html,
|
||||
#[default]
|
||||
Pdf,
|
||||
Generic,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub struct Presentation {
|
||||
title: String,
|
||||
kind: PresKind,
|
||||
}
|
||||
|
||||
impl Presentation {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
title: "".to_string(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_kind(&self) -> &PresKind {
|
||||
&self.kind
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::presentations::{PresKind, Presentation};
|
||||
|
||||
#[test]
|
||||
pub fn test_presentation() {
|
||||
let pres = Presentation::new();
|
||||
assert_eq!(pres.get_kind(), &PresKind::Pdf)
|
||||
}
|
||||
}
|
|
@ -1,11 +1,63 @@
|
|||
use crate::images::Image;
|
||||
use crate::presentations::Presentation;
|
||||
use crate::songs::Song;
|
||||
use crate::videos::Video;
|
||||
|
||||
use super::kinds::ServiceItemKind;
|
||||
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
struct ServiceItem {
|
||||
id: i32,
|
||||
database_id: i32,
|
||||
kind: ServiceItemKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
struct ServiceItemModel {
|
||||
items: Vec<ServiceItem>,
|
||||
}
|
||||
|
||||
impl From<Song> for ServiceItem {
|
||||
fn from(_song: Song) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Song,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Video> for ServiceItem {
|
||||
fn from(_video: Video) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Video,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Image> for ServiceItem {
|
||||
fn from(_image: Image) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Image,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Presentation> for ServiceItem {
|
||||
fn from(presentation: Presentation) -> Self {
|
||||
let preskind = presentation.get_kind();
|
||||
Self {
|
||||
kind: ServiceItemKind::Presentation(preskind.clone()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
pub fn test_service_item() {
|
||||
assert_eq!(true, true)
|
||||
}
|
||||
}
|
||||
|
|
108
src/rust/core/slides.rs
Normal file
108
src/rust/core/slides.rs
Normal file
|
@ -0,0 +1,108 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use color_eyre::eyre::Result;
|
||||
|
||||
use crate::{images::Image, kinds::ServiceItemKind, presentations::Presentation, songs::Song, videos::Video};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub enum TextAlignment {
|
||||
TopLeft,
|
||||
TopCenter,
|
||||
TopRight,
|
||||
MiddleLeft,
|
||||
#[default]
|
||||
MiddleCenter,
|
||||
MiddleRight,
|
||||
BottomLeft,
|
||||
BottomCenter,
|
||||
BottomRight,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
struct Slide {
|
||||
id: i32,
|
||||
database_id: i32,
|
||||
background: PathBuf,
|
||||
text: String,
|
||||
font: String,
|
||||
font_size: i32,
|
||||
kind: ServiceItemKind,
|
||||
text_alignment: TextAlignment,
|
||||
service_item_id: i32,
|
||||
active: bool,
|
||||
selected: bool,
|
||||
video_loop: bool,
|
||||
video_start_time: f32,
|
||||
video_end_time: f32,
|
||||
obs_scene: ObsScene,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
struct ObsScene;
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
struct SlideModel {
|
||||
slides: Vec<Slide>,
|
||||
}
|
||||
|
||||
impl From<Song> for Slide {
|
||||
fn from(_song: Song) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Song,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Video> for Slide {
|
||||
fn from(_video: Video) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Video,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Image> for Slide {
|
||||
fn from(_image: Image) -> Self {
|
||||
Self {
|
||||
kind: ServiceItemKind::Image,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Presentation> for Slide {
|
||||
fn from(presentation: Presentation) -> Self {
|
||||
let preskind = presentation.get_kind();
|
||||
Self {
|
||||
kind: ServiceItemKind::Presentation(preskind.clone()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Slide {
|
||||
pub fn slides_from_song(song: Song) -> Result<Vec<Self>> {
|
||||
let lyrics = song.get_lyrics()?;
|
||||
Ok(lyrics.iter().map(|lyric| {
|
||||
Self {
|
||||
background: song.background.clone().into(),
|
||||
text: lyric.to_owned(),
|
||||
font: song.font.clone(),
|
||||
font_size: song.font_size,
|
||||
kind: ServiceItemKind::Song,
|
||||
text_alignment: song.text_alignment,
|
||||
..Default::default()
|
||||
}
|
||||
}).collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
pub fn test_slides() {
|
||||
assert_eq!(true, true)
|
||||
}
|
||||
}
|
172
src/rust/core/songs.rs
Normal file
172
src/rust/core/songs.rs
Normal file
|
@ -0,0 +1,172 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use color_eyre::eyre::Result;
|
||||
use tracing::{debug, error};
|
||||
|
||||
use crate::slides::TextAlignment;
|
||||
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub struct Song {
|
||||
pub title: String,
|
||||
pub lyrics: String,
|
||||
pub author: String,
|
||||
pub ccli: String,
|
||||
pub audio: String,
|
||||
pub verse_order: String,
|
||||
pub background: String,
|
||||
pub background_type: String,
|
||||
pub text_alignment: TextAlignment,
|
||||
pub horizontal_text_alignment: String,
|
||||
pub vertical_text_alignment: String,
|
||||
pub font: String,
|
||||
pub font_size: i32,
|
||||
}
|
||||
|
||||
const KEYWORDS: [&'static str; 24] = [
|
||||
"Verse 1", "Verse 2", "Verse 3", "Verse 4",
|
||||
"Verse 5", "Verse 6", "Verse 7", "Verse 8",
|
||||
"Chorus 1", "Chorus 2", "Chorus 3", "Chorus 4",
|
||||
"Bridge 1", "Bridge 2", "Bridge 3", "Bridge 4",
|
||||
"Intro 1", "Intro 2", "Ending 1", "Ending 2",
|
||||
"Other 1", "Other 2", "Other 3", "Other 4",
|
||||
];
|
||||
|
||||
impl Song {
|
||||
pub fn get_lyrics(&self) -> Result<Vec<String>> {
|
||||
let mut lyric_list = Vec::new();
|
||||
let raw_lyrics = self.lyrics.as_str();
|
||||
let vorder: Vec<&str> =
|
||||
self.verse_order.split(' ').collect();
|
||||
let _first_item = true;
|
||||
|
||||
let mut lyric_map = HashMap::new();
|
||||
let mut verse_title = String::from("");
|
||||
let mut lyric = String::from("");
|
||||
for (i, line) in raw_lyrics.split('\n').enumerate() {
|
||||
if KEYWORDS.contains(&line) {
|
||||
if i != 0 {
|
||||
lyric_map.insert(verse_title, lyric);
|
||||
lyric = String::from("");
|
||||
verse_title = line.to_string();
|
||||
} else {
|
||||
verse_title = line.to_string();
|
||||
}
|
||||
} else {
|
||||
lyric.push_str(line);
|
||||
lyric.push('\n');
|
||||
}
|
||||
}
|
||||
lyric_map.insert(verse_title, lyric);
|
||||
|
||||
for verse in vorder {
|
||||
let mut verse_name = "";
|
||||
debug!(verse = verse);
|
||||
for word in KEYWORDS.clone() {
|
||||
let end_verse =
|
||||
verse.get(1..2).unwrap_or_default();
|
||||
let beg_verse =
|
||||
verse.get(0..1).unwrap_or_default();
|
||||
if word.starts_with(beg_verse)
|
||||
&& word.ends_with(end_verse)
|
||||
{
|
||||
verse_name = word;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if let Some(lyric) = lyric_map.get(verse_name) {
|
||||
if lyric.contains("\n\n") {
|
||||
let split_lyrics: Vec<&str> =
|
||||
lyric.split("\n\n").collect();
|
||||
for lyric in split_lyrics {
|
||||
if lyric.is_empty() {
|
||||
continue;
|
||||
}
|
||||
lyric_list.push(lyric.to_string());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
lyric_list.push(lyric.to_string());
|
||||
} else {
|
||||
error!("NOT WORKING!");
|
||||
};
|
||||
}
|
||||
for lyric in lyric_list.iter() {
|
||||
debug!(lyric = ?lyric)
|
||||
}
|
||||
Ok(lyric_list)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
pub fn test_song_lyrics() {
|
||||
let mut song = Song::default();
|
||||
song.lyrics = "Verse 1
|
||||
When You found me,
|
||||
I was so blind
|
||||
My sin was before me,
|
||||
I was swallowed by pride
|
||||
|
||||
Chorus 1
|
||||
But out of the darkness,
|
||||
You brought me to Your light
|
||||
You showed me new mercy
|
||||
And opened up my eyes
|
||||
|
||||
Chorus 2
|
||||
From the day
|
||||
You saved my soul
|
||||
'Til the very moment
|
||||
When I come home
|
||||
|
||||
I'll sing, I'll dance,
|
||||
My heart will overflow
|
||||
From the day
|
||||
You saved my soul
|
||||
|
||||
Verse 2
|
||||
Where brilliant light
|
||||
Is all around
|
||||
And endless joy
|
||||
Is the only sound
|
||||
|
||||
Chorus 3
|
||||
Oh, rest my heart
|
||||
Forever now
|
||||
Oh, in Your arms
|
||||
I'll always be found
|
||||
|
||||
Bridge 1
|
||||
My love is Yours
|
||||
My heart is Yours
|
||||
My life is Yours
|
||||
Forever
|
||||
|
||||
My love is Yours
|
||||
My heart is Yours
|
||||
My life is Yours
|
||||
Forever
|
||||
|
||||
Other 1
|
||||
From the Day
|
||||
I Am They
|
||||
|
||||
Other 2
|
||||
|
||||
|
||||
Ending 1
|
||||
Oh Oh Oh
|
||||
From the day
|
||||
You saved my soul".to_string();
|
||||
song.verse_order = "O1 V1 C1 C2 O2 V2 C3 C2 O2 B1 C2 C2 E1 O2".to_string();
|
||||
let lyrics = song.get_lyrics();
|
||||
match lyrics {
|
||||
Ok(lyrics) => { assert_eq!(vec!["From the Day\nI Am They", "When You found me,\nI was so blind\nMy sin was before me,\nI was swallowed by pride", "But out of the darkness,\nYou brought me to Your light\nYou showed me new mercy\nAnd opened up my eyes", "From the day\nYou saved my soul\n'Til the very moment\nWhen I come home", "I'll sing, I'll dance,\nMy heart will overflow\nFrom the day\nYou saved my soul", "Where brilliant light\nIs all around\nAnd endless joy\nIs the only sound", "Oh, rest my heart\nForever now\nOh, in Your arms\nI'll always be found", "From the day\nYou saved my soul\n'Til the very moment\nWhen I come home", "I'll sing, I'll dance,\nMy heart will overflow\nFrom the day\nYou saved my soul", "My love is Yours\nMy heart is Yours\nMy life is Yours\nForever", "My love is Yours\nMy heart is Yours\nMy life is Yours\nForever", "From the day\nYou saved my soul\n'Til the very moment\nWhen I come home", "I'll sing, I'll dance,\nMy heart will overflow\nFrom the day\nYou saved my soul", "From the day\nYou saved my soul\n'Til the very moment\nWhen I come home", "I'll sing, I'll dance,\nMy heart will overflow\nFrom the day\nYou saved my soul", "Oh Oh Oh\nFrom the day\nYou saved my soul\n"], lyrics); },
|
||||
Err(e) => { assert!(false) },
|
||||
}
|
||||
}
|
||||
}
|
11
src/rust/core/videos.rs
Normal file
11
src/rust/core/videos.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
pub struct Video {
|
||||
title: String
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
pub fn test_video() {
|
||||
assert_eq!(true, true)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue