mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 18:34:58 +01:00
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:
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "imgui.h"
|
||||
#include "ImGuiToolkit.h"
|
||||
#include "UserInterfaceManager.h"
|
||||
#include "SystemToolkit.h"
|
||||
|
||||
|
||||
@@ -285,8 +286,9 @@ void ImGuiVisitor::visit (MediaSource& s)
|
||||
}
|
||||
else {
|
||||
ImGui::Text("Video File");
|
||||
if ( ImGui::Button(IMGUI_TITLE_MEDIAPLAYER, ImVec2(IMGUI_RIGHT_ALIGN, 0)) )
|
||||
Settings::application.widget.media_player = true;
|
||||
if ( ImGui::Button(IMGUI_TITLE_MEDIAPLAYER, ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) {
|
||||
UserInterface::manager().showMediaPlayer( s.mediaplayer());
|
||||
}
|
||||
}
|
||||
ImGuiToolkit::ButtonOpenUrl( SystemToolkit::path_filename(s.path()).c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define MEDIA_PLAYER_DEBUG
|
||||
#endif
|
||||
|
||||
|
||||
std::list<MediaPlayer*> MediaPlayer::registered_;
|
||||
|
||||
MediaPlayer::MediaPlayer(string name) : id_(name)
|
||||
{
|
||||
@@ -86,6 +86,7 @@ guint MediaPlayer::texture() const
|
||||
void MediaPlayer::open(string path)
|
||||
{
|
||||
// set uri to open
|
||||
filename_ = path;
|
||||
uri_ = string( gst_uri_construct("file", path.c_str()) );
|
||||
|
||||
// reset
|
||||
@@ -189,6 +190,8 @@ void MediaPlayer::execute_open()
|
||||
// all good
|
||||
Log::Info("MediaPlayer %s Open %s (%s %d x %d)", id_.c_str(), uri_.c_str(), codec_name_.c_str(), width_, height_);
|
||||
ready_ = true;
|
||||
|
||||
MediaPlayer::registered_.push_back(this);
|
||||
}
|
||||
|
||||
bool MediaPlayer::isOpen() const
|
||||
@@ -235,6 +238,8 @@ void MediaPlayer::close()
|
||||
|
||||
// un-ready the media player
|
||||
ready_ = false;
|
||||
|
||||
MediaPlayer::registered_.remove(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -744,6 +749,11 @@ std::string MediaPlayer::uri() const
|
||||
return uri_;
|
||||
}
|
||||
|
||||
std::string MediaPlayer::filename() const
|
||||
{
|
||||
return filename_;
|
||||
}
|
||||
|
||||
double MediaPlayer::frameRate() const
|
||||
{
|
||||
return framerate_;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
#include <gst/gst.h>
|
||||
@@ -215,12 +216,21 @@ public:
|
||||
* Get name of the media
|
||||
* */
|
||||
std::string uri() const;
|
||||
std::string filename() const;
|
||||
|
||||
/**
|
||||
* Accept visitors
|
||||
* */
|
||||
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:
|
||||
|
||||
bool addPlaySegment(GstClockTime begin, GstClockTime end);
|
||||
@@ -230,6 +240,7 @@ private:
|
||||
std::list< std::pair<guint64, guint64> > getPlaySegments() const;
|
||||
|
||||
std::string id_;
|
||||
std::string filename_;
|
||||
std::string uri_;
|
||||
guint textureindex_;
|
||||
guint width_;
|
||||
@@ -279,6 +290,7 @@ private:
|
||||
static void callback_discoverer_process (GstDiscoverer *discoverer, GstDiscovererInfo *info, GError *err, MediaPlayer *m);
|
||||
static void callback_discoverer_finished(GstDiscoverer *discoverer, MediaPlayer *m);
|
||||
|
||||
static std::list<MediaPlayer*> registered_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -582,7 +582,7 @@ void UserInterface::Render()
|
||||
if (Settings::application.widget.preview)
|
||||
RenderPreview();
|
||||
if (Settings::application.widget.media_player)
|
||||
RenderMediaPlayer();
|
||||
mediacontrol.Render();
|
||||
if (Settings::application.widget.shader_editor)
|
||||
RenderShaderEditor();
|
||||
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::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
|
||||
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();
|
||||
return;
|
||||
@@ -888,34 +916,63 @@ void UserInterface::RenderMediaPlayer()
|
||||
float width = ImGui::GetContentRegionAvail().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();
|
||||
ImGui::Image((void*)(uintptr_t)mp->texture(), imagesize);
|
||||
ImGui::Image((void*)(uintptr_t)mp_->texture(), imagesize);
|
||||
ImVec2 draw_pos = ImGui::GetCursorScreenPos();
|
||||
if (ImGui::IsItemHovered()) {
|
||||
|
||||
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::Text(" %s", SystemToolkit::filename(mp->uri()).c_str());
|
||||
ImGui::Text(" %s", mp->codec().c_str());
|
||||
if ( mp->frameRate() > 0.f )
|
||||
ImGui::Text(" %d x %d px, %.2f / %.2f fps", mp->width(), mp->height(), mp->updateFrameRate() , mp->frameRate() );
|
||||
ImGui::Text(" %s", mp_->codec().c_str());
|
||||
if ( mp_->frameRate() > 0.f )
|
||||
ImGui::Text(" %d x %d px, %.2f / %.2f fps", mp_->width(), mp_->height(), mp_->updateFrameRate() , mp_->frameRate() );
|
||||
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);
|
||||
|
||||
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))
|
||||
mp->rewind();
|
||||
mp_->rewind();
|
||||
ImGui::SameLine(0, spacing);
|
||||
|
||||
// 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
|
||||
if (media_playing_mode) {
|
||||
@@ -926,7 +983,7 @@ void UserInterface::RenderMediaPlayer()
|
||||
|
||||
ImGui::PushButtonRepeat(true);
|
||||
if (ImGui::Button(ICON_FA_FORWARD))
|
||||
mp->fastForward ();
|
||||
mp_->fastForward ();
|
||||
ImGui::PopButtonRepeat();
|
||||
}
|
||||
else {
|
||||
@@ -937,7 +994,7 @@ void UserInterface::RenderMediaPlayer()
|
||||
|
||||
ImGui::PushButtonRepeat(true);
|
||||
if (ImGui::Button(ICON_FA_STEP_FORWARD))
|
||||
mp->seekNextFrame();
|
||||
mp_->seekNextFrame();
|
||||
ImGui::PopButtonRepeat();
|
||||
}
|
||||
|
||||
@@ -945,35 +1002,35 @@ void UserInterface::RenderMediaPlayer()
|
||||
|
||||
static int current_loop = 0;
|
||||
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, ¤t_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::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 40.0);
|
||||
// ImGui::SetNextItemWidth(width - 90.0);
|
||||
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);
|
||||
if (ImGuiToolkit::ButtonIcon(12, 14)) {
|
||||
speed = 1.f;
|
||||
mp->setPlaySpeed( static_cast<double>(speed) );
|
||||
mp->setLoop( MediaPlayer::LOOP_REWIND );
|
||||
mp_->setPlaySpeed( static_cast<double>(speed) );
|
||||
mp_->setLoop( MediaPlayer::LOOP_REWIND );
|
||||
}
|
||||
|
||||
guint64 current_t = mp->position();
|
||||
guint64 current_t = mp_->position();
|
||||
guint64 seek_t = current_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
|
||||
// (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)
|
||||
mp->seekTo(seek_t);
|
||||
mp_->seekTo(seek_t);
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
if ( mp->isPlaying(true) != media_play ) {
|
||||
mp->play( media_play );
|
||||
if ( mp_->isPlaying(true) != media_play ) {
|
||||
mp_->play( media_play );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1302,9 +1360,7 @@ void Navigator::Render()
|
||||
// pannel to configure a selected source
|
||||
else
|
||||
{
|
||||
Source *s = Mixer::manager().currentSource();
|
||||
if (s)
|
||||
RenderSourcePannel(s);
|
||||
RenderSourcePannel(Mixer::manager().currentSource());
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor(2);
|
||||
@@ -1315,7 +1371,7 @@ void Navigator::Render()
|
||||
// Source pannel : *s was checked before
|
||||
void Navigator::RenderSourcePannel(Source *s)
|
||||
{
|
||||
if (Settings::application.current_view >3)
|
||||
if (s == nullptr || Settings::application.current_view >3)
|
||||
return;
|
||||
|
||||
// Next window is a side pannel
|
||||
|
||||
@@ -13,6 +13,7 @@ using namespace std;
|
||||
|
||||
struct ImVec2;
|
||||
class Source;
|
||||
class MediaPlayer;
|
||||
|
||||
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
|
||||
{
|
||||
friend class Navigator;
|
||||
Navigator navigator;
|
||||
ToolBox toolbox;
|
||||
MediaController mediacontrol;
|
||||
|
||||
bool keyboard_modifier_active;
|
||||
bool show_about;
|
||||
@@ -131,6 +148,8 @@ public:
|
||||
void StartScreenshot();
|
||||
void showPannel(int id = 0);
|
||||
|
||||
void showMediaPlayer(MediaPlayer *mp);
|
||||
|
||||
// TODO implement the shader editor
|
||||
std::string currentTextEdit;
|
||||
void fillShaderEditor(std::string text);
|
||||
|
||||
Reference in New Issue
Block a user