From dfa4e24f72996d507e710fc6839367536237c501 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 25 Jun 2021 22:52:47 +0200 Subject: Rework youtube redirect code --- src/plugins/Youtube.cpp | 64 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 13 deletions(-) (limited to 'src/plugins/Youtube.cpp') diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index 05fe5c5..f20f38e 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -220,7 +220,7 @@ R"END( // Sometimes youtube returns a redirect url (not in the header but in the body...). // TODO: Find why this happens and if there is a way bypass it. - static std::string get_playback_url_recursive(std::string playback_url) { + static std::string get_playback_url_recursive(std::string playback_url, int &content_length) { std::vector additional_args = get_cookies(); additional_args.push_back({ "-r", "0-4096" }); @@ -232,16 +232,27 @@ R"END( std::string content_type = header_extract_value(response_headers, "content-type"); if(content_type.empty()) { - fprintf(stderr, "Failed to find content-type in youtube video header. Trying to play the video anyways\n"); - return playback_url; + fprintf(stderr, "Failed to find content-type in youtube video header\n"); + return ""; } - if(string_starts_with(content_type, "video") || string_starts_with(content_type, "audio")) + if(string_starts_with(content_type, "video") || string_starts_with(content_type, "audio")) { + std::string content_length_str = header_extract_value(response_headers, "content-length"); + if(content_length_str.empty()) + return ""; + + errno = 0; + char *endptr; + content_length = strtol(content_length_str.c_str(), &endptr, 10); + if(endptr == content_length_str.c_str() || errno != 0) + return ""; + return playback_url; + } if(response_body.empty()) { - fprintf(stderr, "Failed to redirect youtube video. Trying to play the video anyways\n"); - return playback_url; + fprintf(stderr, "Failed to redirect youtube video\n"); + return ""; } playback_url = std::move(response_body); @@ -250,19 +261,46 @@ R"END( return playback_url; } - void youtube_custom_redirect(std::string &video_url, std::string &audio_url) { + bool youtube_custom_redirect(std::string &video_url, std::string &audio_url, int &video_content_length, int &audio_content_length, std::function active_handler) { // TODO: Do this without threads + int num_total_tasks = 0; AsyncTask tasks[2]; - if(!video_url.empty()) - tasks[0] = AsyncTask([video_url]() { return get_playback_url_recursive(std::move(video_url)); }); - if(!audio_url.empty()) - tasks[1] = AsyncTask([audio_url]() { return get_playback_url_recursive(std::move(audio_url)); }); + if(!video_url.empty()) { + tasks[0] = AsyncTask([video_url, &video_content_length]() { return get_playback_url_recursive(std::move(video_url), video_content_length); }); + ++num_total_tasks; + } + + if(!audio_url.empty()) { + tasks[1] = AsyncTask([audio_url, &audio_content_length]() { return get_playback_url_recursive(std::move(audio_url), audio_content_length); }); + ++num_total_tasks; + } + + if(num_total_tasks == 0) + return false; + + int num_finished_tasks = 0; std::string *strings[2] = { &video_url, &audio_url }; - for(int i = 0; i < 2; ++i) { - if(tasks[i].valid()) + while(true) { + for(int i = 0; i < 2; ++i) { + if(!tasks[i].ready()) + continue; + *strings[i] = tasks[i].get(); + if(strings[i]->empty()) + return false; + + ++num_finished_tasks; + if(num_finished_tasks == num_total_tasks) + return true; + } + + if(!active_handler()) + return false; + + std::this_thread::sleep_for(std::chrono::milliseconds(5)); } + return true; } // This is a common setup of text in the youtube json -- cgit v1.2.3