mirror of
https://github.com/GuillemCastro/spotify-dl.git
synced 2024-11-25 03:20:27 +01:00
Merge branch 'master' into pr/1
This commit is contained in:
commit
e0338b221f
7 changed files with 51 additions and 16 deletions
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -27,7 +27,7 @@ jobs:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
|
needs: create_release
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -12,3 +12,5 @@ target/
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1916,7 +1916,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spotify-dl"
|
name = "spotify-dl"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"audiotags",
|
"audiotags",
|
||||||
"flac-bound",
|
"flac-bound",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "spotify-dl"
|
name = "spotify-dl"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
authors = ["Guillem Castro <guillemcastro4@gmail.com>"]
|
authors = ["Guillem Castro <guillemcastro4@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
#links = "FLAC"
|
#links = "FLAC"
|
||||||
|
|
12
README.md
12
README.md
|
@ -28,7 +28,7 @@ brew install flac
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
spotify-dl 0.1.0
|
spotify-dl 0.1.1
|
||||||
A commandline utility to download music directly from Spotify
|
A commandline utility to download music directly from Spotify
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
|
@ -36,17 +36,19 @@ USAGE:
|
||||||
|
|
||||||
FLAGS:
|
FLAGS:
|
||||||
-h, --help Prints help information
|
-h, --help Prints help information
|
||||||
-o, --ordered Download songs in the order they are in the playlist, prfixing the filename with the track number
|
-o, --ordered Prefixing the filename with its index in the playlist
|
||||||
-V, --version Prints version information
|
-V, --version Prints version information
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
|
-c, --compression <compression> Setting the flac compression level from 0 (fastest, least compression) to
|
||||||
|
8 (slowest, most compression). A value larger than 8 will be Treated as 8.
|
||||||
|
Default is 4.
|
||||||
-d, --destination <destination> The directory where the songs will be downloaded [default: .]
|
-d, --destination <destination> The directory where the songs will be downloaded [default: .]
|
||||||
-p, --password <password> Your Spotify password
|
-p, --password <password> Your Spotify password
|
||||||
-u, --username <username> Your Spotify username
|
-u, --username <username> Your Spotify username
|
||||||
|
|
||||||
ARGS:
|
ARGS:
|
||||||
<tracks>... A list of Spotify URIs (songs, podcasts or playlists)
|
<tracks>... A list of Spotify URIs (songs, podcasts or playlists)```
|
||||||
```
|
|
||||||
|
|
||||||
Songs and playlists must be passed as Spotify URIs or URLs (e.g. `spotify:track:123456789abcdefghABCDEF` for songs and `spotify:playlist:123456789abcdefghABCDEF` for playlists or `https://open.spotify.com/playlist/123456789abcdefghABCDEF?si=1234567890`).
|
Songs and playlists must be passed as Spotify URIs or URLs (e.g. `spotify:track:123456789abcdefghABCDEF` for songs and `spotify:playlist:123456789abcdefghABCDEF` for playlists or `https://open.spotify.com/playlist/123456789abcdefghABCDEF?si=1234567890`).
|
||||||
|
|
||||||
|
@ -56,4 +58,4 @@ The usage of this software may infringe Spotify's ToS and/or your local legislat
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
spotify-dl is licensed under the MIT license. See [LICENSE](LICENSE).
|
spotify-dl is lic:ewensed under the MIT license. See [LICENSE](LICENSE).
|
||||||
|
|
|
@ -1,28 +1,38 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use audiotags::{Tag, TagType};
|
use audiotags::{Tag, TagType};
|
||||||
use librespot::{playback::{audio_backend::{Open, Sink, SinkError}, config::AudioFormat, decoder::AudioPacket, convert::Converter}};
|
use librespot::playback::{
|
||||||
|
audio_backend::{Open, Sink, SinkError},
|
||||||
|
config::AudioFormat,
|
||||||
|
convert::Converter,
|
||||||
|
decoder::AudioPacket,
|
||||||
|
};
|
||||||
|
|
||||||
// extern crate flac_bound;
|
// extern crate flac_bound;
|
||||||
|
|
||||||
use flac_bound::{FlacEncoder};
|
use flac_bound::FlacEncoder;
|
||||||
|
|
||||||
use crate::TrackMetadata;
|
use crate::TrackMetadata;
|
||||||
|
|
||||||
pub struct FileSink {
|
pub struct FileSink {
|
||||||
sink: String,
|
sink: String,
|
||||||
content: Vec<i32>,
|
content: Vec<i32>,
|
||||||
metadata: Option<TrackMetadata>
|
metadata: Option<TrackMetadata>,
|
||||||
|
compression: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileSink {
|
impl FileSink {
|
||||||
pub fn add_metadata(&mut self, meta: TrackMetadata) {
|
pub fn add_metadata(&mut self, meta: TrackMetadata) {
|
||||||
self.metadata = Some(meta);
|
self.metadata = Some(meta);
|
||||||
}
|
}
|
||||||
|
pub fn set_compression(&mut self, compression: u32) {
|
||||||
|
self.compression = compression;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Open for FileSink {
|
impl Open for FileSink {
|
||||||
fn open(path: Option<String>, _audio_format: AudioFormat) -> Self {
|
fn open(path: Option<String>, _audio_format: AudioFormat) -> Self {
|
||||||
|
|
||||||
let file_path = path.unwrap_or_else(|| panic!());
|
let file_path = path.unwrap_or_else(|| panic!());
|
||||||
FileSink {
|
FileSink {
|
||||||
sink: file_path,
|
sink: file_path,
|
||||||
|
@ -38,21 +48,33 @@ impl Sink for FileSink {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop(&mut self) -> Result<(), SinkError> {
|
fn stop(&mut self) -> Result<(), SinkError> {
|
||||||
let mut encoder = FlacEncoder::new().unwrap().channels(2).bits_per_sample(16).compression_level(4).init_file(&self.sink).unwrap();
|
let mut encoder = FlacEncoder::new()
|
||||||
encoder.process_interleaved(self.content.as_slice(), (self.content.len()/2) as u32).unwrap();
|
.unwrap()
|
||||||
|
.channels(2)
|
||||||
|
.bits_per_sample(16)
|
||||||
|
.compression_level(*&self.compression)
|
||||||
|
.init_file(&self.sink)
|
||||||
|
.unwrap();
|
||||||
|
encoder
|
||||||
|
.process_interleaved(self.content.as_slice(), (self.content.len() / 2) as u32)
|
||||||
|
.unwrap();
|
||||||
encoder.finish().unwrap();
|
encoder.finish().unwrap();
|
||||||
|
|
||||||
match &self.metadata {
|
match &self.metadata {
|
||||||
Some(meta) => {
|
Some(meta) => {
|
||||||
let mut tag = Tag::new().with_tag_type(TagType::Flac).read_from_path(Path::new(&self.sink)).unwrap();
|
let mut tag = Tag::new()
|
||||||
|
.with_tag_type(TagType::Flac)
|
||||||
|
.read_from_path(Path::new(&self.sink))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
tag.set_album_title(&meta.album);
|
tag.set_album_title(&meta.album);
|
||||||
for artist in &meta.artists {
|
for artist in &meta.artists {
|
||||||
tag.add_artist(artist);
|
tag.add_artist(artist);
|
||||||
}
|
}
|
||||||
tag.set_title(&meta.track_name);
|
tag.set_title(&meta.track_name);
|
||||||
tag.write_to_path(&self.sink).expect("Failed to write metadata");
|
tag.write_to_path(&self.sink)
|
||||||
},
|
.expect("Failed to write metadata");
|
||||||
|
}
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -46,6 +46,13 @@ struct Opt {
|
||||||
help = "Prefixing the filename with its index in the playlist"
|
help = "Prefixing the filename with its index in the playlist"
|
||||||
)]
|
)]
|
||||||
ordered: bool,
|
ordered: bool,
|
||||||
|
#[structopt(
|
||||||
|
short = "c",
|
||||||
|
long = "compression",
|
||||||
|
help = "Setting the flac compression level from 0 (fastest, least compression) to
|
||||||
|
8 (slowest, most compression). A value larger than 8 will be Treated as 8. Default is 4."
|
||||||
|
)]
|
||||||
|
compression: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -79,6 +86,7 @@ async fn download_tracks(
|
||||||
destination: PathBuf,
|
destination: PathBuf,
|
||||||
tracks: Vec<SpotifyId>,
|
tracks: Vec<SpotifyId>,
|
||||||
ordered: bool,
|
ordered: bool,
|
||||||
|
compression: Option<u32>,
|
||||||
) {
|
) {
|
||||||
let player_config = PlayerConfig::default();
|
let player_config = PlayerConfig::default();
|
||||||
let bar_style = ProgressStyle::default_bar()
|
let bar_style = ProgressStyle::default_bar()
|
||||||
|
@ -225,6 +233,7 @@ async fn main() {
|
||||||
PathBuf::from(opt.destination),
|
PathBuf::from(opt.destination),
|
||||||
tracks,
|
tracks,
|
||||||
opt.ordered,
|
opt.ordered,
|
||||||
|
opt.compression,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue