]> git.sesse.net Git - kdenlive/blob - src/utils/freesound.cpp
c67ecb8c6b487f2c3a4fb55da741e2c96575c531
[kdenlive] / src / utils / freesound.cpp
1 /***************************************************************************
2  *   Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
3  *   Copyright (C) 2011 by Marco Gittler (marco@gitma.de)                  *
4  *                                                                         *
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.                                   *
9  *                                                                         *
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.                          *
14  *                                                                         *
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  ***************************************************************************/
20
21
22 #include "freesound.h"
23
24 #include <QPushButton>
25 #include <QSpinBox>
26 #include <QListWidget>
27
28 #include <KDebug>
29 #include "kdenlivesettings.h"
30 #include <KGlobalSettings>
31 #include <KMessageBox>
32 #include <KFileDialog>
33 #include <kio/job.h>
34 #include <KIO/NetAccess>
35 #include <KRun>
36
37 #include <qjson/parser.h>
38
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;
47
48 FreeSound::FreeSound(const QString & folder, QWidget * parent) :
49         QDialog(parent),
50         m_folder(folder)
51 {
52     setFont(KGlobalSettings::toolBarFont());
53     setupUi(this);
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)));
64 }
65
66 FreeSound::~FreeSound()
67 {
68     if (m_previewProcess) delete m_previewProcess;
69 }
70
71 void FreeSound::slotStartSearch()
72 {
73     m_result.clear();
74     m_currentPreview.clear();
75     m_currentUrl.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()));
85 }
86
87 void FreeSound::slotDataIsHere(KIO::Job *,const QByteArray & data )
88 {
89   //kDebug() << "data is here";
90   m_result.append(data);
91 }
92
93 void FreeSound::slotShowResults()
94 {
95     QJson::Parser parser;
96     bool ok;
97     m_data = parser.parse(m_result, &ok);
98     QVariant sounds;
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());
108             }
109             else if (i.key() == "sounds") {
110                 sounds = i.value();
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());
129                                     }
130                                 }
131                             }
132                         }
133                     }
134                 }
135             }
136             ++i;
137         }
138     }
139     search_results->blockSignals(false);
140     search_results->setCurrentRow(0);
141 }
142
143 void FreeSound::slotUpdateCurrentSound()
144 {
145     m_currentPreview.clear();
146     m_currentUrl.clear();
147     QListWidgetItem *item = search_results->currentItem();
148     if (!item) {
149         sound_box->setEnabled(false);
150         return;
151     }
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)) {
164         QString tmpFile;
165         if (KIO::NetAccess::download(img, tmpFile, this)) {
166             QPixmap pix(tmpFile);
167             sound_image->setPixmap(pix);
168             KIO::NetAccess::removeTempFile(tmpFile);
169         }
170     }
171 }
172
173
174 void FreeSound::slotPlaySound()
175 {
176     if (m_currentPreview.isEmpty()) return;
177     if (m_previewProcess && m_previewProcess->state() != QProcess::NotRunning) {
178         m_previewProcess->close();
179         return;
180     }
181     m_previewProcess->start("ffplay", QStringList() << m_currentPreview << "-nodisp");
182 }
183
184 void FreeSound::slotPreviewStatusChanged(QProcess::ProcessState state)
185 {
186     if (state == QProcess::NotRunning)
187         button_preview->setText(i18n("Preview"));
188     else 
189         button_preview->setText(i18n("Stop"));
190 }
191
192 void FreeSound::slotSaveSound()
193 {
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));
203     }
204 }
205
206 void FreeSound::slotOpenUrl(const QString &url)
207 {
208     new KRun(KUrl(url), this);
209 }