File indexing completed on 2025-01-05 03:57:28
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * http://www.digikam.org 0005 * 0006 * Date : 2006-20-12 0007 * Description : a view to embed QtMultimedia media player. 0008 * 0009 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "mediaplayerview.h" 0016 0017 // Qt includes 0018 0019 #include <QApplication> 0020 #include <QVBoxLayout> 0021 #include <QMouseEvent> 0022 #include <QProxyStyle> 0023 #include <QPushButton> 0024 #include <QFileInfo> 0025 #include <QToolBar> 0026 #include <QAction> 0027 #include <QSlider> 0028 #include <QLabel> 0029 #include <QFrame> 0030 #include <QStyle> 0031 #include <QTransform> 0032 #include <QGraphicsView> 0033 #include <QGraphicsScene> 0034 #include <QGraphicsVideoItem> 0035 #include <QVideoSink> 0036 #include <QVideoFrame> 0037 #include <QAudioOutput> 0038 #include <QMediaMetaData> 0039 #include <QStandardPaths> 0040 0041 // KDE includes 0042 0043 #include <klocalizedstring.h> 0044 #include <ksharedconfig.h> 0045 #include <kconfiggroup.h> 0046 0047 // Local includes 0048 0049 #include "digikam_debug.h" 0050 #include "digikam_globals.h" 0051 #include "thememanager.h" 0052 #include "stackedview.h" 0053 #include "dlayoutbox.h" 0054 #include "metaengine.h" 0055 #include "dmetadata.h" 0056 0057 namespace Digikam 0058 { 0059 0060 class Q_DECL_HIDDEN MediaPlayerMouseClickFilter : public QObject 0061 { 0062 Q_OBJECT 0063 0064 public: 0065 0066 explicit MediaPlayerMouseClickFilter(QObject* const parent) 0067 : QObject (parent), 0068 m_parent(parent) 0069 { 0070 } 0071 0072 protected: 0073 0074 bool eventFilter(QObject* obj, QEvent* event) override 0075 { 0076 if ((event->type() == QEvent::MouseButtonPress) || (event->type() == QEvent::MouseButtonDblClick)) 0077 { 0078 bool singleClick = qApp->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick); 0079 QMouseEvent* const mouseEvent = dynamic_cast<QMouseEvent*>(event); 0080 0081 if (m_parent && mouseEvent) 0082 { 0083 MediaPlayerView* const mplayer = dynamic_cast<MediaPlayerView*>(m_parent); 0084 0085 if (mplayer) 0086 { 0087 if ((mouseEvent->button() == Qt::LeftButton) && 0088 ((singleClick && (event->type() == QEvent::MouseButtonPress)) || 0089 (!singleClick && (event->type() == QEvent::MouseButtonDblClick)))) 0090 { 0091 mplayer->slotEscapePressed(); 0092 } 0093 else if ((mouseEvent->button() == Qt::RightButton) && 0094 (event->type() == QEvent::MouseButtonPress)) 0095 { 0096 mplayer->slotRotateVideo(); 0097 } 0098 0099 return true; 0100 } 0101 } 0102 } 0103 0104 return QObject::eventFilter(obj, event); 0105 } 0106 0107 private: 0108 0109 QObject* m_parent = nullptr; 0110 }; 0111 0112 // -------------------------------------------------------- 0113 0114 class Q_DECL_HIDDEN PlayerVideoStyle : public QProxyStyle 0115 { 0116 Q_OBJECT 0117 0118 public: 0119 0120 using QProxyStyle::QProxyStyle; 0121 0122 int styleHint(QStyle::StyleHint hint, 0123 const QStyleOption* option = nullptr, 0124 const QWidget* widget = nullptr, 0125 QStyleHintReturn* returnData = nullptr) const override 0126 { 0127 if (hint == QStyle::SH_Slider_AbsoluteSetButtons) 0128 { 0129 return (Qt::LeftButton | Qt::MiddleButton | Qt::RightButton); 0130 } 0131 0132 return QProxyStyle::styleHint(hint, option, widget, returnData); 0133 } 0134 }; 0135 0136 // -------------------------------------------------------- 0137 0138 class MediaPlayerView::Private 0139 { 0140 0141 public: 0142 0143 enum MediaPlayerViewMode 0144 { 0145 ErrorView = 0, 0146 PlayerView 0147 }; 0148 0149 public: 0150 0151 Private() = default; 0152 0153 QFrame* errorView = nullptr; 0154 QFrame* playerView = nullptr; 0155 0156 QAction* prevAction = nullptr; 0157 QAction* nextAction = nullptr; 0158 QAction* playAction = nullptr; 0159 QAction* grabAction = nullptr; 0160 0161 QPushButton* loopPlay = nullptr; 0162 0163 QToolBar* toolBar = nullptr; 0164 0165 DInfoInterface* iface = nullptr; 0166 0167 QGraphicsScene* videoScene = nullptr; 0168 QGraphicsView* videoView = nullptr; 0169 QGraphicsVideoItem* videoItem = nullptr; 0170 QMediaPlayer* player = nullptr; 0171 QAudioOutput* audio = nullptr; 0172 0173 QSlider* slider = nullptr; 0174 QSlider* volume = nullptr; 0175 QLabel* tlabel = nullptr; 0176 QUrl currentItem; 0177 0178 int videoOrientation = 0; 0179 qint64 sliderTime = 0; 0180 0181 public: 0182 0183 void adjustVideoSize() 0184 { 0185 videoItem->resetTransform(); 0186 0187 QSizeF nativeSize = videoItem->nativeSize(); 0188 int mediaOrientation = videoMediaOrientation(); 0189 0190 if ((nativeSize.width() < 1.0) || 0191 (nativeSize.height() < 1.0)) 0192 { 0193 return; 0194 } 0195 0196 if ((mediaOrientation == 90) || 0197 (mediaOrientation == 270)) 0198 { 0199 nativeSize.transpose(); 0200 } 0201 0202 double ratio = (nativeSize.width() / 0203 nativeSize.height()); 0204 0205 if (videoView->width() > videoView->height()) 0206 { 0207 QSizeF vsize(videoView->height() * ratio, 0208 videoView->height()); 0209 videoItem->setSize(vsize); 0210 } 0211 else 0212 { 0213 QSizeF vsize(videoView->width(), 0214 videoView->width() / ratio); 0215 videoItem->setSize(vsize); 0216 } 0217 0218 videoView->setSceneRect(0, 0, videoItem->size().width(), 0219 videoItem->size().height()); 0220 0221 QPointF center = videoItem->boundingRect().center(); 0222 videoItem->setTransformOriginPoint(center); 0223 videoItem->setRotation(videoOrientation); 0224 0225 videoView->fitInView(videoItem, Qt::KeepAspectRatio); 0226 videoView->centerOn(videoItem); 0227 videoView->raise(); 0228 }; 0229 0230 int videoMediaOrientation() const 0231 { 0232 int orientation = 0; 0233 QVariant val = player->metaData().value(QMediaMetaData::Orientation); 0234 0235 if (!val.isNull()) 0236 { 0237 orientation = val.toInt(); 0238 } 0239 0240 return orientation; 0241 }; 0242 0243 void setVideoItemOrientation(int orientation) 0244 { 0245 videoOrientation = orientation; 0246 adjustVideoSize(); 0247 }; 0248 }; 0249 0250 MediaPlayerView::MediaPlayerView(QWidget* const parent) 0251 : QStackedWidget(parent), 0252 d (new Private) 0253 { 0254 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0255 0256 const int spacing = qMin(QApplication::style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing), 0257 QApplication::style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing)); 0258 0259 d->prevAction = new QAction(QIcon::fromTheme(QLatin1String("go-previous")), 0260 i18nc("go to previous image", "Back"), this); 0261 d->nextAction = new QAction(QIcon::fromTheme(QLatin1String("go-next")), 0262 i18nc("go to next image", "Forward"), this); 0263 d->playAction = new QAction(QIcon::fromTheme(QLatin1String("media-playback-start")), 0264 i18nc("pause/play video", "Pause/Play"), this); 0265 d->grabAction = new QAction(QIcon::fromTheme(QLatin1String("view-preview")), 0266 i18nc("capture video frame", "Capture"), this); 0267 0268 d->errorView = new QFrame(this); 0269 QLabel* const errorMsg = new QLabel(i18n("An error has occurred with the media player..."), this); 0270 0271 errorMsg->setAlignment(Qt::AlignCenter); 0272 d->errorView->setFrameStyle(QFrame::StyledPanel | QFrame::Plain); 0273 d->errorView->setLineWidth(1); 0274 0275 QVBoxLayout* const vbox1 = new QVBoxLayout(d->errorView); 0276 vbox1->addWidget(errorMsg, 10); 0277 vbox1->setContentsMargins(QMargins()); 0278 vbox1->setSpacing(spacing); 0279 0280 insertWidget(Private::ErrorView, d->errorView); 0281 0282 // -------------------------------------------------------------------------- 0283 0284 d->playerView = new QFrame(this); 0285 d->videoScene = new QGraphicsScene(this); 0286 d->videoView = new QGraphicsView(d->videoScene); 0287 d->videoView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0288 d->videoView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0289 d->videoView->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); 0290 d->videoItem = new QGraphicsVideoItem(); 0291 d->player = new QMediaPlayer(this); 0292 d->audio = new QAudioOutput; 0293 d->player->setAudioOutput(d->audio); 0294 d->player->setVideoOutput(d->videoItem); 0295 d->videoScene->addItem(d->videoItem); 0296 0297 d->playerView->setFrameStyle(QFrame::StyledPanel | QFrame::Plain); 0298 d->playerView->setLineWidth(1); 0299 0300 d->videoItem->setAspectRatioMode(Qt::IgnoreAspectRatio); 0301 d->videoView->setMouseTracking(true); 0302 0303 DHBox* const hbox = new DHBox(this); 0304 d->slider = new QSlider(Qt::Horizontal, hbox); 0305 d->slider->setStyle(new PlayerVideoStyle()); 0306 d->slider->setRange(0, 0); 0307 d->tlabel = new QLabel(hbox); 0308 d->tlabel->setText(QLatin1String("00:00:00 / 00:00:00")); 0309 d->loopPlay = new QPushButton(hbox); 0310 d->loopPlay->setIcon(QIcon::fromTheme(QLatin1String("media-playlist-normal"))); 0311 d->loopPlay->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); 0312 d->loopPlay->setToolTip(i18n("Toggle playing in a loop")); 0313 d->loopPlay->setFocusPolicy(Qt::NoFocus); 0314 d->loopPlay->setMinimumSize(22, 22); 0315 d->loopPlay->setCheckable(true); 0316 QLabel* const spk = new QLabel(hbox); 0317 spk->setPixmap(QIcon::fromTheme(QLatin1String("audio-volume-high")).pixmap(22, 22)); 0318 d->volume = new QSlider(Qt::Horizontal, hbox); 0319 d->volume->setRange(0, 100); 0320 d->volume->setValue(50); 0321 0322 hbox->setStretchFactor(d->slider, 10); 0323 hbox->setContentsMargins(0, 0, 0, spacing); 0324 hbox->setSpacing(spacing); 0325 0326 QVBoxLayout* const vbox2 = new QVBoxLayout(d->playerView); 0327 vbox2->addWidget(d->videoView, 10); 0328 vbox2->addWidget(hbox, 0); 0329 vbox2->setContentsMargins(QMargins()); 0330 vbox2->setSpacing(spacing); 0331 0332 insertWidget(Private::PlayerView, d->playerView); 0333 0334 d->toolBar = new QToolBar(this); 0335 d->toolBar->addAction(d->prevAction); 0336 d->toolBar->addAction(d->nextAction); 0337 d->toolBar->addAction(d->playAction); 0338 d->toolBar->addAction(d->grabAction); 0339 d->toolBar->setStyleSheet(toolButtonStyleSheet()); 0340 0341 setPreviewMode(Private::PlayerView); 0342 0343 d->errorView->installEventFilter(new MediaPlayerMouseClickFilter(this)); 0344 d->videoView->installEventFilter(new MediaPlayerMouseClickFilter(this)); 0345 d->playerView->installEventFilter(this); 0346 0347 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0348 KConfigGroup group = config->group(QLatin1String("Media Player Settings")); 0349 int volume = group.readEntry("Volume", 50); 0350 0351 d->volume->setValue(volume); 0352 d->audio->setVolume(volume / 100.0F); 0353 0354 // -------------------------------------------------------------------------- 0355 0356 connect(ThemeManager::instance(), SIGNAL(signalThemeChanged()), 0357 this, SLOT(slotThemeChanged())); 0358 0359 connect(d->prevAction, SIGNAL(triggered()), 0360 this, SIGNAL(signalPrevItem())); 0361 0362 connect(d->nextAction, SIGNAL(triggered()), 0363 this, SIGNAL(signalNextItem())); 0364 0365 connect(d->playAction, SIGNAL(triggered()), 0366 this, SLOT(slotPausePlay())); 0367 0368 connect(d->grabAction, SIGNAL(triggered()), 0369 this, SLOT(slotCapture())); 0370 0371 connect(d->slider, SIGNAL(sliderMoved(int)), 0372 this, SLOT(slotPosition(int))); 0373 0374 connect(d->slider, SIGNAL(valueChanged(int)), 0375 this, SLOT(slotPosition(int))); 0376 0377 connect(d->volume, SIGNAL(valueChanged(int)), 0378 this, SLOT(slotVolumeChanged(int))); 0379 0380 connect(d->loopPlay, SIGNAL(toggled(bool)), 0381 this, SLOT(slotLoopToggled(bool))); 0382 0383 connect(d->player, SIGNAL(playbackStateChanged(QMediaPlayer::PlaybackState)), 0384 this, SLOT(slotPlayerStateChanged(QMediaPlayer::PlaybackState))); 0385 0386 connect(d->player, SIGNAL(positionChanged(qint64)), 0387 this, SLOT(slotPositionChanged(qint64))); 0388 0389 connect(d->player, SIGNAL(durationChanged(qint64)), 0390 this, SLOT(slotDurationChanged(qint64))); 0391 0392 connect(d->player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), 0393 this, SLOT(slotMediaStatusChanged(QMediaPlayer::MediaStatus))); 0394 0395 connect(d->player, SIGNAL(errorOccurred(QMediaPlayer::Error,QString)), 0396 this, SLOT(slotHandlePlayerError(QMediaPlayer::Error,QString))); 0397 0398 connect(d->videoItem, SIGNAL(nativeSizeChanged(QSizeF)), 0399 this, SLOT(slotNativeSizeChanged())); 0400 } 0401 0402 MediaPlayerView::~MediaPlayerView() 0403 { 0404 escapePreview(); 0405 0406 delete d; 0407 } 0408 0409 void MediaPlayerView::setInfoInterface(DInfoInterface* const iface) 0410 { 0411 d->iface = iface; 0412 } 0413 0414 void MediaPlayerView::reload() 0415 { 0416 d->player->stop(); 0417 d->player->setSource(d->currentItem); 0418 d->player->play(); 0419 } 0420 0421 void MediaPlayerView::slotPlayerStateChanged(QMediaPlayer::PlaybackState newState) 0422 { 0423 if (newState == QMediaPlayer::PlayingState) 0424 { 0425 int rotate = d->videoMediaOrientation(); 0426 0427 qCDebug(DIGIKAM_GENERAL_LOG) << "Found video orientation with QtMultimedia:" 0428 << rotate; 0429 0430 rotate = (-rotate) + d->videoOrientation; 0431 0432 if ((rotate > 270) || (rotate < 0)) 0433 { 0434 rotate = d->videoOrientation; 0435 } 0436 0437 d->setVideoItemOrientation(rotate); 0438 0439 d->playAction->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause"))); 0440 } 0441 else 0442 { 0443 d->playAction->setIcon(QIcon::fromTheme(QLatin1String("media-playback-start"))); 0444 0445 if ( 0446 (newState == QMediaPlayer::StoppedState) && 0447 (d->player->error() != QMediaPlayer::NoError) 0448 ) 0449 { 0450 setPreviewMode(Private::ErrorView); 0451 } 0452 0453 if ( 0454 (newState == QMediaPlayer::StoppedState) && 0455 (d->player->mediaStatus() == QMediaPlayer::EndOfMedia) 0456 ) 0457 { 0458 qCDebug(DIGIKAM_GENERAL_LOG) << "Play video with QtMultimedia completed:" << d->player->source(); 0459 0460 if (d->player->error() != QMediaPlayer::NoError) 0461 { 0462 setPreviewMode(Private::ErrorView); 0463 } 0464 } 0465 } 0466 } 0467 0468 void MediaPlayerView::slotMediaStatusChanged(QMediaPlayer::MediaStatus newStatus) 0469 { 0470 if (newStatus == QMediaPlayer::InvalidMedia) 0471 { 0472 setPreviewMode(Private::ErrorView); 0473 } 0474 } 0475 0476 void MediaPlayerView::escapePreview() 0477 { 0478 d->player->stop(); 0479 QString dummy = QStandardPaths::locate(QStandardPaths::GenericDataLocation, 0480 QLatin1String("digikam/data/video-digikam.mp4")); 0481 d->player->setSource(QUrl::fromLocalFile(dummy)); 0482 } 0483 0484 void MediaPlayerView::slotThemeChanged() 0485 { 0486 QPalette palette; 0487 palette.setColor(d->errorView->backgroundRole(), qApp->palette().color(QPalette::Base)); 0488 d->errorView->setPalette(palette); 0489 0490 QPalette palette2; 0491 palette2.setColor(d->playerView->backgroundRole(), qApp->palette().color(QPalette::Base)); 0492 d->playerView->setPalette(palette2); 0493 } 0494 0495 void MediaPlayerView::slotEscapePressed() 0496 { 0497 Q_EMIT signalEscapePreview(); 0498 } 0499 0500 void MediaPlayerView::slotRotateVideo() 0501 { 0502 if (d->player->isPlaying()) 0503 { 0504 int orientation = 0; 0505 0506 switch (d->videoOrientation) 0507 { 0508 case 0: 0509 { 0510 orientation = 90; 0511 break; 0512 } 0513 0514 case 90: 0515 { 0516 orientation = 180; 0517 break; 0518 } 0519 0520 case 180: 0521 { 0522 orientation = 270; 0523 break; 0524 } 0525 0526 default: 0527 { 0528 orientation = 0; 0529 break; 0530 } 0531 } 0532 0533 d->setVideoItemOrientation(orientation); 0534 } 0535 } 0536 0537 void MediaPlayerView::slotPausePlay() 0538 { 0539 if (!d->player->isPlaying()) 0540 { 0541 d->player->play(); 0542 return; 0543 } 0544 0545 d->player->pause(); 0546 } 0547 0548 void MediaPlayerView::slotCapture() 0549 { 0550 if (d->player->playbackState() != QMediaPlayer::StoppedState) 0551 { 0552 int capturePosition = d->player->position(); 0553 QVideoSink* const sink = d->player->videoSink(); 0554 QVideoFrame frame = sink->videoFrame(); 0555 QImage image = frame.toImage(); 0556 0557 if (!image.isNull() && d->currentItem.isValid()) 0558 { 0559 QFileInfo info(d->currentItem.toLocalFile()); 0560 QString tempPath = QString::fromUtf8("%1/%2-%3.digikamtempfile.jpg") 0561 .arg(info.path()) 0562 .arg(info.baseName()) 0563 .arg(capturePosition); 0564 0565 if (image.save(tempPath, "JPG", 100)) 0566 { 0567 QScopedPointer<DMetadata> meta(new DMetadata); 0568 0569 if (meta->load(tempPath)) 0570 { 0571 QDateTime dateTime; 0572 MetaEngine::ImageOrientation orientation = MetaEngine::ORIENTATION_NORMAL; 0573 0574 if (d->iface) 0575 { 0576 DItemInfo dinfo(d->iface->itemInfo(d->currentItem)); 0577 0578 dateTime = dinfo.dateTime(); 0579 orientation = (MetaEngine::ImageOrientation)dinfo.orientation(); 0580 } 0581 else 0582 { 0583 QScopedPointer<DMetadata> meta2(new DMetadata); 0584 0585 if (meta2->load(d->currentItem.toLocalFile())) 0586 { 0587 dateTime = meta2->getItemDateTime(); 0588 orientation = meta2->getItemOrientation(); 0589 } 0590 } 0591 0592 if (dateTime.isValid()) 0593 { 0594 dateTime = dateTime.addMSecs(capturePosition); 0595 } 0596 else 0597 { 0598 dateTime = QDateTime::currentDateTime(); 0599 } 0600 0601 if (orientation == MetaEngine::ORIENTATION_UNSPECIFIED) 0602 { 0603 orientation = MetaEngine::ORIENTATION_NORMAL; 0604 } 0605 0606 meta->setImageDateTime(dateTime, true); 0607 meta->setItemDimensions(image.size()); 0608 meta->setItemOrientation(orientation); 0609 meta->save(tempPath, true); 0610 } 0611 0612 QString finalPath = QString::fromUtf8("%1/%2-%3.jpg") 0613 .arg(info.path()) 0614 .arg(info.baseName()) 0615 .arg(capturePosition); 0616 0617 if (QFile::rename(tempPath, finalPath)) 0618 { 0619 if (d->iface) 0620 { 0621 d->iface->slotMetadataChangedForUrl(QUrl::fromLocalFile(finalPath)); 0622 } 0623 } 0624 else 0625 { 0626 QFile::remove(tempPath); 0627 } 0628 } 0629 } 0630 } 0631 } 0632 0633 int MediaPlayerView::previewMode() 0634 { 0635 return indexOf(currentWidget()); 0636 } 0637 0638 void MediaPlayerView::setPreviewMode(int mode) 0639 { 0640 if ((mode != Private::ErrorView) && (mode != Private::PlayerView)) 0641 { 0642 return; 0643 } 0644 0645 setCurrentIndex(mode); 0646 0647 d->toolBar->adjustSize(); 0648 d->toolBar->raise(); 0649 } 0650 0651 void MediaPlayerView::setCurrentItem(const QUrl& url, bool hasPrevious, bool hasNext) 0652 { 0653 d->prevAction->setEnabled(hasPrevious); 0654 d->nextAction->setEnabled(hasNext); 0655 d->adjustVideoSize(); 0656 0657 if (url.isEmpty()) 0658 { 0659 d->player->stop(); 0660 d->currentItem = url; 0661 0662 return; 0663 } 0664 0665 if ( 0666 (d->currentItem == url) && 0667 ( 0668 (d->player->playbackState() == QMediaPlayer::PlayingState) || 0669 (d->player->playbackState() == QMediaPlayer::PausedState) 0670 ) 0671 ) 0672 { 0673 return; 0674 } 0675 0676 d->player->stop(); 0677 int orientation = 0; 0678 d->currentItem = url; 0679 0680 if (d->iface) 0681 { 0682 DItemInfo info(d->iface->itemInfo(url)); 0683 0684 orientation = info.orientation(); 0685 } 0686 0687 switch (orientation) 0688 { 0689 case MetaEngine::ORIENTATION_ROT_90: 0690 case MetaEngine::ORIENTATION_ROT_90_HFLIP: 0691 case MetaEngine::ORIENTATION_ROT_90_VFLIP: 0692 { 0693 d->videoOrientation = 90; 0694 break; 0695 } 0696 0697 case MetaEngine::ORIENTATION_ROT_180: 0698 { 0699 d->videoOrientation = 180; 0700 break; 0701 } 0702 0703 case MetaEngine::ORIENTATION_ROT_270: 0704 { 0705 d->videoOrientation = 270; 0706 break; 0707 } 0708 0709 default: 0710 { 0711 d->videoOrientation = 0; 0712 break; 0713 } 0714 } 0715 0716 d->player->setSource(d->currentItem); 0717 setPreviewMode(Private::PlayerView); 0718 d->player->play(); 0719 0720 qCDebug(DIGIKAM_GENERAL_LOG) << "Play video with QtMultimedia started:" << d->player->source(); 0721 } 0722 0723 void MediaPlayerView::slotPositionChanged(qint64 position) 0724 { 0725 if ((d->sliderTime < position) && 0726 ((d->sliderTime + 100) > position)) 0727 { 0728 return; 0729 } 0730 0731 d->sliderTime = position; 0732 0733 if (!d->slider->isSliderDown()) 0734 { 0735 d->slider->blockSignals(true); 0736 d->slider->setValue(position); 0737 d->slider->blockSignals(false); 0738 } 0739 0740 d->tlabel->setText(QString::fromLatin1("%1 / %2") 0741 .arg(QTime(0, 0, 0).addMSecs(position).toString(QLatin1String("HH:mm:ss"))) 0742 .arg(QTime(0, 0, 0).addMSecs(d->slider->maximum()).toString(QLatin1String("HH:mm:ss")))); 0743 } 0744 0745 void MediaPlayerView::slotVolumeChanged(int volume) 0746 { 0747 d->audio->setVolume(volume / 100.0F); 0748 0749 if (objectName() != QLatin1String("main_media_player")) 0750 { 0751 return; 0752 } 0753 0754 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0755 KConfigGroup group = config->group(QLatin1String("Media Player Settings")); 0756 group.writeEntry("Volume", volume); 0757 } 0758 0759 void MediaPlayerView::slotLoopToggled(bool loop) 0760 { 0761 if (loop) 0762 { 0763 d->loopPlay->setIcon(QIcon::fromTheme(QLatin1String("media-playlist-repeat"))); 0764 d->player->setLoops(QMediaPlayer::Infinite); 0765 } 0766 else 0767 { 0768 d->loopPlay->setIcon(QIcon::fromTheme(QLatin1String("media-playlist-normal"))); 0769 d->player->setLoops(QMediaPlayer::Once); 0770 } 0771 } 0772 0773 void MediaPlayerView::slotDurationChanged(qint64 duration) 0774 { 0775 qint64 max = qMax((qint64)1, duration); 0776 d->slider->setRange(0, max); 0777 } 0778 0779 void MediaPlayerView::slotPosition(int position) 0780 { 0781 if (d->player->isSeekable()) 0782 { 0783 d->player->setPosition((qint64)position); 0784 } 0785 } 0786 0787 void MediaPlayerView::slotHandlePlayerError(QMediaPlayer::Error /*error*/, const QString& errStr) 0788 { 0789 setPreviewMode(Private::ErrorView); 0790 0791 qCDebug(DIGIKAM_GENERAL_LOG) << "QtMultimedia Error: " << errStr; 0792 } 0793 0794 void MediaPlayerView::slotNativeSizeChanged() 0795 { 0796 d->adjustVideoSize(); 0797 } 0798 0799 bool MediaPlayerView::eventFilter(QObject* watched, QEvent* event) 0800 { 0801 if ((watched == d->playerView) && (event->type() == QEvent::Resize)) 0802 { 0803 d->adjustVideoSize(); 0804 } 0805 0806 return QStackedWidget::eventFilter(watched, event); 0807 } 0808 0809 } // namespace Digikam 0810 0811 #include "mediaplayerview.moc" 0812 0813 #include "moc_mediaplayerview.cpp"