aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Youtube.cpp64
1 files changed, 51 insertions, 13 deletions
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<CommandArg> 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<bool()> active_handler) {
// TODO: Do this without threads
+ int num_total_tasks = 0;
AsyncTask<std::string> tasks[2];
- if(!video_url.empty())
- tasks[0] = AsyncTask<std::string>([video_url]() { return get_playback_url_recursive(std::move(video_url)); });
- if(!audio_url.empty())
- tasks[1] = AsyncTask<std::string>([audio_url]() { return get_playback_url_recursive(std::move(audio_url)); });
+ if(!video_url.empty()) {
+ tasks[0] = AsyncTask<std::string>([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<std::string>([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