diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-01-26 10:14:34 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-01-26 12:13:38 +0100 |
commit | 58761c8d6fa2f64b85845ccd18f759f0ecc7e550 (patch) | |
tree | 5878eaaa3ce68e4971f7effddde3f9aa557da197 | |
parent | b29b8e48fe59f44fd28de5f6879730bcdf34a9dd (diff) |
compat/camera-names: allow cameras with same name
Some users have multiple units of the same camera model connected at
the same time. Allow selecting each of these individual units.
Issue: #1415
-rw-r--r-- | compat/camera-names.cpp | 38 | ||||
-rw-r--r-- | migration/20220126_00-camera-name.cpp | 79 |
2 files changed, 110 insertions, 7 deletions
diff --git a/compat/camera-names.cpp b/compat/camera-names.cpp index 8eef6d61..c7e38544 100644 --- a/compat/camera-names.cpp +++ b/compat/camera-names.cpp @@ -2,6 +2,7 @@ #include <algorithm> #include <iterator> +#include <QRegularExpression> #ifdef _WIN32 # include <cwchar> @@ -41,6 +42,31 @@ int camera_name_to_index(const QString &name) return -1; } +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; +} + std::vector<std::tuple<QString, int>> get_camera_names() { std::vector<std::tuple<QString, int>> ret; @@ -67,18 +93,16 @@ 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))); + 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(); diff --git a/migration/20220126_00-camera-name.cpp b/migration/20220126_00-camera-name.cpp new file mode 100644 index 00000000..adb6d718 --- /dev/null +++ b/migration/20220126_00-camera-name.cpp @@ -0,0 +1,79 @@ +#ifdef _WIN32 +#include "migration.hpp" +#include "options/options.hpp" +#include "compat/camera-names.hpp" + +using namespace migrations; +using namespace options; + +#include "api/plugin-support.hpp" +#include "compat/library-path.hpp" +#include <tuple> +#include <QString> + +static const std::tuple<const char*, const char*> modules[] = { + { "tracker-aruco", "camera-name" }, + { "tracker-easy", "camera-name" }, + { "neuralnet-tracker", "camera-name" }, + { "tracker-pt", "camera-name" }, +}; + +struct win32_camera_name : migration +{ + QString unique_date() const override + { + return "20220126_00"; + } + + QString name() const override + { + return "camera name"; + } + + bool should_run() const override + { + for (const auto& [name, prop] : modules) + { + bundle b { make_bundle(name) }; + QString str = b->get_variant(prop).toString(); + if (!str.isEmpty() && !str.contains(" [")) + return true; + } + return false; + } + + void run() override + { + auto cameras = get_camera_names(); + + for (const auto& [bundle_name, prop] : modules) + { + bundle b { make_bundle(bundle_name) }; + QString name = b->get_variant(prop).toString(); + if (name.isEmpty() || name.contains(" [")) + continue; + auto full_name_of = [&](const QString& str) { + QString ret = str; + auto prefix = str + " ["; + for (const auto& [x, _] : cameras) + { + if (x == str) + return str; + if (x.startsWith(prefix)) + ret = x; + } + return ret; + }; + auto full_name = full_name_of(name); + if (name != full_name) + { + b->store_kv(prop, full_name); + b->save(); + } + } + } +}; + +OPENTRACK_MIGRATION(win32_camera_name) + +#endif |