Audacity 3.2.0
ServiceConfig.cpp
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*!********************************************************************
3
4 Audacity: A Digital Audio Editor
5
6 ServiceConfig.cpp
7
8 Dmitry Vedenko
9
10**********************************************************************/
11#include "ServiceConfig.h"
12#include "Languages.h"
13
14#include <cassert>
15#include <stdexcept>
16#include <string_view>
17
18#include <rapidjson/document.h>
19
20#include "CodeConversions.h"
21#include "Prefs.h"
22
24{
25namespace
26{
27StringSetting audioComApiEndpoint { L"/CloudServices/AudioCom/ApiEndpoint",
28 L"https://api.audio.com" };
29
30StringSetting audioComOAuthClientID { L"/CloudServices/AudioCom/OAuthClientID",
31 L"1741964426607541" };
32
34 L"/CloudServices/AudioCom/OAuthClientSecret",
35 L"shKqnY2sLTfRK7hztwzNEVxnmhJfOy1i"
36};
37
39 L"/CloudServices/AudioCom/OAuthRedirectURL",
40 L"https://audio.com/auth/sign-in/success"
41};
42
44 L"/CloudServices/AudioCom/OAuthLoginPage",
45 L"https://audio.com/audacity/link?clientId={auth_client_id}"
46};
47
49 L"/CloudServices/AudioCom/FinishUploadPage",
50 L"https://audio.com/audacity/upload?audioId={audio_id}&token={auth_token}&clientId={auth_client_id}"
51};
52
53StringSetting audioComFrontendUrl { L"/CloudServices/AudioCom/FrontendURL",
54 L"https://audio.com" };
55
57 L"/CloudServices/AudioCom/DownloadMimeType", L"audio/x-wav"
58};
59
60std::string Substitute(
61 std::string pattern,
62 std::initializer_list<std::pair<std::string_view, std::string_view>>
63 substitutions)
64{
65 for (auto& [key, value] : substitutions)
66 {
67 auto pos = pattern.find(key);
68
69 while (pos > 0 && pos != std::string::npos)
70 {
71 // There is no need to check that pos + key.size() is valid, there
72 // will be a zero terminator in the worst case.
73 if (pattern[pos - 1] == '{' && pattern[pos + key.size()] == '}')
74 pattern.replace(pos - 1, key.size() + 2, value);
75
76 pos = pattern.find(key, pos + 1);
77 }
78 }
79
80 return std::move(pattern);
81}
82
83} // namespace
84
86{
95}
96
98{
99 return mApiEndpoint;
100}
101
103{
104 return Substitute(
105 mOAuthLoginPage, { { "auth_client_id", GetOAuthClientID() } });
106}
107
109{
110 return mOAuthClientID;
111}
112
114{
115 return mOAuthClientSecret;
116}
117
119{
120 return mOAuthRedirectURL;
121}
122
123std::string ServiceConfig::GetAPIUrl(std::string_view apiURI) const
124{
125 return mApiEndpoint + std::string(apiURI);
126}
127
129 std::string_view audioID, std::string_view token) const
130{
131 return Substitute(
132 mFinishUploadPage, { { "audio_id", audioID },
133 { "auth_token", token },
134 { "auth_client_id", mOAuthClientID } });
135}
136
138 std::string_view userSlug, std::string_view audioSlug) const
139{
140 return Substitute(
141 "{frontend_url}/{user_slug}/audio/{audio_slug}/edit",
142 { { "frontend_url", mFrontendURL },
143 { "user_slug", userSlug },
144 { "audio_slug", audioSlug } });
145}
146
147std::chrono::milliseconds ServiceConfig::GetProgressCallbackTimeout() const
148{
149 return std::chrono::seconds(3);
150}
151
152std::vector<std::string>
154{
155 if (preferLossless)
156 return { "audio/x-wavpack", "audio/x-flac", "audio/x-wav" };
157 else
158 return { "audio/mpeg" };
159}
160
161rapidjson::Document
162ServiceConfig::GetExportConfig(const std::string& mimeType) const
163{
164 if (mimeType == "audio/x-wavpack")
165 {
166 rapidjson::Document config;
167 config.SetObject();
168 config.AddMember("quality", rapidjson::Value(2), config.GetAllocator());
169 config.AddMember("bit_rate", rapidjson::Value(40), config.GetAllocator());
170 config.AddMember("bit_depth", 24, config.GetAllocator());
171 config.AddMember("hybrid_mode", false, config.GetAllocator());
172 return config;
173 }
174 else if (mimeType == "audio/x-flac")
175 {
176 rapidjson::Document config;
177 config.SetObject();
178 config.AddMember(
179 "bit_depth", rapidjson::Value(24), config.GetAllocator());
180 config.AddMember("level", rapidjson::Value(5), config.GetAllocator());
181 }
182 else if (mimeType == "audio/x-wav")
183 {
184 return {};
185 }
186 else if (mimeType == "audio/mpeg")
187 {
188 rapidjson::Document config;
189 config.SetObject();
190 config.AddMember("mode", rapidjson::Value("VBR"), config.GetAllocator());
191 config.AddMember("quality", rapidjson::Value(5), config.GetAllocator());
192 return config;
193 }
194
195 throw std::invalid_argument("unknown mime-type");
196}
197
199{
200 return mPreferredMimeType;
201}
202
204{
205 auto language = Languages::GetLang();
206
207 if (language.Contains(L"-") && language.Length() > 2)
208 return wxString::Format(
209 "%s;q=1.0, %s;q=0.7, *;q=0.5", language, language.Left(2))
210 .ToStdString();
211 else
212 return wxString::Format("%s;q=1.0, *;q=0.5", language).ToStdString();
213}
214
216{
217 return GetAPIUrl("/project");
218}
219
220std::string
221ServiceConfig::GetCreateSnapshotUrl(std::string_view projectId) const
222{
223 return Substitute(
224 "{api_url}/project/{project_id}/snapshot",
225 { { "api_url", mApiEndpoint }, { "project_id", projectId } });
226}
227
229 std::string_view projectId, std::string_view snapshotId) const
230{
231 return Substitute(
232 "{api_url}/project/{project_id}/snapshot/{snapshot_id}/sync",
233 { { "api_url", mApiEndpoint },
234 { "project_id", projectId },
235 { "snapshot_id", snapshotId } });
236}
237
239 int page, int pageSize, std::string_view searchTerm) const
240{
241 if (searchTerm.empty())
242 return Substitute(
243 "{api_url}/project?page={page}&per-page={page_size}",
244 { { "api_url", mApiEndpoint },
245 { "page", std::to_string(page) },
246 { "page_size", std::to_string(pageSize) }, });
247
248 return Substitute(
249 "{api_url}/project?page={page}&per-page={page_size}&q={search_term}",
250 { { "api_url", mApiEndpoint },
251 { "page", std::to_string(page) },
252 { "page_size", std::to_string(pageSize) },
253 { "search_term", searchTerm }, });
254}
255
256std::string ServiceConfig::GetProjectInfoUrl(std::string_view projectId) const
257{
258 return Substitute(
259 "{api_url}/project/{project_id}", {
260 { "api_url", mApiEndpoint },
261 { "project_id", projectId },
262 });
263}
264
266 std::string_view projectId, std::string_view snapshotId) const
267{
268 return Substitute(
269 "{api_url}/project/{project_id}/snapshot/{snapshot_id}?expand=blocks,file_url",
270 {
271 { "api_url", mApiEndpoint },
272 { "project_id", projectId },
273 { "snapshot_id", snapshotId },
274 });
275}
276
278 std::string_view projectId, std::string_view snapshotId) const
279{
280 return Substitute(
281 "{api_url}/project/{project_id}/snapshot/{snapshot_id}",
282 {
283 { "api_url", mApiEndpoint },
284 { "project_id", projectId },
285 { "snapshot_id", snapshotId },
286 });
287}
288
289std::string ServiceConfig::GetNetworkStatsUrl(std::string_view projectId) const
290{
291 return Substitute(
292 "{api_url}/project/{project_id}/network-stats",
293 {
294 { "api_url", mApiEndpoint },
295 { "project_id", projectId },
296 });
297}
298
300 std::string_view userId, std::string_view projectId) const
301{
302 return Substitute(
303 "{frontend_url}/{user_slug}/projects/{project_id}",
304 {
305 { "frontend_url", mFrontendURL },
306 { "user_slug", userId },
307 { "project_id", projectId },
308 });
309}
310
311std::string ServiceConfig::GetProjectsPageUrl(std::string_view userId) const
312{
313 return Substitute(
314 "{frontend_url}/{user_slug}/projects",
315 {
316 { "frontend_url", mFrontendURL },
317 { "user_slug", userId },
318 });
319}
320
322{
323 static ServiceConfig config;
324 return config;
325}
326
327} // namespace audacity::cloud::audiocom
Declare functions to perform UTF-8 to std::wstring conversions.
static const AudacityProject::AttachedObjects::RegisteredFactory key
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207
Specialization of Setting for strings.
Definition: Prefs.h:370
Configuration for the audio.com.
Definition: ServiceConfig.h:23
std::string GetProjectsUrl(int page, int pageSize, std::string_view searchTerm) const
std::string GetProjectPageUrl(std::string_view userId, std::string_view projectId) const
std::vector< std::string > GetPreferredAudioFormats(bool preferLossless=true) const
Preferred audio format.
std::string GetOAuthLoginPage() const
Page to open in browser to initiate OAuth.
std::string GetNetworkStatsUrl(std::string_view projectId) const
std::string GetOAuthRedirectURL() const
OAuth2 redirect URL. Only used to satisfy the protocol.
std::string GetCreateSnapshotUrl(std::string_view projectId) const
std::string GetFinishUploadPage(std::string_view audioID, std::string_view token) const
Helper to construct the page URL for the anonymous upload last stage.
std::string GetOAuthClientSecret() const
OAuth2 client secret.
std::string GetAPIEndpoint() const
API endpoint.
rapidjson::Document GetExportConfig(const std::string &exporterName) const
Export configuration suitable for the mime type provided.
std::string GetSnapshotInfoUrl(std::string_view projectId, std::string_view snapshotId) const
std::chrono::milliseconds GetProgressCallbackTimeout() const
Timeout between progress callbacks.
std::string GetAPIUrl(std::string_view apiURI) const
Helper to construct the full URLs for the API.
std::string GetDeleteSnapshotUrl(std::string_view projectId, std::string_view snapshotId) const
std::string GetProjectsPageUrl(std::string_view userId) const
std::string GetAudioURL(std::string_view userSlug, std::string_view audioSlug) const
Helper to construct the page URL for the authorised upload.
std::string GetProjectInfoUrl(std::string_view projectId) const
std::string GetAcceptLanguageValue() const
Returns the preferred language.
std::string GetSnapshotSyncUrl(std::string_view projectId, std::string_view snapshotId) const
std::string GetOAuthClientID() const
OAuth2 client ID.
wxString GetLang()
Definition: Languages.cpp:395
constexpr size_t npos(-1)
std::string Substitute(std::string pattern, std::initializer_list< std::pair< std::string_view, std::string_view > > substitutions)
const ServiceConfig & GetServiceConfig()
Returns the instance of the ServiceConfig.
std::string ToUTF8(const std::wstring &wstr)