aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Soundcloud.cpp
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-05-13 13:36:12 +0200
committerdec05eba <dec05eba@protonmail.com>2021-05-13 13:36:12 +0200
commit4af866c610a8f6650a5d2c5045c085d9af7d7951 (patch)
tree8badf8a702a7ab4b4dd1b8dfa2b5cbb51ab361e0 /src/plugins/Soundcloud.cpp
parent0b86bc6849be72f28dedc15e726015d81d787cdf (diff)
Fix soundcloud not loading all playlist tracks, auto load next page if bottom visible
Diffstat (limited to 'src/plugins/Soundcloud.cpp')
-rw-r--r--src/plugins/Soundcloud.cpp104
1 files changed, 93 insertions, 11 deletions
diff --git a/src/plugins/Soundcloud.cpp b/src/plugins/Soundcloud.cpp
index e0a4d24..9a5fe64 100644
--- a/src/plugins/Soundcloud.cpp
+++ b/src/plugins/Soundcloud.cpp
@@ -10,6 +10,7 @@ namespace QuickMedia {
class SoundcloudPlaylist : public BodyItemExtra {
public:
BodyItems tracks;
+ std::vector<int64_t> tracks_to_load;
};
// Return empty string if transcoding files are not found
@@ -23,8 +24,8 @@ namespace QuickMedia {
return "";
}
- static std::string duration_to_descriptive_string(int64_t seconds) {
- seconds /= 1000;
+ static std::string duration_to_descriptive_string(int64_t milliseconds) {
+ time_t seconds = milliseconds / 1000;
time_t minutes = seconds / 60;
time_t hours = minutes / 60;
@@ -66,14 +67,40 @@ namespace QuickMedia {
static std::shared_ptr<BodyItem> parse_collection_item(const Json::Value &item_json) {
std::string title;
+ int num_playlists = 0;
+ const Json::Value &playlist_count_json = item_json["playlist_count"];
+ if(playlist_count_json.isInt())
+ num_playlists = playlist_count_json.asInt();
+
+ int num_tracks = 0;
+ const Json::Value &track_count_json = item_json["track_count"];
+ if(track_count_json.isInt())
+ num_tracks = track_count_json.asInt();
+
+ const Json::Value &user_json = item_json["user"];
+ if(user_json.isObject()) {
+ const Json::Value &username_json = user_json["username"];
+ if(username_json.isString())
+ title = username_json.asString();
+
+ const Json::Value &track_count_json = user_json["track_count"];
+ if(track_count_json.isInt())
+ num_tracks = track_count_json.asInt();
+ }
+
const Json::Value &title_json = item_json["title"];
const Json::Value &username_json = item_json["username"];
- if(title_json.isString())
- title = title_json.asString();
- else if(username_json.isString())
- title = username_json.asString();
- else
+ if(title_json.isString()) {
+ if(!title.empty())
+ title += " - ";
+ title += title_json.asString();
+ } else if(username_json.isString()) {
+ if(!title.empty())
+ title += " - ";
+ title += username_json.asString();
+ } else {
return nullptr;
+ }
auto body_item = BodyItem::create(std::move(title));
std::string description;
@@ -82,6 +109,7 @@ namespace QuickMedia {
if(media_json.isObject())
body_item->url = get_best_transcoding_audio_url(media_json);
+ bool is_playlist = false;
if(body_item->url.empty()) {
const Json::Value &tracks_json = item_json["tracks"];
if(tracks_json.isArray()) {
@@ -91,13 +119,20 @@ namespace QuickMedia {
continue;
auto track = parse_collection_item(track_json);
- if(track)
+ if(track) {
playlist->tracks.push_back(std::move(track));
+ } else {
+ const Json::Value &track_id_json = track_json["id"];
+ if(track_id_json.isInt64())
+ playlist->tracks_to_load.push_back(track_id_json.asInt64());
+ }
}
- description = "Playlist with " + std::to_string(playlist->tracks.size()) + " track" + (playlist->tracks.size() == 1 ? "" : "s");
+ num_tracks = tracks_json.size();
+ description = "Playlist with " + std::to_string(num_tracks) + " track" + (num_tracks == 1 ? "" : "s");
body_item->extra = std::move(playlist);
body_item->url = "track";
+ is_playlist = true;
}
}
@@ -134,6 +169,20 @@ namespace QuickMedia {
body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE;
}
+ if(username_json.isString()) {
+ if(!description.empty())
+ description += '\n';
+ description += "Artist";
+ if(num_playlists > 0)
+ description += " • " + std::to_string(num_playlists) + " playlist" + (num_playlists == 1 ? "" : "s");
+ if(num_tracks > 0)
+ description += " • " + std::to_string(num_tracks) + " track" + (num_tracks == 1 ? "" : "s");
+ } else if(!is_playlist) {
+ if(!description.empty())
+ description += '\n';
+ description += "Track";
+ }
+
std::string duration_str = collection_item_get_duration(item_json);
if(!duration_str.empty()) {
if(!description.empty())
@@ -183,9 +232,10 @@ namespace QuickMedia {
return PluginResult::ERR;
if(url == "track") {
+ SoundcloudPlaylist *playlist = static_cast<SoundcloudPlaylist*>(submit_body_item->extra.get());
auto body = create_body();
- body->items = static_cast<SoundcloudPlaylist*>(submit_body_item->extra.get())->tracks;
- result_tabs.push_back(Tab{std::move(body), std::make_unique<SoundcloudPlaylistPage>(program, title), nullptr});
+ body->items = playlist->tracks;
+ result_tabs.push_back(Tab{std::move(body), std::make_unique<SoundcloudPlaylistPage>(program, playlist, title), nullptr});
} else if(url.find("/stream/users/") != std::string::npos) {
std::string query_url = url + "?client_id=" + client_id + "&limit=20&offset=0&linked_partitioning=1&app_version=1616689516&app_locale=en";
@@ -352,6 +402,38 @@ namespace QuickMedia {
return parse_user_page(json_root, result_items, next_href);
}
+ PluginResult SoundcloudPlaylistPage::get_page(const std::string&, int, BodyItems &result_items) {
+ std::string ids_param;
+ const size_t tracks_load_end = std::min(track_offset + 10, playlist->tracks_to_load.size());
+ for(size_t i = track_offset; i < tracks_load_end; ++i) {
+ if(!ids_param.empty())
+ ids_param += "%2C";
+ ids_param += std::to_string(playlist->tracks_to_load[i]);
+ }
+ track_offset = tracks_load_end;
+
+ if(ids_param.empty())
+ return PluginResult::OK;
+
+ Json::Value json_root;
+ DownloadResult result = download_json(json_root, "https://api-v2.soundcloud.com/tracks?ids=" + ids_param + "&client_id=" + client_id + "&app_version=1616689516&app_locale=en", {}, true);
+ if(result != DownloadResult::OK) return download_result_to_plugin_result(result);
+
+ if(!json_root.isArray())
+ return PluginResult::ERR;
+
+ for(const Json::Value &item_json : json_root) {
+ if(!item_json.isObject())
+ continue;
+
+ auto track_item = parse_collection_item(item_json);
+ if(track_item)
+ result_items.push_back(std::move(track_item));
+ }
+
+ return PluginResult::OK;
+ }
+
std::string SoundcloudAudioPage::url_get_playable_url(const std::string &url) {
std::string query_url = url + "?client_id=" + client_id;