aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-03-26 17:33:33 +0100
committerdec05eba <dec05eba@protonmail.com>2021-03-26 17:33:33 +0100
commit8fc6edc4033c04de3cdc6a400976a019a35694b7 (patch)
tree446627137ce186516a5f5cfa6e59b72831fcb820
parentda827778f8c5d2f0cfc56b297099ba58454c38ed (diff)
Soundcloud: autoplay next song in list
-rw-r--r--include/QuickMedia.hpp2
-rw-r--r--plugins/Page.hpp3
-rw-r--r--plugins/Soundcloud.hpp3
-rw-r--r--src/QuickMedia.cpp24
-rw-r--r--src/plugins/Soundcloud.cpp17
5 files changed, 41 insertions, 8 deletions
diff --git a/include/QuickMedia.hpp b/include/QuickMedia.hpp
index 51a97b4..8c6b02e 100644
--- a/include/QuickMedia.hpp
+++ b/include/QuickMedia.hpp
@@ -101,7 +101,7 @@ namespace QuickMedia {
void page_loop_render(sf::RenderWindow &window, std::vector<Tab> &tabs, int selected_tab, TabAssociatedData &tab_associated_data, const Json::Value *json_chapters);
using PageLoopSubmitHandler = std::function<void(const std::vector<Tab> &new_tabs)>;
void page_loop(std::vector<Tab> &tabs, int start_tab_index = 0, PageLoopSubmitHandler after_submit_handler = nullptr);
- void video_content_page(VideoPage *video_page, std::string video_title, bool download_if_streaming_fails);
+ void video_content_page(VideoPage *video_page, std::string video_title, bool download_if_streaming_fails, BodyItems &next_play_items, int play_index);
// Returns -1 to go to previous chapter, 0 to stay on same chapter and 1 to go to next chapter
int image_page(MangaImagesPage *images_page, Body *chapters_body);
void image_continuous_page(MangaImagesPage *images_page);
diff --git a/plugins/Page.hpp b/plugins/Page.hpp
index f1ef893..803b9e6 100644
--- a/plugins/Page.hpp
+++ b/plugins/Page.hpp
@@ -100,6 +100,7 @@ namespace QuickMedia {
public:
VideoPage(Program *program) : Page(program) {}
virtual PageTypez get_type() const override { return PageTypez::VIDEO; }
+ virtual bool autoplay_next_item() { return false; }
virtual BodyItems get_related_media(const std::string &url, std::string &channel_url) { (void)url; (void)channel_url; return {}; }
virtual std::unique_ptr<Page> create_search_page(Program *program, int &search_delay) { (void)program; (void)search_delay; return nullptr; }
virtual std::unique_ptr<Page> create_comments_page(Program *program) { (void)program; return nullptr; }
@@ -108,5 +109,7 @@ namespace QuickMedia {
// Return nullptr if the service doesn't support channels page
virtual std::unique_ptr<LazyFetchPage> create_channels_page(Program *program, const std::string &channel_url) = 0;
virtual std::string get_url() = 0;
+ virtual std::string url_get_playable_url(const std::string &url) { return url; }
+ virtual bool video_should_be_skipped(const std::string &url) { return false; }
};
} \ No newline at end of file
diff --git a/plugins/Soundcloud.hpp b/plugins/Soundcloud.hpp
index 4962c04..0d73d36 100644
--- a/plugins/Soundcloud.hpp
+++ b/plugins/Soundcloud.hpp
@@ -47,9 +47,12 @@ namespace QuickMedia {
public:
SoundcloudAudioPage(Program *program, const std::string &url) : VideoPage(program), url(url) {}
const char* get_title() const override { return ""; }
+ bool autoplay_next_item() override { return true; }
std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *, const std::string &, const std::string &) override { return nullptr; }
std::unique_ptr<LazyFetchPage> create_channels_page(Program *, const std::string &) override { return nullptr; }
std::string get_url() override { return url; }
+ std::string url_get_playable_url(const std::string &url) override;
+ bool video_should_be_skipped(const std::string &url) override { return url == "track"; }
private:
std::string url;
};
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index ff78735..cc89146 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -1200,7 +1200,8 @@ namespace QuickMedia {
image_board_thread_page(static_cast<ImageBoardThreadPage*>(new_tabs[0].page.get()), new_tabs[0].body.get());
} else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::VIDEO) {
current_page = PageType::VIDEO_CONTENT;
- video_content_page(static_cast<VideoPage*>(new_tabs[0].page.get()), selected_item->get_title(), false);
+ int selected_index = tabs[selected_tab].body->get_selected_item();
+ video_content_page(static_cast<VideoPage*>(new_tabs[0].page.get()), selected_item->get_title(), false, tabs[selected_tab].body->items, selected_index);
} else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::CHAT) {
body_set_selected_item(tabs[selected_tab].body.get(), selected_item.get());
current_page = PageType::CHAT;
@@ -1740,7 +1741,7 @@ namespace QuickMedia {
#define CLEANMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask|Mod4Mask|Mod5Mask))
- void Program::video_content_page(VideoPage *video_page, std::string video_title, bool download_if_streaming_fails) {
+ void Program::video_content_page(VideoPage *video_page, std::string video_title, bool download_if_streaming_fails, BodyItems &next_play_items, int play_index) {
sf::Clock time_watched_timer;
bool added_recommendations = false;
bool video_loaded = false;
@@ -1806,6 +1807,9 @@ namespace QuickMedia {
std::unique_ptr<VideoPlayer> video_player;
BodyItems related_videos;
+ if(video_page->autoplay_next_item())
+ related_videos.insert(related_videos.end(), next_play_items.begin() + play_index + 1, next_play_items.end());
+
std::string channel_url;
sf::WindowHandle video_player_window = None;
@@ -1839,6 +1843,9 @@ namespace QuickMedia {
show_notification("QuickMedia", err_msg.c_str(), Urgency::CRITICAL);
current_page = previous_page;
} else {
+ if(video_page->autoplay_next_item())
+ return;
+
channel_url.clear();
// TODO: Remove this and use lazy_fetch instead
related_videos = video_page->get_related_media(video_url, channel_url);
@@ -2037,7 +2044,7 @@ namespace QuickMedia {
// Find video that hasn't been played before in this video session
// TODO: Remove duplicates
for(auto it = related_videos.begin(), end = related_videos.end(); it != end; ++it) {
- if(watched_videos.find((*it)->url) == watched_videos.end()) {
+ if(watched_videos.find((*it)->url) == watched_videos.end() && !video_page->video_should_be_skipped((*it)->url)) {
new_video_url = (*it)->url;
new_video_title = (*it)->get_title();
break;
@@ -2051,7 +2058,7 @@ namespace QuickMedia {
break;
}
- video_url = std::move(new_video_url);
+ video_url = video_page->url_get_playable_url(new_video_url);
video_title = std::move(new_video_title);
load_video_error_check(false);
} else if(update_err != VideoPlayer::Error::OK) {
@@ -2839,7 +2846,8 @@ namespace QuickMedia {
watched_videos.clear();
// TODO: Use real title
thread_page->video_url = selected_item->attached_content_url;
- video_content_page(thread_page, "No title.webm", true);
+ BodyItems next_items;
+ video_content_page(thread_page, "No title.webm", true, next_items, 0);
redraw = true;
} else {
if(downloading_image && load_image_future.valid())
@@ -4133,7 +4141,8 @@ namespace QuickMedia {
current_page = PageType::VIDEO_CONTENT;
// TODO: Add title
video_page->url = url;
- video_content_page(video_page.get(), "No title", false);
+ BodyItems next_items;
+ video_content_page(video_page.get(), "No title", false, next_items, 0);
redraw = true;
} else {
const char *launch_program = "xdg-open";
@@ -4212,7 +4221,8 @@ namespace QuickMedia {
no_video = is_audio;
// TODO: Add title
video_page->url = selected->url;
- video_content_page(video_page.get(), "No title", message_type == MessageType::VIDEO || message_type == MessageType::AUDIO);
+ BodyItems next_items;
+ video_content_page(video_page.get(), "No title", message_type == MessageType::VIDEO || message_type == MessageType::AUDIO, next_items, 0);
no_video = prev_no_video;
redraw = true;
return true;
diff --git a/src/plugins/Soundcloud.cpp b/src/plugins/Soundcloud.cpp
index cfb6011..37538ed 100644
--- a/src/plugins/Soundcloud.cpp
+++ b/src/plugins/Soundcloud.cpp
@@ -284,4 +284,21 @@ namespace QuickMedia {
if(result != DownloadResult::OK) return download_result_to_plugin_result(result);
return parse_user_page(json_root, result_items, next_href);
}
+
+ std::string SoundcloudAudioPage::url_get_playable_url(const std::string &url) {
+ std::string query_url = url + "?client_id=" + client_id;
+
+ Json::Value json_root;
+ DownloadResult result = download_json(json_root, query_url, {}, true);
+ if(result != DownloadResult::OK) return url;
+
+ if(!json_root.isObject())
+ return url;
+
+ const Json::Value &url_json = json_root["url"];
+ if(!url_json.isString())
+ return url;
+
+ return url_json.asString();
+ }
} \ No newline at end of file