File indexing completed on 2024-04-28 15:40:29
0001 // SPDX-FileCopyrightText: 2021 Henner Zeller <h.zeller@acm.org> 0002 // SPDX-FileCopyrightText: 2021 Jesper K. Pedersen <blackie@kde.org> 0003 // SPDX-FileCopyrightText: 2021-2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at> 0004 // 0005 // SPDX-License-Identifier: GPL-2.0-or-later 0006 0007 #include "VLCDisplay.h" 0008 #include "Logging.h" 0009 #include "VideoToolBar.h" 0010 0011 #include <DB/ImageInfo.h> 0012 0013 #include <QDebug> 0014 #include <QGuiApplication> 0015 #include <QLabel> 0016 #include <QScreen> 0017 #include <QSlider> 0018 #include <QTimer> 0019 #include <QVBoxLayout> 0020 0021 #include <vlc/libvlc_media_player.h> 0022 #include <vlc/libvlc_version.h> 0023 0024 Viewer::VLCDisplay::VLCDisplay(QWidget *parent) 0025 : Viewer::VideoDisplay(parent) 0026 { 0027 QVBoxLayout *layout = new QVBoxLayout(this); 0028 m_videoWidget = new QWidget(this); 0029 layout->addWidget(m_videoWidget, 1); 0030 0031 m_videoToolBar = new VideoToolBar; 0032 layout->addWidget(m_videoToolBar); 0033 0034 m_poller = new QTimer(this); 0035 0036 setupVLC(); 0037 0038 connect(m_poller, &QTimer::timeout, this, &Viewer::VLCDisplay::updateInterface); 0039 connect(m_videoToolBar, &VideoToolBar::positionChanged, this, &VLCDisplay::setPosition); 0040 connect(m_videoToolBar, &VideoToolBar::volumeChanged, this, &VLCDisplay::changeVolume); 0041 connect(m_videoToolBar, &VideoToolBar::muted, this, [this](bool b) { 0042 libvlc_audio_set_mute(m_player, b); 0043 }); 0044 } 0045 0046 Viewer::VLCDisplay::~VLCDisplay() 0047 { 0048 if (VLCDisplay::isPlaying()) { 0049 qCWarning(ViewerLog) << "VLCDisplay is deleted while video is still playing! Please file a bug with KPhotoAlbum!"; 0050 } 0051 releaseVLC(); 0052 } 0053 0054 void Viewer::VLCDisplay::changeVolume(int newVolume) 0055 { 0056 libvlc_audio_set_volume(m_player, newVolume); 0057 } 0058 0059 void Viewer::VLCDisplay::setPosition(int newPosition) 0060 { 0061 // It's possible that the vlc doesn't play anything 0062 // so check before 0063 libvlc_media_t *curMedia = libvlc_media_player_get_media(m_player); 0064 if (curMedia == nullptr) 0065 return; 0066 0067 float pos = (float)(newPosition) / (float)m_videoToolBar->maximum(); 0068 #if LIBVLC_VERSION_INT >= 0x04000000 0069 libvlc_media_player_set_position(m_player, pos, /*fastseek=*/true); 0070 #else 0071 libvlc_media_player_set_position(m_player, pos); 0072 #endif 0073 } 0074 0075 void Viewer::VLCDisplay::playPause() 0076 { 0077 libvlc_media_player_set_pause(m_player, isPaused() ? 0 : 1); 0078 } 0079 0080 void Viewer::VLCDisplay::updateInterface() 0081 { 0082 libvlc_media_t *curMedia = libvlc_media_player_get_media(m_player); 0083 if (!curMedia || libvlc_media_get_state(m_media) == libvlc_Ended) { 0084 m_poller->stop(); 0085 Q_EMIT stopped(); 0086 return; 0087 } 0088 0089 const int currentPos 0090 = libvlc_media_player_get_position(m_player) * m_videoToolBar->maximum(); 0091 const auto length = libvlc_media_player_get_length(m_player); 0092 m_videoToolBar->setRange(0, length); 0093 m_videoToolBar->setPosition(currentPos); 0094 m_videoToolBar->setVolume(libvlc_audio_get_volume(m_player)); 0095 m_videoToolBar->setMuted(libvlc_audio_get_mute(m_player)); 0096 } 0097 0098 bool Viewer::VLCDisplay::setImageImpl(DB::ImageInfoPtr info, bool /*forward*/) 0099 { 0100 if (m_media) { 0101 libvlc_media_release(m_media); 0102 } 0103 m_media = libvlc_media_new_path(m_vlcInstance, info->fileName().absolute().toUtf8().data()); 0104 0105 libvlc_media_player_set_media(m_player, m_media); 0106 0107 int windid = m_videoWidget->winId(); 0108 libvlc_media_player_set_xwindow(m_player, windid); 0109 0110 libvlc_media_player_play(m_player); 0111 m_poller->start(100); 0112 0113 return true; 0114 } 0115 0116 bool Viewer::VLCDisplay::isPaused() const 0117 { 0118 return libvlc_media_get_state(m_media) == libvlc_Paused; 0119 } 0120 0121 void Viewer::VLCDisplay::stop() 0122 { 0123 #if LIBVLC_VERSION_INT >= 0x04000000 0124 libvlc_media_player_stop_async(m_player); 0125 #else 0126 libvlc_media_player_stop(m_player); 0127 #endif 0128 m_poller->stop(); 0129 } 0130 0131 void Viewer::VLCDisplay::rotate(const DB::ImageInfoPtr &info) 0132 { 0133 m_info = info; 0134 libvlc_time_t offset = 0; 0135 if (m_vlcInstance) 0136 offset = libvlc_media_player_get_time(m_player); 0137 0138 releaseVLC(); 0139 setupVLC(); 0140 0141 if (m_info) 0142 setImage(m_info, true); 0143 0144 setPosition(offset); 0145 } 0146 0147 void Viewer::VLCDisplay::releaseVLC() 0148 { 0149 if (!m_vlcInstance) 0150 return; 0151 0152 stop(); 0153 if (m_media) { 0154 libvlc_media_release(m_media); 0155 m_media = nullptr; 0156 } 0157 libvlc_media_player_release(m_player); 0158 libvlc_release(m_vlcInstance); 0159 } 0160 0161 void Viewer::VLCDisplay::setupVLC() 0162 { 0163 if (m_info && !m_info->isNull() && m_info->angle() != 0) { 0164 constexpr int BUF_SIZE = 64; 0165 char buf[BUF_SIZE]; 0166 snprintf(buf, BUF_SIZE, "--video-filter=transform{type=%d}", m_info->angle()); 0167 0168 const char *vlc_args[] = { "--verbose=2", // be much more verbose then normal for debugging purpose 0169 buf }; 0170 m_vlcInstance = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args); 0171 } else 0172 m_vlcInstance = libvlc_new(0, {}); 0173 0174 m_player = libvlc_media_player_new(m_vlcInstance); 0175 } 0176 0177 bool Viewer::VLCDisplay::isPlaying() const 0178 { 0179 return m_media && libvlc_media_get_state(m_media) == libvlc_Playing; 0180 } 0181 0182 QImage Viewer::VLCDisplay::screenShoot() 0183 { 0184 return QGuiApplication::primaryScreen()->grabWindow(m_videoWidget->winId()).toImage(); 0185 } 0186 0187 void Viewer::VLCDisplay::relativeSeek(int msec) 0188 { 0189 setPosition(libvlc_media_player_get_time(m_player) + msec); 0190 } 0191 0192 void Viewer::VLCDisplay::restart() 0193 { 0194 setImageImpl(m_info, true); 0195 } 0196 0197 #include "moc_VLCDisplay.cpp"