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 "FileDialog.h"
#include "ImGuiToolkit.h" #include "ImGuiToolkit.h"
#include "GstToolkit.h" #include "GstToolkit.h"
#include "SystemToolkit.h"
unsigned int textureicons = 0; unsigned int textureicons = 0;
std::map <ImGuiToolkit::font_style, ImFont*>fontmap; 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]; char label[512];
sprintf( label, "%s %s", ICON_FA_EXTERNAL_LINK_ALT, url ); sprintf( label, "%s %s", ICON_FA_EXTERNAL_LINK_ALT, url );
if ( ImGui::Button(label) ) if ( ImGui::Button(label, size_arg) )
{ SystemToolkit::open(url);
#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
}
} }

View File

@@ -21,7 +21,7 @@ namespace ImGuiToolkit
bool ButtonIconMultistate(std::vector<std::pair<int, int> > icons, int* state); bool ButtonIconMultistate(std::vector<std::pair<int, int> > icons, int* state);
void ButtonToggle( const char* label, bool* toggle ); void ButtonToggle( const char* label, bool* toggle );
void ButtonSwitch(const char* label, bool* toggle , const char *help = nullptr); 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); void HelpMarker(const char* desc);

View File

@@ -21,6 +21,7 @@
#include "imgui.h" #include "imgui.h"
#include "ImGuiToolkit.h" #include "ImGuiToolkit.h"
#include "SystemToolkit.h"
ImGuiVisitor::ImGuiVisitor() ImGuiVisitor::ImGuiVisitor()
@@ -278,6 +279,7 @@ void ImGuiVisitor::visit (MediaSource& s)
if (ImGui::Button("Open Media Player", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) if (ImGui::Button("Open Media Player", ImVec2(IMGUI_RIGHT_ALIGN, 0)) )
Settings::application.media_player = true; Settings::application.media_player = true;
} }
ImGuiToolkit::ButtonOpenUrl( SystemToolkit::path_filename(s.path()).c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
} }
void ImGuiVisitor::visit (SessionSource& s) void ImGuiVisitor::visit (SessionSource& s)
@@ -286,4 +288,5 @@ void ImGuiVisitor::visit (SessionSource& s)
ImGui::Text("Session"); ImGui::Text("Session");
if (ImGui::Button("Make Current", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) if (ImGui::Button("Make Current", ImVec2(IMGUI_RIGHT_ALIGN, 0)) )
Mixer::manager().set( s.detach() ); 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 // CALLBACKS
bool MediaPlayer::fill_v_frame(GstBuffer *buf) bool MediaPlayer::fill_v_frame(GstBuffer *buf, bool ignorepts)
{ {
// always empty frame before filling it again // always empty frame before filling it again
if (v_frame_.buffer) if (v_frame_.buffer)
@@ -618,7 +618,7 @@ bool MediaPlayer::fill_v_frame(GstBuffer *buf)
// get the frame from buffer // get the frame from buffer
if ( !gst_video_frame_map (&v_frame_, &v_frame_video_info_, buf, GST_MAP_READ ) ) { 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; 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) { if( GST_VIDEO_INFO_IS_RGB(&(v_frame_).info) && GST_VIDEO_INFO_N_PLANES(&(v_frame_).info) == 1) {
// validate time // validate time
if (position_ != buf->pts) { if (ignorepts || position_ != buf->pts)
{
// got a new RGB frame ! // got a new RGB frame !
v_frame_is_full_ = true; 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) ); GstBuffer *buf = gst_buffer_ref ( gst_sample_get_buffer (sample) );
// fill frame from buffer // fill frame from buffer
if ( !m->fill_v_frame(buf) ) if ( !m->fill_v_frame(buf, m->isimage_) )
ret = GST_FLOW_ERROR; ret = GST_FLOW_ERROR;
// free buffer // free buffer
gst_buffer_unref (buf); gst_buffer_unref (buf);

View File

@@ -255,7 +255,7 @@ private:
void execute_open(); void execute_open();
void execute_loop_command(); void execute_loop_command();
void execute_seek_command(GstClockTime target = GST_CLOCK_TIME_NONE); 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 GstFlowReturn callback_pull_sample_video (GstElement *bin, MediaPlayer *m);
static void callback_end_of_video (GstElement *, 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 // ADJUST alpha based on MIXING node
// read position of the mixing node and interpret this as transparency of render output // read position of the mixing node and interpret this as transparency of render output
glm::vec2 dist = glm::vec2(groups_[View::MIXING]->translation_); 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; blendingshader_->color.a = alpha;
// MODIFY geometry based on GEOMETRY node // MODIFY geometry based on GEOMETRY node

View File

@@ -146,3 +146,18 @@ bool SystemToolkit::create_directory(const string& path)
// TODO : verify WIN32 implementation // 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 // true if directory could be created
bool create_directory(const std::string& path); bool create_directory(const std::string& path);
// try to open the file with system
void open(const std::string& path);
} }
#endif // SYSTEMTOOLKIT_H #endif // SYSTEMTOOLKIT_H

View File

@@ -58,15 +58,15 @@ void ShowAboutOpengl(bool* p_open);
void ShowAbout(bool* p_open); void ShowAbout(bool* p_open);
// static objects for multithreaded file dialog // static objects for multithreaded file dialog
static std::atomic<bool> FileDialogPending_ = false; static std::atomic<bool> fileDialogPending_ = false;
static std::atomic<bool> SessionFileDialogLoadFinished_ = false; static std::atomic<bool> sessionFileDialogLoadFinished_ = false;
static std::atomic<bool> SessionFileDialogSaveFinished_ = false; static std::atomic<bool> sessionFileDialogSaveFinished_ = false;
static std::string SessionFileDialogFilename_ = ""; static std::string sessionFileDialogFilename_ = "";
static void SessionFileDialogOpen(std::string path) static void SessionFileDialogOpen(std::string path)
{ {
FileDialogPending_ = true; fileDialogPending_ = true;
SessionFileDialogLoadFinished_ = false; sessionFileDialogLoadFinished_ = false;
char const * open_file_name; char const * open_file_name;
char const * open_pattern[1] = { "*.vmx" }; 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); open_file_name = tinyfd_openFileDialog( "Open a session file", path.c_str(), 1, open_pattern, "vimix session", 0);
if (!open_file_name) if (!open_file_name)
SessionFileDialogFilename_ = ""; sessionFileDialogFilename_ = "";
else else
SessionFileDialogFilename_ = std::string( open_file_name ); sessionFileDialogFilename_ = std::string( open_file_name );
SessionFileDialogLoadFinished_ = true; sessionFileDialogLoadFinished_ = true;
} }
static void SessionFileDialogSave(std::string path) static void SessionFileDialogSave(std::string path)
{ {
FileDialogPending_ = true; fileDialogPending_ = true;
SessionFileDialogSaveFinished_ = false; sessionFileDialogSaveFinished_ = false;
char const * save_file_name; char const * save_file_name;
char const * save_pattern[1] = { "*.vmx" }; 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"); save_file_name = tinyfd_saveFileDialog( "Save a session file", path.c_str(), 1, save_pattern, "vimix session");
if (!save_file_name) if (!save_file_name)
SessionFileDialogFilename_ = ""; sessionFileDialogFilename_ = "";
else else
{ {
SessionFileDialogFilename_ = std::string( save_file_name ); sessionFileDialogFilename_ = std::string( save_file_name );
// check extension // 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") if (extension != "vmx")
SessionFileDialogFilename_ += ".vmx"; sessionFileDialogFilename_ += ".vmx";
} }
SessionFileDialogSaveFinished_ = true; sessionFileDialogSaveFinished_ = true;
} }
static void ImportFileDialogOpen(char *filename, const std::string &path) static void ImportFileDialogOpen(char *filename, const std::string &path)
{ {
if (FileDialogPending_) if (fileDialogPending_)
return; 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; 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); sprintf(filename, "%s", open_file_name);
FileDialogPending_ = false; fileDialogPending_ = false;
} }
UserInterface::UserInterface() UserInterface::UserInterface()
@@ -239,17 +239,12 @@ void UserInterface::handleKeyboard()
} }
} }
// No CTRL modifier
else { else {
// TODO make sure no entry / window box is active
keyboard_modifier_active = false; 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 // Application F-Keys
else if (ImGui::IsKeyPressed( GLFW_KEY_F1 )) if (ImGui::IsKeyPressed( GLFW_KEY_F1 ))
Mixer::manager().setCurrentView(View::MIXING); Mixer::manager().setCurrentView(View::MIXING);
else if (ImGui::IsKeyPressed( GLFW_KEY_F2 )) else if (ImGui::IsKeyPressed( GLFW_KEY_F2 ))
Mixer::manager().setCurrentView(View::GEOMETRY); Mixer::manager().setCurrentView(View::GEOMETRY);
@@ -257,12 +252,22 @@ void UserInterface::handleKeyboard()
Mixer::manager().setCurrentView(View::LAYER); Mixer::manager().setCurrentView(View::LAYER);
else if (ImGui::IsKeyPressed( GLFW_KEY_F11 )) else if (ImGui::IsKeyPressed( GLFW_KEY_F11 ))
Rendering::manager().ToggleFullscreen(); 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 )){ else if (ImGui::IsKeyPressed( GLFW_KEY_ESCAPE )){
if (Rendering::manager().IsFullscreen()) if (Rendering::manager().IsFullscreen())
Rendering::manager().ToggleFullscreen(); Rendering::manager().ToggleFullscreen();
} }
else if (ImGui::IsKeyPressed( GLFW_KEY_F12 )) }
toolbox.StartScreenshot();
} }
} }
@@ -327,10 +332,13 @@ void UserInterface::handleMouse()
else { else {
// Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y); // Log::Info("Mouse drag (%.1f,%.1f)(%.1f,%.1f)", io.MouseClickedPos[0].x, io.MouseClickedPos[0].y, io.MousePos.x, io.MousePos.y);
// Selection area // Selection area
ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos, // ImGui::GetBackgroundDrawList()->AddRect(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered)); // ImGui::GetColorU32(ImGuiCol_ResizeGripHovered));
ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos, // ImGui::GetBackgroundDrawList()->AddRectFilled(io.MouseClickedPos[ImGuiMouseButton_Left], io.MousePos,
ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f)); // ImGui::GetColorU32(ImGuiCol_ResizeGripHovered, 0.3f));
// TODO Multiple sources selection
} }
} }
else if ( ImGui::IsMouseDown(ImGuiMouseButton_Left) ) { else if ( ImGui::IsMouseDown(ImGuiMouseButton_Left) ) {
@@ -378,25 +386,25 @@ void UserInterface::NewFrame()
handleMouse(); handleMouse();
// handle FileDialog // handle FileDialog
if (SessionFileDialogLoadFinished_) { if (sessionFileDialogLoadFinished_) {
SessionFileDialogLoadFinished_ = false; sessionFileDialogLoadFinished_ = false;
FileDialogPending_ = false; fileDialogPending_ = false;
if (!SessionFileDialogFilename_.empty()) { if (!sessionFileDialogFilename_.empty()) {
Mixer::manager().open(SessionFileDialogFilename_); Mixer::manager().open(sessionFileDialogFilename_);
Settings::application.recentSessions.path = SystemToolkit::path_filename(SessionFileDialogFilename_); Settings::application.recentSessions.path = SystemToolkit::path_filename(sessionFileDialogFilename_);
} }
} }
if (SessionFileDialogSaveFinished_) { if (sessionFileDialogSaveFinished_) {
SessionFileDialogSaveFinished_ = false; sessionFileDialogSaveFinished_ = false;
FileDialogPending_ = false; fileDialogPending_ = false;
if (!SessionFileDialogFilename_.empty()) { if (!sessionFileDialogFilename_.empty()) {
Mixer::manager().saveas(SessionFileDialogFilename_); Mixer::manager().saveas(sessionFileDialogFilename_);
Settings::application.recentSessions.path = SystemToolkit::path_filename(SessionFileDialogFilename_); Settings::application.recentSessions.path = SystemToolkit::path_filename(sessionFileDialogFilename_);
} }
} }
// overlay to ensure file dialog is modal // overlay to ensure file dialog is modal
if (FileDialogPending_){ if (fileDialogPending_){
ImGui::OpenPopup("Busy"); ImGui::OpenPopup("Busy");
if (ImGui::BeginPopupModal("Busy", NULL, ImGuiWindowFlags_AlwaysAutoResize)) if (ImGui::BeginPopupModal("Busy", NULL, ImGuiWindowFlags_AlwaysAutoResize))
{ {
@@ -913,6 +921,7 @@ void Navigator::Render()
// the "=" icon for menu // the "=" icon for menu
if (ImGui::Selectable( ICON_FA_BARS, &selected_button[NAV_MENU], 0, iconsize)) if (ImGui::Selectable( ICON_FA_BARS, &selected_button[NAV_MENU], 0, iconsize))
{ {
Mixer::manager().unsetCurrentSource();
toggle(NAV_MENU); toggle(NAV_MENU);
} }
// the list of INITIALS for sources // the list of INITIALS for sources
@@ -984,6 +993,10 @@ void Navigator::Render()
// window menu // window menu
if (selected_button[NAV_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(); RenderMainPannel();
} }
// window to create a source // window to create a source
@@ -1234,7 +1247,7 @@ void ShowAbout(bool* p_open)
ImGui::Separator(); ImGui::Separator();
ImGui::Text("vimix is a video mixing software for live performance."); 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."); 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(); ImGui::End();
} }
@@ -1253,7 +1266,7 @@ void ShowAboutOpengl(bool* p_open)
ImGui::PopFont(); ImGui::PopFont();
ImGui::Separator(); ImGui::Separator();
ImGui::Text("OpenGL is the premier environment for developing portable, \ninteractive 2D and 3D graphics applications."); 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(); ImGui::SameLine();
static bool show_opengl_info = false; static bool show_opengl_info = false;
@@ -1320,7 +1333,7 @@ void ShowAboutGStreamer(bool* p_open)
ImGui::Separator(); ImGui::Separator();
ImGui::Text("A flexible, fast and multiplatform multimedia framework."); ImGui::Text("A flexible, fast and multiplatform multimedia framework.");
ImGui::Text("GStreamer is licensed under the LGPL License."); ImGui::Text("GStreamer is licensed under the LGPL License.");
ImGuiToolkit::ButtonOpenWebpage("https://gstreamer.freedesktop.org/"); ImGuiToolkit::ButtonOpenUrl("https://gstreamer.freedesktop.org/");
ImGui::SameLine(); ImGui::SameLine();
static bool show_config_info = false; static bool show_config_info = false;

View File

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