gstreamer plugin install
This commit is contained in:
parent
87e49a8bbb
commit
ce59addefd
2 changed files with 292 additions and 99 deletions
137
Cargo.lock
generated
137
Cargo.lock
generated
|
|
@ -778,9 +778,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bytemuck_derive"
|
||||
version = "1.7.1"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26"
|
||||
checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -1868,10 +1868,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "font-types"
|
||||
version = "0.6.0"
|
||||
name = "foldhash"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f0189ccb084f77c5523e08288d418cbaa09c451a08515678a0aa265df9a8b60"
|
||||
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
|
||||
|
||||
[[package]]
|
||||
name = "font-types"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dda6e36206148f69fc6ecb1bb6c0dedd7ee469f3db1d0dc2045beea28430ca43"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
|
@ -2376,6 +2382,36 @@ dependencies = [
|
|||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-audio"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36d39b07213f83055fc705a384fa32ad581776b8e5b04c86f3a419ec5dfc0f81"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"glib",
|
||||
"gstreamer",
|
||||
"gstreamer-audio-sys",
|
||||
"gstreamer-base",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-audio-sys"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d84744e7ac8f8bc0cf76b7be40f2d5be12e6cf197e4c6ca9d3438109c21e2f51"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"gstreamer-base-sys",
|
||||
"gstreamer-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-base"
|
||||
version = "0.23.2"
|
||||
|
|
@ -2403,6 +2439,36 @@ dependencies = [
|
|||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-pbutils"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bc96a1ef43542ba68159e440adc7211e1f03824d91fd8f4e05b84f84002d33c"
|
||||
dependencies = [
|
||||
"glib",
|
||||
"gstreamer",
|
||||
"gstreamer-audio",
|
||||
"gstreamer-pbutils-sys",
|
||||
"gstreamer-video",
|
||||
"libc",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-pbutils-sys"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ba8e30cb601e11aa8b61d40bef1891ba51744d108406807932d0afc58992205"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"gstreamer-audio-sys",
|
||||
"gstreamer-sys",
|
||||
"gstreamer-video-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-sys"
|
||||
version = "0.23.2"
|
||||
|
|
@ -2415,6 +2481,37 @@ dependencies = [
|
|||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-video"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "696ac49ef4c635230b4e4bdebb72cdc31b7a3e8f4fd3f2c1b5009bb10d4ec922"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-channel",
|
||||
"glib",
|
||||
"gstreamer",
|
||||
"gstreamer-base",
|
||||
"gstreamer-video-sys",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gstreamer-video-sys"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "303620a75f22015110ead435c08577bfb7f7425a13b0165e1d03628725742f14"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"gstreamer-base-sys",
|
||||
"gstreamer-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "guillotiere"
|
||||
version = "0.6.2"
|
||||
|
|
@ -2450,6 +2547,11 @@ name = "hashbrown"
|
|||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hassle-rs"
|
||||
|
|
@ -2739,12 +2841,13 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_video_player"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/jackpot51/iced_video_player.git?branch=cosmic#52a3f4a96359716dfe74199ce46a24d3a376e6b1"
|
||||
source = "git+https://github.com/jackpot51/iced_video_player.git?branch=cosmic#8d59eb6ef219e687df54a07709b8f9bbf939825c"
|
||||
dependencies = [
|
||||
"glib",
|
||||
"gstreamer",
|
||||
"gstreamer-app",
|
||||
"gstreamer-base",
|
||||
"gstreamer-pbutils",
|
||||
"libcosmic",
|
||||
"log",
|
||||
"thiserror",
|
||||
|
|
@ -3249,11 +3352,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
|||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.12.4"
|
||||
version = "0.12.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904"
|
||||
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
|
||||
dependencies = [
|
||||
"hashbrown 0.14.5",
|
||||
"hashbrown 0.15.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4148,9 +4251,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
version = "1.0.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
|
@ -4264,9 +4367,9 @@ checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f"
|
|||
|
||||
[[package]]
|
||||
name = "read-fonts"
|
||||
version = "0.20.0"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c141b9980e1150201b2a3a32879001c8f975fe313ec3df5471a9b5c79a880cd"
|
||||
checksum = "fb94d9ac780fdcf9b6b252253f7d8f221379b84bd3573131139b383df69f85e1"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"font-types",
|
||||
|
|
@ -4711,9 +4814,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
|||
|
||||
[[package]]
|
||||
name = "skrifa"
|
||||
version = "0.20.0"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abea4738067b1e628c6ce28b2c216c19e9ea95715cdb332680e821c3bec2ef23"
|
||||
checksum = "8e1c44ad1f6c5bdd4eefed8326711b7dbda9ea45dfd36068c427d332aa382cbe"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"read-fonts",
|
||||
|
|
@ -4929,9 +5032,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "swash"
|
||||
version = "0.1.18"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93cdc334a50fcc2aa3f04761af3b28196280a6aaadb1ef11215c478ae32615ac"
|
||||
checksum = "cbd59f3f359ddd2c95af4758c18270eddd9c730dde98598023cdabff472c2ca2"
|
||||
dependencies = [
|
||||
"skrifa",
|
||||
"yazi",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use cosmic::{
|
||||
app::{Command, Core, Settings},
|
||||
app::{message, Command, Core, Settings},
|
||||
cosmic_config::{self, CosmicConfigEntry},
|
||||
cosmic_theme, executor, font,
|
||||
iced::{
|
||||
|
|
@ -17,7 +17,7 @@ use cosmic::{
|
|||
};
|
||||
use iced_video_player::{
|
||||
gst::{self, prelude::*},
|
||||
Video, VideoPlayer,
|
||||
gst_pbutils, Video, VideoPlayer,
|
||||
};
|
||||
use std::{any::TypeId, collections::HashMap, time::Duration};
|
||||
|
||||
|
|
@ -107,7 +107,9 @@ pub enum Message {
|
|||
SeekRelative(f64),
|
||||
SeekRelease,
|
||||
EndOfStream,
|
||||
MissingPlugin(gst::Message),
|
||||
NewFrame,
|
||||
Reload,
|
||||
SystemThemeModeChange(cosmic_theme::ThemeMode),
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +119,7 @@ pub struct App {
|
|||
flags: Flags,
|
||||
fullscreen: bool,
|
||||
key_binds: HashMap<KeyBind, Action>,
|
||||
video: Video,
|
||||
video_opt: Option<Video>,
|
||||
position: f64,
|
||||
duration: f64,
|
||||
dragging: bool,
|
||||
|
|
@ -128,6 +130,67 @@ pub struct App {
|
|||
}
|
||||
|
||||
impl App {
|
||||
fn close(&mut self) {
|
||||
self.video_opt = None;
|
||||
self.position = 0.0;
|
||||
self.duration = 0.0;
|
||||
self.dragging = false;
|
||||
self.audio_codes = Vec::new();
|
||||
self.current_audio = -1;
|
||||
self.text_codes = Vec::new();
|
||||
self.current_text = -1;
|
||||
}
|
||||
|
||||
fn load(&mut self) -> Command<Message> {
|
||||
self.close();
|
||||
|
||||
let video = match Video::new(&self.flags.url) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
log::warn!("failed to open {:?}: {err}", self.flags.url);
|
||||
return Command::none();
|
||||
}
|
||||
};
|
||||
self.duration = video.duration().as_secs_f64();
|
||||
let pipeline = video.pipeline();
|
||||
self.video_opt = Some(video);
|
||||
|
||||
let n_audio = pipeline.property::<i32>("n-audio");
|
||||
self.audio_codes = Vec::with_capacity(n_audio as usize);
|
||||
for i in 0..n_audio {
|
||||
let tags: gst::TagList = pipeline.emit_by_name("get-audio-tags", &[&i]);
|
||||
println!("audio stream {}: {:?}", i, tags);
|
||||
self.audio_codes.push(
|
||||
if let Some(language_code) = tags.get::<gst::tags::LanguageCode>() {
|
||||
language_code.get().to_string()
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
);
|
||||
}
|
||||
self.current_audio = pipeline.property::<i32>("current-audio");
|
||||
|
||||
let n_text = pipeline.property::<i32>("n-text");
|
||||
self.text_codes = Vec::with_capacity(n_text as usize);
|
||||
for i in 0..n_text {
|
||||
let tags: gst::TagList = pipeline.emit_by_name("get-text-tags", &[&i]);
|
||||
println!("text stream {}: {:?}", i, tags);
|
||||
self.text_codes.push(
|
||||
if let Some(language_code) = tags.get::<gst::tags::LanguageCode>() {
|
||||
language_code.get().to_string()
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
);
|
||||
}
|
||||
self.current_text = pipeline.property::<i32>("current-text");
|
||||
|
||||
//TODO: Flags can be used to enable/disable subtitles
|
||||
println!("flags {:?}", pipeline.property_value("flags"));
|
||||
|
||||
self.update_title()
|
||||
}
|
||||
|
||||
fn update_config(&mut self) -> Command<Message> {
|
||||
cosmic::app::command::set_theme(self.flags.config.app_theme.theme())
|
||||
}
|
||||
|
|
@ -165,59 +228,22 @@ impl Application for App {
|
|||
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 pipeline = video.pipeline();
|
||||
|
||||
let current_audio = pipeline.property::<i32>("current-audio");
|
||||
let n_audio = pipeline.property::<i32>("n-audio");
|
||||
let mut audio_codes = Vec::with_capacity(n_audio as usize);
|
||||
for i in 0..n_audio {
|
||||
let tags: gst::TagList = pipeline.emit_by_name("get-audio-tags", &[&i]);
|
||||
println!("audio stream {}: {:?}", i, tags);
|
||||
audio_codes.push(
|
||||
if let Some(language_code) = tags.get::<gst::tags::LanguageCode>() {
|
||||
language_code.get().to_string()
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let current_text = pipeline.property::<i32>("current-text");
|
||||
let n_text = pipeline.property::<i32>("n-text");
|
||||
let mut text_codes = Vec::with_capacity(n_text as usize);
|
||||
for i in 0..n_text {
|
||||
let tags: gst::TagList = pipeline.emit_by_name("get-text-tags", &[&i]);
|
||||
println!("text stream {}: {:?}", i, tags);
|
||||
text_codes.push(
|
||||
if let Some(language_code) = tags.get::<gst::tags::LanguageCode>() {
|
||||
language_code.get().to_string()
|
||||
} else {
|
||||
String::new()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Flags can be used to enable/disable subtitles
|
||||
println!("flags {:?}", pipeline.property_value("flags"));
|
||||
|
||||
let duration = video.duration().as_secs_f64();
|
||||
|
||||
let mut app = App {
|
||||
core,
|
||||
flags,
|
||||
fullscreen: false,
|
||||
key_binds: key_binds(),
|
||||
video,
|
||||
video_opt: None,
|
||||
position: 0.0,
|
||||
duration,
|
||||
duration: 0.0,
|
||||
dragging: false,
|
||||
audio_codes,
|
||||
current_audio,
|
||||
text_codes,
|
||||
current_text,
|
||||
audio_codes: Vec::new(),
|
||||
current_audio: -1,
|
||||
text_codes: Vec::new(),
|
||||
current_text: -1,
|
||||
};
|
||||
let command = app.update_title();
|
||||
|
||||
let command = app.load();
|
||||
(app, command)
|
||||
}
|
||||
|
||||
|
|
@ -260,51 +286,106 @@ impl Application for App {
|
|||
}
|
||||
Message::AudioCode(code) => {
|
||||
if let Ok(code) = i32::try_from(code) {
|
||||
let pipeline = self.video.pipeline();
|
||||
pipeline.set_property("current-audio", code);
|
||||
self.current_audio = pipeline.property("current-audio");
|
||||
if let Some(video) = &self.video_opt {
|
||||
let pipeline = video.pipeline();
|
||||
pipeline.set_property("current-audio", code);
|
||||
self.current_audio = pipeline.property("current-audio");
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::TextCode(code) => {
|
||||
if let Ok(code) = i32::try_from(code) {
|
||||
let pipeline = self.video.pipeline();
|
||||
pipeline.set_property("current-text", code);
|
||||
self.current_text = pipeline.property("current-text");
|
||||
if let Some(video) = &self.video_opt {
|
||||
let pipeline = video.pipeline();
|
||||
pipeline.set_property("current-text", code);
|
||||
self.current_text = pipeline.property("current-text");
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::TogglePause => {
|
||||
self.video.set_paused(!self.video.paused());
|
||||
if let Some(video) = &mut self.video_opt {
|
||||
video.set_paused(!video.paused());
|
||||
}
|
||||
}
|
||||
Message::ToggleLoop => {
|
||||
self.video.set_looping(!self.video.looping());
|
||||
if let Some(video) = &mut self.video_opt {
|
||||
video.set_looping(!video.looping());
|
||||
}
|
||||
}
|
||||
Message::Seek(secs) => {
|
||||
self.dragging = true;
|
||||
self.position = secs;
|
||||
self.video.set_paused(true);
|
||||
let duration = Duration::try_from_secs_f64(self.position).unwrap_or_default();
|
||||
self.video.seek(duration, true).expect("seek");
|
||||
if let Some(video) = &mut self.video_opt {
|
||||
self.dragging = true;
|
||||
self.position = secs;
|
||||
video.set_paused(true);
|
||||
let duration = Duration::try_from_secs_f64(self.position).unwrap_or_default();
|
||||
video.seek(duration, true).expect("seek");
|
||||
}
|
||||
}
|
||||
Message::SeekRelative(secs) => {
|
||||
self.position = self.video.position().as_secs_f64();
|
||||
let duration =
|
||||
Duration::try_from_secs_f64(self.position + secs).unwrap_or_default();
|
||||
self.video.seek(duration, true).expect("seek");
|
||||
if let Some(video) = &mut self.video_opt {
|
||||
self.position = video.position().as_secs_f64();
|
||||
let duration =
|
||||
Duration::try_from_secs_f64(self.position + secs).unwrap_or_default();
|
||||
video.seek(duration, true).expect("seek");
|
||||
}
|
||||
}
|
||||
Message::SeekRelease => {
|
||||
self.dragging = false;
|
||||
let duration = Duration::try_from_secs_f64(self.position).unwrap_or_default();
|
||||
self.video.seek(duration, true).expect("seek");
|
||||
self.video.set_paused(false);
|
||||
if let Some(video) = &mut self.video_opt {
|
||||
self.dragging = false;
|
||||
let duration = Duration::try_from_secs_f64(self.position).unwrap_or_default();
|
||||
video.seek(duration, true).expect("seek");
|
||||
video.set_paused(false);
|
||||
}
|
||||
}
|
||||
Message::EndOfStream => {
|
||||
println!("end of stream");
|
||||
}
|
||||
Message::MissingPlugin(element) => {
|
||||
if let Some(video) = &mut self.video_opt {
|
||||
video.set_paused(true);
|
||||
}
|
||||
return Command::perform(
|
||||
async move {
|
||||
tokio::task::spawn_blocking(move || {
|
||||
match gst_pbutils::MissingPluginMessage::parse(&element) {
|
||||
Ok(missing_plugin) => {
|
||||
let mut install_ctx = gst_pbutils::InstallPluginsContext::new();
|
||||
install_ctx
|
||||
.set_desktop_id(&format!("{}.desktop", Self::APP_ID));
|
||||
let install_detail = missing_plugin.installer_detail();
|
||||
println!("installing plugins: {}", install_detail);
|
||||
let status = gst_pbutils::missing_plugins::install_plugins_sync(
|
||||
&[&install_detail],
|
||||
Some(&install_ctx),
|
||||
);
|
||||
log::info!("plugin install status: {}", status);
|
||||
log::info!(
|
||||
"gstreamer registry update: {:?}",
|
||||
gst::Registry::update()
|
||||
);
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("failed to parse missing plugin message: {err}");
|
||||
}
|
||||
}
|
||||
message::app(Message::Reload)
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
},
|
||||
|x| x,
|
||||
);
|
||||
}
|
||||
Message::NewFrame => {
|
||||
if !self.dragging {
|
||||
self.position = self.video.position().as_secs_f64();
|
||||
if let Some(video) = &self.video_opt {
|
||||
self.position = video.position().as_secs_f64();
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Reload => {
|
||||
return self.load();
|
||||
}
|
||||
Message::SystemThemeModeChange(_theme_mode) => {
|
||||
return self.update_config();
|
||||
}
|
||||
|
|
@ -353,15 +434,20 @@ impl Application for App {
|
|||
format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
|
||||
};
|
||||
|
||||
let mut column = widget::column::with_capacity(4)
|
||||
.push(widget::vertical_space(Length::Fill))
|
||||
.push(
|
||||
VideoPlayer::new(&self.video)
|
||||
let mut column = widget::column::with_capacity(4);
|
||||
column = column.push(widget::vertical_space(Length::Fill));
|
||||
if let Some(video) = &self.video_opt {
|
||||
column = column.push(
|
||||
VideoPlayer::new(video)
|
||||
.on_end_of_stream(Message::EndOfStream)
|
||||
.on_missing_plugin(Message::MissingPlugin)
|
||||
.on_new_frame(Message::NewFrame)
|
||||
.width(Length::Fill),
|
||||
)
|
||||
.push(widget::vertical_space(Length::Fill));
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill),
|
||||
);
|
||||
}
|
||||
//TODO: open button if no video?
|
||||
column = column.push(widget::vertical_space(Length::Fill));
|
||||
|
||||
if !self.fullscreen {
|
||||
column = column.push(
|
||||
|
|
@ -371,11 +457,15 @@ impl Application for App {
|
|||
.spacing(8)
|
||||
.padding([0, 8])
|
||||
.push(
|
||||
widget::button::icon(if self.video.paused() {
|
||||
widget::icon::from_name("media-playback-start-symbolic").size(16)
|
||||
} else {
|
||||
widget::icon::from_name("media-playback-pause-symbolic").size(16)
|
||||
})
|
||||
widget::button::icon(
|
||||
if self.video_opt.as_ref().map_or(true, |video| video.paused()) {
|
||||
widget::icon::from_name("media-playback-start-symbolic")
|
||||
.size(16)
|
||||
} else {
|
||||
widget::icon::from_name("media-playback-pause-symbolic")
|
||||
.size(16)
|
||||
},
|
||||
)
|
||||
.on_press(Message::TogglePause),
|
||||
)
|
||||
.push(widget::text(format_time(self.position)).font(font::mono()))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue