added android client

This commit is contained in:
nvrl committed 2026-08-05 13:07:56 +02:00
1 parent 8b95cf7a05
commit 6db6909824
73 files changed
+9234 -106

No files matched your search

+1 -1
View File
@@ -39,7 +39,7 @@ pub use error::{Error, Result};
/// returns it and `StreamSource::open` takes it — and taking a dependency on the
/// whole SDK for a newtype is not a reasonable price for that.
pub use proton_sdk::ids::NodeUid;
pub use reader::{LibraryOpener, RevisionBlocks};
pub use reader::{FileBlocks, LibraryOpener, RevisionBlocks};
pub use ring::{DEFAULT_RING_BYTES, RingStats};
pub use source::{RevisionOpener, StreamConfig, StreamSource};
pub use stream::{DEFAULT_READAHEAD_BLOCKS, StreamStats, VideoStream};
+46
View File
@@ -8,6 +8,7 @@
//! one, and the caching layer above would then hold neither of them whole.
//! Aligning here means each block is fetched, decrypted and cached exactly once.
use std::path::PathBuf;
use std::sync::Arc;
use async_trait::async_trait;
@@ -63,6 +64,51 @@ impl BlockSource for RevisionBlocks {
}
}
/// A fully-downloaded revision. It uses the same block seam as Proton so mpv
/// can seek normally without a second playback path.
pub struct FileBlocks {
revision_id: String,
path: PathBuf,
sizes: Vec<u64>,
map: BlockMap,
}
impl FileBlocks {
pub fn new(revision_id: String, path: PathBuf, sizes: Vec<u64>) -> Self {
let map = BlockMap::new(&sizes);
Self {
revision_id,
path,
sizes,
map,
}
}
}
#[async_trait]
impl BlockSource for FileBlocks {
fn revision_id(&self) -> &str {
&self.revision_id
}
fn block_sizes(&self) -> &[u64] {
&self.sizes
}
async fn read_block(&self, index: usize) -> Result<Vec<u8>> {
use tokio::io::{AsyncReadExt, AsyncSeekExt};
let (start, size) = match (self.map.start_of(index), self.map.size_of(index)) {
(Some(a), Some(b)) => (a, b),
_ => {
return Err(Error::NotFound(format!(
"offline block {index} is past the end"
)));
}
};
let mut file = tokio::fs::File::open(&self.path).await?;
file.seek(std::io::SeekFrom::Start(start)).await?;
let mut data = vec![0; size as usize];
file.read_exact(&mut data).await?;
Ok(data)
}
}
/// Opens revisions out of the configured shares.
pub struct LibraryOpener {
library: Arc<pstr_core::SharedLibrary>,
+4
View File
@@ -121,6 +121,10 @@ struct Inner {
}
impl VideoStream {
/// Build a seekable stream from complete local content.
pub fn offline(uid: NodeUid, blocks: SharedBlocks, ring_bytes: u64) -> Self {
Self::new(uid, blocks, Arc::new(BlockRing::new(ring_bytes)), None, 0)
}
pub(crate) fn new(
uid: NodeUid,
blocks: SharedBlocks,