added path searching and standard message types
This commit is contained in:
parent
7257db9c9a
commit
36530b8b22
5 changed files with 182 additions and 107 deletions
|
@ -1,8 +1,7 @@
|
|||
use derive_more::From;
|
||||
use rusqlite::{params, Connection, Result};
|
||||
|
||||
use crate::file_operations::ItemTag;
|
||||
use crate::server_handling::PartialTag;
|
||||
use crate::message_types::{ItemTag, PartialTag};
|
||||
|
||||
/// Catch all Error for database creation errors
|
||||
#[derive(From, Debug)]
|
||||
|
@ -16,6 +15,22 @@ pub struct DatabaseRequest {
|
|||
pub search_tag: PartialTag,
|
||||
}
|
||||
|
||||
impl SearchType {
|
||||
pub fn is_where(self: &Self) -> bool {
|
||||
match self {
|
||||
SearchType::Where => true,
|
||||
SearchType::Like => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_like(self: &Self) -> bool {
|
||||
match self {
|
||||
SearchType::Where => false,
|
||||
SearchType::Like => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SearchType {
|
||||
Where,
|
||||
Like,
|
||||
|
@ -114,38 +129,54 @@ impl DBObject {
|
|||
|
||||
let mut conditions = Vec::<String>::new();
|
||||
|
||||
let does_have_wild = if request.search_type.is_like() {
|
||||
("'%", "%'")
|
||||
} else {
|
||||
("'", "'")
|
||||
};
|
||||
|
||||
if request.search_tag.has_path() {
|
||||
conditions.push(format!(
|
||||
"path = '{}'",
|
||||
request.search_tag.path.clone().unwrap()
|
||||
"path = {}{}{}",
|
||||
does_have_wild.0,
|
||||
request.search_tag.path.clone().unwrap(),
|
||||
does_have_wild.1,
|
||||
));
|
||||
}
|
||||
|
||||
if request.search_tag.has_title() {
|
||||
conditions.push(format!(
|
||||
"title = '{}'",
|
||||
request.search_tag.title.clone().unwrap()
|
||||
"title = {}{}{}",
|
||||
does_have_wild.0,
|
||||
request.search_tag.title.clone().unwrap(),
|
||||
does_have_wild.1,
|
||||
));
|
||||
}
|
||||
|
||||
if request.search_tag.has_artist() {
|
||||
conditions.push(format!(
|
||||
"artist = '{}'",
|
||||
request.search_tag.artist.clone().unwrap()
|
||||
"artist = {}{}{}",
|
||||
does_have_wild.0,
|
||||
request.search_tag.artist.clone().unwrap(),
|
||||
does_have_wild.1,
|
||||
));
|
||||
}
|
||||
|
||||
if request.search_tag.has_album() {
|
||||
conditions.push(format!(
|
||||
"album = '{}'",
|
||||
request.search_tag.album.clone().unwrap()
|
||||
"album = {}{}{}",
|
||||
does_have_wild.0,
|
||||
request.search_tag.album.clone().unwrap(),
|
||||
does_have_wild.1,
|
||||
));
|
||||
}
|
||||
|
||||
if request.search_tag.has_album_artist() {
|
||||
conditions.push(format!(
|
||||
"album_artist = '{}'",
|
||||
request.search_tag.album_artist.clone().unwrap()
|
||||
"album_artist = {}{}{}",
|
||||
does_have_wild.0,
|
||||
request.search_tag.album_artist.clone().unwrap(),
|
||||
does_have_wild.1,
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use id3::{Tag, TagLike};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use scan_dir::ScanDir;
|
||||
|
||||
use crate::message_types::{ItemTag};
|
||||
|
||||
const SUPPORTED_FILETYPES: [&str; 1] = ["mp3"];
|
||||
|
||||
/// The object that iteratively and recursively scans the directories
|
||||
|
@ -77,27 +78,6 @@ impl Iterator for MusicScanner {
|
|||
}
|
||||
}
|
||||
|
||||
/// A struct that defines all the music tags supported by Sousa
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ItemTag {
|
||||
pub path: String,
|
||||
pub title: String,
|
||||
pub artist: String,
|
||||
pub album: String,
|
||||
pub album_artist: String,
|
||||
}
|
||||
|
||||
impl ItemTag {
|
||||
pub fn new() -> Self {
|
||||
ItemTag {
|
||||
path: String::new(),
|
||||
title: String::new(),
|
||||
artist: String::new(),
|
||||
album: String::new(),
|
||||
album_artist: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the music information from a filepath
|
||||
pub fn get_tag(filepath: &PathBuf) -> Result<ItemTag, id3::Error> {
|
||||
|
|
36
src/main.rs
36
src/main.rs
|
@ -1,5 +1,4 @@
|
|||
use rodio::{Decoder, OutputStream, Sink};
|
||||
use server_handling::UIRequest;
|
||||
use std::io::BufReader;
|
||||
use std::net::TcpStream;
|
||||
use std::path::PathBuf;
|
||||
|
@ -11,11 +10,13 @@ use clap::Parser;
|
|||
use dirs_next;
|
||||
|
||||
use crate::db_operations::DatabaseRequest;
|
||||
use crate::server_handling::PartialTag;
|
||||
|
||||
pub mod db_operations;
|
||||
pub mod file_operations;
|
||||
pub mod server_handling;
|
||||
pub mod message_types;
|
||||
|
||||
use crate::message_types::{PartialTag, ServerResponse, UIRequest};
|
||||
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about=None)]
|
||||
|
@ -74,7 +75,7 @@ fn main() {
|
|||
}
|
||||
|
||||
let test_tag = PartialTag {
|
||||
title: Some("%bees%".to_string()),
|
||||
title: Some("bees".to_string()),
|
||||
..PartialTag::default()
|
||||
};
|
||||
|
||||
|
@ -124,7 +125,32 @@ fn main() {
|
|||
UIRequest::Play => sink.play(),
|
||||
UIRequest::Pause => sink.pause(),
|
||||
UIRequest::Skip(skip_direction) => todo!(),
|
||||
UIRequest::GetList(request) => todo!(),
|
||||
UIRequest::Search(request) => {
|
||||
println!("got a: {:?}", request);
|
||||
let items = dbo
|
||||
.get(&DatabaseRequest {
|
||||
search_type: db_operations::SearchType::Like,
|
||||
search_tag: request,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
match items {
|
||||
None => sockets[i].write_message("None".into()).unwrap(),
|
||||
Some(items) => {
|
||||
sockets[i]
|
||||
.write_message(
|
||||
serde_json::to_string(&ServerResponse {
|
||||
search_results: items,
|
||||
})
|
||||
.unwrap()
|
||||
.into(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
//println!("got from db: {:?}", items);
|
||||
}
|
||||
UIRequest::SwitchTo(partial_tag) => todo!(),
|
||||
UIRequest::GetStatus => todo!(),
|
||||
},
|
||||
|
|
95
src/message_types.rs
Normal file
95
src/message_types.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A struct that defines all the music tags supported by Sousa
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ItemTag {
|
||||
pub path: String,
|
||||
pub title: String,
|
||||
pub artist: String,
|
||||
pub album: String,
|
||||
pub album_artist: String,
|
||||
}
|
||||
|
||||
impl Default for ItemTag {
|
||||
fn default() -> Self {
|
||||
ItemTag {
|
||||
path: String::new(),
|
||||
title: String::new(),
|
||||
artist: String::new(),
|
||||
album: String::new(),
|
||||
album_artist: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct PartialTag {
|
||||
pub path: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub artist: Option<String>,
|
||||
pub album: Option<String>,
|
||||
pub album_artist: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for PartialTag {
|
||||
fn default() -> Self {
|
||||
PartialTag {
|
||||
path: None,
|
||||
title: None,
|
||||
artist: None,
|
||||
album: None,
|
||||
album_artist: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialTag {
|
||||
pub fn has_path(self: &Self) -> bool {
|
||||
self.path.is_some()
|
||||
}
|
||||
|
||||
pub fn has_title(self: &Self) -> bool {
|
||||
self.title.is_some()
|
||||
}
|
||||
|
||||
pub fn has_artist(self: &Self) -> bool {
|
||||
self.artist.is_some()
|
||||
}
|
||||
|
||||
pub fn has_album(self: &Self) -> bool {
|
||||
self.album.is_some()
|
||||
}
|
||||
|
||||
pub fn has_album_artist(self: &Self) -> bool {
|
||||
self.album_artist.is_some()
|
||||
}
|
||||
|
||||
pub fn is_empty(self: &Self) -> bool {
|
||||
return self.path.is_none()
|
||||
&& self.title.is_none()
|
||||
&& self.artist.is_none()
|
||||
&& self.album.is_none()
|
||||
&& self.album_artist.is_none();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct ServerResponse {
|
||||
pub search_results: Vec<ItemTag>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum SkipDirection {
|
||||
Forward,
|
||||
Backward,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum UIRequest {
|
||||
Play,
|
||||
Pause,
|
||||
Skip(SkipDirection),
|
||||
Search(PartialTag),
|
||||
SwitchTo(PartialTag),
|
||||
GetStatus,
|
||||
}
|
|
@ -1,74 +1,17 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct PartialTag {
|
||||
pub path: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub artist: Option<String>,
|
||||
pub album: Option<String>,
|
||||
pub album_artist: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for PartialTag {
|
||||
fn default() -> Self {
|
||||
PartialTag {
|
||||
path: None,
|
||||
title: None,
|
||||
artist: None,
|
||||
album: None,
|
||||
album_artist: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialTag {
|
||||
pub fn has_path(self: &Self) -> bool {
|
||||
self.path.is_some()
|
||||
}
|
||||
|
||||
pub fn has_title(self: &Self) -> bool {
|
||||
self.title.is_some()
|
||||
}
|
||||
|
||||
pub fn has_artist(self: &Self) -> bool {
|
||||
self.artist.is_some()
|
||||
}
|
||||
|
||||
pub fn has_album(self: &Self) -> bool {
|
||||
self.album.is_some()
|
||||
}
|
||||
|
||||
pub fn has_album_artist(self: &Self) -> bool {
|
||||
self.album_artist.is_some()
|
||||
}
|
||||
|
||||
pub fn is_empty(self: &Self) -> bool {
|
||||
return self.path.is_none()
|
||||
&& self.title.is_none()
|
||||
&& self.artist.is_none()
|
||||
&& self.album.is_none()
|
||||
&& self.album_artist.is_none();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum SkipDirection {
|
||||
Forward,
|
||||
Backward,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum UIRequest {
|
||||
Play,
|
||||
Pause,
|
||||
Skip(SkipDirection),
|
||||
GetList(String),
|
||||
SwitchTo(PartialTag),
|
||||
GetStatus,
|
||||
}
|
||||
use crate::message_types::{UIRequest};
|
||||
|
||||
/// Pass a
|
||||
pub fn handle_request(socket_message: String) -> Result<UIRequest, serde_json::Error> {
|
||||
println!("Recieved a socket message: {}", socket_message);
|
||||
let request: UIRequest = serde_json::from_str(&socket_message)?;
|
||||
|
||||
Ok(request)
|
||||
}
|
||||
|
||||
fn sanitize_input(input: UIRequest) -> Result<UIRequest, ()> {
|
||||
// if UIRequest is a search string, make sure it is
|
||||
// not empty
|
||||
// has no %, this is a fuzzy search, This program handles that, maybe replace * with %
|
||||
// has a type of request (e.g. "title search: value")
|
||||
Ok(UIRequest::Pause)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue