void ClipManager::slotAddClip(KIO::Job *job, const KUrl &, const KUrl &dst)
{
KIO::MetaData meta = job->metaData();
+ QMap <QString, QString> data;
+ data.insert("group", meta.value("group"));
+ data.insert("groupid", meta.value("groupid"));
+ data.insert("comment", meta.value("comment"));
kDebug()<<"Finished copying: "<<dst<<" / "<<meta.value("group")<<" / "<<meta.value("groupid");
- slotAddClipList(KUrl::List () << dst, meta.value("group"), meta.value("groupid"), meta.value("comment"));
+ slotAddClipList(KUrl::List () << dst, data);
}
-void ClipManager::slotAddClipList(const KUrl::List urls, const QString &group, const QString &groupId, const QString &comment)
+void ClipManager::slotAddClipList(const KUrl::List urls, QMap <QString, QString> data)
{
QUndoCommand *addClips = new QUndoCommand();
// Update list of removable volumes
listRemovableVolumes();
foreach(const KUrl & file, urls) {
if (QFile::exists(file.path())) {//KIO::NetAccess::exists(file, KIO::NetAccess::SourceSide, NULL)) {
- if (!getClipByResource(file.path()).empty()) {
+ if (!data.contains("bypassDuplicate") && !getClipByResource(file.path()).empty()) {
if (KMessageBox::warningContinueCancel(kapp->activeWindow(), i18n("Clip <b>%1</b><br />already exists in project, what do you want to do?", file.path()), i18n("Clip already exists")) == KMessageBox::Cancel)
continue;
}
//KIO::filesize_t m_requestedSize;
KIO::CopyJob *copyjob = KIO::copy (file, KUrl(sourcesFolder));
//TODO: for some reason, passing metadata does not work...
- copyjob->addMetaData("group", group);
- copyjob->addMetaData("groupId", groupId);
- copyjob->addMetaData("comment", comment);
+ copyjob->addMetaData("group", data.value("group"));
+ copyjob->addMetaData("groupId", data.value("groupId"));
+ copyjob->addMetaData("comment", data.value("comment"));
copyjob->ui()->setWindow(kapp->activeWindow());
connect(copyjob, SIGNAL(copyingDone(KIO::Job *, const KUrl &, const KUrl &, time_t, bool, bool)), this, SLOT(slotAddClip(KIO::Job *, const KUrl &, const KUrl &)));
continue;
prod.setAttribute("resource", file.path());
uint id = m_clipIdCounter++;
prod.setAttribute("id", QString::number(id));
- if (!comment.isEmpty()) prod.setAttribute("description", comment);
- if (!group.isEmpty()) {
- prod.setAttribute("groupname", group);
- prod.setAttribute("groupid", groupId);
+ if (data.contains("comment")) prod.setAttribute("description", data.value("comment"));
+ if (data.contains("group")) {
+ prod.setAttribute("groupname", data.value("group"));
+ prod.setAttribute("groupid", data.value("groupId"));
}
+ if (data.contains("video_index")) prod.setAttribute("video_index", data.value("video_index"));
+ if (data.contains("audio_index")) prod.setAttribute("audio_index", data.value("audio_index"));
+
KMimeType::Ptr type = KMimeType::findByUrl(file);
if (type->name().startsWith("image/")) {
prod.setAttribute("type", (int) IMAGE);
}
}
-void ClipManager::slotAddClipFile(const KUrl &url, const QString &group, const QString &groupId, const QString &comment)
+void ClipManager::slotAddClipFile(const KUrl &url, QMap <QString, QString> data)
{
- slotAddClipList(KUrl::List(url), group, groupId, comment);
+ slotAddClipList(KUrl::List(url), data);
}
void ClipManager::slotAddXmlClipFile(const QString &name, const QDomElement &xml, const QString &group, const QString &groupId)
* @param url file to add
* @param group name of the group to insert the file in (can be empty)
* @param groupId id of the group (if any) */
- void slotAddClipFile(const KUrl &url, const QString &group, const QString &groupId, const QString &comment = QString());
+ void slotAddClipFile(const KUrl &url, QMap <QString, QString> data);
/** @brief Adds a list of files to the project.
* @param urls files to add
* @param group name of the group to insert the files in (can be empty)
* @param groupId id of the group (if any)
* It checks for duplicated items and asks to the user for instructions. */
- void slotAddClipList(const KUrl::List urls, const QString &group, const QString &groupId, const QString &comment = QString());
+ void slotAddClipList(const KUrl::List urls, QMap <QString, QString> data);
void slotAddTextClipFile(const QString &titleName, int out, const QString &xml, const QString &group, const QString &groupId);
void slotAddTextTemplateClip(QString titleName, const KUrl &path, const QString &group, const QString &groupId);
void slotAddXmlClipFile(const QString &name, const QDomElement &xml, const QString &group, const QString &groupId);
//kDebug() << "// SETTING SCENE LIST:\n\n" << m_document.toString();
connect(m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave()));
+ connect(m_render, SIGNAL(addClip(const KUrl &, stringMap)), this, SLOT(slotAddClipFile(const KUrl &, stringMap)));
}
KdenliveDoc::~KdenliveDoc()
emit signalDeleteProjectClip(clipId);
}
-void KdenliveDoc::slotAddClipList(const KUrl::List urls, const QString &group, const QString &groupId)
+void KdenliveDoc::slotAddClipList(const KUrl::List urls, stringMap data)
{
- m_clipManager->slotAddClipList(urls, group, groupId);
+ m_clipManager->slotAddClipList(urls, data);
//emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
setModified(true);
}
-void KdenliveDoc::slotAddClipFile(const KUrl &url, const QString &group, const QString &groupId, const QString &comment)
+void KdenliveDoc::slotAddClipFile(const KUrl &url, stringMap data)
{
- m_clipManager->slotAddClipFile(url, group, groupId, comment);
+ m_clipManager->slotAddClipFile(url, data);
emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
setModified(true);
}
*
* If the clip wasn't added before, it tries to add it to the project. */
bool addClipInfo(QDomElement elem, QDomElement orig, QString clipId);
- void slotAddClipFile(const KUrl &url, const QString &group = QString(), const QString &groupId = QString(), const QString &comment = QString());
- void slotAddClipList(const KUrl::List urls, const QString &group = QString(), const QString &groupId = QString());
+ void slotAddClipList(const KUrl::List urls, stringMap data = QMap <QString, QString>());
void deleteClip(const QString &clipId);
int getFramePos(QString duration);
DocClipBase *getBaseClip(const QString &clipId);
* @param mod (optional) true if the document has to be saved */
void setModified(bool mod = true);
void checkProjectClips(bool displayRatioChanged = false, bool fpsChanged = false);
+ void slotAddClipFile(const KUrl &url, stringMap data = QMap <QString, QString>());
private slots:
void slotAutoSave();
// Mlt::Factory::init(NULL);
// Get the number of streams and add the information of each of them if it is an audio stream.
- int streams = atoi(producer->get("meta.media.nb_streams"));
+ int streams = producer->get_int("meta.media.nb_streams");
for (int i = 0; i < streams; i++) {
QByteArray propertyName = QString("meta.media.%1.stream.type").arg(i).toLocal8Bit();
const char* streamtype = producer->get(propertyName.data());
if (streamtype && strcmp("audio", streamtype) == 0) {
m_list << new AudioStreamInfo(producer, i);
}
-
}
}
m_activeTimeline->projectView()->editItemDuration();
}
-void MainWindow::slotAddProjectClip(KUrl url, const QString &comment)
+void MainWindow::slotAddProjectClip(KUrl url, QMap <QString, QString> data)
{
- if (m_activeDocument)
- m_activeDocument->slotAddClipFile(url, QString(), QString(), comment);
+ if (m_activeDocument) {
+ m_activeDocument->slotAddClipFile(url, data);
+ }
}
void MainWindow::slotAddProjectClipList(KUrl::List urls)
{
if (m_activeDocument)
- m_activeDocument->slotAddClipList(urls, QString());
+ m_activeDocument->slotAddClipList(urls);
}
void MainWindow::slotAddTransition(QAction *result)
if (m_activeDocument) currentFolder = m_activeDocument->projectFolder().path();
else currentFolder = KdenliveSettings::defaultprojectfolder();
ResourceWidget *d = new ResourceWidget(currentFolder);
- connect(d, SIGNAL(addClip(KUrl, const QString &)), this, SLOT(slotAddProjectClip(KUrl, const QString &)));
+ connect(d, SIGNAL(addClip(KUrl, QMap <QString, QString>)), this, SLOT(slotAddProjectClip(KUrl, QMap <QString, QString>)));
d->show();
}
void slotSelectAddTimelineTransition();
void slotAddVideoEffect(QAction *result);
void slotAddTransition(QAction *result);
- void slotAddProjectClip(KUrl url, const QString &comment = QString());
+ void slotAddProjectClip(KUrl url, QMap <QString, QString>data = QMap <QString, QString>());
void slotAddProjectClipList(KUrl::List urls);
void slotShowClipProperties(DocClipBase *clip);
void slotShowClipProperties(QList <DocClipBase *>cliplist, QMap<QString, QString> commonproperties);
ProjectItem *item = getItemById(id);
if (item) {
slotUpdateClipProperties(item, properties);
- if (properties.contains("out") || properties.contains("force_fps") || properties.contains("resource")) {
+ if (properties.contains("out") || properties.contains("force_fps") || properties.contains("resource") || properties.contains("video_index") || properties.contains("audio_index")) {
slotReloadClip(id);
} else if (properties.contains("colour") ||
properties.contains("xmldata") ||
{
//m_listView->setEnabled(false);
const QString parent = clip->getProperty("groupid");
+ QString groupName = clip->getProperty("groupname");
ProjectItem *item = NULL;
- kDebug()<<"// Adding clip 1";
monitorItemEditing(false);
if (!parent.isEmpty()) {
FolderProjectItem *parentitem = getFolderItemById(parent);
if (!parentitem) {
QStringList text;
- QString groupName = clip->getProperty("groupname");
//kDebug() << "Adding clip to new group: " << groupName;
if (groupName.isEmpty()) groupName = i18n("Folder");
text << groupName;
if (item == NULL) {
item = new ProjectItem(m_listView, clip);
}
- kDebug()<<"// Adding clip 2";
if (item->data(0, DurationRole).isNull()) item->setData(0, DurationRole, i18n("Loading"));
connect(clip, SIGNAL(createProxy(const QString &)), this, SLOT(slotCreateProxy(const QString &)));
connect(clip, SIGNAL(abortProxy(const QString &, const QString &)), this, SLOT(slotAbortProxy(const QString, const QString)));
//item->setFlags(Qt::ItemIsSelectable);
m_listView->processLayout();
QDomElement e = clip->toXML().cloneNode().toElement();
+ if (!groupName.isEmpty()) {
+ e.setAttribute("groupId", parent);
+ e.setAttribute("group", groupName);
+ }
e.removeAttribute("file_hash");
resetThumbsProducer(clip);
m_render->getFileProperties(e, clip->getId(), m_listView->iconSize().height(), true);
if (givenList.isEmpty() && !list.isEmpty()) {
QStringList groupInfo = getGroup();
- m_doc->slotAddClipList(list, groupInfo.at(0), groupInfo.at(1));
+ QMap <QString, QString> data;
+ data.insert("group", groupInfo.at(0));
+ data.insert("groupId", groupInfo.at(1));
+ m_doc->slotAddClipList(list, data);
} else if (!list.isEmpty()) {
- m_doc->slotAddClipList(list, groupName, groupId);
+ QMap <QString, QString> data;
+ data.insert("group", groupName);
+ data.insert("groupId", groupId);
+ m_doc->slotAddClipList(list, data);
}
if (!foldersList.isEmpty()) {
folder = getFolderItemByName(folderName);
}
}
- if (folder)
- m_doc->slotAddClipList(urls, folder->groupName(), folder->clipId());
+ if (folder) {
+ QMap <QString, QString> data;
+ data.insert("group", folder->groupName());
+ data.insert("groupId", folder->clipId());
+ m_doc->slotAddClipList(urls, data);
+ }
else m_doc->slotAddClipList(urls);
}
}
void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Producer *producer, const stringMap &properties, const stringMap &metadata, bool replace)
{
QString toReload;
- kDebug()<<"// CLIP LOADED 1;";
ProjectItem *item = getItemById(clipId);
int queue = m_render->processingItems();
if (item && producer) {
if (queue == 0) {
monitorItemEditing(true);
if (item && m_thumbnailQueue.isEmpty()) {
- kDebug()<<"// CLIP LOADED;";
if (!item->hasProxy() || m_render->activeClipId() == item->clipId())
m_listView->setCurrentItem(item);
bool updatedProfile = false;
m_blackClip(NULL),
m_winid(winid)
{
+ qRegisterMetaType<stringMap> ("stringMap");
analyseAudio = KdenliveSettings::monitor_audio();
if (profile.isEmpty()) profile = KdenliveSettings::current_profile();
buildConsumer(profile);
m_refreshTimer.setSingleShot(true);
m_refreshTimer.setInterval(70);
connect(&m_refreshTimer, SIGNAL(timeout()), this, SLOT(refresh()));
+ connect(this, SIGNAL(multiStreamFound(const QString &,QList<int>,QList<int>,stringMap)), this, SLOT(slotMultiStreamProducerFound(const QString &,QList<int>,QList<int>,stringMap)));
}
Render::~Render()
// Get frame rate
int vindex = producer->get_int("video_index");
+
+ // List streams
+ int streams = producer->get_int("meta.media.nb_streams");
+ QList <int> audio_list;
+ QList <int> video_list;
+ for (int i = 0; i < streams; i++) {
+ QByteArray propertyName = QString("meta.media.%1.stream.type").arg(i).toLocal8Bit();
+ QString type = producer->get(propertyName.data());
+ if (type == "audio") audio_list.append(i);
+ else if (type == "video") video_list.append(i);
+ }
+
+ if (!info.xml.hasAttribute("video_index") && video_list.count() > 1) {
+ // Clip has more than one video stream, ask which one should be used
+ QMap <QString, QString> data;
+ if (info.xml.hasAttribute("group")) data.insert("group", info.xml.attribute("group"));
+ if (info.xml.hasAttribute("groupId")) data.insert("groupId", info.xml.attribute("groupId"));
+ emit multiStreamFound(path, audio_list, video_list, data);
+ // Force video index so that when reloading the clip we don't ask again for other streams
+ filePropertyMap["video_index"] = QString::number(vindex);
+ }
+
if (vindex > -1) {
snprintf(property, sizeof(property), "meta.media.%d.stream.frame_rate", vindex);
if (producer->get(property))
return true;
}
-
+void Render::slotMultiStreamProducerFound(const QString path, QList<int> audio_list, QList<int> video_list, stringMap data)
+{
+ int width = 60.0 * m_mltProfile->dar();
+ int swidth = 60.0 * m_mltProfile->width() / m_mltProfile->height();
+ if (width % 2 == 1) width++;
+
+ KDialog dialog(qApp->activeWindow());
+ dialog.setCaption("Multi Stream Clip");
+ dialog.setButtons(KDialog::Ok | KDialog::Cancel);
+ dialog.setButtonText(KDialog::Ok, i18n("Import selected clips"));
+ QWidget *content = new QWidget(&dialog);
+ dialog.setMainWidget(content);
+ QVBoxLayout *vbox = new QVBoxLayout(content);
+ QLabel *lab1 = new QLabel(i18n("Additional streams for clip\n %1", path), content);
+ vbox->addWidget(lab1);
+ QList <QGroupBox*> groupList;
+ QList <QComboBox*> comboList;
+ // We start loading the list at 1, video index 0 should already be loaded
+ for (int j = 1; j < video_list.count(); j++) {
+ Mlt::Producer multiprod(* m_mltProfile, path.toUtf8().constData());
+ multiprod.set("video_index", video_list.at(j));
+ kDebug()<<"// LOADING: "<<j<<" = "<<video_list.at(j);
+ QImage thumb = KThumb::getFrame(&multiprod, 0, swidth, width, 60);
+ QGroupBox *streamFrame = new QGroupBox(i18n("Video stream %1", video_list.at(j)), content);
+ streamFrame->setProperty("vindex", video_list.at(j));
+ groupList << streamFrame;
+ streamFrame->setCheckable(true);
+ streamFrame->setChecked(false);
+ QVBoxLayout *vh = new QVBoxLayout( streamFrame );
+ QLabel *iconLabel = new QLabel(content);
+ iconLabel->setPixmap(QPixmap::fromImage(thumb));
+ vh->addWidget(iconLabel);
+ if (audio_list.count() > 1) {
+ QComboBox *cb = new QComboBox(content);
+ for (int k = 0; k < audio_list.count(); k++) {
+ cb->addItem(i18n("Audio stream %1", audio_list.at(k)), audio_list.at(k));
+ }
+ comboList << cb;
+ cb->setCurrentIndex(j);
+ vh->addWidget(cb);
+ }
+ vbox->addWidget(streamFrame);
+ }
+ if (dialog.exec() == QDialog::Accepted) {
+ // import selected streams
+ for (int i = 0; i < groupList.count(); i++) {
+ if (groupList.at(i)->isChecked()) {
+ int vindex = groupList.at(i)->property("vindex").toInt();
+ int aindex = comboList.at(i)->itemData(comboList.at(i)->currentIndex()).toInt();
+ data.insert("video_index", QString::number(vindex));
+ data.insert("audio_index", QString::number(aindex));
+ data.insert("bypassDuplicate", "1");
+ emit addClip(KUrl(path), data);
+ }
+ }
+ }
+}
#include "renderer.moc"
void slotOsdTimeout();
/** @brief Process the clip info requests (in a separate thread). */
void processFileProperties();
+ /** @brief A clip with multiple video streams was found, ask what to do. */
+ void slotMultiStreamProducerFound(const QString path, QList<int> audio_list, QList<int> video_list, stringMap data);
signals:
void refreshDocumentProducers(bool displayRatioChanged, bool fpsChanged);
/** @brief A proxy clip is missing, ask for creation. */
void requestProxy(QString);
+ /** @brief A multiple stream clip was found. */
+ void multiStreamFound(const QString &,QList<int>,QList<int>,stringMap data);
/** @brief A frame's image has to be shown.
* Used in Mac OS X. */
void showImageSignal(QImage);
void showAudioSignal(const QByteArray &);
+ void addClip(const KUrl &, stringMap);
public slots:
//res.setProperty( Soprano::Vocabulary::NAO::description(),
#endif
#endif
- emit addClip(filePath, QString());
+ emit addClip(filePath);
}
void ResourceWidget::slotOpenUrl(const QString &url)
void updateLayout();
signals:
- void addClip(KUrl, const QString &);
+ void addClip(KUrl, QMap <QString, QString> data = QMap <QString, QString>());
};