summaryrefslogtreecommitdiffhomepage
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/CMakeLists.txt19
-rw-r--r--compat/camera-names.cpp54
-rw-r--r--compat/check-visible.cpp2
-rw-r--r--compat/check-visible.hpp2
-rw-r--r--compat/correlation-calibrator.cpp3
-rw-r--r--compat/hamilton-tools.cpp109
-rw-r--r--compat/hamilton-tools.h76
-rw-r--r--compat/lang/de_DE.ts4
-rw-r--r--compat/lang/zh_CN.ts2
-rw-r--r--compat/macros.h (renamed from compat/macros1.h)19
-rw-r--r--compat/macros.hpp25
-rw-r--r--compat/math.hpp59
-rw-r--r--compat/mutex.cpp30
-rw-r--r--compat/mutex.hpp18
-rw-r--r--compat/process-list.cpp195
-rw-r--r--compat/process-list.hpp161
-rw-r--r--compat/qt-dpi.hpp17
-rw-r--r--compat/qt-signal.cpp12
-rw-r--r--compat/qt-signal.hpp59
-rw-r--r--compat/run-in-thread.hpp108
-rw-r--r--compat/shm.cpp3
-rw-r--r--compat/shm.h4
-rw-r--r--compat/timer.cpp24
-rw-r--r--compat/timer.hpp2
24 files changed, 593 insertions, 414 deletions
diff --git a/compat/CMakeLists.txt b/compat/CMakeLists.txt
index fb498fb6..87b191cc 100644
--- a/compat/CMakeLists.txt
+++ b/compat/CMakeLists.txt
@@ -1,7 +1,3 @@
-if(CMAKE_COMPILER_IS_GNUCXX)
- add_compile_options(-fno-lto -fno-fast-math -fno-finite-math-only -O0)
-endif()
-
otr_module(compat NO-COMPAT BIN)
if(NOT WIN32 AND NOT APPLE)
@@ -11,3 +7,18 @@ endif()
if(WIN32)
target_link_libraries(${self} strmiids)
endif()
+
+
+if(APPLE)
+ target_link_libraries(${self} proc)
+elseif(LINUX)
+ otr_pkgconfig_(has-libproc2 ${self} libproc2)
+ if(has-libproc2)
+ target_compile_definitions(${self} PUBLIC -DOTR_HAS_LIBPROC2)
+ else()
+ otr_pkgconfig_(has-libprocps ${self} libprocps)
+ if(NOT has-libprocps)
+ message(FATAL_ERROR "install libproc2 or libprocps development files")
+ endif()
+ endif()
+endif()
diff --git a/compat/camera-names.cpp b/compat/camera-names.cpp
index 5d190943..82776584 100644
--- a/compat/camera-names.cpp
+++ b/compat/camera-names.cpp
@@ -12,7 +12,8 @@
#endif
#ifdef __APPLE__
-# include <QCameraInfo>
+# include <QCameraDevice>
+# include <QMediaDevices>
#endif
#ifdef __linux__
@@ -41,6 +42,36 @@ int camera_name_to_index(const QString &name)
return -1;
}
+#ifdef _WIN32
+# include <QRegularExpression>
+
+static QString prop_to_qstring(IPropertyBag* pPropBag, const wchar_t* name)
+{
+ QString ret{};
+ VARIANT var;
+ VariantInit(&var);
+ HRESULT hr = pPropBag->Read(name, &var, nullptr);
+ if (SUCCEEDED(hr))
+ ret = QString{(const QChar*)var.bstrVal, int(std::wcslen(var.bstrVal))};
+ VariantClear(&var);
+ return ret;
+}
+
+static QString device_path_from_qstring(const QString& str)
+{
+ // language=RegExp prefix=R"/( suffix=)/"
+ static const QRegularExpression regexp{R"/(#vid_([0-9a-f]{4})&pid_([0-9a-f]{4})&mi_([0-9a-f]{2})#([^#]+))/",
+ QRegularExpression::CaseInsensitiveOption};
+ auto match = regexp.match(str);
+ if (!match.hasMatch())
+ return {};
+ QString id = match.captured(4);
+ id.replace('&', '_');
+ return id;
+}
+
+#endif
+
std::vector<std::tuple<QString, int>> get_camera_names()
{
std::vector<std::tuple<QString, int>> ret;
@@ -67,26 +98,26 @@ std::vector<std::tuple<QString, int>> get_camera_names()
{
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(nullptr, nullptr, IID_IPropertyBag, (void **)&pPropBag);
- if (SUCCEEDED(hr)) {
+ if (SUCCEEDED(hr)) {
// To retrieve the filter's friendly name, do the following:
- VARIANT var;
- VariantInit(&var);
- hr = pPropBag->Read(L"FriendlyName", &var, nullptr);
if (SUCCEEDED(hr))
{
- // Display the name in your UI somehow.
- QString str((QChar*)var.bstrVal, int(std::wcslen(var.bstrVal)));
- ret.push_back({ str, ret.size() });
+ QString str = prop_to_qstring(pPropBag, L"FriendlyName");
+ QString path = device_path_from_qstring(prop_to_qstring(pPropBag, L"DevicePath"));
+ if (!path.isNull())
+ str += QStringLiteral(" [%1]").arg(path);
+ ret.push_back({ str, (int)ret.size() });
}
- VariantClear(&var);
pPropBag->Release();
}
pMoniker->Release();
}
pEnumCat->Release();
}
+#if 0
else
qDebug() << "failed CLSID_VideoInputDeviceCategory" << hr;
+#endif
pSysDevEnum->Release();
#endif
@@ -113,9 +144,8 @@ std::vector<std::tuple<QString, int>> get_camera_names()
}
#endif
#ifdef __APPLE__
- QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
- for (const QCameraInfo &cameraInfo : cameras)
- ret.push_back({ cameraInfo.description(), ret.size() });
+ for (const QCameraDevice& camera_info : QMediaDevices::videoInputs())
+ ret.push_back({ camera_info.description(), ret.size() });
#endif
return ret;
diff --git a/compat/check-visible.cpp b/compat/check-visible.cpp
index 4da649c7..621d941a 100644
--- a/compat/check-visible.cpp
+++ b/compat/check-visible.cpp
@@ -10,7 +10,7 @@ static bool visible = true;
#if defined _WIN32
#include "timer.hpp"
-#include "macros.hpp"
+#include "macros.h"
static Timer timer;
diff --git a/compat/check-visible.hpp b/compat/check-visible.hpp
index e24260ab..6669b84d 100644
--- a/compat/check-visible.hpp
+++ b/compat/check-visible.hpp
@@ -1,7 +1,7 @@
#pragma once
#include "export.hpp"
-#include "macros1.h"
+#include "macros.h"
class QWidget;
diff --git a/compat/correlation-calibrator.cpp b/compat/correlation-calibrator.cpp
index 01f3b14f..07ef7d3d 100644
--- a/compat/correlation-calibrator.cpp
+++ b/compat/correlation-calibrator.cpp
@@ -2,6 +2,7 @@
#include "variance.hpp"
#include "compat/math.hpp"
#include "compat/meta.hpp"
+#include "compat/macros.h"
#include <cmath>
#include <iterator>
@@ -49,7 +50,7 @@ bool correlation_calibrator::check_buckets(const vec6& data)
for (unsigned k = 0; k < 6; k++)
{
- const double val = clamp(data[k], min[k], max[k]);
+ const double val = std::clamp(data[k], min[k], max[k]);
pos[k] = unsigned((val-min[k])/spacing[k]);
if (pos[k] >= nbuckets[k])
diff --git a/compat/hamilton-tools.cpp b/compat/hamilton-tools.cpp
new file mode 100644
index 00000000..eb0ef984
--- /dev/null
+++ b/compat/hamilton-tools.cpp
@@ -0,0 +1,109 @@
+#include "hamilton-tools.h"
+#include <cmath>
+
+tQuat QuatFromAngleAxe(const double angle, const tVector& axe)
+{
+ double a = TO_RAD * 0.5 * angle;
+ double d = sin(a) / VectorLength(axe);
+ return ( tQuat (
+ axe.v[0] * d,
+ axe.v[1] * d,
+ axe.v[2] * d,
+ cos(a)
+ )
+ );
+}
+
+tQuat QuatMultiply(const tQuat& qL, const tQuat& qR)
+{
+ tQuat Q;
+ Q.x = qL.w*qR.x + qL.x*qR.w + qL.y*qR.z - qL.z*qR.y;
+ Q.y = qL.w*qR.y + qL.y*qR.w + qL.z*qR.x - qL.x*qR.z;
+ Q.z = qL.w*qR.z + qL.z*qR.w + qL.x*qR.y - qL.y*qR.x;
+ Q.w = qL.w*qR.w - qL.x*qR.x - qL.y*qR.y - qL.z*qR.z;
+ return(Q);
+}
+
+tQuat QuatFromYPR(const double YPR[])
+{
+ tQuat Q, Qp, Qy;
+ Q = QuatFromAngleAxe( -YPR[2], {0, 0, 1} ); //Roll, Z axe
+ Qp = QuatFromAngleAxe( -YPR[1], {1, 0, 0} ); //Pitch, X axe
+ Qy = QuatFromAngleAxe( -YPR[0], {0, 1, 0} ); //Yaw, Y axe
+
+ Q = QuatMultiply(Qp, Q);
+ return(QuatMultiply(Qy, Q));
+}
+
+void Normalize(tQuat& Q)
+{
+ double m = sqrt(Q.x*Q.x + Q.y*Q.y + Q.z*Q.z + Q.w*Q.w);
+ if (m > EPSILON)
+ {
+ m = 1 / m;
+ Q.x = Q.x * m;
+ Q.y = Q.y * m;
+ Q.z = Q.z * m;
+ Q.w = Q.w * m;
+ }
+ else Q = tQuat(0, 0, 0, 1);
+}
+
+tQuat Slerp(const tQuat& S, const tQuat& D, const double alpha)
+{
+ // calc cosine of half angle
+ double cosin = S.x*D.x + S.y*D.y + S.z*D.z + S.w*D.w;
+
+ // select nearest rotation direction
+ tQuat Q;
+ if (cosin < 0)
+ {
+ cosin = - cosin;
+ Q.x = - D.x;
+ Q.y = - D.y;
+ Q.z = - D.z;
+ Q.w = - D.w;
+ }
+ else Q = D;
+
+ // calculate coefficients
+ double scale0, scale1;
+ if ((1.0 - cosin) > EPSILON)
+ {
+ double omega = acos(cosin);
+ double sinus = 1 / sin(omega);
+ scale0 = sin((1.0 - alpha) * omega) * sinus;
+ scale1 = sin(alpha * omega)* sinus;
+ }
+ else
+ {
+ scale0 = 1.0 - alpha;
+ scale1 = alpha;
+ }
+
+ Q.x = scale0 * S.x + scale1 * Q.x;
+ Q.y = scale0 * S.y + scale1 * Q.y;
+ Q.z = scale0 * S.z + scale1 * Q.z;
+ Q.w = scale0 * S.w + scale1 * Q.w;
+
+ Normalize(Q);
+
+ return( Q );
+}
+
+void QuatToYPR(const tQuat& Q, double YPR[])
+{
+ const double xx = Q.x * Q.x;
+ const double xy = Q.x * Q.y;
+ const double xz = Q.x * Q.z;
+ const double xw = Q.x * Q.w;
+ const double yy = Q.y * Q.y;
+ const double yz = Q.y * Q.z;
+ const double yw = Q.y * Q.w;
+ const double zz = Q.z * Q.z;
+ const double zw = Q.z * Q.w;
+
+ YPR[0] = TO_DEG * ( -atan2( 2 * ( xz + yw ), 1 - 2 * ( xx + yy ) ));
+ YPR[1] = TO_DEG * ( asin ( 2 * ( yz - xw ) ));
+ YPR[2] = TO_DEG * ( -atan2( 2 * ( xy + zw ), 1 - 2 * ( xx + zz ) ));
+}
diff --git a/compat/hamilton-tools.h b/compat/hamilton-tools.h
new file mode 100644
index 00000000..885e9f79
--- /dev/null
+++ b/compat/hamilton-tools.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <algorithm>
+#include "export.hpp"
+#include "compat/math.hpp"
+
+constexpr double TO_RAD = (M_PI / 180);
+constexpr double TO_DEG = (180 / M_PI);
+constexpr double EPSILON = 1e-30;
+
+struct tVector
+{
+ double v[3];
+ tVector(double X = 0, double Y = 0, double Z = 0) {v[0]=X; v[1]=Y; v[2]=Z;}
+ tVector(const double V[]) {v[0]=V[0]; v[1]=V[1]; v[2]=V[2];}
+
+ void operator=(const tVector& other)
+ {
+ std::copy(other.v, other.v + 3, v);
+ }
+ inline const tVector operator+(const tVector& other) const
+ {
+ return tVector(v[0] + other.v[0], v[1] + other.v[1], v[2] + other.v[2]);
+ }
+ void operator+=(const tVector& other)
+ {
+ v[0] += other.v[0];
+ v[1] += other.v[1];
+ v[2] += other.v[2];
+ }
+ const tVector operator-(const tVector& other) const
+ {
+ return tVector(v[0] - other.v[0], v[1] - other.v[1], v[2] - other.v[2]);
+ }
+ void operator-=(const tVector& other)
+ {
+ v[0] -= other.v[0];
+ v[1] -= other.v[1];
+ v[2] -= other.v[2];
+ }
+ const tVector operator*(double scalar) const
+ {
+ return tVector(v[0] * scalar, v[1] * scalar, v[2] * scalar);
+ }
+ void operator*=(double scalar)
+ {
+ v[0] *= scalar;
+ v[1] *= scalar;
+ v[2] *= scalar;
+ }
+ const tVector operator/(double scalar) const
+ {
+ return *this * (1.0 / scalar);
+ }
+ void operator/= (double scalar)
+ {
+ *this *= 1.0 / scalar;
+ }
+};
+
+struct tQuat
+{
+ double x, y, z, w;
+ tQuat(double X = 0, double Y = 0, double Z = 0, double W = 1)
+ {x = X; y = Y; z = Z; w = W;}
+};
+
+inline double VectorLength(const tVector& v) { return sqrt(v.v[0] * v.v[0] + v.v[1] * v.v[1] + v.v[2] * v.v[2]); }
+inline double VectorDistance(const tVector& v1, const tVector& v2) { return VectorLength(v2 - v1); }
+inline tVector Lerp(const tVector& s, const tVector& d, const double alpha) { return s + (d - s) * alpha; }
+tQuat OTR_COMPAT_EXPORT QuatFromYPR(const double YPR[]);
+tQuat OTR_COMPAT_EXPORT QuatMultiply(const tQuat& qL, const tQuat& qR);
+inline tQuat QuatDivide(const tQuat& qL, const tQuat& qR) { return QuatMultiply(qL, tQuat(-qR.x, -qR.y, -qR.z, qR.w)); }
+inline double AngleBetween(const tQuat& S, const tQuat& D) { return TO_DEG * 2 * acos(fabs(S.x * D.x + S.y * D.y + S.z * D.z + S.w * D.w)); }
+tQuat OTR_COMPAT_EXPORT Slerp(const tQuat& S, const tQuat& D, const double alpha);
+void OTR_COMPAT_EXPORT QuatToYPR(const tQuat& Q, double YPR[]);
diff --git a/compat/lang/de_DE.ts b/compat/lang/de_DE.ts
new file mode 100644
index 00000000..1552582e
--- /dev/null
+++ b/compat/lang/de_DE.ts
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="de_DE">
+</TS>
diff --git a/compat/lang/zh_CN.ts b/compat/lang/zh_CN.ts
index 6401616d..e5ca8aa9 100644
--- a/compat/lang/zh_CN.ts
+++ b/compat/lang/zh_CN.ts
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1">
+<TS version="2.1" language="zh_CN">
</TS>
diff --git a/compat/macros1.h b/compat/macros.h
index 2ebfc4df..7de7fb86 100644
--- a/compat/macros1.h
+++ b/compat/macros.h
@@ -9,7 +9,7 @@
#if defined _MSC_VER
# define force_inline __forceinline
#else
-# define force_inline __attribute__((always_inline))
+# define force_inline __attribute__((always_inline)) inline
#endif
#if !defined likely
@@ -38,5 +38,20 @@
# define progn(...) ([&]() -> decltype(auto) { __VA_ARGS__ }())
# define eval_once2(expr, ctr) eval_once3(expr, ctr)
# define eval_once3(expr, ctr) ([&] { [[maybe_unused]] static const char init_ ## ctr = ((void)(expr), 0); }())
-# define eval_once(expr) eval_once2(expr, __COUNTER__)
+# ifdef QT_NO_DEBUG_OUTPUT
+# define eval_once(expr) void()
+# else
+# define eval_once(expr) eval_once2(expr, __COUNTER__)
+# endif
+
+#define OTR_DISABLE_MOVE_COPY(type) \
+ type(const type&) = delete; \
+ type(type&&) = delete; \
+ type& operator=(const type&) = delete; \
+ type& operator=(type&&) = delete
+#endif
+
+#ifdef _MSC_VER
+# define strncasecmp _strnicmp
+# define strcasecmp _stricmp
#endif
diff --git a/compat/macros.hpp b/compat/macros.hpp
deleted file mode 100644
index 497933cf..00000000
--- a/compat/macros.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include "macros1.h"
-
-#include <utility>
-#include <type_traits>
-
-// before C++20
-namespace cxx20_compat {
- template<typename T>
- struct remove_cvref {
- using type = std::remove_cv_t<std::remove_reference_t<T>>;
- };
-} // ns cxx20_compat
-
-template<typename t>
-using remove_cvref_t = typename cxx20_compat::remove_cvref<t>::type;
-
-template<typename t>
-using to_const_ref_t = std::add_lvalue_reference_t<std::add_const_t<remove_cvref_t<t>>>;
-
-template<typename t>
-using cv_qualified = std::conditional_t<std::is_fundamental_v<remove_cvref_t<t>>,
- remove_cvref_t<t>,
- to_const_ref_t<t>>;
diff --git a/compat/math.hpp b/compat/math.hpp
index 34428cbd..c5981cc2 100644
--- a/compat/math.hpp
+++ b/compat/math.hpp
@@ -1,72 +1,15 @@
#pragma once
-#include "macros.hpp"
-
#include <cmath>
#include <type_traits>
-namespace util_detail {
-
-template<typename n>
-inline auto clamp_float(n val, n min_, n max_)
-{
- return std::fmin(std::fmax(val, min_), max_);
-}
-
-template<typename t>
-struct clamp final
-{
- static inline auto clamp_(t val, t min_, t max_)
- {
- if (unlikely(val > max_))
- return max_;
- if (unlikely(val < min_))
- return min_;
- return val;
- }
-};
-
-template<>
-struct clamp<float>
-{
- static inline auto clamp_(float val, float min_, float max_)
- {
- return clamp_float(val, min_, max_);
- }
-};
-
-template<>
-struct clamp<double>
-{
- static inline auto clamp_(double val, double min_, double max_)
- {
- return clamp_float(val, min_, max_);
- }
-};
-
-} // ns util_detail
-
-template<typename t, typename u, typename v>
-inline auto clamp(const t& val, const u& min, const v& max)
-{
- using w = cv_qualified<decltype(val + min + max)>;
- return util_detail::clamp<w>::clamp_(val, min, max);
-}
-
template<typename t>
-inline auto iround(t val) -> std::enable_if_t<std::is_floating_point_v<remove_cvref_t<t>>, int>
+inline auto iround(t val) -> std::enable_if_t<std::is_floating_point_v<std::decay_t<t>>, int>
{
return (int)std::round(val);
}
-template<typename t>
-inline auto uround(t val) -> std::enable_if_t<std::is_floating_point_v<remove_cvref_t<t>>, unsigned>
-{
- return (unsigned)std::fmax(0, std::round(val));
-}
-
template <typename t>
-force_inline
constexpr int signum(const t& x)
{
return x < t{0} ? -1 : 1;
diff --git a/compat/mutex.cpp b/compat/mutex.cpp
index 664677ea..71f42329 100644
--- a/compat/mutex.cpp
+++ b/compat/mutex.cpp
@@ -1,33 +1,31 @@
+#include "export.hpp"
#include "mutex.hpp"
#include <cstdlib>
+#include <QMutex>
+#include <QRecursiveMutex>
-mutex& mutex::operator=(const mutex& rhs)
+template<typename M>
+mutex<M>& mutex<M>::operator=(const mutex& rhs)
{
- if (rhs->isRecursive() != inner.isRecursive())
- std::abort();
-
return *this;
}
-mutex::mutex(const mutex& datum) : mutex{datum.inner.isRecursive() ? Recursive : NonRecursive}
-{
-}
+template<typename MutexType> MutexType* mutex<MutexType>::operator&() const { return &inner; }
-mutex::mutex(RecursionMode m) : inner{m}
-{
-}
+template<typename M> mutex<M>::mutex(const mutex<M>& datum) {}
+template<typename M> mutex<M>::mutex() = default;
-QMutex* mutex::operator&() const noexcept
+template<typename M>
+mutex<M>::operator M*() const noexcept
{
return &inner;
}
-mutex::operator QMutex*() const noexcept
+template<typename M>
+M* mutex<M>::operator->() const noexcept
{
return &inner;
}
-QMutex* mutex::operator->() const noexcept
-{
- return &inner;
-}
+template class OTR_COMPAT_EXPORT mutex<QMutex>;
+template class OTR_COMPAT_EXPORT mutex<QRecursiveMutex>;
diff --git a/compat/mutex.hpp b/compat/mutex.hpp
index 54758a08..6ba4fa8c 100644
--- a/compat/mutex.hpp
+++ b/compat/mutex.hpp
@@ -1,24 +1,18 @@
#pragma once
-#include <QMutex>
-
#include "export.hpp"
+template<typename MutexType>
class OTR_COMPAT_EXPORT mutex
{
- mutable QMutex inner;
+ mutable MutexType inner{};
public:
- using RecursionMode = QMutex::RecursionMode;
- static constexpr RecursionMode Recursive = RecursionMode::Recursive;
- static constexpr RecursionMode NonRecursive = RecursionMode::NonRecursive;
-
mutex& operator=(const mutex& datum);
+ MutexType* operator&() const;
mutex(const mutex& datum);
- explicit mutex(RecursionMode m);
- mutex() : mutex{NonRecursive} {}
+ explicit mutex();
- QMutex* operator&() const noexcept;
- explicit operator QMutex*() const noexcept;
- QMutex* operator->() const noexcept;
+ explicit operator MutexType*() const noexcept;
+ MutexType* operator->() const noexcept;
};
diff --git a/compat/process-list.cpp b/compat/process-list.cpp
new file mode 100644
index 00000000..34c83b06
--- /dev/null
+++ b/compat/process-list.cpp
@@ -0,0 +1,195 @@
+#include "process-list.hpp"
+
+#include <vector>
+#include <QStringList>
+#include <QDebug>
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <tlhelp32.h>
+
+QStringList get_all_executable_names()
+{
+ QStringList ret;
+ HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (h == INVALID_HANDLE_VALUE)
+ return ret;
+
+ PROCESSENTRY32 e;
+ e.dwSize = sizeof(e);
+
+ if (Process32First(h, &e) != TRUE)
+ {
+ CloseHandle(h);
+ return ret;
+ }
+
+ do {
+ ret.append(QString{e.szExeFile});
+ } while (Process32Next(h, &e) == TRUE);
+
+ CloseHandle(h);
+
+ return ret;
+}
+
+#elif defined __APPLE__
+
+#include <sys/sysctl.h>
+#include <libproc.h>
+
+QStringList get_all_executable_names()
+{
+ QStringList ret; ret.reserve(512);
+ QList<int> vec; vec.reserve(512);
+
+ while (true)
+ {
+ int numproc = proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0);
+ if (numproc == -1)
+ {
+ qDebug() << "proc_listpids numproc failed" << errno;
+ return ret;
+ }
+ vec.resize(numproc);
+ int cnt = proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(int) * numproc);
+
+ if (cnt <= numproc)
+ {
+ std::vector<char> arglist;
+ int mib[2] { CTL_KERN, KERN_ARGMAX };
+ size_t sz = sizeof(int);
+ int maxarg = 0;
+ if (sysctl(mib, 2, &maxarg, &sz, NULL, 0) == -1)
+ {
+ qDebug() << "sysctl KERN_ARGMAX" << errno;
+ return ret;
+ }
+ arglist.resize(maxarg);
+ for (int i = 0; i < numproc; i++)
+ {
+ size_t maxarg_ = (size_t)maxarg;
+ int mib[3] { CTL_KERN, KERN_PROCARGS2, vec[i] };
+ if (sysctl(mib, 3, &arglist[0], &maxarg_, NULL, 0) == -1)
+ {
+ //qDebug() << "sysctl KERN_PROCARGS2" << vec[i] << errno;
+ continue;
+ }
+ QStringList cmdline;
+ for (unsigned j = sizeof(int) + strlen(&arglist[sizeof(int)]); j < maxarg_; j++)
+ {
+ QString arg(&arglist[j]);
+ if (arg.size() != 0)
+ {
+ cmdline << arg;
+ j += arg.size();
+ }
+ }
+ if (cmdline.size() > 0)
+ {
+ int idx = cmdline[0].lastIndexOf('/');
+ if (idx != -1)
+ {
+ QString tmp = cmdline[0].mid(idx+1);
+ if (cmdline.size() > 1 && (tmp == QStringLiteral("wine.bin") || tmp == QStringLiteral("wine")))
+ {
+ idx = cmdline[1].lastIndexOf('/');
+ if (idx == -1)
+ idx = cmdline[1].lastIndexOf('\\');
+ if (idx != -1)
+ {
+ ret.append(cmdline[1].mid(idx+1));
+ }
+ else
+ ret.append(cmdline[1]);
+ }
+ else
+ {
+ ret.append(tmp);
+ }
+ }
+ else
+ ret.append(cmdline[0]);
+ }
+ }
+ return ret;
+ }
+ }
+}
+
+#elif defined __linux__
+
+#include <cerrno>
+
+#ifdef OTR_HAS_LIBPROC2
+#include <libproc2/pids.h>
+QStringList get_all_executable_names()
+{
+ QStringList ret;
+ enum pids_item items[] = { PIDS_ID_PID, PIDS_CMD, PIDS_CMDLINE_V };
+
+ enum rel_items { rel_pid, rel_cmd, rel_cmdline };
+ struct pids_info *info = NULL;
+ struct pids_stack *stack;
+ QString tmp; tmp.reserve(64);
+
+ procps_pids_new(&info, items, 3);
+
+ while ((stack = procps_pids_get(info, PIDS_FETCH_TASKS_ONLY)))
+ {
+ char **p_cmdline = PIDS_VAL(rel_cmdline, strv, stack, info);
+
+ // note, wine sets argv[0] so no parsing like in OSX case
+ if (p_cmdline && p_cmdline[0] && p_cmdline[0][0] &&
+ !(p_cmdline[0][0] == '-' && !p_cmdline[0][1]))
+ {
+ tmp = QString{p_cmdline[0]};
+ const int idx = std::max(tmp.lastIndexOf('\\'), tmp.lastIndexOf('/'));
+ if (idx != -1)
+ tmp = tmp.mid(idx+1);
+ //qDebug() << "procps" << tmp;
+ ret.append(tmp);
+ }
+ }
+ //qDebug() << "-- procps end";
+
+ procps_pids_unref(&info);
+
+ return ret;
+}
+#else
+#include <proc/readproc.h>
+#include <cerrno>
+
+QStringList get_all_executable_names()
+{
+ QStringList ret;
+ proc_t** procs = readproctab(PROC_FILLCOM);
+ if (procs == nullptr)
+ {
+ qDebug() << "readproctab" << errno;
+ return ret;
+ }
+ for (int i = 0; procs[i]; i++)
+ {
+ // note, wine sets argv[0] so no parsing like in OSX case
+ auto proc = procs[i];
+ if (proc->cmdline && proc->cmdline[0])
+ {
+ QString tmp(proc->cmdline[0]);
+ const int idx = std::max(tmp.lastIndexOf('\\'), tmp.lastIndexOf('/'));
+ tmp = tmp.mid(idx == -1 ? 0 : idx+1);
+ ret.append(tmp);
+ }
+ freeproc(procs[i]);
+ }
+ free(procs);
+ return ret;
+}
+#endif
+
+#else
+QStringList get_all_executable_names() { return {}; }
+
+#endif
diff --git a/compat/process-list.hpp b/compat/process-list.hpp
index 782dc0a4..323829bf 100644
--- a/compat/process-list.hpp
+++ b/compat/process-list.hpp
@@ -7,164 +7,7 @@
#pragma once
-#include <QDebug>
+#include "export.hpp"
#include <QStringList>
-#if defined _WIN32
-
-#include <windows.h>
-#include <tlhelp32.h>
-
-template<typename = void>
-static QStringList get_all_executable_names()
-{
- QStringList ret;
- HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- if (h == INVALID_HANDLE_VALUE)
- return ret;
-
- PROCESSENTRY32 e;
- e.dwSize = sizeof(e);
-
- if (Process32First(h, &e) != TRUE)
- {
- CloseHandle(h);
- return ret;
- }
-
- do {
- ret.append(e.szExeFile);
- } while (Process32Next(h, &e) == TRUE);
-
- CloseHandle(h);
-
- return ret;
-}
-#elif defined __APPLE__
-#include <libproc.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <cerrno>
-#include <cstring>
-#include <vector>
-
-template<typename = void>
-static QStringList get_all_executable_names()
-{
- QStringList ret;
- std::vector<int> vec;
-
- while (true)
- {
- int numproc = proc_listpids(PROC_ALL_PIDS, 0, nullptr, 0);
- if (numproc == -1)
- {
- qDebug() << "proc_listpids numproc failed" << errno;
- return ret;
- }
- vec.resize(numproc);
- int cnt = proc_listpids(PROC_ALL_PIDS, 0, &vec[0], sizeof(int) * numproc);
-
- if (cnt <= numproc)
- {
- std::vector<char> arglist;
- int mib[2] { CTL_KERN, KERN_ARGMAX };
- size_t sz = sizeof(int);
- int maxarg = 0;
- if (sysctl(mib, 2, &maxarg, &sz, NULL, 0) == -1)
- {
- qDebug() << "sysctl KERN_ARGMAX" << errno;
- return ret;
- }
- arglist.resize(maxarg);
- for (int i = 0; i < numproc; i++)
- {
- size_t maxarg_ = (size_t)maxarg;
- int mib[3] { CTL_KERN, KERN_PROCARGS2, vec[i] };
- if (sysctl(mib, 3, &arglist[0], &maxarg_, NULL, 0) == -1)
- {
- //qDebug() << "sysctl KERN_PROCARGS2" << vec[i] << errno;
- continue;
- }
- QStringList cmdline;
- for (unsigned j = sizeof(int) + strlen(&arglist[sizeof(int)]); j < maxarg_; j++)
- {
- QString arg(&arglist[j]);
- if (arg.size() != 0)
- {
- cmdline << arg;
- j += arg.size();
- }
- }
- if (cmdline.size() > 0)
- {
- int idx = cmdline[0].lastIndexOf('/');
- if (idx != -1)
- {
- QString tmp = cmdline[0].mid(idx+1);
- if (cmdline.size() > 1 && (tmp == QStringLiteral("wine.bin") || tmp == QStringLiteral("wine")))
- {
- idx = cmdline[1].lastIndexOf('/');
- if (idx == -1)
- idx = cmdline[1].lastIndexOf('\\');
- if (idx != -1)
- {
- ret.append(cmdline[1].mid(idx+1));
- }
- else
- ret.append(cmdline[1]);
- }
- else
- {
- ret.append(tmp);
- }
- }
- else
- ret.append(cmdline[0]);
- }
- }
- return ret;
- }
- }
-}
-
-#elif defined __linux__
-
-#include <proc/readproc.h>
-#include <cerrno>
-
-template<typename = void>
-QStringList get_all_executable_names()
-{
- QStringList ret;
- proc_t** procs = readproctab(PROC_FILLCOM);
- if (procs == nullptr)
- {
- qDebug() << "readproctab" << errno;
- return ret;
- }
- for (int i = 0; procs[i]; i++)
- {
- // note, wine sets argv[0] so no parsing like in OSX case
- auto proc = procs[i];
- if (proc->cmdline && proc->cmdline[0])
- {
- QString tmp(proc->cmdline[0]);
- const int idx = std::max(tmp.lastIndexOf('\\'), tmp.lastIndexOf('/'));
- tmp = tmp.mid(idx == -1 ? 0 : idx+1);
- ret.append(tmp);
- }
- freeproc(procs[i]);
- }
- free(procs);
- return ret;
-}
-
-#else
-template<typename = void>
-static QStringList get_all_executable_names()
-{
- return QStringList();
-}
-#endif
+OTR_COMPAT_EXPORT QStringList get_all_executable_names();
diff --git a/compat/qt-dpi.hpp b/compat/qt-dpi.hpp
index 01659c8a..fc17a062 100644
--- a/compat/qt-dpi.hpp
+++ b/compat/qt-dpi.hpp
@@ -3,17 +3,22 @@
#include <algorithm>
#include <QWidget>
+static inline double screen_dpi(const QPaintDevice* widget)
+{
+ const auto& x = *widget;
+#ifdef _WIN32
+ return std::max(x.devicePixelRatioF(), 1.);
+#else
+ return std::max(std::max(x.logicalDpiX()/(double)x.physicalDpiX(), x.devicePixelRatioF()), 1.);
+#endif
+}
+
template<typename self>
struct screen_dpi_mixin
{
protected:
double screen_dpi() const
{
- const auto& x = *static_cast<const self*>(this);
-#ifdef _WIN32
- return std::max(x.devicePixelRatioF(), 1.);
-#else
- return std::max(std::max(x.logicalDpiX()/(double)x.physicalDpiX(), x.devicePixelRatioF()), 1.);
-#endif
+ return ::screen_dpi(static_cast<const self*>(this));
}
};
diff --git a/compat/qt-signal.cpp b/compat/qt-signal.cpp
index 08aac663..8c23866b 100644
--- a/compat/qt-signal.cpp
+++ b/compat/qt-signal.cpp
@@ -1,13 +1,7 @@
+#define OTR_GENERATE_SIGNAL3(type) void sig_##type::operator()(const type& x) const { notify(x); }
#include "qt-signal.hpp"
+namespace _qt_sig_impl {
-namespace qt_sig {
+sig_void::sig_void(QObject* parent) : QObject(parent) {}
-nullary::nullary(QObject* parent) : QObject(parent) {}
-nullary::~nullary() = default;
-
-void nullary::operator()() const
-{
- notify();
}
-
-} // ns qt_sig
diff --git a/compat/qt-signal.hpp b/compat/qt-signal.hpp
index 119e063c..92ab7e6f 100644
--- a/compat/qt-signal.hpp
+++ b/compat/qt-signal.hpp
@@ -4,27 +4,66 @@
#include "export.hpp"
#include <QObject>
+#include <QList>
+#include <QPointF>
+#include <QVariant>
-namespace qt_sig {
+namespace _qt_sig_impl {
-class OTR_COMPAT_EXPORT nullary : public QObject
+template<typename t> struct sig;
+
+class OTR_COMPAT_EXPORT sig_void final : public QObject
{
Q_OBJECT
public:
template<typename t, typename F>
- nullary(t* datum, F&& f, Qt::ConnectionType conntype = Qt::AutoConnection) : QObject(datum)
+ sig_void(t* datum, F&& f, Qt::ConnectionType conntype = Qt::AutoConnection) : QObject(datum)
{
- connect(this, &nullary::notify, datum, f, conntype);
+ connect(this, &sig_void::notify, datum, f, conntype);
}
-
- nullary(QObject* parent = nullptr);
- ~nullary() override;
-
- void operator()() const;
+ explicit sig_void(QObject* parent = nullptr);
+ void operator()() const { notify(); }
signals:
void notify() const;
};
-} // ns qt_sig
+template<> struct sig<void> { using t = sig_void; };
+
+#ifndef OTR_GENERATE_SIGNAL3
+# define OTR_GENERATE_SIGNAL3(x)
+#endif
+#define OTR_GENERATE_SIGNAL2(type) \
+ class OTR_COMPAT_EXPORT sig_##type final : public QObject \
+ { \
+ Q_OBJECT \
+ public: \
+ explicit sig_##type(QObject* parent = nullptr) : QObject(parent) {} \
+ void operator()(const type& x) const; \
+ Q_SIGNALS: \
+ void notify(const type& x) const; \
+ }; \
+ OTR_GENERATE_SIGNAL3(type)
+
+# define OTR_GENERATE_SIGNAL(type) \
+ OTR_GENERATE_SIGNAL2(type); \
+ using qlist##type = QList<type>; \
+ OTR_GENERATE_SIGNAL2(qlist##type); \
+ template<> struct sig<type> { using t = sig_##type; }; \
+ template<> struct sig<qlist##type> { using t = qlist##type; }
+
+OTR_GENERATE_SIGNAL(int);
+OTR_GENERATE_SIGNAL(double);
+OTR_GENERATE_SIGNAL(float);
+OTR_GENERATE_SIGNAL(bool);
+OTR_GENERATE_SIGNAL(QString);
+OTR_GENERATE_SIGNAL(QPointF);
+OTR_GENERATE_SIGNAL(QVariant);
+
+} // namespace _qt_sig_impl
+
+#undef OTR_GENERATE_SIGNAL2
+#undef OTR_GENERATE_SIGNAL
+
+template<typename t> using qt_signal = typename _qt_sig_impl::sig<t>::t;
diff --git a/compat/run-in-thread.hpp b/compat/run-in-thread.hpp
index b8ffc179..c552c600 100644
--- a/compat/run-in-thread.hpp
+++ b/compat/run-in-thread.hpp
@@ -7,9 +7,6 @@
* copyright notice and this permission notice appear in all copies.
*/
-#include "macros.hpp"
-
-#include <cassert>
#include <thread>
#include <condition_variable>
#include <utility>
@@ -17,99 +14,56 @@
#include <QObject>
#include <QThread>
-namespace qt_impl_detail {
-
-template<typename t>
-struct run_in_thread_traits
+namespace impl_run_in_thread {
+struct semaphore final
{
- using type = t;
- using ret_type = t;
- static inline void assign(t& lvalue, const t& rvalue) { lvalue = rvalue; }
- static inline t pass(const t& val) { return val; }
- template<typename F> static inline t call(F&& fun) { return std::move(fun()); }
-};
+ using lock_guard = std::unique_lock<std::mutex>;
+ std::mutex mtx;
+ std::condition_variable cvar;
+ bool flag = false;
-template<typename u>
-struct run_in_thread_traits<u&&>
-{
- using t = typename std::remove_reference<u>::type;
- using type = t;
- using ret_type = u;
- static inline void assign(t& lvalue, t&& rvalue) { lvalue = rvalue; }
- static inline t&& pass(t&& val) { return val; }
- template<typename F> static inline t&& call(F&& fun) { return std::move(fun()); }
-};
+ semaphore() = default;
-template<>
-struct run_in_thread_traits<void>
-{
- using type = unsigned char;
- using ret_type = void;
- static inline void assign(unsigned char&, unsigned char&&) {}
- static inline void pass(type&&) {}
- template<typename F> static type call(F&& fun) { fun(); return type(0); }
-};
+ void wait()
+ {
+ lock_guard guard(mtx);
+ while (!flag)
+ cvar.wait(guard);
+ }
+ void notify()
+ {
+ lock_guard guard(mtx);
+ flag = true;
+ cvar.notify_one();
+ }
+};
}
template<typename F>
-auto never_inline
-run_in_thread_sync(QObject* obj, F&& fun)
- -> typename qt_impl_detail::run_in_thread_traits<decltype(fun())>::ret_type
+void run_in_thread_sync(QObject* obj, F&& fun)
{
- using lock_guard = std::unique_lock<std::mutex>;
+ if (obj->thread() == QThread::currentThread())
+ return (void)fun();
- using traits = qt_impl_detail::run_in_thread_traits<decltype(fun())>;
-
- typename traits::type ret;
-
- struct semaphore final
- {
- std::mutex mtx;
- std::condition_variable cvar;
- bool flag;
-
- semaphore() : flag(false) {}
-
- void wait()
- {
- lock_guard guard(mtx);
- while (!flag)
- cvar.wait(guard);
- }
-
- void notify()
- {
- lock_guard guard(mtx);
- flag = true;
- cvar.notify_one();
- }
- };
-
- semaphore sem;
+ impl_run_in_thread::semaphore sem;
{
QObject src;
- QObject::connect(&src,
- &QObject::destroyed,
- obj,
- [&] {
- traits::assign(ret, traits::call(fun));
- sem.notify();
- },
- Qt::AutoConnection);
+ QObject::connect(&src, &QObject::destroyed,
+ obj, [&] { fun(); sem.notify(); },
+ Qt::QueuedConnection);
}
sem.wait();
- return traits::pass(std::move(ret));
}
template<typename F>
void run_in_thread_async(QObject* obj, F&& fun)
{
+ if (obj->thread() == QThread::currentThread())
+ return (void)fun();
+
QObject src;
- QThread* t = obj->thread();
- if (!t) abort();
- src.moveToThread(t);
- QObject::connect(&src, &QObject::destroyed, obj, std::move(fun), Qt::AutoConnection);
+ QObject::connect(&src, &QObject::destroyed, obj, std::forward<F>(fun), Qt::QueuedConnection);
}
diff --git a/compat/shm.cpp b/compat/shm.cpp
index f59469dc..341de40f 100644
--- a/compat/shm.cpp
+++ b/compat/shm.cpp
@@ -17,7 +17,7 @@
#ifdef QT_CORE_LIB
# include <QDebug>
-# define warn(str, ...) (qDebug() << "shm:" str ": " << __VA_ARGS__)
+# define warn(str, ...) (qDebug() << "shm " str ": " << __VA_ARGS__)
#else
# define warn(str, ...) (void)0
#endif
@@ -134,4 +134,3 @@ bool shm_wrapper::success()
return mem != nullptr;
#endif
}
-
diff --git a/compat/shm.h b/compat/shm.h
index d1363219..5036b335 100644
--- a/compat/shm.h
+++ b/compat/shm.h
@@ -20,7 +20,7 @@
#endif
#include "export.hpp"
-#include "macros1.h"
+#include "macros.h"
class OTR_COMPAT_EXPORT shm_wrapper final
{
@@ -39,4 +39,6 @@ public:
bool unlock();
bool success();
inline void* ptr() { return mem; }
+
+ OTR_DISABLE_MOVE_COPY(shm_wrapper);
};
diff --git a/compat/timer.cpp b/compat/timer.cpp
index f60e4f62..fdea185a 100644
--- a/compat/timer.cpp
+++ b/compat/timer.cpp
@@ -23,26 +23,24 @@ void Timer::start()
gettime(&state);
}
-struct timespec Timer::gettime_() const
+struct timespec Timer::get_delta() const
{
struct timespec ts; // NOLINT
gettime(&ts);
- unsigned long long a = ts.tv_sec, b = state.tv_sec;
- int c = ts.tv_nsec, d = state.tv_nsec;
- return { (time_t)(a - b), (long)(c - d) };
+ return { ts.tv_sec - state.tv_sec, ts.tv_nsec - state.tv_nsec };
}
// milliseconds
double Timer::elapsed_ms() const
{
- struct timespec delta = gettime_();
+ struct timespec delta = get_delta();
return delta.tv_sec * 1000 + delta.tv_nsec * 1e-6;
}
double Timer::elapsed_seconds() const
{
- struct timespec delta = gettime_();
+ struct timespec delta = get_delta();
return delta.tv_sec + delta.tv_nsec * 1e-9;
}
@@ -63,20 +61,14 @@ static auto otr_get_clock_frequency()
void Timer::gettime(timespec* state)
{
- static const unsigned long long freq = otr_get_clock_frequency();
+ static const auto freq = otr_get_clock_frequency();
LARGE_INTEGER d;
BOOL ret = QueryPerformanceCounter(&d);
assert(ret && "QueryPerformanceCounter failed");
- constexpr int usec = 1000000;
- unsigned long long tm = d.QuadPart;
- tm *= usec;
- tm /= freq;
- tm %= usec;
- tm *= 1000;
-
- state->tv_sec = (time_t)((unsigned long long)d.QuadPart/freq);
- state->tv_nsec = (long)tm;
+ constexpr int nsec = 1'000'000 * 1000;
+ state->tv_sec = (time_t)(d.QuadPart/freq);
+ state->tv_nsec = (decltype(state->tv_nsec))(d.QuadPart % freq * nsec / freq);
}
#elif defined __MACH__
diff --git a/compat/timer.hpp b/compat/timer.hpp
index f7791a1a..47072226 100644
--- a/compat/timer.hpp
+++ b/compat/timer.hpp
@@ -23,6 +23,6 @@ struct OTR_COMPAT_EXPORT Timer final
private:
struct timespec state {};
static void gettime(struct timespec* state);
- struct timespec gettime_() const;
+ struct timespec get_delta() const;
using ns = time_units::ns;
};