aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AsyncImageLoader.cpp29
-rw-r--r--src/Body.cpp92
-rw-r--r--src/QuickMedia.cpp55
3 files changed, 84 insertions, 92 deletions
diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp
index 947f637..1769846 100644
--- a/src/AsyncImageLoader.cpp
+++ b/src/AsyncImageLoader.cpp
@@ -7,6 +7,7 @@
#include "../external/hash-library/sha256.h"
#include <sys/stat.h>
+#include <malloc.h>
#include <assert.h>
namespace QuickMedia {
@@ -212,6 +213,32 @@ namespace QuickMedia {
});
}
+ std::shared_ptr<ThumbnailData> AsyncImageLoader::get_thumbnail(const std::string &url, bool local, sf::Vector2i resize_target_size) {
+ // TODO: Instead of generating a new hash everytime to access thumbnail, cache the hash of the thumbnail url
+ auto &thumbnail_data = thumbnails[url];
+ if(!thumbnail_data)
+ thumbnail_data = std::make_shared<ThumbnailData>();
+ thumbnail_data->counter = counter;
+ load_thumbnail(url, local, resize_target_size, thumbnail_data);
+ return thumbnail_data;
+ }
+
+ void AsyncImageLoader::update() {
+ bool loaded_textures_changed = false;
+ for(auto it = thumbnails.begin(); it != thumbnails.end();) {
+ if(it->second->counter != counter) {
+ it = thumbnails.erase(it);
+ loaded_textures_changed = true;
+ } else {
+ ++it;
+ }
+ }
+
+ ++counter;
+ if(loaded_textures_changed)
+ malloc_trim(0);
+ }
+
int AsyncImageLoader::get_free_load_index() const {
for(int i = 0; i < NUM_IMAGE_LOAD_THREADS; ++i) {
if(!loading_image[i])
@@ -219,4 +246,4 @@ namespace QuickMedia {
}
return -1;
}
-} \ No newline at end of file
+}
diff --git a/src/Body.cpp b/src/Body.cpp
index 09d3051..803cece 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -144,7 +144,6 @@ namespace QuickMedia {
}
Body::~Body() {
- item_thumbnail_textures.clear();
items.clear();
malloc_trim(0);
}
@@ -334,7 +333,7 @@ namespace QuickMedia {
void Body::clear_cache() {
clear_text_cache();
- clear_thumbnails();
+ malloc_trim(0);
}
void Body::clear_text_cache() {
@@ -345,11 +344,6 @@ namespace QuickMedia {
}
}
- void Body::clear_thumbnails() {
- item_thumbnail_textures.clear();
- malloc_trim(0);
- }
-
BodyItem* Body::get_selected() const {
if(selected_item < 0 || selected_item >= (int)items.size() || !items[selected_item]->visible)
return nullptr;
@@ -580,7 +574,6 @@ namespace QuickMedia {
int num_items = items.size();
if(num_items == 0 || size.y <= 0.0f) {
- item_thumbnail_textures.clear();
for(auto &body_item : items) {
clear_body_item_cache(body_item.get());
if(body_item->embedded_item)
@@ -596,10 +589,6 @@ namespace QuickMedia {
return;
}
- for(auto &thumbnail_it : item_thumbnail_textures) {
- thumbnail_it.second->referenced = false;
- }
-
if(prev_selected_item < 0 || prev_selected_item >= (int)items.size()) {
prev_selected_item = selected_item;
}
@@ -848,15 +837,6 @@ namespace QuickMedia {
if(!items_cut_off_set)
items_cut_off = false;
- for(auto it = item_thumbnail_textures.begin(); it != item_thumbnail_textures.end();) {
- if(!it->second->referenced) {
- it = item_thumbnail_textures.erase(it);
- loaded_textures_changed = true;
- } else {
- ++it;
- }
- }
-
// TODO: Only do this for items that are not visible, do not loop all items.
// TODO: Improve performance! right now it can use up to 5-7% cpu with a lot of items!
for(auto &body_item : items) {
@@ -867,11 +847,6 @@ namespace QuickMedia {
clear_body_item_cache(body_item->embedded_item.get());
}
- if(loaded_textures_changed) {
- loaded_textures_changed = false;
- malloc_trim(0);
- }
-
mouse_left_clicked = false;
if(clicked_body_item) {
auto clicked_body_item_tmp = clicked_body_item; // tmp because below call to body_item_select_callback may call this same draw function
@@ -1116,18 +1091,10 @@ 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, bool include_embedded_item, bool merge_with_previous) {
- // TODO: Instead of generating a new hash everytime to access textures, cache the hash of the thumbnail url
+ sf::Vector2i thumbnail_size = get_item_thumbnail_size(item);
std::shared_ptr<ThumbnailData> item_thumbnail;
- if(draw_thumbnails && !item->thumbnail_url.empty()) {
- 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 && !item->thumbnail_url.empty())
+ item_thumbnail = AsyncImageLoader::get_instance().get_thumbnail(item->thumbnail_url, item->thumbnail_is_local, thumbnail_size);
if(body_item_render_callback && include_embedded_item)
body_item_render_callback(item);
@@ -1156,13 +1123,13 @@ namespace QuickMedia {
}
float text_offset_x = padding_x;
- if(draw_thumbnails && item_thumbnail && !merge_with_previous) {
+ if(item_thumbnail && !merge_with_previous) {
// TODO: Verify if this is safe. The thumbnail is being modified in another thread
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();
sf::Vector2f image_size_f(image_size.x, image_size.y);
- sf::Vector2f content_size = to_vec2f(get_item_thumbnail_size(item));
+ sf::Vector2f content_size = to_vec2f(thumbnail_size);
auto new_image_size = clamp_to_size(image_size_f, content_size);
auto image_scale = get_ratio(image_size_f, new_image_size);
image.setScale(image_scale);
@@ -1177,7 +1144,7 @@ namespace QuickMedia {
// We want the next image fallback to have the same size as the successful image rendering, because its likely the image fallback will have the same size (for example thumbnails on youtube)
//image_fallback.setSize(sf::Vector2f(width_ratio * image_size.x, height_ratio * image_size.y));
} else if(!item->thumbnail_url.empty()) {
- sf::Vector2f content_size = to_vec2f(get_item_thumbnail_size(item));
+ sf::Vector2f content_size = to_vec2f(thumbnail_size);
sf::Color fallback_color(52, 58, 70);
if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) {
@@ -1204,7 +1171,7 @@ namespace QuickMedia {
text_offset_x += image_padding_x + content_size.x;
}
} else if(item->thumbnail_size.x > 0) {
- text_offset_x += image_padding_x + get_item_thumbnail_size(item).x;
+ text_offset_x += image_padding_x + thumbnail_size.x;
}
const float timestamp_text_y = std::floor(item_pos.y + padding_y - std::floor(6.0f * get_ui_scale()));
@@ -1320,39 +1287,20 @@ namespace QuickMedia {
if(load_texture)
item->last_drawn_time = elapsed_time_sec;
+ sf::Vector2i content_size = get_item_thumbnail_size(item);
float image_height = 0.0f;
float text_offset_x = padding_x;
- if(draw_thumbnails && !item->thumbnail_url.empty() && !merge_with_previous) {
- sf::Vector2i content_size = get_item_thumbnail_size(item);
+ if(draw_thumbnails && load_texture && !item->thumbnail_url.empty() && !merge_with_previous) {
image_height = content_size.y;
-
- 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()) {
- if(load_texture) {
- 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;
- }
-
- if(load_texture && item_thumbnail) {
- item_thumbnail->referenced = true;
-
- if(!item->thumbnail_url.empty() && item_thumbnail->loading_state == LoadingState::NOT_LOADED)
- AsyncImageLoader::get_instance().load_thumbnail(item->thumbnail_url, item->thumbnail_is_local, content_size, item_thumbnail);
-
- if(item_thumbnail->loading_state == LoadingState::FINISHED_LOADING && item_thumbnail->image->getSize().x > 0 && item_thumbnail->image->getSize().y > 0) {
- 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->texture.setSmooth(true);
- //item_thumbnail->texture.generateMipmap();
- item_thumbnail->image.reset();
- item_thumbnail->loading_state = LoadingState::APPLIED_TO_TEXTURE;
- item_thumbnail->texture_applied_time.restart();
- loaded_textures_changed = true;
- }
+ std::shared_ptr<ThumbnailData> item_thumbnail = AsyncImageLoader::get_instance().get_thumbnail(item->thumbnail_url, item->thumbnail_is_local, content_size);
+
+ if(item_thumbnail && item_thumbnail->loading_state == LoadingState::FINISHED_LOADING && item_thumbnail->image->getSize().x > 0 && item_thumbnail->image->getSize().y > 0) {
+ 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->texture.setSmooth(true);
+ //item_thumbnail->texture.generateMipmap();
+ item_thumbnail->image.reset();
+ item_thumbnail->loading_state = LoadingState::APPLIED_TO_TEXTURE;
}
if(item_thumbnail && item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.getNativeHandle() != 0) {
@@ -1365,7 +1313,7 @@ namespace QuickMedia {
text_offset_x += image_padding_x + content_size.x;
}
} else if(item->thumbnail_size.x > 0) {
- text_offset_x += image_padding_x + get_item_thumbnail_size(item).x;
+ text_offset_x += image_padding_x + content_size.x;
}
if(load_texture)
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index a58b3d8..903c966 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -1547,7 +1547,6 @@ namespace QuickMedia {
if(tabs[selected_tab].page->is_single_page()) {
if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->clear();
if(new_tabs.size() == 1 && !new_tabs[0].page) {
- tabs[selected_tab].body->clear_thumbnails();
tabs[selected_tab].body = std::move(new_tabs[0].body);
tabs[selected_tab].page->submit_body_item = prev_selected_item;
return;
@@ -1871,7 +1870,6 @@ namespace QuickMedia {
if(associated_data.fetch_status == FetchStatus::LOADING && associated_data.fetch_type == FetchType::SEARCH && associated_data.fetch_future.ready()) {
if(!associated_data.search_text_updated) {
FetchResult fetch_result = associated_data.fetch_future.get();
- tabs[i].body->clear_thumbnails();
tabs[i].body->items = std::move(fetch_result.body_items);
tabs[i].body->select_first_item();
associated_data.fetched_page = 0;
@@ -1924,6 +1922,7 @@ namespace QuickMedia {
window.clear(back_color);
page_loop_render(window, tabs, selected_tab, tab_associated_data[selected_tab], json_chapters, ui_tabs);
+ AsyncImageLoader::get_instance().update();
window.display();
if(!tabs[selected_tab].body->items.empty() && tabs[selected_tab].body->is_last_item_fully_visible())
@@ -2442,6 +2441,8 @@ namespace QuickMedia {
break;
}
+ AsyncImageLoader::get_instance().update();
+
if(!video_loaded) {
window.clear(back_color);
load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f);
@@ -2697,6 +2698,7 @@ namespace QuickMedia {
load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f);
load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0);
window.draw(load_sprite);
+ AsyncImageLoader::get_instance().update();
window.display();
}
}
@@ -2952,6 +2954,7 @@ namespace QuickMedia {
current_page = PageType::IMAGES;
break;
}
+ AsyncImageLoader::get_instance().update();
window.display();
int focused_page = image_viewer.get_focused_page();
@@ -3071,6 +3074,8 @@ namespace QuickMedia {
});
};
+ bool redraw = true;
+
Entry comment_input("Press i to begin writing a comment...", &rounded_rectangle_shader);
comment_input.draw_background = false;
comment_input.set_editable(false);
@@ -3151,7 +3156,8 @@ namespace QuickMedia {
sf::Vector2f logo_size(std::floor(plugin_logo.getSize().x * logo_sprite.getScale().x), std::floor(plugin_logo.getSize().y * logo_sprite.getScale().y));
sf::Sprite file_to_upload_sprite;
- auto file_to_upload_thumbnail_data = std::make_shared<ThumbnailData>();
+ bool sprite_applied_texture = false;
+ std::shared_ptr<ThumbnailData> file_to_upload_thumbnail_data;
const float logo_file_to_upload_spacing = std::floor(10.0f * get_ui_scale());
@@ -3163,7 +3169,6 @@ namespace QuickMedia {
sf::Vector2f body_pos;
sf::Vector2f body_size;
- bool redraw = true;
sf::Event event;
std::stack<int> comment_navigation_stack;
@@ -3408,22 +3413,28 @@ namespace QuickMedia {
update_idle_state();
handle_window_close();
- if(!selected_file_for_upload.empty() && file_to_upload_thumbnail_data->loading_state == LoadingState::NOT_LOADED)
- AsyncImageLoader::get_instance().load_thumbnail(selected_file_for_upload, true, sf::Vector2i(logo_size.x, logo_size.y * 4), file_to_upload_thumbnail_data);
-
- if(selected_file_for_upload.empty() && file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE) {
- file_to_upload_thumbnail_data = std::make_unique<ThumbnailData>();
- redraw = true;
+ if(selected_file_for_upload.empty()) {
+ if(file_to_upload_thumbnail_data) {
+ file_to_upload_thumbnail_data.reset();
+ redraw = true;
+ }
+ } else {
+ file_to_upload_thumbnail_data = AsyncImageLoader::get_instance().get_thumbnail(selected_file_for_upload, true, sf::Vector2i(logo_size.x, logo_size.y * 4));
}
- if(file_to_upload_thumbnail_data->loading_state == LoadingState::FINISHED_LOADING && file_to_upload_thumbnail_data->image->getSize().x > 0 && file_to_upload_thumbnail_data->image->getSize().y > 0) {
+ if(file_to_upload_thumbnail_data && file_to_upload_thumbnail_data->loading_state == LoadingState::FINISHED_LOADING && file_to_upload_thumbnail_data->image->getSize().x > 0 && file_to_upload_thumbnail_data->image->getSize().y > 0) {
if(!file_to_upload_thumbnail_data->texture.loadFromImage(*file_to_upload_thumbnail_data->image))
fprintf(stderr, "Warning: failed to load texture for attached file\n");
file_to_upload_thumbnail_data->texture.setSmooth(true);
//room_avatar_thumbnail_data->texture.generateMipmap();
file_to_upload_thumbnail_data->image.reset();
file_to_upload_thumbnail_data->loading_state = LoadingState::APPLIED_TO_TEXTURE;
+ sprite_applied_texture = false;
+ }
+
+ if(file_to_upload_thumbnail_data && file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE && !sprite_applied_texture) {
file_to_upload_sprite.setTexture(file_to_upload_thumbnail_data->texture, true);
+ sprite_applied_texture = true;
sf::Vector2f texture_size_f(file_to_upload_thumbnail_data->texture.getSize().x, file_to_upload_thumbnail_data->texture.getSize().y);
sf::Vector2f image_scale = get_ratio(texture_size_f, clamp_to_size_x(texture_size_f, logo_size));
@@ -3432,7 +3443,7 @@ namespace QuickMedia {
}
float chat_input_height_full_images = logo_size.y;
- if(file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE) {
+ if(file_to_upload_thumbnail_data && file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE) {
const float file_to_upload_height = std::floor(logo_file_to_upload_spacing + file_to_upload_sprite.getTexture()->getSize().y * file_to_upload_sprite.getScale().y);
chat_input_height_full_images += file_to_upload_height;
}
@@ -3554,18 +3565,19 @@ namespace QuickMedia {
} else if(navigation_stage == NavigationStage::REPLYING) {
window.draw(comment_input_shade);
window.draw(logo_sprite);
- if(file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE)
+ if(file_to_upload_thumbnail_data && file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE)
window.draw(file_to_upload_sprite);
comment_input.draw(window);
thread_body->draw(window, body_pos, body_size);
} else if(navigation_stage == NavigationStage::VIEWING_COMMENTS) {
window.draw(comment_input_shade);
window.draw(logo_sprite);
- if(file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE)
+ if(file_to_upload_thumbnail_data && file_to_upload_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE)
window.draw(file_to_upload_sprite);
comment_input.draw(window);
thread_body->draw(window, body_pos, body_size);
}
+ AsyncImageLoader::get_instance().update();
window.display();
}
}
@@ -3672,6 +3684,7 @@ namespace QuickMedia {
inputs[i]->update();
inputs[i]->draw(window, background.get_size() - sf::Vector2f(padding_x * 2.0f, 0.0f), false);
}
+ AsyncImageLoader::get_instance().update();
window.display();
}
}
@@ -4170,7 +4183,6 @@ namespace QuickMedia {
std::string room_topic = current_room->get_topic();
room_name_text.setString(sf::String::fromUtf8(room_name.begin(), room_name.end()));
room_topic_text.setString(sf::String::fromUtf8(room_topic.begin(), room_topic.end()));
- room_avatar_thumbnail_data = std::make_shared<ThumbnailData>();
read_marker_timeout_ms = 0;
redraw = true;
@@ -5215,8 +5227,8 @@ namespace QuickMedia {
typing_state_queue.push(false);
}
- if(current_room && current_room->body_item && room_avatar_thumbnail_data->loading_state == LoadingState::NOT_LOADED)
- AsyncImageLoader::get_instance().load_thumbnail(current_room->body_item->thumbnail_url, false, AVATAR_THUMBNAIL_SIZE, room_avatar_thumbnail_data);
+ if(!current_room->body_item->thumbnail_url.empty())
+ room_avatar_thumbnail_data = AsyncImageLoader::get_instance().get_thumbnail(current_room->body_item->thumbnail_url, false, AVATAR_THUMBNAIL_SIZE);
if(room_avatar_thumbnail_data->loading_state == LoadingState::FINISHED_LOADING && room_avatar_thumbnail_data->image->getSize().x > 0 && room_avatar_thumbnail_data->image->getSize().y > 0) {
if(!room_avatar_thumbnail_data->texture.loadFromImage(*room_avatar_thumbnail_data->image))
@@ -5225,8 +5237,10 @@ namespace QuickMedia {
//room_avatar_thumbnail_data->texture.generateMipmap();
room_avatar_thumbnail_data->image.reset();
room_avatar_thumbnail_data->loading_state = LoadingState::APPLIED_TO_TEXTURE;
- room_avatar_sprite.setTexture(room_avatar_thumbnail_data->texture, true);
+ }
+ if(room_avatar_thumbnail_data->loading_state == LoadingState::APPLIED_TO_TEXTURE && !room_avatar_sprite.getTexture()) {
+ room_avatar_sprite.setTexture(room_avatar_thumbnail_data->texture, true);
auto texture_size = room_avatar_sprite.getTexture()->getSize();
if(texture_size.x > 0 && texture_size.y > 0) {
float width_ratio = (float)texture_size.x / (float)texture_size.y;
@@ -5234,6 +5248,7 @@ namespace QuickMedia {
float width_scale = height_scale * width_ratio;
room_avatar_sprite.setScale(width_scale * get_ui_scale(), height_scale * get_ui_scale());
}
+ redraw = true;
}
const int selected_tab = ui_tabs.get_selected();
@@ -5549,6 +5564,7 @@ namespace QuickMedia {
}
}
+ AsyncImageLoader::get_instance().update();
window.display();
if(selected_tab == MESSAGES_TAB_INDEX)
@@ -6158,6 +6174,7 @@ namespace QuickMedia {
window.draw(status_text);
window.draw(filename_text);
window.draw(download_speed_text);
+ AsyncImageLoader::get_instance().update();
window.display();
frame_timer.restart();
}
@@ -6233,7 +6250,6 @@ namespace QuickMedia {
if(task_result == TaskResult::TRUE) {
if(!new_tabs.empty()) {
- file_manager_body->clear_thumbnails();
file_manager_body->items = std::move(new_tabs[0].body->items);
file_manager_body->select_first_item();
search_bar->clear();
@@ -6371,6 +6387,7 @@ namespace QuickMedia {
save_button.draw(window);
file_name_entry.draw(window);
+ AsyncImageLoader::get_instance().update();
window.display();
}