mirror of
https://github.com/CDrummond/bliss-analyser.git
synced 2026-10-22 14:32:08 +03:00
Update version of bliss-rs, this now handles CUE processing internally.
This commit is contained in:
1 parent
2788759829
commit
467e341cfb
7 files changed
+96
-615
No files matched your search
Generated
+9
-292
@@ -69,12 +69,6 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "base-x"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
@@ -128,25 +122,21 @@ dependencies = [
|
|||||||
"configparser",
|
"configparser",
|
||||||
"dirs",
|
"dirs",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"hhmmss",
|
|
||||||
"if_chain",
|
"if_chain",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
"lofty",
|
"lofty",
|
||||||
"log",
|
"log",
|
||||||
"num_cpus",
|
|
||||||
"rcue",
|
|
||||||
"regex",
|
"regex",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"subprocess",
|
|
||||||
"substring",
|
"substring",
|
||||||
"tempdir",
|
|
||||||
"ureq",
|
"ureq",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bliss-audio"
|
name = "bliss-audio"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/Polochon-street/bliss-rs#c08fd3d7034c737e7645f59498dfa78b24eea182"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "947fa29cb8c27448497bdbcbab05a9eb3c1f046a5efd7b684060a6dc587bb761"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bliss-audio-aubio-rs",
|
"bliss-audio-aubio-rs",
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
@@ -160,6 +150,7 @@ dependencies = [
|
|||||||
"noisy_float",
|
"noisy_float",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
"rcue",
|
||||||
"ripemd160",
|
"ripemd160",
|
||||||
"rustfft",
|
"rustfft",
|
||||||
"strum",
|
"strum",
|
||||||
@@ -266,7 +257,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"time 0.1.44",
|
"time",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -306,12 +297,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const_fn"
|
|
||||||
version = "0.4.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "constant_time_eq"
|
name = "constant_time_eq"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@@ -424,12 +409,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "discard"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
@@ -520,12 +499,6 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fuchsia-cprng"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.12.4"
|
version = "0.12.4"
|
||||||
@@ -609,16 +582,6 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hhmmss"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "11a3a7d0916cb01ef108a66108640419767991ea31d11a1c851bed37686a6062"
|
|
||||||
dependencies = [
|
|
||||||
"chrono",
|
|
||||||
"time 0.2.27",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humantime"
|
name = "humantime"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
@@ -673,12 +636,6 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itoa"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
@@ -852,7 +809,7 @@ dependencies = [
|
|||||||
"noisy_float",
|
"noisy_float",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rand 0.8.5",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1048,12 +1005,6 @@ dependencies = [
|
|||||||
"num-integer",
|
"num-integer",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-hack"
|
|
||||||
version = "0.5.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.36"
|
version = "1.0.36"
|
||||||
@@ -1085,19 +1036,6 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.4.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
|
||||||
dependencies = [
|
|
||||||
"fuchsia-cprng",
|
|
||||||
"libc",
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
"rdrand",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@@ -1106,7 +1044,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
"rand_core 0.6.3",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1116,24 +1054,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"ppv-lite86",
|
||||||
"rand_core 0.6.3",
|
"rand_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.4.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
@@ -1176,17 +1099,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rcue"
|
name = "rcue"
|
||||||
version = "0.1.0"
|
version = "0.1.3"
|
||||||
source = "git+https://github.com/gyng/rcue#9ecd1ccbb764acfb7d54c3395525a4c85b43daea"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rdrand"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
checksum = "fca1481d62f18158646de2ec552dd63f8bdc5be6448389b192ba95c939df997e"
|
||||||
dependencies = [
|
|
||||||
"rand_core 0.3.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
@@ -1222,15 +1137,6 @@ version = "0.6.25"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "remove_dir_all"
|
|
||||||
version = "0.5.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
version = "0.16.20"
|
version = "0.16.20"
|
||||||
@@ -1290,15 +1196,6 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc_version"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
|
||||||
dependencies = [
|
|
||||||
"semver",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustfft"
|
name = "rustfft"
|
||||||
version = "5.1.1"
|
version = "5.1.1"
|
||||||
@@ -1325,12 +1222,6 @@ dependencies = [
|
|||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -1347,49 +1238,6 @@ dependencies = [
|
|||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "semver"
|
|
||||||
version = "0.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
|
||||||
dependencies = [
|
|
||||||
"semver-parser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "semver-parser"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde"
|
|
||||||
version = "1.0.136"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.136"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_json"
|
|
||||||
version = "1.0.79"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha-1"
|
name = "sha-1"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
@@ -1402,21 +1250,6 @@ dependencies = [
|
|||||||
"opaque-debug 0.2.3",
|
"opaque-debug 0.2.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha1"
|
|
||||||
version = "0.6.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
|
|
||||||
dependencies = [
|
|
||||||
"sha1_smol",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sha1_smol"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -1435,64 +1268,6 @@ version = "0.5.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "standback"
|
|
||||||
version = "0.2.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
|
|
||||||
dependencies = [
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stdweb"
|
|
||||||
version = "0.4.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
|
|
||||||
dependencies = [
|
|
||||||
"discard",
|
|
||||||
"rustc_version",
|
|
||||||
"stdweb-derive",
|
|
||||||
"stdweb-internal-macros",
|
|
||||||
"stdweb-internal-runtime",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stdweb-derive"
|
|
||||||
version = "0.5.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stdweb-internal-macros"
|
|
||||||
version = "0.2.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
|
||||||
dependencies = [
|
|
||||||
"base-x",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
"sha1",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stdweb-internal-runtime"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strength_reduce"
|
name = "strength_reduce"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
@@ -1517,16 +1292,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subprocess"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "055cf3ebc2981ad8f0a5a17ef6652f652d87831f79fddcba2ac57bcb9a0aa407"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "substring"
|
name = "substring"
|
||||||
version = "1.4.5"
|
version = "1.4.5"
|
||||||
@@ -1547,16 +1312,6 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tempdir"
|
|
||||||
version = "0.3.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
|
||||||
dependencies = [
|
|
||||||
"rand 0.4.6",
|
|
||||||
"remove_dir_all",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
@@ -1607,44 +1362,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time"
|
|
||||||
version = "0.2.27"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
|
|
||||||
dependencies = [
|
|
||||||
"const_fn",
|
|
||||||
"libc",
|
|
||||||
"standback",
|
|
||||||
"stdweb",
|
|
||||||
"time-macros",
|
|
||||||
"version_check",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time-macros"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-hack",
|
|
||||||
"time-macros-impl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time-macros-impl"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-hack",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"standback",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.5.1"
|
version = "1.5.1"
|
||||||
|
|||||||
+1
-6
@@ -10,7 +10,7 @@ keywords = ["audio", "song", "similarity"]
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bliss-audio = { git = "https://github.com/Polochon-street/bliss-rs" }
|
bliss-audio = "0.5.0"
|
||||||
argparse = "0.2.2"
|
argparse = "0.2.2"
|
||||||
anyhow = "1.0.40"
|
anyhow = "1.0.40"
|
||||||
rusqlite = { version = "0.25.0", features = ["bundled"] }
|
rusqlite = { version = "0.25.0", features = ["bundled"] }
|
||||||
@@ -24,9 +24,4 @@ regex = "1"
|
|||||||
substring = "1.4.5"
|
substring = "1.4.5"
|
||||||
ureq = "2.4.0"
|
ureq = "2.4.0"
|
||||||
configparser = "3.0.0"
|
configparser = "3.0.0"
|
||||||
rcue = { git = "https://github.com/gyng/rcue" }
|
|
||||||
hhmmss = "0.1.0"
|
|
||||||
num_cpus = "1.13.0"
|
|
||||||
tempdir = "0.3.7"
|
|
||||||
subprocess = "0.2.8"
|
|
||||||
if_chain = "1.0.2"
|
if_chain = "1.0.2"
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
1. Tidy up code, thanks to Serial-ATA
|
1. Tidy up code, thanks to Serial-ATA
|
||||||
2. Update version of tag reader library, should now support ID3v2 in FLAC.
|
2. Update version of tag reader library, should now support ID3v2 in FLAC.
|
||||||
3. Show error message if can't open, or create, database file.
|
3. Show error message if can't open, or create, database file.
|
||||||
4. Update version of bliss-rs.
|
4. Update version of bliss-rs, this now handles CUE processing internally.
|
||||||
|
|
||||||
0.1.0
|
0.1.0
|
||||||
-----
|
-----
|
||||||
|
|||||||
+77
-211
@@ -6,33 +6,24 @@
|
|||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
||||||
use crate::cue;
|
|
||||||
use crate::db;
|
use crate::db;
|
||||||
use crate::tags;
|
use crate::tags;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bliss_audio::{analyze_paths, BlissResult, Song};
|
use bliss_audio::{analyze_paths};
|
||||||
use hhmmss::Hhmmss;
|
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
use num_cpus;
|
use std::collections::HashSet;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fs;
|
|
||||||
use std::fs::{DirEntry, File};
|
use std::fs::{DirEntry, File};
|
||||||
use std::io::{BufRead, BufReader};
|
use std::io::{BufRead, BufReader};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::mpsc;
|
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
|
||||||
use std::thread;
|
|
||||||
use std::time::Duration;
|
|
||||||
use subprocess::{Exec, NullFile};
|
|
||||||
use tempdir::TempDir;
|
|
||||||
|
|
||||||
const DONT_ANALYSE: &str = ".notmusic";
|
const DONT_ANALYSE: &str = ".notmusic";
|
||||||
const MAX_ERRORS_TO_SHOW: usize = 100;
|
const MAX_ERRORS_TO_SHOW: usize = 100;
|
||||||
const MAX_TAG_ERRORS_TO_SHOW: usize = 50;
|
const MAX_TAG_ERRORS_TO_SHOW: usize = 50;
|
||||||
const VALID_EXTENSIONS: [&str; 5] = ["m4a", "mp3", "ogg", "flac", "opus"];
|
const VALID_EXTENSIONS: [&str; 5] = ["m4a", "mp3", "ogg", "flac", "opus"];
|
||||||
|
|
||||||
fn get_file_list(db: &mut db::Db, mpath: &Path, path: &Path, track_paths: &mut Vec<String>, cue_tracks: &mut Vec<cue::CueTrack>) {
|
fn get_file_list(db: &mut db::Db, mpath: &Path, path: &Path, track_paths: &mut Vec<String>) {
|
||||||
if !path.is_dir() {
|
if !path.is_dir() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -40,20 +31,20 @@ fn get_file_list(db: &mut db::Db, mpath: &Path, path: &Path, track_paths: &mut V
|
|||||||
if let Ok(items) = path.read_dir() {
|
if let Ok(items) = path.read_dir() {
|
||||||
for item in items {
|
for item in items {
|
||||||
if let Ok(entry) = item {
|
if let Ok(entry) = item {
|
||||||
check_dir_entry(db, mpath, entry, track_paths, cue_tracks);
|
check_dir_entry(db, mpath, entry, track_paths);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_dir_entry(db: &mut db::Db, mpath: &Path, entry: DirEntry, track_paths: &mut Vec<String>, cue_tracks: &mut Vec<cue::CueTrack>) {
|
fn check_dir_entry(db: &mut db::Db, mpath: &Path, entry: DirEntry, track_paths: &mut Vec<String>) {
|
||||||
let pb = entry.path();
|
let pb = entry.path();
|
||||||
if pb.is_dir() {
|
if pb.is_dir() {
|
||||||
let check = pb.join(DONT_ANALYSE);
|
let check = pb.join(DONT_ANALYSE);
|
||||||
if check.exists() {
|
if check.exists() {
|
||||||
log::info!("Skipping '{}', found '{}'", pb.to_string_lossy(), DONT_ANALYSE);
|
log::info!("Skipping '{}', found '{}'", pb.to_string_lossy(), DONT_ANALYSE);
|
||||||
} else {
|
} else {
|
||||||
get_file_list(db, mpath, &pb, track_paths, cue_tracks);
|
get_file_list(db, mpath, &pb, track_paths);
|
||||||
}
|
}
|
||||||
} else if pb.is_file() {
|
} else if pb.is_file() {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
@@ -62,24 +53,21 @@ fn check_dir_entry(db: &mut db::Db, mpath: &Path, entry: DirEntry, track_paths:
|
|||||||
if VALID_EXTENSIONS.contains(&&*ext);
|
if VALID_EXTENSIONS.contains(&&*ext);
|
||||||
if let Ok(stripped) = pb.strip_prefix(mpath);
|
if let Ok(stripped) = pb.strip_prefix(mpath);
|
||||||
then {
|
then {
|
||||||
|
let sname = String::from(stripped.to_string_lossy());
|
||||||
let mut cue_file = pb.clone();
|
let mut cue_file = pb.clone();
|
||||||
cue_file.set_extension("cue");
|
cue_file.set_extension("cue");
|
||||||
if cue_file.exists() {
|
if cue_file.exists() {
|
||||||
// Found a CUE file, try to parse and then check if tracks exists in DB
|
// For cue files, check if first track is in DB
|
||||||
let this_cue_tracks = cue::parse(&pb, &cue_file);
|
let mut track_path = pb.clone();
|
||||||
for track in this_cue_tracks {
|
let ext = pb.extension().unwrap().to_string_lossy();
|
||||||
if let Ok(tstripped) = track.track_path.strip_prefix(mpath) {
|
track_path.set_extension(format!("{}{}1", ext, db::CUE_MARKER));
|
||||||
let sname = String::from(tstripped.to_string_lossy());
|
let db_track = String::from(track_path.to_string_lossy());
|
||||||
|
if let Ok(id) = db.get_rowid(&db_track) {
|
||||||
if let Ok(id) = db.get_rowid(&sname) {
|
|
||||||
if id<=0 {
|
if id<=0 {
|
||||||
cue_tracks.push(track);
|
track_paths.push(String::from(cue_file.to_string_lossy()));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let sname = String::from(stripped.to_string_lossy());
|
|
||||||
if let Ok(id) = db.get_rowid(&sname) {
|
if let Ok(id) = db.get_rowid(&sname) {
|
||||||
if id<=0 {
|
if id<=0 {
|
||||||
track_paths.push(String::from(pb.to_string_lossy()));
|
track_paths.push(String::from(pb.to_string_lossy()));
|
||||||
@@ -102,41 +90,86 @@ pub fn analyse_new_files(db: &db::Db, mpath: &PathBuf, track_paths: Vec<String>)
|
|||||||
let mut analysed = 0;
|
let mut analysed = 0;
|
||||||
let mut failed: Vec<String> = Vec::new();
|
let mut failed: Vec<String> = Vec::new();
|
||||||
let mut tag_error: Vec<String> = Vec::new();
|
let mut tag_error: Vec<String> = Vec::new();
|
||||||
|
let mut reported_cue:HashSet<String> = HashSet::new();
|
||||||
|
|
||||||
log::info!("Analysing new tracks");
|
log::info!("Analysing new files");
|
||||||
for (path, result) in analyze_paths(track_paths) {
|
for (path, result) in analyze_paths(track_paths) {
|
||||||
let pbuff = PathBuf::from(&path);
|
let pbuff = PathBuf::from(&path);
|
||||||
let stripped = pbuff.strip_prefix(mpath).unwrap();
|
let stripped = pbuff.strip_prefix(mpath).unwrap();
|
||||||
let spbuff = stripped.to_path_buf();
|
let spbuff = stripped.to_path_buf();
|
||||||
let sname = String::from(spbuff.to_string_lossy());
|
let sname = String::from(spbuff.to_string_lossy());
|
||||||
progress.set_message(format!("{}", sname));
|
progress.set_message(format!("{}", sname));
|
||||||
|
let mut inc_progress = true; // Only want to increment progress once for cue tracks
|
||||||
match result {
|
match result {
|
||||||
Ok(track) => {
|
Ok(track) => {
|
||||||
let cpath = String::from(path);
|
let cpath = String::from(path);
|
||||||
let meta = tags::read(&cpath);
|
match track.cue_info {
|
||||||
|
Some(cue) => {
|
||||||
|
match track.track_number {
|
||||||
|
Some(track_num) => {
|
||||||
|
let t_num = track_num.parse::<i32>().unwrap();
|
||||||
|
if reported_cue.contains(&cpath) {
|
||||||
|
inc_progress = false;
|
||||||
|
} else {
|
||||||
|
analysed += 1;
|
||||||
|
reported_cue.insert(cpath);
|
||||||
|
}
|
||||||
|
let meta = db::Metadata {
|
||||||
|
title: track.title.unwrap_or_default().to_string(),
|
||||||
|
artist: track.artist.unwrap_or_default().to_string(),
|
||||||
|
album: track.album.unwrap_or_default().to_string(),
|
||||||
|
album_artist: track.album_artist.unwrap_or_default().to_string(),
|
||||||
|
genre: track.genre.unwrap_or_default().to_string(),
|
||||||
|
duration: track.duration.as_secs() as u32
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove prefix from audio_file_path
|
||||||
|
let pbuff = PathBuf::from(&cue.audio_file_path);
|
||||||
|
let stripped = pbuff.strip_prefix(mpath).unwrap();
|
||||||
|
let spbuff = stripped.to_path_buf();
|
||||||
|
let sname = String::from(spbuff.to_string_lossy());
|
||||||
|
|
||||||
|
let db_path = format!("{}{}{}", sname, db::CUE_MARKER, t_num);
|
||||||
|
db.add_track(&db_path, &meta, &track.analysis);
|
||||||
|
}
|
||||||
|
None => { failed.push(format!("{} - No track number?", sname)); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// Use lofty to read tags here, and not bliss's, so that if update
|
||||||
|
// tags is ever used they are from the same source.
|
||||||
|
let mut meta = tags::read(&cpath);
|
||||||
|
if meta.is_empty() {
|
||||||
|
// Lofty failed? Try from bliss...
|
||||||
|
meta.title = track.title.unwrap_or_default().to_string();
|
||||||
|
meta.artist = track.artist.unwrap_or_default().to_string();
|
||||||
|
meta.album = track.album.unwrap_or_default().to_string();
|
||||||
|
meta.album_artist = track.album_artist.unwrap_or_default().to_string();
|
||||||
|
meta.genre = track.genre.unwrap_or_default().to_string();
|
||||||
|
meta.duration = track.duration.as_secs() as u32;
|
||||||
|
}
|
||||||
if meta.is_empty() {
|
if meta.is_empty() {
|
||||||
tag_error.push(sname.clone());
|
tag_error.push(sname.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
db.add_track(&sname, &meta, &track.analysis);
|
db.add_track(&sname, &meta, &track.analysis);
|
||||||
analysed += 1;
|
analysed += 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(e) => { failed.push(format!("{} - {}", sname, e)); }
|
Err(e) => { failed.push(format!("{} - {}", sname, e)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if inc_progress {
|
||||||
progress.inc(1);
|
progress.inc(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
progress.finish_with_message(format!(
|
progress.finish_with_message(format!("{} Analysed. {} Failure(s).", analysed, failed.len()));
|
||||||
"{} Analysed. {} Failure(s).",
|
|
||||||
analysed,
|
|
||||||
failed.len()
|
|
||||||
));
|
|
||||||
if !failed.is_empty() {
|
if !failed.is_empty() {
|
||||||
let total = failed.len();
|
let total = failed.len();
|
||||||
failed.truncate(MAX_ERRORS_TO_SHOW);
|
failed.truncate(MAX_ERRORS_TO_SHOW);
|
||||||
|
|
||||||
log::error!("Failed to analyse the following track(s):");
|
log::error!("Failed to analyse the following file(s):");
|
||||||
for err in failed {
|
for err in failed {
|
||||||
log::error!(" {}", err);
|
log::error!(" {}", err);
|
||||||
}
|
}
|
||||||
@@ -148,7 +181,7 @@ pub fn analyse_new_files(db: &db::Db, mpath: &PathBuf, track_paths: Vec<String>)
|
|||||||
let total = tag_error.len();
|
let total = tag_error.len();
|
||||||
tag_error.truncate(MAX_TAG_ERRORS_TO_SHOW);
|
tag_error.truncate(MAX_TAG_ERRORS_TO_SHOW);
|
||||||
|
|
||||||
log::error!("Failed to read tags of the following track(s):");
|
log::error!("Failed to read tags of the following file(s):");
|
||||||
for err in tag_error {
|
for err in tag_error {
|
||||||
log::error!(" {}", err);
|
log::error!(" {}", err);
|
||||||
}
|
}
|
||||||
@@ -159,149 +192,6 @@ pub fn analyse_new_files(db: &db::Db, mpath: &PathBuf, track_paths: Vec<String>)
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn analyze_cue_tracks(tracks: Vec<cue::CueTrack>) -> mpsc::IntoIter<(cue::CueTrack, BlissResult<Song>)> {
|
|
||||||
let num_cpus = num_cpus::get();
|
|
||||||
let last_track_duration = Duration::new(cue::LAST_TRACK_DURATION, 0);
|
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
let (tx, rx): (
|
|
||||||
Sender<(cue::CueTrack, BlissResult<Song>)>,
|
|
||||||
Receiver<(cue::CueTrack, BlissResult<Song>)>,
|
|
||||||
) = mpsc::channel();
|
|
||||||
if tracks.is_empty() {
|
|
||||||
return rx.into_iter();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut handles = Vec::new();
|
|
||||||
let mut chunk_length = tracks.len() / num_cpus;
|
|
||||||
if chunk_length == 0 {
|
|
||||||
chunk_length = tracks.len();
|
|
||||||
} else if chunk_length == 1 && tracks.len() > num_cpus {
|
|
||||||
chunk_length = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for chunk in tracks.chunks(chunk_length) {
|
|
||||||
let tx_thread = tx.clone();
|
|
||||||
let owned_chunk = chunk.to_owned();
|
|
||||||
let child = thread::spawn(move || {
|
|
||||||
let dir = TempDir::new("bliss");
|
|
||||||
if let Err(e) = dir {
|
|
||||||
log::error!("Failed to create temp folder. {}", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut idx = 0;
|
|
||||||
let dir = dir.unwrap();
|
|
||||||
for mut cue_track in owned_chunk {
|
|
||||||
let audio_path = String::from(cue_track.audio_path.to_string_lossy());
|
|
||||||
let ext = cue_track.audio_path.extension();
|
|
||||||
let track_path = String::from(cue_track.track_path.to_string_lossy());
|
|
||||||
let mut tmp_file = PathBuf::from(dir.path());
|
|
||||||
if ext.is_some() {
|
|
||||||
tmp_file.push(format!("{}.{}", idx, ext.unwrap().to_string_lossy()));
|
|
||||||
} else {
|
|
||||||
tmp_file.push(format!("{}.flac", idx));
|
|
||||||
}
|
|
||||||
idx += 1;
|
|
||||||
|
|
||||||
log::debug!("Extracting '{}'", track_path);
|
|
||||||
let cmd = Exec::cmd("ffmpeg")
|
|
||||||
.arg("-i")
|
|
||||||
.arg(&audio_path)
|
|
||||||
.arg("-ss")
|
|
||||||
.arg(&cue_track.start.hhmmss())
|
|
||||||
.arg("-t")
|
|
||||||
.arg(&cue_track.duration.hhmmss())
|
|
||||||
.arg("-c")
|
|
||||||
.arg("copy")
|
|
||||||
.arg(String::from(tmp_file.to_string_lossy()))
|
|
||||||
.stderr(NullFile)
|
|
||||||
.join();
|
|
||||||
|
|
||||||
if let Err(e) = cmd {
|
|
||||||
log::error!("Failed to call ffmpeg. {}", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !cfg!(windows) {
|
|
||||||
// ffmpeg seeks to break echo on terminal? 'stty echo' restores...
|
|
||||||
let _ = Exec::cmd("stty").arg("echo").join();
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp_file.exists() {
|
|
||||||
log::debug!("Analyzing '{}'", track_path);
|
|
||||||
let song = Song::from_path(&tmp_file);
|
|
||||||
if cue_track.duration >= last_track_duration {
|
|
||||||
// Last track, so read duration from temp file
|
|
||||||
let meta = tags::read(&String::from(tmp_file.to_string_lossy()));
|
|
||||||
cue_track.duration = Duration::new(meta.duration as u64, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
tx_thread.send((cue_track, song)).unwrap();
|
|
||||||
let _ = fs::remove_file(tmp_file);
|
|
||||||
} else {
|
|
||||||
log::error!("Failed to create temp file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
handles.push(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
rx.into_iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn analyse_new_cue_tracks(db: &db::Db, mpath: &PathBuf, cue_tracks: Vec<cue::CueTrack>) -> Result<()> {
|
|
||||||
let total = cue_tracks.len();
|
|
||||||
let progress = ProgressBar::new(total.try_into().unwrap()).with_style(
|
|
||||||
ProgressStyle::default_bar()
|
|
||||||
.template("[{elapsed_precise}] [{bar:25}] {percent:>3}% {pos:>6}/{len:6} {wide_msg}")
|
|
||||||
.progress_chars("=> "),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut analysed = 0;
|
|
||||||
let mut failed: Vec<String> = Vec::new();
|
|
||||||
|
|
||||||
log::info!("Analysing new cue tracks");
|
|
||||||
for (track, result) in analyze_cue_tracks(cue_tracks) {
|
|
||||||
let stripped = track.track_path.strip_prefix(mpath).unwrap();
|
|
||||||
let spbuff = stripped.to_path_buf();
|
|
||||||
let sname = String::from(spbuff.to_string_lossy());
|
|
||||||
progress.set_message(format!("{}", sname));
|
|
||||||
match result {
|
|
||||||
Ok(song) => {
|
|
||||||
let meta = db::Metadata {
|
|
||||||
title: track.title,
|
|
||||||
artist: track.artist,
|
|
||||||
album_artist: track.album_artist,
|
|
||||||
album: track.album,
|
|
||||||
genre: track.genre,
|
|
||||||
duration: track.duration.as_secs() as u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
db.add_track(&sname, &meta, &song.analysis);
|
|
||||||
analysed += 1;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
failed.push(format!("{} - {}", sname, e));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
progress.inc(1);
|
|
||||||
}
|
|
||||||
progress.finish_with_message(format!("{} Analysed. {} Failure(s).", analysed, failed.len()));
|
|
||||||
if !failed.is_empty() {
|
|
||||||
let total = failed.len();
|
|
||||||
failed.truncate(MAX_ERRORS_TO_SHOW);
|
|
||||||
|
|
||||||
log::error!("Failed to analyse the following track(s):");
|
|
||||||
for err in failed {
|
|
||||||
log::error!(" {}", err);
|
|
||||||
}
|
|
||||||
if total > MAX_ERRORS_TO_SHOW {
|
|
||||||
log::error!(" + {} other(s)", total - MAX_ERRORS_TO_SHOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn analyse_files(db_path: &str, mpaths: &Vec<PathBuf>, dry_run: bool, keep_old: bool, max_num_tracks: usize) {
|
pub fn analyse_files(db_path: &str, mpaths: &Vec<PathBuf>, dry_run: bool, keep_old: bool, max_num_tracks: usize) {
|
||||||
let mut db = db::Db::new(&String::from(db_path));
|
let mut db = db::Db::new(&String::from(db_path));
|
||||||
let mut track_count_left = max_num_tracks;
|
let mut track_count_left = max_num_tracks;
|
||||||
@@ -316,49 +206,31 @@ pub fn analyse_files(db_path: &str, mpaths: &Vec<PathBuf>, dry_run: bool, keep_o
|
|||||||
let mpath = path.clone();
|
let mpath = path.clone();
|
||||||
let cur = path.clone();
|
let cur = path.clone();
|
||||||
let mut track_paths: Vec<String> = Vec::new();
|
let mut track_paths: Vec<String> = Vec::new();
|
||||||
let mut cue_tracks: Vec<cue::CueTrack> = Vec::new();
|
|
||||||
|
|
||||||
if mpaths.len() > 1 {
|
if mpaths.len() > 1 {
|
||||||
log::info!("Looking for new tracks in {}", mpath.to_string_lossy());
|
log::info!("Looking for new files in {}", mpath.to_string_lossy());
|
||||||
} else {
|
} else {
|
||||||
log::info!("Looking for new tracks");
|
log::info!("Looking for new files");
|
||||||
}
|
}
|
||||||
get_file_list(&mut db, &mpath, &cur, &mut track_paths, &mut cue_tracks);
|
get_file_list(&mut db, &mpath, &cur, &mut track_paths);
|
||||||
track_paths.sort();
|
track_paths.sort();
|
||||||
log::info!("Num new tracks: {}", track_paths.len());
|
log::info!("Num new files: {}", track_paths.len());
|
||||||
if !cue_tracks.is_empty() {
|
|
||||||
log::info!("Num new cue tracks: {}", cue_tracks.len());
|
|
||||||
}
|
|
||||||
|
|
||||||
if dry_run {
|
if dry_run {
|
||||||
if !track_paths.is_empty() || !cue_tracks.is_empty() {
|
if !track_paths.is_empty() {
|
||||||
log::info!("The following need to be analysed:");
|
log::info!("The following need to be analysed:");
|
||||||
for track in track_paths {
|
for track in track_paths {
|
||||||
log::info!(" {}", track);
|
log::info!(" {}", track);
|
||||||
}
|
}
|
||||||
for track in cue_tracks {
|
|
||||||
log::info!(" {}", track.track_path.to_string_lossy());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if max_num_tracks > 0 {
|
if max_num_tracks > 0 {
|
||||||
if track_paths.len() > track_count_left {
|
if track_paths.len() > track_count_left {
|
||||||
log::info!("Only analysing {} tracks", track_count_left);
|
log::info!("Only analysing {} files", track_count_left);
|
||||||
track_paths.truncate(track_count_left);
|
track_paths.truncate(track_count_left);
|
||||||
}
|
}
|
||||||
track_count_left -= track_paths.len();
|
track_count_left -= track_paths.len();
|
||||||
}
|
}
|
||||||
if max_num_tracks > 0 {
|
|
||||||
if track_count_left == 0 {
|
|
||||||
cue_tracks.clear();
|
|
||||||
} else {
|
|
||||||
if cue_tracks.len() > track_count_left {
|
|
||||||
log::info!("Only analysing {} cue tracks", track_count_left);
|
|
||||||
cue_tracks.truncate(track_count_left);
|
|
||||||
}
|
|
||||||
track_count_left -= track_paths.len();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !track_paths.is_empty() {
|
if !track_paths.is_empty() {
|
||||||
match analyse_new_files(&db, &mpath, track_paths) {
|
match analyse_new_files(&db, &mpath, track_paths) {
|
||||||
@@ -366,17 +238,11 @@ pub fn analyse_files(db_path: &str, mpaths: &Vec<PathBuf>, dry_run: bool, keep_o
|
|||||||
Err(e) => { log::error!("Analysis returned error: {}", e); }
|
Err(e) => { log::error!("Analysis returned error: {}", e); }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::info!("No new tracks to analyse");
|
log::info!("No new files to analyse");
|
||||||
}
|
|
||||||
|
|
||||||
if !cue_tracks.is_empty() {
|
|
||||||
if let Err(e) = analyse_new_cue_tracks(&db, &mpath, cue_tracks) {
|
|
||||||
log::error!("Cue analysis returned error: {}", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if max_num_tracks > 0 && track_count_left <= 0 {
|
if max_num_tracks > 0 && track_count_left <= 0 {
|
||||||
log::info!("Track limit reached");
|
log::info!("File limit reached");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-97
@@ -1,97 +0,0 @@
|
|||||||
/**
|
|
||||||
* Analyse music with Bliss
|
|
||||||
*
|
|
||||||
* Copyright (c) 2022 Craig Drummond <craig.p.drummond@gmail.com>
|
|
||||||
* GPLv3 license.
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
|
|
||||||
extern crate rcue;
|
|
||||||
|
|
||||||
use rcue::parser::parse_from_file;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
pub const MARKER: &str = ".CUE_TRACK.";
|
|
||||||
pub const LAST_TRACK_DURATION: u64 = 60 * 60 * 24;
|
|
||||||
const GENRE: &str = "GENRE";
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct CueTrack {
|
|
||||||
pub audio_path: PathBuf,
|
|
||||||
pub track_path: PathBuf,
|
|
||||||
pub title: String,
|
|
||||||
pub artist: String,
|
|
||||||
pub album: String,
|
|
||||||
pub album_artist: String,
|
|
||||||
pub genre: String,
|
|
||||||
pub start: Duration,
|
|
||||||
pub duration: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse(audio_path: &PathBuf, cue_path: &PathBuf) -> Vec<CueTrack> {
|
|
||||||
let mut resp: Vec<CueTrack> = Vec::new();
|
|
||||||
|
|
||||||
match parse_from_file(&cue_path.to_string_lossy(), false) {
|
|
||||||
Ok(mut cue) => {
|
|
||||||
let album = cue.title.unwrap_or(String::new());
|
|
||||||
let album_artist = cue.performer.unwrap_or(String::new());
|
|
||||||
let mut genre = String::new();
|
|
||||||
for comment in cue.comments {
|
|
||||||
if comment.0.eq(GENRE) {
|
|
||||||
genre = comment.1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(file) = cue.files.pop() {
|
|
||||||
for track in file.tracks {
|
|
||||||
match track.indices.get(0) {
|
|
||||||
Some((_, start)) => {
|
|
||||||
let mut track_path = audio_path.clone();
|
|
||||||
let ext = audio_path.extension().unwrap().to_string_lossy();
|
|
||||||
track_path.set_extension(format!("{}{}{}", ext, MARKER, resp.len() + 1));
|
|
||||||
|
|
||||||
let mut ctrack = CueTrack {
|
|
||||||
audio_path: audio_path.clone(),
|
|
||||||
track_path,
|
|
||||||
title: track.title.unwrap_or_default(),
|
|
||||||
artist: track.performer.unwrap_or_default(),
|
|
||||||
album_artist: album_artist.clone(),
|
|
||||||
album: album.clone(),
|
|
||||||
genre: genre.clone(),
|
|
||||||
start: start.clone(),
|
|
||||||
duration: Duration::new(LAST_TRACK_DURATION, 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
if ctrack.artist.is_empty() && !ctrack.album_artist.is_empty() {
|
|
||||||
ctrack.artist = ctrack.album_artist.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctrack.album.is_empty() {
|
|
||||||
if let Some(name) = audio_path.file_name() {
|
|
||||||
ctrack.album = String::from(name.to_string_lossy());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.push(ctrack);
|
|
||||||
}
|
|
||||||
None => { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => { log::error!("Failed to parse '{}'. {}", cue_path.to_string_lossy(), e); }
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 0..(resp.len() - 1) {
|
|
||||||
let mut next_start = Duration::ZERO;
|
|
||||||
if let Some(next) = resp.get(i + 1) {
|
|
||||||
next_start = next.start;
|
|
||||||
}
|
|
||||||
if let Some(elem) = resp.get_mut(i) {
|
|
||||||
(*elem).duration = next_start - elem.start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
||||||
use crate::cue;
|
|
||||||
use crate::tags;
|
use crate::tags;
|
||||||
use bliss_audio::{Analysis, AnalysisIndex};
|
use bliss_audio::{Analysis, AnalysisIndex};
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
@@ -15,6 +14,8 @@ use std::convert::TryInto;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
|
pub const CUE_MARKER: &str = ".CUE_TRACK.";
|
||||||
|
|
||||||
pub struct FileMetadata {
|
pub struct FileMetadata {
|
||||||
pub rowid: usize,
|
pub rowid: usize,
|
||||||
pub file: String,
|
pub file: String,
|
||||||
@@ -173,7 +174,7 @@ impl Db {
|
|||||||
for tr in track_iter {
|
for tr in track_iter {
|
||||||
let mut db_path: String = tr.unwrap().0;
|
let mut db_path: String = tr.unwrap().0;
|
||||||
let orig_path = db_path.clone();
|
let orig_path = db_path.clone();
|
||||||
match orig_path.find(cue::MARKER) {
|
match orig_path.find(CUE_MARKER) {
|
||||||
Some(s) => {
|
Some(s) => {
|
||||||
db_path.truncate(s);
|
db_path.truncate(s);
|
||||||
}
|
}
|
||||||
@@ -266,7 +267,7 @@ impl Db {
|
|||||||
let mut updated = 0;
|
let mut updated = 0;
|
||||||
for tr in track_iter {
|
for tr in track_iter {
|
||||||
let dbtags = tr.unwrap();
|
let dbtags = tr.unwrap();
|
||||||
if !dbtags.file.contains(cue::MARKER) {
|
if !dbtags.file.contains(CUE_MARKER) {
|
||||||
let dtags = Metadata {
|
let dtags = Metadata {
|
||||||
title: dbtags.title.unwrap_or_default(),
|
title: dbtags.title.unwrap_or_default(),
|
||||||
artist: dbtags.artist.unwrap_or_default(),
|
artist: dbtags.artist.unwrap_or_default(),
|
||||||
|
|||||||
+4
-5
@@ -15,7 +15,6 @@ use std::io::Write;
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process;
|
use std::process;
|
||||||
mod analyse;
|
mod analyse;
|
||||||
mod cue;
|
|
||||||
mod db;
|
mod db;
|
||||||
mod tags;
|
mod tags;
|
||||||
mod upload;
|
mod upload;
|
||||||
@@ -33,7 +32,7 @@ fn main() {
|
|||||||
let mut dry_run: bool = false;
|
let mut dry_run: bool = false;
|
||||||
let mut task = "".to_string();
|
let mut task = "".to_string();
|
||||||
let mut lms_host = "127.0.0.1".to_string();
|
let mut lms_host = "127.0.0.1".to_string();
|
||||||
let mut max_num_tracks: usize = 0;
|
let mut max_num_files: usize = 0;
|
||||||
let mut music_paths: Vec<PathBuf> = Vec::new();
|
let mut music_paths: Vec<PathBuf> = Vec::new();
|
||||||
|
|
||||||
match dirs::home_dir() {
|
match dirs::home_dir() {
|
||||||
@@ -60,11 +59,11 @@ fn main() {
|
|||||||
arg_parse.refer(&mut music_path).add_option(&["-m", "--music"], Store, &music_path_help);
|
arg_parse.refer(&mut music_path).add_option(&["-m", "--music"], Store, &music_path_help);
|
||||||
arg_parse.refer(&mut db_path).add_option(&["-d", "--db"], Store, &db_path_help);
|
arg_parse.refer(&mut db_path).add_option(&["-d", "--db"], Store, &db_path_help);
|
||||||
arg_parse.refer(&mut logging).add_option(&["-l", "--logging"], Store, &logging_help);
|
arg_parse.refer(&mut logging).add_option(&["-l", "--logging"], Store, &logging_help);
|
||||||
arg_parse.refer(&mut keep_old).add_option(&["-k", "--keep-old"], StoreTrue, "Don't remove tracks from DB if they don't exist (used with analyse task)");
|
arg_parse.refer(&mut keep_old).add_option(&["-k", "--keep-old"], StoreTrue, "Don't remove files from DB if they don't exist (used with analyse task)");
|
||||||
arg_parse.refer(&mut dry_run).add_option(&["-r", "--dry-run"], StoreTrue, "Dry run, only show what needs to be done (used with analyse task)");
|
arg_parse.refer(&mut dry_run).add_option(&["-r", "--dry-run"], StoreTrue, "Dry run, only show what needs to be done (used with analyse task)");
|
||||||
arg_parse.refer(&mut ignore_file).add_option(&["-i", "--ignore"], Store, &ignore_file_help);
|
arg_parse.refer(&mut ignore_file).add_option(&["-i", "--ignore"], Store, &ignore_file_help);
|
||||||
arg_parse.refer(&mut lms_host).add_option(&["-L", "--lms"], Store, &lms_host_help);
|
arg_parse.refer(&mut lms_host).add_option(&["-L", "--lms"], Store, &lms_host_help);
|
||||||
arg_parse.refer(&mut max_num_tracks).add_option(&["-n", "--numtracks"], Store, "Maximum number of tracks to analyse");
|
arg_parse.refer(&mut max_num_files).add_option(&["-n", "--numfiles"], Store, "Maximum number of files to analyse");
|
||||||
arg_parse.refer(&mut task).add_argument("task", Store, "Task to perform; analyse, tags, ignore, upload, stopmixer.");
|
arg_parse.refer(&mut task).add_argument("task", Store, "Task to perform; analyse, tags, ignore, upload, stopmixer.");
|
||||||
arg_parse.parse_args_or_exit();
|
arg_parse.parse_args_or_exit();
|
||||||
}
|
}
|
||||||
@@ -176,7 +175,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
analyse::update_ignore(&db_path, &ignore_path);
|
analyse::update_ignore(&db_path, &ignore_path);
|
||||||
} else {
|
} else {
|
||||||
analyse::analyse_files(&db_path, &music_paths, dry_run, keep_old, max_num_tracks);
|
analyse::analyse_files(&db_path, &music_paths, dry_run, keep_old, max_num_files);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user