/** @brief This property is used to decide if the renderer should convert it's frames to QImage for use in other Kdenlive widgets. */
bool sendFrameForAnalysis;
+ /** @brief This property is used to decide if the renderer should send audio data for monitoring. */
+ bool analyseAudio;
+
const QString &name() const {return m_name;};
/** @brief Someone needs us to send again a frame. */
void frameUpdated(QImage);
/** @brief This signal contains the audio of the current frame. */
- void audioSamplesSignal(const QVector<int16_t>&, const int&, const int&, const int&);
+ void audioSamplesSignal(QVector<int16_t>,int,int,int);
};
class AbstractMonitor : public QWidget
#include "gentime.h"
#include "effectslist.h"
-#include <QTreeWidgetItem>
#include <KLocale>
+#include <QTreeWidgetItem>
+ #include <QtCore/QString>
+
const int MAXCLIPDURATION = 15000;
+namespace Kdenlive {
+ const QString clipMonitor("clipMonitor");
+ const QString recordMonitor("recordMonitor");
+ const QString projectMonitor("projectMonitor");
+ const QString stopmotionMonitor("stopmotionMonitor");
+}
+
enum OPERATIONTYPE { NONE = 0, MOVE = 1, RESIZESTART = 2, RESIZEEND = 3, FADEIN = 4, FADEOUT = 5, TRANSITIONSTART = 6, TRANSITIONEND = 7, MOVEGUIDE = 8, KEYFRAME = 9, SEEK = 10, SPACER = 11, RUBBERSELECTION = 12};
enum CLIPTYPE { UNKNOWN = 0, AUDIO = 1, VIDEO = 2, AV = 3, COLOR = 4, IMAGE = 5, TEXT = 6, SLIDESHOW = 7, VIRTUAL = 8, PLAYLIST = 9 };
#include "transitionsettings.h"
#include "renderwidget.h"
#include "renderer.h"
-#include "audiosignal.h"
#ifdef USE_JOGSHUTTLE
#include "jogshuttle.h"
#include "jogaction.h"
#include "config-kdenlive.h"
#include "cliptranscode.h"
#include "ui_templateclip_ui.h"
-#include "colorscopes/vectorscope.h"
-#include "colorscopes/waveform.h"
-#include "colorscopes/rgbparade.h"
-#include "colorscopes/histogram.h"
-#include "audioscopes/audiospectrum.h"
-#include "audioscopes/spectrogram.h"
+#include "scopes/scopemanager.h"
+#include "scopes/colorscopes/vectorscope.h"
+#include "scopes/colorscopes/waveform.h"
+#include "scopes/colorscopes/rgbparade.h"
+#include "scopes/colorscopes/histogram.h"
+#include "scopes/audioscopes/audiosignal.h"
+#include "scopes/audioscopes/audiospectrum.h"
+#include "scopes/audioscopes/spectrogram.h"
#include "archivewidget.h"
#include "databackup/backupwidget.h"
#include "utils/resourcewidget.h"
#endif
m_findActivated(false),
m_stopmotion(NULL)
-{
+{
qRegisterMetaType<QVector<int16_t> > ();
qRegisterMetaType<stringMap> ("stringMap");
qRegisterMetaType<audioByteArray> ("audioByteArray");
if (strncmp(separator, ".", 1) == 0) systemLocale = QLocale::c();
else if (strncmp(separator, ",", 1) == 0) systemLocale = QLocale("fr_FR.UTF-8");
}
-
+
systemLocale.setNumberOptions(QLocale::OmitGroupSeparator);
QLocale::setDefault(systemLocale);
dbus.registerObject("/MainWindow", this);
if (!KdenliveSettings::colortheme().isEmpty()) slotChangePalette(NULL, KdenliveSettings::colortheme());
- setFont(KGlobalSettings::toolBarFont());
+ //setFont(KGlobalSettings::toolBarFont());
parseProfiles(MltPath);
KdenliveSettings::setCurrent_profile(KdenliveSettings::default_profile());
m_commandStack = new QUndoGroup;
m_clipMonitorDock = new QDockWidget(i18n("Clip Monitor"), this);
m_clipMonitorDock->setObjectName("clip_monitor");
- m_clipMonitor = new Monitor("clip", m_monitorManager, QString(), m_timelineArea);
+ m_clipMonitor = new Monitor(Kdenlive::clipMonitor, m_monitorManager, QString(), m_timelineArea);
m_clipMonitorDock->setWidget(m_clipMonitor);
-
+
// Connect the project list
connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint, bool)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool)));
connect(m_projectList, SIGNAL(raiseClipMonitor()), m_clipMonitor, SLOT(activateMonitor()));
m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this);
m_projectMonitorDock->setObjectName("project_monitor");
- m_projectMonitor = new Monitor("project", m_monitorManager, QString());
+ m_projectMonitor = new Monitor(Kdenlive::projectMonitor, m_monitorManager, QString());
m_projectMonitorDock->setWidget(m_projectMonitor);
#ifndef Q_WS_MAC
m_recMonitorDock = new QDockWidget(i18n("Record Monitor"), this);
m_recMonitorDock->setObjectName("record_monitor");
- m_recMonitor = new RecMonitor("record", m_monitorManager);
+ m_recMonitor = new RecMonitor(Kdenlive::recordMonitor, m_monitorManager);
m_recMonitorDock->setWidget(m_recMonitor);
connect(m_recMonitor, SIGNAL(addProjectClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl)));
connect(m_recMonitor, SIGNAL(addProjectClipList(KUrl::List)), this, SLOT(slotAddProjectClipList(KUrl::List)));
connect(m_recMonitor, SIGNAL(showConfigDialog(int, int)), this, SLOT(slotPreferences(int, int)));
-
+
#endif /* ! Q_WS_MAC */
m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor, m_recMonitor);
m_notesWidget = new NotesWidget();
connect(m_notesWidget, SIGNAL(insertNotesTimecode()), this, SLOT(slotInsertNotesTimecode()));
connect(m_notesWidget, SIGNAL(seekProject(int)), m_projectMonitor->render, SLOT(seekToFrame(int)));
-
+
m_notesWidget->setTabChangesFocus(true);
#if KDE_IS_VERSION(4,4,0)
m_notesWidget->setClickMessage(i18n("Enter your project notes here ..."));
m_effectListDock->setWidget(m_effectList);
addDockWidget(Qt::TopDockWidgetArea, m_effectListDock);
- m_vectorscope = new Vectorscope(m_monitorManager);
+ m_scopeManager = new ScopeManager(m_monitorManager);
+ m_vectorscope = new Vectorscope();
m_vectorscopeDock = new QDockWidget(i18n("Vectorscope"), this);
m_vectorscopeDock->setObjectName(m_vectorscope->widgetName());
m_vectorscopeDock->setWidget(m_vectorscope);
addDockWidget(Qt::TopDockWidgetArea, m_vectorscopeDock);
- connect(m_vectorscopeDock, SIGNAL(visibilityChanged(bool)), m_vectorscope, SLOT(forceUpdate(bool)));
- connect(m_vectorscopeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
- connect(m_vectorscope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
- m_gfxScopesList.append(m_vectorscopeDock);
+ m_scopeManager->addScope(m_vectorscope, m_vectorscopeDock);
- m_waveform = new Waveform(m_monitorManager);
+ m_waveform = new Waveform();
m_waveformDock = new QDockWidget(i18n("Waveform"), this);
m_waveformDock->setObjectName(m_waveform->widgetName());
m_waveformDock->setWidget(m_waveform);
addDockWidget(Qt::TopDockWidgetArea, m_waveformDock);
- connect(m_waveformDock, SIGNAL(visibilityChanged(bool)), m_waveform, SLOT(forceUpdate(bool)));
- connect(m_waveformDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
- connect(m_waveform, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
- m_gfxScopesList.append(m_waveformDock);
+ m_scopeManager->addScope(m_waveform, m_waveformDock);
- m_RGBParade = new RGBParade(m_monitorManager);
+ m_RGBParade = new RGBParade();
m_RGBParadeDock = new QDockWidget(i18n("RGB Parade"), this);
m_RGBParadeDock->setObjectName(m_RGBParade->widgetName());
m_RGBParadeDock->setWidget(m_RGBParade);
addDockWidget(Qt::TopDockWidgetArea, m_RGBParadeDock);
- connect(m_RGBParadeDock, SIGNAL(visibilityChanged(bool)), m_RGBParade, SLOT(forceUpdate(bool)));
- connect(m_RGBParadeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
- connect(m_RGBParade, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
- m_gfxScopesList.append(m_RGBParadeDock);
+ m_scopeManager->addScope(m_RGBParade, m_RGBParadeDock);
- m_histogram = new Histogram(m_monitorManager);
+ m_histogram = new Histogram();
m_histogramDock = new QDockWidget(i18n("Histogram"), this);
m_histogramDock->setObjectName(m_histogram->widgetName());
m_histogramDock->setWidget(m_histogram);
addDockWidget(Qt::TopDockWidgetArea, m_histogramDock);
- connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), m_histogram, SLOT(forceUpdate(bool)));
- connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
- connect(m_histogram, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest()));
- m_gfxScopesList.append(m_histogramDock);
-
+ m_scopeManager->addScope(m_histogram, m_histogramDock);
m_audiosignal = new AudioSignal;
m_audiosignalDock = new QDockWidget(i18n("Audio Signal"), this);
m_audiosignalDock->setObjectName("audiosignal");
m_audiosignalDock->setWidget(m_audiosignal);
addDockWidget(Qt::TopDockWidgetArea, m_audiosignalDock);
- connect(m_audiosignalDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest()));
- connect(m_audiosignal, SIGNAL(updateAudioMonitoring()), this, SLOT(slotUpdateAudioScopeFrameRequest()));
+ m_scopeManager->addScope(m_audiosignal, m_audiosignalDock);
m_audioSpectrum = new AudioSpectrum();
m_audioSpectrumDock = new QDockWidget(i18n("AudioSpectrum"), this);
m_audioSpectrumDock->setObjectName(m_audioSpectrum->widgetName());
m_audioSpectrumDock->setWidget(m_audioSpectrum);
addDockWidget(Qt::TopDockWidgetArea, m_audioSpectrumDock);
- m_audioScopesList.append(m_audioSpectrum);
- connect(m_audioSpectrumDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest()));
- connect(m_audioSpectrum, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest()));
+ m_scopeManager->addScope(m_audioSpectrum, m_audioSpectrumDock);
m_spectrogram = new Spectrogram();
m_spectrogramDock = new QDockWidget(i18n("Spectrogram"), this);
m_spectrogramDock->setObjectName(m_spectrogram->widgetName());
m_spectrogramDock->setWidget(m_spectrogram);
addDockWidget(Qt::TopDockWidgetArea, m_spectrogramDock);
- m_audioScopesList.append(m_spectrogram);
- connect(m_audioSpectrumDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest()));
- connect(m_audioSpectrum, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest()));
-
- // Connect the audio signal to the audio scope slots
- bool b = true;
- if (m_projectMonitor) {
- qDebug() << "project monitor connected";
- b &= connect(m_projectMonitor->render, SIGNAL(audioSamplesSignal(QVector<int16_t>, int, int, int)),
- m_audioSpectrum, SLOT(slotReceiveAudio(QVector<int16_t>, int, int, int)));
- b &= connect(m_projectMonitor->render, SIGNAL(audioSamplesSignal(const QVector<int16_t>&, const int&, const int&, const int&)),
- m_audiosignal, SLOT(slotReceiveAudio(const QVector<int16_t>&, const int&, const int&, const int&)));
- b &= connect(m_projectMonitor->render, SIGNAL(audioSamplesSignal(QVector<int16_t>,int,int,int)),
- m_spectrogram, SLOT(slotReceiveAudio(QVector<int16_t>,int,int,int)));
- }
- if (m_clipMonitor) {
- qDebug() << "clip monitor connected";
- b &= connect(m_clipMonitor->render, SIGNAL(audioSamplesSignal(QVector<int16_t>, int, int, int)),
- m_audioSpectrum, SLOT(slotReceiveAudio(QVector<int16_t>, int, int, int)));
- b &= connect(m_clipMonitor->render, SIGNAL(audioSamplesSignal(const QVector<int16_t>&, int, int, int)),
- m_audiosignal, SLOT(slotReceiveAudio(const QVector<int16_t>&, int, int, int)));
- b &= connect(m_clipMonitor->render, SIGNAL(audioSamplesSignal(QVector<int16_t>,int,int,int)),
- m_spectrogram, SLOT(slotReceiveAudio(QVector<int16_t>,int,int,int)));
- }
- // Ensure connections were set up correctly
- Q_ASSERT(b);
-
-
+ m_scopeManager->addScope(m_spectrogram, m_spectrogramDock);
// Add monitors here to keep them at the right of the window
addDockWidget(Qt::TopDockWidgetArea, m_clipMonitorDock);
m_effectActions = new KActionCategory(i18n("Effects"), actionCollection());
m_effectList->reloadEffectList(m_effectsMenu, m_effectActions);
m_effectsActionCollection->readSettings();
-
+
setupGUI();
// Find QDockWidget tab bars and show / hide widget title bars on right click
connect(m_projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool)));
connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool)));
- connect(m_monitorManager, SIGNAL(checkColorScopes()), this, SLOT(slotUpdateColorScopes()));
- connect(m_monitorManager, SIGNAL(clearScopes()), this, SLOT(slotClearColorScopes()));
+ //connect(m_monitorManager, SIGNAL(checkColorScopes()), this, SLOT(slotUpdateColorScopes()));
+ //connect(m_monitorManager, SIGNAL(clearScopes()), this, SLOT(slotClearColorScopes()));
connect(m_effectList, SIGNAL(addEffect(const QDomElement)), this, SLOT(slotAddEffect(const QDomElement)));
connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects()));
actionCollection()->addAssociatedWidget(m_clipMonitor->container());
actionCollection()->addAssociatedWidget(m_projectMonitor->container());
-
+
// Populate encoding profiles
KConfig conf("encodingprofiles.rc", KConfig::FullConfig, "appdata");
if (KdenliveSettings::proxyparams().isEmpty() || KdenliveSettings::proxyextension().isEmpty()) {
delete m_clipMonitor;
delete m_shortcutRemoveFocus;
delete[] m_transitions;
+ delete m_monitorManager;
+ delete m_scopeManager;
Mlt::Factory::close();
}
delete m_jogProcess;
m_jogProcess = NULL;
if (KdenliveSettings::enableshuttle() == false) return;
-
+
m_jogProcess = new JogShuttle(KdenliveSettings::shuttledevice());
m_jogShuttle = new JogShuttleAction(m_jogProcess, JogShuttleConfig::actionMap(KdenliveSettings::shuttlebuttons()));
-
+
connect(m_jogShuttle, SIGNAL(rewindOneFrame()), m_monitorManager, SLOT(slotRewindOneFrame()));
connect(m_jogShuttle, SIGNAL(forwardOneFrame()), m_monitorManager, SLOT(slotForwardOneFrame()));
connect(m_jogShuttle, SIGNAL(rewind(double)), m_monitorManager, SLOT(slotRewind(double)));
connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool)), m_projectList, SLOT(slotReplyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool)));
connect(m_projectMonitor->render, SIGNAL(removeInvalidClip(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidClip(const QString &, bool)));
-
+
connect(m_projectMonitor->render, SIGNAL(removeInvalidProxy(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidProxy(const QString &, bool)));
connect(m_clipMonitor, SIGNAL(refreshClipThumbnail(const QString &, bool)), m_projectList, SLOT(slotRefreshClipThumbnail(const QString &, bool)));
QColor buttonBg = scheme.background(KColorScheme::LinkBackground).color();
QColor buttonBord = scheme.foreground(KColorScheme::LinkText).color();
QColor buttonBord2 = scheme.shade(KColorScheme::LightShade);
- statusBar()->setStyleSheet(QString("QStatusBar QLabel {font-size:%1pt;} QStatusBar::item { border: 0px; font-size:%1pt;padding:0px; }").arg(statusBar()->font().pointSize()));
+ //statusBar()->setStyleSheet(QString("QStatusBar QLabel {font-size:%1pt;} QStatusBar::item { border: 0px; font-size:%1pt;padding:0px; }").arg(statusBar()->font().pointSize()));
QString style1 = QString("QToolBar { border: 0px } QToolButton { border-style: inset; border:1px solid transparent;border-radius: 3px;margin: 0px 3px;padding: 0px;} QToolButton:hover { background: rgb(%7, %8, %9);border-style: inset; border:1px solid rgb(%7, %8, %9);border-radius: 3px;} QToolButton:checked { background-color: rgb(%1, %2, %3); border-style: inset; border:1px solid rgb(%4, %5, %6);border-radius: 3px;}").arg(buttonBg.red()).arg(buttonBg.green()).arg(buttonBg.blue()).arg(buttonBord.red()).arg(buttonBord.green()).arg(buttonBord.blue()).arg(buttonBord2.red()).arg(buttonBord2.green()).arg(buttonBord2.blue());
QString styleBorderless = "QToolButton { border-width: 0px;margin: 1px 3px 0px;padding: 0px;}";
KAction *archiveProject = new KAction(KIcon("file-save"), i18n("Archive Project"), this);
collection.addAction("archive_project", archiveProject);
connect(archiveProject, SIGNAL(triggered(bool)), this, SLOT(slotArchiveProject()));
-
+
KAction *markIn = collection.addAction("mark_in");
markIn->setText(i18n("Set Zone In"));
m_tracksActionCollection = new KActionCollection(this, KGlobal::mainComponent());
m_tracksActionCollection->addAssociatedWidget(m_timelineArea);
-
+
KAction *insertTrack = new KAction(KIcon(), i18n("Insert Track"), m_tracksActionCollection);
m_tracksActionCollection->addAction("insert_track", insertTrack);
connect(insertTrack, SIGNAL(triggered()), this, SLOT(slotInsertTrack()));
KAction *selectTrack = new KAction(KIcon(), i18n("Select All in Current Track"), m_tracksActionCollection);
connect(selectTrack, SIGNAL(triggered()), this, SLOT(slotSelectTrack()));
m_tracksActionCollection->addAction("select_track", selectTrack);
-
+
QAction *selectAll = KStandardAction::selectAll(this, SLOT(slotSelectAllTracks()), m_tracksActionCollection);
selectAll->setShortcutContext(Qt::WidgetWithChildrenShortcut);
m_tracksActionCollection->addAction("select_all_tracks", selectAll);
-
+
KAction *addGuide = new KAction(KIcon("document-new"), i18n("Add Guide"), this);
collection.addAction("add_guide", addGuide);
connect(addGuide, SIGNAL(triggered()), this, SLOT(slotAddGuide()));
QAction *addFolderButton = new KAction(KIcon("folder-new"), i18n("Create Folder"), this);
collection.addAction("add_folder", addFolderButton);
connect(addFolderButton , SIGNAL(triggered()), m_projectList, SLOT(slotAddFolder()));
-
+
QAction *downloadResources = new KAction(KIcon("download"), i18n("Online Resources"), this);
collection.addAction("download_resource", downloadResources);
connect(downloadResources , SIGNAL(triggered()), this, SLOT(slotDownloadResources()));
proxyClip->setCheckable(true);
proxyClip->setChecked(false);
connect(proxyClip, SIGNAL(toggled(bool)), m_projectList, SLOT(slotProxyCurrentItem(bool)));
-
+
QAction *stopMotion = new KAction(KIcon("image-x-generic"), i18n("Stop Motion Capture"), this);
- collection.addAction("stopmotion", stopMotion);
+ collection.addAction(Kdenlive::stopmotionMonitor, stopMotion);
connect(stopMotion , SIGNAL(triggered()), this, SLOT(slotOpenStopmotion()));
QMenu *addClips = new QMenu();
connectDocument(trackView, doc);
} else
m_timelineArea->setTabBarHidden(false);
- m_monitorManager->activateMonitor("clip");
+ m_monitorManager->activateMonitor(Kdenlive::clipMonitor);
m_closeAction->setEnabled(m_timelineArea->count() > 1);
}
KMessageBox::sorry(this, i18n("File %1 is not a Kdenlive project file", url.path()));
return;
}
-
+
// Check if the document is already opened
const int ct = m_timelineArea->count();
bool isOpened = false;
delete m_stopmotion;
m_stopmotion = NULL;
}
-
+
m_timer.start();
KProgressDialog progressDialog(this, i18n("Loading project"), i18n("Loading project"));
progressDialog.setAllowCancel(false);
disconnect(m_activeTimeline->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType)));
disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, bool, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool, const int)));
disconnect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), m_activeTimeline->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap)));
-
+
disconnect(m_activeTimeline, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
disconnect(m_activeTimeline, SIGNAL(configTrack(int)), this, SLOT(slotConfigTrack(int)));
disconnect(m_activeDocument, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool)));
connect(doc, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool)));
connect(doc, SIGNAL(guidesUpdated()), this, SLOT(slotGuidesUpdated()));
connect(doc, SIGNAL(saveTimelinePreview(const QString &)), trackView, SLOT(slotSaveTimelinePreview(const QString)));
-
+
connect(m_notesWidget, SIGNAL(textChanged()), doc, SLOT(setModified()));
connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_effectStack, SLOT(slotClipItemSelected(ClipItem*, int)));
connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*)));
connect(trackView->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*)));
-
+
connect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), trackView->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap)));
connect(m_effectStack, SIGNAL(updateEffect(ClipItem*, int, QDomElement, QDomElement, int)), trackView->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, int, QDomElement, QDomElement, int)));
#endif
//Update the mouse position display so it will display in DF/NDF format by default based on the project setting.
slotUpdateMousePosition(0);
- m_monitorManager->activateMonitor("clip");
+ m_monitorManager->activateMonitor(Kdenlive::clipMonitor);
// set tool to select tool
m_buttonSelectTool->setChecked(true);
}
// KConfigDialog didn't find an instance of this dialog, so lets
// create it :
-
+
// Get the mappable actions in localized form
QMap<QString, QString> actions;
KActionCollection* collection = actionCollection();
foreach (const QString& action_name, m_action_names) {
actions[collection->action(action_name)->text()] = action_name;
}
-
+
KdenliveSettingsDialog* dialog = new KdenliveSettingsDialog(actions, this);
connect(dialog, SIGNAL(settingsChanged(const QString&)), this, SLOT(updateConfiguration()));
connect(dialog, SIGNAL(doResetProfile()), m_monitorManager, SLOT(slotResetProfiles()));
DocClipBase *clip = cliplist.at(i);
if (clip->clipType() == IMAGE)
new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newImageProps), newImageProps, true, command);
- else
+ else
new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newProps), newProps, true, command);
}
m_activeDocument->commandStack()->push(command);
{
QMenu *transMenu = static_cast<QMenu*>(factory()->container("transcoders", this));
transMenu->clear();
-
+
QMenu *extractAudioMenu = static_cast<QMenu*>(factory()->container("extract_audio", this));
extractAudioMenu->clear();
QString destination;
ProjectItem *item = m_projectList->getClipById(ids.at(0));
if (ids.count() == 1) {
-
+
}
ClipStabilize *d = new ClipStabilize(destination, ids.count(), filtername);
//connect(d, SIGNAL(addClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl)));
}
}
}
-
+
// Do we want proxy rendering
if (m_projectList->useProxy() && !m_renderWidget->proxyRendering()) {
QString root = doc.documentElement().attribute("root");
}
}
}
-
+
/*QMapIterator<QString, QString> i(proxies);
while (i.hasNext()) {
i.next();
}*/
}
playlistContent = doc.toString();
-
+
// Do save scenelist
QFile file(playlistPath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
plt = KGlobalSettings::createNewApplicationPalette(config);
#else
// Since there was a bug in createApplicationPalette in KDE < 4.6.3 we need
- // to do the palette loading stuff ourselves. (https://bugs.kde.org/show_bug.cgi?id=263497)
+ // to do the palette loading stuff ourselves. (https://bugs.kde.org/show_bug.cgi?id=263497)
QPalette::ColorGroup states[3] = { QPalette::Active, QPalette::Inactive,
QPalette::Disabled };
// TT thinks tooltips shouldn't use active, so we use our active colors for all states
KColorScheme schemeTooltip(QPalette::Active, KColorScheme::Tooltip, config);
-
+
for ( int i = 0; i < 3 ; i++ ) {
QPalette::ColorGroup state = states[i];
KColorScheme schemeView(state, KColorScheme::View, config);
KColorScheme schemeWindow(state, KColorScheme::Window, config);
KColorScheme schemeButton(state, KColorScheme::Button, config);
KColorScheme schemeSelection(state, KColorScheme::Selection, config);
-
+
plt.setBrush( state, QPalette::WindowText, schemeWindow.foreground() );
plt.setBrush( state, QPalette::Window, schemeWindow.background() );
plt.setBrush( state, QPalette::Base, schemeView.background() );
plt.setBrush( state, QPalette::HighlightedText, schemeSelection.foreground() );
plt.setBrush( state, QPalette::ToolTipBase, schemeTooltip.background() );
plt.setBrush( state, QPalette::ToolTipText, schemeTooltip.foreground() );
-
+
plt.setColor( state, QPalette::Light, schemeWindow.shade( KColorScheme::LightShade ) );
plt.setColor( state, QPalette::Midlight, schemeWindow.shade( KColorScheme::MidlightShade ) );
plt.setColor( state, QPalette::Mid, schemeWindow.shade( KColorScheme::MidShade ) );
plt.setColor( state, QPalette::Dark, schemeWindow.shade( KColorScheme::DarkShade ) );
plt.setColor( state, QPalette::Shadow, schemeWindow.shade( KColorScheme::ShadowShade ) );
-
+
plt.setBrush( state, QPalette::AlternateBase, schemeView.background( KColorScheme::AlternateBackground) );
plt.setBrush( state, QPalette::Link, schemeView.foreground( KColorScheme::LinkText ) );
plt.setBrush( state, QPalette::LinkVisited, schemeView.foreground( KColorScheme::VisitedText ) );
}
}
-void MainWindow::slotUpdateGfxScopeFrameRequest()
-{
- // We need a delay to make sure widgets are hidden after a close event for example
- QTimer::singleShot(500, this, SLOT(slotDoUpdateGfxScopeFrameRequest()));
-}
-
-void MainWindow::slotDoUpdateGfxScopeFrameRequest()
-{
- // Check scopes
- bool request = false;
- for (int i = 0; i < m_gfxScopesList.count(); i++) {
- if (!m_gfxScopesList.at(i)->widget()->visibleRegion().isEmpty() && static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled()) {
- kDebug() << "SCOPE VISIBLE: " << static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->widgetName();
- request = true;
- break;
- }
- }
- if (!request) {
- if (!m_projectMonitor->effectSceneDisplayed()) {
- m_projectMonitor->render->sendFrameForAnalysis = false;
- }
- m_clipMonitor->render->sendFrameForAnalysis = false;
- if (m_recMonitor)
- m_recMonitor->analyseFrames(false);
- } else {
- m_projectMonitor->render->sendFrameForAnalysis = true;
- m_clipMonitor->render->sendFrameForAnalysis = true;
- if (m_recMonitor)
- m_recMonitor->analyseFrames(true);
- }
-}
-
-void MainWindow::slotUpdateAudioScopeFrameRequest()
-{
- QTimer::singleShot(500, this, SLOT(slotDoUpdateAudioScopeFrameRequest()));
-}
-
-void MainWindow::slotDoUpdateAudioScopeFrameRequest()
-{
- bool request = false;
- for (int i = 0; i < m_audioScopesList.count(); i++) {
- if (!m_audioScopesList.at(i)->visibleRegion().isEmpty() && m_audioScopesList.at(i)->autoRefreshEnabled()) {
- kDebug() << "AUDIO SCOPE VISIBLE: " << m_audioScopesList.at(i)->widgetName();
- request = true;
- break;
- }
- }
- // Handle audio signal separately (no common interface)
- if (!m_audiosignal->visibleRegion().isEmpty() && m_audiosignal->monitoringEnabled()) {
- kDebug() << "AUDIO SCOPE VISIBLE: " << "audiosignal";
- request = true;
- }
-#ifdef DEBUG_MAINW
- qDebug() << "Scopes Requesting Audio data: " << request;
-#endif
- KdenliveSettings::setMonitor_audio(request);
- m_monitorManager->slotUpdateAudioMonitoring();
-}
-
-void MainWindow::slotUpdateColorScopes()
-{
- bool request = false;
- for (int i = 0; i < m_gfxScopesList.count(); i++) {
- // Check if we need the renderer to send a new frame for update
- if (!m_gfxScopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled())) request = true;
- static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->slotActiveMonitorChanged();
- }
- if (request && m_monitorManager->activeRenderer()) {
- m_monitorManager->activeRenderer()->sendFrameUpdate();
- }
- if (m_audiosignal->isVisible() && m_recMonitor->abstractRender()) {
- connect(m_recMonitor->abstractRender(), SIGNAL(audioSamplesSignal(const QVector<int16_t>&, const int&, const int&, const int&)), m_audiosignal, SLOT(slotReceiveAudio(const QVector<int16_t>&, const int&, const int&, const int&)));
- }
-}
-
-void MainWindow::slotClearColorScopes()
-{
- for (int i = 0; i < m_gfxScopesList.count(); i++) {
- static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->slotClearMonitor();
- }
-}
void MainWindow::slotOpenStopmotion()
{
class DocClipBase;
class Render;
class Transition;
+class ScopeManager;
class Histogram;
class Vectorscope;
class Waveform;
KTabWidget* m_timelineArea;
QProgressBar *m_statusProgressBar;
+ ScopeManager *m_scopeManager;
+
/** @brief Sets up all the actions and attaches them to the collection. */
void setupActions();
KdenliveDoc *m_activeDocument;
/** This list holds all the scopes used in Kdenlive, allowing to manage some global settings */
QList <QDockWidget *> m_gfxScopesList;
- QList <AbstractAudioScopeWidget *> m_audioScopesList;
KActionCategory *m_effectActions;
QMenu *m_effectsMenu;
/** Actions used in the stopmotion widget */
KActionCategory *m_stopmotion_actions;
-
+
/** Action names that can be used in the slotDoAction() slot, with their i18n() names */
QStringList m_action_names;
/** @brief The monitor informs that it needs (or not) to have frames sent by the renderer. */
void slotMonitorRequestRenderFrame(bool request);
- /** @brief Check if someone needs the render frame sent. */
- void slotUpdateGfxScopeFrameRequest();
- /** @brief Check if someone needs the render frame sent. */
- void slotDoUpdateGfxScopeFrameRequest();
- void slotUpdateAudioScopeFrameRequest();
- void slotDoUpdateAudioScopeFrameRequest();
- /** @brief When switching between monitors, update the visible scopes. */
- void slotUpdateColorScopes();
- /** @brief Active monitor deleted, clear scopes. */
- void slotClearColorScopes();
/** @brief Switch current monitor to fullscreen. */
void slotSwitchFullscreen();
/** @brief Open the stopmotion dialog. */
self->showFrame(frame);
}
-static void rec_consumer_frame_show(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
+/*static void rec_consumer_frame_show(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
{
Mlt::Frame frame(frame_ptr);
if (!frame.is_valid()) return;
self->gotCapturedFrame(frame);
-}
+}*/
static void rec_consumer_frame_preview(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
{
AbstractRender("capture", parent),
doCapture(0),
sendFrameForAnalysis(false),
- analyseAudio(KdenliveSettings::monitor_audio()),
processingImage(false),
m_mltConsumer(NULL),
m_mltProducer(NULL),
m_captureDisplayWidget(surface),
m_winid((int) surface->winId())
{
+ analyseAudio = KdenliveSettings::monitor_audio();
if (profile.isEmpty()) profile = KdenliveSettings::current_profile();
buildConsumer(profile);
connect(this, SIGNAL(unblockPreview()), this, SLOT(slotPreparePreview()));
/** @brief This will add a horizontal flip effect, easier to work when filming yourself. */
void mirror(bool activate);
-
- /** @brief This property is used to decide if the renderer should send audio data for monitoring. */
- bool analyseAudio;
/** @brief True if we are processing an image (yuv > rgb) when recording. */
bool processingImage;
configButton->setPopupMode(QToolButton::QToolButton::InstantPopup);
m_toolbar->addWidget(configButton);
- if (name == "clip") {
+ if (name == Kdenlive::clipMonitor) {
m_markerMenu = new QMenu(i18n("Go to marker..."), this);
m_markerMenu->setEnabled(false);
m_configMenu->addMenu(m_markerMenu);
connect(render, SIGNAL(rendererStopped(int)), this, SLOT(rendererStopped(int)));
connect(render, SIGNAL(rendererPosition(int)), this, SLOT(seekCursor(int)));
- if (name != "clip") {
+ if (name != Kdenlive::clipMonitor) {
connect(render, SIGNAL(rendererPosition(int)), this, SIGNAL(renderPosition(int)));
connect(render, SIGNAL(durationChanged(int)), this, SIGNAL(durationChanged(int)));
connect(m_ruler, SIGNAL(zoneChanged(QPoint)), this, SIGNAL(zoneUpdated(QPoint)));
if (m_monitorRefresh) m_monitorRefresh->show();
- if (name == "project") {
+ if (name == Kdenlive::projectMonitor) {
m_effectWidget = new MonitorEditWidget(render, m_videoBox);
m_toolbar->addAction(m_effectWidget->getVisibilityAction());
lay->addWidget(m_effectWidget);
}
//TODO: add save zone to timeline monitor when fixed
- if (m_name == "clip") {
+ if (m_name == Kdenlive::clipMonitor) {
m_contextMenu->addMenu(m_markerMenu);
m_contextMenu->addAction(KIcon("document-save"), i18n("Save zone"), this, SLOT(slotSaveZone()));
QAction *extractZone = m_configMenu->addAction(KIcon("document-new"), i18n("Extract Zone"), this, SLOT(slotExtractCurrentZone()));
QAction *extractFrame = m_configMenu->addAction(KIcon("document-new"), i18n("Extract frame"), this, SLOT(slotExtractCurrentFrame()));
m_contextMenu->addAction(extractFrame);
- if (m_name != "clip") {
+ if (m_name != Kdenlive::clipMonitor) {
QAction *splitView = m_contextMenu->addAction(KIcon("view-split-left-right"), i18n("Split view"), render, SLOT(slotSplitView(bool)));
splitView->setCheckable(true);
m_configMenu->addAction(splitView);
render->setProducer(NULL, -1);
return;
}
-
+
if (clip != m_currentClip || forceUpdate) {
m_currentClip = clip;
if (m_currentClip) activateMonitor();
void Monitor::slotEffectScene(bool show)
{
- if (m_name == "project") {
+ if (m_name == Kdenlive::projectMonitor) {
if (m_monitorRefresh) {
m_monitorRefresh->setVisible(!show);
} else {
m_monitorsList.removeAll(monitor);
}
+AbstractMonitor* MonitorManager::monitor(const QString monitorName)
+{
+ AbstractMonitor *monitor = NULL;
+ for (int i = 0; i < m_monitorsList.size(); i++) {
+ if (m_monitorsList[i]->name() == monitorName) {
+ monitor = m_monitorsList[i];
+ }
+ }
+ return monitor;
+}
+
bool MonitorManager::activateMonitor(const QString &name)
{
if (m_clipMonitor == NULL || m_projectMonitor == NULL)
void MonitorManager::slotSwitchMonitors(bool activateClip)
{
if (activateClip)
- activateMonitor("clip");
+ activateMonitor(Kdenlive::clipMonitor);
else
- activateMonitor("project");
+ activateMonitor(Kdenlive::projectMonitor);
}
void MonitorManager::stopActiveMonitor()
void MonitorManager::slotUpdateAudioMonitoring()
{
// if(...) added since they are 0x0 when the config wizard is running! --Granjow
- if (m_clipMonitor) {
+ /*if (m_clipMonitor) {
m_clipMonitor->render->analyseAudio = KdenliveSettings::monitor_audio();
}
if (m_projectMonitor) {
m_projectMonitor->render->analyseAudio = KdenliveSettings::monitor_audio();
+ }*/
+ for (int i = 0; i < m_monitorsList.count(); i++) {
+ if (m_monitorsList.at(i)->abstractRender()) m_monitorsList.at(i)->abstractRender()->analyseAudio = KdenliveSettings::monitor_audio();
}
}
void resetProfiles(Timecode tc);
void stopActiveMonitor();
AbstractRender *activeRenderer();
+ /** Searches for a monitor with the given name.
+ @return NULL, if no monitor could be found, or the monitor otherwise.
+ */
+ AbstractMonitor *monitor(const QString monitorName);
void updateScopeSource();
void clearScopeSource();
m_recAction = toolbar->addAction(KIcon("media-record"), i18n("Record"));
connect(m_recAction, SIGNAL(triggered()), this, SLOT(slotRecord()));
m_recAction->setCheckable(true);
-
+
rec_options->setIcon(KIcon("system-run"));
QMenu *menu = new QMenu(this);
m_addCapturedClip = new QAction(i18n("Add Captured File to Project"), this);
m_addCapturedClip->setCheckable(true);
m_addCapturedClip->setChecked(true);
menu->addAction(m_addCapturedClip);
-
+
rec_audio->setChecked(KdenliveSettings::v4l_captureaudio());
rec_video->setChecked(KdenliveSettings::v4l_capturevideo());
-
+
m_previewSettings = new QAction(i18n("Recording Preview"), this);
m_previewSettings->setCheckable(true);
-
+
rec_options->setMenu(menu);
menu->addAction(m_previewSettings);
connect(m_captureProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(slotProcessStatus(QProcess::ProcessState)));
connect(m_captureProcess, SIGNAL(readyReadStandardError()), this, SLOT(slotReadDvgrabInfo()));
-
+
QString videoDriver = KdenliveSettings::videodrivername();
#if QT_VERSION >= 0x040600
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
break;
case VIDEO4LINUX:
path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
- m_manager->activateMonitor("record");
+ m_manager->activateMonitor(Kdenlive::recordMonitor);
buildMltDevice(path);
profile = ProfilesDialog::getVideoProfile(path);
producer = getV4lXmlPlaylist(profile);
-
+
//producer = QString("avformat-novalidate:video4linux2:%1?width:%2&height:%3&frame_rate:%4").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) profile.frame_rate_num / profile.frame_rate_den);
if (!m_captureDevice->slotStartPreview(producer, true)) {
// v4l capture failed to start
video_frame->setText(i18n("Failed to start Video4Linux,\ncheck your parameters..."));
m_videoBox->setHidden(true);
-
+
} else {
m_playAction->setEnabled(false);
m_stopAction->setEnabled(true);
m_isPlaying = true;
}
-
+
break;
case BLACKMAGIC:
path = KdenliveSettings::current_profile();
- m_manager->activateMonitor("record");
+ m_manager->activateMonitor(Kdenlive::recordMonitor);
buildMltDevice(path);
producer = QString("decklink:%1").arg(KdenliveSettings::decklink_capturedevice());
if (!m_captureDevice->slotStartPreview(producer)) {
// v4l capture failed to start
video_frame->setText(i18n("Failed to start Decklink,\ncheck your parameters..."));
m_videoBox->setHidden(true);
-
+
} else {
m_playAction->setEnabled(false);
m_stopAction->setEnabled(true);
switch (device_selector->currentIndex()) {
case VIDEO4LINUX:
- m_manager->activateMonitor("record");
+ m_manager->activateMonitor(Kdenlive::recordMonitor);
path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
profile = ProfilesDialog::getVideoProfile(path);
m_videoBox->setRatio((double) profile.display_aspect_num / profile.display_aspect_den);
playlist = getV4lXmlPlaylist(profile);
v4lparameters = KdenliveSettings::v4l_parameters();
-
+
// TODO: when recording audio only, allow param configuration?
if (!rec_video->isChecked()) v4lparameters.clear();
v4lparameters = QString(v4lparameters.section("acodec", 0, 0) + "an=1 " + endParam).simplified();
}
}
-
+
showPreview = m_previewSettings->isChecked();
if (!rec_video->isChecked()) showPreview = false;
m_previewSettings->setEnabled(false);
}
else {
- video_frame->setText(i18n("Failed to start Video4Linux,\ncheck your parameters..."));
+ video_frame->setText(i18n("Failed to start Video4Linux,\ncheck your parameters..."));
m_videoBox->setHidden(true);
m_isCapturing = false;
}
break;
-
+
case BLACKMAGIC:
- m_manager->activateMonitor("record");
+ m_manager->activateMonitor(Kdenlive::recordMonitor);
path = KdenliveSettings::current_profile();
profile = ProfilesDialog::getVideoProfile(path);
m_videoBox->setRatio((double) profile.display_aspect_num / profile.display_aspect_den);
buildMltDevice(path);
-
+
playlist = QString("<producer id=\"producer0\" in=\"0\" out=\"99999\"><property name=\"mlt_type\">producer</property><property name=\"length\">100000</property><property name=\"eof\">pause</property><property name=\"resource\">%1</property><property name=\"mlt_service\">decklink</property></producer>").arg(KdenliveSettings::decklink_capturedevice());
if (m_captureDevice->slotStartCapture(KdenliveSettings::decklink_parameters(), m_captureFile.path(), QString("decklink:%1").arg(KdenliveSettings::decklink_capturedevice()), m_previewSettings->isChecked(), false)) {
m_isCapturing = false;
}
break;
-
+
case SCREENGRAB:
switch (KdenliveSettings::rmd_capture_type()) {
case 0:
}
const QString RecMonitor::getV4lXmlPlaylist(MltVideoProfile profile) {
-
+
QString playlist = QString("<mlt title=\"capture\" LC_NUMERIC=\"C\"><profile description=\"v4l\" width=\"%1\" height=\"%2\" progressive=\"%3\" sample_aspect_num=\"%4\" sample_aspect_den=\"%5\" display_aspect_num=\"%6\" display_aspect_den=\"%7\" frame_rate_num=\"%8\" frame_rate_den=\"%9\" colorspace=\"%10\"/>").arg(profile.width).arg(profile.height).arg(profile.progressive).arg(profile.sample_aspect_num).arg(profile.sample_aspect_den).arg(profile.display_aspect_num).arg(profile.display_aspect_den).arg(profile.frame_rate_num).arg(profile.frame_rate_den).arg(profile.colorspace);
-
+
if (rec_video->isChecked()) {
playlist.append(QString("<producer id=\"producer0\" in=\"0\" out=\"999999\"><property name=\"mlt_type\">producer</property><property name=\"length\">1000000</property><property name=\"eof\">loop</property><property name=\"resource\">video4linux2:%1?width:%2&height:%3&frame_rate:%4</property><property name=\"mlt_service\">avformat-novalidate</property></producer><playlist id=\"playlist0\"><entry producer=\"producer0\" in=\"0\" out=\"999999\"/></playlist>").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) profile.frame_rate_num / profile.frame_rate_den));
}
-
+
if (rec_audio->isChecked()) {
playlist.append(QString("<producer id=\"producer1\" in=\"0\" out=\"999999\"><property name=\"mlt_type\">producer</property><property name=\"length\">1000000</property><property name=\"eof\">loop</property><property name=\"resource\">alsa:%5</property><property name=\"audio_index\">0</property><property name=\"video_index\">-1</property><property name=\"mlt_service\">avformat-novalidate</property></producer><playlist id=\"playlist1\"><entry producer=\"producer1\" in=\"0\" out=\"999999\"/></playlist>").arg(KdenliveSettings::v4l_alsadevicename()));
}
if (QFile::rename(url.path(), newUrl)) {
url = KUrl(newUrl);
}
-
+
}
capturedFiles.append(url);
}
Render::Render(const QString & rendererName, int winid, QString profile, QWidget *parent) :
AbstractRender(rendererName, parent),
- analyseAudio(KdenliveSettings::monitor_audio()),
m_name(rendererName),
m_mltConsumer(NULL),
m_mltProducer(NULL),
m_blackClip(NULL),
m_winid(winid)
{
+ analyseAudio = KdenliveSettings::monitor_audio();
if (profile.isEmpty()) profile = KdenliveSettings::current_profile();
buildConsumer(profile);
m_mltProducer = m_blackClip->cut(0, 1);
void Render::closeMlt()
-{
+{
//delete m_osdTimer;
m_requestList.clear();
m_infoThread.waitForFinished();
m_blackClip->set("id", "black");
m_blackClip->set("mlt_type", "producer");
- if (KdenliveSettings::external_display() && m_name != "clip") {
+ if (KdenliveSettings::external_display() && m_name != Kdenlive::clipMonitor) {
#ifdef USE_BLACKMAGIC
// Use blackmagic card for video output
QMap< QString, QString > profileProperties = ProfilesDialog::getSettingsFromFile(profileName);
buildConsumer(profileName);
double new_fps = m_mltProfile->fps();
double new_dar = m_mltProfile->dar();
-
+
if (!dropSceneList) {
// We need to recover our playlist
if (current_fps != new_fps) {
else delete producer;
}
}
-
+
if (!m_mltProducer || !path.isEmpty()) {
QImage pix(width, height, QImage::Format_RGB32);
pix.fill(Qt::black);
info = m_requestList.takeFirst();
m_processingClipId = info.clipId;
m_infoMutex.unlock();
-
+
QString path;
bool proxyProducer;
if (info.xml.hasAttribute("proxy") && info.xml.attribute("proxy") != "-") {
int imageWidth = (int)((double) info.imageHeight * m_mltProfile->width() / m_mltProfile->height() + 0.5);
int fullWidth = (int)((double) info.imageHeight * m_mltProfile->dar() + 0.5);
int frameNumber = info.xml.attribute("thumbnail", "-1").toInt();
-
+
if ((!info.replaceProducer && info.xml.hasAttribute("file_hash")) || proxyProducer) {
// Clip already has all properties
if (proxyProducer) {
stringMap filePropertyMap;
stringMap metadataPropertyMap;
char property[200];
-
+
if (frameNumber > 0) producer->seek(frameNumber);
-
+
duration = duration > 0 ? duration : producer->get_playtime();
filePropertyMap["duration"] = QString::number(duration);
//kDebug() << "/////// PRODUCER: " << url.path() << " IS: " << producer->get_playtime();
}
}
}
-
+
// Get frame rate
- int vindex = producer->get_int("video_index");
+ int vindex = producer->get_int("video_index");
if (vindex > -1) {
snprintf(property, sizeof(property), "meta.media.%d.stream.frame_rate", vindex);
if (producer->get(property))
int video_max = 0;
int default_audio = producer->get_int("audio_index");
int audio_max = 0;
-
+
int scan = producer->get_int("meta.media.progressive");
filePropertyMap["progressive"] = QString::number(scan);
Mlt::Consumer xmlConsumer(*m_mltProfile, ("xml:" + url.path()).toUtf8().constData());
m_mltProducer->optimise();
xmlConsumer.set("terminate_on_pause", 1);
- if (m_name == "clip") {
+ if (m_name == Kdenlive::clipMonitor) {
Mlt::Producer *prod = m_mltProducer->cut(zone.x(), zone.y());
Mlt::Playlist list;
list.insert_at(0, prod, 0);
return;
if (m_isZoneMode) resetZoneMode();
if (play && m_mltProducer->get_speed() == 0.0) {
- if (m_name == "clip" && m_mltConsumer->position() == m_mltProducer->get_out()) m_mltProducer->seek(0);
+ if (m_name == Kdenlive::clipMonitor && m_mltConsumer->position() == m_mltProducer->get_out()) m_mltProducer->seek(0);
if (m_mltConsumer->is_stopped()) {
m_mltConsumer->start();
}
m_mltProducer->seek(m_mltConsumer->position());
if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
if (m_isZoneMode) resetZoneMode();
-
+
//emitConsumerStopped();
/*m_mltConsumer->set("refresh", 0);
m_mltConsumer->stop();
void Render::emitFrameUpdated(Mlt::Frame& frame)
{
- mlt_image_format format = mlt_image_rgb24;
+ mlt_image_format format = mlt_image_rgb24a;
+ int width = 0;
+ int height = 0;
+ const uchar* image = frame.get_image(format, width, height);
+ QImage qimage(width, height, QImage::Format_ARGB32_Premultiplied);
+ memcpy(qimage.scanLine(0), image, width * height * 4);
+
+ /*mlt_image_format format = mlt_image_rgb24;
int width = 0;
int height = 0;
const uchar* image = frame.get_image(format, width, height);
QImage qimage(width, height, QImage::Format_RGB888);
- memcpy(qimage.bits(), image, width * height * 3);
+ memcpy(qimage.bits(), image, width * height * 3);*/
emit frameUpdated(qimage);
}
}
service.lock();
return new Mlt::Tractor(service);
-
+
}
void Render::unlockService(Mlt::Tractor *tractor)
service.lock();
for (int j = 0; j < params.count(); j++) {
filter->set((prefix + params.at(j).name()).toUtf8().constData(), params.at(j).value().toUtf8().constData());
- }
+ }
delete clip;
service.unlock();
trackProducer.set("hide", 0);
}
if (audioMixingBroken) fixAudioMixing(tractor);
-
+
tractor.multitrack()->refresh();
tractor.refresh();
refresh();
void showFrame(Mlt::Frame&);
void showAudio(Mlt::Frame&);
- /** @brief This property is used to decide if the renderer should send audio data for monitoring. */
- bool analyseAudio;
QList <int> checkTrackSequence(int);
void sendFrameUpdate();
* (at your option) any later version. *
***************************************************************************/
+#include "qtconcurrentrun.h"
+
#include "abstractscopewidget.h"
#include "renderer.h"
#include "monitor.h"
-#include <QtConcurrentRun>
#include <QFuture>
#include <QColor>
#include <QMenu>
initialDimensionUpdateDone(false),
m_requestForcedUpdate(false),
m_rescaleMinDist(4),
- m_rescaleVerticalThreshold(2.0f)
+ m_rescaleVerticalThreshold(2.0f),
+ m_rescaleActive(false)
{
m_scopePalette = QPalette();
qDebug() << "Trying to start a new HUD thread for " << m_widgetName
<< ". New frames/updates: " << m_newHUDFrames << "/" << m_newHUDUpdates;
#endif
- prodHUDThread();;
+ prodHUDThread();
}
}
}
}
-bool AbstractScopeWidget::autoRefreshEnabled()
+bool AbstractScopeWidget::autoRefreshEnabled() const
{
return m_aAutoRefresh->isChecked();
}
* (at your option) any later version. *
***************************************************************************/
+
+
+#ifndef ABSTRACTSCOPEWIDGET_H
+#define ABSTRACTSCOPEWIDGET_H
+
+#include <QtCore>
+#include <QWidget>
+
+class QMenu;
/**
- This abstract widget is a proof that abstract things sometimes *are* useful.
+ \brief Abstract class for audio/colour scopes (receive data and paint it).
+
+ This abstract widget is a proof that abstract things sometimes \b *are* useful.
The widget expects three layers which
- * Will be painted on top of each other on each update
- * Are rendered in a separate thread so that the UI is not blocked
- * Are rendered only if necessary (e.g., if a layer does not depend
+ \li Will be painted on top of each other on each update
+ \li Are rendered in a separate thread so that the UI is not blocked
+ \li Are rendered only if necessary (e.g., if a layer does not depend
on input images, it will not be re-rendered for incoming frames)
The layer order is as follows:
+ \verbatim
_____________________
/ \
/ HUD Layer \
/ Background Layer \
/ \
---------------------------
+ \endverbatim
Colors of Scope Widgets are defined in here (and thus don't need to be
re-defined in the implementation of the widget's .ui file).
the comments on the unimplemented methods carefully. They are not only here
for optical amusement, but also contain important information.
*/
-
-#ifndef ABSTRACTSCOPEWIDGET_H
-#define ABSTRACTSCOPEWIDGET_H
-
-#include <QtCore>
-#include <QWidget>
-
-class QMenu;
-
class AbstractScopeWidget : public QWidget
{
Q_OBJECT
public:
- /** trackMouse enables mouse tracking; The variables m_mousePos and m_mouseWithinWidget will be set
- if mouse tracking is enabled. See also signalMousePositionChanged(). */
+ /**
+ \param trackMouse enables mouse tracking; The variables m_mousePos and m_mouseWithinWidget will be set
+ if mouse tracking is enabled.
+ \see signalMousePositionChanged(): Emitted when mouse tracking is enabled
+ */
AbstractScopeWidget(bool trackMouse = false, QWidget *parent = 0);
virtual ~AbstractScopeWidget(); // Must be virtual because of inheritance, to avoid memory leaks
/** Tell whether this scope has auto-refresh enabled. Required for determining whether
new data (e.g. an image frame) has to be delivered to this widget. */
- bool autoRefreshEnabled();
+ bool autoRefreshEnabled() const;
+
+ bool needsSingleFrame();
///// Unimplemented /////
that have to change together with the widget's size. */
virtual QRect scopeRect() = 0;
- /** @brief HUD renderer. Must emit signalHUDRenderingFinished(). @see renderScope */
+ /** @brief HUD renderer. Must emit signalHUDRenderingFinished().
+ @see renderScope(uint). */
virtual QImage renderHUD(uint accelerationFactor) = 0;
- /** @brief Scope renderer. Must emit signalScopeRenderingFinished()
- when calculation has finished, to allow multi-threading.
- accelerationFactor hints how much faster than usual the calculation should be accomplished, if possible. */
+ /** @brief Rendering function for the scope layer.
+ This function \b must emit signalScopeRenderingFinished(), otherwise the scope
+ will not attempt to ever call this function again. This signal is required for multi-threading;
+ not emitting it on unused rendering function may increase performance.
+ @param accelerationFactor hints how much faster than usual the calculation should be accomplished, if possible.
+ @see renderHUD(uint) for the upper layer
+ @see renderBackground(uint) for the layer below
+ */
virtual QImage renderScope(uint accelerationFactor) = 0;
- /** @brief Background renderer. Must emit signalBackgroundRenderingFinished(). @see renderScope */
+ /** @brief Background renderer. Must emit signalBackgroundRenderingFinished().
+ @see renderScope(uint) */
virtual QImage renderBackground(uint accelerationFactor) = 0;
/** Must return true if the HUD layer depends on the input data.
// void raise(); // Called only when manually calling the event -> useless
-protected slots:
+public slots:
/** Forces an update of all layers. */
void forceUpdate(bool doUpdate = true);
void forceUpdateHUD();
void forceUpdateScope();
void forceUpdateBackground();
+
+protected slots:
void slotAutoRefreshToggled(bool);
signals:
- /** mseconds represent the time taken for the calculation,
- accelerationFactor is the acceleration factor that has been used for this calculation. */
+ /**
+ \param mseconds represents the time taken for the calculation.
+ \param accelerationFactor is the acceleration factor that has been used for this calculation.
+ */
void signalHUDRenderingFinished(uint mseconds, uint accelerationFactor);
void signalScopeRenderingFinished(uint mseconds, uint accelerationFactor);
void signalBackgroundRenderingFinished(uint mseconds, uint accelerationFactor);
This signal is typically connected to forceUpdateHUD(). */
void signalMousePositionChanged();
- /** Do we need the renderer to send its frames to us? */
+ /** Do we need the renderer to send its frames to us?
+ Emitted when auto-refresh is toggled. */
void requestAutoRefresh(bool);
private:
/** Counts the number of data frames that have been rendered in the active monitor.
- The frame number will be reset when the calculation starts for the current data set. */
+ The frame number will be reset when the calculation starts for the current data set. */
QAtomicInt m_newHUDFrames;
QAtomicInt m_newScopeFrames;
QAtomicInt m_newBackgroundFrames;
/** Counts the number of updates that, unlike new frames, force a recalculation
- of the scope, like for example a resize event. */
+ of the scope, like for example a resize event. */
QAtomicInt m_newHUDUpdates;
QAtomicInt m_newScopeUpdates;
QAtomicInt m_newBackgroundUpdates;
/** The semaphores ensure that the QFutures for the HUD/Scope/Background threads cannot
- be assigned a new thread while it is still running. (Could cause deadlocks and other
- nasty things known from parallelism.) */
+ be assigned a new thread while it is still running. (Could cause deadlocks and other
+ nasty things known from parallelism.) */
QSemaphore m_semaphoreHUD;
QSemaphore m_semaphoreScope;
QSemaphore m_semaphoreBackground;
protected slots:
void customContextMenuRequested(const QPoint &pos);
/** To be called when a new frame has been received.
- The scope then decides whether and when it wants to recalculate the scope, depending
- on whether it is currently visible and whether a calculation thread is already running. */
+ The scope then decides whether and when it wants to recalculate the scope, depending
+ on whether it is currently visible and whether a calculation thread is already running. */
void slotRenderZoneUpdated();
/** The following slots are called when rendering of a component has finished. They e.g. update
- the widget and decide whether to immediately restart the calculation thread. */
+ the widget and decide whether to immediately restart the calculation thread. */
void slotHUDRenderingFinished(uint mseconds, uint accelerationFactor);
void slotScopeRenderingFinished(uint mseconds, uint accelerationFactor);
void slotBackgroundRenderingFinished(uint mseconds, uint accelerationFactor);
{
}
-void AbstractAudioScopeWidget::slotReceiveAudio(const QVector<int16_t> &sampleData, int freq, int num_channels, int num_samples)
+void AbstractAudioScopeWidget::slotReceiveAudio(QVector<int16_t> sampleData, int freq, int num_channels, int num_samples)
{
#ifdef DEBUG_AASW
qDebug() << "Received audio for " << widgetName() << ".";
#include <stdint.h>
-#include "abstractscopewidget.h"
+#include "../abstractscopewidget.h"
class QMenu;
class Monitor;
class Render;
+/**
+ \brief Abstract class for scopes analyzing audio samples.
+ */
class AbstractAudioScopeWidget : public AbstractScopeWidget
{
Q_OBJECT
AbstractAudioScopeWidget(bool trackMouse = false, QWidget *parent = 0);
virtual ~AbstractAudioScopeWidget();
+public slots:
+ void slotReceiveAudio(QVector<int16_t> sampleData, int freq, int num_channels, int num_samples);
+
protected:
/** @brief This is just a wrapper function, subclasses can use renderAudioScope. */
virtual QImage renderScope(uint accelerationFactor);
QVector<int16_t> m_audioFrame;
QAtomicInt m_newData;
-private slots:
- void slotReceiveAudio(const QVector<int16_t>& sampleData, int freq, int num_channels, int num_samples);
-
};
#endif // ABSTRACTAUDIOSCOPEWIDGET_H
#include "audiosignal.h"
#include <KLocale>
+#include <KDebug>
#include <QVBoxLayout>
-#include <QLabel>
#include <QAction>
+#include <QMenu>
#include <QPainter>
#include <QDebug>
#include <QList>
#include <math.h>
-AudioSignal::AudioSignal(QWidget *parent): QWidget(parent)
+AudioSignal::AudioSignal(QWidget *parent): AbstractAudioScopeWidget(false, parent)
{
- //QVBoxLayout *vbox=new QVBoxLayout(this);
- //label=new QLabel();
- //vbox->addWidget(label);
setMinimumHeight(10);
setMinimumWidth(10);
dbscale << 0 << -1 << -2 << -3 << -4 << -5 << -6 << -8 << -10 << -20 << -40 ;
- setContextMenuPolicy(Qt::ActionsContextMenu);
- m_aMonitoringEnabled = new QAction(i18n("Monitor audio signal"), this);
- m_aMonitoringEnabled->setCheckable(true);
- m_aMonitoringEnabled->setChecked(true);
- connect(m_aMonitoringEnabled, SIGNAL(toggled(bool)), this, SLOT(slotSwitchAudioMonitoring(bool)));
+ m_menu->removeAction(m_aRealtime);
connect(&m_timer,SIGNAL(timeout()),this,SLOT(slotNoAudioTimeout()));
- addAction(m_aMonitoringEnabled);
+ init();
}
AudioSignal::~AudioSignal()
{
- delete m_aMonitoringEnabled;
}
-bool AudioSignal::monitoringEnabled() const
-{
- return m_aMonitoringEnabled->isChecked();
-}
-
-void AudioSignal::slotReceiveAudio(const QVector<int16_t>& data, int, int num_channels, int samples)
+QImage AudioSignal::renderAudioScope(uint, const QVector<int16_t> audioFrame,
+ const int, const int num_channels, const int samples, const int)
{
+ QTime start = QTime::currentTime();
int num_samples = samples > 200 ? 200 : samples;
QByteArray channels;
- int num_oversample=0;
for (int i = 0; i < num_channels; i++) {
long val = 0;
- double over1=0.0;
- double over2=0.0;
for (int s = 0; s < num_samples; s ++) {
- int sample=abs(data[i+s*num_channels] / 128);
- val += sample;
- if (sample==128){
- num_oversample++;
- }else{
- num_oversample=0;
- }
- //if 3 samples over max => 1 peak over 0 db (0db=40.0)
- if (num_oversample>3){
- over1=41.0/42.0*127;
- }
- // 10 samples @max => show max signal
- if (num_oversample>10){
- over2=127;
- }
-
-
-
+ val += abs(audioFrame[i+s*num_channels] / 128);
}
- //max amplitude = 40/42, 3to10 oversamples=41, more then 10 oversamples=42
- if (over2>0.0){
- channels.append(over2);
- } else if (over1>0.0){
- channels.append(over1);
- }else
- channels.append(val / num_samples*40.0/42.0);
+ channels.append(val / num_samples);
}
- showAudio(channels);
- m_timer.start(1000);
-}
-void AudioSignal::slotNoAudioTimeout(){
- peeks.fill(0);
- showAudio(QByteArray(2,0));
- m_timer.stop();
-}
-
-void AudioSignal::showAudio(const QByteArray arr)
-{
- channels = arr;
if (peeks.count()!=channels.count()){
peeks=QByteArray(channels.count(),0);
peekage=QByteArray(channels.count(),0);
}
for (int chan=0;chan<peeks.count();chan++)
{
- peekage[chan]=peekage[chan]+1;
- if ( peeks.at(chan)<arr.at(chan) || peekage.at(chan)>50 )
+ peekage[chan] = peekage[chan]+1;
+ if ( peeks.at(chan)<channels.at(chan) || peekage.at(chan)>50 )
{
peekage[chan]=0;
- peeks[chan]=arr[chan];
+ peeks[chan]=channels[chan];
}
}
- update();
-}
-
-double AudioSignal::valueToPixel(double in)
-{
- //in=0 -> return 0 (null length from max), in=127/127 return 1 (max length )
- return 1.0- log10( in)/log10(1.0/127.0);
-}
-void AudioSignal::paintEvent(QPaintEvent* /*e*/)
-{
- if (!m_aMonitoringEnabled->isChecked()) {
- return;
- }
- QPainter p(this);
+ QImage image(m_scopeRect.size(), QImage::Format_ARGB32);
+ image.fill(Qt::transparent);
+ QPainter p(&image);
+ p.setPen(Qt::white);
+ p.setRenderHint(QPainter::TextAntialiasing, false);
+ p.setRenderHint(QPainter::Antialiasing, false);
+
int numchan = channels.size();
bool horiz=width() > height();
int dbsize=20;
for (int i = 0; i < numchan; i++) {
//int maxx= (unsigned char)channels[i] * (horiz ? width() : height() ) / 127;
double valpixel=valueToPixel((double)(unsigned char)channels[i]/127.0);
- int maxx= height() * valpixel;
+ int maxx= height() * valpixel;
int xdelta= height() /42 ;
int _y2= (showdb?width()-dbsize:width () ) / numchan - 1 ;
int _y1= (showdb?width()-dbsize:width() ) *i/numchan;
if (horiz){
dbsize=9;
showdb=height()>(dbsize);
- maxx=width()*valpixel;
+ maxx=width()*valpixel;
xdelta = width() / 42;
_y2=( showdb?height()-dbsize:height() ) / numchan - 1 ;
_y1= (showdb?height()-dbsize:height() ) * i/numchan;
}
}
int xp=valueToPixel((double)peeks.at(i)/127.0)*(horiz?width():height())-2;
- p.fillRect(horiz?xp:_y1,horiz?_y1:height()-xdelta-xp,horiz?3:_y2,horiz?_y2:3,QBrush(Qt::black,Qt::SolidPattern));
+ p.fillRect(horiz?xp:_y1,horiz?_y1:height()-xdelta-xp,horiz?3:_y2,horiz?_y2:3,QBrush(Qt::gray,Qt::SolidPattern));
}
if (showdb){
}
}
p.end();
+ emit signalScopeRenderingFinished((uint) start.elapsed(), 1);
+ return image;
+}
+
+QRect AudioSignal::scopeRect() { return QRect(0, 0, width(), height()); }
+
+QImage AudioSignal::renderHUD(uint) { return QImage(); }
+QImage AudioSignal::renderBackground(uint) { return QImage(); }
+
+void AudioSignal::slotReceiveAudio(QVector<int16_t> data, int, int num_channels, int samples)
+{
+
+ int num_samples = samples > 200 ? 200 : samples;
+
+ QByteArray channels;
+ int num_oversample=0;
+ for (int i = 0; i < num_channels; i++) {
+ long val = 0;
+ double over1=0.0;
+ double over2=0.0;
+ for (int s = 0; s < num_samples; s ++) {
+ int sample=abs(data[i+s*num_channels] / 128);
+ val += sample;
+ if (sample==128){
+ num_oversample++;
+ }else{
+ num_oversample=0;
+ }
+ //if 3 samples over max => 1 peak over 0 db (0db=40.0)
+ if (num_oversample>3){
+ over1=41.0/42.0*127;
+ }
+ // 10 samples @max => show max signal
+ if (num_oversample>10){
+ over2=127;
+ }
+
+
+
+ }
+ //max amplitude = 40/42, 3to10 oversamples=41, more then 10 oversamples=42
+ if (over2>0.0){
+ channels.append(over2);
+ } else if (over1>0.0){
+ channels.append(over1);
+ }else
+ channels.append(val / num_samples*40.0/42.0);
+ }
+ showAudio(channels);
+ m_timer.start(1000);
+}
+
+void AudioSignal::slotNoAudioTimeout(){
+ peeks.fill(0);
+ showAudio(QByteArray(2,0));
+ m_timer.stop();
+}
+
+void AudioSignal::showAudio(const QByteArray arr)
+{
+ channels = arr;
+ if (peeks.count()!=channels.count()){
+ peeks=QByteArray(channels.count(),0);
+ peekage=QByteArray(channels.count(),0);
+ }
+ for (int chan=0;chan<peeks.count();chan++)
+ {
+ peekage[chan]=peekage[chan]+1;
+ if ( peeks.at(chan)<arr.at(chan) || peekage.at(chan)>50 )
+ {
+ peekage[chan]=0;
+ peeks[chan]=arr[chan];
+ }
+ }
+ update();
}
-void AudioSignal::slotSwitchAudioMonitoring(bool)
+double AudioSignal::valueToPixel(double in)
{
- emit updateAudioMonitoring();
+ //in=0 -> return 0 (null length from max), in=127/127 return 1 (max length )
+ return 1.0- log10( in)/log10(1.0/127.0);
}
#include "audiosignal.moc"
#ifndef AUDIOSIGNAL_H
#define AUDIOSIGNAL_H
+#include "scopes/audioscopes/abstractaudioscopewidget.h"
+
#include <QByteArray>
#include <QList>
#include <QColor>
#include <stdint.h>
-class AudioSignal : public QWidget
+class AudioSignal : public AbstractAudioScopeWidget
{
Q_OBJECT
public:
/** @brief Used for checking whether audio data needs to be delivered */
bool monitoringEnabled() const;
+ QRect scopeRect();
+ QImage renderHUD(uint accelerationFactor);
+ QImage renderBackground(uint accelerationFactor);
+ QImage renderAudioScope(uint accelerationFactor, const QVector<int16_t> audioFrame, const int, const int num_channels, const int samples, const int);
+
+ QString widgetName() const { return "audioSignal"; }
+ bool isHUDDependingOnInput() const { return false; }
+ bool isScopeDependingOnInput() const { return true; }
+ bool isBackgroundDependingOnInput() const { return false; }
+
private:
double valueToPixel(double in);
- QTimer m_timer;
- QLabel* label;
+ QTimer m_timer;
QByteArray channels,peeks,peekage;
- QList<int> dbscale;
- QAction *m_aMonitoringEnabled;
-
-protected:
- void paintEvent(QPaintEvent*);
+ QList<int> dbscale;
public slots:
void showAudio(const QByteArray);
- void slotReceiveAudio(const QVector<int16_t>&,int,int,int);
+ void slotReceiveAudio(QVector<int16_t>,int,int,int);
private slots:
- void slotSwitchAudioMonitoring(bool isOn);
- void slotNoAudioTimeout();
+ void slotNoAudioTimeout();
signals:
void updateAudioMonitoring();
* (at your option) any later version. *
***************************************************************************/
-/**
- Displays a spectral power distribution of audio samples.
- The frequency distribution is calculated by means of a Fast Fourier Transformation.
- For more information see Wikipedia:FFT and the code comments.
-*/
#ifndef AUDIOSPECTRUM_H
#define AUDIOSPECTRUM_H
#include "ffttools.h"
class AudioSpectrum_UI;
+
+/**
+ \brief Displays a spectral power distribution of audio samples.
+ The frequency distribution is calculated by means of a Fast Fourier Transformation.
+ For more information see Wikipedia:FFT and the code comments.
+
+ \todo Currently only supports one channel. Add support for multiple channels.
+*/
class AudioSpectrum : public AbstractAudioScopeWidget {
Q_OBJECT
const int REALTIME_FPS = 30;
-AbstractGfxScopeWidget::AbstractGfxScopeWidget(MonitorManager *manager, bool trackMouse, QWidget *parent) :
- AbstractScopeWidget(trackMouse, parent),
- m_manager(manager)
+AbstractGfxScopeWidget::AbstractGfxScopeWidget(bool trackMouse, QWidget *parent) :
+ AbstractScopeWidget(trackMouse, parent)
{
- m_activeRender = m_manager->activeRenderer();
-
- bool b = true;
- if (m_activeRender != NULL)
- b &= connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
- Q_ASSERT(b);
}
AbstractGfxScopeWidget::~AbstractGfxScopeWidget() { }
void AbstractGfxScopeWidget::mouseReleaseEvent(QMouseEvent *event)
{
- if (!m_aAutoRefresh->isChecked() && m_activeRender) {
- m_activeRender->sendFrameUpdate();
- }
AbstractScopeWidget::mouseReleaseEvent(event);
+ emit signalFrameRequest(widgetName());
}
///// Slots /////
-void AbstractGfxScopeWidget::slotActiveMonitorChanged()
-{
- if (m_activeRender) {
- if (m_activeRender == m_manager->activeRenderer()) return;
- bool b = true;
- b &= m_activeRender->disconnect(this);
- Q_ASSERT(b);
- }
- m_activeRender = m_manager->activeRenderer();
-
- if (m_activeRender) {
-#ifdef DEBUG_AGSW
- qDebug() << "Active monitor has changed in " << widgetName() << ". Is the clip monitor active now? " << m_activeRender->name();
-#endif
- bool b = connect(m_activeRender, SIGNAL(frameUpdated(QImage)), this, SLOT(slotRenderZoneUpdated(QImage)));
- Q_ASSERT(b);
- }
-
- // Update the scope for the new monitor.
- forceUpdate(true);
-}
-
-void AbstractGfxScopeWidget::slotClearMonitor()
-{
- m_activeRender = NULL;
-}
void AbstractGfxScopeWidget::slotRenderZoneUpdated(QImage frame)
{
void AbstractGfxScopeWidget::slotAutoRefreshToggled(bool autoRefresh)
{
- if (autoRefresh && m_activeRender) {
- m_activeRender->sendFrameUpdate();
+ if (autoRefresh) {
+ emit signalFrameRequest(widgetName());
}
}
#define ABSTRACTGFXSCOPEWIDGET_H
#include <QtCore>
+#include <QtCore/QString>
#include <QWidget>
-#include "abstractscopewidget.h"
-#include "renderer.h"
+#include "../abstractscopewidget.h"
class QMenu;
-class MonitorManager;
+/**
+\brief Abstract class for scopes analyzing image frames.
+*/
class AbstractGfxScopeWidget : public AbstractScopeWidget
{
Q_OBJECT
public:
- AbstractGfxScopeWidget(MonitorManager *manager, bool trackMouse = false, QWidget *parent = 0);
+ AbstractGfxScopeWidget(bool trackMouse = false, QWidget *parent = 0);
virtual ~AbstractGfxScopeWidget(); // Must be virtual because of inheritance, to avoid memory leaks
protected:
///// Variables /////
- MonitorManager *m_manager;
- AbstractRender *m_activeRender;
-
/** @brief Scope renderer. Must emit signalScopeRenderingFinished()
when calculation has finished, to allow multi-threading.
accelerationFactor hints how much faster than usual the calculation should be accomplished, if possible. */
/** @brief Must be called when the active monitor has shown a new frame.
This slot must be connected in the implementing class, it is *not*
done in this abstract class. */
- void slotActiveMonitorChanged();
- void slotClearMonitor();
+ void slotRenderZoneUpdated(QImage);
protected slots:
virtual void slotAutoRefreshToggled(bool autoRefresh);
-private slots:
- void slotRenderZoneUpdated(QImage);
+signals:
+ void signalFrameRequest(const QString widgetName);
};
#include <QTime>
#include "colorcorrection/histogramgenerator.h"
#include "histogram.h"
-#include "renderer.h"
-Histogram::Histogram(MonitorManager *manager, QWidget *parent) :
- AbstractGfxScopeWidget(manager, false, parent)
+Histogram::Histogram(QWidget *parent) :
+ AbstractGfxScopeWidget(false, parent)
{
ui = new Ui::Histogram_UI();
ui->setupUi(this);
class HistogramGenerator;
+/**
+ * \brief Displays the histogram of frames.
+ */
class Histogram : public AbstractGfxScopeWidget {
Q_OBJECT
public:
- Histogram(MonitorManager *manager, QWidget *parent = 0);
+ Histogram(QWidget *parent = 0);
~Histogram();
QString widgetName() const;
#include <QPainter>
#include <QRect>
#include <QTime>
-#include "renderer.h"
#include "rgbparade.h"
#include "colorcorrection/rgbparadegenerator.h"
-RGBParade::RGBParade(MonitorManager *manager, QWidget *parent) :
- AbstractGfxScopeWidget(manager, true, parent)
+RGBParade::RGBParade(QWidget *parent) :
+ AbstractGfxScopeWidget(true, parent)
{
ui = new Ui::RGBParade_UI();
ui->setupUi(this);
#include "abstractgfxscopewidget.h"
#include "ui_rgbparade_ui.h"
-class Monitor;
class QImage;
class RGBParade_UI;
class RGBParadeGenerator;
+/**
+ * \brief Displays the RGB waveform of a frame.
+ * This is the same as the Waveform, but for each colour channel separately.
+ */
class RGBParade : public AbstractGfxScopeWidget
{
public:
- RGBParade(MonitorManager *manager, QWidget *parent = 0);
+ RGBParade(QWidget *parent = 0);
~RGBParade();
QString widgetName() const;
#include "colorplaneexport.h"
#include "colortools.h"
-#include "renderer.h"
#include "vectorscope.h"
#include "colorcorrection/vectorscopegenerator.h"
const QPointF YPbPr_Yl(-.5, .081);
-Vectorscope::Vectorscope(MonitorManager *manager, QWidget *parent) :
- AbstractGfxScopeWidget(manager, true, parent),
+Vectorscope::Vectorscope(QWidget *parent) :
+ AbstractGfxScopeWidget(true, parent),
m_gain(1)
{
ui = new Ui::Vectorscope_UI();
class ColorPlaneExport;
class ColorTools;
-class Render;
-class Monitor;
+
class Vectorscope_UI;
class VectorscopeGenerator;
enum BACKGROUND_MODE { BG_NONE = 0, BG_YUV = 1, BG_CHROMA = 2, BG_YPbPr = 3 };
+/**
+ \brief Displays the vectorscope of a frame.
+
+ \see VectorscopeGenerator for more details about the vectorscope.
+ */
class Vectorscope : public AbstractGfxScopeWidget {
Q_OBJECT
public:
- Vectorscope(MonitorManager *manager, QWidget *parent = 0);
+ Vectorscope(QWidget *parent = 0);
~Vectorscope();
QString widgetName() const;
#include "kdenlivesettings.h"
#include "profilesdialog.h"
-#include "renderer.h"
#include "waveform.h"
#include "colorcorrection/waveformgenerator.h"
const QSize Waveform::m_textWidth(35,0);
const int Waveform::m_paddingBottom(20);
-Waveform::Waveform(MonitorManager *manager, QWidget *parent) :
- AbstractGfxScopeWidget(manager, true, parent)
+Waveform::Waveform(QWidget *parent) :
+ AbstractGfxScopeWidget(true, parent)
,ui(NULL)
{
ui = new Ui::Waveform_UI();
class Waveform_UI;
class WaveformGenerator;
+/**
+ \brief Displays the waveform of a frame.
+
+ For further explanations of the waveform see the WaveformGenerator class.
+*/
class Waveform : public AbstractGfxScopeWidget {
Q_OBJECT
public:
- Waveform(MonitorManager *manager, QWidget *parent = 0);
+ Waveform(QWidget *parent = 0);
~Waveform();
virtual QString widgetName() const;