chore: drop windows-specific code
This commit is contained in:
@@ -81,7 +81,6 @@ endfunction()
|
||||
|
||||
# ==========================================
|
||||
# 允许通过缓存变量或环境变量提供 Qt 安装路径
|
||||
# Windows 未显式指定时仍会尝试兼容现有本地默认路径
|
||||
# ==========================================
|
||||
set(QEMBY_QT_ROOT "" CACHE PATH
|
||||
"Optional Qt installation root or CMake prefix path")
|
||||
|
||||
@@ -17,13 +17,6 @@ function(qemby_append_default_qt_prefixes)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND _qemby_qt_prefixes
|
||||
"E:/Qt6/6.9.2/msvc2022_64"
|
||||
"E:/Qt6/6.9.2/msvc2022_64/lib/cmake"
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(_qemby_qt_prefix IN LISTS _qemby_qt_prefixes)
|
||||
if(EXISTS "${_qemby_qt_prefix}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${_qemby_qt_prefix}")
|
||||
@@ -42,26 +35,6 @@ function(qemby_link_libmpv target)
|
||||
message(FATAL_ERROR "qemby_link_libmpv: target '${target}' does not exist")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(_qemby_mpv_root "${CMAKE_SOURCE_DIR}/libs/libmpv")
|
||||
set(_qemby_mpv_include_dir "${_qemby_mpv_root}/include")
|
||||
|
||||
find_library(MPV_LIBRARY
|
||||
NAMES mpv libmpv mpv-2 libmpv-2
|
||||
PATHS "${_qemby_mpv_root}/lib"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
if(NOT MPV_LIBRARY OR NOT EXISTS "${_qemby_mpv_include_dir}/mpv/client.h")
|
||||
message(FATAL_ERROR
|
||||
"Could not find bundled libmpv. Place the libmpv SDK under libs/libmpv.")
|
||||
endif()
|
||||
|
||||
target_include_directories("${target}" PRIVATE "${_qemby_mpv_include_dir}")
|
||||
target_link_libraries("${target}" PRIVATE "${MPV_LIBRARY}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(MPV REQUIRED IMPORTED_TARGET mpv)
|
||||
target_link_libraries("${target}" PRIVATE PkgConfig::MPV)
|
||||
|
||||
@@ -10,13 +10,6 @@ set(APP_QRC_FILES resources/resources.qrc)
|
||||
|
||||
file(GLOB_RECURSE APP_HEADERS CONFIGURE_DEPENDS "*.h")
|
||||
file(GLOB_RECURSE APP_SOURCES CONFIGURE_DEPENDS "*.cpp")
|
||||
|
||||
# ==========================================
|
||||
# 平台原生资源配置 (如 Windows .exe 图标)
|
||||
# ==========================================
|
||||
if(WIN32)
|
||||
set(APP_NATIVE_RESOURCES qEmbyApp.rc)
|
||||
endif()
|
||||
|
||||
qt_add_executable(qEmbyApp
|
||||
MANUAL_FINALIZATION
|
||||
@@ -24,12 +17,10 @@ qt_add_executable(qEmbyApp
|
||||
${APP_SOURCES}
|
||||
${TS_FILES}
|
||||
${APP_QRC_FILES}
|
||||
${APP_NATIVE_RESOURCES} # <-- 将 .rc 资源文件加入编译列表
|
||||
)
|
||||
|
||||
# ==========================================
|
||||
# 集成 libmpv 播放器核心
|
||||
# Windows 使用仓库内置 libmpv
|
||||
# Linux / macOS 优先使用系统安装的 libmpv
|
||||
# ==========================================
|
||||
qemby_link_libmpv(qEmbyApp)
|
||||
@@ -121,7 +112,7 @@ else()
|
||||
target_sources(qEmbyApp PRIVATE ${QM_FILES})
|
||||
endif()
|
||||
|
||||
# 4. 设置平台属性 (Windows 和 macOS)
|
||||
# 4. 设置平台属性
|
||||
if(${QT_VERSION} VERSION_LESS 6.1.0)
|
||||
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.hl.qEmby)
|
||||
endif()
|
||||
@@ -132,7 +123,6 @@ set_target_properties(qEmbyApp PROPERTIES
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
# MACOSX_BUNDLE_ICON_FILE app.icns # 如果未来需要适配 macOS 图标,取消此注释
|
||||
)
|
||||
|
||||
@@ -157,31 +147,3 @@ if(QT_VERSION_MAJOR EQUAL 6)
|
||||
# 注意:目标从 qEmby 改为 qEmbyApp
|
||||
qt_finalize_executable(qEmbyApp)
|
||||
endif()
|
||||
|
||||
# ==========================================
|
||||
# 终极防弹方案:调用 windeployqt 自动补全所有 Qt 依赖
|
||||
# ==========================================
|
||||
if(WIN32)
|
||||
# 找到 Qt 官方的部署工具
|
||||
set(_windeployqt_hints)
|
||||
if(QEMBY_QT_ROOT)
|
||||
list(APPEND _windeployqt_hints "${QEMBY_QT_ROOT}/bin")
|
||||
endif()
|
||||
if(DEFINED ENV{QTDIR} AND NOT "$ENV{QTDIR}" STREQUAL "")
|
||||
list(APPEND _windeployqt_hints "$ENV{QTDIR}/bin")
|
||||
endif()
|
||||
list(APPEND _windeployqt_hints "E:/Qt6/6.9.2/msvc2022_64/bin")
|
||||
list(REMOVE_DUPLICATES _windeployqt_hints)
|
||||
|
||||
find_program(WINDEPLOYQT_EXECUTABLE windeployqt PATHS ${_windeployqt_hints})
|
||||
|
||||
if(WINDEPLOYQT_EXECUTABLE)
|
||||
# 在 qEmbyApp 编译完成后的那一刻,自动执行该工具
|
||||
add_custom_command(TARGET qEmbyApp POST_BUILD
|
||||
COMMAND ${WINDEPLOYQT_EXECUTABLE} $<TARGET_FILE:qEmbyApp>
|
||||
COMMENT "正在召唤 windeployqt 自动补全所有的 Qt DLL 和底层插件..."
|
||||
)
|
||||
else()
|
||||
message(WARNING "未找到 windeployqt,自动部署失败!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -8,43 +8,10 @@
|
||||
#include <widgetframe/windowbar.h>
|
||||
#include <widgetframe/windowbutton.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
using DwmSetWindowAttributePtr =
|
||||
HRESULT(WINAPI *)(HWND, DWORD, LPCVOID, DWORD);
|
||||
|
||||
void setWindowTransitionsDisabled(WId windowId, bool disabled)
|
||||
{
|
||||
static const HMODULE dwmapi = LoadLibraryW(L"dwmapi.dll");
|
||||
if (!dwmapi || !windowId) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const auto dwmSetWindowAttribute =
|
||||
reinterpret_cast<DwmSetWindowAttributePtr>(
|
||||
GetProcAddress(dwmapi, "DwmSetWindowAttribute"));
|
||||
if (!dwmSetWindowAttribute) {
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr DWORD kDwmwaTransitionsForcedDisabled = 3;
|
||||
const BOOL value = disabled ? TRUE : FALSE;
|
||||
dwmSetWindowAttribute(reinterpret_cast<HWND>(windowId),
|
||||
kDwmwaTransitionsForcedDisabled,
|
||||
&value, sizeof(value));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
ModernDialogBase::ModernDialogBase(QWidget *parent,
|
||||
bool disableNativeTransitions)
|
||||
: QDialog(parent) {
|
||||
Q_UNUSED(disableNativeTransitions);
|
||||
|
||||
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||
|
||||
@@ -101,14 +68,6 @@ ModernDialogBase::ModernDialogBase(QWidget *parent,
|
||||
agent->setSystemButton(QWK::WindowAgentBase::Close, closeBtn);
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (disableNativeTransitions) {
|
||||
setWindowTransitionsDisabled(winId(), true);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(disableNativeTransitions);
|
||||
#endif
|
||||
|
||||
|
||||
m_contentLayout = new QVBoxLayout();
|
||||
m_contentLayout->setContentsMargins(20, 10, 20, 20);
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
#include <config/config_keys.h>
|
||||
#include <QStandardPaths>
|
||||
#include <QRegularExpression>
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QThread>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
QAtomicInt MpvController::s_warmedUp(0);
|
||||
@@ -56,7 +52,7 @@ void MpvController::warmupOnce() {
|
||||
}
|
||||
|
||||
qDebug() << "[MpvController::warmupOnce] dispatch mpv warmup to worker thread"
|
||||
<< "(preload libmpv DLLs + FFmpeg codec tables to avoid first-play UI freeze)";
|
||||
<< "(preload libmpv + FFmpeg codec tables to avoid first-play UI freeze)";
|
||||
|
||||
|
||||
|
||||
@@ -93,7 +89,7 @@ void MpvController::warmupOnce() {
|
||||
|
||||
|
||||
qDebug() << "[MpvController::warmupOnce] total elapsed" << timer.elapsed() << "ms"
|
||||
<< "(libmpv DLLs + codec tables now resident in process memory;"
|
||||
<< "(libmpv + codec tables now resident in process memory;"
|
||||
<< "next mpv_initialize will run on hot path)";
|
||||
});
|
||||
}
|
||||
@@ -153,22 +149,6 @@ bool MpvController::init() {
|
||||
|
||||
|
||||
QString hwdec = ConfigStore::instance()->get<QString>(ConfigKeys::PlayerHwDec, "auto-copy");
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
mpv_set_option_string(m_mpv, "gpu-api", "opengl");
|
||||
mpv_set_option_string(m_mpv, "opengl-es", "no");
|
||||
bool isRDP = GetSystemMetrics(SM_REMOTESESSION) != 0;
|
||||
if (isRDP) {
|
||||
|
||||
hwdec = "no";
|
||||
mpv_set_option_string(m_mpv, "profile", "sw-fast");
|
||||
|
||||
|
||||
mpv_set_option_string(m_mpv, "gpu-dumb-mode", "yes");
|
||||
mpv_set_option_string(m_mpv, "opengl-pbo", "no");
|
||||
mpv_set_option_string(m_mpv, "dither-depth", "no");
|
||||
}
|
||||
#endif
|
||||
mpv_set_option_string(m_mpv, "hwdec", hwdec.toUtf8().constData());
|
||||
|
||||
|
||||
|
||||
@@ -12,19 +12,7 @@
|
||||
#include "managers/languagemanager.h"
|
||||
#include "managers/logmanager.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
int main(int argc, char *argv[]) {
|
||||
#ifdef Q_OS_WIN
|
||||
bool isRDP = GetSystemMetrics(SM_REMOTESESSION) != 0;
|
||||
if (isRDP) {
|
||||
|
||||
|
||||
qputenv("QT_OPENGL", "software");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
const QByteArray qpaPlatform = qgetenv("QT_QPA_PLATFORM");
|
||||
const QByteArray forceXcb = qgetenv("QEMBY_FORCE_XCB").toLower();
|
||||
|
||||
@@ -637,22 +637,7 @@ bool DownloadManager::openContainingFolder(const QString& recordId) const
|
||||
<< "| filePath:" << fileInfo.absoluteFilePath()
|
||||
<< "| directory:" << directory;
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
if (fileInfo.exists() && fileInfo.isFile()) {
|
||||
const bool started = QProcess::startDetached(
|
||||
QStringLiteral("explorer.exe"),
|
||||
{QStringLiteral("/select,"),
|
||||
QDir::toNativeSeparators(fileInfo.absoluteFilePath())});
|
||||
if (started) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qWarning() << "[DownloadManager] Failed to launch Explorer with"
|
||||
" file selection"
|
||||
<< "| recordId:" << recordId
|
||||
<< "| filePath:" << fileInfo.absoluteFilePath();
|
||||
}
|
||||
#elif defined(Q_OS_MACOS)
|
||||
#if defined(Q_OS_MACOS)
|
||||
if (fileInfo.exists() && fileInfo.isFile()) {
|
||||
const bool started = QProcess::startDetached(
|
||||
QStringLiteral("open"),
|
||||
|
||||
@@ -2,16 +2,10 @@
|
||||
#include <config/config_keys.h>
|
||||
#include <config/configstore.h>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QSet>
|
||||
#include <QStandardPaths>
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QSettings>
|
||||
#endif
|
||||
|
||||
QList<DetectedPlayer> ExternalPlayerDetector::detect() {
|
||||
QList<DetectedPlayer> result;
|
||||
@@ -27,110 +21,7 @@ QList<DetectedPlayer> ExternalPlayerDetector::detect() {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
auto tryRegistry = [&](const QString &name, const QString ®Key,
|
||||
const QString &valueName,
|
||||
const QString &exeName = {}) {
|
||||
QSettings reg(regKey, QSettings::NativeFormat);
|
||||
QString val = reg.value(valueName).toString();
|
||||
if (val.isEmpty())
|
||||
return;
|
||||
QString fullPath = val;
|
||||
if (!exeName.isEmpty() && QFileInfo(val).isDir()) {
|
||||
fullPath = val + "/" + exeName;
|
||||
}
|
||||
if (QFile::exists(fullPath)) {
|
||||
result.append({name, QDir::toNativeSeparators(fullPath)});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
tryRegistry(
|
||||
"PotPlayer",
|
||||
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App "
|
||||
"Paths\\PotPlayerMini64.exe",
|
||||
".", "");
|
||||
if (result.isEmpty() || result.last().name != "PotPlayer") {
|
||||
tryRegistry("PotPlayer",
|
||||
"HKEY_LOCAL_MACHINE\\SOFTWARE\\DAUM\\PotPlayer64",
|
||||
"ProgramFolder", "PotPlayerMini64.exe");
|
||||
}
|
||||
|
||||
|
||||
tryRegistry("VLC", "HKEY_LOCAL_MACHINE\\SOFTWARE\\VideoLAN\\VLC",
|
||||
"InstallDir", "vlc.exe");
|
||||
|
||||
|
||||
tryRegistry(
|
||||
"MPC-HC",
|
||||
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App "
|
||||
"Paths\\mpc-hc64.exe",
|
||||
".", "");
|
||||
if (result.isEmpty() || result.last().name != "MPC-HC") {
|
||||
tryRegistry("MPC-HC",
|
||||
"HKEY_LOCAL_"
|
||||
"MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App "
|
||||
"Paths\\mpc-hc.exe",
|
||||
".", "");
|
||||
}
|
||||
|
||||
|
||||
tryRegistry(
|
||||
"MPC-BE",
|
||||
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App "
|
||||
"Paths\\mpc-be64.exe",
|
||||
".", "");
|
||||
if (result.isEmpty() || result.last().name != "MPC-BE") {
|
||||
tryRegistry("MPC-BE",
|
||||
"HKEY_LOCAL_"
|
||||
"MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App "
|
||||
"Paths\\mpc-be.exe",
|
||||
".", "");
|
||||
}
|
||||
if (result.isEmpty() || result.last().name != "MPC-BE") {
|
||||
QStringList beDirs;
|
||||
for (const auto &drive : QDir::drives()) {
|
||||
QString d = drive.absolutePath();
|
||||
beDirs << d + "Program Files/MPC-BE x64" << d + "Program Files/MPC-BE"
|
||||
<< d + "Program Files (x86)/MPC-BE";
|
||||
}
|
||||
tryDetect("MPC-BE", {"mpc-be64.exe", "mpc-be.exe"}, beDirs);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
QString pathMpv = QStandardPaths::findExecutable("mpv.exe");
|
||||
if (!pathMpv.isEmpty()) {
|
||||
result.append({"MPV", QDir::toNativeSeparators(pathMpv)});
|
||||
}
|
||||
QSet<QString> foundPaths;
|
||||
if (!pathMpv.isEmpty())
|
||||
foundPaths.insert(QDir::toNativeSeparators(pathMpv));
|
||||
|
||||
for (const auto &drive : QDir::drives()) {
|
||||
QString d = drive.absolutePath();
|
||||
QStringList searchRoots = {d + "Program Files",
|
||||
d + "Program Files (x86)"};
|
||||
for (const auto &root : searchRoots) {
|
||||
QDir rootDir(root);
|
||||
if (!rootDir.exists())
|
||||
continue;
|
||||
QStringList mpvDirs = rootDir.entryList({"mpv*"}, QDir::Dirs);
|
||||
for (const auto &sub : mpvDirs) {
|
||||
QString exePath = root + "/" + sub + "/mpv.exe";
|
||||
if (QFile::exists(exePath)) {
|
||||
QString native = QDir::toNativeSeparators(exePath);
|
||||
if (!foundPaths.contains(native)) {
|
||||
foundPaths.insert(native);
|
||||
QString label = QString("MPV (%1)").arg(sub);
|
||||
result.append({label, native});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(Q_OS_MAC)
|
||||
#if defined(Q_OS_MAC)
|
||||
tryDetect("MPV", {"mpv"});
|
||||
tryDetect("VLC", {"vlc"}, {"/Applications/VLC.app/Contents/MacOS"});
|
||||
tryDetect("IINA", {"iina"}, {"/Applications/IINA.app/Contents/MacOS"});
|
||||
|
||||
@@ -24,13 +24,7 @@ ExternalPlayerIPC* ExternalPlayerIPC::create(PlayerType type, const QString& ipc
|
||||
return new MpvIPC(ipcEndpoint, parent);
|
||||
|
||||
case PlayerType::VLC:
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
case PlayerType::MPC_HC:
|
||||
return new MpcSlaveIPC(parent);
|
||||
#endif
|
||||
|
||||
case PlayerType::MPC_BE:
|
||||
return new EstimationIPC(parent);
|
||||
|
||||
default:
|
||||
return new EstimationIPC(parent);
|
||||
@@ -293,136 +287,6 @@ void VlcRcIPC::onReadyRead()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
|
||||
|
||||
namespace MpcCmd {
|
||||
|
||||
constexpr DWORD CMD_CURRENTPOSITION = 0x50000007;
|
||||
constexpr DWORD CMD_NOWPLAYING = 0x50000003;
|
||||
constexpr DWORD CMD_PLAYMODE = 0x50000004;
|
||||
constexpr DWORD CMD_NOTIFYSEEK = 0x50000008;
|
||||
constexpr DWORD CMD_NOTIFYENDSTREAM = 0x50000009;
|
||||
|
||||
|
||||
constexpr DWORD CMD_GETCURRENTPOSITION = 0xA0003004;
|
||||
}
|
||||
|
||||
MpcSlaveWindow::MpcSlaveWindow(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
|
||||
setFixedSize(1, 1);
|
||||
setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
||||
setAttribute(Qt::WA_ShowWithoutActivating);
|
||||
|
||||
|
||||
winId();
|
||||
}
|
||||
|
||||
bool MpcSlaveWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr* result)
|
||||
{
|
||||
if (eventType == "windows_generic_MSG") {
|
||||
MSG* msg = static_cast<MSG*>(message);
|
||||
if (msg->message == WM_COPYDATA) {
|
||||
COPYDATASTRUCT* cds = reinterpret_cast<COPYDATASTRUCT*>(msg->lParam);
|
||||
if (!cds) return false;
|
||||
|
||||
|
||||
QString data = QString::fromWCharArray(
|
||||
reinterpret_cast<const wchar_t*>(cds->lpData),
|
||||
cds->cbData / sizeof(wchar_t));
|
||||
|
||||
if (data.endsWith(QChar('\0')))
|
||||
data.chop(1);
|
||||
|
||||
switch (cds->dwData) {
|
||||
case MpcCmd::CMD_CURRENTPOSITION:
|
||||
case MpcCmd::CMD_NOTIFYSEEK: {
|
||||
|
||||
bool ok;
|
||||
|
||||
double seconds = data.toDouble(&ok);
|
||||
if (!ok) {
|
||||
|
||||
QStringList parts = data.split(':');
|
||||
if (parts.size() == 3) {
|
||||
seconds = parts[0].toDouble() * 3600 + parts[1].toDouble() * 60 + parts[2].toDouble();
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
if (ok && seconds >= 0.0) {
|
||||
long long posMs = static_cast<long long>(seconds * 1000);
|
||||
Q_EMIT positionReceived(posMs);
|
||||
}
|
||||
if (result) *result = 1;
|
||||
return true;
|
||||
}
|
||||
case MpcCmd::CMD_NOTIFYENDSTREAM:
|
||||
Q_EMIT playbackEnded();
|
||||
if (result) *result = 1;
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QWidget::nativeEvent(eventType, message, result);
|
||||
}
|
||||
|
||||
MpcSlaveIPC::MpcSlaveIPC(QObject* parent)
|
||||
: ExternalPlayerIPC(parent)
|
||||
{
|
||||
}
|
||||
|
||||
MpcSlaveIPC::~MpcSlaveIPC()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void MpcSlaveIPC::start(long long startPositionTicks)
|
||||
{
|
||||
m_lastPositionTicks = startPositionTicks;
|
||||
|
||||
m_window = new MpcSlaveWindow();
|
||||
connect(m_window, &MpcSlaveWindow::positionReceived, this, [this](long long posMs) {
|
||||
m_lastPositionTicks = posMs * 10000LL;
|
||||
Q_EMIT positionUpdated(m_lastPositionTicks);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MpcSlaveIPC::stop()
|
||||
{
|
||||
if (m_window) {
|
||||
m_window->deleteLater();
|
||||
m_window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
long long MpcSlaveIPC::currentPositionTicks() const
|
||||
{
|
||||
return m_lastPositionTicks;
|
||||
}
|
||||
|
||||
QString MpcSlaveIPC::hwndString() const
|
||||
{
|
||||
if (m_window)
|
||||
return QString::number(static_cast<quintptr>(m_window->winId()));
|
||||
return {};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
EstimationIPC::EstimationIPC(QObject* parent)
|
||||
: ExternalPlayerIPC(parent)
|
||||
{
|
||||
|
||||
@@ -15,9 +15,6 @@ enum class PlayerType {
|
||||
MPV,
|
||||
IINA,
|
||||
VLC,
|
||||
PotPlayer,
|
||||
MPC_HC,
|
||||
MPC_BE,
|
||||
MPC_Qt,
|
||||
Unknown
|
||||
};
|
||||
@@ -120,50 +117,6 @@ private:
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class MpcSlaveWindow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MpcSlaveWindow(QWidget* parent = nullptr);
|
||||
|
||||
signals:
|
||||
void positionReceived(long long positionMs);
|
||||
void playbackEnded();
|
||||
|
||||
protected:
|
||||
bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
|
||||
};
|
||||
|
||||
class MpcSlaveIPC : public ExternalPlayerIPC
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MpcSlaveIPC(QObject* parent = nullptr);
|
||||
~MpcSlaveIPC() override;
|
||||
|
||||
void start(long long startPositionTicks) override;
|
||||
void stop() override;
|
||||
long long currentPositionTicks() const override;
|
||||
bool isPrecise() const override { return true; }
|
||||
|
||||
|
||||
QString hwndString() const;
|
||||
|
||||
private:
|
||||
MpcSlaveWindow* m_window = nullptr;
|
||||
long long m_lastPositionTicks = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
class EstimationIPC : public ExternalPlayerIPC
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -151,14 +151,8 @@ PlayerType PlaybackManager::identifyPlayerType(const QString& playerPath)
|
||||
{
|
||||
QString baseName = QFileInfo(playerPath).baseName().toLower();
|
||||
|
||||
if (baseName.contains("potplayer"))
|
||||
return PlayerType::PotPlayer;
|
||||
if (baseName == "vlc")
|
||||
return PlayerType::VLC;
|
||||
if (baseName.contains("mpc-hc") || baseName == "mpc-hc64")
|
||||
return PlayerType::MPC_HC;
|
||||
if (baseName.contains("mpc-be") || baseName == "mpc-be64")
|
||||
return PlayerType::MPC_BE;
|
||||
if (baseName == "mpv")
|
||||
return PlayerType::MPV;
|
||||
if (baseName == "iina")
|
||||
@@ -217,11 +211,7 @@ QString PlaybackManager::generateIpcEndpoint(PlayerType type)
|
||||
switch (type) {
|
||||
case PlayerType::MPV:
|
||||
case PlayerType::IINA:
|
||||
#ifdef Q_OS_WIN
|
||||
return QString("\\\\.\\pipe\\qemby-mpv-%1").arg(pid);
|
||||
#else
|
||||
return QString("/tmp/qemby-mpv-%1.sock").arg(pid);
|
||||
#endif
|
||||
case PlayerType::VLC: {
|
||||
|
||||
int port = 42900 + static_cast<int>(pid % 1000);
|
||||
@@ -282,12 +272,6 @@ QStringList PlaybackManager::buildPlayerArgs(PlayerType type,
|
||||
args << "--mpv-sid=no";
|
||||
break;
|
||||
|
||||
case PlayerType::PotPlayer:
|
||||
if (startPositionTicks > 0)
|
||||
args << QString("/seek=%1").arg(timeStr);
|
||||
|
||||
break;
|
||||
|
||||
case PlayerType::VLC:
|
||||
if (startPositionTicks > 0)
|
||||
args << QString("--start-time=%1").arg(static_cast<int>(seconds));
|
||||
@@ -297,16 +281,6 @@ QStringList PlaybackManager::buildPlayerArgs(PlayerType type,
|
||||
args << QString("--sub-track=%1").arg(relSub);
|
||||
break;
|
||||
|
||||
case PlayerType::MPC_HC:
|
||||
if (startPositionTicks > 0)
|
||||
args << "/startpos" << timeStr;
|
||||
break;
|
||||
|
||||
case PlayerType::MPC_BE:
|
||||
if (startPositionTicks > 0)
|
||||
args << "/startpos" << timeStr;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -543,9 +517,6 @@ void PlaybackManager::launchExternalPlayer(const QString& mediaId, const QString
|
||||
if (isLocalPath) {
|
||||
qDebug() << "[PlaybackManager] Detected local path, adapting format...";
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
actualStreamUrl.replace('/', '\\');
|
||||
#endif
|
||||
switch (playerType) {
|
||||
case PlayerType::MPV:
|
||||
case PlayerType::IINA:
|
||||
@@ -570,20 +541,6 @@ void PlaybackManager::launchExternalPlayer(const QString& mediaId, const QString
|
||||
m_currentMediaId = mediaId;
|
||||
m_currentMediaSourceId = mediaSourceId;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (playerType == PlayerType::MPC_HC) {
|
||||
|
||||
|
||||
auto* mpcIpc = new MpcSlaveIPC(this);
|
||||
mpcIpc->start(startPositionTicks);
|
||||
QString hwnd = mpcIpc->hwndString();
|
||||
if (!hwnd.isEmpty()) {
|
||||
args.insert(args.size() - 1, "/slave");
|
||||
args.insert(args.size() - 1, hwnd);
|
||||
}
|
||||
m_ipc = mpcIpc;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
m_ipc = ExternalPlayerIPC::create(playerType, ipcEndpoint, this);
|
||||
m_ipc->start(startPositionTicks);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <QPalette>
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QSettings>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include "config/configstore.h"
|
||||
@@ -162,13 +161,6 @@ ThemeManager::Theme ThemeManager::detectSystemTheme()
|
||||
|
||||
auto scheme = QGuiApplication::styleHints()->colorScheme();
|
||||
return (scheme == Qt::ColorScheme::Light) ? Light : Dark;
|
||||
#elif defined(Q_OS_WIN)
|
||||
|
||||
|
||||
QSettings reg("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
|
||||
QSettings::NativeFormat);
|
||||
QVariant val = reg.value("AppsUseLightTheme", 0);
|
||||
return val.toInt() == 1 ? Light : Dark;
|
||||
#elif defined(Q_OS_MACOS)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
// This is the complete Windows Resource file for qEmbyApp.
|
||||
|
||||
// IDI_ICON1 是图标资源的 ID,101 是任意不冲突的整数。
|
||||
// ICON 声明资源类型为图标。
|
||||
// "qEmbyApp.ico" 是图标文件的相对路径(相对于此 .rc 文件)。
|
||||
|
||||
IDI_ICON1 ICON DISCARDABLE "resources/qEmbyApp.ico"
|
||||
@@ -2038,10 +2038,6 @@ Cette opération supprimera le fichier journal actuel ainsi que les sauvegardes
|
||||
|
||||
<context>
|
||||
<name>PagePlayer</name>
|
||||
<message>
|
||||
<source>D3D11VA (Windows)</source>
|
||||
<translation>D3D11VA (Windows)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select GPU acceleration API for video rendering</source>
|
||||
<translation>Sélectionner l'API d'accélération GPU pour le rendu vidéo</translation>
|
||||
@@ -2507,12 +2503,12 @@ Cette action ne peut pas être annulée.</translation>
|
||||
<translation>Auto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>D3D11VA</source>
|
||||
<translation>D3D11VA</translation>
|
||||
<source>VAAPI</source>
|
||||
<translation>VAAPI</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DXVA2</source>
|
||||
<translation>DXVA2</translation>
|
||||
<source>VDPAU</source>
|
||||
<translation>VDPAU</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>CUDA (NVIDIA)</source>
|
||||
|
||||
@@ -2298,10 +2298,6 @@ This will remove the current log and rotated backups. This action cannot be undo
|
||||
|
||||
<context>
|
||||
<name>PagePlayer</name>
|
||||
<message>
|
||||
<source>D3D11VA (Windows)</source>
|
||||
<translation>D3D11VA (Windows)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select GPU acceleration API for video rendering</source>
|
||||
<translation>选择视频渲染的 GPU 加速接口</translation>
|
||||
@@ -2819,12 +2815,12 @@ This action cannot be undone.</source>
|
||||
<translation>自动</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>D3D11VA</source>
|
||||
<translation>D3D11VA</translation>
|
||||
<source>VAAPI</source>
|
||||
<translation>VAAPI</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DXVA2</source>
|
||||
<translation>DXVA2</translation>
|
||||
<source>VDPAU</source>
|
||||
<translation>VDPAU</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>CUDA (NVIDIA)</source>
|
||||
|
||||
@@ -2376,7 +2376,7 @@ QProgressBar#detail-progress-bar {
|
||||
max-height: 2px;
|
||||
background-color: rgba(255, 255, 255, 0.12);
|
||||
border: 1px solid transparent;
|
||||
/* 核心:用透明边框强制覆盖 Windows 原生样式引擎 */
|
||||
/* 核心:用透明边框强制覆盖原生样式引擎 */
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
|
||||
@@ -2048,7 +2048,7 @@ QPushButton#gallery-nav-btn:pressed {
|
||||
QPushButton#section-more-btn {
|
||||
background: transparent;
|
||||
color: #0078D7;
|
||||
/* Windows 经典强调色,或替换为你系统的 Primary Color */
|
||||
/* 经典强调色,或替换为系统的 Primary Color */
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
@@ -2450,7 +2450,7 @@ QProgressBar#detail-progress-bar {
|
||||
max-height: 2px;
|
||||
background-color: rgba(0, 0, 0, 0.12);
|
||||
border: 1px solid transparent;
|
||||
/* 核心:用透明边框强制覆盖 Windows 原生样式引擎 */
|
||||
/* 核心:用透明边框强制覆盖原生样式引擎 */
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <windows.h>
|
||||
#elif defined(Q_OS_MACOS)
|
||||
#if defined(Q_OS_MACOS)
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/pwr_mgt/IOPMLib.h>
|
||||
#elif defined(QEMBY_HAS_QT_DBUS)
|
||||
@@ -22,7 +20,7 @@ bool g_platformInhibited = false;
|
||||
#if defined(Q_OS_MACOS)
|
||||
IOPMAssertionID g_displayAssertion = kIOPMNullAssertionID;
|
||||
IOPMAssertionID g_systemAssertion = kIOPMNullAssertionID;
|
||||
#elif defined(QEMBY_HAS_QT_DBUS) && !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
|
||||
#elif defined(QEMBY_HAS_QT_DBUS)
|
||||
enum class DbusInhibitor {
|
||||
None,
|
||||
FreedesktopScreenSaver,
|
||||
@@ -57,18 +55,7 @@ CFStringRef createCFString(const QString &value)
|
||||
|
||||
bool activatePlatformInhibition(const QString &reason)
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
const EXECUTION_STATE state =
|
||||
ES_CONTINUOUS | ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED;
|
||||
const EXECUTION_STATE previous = SetThreadExecutionState(state);
|
||||
if (previous == 0) {
|
||||
qWarning() << "[PowerInhibit] Failed to prevent display sleep on Windows";
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "[PowerInhibit] Display sleep inhibited on Windows";
|
||||
return true;
|
||||
#elif defined(Q_OS_MACOS)
|
||||
#if defined(Q_OS_MACOS)
|
||||
const QString resolvedReason = inhibitionReason(reason);
|
||||
CFStringRef reasonRef = createCFString(resolvedReason);
|
||||
if (!reasonRef) {
|
||||
@@ -181,10 +168,7 @@ bool activatePlatformInhibition(const QString &reason)
|
||||
|
||||
void deactivatePlatformInhibition()
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
SetThreadExecutionState(ES_CONTINUOUS);
|
||||
qDebug() << "[PowerInhibit] Display sleep inhibition released on Windows";
|
||||
#elif defined(Q_OS_MACOS)
|
||||
#if defined(Q_OS_MACOS)
|
||||
if (g_displayAssertion != kIOPMNullAssertionID) {
|
||||
IOPMAssertionRelease(g_displayAssertion);
|
||||
g_displayAssertion = kIOPMNullAssertionID;
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include <QRegularExpression>
|
||||
#include <QSignalBlocker>
|
||||
#include <QSet>
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
#include <QStandardPaths>
|
||||
#include <QTextStream>
|
||||
@@ -53,8 +52,8 @@ PagePlayer::PagePlayer(QEmbyCore *core, QWidget *parent)
|
||||
|
||||
auto *hwCombo = new ModernComboBox(this);
|
||||
hwCombo->addItem(tr("Auto"), "auto-copy");
|
||||
hwCombo->addItem(tr("D3D11VA"), "d3d11va-copy");
|
||||
hwCombo->addItem(tr("DXVA2"), "dxva2-copy");
|
||||
hwCombo->addItem(tr("VAAPI"), "vaapi-copy");
|
||||
hwCombo->addItem(tr("VDPAU"), "vdpau-copy");
|
||||
hwCombo->addItem(tr("CUDA (NVIDIA)"), "cuda-copy");
|
||||
hwCombo->addItem(tr("None (Software)"), "no");
|
||||
m_mainLayout->addWidget(
|
||||
@@ -880,21 +879,9 @@ PagePlayer::PagePlayer(QEmbyCore *core, QWidget *parent)
|
||||
m_mainLayout->addWidget(extTitle);
|
||||
|
||||
QStringList supportedExternalPlayers;
|
||||
#ifdef Q_OS_WIN
|
||||
supportedExternalPlayers = {QStringLiteral("PotPlayer"),
|
||||
QStringLiteral("VLC"),
|
||||
QStringLiteral("MPC-HC"),
|
||||
QStringLiteral("MPC-BE"),
|
||||
QStringLiteral("MPV")};
|
||||
#elif defined(Q_OS_MAC)
|
||||
supportedExternalPlayers = {QStringLiteral("MPV"),
|
||||
QStringLiteral("VLC"),
|
||||
QStringLiteral("IINA")};
|
||||
#else
|
||||
supportedExternalPlayers = {QStringLiteral("MPV"),
|
||||
QStringLiteral("VLC"),
|
||||
QStringLiteral("MPC-Qt")};
|
||||
#endif
|
||||
const QString externalPlayerSupportText =
|
||||
tr("Supported players on this platform: %1")
|
||||
.arg(supportedExternalPlayers.join(QStringLiteral(", ")));
|
||||
@@ -1130,11 +1117,7 @@ PagePlayer::PagePlayer(QEmbyCore *core, QWidget *parent)
|
||||
if (source == PlayerComboBox::SourceCustom) {
|
||||
QString filePath = QFileDialog::getOpenFileName(
|
||||
this, tr("Select External Player"), QString(),
|
||||
#ifdef Q_OS_WIN
|
||||
tr("Executable Files (*.exe)")
|
||||
#else
|
||||
tr("All Files (*)")
|
||||
#endif
|
||||
);
|
||||
if (!filePath.isEmpty()) {
|
||||
filePath = QDir::toNativeSeparators(filePath);
|
||||
|
||||
@@ -65,29 +65,10 @@ QString compactProductType(QString type)
|
||||
return type;
|
||||
}
|
||||
|
||||
int windowsBuildNumber()
|
||||
{
|
||||
const QStringList parts = QSysInfo::kernelVersion().split(QLatin1Char('.'));
|
||||
bool ok = false;
|
||||
const int build = parts.size() >= 3 ? parts.at(2).toInt(&ok) : 0;
|
||||
return ok ? build : 0;
|
||||
}
|
||||
|
||||
|
||||
QString readableOsName()
|
||||
{
|
||||
const QString type = QSysInfo::productType().toLower();
|
||||
const QString version = QSysInfo::productVersion().trimmed();
|
||||
if (type == QStringLiteral("windows"))
|
||||
{
|
||||
const int build = windowsBuildNumber();
|
||||
if (build >= 22000)
|
||||
return QStringLiteral("Win11");
|
||||
if (build > 0)
|
||||
return QStringLiteral("Win10");
|
||||
return version.isEmpty() ? QStringLiteral("Windows")
|
||||
: QStringLiteral("Windows%1").arg(version);
|
||||
}
|
||||
if (type == QStringLiteral("macos") || type == QStringLiteral("osx"))
|
||||
return version.isEmpty() ? QStringLiteral("macOS")
|
||||
: QStringLiteral("macOS%1").arg(version);
|
||||
|
||||
Reference in New Issue
Block a user