Skip to content

Commit

Permalink
Playback implementation, closes #21 and closes #19
Browse files Browse the repository at this point in the history
  • Loading branch information
LaineZ committed Nov 2, 2020
1 parent 74b1af1 commit b238851
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 33 deletions.
8 changes: 5 additions & 3 deletions src/bc_core/album_parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,20 @@ pub fn get_album(url: &str) -> Option<Album> {
file.write_all(json.as_bytes()).unwrap();
*/

log::info!("{}", json);

let data: Album = serde_json::from_str(&json).unwrap();

Some(data)
}

pub fn parse(html_code: &str) -> Option<String> {
let start = "var TralbumData = {";
let stop = "};";
let start = "data-tralbum=\"{";
let stop = "}\"";

let album_data = &html_code[html_code.find(start)? + start.len() - 1..];
let album_data = &album_data[..=album_data.find(stop)?];
let album_data_json = fix_json(album_data);
let album_data_json = fix_json(&album_data.replace("&quot;", "\""));
Some(album_data_json)
}

Expand Down
15 changes: 12 additions & 3 deletions src/bc_core/queue.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use core::fmt;
use std::{fmt::Display, time::Duration};

use super::album_parsing;

#[derive(Clone)]
Expand All @@ -7,7 +10,7 @@ pub struct QueuedTrack {
pub album: String,
pub audio_url: String,
pub album_url: String,
pub duration: f64,
pub duration: Duration,
}

impl Default for QueuedTrack {
Expand All @@ -18,11 +21,17 @@ impl Default for QueuedTrack {
audio_url: String::new(),
album: String::new(),
album_url: String::new(),
duration: 0.0,
duration: Duration::from_secs(0),
}
}
}

impl Display for QueuedTrack {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} - {}", self.artist, self.title)
}
}

pub struct Queue<'a> {
pub queue: Vec<QueuedTrack>,
pub shuffle: bool,
Expand Down Expand Up @@ -98,7 +107,7 @@ impl<'a> Queue<'a> {
// TODO: switch to normal error-handling and not this garbage that panic...
audio_url: album_track.file.unwrap().mp3128,
album_url: album_url.mp3128,
duration: album_track.duration.unwrap_or(0.0),
duration: Duration::from_secs_f64(album_track.duration.unwrap_or(0.0)),
};
self.queue.push(pushed_track.clone());
}
Expand Down
11 changes: 5 additions & 6 deletions src/bop_interfaces/listbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ pub struct ListBox {
pub position: usize,
pub screen: Screen,
pub focused: bool,
pub description: String,
}

impl ListBox {
pub fn new(w: u16, h: u16, focused: bool) -> Self {
pub fn new<S: Into<String>>(w: u16, h: u16, focused: bool, description: S) -> Self {
Self {
display: Vec::new(),
page: 0,
position: 0,
screen: Screen::new_empty(w as u32, h as u32),
focused,
description: description.into()
}
}

Expand Down Expand Up @@ -58,11 +60,8 @@ impl ListBox {
self.screen.clear();
}

pub fn get_selected_item(&mut self, pos: usize) -> String {
self.display[(pos + (self.page * self.screen.get_height() as usize))
.checked_sub(1)
.unwrap_or(0)]
.clone()
pub fn get_selected_idx(&mut self) -> usize {
self.position + (self.page * self.screen.get_height() as usize)
}

pub fn remove(&mut self, value: String) {
Expand Down
4 changes: 2 additions & 2 deletions src/bop_interfaces/statebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl StateBar {

Self {
header_text: BASE_HEADER.to_string(),
bottom_text: String::from("Loading..."),
bottom_text: String::from("Nothing playing..."),
error: false,
screen: Screen::new(cols.into(), 2),
y: (rows as u32) - 2,
Expand All @@ -33,7 +33,7 @@ impl StateBar {

pub fn information<T: Display>(&mut self, item: &T) {
self.error = false;
self.header_text = item.to_string();
self.header_text = format!("{}{}", BASE_HEADER, item.to_string());
}

pub fn draw(&mut self) -> &Screen {
Expand Down
95 changes: 78 additions & 17 deletions src/bop_interfaces/tui.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use std::time::Duration;
use std::{
sync::{Arc, Mutex},
time::Duration,
};

use crate::bc_core::{playback::Player, queue::Queue};

use super::{listbox::ListBox, tui_structs::State, statebar::StateBar};
use super::{listbox::ListBox, statebar::StateBar, tui_structs::State};
use console_engine::{
crossterm::{
event::{self, read},
Expand All @@ -11,20 +16,20 @@ use console_engine::{

const LIST_TAGS: usize = 0;
const LIST_DISCOVER: usize = 1;
const LIST_QUEUE: usize = 3;

const LIST_QUEUE: usize = 2;

fn setup_focus_at(id: usize, lbx: &mut Vec<ListBox>) {
fn setup_focus_at(id: usize, lbx: &mut Vec<ListBox>, bar: &mut StateBar) {
for list in lbx.iter_mut() {
list.focused = false;
}
lbx[id].focused = true;
bar.information(&lbx[id].description);
}

fn get_focus_at(lbx: &mut Vec<ListBox>) -> usize {
for (id, list) in lbx.iter_mut().enumerate() {
if list.focused {
return id
return id;
}
}
0
Expand All @@ -41,13 +46,22 @@ pub fn loadinterface(_args: Vec<String>) -> Result<(), Box<dyn std::error::Error
let mut debug_overlay = false;

let mut listboxes = Vec::new();
listboxes.push(ListBox::new(cols, rows, true));
listboxes.push(ListBox::new(cols, rows, false));
listboxes.push(ListBox::new(cols, rows, false));
listboxes.push(ListBox::new(cols, rows, true, "Tags"));
listboxes.push(ListBox::new(cols, rows, false, "Discover"));
listboxes.push(ListBox::new(cols, rows, false, "Play queue"));
listboxes[LIST_TAGS].display.extend(tags);

let mut player = Arc::new(Mutex::new(Player::new()));

let mut state = State::new();
let mut bar = StateBar::new();

let player_box = player.clone();
let mut queue = Queue::new(Box::new(move |track| {
player_box.try_lock().unwrap().switch_track(track.audio_url);
player_box.try_lock().unwrap().play();
}));

let mut engine = console_engine::ConsoleEngine::init(cols as u32, rows as u32, 30);

loop {
Expand All @@ -62,7 +76,16 @@ pub fn loadinterface(_args: Vec<String>) -> Result<(), Box<dyn std::error::Error
engine.print_screen(0, bar.y as i32, bar.draw());

if debug_overlay {
engine.print(1, 1, format!("Terminal size: {}x{}", engine.get_width(), engine.get_height()).as_str());
engine.print(
1,
1,
format!(
"Terminal size: {}x{}",
engine.get_width(),
engine.get_height()
)
.as_str(),
);
}

engine.draw();
Expand Down Expand Up @@ -99,34 +122,51 @@ pub fn loadinterface(_args: Vec<String>) -> Result<(), Box<dyn std::error::Error
if engine.is_key_pressed(KeyCode::Enter) {
log::info!("Enter pressed");
if listboxes[LIST_TAGS].focused {

state.selected_tags.push(listboxes[LIST_TAGS].get_selected_str());
state
.selected_tags
.push(listboxes[LIST_TAGS].get_selected_str());

state.extend_discover()?;
for data in state.discover.iter_mut() {
listboxes[LIST_DISCOVER]
.display
.push(format!("{} - {}", data.artist, data.title))
}
setup_focus_at(LIST_DISCOVER, &mut listboxes, &mut bar);
}

if listboxes[LIST_DISCOVER].focused {
let artist = state.discover[listboxes[LIST_DISCOVER].get_selected_idx()]
.artist
.clone();
let url = state.discover[listboxes[LIST_DISCOVER].get_selected_idx()]
.tralbum_url
.clone();
queue.add_album_in_queue(artist, url.as_str()).unwrap();

for data in queue.queue.iter_mut() {
listboxes[LIST_QUEUE].display.push(data.to_string())
}
}

setup_focus_at(LIST_DISCOVER, &mut listboxes);
if listboxes[LIST_QUEUE].focused {
queue.set(listboxes[LIST_QUEUE].get_selected_idx());
}
}

if engine.is_key_pressed(KeyCode::Tab) {
let switch = get_focus_at(&mut listboxes) + 1;
if switch > listboxes.len() - 1 {
setup_focus_at(LIST_TAGS, &mut listboxes);
setup_focus_at(LIST_TAGS, &mut listboxes, &mut bar);
} else {
setup_focus_at(switch, &mut listboxes);
setup_focus_at(switch, &mut listboxes, &mut bar);
}
}

if engine.is_key_pressed(KeyCode::F(1)) {
debug_overlay =! debug_overlay;
debug_overlay = !debug_overlay;
}


match engine.get_resize() {
Some((width, height)) => {
for list in listboxes.iter_mut() {
Expand All @@ -137,6 +177,27 @@ pub fn loadinterface(_args: Vec<String>) -> Result<(), Box<dyn std::error::Error

None => {}
}

// TODO: change this
match player.clone().try_lock().unwrap().get_time() {
Some(time) => {
if time
>= queue
.get_current_track()
.ok_or_else(|| {
bar.error(&"Queue is empty!".to_string());
})
.unwrap()
.duration
{
queue.next().unwrap();
}
}

None => {
// TODO: Loading
}
}
}
Ok(())
}
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}

match args[1].as_str() {
"cli" => tui::loadinterface(args)?,
"tui" => tui::loadinterface(args)?,
_ => {
eprintln!("error: Invalid arguments supplyed. Exiting");
println!("Allowed options:");
println!("cli - TUI player mode");
println!("tui - TUI player mode");
}
}
Ok(())
Expand Down

0 comments on commit b238851

Please sign in to comment.