return m_fps;
}
+void AbstractClipItem::updateFps(double fps)
+{
+ m_fps = fps;
+ setPos((qreal) startPos().frames(m_fps), pos().y());
+ updateRectGeometry();
+}
+
GenTime AbstractClipItem::maxDuration() const
{
return m_maxDuration;
virtual void resizeStart(int posx, double speed = 1.0);
virtual void resizeEnd(int posx, double speed = 1.0);
virtual double fps() const;
+ virtual void updateFps(double fps);
virtual GenTime maxDuration() const;
virtual void setCropStart(GenTime pos);
}
QList<QGraphicsItem *> selection = m_scene->selectedItems();
if (selection.isEmpty()) return;
- QPointF top = selection.at(0)->sceneBoundingRect().topLeft();
+ QRectF rectUnion;
// Find top left position of selection
- for (int i = 1; i < selection.count(); i++) {
+ for (int i = 0; i < selection.count(); i++) {
if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET) {
- QPointF currenttop = selection.at(i)->sceneBoundingRect().topLeft();
- if (currenttop.x() < top.x()) top.setX(currenttop.x());
- if (currenttop.y() < top.y()) top.setY(currenttop.y());
+ rectUnion = rectUnion.united(selection.at(i)->sceneBoundingRect());
}
}
KdenliveSettings::setSnaptopoints(false);
if (createNewGroup) {
AbstractGroupItem *newGroup = m_document->clipManager()->createGroup();
- newGroup->translate(-top.x(), -top.y() + 1);
- newGroup->setPos(top.x(), top.y() - 1);
+ newGroup->translate(-rectUnion.left(), -rectUnion.top() + 1);
+ newGroup->setPos(rectUnion.left(), rectUnion.top() - 1);
scene()->addItem(newGroup);
// CHeck if we are trying to include a group in a group
KdenliveSettings::setSnaptopoints(snap);
} else {
m_selectionGroup = new AbstractGroupItem(m_document->fps());
- m_selectionGroup->translate(-top.x(), -top.y() + 1);
- m_selectionGroup->setPos(top.x(), top.y() - 1);
+ m_selectionGroup->translate(-rectUnion.left(), -rectUnion.top() + 1);
+ m_selectionGroup->setPos(rectUnion.left(), rectUnion.top() - 1);
scene()->addItem(m_selectionGroup);
for (int i = 0; i < selection.count(); i++) {
if (selection.at(i)->parentItem() == NULL && (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET || selection.at(i)->type() == GROUPWIDGET)) {
ClipItem *clip = getClipItemAt(startClip.at(i).startPos, startClip.at(i).track);
if (clip) {
clip->setItemLocked(false);
- if (clip->parentItem()) clip->parentItem()->setSelected(true);
- else clip->setSelected(true);
+ if (clip->parentItem()) {
+ clip->parentItem()->setSelected(true);
+ }
+ clip->setSelected(true);
m_document->renderer()->mltRemoveClip(m_document->tracksCount() - startClip.at(i).track, startClip.at(i).startPos);
} else kDebug() << "//MISSING CLIP AT: " << startClip.at(i).startPos.frames(25);
}
Transition *tr = getTransitionItemAt(startTransition.at(i).startPos, startTransition.at(i).track);
if (tr) {
tr->setItemLocked(false);
- if (tr->parentItem()) tr->parentItem()->setSelected(true);
- else tr->setSelected(true);
+ if (tr->parentItem()) {
+ tr->parentItem()->setSelected(true);
+ } else tr->setSelected(true);
m_document->renderer()->mltDeleteTransition(tr->transitionTag(), tr->transitionEndTrack(), m_document->tracksCount() - startTransition.at(i).track, startTransition.at(i).startPos, startTransition.at(i).endPos, tr->toXML());
} else kDebug() << "//MISSING TRANSITION AT: " << startTransition.at(i).startPos.frames(25);
}
for (int i = 0; i < max; i++) {
if (children.at(i)->type() == GROUPWIDGET) {
children += children.at(i)->childItems();
+ AbstractGroupItem *grp = static_cast<AbstractGroupItem *>(children.at(i));
+ //grp->moveBy(offset.frames(m_document->fps()), trackOffset *(qreal) m_tracksHeight);
+ /*m_document->clipManager()->removeGroup(grp);
+ m_scene->destroyItemGroup(grp);*/
+ children.removeAll(children.at(i));
+ i--;
}
}
return false;
}
}
- Guide *g = new Guide(this, pos, comment, m_document->fps(), m_tracksHeight * m_document->tracksCount());
+ Guide *g = new Guide(this, pos, comment, m_tracksHeight * m_document->tracksCount());
scene()->addItem(g);
m_guides.append(g);
qSort(m_guides.begin(), m_guides.end(), sortGuidesList);
emit transitionItemSelected(NULL);
}
-#include "customtrackview.moc"
+double CustomTrackView::fps() const
+{
+ return m_document->fps();
+}
+
+void CustomTrackView::updateProjectFps()
+{
+ // update all clips to the new fps
+ resetSelectionGroup();
+ scene()->clearSelection();
+ m_dragItem = NULL;
+ QList<QGraphicsItem *> itemList = items();
+ for (int i = 0; i < itemList.count(); i++) {
+ // remove all items and re-add them one by one
+ if (itemList.at(i) != m_cursorLine && itemList.at(i)->parentItem() == NULL) m_scene->removeItem(itemList.at(i));
+ }
+ for (int i = 0; i < itemList.count(); i++) {
+ if (itemList.at(i)->parentItem() == 0 && (itemList.at(i)->type() == AVWIDGET || itemList.at(i)->type() == TRANSITIONWIDGET)) {
+ AbstractClipItem *clip = static_cast <AbstractClipItem *>(itemList.at(i));
+ clip->updateFps(m_document->fps());
+ m_scene->addItem(clip);
+ } else if (itemList.at(i)->type() == GROUPWIDGET) {
+ AbstractGroupItem *grp = static_cast <AbstractGroupItem *>(itemList.at(i));
+ QList<QGraphicsItem *> children = grp->childItems();
+ for (int j = 0; j < children.count(); j++) {
+ if (children.at(j)->type() == AVWIDGET || children.at(j)->type() == TRANSITIONWIDGET) {
+ AbstractClipItem *clip = static_cast <AbstractClipItem *>(children.at(j));
+ clip->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
+ clip->updateFps(m_document->fps());
+ }
+ }
+ m_document->clipManager()->removeGroup(grp);
+ m_scene->addItem(grp);
+ scene()->destroyItemGroup(grp);
+ for (int j = 0; j < children.count(); j++) {
+ if (children.at(j)->type() == AVWIDGET || children.at(j)->type() == TRANSITIONWIDGET) {
+ //children.at(j)->setParentItem(0);
+ children.at(j)->setSelected(true);
+ }
+ }
+ groupSelectedItems(true, true);
+ } else if (itemList.at(i)->type() == GUIDEITEM) {
+ Guide *g = static_cast<Guide *>(itemList.at(i));
+ g->updatePos();
+ m_scene->addItem(g);
+ }
+ }
+ viewport()->update();
+}
+
+#include "customtrackview.moc"
\ No newline at end of file
void doChangeClipType(const GenTime &pos, int track, bool videoOnly, bool audioOnly);
int hasGuide(int pos, int offset);
void reloadTransitionLumas();
+ void updateProjectFps();
+ double fps() const;
public slots:
void setCursorPos(int pos, bool seek = true);
child->setIcon(0, KIcon("dialog-ok"));
child->setData(0, statusRole, CLIPOK);
}
- }
- else if (child->data(0, statusRole).toInt() == LUMAMISSING) {
+ } else if (child->data(0, statusRole).toInt() == LUMAMISSING) {
QString fileName = searchLuma(child->data(0, idRole).toString());
if (!fileName.isEmpty()) {
child->setText(1, fileName);
// prepare transitions
QDomNodeList trans = m_doc.elementsByTagName("transition");
-
+
QTreeWidgetItem *child = treeWidget->topLevelItem(ix);
while (child) {
if (child->data(0, statusRole).toInt() == CLIPOK) {
} else if (child->data(0, statusRole).toInt() == LUMAOK) {
for (int i = 0; i < trans.count(); i++) {
QString luma = getProperty(trans.at(i).toElement(), "luma");
- kDebug()<< "luma: "<<luma;
+ kDebug() << "luma: " << luma;
if (!luma.isEmpty() && luma == child->data(0, idRole).toString()) {
setProperty(trans.at(i).toElement(), "luma", child->text(1));
- kDebug()<< "replace with; "<<child->text(1);
+ kDebug() << "replace with; " << child->text(1);
}
}
} else if (child->data(0, statusRole).toInt() == LUMAMISSING) {
if (child->data(0, statusRole).toInt() == CLIPMISSING) {
child->setData(0, statusRole, CLIPPLACEHOLDER);
child->setIcon(0, KIcon("dialog-ok"));
- }
- else if (child->data(0, statusRole).toInt() == LUMAMISSING) {
+ } else if (child->data(0, statusRole).toInt() == LUMAMISSING) {
child->setData(0, statusRole, LUMAPLACEHOLDER);
child->setIcon(0, KIcon("dialog-ok"));
}
#include <QBrush>
#include <QStyleOptionGraphicsItem>
-Guide::Guide(CustomTrackView *view, GenTime pos, QString label, double fps, double height) :
+Guide::Guide(CustomTrackView *view, GenTime pos, QString label, double height) :
QGraphicsLineItem(),
m_position(pos),
m_label(label),
- m_fps(fps),
m_view(view),
m_pen(QPen())
{
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIgnoresTransformations);
setToolTip(label);
setLine(0, 0, 0, height);
- setPos(m_position.frames(m_fps), 0);
+ setPos(m_position.frames(m_view->fps()), 0);
m_pen.setWidthF(0);
m_pen.setColor(QColor(0, 0, 200, 180));
//m_pen.setCosmetic(true);
void Guide::updateGuide(const GenTime newPos, const QString &comment)
{
m_position = newPos;
- setPos(m_position.frames(m_fps), 0);
+ setPos(m_position.frames(m_view->fps()), 0);
if (!comment.isEmpty()) {
m_label = comment;
setToolTip(m_label);
}
}
+void Guide::updatePos()
+{
+ setPos(m_position.frames(m_view->fps()), 0);
+}
+
//virtual
int Guide::type() const
{
{
public:
- Guide(CustomTrackView *view, GenTime pos, QString label, double fps, double height);
+ Guide(CustomTrackView *view, GenTime pos, QString label, double height);
GenTime position() const;
void updateGuide(const GenTime newPos, const QString &comment = QString());
QString label() const;
CommentedTime info() const;
+ void updatePos();
virtual int type() const;
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *w);
virtual QRectF boundingRect() const;
private:
GenTime m_position;
QString m_label;
- double m_fps;
CustomTrackView *m_view;
int m_width;
QPen m_pen;
success = m_document.setContent(&file, false, &errorMsg);
file.close();
KIO::NetAccess::removeTempFile(tmpFile);
+
if (!success) // It is corrupted
KMessageBox::error(parent, errorMsg);
else {
return 0;
}
-QDomDocument KdenliveDoc::createEmptyDocument(const int videotracks, const int audiotracks)
+QDomDocument KdenliveDoc::createEmptyDocument(int videotracks, int audiotracks)
{
- // Creating new document
- QDomDocument doc;
- QDomElement mlt = doc.createElement("mlt");
- doc.appendChild(mlt);
-
-
TrackInfo videoTrack;
videoTrack.type = VIDEOTRACK;
videoTrack.isMute = false;
audioTrack.isBlind = true;
audioTrack.isLocked = false;
+ m_tracksList.clear();
+
+ for (int i = 0; i < audiotracks; i++) {
+ m_tracksList.append(audioTrack);
+ }
+ for (int i = 0; i < videotracks; i++) {
+ m_tracksList.append(videoTrack);
+ }
+ return createEmptyDocument(m_tracksList);
+}
+
+QDomDocument KdenliveDoc::createEmptyDocument(QList <TrackInfo> tracks)
+{
+ // Creating new document
+ QDomDocument doc;
+ QDomElement mlt = doc.createElement("mlt");
+ doc.appendChild(mlt);
+
+
// Create black producer
// For some unknown reason, we have to build the black producer here and not in renderer.cpp, otherwise
// the composite transitions with the black track are corrupted.
playlist.appendChild(blank0);
// create playlists
- int total = audiotracks + videotracks + 1;
+ int total = tracks.count() + 1;
for (int i = 1; i < total; i++) {
QDomElement playlist = doc.createElement("playlist");
tractor.appendChild(track0);
// create audio tracks
- for (int i = 1; i < audiotracks + 1; i++) {
- QDomElement track = doc.createElement("track");
- track.setAttribute("producer", "playlist" + QString::number(i));
- track.setAttribute("hide", "video");
- tractor.appendChild(track);
- m_tracksList.append(audioTrack);
- }
-
- // create video tracks
- for (int i = audiotracks + 1; i < total; i++) {
+ for (int i = 1; i < total; i++) {
QDomElement track = doc.createElement("track");
track.setAttribute("producer", "playlist" + QString::number(i));
+ if (tracks.at(i - 1).type == AUDIOTRACK)
+ track.setAttribute("hide", "video");
+ else if (tracks.at(i - 1).isBlind)
+ track.setAttribute("hide", "video");
+ if (tracks.at(i - 1).isMute)
+ track.setAttribute("hide", "audio");
tractor.appendChild(track);
- m_tracksList.append(videoTrack);
}
for (int i = 2; i < total ; i++) {
return m_profile;
}
-void KdenliveDoc::setProfilePath(QString path)
+bool KdenliveDoc::setProfilePath(QString path)
{
if (path.isEmpty()) path = KdenliveSettings::default_profile();
if (path.isEmpty()) path = "dv_pal";
m_profile = ProfilesDialog::getVideoProfile(path);
+ bool current_fps = m_fps;
if (m_profile.path.isEmpty()) {
// Profile not found, use embedded profile
QDomElement profileInfo = m_document.elementsByTagName("profileinfo").at(0).toElement();
kDebug() << "Kdenlive document, init timecode from path: " << path << ", " << m_fps;
if (m_fps == 30000.0 / 1001.0) m_timecode.setFormat(m_fps, true);
else m_timecode.setFormat(m_fps);
+ return (current_fps != m_fps);
}
double KdenliveDoc::dar()
MltVideoProfile mltProfile() const;
const QString description() const;
void setUrl(KUrl url);
- void setProfilePath(QString path);
+ /** update project profile, returns true if fps was changed */
+ bool setProfilePath(QString path);
const QString getFreeClipId();
/** does the document need saving */
bool isModified() const;
QMap <QString, QString> m_documentProperties;
QList <TrackInfo> m_tracksList;
-
- QDomDocument createEmptyDocument(const int videotracks, const int audiotracks);
-
void setNewClipResource(const QString &id, const QString &path);
QString searchFileRecursively(const QDir &dir, const QString &matchSize, const QString &matchHash) const;
void moveProjectData(KUrl url);
bool checkDocumentClips(QDomNodeList infoproducers);
+ QDomDocument createEmptyDocument(int videotracks, int audiotracks);
+ QDomDocument createEmptyDocument(QList <TrackInfo> tracks);
public slots:
void slotCreateColorClip(const QString &name, const QString &color, const QString &duration, QString group, const QString &groupId);
m_statusProgressBar->setMaximumWidth(150);
m_statusProgressBar->setVisible(false);
- KToolBar *toolbar = new KToolBar("statusToolBar", this, Qt::BottomToolBarArea);
+ KToolBar *toolbar = new KToolBar("statusToolBar", this, Qt::BottomToolBarArea);
toolbar->setMovable(false);
m_toolGroup = new QActionGroup(this);
statusBar()->setStyleSheet(QString("QStatusBar QLabel {font-size:%1pt;} QStatusBar::item { border: 0px; font-size:%1pt;padding:0px; }").arg(statusBar()->font().pointSize()));
m_effectStack->slotClipItemSelected(NULL, 0);
m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false);
m_clipMonitor->slotSetXml(NULL, 0);
- m_activeDocument->setProfilePath(profile);
+ bool updateFps = m_activeDocument->setProfilePath(profile);
KdenliveSettings::setCurrent_profile(profile);
KdenliveSettings::setProject_fps(m_activeDocument->fps());
setCaption(m_activeDocument->description(), m_activeDocument->isModified());
m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description());
//m_activeDocument->clipManager()->resetProducersList(m_projectMonitor->render->producersList());
if (dar != m_activeDocument->dar()) m_projectList->reloadClipThumbnails();
- m_activeTimeline->updateProjectFps();
+ if (updateFps) m_activeTimeline->updateProjectFps();
// We need to desactivate & reactivate monitors to get a refresh
//m_monitorManager->switchMonitors();
Mlt::Tractor tractor(service);
Mlt::Field *field = tractor.field();
mlt_service nextservice = mlt_service_get_producer(service.get_service());
+ mlt_service nextservicetodisconnect;
mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
QString mlt_type = mlt_properties_get(properties, "mlt_type");
QString resource = mlt_properties_get(properties, "mlt_service");
// Delete all transitions
while (mlt_type == "transition") {
- mlt_field_disconnect_service(field->get_field(), nextservice);
+ nextservicetodisconnect = nextservice;
+ nextservice = mlt_service_producer(nextservice);
+ mlt_field_disconnect_service(field->get_field(), nextservicetodisconnect);
nextservice = mlt_service_producer(nextservice);
if (nextservice == NULL) break;
properties = MLT_SERVICE_PROPERTIES(nextservice);
m_mltConsumer = NULL;
QString scene = sceneList();
int pos = 0;
-
+ double current_fps = m_mltProfile->fps();
delete m_blackClip;
m_blackClip = NULL;
m_mltProducer = NULL;
buildConsumer();
-
+ double new_fps = m_mltProfile->fps();
+ if (current_fps != new_fps) {
+ // fps changed, we must update the scenelist positions
+ scene = updateSceneListFps(current_fps, new_fps, scene);
+ }
//kDebug() << "//RESET WITHSCENE: " << scene;
setSceneList(scene, pos);
Mlt::Tractor tractor(service);
Mlt::Field *field = tractor.field();
mlt_service nextservice = mlt_service_get_producer(service.get_service());
+ mlt_service nextservicetodisconnect;
mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
QString mlt_type = mlt_properties_get(properties, "mlt_type");
QString resource = mlt_properties_get(properties, "mlt_service");
// Delete all transitions
while (mlt_type == "transition") {
- mlt_field_disconnect_service(field->get_field(), nextservice);
+ nextservicetodisconnect = nextservice;
nextservice = mlt_service_producer(nextservice);
+ mlt_field_disconnect_service(field->get_field(), nextservicetodisconnect);
if (nextservice == NULL) break;
properties = MLT_SERVICE_PROPERTIES(nextservice);
mlt_type = mlt_properties_get(properties, "mlt_type");
setSceneList(scene, pos);
}
+
+QString Render::updateSceneListFps(double current_fps, double new_fps, QString scene)
+{
+ // Update all frame positions to the new fps value
+ //WARNING: there are probably some effects or other that hold a frame value
+ // as parameter and will also need to be updated here!
+ QDomDocument doc;
+ doc.setContent(scene);
+
+ double factor = new_fps / current_fps;
+ QDomNodeList producers = doc.elementsByTagName("producer");
+ for (int i = 0; i < producers.count(); i++) {
+ QDomElement prod = producers.at(i).toElement();
+ prod.removeAttribute("in");
+ prod.removeAttribute("out");
+
+ QDomNodeList props = prod.childNodes();
+ for (int j = 0; j < props.count(); j++) {
+ QDomElement param = props.at(j).toElement();
+ QString paramName = param.attribute("name");
+ if (paramName.startsWith("meta.") || paramName == "length") {
+ prod.removeChild(props.at(j));
+ j--;
+ }
+ }
+ }
+
+ QDomNodeList entries = doc.elementsByTagName("entry");
+ for (int i = 0; i < entries.count(); i++) {
+ QDomElement entry = entries.at(i).toElement();
+ int in = entry.attribute("in").toInt();
+ int out = entry.attribute("out").toInt();
+ in = factor * in + 0.5;
+ out = factor * out + 0.5;
+ entry.setAttribute("in", in);
+ entry.setAttribute("out", out);
+ }
+
+ QDomNodeList blanks = doc.elementsByTagName("blank");
+ for (int i = 0; i < blanks.count(); i++) {
+ QDomElement blank = blanks.at(i).toElement();
+ int length = blank.attribute("length").toInt();
+ length = factor * length + 0.5;
+ blank.setAttribute("length", QString::number(length));
+ }
+
+ QDomNodeList filters = doc.elementsByTagName("filter");
+ for (int i = 0; i < filters.count(); i++) {
+ QDomElement filter = filters.at(i).toElement();
+ int in = filter.attribute("in").toInt();
+ int out = filter.attribute("out").toInt();
+ in = factor * in + 0.5;
+ out = factor * out + 0.5;
+ filter.setAttribute("in", in);
+ filter.setAttribute("out", out);
+ }
+
+ QDomNodeList transitions = doc.elementsByTagName("transition");
+ for (int i = 0; i < transitions.count(); i++) {
+ QDomElement transition = transitions.at(i).toElement();
+ int in = transition.attribute("in").toInt();
+ int out = transition.attribute("out").toInt();
+ in = factor * in + 0.5;
+ out = factor * out + 0.5;
+ transition.setAttribute("in", in);
+ transition.setAttribute("out", out);
+ QDomNodeList props = transition.childNodes();
+ for (int j = 0; j < props.count(); j++) {
+ QDomElement param = props.at(j).toElement();
+ QString paramName = param.attribute("name");
+ if (paramName == "geometry") {
+ QString geom = param.firstChild().nodeValue();
+ QStringList keys = geom.split(';');
+ QStringList newKeys;
+ for (int k = 0; k < keys.size(); ++k) {
+ if (keys.at(k).contains('=')) {
+ int pos = keys.at(k).section('=', 0, 0).toInt();
+ pos = factor * pos + 0.5;
+ newKeys.append(QString::number(pos) + '=' + keys.at(k).section('=', 1));
+ } else newKeys.append(keys.at(k));
+ }
+ param.firstChild().setNodeValue(newKeys.join(";"));
+ }
+ }
+ }
+ QDomElement tractor = doc.elementsByTagName("tractor").at(0).toElement();
+ int out = tractor.attribute("out").toInt();
+ out = factor * out + 0.5;
+ tractor.setAttribute("out", out);
+ emit durationChanged(out);
+
+ kDebug() << "///////////////////////////// " << out << " \n" << doc.toString() << "\n-------------------------";
+ return doc.toString();
+}
+
#include "renderer.moc"
const QList <Mlt::Producer *> producersList();
void updatePreviewSettings();
void setDropFrames(bool show);
+ QString updateSceneListFps(double current_fps, double new_fps, QString scene);
#ifdef Q_WS_MAC
void showFrame(Mlt::Frame&);
#endif
void TrackView::updateProjectFps()
{
m_ruler->updateProjectFps(m_doc->timecode());
+ m_trackview->updateProjectFps();
}
void TrackView::slotRenameTrack(int ix)