use rust loaders and refactor http fetch
This commit is contained in:
parent
f7033ffb5d
commit
4e078a857a
6 changed files with 359 additions and 169 deletions
319
Cargo.lock
generated
319
Cargo.lock
generated
|
@ -29,6 +29,18 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
|
@ -38,21 +50,6 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.93"
|
||||
|
@ -248,12 +245,14 @@ dependencies = [
|
|||
"gtk4",
|
||||
"http-cache",
|
||||
"http-cache-reqwest",
|
||||
"image",
|
||||
"libadwaita",
|
||||
"oo7",
|
||||
"rand",
|
||||
"reqwest",
|
||||
"reqwest-middleware",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
|
@ -268,6 +267,19 @@ version = "1.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "av-data"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fca67ba5d317924c02180c576157afd54babe48a76ebc66ce6d34bb8ba08308e"
|
||||
dependencies = [
|
||||
"byte-slice-cast",
|
||||
"bytes",
|
||||
"num-derive",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.74"
|
||||
|
@ -310,7 +322,7 @@ version = "0.70.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.6.0",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
|
@ -324,12 +336,27 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "bitreader"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "886559b1e163d56c765bc3a985febb4eee8009f625244511d8ee3c432e08c066"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
|
@ -373,6 +400,12 @@ version = "3.16.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
|
||||
[[package]]
|
||||
name = "byte-slice-cast"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.19.0"
|
||||
|
@ -385,6 +418,12 @@ version = "1.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder-lite"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.8.0"
|
||||
|
@ -424,7 +463,7 @@ version = "0.20.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7fa699e1d7ae691001a811dda5ef0e3e42e1d4119b26426352989df9e94e3e6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.6.0",
|
||||
"cairo-sys-rs",
|
||||
"glib",
|
||||
"libc",
|
||||
|
@ -438,7 +477,7 @@ checksum = "428290f914b9b86089f60f5d8a9f6e440508e1bcff23b25afd51502b0a2da88f"
|
|||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -468,6 +507,16 @@ dependencies = [
|
|||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.15.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02"
|
||||
dependencies = [
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-expr"
|
||||
version = "0.17.1"
|
||||
|
@ -496,13 +545,8 @@ version = "0.4.38"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -596,6 +640,28 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dav1d"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d4b54a40baf633a71c6f0fb49494a7e4ee7bc26f3e727212b6cb915aa1ea1e1"
|
||||
dependencies = [
|
||||
"av-data",
|
||||
"bitflags 2.6.0",
|
||||
"dav1d-sys",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dav1d-sys"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ecb1c5e8f4dc438eedc1b534a54672fb0e0a56035dae6b50162787bd2c50e95"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"system-deps 6.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
|
@ -706,12 +772,30 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible_collections"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd"
|
||||
dependencies = [
|
||||
"hashbrown 0.13.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4"
|
||||
|
||||
[[package]]
|
||||
name = "fdeflate"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb"
|
||||
dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "field-offset"
|
||||
version = "0.3.6"
|
||||
|
@ -871,7 +955,7 @@ dependencies = [
|
|||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -903,7 +987,7 @@ dependencies = [
|
|||
"libc",
|
||||
"pango-sys",
|
||||
"pkg-config",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -981,7 +1065,7 @@ dependencies = [
|
|||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
|
@ -991,7 +1075,7 @@ version = "0.20.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86bd3e4ee7998ab5a135d900db56930cc19ad16681adf245daff54f618b9d5e1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.6.0",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
|
@ -1035,7 +1119,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "3d0b1827e8621fc42c0dfb228e5d57ff6a71f9699e666ece8113f979ad87c2de"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1052,7 +1136,7 @@ checksum = "a4c674d2ff8478cf0ec29d2be730ed779fef54415a2fb4b565c52def62696462"
|
|||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1075,7 +1159,7 @@ dependencies = [
|
|||
"glib-sys",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1106,7 +1190,7 @@ dependencies = [
|
|||
"graphene-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1158,7 +1242,7 @@ dependencies = [
|
|||
"gsk4-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1180,6 +1264,15 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.1"
|
||||
|
@ -1386,29 +1479,6 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "1.5.0"
|
||||
|
@ -1548,6 +1618,33 @@ dependencies = [
|
|||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.25.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder-lite",
|
||||
"dav1d",
|
||||
"image-webp",
|
||||
"mp4parse",
|
||||
"num-traits",
|
||||
"png",
|
||||
"zune-core",
|
||||
"zune-jpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image-webp"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f"
|
||||
dependencies = [
|
||||
"byteorder-lite",
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.6.0"
|
||||
|
@ -1555,7 +1652,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"hashbrown 0.15.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1635,7 +1732,7 @@ dependencies = [
|
|||
"gtk4-sys",
|
||||
"libc",
|
||||
"pango-sys",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1776,6 +1873,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1790,13 +1888,27 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp4parse"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63a35203d3c6ce92d5251c77520acb2e57108c88728695aa883f70023624c570"
|
||||
dependencies = [
|
||||
"bitreader",
|
||||
"byteorder",
|
||||
"fallible_collections",
|
||||
"log",
|
||||
"num-traits",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
|
@ -1880,6 +1992,17 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
|
@ -2040,7 +2163,7 @@ dependencies = [
|
|||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"system-deps 7.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2094,6 +2217,19 @@ version = "0.3.31"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "3.7.4"
|
||||
|
@ -2152,6 +2288,12 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.6"
|
||||
|
@ -2397,11 +2539,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.40"
|
||||
version = "0.38.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0"
|
||||
checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.6.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
|
@ -2481,9 +2623,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.26"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1"
|
||||
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
@ -2494,7 +2636,7 @@ version = "2.11.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.6.0",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
|
@ -2638,6 +2780,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
|
@ -2735,13 +2883,26 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "6.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
|
||||
dependencies = [
|
||||
"cfg-expr 0.15.8",
|
||||
"heck",
|
||||
"pkg-config",
|
||||
"toml",
|
||||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-deps"
|
||||
version = "7.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66d23aaf9f331227789a99e8de4c91bf46703add012bdfd45fdecdfb2975a005"
|
||||
dependencies = [
|
||||
"cfg-expr",
|
||||
"cfg-expr 0.17.1",
|
||||
"heck",
|
||||
"pkg-config",
|
||||
"toml",
|
||||
|
@ -3270,16 +3431,7 @@ version = "0.58.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
|
||||
dependencies = [
|
||||
"windows-core 0.58.0",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
|
@ -3706,6 +3858,21 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
|
||||
|
||||
[[package]]
|
||||
name = "zune-jpeg"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768"
|
||||
dependencies = [
|
||||
"zune-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "4.2.0"
|
||||
|
|
15
Cargo.toml
15
Cargo.toml
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||
adw = { version = "0.7.0", package = "libadwaita", features = ["v1_6"] }
|
||||
async-channel = "2.3.1"
|
||||
bytes = "1.8.0"
|
||||
chrono = { version = "0.4.38", features = ["serde"] }
|
||||
chrono = { version = "0.4.38", features = ["serde", "std"], default-features = false }
|
||||
color-thief = "0.2.2"
|
||||
event-listener = "5.3.1"
|
||||
futures = "0.3.31"
|
||||
|
@ -19,6 +19,12 @@ http-cache = { version = "0.20.0", default-features = false, features = [
|
|||
"manager-cacache",
|
||||
] }
|
||||
http-cache-reqwest = "0.15.0"
|
||||
image = { version = "0.25.5", default-features = false, features = [
|
||||
"avif-native",
|
||||
"jpeg",
|
||||
"png",
|
||||
"webp",
|
||||
] }
|
||||
oo7 = "0.3.3"
|
||||
rand = "0.8"
|
||||
reqwest = { version = "0.12.9", default-features = false, features = [
|
||||
|
@ -28,8 +34,13 @@ reqwest = { version = "0.12.9", default-features = false, features = [
|
|||
"http2",
|
||||
"rustls-tls-native-roots",
|
||||
] }
|
||||
reqwest-middleware = { version = "0.4.0", features = ["json", "http2", "charset"] }
|
||||
reqwest-middleware = { version = "0.4.0", features = [
|
||||
"json",
|
||||
"http2",
|
||||
"charset",
|
||||
] }
|
||||
serde = { version = "1.0.214", features = ["derive"] }
|
||||
serde_json = "1.0.133"
|
||||
tokio = { version = "1", features = ["rt-multi-thread"] }
|
||||
tracing = { version = "0.1.40", default-features = false, features = [
|
||||
"attributes",
|
||||
|
|
|
@ -98,12 +98,12 @@ impl Song {
|
|||
*thumbnail_loading = Some(glib::spawn_future_local(async move {
|
||||
let _permit = SEM.acquire().await.unwrap();
|
||||
|
||||
let bytes = match api
|
||||
.cover_art(&id, Some(50 * scale_factor)) // see pixel-size in
|
||||
// play_queue_song.blp
|
||||
let pixbuf = match api
|
||||
// see pixel-size in play_queue_song.blp
|
||||
.cover_art(&id, Some(50 * scale_factor))
|
||||
.await
|
||||
{
|
||||
Ok(bytes) => bytes,
|
||||
Ok(pixbuf) => pixbuf,
|
||||
Err(err) => {
|
||||
event!(
|
||||
Level::ERROR,
|
||||
|
@ -113,13 +113,14 @@ impl Song {
|
|||
}
|
||||
};
|
||||
event!(target: "audrey::thumbnail_loader", Level::DEBUG, id = id, "fetched thumbnail");
|
||||
|
||||
let song = match song_weak.upgrade() {
|
||||
None => return,
|
||||
Some(song) => song,
|
||||
};
|
||||
song.set_thumbnail(
|
||||
gdk::Texture::from_bytes(&glib::Bytes::from_owned(bytes)).unwrap(),
|
||||
);
|
||||
|
||||
let texture = gdk::Texture::for_pixbuf(&pixbuf);
|
||||
song.set_thumbnail(texture);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
163
src/subsonic.rs
163
src/subsonic.rs
|
@ -3,8 +3,9 @@ pub mod schema;
|
|||
mod album_list;
|
||||
pub use album_list::AlbumListType;
|
||||
|
||||
use adw::glib;
|
||||
use bytes::Bytes;
|
||||
use gtk::glib;
|
||||
use image::ImageReader;
|
||||
use rand::Rng;
|
||||
use tracing::{event, Level};
|
||||
|
||||
|
@ -23,6 +24,8 @@ fn runtime() -> &'static tokio::runtime::Runtime {
|
|||
pub enum Error {
|
||||
UrlParseError(url::ParseError),
|
||||
ReqwestError(reqwest_middleware::Error),
|
||||
JsonDecodeError(serde_json::Error),
|
||||
ImageDecodeError(image::error::ImageError),
|
||||
SubsonicError(schema::Error),
|
||||
OtherError(&'static str),
|
||||
}
|
||||
|
@ -33,6 +36,8 @@ impl fmt::Display for Error {
|
|||
match self {
|
||||
Self::UrlParseError(err) => fmt::Display::fmt(err, f),
|
||||
Self::ReqwestError(err) => fmt::Display::fmt(err, f),
|
||||
Self::ImageDecodeError(err) => fmt::Display::fmt(err, f),
|
||||
Self::JsonDecodeError(err) => fmt::Display::fmt(err, f),
|
||||
Self::SubsonicError(err) => fmt::Display::fmt(&err.message, f),
|
||||
Self::OtherError(err) => fmt::Display::fmt(err, f),
|
||||
}
|
||||
|
@ -63,6 +68,12 @@ impl From<reqwest::Error> for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for Error {
|
||||
fn from(err: serde_json::Error) -> Self {
|
||||
Self::JsonDecodeError(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Client {
|
||||
client: reqwest_middleware::ClientWithMiddleware,
|
||||
|
@ -123,10 +134,7 @@ impl Client {
|
|||
|
||||
let http_cache = Cache(HttpCache {
|
||||
mode: CacheMode::default(),
|
||||
manager: CACacheManager {
|
||||
path: cache_dir,
|
||||
..Default::default()
|
||||
},
|
||||
manager: CACacheManager { path: cache_dir },
|
||||
options: HttpCacheOptions {
|
||||
cache_options: Some(CacheOptions {
|
||||
ignore_cargo_cult: true,
|
||||
|
@ -147,10 +155,7 @@ impl Client {
|
|||
Ok(Client { client, base_url })
|
||||
}
|
||||
|
||||
async fn send<T: serde::de::DeserializeOwned + Send + 'static>(
|
||||
&self,
|
||||
request: reqwest_middleware::RequestBuilder,
|
||||
) -> Result<T, Error> {
|
||||
async fn send(&self, request: reqwest_middleware::RequestBuilder) -> Result<Bytes, Error> {
|
||||
// FIXME: is an entire channel per request overkill? maybe pool them?
|
||||
let (sender, receiver) = async_channel::bounded(1);
|
||||
|
||||
|
@ -161,16 +166,27 @@ impl Client {
|
|||
let future = request.send();
|
||||
runtime().spawn(async move {
|
||||
// wrap this logic in a fn so we can use ?
|
||||
async fn perform<T: serde::de::DeserializeOwned + Send + 'static>(
|
||||
async fn perform(
|
||||
response: Result<reqwest::Response, reqwest_middleware::Error>,
|
||||
) -> Result<schema::SubsonicResponseOuter<T>, reqwest_middleware::Error> {
|
||||
) -> Result<Bytes, Error> {
|
||||
let response = response?.error_for_status()?;
|
||||
let xcache = response.headers()[http_cache::XCACHE].to_str().ok();
|
||||
event!(target: "audrey::http_request", Level::DEBUG, url=response.url().as_str(), status=response.status().as_str(), cache_status=xcache);
|
||||
let content_type = response.headers()[reqwest::header::CONTENT_TYPE]
|
||||
.to_str()
|
||||
.ok();
|
||||
event!(
|
||||
name: "response",
|
||||
target: "audrey::http",
|
||||
Level::DEBUG,
|
||||
url=response.url().as_str(),
|
||||
status=response.status().as_str(),
|
||||
cache_status=xcache,
|
||||
content_type=content_type
|
||||
);
|
||||
response
|
||||
.json::<schema::SubsonicResponseOuter<T>>()
|
||||
.bytes()
|
||||
.await
|
||||
.map_err(|e| reqwest_middleware::Error::Reqwest(e))
|
||||
.map_err(|e| Error::ReqwestError(reqwest_middleware::Error::Reqwest(e)))
|
||||
}
|
||||
|
||||
sender
|
||||
|
@ -179,16 +195,10 @@ impl Client {
|
|||
.expect("could not send subsonic response back to the main loop");
|
||||
});
|
||||
|
||||
let response = receiver
|
||||
receiver
|
||||
.recv()
|
||||
.await
|
||||
.expect("could not receive subsonic response from tokio")?
|
||||
.subsonic_response;
|
||||
|
||||
match response {
|
||||
schema::SubsonicResponse::Ok { inner } => Ok(inner),
|
||||
schema::SubsonicResponse::Failed { error } => Err(Error::SubsonicError(error)),
|
||||
}
|
||||
.expect("could not receive subsonic response from tokio")
|
||||
}
|
||||
|
||||
fn url(&self, path: &[&str], query: &[(&str, &str)]) -> url::Url {
|
||||
|
@ -201,22 +211,40 @@ impl Client {
|
|||
url
|
||||
}
|
||||
|
||||
async fn get<T: serde::de::DeserializeOwned + Send + 'static>(
|
||||
async fn get_bytes(&self, url: url::Url) -> Result<Bytes, Error> {
|
||||
self.send(self.client.get(url)).await
|
||||
}
|
||||
|
||||
async fn get_json<T: serde::de::DeserializeOwned + Send + 'static>(
|
||||
&self,
|
||||
path: &[&str],
|
||||
query: &[(&str, &str)],
|
||||
url: url::Url,
|
||||
) -> Result<T, Error> {
|
||||
self.send(self.client.get(self.url(path, query))).await
|
||||
let bytes = self.get_bytes(url).await?;
|
||||
serde_json::from_slice::<T>(&bytes).map_err(Error::JsonDecodeError)
|
||||
}
|
||||
|
||||
async fn get_subsonic<T: serde::de::DeserializeOwned + Send + 'static>(
|
||||
&self,
|
||||
url: url::Url,
|
||||
) -> Result<T, Error> {
|
||||
let response = self
|
||||
.get_json::<schema::SubsonicResponseOuter<T>>(url)
|
||||
.await?;
|
||||
|
||||
match response.subsonic_response {
|
||||
schema::SubsonicResponse::Ok { inner } => Ok(inner),
|
||||
schema::SubsonicResponse::Failed { error } => Err(Error::SubsonicError(error)),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn ping(&self) -> Result<(), Error> {
|
||||
self.get(&["rest", "ping"], &[]).await
|
||||
let url = self.url(&["rest", "ping"], &[]);
|
||||
self.get_bytes(url).await.map(|_| ())
|
||||
}
|
||||
|
||||
pub async fn random_songs(&self, size: u32) -> Result<Vec<schema::Child>, Error> {
|
||||
self.get::<schema::RandomSongsOuter>(
|
||||
&["rest", "getRandomSongs"],
|
||||
&[("size", &size.to_string())],
|
||||
self.get_subsonic::<schema::RandomSongsOuter>(
|
||||
self.url(&["rest", "getRandomSongs"], &[("size", &size.to_string())]),
|
||||
)
|
||||
.await
|
||||
.map(|response| response.random_songs.song)
|
||||
|
@ -232,53 +260,40 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn cover_art(&self, id: &str, size: Option<u32>) -> Result<Bytes, Error> {
|
||||
let (sender, receiver) = async_channel::bounded(1);
|
||||
pub async fn cover_art(
|
||||
&self,
|
||||
id: &str,
|
||||
size: Option<u32>,
|
||||
) -> Result<gtk::gdk_pixbuf::Pixbuf, Error> {
|
||||
let url = self.cover_art_url(id, size);
|
||||
let cover_art_bytes = self.get_bytes(url).await?;
|
||||
let image = ImageReader::new(std::io::BufReader::new(std::io::Cursor::new(
|
||||
cover_art_bytes,
|
||||
)))
|
||||
.with_guessed_format()
|
||||
.map_err(|e| Error::ImageDecodeError(image::ImageError::IoError(e)))?
|
||||
.decode()
|
||||
.map_err(Error::ImageDecodeError)?;
|
||||
|
||||
event!(target: "audrey::http_request_cover_art", Level::DEBUG, url = url.as_str());
|
||||
event!(Level::DEBUG, "loaded image: {:?}", image.color());
|
||||
let width = image.width();
|
||||
let height = image.height();
|
||||
// 8bpc rgba -> 32 -> 4 bytes
|
||||
let stride = width * 4;
|
||||
// gtk only supports 8bpc; maybe in the future we should handle hdr >8bpc too
|
||||
let image = image.into_rgba8().into_vec();
|
||||
|
||||
let future = self.client.get(url).send();
|
||||
runtime().spawn(async move {
|
||||
async fn perform(
|
||||
response: Result<reqwest::Response, reqwest_middleware::Error>,
|
||||
) -> Result<Bytes, Error> {
|
||||
let response = response?.error_for_status()?;
|
||||
let xcache = response.headers()[http_cache::XCACHE].to_str().ok();
|
||||
event!(target: "audrey::http_request_cover_art", Level::DEBUG, url=response.url().as_str(), status=response.status().as_str(), cache_status=xcache);
|
||||
if response.headers()[reqwest::header::CONTENT_TYPE]
|
||||
.to_str()
|
||||
.expect("bad content type")
|
||||
.starts_with("text/json")
|
||||
{
|
||||
match response
|
||||
.json::<schema::SubsonicResponseOuter<()>>()
|
||||
.await?
|
||||
.subsonic_response
|
||||
{
|
||||
schema::SubsonicResponse::Failed { error } => {
|
||||
Err(Error::SubsonicError(error))
|
||||
}
|
||||
_ => panic!("unlimited error but no error"),
|
||||
}
|
||||
} else {
|
||||
Ok(response.bytes().await?)
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(async_channel::SendError(_)) = sender.send(perform(future.await).await).await
|
||||
{
|
||||
event!(
|
||||
Level::INFO,
|
||||
"could not send cover art bytes to main loop (task cancelled?)"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
receiver
|
||||
.recv()
|
||||
.await
|
||||
.expect("could not receive cover art bytes from tokio")
|
||||
let pixbuf = gtk::gdk_pixbuf::Pixbuf::from_bytes(
|
||||
&glib::Bytes::from_owned(image),
|
||||
gtk::gdk_pixbuf::Colorspace::Rgb,
|
||||
true,
|
||||
8,
|
||||
// TODO: bubble up these to fail image loads instead of crashing
|
||||
width.try_into().unwrap(),
|
||||
height.try_into().unwrap(),
|
||||
stride.try_into().unwrap(),
|
||||
);
|
||||
Ok(pixbuf)
|
||||
}
|
||||
|
||||
pub fn stream_url(&self, id: &str) -> url::Url {
|
||||
|
|
|
@ -24,14 +24,14 @@ impl Client {
|
|||
) -> Result<Vec<schema::AlbumID3>, Error> {
|
||||
match type_ {
|
||||
AlbumListType::Newest => {
|
||||
self.get::<schema::AlbumList2Outer>(
|
||||
self.get_subsonic::<schema::AlbumList2Outer>(self.url(
|
||||
&["rest", "getAlbumList2"],
|
||||
&[
|
||||
("type", "newest"),
|
||||
("size", &size.to_string()),
|
||||
("offset", &offset.to_string()),
|
||||
],
|
||||
)
|
||||
))
|
||||
.await
|
||||
}
|
||||
|
||||
|
|
|
@ -663,11 +663,11 @@ mod imp {
|
|||
.loading_cover_handle
|
||||
.replace(Some(glib::spawn_future_local(async move {
|
||||
let api = window.imp().api.borrow().as_ref().unwrap().clone();
|
||||
let bytes = match api
|
||||
let pixbuf = match api
|
||||
.cover_art(&song_id, None) // full size
|
||||
.await
|
||||
{
|
||||
Ok(bytes) => bytes,
|
||||
Ok(pixbuf) => pixbuf,
|
||||
Err(err) => {
|
||||
event!(
|
||||
Level::ERROR,
|
||||
|
@ -679,13 +679,9 @@ mod imp {
|
|||
|
||||
match window.song() {
|
||||
Some(song) if song.id() == song_id => {
|
||||
let loader = gtk::gdk_pixbuf::PixbufLoader::new();
|
||||
loader.write(&bytes).unwrap();
|
||||
loader.close().unwrap();
|
||||
let pixbuf = loader.pixbuf().unwrap();
|
||||
|
||||
let texture = gdk::Texture::for_pixbuf(&pixbuf);
|
||||
window.set_playing_cover_art(Some(&texture.clone().into()));
|
||||
|
||||
window.set_playing_cover_art(Some(&texture.into()));
|
||||
|
||||
// from amberol
|
||||
let palette = color_thief::get_palette(
|
||||
|
|
Loading…
Reference in a new issue