From 1b8e3accea3e6c388dfa8f7237040bdc5d3b982d Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Sun, 10 May 2020 17:45:37 +0200 Subject: [PATCH] Added mechanisms to detect when a source failed, and to remove it if its the case. --- MediaPlayer.cpp | 14 ++++++++++++++ MediaPlayer.h | 5 +++++ Source.cpp | 5 +++++ Source.h | 16 ++++++++++------ UserInterfaceManager.cpp | 16 ++++++++++++---- 5 files changed, 46 insertions(+), 10 deletions(-) diff --git a/MediaPlayer.cpp b/MediaPlayer.cpp index a08b7fb..1a548bf 100644 --- a/MediaPlayer.cpp +++ b/MediaPlayer.cpp @@ -36,6 +36,7 @@ MediaPlayer::MediaPlayer(string name) : id_(name) discoverer_ = nullptr; ready_ = false; + failed_ = false; seekable_ = false; isimage_ = false; interlaced_ = false; @@ -90,6 +91,7 @@ void MediaPlayer::open(string path) if (!discoverer_) { Log::Warning("MediaPlayer Error creating discoverer instance: %s\n", err->message); g_clear_error (&err); + failed_ = true; return; } @@ -105,6 +107,7 @@ void MediaPlayer::open(string path) Log::Warning("MediaPlayer %s Failed to start discovering URI '%s'\n", id_.c_str(), uri_.c_str()); g_object_unref (discoverer_); discoverer_ = nullptr; + failed_ = true; } // and wait for discoverer to finish... @@ -125,6 +128,7 @@ void MediaPlayer::execute_open() if (error != NULL) { Log::Warning("MediaPlayer %s Could not construct pipeline %s:\n%s", id_.c_str(), description.c_str(), error->message); g_clear_error (&error); + failed_ = true; return; } g_object_set(G_OBJECT(pipeline_), "name", id_.c_str(), NULL); @@ -134,6 +138,7 @@ void MediaPlayer::execute_open() GstCaps *caps = gst_caps_from_string(capstring.c_str()); if (!gst_video_info_from_caps (&v_frame_video_info_, caps)) { Log::Warning("MediaPlayer %s Could not configure video frame info", id_.c_str()); + failed_ = true; return; } @@ -159,6 +164,7 @@ void MediaPlayer::execute_open() } else { Log::Warning("MediaPlayer %s Could not configure sink", id_.c_str()); + failed_ = true; return; } gst_caps_unref (caps); @@ -170,6 +176,7 @@ void MediaPlayer::execute_open() GstStateChangeReturn ret = gst_element_set_state (pipeline_, desired_state_); if (ret == GST_STATE_CHANGE_FAILURE) { Log::Warning("MediaPlayer %s Could not open %s", id_.c_str(), uri_.c_str()); + failed_ = true; return; } @@ -183,6 +190,11 @@ bool MediaPlayer::isOpen() const return ready_; } +bool MediaPlayer::failed() const +{ + return failed_; +} + void MediaPlayer::close() { // stop discovering stream @@ -284,6 +296,7 @@ void MediaPlayer::play(bool on) GstStateChangeReturn ret = gst_element_set_state (pipeline_, desired_state_); if (ret == GST_STATE_CHANGE_FAILURE) { Log::Warning("MediaPlayer %s Failed to start", gst_element_get_name(pipeline_)); + failed_ = true; } #ifdef MEDIA_PLAYER_DEBUG else if (on) @@ -775,6 +788,7 @@ void MediaPlayer::callback_discoverer_finished(GstDiscoverer *discoverer, MediaP else { Log::Warning("MediaPlayer %s Failed to open %s\n%s", m->id_.c_str(), m->uri_.c_str(), m->discoverer_message_.str().c_str()); m->discoverer_message_.clear(); + m->failed_ = true; } } } diff --git a/MediaPlayer.h b/MediaPlayer.h index 2a9e819..b3b6751 100644 --- a/MediaPlayer.h +++ b/MediaPlayer.h @@ -106,6 +106,10 @@ public: * True if a media was oppenned * */ bool isOpen() const; + /** + * True if problem occured + * */ + bool failed() const; /** * Close the Media * */ @@ -243,6 +247,7 @@ private: MediaSegmentSet::iterator current_segment_; bool ready_; + bool failed_; bool seekable_; bool isimage_; bool interlaced_; diff --git a/Source.cpp b/Source.cpp index 6d23689..daaed9f 100644 --- a/Source.cpp +++ b/Source.cpp @@ -142,6 +142,11 @@ MediaPlayer *MediaSource::mediaplayer() const return mediaplayer_; } +bool MediaSource::failed() const +{ + return mediaplayer_->failed(); +} + void MediaSource::init() { if ( mediaplayer_->isOpen() ) { diff --git a/Source.h b/Source.h index 178f481..d07e28a 100644 --- a/Source.h +++ b/Source.h @@ -28,6 +28,9 @@ public: inline std::string name () const { return name_; } inline const char *initials() const { return initials_; } + // an overlay can be displayed on top of the source + virtual void setOverlayVisible(bool on); + // get handle on the node used to manipulate the source in a view inline Group *group(View::Mode m) const { return groups_.at(m); } inline Node *node(View::Mode m) const { return static_cast(groups_.at(m)); } @@ -44,12 +47,12 @@ public: // every Source shall be rendered before draw virtual void render() = 0; - // an overlay can be displayed on top of the source - virtual void setOverlayVisible(bool on); - // accept all kind of visitors virtual void accept (Visitor& v); + // informs if the source failed (and might have to be deleted) + virtual bool failed() const { return false; } + protected: // name std::string name_; @@ -112,9 +115,10 @@ public: ~MediaSource(); // implementation of source API - FrameBuffer *frame() const; - void render(); - void accept (Visitor& v); + FrameBuffer *frame() const override; + void render() override; + void accept (Visitor& v) override; + bool failed() const override; // Media specific interface void setPath(const std::string &p); diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index ff77138..8d02b1e 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -891,6 +891,7 @@ void Navigator::Render() // the list of INITIALS for sources int index = 0; SourceList::iterator iter; + Source *source_to_delete = nullptr; for (iter = Mixer::manager().session()->begin(); iter != Mixer::manager().session()->end(); iter++, index++) { // draw an indicator for current source @@ -909,7 +910,14 @@ void Navigator::Render() if (selected_button[index]) Mixer::manager().setCurrentSource(selected_source_index); } + // delete sources which failed + if ( (*iter)->failed() ) + source_to_delete = *iter; } + // TODO : general (mixer?) paradigm to delete failed sources (here it looks like a hack) + if (source_to_delete != nullptr) + Mixer::manager().deleteSource(source_to_delete); + // the "+" icon for action of creating new source if (ImGui::Selectable( ICON_FA_PLUS, &selected_button[NAV_NEW], 0, iconsize)) { @@ -1158,15 +1166,15 @@ void Navigator::RenderMainPannel() // Bottom aligned ImGui::SetCursorPosY(height - 4.f * ImGui::GetTextLineHeightWithSpacing()); ImGui::Text("About"); - if ( ImGui::Button( " About vimix", ImVec2(pannel_width - padding_width, 0)) ) + if ( ImGui::Button( ICON_FA_CROW " About vimix", ImVec2(ImGui::GetContentRegionAvail().x, 0)) ) UserInterface::manager().show_about = true; - if ( ImGui::Button("About ImGui")) + if ( ImGui::Button("ImGui")) UserInterface::manager().show_imgui_about = true; ImGui::SameLine(); - if ( ImGui::Button("About GStreamer")) + if ( ImGui::Button("GStreamer")) UserInterface::manager().show_gst_about = true; ImGui::SameLine(); - if ( ImGui::Button("About OpenGL")) + if ( ImGui::Button("OpenGL", ImVec2(ImGui::GetContentRegionAvail().x, 0))) UserInterface::manager().show_opengl_about = true; }