small upd
This commit is contained in:
parent
a724560d58
commit
13bb433bfe
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -1284,8 +1284,8 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "itunesdb"
|
||||
version = "0.1.90"
|
||||
source = "git+https://gitea.awain.net/alterwain/ITunesDB.git#d37957a9a0b66577dadf3b305b02c72f1ca50a62"
|
||||
version = "0.1.95"
|
||||
source = "git+https://gitea.awain.net/alterwain/ITunesDB.git#2ecbe7666bf7c561c9ace767d2e4055e0d92127d"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"env_logger",
|
||||
@ -2349,8 +2349,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "soundcloud"
|
||||
version = "0.1.8"
|
||||
source = "git+https://gitea.awain.net/alterwain/soundcloud_api.git#656aef28f356411ff25cee14214ea0e677563537"
|
||||
version = "0.1.9"
|
||||
source = "git+https://gitea.awain.net/alterwain/soundcloud_api.git#a6732847bebbcb6e59a1b8a44a965fe7092af6e9"
|
||||
dependencies = [
|
||||
"hyper-util",
|
||||
"regex",
|
||||
|
@ -20,8 +20,8 @@ crossterm = { version = "0.28.1", features = ["event-stream"] }
|
||||
futures = "0.3"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-util = { version = "0.7.12", features = ["codec"] }
|
||||
soundcloud = { version = "0.1.8", git = "https://gitea.awain.net/alterwain/soundcloud_api.git" }
|
||||
itunesdb = { version = "0.1.90", git = "https://gitea.awain.net/alterwain/ITunesDB.git" }
|
||||
soundcloud = { version = "0.1.9", git = "https://gitea.awain.net/alterwain/soundcloud_api.git" }
|
||||
itunesdb = { version = "0.1.95", git = "https://gitea.awain.net/alterwain/ITunesDB.git" }
|
||||
rand = "0.8.5"
|
||||
tui-big-text = "0.7.1"
|
||||
throbber-widgets-tui = "0.8.0"
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
Lightweight iPod manager, batteries included.
|
||||
|
||||
#
|
||||
#
|
||||
|
||||
<div align="center">
|
||||
<img src=""/>
|
||||
<img src="https://w0n.zip/file/eZm8gd"/>
|
||||
<p>
|
||||
<small>Screenshot from MacOS Big Sur terminal</small>
|
||||
</p>
|
||||
@ -41,6 +41,5 @@ Lightweight iPod manager, batteries included.
|
||||
|
||||
## Todos
|
||||
|
||||
- Implement artwork integration
|
||||
- Implement youtube api
|
||||
- Implement albums generation
|
||||
- Implement manual playlist editing
|
||||
- Implement youtube api
|
@ -32,12 +32,6 @@ pub fn get_temp_itunesdb() -> PathBuf {
|
||||
p
|
||||
}
|
||||
|
||||
pub fn get_db() -> PathBuf {
|
||||
let mut p = get_configs_dir();
|
||||
p.push("data.redb");
|
||||
p
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct YouTubeConfiguration {
|
||||
pub user_id: u64,
|
||||
|
16
src/dlp.rs
16
src/dlp.rs
@ -1,7 +1,7 @@
|
||||
use std::{io, path::PathBuf, process::Stdio};
|
||||
|
||||
use ratatui::style::Color;
|
||||
use regex::Regex;
|
||||
use serde::Deserialize;
|
||||
use std::{io, path::PathBuf, process::Stdio};
|
||||
use tokio::{
|
||||
io::{AsyncBufReadExt, BufReader},
|
||||
process::Command,
|
||||
@ -59,11 +59,15 @@ pub async fn download_track_from_soundcloud(
|
||||
while let Ok(Some(line)) = reader.next_line().await {
|
||||
if line.starts_with("{") {
|
||||
let progress: DownloadProgress = serde_json::from_str(&line).unwrap();
|
||||
let _ = sender.send(AppEvent::OverallProgress((0, 1))).await;
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((0, 1, Color::Green)))
|
||||
.await;
|
||||
let _ = sender.send(AppEvent::CurrentProgress(progress)).await;
|
||||
}
|
||||
}
|
||||
let _ = sender.send(AppEvent::OverallProgress((1, 1))).await;
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((1, 1, Color::Green)))
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -114,7 +118,9 @@ pub async fn download_from_soundcloud(
|
||||
let s: Vec<&str> = s.split(' ').collect();
|
||||
let cur = s.first().unwrap().trim().parse().unwrap();
|
||||
let max = s.last().unwrap().trim().parse().unwrap();
|
||||
let _ = sender.send(AppEvent::OverallProgress((cur, max))).await;
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((cur, max, Color::Green)))
|
||||
.await;
|
||||
}
|
||||
None => {
|
||||
if line.starts_with("{") {
|
||||
|
@ -21,13 +21,30 @@ pub struct FileSystem {
|
||||
sender: UnboundedSender<AppEvent>,
|
||||
}
|
||||
|
||||
fn check_extension_compatibility(ext: &OsStr) -> bool {
|
||||
fn check_extension_compatibility(ext: &str) -> bool {
|
||||
matches!(
|
||||
ext.to_str().unwrap().to_lowercase().as_str(),
|
||||
ext.to_lowercase().as_str(),
|
||||
"mp3" | "m4a" | "wav" | "aiff" | "aif"
|
||||
)
|
||||
}
|
||||
|
||||
fn get_extension_from_filename(file_name: Option<&OsStr>) -> String {
|
||||
if let Some(fname) = file_name {
|
||||
let file_name = fname.to_str().unwrap();
|
||||
let index = file_name
|
||||
.chars()
|
||||
.enumerate()
|
||||
.filter(|(i, c)| *c == '.')
|
||||
.map(|(i, c)| i)
|
||||
.last();
|
||||
if let Some(index) = index {
|
||||
let extension: String = file_name.chars().skip(index).collect();
|
||||
return extension;
|
||||
}
|
||||
}
|
||||
"none".to_string()
|
||||
}
|
||||
|
||||
fn list_files_recursively(p: PathBuf) -> Vec<PathBuf> {
|
||||
let mut files = Vec::new();
|
||||
|
||||
@ -38,7 +55,14 @@ fn list_files_recursively(p: PathBuf) -> Vec<PathBuf> {
|
||||
continue;
|
||||
}
|
||||
let a = path.unwrap().path();
|
||||
if a.is_file() && check_extension_compatibility(a.extension().unwrap()) {
|
||||
if a.is_file()
|
||||
&& check_extension_compatibility(
|
||||
a.extension()
|
||||
.map_or(&get_extension_from_filename(a.file_name()), |s| {
|
||||
s.to_str().unwrap()
|
||||
}),
|
||||
)
|
||||
{
|
||||
files.push(a.clone());
|
||||
}
|
||||
if a.is_dir() {
|
||||
@ -130,10 +154,9 @@ impl FileSystem {
|
||||
let mut dir = paths
|
||||
.filter_map(|res| res.ok())
|
||||
.filter(|p| {
|
||||
p.path()
|
||||
.extension()
|
||||
.map_or(false, check_extension_compatibility)
|
||||
|| p.path().is_dir()
|
||||
p.path().extension().map_or(false, |s| {
|
||||
check_extension_compatibility(s.to_str().unwrap_or("none"))
|
||||
}) || p.path().is_dir()
|
||||
})
|
||||
.collect::<Vec<DirEntry>>();
|
||||
dir.sort_by(|a, b| {
|
||||
|
@ -10,7 +10,8 @@ use crate::{dlp::DownloadProgress, screen::AppScreen, theme::Theme};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LoadingScreen {
|
||||
pub progress: Option<(u32, u32)>,
|
||||
pub progress: Option<(u32, u32, ratatui::style::Color)>,
|
||||
pub artwork_progress: Option<(u32, u32)>,
|
||||
pub s_progress: Option<DownloadProgress>,
|
||||
}
|
||||
|
||||
@ -61,11 +62,29 @@ impl LoadingScreen {
|
||||
self.render_overall(frame, chunks[1]);
|
||||
}
|
||||
|
||||
if self.s_progress.is_some() {
|
||||
if self.artwork_progress.is_some() {
|
||||
self.render_artwork_progress(frame, chunks[2]);
|
||||
} else if self.s_progress.is_some() {
|
||||
self.render_current(frame, chunks[2]);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_artwork_progress(&self, frame: &mut Frame, area: Rect) {
|
||||
let gauge = Gauge::default()
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.title(" Generating album covers "),
|
||||
)
|
||||
.gauge_style(Style::default().fg(Color::LightBlue))
|
||||
.ratio(
|
||||
self.artwork_progress.unwrap().0 as f64 / self.artwork_progress.unwrap().1 as f64,
|
||||
)
|
||||
.label("Generating album covers...");
|
||||
|
||||
frame.render_widget(gauge, area);
|
||||
}
|
||||
|
||||
fn render_current(&self, frame: &mut Frame, area: Rect) {
|
||||
let s: String = self
|
||||
.s_progress
|
||||
@ -96,7 +115,7 @@ impl LoadingScreen {
|
||||
.borders(Borders::ALL)
|
||||
.title(" Downloading Playlist "),
|
||||
)
|
||||
.gauge_style(Style::default().fg(Color::Green))
|
||||
.gauge_style(Style::default().fg(self.progress.unwrap().2))
|
||||
.ratio(self.progress.unwrap().0 as f64 / self.progress.unwrap().1 as f64)
|
||||
.label(format!(
|
||||
"{:}/{:}",
|
||||
|
12
src/main.rs
12
src/main.rs
@ -121,14 +121,22 @@ impl App {
|
||||
let screen: &mut MainScreen = self.get_screen(&AppState::MainScreen);
|
||||
screen.set_soundcloud_playlists(playlists);
|
||||
},
|
||||
AppEvent::OverallProgress((c, max)) => {
|
||||
AppEvent::OverallProgress((c, max, color)) => {
|
||||
self.state = AppState::LoadingScreen;
|
||||
let screen: &mut LoadingScreen = self.get_screen(&AppState::LoadingScreen);
|
||||
screen.progress = Some((c, max));
|
||||
screen.progress = Some((c, max, color));
|
||||
screen.artwork_progress = None;
|
||||
},
|
||||
AppEvent::CurrentProgress(progress) => {
|
||||
let screen: &mut LoadingScreen = self.get_screen(&AppState::LoadingScreen);
|
||||
screen.artwork_progress = None;
|
||||
screen.s_progress = Some(progress);
|
||||
},
|
||||
AppEvent::ArtworkProgress((c, max)) => {
|
||||
let screen: &mut LoadingScreen = self.get_screen(&AppState::LoadingScreen);
|
||||
screen.artwork_progress = Some((c, max));
|
||||
screen.s_progress = None;
|
||||
},
|
||||
AppEvent::SwitchScreen(screen) => {
|
||||
self.state = screen;
|
||||
}
|
||||
|
277
src/sync.rs
277
src/sync.rs
@ -6,6 +6,7 @@ use itunesdb::artworkdb::aobjects::ADatabase;
|
||||
use itunesdb::objects::{ListSortOrder, PlaylistItem};
|
||||
use itunesdb::serializer;
|
||||
use itunesdb::xobjects::{XDatabase, XPlArgument, XPlaylist, XTrackItem};
|
||||
use ratatui::style::Color;
|
||||
use soundcloud::sobjects::{CloudPlaylist, CloudPlaylists, CloudTrack};
|
||||
use std::io::Read;
|
||||
use std::io::{Cursor, Write};
|
||||
@ -34,7 +35,8 @@ pub enum AppEvent {
|
||||
DownloadPlaylist(CloudPlaylist),
|
||||
DownloadTrack(CloudTrack),
|
||||
CurrentProgress(DownloadProgress),
|
||||
OverallProgress((u32, u32)),
|
||||
OverallProgress((u32, u32, ratatui::style::Color)),
|
||||
ArtworkProgress((u32, u32)),
|
||||
SwitchScreen(AppState),
|
||||
LoadFromFS(PathBuf),
|
||||
LoadFromFSVec(Vec<PathBuf>),
|
||||
@ -51,7 +53,11 @@ pub struct DBPlaylist {
|
||||
pub tracks: Vec<XTrackItem>,
|
||||
}
|
||||
|
||||
async fn track_from_soundcloud(value: &CloudTrack, ipod_path: String) -> Option<XTrackItem> {
|
||||
async fn track_from_soundcloud(
|
||||
value: &CloudTrack,
|
||||
ipod_path: String,
|
||||
sender: &Sender<AppEvent>,
|
||||
) -> Option<XTrackItem> {
|
||||
let mut track_path = get_temp_dl_dir();
|
||||
track_path.push(value.id.to_string());
|
||||
track_path.set_extension("mp3");
|
||||
@ -62,7 +68,6 @@ async fn track_from_soundcloud(value: &CloudTrack, ipod_path: String) -> Option<
|
||||
.await
|
||||
.unwrap();
|
||||
let audio_info = &audio_file.audio_file.tracks.track;
|
||||
|
||||
let song_dbid = util::hash_from_path(track_path);
|
||||
|
||||
let mut track = XTrackItem::new(
|
||||
@ -77,20 +82,24 @@ async fn track_from_soundcloud(value: &CloudTrack, ipod_path: String) -> Option<
|
||||
);
|
||||
|
||||
if image_path.exists() {
|
||||
let _ = sender.send(AppEvent::ArtworkProgress((0, 2))).await;
|
||||
let mut adb = get_artwork_db(&ipod_path);
|
||||
|
||||
let image_data = std::fs::read(image_path).unwrap();
|
||||
|
||||
let (small_img_name, large_img_name) = adb.add_images(song_dbid, util::hash(&image_data));
|
||||
let cover_hash = util::hash(&image_data);
|
||||
|
||||
let mut dst = PathBuf::from(&ipod_path);
|
||||
dst.push("iPod_Control");
|
||||
dst.push("Artwork");
|
||||
let if_cover_present = adb.if_cover_present(cover_hash);
|
||||
|
||||
let (small_img_name, large_img_name) = adb.add_images(song_dbid, cover_hash);
|
||||
|
||||
let size = image_data.len();
|
||||
|
||||
make_cover_image(&image_data, &ipod_path, &small_img_name, (100, 100));
|
||||
make_cover_image(&image_data, &ipod_path, &large_img_name, (200, 200));
|
||||
if !if_cover_present {
|
||||
make_cover_image(&image_data, &ipod_path, &small_img_name, (100, 100));
|
||||
let _ = sender.send(AppEvent::ArtworkProgress((1, 2))).await;
|
||||
make_cover_image(&image_data, &ipod_path, &large_img_name, (200, 200));
|
||||
}
|
||||
|
||||
write_artwork_db(adb, &ipod_path);
|
||||
|
||||
@ -98,6 +107,7 @@ async fn track_from_soundcloud(value: &CloudTrack, ipod_path: String) -> Option<
|
||||
track.data.mhii_link = 0;
|
||||
track.data.has_artwork = 1;
|
||||
track.data.artwork_count = 1;
|
||||
let _ = sender.send(AppEvent::ArtworkProgress((2, 2))).await;
|
||||
}
|
||||
|
||||
audio_file.modify_xtrack(&mut track);
|
||||
@ -109,7 +119,9 @@ async fn track_from_soundcloud(value: &CloudTrack, ipod_path: String) -> Option<
|
||||
.clone()
|
||||
.map_or(String::new(), |a| a.username.unwrap_or(a.permalink)),
|
||||
);
|
||||
track.set_genre(value.genre.clone().unwrap());
|
||||
if value.genre.is_some() {
|
||||
track.set_genre(value.genre.clone().unwrap());
|
||||
}
|
||||
Some(track)
|
||||
}
|
||||
|
||||
@ -207,11 +219,15 @@ async fn remove_track_from_playlist(
|
||||
sender: &Sender<AppEvent>,
|
||||
ipod_path: String,
|
||||
) {
|
||||
let _ = sender.send(AppEvent::OverallProgress((0, 1))).await;
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((0, 1, Color::Red)))
|
||||
.await;
|
||||
|
||||
database.remove_track_from_playlist(track_id, pl_id);
|
||||
|
||||
let _ = sender.send(AppEvent::OverallProgress((1, 1))).await;
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((1, 1, Color::Red)))
|
||||
.await;
|
||||
|
||||
let _ = sender
|
||||
.send(AppEvent::SwitchScreen(AppState::MainScreen))
|
||||
@ -242,18 +258,22 @@ async fn remove_playlist(
|
||||
let mut i = 1;
|
||||
for (item, args) in pl.elems.iter() {
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((i, max as u32)))
|
||||
.send(AppEvent::OverallProgress((i, max as u32, Color::Red)))
|
||||
.await;
|
||||
remove_track(item.track_id, database, sender, ipod_path.clone()).await;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let _ = sender.send(AppEvent::OverallProgress((0, 1))).await;
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((0, 1, Color::Red)))
|
||||
.await;
|
||||
|
||||
database.remove_playlist(pl_id);
|
||||
|
||||
let _ = sender.send(AppEvent::OverallProgress((1, 1))).await;
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((1, 1, Color::Red)))
|
||||
.await;
|
||||
|
||||
let _ = sender
|
||||
.send(AppEvent::SwitchScreen(AppState::MainScreen))
|
||||
@ -272,14 +292,18 @@ async fn remove_track(
|
||||
sender: &Sender<AppEvent>,
|
||||
ipod_path: String,
|
||||
) {
|
||||
let _ = sender.send(AppEvent::OverallProgress((0, 1))).await;
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((0, 1, Color::Red)))
|
||||
.await;
|
||||
database.remove_track_completely(id);
|
||||
for ext in ["mp3", "m4a", "wav", "aif"].iter() {
|
||||
let dest = get_full_track_location(PathBuf::from(ipod_path.clone()), id, ext);
|
||||
let _ = std::fs::remove_file(dest);
|
||||
}
|
||||
|
||||
let _ = sender.send(AppEvent::OverallProgress((1, 1))).await;
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((1, 1, Color::Red)))
|
||||
.await;
|
||||
|
||||
let _ = sender
|
||||
.send(AppEvent::SwitchScreen(AppState::MainScreen))
|
||||
@ -305,7 +329,11 @@ async fn load_files_from_fs_as_playlist(
|
||||
|
||||
for (i, file) in files.iter().enumerate() {
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((i as u32, files.len() as u32)))
|
||||
.send(AppEvent::OverallProgress((
|
||||
i as u32,
|
||||
files.len() as u32,
|
||||
Color::Green,
|
||||
)))
|
||||
.await;
|
||||
let id = load_from_fs(file.clone(), database, sender, ipod_path.clone()).await;
|
||||
|
||||
@ -333,7 +361,11 @@ async fn load_files_from_fs(
|
||||
) {
|
||||
for (i, file) in files.iter().enumerate() {
|
||||
let _ = sender
|
||||
.send(AppEvent::OverallProgress((i as u32, files.len() as u32)))
|
||||
.send(AppEvent::OverallProgress((
|
||||
i as u32,
|
||||
files.len() as u32,
|
||||
Color::Green,
|
||||
)))
|
||||
.await;
|
||||
load_from_fs(file.clone(), database, sender, ipod_path.clone()).await;
|
||||
}
|
||||
@ -347,7 +379,7 @@ async fn load_from_fs(
|
||||
) -> u32 {
|
||||
let tag = Tag::new().read_from_path(&path).unwrap();
|
||||
|
||||
let id = database.get_unique_id();
|
||||
let mut id = database.get_unique_id();
|
||||
|
||||
let audio_file = audio_file_info::from_path(path.to_str().unwrap())
|
||||
.await
|
||||
@ -356,75 +388,86 @@ async fn load_from_fs(
|
||||
|
||||
let song_dbid = util::hash_from_path(path.clone());
|
||||
|
||||
let mut track = XTrackItem::new(
|
||||
id,
|
||||
audio_info.audio_bytes as u32,
|
||||
(audio_info.duration * 1000.0) as u32,
|
||||
tag.year().unwrap_or(0) as u32,
|
||||
(audio_info.bit_rate / 1000) as u32,
|
||||
audio_info.sample_rate as u32,
|
||||
song_dbid,
|
||||
0,
|
||||
);
|
||||
if !database.if_track_in_library(song_dbid) {
|
||||
let mut track = XTrackItem::new(
|
||||
id,
|
||||
audio_info.audio_bytes as u32,
|
||||
(audio_info.duration * 1000.0) as u32,
|
||||
tag.year().unwrap_or(0) as u32,
|
||||
(audio_info.bit_rate / 1000) as u32,
|
||||
audio_info.sample_rate as u32,
|
||||
song_dbid,
|
||||
0,
|
||||
);
|
||||
|
||||
audio_file.modify_xtrack(&mut track);
|
||||
audio_file.modify_xtrack(&mut track);
|
||||
|
||||
if let Some(title) = tag.title() {
|
||||
track.set_title(title.to_string());
|
||||
} else {
|
||||
track.set_title(path.file_name().unwrap().to_str().unwrap().to_string());
|
||||
if let Some(title) = tag.title() {
|
||||
track.set_title(title.to_string());
|
||||
} else {
|
||||
track.set_title(path.file_name().unwrap().to_str().unwrap().to_string());
|
||||
}
|
||||
|
||||
if let Some(genre) = tag.genre() {
|
||||
track.set_genre(genre.to_string());
|
||||
}
|
||||
|
||||
if let Some(artist) = tag.artist() {
|
||||
track.set_artist(artist.to_string());
|
||||
}
|
||||
|
||||
if let Some(cover) = tag.album_cover() {
|
||||
let _ = sender.send(AppEvent::ArtworkProgress((0, 2))).await;
|
||||
|
||||
let mut adb = get_artwork_db(&ipod_path);
|
||||
|
||||
let cover_hash = util::hash(cover.data);
|
||||
|
||||
let if_cover_present = adb.if_cover_present(cover_hash);
|
||||
|
||||
let (small_img_name, large_img_name) = adb.add_images(song_dbid, cover_hash);
|
||||
|
||||
let size = cover.data.len();
|
||||
|
||||
if !if_cover_present {
|
||||
make_cover_image(cover.data, &ipod_path, &small_img_name, (100, 100));
|
||||
let _ = sender.send(AppEvent::ArtworkProgress((1, 2))).await;
|
||||
make_cover_image(cover.data, &ipod_path, &large_img_name, (200, 200));
|
||||
}
|
||||
|
||||
write_artwork_db(adb, &ipod_path);
|
||||
|
||||
track.data.artwork_size = size as u32;
|
||||
track.data.mhii_link = 0;
|
||||
track.data.has_artwork = 1;
|
||||
track.data.artwork_count = 1;
|
||||
|
||||
let _ = sender.send(AppEvent::ArtworkProgress((2, 2))).await;
|
||||
}
|
||||
|
||||
if let Some(album) = tag.album() {
|
||||
track.set_album(album.title.to_string());
|
||||
// TODO: Add new album into iTunesDB
|
||||
}
|
||||
|
||||
track.set_location(get_track_location(
|
||||
track.data.unique_id,
|
||||
audio_file.get_audio_extension(),
|
||||
));
|
||||
|
||||
let dest = get_full_track_location(
|
||||
PathBuf::from(ipod_path.clone()),
|
||||
track.data.unique_id,
|
||||
audio_file.get_audio_extension(),
|
||||
);
|
||||
|
||||
let _ = std::fs::copy(path.to_str().unwrap(), dest.to_str().unwrap());
|
||||
|
||||
database.add_track(track);
|
||||
} else if let Some(unique_id) = database.get_unique_id_by_dbid(song_dbid) {
|
||||
id = unique_id;
|
||||
}
|
||||
|
||||
if let Some(genre) = tag.genre() {
|
||||
track.set_genre(genre.to_string());
|
||||
}
|
||||
|
||||
if let Some(artist) = tag.artist() {
|
||||
track.set_artist(artist.to_string());
|
||||
}
|
||||
|
||||
if let Some(cover) = tag.album_cover() {
|
||||
let mut adb = get_artwork_db(&ipod_path);
|
||||
|
||||
let (small_img_name, large_img_name) = adb.add_images(song_dbid, util::hash(cover.data));
|
||||
|
||||
let mut dst = PathBuf::from(&ipod_path);
|
||||
dst.push("iPod_Control");
|
||||
dst.push("Artwork");
|
||||
|
||||
let size = cover.data.len();
|
||||
|
||||
make_cover_image(cover.data, &ipod_path, &small_img_name, (100, 100));
|
||||
make_cover_image(cover.data, &ipod_path, &large_img_name, (200, 200));
|
||||
|
||||
write_artwork_db(adb, &ipod_path);
|
||||
|
||||
track.data.artwork_size = size as u32;
|
||||
track.data.mhii_link = 0;
|
||||
track.data.has_artwork = 1;
|
||||
track.data.artwork_count = 1;
|
||||
}
|
||||
|
||||
if let Some(album) = tag.album() {
|
||||
track.set_album(album.title.to_string());
|
||||
// TODO: Add new album into iTunesDB
|
||||
}
|
||||
|
||||
track.set_location(get_track_location(
|
||||
track.data.unique_id,
|
||||
audio_file.get_audio_extension(),
|
||||
));
|
||||
|
||||
let dest = get_full_track_location(
|
||||
PathBuf::from(ipod_path.clone()),
|
||||
track.data.unique_id,
|
||||
audio_file.get_audio_extension(),
|
||||
);
|
||||
|
||||
let _ = std::fs::copy(path.to_str().unwrap(), dest.to_str().unwrap());
|
||||
|
||||
database.add_track(track);
|
||||
|
||||
let _ = sender
|
||||
.send(AppEvent::SwitchScreen(AppState::MainScreen))
|
||||
.await;
|
||||
@ -522,18 +565,20 @@ async fn download_track(
|
||||
{
|
||||
let p: PathBuf = Path::new(&ipod_path).into();
|
||||
|
||||
if let Some(mut t) = track_from_soundcloud(&track, ipod_path.clone()).await {
|
||||
t.data.unique_id = database.get_unique_id();
|
||||
t.set_location(get_track_location(t.data.unique_id, "mp3"));
|
||||
let dest = get_full_track_location(p.clone(), t.data.unique_id, "mp3");
|
||||
if let Some(mut t) = track_from_soundcloud(&track, ipod_path.clone(), sender).await {
|
||||
if !database.if_track_in_library(t.data.dbid) {
|
||||
t.data.unique_id = database.get_unique_id();
|
||||
t.set_location(get_track_location(t.data.unique_id, "mp3"));
|
||||
let dest = get_full_track_location(p.clone(), t.data.unique_id, "mp3");
|
||||
|
||||
let mut track_path = get_temp_dl_dir();
|
||||
track_path.push(track.id.to_string());
|
||||
track_path.set_extension("mp3");
|
||||
let mut track_path = get_temp_dl_dir();
|
||||
track_path.push(track.id.to_string());
|
||||
track_path.set_extension("mp3");
|
||||
|
||||
let _ = std::fs::copy(track_path.to_str().unwrap(), dest.to_str().unwrap());
|
||||
let _ = std::fs::copy(track_path.to_str().unwrap(), dest.to_str().unwrap());
|
||||
|
||||
database.add_track(t);
|
||||
database.add_track(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -572,18 +617,21 @@ async fn download_playlist(
|
||||
if track.title.is_none() {
|
||||
continue;
|
||||
}
|
||||
if let Some(mut t) = track_from_soundcloud(&track, ipod_path.clone()).await {
|
||||
t.data.unique_id = database.get_unique_id();
|
||||
new_playlist.add_elem(t.data.unique_id);
|
||||
t.set_location(get_track_location(t.data.unique_id, "mp3"));
|
||||
let dest = get_full_track_location(p.clone(), t.data.unique_id, "mp3");
|
||||
let mut track_path = get_temp_dl_dir();
|
||||
track_path.push(track.id.to_string());
|
||||
track_path.set_extension("mp3");
|
||||
if let Some(mut t) = track_from_soundcloud(&track, ipod_path.clone(), sender).await {
|
||||
if !database.if_track_in_library(t.data.dbid) {
|
||||
t.data.unique_id = database.get_unique_id();
|
||||
new_playlist.add_elem(t.data.unique_id);
|
||||
t.set_location(get_track_location(t.data.unique_id, "mp3"));
|
||||
let dest = get_full_track_location(p.clone(), t.data.unique_id, "mp3");
|
||||
let mut track_path = get_temp_dl_dir();
|
||||
track_path.push(track.id.to_string());
|
||||
track_path.set_extension("mp3");
|
||||
|
||||
let _ = std::fs::copy(track_path.to_str().unwrap(), dest.to_str().unwrap());
|
||||
|
||||
database.add_track(t);
|
||||
let _ = std::fs::copy(track_path.to_str().unwrap(), dest.to_str().unwrap());
|
||||
database.add_track(t);
|
||||
} else if let Some(unique_id) = database.get_unique_id_by_dbid(t.data.dbid) {
|
||||
new_playlist.add_elem(unique_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -663,14 +711,17 @@ async fn parse_itunes(sender: &Sender<AppEvent>, path: String) -> XDatabase {
|
||||
let mut playlists = playlists.collection;
|
||||
|
||||
for playlist in playlists.iter_mut() {
|
||||
if let Ok(tracks) = soundcloud::get_tracks(
|
||||
playlist.tracks.clone(),
|
||||
client_id.clone(),
|
||||
app_version.clone(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
playlist.tracks = tracks;
|
||||
let trr = playlist.tracks.clone();
|
||||
playlist.tracks = Vec::new();
|
||||
for pl_tracks in trr.clone().chunks(45) {
|
||||
if let Ok(tracks) =
|
||||
soundcloud::get_tracks(pl_tracks.to_vec(), client_id.clone(), app_version.clone())
|
||||
.await
|
||||
{
|
||||
let mut tracks = tracks;
|
||||
tracks.retain(|t| t.title.is_some());
|
||||
playlist.tracks.append(&mut tracks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user