File indexing completed on 2024-04-28 15:40:27
0001 // SPDX-FileCopyrightText: 2006-2010, 2012, 2021 Jesper K. Pedersen <blackie@kde.org> 0002 // SPDX-FileCopyrightText: 2007 Dirk Mueller <mueller@kde.org> 0003 // SPDX-FileCopyrightText: 2007 Thiago Macieira <thiago@kde.org> 0004 // SPDX-FileCopyrightText: 2007-2008 Laurent Montel <montel@kde.org> 0005 // SPDX-FileCopyrightText: 2008 Henner Zeller <h.zeller@acm.org> 0006 // SPDX-FileCopyrightText: 2009 Tuomas Suutari <tuomas@nepnep.net> 0007 // SPDX-FileCopyrightText: 2013 Dominik Broj <broj.dominik@gmail.com> 0008 // SPDX-FileCopyrightText: 2013 Miika Turkia <miika.turkia@gmail.com> 0009 // SPDX-FileCopyrightText: 2013, 2015-2016, 2019-2022 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 0010 // SPDX-FileCopyrightText: 2018-2019 Tobias Leupold <tl at stonemx dot de> 0011 // 0012 // SPDX-License-Identifier: GPL-2.0-or-later 0013 0014 #include "PhononDisplay.h" 0015 #include "Logging.h" 0016 0017 #include <DB/ImageInfo.h> 0018 #include <DB/ImageInfoPtr.h> 0019 #include <MainWindow/FeatureDialog.h> 0020 0021 #include "VideoToolBar.h" 0022 #include <KLocalizedString> 0023 #include <QAction> 0024 #include <QGuiApplication> 0025 #include <QResizeEvent> 0026 #include <QScreen> 0027 #include <QtMath> 0028 #include <kmessagebox.h> 0029 #include <ktoolbar.h> 0030 #include <kxmlguibuilder.h> 0031 #include <kxmlguiclient.h> 0032 #include <kxmlguifactory.h> 0033 #include <phonon/audiooutput.h> 0034 #include <phonon/mediaobject.h> 0035 #include <phonon/videowidget.h> 0036 #include <qglobal.h> 0037 #include <qlayout.h> 0038 0039 namespace 0040 { 0041 constexpr qreal LOUDNESS_TO_VOLTAGE_EXPONENT = qreal(0.67); 0042 constexpr qreal VOLTAGE_TO_LOUDNESS_EXPONENT = qreal(1.0 / LOUDNESS_TO_VOLTAGE_EXPONENT); 0043 } 0044 0045 Viewer::PhononDisplay::PhononDisplay(QWidget *parent) 0046 : Viewer::VideoDisplay(parent) 0047 { 0048 setBackgroundRole(QPalette::Shadow); 0049 setAutoFillBackground(true); 0050 setup(); 0051 } 0052 0053 void Viewer::PhononDisplay::setup() 0054 { 0055 m_mediaObject = new Phonon::MediaObject(this); 0056 m_audioDevice = new Phonon::AudioOutput(Phonon::VideoCategory, this); 0057 Phonon::createPath(m_mediaObject, m_audioDevice); 0058 0059 m_videoWidget = new Phonon::VideoWidget(this); 0060 Phonon::createPath(m_mediaObject, m_videoWidget); 0061 0062 m_videoToolBar = new VideoToolBar(this); 0063 m_videoToolBar->show(); 0064 m_mediaObject->setTickInterval(100); 0065 0066 m_videoWidget->setFocus(); 0067 m_videoWidget->resize(1024, 768); 0068 m_videoWidget->move(0, 0); 0069 m_videoWidget->show(); 0070 0071 connect(m_mediaObject, &Phonon::MediaObject::finished, this, &PhononDisplay::stopped); 0072 connect(m_mediaObject, &Phonon::MediaObject::stateChanged, this, &PhononDisplay::phononStateChanged); 0073 connect(m_mediaObject, &Phonon::MediaObject::tick, m_videoToolBar, &VideoToolBar::setPosition); 0074 connect(m_videoToolBar, &VideoToolBar::positionChanged, m_mediaObject, &Phonon::MediaObject::seek); 0075 // use proxy slots to avoid a signal-loop between the VideoToolBar and the Phonon::AudioOutput 0076 connect(m_videoToolBar, &VideoToolBar::volumeChanged, this, &PhononDisplay::changeVolume); 0077 connect(m_audioDevice, &Phonon::AudioOutput::volumeChanged, this, &PhononDisplay::updateVolume); 0078 connect(m_videoToolBar, &VideoToolBar::muted, this, &PhononDisplay::setMuted); 0079 connect(m_audioDevice, &Phonon::AudioOutput::mutedChanged, this, &PhononDisplay::updateMuteState); 0080 } 0081 0082 bool Viewer::PhononDisplay::setImageImpl(DB::ImageInfoPtr info, bool /*forward*/) 0083 { 0084 m_mediaObject->setCurrentSource(QUrl::fromLocalFile(info->fileName().absolute())); 0085 m_mediaObject->play(); 0086 0087 return true; 0088 } 0089 0090 void Viewer::PhononDisplay::zoomIn() 0091 { 0092 resize(1.25); 0093 } 0094 0095 void Viewer::PhononDisplay::zoomOut() 0096 { 0097 resize(0.8); 0098 } 0099 0100 void Viewer::PhononDisplay::zoomFull() 0101 { 0102 m_zoomType = FullZoom; 0103 setVideoWidgetSize(); 0104 } 0105 0106 void Viewer::PhononDisplay::zoomPixelForPixel() 0107 { 0108 m_zoomType = PixelForPixelZoom; 0109 m_zoomFactor = 1; 0110 setVideoWidgetSize(); 0111 } 0112 0113 void Viewer::PhononDisplay::resize(double factor) 0114 { 0115 m_zoomType = FixedZoom; 0116 m_zoomFactor *= factor; 0117 setVideoWidgetSize(); 0118 } 0119 0120 void Viewer::PhononDisplay::resizeEvent(QResizeEvent *event) 0121 { 0122 AbstractDisplay::resizeEvent(event); 0123 setVideoWidgetSize(); 0124 } 0125 0126 Viewer::PhononDisplay::~PhononDisplay() 0127 { 0128 if (m_mediaObject) 0129 m_mediaObject->stop(); 0130 } 0131 0132 void Viewer::PhononDisplay::stop() 0133 { 0134 if (m_mediaObject) 0135 m_mediaObject->stop(); 0136 } 0137 0138 void Viewer::PhononDisplay::playPause() 0139 { 0140 if (!m_mediaObject) 0141 return; 0142 0143 if (m_mediaObject->state() != Phonon::PlayingState) 0144 m_mediaObject->play(); 0145 else 0146 m_mediaObject->pause(); 0147 } 0148 0149 QImage Viewer::PhononDisplay::screenShoot() 0150 { 0151 return QGuiApplication::primaryScreen()->grabWindow(m_videoWidget->winId()).toImage(); 0152 } 0153 0154 void Viewer::PhononDisplay::restart() 0155 { 0156 if (!m_mediaObject) 0157 return; 0158 0159 m_mediaObject->seek(0); 0160 m_mediaObject->play(); 0161 } 0162 0163 bool Viewer::PhononDisplay::isPaused() const 0164 { 0165 if (!m_mediaObject) 0166 return false; 0167 0168 return m_mediaObject->state() == Phonon::PausedState; 0169 } 0170 0171 bool Viewer::PhononDisplay::isPlaying() const 0172 { 0173 if (!m_mediaObject) 0174 return false; 0175 0176 return m_mediaObject->state() == Phonon::PlayingState; 0177 } 0178 0179 void Viewer::PhononDisplay::phononStateChanged(Phonon::State newState, Phonon::State /*oldState*/) 0180 { 0181 setVideoWidgetSize(); 0182 if (newState == Phonon::ErrorState) { 0183 KMessageBox::error(nullptr, m_mediaObject->errorString(), i18n("Error playing media")); 0184 } 0185 } 0186 0187 void Viewer::PhononDisplay::updateVolume(qreal newVolumeVolt) 0188 { 0189 const QSignalBlocker blocker { m_videoToolBar }; 0190 const auto volume = qPow(newVolumeVolt, VOLTAGE_TO_LOUDNESS_EXPONENT) * 100.0; 0191 m_videoToolBar->setVolume(volume); 0192 qCDebug(ViewerLog) << "Phonon volume is now at" << volume; 0193 } 0194 0195 void Viewer::PhononDisplay::updateMuteState(bool mute) 0196 { 0197 const QSignalBlocker blocker { m_videoToolBar }; 0198 m_videoToolBar->setMuted(mute); 0199 qCDebug(ViewerLog) << "Phonon mute state is now" << mute; 0200 } 0201 0202 void Viewer::PhononDisplay::setVideoWidgetSize() 0203 { 0204 if (!m_mediaObject) 0205 return; 0206 0207 QSize videoSize; 0208 if (m_zoomType == FullZoom) { 0209 videoSize = QSize(size().width(), size().height() - m_videoToolBar->height()); 0210 if (m_videoWidget->sizeHint().width() > 0) { 0211 m_zoomFactor = videoSize.width() / m_videoWidget->sizeHint().width(); 0212 } 0213 } else { 0214 videoSize = m_videoWidget->sizeHint(); 0215 if (m_zoomType == FixedZoom) 0216 videoSize *= m_zoomFactor; 0217 } 0218 0219 m_videoWidget->resize(videoSize); 0220 0221 QPoint pos = QPoint(width() / 2, (height() - m_videoToolBar->sizeHint().height()) / 2) - QPoint(videoSize.width() / 2, videoSize.height() / 2); 0222 m_videoWidget->move(pos); 0223 0224 m_videoToolBar->move(0, height() - m_videoToolBar->sizeHint().height()); 0225 m_videoToolBar->resize(width(), m_videoToolBar->sizeHint().height()); 0226 m_videoToolBar->setRange(0, m_mediaObject->totalTime()); 0227 } 0228 0229 void Viewer::PhononDisplay::rotate(const DB::ImageInfoPtr & /*info*/) 0230 { 0231 // Not supported. 0232 } 0233 0234 void Viewer::PhononDisplay::changeVolume(int newVolumePercent) 0235 { 0236 QSignalBlocker blocker { m_audioDevice }; 0237 m_audioDevice->setVolume(qPow(newVolumePercent / 100.0, LOUDNESS_TO_VOLTAGE_EXPONENT)); 0238 } 0239 0240 void Viewer::PhononDisplay::setMuted(bool mute) 0241 { 0242 QSignalBlocker blocker { m_audioDevice }; 0243 // Phonon::AudioDevice::setMuted() does not seem to be able to reliably unmute things 0244 // luckily, we know the correct value for the volume slider 0245 m_audioDevice->setMuted(mute); 0246 if (!mute) { 0247 const auto volumeDb = qPow(m_videoToolBar->volume() / 100.0, LOUDNESS_TO_VOLTAGE_EXPONENT); 0248 m_audioDevice->setVolume(volumeDb); 0249 } 0250 } 0251 0252 void Viewer::PhononDisplay::relativeSeek(int msec) 0253 { 0254 m_mediaObject->seek(m_mediaObject->currentTime() + msec); 0255 } 0256 0257 // vi:expandtab:tabstop=4 shiftwidth=4: 0258 0259 #include "moc_PhononDisplay.cpp"