1use std::fmt;
4use std::sync::Arc;
5
6use crate::cancellation::CancellationToken;
7use crate::config::DownloadOptions;
8use crate::error::{Error, Result};
9use crate::event::ProgressEvent;
10use crate::manifest::StreamSelector;
11use crate::session::DownloadSession;
12
13#[derive(Clone, Debug, Default)]
15pub struct DownloadClient;
16
17impl DownloadClient {
18 pub fn new() -> Self {
20 Self
21 }
22
23 pub fn prepare(&self, request: DownloadRequest) -> Result<DownloadSession> {
25 if request.input.trim().is_empty() {
26 return Err(Error::config("input must not be empty"));
27 }
28 Ok(DownloadSession::new(request))
29 }
30}
31
32type ProgressCallbackFn = dyn Fn(&ProgressEvent) -> Result<()> + Send + Sync + 'static;
38
39#[derive(Clone)]
40pub struct ProgressCallback {
41 callback: Arc<ProgressCallbackFn>,
42}
43
44impl ProgressCallback {
45 pub fn new<F>(callback: F) -> Self
47 where
48 F: Fn(&ProgressEvent) -> Result<()> + Send + Sync + 'static,
49 {
50 Self {
51 callback: Arc::new(callback),
52 }
53 }
54
55 pub fn emit(&self, event: &ProgressEvent) -> Result<()> {
57 (self.callback)(event)
58 }
59}
60
61impl fmt::Debug for ProgressCallback {
62 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
63 formatter.write_str("ProgressCallback")
64 }
65}
66
67#[derive(Clone, Debug)]
69pub struct DownloadRequest {
70 pub input: String,
72 pub options: DownloadOptions,
74 pub stream_selector: StreamSelector,
76 pub cancellation_token: CancellationToken,
78 pub progress_callback: Option<ProgressCallback>,
80}
81
82impl DownloadRequest {
83 pub fn new(input: impl Into<String>) -> Self {
85 Self {
86 input: input.into(),
87 options: DownloadOptions::default(),
88 stream_selector: StreamSelector::default(),
89 cancellation_token: CancellationToken::new(),
90 progress_callback: None,
91 }
92 }
93
94 pub fn with_options(mut self, options: DownloadOptions) -> Self {
96 self.options = options;
97 self
98 }
99
100 pub fn with_stream_selector(mut self, stream_selector: StreamSelector) -> Self {
102 self.stream_selector = stream_selector;
103 self
104 }
105
106 pub fn with_cancellation_token(mut self, cancellation_token: CancellationToken) -> Self {
108 self.cancellation_token = cancellation_token;
109 self
110 }
111
112 pub fn with_progress_callback(mut self, progress_callback: ProgressCallback) -> Self {
114 self.progress_callback = Some(progress_callback);
115 self
116 }
117}
118
119#[derive(Clone, Debug)]
121pub struct LiveRecorder {
122 request: DownloadRequest,
123}
124
125impl LiveRecorder {
126 pub fn new(request: DownloadRequest) -> Self {
128 Self { request }
129 }
130
131 pub fn request(&self) -> &DownloadRequest {
133 &self.request
134 }
135
136 pub async fn start(self) -> Result<Vec<ProgressEvent>> {
138 Box::pin(DownloadClient::new().prepare(self.request)?.start()).await
139 }
140}