Exemple #1
0
bool TransitionHandler::addTransition(QString tag, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml)
{
    if (in >= out) return false;
    double fps = m_tractor->get_fps();
    QMap<QString, QString> args = getTransitionParamsFromXml(xml);
    QScopedPointer<Mlt::Field> field(m_tractor->field());

    Mlt::Transition transition(*m_tractor->profile(), tag.toUtf8().constData());
    if (!transition.is_valid()) return false;
    if (out != GenTime())
        transition.set_in_and_out((int) in.frames(fps), (int) out.frames(fps) - 1);

    QMap<QString, QString>::Iterator it;
    QString key;
    if (xml.attribute(QStringLiteral("automatic")) == QLatin1String("1")) transition.set("automatic", 1);
    ////qDebug() << " ------  ADDING TRANSITION PARAMs: " << args.count();
    if (xml.hasAttribute(QStringLiteral("id")))
        transition.set("kdenlive_id", xml.attribute(QStringLiteral("id")).toUtf8().constData());
    if (xml.hasAttribute(QStringLiteral("force_track")))
        transition.set("force_track", xml.attribute(QStringLiteral("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());
        ////qDebug() << " ------  ADDING TRANS PARAM: " << key << ": " << it.value();
    }
    // attach transition
    m_tractor->lock();
    plantTransition(field.data(), transition, a_track, b_track);
    // field->plant_transition(*transition, a_track, b_track);
    m_tractor->unlock();
    return true;
}
bool TransitionHandler::moveTransition(QString type, int startTrack, int newTrack, int newTransitionTrack, GenTime oldIn, GenTime oldOut, GenTime newIn, GenTime newOut)
{
    double fps = m_tractor->get_fps();
    int new_in = (int)newIn.frames(fps);
    int new_out = (int)newOut.frames(fps) - 1;
    if (new_in >= new_out) return false;
    int old_in = (int)oldIn.frames(fps);
    int old_out = (int)oldOut.frames(fps) - 1;

    bool doRefresh = true;
    // Check if clip is visible in monitor
    int position = mlt_producer_position(m_tractor->get_producer());
    int diff = old_out - position;
    if (diff < 0 || diff > old_out - old_in) doRefresh = false;
    if (doRefresh) {
        diff = new_out - position;
        if (diff < 0 || diff > new_out - new_in) doRefresh = false;
    }
    QScopedPointer<Mlt::Field> field(m_tractor->field());
    field->lock();
    mlt_service nextservice = mlt_service_get_producer(field->get_service());
    mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
    QString resource = mlt_properties_get(properties, "mlt_service");
    int old_pos = (int)(old_in + old_out) / 2;
    bool found = false;
    mlt_service_type mlt_type = mlt_service_identify( nextservice );
    while (mlt_type == transition_type) {
        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();

        if (resource == type && startTrack == currentTrack && currentIn <= old_pos && currentOut >= old_pos) {
            found = true;
            if (newTrack - startTrack != 0) {
                Mlt::Properties trans_props(transition.get_properties());
                Mlt::Transition new_transition(*m_tractor->profile(), transition.get("mlt_service"));
                Mlt::Properties new_trans_props(new_transition.get_properties());
                // We cannot use MLT's property inherit because it also clones internal values like _unique_id which messes up the playlist
                cloneProperties(new_trans_props, trans_props);
                new_transition.set_in_and_out(new_in, new_out);
                field->disconnect_service(transition);
                plantTransition(field.data(), new_transition, newTransitionTrack, newTrack);
            } else transition.set_in_and_out(new_in, new_out);
            break;
        }
        if (nextservice == NULL) break;
        properties = MLT_SERVICE_PROPERTIES(nextservice);
        mlt_type = mlt_service_identify( nextservice );
        resource = mlt_properties_get(properties, "mlt_service");
    }
    field->unlock();
    if (doRefresh) refresh();
    //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
    return found;
}
void TransitionHandler::updateTransition(QString oldTag, QString tag, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml, bool force)
{
    if (oldTag == tag && !force) updateTransitionParams(tag, a_track, b_track, in, out, xml);
    else {
        ////qDebug()<<"// DELETING TRANS: "<<a_track<<"-"<<b_track;
        deleteTransition(oldTag, a_track, b_track, in, out, xml, false);
        addTransition(tag, a_track, b_track, in, out, xml, false);
    }

    int position = mlt_producer_position(m_tractor->get_producer());
    if (position >= in.frames(m_fps) && position <= out.frames(m_fps)) emit refresh();
}
Exemple #4
0
void AbstractClipItem::updateKeyFramePos(const GenTime &pos, const double value)
{
    if (!m_keyframes.contains(m_editedKeyframe))
        return;
    int newpos = (int) pos.frames(m_fps);
    int min = (int) cropStart().frames(m_fps) - 1;
    int max = (int)(cropStart() + cropDuration()).frames(m_fps);
    QMap<int, int>::const_iterator i = m_keyframes.constBegin();
    while (i.key() < m_editedKeyframe) {
        min = qMax(i.key(), min);
        ++i;
    }
    i = m_keyframes.constEnd() - 1;
    while (i.key() > m_editedKeyframe) {
        max = qMin(i.key(), max);
        --i;
    }
    if (newpos <= min)
        newpos = min + 1;
    if (newpos >= max)
        newpos = max - 1;

    double newval = qMax(value, 0.0);
    newval = qMin(newval, 100.0);
    newval = newval / m_keyframeFactor + m_keyframeOffset;
    if (m_editedKeyframe != newpos)
        m_keyframes.remove(m_editedKeyframe);
    m_keyframes[newpos] = (int) newval;
    m_editedKeyframe = newpos;
    update();
}
const QString Timecode::getTimecodeHH_MM_SS_HH(const GenTime & time) const
{
    int hundredths = (int)(time.seconds() * 100);

    bool negative = false;
    if (hundredths < 0) {
        negative = true;
        hundredths = qAbs(hundredths);
    }

    int seconds = hundredths / 100;
    hundredths = hundredths % 100;
    int minutes = seconds / 60;
    seconds = seconds % 60;
    int hours = minutes / 60;
    minutes = minutes % 60;

    QString text;
    if (negative)
        text.append('-');
    text.append(QString::number(hours).rightJustified(2, '0', false));
    text.append(':');
    text.append(QString::number(minutes).rightJustified(2, '0', false));
    text.append(':');
    text.append(QString::number(seconds).rightJustified(2, '0', false));
    if (m_dropFrameTimecode)
        text.append(',');
    else
        text.append(':');
    text.append(QString::number(hundredths).rightJustified(2, '0', false));

    return text;
}
const QString Timecode::getTimecodeHH_MM_SS_FF(const GenTime & time) const
{
    if (m_dropFrameTimecode) {
        return getTimecodeDropFrame(time);
    }
    return getTimecodeHH_MM_SS_FF((int) time.frames(m_realFps));
}
Exemple #7
0
int AbstractClipItem::addKeyFrame(const GenTime &pos, const double value)
{
    QRectF br = sceneBoundingRect();
    double maxh = 100.0 / br.height() / m_keyframeFactor;
    int newval = (br.bottom() - value) * maxh + m_keyframeOffset;
    //kDebug() << "Rect: " << br << "/ SCENE: " << sceneBoundingRect() << ", VALUE: " << value << ", MAX: " << maxh << ", NEWVAL: " << newval;
    int newpos = (int) pos.frames(m_fps) ;
    m_keyframes[newpos] = newval;
    m_selectedKeyframe = newpos;
    update();
    return newval;
}
//static
QString Timecode::getEasyTimecode(const GenTime & time, const double &fps)
{
    // Returns the timecode in an easily read display, like 3 min. 5 sec.
    int frames = (int) time.frames(fps);

    bool negative = false;
    if (frames < 0) {
        negative = true;
        frames = qAbs(frames);
    }

    int seconds = (int)(frames / fps);
    frames = frames - ((int)(fps * seconds));

    int minutes = seconds / 60;
    seconds = seconds % 60;
    int hours = minutes / 60;
    minutes = minutes % 60;

    QString text;
    bool trim = false;

    if (negative)
        text.append('-');
    if (hours != 0) {
        text.append(QString::number(hours).rightJustified(2, '0', false));
        text.append(' ' + i18n("hour") + ' ');
        trim = true;
    }
    if (minutes != 0 || trim) {
        if (!trim) {
            text.append(QString::number(minutes));
        } else
            text.append(QString::number(minutes).rightJustified(2, '0', false));
        text.append(' ' + i18n("min.") + ' ');
        trim = true;
    }
    if (seconds != 0 || trim) {
        if (!trim) {
            text.append(QString::number(seconds));
        } else
            text.append(QString::number(seconds).rightJustified(2, '0', false));
        text.append(' ' + i18n("sec."));
        trim = true;
    }
    if (!trim) {
        text.append(QString::number(frames));
        text.append(' ' + i18n("frames"));
    }

    return text;
}
void AbstractClipItem::resizeStart(int posx, bool hasSizeLimit, bool /*emitChange*/)
{
    GenTime durationDiff = GenTime(posx, m_fps) - m_info.startPos;
    if (durationDiff == GenTime()) return;

    if (type() == AVWidget && hasSizeLimit && (cropStart() + durationDiff < GenTime())) {
        durationDiff = GenTime() - cropStart();
    } else if (durationDiff >= cropDuration()) {
        return;
    }
    m_info.startPos += durationDiff;
    m_keyframeView.setOffset(durationDiff.frames(m_fps));

    // set to true if crop from start is negative (possible for color clips, images as they have no size limit)
    bool negCropStart = false;
    if (type() == AVWidget) {
        m_info.cropStart += durationDiff;
        if (m_info.cropStart < GenTime())
            negCropStart = true;
    }

    m_info.cropDuration -= durationDiff;
    setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
    moveBy(durationDiff.frames(m_fps), 0);

    if (m_info.startPos != GenTime(posx, m_fps)) {
        GenTime diff = m_info.startPos - GenTime(posx, m_fps);

        if (type() == AVWidget)
            m_info.cropStart += diff;

        m_info.cropDuration -= diff;
        setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
    }

    // set crop from start to 0 (isn't relevant as this only happens for color clips, images)
    if (negCropStart)
        m_info.cropStart = GenTime();
}
Exemple #10
0
void AbstractClipItem::resizeStart(int posx, bool hasSizeLimit, bool /*emitChange*/)
{
    GenTime durationDiff = GenTime(posx, m_fps) - m_info.startPos;
    if (durationDiff == GenTime()) return;

    if (type() == AVWIDGET && hasSizeLimit && (cropStart() + durationDiff < GenTime())) {
        durationDiff = GenTime() - cropStart();
    } else if (durationDiff >= cropDuration()) {
        return;
        /*if (cropDuration() > GenTime(3, m_fps)) durationDiff = GenTime(3, m_fps);
        else return;*/
    }
    m_info.startPos += durationDiff;

    // set to true if crop from start is negative (possible for color clips, images as they have no size limit)
    bool negCropStart = false;
    if (type() == AVWIDGET) {
        m_info.cropStart += durationDiff;
        if (m_info.cropStart < GenTime())
            negCropStart = true;
    }

    m_info.cropDuration -= durationDiff;
    setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
    moveBy(durationDiff.frames(m_fps), 0);

    if (m_info.startPos != GenTime(posx, m_fps)) {
        //kDebug() << "//////  WARNING, DIFF IN XPOS: " << pos().x() << " == " << m_info.startPos.frames(m_fps);
        GenTime diff = m_info.startPos - GenTime(posx, m_fps);

        if (type() == AVWIDGET)
            m_info.cropStart += diff;

        m_info.cropDuration -= diff;
        setRect(0, 0, cropDuration().frames(m_fps) - 0.02, rect().height());
        //kDebug()<<"// NEW START: "<<m_startPos.frames(25)<<", NW DUR: "<<m_cropDuration.frames(25);
    }

    // set crop from start to 0 (isn't relevant as this only happens for color clips, images)
    if (negCropStart)
        m_info.cropStart = GenTime();

    //kDebug() << "-- NEW CLIP=" << startPos().frames(25) << "-" << endPos().frames(25);
    //setRect((double) m_startPos.frames(m_fps) * scale, rect().y(), (double) m_cropDuration.frames(m_fps) * scale, rect().height());

    /*    if (durationDiff < GenTime()) {
            QList <QGraphicsItem *> collisionList = collidingItems(Qt::IntersectsItemBoundingRect);
            for (int i = 0; i < collisionList.size(); ++i) {
                QGraphicsItem *item = collisionList.at(i);
                if (item->type() == type() && item->pos().x() < pos().x()) {
                    kDebug() << "/////////  COLLISION DETECTED!!!!!!!!!";
                    GenTime diff = ((AbstractClipItem *)item)->endPos() + GenTime(1, m_fps) - m_startPos;
                    setRect(0, 0, (m_cropDuration - diff).frames(m_fps) - 0.02, rect().height());
                    setPos((m_startPos + diff).frames(m_fps), pos().y());
                    m_startPos += diff;
                    if (type() == AVWIDGET) m_cropStart += diff;
                    m_cropDuration = m_cropDuration - diff;
                    break;
                }
            }
        }*/
}
void TransitionHandler::updateTransitionParams(QString type, int a_track, int b_track, GenTime in, GenTime out, QDomElement xml)
{
    QScopedPointer<Mlt::Field> field(m_tractor->field());
    field->lock();

    mlt_service nextservice = mlt_service_get_producer(field->get_service());
    mlt_properties properties = MLT_SERVICE_PROPERTIES(nextservice);
    QString mlt_type = mlt_properties_get(properties, "mlt_type");
    QString resource = mlt_properties_get(properties, "mlt_service");
    int in_pos = (int) in.frames(m_fps);
    int out_pos = (int) out.frames(m_fps) - 1;

    while (mlt_type == QLatin1String("transition")) {
        mlt_transition tr = (mlt_transition) nextservice;
        int currentTrack = mlt_transition_get_b_track(tr);
        int currentBTrack = mlt_transition_get_a_track(tr);
        int currentIn = (int) mlt_transition_get_in(tr);
        int currentOut = (int) mlt_transition_get_out(tr);

        // //qDebug()<<"Looking for transition : " << currentIn <<'x'<<currentOut<< ", OLD oNE: "<<in_pos<<'x'<<out_pos;
        if (resource == type && b_track == currentTrack && currentIn == in_pos && currentOut == out_pos) {
            QMap<QString, QString> map = getTransitionParamsFromXml(xml);
            QMap<QString, QString>::Iterator it;
            QString key;
            mlt_properties transproperties = MLT_TRANSITION_PROPERTIES(tr);

            QString currentId = mlt_properties_get(transproperties, "kdenlive_id");
            if (currentId != xml.attribute(QStringLiteral("id"))) {
                // The transition ID is not the same, so reset all properties
                mlt_properties_set(transproperties, "kdenlive_id", xml.attribute(QStringLiteral("id")).toUtf8().constData());
                // Cleanup previous properties
                QStringList permanentProps;
                permanentProps << QStringLiteral("factory") << QStringLiteral("kdenlive_id") << QStringLiteral("mlt_service") << QStringLiteral("mlt_type") << QStringLiteral("in");
                permanentProps << QStringLiteral("out") << QStringLiteral("a_track") << QStringLiteral("b_track");
                for (int i = 0; i < mlt_properties_count(transproperties); ++i) {
                    QString propName = mlt_properties_get_name(transproperties, i);
                    if (!propName.startsWith('_') && ! permanentProps.contains(propName)) {
                        mlt_properties_set(transproperties, propName.toUtf8().constData(), "");
                    }
                }
            }

            mlt_properties_set_int(transproperties, "force_track", xml.attribute(QStringLiteral("force_track")).toInt());
            mlt_properties_set_int(transproperties, "automatic", xml.attribute(QStringLiteral("automatic"), QStringLiteral("0")).toInt());

            if (currentBTrack != a_track) {
                mlt_properties_set_int(transproperties, "a_track", a_track);
            }
            for (it = map.begin(); it != map.end(); ++it) {
                key = it.key();
                mlt_properties_set(transproperties, key.toUtf8().constData(), it.value().toUtf8().constData());
                ////qDebug() << " ------  UPDATING TRANS PARAM: " << key.toUtf8().constData() << ": " << it.value().toUtf8().constData();
                //filter->set("kdenlive_id", id);
            }
            break;
        }
        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");
    }
    field->unlock();
    //askForRefresh();
    //if (m_isBlocked == 0) m_mltConsumer->set("refresh", 1);
}
const QString Timecode::getTimecodeDropFrame(const GenTime & time) const
{
    return getTimecodeDropFrame((int)time.frames(m_realFps));
}
const QString Timecode::getTimecodeSeconds(const GenTime & time) const
{
    QLocale locale;
    locale.setNumberOptions(QLocale::OmitGroupSeparator);
    return locale.toString(time.seconds());
}
const QString Timecode::getTimecodeFrames(const GenTime & time) const
{
    return QString::number((int) time.frames(m_realFps));
}
QString Timecode::getDisplayTimecode(const GenTime & time, bool frameDisplay) const
{
    if (frameDisplay) return QString::number((int) time.frames(m_realFps));
    return getTimecode(time);
}