diff options
| author | salmonik <raisersoft@proton.me> | 2026-05-18 21:46:26 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-05-18 21:46:26 +0200 |
| commit | 6cceb3cbfacb6f4416e49321a9b63b4ce7a9f036 (patch) | |
| tree | 9d883ada0e6cfb4fd533635885dfb4459f200128 | |
| parent | first public release. (diff) | |
| download | rsplayer-6cceb3cbfacb6f4416e49321a9b63b4ce7a9f036.tar.gz rsplayer-6cceb3cbfacb6f4416e49321a9b63b4ce7a9f036.zip | |
fix for new symphony API and less debug info in release
| -rw-r--r-- | Cargo.lock | 311 | ||||
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | README.md | 66 | ||||
| -rw-r--r-- | src/audio.rs | 97 | ||||
| -rw-r--r-- | src/daemon.rs | 39 | ||||
| -rw-r--r-- | src/lib.rs | 7 | ||||
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/queue.rs | 64 | ||||
| -rw-r--r-- | src/scrobbler.rs | 72 |
9 files changed, 306 insertions, 354 deletions
| @@ -9,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 9 | checksum = "812947049edcd670a82cd5c73c3661d2e58468577ba8489de58e1a73c04cbd5d" | 9 | checksum = "812947049edcd670a82cd5c73c3661d2e58468577ba8489de58e1a73c04cbd5d" |
| 10 | dependencies = [ | 10 | dependencies = [ |
| 11 | "alsa-sys", | 11 | "alsa-sys", |
| 12 | "bitflags 2.11.1", | 12 | "bitflags", |
| 13 | "cfg-if", | 13 | "cfg-if", |
| 14 | "libc", | 14 | "libc", |
| 15 | ] | 15 | ] |
| @@ -90,12 +90,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 90 | checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" | 90 | checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" |
| 91 | 91 | ||
| 92 | [[package]] | 92 | [[package]] |
| 93 | name = "arrayvec" | ||
| 94 | version = "0.7.6" | ||
| 95 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 96 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" | ||
| 97 | |||
| 98 | [[package]] | ||
| 99 | name = "async-broadcast" | 93 | name = "async-broadcast" |
| 100 | version = "0.7.2" | 94 | version = "0.7.2" |
| 101 | source = "registry+https://github.com/rust-lang/crates.io-index" | 95 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -268,12 +262,6 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" | |||
| 268 | 262 | ||
| 269 | [[package]] | 263 | [[package]] |
| 270 | name = "bitflags" | 264 | name = "bitflags" |
| 271 | version = "1.3.2" | ||
| 272 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 273 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | ||
| 274 | |||
| 275 | [[package]] | ||
| 276 | name = "bitflags" | ||
| 277 | version = "2.11.1" | 265 | version = "2.11.1" |
| 278 | source = "registry+https://github.com/rust-lang/crates.io-index" | 266 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 279 | checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" | 267 | checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" |
| @@ -502,7 +490,7 @@ version = "0.14.2" | |||
| 502 | source = "registry+https://github.com/rust-lang/crates.io-index" | 490 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 503 | checksum = "7d5d7dca3ebcf65a035582c9ad4385371a9d9ee6537474d2a278f4e1e475bb58" | 491 | checksum = "7d5d7dca3ebcf65a035582c9ad4385371a9d9ee6537474d2a278f4e1e475bb58" |
| 504 | dependencies = [ | 492 | dependencies = [ |
| 505 | "bitflags 2.11.1", | 493 | "bitflags", |
| 506 | "libc", | 494 | "libc", |
| 507 | "objc2-audio-toolbox", | 495 | "objc2-audio-toolbox", |
| 508 | "objc2-core-audio", | 496 | "objc2-core-audio", |
| @@ -637,7 +625,7 @@ version = "0.3.1" | |||
| 637 | source = "registry+https://github.com/rust-lang/crates.io-index" | 625 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 638 | checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" | 626 | checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" |
| 639 | dependencies = [ | 627 | dependencies = [ |
| 640 | "bitflags 2.11.1", | 628 | "bitflags", |
| 641 | "block2", | 629 | "block2", |
| 642 | "libc", | 630 | "libc", |
| 643 | "objc2", | 631 | "objc2", |
| @@ -1388,15 +1376,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 1388 | checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" | 1376 | checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" |
| 1389 | 1377 | ||
| 1390 | [[package]] | 1378 | [[package]] |
| 1391 | name = "lock_api" | ||
| 1392 | version = "0.4.14" | ||
| 1393 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1394 | checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" | ||
| 1395 | dependencies = [ | ||
| 1396 | "scopeguard", | ||
| 1397 | ] | ||
| 1398 | |||
| 1399 | [[package]] | ||
| 1400 | name = "log" | 1379 | name = "log" |
| 1401 | version = "0.4.29" | 1380 | version = "0.4.29" |
| 1402 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1381 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1477,7 +1456,7 @@ version = "0.9.0" | |||
| 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1456 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1478 | checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" | 1457 | checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" |
| 1479 | dependencies = [ | 1458 | dependencies = [ |
| 1480 | "bitflags 2.11.1", | 1459 | "bitflags", |
| 1481 | "jni-sys 0.3.1", | 1460 | "jni-sys 0.3.1", |
| 1482 | "log", | 1461 | "log", |
| 1483 | "ndk-sys", | 1462 | "ndk-sys", |
| @@ -1506,7 +1485,7 @@ version = "0.31.2" | |||
| 1506 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1485 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1507 | checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" | 1486 | checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" |
| 1508 | dependencies = [ | 1487 | dependencies = [ |
| 1509 | "bitflags 2.11.1", | 1488 | "bitflags", |
| 1510 | "cfg-if", | 1489 | "cfg-if", |
| 1511 | "cfg_aliases", | 1490 | "cfg_aliases", |
| 1512 | "libc", | 1491 | "libc", |
| @@ -1527,6 +1506,15 @@ dependencies = [ | |||
| 1527 | ] | 1506 | ] |
| 1528 | 1507 | ||
| 1529 | [[package]] | 1508 | [[package]] |
| 1509 | name = "num-complex" | ||
| 1510 | version = "0.4.6" | ||
| 1511 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1512 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" | ||
| 1513 | dependencies = [ | ||
| 1514 | "num-traits", | ||
| 1515 | ] | ||
| 1516 | |||
| 1517 | [[package]] | ||
| 1530 | name = "num-conv" | 1518 | name = "num-conv" |
| 1531 | version = "0.2.1" | 1519 | version = "0.2.1" |
| 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1520 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1544,6 +1532,15 @@ dependencies = [ | |||
| 1544 | ] | 1532 | ] |
| 1545 | 1533 | ||
| 1546 | [[package]] | 1534 | [[package]] |
| 1535 | name = "num-integer" | ||
| 1536 | version = "0.1.46" | ||
| 1537 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1538 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" | ||
| 1539 | dependencies = [ | ||
| 1540 | "num-traits", | ||
| 1541 | ] | ||
| 1542 | |||
| 1543 | [[package]] | ||
| 1547 | name = "num-traits" | 1544 | name = "num-traits" |
| 1548 | version = "0.2.19" | 1545 | version = "0.2.19" |
| 1549 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1589,7 +1586,7 @@ version = "0.3.2" | |||
| 1589 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1586 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1590 | checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08" | 1587 | checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08" |
| 1591 | dependencies = [ | 1588 | dependencies = [ |
| 1592 | "bitflags 2.11.1", | 1589 | "bitflags", |
| 1593 | "libc", | 1590 | "libc", |
| 1594 | "objc2", | 1591 | "objc2", |
| 1595 | "objc2-core-audio", | 1592 | "objc2-core-audio", |
| @@ -1627,7 +1624,7 @@ version = "0.3.2" | |||
| 1627 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1624 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1628 | checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" | 1625 | checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" |
| 1629 | dependencies = [ | 1626 | dependencies = [ |
| 1630 | "bitflags 2.11.1", | 1627 | "bitflags", |
| 1631 | "objc2", | 1628 | "objc2", |
| 1632 | ] | 1629 | ] |
| 1633 | 1630 | ||
| @@ -1637,7 +1634,7 @@ version = "0.3.2" | |||
| 1637 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1634 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1638 | checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" | 1635 | checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" |
| 1639 | dependencies = [ | 1636 | dependencies = [ |
| 1640 | "bitflags 2.11.1", | 1637 | "bitflags", |
| 1641 | "block2", | 1638 | "block2", |
| 1642 | "dispatch2", | 1639 | "dispatch2", |
| 1643 | "libc", | 1640 | "libc", |
| @@ -1656,7 +1653,7 @@ version = "0.3.2" | |||
| 1656 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1653 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1657 | checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" | 1654 | checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" |
| 1658 | dependencies = [ | 1655 | dependencies = [ |
| 1659 | "bitflags 2.11.1", | 1656 | "bitflags", |
| 1660 | "block2", | 1657 | "block2", |
| 1661 | "libc", | 1658 | "libc", |
| 1662 | "objc2", | 1659 | "objc2", |
| @@ -1704,29 +1701,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 1704 | checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" | 1701 | checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" |
| 1705 | 1702 | ||
| 1706 | [[package]] | 1703 | [[package]] |
| 1707 | name = "parking_lot" | ||
| 1708 | version = "0.12.5" | ||
| 1709 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1710 | checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" | ||
| 1711 | dependencies = [ | ||
| 1712 | "lock_api", | ||
| 1713 | "parking_lot_core", | ||
| 1714 | ] | ||
| 1715 | |||
| 1716 | [[package]] | ||
| 1717 | name = "parking_lot_core" | ||
| 1718 | version = "0.9.12" | ||
| 1719 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1720 | checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" | ||
| 1721 | dependencies = [ | ||
| 1722 | "cfg-if", | ||
| 1723 | "libc", | ||
| 1724 | "redox_syscall", | ||
| 1725 | "smallvec", | ||
| 1726 | "windows-link 0.2.1", | ||
| 1727 | ] | ||
| 1728 | |||
| 1729 | [[package]] | ||
| 1730 | name = "percent-encoding" | 1704 | name = "percent-encoding" |
| 1731 | version = "2.3.2" | 1705 | version = "2.3.2" |
| 1732 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1706 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1804,6 +1778,15 @@ dependencies = [ | |||
| 1804 | ] | 1778 | ] |
| 1805 | 1779 | ||
| 1806 | [[package]] | 1780 | [[package]] |
| 1781 | name = "primal-check" | ||
| 1782 | version = "0.3.4" | ||
| 1783 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1784 | checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08" | ||
| 1785 | dependencies = [ | ||
| 1786 | "num-integer", | ||
| 1787 | ] | ||
| 1788 | |||
| 1789 | [[package]] | ||
| 1807 | name = "proc-macro-crate" | 1790 | name = "proc-macro-crate" |
| 1808 | version = "3.5.0" | 1791 | version = "3.5.0" |
| 1809 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1792 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1954,15 +1937,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 1954 | checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" | 1937 | checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" |
| 1955 | 1938 | ||
| 1956 | [[package]] | 1939 | [[package]] |
| 1957 | name = "redox_syscall" | ||
| 1958 | version = "0.5.18" | ||
| 1959 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1960 | checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" | ||
| 1961 | dependencies = [ | ||
| 1962 | "bitflags 2.11.1", | ||
| 1963 | ] | ||
| 1964 | |||
| 1965 | [[package]] | ||
| 1966 | name = "redox_users" | 1940 | name = "redox_users" |
| 1967 | version = "0.5.2" | 1941 | version = "0.5.2" |
| 1968 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1942 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1974,6 +1948,12 @@ dependencies = [ | |||
| 1974 | ] | 1948 | ] |
| 1975 | 1949 | ||
| 1976 | [[package]] | 1950 | [[package]] |
| 1951 | name = "regex-lite" | ||
| 1952 | version = "0.1.9" | ||
| 1953 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1954 | checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" | ||
| 1955 | |||
| 1956 | [[package]] | ||
| 1977 | name = "reqwest" | 1957 | name = "reqwest" |
| 1978 | version = "0.13.3" | 1958 | version = "0.13.3" |
| 1979 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1959 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2053,7 +2033,6 @@ dependencies = [ | |||
| 2053 | "symphonia", | 2033 | "symphonia", |
| 2054 | "tempfile", | 2034 | "tempfile", |
| 2055 | "terminal_size", | 2035 | "terminal_size", |
| 2056 | "tokio", | ||
| 2057 | "toml", | 2036 | "toml", |
| 2058 | ] | 2037 | ] |
| 2059 | 2038 | ||
| @@ -2073,7 +2052,7 @@ version = "0.39.0" | |||
| 2073 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2052 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2074 | checksum = "a0d2b0146dd9661bf67bb107c0bb2a55064d556eeb3fc314151b957f313bcd4e" | 2053 | checksum = "a0d2b0146dd9661bf67bb107c0bb2a55064d556eeb3fc314151b957f313bcd4e" |
| 2075 | dependencies = [ | 2054 | dependencies = [ |
| 2076 | "bitflags 2.11.1", | 2055 | "bitflags", |
| 2077 | "fallible-iterator", | 2056 | "fallible-iterator", |
| 2078 | "fallible-streaming-iterator", | 2057 | "fallible-streaming-iterator", |
| 2079 | "hashlink", | 2058 | "hashlink", |
| @@ -2098,12 +2077,26 @@ dependencies = [ | |||
| 2098 | ] | 2077 | ] |
| 2099 | 2078 | ||
| 2100 | [[package]] | 2079 | [[package]] |
| 2080 | name = "rustfft" | ||
| 2081 | version = "6.4.1" | ||
| 2082 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2083 | checksum = "21db5f9893e91f41798c88680037dba611ca6674703c1a18601b01a72c8adb89" | ||
| 2084 | dependencies = [ | ||
| 2085 | "num-complex", | ||
| 2086 | "num-integer", | ||
| 2087 | "num-traits", | ||
| 2088 | "primal-check", | ||
| 2089 | "strength_reduce", | ||
| 2090 | "transpose", | ||
| 2091 | ] | ||
| 2092 | |||
| 2093 | [[package]] | ||
| 2101 | name = "rustix" | 2094 | name = "rustix" |
| 2102 | version = "1.1.4" | 2095 | version = "1.1.4" |
| 2103 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2096 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2104 | checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" | 2097 | checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" |
| 2105 | dependencies = [ | 2098 | dependencies = [ |
| 2106 | "bitflags 2.11.1", | 2099 | "bitflags", |
| 2107 | "errno", | 2100 | "errno", |
| 2108 | "libc", | 2101 | "libc", |
| 2109 | "linux-raw-sys", | 2102 | "linux-raw-sys", |
| @@ -2216,18 +2209,12 @@ dependencies = [ | |||
| 2216 | ] | 2209 | ] |
| 2217 | 2210 | ||
| 2218 | [[package]] | 2211 | [[package]] |
| 2219 | name = "scopeguard" | ||
| 2220 | version = "1.2.0" | ||
| 2221 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2222 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" | ||
| 2223 | |||
| 2224 | [[package]] | ||
| 2225 | name = "security-framework" | 2212 | name = "security-framework" |
| 2226 | version = "3.7.0" | 2213 | version = "3.7.0" |
| 2227 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2214 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2228 | checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" | 2215 | checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" |
| 2229 | dependencies = [ | 2216 | dependencies = [ |
| 2230 | "bitflags 2.11.1", | 2217 | "bitflags", |
| 2231 | "core-foundation 0.10.1", | 2218 | "core-foundation 0.10.1", |
| 2232 | "core-foundation-sys", | 2219 | "core-foundation-sys", |
| 2233 | "libc", | 2220 | "libc", |
| @@ -2398,6 +2385,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 2398 | checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" | 2385 | checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" |
| 2399 | 2386 | ||
| 2400 | [[package]] | 2387 | [[package]] |
| 2388 | name = "strength_reduce" | ||
| 2389 | version = "0.2.4" | ||
| 2390 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2391 | checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" | ||
| 2392 | |||
| 2393 | [[package]] | ||
| 2401 | name = "strsim" | 2394 | name = "strsim" |
| 2402 | version = "0.11.1" | 2395 | version = "0.11.1" |
| 2403 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2396 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2411,22 +2404,15 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" | |||
| 2411 | 2404 | ||
| 2412 | [[package]] | 2405 | [[package]] |
| 2413 | name = "symphonia" | 2406 | name = "symphonia" |
| 2414 | version = "0.5.5" | 2407 | version = "0.6.0" |
| 2415 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2408 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2416 | checksum = "5773a4c030a19d9bfaa090f49746ff35c75dfddfa700df7a5939d5e076a57039" | 2409 | checksum = "1758d6c853020a7244de03cc3e0185eaea3f58715122422dd3cc7452e6d4c16a" |
| 2417 | dependencies = [ | 2410 | dependencies = [ |
| 2418 | "lazy_static", | 2411 | "lazy_static", |
| 2419 | "symphonia-bundle-flac", | 2412 | "symphonia-bundle-flac", |
| 2420 | "symphonia-bundle-mp3", | 2413 | "symphonia-bundle-mp3", |
| 2421 | "symphonia-codec-aac", | ||
| 2422 | "symphonia-codec-adpcm", | ||
| 2423 | "symphonia-codec-alac", | ||
| 2424 | "symphonia-codec-pcm", | ||
| 2425 | "symphonia-codec-vorbis", | 2414 | "symphonia-codec-vorbis", |
| 2426 | "symphonia-core", | 2415 | "symphonia-core", |
| 2427 | "symphonia-format-caf", | ||
| 2428 | "symphonia-format-isomp4", | ||
| 2429 | "symphonia-format-mkv", | ||
| 2430 | "symphonia-format-ogg", | 2416 | "symphonia-format-ogg", |
| 2431 | "symphonia-format-riff", | 2417 | "symphonia-format-riff", |
| 2432 | "symphonia-metadata", | 2418 | "symphonia-metadata", |
| @@ -2434,33 +2420,21 @@ dependencies = [ | |||
| 2434 | 2420 | ||
| 2435 | [[package]] | 2421 | [[package]] |
| 2436 | name = "symphonia-bundle-flac" | 2422 | name = "symphonia-bundle-flac" |
| 2437 | version = "0.5.5" | 2423 | version = "0.6.0" |
| 2438 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2424 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2439 | checksum = "c91565e180aea25d9b80a910c546802526ffd0072d0b8974e3ebe59b686c9976" | 2425 | checksum = "ee69ad01236a67260b82fd1ff9790dd75ead29f2f46af145e63b7e72273e0e03" |
| 2440 | dependencies = [ | 2426 | dependencies = [ |
| 2441 | "log", | 2427 | "log", |
| 2428 | "symphonia-common", | ||
| 2442 | "symphonia-core", | 2429 | "symphonia-core", |
| 2443 | "symphonia-metadata", | 2430 | "symphonia-metadata", |
| 2444 | "symphonia-utils-xiph", | ||
| 2445 | ] | 2431 | ] |
| 2446 | 2432 | ||
| 2447 | [[package]] | 2433 | [[package]] |
| 2448 | name = "symphonia-bundle-mp3" | 2434 | name = "symphonia-bundle-mp3" |
| 2449 | version = "0.5.5" | 2435 | version = "0.6.0" |
| 2450 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2451 | checksum = "4872dd6bb56bf5eac799e3e957aa1981086c3e613b27e0ac23b176054f7c57ed" | ||
| 2452 | dependencies = [ | ||
| 2453 | "lazy_static", | ||
| 2454 | "log", | ||
| 2455 | "symphonia-core", | ||
| 2456 | "symphonia-metadata", | ||
| 2457 | ] | ||
| 2458 | |||
| 2459 | [[package]] | ||
| 2460 | name = "symphonia-codec-aac" | ||
| 2461 | version = "0.5.5" | ||
| 2462 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2436 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2463 | checksum = "4c263845aa86881416849c1729a54c7f55164f8b96111dba59de46849e73a790" | 2437 | checksum = "350f1f2f2e19ad4dd315db94304d1eb361b29af070681f94e51b8fdaad769546" |
| 2464 | dependencies = [ | 2438 | dependencies = [ |
| 2465 | "lazy_static", | 2439 | "lazy_static", |
| 2466 | "log", | 2440 | "log", |
| @@ -2468,113 +2442,59 @@ dependencies = [ | |||
| 2468 | ] | 2442 | ] |
| 2469 | 2443 | ||
| 2470 | [[package]] | 2444 | [[package]] |
| 2471 | name = "symphonia-codec-adpcm" | ||
| 2472 | version = "0.5.5" | ||
| 2473 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2474 | checksum = "2dddc50e2bbea4cfe027441eece77c46b9f319748605ab8f3443350129ddd07f" | ||
| 2475 | dependencies = [ | ||
| 2476 | "log", | ||
| 2477 | "symphonia-core", | ||
| 2478 | ] | ||
| 2479 | |||
| 2480 | [[package]] | ||
| 2481 | name = "symphonia-codec-alac" | ||
| 2482 | version = "0.5.5" | ||
| 2483 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2484 | checksum = "8413fa754942ac16a73634c9dfd1500ed5c61430956b33728567f667fdd393ab" | ||
| 2485 | dependencies = [ | ||
| 2486 | "log", | ||
| 2487 | "symphonia-core", | ||
| 2488 | ] | ||
| 2489 | |||
| 2490 | [[package]] | ||
| 2491 | name = "symphonia-codec-pcm" | ||
| 2492 | version = "0.5.5" | ||
| 2493 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2494 | checksum = "4e89d716c01541ad3ebe7c91ce4c8d38a7cf266a3f7b2f090b108fb0cb031d95" | ||
| 2495 | dependencies = [ | ||
| 2496 | "log", | ||
| 2497 | "symphonia-core", | ||
| 2498 | ] | ||
| 2499 | |||
| 2500 | [[package]] | ||
| 2501 | name = "symphonia-codec-vorbis" | 2445 | name = "symphonia-codec-vorbis" |
| 2502 | version = "0.5.5" | 2446 | version = "0.6.0" |
| 2503 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2504 | checksum = "f025837c309cd69ffef572750b4a2257b59552c5399a5e49707cc5b1b85d1c73" | ||
| 2505 | dependencies = [ | ||
| 2506 | "log", | ||
| 2507 | "symphonia-core", | ||
| 2508 | "symphonia-utils-xiph", | ||
| 2509 | ] | ||
| 2510 | |||
| 2511 | [[package]] | ||
| 2512 | name = "symphonia-core" | ||
| 2513 | version = "0.5.5" | ||
| 2514 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2515 | checksum = "ea00cc4f79b7f6bb7ff87eddc065a1066f3a43fe1875979056672c9ef948c2af" | ||
| 2516 | dependencies = [ | ||
| 2517 | "arrayvec", | ||
| 2518 | "bitflags 1.3.2", | ||
| 2519 | "bytemuck", | ||
| 2520 | "lazy_static", | ||
| 2521 | "log", | ||
| 2522 | ] | ||
| 2523 | |||
| 2524 | [[package]] | ||
| 2525 | name = "symphonia-format-caf" | ||
| 2526 | version = "0.5.5" | ||
| 2527 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2447 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2528 | checksum = "b8faf379316b6b6e6bbc274d00e7a592e0d63ff1a7e182ce8ba25e24edd3d096" | 2448 | checksum = "45b07b4423cd8e0fc472575909a5554b12c2f58e3c190b38c24f042e732fd8de" |
| 2529 | dependencies = [ | 2449 | dependencies = [ |
| 2530 | "log", | 2450 | "log", |
| 2451 | "symphonia-common", | ||
| 2531 | "symphonia-core", | 2452 | "symphonia-core", |
| 2532 | "symphonia-metadata", | ||
| 2533 | ] | 2453 | ] |
| 2534 | 2454 | ||
| 2535 | [[package]] | 2455 | [[package]] |
| 2536 | name = "symphonia-format-isomp4" | 2456 | name = "symphonia-common" |
| 2537 | version = "0.5.5" | 2457 | version = "0.6.0" |
| 2538 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2458 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2539 | checksum = "243739585d11f81daf8dac8d9f3d18cc7898f6c09a259675fc364b382c30e0a5" | 2459 | checksum = "8257891ffa7f05e02b58f4761e2abf7e5278c8744fd59e981559e050f86eef55" |
| 2540 | dependencies = [ | 2460 | dependencies = [ |
| 2541 | "encoding_rs", | ||
| 2542 | "log", | 2461 | "log", |
| 2543 | "symphonia-core", | 2462 | "symphonia-core", |
| 2544 | "symphonia-metadata", | 2463 | "symphonia-metadata", |
| 2545 | "symphonia-utils-xiph", | ||
| 2546 | ] | 2464 | ] |
| 2547 | 2465 | ||
| 2548 | [[package]] | 2466 | [[package]] |
| 2549 | name = "symphonia-format-mkv" | 2467 | name = "symphonia-core" |
| 2550 | version = "0.5.5" | 2468 | version = "0.6.0" |
| 2551 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2469 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2552 | checksum = "122d786d2c43a49beb6f397551b4a050d8229eaa54c7ddf9ee4b98899b8742d0" | 2470 | checksum = "95ec293b5f288383b72a7bffcade6b2860b642cf66f28b3bd5967349a49938b1" |
| 2553 | dependencies = [ | 2471 | dependencies = [ |
| 2472 | "bitflags", | ||
| 2473 | "bytemuck", | ||
| 2554 | "lazy_static", | 2474 | "lazy_static", |
| 2555 | "log", | 2475 | "log", |
| 2556 | "symphonia-core", | 2476 | "num-complex", |
| 2557 | "symphonia-metadata", | 2477 | "rustfft", |
| 2558 | "symphonia-utils-xiph", | 2478 | "smallvec", |
| 2559 | ] | 2479 | ] |
| 2560 | 2480 | ||
| 2561 | [[package]] | 2481 | [[package]] |
| 2562 | name = "symphonia-format-ogg" | 2482 | name = "symphonia-format-ogg" |
| 2563 | version = "0.5.5" | 2483 | version = "0.6.0" |
| 2564 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2484 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2565 | checksum = "2b4955c67c1ed3aa8ae8428d04ca8397fbef6a19b2b051e73b5da8b1435639cb" | 2485 | checksum = "b05a67e02b1e4fca1a261ba4fe06910a9357489ad8c36aafdd2960e9c6559433" |
| 2566 | dependencies = [ | 2486 | dependencies = [ |
| 2567 | "log", | 2487 | "log", |
| 2488 | "symphonia-common", | ||
| 2568 | "symphonia-core", | 2489 | "symphonia-core", |
| 2569 | "symphonia-metadata", | 2490 | "symphonia-metadata", |
| 2570 | "symphonia-utils-xiph", | ||
| 2571 | ] | 2491 | ] |
| 2572 | 2492 | ||
| 2573 | [[package]] | 2493 | [[package]] |
| 2574 | name = "symphonia-format-riff" | 2494 | name = "symphonia-format-riff" |
| 2575 | version = "0.5.5" | 2495 | version = "0.6.0" |
| 2576 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2496 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2577 | checksum = "c2d7c3df0e7d94efb68401d81906eae73c02b40d5ec1a141962c592d0f11a96f" | 2497 | checksum = "17424452a777666d3eaf09a5c651029b15b6a333812fcc5b5474f2a3f0cff3f0" |
| 2578 | dependencies = [ | 2498 | dependencies = [ |
| 2579 | "extended", | 2499 | "extended", |
| 2580 | "log", | 2500 | "log", |
| @@ -2584,27 +2504,18 @@ dependencies = [ | |||
| 2584 | 2504 | ||
| 2585 | [[package]] | 2505 | [[package]] |
| 2586 | name = "symphonia-metadata" | 2506 | name = "symphonia-metadata" |
| 2587 | version = "0.5.5" | 2507 | version = "0.6.0" |
| 2588 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2508 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2589 | checksum = "36306ff42b9ffe6e5afc99d49e121e0bd62fe79b9db7b9681d48e29fa19e6b16" | 2509 | checksum = "a31acf5cd623398a6208e2225d18f4b20f761c55098a796a5247ad516a4a8681" |
| 2590 | dependencies = [ | 2510 | dependencies = [ |
| 2591 | "encoding_rs", | ||
| 2592 | "lazy_static", | 2511 | "lazy_static", |
| 2593 | "log", | 2512 | "log", |
| 2513 | "regex-lite", | ||
| 2514 | "smallvec", | ||
| 2594 | "symphonia-core", | 2515 | "symphonia-core", |
| 2595 | ] | 2516 | ] |
| 2596 | 2517 | ||
| 2597 | [[package]] | 2518 | [[package]] |
| 2598 | name = "symphonia-utils-xiph" | ||
| 2599 | version = "0.5.5" | ||
| 2600 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2601 | checksum = "ee27c85ab799a338446b68eec77abf42e1a6f1bb490656e121c6e27bfbab9f16" | ||
| 2602 | dependencies = [ | ||
| 2603 | "symphonia-core", | ||
| 2604 | "symphonia-metadata", | ||
| 2605 | ] | ||
| 2606 | |||
| 2607 | [[package]] | ||
| 2608 | name = "syn" | 2519 | name = "syn" |
| 2609 | version = "2.0.117" | 2520 | version = "2.0.117" |
| 2610 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2521 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2641,7 +2552,7 @@ version = "0.7.0" | |||
| 2641 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2552 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2642 | checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" | 2553 | checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" |
| 2643 | dependencies = [ | 2554 | dependencies = [ |
| 2644 | "bitflags 2.11.1", | 2555 | "bitflags", |
| 2645 | "core-foundation 0.9.4", | 2556 | "core-foundation 0.9.4", |
| 2646 | "system-configuration-sys", | 2557 | "system-configuration-sys", |
| 2647 | ] | 2558 | ] |
| @@ -2784,26 +2695,12 @@ dependencies = [ | |||
| 2784 | "bytes", | 2695 | "bytes", |
| 2785 | "libc", | 2696 | "libc", |
| 2786 | "mio", | 2697 | "mio", |
| 2787 | "parking_lot", | ||
| 2788 | "pin-project-lite", | 2698 | "pin-project-lite", |
| 2789 | "signal-hook-registry", | ||
| 2790 | "socket2", | 2699 | "socket2", |
| 2791 | "tokio-macros", | ||
| 2792 | "windows-sys 0.61.2", | 2700 | "windows-sys 0.61.2", |
| 2793 | ] | 2701 | ] |
| 2794 | 2702 | ||
| 2795 | [[package]] | 2703 | [[package]] |
| 2796 | name = "tokio-macros" | ||
| 2797 | version = "2.7.0" | ||
| 2798 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2799 | checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" | ||
| 2800 | dependencies = [ | ||
| 2801 | "proc-macro2", | ||
| 2802 | "quote", | ||
| 2803 | "syn", | ||
| 2804 | ] | ||
| 2805 | |||
| 2806 | [[package]] | ||
| 2807 | name = "tokio-rustls" | 2704 | name = "tokio-rustls" |
| 2808 | version = "0.26.4" | 2705 | version = "0.26.4" |
| 2809 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2706 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -2898,7 +2795,7 @@ version = "0.6.9" | |||
| 2898 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2795 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 2899 | checksum = "a28f0d049ccfaa566e14e9663d304d8577427b368cb4710a20528690287a738b" | 2796 | checksum = "a28f0d049ccfaa566e14e9663d304d8577427b368cb4710a20528690287a738b" |
| 2900 | dependencies = [ | 2797 | dependencies = [ |
| 2901 | "bitflags 2.11.1", | 2798 | "bitflags", |
| 2902 | "bytes", | 2799 | "bytes", |
| 2903 | "futures-util", | 2800 | "futures-util", |
| 2904 | "http", | 2801 | "http", |
| @@ -2954,6 +2851,16 @@ dependencies = [ | |||
| 2954 | ] | 2851 | ] |
| 2955 | 2852 | ||
| 2956 | [[package]] | 2853 | [[package]] |
| 2854 | name = "transpose" | ||
| 2855 | version = "0.2.3" | ||
| 2856 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2857 | checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" | ||
| 2858 | dependencies = [ | ||
| 2859 | "num-integer", | ||
| 2860 | "strength_reduce", | ||
| 2861 | ] | ||
| 2862 | |||
| 2863 | [[package]] | ||
| 2957 | name = "try-lock" | 2864 | name = "try-lock" |
| 2958 | version = "0.2.5" | 2865 | version = "0.2.5" |
| 2959 | source = "registry+https://github.com/rust-lang/crates.io-index" | 2866 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -3161,7 +3068,7 @@ version = "0.244.0" | |||
| 3161 | source = "registry+https://github.com/rust-lang/crates.io-index" | 3068 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 3162 | checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" | 3069 | checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" |
| 3163 | dependencies = [ | 3070 | dependencies = [ |
| 3164 | "bitflags 2.11.1", | 3071 | "bitflags", |
| 3165 | "hashbrown 0.15.5", | 3072 | "hashbrown 0.15.5", |
| 3166 | "indexmap", | 3073 | "indexmap", |
| 3167 | "semver", | 3074 | "semver", |
| @@ -3719,7 +3626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 3719 | checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" | 3626 | checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" |
| 3720 | dependencies = [ | 3627 | dependencies = [ |
| 3721 | "anyhow", | 3628 | "anyhow", |
| 3722 | "bitflags 2.11.1", | 3629 | "bitflags", |
| 3723 | "indexmap", | 3630 | "indexmap", |
| 3724 | "log", | 3631 | "log", |
| 3725 | "serde", | 3632 | "serde", |
| @@ -22,9 +22,8 @@ rusqlite = { version = "0.39", features = ["bundled"] } | |||
| 22 | directories = "6.0" | 22 | directories = "6.0" |
| 23 | serde = { version = "1.0.228", features = ["derive"] } | 23 | serde = { version = "1.0.228", features = ["derive"] } |
| 24 | toml = "1.1.2" | 24 | toml = "1.1.2" |
| 25 | tokio = { version = "1.52.2", features = ["full"] } | ||
| 26 | reqwest = { version = "0.13.3", features = ["json", "form", "blocking"] } | 25 | reqwest = { version = "0.13.3", features = ["json", "form", "blocking"] } |
| 27 | symphonia = { version = "0.5.5", features = ["all"] } | 26 | symphonia = { version = "0.6", default-features = false, features = ["mp3", "flac", "vorbis", "wav", "ogg", "opt-simd"] } |
| 28 | cpal = "0.17.3" | 27 | cpal = "0.17.3" |
| 29 | chrono = "0.4.44" | 28 | chrono = "0.4.44" |
| 30 | serde_json = "1.0.149" | 29 | serde_json = "1.0.149" |
| @@ -7,47 +7,47 @@ cd RSPlayer | |||
| 7 | ./install.sh | 7 | ./install.sh |
| 8 | ``` | 8 | ``` |
| 9 | 9 | ||
| 10 | install.sh will: | 10 | install.sh will: |
| 11 | compile RSP (make sure you have rust properly installed!) | 11 | - compile RSP (make sure you have rust properly installed!) |
| 12 | install shell autocompletions (zsh, bash and fish supported) | 12 | - install shell autocompletions (zsh, bash and fish supported) |
| 13 | install user systemd service and activate it | 13 | - install user systemd service and activate it |
| 14 | 14 | ||
| 15 | ## Usage | 15 | ## Usage |
| 16 | 16 | ||
| 17 | configuration is generated at startup in $XDG_CONFIG_HOME/rsplayer/config.toml | 17 | configuration is generated at startup in $XDG_CONFIG_HOME/rsplayer/config.toml |
| 18 | most important values there are: | 18 | - most important values there are: |
| 19 | listenbrainz_token (last.fm scrobbling not yet tested) | 19 | - listenbrainz_token (last.fm scrobbling not yet tested) |
| 20 | display_format (supports $ARTIST $ALBUM and $TRACK) | 20 | - display_format (supports $ARTIST $ALBUM and $TRACK) |
| 21 | music_paths (for DB usage, still WIP) | 21 | - music_paths (for DB usage, still WIP) |
| 22 | scan_interval (same as above) | 22 | - scan_interval (same as above) |
| 23 | 23 | ||
| 24 | all other values can be changed in runtime using commands | 24 | all other values can be changed in runtime using commands |
| 25 | 25 | ||
| 26 | as for commands: | 26 | as for commands: |
| 27 | RSP will be installed as rsp, in this fragment, rsp will be ommited | 27 | RSP will be installed as rsp, in this fragment, rsp will be ommited |
| 28 | 28 | ||
| 29 | these commands should only be used in testing or by systemd service: | 29 | these commands should only be used in testing or by systemd service: |
| 30 | `start-daemon` Start the daemon | 30 | - `start-daemon` Start the daemon |
| 31 | `stop-daemon` Stop the daemon | 31 | - `stop-daemon` Stop the daemon |
| 32 | `restart` Restart the daemon (kill existing and start new) | 32 | - `restart` Restart the daemon (kill existing and start new) |
| 33 | 33 | ||
| 34 | these are normal commands: | 34 | these are normal commands: |
| 35 | `play` Play a track, album, or artist | 35 | - `play` Play a track, album, or artist |
| 36 | `pause` Pause playback | 36 | - `pause` Pause playback |
| 37 | `resume` Resume playback | 37 | - `resume` Resume playback |
| 38 | `toggle` Toggle play/pause | 38 | - `toggle` Toggle play/pause |
| 39 | `stop` Stop playback | 39 | - `stop` Stop playback |
| 40 | `next` Skip to next track | 40 | - `next` Skip to next track |
| 41 | `previous` Skip to previous track | 41 | - `previous` Skip to previous track |
| 42 | `volume` Set volume (0-100) | 42 | - `volume` Set volume (0-100) |
| 43 | `shuffle` Shuffle mode | 43 | - `shuffle` Shuffle mode |
| 44 | `queue` Queue management | 44 | - `queue` Queue management |
| 45 | `status` Show player status | 45 | - `status` Show player status |
| 46 | `scan` Scan music paths to populate database | 46 | - `scan` Scan music paths to populate database |
| 47 | `settings` Settings management | 47 | - `settings` Settings management |
| 48 | `help` Print this message or the help of the given subcommand(s) | 48 | - `help` Print this message or the help of the given subcommand(s) |
| 49 | 49 | ||
| 50 | 50 | ||
| 51 | ## Technical stuff | 51 | ## Technical stuff |
| 52 | The main culprit of this player is lack of integration with programs such as playerctl | 52 | The main culprit of this player is lack of integration with programs such as playerctl |
| 53 | this is due to the daemon not being asynchronous | 53 | this is due to the daemon not being asynchronous |
diff --git a/src/audio.rs b/src/audio.rs index 62afd93..62d13ff 100644 --- a/src/audio.rs +++ b/src/audio.rs | |||
| @@ -101,7 +101,7 @@ impl AudioEngine { | |||
| 101 | 101 | ||
| 102 | struct AudioData { | 102 | struct AudioData { |
| 103 | format: Box<dyn symphonia::core::formats::FormatReader>, | 103 | format: Box<dyn symphonia::core::formats::FormatReader>, |
| 104 | decoder: Box<dyn symphonia::core::codecs::Decoder>, | 104 | decoder: Box<dyn symphonia::core::codecs::audio::AudioDecoder>, |
| 105 | sample_rate: u32, | 105 | sample_rate: u32, |
| 106 | channels: u16, | 106 | channels: u16, |
| 107 | sample_buffer: Vec<f32>, | 107 | sample_buffer: Vec<f32>, |
| @@ -165,10 +165,10 @@ fn audio_thread( | |||
| 165 | 165 | ||
| 166 | let device_sample_rate = config.sample_rate(); | 166 | let device_sample_rate = config.sample_rate(); |
| 167 | let channels = config.channels(); | 167 | let channels = config.channels(); |
| 168 | eprintln!( | 168 | crate::debug_eprintln(format_args!( |
| 169 | "Default output: {} Hz, {} channels", | 169 | "Default output: {} Hz, {} channels", |
| 170 | device_sample_rate, channels | 170 | device_sample_rate, channels |
| 171 | ); | 171 | )); |
| 172 | 172 | ||
| 173 | let mut current_stream: Option<cpal::Stream> = None; | 173 | let mut current_stream: Option<cpal::Stream> = None; |
| 174 | let audio_data: Arc<Mutex<Option<AudioData>>> = Arc::new(Mutex::new(None)); | 174 | let audio_data: Arc<Mutex<Option<AudioData>>> = Arc::new(Mutex::new(None)); |
| @@ -186,13 +186,16 @@ fn audio_thread( | |||
| 186 | 186 | ||
| 187 | match open_audio_file(&path) { | 187 | match open_audio_file(&path) { |
| 188 | Ok(mut data) => { | 188 | Ok(mut data) => { |
| 189 | eprintln!("File: {} Hz, {} channels", data.sample_rate, data.channels); | 189 | crate::debug_eprintln(format_args!( |
| 190 | "File: {} Hz, {} channels", | ||
| 191 | data.sample_rate, data.channels | ||
| 192 | )); | ||
| 190 | 193 | ||
| 191 | if data.sample_rate != device_sample_rate { | 194 | if data.sample_rate != device_sample_rate { |
| 192 | eprintln!( | 195 | crate::debug_eprintln(format_args!( |
| 193 | "Resampling from {} Hz to {} Hz", | 196 | "Resampling from {} Hz to {} Hz", |
| 194 | data.sample_rate, device_sample_rate | 197 | data.sample_rate, device_sample_rate |
| 195 | ); | 198 | )); |
| 196 | data.resample_ratio = | 199 | data.resample_ratio = |
| 197 | Some(device_sample_rate as f64 / data.sample_rate as f64); | 200 | Some(device_sample_rate as f64 / data.sample_rate as f64); |
| 198 | } | 201 | } |
| @@ -201,28 +204,23 @@ fn audio_thread( | |||
| 201 | let channels = data.channels as usize; | 204 | let channels = data.channels as usize; |
| 202 | for _ in 0..100 { | 205 | for _ in 0..100 { |
| 203 | match data.format.next_packet() { | 206 | match data.format.next_packet() { |
| 204 | Ok(packet) => match data.decoder.decode(&packet) { | 207 | Ok(Some(packet)) => match data.decoder.decode(&packet) { |
| 205 | Ok(decoded) => { | 208 | Ok(decoded) => { |
| 206 | let spec = *decoded.spec(); | 209 | let num_samples = decoded.samples_interleaved(); |
| 207 | let mut sample_buf = symphonia::core::audio::SampleBuffer::< | 210 | let mut samples = vec![0.0f32; num_samples]; |
| 208 | f32, | 211 | decoded.copy_to_slice_interleaved(&mut samples); |
| 209 | >::new( | ||
| 210 | decoded.capacity() as u64, spec | ||
| 211 | ); | ||
| 212 | sample_buf.copy_interleaved_ref(decoded); | ||
| 213 | let samples = sample_buf.samples(); | ||
| 214 | 212 | ||
| 215 | let resampled = if let Some(ratio) = data.resample_ratio { | 213 | let resampled = if let Some(ratio) = data.resample_ratio { |
| 216 | resample_linear(samples, ratio, channels) | 214 | resample_linear(&samples, ratio, channels) |
| 217 | } else { | 215 | } else { |
| 218 | samples.to_vec() | 216 | samples |
| 219 | }; | 217 | }; |
| 220 | 218 | ||
| 221 | data.sample_buffer.extend(resampled); | 219 | data.sample_buffer.extend(resampled); |
| 222 | } | 220 | } |
| 223 | Err(_) => break, | 221 | Err(_) => break, |
| 224 | }, | 222 | }, |
| 225 | Err(_) => break, | 223 | _ => break, |
| 226 | } | 224 | } |
| 227 | } | 225 | } |
| 228 | data.buffer_pos = 0; | 226 | data.buffer_pos = 0; |
| @@ -274,29 +272,26 @@ fn audio_thread( | |||
| 274 | 272 | ||
| 275 | // Decode more data | 273 | // Decode more data |
| 276 | match state.format.next_packet() { | 274 | match state.format.next_packet() { |
| 277 | Ok(packet) => { | 275 | Ok(Some(packet)) => { |
| 278 | match state.decoder.decode(&packet) { | 276 | match state.decoder.decode(&packet) { |
| 279 | Ok(decoded) => { | 277 | Ok(decoded) => { |
| 280 | let spec = *decoded.spec(); | 278 | let num_samples = |
| 281 | let mut sample_buf = | 279 | decoded.samples_interleaved(); |
| 282 | symphonia::core::audio::SampleBuffer::< | 280 | let mut samples = |
| 283 | f32, | 281 | vec![0.0f32; num_samples]; |
| 284 | >::new( | 282 | decoded.copy_to_slice_interleaved( |
| 285 | decoded.capacity() as u64, spec | 283 | &mut samples, |
| 286 | ); | 284 | ); |
| 287 | sample_buf | ||
| 288 | .copy_interleaved_ref(decoded); | ||
| 289 | let samples = sample_buf.samples(); | ||
| 290 | 285 | ||
| 291 | // Resample if needed | 286 | // Resample if needed |
| 292 | let resampled = if let Some(ratio) = | 287 | let resampled = if let Some(ratio) = |
| 293 | state.resample_ratio | 288 | state.resample_ratio |
| 294 | { | 289 | { |
| 295 | resample_linear( | 290 | resample_linear( |
| 296 | samples, ratio, channels, | 291 | &samples, ratio, channels, |
| 297 | ) | 292 | ) |
| 298 | } else { | 293 | } else { |
| 299 | samples.to_vec() | 294 | samples |
| 300 | }; | 295 | }; |
| 301 | 296 | ||
| 302 | // Copy what we can to output | 297 | // Copy what we can to output |
| @@ -323,7 +318,7 @@ fn audio_thread( | |||
| 323 | Err(_) => break, | 318 | Err(_) => break, |
| 324 | } | 319 | } |
| 325 | } | 320 | } |
| 326 | Err(_) => break, | 321 | _ => break, |
| 327 | } | 322 | } |
| 328 | } | 323 | } |
| 329 | 324 | ||
| @@ -419,36 +414,50 @@ fn audio_thread( | |||
| 419 | } | 414 | } |
| 420 | 415 | ||
| 421 | fn open_audio_file(path: &PathBuf) -> Result<AudioData, Box<dyn std::error::Error>> { | 416 | fn open_audio_file(path: &PathBuf) -> Result<AudioData, Box<dyn std::error::Error>> { |
| 422 | use symphonia::core::audio::Channels; | 417 | use symphonia::core::audio::layouts::CHANNEL_LAYOUT_STEREO; |
| 418 | use symphonia::core::codecs::audio::AudioDecoderOptions; | ||
| 419 | use symphonia::core::formats::probe::Hint; | ||
| 423 | use symphonia::core::io::MediaSourceStream; | 420 | use symphonia::core::io::MediaSourceStream; |
| 424 | 421 | ||
| 425 | let file = std::fs::File::open(path)?; | 422 | let file = std::fs::File::open(path)?; |
| 426 | let mss = MediaSourceStream::new(Box::new(file), Default::default()); | 423 | let mss = MediaSourceStream::new(Box::new(file), Default::default()); |
| 427 | 424 | ||
| 428 | let hint = symphonia::core::probe::Hint::new(); | 425 | let hint = Hint::new(); |
| 429 | let probed = symphonia::default::get_probe().format( | 426 | let format = symphonia::default::get_probe().probe( |
| 430 | &hint, | 427 | &hint, |
| 431 | mss, | 428 | mss, |
| 432 | &Default::default(), | 429 | Default::default(), |
| 433 | &Default::default(), | 430 | Default::default(), |
| 434 | )?; | 431 | )?; |
| 435 | 432 | ||
| 436 | let format = probed.format; | ||
| 437 | let track = format | 433 | let track = format |
| 438 | .tracks() | 434 | .tracks() |
| 439 | .iter() | 435 | .iter() |
| 440 | .find(|t| t.codec_params.sample_rate.is_some()) | 436 | .find(|t| { |
| 437 | t.codec_params | ||
| 438 | .as_ref() | ||
| 439 | .and_then(|p| p.audio()) | ||
| 440 | .and_then(|a| a.sample_rate) | ||
| 441 | .is_some() | ||
| 442 | }) | ||
| 441 | .ok_or("No suitable track found")?; | 443 | .ok_or("No suitable track found")?; |
| 442 | 444 | ||
| 443 | let sample_rate = track.codec_params.sample_rate.unwrap_or(44100); | 445 | let codec_params = track |
| 444 | let channels = track | ||
| 445 | .codec_params | 446 | .codec_params |
| 447 | .as_ref() | ||
| 448 | .ok_or("No codec parameters")? | ||
| 449 | .audio() | ||
| 450 | .ok_or("Not an audio track")?; | ||
| 451 | |||
| 452 | let sample_rate = codec_params.sample_rate.unwrap_or(44100); | ||
| 453 | let channels = codec_params | ||
| 446 | .channels | 454 | .channels |
| 447 | .unwrap_or(Channels::FRONT_LEFT | Channels::FRONT_RIGHT) | 455 | .clone() |
| 456 | .unwrap_or(CHANNEL_LAYOUT_STEREO) | ||
| 448 | .count() as u16; | 457 | .count() as u16; |
| 449 | 458 | ||
| 450 | let decoder = | 459 | let decoder = symphonia::default::get_codecs() |
| 451 | symphonia::default::get_codecs().make(&track.codec_params, &Default::default())?; | 460 | .make_audio_decoder(codec_params, &AudioDecoderOptions::default())?; |
| 452 | 461 | ||
| 453 | Ok(AudioData { | 462 | Ok(AudioData { |
| 454 | format, | 463 | format, |
diff --git a/src/daemon.rs b/src/daemon.rs index 59fc3d8..8b74357 100644 --- a/src/daemon.rs +++ b/src/daemon.rs | |||
| @@ -33,10 +33,10 @@ impl ScrobbleState { | |||
| 33 | .as_secs(); | 33 | .as_secs(); |
| 34 | let title = track.title.clone().unwrap_or_default(); | 34 | let title = track.title.clone().unwrap_or_default(); |
| 35 | let artist = track.artist.clone().unwrap_or_default(); | 35 | let artist = track.artist.clone().unwrap_or_default(); |
| 36 | eprintln!( | 36 | crate::debug_eprintln(format_args!( |
| 37 | "scrobble: tracking start for '{} - {}' (ts={})", | 37 | "scrobble: tracking start for '{} - {}' (ts={})", |
| 38 | artist, title, ts | 38 | artist, title, ts |
| 39 | ); | 39 | )); |
| 40 | self.track = Some(track); | 40 | self.track = Some(track); |
| 41 | self.start_time = Some(Instant::now()); | 41 | self.start_time = Some(Instant::now()); |
| 42 | self.timestamp = Some(ts); | 42 | self.timestamp = Some(ts); |
| @@ -44,7 +44,9 @@ impl ScrobbleState { | |||
| 44 | 44 | ||
| 45 | fn should_scrobble(&self) -> bool { | 45 | fn should_scrobble(&self) -> bool { |
| 46 | let (Some(track), Some(start)) = (&self.track, self.start_time) else { | 46 | let (Some(track), Some(start)) = (&self.track, self.start_time) else { |
| 47 | eprintln!("scrobble: should_scrobble false — no track or start_time"); | 47 | crate::debug_eprintln(format_args!( |
| 48 | "scrobble: should_scrobble false — no track or start_time" | ||
| 49 | )); | ||
| 48 | return false; | 50 | return false; |
| 49 | }; | 51 | }; |
| 50 | let elapsed = start.elapsed().as_secs(); | 52 | let elapsed = start.elapsed().as_secs(); |
| @@ -54,10 +56,10 @@ impl ScrobbleState { | |||
| 54 | .map(|d| (d / 2.0) as u64) | 56 | .map(|d| (d / 2.0) as u64) |
| 55 | .unwrap_or(u64::MAX) | 57 | .unwrap_or(u64::MAX) |
| 56 | .min(240); | 58 | .min(240); |
| 57 | eprintln!( | 59 | crate::debug_eprintln(format_args!( |
| 58 | "scrobble: should_scrobble {} (elapsed={}s threshold={}s duration={:?})", | 60 | "scrobble: should_scrobble {} (elapsed={}s threshold={}s duration={:?})", |
| 59 | result, elapsed, threshold, track.duration_secs | 61 | result, elapsed, threshold, track.duration_secs |
| 60 | ); | 62 | )); |
| 61 | result | 63 | result |
| 62 | } | 64 | } |
| 63 | 65 | ||
| @@ -158,10 +160,10 @@ fn try_scrobble_current(scrobbler: &RwLock<Scrobbler>, state: &mut ScrobbleState | |||
| 158 | let artist = track.artist.as_deref().unwrap_or("(unknown artist)"); | 160 | let artist = track.artist.as_deref().unwrap_or("(unknown artist)"); |
| 159 | let title = track.title.as_deref().unwrap_or("(unknown title)"); | 161 | let title = track.title.as_deref().unwrap_or("(unknown title)"); |
| 160 | let album = track.album.as_deref(); | 162 | let album = track.album.as_deref(); |
| 161 | eprintln!( | 163 | crate::debug_eprintln(format_args!( |
| 162 | "scrobble: sending scrobble for '{} - {}' at ts={}", | 164 | "scrobble: sending scrobble for '{} - {}' at ts={}", |
| 163 | artist, title, ts | 165 | artist, title, ts |
| 164 | ); | 166 | )); |
| 165 | if let Ok(s) = scrobbler.read() { | 167 | if let Ok(s) = scrobbler.read() { |
| 166 | s.scrobble(artist, title, album, ts); | 168 | s.scrobble(artist, title, album, ts); |
| 167 | } | 169 | } |
| @@ -171,10 +173,10 @@ fn try_scrobble_current(scrobbler: &RwLock<Scrobbler>, state: &mut ScrobbleState | |||
| 171 | .as_ref() | 173 | .as_ref() |
| 172 | .and_then(|t| t.title.as_deref()) | 174 | .and_then(|t| t.title.as_deref()) |
| 173 | .unwrap_or("(no track)"); | 175 | .unwrap_or("(no track)"); |
| 174 | eprintln!( | 176 | crate::debug_eprintln(format_args!( |
| 175 | "scrobble: skipping scrobble for '{}' — not enough play time", | 177 | "scrobble: skipping scrobble for '{}' — not enough play time", |
| 176 | title | 178 | title |
| 177 | ); | 179 | )); |
| 178 | } | 180 | } |
| 179 | state.clear(); | 181 | state.clear(); |
| 180 | } | 182 | } |
| @@ -183,7 +185,10 @@ fn send_now_playing(scrobbler: &RwLock<Scrobbler>, track: &Track) { | |||
| 183 | let artist = track.artist.as_deref().unwrap_or("(unknown artist)"); | 185 | let artist = track.artist.as_deref().unwrap_or("(unknown artist)"); |
| 184 | let title = track.title.as_deref().unwrap_or("(unknown title)"); | 186 | let title = track.title.as_deref().unwrap_or("(unknown title)"); |
| 185 | let album = track.album.as_deref(); | 187 | let album = track.album.as_deref(); |
| 186 | eprintln!("scrobble: sending now_playing for '{} - {}'", artist, title); | 188 | crate::debug_eprintln(format_args!( |
| 189 | "scrobble: sending now_playing for '{} - {}'", | ||
| 190 | artist, title | ||
| 191 | )); | ||
| 187 | if let Ok(s) = scrobbler.read() { | 192 | if let Ok(s) = scrobbler.read() { |
| 188 | s.now_playing(artist, title, album); | 193 | s.now_playing(artist, title, album); |
| 189 | } | 194 | } |
| @@ -260,9 +265,17 @@ pub fn start_daemon() -> Result<(), Box<dyn std::error::Error>> { | |||
| 260 | && let Ok(s) = scrobbler.read() | 265 | && let Ok(s) = scrobbler.read() |
| 261 | { | 266 | { |
| 262 | match s.validate_listenbrainz_token() { | 267 | match s.validate_listenbrainz_token() { |
| 263 | Ok(Some(user)) => eprintln!("scrobble: listenbrainz token valid (user: {})", user), | 268 | Ok(Some(user)) => crate::debug_eprintln(format_args!( |
| 264 | Ok(None) => eprintln!("scrobble: listenbrainz token invalid, scrobbling disabled"), | 269 | "scrobble: listenbrainz token valid (user: {})", |
| 265 | Err(e) => eprintln!("scrobble: listenbrainz validation error: {}", e), | 270 | user |
| 271 | )), | ||
| 272 | Ok(None) => crate::debug_eprintln(format_args!( | ||
| 273 | "scrobble: listenbrainz token invalid, scrobbling disabled" | ||
| 274 | )), | ||
| 275 | Err(e) => crate::debug_eprintln(format_args!( | ||
| 276 | "scrobble: listenbrainz validation error: {}", | ||
| 277 | e | ||
| 278 | )), | ||
| 266 | } | 279 | } |
| 267 | } | 280 | } |
| 268 | let scrobble_state = Arc::new(Mutex::new(ScrobbleState::new())); | 281 | let scrobble_state = Arc::new(Mutex::new(ScrobbleState::new())); |
| @@ -1,3 +1,10 @@ | |||
| 1 | #[inline(always)] | ||
| 2 | pub fn debug_eprintln(args: core::fmt::Arguments<'_>) { | ||
| 3 | if cfg!(debug_assertions) { | ||
| 4 | eprintln!("{}", args); | ||
| 5 | } | ||
| 6 | } | ||
| 7 | |||
| 1 | pub mod audio; | 8 | pub mod audio; |
| 2 | pub mod cli; | 9 | pub mod cli; |
| 3 | pub mod config; | 10 | pub mod config; |
diff --git a/src/main.rs b/src/main.rs index c1e42d0..fe450dd 100644 --- a/src/main.rs +++ b/src/main.rs | |||
| @@ -10,6 +10,7 @@ mod scrobbler; | |||
| 10 | 10 | ||
| 11 | use clap::Parser; | 11 | use clap::Parser; |
| 12 | use cli::Cli; | 12 | use cli::Cli; |
| 13 | pub use rsp::debug_eprintln; | ||
| 13 | 14 | ||
| 14 | fn main() { | 15 | fn main() { |
| 15 | let cli = Cli::parse(); | 16 | let cli = Cli::parse(); |
diff --git a/src/queue.rs b/src/queue.rs index 26aeb8b..b0acf5f 100644 --- a/src/queue.rs +++ b/src/queue.rs | |||
| @@ -17,28 +17,27 @@ pub struct AudioMetadata { | |||
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | pub fn extract_metadata(path: &Path) -> Option<AudioMetadata> { | 19 | pub fn extract_metadata(path: &Path) -> Option<AudioMetadata> { |
| 20 | use symphonia::core::formats::probe::Hint; | ||
| 20 | use symphonia::core::io::MediaSourceStream; | 21 | use symphonia::core::io::MediaSourceStream; |
| 21 | use symphonia::core::meta::StandardTagKey; | 22 | use symphonia::core::meta::StandardTag; |
| 22 | use symphonia::core::probe::Hint; | ||
| 23 | 23 | ||
| 24 | let file = std::fs::File::open(path).ok()?; | 24 | let file = std::fs::File::open(path).ok()?; |
| 25 | let mss = MediaSourceStream::new(Box::new(file), Default::default()); | 25 | let mss = MediaSourceStream::new(Box::new(file), Default::default()); |
| 26 | 26 | ||
| 27 | let hint = Hint::new(); | 27 | let hint = Hint::new(); |
| 28 | let mut probed = symphonia::default::get_probe() | 28 | let mut probed = symphonia::default::get_probe() |
| 29 | .format(&hint, mss, &Default::default(), &Default::default()) | 29 | .probe(&hint, mss, Default::default(), Default::default()) |
| 30 | .ok()?; | 30 | .ok()?; |
| 31 | 31 | ||
| 32 | // Extract duration from format track's codec parameters | 32 | // Extract duration from track's num_frames and time_base |
| 33 | let duration_secs = probed | 33 | let duration_secs = probed |
| 34 | .format | ||
| 35 | .tracks() | 34 | .tracks() |
| 36 | .iter() | 35 | .iter() |
| 37 | .find(|t| t.codec_params.n_frames.is_some() && t.codec_params.time_base.is_some()) | 36 | .find(|t| t.num_frames.is_some() && t.time_base.is_some()) |
| 38 | .and_then(|t| { | 37 | .and_then(|t| { |
| 39 | let n_frames = t.codec_params.n_frames?; | 38 | let n_frames = t.num_frames?; |
| 40 | let tb = t.codec_params.time_base?; | 39 | let tb = t.time_base?; |
| 41 | Some(n_frames as f64 * tb.numer as f64 / tb.denom as f64) | 40 | Some(n_frames as f64 * tb.numer.get() as f64 / tb.denom.get() as f64) |
| 42 | }); | 41 | }); |
| 43 | 42 | ||
| 44 | let mut metadata = AudioMetadata { | 43 | let mut metadata = AudioMetadata { |
| @@ -46,38 +45,39 @@ pub fn extract_metadata(path: &Path) -> Option<AudioMetadata> { | |||
| 46 | ..Default::default() | 45 | ..Default::default() |
| 47 | }; | 46 | }; |
| 48 | 47 | ||
| 49 | if let Some(meta) = probed.metadata.get() | ||
| 50 | && let Some(rev) = meta.current() | ||
| 51 | { | 48 | { |
| 52 | for tag in rev.tags() { | 49 | let meta = probed.metadata(); |
| 53 | match tag.std_key { | 50 | if let Some(rev) = meta.current() { |
| 54 | Some(StandardTagKey::TrackTitle) => { | 51 | for tag in &rev.media.tags { |
| 55 | metadata.title = Some(tag.value.to_string()); | 52 | match &tag.std { |
| 56 | } | 53 | Some(StandardTag::TrackTitle(value)) => { |
| 57 | Some(StandardTagKey::Artist) => { | 54 | metadata.title = Some(value.to_string()); |
| 58 | metadata.artist = Some(tag.value.to_string()); | 55 | } |
| 59 | } | 56 | Some(StandardTag::Artist(value)) => { |
| 60 | Some(StandardTagKey::Album) => { | 57 | metadata.artist = Some(value.to_string()); |
| 61 | metadata.album = Some(tag.value.to_string()); | 58 | } |
| 59 | Some(StandardTag::Album(value)) => { | ||
| 60 | metadata.album = Some(value.to_string()); | ||
| 61 | } | ||
| 62 | _ => {} | ||
| 62 | } | 63 | } |
| 63 | _ => {} | ||
| 64 | } | 64 | } |
| 65 | } | 65 | } |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | if metadata.title.is_none() && metadata.artist.is_none() && metadata.album.is_none() { | 68 | if metadata.title.is_none() && metadata.artist.is_none() && metadata.album.is_none() { |
| 69 | let mut format = probed.format; | 69 | let meta = probed.metadata(); |
| 70 | if let Some(rev) = format.metadata().current() { | 70 | if let Some(rev) = meta.current() { |
| 71 | for tag in rev.tags() { | 71 | for tag in &rev.media.tags { |
| 72 | match tag.std_key { | 72 | match &tag.std { |
| 73 | Some(StandardTagKey::TrackTitle) => { | 73 | Some(StandardTag::TrackTitle(value)) => { |
| 74 | metadata.title = Some(tag.value.to_string()); | 74 | metadata.title = Some(value.to_string()); |
| 75 | } | 75 | } |
| 76 | Some(StandardTagKey::Artist) => { | 76 | Some(StandardTag::Artist(value)) => { |
| 77 | metadata.artist = Some(tag.value.to_string()); | 77 | metadata.artist = Some(value.to_string()); |
| 78 | } | 78 | } |
| 79 | Some(StandardTagKey::Album) => { | 79 | Some(StandardTag::Album(value)) => { |
| 80 | metadata.album = Some(tag.value.to_string()); | 80 | metadata.album = Some(value.to_string()); |
| 81 | } | 81 | } |
| 82 | _ => {} | 82 | _ => {} |
| 83 | } | 83 | } |
diff --git a/src/scrobbler.rs b/src/scrobbler.rs index 2e79933..93cb3c2 100644 --- a/src/scrobbler.rs +++ b/src/scrobbler.rs | |||
| @@ -47,10 +47,10 @@ impl Scrobbler { | |||
| 47 | .send()?; | 47 | .send()?; |
| 48 | 48 | ||
| 49 | if !resp.status().is_success() { | 49 | if !resp.status().is_success() { |
| 50 | eprintln!( | 50 | crate::debug_eprintln(format_args!( |
| 51 | "scrobble: listenbrainz token validation failed: {}", | 51 | "scrobble: listenbrainz token validation failed: {}", |
| 52 | resp.status() | 52 | resp.status() |
| 53 | ); | 53 | )); |
| 54 | return Ok(None); | 54 | return Ok(None); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| @@ -62,13 +62,18 @@ impl Scrobbler { | |||
| 62 | .and_then(|v| v.as_str()) | 62 | .and_then(|v| v.as_str()) |
| 63 | .map(|s| s.to_string()); | 63 | .map(|s| s.to_string()); |
| 64 | if let Some(ref u) = user { | 64 | if let Some(ref u) = user { |
| 65 | eprintln!("scrobble: listenbrainz token valid (user: {})", u); | 65 | crate::debug_eprintln(format_args!( |
| 66 | "scrobble: listenbrainz token valid (user: {})", | ||
| 67 | u | ||
| 68 | )); | ||
| 66 | } else { | 69 | } else { |
| 67 | eprintln!("scrobble: listenbrainz token valid"); | 70 | crate::debug_eprintln(format_args!("scrobble: listenbrainz token valid")); |
| 68 | } | 71 | } |
| 69 | Ok(user) | 72 | Ok(user) |
| 70 | } else { | 73 | } else { |
| 71 | eprintln!("scrobble: listenbrainz token invalid — scrobbling will fail"); | 74 | crate::debug_eprintln(format_args!( |
| 75 | "scrobble: listenbrainz token invalid — scrobbling will fail" | ||
| 76 | )); | ||
| 72 | Ok(None) | 77 | Ok(None) |
| 73 | } | 78 | } |
| 74 | } | 79 | } |
| @@ -82,22 +87,29 @@ impl Scrobbler { | |||
| 82 | && !secret.is_empty() | 87 | && !secret.is_empty() |
| 83 | && !session_key.is_empty() | 88 | && !session_key.is_empty() |
| 84 | { | 89 | { |
| 85 | eprintln!("scrobble: now_playing -> lastfm '{} - {}'", artist, track); | 90 | crate::debug_eprintln(format_args!( |
| 91 | "scrobble: now_playing -> lastfm '{} - {}'", | ||
| 92 | artist, track | ||
| 93 | )); | ||
| 86 | let _ = | 94 | let _ = |
| 87 | self.send_lastfm_now_playing(api_key, secret, session_key, artist, track, album); | 95 | self.send_lastfm_now_playing(api_key, secret, session_key, artist, track, album); |
| 88 | } else { | 96 | } else { |
| 89 | eprintln!("scrobble: now_playing -> lastfm skipped (no credentials)"); | 97 | crate::debug_eprintln(format_args!( |
| 98 | "scrobble: now_playing -> lastfm skipped (no credentials)" | ||
| 99 | )); | ||
| 90 | } | 100 | } |
| 91 | if let Some(token) = &self.listenbrainz_token | 101 | if let Some(token) = &self.listenbrainz_token |
| 92 | && !token.is_empty() | 102 | && !token.is_empty() |
| 93 | { | 103 | { |
| 94 | eprintln!( | 104 | crate::debug_eprintln(format_args!( |
| 95 | "scrobble: now_playing -> listenbrainz '{} - {}'", | 105 | "scrobble: now_playing -> listenbrainz '{} - {}'", |
| 96 | artist, track | 106 | artist, track |
| 97 | ); | 107 | )); |
| 98 | let _ = self.send_listenbrainz_now_playing(token, artist, track, album); | 108 | let _ = self.send_listenbrainz_now_playing(token, artist, track, album); |
| 99 | } else { | 109 | } else { |
| 100 | eprintln!("scrobble: now_playing -> listenbrainz skipped (no token)"); | 110 | crate::debug_eprintln(format_args!( |
| 111 | "scrobble: now_playing -> listenbrainz skipped (no token)" | ||
| 112 | )); | ||
| 101 | } | 113 | } |
| 102 | } | 114 | } |
| 103 | 115 | ||
| @@ -110,10 +122,10 @@ impl Scrobbler { | |||
| 110 | && !secret.is_empty() | 122 | && !secret.is_empty() |
| 111 | && !session_key.is_empty() | 123 | && !session_key.is_empty() |
| 112 | { | 124 | { |
| 113 | eprintln!( | 125 | crate::debug_eprintln(format_args!( |
| 114 | "scrobble: scrobble -> lastfm '{} - {}' (ts={})", | 126 | "scrobble: scrobble -> lastfm '{} - {}' (ts={})", |
| 115 | artist, track, timestamp | 127 | artist, track, timestamp |
| 116 | ); | 128 | )); |
| 117 | let _ = self.send_lastfm_scrobble( | 129 | let _ = self.send_lastfm_scrobble( |
| 118 | api_key, | 130 | api_key, |
| 119 | secret, | 131 | secret, |
| @@ -124,18 +136,22 @@ impl Scrobbler { | |||
| 124 | timestamp, | 136 | timestamp, |
| 125 | ); | 137 | ); |
| 126 | } else { | 138 | } else { |
| 127 | eprintln!("scrobble: scrobble -> lastfm skipped (no credentials)"); | 139 | crate::debug_eprintln(format_args!( |
| 140 | "scrobble: scrobble -> lastfm skipped (no credentials)" | ||
| 141 | )); | ||
| 128 | } | 142 | } |
| 129 | if let Some(token) = &self.listenbrainz_token | 143 | if let Some(token) = &self.listenbrainz_token |
| 130 | && !token.is_empty() | 144 | && !token.is_empty() |
| 131 | { | 145 | { |
| 132 | eprintln!( | 146 | crate::debug_eprintln(format_args!( |
| 133 | "scrobble: scrobble -> listenbrainz '{} - {}' (ts={})", | 147 | "scrobble: scrobble -> listenbrainz '{} - {}' (ts={})", |
| 134 | artist, track, timestamp | 148 | artist, track, timestamp |
| 135 | ); | 149 | )); |
| 136 | let _ = self.send_listenbrainz_scrobble(token, artist, track, album, timestamp); | 150 | let _ = self.send_listenbrainz_scrobble(token, artist, track, album, timestamp); |
| 137 | } else { | 151 | } else { |
| 138 | eprintln!("scrobble: scrobble -> listenbrainz skipped (no token)"); | 152 | crate::debug_eprintln(format_args!( |
| 153 | "scrobble: scrobble -> listenbrainz skipped (no token)" | ||
| 154 | )); | ||
| 139 | } | 155 | } |
| 140 | } | 156 | } |
| 141 | 157 | ||
| @@ -177,13 +193,13 @@ impl Scrobbler { | |||
| 177 | 193 | ||
| 178 | let resp = self.client.post(LASTFM_API_URL).form(¶ms).send()?; | 194 | let resp = self.client.post(LASTFM_API_URL).form(¶ms).send()?; |
| 179 | if resp.status().is_success() { | 195 | if resp.status().is_success() { |
| 180 | eprintln!("scrobble: lastfm now_playing ok"); | 196 | crate::debug_eprintln(format_args!("scrobble: lastfm now_playing ok")); |
| 181 | } else { | 197 | } else { |
| 182 | eprintln!( | 198 | crate::debug_eprintln(format_args!( |
| 183 | "scrobble: lastfm now_playing error: {} {}", | 199 | "scrobble: lastfm now_playing error: {} {}", |
| 184 | resp.status(), | 200 | resp.status(), |
| 185 | resp.text().unwrap_or_default() | 201 | resp.text().unwrap_or_default() |
| 186 | ); | 202 | )); |
| 187 | } | 203 | } |
| 188 | Ok(()) | 204 | Ok(()) |
| 189 | } | 205 | } |
| @@ -217,13 +233,13 @@ impl Scrobbler { | |||
| 217 | 233 | ||
| 218 | let resp = self.client.post(LASTFM_API_URL).form(¶ms).send()?; | 234 | let resp = self.client.post(LASTFM_API_URL).form(¶ms).send()?; |
| 219 | if resp.status().is_success() { | 235 | if resp.status().is_success() { |
| 220 | eprintln!("scrobble: lastfm scrobble ok"); | 236 | crate::debug_eprintln(format_args!("scrobble: lastfm scrobble ok")); |
| 221 | } else { | 237 | } else { |
| 222 | eprintln!( | 238 | crate::debug_eprintln(format_args!( |
| 223 | "scrobble: lastfm scrobble error: {} {}", | 239 | "scrobble: lastfm scrobble error: {} {}", |
| 224 | resp.status(), | 240 | resp.status(), |
| 225 | resp.text().unwrap_or_default() | 241 | resp.text().unwrap_or_default() |
| 226 | ); | 242 | )); |
| 227 | } | 243 | } |
| 228 | Ok(()) | 244 | Ok(()) |
| 229 | } | 245 | } |
| @@ -257,13 +273,13 @@ impl Scrobbler { | |||
| 257 | .json(&payload) | 273 | .json(&payload) |
| 258 | .send()?; | 274 | .send()?; |
| 259 | if resp.status().is_success() { | 275 | if resp.status().is_success() { |
| 260 | eprintln!("scrobble: listenbrainz now_playing ok"); | 276 | crate::debug_eprintln(format_args!("scrobble: listenbrainz now_playing ok")); |
| 261 | } else { | 277 | } else { |
| 262 | eprintln!( | 278 | crate::debug_eprintln(format_args!( |
| 263 | "scrobble: listenbrainz now_playing error: {} {}", | 279 | "scrobble: listenbrainz now_playing error: {} {}", |
| 264 | resp.status(), | 280 | resp.status(), |
| 265 | resp.text().unwrap_or_default() | 281 | resp.text().unwrap_or_default() |
| 266 | ); | 282 | )); |
| 267 | } | 283 | } |
| 268 | Ok(()) | 284 | Ok(()) |
| 269 | } | 285 | } |
| @@ -299,13 +315,13 @@ impl Scrobbler { | |||
| 299 | .json(&payload) | 315 | .json(&payload) |
| 300 | .send()?; | 316 | .send()?; |
| 301 | if resp.status().is_success() { | 317 | if resp.status().is_success() { |
| 302 | eprintln!("scrobble: listenbrainz scrobble ok"); | 318 | crate::debug_eprintln(format_args!("scrobble: listenbrainz scrobble ok")); |
| 303 | } else { | 319 | } else { |
| 304 | eprintln!( | 320 | crate::debug_eprintln(format_args!( |
| 305 | "scrobble: listenbrainz scrobble error: {} {}", | 321 | "scrobble: listenbrainz scrobble error: {} {}", |
| 306 | resp.status(), | 322 | resp.status(), |
| 307 | resp.text().unwrap_or_default() | 323 | resp.text().unwrap_or_default() |
| 308 | ); | 324 | )); |
| 309 | } | 325 | } |
| 310 | Ok(()) | 326 | Ok(()) |
| 311 | } | 327 | } |
