[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdenlive/refactoring_timeline] src: Qml timeline: audio thumbnails (still requires timeline <> bin
From: Jean-Baptiste Mardelle <null () kde ! org>
Date: 2017-02-28 20:35:16
Message-ID: E1cioUO-00051Y-OH () code ! kde ! org
[Download RAW message or body]
Git commit c5aedee4141f001523a510a1d74901998682d71f by Jean-Baptiste Mardelle.
Committed on 28/02/2017 at 20:35.
Pushed by mardelle into branch 'refactoring_timeline'.
Qml timeline: audio thumbnails (still requires timeline <> bin communication to \
extract data
M +10 -0 src/bin/bin.cpp
M +1 -0 src/bin/bin.h
M +1 -0 src/timeline/clipitem.cpp
M +4 -0 src/timeline2/model/timelineitemmodel.cpp
M +8 -8 src/timeline2/view/qml/Clip.qml
M +1 -1 src/timeline2/view/qml/Track.qml
M +56 -0 src/timeline2/view/qml/timelineitems.cpp
M +4 -0 src/timeline2/view/timelinewidget.cpp
M +3 -0 src/timeline2/view/timelinewidget.h
https://commits.kde.org/kdenlive/c5aedee4141f001523a510a1d74901998682d71f
diff --git a/src/bin/bin.cpp b/src/bin/bin.cpp
index 1bdcedab3..555c92677 100644
--- a/src/bin/bin.cpp
+++ b/src/bin/bin.cpp
@@ -3825,3 +3825,13 @@ void Bin::saveZone(const QStringList &info, const QDir &dir)
clip->controller()->saveZone(zone, dir);
}
}
+
+QVariantList Bin::audioFrameCache(const QString &id)
+{
+ ProjectClip *clip = getBinClip(id);
+ if (clip && clip->controller()) {
+ return clip->audioFrameCache;
+ } else {
+ return QVariantList();
+ }
+}
diff --git a/src/bin/bin.h b/src/bin/bin.h
index 888e3dfdd..7c8869d83 100644
--- a/src/bin/bin.h
+++ b/src/bin/bin.h
@@ -530,6 +530,7 @@ public:
const QStringList getFolderInfo(const QModelIndex &selectedIx = QModelIndex());
/** @brief Save a clip zone as MLT playlist */
void saveZone(const QStringList &info, const QDir &dir);
+ QVariantList audioFrameCache(const QString &id);
private slots:
void slotAddClip();
diff --git a/src/timeline/clipitem.cpp b/src/timeline/clipitem.cpp
index 7bbe3229d..7ac113915 100644
--- a/src/timeline/clipitem.cpp
+++ b/src/timeline/clipitem.cpp
@@ -1,3 +1,4 @@
+
/***************************************************************************
* Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
* *
diff --git a/src/timeline2/model/timelineitemmodel.cpp \
b/src/timeline2/model/timelineitemmodel.cpp index bc7e124bf..f2d5665b1 100644
--- a/src/timeline2/model/timelineitemmodel.cpp
+++ b/src/timeline2/model/timelineitemmodel.cpp
@@ -219,6 +219,10 @@ QVariant TimelineItemModel::data(const QModelIndex &index, int \
role) const case ServiceRole:
return clip->getProperty("mlt_service");
break;
+ case AudioLevelsRole:
+ //TODO: get data from bin clip when interface is ready
+ //return \
QVariant::fromValue(pCore->bin()->audioFrameCache(clip->getProperty("kdenlive:id"))); \
+ return QVariant(); case IsBlankRole: //probably useless
return false;
case StartRole:
diff --git a/src/timeline2/view/qml/Clip.qml b/src/timeline2/view/qml/Clip.qml
index 43769087a..4ac8df10c 100644
--- a/src/timeline2/view/qml/Clip.qml
+++ b/src/timeline2/view/qml/Clip.qml
@@ -93,16 +93,16 @@ Rectangle {
isAudio = track.isAudio
height = track.height
y = track.y
- //generateWaveform()
+ generateWaveform()
}
- /*function generateWaveform() {
+ function generateWaveform() {
// This is needed to make the model have the correct count.
// Model as a property expression is not working in all cases.
waveformRepeater.model = Math.ceil(waveform.innerWidth / waveform.maxWidth)
for (var i = 0; i < waveformRepeater.count; i++)
waveformRepeater.itemAt(0).update()
- }*/
+ }
function imagePath(time) {
if (isAudio || isBlank || isTransition) {
@@ -112,7 +112,7 @@ Rectangle {
}
}
- //onAudioLevelsChanged: generateWaveform()
+ onAudioLevelsChanged: generateWaveform()
Image {
id: outThumbnail
@@ -155,7 +155,7 @@ Rectangle {
Row {
id: waveform
- visible: !isBlank //&& settings.timelineShowWaveforms
+ visible: timeline.showWaveforms()
height: isAudio? parent.height : parent.height / 2
anchors.left: parent.left
anchors.bottom: parent.bottom
@@ -164,18 +164,18 @@ Rectangle {
property int maxWidth: 10000
property int innerWidth: clipRoot.width - clipRoot.border.width * 2
- /*Repeater {
+ Repeater {
id: waveformRepeater
TimelineWaveform {
width: Math.min(waveform.innerWidth, waveform.maxWidth)
height: waveform.height
- fillColor: getColor()
+ fillColor: 'red'
property int channels: 2
inPoint: Math.round((clipRoot.inPoint + index * waveform.maxWidth / \
timeScale) * speed) * channels
outPoint: inPoint + Math.round(width / timeScale * speed) * channels
levels: audioLevels
}
- }*/
+ }
}
Rectangle {
diff --git a/src/timeline2/view/qml/Track.qml b/src/timeline2/view/qml/Track.qml
index 5d28ede8a..7f2f2ba0c 100644
--- a/src/timeline2/view/qml/Track.qml
+++ b/src/timeline2/view/qml/Track.qml
@@ -74,7 +74,7 @@ Column{
binId: model.binId
isAudio: false //model.audio
isTransition: false //model.isTransition
- audioLevels: false //model.audioLevels
+ audioLevels: model.audioLevels
width: model.duration * timeScale
height: parent.height
modelStart: model.start
diff --git a/src/timeline2/view/qml/timelineitems.cpp \
b/src/timeline2/view/qml/timelineitems.cpp index 1eb65617e..aec276ace 100644
--- a/src/timeline2/view/qml/timelineitems.cpp
+++ b/src/timeline2/view/qml/timelineitems.cpp
@@ -37,9 +37,65 @@ class TimelinePlayhead : public QQuickPaintedItem
}
};
+class TimelineWaveform : public QQuickPaintedItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant levels MEMBER m_audioLevels NOTIFY propertyChanged)
+ Q_PROPERTY(QColor fillColor MEMBER m_color NOTIFY propertyChanged)
+ Q_PROPERTY(int inPoint MEMBER m_inPoint NOTIFY inPointChanged)
+ Q_PROPERTY(int outPoint MEMBER m_outPoint NOTIFY outPointChanged)
+
+public:
+ TimelineWaveform()
+ {
+ setAntialiasing(QPainter::Antialiasing);
+ connect(this, SIGNAL(propertyChanged()), this, SLOT(update()));
+ }
+
+ void paint(QPainter *painter)
+ {
+ QVariantList data = m_audioLevels.toList();
+ if (data.isEmpty())
+ return;
+
+ const qreal indicesPrPixel = qreal(m_outPoint - m_inPoint) / width();
+
+ QPainterPath path;
+ path.moveTo(-1, height());
+ int i = 0;
+ for (; i < width(); ++i)
+ {
+ int idx = m_inPoint + int(i * indicesPrPixel);
+ if (idx + 1 >= data.length())
+ break;
+ qreal level = qMax(data.at(idx).toReal(), data.at(idx + 1).toReal()) / \
256; + path.lineTo(i, height() - level * height());
+ }
+ path.lineTo(i, height());
+ painter->fillPath(path, m_color.lighter());
+
+ QPen pen(painter->pen());
+ pen.setColor(m_color.darker());
+ painter->strokePath(path, pen);
+ }
+
+signals:
+ void propertyChanged();
+ void inPointChanged();
+ void outPointChanged();
+
+private:
+ QVariant m_audioLevels;
+ int m_inPoint;
+ int m_outPoint;
+ QColor m_color;
+};
void registerTimelineItems()
{
qmlRegisterType<TimelineTriangle>("Kdenlive.Controls", 1, 0, \
"TimelineTriangle");
qmlRegisterType<TimelinePlayhead>("Kdenlive.Controls", 1, 0, \
"TimelinePlayhead"); + qmlRegisterType<TimelineWaveform>("Kdenlive.Controls", 1, \
0, "TimelineWaveform"); }
+
+#include "timelineitems.moc"
diff --git a/src/timeline2/view/timelinewidget.cpp \
b/src/timeline2/view/timelinewidget.cpp index cd35f672d..b30bec084 100644
--- a/src/timeline2/view/timelinewidget.cpp
+++ b/src/timeline2/view/timelinewidget.cpp
@@ -266,3 +266,7 @@ bool TimelineWidget::showThumbnails() const
return KdenliveSettings::videothumbnails();
}
+bool TimelineWidget::showWaveforms() const
+{
+ return KdenliveSettings::audiothumbnails();
+}
diff --git a/src/timeline2/view/timelinewidget.h \
b/src/timeline2/view/timelinewidget.h index ab36ea535..261044349 100644
--- a/src/timeline2/view/timelinewidget.h
+++ b/src/timeline2/view/timelinewidget.h
@@ -138,6 +138,9 @@ public:
/* @brief Do we want to display video thumbnails
*/
Q_INVOKABLE bool showThumbnails() const;
+ /* @brief Do we want to display audio thumbnails
+ */
+ Q_INVOKABLE bool showWaveforms() const;
protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic