feat: add skip forward and backward playback controls
This commit is contained in:
parent
468b5f1459
commit
f3d6469bed
4 changed files with 119 additions and 13 deletions
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.1693 13.9167C3.11349 13.9167 3.06326 13.8972 3.01862 13.8583C2.97955 13.8194 2.96002 13.7694 2.96002 13.7083V9.56667L1.75459 10.4917C1.70436 10.5306 1.65135 10.5444 1.59554 10.5333C1.54531 10.5222 1.50067 10.4917 1.4616 10.4417L1.04305 9.9C1.00957 9.85 0.995615 9.79722 1.0012 9.74167C1.01236 9.68611 1.04305 9.64167 1.09328 9.60833L3.00187 8.14167C3.03536 8.11944 3.06605 8.10556 3.09396 8.1C3.12744 8.08889 3.16372 8.08333 3.20278 8.08333H4.09011C4.14592 8.08333 4.19335 8.10278 4.23242 8.14167C4.27148 8.18056 4.29102 8.23056 4.29102 8.29167V13.7083C4.29102 13.7694 4.27148 13.8194 4.23242 13.8583C4.19335 13.8972 4.14592 13.9167 4.09011 13.9167H3.1693Z" fill="#232323"/>
|
||||
<path d="M7.66029 14C7.25848 14 6.91248 13.9444 6.62228 13.8333C6.33767 13.7167 6.10049 13.5583 5.91075 13.3583C5.72658 13.1528 5.58707 12.9167 5.49219 12.65C5.4029 12.3778 5.34989 12.0889 5.33314 11.7833C5.32756 11.6333 5.32198 11.4667 5.3164 11.2833C5.3164 11.0944 5.3164 10.9056 5.3164 10.7167C5.32198 10.5278 5.32756 10.3556 5.33314 10.2C5.34431 9.89444 5.39732 9.60833 5.49219 9.34167C5.59265 9.075 5.73774 8.84167 5.92749 8.64167C6.11723 8.44167 6.35441 8.28611 6.63903 8.175C6.92922 8.05833 7.26965 8 7.66029 8C8.05094 8 8.38857 8.05833 8.67319 8.175C8.95781 8.28611 9.19499 8.44167 9.38473 8.64167C9.57447 8.84167 9.71678 9.075 9.81165 9.34167C9.9121 9.60833 9.9707 9.89444 9.98744 10.2C9.99302 10.3556 9.99581 10.5278 9.99581 10.7167C10.0014 10.9056 10.0014 11.0944 9.99581 11.2833C9.99581 11.4667 9.99302 11.6333 9.98744 11.7833C9.9707 12.0889 9.91489 12.3778 9.82002 12.65C9.72515 12.9167 9.58284 13.1528 9.3931 13.3583C9.20894 13.5583 8.97176 13.7167 8.68156 13.8333C8.39695 13.9444 8.05652 14 7.66029 14ZM7.66029 12.9167C7.98397 12.9167 8.22115 12.8111 8.37183 12.6C8.52251 12.3889 8.60343 12.1028 8.61459 11.7417C8.62017 11.5806 8.62296 11.4139 8.62296 11.2417C8.62854 11.0694 8.62854 10.8972 8.62296 10.725C8.62296 10.5528 8.62017 10.3917 8.61459 10.2417C8.60343 9.89722 8.52251 9.61667 8.37183 9.4C8.22115 9.18333 7.98397 9.07222 7.66029 9.06667C7.33103 9.07222 7.09106 9.18333 6.94038 9.4C6.79529 9.61667 6.71716 9.89722 6.706 10.2417C6.70041 10.3917 6.69483 10.5528 6.68925 10.725C6.68925 10.8972 6.68925 11.0694 6.68925 11.2417C6.69483 11.4139 6.70041 11.5806 6.706 11.7417C6.71716 12.1028 6.79808 12.3889 6.94876 12.6C7.09943 12.8111 7.33661 12.9167 7.66029 12.9167Z" fill="#232323"/>
|
||||
<path d="M1.5 4L6 7V5.01465C6.16505 5.00595 6.33174 5 6.5 5C10.0899 5 13 7.01472 13 9.5C13 10.4041 12.613 11.244 11.9502 11.9492C11.6152 12.3713 11.6558 12.9781 12.0479 13.3281C12.455 13.6916 13.1076 13.6232 13.4854 13.2002C14.4387 12.1498 15 10.8755 15 9.5C15 5.91015 11.1944 3 6.5 3C6.33214 3 6.16545 3.00438 6 3.01172V1L1.5 4Z" fill="#232323"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.1693 13.9167C7.11349 13.9167 7.06326 13.8972 7.01862 13.8583C6.97955 13.8194 6.96002 13.7694 6.96002 13.7083V9.56667L5.75459 10.4917C5.70436 10.5306 5.65135 10.5444 5.59554 10.5333C5.54531 10.5222 5.50067 10.4917 5.4616 10.4417L5.04305 9.9C5.00957 9.85 4.99562 9.79722 5.0012 9.74167C5.01236 9.68611 5.04305 9.64167 5.09328 9.60833L7.00187 8.14167C7.03536 8.11944 7.06605 8.10556 7.09396 8.1C7.12744 8.08889 7.16372 8.08333 7.20278 8.08333H8.09011C8.14592 8.08333 8.19335 8.10278 8.23242 8.14167C8.27148 8.18056 8.29102 8.23056 8.29102 8.29167V13.7083C8.29102 13.7694 8.27148 13.8194 8.23242 13.8583C8.19335 13.8972 8.14592 13.9167 8.09011 13.9167H7.1693Z" fill="#232323"/>
|
||||
<path d="M11.6603 14C11.2585 14 10.9125 13.9444 10.6223 13.8333C10.3377 13.7167 10.1005 13.5583 9.91075 13.3583C9.72658 13.1528 9.58707 12.9167 9.49219 12.65C9.4029 12.3778 9.34989 12.0889 9.33314 11.7833C9.32756 11.6333 9.32198 11.4667 9.3164 11.2833C9.3164 11.0944 9.3164 10.9056 9.3164 10.7167C9.32198 10.5278 9.32756 10.3556 9.33314 10.2C9.34431 9.89444 9.39732 9.60833 9.49219 9.34167C9.59265 9.075 9.73774 8.84167 9.92749 8.64167C10.1172 8.44167 10.3544 8.28611 10.639 8.175C10.9292 8.05833 11.2696 8 11.6603 8C12.0509 8 12.3886 8.05833 12.6732 8.175C12.9578 8.28611 13.195 8.44167 13.3847 8.64167C13.5745 8.84167 13.7168 9.075 13.8117 9.34167C13.9121 9.60833 13.9707 9.89444 13.9874 10.2C13.993 10.3556 13.9958 10.5278 13.9958 10.7167C14.0014 10.9056 14.0014 11.0944 13.9958 11.2833C13.9958 11.4667 13.993 11.6333 13.9874 11.7833C13.9707 12.0889 13.9149 12.3778 13.82 12.65C13.7252 12.9167 13.5828 13.1528 13.3931 13.3583C13.2089 13.5583 12.9718 13.7167 12.6816 13.8333C12.3969 13.9444 12.0565 14 11.6603 14ZM11.6603 12.9167C11.984 12.9167 12.2212 12.8111 12.3718 12.6C12.5225 12.3889 12.6034 12.1028 12.6146 11.7417C12.6202 11.5806 12.623 11.4139 12.623 11.2417C12.6285 11.0694 12.6285 10.8972 12.623 10.725C12.623 10.5528 12.6202 10.3917 12.6146 10.2417C12.6034 9.89722 12.5225 9.61667 12.3718 9.4C12.2212 9.18333 11.984 9.07222 11.6603 9.06667C11.331 9.07222 11.0911 9.18333 10.9404 9.4C10.7953 9.61667 10.7172 9.89722 10.706 10.2417C10.7004 10.3917 10.6948 10.5528 10.6893 10.725C10.6893 10.8972 10.6893 11.0694 10.6893 11.2417C10.6948 11.4139 10.7004 11.5806 10.706 11.7417C10.7172 12.1028 10.7981 12.3889 10.9488 12.6C11.0994 12.8111 11.3366 12.9167 11.6603 12.9167Z" fill="#232323"/>
|
||||
<path d="M14.5 4L10 7V5.01465C9.83495 5.00595 9.66826 5 9.5 5C5.91015 5 3 7.01472 3 9.5C3 10.4041 3.38701 11.244 4.0498 11.9492C4.38477 12.3713 4.34421 12.9781 3.95215 13.3281C3.545 13.6916 2.89241 13.6232 2.51465 13.2002C1.56125 12.1498 1 10.8755 1 9.5C1 5.91015 4.80558 3 9.5 3C9.66786 3 9.83455 3.00438 10 3.01172V1L14.5 4Z" fill="#232323"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
114
src/main.rs
114
src/main.rs
|
|
@ -47,6 +47,12 @@ const GST_PLAY_FLAG_VIDEO: i32 = 1 << 0;
|
|||
const GST_PLAY_FLAG_AUDIO: i32 = 1 << 1;
|
||||
const GST_PLAY_FLAG_TEXT: i32 = 1 << 2;
|
||||
|
||||
const JUMP_BACKWARD_ICON: &[u8] =
|
||||
include_bytes!("../res/icons/hicolor/16x16/apps/jump-backward-10-symbolic.svg");
|
||||
|
||||
const JUMP_FORWARD_ICON: &[u8] =
|
||||
include_bytes!("../res/icons/hicolor/16x16/apps/jump-forward-10-symbolic.svg");
|
||||
|
||||
use std::error::Error;
|
||||
|
||||
fn language_name(code: &str) -> Option<String> {
|
||||
|
|
@ -170,6 +176,8 @@ pub enum Action {
|
|||
FolderOpenRecent(usize),
|
||||
Fullscreen,
|
||||
PlayPause,
|
||||
PlayPrev,
|
||||
PlayNext,
|
||||
SeekBackward,
|
||||
SeekForward,
|
||||
NextFrame,
|
||||
|
|
@ -193,6 +201,8 @@ impl MenuAction for Action {
|
|||
Self::FolderOpenRecent(index) => Message::FolderOpenRecent(*index),
|
||||
Self::Fullscreen => Message::Fullscreen,
|
||||
Self::PlayPause => Message::PlayPause,
|
||||
Self::PlayPrev => Message::PlayPrev,
|
||||
Self::PlayNext => Message::PlayNext,
|
||||
Self::SeekBackward => Message::SeekRelative(-10.0),
|
||||
Self::SeekForward => Message::SeekRelative(10.0),
|
||||
Self::NextFrame => Message::NextFrame,
|
||||
|
|
@ -291,6 +301,7 @@ pub enum Message {
|
|||
Seek(f64),
|
||||
SeekRelative(f64),
|
||||
SeekRelease,
|
||||
PlayPrev,
|
||||
PlayNext,
|
||||
NextFrame,
|
||||
PreviousFrame,
|
||||
|
|
@ -1338,6 +1349,55 @@ impl Application for App {
|
|||
}
|
||||
}
|
||||
|
||||
Message::PlayPrev => {
|
||||
if self.flags.config_state.player_state.repeat == RepeatState::Track {
|
||||
return Task::none();
|
||||
}
|
||||
|
||||
//first we get info about current media id & position in nav_bar
|
||||
let curr_id = self.nav_model.active();
|
||||
let curr_position = match self.nav_model.position(curr_id) {
|
||||
Some(pos) => pos,
|
||||
None => {
|
||||
log::warn!("Failed to get position of current media: {:?}", curr_id);
|
||||
return self.update(Message::EndOfStream);
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(video) = &mut self.video_opt {
|
||||
self.position = video.position().as_secs_f64();
|
||||
|
||||
if self.position > 3.0 {
|
||||
video.seek(0, false).expect("seek");
|
||||
} else {
|
||||
if self.nav_model.activate_position(curr_position - 1) {
|
||||
let curr_id = self.nav_model.active();
|
||||
match self.nav_model.data::<ProjectNode>(curr_id) {
|
||||
//The prev one is a media file, we play it.
|
||||
Some(ProjectNode::File { .. }) => {
|
||||
return self.on_nav_select(curr_id);
|
||||
}
|
||||
|
||||
//The prev one is a folder. We expand it and recall PlayPrev.
|
||||
Some(ProjectNode::Folder { .. }) => {
|
||||
let _ = self.on_nav_select(curr_id);
|
||||
return self.update(Message::PlayPrev);
|
||||
}
|
||||
|
||||
//Unknown type. We do nothing.
|
||||
_ => log::warn!(
|
||||
"unknown type: {:?}",
|
||||
self.nav_model.data::<ProjectNode>(curr_id)
|
||||
),
|
||||
}
|
||||
} else {
|
||||
// first file
|
||||
video.seek(0, false).expect("seek");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Message::PlayNext => {
|
||||
// TODO: known limitations:
|
||||
// 1) if the user collapses the folder entry while a song is playing,
|
||||
|
|
@ -1779,19 +1839,55 @@ impl Application for App {
|
|||
);
|
||||
}
|
||||
if self.controls {
|
||||
let mut row = widget::row::with_capacity(7)
|
||||
let mut row = widget::row::with_capacity(9)
|
||||
.align_y(Alignment::Center)
|
||||
.spacing(space_xxs)
|
||||
.push(
|
||||
widget::button::icon(
|
||||
if self.video_opt.as_ref().is_none_or(|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::PlayPause),
|
||||
if self
|
||||
.video_opt
|
||||
.as_ref()
|
||||
.map_or(true, |video| video.has_video())
|
||||
{
|
||||
widget::button::icon(
|
||||
widget::icon::from_svg_bytes(JUMP_BACKWARD_ICON).symbolic(true),
|
||||
)
|
||||
.on_press(Message::SeekRelative(-10.0))
|
||||
} else {
|
||||
widget::button::icon(
|
||||
widget::icon::from_name("media-skip-backward-symbolic").size(16),
|
||||
)
|
||||
.on_press(Message::PlayPrev)
|
||||
},
|
||||
);
|
||||
row = row.push(
|
||||
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::PlayPause),
|
||||
);
|
||||
|
||||
row = row.push(
|
||||
if self
|
||||
.video_opt
|
||||
.as_ref()
|
||||
.map_or(true, |video| video.has_video())
|
||||
{
|
||||
widget::button::icon(
|
||||
widget::icon::from_svg_bytes(JUMP_FORWARD_ICON).symbolic(true),
|
||||
)
|
||||
.on_press(Message::SeekRelative(10.0))
|
||||
} else {
|
||||
widget::button::icon(
|
||||
widget::icon::from_name("media-skip-forward-symbolic").size(16),
|
||||
)
|
||||
.on_press(Message::PlayNext)
|
||||
},
|
||||
);
|
||||
|
||||
row = row.push(widget::tooltip(
|
||||
widget::button::icon(
|
||||
widget::icon::from_name(match self.flags.config_state.player_state.repeat {
|
||||
|
|
|
|||
|
|
@ -150,12 +150,12 @@ impl RootInterface for Player {
|
|||
impl PlayerInterface for Player {
|
||||
async fn next(&self) -> fdo::Result<()> {
|
||||
log::info!("Next");
|
||||
Ok(())
|
||||
self.message(Message::PlayNext).await
|
||||
}
|
||||
|
||||
async fn previous(&self) -> fdo::Result<()> {
|
||||
log::info!("Previous");
|
||||
Ok(())
|
||||
self.message(Message::PlayPrev).await
|
||||
}
|
||||
|
||||
async fn pause(&self) -> fdo::Result<()> {
|
||||
|
|
@ -271,12 +271,12 @@ impl PlayerInterface for Player {
|
|||
|
||||
async fn can_go_next(&self) -> fdo::Result<bool> {
|
||||
log::info!("CanGoNext");
|
||||
Ok(false)
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn can_go_previous(&self) -> fdo::Result<bool> {
|
||||
log::info!("CanGoPrevious");
|
||||
Ok(false)
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn can_play(&self) -> fdo::Result<bool> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue