Refactor Broadcast manager methods to use FrameGrabber type instead of ID, forcing the use of singletons. Update OutputPreviewWindow to reflect these changes and remove unused variables.

This commit is contained in:
brunoherbelin
2025-11-09 22:47:17 +01:00
parent ec9a4ef88a
commit 6b7f4477b0
5 changed files with 48 additions and 67 deletions

View File

@@ -611,7 +611,7 @@ bool Control::receiveOutputAttribute(const std::string &attribute,
// if argument is given, it is the connection port // if argument is given, it is the connection port
if (!arguments.Eos()) if (!arguments.Eos())
arguments >> f >> osc::EndMessage; arguments >> f >> osc::EndMessage;
Broadcast::manager().start( new VideoBroadcast((int) f), true); Broadcast::manager().start( new VideoBroadcast((int) f));
} }
else if ( attribute.compare(OSC_OUTPUT_SRT_STOP) == 0) { else if ( attribute.compare(OSC_OUTPUT_SRT_STOP) == 0) {
Broadcast::manager().stop(FrameGrabber::GRABBER_BROADCAST); Broadcast::manager().stop(FrameGrabber::GRABBER_BROADCAST);

View File

@@ -659,54 +659,38 @@ guint64 FrameGrabber::frames() const
} }
uint64_t Broadcast::start(FrameGrabber *ptr, bool singleton) void Broadcast::start(FrameGrabber *ptr)
{ {
if (singleton) stop( ptr->type() );
stop( ptr->type() );
uint64_t b = ptr->id();
FrameGrabbing::manager().add(ptr); FrameGrabbing::manager().add(ptr);
return b;
} }
bool Broadcast::enabled(uint64_t b) bool Broadcast::busy(FrameGrabber::Type T)
{ {
return ( FrameGrabbing::manager().get(b) != nullptr); FrameGrabber *ptr = FrameGrabbing::manager().get( T );
}
bool Broadcast::busy(uint64_t b)
{
FrameGrabber *ptr = FrameGrabbing::manager().get(b);
if (ptr != nullptr) if (ptr != nullptr)
return ptr->busy(); return ptr->busy();
return false; return false;
} }
std::string Broadcast::info(uint64_t b, bool extended) std::string Broadcast::info(FrameGrabber::Type T, bool extended)
{ {
FrameGrabber *ptr = FrameGrabbing::manager().get(b); FrameGrabber *ptr = FrameGrabbing::manager().get( T );
if (ptr != nullptr) if (ptr != nullptr)
return ptr->info(extended); return ptr->info(extended);
return "Disabled"; return "Disabled";
} }
void Broadcast::stop(uint64_t b) bool Broadcast::enabled(FrameGrabber::Type T)
{ {
FrameGrabber *ptr = FrameGrabbing::manager().get(b); return ( FrameGrabbing::manager().get( T ) != nullptr);
if (ptr != nullptr)
ptr->stop();
} }
void Broadcast::stop(FrameGrabber::Type T) void Broadcast::stop(FrameGrabber::Type T)
{ {
FrameGrabber *prev = nullptr; FrameGrabber *prev = FrameGrabbing::manager().get( T );
do { if (prev != nullptr)
prev = FrameGrabbing::manager().get( T ); prev->stop();
if (prev != nullptr)
prev->stop();
}
while (prev != nullptr);
} }

View File

@@ -173,7 +173,7 @@ private:
* *
* FrameGrabbers can terminate (normal behavior or failure) and the FrameGrabber * FrameGrabbers can terminate (normal behavior or failure) and the FrameGrabber
* is deleted automatically; pointer is then invalid and cannot be accessed. To avoid this, * is deleted automatically; pointer is then invalid and cannot be accessed. To avoid this,
* the Broadcast::manager() gives access to FrameGrabbers by id. * the Broadcast::manager() gives access to FrameGrabbers by type (single instance).
* *
* Singleton mechanism also allows starting a unique instance of each FrameGrabber::Type * Singleton mechanism also allows starting a unique instance of each FrameGrabber::Type
*/ */
@@ -193,11 +193,10 @@ public:
return _instance; return _instance;
} }
uint64_t start(FrameGrabber *ptr, bool singleton = false); void start(FrameGrabber *ptr);
bool enabled(uint64_t); bool enabled(FrameGrabber::Type);
bool busy(uint64_t); bool busy(FrameGrabber::Type);
std::string info(uint64_t, bool extended = false); std::string info(FrameGrabber::Type, bool extended = false);
void stop(uint64_t);
void stop(FrameGrabber::Type); void stop(FrameGrabber::Type);
}; };

View File

@@ -41,7 +41,7 @@
OutputPreviewWindow::OutputPreviewWindow() : WorkspaceWindow("OutputPreview"), OutputPreviewWindow::OutputPreviewWindow() : WorkspaceWindow("OutputPreview"),
video_recorder_(nullptr), srt_(0), shm_(0), loopback_(0), video_recorder_(nullptr),
magnifying_glass(false) magnifying_glass(false)
{ {
@@ -135,19 +135,19 @@ void OutputPreviewWindow::ToggleRecordPause()
void OutputPreviewWindow::ToggleVideoBroadcast() void OutputPreviewWindow::ToggleVideoBroadcast()
{ {
if (Broadcast::manager().enabled(srt_) ) if (Broadcast::manager().enabled( FrameGrabber::GRABBER_BROADCAST ) )
Broadcast::manager().stop(srt_); Broadcast::manager().stop( FrameGrabber::GRABBER_BROADCAST );
else { else {
if (Settings::application.broadcast_port<1000) if (Settings::application.broadcast_port<1000)
Settings::application.broadcast_port = BROADCAST_DEFAULT_PORT; Settings::application.broadcast_port = BROADCAST_DEFAULT_PORT;
srt_ = Broadcast::manager().start( new VideoBroadcast(Settings::application.broadcast_port), true); Broadcast::manager().start( new VideoBroadcast(Settings::application.broadcast_port));
} }
} }
void OutputPreviewWindow::ToggleSharedMemory() void OutputPreviewWindow::ToggleSharedMemory()
{ {
if (Broadcast::manager().enabled(shm_) ) if (Broadcast::manager().enabled( FrameGrabber::GRABBER_SHM ) )
Broadcast::manager().stop(shm_); Broadcast::manager().stop( FrameGrabber::GRABBER_SHM );
else { else {
// find a folder to put the socket for shm // find a folder to put the socket for shm
std::string _shm_socket_file = Settings::application.shm_socket_path; std::string _shm_socket_file = Settings::application.shm_socket_path;
@@ -156,22 +156,22 @@ void OutputPreviewWindow::ToggleSharedMemory()
_shm_socket_file = SystemToolkit::full_filename(_shm_socket_file, ".shm_vimix" + std::to_string(Settings::application.instance_id)); _shm_socket_file = SystemToolkit::full_filename(_shm_socket_file, ".shm_vimix" + std::to_string(Settings::application.instance_id));
// create shhmdata broadcaster with method // create shhmdata broadcaster with method
shm_ = Broadcast::manager().start( new ShmdataBroadcast( (ShmdataBroadcast::Method) Settings::application.shm_method, _shm_socket_file), true); Broadcast::manager().start( new ShmdataBroadcast( (ShmdataBroadcast::Method) Settings::application.shm_method, _shm_socket_file));
} }
} }
bool OutputPreviewWindow::ToggleLoopbackCamera() bool OutputPreviewWindow::ToggleLoopbackCamera()
{ {
bool need_initialization = false; bool need_initialization = false;
if (Broadcast::manager().enabled(loopback_)) if (Broadcast::manager().enabled( FrameGrabber::GRABBER_LOOPBACK ))
Broadcast::manager().stop(loopback_); Broadcast::manager().stop( FrameGrabber::GRABBER_LOOPBACK );
else { else {
if (Settings::application.loopback_camera < 1) if (Settings::application.loopback_camera < 1)
Settings::application.loopback_camera = LOOPBACK_DEFAULT_DEVICE; Settings::application.loopback_camera = LOOPBACK_DEFAULT_DEVICE;
Settings::application.loopback_camera += Settings::application.instance_id; Settings::application.loopback_camera += Settings::application.instance_id;
try { try {
loopback_ = Broadcast::manager().start( new Loopback(Settings::application.loopback_camera), true ); Broadcast::manager().start( new Loopback(Settings::application.loopback_camera) );
} }
catch (const std::runtime_error &e) { catch (const std::runtime_error &e) {
need_initialization = true; need_initialization = true;
@@ -389,27 +389,28 @@ void OutputPreviewWindow::Render()
// Broadcasting menu // Broadcasting menu
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.9f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.9f));
if (VideoBroadcast::available()) { if (VideoBroadcast::available()) {
if ( ImGui::MenuItem( ICON_FA_GLOBE " SRT Broadcast", NULL, Broadcast::manager().enabled(srt_) ) ) if ( ImGui::MenuItem( ICON_FA_GLOBE " SRT Broadcast", NULL, Broadcast::manager().enabled( FrameGrabber::GRABBER_BROADCAST ) ) )
ToggleVideoBroadcast(); ToggleVideoBroadcast();
} }
// Shared Memory menu // Shared Memory menu
if (ShmdataBroadcast::available()) { if (ShmdataBroadcast::available()) {
if ( ImGui::MenuItem( ICON_FA_MEMORY " SHM Shared Memory", NULL, Broadcast::manager().enabled(shm_) ) ) if ( ImGui::MenuItem( ICON_FA_MEMORY " SHM Shared Memory", NULL, Broadcast::manager().enabled( FrameGrabber::GRABBER_SHM ) ) )
ToggleSharedMemory(); ToggleSharedMemory();
} }
// Loopback camera menu // Loopback camera menu
if (Loopback::available()) { if (Loopback::available()) {
if ( ImGui::MenuItem( ICON_FA_VIDEO " Loopback Camera", NULL, Broadcast::manager().enabled(loopback_)) ) if ( ImGui::MenuItem( ICON_FA_VIDEO " Loopback Camera", NULL, Broadcast::manager().enabled( FrameGrabber::GRABBER_LOOPBACK )) )
openInitializeSystemLoopback = ToggleLoopbackCamera(); openInitializeSystemLoopback = ToggleLoopbackCamera();
} }
ImGui::PopStyleColor(1); ImGui::PopStyleColor(1);
// Display list of active stream // Display list of active stream
if (ls.size()>0 || Broadcast::manager().enabled(srt_) || if (ls.size()>0 || Broadcast::manager().enabled( FrameGrabber::GRABBER_BROADCAST ) ||
Broadcast::manager().enabled(shm_) || Broadcast::manager().enabled(loopback_)) { Broadcast::manager().enabled( FrameGrabber::GRABBER_SHM ) ||
Broadcast::manager().enabled( FrameGrabber::GRABBER_LOOPBACK )) {
ImGui::Separator(); ImGui::Separator();
ImGui::MenuItem("Active streams:", nullptr, false, false); ImGui::MenuItem("Active streams:", nullptr, false, false);
@@ -418,36 +419,36 @@ void OutputPreviewWindow::Render()
ImGui::Text(" %s ", (*it).c_str() ); ImGui::Text(" %s ", (*it).c_str() );
// SRT broadcast description // SRT broadcast description
if (Broadcast::manager().enabled(srt_)) { if (Broadcast::manager().enabled( FrameGrabber::GRABBER_BROADCAST )) {
ImGui::Text(" %s ", Broadcast::manager().info(srt_).c_str()); ImGui::Text(" %s ", Broadcast::manager().info( FrameGrabber::GRABBER_BROADCAST ).c_str());
// copy text icon to give user the srt link to connect to // copy text icon to give user the srt link to connect to
ImVec2 draw_pos = ImGui::GetCursorPos(); ImVec2 draw_pos = ImGui::GetCursorPos();
ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) ); ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) );
std::string moreinfo = Broadcast::manager().info(srt_, true); std::string moreinfo = Broadcast::manager().info( FrameGrabber::GRABBER_BROADCAST , true);
if (ImGuiToolkit::IconButton( ICON_FA_COPY, moreinfo.c_str())) if (ImGuiToolkit::IconButton( ICON_FA_COPY, moreinfo.c_str()))
ImGui::SetClipboardText(moreinfo.c_str()); ImGui::SetClipboardText(moreinfo.c_str());
ImGui::SetCursorPos(draw_pos); ImGui::SetCursorPos(draw_pos);
} }
// Shared memory broadcast description // Shared memory broadcast description
if (Broadcast::manager().enabled(shm_)) { if (Broadcast::manager().enabled( FrameGrabber::GRABBER_SHM )) {
ImGui::Text(" %s ", Broadcast::manager().info(shm_).c_str()); ImGui::Text(" %s ", Broadcast::manager().info( FrameGrabber::GRABBER_SHM ).c_str());
// copy text icon to give user the socket path to connect to // copy text icon to give user the socket path to connect to
ImVec2 draw_pos = ImGui::GetCursorPos(); ImVec2 draw_pos = ImGui::GetCursorPos();
ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) ); ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) );
std::string moreinfo = Broadcast::manager().info(shm_, true); std::string moreinfo = Broadcast::manager().info( FrameGrabber::GRABBER_SHM , true);
if (ImGuiToolkit::IconButton( ICON_FA_COPY, moreinfo.c_str())) if (ImGuiToolkit::IconButton( ICON_FA_COPY, moreinfo.c_str()))
ImGui::SetClipboardText(moreinfo.c_str()); ImGui::SetClipboardText(moreinfo.c_str());
ImGui::SetCursorPos(draw_pos); ImGui::SetCursorPos(draw_pos);
} }
// Loopback camera description // Loopback camera description
if (Broadcast::manager().enabled(loopback_)) { if (Broadcast::manager().enabled( FrameGrabber::GRABBER_LOOPBACK )) {
ImGui::Text(" %s ", Broadcast::manager().info(loopback_).c_str()); ImGui::Text(" %s ", Broadcast::manager().info( FrameGrabber::GRABBER_LOOPBACK ).c_str());
// copy text icon to give user the device path to connect to // copy text icon to give user the device path to connect to
ImVec2 draw_pos = ImGui::GetCursorPos(); ImVec2 draw_pos = ImGui::GetCursorPos();
ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) ); ImGui::SetCursorPos(draw_pos + ImVec2(ImGui::GetContentRegionAvailWidth() - 1.2 * ImGui::GetTextLineHeightWithSpacing(), -0.8 * ImGui::GetFrameHeight()) );
std::string moreinfo = Broadcast::manager().info(loopback_, true); std::string moreinfo = Broadcast::manager().info( FrameGrabber::GRABBER_LOOPBACK , true);
if (ImGuiToolkit::IconButton( ICON_FA_COPY, moreinfo.c_str())) if (ImGuiToolkit::IconButton( ICON_FA_COPY, moreinfo.c_str()))
ImGui::SetClipboardText(moreinfo.c_str()); ImGui::SetClipboardText(moreinfo.c_str());
ImGui::SetCursorPos(draw_pos); ImGui::SetCursorPos(draw_pos);
@@ -549,10 +550,10 @@ void OutputPreviewWindow::Render()
} }
// broadcast indicator // broadcast indicator
float vertical = r; float vertical = r;
if (Broadcast::manager().enabled(srt_)) if (Broadcast::manager().enabled( FrameGrabber::GRABBER_BROADCAST ))
{ {
ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical)); ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical));
if (Broadcast::manager().busy(srt_)) if (Broadcast::manager().busy( FrameGrabber::GRABBER_BROADCAST ))
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f));
else else
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f));
@@ -561,10 +562,10 @@ void OutputPreviewWindow::Render()
vertical += 2.f * r; vertical += 2.f * r;
} }
// shmdata indicator // shmdata indicator
if (Broadcast::manager().enabled(shm_)) if (Broadcast::manager().enabled( FrameGrabber::GRABBER_SHM ))
{ {
ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical)); ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical));
if (Broadcast::manager().busy(shm_)) if (Broadcast::manager().busy( FrameGrabber::GRABBER_SHM ))
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f));
else else
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f));
@@ -573,10 +574,10 @@ void OutputPreviewWindow::Render()
vertical += 2.f * r; vertical += 2.f * r;
} }
// loopback camera indicator // loopback camera indicator
if (Broadcast::manager().enabled(loopback_)) if (Broadcast::manager().enabled( FrameGrabber::GRABBER_LOOPBACK ))
{ {
ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical)); ImGui::SetCursorScreenPos(ImVec2(draw_pos.x + imagesize.x - 2.5f * r, draw_pos.y + vertical));
if (Broadcast::manager().busy(loopback_)) if (Broadcast::manager().busy( FrameGrabber::GRABBER_LOOPBACK ))
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.8f));
else else
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_BROADCAST, 0.4f));

View File

@@ -12,9 +12,6 @@ class OutputPreviewWindow : public WorkspaceWindow
{ {
// frame grabbers // frame grabbers
VideoRecorder *video_recorder_; VideoRecorder *video_recorder_;
uint64_t srt_;
uint64_t shm_;
uint64_t loopback_;
// delayed trigger for recording // delayed trigger for recording
std::vector< std::future<VideoRecorder *> > _video_recorders; std::vector< std::future<VideoRecorder *> > _video_recorders;