diff options
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | src/QuickMedia.cpp | 163 | ||||
-rw-r--r-- | src/plugins/Youtube.cpp | 39 |
4 files changed, 122 insertions, 85 deletions
@@ -80,7 +80,9 @@ Type text and then wait and QuickMedia will automatically search.\ `Ctrl+S`: Save the video/music (with dialog).\ `Ctrl+Shift+S`: Save the video/music (without dialog).\ `Ctrl+C`: Copy the url of the currently playing video to the clipboard (with timestamp, if supported).\ -`F5`: Reload the video/music. +`F5`: Reload the video/music.\ +`<`: Go to the previous video.\ +`>`: Go to the next video. ### Youtube channel controls `Ctrl+T`: Subscribe/Unsubscribe from the channel. ### Manga search/history/chapters page controls @@ -293,3 +293,4 @@ Fix youtube age restricted videos. Direct link to youtube playlist should open the playlist page and select the playlist item. Support youtube mix. Doesn't work that nicely because the mix playlist doesn't show all items unless you click on the last item and then it will show more items. Youtube community tab. +v0.m3u8 doesn't work for some lbry videos (such as https://odysee.com/@MoneroMagazine:9/Privacy-101-w-Luke-Smith:2). Fallback to v1.m3u8 (next track in the master.m3u8 file) in such cases.
\ No newline at end of file diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index d145dda..4e0367a 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -3558,6 +3558,72 @@ namespace QuickMedia { } }; + auto play_video = [&](const std::string &new_video_url) { + TaskResult get_playable_url_result = run_task_with_loading_screen([video_page, &new_video_url]() { + video_page->set_url(video_page->url_get_playable_url(new_video_url)); + return true; + }); + + if(get_playable_url_result == TaskResult::CANCEL) { + current_page = previous_page; + go_to_previous_page = true; + return; + } else if(get_playable_url_result == TaskResult::FALSE) { + show_notification("QuickMedia", "Failed to get playable url", Urgency::CRITICAL); + current_page = previous_page; + go_to_previous_page = true; + return; + } + + load_video_error_check("0"); + }; + + auto load_next_page = [&]() -> size_t { + if(!parent_body_page) + return 0; + + BodyItems new_body_items; + const int fetch_page = (*parent_body_page) + 1; + TaskResult load_next_page_result = run_task_with_loading_screen([parent_page, parent_page_search, fetch_page, &new_body_items] { + if(parent_page->get_page(parent_page_search, fetch_page, new_body_items) != PluginResult::OK) { + fprintf(stderr, "Failed to get next page (page %d)\n", fetch_page); + return false; + } + return true; + }); + + fprintf(stderr, "Finished fetching page %d, num new items: %zu\n", fetch_page, new_body_items.size()); + size_t num_new_messages = new_body_items.size(); + if(num_new_messages > 0) { + if(parent_body) + parent_body->append_items(new_body_items); + (*parent_body_page)++; + related_videos = std::move(new_body_items); + } + + if(load_next_page_result == TaskResult::CANCEL) { + current_page = previous_page; + go_to_previous_page = true; + } + + return num_new_messages; + }; + + auto play_next_video = [&]() -> bool { + if(parent_body->select_next_item(false, true)) { + play_video(parent_body->get_selected()->url); + return true; + } else { + if(load_next_page() == 0) { + return false; + } else { + parent_body->select_next_item(false, true); + play_video(parent_body->get_selected()->url); + return true; + } + } + }; + idle_active_handler(); while (current_page == PageType::VIDEO_CONTENT && window.is_open() && !go_to_previous_page) { @@ -3640,6 +3706,20 @@ namespace QuickMedia { double resume_start_time = 0.0; video_player->get_time_in_file(&resume_start_time); load_video_error_check(std::to_string((int)resume_start_time)); + } else if(pressed_keysym == XK_less) { + const bool forward = pressing_shift; + if(parent_body && video_page->autoplay_next_item() && video_page->should_autoplay()) { + if(forward) { + if(!play_next_video()) + show_notification("QuickMedia", "You have reached the last video in the playlist", Urgency::LOW); + } else { + if(parent_body->select_previous_item(false, true)) { + play_video(parent_body->get_selected()->url); + } else { + show_notification("QuickMedia", "You have reached the first video in the playlist", Urgency::LOW); + } + } + } } else if(pressed_keysym == XK_r && pressing_ctrl && !video_page->is_local()) { cursor_hide_timer.restart(); if(!cursor_visible) @@ -3778,62 +3858,55 @@ namespace QuickMedia { } } }; - find_next_video(); - - if(new_video_url.empty() && parent_page && parent_body_page && video_page->autoplay_next_item()) { - BodyItems new_body_items; - const int fetch_page = (*parent_body_page) + 1; - TaskResult load_next_page_result = run_task_with_loading_screen([parent_page, parent_page_search, fetch_page, &new_body_items] { - if(parent_page->get_page(parent_page_search, fetch_page, new_body_items) != PluginResult::OK) { - fprintf(stderr, "Failed to get next page (page %d)\n", fetch_page); - return false; - } - return true; - }); - fprintf(stderr, "Finished fetching page %d, num new items: %zu\n", fetch_page, new_body_items.size()); - size_t num_new_messages = new_body_items.size(); - if(num_new_messages > 0) { - if(parent_body) - parent_body->append_items(new_body_items); - (*parent_body_page)++; - related_videos = std::move(new_body_items); - find_next_video(); + if(parent_body && video_page->autoplay_next_item() && video_page->should_autoplay()) { + if(!play_next_video()) { + if(!video_page->is_local()) + show_notification("QuickMedia", "No more related videos to play"); + current_page = previous_page; + go_to_previous_page = true; + break; } + } else { + find_next_video(); - if(load_next_page_result == TaskResult::CANCEL) { + if(new_video_url.empty() && parent_page && parent_body_page && video_page->autoplay_next_item()) { + if(load_next_page() > 0) { + find_next_video(); + } else { + current_page = previous_page; + go_to_previous_page = true; + break; + } + } + + // If there are no videos to play, then dont play any... + if(new_video_url.empty()) { + if(!video_page->is_local()) + show_notification("QuickMedia", "No more related videos to play"); current_page = previous_page; go_to_previous_page = true; break; } - } - // If there are no videos to play, then dont play any... - if(new_video_url.empty()) { - if(!video_page->is_local()) - show_notification("QuickMedia", "No more related videos to play"); - current_page = previous_page; - go_to_previous_page = true; - break; - } + TaskResult get_playable_url_result = run_task_with_loading_screen([video_page, &new_video_url]() { + video_page->set_url(video_page->url_get_playable_url(new_video_url)); + return true; + }); - TaskResult get_playable_url_result = run_task_with_loading_screen([video_page, &new_video_url]() { - video_page->set_url(video_page->url_get_playable_url(new_video_url)); - return true; - }); + if(get_playable_url_result == TaskResult::CANCEL) { + current_page = previous_page; + go_to_previous_page = true; + break; + } else if(get_playable_url_result == TaskResult::FALSE) { + show_notification("QuickMedia", "Failed to get playable url", Urgency::CRITICAL); + current_page = previous_page; + go_to_previous_page = true; + break; + } - if(get_playable_url_result == TaskResult::CANCEL) { - current_page = previous_page; - go_to_previous_page = true; - break; - } else if(get_playable_url_result == TaskResult::FALSE) { - show_notification("QuickMedia", "Failed to get playable url", Urgency::CRITICAL); - current_page = previous_page; - go_to_previous_page = true; - break; + load_video_error_check(); } - - load_video_error_check(); } else if(update_err != VideoPlayer::Error::OK) { show_notification("QuickMedia", "Failed to play the video (error code " + std::to_string((int)update_err) + ")", Urgency::CRITICAL); current_page = previous_page; diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index d4211b3..2e3a238 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -2312,45 +2312,6 @@ namespace QuickMedia { return PluginResult::OK; } - static void playlist_get_items(const Json::Value &json_root, std::unordered_set<std::string> &added_videos, BodyItems &result_items) { - if(!json_root.isObject()) - return; - - const Json::Value *response_json = &json_root["response"]; - if(!response_json->isObject()) - response_json = &json_root; - - const Json::Value &contents_json = (*response_json)["contents"]; - if(!contents_json.isObject()) - return; - - const Json::Value &tcwnr_json = contents_json["twoColumnWatchNextResults"]; - if(!tcwnr_json.isObject()) - return; - - const Json::Value &playlist_json = tcwnr_json["playlist"]; - if(!playlist_json.isObject()) - return; - - const Json::Value &playlist_inner_json = playlist_json["playlist"]; - if(!playlist_inner_json.isObject()) - return; - - //const Json::Value &title_json = playlist_inner_json["title"]; - const Json::Value &playlist_contents_json = playlist_inner_json["contents"]; - if(!playlist_contents_json.isArray()) - return; - - for(const Json::Value &content_json : playlist_contents_json) { - if(!content_json.isObject()) - continue; - - auto body_item = parse_common_video_item(content_json["playlistPanelVideoRenderer"], added_videos); - if(body_item) - result_items.push_back(std::move(body_item)); - } - } - YoutubePlaylistPage::YoutubePlaylistPage(Program *program, const std::string &url, std::string title) : LazyFetchPage(program), title(std::move(title)) { |