@@ -13,9 +13,12 @@ travis-ci = { repository = "hrkfdn/ncspot", branch = "master" }
|
|||||||
maintenance = { status = "experimental" }
|
maintenance = { status = "experimental" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
clap = "2.32.0"
|
||||||
|
chrono = "0.4"
|
||||||
crossbeam-channel = "0.3.8"
|
crossbeam-channel = "0.3.8"
|
||||||
directories = "1.0"
|
directories = "1.0"
|
||||||
failure = "0.1.3"
|
failure = "0.1.3"
|
||||||
|
fern = "0.5"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
log = "0.4.0"
|
log = "0.4.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ future. Contributions welcome, but please be kind ;)
|
|||||||
|
|
||||||
* Set your login credentials (see configuration)
|
* Set your login credentials (see configuration)
|
||||||
* Build using `cargo build --release`
|
* Build using `cargo build --release`
|
||||||
* The initial screen is the debug log. Press `F2` for the queue and `F3` to
|
* The initial screen is the debug log. Press `F1` for the queue and `F2` to
|
||||||
search for a track. More key bindings are described below.
|
search for a track. More key bindings are described below.
|
||||||
|
|
||||||
### Key Bindings
|
### Key Bindings
|
||||||
@@ -39,7 +39,6 @@ have them configurable.
|
|||||||
* `F3`: Playlists
|
* `F3`: Playlists
|
||||||
* `d` deletes the currently selected track
|
* `d` deletes the currently selected track
|
||||||
* `c` clears the entire playlist
|
* `c` clears the entire playlist
|
||||||
* `F9`: Debug log
|
|
||||||
* Tracks and playlists can be played using `Return` and queued using `Space`
|
* Tracks and playlists can be played using `Return` and queued using `Space`
|
||||||
* `Shift-p` toggles playback of a track
|
* `Shift-p` toggles playback of a track
|
||||||
* `Shift-s` stops a track
|
* `Shift-s` stops a track
|
||||||
|
|||||||
@@ -129,17 +129,6 @@ impl CommandManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.register(
|
|
||||||
"log",
|
|
||||||
Vec::new(),
|
|
||||||
Box::new(move |s, _args| {
|
|
||||||
s.call_on_id("main", |v: &mut Layout| {
|
|
||||||
v.set_view("log");
|
|
||||||
});
|
|
||||||
Ok(None)
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.register(
|
self.register(
|
||||||
"move",
|
"move",
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
@@ -365,7 +354,6 @@ impl CommandManager {
|
|||||||
kb.insert("F1".into(), "queue".into());
|
kb.insert("F1".into(), "queue".into());
|
||||||
kb.insert("F2".into(), "search".into());
|
kb.insert("F2".into(), "search".into());
|
||||||
kb.insert("F3".into(), "playlists".into());
|
kb.insert("F3".into(), "playlists".into());
|
||||||
kb.insert("F9".into(), "log".into());
|
|
||||||
|
|
||||||
kb.insert("Up".into(), "move up".into());
|
kb.insert("Up".into(), "move up".into());
|
||||||
kb.insert("Down".into(), "move down".into());
|
kb.insert("Down".into(), "move down".into());
|
||||||
|
|||||||
50
src/main.rs
50
src/main.rs
@@ -1,3 +1,4 @@
|
|||||||
|
extern crate clap;
|
||||||
extern crate crossbeam_channel;
|
extern crate crossbeam_channel;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate cursive;
|
extern crate cursive;
|
||||||
@@ -21,14 +22,15 @@ extern crate toml;
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
extern crate chrono;
|
||||||
|
extern crate fern;
|
||||||
|
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
|
use clap::{Arg, App};
|
||||||
use cursive::traits::Identifiable;
|
use cursive::traits::Identifiable;
|
||||||
use cursive::view::ScrollStrategy;
|
|
||||||
use cursive::views::*;
|
|
||||||
use cursive::Cursive;
|
use cursive::Cursive;
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
@@ -50,8 +52,45 @@ use events::{Event, EventManager};
|
|||||||
use playlists::Playlists;
|
use playlists::Playlists;
|
||||||
use spotify::PlayerEvent;
|
use spotify::PlayerEvent;
|
||||||
|
|
||||||
|
fn setup_logging(filename: &str) -> Result<(), fern::InitError> {
|
||||||
|
fern::Dispatch::new()
|
||||||
|
// Perform allocation-free log formatting
|
||||||
|
.format(|out, message, record| {
|
||||||
|
out.finish(format_args!(
|
||||||
|
"{} [{}] [{}] {}",
|
||||||
|
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
|
||||||
|
record.target(),
|
||||||
|
record.level(),
|
||||||
|
message
|
||||||
|
))
|
||||||
|
})
|
||||||
|
// Add blanket level filter -
|
||||||
|
.level(log::LevelFilter::Trace)
|
||||||
|
// - and per-module overrides
|
||||||
|
.level_for("librespot", log::LevelFilter::Debug)
|
||||||
|
// Output to stdout, files, and other Dispatch configurations
|
||||||
|
.chain(fern::log_file(filename)?)
|
||||||
|
// Apply globally
|
||||||
|
.apply()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
cursive::logger::init();
|
let matches = App::new("ncspot")
|
||||||
|
.version("0.1.0")
|
||||||
|
.author("Henrik Friedrichsen <henrik@affekt.org>")
|
||||||
|
.about("cross-platform ncurses Spotify client")
|
||||||
|
.arg(Arg::with_name("debug")
|
||||||
|
.short("d")
|
||||||
|
.long("debug")
|
||||||
|
.value_name("FILE")
|
||||||
|
.help("Enable debug logging to the specified file")
|
||||||
|
.takes_value(true))
|
||||||
|
.get_matches();
|
||||||
|
|
||||||
|
if let Some(filename) = matches.value_of("debug") {
|
||||||
|
setup_logging(filename).expect("can't setup logging");
|
||||||
|
}
|
||||||
|
|
||||||
// Things here may cause the process to abort; we must do them before creating curses windows
|
// Things here may cause the process to abort; we must do them before creating curses windows
|
||||||
// otherwise the error message will not be seen by a user
|
// otherwise the error message will not be seen by a user
|
||||||
@@ -74,8 +113,6 @@ fn main() {
|
|||||||
|
|
||||||
let theme = theme::load(&cfg);
|
let theme = theme::load(&cfg);
|
||||||
|
|
||||||
let logview = DebugView::new();
|
|
||||||
|
|
||||||
let mut cursive = Cursive::default();
|
let mut cursive = Cursive::default();
|
||||||
cursive.set_theme(theme.clone());
|
cursive.set_theme(theme.clone());
|
||||||
|
|
||||||
@@ -115,13 +152,10 @@ fn main() {
|
|||||||
|
|
||||||
let queueview = ui::queue::QueueView::new(queue.clone());
|
let queueview = ui::queue::QueueView::new(queue.clone());
|
||||||
|
|
||||||
let logview_scroller = ScrollView::new(logview).scroll_strategy(ScrollStrategy::StickToBottom);
|
|
||||||
|
|
||||||
let status = ui::statusbar::StatusBar::new(queue.clone(), spotify.clone());
|
let status = ui::statusbar::StatusBar::new(queue.clone(), spotify.clone());
|
||||||
|
|
||||||
let mut layout = ui::layout::Layout::new(status, &event_manager, theme)
|
let mut layout = ui::layout::Layout::new(status, &event_manager, theme)
|
||||||
.view("search", search.with_id("search"), "Search")
|
.view("search", search.with_id("search"), "Search")
|
||||||
.view("log", logview_scroller, "Debug Log")
|
|
||||||
.view("playlists", playlistsview, "Playlists")
|
.view("playlists", playlistsview, "Playlists")
|
||||||
.view("queue", queueview, "Queue");
|
.view("queue", queueview, "Queue");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user