void CustomTrackView::addTrack(TrackInfo type, int ix) {
if (ix == -1) m_scene->m_tracksList << type;
- else m_scene->m_tracksList.insert(ix, type);
+ else {
+ m_scene->m_tracksList.insert(m_scene->m_tracksList.count() - ix, type);
+ // insert track in MLT playlist
+ m_document->renderer()->mltInsertTrack(m_scene->m_tracksList.count() - ix);
+
+ double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2;
+ QRectF r(0, startY, sceneRect().width(), sceneRect().height() - startY);
+ QList<QGraphicsItem *> selection = m_scene->items(r);
+ resetSelectionGroup();
+
+ m_selectionGroup = new AbstractGroupItem(m_document->fps());
+ scene()->addItem(m_selectionGroup);
+ for (int i = 0; i < selection.count(); i++) {
+ if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET)
+ m_selectionGroup->addToGroup(selection.at(i));
+ }
+ QPointF top = m_selectionGroup->boundingRect().topLeft();
+ const int width = m_selectionGroup->boundingRect().width();
+ const int height = m_selectionGroup->boundingRect().height();
+ m_selectionGroup->setPos(top);
+ m_selectionGroup->translate(-top.x(), -top.y() + 1);
+
+ // Move graphic items
+ m_selectionGroup->setPos(m_selectionGroup->pos().x(), m_selectionGroup->pos().y() + m_tracksHeight);
+
+ // adjust track number
+ QList<QGraphicsItem *> children = m_selectionGroup->childItems();
+ for (int i = 0; i < children.count(); i++) {
+ AbstractClipItem *item = static_cast <AbstractClipItem *>(children.at(i));
+ item->updateItem();
+ ItemInfo clipinfo = item->info();
+ if (item->type() == AVWIDGET) {
+ ClipItem *clip = static_cast <ClipItem *>(item);
+ // We add a move clip command so that we get the correct producer for new track number
+ /*if (clip->clipType() == AV || clip->clipType() == AUDIO)
+ moveClip(clipinfo, clipinfo, true);*/
+ } else if (item->type() == TRANSITIONWIDGET) {
+ Transition *tr = static_cast <Transition *>(item);
+ int track = tr->transitionEndTrack();
+ if (track >= ix) {
+ tr->updateTransitionEndTrack(getPreviousVideoTrack(clipinfo.track));
+ }
+ }
+ }
+ resetSelectionGroup();
+
+ }
m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), m_tracksHeight * m_scene->m_tracksList.count());
setSceneRect(0, 0, sceneRect().width(), m_tracksHeight * m_scene->m_tracksList.count());
verticalScrollBar()->setMaximum(m_tracksHeight * m_scene->m_tracksList.count());
//setFixedHeight(50 * m_tracksCount);
}
-void CustomTrackView::removeTrack() {
- // TODO: implement track deletion
- //m_tracksCount--;
+void CustomTrackView::removeTrack(int ix) {
+ // Delete track in MLT playlist
+ m_document->renderer()->mltDeleteTrack(m_scene->m_tracksList.count() - ix);
+ m_scene->m_tracksList.removeAt(m_scene->m_tracksList.count() - ix);
+
+ double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2;
+ QRectF r(0, startY, sceneRect().width(), sceneRect().height() - startY);
+ QList<QGraphicsItem *> selection = m_scene->items(r);
+
+ resetSelectionGroup();
+
+ m_selectionGroup = new AbstractGroupItem(m_document->fps());
+ scene()->addItem(m_selectionGroup);
+ for (int i = 0; i < selection.count(); i++) {
+ if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET)
+ m_selectionGroup->addToGroup(selection.at(i));
+ }
+
+ QPointF top = m_selectionGroup->boundingRect().topLeft();
+ const int width = m_selectionGroup->boundingRect().width();
+ const int height = m_selectionGroup->boundingRect().height();
+ m_selectionGroup->setPos(top);
+ m_selectionGroup->translate(-top.x(), -top.y() + 1);
+
+ // Move graphic items
+ m_selectionGroup->setPos(m_selectionGroup->pos().x(), m_selectionGroup->pos().y() - m_tracksHeight);
+
+ // adjust track number
+ QList<QGraphicsItem *> children = m_selectionGroup->childItems();
+ kDebug() << "// FOUND CLIPS TO MOVE: " << children.count();
+ for (int i = 0; i < children.count(); i++) {
+ if (children.at(i)->type() == AVWIDGET) {
+ ClipItem *clip = static_cast <ClipItem *>(children.at(i));
+ clip->updateItem();
+ ItemInfo clipinfo = clip->info();
+ kDebug() << "// CLIP TRK IS: " << clipinfo.track;
+ // We add a move clip command so that we get the correct producer for new track number
+ /*if (clip->clipType() == AV || clip->clipType() == AUDIO)
+ moveClip(clipinfo, clipinfo, true);*/
+ } else if (children.at(i)->type() == TRANSITIONWIDGET) {
+ Transition *tr = static_cast <Transition *>(children.at(i));
+ tr->updateItem();
+ int track = tr->transitionEndTrack();
+ if (track >= ix) {
+ ItemInfo clipinfo = tr->info();
+ tr->updateTransitionEndTrack(getPreviousVideoTrack(clipinfo.track));
+ }
+ }
+ }
+ resetSelectionGroup();
+
m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), m_tracksHeight * m_scene->m_tracksList.count());
+ setSceneRect(0, 0, sceneRect().width(), m_tracksHeight * m_scene->m_tracksList.count());
+ verticalScrollBar()->setMaximum(m_tracksHeight * m_scene->m_tracksList.count());
}
void CustomTrackView::slotInsertTrack(int ix) {
kDebug() << "// INSERTING TRK: " << ix;
-
QDialog d(parentWidget());
Ui::AddTrack_UI view;
view.setupUi(&d);
info.isMute = false;
info.isBlind = false;
}
- AddTrackCommand* command = new AddTrackCommand(this, ix, info, true, true);
- m_commandStack->push(command);
+ addTimelineTrack(ix, info);
+ /*AddTrackCommand* command = new AddTrackCommand(this, ix, info, true, true);
+ m_commandStack->push(command);*/
}
}
void CustomTrackView::slotDeleteTrack(int ix) {
+ bool ok;
+ ix = QInputDialog::getInteger(this, i18n("Remove Track"), i18n("Track"), ix, 0, m_scene->m_tracksList.count() - 1, 1, &ok);
+ if (ok) {
+ TrackInfo info = m_scene->m_tracksList.at(m_scene->m_tracksList.count() - ix);
+ deleteTimelineTrack(ix, info);
+ /*AddTrackCommand* command = new AddTrackCommand(this, ix, info, false, true);
+ m_commandStack->push(command);*/
+ }
}
-void CustomTrackView::addTimelineTrack(int ix, TrackInfo info) {
+void CustomTrackView::addTimelineTrack(int ix, TrackInfo trackinfo) {
double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2;
QRectF r(0, startY, sceneRect().width(), sceneRect().height() - startY);
QList<QGraphicsItem *> selection = m_scene->items(r);
kDebug() << "// TRK RECT: " << r << ", ITEMS: " << selection.count();
- addTrack(info, m_scene->m_tracksList.count() - ix);
QUndoCommand *addTrack = new QUndoCommand();
addTrack->setText("Add track");
+ new AddTrackCommand(this, ix, trackinfo, true, true, addTrack);
- resetSelectionGroup();
-
- m_selectionGroup = new AbstractGroupItem(m_document->fps());
- scene()->addItem(m_selectionGroup);
- for (int i = 0; i < selection.count(); i++) {
- if (selection.at(i)->type() == AVWIDGET || selection.at(i)->type() == TRANSITIONWIDGET)
- m_selectionGroup->addToGroup(selection.at(i));
- }
- // insert track in MLT playlist
- m_document->renderer()->mltInsertTrack(m_scene->m_tracksList.count() - ix);
-
- // Move graphic items
- m_selectionGroup->setPos(m_selectionGroup->pos().x(), m_selectionGroup->pos().y() + m_tracksHeight);
-
- // adjust track number
- QList<QGraphicsItem *> children = m_selectionGroup->childItems();
- for (int i = 0; i < children.count(); i++) {
- AbstractClipItem *item = static_cast <AbstractClipItem *>(children.at(i));
- item->updateItem();
- if (item->type() == AV || item->type() == AUDIO) {
- // We add a move clip command so that we get the correct producer for new track number
- ItemInfo clipinfo = item->info();
- MoveClipCommand(this, clipinfo, clipinfo, true, true, addTrack);
- }
- }
- resetSelectionGroup();
m_commandStack->push(addTrack);
+ kDebug() << "// ADD TRCKL DONE...";
update();
- emit trackHeightChanged();
+ QTimer::singleShot(300, this, SIGNAL(trackHeightChanged()));
}
-void CustomTrackView::deleteTimelineTrack(int ix) {
+void CustomTrackView::deleteTimelineTrack(int ix, TrackInfo trackinfo) {
+ double startY = ix * m_tracksHeight + 1 + m_tracksHeight / 2;
+ QRectF r(0, startY, sceneRect().width(), m_tracksHeight / 2 - 1);
+ QList<QGraphicsItem *> selection = m_scene->items(r);
+ QUndoCommand *deleteTrack = new QUndoCommand();
+ deleteTrack->setText("Delete track");
+
+ // Delete all clips in selected track
+ for (int i = 0; i < selection.count(); i++) {
+ if (selection.at(i)->type() == AVWIDGET) {
+ ClipItem *item = static_cast <ClipItem *>(selection.at(i));
+ new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), item->info(), item->effectList(), false, false, deleteTrack);
+ m_scene->removeItem(item);
+ delete item;
+ item = NULL;
+ } else if (selection.at(i)->type() == TRANSITIONWIDGET) {
+ Transition *item = static_cast <Transition *>(selection.at(i));
+ new AddTransitionCommand(this, item->info(), item->transitionEndTrack(), item->toXML(), true, false, deleteTrack);
+ m_scene->removeItem(item);
+ delete item;
+ item = NULL;
+ }
+ }
+
+ new AddTrackCommand(this, ix, trackinfo, false, true, deleteTrack);
+
+ m_commandStack->push(deleteTrack);
+ //removeTrack(ix, trackinfo);
+ kDebug() << "// REM TRK DONE...";
+ update();
+ QTimer::singleShot(300, this, SIGNAL(trackHeightChanged()));
+
}
#include "customtrackview.moc"
if (m_mltConsumer) {
m_mltConsumer->stop();
//m_mltConsumer->set("refresh", 0);
- } else return;
+ } else {
+ m_isBlocked = false;
+ return;
+ }
if (m_mltProducer) {
m_mltProducer->set_speed(0);
emit stopped();
}
+ blockSignals(true);
char *tmp = decodedString(playlist);
m_mltProducer = new Mlt::Producer(*m_mltProfile, "westley-xml", tmp);
delete[] tmp;
if (position != 0) {
//TODO: seek to correct place after opening project.
// Needs to be done from another place since it crashes here.
- //m_mltProducer->seek(position);
- //emit rendererPosition(position);
+ m_mltProducer->seek(position);
}
m_isBlocked = false;
-
+ blockSignals(false);
+ emit rendererPosition(position);
}
/** Create the producer from the Westley QDomDocument */
bool checkLength = false;
if (endTrack == startTrack) {
//mlt_service_lock(service.get_service());
+ Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
if (forceProducer) {
- Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
+ if (clipProducer.is_blank()) {
+ kDebug() << "// ERROR RESTTING CLIP PROD: " << moveEnd << ", TRK: " << startTrack;
+ mlt_service_unlock(m_mltConsumer->get_service());
+ m_isBlocked = false;
+ return false;
+ }
trackPlaylist.insert(clipProducer, moveEnd, clipProducer.get_in(), clipProducer.get_out());
} else {
- Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
-
- if (!trackPlaylist.is_blank_at(moveEnd)) {
+ if (!trackPlaylist.is_blank_at(moveEnd) || clipProducer.is_blank()) {
// error, destination is not empty
//int ix = trackPlaylist.get_clip_index_at(moveEnd);
kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd;
return false;
} else {
Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
+ if (clipProducer.is_blank()) {
+ // error, destination is not empty
+ //int ix = trackPlaylist.get_clip_index_at(moveEnd);
+ kDebug() << "// ERROR MOVING CLIP TO : " << moveEnd;
+ mlt_service_unlock(m_mltConsumer->get_service());
+ m_isBlocked = false;
+ return false;
+ }
trackPlaylist.consolidate_blanks(0);
destTrackPlaylist.consolidate_blanks(1);
Mlt::Producer *clip;
mlt_service_unlock(m_mltConsumer->get_service());
m_isBlocked = false;
blockSignals(false);
- //Mlt::Producer trackProducer(tractor.track(startTrack));
+}
+
+
+void Render::mltDeleteTrack(int ix) {
+ QDomDocument doc;
+ doc.setContent(sceneList(), false);
+ QDomNode track = doc.elementsByTagName("track").at(ix);
+ QDomNode tractor = doc.elementsByTagName("tractor").at(0);
+ tractor.removeChild(track);
+ setSceneList(doc.toString(), m_framePosition);
+ return;
+
+ blockSignals(true);
+ m_isBlocked = true;
+
+ m_mltConsumer->set("refresh", 0);
+ mlt_service_lock(m_mltConsumer->get_service());
+ Mlt::Service service(m_mltProducer->parent().get_service());
+ if (service.type() != tractor_type) kWarning() << "// TRACTOR PROBLEM";
+
+ /*Mlt::Tractor tractor(service);
+
+
+ Mlt::Multitrack *multi = tractor.multitrack();
+
+
+ int ct = tractor.count();
+ kDebug() << "// TRACK REMOVE: " << ix << ", MAX: " << ct;
+ int pos = ix;
+ for (; pos < ct ; pos++) {
+ Mlt::Service *lastTrack = new Mlt::Service(tractor.track(pos)->get_service());
+ //mlt_service_close(lastTrack->get_service());
+ delete lastTrack;
+ Mlt::Producer *prodToMove = new Mlt::Producer(tractor.track(pos + 1));
+ Mlt::Producer *prodToClose = new Mlt::Producer(tractor.track(pos));
+ mlt_service_close(prodToMove->get_service());
+ mlt_service_close(prodToClose->get_service());
+ tractor.set_track(*prodToMove, pos);
+ }*/
+
+ // Move transitions
+ /*mlt_service serv = m_mltProducer->parent().get_service();
+ mlt_service nextservice = mlt_service_get_producer(serv);
+ mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
+ QString mlt_type = mlt_properties_get(properties, "mlt_type");
+ QString resource = mlt_properties_get(properties, "mlt_service");
+
+ while (mlt_type == "transition") {
+ if (resource != "mix") {
+ mlt_transition tr = (mlt_transition) nextservice;
+ int currentTrack = mlt_transition_get_b_track(tr);
+ int currentaTrack = mlt_transition_get_a_track(tr);
+ mlt_properties properties = MLT_TRANSITION_PROPERTIES(tr);
+
+ if (currentTrack >= ix) {
+ mlt_properties_set_int(properties, "b_track", currentTrack + 1);
+ mlt_properties_set_int(properties, "a_track", currentaTrack + 1);
+ }
+ }
+ nextservice = mlt_service_producer(nextservice);
+ if (nextservice == NULL) break;
+ properties = MLT_SERVICE_PROPERTIES(nextservice);
+ mlt_type = mlt_properties_get(properties, "mlt_type");
+ resource = mlt_properties_get(properties, "mlt_service");
+ }
+
+ // Add audio mix transition to last track
+ Mlt::Field *field = tractor.field();
+ Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, "mix");
+ //transition->set("mlt_service", "mix");
+ transition->set("a_track", 1);
+ transition->set("b_track", ct);
+ transition->set("always_active", 1);
+ transition->set("internal_added", 237);
+ transition->set("combine", 1);
+ field->plant_transition(*transition, 1, ct);
+ */
+
+ mlt_service_unlock(m_mltConsumer->get_service());
+ m_isBlocked = false;
+ blockSignals(false);
}
#include "renderer.moc"