/* SPDX-FileCopyrightText: 2007 Matthias Kretz SPDX-License-Identifier: GPL-2.0-or-later */ #include "phononwidget.h" #include #include #include #include #include #include #include #include #include class EmbeddedVideoPlayer : public Phonon::VideoWidget { Q_OBJECT public: EmbeddedVideoPlayer(QWidget *parent = nullptr) : Phonon::VideoWidget(parent) { } void setSizeHint(const QSize &size) { m_sizeHint = size; updateGeometry(); } QSize sizeHint() const override { return m_sizeHint.isValid() ? m_sizeHint : Phonon::VideoWidget::sizeHint(); } private: QSize m_sizeHint; }; PhononWidget::PhononWidget(QWidget *parent) : QWidget(parent) , m_url() , m_playButton(nullptr) , m_pauseButton(nullptr) , m_topLayout(nullptr) , m_media(nullptr) , m_seekSlider(nullptr) , m_audioOutput(nullptr) , m_videoPlayer(nullptr) { } void PhononWidget::setUrl(const QUrl &url, MediaKind kind) { if (m_url != url) { m_url = url; m_isVideo = kind == MediaKind::Video; } if (m_autoPlay) { play(); } else { stop(); } } void PhononWidget::setAutoPlay(bool autoPlay) { m_autoPlay = autoPlay; if (!m_url.isEmpty() && (m_media == nullptr || m_media->state() != Phonon::State::PlayingState) && m_autoPlay && isVisible()) { play(); } } QUrl PhononWidget::url() const { return m_url; } void PhononWidget::clearUrl() { m_url.clear(); } void PhononWidget::togglePlayback() { if (m_media && m_media->state() == Phonon::State::PlayingState) { m_media->pause(); } else { play(); } } bool PhononWidget::eventFilter(QObject *object, QEvent *event) { Q_UNUSED(object) if (event->type() == QEvent::MouseButtonPress) { const QMouseEvent *mouseEvent = static_cast(event); if (mouseEvent->button() == Qt::LeftButton) { // toggle playback togglePlayback(); return true; } } return false; } void PhononWidget::setVideoSize(const QSize &size) { if (m_videoSize != size) { m_videoSize = size; applyVideoSize(); } } QSize PhononWidget::videoSize() const { return m_videoSize; } void PhononWidget::showEvent(QShowEvent *event) { if (event->spontaneous()) { QWidget::showEvent(event); return; } if (!m_topLayout) { m_topLayout = new QVBoxLayout(this); m_topLayout->setContentsMargins(0, 0, 0, 0); QHBoxLayout *controlsLayout = new QHBoxLayout(); controlsLayout->setContentsMargins(0, 0, 0, 0); controlsLayout->setSpacing(0); m_playButton = new QToolButton(this); m_pauseButton = new QToolButton(this); m_seekSlider = new Phonon::SeekSlider(this); controlsLayout->addWidget(m_playButton); controlsLayout->addWidget(m_pauseButton); controlsLayout->addWidget(m_seekSlider); m_topLayout->addLayout(controlsLayout); const int smallIconSize = style()->pixelMetric(QStyle::PM_SmallIconSize); const QSize buttonSize(smallIconSize, smallIconSize); m_playButton->setToolTip(i18n("play")); m_playButton->setIconSize(buttonSize); m_playButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); m_playButton->setAutoRaise(true); connect(m_playButton, &QToolButton::clicked, this, &PhononWidget::play); m_pauseButton->setToolTip(i18n("pause")); m_pauseButton->setIconSize(buttonSize); m_pauseButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause"))); m_pauseButton->setAutoRaise(true); m_pauseButton->hide(); connect(m_pauseButton, &QToolButton::clicked, this, &PhononWidget::togglePlayback); m_seekSlider->setIconVisible(false); // Creating an audio player or video player instance might take up to // 2 seconds when doing it the first time. To prevent that the user // interface gets noticeable blocked, the creation is delayed until // the play button has been pressed (see PhononWidget::play()). } } void PhononWidget::hideEvent(QHideEvent *event) { QWidget::hideEvent(event); if (!event->spontaneous()) { stop(); } } void PhononWidget::stateChanged(Phonon::State newstate) { setUpdatesEnabled(false); switch (newstate) { case Phonon::PlayingState: case Phonon::BufferingState: m_playButton->hide(); m_pauseButton->show(); break; default: m_pauseButton->hide(); m_playButton->show(); break; } setUpdatesEnabled(true); } void PhononWidget::play() { if (!m_media) { m_media = new Phonon::MediaObject(this); connect(m_media, &Phonon::MediaObject::stateChanged, this, &PhononWidget::stateChanged); connect(m_media, &Phonon::MediaObject::finished, this, &PhononWidget::finished); m_seekSlider->setMediaObject(m_media); } if (!m_videoPlayer) { m_videoPlayer = new EmbeddedVideoPlayer(this); m_videoPlayer->setCursor(Qt::PointingHandCursor); m_videoPlayer->installEventFilter(this); m_topLayout->insertWidget(0, m_videoPlayer); Phonon::createPath(m_media, m_videoPlayer); applyVideoSize(); } if (!m_audioOutput) { m_audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this); Phonon::createPath(m_media, m_audioOutput); } if (m_isVideo) { Q_EMIT hasVideoChanged(true); } if (m_url != m_media->currentSource().url()) { m_media->setCurrentSource(m_url); } m_media->play(); m_videoPlayer->setVisible(m_isVideo); } void PhononWidget::finished() { if (m_isVideo) { m_videoPlayer->hide(); Q_EMIT hasVideoChanged(false); } } Phonon::State PhononWidget::state() const { return m_media == nullptr ? Phonon::State::StoppedState : m_media->state(); } void PhononWidget::stop() { if (m_media) { m_media->stop(); m_videoPlayer->hide(); Q_EMIT hasVideoChanged(false); } } void PhononWidget::applyVideoSize() { if ((m_videoPlayer) && m_videoSize.isValid()) { m_videoPlayer->setSizeHint(m_videoSize); } } #include "moc_phononwidget.cpp" #include "phononwidget.moc"