1 /***************************************************************************
2 * Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
3 * Copyright (C) 2011 by Marco Gittler (marco@gitma.de) *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
19 ***************************************************************************/
22 #include "freesound.h"
24 #include <QPushButton>
26 #include <QListWidget>
29 #include "kdenlivesettings.h"
30 #include <KGlobalSettings>
31 #include <KMessageBox>
32 #include <KFileDialog>
34 #include <KIO/NetAccess>
37 #include <qjson/parser.h>
39 const int imageRole = Qt::UserRole;
40 const int urlRole = Qt::UserRole + 1;
41 const int soundRole = Qt::UserRole + 2;
42 const int durationRole = Qt::UserRole + 3;
43 const int previewRole = Qt::UserRole + 4;
44 const int authorRole = Qt::UserRole + 5;
45 const int authorUrl = Qt::UserRole + 6;
46 const int soundUrl = Qt::UserRole + 7;
48 FreeSound::FreeSound(const QString & folder, QWidget * parent) :
52 setFont(KGlobalSettings::toolBarFont());
54 setAttribute(Qt::WA_DeleteOnClose);
55 setWindowTitle(i18n("Search FreeSound Audio Library"));
56 connect(button_search, SIGNAL(clicked()), this, SLOT(slotStartSearch()));
57 connect(search_results, SIGNAL(currentRowChanged(int)), this, SLOT(slotUpdateCurrentSound()));
58 connect(button_preview, SIGNAL(clicked()), this, SLOT(slotPlaySound()));
59 connect(button_import, SIGNAL(clicked()), this, SLOT(slotSaveSound()));
60 connect(sound_author, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
61 connect(sound_name, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
62 m_previewProcess = new QProcess;
63 connect(m_previewProcess, SIGNAL(stateChanged(QProcess::ProcessState)), this, SLOT(slotPreviewStatusChanged(QProcess::ProcessState)));
66 FreeSound::~FreeSound()
68 if (m_previewProcess) delete m_previewProcess;
71 void FreeSound::slotStartSearch()
74 m_currentPreview.clear();
76 page_number->blockSignals(true);
77 page_number->setValue(0);
78 page_number->blockSignals(false);
79 QString uri = "http://www.freesound.org/api/sounds/search/?q=";
80 uri.append(search_text->text());
81 uri.append("&api_key=a1772c8236e945a4bee30a64058dabf8");
82 KIO::TransferJob *job = KIO::get(KUrl(uri));
83 connect (job, SIGNAL( data(KIO::Job *, const QByteArray & )), this, SLOT(slotDataIsHere(KIO::Job *,const QByteArray &)));
84 connect(job, SIGNAL(result(KJob*)), this, SLOT(slotShowResults()));
87 void FreeSound::slotDataIsHere(KIO::Job *,const QByteArray & data )
89 //kDebug() << "data is here";
90 m_result.append(data);
93 void FreeSound::slotShowResults()
97 m_data = parser.parse(m_result, &ok);
99 search_results->blockSignals(true);
100 search_results->clear();
101 if (m_data.canConvert(QVariant::Map)) {
102 QMap <QString, QVariant> map = m_data.toMap();
103 QMap<QString, QVariant>::const_iterator i = map.constBegin();
104 while (i != map.constEnd()) {
105 if (i.key() == "num_results") search_info->setText(i18np("Found %1 result", "Found %1 results", i.value().toInt()));
106 else if (i.key() == "num_pages") {
107 page_number->setMaximum(i.value().toInt());
109 else if (i.key() == "sounds") {
111 if (sounds.canConvert(QVariant::List)) {
112 QList <QVariant> soundsList = sounds.toList();
113 for (int j = 0; j < soundsList.count(); j++) {
114 if (soundsList.at(j).canConvert(QVariant::Map)) {
115 QMap <QString, QVariant> soundmap = soundsList.at(j).toMap();
116 if (soundmap.contains("original_filename")) {
117 QListWidgetItem *item = new QListWidgetItem(soundmap.value("original_filename").toString(), search_results);
118 item->setData(imageRole, soundmap.value("waveform_m").toString());
119 item->setData(soundUrl, soundmap.value("url").toString());
120 item->setData(durationRole, soundmap.value("duration").toDouble());
121 item->setData(previewRole, soundmap.value("preview-hq-mp3").toString());
122 item->setData(soundRole, soundmap.value("serve").toString() + "?api_key=a1772c8236e945a4bee30a64058dabf8");
123 QVariant authorInfo = soundmap.value("user");
124 if (authorInfo.canConvert(QVariant::Map)) {
125 QMap <QString, QVariant> authorMap = authorInfo.toMap();
126 if (authorMap.contains("username")) {
127 item->setData(authorRole, authorMap.value("username").toString());
128 item->setData(authorUrl, authorMap.value("url").toString());
139 search_results->blockSignals(false);
140 search_results->setCurrentRow(0);
143 void FreeSound::slotUpdateCurrentSound()
145 m_currentPreview.clear();
146 m_currentUrl.clear();
147 QListWidgetItem *item = search_results->currentItem();
149 sound_box->setEnabled(false);
152 m_currentPreview = item->data(previewRole).toString();
153 m_currentUrl = item->data(soundRole).toString();
154 button_preview->setEnabled(!m_currentPreview.isEmpty());
155 sound_box->setEnabled(true);
156 sound_name->setText(item->text());
157 sound_name->setUrl(item->data(soundUrl).toString());
158 sound_author->setText(item->data(authorRole).toString());
159 sound_author->setUrl(item->data(authorUrl).toString());
160 sound_duration->setText(QString::number(item->data(durationRole).toDouble()));
161 KUrl img(item->data(imageRole).toString());
162 if (img.isEmpty()) return;
163 if (KIO::NetAccess::exists(img, KIO::NetAccess::SourceSide, this)) {
165 if (KIO::NetAccess::download(img, tmpFile, this)) {
166 QPixmap pix(tmpFile);
167 sound_image->setPixmap(pix);
168 KIO::NetAccess::removeTempFile(tmpFile);
174 void FreeSound::slotPlaySound()
176 if (m_currentPreview.isEmpty()) return;
177 if (m_previewProcess && m_previewProcess->state() != QProcess::NotRunning) {
178 m_previewProcess->close();
181 m_previewProcess->start("ffplay", QStringList() << m_currentPreview << "-nodisp");
184 void FreeSound::slotPreviewStatusChanged(QProcess::ProcessState state)
186 if (state == QProcess::NotRunning)
187 button_preview->setText(i18n("Preview"));
189 button_preview->setText(i18n("Stop"));
192 void FreeSound::slotSaveSound()
194 if (m_currentUrl.isEmpty()) return;
195 QString path = m_folder;
196 if (!path.endsWith('/')) path.append('/');
197 path.append(sound_name->text());
198 QString ext = "*." + sound_name->text().section('.', -1);
199 QString saveUrl = KFileDialog::getSaveFileName(KUrl(path), ext);
200 if (saveUrl.isEmpty()) return;
201 if (KIO::NetAccess::download(KUrl(m_currentUrl), saveUrl, this)) {
202 emit addClip(KUrl(saveUrl));
206 void FreeSound::slotOpenUrl(const QString &url)
208 new KRun(KUrl(url), this);