Logo Search packages:      
Sourcecode: kdenlive version File versions

docclipref.cpp

/**************************1*************************************************
                          DocClipRef.cpp  -  description
                             -------------------
    begin                : Fri Apr 12 2002
    copyright            : (C) 2002 by Jason Wood
    email                : jasonwood@blueyonder.co.uk
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <qimage.h>
#include <qdir.h>

#include <kdebug.h>

#include "docclipref.h"

#include "clipmanager.h"
#include "docclipbase.h"
#include "docclipavfile.h"
#include "doccliptextfile.h"
#include "docclipproject.h"
#include "doctrackbase.h"
#include "docclipbase.h"
#include "effectdesc.h"
#include "effectkeyframe.h"
#include "effectparameter.h"
#include "effectparamdesc.h"
#include "effectdoublekeyframe.h"
#include "effectcomplexkeyframe.h"
#include "kdenlivedoc.h"
#include "kdenlivesettings.h"
#include "initeffects.h"

#define AUDIO_FRAME_WIDTH 20
DocClipRef::DocClipRef(DocClipBase * clip):
startTimer(0),
endTimer(0),
m_trackStart(0.0),
m_cropStart(0.0),
m_trackEnd(0.0), m_parentTrack(0),  m_trackNum(-1),
m_clip(clip),  m_speed(1.0)
{
    if (!clip) {
      kdError() <<
          "Creating a DocClipRef with no clip - not a very clever thing to do!!!"
          << endl;
    }

    DocClipBase::CLIPTYPE t = m_clip->clipType();

    // If clip is a video, resizing it should update the thumbnails
    if (t == DocClipBase::VIDEO || t == DocClipBase::AV || t == DocClipBase::VIRTUAL || t == DocClipBase::PLAYLIST) {
      m_thumbnail = QPixmap();
        m_endthumbnail = QPixmap();
        startTimer = new QTimer( this );
        endTimer = new QTimer( this );
        connect(clip->thumbCreator, SIGNAL(thumbReady(int, QPixmap)),this,SLOT(updateThumbnail(int, QPixmap)));
        connect(this, SIGNAL(getClipThumbnail(KURL, int, int, int)), clip->thumbCreator, SLOT(getImage(KURL, int, int, int)));
        connect( startTimer, SIGNAL(timeout()), this, SLOT(doFetchStartThumbnail()));
        connect( endTimer, SIGNAL(timeout()), this, SLOT(doFetchEndThumbnail()));
    }
    if (t == DocClipBase::AUDIO || t == DocClipBase::AV) {
      if (t != DocClipBase::AV){
            m_thumbnail = referencedClip()->thumbnail();
            m_endthumbnail = m_thumbnail;
      }
      connect(clip->thumbCreator, SIGNAL(audioThumbReady(QMap<int,QMap<int,QByteArray> >)), this, SLOT(updateAudioThumbnail(QMap<int,QMap<int,QByteArray> >)));
    }
}

DocClipRef::~DocClipRef()
{
    delete startTimer;
    delete endTimer;
}

void DocClipRef::refreshAudioThumbnail()
{
      if (m_clip->clipType() != DocClipBase::AV && m_clip->clipType() != DocClipBase::AUDIO) return;
      if (KdenliveSettings::audiothumbnails()) {
            if (!m_clip->audioThumbCreated) m_clip->toDocClipAVFile()->getAudioThumbs();
      }
      else {
            if (!m_clip->audioThumbCreated) m_clip->toDocClipAVFile()->stopAudioThumbs();
            m_clip->audioThumbCreated = false;
            referencedClip()->audioFrameChache.clear();
            kdDebug()<<"**********  FREED MEM FOR: "<<name()<<", COUNT: "<<referencedClip()->audioFrameChache.count ()<<endl;
      }
}

void DocClipRef::updateAudioThumbnail(QMap<int,QMap<int,QByteArray> >)
{
    m_clip->audioThumbCreated = true;
    if (m_parentTrack) QTimer::singleShot(200, this, SLOT(refreshCurrentTrack()));
}

void DocClipRef::refreshCurrentTrack()
{
    m_parentTrack->notifyClipChanged(this);
}

bool DocClipRef::hasVariableThumbnails()
{
    DocClipBase::CLIPTYPE t = m_clip->clipType();
    if (( t == DocClipBase::VIDEO || t == DocClipBase::AV || t == DocClipBase::VIRTUAL || t == DocClipBase::PLAYLIST) && KdenliveSettings::videothumbnails())
        return true;
    return false;
}

void DocClipRef::generateThumbnails()
{
    DocClipBase::CLIPTYPE t = m_clip->clipType();
    if (t == DocClipBase::VIDEO || t == DocClipBase::AV || t == DocClipBase::VIRTUAL || t == DocClipBase::PLAYLIST) {
      fetchThumbnails();
      return;
    }

    uint height = (uint)KdenliveSettings::videotracksize();
    uint width = (uint) (height * KdenliveSettings::displayratio());

    QPixmap result(width, height);
    result.fill(Qt::black);

    if (m_clip->clipType() == DocClipBase::COLOR) {
        QPixmap p(width - 2, height - 2);
        QString col = m_clip->toDocClipAVFile()->color();
        col = col.replace(0, 2, "#");
        p.fill(QColor(col.left(7)));
      copyBlt(&result, 1, 1, &p, 0, 0, width - 2, height - 2);
        m_endthumbnail = result;
        m_thumbnail = result;
    }
    else if (m_clip->clipType() == DocClipBase::TEXT || m_clip->clipType() == DocClipBase::IMAGE) {
          QPixmap p(fileURL().path());
            QImage im;
            im = p;
            p = im.smoothScale(width - 2, height - 2);
          copyBlt(&result, 1, 1, &p, 0, 0, width - 2, height - 2);
            m_endthumbnail = result;
            m_thumbnail = result;
    }
    else if (m_clip->clipType() == DocClipBase::SLIDESHOW) {
          QString fileType = fileURL().filename().right(3);
          QStringList more;
          QStringList::Iterator it;
          QPixmap p1, p2;
          QDir dir( fileURL().directory() );
          more = dir.entryList( QDir::Files );
      
          for ( it = more.begin() ; it != more.end() ; ++it ) {
            if ((*it).endsWith("."+fileType, FALSE)) {
                p1.load(fileURL().directory() + "/" + *it);
                break;
            }
          }

          for ( it = more.end() ; it != more.begin() ; --it ) {
              if ((*it).endsWith("."+fileType, FALSE)) {
                p2.load(fileURL().directory() + "/" + *it);
                break;
            }
          }
          QImage im;
          im = p1;
          p1 = im.smoothScale(width - 2, height - 2);
          copyBlt(&result, 1, 1, &p1, 0, 0, width - 2, height - 2);
          m_thumbnail = result;
          result.fill(Qt::black);
          im = p2;
          p2 = im.smoothScale(width - 2, height - 2);
          copyBlt(&result, 1, 1, &p2, 0, 0, width - 2, height - 2);
          m_endthumbnail = result;
      }
}

QPixmap DocClipRef::extractThumbnail(int width, int height)
{
    return m_clip->thumbCreator->extractImage( fileURL(), referencedClip()->getProjectThumbFrame(), width, height );
}

const GenTime & DocClipRef::trackStart() const
{
    return m_trackStart;
}


void DocClipRef::setTrackStart(const GenTime time)
{
    m_trackStart = time;

    if (m_parentTrack) {
      m_parentTrack->clipMoved(this);
    }
}

const QString & DocClipRef::name() const
{
    return m_clip->name();
}

const QString & DocClipRef::description() const
{
    return m_clip->description();
}

void DocClipRef::setDescription(const QString & description)
{
    m_clip->setDescription(description);
}

void DocClipRef::fetchStartThumbnail()
{
      startTimer->start( 180 , TRUE);
}

void DocClipRef::doFetchStartThumbnail()
{
      uint height = (uint)(KdenliveSettings::videotracksize());
      uint width = (uint)(height * KdenliveSettings::displayratio());
      emit getClipThumbnail(fileURL(), (int) (m_cropStart.frames(KdenliveSettings::defaultfps()) * m_speed), width, height);
}

void DocClipRef::fetchThumbnails()
{
      if (!m_thumbnail.isNull() && !m_endthumbnail.isNull() && m_thumbnail.height() == KdenliveSettings::videotracksize()) return;
      uint height = (uint)(KdenliveSettings::videotracksize());
      uint width = (uint)(height * KdenliveSettings::displayratio());
      int startFrame = (int) (m_cropStart.frames(KdenliveSettings::defaultfps() * m_speed));
      m_clip->thumbCreator->getThumbs(fileURL(), startFrame, (int) ( startFrame + cropDuration().frames(KdenliveSettings::defaultfps()) - 1), width, height);
}

void DocClipRef::fetchEndThumbnail()
{
      endTimer->start( 180 , TRUE);
}

void DocClipRef::doFetchEndThumbnail()
{
      uint height = (uint)(KdenliveSettings::videotracksize());
      uint width = (uint)(height * KdenliveSettings::displayratio());
      emit getClipThumbnail(fileURL(),(int) (( m_cropStart.frames(KdenliveSettings::defaultfps())+cropDuration().frames(KdenliveSettings::defaultfps()) - 1) * m_speed), width, height);
}

void DocClipRef::setCropStartTime(const GenTime & time)
{
    // Adjust all transitions
    if (!m_transitionStack.isEmpty()) {
        TransitionStack::iterator itt = m_transitionStack.begin();
        while (itt != m_transitionStack.end()) {
            if ((*itt)->transitionStartTime() != trackStart())
                (*itt)->moveTransition(m_cropStart - time);
            ++itt;
        }
    }
    m_cropStart = time;
    if (m_parentTrack) {
      m_parentTrack->clipMoved(this);
    }
}

void DocClipRef::moveCropStartTime(const GenTime & time)
{
    // Delete all transitions before new start time
    if (!m_transitionStack.isEmpty()) {
      GenTime cutTime = time + m_trackStart - m_cropStart;
        TransitionStack::iterator itt = m_transitionStack.begin();
        while (itt != m_transitionStack.end()) {
            if ((*itt)->transitionStartTime() < cutTime) {
                if ((*itt)->transitionEndTime() < cutTime) m_transitionStack.remove(*itt);
            else {
                  GenTime transEnd = (*itt)->transitionEndTime();
                  (*itt)->moveTransition(m_cropStart - time);
                  (*itt)->resizeTransitionEnd(transEnd + m_cropStart - time);
            }
          }
          else (*itt)->moveTransition(m_cropStart - time);
            ++itt;
        }
    }
    m_cropStart = time;
    if (m_parentTrack) {
      m_parentTrack->clipMoved(this);
    }
}

const GenTime & DocClipRef::cropStartTime() const
{
    return m_cropStart;
    //return adjustTimeToSpeed(m_cropStart);
}


void DocClipRef::setTrackEnd(const GenTime & time)
{
    // Check all transitions
    if (!m_transitionStack.isEmpty()) {
        TransitionStack::iterator itt = m_transitionStack.begin();
        while (itt != m_transitionStack.end()) {
            if (time - (*itt)->transitionStartTime() < GenTime(2, m_clip->framesPerSecond()))
                (*itt)->moveTransition(time - trackEnd());
            //GenTime(0) - GenTime(3, m_clip->framesPerSecond()));
            ++itt;
        }
    }

    // do not allow clips below 0
    if (time > GenTime(0.0)) {
      // If user tries to make clip of 0 frame, resize to 5 frames
      if (time < m_trackStart || time == m_trackStart) m_trackEnd = m_trackStart + GenTime(5, m_clip->framesPerSecond());
      else m_trackEnd = time;
    }
    else m_trackEnd = GenTime(5, m_clip->framesPerSecond());

    if (m_parentTrack) {
      m_parentTrack->clipMoved(this);
    }
}

GenTime DocClipRef::cropDuration() const
{
    return trackEnd() - trackStart();
}

void DocClipRef::updateThumbnail(int frame, QPixmap newpix)
{
    if (m_cropStart.frames(KdenliveSettings::defaultfps()) + cropDuration().frames(KdenliveSettings::defaultfps()) -1 == frame)
        m_endthumbnail = newpix;
    else if (m_cropStart.frames(KdenliveSettings::defaultfps()) == frame) m_thumbnail = newpix;
    else return;
    if (m_parentTrack) m_parentTrack->notifyClipChanged(this);
}

QPixmap DocClipRef::thumbnail(bool end) const
{
    if (end) return m_endthumbnail;
    return m_thumbnail;
}

int DocClipRef::thumbnailWidth() const
{
    return m_thumbnail.width();
}

DocClipRef *DocClipRef::
createClip(KdenliveDoc *doc, const QDomElement & element)
{
    DocClipRef *clip = 0;
    GenTime trackStart;
    GenTime cropStart;
    GenTime cropDuration;
    GenTime trackEnd;
    QString description;
    double speed = 1.0;
    EffectStack effectStack;
    QValueVector < CommentedTime > markers;

    /*kdWarning() << "================================" << endl;
    kdWarning() << "Creating Clip : " << element.ownerDocument().
    toString() << endl;*/

    int trackNum = -1;

    QDomNode node = element;
    node.normalize();

    if (element.tagName() != "kdenliveclip") {
      kdWarning() <<
          "DocClipRef::createClip() element has unknown tagName : " <<
          element.tagName() << endl;
      return 0;
    }
    int clipId = -1;

    QDomElement t;
    QDomNode n = element.firstChild();
    QDomElement e;

    while (!n.isNull()) {
      e = n.toElement();
      if (!e.isNull()) {
          //kdWarning() << "DocClipRef::createClip() tag = " << e.tagName() << endl;
          if (e.tagName() == "avfile") {
            clipId = e.attribute("id", "-1").toInt();
            // Do nothing, this is handled via the clipmanage insertClip method above.
          } else if (e.tagName() == "project") {
            // Do nothing, this is handled via the clipmanage insertClip method above.
          } else if (e.tagName() == "position") {
            trackNum = e.attribute("kdenlivetrack", "-1").toInt();
            trackStart =
                GenTime(e.attribute("trackstart", "0").toDouble());
            cropStart =
                GenTime(e.attribute("cropstart", "0").toDouble());
            cropDuration =
                GenTime(e.attribute("cropduration", "0").toDouble());
            trackEnd =
                GenTime(e.attribute("trackend", "-1").toDouble());
            speed = e.attribute("speed", "1.0").toDouble();
          }  else if (e.tagName() == "effects") {
            //kdWarning() << "Found effects tag" << endl;
            QDomNode effectNode = e.firstChild();
            while (!effectNode.isNull()) {
                QDomElement effectElement = effectNode.toElement();
                //kdWarning() << "Effect node..." << endl;
                if (!effectElement.isNull()) {
                  //kdWarning() << "has tag name " << effectElement.tagName() << endl;
                  if (effectElement.tagName() == "effect") {
                        //kdWarning() << "Appending effect " <<desc->name() << endl;
                        effectStack.append(doc->createEffect( effectElement));
                  } else {
                      kdWarning() << "Unknown tag " << effectElement.
                        tagName() << endl;
                  }
                }
                effectNode = effectNode.nextSibling();
            }
            }
            else if (e.tagName() == "transitions") {
                t = e;
                //kdWarning() << "Found transition tag" << endl;

            } else if (e.tagName() == "markers") {
            QDomNode markerNode = e.firstChild();
            while (!markerNode.isNull()) {
                QDomElement markerElement = markerNode.toElement();
                if (!markerElement.isNull()) {
                  if (markerElement.tagName() == "marker") {
                      markers.append(CommentedTime(GenTime(markerElement.
                            attribute("time", "0").toDouble()),markerElement.attribute("comment", "")));
                  } else {
                      kdWarning() << "Unknown tag " << markerElement.
                        tagName() << endl;
                  }
                }
                markerNode = markerNode.nextSibling();
            }
          }
            else {
//               kdWarning() << "DocClipRef::createClip() unknown tag : " << e.tagName() << endl;
          }
      }

      n = n.nextSibling();
    }

    DocClipBase *baseClip = doc->clipManager().insertClip(element, clipId);
    if (baseClip) {
      clip = new DocClipRef(baseClip);
    }


    if (clip == 0) {
      kdWarning() << "DocClipRef::createClip() unable to create clip" <<
          endl;
    } else {
      // setup DocClipRef specifics of the clip.
      clip->setSpeed(speed);
      clip->setTrackStart(trackStart);
      clip->setCropStartTime(cropStart);
      if (clip->snapMarkers().count() == 0) clip->setSnapMarkers(markers);
      if (trackEnd.seconds() != -1) {
          clip->setTrackEnd(trackEnd);
      } else {
            clip->setTrackEnd(trackStart + cropDuration - GenTime(1, clip->framesPerSecond()));
      }
      clip->setParentTrack(0, trackNum);
      //clip->setDescription(description);
      clip->setEffectStack(effectStack);
        // add Transitions
        if (!t.isNull()) {
            QDomNode transitionNode = t.firstChild();
            while (!transitionNode.isNull()) {
                QDomElement transitionElement = transitionNode.toElement();
                if (!transitionElement.isNull()) {
                    if (transitionElement.tagName() == "ktransition") {
                  Transition *transit = new Transition(clip, transitionElement);
                        clip->addTransition(transit);
                    } else {
                        kdWarning() << "Unknown transition " <<transitionElement.attribute("type",QString::null) << endl;
                    }
                } else {
                kdWarning() << "Unknown tag " << transitionElement.tagName() << endl;
                }
                transitionNode = transitionNode.nextSibling();
            }
        }
    }
    return clip;
}

/** Sets the parent track for this clip. */
void DocClipRef::setParentTrack(DocTrackBase * track, const int trackNum)
{
    m_parentTrack = track;
    m_trackNum = trackNum;
}

/** Returns the track number. This is a hint as to which track the clip is on, or should be placed on. */
int DocClipRef::trackNum() const
{
    return m_trackNum;
}

/** Returns the track number in MLT's playlist */
int DocClipRef::playlistTrackNum() const
{
    return m_parentTrack->projectClip()->playlistTrackNum(m_trackNum);
}

/** Returns the track number in MLT's playlist */
int DocClipRef::playlistNextTrackNum() const
{
    return m_parentTrack->projectClip()->playlistNextVideoTrack(m_trackNum);
}

/** Returns the track number in MLT's playlist */
int DocClipRef::playlistOtherTrackNum(int num) const
{
    return m_parentTrack->projectClip()->playlistTrackNum(num);
}

/** Returns the end of the clip on the track. A convenience function, equivalent
to trackStart() + cropDuration() */
GenTime DocClipRef::trackEnd() const
{
    return m_trackEnd;
    //return adjustTimeToSpeed(m_trackEnd - m_trackStart + m_cropStart) - cropStartTime() + m_trackStart;
}

/** Returns the parentTrack of this clip. */
DocTrackBase *DocClipRef::parentTrack()
{
    return m_parentTrack;
}

/** Move the clips so that it's trackStart coincides with the time specified. */
void DocClipRef::moveTrackStart(const GenTime & time)
{
    m_trackEnd = m_trackEnd + time - m_trackStart;
    m_trackStart = time;
}

DocClipRef *DocClipRef::clone(KdenliveDoc *doc)
{
    return createClip(doc, toXML().documentElement());
}

bool DocClipRef::referencesClip(DocClipBase * clip) const
{
    return m_clip->referencesClip(clip);
}

uint DocClipRef::numReferences() const
{
    return m_clip->numReferences();
}

double DocClipRef::framesPerSecond() const
{
    if (m_parentTrack) {
      return m_parentTrack->framesPerSecond();
    } else {
      return m_clip->framesPerSecond();
    }
}

//returns clip video properties -reh
DocClipBase::CLIPTYPE DocClipRef::clipType() const
{
    return m_clip->clipType();
}

uint DocClipRef::clipHeight() const
{
    if (m_clip->isDocClipAVFile())
        return m_clip->toDocClipAVFile()->clipHeight();
    else if (m_clip->isDocClipTextFile())
        return m_clip->toDocClipTextFile()->clipHeight();
    return KdenliveSettings::defaultheight();
}

uint DocClipRef::clipWidth() const
{
    if (m_clip->isDocClipAVFile())
        return m_clip->toDocClipAVFile()->clipWidth();
    else if (m_clip->isDocClipTextFile())
        return m_clip->toDocClipTextFile()->clipWidth();
    return KdenliveSettings::defaultwidth();
}

QString DocClipRef::avDecompressor()
{
    if (m_clip->isDocClipAVFile())
        return m_clip->toDocClipAVFile()->avDecompressor();
    return QString::null;
}

//type ntsc/pal
QString DocClipRef::avSystem()
{
    if (m_clip->isDocClipAVFile())
        return m_clip->toDocClipAVFile()->avSystem();
    return QString::null;
}

//returns clip audio properties -reh
uint DocClipRef::audioChannels() const
{
    if (m_clip->isDocClipAVFile())
        return m_clip->toDocClipAVFile()->audioChannels();
    return 0;
}

QString DocClipRef::audioFormat()
{
    if (m_clip->isDocClipAVFile())
        return m_clip->toDocClipAVFile()->audioFormat();
    return QString::null;
}

uint DocClipRef::audioBits() const
{
    if (m_clip->isDocClipAVFile())
        return m_clip->toDocClipAVFile()->audioBits();
    return 0;
}

uint DocClipRef::audioFrequency() const
{
    if (m_clip->isDocClipAVFile())
        return m_clip->toDocClipAVFile()->audioFrequency();
    return 0;
}

QDomDocument DocClipRef::toXML() const
{
    QDomDocument doc = m_clip->toXML();

    QDomElement clip = doc.documentElement();

    if (clip.tagName() != "kdenliveclip") {
      kdError() <<
          "Expected tagname of 'clip' in DocClipRef::toXML(), expect things to go wrong!"
          << endl;
    }

    QDomElement position = doc.createElement("position");
    position.setAttribute("kdenlivetrack", QString::number(trackNum()));
    position.setAttribute("trackstart",
      QString::number(trackStart().seconds(), 'f', 10));
    position.setAttribute("cropstart",
      QString::number(cropStartTime().seconds(), 'f', 10));
    position.setAttribute("cropduration",
      QString::number(cropDuration().seconds(), 'f', 10));
    position.setAttribute("trackend", QString::number(trackEnd().seconds(),
          'f', 10));
    position.setAttribute("speed", QString::number(m_speed, 'f'));

    clip.appendChild(position);

    //  append clip effects
    if (!m_effectStack.isEmpty()) {
      QDomElement effects = doc.createElement("effects");

      EffectStack::iterator itt = m_effectStack.begin();
      while (itt != m_effectStack.end()) {
          effects.appendChild(doc.importNode((*itt)->toXML().
                documentElement(), true));
          ++itt;
      }

      clip.appendChild(effects);
    }
    
    //  append clip transitions
    if (!m_transitionStack.isEmpty()) {
        QDomElement trans = doc.createElement("transitions");

        TransitionStack::iterator itt = m_transitionStack.begin();
        while (itt != m_transitionStack.end()) {
            trans.appendChild(doc.importNode((*itt)->toXML(), true));
            ++itt;
        }

        clip.appendChild(trans);
    }
    doc.appendChild(clip);

    return doc;
}

QStringList DocClipRef::clipEffectNames() const
{
    QStringList effectNames;
    if (!m_effectStack.isEmpty()) {
      EffectStack::iterator itt = m_effectStack.begin();
      while (itt != m_effectStack.end()) {
          if ((*itt)->isEnabled()) effectNames<<(*itt)->name();
          ++itt;
      }
    }
    return effectNames;
}

bool DocClipRef::matchesXML(const QDomElement & element) const
{
    bool result = false;
    if (element.tagName() == "kdenliveclip") {
      QDomNodeList nodeList = element.elementsByTagName("position");
      if (nodeList.length() > 0) {
          if (nodeList.length() > 1) {
            kdWarning() <<
                "More than one position in XML for a docClip? Only matching first one"
                << endl;
          }
          QDomElement positionElement = nodeList.item(0).toElement();

          if (!positionElement.isNull()) {
            result = true;
            if (positionElement.attribute("kdenlivetrack").toInt() !=
                trackNum())
                result = false;
            if (positionElement.attribute("trackstart").toInt() !=
                trackStart().seconds())
                result = false;
            if (positionElement.attribute("cropstart").toInt() !=
                cropStartTime().seconds())
                result = false;
            if (positionElement.attribute("cropduration").toInt() !=
                cropDuration().seconds())
                result = false;
            if (positionElement.attribute("trackend").toInt() !=
                trackEnd().seconds())
                result = false;
            if (positionElement.attribute("speed").toDouble() !=
                speed())
                result = false;

          }
      }
    }

    return result;
}

const GenTime & DocClipRef::duration() const
{
    return m_clip->duration();
    /*if (m_speed == 1.0 && m_endspeed == 1.0) return m_clip->duration();
    else {
      int frameCount = (int)(m_clip->duration().frames(framesPerSecond()) * 2 / (m_speed + m_endspeed));
      return GenTime(frameCount, framesPerSecond());
    }*/
}

bool DocClipRef::durationKnown() const
{
    return m_clip->durationKnown();
}

double DocClipRef::speed() const
{
    return m_speed;
}

void DocClipRef::setSpeed(double newspeed)
{
    if (!m_parentTrack) {
      m_speed = newspeed;
      return;
    }
    double newDuration = (double)((m_trackEnd.frames(framesPerSecond()) - m_trackStart.frames(framesPerSecond())) * m_speed) / (newspeed);
    double newCropStart = (double) m_cropStart.frames(framesPerSecond()) * m_speed / (newspeed);
    //double newDuration = origDuration * 2.0 / (newspeed + endspeed);
    if (trackEnd() != m_parentTrack->trackLength()) {
      // The clip is not the last one on track, check available space
        GenTime availableSpace = GenTime(0) - m_parentTrack->spaceLength(trackEnd() + GenTime(1, framesPerSecond()));
        if (GenTime(newDuration, framesPerSecond()) - cropDuration() > availableSpace) {
          kdDebug()<<"// Cannot change speed, it would overlap another clip."<<endl;
          if (!m_effectStack.isEmpty()) {
            EffectStack::iterator itt = m_effectStack.begin();
            while (itt != m_effectStack.end()) {
                  if ((*itt)->name() == i18n("Speed")) {
                      (*itt)->effectDescription().parameter(0)->setValue(QString::number((int) (m_speed * 100)));
                  }
                  ++itt;
            }
            }
          return;
      }
    }
    m_speed = newspeed;
    m_trackEnd = m_trackStart + GenTime(newDuration, framesPerSecond());
    m_cropStart = GenTime(newCropStart, framesPerSecond());
    if (m_parentTrack) m_parentTrack->notifyTrackChanged(this);
}

QDomDocument DocClipRef::generateSceneList(bool, bool)
{
    QDomDocument sceneList = m_clip->generateSceneList();
    QDomNodeList producers = sceneList.elementsByTagName("producer");
    
    if (producers.count() == 0)
        return sceneList;
    
    QDomElement producer = producers.item(0).toElement();
    // producer.setAttribute("in", cropStartTime().frames(framesPerSecond()));
    // producer.setAttribute("out", (cropStartTime() + cropDuration()).frames(framesPerSecond()));
    // If this clip has a non 1.0 speed, wrap it in a framebuffer service so 
    // that when resizing individual clips with a speed effect, the correct frame 
    // is shown
    if (m_speed == 1.0)
        return sceneList;

    // Get the producer for this scene list. If it has no associated service, 
    // give it to the frambuffer service and set its speed

    if (!producer.hasAttribute("resource") || producer.hasAttribute("mlt_service"))
        return sceneList;

    producer.setAttribute("mlt_service", "framebuffer");
      producer.setAttribute("resource", producer.attribute("resource") + ":" + QString::number(m_speed));

    return sceneList;
}

QDomDocumentFragment DocClipRef::generateXMLTransition(bool hideVideo, bool hideAudio)
{
    QDomDocument transitionList;
    QDomDocumentFragment list = transitionList.createDocumentFragment();

    transitionList.appendChild(list);
    DocClipBase::CLIPTYPE ct = clipType();
    bool transparentBackgroundClip = false;

    if (!hideVideo) {
      if (ct == DocClipBase::TEXT && m_clip->toDocClipTextFile()->isTransparent()) 
          transparentBackgroundClip = true;
      else if ((ct == DocClipBase::IMAGE || ct == DocClipBase::SLIDESHOW) && m_clip->toDocClipAVFile()->isTransparent()) 
          transparentBackgroundClip = true;
    }

    // Add transition to create transparent bg effect for image/text clips 
    //      or clips with Blue screen effect
    if (transparentBackgroundClip || hasEffect("chroma"))
    {
      int transitionNumber = m_transitionStack.count();
      QValueList < QPoint > blanklist;
      blanklist.append(QPoint((int) trackStart().frames(framesPerSecond()), (int) trackEnd().frames(framesPerSecond())));
      while (transitionNumber > 0) {
          // Parse all clip transitions and build a list of times without transitions
          QValueList < QPoint >::Iterator it;
          Transition *t = m_transitionStack.at(transitionNumber - 1);
          int transStart = (int) t->transitionStartTime().frames(framesPerSecond());
          int transEnd = (int) t->transitionEndTime().frames(framesPerSecond());
          for ( it = blanklist.begin(); it != blanklist.end(); ++it ) {
            int currentStart = (*it).x();
            int currentEnd = (*it).y();
            // kdDebug()<<"// CURRENT TRANSITION IS: "<<transStart<<" - "<<transEnd<<endl;
            // kdDebug()<<"// CURRENT ANALYSED: "<<currentStart<<" - "<<currentEnd<<endl;
            if (transStart <= currentEnd && transEnd >= currentStart) {
                if (currentStart != transStart) {
                  (*it) = QPoint(currentStart, transStart);
                  if (transEnd != currentEnd) blanklist.append(QPoint(transEnd, currentEnd));
                }
                else {
                  if (transEnd == currentEnd) blanklist.remove(*it);
                  else (*it) = QPoint(transEnd, currentEnd);
                }
                break;
            }
          }
          transitionNumber--;
      }

      // Insert "transparent" composite transition in places where the clip has no transition
      QValueList < QPoint >::Iterator it;
      for ( it = blanklist.begin(); it != blanklist.end(); ++it ) {
          QDomElement transition = transitionList.createElement("transition");
            transition.setAttribute("in", (*it).x());
            transition.setAttribute("out", (*it).y());
            transition.setAttribute("mlt_service", "composite");
            transition.setAttribute("fill", "1");
          //if (ct == DocClipBase::TEXT) transition.setAttribute("distort", "1");
            transition.setAttribute("progressive","1");
          transition.setAttribute("valign","1");
          transition.setAttribute("halign","1");
            transition.setAttribute("a_track", QString::number( playlistNextTrackNum()));
            transition.setAttribute("b_track", QString::number(playlistTrackNum()));
            list.appendChild(transition);
      }
    }
 
    TransitionStack::iterator itt = m_transitionStack.begin(); 
    while (itt) {
      bool block = false;
      uint type = (*itt)->transitionType();
      if ((type < 100) &&  m_parentTrack->clipType() == "Sound")
          block = true;
      if (hideVideo && type < 200) block = true;
      if (hideAudio && type > 99) block = true;
      if (!block) {
            QDomElement transition = transitionList.createElement("transition");
            transition.setAttribute("in", QString::number((*itt)->transitionStartTime().frames(framesPerSecond())));
            transition.setAttribute("out", QString::number((*itt)->transitionEndTime().frames(framesPerSecond()) - 1));
            if (type == Transition::PIP_TRANSITION)
            transition.setAttribute("mlt_service", "composite");
            else transition.setAttribute("mlt_service", (*itt)->transitionTag());
            transition.setAttribute("fill", "1");

          if (transition.attribute("mlt_service") == "composite") {
            transition.setAttribute("valign", "1");
            transition.setAttribute("halign", "1");
          }
            //transition.setAttribute("distort", "1");

          // Parse transition attributes
            typedef QMap<QString, QString> ParamMap;
            ParamMap params;
            params = (*itt)->transitionParameters();
            ParamMap::Iterator it;
            for ( it = params.begin(); it != params.end(); ++it ) {
                  transition.setAttribute(it.key(), it.data());
            }

          /* The crossfade LUMA transition does not work on images/texts with transp. 
             background, so we replace it with a composite transition */
          if (transparentBackgroundClip && type == Transition::LUMA_TRANSITION) {
            transition.setAttribute("mlt_service", "composite");
            QString geom;
            if (!(*itt)->invertTransition()) geom = "0=0,0:100%x100%:0;-1=0,0:100%x100%:100";
            else geom = "0=0,0:100%x100%:100;-1=0,0:100%x100%:0";
            transition.setAttribute("geometry", geom);
            transition.setAttribute("halign", 1);
            transition.setAttribute("valign", 1);
          }

          if (type == Transition::LUMA_TRANSITION || type == Transition::MIX_TRANSITION || type == Transition::LUMAFILE_TRANSITION) {
                transition.setAttribute("b_track", QString::number((*itt)->transitionStartTrack()));
                transition.setAttribute("a_track", QString::number((*itt)->transitionEndTrack()));
              if ((*itt)->invertTransition()) transition.setAttribute("reverse", "1");
          }
          else if ((*itt)->invertTransition()) {
                transition.setAttribute("a_track", QString::number((*itt)->transitionStartTrack()));
                transition.setAttribute("b_track", QString::number((*itt)->transitionEndTrack()));
            }
            else {
                transition.setAttribute("b_track", QString::number((*itt)->transitionStartTrack()));
                transition.setAttribute("a_track", QString::number((*itt)->transitionEndTrack()));
            }
            list.appendChild(transition);
      }
        ++itt;
    }
    return list;
}


QDomDocumentFragment DocClipRef::generateOffsetXMLTransition(bool hideVideo, bool hideAudio, GenTime start, GenTime end)
{
    QDomDocument transitionList;
    QDomDocumentFragment list = transitionList.createDocumentFragment();

    transitionList.appendChild(list);
    DocClipBase::CLIPTYPE ct = clipType();
    bool transparentBackgroundClip = false;

    if (!hideVideo) {
      if (ct == DocClipBase::TEXT && m_clip->toDocClipTextFile()->isTransparent()) 
      transparentBackgroundClip = true;
    else if ((ct == DocClipBase::IMAGE || ct == DocClipBase::SLIDESHOW) && m_clip->toDocClipAVFile()->isTransparent()) 
      transparentBackgroundClip = true;
    }

    // Add transition to create transparent bg effect for image/text clips
    if (( transparentBackgroundClip && m_transitionStack.count() == 0 )  || hasEffect("chroma"))
    {
        QDomElement transition = transitionList.createElement("transition");
        transition.setAttribute("in", (trackStart() - start).frames(framesPerSecond()));
        transition.setAttribute("out", (trackEnd() - start).frames(framesPerSecond()) - 1);
        transition.setAttribute("mlt_service", "composite");
        transition.setAttribute("fill", "1");
        transition.setAttribute("progressive","1");
      transition.setAttribute("valign","1");
      transition.setAttribute("halign","1");
        transition.setAttribute("a_track", QString::number( playlistNextTrackNum()));
        transition.setAttribute("b_track", QString::number(playlistTrackNum()));
        list.appendChild(transition);
    }
 
    TransitionStack::iterator itt = m_transitionStack.begin(); 
    while (itt) {
      bool block = false;
      uint type = (*itt)->transitionType();
      if ((type < 100) &&  m_parentTrack->clipType() == "Sound")
          block = true;
      if (hideVideo && type < 200) block = true;
      if (hideAudio && type > 99) block = true;
      if (!block) {
            QDomElement transition = transitionList.createElement("transition");
            transition.setAttribute("in", QString::number(((*itt)->transitionStartTime() - start).frames(framesPerSecond())));
            transition.setAttribute("out", QString::number(((*itt)->transitionEndTime() - start).frames(framesPerSecond()) - 1));

            if (type == Transition::PIP_TRANSITION) transition.setAttribute("mlt_service", "composite");
            else transition.setAttribute("mlt_service", (*itt)->transitionTag());
            transition.setAttribute("fill", "1");

          if (transition.attribute("mlt_service") == "composite") {
            transition.setAttribute("valign", "1");
            transition.setAttribute("halign", "1");
          }
            //transition.setAttribute("distort", "1");

          // Parse transition attributes
            typedef QMap<QString, QString> ParamMap;
            ParamMap params;
            params = (*itt)->transitionParameters();
            ParamMap::Iterator it;
            for ( it = params.begin(); it != params.end(); ++it ) {
                  transition.setAttribute(it.key(), it.data());
            }

          /* The crossfade LUMA transition does not work on images/texts with transp. 
             background, so we replace it with a composite transition */
          if (transparentBackgroundClip && type == Transition::LUMA_TRANSITION) {
            transition.setAttribute("mlt_service", "composite");
            QString geom;
            if (!(*itt)->invertTransition()) geom = "0=0,0:100%x100%:0;-1=0,0:100%x100%:100";
            else geom = "0=0,0:100%x100%:100;-1=0,0:100%x100%:0";
            transition.setAttribute("geometry", geom);
            transition.setAttribute("halign", 1);
            transition.setAttribute("valign", 1);
          }

          if (type == Transition::LUMA_TRANSITION || type == Transition::MIX_TRANSITION || type == Transition::LUMAFILE_TRANSITION) {
                transition.setAttribute("b_track", QString::number((*itt)->transitionStartTrack()));
                transition.setAttribute("a_track", QString::number((*itt)->transitionEndTrack()));
              if ((*itt)->invertTransition()) transition.setAttribute("reverse", "1");
          }
          else if ((*itt)->invertTransition()) {
                transition.setAttribute("a_track", QString::number((*itt)->transitionStartTrack()));
                transition.setAttribute("b_track", QString::number((*itt)->transitionEndTrack()));
            }
            else {
                transition.setAttribute("b_track", QString::number((*itt)->transitionStartTrack()));
                transition.setAttribute("a_track", QString::number((*itt)->transitionEndTrack()));
            }
            list.appendChild(transition);
      }
        ++itt;
    }
    return list;
}


QDomDocument DocClipRef::generateXMLClip(bool rendering)
{
    if (m_cropStart == m_trackEnd)
      return QDomDocument();

    QDomDocument sceneList;
 
    QDomElement entry;

     //if (m_speed == 1.0) 
    {
      entry = sceneList.createElement("entry");
      entry.setAttribute("producer", m_clip->getId());
    }

    if (m_clip->clipType() == DocClipBase::SLIDESHOW && m_clip->toDocClipAVFile()->hasCrossfade()) {
      QDomElement clipFilter =
      sceneList.createElement("filter");
        clipFilter.setAttribute("mlt_service", "luma");
      clipFilter.setAttribute("period", QString::number(m_clip->toDocClipAVFile()->clipTtl()));
      clipFilter.setAttribute("resource", m_clip->toDocClipAVFile()->lumaFile());
      clipFilter.setAttribute("luma.softness", QString::number(m_clip->toDocClipAVFile()->lumaSoftness()));
      //clipFilter.setAttribute("luma.out", QString::number(m_clip->toDocClipAVFile()->lumaDuration()));
      entry.appendChild(clipFilter);
    }

    // Check if clip is positionned under 0 in the timeline
       int checkStart = (int)(m_trackStart.frames(framesPerSecond()));
    if (checkStart < 0)
        entry.setAttribute("in", QString::number(m_cropStart.frames(framesPerSecond()) - checkStart));
    else 
        entry.setAttribute("in", QString::number(m_cropStart.frames(framesPerSecond())));
        entry.setAttribute("out", QString::number((m_cropStart + cropDuration()).frames(framesPerSecond()) - 1));
    
    // Generate XML for the clip's effects 
    // As a starting point, let's consider effects don't have more than one keyframable parameter.
    // All other parameters are supposed to be "constant", ie a value which can be adjusted by 
    // the user but remains the same during all the clip's duration.

    QDomElement monoFilter = sceneList.createElement("filter");
    monoFilter.setAttribute("mlt_service", "channelcopy");

    uint i = 0;
    if (hasEffect() && (KdenliveSettings::showeffects() || rendering))
      while (effectAt(i) != NULL) {
          Effect *effect = effectAt(i);
          
          if (effect->isEnabled()) {
          uint parameterNum = 0;
         // bool hasParameters = false;

          if (effect->effectDescription().tag() == "sox") {
            // THIS is a SOX FILTER, process 
                        QDomElement clipFilter = sceneList.createElement("filter");
                  clipFilter.setAttribute("mlt_service", "sox");
                  clipFilter.setAttribute("kdenlive_id", effect->effectDescription().stringId());
                  QStringList params;
                  params<<QString(effect->effectDescription().stringId()).remove("sox_");
                  while (effect->parameter(parameterNum)) {
                  if (effect->effectDescription().parameter(parameterNum)->type() == "constant") {
                        double effectParam;
                        if (effect->effectDescription().parameter(parameterNum)->factor() != 1.0)
                                    effectParam = effect->effectDescription().parameter(parameterNum)->value().toDouble() / effect->effectDescription().parameter(parameterNum)->factor();
                        else effectParam = effect->effectDescription().parameter(parameterNum)->value().toDouble();
                        params.append(QString::number(effectParam));
                      }
                      //params.append(effect->effectDescription().parameter(parameterNum)->value());
                      parameterNum++;
                  }
                  clipFilter.setAttribute("effect", params.join(" "));
                  entry.appendChild(clipFilter);
          }
          else if (effect->effectDescription().tag().startsWith("ladspa", false)) {
            // THIS is a LADSPA FILTER, process 
                        QDomElement clipFilter = sceneList.createElement("filter");
                  clipFilter.setAttribute("mlt_service", "ladspa");
                  clipFilter.setAttribute("kdenlive_id", effect->effectDescription().stringId());
                  QStringList params;


                  while (effect->parameter(parameterNum)) {
                      if (effect->effectDescription().parameter(parameterNum)->type() == "constant") {
                        double effectParam;
                        if (effect->effectDescription().parameter(parameterNum)->factor() != 1.0)
                                    effectParam = effect->effectDescription().parameter(parameterNum)->value().toDouble() / effect->effectDescription().parameter(parameterNum)->factor();
                        else effectParam = effect->effectDescription().parameter(parameterNum)->value().toDouble();
                        params.append(QString::number(effectParam));
                      }
                      else params.append(effect->effectDescription().parameter(parameterNum)->value());
                      parameterNum++;
                  }
                  int ladspaid = effect->effectDescription().tag().right(effect->effectDescription().tag().length() - 6).toInt();

                  QString effectFile = effect->tempFileName();
                  if (!effectFile.isEmpty()) {
                      initEffects::ladspaEffectFile( effectFile, ladspaid, params );
                      clipFilter.setAttribute("src", effectFile );
                  }
//                clipFilter.setAttribute("data", initEffects::ladspaEffectString(ladspaid, params ));
                  entry.appendChild(clipFilter);
                  if (effect->effectDescription().isMono()) {
                      // Audio Mono clip. Duplicate audio channel
                      entry.appendChild(monoFilter);
                  }

            // end of LADSPA FILTER

          }
          else while (effect->parameter(parameterNum)) {
            uint keyFrameNum = 0;

            if (effect->effectDescription().parameter(parameterNum)->type() == "complex") {
                // Effect has keyframes with several sub-parameters
                QString startTag, endTag;
                keyFrameNum =
                  effect->parameter(parameterNum)->numKeyFrames();
                startTag =
                  effect->effectDescription().
                  parameter(parameterNum)->startTag();
                endTag =
                  effect->effectDescription().
                  parameter(parameterNum)->endTag();

                if (keyFrameNum > 1) {
                  for (uint count = 0; count < keyFrameNum - 1;
                      count++) {
                      QDomElement transition =
                        sceneList.createElement("filter");
                      transition.setAttribute("mlt_service", effect->effectDescription().tag());
                      transition.setAttribute("kdenlive_id", effect->effectDescription().stringId());
                      uint in = (uint)(m_cropStart.frames(framesPerSecond()));
                      uint duration = (uint)(cropDuration().frames(framesPerSecond()));
                      transition.setAttribute("in",
                        QString::number(in +
                            (effect->parameter(parameterNum)->
                              keyframe(count)->time()) *
                            duration));
                      transition.setAttribute("out",
                        QString::number(in +
                            (effect->parameter(parameterNum)->
                              keyframe(count +
                                  1)->time()) * duration));

                      transition.setAttribute(startTag,
                        effect->parameter(parameterNum)->
                        keyframe(count)->toComplexKeyFrame()->
                        processComplexKeyFrame());

                      transition.setAttribute(endTag,
                        effect->parameter(parameterNum)->
                        keyframe(count +
                            1)->toComplexKeyFrame()->
                        processComplexKeyFrame());
                      entry.appendChild(transition);
                  }
                }
            }
            else if (effect->effectDescription().parameter(parameterNum)->type() == "double") {
                // Effect has one parameter with keyframes
                QString startTag, endTag;
                keyFrameNum =
                  effect->parameter(parameterNum)->numKeyFrames();
                startTag =
                  effect->effectDescription().
                  parameter(parameterNum)->startTag();
                endTag =
                  effect->effectDescription().
                  parameter(parameterNum)->endTag();

                double factor = effect->effectDescription().parameter(parameterNum)->factor();

                if (keyFrameNum > 1) {
                  QDomElement clipFilter;
                  for (uint count = 0; count < keyFrameNum - 1;
                      count++) {
                                clipFilter =
                        sceneList.createElement("filter");
                      clipFilter.setAttribute("mlt_service",
                        effect->effectDescription().tag());
                  clipFilter.setAttribute("kdenlive_id", effect->effectDescription().stringId());
                         uint in =(uint)
                        m_cropStart.frames(framesPerSecond());
                         uint duration =(uint)
                        cropDuration().frames(framesPerSecond());
                      clipFilter.setAttribute("in",
                        QString::number(in +
                            (effect->parameter(parameterNum)->
                              keyframe(count)->time()) *
                            duration));
                      clipFilter.setAttribute(startTag,
                        QString::number(effect->
                            parameter(parameterNum)->
                            keyframe(count)->toDoubleKeyFrame()->
                            value() / factor));
                      clipFilter.setAttribute("out",
                        QString::number(in +
                            (effect->parameter(parameterNum)->
                              keyframe(count +
                                  1)->time()) * duration));
                      clipFilter.setAttribute(endTag,
                        QString::number(effect->
                            parameter(parameterNum)->
                            keyframe(count +
                              1)->toDoubleKeyFrame()->value() / factor));
                      entry.appendChild(clipFilter);
                  }
                  // Add the other constant parameters if any
                  uint parameterNumBis = parameterNum + 1;
                  while (effect->parameter(parameterNumBis)) {
                      clipFilter.setAttribute(effect->effectDescription().parameter(parameterNumBis)->name(), QString::number( effect->effectDescription().parameter(parameterNumBis)->value().toDouble() / effect->effectDescription().parameter(parameterNumBis)->factor()));
                      parameterNumBis++;
                  }
                  parameterNum = parameterNumBis;
                }
                    }
                else {  // Effect has only constant parameters
                if (effect->effectDescription().tag() != "framebuffer") {
                    QDomElement clipFilter =
                  sceneList.createElement("filter");

                QString effecttag = effect->effectDescription().tag();
                QString effecttype = effect->effectDescription().parameter(parameterNum)->type();

                clipFilter.setAttribute("mlt_service", effecttag);
                clipFilter.setAttribute("kdenlive_id", effect->effectDescription().stringId());
                if (effecttype == "constant" || effecttype == "list" || effecttype == "bool" || effecttype == "color" || effecttype == "geometry")
                  while (effect->parameter(parameterNum)) {
                      if (effect->effectDescription().parameter(parameterNum)->factor() != 1.0)
                            clipFilter.setAttribute(effect->
                        effectDescription().
                        parameter(parameterNum)->name(), QString::number(
                        effect->
                            effectDescription().
                            parameter(parameterNum)->value().toDouble() / effect->
                            effectDescription().
                            parameter(parameterNum)->factor()));
                      else clipFilter.setAttribute(effect->
                        effectDescription().
                        parameter(parameterNum)->name(), effect->effectDescription().parameter(parameterNum)->value());
                      parameterNum++;
                  }
                        entry.appendChild(clipFilter);
                }
                else {  //slowmotion or freeze effect, use special producer

                  QDomElement slowProd;
                  slowProd = sceneList.createElement("producer");
                  QString filterId = "slowmotion"+ QString::number(m_clip->getId()) + QString::number(trackNum()) + QString::number(trackStart().frames(framesPerSecond()));
                  slowProd.setAttribute("id", filterId);
                  slowProd.setAttribute("mlt_service","framebuffer");

                        //entry.setTagName("producer");
                        //entry.setAttribute("mlt_service","framebuffer");
                        //entry.setAttribute("id","slowmotion"+ QString::number(m_clip->getId()));
                        QString fileName;
                        if (effect->effectDescription().name() == i18n("Speed")) {
                            double speed = effect->effectDescription().parameter(0)->value().toDouble() / effect->effectDescription().parameter(0)->factor();
                            // entry.setAttribute("in", QString::number(entry.attribute("in").toInt() / speed));
                            // entry.setAttribute("out", QString::number(entry.attribute("out").toInt() / speed));
                            fileName = fileURL().path() + ":" + QString::number(speed);
                        }
                        else fileName = fileURL().path() + ":1";
                        slowProd.setAttribute("resource", fileName.ascii());
                        entry.setAttribute("producer", filterId);
                        while (effect->parameter(parameterNum)) {
                              slowProd.setAttribute(effect->effectDescription().parameter(parameterNum)->name(), QString::number(effect->effectDescription().parameter(parameterNum)->value().toDouble() / effect->effectDescription().parameter(parameterNum)->factor()));
                              parameterNum++;
                        }
                        sceneList.appendChild(slowProd);
                }
            }
            parameterNum++;
          }
          }
          i++;
      }

    sceneList.appendChild(entry);
    //kdDebug()<<"-------------------\n"<<sceneList.toString()<<endl;
    return sceneList;
    //return m_clip->toDocClipAVFile()->sceneToXML(m_cropStart, m_cropStart+cropDuration());        
}


QDomDocument DocClipRef::generateOffsetXMLClip(GenTime start, GenTime end)
{
    if (m_cropStart == m_trackEnd || m_trackStart.frames(framesPerSecond())  == end.frames(framesPerSecond()) - 1)
      return QDomDocument();

    QDomDocument sceneList;
    QDomElement entry;

     //if (m_speed == 1.0) 
    {
      entry = sceneList.createElement("entry");
      entry.setAttribute("producer", m_clip->getId());
    }

    if (m_clip->clipType() == DocClipBase::SLIDESHOW && m_clip->toDocClipAVFile()->hasCrossfade()) {
      QDomElement clipFilter =
      sceneList.createElement("filter");
        clipFilter.setAttribute("mlt_service", "luma");
      clipFilter.setAttribute("period", QString::number(m_clip->toDocClipAVFile()->clipTtl()));
      clipFilter.setAttribute("resource", m_clip->toDocClipAVFile()->lumaFile());
      clipFilter.setAttribute("luma.softness", QString::number(m_clip->toDocClipAVFile()->lumaSoftness()));
      //clipFilter.setAttribute("luma.out", QString::number(m_clip->toDocClipAVFile()->lumaDuration()));
      entry.appendChild(clipFilter);
    }

    // Check if clip is starting before selected zone in the timeline
       int checkStart = (int)((m_trackStart - start).frames(framesPerSecond()));
    if (checkStart < 0)
        entry.setAttribute("in", QString::number(m_cropStart.frames(framesPerSecond()) - checkStart));
    else 
        entry.setAttribute("in", QString::number(m_cropStart.frames(framesPerSecond())));
      int checkEnd = (int)((m_trackEnd - end).frames(framesPerSecond()));
      if (checkEnd > 0)
          entry.setAttribute("out", QString::number((m_cropStart + cropDuration()).frames(framesPerSecond()) - 1 - checkEnd));
      else entry.setAttribute("out", QString::number((m_cropStart + cropDuration()).frames(framesPerSecond()) - 1));
    
    // Generate XML for the clip's effects 
    // As a starting point, let's consider effects don't have more than one keyframable parameter.
    // All other parameters are supposed to be "constant", ie a value which can be adjusted by 
    // the user but remains the same during all the clip's duration.

    QDomElement monoFilter = sceneList.createElement("filter");
    monoFilter.setAttribute("mlt_service", "channelcopy");

    uint i = 0;
    if (hasEffect())
      while (effectAt(i) != NULL) {
          Effect *effect = effectAt(i);
          if (effect->isEnabled()) {
          uint parameterNum = 0;
         // bool hasParameters = false;

          if (effect->effectDescription().tag().startsWith("ladspa", false)) {
            // THIS is a LADSPA FILTER, process 
                        QDomElement clipFilter = sceneList.createElement("filter");
                  clipFilter.setAttribute("mlt_service", "ladspa");
                  QStringList params;


                  while (effect->parameter(parameterNum)) {
                      if (effect->effectDescription().parameter(parameterNum)->type() == "constant") {
                        double effectParam;
                        if (effect->effectDescription().parameter(parameterNum)->factor() != 1.0)
                                    effectParam = effect->effectDescription().parameter(parameterNum)->value().toDouble() / effect->effectDescription().parameter(parameterNum)->factor();
                        else effectParam = effect->effectDescription().parameter(parameterNum)->value().toDouble();
                        params.append(QString::number(effectParam));
                      }
                      else params.append(effect->effectDescription().parameter(parameterNum)->value());
                      parameterNum++;
                  }
                  int ladspaid = effect->effectDescription().tag().right(effect->effectDescription().tag().length() - 6).toInt();

                  QString effectFile = effect->tempFileName();
                  if (!effectFile.isEmpty()) {
                      initEffects::ladspaEffectFile( effectFile, ladspaid, params );
                      clipFilter.setAttribute("src", effectFile );
                  }
//                clipFilter.setAttribute("data", initEffects::ladspaEffectString(ladspaid, params ));
                  entry.appendChild(clipFilter);
                  if (effect->effectDescription().isMono()) entry.appendChild(monoFilter);

            // end of LADSPA FILTER

          }
          else while (effect->parameter(parameterNum)) {
            uint keyFrameNum = 0;

            if (effect->effectDescription().parameter(parameterNum)->type() == "complex") {
                // Effect has keyframes with several sub-parameters
                QString startTag, endTag;
                keyFrameNum =
                  effect->parameter(parameterNum)->numKeyFrames();
                startTag =
                  effect->effectDescription().
                  parameter(parameterNum)->startTag();
                endTag =
                  effect->effectDescription().
                  parameter(parameterNum)->endTag();

                if (keyFrameNum > 1) {
                  for (uint count = 0; count < keyFrameNum - 1;
                      count++) {
                      QDomElement transition =
                        sceneList.createElement("filter");
                      transition.setAttribute("mlt_service",
                        effect->effectDescription().tag());
                      uint in =
                        (uint)(m_cropStart.frames(framesPerSecond()));
                      uint duration =
                        (uint)(cropDuration().frames(framesPerSecond()));
                      transition.setAttribute("in",
                        QString::number(in +
                            (effect->parameter(parameterNum)->
                              keyframe(count)->time()) *
                            duration));
                      transition.setAttribute("out",
                        QString::number(in +
                            (effect->parameter(parameterNum)->
                              keyframe(count +
                                  1)->time()) * duration));

                      transition.setAttribute(startTag,
                        effect->parameter(parameterNum)->
                        keyframe(count)->toComplexKeyFrame()->
                        processComplexKeyFrame());

                      transition.setAttribute(endTag,
                        effect->parameter(parameterNum)->
                        keyframe(count +
                            1)->toComplexKeyFrame()->
                        processComplexKeyFrame());
                      entry.appendChild(transition);
                  }
                }
            }

            else if (effect->effectDescription().
                parameter(parameterNum)->type() == "double") {
                // Effect has one parameter with keyframes
                QString startTag, endTag;
                keyFrameNum =
                  effect->parameter(parameterNum)->numKeyFrames();
                startTag =
                  effect->effectDescription().
                  parameter(parameterNum)->startTag();
                endTag =
                  effect->effectDescription().
                  parameter(parameterNum)->endTag();

                double factor = effect->effectDescription().parameter(parameterNum)->factor();

                if (keyFrameNum > 1) {
                  for (uint count = 0; count < keyFrameNum - 1;
                      count++) {
                                QDomElement clipFilter =
                        sceneList.createElement("filter");
                      clipFilter.setAttribute("mlt_service",
                        effect->effectDescription().tag());
                         uint in =(uint)
                        m_cropStart.frames(framesPerSecond());
                         uint duration =(uint)
                        cropDuration().frames(framesPerSecond());
                      clipFilter.setAttribute("in",
                        QString::number(in +
                            (effect->parameter(parameterNum)->
                              keyframe(count)->time()) *
                            duration));
                      clipFilter.setAttribute(startTag,
                        QString::number(effect->
                            parameter(parameterNum)->
                            keyframe(count)->toDoubleKeyFrame()->
                            value() / factor));
                      clipFilter.setAttribute("out",
                        QString::number(in +
                            (effect->parameter(parameterNum)->
                              keyframe(count +
                                  1)->time()) * duration));
                      clipFilter.setAttribute(endTag,
                        QString::number(effect->
                            parameter(parameterNum)->
                            keyframe(count +
                              1)->toDoubleKeyFrame()->value() / factor));

                      // Add the other constant parameters if any
                      /*uint parameterNumBis = parameterNum;
                         while (effect->parameter(parameterNumBis)) {
                         transition.setAttribute(effect->effectDescription().parameter(parameterNumBis)->name(),QString::number(effect->effectDescription().parameter(parameterNumBis)->value()));
                         parameterNumBis++;
                         } */
                      entry.appendChild(clipFilter);
                  }
                }
                    }
                else {  // Effect has only constant parameters
                if (effect->effectDescription().tag() != "framebuffer") {
                    QDomElement clipFilter =
                  sceneList.createElement("filter");

                QString effecttag = effect->effectDescription().tag();
                QString effecttype = effect->effectDescription().parameter(parameterNum)->type();
                clipFilter.setAttribute("mlt_service", effecttag);

                if (effecttype == "constant" || effecttype == "list" || effecttype == "bool" || effecttype == "color" || effecttype == "geometry")
                  while (effect->parameter(parameterNum)) {
                      if (effect->effectDescription().parameter(parameterNum)->factor() != 1.0)
                            clipFilter.setAttribute(effect->
                        effectDescription().
                        parameter(parameterNum)->name(), QString::number(
                        effect->
                            effectDescription().
                            parameter(parameterNum)->value().toDouble() / effect->
                            effectDescription().
                            parameter(parameterNum)->factor()));
                      else clipFilter.setAttribute(effect->
                        effectDescription().
                        parameter(parameterNum)->name(), effect->effectDescription().parameter(parameterNum)->value());
                      parameterNum++;
                  }
                        entry.appendChild(clipFilter);
                }
                else {  //slowmotion or freeze effect, use special producer
                        entry.setTagName("producer");
                        entry.setAttribute("mlt_service","framebuffer");
                        entry.setAttribute("id","slowmotion"+ QString::number(m_clip->getId()));
                        QString fileName;
                        if (effect->effectDescription().name() == i18n("Speed")) {
                            double speed = effect->effectDescription().parameter(0)->value().toDouble() / effect->effectDescription().parameter(0)->factor();
                            // entry.setAttribute("in", QString::number(entry.attribute("in").toInt() / speed));
                            // entry.setAttribute("out", QString::number(entry.attribute("out").toInt() / speed));
                            fileName = fileURL().path() + ":" + QString::number(speed);
                        }
                        else fileName = fileURL().path() + ":1";
                        entry.setAttribute("resource", fileName.ascii());
                        entry.removeAttribute("producer");
                        while (effect->parameter(parameterNum)) {
                              entry.setAttribute(effect->effectDescription().parameter(parameterNum)->name(), QString::number(effect->effectDescription().parameter(parameterNum)->value().toDouble() / effect->effectDescription().parameter(parameterNum)->factor()));
                              parameterNum++;
                        }
                }
            }
            parameterNum++;
          }
          }
          i++;
      }

    sceneList.appendChild(entry);
    return sceneList;
    //return m_clip->toDocClipAVFile()->sceneToXML(m_cropStart, m_cropStart+cropDuration());        
}


const KURL & DocClipRef::fileURL() const
{
    return m_clip->fileURL();
}

uint DocClipRef::fileSize() const
{
    return m_clip->fileSize();
}

QString DocClipRef::formattedFileSize() const
{

      uint fileSize = m_clip->fileSize();
        long tenth;
        QString text;
        if (fileSize < 1024) {
            text = QString::number(fileSize) + i18n(" byte(s)");
        } else {
            fileSize = (int) floor((fileSize / 1024.0) + 0.5);

            if (fileSize < 1024) {
                text = QString::number(fileSize) + i18n(" Kb");
            } else {
                fileSize = (int) floor((fileSize / 102.4) + 0.5);
            if (fileSize < 1024) {
                    tenth = fileSize % 10;
                    fileSize /= 10;
                    text = QString::number(fileSize) + "." + QString::number(tenth) + i18n(" Mb");
            }
            else {
                fileSize = (int) floor((fileSize / 1024.0) + 0.5);
                    tenth = fileSize % 10;
                    fileSize /= 10;
                    text = QString::number(fileSize) + "." + QString::number(tenth) + i18n(" Gb");
            }
            }
        }
        return text;
}

void DocClipRef::populateSceneTimes(QValueVector < GenTime > &toPopulate)
{
    QValueVector < GenTime > sceneTimes;

    m_clip->populateSceneTimes(sceneTimes);

    QValueVector < GenTime >::iterator itt = sceneTimes.begin();
    while (itt != sceneTimes.end()) {
      GenTime convertedTime = (*itt) - cropStartTime();
      if ((convertedTime >= GenTime(0))
          && (convertedTime <= cropDuration())) {
          convertedTime += trackStart();
          toPopulate.append(convertedTime);
      }

      ++itt;
    }

    toPopulate.append(trackStart());
    toPopulate.append(trackEnd());
}

QDomDocument DocClipRef::sceneToXML(const GenTime & startTime,
    const GenTime & endTime)
{
    QDomDocument sceneDoc;

    if (m_effectStack.isEmpty()) {
      sceneDoc =
          m_clip->sceneToXML(startTime - trackStart() + cropStartTime(),
          endTime - trackStart() + cropStartTime());
    } else {
      // We traverse the effect stack forwards; this let's us add the video clip at the top of the effect stack.
      QDomNode constructedNode =
          sceneDoc.importNode(m_clip->sceneToXML(startTime -
            trackStart() + cropStartTime(),
            endTime - trackStart() +
            cropStartTime()).documentElement(), true);
      EffectStackIterator itt(m_effectStack);

      while (itt.current()) {
          QDomElement parElement = sceneDoc.createElement("par");
          parElement.appendChild(constructedNode);

          QDomElement effectElement =
            sceneDoc.createElement("videoeffect");
          effectElement.setAttribute("name",
            (*itt)->effectDescription().name());
          effectElement.setAttribute("begin", QString::number(0, 'f',
                10));
          effectElement.setAttribute("dur",
            QString::number((endTime - startTime).seconds(), 'f', 10));
          parElement.appendChild(effectElement);

          constructedNode = parElement;
          ++itt;
      }
      sceneDoc.appendChild(constructedNode);
    }

    return sceneDoc;
}

void DocClipRef::setSnapMarkers(QValueVector < CommentedTime > markers)
{
    m_clip->setSnapMarkers( markers );
    /*qHeapSort(m_snapMarkers);

    QValueVector < CommentedTime >::Iterator itt = markers.begin();
       while(itt != markers.end()) {
       addSnapMarker((*itt).time(), (*itt).comment(), false);
       ++itt;
       }*/
}

GenTime DocClipRef::adjustTimeToSpeed(GenTime t) const
{
      if (m_speed == 1.0) return t;
      int pos = (int) (t - m_cropStart).frames(m_clip->framesPerSecond());
      double actual_speed = m_speed + ((double) pos) / (double)((m_trackEnd - m_trackStart).frames(m_clip->framesPerSecond())) * (m_speed);

      int actual_position = (int) floor((double) pos / actual_speed);
      return GenTime(actual_position, m_clip->framesPerSecond()) + cropStartTime();

      // TODO: markers not adjusted when clip is played reverse
}

QValueVector < GenTime > DocClipRef::snapMarkersOnTrack() const
{
    QValueVector < GenTime > markers;
    QValueVector < CommentedTime > originalMarkers = commentedSnapMarkers();
    markers.reserve(originalMarkers.count());

    for (uint count = 0; count < originalMarkers.count(); ++count) {
      GenTime t = originalMarkers[count].time();
      if (t > m_cropStart && t < m_trackEnd - m_trackStart + m_cropStart) {
          t = adjustTimeToSpeed(t);
          if (t < cropStartTime() + cropDuration() && t > cropStartTime()) markers.append(t + trackStart() - cropStartTime());
      }
    }

    return markers;
}

void DocClipRef::addSnapMarker(const GenTime & time, QString comment, bool notify)
{
    m_clip->addSnapMarker(time, comment);
    //if (notify) m_parentTrack->notifyClipChanged(this);
}

void DocClipRef::editSnapMarker(const GenTime & time, QString comment)
{
    m_clip->editSnapMarker(time, comment);
}

QValueVector < GenTime > DocClipRef::transitionSnaps()
{
    QValueVector < GenTime > tranList;
    TransitionStack::iterator itt = m_transitionStack.begin();
    while (itt) {
        tranList.append((*itt)->transitionStartTime());
      tranList.append((*itt)->transitionEndTime());
        ++itt;
    }
    return tranList;
}

void DocClipRef::deleteSnapMarker(const GenTime & time)
{
    if (!m_clip->deleteSnapMarker(time)) //m_parentTrack->notifyClipChanged(this);
    kdError() << "Could not delete marker at time " << time.seconds() << " - it doesn't exist!" << endl;
}

GenTime DocClipRef::hasSnapMarker(const GenTime & time)
{
    return m_clip->hasSnapMarkers(time);
}

void DocClipRef::setCropDuration(const GenTime & time)
{
    setTrackEnd(trackStart() + time);
}

GenTime DocClipRef::trackMiddleTime() const
{
    return (m_trackStart + m_trackEnd) / 2;
}

QValueVector < GenTime > DocClipRef::snapMarkers() const
{
    return m_clip->snapMarkers();
}

QString DocClipRef::markerComment(GenTime t) const
{
    return m_clip->markerComment(t);
}

QValueVector < CommentedTime > DocClipRef::commentedSnapMarkers() const
{
    return m_clip->commentedSnapMarkers();
}

QValueVector < CommentedTime > DocClipRef::commentedTrackSnapMarkers() const
{
    QValueVector < CommentedTime > markers;
    QValueVector < CommentedTime > originalMarkers = commentedSnapMarkers();
    markers.reserve(originalMarkers.count());

    for (uint count = 0; count < originalMarkers.count(); ++count) {
      GenTime t = originalMarkers[count].time();
      if (t > m_cropStart && t < m_trackEnd - m_trackStart + m_cropStart) {
          t = adjustTimeToSpeed(t);
          if (t < cropStartTime() + cropDuration() && t > cropStartTime())
          markers.append(CommentedTime(t + trackStart() - cropStartTime(), originalMarkers[count].comment()));
      }
    }

    return markers;
}

void DocClipRef::addEffect(uint index, Effect * effect)
{
    m_effectStack.insert(index, effect);
}

void DocClipRef::deleteEffect(uint index)
{
    m_effectStack.remove(index);
    if (m_speed != 1.0) {
      // Check if speed effect was removed. if it was, reset speed to normal
      if (clipEffectNames().findIndex(i18n("Speed")) == -1) {
          setSpeed(1.0);
      }
    }
}


void DocClipRef::setEffectStackSelectedItem(uint ix)
{
    m_effectStack.setSelected(ix);
}

Effect *DocClipRef::selectedEffect()
{
    Effect *eff = m_effectStack.selectedItem();
    if (eff) return eff;
    return m_effectStack.at(0);
}

bool DocClipRef::hasEffect() const
{
    if (m_effectStack.count() > 0)
      return true;
    return false;
}

void DocClipRef::clearVideoEffects()
{
      for (uint count = 0; count < m_effectStack.count(); ++count)
      {
          if (m_effectStack.at(count)->effectDescription().type() == VIDEOEFFECT) {
                m_effectStack.remove(count);
                count--;
          }
      }
}

void DocClipRef::renameEffectGroup(QString oldName, QString newName)
{
      for (uint count = 0; count < m_effectStack.count(); ++count)
      {
          if (m_effectStack.at(count)->group() == oldName) {
                m_effectStack.at(count)->setGroup(newName);
          }
      }
}

Effect *DocClipRef::effectAt(uint index) const
{
    EffectStack::iterator itt = m_effectStack.begin();

    if (index < m_effectStack.count()) {
      for (uint count = 0; count < index; ++count)
          ++itt;
      return *itt;
    }
    //kdError() << "DocClipRef::effectAt() : index out of range" << endl;
    return 0;
}

bool DocClipRef::hasEffect(QString effectTag) const
{
    EffectStack::iterator itt = m_effectStack.begin();

    while (itt != m_effectStack.end()) {
      if ((*itt)->effectDescription().tag() == effectTag && (*itt)->isEnabled());
      return true;
      ++itt;
    }
    return false;
}

void DocClipRef::setEffectStack(const EffectStack & effectStack)
{
    m_effectStack = effectStack;
}

const QPixmap & DocClipRef::getAudioImage(int /*width*/, int /*height*/,
      double /*frame*/, double /*numFrames*/, int /*channel*/)
{
    static QPixmap nullPixmap;

    return nullPixmap;
}

int DocClipRef::addTransition(Transition *transition)
{
    m_transitionStack.append(transition);
    if (m_parentTrack) m_parentTrack->notifyClipChanged(this);
    return m_transitionStack.count() - 1;
}

void DocClipRef::deleteTransition(QDomElement transitionXml)
{
    if (m_transitionStack.isEmpty()) return;
    for ( uint i = 0; i < m_transitionStack.count(); ++i ) {
      Transition *t = m_transitionStack.at(i);
        if ( t && t->toXML().attribute("start") == transitionXml.attribute("start") && t->toXML().attribute("end") == transitionXml.attribute("end")) {
          m_transitionStack.remove(i);
      }
    }

    if (m_parentTrack) m_parentTrack->notifyClipChanged(this);
}


void DocClipRef::deleteTransition(int ix)
{
    if (m_transitionStack.isEmpty() || ix > m_transitionStack.count() - 1) return;
    m_transitionStack.remove(ix);
    if (m_parentTrack) m_parentTrack->notifyClipChanged(this);
}

Transition *DocClipRef::transitionAt(const GenTime &time)
{
    TransitionStack::iterator itt = m_transitionStack.begin();
    while (itt) {
        if ((*itt)->transitionStartTime()<time && (*itt)->transitionEndTime()>time) {
            return (*itt);
          }
        ++itt;
    }
    return 0;
}

int DocClipRef::transitionIndex(Transition *trans)
{
    TransitionStack::iterator itt = m_transitionStack.begin();
    int count = 0;
    while (itt) {
        if ((*itt) == trans) break;
        ++itt;
      count ++;
    }
    return count;
}

Transition *DocClipRef::transitionAt(int ix)
{
    if (m_transitionStack.isEmpty() || ix > m_transitionStack.count() - 1) return NULL;
    return m_transitionStack.at(ix);
}

QDomElement DocClipRef::transitionAtIndex(int ix)
{
    if (m_transitionStack.isEmpty() || ix > m_transitionStack.count() - 1) return QDomElement();
    return m_transitionStack.at(ix)->toXML();
}

void DocClipRef::deleteTransitions()
{
    m_transitionStack.clear();
    if (m_parentTrack) m_parentTrack->notifyClipChanged(this);
}

bool DocClipRef::hasTransition(DocClipRef *clip)
{
    TransitionStack::iterator itt = m_transitionStack.begin();
    while (itt) {
        if ((*itt)->hasClip(clip)) {
            return true;
        }
        ++itt;
    }
    return false;
}


TransitionStack DocClipRef::clipTransitions()
{
    return m_transitionStack;
}

void DocClipRef::resizeTransitionStart(uint ix, GenTime time)
{
    m_transitionStack.at(ix)->resizeTransitionStart(time);
    if (m_parentTrack) m_parentTrack->notifyClipChanged(this);
}

void DocClipRef::resizeTransitionEnd(uint ix, GenTime time)
{
    m_transitionStack.at(ix)->resizeTransitionEnd(time);
    if (m_parentTrack) m_parentTrack->notifyClipChanged(this);
}

void DocClipRef::moveTransition(uint ix, GenTime time)
{
    m_transitionStack.at(ix)->moveTransition(time);
    if (m_parentTrack) m_parentTrack->notifyClipChanged(this);
}

int DocClipRef::getAudioPart(double from, double length,int channel){
      int ret=0;
      QMap<int,QMap<int,QByteArray> >::Iterator it;
      /** we can have frame fro 7.2 to 10.4
            so we need max(max (7.2-7.99999),
            max(8-10),
            max(10.000-10.2000)
            )
      */
      /** max from first framepart*/
      size_t startpart=(size_t)(from*(double)AUDIO_FRAME_WIDTH)%AUDIO_FRAME_WIDTH;
      size_t endpart=(size_t)((from+length)*(double)AUDIO_FRAME_WIDTH)%AUDIO_FRAME_WIDTH;
      for (int i=(int)from;i<(int)from+1;i++){
            it=referencedClip()->audioFrameChache.find(i);
            if (it!=referencedClip()->audioFrameChache.end()){
                  QMap<int,QByteArray>::iterator it_channel;
                  it_channel=(*it).find(channel);
                  if (it_channel!=(*it).end()){
                        QByteArray arr=*it_channel;
                        size_t end=endpart;
                        if (length>=1.0)
                              end=AUDIO_FRAME_WIDTH-1;
                        for (size_t j=startpart;j<=end;j++){
                              ret=QMAX(arr[j],ret);
                        }
                  }
            }
      }

      /** max from full frames between */
      for (int i=(int)from+1;i<from+length /*&& i<(int)from +2*/;i++){
            /*m_thumbcreator->getAudioThumbs(fileURL(),channel,i,
            200.0,10,referencedClip()->audioFrameChache);*/
            it=referencedClip()->audioFrameChache.find(i);
            
            
            if (it!=referencedClip()->audioFrameChache.end()){
                  QMap<int,QByteArray>::iterator it_channel;
                  it_channel=(*it).find(channel);
                  if (it_channel!=(*it).end()){
                        QByteArray arr=*it_channel;
                        for (int j=0;j<AUDIO_FRAME_WIDTH;j++){
                              ret=QMAX(arr[j],ret);
                        }
                  }
            }
      }
      /** max from last frame part */
      ///TODO
      
      return ret;

      
}

QByteArray DocClipRef::getAudioThumbs(int channel, double frame, double frameLength, int arrayWidth){
      
      /** Merge alle Frames into scaled frames*/
      if (frame<0.0)
            frame=0.0;
      QByteArray ret(arrayWidth);
      if (!m_clip->audioThumbCreated) ret.fill(00);
      else for ( int i=0;i< arrayWidth;i++){
            double step=(double)frameLength/(double)arrayWidth;
            double startpos=frame+(double)i*step;
            ret[i]=getAudioPart(startpos,step,channel);
      }
      return ret;

      
}

Generated by  Doxygen 1.6.0   Back to index