]> git.sesse.net Git - kdenlive/blobdiff - src/renderer.cpp
Fix adding effect group from timeline context menu:
[kdenlive] / src / renderer.cpp
index 5352051857cd9d21b0c5eb550a76b63d22bd5860..14927a75045a807cd64cefc97748a809aae9087e 100644 (file)
@@ -103,7 +103,7 @@ static void consumer_gl_frame_show(mlt_consumer, Render * self, mlt_frame frame_
     }
 }
 
-Render::Render(const QString & rendererName, int winid, QString profile, QWidget *parent) :
+Render::Render(Kdenlive::MONITORID rendererName, int winid, QString profile, QWidget *parent) :
     AbstractRender(rendererName, parent),
     m_name(rendererName),
     m_mltConsumer(NULL),
@@ -125,7 +125,7 @@ Render::Render(const QString & rendererName, int winid, QString profile, QWidget
     m_mltConsumer->connect(*m_mltProducer);
     m_mltProducer->set_speed(0.0);
     m_refreshTimer.setSingleShot(true);
-    m_refreshTimer.setInterval(50);
+    m_refreshTimer.setInterval(70);
     connect(&m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
 }
 
@@ -561,13 +561,16 @@ void Render::slotSplitView(bool doit)
         mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
         QString mlt_type = mlt_properties_get(properties, "mlt_type");
         QString resource = mlt_properties_get(properties, "mlt_service");
+       mlt_service nextservicetodisconnect;
 
         while (mlt_type == "transition") {
             QString added = mlt_properties_get(MLT_SERVICE_PROPERTIES(nextservice), "internal_added");
             if (added == "200") {
-                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);
+            else nextservice = mlt_service_producer(nextservice);
             if (nextservice == NULL) break;
             properties = MLT_SERVICE_PROPERTIES(nextservice);
             mlt_type = mlt_properties_get(properties, "mlt_type");
@@ -1578,11 +1581,6 @@ int Render::seekFramePosition() const
     return 0;
 }
 
-const QString & Render::rendererName() const
-{
-    return m_name;
-}
-
 void Render::emitFrameUpdated(Mlt::Frame& frame)
 {
     mlt_image_format format = mlt_image_rgb24a;
@@ -1598,7 +1596,7 @@ void Render::emitFrameUpdated(Mlt::Frame& frame)
     const uchar* image = frame.get_image(format, width, height);
     QImage qimage(width, height, QImage::Format_RGB888);
     memcpy(qimage.bits(), image, width * height * 3);*/
-    emit frameUpdated(qimage);
+    emit frameUpdated(qimage.rgbSwapped());
 }
 
 void Render::emitFrameNumber()
@@ -2757,7 +2755,7 @@ bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList par
     int index = params.paramValue("kdenlive_ix").toInt();
     QString tag =  params.paramValue("tag");
 
-    if (!params.paramValue("keyframes").isEmpty() || /*it.key().startsWith("#") || */tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle" || params.hasParam("region")) {
+    if (!params.paramValue("keyframes").isEmpty() || (tag == "affine" && params.hasParam("background")) || tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle" || params.hasParam("region")) {
         // This is a keyframe effect, to edit it, we remove it and re-add it.
         bool success = mltRemoveEffect(track, position, index, false);
 //         if (!success) kDebug() << "// ERROR Removing effect : " << index;
@@ -3472,6 +3470,7 @@ bool Render::mltMoveTransition(QString type, int startTrack, int newTrack, int n
 
     while (mlt_type == "transition") {
         Mlt::Transition transition((mlt_transition) nextservice);
+       nextservice = mlt_service_producer(nextservice);
         int currentTrack = transition.get_b_track();
         int currentIn = (int) transition.get_in();
         int currentOut = (int) transition.get_out();
@@ -3490,7 +3489,6 @@ bool Render::mltMoveTransition(QString type, int startTrack, int newTrack, int n
             } else transition.set_in_and_out(new_in, new_out);
             break;
         }
-        nextservice = mlt_service_producer(nextservice);
         if (nextservice == NULL) break;
         properties = MLT_SERVICE_PROPERTIES(nextservice);
         mlt_type = mlt_properties_get(properties, "mlt_type");
@@ -3510,12 +3508,16 @@ void Render::mltPlantTransition(Mlt::Field *field, Mlt::Transition &tr, int a_tr
     QString mlt_type = mlt_properties_get(properties, "mlt_type");
     QString resource = mlt_properties_get(properties, "mlt_service");
     QList <Mlt::Transition *> trList;
+    mlt_properties insertproperties = tr.get_properties();
+    QString insertresource = mlt_properties_get(insertproperties, "mlt_service");
+    bool isMixTransition = insertresource == "mix";
 
     while (mlt_type == "transition") {
         Mlt::Transition transition((mlt_transition) nextservice);
+       nextservice = mlt_service_producer(nextservice);
         int aTrack = transition.get_a_track();
         int bTrack = transition.get_b_track();
-        if (resource != "mix" && (aTrack < a_track || (aTrack == a_track && bTrack > b_track))) {
+        if ((isMixTransition || resource != "mix") && (aTrack < a_track || (aTrack == a_track && bTrack > b_track))) {
             Mlt::Properties trans_props(transition.get_properties());
             Mlt::Transition *cp = new Mlt::Transition(*m_mltProfile, transition.get("mlt_service"));
             Mlt::Properties new_trans_props(cp->get_properties());
@@ -3525,7 +3527,6 @@ void Render::mltPlantTransition(Mlt::Field *field, Mlt::Transition &tr, int a_tr
         }
         //else kDebug() << "// FOUND TRANS OK, "<<resource<< ", A_: " << aTrack << ", B_ "<<bTrack;
 
-        nextservice = mlt_service_producer(nextservice);
         if (nextservice == NULL) break;
         properties = MLT_SERVICE_PROPERTIES(nextservice);
         mlt_type = mlt_properties_get(properties, "mlt_type");
@@ -3538,6 +3539,7 @@ void Render::mltPlantTransition(Mlt::Field *field, Mlt::Transition &tr, int a_tr
         //kDebug()<< "REPLANT ON TK: "<<trList.at(i)->get_a_track()<<", "<<trList.at(i)->get_b_track();
         field->plant_transition(*trList.at(i), trList.at(i)->get_a_track(), trList.at(i)->get_b_track());
     }
+    qDeleteAll(trList);
 }
 
 void Render::mltUpdateTransition(QString oldTag, QString tag, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml, bool force)
@@ -3841,29 +3843,29 @@ bool Render::mltAddTransition(QString tag, int a_track, int b_track, GenTime in,
     Mlt::Tractor tractor(service);
     Mlt::Field *field = tractor.field();
 
-    Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, tag.toUtf8().constData());
+    Mlt::Transition transition(*m_mltProfile, tag.toUtf8().constData());
     if (out != GenTime())
-        transition->set_in_and_out((int) in.frames(m_fps), (int) out.frames(m_fps) - 1);
+        transition.set_in_and_out((int) in.frames(m_fps), (int) out.frames(m_fps) - 1);
 
     if (do_refresh && (m_mltProducer->position() < in.frames(m_fps) || m_mltProducer->position() > out.frames(m_fps))) do_refresh = false;
     QMap<QString, QString>::Iterator it;
     QString key;
-    if (xml.attribute("automatic") == "1") transition->set("automatic", 1);
+    if (xml.attribute("automatic") == "1") transition.set("automatic", 1);
     //kDebug() << " ------  ADDING TRANSITION PARAMs: " << args.count();
     if (xml.hasAttribute("id"))
-        transition->set("kdenlive_id", xml.attribute("id").toUtf8().constData());
+        transition.set("kdenlive_id", xml.attribute("id").toUtf8().constData());
     if (xml.hasAttribute("force_track"))
-        transition->set("force_track", xml.attribute("force_track").toInt());
+        transition.set("force_track", xml.attribute("force_track").toInt());
 
     for (it = args.begin(); it != args.end(); ++it) {
         key = it.key();
         if (!it.value().isEmpty())
-            transition->set(key.toUtf8().constData(), it.value().toUtf8().constData());
+            transition.set(key.toUtf8().constData(), it.value().toUtf8().constData());
         //kDebug() << " ------  ADDING TRANS PARAM: " << key << ": " << it.value();
     }
     // attach transition
     service.lock();
-    mltPlantTransition(field, *transition, a_track, b_track);
+    mltPlantTransition(field, transition, a_track, b_track);
     // field->plant_transition(*transition, a_track, b_track);
     service.unlock();
     if (do_refresh) refresh();
@@ -3950,19 +3952,17 @@ void Render::fillSlowMotionProducers()
     }
 }
 
-void Render::mltInsertTrack(int ix, bool videoTrack)
+QList <TransitionInfo> Render::mltInsertTrack(int ix, bool videoTrack)
 {
-    blockSignals(true);
-
     Mlt::Service service(m_mltProducer->parent().get_service());
-    service.lock();
     if (service.type() != tractor_type) {
         kWarning() << "// TRACTOR PROBLEM";
-        return;
+        return QList <TransitionInfo> ();
     }
-
+    blockSignals(true);
+    service.lock();
     Mlt::Tractor tractor(service);
-
+    QList <TransitionInfo> transitionInfos;
     Mlt::Playlist playlist;
     int ct = tractor.count();
     if (ix > ct) {
@@ -3995,20 +3995,51 @@ void Render::mltInsertTrack(int ix, bool videoTrack)
     mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
     QString mlt_type = mlt_properties_get(properties, "mlt_type");
     QString resource = mlt_properties_get(properties, "mlt_service");
+    Mlt::Field *field = tractor.field();
+    QList <Mlt::Transition *> trList;
 
     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);
-            }
+           Mlt::Transition transition((mlt_transition) nextservice);
+           nextservice = mlt_service_producer(nextservice);
+            int currentbTrack = transition.get_b_track();
+            int currentaTrack = transition.get_a_track();
+           bool trackChanged = false;
+           bool forceTransitionTrack = false;
+            if (currentbTrack >= ix) {
+               if (currentbTrack == ix && currentaTrack < ix) forceTransitionTrack = true;
+               currentbTrack++;
+               trackChanged = true;
+           }
+           if (currentaTrack >= ix) {
+               currentaTrack++;
+               trackChanged = true;
+           }
+           kDebug()<<"// Newtrans: "<<currentaTrack<<"/"<<currentbTrack;
+           
+           // disconnect all transitions
+           Mlt::Properties trans_props(transition.get_properties());
+           Mlt::Transition *cp = new Mlt::Transition(*m_mltProfile, transition.get("mlt_service"));
+           Mlt::Properties new_trans_props(cp->get_properties());
+           new_trans_props.inherit(trans_props);
+           
+           if (trackChanged) {
+               // Transition track needs to be adjusted
+               cp->set("a_track", currentaTrack);
+               cp->set("b_track", currentbTrack);
+               // Check if transition track was changed and needs to be forced
+               if (forceTransitionTrack) cp->set("force_track", 1);
+               TransitionInfo trInfo;
+               trInfo.startPos = GenTime(transition.get_in(), m_fps);
+               trInfo.a_track = currentaTrack;
+               trInfo.b_track = currentbTrack;
+               trInfo.forceTrack = cp->get_int("force_track");
+               transitionInfos.append(trInfo);
+           }
+           trList.append(cp);
+           field->disconnect_service(transition);
         }
-        nextservice = mlt_service_producer(nextservice);
+        else nextservice = mlt_service_producer(nextservice);
         if (nextservice == NULL) break;
         properties = MLT_SERVICE_PROPERTIES(nextservice);
         mlt_type = mlt_properties_get(properties, "mlt_type");
@@ -4016,19 +4047,23 @@ void Render::mltInsertTrack(int ix, bool videoTrack)
     }
 
     // Add audio mix transition to last track
-    Mlt::Field *field = tractor.field();
-    Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, "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());
+    Mlt::Transition transition(*m_mltProfile, "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);
+    mltPlantTransition(field, transition, 1, ct);
+    
+    // re-add transitions
+    for (int i = trList.count() - 1; i >= 0; i--) {
+        field->plant_transition(*trList.at(i), trList.at(i)->get_a_track(), trList.at(i)->get_b_track());
+    }
+    qDeleteAll(trList);
+    
     service.unlock();
-    //tractor.multitrack()->refresh();
-    //tractor.refresh();
     blockSignals(false);
+    return transitionInfos;
 }
 
 
@@ -4218,5 +4253,48 @@ const QString Render::activeClipId()
     return QString();
 }
 
+//static 
+bool Render::getBlackMagicDeviceList(KComboBox *devicelist)
+{
+    Mlt::Profile profile;
+    Mlt::Producer bm(profile, "decklink");
+    int found_devices = 0;
+    if (bm.is_valid()) {
+       bm.set("list_devices", 1);
+       found_devices = bm.get_int("devices");
+    }
+    if (found_devices <= 0) {
+       devicelist->setEnabled(false);
+       return false;
+    }
+    for (int i = 0; i < found_devices; i++) {
+       char *tmp = qstrdup(QString("device.%1").arg(i).toUtf8().constData());
+       devicelist->addItem(bm.get(tmp));
+       delete[] tmp;
+    }
+    return true;
+}
+
+bool Render::getBlackMagicOutputDeviceList(KComboBox *devicelist)
+{
+    Mlt::Profile profile;
+    Mlt::Consumer bm(profile, "decklink");
+    int found_devices = 0;
+    if (bm.is_valid()) {
+       bm.set("list_devices", 1);
+       found_devices = bm.get_int("devices");
+    }
+    if (found_devices <= 0) {
+       devicelist->setEnabled(false);
+       return false;
+    }
+    for (int i = 0; i < found_devices; i++) {
+       char *tmp = qstrdup(QString("device.%1").arg(i).toUtf8().constData());
+       devicelist->addItem(bm.get(tmp));
+       delete[] tmp;
+    }
+    return true;
+}
+
 #include "renderer.moc"