Improve display of times
This commit is contained in:
parent
4dd3e6bad0
commit
06192e553b
1 changed files with 83 additions and 62 deletions
|
|
@ -11,6 +11,7 @@ use cosmic::{
|
||||||
subscription::{self, Subscription},
|
subscription::{self, Subscription},
|
||||||
Alignment, Length, Limits, Size,
|
Alignment, Length, Limits, Size,
|
||||||
},
|
},
|
||||||
|
theme,
|
||||||
widget::{self, Column, Row, Slider},
|
widget::{self, Column, Row, Slider},
|
||||||
Application, ApplicationExt, Element,
|
Application, ApplicationExt, Element,
|
||||||
};
|
};
|
||||||
|
|
@ -127,8 +128,8 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_title(&mut self) -> Command<Message> {
|
fn update_title(&mut self) -> Command<Message> {
|
||||||
|
//TODO: filename?
|
||||||
let title = "COSMIC Media Player";
|
let title = "COSMIC Media Player";
|
||||||
self.set_header_title(title.to_string());
|
|
||||||
self.set_window_title(title.to_string())
|
self.set_window_title(title.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +157,9 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates the application, and optionally emits command on initialize.
|
/// Creates the application, and optionally emits command on initialize.
|
||||||
fn init(core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
||||||
|
core.window.content_container = false;
|
||||||
|
|
||||||
let video = Video::new(&flags.url).unwrap();
|
let video = Video::new(&flags.url).unwrap();
|
||||||
let pipeline = video.pipeline();
|
let pipeline = video.pipeline();
|
||||||
|
|
||||||
|
|
@ -249,10 +252,10 @@ impl Application for App {
|
||||||
Message::Seek(secs) => {
|
Message::Seek(secs) => {
|
||||||
self.dragging = true;
|
self.dragging = true;
|
||||||
self.position = secs;
|
self.position = secs;
|
||||||
|
self.video.set_paused(true);
|
||||||
self.video
|
self.video
|
||||||
.seek(Duration::from_secs_f64(self.position), false)
|
.seek(Duration::from_secs_f64(self.position), true)
|
||||||
.expect("seek");
|
.expect("seek");
|
||||||
self.video.set_paused(false);
|
|
||||||
}
|
}
|
||||||
Message::SeekRelative(secs) => {
|
Message::SeekRelative(secs) => {
|
||||||
self.video
|
self.video
|
||||||
|
|
@ -270,9 +273,7 @@ impl Application for App {
|
||||||
println!("end of stream");
|
println!("end of stream");
|
||||||
}
|
}
|
||||||
Message::NewFrame => {
|
Message::NewFrame => {
|
||||||
if self.dragging {
|
if !self.dragging {
|
||||||
self.video.set_paused(true);
|
|
||||||
} else {
|
|
||||||
self.position = self.video.position().as_secs_f64();
|
self.position = self.video.position().as_secs_f64();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -283,64 +284,84 @@ impl Application for App {
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn header_start(&self) -> Vec<Element<Self::Message>> {
|
||||||
|
vec![widget::row::with_children(vec![
|
||||||
|
//TODO: allow mute/unmute/change volume
|
||||||
|
widget::icon::from_name("audio-volume-high-symbolic")
|
||||||
|
.size(16)
|
||||||
|
.into(),
|
||||||
|
widget::dropdown(
|
||||||
|
&self.audio_codes,
|
||||||
|
usize::try_from(self.current_audio).ok(),
|
||||||
|
Message::AudioCode,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
//TODO: allow toggling subtitles
|
||||||
|
widget::icon::from_name("media-view-subtitles-symbolic")
|
||||||
|
.size(16)
|
||||||
|
.into(),
|
||||||
|
widget::dropdown(
|
||||||
|
&self.text_codes,
|
||||||
|
usize::try_from(self.current_text).ok(),
|
||||||
|
Message::TextCode,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
])
|
||||||
|
.align_items(Alignment::Center)
|
||||||
|
.spacing(8)
|
||||||
|
.into()]
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a view after each update.
|
/// Creates a view after each update.
|
||||||
fn view(&self) -> Element<Self::Message> {
|
fn view(&self) -> Element<Self::Message> {
|
||||||
Column::new()
|
let format_time = |duration: Duration| -> String {
|
||||||
.push(widget::vertical_space(Length::Fill))
|
let seconds = duration.as_secs() % 60;
|
||||||
.push(
|
let minutes = (duration.as_secs() / 60) % 60;
|
||||||
VideoPlayer::new(&self.video)
|
let hours = (duration.as_secs() / 60) / 60;
|
||||||
.on_end_of_stream(Message::EndOfStream)
|
format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
|
||||||
.on_new_frame(Message::NewFrame)
|
};
|
||||||
.width(Length::Fill),
|
widget::container(
|
||||||
)
|
Column::new()
|
||||||
.push(widget::vertical_space(Length::Fill))
|
.push(widget::vertical_space(Length::Fill))
|
||||||
.push(
|
.push(
|
||||||
Row::new()
|
VideoPlayer::new(&self.video)
|
||||||
.align_items(Alignment::Center)
|
.on_end_of_stream(Message::EndOfStream)
|
||||||
.height(Length::Fixed(32.0))
|
.on_new_frame(Message::NewFrame)
|
||||||
.spacing(8)
|
.width(Length::Fill),
|
||||||
.push(
|
)
|
||||||
widget::button::icon(if self.video.paused() {
|
.push(widget::vertical_space(Length::Fill))
|
||||||
widget::icon::from_name("media-playback-start-symbolic").size(16)
|
.push(
|
||||||
} else {
|
Row::new()
|
||||||
widget::icon::from_name("media-playback-pause-symbolic").size(16)
|
.align_items(Alignment::Center)
|
||||||
})
|
.spacing(8)
|
||||||
.on_press(Message::TogglePause),
|
.padding([0, 8])
|
||||||
)
|
.push(
|
||||||
.push(
|
widget::button::icon(if self.video.paused() {
|
||||||
//TODO: allow mute/unmute/change volume
|
widget::icon::from_name("media-playback-start-symbolic").size(16)
|
||||||
widget::icon::from_name("audio-volume-high-symbolic").size(16),
|
} else {
|
||||||
)
|
widget::icon::from_name("media-playback-pause-symbolic").size(16)
|
||||||
.push(widget::dropdown(
|
})
|
||||||
&self.audio_codes,
|
.on_press(Message::TogglePause),
|
||||||
usize::try_from(self.current_audio).ok(),
|
|
||||||
Message::AudioCode,
|
|
||||||
))
|
|
||||||
.push(
|
|
||||||
//TODO: allow toggling subtitles
|
|
||||||
widget::icon::from_name("media-view-subtitles-symbolic").size(16),
|
|
||||||
)
|
|
||||||
.push(widget::dropdown(
|
|
||||||
&self.text_codes,
|
|
||||||
usize::try_from(self.current_text).ok(),
|
|
||||||
Message::TextCode,
|
|
||||||
))
|
|
||||||
.push(widget::text(format!(
|
|
||||||
"{:#?}s / {:#?}s",
|
|
||||||
self.position as u64,
|
|
||||||
self.video.duration().as_secs()
|
|
||||||
)))
|
|
||||||
.push(
|
|
||||||
Slider::new(
|
|
||||||
0.0..=self.video.duration().as_secs_f64(),
|
|
||||||
self.position,
|
|
||||||
Message::Seek,
|
|
||||||
)
|
)
|
||||||
.step(0.1)
|
.push(widget::text(format_time(Duration::from_secs_f64(
|
||||||
.on_release(Message::SeekRelease),
|
self.position,
|
||||||
),
|
))))
|
||||||
)
|
.push(
|
||||||
.into()
|
Slider::new(
|
||||||
|
0.0..=self.video.duration().as_secs_f64(),
|
||||||
|
self.position,
|
||||||
|
Message::Seek,
|
||||||
|
)
|
||||||
|
.step(0.1)
|
||||||
|
.on_release(Message::SeekRelease),
|
||||||
|
)
|
||||||
|
.push(widget::text(format_time(
|
||||||
|
self.video.duration() - Duration::from_secs_f64(self.position),
|
||||||
|
))),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.style(theme::Container::WindowBackground)
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Self::Message> {
|
fn subscription(&self) -> Subscription<Self::Message> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue