utilizing the same video and now changing slides works
This commit is contained in:
parent
e1a397c192
commit
d9459d6336
134
src/main.rs
134
src/main.rs
|
@ -7,7 +7,7 @@ use cosmic::iced::{
|
||||||
self, event, window, ContentFit, Font, Length, Point,
|
self, event, window, ContentFit, Font, Length, Point,
|
||||||
};
|
};
|
||||||
use cosmic::iced_core::SmolStr;
|
use cosmic::iced_core::SmolStr;
|
||||||
use cosmic::iced_widget::{row, stack};
|
use cosmic::iced_widget::{column, row, stack};
|
||||||
use cosmic::widget::icon;
|
use cosmic::widget::icon;
|
||||||
use cosmic::widget::tooltip::Position as TPosition;
|
use cosmic::widget::tooltip::Position as TPosition;
|
||||||
use cosmic::widget::{button, image, nav_bar, text, tooltip, Space};
|
use cosmic::widget::{button, image, nav_bar, text, tooltip, Space};
|
||||||
|
@ -80,8 +80,6 @@ struct App {
|
||||||
windows: Vec<window::Id>,
|
windows: Vec<window::Id>,
|
||||||
slides: Vec<Slide>,
|
slides: Vec<Slide>,
|
||||||
current_slide: Slide,
|
current_slide: Slide,
|
||||||
active_video: Option<Video>,
|
|
||||||
preview_video: Option<Video>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for App {
|
impl Default for App {
|
||||||
|
@ -96,42 +94,6 @@ impl Default for App {
|
||||||
.expect("oops slide");
|
.expect("oops slide");
|
||||||
let slides = vec![initial_slide.clone()];
|
let slides = vec![initial_slide.clone()];
|
||||||
let presenter = Presenter::with_app_slides(slides.clone());
|
let presenter = Presenter::with_app_slides(slides.clone());
|
||||||
let active_video = match initial_slide.background().kind {
|
|
||||||
crate::BackgroundKind::Image => None,
|
|
||||||
crate::BackgroundKind::Video => {
|
|
||||||
if let Ok(video) = &Url::from_file_path(
|
|
||||||
&initial_slide.background().path,
|
|
||||||
) {
|
|
||||||
match Video::new(video) {
|
|
||||||
Ok(video) => Some(video),
|
|
||||||
Err(e) => {
|
|
||||||
error!("Problem loading initial video from slide: {e}");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let preview_video = match initial_slide.background().kind {
|
|
||||||
crate::BackgroundKind::Image => None,
|
|
||||||
crate::BackgroundKind::Video => {
|
|
||||||
if let Ok(video) = &Url::from_file_path(
|
|
||||||
&initial_slide.background().path,
|
|
||||||
) {
|
|
||||||
match Video::new(video) {
|
|
||||||
Ok(video) => Some(video),
|
|
||||||
Err(e) => {
|
|
||||||
error!("Problem loading initial video from slide: {e}");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Self {
|
Self {
|
||||||
presenter,
|
presenter,
|
||||||
core: Core::default(),
|
core: Core::default(),
|
||||||
|
@ -140,8 +102,6 @@ impl Default for App {
|
||||||
windows: vec![],
|
windows: vec![],
|
||||||
slides,
|
slides,
|
||||||
current_slide: initial_slide,
|
current_slide: initial_slide,
|
||||||
active_video,
|
|
||||||
preview_video,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,7 +114,6 @@ enum Message {
|
||||||
CloseWindow(window::Id),
|
CloseWindow(window::Id),
|
||||||
WindowOpened(window::Id, Option<Point>),
|
WindowOpened(window::Id, Option<Point>),
|
||||||
WindowClosed(window::Id),
|
WindowClosed(window::Id),
|
||||||
ToggleMuteVideo,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl cosmic::Application for App {
|
impl cosmic::Application for App {
|
||||||
|
@ -203,55 +162,29 @@ impl cosmic::Application for App {
|
||||||
.build()
|
.build()
|
||||||
.expect("oops slide");
|
.expect("oops slide");
|
||||||
|
|
||||||
let slides = vec![initial_slide.clone()];
|
let second_slide = SlideBuilder::new()
|
||||||
|
.background(
|
||||||
|
PathBuf::from("/home/chris/pics/frodo.jpg")
|
||||||
|
.canonicalize()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.expect("oops video")
|
||||||
|
.text("Hello")
|
||||||
|
.font("Quicksand")
|
||||||
|
.font_size(50)
|
||||||
|
.text_alignment(TextAlignment::MiddleCenter)
|
||||||
|
.video_loop(false)
|
||||||
|
.video_start_time(0.0)
|
||||||
|
.video_end_time(0.0)
|
||||||
|
.build()
|
||||||
|
.expect("oops slide");
|
||||||
|
|
||||||
|
let slides = vec![
|
||||||
|
initial_slide.clone(),
|
||||||
|
second_slide.clone(),
|
||||||
|
second_slide.clone(),
|
||||||
|
];
|
||||||
let presenter = Presenter::with_app_slides(slides.clone());
|
let presenter = Presenter::with_app_slides(slides.clone());
|
||||||
let active_video = match initial_slide.background().kind {
|
|
||||||
crate::BackgroundKind::Image => None,
|
|
||||||
crate::BackgroundKind::Video => {
|
|
||||||
if let Ok(video) = &Url::from_file_path(
|
|
||||||
&initial_slide.background().path,
|
|
||||||
) {
|
|
||||||
match Video::new(video) {
|
|
||||||
Ok(mut video) => {
|
|
||||||
video.set_looping(
|
|
||||||
initial_slide.video_loop(),
|
|
||||||
);
|
|
||||||
Some(video)
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("Problem loading initial video from slide: {e}");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let preview_video = match initial_slide.background().kind {
|
|
||||||
crate::BackgroundKind::Image => None,
|
|
||||||
crate::BackgroundKind::Video => {
|
|
||||||
if let Ok(video) = &Url::from_file_path(
|
|
||||||
&initial_slide.background().path,
|
|
||||||
) {
|
|
||||||
match Video::new(video) {
|
|
||||||
Ok(mut video) => {
|
|
||||||
video.set_looping(
|
|
||||||
initial_slide.video_loop(),
|
|
||||||
);
|
|
||||||
video.set_muted(true);
|
|
||||||
Some(video)
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("Problem loading initial video from slide: {e}");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut app = App {
|
let mut app = App {
|
||||||
presenter,
|
presenter,
|
||||||
core,
|
core,
|
||||||
|
@ -260,8 +193,6 @@ impl cosmic::Application for App {
|
||||||
windows: vec![],
|
windows: vec![],
|
||||||
slides,
|
slides,
|
||||||
current_slide: initial_slide,
|
current_slide: initial_slide,
|
||||||
active_video,
|
|
||||||
preview_video,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let command;
|
let command;
|
||||||
|
@ -466,12 +397,6 @@ impl cosmic::Application for App {
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::ToggleMuteVideo => {
|
|
||||||
if let Some(video) = &mut self.active_video {
|
|
||||||
video.set_muted(true);
|
|
||||||
}
|
|
||||||
Task::none()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,7 +442,18 @@ impl cosmic::Application for App {
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.spacing(20);
|
.spacing(20);
|
||||||
row.into()
|
|
||||||
|
let column = column![
|
||||||
|
Container::new(row).center_y(Length::Fill),
|
||||||
|
Container::new(
|
||||||
|
self.presenter
|
||||||
|
.slide_preview()
|
||||||
|
.map(|m| Message::Present(m))
|
||||||
|
)
|
||||||
|
.center_y(Length::Shrink)
|
||||||
|
];
|
||||||
|
|
||||||
|
column.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
// View for presentation
|
// View for presentation
|
||||||
|
|
|
@ -6,7 +6,7 @@ use cosmic::{
|
||||||
iced_widget::{row, stack, Stack},
|
iced_widget::{row, stack, Stack},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
widget::{
|
widget::{
|
||||||
button, container, icon::Named, image, Container, Space,
|
button, container, icon::Named, image, Container, Row, Space,
|
||||||
},
|
},
|
||||||
Task,
|
Task,
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@ use iced_video_player::{Video, VideoPlayer};
|
||||||
use miette::{Context, IntoDiagnostic, Result};
|
use miette::{Context, IntoDiagnostic, Result};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
use crate::core::slide::Slide;
|
use crate::{core::slide::Slide, BackgroundKind};
|
||||||
|
|
||||||
// #[derive(Default, Clone, Debug)]
|
// #[derive(Default, Clone, Debug)]
|
||||||
pub(crate) struct Presenter {
|
pub(crate) struct Presenter {
|
||||||
|
@ -88,10 +88,20 @@ impl Presenter {
|
||||||
match message {
|
match message {
|
||||||
Message::NextSlide => {
|
Message::NextSlide => {
|
||||||
debug!("next slide");
|
debug!("next slide");
|
||||||
|
if let Some(video) = &mut self.video {
|
||||||
|
let _ = video.restart_stream();
|
||||||
|
}
|
||||||
|
self.current_slide += 1;
|
||||||
|
self.reset_video();
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::PrevSlide => {
|
Message::PrevSlide => {
|
||||||
debug!("prev slide");
|
debug!("prev slide");
|
||||||
|
if let Some(video) = &mut self.video {
|
||||||
|
let _ = video.restart_stream();
|
||||||
|
}
|
||||||
|
self.current_slide -= 1;
|
||||||
|
self.reset_video();
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::SlideChange(id) => {
|
Message::SlideChange(id) => {
|
||||||
|
@ -135,6 +145,61 @@ impl Presenter {
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn slide_preview(&self) -> Element<Message> {
|
||||||
|
let mut items = vec![];
|
||||||
|
for slide in self.slides.iter() {
|
||||||
|
items.push(Self::slide_delegate(slide));
|
||||||
|
}
|
||||||
|
Row::from_vec(items).spacing(10).padding(10).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn slide_delegate(slide: &Slide) -> Element<Message> {
|
||||||
|
let text =
|
||||||
|
text!("{}", slide.text()).size(slide.font_size() as u16);
|
||||||
|
let text = Container::new(text).center(Length::Fill);
|
||||||
|
let container = match slide.background().kind {
|
||||||
|
crate::BackgroundKind::Image => Container::new(
|
||||||
|
image("/home/chris/pics/frodo.jpg")
|
||||||
|
.content_fit(ContentFit::Cover)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill),
|
||||||
|
),
|
||||||
|
crate::BackgroundKind::Video => {
|
||||||
|
Container::new(Space::new(Length::Fill, Length::Fill))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
stack!(container, text)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset_video(&mut self) {
|
||||||
|
if let Some(slide) =
|
||||||
|
self.slides.get(self.current_slide as usize)
|
||||||
|
{
|
||||||
|
match slide.background().kind {
|
||||||
|
BackgroundKind::Image => self.video = None,
|
||||||
|
BackgroundKind::Video => {
|
||||||
|
let path = slide.background().path.clone();
|
||||||
|
if path.exists() {
|
||||||
|
let url = Url::from_file_path(path).unwrap();
|
||||||
|
let result = Video::new(&url);
|
||||||
|
match result {
|
||||||
|
Ok(v) => self.video = Some(v),
|
||||||
|
Err(e) => {
|
||||||
|
error!("Had an error creating the video object: {e}");
|
||||||
|
self.video = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.video = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn slide_view<'a>(
|
pub(crate) fn slide_view<'a>(
|
||||||
|
|
Loading…
Reference in a new issue