Changed behavior of MediaPlayer: offer to either follow the active

source or to show a fixed MediaPlayer. List of available mediaplayers is
maintained statically at the level of MediaPlayer class.
This commit is contained in:
brunoherbelin
2020-07-10 19:01:17 +02:00
parent 9be5495a05
commit b837e7bf8b
5 changed files with 203 additions and 104 deletions

View File

@@ -21,6 +21,7 @@
#include "imgui.h" #include "imgui.h"
#include "ImGuiToolkit.h" #include "ImGuiToolkit.h"
#include "UserInterfaceManager.h"
#include "SystemToolkit.h" #include "SystemToolkit.h"
@@ -285,8 +286,9 @@ void ImGuiVisitor::visit (MediaSource& s)
} }
else { else {
ImGui::Text("Video File"); ImGui::Text("Video File");
if ( ImGui::Button(IMGUI_TITLE_MEDIAPLAYER, ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) if ( ImGui::Button(IMGUI_TITLE_MEDIAPLAYER, ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) {
Settings::application.widget.media_player = true; UserInterface::manager().showMediaPlayer( s.mediaplayer());
}
} }
ImGuiToolkit::ButtonOpenUrl( SystemToolkit::path_filename(s.path()).c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) ); ImGuiToolkit::ButtonOpenUrl( SystemToolkit::path_filename(s.path()).c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
} }

View File

@@ -24,7 +24,7 @@
#define MEDIA_PLAYER_DEBUG #define MEDIA_PLAYER_DEBUG
#endif #endif
std::list<MediaPlayer*> MediaPlayer::registered_;
MediaPlayer::MediaPlayer(string name) : id_(name) MediaPlayer::MediaPlayer(string name) : id_(name)
{ {
@@ -86,6 +86,7 @@ guint MediaPlayer::texture() const
void MediaPlayer::open(string path) void MediaPlayer::open(string path)
{ {
// set uri to open // set uri to open
filename_ = path;
uri_ = string( gst_uri_construct("file", path.c_str()) ); uri_ = string( gst_uri_construct("file", path.c_str()) );
// reset // reset
@@ -189,6 +190,8 @@ void MediaPlayer::execute_open()
// all good // all good
Log::Info("MediaPlayer %s Open %s (%s %d x %d)", id_.c_str(), uri_.c_str(), codec_name_.c_str(), width_, height_); Log::Info("MediaPlayer %s Open %s (%s %d x %d)", id_.c_str(), uri_.c_str(), codec_name_.c_str(), width_, height_);
ready_ = true; ready_ = true;
MediaPlayer::registered_.push_back(this);
} }
bool MediaPlayer::isOpen() const bool MediaPlayer::isOpen() const
@@ -235,6 +238,8 @@ void MediaPlayer::close()
// un-ready the media player // un-ready the media player
ready_ = false; ready_ = false;
MediaPlayer::registered_.remove(this);
} }
@@ -744,6 +749,11 @@ std::string MediaPlayer::uri() const
return uri_; return uri_;
} }
std::string MediaPlayer::filename() const
{
return filename_;
}
double MediaPlayer::frameRate() const double MediaPlayer::frameRate() const
{ {
return framerate_; return framerate_;

View File

@@ -6,6 +6,7 @@
#include <sstream> #include <sstream>
#include <set> #include <set>
#include <list> #include <list>
#include <map>
#include <utility> #include <utility>
#include <gst/gst.h> #include <gst/gst.h>
@@ -215,12 +216,21 @@ public:
* Get name of the media * Get name of the media
* */ * */
std::string uri() const; std::string uri() const;
std::string filename() const;
/** /**
* Accept visitors * Accept visitors
* */ * */
void accept(Visitor& v); void accept(Visitor& v);
/**
* @brief registered
* @return list of media players currently registered
*/
static std::list<MediaPlayer*> registered() { return registered_; }
static std::list<MediaPlayer*>::const_iterator begin() { return registered_.cbegin(); }
static std::list<MediaPlayer*>::const_iterator end() { return registered_.cend(); }
private: private:
bool addPlaySegment(GstClockTime begin, GstClockTime end); bool addPlaySegment(GstClockTime begin, GstClockTime end);
@@ -230,6 +240,7 @@ private:
std::list< std::pair<guint64, guint64> > getPlaySegments() const; std::list< std::pair<guint64, guint64> > getPlaySegments() const;
std::string id_; std::string id_;
std::string filename_;
std::string uri_; std::string uri_;
guint textureindex_; guint textureindex_;
guint width_; guint width_;
@@ -279,6 +290,7 @@ private:
static void callback_discoverer_process (GstDiscoverer *discoverer, GstDiscovererInfo *info, GError *err, MediaPlayer *m); static void callback_discoverer_process (GstDiscoverer *discoverer, GstDiscovererInfo *info, GError *err, MediaPlayer *m);
static void callback_discoverer_finished(GstDiscoverer *discoverer, MediaPlayer *m); static void callback_discoverer_finished(GstDiscoverer *discoverer, MediaPlayer *m);
static std::list<MediaPlayer*> registered_;
}; };

View File

@@ -582,7 +582,7 @@ void UserInterface::Render()
if (Settings::application.widget.preview) if (Settings::application.widget.preview)
RenderPreview(); RenderPreview();
if (Settings::application.widget.media_player) if (Settings::application.widget.media_player)
RenderMediaPlayer(); mediacontrol.Render();
if (Settings::application.widget.shader_editor) if (Settings::application.widget.shader_editor)
RenderShaderEditor(); RenderShaderEditor();
if (Settings::application.widget.stats) if (Settings::application.widget.stats)
@@ -862,24 +862,52 @@ void UserInterface::RenderPreview()
} }
} }
void UserInterface::RenderMediaPlayer()
{
bool show = false;
MediaPlayer *mp = nullptr;
MediaSource *s = nullptr;
if ( Mixer::manager().currentSource()) {
s = dynamic_cast<MediaSource *>(Mixer::manager().currentSource());
if (s) {
mp = s->mediaplayer();
if (mp && mp->isOpen())
show = true;
}
}
void UserInterface::showMediaPlayer(MediaPlayer *mp)
{
Settings::application.widget.media_player = true;
mediacontrol.setMediaPlayer(mp);
}
#define LABEL_AUTO_MEDIA_PLAYER "Follow active source"
MediaController::MediaController() : mp_(nullptr), current_(LABEL_AUTO_MEDIA_PLAYER), follow_active_source_(true)
{
}
void MediaController::setMediaPlayer(MediaPlayer *mp)
{
if (mp && mp->isOpen()) {
mp_ = mp;
current_ = SystemToolkit::base_filename(mp_->filename());
follow_active_source_ = false;
}
else {
mp_ = nullptr;
current_ = LABEL_AUTO_MEDIA_PLAYER;
follow_active_source_ = true;
}
}
void MediaController::followCurrentSource()
{
Source *s = Mixer::manager().currentSource();
if ( s != nullptr) {
MediaSource *ms = dynamic_cast<MediaSource *>(s);
if (ms)
mp_ = ms->mediaplayer();
else
mp_ = nullptr;
}
}
void MediaController::Render()
{
ImGui::SetNextWindowPos(ImVec2(1180, 400), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(1180, 400), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints(ImVec2(350, 300), ImVec2(FLT_MAX, FLT_MAX)); ImGui::SetNextWindowSizeConstraints(ImVec2(350, 300), ImVec2(FLT_MAX, FLT_MAX));
if ( !ImGui::Begin(IMGUI_TITLE_MEDIAPLAYER, &Settings::application.widget.media_player, ImGuiWindowFlags_NoScrollbar ) || !show) if ( !ImGui::Begin(IMGUI_TITLE_MEDIAPLAYER, &Settings::application.widget.media_player, ImGuiWindowFlags_NoScrollbar ))
{ {
ImGui::End(); ImGui::End();
return; return;
@@ -888,34 +916,63 @@ void UserInterface::RenderMediaPlayer()
float width = ImGui::GetContentRegionAvail().x; float width = ImGui::GetContentRegionAvail().x;
float spacing = ImGui::GetStyle().ItemInnerSpacing.x; float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
ImVec2 imagesize ( width, width / mp->aspectRatio()); // verify that mp is still registered
if ( std::find(MediaPlayer::begin(),MediaPlayer::end(), mp_ ) == MediaPlayer::end() ) {
setMediaPlayer();
}
// display list of available media
ImGui::SetNextItemWidth(width);
if (ImGui::BeginCombo("##MediaPlayers", current_.c_str()))
{
if (ImGui::Selectable( LABEL_AUTO_MEDIA_PLAYER ))
setMediaPlayer();
for (auto mpit = MediaPlayer::begin();
mpit != MediaPlayer::end(); mpit++ )
{
std::string label = (*mpit)->filename();
if (ImGui::Selectable( label.c_str() ))
setMediaPlayer(*mpit);
}
ImGui::EndCombo();
}
// mode auto
if (follow_active_source_)
followCurrentSource();
// Something to show ?
if (mp_ && mp_->isOpen())
{
// display media
ImVec2 imagesize ( width, width / mp_->aspectRatio());
ImVec2 tooltip_pos = ImGui::GetCursorScreenPos(); ImVec2 tooltip_pos = ImGui::GetCursorScreenPos();
ImGui::Image((void*)(uintptr_t)mp->texture(), imagesize); ImGui::Image((void*)(uintptr_t)mp_->texture(), imagesize);
ImVec2 draw_pos = ImGui::GetCursorScreenPos(); ImVec2 draw_pos = ImGui::GetCursorScreenPos();
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImDrawList* draw_list = ImGui::GetWindowDrawList(); ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->AddRectFilled(tooltip_pos, ImVec2(tooltip_pos.x + width, tooltip_pos.y + 3.f * ImGui::GetTextLineHeightWithSpacing()), IM_COL32(55, 55, 55, 200)); draw_list->AddRectFilled(tooltip_pos, ImVec2(tooltip_pos.x + width, tooltip_pos.y + 2.f * ImGui::GetTextLineHeightWithSpacing()), IM_COL32(55, 55, 55, 200));
ImGui::SetCursorScreenPos(tooltip_pos); ImGui::SetCursorScreenPos(tooltip_pos);
ImGui::Text(" %s", SystemToolkit::filename(mp->uri()).c_str()); ImGui::Text(" %s", mp_->codec().c_str());
ImGui::Text(" %s", mp->codec().c_str()); if ( mp_->frameRate() > 0.f )
if ( mp->frameRate() > 0.f ) ImGui::Text(" %d x %d px, %.2f / %.2f fps", mp_->width(), mp_->height(), mp_->updateFrameRate() , mp_->frameRate() );
ImGui::Text(" %d x %d px, %.2f / %.2f fps", mp->width(), mp->height(), mp->updateFrameRate() , mp->frameRate() );
else else
ImGui::Text(" %d x %d px", mp->width(), mp->height()); ImGui::Text(" %d x %d px", mp_->width(), mp_->height());
} }
ImGui::SetCursorScreenPos(draw_pos); ImGui::SetCursorScreenPos(draw_pos);
if ( mp->isEnabled() && mp->duration() != GST_CLOCK_TIME_NONE) { if ( mp_->isEnabled() && mp_->duration() != GST_CLOCK_TIME_NONE) {
if (ImGui::Button(ICON_FA_FAST_BACKWARD)) if (ImGui::Button(ICON_FA_FAST_BACKWARD))
mp->rewind(); mp_->rewind();
ImGui::SameLine(0, spacing); ImGui::SameLine(0, spacing);
// remember playing mode of the GUI // remember playing mode of the GUI
bool media_playing_mode = mp->isPlaying(); bool media_playing_mode = mp_->isPlaying();
// display buttons Play/Stop depending on current playing mode // display buttons Play/Stop depending on current playing mode
if (media_playing_mode) { if (media_playing_mode) {
@@ -926,7 +983,7 @@ void UserInterface::RenderMediaPlayer()
ImGui::PushButtonRepeat(true); ImGui::PushButtonRepeat(true);
if (ImGui::Button(ICON_FA_FORWARD)) if (ImGui::Button(ICON_FA_FORWARD))
mp->fastForward (); mp_->fastForward ();
ImGui::PopButtonRepeat(); ImGui::PopButtonRepeat();
} }
else { else {
@@ -937,7 +994,7 @@ void UserInterface::RenderMediaPlayer()
ImGui::PushButtonRepeat(true); ImGui::PushButtonRepeat(true);
if (ImGui::Button(ICON_FA_STEP_FORWARD)) if (ImGui::Button(ICON_FA_STEP_FORWARD))
mp->seekNextFrame(); mp_->seekNextFrame();
ImGui::PopButtonRepeat(); ImGui::PopButtonRepeat();
} }
@@ -945,35 +1002,35 @@ void UserInterface::RenderMediaPlayer()
static int current_loop = 0; static int current_loop = 0;
static std::vector< std::pair<int, int> > iconsloop = { {0,15}, {1,15}, {19,14} }; static std::vector< std::pair<int, int> > iconsloop = { {0,15}, {1,15}, {19,14} };
current_loop = (int) mp->loop(); current_loop = (int) mp_->loop();
if ( ImGuiToolkit::ButtonIconMultistate(iconsloop, &current_loop) ) if ( ImGuiToolkit::ButtonIconMultistate(iconsloop, &current_loop) )
mp->setLoop( (MediaPlayer::LoopMode) current_loop ); mp_->setLoop( (MediaPlayer::LoopMode) current_loop );
float speed = static_cast<float>(mp->playSpeed()); float speed = static_cast<float>(mp_->playSpeed());
ImGui::SameLine(0, spacing); ImGui::SameLine(0, spacing);
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 40.0); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 40.0);
// ImGui::SetNextItemWidth(width - 90.0); // ImGui::SetNextItemWidth(width - 90.0);
if (ImGui::DragFloat( "##Speed", &speed, 0.01f, -10.f, 10.f, "Speed x %.1f", 2.f)) if (ImGui::DragFloat( "##Speed", &speed, 0.01f, -10.f, 10.f, "Speed x %.1f", 2.f))
mp->setPlaySpeed( static_cast<double>(speed) ); mp_->setPlaySpeed( static_cast<double>(speed) );
ImGui::SameLine(0, spacing); ImGui::SameLine(0, spacing);
if (ImGuiToolkit::ButtonIcon(12, 14)) { if (ImGuiToolkit::ButtonIcon(12, 14)) {
speed = 1.f; speed = 1.f;
mp->setPlaySpeed( static_cast<double>(speed) ); mp_->setPlaySpeed( static_cast<double>(speed) );
mp->setLoop( MediaPlayer::LOOP_REWIND ); mp_->setLoop( MediaPlayer::LOOP_REWIND );
} }
guint64 current_t = mp->position(); guint64 current_t = mp_->position();
guint64 seek_t = current_t; guint64 seek_t = current_t;
bool slider_pressed = ImGuiToolkit::TimelineSlider( "simpletimeline", &seek_t, bool slider_pressed = ImGuiToolkit::TimelineSlider( "simpletimeline", &seek_t,
mp->duration(), mp->frameDuration()); mp_->duration(), mp_->frameDuration());
// if the seek target time is different from the current position time // if the seek target time is different from the current position time
// (i.e. the difference is less than one frame) // (i.e. the difference is less than one frame)
if ( ABS_DIFF (current_t, seek_t) > mp->frameDuration() ) { if ( ABS_DIFF (current_t, seek_t) > mp_->frameDuration() ) {
// request seek (ASYNC) // request seek (ASYNC)
mp->seekTo(seek_t); mp_->seekTo(seek_t);
} }
// play/stop command should be following the playing mode (buttons) // play/stop command should be following the playing mode (buttons)
@@ -983,8 +1040,9 @@ void UserInterface::RenderMediaPlayer()
// apply play action to media only if status should change // apply play action to media only if status should change
// NB: The seek command performed an ASYNC state change, but // NB: The seek command performed an ASYNC state change, but
// gst_element_get_state called in isPlaying() will wait for the state change to complete. // gst_element_get_state called in isPlaying() will wait for the state change to complete.
if ( mp->isPlaying(true) != media_play ) { if ( mp_->isPlaying(true) != media_play ) {
mp->play( media_play ); mp_->play( media_play );
}
} }
} }
@@ -1302,9 +1360,7 @@ void Navigator::Render()
// pannel to configure a selected source // pannel to configure a selected source
else else
{ {
Source *s = Mixer::manager().currentSource(); RenderSourcePannel(Mixer::manager().currentSource());
if (s)
RenderSourcePannel(s);
} }
} }
ImGui::PopStyleColor(2); ImGui::PopStyleColor(2);
@@ -1315,7 +1371,7 @@ void Navigator::Render()
// Source pannel : *s was checked before // Source pannel : *s was checked before
void Navigator::RenderSourcePannel(Source *s) void Navigator::RenderSourcePannel(Source *s)
{ {
if (Settings::application.current_view >3) if (s == nullptr || Settings::application.current_view >3)
return; return;
// Next window is a side pannel // Next window is a side pannel

View File

@@ -13,6 +13,7 @@ using namespace std;
struct ImVec2; struct ImVec2;
class Source; class Source;
class MediaPlayer;
class SourcePreview { class SourcePreview {
@@ -79,11 +80,27 @@ public:
}; };
class MediaController
{
MediaPlayer *mp_;
std::string current_;
bool follow_active_source_;
public:
MediaController();
void setMediaPlayer(MediaPlayer *mp = nullptr);
void followCurrentSource();
void Render();
};
class UserInterface class UserInterface
{ {
friend class Navigator; friend class Navigator;
Navigator navigator; Navigator navigator;
ToolBox toolbox; ToolBox toolbox;
MediaController mediacontrol;
bool keyboard_modifier_active; bool keyboard_modifier_active;
bool show_about; bool show_about;
@@ -131,6 +148,8 @@ public:
void StartScreenshot(); void StartScreenshot();
void showPannel(int id = 0); void showPannel(int id = 0);
void showMediaPlayer(MediaPlayer *mp);
// TODO implement the shader editor // TODO implement the shader editor
std::string currentTextEdit; std::string currentTextEdit;
void fillShaderEditor(std::string text); void fillShaderEditor(std::string text);