1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
//! Provides the `AudioFile` abstraction for handling audio stream playback.
//!
//! This module implements a unified interface for both encrypted and unencrypted audio files,
//! providing buffered reading optimized for media playback. All downloads are wrapped in
//! a 32 KiB buffer, with additional 2 KiB block processing for encrypted content.
//!
//! # Examples
//!
//! ```no_run
//! use pleezer::audio_file::AudioFile;
//! use std::io::{Read, Seek, SeekFrom};
//!
//! // Create audio file, handling potential errors
//! let mut audio = AudioFile::try_from_download(&track, download)?;
//!
//! // Check if seeking is supported
//! if audio.is_seekable() {
//! audio.seek(SeekFrom::Start(1000))?;
//! }
//!
//! // Read data, handling I/O errors
//! let mut buf = vec![0; 1024];
//! match audio.read(&mut buf) {
//! Ok(n) => println!("Read {n} bytes"),
//! Err(e) => eprintln!("Read error: {e}"),
//! }
//! ```
use ;
use ;
use MediaSource;
use crate::;
/// Combines Read and Seek traits for audio stream handling.
///
/// This trait requires thread-safety (Send + Sync) to enable:
/// * Concurrent playback and downloading
/// * Safe sharing between threads
/// * Integration with async runtimes
/// Blanket implementation for any type that implements both Read and Seek
/// Default buffer size for audio stream reads (32 KiB).
///
/// This size is chosen to match Symphonia's read pattern, which reads
/// sequentially in increasing chunks up to 32 KiB. This buffering is applied
/// to all downloads, with encrypted content receiving additional 2 KiB block
/// processing through the [`Decrypt`] implementation.
pub const BUFFER_LEN: usize = 32 * 1024;
/// Represents an audio file stream that can be either encrypted or unencrypted.
///
/// `AudioFile` provides a unified interface for handling audio streams, wrapping
/// all downloads in a 32 KiB buffer. For encrypted content, additional 2 KiB
/// block processing is applied through the [`Decrypt`] implementation.
/// Implements reading from the audio stream.
///
/// This implementation delegates all read operations directly to the underlying stream,
/// whether it's a decrypted stream or raw download stream, providing transparent
/// handling of encrypted and unencrypted content.
///
/// # Arguments
///
/// * `buf` - Buffer to read data into
///
/// # Returns
///
/// Number of bytes read, or 0 at end of stream
///
/// # Errors
///
/// Propagates errors from the underlying stream:
/// * `InvalidInput` - Buffer position invalid
/// * `InvalidData` - Decryption failed
/// * Standard I/O errors
/// Implements seeking within the audio stream.
///
/// This implementation delegates all seek operations directly to the underlying stream.
/// Note that seeking may not be available for livestreams, which can be checked via
/// the `is_seekable()` method.
///
/// # Arguments
///
/// * `pos` - Seek position (Start/Current/End)
///
/// # Returns
///
/// New position in the stream
///
/// # Errors
///
/// Propagates errors from the underlying stream:
/// * `InvalidInput` - Invalid seek position
/// * `UnexpectedEof` - Seek beyond end of file
/// * `Unsupported` - Seeking from end with unknown size
/// Implements the `MediaSource` trait required by Symphonia for media playback.
///
/// This implementation provides metadata about the stream's capabilities and properties:
/// - Seekability: determined by whether the track is a livestream
/// - Byte length: provided if known from the track metadata