diff --git a/README.md b/README.md index d88c7b4..e70d775 100644 --- a/README.md +++ b/README.md @@ -110,11 +110,6 @@ transcodeCtx->audioPts += frame->nb_samples; qt.dbus.integration: Could not connect "org.freedesktop.IBus" to globalEngineChanged(QString) ``` -- 在Windows和Unix下,ControlWidget和TitleWidget的控制方式不同 - - 1. Windows下使用 `mpv_set_property(d_ptr->mpv, "wid", MPV_FORMAT_INT64, &wid);`,使用layout布局,会使得视频窗口在最前面,遮挡ControlWidget和TitleWidget,所以将ControlWidget和TitleWidget悬浮在视频窗口上方,使用 `eventFilter`去处理大部分情况下ControlWidget和TitleWidget的显示,写的非常啰嗦,但是为了能够使用D3D11渲染,更棒的性能,只能这样处理,也是值得的; - 2. Unix下使用QOpenGLWidget,使用layout布局更加方便; - - MacOS打包需要[install_name_tool](/mac/change_lib_dependencies.rb),依赖拷贝脚本文件来自[iina](https://github.com/iina/iina/blob/develop/other/change_lib_dependencies.rb); **当前 `brew`安装的 `mpv`中,`libmpv.dylib`的依赖是 `@loader_path/`,所以对脚本进行了一些修改;** @@ -125,6 +120,10 @@ transcodeCtx->audioPts += frame->nb_samples; 依赖会拷贝到 `packet/Qt-Mpv.app/Contents/Frameworks/`; +# QPlayer + +- 参考 [Media Player Example](https://doc.qt.io/qt-6/qtmultimedia-player-example.html) + ## QT-BUG - 动态切换Video Render,从opengl切换到widget,还是有GPU 0-3D占用,而且使用量是opengl的2倍!!!QT-BUG? diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b4e78f8..f61566c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,5 +1,6 @@ add_subdirectory(ffmpegplayer) add_subdirectory(ffmpegtranscoder) +add_subdirectory(qplayer) if(BUILD_MPV) add_subdirectory(mpvplayer) diff --git a/examples/common/commonstr.hpp b/examples/common/commonstr.hpp new file mode 100644 index 0000000..8b97998 --- /dev/null +++ b/examples/common/commonstr.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace Common { + +struct Tr +{ + Q_DECLARE_TR_FUNCTIONS(Common) +}; + +} // namespace Common \ No newline at end of file diff --git a/examples/common/controlwidget.cc b/examples/common/controlwidget.cc index 0553dc4..2abe37b 100644 --- a/examples/common/controlwidget.cc +++ b/examples/common/controlwidget.cc @@ -131,9 +131,6 @@ ControlWidget::ControlWidget(QWidget *parent) : QWidget{parent} , d_ptr(new ControlWidgetPrivate(this)) { - setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::Tool); - setAttribute(Qt::WA_TranslucentBackground); //设置窗口背景透明 - d_ptr->setupUI(); buildConnect(); d_ptr->initModelButton(); @@ -213,7 +210,7 @@ void ControlWidget::setDuration(int value) setPosition(0); } -#ifdef MPV_ON +#if defined(MPV_ON) void ControlWidget::setChapters(const Mpv::Chapters &chapters) { QVector nodes; @@ -222,7 +219,7 @@ void ControlWidget::setChapters(const Mpv::Chapters &chapters) } d_ptr->slider->setNodes(nodes); } -#else +#elif defined(FFMPEG_ON) void ControlWidget::setChapters(const Ffmpeg::Chapters &chapters) { QVector nodes; diff --git a/examples/common/controlwidget.hpp b/examples/common/controlwidget.hpp index 07d61b1..f725c28 100644 --- a/examples/common/controlwidget.hpp +++ b/examples/common/controlwidget.hpp @@ -1,9 +1,9 @@ #ifndef CONTROLWIDGET_HPP #define CONTROLWIDGET_HPP -#ifdef MPV_ON +#if defined(MPV_ON) #include -#else +#elif defined(FFMPEG_ON) #include #endif @@ -21,9 +21,9 @@ class ControlWidget : public QWidget void setDuration(int value); [[nodiscard]] auto duration() const -> int; -#ifdef MPV_ON +#if defined(MPV_ON) void setChapters(const Mpv::Chapters &chapters); -#else +#elif defined(FFMPEG_ON) void setChapters(const Ffmpeg::Chapters &chapters); #endif [[nodiscard]] auto sliderGlobalPos() const -> QPoint; diff --git a/examples/common/titlewidget.cc b/examples/common/titlewidget.cc index 7b43f8c..4edd4c9 100644 --- a/examples/common/titlewidget.cc +++ b/examples/common/titlewidget.cc @@ -25,8 +25,6 @@ TitleWidget::TitleWidget(QWidget *parent) : QWidget{parent} , d_ptr(new TitleWidgetPrivate(this)) { - setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::Tool); - setAttribute(Qt::WA_TranslucentBackground); setupUI(); buildConnect(); diff --git a/examples/examples.pro b/examples/examples.pro index 09dc8a9..2f0607f 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -3,7 +3,8 @@ CONFIG += ordered SUBDIRS += \ ffmpegplayer \ - ffmpegtranscoder + ffmpegtranscoder \ + qplayer win32 { exists("C:/3rd/x64/mpv/include"){ diff --git a/examples/ffmpegplayer/CMakeLists.txt b/examples/ffmpegplayer/CMakeLists.txt index 8745840..33c1e63 100644 --- a/examples/ffmpegplayer/CMakeLists.txt +++ b/examples/ffmpegplayer/CMakeLists.txt @@ -1,4 +1,5 @@ set(PROJECT_SOURCES + ../common/commonstr.hpp ../common/controlwidget.cc ../common/controlwidget.hpp ../common/equalizerdialog.cpp @@ -24,6 +25,7 @@ set(PROJECT_SOURCES mainwindow.h) qt_add_executable(FfmpegPlayer MANUAL_FINALIZATION ${PROJECT_SOURCES}) +target_compile_definitions(FfmpegPlayer PRIVATE "FFMPEG_ON") target_link_libraries( FfmpegPlayer PRIVATE ffmpeg @@ -31,9 +33,9 @@ target_link_libraries( thirdparty dump utils - Qt6::Widgets - Qt6::Multimedia - Qt6::OpenGLWidgets) + Qt::Widgets + Qt::Multimedia + Qt::OpenGLWidgets) target_link_libraries(FfmpegPlayer PRIVATE PkgConfig::ffmpeg) if(CMAKE_HOST_APPLE) target_link_libraries( diff --git a/examples/ffmpegplayer/ffmpegplayer.pro b/examples/ffmpegplayer/ffmpegplayer.pro index 0278c70..6aecbf8 100644 --- a/examples/ffmpegplayer/ffmpegplayer.pro +++ b/examples/ffmpegplayer/ffmpegplayer.pro @@ -6,6 +6,8 @@ TEMPLATE = app TARGET = FfmpegPlayer +DEFINES += FFMPEG_ON + LIBS += \ -l$$replaceLibName(ffmpeg) \ -l$$replaceLibName(mediaconfig) \ @@ -30,6 +32,7 @@ SOURCES += \ mainwindow.cpp HEADERS += \ + ../common/commonstr.hpp \ ../common/controlwidget.hpp \ ../common/equalizerdialog.h \ ../common/openwebmediadialog.hpp \ diff --git a/examples/ffmpegplayer/mainwindow.cpp b/examples/ffmpegplayer/mainwindow.cpp index 2c6082d..163d399 100644 --- a/examples/ffmpegplayer/mainwindow.cpp +++ b/examples/ffmpegplayer/mainwindow.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" +#include #include #include #include @@ -18,6 +19,7 @@ #include #include +#include #include class MainWindow::MainWindowPrivate @@ -32,14 +34,6 @@ class MainWindow::MainWindowPrivate titleWidget = new TitleWidget(q_ptr); titleWidget->setMinimumHeight(80); titleWidget->setVisible(false); - auto *bottomLayout = new QHBoxLayout; - bottomLayout->addStretch(); - bottomLayout->addWidget(controlWidget); - bottomLayout->addStretch(); - controlLayout = new QVBoxLayout; - controlLayout->addWidget(titleWidget); - controlLayout->addStretch(); - controlLayout->addLayout(bottomLayout); playlistModel = new PlaylistModel(q_ptr); playlistView = new PlayListView(q_ptr); @@ -47,12 +41,12 @@ class MainWindow::MainWindowPrivate playlistView->setCurrentIndex( playlistModel->index(playlistModel->playlist()->currentIndex(), 0)); //playlistView->setMaximumWidth(250); + playListMenu = new QMenu(q_ptr); menu = new QMenu(q_ptr); - - videoMenu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Video"), q_ptr); - audioMenu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Audio"), q_ptr); - subMenu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Subtitles"), q_ptr); + videoMenu = new QMenu(Common::Tr::tr("Video"), q_ptr); + audioMenu = new QMenu(Common::Tr::tr("Audio"), q_ptr); + subMenu = new QMenu(Common::Tr::tr("Subtitles"), q_ptr); videoTracksGroup = new QActionGroup(q_ptr); videoTracksGroup->setExclusive(true); @@ -61,27 +55,36 @@ class MainWindow::MainWindowPrivate subTracksGroup = new QActionGroup(q_ptr); subTracksGroup->setExclusive(true); - mediaInfoAction = new QAction(QCoreApplication::translate("MainWindowPrivate", "Media Info"), - q_ptr); - - playListMenu = new QMenu(q_ptr); + mediaInfoAction = new QAction(Common::Tr::tr("Media Info"), q_ptr); fpsTimer = new QTimer(q_ptr); - splitter = new QSplitter(q_ptr); - splitter->addWidget(playlistView); - initShortcut(); } ~MainWindowPrivate() = default; + void setupUI() + { + auto *bottomLayout = new QHBoxLayout; + bottomLayout->addStretch(); + bottomLayout->addWidget(controlWidget); + bottomLayout->addStretch(); + controlLayout = new QVBoxLayout; + controlLayout->addWidget(titleWidget); + controlLayout->addStretch(); + controlLayout->addLayout(bottomLayout); + + splitter = new QSplitter(q_ptr); + splitter->addWidget(playlistView); + q_ptr->setCentralWidget(splitter); + } + auto createToneMappingMenu() -> QMenu * { auto *group = new QActionGroup(q_ptr); group->setExclusive(true); - auto *menu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Tone-Mapping"), - q_ptr); + auto *menu = new QMenu(Common::Tr::tr("Tone-Mapping"), q_ptr); auto toneMappings = QMetaEnum::fromType(); for (int i = 0; i < toneMappings.keyCount(); ++i) { auto value = toneMappings.value(i); @@ -110,8 +113,7 @@ class MainWindow::MainWindowPrivate { auto *group = new QActionGroup(q_ptr); group->setExclusive(true); - auto *menu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Target Primaries"), - q_ptr); + auto *menu = new QMenu(Common::Tr::tr("Target Primaries"), q_ptr); auto primaris = QMetaEnum::fromType(); for (int i = 0; i < primaris.keyCount(); ++i) { auto value = primaris.value(i); @@ -242,6 +244,24 @@ class MainWindow::MainWindowPrivate controlWidget->setPosition(0); } + void addToPlaylist(const QList &urls) + { + auto *playlist = playlistModel->playlist(); + const int previousMediaCount = playlist->mediaCount(); + for (const auto &url : urls) { + if (isPlaylist(url)) { + playlist->load(url); + } else { + playlist->addMedia(url); + } + } + if (playlist->mediaCount() > previousMediaCount) { + auto index = playlistModel->index(previousMediaCount, 0); + playlistView->setCurrentIndex(index); + q_ptr->jump(index); + } + } + MainWindow *q_ptr; QScopedPointer playerPtr; @@ -254,6 +274,8 @@ class MainWindow::MainWindowPrivate PlayListView *playlistView; PlaylistModel *playlistModel; + QMenu *playListMenu; + QSplitter *splitter; QMenu *menu; @@ -271,12 +293,8 @@ class MainWindow::MainWindowPrivate QAction *mediaInfoAction; - QMenu *playListMenu; - QTimer *fpsTimer; - QSplitter *splitter; - Ffmpeg::ToneMapping::Type toneMappingType = Ffmpeg::ToneMapping::Type::AUTO; Ffmpeg::ColorUtils::Primaries::Type primarisType = Ffmpeg::ColorUtils::Primaries::Type::AUTO; }; @@ -287,7 +305,12 @@ MainWindow::MainWindow(QWidget *parent) { Ffmpeg::printFfmpegInfo(); - setupUI(); + // QPlatformMediaDevices中有一个static std::unique_ptr create(); + // 这个QPlatformMediaDevices最终会在主线程释放,需要在主线程创建 + // 如果在主线程创建,会导致退出程序崩溃,ASSERT: "m_threadId == GetCurrentThreadId()" + QMediaDevices mediaDevices; + + d_ptr->setupUI(); buildConnect(); initMenu(); initPlayListMenu(); @@ -369,7 +392,7 @@ void MainWindow::onOpenLocalMedia() if (urls.isEmpty()) { return; } - addToPlaylist(urls); + d_ptr->addToPlaylist(urls); } void MainWindow::onOpenWebMedia() @@ -379,7 +402,7 @@ void MainWindow::onOpenWebMedia() if (dialog.exec() != QDialog::Accepted) { return; } - addToPlaylist({QUrl(dialog.url())}); + d_ptr->addToPlaylist({QUrl(dialog.url())}); } void MainWindow::onRenderChanged(QAction *action) @@ -552,7 +575,7 @@ auto MainWindow::eventFilter(QObject *watched, QEvent *event) -> bool auto *ev = dynamic_cast(event); auto urls = ev->mimeData()->urls(); if (!urls.isEmpty()) { - addToPlaylist(urls); + d_ptr->addToPlaylist(urls); } } break; case QEvent::ContextMenu: { @@ -619,11 +642,6 @@ void MainWindow::keyPressEvent(QKeyEvent *event) } } -void MainWindow::setupUI() -{ - setCentralWidget(d_ptr->splitter); -} - void MainWindow::buildConnect() { connect(d_ptr->playerPtr.data(), @@ -776,21 +794,3 @@ void MainWindow::initPlayListMenu() d_ptr->playlistModel->playlist()->clear(); }); } - -void MainWindow::addToPlaylist(const QList &urls) -{ - auto *playlist = d_ptr->playlistModel->playlist(); - const int previousMediaCount = playlist->mediaCount(); - for (const auto &url : urls) { - if (isPlaylist(url)) { - playlist->load(url); - } else { - playlist->addMedia(url); - } - } - if (playlist->mediaCount() > previousMediaCount) { - auto index = d_ptr->playlistModel->index(previousMediaCount, 0); - d_ptr->playlistView->setCurrentIndex(index); - jump(index); - } -} diff --git a/examples/ffmpegplayer/mainwindow.h b/examples/ffmpegplayer/mainwindow.h index 8e8e8d9..a14be94 100644 --- a/examples/ffmpegplayer/mainwindow.h +++ b/examples/ffmpegplayer/mainwindow.h @@ -35,12 +35,10 @@ private slots: void keyPressEvent(QKeyEvent *event) override; private: - void setupUI(); void buildConnect(); void initMenu(); void renderMenu(); void initPlayListMenu(); - void addToPlaylist(const QList &urls); class MainWindowPrivate; QScopedPointer d_ptr; diff --git a/examples/ffmpegtranscoder/CMakeLists.txt b/examples/ffmpegtranscoder/CMakeLists.txt index da878f6..3ca2632 100644 --- a/examples/ffmpegtranscoder/CMakeLists.txt +++ b/examples/ffmpegtranscoder/CMakeLists.txt @@ -1,4 +1,5 @@ set(PROJECT_SOURCES + ../common/commonstr.hpp audioencodermodel.cc audioencodermodel.hpp audioencodertableview.cc @@ -37,9 +38,9 @@ target_link_libraries( thirdparty dump utils - Qt6::Widgets - Qt6::Multimedia - Qt6::OpenGLWidgets) + Qt::Widgets + Qt::Multimedia + Qt::OpenGLWidgets) target_link_libraries(FfmpegTranscoder PRIVATE PkgConfig::ffmpeg) if(CMAKE_HOST_APPLE) diff --git a/examples/ffmpegtranscoder/ffmpegtranscoder.pro b/examples/ffmpegtranscoder/ffmpegtranscoder.pro index 5e0d642..ac42e69 100644 --- a/examples/ffmpegtranscoder/ffmpegtranscoder.pro +++ b/examples/ffmpegtranscoder/ffmpegtranscoder.pro @@ -33,6 +33,7 @@ SOURCES += \ videoencoderwidget.cc HEADERS += \ + ../common/commonstr.hpp \ audioencodermodel.hpp \ audioencodertableview.hpp \ audioencoderwidget.hpp \ diff --git a/examples/ffmpegtranscoder/mainwindow.cc b/examples/ffmpegtranscoder/mainwindow.cc index e3434ee..3c397bd 100644 --- a/examples/ffmpegtranscoder/mainwindow.cc +++ b/examples/ffmpegtranscoder/mainwindow.cc @@ -7,6 +7,7 @@ #include "subtitleencoderwidget.hpp" #include "videoencoderwidget.hpp" +#include #include #include #include @@ -36,14 +37,10 @@ class MainWindow::MainWindowPrivate videoEncoderWidget = new VideoEncoderWidget(q_ptr); audioEncoderWidget = new AudioEncoderWidget(q_ptr); subtitleEncoderWidget = new SubtitleEncoderWidget(q_ptr); - tabWidget->addTab(previewWidget, - QCoreApplication::translate("MainWindowPrivate", "Preview")); - tabWidget->addTab(videoEncoderWidget, - QCoreApplication::translate("MainWindowPrivate", "Video")); - tabWidget->addTab(audioEncoderWidget, - QCoreApplication::translate("MainWindowPrivate", "Audio")); - tabWidget->addTab(subtitleEncoderWidget, - QCoreApplication::translate("MainWindowPrivate", "Subtitle")); + tabWidget->addTab(previewWidget, Common::Tr::tr("Preview")); + tabWidget->addTab(videoEncoderWidget, Common::Tr::tr("Video")); + tabWidget->addTab(audioEncoderWidget, Common::Tr::tr("Audio")); + tabWidget->addTab(subtitleEncoderWidget, Common::Tr::tr("Subtitle")); outPutWidget = new OutPutWidget(q_ptr); statusWidget = new StautusWidget(q_ptr); diff --git a/examples/mpvplayer/CMakeLists.txt b/examples/mpvplayer/CMakeLists.txt index b17f5af..1495ce7 100644 --- a/examples/mpvplayer/CMakeLists.txt +++ b/examples/mpvplayer/CMakeLists.txt @@ -1,4 +1,5 @@ set(PROJECT_SOURCES + ../common/commonstr.hpp ../common/controlwidget.cc ../common/controlwidget.hpp ../common/equalizerdialog.cpp @@ -36,10 +37,10 @@ target_link_libraries( thirdparty dump utils - Qt6::Widgets - Qt6::Multimedia - Qt6::Network - Qt6::OpenGLWidgets) + Qt::Widgets + Qt::Multimedia + Qt::Network + Qt::OpenGLWidgets) if(CMAKE_HOST_WIN32) target_link_libraries(MpvPlayer PRIVATE C:\\3rd\\x64\\mpv\\libmpv.dll.a) file(COPY C:\\3rd\\x64\\mpv\\libmpv-2.dll diff --git a/examples/mpvplayer/mainwindow.cc b/examples/mpvplayer/mainwindow.cc index 6e854aa..07e4372 100644 --- a/examples/mpvplayer/mainwindow.cc +++ b/examples/mpvplayer/mainwindow.cc @@ -2,6 +2,7 @@ #include "mpvlogwindow.hpp" #include "subtitledelaydialog.hpp" +#include #include #include #include @@ -46,6 +47,11 @@ class MainWindow::MainWindowPrivate logWindow->show(); logWindow->move(qApp->primaryScreen()->availableGeometry().topLeft()); + floatingWidget = new QWidget(q_ptr); + floatingWidget->setWindowFlags(floatingWidget->windowFlags() | Qt::FramelessWindowHint + | Qt::Tool); + floatingWidget->setAttribute(Qt::WA_TranslucentBackground); //设置窗口背景透明 + floatingWidget->setVisible(true); controlWidget = new ControlWidget(q_ptr); controlWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); titleWidget = new TitleWidget(q_ptr); @@ -57,13 +63,13 @@ class MainWindow::MainWindowPrivate playlistView->setCurrentIndex( playlistModel->index(playlistModel->playlist()->currentIndex(), 0)); //playlistView->setMaximumWidth(250); + playListMenu = new QMenu(q_ptr); menu = new QMenu(q_ptr); - videoMenu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Video"), q_ptr); - audioMenu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Audio"), q_ptr); - subMenu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Subtitles"), q_ptr); - subDelayAction = new QAction(QCoreApplication::translate("MainWindowPrivate", "Delay"), - q_ptr); + videoMenu = new QMenu(Common::Tr::tr("Video"), q_ptr); + audioMenu = new QMenu(Common::Tr::tr("Audio"), q_ptr); + subMenu = new QMenu(Common::Tr::tr("Subtitles"), q_ptr); + subDelayAction = new QAction(Common::Tr::tr("Delay"), q_ptr); loadSubTitlesAction = new QAction(QCoreApplication::translate("MainWindowPrivate", "Load Subtitles"), @@ -75,8 +81,6 @@ class MainWindow::MainWindowPrivate subTracksGroup = new QActionGroup(q_ptr); subTracksGroup->setExclusive(true); - playListMenu = new QMenu(q_ptr); - initShortcut(); } @@ -86,7 +90,7 @@ class MainWindow::MainWindowPrivate { hwdecGroup = new QActionGroup(q_ptr); hwdecGroup->setExclusive(true); - auto *menu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "H/W"), q_ptr); + auto *menu = new QMenu(Common::Tr::tr("H/W"), q_ptr); auto hwdecs = mpvPlayer->hwdecs(); for (const auto &hwdec : std::as_const(hwdecs)) { auto *action = new QAction(hwdec, q_ptr); @@ -106,7 +110,7 @@ class MainWindow::MainWindowPrivate { gpuApiGroup = new QActionGroup(q_ptr); gpuApiGroup->setExclusive(true); - auto *menu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Gpu Api"), q_ptr); + auto *menu = new QMenu(Common::Tr::tr("Gpu Api"), q_ptr); auto gpuApis = mpvPlayer->gpuApis(); for (const auto &gpuApi : std::as_const(gpuApis)) { auto *action = new QAction(gpuApi, q_ptr); @@ -126,8 +130,7 @@ class MainWindow::MainWindowPrivate { auto *group = new QActionGroup(q_ptr); group->setExclusive(true); - auto *menu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Tone-Mapping"), - q_ptr); + auto *menu = new QMenu(Common::Tr::tr("Tone-Mapping"), q_ptr); auto toneMappings = mpvPlayer->toneMappings(); for (const auto &toneMapping : std::as_const(toneMappings)) { auto *action = new QAction(toneMapping, q_ptr); @@ -147,8 +150,7 @@ class MainWindow::MainWindowPrivate { auto *group = new QActionGroup(q_ptr); group->setExclusive(true); - auto *menu = new QMenu(QCoreApplication::translate("MainWindowPrivate", "Target Primaries"), - q_ptr); + auto *menu = new QMenu(Common::Tr::tr("Target Primaries"), q_ptr); auto targetPrimaries = mpvPlayer->targetPrimaries(); for (const auto &targetPrimary : std::as_const(targetPrimaries)) { auto *action = new QAction(targetPrimary, q_ptr); @@ -213,17 +215,11 @@ class MainWindow::MainWindowPrivate { new QShortcut(QKeySequence::MoveToNextChar, q_ptr, q_ptr, [this] { mpvPlayer->seekRelative(5); - titleWidget->setText( - QCoreApplication::translate("MainWindowPrivate", "Fast forward: 5 seconds")); - titleWidget->setAutoHide(3000); - setTitleWidgetGeometry(true); + setTitleWidgetText(Common::Tr::tr("Fast forward: 5 seconds")); }); new QShortcut(QKeySequence::MoveToPreviousChar, q_ptr, q_ptr, [this] { mpvPlayer->seekRelative(-5); - titleWidget->setText( - QCoreApplication::translate("MainWindowPrivate", "Fast return: 5 seconds")); - titleWidget->setAutoHide(3000); - setTitleWidgetGeometry(true); + setTitleWidgetText(Common::Tr::tr("Fast return: 5 seconds")); }); new QShortcut(QKeySequence::MoveToPreviousLine, q_ptr, q_ptr, [this] { controlWidget->setVolume(controlWidget->volume() + 10); @@ -234,18 +230,16 @@ class MainWindow::MainWindowPrivate new QShortcut(Qt::Key_Space, q_ptr, q_ptr, [this] { pause(); }); } - void setupUI() const + void setupUI() { -#ifndef Q_OS_WIN - auto controlLayout = new QHBoxLayout; + auto *controlLayout = new QHBoxLayout; controlLayout->addStretch(); controlLayout->addWidget(controlWidget); controlLayout->addStretch(); - auto layout = new QVBoxLayout(mpvWidget); + auto *layout = new QVBoxLayout(floatingWidget); layout->addWidget(titleWidget); layout->addStretch(); layout->addLayout(controlLayout); -#endif auto *splitter = new QSplitter(q_ptr); splitter->setHandleWidth(0); @@ -256,42 +250,32 @@ class MainWindow::MainWindowPrivate q_ptr->setCentralWidget(splitter); } + void setTitleWidgetText(const QString &text) + { + setTitleWidgetGeometry(true); + titleWidget->setText(text); + titleWidget->setAutoHide(3000); + } + void setControlWidgetGeometry(bool show = true) { -#ifdef Q_OS_WIN - controlWidget->setFixedSize({QWIDGETSIZE_MAX, QWIDGETSIZE_MAX}); - controlWidget->setMinimumWidth(mpvWidget->width() / 2); - controlWidget->adjustSize(); - if (controlWidget->width() * 2 < mpvWidget->width()) { - controlWidget->setMinimumWidth(mpvWidget->width() / 2); - } - auto margain = 10; - auto geometry = mpvWidget->geometry(); - auto p1 = QPoint(geometry.x() + (geometry.width() - controlWidget->width()) / 2.0, - geometry.bottomLeft().y() - controlWidget->height() - margain); - globalControlWidgetGeometry = {q_ptr->mapToGlobal(p1), controlWidget->size()}; - controlWidget->setFixedSize(globalControlWidgetGeometry.size()); - controlWidget->setGeometry(globalControlWidgetGeometry); + controlWidget->setVisible(true); + setFloatingWidgetGeometry(show); controlWidget->setVisible(show); -#else - controlWidget->setVisible(show); -#endif } void setTitleWidgetGeometry(bool show = true) { -#ifdef Q_OS_WIN - auto margain = 10; - auto geometry = mpvWidget->geometry(); - auto p1 = QPoint(geometry.x() + margain, geometry.y() + margain); - auto p2 = QPoint(geometry.topRight().x() - margain, geometry.y() + margain + 80); - globalTitlelWidgetGeometry = {q_ptr->mapToGlobal(p1), q_ptr->mapToGlobal(p2)}; - titleWidget->setFixedSize(globalTitlelWidgetGeometry.size()); - titleWidget->setGeometry(globalTitlelWidgetGeometry); - titleWidget->setVisible(show); -#else + titleWidget->setVisible(true); + setFloatingWidgetGeometry(show); titleWidget->setVisible(show); -#endif + } + + void setFloatingWidgetGeometry(bool show = true) + { + auto geometry = mpvWidget->geometry(); + geometry = QRect{q_ptr->mapToGlobal(geometry.topLeft()), geometry.size()}; + floatingWidget->setGeometry(geometry); } void pause() const { mpvPlayer->pauseAsync(); } @@ -303,15 +287,13 @@ class MainWindow::MainWindowPrivate QScopedPointer previewWidgetPtr; Mpv::MpvLogWindow *logWindow; + QWidget *floatingWidget; ControlWidget *controlWidget; TitleWidget *titleWidget; -#ifdef Q_OS_WIN - QRect globalTitlelWidgetGeometry; - QRect globalControlWidgetGeometry; -#endif PlayListView *playlistView; PlaylistModel *playlistModel; + QMenu *playListMenu; QMenu *menu; QActionGroup *hwdecGroup; @@ -330,8 +312,6 @@ class MainWindow::MainWindowPrivate QPointer subTracksMenuPtr; QActionGroup *subTracksGroup; QAction *loadSubTitlesAction; - - QMenu *playListMenu; }; MainWindow::MainWindow(QWidget *parent) @@ -580,7 +560,6 @@ auto MainWindow::eventFilter(QObject *watched, QEvent *event) -> bool auto *e = static_cast(event); d_ptr->menu->exec(e->globalPos()); } break; -#ifdef Q_OS_WIN case QEvent::Resize: QMetaObject::invokeMethod( this, @@ -590,7 +569,6 @@ auto MainWindow::eventFilter(QObject *watched, QEvent *event) -> bool }, Qt::QueuedConnection); break; -#endif // case QEvent::MouseButtonPress: { // auto e = static_cast(event); // if (e->button() & Qt::LeftButton) { @@ -617,7 +595,6 @@ auto MainWindow::eventFilter(QObject *watched, QEvent *event) -> bool } } else if (watched == this) { switch (event->type()) { -#ifdef Q_OS_WIN case QEvent::Show: case QEvent::Move: QMetaObject::invokeMethod( @@ -628,50 +605,19 @@ auto MainWindow::eventFilter(QObject *watched, QEvent *event) -> bool }, Qt::QueuedConnection); break; - case QEvent::Hide: d_ptr->controlWidget->hide(); break; - case QEvent::HoverMove: - if (d_ptr->globalControlWidgetGeometry.isValid()) { - auto *e = static_cast(event); - bool contain = d_ptr->globalControlWidgetGeometry.contains( - e->globalPosition().toPoint()); - bool isVisible = d_ptr->controlWidget->isVisible(); - if (contain && !isVisible) { - d_ptr->setControlWidgetGeometry(true); - } else if (!contain && isVisible) { - d_ptr->controlWidget->hide(); - } - } - if (d_ptr->globalTitlelWidgetGeometry.isValid() && isFullScreen()) { - auto *e = static_cast(event); - bool contain = d_ptr->globalTitlelWidgetGeometry.contains( - e->globalPosition().toPoint()); - bool isVisible = d_ptr->titleWidget->isVisible(); - if (contain && !isVisible) { - d_ptr->titleWidget->setText(windowTitle()); - d_ptr->setTitleWidgetGeometry(true); - } else if (!contain && isVisible) { - d_ptr->titleWidget->hide(); - } - } - break; -#else + case QEvent::Hide: d_ptr->setFloatingWidgetGeometry(false); break; case QEvent::HoverMove: { - d_ptr->controlWidget->show(); - d_ptr->controlWidget->hide(); auto controlWidgetGeometry = d_ptr->controlWidget->geometry(); auto e = static_cast(event); bool contain = controlWidgetGeometry.contains(e->position().toPoint()); d_ptr->setControlWidgetGeometry(contain); if (isFullScreen()) { - d_ptr->titleWidget->show(); - d_ptr->titleWidget->hide(); auto titleWidgetGeometry = d_ptr->titleWidget->geometry(); contain = titleWidgetGeometry.contains(e->position().toPoint()); d_ptr->setTitleWidgetGeometry(contain); } break; } -#endif default: break; } } @@ -731,19 +677,15 @@ void MainWindow::buildConnect() &QMediaPlaylist::next); connect(d_ptr->controlWidget, &ControlWidget::seek, d_ptr->mpvPlayer, [this](int value) { d_ptr->mpvPlayer->seek(value); - d_ptr->titleWidget->setText( + d_ptr->setTitleWidgetText( tr("Fast forward to: %1") .arg(QTime::fromMSecsSinceStartOfDay(value * 1000).toString("hh:mm:ss"))); - d_ptr->titleWidget->setAutoHide(3000); - d_ptr->setTitleWidgetGeometry(true); }); connect(d_ptr->controlWidget, &ControlWidget::hoverPosition, this, &MainWindow::onPreview); connect(d_ptr->controlWidget, &ControlWidget::leavePosition, this, &MainWindow::onPreviewFinish); connect(d_ptr->controlWidget, &ControlWidget::volumeChanged, d_ptr->mpvPlayer, [this](int value) { d_ptr->mpvPlayer->setVolume(value); - d_ptr->titleWidget->setText(tr("Volume: %1%").arg(value)); - d_ptr->titleWidget->setAutoHide(3000); - d_ptr->setTitleWidgetGeometry(true); + d_ptr->setTitleWidgetText(tr("Volume: %1%").arg(value)); }); auto max = d_ptr->mpvPlayer->volumeMax(); d_ptr->controlWidget->setVolumeMax(max); @@ -753,9 +695,7 @@ void MainWindow::buildConnect() d_ptr->mpvPlayer, [this](double value) { d_ptr->mpvPlayer->setSpeed(value); - d_ptr->titleWidget->setText(tr("Speed: %1").arg(value)); - d_ptr->titleWidget->setAutoHide(3000); - d_ptr->setTitleWidgetGeometry(true); + d_ptr->setTitleWidgetText(tr("Speed: %1").arg(value)); }); connect(d_ptr->controlWidget, &ControlWidget::modelChanged, diff --git a/examples/mpvplayer/mpvplayer.pro b/examples/mpvplayer/mpvplayer.pro index 25545a1..fe74147 100644 --- a/examples/mpvplayer/mpvplayer.pro +++ b/examples/mpvplayer/mpvplayer.pro @@ -35,6 +35,7 @@ SOURCES += \ subtitledelaydialog.cc HEADERS += \ + ../common/commonstr.hpp \ ../common/controlwidget.hpp \ ../common/equalizerdialog.h \ ../common/openwebmediadialog.hpp \ diff --git a/examples/qplayer/CMakeLists.txt b/examples/qplayer/CMakeLists.txt new file mode 100644 index 0000000..276e7cb --- /dev/null +++ b/examples/qplayer/CMakeLists.txt @@ -0,0 +1,41 @@ +find_package(Qt6 REQUIRED COMPONENTS MultimediaWidgets) + +set(PROJECT_SOURCES + ../common/commonstr.hpp + ../common/controlwidget.cc + ../common/controlwidget.hpp + ../common/equalizerdialog.cpp + ../common/equalizerdialog.h + ../common/openwebmediadialog.cc + ../common/openwebmediadialog.hpp + ../common/playlistmodel.cpp + ../common/playlistmodel.h + ../common/playlistview.cc + ../common/playlistview.hpp + ../common/qmediaplaylist_p.cpp + ../common/qmediaplaylist_p.h + ../common/qmediaplaylist.cpp + ../common/qmediaplaylist.h + ../common/qplaylistfileparser.cpp + ../common/qplaylistfileparser.h + ../common/slider.cpp + ../common/slider.h + ../common/titlewidget.cc + ../common/titlewidget.hpp + main.cc + mainwindow.cc + mainwindow.hpp + videowidget.cc + videowidget.hpp) + +qt_add_executable(QPlayer MANUAL_FINALIZATION ${PROJECT_SOURCES}) +target_link_libraries( + QPlayer + PRIVATE mediaconfig + thirdparty + dump + utils + Qt::MultimediaWidgets + Qt::Network + Qt::GuiPrivate) +qt_finalize_executable(QPlayer) diff --git a/examples/qplayer/main.cc b/examples/qplayer/main.cc new file mode 100644 index 0000000..d8b1b2d --- /dev/null +++ b/examples/qplayer/main.cc @@ -0,0 +1,82 @@ +#include "mainwindow.hpp" + +#include <3rdparty/qtsingleapplication/qtsingleapplication.h> +#include +#include +#include +#include + +#include +#include +#include +#include + +#define AppName "QPlayer" + +void setAppInfo() +{ + qApp->setApplicationVersion(AppInfo::version.toString()); + qApp->setApplicationDisplayName(AppName); + qApp->setApplicationName(AppName); + qApp->setDesktopFileName(AppName); + qApp->setOrganizationDomain(AppInfo::organizationDomain); + qApp->setOrganizationName(AppInfo::organzationName); + qApp->setWindowIcon(qApp->style()->standardIcon(QStyle::SP_MediaPlay)); +} + +int main(int argc, char *argv[]) +{ +#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + if (!qEnvironmentVariableIsSet("QT_OPENGL")) { + QCoreApplication::setAttribute(Qt::AA_UseOpenGLES); + } +#else + qputenv("QSG_RHI_BACKEND", "opengl"); +#endif + Utils::setHighDpiEnvironmentVariable(); + + Utils::setSurfaceFormatVersion(3, 3); + + SharedTools::QtSingleApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + SharedTools::QtSingleApplication app(AppName, argc, argv); + if (app.isRunning()) { + qWarning() << "This is already running"; + if (app.sendMessage("raise_window_noop", 5000)) { + return EXIT_SUCCESS; + } + } +#ifdef Q_OS_WIN + if (!qFuzzyCompare(app.devicePixelRatio(), 1.0) + && QApplication::style()->objectName().startsWith(QLatin1String("windows"), + Qt::CaseInsensitive)) { + QApplication::setStyle(QLatin1String("fusion")); + } +#endif +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + app.setAttribute(Qt::AA_UseHighDpiPixmaps); + app.setAttribute(Qt::AA_DisableWindowContextHelpButton); +#endif + setAppInfo(); + Dump::BreakPad::instance()->setDumpPath(Utils::crashPath()); + QDir::setCurrent(app.applicationDirPath()); + + // 异步日志 + auto *log = Utils::LogAsync::instance(); + log->setLogPath(Utils::logPath()); + log->setAutoDelFile(true); + log->setAutoDelFileDays(7); + log->setOrientation(Utils::LogAsync::Orientation::StdAndFile); + log->setLogLevel(QtDebugMsg); + log->startWork(); + + // Make sure we honor the system's proxy settings + QNetworkProxyFactory::setUseSystemConfiguration(true); + + MainWindow w; + app.setActivationWindow(&w); + w.show(); + + auto ret = app.exec(); + log->stop(); + return ret; +} diff --git a/examples/qplayer/mainwindow.cc b/examples/qplayer/mainwindow.cc new file mode 100644 index 0000000..cdf5987 --- /dev/null +++ b/examples/qplayer/mainwindow.cc @@ -0,0 +1,684 @@ +#include "mainwindow.hpp" +#include "videowidget.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +void printAudioOuputDevice() +{ + const auto audioDevices = QMediaDevices::audioOutputs(); + for (const QAudioDevice &audioDevice : std::as_const(audioDevices)) { + qDebug() << audioDevice.id() << audioDevice.description() << audioDevice.isDefault(); + } +} +QString trackName(const QMediaMetaData &metaData, int index) +{ + QString name; + QString title = metaData.stringValue(QMediaMetaData::Title); + QLocale::Language lang = metaData.value(QMediaMetaData::Language).value(); + + if (title.isEmpty()) { + if (lang == QLocale::Language::AnyLanguage) { + name = Common::Tr::tr("Track %1").arg(index + 1); + } else { + name = QLocale::languageToString(lang); + } + } else { + if (lang == QLocale::Language::AnyLanguage) { + name = title; + } else { + name = QStringLiteral("%1 - [%2]").arg(title).arg(QLocale::languageToString(lang)); + } + } + return name; +} + +class MainWindow::MainWindowPrivate +{ +public: + explicit MainWindowPrivate(MainWindow *q) + : q_ptr(q) + { + mediaDevices = new QMediaDevices(q_ptr); + + player = new QMediaPlayer(q_ptr); + audioOutput = new QAudioOutput(q_ptr); + player->setAudioOutput(audioOutput); + videoWidget = new VideoWidget(q_ptr); + player->setVideoOutput(videoWidget); + + floatingWidget = new QWidget(q_ptr); + floatingWidget->setWindowFlags(floatingWidget->windowFlags() | Qt::FramelessWindowHint + | Qt::Tool); + floatingWidget->setAttribute(Qt::WA_TranslucentBackground); //设置窗口背景透明 + floatingWidget->setVisible(true); + controlWidget = new ControlWidget(q_ptr); + controlWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + titleWidget = new TitleWidget(q_ptr); + titleWidget->setMinimumHeight(80); + + playlistModel = new PlaylistModel(q_ptr); + playlistView = new PlayListView(q_ptr); + playlistView->setModel(playlistModel); + playlistView->setCurrentIndex( + playlistModel->index(playlistModel->playlist()->currentIndex(), 0)); + //playlistView->setMaximumWidth(250); + playListMenu = new QMenu(q_ptr); + + menu = new QMenu(q_ptr); + videoMenu = new QMenu(Common::Tr::tr("Video"), q_ptr); + audioMenu = new QMenu(Common::Tr::tr("Audio"), q_ptr); + subMenu = new QMenu(Common::Tr::tr("Subtitles"), q_ptr); + videoTracksGroup = new QActionGroup(q_ptr); + videoTracksGroup->setExclusive(true); + audioTracksGroup = new QActionGroup(q_ptr); + audioTracksGroup->setExclusive(true); + subTracksGroup = new QActionGroup(q_ptr); + subTracksGroup->setExclusive(true); + + initShortcut(); + } + + void initShortcut() + { + new QShortcut(QKeySequence::MoveToNextChar, q_ptr, q_ptr, [this] { + auto position = player->position(); + position += 5000; + if (position > player->duration()) { + position = player->duration(); + } + setPosition(position); + setTitleWidgetText(Common::Tr::tr("Fast forward: 5 seconds")); + }); + new QShortcut(QKeySequence::MoveToPreviousChar, q_ptr, q_ptr, [this] { + auto position = player->position(); + position -= 5000; + if (position < 0) { + position = 0; + } + setPosition(position); + setTitleWidgetText(Common::Tr::tr("Fast return: 5 seconds")); + }); + new QShortcut(QKeySequence::MoveToPreviousLine, q_ptr, q_ptr, [this] { + controlWidget->setVolume(controlWidget->volume() + 10); + }); + new QShortcut(QKeySequence::MoveToNextLine, q_ptr, q_ptr, [this] { + controlWidget->setVolume(controlWidget->volume() - 10); + }); + new QShortcut(Qt::Key_Space, q_ptr, q_ptr, [this] { player->pause(); }); + } + + void setupUI() + { + auto *controlLayout = new QHBoxLayout; + controlLayout->addStretch(); + controlLayout->addWidget(controlWidget); + controlLayout->addStretch(); + auto *layout = new QVBoxLayout(floatingWidget); + layout->addWidget(titleWidget); + layout->addStretch(); + layout->addLayout(controlLayout); + + auto *splitter = new QSplitter(q_ptr); + splitter->addWidget(videoWidget); + splitter->addWidget(playlistView); + splitter->setSizes({200, 1}); + + q_ptr->setCentralWidget(splitter); + } + + void setTitleWidgetText(const QString &text) + { + setTitleWidgetGeometry(true); + titleWidget->setText(text); + titleWidget->setAutoHide(3000); + } + + void setControlWidgetGeometry(bool show = true) + { + controlWidget->setVisible(true); + setFloatingWidgetGeometry(show); + controlWidget->setVisible(show); + } + + void setTitleWidgetGeometry(bool show = true) + { + titleWidget->setVisible(true); + setFloatingWidgetGeometry(show); + titleWidget->setVisible(show); + } + + void setFloatingWidgetGeometry(bool show = true) + { + auto geometry = videoWidget->geometry(); + geometry = QRect{q_ptr->mapToGlobal(geometry.topLeft()), geometry.size()}; + floatingWidget->setGeometry(geometry); + } + + void addToPlaylist(const QList &urls) + { + auto *playlist = playlistModel->playlist(); + const int previousMediaCount = playlist->mediaCount(); + for (const auto &url : urls) { + if (isPlaylist(url)) { + playlist->load(url); + } else { + playlist->addMedia(url); + } + } + if (playlist->mediaCount() > previousMediaCount) { + auto index = playlistModel->index(previousMediaCount, 0); + playlistView->setCurrentIndex(index); + q_ptr->jump(index); + } + } + + void handleCursor(QMediaPlayer::MediaStatus status) + { +#ifndef QT_NO_CURSOR + if (status == QMediaPlayer::LoadingMedia || status == QMediaPlayer::BufferingMedia + || status == QMediaPlayer::StalledMedia) { + q_ptr->setCursor(QCursor(Qt::BusyCursor)); + } else { + q_ptr->unsetCursor(); + } +#endif + } + + void setPosition(qint64 position) + { + if (player->isSeekable()) { + player->setPosition(position); + } + } + + void resetTrackMenu() + { + auto actions = audioTracksGroup->actions(); + for (auto *action : actions) { + audioTracksGroup->removeAction(action); + delete action; + } + actions = videoTracksGroup->actions(); + for (auto *action : actions) { + videoTracksGroup->removeAction(action); + delete action; + } + actions = subTracksGroup->actions(); + for (auto *action : actions) { + subTracksGroup->removeAction(action); + delete action; + } + + if (!audioTracksMenuPtr.isNull()) { + delete audioTracksMenuPtr.data(); + } + if (!videoTracksMenuPtr.isNull()) { + delete videoTracksMenuPtr.data(); + } + if (!subTracksMenuPtr.isNull()) { + delete subTracksMenuPtr.data(); + } + audioTracksMenuPtr = new QMenu(QCoreApplication::translate("MainWindowPrivate", + "Select audio track"), + q_ptr); + videoTracksMenuPtr = new QMenu(QCoreApplication::translate("MainWindowPrivate", + "Select video track"), + q_ptr); + subTracksMenuPtr = new QMenu(QCoreApplication::translate("MainWindowPrivate", + "Select subtitle track"), + q_ptr); + subTracksMenuPtr->addSeparator(); + + videoMenu->addMenu(videoTracksMenuPtr.data()); + audioMenu->addMenu(audioTracksMenuPtr.data()); + subMenu->addMenu(subTracksMenuPtr.data()); + } + + MainWindow *q_ptr; + + QMediaDevices *mediaDevices; + QMediaPlayer *player; + QAudioOutput *audioOutput; + VideoWidget *videoWidget; + + QWidget *floatingWidget; + ControlWidget *controlWidget; + TitleWidget *titleWidget; + + PlayListView *playlistView; + PlaylistModel *playlistModel; + QMenu *playListMenu; + + QMenu *menu; + + QMenu *videoMenu; + QPointer videoTracksMenuPtr; + QActionGroup *videoTracksGroup; + + QMenu *audioMenu; + QPointer audioTracksMenuPtr; + QActionGroup *audioTracksGroup; + + QMenu *subMenu; + QPointer subTracksMenuPtr; + QActionGroup *subTracksGroup; +}; + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , d_ptr(new MainWindowPrivate(this)) +{ + d_ptr->setupUI(); + initMenu(); + initPlayListMenu(); + buildConnect(); + + setAttribute(Qt::WA_Hover); + d_ptr->videoWidget->installEventFilter(this); + d_ptr->playlistView->installEventFilter(this); + installEventFilter(this); + + resize(1000, 618); + printAudioOuputDevice(); +} + +MainWindow::~MainWindow() {} + +void MainWindow::onOpenLocalMedia() +{ + const auto path = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation) + .value(0, QDir::homePath()); + const auto filter = tr("Media (*)"); + const auto urls = QFileDialog::getOpenFileUrls(this, + tr("Open Media"), + QUrl::fromUserInput(path), + filter); + if (urls.isEmpty()) { + return; + } + d_ptr->addToPlaylist(urls); +} + +void MainWindow::onOpenWebMedia() +{ + OpenWebMediaDialog dialog(this); + dialog.setMinimumSize(size() / 2.0); + if (dialog.exec() != QDialog::Accepted) { + return; + } + d_ptr->addToPlaylist({QUrl(dialog.url())}); +} + +void MainWindow::onTrackChanged() +{ + d_ptr->resetTrackMenu(); + + auto newNoAction = [](QWidget *parent = nullptr) { + auto *action = new QAction("no", parent); + action->setData(-1); + action->setCheckable(true); + return action; + }; + + const auto audioTracks = d_ptr->player->audioTracks(); + auto *action = newNoAction(this); + d_ptr->audioTracksMenuPtr->addAction(action); + d_ptr->audioTracksGroup->addAction(action); + if (d_ptr->player->activeAudioTrack() == -1) { + action->setChecked(true); + } + for (int i = 0; i < audioTracks.size(); ++i) { + action = new QAction(trackName(audioTracks.at(i), i), this); + action->setData(i); + action->setCheckable(true); + d_ptr->audioTracksMenuPtr->addAction(action); + d_ptr->audioTracksGroup->addAction(action); + if (d_ptr->player->activeAudioTrack() == i) { + action->setChecked(true); + } + } + + const auto videoTracks = d_ptr->player->videoTracks(); + action = newNoAction(this); + d_ptr->videoTracksMenuPtr->addAction(action); + d_ptr->videoTracksGroup->addAction(action); + if (d_ptr->player->activeVideoTrack() == -1) { + action->setChecked(true); + } + for (int i = 0; i < videoTracks.size(); ++i) { + action = new QAction(trackName(videoTracks.at(i), i), this); + action->setData(i); + action->setCheckable(true); + d_ptr->videoTracksMenuPtr->addAction(action); + d_ptr->videoTracksGroup->addAction(action); + if (d_ptr->player->activeVideoTrack() == i) { + action->setChecked(true); + } + } + + const auto subTracks = d_ptr->player->subtitleTracks(); + action = newNoAction(this); + d_ptr->subTracksMenuPtr->addAction(action); + d_ptr->subTracksGroup->addAction(action); + if (d_ptr->player->activeSubtitleTrack() == -1) { + action->setChecked(true); + } + for (int i = 0; i < subTracks.size(); ++i) { + action = new QAction(trackName(subTracks.at(i), i), this); + action->setData(i); + action->setCheckable(true); + d_ptr->subTracksMenuPtr->addAction(action); + d_ptr->subTracksGroup->addAction(action); + if (d_ptr->player->activeSubtitleTrack() == i) { + action->setChecked(true); + } + } +} + +void MainWindow::onBufferingProgress(float progress) +{ + if (d_ptr->player->mediaStatus() == QMediaPlayer::StalledMedia) { + d_ptr->setTitleWidgetText(tr("Stalled %1%").arg(qRound(progress * 100.))); + } else { + d_ptr->setTitleWidgetText(tr("Buffering %1%").arg(qRound(progress * 100.))); + } +} + +void MainWindow::onDisplayError() +{ + if (d_ptr->player->error() != QMediaPlayer::NoError) { + d_ptr->titleWidget->setText(d_ptr->player->errorString()); + } +} + +void MainWindow::onStatusChanged(QMediaPlayer::MediaStatus status) +{ + d_ptr->handleCursor(status); + + switch (status) { + case QMediaPlayer::NoMedia: + case QMediaPlayer::LoadedMedia: { + auto *videoSink = d_ptr->player->videoSink(); + auto text = tr("%1 [%2x%3] - Backend:%4") + .arg(d_ptr->player->source().fileName(), + QString::number(videoSink->videoSize().width()), + QString::number(videoSink->videoSize().height()), + videoSink->rhi()->backendName()); + setWindowTitle(text); + } break; + case QMediaPlayer::LoadingMedia: d_ptr->setTitleWidgetText(tr("Loading...")); break; + case QMediaPlayer::BufferingMedia: + case QMediaPlayer::BufferedMedia: + d_ptr->setTitleWidgetText( + tr("Buffering %1%").arg(qRound(d_ptr->player->bufferProgress() * 100.))); + break; + case QMediaPlayer::StalledMedia: + d_ptr->setTitleWidgetText( + tr("Stalled %1%").arg(qRound(d_ptr->player->bufferProgress() * 100.))); + break; + case QMediaPlayer::EndOfMedia: + QApplication::alert(this); + d_ptr->playlistModel->playlist()->next(); + break; + case QMediaPlayer::InvalidMedia: onDisplayError(); break; + } +} + +void MainWindow::onAudioOutputsChanged() +{ + printAudioOuputDevice(); + auto audioDevice = d_ptr->mediaDevices->defaultAudioOutput(); + d_ptr->player->audioOutput()->setDevice(audioDevice); +} + +void MainWindow::playlistPositionChanged(int currentItem) +{ + if (currentItem < 0) { + return; + } + auto url = d_ptr->playlistModel->playlist()->currentMedia(); + d_ptr->playlistView->setCurrentIndex(d_ptr->playlistModel->index(currentItem, 0)); + + d_ptr->player->setSource(url); + d_ptr->player->play(); +} + +void MainWindow::jump(const QModelIndex &index) +{ + if (index.isValid()) { + d_ptr->playlistModel->playlist()->setCurrentIndex(index.row()); + } +} + +auto MainWindow::eventFilter(QObject *watched, QEvent *event) -> bool +{ + if (watched == d_ptr->videoWidget) { + switch (event->type()) { + case QEvent::DragEnter: { + auto *e = static_cast(event); + e->acceptProposedAction(); + } break; + case QEvent::DragMove: { + auto *e = static_cast(event); + e->acceptProposedAction(); + } break; + case QEvent::Drop: { + auto *e = static_cast(event); + QList urls = e->mimeData()->urls(); + if (!urls.isEmpty()) { + d_ptr->addToPlaylist(urls); + } + } break; + case QEvent::ContextMenu: { + auto *e = static_cast(event); + d_ptr->menu->exec(e->globalPos()); + } break; + case QEvent::Resize: + QMetaObject::invokeMethod( + this, + [=] { + d_ptr->setControlWidgetGeometry(d_ptr->controlWidget->isVisible()); + d_ptr->setTitleWidgetGeometry(d_ptr->titleWidget->isVisible()); + }, + Qt::QueuedConnection); + break; + // case QEvent::MouseButtonPress: { + // auto e = static_cast(event); + // if (e->button() & Qt::LeftButton) { + // d_ptr->mpvPlayer->pause(); + // } + // } break; + case QEvent::MouseButtonDblClick: + if (isFullScreen()) { + showNormal(); + } else { + d_ptr->playlistView->hide(); + showFullScreen(); + } + break; + default: break; + } + } else if (watched == d_ptr->playlistView) { + switch (event->type()) { + case QEvent::ContextMenu: { + auto *e = static_cast(event); + d_ptr->playListMenu->exec(e->globalPos()); + } break; + default: break; + } + } else if (watched == this) { + switch (event->type()) { + case QEvent::Show: + case QEvent::Move: + QMetaObject::invokeMethod( + this, + [=] { + d_ptr->setControlWidgetGeometry(d_ptr->controlWidget->isVisible()); + d_ptr->setTitleWidgetGeometry(d_ptr->titleWidget->isVisible()); + }, + Qt::QueuedConnection); + break; + case QEvent::Hide: d_ptr->setFloatingWidgetGeometry(false); break; + case QEvent::HoverMove: { + auto controlWidgetGeometry = d_ptr->controlWidget->geometry(); + auto e = static_cast(event); + bool contain = controlWidgetGeometry.contains(e->position().toPoint()); + d_ptr->setControlWidgetGeometry(contain); + if (isFullScreen()) { + auto titleWidgetGeometry = d_ptr->titleWidget->geometry(); + contain = titleWidgetGeometry.contains(e->position().toPoint()); + d_ptr->setTitleWidgetGeometry(contain); + } + break; + } + default: break; + } + } + return QMainWindow::eventFilter(watched, event); +} + +void MainWindow::keyPressEvent(QKeyEvent *event) +{ + QMainWindow::keyPressEvent(event); + + qInfo() << "MainWindow Pressed key:" << event->key(); + switch (event->key()) { + case Qt::Key_Escape: + if (isFullScreen()) { + showNormal(); + } else { + showMinimized(); + } + break; + case Qt::Key_Q: qApp->quit(); break; + default: break; + } +} + +void MainWindow::buildConnect() +{ + connect(d_ptr->mediaDevices, + &QMediaDevices::audioOutputsChanged, + this, + &MainWindow::onAudioOutputsChanged); + + connect(d_ptr->player, + &QMediaPlayer::durationChanged, + d_ptr->controlWidget, + [this](qint64 duration) { d_ptr->controlWidget->setDuration(duration / 1000); }); + connect(d_ptr->player, + &QMediaPlayer::positionChanged, + d_ptr->controlWidget, + [this](qint64 position) { d_ptr->controlWidget->setPosition(position / 1000); }); + connect(d_ptr->player, &QMediaPlayer::mediaStatusChanged, this, &MainWindow::onStatusChanged); + connect(d_ptr->player, + &QMediaPlayer::bufferProgressChanged, + this, + &MainWindow::onBufferingProgress); + connect(d_ptr->player, &QMediaPlayer::tracksChanged, this, &MainWindow::onTrackChanged); + connect(d_ptr->player, &QMediaPlayer::errorChanged, this, &MainWindow::onDisplayError); + + connect(d_ptr->controlWidget, + &ControlWidget::previous, + d_ptr->playlistModel->playlist(), + &QMediaPlaylist::previous); + connect(d_ptr->controlWidget, + &ControlWidget::next, + d_ptr->playlistModel->playlist(), + &QMediaPlaylist::next); + // connect(d_ptr->controlWidget, &ControlWidget::hoverPosition, this, &MainWindow::onHoverSlider); + // connect(d_ptr->controlWidget, &ControlWidget::leavePosition, this, &MainWindow::onLeaveSlider); + connect(d_ptr->controlWidget, &ControlWidget::seek, d_ptr->player, [this](int value) { + qint64 position = value; + d_ptr->setPosition(position * 1000); + }); + connect(d_ptr->controlWidget, &ControlWidget::play, d_ptr->player, [this](bool checked) { + if (checked && !d_ptr->player->isPlaying()) { + d_ptr->player->play(); + } else if (checked) { + d_ptr->player->pause(); + } else if (!checked) { + d_ptr->player->play(); + } + }); + connect(d_ptr->controlWidget, + &ControlWidget::volumeChanged, + d_ptr->audioOutput, + [this](int value) { + d_ptr->audioOutput->setVolume(value / 100.0); + d_ptr->setTitleWidgetText(tr("Volume: %1").arg(value)); + }); + d_ptr->controlWidget->setVolume(50); + connect(d_ptr->controlWidget, &ControlWidget::speedChanged, d_ptr->player, [this](double value) { + d_ptr->player->setPlaybackRate(value); + d_ptr->setTitleWidgetText(tr("Speed: %1").arg(value)); + }); + connect(d_ptr->controlWidget, + &ControlWidget::modelChanged, + d_ptr->playlistModel->playlist(), + [this](int model) { + d_ptr->playlistModel->playlist()->setPlaybackMode( + static_cast(model)); + }); + connect(d_ptr->controlWidget, &ControlWidget::showList, d_ptr->playlistView, [this] { + d_ptr->playlistView->setVisible(!d_ptr->playlistView->isVisible()); + }); + + connect(d_ptr->playlistModel->playlist(), + &QMediaPlaylist::currentIndexChanged, + this, + &MainWindow::playlistPositionChanged); + connect(d_ptr->playlistView, &QAbstractItemView::activated, this, &MainWindow::jump); +} + +void MainWindow::initMenu() +{ + d_ptr->menu->addAction(tr("Open Local Media"), this, &MainWindow::onOpenLocalMedia); + d_ptr->menu->addAction(tr("Open Web Media"), this, &MainWindow::onOpenWebMedia); + d_ptr->menu->addMenu(d_ptr->videoMenu); + d_ptr->menu->addMenu(d_ptr->audioMenu); + d_ptr->menu->addMenu(d_ptr->subMenu); + + connect(d_ptr->audioTracksGroup, &QActionGroup::triggered, this, [this](QAction *action) { + d_ptr->player->setActiveAudioTrack(action->data().toInt()); + }); + connect(d_ptr->videoTracksGroup, &QActionGroup::triggered, this, [this](QAction *action) { + d_ptr->player->setActiveVideoTrack(action->data().toInt()); + }); + connect(d_ptr->subTracksGroup, &QActionGroup::triggered, this, [this](QAction *action) { + d_ptr->player->setActiveSubtitleTrack(action->data().toInt()); + }); +} + +void MainWindow::initPlayListMenu() +{ + d_ptr->playListMenu->addAction(tr("Open Local Media"), this, &MainWindow::onOpenLocalMedia); + d_ptr->playListMenu->addAction(tr("Open Web Media"), this, &MainWindow::onOpenWebMedia); + d_ptr->playListMenu + ->addAction(tr("Remove the currently selected item"), d_ptr->playlistView, [this] { + auto indexs = d_ptr->playlistView->selectedAllIndexs(); + std::sort(indexs.begin(), indexs.end(), [&](QModelIndex left, QModelIndex right) { + return left.row() > right.row(); + }); + for (const auto &index : std::as_const(indexs)) { + d_ptr->playlistModel->playlist()->removeMedia(index.row()); + } + }); + d_ptr->playListMenu->addAction(tr("Clear"), d_ptr->playlistView, [this] { + d_ptr->playlistModel->playlist()->clear(); + }); +} diff --git a/examples/qplayer/mainwindow.hpp b/examples/qplayer/mainwindow.hpp new file mode 100644 index 0000000..704d403 --- /dev/null +++ b/examples/qplayer/mainwindow.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private slots: + void onOpenLocalMedia(); + void onOpenWebMedia(); + + void onTrackChanged(); + void onBufferingProgress(float progress); + void onDisplayError(); + void onStatusChanged(QMediaPlayer::MediaStatus status); + + void onAudioOutputsChanged(); + + void playlistPositionChanged(int /*currentItem*/); + void jump(const QModelIndex &index); + +protected: + auto eventFilter(QObject *watched, QEvent *event) -> bool override; + void keyPressEvent(QKeyEvent *event) override; + +private: + void buildConnect(); + void initMenu(); + void initPlayListMenu(); + + class MainWindowPrivate; + QScopedPointer d_ptr; +}; diff --git a/examples/qplayer/qplayer.pro b/examples/qplayer/qplayer.pro new file mode 100644 index 0000000..2156970 --- /dev/null +++ b/examples/qplayer/qplayer.pro @@ -0,0 +1,47 @@ +include(../../common.pri) + +QT += core gui widgets network multimediawidgets core5compat gui-private + +TEMPLATE = app + +TARGET = QPlayer + +LIBS += \ + -l$$replaceLibName(mediaconfig) \ + -l$$replaceLibName(thirdparty) \ + -l$$replaceLibName(dump) \ + -l$$replaceLibName(utils) + +include(../../src/3rdparty/3rdparty.pri) + +SOURCES += \ + ../common/controlwidget.cc \ + ../common/equalizerdialog.cpp \ + ../common/openwebmediadialog.cc \ + ../common/playlistmodel.cpp \ + ../common/playlistview.cc \ + ../common/qmediaplaylist_p.cpp \ + ../common/qmediaplaylist.cpp \ + ../common/qplaylistfileparser.cpp \ + ../common/slider.cpp \ + ../common/titlewidget.cc \ + main.cc \ + mainwindow.cc \ + videowidget.cc + +HEADERS += \ + ../common/commonstr.hpp + ../common/controlwidget.hpp \ + ../common/equalizerdialog.h \ + ../common/openwebmediadialog.hpp \ + ../common/playlistmodel.h \ + ../common/playlistview.hpp \ + ../common/qmediaplaylist.h \ + ../common/qmediaplaylist_p.h \ + ../common/qplaylistfileparser.h \ + ../common/slider.h \ + ../common/titlewidget.hpp \ + mainwindow.hpp \ + videowidget.hpp + +DESTDIR = $$APP_OUTPUT_PATH diff --git a/examples/qplayer/videowidget.cc b/examples/qplayer/videowidget.cc new file mode 100644 index 0000000..b7ae342 --- /dev/null +++ b/examples/qplayer/videowidget.cc @@ -0,0 +1,11 @@ +#include "videowidget.hpp" + +VideoWidget::VideoWidget(QWidget *parent) + : QVideoWidget{parent} +{ + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); + + QPalette p = palette(); + p.setColor(QPalette::Window, Qt::black); + setPalette(p); +} diff --git a/examples/qplayer/videowidget.hpp b/examples/qplayer/videowidget.hpp new file mode 100644 index 0000000..7ac2e68 --- /dev/null +++ b/examples/qplayer/videowidget.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +class VideoWidget : public QVideoWidget +{ + Q_OBJECT +public: + explicit VideoWidget(QWidget *parent = nullptr); +}; diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index b315c08..b05645b 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -8,8 +8,8 @@ set(PROJECT_SOURCES thirdparty_global.hpp) add_custom_library(thirdparty ${PROJECT_SOURCES}) -target_link_libraries(thirdparty PRIVATE shared_qtlockedfile Qt6::Network - Qt6::Widgets) +target_link_libraries(thirdparty PRIVATE shared_qtlockedfile Qt::Network + Qt::Widgets) if(CMAKE_HOST_WIN32) target_compile_definitions(thirdparty PRIVATE "THRIDPARTY_LIBRARY") diff --git a/src/3rdparty/qtlockedfile/CMakeLists.txt b/src/3rdparty/qtlockedfile/CMakeLists.txt index da604dc..b4d4af9 100644 --- a/src/3rdparty/qtlockedfile/CMakeLists.txt +++ b/src/3rdparty/qtlockedfile/CMakeLists.txt @@ -6,7 +6,7 @@ endif() add_library(shared_qtlockedfile STATIC ${OS_SOURCES} qtlockedfile.cpp qtlockedfile.h) -target_link_libraries(shared_qtlockedfile Qt6::Core) +target_link_libraries(shared_qtlockedfile Qt::Core) target_include_directories(shared_qtlockedfile PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") if(CMAKE_HOST_WIN32) diff --git a/src/3rdparty/qtsingleapplication/CMakeLists.txt b/src/3rdparty/qtsingleapplication/CMakeLists.txt index 923ab85..3a37d85 100644 --- a/src/3rdparty/qtsingleapplication/CMakeLists.txt +++ b/src/3rdparty/qtsingleapplication/CMakeLists.txt @@ -1,9 +1,11 @@ -add_library(shared_qtsingleapplication SHARED - qtsingleapplication.cpp qtsingleapplication.h - qtlocalpeer.cpp qtlocalpeer.h -) -target_link_libraries(shared_qtsingleapplication shared_qtlockedfile Qt6::Core Qt6::Network Qt6::Widgets) -target_include_directories(shared_qtsingleapplication PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") -if (WIN32) - target_compile_definitions(shared_qtsingleapplication PRIVATE "THRIDPARTY_LIBRARY" _UNICODE UNICODE) +add_library( + shared_qtsingleapplication SHARED + qtsingleapplication.cpp qtsingleapplication.h qtlocalpeer.cpp qtlocalpeer.h) +target_link_libraries(shared_qtsingleapplication shared_qtlockedfile Qt::Core + Qt::Network Qt::Widgets) +target_include_directories(shared_qtsingleapplication + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") +if(WIN32) + target_compile_definitions(shared_qtsingleapplication + PRIVATE "THRIDPARTY_LIBRARY" _UNICODE UNICODE) endif() diff --git a/src/dump/CMakeLists.txt b/src/dump/CMakeLists.txt index ee32b6f..18a7b02 100644 --- a/src/dump/CMakeLists.txt +++ b/src/dump/CMakeLists.txt @@ -2,7 +2,7 @@ set(PROJECT_SOURCES breakpad.hpp breakpad.cc crashpad.hpp crashpad.cc dump_global.hpp) add_custom_library(dump ${PROJECT_SOURCES}) target_link_libraries( - dump PRIVATE utils Qt6::Widgets unofficial::breakpad::libbreakpad + dump PRIVATE utils Qt::Widgets unofficial::breakpad::libbreakpad unofficial::breakpad::libbreakpad_client crashpad::crashpad) if(CMAKE_HOST_WIN32) diff --git a/src/ffmpeg/CMakeLists.txt b/src/ffmpeg/CMakeLists.txt index 2d5f10f..8898900 100644 --- a/src/ffmpeg/CMakeLists.txt +++ b/src/ffmpeg/CMakeLists.txt @@ -109,8 +109,8 @@ set(PROJECT_SOURCES qt_add_resources(SOURCES videorender/shaders.qrc) add_custom_library(ffmpeg ${PROJECT_SOURCES} ${SOURCES}) -target_link_libraries(ffmpeg PRIVATE mediaconfig utils Qt6::Widgets - Qt6::Multimedia Qt6::OpenGLWidgets) +target_link_libraries(ffmpeg PRIVATE mediaconfig utils Qt::Widgets + Qt::Multimedia Qt::OpenGLWidgets) target_link_libraries(ffmpeg PRIVATE PkgConfig::ffmpeg PkgConfig::ass) if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux") target_link_libraries(ffmpeg PRIVATE PkgConfig::fontconfig expat::expat) diff --git a/src/ffmpeg/audiorender/audiooutput.cc b/src/ffmpeg/audiorender/audiooutput.cc index cdaa722..425007f 100644 --- a/src/ffmpeg/audiorender/audiooutput.cc +++ b/src/ffmpeg/audiorender/audiooutput.cc @@ -36,6 +36,10 @@ class AudioOutput::AudioOutputPrivate int sampleSize = 0; auto format = getAudioFormatFromCodecCtx(contextInfo->codecCtx(), sampleSize); + if (!audioDevice.isFormatSupported(format)) { + qWarning() << "Raw audio format not supported by backend, cannot play audio."; + return; + } audioConverterPtr.reset(new AudioFrameConverter(contextInfo->codecCtx(), format)); audioSinkPtr.reset(new QAudioSink(format)); diff --git a/src/mediaconfig/CMakeLists.txt b/src/mediaconfig/CMakeLists.txt index 2485887..cdb1e62 100644 --- a/src/mediaconfig/CMakeLists.txt +++ b/src/mediaconfig/CMakeLists.txt @@ -1,7 +1,7 @@ set(PROJECT_SOURCES equalizer.cc equalizer.hpp mediaconfig_global.hpp) add_custom_library(mediaconfig ${PROJECT_SOURCES}) -target_link_libraries(mediaconfig PRIVATE utils Qt6::Core) +target_link_libraries(mediaconfig PRIVATE utils Qt::Core) if(CMAKE_HOST_WIN32) target_compile_definitions(mediaconfig PRIVATE "MEDIACONFIG_LIBRARY") diff --git a/src/mpv/CMakeLists.txt b/src/mpv/CMakeLists.txt index e9c10e7..9ce57a0 100644 --- a/src/mpv/CMakeLists.txt +++ b/src/mpv/CMakeLists.txt @@ -13,7 +13,7 @@ set(PROJECT_SOURCES qthelper.hpp) add_custom_library(qmpv ${PROJECT_SOURCES}) -target_link_libraries(qmpv PRIVATE Qt6::Widgets Qt6::OpenGLWidgets) +target_link_libraries(qmpv PRIVATE Qt::Widgets Qt::OpenGLWidgets) if(CMAKE_HOST_WIN32) target_include_directories(qmpv PRIVATE "C:\\3rd\\x64\\mpv\\include") diff --git a/src/mpv/mpvwidget.cc b/src/mpv/mpvwidget.cc index 74700a9..59f83ce 100644 --- a/src/mpv/mpvwidget.cc +++ b/src/mpv/mpvwidget.cc @@ -9,7 +9,7 @@ MpvWidget::MpvWidget(QWidget *parent) setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_StyledBackground); - setStyleSheet("QWidget{background:black;}"); + setStyleSheet("QWidget{ background:black; }"); } MpvWidget::~MpvWidget() = default; diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 2703bd8..75d7cd8 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -20,7 +20,7 @@ set(PROJECT_SOURCES utilstr.h) add_custom_library(utils ${PROJECT_SOURCES}) -target_link_libraries(utils PRIVATE Qt6::Widgets Qt6::Core5Compat) +target_link_libraries(utils PRIVATE Qt::Widgets Qt::Core5Compat) if(CMAKE_HOST_WIN32) target_compile_definitions(utils PRIVATE "UTILS_LIBRARY") diff --git a/src/utils/utilstr.h b/src/utils/utilstr.h index 5cfd23d..95f9de0 100644 --- a/src/utils/utilstr.h +++ b/src/utils/utilstr.h @@ -9,7 +9,7 @@ namespace Utils { struct Tr { - Q_DECLARE_TR_FUNCTIONS(QtC::Utils) + Q_DECLARE_TR_FUNCTIONS(Utils) }; -} // Utils +} // namespace Utils diff --git a/tests/subtitle_unittest/CMakeLists.txt b/tests/subtitle_unittest/CMakeLists.txt index 3b711fc..ffe14b2 100644 --- a/tests/subtitle_unittest/CMakeLists.txt +++ b/tests/subtitle_unittest/CMakeLists.txt @@ -2,8 +2,8 @@ set(PROJECT_SOURCES main.cc mainwindow.cc mainwindow.hpp subtitlethread.cc subtitlethread.hpp) qt_add_executable(subtitle_unittest MANUAL_FINALIZATION ${PROJECT_SOURCES}) -target_link_libraries(subtitle_unittest PRIVATE Qt6::Widgets Qt6::Multimedia - Qt6::OpenGLWidgets ffmpeg utils) +target_link_libraries(subtitle_unittest PRIVATE Qt::Widgets Qt::Multimedia + Qt::OpenGLWidgets ffmpeg utils) target_link_libraries(subtitle_unittest PRIVATE PkgConfig::ffmpeg) if(CMAKE_HOST_APPLE)