File indexing completed on 2024-05-12 08:54:15
0001 /* 0002 SPDX-FileCopyrightText: 2007 Jean-Baptiste Mardelle <jb@kdenlive.org> 0003 0004 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "monitormanager.h" 0008 #include "core.h" 0009 #include "doc/kdenlivedoc.h" 0010 #include "kdenlivesettings.h" 0011 #include "mainwindow.h" 0012 #include "timeline2/view/timelinewidget.h" 0013 0014 #include <mlt++/Mlt.h> 0015 0016 #include "klocalizedstring.h" 0017 #include <KDualAction> 0018 #include <kwidgetsaddons_version.h> 0019 0020 #include "kdenlive_debug.h" 0021 #include <QObject> 0022 #include <dialogs/timeremap.h> 0023 #include <timeline2/view/timelinecontroller.h> 0024 0025 const double MonitorManager::speedArray[6] = {1., 1.5, 2., 3., 5.5, 10.}; 0026 0027 MonitorManager::MonitorManager(QObject *parent) 0028 : QObject(parent) 0029 , m_activeMultiTrack(-1) 0030 0031 { 0032 setupActions(); 0033 refreshTimer.setSingleShot(true); 0034 refreshTimer.setInterval(200); 0035 connect(&refreshTimer, &QTimer::timeout, this, &MonitorManager::forceProjectMonitorRefresh); 0036 connect(pCore.get(), &Core::monitorProfileUpdated, this, [&]() { 0037 QAction *prog = pCore->window()->actionCollection()->action(QStringLiteral("mlt_progressive")); 0038 if (prog) { 0039 prog->setEnabled(!pCore->getProjectProfile().progressive()); 0040 slotProgressivePlay(prog->isChecked()); 0041 } 0042 }); 0043 } 0044 0045 QAction *MonitorManager::getAction(const QString &name) 0046 { 0047 return pCore->window()->action(name.toUtf8().constData()); 0048 } 0049 0050 void MonitorManager::initMonitors(Monitor *clipMonitor, Monitor *projectMonitor) 0051 { 0052 m_clipMonitor = clipMonitor; 0053 m_projectMonitor = projectMonitor; 0054 m_monitorsList.append(clipMonitor); 0055 m_monitorsList.append(projectMonitor); 0056 } 0057 0058 void MonitorManager::appendMonitor(AbstractMonitor *monitor) 0059 { 0060 if (!m_monitorsList.contains(monitor)) { 0061 m_monitorsList.append(monitor); 0062 } 0063 } 0064 0065 void MonitorManager::removeMonitor(AbstractMonitor *monitor) 0066 { 0067 m_monitorsList.removeAll(monitor); 0068 } 0069 0070 AbstractMonitor *MonitorManager::monitor(Kdenlive::MonitorId monitorName) 0071 { 0072 AbstractMonitor *monitor = nullptr; 0073 for (auto &i : m_monitorsList) { 0074 if (i->id() == monitorName) { 0075 monitor = i; 0076 } 0077 } 0078 return monitor; 0079 } 0080 0081 void MonitorManager::setConsumerProperty(const QString &name, const QString &value) 0082 { 0083 if (m_clipMonitor) { 0084 m_clipMonitor->setConsumerProperty(name, value); 0085 } 0086 if (m_projectMonitor) { 0087 m_projectMonitor->setConsumerProperty(name, value); 0088 } 0089 } 0090 0091 void MonitorManager::lockMonitor(Kdenlive::MonitorId name, bool lock) 0092 { 0093 Q_UNUSED(name) 0094 if (lock) { 0095 m_refreshMutex.lock(); 0096 } else { 0097 m_refreshMutex.unlock(); 0098 } 0099 } 0100 0101 void MonitorManager::focusProjectMonitor() 0102 { 0103 if (!m_projectMonitor->isActive()) { 0104 activateMonitor(Kdenlive::ProjectMonitor); 0105 } else { 0106 // Force raise 0107 m_projectMonitor->parentWidget()->raise(); 0108 } 0109 } 0110 0111 void MonitorManager::refreshProjectRange(QPair<int, int> range, bool forceRefresh) 0112 { 0113 if (m_projectMonitor->position() >= range.first && m_projectMonitor->position() <= range.second) { 0114 if (forceRefresh) { 0115 m_projectMonitor->refreshMonitor(false); 0116 } else { 0117 m_projectMonitor->refreshMonitorIfActive(); 0118 } 0119 } 0120 } 0121 0122 void MonitorManager::refreshProjectMonitor(bool directUpdate) 0123 { 0124 m_projectMonitor->refreshMonitor(directUpdate); 0125 } 0126 0127 void MonitorManager::refreshClipMonitor(bool directUpdate) 0128 { 0129 m_clipMonitor->refreshMonitor(directUpdate); 0130 } 0131 0132 void MonitorManager::forceProjectMonitorRefresh() 0133 { 0134 m_projectMonitor->forceMonitorRefresh(); 0135 } 0136 0137 bool MonitorManager::projectMonitorVisible() const 0138 { 0139 return (m_projectMonitor->monitorIsFullScreen() || (m_projectMonitor->isVisible() && !m_projectMonitor->visibleRegion().isEmpty())); 0140 } 0141 0142 bool MonitorManager::clipMonitorVisible() const 0143 { 0144 return (m_clipMonitor->monitorIsFullScreen() || (m_clipMonitor->isVisible() && !m_clipMonitor->visibleRegion().isEmpty())); 0145 } 0146 0147 void MonitorManager::refreshMonitors() 0148 { 0149 if (m_activeMonitor) { 0150 if (m_activeMonitor == m_clipMonitor) { 0151 activateMonitor(Kdenlive::ProjectMonitor); 0152 refreshProjectMonitor(true); 0153 activateMonitor(Kdenlive::ClipMonitor); 0154 refreshClipMonitor(true); 0155 } else { 0156 bool playing = m_projectMonitor->isPlaying(); 0157 if (playing) { 0158 m_projectMonitor->switchPlay(false); 0159 } 0160 activateMonitor(Kdenlive::ClipMonitor); 0161 refreshClipMonitor(true); 0162 activateMonitor(Kdenlive::ProjectMonitor); 0163 refreshProjectMonitor(true); 0164 if (playing) { 0165 m_projectMonitor->switchPlay(true); 0166 } 0167 } 0168 } 0169 } 0170 0171 bool MonitorManager::activateMonitor(Kdenlive::MonitorId name, bool raiseMonitor) 0172 { 0173 if ((m_activeMonitor != nullptr) && m_activeMonitor->id() == name) { 0174 return true; 0175 } 0176 if (m_clipMonitor == nullptr || m_projectMonitor == nullptr) { 0177 return false; 0178 } 0179 QMutexLocker locker(&m_switchMutex); 0180 bool stopCurrent = m_activeMonitor != nullptr; 0181 for (int i = 0; i < m_monitorsList.count(); ++i) { 0182 if (m_monitorsList.at(i)->id() == name) { 0183 m_activeMonitor = m_monitorsList.at(i); 0184 } else if (stopCurrent) { 0185 m_monitorsList.at(i)->stop(); 0186 } 0187 } 0188 if (m_activeMonitor) { 0189 if (name == Kdenlive::ClipMonitor) { 0190 if (!m_clipMonitor->monitorIsFullScreen()) { 0191 if (raiseMonitor) { 0192 m_clipMonitor->parentWidget()->raise(); 0193 } 0194 } else { 0195 m_clipMonitor->fixFocus(); 0196 } 0197 // Set guides list to show guides 0198 m_clipMonitor->updateGuidesList(); 0199 if (!m_clipMonitor->isVisible()) { 0200 pCore->displayMessage(i18n("Do you want to <a href=\"#clipmonitor\">show the clip monitor</a> to view timeline?"), 0201 MessageType::InformationMessage); 0202 m_activeMonitor = m_projectMonitor; 0203 return false; 0204 } 0205 Q_EMIT updateOverlayInfos(name, KdenliveSettings::displayClipMonitorInfo()); 0206 m_projectMonitor->displayAudioMonitor(false); 0207 m_clipMonitor->displayAudioMonitor(true); 0208 } else if (name == Kdenlive::ProjectMonitor) { 0209 // Set guides list to show guides 0210 m_projectMonitor->updateGuidesList(); 0211 if (!m_projectMonitor->monitorIsFullScreen()) { 0212 if (raiseMonitor) { 0213 m_projectMonitor->parentWidget()->raise(); 0214 } 0215 } else { 0216 m_projectMonitor->fixFocus(); 0217 } 0218 if (!m_projectMonitor->isVisible()) { 0219 pCore->displayMessage(i18n("Do you want to <a href=\"#projectmonitor\">show the project monitor</a> to view timeline?"), 0220 MessageType::InformationMessage); 0221 m_activeMonitor = m_clipMonitor; 0222 return false; 0223 } 0224 Q_EMIT updateOverlayInfos(name, KdenliveSettings::displayProjectMonitorInfo()); 0225 m_clipMonitor->displayAudioMonitor(false); 0226 m_projectMonitor->displayAudioMonitor(true); 0227 } 0228 } 0229 Q_EMIT checkColorScopes(); 0230 return (m_activeMonitor != nullptr); 0231 } 0232 0233 void MonitorManager::resetDisplay() 0234 { 0235 m_projectMonitor->clearDisplay(); 0236 m_clipMonitor->clearDisplay(); 0237 } 0238 0239 bool MonitorManager::isActive(Kdenlive::MonitorId id) const 0240 { 0241 return m_activeMonitor ? m_activeMonitor->id() == id : false; 0242 } 0243 0244 void MonitorManager::slotSwitchMonitors(bool activateClip) 0245 { 0246 if (activateClip) { 0247 activateMonitor(Kdenlive::ClipMonitor); 0248 } else { 0249 activateMonitor(Kdenlive::ProjectMonitor); 0250 } 0251 } 0252 0253 void MonitorManager::stopActiveMonitor() 0254 { 0255 if (m_activeMonitor) { 0256 m_activeMonitor->stop(); 0257 } 0258 } 0259 0260 void MonitorManager::pauseActiveMonitor() 0261 { 0262 if (m_activeMonitor == m_clipMonitor) { 0263 m_clipMonitor->pause(); 0264 } else if (m_activeMonitor == m_projectMonitor) { 0265 m_projectMonitor->pause(); 0266 } 0267 } 0268 0269 void MonitorManager::slotPlay() 0270 { 0271 if (m_activeMonitor) { 0272 m_activeMonitor->slotPlay(); 0273 } 0274 } 0275 0276 void MonitorManager::slotPause() 0277 { 0278 pauseActiveMonitor(); 0279 } 0280 0281 void MonitorManager::slotPlayZone() 0282 { 0283 if (m_activeMonitor == m_clipMonitor) { 0284 m_clipMonitor->slotPlayZone(); 0285 } else if (m_activeMonitor == m_projectMonitor) { 0286 m_projectMonitor->slotPlayZone(); 0287 } 0288 } 0289 0290 void MonitorManager::slotLoopZone() 0291 { 0292 if (m_activeMonitor == m_clipMonitor) { 0293 m_clipMonitor->slotLoopZone(); 0294 } else { 0295 m_projectMonitor->slotLoopZone(); 0296 } 0297 } 0298 0299 void MonitorManager::slotRewind(double speed) 0300 { 0301 if (m_activeMonitor) { 0302 m_activeMonitor->slotRewind(speed); 0303 } 0304 } 0305 0306 void MonitorManager::slotForward(double speed) 0307 { 0308 if (m_activeMonitor) { 0309 m_activeMonitor->slotForward(speed, true); 0310 } 0311 } 0312 0313 void MonitorManager::slotRewindOneFrame() 0314 { 0315 if (pCore->activeTool() == ToolType::SlipTool) { 0316 m_projectMonitor->slotTrimmingPos(-1); 0317 pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(-1, true); 0318 } else if (isTrimming()) { 0319 return; 0320 } else { 0321 if (m_activeMonitor == m_clipMonitor) { 0322 m_clipMonitor->slotRewindOneFrame(); 0323 } else if (m_activeMonitor == m_projectMonitor) { 0324 m_projectMonitor->slotRewindOneFrame(); 0325 } 0326 } 0327 } 0328 0329 void MonitorManager::slotForwardOneFrame() 0330 { 0331 if (pCore->activeTool() == ToolType::SlipTool) { 0332 m_projectMonitor->slotTrimmingPos(1); 0333 pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(1, true); 0334 } else if (isTrimming()) { 0335 return; 0336 } else { 0337 if (m_activeMonitor == m_clipMonitor) { 0338 m_clipMonitor->slotForwardOneFrame(); 0339 } else if (m_activeMonitor == m_projectMonitor) { 0340 m_projectMonitor->slotForwardOneFrame(); 0341 } 0342 } 0343 } 0344 0345 void MonitorManager::slotRewindOneSecond() 0346 { 0347 if (pCore->activeTool() == ToolType::SlipTool) { 0348 m_projectMonitor->slotTrimmingPos(-qRound(pCore->getCurrentFps())); 0349 pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(-qRound(pCore->getCurrentFps()), true); 0350 } else if (isTrimming()) { 0351 return; 0352 } else { 0353 if (m_activeMonitor == m_clipMonitor) { 0354 m_clipMonitor->slotRewindOneFrame(qRound(pCore->getCurrentFps())); 0355 } else if (m_activeMonitor == m_projectMonitor) { 0356 m_projectMonitor->slotRewindOneFrame(qRound(pCore->getCurrentFps())); 0357 } 0358 } 0359 } 0360 0361 void MonitorManager::slotForwardOneSecond() 0362 { 0363 if (pCore->activeTool() == ToolType::SlipTool) { 0364 m_projectMonitor->slotTrimmingPos(qRound(pCore->getCurrentFps())); 0365 pCore->window()->getCurrentTimeline()->model()->requestSlipSelection(qRound(pCore->getCurrentFps()), true); 0366 } else if (isTrimming()) { 0367 return; 0368 } else { 0369 if (m_activeMonitor == m_clipMonitor) { 0370 m_clipMonitor->slotForwardOneFrame(qRound(pCore->getCurrentFps())); 0371 } else if (m_activeMonitor == m_projectMonitor) { 0372 m_projectMonitor->slotForwardOneFrame(qRound(pCore->getCurrentFps())); 0373 } 0374 } 0375 } 0376 0377 void MonitorManager::slotStartMultiTrackMode() 0378 { 0379 getAction(QStringLiteral("monitor_multitrack"))->setEnabled(false); 0380 m_activeMultiTrack = pCore->window()->getCurrentTimeline()->controller()->activeTrack(); 0381 pCore->window()->getCurrentTimeline()->controller()->setMulticamIn(m_projectMonitor->position()); 0382 } 0383 0384 void MonitorManager::slotStopMultiTrackMode() 0385 { 0386 if (m_activeMultiTrack == -1) { 0387 return; 0388 } 0389 getAction(QStringLiteral("monitor_multitrack"))->setEnabled(true); 0390 pCore->window()->getCurrentTimeline()->controller()->setMulticamIn(-1); 0391 m_activeMultiTrack = -1; 0392 } 0393 0394 void MonitorManager::slotPerformMultiTrackMode() 0395 { 0396 if (m_activeMultiTrack == -1) { 0397 return; 0398 } 0399 pCore->window()->getCurrentTimeline()->controller()->processMultitrackOperation(m_activeMultiTrack, 0400 pCore->window()->getCurrentTimeline()->controller()->multicamIn); 0401 m_activeMultiTrack = pCore->window()->getCurrentTimeline()->controller()->activeTrack(); 0402 pCore->window()->getCurrentTimeline()->controller()->setMulticamIn(m_projectMonitor->position()); 0403 } 0404 0405 void MonitorManager::slotStart() 0406 { 0407 if (m_activeMonitor == m_clipMonitor) { 0408 m_clipMonitor->slotStart(); 0409 } else if (m_activeMonitor == m_projectMonitor) { 0410 m_projectMonitor->slotStart(); 0411 } 0412 } 0413 0414 void MonitorManager::slotEnd() 0415 { 0416 if (m_activeMonitor == m_clipMonitor) { 0417 m_clipMonitor->slotEnd(); 0418 } else if (m_activeMonitor == m_projectMonitor) { 0419 m_projectMonitor->slotEnd(); 0420 } 0421 } 0422 0423 void MonitorManager::resetProfiles() 0424 { 0425 if (m_clipMonitor) { 0426 m_clipMonitor->resetProfile(); 0427 } 0428 if (m_projectMonitor) { 0429 m_projectMonitor->resetProfile(); 0430 } 0431 } 0432 0433 void MonitorManager::resetConsumers(bool fullReset) 0434 { 0435 bool clipMonitorActive = m_clipMonitor->isActive(); 0436 m_clipMonitor->resetConsumer(fullReset); 0437 m_projectMonitor->resetConsumer(fullReset); 0438 if (clipMonitorActive) { 0439 refreshClipMonitor(); 0440 } else { 0441 refreshProjectMonitor(); 0442 } 0443 } 0444 0445 void MonitorManager::slotToggleEffectScene(bool enable) 0446 { 0447 if (m_activeMonitor) { 0448 static_cast<Monitor *>(m_activeMonitor)->enableEffectScene(enable); 0449 } 0450 } 0451 0452 void MonitorManager::slotUpdateAudioMonitoring() 0453 { 0454 if (m_clipMonitor) { 0455 m_clipMonitor->updateAudioForAnalysis(); 0456 } 0457 if (m_projectMonitor) { 0458 m_projectMonitor->updateAudioForAnalysis(); 0459 } 0460 } 0461 0462 void MonitorManager::clearScopeSource() 0463 { 0464 Q_EMIT clearScopes(); 0465 } 0466 0467 void MonitorManager::updateScopeSource() 0468 { 0469 Q_EMIT checkColorScopes(); 0470 } 0471 0472 AbstractMonitor *MonitorManager::activeMonitor() 0473 { 0474 if (m_activeMonitor) { 0475 return m_activeMonitor; 0476 } 0477 return nullptr; 0478 } 0479 0480 void MonitorManager::slotSwitchFullscreen() 0481 { 0482 if (m_activeMonitor) { 0483 m_activeMonitor->slotSwitchFullScreen(); 0484 } 0485 } 0486 0487 void MonitorManager::setupActions() 0488 { 0489 KDualAction *playAction = new KDualAction(i18n("Play"), i18n("Pause"), this); 0490 playAction->setInactiveIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); 0491 playAction->setActiveIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause"))); 0492 connect(playAction, &KDualAction::activeChangedByUser, this, &MonitorManager::slotPlay); 0493 pCore->window()->addAction(QStringLiteral("monitor_play"), playAction, Qt::Key_Space, QStringLiteral("navandplayback")); 0494 0495 QAction *monitorPause = new QAction(QIcon::fromTheme(QStringLiteral("media-playback-stop")), i18n("Pause"), this); 0496 connect(monitorPause, &QAction::triggered, this, &MonitorManager::slotPause); 0497 pCore->window()->addAction(QStringLiteral("monitor_pause"), monitorPause, Qt::Key_K, QStringLiteral("navandplayback")); 0498 0499 QAction *fullMonitor = new QAction(i18n("Switch Monitor Fullscreen"), this); 0500 fullMonitor->setIcon(QIcon::fromTheme(QStringLiteral("view-fullscreen"))); 0501 connect(fullMonitor, &QAction::triggered, this, &MonitorManager::slotSwitchFullscreen); 0502 pCore->window()->addAction(QStringLiteral("monitor_fullscreen"), fullMonitor, Qt::Key_F11, QStringLiteral("monitor")); 0503 0504 QAction *monitorZoomIn = new QAction(i18n("Zoom In Monitor"), this); 0505 monitorZoomIn->setIcon(QIcon::fromTheme(QStringLiteral("zoom-in"))); 0506 connect(monitorZoomIn, &QAction::triggered, this, &MonitorManager::slotZoomIn); 0507 pCore->window()->addAction(QStringLiteral("monitor_zoomin"), monitorZoomIn, {}, QStringLiteral("monitor")); 0508 0509 QAction *monitorZoomOut = new QAction(i18n("Zoom Out Monitor"), this); 0510 monitorZoomOut->setIcon(QIcon::fromTheme(QStringLiteral("zoom-out"))); 0511 connect(monitorZoomOut, &QAction::triggered, this, &MonitorManager::slotZoomOut); 0512 pCore->window()->addAction(QStringLiteral("monitor_zoomout"), monitorZoomOut, {}, QStringLiteral("monitor")); 0513 0514 QAction *monitorSeekBackward = new QAction(QIcon::fromTheme(QStringLiteral("media-seek-backward")), i18n("Rewind"), this); 0515 connect(monitorSeekBackward, &QAction::triggered, this, [&](bool) { MonitorManager::slotRewind(); }); 0516 pCore->window()->addAction(QStringLiteral("monitor_seek_backward"), monitorSeekBackward, Qt::Key_J, QStringLiteral("navandplayback")); 0517 0518 QAction *monitorSeekBackwardOneFrame = new QAction(QIcon::fromTheme(QStringLiteral("media-skip-backward")), i18n("Rewind 1 Frame"), this); 0519 connect(monitorSeekBackwardOneFrame, &QAction::triggered, this, &MonitorManager::slotRewindOneFrame); 0520 pCore->window()->addAction(QStringLiteral("monitor_seek_backward-one-frame"), monitorSeekBackwardOneFrame, Qt::Key_Left, QStringLiteral("navandplayback")); 0521 0522 QAction *monitorSeekBackwardOneSecond = new QAction(QIcon::fromTheme(QStringLiteral("media-skip-backward")), i18n("Rewind 1 Second"), this); 0523 connect(monitorSeekBackwardOneSecond, &QAction::triggered, this, &MonitorManager::slotRewindOneSecond); 0524 pCore->window()->addAction(QStringLiteral("monitor_seek_backward-one-second"), monitorSeekBackwardOneSecond, Qt::SHIFT | Qt::Key_Left, 0525 QStringLiteral("navandplayback")); 0526 0527 QAction *monitorSeekForward = new QAction(QIcon::fromTheme(QStringLiteral("media-seek-forward")), i18n("Forward"), this); 0528 connect(monitorSeekForward, &QAction::triggered, this, [&](bool) { MonitorManager::slotForward(); }); 0529 pCore->window()->addAction(QStringLiteral("monitor_seek_forward"), monitorSeekForward, Qt::Key_L, QStringLiteral("navandplayback")); 0530 0531 QAction *projectStart = new QAction(QIcon::fromTheme(QStringLiteral("go-first")), i18n("Go to Project Start"), this); 0532 connect(projectStart, &QAction::triggered, this, &MonitorManager::slotStart); 0533 pCore->window()->addAction(QStringLiteral("seek_start"), projectStart, Qt::CTRL | Qt::Key_Home, QStringLiteral("navandplayback")); 0534 0535 QAction *projectEnd = new QAction(QIcon::fromTheme(QStringLiteral("go-last")), i18n("Go to Project End"), this); 0536 connect(projectEnd, &QAction::triggered, this, &MonitorManager::slotEnd); 0537 pCore->window()->addAction(QStringLiteral("seek_end"), projectEnd, Qt::CTRL | Qt::Key_End, QStringLiteral("navandplayback")); 0538 0539 QAction *monitorSeekForwardOneFrame = new QAction(QIcon::fromTheme(QStringLiteral("media-skip-forward")), i18n("Forward 1 Frame"), this); 0540 connect(monitorSeekForwardOneFrame, &QAction::triggered, this, &MonitorManager::slotForwardOneFrame); 0541 pCore->window()->addAction(QStringLiteral("monitor_seek_forward-one-frame"), monitorSeekForwardOneFrame, Qt::Key_Right, QStringLiteral("navandplayback")); 0542 0543 QAction *monitorSeekForwardOneSecond = new QAction(QIcon::fromTheme(QStringLiteral("media-skip-forward")), i18n("Forward 1 Second"), this); 0544 connect(monitorSeekForwardOneSecond, &QAction::triggered, this, &MonitorManager::slotForwardOneSecond); 0545 pCore->window()->addAction(QStringLiteral("monitor_seek_forward-one-second"), monitorSeekForwardOneSecond, Qt::SHIFT | Qt::Key_Right, 0546 QStringLiteral("navandplayback")); 0547 0548 m_multiTrack = new QAction(QIcon::fromTheme(QStringLiteral("view-split-left-right")), i18n("Multitrack View"), this); 0549 m_multiTrack->setCheckable(true); 0550 connect(m_multiTrack, &QAction::triggered, this, [&](bool checked) { 0551 if (m_projectMonitor) { 0552 Q_EMIT m_projectMonitor->multitrackView(checked, true); 0553 } 0554 }); 0555 pCore->window()->addAction(QStringLiteral("monitor_multitrack"), m_multiTrack, Qt::Key_F12, QStringLiteral("monitor")); 0556 0557 QAction *performMultiTrackOperation = new QAction(QIcon::fromTheme(QStringLiteral("media-playback-pause")), i18n("Perform Multitrack Operation"), this); 0558 connect(performMultiTrackOperation, &QAction::triggered, this, &MonitorManager::slotPerformMultiTrackMode); 0559 pCore->window()->addAction(QStringLiteral("perform_multitrack_mode"), performMultiTrackOperation); 0560 0561 QAction *enableEditmode = new QAction(QIcon::fromTheme(QStringLiteral("transform-crop")), i18n("Show/Hide edit mode"), this); 0562 enableEditmode->setWhatsThis(xi18nc("@info:whatsthis", "Toggles edit mode (and the display of the object handles).")); 0563 enableEditmode->setCheckable(true); 0564 enableEditmode->setChecked(KdenliveSettings::showOnMonitorScene()); 0565 connect(enableEditmode, &QAction::triggered, this, &MonitorManager::slotToggleEffectScene); 0566 pCore->window()->addAction(QStringLiteral("monitor_editmode"), enableEditmode, {}, QStringLiteral("monitor")); 0567 0568 KSelectAction *interlace = new KSelectAction(i18n("Deinterlacer"), this); 0569 interlace->addAction(i18n("One Field (fast)")); 0570 interlace->addAction(i18n("Linear Blend (fast)")); 0571 interlace->addAction(i18n("YADIF - temporal only (good)")); 0572 interlace->addAction(i18n("YADIF - temporal + spacial (best)")); 0573 if (KdenliveSettings::mltdeinterlacer() == QLatin1String("linearblend")) { 0574 interlace->setCurrentItem(1); 0575 } else if (KdenliveSettings::mltdeinterlacer() == QLatin1String("yadif-nospatial")) { 0576 interlace->setCurrentItem(2); 0577 } else if (KdenliveSettings::mltdeinterlacer() == QLatin1String("yadif")) { 0578 interlace->setCurrentItem(3); 0579 } else { 0580 interlace->setCurrentItem(0); 0581 } 0582 connect(interlace, &KSelectAction::indexTriggered, this, &MonitorManager::slotSetDeinterlacer); 0583 pCore->window()->addAction(QStringLiteral("mlt_interlace"), interlace); 0584 pCore->window()->actionCollection()->setShortcutsConfigurable(interlace, false); 0585 0586 KSelectAction *interpol = new KSelectAction(i18n("Interpolation"), this); 0587 interpol->addAction(i18n("Nearest Neighbor (fast)")); 0588 interpol->addAction(i18n("Bilinear (good)")); 0589 interpol->addAction(i18n("Bicubic (better)")); 0590 interpol->addAction(i18n("Hyper/Lanczos (best)")); 0591 if (KdenliveSettings::mltinterpolation() == QLatin1String("bilinear")) { 0592 interpol->setCurrentItem(1); 0593 } else if (KdenliveSettings::mltinterpolation() == QLatin1String("bicubic")) { 0594 interpol->setCurrentItem(2); 0595 } else if (KdenliveSettings::mltinterpolation() == QLatin1String("hyper")) { 0596 interpol->setCurrentItem(3); 0597 } else { 0598 interpol->setCurrentItem(0); 0599 } 0600 connect(interpol, &KSelectAction::indexTriggered, this, &MonitorManager::slotSetInterpolation); 0601 pCore->window()->addAction(QStringLiteral("mlt_interpolation"), interpol); 0602 pCore->window()->actionCollection()->setShortcutsConfigurable(interpol, false); 0603 0604 QAction *progressive = new QAction(i18n("Progressive playback"), this); 0605 connect(progressive, &QAction::triggered, this, &MonitorManager::slotProgressivePlay); 0606 pCore->window()->addAction(QStringLiteral("mlt_progressive"), progressive); 0607 progressive->setCheckable(true); 0608 progressive->setChecked(KdenliveSettings::monitor_progressive()); 0609 0610 QAction *audioScrub = new QAction(i18n("Audio Scrubbing"), this); 0611 connect(audioScrub, &QAction::triggered, this, [&](bool enable) { KdenliveSettings::setAudio_scrub(enable); }); 0612 pCore->window()->addAction(QStringLiteral("mlt_scrub"), audioScrub); 0613 audioScrub->setCheckable(true); 0614 audioScrub->setChecked(KdenliveSettings::audio_scrub()); 0615 0616 m_muteAction = new KDualAction(i18n("Mute Monitor"), i18n("Unmute Monitor"), this); 0617 m_muteAction->setActiveIcon(QIcon::fromTheme(QStringLiteral("audio-volume-medium"))); 0618 m_muteAction->setInactiveIcon(QIcon::fromTheme(QStringLiteral("audio-volume-muted"))); 0619 connect(m_muteAction, &KDualAction::activeChangedByUser, this, &MonitorManager::slotMuteCurrentMonitor); 0620 pCore->window()->addAction(QStringLiteral("mlt_mute"), m_muteAction, {}, QStringLiteral("monitor")); 0621 0622 QAction *zoneStart = new QAction(QIcon::fromTheme(QStringLiteral("media-seek-backward")), i18n("Go to Zone Start"), this); 0623 connect(zoneStart, &QAction::triggered, this, &MonitorManager::slotZoneStart); 0624 pCore->window()->addAction(QStringLiteral("seek_zone_start"), zoneStart, Qt::SHIFT | Qt::Key_I, QStringLiteral("navandplayback")); 0625 0626 QAction *zoneEnd = new QAction(QIcon::fromTheme(QStringLiteral("media-seek-forward")), i18n("Go to Zone End"), this); 0627 connect(zoneEnd, &QAction::triggered, this, &MonitorManager::slotZoneEnd); 0628 pCore->window()->addAction(QStringLiteral("seek_zone_end"), zoneEnd, Qt::SHIFT | Qt::Key_O, QStringLiteral("navandplayback")); 0629 0630 QAction *markIn = new QAction(QIcon::fromTheme(QStringLiteral("zone-in")), i18n("Set Zone In"), this); 0631 connect(markIn, &QAction::triggered, this, &MonitorManager::slotSetInPoint); 0632 pCore->window()->addAction(QStringLiteral("mark_in"), markIn, Qt::Key_I); 0633 0634 QAction *markOut = new QAction(QIcon::fromTheme(QStringLiteral("zone-out")), i18n("Set Zone Out"), this); 0635 connect(markOut, &QAction::triggered, this, &MonitorManager::slotSetOutPoint); 0636 pCore->window()->addAction(QStringLiteral("mark_out"), markOut, Qt::Key_O); 0637 } 0638 0639 void MonitorManager::refreshIcons() 0640 { 0641 QList<QAction *> allMenus = this->findChildren<QAction *>(); 0642 for (int i = 0; i < allMenus.count(); i++) { 0643 QAction *m = allMenus.at(i); 0644 QIcon ic = m->icon(); 0645 if (ic.isNull() || ic.name().isEmpty()) { 0646 continue; 0647 } 0648 QIcon newIcon = QIcon::fromTheme(ic.name()); 0649 m->setIcon(newIcon); 0650 } 0651 } 0652 0653 void MonitorManager::slotSetDeinterlacer(int ix) 0654 { 0655 QString value; 0656 switch (ix) { 0657 0658 case 1: 0659 value = QStringLiteral("linearblend"); 0660 break; 0661 case 2: 0662 value = QStringLiteral("yadif-nospatial"); 0663 break; 0664 case 3: 0665 value = QStringLiteral("yadif"); 0666 break; 0667 default: 0668 value = QStringLiteral("onefield"); 0669 } 0670 KdenliveSettings::setMltdeinterlacer(value); 0671 setConsumerProperty(QStringLiteral("deinterlacer"), value); 0672 } 0673 0674 void MonitorManager::slotSetInterpolation(int ix) 0675 { 0676 QString value; 0677 switch (ix) { 0678 case 1: 0679 value = QStringLiteral("bilinear"); 0680 break; 0681 case 2: 0682 value = QStringLiteral("bicubic"); 0683 break; 0684 case 3: 0685 value = QStringLiteral("hyper"); 0686 break; 0687 default: 0688 value = QStringLiteral("nearest"); 0689 } 0690 KdenliveSettings::setMltinterpolation(value); 0691 setConsumerProperty(QStringLiteral("rescale"), value); 0692 } 0693 0694 void MonitorManager::slotMuteCurrentMonitor(bool active) 0695 { 0696 m_activeMonitor->mute(active); 0697 } 0698 0699 void MonitorManager::slotProgressivePlay(bool active) 0700 { 0701 if (pCore->getProjectProfile().progressive()) { 0702 // nothing to do 0703 return; 0704 } 0705 KdenliveSettings::setMonitor_progressive(active); 0706 if (m_clipMonitor) { 0707 m_clipMonitor->resetConsumer(true); 0708 m_clipMonitor->refreshMonitor(true); 0709 } 0710 if (m_projectMonitor) { 0711 m_projectMonitor->resetConsumer(true); 0712 m_projectMonitor->refreshMonitor(true); 0713 } 0714 } 0715 0716 Monitor *MonitorManager::clipMonitor() 0717 { 0718 return m_clipMonitor; 0719 } 0720 0721 Monitor *MonitorManager::projectMonitor() 0722 { 0723 return m_projectMonitor; 0724 } 0725 0726 void MonitorManager::slotZoneStart() 0727 { 0728 if (m_activeMonitor == m_clipMonitor) { 0729 m_clipMonitor->slotZoneStart(); 0730 } else if (m_activeMonitor == m_projectMonitor) { 0731 m_projectMonitor->slotZoneStart(); 0732 } 0733 } 0734 0735 void MonitorManager::slotZoneEnd() 0736 { 0737 if (m_activeMonitor == m_projectMonitor) { 0738 m_projectMonitor->slotZoneEnd(); 0739 } else if (m_activeMonitor == m_clipMonitor) { 0740 m_clipMonitor->slotZoneEnd(); 0741 } 0742 } 0743 0744 void MonitorManager::slotSetInPoint() 0745 { 0746 if (m_activeMonitor == m_clipMonitor) { 0747 m_clipMonitor->slotSetZoneStart(); 0748 } else if (m_activeMonitor == m_projectMonitor) { 0749 QPoint sourceZone = m_projectMonitor->getZoneInfo(); 0750 QPoint destZone = sourceZone; 0751 destZone.setX(m_projectMonitor->position()); 0752 if (destZone.x() > destZone.y()) { 0753 destZone.setY(qMin(pCore->projectDuration(), destZone.x() + (sourceZone.y() - sourceZone.x()))); 0754 } 0755 Q_EMIT m_projectMonitor->zoneUpdatedWithUndo(sourceZone, destZone); 0756 } 0757 } 0758 0759 void MonitorManager::slotSetOutPoint() 0760 { 0761 if (m_activeMonitor == m_clipMonitor) { 0762 m_clipMonitor->slotSetZoneEnd(); 0763 } else if (m_activeMonitor == m_projectMonitor) { 0764 QPoint sourceZone = m_projectMonitor->getZoneInfo(); 0765 QPoint destZone = sourceZone; 0766 destZone.setY(m_projectMonitor->position() + 1); 0767 if (destZone.y() < destZone.x()) { 0768 destZone.setX(qMax(0, destZone.y() - (sourceZone.y() - sourceZone.x()))); 0769 } 0770 Q_EMIT m_projectMonitor->zoneUpdatedWithUndo(sourceZone, destZone); 0771 } 0772 } 0773 0774 void MonitorManager::slotExtractCurrentFrame() 0775 { 0776 if (m_activeMonitor) { 0777 static_cast<Monitor *>(m_activeMonitor)->slotExtractCurrentFrame(); 0778 } 0779 } 0780 0781 void MonitorManager::slotExtractCurrentFrameToProject() 0782 { 0783 if (m_activeMonitor) { 0784 static_cast<Monitor *>(m_activeMonitor)->slotExtractCurrentFrame(QString(), true); 0785 } 0786 } 0787 0788 void MonitorManager::slotZoomIn() 0789 { 0790 if (m_activeMonitor) { 0791 static_cast<Monitor *>(m_activeMonitor)->slotZoomIn(); 0792 } 0793 } 0794 0795 void MonitorManager::slotZoomOut() 0796 { 0797 if (m_activeMonitor) { 0798 static_cast<Monitor *>(m_activeMonitor)->slotZoomOut(); 0799 } 0800 } 0801 0802 bool MonitorManager::isMultiTrack() const 0803 { 0804 if (m_multiTrack) { 0805 return m_multiTrack->isChecked(); 0806 } 0807 return false; 0808 } 0809 0810 void MonitorManager::switchMultiTrackView(bool enable) 0811 { 0812 if (isMultiTrack()) { 0813 if (!enable) { 0814 m_multiTrack->trigger(); 0815 } 0816 } else if (enable) { 0817 m_multiTrack->trigger(); 0818 } 0819 } 0820 0821 bool MonitorManager::isTrimming() const 0822 { 0823 if (m_projectMonitor && m_projectMonitor->m_trimmingbar) { 0824 return m_projectMonitor->m_trimmingbar->isVisible(); 0825 } 0826 return false; 0827 } 0828 0829 void MonitorManager::updateBgColor() 0830 { 0831 if (m_projectMonitor) { 0832 m_projectMonitor->updateBgColor(); 0833 m_projectMonitor->forceMonitorRefresh(); 0834 } 0835 if (m_clipMonitor) { 0836 m_clipMonitor->updateBgColor(); 0837 m_clipMonitor->forceMonitorRefresh(); 0838 } 0839 }