mirror of
https://github.com/ivabus/lonelyradio
synced 2024-11-24 17:15:10 +03:00
0.1.7: switch logs err/out, bump symphonia, buffer wisely
Signed-off-by: Ivan Bushchik <ivabus@ivabus.dev>
This commit is contained in:
parent
31c0db5d99
commit
6daba088b8
4 changed files with 211 additions and 90 deletions
151
Cargo.lock
generated
151
Cargo.lock
generated
|
@ -387,6 +387,12 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "extended"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.12"
|
||||
|
@ -568,7 +574,7 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
|||
|
||||
[[package]]
|
||||
name = "lonelyradio"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
|
@ -679,6 +685,15 @@ dependencies = [
|
|||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.3.3"
|
||||
|
@ -690,6 +705,15 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
|
@ -815,6 +839,15 @@ version = "0.2.17"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "primal-check"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df7f93fd637f083201473dab4fee2db4c429d32e55e3299980ab3957ab916a0"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.3.1"
|
||||
|
@ -938,6 +971,21 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustfft"
|
||||
version = "6.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86"
|
||||
dependencies = [
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"primal-check",
|
||||
"strength_reduce",
|
||||
"transpose",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
|
@ -984,6 +1032,12 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strength_reduce"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
|
@ -992,9 +1046,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||
|
||||
[[package]]
|
||||
name = "symphonia"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62e48dba70095f265fdb269b99619b95d04c89e619538138383e63310b14d941"
|
||||
checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"symphonia-bundle-flac",
|
||||
|
@ -1005,18 +1059,19 @@ dependencies = [
|
|||
"symphonia-codec-pcm",
|
||||
"symphonia-codec-vorbis",
|
||||
"symphonia-core",
|
||||
"symphonia-format-caf",
|
||||
"symphonia-format-isomp4",
|
||||
"symphonia-format-mkv",
|
||||
"symphonia-format-ogg",
|
||||
"symphonia-format-wav",
|
||||
"symphonia-format-riff",
|
||||
"symphonia-metadata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia-bundle-flac"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f23b0482a7cb18fcdf9981ab0b78df800ef0080187d294650023c462439058d"
|
||||
checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97"
|
||||
dependencies = [
|
||||
"log",
|
||||
"symphonia-core",
|
||||
|
@ -1026,11 +1081,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-bundle-mp3"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a"
|
||||
checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"symphonia-core",
|
||||
|
@ -1039,9 +1093,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-codec-aac"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68bdd75b25ce4b84b12a4bd20bfea2460c2dbd7fc1d227ef5533504d3168109d"
|
||||
checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
|
@ -1050,9 +1104,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-codec-adpcm"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "870e7dc1865d818c7b6318879d060553a73a3b2a3b8443dff90910f10ac41150"
|
||||
checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f"
|
||||
dependencies = [
|
||||
"log",
|
||||
"symphonia-core",
|
||||
|
@ -1060,9 +1114,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-codec-alac"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a27e8763d1c9eff666faf903e73a99d4de2f7a93fca4e3c214c1d68432903b9"
|
||||
checksum = "2d8a6666649a08412906476a8b0efd9b9733e241180189e9f92b09c08d0e38f3"
|
||||
dependencies = [
|
||||
"log",
|
||||
"symphonia-core",
|
||||
|
@ -1070,9 +1124,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-codec-pcm"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47f1fbd220a06a641c8ce2ddad10f5ef6ee5cc0c54d9044d25d43b0d3119deaa"
|
||||
checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b"
|
||||
dependencies = [
|
||||
"log",
|
||||
"symphonia-core",
|
||||
|
@ -1080,9 +1134,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-codec-vorbis"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3953397e3506aa01350c4205817e4f95b58d476877a42f0458d07b665749e203"
|
||||
checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30"
|
||||
dependencies = [
|
||||
"log",
|
||||
"symphonia-core",
|
||||
|
@ -1091,22 +1145,34 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-core"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7c73eb88fee79705268cc7b742c7bc93a7b76e092ab751d0833866970754142"
|
||||
checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags 1.3.2",
|
||||
"bytemuck",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"rustfft",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia-format-caf"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e43c99c696a388295a29fe71b133079f5d8b18041cf734c5459c35ad9097af50"
|
||||
dependencies = [
|
||||
"log",
|
||||
"symphonia-core",
|
||||
"symphonia-metadata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia-format-isomp4"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffdf14bae5cf352032416bc64151e5d6242d29d33cbf3238513b44d4427a1efb"
|
||||
checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"log",
|
||||
|
@ -1117,9 +1183,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-format-mkv"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5c61dfc851ad25d4043d8c231d8617e8f7cd02a6cc0edad21ade21848d58895"
|
||||
checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
|
@ -1130,9 +1196,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-format-ogg"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bf1a00ccd11452d44048a0368828040f778ae650418dbd9d8765b7ee2574c8d"
|
||||
checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931"
|
||||
dependencies = [
|
||||
"log",
|
||||
"symphonia-core",
|
||||
|
@ -1141,11 +1207,12 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "symphonia-format-wav"
|
||||
version = "0.5.3"
|
||||
name = "symphonia-format-riff"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da76614728fa27c003bdcdfbac51396bd8fcbf94c95fe8e62f1d2bac58ef03a4"
|
||||
checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50"
|
||||
dependencies = [
|
||||
"extended",
|
||||
"log",
|
||||
"symphonia-core",
|
||||
"symphonia-metadata",
|
||||
|
@ -1153,9 +1220,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-metadata"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89c3e1937e31d0e068bbe829f66b2f2bfaa28d056365279e0ef897172c3320c0"
|
||||
checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"lazy_static",
|
||||
|
@ -1165,9 +1232,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "symphonia-utils-xiph"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a450ca645b80d69aff8b35576cbfdc7f20940b29998202aab910045714c951f8"
|
||||
checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe"
|
||||
dependencies = [
|
||||
"symphonia-core",
|
||||
"symphonia-metadata",
|
||||
|
@ -1260,6 +1327,16 @@ dependencies = [
|
|||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "transpose"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6522d49d03727ffb138ae4cbc1283d3774f0d10aa7f9bf52e6784c45daf9b23"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"strength_reduce",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
|
@ -1272,6 +1349,12 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.4.0"
|
||||
|
|
|
@ -4,7 +4,7 @@ members = ["monoclient"]
|
|||
[package]
|
||||
name = "lonelyradio"
|
||||
description = "TCP radio for singles"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Ivan Bushchik <ivabus@ivabus.dev>"]
|
||||
|
@ -22,11 +22,10 @@ tokio = { version = "1.35.1", features = [
|
|||
"macros",
|
||||
] }
|
||||
walkdir = "2.4.0"
|
||||
symphonia = { version = "0.5.3", features = [
|
||||
symphonia = { version = "0.5.4", features = [
|
||||
"all-codecs",
|
||||
"all-formats",
|
||||
"pcm",
|
||||
"symphonia-codec-pcm",
|
||||
"opt-simd",
|
||||
] }
|
||||
samplerate = "0.2.4"
|
||||
chrono = "0.4"
|
||||
|
|
|
@ -4,9 +4,12 @@ use rodio::buffer::SamplesBuffer;
|
|||
use rodio::{OutputStream, Sink};
|
||||
use std::io::Read;
|
||||
use std::net::TcpStream;
|
||||
use std::time::Instant;
|
||||
|
||||
// How many samples to cache before playing (half a second)
|
||||
const BUFFER_SIZE: usize = 44100;
|
||||
// How many samples to cache before playing in samples (both channels) SHOULD BE EVEN
|
||||
const BUFFER_SIZE: usize = 2400;
|
||||
// How many buffers to cache
|
||||
const CACHE_SIZE: usize = 100;
|
||||
|
||||
enum Channel {
|
||||
Right,
|
||||
|
@ -18,16 +21,29 @@ enum Channel {
|
|||
struct Args {
|
||||
/// Remote address
|
||||
address: String,
|
||||
#[arg(short, long, default_value = "s")]
|
||||
/// L, R or S for Left, Right or Stereo
|
||||
channel: String,
|
||||
#[arg(short)]
|
||||
/// Play only on specified channel, with it if channel = Right => L=0 and R=R, without L=R and R=R. No effect on Stereo
|
||||
single: bool,
|
||||
|
||||
/// More verbose
|
||||
#[arg(short)]
|
||||
verbose: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let start = Instant::now();
|
||||
let args = Args::parse();
|
||||
let mut stream = TcpStream::connect(args.address).unwrap();
|
||||
if args.verbose {
|
||||
eprintln!(
|
||||
"Connected to {} from {}",
|
||||
stream.peer_addr().unwrap(),
|
||||
stream.local_addr().unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
let channel = match args.channel.to_ascii_lowercase().as_str() {
|
||||
"l" => Channel::Left,
|
||||
|
@ -38,12 +54,14 @@ fn main() {
|
|||
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
|
||||
let sink = Sink::try_new(&stream_handle).unwrap();
|
||||
let mut buffer = [0u8; 4];
|
||||
let mut samples = vec![];
|
||||
let mut samples = [0f32; BUFFER_SIZE];
|
||||
let mut index = 0usize;
|
||||
let mut first = true;
|
||||
while stream.read_exact(&mut buffer).is_ok() {
|
||||
let sample_l = byteorder::LittleEndian::read_i16(&buffer[..2]) as f32 / 32768.0;
|
||||
let sample_r = byteorder::LittleEndian::read_i16(&buffer[2..]) as f32 / 32768.0;
|
||||
// Left channel
|
||||
samples.push(match channel {
|
||||
samples[index] = match channel {
|
||||
Channel::Left | Channel::Stereo => sample_l,
|
||||
Channel::Right => {
|
||||
if args.single {
|
||||
|
@ -52,9 +70,10 @@ fn main() {
|
|||
sample_r
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
index += 1;
|
||||
// Right channel
|
||||
samples.push(match channel {
|
||||
samples[index] = match channel {
|
||||
Channel::Right | Channel::Stereo => sample_r,
|
||||
Channel::Left => {
|
||||
if args.single {
|
||||
|
@ -63,20 +82,35 @@ fn main() {
|
|||
sample_l
|
||||
}
|
||||
}
|
||||
});
|
||||
if samples.len() >= BUFFER_SIZE {
|
||||
// What is next three lines?
|
||||
// Sink's thread is detached from main thread, so we need to somehow synchronize with it
|
||||
};
|
||||
index += 1;
|
||||
if index == BUFFER_SIZE {
|
||||
let mut first_wait_iteration = true;
|
||||
// Sink's thread is detached from main thread, so we need to synchronize with it
|
||||
// Why we should synchronize with it?
|
||||
// Let's say, that if we don't synchronize with it, we would have
|
||||
// a lot (no upper limit, actualy) of buffered sound, waiting for playing in sink
|
||||
while sink.len() >= 3
|
||||
// buffered >= 1.5 sec
|
||||
{
|
||||
std::thread::sleep(std::time::Duration::from_secs_f32(0.25))
|
||||
while sink.len() >= CACHE_SIZE {
|
||||
if args.verbose && first_wait_iteration {
|
||||
eprint!(".");
|
||||
first_wait_iteration = false;
|
||||
}
|
||||
sink.append(SamplesBuffer::new(2, 44100, samples));
|
||||
samples = vec![];
|
||||
// Sleeping exactly one buffer
|
||||
std::thread::sleep(std::time::Duration::from_secs_f32(
|
||||
(if sink.len() >= 2 {
|
||||
sink.len() - 2
|
||||
} else {
|
||||
1
|
||||
} as f32) * BUFFER_SIZE as f32
|
||||
/ 44100.0 / 2.0,
|
||||
))
|
||||
}
|
||||
if first && args.verbose {
|
||||
eprintln!("Started playing in {} ms", (Instant::now() - start).as_millis());
|
||||
first = false;
|
||||
}
|
||||
sink.append(SamplesBuffer::new(2, 44100, samples.as_slice()));
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
65
src/main.rs
65
src/main.rs
|
@ -1,4 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Local;
|
||||
use clap::Parser;
|
||||
|
@ -6,9 +7,7 @@ use rand::prelude::*;
|
|||
use samplerate::ConverterType;
|
||||
use symphonia::core::audio::SampleBuffer;
|
||||
use symphonia::core::codecs::CODEC_TYPE_NULL;
|
||||
use symphonia::core::formats::FormatOptions;
|
||||
use symphonia::core::io::MediaSourceStream;
|
||||
use symphonia::core::meta::MetadataOptions;
|
||||
use symphonia::core::probe::Hint;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
@ -30,42 +29,43 @@ struct Args {
|
|||
#[tokio::main]
|
||||
async fn main() {
|
||||
let listener = TcpListener::bind(Args::parse().address).await.unwrap();
|
||||
|
||||
let tracklist = Arc::new(
|
||||
walkdir::WalkDir::new(Args::parse().dir)
|
||||
.into_iter()
|
||||
.filter_entry(is_not_hidden)
|
||||
.filter_map(|v| v.ok())
|
||||
.map(|x| x.into_path())
|
||||
.filter(track_valid)
|
||||
.into_iter()
|
||||
.collect::<Vec<PathBuf>>(),
|
||||
);
|
||||
loop {
|
||||
let (socket, _) = listener.accept().await.unwrap();
|
||||
tokio::spawn(stream(socket));
|
||||
tokio::spawn(stream(socket, tracklist.clone()));
|
||||
}
|
||||
}
|
||||
fn is_not_hidden(entry: &DirEntry) -> bool {
|
||||
entry.file_name().to_str().map(|s| entry.depth() == 0 || !s.starts_with('.')).unwrap_or(false)
|
||||
}
|
||||
|
||||
// Recursively finding music file
|
||||
fn pick_track(tracklist: &Vec<PathBuf>) -> &PathBuf {
|
||||
let mut track = tracklist.choose(&mut thread_rng()).unwrap();
|
||||
while !track.metadata().unwrap().is_file() {
|
||||
track = pick_track(tracklist)
|
||||
fn track_valid(track: &PathBuf) -> bool {
|
||||
if !track.metadata().unwrap().is_file() {
|
||||
return false;
|
||||
}
|
||||
// Skipping "images" (covers)
|
||||
while "jpgjpegpngwebp"
|
||||
.contains(&track.extension().unwrap().to_str().unwrap().to_ascii_lowercase())
|
||||
if "jpgjpegpngwebp".contains(&track.extension().unwrap().to_str().unwrap().to_ascii_lowercase())
|
||||
{
|
||||
track = pick_track(tracklist)
|
||||
return false;
|
||||
}
|
||||
track
|
||||
true
|
||||
}
|
||||
|
||||
async fn stream(mut s: TcpStream) {
|
||||
async fn stream(mut s: TcpStream, tracklist: Arc<Vec<PathBuf>>) {
|
||||
let args = Args::parse();
|
||||
let tracklist = walkdir::WalkDir::new(Args::parse().dir)
|
||||
.into_iter()
|
||||
.filter_entry(is_not_hidden)
|
||||
.filter_map(|v| v.ok())
|
||||
.map(|x| x.into_path())
|
||||
.collect::<Vec<PathBuf>>();
|
||||
|
||||
'track: loop {
|
||||
let track = pick_track(&tracklist);
|
||||
println!(
|
||||
let track = tracklist.choose(&mut thread_rng()).unwrap();
|
||||
eprintln!(
|
||||
"[{}] {} to {}:{}{}",
|
||||
Local::now().to_rfc3339(),
|
||||
track.to_str().unwrap(),
|
||||
|
@ -79,7 +79,7 @@ async fn stream(mut s: TcpStream) {
|
|||
);
|
||||
|
||||
if args.public_log {
|
||||
eprintln!(
|
||||
println!(
|
||||
"[{}] {} to {}{}",
|
||||
Local::now().to_rfc3339(),
|
||||
track.to_str().unwrap(),
|
||||
|
@ -95,13 +95,14 @@ async fn stream(mut s: TcpStream) {
|
|||
let file = Box::new(std::fs::File::open(track).unwrap());
|
||||
let mut hint = Hint::new();
|
||||
hint.with_extension(track.extension().unwrap().to_str().unwrap());
|
||||
let mss = MediaSourceStream::new(file, Default::default());
|
||||
|
||||
let meta_opts: MetadataOptions = Default::default();
|
||||
let fmt_opts: FormatOptions = Default::default();
|
||||
|
||||
let probed = symphonia::default::get_probe()
|
||||
.format(&hint, mss, &fmt_opts, &meta_opts)
|
||||
.format(
|
||||
&hint,
|
||||
MediaSourceStream::new(file, Default::default()),
|
||||
&Default::default(),
|
||||
&Default::default(),
|
||||
)
|
||||
.expect("unsupported format");
|
||||
|
||||
let mut format = probed.format;
|
||||
|
@ -138,14 +139,18 @@ async fn stream(mut s: TcpStream) {
|
|||
let mut byte_buf =
|
||||
SampleBuffer::<f32>::new(decoded.capacity() as u64, *decoded.spec());
|
||||
byte_buf.copy_interleaved_ref(decoded);
|
||||
let samples = samplerate::convert(
|
||||
let samples = if rate != 44100 {
|
||||
samplerate::convert(
|
||||
rate,
|
||||
44100,
|
||||
2,
|
||||
ConverterType::Linear,
|
||||
byte_buf.samples(),
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
} else {
|
||||
byte_buf.samples().to_vec()
|
||||
};
|
||||
for sample in samples {
|
||||
let result = s
|
||||
.write(
|
||||
|
|
Loading…
Reference in a new issue