diff --git a/.github/actions/install-dependencies/action.yml b/.github/actions/install-dependencies/action.yml index 0d3a514..93f2542 100644 --- a/.github/actions/install-dependencies/action.yml +++ b/.github/actions/install-dependencies/action.yml @@ -23,7 +23,7 @@ inputs: qt_ver: description: 'qt version' required: false - default: '6.7.2' + default: '6.8.0' type: string runs: @@ -42,7 +42,7 @@ runs: rm vcpkg.json - name: Cache windows vcpkg - if: startsWith(runner.os, 'Windows') + if: runner.os == 'Windows' uses: actions/cache@v4 with: path: C:\vcpkg\installed @@ -51,10 +51,9 @@ runs: ${{ inputs.os_name }}-vcpkg-installed-${{ runner.os_name }}- ${{ inputs.os_name }}-vcpkg-installed- ${{ inputs.os_name }}- - save-always: true - name: Cache macos or linux vcpkg - if: startsWith(runner.os, 'macOS') || startsWith(runner.os, 'Linux') + if: runner.os == 'macOS' || runner.os == 'Linux' uses: actions/cache@v4 with: path: /usr/local/share/vcpkg/installed @@ -63,10 +62,9 @@ runs: ${{ inputs.os_name }}-vcpkg-installed-${{ runner.os_name }}- ${{ inputs.os_name }}-vcpkg-installed- ${{ inputs.os_name }}- - save-always: true - name: Install dependencies on windows - if: startsWith(runner.os, 'Windows') + if: runner.os == 'Windows' shell: bash run: | choco install ninja @@ -77,7 +75,7 @@ runs: || (cat C:/vcpkg/installed/vcpkg/issue_body.md && exit 1) - name: Install dependencies on macos - if: startsWith(runner.os, 'macOS') + if: runner.os == 'macOS' shell: bash run: | brew install ninja nasm python-setuptools mpv @@ -92,7 +90,7 @@ runs: || (cat /usr/local/share/vcpkg/installed/vcpkg/issue_body.md && exit 1) - name: Install dependencies on linux - if: startsWith(runner.os, 'Linux') + if: runner.os == 'Linux' shell: bash run: | sudo apt-get update @@ -112,3 +110,4 @@ runs: version: ${{ inputs.qt_ver }} modules: ${{ inputs.qt_modules }} cache: 'true' + \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..5d5094d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "github-actions" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" + \ No newline at end of file diff --git a/.github/workflows/qmake.yml b/.github/workflows/qmake.yml index 8bf5e5d..8fc3428 100644 --- a/.github/workflows/qmake.yml +++ b/.github/workflows/qmake.yml @@ -31,7 +31,7 @@ jobs: fail-fast: false matrix: os: - - windows-2019 + - windows-latest - macos-latest - ubuntu-latest @@ -55,7 +55,7 @@ jobs: if: startsWith(matrix.os, 'windows') shell: pwsh run: | - ..\scripts\windows\setVsDev.ps1 -VersionRange "[16.0,17.0)" -Arch "x64" + ..\scripts\windows\setVsDev.ps1 & qmake ./../. & jom working-directory: build diff --git a/.github/workflows/toolchain.yml b/.github/workflows/toolchain.yml index 39dd345..c56f5b0 100644 --- a/.github/workflows/toolchain.yml +++ b/.github/workflows/toolchain.yml @@ -20,7 +20,6 @@ jobs: matrix: os: - windows-latest - - windows-2019 - macos-latest - ubuntu-latest diff --git a/cmake/qt.cmake b/cmake/qt.cmake index 56163b4..f50baf5 100644 --- a/cmake/qt.cmake +++ b/cmake/qt.cmake @@ -1,7 +1,7 @@ if(CMAKE_HOST_WIN32) - list(APPEND CMAKE_PREFIX_PATH "C:\\Qt\\6.7.2\\msvc2019_64") + list(APPEND CMAKE_PREFIX_PATH "C:\\Qt\\6.8.0\\msvc2022_64") elseif(CMAKE_HOST_APPLE) elseif(CMAKE_HOST_LINUX) - list(APPEND CMAKE_PREFIX_PATH "/opt/Qt/6.7.2/gcc_64") + list(APPEND CMAKE_PREFIX_PATH "/opt/Qt/6.8.0/gcc_64") endif() diff --git a/examples/common/playlistmodel.cpp b/examples/common/playlistmodel.cpp index 030db1f..a417b80 100644 --- a/examples/common/playlistmodel.cpp +++ b/examples/common/playlistmodel.cpp @@ -53,7 +53,7 @@ QModelIndex PlaylistModel::parent(const QModelIndex &child) const QVariant PlaylistModel::data(const QModelIndex &index, int role) const { - if (index.isValid() && (role == Qt::DisplayRole || role == Qt::ToolTipRole)) { + if (index.isValid() && role == Qt::DisplayRole) { QVariant value = m_data[index]; if (!value.isValid() && index.column() == Title) { QUrl location = m_playlist->media(index.row()); @@ -97,7 +97,7 @@ void PlaylistModel::beginRemoveItems(int start, int end) void PlaylistModel::endRemoveItems() { - endRemoveRows(); + endInsertRows(); } void PlaylistModel::changeItems(int start, int end) @@ -105,3 +105,5 @@ void PlaylistModel::changeItems(int start, int end) m_data.clear(); emit dataChanged(index(start, 0), index(end, ColumnCount)); } + +#include "moc_playlistmodel.cpp" diff --git a/examples/common/playlistmodel.h b/examples/common/playlistmodel.h index 01822cf..0c510f6 100644 --- a/examples/common/playlistmodel.h +++ b/examples/common/playlistmodel.h @@ -16,26 +16,24 @@ class PlaylistModel : public QAbstractItemModel Q_OBJECT public: - enum Column - { - Title = 0, - ColumnCount - }; + enum Column { Title = 0, ColumnCount }; explicit PlaylistModel(QObject *parent = nullptr); - ~PlaylistModel() override; + ~PlaylistModel(); - [[nodiscard]] auto rowCount(const QModelIndex &parent = QModelIndex()) const -> int override; - [[nodiscard]] auto columnCount(const QModelIndex &parent = QModelIndex()) const -> int override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; - [[nodiscard]] auto index(int row, int column, const QModelIndex &parent = QModelIndex()) const -> QModelIndex override; - [[nodiscard]] auto parent(const QModelIndex &child) const -> QModelIndex override; + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &child) const override; - [[nodiscard]] auto data(const QModelIndex &index, int role = Qt::DisplayRole) const -> QVariant override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - [[nodiscard]] auto playlist() const -> QMediaPlaylist *; + QMediaPlaylist *playlist() const; - auto setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole) -> bool override; + bool setData(const QModelIndex &index, const QVariant &value, + int role = Qt::DisplayRole) override; private slots: void beginInsertItems(int start, int end); diff --git a/examples/common/qmediaplaylist.cpp b/examples/common/qmediaplaylist.cpp index a2bdd24..0fc8c05 100644 --- a/examples/common/qmediaplaylist.cpp +++ b/examples/common/qmediaplaylist.cpp @@ -1,16 +1,15 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include "qmediaplaylist.h" #include "qmediaplaylist_p.h" -#include "qplaylistfileparser_p.h" +#include "qplaylistfileparser.h" +#include +#include +#include #include -#include -#include -#include -#include -#include +#include QT_BEGIN_NAMESPACE @@ -124,10 +123,12 @@ int QMediaPlaylistPrivate::prevPosition(int steps) const \value CurrentItemInLoop The current item is played repeatedly in a loop. - \value Sequential Playback starts from the current and moves through each successive item until the last is reached and then stops. - The next item is a null item when the last one is currently playing. + \value Sequential Playback starts from the current and moves through each successive + item until the last is reached and then stops. The next item is a null item when the last one is + currently playing. - \value Loop Playback restarts at the first item after the last has finished playing. + \value Loop Playback restarts at the first item after the last has finished + playing. \value Random Play items in random order. */ diff --git a/examples/common/qmediaplaylist.h b/examples/common/qmediaplaylist.h index 2da5cae..a954ad2 100644 --- a/examples/common/qmediaplaylist.h +++ b/examples/common/qmediaplaylist.h @@ -1,13 +1,10 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef QMEDIAPLAYLIST_H #define QMEDIAPLAYLIST_H -#include - -#include -#include +#include QT_BEGIN_NAMESPACE @@ -27,41 +24,41 @@ class QMediaPlaylist : public QObject Q_ENUM(Error) explicit QMediaPlaylist(QObject *parent = nullptr); - ~QMediaPlaylist() override; + virtual ~QMediaPlaylist(); - [[nodiscard]] auto playbackMode() const -> PlaybackMode; + PlaybackMode playbackMode() const; void setPlaybackMode(PlaybackMode mode); - [[nodiscard]] auto currentIndex() const -> int; - [[nodiscard]] auto currentMedia() const -> QUrl; + int currentIndex() const; + QUrl currentMedia() const; - [[nodiscard]] auto nextIndex(int steps = 1) const -> int; - [[nodiscard]] auto previousIndex(int steps = 1) const -> int; + int nextIndex(int steps = 1) const; + int previousIndex(int steps = 1) const; - [[nodiscard]] auto media(int index) const -> QUrl; + QUrl media(int index) const; - [[nodiscard]] auto mediaCount() const -> int; - [[nodiscard]] auto isEmpty() const -> bool; + int mediaCount() const; + bool isEmpty() const; void addMedia(const QUrl &content); void addMedia(const QList &items); - auto insertMedia(int index, const QUrl &content) -> bool; - auto insertMedia(int index, const QList &items) -> bool; - auto moveMedia(int from, int to) -> bool; - auto removeMedia(int pos) -> bool; - auto removeMedia(int start, int end) -> bool; + bool insertMedia(int index, const QUrl &content); + bool insertMedia(int index, const QList &items); + bool moveMedia(int from, int to); + bool removeMedia(int pos); + bool removeMedia(int start, int end); void clear(); void load(const QUrl &location, const char *format = nullptr); void load(QIODevice *device, const char *format = nullptr); - auto save(const QUrl &location, const char *format = nullptr) const -> bool; - auto save(QIODevice *device, const char *format) const -> bool; + bool save(const QUrl &location, const char *format = nullptr) const; + bool save(QIODevice *device, const char *format) const; - [[nodiscard]] auto error() const -> Error; - [[nodiscard]] auto errorString() const -> QString; + Error error() const; + QString errorString() const; -public Q_SLOTS: +public slots: void shuffle(); void next(); @@ -69,7 +66,7 @@ public Q_SLOTS: void setCurrentIndex(int index); -Q_SIGNALS: +signals: void currentIndexChanged(int index); void playbackModeChanged(QMediaPlaylist::PlaybackMode mode); void currentMediaChanged(const QUrl &); @@ -90,7 +87,4 @@ public Q_SLOTS: QT_END_NAMESPACE -Q_MEDIA_ENUM_DEBUG(QMediaPlaylist, PlaybackMode) -Q_MEDIA_ENUM_DEBUG(QMediaPlaylist, Error) - #endif // QMEDIAPLAYLIST_H diff --git a/examples/common/qmediaplaylist_p.cpp b/examples/common/qmediaplaylist_p.cpp new file mode 100644 index 0000000..13e1644 --- /dev/null +++ b/examples/common/qmediaplaylist_p.cpp @@ -0,0 +1,65 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "qmediaplaylist_p.h" + +QT_BEGIN_NAMESPACE + +QMediaPlaylistPrivate::QMediaPlaylistPrivate() : error(QMediaPlaylist::NoError) { } + +QMediaPlaylistPrivate::~QMediaPlaylistPrivate() +{ + delete parser; +} + +void QMediaPlaylistPrivate::loadFailed(QMediaPlaylist::Error error, const QString &errorString) +{ + this->error = error; + this->errorString = errorString; + + emit q_ptr->loadFailed(); +} + +void QMediaPlaylistPrivate::loadFinished() +{ + q_ptr->addMedia(parser->playlist); + + emit q_ptr->loaded(); +} + +bool QMediaPlaylistPrivate::checkFormat(const char *format) const +{ + QLatin1String f(format); + QPlaylistFileParser::FileType type = + format ? QPlaylistFileParser::UNKNOWN : QPlaylistFileParser::M3U8; + if (format) { + if (f == QLatin1String("m3u") || f == QLatin1String("text/uri-list") + || f == QLatin1String("audio/x-mpegurl") || f == QLatin1String("audio/mpegurl")) + type = QPlaylistFileParser::M3U; + else if (f == QLatin1String("m3u8") || f == QLatin1String("application/x-mpegURL") + || f == QLatin1String("application/vnd.apple.mpegurl")) + type = QPlaylistFileParser::M3U8; + } + + if (type == QPlaylistFileParser::UNKNOWN || type == QPlaylistFileParser::PLS) { + error = QMediaPlaylist::FormatNotSupportedError; + errorString = QMediaPlaylist::tr("This file format is not supported."); + return false; + } + return true; +} + +void QMediaPlaylistPrivate::ensureParser() +{ + if (parser) + return; + + parser = new QPlaylistFileParser(q_ptr); + QObject::connect(parser, &QPlaylistFileParser::finished, q_ptr, [this]() { loadFinished(); }); + QObject::connect(parser, &QPlaylistFileParser::error, q_ptr, + [this](QMediaPlaylist::Error err, const QString &errorMsg) { + loadFailed(err, errorMsg); + }); +} + +QT_END_NAMESPACE diff --git a/examples/common/qmediaplaylist_p.h b/examples/common/qmediaplaylist_p.h index 76663f8..df43776 100644 --- a/examples/common/qmediaplaylist_p.h +++ b/examples/common/qmediaplaylist_p.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef QMEDIAPLAYLIST_P_H #define QMEDIAPLAYLIST_P_H @@ -16,12 +16,14 @@ // #include "qmediaplaylist.h" -#include "qplaylistfileparser_p.h" +#include "qplaylistfileparser.h" -#include +#include + +#include #ifdef Q_MOC_RUN -#pragma Q_MOC_EXPAND_MACROS +# pragma Q_MOC_EXPAND_MACROS #endif QT_BEGIN_NAMESPACE @@ -32,69 +34,20 @@ class QMediaPlaylistPrivate { Q_DECLARE_PUBLIC(QMediaPlaylist) public: - QMediaPlaylistPrivate() - : error(QMediaPlaylist::NoError) - {} - - virtual ~QMediaPlaylistPrivate() - { - if (parser) - delete parser; - } - - void loadFailed(QMediaPlaylist::Error error, const QString &errorString) - { - this->error = error; - this->errorString = errorString; - - emit q_ptr->loadFailed(); - } - - void loadFinished() const - { - q_ptr->addMedia(parser->playlist); - - emit q_ptr->loaded(); - } - - auto checkFormat(const char *format) const -> bool - { - QLatin1String f(format); - QPlaylistFileParser::FileType type = format != nullptr ? QPlaylistFileParser::UNKNOWN - : QPlaylistFileParser::M3U8; - if (format != nullptr) { - if (f == QLatin1String("m3u") || f == QLatin1String("text/uri-list") - || f == QLatin1String("audio/x-mpegurl") || f == QLatin1String("audio/mpegurl")) - type = QPlaylistFileParser::M3U; - else if (f == QLatin1String("m3u8") || f == QLatin1String("application/x-mpegURL") - || f == QLatin1String("application/vnd.apple.mpegurl")) - type = QPlaylistFileParser::M3U8; - } - - if (type == QPlaylistFileParser::UNKNOWN || type == QPlaylistFileParser::PLS) { - error = QMediaPlaylist::FormatNotSupportedError; - errorString = QMediaPlaylist::tr("This file format is not supported."); - return false; - } - return true; - } - - void ensureParser() - { - if (parser != nullptr) - return; - - parser = new QPlaylistFileParser(q_ptr); - QObject::connect(parser, &QPlaylistFileParser::finished, [this]() { loadFinished(); }); - QObject::connect(parser, - &QPlaylistFileParser::error, - [this](QMediaPlaylist::Error err, const QString &errorMsg) { - loadFailed(err, errorMsg); - }); - } - - auto nextPosition(int steps) const -> int; - auto prevPosition(int steps) const -> int; + QMediaPlaylistPrivate(); + + virtual ~QMediaPlaylistPrivate(); + + void loadFailed(QMediaPlaylist::Error error, const QString &errorString); + + void loadFinished(); + + bool checkFormat(const char *format) const; + + void ensureParser(); + + int nextPosition(int steps) const; + int prevPosition(int steps) const; QList playlist; diff --git a/examples/common/qplaylistfileparser.cpp b/examples/common/qplaylistfileparser.cpp index 1b2761f..27982bd 100644 --- a/examples/common/qplaylistfileparser.cpp +++ b/examples/common/qplaylistfileparser.cpp @@ -1,14 +1,16 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -#include "qplaylistfileparser_p.h" -#include -#include -#include -#include -#include -#include -#include +#include "qmediametadata.h" +#include "qmediaplayer.h" +#include "qplaylistfileparser.h" + +#include +#include +#include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -17,14 +19,12 @@ namespace { class ParserBase { public: - explicit ParserBase(QPlaylistFileParser *parent) - : m_parent(parent) - , m_aborted(false) + explicit ParserBase(QPlaylistFileParser *parent) : m_parent(parent), m_aborted(false) { Q_ASSERT(m_parent); } - bool parseLine(int lineIndex, const QString& line, const QUrl& root) + bool parseLine(int lineIndex, const QString &line, const QUrl &root) { if (m_aborted) return false; @@ -37,7 +37,7 @@ class ParserBase virtual ~ParserBase() = default; protected: - virtual bool parseLineImpl(int lineIndex, const QString& line, const QUrl& root) = 0; + virtual bool parseLineImpl(int lineIndex, const QString &line, const QUrl &root) = 0; static QUrl expandToFullPath(const QUrl &root, const QString &line) { @@ -51,7 +51,8 @@ class ParserBase if (url.scheme().isEmpty()) { // Resolve it relative to root if (root.isLocalFile()) - return QUrl::fromUserInput(line, root.adjusted(QUrl::RemoveFilename).toLocalFile(), QUrl::AssumeLocalFile); + return QUrl::fromUserInput(line, root.adjusted(QUrl::RemoveFilename).toLocalFile(), + QUrl::AssumeLocalFile); return root.resolved(url); } if (url.scheme().length() == 1) @@ -61,8 +62,7 @@ class ParserBase return url; } - void newItemFound(const QVariant& content) { Q_EMIT m_parent->newItem(content); } - + void newItemFound(const QVariant &content) { Q_EMIT m_parent->newItem(content); } QPlaylistFileParser *m_parent; bool m_aborted; @@ -71,11 +71,7 @@ class ParserBase class M3UParser : public ParserBase { public: - explicit M3UParser(QPlaylistFileParser *q) - : ParserBase(q) - , m_extendedFormat(false) - { - } + explicit M3UParser(QPlaylistFileParser *q) : ParserBase(q), m_extendedFormat(false) { } /* * @@ -94,31 +90,41 @@ class M3UParser : public ParserBase C:\Documents and Settings\I\My Music\Greatest Hits\Example.ogg */ - bool parseLineImpl(int lineIndex, const QString& line, const QUrl& root) override + bool parseLineImpl(int lineIndex, const QString &line, const QUrl &root) override { - if (line[0] == u'#' ) { + if (line[0] == u'#') { if (m_extendedFormat) { if (line.startsWith(QLatin1String("#EXTINF:"))) { m_extraInfo.clear(); int artistStart = line.indexOf(QLatin1String(","), 8); bool ok = false; - QStringView lineView { line }; - int length = lineView.mid(8, artistStart < 8 ? -1 : artistStart - 8).trimmed().toInt(&ok); + QStringView lineView{ line }; + int length = lineView.mid(8, artistStart < 8 ? -1 : artistStart - 8) + .trimmed() + .toInt(&ok); if (ok && length > 0) { - //convert from second to milisecond + // convert from second to milisecond m_extraInfo[QMediaMetaData::Duration] = QVariant(length * 1000); } if (artistStart > 0) { int titleStart = getSplitIndex(line, artistStart); if (titleStart > artistStart) { - m_extraInfo[QMediaMetaData::Author] = lineView.mid(artistStart + 1, - titleStart - artistStart - 1).trimmed().toString(). - replace(QLatin1String("--"), QLatin1String("-")); - m_extraInfo[QMediaMetaData::Title] = lineView.mid(titleStart + 1).trimmed().toString(). - replace(QLatin1String("--"), QLatin1String("-")); + m_extraInfo[QMediaMetaData::Author] = + lineView.mid(artistStart + 1, titleStart - artistStart - 1) + .trimmed() + .toString() + .replace(QLatin1String("--"), QLatin1String("-")); + m_extraInfo[QMediaMetaData::Title] = + lineView.mid(titleStart + 1) + .trimmed() + .toString() + .replace(QLatin1String("--"), QLatin1String("-")); } else { - m_extraInfo[QMediaMetaData::Title] = lineView.mid(artistStart + 1).trimmed().toString(). - replace(QLatin1String("--"), QLatin1String("-")); + m_extraInfo[QMediaMetaData::Title] = + lineView.mid(artistStart + 1) + .trimmed() + .toString() + .replace(QLatin1String("--"), QLatin1String("-")); } } } @@ -136,11 +142,11 @@ class M3UParser : public ParserBase return true; } - int getSplitIndex(const QString& line, int startPos) + int getSplitIndex(const QString &line, int startPos) { if (startPos < 0) startPos = 0; - const QChar* buf = line.data(); + const QChar *buf = line.data(); for (int i = startPos; i < line.length(); ++i) { if (buf[i] == u'-') { if (i == line.length() - 1) @@ -154,56 +160,53 @@ class M3UParser : public ParserBase } private: - QMediaMetaData m_extraInfo; - bool m_extendedFormat; + QMediaMetaData m_extraInfo; + bool m_extendedFormat; }; class PLSParser : public ParserBase { public: - explicit PLSParser(QPlaylistFileParser *q) - : ParserBase(q) - { - } + explicit PLSParser(QPlaylistFileParser *q) : ParserBase(q) { } -/* - * -The format is essentially that of an INI file structured as follows: + /* + * + The format is essentially that of an INI file structured as follows: -Header + Header - * [playlist] : This tag indicates that it is a Playlist File + * [playlist] : This tag indicates that it is a Playlist File -Track Entry -Assuming track entry #X + Track Entry + Assuming track entry #X - * FileX : Variable defining location of stream. - * TitleX : Defines track title. - * LengthX : Length in seconds of track. Value of -1 indicates indefinite. + * FileX : Variable defining location of stream. + * TitleX : Defines track title. + * LengthX : Length in seconds of track. Value of -1 indicates indefinite. -Footer + Footer - * NumberOfEntries : This variable indicates the number of tracks. - * Version : Playlist version. Currently only a value of 2 is valid. + * NumberOfEntries : This variable indicates the number of tracks. + * Version : Playlist version. Currently only a value of 2 is valid. -[playlist] + [playlist] -File1=Alternative\everclear - SMFTA.mp3 + File1=Alternative\everclear - SMFTA.mp3 -Title1=Everclear - So Much For The Afterglow + Title1=Everclear - So Much For The Afterglow -Length1=233 + Length1=233 -File2=http://www.site.com:8000/listen.pls + File2=http://www.site.com:8000/listen.pls -Title2=My Cool Stream + Title2=My Cool Stream -Length5=-1 + Length5=-1 -NumberOfEntries=2 + NumberOfEntries=2 -Version=2 -*/ + Version=2 + */ bool parseLineImpl(int, const QString &line, const QUrl &root) override { // We ignore everything but 'File' entries, since that's the only thing we care about. @@ -221,7 +224,8 @@ Version=2 return true; } - QString getValue(QStringView line) { + QString getValue(QStringView line) + { int start = line.indexOf(u'='); if (start < 0) return QString(); @@ -237,13 +241,13 @@ class QPlaylistFileParserPrivate Q_DECLARE_PUBLIC(QPlaylistFileParser) public: QPlaylistFileParserPrivate(QPlaylistFileParser *q) - : q_ptr(q) - , m_stream(nullptr) - , m_type(QPlaylistFileParser::UNKNOWN) - , m_scanIndex(0) - , m_lineIndex(-1) - , m_utf8(false) - , m_aborted(false) + : q_ptr(q), + m_stream(nullptr), + m_type(QPlaylistFileParser::UNKNOWN), + m_scanIndex(0), + m_lineIndex(-1), + m_utf8(false), + m_aborted(false) { } @@ -254,8 +258,8 @@ class QPlaylistFileParserPrivate QScopedPointer m_source; QScopedPointer m_currentParser; - QByteArray m_buffer; - QUrl m_root; + QByteArray m_buffer; + QUrl m_root; QNetworkAccessManager m_mgr; QString m_mimeType; QPlaylistFileParser *q_ptr; @@ -267,7 +271,12 @@ class QPlaylistFileParserPrivate QUrl m_media; QString m_mimeType; [[nodiscard]] bool isValid() const { return m_stream || !m_media.isEmpty(); } - void reset() { m_stream = nullptr; m_media = QUrl(); m_mimeType = QString(); } + void reset() + { + m_stream = nullptr; + m_media = QUrl(); + m_mimeType = QString(); + } } m_pendingJob; int m_scanIndex; int m_lineIndex; @@ -278,8 +287,8 @@ class QPlaylistFileParserPrivate bool processLine(int startIndex, int length); }; -#define LINE_LIMIT 4096 -#define READ_LIMIT 64 +#define LINE_LIMIT 4096 +#define READ_LIMIT 64 bool QPlaylistFileParserPrivate::processLine(int startIndex, int length) { @@ -292,7 +301,9 @@ bool QPlaylistFileParserPrivate::processLine(int startIndex, int length) QString mimeType; if (m_source) mimeType = m_source->header(QNetworkRequest::ContentTypeHeader).toString(); - m_type = QPlaylistFileParser::findPlaylistType(suffix, !mimeType.isEmpty() ? mimeType : m_mimeType, m_buffer.constData(), quint32(m_buffer.size())); + m_type = QPlaylistFileParser::findPlaylistType( + suffix, !mimeType.isEmpty() ? mimeType : m_mimeType, m_buffer.constData(), + quint32(m_buffer.size())); switch (m_type) { case QPlaylistFileParser::UNKNOWN: @@ -332,9 +343,14 @@ bool QPlaylistFileParserPrivate::processLine(int startIndex, int length) void QPlaylistFileParserPrivate::handleData() { Q_Q(QPlaylistFileParser); + + if (!m_stream) + return; + while (m_stream->bytesAvailable() && !m_aborted) { - int expectedBytes = qMin(READ_LIMIT, int(qMin(m_stream->bytesAvailable(), - qint64(LINE_LIMIT - m_buffer.size())))); + int expectedBytes = + qMin(READ_LIMIT, + int(qMin(m_stream->bytesAvailable(), qint64(LINE_LIMIT - m_buffer.size())))); m_buffer.push_back(m_stream->read(expectedBytes)); int processedBytes = 0; while (m_scanIndex < m_buffer.length() && !m_aborted) { @@ -346,10 +362,6 @@ void QPlaylistFileParserPrivate::handleData() break; } processedBytes = m_scanIndex + 1; - if (!m_stream) { - //some error happened, so exit parsing - return; - } } m_scanIndex++; } @@ -358,13 +370,14 @@ void QPlaylistFileParserPrivate::handleData() break; if (m_buffer.length() - processedBytes >= LINE_LIMIT) { - emit q->error(QMediaPlaylist::FormatError, QMediaPlaylist::tr("invalid line in playlist file")); + emit q->error(QMediaPlaylist::FormatError, + QMediaPlaylist::tr("invalid line in playlist file")); q->abort(); break; } if (!m_stream->bytesAvailable() && (!m_source || !m_source->isFinished())) { - //last line + // last line processLine(processedBytes, -1); break; } @@ -387,20 +400,20 @@ void QPlaylistFileParserPrivate::handleData() } QPlaylistFileParser::QPlaylistFileParser(QObject *parent) - : QObject(parent) - , d_ptr(new QPlaylistFileParserPrivate(this)) + : QObject(parent), d_ptr(new QPlaylistFileParserPrivate(this)) { - } QPlaylistFileParser::~QPlaylistFileParser() = default; QPlaylistFileParser::FileType QPlaylistFileParser::findByMimeType(const QString &mime) { - if (mime == QLatin1String("text/uri-list") || mime == QLatin1String("audio/x-mpegurl") || mime == QLatin1String("audio/mpegurl")) + if (mime == QLatin1String("text/uri-list") || mime == QLatin1String("audio/x-mpegurl") + || mime == QLatin1String("audio/mpegurl")) return QPlaylistFileParser::M3U; - if (mime == QLatin1String("application/x-mpegURL") || mime == QLatin1String("application/vnd.apple.mpegurl")) + if (mime == QLatin1String("application/x-mpegURL") + || mime == QLatin1String("application/vnd.apple.mpegurl")) return QPlaylistFileParser::M3U8; if (mime == QLatin1String("audio/x-scpls")) @@ -439,10 +452,9 @@ QPlaylistFileParser::FileType QPlaylistFileParser::findByDataHeader(const char * return QPlaylistFileParser::UNKNOWN; } -QPlaylistFileParser::FileType QPlaylistFileParser::findPlaylistType(const QString& suffix, - const QString& mime, - const char *data, - quint32 size) +QPlaylistFileParser::FileType QPlaylistFileParser::findPlaylistType(const QString &suffix, + const QString &mime, + const char *data, quint32 size) { FileType dataHeaderType = findByDataHeader(data, size); @@ -499,13 +511,14 @@ void QPlaylistFileParser::start(QIODevice *stream, const QString &mimeType) d->handleData(); } -void QPlaylistFileParser::start(const QUrl& request, const QString &mimeType) +void QPlaylistFileParser::start(const QUrl &request, const QString &mimeType) { Q_D(QPlaylistFileParser); const QUrl &url = request.url(); if (url.isLocalFile() && !QFile::exists(url.toLocalFile())) { - emit error(QMediaPlaylist::AccessDeniedError, QString(QMediaPlaylist::tr("%1 does not exist")).arg(url.toString())); + emit error(QMediaPlaylist::AccessDeniedError, + QString(QMediaPlaylist::tr("%1 does not exist")).arg(url.toString())); return; } @@ -522,7 +535,8 @@ void QPlaylistFileParser::start(const QUrl& request, const QString &mimeType) d->m_stream = d->m_source.get(); connect(d->m_source.data(), SIGNAL(readyRead()), this, SLOT(handleData())); connect(d->m_source.data(), SIGNAL(finished()), this, SLOT(handleData())); - connect(d->m_source.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(handleError())); + connect(d->m_source.data(), SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, + SLOT(handleError())); if (url.isLocalFile()) d->handleData(); @@ -553,7 +567,8 @@ void QPlaylistFileParserPrivate::handleParserFinished() Q_Q(QPlaylistFileParser); const bool isParserValid = !m_currentParser.isNull(); if (!isParserValid && !m_aborted) - emit q->error(QMediaPlaylist::FormatNotSupportedError, QMediaPlaylist::tr("Empty file provided")); + emit q->error(QMediaPlaylist::FormatNotSupportedError, + QMediaPlaylist::tr("Empty file provided")); if (isParserValid && !m_aborted) { m_currentParser.reset(); @@ -602,3 +617,5 @@ void QPlaylistFileParser::handleError() } QT_END_NAMESPACE + +#include "moc_qplaylistfileparser.cpp" diff --git a/examples/common/qplaylistfileparser_p.h b/examples/common/qplaylistfileparser.h similarity index 62% rename from examples/common/qplaylistfileparser_p.h rename to examples/common/qplaylistfileparser.h index f1d7fd6..0d83289 100644 --- a/examples/common/qplaylistfileparser_p.h +++ b/examples/common/qplaylistfileparser.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #ifndef PLAYLISTFILEPARSER_P_H #define PLAYLISTFILEPARSER_P_H @@ -16,7 +16,9 @@ // #include "qmediaplaylist.h" -#include +#include "qtmultimediaglobal.h" + +#include QT_BEGIN_NAMESPACE @@ -30,8 +32,8 @@ class QPlaylistFileParser : public QObject { Q_OBJECT public: - explicit QPlaylistFileParser(QObject *parent = nullptr); - ~QPlaylistFileParser() override; + QPlaylistFileParser(QObject *parent = nullptr); + ~QPlaylistFileParser(); enum FileType { UNKNOWN, @@ -47,24 +49,22 @@ class QPlaylistFileParser : public QObject QList playlist; -Q_SIGNALS: +signals: void newItem(const QVariant &content); void finished(); void error(QMediaPlaylist::Error err, const QString &errorMsg); -private Q_SLOTS: +private slots: void handleData(); void handleError(); private: - static auto findByMimeType(const QString &mime) -> FileType; - static auto findBySuffixType(const QString &suffix) -> FileType; - static auto findByDataHeader(const char *data, quint32 size) -> FileType; - static auto findPlaylistType(QIODevice *device, const QString &mime) -> FileType; - static auto findPlaylistType(const QString &suffix, - const QString &mime, - const char *data = nullptr, - quint32 size = 0) -> FileType; + static FileType findByMimeType(const QString &mime); + static FileType findBySuffixType(const QString &suffix); + static FileType findByDataHeader(const char *data, quint32 size); + static FileType findPlaylistType(QIODevice *device, const QString &mime); + static FileType findPlaylistType(const QString &suffix, const QString &mime, + const char *data = nullptr, quint32 size = 0); Q_DISABLE_COPY(QPlaylistFileParser) Q_DECLARE_PRIVATE(QPlaylistFileParser) diff --git a/examples/ffmpegplayer/CMakeLists.txt b/examples/ffmpegplayer/CMakeLists.txt index 6f545d6..8745840 100644 --- a/examples/ffmpegplayer/CMakeLists.txt +++ b/examples/ffmpegplayer/CMakeLists.txt @@ -9,11 +9,12 @@ set(PROJECT_SOURCES ../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_p.h ../common/qplaylistfileparser.cpp + ../common/qplaylistfileparser.h ../common/slider.cpp ../common/slider.h ../common/titlewidget.cc diff --git a/examples/ffmpegplayer/ffmpegplayer.pro b/examples/ffmpegplayer/ffmpegplayer.pro index 1819d2d..0278c70 100644 --- a/examples/ffmpegplayer/ffmpegplayer.pro +++ b/examples/ffmpegplayer/ffmpegplayer.pro @@ -21,6 +21,7 @@ SOURCES += \ ../common/openwebmediadialog.cc \ ../common/playlistmodel.cpp \ ../common/playlistview.cc \ + ../common/qmediaplaylist_p.cpp \ ../common/qmediaplaylist.cpp \ ../common/qplaylistfileparser.cpp \ ../common/slider.cpp \ @@ -36,7 +37,7 @@ HEADERS += \ ../common/playlistview.hpp \ ../common/qmediaplaylist.h \ ../common/qmediaplaylist_p.h \ - ../common/qplaylistfileparser_p.h \ + ../common/qplaylistfileparser.h \ ../common/slider.h \ ../common/titlewidget.hpp \ mainwindow.h diff --git a/examples/mpvplayer/CMakeLists.txt b/examples/mpvplayer/CMakeLists.txt index dc06c76..b17f5af 100644 --- a/examples/mpvplayer/CMakeLists.txt +++ b/examples/mpvplayer/CMakeLists.txt @@ -9,11 +9,12 @@ set(PROJECT_SOURCES ../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_p.h ../common/qplaylistfileparser.cpp + ../common/qplaylistfileparser.h ../common/slider.cpp ../common/slider.h ../common/titlewidget.cc diff --git a/examples/mpvplayer/mpvplayer.pro b/examples/mpvplayer/mpvplayer.pro index 6e5760a..25545a1 100644 --- a/examples/mpvplayer/mpvplayer.pro +++ b/examples/mpvplayer/mpvplayer.pro @@ -24,6 +24,7 @@ SOURCES += \ ../common/openwebmediadialog.cc \ ../common/playlistmodel.cpp \ ../common/playlistview.cc \ + ../common/qmediaplaylist_p.cpp \ ../common/qmediaplaylist.cpp \ ../common/qplaylistfileparser.cpp \ ../common/slider.cpp \ @@ -41,7 +42,7 @@ HEADERS += \ ../common/playlistview.hpp \ ../common/qmediaplaylist.h \ ../common/qmediaplaylist_p.h \ - ../common/qplaylistfileparser_p.h \ + ../common/qplaylistfileparser.h \ ../common/slider.h \ ../common/titlewidget.hpp \ mainwindow.hpp \ diff --git a/src/3rdparty/3rdparty.pri b/src/3rdparty/3rdparty.pri index b0fcc8f..b9d5e03 100644 --- a/src/3rdparty/3rdparty.pri +++ b/src/3rdparty/3rdparty.pri @@ -35,7 +35,7 @@ CONFIG(debug, debug|release) { -llibbreakpad_client -llibbreakpad } -LIBS += -lcommon -lclient -lutil -lbase +LIBS += -lvcpkg_crashpad_client_common -lvcpkg_crashpad_client -lvcpkg_crashpad_util -lvcpkg_crashpad_base LIBS += -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil \ -lass -lharfbuzz -lfribidi diff --git a/src/ffmpeg/averror.cpp b/src/ffmpeg/averror.cpp index 7c34f7a..7fc03d8 100644 --- a/src/ffmpeg/averror.cpp +++ b/src/ffmpeg/averror.cpp @@ -69,9 +69,9 @@ auto AVError::setErrorCode(int error) -> AVError & { d_ptr->error = error; if (error < 0) { - char errbuf[AV_ERROR_MAX_STRING_SIZE] = {0}; - av_strerror(error, errbuf, sizeof(errbuf)); - d_ptr->errorString = QString::fromUtf8(errbuf); + char buffer[AV_ERROR_MAX_STRING_SIZE + 1] = {}; + av_make_error_string(buffer, AV_ERROR_MAX_STRING_SIZE, error); + d_ptr->errorString = QString::fromLocal8Bit(buffer); } else { d_ptr->errorString.clear(); } diff --git a/src/ffmpeg/videorender/shader/video_vulkan.frag b/src/ffmpeg/videorender/shader/video_vulkan.frag deleted file mode 100644 index 63ad072..0000000 --- a/src/ffmpeg/videorender/shader/video_vulkan.frag +++ /dev/null @@ -1,95 +0,0 @@ -#version 440 - -layout(location = 0) in vec2 TexCord; // 纹理坐标 -layout(location = 1) flat in int format; // 像素格式 -layout(location = 2) in vec3 offset; -layout(location = 3) in mat3 colorConversion; - -layout(binding = 1) uniform sampler2D tex_y; -layout(binding = 2) uniform sampler2D tex_u; -layout(binding = 3) uniform sampler2D tex_v; -layout(binding = 4) uniform sampler2D tex_uv; -layout(binding = 5) uniform sampler2D tex_rgba; - -layout(location = 0) out vec4 fragColor; - -void main() -{ - vec3 yuv; - vec3 rgb; - - if (format == 0 || format == 4 || format == 5 || format == 6 || format == 7) { // YUV420P - yuv.x = texture(tex_y, TexCord).r; - yuv.y = texture(tex_u, TexCord).r; - yuv.z = texture(tex_v, TexCord).r; - } else if (format == 1) { // YUYV422 - yuv.x = texture(tex_rgba, TexCord).r; - yuv.y = texture(tex_rgba, TexCord).g; - yuv.z = texture(tex_rgba, TexCord).a; - } else if (format == 2 || format == 17 || format == 20) { // RGB24 - fragColor = vec4(texture(tex_rgba, TexCord).rgb, 1); - return; - } else if (format == 3) { // BGR24 - fragColor = vec4(texture(tex_rgba, TexCord).bgr, 1); - return; - } else if (format == 15) { // UYVY422 - int width = textureSize(tex_rgba, 0).x * 2; - float tex_x = TexCord.x; - int pixel = int(floor(width * tex_x)) % 2; - vec4 tc = texture(tex_rgba, TexCord).rgba; - float cb = tc.r; - float y1 = tc.g; - float cr = tc.b; - float y2 = tc.a; - float y = (pixel == 1) ? y2 : y1; - yuv = vec3(y, cb, cr); - } else if (format == 23 || format == 161) { // NV12 - yuv.x = texture(tex_y, TexCord).r; - yuv.y = texture(tex_uv, TexCord).r; - yuv.z = texture(tex_uv, TexCord).a; - } else if (format == 24) { // NV21 - yuv.x = texture(tex_y, TexCord).r; - yuv.y = texture(tex_uv, TexCord).a; - yuv.z = texture(tex_uv, TexCord).r; - } else if (format == 25) { // ARGB - fragColor = texture(tex_rgba, TexCord).gbar; - return; - } else if (format == 26) { // RGBA - fragColor = texture(tex_rgba, TexCord); - return; - } else if (format == 27) { // ABGR - fragColor = texture(tex_rgba, TexCord).abgr; - return; - } else if (format == 28) { // BGRA - fragColor = texture(tex_rgba, TexCord).bgra; - return; - } else if (format == 64) { // YUV420P10LE - vec3 yuv_l; - vec3 yuv_h; - yuv_l.x = texture(tex_y, TexCord).r; - yuv_h.x = texture(tex_y, TexCord).a; - yuv_l.y = texture(tex_u, TexCord).r; - yuv_h.y = texture(tex_u, TexCord).a; - yuv_l.z = texture(tex_v, TexCord).r; - yuv_h.z = texture(tex_v, TexCord).a; - yuv = (yuv_l * 255.0 + yuv_h * 255.0 * 256.0) / (1023.0); - } else if (format == 120) { // 0RGB - fragColor = vec4(texture(tex_rgba, TexCord).gba, 1); - return; - } else if (format == 121) { // RGB0 - fragColor = vec4(texture(tex_rgba, TexCord).rgb, 1); - return; - } else if (format == 122) { // 0BGR - fragColor = vec4(texture(tex_rgba, TexCord).abg, 1); - return; - } else if (format == 123) { // BGR0 - fragColor = vec4(texture(tex_rgba, TexCord).bgr, 1); - return; - } else { - } - - yuv += offset; - rgb = yuv * colorConversion; - - fragColor = vec4(rgb, 1.0); -} diff --git a/src/ffmpeg/videorender/shader/video_vulkan.vert b/src/ffmpeg/videorender/shader/video_vulkan.vert deleted file mode 100644 index 25cfd4e..0000000 --- a/src/ffmpeg/videorender/shader/video_vulkan.vert +++ /dev/null @@ -1,11 +0,0 @@ -#version 440 -layout(location = 0) in vec3 aPos; -layout(location = 1) in vec2 aTexCord; - -layout(location = 0)out vec2 TexCord; // 纹理坐标 - -void main() -{ - gl_Position = vec4(aPos.x, -aPos.y, aPos.z, 1.0); // 图像坐标和OpenGL坐标Y轴相反, - TexCord = aTexCord; -} diff --git a/src/ffmpeg/videorender/shaders.qrc b/src/ffmpeg/videorender/shaders.qrc index df0048d..e2c590c 100644 --- a/src/ffmpeg/videorender/shaders.qrc +++ b/src/ffmpeg/videorender/shaders.qrc @@ -2,8 +2,6 @@ shader/video.frag shader/video.vert - shader/video_vulkan.frag - shader/video_vulkan.vert shader/sub.frag shader/video_nv12.frag shader/video_yuv420p.frag diff --git a/vcpkg.json b/vcpkg.json index 6569c78..8e0d70a 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -34,5 +34,5 @@ ] } ], - "builtin-baseline": "c4467cb686f92671f0172aa8299a77d908175b4e" + "builtin-baseline": "2ddc10c8afa00a762a69f21f6427849fe906ede0" }