diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 993703c6..cfce88e0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -107,6 +107,9 @@ target_sources(tomato PUBLIC ./frame_streams/audio_stream2.hpp ./frame_streams/stream_manager.hpp ./frame_streams/stream_manager.cpp + + ./stream_manager_ui.hpp + ./stream_manager_ui.cpp ) if (TOMATO_TOX_AV) diff --git a/src/main_screen.cpp b/src/main_screen.cpp index 8454f9e1..79902a0f 100644 --- a/src/main_screen.cpp +++ b/src/main_screen.cpp @@ -42,7 +42,8 @@ MainScreen::MainScreen(SimpleConfigModel&& conf_, SDL_Renderer* renderer_, Theme sw(conf), osui(os), tuiu(tc, conf), - tdch(tpi) + tdch(tpi), + smui(os, sm) { tel.subscribeAll(tc); @@ -261,6 +262,7 @@ Screen* MainScreen::render(float time_delta, bool&) { osui.render(); tuiu.render(); // render tdch.render(); // render + smui.render(); { // main window menubar injection if (ImGui::Begin("tomato")) { diff --git a/src/main_screen.hpp b/src/main_screen.hpp index 51721efe..42f11254 100644 --- a/src/main_screen.hpp +++ b/src/main_screen.hpp @@ -34,6 +34,7 @@ #include "./tox_ui_utils.hpp" #include "./tox_dht_cap_histo.hpp" #include "./tox_friend_faux_offline_messaging.hpp" +#include "./stream_manager_ui.hpp" #if TOMATO_TOX_AV #include "./tox_av.hpp" @@ -91,6 +92,7 @@ struct MainScreen final : public Screen { ObjectStoreUI osui; ToxUIUtils tuiu; ToxDHTCapHisto tdch; + StreamManagerUI smui; PluginManager pm; // last, so it gets destroyed first diff --git a/src/sdlrenderer_texture_uploader.cpp b/src/sdlrenderer_texture_uploader.cpp index 66b810cf..4ea9b675 100644 --- a/src/sdlrenderer_texture_uploader.cpp +++ b/src/sdlrenderer_texture_uploader.cpp @@ -32,7 +32,7 @@ uint64_t SDLRendererTextureUploader::uploadRGBA(const uint8_t* data, uint32_t wi SDL_UpdateTexture(tex, nullptr, surf->pixels, surf->pitch); SDL_BlendMode surf_blend_mode = SDL_BLENDMODE_NONE; - if (SDL_GetSurfaceBlendMode(surf, &surf_blend_mode) == 0) { + if (SDL_GetSurfaceBlendMode(surf, &surf_blend_mode)) { SDL_SetTextureBlendMode(tex, surf_blend_mode); } diff --git a/src/stream_manager_ui.cpp b/src/stream_manager_ui.cpp new file mode 100644 index 00000000..57b6332a --- /dev/null +++ b/src/stream_manager_ui.cpp @@ -0,0 +1,222 @@ +#include "./stream_manager_ui.hpp" + +#include + +#include + +#include + +StreamManagerUI::StreamManagerUI(ObjectStore2& os, StreamManager& sm) : _os(os), _sm(sm) { +} + +void StreamManagerUI::render(void) { + { // main window menubar injection + // assumes the window "tomato" was rendered already by cg + if (ImGui::Begin("tomato")) { + if (ImGui::BeginMenuBar()) { + // TODO: drop all menu sep? + //ImGui::Separator(); // os already exists (very hacky) + if (ImGui::BeginMenu("ObjectStore")) { + if (ImGui::MenuItem("Stream Manger", nullptr, _show_window)) { + _show_window = !_show_window; + } + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } + + } + ImGui::End(); + } + + + if (!_show_window) { + return; + } + + if (ImGui::Begin("StreamManagerUI", &_show_window)) { + // TODO: node canvas + + // by fametype ?? + + if (ImGui::CollapsingHeader("Sources", ImGuiTreeNodeFlags_DefaultOpen)) { + // list sources + if (ImGui::BeginTable("sources_and_sinks", 4, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_BordersInnerV)) { + ImGui::TableSetupColumn("id"); + ImGui::TableSetupColumn("name"); + ImGui::TableSetupColumn("##conn"); + ImGui::TableSetupColumn("type"); + + ImGui::TableHeadersRow(); + + for (const auto& [oc, ss] : _os.registry().view().each()) { + //ImGui::Text("src %d (%s)[%s]", entt::to_integral(entt::to_entity(oc)), ss.name.c_str(), ss.frame_type_name.c_str()); + ImGui::PushID(entt::to_integral(oc)); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entt::to_integral(entt::to_entity(oc))); + + const auto *ssrc = _os.registry().try_get(oc); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(ssrc!=nullptr?ssrc->name.c_str():"none"); + + ImGui::TableNextColumn(); + if (ImGui::SmallButton("->")) { + ImGui::OpenPopup("src_connect"); + } + if (ImGui::BeginPopup("src_connect")) { + if (ImGui::BeginMenu("connect to")) { + for (const auto& [oc_sink, s_sink] : _os.registry().view().each()) { + if (s_sink.frame_type_name != ss.frame_type_name) { + continue; + } + + ImGui::PushID(entt::to_integral(oc_sink)); + + std::string sink_label {"src "}; + sink_label += std::to_string(entt::to_integral(entt::to_entity(oc_sink))); + sink_label += " ("; + sink_label += s_sink.name; + sink_label += ")["; + sink_label += s_sink.frame_type_name; + sink_label += "]"; + if (ImGui::MenuItem(sink_label.c_str())) { + _sm.connect(oc, oc_sink); + } + + ImGui::PopID(); + } + + ImGui::EndMenu(); + } + ImGui::EndPopup(); + } + + ImGui::TableNextColumn(); + ImGui::TextUnformatted(ssrc!=nullptr?ssrc->frame_type_name.c_str():"???"); + + ImGui::PopID(); + } + + ImGui::EndTable(); + } + } // sources header + + if (ImGui::CollapsingHeader("Sinks", ImGuiTreeNodeFlags_DefaultOpen)) { + // list sinks + if (ImGui::BeginTable("sources_and_sinks", 4, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_BordersInnerV)) { + ImGui::TableSetupColumn("id"); + ImGui::TableSetupColumn("name"); + ImGui::TableSetupColumn("##conn"); + ImGui::TableSetupColumn("type"); + + ImGui::TableHeadersRow(); + + for (const auto& [oc, ss] : _os.registry().view().each()) { + ImGui::PushID(entt::to_integral(oc)); + + ImGui::TableNextColumn(); + ImGui::Text("%d", entt::to_integral(entt::to_entity(oc))); + + const auto *ssink = _os.registry().try_get(oc); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(ssink!=nullptr?ssink->name.c_str():"none"); + + ImGui::TableNextColumn(); + if (ImGui::SmallButton("->")) { + ImGui::OpenPopup("sink_connect"); + } + // ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings + if (ImGui::BeginPopup("sink_connect")) { + if (ImGui::BeginMenu("connect to")) { + for (const auto& [oc_src, s_src] : _os.registry().view().each()) { + if (s_src.frame_type_name != ss.frame_type_name) { + continue; + } + + ImGui::PushID(entt::to_integral(oc_src)); + + std::string source_label {"src "}; + source_label += std::to_string(entt::to_integral(entt::to_entity(oc_src))); + source_label += " ("; + source_label += s_src.name; + source_label += ")["; + source_label += s_src.frame_type_name; + source_label += "]"; + if (ImGui::MenuItem(source_label.c_str())) { + _sm.connect(oc_src, oc); + } + + ImGui::PopID(); + } + + ImGui::EndMenu(); + } + ImGui::EndPopup(); + } + + ImGui::TableNextColumn(); + ImGui::TextUnformatted(ssink!=nullptr?ssink->frame_type_name.c_str():"???"); + + ImGui::PopID(); + } + + ImGui::EndTable(); + } + } // sink header + + if (ImGui::CollapsingHeader("Connections", ImGuiTreeNodeFlags_DefaultOpen)) { + // list connections + if (ImGui::BeginTable("connections", 6, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_BordersInnerV)) { + ImGui::TableSetupColumn("##id"); // TODO: remove? + ImGui::TableSetupColumn("##disco"); + ImGui::TableSetupColumn("##qdesc"); + ImGui::TableSetupColumn("from"); + ImGui::TableSetupColumn("to"); + ImGui::TableSetupColumn("type"); + + ImGui::TableHeadersRow(); + + for (size_t i = 0; i < _sm._connections.size(); i++) { + const auto& con = _sm._connections[i]; + //ImGui::Text("con %d->%d", entt::to_integral(entt::to_entity(con->src.entity())), entt::to_integral(entt::to_entity(con->sink.entity()))); + + ImGui::PushID(i); + + ImGui::TableNextColumn(); + ImGui::Text("%zu", i); // do connections have ids? + + ImGui::TableNextColumn(); + if (ImGui::SmallButton("X")) { + con->stop = true; + } + + ImGui::TableNextColumn(); + ImGui::Text("%d->%d", entt::to_integral(entt::to_entity(con->src.entity())), entt::to_integral(entt::to_entity(con->sink.entity()))); + + const auto *ssrc = con->src.try_get(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(ssrc!=nullptr?ssrc->name.c_str():"none"); + + const auto *ssink = con->sink.try_get(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(ssink!=nullptr?ssink->name.c_str():"none"); + + ImGui::TableNextColumn(); + ImGui::TextUnformatted( + (ssrc!=nullptr)? + ssrc->frame_type_name.c_str(): + (ssink!=nullptr)? + ssink->frame_type_name.c_str() + :"???" + ); + + ImGui::PopID(); + } + ImGui::EndTable(); + } + } // con header + } + ImGui::End(); +} + diff --git a/src/stream_manager_ui.hpp b/src/stream_manager_ui.hpp new file mode 100644 index 00000000..c486a39d --- /dev/null +++ b/src/stream_manager_ui.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include +#include "./frame_streams/stream_manager.hpp" + +class StreamManagerUI { + ObjectStore2& _os; + StreamManager& _sm; + + bool _show_window {false}; + + public: + StreamManagerUI(ObjectStore2& os, StreamManager& sm); + + void render(void); +}; +