improve streams also throw os events
This commit is contained in:
parent
4d5d708d6d
commit
d0eeef2b94
@ -32,18 +32,5 @@ namespace Content1::Components {
|
||||
entt::dense_set<Contact3> participants;
|
||||
};
|
||||
|
||||
struct ReadHeadHint {
|
||||
// points to the first byte we want
|
||||
// this is just a hint, that can be set from outside
|
||||
// to guide the sequential "piece picker" strategy
|
||||
// the strategy *should* set this to the first byte we dont yet have
|
||||
uint64_t offset_into_file {0u};
|
||||
};
|
||||
|
||||
} // Content::Components
|
||||
|
||||
// TODO: i have no idea
|
||||
struct RawFile2ReadFromContentFactoryI {
|
||||
virtual std::shared_ptr<File2I> open(ObjectHandle h) = 0;
|
||||
};
|
||||
|
||||
|
@ -274,15 +274,19 @@ DebugToxCall::~DebugToxCall(void) {
|
||||
|
||||
for (auto& [fid, call] : _calls) {
|
||||
if (static_cast<bool>(call.incoming_vsrc)) {
|
||||
_os.throwEventDestroy(call.incoming_vsrc);
|
||||
call.incoming_vsrc.destroy();
|
||||
}
|
||||
if (static_cast<bool>(call.incoming_asrc)) {
|
||||
_os.throwEventDestroy(call.incoming_asrc);
|
||||
call.incoming_asrc.destroy();
|
||||
}
|
||||
if (static_cast<bool>(call.outgoing_vsink)) {
|
||||
_os.throwEventDestroy(call.outgoing_vsink);
|
||||
call.outgoing_vsink.destroy();
|
||||
}
|
||||
if (static_cast<bool>(call.outgoing_asink)) {
|
||||
_os.throwEventDestroy(call.outgoing_asink);
|
||||
call.outgoing_asink.destroy();
|
||||
}
|
||||
}
|
||||
@ -375,14 +379,16 @@ float DebugToxCall::render(void) {
|
||||
auto new_vsink = std::make_unique<ToxAVCallVideoSink>(_toxav, fid);
|
||||
call.outgoing_vsink.emplace<ToxAVCallVideoSink*>(new_vsink.get());
|
||||
call.outgoing_vsink.emplace<Components::FrameStream2Sink<SDLVideoFrame>>(std::move(new_vsink));
|
||||
call.outgoing_vsink.emplace<Components::StreamSink>("ToxAV friend call video", std::string{entt::type_name<SDLVideoFrame>::value()});
|
||||
call.outgoing_vsink.emplace<Components::StreamSink>(Components::StreamSink::create<SDLVideoFrame>("ToxAV friend call video"));
|
||||
_os.throwEventConstruct(call.outgoing_vsink);
|
||||
}
|
||||
call.outgoing_asink = {_os.registry(), _os.registry().create()};
|
||||
{
|
||||
auto new_asink = std::make_unique<ToxAVCallAudioSink>(_toxav, fid);
|
||||
call.outgoing_asink.emplace<ToxAVCallAudioSink*>(new_asink.get());
|
||||
call.outgoing_asink.emplace<Components::FrameStream2Sink<AudioFrame>>(std::move(new_asink));
|
||||
call.outgoing_asink.emplace<Components::StreamSink>("ToxAV friend call audio", std::string{entt::type_name<AudioFrame>::value()});
|
||||
call.outgoing_asink.emplace<Components::StreamSink>(Components::StreamSink::create<AudioFrame>("ToxAV friend call audio"));
|
||||
_os.throwEventConstruct(call.outgoing_asink);
|
||||
}
|
||||
|
||||
// create sources
|
||||
@ -392,7 +398,8 @@ float DebugToxCall::render(void) {
|
||||
auto new_vsrc = std::make_unique<SDLVideoFrameStream2MultiSource>();
|
||||
call.incoming_vsrc.emplace<SDLVideoFrameStream2MultiSource*>(new_vsrc.get());
|
||||
call.incoming_vsrc.emplace<Components::FrameStream2Source<SDLVideoFrame>>(std::move(new_vsrc));
|
||||
call.incoming_vsrc.emplace<Components::StreamSource>("ToxAV friend call video", std::string{entt::type_name<SDLVideoFrame>::value()});
|
||||
call.incoming_vsrc.emplace<Components::StreamSource>(Components::StreamSource::create<SDLVideoFrame>("ToxAV friend call video"));
|
||||
_os.throwEventConstruct(call.incoming_vsrc);
|
||||
}
|
||||
}
|
||||
if (call.incoming_a) {
|
||||
@ -401,7 +408,8 @@ float DebugToxCall::render(void) {
|
||||
auto new_asrc = std::make_unique<AudioFrameStream2MultiSource>();
|
||||
call.incoming_asrc.emplace<AudioFrameStream2MultiSource*>(new_asrc.get());
|
||||
call.incoming_asrc.emplace<Components::FrameStream2Source<AudioFrame>>(std::move(new_asrc));
|
||||
call.incoming_asrc.emplace<Components::StreamSource>("ToxAV friend call audio", std::string{entt::type_name<AudioFrame>::value()});
|
||||
call.incoming_asrc.emplace<Components::StreamSource>(Components::StreamSource::create<AudioFrame>("ToxAV friend call audio"));
|
||||
_os.throwEventConstruct(call.incoming_asrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -418,15 +426,19 @@ float DebugToxCall::render(void) {
|
||||
|
||||
// TODO: stream manager disconnectAll()
|
||||
if (static_cast<bool>(call.incoming_vsrc)) {
|
||||
_os.throwEventDestroy(call.incoming_vsrc);
|
||||
call.incoming_vsrc.destroy();
|
||||
}
|
||||
if (static_cast<bool>(call.incoming_asrc)) {
|
||||
_os.throwEventDestroy(call.incoming_asrc);
|
||||
call.incoming_asrc.destroy();
|
||||
}
|
||||
if (static_cast<bool>(call.outgoing_vsink)) {
|
||||
_os.throwEventDestroy(call.outgoing_vsink);
|
||||
call.outgoing_vsink.destroy();
|
||||
}
|
||||
if (static_cast<bool>(call.outgoing_asink)) {
|
||||
_os.throwEventDestroy(call.outgoing_asink);
|
||||
call.outgoing_asink.destroy();
|
||||
}
|
||||
}
|
||||
@ -468,15 +480,19 @@ bool DebugToxCall::onEvent(const Events::FriendCallState& e) {
|
||||
(call.state & TOXAV_FRIEND_CALL_STATE_ERROR) != 0
|
||||
) {
|
||||
if (static_cast<bool>(call.incoming_vsrc)) {
|
||||
_os.throwEventDestroy(call.incoming_vsrc);
|
||||
call.incoming_vsrc.destroy();
|
||||
}
|
||||
if (static_cast<bool>(call.incoming_asrc)) {
|
||||
_os.throwEventDestroy(call.incoming_asrc);
|
||||
call.incoming_asrc.destroy();
|
||||
}
|
||||
if (static_cast<bool>(call.outgoing_vsink)) {
|
||||
_os.throwEventDestroy(call.outgoing_vsink);
|
||||
call.outgoing_vsink.destroy();
|
||||
}
|
||||
if (static_cast<bool>(call.outgoing_asink)) {
|
||||
_os.throwEventDestroy(call.outgoing_asink);
|
||||
call.outgoing_asink.destroy();
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ DebugVideoTap::DebugVideoTap(ObjectStore2& os, StreamManager& sm, TextureUploade
|
||||
std::move(dvts)
|
||||
);
|
||||
|
||||
_tap.emplace<Components::StreamSink>("DebugVideoTap", std::string{entt::type_name<SDLVideoFrame>::value()});
|
||||
_tap.emplace<Components::StreamSink>(Components::StreamSink::create<SDLVideoFrame>("DebugVideoTap"));
|
||||
} catch (...) {
|
||||
_os.registry().destroy(_tap);
|
||||
}
|
||||
|
@ -154,7 +154,9 @@ MainScreen::MainScreen(SimpleConfigModel&& conf_, SDL_Renderer* renderer_, Theme
|
||||
std::make_unique<SDLVideoCameraContent>()
|
||||
);
|
||||
|
||||
vsrc.emplace<Components::StreamSource>("WebCam", std::string{entt::type_name<SDLVideoFrame>::value()});
|
||||
vsrc.emplace<Components::StreamSource>(Components::StreamSource::create<SDLVideoFrame>("WebCam"));
|
||||
|
||||
os.throwEventConstruct(vsrc);
|
||||
} catch (...) {
|
||||
os.registry().destroy(vsrc);
|
||||
}
|
||||
@ -176,7 +178,9 @@ MainScreen::MainScreen(SimpleConfigModel&& conf_, SDL_Renderer* renderer_, Theme
|
||||
std::make_unique<SDLAudioOutputDeviceDefaultSink>()
|
||||
);
|
||||
|
||||
asink.emplace<Components::StreamSink>("LoudSpeaker", std::string{entt::type_name<AudioFrame>::value()});
|
||||
asink.emplace<Components::StreamSink>(Components::StreamSink::create<AudioFrame>("LoudSpeaker"));
|
||||
|
||||
os.throwEventConstruct(asink);
|
||||
} catch (...) {
|
||||
os.registry().destroy(asink);
|
||||
}
|
||||
|
@ -13,17 +13,26 @@
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
// fwd
|
||||
class StreamManager;
|
||||
|
||||
namespace Components {
|
||||
struct StreamSource {
|
||||
std::string name;
|
||||
std::string frame_type_name;
|
||||
// TODO: connect fn
|
||||
|
||||
std::function<bool(StreamManager&, Object, Object, bool)> connect_fn;
|
||||
|
||||
template<typename FrameType>
|
||||
static StreamSource create(const std::string& name);
|
||||
};
|
||||
|
||||
struct StreamSink {
|
||||
std::string name;
|
||||
std::string frame_type_name;
|
||||
// TODO: connect fn
|
||||
|
||||
template<typename FrameType>
|
||||
static StreamSink create(const std::string& name);
|
||||
};
|
||||
|
||||
template<typename FrameType>
|
||||
@ -102,8 +111,6 @@ class StreamManager {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: default typed sources and sinks
|
||||
|
||||
// stream type is FrameStream2I<FrameType>
|
||||
// TODO: improve this design
|
||||
// src and sink need to be a FrameStream2MultiStream<FrameType>
|
||||
@ -135,14 +142,6 @@ class StreamManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
// HACK:
|
||||
if (!h_src.all_of<Components::StreamSource>()) {
|
||||
h_src.emplace<Components::StreamSource>("", std::string{entt::type_name<FrameType>::value()});
|
||||
}
|
||||
if (!h_sink.all_of<Components::StreamSink>()) {
|
||||
h_sink.emplace<Components::StreamSink>("", std::string{entt::type_name<FrameType>::value()});
|
||||
}
|
||||
|
||||
auto& src_stream = h_src.get<Components::FrameStream2Source<FrameType>>();
|
||||
auto& sink_stream = h_sink.get<Components::FrameStream2Sink<FrameType>>();
|
||||
|
||||
@ -195,6 +194,43 @@ class StreamManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool connect(Object src, Object sink, bool threaded = true) {
|
||||
auto h_src = _os.objectHandle(src);
|
||||
auto h_sink = _os.objectHandle(sink);
|
||||
if (!static_cast<bool>(h_src) || !static_cast<bool>(h_sink)) {
|
||||
// an object does not exist
|
||||
return false;
|
||||
}
|
||||
|
||||
// get src and sink comps
|
||||
if (!h_src.all_of<Components::StreamSource>()) {
|
||||
// src not stream source
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!h_sink.all_of<Components::StreamSink>()) {
|
||||
// sink not stream sink
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& ssrc = h_src.get<Components::StreamSource>();
|
||||
const auto& ssink = h_sink.get<Components::StreamSink>();
|
||||
|
||||
// compare type
|
||||
if (ssrc.frame_type_name != ssink.frame_type_name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// always fail in debug mode
|
||||
assert(static_cast<bool>(ssrc.connect_fn));
|
||||
if (!static_cast<bool>(ssrc.connect_fn)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// use connect fn from src
|
||||
return ssrc.connect_fn(*this, src, sink, threaded);
|
||||
}
|
||||
|
||||
template<typename StreamType>
|
||||
bool disconnect(Object src, Object sink) {
|
||||
auto res = std::find_if(
|
||||
@ -258,3 +294,27 @@ class StreamManager {
|
||||
}
|
||||
};
|
||||
|
||||
namespace Components {
|
||||
|
||||
// we require the complete sm type here
|
||||
template<typename FrameType>
|
||||
StreamSource StreamSource::create(const std::string& name) {
|
||||
return StreamSource{
|
||||
name,
|
||||
std::string{entt::type_name<FrameType>::value()},
|
||||
+[](StreamManager& sm, Object src, Object sink, bool threaded) {
|
||||
return sm.connect<FrameType>(src, sink, threaded);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
template<typename FrameType>
|
||||
StreamSink StreamSink::create(const std::string& name) {
|
||||
return StreamSink{
|
||||
name,
|
||||
std::string{entt::type_name<FrameType>::value()},
|
||||
};
|
||||
}
|
||||
|
||||
} // Components
|
||||
|
||||
|
@ -1,8 +1,5 @@
|
||||
#include "./stream_manager_ui.hpp"
|
||||
|
||||
#include "./content/sdl_video_frame_stream2.hpp"
|
||||
#include "./content/audio_stream.hpp"
|
||||
|
||||
#include <solanaceae/object_store/object_store.hpp>
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
@ -42,7 +39,7 @@ void StreamManagerUI::render(void) {
|
||||
|
||||
// by fametype ??
|
||||
|
||||
if (ImGui::CollapsingHeader("Sources")) {
|
||||
if (ImGui::CollapsingHeader("Sources", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
// list sources
|
||||
if (ImGui::BeginTable("sources_and_sinks", 4, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_BordersInnerV)) {
|
||||
ImGui::TableSetupColumn("id");
|
||||
@ -65,7 +62,34 @@ void StreamManagerUI::render(void) {
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::SmallButton("->")) {
|
||||
// TODO: list type sinks
|
||||
ImGui::OpenPopup("src_connect");
|
||||
}
|
||||
if (ImGui::BeginPopup("src_connect")) {
|
||||
if (ImGui::BeginMenu("connect to")) {
|
||||
for (const auto& [oc_sink, s_sink] : _os.registry().view<Components::StreamSink>().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();
|
||||
@ -78,7 +102,7 @@ void StreamManagerUI::render(void) {
|
||||
}
|
||||
} // sources header
|
||||
|
||||
if (ImGui::CollapsingHeader("Sinks")) {
|
||||
if (ImGui::CollapsingHeader("Sinks", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
// list sinks
|
||||
if (ImGui::BeginTable("sources_and_sinks", 4, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_BordersInnerV)) {
|
||||
ImGui::TableSetupColumn("id");
|
||||
@ -89,8 +113,6 @@ void StreamManagerUI::render(void) {
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (const auto& [oc, ss] : _os.registry().view<Components::StreamSink>().each()) {
|
||||
//ImGui::Text("sink %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();
|
||||
@ -102,10 +124,11 @@ void StreamManagerUI::render(void) {
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::SmallButton("->")) {
|
||||
// TODO: list type sinks
|
||||
ImGui::OpenPopup("sink_connect");
|
||||
}
|
||||
if (ImGui::BeginPopupContextItem("sink_connect")) {
|
||||
if (ImGui::BeginMenu("connect video", ss.frame_type_name == entt::type_name<SDLVideoFrame>::value())) {
|
||||
// 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<Components::StreamSource>().each()) {
|
||||
if (s_src.frame_type_name != ss.frame_type_name) {
|
||||
continue;
|
||||
@ -121,32 +144,7 @@ void StreamManagerUI::render(void) {
|
||||
source_label += s_src.frame_type_name;
|
||||
source_label += "]";
|
||||
if (ImGui::MenuItem(source_label.c_str())) {
|
||||
_sm.connect<SDLVideoFrame>(oc_src, oc);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("connect audio", ss.frame_type_name == entt::type_name<AudioFrame>::value())) {
|
||||
for (const auto& [oc_src, s_src] : _os.registry().view<Components::StreamSource>().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<AudioFrame>(oc_src, oc);
|
||||
_sm.connect(oc_src, oc);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
|
Loading…
Reference in New Issue
Block a user