mirror of
https://github.com/tsirysndr/music-player.git
synced 2026-01-08 20:58:07 -05:00
feat: add scan subcommand
This commit is contained in:
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -1551,9 +1551,12 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
|
||||
|
||||
[[package]]
|
||||
name = "music-player"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"futures",
|
||||
"lofty",
|
||||
"md5",
|
||||
"music-player-addons",
|
||||
"music-player-entity",
|
||||
"music-player-migration",
|
||||
@@ -1563,6 +1566,8 @@ dependencies = [
|
||||
"music-player-settings",
|
||||
"music-player-storage",
|
||||
"music-player-tracklist",
|
||||
"owo-colors",
|
||||
"sea-orm",
|
||||
"sea-orm-migration",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "music-player"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/tsirysndr/music-player"
|
||||
license = "MIT"
|
||||
@@ -69,3 +69,8 @@ features = [
|
||||
[dependencies]
|
||||
clap = "3.2.20"
|
||||
tokio = { version = "1.21.0", features = ["full"] }
|
||||
md5 = "0.7.0"
|
||||
sea-orm = { version = "0.9.2", features = ["runtime-tokio-rustls", "sqlx-sqlite"] }
|
||||
futures = "0.3.24"
|
||||
lofty = "0.8.1"
|
||||
owo-colors = "3.5.0"
|
||||
|
||||
@@ -29,6 +29,10 @@ Note: This is a work in progress.
|
||||
|
||||
This is a simple music player that I made for my own use. It is written in Rust and uses [rodio](https://github.com/RustAudio/rodio), [symphonia](https://github.com/pdeljanov/Symphonia), and [gRPC](https://grpc.io/) libraries.
|
||||
|
||||
<p style="margin-top: 20px; margin-bottom: 20px;">
|
||||
<img src="./preview.svg" width="800" />
|
||||
</p>
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
|
||||
1
preview.svg
Normal file
1
preview.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 371 KiB |
@@ -7,8 +7,11 @@ use music_player_playback::{
|
||||
player::{Player, PlayerEngine},
|
||||
};
|
||||
use music_player_server::server::MusicPlayerServer;
|
||||
use scan::scan_music_library;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
mod scan;
|
||||
|
||||
fn cli() -> Command<'static> {
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
Command::new("music-player")
|
||||
@@ -30,6 +33,7 @@ A simple music player written in Rust"#,
|
||||
.about("Play a song")
|
||||
.arg_from_usage("<song> 'The path to the song'"),
|
||||
)
|
||||
.subcommand(Command::new("scan").about("Scan music library: $HOME/Music"))
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@@ -50,6 +54,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(_matches) = matches.subcommand_matches("scan") {
|
||||
scan_music_library().await.map_err(|e| e.to_string())?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
migration::run().await;
|
||||
|
||||
MusicPlayerServer::new(Arc::new(Mutex::new(player)))
|
||||
|
||||
72
src/scan.rs
Normal file
72
src/scan.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use futures::future::FutureExt;
|
||||
use music_player_entity::{album, artist, track};
|
||||
use music_player_scanner::scan_directory;
|
||||
use music_player_scanner::types::Song;
|
||||
use owo_colors::OwoColorize;
|
||||
use sea_orm::{ActiveModelTrait, ActiveValue};
|
||||
|
||||
pub async fn scan_music_library() -> Result<Vec<Song>, lofty::error::LoftyError> {
|
||||
scan_directory(move |song, db| {
|
||||
async move {
|
||||
let id = format!("{:x}", md5::compute(song.artist.to_string()));
|
||||
let item = artist::ActiveModel {
|
||||
id: ActiveValue::set(id),
|
||||
name: ActiveValue::Set(song.artist.clone()),
|
||||
};
|
||||
match item.insert(db.get_connection()).await {
|
||||
Ok(_) => (),
|
||||
Err(_) => (),
|
||||
}
|
||||
|
||||
let id = format!(
|
||||
"{:x}",
|
||||
md5::compute(format!("{}{}", song.album, song.artist))
|
||||
);
|
||||
let item = album::ActiveModel {
|
||||
id: ActiveValue::set(id),
|
||||
title: ActiveValue::Set(song.album.clone()),
|
||||
artist: ActiveValue::Set(song.artist.clone()),
|
||||
artist_id: ActiveValue::Set(Some(format!(
|
||||
"{:x}",
|
||||
md5::compute(song.artist.to_string())
|
||||
))),
|
||||
};
|
||||
match item.insert(db.get_connection()).await {
|
||||
Ok(_) => (),
|
||||
Err(_) => (),
|
||||
}
|
||||
let id = format!("{:x}", md5::compute(song.uri.as_ref().unwrap()));
|
||||
let item = track::ActiveModel {
|
||||
id: ActiveValue::set(id),
|
||||
title: ActiveValue::Set(song.title.clone()),
|
||||
artist: ActiveValue::Set(song.artist.clone()),
|
||||
album: ActiveValue::Set(song.album.clone()),
|
||||
genre: ActiveValue::Set(song.genre.clone()),
|
||||
year: ActiveValue::Set(song.year),
|
||||
track: ActiveValue::Set(song.track),
|
||||
bitrate: ActiveValue::Set(song.bitrate),
|
||||
sample_rate: ActiveValue::Set(song.sample_rate),
|
||||
bit_depth: ActiveValue::Set(song.bit_depth),
|
||||
channels: ActiveValue::Set(song.channels),
|
||||
duration: ActiveValue::Set(Some(song.duration.as_secs_f32())),
|
||||
uri: ActiveValue::Set(song.uri.clone().unwrap_or_default()),
|
||||
album_id: ActiveValue::Set(Some(format!(
|
||||
"{:x}",
|
||||
md5::compute(format!("{}{}", song.album, song.artist))
|
||||
))),
|
||||
};
|
||||
|
||||
let filename = song.uri.as_ref().unwrap().split("/").last().unwrap();
|
||||
let path = song.uri.as_ref().unwrap().replace(filename, "");
|
||||
|
||||
println!("{}{}", path, filename.magenta());
|
||||
|
||||
match item.insert(db.get_connection()).await {
|
||||
Ok(_) => (),
|
||||
Err(_) => (),
|
||||
}
|
||||
}
|
||||
.boxed()
|
||||
})
|
||||
.await
|
||||
}
|
||||
Reference in New Issue
Block a user