aboutsummaryrefslogtreecommitdiff
path: root/src/Body.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Body.cpp')
-rw-r--r--src/Body.cpp117
1 files changed, 66 insertions, 51 deletions
diff --git a/src/Body.cpp b/src/Body.cpp
index 25a7bc3..477591e 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -86,6 +86,11 @@ namespace QuickMedia {
item_background.setFillColor(sf::Color(55, 60, 68));
}
+ Body::~Body() {
+ if(load_thumbnail_future.valid())
+ load_thumbnail_future.get();
+ }
+
bool Body::select_previous_item() {
if(items.empty())
return false;
@@ -292,65 +297,49 @@ namespace QuickMedia {
// TODO: Do not load thumbnails for images larger than 30mb.
// TODO: Load the thumbnail embedded in the file instead.
- std::shared_ptr<sf::Texture> Body::load_thumbnail_from_url(const std::string &url, bool local, sf::Vector2i thumbnail_resize_target_size) {
- auto result = std::make_shared<sf::Texture>();
- result->setSmooth(true);
+ void Body::load_thumbnail_from_url(const std::string &url, bool local, sf::Vector2i thumbnail_resize_target_size, std::shared_ptr<ThumbnailData> thumbnail_data) {
assert(!loading_thumbnail);
loading_thumbnail = true;
- thumbnail_load_thread = std::thread([this, result, url, local, thumbnail_resize_target_size]() {
+
+ load_thumbnail_future = std::async(std::launch::async, [this, url, local, thumbnail_resize_target_size, thumbnail_data]() {
// TODO: Use sha256 instead of base64_url encoding
Path thumbnail_path = get_cache_dir().join("thumbnails").join(base64_url::encode(url));
- std::string texture_data;
- if(file_get_content(thumbnail_path, texture_data) == 0) {
+ thumbnail_data->image = std::make_unique<sf::Image>();
+ if(thumbnail_data->image->loadFromFile(thumbnail_path.data)) {
fprintf(stderr, "Loaded %s from thumbnail cache\n", url.c_str());
- result->loadFromMemory(texture_data.data(), texture_data.size());
- loading_thumbnail = false;
+ thumbnail_data->loading_state = LoadingState::FINISHED_LOADING;
return;
} else {
if(local) {
- if(file_get_content(url, texture_data) != 0) {
- loading_thumbnail = false;
+ if(!thumbnail_data->image->loadFromFile(url)) {
+ thumbnail_data->loading_state = LoadingState::FINISHED_LOADING;
return;
}
} else {
- if(download_to_string_cache(url, texture_data, {}, program->get_current_plugin()->use_tor, true) != DownloadResult::OK) {
- loading_thumbnail = false;
+ std::string texture_data;
+ if(download_to_string_cache(url, texture_data, {}, program->get_current_plugin()->use_tor, true) != DownloadResult::OK || !thumbnail_data->image->loadFromMemory(texture_data.data(), texture_data.size())) {
+ thumbnail_data->loading_state = LoadingState::FINISHED_LOADING;
return;
}
}
}
if(thumbnail_resize_target_size.x != 0 && thumbnail_resize_target_size.y != 0) {
- auto image = std::make_unique<sf::Image>();
- // TODO: Load from file instead? decreases ram usage and we save to file above anyways
- if(image->loadFromMemory(texture_data.data(), texture_data.size())) {
- texture_data.resize(0);
- sf::Vector2u new_image_size = to_vec2u(clamp_to_size(to_vec2f(image->getSize()), to_vec2f(thumbnail_resize_target_size)));
- if(new_image_size.x < image->getSize().x || new_image_size.y < image->getSize().y) {
- sf::Image destination_image;
- copy_resize(*image, destination_image, new_image_size);
- if(save_image_as_thumbnail_atomic(destination_image, thumbnail_path, get_ext(url))) {
- image.reset();
- result->loadFromImage(destination_image);
- } else {
- result->loadFromImage(*image);
- }
- loading_thumbnail = false;
- return;
- } else {
- result->loadFromImage(*image);
- loading_thumbnail = false;
- return;
- }
+ sf::Vector2u new_image_size = to_vec2u(clamp_to_size(to_vec2f(thumbnail_data->image->getSize()), to_vec2f(thumbnail_resize_target_size)));
+ if(new_image_size.x < thumbnail_data->image->getSize().x || new_image_size.y < thumbnail_data->image->getSize().y) {
+ auto destination_image = std::make_unique<sf::Image>();
+ copy_resize(*thumbnail_data->image, *destination_image, new_image_size);
+ thumbnail_data->image = std::move(destination_image);
+ save_image_as_thumbnail_atomic(*thumbnail_data->image, thumbnail_path, get_ext(url));
+ thumbnail_data->loading_state = LoadingState::FINISHED_LOADING;
+ return;
}
}
- result->loadFromMemory(texture_data.data(), texture_data.size());
- loading_thumbnail = false;
+ thumbnail_data->loading_state = LoadingState::FINISHED_LOADING;
+ return;
});
- thumbnail_load_thread.detach();
- return result;
}
void Body::draw(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size) {
@@ -376,10 +365,15 @@ namespace QuickMedia {
image_fallback.setSize(thumbnail_fallback_size);
item_background_shadow.setFillColor(line_seperator_color);
+ if(loading_thumbnail && load_thumbnail_future.valid() && load_thumbnail_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
+ load_thumbnail_future.get();
+ loading_thumbnail = false;
+ }
+
int num_items = items.size();
if(num_items == 0 || size.y <= 0.0f) {
for(auto it = item_thumbnail_textures.begin(); it != item_thumbnail_textures.end();) {
- if(!it->second.referenced)
+ if(!it->second->referenced)
it = item_thumbnail_textures.erase(it);
else
++it;
@@ -388,7 +382,7 @@ namespace QuickMedia {
}
for(auto &thumbnail_it : item_thumbnail_textures) {
- thumbnail_it.second.referenced = false;
+ thumbnail_it.second->referenced = false;
}
for(auto &body_item : items) {
@@ -503,7 +497,7 @@ namespace QuickMedia {
glDisable(GL_SCISSOR_TEST);
for(auto it = item_thumbnail_textures.begin(); it != item_thumbnail_textures.end();) {
- if(!it->second.referenced)
+ if(!it->second->referenced)
it = item_thumbnail_textures.erase(it);
else
++it;
@@ -512,14 +506,27 @@ namespace QuickMedia {
void Body::draw_item(sf::RenderWindow &window, BodyItem *item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress) {
// TODO: Instead of generating a new hash everytime to access textures, cache the hash of the thumbnail url
- // Intentionally create the item with the key item->thumbnail_url if it doesn't exist
- item_thumbnail_textures[item->thumbnail_url].referenced = true;
- auto &item_thumbnail = item_thumbnail_textures[item->thumbnail_url];
+ std::shared_ptr<ThumbnailData> item_thumbnail;
+ auto item_thumbnail_it = item_thumbnail_textures.find(item->thumbnail_url);
+ if(item_thumbnail_it == item_thumbnail_textures.end()) {
+ item_thumbnail = std::make_shared<ThumbnailData>();
+ item_thumbnail_textures.insert(std::make_pair(item->thumbnail_url, item_thumbnail));
+ } else {
+ item_thumbnail = item_thumbnail_it->second;
+ }
+ item_thumbnail->referenced = true;
if(draw_thumbnails) {
- if(!item->thumbnail_url.empty() && !loading_thumbnail && !item_thumbnail.loaded && !item_thumbnail.texture) {
- item_thumbnail.loaded = true;
- item_thumbnail.texture = load_thumbnail_from_url(item->thumbnail_url, item->thumbnail_is_local, thumbnail_resize_target_size);
+ if(!loading_thumbnail && !item->thumbnail_url.empty() && item_thumbnail->loading_state == LoadingState::NOT_LOADED) {
+ item_thumbnail->loading_state = LoadingState::LOADING;
+ load_thumbnail_from_url(item->thumbnail_url, item->thumbnail_is_local, thumbnail_resize_target_size, item_thumbnail);
+ }
+
+ if(item_thumbnail->loading_state == LoadingState::FINISHED_LOADING) {
+ if(!item_thumbnail->texture.loadFromImage(*item_thumbnail->image))
+ fprintf(stderr, "Warning: failed to load texture from image: %s\n", item->thumbnail_url.c_str());
+ item_thumbnail->image.reset();
+ item_thumbnail->loading_state = LoadingState::APPLIED_TO_TEXTURE;
}
}
@@ -541,8 +548,8 @@ namespace QuickMedia {
if(draw_thumbnails) {
// TODO: Verify if this is safe. The thumbnail is being modified in another thread
// and it might not be fully finished before the native handle is set?
- if(item_thumbnail.loaded && item_thumbnail.texture && item_thumbnail.texture->getNativeHandle() != 0) {
- image.setTexture(*item_thumbnail.texture, true);
+ if(item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.getNativeHandle() != 0) {
+ image.setTexture(item_thumbnail->texture, true);
auto image_size = image.getTexture()->getSize();
auto height_ratio = std::min(image_max_height, (float)image_size.y) / image_size.y;
auto scale = image.getScale();
@@ -628,10 +635,18 @@ namespace QuickMedia {
item_height += item->description_text->getHeight() - 2.0f;
}
if(draw_thumbnails && !item->thumbnail_url.empty()) {
- auto &item_thumbnail = item_thumbnail_textures[item->thumbnail_url];
+ std::shared_ptr<ThumbnailData> item_thumbnail;
+ auto item_thumbnail_it = item_thumbnail_textures.find(item->thumbnail_url);
+ if(item_thumbnail_it == item_thumbnail_textures.end()) {
+ item_thumbnail = std::make_shared<ThumbnailData>();
+ item_thumbnail_textures.insert(std::make_pair(item->thumbnail_url, item_thumbnail));
+ } else {
+ item_thumbnail = item_thumbnail_it->second;
+ }
+
float image_height = image_fallback.getSize().y;
- if(item_thumbnail.texture && item_thumbnail.texture->getNativeHandle() != 0) {
- auto image_size = item_thumbnail.texture->getSize();
+ if(item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.getNativeHandle() != 0) {
+ auto image_size = item_thumbnail->texture.getSize();
image_height = std::min(image_max_height, (float)image_size.y);
}
item_height = std::max(item_height, image_height);