]> git.sesse.net Git - kdenlive/blob - src/docclipbase.cpp
Comment out names of unused parameters [PATCH by Ray Lehtiniemi]
[kdenlive] / src / docclipbase.cpp
1 /***************************************************************************
2  *                         DocClipBase.cpp  -  description                 *
3  *                           -------------------                           *
4  *   begin                : Fri Apr 12 2002                                *
5  *   Copyright (C) 2002 by Jason Wood (jasonwood@blueyonder.co.uk)         *
6  *   Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program; if not, write to the                         *
20  *   Free Software Foundation, Inc.,                                       *
21  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
22  ***************************************************************************/
23
24
25
26
27 #include "docclipbase.h"
28 #include "kdenlivesettings.h"
29 #include "kthumb.h"
30 #include "clipmanager.h"
31
32 #include <KDebug>
33
34 #include <QCryptographicHash>
35
36 DocClipBase::DocClipBase(ClipManager *clipManager, QDomElement xml, const QString &id):
37         m_id(id), m_description(QString()), m_refcount(0), m_audioThumbCreated(false), m_duration(GenTime()), m_thumbProd(NULL), m_audioTimer(NULL), m_properties(QMap <QString, QString> ()), audioFrameChache(QMap<int, QMap<int, QByteArray> > ()), m_baseTrackProducers(QList <Mlt::Producer *>()), m_snapMarkers(QList < CommentedTime > ())  {
38     int type = xml.attribute("type").toInt();
39     m_clipType = (CLIPTYPE) type;
40
41     QDomNamedNodeMap attributes = xml.attributes();
42     for (unsigned int i = 0; i < attributes.count(); i++) {
43         m_properties.insert(attributes.item(i).nodeName(), attributes.item(i).nodeValue());
44     }
45
46     KUrl url = KUrl(xml.attribute("resource"));
47     if (!m_properties.contains("file_hash") && !url.isEmpty()) getFileHash(url.path());
48
49     if (xml.hasAttribute("duration")) {
50         setDuration(GenTime(xml.attribute("duration").toInt(), KdenliveSettings::project_fps()));
51     } else {
52         int out = xml.attribute("out").toInt();
53         int in = xml.attribute("in").toInt();
54         setDuration(GenTime(out - in, KdenliveSettings::project_fps()));
55     }
56
57     if (!m_properties.contains("name")) m_properties.insert("name", url.fileName());
58
59     //if (!url.isEmpty() && QFile::exists(url.path()))
60     {
61         m_thumbProd = new KThumb(clipManager, url, m_id, m_properties.value("file_hash"));
62         if (m_clipType == AV || m_clipType == AUDIO) slotCreateAudioTimer();
63     }
64     //kDebug() << "type is video" << (m_clipType == AV) << " " << m_clipType;
65 }
66
67 /*DocClipBase & DocClipBase::operator=(const DocClipBase & clip) {
68     DocClipBase::operator=(clip);
69     m_id = clip.getId();
70     m_clipType = clip.clipType();
71     m_name = clip.name();
72     m_duration = clip.duration();
73     m_audioThumbCreated = clip.audioThumbCreated();
74     m_properties = clip.properties();
75     return *this;
76 }*/
77
78 DocClipBase::~DocClipBase() {
79     if (m_thumbProd) {
80         delete m_thumbProd;
81     }
82     if (m_audioTimer) {
83         m_audioTimer->stop();
84         delete m_audioTimer;
85     }
86     qDeleteAll(m_baseTrackProducers);
87     m_baseTrackProducers.clear();
88 }
89
90 void DocClipBase::setZone(QPoint zone) {
91     m_properties.insert("zone_in", QString::number(zone.x()));
92     m_properties.insert("zone_out", QString::number(zone.y()));
93 }
94
95 QPoint DocClipBase::zone() const {
96     QPoint zone;
97     zone.setX(m_properties.value("zone_in").toInt());
98     zone.setY(m_properties.value("zone_out", "50").toInt());
99     return zone;
100 }
101
102 void DocClipBase::slotCreateAudioTimer() {
103     connect(m_thumbProd, SIGNAL(audioThumbReady(QMap <int, QMap <int, QByteArray> >)), this , SLOT(updateAudioThumbnail(QMap <int, QMap <int, QByteArray> >)));
104     connect(this, SIGNAL(getAudioThumbs()), this , SLOT(slotGetAudioThumbs()));
105     m_audioTimer = new QTimer(this);
106     connect(m_audioTimer, SIGNAL(timeout()), this, SLOT(slotGetAudioThumbs()));
107 }
108
109 void DocClipBase::askForAudioThumbs() {
110     if (m_thumbProd) m_thumbProd->askForAudioThumbs(getId());
111 }
112
113 void DocClipBase::slotClearAudioCache() {
114     if (m_thumbProd) m_thumbProd->stopAudioThumbs();
115     if (m_audioTimer != NULL) m_audioTimer->stop();
116     audioFrameChache.clear();
117     m_audioThumbCreated = false;
118 }
119
120 /*void DocClipBase::getClipMainThumb() {
121     if (m_thumbProd) m_thumbProd->getMainThumb(m_properties.value("thumbnail").toInt());
122 }*/
123
124 KThumb *DocClipBase::thumbProducer() {
125     return m_thumbProd;
126 }
127
128 bool DocClipBase::audioThumbCreated() const {
129     return m_audioThumbCreated;
130 }
131
132 const QString DocClipBase::name() const {
133
134     return m_properties.value("name");
135 }
136
137 const QString &DocClipBase::getId() const {
138     return m_id;
139 }
140
141 void DocClipBase::setId(const QString &newId) {
142     m_id = newId;
143 }
144
145 const CLIPTYPE & DocClipBase::clipType() const {
146     return m_clipType;
147 }
148
149 void DocClipBase::setClipType(CLIPTYPE type) {
150     m_clipType = type;
151
152     m_properties.insert("type", QString::number((int) type));
153     if (m_thumbProd && m_audioTimer == NULL && (m_clipType == AV || m_clipType == AUDIO))
154         slotCreateAudioTimer();
155 }
156
157 KUrl DocClipBase::fileURL() const {
158     QString res = m_properties.value("resource");
159     if (m_clipType != COLOR && !res.isEmpty()) return KUrl(res);
160     return KUrl();
161 }
162
163 void DocClipBase::setClipThumbFrame(const uint &ix) {
164     m_properties.insert("thumbnail", QString::number((int) ix));
165 }
166
167 uint DocClipBase::getClipThumbFrame() const {
168     return (uint) m_properties.value("thumbnail").toInt();
169 }
170
171 const QString DocClipBase::description() const {
172     return m_properties.value("description");
173 }
174
175 bool DocClipBase::isTransparent() const {
176     return (m_properties.value("transparency") == "1");
177 }
178
179 const QString DocClipBase::getProperty(const QString prop) const {
180     return m_properties.value(prop);
181 }
182
183 void DocClipBase::setDuration(GenTime dur) {
184     m_duration = dur;
185     m_properties.insert("duration", QString::number((int) dur.frames(KdenliveSettings::project_fps())));
186 }
187
188 const GenTime &DocClipBase::duration() const {
189     return m_duration;
190 }
191
192 const GenTime DocClipBase::maxDuration() const {
193     if (m_clipType == COLOR || m_clipType == IMAGE || m_clipType == TEXT || (m_clipType == SLIDESHOW &&  m_properties.value("loop") == "1")) {
194         const GenTime dur(15000, KdenliveSettings::project_fps());
195         return dur;
196     }
197     return m_duration;
198 }
199
200 bool DocClipBase::hasFileSize() const {
201     return true;
202 }
203
204
205 // virtual
206 QDomElement DocClipBase::toXML() const {
207     QDomDocument doc;
208     QDomElement clip = doc.createElement("producer");
209
210     QMapIterator<QString, QString> i(m_properties);
211     while (i.hasNext()) {
212         i.next();
213         if (!i.value().isEmpty()) clip.setAttribute(i.key(), i.value());
214     }
215     doc.appendChild(clip);
216     //kDebug()<<"/// CLIP XML: "<<doc.toString();
217     return doc.documentElement();
218 }
219
220 DocClipBase *DocClipBase::
221 createClip(KdenliveDoc */*doc*/, const QDomElement & element) {
222     DocClipBase *clip = 0;
223     QString description;
224     QDomNode node = element;
225     node.normalize();
226     if (element.tagName() != "kdenliveclip") {
227         kWarning() <<
228         "DocClipBase::createClip() element has unknown tagName : " << element.tagName();
229         return 0;
230     }
231
232     QDomNode n = element.firstChild();
233
234     while (!n.isNull()) {
235         QDomElement e = n.toElement();
236         if (!e.isNull()) {
237             QString tagName = e.tagName();
238             if (e.tagName() == "avfile") {
239                 // clip = DocClipAVFile::createClip(e);
240             } else if (e.tagName() == "DocTrackBaseList") {
241                 // clip = DocClipProject::createClip(doc, e);
242             }
243         } else {
244             QDomText text = n.toText();
245             if (!text.isNull()) {
246                 description = text.nodeValue();
247             }
248         }
249
250         n = n.nextSibling();
251     }
252     if (clip == 0) {
253         kWarning() << "DocClipBase::createClip() unable to create clip";
254     } else {
255         // setup DocClipBase specifics of the clip.
256         QMap <QString, QString> props;
257         props.insert("description", description);
258         clip->setProperties(props);
259         clip->setAudioThumbCreated(false);
260     }
261     return clip;
262 }
263
264 void DocClipBase::setAudioThumbCreated(bool isDone) {
265     m_audioThumbCreated = isDone;
266 }
267
268
269 void DocClipBase::setThumbnail(const QPixmap & pixmap) {
270     m_thumbnail = pixmap;
271 }
272
273 const QPixmap & DocClipBase::thumbnail() const {
274     return m_thumbnail;
275 }
276
277 void DocClipBase::updateAudioThumbnail(QMap<int, QMap<int, QByteArray> > data) {
278     //kDebug() << "CLIPBASE RECIEDVED AUDIO DATA*********************************************";
279     audioFrameChache = data;
280     m_audioThumbCreated = true;
281     emit gotAudioData();
282 }
283
284 QList < GenTime > DocClipBase::snapMarkers() const {
285     QList < GenTime > markers;
286
287     for (uint count = 0; count < m_snapMarkers.count(); ++count) {
288         markers.append(m_snapMarkers[count].time());
289     }
290
291     return markers;
292 }
293
294 QList < CommentedTime > DocClipBase::commentedSnapMarkers() const {
295     return m_snapMarkers;
296 }
297
298 void DocClipBase::setSnapMarkers(QList < CommentedTime > markers) {
299     m_snapMarkers = markers;
300 }
301
302 void DocClipBase::addSnapMarker(const GenTime & time, QString comment) {
303     QList < CommentedTime >::Iterator it = m_snapMarkers.begin();
304     for (it = m_snapMarkers.begin(); it != m_snapMarkers.end(); ++it) {
305         if ((*it).time() >= time)
306             break;
307     }
308
309     if ((it != m_snapMarkers.end()) && ((*it).time() == time)) {
310         (*it).setComment(comment);
311         //kError() << "trying to add Snap Marker that already exists, this will cause inconsistancies with undo/redo";
312     } else {
313         CommentedTime t(time, comment);
314         m_snapMarkers.insert(it, t);
315     }
316
317 }
318
319 void DocClipBase::editSnapMarker(const GenTime & time, QString comment) {
320     QList < CommentedTime >::Iterator it;
321     for (it = m_snapMarkers.begin(); it != m_snapMarkers.end(); ++it) {
322         if ((*it).time() == time)
323             break;
324     }
325     if (it != m_snapMarkers.end()) {
326         (*it).setComment(comment);
327     } else {
328         kError() << "trying to edit Snap Marker that does not already exists";
329     }
330 }
331
332 QString DocClipBase::deleteSnapMarker(const GenTime & time) {
333     QString result = i18n("Marker");
334     QList < CommentedTime >::Iterator itt = m_snapMarkers.begin();
335
336     while (itt != m_snapMarkers.end()) {
337         if ((*itt).time() == time)
338             break;
339         ++itt;
340     }
341
342     if ((itt != m_snapMarkers.end()) && ((*itt).time() == time)) {
343         result = (*itt).comment();
344         m_snapMarkers.erase(itt);
345     }
346     return result;
347 }
348
349
350 GenTime DocClipBase::hasSnapMarkers(const GenTime & time) {
351     QList < CommentedTime >::Iterator itt = m_snapMarkers.begin();
352
353     while (itt != m_snapMarkers.end()) {
354         if ((*itt).time() == time)
355             return time;
356         ++itt;
357     }
358
359     return GenTime(0.0);
360 }
361
362 GenTime DocClipBase::findPreviousSnapMarker(const GenTime & currTime) {
363     int it;
364     for (it = 0; it < m_snapMarkers.count(); it++) {
365         if (m_snapMarkers[it].time() >= currTime)
366             break;
367     }
368     if (it == 0) return GenTime();
369     else if (it == m_snapMarkers.count() - 1 && m_snapMarkers[it].time() < currTime)
370         return m_snapMarkers[it].time();
371     else return m_snapMarkers[it-1].time();
372 }
373
374 GenTime DocClipBase::findNextSnapMarker(const GenTime & currTime) {
375     int it;
376     for (it = 0; it < m_snapMarkers.count(); it++) {
377         if (m_snapMarkers[it].time() > currTime)
378             break;
379     }
380     if (it < m_snapMarkers.count() && m_snapMarkers[it].time() > currTime) return m_snapMarkers[it].time();
381     return duration();
382 }
383
384 QString DocClipBase::markerComment(GenTime t) {
385     QList < CommentedTime >::Iterator itt = m_snapMarkers.begin();
386
387     while (itt != m_snapMarkers.end()) {
388         if ((*itt).time() == t)
389             return (*itt).comment();
390         ++itt;
391     }
392     return QString();
393 }
394
395 void DocClipBase::deleteProducers() {
396     qDeleteAll(m_baseTrackProducers);
397     m_baseTrackProducers.clear();
398     if (m_thumbProd) m_thumbProd->clearProducer();
399 }
400
401 void DocClipBase::setProducer(Mlt::Producer *producer) {
402     if (producer == NULL) return;
403     QString id = producer->get("id");
404     if (id.contains('_')) {
405         // this is a subtrack producer, insert it at correct place
406         int pos = id.section('_', 1, 1).toInt();
407         if (pos >= m_baseTrackProducers.count()) {
408             while (m_baseTrackProducers.count() - 1 < pos) {
409                 m_baseTrackProducers.append(NULL);
410             }
411         }
412         if (m_baseTrackProducers.at(pos) == NULL) m_baseTrackProducers[pos] = producer;
413     } else {
414         if (m_baseTrackProducers.isEmpty()) m_baseTrackProducers.append(producer);
415         else if (m_baseTrackProducers.at(0) == NULL) m_baseTrackProducers[0] = producer;
416     }
417     //m_clipProducer = producer;
418     //m_clipProducer->set("transparency", m_properties.value("transparency").toInt());
419     if (m_thumbProd && !m_thumbProd->hasProducer()) m_thumbProd->setProducer(producer);
420 }
421
422 Mlt::Producer *DocClipBase::producer(int track) {
423     /*for (int i = 0; i < m_baseTrackProducers.count(); i++) {
424         if (m_baseTrackProducers.at(i)) kDebug() << "// PROD: " << i << ", ID: " << m_baseTrackProducers.at(i)->get("id");
425     }*/
426     if (track == -1 || (m_clipType != AUDIO && m_clipType != AV)) {
427         if (m_baseTrackProducers.count() == 0) return NULL;
428         for (int i = 0; i < m_baseTrackProducers.count(); i++) {
429             if (m_baseTrackProducers.at(i) != NULL)
430                 return m_baseTrackProducers.at(i);
431         }
432         return NULL;
433     }
434     if (track >= m_baseTrackProducers.count()) {
435         while (m_baseTrackProducers.count() - 1 < track) {
436             m_baseTrackProducers.append(NULL);
437         }
438     }
439     if (m_baseTrackProducers.at(track) == NULL) {
440         int i;
441         for (i = 0; i < m_baseTrackProducers.count(); i++)
442             if (m_baseTrackProducers.at(i) != NULL) break;
443         if (i >= m_baseTrackProducers.count()) return NULL;
444         m_baseTrackProducers[track] = new Mlt::Producer(*m_baseTrackProducers.at(i)->profile(), m_baseTrackProducers.at(i)->get("resource"));
445         if (m_properties.contains("force_aspect_ratio")) m_baseTrackProducers[track]->set("force_aspect_ratio", m_properties.value("force_aspect_ratio").toDouble());
446         if (m_properties.contains("threads")) m_baseTrackProducers[track]->set("threads", m_properties.value("threads").toInt());
447         if (m_properties.contains("video_index")) m_baseTrackProducers[track]->set("video_index", m_properties.value("video_index").toInt());
448         if (m_properties.contains("audio_index")) m_baseTrackProducers[track]->set("audio_index", m_properties.value("audio_index").toInt());
449         char *tmp = (char *) qstrdup(QString(getId() + '_' + QString::number(track)).toUtf8().data());
450         m_baseTrackProducers[track]->set("id", tmp);
451         delete[] tmp;
452         if (KdenliveSettings::dropbframes() && m_baseTrackProducers.at(i)->get("skip_loop_filter") && strcmp(m_baseTrackProducers.at(i)->get("skip_loop_filter"), "all") == 0) {
453             m_baseTrackProducers[track]->set("skip_loop_filter", "all");
454             m_baseTrackProducers[track]->set("skip_frame", "bidir");
455         }
456     }
457     return m_baseTrackProducers.at(track);
458 }
459
460 void DocClipBase::setProducerProperty(const char *name, int data) {
461     for (int i = 0; i < m_baseTrackProducers.count(); i++) {
462         if (m_baseTrackProducers.at(i) != NULL)
463             m_baseTrackProducers[i]->set(name, data);
464     }
465 }
466
467 void DocClipBase::setProducerProperty(const char *name, const char *data) {
468     for (int i = 0; i < m_baseTrackProducers.count(); i++) {
469         if (m_baseTrackProducers.at(i) != NULL)
470             m_baseTrackProducers[i]->set(name, data);
471     }
472 }
473
474 const char *DocClipBase::producerProperty(const char *name) const {
475     for (int i = 0; i < m_baseTrackProducers.count(); i++) {
476         if (m_baseTrackProducers.at(i) != NULL) {
477             return m_baseTrackProducers.at(i)->get(name);
478         }
479     }
480     return NULL;
481 }
482
483
484 void DocClipBase::slotRefreshProducer() {
485     if (m_baseTrackProducers.count() == 0) return;
486     kDebug() << "////////////   REFRESH CLIP !!!!!!!!!!!!!!!!";
487     if (m_clipType == SLIDESHOW) {
488         /*char *tmp = (char *) qstrdup(getProperty("resource").toUtf8().data());
489                Mlt::Producer producer(*(m_clipProducer->profile()), tmp);
490                delete[] tmp;
491         delete m_clipProducer;
492         m_clipProducer = new Mlt::Producer(producer.get_producer());
493         if (!getProperty("out").isEmpty()) m_clipProducer->set_in_and_out(getProperty("in").toInt(), getProperty("out").toInt());*/
494         setProducerProperty("ttl", getProperty("ttl").toInt());
495         //m_clipProducer->set("id", getProperty("id"));
496         if (getProperty("fade") == "1") {
497             // we want a fade filter effect
498             kDebug() << "////////////   FADE WANTED";
499             Mlt::Service clipService(m_baseTrackProducers.at(0)->get_service());
500             int ct = 0;
501             Mlt::Filter *filter = clipService.filter(ct);
502             while (filter) {
503                 if (filter->get("mlt_service") == "luma") {
504                     break;
505                 }
506                 ct++;
507                 filter = clipService.filter(ct);
508             }
509
510             if (filter && filter->get("mlt_service") == "luma") {
511                 filter->set("period", getProperty("ttl").toInt() - 1);
512                 filter->set("luma.out", getProperty("luma_duration").toInt());
513                 QString resource = getProperty("luma_file");
514                 char *tmp = (char *) qstrdup(resource.toUtf8().data());
515                 filter->set("luma.resource", tmp);
516                 delete[] tmp;
517                 if (!getProperty("softness").isEmpty()) {
518                     int soft = getProperty("softness").toInt();
519                     filter->set("luma.softness", (double) soft / 100.0);
520                 }
521             } else {
522                 // filter does not exist, create it...
523                 Mlt::Filter *filter = new Mlt::Filter(*(m_baseTrackProducers.at(0)->profile()), "luma");
524                 filter->set("period", getProperty("ttl").toInt() - 1);
525                 filter->set("luma.out", getProperty("luma_duration").toInt());
526                 QString resource = getProperty("luma_file");
527                 char *tmp = (char *) qstrdup(resource.toUtf8().data());
528                 filter->set("luma.resource", tmp);
529                 delete[] tmp;
530                 if (!getProperty("softness").isEmpty()) {
531                     int soft = getProperty("softness").toInt();
532                     filter->set("luma.softness", (double) soft / 100.0);
533                 }
534                 clipService.attach(*filter);
535             }
536         } else {
537             kDebug() << "////////////   FADE NOT WANTED!!!";
538             Mlt::Service clipService(m_baseTrackProducers.at(0)->get_service());
539             int ct = 0;
540             Mlt::Filter *filter = clipService.filter(0);
541             while (filter) {
542                 if (filter->get("mlt_service") == "luma") {
543                     clipService.detach(*filter);
544                 } else ct++;
545                 filter = clipService.filter(ct);
546             }
547         }
548     }
549 }
550
551 void DocClipBase::setProperties(QMap <QString, QString> properties) {
552     // changing clip type is not allowed
553     properties.remove("type");
554     QMapIterator<QString, QString> i(properties);
555     bool refreshProducer = false;
556     QStringList keys;
557     keys << "luma_duration" << "luma_file" << "fade" << "ttl" << "softness";
558     while (i.hasNext()) {
559         i.next();
560         setProperty(i.key(), i.value());
561         if (m_clipType == SLIDESHOW && keys.contains(i.key())) refreshProducer = true;
562     }
563     if (refreshProducer) slotRefreshProducer();
564 }
565
566 void DocClipBase::setMetadata(QMap <QString, QString> properties) {
567     m_metadata = properties;
568 }
569
570 QMap <QString, QString> DocClipBase::metadata() const {
571     return m_metadata;
572 }
573
574 void DocClipBase::clearProperty(const QString &key) {
575     m_properties.remove(key);
576 }
577
578 void DocClipBase::getFileHash(const QString &url) {
579     if (m_clipType == SLIDESHOW) return;
580     QFile file(url);
581     if (file.open(QIODevice::ReadOnly)) { // write size and hash only if resource points to a file
582         QByteArray fileData;
583         QByteArray fileHash;
584         //kDebug() << "SETTING HASH of" << value;
585         m_properties.insert("file_size", QString::number(file.size()));
586         /*
587                * 1 MB = 1 second per 450 files (or faster)
588                * 10 MB = 9 seconds per 450 files (or faster)
589                */
590         if (file.size() > 1000000*2) {
591             fileData = file.read(1000000);
592             if (file.seek(file.size() - 1000000))
593                 fileData.append(file.readAll());
594         } else
595             fileData = file.readAll();
596         file.close();
597         fileHash = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
598         m_properties.insert("file_hash", QString(fileHash.toHex()));
599         //kDebug() << file.fileName() << file.size() << fileHash.toHex();
600     }
601 }
602
603 QString DocClipBase::getClipHash() const {
604     QString hash;
605     if (m_clipType == SLIDESHOW) hash = QCryptographicHash::hash(m_properties.value("resource").toAscii().data(), QCryptographicHash::Md5).toHex();
606     else if (m_clipType == COLOR) hash = QCryptographicHash::hash(m_properties.value("colour").toAscii().data(), QCryptographicHash::Md5).toHex();
607     else hash = m_properties.value("file_hash");
608     return hash;
609 }
610
611 void DocClipBase::refreshThumbUrl() {
612     if (m_thumbProd) m_thumbProd->updateThumbUrl(m_properties.value("file_hash"));
613 }
614
615 void DocClipBase::setProperty(const QString &key, const QString &value) {
616     m_properties.insert(key, value);
617     if (key == "resource") {
618         getFileHash(value);
619         if (m_thumbProd) m_thumbProd->updateClipUrl(KUrl(value), m_properties.value("file_hash"));
620     } else if (key == "out") setDuration(GenTime(value.toInt(), KdenliveSettings::project_fps()));
621     //else if (key == "transparency") m_clipProducer->set("transparency", value.toInt());
622     else if (key == "colour") {
623         char *tmp = (char *) qstrdup(value.toUtf8().data());
624         setProducerProperty("colour", tmp);
625         delete[] tmp;
626     } else if (key == "xmldata") {
627         setProducerProperty("force_reload", 1);
628     } else if (key == "force_aspect_ratio") {
629         if (value.isEmpty()) {
630             m_properties.remove("force_aspect_ratio");
631             setProducerProperty("force_aspect_ratio", 0);
632         } else setProducerProperty("force_aspect_ratio", value.toDouble());
633     } else if (key == "threads") {
634         if (value.isEmpty()) {
635             m_properties.remove("threads");
636             setProducerProperty("threads", 1);
637         } else setProducerProperty("threads", value.toInt());
638     } else if (key == "video_index") {
639         if (value.isEmpty()) {
640             m_properties.remove("video_index");
641             setProducerProperty("video_index", m_properties.value("default_video").toInt());
642         } else setProducerProperty("video_index", value.toInt());
643     } else if (key == "audio_index") {
644         if (value.isEmpty()) {
645             m_properties.remove("audio_index");
646             setProducerProperty("audio_index", m_properties.value("default_audio").toInt());
647         } else setProducerProperty("audio_index", value.toInt());
648     }
649 }
650
651 QMap <QString, QString> DocClipBase::properties() const {
652     return m_properties;
653 }
654
655 bool DocClipBase::slotGetAudioThumbs() {
656     if (m_thumbProd == NULL) return false;
657     if (!KdenliveSettings::audiothumbnails()) {
658         if (m_audioTimer != NULL) m_audioTimer->stop();
659         return false;
660     }
661     if (m_audioThumbCreated) {
662         if (m_audioTimer != NULL) m_audioTimer->stop();
663         return false;
664     }
665     if (m_audioTimer != NULL)
666         m_audioTimer->start(1500);
667     double lengthInFrames = duration().frames(KdenliveSettings::project_fps());
668     m_thumbProd->getAudioThumbs(2, 0, lengthInFrames /*must be number of frames*/, 20);
669     return true;
670 }
671
672
673