initial prototype
This commit is contained in:
41
src/streamer.rs
Normal file
41
src/streamer.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use crate::state::AppState;
|
||||
use axum::{body::Body, extract::State, response::Response};
|
||||
use std::sync::Arc;
|
||||
use tokio_stream::Stream;
|
||||
|
||||
pub async fn stream_handler(State(state): State<Arc<AppState>>) -> Response {
|
||||
let stream = create_chunk_stream(state);
|
||||
let body = Body::from_stream(stream);
|
||||
|
||||
Response::builder()
|
||||
.header("Content-Type", "audio/mpeg")
|
||||
.header("Cache-Control", "no-cache")
|
||||
.body(body)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn create_chunk_stream(
|
||||
state: Arc<AppState>,
|
||||
) -> impl Stream<Item = Result<bytes::Bytes, std::io::Error>> {
|
||||
async_stream::stream! {
|
||||
let mut position = 0;
|
||||
|
||||
loop {
|
||||
// Send available chunks
|
||||
let chunks = state.chunks.read().await;
|
||||
while position < chunks.len() {
|
||||
yield Ok(chunks[position].clone());
|
||||
position += 1;
|
||||
}
|
||||
drop(chunks);
|
||||
|
||||
// Exit if download complete and all chunks sent
|
||||
if state.is_complete().await && position >= state.chunk_count().await {
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait for new chunks
|
||||
state.notify.notified().await;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user