--- /dev/null
+project(kdenlive)
+
+
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules )
+
+# search packages used by KDE
+find_package(KDE4 REQUIRED)
+include (KDE4Defaults)
+include (MacroLibrary)
+include(MacroOptionalAddSubdirectory)
+
+add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
+include_directories (${QDBUS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES} ${CMAKE_SOURCE_DIR}/widgets)
+
+FIND_PACKAGE(LIBMLT REQUIRED)
+FIND_PACKAGE(LIBMLTPLUS REQUIRED)
+FIND_PACKAGE(LIBFFMPEG REQUIRED)
+
+add_subdirectory(src)
+
\ No newline at end of file
--- /dev/null
+
+add_subdirectory( widgets )
+
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/src/widgets
+ ${LIBMLT_INCLUDE_DIR}
+ ${LIBMLTPLUS_INCLUDE_DIR}
+ ${LIBFFMPEG_INCLUDE_DIR}
+)
+
+LINK_DIRECTORIES(
+${LIBMLT_LIBRARY}
+${LIBMLTPLUS_LIBRARY}
+${LIBFFMPEG_LIBRARY}
+)
+
+
+kde4_add_ui_files(kdenlive_UI
+ widgets/timeline_ui.ui
+ widgets/projectlist_ui.ui
+ widgets/monitor_ui.ui
+)
+
+set(kdenlive_SRCS
+ main.cpp
+ mainwindow.cpp
+ customruler.cpp
+ projectlist.cpp
+ projectitem.cpp
+ monitor.cpp
+ gentime.cpp
+ renderer.cpp
+ kdenlivedoc.cpp
+ trackview.cpp
+ docclipbase.cpp
+ timecode.cpp
+)
+
+kde4_add_executable(kdenlive ${kdenlive_SRCS} ${kdenlive_UI})
+
+target_link_libraries(kdenlive
+ ${KDE4_KDEUI_LIBS}
+ ${KDE4_KIO_LIBS}
+ ${LIBMLTPLUS_LIBRARY}
+ ${LIBMLT_LIBRARY}
+)
+
+install(TARGETS kdenlive DESTINATION ${BIN_INSTALL_DIR})
+install( FILES kdenliveui.rc
+ DESTINATION ${DATA_INSTALL_DIR}/kdenlive )
\ No newline at end of file
--- /dev/null
+
+#include <QMouseEvent>
+#include <QStylePainter>
+
+#include <KDebug>
+
+
+#include "customruler.h"
+
+
+#define INIT_VALUE 0
+#define INIT_MIN_VALUE 0
+#define INIT_MAX_VALUE 100
+#define INIT_TINY_MARK_DISTANCE 1
+#define INIT_LITTLE_MARK_DISTANCE 5
+#define INIT_MIDDLE_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 2)
+#define INIT_BIG_MARK_DISTANCE (INIT_LITTLE_MARK_DISTANCE * 10)
+#define INIT_SHOW_TINY_MARK false
+#define INIT_SHOW_LITTLE_MARK true
+#define INIT_SHOW_MEDIUM_MARK true
+#define INIT_SHOW_BIG_MARK true
+#define INIT_SHOW_END_MARK true
+#define INIT_SHOW_POINTER true
+#define INIT_SHOW_END_LABEL true
+
+#define INIT_PIXEL_PER_MARK (double)10.0 /* distance between 2 base marks in pixel */
+#define INIT_OFFSET (-20)
+#define INIT_LENGTH_FIX true
+#define INIT_END_OFFSET 0
+
+#define FIX_WIDTH 20 /* widget width in pixel */
+#define LINE_END (FIX_WIDTH - 3)
+#define END_MARK_LENGTH (FIX_WIDTH - 6)
+#define END_MARK_X2 LINE_END
+#define END_MARK_X1 (END_MARK_X2 - END_MARK_LENGTH)
+#define BIG_MARK_LENGTH (END_MARK_LENGTH*3/4)
+#define BIG_MARK_X2 LINE_END
+#define BIG_MARK_X1 (BIG_MARK_X2 - BIG_MARK_LENGTH)
+#define MIDDLE_MARK_LENGTH (END_MARK_LENGTH/2)
+#define MIDDLE_MARK_X2 LINE_END
+#define MIDDLE_MARK_X1 (MIDDLE_MARK_X2 - MIDDLE_MARK_LENGTH)
+#define LITTLE_MARK_LENGTH (MIDDLE_MARK_LENGTH/2)
+#define LITTLE_MARK_X2 LINE_END
+#define LITTLE_MARK_X1 (LITTLE_MARK_X2 - LITTLE_MARK_LENGTH)
+#define BASE_MARK_LENGTH (LITTLE_MARK_LENGTH/2)
+#define BASE_MARK_X2 LINE_END
+#define BASE_MARK_X1 (BASE_MARK_X2 - 3) //BASE_MARK_LENGTH
+
+#define LABEL_SIZE 8
+#define END_LABEL_X 4
+#define END_LABEL_Y (END_LABEL_X + LABEL_SIZE - 2)
+
+#define FRAME_SIZE 90
+
+
+const int CustomRuler::comboScale[] =
+ { 1, 2, 5, 10, 25, 50, 125, 250, 500, 725, 1500, 3000, 6000,
+ 12000 };
+
+CustomRuler::CustomRuler(QWidget *parent)
+ : KRuler(parent)
+{
+ slotNewOffset(0);
+ setRulerMetricStyle(KRuler::Pixel);
+ setLength(1024);
+ setMaximum(1024);
+ setPixelPerMark(3);
+ setLittleMarkDistance (FRAME_SIZE);
+ setMediumMarkDistance (FRAME_SIZE * 25);
+ setBigMarkDistance (FRAME_SIZE * 25 * 60);
+}
+
+// virtual
+void CustomRuler::mousePressEvent ( QMouseEvent * event )
+{
+ int pos = event->x();
+ slotNewValue( pos );
+ kDebug()<<pos;
+}
+
+void CustomRuler::slotNewValue ( int _value )
+{
+ m_cursorPosition = _value / pixelPerMark();
+ KRuler::slotNewValue(_value);
+}
+
+void CustomRuler::setPixelPerMark (double rate)
+{
+ int scale = comboScale[(int) rate];
+ int newPos = m_cursorPosition * (1.0 / scale);
+ KRuler::setPixelPerMark(1.0 / scale);
+ KRuler::slotNewValue( newPos );
+}
+
+// virtual
+void CustomRuler::paintEvent(QPaintEvent * /*e*/)
+ {
+ // debug ("KRuler::drawContents, %s",(horizontal==dir)?"horizontal":"vertical");
+
+ QStylePainter p(this);
+
+
+ int value = this->value(),
+ minval = minimum(),
+ maxval;
+ maxval = maximum()
+ + offset() - endOffset();
+
+ //ioffsetval = value-offset;
+ // pixelpm = (int)ppm;
+ // left = clip.left(),
+ // right = clip.right();
+ double f, fend,
+ offsetmin=(double)(minval-offset()),
+ offsetmax=(double)(maxval-offset()),
+ fontOffset = (((double)minval)>offsetmin)?(double)minval:offsetmin;
+
+ // draw labels
+ QFont font = p.font();
+ font.setPointSize(LABEL_SIZE);
+ p.setFont( font );
+ // draw littlemarklabel
+
+ // draw mediummarklabel
+
+ // draw bigmarklabel
+
+ // draw endlabel
+ /*if (d->showEndL) {
+ if (d->dir == Qt::Horizontal) {
+ p.translate( fontOffset, 0 );
+ p.drawText( END_LABEL_X, END_LABEL_Y, d->endlabel );
+ }*/
+
+ // draw the tiny marks
+ //if (showTinyMarks())
+ /*{
+ fend = pixelPerMark()*tinyMarkDistance();
+ if (fend > 5) for ( f=offsetmin; f<offsetmax; f+=fend ) {
+ p.drawLine((int)f, BASE_MARK_X1, (int)f, BASE_MARK_X2);
+ }
+ }*/
+ if (showLittleMarks()) {
+ // draw the little marks
+ fend = pixelPerMark()*littleMarkDistance();
+ if (fend > 5) for ( f=offsetmin; f<offsetmax; f+=fend ) {
+ p.drawLine((int)f, LITTLE_MARK_X1, (int)f, LITTLE_MARK_X2);
+ if (fend > 30) p.drawText( (int)f + 2, LABEL_SIZE, QString::number((f - offsetmin) / pixelPerMark() / FRAME_SIZE) );
+ }
+ }
+ if (showMediumMarks()) {
+ // draw medium marks
+ fend = pixelPerMark()*mediumMarkDistance();
+ if (fend > 5) for ( f=offsetmin; f<offsetmax; f+=fend ) {
+ p.drawLine((int)f, MIDDLE_MARK_X1, (int)f, MIDDLE_MARK_X2);
+ if (fend > 30) p.drawText( (int)f + 2, LABEL_SIZE, QString::number((f - offsetmin) / pixelPerMark() / FRAME_SIZE) );
+ }
+ }
+ if (showBigMarks()) {
+ // draw big marks
+ fend = pixelPerMark()*bigMarkDistance();
+ if (fend > 5) for ( f=offsetmin; f<offsetmax; f+=fend ) {
+ p.drawLine((int)f, BIG_MARK_X1, (int)f, BIG_MARK_X2);
+ if (fend > 30) p.drawText( (int)f + 2, LABEL_SIZE, QString::number((f - offsetmin) / pixelPerMark() / FRAME_SIZE) );
+ }
+ }
+/* if (d->showem) {
+ // draw end marks
+ if (d->dir == Qt::Horizontal) {
+ p.drawLine(minval-d->offset, END_MARK_X1, minval-d->offset, END_MARK_X2);
+ p.drawLine(maxval-d->offset, END_MARK_X1, maxval-d->offset, END_MARK_X2);
+ }
+ else {
+ p.drawLine(END_MARK_X1, minval-d->offset, END_MARK_X2, minval-d->offset);
+ p.drawLine(END_MARK_X1, maxval-d->offset, END_MARK_X2, maxval-d->offset);
+ }
+ }*/
+
+ // draw pointer
+ if (showPointer()) {
+ QPolygon pa(4);
+ pa.setPoints(3, value-6, 9, value+6, 9, value/*+0*/, 16);
+ p.setBrush( QBrush(Qt::yellow) );
+ p.drawPolygon( pa );
+ }
+
+ }
+
+#include "customruler.moc"
--- /dev/null
+#ifndef CUSTOMRULER_H
+#define CUSTOMRULER_H
+
+#include <KRuler>
+
+class CustomRuler : public KRuler
+{
+ Q_OBJECT
+
+ public:
+ CustomRuler(QWidget *parent=0);
+ virtual void mousePressEvent ( QMouseEvent * event );
+ void setPixelPerMark (double rate);
+ static const int comboScale[];
+ protected:
+ virtual void paintEvent(QPaintEvent * /*e*/);
+
+ private:
+ int m_cursorPosition;
+
+ public slots:
+ void slotNewValue ( int _value );
+};
+
+#endif
--- /dev/null
+/**************************1*************************************************
+ DocClipBase.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 <KDebug>
+
+#include "docclipbase.h"
+/*#include "docclipavfile.h"
+#include "doccliptextfile.h"
+#include "docclipproject.h"
+#include "doctrackbase.h"*/
+
+DocClipBase::DocClipBase():
+m_description(""), m_refcount(0), m_projectThumbFrame(0), audioThumbCreated(false)
+{
+ //thumbCreator = 0;
+}
+
+DocClipBase::~DocClipBase()
+{
+ //delete thumbCreator;
+}
+
+void DocClipBase::setName(const QString name)
+{
+ m_name = name;
+}
+
+const QString & DocClipBase::name() const
+{
+ return m_name;
+}
+
+uint DocClipBase::getId() const
+{
+ return m_id;
+}
+
+void DocClipBase::setId( const uint &newId)
+{
+ m_id = newId;
+}
+
+void DocClipBase::setProjectThumbFrame( const uint &ix)
+{
+ m_projectThumbFrame = ix;
+}
+
+uint DocClipBase::getProjectThumbFrame() const
+{
+ return m_projectThumbFrame;
+}
+
+void DocClipBase::setDescription(const QString & description)
+{
+ m_description = description;
+}
+
+const QString & DocClipBase::description() const
+{
+ return m_description;
+}
+
+// virtual
+QDomDocument DocClipBase::toXML() const
+{
+ QDomDocument doc;
+
+ QDomElement clip = doc.createElement("kdenliveclip");
+ QDomText text = doc.createTextNode(description());
+ clip.appendChild(text);
+ doc.appendChild(clip);
+
+ return doc;
+}
+
+DocClipBase *DocClipBase::
+createClip(KdenliveDoc *doc, const QDomElement & element)
+{
+ DocClipBase *clip = 0;
+ QString description;
+ QDomNode node = element;
+ node.normalize();
+ if (element.tagName() != "kdenliveclip") {
+ kWarning() <<
+ "DocClipBase::createClip() element has unknown tagName : " <<
+ element.tagName() << endl;
+ return 0;
+ }
+
+ QDomNode n = element.firstChild();
+
+ while (!n.isNull()) {
+ QDomElement e = n.toElement();
+ if (!e.isNull()) {
+ QString tagName = e.tagName();
+ if (e.tagName() == "avfile") {
+ // clip = DocClipAVFile::createClip(e);
+ } else if (e.tagName() == "DocTrackBaseList") {
+ // clip = DocClipProject::createClip(doc, e);
+ }
+ } else {
+ QDomText text = n.toText();
+ if (!text.isNull()) {
+ description = text.nodeValue();
+ }
+ }
+
+ n = n.nextSibling();
+ }
+ if (clip == 0) {
+ kWarning() << "DocClipBase::createClip() unable to create clip" <<
+ endl;
+ } else {
+ // setup DocClipBase specifics of the clip.
+ clip->setDescription(description);
+ clip->setAudioThumbCreated(false);
+ }
+ return clip;
+}
+
+void DocClipBase::setAudioThumbCreated(bool isDone)
+{
+ audioThumbCreated = isDone;
+}
+
+
+QDomDocument DocClipBase::generateSceneList(bool, bool) const
+{
+}
+
+void DocClipBase::setThumbnail(const QPixmap & pixmap)
+{
+ m_thumbnail = pixmap;
+}
+
+const QPixmap & DocClipBase::thumbnail() const
+{
+ return m_thumbnail;
+}
+
+void DocClipBase::updateAudioThumbnail(QMap<int,QMap<int,QByteArray> > data)
+{
+ audioFrameChache = data;
+ audioThumbCreated = true;
+}
+
+QList < GenTime > DocClipBase::snapMarkers() const
+{
+ QList < GenTime > markers;
+
+ for (uint count = 0; count < m_snapMarkers.count(); ++count) {
+ markers.append(m_snapMarkers[count].time());
+ }
+
+ return markers;
+}
+
+QList < CommentedTime > DocClipBase::commentedSnapMarkers() const
+{
+ return m_snapMarkers;
+}
+
+void DocClipBase::setSnapMarkers(QList < CommentedTime > markers)
+{
+ m_snapMarkers = markers;
+}
+
+void DocClipBase::addSnapMarker(const GenTime & time, QString comment)
+{
+ QList < CommentedTime >::Iterator it = m_snapMarkers.begin();
+ for ( it = m_snapMarkers.begin(); it != m_snapMarkers.end(); ++it ) {
+ if ((*it).time() >= time)
+ break;
+ }
+
+ if ((it != m_snapMarkers.end()) && ((*it).time() == time)) {
+ kError() <<
+ "trying to add Snap Marker that already exists, this will cause inconsistancies with undo/redo"
+ << endl;
+ } else {
+ CommentedTime t(time, comment);
+ m_snapMarkers.insert(it, t);
+ }
+
+}
+
+void DocClipBase::editSnapMarker(const GenTime & time, QString comment)
+{
+ QList < CommentedTime >::Iterator it;
+ for ( it = m_snapMarkers.begin(); it != m_snapMarkers.end(); ++it ) {
+ if ((*it).time() == time)
+ break;
+ }
+ if (it != m_snapMarkers.end()) {
+ (*it).setComment(comment);
+ } else {
+ kError() <<
+ "trying to edit Snap Marker that does not already exists" << endl;
+ }
+}
+
+QString DocClipBase::deleteSnapMarker(const GenTime & time)
+{
+ QString result = i18n("Marker");
+ QList < CommentedTime >::Iterator itt = m_snapMarkers.begin();
+
+ while (itt != m_snapMarkers.end()) {
+ if ((*itt).time() == time)
+ break;
+ ++itt;
+ }
+
+ if ((itt != m_snapMarkers.end()) && ((*itt).time() == time)) {
+ result = (*itt).comment();
+ m_snapMarkers.erase(itt);
+ }
+ return result;
+}
+
+
+GenTime DocClipBase::hasSnapMarkers(const GenTime & time)
+{
+ QList < CommentedTime >::Iterator itt = m_snapMarkers.begin();
+
+ while (itt != m_snapMarkers.end()) {
+ if ((*itt).time() == time)
+ return time;
+ ++itt;
+ }
+
+ return GenTime(0.0);
+}
+
+GenTime DocClipBase::findPreviousSnapMarker(const GenTime & currTime)
+{
+ int it;
+ for ( it = 0; it < m_snapMarkers.count(); it++ ) {
+ if (m_snapMarkers[it].time() >= currTime)
+ break;
+ }
+ if (it == 0) return GenTime();
+ else if (it == m_snapMarkers.count() - 1 && m_snapMarkers[it].time() < currTime)
+ return m_snapMarkers[it].time();
+ else return m_snapMarkers[it-1].time();
+}
+
+GenTime DocClipBase::findNextSnapMarker(const GenTime & currTime)
+{
+ int it;
+ for ( it = 0; it < m_snapMarkers.count(); it++ ) {
+ if (m_snapMarkers[it].time() > currTime)
+ break;
+ }
+ if (it < m_snapMarkers.count() && m_snapMarkers[it].time() > currTime) return m_snapMarkers[it].time();
+ return duration();
+}
+
+QString DocClipBase::markerComment(GenTime t)
+{
+ QList < CommentedTime >::Iterator itt = m_snapMarkers.begin();
+
+ while (itt != m_snapMarkers.end()) {
+ if ((*itt).time() == t)
+ return (*itt).comment();
+ ++itt;
+ }
+ return QString::null;
+}
+
+//static
+QString DocClipBase::getTypeName(CLIPTYPE type)
+{
+ QString result;
+ switch (type) {
+ case AV:
+ result = i18n("Video Clip");
+ break;
+ case COLOR:
+ result = i18n("Color Clip");
+ break;
+ case PLAYLIST:
+ result = i18n("Playlist Clip");
+ break;
+ case IMAGE:
+ result = i18n("Image Clip");
+ break;
+ case SLIDESHOW:
+ result = i18n("Slideshow Clip");
+ break;
+ case VIRTUAL:
+ result = i18n("Virtual Clip");
+ break;
+ case AUDIO:
+ result = i18n("Audio Clip");
+ break;
+ case VIDEO:
+ result = i18n("Mute Video Clip");
+ break;
+ case TEXT:
+ result = i18n("Text Clip");
+ break;
+ default:
+ result = i18n("None");
+ break;
+ }
+ return result;
+}
+
+
--- /dev/null
+/***************************************************************************
+ docclipbase.h - 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef DOCCLIPBASE_H
+#define DOCCLIPBASE_H
+
+/**DocClip is a class for the various types of clip
+ *@author Jason Wood
+ */
+
+#include <qdom.h>
+#include <qobject.h>
+#include <qpixmap.h>
+
+#include <kurl.h>
+#include <klocale.h>
+
+#include "gentime.h"
+// #include "kthumb.h"
+
+/*
+class DocTrackBase;
+class DocClipAVFile;
+class DocClipTextFile;
+class DocClipVirtual;
+class EffectDescriptionList;*/
+class KdenliveDoc;
+
+class CommentedTime
+ {
+ public:
+ CommentedTime(): t(GenTime(0)) {}
+ CommentedTime( const GenTime time, QString comment)
+ : t( time ), c( comment )
+ { }
+
+ QString comment() const { return (c.isEmpty() ? i18n("Marker") : c);}
+ GenTime time() const { return t; }
+ void setComment( QString comm) { c = comm; }
+ private:
+ GenTime t;
+ QString c;
+ };
+
+
+class DocClipBase:public QObject {
+ Q_OBJECT public:
+ /** this enum determines the types of "feed" available within this clip. types must be non-exclusive
+ * - e.g. if you can have audio and video seperately, it should be possible to combin the two, as is
+ * done here. If a new clip type is added then it should be possible to combine it with both audio
+ * and video. */
+ enum CLIPTYPE { NONE = 0, AUDIO = 1, VIDEO = 2, AV = 3, COLOR =
+ 4, IMAGE = 5, TEXT = 6, SLIDESHOW = 7, VIRTUAL = 8, PLAYLIST = 9};
+
+ DocClipBase();
+ virtual ~ DocClipBase();
+
+ /** sets the name of this clip. */
+ void setName(const QString name);
+
+ /** returns the name of this clip. */
+ const QString & name() const;
+
+ /** Sets the description for this clip. */
+ void setDescription(const QString & descripton);
+
+ /** Returns the description of this clip. */
+ const QString & description() const;
+
+ /** Returns the internal unique id of the clip. */
+ uint getId() const;
+ void setId( const uint &newId);
+
+ //KThumb *thumbCreator;
+ bool audioThumbCreated;
+
+ /** returns the duration of this clip */
+ virtual const GenTime & duration() const = 0;
+
+ /** returns clip type (audio, text, image,...) */
+ virtual const DocClipBase::CLIPTYPE & clipType() const = 0;
+
+ /** remove tmp file if the clip has one (for example text clips) */
+ virtual void removeTmpFile() const = 0;
+
+ /** Returns a url to a file describing this clip. Exactly what this url is,
+ whether it is temporary or not, and whether it provokes a render will
+ depend entirely on what the clip consists of. */
+ virtual const KUrl & fileURL() const = 0;
+
+ /** Returns true if the clip duration is known, false otherwise. */
+ virtual bool durationKnown() const = 0;
+ // Returns the number of frames per second that this clip should play at.
+ virtual double framesPerSecond() const = 0;
+
+ virtual bool isDocClipAVFile() const {
+ return false;
+ }
+
+ /*virtual DocClipAVFile *toDocClipAVFile() {
+ return 0;
+ }
+
+ virtual DocClipTextFile *toDocClipTextFile() {
+ return 0;
+ }
+
+ virtual bool isDocClipTextFile() const {
+ return false;
+ }
+
+ virtual bool isDocClipVirtual() const {
+ return false;
+ }
+
+ virtual DocClipVirtual *toDocClipVirtual() {
+ return 0;
+ }*/
+
+ /** Returns true if this clip is a project clip, false otherwise. Overridden in DocClipProject,
+ * where it returns true. */
+ virtual bool isProjectClip() const {
+ return false;
+ }
+ // Appends scene times for this clip to the passed vector.
+/* virtual void populateSceneTimes(QList < GenTime >
+ &toPopulate) const = 0;*/
+
+ /** Reads in the element structure and creates a clip out of it.*/
+ // Returns an XML document that describes part of the current scene.
+ virtual QDomDocument sceneToXML(const GenTime & startTime,
+ const GenTime & endTime) const = 0;
+ /** returns a QString containing all of the XML data required to recreate this clip. */
+ virtual QDomDocument toXML() const;
+ virtual QDomDocument generateSceneList(bool addProducers = true, bool rendering = false) const;
+
+ /** Returns true if the xml passed matches the values in this clip */
+ virtual bool matchesXML(const QDomElement & element) const = 0;
+
+ void addReference() {
+ ++m_refcount;
+ }
+ void removeReference() {
+ --m_refcount;
+ }
+ uint numReferences() const {
+ return m_refcount;
+ }
+ /** Returns true if this clip has a meaningful filesize. */
+ virtual bool hasFileSize() const = 0;
+
+ /** Returns the filesize, or 0 if there is no appropriate filesize. */
+ virtual uint fileSize() const = 0;
+
+ /** Returns true if this clip refers to the clip passed in. A clip refers to another clip if
+ * it uses it as part of it's own composition. */
+ virtual bool referencesClip(DocClipBase * clip) const = 0;
+
+ /** Sets the thumbnail to be used by this clip */
+ void setThumbnail(const QPixmap & pixmap);
+
+ /** Returns the thumbnail used by this clip */
+ const QPixmap & thumbnail() const;
+
+ static DocClipBase *createClip(KdenliveDoc *doc, const QDomElement & element);
+ /** Cache for every audio Frame with 10 Bytes */
+ /** format is frame -> channel ->bytes */
+ QMap<int,QMap<int,QByteArray> > audioFrameChache;
+
+ /** return english name for clip type */
+ static QString getTypeName(CLIPTYPE type);
+
+ private: // Private attributes
+ /** The name of this clip */
+ QString m_name;
+ /** A description of this clip */
+ QString m_description;
+ /** The number of times this clip is used in the project - the number of references to this clip
+ * that exist. */
+ uint m_refcount;
+
+ /** A list of snap markers; these markers are added to a clips snap-to points, and are displayed as necessary. */
+ QList < CommentedTime > m_snapMarkers;
+
+
+ /** A thumbnail for this clip */
+ QPixmap m_thumbnail;
+
+ /** a unique numeric id */
+ uint m_id;
+ uint m_projectThumbFrame;
+ void setAudioThumbCreated(bool isDone);
+
+ public slots:
+ void updateAudioThumbnail(QMap<int,QMap<int,QByteArray> > data);
+ QList < CommentedTime > commentedSnapMarkers() const;
+ void setSnapMarkers(QList < CommentedTime > markers);
+ GenTime findNextSnapMarker(const GenTime & currTime);
+ GenTime findPreviousSnapMarker(const GenTime & currTime);
+ GenTime hasSnapMarkers(const GenTime & time);
+ QString deleteSnapMarker(const GenTime & time);
+ void editSnapMarker(const GenTime & time, QString comment);
+ void addSnapMarker(const GenTime & time, QString comment);
+ QList < GenTime > snapMarkers() const;
+ QString markerComment(GenTime t);
+ void setProjectThumbFrame( const uint &ix);
+ uint getProjectThumbFrame() const;
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ time.cpp - description
+ -------------------
+ begin : Sat Sep 14 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 "gentime.h"
+
+double GenTime::s_delta = 0.00001;
+
+/** Creates a time object, with a time of 0 seconds. */
+GenTime::GenTime()
+{
+ m_time = 0.0;
+}
+
+/** Creates a time object, with time given in seconds. */
+GenTime::GenTime(double seconds)
+{
+ m_time = seconds;
+}
+
+/** Creates a time object, by passing number of frames and how many frames per second */
+GenTime::GenTime(int frames, double framesPerSecond)
+{
+ m_time = (double) frames / framesPerSecond;
+}
+
+/** Returns the time, in milliseconds */
+double GenTime::ms() const
+{
+ return m_time * 1000;
+}
+
+/** Returns the time in frames, after being given the number of frames per second */
+double GenTime::frames(double framesPerSecond) const
+{
+ return (int) floor(m_time * framesPerSecond + 0.5);
+}
+
+GenTime::~GenTime()
+{
+}
--- /dev/null
+/***************************************************************************
+ time.h - description
+ -------------------
+ begin : Sat Sep 14 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef GENTIME_H
+#define GENTIME_H
+
+#include <cmath>
+
+/**Encapsulates a time, which can be set in various forms and outputted in various forms.
+ *@author Jason Wood
+ */
+
+class GenTime {
+ public:
+ /** Creates a time object, with a time of 0 seconds. */
+ GenTime();
+
+ /** Creates a time object, with time given in seconds. */
+ explicit GenTime(double seconds);
+
+ /** Creates a time object, by passing number of frames and how many frames per second */
+ GenTime(int frames, double framesPerSecond);
+
+ /** returns the time, in seconds */
+ double seconds() const {
+ return m_time;
+ }
+ /** Returns the time, in milliseconds */ double ms() const;
+
+ /** Returns the time in frames, after being given the number of frames per second */
+ double frames(double framesPerSecond) const;
+
+ GenTime & operator+=(GenTime op) {
+ m_time += op.m_time;
+ return *this;
+ }
+ /** Adds two GenTimes */ GenTime operator+(GenTime op) const {
+ return GenTime(m_time + op.m_time);
+ }
+ /** Subtracts one genTime from another */ GenTime operator-(GenTime op) const {
+ return GenTime(m_time - op.m_time);
+ }
+ /** Multiplies one GenTime by a double value, returning a GenTime */
+ GenTime operator*(double op) const {
+ return GenTime(m_time * op);
+ }
+ /** Divides one GenTime by a double value, returning a GenTime */
+ GenTime operator/(double op) const {
+ return GenTime(m_time / op);
+ }
+ /* Implementation of < operator; Works identically as with basic types. */
+ bool operator<(GenTime op) const {
+ return m_time + s_delta < op.m_time;
+ }
+ /* Implementation of > operator; Works identically as with basic types. */
+ bool operator>(GenTime op) const {
+ return m_time > op.m_time + s_delta;
+ }
+ /* Implementation of >= operator; Works identically as with basic types. */
+ bool operator>=(GenTime op) const {
+ return m_time + s_delta >= op.m_time;
+ }
+ /* Implementation of <= operator; Works identically as with basic types. */
+ bool operator<=(GenTime op) const {
+ return m_time <= op.m_time + s_delta;
+ }
+ /* Implementation of == operator; Works identically as with basic types. */
+ bool operator==(GenTime op) const {
+ return fabs(m_time - op.m_time) < s_delta;
+ }
+ /* Implementation of != operator; Works identically as with basic types. */
+ bool operator!=(GenTime op) const {
+ return fabs(m_time - op.m_time) >= s_delta;
+ }
+ /* Rounds the GenTIme's value to the nearest frame */
+ GenTime & roundNearestFrame(double framesPerSecond) {
+ m_time = floor((m_time * framesPerSecond) + 0.5) / framesPerSecond;
+ return *this;
+ }
+
+ ~GenTime();
+ private: // Private attributes
+ /** Holds the time for this object. */
+ double m_time;
+
+ /** A delta value that is used to get around floating point rounding issues. */
+ static double s_delta;
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ kdenlivedoc.cpp - description
+ -------------------
+ begin : Fri Nov 22 2002
+ copyright : (C) 2002 by Jason Wood
+ email : jasonwood@blueyonder.co.uk
+ copyright : (C) 2005 Lucio Flavio Correa
+ email : lucio.correa@gmail.com
+ copyright : (C) Marco Gittler
+ email : g.marco@freenet.de
+ copyright : (C) 2006 Jean-Baptiste Mardelle
+ email : jb@ader.ch
+
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 <KDebug>
+#include <KStandardDirs>
+#include <KMessageBox>
+#include <KLocale>
+#include <KFileDialog>
+#include <KIO/NetAccess>
+
+
+#include "kdenlivedoc.h"
+
+KdenliveDoc::KdenliveDoc(KUrl url, double fps, int width, int height, QWidget *parent):QObject(parent), m_url(url), m_projectName(NULL)
+{
+ if (!url.isEmpty()) {
+ QString tmpFile;
+ if(KIO::NetAccess::download(url.path(), tmpFile, parent))
+ {
+ QFile file(tmpFile);
+ m_document.setContent(&file, false);
+ file.close();
+ m_projectName = url.fileName();
+
+ KIO::NetAccess::removeTempFile(tmpFile);
+ }
+ else
+ {
+ KMessageBox::error(parent,
+ KIO::NetAccess::lastErrorString());
+ }
+ }
+}
+
+KdenliveDoc::~KdenliveDoc()
+{
+}
+
+QString KdenliveDoc::documentName()
+{
+ return m_projectName;
+}
+
+QDomNodeList KdenliveDoc::producersList()
+{
+ return m_document.elementsByTagName("producer");
+}
+
+#include "kdenlivedoc.moc"
+
--- /dev/null
+/***************************************************************************
+ krender.h - description
+ -------------------
+ begin : Fri Nov 22 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef KDENLIVEDOC_H
+#define KDENLIVEDOC_H
+
+#include <qdom.h>
+#include <qstring.h>
+#include <qmap.h>
+#include <QList>
+#include <QObject>
+
+#include <kurl.h>
+
+#include "gentime.h"
+
+
+class KdenliveDoc:public QObject {
+ Q_OBJECT public:
+
+ KdenliveDoc(KUrl url, double fps, int width, int height, QWidget *parent = 0);
+ ~KdenliveDoc();
+ QString documentName();
+ QDomNodeList producersList();
+
+ private:
+ KUrl m_url;
+ QDomDocument m_document;
+ QString m_projectName;
+
+ public slots:
+
+};
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<gui name="kdenlive" version="1">
+ <ToolBar name="mainToolBar" >
+ <text>Main Toolbar</text>
+ <Action name="clear" />
+ </ToolBar>
+ <MenuBar>
+ <Menu name="file" >
+ <Action name="clear" />
+ </Menu>
+ </MenuBar>
+</gui>
\ No newline at end of file
--- /dev/null
+#include <KApplication>
+#include <KAboutData>
+#include <KCmdLineArgs>
+#include <KUrl> //new
+
+#include "mainwindow.h"
+
+int main (int argc, char *argv[])
+{
+ KAboutData aboutData( "Kdenlive", "kdenlive",
+ ki18n("Kdenlive"), "1.0",
+ ki18n("A simple text area which can load and save."),
+ KAboutData::License_GPL,
+ ki18n("Copyright (c) 2007 Developer") );
+ KCmdLineArgs::init( argc, argv, &aboutData );
+
+ KCmdLineOptions options; //new
+ options.add("+[file]", ki18n("Document to open")); //new
+ KCmdLineArgs::addCmdLineOptions(options); //new
+
+ KApplication app;
+
+ MainWindow* window = new MainWindow();
+ window->show();
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); //new
+ if(args->count()) //new
+ {
+ window->openFile(args->url(0).url()); //new
+ }
+
+ return app.exec();
+}
--- /dev/null
+
+
+#include <KApplication>
+#include <KAction>
+#include <KLocale>
+#include <KActionCollection>
+#include <KStandardAction>
+#include <KFileDialog>
+#include <KMessageBox>
+#include <KDebug>
+#include <KIO/NetAccess>
+#include <KSaveFile>
+#include <KRuler>
+#include <QTextStream>
+
+#include <mlt++/Mlt.h>
+
+#include "mainwindow.h"
+#include "trackview.h"
+
+MainWindow::MainWindow(QWidget *parent)
+ : KXmlGuiWindow(parent),
+ fileName(QString())
+{
+ m_timelineArea = new KTabWidget(this);
+ m_timelineArea->setHoverCloseButton(true);
+ m_timelineArea->setTabReorderingEnabled(true);
+ connect(m_timelineArea, SIGNAL(currentChanged (int)), this, SLOT(activateDocument()));
+ setCentralWidget(m_timelineArea);
+
+ projectListDock = new QDockWidget(i18n("Project Tree"), this);
+ m_projectList = new ProjectList(NULL, this);
+ projectListDock->setWidget(m_projectList);
+ addDockWidget(Qt::TopDockWidgetArea, projectListDock);
+
+ effectListDock = new QDockWidget(i18n("Effect List"), this);
+ effectList = new KListWidget(this);
+ effectListDock->setWidget(effectList);
+ addDockWidget(Qt::TopDockWidgetArea, effectListDock);
+
+ effectStackDock = new QDockWidget(i18n("Effect Stack"), this);
+ effectStack = new KListWidget(this);
+ effectStackDock->setWidget(effectStack);
+ addDockWidget(Qt::TopDockWidgetArea, effectStackDock);
+
+ transitionConfigDock = new QDockWidget(i18n("Transition"), this);
+ transitionConfig = new KListWidget(this);
+ transitionConfigDock->setWidget(transitionConfig);
+ addDockWidget(Qt::TopDockWidgetArea, transitionConfigDock);
+
+ Mlt::Factory::init(NULL);
+
+ clipMonitorDock = new QDockWidget(i18n("Clip Monitor"), this);
+ m_clipMonitor = new Monitor("clip", this);
+ clipMonitorDock->setWidget(m_clipMonitor);
+ addDockWidget(Qt::TopDockWidgetArea, clipMonitorDock);
+
+ projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this);
+ m_projectMonitor = new Monitor("project", this);
+ projectMonitorDock->setWidget(m_projectMonitor);
+ addDockWidget(Qt::TopDockWidgetArea, projectMonitorDock);
+
+ setupActions();
+ tabifyDockWidget (effectListDock, projectListDock);
+ tabifyDockWidget (effectListDock, effectStackDock);
+ tabifyDockWidget (effectListDock, transitionConfigDock);
+
+ tabifyDockWidget (clipMonitorDock, projectMonitorDock);
+
+ connect(m_projectList, SIGNAL(clipSelected(const QDomElement &)), m_projectMonitor, SLOT(slotSetXml(const QDomElement &)));
+
+ connect(m_projectList, SIGNAL(getFileProperties(const KUrl &, uint)), m_projectMonitor->render, SLOT(getFileProperties(const KUrl &, uint)));
+
+ connect(m_projectMonitor->render, SIGNAL(replyGetImage(const KUrl &, int, const QPixmap &, int, int)), m_projectList, SLOT(slotReplyGetImage(const KUrl &, int, const QPixmap &, int, int)));
+
+ connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QMap < QString, QString > &, const QMap < QString, QString > &)), m_projectList, SLOT(slotReplyGetFileProperties(const QMap < QString, QString > &, const QMap < QString, QString > &)));
+
+}
+
+void MainWindow::setupActions()
+{
+ KAction* clearAction = new KAction(this);
+ clearAction->setText(i18n("Clear"));
+ clearAction->setIcon(KIcon("document-new"));
+ clearAction->setShortcut(Qt::CTRL + Qt::Key_W);
+ actionCollection()->addAction("clear", clearAction);
+ /*connect(clearAction, SIGNAL(triggered(bool)),
+ textArea, SLOT(clear()));*/
+
+ KStandardAction::quit(kapp, SLOT(quit()),
+ actionCollection());
+
+ KStandardAction::open(this, SLOT(openFile()),
+ actionCollection());
+
+ KStandardAction::save(this, SLOT(saveFile()),
+ actionCollection());
+
+ KStandardAction::saveAs(this, SLOT(saveFileAs()),
+ actionCollection());
+
+ KStandardAction::openNew(this, SLOT(newFile()),
+ actionCollection());
+
+ setupGUI();
+}
+
+void MainWindow::newFile()
+{
+ KdenliveDoc *doc = new KdenliveDoc(KUrl(), 25, 720, 576);
+ TrackView *trackView = new TrackView(doc);
+ m_timelineArea->addTab(trackView, "New Project");
+}
+
+void MainWindow::activateDocument()
+{
+ TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget();
+ KdenliveDoc *currentDoc = currentTab->document();
+ connectDocument(currentDoc);
+}
+
+void MainWindow::saveFileAs(const QString &outputFileName)
+{
+ KSaveFile file(outputFileName);
+ file.open();
+
+ QByteArray outputByteArray;
+ //outputByteArray.append(textArea->toPlainText());
+ file.write(outputByteArray);
+ file.finalize();
+ file.close();
+
+ fileName = outputFileName;
+}
+
+void MainWindow::saveFileAs()
+{
+ saveFileAs(KFileDialog::getSaveFileName());
+}
+
+void MainWindow::saveFile()
+{
+ if(!fileName.isEmpty())
+ {
+ saveFileAs(fileName);
+ }
+ else
+ {
+ saveFileAs();
+ }
+}
+
+void MainWindow::openFile() //changed
+{
+ openFile(KFileDialog::getOpenFileName(KUrl(), "application/vnd.kde.kdenlive"));
+}
+
+void MainWindow::openFile(const QString &inputFileName) //new
+{
+ KdenliveDoc *doc = new KdenliveDoc(KUrl(inputFileName), 25, 720, 576);
+ TrackView *trackView = new TrackView(doc);
+ m_timelineArea->setCurrentIndex(m_timelineArea->addTab(trackView, QIcon(), doc->documentName()));
+ connectDocument(doc);
+
+}
+
+void MainWindow::connectDocument(KdenliveDoc *doc) //changed
+{
+ m_projectList->populate(doc->producersList());
+ //connect(doc, SIGNAL(addClip(QDomElement &)), m_projectList, SLOT(slotAddClip(QDomElement &)));
+}
+
+#include "mainwindow.moc"
--- /dev/null
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QDockWidget>
+
+#include <KXmlGuiWindow>
+#include <KTextEdit>
+#include <KListWidget>
+#include <KTabWidget>
+
+#include "projectlist.h"
+#include "monitor.h"
+#include "kdenlivedoc.h"
+
+class MainWindow : public KXmlGuiWindow
+{
+ Q_OBJECT
+
+ public:
+ MainWindow(QWidget *parent=0);
+ void openFile(const QString &inputFileName);
+
+ private:
+ KTabWidget* m_timelineArea;
+ void setupActions();
+ QString fileName;
+
+ QDockWidget *projectListDock;
+ ProjectList *m_projectList;
+
+ QDockWidget *effectListDock;
+ KListWidget *effectList;
+
+ QDockWidget *effectStackDock;
+ KListWidget *effectStack;
+
+ QDockWidget *transitionConfigDock;
+ KListWidget *transitionConfig;
+
+ QDockWidget *clipMonitorDock;
+ Monitor *m_clipMonitor;
+
+ QDockWidget *projectMonitorDock;
+ Monitor *m_projectMonitor;
+
+ private slots:
+ void newFile();
+ void activateDocument();
+ void connectDocument(KdenliveDoc*);
+ void openFile();
+ void saveFile();
+ void saveFileAs();
+ void saveFileAs(const QString &outputFileName);
+};
+
+#endif
--- /dev/null
+
+#include <QMouseEvent>
+#include <QStylePainter>
+
+#include <KDebug>
+#include <KLocale>
+
+#include "gentime.h"
+#include "monitor.h"
+
+Monitor::Monitor(QString name, QWidget *parent)
+ : QWidget(parent)
+{
+ ui.setupUi(this);
+ if (name == "project") {
+ render = new Render(name, this);
+ render->createVideoXWindow(ui.video_frame->winId(), -1);
+ connect(ui.button_play, SIGNAL(clicked()), this, SLOT(slotOpen()));
+ connect(ui.button_rew, SIGNAL(clicked()), this, SLOT(slotRewind()));
+ connect(ui.button_play_2, SIGNAL(clicked()), this, SLOT(slotPlay()));
+ }
+}
+
+void Monitor::slotOpen()
+{
+
+render->mltInsertClip(2, GenTime(1, 25), QString("<westley><producer mlt_service=\"colour\" colour=\"red\" in=\"1\" out=\"30\" /></westley>"));
+render->mltInsertClip(2, GenTime(0, 25), QString("<westley><producer mlt_service=\"avformat\" resource=\"/home/one/.vids/clip3e.mpg\" in=\"1\" out=\"300\" /></westley>"));
+}
+
+void Monitor::slotRewind()
+{
+ render->seek(GenTime(0));
+
+}
+
+void Monitor::slotPlay()
+{
+ render->switchPlay();
+}
+
+void Monitor::slotSetXml(const QDomElement &e)
+{
+ QDomDocument doc;
+ QDomElement westley = doc.createElement("westley");
+ doc.appendChild(westley);
+ westley.appendChild(e);
+ render->setSceneList(doc, 0);
+}
+
+
+void Monitor::slotOpenFile(const QString &file)
+{
+ QDomDocument doc;
+ QDomElement westley = doc.createElement("westley");
+ doc.appendChild(westley);
+ QDomElement prod = doc.createElement("producer");
+ westley.appendChild(prod);
+ prod.setAttribute("mlt_service", "avformat");
+ prod.setAttribute("resource", file);
+ render->setSceneList(doc, 0);
+}
+
+
+
+#include "monitor.moc"
--- /dev/null
+#ifndef MONITOR_H
+#define MONITOR_H
+
+#include <KListWidget>
+#include "ui_monitor_ui.h"
+#include "renderer.h"
+
+class Monitor : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ Monitor(QString name, QWidget *parent=0);
+ Render *render;
+
+ private:
+ Ui::Monitor_UI ui;
+
+ private slots:
+ void slotPlay();
+ void slotOpen();
+ void slotRewind();
+
+ public slots:
+ void slotOpenFile(const QString &);
+ void slotSetXml(const QDomElement &e);
+};
+
+#endif
--- /dev/null
+
+#include <QMouseEvent>
+#include <QStylePainter>
+#include <QLabel>
+#include <QLayout>
+
+#include <KDebug>
+#include <KLocale>
+
+
+#include "projectitem.h"
+#include "timecode.h"
+
+ const int NameRole = Qt::UserRole;
+ const int DurationRole = NameRole + 1;
+ const int FullPathRole = NameRole + 2;
+ const int ClipTypeRole = NameRole + 3;
+
+ProjectItem::ProjectItem(QTreeWidget * parent, const QStringList & strings, QDomElement xml, int type)
+ : QTreeWidgetItem(parent, strings, type), m_element(xml), m_clipType(DocClipBase::NONE)
+{
+ setSizeHint(0, QSize(65, 45));
+ setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled);
+ QString cType = m_element.attribute("type", 0);
+ if (!cType.isEmpty()) {
+ m_clipType = (DocClipBase::CLIPTYPE) cType.toInt();
+ slotSetToolTip();
+ }
+
+}
+
+ProjectItem::~ProjectItem()
+{
+}
+
+QDomElement ProjectItem::toXml()
+{
+ return m_element;
+}
+
+void ProjectItem::slotSetToolTip()
+{
+ QString tip = "<qt><b>";
+ switch (m_clipType) {
+ case 1:
+ tip.append(i18n("Audio clip"));
+ break;
+ case 2:
+ tip.append(i18n("Mute video clip"));
+ break;
+ case 3:
+ tip.append(i18n("Video clip"));
+ break;
+ case 4:
+ tip.append(i18n("Color clip"));
+ break;
+ case 5:
+ tip.append(i18n("Image clip"));
+ break;
+ case 6:
+ tip.append(i18n("Text clip"));
+ break;
+ case 7:
+ tip.append(i18n("Slideshow clip"));
+ break;
+ case 8:
+ tip.append(i18n("Virtual clip"));
+ break;
+ case 9:
+ tip.append(i18n("Playlist clip"));
+ break;
+ default:
+ tip.append(i18n("Unknown clip"));
+ break;
+ }
+
+ setToolTip(1, tip);
+}
+
+void ProjectItem::setProperties(const QMap < QString, QString > &attributes, const QMap < QString, QString > &metadata)
+{
+ if (attributes.contains("duration")) {
+ m_duration = GenTime(attributes["duration"].toInt(), 25);
+ setData(1, DurationRole, Timecode::getEasyTimecode(m_duration, 25));
+ m_durationKnown = true;
+ } else {
+ // No duration known, use an arbitrary one until it is.
+ m_duration = GenTime(0.0);
+ m_durationKnown = false;
+ }
+
+
+ //extend attributes -reh
+ if (attributes.contains("type")) {
+ if (attributes["type"] == "audio")
+ m_clipType = DocClipBase::AUDIO;
+ else if (attributes["type"] == "video")
+ m_clipType = DocClipBase::VIDEO;
+ else if (attributes["type"] == "av")
+ m_clipType = DocClipBase::AV;
+ else if (attributes["type"] == "playlist")
+ m_clipType = DocClipBase::PLAYLIST;
+ } else {
+ m_clipType = DocClipBase::AV;
+ }
+ slotSetToolTip();
+
+ if (m_element.isNull()) {
+ QDomDocument doc;
+ m_element = doc.createElement("producer");
+ m_element.setAttribute("resource", attributes["filename"]);
+ m_element.setAttribute("type", (int) m_clipType);
+ }
+/*
+ if (attributes.contains("height")) {
+ m_height = attributes["height"].toInt();
+ } else {
+ m_height = 0;
+ }
+ if (attributes.contains("width")) {
+ m_width = attributes["width"].toInt();
+ } else {
+ m_width = 0;
+ }
+ //decoder name
+ if (attributes.contains("name")) {
+ m_decompressor = attributes["name"];
+ } else {
+ m_decompressor = "n/a";
+ }
+ //video type ntsc/pal
+ if (attributes.contains("system")) {
+ m_system = attributes["system"];
+ } else {
+ m_system = "n/a";
+ }
+ if (attributes.contains("fps")) {
+ m_framesPerSecond = attributes["fps"].toInt();
+ } else {
+ // No frame rate known.
+ m_framesPerSecond = 0;
+ }
+ //audio attributes -reh
+ if (attributes.contains("channels")) {
+ m_channels = attributes["channels"].toInt();
+ } else {
+ m_channels = 0;
+ }
+ if (attributes.contains("format")) {
+ m_format = attributes["format"];
+ } else {
+ m_format = "n/a";
+ }
+ if (attributes.contains("frequency")) {
+ m_frequency = attributes["frequency"].toInt();
+ } else {
+ m_frequency = 0;
+ }
+ if (attributes.contains("videocodec")) {
+ m_videoCodec = attributes["videocodec"];
+ }
+ if (attributes.contains("audiocodec")) {
+ m_audioCodec = attributes["audiocodec"];
+ }
+
+ m_metadata = metadata;
+
+ if (m_metadata.contains("description")) {
+ setDescription (m_metadata["description"]);
+ }
+ else if (m_metadata.contains("comment")) {
+ setDescription (m_metadata["comment"]);
+ }
+*/
+
+}
+
+#include "projectitem.moc"
--- /dev/null
+#ifndef PROJECTITEM_H
+#define PROJECTITEM_H
+
+#include <QTreeWidgetItem>
+#include <QTreeWidget>
+#include <QDomElement>
+
+#include "gentime.h"
+#include "docclipbase.h"
+
+
+class ProjectItem : public QTreeWidgetItem
+{
+ public:
+ ProjectItem(QTreeWidget * parent, const QStringList & strings, QDomElement xml = QDomElement(), int type = QTreeWidgetItem::UserType);
+ ~ProjectItem();
+ QDomElement toXml();
+
+ void setProperties(const QMap < QString, QString > &attributes, const QMap < QString, QString > &metadata);
+
+ private:
+ QDomElement m_element;
+ GenTime m_duration;
+ bool m_durationKnown;
+ DocClipBase::CLIPTYPE m_clipType;
+ void slotSetToolTip();
+};
+
+#endif
--- /dev/null
+
+#include <QMouseEvent>
+#include <QStylePainter>
+#include <QPixmap>
+#include <QIcon>
+
+#include <KDebug>
+#include <KLocale>
+#include <KFileDialog>
+#include <klistwidgetsearchline.h>
+
+#include "projectlist.h"
+#include "projectitem.h"
+
+#include <QtGui>
+
+ const int NameRole = Qt::UserRole;
+ const int DurationRole = NameRole + 1;
+ const int FullPathRole = NameRole + 2;
+ const int ClipTypeRole = NameRole + 3;
+
+class ItemDelegate: public QItemDelegate
+{
+ public:
+ ItemDelegate(QObject* parent = 0): QItemDelegate(parent)
+ {
+ }
+
+void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
+{
+ if (index.column() == 1)
+ {
+ QFont font = painter->font();
+ font.setPointSize(font.pointSize() - 2 );
+ QRect r1 = option.rect;
+ r1.setBottom(r1.y() + (r1.height() *2 / 3 ));
+ QRect r2 = option.rect;
+ r2.setTop(r2.y() + (r2.height() *2 / 3 ));
+ painter->drawText(r1, Qt::AlignLeft | Qt::AlignVCenter , index.data().toString());
+ painter->setPen(Qt::green);
+ painter->drawText(r2, Qt::AlignLeft | Qt::AlignTop , index.data(DurationRole).toString());
+ painter->setPen(Qt::black);
+ }
+ else
+ {
+ QItemDelegate::paint(painter, option, index);
+ }
+}
+};
+
+
+ProjectList::ProjectList(Render *projectRender, QWidget *parent)
+ : QWidget(parent), m_render(projectRender)
+{
+
+ ui.setupUi(this);
+ ui.project_search->setTreeWidget(ui.project_list);
+ QStringList itemEntry;
+ itemEntry.append(QString::null);
+ itemEntry.append("coucou");
+ new ProjectItem(ui.project_list, itemEntry);
+ connect(ui.button_add, SIGNAL(clicked ( bool )), this, SLOT(slotAddClip()));
+ connect(ui.project_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotClipSelected()));
+ connect(ui.project_list, SIGNAL(itemDoubleClicked ( QTreeWidgetItem *, int )), this, SLOT(slotEditClip(QTreeWidgetItem *, int)));
+
+
+ ui.project_list->setItemDelegate(new ItemDelegate(ui.project_list));
+ ui.project_list->setIconSize(QSize(60, 40));
+ ui.project_list->setSortingEnabled (true);
+
+}
+
+void ProjectList::setRenderer(Render *projectRender)
+{
+ m_render = projectRender;
+}
+
+void ProjectList::slotDoubleClicked(QListWidgetItem *item, const QPoint &pos)
+{
+ kDebug()<<" / / / DBL CLICK";
+ if (item) {
+ KUrl url = KFileDialog::getOpenUrl( KUrl(), "video/mpeg");
+ }
+}
+
+void ProjectList::slotClipSelected()
+{
+ ProjectItem *item = (ProjectItem*) ui.project_list->currentItem();
+ if (item) emit clipSelected(item->toXml());
+}
+
+void ProjectList::slotEditClip(QTreeWidgetItem *item, int column)
+{
+ if (column != 2){
+ return;
+ }
+}
+
+void ProjectList::slotAddClip()
+{
+
+ KUrl::List list = KFileDialog::getOpenUrls( KUrl(), "application/vnd.kde.kdenlive application/vnd.westley.scenelist application/flv application/vnd.rn-realmedia video/x-dv video/x-msvideo video/mpeg video/x-ms-wmv audio/x-mp3 audio/x-wav application/ogg *.m2t *.dv video/mp4 video/quicktime image/gif image/jpeg image/png image/x-bmp image/svg+xml image/tiff image/x-xcf-gimp image/x-vnd.adobe.photoshop image/x-pcx image/x-exr");
+
+ KUrl::List::Iterator it;
+ KUrl url;
+
+ for (it = list.begin(); it != list.end(); it++) {
+ QStringList itemEntry;
+ itemEntry.append(QString::null);
+ itemEntry.append((*it).fileName());
+ ProjectItem *item = new ProjectItem(ui.project_list, itemEntry, QDomElement());
+ item->setData(1, FullPathRole, (*it).path());
+ emit getFileProperties((*it), 0);
+ }
+
+}
+
+void ProjectList::populate(QDomNodeList prods)
+{
+ ui.project_list->clear();
+ for (int i = 0; i < prods.count () ; i++)
+ {
+ addProducer(prods.item(i).toElement());
+ }
+}
+
+void ProjectList::slotReplyGetFileProperties(const QMap < QString, QString > &properties, const QMap < QString, QString > &metadata)
+{
+ QTreeWidgetItem *parent = 0;
+ int count =
+ parent ? parent->childCount() : ui.project_list->topLevelItemCount();
+
+ for (int i = 0; i < count; i++)
+ {
+ QTreeWidgetItem *item =
+ parent ? parent->child(i) : ui.project_list->topLevelItem(i);
+
+ if (item->data(1, FullPathRole).toString() == properties["filename"]) {
+ ((ProjectItem *) item)->setProperties(properties, metadata);
+ break;
+ }
+ }
+}
+
+
+void ProjectList::slotReplyGetImage(const KUrl &url, int pos, const QPixmap &pix, int w, int h)
+{
+ QTreeWidgetItem *parent = 0;
+ int count =
+ parent ? parent->childCount() : ui.project_list->topLevelItemCount();
+
+ for (int i = 0; i < count; i++)
+ {
+ QTreeWidgetItem *item =
+ parent ? parent->child(i) : ui.project_list->topLevelItem(i);
+
+ if (item->data(1, FullPathRole).toString() == url.path()) {
+ item->setIcon(0,pix);
+ break;
+ }
+ }
+
+}
+
+
+void ProjectList::addProducer(QDomElement producer)
+{
+ DocClipBase::CLIPTYPE type = (DocClipBase::CLIPTYPE) producer.attribute("type").toInt();
+
+ if (type == DocClipBase::AUDIO || type == DocClipBase::VIDEO || type == DocClipBase::AV)
+ {
+ KUrl resource = KUrl(producer.attribute("resource"));
+ if (!resource.isEmpty()) {
+ QStringList itemEntry;
+ itemEntry.append(QString::null);
+ itemEntry.append(resource.fileName());
+ ProjectItem *item = new ProjectItem(ui.project_list, itemEntry, producer);
+ //item->setIcon(0, Render::getVideoThumbnail(resource, 0, 60, 40));
+ item->setData(1, FullPathRole, resource.path());
+ item->setData(1, ClipTypeRole, (int) type);
+ emit getFileProperties(resource, producer.attribute("frame_thumbnail", 0).toInt());
+ }
+ }
+ else if (type == DocClipBase::COLOR) {
+ QString colour = producer.attribute("colour");
+ QPixmap pix(60, 40);
+ colour = colour.replace(0, 2, "#");
+ pix.fill(QColor(colour.left(7)));
+ QStringList itemEntry;
+ itemEntry.append(QString::null);
+ itemEntry.append(i18n("Color Clip"));
+ ProjectItem *item = new ProjectItem(ui.project_list, itemEntry, producer);
+ item->setIcon(0, QIcon(pix));
+ item->setData(1, ClipTypeRole, (int) type);
+ }
+
+}
+
+#include "projectlist.moc"
--- /dev/null
+#ifndef PRJECTLIST_H
+#define PRJECTLIST_H
+
+#include <QDomNodeList>
+#include <QTreeWidget>
+
+#include "ui_projectlist_ui.h"
+#include "docclipbase.h"
+#include "renderer.h"
+
+class ProjectList : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ ProjectList(Render *projectRender, QWidget *parent=0);
+
+ public slots:
+ void populate(QDomNodeList prods);
+ void addProducer(QDomElement producer);
+ void setRenderer(Render *projectRender);
+ void slotReplyGetImage(const KUrl &url, int pos, const QPixmap &pix, int w, int h);
+ void slotReplyGetFileProperties(const QMap < QString, QString > &properties, const QMap < QString, QString > &metadata);
+
+ private:
+ Ui::ProjectList_UI ui;
+ Render *m_render;
+
+ private slots:
+ void slotDoubleClicked(QListWidgetItem *, const QPoint &);
+ void slotAddClip();
+ void slotEditClip(QTreeWidgetItem *item, int column);
+ void slotClipSelected();
+
+ signals:
+ void clipSelected(const QDomElement &);
+ void getFileProperties(const KUrl &, uint);
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ krender.cpp - description
+ -------------------
+ begin : Fri Nov 22 2002
+ copyright : (C) 2002 by Jason Wood
+ email : jasonwood@blueyonder.co.uk
+ copyright : (C) 2005 Lucio Flavio Correa
+ email : lucio.correa@gmail.com
+ copyright : (C) Marco Gittler
+ email : g.marco@freenet.de
+ copyright : (C) 2006 Jean-Baptiste Mardelle
+ email : jb@ader.ch
+
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+// ffmpeg Header files
+
+extern "C" {
+#include <ffmpeg/avformat.h>
+}
+#include <QTimer>
+#include <QDir>
+#include <QApplication>
+#include <QPainter>
+
+#include <KDebug>
+#include <KStandardDirs>
+#include <KMessageBox>
+#include <KLocale>
+
+
+#include <mlt++/Mlt.h>
+
+
+#include "renderer.h"
+
+Render::Render(const QString & rendererName, QWidget *parent):QObject(parent), m_name(rendererName), m_mltConsumer(NULL), m_mltProducer(NULL), m_mltTextProducer(NULL), m_sceneList(QDomDocument()), m_winid(-1), m_framePosition(0), m_generateScenelist(false), isBlocked(true)
+{
+ refreshTimer = new QTimer( this );
+ connect( refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()) );
+
+ m_connectTimer = new QTimer( this );
+ connect( m_connectTimer, SIGNAL(timeout()), this, SLOT(connectPlaylist()) );
+
+ if (rendererName == "project") m_monitorId = 10000;
+ else m_monitorId = 10001;
+ osdTimer = new QTimer( this );
+ connect( osdTimer, SIGNAL(timeout()), this, SLOT(slotOsdTimeout()) );
+
+ m_osdProfile = KStandardDirs::locate("data", "kdenlive/profiles/metadata.properties");
+ /*m_osdInfo = new Mlt::Filter("data_show");
+ char *tmp = decodedString(m_osdProfile);
+ m_osdInfo->set("resource", tmp);
+ delete[] tmp;*/
+ // Does it do anything usefull? I mean, RenderThread doesn't do anything useful at the moment
+ // (except being cpu hungry :)
+
+ /* if(!s_renderThread) {
+ s_renderThread = new RenderThread;
+ s_renderThread->start();
+ } */
+}
+
+Render::~Render()
+{
+ closeMlt();
+}
+
+
+void Render::closeMlt()
+{
+ delete m_connectTimer;
+ delete osdTimer;
+ delete refreshTimer;
+ if (m_mltConsumer)
+ delete m_mltConsumer;
+ if (m_mltProducer)
+ delete m_mltProducer;
+ //delete m_osdInfo;
+}
+
+
+
+static void consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_ptr)
+{
+ // detect if the producer has finished playing. Is there a better way to do it ?
+ //if (self->isBlocked) return;
+ if (mlt_properties_get_double( MLT_FRAME_PROPERTIES( frame_ptr ), "_speed" ) == 0.0) {
+ self->emitConsumerStopped();
+ }
+ else {
+ self->emitFrameNumber(mlt_frame_get_position(frame_ptr));
+ }
+}
+
+/** Wraps the VEML command of the same name; requests that the renderer
+should create a video window. If show is true, then the window should be
+displayed, otherwise it should be hidden. Render will emit the signal
+replyCreateVideoXWindow() once the renderer has replied. */
+
+void Render::createVideoXWindow(WId winid, WId externalMonitor)
+{
+ if (m_mltConsumer) {
+ delete m_mltConsumer;
+ }
+
+ m_mltConsumer = new Mlt::Consumer("sdl_preview");
+ if (!m_mltConsumer || !m_mltConsumer->is_valid()) {
+ KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install.\n Exiting now..."));
+ kError()<<"Sorry, cannot create MLT consumer, check your MLT install you miss SDL libraries support in MLT";
+ exit(1);
+ }
+
+ //only as is saw, if we want to lock something with the sdl lock
+ /*if (!KdenliveSettings::videoprofile().isEmpty())
+ m_mltConsumer->set("profile", KdenliveSettings::videoprofile().ascii());*/
+
+ m_mltConsumer->set("profile", "hdv_1080_50i"); //KdenliveSettings::videoprofile().ascii());
+ /*m_mltConsumer->set("app_locked", 1);
+ m_mltConsumer->set("app_lock", (void *) &my_lock, 0);
+ m_mltConsumer->set("app_unlock", (void *) &my_unlock, 0);*/
+ m_externalwinid = (int) externalMonitor;
+ m_winid = (int) winid;
+
+ m_mltConsumer->set("window_id", m_winid);
+ m_mltConsumer->set("resize", 1);
+
+ m_mltConsumer->set("terminate_on_pause", 1);
+ /*QString aDevice = KdenliveSettings::audiodevice();
+ if (!KdenliveSettings::videodriver().isEmpty()) m_mltConsumer->set("video_driver", KdenliveSettings::videodriver().ascii());
+ if (!KdenliveSettings::audiodriver().isEmpty()) m_mltConsumer->set("audio_driver", KdenliveSettings::audiodriver().ascii());
+ m_mltConsumer->set("audio_device", aDevice.section(";", 1).ascii());*/
+ m_mltConsumer->set("progressive", 1);
+ m_mltConsumer->set("audio_buffer", 1024);
+ m_mltConsumer->set("frequency", 48000);
+
+ m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show);
+
+ QTimer::singleShot(500, this, SLOT(initSceneList()));
+ //initSceneList();
+// m_mltConsumer->listen("consumer-stopped", this, (mlt_listener) consumer_stopped);
+// m_mltConsumer->set("buffer", 25);
+}
+
+
+int Render::resetRendererProfile(char * profile)
+{
+ if (!m_mltConsumer) return 0;
+ if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
+ m_mltConsumer->set("refresh", 0);
+ m_mltConsumer->set("profile", profile);
+ kDebug()<<" + + RESET CONSUMER WITH PROFILE: "<<profile;
+ m_fps = 25;
+ m_mltConsumer->set("fps", m_fps);
+ mlt_properties properties = MLT_CONSUMER_PROPERTIES( m_mltConsumer->get_consumer() );
+ int result = mlt_consumer_profile( properties, profile );
+ refresh();
+ return result;
+}
+
+void Render::restartConsumer()
+{
+ if (m_winid != -1) createVideoXWindow( m_winid, m_externalwinid);
+}
+
+/** Wraps the VEML command of the same name; Seeks the renderer clip to the given time. */
+void Render::seek(GenTime time)
+{
+ sendSeekCommand(time);
+ //emit positionChanged(time);
+}
+
+//static
+char *Render::decodedString(QString str)
+{
+ /*QCString fn = QFile::encodeName(str);
+ char *t = new char[fn.length() + 1];
+ strcpy(t, (const char *)fn);*/
+
+ return qstrdup( str.toLatin1().data() );
+}
+
+//static
+QPixmap Render::frameThumbnail(Mlt::Frame *frame, int width, int height, bool border)
+{
+ QPixmap pix(width, height);
+
+ mlt_image_format format = mlt_image_rgb24a;
+ /*if (border) {
+ width = width -2;
+ height = height -2;
+ }*/
+ uint8_t *thumb = frame->get_image(format, width, height);
+ QImage image(thumb, width, height, QImage::Format_ARGB32);
+
+ if (!image.isNull()) {
+ pix = pix.fromImage(image);
+ if (border) {
+ QPainter painter(&pix);
+ painter.drawRect(0, 0, width - 1, height - 1);
+ }
+ /*if (!border) pix = pix.fromImage(image);
+ //bitBlt(&pix, 0, 0, &image, 0, 0, width, height);
+ else {
+ pix.fill(black);
+ bitBlt(&pix, 1, 1, &image, 0, 0, width, height);
+ }*/
+ }
+ else pix.fill(Qt::black);
+ return pix;
+}
+
+
+QPixmap Render::extractFrame(int frame_position, int width, int height)
+{
+ QPixmap pix(width, height);
+ if (!m_mltProducer) {
+ pix.fill(Qt::black);
+ return pix;
+ }
+ Mlt::Producer *mlt_producer = m_mltProducer->cut(frame_position, frame_position + 1);
+ Mlt::Filter m_convert("avcolour_space");
+ m_convert.set("forced", mlt_image_rgb24a);
+ mlt_producer->attach(m_convert);
+ Mlt::Frame *frame = mlt_producer->get_frame();
+
+ if (frame) {
+ pix = frameThumbnail(frame, width, height);
+ delete frame;
+ }
+ else pix.fill(Qt::black);
+ delete mlt_producer;
+ return pix;
+}
+
+QPixmap Render::getImageThumbnail(KUrl url, int width, int height)
+{
+ QImage im;
+ QPixmap pixmap;
+ if (url.fileName().startsWith(".all.")) { // check for slideshow
+ QString fileType = url.fileName().right(3);
+ QStringList more;
+ QStringList::Iterator it;
+
+ QDir dir( url.directory() );
+ more = dir.entryList( QDir::Files );
+
+ for ( it = more.begin() ; it != more.end() ; ++it ) {
+ if ((*it).endsWith("."+fileType, Qt::CaseInsensitive)) {
+ im.load(url.directory() + "/" + *it);
+ break;
+ }
+ }
+ }
+ else im.load(url.path());
+ //pixmap = im.scaled(width, height);
+ return pixmap;
+}
+
+//static
+QPixmap Render::getVideoThumbnail(QString file, int frame_position, int width, int height)
+{
+ QPixmap pix(width, height);
+ char *tmp = decodedString(file);
+ Mlt::Producer m_producer(tmp);
+ delete[] tmp;
+ if (m_producer.is_blank()) {
+ pix.fill(Qt::black);
+ return pix;
+ }
+
+ Mlt::Filter m_convert("avcolour_space");
+ m_convert.set("forced", mlt_image_rgb24a);
+ m_producer.attach(m_convert);
+ m_producer.seek(frame_position);
+ Mlt::Frame * frame = m_producer.get_frame();
+ if (frame) {
+ pix = frameThumbnail(frame, width, height, true);
+ delete frame;
+ }
+ return pix;
+}
+
+
+void Render::getImage(KUrl url, int frame_position, QPoint size)
+{
+ char *tmp = decodedString(url.path());
+ Mlt::Producer m_producer(tmp);
+ delete[] tmp;
+ if (m_producer.is_blank()) {
+ return;
+ }
+ Mlt::Filter m_convert("avcolour_space");
+ m_convert.set("forced", mlt_image_rgb24a);
+ m_producer.attach(m_convert);
+ m_producer.seek(frame_position);
+
+ Mlt::Frame * frame = m_producer.get_frame();
+
+ if (frame) {
+ QPixmap pix = frameThumbnail(frame, size.x(), size.y(), true);
+ delete frame;
+ emit replyGetImage(url, frame_position, pix, size.x(), size.y());
+ }
+}
+
+/* Create thumbnail for color */
+void Render::getImage(int id, QString color, QPoint size)
+{
+ QPixmap pixmap(size.x() - 2, size.y() - 2);
+ color = color.replace(0, 2, "#");
+ color = color.left(7);
+ pixmap.fill(QColor(color));
+ QPixmap result(size.x(), size.y());
+ result.fill(Qt::black);
+ //copyBlt(&result, 1, 1, &pixmap, 0, 0, size.x() - 2, size.y() - 2);
+ emit replyGetImage(id, result, size.x(), size.y());
+
+}
+
+/* Create thumbnail for image */
+void Render::getImage(KUrl url, QPoint size)
+{
+ QImage im;
+ QPixmap pixmap;
+ if (url.fileName().startsWith(".all.")) { // check for slideshow
+ QString fileType = url.fileName().right(3);
+ QStringList more;
+ QStringList::Iterator it;
+
+ QDir dir( url.directory() );
+ more = dir.entryList( QDir::Files );
+ for ( it = more.begin() ; it != more.end() ; ++it ) {
+ if ((*it).endsWith("."+fileType, Qt::CaseInsensitive)) {
+ if (!im.load(url.directory() + "/" + *it))
+ kDebug()<<"++ ERROR LOADIN IMAGE: "<<url.directory() + "/" + *it;
+ break;
+ }
+ }
+ }
+ else im.load(url.path());
+
+ //pixmap = im.smoothScale(size.x() - 2, size.y() - 2);
+ QPixmap result(size.x(), size.y());
+ result.fill(Qt::black);
+ //copyBlt(&result, 1, 1, &pixmap, 0, 0, size.x() - 2, size.y() - 2);
+ emit replyGetImage(url, 1, result, size.x(), size.y());
+}
+
+
+double Render::consumerRatio() const
+{
+ if (!m_mltConsumer) return 1.0;
+ return (m_mltConsumer->get_double("aspect_ratio_num")/m_mltConsumer->get_double("aspect_ratio_den"));
+}
+
+
+int Render::getLength()
+{
+
+ if (m_mltProducer)
+ {
+ kDebug()<<"////// LENGTH: "<<mlt_producer_get_playtime(m_mltProducer->get_producer());
+ return mlt_producer_get_playtime(m_mltProducer->get_producer());
+ }
+ return 0;
+}
+
+bool Render::isValid(KUrl url)
+{
+ char *tmp = decodedString(url.path());
+ Mlt::Producer producer(tmp);
+ delete[] tmp;
+ if (producer.is_blank())
+ return false;
+
+ return true;
+}
+
+
+void Render::getFileProperties(const KUrl &url, uint framenb)
+{
+ int height = 40;
+ int width = height * 16/9.0; //KdenliveSettings::displayratio();
+ char *tmp = decodedString(url.path());
+ Mlt::Producer producer(tmp);
+ delete[] tmp;
+ if (producer.is_blank()) {
+ return;
+ }
+ producer.seek( framenb );
+ mlt_properties properties = MLT_PRODUCER_PROPERTIES( producer.get_producer() );
+
+ QMap < QString, QString > filePropertyMap;
+ QMap < QString, QString > metadataPropertyMap;
+
+ filePropertyMap["filename"] = url.path();
+ filePropertyMap["duration"] = QString::number(producer.get_playtime());
+
+ Mlt::Filter m_convert("avcolour_space");
+ m_convert.set("forced", mlt_image_rgb24a);
+ producer.attach(m_convert);
+
+ Mlt::Frame * frame = producer.get_frame();
+
+ if (frame->is_valid()) {
+ filePropertyMap["fps"] =
+ QString::number(mlt_producer_get_fps( producer.get_producer() ));
+ filePropertyMap["width"] =
+ QString::number(frame->get_int("width"));
+ filePropertyMap["height"] =
+ QString::number(frame->get_int("height"));
+ filePropertyMap["frequency"] =
+ QString::number(frame->get_int("frequency"));
+ filePropertyMap["channels"] =
+ QString::number(frame->get_int("channels"));
+
+ // Retrieve audio / video codec name
+
+ // Fetch the video_context
+ AVFormatContext *context = (AVFormatContext *) mlt_properties_get_data( properties, "video_context", NULL );
+ if (context != NULL) {
+ // Get the video_index
+ int index = mlt_properties_get_int( properties, "video_index" );
+ filePropertyMap["videocodec"] = context->streams[ index ]->codec->codec->name;
+ }
+ context = (AVFormatContext *) mlt_properties_get_data( properties, "audio_context", NULL );
+ if (context != NULL) {
+ // Get the video_index
+ int index = mlt_properties_get_int( properties, "audio_index" );
+ filePropertyMap["audiocodec"] = context->streams[ index ]->codec->codec->name;
+ }
+
+
+
+ // metadata
+
+ mlt_properties metadata = mlt_properties_new( );
+ mlt_properties_pass( metadata, properties, "meta.attr." );
+ int count = mlt_properties_count( metadata );
+ for ( int i = 0; i < count; i ++ )
+ {
+ QString name = mlt_properties_get_name( metadata, i );
+ QString value = QString::fromUtf8(mlt_properties_get_value( metadata, i ));
+ if (name.endsWith("markup") && !value.isEmpty())
+ metadataPropertyMap[ name.section(".", 0, -2) ] = value;
+ }
+
+ if (frame->get_int("test_image") == 0) {
+ if (url.path().endsWith(".westley") || url.path().endsWith(".kdenlive")) {
+ filePropertyMap["type"] = "playlist";
+ metadataPropertyMap["comment"] = QString::fromUtf8(mlt_properties_get( MLT_SERVICE_PROPERTIES( producer.get_service() ), "title"));
+ }
+ else if (frame->get_int("test_audio") == 0)
+ filePropertyMap["type"] = "av";
+ else
+ filePropertyMap["type"] = "video";
+
+ // Generate thumbnail for this frame
+ QPixmap pixmap = frameThumbnail(frame, width, height, true);
+
+ emit replyGetImage(url, 0, pixmap, width, height);
+
+ } else if (frame->get_int("test_audio") == 0) {
+ QPixmap pixmap(KStandardDirs::locate("appdata", "graphics/music.png"));
+ emit replyGetImage(url, 0, pixmap, width, height);
+ filePropertyMap["type"] = "audio";
+ }
+ }
+ emit replyGetFileProperties(filePropertyMap, metadataPropertyMap);
+ delete frame;
+}
+
+QDomDocument Render::sceneList() const
+{
+ return m_sceneList;
+}
+
+/** Create the producer from the Westley QDomDocument */
+void Render::initSceneList()
+{
+ kDebug()<<"-------- INIT SCENE LIST ------_";
+ QDomDocument doc;
+ QDomElement westley = doc.createElement("westley");
+ doc.appendChild(westley);
+ QDomElement prod = doc.createElement("producer");
+ prod.setAttribute("resource", "colour");
+ prod.setAttribute("colour", "red");
+ prod.setAttribute("id", "black");
+ prod.setAttribute("in", "0");
+ prod.setAttribute("out", "0");
+
+ QDomElement tractor = doc.createElement("tractor");
+ QDomElement multitrack = doc.createElement("multitrack");
+
+ QDomElement playlist1 = doc.createElement("playlist");
+ playlist1.appendChild(prod);
+ multitrack.appendChild(playlist1);
+ QDomElement playlist2 = doc.createElement("playlist");
+ multitrack.appendChild(playlist2);
+ QDomElement playlist3 = doc.createElement("playlist");
+ multitrack.appendChild(playlist3);
+ QDomElement playlist4 = doc.createElement("playlist");
+ multitrack.appendChild(playlist4);
+ QDomElement playlist5 = doc.createElement("playlist");
+ multitrack.appendChild(playlist5);
+ tractor.appendChild(multitrack);
+ westley.appendChild(tractor);
+ kDebug()<<doc.toString();
+/*
+ QString tmp = QString("<westley><producer resource=\"colour\" colour=\"red\" id=\"red\" /><tractor><multitrack><playlist></playlist><playlist></playlist><playlist /><playlist /><playlist></playlist></multitrack></tractor></westley>");*/
+ setSceneList(doc, 0);
+}
+
+
+/** Create the producer from the Westley QDomDocument */
+void Render::setSceneList(QDomDocument list, int position)
+{
+ if (!m_winid == -1) return;
+ m_generateScenelist = true;
+
+ kWarning()<<"////// RENDER, SET SCENE LIST";
+
+ Mlt::Playlist track;
+ char *tmp = decodedString(list.toString());
+ kDebug()<<" / / /STRING rESULT-----------: "<<tmp;
+ Mlt::Producer clip("westley-xml", tmp);
+ delete[] tmp;
+
+ if (!clip.is_valid()) {
+ kWarning()<<" ++++ WARNING, UNABLE TO CREATE MLT PRODUCER";
+ m_generateScenelist = false;
+ return;
+ }
+
+ track.append(clip);
+
+ if (m_mltConsumer) {
+ m_mltConsumer->set("refresh", 0);
+ if (!m_mltConsumer->is_stopped()) {
+ //emitConsumerStopped();
+ m_mltConsumer->stop();
+ }
+ }
+
+ if (m_mltProducer) {
+ m_mltProducer->set_speed(0.0);
+
+ //if (KdenliveSettings::osdtimecode() && m_osdInfo) m_mltProducer->detach(*m_osdInfo);
+
+ delete m_mltProducer;
+ m_mltProducer = NULL;
+ emit stopped();
+ }
+
+ m_mltProducer = new Mlt::Producer(clip); //track.current();
+ m_mltProducer->optimise();
+ if (position != 0) m_mltProducer->seek(position);
+
+ /*if (KdenliveSettings::osdtimecode()) {
+ // Attach filter for on screen display of timecode
+ delete m_osdInfo;
+ QString attr = "attr_check";
+ mlt_filter filter = mlt_factory_filter( "data_feed", (char*) attr.ascii() );
+ mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "_fezzik", 1 );
+ mlt_producer_attach( m_mltProducer->get_producer(), filter );
+ mlt_filter_close( filter );
+
+ m_osdInfo = new Mlt::Filter("data_show");
+ tmp = decodedString(m_osdProfile);
+ m_osdInfo->set("resource", tmp);
+ delete[] tmp;
+ mlt_properties properties = MLT_PRODUCER_PROPERTIES(m_mltProducer->get_producer());
+ mlt_properties_set_int( properties, "meta.attr.timecode", 1);
+ mlt_properties_set( properties, "meta.attr.timecode.markup", "#timecode#");
+ m_osdInfo->set("dynamic", "1");
+
+ if (m_mltProducer->attach(*m_osdInfo) == 1) kDebug()<<"////// error attaching filter";
+ } else {
+ m_osdInfo->set("dynamic", "0");
+ }*/
+
+ m_fps = m_mltProducer->get_fps();
+ if (!m_mltConsumer) {
+ restartConsumer();
+ }
+
+ m_connectTimer->start( 500 );
+ m_generateScenelist = false;
+
+}
+
+
+void Render::connectPlaylist() {
+ kDebug()<<"************** CONNECTING PLAYLIST";
+ m_connectTimer->stop();
+ if (m_mltConsumer->start() == -1) {
+ KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install or your driver settings, please fix it."));
+ m_mltConsumer = NULL;
+ }
+ else {
+ m_mltConsumer->connect(*m_mltProducer);
+ m_mltProducer->set_speed(0.0);
+ refresh();
+ }
+}
+
+void Render::refreshDisplay() {
+
+ if (!m_mltProducer) return;
+ m_mltConsumer->set("refresh", 0);
+
+ mlt_properties properties = MLT_PRODUCER_PROPERTIES(m_mltProducer->get_producer());
+ /*if (KdenliveSettings::osdtimecode()) {
+ mlt_properties_set_int( properties, "meta.attr.timecode", 1);
+ mlt_properties_set( properties, "meta.attr.timecode.markup", "#timecode#");
+ m_osdInfo->set("dynamic", "1");
+ m_mltProducer->attach(*m_osdInfo);
+ }
+ else {
+ m_mltProducer->detach(*m_osdInfo);
+ m_osdInfo->set("dynamic", "0");
+ }*/
+ refresh();
+}
+
+void Render::setVolume(double volume)
+{
+ if (!m_mltConsumer || !m_mltProducer) return;
+ /*osdTimer->stop();
+ m_mltConsumer->set("refresh", 0);
+ // Attach filter for on screen display of timecode
+ mlt_properties properties = MLT_PRODUCER_PROPERTIES(m_mltProducer->get_producer());
+ mlt_properties_set_double( properties, "meta.volume", volume );
+ mlt_properties_set_int( properties, "meta.attr.osdvolume", 1);
+ mlt_properties_set( properties, "meta.attr.osdvolume.markup", i18n("Volume: ") + QString::number(volume * 100));
+
+ if (!KdenliveSettings::osdtimecode()) {
+ m_mltProducer->detach(*m_osdInfo);
+ mlt_properties_set_int( properties, "meta.attr.timecode", 0);
+ if (m_mltProducer->attach(*m_osdInfo) == 1) kDebug()<<"////// error attaching filter";
+ }*/
+ refresh();
+ osdTimer->setSingleShot(2500 );
+}
+
+void Render::slotOsdTimeout()
+{
+ mlt_properties properties = MLT_PRODUCER_PROPERTIES(m_mltProducer->get_producer());
+ mlt_properties_set_int(properties, "meta.attr.osdvolume", 0);
+ mlt_properties_set(properties, "meta.attr.osdvolume.markup", NULL);
+ //if (!KdenliveSettings::osdtimecode()) m_mltProducer->detach(*m_osdInfo);
+ refresh();
+}
+
+void Render::start()
+{
+ if (!m_mltConsumer || m_winid == -1) {
+ restartConsumer();
+ return;
+ }
+
+ if (m_mltConsumer->is_stopped()) {
+ if (m_mltConsumer->start() == -1) {
+ KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install or your driver settings, please fix it."));
+ m_mltConsumer = NULL;
+ return;
+ }
+ else {
+ refresh();
+ }
+ }
+ isBlocked = false;
+}
+
+void Render::clear()
+{
+ if (m_mltConsumer) {
+ m_mltConsumer->set("refresh", 0);
+ if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
+ }
+
+ if (m_mltProducer) {
+ //if (KdenliveSettings::osdtimecode() && m_osdInfo) m_mltProducer->detach(*m_osdInfo);
+ m_mltProducer->set_speed(0.0);
+ delete m_mltProducer;
+ m_mltProducer = NULL;
+ emit stopped();
+ }
+}
+
+void Render::stop()
+{
+ kDebug()<<"///////////// RENDER STOP-------";
+ if (m_mltConsumer && !m_mltConsumer->is_stopped()) {
+ m_mltConsumer->set("refresh", 0);
+ m_mltConsumer->stop();
+ }
+
+ isBlocked = true;
+
+ if (m_mltProducer) {
+ m_mltProducer->set_speed(0.0);
+ m_mltProducer->set("out", m_mltProducer->get_length() - 1);
+ }
+}
+
+void Render::stop(const GenTime & startTime)
+{
+ kDebug()<<"///////////// RENDER STOP-------2";
+ if (m_mltProducer) {
+ m_mltProducer->set_speed(0.0);
+ m_mltProducer->seek((int) startTime.frames(m_fps));
+ }
+ m_mltConsumer->purge();
+}
+
+void Render::switchPlay()
+{
+ if (!m_mltProducer)
+ return;
+ if (m_mltProducer->get_speed() == 0.0) m_mltProducer->set_speed(1.0);
+ else {
+ m_mltProducer->set_speed(0.0);
+ kDebug()<<"// POSITON: "<<m_framePosition;
+ m_mltProducer->seek((int) m_framePosition);
+ }
+
+ /*if (speed == 0.0) {
+ m_mltProducer->seek((int) m_framePosition + 1);
+ m_mltConsumer->purge();
+ }*/
+ refresh();
+}
+
+void Render::play(double speed)
+{
+ if (!m_mltProducer)
+ return;
+ if (speed == 0.0) m_mltProducer->set("out", m_mltProducer->get_length() - 1);
+ m_mltProducer->set_speed(speed);
+ /*if (speed == 0.0) {
+ m_mltProducer->seek((int) m_framePosition + 1);
+ m_mltConsumer->purge();
+ }*/
+ refresh();
+}
+
+void Render::play(double speed, const GenTime & startTime)
+{
+ kDebug()<<"///////////// RENDER PLAY2-------"<<speed;
+ if (!m_mltProducer)
+ return;
+ //m_mltProducer->set("out", m_mltProducer->get_length() - 1);
+ //if (speed == 0.0) m_mltConsumer->set("refresh", 0);
+ m_mltProducer->set_speed(speed);
+ m_mltProducer->seek((int) (startTime.frames(m_fps)));
+ //m_mltConsumer->purge();
+ //refresh();
+}
+
+void Render::play(double speed, const GenTime & startTime,
+ const GenTime & stopTime)
+{
+ kDebug()<<"///////////// RENDER PLAY3-------"<<speed;
+ if (!m_mltProducer)
+ return;
+ m_mltProducer->set("out", stopTime.frames(m_fps));
+ m_mltProducer->seek((int) (startTime.frames(m_fps)));
+ m_mltConsumer->purge();
+ m_mltProducer->set_speed(speed);
+ refresh();
+}
+
+void Render::render(const KUrl & url)
+{
+ QDomDocument doc;
+ QDomElement elem = doc.createElement("render");
+ elem.setAttribute("filename", url.path());
+ doc.appendChild(elem);
+}
+
+void Render::sendSeekCommand(GenTime time)
+{
+ if (!m_mltProducer)
+ return;
+ //kDebug()<<"////////// KDENLIVE SEEK: "<<(int) (time.frames(m_fps));
+ m_mltProducer->seek((int) (time.frames(m_fps)));
+ refresh();
+}
+
+void Render::askForRefresh()
+{
+ // Use a Timer so that we don't refresh too much
+ refreshTimer->start(200 );
+}
+
+void Render::refresh()
+{
+ if (!m_mltProducer)
+ return;
+ refreshTimer->stop();
+ if (m_mltConsumer) {
+ m_mltConsumer->set("refresh", 1);
+ }
+}
+
+/** Sets the description of this renderer to desc. */
+void Render::setDescription(const QString & description)
+{
+ m_description = description;
+}
+
+/** Returns the description of this renderer */
+QString Render::description()
+{
+ return m_description;
+}
+
+
+double Render::playSpeed()
+{
+ if (m_mltProducer) return m_mltProducer->get_speed();
+ return 0.0;
+}
+
+const GenTime & Render::seekPosition() const
+{
+ if (m_mltProducer) return GenTime((int) m_mltProducer->position(), m_fps);
+ else return GenTime();
+}
+
+
+const QString & Render::rendererName() const
+{
+ return m_name;
+}
+
+
+void Render::emitFrameNumber(double position)
+{
+ kDebug()<<"// POSITON: "<<m_framePosition;
+ if (m_generateScenelist) return;
+ m_framePosition = position;
+ //if (qApp->activeWindow()) QApplication::postEvent(qApp->activeWindow(), new PositionChangeEvent( GenTime((int) position, m_fps), m_monitorId));
+}
+
+void Render::emitConsumerStopped()
+{
+ // This is used to know when the playing stopped
+ if (m_mltProducer && !m_generateScenelist) {
+ double pos = m_mltProducer->position();
+ //if (qApp->activeWindow()) QApplication::postEvent(qApp->activeWindow(), new PositionChangeEvent(GenTime((int) pos, m_fps), m_monitorId + 100));
+ //new QCustomEvent(10002));
+ }
+}
+
+
+
+void Render::exportFileToFirewire(QString srcFileName, int port, GenTime startTime, GenTime endTime)
+{
+KMessageBox::sorry(0, i18n("Firewire is not enabled on your system.\n Please install Libiec61883 and recompile Kdenlive"));
+}
+
+
+void Render::exportCurrentFrame(KUrl url, bool notify) {
+ if (!m_mltProducer) {
+ KMessageBox::sorry(qApp->activeWindow(), i18n("There is no clip, cannot extract frame."));
+ return;
+ }
+
+ int height = 1080;//KdenliveSettings::defaultheight();
+ int width = 1940; //KdenliveSettings::displaywidth();
+
+ QPixmap pix(width, height);
+
+ Mlt::Filter m_convert("avcolour_space");
+ m_convert.set("forced", mlt_image_rgb24a);
+ m_mltProducer->attach(m_convert);
+ Mlt::Frame * frame = m_mltProducer->get_frame();
+ m_mltProducer->detach(m_convert);
+ if (frame) {
+ pix = frameThumbnail(frame, width, height);
+ delete frame;
+ }
+ pix.save(url.path(), "PNG");
+ //if (notify) QApplication::postEvent(qApp->activeWindow(), new UrlEvent(url, 10003));
+}
+
+/** MLT PLAYLIST DIRECT MANIPULATON **/
+
+
+void Render::mltCheckLength()
+{
+ //kDebug()<<"checking track length: "<<track<<"..........";
+ Mlt::Service service(m_mltProducer->get_service());
+ Mlt::Tractor tractor(service);
+
+ int trackNb = tractor.count( );
+ double duration = 0;
+ double trackDuration;
+ if (trackNb == 1) {
+ Mlt::Producer trackProducer(tractor.track(0));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ duration = Mlt::Producer(trackPlaylist.get_producer()).get_playtime() - 1;
+ m_mltProducer->set("out", duration);
+ emit durationChanged();
+ return;
+ }
+ while (trackNb > 1) {
+ Mlt::Producer trackProducer(tractor.track(trackNb - 1));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ trackDuration = Mlt::Producer(trackPlaylist.get_producer()).get_playtime() - 1;
+
+ kDebug()<<" / / /DURATON FOR TRACK "<<trackNb - 1<<" = "<<trackDuration;
+ if (trackDuration > duration) duration = trackDuration;
+ trackNb--;
+ }
+
+ Mlt::Producer blackTrackProducer(tractor.track(0));
+ Mlt::Playlist blackTrackPlaylist(( mlt_playlist ) blackTrackProducer.get_service());
+ double blackDuration = Mlt::Producer(blackTrackPlaylist.get_producer()).get_playtime() - 1;
+ kDebug()<<" / / /DURATON FOR TRACK 0 = "<<blackDuration;
+ if (blackDuration != duration) {
+ blackTrackPlaylist.remove_region( 0, blackDuration );
+ int i = 0;
+ int dur = duration;
+
+ while (dur > 14000) { // <producer mlt_service=\"colour\" colour=\"black\" in=\"0\" out=\"13999\" />
+ mltInsertClip(0, GenTime(i * 14000, m_fps), QString("<westley><producer mlt_service=\"colour\" colour=\"black\" in=\"0\" out=\"13999\" /></westley>"));
+ dur = dur - 14000;
+ i++;
+ }
+
+ mltInsertClip(0, GenTime(), QString("<westley><producer mlt_service=\"colour\" colour=\"black\" in=\"0\" out=\"" + QString::number(dur) + "\" /></westley>"));
+
+ m_mltProducer->set("out", duration);
+ emit durationChanged();
+ }
+}
+
+
+void Render::mltInsertClip(int track, GenTime position, QString resource)
+{
+ if (!m_mltProducer) {
+ kDebug()<<"PLAYLISTÂ NOT INITIALISED //////";
+ return;
+ }
+ Mlt::Producer parentProd(m_mltProducer->parent());
+ if (parentProd.get_producer() == NULL) {
+ kDebug()<<"PLAYLISTÂ BROKEN, CANNOT INSERTÂ CLIP //////";
+ return;
+ }
+ Mlt::Service service(parentProd.get_service());
+ Mlt::Tractor tractor(service);
+
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ char *tmp = decodedString(resource);
+ Mlt::Producer clip("westley-xml", tmp);
+ //clip.set_in_and_out(in.frames(m_fps), out.frames(m_fps));
+ delete[] tmp;
+
+ trackPlaylist.insert_at(position.frames(m_fps), clip, 1);
+ tractor.multitrack()->refresh();
+ tractor.refresh();
+ if (track != 0) mltCheckLength();
+ double duration = Mlt::Producer(trackPlaylist.get_producer()).get_playtime();
+ kDebug()<<"// + +INSERTING CLIP: "<<resource<<" AT: "<<position.frames(m_fps)<<" on track: "<<track<<", DURATION: "<<duration;
+
+
+}
+
+void Render::mltCutClip(int track, GenTime position)
+{
+ Mlt::Service service(m_mltProducer->parent().get_service());
+ if (service.type() == playlist_type) kDebug()<<"// PLAYLIST TYPE";
+ if (service.type() == tractor_type) kDebug()<<"// TRACOT TYPE";
+ if (service.type() == multitrack_type) kDebug()<<"// MULTITRACK TYPE";
+ if (service.type() == producer_type) kDebug()<<"// PROD TYPE";
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ trackPlaylist.split_at(position.frames(m_fps));
+ trackPlaylist.consolidate_blanks(0);
+ kDebug()<<"/ / / /CUTTING CLIP AT: "<<position.frames(m_fps);
+}
+
+
+void Render::mltRemoveClip(int track, GenTime position)
+{
+ Mlt::Service service(m_mltProducer->parent().get_service());
+ if (service.type() == playlist_type) kDebug()<<"// PLAYLIST TYPE";
+ if (service.type() == tractor_type) kDebug()<<"// TRACOT TYPE";
+ if (service.type() == multitrack_type) kDebug()<<"// MULTITRACK TYPE";
+ if (service.type() == producer_type) kDebug()<<"// PROD TYPE";
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
+ //trackPlaylist.remove(clipIndex);
+ trackPlaylist.replace_with_blank(clipIndex);
+ trackPlaylist.consolidate_blanks(0);
+ if (track != 0) mltCheckLength();
+ //emit durationChanged();
+}
+
+void Render::mltRemoveEffect(int track, GenTime position, QString id, QString tag, int index)
+{
+ Mlt::Service service(m_mltProducer->parent().get_service());
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ //int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
+ Mlt::Producer *clip = trackPlaylist.get_clip_at(position.frames(m_fps));
+ if (!clip) {
+ kDebug()<<" / / / CANNOT FIND CLIP TO REMOVE EFFECT";
+ return;
+ }
+ Mlt::Service clipService(clip->get_service());
+
+ if (tag.startsWith("ladspa")) tag = "ladspa";
+
+ if (index == -1) {
+ int ct = 0;
+ Mlt::Filter *filter = clipService.filter( ct );
+ while (filter) {
+ if (filter->get("mlt_service") == tag && filter->get("kdenlive_id") == id) {
+ clipService.detach(*filter);
+ kDebug()<<" / / / DLEETED EFFECT: "<<ct;
+ }
+ else ct++;
+ filter = clipService.filter( ct );
+ }
+ }
+ else {
+ Mlt::Filter *filter = clipService.filter( index );
+ if (filter && filter->get("mlt_service") == tag && filter->get("kdenlive_id") == id) clipService.detach(*filter);
+ else {
+ kDebug()<<"WARINIG, FILTER "<<id<<" NOT FOUND!!!!!";
+ }
+ }
+ refresh();
+}
+
+
+void Render::mltAddEffect(int track, GenTime position, QString id, QString tag, QMap <QString, QString> args)
+{
+ Mlt::Service service(m_mltProducer->parent().get_service());
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+
+ Mlt::Producer *clip = trackPlaylist.get_clip_at(position.frames(m_fps));
+
+ if (!clip) {
+ kDebug()<<"********** CANNOT FIND CLIP TO APPLY EFFECT-----------";
+ return;
+ }
+ Mlt::Service clipService(clip->get_service());
+
+ // create filter
+ kDebug()<<" / / INSERTING EFFECT: "<<id;
+ if (tag.startsWith("ladspa")) tag = "ladspa";
+ char *filterId = decodedString(tag);
+ Mlt::Filter *filter = new Mlt::Filter(filterId);
+ filter->set("kdenlive_id", filterId);
+
+ QMap<QString, QString>::Iterator it;
+ QString keyFrameNumber = "#0";
+
+ for ( it = args.begin(); it != args.end(); ++it ) {
+ //kDebug()<<" / / INSERTING EFFECT ARGS: "<<it.key()<<": "<<it.data();
+ QString key;
+ QString currentKeyFrameNumber;
+ if (it.key().startsWith("#")) {
+ currentKeyFrameNumber = it.key().section(":", 0, 0);
+ if (currentKeyFrameNumber != keyFrameNumber) {
+ // attach filter to the clip
+ clipService.attach(*filter);
+ filter = new Mlt::Filter(filterId);
+ filter->set("kdenlive_id", filterId);
+ keyFrameNumber = currentKeyFrameNumber;
+ }
+ key = it.key().section(":", 1);
+ }
+ else key = it.key();
+ char *name = decodedString(key);
+ char *value = decodedString(it.value());
+ filter->set(name, value);
+ delete[] name;
+ delete[] value;
+ }
+ // attach filter to the clip
+ clipService.attach(*filter);
+ delete[] filterId;
+ refresh();
+
+}
+
+void Render::mltEditEffect(int track, GenTime position, int index, QString id, QString tag, QMap <QString, QString> args)
+{
+ QMap<QString, QString>::Iterator it = args.begin();
+ if (it.key().startsWith("#") || tag.startsWith("ladspa") || tag == "sox" || tag == "autotrack_rectangle") {
+ // This is a keyframe effect, to edit it, we remove it and re-add it.
+ mltRemoveEffect(track, position, id, tag, -1);
+ mltAddEffect(track, position, id, tag, args);
+ return;
+ }
+
+ // create filter
+ Mlt::Service service(m_mltProducer->parent().get_service());
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ //int clipIndex = trackPlaylist.get_clip_index_at(position.frames(m_fps));
+ Mlt::Producer *clip = trackPlaylist.get_clip_at(position.frames(m_fps));
+ Mlt::Service clipService(clip->get_service());
+ Mlt::Filter *filter = clipService.filter( index );
+
+
+ if (!filter || filter->get("mlt_service") != tag) {
+ kDebug()<<"WARINIG, FILTER NOT FOUND!!!!!";
+ int index = 0;
+ filter = clipService.filter( index );
+ while (filter) {
+ if (filter->get("mlt_service") == tag && filter->get("kdenlive_id") == id) break;
+ index++;
+ filter = clipService.filter( index );
+ }
+ }
+ if (!filter) {
+ kDebug()<<"WARINIG, FILTER "<<id<<" NOT FOUND!!!!!";
+ return;
+ }
+
+ for ( it = args.begin(); it != args.end(); ++it ) {
+ kDebug()<<" / / INSERTING EFFECT ARGS: "<<it.key()<<": "<<it.value();
+ char *name = decodedString(it.key());
+ char *value = decodedString(it.value());
+ filter->set(name, value);
+ delete[] name;
+ delete[] value;
+ }
+ refresh();
+}
+
+void Render::mltResizeClipEnd(int track, GenTime pos, GenTime in, GenTime out)
+{
+ Mlt::Service service(m_mltProducer->parent().get_service());
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ if (trackPlaylist.is_blank_at(pos.frames(m_fps) + 1))
+ kDebug()<<"//////// ERROR RSIZING BLANK CLIP!!!!!!!!!!!";
+ int clipIndex = trackPlaylist.get_clip_index_at(pos.frames(m_fps) + 1);
+
+ int previousDuration = trackPlaylist.clip_length(clipIndex) - 1;
+ int newDuration = out.frames(m_fps) - 1;
+
+ kDebug()<<" ** RESIZING CLIP END:" << clipIndex << " on track:"<< track <<", mid pos: "<<pos.frames(25)<<", in: "<<in.frames(25)<<", out: "<<out.frames(25)<<", PREVIOUS duration: "<<previousDuration;
+ trackPlaylist.resize_clip(clipIndex, in.frames(m_fps), newDuration);
+ trackPlaylist.consolidate_blanks(0);
+ if (previousDuration < newDuration) {
+ // clip was made longer, trim next blank if there is one.
+ if (trackPlaylist.is_blank(clipIndex + 1)) {
+ trackPlaylist.split(clipIndex + 1, newDuration - previousDuration);
+ trackPlaylist.remove(clipIndex + 1);
+ }
+ }
+ else trackPlaylist.insert_blank(clipIndex + 1, previousDuration - newDuration - 1);
+
+ trackPlaylist.consolidate_blanks(0);
+ tractor.multitrack()->refresh();
+ tractor.refresh();
+ if (track != 0) mltCheckLength();
+
+}
+
+void Render::mltChangeTrackState(int track, bool mute, bool blind)
+{
+ Mlt::Service service(m_mltProducer->parent().get_service());
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ if (mute) {
+ if (blind) trackProducer.set("hide", 3);
+ else trackProducer.set("hide", 2);
+ }
+ else if (blind) {
+ trackProducer.set("hide", 1);
+ }
+ else {
+ trackProducer.set("hide", 0);
+ }
+ tractor.multitrack()->refresh();
+ tractor.refresh();
+ refresh();
+}
+
+void Render::mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime moveStart, GenTime in, GenTime out)
+{
+ Mlt::Service service(m_mltProducer->parent().get_service());
+ if (service.type() == playlist_type) kDebug()<<"// PLAYLIST TYPE";
+ if (service.type() == tractor_type) kDebug()<<"// TRACOT TYPE";
+ if (service.type() == multitrack_type) kDebug()<<"// MULTITRACK TYPE";
+ if (service.type() == producer_type) kDebug()<<"// PROD TYPE";
+
+ int moveFrame = (moveEnd - moveStart).frames(m_fps);
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(track));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ if (trackPlaylist.is_blank_at(pos.frames(m_fps) - 1))
+ kDebug()<<"//////// ERROR RSIZING BLANK CLIP!!!!!!!!!!!";
+ int clipIndex = trackPlaylist.get_clip_index_at(pos.frames(m_fps) - 1);
+ kDebug()<<" ** RESIZING CLIP START:" << clipIndex << " on track:"<< track <<", mid pos: "<<pos.frames(25)<<", moving: "<<moveFrame<<", in: "<<in.frames(25)<<", out: "<<out.frames(25);
+
+ trackPlaylist.resize_clip(clipIndex, in.frames(m_fps), out.frames(m_fps));
+ if (moveFrame > 0) trackPlaylist.insert_blank(clipIndex, moveFrame - 1);
+ else {
+ int midpos = moveStart.frames(m_fps) - 1; //+ (moveFrame / 2)
+ int blankIndex = trackPlaylist.get_clip_index_at(midpos);
+ int blankLength = trackPlaylist.clip_length(blankIndex);
+
+ kDebug()<<" + resizing blank: "<<blankIndex<<", Mid: "<<midpos<<", Length: "<<blankLength<< ", SIZE DIFF: "<<moveFrame;
+
+
+ if (blankLength + moveFrame == 0) trackPlaylist.remove(blankIndex);
+ else trackPlaylist.resize_clip(blankIndex, 0, blankLength + moveFrame -1);
+ }
+ trackPlaylist.consolidate_blanks(0);
+
+ kDebug()<<"-----------------\n"<<"CLIP 0: "<<trackPlaylist.clip_start(0)<<", LENGT: "<<trackPlaylist.clip_length(0);
+ kDebug()<<"CLIP 1: "<<trackPlaylist.clip_start(1)<<", LENGT: "<<trackPlaylist.clip_length(1);
+ kDebug()<<"CLIP 2: "<<trackPlaylist.clip_start(2)<<", LENGT: "<<trackPlaylist.clip_length(2);
+ kDebug()<<"CLIP 3: "<<trackPlaylist.clip_start(3)<<", LENGT: "<<trackPlaylist.clip_length(3);
+ kDebug()<<"CLIP 4: "<<trackPlaylist.clip_start(4)<<", LENGT: "<<trackPlaylist.clip_length(4);
+}
+
+void Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTime moveEnd)
+{
+ mltMoveClip(startTrack, endTrack, (int) moveStart.frames(m_fps), (int) moveEnd.frames(m_fps));
+}
+
+
+void Render::mltMoveClip(int startTrack, int endTrack, int moveStart, int moveEnd)
+{
+ m_mltConsumer->set("refresh", 0);
+ Mlt::Service service(m_mltProducer->parent().get_service());
+
+ Mlt::Tractor tractor(service);
+ Mlt::Producer trackProducer(tractor.track(startTrack));
+ Mlt::Playlist trackPlaylist(( mlt_playlist ) trackProducer.get_service());
+ int clipIndex = trackPlaylist.get_clip_index_at(moveStart + 1);
+
+
+ mlt_field field = mlt_tractor_field(tractor.get_tractor());
+
+ mlt_multitrack multitrack = mlt_field_multitrack(field); //mlt_tractor_multitrack(tractor.get_tractor());
+ kDebug()<<" -- CURRENT MULTIOTRACK HAS: "<<mlt_multitrack_count(multitrack)<<" tracks";;
+ mlt_service multiprod = mlt_multitrack_service( multitrack );
+
+ Mlt::Producer clipProducer(trackPlaylist.replace_with_blank(clipIndex));
+ trackPlaylist.consolidate_blanks(0);
+ mlt_events_block( MLT_PRODUCER_PROPERTIES(clipProducer.get_producer()), NULL );
+
+ if (endTrack == startTrack) {
+ if (!trackPlaylist.is_blank_at(moveEnd)) {
+ kWarning()<<"// ERROR, CLIP COLLISION----------";
+ int ix = trackPlaylist.get_clip_index_at(moveEnd);
+ kDebug()<<"BAD CLIP STARTS AT: "<<trackPlaylist.clip_start(ix)<<", LENGT: "<<trackPlaylist.clip_length(ix);
+ }
+ trackPlaylist.insert_at(moveEnd, clipProducer, 1);
+ trackPlaylist.consolidate_blanks(0);
+ }
+ else {
+ trackPlaylist.consolidate_blanks(0);
+ Mlt::Producer destTrackProducer(tractor.track(endTrack));
+ Mlt::Playlist destTrackPlaylist(( mlt_playlist ) destTrackProducer.get_service());
+ destTrackPlaylist.consolidate_blanks(1);
+ destTrackPlaylist.insert_at(moveEnd, clipProducer, 1);
+ destTrackPlaylist.consolidate_blanks(0);
+ }
+
+ mltCheckLength();
+ mlt_events_unblock( MLT_PRODUCER_PROPERTIES(clipProducer.get_producer()), NULL );
+}
+
+void Render::mltMoveTransition(QString type, int startTrack, int trackOffset, GenTime oldIn, GenTime oldOut, GenTime newIn, GenTime newOut)
+{
+ m_mltConsumer->set("refresh", 0);
+ mlt_service serv = m_mltProducer->parent().get_service();
+
+ mlt_service nextservice = mlt_service_get_producer(serv);
+ mlt_properties properties = MLT_SERVICE_PROPERTIES( nextservice );
+ QString mlt_type = mlt_properties_get( properties, "mlt_type" );
+ QString resource = mlt_properties_get( properties, "mlt_service");
+ int old_pos = (oldIn.frames(m_fps) + oldOut.frames(m_fps)) / 2;
+
+ int new_in = newIn.frames(m_fps);
+ int new_out = newOut.frames(m_fps) - 1;
+ while (mlt_type == "transition") {
+ mlt_transition tr = (mlt_transition) nextservice;
+ int currentTrack = mlt_transition_get_b_track(tr);
+ int currentIn = (int) mlt_transition_get_in(tr);
+ int currentOut = (int) mlt_transition_get_out(tr);
+ kDebug()<<"// FOUND EXISTING TRANS, IN: "<<currentIn<<", OUT: "<<currentOut<<", TRACK: "<<currentTrack;
+ //kDebug()<<"// LOOKING FOR IN: "<<old_in<<", OUT: "<<old_out;
+ kDebug()<<"// OLD IN: "<<oldIn.frames(m_fps)<<" // OLD OUT: "<<oldOut.frames(m_fps)<<", TRACK: "<<startTrack<<", MID POS: "<<old_pos;
+ if (resource == type && startTrack == currentTrack && currentIn <= old_pos && currentOut >= old_pos) {
+ mlt_transition_set_in_and_out(tr, new_in, new_out);
+ if (trackOffset != 0) {
+ mlt_properties properties = MLT_TRANSITION_PROPERTIES( tr );
+ mlt_properties_set_int( properties, "a_track", mlt_transition_get_a_track(tr) + trackOffset );
+ mlt_properties_set_int( properties, "b_track", mlt_transition_get_b_track(tr) + trackOffset );
+ }
+ break;
+ }
+ nextservice = mlt_service_producer(nextservice);
+ properties = MLT_SERVICE_PROPERTIES( nextservice );
+ mlt_type = mlt_properties_get( properties, "mlt_type" );
+ resource = mlt_properties_get( properties, "mlt_service" );
+ }
+}
+
+void Render::mltAddTransition(QString tag, int a_track, int b_track, GenTime in, GenTime out, QMap <QString, QString> args)
+{
+ Mlt::Service service(m_mltProducer->parent().get_service());
+
+ Mlt::Tractor tractor(service);
+ Mlt::Field *field = tractor.field();
+
+ char *transId = decodedString(tag);
+ Mlt::Transition *transition = new Mlt::Transition(transId);
+ transition->set_in_and_out((int) in.frames(m_fps), (int) out.frames(m_fps));
+ QMap<QString, QString>::Iterator it;
+ QString key;
+
+ kDebug()<<" ------ ADDING TRANSITION PARAMs: "<<args.count();
+
+ for ( it = args.begin(); it != args.end(); ++it ) {
+ key = it.key();
+ char *name = decodedString(key);
+ char *value = decodedString(it.value());
+ transition->set(name, value);
+ kDebug()<<" ------ ADDING TRANS PARAM: "<<name<<": "<<value;
+ //filter->set("kdenlive_id", id);
+ delete[] name;
+ delete[] value;
+ }
+ // attach filter to the clip
+ field->plant_transition(*transition, a_track, b_track);
+ delete[] transId;
+ refresh();
+
+}
+
+void Render::mltSavePlaylist()
+{
+ kWarning()<<"// UPDATING PLAYLIST TO DISK++++++++++++++++";
+ Mlt::Consumer *fileConsumer = new Mlt::Consumer("westley");
+ fileConsumer->set("resource", "/home/one/playlist.xml");
+
+ Mlt::Service service(m_mltProducer->get_service());
+ Mlt::Tractor tractor(service);
+
+ fileConsumer->connect(service);
+ fileConsumer->start();
+
+}
+
+#include "renderer.moc"
--- /dev/null
+/***************************************************************************
+ krender.h - description
+ -------------------
+ begin : Fri Nov 22 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRENDER_H
+#define KRENDER_H
+
+#include <qdom.h>
+#include <qstring.h>
+#include <qmap.h>
+#include <QList>
+#include <QWidget>
+
+#include <kurl.h>
+
+#include "gentime.h"
+/*#include "docclipref.h"
+#include "effectdesc.h"
+#include "effectparamdescfactory.h"*/
+
+/**Render encapsulates the client side of the interface to a renderer.
+From Kdenlive's point of view, you treat the Render object as the
+renderer, and simply use it as if it was local. Calls are asyncrhonous -
+you send a call out, and then recieve the return value through the
+relevant signal that get's emitted once the call completes.
+ *@author Jason Wood
+ */
+
+class Render;
+//class EffectParamDesc;
+class QPixmap;
+
+namespace Mlt {
+ class Consumer;
+ class Playlist;
+ class Tractor;
+ class Frame;
+ class Producer;
+ class Filter;
+
+ class Multitrack;
+};
+
+
+
+class Render:public QObject {
+ Q_OBJECT public:
+
+ enum FailStates { OK = 0,
+ APP_NOEXIST
+ };
+
+ Render(const QString & rendererName, QWidget *parent = 0);
+ ~Render();
+
+ /** Wraps the VEML command of the same name; requests that the renderer
+ should create a video window. If show is true, then the window should be
+ displayed, otherwise it should be hidden. Render will emit the signal
+ replyCreateVideoXWindow() once the renderer has replied. */
+ void createVideoXWindow(WId winid, WId externalMonitor);
+ /** Seeks the renderer clip to the given time. */
+ void seek(GenTime time);
+
+ static QPixmap getVideoThumbnail(QString file, int frame, int width, int height);
+ QPixmap getImageThumbnail(KUrl url, int width, int height);
+
+ /** Return thumbnail for color clip */
+ void getImage(int id, QString color, QPoint size);
+
+ static QPixmap frameThumbnail(Mlt::Frame *frame, int width, int height, bool border = false);
+
+ /** Return thumbnail for image clip */
+ void getImage(KUrl url, QPoint size);
+
+ /** Requests a particular frame from the given file.
+ *
+ * The pixmap will be returned by emitting the replyGetImage() signal.
+ * */
+ void getImage(KUrl url, int frame, QPoint size);
+
+ /** Wraps the VEML command of the same name. Sets the current scene list to
+ be list. */
+ void setSceneList(QDomDocument list, int position = 0);
+
+ /** Wraps the VEML command of the same name. Tells the renderer to
+ play the current scene at the speed specified, relative to normal
+ playback. e.g. 1.0 is normal speed, 0.0 is paused, -1.0 means play
+ backwards. Does not specify start/stop times for playback.*/
+ void play(double speed);
+ void switchPlay();
+ /** stop playing */
+ void stop(const GenTime & startTime);
+ void setVolume(double volume);
+
+ QPixmap extractFrame(int frame_position, int width, int height);
+ /** Wraps the VEML command of the same name. Tells the renderer to
+ play the current scene at the speed specified, relative to normal
+ playback. e.g. 1.0 is normal speed, 0.0 is paused, -1.0 means play
+ backwards. Specifes the start/stop times for playback.*/
+ void play(double speed, const GenTime & startTime);
+ void play(double speed, const GenTime & startTime,
+ const GenTime & stopTime);
+ /** Wraps the VEML command of the same name - render the currently
+ specified sceneList - set with setSceneList() - to the document
+ name specified. */
+ void render(const KUrl & url);
+
+ /** Returns the description of this renderer */
+ QString description();
+
+ /** Returns the name of the renderer. */
+ const QString & rendererName() const;
+
+ /** Returns the speed at which the renderer is currently playing, 0.0 if the renderer is
+ not playing anything. */
+ double playSpeed();
+ /** Returns the current seek position of the renderer. */
+ const GenTime & seekPosition() const;
+
+ void emitFrameNumber(double position);
+ void emitConsumerStopped();
+
+ /** Gives the aspect ratio of the consumer */
+ double consumerRatio() const;
+
+ /** Gives the aspect ratio of the consumer */
+ void askForRefresh();
+
+ /** Save current producer frame as image */
+ void exportCurrentFrame(KUrl url, bool notify);
+
+ /** Turn on or off on screen display */
+ void refreshDisplay();
+ /** returns the current scenelist */
+ QDomDocument sceneList() const;
+ int resetRendererProfile(char * profile);
+ bool isBlocked;
+
+ /** Playlist manipulation */
+ void mltInsertClip(int track, GenTime position, QString resource);
+ void mltCutClip(int track, GenTime position);
+ void mltResizeClipEnd(int track, GenTime pos, GenTime in, GenTime out);
+ void mltResizeClipStart(int track, GenTime pos, GenTime moveEnd, GenTime moveStart, GenTime in, GenTime out);
+ void mltMoveClip(int startTrack, int endTrack, GenTime pos, GenTime moveStart);
+ void mltMoveClip(int startTrack, int endTrack, int pos, int moveStart);
+ void mltRemoveClip(int track, GenTime position);
+ void mltRemoveEffect(int track, GenTime position, QString id, QString tag, int index);
+ void mltAddEffect(int track, GenTime position, QString id, QString tag, QMap <QString, QString> args);
+ void mltEditEffect(int track, GenTime position, int index, QString id, QString tag, QMap <QString, QString> args);
+ void mltChangeTrackState(int track, bool mute, bool blind);
+ void mltMoveTransition(QString type, int startTrack, int trackOffset, GenTime oldIn, GenTime oldOut, GenTime newIn, GenTime newOut);
+ void mltAddTransition(QString tag, int a_track, int b_track, GenTime in, GenTime out, QMap <QString, QString> args);
+
+
+ private: // Private attributes & methods
+ /** The name of this renderer - useful to identify the renderes by what they do - e.g. background rendering, workspace monitor, etc... */
+ QString m_name;
+ Mlt::Consumer * m_mltConsumer;
+ Mlt::Producer * m_mltProducer;
+ Mlt::Producer *m_mltTextProducer;
+ Mlt::Filter *m_osdInfo;
+ double m_framePosition;
+ double m_fps;
+ uint m_monitorId;
+ bool m_generateScenelist;
+
+ /** Holds the path to on screen display profile */
+ QString m_osdProfile;
+
+ QTimer *refreshTimer;
+ QTimer *osdTimer;
+ QTimer *m_connectTimer;
+ KUrl m_exportedFile;
+ int exportDuration, firstExportFrame, lastExportFrame;
+
+ /** Holds the scenelist to be sent, if pending. */
+ QDomDocument m_sceneList;
+
+ /** A human-readable description of this renderer. */
+ QString m_description;
+ int m_winid;
+ int m_externalwinid;
+ /** The actually seek command, private so people can't avoid the buffering of multiple seek commands. */
+ void sendSeekCommand(GenTime time);
+
+ /** Sets the description of this renderer to desc. */
+ void setDescription(const QString & description);
+ void closeMlt();
+ void mltCheckLength();
+
+ private slots: // Private slots
+ /** refresh monitor display */
+ void refresh();
+ void slotOsdTimeout();
+ void restartConsumer();
+ void connectPlaylist();
+ void initSceneList();
+
+ signals: // Signals
+ /** This signal is emitted once a reply to createVideoXWidow() has been recieved. */
+ void replyCreateVideoXWindow(WId);
+ /** emitted when the renderer recieves a reply to a getFileProperties request. */
+ void replyGetFileProperties(const QMap < QString, QString > &, const QMap < QString, QString > &);
+
+ /** emitted when the renderer recieves a reply to a getImage request. */
+ void replyGetImage(const KUrl &, int, const QPixmap &, int, int);
+ void replyGetImage(int, const QPixmap &, int, int);
+
+ /** Emitted when the renderer stops, either playing or rendering. */
+ void stopped();
+ /** Emitted when the renderer starts playing. */
+ void playing(double);
+ /** Emitted when the renderer is rendering. */
+ void rendering(const GenTime &);
+ /** Emitted when rendering has finished */
+ void renderFinished();
+ /** Emitted when the current seek position has been changed by the renderer. */
+// void positionChanged(const GenTime &);
+ /** Emitted when an error occurs within this renderer. */
+ void error(const QString &, const QString &);
+ void durationChanged();
+
+
+ public slots: // Public slots
+ /** Start Consumer */
+ void start();
+ /** Stop Consumer */
+ void stop();
+ void clear();
+ int getLength();
+ /** If the file is readable by mlt, return true, otherwise false */
+ bool isValid(KUrl url);
+
+ /** Wraps the VEML command of the same name. Requests the file properties
+ for the specified url from the renderer. Upon return, the result will be emitted
+ via replyGetFileProperties(). */
+ void getFileProperties(const KUrl &url, uint framenb = 0);
+
+ void exportFileToFirewire(QString srcFileName, int port, GenTime startTime, GenTime endTime);
+ static char *decodedString(QString str);
+ void mltSavePlaylist();
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ timecode - description
+ -------------------
+ begin : Wed Dec 17 2003
+ copyright : (C) 2003 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 "timecode.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+
+Timecode::Timecode(Formats format, int framesPerSecond,
+ bool dropFrame):m_format(format), m_dropFrame(dropFrame),
+m_displayedFramesPerSecond(framesPerSecond)
+{
+}
+
+Timecode::~Timecode()
+{
+}
+
+int Timecode::getFrameNumber(const QString duration, double fps) const
+{
+ if (m_dropFrame) {
+ // calculate how many frames need to be dropped every minute.
+ int frames;
+ int toDrop = (int) floor (600.0 * (m_displayedFramesPerSecond - fps) + 0.5);
+
+ int perMinute = toDrop / 9;
+ int tenthMinute = toDrop % 9;
+
+ // calculate how many frames are in a normal minute, and how many are in a tenth minute.
+ int normalMinuteFrames = (m_displayedFramesPerSecond * 60) - perMinute;
+ int tenthMinuteFrames = (m_displayedFramesPerSecond * 60) - tenthMinute;;
+
+ // Number of actual frames in a 10 minute interval :
+ int tenMinutes = (normalMinuteFrames * 9) + tenthMinuteFrames;
+ frames = 6 * duration.section(":",0,0).toInt() * tenMinutes;
+ int minutes = duration.section(":",1,1).toInt();
+ frames += ((int) minutes / 10) * tenMinutes;
+ int mins = minutes % 10;
+ if (mins > 0) {
+ frames += tenthMinuteFrames;
+ mins--;
+ if (mins > 0) frames += mins * normalMinuteFrames;
+ }
+ if (minutes % 10 > 0) frames -= perMinute;
+ frames += duration.section(":",2,2).toInt() * m_displayedFramesPerSecond + duration.section(":",3,3).toInt();
+ return frames;
+ }
+ return (int) ((duration.section(":",0,0).toInt()*3600.0 + duration.section(":",1,1).toInt()*60.0 + duration.section(":",2,2).toInt()) * fps + duration.section(":",3,3).toInt());
+}
+
+QString Timecode::getTimecode(const GenTime & time, double fps) const
+{
+ switch (m_format) {
+ case HH_MM_SS_FF:
+ return getTimecodeHH_MM_SS_FF(time, fps);
+ break;
+ case HH_MM_SS_HH:
+ return getTimecodeHH_MM_SS_HH(time);
+ break;
+ case Frames:
+ return getTimecodeFrames(time, fps);
+ break;
+ case Seconds:
+ return getTimecodeSeconds(time);
+ break;
+ default:
+ kWarning() <<
+ "Unknown timecode format specified, defaulting to HH_MM_SS_FF"
+ << endl;
+ return getTimecodeHH_MM_SS_FF(time, fps);
+ }
+}
+
+QString Timecode::getTimecodeFromFrames(int frames)
+{
+ return getTimecodeHH_MM_SS_FF(frames);
+}
+
+//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);
+ int seconds = frames / (int) floor(fps + 0.5);
+ frames = frames % ((int) fps);
+
+ int minutes = seconds / 60;
+ seconds = seconds % 60;
+ int hours = minutes / 60;
+ minutes = minutes % 60;
+
+ QString text;
+ bool trim = false;
+
+ 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;
+}
+
+
+QString Timecode::getTimecodeHH_MM_SS_FF(const GenTime & time, double fps) const
+{
+ if (m_dropFrame)
+ return getTimecodeDropFrame(time, fps);
+
+ return getTimecodeHH_MM_SS_FF((int)time.frames(fps));
+}
+
+QString Timecode::getTimecodeHH_MM_SS_FF(int frames) const
+{
+ int seconds = frames / m_displayedFramesPerSecond;
+ frames = frames % m_displayedFramesPerSecond;
+
+ int minutes = seconds / 60;
+ seconds = seconds % 60;
+ int hours = minutes / 60;
+ minutes = minutes % 60;
+
+ QString text;
+
+ 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));
+ text.append(":");
+ text.append(QString::number(frames).rightJustified(2, '0', FALSE));
+
+ return text;
+}
+
+QString Timecode::getTimecodeHH_MM_SS_HH(const GenTime & time) const
+{
+ int hundredths = (int)(time.seconds() * 100);
+ int seconds = hundredths / 100;
+ hundredths = hundredths % 100;
+ int minutes = seconds / 60;
+ seconds = seconds % 60;
+ int hours = minutes / 60;
+ minutes = minutes % 60;
+
+ QString text;
+
+ 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));
+ text.append(":");
+ text.append(QString::number(hundredths).rightJustified(2, '0', FALSE));
+
+ return text;
+}
+
+QString Timecode::getTimecodeFrames(const GenTime & time, double fps) const
+{
+ return QString::number(time.frames(fps));
+}
+
+QString Timecode::getTimecodeSeconds(const GenTime & time) const
+{
+ return QString::number(time.seconds());
+}
+
+QString Timecode::getTimecodeDropFrame(const GenTime & time, double fps) const
+{
+ // Calculate the timecode using dropframes to remove the difference in fps. Note that this algorithm should work
+ // for NTSC times, but is untested for any others - it is in no way an "official" algorithm, unless it's by fluke.
+ int frames = (int)time.frames(fps);
+
+ // calculate how many frames need to be dropped every minute.
+ int toDrop = (int) floor (600.0 * (m_displayedFramesPerSecond - fps) + 0.5);
+
+ int perMinute = toDrop / 9;
+ int tenthMinute = toDrop % 9;
+
+ // calculate how many frames are in a normal minute, and how many are in a tenth minute.
+ int normalMinuteFrames = (m_displayedFramesPerSecond * 60) - perMinute;
+ int tenthMinuteFrames = (m_displayedFramesPerSecond * 60) - tenthMinute;;
+
+ // Number of actual frames in a 10 minute interval :
+ int tenMinutes = (normalMinuteFrames * 9) + tenthMinuteFrames;
+
+ int tenMinuteIntervals = frames / tenMinutes;
+ frames = frames % tenMinutes;
+
+ int hours = tenMinuteIntervals / 6;
+ tenMinuteIntervals = tenMinuteIntervals % 6;
+
+ // At the point, we have figured out HH:M?:??:??
+
+ int numMinutes;
+
+ if (frames < tenthMinuteFrames) {
+ // tenth minute logic applies.
+ numMinutes = 0;
+ } else {
+ // normal minute logic applies.
+ numMinutes = 1 + (frames - tenthMinuteFrames) / normalMinuteFrames;
+ frames = (frames - tenthMinuteFrames) % normalMinuteFrames;
+ frames += tenthMinute + perMinute;
+ }
+ // We now have HH:MM:??:??
+
+ int seconds = frames / m_displayedFramesPerSecond;
+ frames = frames % m_displayedFramesPerSecond;
+
+ // We now have HH:MM:SS:FF
+
+ // THANK FUCK FOR THAT.
+
+ QString text;
+ text.append(QString::number(hours).rightJustified(2, '0', FALSE));
+ text.append(":");
+ text.append(QString::number(tenMinuteIntervals));
+ text.append(QString::number(numMinutes));
+ text.append(":");
+ text.append(QString::number(seconds).rightJustified(2, '0', FALSE));
+ text.append(":");
+ text.append(QString::number(frames).rightJustified(2, '0', FALSE));
+
+ return text;
+}
--- /dev/null
+/***************************************************************************
+ timecode - description
+ -------------------
+ begin : Wed Dec 17 2003
+ copyright : (C) 2003 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. *
+ * *
+ ***************************************************************************/
+#ifndef TIMECODE_H
+#define TIMECODE_H
+
+#include <qstring.h>
+
+#include "gentime.h"
+
+/**
+Handles the conversion of a GenTime into a nicely formatted string, taking into account things such as drop frame if necessary. Handles multiple formats, such as HH:MM:SS:FF, HH:MM:SS:F, All Frames, All Seconds, etc.
+
+@author Jason Wood
+*/
+class Timecode {
+ public:
+ enum Formats { HH_MM_SS_FF, HH_MM_SS_HH, Frames, Seconds };
+
+ Timecode(Formats format = HH_MM_SS_FF, int framesPerSecond =
+ 25, bool dropFrame = false);
+
+ /** Set the current timecode format; this is the output format for this timecode. */
+ void setFormat(int framesPerSecond, bool dropFrame = false, Formats format = HH_MM_SS_FF) {
+ m_displayedFramesPerSecond = framesPerSecond;
+ m_dropFrame = dropFrame;
+ m_format = format;
+ }
+
+ Formats format() const {
+ return m_format;
+ }
+
+ ~Timecode();
+
+ /** Returns the timecode for a given time */
+ QString getTimecode(const GenTime & time, double fps) const;
+ int getFrameNumber(const QString duration, double fps) const;
+ static QString getEasyTimecode(const GenTime & time, const double &fps);
+ QString getTimecodeFromFrames(int frames);
+ private:
+ Formats m_format;
+ bool m_dropFrame;
+ int m_displayedFramesPerSecond;
+
+ QString getTimecodeHH_MM_SS_FF(const GenTime & time, double fps) const;
+ QString getTimecodeHH_MM_SS_FF(int frames) const;
+ QString getTimecodeHH_MM_SS_HH(const GenTime & time) const;
+ QString getTimecodeFrames(const GenTime & time, double fps) const;
+ QString getTimecodeSeconds(const GenTime & time) const;
+ QString getTimecodeDropFrame(const GenTime & time, double fps) const;
+};
+
+#endif
--- /dev/null
+
+#include <QMouseEvent>
+#include <QStylePainter>
+
+#include <KDebug>
+
+
+#include "trackview.h"
+
+TrackView::TrackView(KdenliveDoc *doc, QWidget *parent)
+ : QWidget(parent), m_doc(doc)
+{
+ view = new Ui::TimeLine_UI();
+ view->setupUi(this);
+ m_ruler = new CustomRuler();
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(m_ruler);
+ view->ruler_frame->setLayout(layout);
+
+ connect(view->horizontalSlider, SIGNAL(valueChanged ( int )), this, SLOT(slotChangeZoom( int )));
+}
+
+void TrackView::slotChangeZoom(int factor)
+{
+ m_ruler->setPixelPerMark(factor);
+}
+
+KdenliveDoc *TrackView::document()
+{
+ return m_doc;
+}
+
+#include "trackview.moc"
--- /dev/null
+#ifndef TRACKVIEW_H
+#define TRACKVIEW_H
+
+#include <KRuler>
+#include "ui_timeline_ui.h"
+#include "customruler.h"
+#include "kdenlivedoc.h"
+
+class TrackView : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ TrackView(KdenliveDoc *doc, QWidget *parent=0);
+
+ public slots:
+ KdenliveDoc *document();
+
+ private:
+ Ui::TimeLine_UI *view;
+ CustomRuler *m_ruler;
+ KdenliveDoc *m_doc;
+
+ private slots:
+ void slotChangeZoom(int factor);
+};
+
+#endif
--- /dev/null
+<ui version="4.0" >
+ <class>Monitor_UI</class>
+ <widget class="QWidget" name="Monitor_UI" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>365</width>
+ <height>249</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" colspan="2" >
+ <widget class="QFrame" name="video_frame" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2" >
+ <widget class="KRuler" name="monitor_ruler" />
+ </item>
+ <item row="2" column="0" >
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="KPushButton" name="button_play" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="button_rew" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="button_play_2" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="kpushbutton_18" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="kpushbutton_19" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="kpushbutton_20" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="3" column="0" >
+ <layout class="QHBoxLayout" >
+ <property name="spacing" >
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="KPushButton" name="kpushbutton_9" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="kpushbutton_10" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="kpushbutton_11" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="kpushbutton_12" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="kpushbutton_13" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="KPushButton" name="kpushbutton_14" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize" >
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="flat" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="3" column="1" >
+ <widget class="KRestrictedLine" name="krestrictedline" >
+ <property name="inputMask" >
+ <string>99:99:99:99; </string>
+ </property>
+ <property name="validChars" >
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KPushButton</class>
+ <extends>QPushButton</extends>
+ <header>kpushbutton.h</header>
+ </customwidget>
+ <customwidget>
+ <class>KRestrictedLine</class>
+ <extends>KLineEdit</extends>
+ <header>krestrictedline.h</header>
+ </customwidget>
+ <customwidget>
+ <class>KRuler</class>
+ <extends>QWidget</extends>
+ <header>kruler.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+<ui version="4.0" >
+ <class>ProjectList_UI</class>
+ <widget class="QWidget" name="ProjectList_UI" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>347</width>
+ <height>205</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="KTreeWidgetSearchLine" name="project_search" />
+ </item>
+ <item row="0" column="1" >
+ <widget class="KPushButton" name="button_add" />
+ </item>
+ <item row="0" column="2" >
+ <widget class="KPushButton" name="button_edit" />
+ </item>
+ <item row="0" column="3" >
+ <widget class="KPushButton" name="button_delete" />
+ </item>
+ <item row="1" column="0" colspan="4" >
+ <widget class="QTreeWidget" name="project_list" >
+ <property name="alternatingRowColors" >
+ <bool>true</bool>
+ </property>
+ <property name="allColumnsShowFocus" >
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>Thumb</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Filename</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Description</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KPushButton</class>
+ <extends>QPushButton</extends>
+ <header>kpushbutton.h</header>
+ </customwidget>
+ <customwidget>
+ <class>KTreeWidgetSearchLine</class>
+ <extends>KLineEdit</extends>
+ <header>ktreewidgetsearchline.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+<ui version="4.0" >
+ <class>TimeLine_UI</class>
+ <widget class="QWidget" name="TimeLine_UI" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>390</width>
+ <height>288</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="topMargin" >
+ <number>0</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QSlider" name="horizontalSlider" >
+ <property name="maximumSize" >
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="minimum" >
+ <number>0</number>
+ </property>
+ <property name="maximum" >
+ <number>13</number>
+ </property>
+ <property name="singleStep" >
+ <number>1</number>
+ </property>
+ <property name="pageStep" >
+ <number>3</number>
+ </property>
+ <property name="value" >
+ <number>5</number>
+ </property>
+ <property name="sliderPosition" >
+ <number>5</number>
+ </property>
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QFrame" name="ruler_frame" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2" >
+ <widget class="QFrame" name="frame" >
+ <property name="frameShape" >
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow" >
+ <enum>QFrame::Raised</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>