You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.8 KiB
129 lines
4.8 KiB
use std::{io::{Read, Seek}, time::SystemTime};
|
|
|
|
pub struct Player {
|
|
pub sink: rodio::Sink,
|
|
pub stream_thread: std::thread::JoinHandle<()>,
|
|
pub stream_handle: rodio::OutputStreamHandle,
|
|
pub stream_source: String,
|
|
pub stream_exif: String,
|
|
pub exif_date: SystemTime,
|
|
pub decode_err_date: SystemTime,
|
|
pub volume: f32,
|
|
pub playing: bool
|
|
}
|
|
|
|
impl Player {
|
|
pub fn new(sink: rodio::Sink, stream_handle: rodio::OutputStreamHandle) -> Self {
|
|
Self {
|
|
sink,
|
|
stream_handle,
|
|
stream_thread: std::thread::spawn(|| {}),
|
|
stream_source: "https://radio.wownero.com/wow.ogg".to_owned(),
|
|
stream_exif: "".to_owned(),
|
|
exif_date: SystemTime::now(),
|
|
decode_err_date: SystemTime::now(),
|
|
volume: 100.0,
|
|
playing: false
|
|
}
|
|
}
|
|
|
|
pub fn default() -> Self {
|
|
let (_stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
|
|
let sink = rodio::Sink::try_new(&stream_handle).unwrap();
|
|
Self::new(sink, stream_handle)
|
|
}
|
|
|
|
pub fn check_proxy(&self) -> bool {
|
|
let stream = std::net::TcpStream::connect("127.0.0.1:19050");
|
|
return stream.is_ok()
|
|
}
|
|
|
|
pub fn get_radio_size(&self) -> u64 {
|
|
let file = std::fs::File::open(crate::RADIO_STREAM);
|
|
if file.is_ok() {
|
|
return file.unwrap().metadata().unwrap().len();
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
pub fn start_radio_stream(&self, tor_required: bool) -> std::thread::JoinHandle<()> {
|
|
let url = self.stream_source.clone();
|
|
let t: Result<std::thread::JoinHandle<()>, std::io::Error> = std::thread::Builder::new().name("radio_stream".to_string()).spawn(move || {
|
|
let mut client_builder = reqwest::blocking::Client::builder()
|
|
.user_agent("WOC GUI + BoomBox");
|
|
if tor_required {
|
|
let proxy = reqwest::Proxy::all("socks5://127.0.0.1:19050").unwrap();
|
|
client_builder = client_builder.proxy(proxy);
|
|
}
|
|
let mut res = client_builder.build()
|
|
.unwrap()
|
|
.get(url)
|
|
.send()
|
|
.unwrap();
|
|
let mut out: std::fs::File = std::fs::File::create(&crate::RADIO_STREAM).expect("failed to create file");
|
|
std::io::copy(&mut res, &mut out).expect("failed to copy content");
|
|
});
|
|
return t.unwrap()
|
|
}
|
|
|
|
pub fn wait_for_source(&self) {
|
|
loop {
|
|
let r: Result<std::fs::File, std::io::Error> = std::fs::File::open(&crate::RADIO_STREAM);
|
|
if r.is_ok() {
|
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
|
return ()
|
|
}
|
|
std::thread::sleep(std::time::Duration::from_secs(2));
|
|
}
|
|
}
|
|
|
|
pub fn get_song_meta(&self) -> Option<String> {
|
|
let file = std::fs::File::open(&crate::RADIO_STREAM);
|
|
if file.is_ok() {
|
|
let mut buffer = vec![];
|
|
let file_size = file.unwrap().metadata().unwrap().len();
|
|
let chunk_size = 100000;
|
|
let mut start_pos = if file_size < chunk_size { 0 } else { file_size - chunk_size };
|
|
let tries = file_size / chunk_size;
|
|
for _i in 0..tries + 1 {
|
|
// println!("Scanning radio stream: {} ({} bytes)\nTry: {}", &crate::RADIO_STREAM, file_size, _i);
|
|
let mut f = std::fs::File::open(&crate::RADIO_STREAM).unwrap();
|
|
f.seek(std::io::SeekFrom::Start(start_pos)).unwrap();
|
|
f.take(chunk_size).read_to_end(&mut buffer).unwrap();
|
|
let s = std::string::String::from_utf8_lossy(&buffer);
|
|
let re = regex::Regex::new(r"title=(.*).{4}server=").unwrap();
|
|
let caps = re.captures(&s);
|
|
if caps.is_some() {
|
|
// eat whatever the fuck you want - food moderation and other philosophies
|
|
// im 63, i walk everyday, everyone can do that, if they want
|
|
// if you're gonna drink, you gotta balance it out
|
|
return Some(caps.unwrap().get(1).map_or("", |m| m.as_str()).to_owned());
|
|
}
|
|
if start_pos < chunk_size {
|
|
start_pos = 0;
|
|
} else {
|
|
start_pos -= chunk_size;
|
|
}
|
|
}
|
|
}
|
|
return Some("".to_owned());
|
|
}
|
|
|
|
pub fn get_radio_source(&self) -> Result<rodio::Decoder<std::io::BufReader<std::fs::File>>, ()> {
|
|
// Self::wait_for_source();
|
|
let f = std::fs::File::open(&crate::RADIO_STREAM);
|
|
if let Ok(fo) = f {
|
|
let file = std::io::BufReader::new(fo);
|
|
let source = rodio::Decoder::new(file).unwrap();
|
|
return Ok(source)
|
|
}
|
|
Err(())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|