[multimedia/kdenlive/release/26.08] src: Resolve video import and profile loading failures on paths with diacritical marks
Jean-Baptiste Mardelle <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit a248b44adcfaac52ff967a9e509532a1111419de by Jean-Baptiste Mardelle, on behalf of Jaimukund Bhan.
Committed on 23/07/2026 at 07:37.
Pushed by mardelle into branch 'release/26.08'.
Resolve video import and profile loading failures on paths with diacritical marks
When Kdenlive is run from a standalone folder located in a directory path containing diacritical marks or non-ASCII characters, it fails to import video files and displays a "Cannot open file" error in the GUI. This MR fixes the issue by resolving startup and library search paths to their ASCII-only Windows 8.3 short paths before configuring the runtime environment.
* **Windows Short Path Helper**: Implemented a `getShortPath()` helper function on Windows to convert long paths containing spaces or non-ASCII characters to their 8.3 short path representation.
* **Environment PATH**: Updated the `PATH` environment variable setup in `main.cpp` using the short path.
* **MLT Path Configuration**: Relocated `locateMeltAndProfilesPath` earlier during MLT initialization in `MltConnection` and exported `MLT_PROFILES_PATH` and `MLT_DATA` environment variables using the Windows short paths.
BUG: 513899
M +16 -2 src/main.cpp
M +33 -2 src/mltconnection.cpp
https://invent.kde.org/multimedia/kdenlive/-/commit/a248b44adcfaac52ff967a9e509532a1111419de
diff --git a/src/main.cpp b/src/main.cpp
index 9a155d6811..83df480af5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -60,11 +60,24 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include <QUrl> //new
#ifdef Q_OS_WIN
+#include <windows.h>
extern "C" {
// Inform the driver we could make use of the discrete gpu
// __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
// __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
+static QString getShortPath(const QString &longPath)
+{
+ std::wstring longPathStd = QDir::toNativeSeparators(longPath).toStdWString();
+ DWORD size = GetShortPathNameW(longPathStd.c_str(), nullptr, 0);
+ if (size > 0) {
+ std::vector<wchar_t> buffer(size);
+ if (GetShortPathNameW(longPathStd.c_str(), buffer.data(), size) > 0) {
+ return QString::fromWCharArray(buffer.data());
+ }
+ }
+ return longPath;
+}
#endif
static LinuxPackageType getPackageType()
@@ -514,8 +527,9 @@ int main(int argc, char *argv[])
}
#ifdef Q_OS_WIN
- QString path = qApp->applicationDirPath() + QLatin1Char(';') + qgetenv("PATH");
- qputenv("PATH", path.toUtf8().constData());
+#include <stdlib.h>
+ QString path = getShortPath(qApp->applicationDirPath()) + QLatin1Char(';') + qEnvironmentVariable("PATH");
+ _wputenv_s(L"PATH", path.toStdWString().c_str());
#endif
if (QQuickWindow::graphicsApi() == QSGRendererInterface::Vulkan) {
diff --git a/src/mltconnection.cpp b/src/mltconnection.cpp
index 7f2d839e6c..739ec34999 100644
--- a/src/mltconnection.cpp
+++ b/src/mltconnection.cpp
@@ -12,7 +12,10 @@ SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#include <KLocalizedString>
#include <KUrlRequester>
#include <KUrlRequesterDialog>
+#include <QDir>
#include <QDirIterator>
+#include <QFile>
+#include <QTextStream>
#include <QtConcurrent/QtConcurrentRun>
#include <clocale>
@@ -49,6 +52,22 @@ static void mlt_log_handler(void *service, int mlt_level, const char *format, va
qDebug() << "MLT:" << message;
}
+#ifdef Q_OS_WIN
+#include <windows.h>
+static QString getShortPath(const QString &longPath)
+{
+ std::wstring longPathStd = QDir::toNativeSeparators(longPath).toStdWString();
+ DWORD size = GetShortPathNameW(longPathStd.c_str(), nullptr, 0);
+ if (size > 0) {
+ std::vector<wchar_t> buffer(size);
+ if (GetShortPathNameW(longPathStd.c_str(), buffer.data(), size) > 0) {
+ return QString::fromWCharArray(buffer.data());
+ }
+ }
+ return longPath;
+}
+#endif
+
std::unique_ptr<MltConnection> MltConnection::m_self;
MltConnection::MltConnection(const QString &mltPath)
{
@@ -59,6 +78,20 @@ MltConnection::MltConnection(const QString &mltPath)
qputenv("MLT_AVFORMAT_HWACCEL", KdenliveSettings::hwDecoding().toUtf8());
}
+ locateMeltAndProfilesPath(mltPath);
+
+#ifdef Q_OS_WIN
+ {
+ QString profilesDir = KdenliveSettings::mltpath();
+ if (QFile::exists(profilesDir)) {
+ QString shortProfilePath = getShortPath(profilesDir);
+ QString shortMltDataPath = getShortPath(QDir(profilesDir).absoluteFilePath(QStringLiteral("..")));
+ _wputenv_s(L"MLT_PROFILES_PATH", shortProfilePath.toStdWString().c_str());
+ _wputenv_s(L"MLT_DATA", shortMltDataPath.toStdWString().c_str());
+ }
+ }
+#endif
+
// After initialising the MLT factory, set the locale back from user default to C
// to ensure numbers are always serialised with . as decimal point.
m_repository = std::unique_ptr<Mlt::Repository>(Mlt::Factory::init());
@@ -69,8 +102,6 @@ MltConnection::MltConnection(const QString &mltPath)
std::setlocale(MLT_LC_CATEGORY, nullptr);
#endif
- locateMeltAndProfilesPath(mltPath);
-
// Retrieve the list of available producers.
QScopedPointer<Mlt::Properties> producers(m_repository->producers());
QStringList producersList;