aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/Youtube.hpp3
-rw-r--r--src/QuickMedia.cpp1
-rw-r--r--src/VideoPlayer.cpp4
-rw-r--r--src/plugins/Youtube.cpp79
4 files changed, 78 insertions, 9 deletions
diff --git a/plugins/Youtube.hpp b/plugins/Youtube.hpp
index 6fc6039..16f5870 100644
--- a/plugins/Youtube.hpp
+++ b/plugins/Youtube.hpp
@@ -12,5 +12,8 @@ namespace QuickMedia {
int get_search_delay() const override { return 500; }
bool search_suggestion_is_search() const override { return true; }
Page get_page_after_search() const override { return Page::VIDEO_CONTENT; }
+ private:
+ std::string last_related_media_playlist_id;
+ BodyItems last_playlist_data;
};
} \ No newline at end of file
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index a7dc7ff..a57c522 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -397,7 +397,6 @@ namespace QuickMedia {
std::unique_ptr<VideoPlayer> video_player;
auto play_video = [this, &video_player, &play_next_video, &on_window_create, &video_player_ui_window, &ui_resize]() {
- printf("Playing video: %s\n", content_url.c_str());
watched_videos.insert(content_url);
video_player = std::make_unique<VideoPlayer>([this, &play_next_video, &video_player_ui_window, &ui_resize](const char *event_name) {
if(strcmp(event_name, "end-file") == 0) {
diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp
index 65bbb67..96b9ee2 100644
--- a/src/VideoPlayer.cpp
+++ b/src/VideoPlayer.cpp
@@ -165,8 +165,6 @@ namespace QuickMedia {
VideoPlayer::Error VideoPlayer::read_ipc_func() {
assert(connected_to_ipc);
- assert(event_callback);
-
Json::Value json_root;
Json::CharReaderBuilder json_builder;
std::unique_ptr<Json::CharReader> json_reader(json_builder.newCharReader());
@@ -189,7 +187,7 @@ namespace QuickMedia {
if(json_reader->parse(buffer + start, buffer + i, &json_root, &json_errors)) {
const Json::Value &event = json_root["event"];
const Json::Value &request_id_json = json_root["request_id"];
- if(event.isString())
+ if(event.isString() && event_callback)
event_callback(event.asCString());
else if(expected_request_id != 0 && request_id_json.isNumeric() && request_id_json.asUInt() == expected_request_id) {
request_response_data = json_root["data"];
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp
index 56e8574..0f0ca05 100644
--- a/src/plugins/Youtube.cpp
+++ b/src/plugins/Youtube.cpp
@@ -127,11 +127,44 @@ namespace QuickMedia {
return result == 0 ? SuggestionResult::OK : SuggestionResult::ERR;
}
+ static std::string get_playlist_id_from_url(const std::string &url) {
+ std::string playlist_id = url;
+ size_t list_index = playlist_id.find("&list=");
+ if(list_index == std::string::npos)
+ return playlist_id;
+ return playlist_id.substr(list_index);
+ }
+
+ static std::string remove_index_from_playlist_url(const std::string &url) {
+ std::string result = url;
+ size_t index = result.rfind("&index=");
+ if(index == std::string::npos)
+ return result;
+ return result.substr(0, index);
+ }
+
+ // TODO: Make this faster by using string search instead of parsing html.
+ // TODO: If the result is a play
BodyItems Youtube::get_related_media(const std::string &url) {
BodyItems result_items;
+ struct ItemData {
+ BodyItems &result_items;
+ size_t index = 0;
+ };
+ ItemData item_data { result_items, 0 };
+
+ std::string modified_url = remove_index_from_playlist_url(url);
+ std::string playlist_id = get_playlist_id_from_url(modified_url);
+ if(playlist_id == last_related_media_playlist_id) {
+ result_items.reserve(last_playlist_data.size());
+ for(auto &data : last_playlist_data) {
+ result_items.push_back(std::make_unique<BodyItem>(*data));
+ }
+ return result_items;
+ }
std::string website_data;
- if(download_to_string(url, website_data) != DownloadResult::OK)
+ if(download_to_string(modified_url, website_data) != DownloadResult::OK)
return result_items;
QuickMediaHtmlSearch html_search;
@@ -139,19 +172,55 @@ namespace QuickMedia {
if(result != 0)
goto cleanup;
+ if(!playlist_id.empty()) {
+ result = quickmedia_html_find_nodes_xpath(&html_search, "//a",
+ [](QuickMediaHtmlNode *node, void *userdata) {
+ auto *item_data = (ItemData*)userdata;
+ const char *node_class = quickmedia_html_node_get_attribute_value(node, "class");
+ const char *href = quickmedia_html_node_get_attribute_value(node, "href");
+ if(node_class && href && contains(node_class, "playlist-video")) {
+ auto item = std::make_unique<BodyItem>("");
+ item->url = std::string("https://www.youtube.com") + remove_index_from_playlist_url(href);
+ item_data->result_items.push_back(std::move(item));
+ }
+ }, &item_data);
+
+ result = quickmedia_html_find_nodes_xpath(&html_search, "//li",
+ [](QuickMediaHtmlNode *node, void *userdata) {
+ auto *item_data = (ItemData*)userdata;
+ if(item_data->index >= item_data->result_items.size())
+ return;
+
+ // TODO: Also add title for related media. This data is in @data-title
+ const char *data_thumbnail_url = quickmedia_html_node_get_attribute_value(node, "data-thumbnail-url");
+ if(data_thumbnail_url && contains(data_thumbnail_url, "ytimg.com")) {
+ item_data->result_items[item_data->index]->thumbnail_url = data_thumbnail_url;
+ ++item_data->index;
+ }
+ }, &item_data);
+ }
+
+ // We want non-playlist videos every when there is a playlist, since we want to play non-playlist videos after
+ // playing all playlist videos
result = quickmedia_html_find_nodes_xpath(&html_search, "//ul[class=\"video-list\"]//div[class=\"content-wrapper\"]/a",
[](QuickMediaHtmlNode *node, void *userdata) {
- auto *result_items = (BodyItems*)userdata;
+ auto *item_data = (ItemData*)userdata;
const char *href = quickmedia_html_node_get_attribute_value(node, "href");
- // TODO: Also add title for related media
+ // TODO: Also add title for related media and thumbnail
if(href && begins_with(href, "/watch?v=")) {
auto item = std::make_unique<BodyItem>("");
item->url = std::string("https://www.youtube.com") + href;
- result_items->push_back(std::move(item));
+ item_data->result_items.push_back(std::move(item));
}
- }, &result_items);
+ }, &item_data);
cleanup:
+ last_playlist_data.clear();
+ last_playlist_data.reserve(result_items.size());
+ for(auto &data : result_items) {
+ last_playlist_data.push_back(std::make_unique<BodyItem>(*data));
+ }
+ last_related_media_playlist_id = playlist_id;
quickmedia_html_search_deinit(&html_search);
return result_items;
}