Bugfix MediaPlayer, ButtonOpenUrl and UserInterfaceManager

This commit is contained in:
brunoherbelin
2020-05-21 14:12:36 +02:00
parent 34c9d85863
commit 5b489dd2df
10 changed files with 102 additions and 78 deletions

View File

@@ -21,32 +21,19 @@
#include "FileDialog.h"
#include "ImGuiToolkit.h"
#include "GstToolkit.h"
#include "SystemToolkit.h"
unsigned int textureicons = 0;
std::map <ImGuiToolkit::font_style, ImFont*>fontmap;
void ImGuiToolkit::ButtonOpenWebpage( const char* url )
void ImGuiToolkit::ButtonOpenUrl( const char* url, const ImVec2& size_arg )
{
char label[512];
sprintf( label, "%s %s", ICON_FA_EXTERNAL_LINK_ALT, url );
if ( ImGui::Button(label) )
{
#ifdef _WIN32
ShellExecuteA( nullptr, nullptr, url, nullptr, nullptr, 0 );
#elif defined __APPLE__
char buf[1024];
sprintf( buf, "open %s", url );
system( buf );
#else
char buf[1024];
sprintf( buf, "xdg-open %s", url );
system( buf );
#endif
}
if ( ImGui::Button(label, size_arg) )
SystemToolkit::open(url);
}

View File

@@ -21,7 +21,7 @@ namespace ImGuiToolkit
bool ButtonIconMultistate(std::vector<std::pair<int, int> > icons, int* state);
void ButtonToggle( const char* label, bool* toggle );
void ButtonSwitch(const char* label, bool* toggle , const char *help = nullptr);
void ButtonOpenWebpage( const char* url );
void ButtonOpenUrl( const char* url, const ImVec2& size_arg = ImVec2(0,0));
void HelpMarker(const char* desc);

View File

@@ -21,6 +21,7 @@
#include "imgui.h"
#include "ImGuiToolkit.h"
#include "SystemToolkit.h"
ImGuiVisitor::ImGuiVisitor()
@@ -278,6 +279,7 @@ void ImGuiVisitor::visit (MediaSource& s)
if (ImGui::Button("Open Media Player", ImVec2(IMGUI_RIGHT_ALIGN, 0)) )
Settings::application.media_player = true;
}
ImGuiToolkit::ButtonOpenUrl( SystemToolkit::path_filename(s.path()).c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
}
void ImGuiVisitor::visit (SessionSource& s)
@@ -286,4 +288,5 @@ void ImGuiVisitor::visit (SessionSource& s)
ImGui::Text("Session");
if (ImGui::Button("Make Current", ImVec2(IMGUI_RIGHT_ALIGN, 0)) )
Mixer::manager().set( s.detach() );
ImGuiToolkit::ButtonOpenUrl( SystemToolkit::path_filename(s.path()).c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
}

View File

@@ -610,7 +610,7 @@ double MediaPlayer::updateFrameRate() const
// CALLBACKS
bool MediaPlayer::fill_v_frame(GstBuffer *buf)
bool MediaPlayer::fill_v_frame(GstBuffer *buf, bool ignorepts)
{
// always empty frame before filling it again
if (v_frame_.buffer)
@@ -618,7 +618,7 @@ bool MediaPlayer::fill_v_frame(GstBuffer *buf)
// get the frame from buffer
if ( !gst_video_frame_map (&v_frame_, &v_frame_video_info_, buf, GST_MAP_READ ) ) {
Log::Info("MediaPlayer %s Failed to map the video buffer");
Log::Info("MediaPlayer %s Failed to map the video buffer", id_.c_str());
return false;
}
@@ -626,7 +626,8 @@ bool MediaPlayer::fill_v_frame(GstBuffer *buf)
if( GST_VIDEO_INFO_IS_RGB(&(v_frame_).info) && GST_VIDEO_INFO_N_PLANES(&(v_frame_).info) == 1) {
// validate time
if (position_ != buf->pts) {
if (ignorepts || position_ != buf->pts)
{
// got a new RGB frame !
v_frame_is_full_ = true;
@@ -664,7 +665,7 @@ GstFlowReturn MediaPlayer::callback_pull_sample_video (GstElement *bin, MediaPla
GstBuffer *buf = gst_buffer_ref ( gst_sample_get_buffer (sample) );
// fill frame from buffer
if ( !m->fill_v_frame(buf) )
if ( !m->fill_v_frame(buf, m->isimage_) )
ret = GST_FLOW_ERROR;
// free buffer
gst_buffer_unref (buf);

View File

@@ -255,7 +255,7 @@ private:
void execute_open();
void execute_loop_command();
void execute_seek_command(GstClockTime target = GST_CLOCK_TIME_NONE);
bool fill_v_frame(GstBuffer *buf);
bool fill_v_frame(GstBuffer *buf, bool ignorepts = false);
static GstFlowReturn callback_pull_sample_video (GstElement *bin, MediaPlayer *m);
static void callback_end_of_video (GstElement *, MediaPlayer *m);

View File

@@ -143,7 +143,7 @@ void Source::update(float dt)
// ADJUST alpha based on MIXING node
// read position of the mixing node and interpret this as transparency of render output
glm::vec2 dist = glm::vec2(groups_[View::MIXING]->translation_);
float alpha = 1.0 - CLAMP( SQUARE( glm::length(dist) ), 0.f, 1.f );
float alpha = 1.0 - CLAMP( ( dist.x * dist.x ) + ( dist.y * dist.y ), 0.f, 1.f );
blendingshader_->color.a = alpha;
// MODIFY geometry based on GEOMETRY node

View File

@@ -146,3 +146,18 @@ bool SystemToolkit::create_directory(const string& path)
// TODO : verify WIN32 implementation
}
void SystemToolkit::open(const std::string& url)
{
#ifdef WIN32
ShellExecuteA( nullptr, nullptr, url.c_str(), nullptr, nullptr, 0 );
#elif defined APPLE
char buf[2048];
sprintf( buf, "open '%s'", url.c_str() );
system( buf );
#else
char buf[2048];
sprintf( buf, "xdg-open '%s'", url.c_str() );
system( buf );
#endif
}

View File

@@ -39,6 +39,8 @@ namespace SystemToolkit
// true if directory could be created
bool create_directory(const std::string& path);
// try to open the file with system
void open(const std::string& path);
}
#endif // SYSTEMTOOLKIT_H

View File

@@ -58,15 +58,15 @@ void ShowAboutOpengl(bool* p_open);
void ShowAbout(bool* p_open);
// static objects for multithreaded file dialog
static std::atomic<bool> FileDialogPending_ = false;
static std::atomic<bool> SessionFileDialogLoadFinished_ = false;
static std::atomic<bool> SessionFileDialogSaveFinished_ = false;
static std::string SessionFileDialogFilename_ = "";
static std::atomic<bool> fileDialogPending_ = false;
static std::atomic<bool> sessionFileDialogLoadFinished_ = false;
static std::atomic<bool> sessionFileDialogSaveFinished_ = false;
static std::string sessionFileDialogFilename_ = "";
static void SessionFileDialogOpen(std::string path)
{
FileDialogPending_ = true;
SessionFileDialogLoadFinished_ = false;
fileDialogPending_ = true;
sessionFileDialogLoadFinished_ = false;
char const * open_file_name;
char const * open_pattern[1] = { "*.vmx" };
@@ -74,17 +74,17 @@ static void SessionFileDialogOpen(std::string path)
open_file_name = tinyfd_openFileDialog( "Open a session file", path.c_str(), 1, open_pattern, "vimix session", 0);
if (!open_file_name)
SessionFileDialogFilename_ = "";
sessionFileDialogFilename_ = "";
else
SessionFileDialogFilename_ = std::string( open_file_name );
sessionFileDialogFilename_ = std::string( open_file_name );
SessionFileDialogLoadFinished_ = true;
sessionFileDialogLoadFinished_ = true;
}
static void SessionFileDialogSave(std::string path)
{
FileDialogPending_ = true;
SessionFileDialogSaveFinished_ = false;
fileDialogPending_ = true;
sessionFileDialogSaveFinished_ = false;
char const * save_file_name;
char const * save_pattern[1] = { "*.vmx" };
@@ -92,32 +92,32 @@ static void SessionFileDialogSave(std::string path)
save_file_name = tinyfd_saveFileDialog( "Save a session file", path.c_str(), 1, save_pattern, "vimix session");
if (!save_file_name)
SessionFileDialogFilename_ = "";
sessionFileDialogFilename_ = "";
else
{
SessionFileDialogFilename_ = std::string( save_file_name );
sessionFileDialogFilename_ = std::string( save_file_name );
// check extension
std::string extension = SessionFileDialogFilename_.substr(SessionFileDialogFilename_.find_last_of(".") + 1);
std::string extension = sessionFileDialogFilename_.substr(sessionFileDialogFilename_.find_last_of(".") + 1);
if (extension != "vmx")
SessionFileDialogFilename_ += ".vmx";
sessionFileDialogFilename_ += ".vmx";
}
SessionFileDialogSaveFinished_ = true;
sessionFileDialogSaveFinished_ = true;
}
static void ImportFileDialogOpen(char *filename, const std::string &path)
{
if (FileDialogPending_)
if (fileDialogPending_)
return;
FileDialogPending_ = true;
fileDialogPending_ = true;
char const * open_pattern[17] = { "*vmx", "*.mp4", "*.mpg", "*.avi", "*.mov", "*.mkv", "*.webm", "*.mod", "*.wmv", "*.mxf", "*.ogg", "*.flv", "*.asf", "*.jpg", "*.png", "*.gif", "*.svg" };
char const * open_pattern[18] = { "*vmx", "*.mp4", "*.mpg", "*.avi", "*.mov", "*.mkv", "*.webm", "*.mod", "*.wmv", "*.mxf", "*.ogg", "*.flv", "*.asf", "*.jpg", "*.png", "*.gif", "*.tif", "*.svg" };
char const * open_file_name;
open_file_name = tinyfd_openFileDialog( "Import a file", path.c_str(), 17, open_pattern, "All supported formats", 0);
open_file_name = tinyfd_openFileDialog( "Import a file", path.c_str(), 18, open_pattern, "All supported formats", 0);
sprintf(filename, "%s", open_file_name);
FileDialogPending_ = false;
fileDialogPending_ = false;
}
UserInterface::UserInterface()
@@ -239,17 +239,12 @@ void UserInterface::handleKeyboard()
}
}
// No CTRL modifier
else {
// TODO make sure no entry / window box is active
keyboard_modifier_active = false;
// Action keys
if (ImGui::IsKeyPressed( GLFW_KEY_BACKSPACE ))
Mixer::manager().deleteCurrentSource();
else if (ImGui::IsKeyPressed( GLFW_KEY_GRAVE_ACCENT ))
navigator.toggleMenu();
// Application F-Keys
else if (ImGui::IsKeyPressed( GLFW_KEY_F1 ))
if (ImGui::IsKeyPressed( GLFW_KEY_F1 ))
Mixer::manager().setCurrentView(View::MIXING);
else if (ImGui::IsKeyPressed( GLFW_KEY_F2 ))
Mixer::manager().setCurrentView(View::GEOMETRY);
@@ -257,12 +252,22 @@ void UserInterface::handleKeyboard()
Mixer::manager().setCurrentView(View::LAYER);
else if (ImGui::IsKeyPressed( GLFW_KEY_F11 ))
Rendering::manager().ToggleFullscreen();
else if (ImGui::IsKeyPressed( GLFW_KEY_F12 ))
toolbox.StartScreenshot();
// normal keys // make sure no entry / window box is active
else if ( !ImGui::IsAnyWindowFocused() ){
// Backspace to delete source
if (ImGui::IsKeyPressed( GLFW_KEY_BACKSPACE ))
Mixer::manager().deleteCurrentSource();
// button under esc to toggle menu
else if (ImGui::IsKeyPressed( GLFW_KEY_GRAVE_ACCENT ))
navigator.toggleMenu();
// esc to exit fullscreen
else if (ImGui::IsKeyPressed( GLFW_KEY_ESCAPE )){
if (Rendering::manager().IsFullscreen())
Rendering::manager().ToggleFullscreen();
}
else if (ImGui::IsKeyPressed( GLFW_KEY_F12 ))
toolbox.StartScreenshot();
}
}
}
@@ -327,10 +332,13 @@ void UserInterface::handleMouse()
else {
// Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y);
// Selection area
ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered));
ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f));
// ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
// ImGui::GetColorU32(ImGuiCol_ResizeGripHovered));
// ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
// ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f));
// TODO Multiple sources selection
}
}
else if ( ImGui::IsMouseDown(ImGuiMouseButton_Left) ) {
@@ -378,25 +386,25 @@ void UserInterface::NewFrame()
handleMouse();
// handle FileDialog
if (SessionFileDialogLoadFinished_) {
SessionFileDialogLoadFinished_ = false;
FileDialogPending_ = false;
if (!SessionFileDialogFilename_.empty()) {
Mixer::manager().open(SessionFileDialogFilename_);
Settings::application.recentSessions.path = SystemToolkit::path_filename(SessionFileDialogFilename_);
if (sessionFileDialogLoadFinished_) {
sessionFileDialogLoadFinished_ = false;
fileDialogPending_ = false;
if (!sessionFileDialogFilename_.empty()) {
Mixer::manager().open(sessionFileDialogFilename_);
Settings::application.recentSessions.path = SystemToolkit::path_filename(sessionFileDialogFilename_);
}
}
if (SessionFileDialogSaveFinished_) {
SessionFileDialogSaveFinished_ = false;
FileDialogPending_ = false;
if (!SessionFileDialogFilename_.empty()) {
Mixer::manager().saveas(SessionFileDialogFilename_);
Settings::application.recentSessions.path = SystemToolkit::path_filename(SessionFileDialogFilename_);
if (sessionFileDialogSaveFinished_) {
sessionFileDialogSaveFinished_ = false;
fileDialogPending_ = false;
if (!sessionFileDialogFilename_.empty()) {
Mixer::manager().saveas(sessionFileDialogFilename_);
Settings::application.recentSessions.path = SystemToolkit::path_filename(sessionFileDialogFilename_);
}
}
// overlay to ensure file dialog is modal
if (FileDialogPending_){
if (fileDialogPending_){
ImGui::OpenPopup("Busy");
if (ImGui::BeginPopupModal("Busy", NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
@@ -913,6 +921,7 @@ void Navigator::Render()
// the "=" icon for menu
if (ImGui::Selectable( ICON_FA_BARS, &selected_button[NAV_MENU], 0, iconsize))
{
Mixer::manager().unsetCurrentSource();
toggle(NAV_MENU);
}
// the list of INITIALS for sources
@@ -984,6 +993,10 @@ void Navigator::Render()
// window menu
if (selected_button[NAV_MENU])
{
// if a source is selected in the meantime, revert to selected source pannel
if (Mixer::manager().indexCurrentSource() > -1 )
selected_button[NAV_MENU] = false;
else
RenderMainPannel();
}
// window to create a source
@@ -1234,7 +1247,7 @@ void ShowAbout(bool* p_open)
ImGui::Separator();
ImGui::Text("vimix is a video mixing software for live performance.");
ImGui::Text("vimix is licensed under the GNU GPL version 3. Copyright 2019-2020 Bruno Herbelin.");
ImGuiToolkit::ButtonOpenWebpage("https://github.com/brunoherbelin/v-mix");
ImGuiToolkit::ButtonOpenUrl("https://github.com/brunoherbelin/v-mix");
ImGui::End();
}
@@ -1253,7 +1266,7 @@ void ShowAboutOpengl(bool* p_open)
ImGui::PopFont();
ImGui::Separator();
ImGui::Text("OpenGL is the premier environment for developing portable, \ninteractive 2D and 3D graphics applications.");
ImGuiToolkit::ButtonOpenWebpage("https://www.opengl.org");
ImGuiToolkit::ButtonOpenUrl("https://www.opengl.org");
ImGui::SameLine();
static bool show_opengl_info = false;
@@ -1320,7 +1333,7 @@ void ShowAboutGStreamer(bool* p_open)
ImGui::Separator();
ImGui::Text("A flexible, fast and multiplatform multimedia framework.");
ImGui::Text("GStreamer is licensed under the LGPL License.");
ImGuiToolkit::ButtonOpenWebpage("https://gstreamer.freedesktop.org/");
ImGuiToolkit::ButtonOpenUrl("https://gstreamer.freedesktop.org/");
ImGui::SameLine();
static bool show_config_info = false;

View File

@@ -75,8 +75,11 @@ int main(int, char**)
/// GStreamer
///
#ifndef NDEBUG
gst_debug_set_default_threshold (GST_LEVEL_ERROR);
gst_debug_set_default_threshold (GST_LEVEL_WARNING);
gst_debug_set_active(TRUE);
#else
gst_debug_set_default_threshold (GST_LEVEL_ERROR);
gst_debug_set_active(FALSE);
#endif
// test text editor