Merge pull request #137 from awiouy/core_API

core API review changes.
This commit is contained in:
Sasha Hilton 2018-02-10 23:14:41 +01:00 committed by GitHub
commit f3bb85c33a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 84 additions and 86 deletions

View file

@ -1,8 +1,11 @@
use std::path::PathBuf; use std::fs;
use std::io::Read;
use std::fs::File; 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; use authentication::Credentials;
#[derive(Clone)] #[derive(Clone)]
@ -11,6 +14,16 @@ pub struct Cache {
use_audio_cache: bool, 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 { impl Cache {
pub fn new(location: PathBuf, use_audio_cache: bool) -> Cache { pub fn new(location: PathBuf, use_audio_cache: bool) -> Cache {
mkdir_existing(&location).unwrap(); mkdir_existing(&location).unwrap();

View file

@ -11,7 +11,7 @@ pub struct MercurySender {
impl MercurySender { impl MercurySender {
// TODO: pub(super) when stable // TODO: pub(super) when stable
pub fn new(mercury: MercuryManager, uri: String) -> MercurySender { pub(crate) fn new(mercury: MercuryManager, uri: String) -> MercurySender {
MercurySender { MercurySender {
mercury: mercury, mercury: mercury,
uri: uri, uri: uri,

View file

@ -184,7 +184,7 @@ impl Session {
self.0.cache.as_ref() self.0.cache.as_ref()
} }
pub fn config(&self) -> &SessionConfig { fn config(&self) -> &SessionConfig {
&self.0.config &self.0.config
} }
@ -200,7 +200,7 @@ impl Session {
&self.config().device_id &self.config().device_id
} }
pub fn weak(&self) -> SessionWeak { fn weak(&self) -> SessionWeak {
SessionWeak(Arc::downgrade(&self.0)) SessionWeak(Arc::downgrade(&self.0))
} }
@ -213,11 +213,11 @@ impl Session {
pub struct SessionWeak(pub Weak<SessionInternal>); pub struct SessionWeak(pub Weak<SessionInternal>);
impl SessionWeak { impl SessionWeak {
pub fn try_upgrade(&self) -> Option<Session> { fn try_upgrade(&self) -> Option<Session> {
self.0.upgrade().map(Session) self.0.upgrade().map(Session)
} }
pub fn upgrade(&self) -> Session { pub(crate) fn upgrade(&self) -> Session {
self.try_upgrade().expect("Session died") self.try_upgrade().expect("Session died")
} }
} }

View file

@ -2,54 +2,19 @@ use num_bigint::BigUint;
use num_traits::{Zero, One}; use num_traits::{Zero, One};
use num_integer::Integer; use num_integer::Integer;
use rand::{Rng, Rand}; use rand::{Rng, Rand};
use std::io;
use std::mem; use std::mem;
use std::ops::{Mul, Rem, Shr}; 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 int128;
mod spotify_id; mod spotify_id;
mod subfile;
pub use util::int128::u128; pub use util::int128::u128;
pub use util::spotify_id::{SpotifyId, FileId}; 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> { pub fn rand_vec<G: Rng, R: Rand>(rng: &mut G, size: usize) -> Vec<R> {
rng.gen_iter().take(size).collect() 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 { pub fn powm(base: &BigUint, exp: &BigUint, modulus: &BigUint) -> BigUint {
let mut base = base.clone(); let mut base = base.clone();
let mut exp = exp.clone(); let mut exp = exp.clone();

View file

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

View file

@ -1,15 +1,17 @@
use futures::sync::oneshot; use futures::sync::oneshot;
use futures::{future, Future}; use futures::{future, Future};
use std;
use std::borrow::Cow; use std::borrow::Cow;
use std::io::{Read, Seek, SeekFrom, Result};
use std::mem; use std::mem;
use std::process::Command;
use std::sync::mpsc::{RecvError, TryRecvError, RecvTimeoutError}; use std::sync::mpsc::{RecvError, TryRecvError, RecvTimeoutError};
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use std;
use core::config::{Bitrate, PlayerConfig}; use core::config::{Bitrate, PlayerConfig};
use core::session::Session; use core::session::Session;
use core::util::{self, SpotifyId, Subfile}; use core::util::SpotifyId;
use audio_backend::Sink; use audio_backend::Sink;
use audio::{AudioFile, AudioDecrypt}; use audio::{AudioFile, AudioDecrypt};
@ -375,13 +377,13 @@ impl PlayerInternal {
fn run_onstart(&self) { fn run_onstart(&self) {
if let Some(ref program) = self.config.onstart { if let Some(ref program) = self.config.onstart {
util::run_program(program) run_program(program)
} }
} }
fn run_onstop(&self) { fn run_onstop(&self) {
if let Some(ref program) = self.config.onstop { 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);
}

View file

@ -6,7 +6,7 @@ use protobuf::{self, Message};
use core::config::ConnectConfig; use core::config::ConnectConfig;
use core::mercury::MercuryError; use core::mercury::MercuryError;
use core::session::Session; use core::session::Session;
use core::util::{now_ms, SpotifyId, SeqGenerator}; use core::util::{SpotifyId, SeqGenerator};
use core::version; use core::version;
use protocol; use protocol;
@ -18,6 +18,7 @@ use playback::player::Player;
use std; use std;
use rand; use rand;
use rand::Rng; use rand::Rng;
use std::time::{UNIX_EPOCH, SystemTime};
pub struct SpircTask { pub struct SpircTask {
player: Player, player: Player,
@ -53,6 +54,14 @@ pub struct Spirc {
commands: mpsc::UnboundedSender<SpircCommand>, 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 { fn initial_state() -> State {
protobuf_init!(protocol::spirc::State::new(), { protobuf_init!(protocol::spirc::State::new(), {
repeat: false, repeat: false,