rssguard/src/librssguard/gui/mediaplayer/qtmultimedia/qtmultimediabackend.cpp
2023-11-29 14:47:23 +01:00

288 lines
8 KiB
C++

// 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
emit volumeChanged(volume);
}
void QtMultimediaBackend::setPosition(int position) {
m_player->setPosition(convertSliderProgress(position));
}
void QtMultimediaBackend::setFullscreen(bool fullscreen) {
Q_UNUSED(fullscreen)
// No extra work needed here.
}
void QtMultimediaBackend::setMuted(bool muted) {
// This backend audio class does not support muting on Qt 5, so we emulate
// muting by seting volume to 0;
if (muted) {
// Remember volume and mute.
#if QT_VERSION_MAJOR == 6
m_volume = convertToSliderVolume(m_player->audioOutput()->volume());
#else
m_volume = m_player->volume();
#endif
#if QT_VERSION_MAJOR == 6
m_player->audioOutput()->setVolume(convertSliderVolume(0));
#else
m_player->setVolume(0);
#endif
}
else {
// Unmute.
#if QT_VERSION_MAJOR == 6
m_player->audioOutput()->setVolume(convertSliderVolume(m_volume));
#else
m_player->setVolume(m_volume);
#endif
}
emit mutedChanged(muted);
}
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);
}
int QtMultimediaBackend::convertToSliderVolume(float volume) const {
return volume * 100;
}