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
//! Download delegates for the central API service.
use std::{
path::{Path, PathBuf},
sync::{Arc, atomic::AtomicBool},
};
use crate::{
api::{
content::{
album_download::download_album,
artist_download::download_artist,
playlist_download::download_playlist,
tracks::{download_track, get_track_file_url},
},
service::QobuzApiService,
},
errors::QobuzApiError,
metadata::config::MetadataConfig,
models::file_url::FileUrl,
};
impl QobuzApiService {
delegate_with_retry!(pub fn get_track_file_url(track_id: i32, format_id: i32) -> FileUrl = get_track_file_url);
delegate_with_retry_cancellable!(
pub fn download_track_cancellable(track_id: i32, format_id: i32, output_dir: &Path, config: Option<&MetadataConfig>) -> PathBuf = download_track,
cancel: Option<&AtomicBool>
);
delegate_with_retry_cancellable!(
pub fn download_album_cancellable(album_id: &str, format_id: i32, output_dir: &Path, config: Option<&MetadataConfig>, concurrency: Option<usize>) -> Vec<PathBuf> = download_album,
cancel: Option<Arc<AtomicBool>>
);
delegate_with_retry_cancellable!(
pub fn download_artist_cancellable(artist_id: i32, format_id: i32, output_dir: &Path, config: Option<&MetadataConfig>, concurrency: Option<usize>) -> Vec<PathBuf> = download_artist,
cancel: Option<Arc<AtomicBool>>
);
delegate_with_retry_cancellable!(
pub fn download_playlist_cancellable(playlist_id: &str, format_id: i32, output_dir: &Path, config: Option<&MetadataConfig>, concurrency: Option<usize>) -> Vec<PathBuf> = download_playlist,
cancel: Option<Arc<AtomicBool>>
);
/// Downloads a single track with cancellation support.
///
/// # Arguments
///
/// * `track_id` - Track identifier
/// * `format_id` - Quality format ID
/// * `output_dir` - Directory to save the downloaded file
/// * `config` - Optional metadata configuration for tagging
/// * `cancel` - Optional cancellation flag checked during the download
///
/// # Returns
///
/// The path to the downloaded file.
///
/// # Errors
///
/// Returns a `QobuzApiError` if URL retrieval, download, I/O fails, or `Canceled` if cancelled.
pub fn download_track(
&mut self,
track_id: i32,
format_id: i32,
output_dir: &Path,
config: Option<&MetadataConfig>,
) -> Result<PathBuf, QobuzApiError> {
self.download_track_cancellable(track_id, format_id, output_dir, config, None)
}
/// Downloads an album.
///
/// # Arguments
///
/// * `album_id` - Album identifier
/// * `format_id` - Quality format ID
/// * `output_dir` - Base output directory for downloaded files
/// * `config` - Optional metadata configuration for tagging
/// * `concurrency` - Maximum number of concurrent track downloads
///
/// # Returns
///
/// A vector of paths to the downloaded track files.
///
/// # Errors
///
/// Returns a `QobuzApiError` if album retrieval, track download, or I/O fails.
pub fn download_album(
&mut self,
album_id: &str,
format_id: i32,
output_dir: &Path,
config: Option<&MetadataConfig>,
concurrency: Option<usize>,
) -> Result<Vec<PathBuf>, QobuzApiError> {
self.download_album_cancellable(album_id, format_id, output_dir, config, concurrency, None)
}
/// Downloads all albums by an artist.
///
/// # Arguments
///
/// * `artist_id` - Artist identifier
/// * `format_id` - Quality format ID
/// * `output_dir` - Base output directory for downloaded files
/// * `config` - Optional metadata configuration for tagging
/// * `concurrency` - Maximum number of concurrent track downloads per album
///
/// # Returns
///
/// A vector of paths to the downloaded track files.
///
/// # Errors
///
/// Returns a `QobuzApiError` if artist release list retrieval or any album download fails.
pub fn download_artist(
&mut self,
artist_id: i32,
format_id: i32,
output_dir: &Path,
config: Option<&MetadataConfig>,
concurrency: Option<usize>,
) -> Result<Vec<PathBuf>, QobuzApiError> {
self.download_artist_cancellable(
artist_id,
format_id,
output_dir,
config,
concurrency,
None,
)
}
/// Downloads all tracks in a playlist.
///
/// # Arguments
///
/// * `playlist_id` - Playlist identifier
/// * `format_id` - Quality format ID
/// * `output_dir` - Base output directory for downloaded files
/// * `config` - Optional metadata configuration for tagging
/// * `concurrency` - Maximum number of concurrent track downloads (unused for playlists)
///
/// # Returns
///
/// A vector of paths to the downloaded track files.
///
/// # Errors
///
/// Returns a `QobuzApiError` if playlist retrieval, directory creation, or any track download
/// fails.
pub fn download_playlist(
&mut self,
playlist_id: &str,
format_id: i32,
output_dir: &Path,
config: Option<&MetadataConfig>,
concurrency: Option<usize>,
) -> Result<Vec<PathBuf>, QobuzApiError> {
self.download_playlist_cancellable(
playlist_id,
format_id,
output_dir,
config,
concurrency,
None,
)
}
}