dvdwizard.cpp
locktrackcommand.cpp
groupclipscommand.cpp
+ splitaudiocommand.cpp
)
add_definitions( ${KDE4_DEFINITIONS} )
#include "kthumb.h"
#include <KDebug>
+#include <KIcon>
#include <QPainter>
#include <QTimer>
ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, bool generateThumbs)
- : AbstractClipItem(info, QRectF(), fps), m_clip(clip), m_resizeMode(NONE), m_grabPoint(0), m_maxTrack(0), m_hasThumbs(false), startThumbTimer(NULL), endThumbTimer(NULL), audioThumbWasDrawn(false), m_opacity(1.0), m_timeLine(0), m_startThumbRequested(false), m_endThumbRequested(false), m_startFade(0), m_endFade(0), m_hover(false), m_selectedEffect(-1), m_speed(speed), framePixelWidth(0), m_startPix(QPixmap()), m_endPix(QPixmap()) {
+ : AbstractClipItem(info, QRectF(), fps), m_clip(clip), m_resizeMode(NONE), m_grabPoint(0), m_maxTrack(0), m_hasThumbs(false), startThumbTimer(NULL), endThumbTimer(NULL), audioThumbWasDrawn(false), m_opacity(1.0), m_timeLine(0), m_startThumbRequested(false), m_endThumbRequested(false), m_startFade(0), m_endFade(0), m_hover(false), m_selectedEffect(-1), m_speed(speed), framePixelWidth(0), m_startPix(QPixmap()), m_endPix(QPixmap()), m_videoOnly(false), m_audioOnly(false) {
setZValue(1);
setRect(0, 0, (info.endPos - info.startPos).frames(fps) - 0.02, (double)(KdenliveSettings::trackheight() - 2));
setPos(info.startPos.frames(fps), (double)(info.track * KdenliveSettings::trackheight()) + 1);
}
// Draw clip name
+
QRectF txtBounding = painter->boundingRect(mapped, Qt::AlignHCenter | Qt::AlignVCenter, ' ' + m_clipName + ' ');
painter->fillRect(txtBounding, QBrush(QColor(0, 0, 0, 150)));
//painter->setPen(QColor(0, 0, 0, 180));
//painter->drawText(txtBounding, Qt::AlignCenter, m_clipName);
+ if (m_videoOnly) {
+ painter->drawPixmap(txtBounding.topLeft() - QPointF(17, -1), KIcon("video-x-generic").pixmap(QSize(15, 15)));
+ } else if (m_audioOnly) {
+ painter->drawPixmap(txtBounding.topLeft() - QPointF(17, -1), KIcon("audio-x-generic").pixmap(QSize(15, 15)));
+ }
txtBounding.translate(QPointF(1, 1));
painter->setPen(QColor(255, 255, 255, 255));
painter->drawText(txtBounding, Qt::AlignCenter, m_clipName);
QDomElement e = doc.documentElement();
//if (view) view->slotAddTransition(this, t->toXML() , t->startPos(), track());
}
+
+void ClipItem::setVideoOnly(bool force) {
+ m_videoOnly = force;
+}
+
+void ClipItem::setAudioOnly(bool force) {
+ m_audioOnly = force;
+}
+
// virtual
/*
void CustomTrackView::mousePressEvent ( QMouseEvent * event )
bool checkKeyFrames();
QPixmap startThumb() const;
QPixmap endThumb() const;
+ void setVideoOnly(bool force);
+ void setAudioOnly(bool force);
protected:
//virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
uint m_startFade;
uint m_endFade;
int m_maxTrack;
+ bool m_audioOnly;
+ bool m_videoOnly;
QPixmap m_startPix;
QPixmap m_endPix;
#include "initeffects.h"
#include "locktrackcommand.h"
#include "groupclipscommand.h"
+#include "splitaudiocommand.h"
#include <KDebug>
#include <KLocale>
}
}
+void CustomTrackView::splitAudio() {
+ resetSelectionGroup();
+ QList<QGraphicsItem *> selection = scene()->selectedItems();
+ if (selection.isEmpty()) {
+ emit displayMessage(i18n("You must select one clip for this action"), ErrorMessage);
+ return;
+ }
+ QUndoCommand *splitCommand = new QUndoCommand();
+ splitCommand->setText(i18n("Split audio"));
+ for (int i = 0; i < selection.count(); i++) {
+ if (selection.at(i)->type() == AVWIDGET) {
+ ClipItem *clip = static_cast <ClipItem *>(selection.at(i));
+ if (clip->clipType() == AV || clip->clipType() == PLAYLIST) {
+ if (clip->parentItem()) {
+ emit displayMessage(i18n("Cannot split audio of grouped clips"), ErrorMessage);
+ } else {
+ new SplitAudioCommand(this, clip->track(), clip->startPos(), true, splitCommand);
+ }
+ }
+ }
+ }
+ m_commandStack->push(splitCommand);
+}
+
+void CustomTrackView::doSplitAudio(const GenTime &pos, int track, bool split) {
+ ClipItem *clip = getClipItemAt(pos, track);
+ if (clip == NULL) {
+ kDebug() << "// Cannot find clip to split!!!";
+ return;
+ }
+ if (split) {
+ int start = pos.frames(m_document->fps());
+ int freetrack = m_document->tracksCount() - track - 1;
+ for (; freetrack > 0; freetrack--) {
+ kDebug() << "// CHK DOC TRK:" << freetrack << ", DUR:" << m_document->renderer()->mltTrackDuration(freetrack);
+ if (m_document->trackInfoAt(freetrack - 1).type == AUDIOTRACK) {
+ kDebug() << "// CHK DOC TRK:" << freetrack << ", DUR:" << m_document->renderer()->mltTrackDuration(freetrack);
+ if (m_document->renderer()->mltTrackDuration(freetrack) < start || m_document->renderer()->mltGetSpaceLength(pos, freetrack, false) >= clip->duration().frames(m_document->fps())) {
+ kDebug() << "FOUND SPACE ON TRK: " << freetrack;
+ break;
+ }
+ }
+ }
+ kDebug() << "GOT TRK: " << track;
+ if (freetrack == 0) {
+ emit displayMessage(i18n("No empty space to put clip audio"), ErrorMessage);
+ } else {
+ ItemInfo info;
+ info.startPos = clip->startPos();
+ info.endPos = clip->endPos();
+ info.cropStart = clip->cropStart();
+ info.track = m_document->tracksCount() - freetrack;
+ addClip(clip->xml(), clip->clipProducer(), info, clip->effectList());
+ scene()->clearSelection();
+ clip->setSelected(true);
+ ClipItem *audioClip = getClipItemAt(start, info.track);
+ if (audioClip) {
+ clip->setVideoOnly(true);
+ m_document->renderer()->mltUpdateClipProducer(m_document->tracksCount() - track, start, clip->baseClip()->videoProducer());
+ m_document->renderer()->mltUpdateClipProducer(m_document->tracksCount() - info.track, start, clip->baseClip()->audioProducer());
+ audioClip->setSelected(true);
+ audioClip->setAudioOnly(true);
+ groupSelectedItems(false, true);
+ }
+ }
+ }
+}
+
#include "customtrackview.moc"
void groupClips(bool group = true);
void doGroupClips(QList <ItemInfo> clipInfos, QList <ItemInfo> transitionInfos, bool group);
void loadGroups(const QDomNodeList groups);
+ void splitAudio();
+ void doSplitAudio(const GenTime &pos, int track, bool split);
public slots:
void setCursorPos(int pos, bool seek = true);
#include <QCryptographicHash>
DocClipBase::DocClipBase(ClipManager *clipManager, QDomElement xml, const QString &id):
- m_id(id), m_description(QString()), m_refcount(0), m_audioThumbCreated(false), m_duration(GenTime()), m_thumbProd(NULL), m_audioTimer(NULL), m_properties(QMap <QString, QString> ()), audioFrameChache(QMap<int, QMap<int, QByteArray> > ()), m_baseTrackProducers(QList <Mlt::Producer *>()), m_snapMarkers(QList < CommentedTime > ()) {
+ m_id(id), m_description(QString()), m_refcount(0), m_audioThumbCreated(false), m_duration(GenTime()), m_thumbProd(NULL), m_audioTimer(NULL), m_properties(QMap <QString, QString> ()), audioFrameChache(QMap<int, QMap<int, QByteArray> > ()), m_baseTrackProducers(QList <Mlt::Producer *>()), m_snapMarkers(QList < CommentedTime > ()), m_videoOnlyProducer(NULL), m_audioOnlyProducer(NULL) {
int type = xml.attribute("type").toInt();
m_clipType = (CLIPTYPE) type;
QString id = producer->get("id");
if (id.contains('_')) {
// this is a subtrack producer, insert it at correct place
- int pos = id.section('_', 1, 1).toInt();
+ id = id.section('_', 1, 1);
+ if (id == "audio") {
+ m_audioOnlyProducer = producer;
+ return;
+ }
+ if (id == "video") {
+ m_videoOnlyProducer = producer;
+ return;
+ }
+ int pos = id.toInt();
if (pos >= m_baseTrackProducers.count()) {
while (m_baseTrackProducers.count() - 1 < pos) {
m_baseTrackProducers.append(NULL);
if (m_thumbProd && !m_thumbProd->hasProducer()) m_thumbProd->setProducer(producer);
}
+Mlt::Producer *DocClipBase::audioProducer() {
+ if (m_audioOnlyProducer == NULL) {
+ int i;
+ for (i = 0; i < m_baseTrackProducers.count(); i++)
+ if (m_baseTrackProducers.at(i) != NULL) break;
+ if (i >= m_baseTrackProducers.count()) return NULL;
+ m_audioOnlyProducer = new Mlt::Producer(*m_baseTrackProducers.at(i)->profile(), m_baseTrackProducers.at(i)->get("resource"));
+ if (m_properties.contains("force_aspect_ratio")) m_audioOnlyProducer->set("force_aspect_ratio", m_properties.value("force_aspect_ratio").toDouble());
+ if (m_properties.contains("threads")) m_audioOnlyProducer->set("threads", m_properties.value("threads").toInt());
+ m_audioOnlyProducer->set("video_index", -1);
+ if (m_properties.contains("audio_index")) m_audioOnlyProducer->set("audio_index", m_properties.value("audio_index").toInt());
+ char *tmp = (char *) qstrdup(QString(getId() + "_audio").toUtf8().data());
+ m_audioOnlyProducer->set("id", tmp);
+ delete[] tmp;
+ }
+ return m_audioOnlyProducer;
+}
+
+Mlt::Producer *DocClipBase::videoProducer() {
+ if (m_videoOnlyProducer == NULL) {
+ int i;
+ for (i = 0; i < m_baseTrackProducers.count(); i++)
+ if (m_baseTrackProducers.at(i) != NULL) break;
+ if (i >= m_baseTrackProducers.count()) return NULL;
+ m_videoOnlyProducer = new Mlt::Producer(*m_baseTrackProducers.at(i)->profile(), m_baseTrackProducers.at(i)->get("resource"));
+ if (m_properties.contains("force_aspect_ratio")) m_videoOnlyProducer->set("force_aspect_ratio", m_properties.value("force_aspect_ratio").toDouble());
+ if (m_properties.contains("threads")) m_videoOnlyProducer->set("threads", m_properties.value("threads").toInt());
+ m_videoOnlyProducer->set("audio_index", -1);
+ if (m_properties.contains("video_index")) m_videoOnlyProducer->set("video_index", m_properties.value("video_index").toInt());
+ char *tmp = (char *) qstrdup(QString(getId() + "_video").toUtf8().data());
+ m_videoOnlyProducer->set("id", tmp);
+ delete[] tmp;
+ }
+ return m_videoOnlyProducer;
+}
+
Mlt::Producer *DocClipBase::producer(int track) {
/*for (int i = 0; i < m_baseTrackProducers.count(); i++) {
if (m_baseTrackProducers.at(i)) kDebug() << "// PROD: " << i << ", ID: " << m_baseTrackProducers.at(i)->get("id");
return false;
}
+ /** Sets producers for the current clip (one for each track due to a limitation in MLT's track mixing */
void setProducer(Mlt::Producer *producer);
+ /** Retrieve a producer for a track */
Mlt::Producer *producer(int track = -1);
+ /** Retrieve the producer that shows only video */
+ Mlt::Producer *videoProducer();
+ /** Retrieve the producer that shows only audio */
+ Mlt::Producer *audioProducer();
/** Returns true if this clip is a project clip, false otherwise. Overridden in DocClipProject,
* where it returns true. */
* that exist. */
uint m_refcount;
QList <Mlt::Producer *> m_baseTrackProducers;
+ Mlt::Producer *m_audioOnlyProducer;
+ Mlt::Producer *m_videoOnlyProducer;
CLIPTYPE m_clipType;
/** A list of snap markers; these markers are added to a clips snap-to points, and are displayed as necessary. */
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<gui name="kdenlive" version="37">
+<gui name="kdenlive" version="38">
<ToolBar name="extraToolBar" >
<text>Extra Toolbar</text>
<Action name="project_render" />
<Action name="delete_all_clip_markers" />
</Menu>
<Action name="auto_transition" />
+ <Action name="split_audio" />
</Menu>
<Menu name="timeline" ><text>Timeline</text>
m_timelineContextClipMenu->addAction(actionCollection()->action("cut_timeline_clip"));
m_timelineContextClipMenu->addAction(actionCollection()->action(KStandardAction::name(KStandardAction::Copy)));
m_timelineContextClipMenu->addAction(actionCollection()->action("paste_effects"));
+ m_timelineContextClipMenu->addAction(actionCollection()->action("split_audio"));
QMenu *markersMenu = (QMenu*)(factory()->container("marker_menu", this));
m_timelineContextClipMenu->addMenu(markersMenu);
collection->addAction("edit_clip_marker", editClipMarker);
connect(editClipMarker, SIGNAL(triggered(bool)), this, SLOT(slotEditClipMarker()));
+ KAction* splitAudio = new KAction(KIcon("document-new"), i18n("Split Audio"), this);
+ collection->addAction("split_audio", splitAudio);
+ connect(splitAudio, SIGNAL(triggered(bool)), this, SLOT(slotSplitAudio()));
+
KAction *insertSpace = new KAction(KIcon(), i18n("Insert Space"), this);
collection->addAction("insert_space", insertSpace);
connect(insertSpace, SIGNAL(triggered()), this, SLOT(slotInsertSpace()));
}
void MainWindow::slotAutoTransition() {
- m_activeTimeline->projectView()->autoTransition();
+ if (m_activeTimeline) m_activeTimeline->projectView()->autoTransition();
+}
+
+void MainWindow::slotSplitAudio() {
+ if (m_activeTimeline) m_activeTimeline->projectView()->splitAudio();
}
void MainWindow::slotDvdWizard(const QString &url, const QString &profile) {
void slotDvdWizard(const QString &url = QString(), const QString &profile = "dv_pal");
void slotGroupClips();
void slotUnGroupClips();
+ void slotSplitAudio();
signals:
Q_SCRIPTABLE void abortRenderJob(const QString &url);
double trackDuration;
if (trackNb == 1) {
Mlt::Producer trackProducer(tractor.track(0));
- Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
- duration = Mlt::Producer(trackPlaylist.get_producer()).get_playtime() - 1;
+ duration = trackProducer.get_playtime() - 1;
m_mltProducer->set("out", duration);
emit durationChanged((int) duration);
return;
}
while (trackNb > 1) {
Mlt::Producer trackProducer(tractor.track(trackNb - 1));
- Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
- trackDuration = Mlt::Producer(trackPlaylist.get_producer()).get_playtime() - 1;
+ trackDuration = trackProducer.get_playtime() - 1;
//kDebug() << " / / /DURATON FOR TRACK " << trackNb - 1 << " = " << trackDuration;
if (trackDuration > duration) duration = trackDuration;
}
Mlt::Producer blackTrackProducer(tractor.track(0));
- Mlt::Playlist blackTrackPlaylist((mlt_playlist) blackTrackProducer.get_service());
- double blackDuration = Mlt::Producer(blackTrackPlaylist.get_producer()).get_playtime() - 1;
+ double blackDuration = blackTrackProducer.get_playtime() - 1;
if (blackDuration != duration) {
+ Mlt::Playlist blackTrackPlaylist((mlt_playlist) blackTrackProducer.get_service());
blackTrackPlaylist.clear();
int dur = (int)duration;
while (dur > 14000) {
return trackPlaylist.clip_length(clipIndex) + trackPlaylist.clip_start(clipIndex) - insertPos;
}
+int Render::mltTrackDuration(int track) {
+ if (!m_mltProducer) {
+ kDebug() << "PLAYLIST NOT INITIALISED //////";
+ return -1;
+ }
+ Mlt::Producer parentProd(m_mltProducer->parent());
+ if (parentProd.get_producer() == NULL) {
+ kDebug() << "PLAYLIST BROKEN, CANNOT INSERT CLIP //////";
+ return -1;
+ }
+
+ Mlt::Service service(parentProd.get_service());
+ Mlt::Tractor tractor(service);
+
+ Mlt::Producer trackProducer(tractor.track(track));
+ return trackProducer.get_playtime() - 1;
+}
void Render::mltInsertSpace(QMap <int, int> trackClipStartList, QMap <int, int> trackTransitionStartList, int track, const GenTime duration, const GenTime timeOffset) {
if (!m_mltProducer) {
Mlt::Producer *clip;
// check if we are moving a slowmotion producer
QString serv = clipProducer.parent().get("mlt_service");
- if (serv == "framebuffer") {
+ QString currentid = clipProducer.parent().get("id");
+ if (serv == "framebuffer" || currentid.endsWith("_video")) {
clip = &clipProducer;
} else clip = prod->cut(clipProducer.get_in(), clipProducer.get_out());
void mltCutClip(int track, GenTime position);
void mltInsertSpace(QMap <int, int> trackClipStartList, QMap <int, int> trackTransitionStartList, int track, const GenTime duration, const GenTime timeOffset);
int mltGetSpaceLength(const GenTime pos, int track, bool fromBlankStart);
+ int mltTrackDuration(int track);
bool mltResizeClipEnd(ItemInfo info, GenTime clipDuration);
bool mltResizeClipStart(ItemInfo info, GenTime diff);
bool mltResizeClipCrop(ItemInfo info, GenTime diff);
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+
+#include "splitaudiocommand.h"
+#include "customtrackview.h"
+
+#include <KLocale>
+
+SplitAudioCommand::SplitAudioCommand(CustomTrackView *view, const int track, const GenTime &pos, bool doIt, QUndoCommand * parent) : QUndoCommand(parent), m_view(view), m_track(track), m_pos(pos), m_doIt(doIt) {
+ setText(i18n("Split audio"));
+}
+
+// virtual
+void SplitAudioCommand::undo() {
+// kDebug()<<"---- undoing action";
+ m_doIt = true;
+ m_view->doSplitAudio(m_pos, m_track, false);
+}
+// virtual
+void SplitAudioCommand::redo() {
+ kDebug() << "---- redoing action";
+ if (m_doIt)
+ m_view->doSplitAudio(m_pos, m_track, true);
+ m_doIt = true;
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2009 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+
+#ifndef SPLITAUDIOCOMMAND_H
+#define SPLITAUDIOCOMMAND_H
+
+#include <QUndoCommand>
+#include <QGraphicsView>
+#include <QPointF>
+
+#include <KDebug>
+#include "definitions.h"
+
+class GenTime;
+class CustomTrackView;
+
+class SplitAudioCommand : public QUndoCommand {
+public:
+ SplitAudioCommand(CustomTrackView *view, const int track, const GenTime &pos, bool doIt, QUndoCommand * parent = 0);
+ virtual void undo();
+ virtual void redo();
+
+private:
+ CustomTrackView *m_view;
+ const GenTime m_pos;
+ const int m_track;
+ bool m_doIt;
+};
+
+#endif
+
clipinfo.track = ix;
//kDebug() << "// INSERTING CLIP: " << in << "x" << out << ", track: " << ix << ", ID: " << id << ", SCALE: " << m_scale << ", FPS: " << m_doc->fps();
ClipItem *item = new ClipItem(clip, clipinfo, m_doc->fps(), speed, false);
+ if (idString.endsWith("_video")) item->setVideoOnly(true);
+ else if (idString.endsWith("_audio")) item->setAudioOnly(true);
m_scene->addItem(item);
if (locked) item->setItemLocked(true);
clip->addReference();