Add seeking

This commit is contained in:
KoffeinFlummi
2019-03-25 18:29:00 +01:00
parent 992be7c502
commit e6a7d8a693
6 changed files with 130 additions and 7 deletions

View File

@@ -297,6 +297,28 @@ impl CommandManager {
}),
);
}
{
let spotify = spotify.clone();
self.register(
"seek",
Vec::new(),
Box::new(move |_s, args| {
if let Some(arg) = args.get(0) {
match arg.chars().next().unwrap() {
'+' | '-' => {
spotify.seek_relative(arg.parse::<i32>().unwrap_or(0));
},
_ => {
spotify.seek(arg.parse::<u32>().unwrap_or(0));
}
}
}
Ok(None)
}),
);
}
}
fn handle_aliases(&self, name: &String) -> String {
@@ -308,7 +330,7 @@ impl CommandManager {
}
pub fn handle(&self, s: &mut Cursive, cmd: String) {
let components: Vec<String> = cmd.split(' ').map(|s| s.to_string()).collect();
let components: Vec<String> = cmd.trim().split(' ').map(|s| s.to_string()).collect();
let result = if let Some(cb) = self.commands.get(&self.handle_aliases(&components[0])) {
cb(s, components[1..].to_vec())
@@ -363,6 +385,8 @@ impl CommandManager {
kb.insert("Enter".into(), "play selected".into());
kb.insert("d".into(), "delete selected".into());
kb.insert("/".into(), "search".into());
kb.insert(".".into(), "seek +500".into());
kb.insert(",".into(), "seek -500".into());
kb.insert("F1".into(), "queue".into());
kb.insert("F2".into(), "search".into());

View File

@@ -35,7 +35,7 @@ fn get_metadata(queue: Arc<Queue>) -> HashMap<String, Variant<Box<RefArg>>> {
);
hm.insert(
"mpris:length".to_string(),
Variant(Box::new(track.map(|t| t.duration * 1_000_000).unwrap_or(0))),
Variant(Box::new(track.map(|t| t.duration * 1_000).unwrap_or(0))),
);
hm.insert(
"mpris:artUrl".to_string(),

View File

@@ -40,6 +40,7 @@ enum WorkerCommand {
Play,
Pause,
Stop,
Seek(u32),
RequestToken(oneshot::Sender<Token>),
}
@@ -135,6 +136,9 @@ impl futures::Future for Worker {
self.events.send(Event::Player(PlayerEvent::Stopped));
self.active = false;
}
WorkerCommand::Seek(pos) => {
self.player.seek(pos);
}
WorkerCommand::RequestToken(sender) => {
self.token_task = Spotify::get_token(&self.session, sender);
progress = true;
@@ -499,4 +503,21 @@ impl Spotify {
info!("stop()");
self.channel.unbounded_send(WorkerCommand::Stop).unwrap();
}
pub fn seek(&self, position_ms: u32) {
self.set_elapsed(Some(Duration::from_millis(position_ms.into())));
self.set_since(if self.get_current_status() == PlayerEvent::Playing {
Some(SystemTime::now())
} else {
None
});
self.channel.unbounded_send(WorkerCommand::Seek(position_ms)).unwrap();
}
pub fn seek_relative(&self, delta: i32) {
let progress = self.get_current_progress();
let new = (progress.as_secs() * 1000) as i32 + progress.subsec_millis() as i32 + delta;
self.seek(std::cmp::max(0, new) as u32);
}
}

View File

@@ -44,7 +44,7 @@ impl Track {
title: track.name.clone(),
track_number: track.track_number,
disc_number: track.disc_number,
duration: track.duration_ms / 1000,
duration: track.duration_ms,
artists: artists,
album: track.album.name.clone(),
album_artists: album_artists,
@@ -54,8 +54,8 @@ impl Track {
}
pub fn duration_str(&self) -> String {
let minutes = self.duration / 60;
let seconds = self.duration % 60;
let minutes = self.duration / 60_000;
let seconds = (self.duration / 1000) % 60;
format!("{:02}:{:02}", minutes, seconds)
}
}

View File

@@ -29,6 +29,7 @@ pub struct Layout {
error: Option<String>,
error_time: Option<SystemTime>,
screenchange: bool,
last_size: Vec2,
ev: events::EventManager,
theme: Theme,
}
@@ -49,8 +50,9 @@ impl Layout {
cmdline_focus: false,
error: None,
error_time: None,
ev: ev.clone(),
screenchange: true,
last_size: Vec2::new(0, 0),
ev: ev.clone(),
theme: theme,
}
}
@@ -166,6 +168,30 @@ impl View for Layout {
}
fn on_event(&mut self, event: Event) -> EventResult {
if let Event::Mouse {
position,
..
} = event {
let error = self.get_error();
let cmdline_visible = self.cmdline.get_content().len() > 0;
let mut cmdline_height = if cmdline_visible { 1 } else { 0 };
if error.is_some() {
cmdline_height += 1;
}
if position.y < self.last_size.y - 2 - cmdline_height {
if let Some(ref id) = self.focus {
let screen = self.views.get_mut(id).unwrap();
screen.view.on_event(event.clone());
}
} else if position.y < self.last_size.y - cmdline_height {
self.statusbar.on_event(event.relativized(Vec2::new(0, self.last_size.y - 2 - cmdline_height)));
}
return EventResult::Consumed(None);
}
if self.cmdline_focus {
return self.cmdline.on_event(event);
}
@@ -179,6 +205,10 @@ impl View for Layout {
}
fn layout(&mut self, size: Vec2) {
self.last_size = size;
self.statusbar.layout(Vec2::new(size.x, 2));
self.cmdline.layout(Vec2::new(size.x, 1));
if let Some(ref id) = self.focus {

View File

@@ -1,6 +1,7 @@
use std::sync::Arc;
use cursive::align::HAlign;
use cursive::event::{Event, EventResult, MouseButton, MouseEvent};
use cursive::theme::{ColorStyle, ColorType, PaletteColor};
use cursive::traits::View;
use cursive::vec::Vec2;
@@ -13,6 +14,7 @@ use spotify::{PlayerEvent, Spotify};
pub struct StatusBar {
queue: Arc<Queue>,
spotify: Arc<Spotify>,
last_size: Vec2,
}
impl StatusBar {
@@ -20,6 +22,7 @@ impl StatusBar {
StatusBar {
queue: queue,
spotify: spotify,
last_size: Vec2::new(0, 0),
}
}
}
@@ -63,6 +66,8 @@ impl View for StatusBar {
if let Some(ref t) = self.queue.get_current() {
let elapsed = self.spotify.get_current_progress();
let elapsed_ms = elapsed.as_secs() as u32 * 1000 + elapsed.subsec_millis();
let formatted_elapsed = format!(
"{:02}:{:02}",
elapsed.as_secs() / 60,
@@ -80,7 +85,7 @@ impl View for StatusBar {
printer.with_color(style_bar, |printer| {
printer.print((0, 0), &"".repeat(printer.size.x));
let duration_width =
(((printer.size.x as u32) * (elapsed.as_secs() as u32)) / t.duration) as usize;
(((printer.size.x as u32) * elapsed_ms) / t.duration) as usize;
printer.print((0, 0), &format!("{}{}", "=".repeat(duration_width), ">"));
});
} else {
@@ -90,7 +95,50 @@ impl View for StatusBar {
}
}
fn layout(&mut self, size: Vec2) {
self.last_size = size;
}
fn required_size(&mut self, constraint: Vec2) -> Vec2 {
Vec2::new(constraint.x, 2)
}
fn on_event(&mut self, event: Event) -> EventResult {
if let Event::Mouse {
offset,
position,
event
} = event {
let position = position - offset;
if position.y == 0 {
if event == MouseEvent::WheelUp {
self.spotify.seek_relative(-500);
}
if event == MouseEvent::WheelDown {
self.spotify.seek_relative(500);
}
if event == MouseEvent::Press(MouseButton::Left) ||
event == MouseEvent::Hold(MouseButton::Left)
{
if let Some(ref t) = self.queue.get_current() {
let f: f32 = position.x as f32 / self.last_size.x as f32;
let new = t.duration as f32 * f;
self.spotify.seek(new as u32);
}
}
} else {
if event == MouseEvent::Press(MouseButton::Left) {
self.queue.toggleplayback();
}
}
EventResult::Consumed(None)
} else {
EventResult::Ignored
}
}
}