1 /***************************************************************************
2 * Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
20 #include <KFileDialog>
21 #include <kio/netaccess.h>
23 #include "addclipcommand.h"
24 #include "kdenlivesettings.h"
25 #include "clipmanager.h"
26 #include "docclipbase.h"
27 #include "kdenlivedoc.h"
29 #include <mlt++/Mlt.h>
31 ClipManager::ClipManager(KdenliveDoc *doc): m_doc(doc), m_audioThumbsEnabled(false), m_audioThumbsQueue(QList <QString> ()), m_generatingAudioId(QString()) {
33 m_folderIdCounter = 1;
36 ClipManager::~ClipManager() {
37 qDeleteAll(m_clipList);
40 void ClipManager::clear() {
41 qDeleteAll(m_clipList);
44 m_folderIdCounter = 1;
46 m_audioThumbsQueue.clear();
49 void ClipManager::checkAudioThumbs() {
50 if (m_audioThumbsEnabled == KdenliveSettings::audiothumbnails()) return;
51 m_audioThumbsEnabled = KdenliveSettings::audiothumbnails();
52 for (int i = 0; i < m_clipList.count(); i++) {
53 if (m_audioThumbsEnabled) m_audioThumbsQueue.append(m_clipList.at(i)->getId());
54 else m_clipList.at(i)->slotClearAudioCache();
56 if (m_audioThumbsEnabled) {
57 if (m_generatingAudioId.isEmpty()) startAudioThumbsGeneration();
59 m_audioThumbsQueue.clear();
60 m_generatingAudioId = QString();
64 void ClipManager::askForAudioThumb(const QString &id) {
65 DocClipBase *clip = getClipById(id);
66 if (clip && KdenliveSettings::audiothumbnails()) {
67 m_audioThumbsQueue.append(id);
68 if (m_generatingAudioId.isEmpty()) startAudioThumbsGeneration();
72 void ClipManager::startAudioThumbsGeneration() {
73 if (!KdenliveSettings::audiothumbnails()) {
74 m_audioThumbsQueue.clear();
75 m_generatingAudioId = QString();
78 if (!m_audioThumbsQueue.isEmpty()) {
79 m_generatingAudioId = m_audioThumbsQueue.takeFirst();
80 DocClipBase *clip = getClipById(m_generatingAudioId);
81 if (!clip || !clip->slotGetAudioThumbs())
82 endAudioThumbsGeneration(m_generatingAudioId);
84 m_generatingAudioId = QString();
88 void ClipManager::endAudioThumbsGeneration(const QString &requestedId) {
89 if (!KdenliveSettings::audiothumbnails()) {
90 m_audioThumbsQueue.clear();
91 m_generatingAudioId = QString();
94 if (!m_audioThumbsQueue.isEmpty()) {
95 if (m_generatingAudioId == requestedId) {
96 startAudioThumbsGeneration();
99 m_generatingAudioId = QString();
103 void ClipManager::setThumbsProgress(const QString &message, int progress) {
104 m_doc->setThumbsProgress(message, progress);
107 QList <DocClipBase*> ClipManager::documentClipList() const {
111 QMap <QString, QString> ClipManager::documentFolderList() const {
115 void ClipManager::addClip(DocClipBase *clip) {
116 m_clipList.append(clip);
117 const QString id = clip->getId();
118 if (id.toInt() >= m_clipIdCounter) m_clipIdCounter = id.toInt() + 1;
119 const QString gid = clip->getProperty("groupid");
120 if (!gid.isEmpty() && gid.toInt() >= m_folderIdCounter) m_folderIdCounter = gid.toInt() + 1;
123 void ClipManager::slotDeleteClip(const QString &clipId) {
124 for (int i = 0; i < m_clipList.count(); i++) {
125 if (m_clipList.at(i)->getId() == clipId) {
126 AddClipCommand *command = new AddClipCommand(m_doc, m_clipList.at(i)->toXML(), clipId, false);
127 m_doc->commandStack()->push(command);
133 void ClipManager::deleteClip(const QString &clipId) {
134 for (int i = 0; i < m_clipList.count(); i++) {
135 if (m_clipList.at(i)->getId() == clipId) {
136 DocClipBase *clip = m_clipList.takeAt(i);
144 DocClipBase *ClipManager::getClipAt(int pos) {
145 return m_clipList.at(pos);
148 DocClipBase *ClipManager::getClipById(QString clipId) {
149 //kDebug() << "++++ CLIP MAN, LOOKING FOR CLIP ID: " << clipId;
150 clipId = clipId.section('_', 0, 0);
151 for (int i = 0; i < m_clipList.count(); i++) {
152 if (m_clipList.at(i)->getId() == clipId) {
153 //kDebug() << "++++ CLIP MAN, FOUND FOR CLIP ID: " << clipId;
154 return m_clipList.at(i);
160 DocClipBase *ClipManager::getClipByResource(QString resource) {
161 for (int i = 0; i < m_clipList.count(); i++) {
162 if (m_clipList.at(i)->getProperty("resource") == resource) {
163 return m_clipList.at(i);
169 void ClipManager::updatePreviewSettings() {
170 for (int i = 0; i < m_clipList.count(); i++) {
171 if (m_clipList.at(i)->clipType() == AV || m_clipList.at(i)->clipType() == VIDEO) {
172 if (m_clipList.at(i)->producerProperty("meta.media.0.codec.name") && strcmp(m_clipList.at(i)->producerProperty("meta.media.0.codec.name"), "h264") == 0) {
173 if (KdenliveSettings::dropbframes()) {
174 m_clipList[i]->setProducerProperty("skip_loop_filter", "all");
175 m_clipList[i]->setProducerProperty("skip_frame", "bidir");
177 m_clipList[i]->setProducerProperty("skip_loop_filter", "");
178 m_clipList[i]->setProducerProperty("skip_frame", "");
185 void ClipManager::resetProducersList(QList <Mlt::Producer *> prods) {
186 for (int i = 0; i < m_clipList.count(); i++) {
187 if (m_clipList.at(i)->numReferences() > 0) {
188 m_clipList.at(i)->deleteProducers();
192 for (int i = 0; i < prods.count(); i++) {
193 id = prods.at(i)->get("id");
194 if (id.contains('_')) id = id.section('_', 0, 0);
195 DocClipBase *clip = getClipById(id);
197 clip->setProducer(prods.at(i));
198 kDebug() << "// // // REPLACE CLIP: " << id;
203 void ClipManager::slotAddClipList(const KUrl::List urls, const QString group, const QString &groupId) {
204 QUndoCommand *addClips = new QUndoCommand();
205 addClips->setText(i18n("Add clips"));
207 foreach(const KUrl &file, urls) {
208 if (KIO::NetAccess::exists(file, KIO::NetAccess::SourceSide, NULL)) {
210 QDomElement prod = doc.createElement("producer");
211 if (!group.isEmpty()) {
212 prod.setAttribute("groupname", group);
213 prod.setAttribute("groupid", groupId);
215 prod.setAttribute("resource", file.path());
216 uint id = m_clipIdCounter++;
217 prod.setAttribute("id", QString::number(id));
218 KMimeType::Ptr type = KMimeType::findByUrl(file);
219 if (type->name().startsWith("image/")) {
220 prod.setAttribute("type", (int) IMAGE);
221 prod.setAttribute("in", "0");
222 prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::image_duration()) - 1);
224 new AddClipCommand(m_doc, prod, QString::number(id), true, addClips);
227 m_doc->commandStack()->push(addClips);
230 void ClipManager::slotAddClipFile(const KUrl url, const QString group, const QString &groupId) {
231 kDebug() << "///// CLIP MANAGER, ADDING CLIP: " << url;
233 QDomElement prod = doc.createElement("producer");
234 prod.setAttribute("resource", url.path());
235 uint id = m_clipIdCounter++;
236 prod.setAttribute("id", QString::number(id));
237 if (!group.isEmpty()) {
238 prod.setAttribute("groupname", group);
239 prod.setAttribute("groupid", groupId);
241 KMimeType::Ptr type = KMimeType::findByUrl(url);
242 if (type->name().startsWith("image/")) {
243 prod.setAttribute("type", (int) IMAGE);
244 prod.setAttribute("in", "0");
245 prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::image_duration()) - 1);
247 AddClipCommand *command = new AddClipCommand(m_doc, prod, QString::number(id), true);
248 m_doc->commandStack()->push(command);
251 void ClipManager::slotAddColorClipFile(const QString name, const QString color, QString duration, const QString group, const QString &groupId) {
253 QDomElement prod = doc.createElement("producer");
254 prod.setAttribute("mlt_service", "colour");
255 prod.setAttribute("colour", color);
256 prod.setAttribute("type", (int) COLOR);
257 uint id = m_clipIdCounter++;
258 prod.setAttribute("id", QString::number(id));
259 prod.setAttribute("in", "0");
260 prod.setAttribute("out", m_doc->getFramePos(duration) - 1);
261 prod.setAttribute("name", name);
262 if (!group.isEmpty()) {
263 prod.setAttribute("groupname", group);
264 prod.setAttribute("groupid", groupId);
266 AddClipCommand *command = new AddClipCommand(m_doc, prod, QString::number(id), true);
267 m_doc->commandStack()->push(command);
270 void ClipManager::slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration, const bool loop, const bool fade, const QString &luma_duration, const QString &luma_file, const int softness, QString group, const QString &groupId) {
272 QDomElement prod = doc.createElement("producer");
273 prod.setAttribute("resource", path);
274 prod.setAttribute("type", (int) SLIDESHOW);
275 uint id = m_clipIdCounter++;
276 prod.setAttribute("id", QString::number(id));
277 prod.setAttribute("in", "0");
278 prod.setAttribute("out", m_doc->getFramePos(duration) * count - 1);
279 prod.setAttribute("ttl", m_doc->getFramePos(duration));
280 prod.setAttribute("luma_duration", m_doc->getFramePos(luma_duration));
281 prod.setAttribute("name", name);
282 prod.setAttribute("loop", loop);
283 prod.setAttribute("fade", fade);
284 prod.setAttribute("softness", QString::number(softness));
285 prod.setAttribute("luma_file", luma_file);
286 if (!group.isEmpty()) {
287 prod.setAttribute("groupname", group);
288 prod.setAttribute("groupid", groupId);
290 AddClipCommand *command = new AddClipCommand(m_doc, prod, QString::number(id), true);
291 m_doc->commandStack()->push(command);
296 void ClipManager::slotAddTextClipFile(const QString titleName, const QString imagePath, const QString xml, const QString group, const QString &groupId) {
298 QDomElement prod = doc.createElement("producer");
299 prod.setAttribute("resource", imagePath);
300 prod.setAttribute("titlename", titleName);
301 prod.setAttribute("xmldata", xml);
302 uint id = m_clipIdCounter++;
303 prod.setAttribute("id", QString::number(id));
304 if (!group.isEmpty()) {
305 prod.setAttribute("groupname", group);
306 prod.setAttribute("groupid", groupId);
308 prod.setAttribute("type", (int) TEXT);
309 prod.setAttribute("transparency", "1");
310 prod.setAttribute("in", "0");
311 prod.setAttribute("out", m_doc->getFramePos(KdenliveSettings::image_duration()) - 1);
312 AddClipCommand *command = new AddClipCommand(m_doc, prod, QString::number(id), true);
313 m_doc->commandStack()->push(command);
316 int ClipManager::getFreeClipId() {
317 return m_clipIdCounter++;
320 int ClipManager::getFreeFolderId() {
321 return m_folderIdCounter++;
324 int ClipManager::lastClipId() const {
325 return m_clipIdCounter - 1;
328 QString ClipManager::projectFolder() const {
329 return m_doc->projectFolder().path();
332 void ClipManager::addFolder(const QString &id, const QString &name) {
333 m_folderList.insert(id, name);
336 void ClipManager::deleteFolder(const QString &id) {
337 m_folderList.remove(id);