refactor media player, separate into backend logic
This commit is contained in:
parent
d1ae926b5d
commit
2b2aaee70a
@ -24,6 +24,7 @@
|
||||
# NO_UPDATE_CHECK - Disable automatic checking for new application updates.
|
||||
# IS_FLATPAK_BUILD - Set to "ON" when building RSS Guard with Flatpak.
|
||||
# FORCE_BUNDLE_ICONS - Forcibly bundles icons into executables.
|
||||
# ENABLE_MEDIAPLAYER_QTMULTIMEDIA - Enable media player (QtMultimedia/ffmpeg implementation).
|
||||
# ENABLE_COMPRESSED_SITEMAP - Set to "ON" if you want to enable support for "sitemap.xml.gz" format.
|
||||
# This requires "zlib" library and if you want to use specific
|
||||
# zlib location, then use "ZLIB_ROOT" variable, for example
|
||||
@ -122,6 +123,7 @@ option(NO_UPDATE_CHECK "Disable automatic checking for new application updates"
|
||||
option(IS_FLATPAK_BUILD "Set to 'ON' when building RSS Guard with Flatpak." OFF)
|
||||
option(FORCE_BUNDLE_ICONS "Forcibly bundle icon themes into RSS Guard." OFF)
|
||||
option(ENABLE_COMPRESSED_SITEMAP "Enable support for gzip-compressed sitemap feeds. Requires zlib." OFF)
|
||||
option(ENABLE_MEDIAPLAYER_QTMULTIMEDIA "Enable built-in media player. Requires QtMultimedia FFMPEG plugin." ON)
|
||||
|
||||
# Import Qt libraries.
|
||||
set(QT6_MIN_VERSION 6.3.0)
|
||||
@ -139,14 +141,20 @@ set(QT_COMPONENTS
|
||||
Concurrent
|
||||
)
|
||||
|
||||
if(NOT OS2)
|
||||
list(APPEND QT_COMPONENTS Multimedia MultimediaWidgets)
|
||||
endif()
|
||||
|
||||
if(WIN32 AND NOT BUILD_WITH_QT6)
|
||||
list(APPEND QT_COMPONENTS WinExtras)
|
||||
endif()
|
||||
|
||||
if(ENABLE_MEDIAPLAYER_QTMULTIMEDIA)
|
||||
list(APPEND QT_COMPONENTS Multimedia MultimediaWidgets)
|
||||
add_compile_definitions(ENABLE_MEDIAPLAYER_QTMULTIMEDIA)
|
||||
endif()
|
||||
|
||||
if(ENABLE_MEDIAPLAYER_QTMULTIMEDIA OR ENABLE_MEDIAPLAYER_LIBMVP)
|
||||
set(ENABLE_MEDIAPLAYER TRUE)
|
||||
add_compile_definitions(ENABLE_MEDIAPLAYER)
|
||||
endif()
|
||||
|
||||
if(USE_WEBENGINE)
|
||||
list(APPEND QT_COMPONENTS WebEngineWidgets)
|
||||
add_compile_definitions(USE_WEBENGINE)
|
||||
|
@ -133,8 +133,6 @@ set(SOURCES
|
||||
gui/reusable/locationlineedit.h
|
||||
gui/reusable/messagecountspinbox.cpp
|
||||
gui/reusable/messagecountspinbox.h
|
||||
gui/reusable/mediaplayer.cpp
|
||||
gui/reusable/mediaplayer.h
|
||||
gui/reusable/networkproxydetails.cpp
|
||||
gui/reusable/networkproxydetails.h
|
||||
gui/reusable/nonclosablemenu.cpp
|
||||
@ -467,7 +465,6 @@ set(UI_FILES
|
||||
gui/notifications/notificationseditor.ui
|
||||
gui/notifications/singlenotificationeditor.ui
|
||||
gui/notifications/toastnotification.ui
|
||||
gui/reusable/mediaplayer.ui
|
||||
gui/reusable/networkproxydetails.ui
|
||||
gui/reusable/searchtextwidget.ui
|
||||
gui/richtexteditor/mrichtextedit.ui
|
||||
@ -509,6 +506,27 @@ set(UI_FILES
|
||||
services/tt-rss/gui/ttrssfeeddetails.ui
|
||||
)
|
||||
|
||||
if(ENABLE_MEDIAPLAYER)
|
||||
list(APPEND SOURCES
|
||||
gui/mediaplayer/playerbackend.cpp
|
||||
gui/mediaplayer/playerbackend.h
|
||||
gui/mediaplayer/mediaplayer.cpp
|
||||
gui/mediaplayer/mediaplayer.h
|
||||
)
|
||||
|
||||
list(APPEND UI_FILES
|
||||
gui/mediaplayer/mediaplayer.ui
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_MEDIAPLAYER_QTMULTIMEDIA)
|
||||
list(APPEND SOURCES
|
||||
gui/mediaplayer/qtmultimedia/qtmultimediabackend.cpp
|
||||
gui/mediaplayer/qtmultimedia/qtmultimediabackend.h
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
if(USE_WEBENGINE)
|
||||
list(APPEND SOURCES
|
||||
# WebEngine-based web (and message) browser.
|
||||
@ -770,7 +788,7 @@ if(WIN32 AND NOT BUILD_WITH_QT6)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT OS2)
|
||||
if(ENABLE_MEDIAPLAYER_QTMULTIMEDIA)
|
||||
target_link_libraries(rssguard PUBLIC
|
||||
Qt${QT_VERSION_MAJOR}::Multimedia
|
||||
Qt${QT_VERSION_MAJOR}::MultimediaWidgets
|
||||
|
@ -1678,7 +1678,10 @@ UpdatedArticles DatabaseQueries::updateMessages(const QSqlDatabase& db,
|
||||
|
||||
QMutexLocker lck(db_mutex);
|
||||
|
||||
auto bulk_query = db.exec(final_bulk);
|
||||
auto bulk_query = QSqlQuery(final_bulk, db);
|
||||
|
||||
bulk_query.exec();
|
||||
|
||||
auto bulk_error = bulk_query.lastError();
|
||||
|
||||
if (bulk_error.isValid()) {
|
||||
|
172
src/librssguard/gui/mediaplayer/mediaplayer.cpp
Normal file
172
src/librssguard/gui/mediaplayer/mediaplayer.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "gui/mediaplayer/mediaplayer.h"
|
||||
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
|
||||
#include "gui/mediaplayer/qtmultimedia/qtmultimediabackend.h"
|
||||
|
||||
MediaPlayer::MediaPlayer(QWidget* parent)
|
||||
: TabContent(parent), m_backend(new QtMultimediaBackend(this)), m_muted(false) {
|
||||
m_ui.setupUi(this);
|
||||
|
||||
m_ui.m_layoutMain->insertWidget(0, m_backend, 1);
|
||||
|
||||
setupIcons();
|
||||
|
||||
createBackendConnections();
|
||||
createConnections();
|
||||
}
|
||||
|
||||
MediaPlayer::~MediaPlayer() {}
|
||||
|
||||
WebBrowser* MediaPlayer::webBrowser() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MediaPlayer::playUrl(const QString& url) {
|
||||
if (m_muted) {
|
||||
muteUnmute();
|
||||
}
|
||||
else {
|
||||
setVolume(m_ui.m_slidVolume->value());
|
||||
}
|
||||
|
||||
m_backend->playUrl(url);
|
||||
}
|
||||
|
||||
void MediaPlayer::playPause() {
|
||||
m_backend->playPause();
|
||||
}
|
||||
|
||||
void MediaPlayer::stop() {
|
||||
m_backend->stop();
|
||||
}
|
||||
|
||||
void MediaPlayer::download() {
|
||||
emit urlDownloadRequested(m_backend->url());
|
||||
}
|
||||
|
||||
void MediaPlayer::muteUnmute() {
|
||||
m_ui.m_slidVolume->setEnabled(m_muted);
|
||||
setVolume(m_muted ? m_ui.m_slidVolume->value() : 0);
|
||||
|
||||
m_muted = !m_muted;
|
||||
}
|
||||
|
||||
void MediaPlayer::setSpeed(int speed) {
|
||||
m_backend->setPlaybackSpeed(speed);
|
||||
}
|
||||
|
||||
void MediaPlayer::setVolume(int volume) {
|
||||
m_backend->setVolume(volume);
|
||||
|
||||
m_ui.m_btnVolume->setIcon(volume <= 0 ? m_iconMute : m_iconUnmute);
|
||||
}
|
||||
|
||||
void MediaPlayer::seek(int position) {
|
||||
m_backend->setPosition(position);
|
||||
}
|
||||
|
||||
void MediaPlayer::onPositionChanged(int position) {
|
||||
m_ui.m_slidProgress->blockSignals(true);
|
||||
m_ui.m_slidProgress->setValue(position);
|
||||
m_ui.m_slidProgress->blockSignals(false);
|
||||
|
||||
updateTimeAndProgress(position, m_backend->duration());
|
||||
}
|
||||
|
||||
void MediaPlayer::onSpeedChanged(int speed) {
|
||||
m_ui.m_spinSpeed->blockSignals(true);
|
||||
m_ui.m_spinSpeed->setValue(speed);
|
||||
m_ui.m_spinSpeed->blockSignals(false);
|
||||
}
|
||||
|
||||
void MediaPlayer::onDurationChanged(int duration) {
|
||||
m_ui.m_slidProgress->blockSignals(true);
|
||||
m_ui.m_slidProgress->setMaximum(duration);
|
||||
m_ui.m_slidProgress->blockSignals(false);
|
||||
|
||||
updateTimeAndProgress(m_backend->position(), duration);
|
||||
}
|
||||
|
||||
void MediaPlayer::updateTimeAndProgress(int progress, int total) {
|
||||
m_ui.m_lblTime->setText(QSL("%1/%2").arg(QDateTime::fromSecsSinceEpoch(progress).toUTC().toString("hh:mm:ss"),
|
||||
QDateTime::fromSecsSinceEpoch(total).toUTC().toString("hh:mm:ss")));
|
||||
}
|
||||
|
||||
void MediaPlayer::onErrorOccurred(const QString& error_string) {
|
||||
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Error, error_string, error_string);
|
||||
}
|
||||
|
||||
void MediaPlayer::onAudioAvailable(bool available) {
|
||||
m_ui.m_slidVolume->setEnabled(available);
|
||||
m_ui.m_btnVolume->setEnabled(available);
|
||||
}
|
||||
|
||||
void MediaPlayer::onVideoAvailable(bool available) {
|
||||
Q_UNUSED(available)
|
||||
}
|
||||
|
||||
void MediaPlayer::onStatusChanged(const QString& status) {
|
||||
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Information, status, status);
|
||||
}
|
||||
|
||||
void MediaPlayer::onPlaybackStateChanged(PlayerBackend::PlaybackState state) {
|
||||
switch (state) {
|
||||
case PlayerBackend::PlaybackState::StoppedState:
|
||||
m_ui.m_btnPlayPause->setIcon(m_iconPlay);
|
||||
m_ui.m_btnStop->setEnabled(false);
|
||||
break;
|
||||
|
||||
case PlayerBackend::PlaybackState::PlayingState:
|
||||
m_ui.m_btnPlayPause->setIcon(m_iconPause);
|
||||
m_ui.m_btnStop->setEnabled(true);
|
||||
break;
|
||||
|
||||
case PlayerBackend::PlaybackState::PausedState:
|
||||
m_ui.m_btnPlayPause->setIcon(m_iconPlay);
|
||||
m_ui.m_btnStop->setEnabled(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayer::onSeekableChanged(bool seekable) {
|
||||
m_ui.m_slidProgress->setEnabled(seekable);
|
||||
|
||||
if (!seekable) {
|
||||
onPositionChanged(0);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayer::setupIcons() {
|
||||
m_iconPlay = qApp->icons()->fromTheme(QSL("media-playback-start"), QSL("player_play"));
|
||||
m_iconPause = qApp->icons()->fromTheme(QSL("media-playback-pause"), QSL("player_pause"));
|
||||
m_iconMute = qApp->icons()->fromTheme(QSL("player-volume-muted"), QSL("audio-volume-muted"));
|
||||
m_iconUnmute = qApp->icons()->fromTheme(QSL("player-volume"), QSL("stock_volume"));
|
||||
|
||||
m_ui.m_btnDownload->setIcon(qApp->icons()->fromTheme(QSL("download"), QSL("browser-download")));
|
||||
m_ui.m_btnStop->setIcon(qApp->icons()->fromTheme(QSL("media-playback-stop"), QSL("player_stop")));
|
||||
}
|
||||
|
||||
void MediaPlayer::createBackendConnections() {
|
||||
connect(m_backend, &PlayerBackend::speedChanged, this, &MediaPlayer::onSpeedChanged);
|
||||
connect(m_backend, &PlayerBackend::durationChanged, this, &MediaPlayer::onDurationChanged);
|
||||
connect(m_backend, &PlayerBackend::positionChanged, this, &MediaPlayer::onPositionChanged);
|
||||
connect(m_backend, &PlayerBackend::errorOccurred, this, &MediaPlayer::onErrorOccurred);
|
||||
connect(m_backend, &PlayerBackend::playbackStateChanged, this, &MediaPlayer::onPlaybackStateChanged);
|
||||
connect(m_backend, &PlayerBackend::statusChanged, this, &MediaPlayer::onStatusChanged);
|
||||
connect(m_backend, &PlayerBackend::audioAvailable, this, &MediaPlayer::onAudioAvailable);
|
||||
connect(m_backend, &PlayerBackend::videoAvailable, this, &MediaPlayer::onVideoAvailable);
|
||||
connect(m_backend, &PlayerBackend::seekableChanged, this, &MediaPlayer::onSeekableChanged);
|
||||
}
|
||||
|
||||
void MediaPlayer::createConnections() {
|
||||
connect(m_ui.m_btnPlayPause, &PlainToolButton::clicked, this, &MediaPlayer::playPause);
|
||||
connect(m_ui.m_btnStop, &PlainToolButton::clicked, this, &MediaPlayer::stop);
|
||||
connect(m_ui.m_btnDownload, &PlainToolButton::clicked, this, &MediaPlayer::download);
|
||||
connect(m_ui.m_btnVolume, &PlainToolButton::clicked, this, &MediaPlayer::muteUnmute);
|
||||
connect(m_ui.m_slidVolume, &QSlider::valueChanged, this, &MediaPlayer::setVolume);
|
||||
connect(m_ui.m_slidProgress, &QSlider::valueChanged, this, &MediaPlayer::seek);
|
||||
connect(m_ui.m_spinSpeed, QOverload<int>::of(&QSpinBox::valueChanged), this, &MediaPlayer::setSpeed);
|
||||
}
|
71
src/librssguard/gui/mediaplayer/mediaplayer.h
Normal file
71
src/librssguard/gui/mediaplayer/mediaplayer.h
Normal file
@ -0,0 +1,71 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef MEDIAPLAYER_H
|
||||
#define MEDIAPLAYER_H
|
||||
|
||||
#include "gui/tabcontent.h"
|
||||
|
||||
#include "gui/mediaplayer/playerbackend.h"
|
||||
|
||||
#include "ui_mediaplayer.h"
|
||||
|
||||
class MediaPlayer : public TabContent {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MediaPlayer(QWidget* parent = nullptr);
|
||||
virtual ~MediaPlayer();
|
||||
|
||||
virtual WebBrowser* webBrowser() const;
|
||||
|
||||
public slots:
|
||||
void playUrl(const QString& url);
|
||||
|
||||
private slots:
|
||||
void playPause();
|
||||
void stop();
|
||||
void download();
|
||||
void muteUnmute();
|
||||
|
||||
// NOTE: 100 means standard speed, above that value means faster, below means slower.
|
||||
void setSpeed(int speed);
|
||||
|
||||
// NOTE: Volume is from 0 to 100 taken directly from slider or
|
||||
// elsewhere.
|
||||
void setVolume(int volume);
|
||||
|
||||
// NOTE: We seek by second.
|
||||
void seek(int position);
|
||||
|
||||
void onSpeedChanged(int speed);
|
||||
void onDurationChanged(int duration);
|
||||
void onPositionChanged(int position);
|
||||
void onErrorOccurred(const QString& error_string);
|
||||
void onStatusChanged(const QString& status);
|
||||
void onPlaybackStateChanged(PlayerBackend::PlaybackState state);
|
||||
void onAudioAvailable(bool available);
|
||||
void onVideoAvailable(bool available);
|
||||
void onSeekableChanged(bool seekable);
|
||||
|
||||
signals:
|
||||
void urlDownloadRequested(const QUrl& url);
|
||||
|
||||
private:
|
||||
void updateTimeAndProgress(int progress, int total);
|
||||
void setupIcons();
|
||||
|
||||
void createBackendConnections();
|
||||
void createConnections();
|
||||
|
||||
private:
|
||||
Ui::MediaPlayer m_ui;
|
||||
|
||||
PlayerBackend* m_backend;
|
||||
QIcon m_iconPlay;
|
||||
QIcon m_iconPause;
|
||||
QIcon m_iconMute;
|
||||
QIcon m_iconUnmute;
|
||||
bool m_muted;
|
||||
};
|
||||
|
||||
#endif // MEDIAPLAYER_H
|
@ -13,17 +13,7 @@
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QVideoWidget" name="m_video" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<layout class="QVBoxLayout" name="m_layoutMain">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
@ -132,12 +122,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QVideoWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qvideowidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PlainToolButton</class>
|
||||
<extends>QToolButton</extends>
|
10
src/librssguard/gui/mediaplayer/playerbackend.cpp
Normal file
10
src/librssguard/gui/mediaplayer/playerbackend.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "gui/mediaplayer/playerbackend.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
|
||||
PlayerBackend::PlayerBackend(QWidget* parent) : QWidget(parent), m_mainLayout(new QVBoxLayout(this)) {
|
||||
m_mainLayout->setSpacing(0);
|
||||
m_mainLayout->setContentsMargins({0, 0, 0, 0});
|
||||
}
|
53
src/librssguard/gui/mediaplayer/playerbackend.h
Normal file
53
src/librssguard/gui/mediaplayer/playerbackend.h
Normal file
@ -0,0 +1,53 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef PLAYERBACKEND_H
|
||||
#define PLAYERBACKEND_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QVBoxLayout;
|
||||
|
||||
class PlayerBackend : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class PlaybackState {
|
||||
StoppedState,
|
||||
PlayingState,
|
||||
PausedState
|
||||
};
|
||||
|
||||
explicit PlayerBackend(QWidget* parent = nullptr);
|
||||
|
||||
virtual QUrl url() const = 0;
|
||||
virtual int position() const = 0;
|
||||
virtual int duration() const = 0;
|
||||
|
||||
signals:
|
||||
void speedChanged(int speed);
|
||||
void durationChanged(int duration);
|
||||
void positionChanged(int position);
|
||||
void errorOccurred(const QString& error_string);
|
||||
void statusChanged(const QString& status);
|
||||
void playbackStateChanged(PlaybackState state);
|
||||
void audioAvailable(bool available);
|
||||
void videoAvailable(bool available);
|
||||
void seekableChanged(bool seekable);
|
||||
|
||||
public slots:
|
||||
virtual void playUrl(const QUrl& url) = 0;
|
||||
virtual void playPause() = 0;
|
||||
virtual void pause() = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
virtual void setPlaybackSpeed(int speed) = 0;
|
||||
virtual void setVolume(int volume) = 0;
|
||||
virtual void setPosition(int position) = 0;
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
QVBoxLayout* m_mainLayout;
|
||||
};
|
||||
|
||||
#endif // PLAYERBACKEND_H
|
@ -0,0 +1,248 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "gui/mediaplayer/qtmultimedia/qtmultimediabackend.h"
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
#include <QAudioOutput>
|
||||
#include <QWindow>
|
||||
#endif
|
||||
|
||||
#include <QLayout>
|
||||
#include <QVideoWidget>
|
||||
|
||||
QtMultimediaBackend::QtMultimediaBackend(QWidget* parent)
|
||||
: PlayerBackend(parent),
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_audio(new QAudioOutput(this)),
|
||||
#endif
|
||||
m_player(new QMediaPlayer(this)),
|
||||
|
||||
m_video(new QVideoWidget(this)) {
|
||||
layout()->addWidget(m_video);
|
||||
|
||||
m_player->setVideoOutput(m_video);
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_player->setAudioOutput(m_audio);
|
||||
#endif
|
||||
|
||||
connect(m_player, &QMediaPlayer::durationChanged, this, &QtMultimediaBackend::onDurationChanged);
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
connect(m_player, &QMediaPlayer::errorOccurred, this, &QtMultimediaBackend::onErrorOccurred);
|
||||
#else
|
||||
connect(m_player, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), this, [this](QMediaPlayer::Error error) {
|
||||
onErrorOccurred(error);
|
||||
});
|
||||
#endif
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
connect(m_player, &QMediaPlayer::hasAudioChanged, this, &QtMultimediaBackend::onAudioAvailable);
|
||||
connect(m_player, &QMediaPlayer::hasVideoChanged, this, &QtMultimediaBackend::onVideoAvailable);
|
||||
connect(m_player, &QMediaPlayer::playbackStateChanged, this, &QtMultimediaBackend::onPlaybackStateChanged);
|
||||
#else
|
||||
connect(m_player, &QMediaPlayer::audioAvailableChanged, this, &QtMultimediaBackend::onAudioAvailable);
|
||||
connect(m_player, &QMediaPlayer::videoAvailableChanged, this, &QtMultimediaBackend::onVideoAvailable);
|
||||
connect(m_player, &QMediaPlayer::stateChanged, this, &QtMultimediaBackend::onPlaybackStateChanged);
|
||||
#endif
|
||||
|
||||
connect(m_player, &QMediaPlayer::mediaStatusChanged, this, &QtMultimediaBackend::onMediaStatusChanged);
|
||||
connect(m_player, &QMediaPlayer::positionChanged, this, &QtMultimediaBackend::onPositionChanged);
|
||||
connect(m_player, &QMediaPlayer::seekableChanged, this, &QtMultimediaBackend::onSeekableChanged);
|
||||
connect(m_player, &QMediaPlayer::playbackRateChanged, this, &QtMultimediaBackend::onPlaybackRateChanged);
|
||||
}
|
||||
|
||||
int QtMultimediaBackend::convertToSliderProgress(qint64 player_progress) const {
|
||||
return player_progress / 1000;
|
||||
}
|
||||
|
||||
int QtMultimediaBackend::convertDuration(qint64 duration) const {
|
||||
return duration / 1000;
|
||||
}
|
||||
|
||||
qreal QtMultimediaBackend::convertSpeed(int speed) const {
|
||||
return speed / 100.0;
|
||||
}
|
||||
|
||||
int QtMultimediaBackend::convertSpinSpeed(qreal speed) const {
|
||||
return speed * 100;
|
||||
}
|
||||
|
||||
float QtMultimediaBackend::convertSliderVolume(int slider_volume) const {
|
||||
return slider_volume / 100.0f;
|
||||
}
|
||||
|
||||
qint64 QtMultimediaBackend::convertSliderProgress(int slider_progress) const {
|
||||
return qint64(slider_progress) * qint64(1000);
|
||||
}
|
||||
|
||||
QString QtMultimediaBackend::mediaStatusToString(QMediaPlayer::MediaStatus status) const {
|
||||
switch (status) {
|
||||
case QMediaPlayer::NoMedia:
|
||||
return tr("No media");
|
||||
|
||||
case QMediaPlayer::LoadingMedia:
|
||||
return tr("Loading...");
|
||||
|
||||
case QMediaPlayer::LoadedMedia:
|
||||
return tr("Media loaded");
|
||||
|
||||
case QMediaPlayer::StalledMedia:
|
||||
return tr("Media stalled");
|
||||
|
||||
case QMediaPlayer::BufferingMedia:
|
||||
return tr("Buffering...");
|
||||
|
||||
case QMediaPlayer::BufferedMedia:
|
||||
return tr("Loaded");
|
||||
|
||||
case QMediaPlayer::EndOfMedia:
|
||||
return tr("Ended");
|
||||
|
||||
case QMediaPlayer::InvalidMedia:
|
||||
return tr("Media is invalid");
|
||||
|
||||
default:
|
||||
return tr("Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
QString QtMultimediaBackend::errorToString(QMediaPlayer::Error error) const {
|
||||
switch (error) {
|
||||
case QMediaPlayer::ResourceError:
|
||||
return tr("Cannot load media (missing codecs)");
|
||||
|
||||
case QMediaPlayer::FormatError:
|
||||
return tr("Unrecognized format");
|
||||
|
||||
case QMediaPlayer::NetworkError:
|
||||
return tr("Network problem");
|
||||
|
||||
case QMediaPlayer::AccessDeniedError:
|
||||
return tr("Access denied");
|
||||
|
||||
#if QT_VERSION_MAJOR == 5
|
||||
case QMediaPlayer::ServiceMissingError:
|
||||
return tr("Service is missing");
|
||||
|
||||
case QMediaPlayer::MediaIsPlaylist:
|
||||
return tr("This is playlist");
|
||||
#endif
|
||||
|
||||
case QMediaPlayer::NoError:
|
||||
return tr("No errors");
|
||||
|
||||
default:
|
||||
return tr("Unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::playUrl(const QUrl& url) {
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_player->setSource(url);
|
||||
#else
|
||||
m_player->setMedia(QUrl(url));
|
||||
#endif
|
||||
|
||||
m_player->play();
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::playPause() {
|
||||
if (m_player->PLAYBACK_STATE_METHOD() != QMediaPlayer::PLAYBACK_STATE::PlayingState) {
|
||||
m_player->play();
|
||||
}
|
||||
else {
|
||||
m_player->pause();
|
||||
}
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::pause() {
|
||||
m_player->pause();
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::stop() {
|
||||
m_player->stop();
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::setPlaybackSpeed(int speed) {
|
||||
m_player->setPlaybackRate(convertSpeed(speed));
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::setVolume(int volume) {
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_player->audioOutput()->setVolume(convertSliderVolume(volume));
|
||||
#else
|
||||
m_player->setVolume(volume);
|
||||
#endif
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::setPosition(int position) {
|
||||
m_player->setPosition(convertSliderProgress(position));
|
||||
}
|
||||
|
||||
QUrl QtMultimediaBackend::url() const {
|
||||
return
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_player->source();
|
||||
#else
|
||||
m_player->media().request().url();
|
||||
#endif
|
||||
}
|
||||
|
||||
int QtMultimediaBackend::position() const {
|
||||
return convertToSliderProgress(m_player->position());
|
||||
}
|
||||
|
||||
int QtMultimediaBackend::duration() const {
|
||||
return convertDuration(m_player->duration());
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::onPositionChanged(qint64 position) {
|
||||
emit positionChanged(convertToSliderProgress(position));
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::onPlaybackRateChanged(qreal speed) {
|
||||
emit speedChanged(convertSpinSpeed(speed));
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::onDurationChanged(qint64 duration) {
|
||||
emit durationChanged(convertDuration(duration));
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::onErrorOccurred(QMediaPlayer::Error error, const QString& error_string) {
|
||||
QString err = error_string.isEmpty() ? errorToString(error) : error_string;
|
||||
emit errorOccurred(err);
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::onAudioAvailable(bool available) {
|
||||
emit audioAvailable(available);
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::onVideoAvailable(bool available) {
|
||||
emit videoAvailable(available);
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::onMediaStatusChanged(QMediaPlayer::MediaStatus status) {
|
||||
QString st = mediaStatusToString(status);
|
||||
emit statusChanged(st);
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::onPlaybackStateChanged(QMediaPlayer::PLAYBACK_STATE state) {
|
||||
switch (state) {
|
||||
case QMediaPlayer::PLAYBACK_STATE::StoppedState:
|
||||
emit playbackStateChanged(PlayerBackend::PlaybackState::StoppedState);
|
||||
break;
|
||||
|
||||
case QMediaPlayer::PLAYBACK_STATE::PlayingState:
|
||||
emit playbackStateChanged(PlayerBackend::PlaybackState::PlayingState);
|
||||
break;
|
||||
|
||||
case QMediaPlayer::PLAYBACK_STATE::PausedState:
|
||||
emit playbackStateChanged(PlayerBackend::PlaybackState::PausedState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QtMultimediaBackend::onSeekableChanged(bool seekable) {
|
||||
emit seekableChanged(seekable);
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef MEDIAPLAYER_H
|
||||
#define MEDIAPLAYER_H
|
||||
#ifndef QTMULTIMEDIABACKEND_H
|
||||
#define QTMULTIMEDIABACKEND_H
|
||||
|
||||
#include "gui/tabcontent.h"
|
||||
#include "gui/mediaplayer/playerbackend.h"
|
||||
|
||||
#include "ui_mediaplayer.h"
|
||||
#include <QObject>
|
||||
|
||||
#include <QMediaPlayer>
|
||||
|
||||
@ -17,35 +17,32 @@
|
||||
#define PLAYBACK_STATE_METHOD state
|
||||
#endif
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
class QAudioOutput;
|
||||
#endif
|
||||
|
||||
class MediaPlayer : public TabContent {
|
||||
class QVideoWidget;
|
||||
|
||||
class QtMultimediaBackend : public PlayerBackend {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MediaPlayer(QWidget* parent = nullptr);
|
||||
virtual ~MediaPlayer();
|
||||
explicit QtMultimediaBackend(QWidget* parent = nullptr);
|
||||
|
||||
virtual WebBrowser* webBrowser() const;
|
||||
virtual QUrl url() const;
|
||||
virtual int position() const;
|
||||
virtual int duration() const;
|
||||
|
||||
public slots:
|
||||
void playUrl(const QString& url);
|
||||
virtual void playUrl(const QUrl& url);
|
||||
virtual void playPause();
|
||||
virtual void pause();
|
||||
virtual void stop();
|
||||
virtual void setPlaybackSpeed(int speed);
|
||||
virtual void setVolume(int volume);
|
||||
virtual void setPosition(int position);
|
||||
|
||||
private slots:
|
||||
void playPause();
|
||||
void stop();
|
||||
void download();
|
||||
void muteUnmute();
|
||||
void setSpeed(int speed);
|
||||
|
||||
// NOTE: Volume is from 0 to 100 taken directly from slider or
|
||||
// elsewhere.
|
||||
void setVolume(int volume);
|
||||
|
||||
// NOTE: Media is seekable in miliseconds, but that is too muc
|
||||
// for "int" data type, therefore we seek by second.
|
||||
void seek(int position);
|
||||
|
||||
void onPlaybackRateChanged(qreal speed);
|
||||
void onDurationChanged(qint64 duration);
|
||||
void onErrorOccurred(QMediaPlayer::Error error, const QString& error_string = {});
|
||||
@ -56,9 +53,6 @@ class MediaPlayer : public TabContent {
|
||||
void onPositionChanged(qint64 position);
|
||||
void onSeekableChanged(bool seekable);
|
||||
|
||||
signals:
|
||||
void urlDownloadRequested(const QUrl& url);
|
||||
|
||||
private:
|
||||
float convertSliderVolume(int slider_volume) const;
|
||||
qint64 convertSliderProgress(int slider_progress) const;
|
||||
@ -70,23 +64,13 @@ class MediaPlayer : public TabContent {
|
||||
QString errorToString(QMediaPlayer::Error error) const;
|
||||
QString mediaStatusToString(QMediaPlayer::MediaStatus status) const;
|
||||
|
||||
void updateTimeAndProgress(int progress, int total);
|
||||
void setupIcons();
|
||||
void createConnections();
|
||||
|
||||
private:
|
||||
Ui::MediaPlayer m_ui;
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
QAudioOutput* m_audio;
|
||||
#endif
|
||||
|
||||
QMediaPlayer* m_player;
|
||||
QIcon m_iconPlay;
|
||||
QIcon m_iconPause;
|
||||
QIcon m_iconMute;
|
||||
QIcon m_iconUnmute;
|
||||
bool m_muted;
|
||||
QVideoWidget* m_video;
|
||||
};
|
||||
|
||||
#endif // MEDIAPLAYER_H
|
||||
#endif // QTMULTIMEDIABACKEND_H
|
@ -6,7 +6,6 @@
|
||||
#include "miscellaneous/settings.h"
|
||||
|
||||
#include <QCloseEvent>
|
||||
#include <QTimer>
|
||||
#include <QTimerEvent>
|
||||
|
||||
#include <chrono>
|
||||
@ -28,6 +27,11 @@ BaseToastNotification::BaseToastNotification(QWidget* parent) : QDialog(parent),
|
||||
|
||||
setStyleSheet(QSL("BaseToastNotification { border: 1px solid %1; }").arg(palette().windowText().color().name()));
|
||||
installEventFilter(this);
|
||||
|
||||
m_timerClosingClick.setInterval(200);
|
||||
m_timerClosingClick.setSingleShot(true);
|
||||
|
||||
connect(&m_timerClosingClick, &QTimer::timeout, this, &BaseToastNotification::close);
|
||||
}
|
||||
|
||||
BaseToastNotification::~BaseToastNotification() {}
|
||||
@ -82,7 +86,7 @@ bool BaseToastNotification::eventFilter(QObject* watched, QEvent* event) {
|
||||
if (dynamic_cast<QMouseEvent*>(event)->button() == Qt::MouseButton::RightButton) {
|
||||
event->accept();
|
||||
QCoreApplication::processEvents();
|
||||
QTimer::singleShot(200, this, &BaseToastNotification::close);
|
||||
m_timerClosingClick.start();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
class QAbstractButton;
|
||||
class QLabel;
|
||||
|
||||
@ -32,6 +34,7 @@ class BaseToastNotification : public QDialog {
|
||||
void closeRequested(BaseToastNotification* notif);
|
||||
|
||||
private:
|
||||
QTimer m_timerClosingClick;
|
||||
int m_timerId;
|
||||
};
|
||||
|
||||
|
@ -1,309 +0,0 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "mediaplayer.h"
|
||||
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
#include <QAudioOutput>
|
||||
#include <QWindow>
|
||||
#endif
|
||||
|
||||
MediaPlayer::MediaPlayer(QWidget* parent)
|
||||
: TabContent(parent),
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_audio(new QAudioOutput(this)),
|
||||
#endif
|
||||
m_player(new QMediaPlayer(this)), m_muted(false) {
|
||||
m_ui.setupUi(this);
|
||||
|
||||
m_player->setVideoOutput(m_ui.m_video);
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_player->setAudioOutput(m_audio);
|
||||
#endif
|
||||
|
||||
setupIcons();
|
||||
createConnections();
|
||||
|
||||
onPlaybackStateChanged(QMediaPlayer::PLAYBACK_STATE::StoppedState);
|
||||
onMediaStatusChanged(QMediaPlayer::MediaStatus::NoMedia);
|
||||
}
|
||||
|
||||
MediaPlayer::~MediaPlayer() {}
|
||||
|
||||
WebBrowser* MediaPlayer::webBrowser() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MediaPlayer::playUrl(const QString& url) {
|
||||
if (m_muted) {
|
||||
muteUnmute();
|
||||
}
|
||||
else {
|
||||
setVolume(m_ui.m_slidVolume->value());
|
||||
}
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_player->setSource(url);
|
||||
#else
|
||||
m_player->setMedia(QUrl(url));
|
||||
#endif
|
||||
|
||||
m_player->play();
|
||||
}
|
||||
|
||||
void MediaPlayer::playPause() {
|
||||
if (m_player->PLAYBACK_STATE_METHOD() != QMediaPlayer::PLAYBACK_STATE::PlayingState) {
|
||||
m_player->play();
|
||||
}
|
||||
else {
|
||||
m_player->pause();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayer::stop() {
|
||||
m_player->stop();
|
||||
}
|
||||
|
||||
void MediaPlayer::download() {
|
||||
emit urlDownloadRequested(
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_player->source()
|
||||
#else
|
||||
m_player->media().request().url()
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void MediaPlayer::muteUnmute() {
|
||||
m_ui.m_slidVolume->setEnabled(m_muted);
|
||||
setVolume(m_muted ? m_ui.m_slidVolume->value() : 0);
|
||||
|
||||
m_muted = !m_muted;
|
||||
}
|
||||
|
||||
void MediaPlayer::setSpeed(int speed) {
|
||||
m_player->setPlaybackRate(convertSpeed(speed));
|
||||
}
|
||||
|
||||
void MediaPlayer::setVolume(int volume) {
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
m_player->audioOutput()->setVolume(convertSliderVolume(volume));
|
||||
#else
|
||||
m_player->setVolume(volume);
|
||||
#endif
|
||||
|
||||
m_ui.m_btnVolume->setIcon(volume <= 0 ? m_iconMute : m_iconUnmute);
|
||||
}
|
||||
|
||||
void MediaPlayer::seek(int position) {
|
||||
m_player->setPosition(convertSliderProgress(position));
|
||||
}
|
||||
|
||||
void MediaPlayer::onPlaybackRateChanged(qreal speed) {
|
||||
m_ui.m_spinSpeed->blockSignals(true);
|
||||
m_ui.m_spinSpeed->setValue(convertSpinSpeed(speed));
|
||||
m_ui.m_spinSpeed->blockSignals(false);
|
||||
}
|
||||
|
||||
void MediaPlayer::onDurationChanged(qint64 duration) {
|
||||
m_ui.m_slidProgress->blockSignals(true);
|
||||
m_ui.m_slidProgress->setMaximum(convertDuration(duration));
|
||||
m_ui.m_slidProgress->blockSignals(false);
|
||||
|
||||
updateTimeAndProgress(convertToSliderProgress(m_player->position()), convertDuration(duration));
|
||||
}
|
||||
|
||||
void MediaPlayer::onPositionChanged(qint64 position) {
|
||||
m_ui.m_slidProgress->blockSignals(true);
|
||||
m_ui.m_slidProgress->setValue(convertToSliderProgress(position));
|
||||
m_ui.m_slidProgress->blockSignals(false);
|
||||
|
||||
updateTimeAndProgress(convertToSliderProgress(position), convertDuration(m_player->duration()));
|
||||
}
|
||||
|
||||
void MediaPlayer::updateTimeAndProgress(int progress, int total) {
|
||||
m_ui.m_lblTime->setText(QSL("%1/%2").arg(QDateTime::fromSecsSinceEpoch(progress).toUTC().toString("hh:mm:ss"),
|
||||
QDateTime::fromSecsSinceEpoch(total).toUTC().toString("hh:mm:ss")));
|
||||
}
|
||||
|
||||
void MediaPlayer::onErrorOccurred(QMediaPlayer::Error error, const QString& error_string) {
|
||||
QString err = error_string.isEmpty() ? errorToString(error) : error_string;
|
||||
m_ui.m_lblStatus->setStatus(WidgetWithStatus::StatusType::Error, err, err);
|
||||
}
|
||||
|
||||
void MediaPlayer::onAudioAvailable(bool available) {
|
||||
m_ui.m_slidVolume->setEnabled(available);
|
||||
m_ui.m_btnVolume->setEnabled(available);
|
||||
}
|
||||
|
||||
void MediaPlayer::onVideoAvailable(bool available) {
|
||||
Q_UNUSED(available)
|
||||
}
|
||||
|
||||
void MediaPlayer::onMediaStatusChanged(QMediaPlayer::MediaStatus status) {
|
||||
QString st = mediaStatusToString(status);
|
||||
m_ui.m_lblStatus->setStatus(status == QMediaPlayer::MediaStatus::InvalidMedia
|
||||
? WidgetWithStatus::StatusType::Error
|
||||
: WidgetWithStatus::StatusType::Information,
|
||||
st,
|
||||
st);
|
||||
}
|
||||
|
||||
void MediaPlayer::onPlaybackStateChanged(QMediaPlayer::PLAYBACK_STATE state) {
|
||||
switch (state) {
|
||||
case QMediaPlayer::PLAYBACK_STATE::StoppedState:
|
||||
m_ui.m_btnPlayPause->setIcon(m_iconPlay);
|
||||
m_ui.m_btnStop->setEnabled(false);
|
||||
break;
|
||||
|
||||
case QMediaPlayer::PLAYBACK_STATE::PlayingState:
|
||||
m_ui.m_btnPlayPause->setIcon(m_iconPause);
|
||||
m_ui.m_btnStop->setEnabled(true);
|
||||
break;
|
||||
|
||||
case QMediaPlayer::PLAYBACK_STATE::PausedState:
|
||||
m_ui.m_btnPlayPause->setIcon(m_iconPlay);
|
||||
m_ui.m_btnStop->setEnabled(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int MediaPlayer::convertToSliderProgress(qint64 player_progress) const {
|
||||
return player_progress / 1000;
|
||||
}
|
||||
|
||||
int MediaPlayer::convertDuration(qint64 duration) const {
|
||||
return duration / 1000;
|
||||
}
|
||||
|
||||
qreal MediaPlayer::convertSpeed(int speed) const {
|
||||
return speed / 100.0;
|
||||
}
|
||||
|
||||
int MediaPlayer::convertSpinSpeed(qreal speed) const {
|
||||
return speed * 100;
|
||||
}
|
||||
|
||||
void MediaPlayer::onSeekableChanged(bool seekable) {
|
||||
m_ui.m_slidProgress->setEnabled(seekable);
|
||||
|
||||
if (!seekable) {
|
||||
onPositionChanged(0);
|
||||
}
|
||||
}
|
||||
|
||||
QString MediaPlayer::errorToString(QMediaPlayer::Error error) const {
|
||||
switch (error) {
|
||||
case QMediaPlayer::ResourceError:
|
||||
return tr("Cannot load media (missing codecs)");
|
||||
|
||||
case QMediaPlayer::FormatError:
|
||||
return tr("Unrecognized format");
|
||||
|
||||
case QMediaPlayer::NetworkError:
|
||||
return tr("Network problem");
|
||||
|
||||
case QMediaPlayer::AccessDeniedError:
|
||||
return tr("Access denied");
|
||||
|
||||
#if QT_VERSION_MAJOR == 5
|
||||
case QMediaPlayer::ServiceMissingError:
|
||||
return tr("Service is missing");
|
||||
|
||||
case QMediaPlayer::MediaIsPlaylist:
|
||||
return tr("This is playlist");
|
||||
#endif
|
||||
|
||||
case QMediaPlayer::NoError:
|
||||
return tr("No errors");
|
||||
|
||||
default:
|
||||
return tr("Unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
float MediaPlayer::convertSliderVolume(int slider_volume) const {
|
||||
return slider_volume / 100.0f;
|
||||
}
|
||||
|
||||
qint64 MediaPlayer::convertSliderProgress(int slider_progress) const {
|
||||
return qint64(slider_progress) * qint64(1000);
|
||||
}
|
||||
|
||||
QString MediaPlayer::mediaStatusToString(QMediaPlayer::MediaStatus status) const {
|
||||
switch (status) {
|
||||
case QMediaPlayer::NoMedia:
|
||||
return tr("No media");
|
||||
|
||||
case QMediaPlayer::LoadingMedia:
|
||||
return tr("Loading...");
|
||||
|
||||
case QMediaPlayer::LoadedMedia:
|
||||
return tr("Media loaded");
|
||||
|
||||
case QMediaPlayer::StalledMedia:
|
||||
return tr("Media stalled");
|
||||
|
||||
case QMediaPlayer::BufferingMedia:
|
||||
return tr("Buffering...");
|
||||
|
||||
case QMediaPlayer::BufferedMedia:
|
||||
return tr("Loaded");
|
||||
|
||||
case QMediaPlayer::EndOfMedia:
|
||||
return tr("Ended");
|
||||
|
||||
case QMediaPlayer::InvalidMedia:
|
||||
return tr("Media is invalid");
|
||||
|
||||
default:
|
||||
return tr("Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPlayer::setupIcons() {
|
||||
m_iconPlay = qApp->icons()->fromTheme(QSL("media-playback-start"), QSL("player_play"));
|
||||
m_iconPause = qApp->icons()->fromTheme(QSL("media-playback-pause"), QSL("player_pause"));
|
||||
m_iconMute = qApp->icons()->fromTheme(QSL("player-volume-muted"), QSL("audio-volume-muted"));
|
||||
m_iconUnmute = qApp->icons()->fromTheme(QSL("player-volume"), QSL("stock_volume"));
|
||||
|
||||
m_ui.m_btnDownload->setIcon(qApp->icons()->fromTheme(QSL("download"), QSL("browser-download")));
|
||||
m_ui.m_btnStop->setIcon(qApp->icons()->fromTheme(QSL("media-playback-stop"), QSL("player_stop")));
|
||||
}
|
||||
|
||||
void MediaPlayer::createConnections() {
|
||||
connect(m_player, &QMediaPlayer::durationChanged, this, &MediaPlayer::onDurationChanged);
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
connect(m_player, &QMediaPlayer::errorOccurred, this, &MediaPlayer::onErrorOccurred);
|
||||
#else
|
||||
connect(m_player, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), this, [this](QMediaPlayer::Error error) {
|
||||
onErrorOccurred(error);
|
||||
});
|
||||
#endif
|
||||
|
||||
#if QT_VERSION_MAJOR == 6
|
||||
connect(m_player, &QMediaPlayer::hasAudioChanged, this, &MediaPlayer::onAudioAvailable);
|
||||
connect(m_player, &QMediaPlayer::hasVideoChanged, this, &MediaPlayer::onVideoAvailable);
|
||||
connect(m_player, &QMediaPlayer::playbackStateChanged, this, &MediaPlayer::onPlaybackStateChanged);
|
||||
#else
|
||||
connect(m_player, &QMediaPlayer::audioAvailableChanged, this, &MediaPlayer::onAudioAvailable);
|
||||
connect(m_player, &QMediaPlayer::videoAvailableChanged, this, &MediaPlayer::onVideoAvailable);
|
||||
connect(m_player, &QMediaPlayer::stateChanged, this, &MediaPlayer::onPlaybackStateChanged);
|
||||
#endif
|
||||
|
||||
connect(m_player, &QMediaPlayer::mediaStatusChanged, this, &MediaPlayer::onMediaStatusChanged);
|
||||
connect(m_player, &QMediaPlayer::positionChanged, this, &MediaPlayer::onPositionChanged);
|
||||
connect(m_player, &QMediaPlayer::seekableChanged, this, &MediaPlayer::onSeekableChanged);
|
||||
connect(m_player, &QMediaPlayer::playbackRateChanged, this, &MediaPlayer::onPlaybackRateChanged);
|
||||
|
||||
connect(m_ui.m_btnPlayPause, &PlainToolButton::clicked, this, &MediaPlayer::playPause);
|
||||
connect(m_ui.m_btnStop, &PlainToolButton::clicked, this, &MediaPlayer::stop);
|
||||
connect(m_ui.m_btnDownload, &PlainToolButton::clicked, this, &MediaPlayer::download);
|
||||
connect(m_ui.m_btnVolume, &PlainToolButton::clicked, this, &MediaPlayer::muteUnmute);
|
||||
connect(m_ui.m_slidVolume, &QSlider::valueChanged, this, &MediaPlayer::setVolume);
|
||||
connect(m_ui.m_slidProgress, &QSlider::valueChanged, this, &MediaPlayer::seek);
|
||||
connect(m_ui.m_spinSpeed, QOverload<int>::of(&QSpinBox::valueChanged), this, &MediaPlayer::setSpeed);
|
||||
}
|
@ -8,7 +8,6 @@
|
||||
#include "gui/feedsview.h"
|
||||
#include "gui/messagepreviewer.h"
|
||||
#include "gui/messagesview.h"
|
||||
#include "gui/reusable/mediaplayer.h"
|
||||
#include "gui/reusable/plaintoolbutton.h"
|
||||
#include "gui/tabbar.h"
|
||||
#include "gui/webbrowser.h"
|
||||
@ -17,6 +16,10 @@
|
||||
#include "miscellaneous/settings.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
|
||||
#if defined(ENABLE_MEDIAPLAYER)
|
||||
#include "gui/mediaplayer/mediaplayer.h"
|
||||
#endif
|
||||
|
||||
#include <QMenu>
|
||||
#include <QTimer>
|
||||
#include <QToolButton>
|
||||
@ -224,6 +227,7 @@ int TabWidget::addEmptyBrowser() {
|
||||
return addBrowser(false, true);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_MEDIAPLAYER)
|
||||
int TabWidget::addMediaPlayer(const QString& url, bool make_active) {
|
||||
auto* player = new MediaPlayer(this);
|
||||
|
||||
@ -248,6 +252,7 @@ int TabWidget::addMediaPlayer(const QString& url, bool make_active) {
|
||||
|
||||
return index;
|
||||
}
|
||||
#endif
|
||||
|
||||
int TabWidget::addLinkedBrowser(const QUrl& initial_url) {
|
||||
return addBrowser(false, false, initial_url);
|
||||
|
@ -78,7 +78,9 @@ class TabWidget : public QTabWidget {
|
||||
// Adds new WebBrowser tab to global TabWidget.
|
||||
int addEmptyBrowser();
|
||||
|
||||
#if defined(ENABLE_MEDIAPLAYER)
|
||||
int addMediaPlayer(const QString& url, bool make_active);
|
||||
#endif
|
||||
|
||||
// Adds new WebBrowser with link. This is used when user
|
||||
// selects to "Open link in new tab.".
|
||||
|
@ -27,7 +27,10 @@ void WebViewer::processContextMenu(QMenu* specific_menu, QContextMenuEvent* even
|
||||
specific_menu->addAction(m_actionPlayLink.data());
|
||||
|
||||
m_actionOpenExternalBrowser.data()->setEnabled(m_contextMenuData.m_linkUrl.isValid());
|
||||
|
||||
#if defined(ENABLE_MEDIAPLAYER)
|
||||
m_actionPlayLink.data()->setEnabled(m_contextMenuData.m_linkUrl.isValid());
|
||||
#endif
|
||||
|
||||
if (m_contextMenuData.m_linkUrl.isValid()) {
|
||||
QFileIconProvider icon_provider;
|
||||
@ -61,11 +64,13 @@ void WebViewer::processContextMenu(QMenu* specific_menu, QContextMenuEvent* even
|
||||
}
|
||||
|
||||
void WebViewer::playClickedLinkAsMedia() {
|
||||
#if defined(ENABLE_MEDIAPLAYER)
|
||||
auto context_url = m_contextMenuData.m_linkUrl;
|
||||
|
||||
if (context_url.isValid()) {
|
||||
qApp->mainForm()->tabWidget()->addMediaPlayer(context_url.toString(), true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void WebViewer::openClickedLinkInExternalBrowser() {
|
||||
@ -97,6 +102,11 @@ void WebViewer::initializeCommonMenuItems() {
|
||||
m_actionPlayLink.reset(new QAction(qApp->icons()->fromTheme(QSL("player_play"), QSL("media-playback-start")),
|
||||
QObject::tr("Play link as audio/video")));
|
||||
|
||||
#if !defined(ENABLE_MEDIAPLAYER)
|
||||
m_actionPlayLink->setText(m_actionPlayLink->text() + QSL(" ") + QObject::tr("(not supported)"));
|
||||
m_actionPlayLink->setEnabled(false);
|
||||
#endif
|
||||
|
||||
QObject::connect(m_actionOpenExternalBrowser.data(),
|
||||
&QAction::triggered,
|
||||
m_actionOpenExternalBrowser.data(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user