aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/Lbry.cpp62
-rw-r--r--src/plugins/LocalAnime.cpp8
2 files changed, 61 insertions, 9 deletions
diff --git a/src/plugins/Lbry.cpp b/src/plugins/Lbry.cpp
index a5806ab..1ce23c0 100644
--- a/src/plugins/Lbry.cpp
+++ b/src/plugins/Lbry.cpp
@@ -70,9 +70,6 @@ namespace QuickMedia {
body_item->userdata = search_type_channel;
is_channel = true;
} else if(strcmp(value_type_json.asCString(), "stream") == 0) {
- body_item->url = canonical_url_json.asString();
- body_item->userdata = search_type_video;
-
// Skip livestreams for now as they are pretty broken on lbry.
// Livestream requests work by doing GET https://api.live.odysee.com/v1/odysee/live/<claim_id>
// then get stream url with .data.url. If that is missing then there is no livestream going on. What to do then?
@@ -80,6 +77,25 @@ namespace QuickMedia {
const Json::Value &stream_type_json = value_json["stream_type"];
if(!stream_type_json.isString() || strcmp(stream_type_json.asCString(), "video") != 0)
return nullptr;
+
+ if(!name_json.isString())
+ return nullptr;
+
+ const Json::Value &video_source_json = value_json["source"];
+ if(!video_source_json.isObject())
+ return nullptr;
+
+ const Json::Value &media_type_json = video_source_json["media_type"];
+ if(!media_type_json.isString() || !strstr(media_type_json.asCString(), "video/"))
+ return nullptr;
+
+ const Json::Value &hash_json = video_source_json["hash"];
+ const Json::Value &sd_hash_json = video_source_json["sd_hash"];
+ if(!hash_json.isString() || !sd_hash_json.isString())
+ return nullptr;
+
+ body_item->url = "https://player.odycdn.com/api/v4/streams/tc/" + name_json.asString() + "/" + hash_json.asString() + "/" + sd_hash_json.asString() + "/master.m3u8";
+ body_item->userdata = search_type_video;
}
body_item->thumbnail_size = { 220, 130 };
@@ -347,7 +363,8 @@ namespace QuickMedia {
return get_page("", 0, result_items);
}
- static PluginResult video_get_stream_url(Page *page, const std::string &video_url, std::string &streaming_url, std::string &err_str) {
+ static PluginResult video_get_stream_url(Page *page, const std::string &video_url, std::vector<M3U8Stream> &streams, std::string &err_str) {
+#if 0
std::string url = "https://api.na-backend.odysee.com/api/v1/proxy?m=get";
Json::Value request_params_json(Json::objectValue);
@@ -391,6 +408,14 @@ namespace QuickMedia {
streaming_url = streaming_url_json.asString();
return PluginResult::OK;
+#else
+ std::string website_data;
+ DownloadResult result = download_to_string(video_url.c_str(), website_data, {}, true);
+ if(result != DownloadResult::OK) return download_result_to_plugin_result(result);
+
+ streams = m3u8_get_streams(website_data);
+ return PluginResult::OK;
+#endif
}
// TODO: Support |max_height|. This can be done by gettin video source hash and checking for sd_hash and then resolution.
@@ -404,7 +429,30 @@ namespace QuickMedia {
std::string LbryVideoPage::get_video_url(int max_height, bool &has_embedded_audio, std::string &ext) {
has_embedded_audio = true;
ext = ".mp4"; // TODO: Check if this is always correct
- return streaming_url;
+
+ if(streams.empty())
+ return url;
+
+ std::sort(streams.begin(), streams.end(), [](const M3U8Stream &a, const M3U8Stream &b) {
+ return a.height > b.height;
+ });
+
+ size_t selected_stream = 0;
+ for(size_t i = 0; i < streams.size(); ++i) {
+ if(streams[i].height <= max_height) {
+ selected_stream = i;
+ break;
+ }
+ }
+
+ std::string video_url = url;
+ size_t end_section = video_url.rfind('/');
+ if(end_section != std::string::npos && end_section > 0 && end_section != video_url.size() - 1) {
+ end_section += 1;
+ video_url.replace(end_section, video_url.size() - end_section, streams[selected_stream].url);
+ }
+
+ return video_url;
}
std::string LbryVideoPage::get_audio_url(std::string&) {
@@ -412,10 +460,10 @@ namespace QuickMedia {
}
PluginResult LbryVideoPage::load(const SubmitArgs &args, VideoInfo &video_info, std::string &err_str) {
- streaming_url.clear();
+ streams.clear();
video_info.title = args.title;
//title = this->title;
video_info.duration = 0.0;
- return video_get_stream_url(this, url, streaming_url, err_str);
+ return video_get_stream_url(this, url, streams, err_str);
}
} \ No newline at end of file
diff --git a/src/plugins/LocalAnime.cpp b/src/plugins/LocalAnime.cpp
index 3682ea5..a8cebab 100644
--- a/src/plugins/LocalAnime.cpp
+++ b/src/plugins/LocalAnime.cpp
@@ -330,11 +330,15 @@ namespace QuickMedia {
LocalAnimeBodyItemData *item_data = static_cast<LocalAnimeBodyItemData*>(args.extra.get());
if(std::holds_alternative<LocalAnime>(*item_data->anime_item)) {
const LocalAnime &anime = std::get<LocalAnime>(*item_data->anime_item);
- result_tabs.push_back(Tab{ create_body(false, true), std::make_unique<LocalAnimeSearchPage>(program, anime.items, this), create_search_bar("Search...", SEARCH_DELAY_FILTER) });
+ auto page = std::make_unique<LocalAnimeSearchPage>(program, anime.items, this);
+ page->title = anime.name;
+ result_tabs.push_back(Tab{ create_body(false, true), std::move(page), create_search_bar("Search...", SEARCH_DELAY_FILTER) });
return PluginResult::OK;
} else if(std::holds_alternative<LocalAnimeSeason>(*item_data->anime_item)) {
const LocalAnimeSeason &season = std::get<LocalAnimeSeason>(*item_data->anime_item);
- result_tabs.push_back(Tab{ create_body(false, true), std::make_unique<LocalAnimeSearchPage>(program, season.episodes, this), create_search_bar("Search...", SEARCH_DELAY_FILTER) });
+ auto page = std::make_unique<LocalAnimeSearchPage>(program, season.episodes, this);
+ page->title = title + " - " + season.name;
+ result_tabs.push_back(Tab{ create_body(false, true), std::move(page), create_search_bar("Search...", SEARCH_DELAY_FILTER) });
return PluginResult::OK;
} else if(std::holds_alternative<LocalAnimeEpisode>(*item_data->anime_item)) {
const LocalAnimeEpisode &episode = std::get<LocalAnimeEpisode>(*item_data->anime_item);