focus_mode: Add YouTube Music support to Google APIs
This adds YouTube Music support to Google APIs. ChromeOS focus mode integrates with YouTube Music API during focus time for the following functionalities: - Get playlists. - Prepare the playback queue. - Play the next in the queue. Bug: b/331643640 Test: N/A Change-Id: Ie796dd61c07e90c2ebae23bcc744a2a7f527147b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5527963 Commit-Queue: Yongshun Liu <yongshun@chromium.org> Reviewed-by: Alex Ilin <alexilin@chromium.org> Reviewed-by: Sean Kau <skau@chromium.org> Reviewed-by: Richard Chui <richui@chromium.org> Cr-Commit-Position: refs/heads/main@{#1304029}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
5ccb6e05a4
commit
18acfd6e54
@ -4024,6 +4024,7 @@ static_library("ui") {
|
||||
"//google_apis/common",
|
||||
"//google_apis/drive",
|
||||
"//google_apis/tasks",
|
||||
"//google_apis/youtube_music",
|
||||
"//media/capture:capture_lib",
|
||||
"//mojo/public/js:resources_grit",
|
||||
"//remoting/host/chromeos:features",
|
||||
|
24
google_apis/youtube_music/BUILD.gn
Normal file
24
google_apis/youtube_music/BUILD.gn
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright 2024 The Chromium Authors
|
||||
# Use of this source code is governed by a BSD - style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
assert(is_chromeos)
|
||||
|
||||
static_library("youtube_music") {
|
||||
sources = [
|
||||
"youtube_music_api_request_types.cc",
|
||||
"youtube_music_api_request_types.h",
|
||||
"youtube_music_api_requests.cc",
|
||||
"youtube_music_api_requests.h",
|
||||
"youtube_music_api_response_types.cc",
|
||||
"youtube_music_api_response_types.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//google_apis:google_apis",
|
||||
"//google_apis/common:common",
|
||||
"//net",
|
||||
"//url",
|
||||
]
|
||||
}
|
1
google_apis/youtube_music/OWNERS
Normal file
1
google_apis/youtube_music/OWNERS
Normal file
@ -0,0 +1 @@
|
||||
file://ash/system/focus_mode/youtube_music/OWNERS
|
86
google_apis/youtube_music/youtube_music_api_request_types.cc
Normal file
86
google_apis/youtube_music/youtube_music_api_request_types.cc
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "google_apis/youtube_music/youtube_music_api_request_types.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/json/json_writer.h"
|
||||
#include "base/notreached.h"
|
||||
|
||||
namespace google_apis::youtube_music {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kPlayableIdKey[] = "playableId";
|
||||
constexpr char kExplicitFilterKey[] = "explicitFilter";
|
||||
constexpr char kShuffleModeKey[] = "shuffleMode";
|
||||
const char kExplicitFilterNone[] = "none";
|
||||
const char kExplicitFilterBestEffort[] = "besteffort";
|
||||
const char kShuffleModeUnspecified[] = "SHUFFLE_MODE_UNSPECIFIED";
|
||||
const char kShuffleModeOff[] = "OFF";
|
||||
const char kShuffleModeOn[] = "ON";
|
||||
|
||||
const char* GetExplicitFilterValue(
|
||||
const PlaybackQueuePrepareRequestPayload::ExplicitFilter& explicit_filter) {
|
||||
switch (explicit_filter) {
|
||||
case PlaybackQueuePrepareRequestPayload::ExplicitFilter::kNone:
|
||||
return kExplicitFilterNone;
|
||||
case PlaybackQueuePrepareRequestPayload::ExplicitFilter::kBestEffort:
|
||||
return kExplicitFilterBestEffort;
|
||||
}
|
||||
NOTREACHED_NORETURN();
|
||||
}
|
||||
|
||||
const char* GetShuffleModeValue(
|
||||
const PlaybackQueuePrepareRequestPayload::ShuffleMode& shuffle_mode) {
|
||||
switch (shuffle_mode) {
|
||||
case PlaybackQueuePrepareRequestPayload::ShuffleMode::kUnspecified:
|
||||
return kShuffleModeUnspecified;
|
||||
case PlaybackQueuePrepareRequestPayload::ShuffleMode::kOff:
|
||||
return kShuffleModeOff;
|
||||
case PlaybackQueuePrepareRequestPayload::ShuffleMode::kOn:
|
||||
return kShuffleModeOn;
|
||||
}
|
||||
NOTREACHED_NORETURN();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PlaybackQueuePrepareRequestPayload::PlaybackQueuePrepareRequestPayload(
|
||||
std::string playable_id,
|
||||
std::optional<ExplicitFilter> explicit_filter,
|
||||
std::optional<ShuffleMode> shuffle_mode)
|
||||
: playable_id(playable_id),
|
||||
explicit_filter(explicit_filter),
|
||||
shuffle_mode(shuffle_mode) {}
|
||||
PlaybackQueuePrepareRequestPayload::PlaybackQueuePrepareRequestPayload(
|
||||
const PlaybackQueuePrepareRequestPayload&) = default;
|
||||
PlaybackQueuePrepareRequestPayload&
|
||||
PlaybackQueuePrepareRequestPayload::operator=(
|
||||
const PlaybackQueuePrepareRequestPayload&) = default;
|
||||
PlaybackQueuePrepareRequestPayload::~PlaybackQueuePrepareRequestPayload() =
|
||||
default;
|
||||
|
||||
std::string PlaybackQueuePrepareRequestPayload::ToJson() const {
|
||||
base::Value::Dict root;
|
||||
|
||||
CHECK(!playable_id.empty());
|
||||
root.Set(kPlayableIdKey, playable_id);
|
||||
if (explicit_filter.has_value()) {
|
||||
root.Set(kExplicitFilterKey,
|
||||
GetExplicitFilterValue(explicit_filter.value()));
|
||||
}
|
||||
if (shuffle_mode.has_value()) {
|
||||
root.Set(kShuffleModeKey, GetShuffleModeValue(shuffle_mode.value()));
|
||||
}
|
||||
|
||||
const std::optional<std::string> json = base::WriteJson(root);
|
||||
CHECK(json);
|
||||
|
||||
return json.value();
|
||||
}
|
||||
|
||||
} // namespace google_apis::youtube_music
|
47
google_apis/youtube_music/youtube_music_api_request_types.h
Normal file
47
google_apis/youtube_music/youtube_music_api_request_types.h
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef GOOGLE_APIS_YOUTUBE_MUSIC_YOUTUBE_MUSIC_API_REQUEST_TYPES_H_
|
||||
#define GOOGLE_APIS_YOUTUBE_MUSIC_YOUTUBE_MUSIC_API_REQUEST_TYPES_H_
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace google_apis::youtube_music {
|
||||
|
||||
// Payload used as a request body for the API request that prepares the playback
|
||||
// queue.
|
||||
struct PlaybackQueuePrepareRequestPayload {
|
||||
enum class ExplicitFilter {
|
||||
kNone,
|
||||
kBestEffort,
|
||||
};
|
||||
|
||||
enum class ShuffleMode {
|
||||
kUnspecified,
|
||||
kOff,
|
||||
kOn,
|
||||
};
|
||||
|
||||
PlaybackQueuePrepareRequestPayload(
|
||||
std::string playable_id,
|
||||
std::optional<ExplicitFilter> explicit_filter,
|
||||
std::optional<ShuffleMode> shuffle_mode);
|
||||
PlaybackQueuePrepareRequestPayload(const PlaybackQueuePrepareRequestPayload&);
|
||||
PlaybackQueuePrepareRequestPayload& operator=(
|
||||
const PlaybackQueuePrepareRequestPayload&);
|
||||
~PlaybackQueuePrepareRequestPayload();
|
||||
|
||||
std::string ToJson() const;
|
||||
|
||||
std::string playable_id;
|
||||
|
||||
std::optional<ExplicitFilter> explicit_filter;
|
||||
|
||||
std::optional<ShuffleMode> shuffle_mode;
|
||||
};
|
||||
|
||||
} // namespace google_apis::youtube_music
|
||||
|
||||
#endif // GOOGLE_APIS_YOUTUBE_MUSIC_YOUTUBE_MUSIC_API_REQUEST_TYPES_H_
|
252
google_apis/youtube_music/youtube_music_api_requests.cc
Normal file
252
google_apis/youtube_music/youtube_music_api_requests.cc
Normal file
@ -0,0 +1,252 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "google_apis/youtube_music/youtube_music_api_requests.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/values.h"
|
||||
#include "google_apis/common/api_error_codes.h"
|
||||
#include "google_apis/common/request_sender.h"
|
||||
#include "google_apis/youtube_music/youtube_music_api_response_types.h"
|
||||
#include "net/base/url_util.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kContentTypeJson[] = "application/json; charset=utf-8";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace google_apis::youtube_music {
|
||||
|
||||
GetPlaylistsRequest::GetPlaylistsRequest(RequestSender* sender,
|
||||
Callback callback)
|
||||
: UrlFetchRequestBase(sender, ProgressCallback(), ProgressCallback()),
|
||||
callback_(std::move(callback)) {
|
||||
CHECK(!callback_.is_null());
|
||||
}
|
||||
|
||||
GetPlaylistsRequest::~GetPlaylistsRequest() = default;
|
||||
|
||||
GURL GetPlaylistsRequest::GetURL() const {
|
||||
// TODO(b/341324009): Move to an util file or class.
|
||||
return GURL(
|
||||
"https://youtubemediaconnect.googleapis.com/v1/musicSections/"
|
||||
"root:load?intent=focus&category=music§ionRecommendationLimit=10");
|
||||
}
|
||||
|
||||
ApiErrorCode GetPlaylistsRequest::MapReasonToError(ApiErrorCode code,
|
||||
const std::string& reason) {
|
||||
return code;
|
||||
}
|
||||
|
||||
bool GetPlaylistsRequest::IsSuccessfulErrorCode(ApiErrorCode error) {
|
||||
return error == HTTP_SUCCESS;
|
||||
}
|
||||
|
||||
void GetPlaylistsRequest::ProcessURLFetchResults(
|
||||
const network::mojom::URLResponseHead* response_head,
|
||||
base::FilePath response_file,
|
||||
std::string response_body) {
|
||||
ApiErrorCode error = GetErrorCode();
|
||||
switch (error) {
|
||||
case HTTP_SUCCESS:
|
||||
blocking_task_runner()->PostTaskAndReplyWithResult(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&GetPlaylistsRequest::Parse, std::move(response_body)),
|
||||
base::BindOnce(&GetPlaylistsRequest::OnDataParsed,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
break;
|
||||
default:
|
||||
RunCallbackOnPrematureFailure(error);
|
||||
OnProcessURLFetchResultsComplete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GetPlaylistsRequest::RunCallbackOnPrematureFailure(ApiErrorCode error) {
|
||||
std::move(callback_).Run(base::unexpected(error));
|
||||
}
|
||||
|
||||
std::unique_ptr<TopLevelMusicRecommendations> GetPlaylistsRequest::Parse(
|
||||
const std::string& json) {
|
||||
std::unique_ptr<base::Value> value = ParseJson(json);
|
||||
return value ? TopLevelMusicRecommendations::CreateFrom(*value) : nullptr;
|
||||
}
|
||||
|
||||
void GetPlaylistsRequest::OnDataParsed(
|
||||
std::unique_ptr<TopLevelMusicRecommendations> recommendations) {
|
||||
if (!recommendations) {
|
||||
std::move(callback_).Run(base::unexpected(PARSE_ERROR));
|
||||
} else {
|
||||
std::move(callback_).Run(std::move(recommendations));
|
||||
}
|
||||
OnProcessURLFetchResultsComplete();
|
||||
}
|
||||
|
||||
PlaybackQueuePrepareRequest::PlaybackQueuePrepareRequest(
|
||||
RequestSender* sender,
|
||||
const PlaybackQueuePrepareRequestPayload& payload,
|
||||
Callback callback)
|
||||
: UrlFetchRequestBase(sender, ProgressCallback(), ProgressCallback()),
|
||||
payload_(payload),
|
||||
callback_(std::move(callback)) {
|
||||
CHECK(!callback_.is_null());
|
||||
}
|
||||
|
||||
PlaybackQueuePrepareRequest::~PlaybackQueuePrepareRequest() = default;
|
||||
|
||||
GURL PlaybackQueuePrepareRequest::GetURL() const {
|
||||
// TODO(b/341324009): Move to an util file or class.
|
||||
GURL url(
|
||||
"https://youtubemediaconnect.googleapis.com/v1/queues/"
|
||||
"default:preparePlayback");
|
||||
return url;
|
||||
}
|
||||
|
||||
ApiErrorCode PlaybackQueuePrepareRequest::MapReasonToError(
|
||||
ApiErrorCode code,
|
||||
const std::string& reason) {
|
||||
return code;
|
||||
}
|
||||
|
||||
bool PlaybackQueuePrepareRequest::IsSuccessfulErrorCode(ApiErrorCode error) {
|
||||
return error == HTTP_SUCCESS;
|
||||
}
|
||||
|
||||
HttpRequestMethod PlaybackQueuePrepareRequest::GetRequestType() const {
|
||||
return HttpRequestMethod::kPost;
|
||||
}
|
||||
|
||||
bool PlaybackQueuePrepareRequest::GetContentData(
|
||||
std::string* upload_content_type,
|
||||
std::string* upload_content) {
|
||||
*upload_content_type = kContentTypeJson;
|
||||
*upload_content = payload_.ToJson();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlaybackQueuePrepareRequest::ProcessURLFetchResults(
|
||||
const network::mojom::URLResponseHead* response_head,
|
||||
base::FilePath response_file,
|
||||
std::string response_body) {
|
||||
ApiErrorCode error = GetErrorCode();
|
||||
switch (error) {
|
||||
case HTTP_SUCCESS:
|
||||
blocking_task_runner()->PostTaskAndReplyWithResult(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&PlaybackQueuePrepareRequest::Parse,
|
||||
std::move(response_body)),
|
||||
base::BindOnce(&PlaybackQueuePrepareRequest::OnDataParsed,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
break;
|
||||
default:
|
||||
RunCallbackOnPrematureFailure(error);
|
||||
OnProcessURLFetchResultsComplete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackQueuePrepareRequest::RunCallbackOnPrematureFailure(
|
||||
ApiErrorCode error) {
|
||||
std::move(callback_).Run(base::unexpected(error));
|
||||
}
|
||||
|
||||
std::unique_ptr<Queue> PlaybackQueuePrepareRequest::Parse(
|
||||
const std::string& json) {
|
||||
std::unique_ptr<base::Value> value = ParseJson(json);
|
||||
return value ? Queue::CreateFrom(*value) : nullptr;
|
||||
}
|
||||
|
||||
void PlaybackQueuePrepareRequest::OnDataParsed(
|
||||
std::unique_ptr<Queue> playback_queue) {
|
||||
if (!playback_queue) {
|
||||
std::move(callback_).Run(base::unexpected(PARSE_ERROR));
|
||||
} else {
|
||||
std::move(callback_).Run(std::move(playback_queue));
|
||||
}
|
||||
OnProcessURLFetchResultsComplete();
|
||||
}
|
||||
|
||||
PlaybackQueueNextRequest::PlaybackQueueNextRequest(
|
||||
RequestSender* sender,
|
||||
Callback callback,
|
||||
const std::string& playback_queue_name)
|
||||
: UrlFetchRequestBase(sender, ProgressCallback(), ProgressCallback()),
|
||||
callback_(std::move(callback)) {
|
||||
CHECK(!callback_.is_null());
|
||||
playback_queue_name_ = playback_queue_name;
|
||||
}
|
||||
|
||||
PlaybackQueueNextRequest::~PlaybackQueueNextRequest() = default;
|
||||
|
||||
GURL PlaybackQueueNextRequest::GetURL() const {
|
||||
// TODO(b/341324009): Move to an util file or class.
|
||||
return GURL(base::StringPrintf(
|
||||
"https://youtubemediaconnect.googleapis.com/v1/%s:next",
|
||||
playback_queue_name_.c_str()));
|
||||
}
|
||||
|
||||
ApiErrorCode PlaybackQueueNextRequest::MapReasonToError(
|
||||
ApiErrorCode code,
|
||||
const std::string& reason) {
|
||||
return code;
|
||||
}
|
||||
|
||||
bool PlaybackQueueNextRequest::IsSuccessfulErrorCode(ApiErrorCode error) {
|
||||
return error == HTTP_SUCCESS;
|
||||
}
|
||||
|
||||
HttpRequestMethod PlaybackQueueNextRequest::GetRequestType() const {
|
||||
return HttpRequestMethod::kPost;
|
||||
}
|
||||
|
||||
void PlaybackQueueNextRequest::ProcessURLFetchResults(
|
||||
const network::mojom::URLResponseHead* response_head,
|
||||
base::FilePath response_file,
|
||||
std::string response_body) {
|
||||
ApiErrorCode error = GetErrorCode();
|
||||
switch (error) {
|
||||
case HTTP_SUCCESS:
|
||||
blocking_task_runner()->PostTaskAndReplyWithResult(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&PlaybackQueueNextRequest::Parse,
|
||||
std::move(response_body)),
|
||||
base::BindOnce(&PlaybackQueueNextRequest::OnDataParsed,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
break;
|
||||
default:
|
||||
RunCallbackOnPrematureFailure(error);
|
||||
OnProcessURLFetchResultsComplete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PlaybackQueueNextRequest::RunCallbackOnPrematureFailure(
|
||||
ApiErrorCode error) {
|
||||
std::move(callback_).Run(base::unexpected(error));
|
||||
}
|
||||
|
||||
std::unique_ptr<QueueContainer> PlaybackQueueNextRequest::Parse(
|
||||
const std::string& json) {
|
||||
std::unique_ptr<base::Value> value = ParseJson(json);
|
||||
return value ? QueueContainer::CreateFrom(*value) : nullptr;
|
||||
}
|
||||
|
||||
void PlaybackQueueNextRequest::OnDataParsed(
|
||||
std::unique_ptr<QueueContainer> playback_queue) {
|
||||
if (!playback_queue) {
|
||||
std::move(callback_).Run(base::unexpected(PARSE_ERROR));
|
||||
} else {
|
||||
std::move(callback_).Run(std::move(playback_queue));
|
||||
}
|
||||
OnProcessURLFetchResultsComplete();
|
||||
}
|
||||
|
||||
} // namespace google_apis::youtube_music
|
156
google_apis/youtube_music/youtube_music_api_requests.h
Normal file
156
google_apis/youtube_music/youtube_music_api_requests.h
Normal file
@ -0,0 +1,156 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef GOOGLE_APIS_YOUTUBE_MUSIC_YOUTUBE_MUSIC_API_REQUESTS_H_
|
||||
#define GOOGLE_APIS_YOUTUBE_MUSIC_YOUTUBE_MUSIC_API_REQUESTS_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/types/expected.h"
|
||||
#include "google_apis/common/base_requests.h"
|
||||
#include "google_apis/youtube_music/youtube_music_api_request_types.h"
|
||||
#include "google_apis/youtube_music/youtube_music_api_response_types.h"
|
||||
|
||||
namespace google_apis {
|
||||
|
||||
enum ApiErrorCode;
|
||||
class RequestSender;
|
||||
|
||||
namespace youtube_music {
|
||||
|
||||
// Request that gets music recommendations from the API server. For API usage,
|
||||
// please check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/musicSections/load
|
||||
class GetPlaylistsRequest : public UrlFetchRequestBase {
|
||||
public:
|
||||
using Callback = base::OnceCallback<void(
|
||||
base::expected<std::unique_ptr<TopLevelMusicRecommendations>,
|
||||
ApiErrorCode>)>;
|
||||
|
||||
GetPlaylistsRequest(RequestSender* sender, Callback callback);
|
||||
GetPlaylistsRequest(const GetPlaylistsRequest&) = delete;
|
||||
GetPlaylistsRequest& operator=(const GetPlaylistsRequest&) = delete;
|
||||
~GetPlaylistsRequest() override;
|
||||
|
||||
protected:
|
||||
// UrlFetchRequestBase:
|
||||
GURL GetURL() const override;
|
||||
ApiErrorCode MapReasonToError(ApiErrorCode code,
|
||||
const std::string& reason) override;
|
||||
bool IsSuccessfulErrorCode(ApiErrorCode error) override;
|
||||
void ProcessURLFetchResults(
|
||||
const network::mojom::URLResponseHead* response_head,
|
||||
const base::FilePath response_file,
|
||||
std::string response_body) override;
|
||||
void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
|
||||
|
||||
private:
|
||||
static std::unique_ptr<TopLevelMusicRecommendations> Parse(
|
||||
const std::string& json);
|
||||
|
||||
void OnDataParsed(std::unique_ptr<TopLevelMusicRecommendations> sections);
|
||||
|
||||
Callback callback_;
|
||||
|
||||
base::WeakPtrFactory<GetPlaylistsRequest> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
// Request that prepares the playback queue for the API server. For API usage,
|
||||
// please check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/queues/preparePlayback
|
||||
class PlaybackQueuePrepareRequest : public UrlFetchRequestBase {
|
||||
public:
|
||||
using Callback = base::OnceCallback<void(
|
||||
base::expected<std::unique_ptr<Queue>, ApiErrorCode>)>;
|
||||
|
||||
PlaybackQueuePrepareRequest(RequestSender* sender,
|
||||
const PlaybackQueuePrepareRequestPayload& payload,
|
||||
Callback callback);
|
||||
PlaybackQueuePrepareRequest(const PlaybackQueuePrepareRequest&) = delete;
|
||||
PlaybackQueuePrepareRequest& operator=(const PlaybackQueuePrepareRequest&) =
|
||||
delete;
|
||||
~PlaybackQueuePrepareRequest() override;
|
||||
|
||||
protected:
|
||||
// UrlFetchRequestBase:
|
||||
GURL GetURL() const override;
|
||||
ApiErrorCode MapReasonToError(ApiErrorCode code,
|
||||
const std::string& reason) override;
|
||||
bool IsSuccessfulErrorCode(ApiErrorCode error) override;
|
||||
HttpRequestMethod GetRequestType() const override;
|
||||
bool GetContentData(std::string* upload_content_type,
|
||||
std::string* upload_content) override;
|
||||
void ProcessURLFetchResults(
|
||||
const network::mojom::URLResponseHead* response_head,
|
||||
const base::FilePath response_file,
|
||||
std::string response_body) override;
|
||||
void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
|
||||
|
||||
private:
|
||||
static std::unique_ptr<Queue> Parse(const std::string& json);
|
||||
|
||||
void OnDataParsed(std::unique_ptr<Queue> sections);
|
||||
|
||||
const PlaybackQueuePrepareRequestPayload payload_;
|
||||
|
||||
Callback callback_;
|
||||
|
||||
base::WeakPtrFactory<PlaybackQueuePrepareRequest> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
// Request to play the next in the playback queue for the API server. For API
|
||||
// usage, please check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/queues/next
|
||||
class PlaybackQueueNextRequest : public UrlFetchRequestBase {
|
||||
public:
|
||||
using Callback = base::OnceCallback<void(
|
||||
base::expected<std::unique_ptr<QueueContainer>, ApiErrorCode>)>;
|
||||
|
||||
PlaybackQueueNextRequest(RequestSender* sender,
|
||||
Callback callback,
|
||||
const std::string& playlist_name);
|
||||
PlaybackQueueNextRequest(const PlaybackQueueNextRequest&) = delete;
|
||||
PlaybackQueueNextRequest& operator=(const PlaybackQueueNextRequest&) = delete;
|
||||
~PlaybackQueueNextRequest() override;
|
||||
|
||||
const std::string& playback_queue_name() const {
|
||||
return playback_queue_name_;
|
||||
}
|
||||
void set_playback_queue_name(const std::string& playback_queue_name) {
|
||||
playback_queue_name_ = playback_queue_name;
|
||||
}
|
||||
|
||||
protected:
|
||||
// UrlFetchRequestBase:
|
||||
GURL GetURL() const override;
|
||||
ApiErrorCode MapReasonToError(ApiErrorCode code,
|
||||
const std::string& reason) override;
|
||||
bool IsSuccessfulErrorCode(ApiErrorCode error) override;
|
||||
HttpRequestMethod GetRequestType() const override;
|
||||
void ProcessURLFetchResults(
|
||||
const network::mojom::URLResponseHead* response_head,
|
||||
const base::FilePath response_file,
|
||||
std::string response_body) override;
|
||||
void RunCallbackOnPrematureFailure(ApiErrorCode code) override;
|
||||
|
||||
private:
|
||||
static std::unique_ptr<QueueContainer> Parse(const std::string& json);
|
||||
|
||||
void OnDataParsed(std::unique_ptr<QueueContainer> sections);
|
||||
|
||||
// Playlist queue name.
|
||||
std::string playback_queue_name_;
|
||||
|
||||
Callback callback_;
|
||||
|
||||
base::WeakPtrFactory<PlaybackQueueNextRequest> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace youtube_music
|
||||
} // namespace google_apis
|
||||
|
||||
#endif // GOOGLE_APIS_YOUTUBE_MUSIC_YOUTUBE_MUSIC_API_REQUESTS_H_
|
415
google_apis/youtube_music/youtube_music_api_response_types.cc
Normal file
415
google_apis/youtube_music/youtube_music_api_response_types.cc
Normal file
@ -0,0 +1,415 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "google_apis/youtube_music/youtube_music_api_response_types.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/json/json_value_converter.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
|
||||
namespace google_apis::youtube_music {
|
||||
namespace {
|
||||
|
||||
using ::base::JSONValueConverter;
|
||||
|
||||
constexpr char kApiResponseNameKey[] = "name";
|
||||
constexpr char kApiResponseTitleKey[] = "title";
|
||||
constexpr char kApiResponseMusicRecommendationsKey[] = "musicRecommendations";
|
||||
constexpr char kApiResponseMusicSectionKey[] = "musicSection";
|
||||
constexpr char kApiResponseWidthKey[] = "widthPixels";
|
||||
constexpr char kApiResponseHeightKey[] = "heightPixels";
|
||||
constexpr char kApiResponseUriKey[] = "uri";
|
||||
constexpr char kApiResponseDescriptionKey[] = "description";
|
||||
constexpr char kApiResponseItemCountKey[] = "itemCount";
|
||||
constexpr char kApiResponseImagesKey[] = "images";
|
||||
constexpr char kApiResponseOwnerKey[] = "owner";
|
||||
constexpr char kApiResponsePlaylistKey[] = "playlist";
|
||||
constexpr char kApiResponseContextKey[] = "context";
|
||||
constexpr char kApiResponseSizeKey[] = "size";
|
||||
constexpr char kApiResponseQueueKey[] = "queue";
|
||||
constexpr char kApiResponseDurationKey[] = "duration";
|
||||
constexpr char kApiResponseExplicitTypeKey[] = "explicitType";
|
||||
constexpr char kApiResponseTrackKey[] = "track";
|
||||
constexpr char kApiResponseStreamsKey[] = "streams";
|
||||
constexpr char kApiResponseItemKey[] = "item";
|
||||
constexpr char kApiResponseManifestKey[] = "manifest";
|
||||
|
||||
bool ConvertToGurl(std::string_view input, GURL* output) {
|
||||
*output = GURL(input);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Image::Image() = default;
|
||||
Image::~Image() = default;
|
||||
|
||||
// static
|
||||
void Image::RegisterJSONConverter(JSONValueConverter<Image>* converter) {
|
||||
converter->RegisterIntField(kApiResponseWidthKey, &Image::width_);
|
||||
converter->RegisterIntField(kApiResponseHeightKey, &Image::height_);
|
||||
converter->RegisterCustomField<GURL>(kApiResponseUriKey, &Image::url_,
|
||||
&ConvertToGurl);
|
||||
}
|
||||
|
||||
std::string Image::ToString() const {
|
||||
return base::StringPrintf("Image(width=%d, height=%d, url=\"%s\")", width_,
|
||||
height_, url_.spec().c_str());
|
||||
}
|
||||
|
||||
Owner::Owner() = default;
|
||||
Owner::~Owner() = default;
|
||||
|
||||
// static
|
||||
void Owner::RegisterJSONConverter(JSONValueConverter<Owner>* converter) {
|
||||
converter->RegisterStringField(kApiResponseTitleKey, &Owner::title_);
|
||||
}
|
||||
|
||||
std::string Owner::ToString() const {
|
||||
return base::StringPrintf("Owner(title=\"%s\"", title_.c_str());
|
||||
}
|
||||
|
||||
Playlist::Playlist() = default;
|
||||
Playlist::~Playlist() = default;
|
||||
|
||||
// static
|
||||
void Playlist::RegisterJSONConverter(JSONValueConverter<Playlist>* converter) {
|
||||
converter->RegisterStringField(kApiResponseNameKey, &Playlist::name_);
|
||||
converter->RegisterStringField(kApiResponseTitleKey, &Playlist::title_);
|
||||
converter->RegisterStringField(kApiResponseDescriptionKey,
|
||||
&Playlist::description_);
|
||||
converter->RegisterIntField(kApiResponseItemCountKey, &Playlist::item_count_);
|
||||
converter->RegisterRepeatedMessage<Image>(kApiResponseImagesKey,
|
||||
&Playlist::images_);
|
||||
converter->RegisterNestedField(kApiResponseOwnerKey, &Playlist::owner_);
|
||||
}
|
||||
|
||||
std::string Playlist::ToString() const {
|
||||
std::string s;
|
||||
for (size_t i = 0; i < images_.size(); i++) {
|
||||
s += (i ? ", " : "") + images_[i]->ToString();
|
||||
}
|
||||
return base::StringPrintf(
|
||||
"Playlist(name=\"%s\", title=\"%s\", description=\"%s\", item_count=%d, "
|
||||
"images=[%s], owner=%s)",
|
||||
name_.c_str(), title_.c_str(), description_.c_str(), item_count_,
|
||||
s.c_str(), owner_.ToString().c_str());
|
||||
}
|
||||
|
||||
MusicRecommendation::MusicRecommendation() = default;
|
||||
MusicRecommendation::~MusicRecommendation() = default;
|
||||
|
||||
// static
|
||||
void MusicRecommendation::RegisterJSONConverter(
|
||||
JSONValueConverter<MusicRecommendation>* converter) {
|
||||
converter->RegisterNestedField(kApiResponsePlaylistKey,
|
||||
&MusicRecommendation::playlist_);
|
||||
}
|
||||
|
||||
std::string MusicRecommendation::ToString() const {
|
||||
return base::StringPrintf("MusicRecommendation(playlist=%s)",
|
||||
playlist_.ToString().c_str());
|
||||
}
|
||||
|
||||
MusicSection::MusicSection() = default;
|
||||
MusicSection::~MusicSection() = default;
|
||||
|
||||
// static
|
||||
void MusicSection::RegisterJSONConverter(
|
||||
JSONValueConverter<MusicSection>* converter) {
|
||||
converter->RegisterStringField(kApiResponseNameKey, &MusicSection::name_);
|
||||
converter->RegisterStringField(kApiResponseTitleKey, &MusicSection::title_);
|
||||
converter->RegisterRepeatedMessage<MusicRecommendation>(
|
||||
kApiResponseMusicRecommendationsKey,
|
||||
&MusicSection::music_recommendations_);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<MusicSection> MusicSection::CreateFrom(
|
||||
const base::Value& value) {
|
||||
auto music_section = std::make_unique<MusicSection>();
|
||||
JSONValueConverter<MusicSection> converter;
|
||||
if (!converter.Convert(value, music_section.get())) {
|
||||
DVLOG(1) << "Unable to construct `MusicSection` from parsed json.";
|
||||
return nullptr;
|
||||
}
|
||||
return music_section;
|
||||
}
|
||||
|
||||
std::string MusicSection::ToString() const {
|
||||
std::string s;
|
||||
for (size_t i = 0; i < music_recommendations_.size(); i++) {
|
||||
s += (i ? ", " : "") + music_recommendations_[i]->ToString();
|
||||
}
|
||||
return base::StringPrintf(
|
||||
"MusicSection(name=\"%s\", title=\"%s\", "
|
||||
"music_recommendations=[%s])",
|
||||
name_.c_str(), title_.c_str(), s.c_str());
|
||||
}
|
||||
|
||||
TopLevelMusicRecommendation::TopLevelMusicRecommendation() = default;
|
||||
TopLevelMusicRecommendation::~TopLevelMusicRecommendation() = default;
|
||||
|
||||
// static
|
||||
void TopLevelMusicRecommendation::RegisterJSONConverter(
|
||||
JSONValueConverter<TopLevelMusicRecommendation>* converter) {
|
||||
converter->RegisterNestedField(kApiResponseMusicSectionKey,
|
||||
&TopLevelMusicRecommendation::music_section_);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<TopLevelMusicRecommendation>
|
||||
TopLevelMusicRecommendation::CreateFrom(const base::Value& value) {
|
||||
auto top_level_music_recommendation =
|
||||
std::make_unique<TopLevelMusicRecommendation>();
|
||||
JSONValueConverter<TopLevelMusicRecommendation> converter;
|
||||
if (!converter.Convert(value, top_level_music_recommendation.get())) {
|
||||
DVLOG(1) << "Unable to construct `TopLevelMusicRecommendation` from parsed "
|
||||
"json.";
|
||||
return nullptr;
|
||||
}
|
||||
return top_level_music_recommendation;
|
||||
}
|
||||
|
||||
std::string TopLevelMusicRecommendation::ToString() const {
|
||||
return base::StringPrintf("TopLevelMusicRecommendation(music_section=%s)",
|
||||
music_section_.ToString().c_str());
|
||||
}
|
||||
|
||||
TopLevelMusicRecommendations::TopLevelMusicRecommendations() = default;
|
||||
TopLevelMusicRecommendations::~TopLevelMusicRecommendations() = default;
|
||||
|
||||
// static
|
||||
void TopLevelMusicRecommendations::RegisterJSONConverter(
|
||||
JSONValueConverter<TopLevelMusicRecommendations>* converter) {
|
||||
converter->RegisterRepeatedMessage<TopLevelMusicRecommendation>(
|
||||
kApiResponseMusicRecommendationsKey,
|
||||
&TopLevelMusicRecommendations::top_level_music_recommendations_);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<TopLevelMusicRecommendations>
|
||||
TopLevelMusicRecommendations::CreateFrom(const base::Value& value) {
|
||||
auto top_level_music_recommendations =
|
||||
std::make_unique<TopLevelMusicRecommendations>();
|
||||
JSONValueConverter<TopLevelMusicRecommendations> converter;
|
||||
if (!converter.Convert(value, top_level_music_recommendations.get())) {
|
||||
DVLOG(1) << "Unable to construct `TopLevelMusicRecommendations` from "
|
||||
"parsed json.";
|
||||
return nullptr;
|
||||
}
|
||||
return top_level_music_recommendations;
|
||||
}
|
||||
|
||||
std::string TopLevelMusicRecommendations::ToString() const {
|
||||
std::string s;
|
||||
for (size_t i = 0; i < top_level_music_recommendations_.size(); i++) {
|
||||
s += (i ? ", " : "") + top_level_music_recommendations_[i]->ToString();
|
||||
}
|
||||
return base::StringPrintf(
|
||||
"TopLevelMusicRecommendations(top_level_music_recommendations=[%s])",
|
||||
s.c_str());
|
||||
}
|
||||
|
||||
Track::Track() = default;
|
||||
Track::~Track() = default;
|
||||
|
||||
// static
|
||||
void Track::RegisterJSONConverter(JSONValueConverter<Track>* converter) {
|
||||
converter->RegisterStringField(kApiResponseNameKey, &Track::name_);
|
||||
converter->RegisterStringField(kApiResponseTitleKey, &Track::title_);
|
||||
converter->RegisterStringField(kApiResponseDurationKey, &Track::duration_);
|
||||
converter->RegisterStringField(kApiResponseExplicitTypeKey,
|
||||
&Track::explicit_type_);
|
||||
converter->RegisterRepeatedMessage<Image>(kApiResponseImagesKey,
|
||||
&Track::images_);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<Track> Track::CreateFrom(const base::Value& value) {
|
||||
auto track = std::make_unique<Track>();
|
||||
JSONValueConverter<Track> converter;
|
||||
if (!converter.Convert(value, track.get())) {
|
||||
DVLOG(1) << "Unable to construct `Track` from parsed json.";
|
||||
return nullptr;
|
||||
}
|
||||
return track;
|
||||
}
|
||||
|
||||
std::string Track::ToString() const {
|
||||
std::string s;
|
||||
for (size_t i = 0; i < images_.size(); i++) {
|
||||
s += (i ? ", " : "") + images_[i]->ToString();
|
||||
}
|
||||
return base::StringPrintf(
|
||||
"Track(name=\"%s\", title=\"%s\", duration=\"%s\", explicit_type_=%s, "
|
||||
"images=[%s])",
|
||||
name_.c_str(), title_.c_str(), duration_.c_str(), explicit_type_.c_str(),
|
||||
s.c_str());
|
||||
}
|
||||
|
||||
QueueItem::QueueItem() = default;
|
||||
QueueItem::~QueueItem() = default;
|
||||
|
||||
// static
|
||||
void QueueItem::RegisterJSONConverter(
|
||||
JSONValueConverter<QueueItem>* converter) {
|
||||
converter->RegisterNestedField(kApiResponseTrackKey, &QueueItem::track_);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<QueueItem> QueueItem::CreateFrom(const base::Value& value) {
|
||||
auto queue_item = std::make_unique<QueueItem>();
|
||||
JSONValueConverter<QueueItem> converter;
|
||||
if (!converter.Convert(value, queue_item.get())) {
|
||||
DVLOG(1) << "Unable to construct `QueueItem` from parsed json.";
|
||||
return nullptr;
|
||||
}
|
||||
return queue_item;
|
||||
}
|
||||
|
||||
std::string QueueItem::ToString() const {
|
||||
return base::StringPrintf("QueueItem(track=%s)", track_.ToString().c_str());
|
||||
}
|
||||
|
||||
Stream::Stream() = default;
|
||||
Stream::~Stream() = default;
|
||||
|
||||
// static
|
||||
void Stream::RegisterJSONConverter(JSONValueConverter<Stream>* converter) {
|
||||
converter->RegisterCustomField<GURL>(kApiResponseUriKey, &Stream::url_,
|
||||
&ConvertToGurl);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<Stream> Stream::CreateFrom(const base::Value& value) {
|
||||
auto stream = std::make_unique<Stream>();
|
||||
JSONValueConverter<Stream> converter;
|
||||
if (!converter.Convert(value, stream.get())) {
|
||||
DVLOG(1) << "Unable to construct `Stream` from parsed json.";
|
||||
return nullptr;
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::string Stream::ToString() const {
|
||||
return base::StringPrintf("Stream(url=\"%s\")", url_.spec().c_str());
|
||||
}
|
||||
|
||||
PlaybackManifest::PlaybackManifest() = default;
|
||||
PlaybackManifest::~PlaybackManifest() = default;
|
||||
|
||||
// static
|
||||
void PlaybackManifest::RegisterJSONConverter(
|
||||
JSONValueConverter<PlaybackManifest>* converter) {
|
||||
converter->RegisterRepeatedMessage<Stream>(kApiResponseStreamsKey,
|
||||
&PlaybackManifest::streams_);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<PlaybackManifest> PlaybackManifest::CreateFrom(
|
||||
const base::Value& value) {
|
||||
auto playback_manifest = std::make_unique<PlaybackManifest>();
|
||||
JSONValueConverter<PlaybackManifest> converter;
|
||||
if (!converter.Convert(value, playback_manifest.get())) {
|
||||
DVLOG(1) << "Unable to construct `PlaybackManifest` from parsed json.";
|
||||
return nullptr;
|
||||
}
|
||||
return playback_manifest;
|
||||
}
|
||||
|
||||
std::string PlaybackManifest::ToString() const {
|
||||
std::string s;
|
||||
for (size_t i = 0; i < streams_.size(); i++) {
|
||||
s += (i ? ", " : "") + streams_[i]->ToString();
|
||||
}
|
||||
return base::StringPrintf("PlaybackManifest(streams=[%s])", s.c_str());
|
||||
}
|
||||
|
||||
PlaybackContext::PlaybackContext() = default;
|
||||
PlaybackContext::~PlaybackContext() = default;
|
||||
|
||||
// static
|
||||
void PlaybackContext::RegisterJSONConverter(
|
||||
JSONValueConverter<PlaybackContext>* converter) {
|
||||
converter->RegisterNestedField(kApiResponseItemKey,
|
||||
&PlaybackContext::queue_item_);
|
||||
converter->RegisterNestedField(kApiResponseManifestKey,
|
||||
&PlaybackContext::playback_manifest_);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<PlaybackContext> PlaybackContext::CreateFrom(
|
||||
const base::Value& value) {
|
||||
auto playback_context = std::make_unique<PlaybackContext>();
|
||||
JSONValueConverter<PlaybackContext> converter;
|
||||
if (!converter.Convert(value, playback_context.get())) {
|
||||
DVLOG(1) << "Unable to construct `PlaybackManifest` from parsed json.";
|
||||
return nullptr;
|
||||
}
|
||||
return playback_context;
|
||||
}
|
||||
|
||||
std::string PlaybackContext::ToString() const {
|
||||
return base::StringPrintf(
|
||||
"PlaybackContext(queue_item=%s, playback_manifest=%s)",
|
||||
queue_item_.ToString().c_str(), playback_manifest_.ToString().c_str());
|
||||
}
|
||||
|
||||
Queue::Queue() = default;
|
||||
Queue::~Queue() = default;
|
||||
|
||||
// static
|
||||
void Queue::RegisterJSONConverter(JSONValueConverter<Queue>* converter) {
|
||||
converter->RegisterStringField(kApiResponseNameKey, &Queue::name_);
|
||||
converter->RegisterIntField(kApiResponseSizeKey, &Queue::size_);
|
||||
converter->RegisterNestedField(kApiResponseContextKey,
|
||||
&Queue::playback_context_);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<Queue> Queue::CreateFrom(const base::Value& value) {
|
||||
auto queue = std::make_unique<Queue>();
|
||||
JSONValueConverter<Queue> converter;
|
||||
if (!converter.Convert(value, queue.get())) {
|
||||
DVLOG(1) << "Unable to construct `Queue` from parsed json.";
|
||||
return nullptr;
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
std::string Queue::ToString() const {
|
||||
return base::StringPrintf("Queue(name=\"%s\", size=%d, playback_context=%s)",
|
||||
name_.c_str(), size_,
|
||||
playback_context_.ToString().c_str());
|
||||
}
|
||||
|
||||
QueueContainer::QueueContainer() = default;
|
||||
QueueContainer::~QueueContainer() = default;
|
||||
|
||||
// static
|
||||
void QueueContainer::RegisterJSONConverter(
|
||||
JSONValueConverter<QueueContainer>* converter) {
|
||||
converter->RegisterNestedField(kApiResponseQueueKey, &QueueContainer::queue_);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<QueueContainer> QueueContainer::CreateFrom(
|
||||
const base::Value& value) {
|
||||
auto queue_container = std::make_unique<QueueContainer>();
|
||||
JSONValueConverter<QueueContainer> converter;
|
||||
if (!converter.Convert(value, queue_container.get())) {
|
||||
DVLOG(1) << "Unable to construct `QueueContainer` from parsed json.";
|
||||
return nullptr;
|
||||
}
|
||||
return queue_container;
|
||||
}
|
||||
|
||||
std::string QueueContainer::ToString() const {
|
||||
return base::StringPrintf("QueueContainer(queue=%s)",
|
||||
queue_.ToString().c_str());
|
||||
}
|
||||
|
||||
} // namespace google_apis::youtube_music
|
382
google_apis/youtube_music/youtube_music_api_response_types.h
Normal file
382
google_apis/youtube_music/youtube_music_api_response_types.h
Normal file
@ -0,0 +1,382 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef GOOGLE_APIS_YOUTUBE_MUSIC_YOUTUBE_MUSIC_API_RESPONSE_TYPES_H_
|
||||
#define GOOGLE_APIS_YOUTUBE_MUSIC_YOUTUBE_MUSIC_API_RESPONSE_TYPES_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace base {
|
||||
template <class StructType>
|
||||
class JSONValueConverter;
|
||||
class Value;
|
||||
} // namespace base
|
||||
|
||||
namespace google_apis::youtube_music {
|
||||
|
||||
// Image object from the API response. For object details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/Image
|
||||
class Image {
|
||||
public:
|
||||
Image();
|
||||
Image(const Image&) = delete;
|
||||
Image& operator=(const Image&) = delete;
|
||||
~Image();
|
||||
|
||||
static void RegisterJSONConverter(base::JSONValueConverter<Image>* converter);
|
||||
|
||||
int width() const { return width_; }
|
||||
int height() const { return height_; }
|
||||
const GURL& url() const { return url_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
int width_;
|
||||
int height_;
|
||||
GURL url_;
|
||||
};
|
||||
|
||||
// Owner object from the API response. For object details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/playlists#PlaylistOwner
|
||||
class Owner {
|
||||
public:
|
||||
Owner();
|
||||
Owner(const Owner&) = delete;
|
||||
Owner& operator=(const Owner&) = delete;
|
||||
~Owner();
|
||||
|
||||
static void RegisterJSONConverter(base::JSONValueConverter<Owner>* converter);
|
||||
|
||||
const std::string title() const { return title_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
std::string title_;
|
||||
};
|
||||
|
||||
// Playlist object from the API response. For object details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/playlists#Playlist
|
||||
class Playlist {
|
||||
public:
|
||||
Playlist();
|
||||
Playlist(const Playlist&) = delete;
|
||||
Playlist& operator=(const Playlist&) = delete;
|
||||
~Playlist();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<Playlist>* converter);
|
||||
|
||||
const std::string name() const { return name_; }
|
||||
const std::string title() const { return title_; }
|
||||
const std::string description() const { return description_; }
|
||||
int item_count() const { return item_count_; }
|
||||
const std::vector<std::unique_ptr<Image>>& images() const { return images_; }
|
||||
std::vector<std::unique_ptr<Image>>* mutable_images() { return &images_; }
|
||||
Owner& owner() { return owner_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::string title_;
|
||||
std::string description_;
|
||||
int item_count_;
|
||||
std::vector<std::unique_ptr<Image>> images_;
|
||||
Owner owner_;
|
||||
};
|
||||
|
||||
// Music recommendation object from the API response. For object details, check
|
||||
// below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/musicSections/load#musicrecommendation
|
||||
class MusicRecommendation {
|
||||
public:
|
||||
MusicRecommendation();
|
||||
MusicRecommendation(const MusicRecommendation&) = delete;
|
||||
MusicRecommendation& operator=(const MusicRecommendation&) = delete;
|
||||
~MusicRecommendation();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<MusicRecommendation>* converter);
|
||||
|
||||
Playlist& playlist() { return playlist_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
Playlist playlist_;
|
||||
};
|
||||
|
||||
// Music section object from the API response. For object details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/musicSections/load
|
||||
class MusicSection {
|
||||
public:
|
||||
MusicSection();
|
||||
MusicSection(const MusicSection&) = delete;
|
||||
MusicSection& operator=(const MusicSection&) = delete;
|
||||
~MusicSection();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<MusicSection>* converter);
|
||||
|
||||
static std::unique_ptr<MusicSection> CreateFrom(const base::Value& value);
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
const std::string& title() const { return title_; }
|
||||
const std::vector<std::unique_ptr<MusicRecommendation>>&
|
||||
music_recommendations() const {
|
||||
return music_recommendations_;
|
||||
}
|
||||
std::vector<std::unique_ptr<MusicRecommendation>>*
|
||||
mutable_music_recommendations() {
|
||||
return &music_recommendations_;
|
||||
}
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::string title_;
|
||||
std::vector<std::unique_ptr<MusicRecommendation>> music_recommendations_;
|
||||
};
|
||||
|
||||
// Top level music recommendations object from the API response. For object
|
||||
// details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/musicSections/load
|
||||
class TopLevelMusicRecommendation {
|
||||
public:
|
||||
TopLevelMusicRecommendation();
|
||||
TopLevelMusicRecommendation(const TopLevelMusicRecommendation&) = delete;
|
||||
TopLevelMusicRecommendation& operator=(const TopLevelMusicRecommendation&) =
|
||||
delete;
|
||||
~TopLevelMusicRecommendation();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<TopLevelMusicRecommendation>* converter);
|
||||
|
||||
static std::unique_ptr<TopLevelMusicRecommendation> CreateFrom(
|
||||
const base::Value& value);
|
||||
|
||||
MusicSection& music_section() { return music_section_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
MusicSection music_section_;
|
||||
};
|
||||
|
||||
// Top level music section and music recommendations object from the API
|
||||
// response. For object details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/musicSections/load
|
||||
class TopLevelMusicRecommendations {
|
||||
public:
|
||||
TopLevelMusicRecommendations();
|
||||
TopLevelMusicRecommendations(const TopLevelMusicRecommendations&) = delete;
|
||||
TopLevelMusicRecommendations& operator=(const TopLevelMusicRecommendations&) =
|
||||
delete;
|
||||
~TopLevelMusicRecommendations();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<TopLevelMusicRecommendations>* converter);
|
||||
|
||||
static std::unique_ptr<TopLevelMusicRecommendations> CreateFrom(
|
||||
const base::Value& value);
|
||||
|
||||
const std::vector<std::unique_ptr<TopLevelMusicRecommendation>>&
|
||||
top_level_music_recommendations() const {
|
||||
return top_level_music_recommendations_;
|
||||
}
|
||||
std::vector<std::unique_ptr<TopLevelMusicRecommendation>>*
|
||||
mutable_top_level_music_recommendations() {
|
||||
return &top_level_music_recommendations_;
|
||||
}
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<TopLevelMusicRecommendation>>
|
||||
top_level_music_recommendations_;
|
||||
};
|
||||
|
||||
// Track object from the API response. For object details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/tracks#Track
|
||||
class Track {
|
||||
public:
|
||||
Track();
|
||||
Track(const Track&) = delete;
|
||||
Track& operator=(const Track&) = delete;
|
||||
~Track();
|
||||
|
||||
static void RegisterJSONConverter(base::JSONValueConverter<Track>* converter);
|
||||
|
||||
static std::unique_ptr<Track> CreateFrom(const base::Value& value);
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
const std::string& title() const { return title_; }
|
||||
const std::string& duration() const { return duration_; }
|
||||
const std::string& explicit_type() const { return explicit_type_; }
|
||||
const std::vector<std::unique_ptr<Image>>& images() const { return images_; }
|
||||
std::vector<std::unique_ptr<Image>>* mutable_images() { return &images_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::string title_;
|
||||
std::string duration_;
|
||||
std::string explicit_type_;
|
||||
std::vector<std::unique_ptr<Image>> images_;
|
||||
};
|
||||
|
||||
// Queue item object from the API response. For object details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/queues#QueueItem
|
||||
class QueueItem {
|
||||
public:
|
||||
QueueItem();
|
||||
QueueItem(const QueueItem&) = delete;
|
||||
QueueItem& operator=(const QueueItem&) = delete;
|
||||
~QueueItem();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<QueueItem>* converter);
|
||||
|
||||
static std::unique_ptr<QueueItem> CreateFrom(const base::Value& value);
|
||||
|
||||
Track& track() { return track_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
Track track_;
|
||||
};
|
||||
|
||||
// Stream object from the API response. For object details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/queues#Stream
|
||||
class Stream {
|
||||
public:
|
||||
Stream();
|
||||
Stream(const Stream&) = delete;
|
||||
Stream& operator=(const Stream&) = delete;
|
||||
~Stream();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<Stream>* converter);
|
||||
|
||||
static std::unique_ptr<Stream> CreateFrom(const base::Value& value);
|
||||
|
||||
const GURL& url() const { return url_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
GURL url_;
|
||||
};
|
||||
|
||||
// Playback manifest object from the API response. For object details, check
|
||||
// below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/queues#PlaybackManifest
|
||||
class PlaybackManifest {
|
||||
public:
|
||||
PlaybackManifest();
|
||||
PlaybackManifest(const PlaybackManifest&) = delete;
|
||||
PlaybackManifest& operator=(const PlaybackManifest&) = delete;
|
||||
~PlaybackManifest();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<PlaybackManifest>* converter);
|
||||
|
||||
static std::unique_ptr<PlaybackManifest> CreateFrom(const base::Value& value);
|
||||
|
||||
const std::vector<std::unique_ptr<Stream>>& streams() const {
|
||||
return streams_;
|
||||
}
|
||||
std::vector<std::unique_ptr<Stream>>* mutable_streams() { return &streams_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<Stream>> streams_;
|
||||
};
|
||||
|
||||
// Playback context object from the API response. For object details, check
|
||||
// below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/queues#PlaybackContext
|
||||
class PlaybackContext {
|
||||
public:
|
||||
PlaybackContext();
|
||||
PlaybackContext(const PlaybackContext&) = delete;
|
||||
PlaybackContext& operator=(const PlaybackContext&) = delete;
|
||||
~PlaybackContext();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<PlaybackContext>* converter);
|
||||
|
||||
static std::unique_ptr<PlaybackContext> CreateFrom(const base::Value& value);
|
||||
|
||||
QueueItem& queue_item() { return queue_item_; }
|
||||
PlaybackManifest& playback_manifest() { return playback_manifest_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
QueueItem queue_item_;
|
||||
PlaybackManifest playback_manifest_;
|
||||
};
|
||||
|
||||
// Queue object from the API response. For object details, check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/queues#Queue
|
||||
class Queue {
|
||||
public:
|
||||
Queue();
|
||||
Queue(const Queue&) = delete;
|
||||
Queue& operator=(const Queue&) = delete;
|
||||
~Queue();
|
||||
|
||||
static void RegisterJSONConverter(base::JSONValueConverter<Queue>* converter);
|
||||
|
||||
static std::unique_ptr<Queue> CreateFrom(const base::Value& value);
|
||||
|
||||
const std::string name() const { return name_; }
|
||||
int size() const { return size_; }
|
||||
PlaybackContext& playback_context() { return playback_context_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
int size_;
|
||||
PlaybackContext playback_context_;
|
||||
};
|
||||
|
||||
// Playback queue container object from the API response. For object details,
|
||||
// check below:
|
||||
// https://developers.google.com/youtube/mediaconnect/reference/rest/v1/queues/next
|
||||
class QueueContainer {
|
||||
public:
|
||||
QueueContainer();
|
||||
QueueContainer(const QueueContainer&) = delete;
|
||||
QueueContainer& operator=(const QueueContainer&) = delete;
|
||||
~QueueContainer();
|
||||
|
||||
static void RegisterJSONConverter(
|
||||
base::JSONValueConverter<QueueContainer>* converter);
|
||||
|
||||
static std::unique_ptr<QueueContainer> CreateFrom(const base::Value& value);
|
||||
|
||||
Queue& queue() { return queue_; }
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
Queue queue_;
|
||||
};
|
||||
|
||||
} // namespace google_apis::youtube_music
|
||||
|
||||
#endif // GOOGLE_APIS_YOUTUBE_MUSIC_YOUTUBE_MUSIC_API_RESPONSE_TYPES_H_
|
Reference in New Issue
Block a user