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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
gui/src/player.rs

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(())
}
}