Compare commits

..

2 Commits

11 changed files with 247 additions and 16 deletions

View File

@ -15,6 +15,8 @@ add_executable(tomato
./auto_dirty.hpp ./auto_dirty.hpp
./auto_dirty.cpp ./auto_dirty.cpp
./theme.hpp
./image_loader.hpp ./image_loader.hpp
./image_loader_sdl_bmp.hpp ./image_loader_sdl_bmp.hpp
./image_loader_sdl_bmp.cpp ./image_loader_sdl_bmp.cpp
@ -23,16 +25,23 @@ add_executable(tomato
./image_loader_webp.hpp ./image_loader_webp.hpp
./image_loader_webp.cpp ./image_loader_webp.cpp
./theme.hpp
./texture_uploader.hpp ./texture_uploader.hpp
./sdlrenderer_texture_uploader.hpp ./sdlrenderer_texture_uploader.hpp
./sdlrenderer_texture_uploader.cpp ./sdlrenderer_texture_uploader.cpp
./texture_cache.hpp ./texture_cache.hpp
./texture_cache.cpp ./texture_cache.cpp
./tox_avatar_loader.hpp ./tox_avatar_loader.hpp
./tox_avatar_loader.cpp ./tox_avatar_loader.cpp
./message_image_loader.hpp
./message_image_loader.cpp
./media_meta_info_loader.hpp
./media_meta_info_loader.cpp
./sdl_clipboard_utils.hpp ./sdl_clipboard_utils.hpp
./sdl_clipboard_utils.cpp ./sdl_clipboard_utils.cpp
./file_selector.hpp ./file_selector.hpp
./file_selector.cpp ./file_selector.cpp

View File

@ -6,13 +6,13 @@
#include <solanaceae/tox_messages/components.hpp> #include <solanaceae/tox_messages/components.hpp>
#include <solanaceae/contact/components.hpp> #include <solanaceae/contact/components.hpp>
//#include "./media_meta_info_loader.hpp"
#include <imgui/imgui.h> #include <imgui/imgui.h>
#include <imgui/misc/cpp/imgui_stdlib.h> #include <imgui/misc/cpp/imgui_stdlib.h>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include "./media_meta_info_loader.hpp"
#include "./sdl_clipboard_utils.hpp" #include "./sdl_clipboard_utils.hpp"
#include <string> #include <string>
@ -27,7 +27,7 @@ ChatGui4::ChatGui4(
RegistryMessageModel& rmm, RegistryMessageModel& rmm,
Contact3Registry& cr, Contact3Registry& cr,
TextureUploaderI& tu TextureUploaderI& tu
) : _conf(conf), _rmm(rmm), _cr(cr), _tal(_cr), _contact_tc(_tal, tu) { ) : _conf(conf), _rmm(rmm), _cr(cr), _tal(_cr), _contact_tc(_tal, tu), _msg_tc(_mil, tu) {
} }
void ChatGui4::render(void) { void ChatGui4::render(void) {
@ -42,6 +42,7 @@ void ChatGui4::render(void) {
// ACTUALLY NOT IF RENDERED, MOVED LOGIC TO ABOVE // ACTUALLY NOT IF RENDERED, MOVED LOGIC TO ABOVE
// it might unload textures, so it needs to be done before rendering // it might unload textures, so it needs to be done before rendering
_contact_tc.update(); _contact_tc.update();
_msg_tc.update();
const ImGuiViewport* viewport = ImGui::GetMainViewport(); const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos); ImGui::SetNextWindowPos(viewport->WorkPos);
@ -294,6 +295,7 @@ void ChatGui4::render(void) {
_fss.render(); _fss.render();
_contact_tc.workLoadQueue(); _contact_tc.workLoadQueue();
_msg_tc.workLoadQueue();
} }
// has MessageText // has MessageText
@ -400,14 +402,11 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
ImGui::Bullet(); ImGui::Text("%s (%lu)", file_list[i].file_name.c_str(), file_list[i].file_size); ImGui::Bullet(); ImGui::Text("%s (%lu)", file_list[i].file_name.c_str(), file_list[i].file_size);
} }
#if 0
// TODO: use frame dims
if (file_list.size() == 1 && reg.all_of<Message::Components::Transfer::FileInfoLocal, Message::Components::FrameDims>(e)) { if (file_list.size() == 1 && reg.all_of<Message::Components::Transfer::FileInfoLocal, Message::Components::FrameDims>(e)) {
auto [id, width, height] = _tc.get(reg.get<Message::Components::Transfer::FileInfoLocal>(e).file_list.front()); auto [id, width, height] = _msg_tc.get(Message3Handle{reg, e});
// if cache gives 0s, fall back to frame dims (eg if pic not loaded yet) // if cache gives 0s, fall back to frame dims (eg if pic not loaded yet)
if (width > 0 || height > 0) { if (width == 0 || height == 0) {
const auto& frame_dims = reg.get<Message::Components::FrameDims>(e); const auto& frame_dims = reg.get<Message::Components::FrameDims>(e);
width = frame_dims.width; width = frame_dims.width;
height = frame_dims.height; height = frame_dims.height;
@ -420,9 +419,9 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
height = max_inline_height; height = max_inline_height;
width *= scale; width *= scale;
} }
ImGui::Image(id, ImVec2{static_cast<float>(width), static_cast<float>(height)}); ImGui::Image(id, ImVec2{static_cast<float>(width), static_cast<float>(height)});
} }
#endif
} }
void ChatGui4::renderMessageExtra(Message3Registry& reg, const Message3 e) { void ChatGui4::renderMessageExtra(Message3Registry& reg, const Message3 e) {
@ -529,7 +528,6 @@ bool ChatGui4::renderContactListContactBig(const Contact3 c) {
} }
// avatar // avatar
#if 1
const auto [id, width, height] = _contact_tc.get(c); const auto [id, width, height] = _contact_tc.get(c);
ImGui::Image( ImGui::Image(
id, id,
@ -539,9 +537,6 @@ bool ChatGui4::renderContactListContactBig(const Contact3 c) {
{1, 1, 1, 1}, {1, 1, 1, 1},
color_current color_current
); );
#else
ImGui::Dummy({img_y, img_y});
#endif
ImGui::SameLine(); ImGui::SameLine();
ImGui::BeginGroup(); ImGui::BeginGroup();

View File

@ -6,6 +6,7 @@
#include "./texture_uploader.hpp" #include "./texture_uploader.hpp"
#include "./texture_cache.hpp" #include "./texture_cache.hpp"
#include "./tox_avatar_loader.hpp" #include "./tox_avatar_loader.hpp"
#include "./message_image_loader.hpp"
#include "./file_selector.hpp" #include "./file_selector.hpp"
#include <vector> #include <vector>
@ -18,7 +19,8 @@ class ChatGui4 {
ToxAvatarLoader _tal; ToxAvatarLoader _tal;
TextureCache<void*, Contact3, ToxAvatarLoader> _contact_tc; TextureCache<void*, Contact3, ToxAvatarLoader> _contact_tc;
//TextureCache<Message3Handle> _msg_tc; MessageImageLoader _mil;
TextureCache<void*, Message3Handle, MessageImageLoader> _msg_tc;
FileSelector _fss; FileSelector _fss;

View File

@ -2,6 +2,8 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <iostream>
ImageLoaderSDLBMP::ImageInfo ImageLoaderSDLBMP::loadInfoFromMemory(const uint8_t* data, uint64_t data_size) { ImageLoaderSDLBMP::ImageInfo ImageLoaderSDLBMP::loadInfoFromMemory(const uint8_t* data, uint64_t data_size) {
ImageInfo res; ImageInfo res;
@ -48,6 +50,8 @@ ImageLoaderSDLBMP::ImageResult ImageLoaderSDLBMP::loadFromMemoryRGBA(const uint8
SDL_UnlockSurface(conv_surf); SDL_UnlockSurface(conv_surf);
SDL_DestroySurface(conv_surf); SDL_DestroySurface(conv_surf);
std::cout << "IL_SDLBMP: loaded img " << res.width << "x" << res.height << "\n";
return res; return res;
} }

View File

@ -15,6 +15,7 @@ MainScreen::MainScreen(SDL_Renderer* renderer_, std::string save_path) :
tcm(cr, tc, tc), tcm(cr, tc, tc),
tmm(rmm, cr, tcm, tc, tc), tmm(rmm, cr, tcm, tc, tc),
ttm(rmm, cr, tcm, tc, tc), ttm(rmm, cr, tcm, tc, tc),
mmil(rmm),
sdlrtu(renderer_), sdlrtu(renderer_),
cg(conf, rmm, cr, sdlrtu) cg(conf, rmm, cr, sdlrtu)
{ {

View File

@ -16,6 +16,8 @@
#include "./tox_client.hpp" #include "./tox_client.hpp"
#include "./auto_dirty.hpp" #include "./auto_dirty.hpp"
#include "./media_meta_info_loader.hpp"
#include "./sdlrenderer_texture_uploader.hpp" #include "./sdlrenderer_texture_uploader.hpp"
#include "./chat_gui4.hpp" #include "./chat_gui4.hpp"
@ -47,6 +49,8 @@ struct MainScreen final : public Screen {
ToxMessageManager tmm; ToxMessageManager tmm;
ToxTransferManager ttm; ToxTransferManager ttm;
MediaMetaInfoLoader mmil;
SDLRendererTextureUploader sdlrtu; SDLRendererTextureUploader sdlrtu;
//OpenGLTextureUploader ogltu; //OpenGLTextureUploader ogltu;

View File

@ -0,0 +1,84 @@
#include "./media_meta_info_loader.hpp"
#include "./image_loader_webp.hpp"
#include "./image_loader_sdl_bmp.hpp"
#include "./image_loader_stb.hpp"
#include <solanaceae/message3/components.hpp>
#include <fstream>
#include <iostream>
MediaMetaInfoLoader::MediaMetaInfoLoader(RegistryMessageModel& rmm) : _rmm(rmm) {
// HACK: make them be added externally?
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct);
_rmm.subscribe(this, RegistryMessageModel_Event::message_updated);
}
MediaMetaInfoLoader::~MediaMetaInfoLoader(void) {
}
bool MediaMetaInfoLoader::onEvent(const Message::Events::MessageConstruct& e) {
return false;
}
bool MediaMetaInfoLoader::onEvent(const Message::Events::MessageUpdated& e) {
if (e.e.any_of<Message::Components::TagNotImage, Message::Components::FrameDims>()) {
return false;
}
if (!e.e.all_of<Message::Components::Transfer::FileInfoLocal, Message::Components::Transfer::TagHaveAll>()) {
return false;
}
const auto& fil = e.e.get<Message::Components::Transfer::FileInfoLocal>();
if (fil.file_list.size() != 1) {
return false;
}
std::ifstream file(fil.file_list.front(), std::ios::binary);
if (file.is_open()) {
std::vector<uint8_t> tmp_buffer;
while (file.good()) {
auto ch = file.get();
if (ch == EOF) {
break;
} else {
tmp_buffer.push_back(ch);
}
}
bool could_load {false};
// try all loaders after another
for (auto& il : _image_loaders) {
auto res = il->loadInfoFromMemory(tmp_buffer.data(), tmp_buffer.size());
if (res.height == 0 || res.width == 0) {
continue;
}
e.e.emplace<Message::Components::FrameDims>(res.width, res.height);
could_load = true;
std::cout << "MMIL loaded image info " << fil.file_list.front() << "\n";
_rmm.throwEventUpdate(e.e);
break;
}
if (!could_load) {
e.e.emplace<Message::Components::TagNotImage>();
std::cout << "MMIL loading failed image info " << fil.file_list.front() << "\n";
_rmm.throwEventUpdate(e.e);
}
}
return false;
}

View File

@ -0,0 +1,33 @@
#pragma once
#include <solanaceae/message3/registry_message_model.hpp>
#include "./image_loader.hpp"
namespace Message::Components {
struct FrameDims {
uint32_t width {0};
uint32_t height {0};
};
struct TagNotImage {};
} // Message::Components
// adds metadata to file messages
class MediaMetaInfoLoader : public RegistryMessageModelEventI {
protected:
RegistryMessageModel& _rmm;
std::vector<std::unique_ptr<ImageLoaderI>> _image_loaders;
public:
MediaMetaInfoLoader(RegistryMessageModel& rmm);
virtual ~MediaMetaInfoLoader(void);
protected: // rmm
bool onEvent(const Message::Events::MessageConstruct& e) override;
bool onEvent(const Message::Events::MessageUpdated& e) override;
};

View File

@ -0,0 +1,72 @@
#include "./message_image_loader.hpp"
#include "./image_loader_sdl_bmp.hpp"
#include "./image_loader_stb.hpp"
#include "./image_loader_webp.hpp"
#include <solanaceae/message3/components.hpp>
#include <iostream>
#include <fstream>
#include <cassert>
#include <vector>
MessageImageLoader::MessageImageLoader(void) {
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
}
std::optional<TextureEntry> MessageImageLoader::load(TextureUploaderI& tu, Message3Handle m) {
if (!static_cast<bool>(m)) {
return std::nullopt;
}
if (m.all_of<Message::Components::Transfer::FileInfoLocal>()) {
const auto& file_list = m.get<Message::Components::Transfer::FileInfoLocal>().file_list;
assert(!file_list.empty());
const auto& file_path = file_list.front();
std::ifstream file(file_path, std::ios::binary);
if (file.is_open()) {
std::vector<uint8_t> tmp_buffer;
while (file.good()) {
auto ch = file.get();
if (ch == EOF) {
break;
} else {
tmp_buffer.push_back(ch);
}
}
// try all loaders after another
for (auto& il : _image_loaders) {
auto res = il->loadFromMemoryRGBA(tmp_buffer.data(), tmp_buffer.size());
if (res.frames.empty() || res.height == 0 || res.width == 0) {
continue;
}
TextureEntry new_entry;
new_entry.timestamp_last_rendered = getNowMS();
new_entry.current_texture = 0;
for (const auto& [ms, data] : res.frames) {
const auto n_t = tu.uploadRGBA(data.data(), res.width, res.height);
new_entry.textures.push_back(n_t);
new_entry.frame_duration.push_back(ms);
}
new_entry.width = res.width;
new_entry.height = res.height;
std::cout << "MIL: loaded image file " << file_path << "\n";
return new_entry;
}
}
}
std::cerr << "MIL: failed to load message\n";
return std::nullopt;
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <solanaceae/message3/registry_message_model.hpp>
#include "./image_loader.hpp"
#include "./texture_cache.hpp"
#include <optional>
class MessageImageLoader {
std::vector<std::unique_ptr<ImageLoaderI>> _image_loaders;
public:
MessageImageLoader(void);
std::optional<TextureEntry> load(TextureUploaderI& tu, Message3Handle c);
};
// TODO: move to rmm
template<>
struct std::hash<Message3Handle> {
std::size_t operator()(Message3Handle const& m) const noexcept {
const std::size_t h1 = reinterpret_cast<std::size_t>(m.registry());
const std::size_t h2 = entt::to_integral(m.entity());
return (h1 << 3) ^ (h2 * 11400714819323198485llu);
}
};

View File

@ -49,8 +49,8 @@ TextureEntry generateTestAnim(TextureUploaderI& tu) {
new_entry.textures.emplace_back(n_t); new_entry.textures.emplace_back(n_t);
new_entry.frame_duration.emplace_back(250); new_entry.frame_duration.emplace_back(250);
} }
new_entry.width = 2; new_entry.width = 0;
new_entry.height = 2; new_entry.height = 0;
return new_entry; return new_entry;
} }