diff --git a/.DS_Store b/.DS_Store index 8a655fcc..20e2b309 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..86e57e4c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,70 @@ +# Build artifacts +target/ +**/target/ + +# Webapp build artifacts and dependencies +pmoapp/webapp/node_modules/ +pmoapp/webapp/dist/ +**/node_modules/ + +# Git +.git/ +.gitignore +.jj/ + +# IDE and editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# macOS +.DS_Store + +# Cache directories +cache/ +.pmomusic/ + +# Log files +*.log + +# Documentation +doc/ +*.md +!Readme.md + +# Test files +test_upnp/ +examples/ + +# Temporary files +*.tmp +*.temp +*.pcap + +# Database files +db/ + +# Old code and backups +old_code/ +*.txt +!Cargo.lock + +# Development tools +tools/ +gupnp-tools/ + +# Build scripts (we have them in the Dockerfile) +Makefile +setup-deps.sh +setup-env.sh + +# SVG and other assets not needed for runtime +*.svg + +# Audio test files +*.ogg +*.flac +*.wav +*.mp3 diff --git a/.gitea/workflows/build-push.yaml b/.gitea/workflows/build-push.yaml new file mode 100644 index 00000000..340fb686 --- /dev/null +++ b/.gitea/workflows/build-push.yaml @@ -0,0 +1,29 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - main # Changez cela si votre branche principale a un autre nom + + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Setup cache + uses: actions/cache@v3 + with: + path: ~/.npm + key: dont-cache-${{ github.run_id }} + - name: Build and push image + uses: https://gargoton.petite-maison-orange.fr/pmo-actions/build-push-image@main + with: + image_name: public/pmomusic + image_tags: latest + no_cache: true + version_file: version.txt + check_uuid: 82a30d23-b3bd-4199-9237-776965831d20 + + + \ No newline at end of file diff --git a/.gitignore b/.gitignore index 69c4c5f2..ef7ac385 100644 --- a/.gitignore +++ b/.gitignore @@ -41,5 +41,5 @@ test_upnp*.cargo/ setup-env.sh cache gupnp-tools -pmocontrol_[0_9]*.txt +pmo*_[0_9]*.txt webapp_[0_9]*.txt \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 41782122..3736cee7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,6 +32,41 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if 1.0.4", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -64,7 +99,7 @@ checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ "alsa-sys", "bitflags 2.10.0", - "cfg-if", + "cfg-if 1.0.4", "libc", ] @@ -140,28 +175,215 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if 1.0.4", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.2", + "slab", + "windows-sys 0.61.2", +] + [[package]] name = "async-lock" version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel 2.5.0", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if 1.0.4", + "event-listener 5.4.1", + "futures-lite", + "rustix 1.1.2", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if 1.0.4", + "futures-core", + "futures-io", + "rustix 1.1.2", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-std" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8e079a4ab67ae52b7403632e4618815d6db36d2a010cfe41b02c1b1578f93b" +dependencies = [ + "async-attributes", + "async-channel 1.9.0", + "async-global-executor", + "async-io", + "async-lock", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-stream" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22068c0c19514942eefcfd4daf8976ef1aad84e61539f95cd200c35202f80af5" +dependencies = [ + "async-stream-impl 0.2.1", + "futures-core", +] + [[package]] name = "async-stream" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ - "async-stream-impl", + "async-stream-impl 0.3.6", "futures-core", "pin-project-lite", ] +[[package]] +name = "async-stream-impl" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f9db3b38af870bf7e5cc649167533b493928e50744e2c30ae350230b414670" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "async-stream-impl" version = "0.3.6" @@ -173,6 +395,12 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + [[package]] name = "async-trait" version = "0.1.89" @@ -230,6 +458,28 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "aws-lc-rs" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "axum" version = "0.7.9" @@ -537,6 +787,19 @@ dependencies = [ "objc2", ] +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel 2.5.0", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "built" version = "0.7.1" @@ -645,6 +908,12 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.4" @@ -671,6 +940,16 @@ dependencies = [ "windows-link", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clang-sys" version = "1.8.1" @@ -729,7 +1008,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" dependencies = [ "castaway", - "cfg-if", + "cfg-if 1.0.4", "itoa", "ryu", "static_assertions", @@ -901,7 +1180,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", ] [[package]] @@ -982,9 +1261,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "dasp_sample" version = "0.11.0" @@ -1113,6 +1402,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd" +[[package]] +name = "dns-parser" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4d33be9473d06f75f58220f71f7a9317aca647dc061dbd3c361b0bef505fbea" +dependencies = [ + "byteorder", + "quick-error 1.2.3", +] + [[package]] name = "document-features" version = "0.2.12" @@ -1128,6 +1427,12 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.15.0" @@ -1140,7 +1445,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", ] [[package]] @@ -1180,6 +1485,20 @@ dependencies = [ "typeid", ] +[[package]] +name = "err-derive" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22deed3a8124cff5fa835713fa105621e43bbdc46690c3a6b68328a012d350d4" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", + "synstructure 0.12.6", +] + [[package]] name = "errno" version = "0.3.14" @@ -1190,6 +1509,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "event-listener" version = "5.4.1" @@ -1207,7 +1532,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener", + "event-listener 5.4.1", "pin-project-lite", ] @@ -1366,6 +1691,12 @@ dependencies = [ "tokio", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.31" @@ -1414,6 +1745,19 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.31" @@ -1499,7 +1843,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "libc", "wasi", ] @@ -1510,12 +1854,22 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "libc", "r-efi", "wasip2", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gif" version = "0.13.3" @@ -1541,6 +1895,18 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "h2" version = "0.4.12" @@ -1566,7 +1932,7 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "crunchy", "zerocopy", ] @@ -1658,6 +2024,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "htmlescape" version = "0.3.1" @@ -1967,7 +2342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" dependencies = [ "byteorder-lite", - "quick-error", + "quick-error 2.0.1", ] [[package]] @@ -1998,6 +2373,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "interpolate_name" version = "0.2.4" @@ -2074,7 +2458,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ "cesu8", - "cfg-if", + "cfg-if 1.0.4", "combine", "jni-sys", "log", @@ -2109,6 +2493,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -2164,7 +2557,7 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "windows-link", ] @@ -2217,6 +2610,12 @@ dependencies = [ "zlib-rs", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -2275,6 +2674,9 @@ name = "log" version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +dependencies = [ + "value-bag", +] [[package]] name = "loop9" @@ -2330,7 +2732,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "rayon", ] @@ -2340,10 +2742,26 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "digest", ] +[[package]] +name = "mdns" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c769962ac75a6ea437f0922b27834bcccd4c013d591383a16ae5731e3ef0f3f3" +dependencies = [ + "async-std", + "async-stream 0.2.1", + "dns-parser", + "err-derive", + "futures-core", + "futures-util", + "log", + "net2", +] + [[package]] name = "memchr" version = "2.7.6" @@ -2460,7 +2878,7 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "equivalent", - "event-listener", + "event-listener 5.4.1", "futures-util", "parking_lot", "portable-atomic", @@ -2526,6 +2944,17 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + [[package]] name = "netlink-packet-core" version = "0.7.0" @@ -2606,7 +3035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags 2.10.0", - "cfg-if", + "cfg-if 1.0.4", "cfg_aliases", "libc", ] @@ -2959,6 +3388,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl" version = "0.10.75" @@ -2966,7 +3401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ "bitflags 2.10.0", - "cfg-if", + "cfg-if 1.0.4", "foreign-types", "libc", "once_cell", @@ -3057,7 +3492,7 @@ version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "libc", "redox_syscall", "smallvec", @@ -3108,6 +3543,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -3201,6 +3647,7 @@ name = "pmocache" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", "axum 0.8.7", "bytes", "chrono", @@ -3208,6 +3655,7 @@ dependencies = [ "hex", "paste", "pmoconfig", + "pmoflac", "reqwest", "rusqlite", "serde", @@ -3226,8 +3674,10 @@ dependencies = [ name = "pmoconfig" version = "0.1.0" dependencies = [ + "aes-gcm", "anyhow", "axum 0.8.7", + "base64 0.22.1", "dirs", "lazy_static", "log", @@ -3235,6 +3685,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", + "sha2", "tokio", "tracing", "utoipa", @@ -3246,20 +3697,26 @@ name = "pmocontrol" version = "0.1.0" dependencies = [ "anyhow", - "async-stream", + "async-std", + "async-stream 0.3.6", "async-trait", "axum 0.8.7", "chrono", "crossbeam-channel", "crossterm", + "futures-util", + "mdns", "percent-encoding", "pmodidl", "pmoserver", "pmoupnp", "quick-xml 0.38.4", "ratatui", + "rust_cast", + "rustls", "serde", "serde_json", + "smol", "thiserror 2.0.17", "tokio", "tokio-stream", @@ -3286,6 +3743,7 @@ dependencies = [ "pmoserver", "reqwest", "serde", + "serde_json", "tempfile", "tokio", "tracing", @@ -3384,7 +3842,7 @@ name = "pmoparadise" version = "0.1.0" dependencies = [ "anyhow", - "async-stream", + "async-stream 0.3.6", "async-trait", "axum 0.8.7", "bytes", @@ -3428,7 +3886,7 @@ name = "pmoplaylist" version = "0.1.0" dependencies = [ "anyhow", - "async-stream", + "async-stream 0.3.6", "axum 0.8.7", "chrono", "once_cell", @@ -3452,21 +3910,31 @@ name = "pmoqobuz" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", "axum 0.8.7", + "base64 0.22.1", "chrono", "hex", + "indexmap 2.12.0", + "md-5", "mockito", "moka", "pmoaudiocache", + "pmocache", "pmoconfig", "pmocovers", "pmodidl", + "pmoplaylist", "pmoserver", "pmosource", + "regex", "reqwest", + "rusqlite", "serde", "serde_json", + "serde_yaml", "sha1", + "tempfile", "thiserror 1.0.69", "tokio", "tokio-test", @@ -3480,7 +3948,7 @@ name = "pmoserver" version = "0.1.0" dependencies = [ "anyhow", - "async-stream", + "async-stream 0.3.6", "axum 0.8.7", "axum-embed", "axum-server", @@ -3510,6 +3978,7 @@ dependencies = [ "futures", "lazy_static", "pmoaudiocache", + "pmocache", "pmoconfig", "pmocovers", "pmodidl", @@ -3589,6 +4058,32 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if 1.0.4", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.2", + "windows-sys 0.61.2", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if 1.0.4", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.11.1" @@ -3647,6 +4142,30 @@ dependencies = [ "toml_edit 0.23.7", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.103" @@ -3707,6 +4226,57 @@ dependencies = [ "prost", ] +[[package]] +name = "protobuf" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58678a64de2fced2bdec6bca052a6716a0efe692d6e3f53d1bda6a1def64cfc0" +dependencies = [ + "once_cell", + "protobuf-support", + "thiserror 1.0.69", +] + +[[package]] +name = "protobuf-codegen" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32777b0b3f6538d9d2e012b3fad85c7e4b9244b5958d04a6415f4333782b7a77" +dependencies = [ + "anyhow", + "once_cell", + "protobuf", + "protobuf-parse", + "regex", + "tempfile", + "thiserror 1.0.69", +] + +[[package]] +name = "protobuf-parse" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96cb37955261126624a25b5e6bda40ae34cf3989d52a783087ca6091b29b5642" +dependencies = [ + "anyhow", + "indexmap 1.9.3", + "log", + "protobuf", + "protobuf-support", + "tempfile", + "thiserror 1.0.69", + "which", +] + +[[package]] +name = "protobuf-support" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ed294a835b0f30810e13616b1cd34943c6d1e84a8f3b0dcfe466d256c3e7e7" +dependencies = [ + "thiserror 1.0.69", +] + [[package]] name = "psl-types" version = "2.0.11" @@ -3741,6 +4311,12 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-error" version = "2.0.1" @@ -3873,7 +4449,7 @@ dependencies = [ "av1-grain", "bitstream-io", "built", - "cfg-if", + "cfg-if 1.0.4", "interpolate_name", "itertools 0.12.1", "libc", @@ -3905,7 +4481,7 @@ dependencies = [ "avif-serialize", "imgref", "loop9", - "quick-error", + "quick-error 2.0.1", "rav1e", "rayon", "rgb", @@ -4039,7 +4615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "cfg-if", + "cfg-if 1.0.4", "getrandom 0.2.16", "libc", "untrusted", @@ -4094,6 +4670,23 @@ dependencies = [ "walkdir", ] +[[package]] +name = "rust_cast" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "132d5179ff5b592ad1286a4e9ed50e63d5ea789a956a8183914df0b74741f24c" +dependencies = [ + "byteorder", + "log", + "protobuf", + "protobuf-codegen", + "rustls", + "rustls-native-certs", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "rustc-hash" version = "2.1.1" @@ -4109,6 +4702,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + [[package]] name = "rustix" version = "1.1.2" @@ -4118,7 +4724,7 @@ dependencies = [ "bitflags 2.10.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.11.0", "windows-sys 0.61.2", ] @@ -4128,6 +4734,7 @@ version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", @@ -4137,6 +4744,28 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "rustls-pki-types" version = "1.13.0" @@ -4152,6 +4781,7 @@ version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -4322,7 +4952,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "cpufeatures", "digest", ] @@ -4333,7 +4963,7 @@ version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "cpufeatures", "digest", ] @@ -4427,6 +5057,23 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "smol" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33bd3e260892199c3ccfc487c88b2da2265080acb316cd920da72fdfd7c599f" +dependencies = [ + "async-channel 2.5.0", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + [[package]] name = "smol_str" version = "0.2.2" @@ -4752,6 +5399,18 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -4769,7 +5428,7 @@ version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "core-foundation-sys", "libc", "ntapi", @@ -4833,7 +5492,7 @@ dependencies = [ "fastrand", "getrandom 0.3.4", "once_cell", - "rustix", + "rustix 1.1.2", "windows-sys 0.61.2", ] @@ -4883,7 +5542,7 @@ version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", ] [[package]] @@ -4895,7 +5554,7 @@ dependencies = [ "fax", "flate2", "half", - "quick-error", + "quick-error 2.0.1", "weezl", "zune-jpeg", ] @@ -5023,7 +5682,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" dependencies = [ - "async-stream", + "async-stream 0.3.6", "bytes", "futures-core", "tokio", @@ -5113,7 +5772,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ - "async-stream", + "async-stream 0.3.6", "async-trait", "axum 0.7.9", "base64 0.22.1", @@ -5329,6 +5988,22 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "unsafe-libyaml" version = "0.2.11" @@ -5482,6 +6157,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" + [[package]] name = "variadics_please" version = "1.1.0" @@ -5551,7 +6232,7 @@ version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "once_cell", "rustversion", "wasm-bindgen-macro", @@ -5564,7 +6245,7 @@ version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "js-sys", "once_cell", "wasm-bindgen", @@ -5666,6 +6347,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + [[package]] name = "winapi" version = "0.2.8" @@ -6206,7 +6899,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.110", - "synstructure", + "synstructure 0.13.2", ] [[package]] @@ -6247,7 +6940,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.110", - "synstructure", + "synstructure 0.13.2", ] [[package]] diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 00000000..07079d0b --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,302 @@ +# Docker Deployment Guide for PMOMusic + +Ce guide explique comment construire et déployer PMOMusic avec Docker. + +## Architecture + +Le Dockerfile utilise une approche multi-stage pour créer une image minimale : + +1. **Stage 1 (webapp-builder)** : Compile l'application Vue.js avec Node.js +2. **Stage 2 (rust-builder)** : Compile le binaire Rust avec toutes ses dépendances +3. **Stage 3 (runtime)** : Image finale minimale Debian Slim avec uniquement le binaire et les bibliothèques runtime + +### Avantages + +- **Binaire auto-contenu** : L'application web est embarquée dans le binaire Rust +- **Image minimale** : ~200-300MB (vs plusieurs GB pour les images de build) +- **Sécurité** : Exécution en tant qu'utilisateur non-root +- **Reproductibilité** : Build complet et déterministe + +## Build de l'image + +### Option 1 : Build manuel avec Docker + +```bash +# Build l'image +docker build -t pmomusic:latest . + +# Le build prend environ 10-15 minutes selon votre machine +``` + +### Option 2 : Build avec docker-compose + +```bash +# Build et démarre le conteneur +docker-compose up --build + +# Ou juste build +docker-compose build +``` + +### Build optimisé avec cache + +Pour accélérer les builds successifs, Docker réutilise les couches en cache : + +```bash +# Build avec cache +docker build -t pmomusic:latest . + +# Build sans cache (force rebuild complet) +docker build --no-cache -t pmomusic:latest . +``` + +## Exécution du conteneur + +### Option 1 : Avec docker-compose (recommandé) + +```bash +# Démarrer en arrière-plan +docker-compose up -d + +# Voir les logs +docker-compose logs -f + +# Arrêter +docker-compose down + +# Redémarrer +docker-compose restart +``` + +### Option 2 : Avec docker run + +```bash +# Run en mode interactif +docker run -it --rm \ + --name pmomusic \ + --network host \ + -v $(pwd)/config:/home/pmomusic/.pmomusic \ + -v $(pwd)/cache:/home/pmomusic/cache \ + pmomusic:latest + +# Run en mode détaché +docker run -d \ + --name pmomusic \ + --network host \ + --restart unless-stopped \ + -v $(pwd)/config:/home/pmomusic/.pmomusic \ + -v $(pwd)/cache:/home/pmomusic/cache \ + pmomusic:latest +``` + +## Configuration + +### Ports + +Par défaut, PMOMusic écoute sur le port **8080**. Vous pouvez modifier cela : + +- Dans `docker-compose.yml` : modifier la section `ports` +- Avec `docker run` : utiliser `-p 8080:8080` + +### Volumes + +Deux volumes sont recommandés pour la persistance : + +- **Configuration** : `/home/pmomusic/.pmomusic` - Fichiers de configuration +- **Cache** : `/home/pmomusic/cache` - Cache audio et métadonnées + +### Variables d'environnement + +Configurable via `docker-compose.yml` ou `-e` avec `docker run` : + +```bash +# Niveau de logs Rust +RUST_LOG=debug + +# Autres variables (selon votre configuration) +# ... +``` + +### Réseau + +Pour UPnP/DLNA, utilisez **network_mode: host** pour permettre : +- La découverte multicast +- La communication avec les devices UPnP sur le réseau local + +**Note** : Le mode `host` ne fonctionne que sur Linux. Sur macOS/Windows avec Docker Desktop, utilisez le mapping de ports standard. + +## Gestion de l'image + +### Taille de l'image + +```bash +# Voir la taille de l'image +docker images pmomusic:latest + +# Résultat attendu : ~200-300MB +``` + +### Nettoyage + +```bash +# Supprimer l'image +docker rmi pmomusic:latest + +# Nettoyer les images de build intermédiaires +docker builder prune + +# Nettoyer tous les caches Docker (libère beaucoup d'espace) +docker system prune -a +``` + +## Build multi-plateforme + +Pour builder pour différentes architectures (ARM64, AMD64) : + +```bash +# Créer un builder multi-plateforme +docker buildx create --name multiarch --use + +# Build pour AMD64 et ARM64 +docker buildx build \ + --platform linux/amd64,linux/arm64 \ + -t pmomusic:latest \ + --push \ + . + +# Note : nécessite un registry Docker (Docker Hub, GHCR, etc.) +``` + +## Déploiement en production + +### 1. Avec docker-compose (simple) + +```bash +# Sur le serveur de production +git clone +cd pmomusic +docker-compose up -d +``` + +### 2. Avec un registry Docker (recommandé) + +```bash +# Sur votre machine de dev +docker build -t yourregistry.com/pmomusic:v1.0.0 . +docker push yourregistry.com/pmomusic:v1.0.0 + +# Sur le serveur de production +docker pull yourregistry.com/pmomusic:v1.0.0 +docker run -d ... yourregistry.com/pmomusic:v1.0.0 +``` + +### 3. Avec un orchestrateur (Kubernetes, Docker Swarm) + +Créer un fichier de déploiement approprié selon votre orchestrateur. + +## Debugging + +### Logs du conteneur + +```bash +# Logs en temps réel +docker logs -f pmomusic + +# Logs avec docker-compose +docker-compose logs -f +``` + +### Entrer dans le conteneur + +```bash +# Shell interactif (bash n'est pas disponible, utiliser sh) +docker exec -it pmomusic sh + +# Vérifier les processus +docker exec -it pmomusic ps aux + +# Vérifier les fichiers +docker exec -it pmomusic ls -la /home/pmomusic +``` + +### Health check + +Le conteneur inclut un health check. Vérifier l'état : + +```bash +# Voir l'état de santé +docker inspect --format='{{.State.Health.Status}}' pmomusic +``` + +## Troubleshooting + +### Le build échoue + +1. **Erreur de dépendances npm** : + - Vérifier que `pmoapp/webapp/package.json` est correct + - Essayer `docker build --no-cache` + +2. **Erreur de compilation Rust** : + - Vérifier que tous les fichiers Cargo.toml sont présents + - Vérifier les dépendances système (libsoxr, libasound2) + +3. **Out of memory** : + - Augmenter la mémoire allouée à Docker Desktop (settings) + - Utiliser `--memory` pour limiter la mémoire du build + +### Le conteneur ne démarre pas + +1. **Port déjà utilisé** : + ```bash + # Vérifier quel processus utilise le port 8080 + sudo lsof -i :8080 + ``` + +2. **Permissions** : + - Vérifier les permissions des volumes montés + - Le conteneur s'exécute en tant qu'utilisateur `pmomusic` (UID 1000) + +3. **Configuration manquante** : + - Créer les répertoires de configuration avant de démarrer : + ```bash + mkdir -p config cache + ``` + +### UPnP ne fonctionne pas + +1. **Network mode** : + - Sur Linux : utiliser `network_mode: host` + - Sur macOS/Windows : UPnP peut ne pas fonctionner correctement avec Docker Desktop + +2. **Firewall** : + - Vérifier que les ports UPnP ne sont pas bloqués + - Autoriser le multicast sur le réseau + +## Performance + +### Optimisations du build + +1. **Build cache** : Docker réutilise les couches en cache +2. **Multi-stage build** : Réduit la taille de l'image finale +3. **Strip des symboles** : Le binaire est strippé pour réduire sa taille + +### Optimisations runtime + +1. **Resource limits** : Définir des limites CPU/mémoire dans docker-compose.yml +2. **Volumes** : Utiliser des volumes pour les données persistantes +3. **Logs** : Configurer la rotation des logs Docker + +## Sécurité + +- ✅ Exécution en tant qu'utilisateur non-root +- ✅ Image minimale (surface d'attaque réduite) +- ✅ Pas de secrets dans l'image +- ✅ Health checks activés +- ✅ Certificats CA inclus pour HTTPS + +## Références + +- [Dockerfile](./Dockerfile) +- [docker-compose.yml](./docker-compose.yml) +- [.dockerignore](./.dockerignore) +- [Documentation Rust](./Readme.md) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..5ad73435 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,108 @@ +# =================================== +# Stage 1: Build Vue.js webapp +# =================================== +FROM node:22-alpine AS webapp-builder + +WORKDIR /webapp + +# Copy webapp package files +COPY pmoapp/webapp/package*.json ./ + +# Install dependencies +RUN npm ci --production=false + +# Copy webapp source +COPY pmoapp/webapp/ ./ + +# Build the webapp +RUN npm run build + +# =================================== +# Stage 2: Build Rust binary +# =================================== +FROM rustlang/rust:nightly-bookworm AS rust-builder + +WORKDIR /build + +# Install system dependencies for building +RUN apt-get update && apt-get install -y \ + libsoxr-dev \ + libasound2-dev \ + pkg-config \ + cmake \ + && rm -rf /var/lib/apt/lists/* + +# Copy Cargo workspace files +COPY Cargo.toml Cargo.lock ./ + +# Copy all crates +COPY PMOMusic/ ./PMOMusic/ +COPY pmoupnp/ ./pmoupnp/ +COPY pmomediarenderer/ ./pmomediarenderer/ +COPY pmomediaserver/ ./pmomediaserver/ +COPY pmoconfig/ ./pmoconfig/ +COPY pmoutils/ ./pmoutils/ +COPY pmodidl/ ./pmodidl/ +COPY pmoserver/ ./pmoserver/ +COPY pmocache/ ./pmocache/ +COPY pmocovers/ ./pmocovers/ +COPY pmoaudiocache/ ./pmoaudiocache/ +COPY pmoaudio/ ./pmoaudio/ +COPY pmoqobuz/ ./pmoqobuz/ +COPY pmoparadise/ ./pmoparadise/ +COPY pmosource/ ./pmosource/ +COPY pmoplaylist/ ./pmoplaylist/ +COPY pmoflac/ ./pmoflac/ +COPY pmometadata/ ./pmometadata/ +COPY pmocontrol/ ./pmocontrol/ +COPY pmoaudio-ext/ ./pmoaudio-ext/ +COPY pmoapp/ ./pmoapp/ + +# Copy the webapp dist from previous stage +COPY --from=webapp-builder /webapp/dist ./pmoapp/webapp/dist/ + +# Build the Rust binary in release mode +RUN cargo build --release --bin PMOMusic + +# Strip debug symbols to reduce binary size +RUN strip /build/target/release/PMOMusic + +# =================================== +# Stage 3: Minimal runtime image +# =================================== +FROM debian:bookworm-slim + +# Install only runtime dependencies +RUN apt-get update && apt-get install -y \ + libsoxr0 \ + libasound2 \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Create a non-root user +RUN useradd -m -u 1000 pmomusic + +# Copy the binary from builder +COPY --from=rust-builder /build/target/release/PMOMusic /usr/local/bin/PMOMusic + +# Set ownership +RUN chown pmomusic:pmomusic /usr/local/bin/PMOMusic + +# Switch to non-root user +USER pmomusic + +# Create directories for configuration and cache +RUN mkdir -p /home/pmomusic/.pmomusic + +# Set working directory +WORKDIR /home/pmomusic + +# Expose default port (adjust if needed) +EXPOSE 8080 + +# Health check (adjust the URL if needed) +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD ["/usr/local/bin/PMOMusic", "--help"] || exit 1 + +# Run the binary +ENTRYPOINT ["/usr/local/bin/PMOMusic"] diff --git a/PMOMusic/src/main.rs b/PMOMusic/src/main.rs index 9db7cac2..9e44eb03 100644 --- a/PMOMusic/src/main.rs +++ b/PMOMusic/src/main.rs @@ -38,10 +38,10 @@ async fn main() -> Result<(), Box> { // Enregistrer les sources musicales info!("🎵 Registering music sources..."); - // // Enregistrer Qobuz - // if let Err(e) = server.write().await.register_qobuz().await { - // tracing::warn!("⚠️ Failed to register Qobuz: {}", e); - // } + // Enregistrer Qobuz pour activer les lazy providers (QOBUZ:PK) + if let Err(e) = server.write().await.register_qobuz().await { + tracing::warn!("⚠️ Failed to register Qobuz source: {}", e); + } // Initialiser les canaux de streaming Radio Paradise (pipelines + routes HTTP) info!("📻 Initializing Radio Paradise streaming channels..."); diff --git a/docker-build.sh b/docker-build.sh new file mode 100755 index 00000000..f523baa7 --- /dev/null +++ b/docker-build.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# Script de build Docker pour PMOMusic +# Usage: ./docker-build.sh [OPTIONS] + +set -e + +# Couleurs pour l'affichage +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# Configuration par défaut +IMAGE_NAME="pmomusic" +TAG="latest" +NO_CACHE=false +PUSH=false +REGISTRY="" + +# Fonction d'aide +show_help() { + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " -t, --tag TAG Tag de l'image (défaut: latest)" + echo " -r, --registry URL Registry Docker (ex: ghcr.io/user)" + echo " -n, --no-cache Build sans cache" + echo " -p, --push Push l'image vers le registry" + echo " -h, --help Affiche cette aide" + echo "" + echo "Exemples:" + echo " $0 # Build local avec tag 'latest'" + echo " $0 -t v1.0.0 # Build avec tag 'v1.0.0'" + echo " $0 -t v1.0.0 -r ghcr.io/user -p # Build et push vers GHCR" + echo " $0 -n # Build sans cache" + exit 0 +} + +# Parsing des arguments +while [[ $# -gt 0 ]]; do + case $1 in + -t|--tag) + TAG="$2" + shift 2 + ;; + -r|--registry) + REGISTRY="$2" + shift 2 + ;; + -n|--no-cache) + NO_CACHE=true + shift + ;; + -p|--push) + PUSH=true + shift + ;; + -h|--help) + show_help + ;; + *) + echo -e "${RED}Erreur: Option inconnue '$1'${NC}" + show_help + ;; + esac +done + +# Construire le nom complet de l'image +if [ -n "$REGISTRY" ]; then + FULL_IMAGE_NAME="$REGISTRY/$IMAGE_NAME:$TAG" +else + FULL_IMAGE_NAME="$IMAGE_NAME:$TAG" +fi + +# Afficher la configuration +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN}Build Docker PMOMusic${NC}" +echo -e "${GREEN}========================================${NC}" +echo "" +echo "Image: $FULL_IMAGE_NAME" +echo "No cache: $NO_CACHE" +echo "Push: $PUSH" +echo "" + +# Construire la commande Docker +DOCKER_CMD="docker build" + +if [ "$NO_CACHE" = true ]; then + DOCKER_CMD="$DOCKER_CMD --no-cache" +fi + +DOCKER_CMD="$DOCKER_CMD -t $FULL_IMAGE_NAME ." + +# Exécuter le build +echo -e "${YELLOW}→ Démarrage du build...${NC}" +echo "Commande: $DOCKER_CMD" +echo "" + +if eval "$DOCKER_CMD"; then + echo "" + echo -e "${GREEN}✓ Build réussi !${NC}" + + # Afficher la taille de l'image + IMAGE_SIZE=$(docker images "$FULL_IMAGE_NAME" --format "{{.Size}}") + echo "Taille de l'image: $IMAGE_SIZE" + + # Push si demandé + if [ "$PUSH" = true ]; then + echo "" + echo -e "${YELLOW}→ Push de l'image vers le registry...${NC}" + + if docker push "$FULL_IMAGE_NAME"; then + echo -e "${GREEN}✓ Image pushée avec succès !${NC}" + else + echo -e "${RED}✗ Erreur lors du push${NC}" + exit 1 + fi + fi + + echo "" + echo -e "${GREEN}========================================${NC}" + echo -e "${GREEN}Build terminé avec succès !${NC}" + echo -e "${GREEN}========================================${NC}" + echo "" + echo "Pour lancer le conteneur:" + echo " docker run -it --rm --network host $FULL_IMAGE_NAME" + echo "" + echo "Ou avec docker-compose:" + echo " docker-compose up -d" + +else + echo "" + echo -e "${RED}✗ Erreur lors du build${NC}" + exit 1 +fi diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..f0916a54 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,39 @@ +version: '3.8' + +services: + pmomusic: + build: + context: . + dockerfile: Dockerfile + image: pmomusic:latest + container_name: pmomusic + + # Port mapping (adjust to your needs) + ports: + - "8080:8080" + + # Volume for persistent configuration + volumes: + - ./config:/home/pmomusic/.pmomusic + - ./cache:/home/pmomusic/cache + + # Environment variables (adjust as needed) + environment: + - RUST_LOG=info + # Add other environment variables here + + # Network mode for UPnP/DLNA discovery (host mode for multicast) + network_mode: host + + # Restart policy + restart: unless-stopped + + # Resource limits (optional) + deploy: + resources: + limits: + cpus: '2.0' + memory: 1G + reservations: + cpus: '0.5' + memory: 256M diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..a13a2658 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "pmomusic", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/pmoapp/webapp/package-lock.json b/pmoapp/webapp/package-lock.json index 09afc506..a36a612c 100644 --- a/pmoapp/webapp/package-lock.json +++ b/pmoapp/webapp/package-lock.json @@ -18,6 +18,7 @@ }, "devDependencies": { "@types/dompurify": "^3.0.5", + "@types/node": "^22.0.0", "@vitejs/plugin-vue": "^6.0.1", "@vue/tsconfig": "^0.8.1", "typescript": "~5.8.3", @@ -851,6 +852,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "22.19.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz", + "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -1502,6 +1514,13 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, "node_modules/vite": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.7.tgz", diff --git a/pmoapp/webapp/package.json b/pmoapp/webapp/package.json index e71fba0b..a69bb749 100644 --- a/pmoapp/webapp/package.json +++ b/pmoapp/webapp/package.json @@ -18,6 +18,7 @@ "vue-virtual-scroller": "^2.0.0-beta.8" }, "devDependencies": { + "@types/node": "^22.0.0", "@types/dompurify": "^3.0.5", "@vitejs/plugin-vue": "^6.0.1", "@vue/tsconfig": "^0.8.1", diff --git a/pmoapp/webapp/src/App.vue b/pmoapp/webapp/src/App.vue index 882ae346..a201f637 100644 --- a/pmoapp/webapp/src/App.vue +++ b/pmoapp/webapp/src/App.vue @@ -15,6 +15,7 @@ 🎵 UPnP Explorer 🎨 Cover Cache 🎵 Audio Cache + 🗂️ Playlists 🚀 API Dashboard diff --git a/pmoapp/webapp/src/components/AudioCacheManager.vue b/pmoapp/webapp/src/components/AudioCacheManager.vue index 91db4e24..c22468f6 100644 --- a/pmoapp/webapp/src/components/AudioCacheManager.vue +++ b/pmoapp/webapp/src/components/AudioCacheManager.vue @@ -4,6 +4,7 @@

🎵 Audio Cache Manager

{{ tracks.length }} tracks + {{ lazyTracksCount }} lazy pending {{ totalHits }} hits
@@ -12,14 +13,39 @@

➕ Add New Track

+
+ + +
+
+ + +
+

+ Local FLAC files are referenced without duplication. Removing the cache entry never deletes + the original file. +

- -

{{ addError }}

@@ -72,7 +98,7 @@
@@ -85,7 +111,15 @@ />
🎵
- {{ track.hits }} plays + {{ track.hits }} plays + + {{ lazyBadgeLabel(track) }} + + Local file
@@ -98,7 +132,19 @@
{{ track.metadata.album }}
-
{{ track.pk }}
+
+ {{ track.pk }} + + Lazy + + {{ lazyProviderName(track) }} + + +
{{ formatDuration(durationMs(track)!) }} @@ -113,18 +159,29 @@ {{ conversionLabel(track) }}
+
+ Local + + {{ localSourcePath(track) || "Original file" }} + +
{{ track.collection }}
Last used: {{ formatDate(track.last_used) }}
+
+ Audio not downloaded yet + ({{ lazyProviderName(track) }} provider). + First playback (or forcing download) will fetch it automatically. +
@@ -136,6 +193,30 @@ > {{ deletingTracks.has(track.pk) ? "..." : "🗑️" }} + +
@@ -175,6 +256,13 @@

Cache Info

PK: {{ selectedTrack.pk }}

+

Status: {{ trackStatusLabel(selectedTrack) }}

+

+ Local file: + + {{ localSourcePath(selectedTrack) || "Original file retained" }} + +

Source URL: {{ resolveTrackOrigin(selectedTrack) }} @@ -188,10 +276,18 @@ - -