mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
commit
f3bb85c33a
7 changed files with 84 additions and 86 deletions
|
@ -1,8 +1,11 @@
|
|||
use std::path::PathBuf;
|
||||
use std::io::Read;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use util::{FileId, mkdir_existing};
|
||||
use util::FileId;
|
||||
use authentication::Credentials;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -11,6 +14,16 @@ pub struct Cache {
|
|||
use_audio_cache: bool,
|
||||
}
|
||||
|
||||
fn mkdir_existing(path: &Path) -> io::Result<()> {
|
||||
fs::create_dir(path).or_else(|err| {
|
||||
if err.kind() == io::ErrorKind::AlreadyExists {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
impl Cache {
|
||||
pub fn new(location: PathBuf, use_audio_cache: bool) -> Cache {
|
||||
mkdir_existing(&location).unwrap();
|
||||
|
|
|
@ -11,7 +11,7 @@ pub struct MercurySender {
|
|||
|
||||
impl MercurySender {
|
||||
// TODO: pub(super) when stable
|
||||
pub fn new(mercury: MercuryManager, uri: String) -> MercurySender {
|
||||
pub(crate) fn new(mercury: MercuryManager, uri: String) -> MercurySender {
|
||||
MercurySender {
|
||||
mercury: mercury,
|
||||
uri: uri,
|
||||
|
|
|
@ -184,7 +184,7 @@ impl Session {
|
|||
self.0.cache.as_ref()
|
||||
}
|
||||
|
||||
pub fn config(&self) -> &SessionConfig {
|
||||
fn config(&self) -> &SessionConfig {
|
||||
&self.0.config
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ impl Session {
|
|||
&self.config().device_id
|
||||
}
|
||||
|
||||
pub fn weak(&self) -> SessionWeak {
|
||||
fn weak(&self) -> SessionWeak {
|
||||
SessionWeak(Arc::downgrade(&self.0))
|
||||
}
|
||||
|
||||
|
@ -213,11 +213,11 @@ impl Session {
|
|||
pub struct SessionWeak(pub Weak<SessionInternal>);
|
||||
|
||||
impl SessionWeak {
|
||||
pub fn try_upgrade(&self) -> Option<Session> {
|
||||
fn try_upgrade(&self) -> Option<Session> {
|
||||
self.0.upgrade().map(Session)
|
||||
}
|
||||
|
||||
pub fn upgrade(&self) -> Session {
|
||||
pub(crate) fn upgrade(&self) -> Session {
|
||||
self.try_upgrade().expect("Session died")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,54 +2,19 @@ use num_bigint::BigUint;
|
|||
use num_traits::{Zero, One};
|
||||
use num_integer::Integer;
|
||||
use rand::{Rng, Rand};
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::ops::{Mul, Rem, Shr};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::time::{UNIX_EPOCH, SystemTime};
|
||||
|
||||
mod int128;
|
||||
mod spotify_id;
|
||||
mod subfile;
|
||||
|
||||
pub use util::int128::u128;
|
||||
pub use util::spotify_id::{SpotifyId, FileId};
|
||||
pub use util::subfile::Subfile;
|
||||
|
||||
pub fn rand_vec<G: Rng, R: Rand>(rng: &mut G, size: usize) -> Vec<R> {
|
||||
rng.gen_iter().take(size).collect()
|
||||
}
|
||||
|
||||
pub fn now_ms() -> i64 {
|
||||
let dur = match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
Ok(dur) => dur,
|
||||
Err(err) => err.duration(),
|
||||
};
|
||||
(dur.as_secs() * 1000 + (dur.subsec_nanos() / 1000_000) as u64) as i64
|
||||
}
|
||||
|
||||
pub fn mkdir_existing(path: &Path) -> io::Result<()> {
|
||||
fs::create_dir(path).or_else(|err| {
|
||||
if err.kind() == io::ErrorKind::AlreadyExists {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run_program(program: &str) {
|
||||
info!("Running {}", program);
|
||||
let mut v: Vec<&str> = program.split_whitespace().collect();
|
||||
let status = Command::new(&v.remove(0))
|
||||
.args(&v)
|
||||
.status()
|
||||
.expect("program failed to start");
|
||||
info!("Exit status: {}", status);
|
||||
}
|
||||
|
||||
pub fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
|
||||
let mut base = base.clone();
|
||||
let mut exp = exp.clone();
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
use std::io::{Read, Seek, SeekFrom, Result};
|
||||
|
||||
pub struct Subfile<T: Read + Seek> {
|
||||
stream: T,
|
||||
offset: u64,
|
||||
}
|
||||
|
||||
impl<T: Read + Seek> Subfile<T> {
|
||||
pub fn new(mut stream: T, offset: u64) -> Subfile<T> {
|
||||
stream.seek(SeekFrom::Start(offset)).unwrap();
|
||||
Subfile {
|
||||
stream: stream,
|
||||
offset: offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read + Seek> Read for Subfile<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||
self.stream.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read + Seek> Seek for Subfile<T> {
|
||||
fn seek(&mut self, mut pos: SeekFrom) -> Result<u64> {
|
||||
pos = match pos {
|
||||
SeekFrom::Start(offset) => SeekFrom::Start(offset + self.offset),
|
||||
x => x,
|
||||
};
|
||||
|
||||
let newpos = try!(self.stream.seek(pos));
|
||||
if newpos > self.offset {
|
||||
Ok(newpos - self.offset)
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +1,17 @@
|
|||
use futures::sync::oneshot;
|
||||
use futures::{future, Future};
|
||||
use std;
|
||||
use std::borrow::Cow;
|
||||
use std::io::{Read, Seek, SeekFrom, Result};
|
||||
use std::mem;
|
||||
use std::process::Command;
|
||||
use std::sync::mpsc::{RecvError, TryRecvError, RecvTimeoutError};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use std;
|
||||
|
||||
use core::config::{Bitrate, PlayerConfig};
|
||||
use core::session::Session;
|
||||
use core::util::{self, SpotifyId, Subfile};
|
||||
use core::util::SpotifyId;
|
||||
|
||||
use audio_backend::Sink;
|
||||
use audio::{AudioFile, AudioDecrypt};
|
||||
|
@ -375,13 +377,13 @@ impl PlayerInternal {
|
|||
|
||||
fn run_onstart(&self) {
|
||||
if let Some(ref program) = self.config.onstart {
|
||||
util::run_program(program)
|
||||
run_program(program)
|
||||
}
|
||||
}
|
||||
|
||||
fn run_onstop(&self) {
|
||||
if let Some(ref program) = self.config.onstop {
|
||||
util::run_program(program)
|
||||
run_program(program)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -478,3 +480,50 @@ impl ::std::fmt::Debug for PlayerCommand {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Subfile<T: Read + Seek> {
|
||||
stream: T,
|
||||
offset: u64,
|
||||
}
|
||||
|
||||
impl<T: Read + Seek> Subfile<T> {
|
||||
pub fn new(mut stream: T, offset: u64) -> Subfile<T> {
|
||||
stream.seek(SeekFrom::Start(offset)).unwrap();
|
||||
Subfile {
|
||||
stream: stream,
|
||||
offset: offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read + Seek> Read for Subfile<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
||||
self.stream.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read + Seek> Seek for Subfile<T> {
|
||||
fn seek(&mut self, mut pos: SeekFrom) -> Result<u64> {
|
||||
pos = match pos {
|
||||
SeekFrom::Start(offset) => SeekFrom::Start(offset + self.offset),
|
||||
x => x,
|
||||
};
|
||||
|
||||
let newpos = try!(self.stream.seek(pos));
|
||||
if newpos > self.offset {
|
||||
Ok(newpos - self.offset)
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_program(program: &str) {
|
||||
info!("Running {}", program);
|
||||
let mut v: Vec<&str> = program.split_whitespace().collect();
|
||||
let status = Command::new(&v.remove(0))
|
||||
.args(&v)
|
||||
.status()
|
||||
.expect("program failed to start");
|
||||
info!("Exit status: {}", status);
|
||||
}
|
||||
|
|
11
src/spirc.rs
11
src/spirc.rs
|
@ -6,7 +6,7 @@ use protobuf::{self, Message};
|
|||
use core::config::ConnectConfig;
|
||||
use core::mercury::MercuryError;
|
||||
use core::session::Session;
|
||||
use core::util::{now_ms, SpotifyId, SeqGenerator};
|
||||
use core::util::{SpotifyId, SeqGenerator};
|
||||
use core::version;
|
||||
|
||||
use protocol;
|
||||
|
@ -18,6 +18,7 @@ use playback::player::Player;
|
|||
use std;
|
||||
use rand;
|
||||
use rand::Rng;
|
||||
use std::time::{UNIX_EPOCH, SystemTime};
|
||||
|
||||
pub struct SpircTask {
|
||||
player: Player,
|
||||
|
@ -53,6 +54,14 @@ pub struct Spirc {
|
|||
commands: mpsc::UnboundedSender<SpircCommand>,
|
||||
}
|
||||
|
||||
fn now_ms() -> i64 {
|
||||
let dur = match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
Ok(dur) => dur,
|
||||
Err(err) => err.duration(),
|
||||
};
|
||||
(dur.as_secs() * 1000 + (dur.subsec_nanos() / 1000_000) as u64) as i64
|
||||
}
|
||||
|
||||
fn initial_state() -> State {
|
||||
protobuf_init!(protocol::spirc::State::new(), {
|
||||
repeat: false,
|
||||
|
|
Loading…
Reference in a new issue