mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 15:30:00 +01:00
Merge remote-tracking branch 'origin/beta'
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -32,3 +32,6 @@ flatpak/.flatpak-builder
|
||||
flatpak/repo/
|
||||
|
||||
flatpak/build/
|
||||
|
||||
build/
|
||||
.vscode/
|
||||
|
||||
@@ -127,53 +127,75 @@ endif()
|
||||
#
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
#
|
||||
# GSTREAMER
|
||||
#
|
||||
find_package(GLIB2 REQUIRED)
|
||||
macro_log_feature(GLIB2_FOUND "GLib" "GTK general-purpose utility library" "http://www.gtk.org" TRUE)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(GSTREAMER REQUIRED gstreamer-base-1.0>=1.24
|
||||
gstreamer-pbutils-1.0
|
||||
gstreamer-app-1.0
|
||||
gstreamer-audio-1.0
|
||||
gstreamer-video-1.0
|
||||
gstreamer-gl-1.0
|
||||
)
|
||||
|
||||
find_package(GObject REQUIRED)
|
||||
macro_log_feature(GOBJECT_FOUND "GObject" "GTK object-oriented framework" "http://www.gtk.org" TRUE)
|
||||
include_directories(
|
||||
${GSTREAMER_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_package(GStreamer 1.0.0 COMPONENTS base)
|
||||
macro_log_feature(GSTREAMER_FOUND "GStreamer"
|
||||
"Open Source Multiplatform Multimedia Framework"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
link_directories(
|
||||
${GSTREAMER_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
find_package(GStreamerPluginsBase 1.0.0 COMPONENTS app audio video pbutils gl)
|
||||
macro_log_feature(GSTREAMER_APP_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer app library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
else ()
|
||||
find_package(GLIB2 REQUIRED)
|
||||
macro_log_feature(GLIB2_FOUND "GLib" "GTK general-purpose utility library" "http://www.gtk.org" TRUE)
|
||||
|
||||
macro_log_feature(GSTREAMER_AUDIO_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer audio library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
find_package(GObject REQUIRED)
|
||||
macro_log_feature(GOBJECT_FOUND "GObject" "GTK object-oriented framework" "http://www.gtk.org" TRUE)
|
||||
|
||||
macro_log_feature(GSTREAMER_VIDEO_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer video library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
find_package(GStreamer 1.0 COMPONENTS base REQUIRED)
|
||||
|
||||
macro_log_feature(GSTREAMER_PBUTILS_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer pbutils library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
find_package(GStreamerPluginsBase 1.0.0 COMPONENTS app audio video pbutils gl)
|
||||
macro_log_feature(GSTREAMER_APP_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer app library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
macro_log_feature(GSTREAMER_AUDIO_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer audio library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
macro_log_feature(GSTREAMER_VIDEO_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer video library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
macro_log_feature(GSTREAMER_PBUTILS_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer pbutils library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
macro_log_feature(GSTREAMER_GL_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer opengl library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
|
||||
include_directories(
|
||||
${GLIB2_INCLUDE_DIR}
|
||||
${GSTREAMER_INCLUDE_DIR}
|
||||
${GSTREAMER_AUDIO_INCLUDE_DIR}
|
||||
${GSTREAMER_VIDEO_INCLUDE_DIR}
|
||||
${GSTREAMER_BASE_INCLUDE_DIR}
|
||||
${GSTREAMER_APP_INCLUDE_DIR}
|
||||
${GSTREAMER_PBUTILS_INCLUDE_DIR}
|
||||
${GSTREAMER_GL_INCLUDE_DIR}
|
||||
)
|
||||
set( GSTREAMER_LIBRARIES
|
||||
${GOBJECT_LIBRARIES}
|
||||
${GSTREAMER_BASE_LIBRARY}
|
||||
${GSTREAMER_APP_LIBRARY}
|
||||
${GSTREAMER_AUDIO_LIBRARY}
|
||||
${GSTREAMER_VIDEO_LIBRARY}
|
||||
${GSTREAMER_PBUTILS_LIBRARY}
|
||||
${GSTREAMER_GL_LIBRARY}
|
||||
)
|
||||
|
||||
endif ()
|
||||
|
||||
macro_log_feature(GSTREAMER_GL_LIBRARY_FOUND "GStreamerPluginsBase" "GStreamer opengl library"
|
||||
"http://gstreamer.freedesktop.org/" TRUE "1.0.0")
|
||||
|
||||
# Various preprocessor definitions for GST
|
||||
add_definitions(-DGST_DISABLE_XML -DGST_DISABLE_LOADSAVE)
|
||||
|
||||
include_directories(
|
||||
${GLIB2_INCLUDE_DIR}
|
||||
${GSTREAMER_INCLUDE_DIR}
|
||||
${GSTREAMER_AUDIO_INCLUDE_DIR}
|
||||
${GSTREAMER_VIDEO_INCLUDE_DIR}
|
||||
${GSTREAMER_BASE_INCLUDE_DIR}
|
||||
${GSTREAMER_APP_INCLUDE_DIR}
|
||||
${GSTREAMER_PBUTILS_INCLUDE_DIR}
|
||||
${GSTREAMER_GL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
#
|
||||
# ICU4C
|
||||
#
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
#!/bin/bash
|
||||
# test if there is an nvidia GPU
|
||||
gpu=$(lspci | grep -i '.* vga .* nvidia .*')
|
||||
shopt -s nocasematch
|
||||
if [[ $gpu == *' nvidia '* ]]; then
|
||||
# with nvidia, request render offload
|
||||
printf 'Nvidia GPU present: %s\n' "$gpu"
|
||||
__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia vimix "$@"
|
||||
|
||||
# Test if running under wayland
|
||||
if [ -z "$WAYLAND_DISPLAY" ]; then
|
||||
# not Wayland, nothing special
|
||||
vimix "$@"
|
||||
else
|
||||
# otherwise, nothing special
|
||||
printf 'GPU present: %s\n' "$gpu"
|
||||
vimix "$@"
|
||||
# Wayland: test if there is an nvidia GPU
|
||||
gpu=$(lspci | grep -i '.* vga .* nvidia .*')
|
||||
shopt -s nocasematch
|
||||
if [[ $gpu == *' nvidia '* ]]; then
|
||||
# with nvidia, request Wayland render offload
|
||||
printf 'Nvidia GPU present: %s\n' "$gpu"
|
||||
__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia vimix "$@"
|
||||
else
|
||||
# otherwise, nothing special
|
||||
vimix "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -171,14 +171,7 @@ target_link_libraries(${VMIX_BINARY} LINK_PRIVATE
|
||||
${TINYXML2_LIBRARIES}
|
||||
${ICU_LIBRARIES}
|
||||
${CMAKE_DL_LIBS}
|
||||
${GOBJECT_LIBRARIES}
|
||||
${GSTREAMER_LIBRARY}
|
||||
${GSTREAMER_BASE_LIBRARY}
|
||||
${GSTREAMER_APP_LIBRARY}
|
||||
${GSTREAMER_AUDIO_LIBRARY}
|
||||
${GSTREAMER_VIDEO_LIBRARY}
|
||||
${GSTREAMER_PBUTILS_LIBRARY}
|
||||
${GSTREAMER_GL_LIBRARY}
|
||||
${GSTREAMER_LIBRARIES}
|
||||
Threads::Threads
|
||||
ZLIB::ZLIB
|
||||
Ableton::Link
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef GEOMETRYVIEW_H
|
||||
#define GEOMETRYVIEW_H
|
||||
|
||||
// #define ENABLE_CANVAS
|
||||
#define ENABLE_CANVAS
|
||||
|
||||
#include "View.h"
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ string GstToolkit::gst_version()
|
||||
#if GST_GL_HAVE_PLATFORM_GLX
|
||||
// https://gstreamer.freedesktop.org/documentation/nvcodec/index.html?gi-language=c#plugin-nvcodec
|
||||
// list ordered with higher priority at the end (e.g. nvidia proprietary before vaapi)
|
||||
const char *plugins[17] = { "vdpaumpegdec", "omxh264dec", "omxmpeg2dec", "omxmpeg4videodec", "vaapidecodebin",
|
||||
const char *plugins[17] = { "vdpaumpegdec", "omxh264dec", "omxmpeg2dec", "omxmpeg4videodec", "vaapidecodebin",
|
||||
"nvh264sldec", "nvh264dec", "nvh265sldec", "nvh265dec", "nvmpegvideodec", "nvmpeg2videodec", "nvmpeg4videodec",
|
||||
"nvvp8sldec", "nvvp8dec", "nvvp9sldec", "nvvp9dec", "nvav1dec"
|
||||
};
|
||||
|
||||
@@ -70,6 +70,116 @@
|
||||
|
||||
#include "RenderingManager.h"
|
||||
|
||||
// GDBus for screensaver inhibition (works on both X11 and Wayland)
|
||||
#ifdef GLFW_EXPOSE_NATIVE_GLX
|
||||
#include <gio/gio.h>
|
||||
guint screensaver_inhibit_cookie_ = 0;
|
||||
GDBusConnection *session_dbus_ = NULL;
|
||||
|
||||
void inhibitScreensaver (bool on)
|
||||
{
|
||||
/*
|
||||
* Inhibit or un-inhibit the desktop screensaver via the
|
||||
* org.freedesktop.ScreenSaver D-Bus API.
|
||||
*
|
||||
* When 'on' is true:
|
||||
* - Obtain a connection to the session bus (cached in session_dbus_).
|
||||
* - Call the Inhibit method with two strings: the application name
|
||||
* ("vimix") and a human-readable reason.
|
||||
* - The call returns a uint 'cookie' which must be kept and later
|
||||
* passed to UnInhibit to release the inhibition.
|
||||
*
|
||||
* When 'on' is false:
|
||||
* - If we previously inhibited the screensaver (screensaver_inhibit_cookie_ != 0)
|
||||
* call UnInhibit with that cookie.
|
||||
* - Release the cached D-Bus connection (session_dbus_) and reset the cookie.
|
||||
*
|
||||
* Notes:
|
||||
* - This function uses synchronous D-Bus calls. They may block briefly.
|
||||
* - Errors from g_dbus_connection_call_sync are reported to the log and freed.
|
||||
* - The code is guarded by an #ifdef so it only compiles for platforms
|
||||
* where GLFW_EXPOSE_NATIVE_GLX is defined (historically used for X11/GLX),
|
||||
* but the org.freedesktop.ScreenSaver D-Bus interface works on both
|
||||
* X11 and Wayland session daemons that implement the spec.
|
||||
*/
|
||||
if (on ) {
|
||||
GError *error = NULL;
|
||||
/* Lazily open a connection to the session bus and cache it. */
|
||||
if (session_dbus_ == NULL)
|
||||
session_dbus_ = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
|
||||
|
||||
/* Only inhibit once: do nothing if we already have a cookie. */
|
||||
if (session_dbus_ != NULL && screensaver_inhibit_cookie_ == 0) {
|
||||
/* Call org.freedesktop.ScreenSaver.Inhibit(application_name, reason) */
|
||||
GVariant *result = g_dbus_connection_call_sync(
|
||||
session_dbus_,
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"/org/freedesktop/ScreenSaver",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"Inhibit",
|
||||
g_variant_new("(ss)", "vimix", "Video mixing in progress"),
|
||||
G_VARIANT_TYPE("(u)"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
if (result != NULL) {
|
||||
/* The returned variant contains a single unsigned integer cookie. */
|
||||
g_variant_get(result, "(u)", &screensaver_inhibit_cookie_);
|
||||
g_variant_unref(result);
|
||||
Log::Info("Screensaver inhibited for vimix (cookie: %u)", screensaver_inhibit_cookie_);
|
||||
} else {
|
||||
/* If the call failed, log the error and ensure cookie is zero. */
|
||||
if (error != NULL) {
|
||||
Log::Info("Could not inhibit screensaver: %s", error->message);
|
||||
g_error_free(error);
|
||||
screensaver_inhibit_cookie_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Un-inhibit only if we have a valid cookie recorded. */
|
||||
if (screensaver_inhibit_cookie_ != 0) {
|
||||
GError *error = NULL;
|
||||
if (session_dbus_ != NULL) {
|
||||
/* Call org.freedesktop.ScreenSaver.UnInhibit(cookie) */
|
||||
g_dbus_connection_call_sync(
|
||||
session_dbus_,
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"/org/freedesktop/ScreenSaver",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"UnInhibit",
|
||||
g_variant_new("(u)", screensaver_inhibit_cookie_),
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
&error
|
||||
);
|
||||
|
||||
if (error != NULL) {
|
||||
/* Report failure to release inhibition but continue cleanup. */
|
||||
g_printerr("Could not un-inhibit screensaver: %s\n", error->message);
|
||||
g_error_free(error);
|
||||
} else {
|
||||
g_printerr("Screensaver inhibition disabled\n");
|
||||
Log::Info("Screensaver inhibition disabled\n");
|
||||
}
|
||||
|
||||
/* Close and drop our cached session bus connection. */
|
||||
g_object_unref(session_dbus_);
|
||||
session_dbus_ = NULL;
|
||||
}
|
||||
/* Reset cookie so subsequent calls can re-inhibit if needed. */
|
||||
screensaver_inhibit_cookie_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_GST_OPENGL_SYNC_HANDLER
|
||||
|
||||
GLFW_EXPOSE_NATIVE_X11
|
||||
@@ -149,13 +259,6 @@ static void glfw_error_callback(int error, const char* description)
|
||||
|
||||
static void WindowResizeCallback( GLFWwindow *w, int width, int height)
|
||||
{
|
||||
if (Rendering::manager().mainWindow().window() == w) {
|
||||
// UI manager tries to keep windows in the workspace
|
||||
WorkspaceWindow::notifyWorkspaceSizeChanged(Rendering::manager().mainWindow().previous_size.x, Rendering::manager().mainWindow().previous_size.y, width, height);
|
||||
Rendering::manager().mainWindow().previous_size = glm::vec2(width, height);
|
||||
Rendering::manager().draw();
|
||||
}
|
||||
|
||||
int id = Rendering::manager().window(w)->index();
|
||||
Settings::application.windows[id].fullscreen = glfwGetWindowMonitor(w) != nullptr;
|
||||
if (!Settings::application.windows[id].fullscreen) {
|
||||
@@ -163,6 +266,12 @@ static void WindowResizeCallback( GLFWwindow *w, int width, int height)
|
||||
Settings::application.windows[id].h = height;
|
||||
}
|
||||
|
||||
if (Rendering::manager().mainWindow().window() == w) {
|
||||
// UI manager tries to keep windows in the workspace
|
||||
WorkspaceWindow::notifyWorkspaceSizeChanged(Rendering::manager().mainWindow().previous_size.x, Rendering::manager().mainWindow().previous_size.y, width, height);
|
||||
Rendering::manager().mainWindow().previous_size = glm::vec2(width, height);
|
||||
Rendering::manager().draw();
|
||||
}
|
||||
}
|
||||
|
||||
static void WindowMoveCallback( GLFWwindow *w, int x, int y)
|
||||
@@ -328,6 +437,17 @@ Rendering::Rendering()
|
||||
|
||||
bool Rendering::init()
|
||||
{
|
||||
// Forcing X11 on Gnome makes the server use xWayland which has proper Server Side Decorations as opposed to Wayland.
|
||||
if (strcmp(getenv("XDG_CURRENT_DESKTOP"), "GNOME") == 0 ||
|
||||
strcmp(getenv("XDG_CURRENT_DESKTOP"), "Unity") == 0 ){
|
||||
g_printerr("Forcing X11 on GNOME desktop\n");
|
||||
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
||||
}
|
||||
else {
|
||||
g_printerr("Detected %s desktop\n", getenv("XDG_CURRENT_DESKTOP"));
|
||||
glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM);
|
||||
}
|
||||
|
||||
//
|
||||
// Setup GLFW
|
||||
//
|
||||
@@ -510,6 +630,20 @@ void Rendering::draw()
|
||||
main_new_title_.clear();
|
||||
}
|
||||
|
||||
// draw output windows and count number of success
|
||||
int count = 0;
|
||||
for (auto it = outputs_.begin(); it != outputs_.end(); ++it) {
|
||||
if ( it->draw( Mixer::manager().session()->frame() ) )
|
||||
++count;
|
||||
}
|
||||
// terminate or initialize output windows to match number of output windows
|
||||
if (count > Settings::application.num_output_windows)
|
||||
outputs_[count-1].terminate();
|
||||
else if (count < Settings::application.num_output_windows) {
|
||||
outputs_[count].init( count+1, main_.window());
|
||||
outputs_[count].show();
|
||||
}
|
||||
|
||||
// operate on main window context
|
||||
main_.makeCurrent();
|
||||
|
||||
@@ -528,21 +662,6 @@ void Rendering::draw()
|
||||
|
||||
glfwSwapBuffers(main_.window());
|
||||
|
||||
|
||||
// draw output windows and count number of success
|
||||
int count = 0;
|
||||
for (auto it = outputs_.begin(); it != outputs_.end(); ++it) {
|
||||
if ( it->draw( Mixer::manager().session()->frame() ) )
|
||||
++count;
|
||||
}
|
||||
// terminate or initialize output windows to match number of output windows
|
||||
if (count > Settings::application.num_output_windows)
|
||||
outputs_[count-1].terminate();
|
||||
else if (count < Settings::application.num_output_windows) {
|
||||
outputs_[count].init( count+1, main_.window());
|
||||
outputs_[count].show();
|
||||
}
|
||||
|
||||
// software framerate limiter < 62 FPS
|
||||
{
|
||||
static GTimer *timer = g_timer_new ();
|
||||
@@ -1143,6 +1262,9 @@ void RenderingWindow::terminate()
|
||||
fbo_ = 0;
|
||||
index_ = -1;
|
||||
textureid_ = Resource::getTextureBlack();
|
||||
|
||||
// SCREENSAVER UNINHIBIT
|
||||
inhibitScreensaver( Settings::application.num_output_windows > 0 );
|
||||
}
|
||||
|
||||
void RenderingWindow::show()
|
||||
@@ -1156,6 +1278,9 @@ void RenderingWindow::show()
|
||||
GLFWmonitor *mo = Rendering::manager().monitorNamed(Settings::application.windows[index_].monitor);
|
||||
setFullscreen_(mo);
|
||||
}
|
||||
|
||||
// SCREENSAVER INHIBIT
|
||||
inhibitScreensaver( Settings::application.num_output_windows > 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1156,8 +1156,13 @@ void SessionLoader::visit (MediaSource& s)
|
||||
// set config media player
|
||||
s.mediaplayer()->accept(*this);
|
||||
|
||||
// add a callback to activate play speed
|
||||
s.call( new PlaySpeed( s.mediaplayer()->playSpeed() ) );
|
||||
// read source play speed from media player SessionLoader::visit
|
||||
double r = s.mediaplayer()->playSpeed();
|
||||
// reset media player to normal speed
|
||||
s.mediaplayer()->setRate(1.0);
|
||||
// add a callback to activate source play speed and rewind
|
||||
s.call( new PlaySpeed( r ) );
|
||||
s.call( new RePlay( ) );
|
||||
}
|
||||
|
||||
void SessionLoader::visit (SessionFileSource& s)
|
||||
|
||||
@@ -541,7 +541,7 @@ void RePlay::update(Source *s, float dt)
|
||||
SourceCallback::update(s, dt);
|
||||
|
||||
// apply when ready
|
||||
if ( status_ == READY ){
|
||||
if ( status_ == READY && s->ready()){
|
||||
|
||||
// call replay function
|
||||
s->replay();
|
||||
|
||||
Reference in New Issue
Block a user